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