mirror of https://github.com/mgba-emu/mgba.git
Python: Add VFS bindings
This commit is contained in:
parent
0d1d5c988e
commit
606d35ba6c
|
@ -1,14 +1,15 @@
|
|||
#define COMMON_H
|
||||
#define extern
|
||||
#define _TIME_H_
|
||||
#define _SYS_TIME_H_
|
||||
#define ATTRIBUTE_FORMAT(X, Y, Z)
|
||||
#define DECL_BITFIELD(newtype, oldtype) typedef oldtype newtype
|
||||
#define DECL_BIT(type, name, bit)
|
||||
#define DECL_BITS(type, name, bit, nbits)
|
||||
typedef long time_t;
|
||||
typedef int... time_t;
|
||||
typedef int... off_t;
|
||||
typedef ... va_list;
|
||||
#include <limits.h>
|
||||
#include "platform/python/vfs-py.h"
|
||||
#include "core/core.h"
|
||||
#ifdef M_CORE_GBA
|
||||
#include "arm/arm.h"
|
||||
|
|
|
@ -13,10 +13,19 @@ ffi.set_source("mgba._pylib", """
|
|||
#include "gba/gba.h"
|
||||
#include "lr35902/lr35902.h"
|
||||
#include "gb/gb.h"
|
||||
#include "util/vfs.h"
|
||||
|
||||
struct VFile* VFileFromPython(void* fileobj);
|
||||
|
||||
struct VFilePy {
|
||||
struct VFile d;
|
||||
void* fileobj;
|
||||
};
|
||||
""", include_dirs=[src],
|
||||
extra_compile_args=sys.argv[1:],
|
||||
libraries=["mgba"],
|
||||
library_dirs=[os.path.join(os.getcwd(), "..")])
|
||||
library_dirs=[os.path.join(os.getcwd(), "..")],
|
||||
sources=[os.path.join(os.path.dirname(__file__), path) for path in ["vfs-py.c"]])
|
||||
|
||||
with open(os.path.join(os.getcwd(), "_builder.h")) as core:
|
||||
lines = []
|
||||
|
|
|
@ -6,12 +6,24 @@ def find(path):
|
|||
return None
|
||||
return Core(core)
|
||||
|
||||
def findVF(vf):
|
||||
core = lib.mCoreFindVF(vf.handle())
|
||||
if core == ffi.NULL:
|
||||
return None
|
||||
return Core(core)
|
||||
|
||||
def loadPath(path):
|
||||
core = find(path)
|
||||
if not core or not core.loadFile(path):
|
||||
return None
|
||||
return core
|
||||
|
||||
def loadVF(vf):
|
||||
core = findVF(vf)
|
||||
if not core or not core.loadROM(vf):
|
||||
return None
|
||||
return core
|
||||
|
||||
class Core:
|
||||
def __init__(self, native):
|
||||
self._core = ffi.gc(native, self._deinit)
|
||||
|
@ -32,6 +44,12 @@ class Core:
|
|||
def loadFile(self, path):
|
||||
return bool(lib.mCoreLoadFile(self._core, path.encode('UTF-8')))
|
||||
|
||||
def isROM(self, vf):
|
||||
return bool(self._core.isROM(vf.handle()))
|
||||
|
||||
def loadROM(self, vf):
|
||||
return bool(self._core.loadROM(self._core, vf.handle()))
|
||||
|
||||
def autoloadSave(self):
|
||||
return bool(lib.mCoreAutoloadSave(self._core))
|
||||
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
from _pylib import ffi, lib
|
||||
import mmap
|
||||
import os
|
||||
|
||||
@ffi.def_extern()
|
||||
def _vfpClose(vf):
|
||||
vfp = ffi.cast("struct VFilePy*", vf)
|
||||
ffi.from_handle(vfp.fileobj).close()
|
||||
|
||||
@ffi.def_extern()
|
||||
def _vfpSeek(vf, offset, whence):
|
||||
vfp = ffi.cast("struct VFilePy*", vf)
|
||||
f = ffi.from_handle(vfp.fileobj)
|
||||
f.seek(offset, whence)
|
||||
return f.tell()
|
||||
|
||||
@ffi.def_extern()
|
||||
def _vfpRead(vf, buffer, size):
|
||||
vfp = ffi.cast("struct VFilePy*", vf)
|
||||
pybuf = ffi.buffer(buffer, size)
|
||||
return ffi.from_handle(vfp.fileobj).readinto(pybuf)
|
||||
|
||||
@ffi.def_extern()
|
||||
def _vfpWrite(vf, buffer, size):
|
||||
vfp = ffi.cast("struct VFilePy*", vf)
|
||||
pybuf = ffi.buffer(buffer, size)
|
||||
return ffi.from_handle(vfp.fileobj).write(pybuf)
|
||||
|
||||
@ffi.def_extern()
|
||||
def _vfpMap(vf, size, flags):
|
||||
pass
|
||||
|
||||
@ffi.def_extern()
|
||||
def _vfpUnmap(vf, memory, size):
|
||||
pass
|
||||
|
||||
@ffi.def_extern()
|
||||
def _vfpTruncate(vf, size):
|
||||
vfp = ffi.cast("struct VFilePy*", vf)
|
||||
ffi.from_handle(vfp.fileobj).truncate(size)
|
||||
|
||||
@ffi.def_extern()
|
||||
def _vfpSize(vf):
|
||||
vfp = ffi.cast("struct VFilePy*", vf)
|
||||
f = ffi.from_handle(vfp.fileobj)
|
||||
pos = f.tell()
|
||||
f.seek(0, os.SEEK_END)
|
||||
size = f.tell()
|
||||
f.seek(pos, os.SEEK_SET)
|
||||
return size
|
||||
|
||||
@ffi.def_extern()
|
||||
def _vfpSync(vf, buffer, size):
|
||||
vfp = ffi.cast("struct VFilePy*", vf)
|
||||
f = ffi.from_handle(vfp.fileobj)
|
||||
if buffer and size:
|
||||
pos = f.tell()
|
||||
f.seek(0, os.SEEK_SET)
|
||||
_vfpWrite(vf, buffer, size)
|
||||
f.seek(pos, os.SEEK_SET)
|
||||
f.flush()
|
||||
os.fsync()
|
||||
return True
|
||||
|
||||
def open(f):
|
||||
handle = ffi.new_handle(f)
|
||||
vf = VFile(lib.VFileFromPython(handle))
|
||||
# Prevent garbage collection
|
||||
vf._fileobj = f
|
||||
vf._handle = handle
|
||||
return vf
|
||||
|
||||
def openPath(path, mode="r"):
|
||||
flags = 0
|
||||
if mode.startswith("r"):
|
||||
flags |= os.O_RDONLY
|
||||
elif mode.startswith("w"):
|
||||
flags |= os.O_WRONLY | os.O_CREAT | os.O_TRUNC
|
||||
elif mode.startswith("a"):
|
||||
flags |= os.O_WRONLY | os.O_CREAT | os.O_APPEND
|
||||
else:
|
||||
return None
|
||||
|
||||
if "+" in mode[1:]:
|
||||
flags |= os.O_RDWR
|
||||
if "x" in mode[1:]:
|
||||
flags |= os.O_EXCL
|
||||
|
||||
return VFile(lib.VFileOpen(path.encode("UTF-8"), flags))
|
||||
|
||||
class VFile:
|
||||
def __init__(self, vf):
|
||||
self._vf = vf
|
||||
|
||||
def handle(self):
|
||||
return self._vf
|
||||
|
||||
def close(self):
|
||||
return self._vf.close(self._vf)
|
||||
|
||||
def seek(self, offset, whence):
|
||||
return self._vf.seek(self._vf, offset, whence)
|
||||
|
||||
def read(self, buffer, size):
|
||||
return self._vf.read(self._vf, buffer, size)
|
||||
|
||||
def readline(self, buffer, size):
|
||||
return self._vf.readline(self._vf, buffer, size)
|
||||
|
||||
def write(self, buffer, size):
|
||||
return self._vf.write(self._vf, buffer, size)
|
||||
|
||||
def map(self, size, flags):
|
||||
return self._vf.map(self._vf, size, flags)
|
||||
|
||||
def unmap(self, memory, size):
|
||||
self._vf.unmap(self._vf, memory, size)
|
||||
|
||||
def truncate(self, size):
|
||||
self._vf.truncate(self._vf, size)
|
||||
|
||||
def size(self):
|
||||
return self._vf.size(self._vf)
|
||||
|
||||
def sync(self, buffer, size):
|
||||
return self._vf.sync(self._vf, buffer, size)
|
|
@ -1,4 +1,5 @@
|
|||
from setuptools import setup
|
||||
import re
|
||||
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 2",
|
||||
|
@ -6,9 +7,8 @@ classifiers = [
|
|||
"License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)"
|
||||
]
|
||||
|
||||
|
||||
setup(name="${BINARY_NAME}",
|
||||
version="${VERSION_STRING}",
|
||||
version=re.sub("/", "-", "${VERSION_STRING}"),
|
||||
author="Jeffrey Pfau",
|
||||
author_email="jeffrey@endrift.com",
|
||||
url="http://github.com/mgba-emu/mgba/",
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* Copyright (c) 2013-2016 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "util/vfs.h"
|
||||
|
||||
struct VFilePy {
|
||||
struct VFile d;
|
||||
void* fileobj;
|
||||
};
|
||||
|
||||
bool _vfpClose(struct VFile* vf);
|
||||
off_t _vfpSeek(struct VFile* vf, off_t offset, int whence);
|
||||
ssize_t _vfpRead(struct VFile* vf, void* buffer, size_t size);
|
||||
ssize_t _vfpWrite(struct VFile* vf, const void* buffer, size_t size);
|
||||
void* _vfpMap(struct VFile* vf, size_t size, int flags);
|
||||
void _vfpUnmap(struct VFile* vf, void* memory, size_t size);
|
||||
void _vfpTruncate(struct VFile* vf, size_t size);
|
||||
ssize_t _vfpSize(struct VFile* vf);
|
||||
bool _vfpSync(struct VFile* vf, const void* buffer, size_t size);
|
||||
|
||||
struct VFile* VFileFromPython(void* fileobj) {
|
||||
if (!fileobj) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct VFilePy* vfp = malloc(sizeof(struct VFilePy));
|
||||
if (!vfp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
vfp->fileobj = fileobj;
|
||||
vfp->d.close = _vfpClose;
|
||||
vfp->d.seek = _vfpSeek;
|
||||
vfp->d.read = _vfpRead;
|
||||
vfp->d.readline = VFileReadline;
|
||||
vfp->d.write = _vfpWrite;
|
||||
vfp->d.map = _vfpMap;
|
||||
vfp->d.unmap = _vfpUnmap;
|
||||
vfp->d.truncate = _vfpTruncate;
|
||||
vfp->d.size = _vfpSize;
|
||||
vfp->d.sync = _vfpSync;
|
||||
|
||||
return &vfp->d;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* Copyright (c) 2013-2016 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "util/vfs.h"
|
||||
|
||||
struct VFilePy {
|
||||
struct VFile d;
|
||||
void* fileobj;
|
||||
};
|
||||
|
||||
struct VFile* VFileFromPython(void* fileobj);
|
||||
|
||||
extern "Python+C" {
|
||||
|
||||
bool _vfpClose(struct VFile* vf);
|
||||
off_t _vfpSeek(struct VFile* vf, off_t offset, int whence);
|
||||
ssize_t _vfpRead(struct VFile* vf, void* buffer, size_t size);
|
||||
ssize_t _vfpWrite(struct VFile* vf, const void* buffer, size_t size);
|
||||
void* _vfpMap(struct VFile* vf, size_t size, int flags);
|
||||
void _vfpUnmap(struct VFile* vf, void* memory, size_t size);
|
||||
void _vfpTruncate(struct VFile* vf, size_t size);
|
||||
ssize_t _vfpSize(struct VFile* vf);
|
||||
bool _vfpSync(struct VFile* vf, const void* buffer, size_t size);
|
||||
|
||||
}
|
|
@ -65,12 +65,11 @@ struct VDir {
|
|||
struct VFile* VFileOpen(const char* path, int flags);
|
||||
|
||||
struct VFile* VFileOpenFD(const char* path, int flags);
|
||||
struct VFile* VFileFOpen(const char* path, const char* mode);
|
||||
struct VFile* VFileFromFD(int fd);
|
||||
|
||||
struct VFile* VFileFromMemory(void* mem, size_t size);
|
||||
struct VFile* VFileFromConstMemory(const void* mem, size_t size);
|
||||
struct VFile* VFileMemChunk(const void* mem, size_t size);
|
||||
struct VFile* VFileFromFILE(FILE* file);
|
||||
|
||||
struct VDir* VDirOpen(const char* path);
|
||||
struct VDir* VDirOpenArchive(const char* path);
|
||||
|
@ -83,7 +82,11 @@ struct VDir* VDirOpenZip(const char* path, int flags);
|
|||
struct VDir* VDirOpen7z(const char* path, int flags);
|
||||
#endif
|
||||
|
||||
#if defined(WII) || defined(_3DS)
|
||||
struct VFile* VFileFOpen(const char* path, const char* mode);
|
||||
struct VFile* VFileFromFILE(FILE* file);
|
||||
struct VDir* VDeviceList(void);
|
||||
#endif
|
||||
|
||||
void separatePath(const char* path, char* dirname, char* basename, char* extension);
|
||||
|
||||
|
|
Loading…
Reference in New Issue