all repos — mgba @ 2f2e5398719f9d6a78ae84fc241945b46839b01c

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