mirror of https://github.com/mgba-emu/mgba.git
GBA SIO: Add generic JOY bus implementation, Python bindings
This commit is contained in:
parent
5d72a2be9d
commit
63d7927b60
|
@ -55,7 +55,7 @@ file(GLOB UTIL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/*.[cSs])
|
|||
file(GLOB UTIL_TEST_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/test/*.c)
|
||||
file(GLOB GUI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/gui/*.c ${CMAKE_CURRENT_SOURCE_DIR}/src/feature/gui/*.c)
|
||||
file(GLOB GBA_RENDERER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/renderers/*.c)
|
||||
file(GLOB GBA_SIO_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/sio/lockstep.c)
|
||||
file(GLOB GBA_SIO_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/sio/*.c)
|
||||
file(GLOB GBA_EXTRA_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/extra/*.c)
|
||||
file(GLOB GB_SIO_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/sio/*.c)
|
||||
file(GLOB GB_RENDERER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/renderers/*.c)
|
||||
|
|
|
@ -21,6 +21,13 @@ enum GBASIOMode {
|
|||
SIO_JOYBUS = 12
|
||||
};
|
||||
|
||||
enum GBASIOJOYCommand {
|
||||
JOY_RESET = 0xFF,
|
||||
JOY_POLL = 0x00,
|
||||
JOY_TRANS = 0x14,
|
||||
JOY_RECV = 0x15
|
||||
};
|
||||
|
||||
struct GBA;
|
||||
struct GBAAudio;
|
||||
struct GBASIO;
|
||||
|
@ -48,6 +55,10 @@ struct GBASIODriver {
|
|||
uint16_t (*writeRegister)(struct GBASIODriver* driver, uint32_t address, uint16_t value);
|
||||
};
|
||||
|
||||
void GBASIOJOYCreate(struct GBASIODriver* sio);
|
||||
int GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data);
|
||||
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/* 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
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/internal/gba/sio.h>
|
||||
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
#include <mgba/internal/gba/io.h>
|
||||
|
||||
static uint16_t GBASIOJOYWriteRegister(struct GBASIODriver* sio, uint32_t address, uint16_t value);
|
||||
|
||||
void GBASIOJOYCreate(struct GBASIODriver* sio) {
|
||||
sio->init = NULL;
|
||||
sio->deinit = NULL;
|
||||
sio->load = NULL;
|
||||
sio->unload = NULL;
|
||||
sio->writeRegister = GBASIOJOYWriteRegister;
|
||||
}
|
||||
|
||||
uint16_t GBASIOJOYWriteRegister(struct GBASIODriver* sio, uint32_t address, uint16_t value) {
|
||||
switch (address) {
|
||||
case REG_JOYCNT:
|
||||
return (value & 0x0040) | (sio->p->p->memory.io[REG_JOYCNT >> 1] & ~(value & 0x7) & ~0x0040);
|
||||
case REG_JOYSTAT:
|
||||
return (value & 0x0030) | (sio->p->p->memory.io[REG_JOYSTAT >> 1] & ~0x30);
|
||||
case REG_JOY_TRANS_LO:
|
||||
case REG_JOY_TRANS_HI:
|
||||
sio->p->p->memory.io[REG_JOYSTAT >> 1] |= 8;
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data) {
|
||||
switch (command) {
|
||||
case JOY_RESET:
|
||||
sio->p->p->memory.io[REG_JOYCNT >> 1] |= 1;
|
||||
if (sio->p->p->memory.io[REG_JOYCNT >> 1] & 0x40) {
|
||||
GBARaiseIRQ(sio->p->p, IRQ_SIO);
|
||||
}
|
||||
// Fall through
|
||||
case JOY_POLL:
|
||||
data[0] = 0x00;
|
||||
data[1] = 0x04;
|
||||
data[2] = sio->p->p->memory.io[REG_JOYSTAT >> 1];
|
||||
return 3;
|
||||
case JOY_RECV:
|
||||
sio->p->p->memory.io[REG_JOYCNT >> 1] |= 2;
|
||||
sio->p->p->memory.io[REG_JOYSTAT >> 1] |= 2;
|
||||
|
||||
sio->p->p->memory.io[REG_JOY_RECV_LO >> 1] = data[0] | (data[1] << 8);
|
||||
sio->p->p->memory.io[REG_JOY_RECV_HI >> 1] = data[2] | (data[3] << 8);
|
||||
|
||||
data[0] = sio->p->p->memory.io[REG_JOYSTAT >> 1];
|
||||
|
||||
if (sio->p->p->memory.io[REG_JOYCNT >> 1] & 0x40) {
|
||||
GBARaiseIRQ(sio->p->p, IRQ_SIO);
|
||||
}
|
||||
return 1;
|
||||
case JOY_TRANS:
|
||||
sio->p->p->memory.io[REG_JOYCNT >> 1] |= 4;
|
||||
sio->p->p->memory.io[REG_JOYSTAT >> 1] &= ~8;
|
||||
data[0] = sio->p->p->memory.io[REG_JOY_TRANS_LO >> 1];
|
||||
data[1] = sio->p->p->memory.io[REG_JOY_TRANS_LO >> 1] >> 8;
|
||||
data[2] = sio->p->p->memory.io[REG_JOY_TRANS_HI >> 1];
|
||||
data[3] = sio->p->p->memory.io[REG_JOY_TRANS_HI >> 1] >> 8;
|
||||
data[4] = sio->p->p->memory.io[REG_JOYSTAT >> 1];
|
||||
|
||||
if (sio->p->p->memory.io[REG_JOYCNT >> 1] & 0x40) {
|
||||
GBARaiseIRQ(sio->p->p, IRQ_SIO);
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -53,6 +53,7 @@ void free(void*);
|
|||
#include <mgba-util/png-io.h>
|
||||
#endif
|
||||
#ifdef M_CORE_GBA
|
||||
#include <mgba/gba/interface.h>
|
||||
#include <mgba/internal/arm/arm.h>
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
#include <mgba/internal/gba/input.h>
|
||||
|
|
|
@ -30,6 +30,7 @@ ffi.set_source("mgba._pylib", """
|
|||
#include <mgba/core/thread.h>
|
||||
#include <mgba/core/version.h>
|
||||
#include <mgba/debugger/debugger.h>
|
||||
#include <mgba/gba/interface.h>
|
||||
#include <mgba/internal/arm/arm.h>
|
||||
#include <mgba/internal/debugger/cli-debugger.h>
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
|
|
|
@ -26,6 +26,7 @@ class GBA(Core):
|
|||
SIO_NORMAL_32 = lib.SIO_NORMAL_32
|
||||
SIO_MULTI = lib.SIO_MULTI
|
||||
SIO_UART = lib.SIO_UART
|
||||
SIO_JOYBUS = lib.SIO_JOYBUS
|
||||
SIO_GPIO = lib.SIO_GPIO
|
||||
|
||||
def __init__(self, native):
|
||||
|
@ -83,6 +84,32 @@ class GBASIODriver(object):
|
|||
def writeRegister(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)
|
||||
self._native = ffi.gc(lib.GBASIOJOYPythonDriverCreate(self._handle), lib.free)
|
||||
|
||||
def sendCommand(self, cmd, data):
|
||||
buffer = ffi.new('uint8_t[5]')
|
||||
try:
|
||||
buffer[0] = data[0]
|
||||
buffer[1] = data[1]
|
||||
buffer[2] = data[2]
|
||||
buffer[3] = data[3]
|
||||
buffer[4] = data[4]
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
outlen = lib.GBASIOJOYSendCommand(self._native, cmd, buffer)
|
||||
if outlen > 0 and outlen <= 5:
|
||||
return bytes(buffer[0:outlen])
|
||||
return None
|
||||
|
||||
class GBAMemory(Memory):
|
||||
def __init__(self, core, romSize=lib.SIZE_CART0):
|
||||
super(GBAMemory, self).__init__(core, 0x100000000)
|
||||
|
|
|
@ -46,6 +46,18 @@ struct GBASIODriver* GBASIOPythonDriverCreate(void* pyobj) {
|
|||
return &driver->d;
|
||||
}
|
||||
|
||||
struct GBASIODriver* GBASIOJOYPythonDriverCreate(void* pyobj) {
|
||||
struct GBASIOPythonDriver* driver = malloc(sizeof(*driver));
|
||||
GBASIOJOYCreate(&driver->d);
|
||||
driver->d.init = _pyGBASIOPythonDriverInitShim;
|
||||
driver->d.deinit = _pyGBASIOPythonDriverDeinitShim;
|
||||
driver->d.load = _pyGBASIOPythonDriverLoadShim;
|
||||
driver->d.unload = _pyGBASIOPythonDriverUnloadShim;
|
||||
|
||||
driver->pyobj = pyobj;
|
||||
return &driver->d;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
|
|
|
@ -13,6 +13,7 @@ struct GBASIOPythonDriver {
|
|||
};
|
||||
|
||||
struct GBASIODriver* GBASIOPythonDriverCreate(void* pyobj);
|
||||
struct GBASIODriver* GBASIOJOYPythonDriverCreate(void* pyobj);
|
||||
|
||||
PYEXPORT bool _pyGBASIOPythonDriverInit(void* driver);
|
||||
PYEXPORT void _pyGBASIOPythonDriverDeinit(void* driver);
|
||||
|
|
Loading…
Reference in New Issue