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