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#define CLEANUP_THRESHOLD 15
24
25mLOG_DEFINE_CATEGORY(GBA_SAVE, "GBA Savedata");
26
27static void _flashSwitchBank(struct GBASavedata* savedata, int bank);
28static void _flashErase(struct GBASavedata* savedata);
29static void _flashEraseSector(struct GBASavedata* savedata, uint16_t sectorStart);
30
31void GBASavedataInit(struct GBASavedata* savedata, struct VFile* vf) {
32 savedata->type = SAVEDATA_AUTODETECT;
33 savedata->data = 0;
34 savedata->command = EEPROM_COMMAND_NULL;
35 savedata->flashState = FLASH_STATE_RAW;
36 savedata->vf = vf;
37 savedata->realVf = vf;
38 savedata->mapMode = MAP_WRITE;
39 savedata->dirty = 0;
40 savedata->dirtAge = 0;
41}
42
43void GBASavedataDeinit(struct GBASavedata* savedata) {
44 if (savedata->vf) {
45 switch (savedata->type) {
46 case SAVEDATA_SRAM:
47 savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_SRAM);
48 break;
49 case SAVEDATA_FLASH512:
50 savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_FLASH512);
51 break;
52 case SAVEDATA_FLASH1M:
53 savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_FLASH1M);
54 break;
55 case SAVEDATA_EEPROM:
56 savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_EEPROM);
57 break;
58 case SAVEDATA_FORCE_NONE:
59 case SAVEDATA_AUTODETECT:
60 break;
61 }
62 savedata->vf = 0;
63 } else {
64 switch (savedata->type) {
65 case SAVEDATA_SRAM:
66 mappedMemoryFree(savedata->data, SIZE_CART_SRAM);
67 break;
68 case SAVEDATA_FLASH512:
69 mappedMemoryFree(savedata->data, SIZE_CART_FLASH512);
70 break;
71 case SAVEDATA_FLASH1M:
72 mappedMemoryFree(savedata->data, SIZE_CART_FLASH1M);
73 break;
74 case SAVEDATA_EEPROM:
75 mappedMemoryFree(savedata->data, SIZE_CART_EEPROM);
76 break;
77 case SAVEDATA_FORCE_NONE:
78 case SAVEDATA_AUTODETECT:
79 break;
80 }
81 }
82 savedata->data = 0;
83 savedata->type = SAVEDATA_AUTODETECT;
84}
85
86void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf) {
87 enum SavedataType type = savedata->type;
88 GBASavedataDeinit(savedata);
89 savedata->vf = vf;
90 savedata->mapMode = MAP_READ;
91 GBASavedataForceType(savedata, type, savedata->realisticTiming);
92}
93
94void GBASavedataUnmask(struct GBASavedata* savedata) {
95 if (savedata->mapMode != MAP_READ) {
96 return;
97 }
98 enum SavedataType type = savedata->type;
99 GBASavedataDeinit(savedata);
100 savedata->vf = savedata->realVf;
101 savedata->mapMode = MAP_WRITE;
102 GBASavedataForceType(savedata, type, savedata->realisticTiming);
103}
104
105bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) {
106 if (savedata->data) {
107 switch (savedata->type) {
108 case SAVEDATA_SRAM:
109 return out->write(out, savedata->data, SIZE_CART_SRAM) == SIZE_CART_SRAM;
110 case SAVEDATA_FLASH512:
111 return out->write(out, savedata->data, SIZE_CART_FLASH512) == SIZE_CART_FLASH512;
112 case SAVEDATA_FLASH1M:
113 return out->write(out, savedata->data, SIZE_CART_FLASH1M) == SIZE_CART_FLASH1M;
114 case SAVEDATA_EEPROM:
115 return out->write(out, savedata->data, SIZE_CART_EEPROM) == SIZE_CART_EEPROM;
116 case SAVEDATA_AUTODETECT:
117 case SAVEDATA_FORCE_NONE:
118 return true;
119 }
120 } else if (savedata->vf) {
121 off_t read = 0;
122 uint8_t buffer[2048];
123 do {
124 read = savedata->vf->read(savedata->vf, buffer, sizeof(buffer));
125 out->write(out, buffer, read);
126 } while (read == sizeof(buffer));
127 return read >= 0;
128 }
129 return true;
130}
131
132size_t GBASavedataSize(struct GBASavedata* savedata) {
133 switch (savedata->type) {
134 case SAVEDATA_SRAM:
135 return SIZE_CART_SRAM;
136 case SAVEDATA_FLASH512:
137 return SIZE_CART_FLASH512;
138 case SAVEDATA_FLASH1M:
139 return SIZE_CART_FLASH1M;
140 case SAVEDATA_EEPROM:
141 return SIZE_CART_EEPROM;
142 case SAVEDATA_FORCE_NONE:
143 return 0;
144 case SAVEDATA_AUTODETECT:
145 default:
146 if (savedata->vf) {
147 return savedata->vf->size(savedata->vf);
148 }
149 return 0;
150 }
151}
152
153bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in) {
154 if (savedata->vf) {
155 off_t read = 0;
156 uint8_t buffer[2048];
157 memset(buffer, 0xFF, sizeof(buffer));
158 savedata->vf->seek(savedata->vf, 0, SEEK_SET);
159 while (savedata->vf->seek(savedata->vf, 0, SEEK_CUR) < savedata->vf->size(savedata->vf)) {
160 savedata->vf->write(savedata->vf, buffer, sizeof(buffer));
161 }
162 savedata->vf->seek(savedata->vf, 0, SEEK_SET);
163 if (in) {
164 do {
165 read = in->read(in, buffer, sizeof(buffer));
166 read = savedata->vf->write(savedata->vf, buffer, read);
167 } while (read == sizeof(buffer));
168 }
169 return read >= 0;
170 } else if (savedata->data) {
171 if (!in && savedata->type != SAVEDATA_FORCE_NONE) {
172 return false;
173 }
174 switch (savedata->type) {
175 case SAVEDATA_SRAM:
176 return in->read(in, savedata->data, SIZE_CART_SRAM) == SIZE_CART_SRAM;
177 case SAVEDATA_FLASH512:
178 return in->read(in, savedata->data, SIZE_CART_FLASH512) == SIZE_CART_FLASH512;
179 case SAVEDATA_FLASH1M:
180 return in->read(in, savedata->data, SIZE_CART_FLASH1M) == SIZE_CART_FLASH1M;
181 case SAVEDATA_EEPROM:
182 return in->read(in, savedata->data, SIZE_CART_EEPROM) == SIZE_CART_EEPROM;
183 case SAVEDATA_AUTODETECT:
184 case SAVEDATA_FORCE_NONE:
185 return true;
186 }
187 }
188 return true;
189}
190
191void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type, bool realisticTiming) {
192 if (savedata->type != SAVEDATA_AUTODETECT) {
193 struct VFile* vf = savedata->vf;
194 GBASavedataDeinit(savedata);
195 GBASavedataInit(savedata, vf);
196 }
197 switch (type) {
198 case SAVEDATA_FLASH512:
199 case SAVEDATA_FLASH1M:
200 savedata->type = type;
201 GBASavedataInitFlash(savedata, realisticTiming);
202 break;
203 case SAVEDATA_EEPROM:
204 GBASavedataInitEEPROM(savedata);
205 break;
206 case SAVEDATA_SRAM:
207 GBASavedataInitSRAM(savedata);
208 break;
209 case SAVEDATA_FORCE_NONE:
210 savedata->type = SAVEDATA_FORCE_NONE;
211 break;
212 case SAVEDATA_AUTODETECT:
213 break;
214 }
215}
216
217void GBASavedataInitFlash(struct GBASavedata* savedata, bool realisticTiming) {
218 if (savedata->type == SAVEDATA_AUTODETECT) {
219 savedata->type = SAVEDATA_FLASH512;
220 }
221 if (savedata->type != SAVEDATA_FLASH512 && savedata->type != SAVEDATA_FLASH1M) {
222 mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
223 return;
224 }
225 int32_t flashSize = SIZE_CART_FLASH512;
226 if (savedata->type == SAVEDATA_FLASH1M) {
227 flashSize = SIZE_CART_FLASH1M;
228 }
229 off_t end;
230 if (!savedata->vf) {
231 end = 0;
232 savedata->data = anonymousMemoryMap(SIZE_CART_FLASH1M);
233 } else {
234 end = savedata->vf->size(savedata->vf);
235 if (end < flashSize) {
236 savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M);
237 flashSize = SIZE_CART_FLASH1M;
238 }
239 savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_FLASH1M, savedata->mapMode);
240 }
241
242 savedata->currentBank = savedata->data;
243 savedata->dust = 0;
244 savedata->realisticTiming = realisticTiming;
245 if (end < SIZE_CART_FLASH512) {
246 memset(&savedata->data[end], 0xFF, flashSize - end);
247 }
248}
249
250void GBASavedataInitEEPROM(struct GBASavedata* savedata) {
251 if (savedata->type == SAVEDATA_AUTODETECT) {
252 savedata->type = SAVEDATA_EEPROM;
253 } else {
254 mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
255 return;
256 }
257 off_t end;
258 if (!savedata->vf) {
259 end = 0;
260 savedata->data = anonymousMemoryMap(SIZE_CART_EEPROM);
261 } else {
262 end = savedata->vf->size(savedata->vf);
263 if (end < SIZE_CART_EEPROM) {
264 savedata->vf->truncate(savedata->vf, SIZE_CART_EEPROM);
265 }
266 savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, savedata->mapMode);
267 }
268 if (end < SIZE_CART_EEPROM) {
269 memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM - end);
270 }
271}
272
273void GBASavedataInitSRAM(struct GBASavedata* savedata) {
274 if (savedata->type == SAVEDATA_AUTODETECT) {
275 savedata->type = SAVEDATA_SRAM;
276 } else {
277 mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
278 return;
279 }
280 off_t end;
281 if (!savedata->vf) {
282 end = 0;
283 savedata->data = anonymousMemoryMap(SIZE_CART_SRAM);
284 } else {
285 end = savedata->vf->size(savedata->vf);
286 if (end < SIZE_CART_SRAM) {
287 savedata->vf->truncate(savedata->vf, SIZE_CART_SRAM);
288 }
289 savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_SRAM, savedata->mapMode);
290 }
291
292 if (end < SIZE_CART_SRAM) {
293 memset(&savedata->data[end], 0xFF, SIZE_CART_SRAM - end);
294 }
295}
296
297uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address) {
298 if (savedata->command == FLASH_COMMAND_ID) {
299 if (savedata->type == SAVEDATA_FLASH512) {
300 if (address < 2) {
301 return FLASH_MFG_PANASONIC >> (address * 8);
302 }
303 } else if (savedata->type == SAVEDATA_FLASH1M) {
304 if (address < 2) {
305 return FLASH_MFG_SANYO >> (address * 8);
306 }
307 }
308 }
309 if (savedata->dust > 0 && (address >> 12) == savedata->settling) {
310 // Give some overhead for waitstates and the comparison
311 // This estimation can probably be improved
312 savedata->dust -= 10;
313 return 0x5F;
314 }
315 return savedata->currentBank[address];
316}
317
318void GBASavedataWriteFlash(struct GBASavedata* savedata, uint16_t address, uint8_t value) {
319 switch (savedata->flashState) {
320 case FLASH_STATE_RAW:
321 switch (savedata->command) {
322 case FLASH_COMMAND_PROGRAM:
323 savedata->dirty |= SAVEDATA_DIRT_NEW;
324 savedata->currentBank[address] = value;
325 savedata->command = FLASH_COMMAND_NONE;
326 break;
327 case FLASH_COMMAND_SWITCH_BANK:
328 if (address == 0 && value < 2) {
329 _flashSwitchBank(savedata, value);
330 } else {
331 mLOG(GBA_SAVE, GAME_ERROR, "Bad flash bank switch");
332 savedata->command = FLASH_COMMAND_NONE;
333 }
334 savedata->command = FLASH_COMMAND_NONE;
335 break;
336 default:
337 if (address == FLASH_BASE_HI && value == FLASH_COMMAND_START) {
338 savedata->flashState = FLASH_STATE_START;
339 } else {
340 mLOG(GBA_SAVE, GAME_ERROR, "Bad flash write: %#04x = %#02x", address, value);
341 }
342 break;
343 }
344 break;
345 case FLASH_STATE_START:
346 if (address == FLASH_BASE_LO && value == FLASH_COMMAND_CONTINUE) {
347 savedata->flashState = FLASH_STATE_CONTINUE;
348 } else {
349 mLOG(GBA_SAVE, GAME_ERROR, "Bad flash write: %#04x = %#02x", address, value);
350 savedata->flashState = FLASH_STATE_RAW;
351 }
352 break;
353 case FLASH_STATE_CONTINUE:
354 savedata->flashState = FLASH_STATE_RAW;
355 if (address == FLASH_BASE_HI) {
356 switch (savedata->command) {
357 case FLASH_COMMAND_NONE:
358 switch (value) {
359 case FLASH_COMMAND_ERASE:
360 case FLASH_COMMAND_ID:
361 case FLASH_COMMAND_PROGRAM:
362 case FLASH_COMMAND_SWITCH_BANK:
363 savedata->command = value;
364 break;
365 default:
366 mLOG(GBA_SAVE, GAME_ERROR, "Unsupported flash operation: %#02x", value);
367 break;
368 }
369 break;
370 case FLASH_COMMAND_ERASE:
371 switch (value) {
372 case FLASH_COMMAND_ERASE_CHIP:
373 _flashErase(savedata);
374 break;
375 default:
376 mLOG(GBA_SAVE, GAME_ERROR, "Unsupported flash erase operation: %#02x", value);
377 break;
378 }
379 savedata->command = FLASH_COMMAND_NONE;
380 break;
381 case FLASH_COMMAND_ID:
382 if (value == FLASH_COMMAND_TERMINATE) {
383 savedata->command = FLASH_COMMAND_NONE;
384 }
385 break;
386 default:
387 mLOG(GBA_SAVE, ERROR, "Flash entered bad state: %#02x", savedata->command);
388 savedata->command = FLASH_COMMAND_NONE;
389 break;
390 }
391 } else if (savedata->command == FLASH_COMMAND_ERASE) {
392 if (value == FLASH_COMMAND_ERASE_SECTOR) {
393 _flashEraseSector(savedata, address);
394 savedata->command = FLASH_COMMAND_NONE;
395 } else {
396 mLOG(GBA_SAVE, GAME_ERROR, "Unsupported flash erase operation: %#02x", value);
397 }
398 }
399 break;
400 }
401}
402
403void GBASavedataWriteEEPROM(struct GBASavedata* savedata, uint16_t value, uint32_t writeSize) {
404 switch (savedata->command) {
405 // Read header
406 case EEPROM_COMMAND_NULL:
407 default:
408 savedata->command = value & 0x1;
409 break;
410 case EEPROM_COMMAND_PENDING:
411 savedata->command <<= 1;
412 savedata->command |= value & 0x1;
413 if (savedata->command == EEPROM_COMMAND_WRITE) {
414 savedata->writeAddress = 0;
415 } else {
416 savedata->readAddress = 0;
417 }
418 break;
419 // Do commands
420 case EEPROM_COMMAND_WRITE:
421 // Write
422 if (writeSize > 65) {
423 savedata->writeAddress <<= 1;
424 savedata->writeAddress |= (value & 0x1) << 6;
425 } else if (writeSize == 1) {
426 savedata->command = EEPROM_COMMAND_NULL;
427 } else if ((savedata->writeAddress >> 3) < SIZE_CART_EEPROM) {
428 uint8_t current = savedata->data[savedata->writeAddress >> 3];
429 current &= ~(1 << (0x7 - (savedata->writeAddress & 0x7)));
430 current |= (value & 0x1) << (0x7 - (savedata->writeAddress & 0x7));
431 savedata->dirty |= SAVEDATA_DIRT_NEW;
432 savedata->data[savedata->writeAddress >> 3] = current;
433 ++savedata->writeAddress;
434 } else {
435 mLOG(GBA_SAVE, GAME_ERROR, "Writing beyond end of EEPROM: %08X", (savedata->writeAddress >> 3));
436 }
437 break;
438 case EEPROM_COMMAND_READ_PENDING:
439 // Read
440 if (writeSize > 1) {
441 savedata->readAddress <<= 1;
442 if (value & 0x1) {
443 savedata->readAddress |= 0x40;
444 }
445 } else {
446 savedata->readBitsRemaining = 68;
447 savedata->command = EEPROM_COMMAND_READ;
448 }
449 break;
450 }
451}
452
453uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata) {
454 if (savedata->command != EEPROM_COMMAND_READ) {
455 return 1;
456 }
457 --savedata->readBitsRemaining;
458 if (savedata->readBitsRemaining < 64) {
459 int step = 63 - savedata->readBitsRemaining;
460 uint32_t address = (savedata->readAddress + step) >> 3;
461 if (address >= SIZE_CART_EEPROM) {
462 mLOG(GBA_SAVE, GAME_ERROR, "Reading beyond end of EEPROM: %08X", address);
463 return 0xFF;
464 }
465 uint8_t data = savedata->data[address] >> (0x7 - (step & 0x7));
466 if (!savedata->readBitsRemaining) {
467 savedata->command = EEPROM_COMMAND_NULL;
468 }
469 return data & 0x1;
470 }
471 return 0;
472}
473
474void GBASavedataClean(struct GBASavedata* savedata, uint32_t frameCount) {
475 if (!savedata->vf) {
476 return;
477 }
478 if (savedata->dirty & SAVEDATA_DIRT_NEW) {
479 savedata->dirty &= ~SAVEDATA_DIRT_NEW;
480 if (!(savedata->dirty & SAVEDATA_DIRT_SEEN)) {
481 savedata->dirtAge = frameCount;
482 savedata->dirty |= SAVEDATA_DIRT_SEEN;
483 }
484 } else if ((savedata->dirty & SAVEDATA_DIRT_SEEN) && frameCount - savedata->dirtAge > CLEANUP_THRESHOLD) {
485 size_t size;
486 switch (savedata->type) {
487 case SAVEDATA_EEPROM:
488 size = SIZE_CART_EEPROM;
489 break;
490 case SAVEDATA_SRAM:
491 size = SIZE_CART_SRAM;
492 break;
493 case SAVEDATA_FLASH512:
494 size = SIZE_CART_FLASH512;
495 break;
496 case SAVEDATA_FLASH1M:
497 size = SIZE_CART_FLASH1M;
498 break;
499 default:
500 size = 0;
501 break;
502 }
503 savedata->vf->sync(savedata->vf, savedata->data, size);
504 savedata->dirty = 0;
505 mLOG(GBA_SAVE, INFO, "Savedata synced");
506 }
507}
508
509void GBASavedataSerialize(const struct GBASavedata* savedata, struct GBASerializedState* state) {
510 state->savedata.type = savedata->type;
511 state->savedata.command = savedata->command;
512 GBASerializedSavedataFlags flags = 0;
513 flags = GBASerializedSavedataFlagsSetFlashState(flags, savedata->flashState);
514 flags = GBASerializedSavedataFlagsTestFillFlashBank(flags, savedata->currentBank == &savedata->data[0x10000]);
515 state->savedata.flags = flags;
516 STORE_32(savedata->readBitsRemaining, 0, &state->savedata.readBitsRemaining);
517 STORE_32(savedata->readAddress, 0, &state->savedata.readAddress);
518 STORE_32(savedata->writeAddress, 0, &state->savedata.writeAddress);
519 STORE_16(savedata->settling, 0, &state->savedata.settlingSector);
520 STORE_16(savedata->dust, 0, &state->savedata.settlingDust);
521}
522
523void GBASavedataDeserialize(struct GBASavedata* savedata, const struct GBASerializedState* state) {
524 if (state->savedata.type == SAVEDATA_FORCE_NONE) {
525 return;
526 }
527 if (savedata->type != state->savedata.type) {
528 GBASavedataForceType(savedata, state->savedata.type, savedata->realisticTiming);
529 }
530 savedata->command = state->savedata.command;
531 GBASerializedSavedataFlags flags = state->savedata.flags;
532 savedata->flashState = GBASerializedSavedataFlagsGetFlashState(flags);
533 LOAD_32(savedata->readBitsRemaining, 0, &state->savedata.readBitsRemaining);
534 LOAD_32(savedata->readAddress, 0, &state->savedata.readAddress);
535 LOAD_32(savedata->writeAddress, 0, &state->savedata.writeAddress);
536 LOAD_16(savedata->settling, 0, &state->savedata.settlingSector);
537 LOAD_16(savedata->dust, 0, &state->savedata.settlingDust);
538
539 if (savedata->type == SAVEDATA_FLASH1M) {
540 _flashSwitchBank(savedata, GBASerializedSavedataFlagsGetFlashBank(flags));
541 }
542}
543
544void _flashSwitchBank(struct GBASavedata* savedata, int bank) {
545 mLOG(GBA_SAVE, DEBUG, "Performing flash bank switch to bank %i", bank);
546 savedata->currentBank = &savedata->data[bank << 16];
547 if (bank > 0 && savedata->type == SAVEDATA_FLASH512) {
548 savedata->type = SAVEDATA_FLASH1M;
549 if (savedata->vf) {
550 savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M);
551 memset(&savedata->data[SIZE_CART_FLASH512], 0xFF, SIZE_CART_FLASH512);
552 }
553 }
554}
555
556void _flashErase(struct GBASavedata* savedata) {
557 mLOG(GBA_SAVE, DEBUG, "Performing flash chip erase");
558 savedata->dirty |= SAVEDATA_DIRT_NEW;
559 size_t size = SIZE_CART_FLASH512;
560 if (savedata->type == SAVEDATA_FLASH1M) {
561 size = SIZE_CART_FLASH1M;
562 }
563 memset(savedata->data, 0xFF, size);
564}
565
566void _flashEraseSector(struct GBASavedata* savedata, uint16_t sectorStart) {
567 mLOG(GBA_SAVE, DEBUG, "Performing flash sector erase at 0x%04x", sectorStart);
568 savedata->dirty |= SAVEDATA_DIRT_NEW;
569 size_t size = 0x1000;
570 if (savedata->type == SAVEDATA_FLASH1M) {
571 mLOG(GBA_SAVE, DEBUG, "Performing unknown sector-size erase at 0x%04x", sectorStart);
572 }
573 savedata->settling = sectorStart >> 12;
574 if (savedata->realisticTiming) {
575 savedata->dust = FLASH_SETTLE_CYCLES;
576 }
577 memset(&savedata->currentBank[sectorStart & ~(size - 1)], 0xFF, size);
578}