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