all repos — mgba @ d957736ed95751328f6913b1954cdeac0bf7e80d

mGBA Game Boy Advance Emulator

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