all repos — mgba @ 28c896eb9f29599112c2cbd7a8c729071f666993

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