all repos — mgba @ 377d8e60a73ff9b24f460aea4d42e828a677da05

mGBA Game Boy Advance Emulator

VFiles for abstract file operations, used at first in patches
Jeffrey Pfau jeffrey@endrift.com
Wed, 16 Jul 2014 01:31:10 -0700
commit

377d8e60a73ff9b24f460aea4d42e828a677da05

parent

d8654f3b883db94117f5bf9490231fe9745ef9ea

M src/gba/gba-thread.csrc/gba/gba-thread.c

@@ -7,6 +7,7 @@

#include "debugger/debugger.h" #include "util/patch.h" +#include "util/vfile.h" #include <signal.h>

@@ -114,7 +115,7 @@ if (threadContext->biosFd >= 0) {

GBALoadBIOS(&gba, threadContext->biosFd); } - if (threadContext->patchFd >= 0 && loadPatch(threadContext->patchFd, &patch)) { + if (threadContext->patchFd >= 0 && loadPatch(VFileFromFD(threadContext->patchFd), &patch)) { GBAApplyPatch(&gba, &patch); } }
M src/util/patch-ips.csrc/util/patch-ips.c

@@ -1,15 +1,16 @@

#include "util/patch-ips.h" #include "util/patch.h" +#include "util/vfile.h" static size_t _IPSOutputSize(struct Patch* patch, size_t inSize); static bool _IPSApplyPatch(struct Patch* patch, void* out, size_t outSize); bool loadPatchIPS(struct Patch* patch) { - lseek(patch->patchfd, 0, SEEK_SET); + patch->vf->seek(patch->vf, 0, SEEK_SET); char buffer[5]; - if (read(patch->patchfd, buffer, 5) != 5) { + if (patch->vf->read(patch->vf, buffer, 5) != 5) { return false; }

