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