view src/gba/EEprom.cpp @ 331:6ec288064d49

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