@@ -17,8 +18,8 @@ if (memcmp(buffer, "PATCH", 5) != 0) {

return false; } - lseek(patch->patchfd, -3, SEEK_END); - if (read(patch->patchfd, buffer, 3) != 3) { + patch->vf->seek(patch->vf, -3, SEEK_END); + if (patch->vf->read(patch->vf, buffer, 3) != 3) { return false; }

@@ -37,7 +38,7 @@ return inSize;

} bool _IPSApplyPatch(struct Patch* patch, void* out, size_t outSize) { - if (lseek(patch->patchfd, 5, SEEK_SET) != 5) { + if (patch->vf->seek(patch->vf, 5, SEEK_SET) != 5) { return false; } uint8_t* buf = out;

@@ -46,7 +47,7 @@ while (true) {

uint32_t offset = 0; uint16_t size = 0; - if (read(patch->patchfd, &offset, 3) != 3) { + if (patch->vf->read(patch->vf, &offset, 3) != 3) { return false; }

@@ -55,17 +56,17 @@ return true;

} offset = (offset >> 16) | (offset & 0xFF00) | ((offset << 16) & 0xFF0000); - if (read(patch->patchfd, &size, 2) != 2) { + if (patch->vf->read(patch->vf, &size, 2) != 2) { return false; } if (!size) { // RLE chunk - if (read(patch->patchfd, &size, 2) != 2) { + if (patch->vf->read(patch->vf, &size, 2) != 2) { return false; } size = (size >> 8) | (size << 8); uint8_t byte; - if (read(patch->patchfd, &byte, 1) != 1) { + if (patch->vf->read(patch->vf, &byte, 1) != 1) { return false; } if (offset + size > outSize) {

@@ -77,7 +78,7 @@ size = (size >> 8) | (size << 8);

if (offset + size > outSize) { return false; } - if (read(patch->patchfd, &buf[offset], size) != size) { + if (patch->vf->read(patch->vf, &buf[offset], size) != size) { return false; } }
M src/util/patch-ups.csrc/util/patch-ups.c

@@ -2,6 +2,7 @@ #include "util/patch-ips.h"

#include "util/crc32.h" #include "util/patch.h" +#include "util/vfile.h" enum { IN_CHECKSUM = -12,

@@ -13,13 +14,13 @@ };

static size_t _UPSOutputSize(struct Patch* patch, size_t inSize); static bool _UPSApplyPatch(struct Patch* patch, void* out, size_t outSize); -static size_t _UPSDecodeLength(int fd); +static size_t _UPSDecodeLength(struct VFile* vf); bool loadPatchUPS(struct Patch* patch) { - lseek(patch->patchfd, 0, SEEK_SET); + patch->vf->seek(patch->vf, 0, SEEK_SET); char buffer[BUFFER_SIZE]; - if (read(patch->patchfd, buffer, 4) != 4) { + if (patch->vf->read(patch->vf, buffer, 4) != 4) { return false; }

@@ -27,24 +28,24 @@ if (memcmp(buffer, "UPS1", 4) != 0) {

return false; } - size_t filesize = lseek(patch->patchfd, 0, SEEK_END); + size_t filesize = patch->vf->seek(patch->vf, 0, SEEK_END); uint32_t goodCrc32; - lseek(patch->patchfd, PATCH_CHECKSUM, SEEK_END); - if (read(patch->patchfd, &goodCrc32, 4) != 4) { + patch->vf->seek(patch->vf, PATCH_CHECKSUM, SEEK_END); + if (patch->vf->read(patch->vf, &goodCrc32, 4) != 4) { return false; } size_t blocksize; size_t alreadyRead = 0; - lseek(patch->patchfd, 0, SEEK_SET); + patch->vf->seek(patch->vf, 0, SEEK_SET); uint32_t crc = 0; while (alreadyRead < filesize + PATCH_CHECKSUM) { size_t toRead = sizeof(buffer); if (toRead + alreadyRead > filesize + PATCH_CHECKSUM) { toRead = filesize + PATCH_CHECKSUM - alreadyRead; } - blocksize = read(patch->patchfd, buffer, toRead); + blocksize = patch->vf->read(patch->vf, buffer, toRead); alreadyRead += blocksize; crc = updateCrc32(crc, buffer, blocksize); if (blocksize < toRead) {

@@ -63,20 +64,20 @@ }

size_t _UPSOutputSize(struct Patch* patch, size_t inSize) { UNUSED(inSize); - lseek(patch->patchfd, 4, SEEK_SET); - if (_UPSDecodeLength(patch->patchfd) != inSize) { + patch->vf->seek(patch->vf, 4, SEEK_SET); + if (_UPSDecodeLength(patch->vf) != inSize) { return 0; } - return _UPSDecodeLength(patch->patchfd); + return _UPSDecodeLength(patch->vf); } bool _UPSApplyPatch(struct Patch* patch, void* out, size_t outSize) { // TODO: Input checksum - size_t filesize = lseek(patch->patchfd, 0, SEEK_END); - lseek(patch->patchfd, 4, SEEK_SET); - _UPSDecodeLength(patch->patchfd); // Discard input size - if (_UPSDecodeLength(patch->patchfd) != outSize) { + size_t filesize = patch->vf->seek(patch->vf, 0, SEEK_END); + patch->vf->seek(patch->vf, 4, SEEK_SET); + _UPSDecodeLength(patch->vf); // Discard input size + if (_UPSDecodeLength(patch->vf) != outSize) { return false; }

@@ -84,11 +85,11 @@ size_t offset = 0;

size_t alreadyRead = 0; uint8_t* buf = out; while (alreadyRead < filesize + IN_CHECKSUM) { - offset += _UPSDecodeLength(patch->patchfd); + offset += _UPSDecodeLength(patch->vf); uint8_t byte; while (true) { - if (read(patch->patchfd, &byte, 1) != 1) { + if (patch->vf->read(patch->vf, &byte, 1) != 1) { return false; } buf[offset] ^= byte;

@@ -97,28 +98,28 @@ if (!byte) {

break; } } - alreadyRead = lseek(patch->patchfd, 0, SEEK_CUR); + alreadyRead = patch->vf->seek(patch->vf, 0, SEEK_CUR); } uint32_t goodCrc32; - lseek(patch->patchfd, OUT_CHECKSUM, SEEK_END); - if (read(patch->patchfd, &goodCrc32, 4) != 4) { + patch->vf->seek(patch->vf, OUT_CHECKSUM, SEEK_END); + if (patch->vf->read(patch->vf, &goodCrc32, 4) != 4) { return false; } - lseek(patch->patchfd, 0, SEEK_SET); + patch->vf->seek(patch->vf, 0, SEEK_SET); if (crc32(out, outSize) != goodCrc32) { return false; } return true; } -size_t _UPSDecodeLength(int fd) { +size_t _UPSDecodeLength(struct VFile* vf) { size_t shift = 1; size_t value = 0; uint8_t byte; while (true) { - if (read(fd, &byte, 1) != 1) { + if (vf->read(vf, &byte, 1) != 1) { break; } value += (byte & 0x7f) * shift;
M src/util/patch.csrc/util/patch.c

@@ -3,8 +3,8 @@

#include "util/patch-ips.h" #include "util/patch-ups.h" -bool loadPatch(int patchfd, struct Patch* patch) { - patch->patchfd = patchfd; +bool loadPatch(struct VFile* vf, struct Patch* patch) { + patch->vf = vf; if (loadPatchIPS(patch)) { return true;
M src/util/patch.hsrc/util/patch.h

@@ -3,13 +3,15 @@ #define PATCH_H

#include "common.h" +struct VFile; + struct Patch { - int patchfd; + struct VFile* vf; size_t (*outputSize)(struct Patch* patch, size_t inSize); bool (*applyPatch)(struct Patch* patch, void* out, size_t outSize); }; -bool loadPatch(int patchfd, struct Patch* patch); +bool loadPatch(struct VFile* vf, struct Patch* patch); #endif
A src/util/vfile.c

@@ -0,0 +1,76 @@

+#include "util/vfile.h" + +#include <fcntl.h> + +struct VFileFD { + struct VFile d; + int fd; +}; + +static bool _vfdClose(struct VFile* vf); +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); + +struct VFile* VFileOpen(const char* path, int flags) { + int fd = open(path, flags); + return VFileFromFD(fd); +} + +struct VFile* VFileFromFD(int fd) { + if (fd < 0) { + return 0; + } + + struct VFileFD* vfd = malloc(sizeof(struct VFileFD)); + if (!vfd) { + return 0; + } + + vfd->fd = fd; + vfd->d.close = _vfdClose; + vfd->d.seek = _vfdSeek; + vfd->d.read = _vfdRead; + vfd->d.readline = _vfdReadline; + vfd->d.write = _vfdWrite; + + return &vfd->d; +} + +bool _vfdClose(struct VFile* vf) { + struct VFileFD* vfd = (struct VFileFD*) vf; + if (close(vfd->fd) < 0) { + return false; + } + free(vfd); + return true; +} + +size_t _vfdSeek(struct VFile* vf, off_t offset, int whence) { + struct VFileFD* vfd = (struct VFileFD*) vf; + return lseek(vfd->fd, offset, whence); +} + +size_t _vfdRead(struct VFile* vf, void* buffer, size_t size) { + struct VFileFD* vfd = (struct VFileFD*) vf; + return read(vfd->fd, buffer, size); +} + +size_t _vfdReadline(struct VFile* vf, char* buffer, size_t size) { + struct VFileFD* vfd = (struct VFileFD*) vf; + size_t bytesRead = 0; + while (bytesRead < size - 1) { + size_t newRead = read(vfd->fd, &buffer[bytesRead], 1); + bytesRead += newRead; + if (!newRead || buffer[bytesRead] == '\n') { + break; + } + } + return buffer[bytesRead] = '\0'; +} + +size_t _vfdWrite(struct VFile* vf, void* buffer, size_t size) { + struct VFileFD* vfd = (struct VFileFD*) vf; + return write(vfd->fd, buffer, size); +}
A src/util/vfile.h

@@ -0,0 +1,17 @@

+#ifndef VFILE_H +#define VFILE_H + +#include "common.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); +}; + +struct VFile* VFileOpen(const char* path, int flags); +struct VFile* VFileFromFD(int fd); + +#endif