src/gba/savedata.c (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "savedata.h"
7
8#include "gba/gba.h"
9#include "gba/serialize.h"
10
11#include "util/memory.h"
12#include "util/vfs.h"
13
14#include <errno.h>
15#include <fcntl.h>
16
17// Some testing was done here...
18// Erase cycles can vary greatly.
19// Some games may vary anywhere between about 2000 cycles to up to 30000 cycles. (Observed on a Macronix (09C2) chip).
20// Other games vary from very little, with a fairly solid 20500 cycle count. (Observed on a SST (D4BF) chip).
21// An average estimation is as follows.
22#define FLASH_SETTLE_CYCLES 18000
23
24static void _flashSwitchBank(struct GBASavedata* savedata, int bank);
25static void _flashErase(struct GBASavedata* savedata);
26static void _flashEraseSector(struct GBASavedata* savedata, uint16_t sectorStart);
27
28void GBASavedataInit(struct GBASavedata* savedata, struct VFile* vf) {
29 savedata->type = SAVEDATA_AUTODETECT;
30 savedata->data = 0;
31 savedata->command = EEPROM_COMMAND_NULL;
32 savedata->flashState = FLASH_STATE_RAW;
33 savedata->vf = vf;
34 savedata->realVf = vf;
35 savedata->mapMode = MAP_WRITE;
36}
37
38void GBASavedataDeinit(struct GBASavedata* savedata) {
39 if (savedata->vf) {
40 switch (savedata->type) {
41 case SAVEDATA_SRAM:
42 savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_SRAM);
43 break;
44 case SAVEDATA_FLASH512:
45 savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_FLASH512);
46 break;
47 case SAVEDATA_FLASH1M:
48 savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_FLASH1M);
49 break;
50 case SAVEDATA_EEPROM:
51 savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_EEPROM);
52 break;
53 case SAVEDATA_FORCE_NONE:
54 case SAVEDATA_AUTODETECT:
55 break;
56 }
57 savedata->vf = 0;
58 } else {
59 switch (savedata->type) {
60 case SAVEDATA_SRAM:
61 mappedMemoryFree(savedata->data, SIZE_CART_SRAM);
62 break;
63 case SAVEDATA_FLASH512:
64 mappedMemoryFree(savedata->data, SIZE_CART_FLASH512);
65 break;
66 case SAVEDATA_FLASH1M:
67 mappedMemoryFree(savedata->data, SIZE_CART_FLASH1M);
68 break;
69 case SAVEDATA_EEPROM:
70 mappedMemoryFree(savedata->data, SIZE_CART_EEPROM);
71 break;
72 case SAVEDATA_FORCE_NONE:
73 case SAVEDATA_AUTODETECT:
74 break;
75 }
76 }
77 savedata->data = 0;
78 savedata->type = SAVEDATA_AUTODETECT;
79}
80
81void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf) {
82 GBASavedataDeinit(savedata);
83 savedata->vf = vf;
84 savedata->mapMode = MAP_READ;
85}
86
87void GBASavedataUnmask(struct GBASavedata* savedata) {
88 if (savedata->mapMode != MAP_READ) {
89 return;
90 }
91 GBASavedataDeinit(savedata);
92 savedata->vf = savedata->realVf;
93 savedata->mapMode = MAP_WRITE;
94}
95
96bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) {
97 if (savedata->data) {
98 switch (savedata->type) {
99 case SAVEDATA_SRAM:
100 return out->write(out, savedata->data, SIZE_CART_SRAM) == SIZE_CART_SRAM;
101 case SAVEDATA_FLASH512:
102 return out->write(out, savedata->data, SIZE_CART_FLASH512) == SIZE_CART_FLASH512;
103 case SAVEDATA_FLASH1M:
104 return out->write(out, savedata->data, SIZE_CART_FLASH1M) == SIZE_CART_FLASH1M;
105 case SAVEDATA_EEPROM:
106 return out->write(out, savedata->data, SIZE_CART_EEPROM) == SIZE_CART_EEPROM;
107 case SAVEDATA_AUTODETECT:
108 case SAVEDATA_FORCE_NONE:
109 return true;
110 }
111 } else if (savedata->vf) {
112 off_t read = 0;
113 uint8_t buffer[2048];
114 do {
115 read = savedata->vf->read(savedata->vf, buffer, sizeof(buffer));
116 out->write(out, buffer, read);
117 } while (read == sizeof(buffer));
118 return read >= 0;
119 }
120 return true;
121}
122
123void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type, bool realisticTiming) {
124 if (savedata->type != SAVEDATA_AUTODETECT) {
125 struct VFile* vf = savedata->vf;
126 GBASavedataDeinit(savedata);
127 GBASavedataInit(savedata, vf);
128 }
129 switch (type) {
130 case SAVEDATA_FLASH512:
131 case SAVEDATA_FLASH1M:
132 savedata->type = type;
133 GBASavedataInitFlash(savedata, realisticTiming);
134 break;
135 case SAVEDATA_EEPROM:
136 GBASavedataInitEEPROM(savedata);
137 break;
138 case SAVEDATA_SRAM:
139 GBASavedataInitSRAM(savedata);
140 break;
141 case SAVEDATA_FORCE_NONE:
142 savedata->type = SAVEDATA_FORCE_NONE;
143 break;
144 case SAVEDATA_AUTODETECT:
145 break;
146 }
147}
148
149void GBASavedataInitFlash(struct GBASavedata* savedata, bool realisticTiming) {
150 if (savedata->type == SAVEDATA_AUTODETECT) {
151 savedata->type = SAVEDATA_FLASH512;
152 }
153 if (savedata->type != SAVEDATA_FLASH512 && savedata->type != SAVEDATA_FLASH1M) {
154 GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata");
155 return;
156 }
157 int32_t flashSize = SIZE_CART_FLASH512;
158 if (savedata->type == SAVEDATA_FLASH1M) {
159 flashSize = SIZE_CART_FLASH1M;
160 }
161 off_t end;
162 if (!savedata->vf) {
163 end = 0;
164 savedata->data = anonymousMemoryMap(SIZE_CART_FLASH1M);
165 } else {
166 end = savedata->vf->size(savedata->vf);
167 if (end < flashSize) {
168 savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M);
169 flashSize = SIZE_CART_FLASH1M;
170 }
171 savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_FLASH1M, savedata->mapMode);
172 }
173
174 savedata->currentBank = savedata->data;
175 savedata->dust = 0;
176 savedata->realisticTiming = realisticTiming;
177 if (end < SIZE_CART_FLASH512) {
178 memset(&savedata->data[end], 0xFF, flashSize - end);
179 }
180}
181
182void GBASavedataInitEEPROM(struct GBASavedata* savedata) {
183 if (savedata->type == SAVEDATA_AUTODETECT) {
184 savedata->type = SAVEDATA_EEPROM;
185 } else {
186 GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata");
187 return;
188 }
189 off_t end;
190 if (!savedata->vf) {
191 end = 0;
192 savedata->data = anonymousMemoryMap(SIZE_CART_EEPROM);
193 } else {
194 end = savedata->vf->size(savedata->vf);
195 if (end < SIZE_CART_EEPROM) {
196 savedata->vf->truncate(savedata->vf, SIZE_CART_EEPROM);
197 }
198 savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, savedata->mapMode);
199 }
200 if (end < SIZE_CART_EEPROM) {
201 memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM - end);
202 }
203}
204
205void GBASavedataInitSRAM(struct GBASavedata* savedata) {
206 if (savedata->type == SAVEDATA_AUTODETECT) {
207 savedata->type = SAVEDATA_SRAM;
208 } else {
209 GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata");
210 return;
211 }
212 off_t end;
213 if (!savedata->vf) {
214 end = 0;
215 savedata->data = anonymousMemoryMap(SIZE_CART_SRAM);
216 } else {
217 end = savedata->vf->size(savedata->vf);
218 if (end < SIZE_CART_SRAM) {
219 savedata->vf->truncate(savedata->vf, SIZE_CART_SRAM);
220 }
221 savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_SRAM, savedata->mapMode);
222 }
223
224 if (end < SIZE_CART_SRAM) {
225 memset(&savedata->data[end], 0xFF, SIZE_CART_SRAM - end);
226 }
227}
228
229uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address) {
230 if (savedata->command == FLASH_COMMAND_ID) {
231 if (savedata->type == SAVEDATA_FLASH512) {
232 if (address < 2) {
233 return FLASH_MFG_PANASONIC >> (address * 8);
234 }
235 } else if (savedata->type == SAVEDATA_FLASH1M) {
236 if (address < 2) {
237 return FLASH_MFG_SANYO >> (address * 8);
238 }
239 }
240 }
241 if (savedata->dust > 0 && (address >> 12) == savedata->settling) {
242 // Give some overhead for waitstates and the comparison
243 // This estimation can probably be improved
244 savedata->dust -= 10;
245 return 0x5F;
246 }
247 return savedata->currentBank[address];
248}
249
250void GBASavedataWriteFlash(struct GBASavedata* savedata, uint16_t address, uint8_t value) {
251 switch (savedata->flashState) {
252 case FLASH_STATE_RAW:
253 switch (savedata->command) {
254 case FLASH_COMMAND_PROGRAM:
255 savedata->currentBank[address] = value;
256 savedata->command = FLASH_COMMAND_NONE;
257 break;
258 case FLASH_COMMAND_SWITCH_BANK:
259 if (address == 0 && value < 2) {
260 _flashSwitchBank(savedata, value);
261 } else {
262 GBALog(0, GBA_LOG_GAME_ERROR, "Bad flash bank switch");
263 savedata->command = FLASH_COMMAND_NONE;
264 }
265 savedata->command = FLASH_COMMAND_NONE;
266 break;
267 default:
268 if (address == FLASH_BASE_HI && value == FLASH_COMMAND_START) {
269 savedata->flashState = FLASH_STATE_START;
270 } else {
271 GBALog(0, GBA_LOG_GAME_ERROR, "Bad flash write: %#04x = %#02x", address, value);
272 }
273 break;
274 }
275 break;
276 case FLASH_STATE_START:
277 if (address == FLASH_BASE_LO && value == FLASH_COMMAND_CONTINUE) {
278 savedata->flashState = FLASH_STATE_CONTINUE;
279 } else {
280 GBALog(0, GBA_LOG_GAME_ERROR, "Bad flash write: %#04x = %#02x", address, value);
281 savedata->flashState = FLASH_STATE_RAW;
282 }
283 break;
284 case FLASH_STATE_CONTINUE:
285 savedata->flashState = FLASH_STATE_RAW;
286 if (address == FLASH_BASE_HI) {
287 switch (savedata->command) {
288 case FLASH_COMMAND_NONE:
289 switch (value) {
290 case FLASH_COMMAND_ERASE:
291 case FLASH_COMMAND_ID:
292 case FLASH_COMMAND_PROGRAM:
293 case FLASH_COMMAND_SWITCH_BANK:
294 savedata->command = value;
295 break;
296 default:
297 GBALog(0, GBA_LOG_GAME_ERROR, "Unsupported flash operation: %#02x", value);
298 break;
299 }
300 break;
301 case FLASH_COMMAND_ERASE:
302 switch (value) {
303 case FLASH_COMMAND_ERASE_CHIP:
304 _flashErase(savedata);
305 break;
306 default:
307 GBALog(0, GBA_LOG_GAME_ERROR, "Unsupported flash erase operation: %#02x", value);
308 break;
309 }
310 savedata->command = FLASH_COMMAND_NONE;
311 break;
312 case FLASH_COMMAND_ID:
313 if (value == FLASH_COMMAND_TERMINATE) {
314 savedata->command = FLASH_COMMAND_NONE;
315 }
316 break;
317 default:
318 GBALog(0, GBA_LOG_ERROR, "Flash entered bad state: %#02x", savedata->command);
319 savedata->command = FLASH_COMMAND_NONE;
320 break;
321 }
322 } else if (savedata->command == FLASH_COMMAND_ERASE) {
323 if (value == FLASH_COMMAND_ERASE_SECTOR) {
324 _flashEraseSector(savedata, address);
325 savedata->command = FLASH_COMMAND_NONE;
326 } else {
327 GBALog(0, GBA_LOG_GAME_ERROR, "Unsupported flash erase operation: %#02x", value);
328 }
329 }
330 break;
331 }
332}
333
334void GBASavedataWriteEEPROM(struct GBASavedata* savedata, uint16_t value, uint32_t writeSize) {
335 switch (savedata->command) {
336 // Read header
337 case EEPROM_COMMAND_NULL:
338 default:
339 savedata->command = value & 0x1;
340 break;
341 case EEPROM_COMMAND_PENDING:
342 savedata->command <<= 1;
343 savedata->command |= value & 0x1;
344 if (savedata->command == EEPROM_COMMAND_WRITE) {
345 savedata->writeAddress = 0;
346 } else {
347 savedata->readAddress = 0;
348 }
349 break;
350 // Do commands
351 case EEPROM_COMMAND_WRITE:
352 // Write
353 if (writeSize > 65) {
354 savedata->writeAddress <<= 1;
355 savedata->writeAddress |= (value & 0x1) << 6;
356 } else if (writeSize == 1) {
357 savedata->command = EEPROM_COMMAND_NULL;
358 } else if ((savedata->writeAddress >> 3) < SIZE_CART_EEPROM) {
359 uint8_t current = savedata->data[savedata->writeAddress >> 3];
360 current &= ~(1 << (0x7 - (savedata->writeAddress & 0x7)));
361 current |= (value & 0x1) << (0x7 - (savedata->writeAddress & 0x7));
362 savedata->data[savedata->writeAddress >> 3] = current;
363 ++savedata->writeAddress;
364 } else {
365 GBALog(0, GBA_LOG_GAME_ERROR, "Writing beyond end of EEPROM: %08X", (savedata->writeAddress >> 3));
366 }
367 break;
368 case EEPROM_COMMAND_READ_PENDING:
369 // Read
370 if (writeSize > 1) {
371 savedata->readAddress <<= 1;
372 if (value & 0x1) {
373 savedata->readAddress |= 0x40;
374 }
375 } else {
376 savedata->readBitsRemaining = 68;
377 savedata->command = EEPROM_COMMAND_READ;
378 }
379 break;
380 }
381}
382
383uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata) {
384 if (savedata->command != EEPROM_COMMAND_READ) {
385 return 1;
386 }
387 --savedata->readBitsRemaining;
388 if (savedata->readBitsRemaining < 64) {
389 int step = 63 - savedata->readBitsRemaining;
390 uint32_t address = (savedata->readAddress + step) >> 3;
391 if (address >= SIZE_CART_EEPROM) {
392 GBALog(0, GBA_LOG_GAME_ERROR, "Reading beyond end of EEPROM: %08X", address);
393 return 0xFF;
394 }
395 uint8_t data = savedata->data[address] >> (0x7 - (step & 0x7));
396 if (!savedata->readBitsRemaining) {
397 savedata->command = EEPROM_COMMAND_NULL;
398 }
399 return data & 0x1;
400 }
401 return 0;
402}
403
404void GBASavedataSerialize(const struct GBASavedata* savedata, struct GBASerializedState* state, bool includeData) {
405 state->savedata.type = savedata->type;
406 state->savedata.command = savedata->command;
407 state->savedata.flashState = savedata->flashState;
408 state->savedata.flashBank = savedata->currentBank == &savedata->data[0x10000];
409 state->savedata.readBitsRemaining = savedata->readBitsRemaining;
410 state->savedata.readAddress = savedata->readAddress;
411 state->savedata.writeAddress = savedata->writeAddress;
412 state->savedata.settlingSector = savedata->settling;
413 state->savedata.settlingDust = savedata->dust;
414
415 UNUSED(includeData); // TODO
416}
417
418void GBASavedataDeserialize(struct GBASavedata* savedata, const struct GBASerializedState* state, bool includeData) {
419 if (state->savedata.type == SAVEDATA_FORCE_NONE) {
420 return;
421 }
422 if (savedata->type != state->savedata.type) {
423 GBASavedataForceType(savedata, state->savedata.type, savedata->realisticTiming);
424 }
425 savedata->command = state->savedata.command;
426 savedata->flashState = state->savedata.flashState;
427 savedata->readBitsRemaining = state->savedata.readBitsRemaining;
428 savedata->readAddress = state->savedata.readAddress;
429 savedata->writeAddress = state->savedata.writeAddress;
430 savedata->settling = state->savedata.settlingSector;
431 savedata->dust = state->savedata.settlingDust;
432
433 if (savedata->type == SAVEDATA_FLASH1M) {
434 _flashSwitchBank(savedata, state->savedata.flashBank);
435 }
436
437 UNUSED(includeData); // TODO
438}
439
440void _flashSwitchBank(struct GBASavedata* savedata, int bank) {
441 GBALog(0, GBA_LOG_DEBUG, "Performing flash bank switch to bank %i", bank);
442 savedata->currentBank = &savedata->data[bank << 16];
443 if (bank > 0 && savedata->type == SAVEDATA_FLASH512) {
444 savedata->type = SAVEDATA_FLASH1M;
445 if (savedata->vf) {
446 savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M);
447 memset(&savedata->data[SIZE_CART_FLASH512], 0xFF, SIZE_CART_FLASH512);
448 }
449 }
450}
451
452void _flashErase(struct GBASavedata* savedata) {
453 GBALog(0, GBA_LOG_DEBUG, "Performing flash chip erase");
454 size_t size = SIZE_CART_FLASH512;
455 if (savedata->type == SAVEDATA_FLASH1M) {
456 size = SIZE_CART_FLASH1M;
457 }
458 memset(savedata->data, 0xFF, size);
459}
460
461void _flashEraseSector(struct GBASavedata* savedata, uint16_t sectorStart) {
462 GBALog(0, GBA_LOG_DEBUG, "Performing flash sector erase at 0x%04x", sectorStart);
463 size_t size = 0x1000;
464 if (savedata->type == SAVEDATA_FLASH1M) {
465 GBALog(0, GBA_LOG_DEBUG, "Performing unknown sector-size erase at 0x%04x", sectorStart);
466 }
467 savedata->settling = sectorStart >> 12;
468 if (savedata->realisticTiming) {
469 savedata->dust = FLASH_SETTLE_CYCLES;
470 }
471 memset(&savedata->currentBank[sectorStart & ~(size - 1)], 0xFF, size);
472}