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;
|
||||
}
|
||||
|
||||
GBASavedataInit(&memory->savedata, "test.sav");
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
memory->waitstates16[i] = GBA_BASE_WAITSTATES[i];
|
||||
|
@ -65,6 +67,7 @@ void GBAMemoryInit(struct GBAMemory* memory) {
|
|||
void GBAMemoryDeinit(struct GBAMemory* memory) {
|
||||
munmap(memory->wram, SIZE_WORKING_RAM);
|
||||
munmap(memory->iwram, SIZE_WORKING_IRAM);
|
||||
GBASavedataDeinit(&memory->savedata);
|
||||
}
|
||||
|
||||
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:
|
||||
return ((int8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
|
||||
case BASE_CART_SRAM:
|
||||
break;
|
||||
if (gbaMemory->savedata.type == SAVEDATA_NONE) {
|
||||
GBASavedataInitSRAM(&gbaMemory->savedata);
|
||||
}
|
||||
return gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -266,7 +272,10 @@ uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address) {
|
|||
case BASE_CART2_EX:
|
||||
return ((uint8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
|
||||
case BASE_CART_SRAM:
|
||||
break;
|
||||
if (gbaMemory->savedata.type == SAVEDATA_NONE) {
|
||||
GBASavedataInitSRAM(&gbaMemory->savedata);
|
||||
}
|
||||
return gbaMemory->savedata.data[address & (SIZE_CART_SRAM - 1)];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -367,6 +376,18 @@ void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value) {
|
|||
case BASE_CART2_EX:
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "arm.h"
|
||||
|
||||
#include "gba-savedata.h"
|
||||
|
||||
enum GBAMemoryRegion {
|
||||
REGION_BIOS = 0x0,
|
||||
REGION_WORKING_RAM = 0x2,
|
||||
|
@ -108,6 +110,8 @@ struct GBAMemory {
|
|||
uint32_t* rom;
|
||||
uint16_t io[SIZE_IO >> 1];
|
||||
|
||||
struct GBASavedata savedata;
|
||||
|
||||
char waitstates32[256];
|
||||
char waitstates16[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