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