all repos — mgba @ 3a3062ee504659fbe0e5a506668083652c4d0377

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