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 #include "SaveSlot.hh"
00034
00035 using namespace hack4u;
00036
00037 const int SaveSlot::CHECKSUM_XORS[] = {
00038 0x55, 0xAA, 0x33, 0xCC,
00039 0xA5, 0x5A, 0xBB, 0x99
00040 };
00041
00042 SaveSlot::SaveSlot(const unsigned char *data) {
00043 nvram = new unsigned char[0x200];
00044 memcpy(nvram, data, 0x200);
00045
00046 setModified(false);
00047
00048 if (checksum() == nvram[0]) {
00049 valid = true;
00050 } else {
00051 valid = false;
00052 }
00053 }
00054
00055 SaveSlot::~SaveSlot() {
00056 delete nvram;
00057 }
00058
00059 unsigned char SaveSlot::checksum() const {
00060 unsigned char sum = 0;
00061 int index = 0;
00062
00063 for (int i = 1; i < 0x200; i++) {
00064 sum += (nvram[i] ^ CHECKSUM_XORS[index]);
00065
00066 index++;
00067 index &= 0x7;
00068 }
00069
00070 return sum;
00071 }
00072
00073 int SaveSlot::getPhase(int moon) const {
00074 int phase = nvram[MOON_OFFSET];
00075
00076 if (moon == TRAMMEL) {
00077 return (phase / 3);
00078 }
00079
00080 return (phase % 3);
00081 }
00082
00083 void SaveSlot::setPhase(int trammel, int felucca) {
00084 int phase = (trammel * 3) + felucca;
00085
00086 nvram[MOON_OFFSET] = phase;
00087 setModified();
00088 }
00089
00090 wxString SaveSlot::getHerosName() const {
00091 wxString name;
00092
00093 for (int offset = NAME_OFFSET; offset <= (NAME_OFFSET + 5); offset++) {
00094 if (nvram[offset] == 0) {
00095 break;
00096 }
00097
00098 char letter = fromNES(nvram[offset]);
00099 name.append(1, letter);
00100 }
00101
00102 return name;
00103 }
00104
00105 void SaveSlot::setHerosName(wxString &name) {
00106 int pos;
00107 int length = name.size();
00108
00109 for (pos = 0; pos < 5; pos++) {
00110 if ((length - 1) < pos) {
00111 nvram[NAME_OFFSET + pos] = 0;
00112 } else {
00113 nvram[NAME_OFFSET + pos] = toNES(name.at(pos));
00114 }
00115 }
00116
00117 setModified();
00118 }
00119
00120 int SaveSlot::getVirtue(int virtue) const {
00121 return (int)(nvram[VIRTUE_OFFSET + virtue]);
00122 }
00123
00124 void SaveSlot::setVirtue(int virtue, unsigned char value) {
00125 unsigned char *virtues = (nvram + VIRTUE_OFFSET + virtue);
00126 *virtues = value;
00127
00128 int mask = (1 << virtue);
00129 unsigned char *avatar = (nvram + AVATAR_OFFSET);
00130
00131 if (value < 100) {
00132 mask = ~mask;
00133 (*avatar) &= mask;
00134 } else {
00135 (*avatar) |= mask;
00136 }
00137
00138 setModified();
00139 }
00140
00141 int SaveSlot::getMember(int position) const {
00142 return (nvram[MEMBER_OFFSET + position]);
00143 }
00144
00145 void SaveSlot::setMember(int position, int character) {
00146 nvram[MEMBER_OFFSET + position] = character;
00147 setModified();
00148 }
00149
00150 bool SaveSlot::hasStone(int stone) const {
00151 unsigned char stones = *(nvram + STONES_OFFSET);
00152
00153 return (stones & (1 << stone));
00154 }
00155
00156 void SaveSlot::setStone(int stone, bool give) {
00157 unsigned char *stones = (nvram + STONES_OFFSET);
00158 int mask = (1 << stone);
00159
00160 if (give) {
00161 (*stones) |= mask;
00162 } else {
00163 mask = ~mask;
00164 (*stones) &= mask;
00165 }
00166
00167 setModified();
00168 }
00169
00170 bool SaveSlot::hasRune(int rune) const {
00171 unsigned char runes = *(nvram + RUNES_OFFSET);
00172
00173 return (runes & (1 << rune));
00174 }
00175
00176 void SaveSlot::setRune(int rune, bool give) {
00177 unsigned char *runes = (nvram + RUNES_OFFSET);
00178 int mask = (1 << rune);
00179
00180 if (give) {
00181 (*runes) |= mask;
00182 } else {
00183 mask = ~mask;
00184 (*runes) &= mask;
00185 }
00186
00187 setModified();
00188 }
00189
00190 bool SaveSlot::hasMagic(int magic) const {
00191 int offset = MAGIC_OFFSET;
00192
00193 if (magic > 7) {
00194 offset += (magic / 8);
00195 magic %= 8;
00196 }
00197
00198 return (nvram[offset] & (1 << magic));
00199 }
00200
00201 void SaveSlot::setMagic(int magic, bool give) {
00202 int offset = MAGIC_OFFSET;
00203
00204 if (magic > 7) {
00205 offset += (magic / 8);
00206 magic %= 8;
00207 }
00208
00209 unsigned char *magics = (nvram + offset);
00210 int mask = (1 << magic);
00211
00212 if (give) {
00213 (*magics) |= mask;
00214 } else {
00215 mask = ~mask;
00216 (*magics) &= mask;
00217 }
00218
00219 setModified();
00220 }
00221
00222 int SaveSlot::getHerb(int herb) const {
00223 return nvram[HERB_OFFSET + herb];
00224 }
00225
00226 void SaveSlot::setHerb(int herb, unsigned char value) {
00227 nvram[HERB_OFFSET + herb] = value;
00228 setModified();
00229 }
00230
00231 wxInt16 SaveSlot::getGold() const {
00232 wxUint16 *ptr = (wxUint16 *)(nvram + GOLD_OFFSET);
00233
00234 return wxINT16_SWAP_ON_BE(ptr[0]);
00235 }
00236
00237 void SaveSlot::setGold(wxInt16 gold) {
00238 wxUint16 *ptr = (wxUint16 *)(nvram + GOLD_OFFSET);
00239
00240 ptr[0] = wxINT16_SWAP_ON_BE(gold);
00241 setModified();
00242 }
00243
00244 int SaveSlot::getTool(int tool) const {
00245 return (int)nvram[TOOL_OFFSET + tool];
00246 }
00247
00248 void SaveSlot::setTool(int tool, unsigned char value) {
00249 nvram[TOOL_OFFSET + tool] = value;
00250 setModified();
00251 }
00252
00253 int SaveSlot::getEquipment(int character, int slot) const {
00254 return nvram[EQUIPMENT_OFFSET + (character * 6) + slot];
00255 }
00256
00257 void SaveSlot::setEquipment(int character, int slot, unsigned char value) {
00258 nvram[EQUIPMENT_OFFSET + (character * 6) + slot] = value;
00259 setModified();
00260 }
00261
00262 int SaveSlot::getLevel(int character) const {
00263 return nvram[LEVEL_OFFSET + character];
00264 }
00265
00266 void SaveSlot::setLevel(int character, unsigned char level) {
00267 nvram[LEVEL_OFFSET + character] = level;
00268 setModified();
00269 }
00270
00271 wxInt16 SaveSlot::getCurrentHP(int character) const {
00272 wxInt16 *ptr = (wxInt16 *)(nvram + CURRENT_HP_OFFSET + (character * 2));
00273
00274 return wxINT16_SWAP_ON_BE(ptr[0]);
00275 }
00276
00277 void SaveSlot::setCurrentHP(int character, wxInt16 value) {
00278 wxInt16 *ptr = (wxInt16 *)(nvram + CURRENT_HP_OFFSET + (character * 2));
00279
00280 ptr[0] = wxINT16_SWAP_ON_BE(value);
00281 setModified();
00282 }
00283
00284 wxInt16 SaveSlot::getMaxHP(int character) const {
00285 wxInt16 *ptr = (wxInt16 *)(nvram + MAX_HP_OFFSET + (character * 2));
00286
00287 return wxINT16_SWAP_ON_BE(ptr[0]);
00288 }
00289
00290 void SaveSlot::setMaxHP(int character, wxInt16 value) {
00291 wxInt16 *ptr = (wxInt16 *)(nvram + MAX_HP_OFFSET + (character * 2));
00292
00293 ptr[0] = wxINT16_SWAP_ON_BE(value);
00294 setModified();
00295 }
00296
00297 int SaveSlot::getCurrentMP(int character) const {
00298 return nvram[CURRENT_MP_OFFSET + character];
00299 }
00300
00301 void SaveSlot::setCurrentMP(int character, unsigned char value) {
00302 nvram[CURRENT_MP_OFFSET + character] = value;
00303 setModified();
00304 }
00305
00306 int SaveSlot::getMaxMP(int character) const {
00307 return nvram[MAX_MP_OFFSET + character];
00308 }
00309
00310 void SaveSlot::setMaxMP(int character, unsigned char value) {
00311 nvram[MAX_MP_OFFSET + character] = value;
00312 setModified();
00313 }
00314
00315 int SaveSlot::getStrength(int character) const {
00316 return nvram[STRENGTH_OFFSET + character];
00317 }
00318
00319 void SaveSlot::setStrength(int character, unsigned char value) {
00320 nvram[STRENGTH_OFFSET + character] = value;
00321 setModified();
00322 }
00323
00324 int SaveSlot::getIntelligence(int character) const {
00325 return nvram[INTELLIGENCE_OFFSET + character];
00326 }
00327
00328 void SaveSlot::setIntelligence(int character, unsigned char value) {
00329 nvram[INTELLIGENCE_OFFSET + character] = value;
00330 setModified();
00331 }
00332
00333 int SaveSlot::getDexterity(int character) const {
00334 return nvram[DEXTERITY_OFFSET + character];
00335 }
00336
00337 void SaveSlot::setDexterity(int character, unsigned char value) {
00338 nvram[DEXTERITY_OFFSET + character] = value;
00339 setModified();
00340 }
00341
00342 wxInt16 SaveSlot::getExperience(int character) const {
00343 wxInt16 *ptr = (wxInt16 *)(nvram + EXPERIENCE_OFFSET + (character * 2));
00344
00345 return wxINT16_SWAP_ON_BE(ptr[0]);
00346 }
00347
00348 void SaveSlot::setExperience(int character, wxInt16 value) {
00349 wxInt16 *ptr = (wxInt16 *)(nvram + EXPERIENCE_OFFSET + (character * 2));
00350
00351 ptr[0] = wxINT16_SWAP_ON_BE(value);
00352 setModified();
00353 }
00354
00355 void SaveSlot::setModified(bool modified) {
00356 this->modified = modified;
00357
00358 if (modified) {
00359 nvram[CHECKSUM_OFFSET] = checksum();
00360 }
00361 }
00362
00363 unsigned char SaveSlot::toNES(char letter) {
00364 if ((letter >= 'A') && (letter <= 'Z')) {
00365 return (unsigned char)(0x91 + (letter - 'A'));
00366 } else if ((letter >= 'a') && (letter <= 'z')) {
00367 return (unsigned char)(0xD1 + (letter - 'a'));
00368 } else if (letter == '-') {
00369 return (unsigned char)0xD0;
00370 } else if (letter == '!') {
00371 return (unsigned char)0x90;
00372 }
00373
00374
00375 return (unsigned char)0xBC;
00376 }
00377
00378 char SaveSlot::fromNES(unsigned char letter) {
00379 if ((letter >= 0x91) && (letter <= 0xAA)) {
00380 return ((letter - 0x91) + 'A');
00381 } else if ((letter >= 0xD1) && (letter <= 0xEA)) {
00382 return ((letter - 0xD1) + 'a');
00383 } else if (letter == 0xD0) {
00384 return '-';
00385 } else if (letter == 0x90) {
00386 return '!';
00387 }
00388
00389
00390 return '_';
00391 }
00392