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