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 <fstream>
00030
00031 #include "model/SaveSlot.hh"
00032 #include "model/SRAMFile.hh"
00033
00034 using namespace hack4u;
00035
00036 SRAMFile::SRAMFile(const wxString &filename) throw(InvalidSRAMException) {
00037 std::ifstream in(filename.mb_str(),
00038 std::ios_base::in | std::ios_base::binary);
00039
00040 if (!in) {
00041 throw InvalidSRAMException(ISE_NOSUCHFILE);
00042 }
00043
00044 in.read(sram, SRAM_SIZE);
00045
00046 if (!in.good()) {
00047 in.close();
00048
00049 throw InvalidSRAMException(ISE_IOERROR);
00050 }
00051
00052 in.close();
00053
00054 char *temp = new char[SAVE_SIZE];
00055
00056 for (int slot = 0; slot < 3; ++slot) {
00057 std::memcpy(temp, (sram + SRAM_OFFSET + (slot * SAVE_SIZE)), SAVE_SIZE);
00058 saveslot[slot] = new SaveSlot(temp);
00059 }
00060
00061 delete [] temp;
00062
00063
00064 verifyChecksum();
00065
00066 if (!(isValid(0) || isValid(1) || isValid(2))) {
00067 throw InvalidSRAMException(ISE_BADCHECKSUM);
00068 }
00069
00070
00071 wxString bakfile = filename + ".bak";
00072 std::ofstream out(bakfile.mb_str(),
00073 std::ios_base::out | std::ios_base::binary);
00074
00075 if (out) {
00076 out.write(sram, SRAM_SIZE);
00077 out.close();
00078 }
00079 }
00080
00081 SRAMFile::~SRAMFile() {
00082 for (int i = 0; i < 3; ++i) {
00083 delete saveslot[i];
00084 }
00085 }
00086
00087 bool SRAMFile::isModified() const {
00088 return (saveslot[0]->isModified() ||
00089 saveslot[1]->isModified() ||
00090 saveslot[2]->isModified());
00091 }
00092
00093 void SRAMFile::save(const wxString &filename) throw(FileIOException) {
00094 if (isModified()) {
00095 for (int slot = 0; slot < 3; ++slot) {
00096 char *nvram = reinterpret_cast<char *>(saveslot[slot]->nvram);
00097 char *ptr = (sram + SRAM_OFFSET + (slot * SAVE_SIZE));
00098
00099 std::memcpy(ptr, nvram, SAVE_SIZE);
00100
00101 if (isValid(slot)) {
00102 for (int i = 0; i < 3; ++i) {
00103 char *checksum = (sram + SANITY_OFFSET + slot + (i * 3));
00104
00105 if (i == 0) {
00106 *checksum = nvram[0];
00107 } else if (i == 1) {
00108 *checksum = nvram[0] ^ SANITY_XOR1;
00109 } else {
00110 *checksum = nvram[0] ^ SANITY_XOR2;
00111 }
00112 }
00113 }
00114 }
00115 }
00116
00117 std::ofstream out(filename.mb_str(),
00118 std::ios_base::out | std::ios_base::binary);
00119
00120 if (!out) {
00121 throw FileIOException(FIE_CANNOTOPEN);
00122 }
00123
00124 out.write(sram, SRAM_SIZE);
00125
00126 if (!out.good()) {
00127 out.close();
00128 throw FileIOException(FIE_IOERROR);
00129 }
00130
00131 out.close();
00132
00133 for (int i = 0; i < 3; ++i) {
00134 saveslot[i]->setModified(false);
00135 }
00136 }
00137
00138 void SRAMFile::verifyChecksum() {
00139 for (int slot = 0; slot < 3; ++slot) {
00140 char byte1 = getSaveSlot(slot)->checksum();
00141 char byte2 = byte1 ^ SANITY_XOR1;
00142 char byte3 = byte1 ^ SANITY_XOR2;
00143
00144 valid[slot] = ((byte1 == sram[SANITY_OFFSET + slot]) &&
00145 (byte2 == sram[SANITY_OFFSET + slot + 3]) &&
00146 (byte3 == sram[SANITY_OFFSET + slot + 6]) &&
00147 (byte1 == sram[SRAM_OFFSET + (slot * SAVE_SIZE)]));
00148 }
00149 }
00150