From 362c572009ac74f34eda03b4b4b7b5f93faa1daf Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 31 May 2017 22:40:03 -0700 Subject: [PATCH] Python: Add GB SIO --- include/mgba/gb/interface.h | 9 +++++ include/mgba/internal/gb/sio.h | 10 +---- src/platform/python/mgba/gb.py | 45 ++++++++++++++++++++++- src/platform/python/sio.c | 67 ++++++++++++++++++++++++---------- src/platform/python/sio.h | 18 +++++++++ 5 files changed, 119 insertions(+), 30 deletions(-) diff --git a/include/mgba/gb/interface.h b/include/mgba/gb/interface.h index 098a5e5dd..03b836865 100644 --- a/include/mgba/gb/interface.h +++ b/include/mgba/gb/interface.h @@ -34,6 +34,15 @@ enum GBMemoryBankControllerType { GB_MBC5_RUMBLE = 0x105 }; +struct GBSIODriver { + struct GBSIO* p; + + bool (*init)(struct GBSIODriver* driver); + void (*deinit)(struct GBSIODriver* driver); + void (*writeSB)(struct GBSIODriver* driver, uint8_t value); + uint8_t (*writeSC)(struct GBSIODriver* driver, uint8_t value); +}; + CXX_GUARD_END #endif diff --git a/include/mgba/internal/gb/sio.h b/include/mgba/internal/gb/sio.h index 004cf16e8..50d62868b 100644 --- a/include/mgba/internal/gb/sio.h +++ b/include/mgba/internal/gb/sio.h @@ -12,6 +12,7 @@ CXX_GUARD_START #include #include +#include #define MAX_GBS 2 @@ -34,15 +35,6 @@ struct GBSIO { uint8_t pendingSB; }; -struct GBSIODriver { - struct GBSIO* p; - - bool (*init)(struct GBSIODriver* driver); - void (*deinit)(struct GBSIODriver* driver); - void (*writeSB)(struct GBSIODriver* driver, uint8_t value); - uint8_t (*writeSC)(struct GBSIODriver* driver, uint8_t value); -}; - DECL_BITFIELD(GBRegisterSC, uint8_t); DECL_BIT(GBRegisterSC, ShiftClock, 0); DECL_BIT(GBRegisterSC, ClockSpeed, 1); diff --git a/src/platform/python/mgba/gb.py b/src/platform/python/mgba/gb.py index 0caf7ec99..2b490e008 100644 --- a/src/platform/python/mgba/gb.py +++ b/src/platform/python/mgba/gb.py @@ -1,4 +1,4 @@ -# Copyright (c) 2013-2016 Jeffrey Pfau +# Copyright (c) 2013-2017 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 @@ -8,6 +8,7 @@ from .lr35902 import LR35902Core from .core import Core, needsReset from .memory import Memory from .tile import Sprite +from . import createCallback class GB(Core): KEY_A = lib.GBA_KEY_A @@ -34,6 +35,48 @@ class GB(Core): self._native.video.renderer.cache = ffi.NULL lib.mTileCacheDeinit(cache) + def attachSIO(self, link): + lib.GBSIOSetDriver(ffi.addressof(self._native.sio), link._native) + +createCallback("GBSIOPythonDriver", "init") +createCallback("GBSIOPythonDriver", "deinit") +createCallback("GBSIOPythonDriver", "writeSB") +createCallback("GBSIOPythonDriver", "writeSC") + +class GBSIODriver(object): + def __init__(self): + self._handle = ffi.new_handle(self) + self._native = ffi.gc(lib.GBSIOPythonDriverCreate(self._handle), lib.free) + + def init(self): + return True + + def deinit(self): + pass + + def writeSB(self, value): + pass + + def writeSC(self, value): + return value + +class GBSIOSimpleDriver(GBSIODriver): + def __init__(self): + super(GBSIOSimpleDriver, self).__init__() + self.tx = 0xFF + self.rx = 0xFF + + def writeSB(self, value): + self.rx = value + + def schedule(self, period=0x100, when=0): + self._native.p.remainingBits = 8 + self._native.p.period = period + self._native.p.pendingSB = self.tx + self.tx = 0xFF + 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), when) + class GBMemory(Memory): def __init__(self, core): super(GBMemory, self).__init__(core, 0x10000) diff --git a/src/platform/python/sio.c b/src/platform/python/sio.c index 1e5928689..a7cba8973 100644 --- a/src/platform/python/sio.c +++ b/src/platform/python/sio.c @@ -3,36 +3,36 @@ * 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 - #include "flags.h" +#define CREATE_SHIM(PLAT, NAME, RETURN) \ + RETURN _py ## PLAT ## SIOPythonDriver ## NAME (void* driver); \ + static RETURN _py ## PLAT ## SIOPythonDriver ## NAME ## Shim(struct PLAT ## SIODriver* driver) { \ + struct PLAT ## SIODriver* py = (struct PLAT ## SIODriver*) driver; \ + return _py ## PLAT ## SIOPythonDriver ## NAME(py); \ + } + +#define CREATE_SHIM_ARGS(PLAT, NAME, RETURN, TYPES, ...) \ + RETURN _py ## PLAT ## SIOPythonDriver ## NAME TYPES; \ + static RETURN _py ## PLAT ## SIOPythonDriver ## NAME ## Shim TYPES { \ + struct PLAT ## SIODriver* py = (struct PLAT ## SIODriver*) driver; \ + return _py ## PLAT ## SIOPythonDriver ## NAME(py, __VA_ARGS__); \ + } + #ifdef M_CORE_GBA -#define CREATE_SHIM(NAME, RETURN) \ - RETURN _pyGBASIOPythonDriver ## NAME (void* driver); \ - static RETURN _pyGBASIOPythonDriver ## NAME ## Shim(struct GBASIODriver* driver) { \ - struct GBASIODriver* py = (struct GBASIODriver*) driver; \ - return _pyGBASIOPythonDriver ## NAME(py); \ - } - -#define CREATE_SHIM_ARGS(NAME, RETURN, TYPES, ...) \ - RETURN _pyGBASIOPythonDriver ## NAME TYPES; \ - static RETURN _pyGBASIOPythonDriver ## NAME ## Shim TYPES { \ - struct GBASIODriver* py = (struct GBASIODriver*) driver; \ - return _pyGBASIOPythonDriver ## NAME(py, __VA_ARGS__); \ - } +#include struct GBASIOPythonDriver { struct GBASIODriver d; void* pyobj; }; -CREATE_SHIM(Init, bool); -CREATE_SHIM(Deinit, void); -CREATE_SHIM(Load, bool); -CREATE_SHIM(Unload, bool); -CREATE_SHIM_ARGS(WriteRegister, uint16_t, (struct GBASIODriver* driver, uint32_t address, uint16_t value), address, value); +CREATE_SHIM(GBA, Init, bool); +CREATE_SHIM(GBA, Deinit, void); +CREATE_SHIM(GBA, Load, bool); +CREATE_SHIM(GBA, Unload, bool); +CREATE_SHIM_ARGS(GBA, WriteRegister, uint16_t, (struct GBASIODriver* driver, uint32_t address, uint16_t value), address, value); struct GBASIODriver* GBASIOPythonDriverCreate(void* pyobj) { struct GBASIOPythonDriver* driver = malloc(sizeof(*driver)); @@ -47,3 +47,30 @@ struct GBASIODriver* GBASIOPythonDriverCreate(void* pyobj) { } #endif + +#ifdef M_CORE_GB + +#include + +struct GBSIOPythonDriver { + struct GBSIODriver d; + void* pyobj; +}; + +CREATE_SHIM(GB, Init, bool); +CREATE_SHIM(GB, Deinit, void); +CREATE_SHIM_ARGS(GB, WriteSB, void, (struct GBSIODriver* driver, uint8_t value), value); +CREATE_SHIM_ARGS(GB, WriteSC, uint8_t, (struct GBSIODriver* driver, uint8_t value), value); + +struct GBSIODriver* GBSIOPythonDriverCreate(void* pyobj) { + struct GBSIOPythonDriver* driver = malloc(sizeof(*driver)); + driver->d.init = _pyGBSIOPythonDriverInitShim; + driver->d.deinit = _pyGBSIOPythonDriverDeinitShim; + driver->d.writeSB = _pyGBSIOPythonDriverWriteSBShim; + driver->d.writeSC = _pyGBSIOPythonDriverWriteSCShim; + + driver->pyobj = pyobj; + return &driver->d; +} + +#endif diff --git a/src/platform/python/sio.h b/src/platform/python/sio.h index 919d2f596..0403fdfd9 100644 --- a/src/platform/python/sio.h +++ b/src/platform/python/sio.h @@ -21,3 +21,21 @@ PYEXPORT bool _pyGBASIOPythonDriverUnload(void* driver); PYEXPORT uint16_t _pyGBASIOPythonDriverWriteRegister(void* driver, uint32_t address, uint16_t value); #endif + +#ifdef M_CORE_GB + +#include + +struct GBSIOPythonDriver { + struct GBSIODriver d; + void* pyobj; +}; + +struct GBSIODriver* GBSIOPythonDriverCreate(void* pyobj); + +PYEXPORT bool _pyGBSIOPythonDriverInit(void* driver); +PYEXPORT void _pyGBSIOPythonDriverDeinit(void* driver); +PYEXPORT void _pyGBSIOPythonDriverWriteSB(void* driver, uint8_t value); +PYEXPORT uint8_t _pyGBSIOPythonDriverWriteSC(void* driver, uint8_t value); + +#endif