Start implementing save games

This commit is contained in:
Jeffrey Pfau 2013-04-27 19:59:41 -07:00
parent dab27463a9
commit e02059947c
4 changed files with 140 additions and 2 deletions

View File

@ -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;

View File

@ -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];

80
src/gba/gba-savedata.c Normal file
View File

@ -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");
}

33
src/gba/gba-savedata.h Normal file
View File

@ -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