mirror of https://github.com/mgba-emu/mgba.git
Python: Add callbacks
This commit is contained in:
parent
25b4faef12
commit
d1ef27cff9
|
@ -10,17 +10,20 @@ include(FindPythonLibs)
|
|||
list(APPEND DEPENDENCY_LIB ${PYTHON_LIBRARIES})
|
||||
include_directories(AFTER ${PYTHON_INCLUDE_DIRS})
|
||||
|
||||
file(GLOB PYTHON_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py)
|
||||
add_custom_command(OUTPUT build/lib/${BINARY_NAME}/__init__.py
|
||||
COMMAND BINDIR=${CMAKE_CURRENT_BINARY_DIR}/.. CPPFLAGS="${INCLUDE_FLAGS}" ${PYTHON} ${CMAKE_CURRENT_BINARY_DIR}/setup.py build --build-base ${CMAKE_CURRENT_BINARY_DIR}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DEPENDS ${BINARY_NAME}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/setup.py
|
||||
DEPENDS ${PYTHON_HEADERS}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py)
|
||||
|
||||
add_custom_command(OUTPUT lib.c
|
||||
COMMAND BINDIR=${CMAKE_CURRENT_BINARY_DIR}/.. CPPFLAGS="${INCLUDE_FLAGS}" ${PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/lib.h
|
||||
DEPENDS ${PYTHON_HEADERS}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py)
|
||||
|
||||
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/lib.c PROPERTIES GENERATED ON)
|
||||
|
|
|
@ -35,6 +35,7 @@ void free(void*);
|
|||
#include <mgba/core/version.h>
|
||||
|
||||
#define PYEXPORT extern "Python+C"
|
||||
#include "platform/python/core.h"
|
||||
#include "platform/python/log.h"
|
||||
#include "platform/python/sio.h"
|
||||
#include "platform/python/vfs-py.h"
|
||||
|
|
|
@ -38,6 +38,7 @@ ffi.set_source("mgba._pylib", """
|
|||
#include <mgba-util/vfs.h>
|
||||
|
||||
#define PYEXPORT
|
||||
#include "platform/python/core.h"
|
||||
#include "platform/python/log.h"
|
||||
#include "platform/python/sio.h"
|
||||
#include "platform/python/vfs-py.h"
|
||||
|
@ -46,7 +47,7 @@ ffi.set_source("mgba._pylib", """
|
|||
extra_compile_args=cppflags,
|
||||
libraries=["mgba"],
|
||||
library_dirs=[bindir],
|
||||
sources=[os.path.join(pydir, path) for path in ["vfs-py.c", "log.c", "sio.c"]])
|
||||
sources=[os.path.join(pydir, path) for path in ["vfs-py.c", "core.c", "log.c", "sio.c"]])
|
||||
|
||||
preprocessed = subprocess.check_output(cpp + ["-fno-inline", "-P"] + cppflags + [os.path.join(pydir, "_builder.h")], universal_newlines=True)
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/* 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 "core.h"
|
||||
|
||||
#include <mgba/core/core.h>
|
||||
|
||||
struct mCoreCallbacks* mCorePythonCallbackCreate(void* pyobj) {
|
||||
struct mCoreCallbacks* callbacks = malloc(sizeof(*callbacks));
|
||||
callbacks->videoFrameStarted = _mCorePythonCallbacksVideoFrameStarted;
|
||||
callbacks->videoFrameEnded = _mCorePythonCallbacksVideoFrameEnded;
|
||||
callbacks->coreCrashed = _mCorePythonCallbacksCoreCrashed;
|
||||
callbacks->sleep = _mCorePythonCallbacksSleep;
|
||||
|
||||
callbacks->context = pyobj;
|
||||
return callbacks;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/* 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-util/common.h>
|
||||
|
||||
#include "pycommon.h"
|
||||
|
||||
struct mCoreCallbacks* mCorePythonCallbackCreate(void* pyobj);
|
||||
|
||||
PYEXPORT void _mCorePythonCallbacksVideoFrameStarted(void* user);
|
||||
PYEXPORT void _mCorePythonCallbacksVideoFrameEnded(void* user);
|
||||
PYEXPORT void _mCorePythonCallbacksCoreCrashed(void* user);
|
||||
PYEXPORT void _mCorePythonCallbacksSleep(void* user);
|
|
@ -3,14 +3,7 @@
|
|||
* 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/core/log.h>
|
||||
|
||||
struct mLoggerPy {
|
||||
struct mLogger d;
|
||||
void* pyobj;
|
||||
};
|
||||
|
||||
void _pyLog(void* logger, int category, enum mLogLevel level, const char* message);
|
||||
#include "log.h"
|
||||
|
||||
static void _pyLogShim(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {
|
||||
struct mLoggerPy* pylogger = (struct mLoggerPy*) logger;
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <mgba/core/log.h>
|
||||
|
||||
#include "pycommon.h"
|
||||
|
||||
struct mLoggerPy {
|
||||
struct mLogger d;
|
||||
void* pyobj;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# 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
|
||||
from . import tile, createCallback
|
||||
from cached_property import cached_property
|
||||
|
||||
def find(path):
|
||||
|
@ -45,11 +45,58 @@ def protected(f):
|
|||
return f(self, *args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
@ffi.def_extern()
|
||||
def _mCorePythonCallbacksVideoFrameStarted(user):
|
||||
context = ffi.from_handle(user)
|
||||
context._videoFrameStarted()
|
||||
|
||||
@ffi.def_extern()
|
||||
def _mCorePythonCallbacksVideoFrameEnded(user):
|
||||
context = ffi.from_handle(user)
|
||||
context._videoFrameEnded()
|
||||
|
||||
@ffi.def_extern()
|
||||
def _mCorePythonCallbacksCoreCrashed(user):
|
||||
context = ffi.from_handle(user)
|
||||
context._coreCrashed()
|
||||
|
||||
@ffi.def_extern()
|
||||
def _mCorePythonCallbacksSleep(user):
|
||||
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.sleep = []
|
||||
self.context = lib.mCorePythonCallbackCreate(self._handle)
|
||||
|
||||
def _videoFrameStarted(self):
|
||||
for cb in self.videoFrameStarted:
|
||||
cb()
|
||||
|
||||
def _videoFrameEnded(self):
|
||||
for cb in self.videoFrameEnded:
|
||||
cb()
|
||||
|
||||
def _coreCrashed(self):
|
||||
for cb in self.coreCrashed:
|
||||
cb()
|
||||
|
||||
def _sleep(self):
|
||||
for cb in self.sleep:
|
||||
cb()
|
||||
|
||||
class Core(object):
|
||||
def __init__(self, native):
|
||||
self._core = native
|
||||
self._wasReset = False
|
||||
self._protected = False
|
||||
self._callbacks = CoreCallbacks()
|
||||
self._core.addCoreCallbacks(self._core, self._callbacks.context)
|
||||
|
||||
@cached_property
|
||||
def tiles(self):
|
||||
|
@ -150,26 +197,34 @@ class Core(object):
|
|||
def clearKeys(self, *args, **kwargs):
|
||||
self._core.clearKeys(self._core, self._keysToInt(*args, **kwargs))
|
||||
|
||||
@property
|
||||
@needsReset
|
||||
def frameCounter(self):
|
||||
return self._core.frameCounter(self._core)
|
||||
|
||||
@property
|
||||
def frameCycles(self):
|
||||
return self._core.frameCycles(self._core)
|
||||
|
||||
@property
|
||||
def frequency(self):
|
||||
return self._core.frequency(self._core)
|
||||
|
||||
def getGameTitle(self):
|
||||
@property
|
||||
def gameTitle(self):
|
||||
title = ffi.new("char[16]")
|
||||
self._core.getGameTitle(self._core, title)
|
||||
return ffi.string(title, 16).decode("ascii")
|
||||
|
||||
def getGameCode(self):
|
||||
@property
|
||||
def gameCode(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)
|
||||
|
||||
class ICoreOwner(object):
|
||||
def claim(self):
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/* 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/. */
|
||||
#ifndef PYTHON_COMMON_H
|
||||
#define PYTHON_COMMON_H
|
||||
|
||||
#include <mgba-util/common.h>
|
||||
|
||||
#ifndef PYEXPORT
|
||||
#define PYEXPORT extern
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -3,22 +3,7 @@
|
|||
* 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-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);
|
||||
#include "vfs-py.h"
|
||||
|
||||
struct VFile* VFileFromPython(void* fileobj) {
|
||||
if (!fileobj) {
|
||||
|
|
|
@ -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/. */
|
||||
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
#include "pycommon.h"
|
||||
|
||||
struct VFilePy {
|
||||
struct VFile d;
|
||||
void* fileobj;
|
||||
|
|
Loading…
Reference in New Issue