all repos — mgba @ 78db3e1a7491be7ead2e583c4258aad2b97d0295

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