all repos — mgba @ 3fb46a2a8832c383429fd65c00ba3e642c750bcf

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