00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include <config.h>
00024 #endif
00025
00026 #include <wx/wxprec.h>
00027
00028 #ifndef WX_PRECOMP
00029 #include <wx/wx.h>
00030 #endif
00031
00032 #include <cstring>
00033
00034 #include "SaveSlot.hh"
00035
00036 using namespace ffse;
00037
00038 SaveSlot::SaveSlot(const char *nvram) {
00039 this->nvram = new unsigned char[GAME_SIZE];
00040 memcpy(this->nvram, nvram, GAME_SIZE);
00041
00042 if (checksum() == (unsigned char)nvram[CHECKSUM_OFFSET]) {
00043 valid = true;
00044 setModified(false);
00045 } else {
00046 valid = false;
00047 }
00048 }
00049
00050 SaveSlot::~SaveSlot() {
00051 if (nvram != 0) {
00052 delete nvram;
00053 }
00054 }
00055
00056 unsigned char SaveSlot::checksum() {
00057 unsigned char sum = 0;
00058
00059
00060 setCarry(false);
00061
00062 for (int pos = 0; pos < 0x100; pos++) {
00063 if (pos != 0xFD) {
00064 sum = adc(sum, nvram[pos]);
00065 }
00066
00067 sum = adc(sum, nvram[pos + 0x100]);
00068 sum = adc(sum, nvram[pos + 0x200]);
00069 sum = adc(sum, nvram[pos + 0x300]);
00070 }
00071
00072 return (sum ^ 0xFF);
00073 }
00074
00075 wxInt32 SaveSlot::getGold() {
00076 unsigned char *byte = (nvram + GOLD_OFFSET);
00077 wxInt32 value = 0;
00078
00079 for (int i = 2; i >= 0; i--) {
00080 if (byte[i] == 0) {
00081 continue;
00082 }
00083
00084 value <<= 8;
00085 value |= byte[i];
00086 }
00087
00088 return value;
00089 }
00090
00091 void SaveSlot::setGold(wxInt32 value) {
00092 for (int i = 0; i < 3; i++) {
00093 unsigned char temp = (value & 0xFF);
00094 nvram[GOLD_OFFSET + i] = temp;
00095 value >>= 8;
00096 }
00097
00098 setModified();
00099 }
00100
00101 int SaveSlot::getItem(int item) {
00102 return nvram[ITEM_OFFSET + item];
00103 }
00104
00105 void SaveSlot::setItem(int item, unsigned char value) {
00106 nvram[ITEM_OFFSET + item] = value;
00107
00108 setModified();
00109 }
00110
00111 wxString SaveSlot::getName(int member) {
00112 wxString name;
00113
00114 for (int pos = 0; pos < 4; pos++) {
00115 char letter = fromNES(nvram[NAME_OFFSET + (MEMBER_GAP * member) + pos]);
00116 name.append(1, letter);
00117 }
00118
00119 return name;
00120 }
00121
00122 void SaveSlot::setName(int member, wxString &value) {
00123 int length = value.size();
00124
00125 for (int pos = 0; pos < 4; pos++) {
00126 unsigned char letter;
00127
00128 if ((length - 1) < pos) {
00129 letter = toNES(' ');
00130 } else {
00131 letter = toNES(value.at(pos));
00132 }
00133
00134 nvram[NAME_OFFSET + (MEMBER_GAP * member) + pos] = letter;
00135 }
00136
00137 setModified();
00138 }
00139
00140 int SaveSlot::getClass(int member) {
00141 return nvram[CLASS_OFFSET + (MEMBER_GAP * member)];
00142 }
00143
00144 void SaveSlot::setClass(int member, unsigned char value) {
00145 nvram[CLASS_OFFSET + (MEMBER_GAP * member)] = value;
00146
00147 setModified();
00148 }
00149
00150 int SaveSlot::getCondition(int member) {
00151 return nvram[CONDITION_OFFSET + (MEMBER_GAP * member)];
00152 }
00153
00154 void SaveSlot::setCondition(int member, unsigned char value) {
00155 nvram[CONDITION_OFFSET + (MEMBER_GAP * member)] = value;
00156
00157 setModified();
00158 }
00159
00160 wxInt16 SaveSlot::getCurrentHP(int member) {
00161 wxInt16 *ptr = (wxInt16 *)(nvram +
00162 CURRENT_HP_OFFSET + (MEMBER_GAP * member));
00163
00164 return wxINT16_SWAP_ON_BE(ptr[0]);
00165 }
00166
00167 void SaveSlot::setCurrentHP(int member, wxInt16 value) {
00168 wxInt16 *ptr = (wxInt16 *)(nvram +
00169 CURRENT_HP_OFFSET + (MEMBER_GAP * member));
00170
00171 ptr[0] = wxINT16_SWAP_ON_BE(value);
00172 setModified();
00173 }
00174
00175 wxInt16 SaveSlot::getMaxHP(int member) {
00176 wxInt16 *ptr = (wxInt16 *)(nvram + MAX_HP_OFFSET + (MEMBER_GAP * member));
00177
00178 return wxINT16_SWAP_ON_BE(ptr[0]);
00179 }
00180
00181 void SaveSlot::setMaxHP(int member, wxInt16 value) {
00182 wxInt16 *ptr = (wxInt16 *)(nvram + MAX_HP_OFFSET + (MEMBER_GAP * member));
00183
00184 ptr[0] = wxINT16_SWAP_ON_BE(value);
00185 setModified();
00186 }
00187
00188 wxInt32 SaveSlot::getExperience(int member) {
00189 unsigned char *byte = (nvram + EXPERIENCE_OFFSET + (MEMBER_GAP * member));
00190 wxInt32 value = 0;
00191
00192 for (int i = 2; i >= 0; i--) {
00193 if (byte[i] == 0) {
00194 continue;
00195 }
00196
00197 value <<= 8;
00198 value |= byte[i];
00199 }
00200
00201 return value;
00202 }
00203
00204 void SaveSlot::setExperience(int member, wxInt32 value) {
00205 int offset = EXPERIENCE_OFFSET + (MEMBER_GAP * member);
00206
00207 for (int i = 0; i < 3; i++) {
00208 unsigned char temp = (value & 0xFF);
00209 nvram[offset + i] = temp;
00210 value >>= 8;
00211 }
00212
00213 setModified();
00214 }
00215
00216 int SaveSlot::getStrength(int member) {
00217 return nvram[STRENGTH_OFFSET + (MEMBER_GAP * member)];
00218 }
00219
00220 void SaveSlot::setStrength(int member, unsigned char value) {
00221 nvram[STRENGTH_OFFSET + (MEMBER_GAP * member)] = value;
00222
00223 setModified();
00224 }
00225
00226 int SaveSlot::getAgility(int member) {
00227 return nvram[AGILITY_OFFSET + (MEMBER_GAP * member)];
00228 }
00229
00230 void SaveSlot::setAgility(int member, unsigned char value) {
00231 nvram[AGILITY_OFFSET + (MEMBER_GAP * member)] = value;
00232
00233 setModified();
00234 }
00235
00236 int SaveSlot::getIntelligence(int member) {
00237 return nvram[INTELLIGENCE_OFFSET + (MEMBER_GAP * member)];
00238 }
00239
00240 void SaveSlot::setIntelligence(int member, unsigned char value) {
00241 nvram[INTELLIGENCE_OFFSET + (MEMBER_GAP * member)] = value;
00242
00243 setModified();
00244 }
00245
00246 int SaveSlot::getVitality(int member) {
00247 return nvram[VITALITY_OFFSET + (MEMBER_GAP * member)];
00248 }
00249
00250 void SaveSlot::setVitality(int member, unsigned char value) {
00251 nvram[VITALITY_OFFSET + (MEMBER_GAP * member)] = value;
00252
00253 setModified();
00254 }
00255
00256 int SaveSlot::getLuck(int member) {
00257 return nvram[LUCK_OFFSET + (MEMBER_GAP * member)];
00258 }
00259
00260 void SaveSlot::setLuck(int member, unsigned char value) {
00261 nvram[LUCK_OFFSET + (MEMBER_GAP * member)] = value;
00262
00263 setModified();
00264 }
00265
00266 int SaveSlot::getDamage(int member) {
00267 return nvram[DAMAGE_OFFSET + (MEMBER_GAP * member)];
00268 }
00269
00270 void SaveSlot::setDamage(int member, unsigned char value) {
00271 nvram[DAMAGE_OFFSET + (MEMBER_GAP * member)] = value;
00272
00273 setModified();
00274 }
00275
00276 int SaveSlot::getHitPercent(int member) {
00277 return nvram[HIT_PERCENT_OFFSET + (MEMBER_GAP * member)];
00278 }
00279
00280 void SaveSlot::setHitPercent(int member, unsigned char value) {
00281 nvram[HIT_PERCENT_OFFSET + (MEMBER_GAP * member)] = value;
00282
00283 setModified();
00284 }
00285
00286 int SaveSlot::getWeapon(int member, int slot) {
00287 return nvram[WEAPON_OFFSET + (MEMBER_GAP * member) + slot];
00288 }
00289
00290 void SaveSlot::setWeapon(int member, int slot, unsigned char value) {
00291 nvram[WEAPON_OFFSET + (MEMBER_GAP * member) + slot] = value;
00292
00293 setModified();
00294 }
00295
00296 int SaveSlot::getArmor(int member, int slot) {
00297 return nvram[ARMOR_OFFSET + (MEMBER_GAP * member) + slot];
00298 }
00299
00300 void SaveSlot::setArmor(int member, int slot, unsigned char value) {
00301 nvram[ARMOR_OFFSET + (MEMBER_GAP * member) + slot] = value;
00302
00303 setModified();
00304 }
00305
00306 int SaveSlot::getCurrentMagic(int member, int level) {
00307 return nvram[CURRENT_MAGIC_OFFSET + (MEMBER_GAP * member) + level];
00308 }
00309
00310 void SaveSlot::setCurrentMagic(int member, int level, unsigned char value) {
00311 nvram[CURRENT_MAGIC_OFFSET + (MEMBER_GAP * member) + level] = value;
00312
00313 setModified();
00314 }
00315
00316 int SaveSlot::getMaxMagic(int member, int level) {
00317 return nvram[MAX_MAGIC_OFFSET + (MEMBER_GAP * member) + level];
00318 }
00319
00320 void SaveSlot::setMaxMagic(int member, int level, unsigned char value) {
00321 nvram[MAX_MAGIC_OFFSET + (MEMBER_GAP * member) + level] = value;
00322
00323 setModified();
00324 }
00325
00326 int SaveSlot::getMagic(int member, int level, int slot) {
00327 int offset = MAGIC_OFFSET + (MEMBER_GAP * member) +
00328 (level * 3) + level + slot;
00329
00330 return nvram[offset];
00331 }
00332
00333 void SaveSlot::setMagic(int member, int level, int slot, unsigned char value) {
00334 int offset = MAGIC_OFFSET + (MEMBER_GAP * member) +
00335 (level * 3) + level + slot;
00336
00337 nvram[offset] = value;
00338 setModified();
00339 }
00340
00341 unsigned char SaveSlot::adc(unsigned char current, unsigned char value) {
00342 int n = (int)current;
00343
00344 if (carry == 1) {
00345 n++;
00346 carry = 0;
00347 }
00348
00349 n += (int)value;
00350
00351 if ((n >> 8) == 1) {
00352 carry = 1;
00353 }
00354
00355 return (unsigned char)(n & 0xFF);
00356 }
00357
00358 void SaveSlot::setModified(bool modified) {
00359 this->modified = modified;
00360
00361 if (modified) {
00362 nvram[CHECKSUM_OFFSET] = checksum();
00363 }
00364 }
00365
00366 unsigned char SaveSlot::toNES(char letter) {
00367 if ((letter >= '0') && (letter <= '9')) {
00368 return (unsigned char)(0x80 + (letter - '0'));
00369 } else if ((letter >= 'A') && (letter <= 'Z')) {
00370 return (unsigned char)(0x8A + (letter - 'A'));
00371 } else if ((letter >= 'a') && (letter <= 'z')) {
00372 return (unsigned char)(0xA4 + (letter - 'a'));
00373 } else if (letter == '\'') {
00374 return (unsigned char)0xBE;
00375 } else if (letter == ',') {
00376 return (unsigned char)0xBF;
00377 } else if (letter == '.') {
00378 return (unsigned char)0xC0;
00379 } else if (letter == '-') {
00380 return (unsigned char)0xC2;
00381 } else if (letter == ':') {
00382 return (unsigned char)0xC3;
00383 } else if (letter == '!') {
00384 return (unsigned char)0xC4;
00385 } else if (letter == '?') {
00386 return (unsigned char)0xC5;
00387 }
00388
00389 return (unsigned char)0xFF;
00390 }
00391
00392 char SaveSlot::fromNES(unsigned char letter) {
00393 if ((letter >= 0x80) && (letter < 0x8A)) {
00394 return (char)('0' + (letter - 0x80));
00395 } else if ((letter >= 0x8A) && (letter < 0xA4)) {
00396 return (char)('A' + (letter - 0x8A));
00397 } else if ((letter >= 0xA4) && (letter < 0xBE)) {
00398 return (char)('a' + (letter - 0xA4));
00399 } else if (letter == 0xBE) {
00400 return (char)'\'';
00401 } else if (letter == 0xBF) {
00402 return (char)',';
00403 } else if (letter == 0xC0) {
00404 return (char)'.';
00405 } else if (letter == 0xC2) {
00406 return (char)'-';
00407 } else if (letter == 0xC3) {
00408 return (char)':';
00409 } else if (letter == 0xC4) {
00410 return (char)'!';
00411 } else if (letter == 0xC5) {
00412 return (char)'?';
00413 }
00414
00415 return (char)' ';
00416 }
00417