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