annotate src/gba/EEprom.cpp @ 270:49096b8b99d5

script: delivered oak's parcel; got pokedex.
author Robert McIntyre <rlm@mit.edu>
date Mon, 26 Mar 2012 23:54:52 -0500
parents f9f4f1b99eed
children
rev   line source
rlm@1 1 #include <cstring>
rlm@1 2
rlm@1 3 #include "GBA.h" // for SAVE_GAME_VERSION_3
rlm@1 4 #include "EEprom.h"
rlm@1 5 #include "../common/System.h"
rlm@1 6 #include "../common/Util.h"
rlm@1 7
rlm@1 8 extern int32 cpuDmaCount;
rlm@1 9
rlm@1 10 int32 eepromMode = EEPROM_IDLE;
rlm@1 11 int32 eepromByte = 0;
rlm@1 12 int32 eepromBits = 0;
rlm@1 13 int32 eepromAddress = 0;
rlm@1 14 u8 eepromData[0x2000];
rlm@1 15 u8 eepromBuffer[16];
rlm@1 16 bool8 eepromInUse = false;
rlm@1 17 int32 eepromSize = 512;
rlm@1 18
rlm@1 19 variable_desc eepromSaveData[] = {
rlm@1 20 { &eepromMode, sizeof(int32) },
rlm@1 21 { &eepromByte, sizeof(int32) },
rlm@1 22 { &eepromBits, sizeof(int32) },
rlm@1 23 { &eepromAddress, sizeof(int32) },
rlm@1 24 { &eepromInUse, sizeof(bool8) },
rlm@1 25 { &eepromData[0], 512 },
rlm@1 26 { &eepromBuffer[0], 16 },
rlm@1 27 { NULL, 0 }
rlm@1 28 };
rlm@1 29
rlm@1 30 void eepromReset()
rlm@1 31 {
rlm@1 32 eepromMode = EEPROM_IDLE;
rlm@1 33 eepromByte = 0;
rlm@1 34 eepromBits = 0;
rlm@1 35 eepromAddress = 0;
rlm@1 36 eepromInUse = false;
rlm@1 37 eepromSize = 512;
rlm@1 38 }
rlm@1 39
rlm@1 40 void eepromErase()
rlm@1 41 {
rlm@1 42 memset(eepromData, 0, 0x2000*sizeof(u8));
rlm@1 43 eepromMode = EEPROM_IDLE;
rlm@1 44 eepromByte = 0;
rlm@1 45 eepromBits = 0;
rlm@1 46 eepromAddress = 0;
rlm@1 47 memset(eepromBuffer, 0, 16*sizeof(u8));
rlm@1 48 eepromInUse = false;
rlm@1 49 eepromSize = 512;
rlm@1 50 }
rlm@1 51
rlm@1 52 void eepromSaveGame(gzFile gzFile)
rlm@1 53 {
rlm@1 54 utilWriteData(gzFile, eepromSaveData);
rlm@1 55 utilWriteInt(gzFile, eepromSize);
rlm@1 56 utilGzWrite(gzFile, eepromData, 0x2000);
rlm@1 57 }
rlm@1 58
rlm@1 59 void eepromReadGame(gzFile gzFile, int version)
rlm@1 60 {
rlm@1 61 utilReadData(gzFile, eepromSaveData);
rlm@1 62 if (version >= SAVE_GAME_VERSION_3)
rlm@1 63 {
rlm@1 64 eepromSize = utilReadInt(gzFile);
rlm@1 65 utilGzRead(gzFile, eepromData, 0x2000);
rlm@1 66 }
rlm@1 67 else
rlm@1 68 {
rlm@1 69 // prior to 0.7.1, only 4K EEPROM was supported
rlm@1 70 eepromSize = 512;
rlm@1 71 }
rlm@1 72 }
rlm@1 73
rlm@1 74 int eepromRead(u32 /* address */)
rlm@1 75 {
rlm@1 76 switch (eepromMode)
rlm@1 77 {
rlm@1 78 case EEPROM_IDLE:
rlm@1 79 case EEPROM_READADDRESS:
rlm@1 80 case EEPROM_WRITEDATA:
rlm@1 81 return 1;
rlm@1 82 case EEPROM_READDATA:
rlm@1 83 {
rlm@1 84 eepromBits++;
rlm@1 85 if (eepromBits == 4)
rlm@1 86 {
rlm@1 87 eepromMode = EEPROM_READDATA2;
rlm@1 88 eepromBits = 0;
rlm@1 89 eepromByte = 0;
rlm@1 90 }
rlm@1 91 return 0;
rlm@1 92 }
rlm@1 93 case EEPROM_READDATA2:
rlm@1 94 {
rlm@1 95 int data = 0;
rlm@1 96 int address = eepromAddress << 3;
rlm@1 97 int mask = 1 << (7 - (eepromBits & 7));
rlm@1 98 data = (eepromData[address+eepromByte] & mask) ? 1 : 0;
rlm@1 99 eepromBits++;
rlm@1 100 if ((eepromBits & 7) == 0)
rlm@1 101 eepromByte++;
rlm@1 102 if (eepromBits == 0x40)
rlm@1 103 eepromMode = EEPROM_IDLE;
rlm@1 104 return data;
rlm@1 105 }
rlm@1 106 default:
rlm@1 107 return 0;
rlm@1 108 }
rlm@1 109 return 1;
rlm@1 110 }
rlm@1 111
rlm@1 112 void eepromWrite(u32 /* address */, u8 value)
rlm@1 113 {
rlm@1 114 if (cpuDmaCount == 0)
rlm@1 115 return;
rlm@1 116 int bit = value & 1;
rlm@1 117 switch (eepromMode)
rlm@1 118 {
rlm@1 119 case EEPROM_IDLE:
rlm@1 120 eepromByte = 0;
rlm@1 121 eepromBits = 1;
rlm@1 122 eepromBuffer[eepromByte] = bit;
rlm@1 123 eepromMode = EEPROM_READADDRESS;
rlm@1 124 break;
rlm@1 125 case EEPROM_READADDRESS:
rlm@1 126 eepromBuffer[eepromByte] <<= 1;
rlm@1 127 eepromBuffer[eepromByte] |= bit;
rlm@1 128 eepromBits++;
rlm@1 129 if ((eepromBits & 7) == 0)
rlm@1 130 {
rlm@1 131 eepromByte++;
rlm@1 132 }
rlm@1 133 if (cpuDmaCount == 0x11 || cpuDmaCount == 0x51)
rlm@1 134 {
rlm@1 135 if (eepromBits == 0x11)
rlm@1 136 {
rlm@1 137 eepromInUse = true;
rlm@1 138 eepromSize = 0x2000;
rlm@1 139 eepromAddress = ((eepromBuffer[0] & 0x3F) << 8) |
rlm@1 140 ((eepromBuffer[1] & 0xFF));
rlm@1 141 if (!(eepromBuffer[0] & 0x40))
rlm@1 142 {
rlm@1 143 eepromBuffer[0] = bit;
rlm@1 144 eepromBits = 1;
rlm@1 145 eepromByte = 0;
rlm@1 146 eepromMode = EEPROM_WRITEDATA;
rlm@1 147 }
rlm@1 148 else
rlm@1 149 {
rlm@1 150 eepromMode = EEPROM_READDATA;
rlm@1 151 eepromByte = 0;
rlm@1 152 eepromBits = 0;
rlm@1 153 }
rlm@1 154 }
rlm@1 155 }
rlm@1 156 else
rlm@1 157 {
rlm@1 158 if (eepromBits == 9)
rlm@1 159 {
rlm@1 160 eepromInUse = true;
rlm@1 161 eepromAddress = (eepromBuffer[0] & 0x3F);
rlm@1 162 if (!(eepromBuffer[0] & 0x40))
rlm@1 163 {
rlm@1 164 eepromBuffer[0] = bit;
rlm@1 165 eepromBits = 1;
rlm@1 166 eepromByte = 0;
rlm@1 167 eepromMode = EEPROM_WRITEDATA;
rlm@1 168 }
rlm@1 169 else
rlm@1 170 {
rlm@1 171 eepromMode = EEPROM_READDATA;
rlm@1 172 eepromByte = 0;
rlm@1 173 eepromBits = 0;
rlm@1 174 }
rlm@1 175 }
rlm@1 176 }
rlm@1 177 break;
rlm@1 178 case EEPROM_READDATA:
rlm@1 179 case EEPROM_READDATA2:
rlm@1 180 // should we reset here?
rlm@1 181 eepromMode = EEPROM_IDLE;
rlm@1 182 break;
rlm@1 183 case EEPROM_WRITEDATA:
rlm@1 184 eepromBuffer[eepromByte] <<= 1;
rlm@1 185 eepromBuffer[eepromByte] |= bit;
rlm@1 186 eepromBits++;
rlm@1 187 if ((eepromBits & 7) == 0)
rlm@1 188 {
rlm@1 189 eepromByte++;
rlm@1 190 }
rlm@1 191 if (eepromBits == 0x40)
rlm@1 192 {
rlm@1 193 eepromInUse = true;
rlm@1 194 // write data;
rlm@1 195 for (int i = 0; i < 8; i++)
rlm@1 196 {
rlm@1 197 eepromData[(eepromAddress << 3) + i] = eepromBuffer[i];
rlm@1 198 }
rlm@1 199 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
rlm@1 200 }
rlm@1 201 else if (eepromBits == 0x41)
rlm@1 202 {
rlm@1 203 eepromMode = EEPROM_IDLE;
rlm@1 204 eepromByte = 0;
rlm@1 205 eepromBits = 0;
rlm@1 206 }
rlm@1 207 break;
rlm@1 208 }
rlm@1 209 }
rlm@1 210