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