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 "util/memory.h"
|
||||
#include "util/vfile.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -16,7 +17,7 @@ void GBASavedataInit(struct GBASavedata* savedata, const char* filename) {
|
|||
savedata->data = 0;
|
||||
savedata->command = EEPROM_COMMAND_NULL;
|
||||
savedata->flashState = FLASH_STATE_RAW;
|
||||
savedata->fd = -1;
|
||||
savedata->vf = 0;
|
||||
savedata->filename = filename;
|
||||
}
|
||||
|
||||
|
@ -29,24 +30,42 @@ void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type)
|
|||
}
|
||||
|
||||
void GBASavedataDeinit(struct GBASavedata* savedata) {
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (savedata->fd >= 0) {
|
||||
close(savedata->fd);
|
||||
if (savedata->vf) {
|
||||
switch (savedata->type) {
|
||||
case SAVEDATA_SRAM:
|
||||
savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_SRAM);
|
||||
break;
|
||||
case SAVEDATA_FLASH512:
|
||||
savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_FLASH512);
|
||||
break;
|
||||
case SAVEDATA_FLASH1M:
|
||||
savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_FLASH1M);
|
||||
break;
|
||||
case SAVEDATA_EEPROM:
|
||||
savedata->vf->unmap(savedata->vf, savedata->data, SIZE_CART_EEPROM);
|
||||
break;
|
||||
case SAVEDATA_NONE:
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -59,18 +78,18 @@ void GBASavedataInitFlash(struct GBASavedata* savedata) {
|
|||
GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata");
|
||||
return;
|
||||
}
|
||||
savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666);
|
||||
savedata->vf = VFileOpen(savedata->filename, O_RDWR | O_CREAT);
|
||||
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);
|
||||
end = 0;
|
||||
savedata->data = anonymousMemoryMap(SIZE_CART_FLASH1M);
|
||||
} else {
|
||||
end = lseek(savedata->fd, 0, SEEK_END);
|
||||
end = savedata->vf->seek(savedata->vf, 0, SEEK_END);
|
||||
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;
|
||||
|
@ -86,18 +105,18 @@ void GBASavedataInitEEPROM(struct GBASavedata* savedata) {
|
|||
GBALog(0, GBA_LOG_WARN, "Can't re-initialize savedata");
|
||||
return;
|
||||
}
|
||||
savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666);
|
||||
savedata->vf = VFileOpen(savedata->filename, O_RDWR | O_CREAT);
|
||||
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);
|
||||
end = 0;
|
||||
savedata->data = anonymousMemoryMap(SIZE_CART_EEPROM);
|
||||
} else {
|
||||
end = lseek(savedata->fd, 0, SEEK_END);
|
||||
end = savedata->vf->seek(savedata->vf, 0, SEEK_END);
|
||||
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) {
|
||||
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");
|
||||
return;
|
||||
}
|
||||
savedata->fd = open(savedata->filename, O_RDWR | O_CREAT, 0666);
|
||||
savedata->vf = VFileOpen(savedata->filename, O_RDWR | O_CREAT);
|
||||
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);
|
||||
end = 0;
|
||||
savedata->data = anonymousMemoryMap(SIZE_CART_SRAM);
|
||||
} else {
|
||||
end = lseek(savedata->fd, 0, SEEK_END);
|
||||
end = savedata->vf->seek(savedata->vf, 0, SEEK_END);
|
||||
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) {
|
||||
|
@ -299,7 +318,7 @@ void _flashSwitchBank(struct GBASavedata* savedata, int bank) {
|
|||
savedata->currentBank = &savedata->data[bank << 16];
|
||||
if (bank > 0) {
|
||||
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"
|
||||
|
||||
struct VFile;
|
||||
|
||||
enum SavedataType {
|
||||
SAVEDATA_NONE = 0,
|
||||
SAVEDATA_SRAM,
|
||||
|
@ -55,7 +57,7 @@ struct GBASavedata {
|
|||
uint8_t* data;
|
||||
const char* filename;
|
||||
enum SavedataCommand command;
|
||||
int fd;
|
||||
struct VFile* vf;
|
||||
|
||||
int readBitsRemaining;
|
||||
int readAddress;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "gba-thread.h"
|
||||
|
||||
#include "util/memory.h"
|
||||
#include "util/vfile.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
|
@ -62,43 +63,47 @@ void GBADeserialize(struct GBA* gba, struct GBASerializedState* 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];
|
||||
path[PATH_MAX - 1] = '\0';
|
||||
snprintf(path, PATH_MAX - 1, "%s.ss%d", gba->activeFile, slot);
|
||||
int fd = open(path, O_CREAT | O_RDWR, 0777);
|
||||
if (fd >= 0) {
|
||||
ftruncate(fd, sizeof(struct GBASerializedState));
|
||||
struct VFile* vf = VFileOpen(path, O_CREAT | O_RDWR);
|
||||
if (vf) {
|
||||
vf->truncate(vf, sizeof(struct GBASerializedState));
|
||||
}
|
||||
return fd;
|
||||
return vf;
|
||||
}
|
||||
|
||||
bool GBASaveState(struct GBA* gba, int slot) {
|
||||
int fd = _getStateFd(gba, slot);
|
||||
if (fd < 0) {
|
||||
struct VFile* vf = _getStateVf(gba, slot);
|
||||
if (!vf) {
|
||||
return false;
|
||||
}
|
||||
struct GBASerializedState* state = GBAMapState(fd);
|
||||
struct GBASerializedState* state = GBAMapState(vf);
|
||||
GBASerialize(gba, state);
|
||||
GBADeallocateState(state);
|
||||
close(fd);
|
||||
GBAUnmapState(vf, state);
|
||||
vf->close(vf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GBALoadState(struct GBA* gba, int slot) {
|
||||
int fd = _getStateFd(gba, slot);
|
||||
if (fd < 0) {
|
||||
struct VFile* vf = _getStateVf(gba, slot);
|
||||
if (!vf) {
|
||||
return false;
|
||||
}
|
||||
struct GBASerializedState* state = GBAMapState(fd);
|
||||
struct GBASerializedState* state = GBAMapState(vf);
|
||||
GBADeserialize(gba, state);
|
||||
GBADeallocateState(state);
|
||||
close(fd);
|
||||
GBAUnmapState(vf, state);
|
||||
vf->close(vf);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct GBASerializedState* GBAMapState(int fd) {
|
||||
return fileMemoryMap(fd, sizeof(struct GBASerializedState), MEMORY_WRITE);
|
||||
struct GBASerializedState* GBAMapState(struct VFile* vf) {
|
||||
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) {
|
||||
|
|
|
@ -225,13 +225,17 @@ struct GBASerializedState {
|
|||
uint8_t wram[SIZE_WORKING_RAM];
|
||||
};
|
||||
|
||||
struct VFile;
|
||||
|
||||
void GBASerialize(struct GBA* gba, struct GBASerializedState* state);
|
||||
void GBADeserialize(struct GBA* gba, struct GBASerializedState* state);
|
||||
|
||||
bool GBASaveState(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);
|
||||
void GBADeallocateState(struct GBASerializedState* state);
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
|||
GBAVideoAssociateRenderer(&gba.video, threadContext->renderer);
|
||||
}
|
||||
|
||||
if (threadContext->fd >= 0) {
|
||||
if (threadContext->fd) {
|
||||
if (threadContext->fname) {
|
||||
char* dotPoint = strrchr(threadContext->fname, '.');
|
||||
if (dotPoint > strrchr(threadContext->fname, '/') && dotPoint[1] && dotPoint[2] && dotPoint[3]) {
|
||||
|
@ -111,11 +111,11 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
|||
}
|
||||
gba.savefile = savedata;
|
||||
GBALoadROM(&gba, threadContext->fd, threadContext->fname);
|
||||
if (threadContext->biosFd >= 0) {
|
||||
if (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);
|
||||
}
|
||||
}
|
||||
|
@ -191,10 +191,10 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
|||
}
|
||||
|
||||
void GBAMapOptionsToContext(struct StartupOptions* opts, struct GBAThread* threadContext) {
|
||||
threadContext->fd = opts->fd;
|
||||
threadContext->fd = VFileFromFD(opts->fd);
|
||||
threadContext->fname = opts->fname;
|
||||
threadContext->biosFd = opts->biosFd;
|
||||
threadContext->patchFd = opts->patchFd;
|
||||
threadContext->biosFd = VFileFromFD(opts->biosFd);
|
||||
threadContext->patchFd = VFileFromFD(opts->patchFd);
|
||||
threadContext->frameskip = opts->frameskip;
|
||||
threadContext->logLevel = opts->logLevel;
|
||||
threadContext->rewindBufferCapacity = opts->rewindBufferCapacity;
|
||||
|
|
|
@ -47,9 +47,9 @@ struct GBAThread {
|
|||
struct GBAVideoRenderer* renderer;
|
||||
struct GBASIODriverSet sioDrivers;
|
||||
struct ARMDebugger* debugger;
|
||||
int fd;
|
||||
int biosFd;
|
||||
int patchFd;
|
||||
struct VFile* fd;
|
||||
struct VFile* biosFd;
|
||||
struct VFile* patchFd;
|
||||
const char* fname;
|
||||
int activeKeys;
|
||||
int frameskip;
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
|
||||
#include "util/memory.h"
|
||||
#include "util/patch.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include "util/vfile.h"
|
||||
|
||||
const uint32_t GBA_ARM7TDMI_FREQUENCY = 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->rumble = 0;
|
||||
|
||||
gba->romVf = 0;
|
||||
gba->biosVf = 0;
|
||||
|
||||
gba->logLevel = GBA_LOG_INFO | GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL;
|
||||
|
||||
gba->biosChecksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
|
||||
|
@ -143,7 +145,15 @@ void GBADestroy(struct GBA* gba) {
|
|||
if (gba->pristineRom == gba->memory.rom) {
|
||||
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);
|
||||
GBAVideoDeinit(&gba->video);
|
||||
GBAAudioDeinit(&gba->audio);
|
||||
|
@ -363,13 +373,13 @@ void GBADetachDebugger(struct GBA* gba) {
|
|||
gba->debugger = 0;
|
||||
}
|
||||
|
||||
void GBALoadROM(struct GBA* gba, int fd, const char* fname) {
|
||||
struct stat info;
|
||||
gba->pristineRom = fileMemoryMap(fd, SIZE_CART0, MEMORY_READ);
|
||||
void GBALoadROM(struct GBA* gba, struct VFile* vf, const char* fname) {
|
||||
gba->romVf = vf;
|
||||
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->activeFile = fname;
|
||||
fstat(fd, &info);
|
||||
gba->pristineRomSize = info.st_size;
|
||||
gba->memory.romSize = gba->pristineRomSize;
|
||||
if (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
|
||||
}
|
||||
|
||||
void GBALoadBIOS(struct GBA* gba, int fd) {
|
||||
gba->memory.bios = fileMemoryMap(fd, SIZE_BIOS, MEMORY_READ);
|
||||
void GBALoadBIOS(struct GBA* gba, struct VFile* vf) {
|
||||
gba->biosVf = vf;
|
||||
gba->memory.bios = vf->map(vf, SIZE_BIOS, MEMORY_READ);
|
||||
gba->memory.fullBios = 1;
|
||||
uint32_t checksum = GBAChecksum(gba->memory.bios, SIZE_BIOS);
|
||||
GBALog(gba, GBA_LOG_DEBUG, "BIOS Checksum: 0x%X", checksum);
|
||||
|
|
|
@ -60,9 +60,10 @@ enum GBAKey {
|
|||
GBA_KEY_NONE = -1
|
||||
};
|
||||
|
||||
struct GBARotationSource;
|
||||
struct GBA;
|
||||
struct GBARotationSource;
|
||||
struct Patch;
|
||||
struct VFile;
|
||||
|
||||
typedef void (*GBALogHandler)(struct GBA*, enum GBALogLevel, const char* format, va_list args);
|
||||
|
||||
|
@ -99,6 +100,8 @@ struct GBA {
|
|||
struct GBARumble* rumble;
|
||||
void* pristineRom;
|
||||
size_t pristineRomSize;
|
||||
struct VFile* romVf;
|
||||
struct VFile* biosVf;
|
||||
|
||||
const char* activeFile;
|
||||
const char* savefile;
|
||||
|
@ -141,8 +144,8 @@ void GBAHalt(struct GBA* gba);
|
|||
void GBAAttachDebugger(struct GBA* gba, struct ARMDebugger* debugger);
|
||||
void GBADetachDebugger(struct GBA* gba);
|
||||
|
||||
void GBALoadROM(struct GBA* gba, int fd, const char* fname);
|
||||
void GBALoadBIOS(struct GBA* gba, int fd);
|
||||
void GBALoadROM(struct GBA* gba, struct VFile* vf, const char* fname);
|
||||
void GBALoadBIOS(struct GBA* gba, struct VFile* vf);
|
||||
void GBAApplyPatch(struct GBA* gba, struct Patch* patch);
|
||||
|
||||
__attribute__((format (printf, 3, 4)))
|
||||
|
|
|
@ -5,13 +5,6 @@
|
|||
void* anonymousMemoryMap(size_t size) {
|
||||
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) {
|
||||
munmap(memory, size);
|
||||
|
|
|
@ -8,23 +8,6 @@ void* anonymousMemoryMap(size_t 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) {
|
||||
// TODO fill in
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#define MEMORY_WRITE 2
|
||||
|
||||
void* anonymousMemoryMap(size_t size);
|
||||
void* fileMemoryMap(int fd, size_t size, int flags);
|
||||
void mappedMemoryFree(void* memory, size_t size);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,9 +2,19 @@
|
|||
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/mman.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
struct VFileFD {
|
||||
struct VFile d;
|
||||
int fd;
|
||||
#ifdef _WIN32
|
||||
HANDLE hMap;
|
||||
#endif
|
||||
};
|
||||
|
||||
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 _vfdReadline(struct VFile* vf, char* 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) {
|
||||
int fd = open(path, flags);
|
||||
int fd = open(path, flags, 0666);
|
||||
return VFileFromFD(fd);
|
||||
}
|
||||
|
||||
|
@ -34,6 +47,9 @@ struct VFile* VFileFromFD(int fd) {
|
|||
vfd->d.read = _vfdRead;
|
||||
vfd->d.readline = _vfdReadline;
|
||||
vfd->d.write = _vfdWrite;
|
||||
vfd->d.map = _vfdMap;
|
||||
vfd->d.unmap = _vfdUnmap;
|
||||
vfd->d.truncate = _vfdTruncate;
|
||||
|
||||
return &vfd->d;
|
||||
}
|
||||
|
@ -74,3 +90,50 @@ size_t _vfdWrite(struct VFile* vf, void* buffer, size_t size) {
|
|||
struct VFileFD* vfd = (struct VFileFD*) vf;
|
||||
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 "memory.h"
|
||||
|
||||
struct VFile {
|
||||
bool (*close)(struct VFile* vf);
|
||||
size_t (*seek)(struct VFile* vf, off_t offset, int whence);
|
||||
size_t (*read)(struct VFile* vf, void* 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);
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue