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