mirror of https://github.com/mgba-emu/mgba.git
Start implementing save games
This commit is contained in:
parent
dab27463a9
commit
e02059947c
|
@ -40,6 +40,8 @@ void GBAMemoryInit(struct GBAMemory* memory) {
|
||||||
memory->p->errstr = GBA_CANNOT_MMAP;
|
memory->p->errstr = GBA_CANNOT_MMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GBASavedataInit(&memory->savedata, "test.sav");
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 16; ++i) {
|
for (i = 0; i < 16; ++i) {
|
||||||
memory->waitstates16[i] = GBA_BASE_WAITSTATES[i];
|
memory->waitstates16[i] = GBA_BASE_WAITSTATES[i];
|
||||||
|
@ -65,6 +67,7 @@ void GBAMemoryInit(struct GBAMemory* memory) {
|
||||||
void GBAMemoryDeinit(struct GBAMemory* memory) {
|
void GBAMemoryDeinit(struct GBAMemory* memory) {
|
||||||
munmap(memory->wram, SIZE_WORKING_RAM);
|
munmap(memory->wram, SIZE_WORKING_RAM);
|
||||||
munmap(memory->iwram, SIZE_WORKING_IRAM);
|
munmap(memory->iwram, SIZE_WORKING_IRAM);
|
||||||
|
GBASavedataDeinit(&memory->savedata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) {
|
static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) {
|
||||||
|
@ -230,7 +233,10 @@ int8_t GBALoad8(struct ARMMemory* memory, uint32_t address) {
|
||||||
case BASE_CART2_EX:
|
case BASE_CART2_EX:
|
||||||
return ((int8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
|
return ((int8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
|
||||||
case BASE_CART_SRAM:
|
case BASE_CART_SRAM:
|
||||||
break;
|
if (gbaMemory->savedata.type == SAVEDATA_NONE) {
|
||||||
|
GBASavedataInitSRAM(&gbaMemory->savedata);
|
||||||
|
}
|
||||||
|
return gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)];
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -266,7 +272,10 @@ uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address) {
|
||||||
case BASE_CART2_EX:
|
case BASE_CART2_EX:
|
||||||
return ((uint8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
|
return ((uint8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
|
||||||
case BASE_CART_SRAM:
|
case BASE_CART_SRAM:
|
||||||
break;
|
if (gbaMemory->savedata.type == SAVEDATA_NONE) {
|
||||||
|
GBASavedataInitSRAM(&gbaMemory->savedata);
|
||||||
|
}
|
||||||
|
return gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)];
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -367,6 +376,18 @@ void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value) {
|
||||||
case BASE_CART2_EX:
|
case BASE_CART2_EX:
|
||||||
break;
|
break;
|
||||||
case BASE_CART_SRAM:
|
case BASE_CART_SRAM:
|
||||||
|
if (gbaMemory->savedata.type == SAVEDATA_NONE) {
|
||||||
|
if (address == SAVEDATA_FLASH_BASE) {
|
||||||
|
GBASavedataInitFlash(&gbaMemory->savedata);
|
||||||
|
} else {
|
||||||
|
GBASavedataInitSRAM(&gbaMemory->savedata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gbaMemory->savedata.type == SAVEDATA_FLASH512 || gbaMemory->savedata.type == SAVEDATA_FLASH1M) {
|
||||||
|
GBASavedataWriteFlash(&gbaMemory->savedata, value);
|
||||||
|
} else if (gbaMemory->savedata.type == SAVEDATA_SRAM) {
|
||||||
|
gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
|
|
||||||
|
#include "gba-savedata.h"
|
||||||
|
|
||||||
enum GBAMemoryRegion {
|
enum GBAMemoryRegion {
|
||||||
REGION_BIOS = 0x0,
|
REGION_BIOS = 0x0,
|
||||||
REGION_WORKING_RAM = 0x2,
|
REGION_WORKING_RAM = 0x2,
|
||||||
|
@ -108,6 +110,8 @@ struct GBAMemory {
|
||||||
uint32_t* rom;
|
uint32_t* rom;
|
||||||
uint16_t io[SIZE_IO >> 1];
|
uint16_t io[SIZE_IO >> 1];
|
||||||
|
|
||||||
|
struct GBASavedata savedata;
|
||||||
|
|
||||||
char waitstates32[256];
|
char waitstates32[256];
|
||||||
char waitstates16[256];
|
char waitstates16[256];
|
||||||
char waitstatesSeq32[256];
|
char waitstatesSeq32[256];
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
#include "gba-savedata.h"
|
||||||
|
|
||||||
|
#include "gba.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void GBASavedataInit(struct GBASavedata* savedata, const char* filename) {
|
||||||
|
savedata->type = SAVEDATA_NONE;
|
||||||
|
savedata->data = 0;
|
||||||
|
savedata->fd = -1;
|
||||||
|
savedata->filename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GBASavedataDeinit(struct GBASavedata* savedata) {
|
||||||
|
switch (savedata->type) {
|
||||||
|
case SAVEDATA_SRAM:
|
||||||
|
munmap(savedata->data, SIZE_CART_SRAM);
|
||||||
|
break;
|
||||||
|
case SAVEDATA_FLASH512:
|
||||||
|
munmap(savedata->data, SIZE_CART_FLASH512);
|
||||||
|
break;
|
||||||
|
case SAVEDATA_FLASH1M:
|
||||||
|
munmap(savedata->data, SIZE_CART_FLASH1M);
|
||||||
|
break;
|
||||||
|
case SAVEDATA_EEPROM:
|
||||||
|
munmap(savedata->data, SIZE_CART_EEPROM);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
close(savedata->fd);
|
||||||
|
savedata->type = SAVEDATA_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GBASavedataInitFlash(struct GBASavedata* savedata) {
|
||||||
|
savedata->type = SAVEDATA_FLASH512;
|
||||||
|
savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666);
|
||||||
|
if (savedata->fd < 0) {
|
||||||
|
GBALog(GBA_LOG_WARN, "Cannot open savedata file %s", savedata->filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// mmap enough so that we can expand the file if we need to
|
||||||
|
savedata->data = mmap(0, SIZE_CART_FLASH1M, PROT_READ | PROT_WRITE, 0, savedata->fd, 0);
|
||||||
|
|
||||||
|
off_t end = lseek(savedata->fd, 0, SEEK_END);
|
||||||
|
if (end < SIZE_CART_FLASH512) {
|
||||||
|
ftruncate(savedata->fd, SIZE_CART_SRAM);
|
||||||
|
memset(&savedata->data[end], 0xFF, SIZE_CART_SRAM - end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GBASavedataInitSRAM(struct GBASavedata* savedata) {
|
||||||
|
savedata->type = SAVEDATA_SRAM;
|
||||||
|
savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666);
|
||||||
|
off_t end;
|
||||||
|
int flags = MAP_SHARED;
|
||||||
|
if (savedata->fd < 0) {
|
||||||
|
GBALog(GBA_LOG_WARN, "Cannot open savedata file %s", savedata->filename);
|
||||||
|
end = 0;
|
||||||
|
flags |= MAP_ANON;
|
||||||
|
} else {
|
||||||
|
end = lseek(savedata->fd, 0, SEEK_END);
|
||||||
|
if (end < SIZE_CART_SRAM) {
|
||||||
|
ftruncate(savedata->fd, SIZE_CART_SRAM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
savedata->data = mmap(0, SIZE_CART_SRAM, PROT_READ | PROT_WRITE, flags, savedata->fd, 0);
|
||||||
|
if (end < SIZE_CART_SRAM) {
|
||||||
|
memset(&savedata->data[end], 0xFF, SIZE_CART_SRAM - end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GBASavedataWriteFlash(struct GBASavedata* savedata, uint8_t value) {
|
||||||
|
(void)(savedata);
|
||||||
|
(void)(value);
|
||||||
|
GBALog(GBA_LOG_STUB, "Flash memory unimplemented");
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef GBA_SAVEDATA_H
|
||||||
|
#define GBA_SAVEDATA_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum SavedataType {
|
||||||
|
SAVEDATA_NONE = 0,
|
||||||
|
SAVEDATA_SRAM,
|
||||||
|
SAVEDATA_FLASH512,
|
||||||
|
SAVEDATA_FLASH1M,
|
||||||
|
SAVEDATA_EEPROM
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SAVEDATA_FLASH_BASE = 0x0E005555
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GBASavedata {
|
||||||
|
enum SavedataType type;
|
||||||
|
uint8_t* data;
|
||||||
|
const char* filename;
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
void GBASavedataInit(struct GBASavedata* savedata, const char* filename);
|
||||||
|
void GBASavedataDeinit(struct GBASavedata* savedata);
|
||||||
|
|
||||||
|
void GBASavedataInitFlash(struct GBASavedata* savedata);
|
||||||
|
void GBASavedataInitSRAM(struct GBASavedata* savedata);
|
||||||
|
|
||||||
|
void GBASavedataWriteFlash(struct GBASavedata* savedata, uint8_t value);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue