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 savedata->vf->unmap(savedata->vf, savedata->data, size);
50 savedata->vf = NULL;
51 } else {
52 switch (savedata->type) {
53 case SAVEDATA_SRAM:
54 mappedMemoryFree(savedata->data, SIZE_CART_SRAM);
55 break;
56 case SAVEDATA_FLASH512:
57 mappedMemoryFree(savedata->data, SIZE_CART_FLASH512);
58 break;
59 case SAVEDATA_FLASH1M:
60 mappedMemoryFree(savedata->data, SIZE_CART_FLASH1M);
61 break;
62 case SAVEDATA_EEPROM:
63 mappedMemoryFree(savedata->data, SIZE_CART_EEPROM);
64 break;
65 case SAVEDATA_FORCE_NONE:
66 case SAVEDATA_AUTODETECT:
67 break;
68 }
69 }
70 savedata->data = 0;
71 savedata->type = SAVEDATA_AUTODETECT;
72}
73
74void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf, bool writeback) {
75 enum SavedataType type = savedata->type;
76 GBASavedataDeinit(savedata);
77 savedata->vf = vf;
78 savedata->mapMode = MAP_READ;
79 savedata->maskWriteback = writeback;
80 GBASavedataForceType(savedata, type, savedata->realisticTiming);
81}
82
83void GBASavedataUnmask(struct GBASavedata* savedata) {
84 if (savedata->vf == savedata->realVf) {
85 return;
86 }
87 enum SavedataType type = savedata->type;
88 struct VFile* vf = savedata->vf;
89 GBASavedataDeinit(savedata);
90 savedata->vf = savedata->realVf;
91 savedata->mapMode = MAP_WRITE;
92 GBASavedataForceType(savedata, type, savedata->realisticTiming);
93 if (savedata->maskWriteback) {
94 GBASavedataLoad(savedata, vf);
95 savedata->maskWriteback = false;
96 }
97 vf->close(vf);
98}
99
100bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) {
101 if (savedata->data) {
102 switch (savedata->type) {
103 case SAVEDATA_SRAM:
104 return out->write(out, savedata->data, SIZE_CART_SRAM) == SIZE_CART_SRAM;
105 case SAVEDATA_FLASH512:
106 return out->write(out, savedata->data, SIZE_CART_FLASH512) == SIZE_CART_FLASH512;
107 case SAVEDATA_FLASH1M:
108 return out->write(out, savedata->data, SIZE_CART_FLASH1M) == SIZE_CART_FLASH1M;
109 case SAVEDATA_EEPROM:
110 return out->write(out, savedata->data, SIZE_CART_EEPROM) == SIZE_CART_EEPROM;
111 case SAVEDATA_AUTODETECT:
112 case SAVEDATA_FORCE_NONE:
113 return true;
114 }
115 } else if (savedata->vf) {
116 off_t read = 0;
117 uint8_t buffer[2048];
118 do {
119 read = savedata->vf->read(savedata->vf, buffer, sizeof(buffer));
120 out->write(out, buffer, read);
121 } while (read == sizeof(buffer));
122 return read >= 0;
123 }
124 return true;
125}
126
127size_t GBASavedataSize(struct GBASavedata* savedata) {
128 switch (savedata->type) {
129 case SAVEDATA_SRAM:
130 return SIZE_CART_SRAM;
131 case SAVEDATA_FLASH512:
132 return SIZE_CART_FLASH512;
133 case SAVEDATA_FLASH1M:
134 return SIZE_CART_FLASH1M;
135 case SAVEDATA_EEPROM:
136 return SIZE_CART_EEPROM;
137 case SAVEDATA_FORCE_NONE:
138 return 0;
139 case SAVEDATA_AUTODETECT:
140 default:
141 if (savedata->vf) {
142 return savedata->vf->size(savedata->vf);
143 }
144 return 0;
145 }
146}
147
148bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in) {
149 if (savedata->vf) {
150 off_t read = 0;
151 uint8_t buffer[2048];
152 memset(buffer, 0xFF, sizeof(buffer));
153 savedata->vf->seek(savedata->vf, 0, SEEK_SET);
154 while (savedata->vf->seek(savedata->vf, 0, SEEK_CUR) < savedata->vf->size(savedata->vf)) {
155 savedata->vf->write(savedata->vf, buffer, sizeof(buffer));
156 }
157 savedata->vf->seek(savedata->vf, 0, SEEK_SET);
158 if (in) {
159 do {
160 read = in->read(in, buffer, sizeof(buffer));
161 read = savedata->vf->write(savedata->vf, buffer, read);
162 } while (read == sizeof(buffer));
163 }
164 return read >= 0;
165 } else if (savedata->data) {
166 if (!in && savedata->type != SAVEDATA_FORCE_NONE) {
167 return false;
168 }
169 switch (savedata->type) {
170 case SAVEDATA_SRAM:
171 return in->read(in, savedata->data, SIZE_CART_SRAM) == SIZE_CART_SRAM;
172 case SAVEDATA_FLASH512:
173 return in->read(in, savedata->data, SIZE_CART_FLASH512) == SIZE_CART_FLASH512;
174 case SAVEDATA_FLASH1M:
175 return in->read(in, savedata->data, SIZE_CART_FLASH1M) == SIZE_CART_FLASH1M;
176 case SAVEDATA_EEPROM:
177 return in->read(in, savedata->data, SIZE_CART_EEPROM) == SIZE_CART_EEPROM;
178 case SAVEDATA_AUTODETECT:
179 case SAVEDATA_FORCE_NONE:
180 return true;
181 }
182 }
183 return true;
184}
185
186void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type, bool realisticTiming) {
187 if (savedata->type != SAVEDATA_AUTODETECT) {
188 struct VFile* vf = savedata->vf;
189 GBASavedataDeinit(savedata);
190 GBASavedataInit(savedata, vf);
191 }
192 switch (type) {
193 case SAVEDATA_FLASH512:
194 case SAVEDATA_FLASH1M:
195 savedata->type = type;
196 GBASavedataInitFlash(savedata, realisticTiming);
197 break;
198 case SAVEDATA_EEPROM:
199 GBASavedataInitEEPROM(savedata, realisticTiming);
200 break;
201 case SAVEDATA_SRAM:
202 GBASavedataInitSRAM(savedata);
203 break;
204 case SAVEDATA_FORCE_NONE:
205 savedata->type = SAVEDATA_FORCE_NONE;
206 break;
207 case SAVEDATA_AUTODETECT:
208 break;
209 }
210}
211
212void GBASavedataInitFlash(struct GBASavedata* savedata, bool realisticTiming) {
213 if (savedata->type == SAVEDATA_AUTODETECT) {
214 savedata->type = SAVEDATA_FLASH512;
215 }
216 if (savedata->type != SAVEDATA_FLASH512 && savedata->type != SAVEDATA_FLASH1M) {
217 mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
218 return;
219 }
220 int32_t flashSize = SIZE_CART_FLASH512;
221 if (savedata->type == SAVEDATA_FLASH1M) {
222 flashSize = SIZE_CART_FLASH1M;
223 }
224 off_t end;
225 if (!savedata->vf) {
226 end = 0;
227 savedata->data = anonymousMemoryMap(SIZE_CART_FLASH1M);
228 } else {
229 end = savedata->vf->size(savedata->vf);
230 if (end < flashSize) {
231 savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M);
232 flashSize = SIZE_CART_FLASH1M;
233 }
234 savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_FLASH1M, savedata->mapMode);
235 }
236
237 savedata->currentBank = savedata->data;
238 savedata->dust = 0;
239 savedata->realisticTiming = realisticTiming;
240 if (end < SIZE_CART_FLASH512) {
241 memset(&savedata->data[end], 0xFF, flashSize - end);
242 }
243}
244
245void GBASavedataInitEEPROM(struct GBASavedata* savedata, bool realisticTiming) {
246 if (savedata->type == SAVEDATA_AUTODETECT) {
247 savedata->type = SAVEDATA_EEPROM;
248 } else {
249 mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
250 return;
251 }
252 off_t end;
253 if (!savedata->vf) {
254 end = 0;
255 savedata->data = anonymousMemoryMap(SIZE_CART_EEPROM);
256 } else {
257 end = savedata->vf->size(savedata->vf);
258 if (end < SIZE_CART_EEPROM) {
259 savedata->vf->truncate(savedata->vf, SIZE_CART_EEPROM);
260 }
261 savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, savedata->mapMode);
262 }
263 savedata->dust = 0;
264 savedata->realisticTiming = realisticTiming;
265 if (end < SIZE_CART_EEPROM) {
266 memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM - end);
267 }
268}
269
270void GBASavedataInitSRAM(struct GBASavedata* savedata) {
271 if (savedata->type == SAVEDATA_AUTODETECT) {
272 savedata->type = SAVEDATA_SRAM;
273 } else {
274 mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
275 return;
276 }
277 off_t end;
278 if (!savedata->vf) {
279 end = 0;
280 savedata->data = anonymousMemoryMap(SIZE_CART_SRAM);
281 } else {
282 end = savedata->vf->size(savedata->vf);
283 if (end < SIZE_CART_SRAM) {
284 savedata->vf->truncate(savedata->vf, SIZE_CART_SRAM);
285 }
286 savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_SRAM, savedata->mapMode);
287 }
288
289 if (end < SIZE_CART_SRAM) {
290 memset(&savedata->data[end], 0xFF, SIZE_CART_SRAM - end);
291 }
292}
293
294uint8_t GBASavedataReadFlash(struct GBASavedata* savedata, uint16_t address) {
295 if (savedata->command == FLASH_COMMAND_ID) {
296 if (savedata->type == SAVEDATA_FLASH512) {
297 if (address < 2) {
298 return FLASH_MFG_PANASONIC >> (address * 8);
299 }
300 } else if (savedata->type == SAVEDATA_FLASH1M) {
301 if (address < 2) {
302 return FLASH_MFG_SANYO >> (address * 8);
303 }
304 }
305 }
306 if (savedata->dust > 0 && (address >> 12) == savedata->settling) {
307 // Give some overhead for waitstates and the comparison
308 // This estimation can probably be improved
309 savedata->dust -= 5000;
310 return 0x5F;
311 }
312 return savedata->currentBank[address];
313}
314
315void GBASavedataWriteFlash(struct GBASavedata* savedata, uint16_t address, uint8_t value) {
316 switch (savedata->flashState) {
317 case FLASH_STATE_RAW:
318 switch (savedata->command) {
319 case FLASH_COMMAND_PROGRAM:
320 savedata->dirty |= SAVEDATA_DIRT_NEW;
321 savedata->currentBank[address] = value;
322 savedata->command = FLASH_COMMAND_NONE;
323 if (savedata->realisticTiming) {
324 savedata->dust = FLASH_PROGRAM_CYCLES;
325 }
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 if (savedata->realisticTiming) {
434 savedata->dust = EEPROM_SETTLE_CYCLES;
435 }
436 ++savedata->writeAddress;
437 } else {
438 mLOG(GBA_SAVE, GAME_ERROR, "Writing beyond end of EEPROM: %08X", (savedata->writeAddress >> 3));
439 }
440 break;
441 case EEPROM_COMMAND_READ_PENDING:
442 // Read
443 if (writeSize > 1) {
444 savedata->readAddress <<= 1;
445 if (value & 0x1) {
446 savedata->readAddress |= 0x40;
447 }
448 } else {
449 savedata->readBitsRemaining = 68;
450 savedata->command = EEPROM_COMMAND_READ;
451 }
452 break;
453 }
454}
455
456uint16_t GBASavedataReadEEPROM(struct GBASavedata* savedata) {
457 if (savedata->command != EEPROM_COMMAND_READ) {
458 if (!savedata->realisticTiming || savedata->dust <= 0) {
459 return 1;
460 } else {
461 // Give some overhead for waitstates and the comparison
462 // This estimation can probably be improved
463 --savedata->dust;
464 return 0;
465 }
466 }
467 --savedata->readBitsRemaining;
468 if (savedata->readBitsRemaining < 64) {
469 int step = 63 - savedata->readBitsRemaining;
470 uint32_t address = (savedata->readAddress + step) >> 3;
471 if (address >= SIZE_CART_EEPROM) {
472 mLOG(GBA_SAVE, GAME_ERROR, "Reading beyond end of EEPROM: %08X", address);
473 return 0xFF;
474 }
475 uint8_t data = savedata->data[address] >> (0x7 - (step & 0x7));
476 if (!savedata->readBitsRemaining) {
477 savedata->command = EEPROM_COMMAND_NULL;
478 }
479 return data & 0x1;
480 }
481 return 0;
482}
483
484void GBASavedataClean(struct GBASavedata* savedata, uint32_t frameCount) {
485 if (!savedata->vf) {
486 return;
487 }
488 if (savedata->dirty & SAVEDATA_DIRT_NEW) {
489 savedata->dirtAge = frameCount;
490 savedata->dirty &= ~SAVEDATA_DIRT_NEW;
491 if (!(savedata->dirty & SAVEDATA_DIRT_SEEN)) {
492 savedata->dirty |= SAVEDATA_DIRT_SEEN;
493 }
494 } else if ((savedata->dirty & SAVEDATA_DIRT_SEEN) && frameCount - savedata->dirtAge > CLEANUP_THRESHOLD) {
495 if (savedata->maskWriteback) {
496 GBASavedataUnmask(savedata);
497 }
498 size_t size = GBASavedataSize(savedata);
499 savedata->dirty = 0;
500 if (savedata->data && savedata->vf->sync(savedata->vf, savedata->data, size)) {
501 mLOG(GBA_SAVE, INFO, "Savedata synced");
502 } else {
503 mLOG(GBA_SAVE, INFO, "Savedata failed to sync!");
504 }
505 }
506}
507
508void GBASavedataSerialize(const struct GBASavedata* savedata, struct GBASerializedState* state) {
509 state->savedata.type = savedata->type;
510 state->savedata.command = savedata->command;
511 GBASerializedSavedataFlags flags = 0;
512 flags = GBASerializedSavedataFlagsSetFlashState(flags, savedata->flashState);
513 flags = GBASerializedSavedataFlagsTestFillFlashBank(flags, savedata->currentBank == &savedata->data[0x10000]);
514 state->savedata.flags = flags;
515 STORE_32(savedata->readBitsRemaining, 0, &state->savedata.readBitsRemaining);
516 STORE_32(savedata->readAddress, 0, &state->savedata.readAddress);
517 STORE_32(savedata->writeAddress, 0, &state->savedata.writeAddress);
518 STORE_16(savedata->settling, 0, &state->savedata.settlingSector);
519 STORE_16(savedata->dust, 0, &state->savedata.settlingDust);
520}
521
522void GBASavedataDeserialize(struct GBASavedata* savedata, const struct GBASerializedState* state) {
523 if (savedata->type != state->savedata.type) {
524 mLOG(GBA_SAVE, DEBUG, "Switching save types");
525 GBASavedataForceType(savedata, state->savedata.type, savedata->realisticTiming);
526 }
527 savedata->command = state->savedata.command;
528 GBASerializedSavedataFlags flags = state->savedata.flags;
529 savedata->flashState = GBASerializedSavedataFlagsGetFlashState(flags);
530 LOAD_32(savedata->readBitsRemaining, 0, &state->savedata.readBitsRemaining);
531 LOAD_32(savedata->readAddress, 0, &state->savedata.readAddress);
532 LOAD_32(savedata->writeAddress, 0, &state->savedata.writeAddress);
533 LOAD_16(savedata->settling, 0, &state->savedata.settlingSector);
534 LOAD_16(savedata->dust, 0, &state->savedata.settlingDust);
535
536 if (savedata->type == SAVEDATA_FLASH1M) {
537 _flashSwitchBank(savedata, GBASerializedSavedataFlagsGetFlashBank(flags));
538 }
539}
540
541void _flashSwitchBank(struct GBASavedata* savedata, int bank) {
542 mLOG(GBA_SAVE, DEBUG, "Performing flash bank switch to bank %i", bank);
543 savedata->currentBank = &savedata->data[bank << 16];
544 if (bank > 0 && savedata->type == SAVEDATA_FLASH512) {
545 savedata->type = SAVEDATA_FLASH1M;
546 if (savedata->vf) {
547 savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M);
548 memset(&savedata->data[SIZE_CART_FLASH512], 0xFF, SIZE_CART_FLASH512);
549 }
550 }
551}
552
553void _flashErase(struct GBASavedata* savedata) {
554 mLOG(GBA_SAVE, DEBUG, "Performing flash chip erase");
555 savedata->dirty |= SAVEDATA_DIRT_NEW;
556 size_t size = SIZE_CART_FLASH512;
557 if (savedata->type == SAVEDATA_FLASH1M) {
558 size = SIZE_CART_FLASH1M;
559 }
560 memset(savedata->data, 0xFF, size);
561}
562
563void _flashEraseSector(struct GBASavedata* savedata, uint16_t sectorStart) {
564 mLOG(GBA_SAVE, DEBUG, "Performing flash sector erase at 0x%04x", sectorStart);
565 savedata->dirty |= SAVEDATA_DIRT_NEW;
566 size_t size = 0x1000;
567 if (savedata->type == SAVEDATA_FLASH1M) {
568 mLOG(GBA_SAVE, DEBUG, "Performing unknown sector-size erase at 0x%04x", sectorStart);
569 }
570 savedata->settling = sectorStart >> 12;
571 if (savedata->realisticTiming) {
572 savedata->dust = FLASH_ERASE_CYCLES;
573 }
574 memset(&savedata->currentBank[sectorStart & ~(size - 1)], 0xFF, size);
575}