mirror of https://github.com/mgba-emu/mgba.git
Use VFiles for all file operations
This commit is contained in:
parent
377d8e60a7
commit
f1f55cea47
|
@ -3,6 +3,7 @@
|
||||||
#include "gba.h"
|
#include "gba.h"
|
||||||
|
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
#include "util/vfile.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -16,7 +17,7 @@ void GBASavedataInit(struct GBASavedata* savedata, const char* filename) {
|
||||||
savedata->data = 0;
|
savedata->data = 0;
|
||||||
savedata->command = EEPROM_COMMAND_NULL;
|
savedata->command = EEPROM_COMMAND_NULL;
|
||||||
savedata->flashState = FLASH_STATE_RAW;
|
savedata->flashState = FLASH_STATE_RAW;
|
||||||
savedata->fd = -1;
|
savedata->vf = 0;
|
||||||
savedata->filename = filename;
|
savedata->filename = filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,24 +30,42 @@ void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type)
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBASavedataDeinit(struct GBASavedata* savedata) {
|
void GBASavedataDeinit(struct GBASavedata* savedata) {
|
||||||
switch (savedata->type) {
|
if (savedata->vf) {
|
||||||
case SAVEDATA_SRAM:
|
switch (savedata->type) {
|
||||||
mappedMemoryFree(savedata->data, SIZE_CART_SRAM);
|
case SAVEDATA_SRAM:
|
||||||
break;
|
savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_SRAM);
|
||||||
case SAVEDATA_FLASH512:
|
break;
|
||||||
mappedMemoryFree(savedata->data, SIZE_CART_FLASH512);
|
case SAVEDATA_FLASH512:
|
||||||
break;
|
savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_FLASH512);
|
||||||
case SAVEDATA_FLASH1M:
|
break;
|
||||||
mappedMemoryFree(savedata->data, SIZE_CART_FLASH1M);
|
case SAVEDATA_FLASH1M:
|
||||||
break;
|
savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_FLASH1M);
|
||||||
case SAVEDATA_EEPROM:
|
break;
|
||||||
mappedMemoryFree(savedata->data, SIZE_CART_EEPROM);
|
case SAVEDATA_EEPROM:
|
||||||
break;
|
savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_EEPROM);
|
||||||
default:
|
break;
|
||||||
break;
|
case SAVEDATA_NONE:
|
||||||
}
|
break;
|
||||||
if (savedata->fd >= 0) {
|
}
|
||||||
close(savedata->fd);
|
savedata->vf->close(savedata->vf);
|
||||||
|
savedata->vf = 0;
|
||||||
|
} else {
|
||||||
|
switch (savedata->type) {
|
||||||
|
case SAVEDATA_SRAM:
|
||||||
|
mappedMemoryFree(savedata->data, SIZE_CART_SRAM);
|
||||||
|
break;
|
||||||
|
case SAVEDATA_FLASH512:
|
||||||
|
mappedMemoryFree(savedata->data, SIZE_CART_FLASH512);
|
||||||
|
break;
|
||||||
|
case SAVEDATA_FLASH1M:
|
||||||
|
mappedMemoryFree(savedata->data, SIZE_CART_FLASH1M);
|
||||||
|
break;
|
||||||
|
case SAVEDATA_EEPROM:
|
||||||
|
mappedMemoryFree(savedata->data, SIZE_CART_EEPROM);
|
||||||
|
break;
|
||||||
|
case SAVEDATA_NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
savedata->type = SAVEDATA_NONE;
|
savedata->type = SAVEDATA_NONE;
|
||||||
}
|
}
|
||||||
|
@ -59,18 +78,18 @@ void GBASavedataInitFlash(struct GBASavedata* savedata) {
|
||||||
GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata");
|
GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666);
|
savedata->vf = VFileOpen(savedata->filename, O_RDWR | O_CREAT);
|
||||||
off_t end;
|
off_t end;
|
||||||
if (savedata->fd < 0) {
|
if (!savedata->vf) {
|
||||||
GBALog(0, GBA_LOG_ERROR, "Cannot open savedata file %s (errno: %d)", savedata->filename, errno);
|
GBALog(0, GBA_LOG_ERROR, "Cannot open savedata file %s (errno: %d)", savedata->filename, errno);
|
||||||
end = 0;
|
end = 0;
|
||||||
savedata->data = anonymousMemoryMap(SIZE_CART_FLASH1M);
|
savedata->data = anonymousMemoryMap(SIZE_CART_FLASH1M);
|
||||||
} else {
|
} else {
|
||||||
end = lseek(savedata->fd, 0, SEEK_END);
|
end = savedata->vf->seek(savedata->vf, 0, SEEK_END);
|
||||||
if (end < SIZE_CART_FLASH512) {
|
if (end < SIZE_CART_FLASH512) {
|
||||||
ftruncate(savedata->fd, SIZE_CART_FLASH1M);
|
savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M);
|
||||||
}
|
}
|
||||||
savedata->data = fileMemoryMap(savedata->fd, SIZE_CART_FLASH1M, MEMORY_WRITE);
|
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_FLASH1M, MEMORY_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
savedata->currentBank = savedata->data;
|
savedata->currentBank = savedata->data;
|
||||||
|
@ -86,18 +105,18 @@ void GBASavedataInitEEPROM(struct GBASavedata* savedata) {
|
||||||
GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata");
|
GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666);
|
savedata->vf = VFileOpen(savedata->filename, O_RDWR | O_CREAT);
|
||||||
off_t end;
|
off_t end;
|
||||||
if (savedata->fd < 0) {
|
if (!savedata->vf) {
|
||||||
GBALog(0, GBA_LOG_ERROR, "Cannot open savedata file %s (errno: %d)", savedata->filename, errno);
|
GBALog(0, GBA_LOG_ERROR, "Cannot open savedata file %s (errno: %d)", savedata->filename, errno);
|
||||||
end = 0;
|
end = 0;
|
||||||
savedata->data = anonymousMemoryMap(SIZE_CART_EEPROM);
|
savedata->data = anonymousMemoryMap(SIZE_CART_EEPROM);
|
||||||
} else {
|
} else {
|
||||||
end = lseek(savedata->fd, 0, SEEK_END);
|
end = savedata->vf->seek(savedata->vf, 0, SEEK_END);
|
||||||
if (end < SIZE_CART_EEPROM) {
|
if (end < SIZE_CART_EEPROM) {
|
||||||
ftruncate(savedata->fd, SIZE_CART_EEPROM);
|
savedata->vf->truncate(savedata->vf, SIZE_CART_EEPROM);
|
||||||
}
|
}
|
||||||
savedata->data = fileMemoryMap(savedata->fd, SIZE_CART_EEPROM, MEMORY_WRITE);
|
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_EEPROM, MEMORY_WRITE);
|
||||||
}
|
}
|
||||||
if (end < SIZE_CART_EEPROM) {
|
if (end < SIZE_CART_EEPROM) {
|
||||||
memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM - end);
|
memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM - end);
|
||||||
|
@ -111,18 +130,18 @@ void GBASavedataInitSRAM(struct GBASavedata* savedata) {
|
||||||
GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata");
|
GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666);
|
savedata->vf = VFileOpen(savedata->filename, O_RDWR | O_CREAT);
|
||||||
off_t end;
|
off_t end;
|
||||||
if (savedata->fd < 0) {
|
if (!savedata->vf) {
|
||||||
GBALog(0, GBA_LOG_ERROR, "Cannot open savedata file %s (errno: %d)", savedata->filename, errno);
|
GBALog(0, GBA_LOG_ERROR, "Cannot open savedata file %s (errno: %d)", savedata->filename, errno);
|
||||||
end = 0;
|
end = 0;
|
||||||
savedata->data = anonymousMemoryMap(SIZE_CART_SRAM);
|
savedata->data = anonymousMemoryMap(SIZE_CART_SRAM);
|
||||||
} else {
|
} else {
|
||||||
end = lseek(savedata->fd, 0, SEEK_END);
|
end = savedata->vf->seek(savedata->vf, 0, SEEK_END);
|
||||||
if (end < SIZE_CART_SRAM) {
|
if (end < SIZE_CART_SRAM) {
|
||||||
ftruncate(savedata->fd, SIZE_CART_SRAM);
|
savedata->vf->truncate(savedata->vf, SIZE_CART_SRAM);
|
||||||
}
|
}
|
||||||
savedata->data = fileMemoryMap(savedata->fd, SIZE_CART_SRAM, MEMORY_WRITE);
|
savedata->data = savedata->vf->map(savedata->vf, SIZE_CART_SRAM, MEMORY_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end < SIZE_CART_SRAM) {
|
if (end < SIZE_CART_SRAM) {
|
||||||
|
@ -299,7 +318,7 @@ void _flashSwitchBank(struct GBASavedata* savedata, int bank) {
|
||||||
savedata->currentBank = &savedata->data[bank << 16];
|
savedata->currentBank = &savedata->data[bank << 16];
|
||||||
if (bank > 0) {
|
if (bank > 0) {
|
||||||
savedata->type = SAVEDATA_FLASH1M;
|
savedata->type = SAVEDATA_FLASH1M;
|
||||||
ftruncate(savedata->fd, SIZE_CART_FLASH1M);
|
savedata->vf->truncate(savedata->vf, SIZE_CART_FLASH1M);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
struct VFile;
|
||||||
|
|
||||||
enum SavedataType {
|
enum SavedataType {
|
||||||
SAVEDATA_NONE = 0,
|
SAVEDATA_NONE = 0,
|
||||||
SAVEDATA_SRAM,
|
SAVEDATA_SRAM,
|
||||||
|
@ -55,7 +57,7 @@ struct GBASavedata {
|
||||||
uint8_t* data;
|
uint8_t* data;
|
||||||
const char* filename;
|
const char* filename;
|
||||||
enum SavedataCommand command;
|
enum SavedataCommand command;
|
||||||
int fd;
|
struct VFile* vf;
|
||||||
|
|
||||||
int readBitsRemaining;
|
int readBitsRemaining;
|
||||||
int readAddress;
|
int readAddress;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "gba-thread.h"
|
#include "gba-thread.h"
|
||||||
|
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
#include "util/vfile.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
@ -62,43 +63,47 @@ void GBADeserialize(struct GBA* gba, struct GBASerializedState* state) {
|
||||||
GBAAudioDeserialize(&gba->audio, state);
|
GBAAudioDeserialize(&gba->audio, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _getStateFd(struct GBA* gba, int slot) {
|
static struct VFile* _getStateVf(struct GBA* gba, int slot) {
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
path[PATH_MAX - 1] = '\0';
|
path[PATH_MAX - 1] = '\0';
|
||||||
snprintf(path, PATH_MAX - 1, "%s.ss%d", gba->activeFile, slot);
|
snprintf(path, PATH_MAX - 1, "%s.ss%d", gba->activeFile, slot);
|
||||||
int fd = open(path, O_CREAT | O_RDWR, 0777);
|
struct VFile* vf = VFileOpen(path, O_CREAT | O_RDWR);
|
||||||
if (fd >= 0) {
|
if (vf) {
|
||||||
ftruncate(fd, sizeof(struct GBASerializedState));
|
vf->truncate(vf, sizeof(struct GBASerializedState));
|
||||||
}
|
}
|
||||||
return fd;
|
return vf;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GBASaveState(struct GBA* gba, int slot) {
|
bool GBASaveState(struct GBA* gba, int slot) {
|
||||||
int fd = _getStateFd(gba, slot);
|
struct VFile* vf = _getStateVf(gba, slot);
|
||||||
if (fd < 0) {
|
if (!vf) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct GBASerializedState* state = GBAMapState(fd);
|
struct GBASerializedState* state = GBAMapState(vf);
|
||||||
GBASerialize(gba, state);
|
GBASerialize(gba, state);
|
||||||
GBADeallocateState(state);
|
GBAUnmapState(vf, state);
|
||||||
close(fd);
|
vf->close(vf);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GBALoadState(struct GBA* gba, int slot) {
|
bool GBALoadState(struct GBA* gba, int slot) {
|
||||||
int fd = _getStateFd(gba, slot);
|
struct VFile* vf = _getStateVf(gba, slot);
|
||||||
if (fd < 0) {
|
if (!vf) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct GBASerializedState* state = GBAMapState(fd);
|
struct GBASerializedState* state = GBAMapState(vf);
|
||||||
GBADeserialize(gba, state);
|
GBADeserialize(gba, state);
|
||||||
GBADeallocateState(state);
|
GBAUnmapState(vf, state);
|
||||||
close(fd);
|
vf->close(vf);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GBASerializedState* GBAMapState(int fd) {
|
struct GBASerializedState* GBAMapState(struct VFile* vf) {
|
||||||
return fileMemoryMap(fd, sizeof(struct GBASerializedState), MEMORY_WRITE);
|
return vf->map(vf, sizeof(struct GBASerializedState), MEMORY_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GBAUnmapState(struct VFile* vf, struct GBASerializedState* state) {
|
||||||
|
vf->unmap(vf, state, sizeof(struct GBASerializedState));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GBASerializedState* GBAAllocateState(void) {
|
struct GBASerializedState* GBAAllocateState(void) {
|
||||||
|
|
|
@ -225,13 +225,17 @@ struct GBASerializedState {
|
||||||
uint8_t wram[SIZE_WORKING_RAM];
|
uint8_t wram[SIZE_WORKING_RAM];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VFile;
|
||||||
|
|
||||||
void GBASerialize(struct GBA* gba, struct GBASerializedState* state);
|
void GBASerialize(struct GBA* gba, struct GBASerializedState* state);
|
||||||
void GBADeserialize(struct GBA* gba, struct GBASerializedState* state);
|
void GBADeserialize(struct GBA* gba, struct GBASerializedState* state);
|
||||||
|
|
||||||
bool GBASaveState(struct GBA* gba, int slot);
|
bool GBASaveState(struct GBA* gba, int slot);
|
||||||
bool GBALoadState(struct GBA* gba, int slot);
|
bool GBALoadState(struct GBA* gba, int slot);
|
||||||
|
|
||||||
struct GBASerializedState* GBAMapState(int fd);
|
struct GBASerializedState* GBAMapState(struct VFile* vf);
|
||||||
|
void GBAUnmapState(struct VFile* vf, struct GBASerializedState* state);
|
||||||
|
|
||||||
struct GBASerializedState* GBAAllocateState(void);
|
struct GBASerializedState* GBAAllocateState(void);
|
||||||
void GBADeallocateState(struct GBASerializedState* state);
|
void GBADeallocateState(struct GBASerializedState* state);
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
||||||
GBAVideoAssociateRenderer(&gba.video, threadContext->renderer);
|
GBAVideoAssociateRenderer(&gba.video, threadContext->renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (threadContext->fd >= 0) {
|
if (threadContext->fd) {
|
||||||
if (threadContext->fname) {
|
if (threadContext->fname) {
|
||||||
char* dotPoint = strrchr(threadContext->fname, '.');
|
char* dotPoint = strrchr(threadContext->fname, '.');
|
||||||
if (dotPoint > strrchr(threadContext->fname, '/') && dotPoint[1] && dotPoint[2] && dotPoint[3]) {
|
if (dotPoint > strrchr(threadContext->fname, '/') && dotPoint[1] && dotPoint[2] && dotPoint[3]) {
|
||||||
|
@ -111,11 +111,11 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
||||||
}
|
}
|
||||||
gba.savefile = savedata;
|
gba.savefile = savedata;
|
||||||
GBALoadROM(&gba, threadContext->fd, threadContext->fname);
|
GBALoadROM(&gba, threadContext->fd, threadContext->fname);
|
||||||
if (threadContext->biosFd >= 0) {
|
if (threadContext->biosFd) {
|
||||||
GBALoadBIOS(&gba, threadContext->biosFd);
|
GBALoadBIOS(&gba, threadContext->biosFd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (threadContext->patchFd >= 0 && loadPatch(VFileFromFD(threadContext->patchFd), &patch)) {
|
if (threadContext->patchFd && loadPatch(threadContext->patchFd, &patch)) {
|
||||||
GBAApplyPatch(&gba, &patch);
|
GBAApplyPatch(&gba, &patch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,10 +191,10 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAMapOptionsToContext(struct StartupOptions* opts, struct GBAThread* threadContext) {
|
void GBAMapOptionsToContext(struct StartupOptions* opts, struct GBAThread* threadContext) {
|
||||||
threadContext->fd = opts->fd;
|
threadContext->fd = VFileFromFD(opts->fd);
|
||||||
threadContext->fname = opts->fname;
|
threadContext->fname = opts->fname;
|
||||||
threadContext->biosFd = opts->biosFd;
|
threadContext->biosFd = VFileFromFD(opts->biosFd);
|
||||||
threadContext->patchFd = opts->patchFd;
|
threadContext->patchFd = VFileFromFD(opts->patchFd);
|
||||||
threadContext->frameskip = opts->frameskip;
|
threadContext->frameskip = opts->frameskip;
|
||||||
threadContext->logLevel = opts->logLevel;
|
threadContext->logLevel = opts->logLevel;
|
||||||
threadContext->rewindBufferCapacity = opts->rewindBufferCapacity;
|
threadContext->rewindBufferCapacity = opts->rewindBufferCapacity;
|
||||||
|
|
|
@ -47,9 +47,9 @@ struct GBAThread {
|
||||||
struct GBAVideoRenderer* renderer;
|
struct GBAVideoRenderer* renderer;
|
||||||
struct GBASIODriverSet sioDrivers;
|
struct GBASIODriverSet sioDrivers;
|
||||||
struct ARMDebugger* debugger;
|
struct ARMDebugger* debugger;
|
||||||
int fd;
|
struct VFile* fd;
|
||||||
int biosFd;
|
struct VFile* biosFd;
|
||||||
int patchFd;
|
struct VFile* patchFd;
|
||||||
const char* fname;
|
const char* fname;
|
||||||
int activeKeys;
|
int activeKeys;
|
||||||
int frameskip;
|
int frameskip;
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
|
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "util/patch.h"
|
#include "util/patch.h"
|
||||||
|
#include "util/vfile.h"
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000;
|
const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000;
|
||||||
const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
|
const uint32_t GBA_COMPONENT_MAGIC = 0x1000000;
|
||||||
|
@ -134,6 +133,9 @@ static void GBAInit(struct ARMCore* cpu, struct ARMComponent* component) {
|
||||||
gba->rotationSource = 0;
|
gba->rotationSource = 0;
|
||||||
gba->rumble = 0;
|
gba->rumble = 0;
|
||||||
|
|
||||||
|
gba->romVf = 0;
|
||||||
|
gba->biosVf = 0;
|
||||||
|
|
||||||
gba->logLevel = GBA_LOG_INFO | GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL;
|
gba->logLevel = GBA_LOG_INFO | GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL;
|
||||||
|
|
||||||
gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
|
gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
|
||||||
|
@ -143,7 +145,15 @@ void GBADestroy(struct GBA* gba) {
|
||||||
if (gba->pristineRom == gba->memory.rom) {
|
if (gba->pristineRom == gba->memory.rom) {
|
||||||
gba->memory.rom = 0;
|
gba->memory.rom = 0;
|
||||||
}
|
}
|
||||||
mappedMemoryFree(gba->pristineRom, gba->pristineRomSize);
|
|
||||||
|
if (gba->romVf) {
|
||||||
|
gba->romVf->unmap(gba->romVf, gba->pristineRom, gba->pristineRomSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gba->biosVf) {
|
||||||
|
gba->biosVf->unmap(gba->biosVf, gba->memory.bios, SIZE_BIOS);
|
||||||
|
}
|
||||||
|
|
||||||
GBAMemoryDeinit(gba);
|
GBAMemoryDeinit(gba);
|
||||||
GBAVideoDeinit(&gba->video);
|
GBAVideoDeinit(&gba->video);
|
||||||
GBAAudioDeinit(&gba->audio);
|
GBAAudioDeinit(&gba->audio);
|
||||||
|
@ -363,13 +373,13 @@ void GBADetachDebugger(struct GBA* gba) {
|
||||||
gba->debugger = 0;
|
gba->debugger = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBALoadROM(struct GBA* gba, int fd, const char* fname) {
|
void GBALoadROM(struct GBA* gba, struct VFile* vf, const char* fname) {
|
||||||
struct stat info;
|
gba->romVf = vf;
|
||||||
gba->pristineRom = fileMemoryMap(fd, SIZE_CART0, MEMORY_READ);
|
gba->pristineRomSize = vf->seek(vf, 0, SEEK_END);
|
||||||
|
vf->seek(vf, 0, SEEK_SET);
|
||||||
|
gba->pristineRom = vf->map(vf, SIZE_CART0, MEMORY_READ);
|
||||||
gba->memory.rom = gba->pristineRom;
|
gba->memory.rom = gba->pristineRom;
|
||||||
gba->activeFile = fname;
|
gba->activeFile = fname;
|
||||||
fstat(fd, &info);
|
|
||||||
gba->pristineRomSize = info.st_size;
|
|
||||||
gba->memory.romSize = gba->pristineRomSize;
|
gba->memory.romSize = gba->pristineRomSize;
|
||||||
if (gba->savefile) {
|
if (gba->savefile) {
|
||||||
GBASavedataInit(&gba->memory.savedata, gba->savefile);
|
GBASavedataInit(&gba->memory.savedata, gba->savefile);
|
||||||
|
@ -379,8 +389,9 @@ void GBALoadROM(struct GBA* gba, int fd, const char* fname) {
|
||||||
// TODO: error check
|
// TODO: error check
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBALoadBIOS(struct GBA* gba, int fd) {
|
void GBALoadBIOS(struct GBA* gba, struct VFile* vf) {
|
||||||
gba->memory.bios = fileMemoryMap(fd, SIZE_BIOS, MEMORY_READ);
|
gba->biosVf = vf;
|
||||||
|
gba->memory.bios = vf->map(vf, SIZE_BIOS, MEMORY_READ);
|
||||||
gba->memory.fullBios = 1;
|
gba->memory.fullBios = 1;
|
||||||
uint32_t checksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
|
uint32_t checksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
|
||||||
GBALog(gba, GBA_LOG_DEBUG, "BIOS Checksum: 0x%X", checksum);
|
GBALog(gba, GBA_LOG_DEBUG, "BIOS Checksum: 0x%X", checksum);
|
||||||
|
|
|
@ -60,9 +60,10 @@ enum GBAKey {
|
||||||
GBA_KEY_NONE = -1
|
GBA_KEY_NONE = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GBARotationSource;
|
|
||||||
struct GBA;
|
struct GBA;
|
||||||
|
struct GBARotationSource;
|
||||||
struct Patch;
|
struct Patch;
|
||||||
|
struct VFile;
|
||||||
|
|
||||||
typedef void (*GBALogHandler)(struct GBA*, enum GBALogLevel, const char* format, va_list args);
|
typedef void (*GBALogHandler)(struct GBA*, enum GBALogLevel, const char* format, va_list args);
|
||||||
|
|
||||||
|
@ -99,6 +100,8 @@ struct GBA {
|
||||||
struct GBARumble* rumble;
|
struct GBARumble* rumble;
|
||||||
void* pristineRom;
|
void* pristineRom;
|
||||||
size_t pristineRomSize;
|
size_t pristineRomSize;
|
||||||
|
struct VFile* romVf;
|
||||||
|
struct VFile* biosVf;
|
||||||
|
|
||||||
const char* activeFile;
|
const char* activeFile;
|
||||||
const char* savefile;
|
const char* savefile;
|
||||||
|
@ -141,8 +144,8 @@ void GBAHalt(struct GBA* gba);
|
||||||
void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger);
|
void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger);
|
||||||
void GBADetachDebugger(struct GBA* gba);
|
void GBADetachDebugger(struct GBA* gba);
|
||||||
|
|
||||||
void GBALoadROM(struct GBA* gba, int fd, const char* fname);
|
void GBALoadROM(struct GBA* gba, struct VFile* vf, const char* fname);
|
||||||
void GBALoadBIOS(struct GBA* gba, int fd);
|
void GBALoadBIOS(struct GBA* gba, struct VFile* vf);
|
||||||
void GBAApplyPatch(struct GBA* gba, struct Patch* patch);
|
void GBAApplyPatch(struct GBA* gba, struct Patch* patch);
|
||||||
|
|
||||||
__attribute__((format (printf, 3, 4)))
|
__attribute__((format (printf, 3, 4)))
|
||||||
|
|
|
@ -5,13 +5,6 @@
|
||||||
void* anonymousMemoryMap(size_t size) {
|
void* anonymousMemoryMap(size_t size) {
|
||||||
return mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
return mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||||
}
|
}
|
||||||
void* fileMemoryMap(int fd, size_t size, int flags) {
|
|
||||||
int mmapFlags = MAP_PRIVATE;
|
|
||||||
if (flags & MEMORY_WRITE) {
|
|
||||||
mmapFlags = MAP_SHARED;
|
|
||||||
}
|
|
||||||
return mmap(0, size, PROT_READ | PROT_WRITE, mmapFlags, fd, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mappedMemoryFree(void* memory, size_t size) {
|
void mappedMemoryFree(void* memory, size_t size) {
|
||||||
munmap(memory, size);
|
munmap(memory, size);
|
||||||
|
|
|
@ -8,23 +8,6 @@ void* anonymousMemoryMap(size_t size) {
|
||||||
return MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, size);
|
return MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* fileMemoryMap(int fd, size_t size, int flags) {
|
|
||||||
int createFlags = PAGE_READONLY;
|
|
||||||
int mapFiles = FILE_MAP_READ;
|
|
||||||
if (flags & MEMORY_WRITE) {
|
|
||||||
createFlags = PAGE_READWRITE;
|
|
||||||
mapFiles = FILE_MAP_WRITE;
|
|
||||||
}
|
|
||||||
size_t location = lseek(fd, 0, SEEK_CUR);
|
|
||||||
size_t fileSize = lseek(fd, 0, SEEK_END);
|
|
||||||
lseek(fd, location, SEEK_SET);
|
|
||||||
if (size > fileSize) {
|
|
||||||
size = fileSize;
|
|
||||||
}
|
|
||||||
HANDLE hMap = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, createFlags, 0, size & 0xFFFFFFFF, 0);
|
|
||||||
return MapViewOfFile(hMap, mapFiles, 0, 0, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mappedMemoryFree(void* memory, size_t size) {
|
void mappedMemoryFree(void* memory, size_t size) {
|
||||||
// TODO fill in
|
// TODO fill in
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#define MEMORY_WRITE 2
|
#define MEMORY_WRITE 2
|
||||||
|
|
||||||
void* anonymousMemoryMap(size_t size);
|
void* anonymousMemoryMap(size_t size);
|
||||||
void* fileMemoryMap(int fd, size_t size, int flags);
|
|
||||||
void mappedMemoryFree(void* memory, size_t size);
|
void mappedMemoryFree(void* memory, size_t size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,9 +2,19 @@
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#else
|
||||||
|
#include <io.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
struct VFileFD {
|
struct VFileFD {
|
||||||
struct VFile d;
|
struct VFile d;
|
||||||
int fd;
|
int fd;
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE hMap;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool _vfdClose(struct VFile* vf);
|
static bool _vfdClose(struct VFile* vf);
|
||||||
|
@ -12,9 +22,12 @@ static size_t _vfdSeek(struct VFile* vf, off_t offset, int whence);
|
||||||
static size_t _vfdRead(struct VFile* vf, void* buffer, size_t size);
|
static size_t _vfdRead(struct VFile* vf, void* buffer, size_t size);
|
||||||
static size_t _vfdReadline(struct VFile* vf, char* buffer, size_t size);
|
static size_t _vfdReadline(struct VFile* vf, char* buffer, size_t size);
|
||||||
static size_t _vfdWrite(struct VFile* vf, void* buffer, size_t size);
|
static size_t _vfdWrite(struct VFile* vf, void* buffer, size_t size);
|
||||||
|
static void* _vfdMap(struct VFile* vf, size_t size, int flags);
|
||||||
|
static void _vfdUnmap(struct VFile* vf, void* memory, size_t size);
|
||||||
|
static void _vfdTruncate(struct VFile* vf, size_t size);
|
||||||
|
|
||||||
struct VFile* VFileOpen(const char* path, int flags) {
|
struct VFile* VFileOpen(const char* path, int flags) {
|
||||||
int fd = open(path, flags);
|
int fd = open(path, flags, 0666);
|
||||||
return VFileFromFD(fd);
|
return VFileFromFD(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +47,9 @@ struct VFile* VFileFromFD(int fd) {
|
||||||
vfd->d.read = _vfdRead;
|
vfd->d.read = _vfdRead;
|
||||||
vfd->d.readline = _vfdReadline;
|
vfd->d.readline = _vfdReadline;
|
||||||
vfd->d.write = _vfdWrite;
|
vfd->d.write = _vfdWrite;
|
||||||
|
vfd->d.map = _vfdMap;
|
||||||
|
vfd->d.unmap = _vfdUnmap;
|
||||||
|
vfd->d.truncate = _vfdTruncate;
|
||||||
|
|
||||||
return &vfd->d;
|
return &vfd->d;
|
||||||
}
|
}
|
||||||
|
@ -74,3 +90,50 @@ size_t _vfdWrite(struct VFile* vf, void* buffer, size_t size) {
|
||||||
struct VFileFD* vfd = (struct VFileFD*) vf;
|
struct VFileFD* vfd = (struct VFileFD*) vf;
|
||||||
return write(vfd->fd, buffer, size);
|
return write(vfd->fd, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
static void* _vfdMap(struct VFile* vf, size_t size, int flags) {
|
||||||
|
struct VFileFD* vfd = (struct VFileFD*) vf;
|
||||||
|
int mmapFlags = MAP_PRIVATE;
|
||||||
|
if (flags & MEMORY_WRITE) {
|
||||||
|
mmapFlags = MAP_SHARED;
|
||||||
|
}
|
||||||
|
return mmap(0, size, PROT_READ | PROT_WRITE, mmapFlags, vfd->fd, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _vfdUnmap(struct VFile* vf, void* memory, size_t size) {
|
||||||
|
UNUSED(vf);
|
||||||
|
munmap(memory, size);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void* _vfdMap(struct VFile* vf, size_t size, int flags) {
|
||||||
|
struct VFileFD* vfd = (struct VFileFD*) vf;
|
||||||
|
int createFlags = PAGE_READONLY;
|
||||||
|
int mapFiles = FILE_MAP_READ;
|
||||||
|
if (flags & MEMORY_WRITE) {
|
||||||
|
createFlags = PAGE_READWRITE;
|
||||||
|
mapFiles = FILE_MAP_WRITE;
|
||||||
|
}
|
||||||
|
size_t location = lseek(vfd->fd, 0, SEEK_CUR);
|
||||||
|
size_t fileSize = lseek(vfd->fd, 0, SEEK_END);
|
||||||
|
lseek(vfd->fd, location, SEEK_SET);
|
||||||
|
if (size > fileSize) {
|
||||||
|
size = fileSize;
|
||||||
|
}
|
||||||
|
vfd->hMap = CreateFileMapping((HANDLE) _get_osfhandle(vfd->fd), 0, createFlags, 0, size & 0xFFFFFFFF, 0);
|
||||||
|
return MapViewOfFile(hMap, mapFiles, 0, 0, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _vfdUnmap(struct VFile* vf, void* memory, size_t size) {
|
||||||
|
UNUSED(size);
|
||||||
|
struct VFileFD* vfd = (struct VFileFD*) vf;
|
||||||
|
UnmapViewOfFile(memory);
|
||||||
|
CloseHandle(vfd->hMap);
|
||||||
|
vfd->hMap = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void _vfdTruncate(struct VFile* vf, size_t size) {
|
||||||
|
struct VFileFD* vfd = (struct VFileFD*) vf;
|
||||||
|
ftruncate(vfd->fd, size);
|
||||||
|
}
|
||||||
|
|
|
@ -3,12 +3,17 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
struct VFile {
|
struct VFile {
|
||||||
bool (*close)(struct VFile* vf);
|
bool (*close)(struct VFile* vf);
|
||||||
size_t (*seek)(struct VFile* vf, off_t offset, int whence);
|
size_t (*seek)(struct VFile* vf, off_t offset, int whence);
|
||||||
size_t (*read)(struct VFile* vf, void* buffer, size_t size);
|
size_t (*read)(struct VFile* vf, void* buffer, size_t size);
|
||||||
size_t (*readline)(struct VFile* vf, char* buffer, size_t size);
|
size_t (*readline)(struct VFile* vf, char* buffer, size_t size);
|
||||||
size_t (*write)(struct VFile* vf, void* buffer, size_t size);
|
size_t (*write)(struct VFile* vf, void* buffer, size_t size);
|
||||||
|
void* (*map)(struct VFile* vf, size_t size, int flags);
|
||||||
|
void (*unmap)(struct VFile* vf, void* memory, size_t size);
|
||||||
|
void (*truncate)(struct VFile* vf, size_t size);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VFile* VFileOpen(const char* path, int flags);
|
struct VFile* VFileOpen(const char* path, int flags);
|
||||||
|
|
Loading…
Reference in New Issue