View
@@ -3,92 +3,107 @@
# 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/.
-from ._pylib import ffi, lib
-from . import tile, createCallback
+from ._pylib import ffi, lib # pylint: disable=no-name-in-module
+from . import tile
from cached_property import cached_property
+from functools import wraps
+
def find(path):
core = lib.mCoreFind(path.encode('UTF-8'))
if core == ffi.NULL:
return None
return Core._init(core)
-def findVF(vf):
- core = lib.mCoreFindVF(vf.handle)
+
+def find_vf(vfile):
+ core = lib.mCoreFindVF(vfile.handle)
if core == ffi.NULL:
return None
return Core._init(core)
-def loadPath(path):
+
+def load_path(path):
core = find(path)
- if not core or not core.loadFile(path):
+ if not core or not core.load_file(path):
return None
return core
-def loadVF(vf):
- core = findVF(vf)
- if not core or not core.loadROM(vf):
+
+def load_vf(vfile):
+ core = find_vf(vfile)
+ if not core or not core.load_rom(vfile):
return None
return core
-def needsReset(f):
+
+def needs_reset(func):
+ @wraps(func)
def wrapper(self, *args, **kwargs):
- if not self._wasReset:
+ if not self._was_reset:
raise RuntimeError("Core must be reset first")
- return f(self, *args, **kwargs)
+ return func(self, *args, **kwargs)
return wrapper
-def protected(f):
+
+def protected(func):
+ @wraps(func)
def wrapper(self, *args, **kwargs):
if self._protected:
raise RuntimeError("Core is protected")
- return f(self, *args, **kwargs)
+ return func(self, *args, **kwargs)
return wrapper
+
@ffi.def_extern()
-def _mCorePythonCallbacksVideoFrameStarted(user):
+def _mCorePythonCallbacksVideoFrameStarted(user): # pylint: disable=invalid-name
context = ffi.from_handle(user)
- context._videoFrameStarted()
+ context._video_frame_started()
+
@ffi.def_extern()
-def _mCorePythonCallbacksVideoFrameEnded(user):
+def _mCorePythonCallbacksVideoFrameEnded(user): # pylint: disable=invalid-name
context = ffi.from_handle(user)
- context._videoFrameEnded()
+ context._video_frame_ended()
+
@ffi.def_extern()
-def _mCorePythonCallbacksCoreCrashed(user):
+def _mCorePythonCallbacksCoreCrashed(user): # pylint: disable=invalid-name
context = ffi.from_handle(user)
- context._coreCrashed()
+ context._core_crashed()
+
@ffi.def_extern()
-def _mCorePythonCallbacksSleep(user):
+def _mCorePythonCallbacksSleep(user): # pylint: disable=invalid-name
context = ffi.from_handle(user)
context._sleep()
+
class CoreCallbacks(object):
def __init__(self):
self._handle = ffi.new_handle(self)
- self.videoFrameStarted = []
- self.videoFrameEnded = []
- self.coreCrashed = []
+ self.video_frame_started = []
+ self.video_frame_ended = []
+ self.core_crashed = []
self.sleep = []
self.context = lib.mCorePythonCallbackCreate(self._handle)
- def _videoFrameStarted(self):
- for cb in self.videoFrameStarted:
- cb()
+ def _video_frame_started(self):
+ for callback in self.video_frame_started:
+ callback()
- def _videoFrameEnded(self):
- for cb in self.videoFrameEnded:
- cb()
+ def _video_frame_ended(self):
+ for callback in self.video_frame_ended:
+ callback()
- def _coreCrashed(self):
- for cb in self.coreCrashed:
- cb()
+ def _core_crashed(self):
+ for callback in self.core_crashed:
+ callback()
def _sleep(self):
- for cb in self.sleep:
- cb()
+ for callback in self.sleep:
+ callback()
+
class Core(object):
if hasattr(lib, 'PLATFORM_GBA'):
@@ -99,36 +114,36 @@ class Core(object):
def __init__(self, native):
self._core = native
- self._wasReset = False
+ self._was_reset = False
self._protected = False
self._callbacks = CoreCallbacks()
self._core.addCoreCallbacks(self._core, self._callbacks.context)
self.config = Config(ffi.addressof(native.config))
def __del__(self):
- self._wasReset = False
+ self._was_reset = False
@cached_property
- def graphicsCache(self):
- if not self._wasReset:
+ def graphics_cache(self):
+ if not self._was_reset:
raise RuntimeError("Core must be reset first")
return tile.CacheSet(self)
@cached_property
def tiles(self):
- t = []
- ts = ffi.addressof(self.graphicsCache.cache.tiles)
- for i in range(lib.mTileCacheSetSize(ts)):
- t.append(tile.TileView(lib.mTileCacheSetGetPointer(ts, i)))
- return t
+ tiles = []
+ native_tiles = ffi.addressof(self.graphics_cache.cache.tiles)
+ for i in range(lib.mTileCacheSetSize(native_tiles)):
+ tiles.append(tile.TileView(lib.mTileCacheSetGetPointer(native_tiles, i)))
+ return tiles
@cached_property
def maps(self):
- m = []
- ms = ffi.addressof(self.graphicsCache.cache.maps)
- for i in range(lib.mMapCacheSetSize(ms)):
- m.append(tile.MapView(lib.mMapCacheSetGetPointer(ms, i)))
- return m
+ maps = []
+ native_maps = ffi.addressof(self.graphics_cache.cache.maps)
+ for i in range(lib.mMapCacheSetSize(native_maps)):
+ maps.append(tile.MapView(lib.mMapCacheSetGetPointer(native_maps, i)))
+ return maps
@classmethod
def _init(cls, native):
@@ -150,121 +165,125 @@ def _detect(cls, core):
return Core(core)
def _load(self):
- self._wasReset = True
+ self._was_reset = True
- def loadFile(self, path):
+ def load_file(self, path):
return bool(lib.mCoreLoadFile(self._core, path.encode('UTF-8')))
- def isROM(self, vf):
- return bool(self._core.isROM(vf.handle))
+ def is_rom(self, vfile):
+ return bool(self._core.isROM(vfile.handle))
- def loadROM(self, vf):
- return bool(self._core.loadROM(self._core, vf.handle))
+ def load_rom(self, vfile):
+ return bool(self._core.loadROM(self._core, vfile.handle))
- def loadBIOS(self, vf, id=0):
- return bool(self._core.loadBIOS(self._core, vf.handle, id))
+ def load_bios(self, vfile, id=0):
+ return bool(self._core.loadBIOS(self._core, vfile.handle, id))
- def loadSave(self, vf):
- return bool(self._core.loadSave(self._core, vf.handle))
+ def load_save(self, vfile):
+ return bool(self._core.loadSave(self._core, vfile.handle))
- def loadTemporarySave(self, vf):
- return bool(self._core.loadTemporarySave(self._core, vf.handle))
+ def load_temporary_save(self, vfile):
+ return bool(self._core.loadTemporarySave(self._core, vfile.handle))
- def loadPatch(self, vf):
- return bool(self._core.loadPatch(self._core, vf.handle))
+ def load_patch(self, vfile):
+ return bool(self._core.loadPatch(self._core, vfile.handle))
- def loadConfig(self, config):
+ def load_config(self, config):
lib.mCoreLoadForeignConfig(self._core, config._native)
- def autoloadSave(self):
+ def autoload_save(self):
return bool(lib.mCoreAutoloadSave(self._core))
- def autoloadPatch(self):
+ def autoload_patch(self):
return bool(lib.mCoreAutoloadPatch(self._core))
- def autoloadCheats(self):
+ def autoload_cheats(self):
return bool(lib.mCoreAutoloadCheats(self._core))
def platform(self):
return self._core.platform(self._core)
- def desiredVideoDimensions(self):
+ def desired_video_dimensions(self):
width = ffi.new("unsigned*")
height = ffi.new("unsigned*")
self._core.desiredVideoDimensions(self._core, width, height)
return width[0], height[0]
- def setVideoBuffer(self, image):
+ def set_video_buffer(self, image):
self._core.setVideoBuffer(self._core, image.buffer, image.stride)
def reset(self):
self._core.reset(self._core)
self._load()
- @needsReset
+ @needs_reset
@protected
- def runFrame(self):
+ def run_frame(self):
self._core.runFrame(self._core)
- @needsReset
+ @needs_reset
@protected
- def runLoop(self):
+ def run_loop(self):
self._core.runLoop(self._core)
- @needsReset
+ @needs_reset
def step(self):
self._core.step(self._core)
@staticmethod
- def _keysToInt(*args, **kwargs):
+ def _keys_to_int(*args, **kwargs):
keys = 0
if 'raw' in kwargs:
keys = kwargs['raw']
for key in args:
keys |= 1 << key
return keys
- def setKeys(self, *args, **kwargs):
- self._core.setKeys(self._core, self._keysToInt(*args, **kwargs))
+ @protected
+ def set_keys(self, *args, **kwargs):
+ self._core.setKeys(self._core, self._keys_to_int(*args, **kwargs))
- def addKeys(self, *args, **kwargs):
- self._core.addKeys(self._core, self._keysToInt(*args, **kwargs))
+ @protected
+ def add_keys(self, *args, **kwargs):
+ self._core.addKeys(self._core, self._keys_to_int(*args, **kwargs))
- def clearKeys(self, *args, **kwargs):
- self._core.clearKeys(self._core, self._keysToInt(*args, **kwargs))
+ @protected
+ def clear_keys(self, *args, **kwargs):
+ self._core.clearKeys(self._core, self._keys_to_int(*args, **kwargs))
@property
- @needsReset
- def frameCounter(self):
+ @needs_reset
+ def frame_counter(self):
return self._core.frameCounter(self._core)
@property
- def frameCycles(self):
+ def frame_cycles(self):
return self._core.frameCycles(self._core)
@property
def frequency(self):
return self._core.frequency(self._core)
@property
- def gameTitle(self):
+ def game_title(self):
title = ffi.new("char[16]")
self._core.getGameTitle(self._core, title)
return ffi.string(title, 16).decode("ascii")
@property
- def gameCode(self):
+ def game_code(self):
code = ffi.new("char[12]")
self._core.getGameCode(self._core, code)
return ffi.string(code, 12).decode("ascii")
- def addFrameCallback(self, cb):
- self._callbacks.videoFrameEnded.append(cb)
+ def add_frame_callback(self, callback):
+ self._callbacks.video_frame_ended.append(callback)
@property
def crc32(self):
return self._native.romCrc32
+
class ICoreOwner(object):
def claim(self):
raise NotImplementedError
@@ -281,22 +300,26 @@ def __exit__(self, type, value, traceback):
self.core._protected = False
self.release()
+
class IRunner(object):
def pause(self):
raise NotImplementedError
def unpause(self):
raise NotImplementedError
- def useCore(self):
+ def use_core(self):
raise NotImplementedError
- def isRunning(self):
+ @property
+ def running(self):
raise NotImplementedError
- def isPaused(self):
+ @property
+ def paused(self):
raise NotImplementedError
+
class Config(object):
def __init__(self, native=None, port=None, defaults={}):
if not native:
View
@@ -3,26 +3,27 @@
# 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/.
-from ._pylib import ffi, lib
+from ._pylib import ffi, lib # pylint: disable=no-name-in-module
from .core import IRunner, ICoreOwner, Core
-import io
import sys
+
class DebuggerCoreOwner(ICoreOwner):
def __init__(self, debugger):
self.debugger = debugger
- self.wasPaused = False
+ self.was_paused = False
def claim(self):
if self.debugger.isRunning():
- self.wasPaused = True
+ self.was_paused = True
self.debugger.pause()
return self.debugger._core
def release(self):
- if self.wasPaused:
+ if self.was_paused:
self.debugger.unpause()
+
class NativeDebugger(IRunner):
WATCHPOINT_WRITE = lib.WATCHPOINT_WRITE
WATCHPOINT_READ = lib.WATCHPOINT_READ
@@ -49,37 +50,40 @@ def pause(self):
def unpause(self):
self._native.state = lib.DEBUGGER_RUNNING
- def isRunning(self):
+ @property
+ def running(self):
return self._native.state == lib.DEBUGGER_RUNNING
- def isPaused(self):
+ @property
+ def paused(self):
return self._native.state in (lib.DEBUGGER_PAUSED, lib.DEBUGGER_CUSTOM)
- def useCore(self):
+ def use_core(self):
return DebuggerCoreOwner(self)
- def setBreakpoint(self, address):
+ def set_breakpoint(self, address):
if not self._native.platform.setBreakpoint:
raise RuntimeError("Platform does not support breakpoints")
self._native.platform.setBreakpoint(self._native.platform, address)
- def clearBreakpoint(self, address):
+ def clear_breakpoint(self, address):
if not self._native.platform.setBreakpoint:
raise RuntimeError("Platform does not support breakpoints")
self._native.platform.clearBreakpoint(self._native.platform, address)
- def setWatchpoint(self, address):
+ def set_watchpoint(self, address):
if not self._native.platform.setWatchpoint:
raise RuntimeError("Platform does not support watchpoints")
self._native.platform.setWatchpoint(self._native.platform, address)
- def clearWatchpoint(self, address):
+ def clear_watchpoint(self, address):
if not self._native.platform.clearWatchpoint:
raise RuntimeError("Platform does not support watchpoints")
self._native.platform.clearWatchpoint(self._native.platform, address)
- def addCallback(self, cb):
- self._cbs.append(cb)
+ def add_callback(self, callback):
+ self._cbs.append(callback)
+
class CLIBackend(object):
def __init__(self, backend):
@@ -88,6 +92,7 @@ def __init__(self, backend):
def write(self, string):
self.backend.printf(string)
+
class CLIDebugger(NativeDebugger):
def __init__(self, native):
super(CLIDebugger, self).__init__(native)
@@ -97,5 +102,5 @@ def printf(self, message, *args, **kwargs):
message = message.format(*args, **kwargs)
self._cli.backend.printf(ffi.new("char []", b"%s"), ffi.new("char []", message.encode('utf-8')))
- def installPrint(self):
+ def install_print(self):
sys.stdout = CLIBackend(self)
View
@@ -8,6 +8,7 @@
except ImportError:
pass
+
def search(core):
crc32 = None
if hasattr(core, 'PLATFORM_GBA') and core.platform() == core.PLATFORM_GBA:
View
@@ -3,12 +3,13 @@
# 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/.
-from ._pylib import ffi, lib
+from ._pylib import ffi, lib # pylint: disable=no-name-in-module
from .lr35902 import LR35902Core
-from .core import Core, needsReset
+from .core import Core, needs_reset
from .memory import Memory
from .tile import Sprite
-from . import createCallback
+from . import create_callback
+
class GB(Core):
KEY_A = lib.GBA_KEY_A
@@ -25,31 +26,34 @@ def __init__(self, native):
self._native = ffi.cast("struct GB*", native.board)
self.sprites = GBObjs(self)
self.cpu = LR35902Core(self._core.cpu)
+ self.memory = None
- @needsReset
- def _initCache(self, cache):
+ @needs_reset
+ def _init_cache(self, cache):
lib.GBVideoCacheInit(cache)
lib.GBVideoCacheAssociate(cache, ffi.addressof(self._native.video))
- def _deinitCache(self, cache):
+ def _deinit_cache(self, cache):
lib.mCacheSetDeinit(cache)
- if self._wasReset:
+ if self._was_reset:
self._native.video.renderer.cache = ffi.NULL
def _load(self):
super(GB, self)._load()
self.memory = GBMemory(self._core)
- def attachSIO(self, link):
+ def attach_sio(self, link):
lib.GBSIOSetDriver(ffi.addressof(self._native.sio), link._native)
def __del__(self):
lib.GBSIOSetDriver(ffi.addressof(self._native.sio), ffi.NULL)
-createCallback("GBSIOPythonDriver", "init")
-createCallback("GBSIOPythonDriver", "deinit")
-createCallback("GBSIOPythonDriver", "writeSB")
-createCallback("GBSIOPythonDriver", "writeSC")
+
+create_callback("GBSIOPythonDriver", "init")
+create_callback("GBSIOPythonDriver", "deinit")
+create_callback("GBSIOPythonDriver", "writeSB")
+create_callback("GBSIOPythonDriver", "writeSC")
+
class GBSIODriver(object):
def __init__(self):
@@ -62,53 +66,55 @@ def init(self):
def deinit(self):
pass
- def writeSB(self, value):
+ def write_sb(self, value):
pass
- def writeSC(self, value):
+ def write_sc(self, value):
return value
+
class GBSIOSimpleDriver(GBSIODriver):
def __init__(self, period=0x100):
super(GBSIOSimpleDriver, self).__init__()
- self.rx = 0x00
+ self.rx = 0x00 # pylint: disable=invalid-name
self._period = period
def init(self):
self._native.p.period = self._period
return True
- def writeSB(self, value):
- self.rx = value
+ def write_sb(self, value):
+ self.rx = value # pylint: disable=invalid-name
- def writeSC(self, value):
+ def write_sc(self, value):
self._native.p.period = self._period
if value & 0x80:
lib.mTimingDeschedule(ffi.addressof(self._native.p.p.timing), ffi.addressof(self._native.p.event))
lib.mTimingSchedule(ffi.addressof(self._native.p.p.timing), ffi.addressof(self._native.p.event), self._native.p.period)
return value
- def isReady(self):
+ def is_ready(self):
return not self._native.p.remainingBits
@property
- def tx(self):
- self._native.p.pendingSB
+ def tx(self): # pylint: disable=invalid-name
+ return self._native.p.pendingSB
@property
def period(self):
return self._native.p.period
@tx.setter
- def tx(self, newTx):
+ def tx(self, newTx): # pylint: disable=invalid-name
self._native.p.pendingSB = newTx
self._native.p.remainingBits = 8
@period.setter
- def period(self, newPeriod):
- self._period = newPeriod
+ def period(self, new_period):
+ self._period = new_period
if self._native.p:
- self._native.p.period = newPeriod
+ self._native.p.period = new_period
+
class GBMemory(Memory):
def __init__(self, core):
@@ -119,15 +125,16 @@ def __init__(self, core):
self.sram = Memory(core, lib.GB_SIZE_EXTERNAL_RAM, lib.GB_REGION_EXTERNAL_RAM)
self.iwram = Memory(core, lib.GB_SIZE_WORKING_RAM_BANK0, lib.GB_BASE_WORKING_RAM_BANK0)
self.oam = Memory(core, lib.GB_SIZE_OAM, lib.GB_BASE_OAM)
- self.io = Memory(core, lib.GB_SIZE_IO, lib.GB_BASE_IO)
+ self.io = Memory(core, lib.GB_SIZE_IO, lib.GB_BASE_IO) # pylint: disable=invalid-name
self.hram = Memory(core, lib.GB_SIZE_HRAM, lib.GB_BASE_HRAM)
+
class GBSprite(Sprite):
- PALETTE_BASE = 8,
+ PALETTE_BASE = (8,)
def __init__(self, obj, core):
- self.x = obj.x
- self.y = obj.y
+ self.x = obj.x # pylint: disable=invalid-name
+ self.y = obj.y # pylint: disable=invalid-name
self.tile = obj.tile
self._attr = obj.attr
self.width = 8
@@ -136,10 +143,10 @@ def __init__(self, obj, core):
if core._native.model >= lib.GB_MODEL_CGB:
if self._attr & 8:
self.tile += 512
- self.paletteId = self._attr & 7
+ self.palette_id = self._attr & 7
else:
- self.paletteId = (self._attr >> 4) & 1
- self.paletteId += 8
+ self.palette_id = (self._attr >> 4) & 1
+ self.palette_id += 8
class GBObjs:
View
@@ -3,12 +3,13 @@
# 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/.
-from ._pylib import ffi, lib
+from ._pylib import ffi, lib # pylint: disable=no-name-in-module
from .arm import ARMCore
-from .core import Core, needsReset
+from .core import Core, needs_reset
from .tile import Sprite
from .memory import Memory
-from . import createCallback
+from . import create_callback
+
class GBA(Core):
KEY_A = lib.GBA_KEY_A
@@ -34,38 +35,43 @@ def __init__(self, native):
self._native = ffi.cast("struct GBA*", native.board)
self.sprites = GBAObjs(self)
self.cpu = ARMCore(self._core.cpu)
+ self.memory = None
self._sio = set()
- @needsReset
- def _initCache(self, cache):
+ @needs_reset
+ def _init_cache(self, cache):
lib.GBAVideoCacheInit(cache)
lib.GBAVideoCacheAssociate(cache, ffi.addressof(self._native.video))
- def _deinitCache(self, cache):
+ def _deinit_cache(self, cache):
lib.mCacheSetDeinit(cache)
- if self._wasReset:
+ if self._was_reset:
self._native.video.renderer.cache = ffi.NULL
def _load(self):
super(GBA, self)._load()
self.memory = GBAMemory(self._core, self._native.memory.romSize)
- def attachSIO(self, link, mode=lib.SIO_MULTI):
+ def attach_sio(self, link, mode=lib.SIO_MULTI):
self._sio.add(mode)
lib.GBASIOSetDriver(ffi.addressof(self._native.sio), link._native, mode)
def __del__(self):
for mode in self._sio:
lib.GBASIOSetDriver(ffi.addressof(self._native.sio), ffi.NULL, mode)
-createCallback("GBASIOPythonDriver", "init")
-createCallback("GBASIOPythonDriver", "deinit")
-createCallback("GBASIOPythonDriver", "load")
-createCallback("GBASIOPythonDriver", "unload")
-createCallback("GBASIOPythonDriver", "writeRegister")
+
+create_callback("GBASIOPythonDriver", "init")
+create_callback("GBASIOPythonDriver", "deinit")
+create_callback("GBASIOPythonDriver", "load")
+create_callback("GBASIOPythonDriver", "unload")
+create_callback("GBASIOPythonDriver", "writeRegister")
+
class GBASIODriver(object):
def __init__(self):
+ super(GBASIODriver, self).__init__()
+
self._handle = ffi.new_handle(self)
self._native = ffi.gc(lib.GBASIOPythonDriverCreate(self._handle), lib.free)
@@ -81,20 +87,22 @@ def load(self):
def unload(self):
return True
- def writeRegister(self, address, value):
+ def write_register(self, address, value):
return value
+
class GBASIOJOYDriver(GBASIODriver):
RESET = lib.JOY_RESET
POLL = lib.JOY_POLL
TRANS = lib.JOY_TRANS
RECV = lib.JOY_RECV
def __init__(self):
- self._handle = ffi.new_handle(self)
+ super(GBASIOJOYDriver, self).__init__()
+
self._native = ffi.gc(lib.GBASIOJOYPythonDriverCreate(self._handle), lib.free)
- def sendCommand(self, cmd, data):
+ def send_command(self, cmd, data):
buffer = ffi.new('uint8_t[5]')
try:
buffer[0] = data[0]
@@ -110,14 +118,15 @@ def sendCommand(self, cmd, data):
return bytes(buffer[0:outlen])
return None
+
class GBAMemory(Memory):
def __init__(self, core, romSize=lib.SIZE_CART0):
super(GBAMemory, self).__init__(core, 0x100000000)
self.bios = Memory(core, lib.SIZE_BIOS, lib.BASE_BIOS)
self.wram = Memory(core, lib.SIZE_WORKING_RAM, lib.BASE_WORKING_RAM)
self.iwram = Memory(core, lib.SIZE_WORKING_IRAM, lib.BASE_WORKING_IRAM)
- self.io = Memory(core, lib.SIZE_IO, lib.BASE_IO)
+ self.io = Memory(core, lib.SIZE_IO, lib.BASE_IO) # pylint: disable=invalid-name
self.palette = Memory(core, lib.SIZE_PALETTE_RAM, lib.BASE_PALETTE_RAM)
self.vram = Memory(core, lib.SIZE_VRAM, lib.BASE_VRAM)
self.oam = Memory(core, lib.SIZE_OAM, lib.BASE_OAM)
@@ -128,6 +137,7 @@ def __init__(self, core, romSize=lib.SIZE_CART0):
self.rom = self.cart0
self.sram = Memory(core, lib.SIZE_CART_SRAM, lib.BASE_CART_SRAM)
+
class GBASprite(Sprite):
TILE_BASE = 0x800, 0x400
PALETTE_BASE = 0x10, 1
@@ -136,18 +146,19 @@ def __init__(self, obj):
self._a = obj.a
self._b = obj.b
self._c = obj.c
- self.x = self._b & 0x1FF
- self.y = self._a & 0xFF
+ self.x = self._b & 0x1FF # pylint: disable=invalid-name
+ self.y = self._a & 0xFF # pylint: disable=invalid-name
self._shape = self._a >> 14
self._size = self._b >> 14
- self._256Color = bool(self._a & 0x2000)
+ self._256_color = bool(self._a & 0x2000)
self.width, self.height = lib.GBAVideoObjSizes[self._shape * 4 + self._size]
self.tile = self._c & 0x3FF
- if self._256Color:
- self.paletteId = 0
+ if self._256_color:
+ self.palette_id = 0
self.tile >>= 1
else:
- self.paletteId = self._c >> 12
+ self.palette_id = self._c >> 12
+
class GBAObjs:
def __init__(self, core):
@@ -161,7 +172,7 @@ def __getitem__(self, index):
if index >= len(self):
raise IndexError()
sprite = GBASprite(self._obj[index])
- tiles = self._core.tiles[3 if sprite._256Color else 2]
- map1D = bool(self._core._native.memory.io[0] & 0x40)
- sprite.constitute(tiles, 0 if map1D else 0x20)
+ tiles = self._core.tiles[3 if sprite._256_color else 2]
+ map_1d = bool(self._core._native.memory.io[0] & 0x40)
+ sprite.constitute(tiles, 0 if map_1d else 0x20)
return sprite
View
@@ -3,14 +3,15 @@
# 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/.
-from ._pylib import ffi, lib
+from ._pylib import ffi # pylint: disable=no-name-in-module
from . import png
try:
import PIL.Image as PImage
except ImportError:
pass
+
class Image:
def __init__(self, width, height, stride=0, alpha=False):
self.width = width
@@ -24,58 +25,63 @@ def constitute(self):
self.stride = self.width
self.buffer = ffi.new("color_t[{}]".format(self.stride * self.height))
- def savePNG(self, f):
- p = png.PNG(f, mode=png.MODE_RGBA if self.alpha else png.MODE_RGB)
- success = p.writeHeader(self)
- success = success and p.writePixels(self)
- p.writeClose()
+ def save_png(self, fileobj):
+ png_file = png.PNG(fileobj, mode=png.MODE_RGBA if self.alpha else png.MODE_RGB)
+ success = png_file.write_header(self)
+ success = success and png_file.write_pixels(self)
+ png_file.write_close()
return success
if 'PImage' in globals():
- def toPIL(self):
- type = "RGBA" if self.alpha else "RGBX"
- return PImage.frombytes(type, (self.width, self.height), ffi.buffer(self.buffer), "raw",
- type, self.stride * 4)
-
-def u16ToU32(c):
- r = c & 0x1F
- g = (c >> 5) & 0x1F
- b = (c >> 10) & 0x1F
- a = (c >> 15) & 1
+ def to_pil(self):
+ colorspace = "RGBA" if self.alpha else "RGBX"
+ return PImage.frombytes(colorspace, (self.width, self.height), ffi.buffer(self.buffer), "raw",
+ colorspace, self.stride * 4)
+
+
+def u16_to_u32(color):
+ # pylint: disable=invalid-name
+ r = color & 0x1F
+ g = (color >> 5) & 0x1F
+ b = (color >> 10) & 0x1F
+ a = (color >> 15) & 1
abgr = r << 3
abgr |= g << 11
abgr |= b << 19
abgr |= (a * 0xFF) << 24
return abgr
-def u32ToU16(c):
- r = (c >> 3) & 0x1F
- g = (c >> 11) & 0x1F
- b = (c >> 19) & 0x1F
- a = c >> 31
+
+def u32_to_u16(color):
+ # pylint: disable=invalid-name
+ r = (color >> 3) & 0x1F
+ g = (color >> 11) & 0x1F
+ b = (color >> 19) & 0x1F
+ a = color >> 31
abgr = r
abgr |= g << 5
abgr |= b << 10
abgr |= a << 15
return abgr
+
if ffi.sizeof("color_t") == 2:
- def colorToU16(c):
- return c
+ def color_to_u16(color):
+ return color
- colorToU32 = u16ToU32
+ color_to_u32 = u16_to_u32 # pylint: disable=invalid-name
- def u16ToColor(c):
- return c
+ def u16_to_color(color):
+ return color
- u32ToColor = u32ToU16
+ u32_to_color = u32_to_u16 # pylint: disable=invalid-name
else:
- def colorToU32(c):
- return c
+ def color_to_u32(color):
+ return color
- colorToU16 = u32ToU16
+ color_to_u16 = u32_to_u16 # pylint: disable=invalid-name
- def u32ToColor(c):
- return c
+ def u32_to_color(color):
+ return color
- u16ToColor = u16ToU32
+ u16_to_color = u16_to_u32 # pylint: disable=invalid-name
View
@@ -3,17 +3,15 @@
# 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/.
-from ._pylib import ffi, lib
-from . import createCallback
+from ._pylib import ffi, lib # pylint: disable=no-name-in-module
+from . import create_callback
-createCallback("mLoggerPy", "log", "_pyLog")
+create_callback("mLoggerPy", "log", "_pyLog")
-defaultLogger = None
-def installDefault(logger):
- global defaultLogger
- defaultLogger = logger
- lib.mLogSetDefaultLogger(logger._native)
+def install_default(logger):
+ Logger.install_default(logger)
+
class Logger(object):
FATAL = lib.mLOG_FATAL
@@ -24,16 +22,24 @@ class Logger(object):
STUB = lib.mLOG_STUB
GAME_ERROR = lib.mLOG_GAME_ERROR
+ _DEFAULT_LOGGER = None
+
def __init__(self):
self._handle = ffi.new_handle(self)
self._native = ffi.gc(lib.mLoggerPythonCreate(self._handle), lib.free)
@staticmethod
- def categoryName(category):
+ def category_name(category):
return ffi.string(lib.mLogCategoryName(category)).decode('UTF-8')
+ @classmethod
+ def install_default(cls, logger):
+ cls._DEFAULT_LOGGER = logger
+ lib.mLogSetDefaultLogger(logger._native)
+
def log(self, category, level, message):
- print("{}: {}".format(self.categoryName(category), message))
+ print("{}: {}".format(self.category_name(category), message))
+
class NullLogger(Logger):
def log(self, category, level, message):
View
@@ -3,9 +3,11 @@
# 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/.
-from ._pylib import ffi, lib
+from ._pylib import ffi # pylint: disable=no-name-in-module
+
class LR35902Core:
+ # pylint: disable=invalid-name
def __init__(self, native):
self._native = ffi.cast("struct LR35902Core*", native)
View
@@ -3,27 +3,28 @@
# 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/.
-from ._pylib import ffi, lib
+from ._pylib import ffi, lib # pylint: disable=no-name-in-module
+
class MemoryView(object):
def __init__(self, core, width, size, base=0, sign="u"):
self._core = core
self._width = width
self._size = size
self._base = base
- self._busRead = getattr(self._core, "busRead" + str(width * 8))
- self._busWrite = getattr(self._core, "busWrite" + str(width * 8))
- self._rawRead = getattr(self._core, "rawRead" + str(width * 8))
- self._rawWrite = getattr(self._core, "rawWrite" + str(width * 8))
- self._mask = (1 << (width * 8)) - 1 # Used to force values to fit within range so that negative values work
+ self._bus_read = getattr(self._core, "busRead" + str(width * 8))
+ self._bus_write = getattr(self._core, "busWrite" + str(width * 8))
+ self._raw_read = getattr(self._core, "rawRead" + str(width * 8))
+ self._raw_write = getattr(self._core, "rawWrite" + str(width * 8))
+ self._mask = (1 << (width * 8)) - 1 # Used to force values to fit within range so that negative values work
if sign == "u" or sign == "unsigned":
self._type = "uint{}_t".format(width * 8)
elif sign == "i" or sign == "s" or sign == "signed":
self._type = "int{}_t".format(width * 8)
else:
raise ValueError("Invalid sign type: '{}'".format(sign))
- def _addrCheck(self, address):
+ def _addr_check(self, address):
if isinstance(address, slice):
start = address.start or 0
stop = self._size - self._width if address.stop is None else address.stop
@@ -39,33 +40,32 @@ def __len__(self):
return self._size
def __getitem__(self, address):
- self._addrCheck(address)
+ self._addr_check(address)
if isinstance(address, slice):
start = address.start or 0
stop = self._size - self._width if address.stop is None else address.stop
step = address.step or self._width
- return [int(ffi.cast(self._type, self._busRead(self._core, self._base + a))) for a in range(start, stop, step)]
- else:
- return int(ffi.cast(self._type, self._busRead(self._core, self._base + address)))
+ return [int(ffi.cast(self._type, self._bus_read(self._core, self._base + a))) for a in range(start, stop, step)]
+ return int(ffi.cast(self._type, self._bus_read(self._core, self._base + address)))
def __setitem__(self, address, value):
- self._addrCheck(address)
+ self._addr_check(address)
if isinstance(address, slice):
start = address.start or 0
stop = self._size - self._width if address.stop is None else address.stop
step = address.step or self._width
- for a in range(start, stop, step):
- self._busWrite(self._core, self._base + a, value[a] & self._mask)
+ for addr in range(start, stop, step):
+ self._bus_write(self._core, self._base + addr, value[addr] & self._mask)
else:
- self._busWrite(self._core, self._base + address, value & self._mask)
+ self._bus_write(self._core, self._base + address, value & self._mask)
- def rawRead(self, address, segment=-1):
- self._addrCheck(address)
- return int(ffi.cast(self._type, self._rawRead(self._core, self._base + address, segment)))
+ def raw_read(self, address, segment=-1):
+ self._addr_check(address)
+ return int(ffi.cast(self._type, self._raw_read(self._core, self._base + address, segment)))
- def rawWrite(self, address, value, segment=-1):
- self._addrCheck(address)
- self._rawWrite(self._core, self._base + address, segment, value & self._mask)
+ def raw_write(self, address, value, segment=-1):
+ self._addr_check(address)
+ self._raw_write(self._core, self._base + address, segment, value & self._mask)
class MemorySearchResult(object):
@@ -75,12 +75,13 @@ def __init__(self, memory, result):
self.guessDivisor = result.guessDivisor
self.type = result.type
- if result.type == Memory.SEARCH_8:
- self._memory = memory.u8
- elif result.type == Memory.SEARCH_16:
- self._memory = memory.u16
- elif result.type == Memory.SEARCH_32:
- self._memory = memory.u32
+ if result.type == Memory.SEARCH_INT:
+ if result.width == 1:
+ self._memory = memory.u8
+ elif result.width == 2:
+ self._memory = memory.u16
+ elif result.width == 4:
+ self._memory = memory.u32
elif result.type == Memory.SEARCH_STRING:
self._memory = memory.u8
else:
@@ -123,7 +124,7 @@ def __init__(self, core, size, base=0):
self.s32 = MemoryView(core, 4, size, base, "s")
def __len__(self):
- return self._size
+ return self.size
def search(self, value, type=SEARCH_GUESS, flags=RW, limit=10000, old_results=[]):
results = ffi.new("struct mCoreMemorySearchResults*")
@@ -138,11 +139,11 @@ def search(self, value, type=SEARCH_GUESS, flags=RW, limit=10000, old_results=[]
params.valueStr = ffi.new("char[]", str(value).encode("ascii"))
for result in old_results:
- r = lib.mCoreMemorySearchResultsAppend(results)
- r.address = result.address
- r.segment = result.segment
- r.guessDivisor = result.guessDivisor
- r.type = result.type
+ native_result = lib.mCoreMemorySearchResultsAppend(results)
+ native_result.address = result.address
+ native_result.segment = result.segment
+ native_result.guessDivisor = result.guessDivisor
+ native_result.type = result.type
if old_results:
lib.mCoreMemorySearchRepeat(self._core, params, results)
else:
@@ -154,5 +155,4 @@ def search(self, value, type=SEARCH_GUESS, flags=RW, limit=10000, old_results=[]
def __getitem__(self, address):
if isinstance(address, slice):
return bytearray(self.u8[address])
- else:
- return self.u8[address]
+ return self.u8[address]
View
@@ -3,37 +3,41 @@
# 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/.
-from ._pylib import ffi, lib
+from ._pylib import ffi, lib # pylint: disable=no-name-in-module
from . import vfs
MODE_RGB = 0
MODE_RGBA = 1
MODE_INDEX = 2
+
class PNG:
- def __init__(self, f, mode=MODE_RGB):
- self.vf = vfs.open(f)
- self.mode = mode
+ def __init__(self, f, mode=MODE_RGB):
+ self._vfile = vfs.open(f)
+ self._png = None
+ self._info = None
+ self.mode = mode
- def writeHeader(self, image):
- self._png = lib.PNGWriteOpen(self.vf.handle)
- if self.mode == MODE_RGB:
- self._info = lib.PNGWriteHeader(self._png, image.width, image.height)
- if self.mode == MODE_RGBA:
- self._info = lib.PNGWriteHeaderA(self._png, image.width, image.height)
- if self.mode == MODE_INDEX:
- self._info = lib.PNGWriteHeader8(self._png, image.width, image.height)
- return self._info != ffi.NULL
+ def write_header(self, image):
+ self._png = lib.PNGWriteOpen(self._vfile.handle)
+ if self.mode == MODE_RGB:
+ self._info = lib.PNGWriteHeader(self._png, image.width, image.height)
+ if self.mode == MODE_RGBA:
+ self._info = lib.PNGWriteHeaderA(self._png, image.width, image.height)
+ if self.mode == MODE_INDEX:
+ self._info = lib.PNGWriteHeader8(self._png, image.width, image.height)
+ return self._info != ffi.NULL
- def writePixels(self, image):
- if self.mode == MODE_RGB:
- return lib.PNGWritePixels(self._png, image.width, image.height, image.stride, image.buffer)
- if self.mode == MODE_RGBA:
- return lib.PNGWritePixelsA(self._png, image.width, image.height, image.stride, image.buffer)
- if self.mode == MODE_INDEX:
- return lib.PNGWritePixels8(self._png, image.width, image.height, image.stride, image.buffer)
+ def write_pixels(self, image):
+ if self.mode == MODE_RGB:
+ return lib.PNGWritePixels(self._png, image.width, image.height, image.stride, image.buffer)
+ if self.mode == MODE_RGBA:
+ return lib.PNGWritePixelsA(self._png, image.width, image.height, image.stride, image.buffer)
+ if self.mode == MODE_INDEX:
+ return lib.PNGWritePixels8(self._png, image.width, image.height, image.stride, image.buffer)
+ return False
- def writeClose(self):
- lib.PNGWriteClose(self._png, self._info)
- del self._png
- del self._info
+ def write_close(self):
+ lib.PNGWriteClose(self._png, self._info)
+ self._png = None
+ self._info = None
View
@@ -3,9 +3,10 @@
# 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/.
-from ._pylib import ffi, lib
+from ._pylib import ffi, lib # pylint: disable=no-name-in-module
from .core import IRunner, ICoreOwner, Core
+
class ThreadCoreOwner(ICoreOwner):
def __init__(self, thread):
self.thread = thread
@@ -19,12 +20,13 @@ def claim(self):
def release(self):
lib.mCoreThreadContinue(self.thread._native)
+
class Thread(IRunner):
def __init__(self, native=None):
if native:
self._native = native
self._core = Core(native.core)
- self._core._wasReset = lib.mCoreThreadHasStarted(self._native)
+ self._core._was_reset = lib.mCoreThreadHasStarted(self._native)
else:
self._native = ffi.new("struct mCoreThread*")
@@ -34,7 +36,7 @@ def start(self, core):
self._core = core
self._native.core = core._core
lib.mCoreThreadStart(self._native)
- self._core._wasReset = lib.mCoreThreadHasStarted(self._native)
+ self._core._was_reset = lib.mCoreThreadHasStarted(self._native)
def end(self):
if not lib.mCoreThreadHasStarted(self._native):
@@ -48,11 +50,13 @@ def pause(self):
def unpause(self):
lib.mCoreThreadUnpause(self._native)
- def isRunning(self):
+ @property
+ def running(self):
return bool(lib.mCoreThreadIsActive(self._native))
- def isPaused(self):
+ @property
+ def paused(self):
return bool(lib.mCoreThreadIsPaused(self._native))
- def useCore(self):
+ def use_core(self):
return ThreadCoreOwner(self)
View
@@ -3,14 +3,15 @@
# 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/.
-from ._pylib import ffi, lib
+from ._pylib import ffi, lib # pylint: disable=no-name-in-module
from . import image
+
class Tile:
def __init__(self, data):
self.buffer = data
- def toImage(self):
+ def to_image(self):
i = image.Image(8, 8)
self.composite(i, 0, 0)
return i
@@ -19,19 +20,22 @@ def composite(self, i, x, y):
for iy in range(8):
ffi.memmove(ffi.addressof(i.buffer, x + (iy + y) * i.stride), ffi.addressof(self.buffer, iy * 8), 8 * ffi.sizeof("color_t"))
+
class CacheSet:
def __init__(self, core):
self.core = core
- self.cache = ffi.gc(ffi.new("struct mCacheSet*"), core._deinitCache)
- core._initCache(self.cache)
+ self.cache = ffi.gc(ffi.new("struct mCacheSet*"), core._deinit_cache)
+ core._init_cache(self.cache)
+
class TileView:
def __init__(self, cache):
self.cache = cache
- def getTile(self, tile, palette):
+ def get_tile(self, tile, palette):
return Tile(lib.mTileCacheGetTile(self.cache, tile, palette))
+
class MapView:
def __init__(self, cache):
self.cache = cache
@@ -54,6 +58,7 @@ def image(self):
ffi.memmove(ffi.addressof(i.buffer, i.stride * y), row, self.width * 8 * ffi.sizeof("color_t"))
return i
+
class Sprite(object):
def constitute(self, tileView, tilePitch):
i = image.Image(self.width, self.height, alpha=True)
View
@@ -3,139 +3,152 @@
# 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/.
-from ._pylib import ffi, lib
-import mmap
+# pylint: disable=invalid-name,unused-argument
+from ._pylib import ffi, lib # pylint: disable=no-name-in-module
import os
+
@ffi.def_extern()
def _vfpClose(vf):
- vfp = ffi.cast("struct VFilePy*", vf)
- ffi.from_handle(vfp.fileobj).close()
- return True
+ vfp = ffi.cast("struct VFilePy*", vf)
+ ffi.from_handle(vfp.fileobj).close()
+ return True
+
@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()
+ 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)
- ffi.from_handle(vfp.fileobj).readinto(pybuf)
- return size
+ vfp = ffi.cast("struct VFilePy*", vf)
+ pybuf = ffi.buffer(buffer, size)
+ ffi.from_handle(vfp.fileobj).readinto(pybuf)
+ return size
+
@ffi.def_extern()
def _vfpWrite(vf, buffer, size):
- vfp = ffi.cast("struct VFilePy*", vf)
- pybuf = ffi.buffer(buffer, size)
- ffi.from_handle(vfp.fileobj).write(pybuf)
- return size
+ vfp = ffi.cast("struct VFilePy*", vf)
+ pybuf = ffi.buffer(buffer, size)
+ ffi.from_handle(vfp.fileobj).write(pybuf)
+ return size
+
@ffi.def_extern()
def _vfpMap(vf, size, flags):
- pass
+ pass
+
@ffi.def_extern()
def _vfpUnmap(vf, memory, size):
- pass
+ pass
+
@ffi.def_extern()
def _vfpTruncate(vf, size):
- vfp = ffi.cast("struct VFilePy*", vf)
- ffi.from_handle(vfp.fileobj).truncate(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
+ 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
-
- vf = lib.VFileOpen(path.encode("UTF-8"), flags);
- if vf == ffi.NULL:
- return None
- return VFile(vf)
+ 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): # pylint: disable=redefined-builtin
+ handle = ffi.new_handle(f)
+ vf = VFile(lib.VFileFromPython(handle), _no_gc=(f, handle))
+ return vf
+
+
+def open_path(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
+
+ vf = lib.VFileOpen(path.encode("UTF-8"), flags)
+ if vf == ffi.NULL:
+ return None
+ return VFile(vf)
+
class VFile:
- def __init__(self, vf):
- self.handle = vf
+ def __init__(self, vf, _no_gc=None):
+ self.handle = vf
+ self._no_gc = _no_gc
+
+ def __del__(self):
+ self.close()
- def close(self):
- return bool(self.handle.close(self.handle))
+ def close(self):
+ return bool(self.handle.close(self.handle))
- def seek(self, offset, whence):
- return self.handle.seek(self.handle, offset, whence)
+ def seek(self, offset, whence):
+ return self.handle.seek(self.handle, offset, whence)
- def read(self, buffer, size):
- return self.handle.read(self.handle, buffer, size)
+ def read(self, buffer, size):
+ return self.handle.read(self.handle, buffer, size)
- def readAll(self, size=0):
- if not size:
- size = self.size()
- buffer = ffi.new("char[%i]" % size)
- size = self.handle.read(self.handle, buffer, size)
- return ffi.unpack(buffer, size)
+ def read_all(self, size=0):
+ if not size:
+ size = self.size()
+ buffer = ffi.new("char[%i]" % size)
+ size = self.handle.read(self.handle, buffer, size)
+ return ffi.unpack(buffer, size)
- def readline(self, buffer, size):
- return self.handle.readline(self.handle, buffer, size)
+ def readline(self, buffer, size):
+ return self.handle.readline(self.handle, buffer, size)
- def write(self, buffer, size):
- return self.handle.write(self.handle, buffer, size)
+ def write(self, buffer, size):
+ return self.handle.write(self.handle, buffer, size)
- def map(self, size, flags):
- return self.handle.map(self.handle, size, flags)
+ def map(self, size, flags):
+ return self.handle.map(self.handle, size, flags)
- def unmap(self, memory, size):
- self.handle.unmap(self.handle, memory, size)
+ def unmap(self, memory, size):
+ self.handle.unmap(self.handle, memory, size)
- def truncate(self, size):
- self.handle.truncate(self.handle, size)
+ def truncate(self, size):
+ self.handle.truncate(self.handle, size)
- def size(self):
- return self.handle.size(self.handle)
+ def size(self):
+ return self.handle.size(self.handle)
- def sync(self, buffer, size):
- return self.handle.sync(self.handle, buffer, size)
+ def sync(self, buffer, size):
+ return self.handle.sync(self.handle, buffer, size)
View
@@ -1,2 +1,6 @@
[aliases]
test=pytest
+
+[pycodestyle]
+exclude = .eggs
+ignore = E501,E741,E743
View
@@ -0,0 +1,38 @@
+from setuptools import setup
+import re
+import os
+import os.path
+import sys
+import subprocess
+
+
+def get_version_component(piece):
+ return subprocess.check_output(['cmake', '-DPRINT_STRING={}'.format(piece), '-P', '../../../version.cmake']).decode('utf-8').strip()
+
+
+version = '{}.{}.{}'.format(*(get_version_component(p) for p in ('LIB_VERSION_MAJOR', 'LIB_VERSION_MINOR', 'LIB_VERSION_PATCH')))
+if not get_version_component('GIT_TAG'):
+ version += '.{}+g{}'.format(*(get_version_component(p) for p in ('GIT_REV', 'GIT_COMMIT_SHORT')))
+
+setup(
+ name="mgba",
+ version=version,
+ author="Jeffrey Pfau",
+ author_email="jeffrey@endrift.com",
+ url="http://github.com/mgba-emu/mgba/",
+ packages=["mgba"],
+ setup_requires=['cffi>=1.6', 'pytest-runner'],
+ install_requires=['cffi>=1.6', 'cached-property'],
+ extras_require={'pil': ['Pillow>=2.3'], 'cinema': ['pyyaml', 'pytest']},
+ tests_require=['pytest'],
+ cffi_modules=["_builder.py:ffi"],
+ license="MPL 2.0",
+ classifiers=[
+ "Programming Language :: C",
+ "Programming Language :: Python :: 2",
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
+ "Topic :: Games/Entertainment",
+ "Topic :: System :: Emulators"
+ ]
+)
View
@@ -4,7 +4,7 @@
import os.path
import yaml
-mgba.log.installDefault(mgba.log.NullLogger())
+mgba.log.install_default(mgba.log.NullLogger())
def flatten(d):
l = []
@@ -18,7 +18,7 @@ def flatten(d):
def pytest_generate_tests(metafunc):
if 'vtest' in metafunc.fixturenames:
- tests = cinema.test.gatherTests(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'cinema'))
+ tests = cinema.test.gather_tests(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'cinema'))
testList = flatten(tests)
params = []
for test in testList:
@@ -34,9 +34,9 @@ def vtest(request):
return request.param
def test_video(vtest, pytestconfig):
- vtest.setUp()
+ vtest.setup()
if pytestconfig.getoption('--rebaseline'):
- vtest.generateBaseline()
+ vtest.generate_baseline()
else:
try:
vtest.test()
View
@@ -4,26 +4,30 @@
import mgba.vfs as vfs
from mgba._pylib import ffi
+
def test_vfs_open():
with open(__file__) as f:
vf = vfs.open(f)
assert vf
assert vf.close()
-def test_vfs_openPath():
- vf = vfs.openPath(__file__)
+
+def test_vfs_open_path():
+ vf = vfs.open_path(__file__)
assert vf
assert vf.close()
+
def test_vfs_read():
- vf = vfs.openPath(__file__)
+ vf = vfs.open_path(__file__)
buffer = ffi.new('char[13]')
assert vf.read(buffer, 13) == 13
assert ffi.string(buffer) == b'import pytest'
vf.close()
+
def test_vfs_readline():
- vf = vfs.openPath(__file__)
+ vf = vfs.open_path(__file__)
buffer = ffi.new('char[16]')
linelen = vf.readline(buffer, 16)
assert linelen in (14, 15)
@@ -33,16 +37,18 @@ def test_vfs_readline():
assert ffi.string(buffer) == b'import pytest\r\n'
vf.close()
-def test_vfs_readAllSize():
- vf = vfs.openPath(__file__)
- buffer = vf.readAll()
+
+def test_vfs_read_all_size():
+ vf = vfs.open_path(__file__)
+ buffer = vf.read_all()
assert buffer
assert len(buffer)
assert len(buffer) == vf.size()
vf.close()
+
def test_vfs_seek():
- vf = vfs.openPath(__file__)
+ vf = vfs.open_path(__file__)
assert vf.seek(0, os.SEEK_SET) == 0
assert vf.seek(1, os.SEEK_SET) == 1
assert vf.seek(1, os.SEEK_CUR) == 2
@@ -52,6 +58,7 @@ def test_vfs_seek():
assert vf.seek(-1, os.SEEK_END) == vf.size() -1
vf.close()
-def test_vfs_openPath_invalid():
- vf = vfs.openPath('.invalid')
+
+def test_vfs_open_path_invalid():
+ vf = vfs.open_path('.invalid')
assert not vf
View
@@ -47,7 +47,7 @@ if(NOT GIT_BRANCH)
endif()
if(DEFINED PRINT_STRING)
- message("${${PRINT_STRING}}")
+ execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${${PRINT_STRING}}")
elseif(NOT VERSION_STRING_CACHE OR NOT VERSION_STRING STREQUAL VERSION_STRING_CACHE)
set(VERSION_STRING_CACHE ${VERSION_STRING} CACHE STRING "" FORCE)