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