mirror of https://github.com/mgba-emu/mgba.git
Python: Preliminary, incomplete bindings
This commit is contained in:
parent
4ac4733cfd
commit
e5c61e0093
|
@ -28,6 +28,7 @@ set(BUILD_PERF OFF CACHE BOOL "Build performance profiling tool")
|
|||
set(BUILD_TEST OFF CACHE BOOL "Build testing harness")
|
||||
set(BUILD_SUITE OFF CACHE BOOL "Build test suite")
|
||||
set(BUILD_EXAMPLE OFF CACHE BOOL "Build example frontends")
|
||||
set(BUILD_PYTHON OFF CACHE BOOL "Build Python bindings")
|
||||
set(BUILD_STATIC OFF CACHE BOOL "Build a static library")
|
||||
set(BUILD_SHARED ON CACHE BOOL "Build a shared library")
|
||||
set(SKIP_LIBRARY OFF CACHE BOOL "Skip building the library (useful for only building libretro or OpenEmu cores)")
|
||||
|
@ -750,6 +751,11 @@ if(BUILD_SUITE)
|
|||
add_test(${BINARY_NAME}-suite ${BINARY_NAME}-suite)
|
||||
endif()
|
||||
|
||||
if(BUILD_PYTHON)
|
||||
enable_testing()
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/python ${CMAKE_CURRENT_BINARY_DIR}/python)
|
||||
endif()
|
||||
|
||||
if(BUILD_EXAMPLE)
|
||||
add_executable(${BINARY_NAME}-example-server ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/example/client-server/server.c)
|
||||
target_link_libraries(${BINARY_NAME}-example-server ${BINARY_NAME})
|
||||
|
@ -833,6 +839,7 @@ if(NOT QUIET)
|
|||
message(STATUS " Profiling: ${BUILD_PERF}")
|
||||
message(STATUS " Test harness: ${BUILD_TEST}")
|
||||
message(STATUS " Test suite: ${BUILD_SUITE}")
|
||||
message(STATUS " Python bindings: ${BUILD_PYTHON}")
|
||||
message(STATUS " Examples: ${BUILD_EXAMPLE}")
|
||||
message(STATUS "Cores:")
|
||||
message(STATUS " Libretro core: ${BUILD_LIBRETRO}")
|
||||
|
|
|
@ -73,7 +73,7 @@ union PSR {
|
|||
unsigned z : 1;
|
||||
unsigned c : 1;
|
||||
unsigned v : 1;
|
||||
unsigned : 20;
|
||||
unsigned unused : 20;
|
||||
unsigned i : 1;
|
||||
unsigned f : 1;
|
||||
unsigned t : 1;
|
||||
|
@ -83,7 +83,7 @@ union PSR {
|
|||
unsigned t : 1;
|
||||
unsigned f : 1;
|
||||
unsigned i : 1;
|
||||
unsigned : 20;
|
||||
unsigned unused : 20;
|
||||
unsigned v : 1;
|
||||
unsigned c : 1;
|
||||
unsigned z : 1;
|
||||
|
|
|
@ -44,4 +44,18 @@ const char* mLogCategoryName(int category) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void mLog(int category, enum mLogLevel level, const char* format, ...) {
|
||||
struct mLogger* context = mLogGetContext();
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
if (context) {
|
||||
context->log(context, category, level, format, args);
|
||||
} else {
|
||||
printf("%s: ", mLogCategoryName(category));
|
||||
vprintf(format, args);
|
||||
printf("\n");
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
mLOG_DEFINE_CATEGORY(STATUS, "Status")
|
||||
|
|
|
@ -30,6 +30,7 @@ int mLogGenerateCategory(const char*);
|
|||
const char* mLogCategoryName(int);
|
||||
|
||||
ATTRIBUTE_FORMAT(printf, 3, 4)
|
||||
#ifndef __NO_INLINE__
|
||||
static inline void mLog(int category, enum mLogLevel level, const char* format, ...) {
|
||||
struct mLogger* context = mLogGetContext();
|
||||
va_list args;
|
||||
|
@ -43,6 +44,9 @@ static inline void mLog(int category, enum mLogLevel level, const char* format,
|
|||
}
|
||||
va_end(args);
|
||||
}
|
||||
#else
|
||||
void mLog(int category, enum mLogLevel level, const char* format, ...);
|
||||
#endif
|
||||
|
||||
#define mLOG(CATEGORY, LEVEL, ...) mLog(_mLOG_CAT_ ## CATEGORY (), mLOG_ ## LEVEL, __VA_ARGS__)
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ enum mDebuggerState {
|
|||
enum mWatchpointType {
|
||||
WATCHPOINT_WRITE = 1,
|
||||
WATCHPOINT_READ = 2,
|
||||
WATCHPOINT_RW = WATCHPOINT_WRITE | WATCHPOINT_READ
|
||||
WATCHPOINT_RW = 3
|
||||
};
|
||||
|
||||
enum mBreakpointType {
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
set(PY_INCLUDE_DIRS -I${CMAKE_SOURCE_DIR}/src)
|
||||
get_property(INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
|
||||
get_property(COMPILE_DEFINITIONS DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS)
|
||||
foreach(INCLUDE_DIR IN LISTS INCLUDE_DIRECTORIES)
|
||||
list(APPEND PY_INCLUDE_DIRS -I${INCLUDE_DIR})
|
||||
endforeach()
|
||||
foreach(COMPILE_DEF IN LISTS COMPILE_DEFINITIONS)
|
||||
list(APPEND PY_COMPILE_DEFS -D${COMPILE_DEF})
|
||||
endforeach()
|
||||
|
||||
add_custom_command(OUTPUT _builder.h
|
||||
COMMAND ${CMAKE_C_COMPILER} ${PY_COMPILE_DEFS} ${PY_INCLUDE_DIRS} -fno-inline -E -P -c ${CMAKE_CURRENT_SOURCE_DIR}/_builder.h -o _builder.h
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/_builder.h)
|
||||
add_custom_target(_builder.h ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/_builder.h)
|
||||
|
||||
add_custom_command(OUTPUT ${BINARY_NAME}/_pylib.so
|
||||
COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py ${PY_COMPILE_DEFS} ${PY_INCLUDE_DIRS}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/_builder.h)
|
||||
add_custom_target(_pylib.so ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}/_pylib.so)
|
|
@ -0,0 +1,6 @@
|
|||
#define COMMON_H
|
||||
#define ATTRIBUTE_FORMAT(X, Y, Z)
|
||||
typedef long time_t;
|
||||
typedef ... va_list;
|
||||
#include <limits.h>
|
||||
#include "core/core.h"
|
|
@ -0,0 +1,20 @@
|
|||
import cffi
|
||||
import os.path
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
ffi = cffi.FFI()
|
||||
src = os.path.join(os.path.dirname(__file__), "..", "..")
|
||||
|
||||
ffi.set_source("mgba._pylib", """
|
||||
#include "util/common.h"
|
||||
#include "core/core.h"
|
||||
""", include_dirs=[src],
|
||||
extra_compile_args=sys.argv[1:],
|
||||
libraries=["mgba"],
|
||||
library_dirs=[os.path.join(os.getcwd(), "..")])
|
||||
|
||||
with open(os.path.join(os.getcwd(), "_builder.h")) as core:
|
||||
ffi.cdef(core.read())
|
||||
|
||||
ffi.compile()
|
|
@ -0,0 +1,47 @@
|
|||
from _pylib import ffi, lib
|
||||
|
||||
def find(path):
|
||||
core = lib.mCoreFind(path.encode('UTF-8'))
|
||||
if core == ffi.NULL:
|
||||
return None
|
||||
return mCore(core)
|
||||
|
||||
class mCore:
|
||||
def __init__(self, native):
|
||||
self._core = ffi.gc(native, self._deinit)
|
||||
|
||||
def init(self):
|
||||
return bool(self._core.init(self._core))
|
||||
|
||||
def _deinit(self):
|
||||
self._core.deinit(self._core)
|
||||
|
||||
def loadFile(self, path):
|
||||
return bool(lib.mCoreLoadFile(self._core, path.encode('UTF-8')))
|
||||
|
||||
def autoloadSave(self):
|
||||
return bool(lib.mCoreAutoloadSave(self._core))
|
||||
|
||||
def autoloadPatch(self):
|
||||
return bool(lib.mCoreAutoloadPatch(self._core))
|
||||
|
||||
def platform(self):
|
||||
return self._core.platform(self._core)
|
||||
|
||||
def desiredVideoDimensions(self):
|
||||
width = ffi.new("unsigned*")
|
||||
height = ffi.new("unsigned*")
|
||||
self._core.desiredVideoDimensions(self._core, width, height)
|
||||
return width[0], height[0]
|
||||
|
||||
def reset(self):
|
||||
self._core.reset(self._core)
|
||||
|
||||
def runFrame(self):
|
||||
self._core.runFrame(self._core)
|
||||
|
||||
def runLoop(self):
|
||||
self._core.runLoop(self._core)
|
||||
|
||||
def step(self):
|
||||
self._core.step(self._core)
|
|
@ -163,6 +163,14 @@ size_t TableSize(const struct Table* table) {
|
|||
return table->size;
|
||||
}
|
||||
|
||||
void HashTableInit(struct Table* table, size_t initialSize, void (deinitializer(void*))) {
|
||||
TableInit(table, initialSize, deinitializer);
|
||||
}
|
||||
|
||||
void HashTableDeinit(struct Table* table) {
|
||||
TableDeinit(table);
|
||||
}
|
||||
|
||||
void* HashTableLookup(const struct Table* table, const char* key) {
|
||||
uint32_t hash = hash32(key, strlen(key), 0);
|
||||
const struct TableList* list;
|
||||
|
|
|
@ -29,6 +29,7 @@ void TableClear(struct Table*);
|
|||
void TableEnumerate(const struct Table*, void (handler(uint32_t key, void* value, void* user)), void* user);
|
||||
size_t TableSize(const struct Table*);
|
||||
|
||||
#ifndef __NO_INLINE__
|
||||
static inline void HashTableInit(struct Table* table, size_t initialSize, void (deinitializer(void*))) {
|
||||
TableInit(table, initialSize, deinitializer);
|
||||
}
|
||||
|
@ -36,6 +37,10 @@ static inline void HashTableInit(struct Table* table, size_t initialSize, void (
|
|||
static inline void HashTableDeinit(struct Table* table) {
|
||||
TableDeinit(table);
|
||||
}
|
||||
#else
|
||||
void HashTableInit(struct Table* table, size_t initialSize, void (deinitializer(void*)));
|
||||
void HashTableDeinit(struct Table* table);
|
||||
#endif
|
||||
|
||||
void* HashTableLookup(const struct Table*, const char* key);
|
||||
void HashTableInsert(struct Table*, const char* key, void* value);
|
||||
|
|
Loading…
Reference in New Issue