Implemented python script running with emu_frameadvance and loop_test.py
This commit is contained in:
parent
105e46edd7
commit
a415977089
|
@ -0,0 +1,5 @@
|
|||
import emu
|
||||
|
||||
while True:
|
||||
print("PY: Frame")
|
||||
emu.frameadvance()
|
|
@ -224,6 +224,11 @@ else ()
|
|||
)
|
||||
endif()
|
||||
|
||||
# Python and pybind11 configuration
|
||||
find_package(pybind11 REQUIRED)
|
||||
set(PYTHON_LIBS pybind11::embed)
|
||||
set(PYTHON_ENGINE_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/python-engine.cpp)
|
||||
|
||||
if ( ${ZLIB_FOUND} )
|
||||
|
||||
message( STATUS "Using System zlib ${ZLIB_VERSION_STRING}" )
|
||||
|
@ -292,6 +297,7 @@ set(SRC_CORE
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/wave.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/x6502.cpp
|
||||
${LUA_ENGINE_SOURCE}
|
||||
${PYTHON_ENGINE_SOURCE}
|
||||
${ZLIB_SOURCE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/01-222.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/09-034a.cpp
|
||||
|
@ -632,6 +638,7 @@ target_link_libraries( ${APP_NAME} ${ASAN_LDFLAGS}
|
|||
${MINIZIP_LDFLAGS} ${ZLIB_LIBRARIES}
|
||||
${LUA_LDFLAGS} ${X264_LDFLAGS} ${X265_LDFLAGS} ${LIBAV_LDFLAGS}
|
||||
${SYS_LIBS}
|
||||
${PYTHON_LIBS}
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
#include "../../fceulua.h"
|
||||
#endif
|
||||
|
||||
#include "../../fceupython.h"
|
||||
|
||||
#include "common/os_utils.h"
|
||||
#include "common/configSys.h"
|
||||
#include "../../oldmovie.h"
|
||||
|
@ -1068,6 +1070,8 @@ int fceuWrapperInit( int argc, char *argv[] )
|
|||
{
|
||||
s = fi.canonicalFilePath().toStdString();
|
||||
}
|
||||
|
||||
FCEU_LoadPythonCode(s.c_str());
|
||||
}
|
||||
|
||||
g_config->getOption("SDL.NewPPU", &newppu);
|
||||
|
|
|
@ -64,6 +64,8 @@ extern void RefreshThrottleFPS();
|
|||
#include "fceulua.h"
|
||||
#endif
|
||||
|
||||
#include "fceupython.h"
|
||||
|
||||
//TODO - we really need some kind of global platform-specific options api
|
||||
#ifdef __WIN_DRIVER__
|
||||
#include "drivers/win/main.h"
|
||||
|
@ -796,6 +798,8 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
|
|||
FCEU_LuaFrameBoundary();
|
||||
#endif
|
||||
|
||||
FCEU_PythonFrameBoundary();
|
||||
|
||||
FCEU_UpdateInput();
|
||||
lagFlag = 1;
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef _FCEUPYTHON_H
|
||||
#define _FCEUPYTHON_H
|
||||
|
||||
void FCEU_PythonFrameBoundary();
|
||||
void FCEU_LoadPythonCode(const char* filename);
|
||||
|
||||
#endif //_FCEUPYTHON_H
|
|
@ -0,0 +1,122 @@
|
|||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <iostream>
|
||||
|
||||
#include <pybind11/embed.h>
|
||||
namespace py = pybind11;
|
||||
|
||||
#include "fceupython.h"
|
||||
|
||||
#define SetCurrentDir chdir
|
||||
|
||||
// Are we running any code right now?
|
||||
static char* pythonScriptName = NULL;
|
||||
bool pythonRunning = false;
|
||||
|
||||
// True if there's a thread waiting to run after a run of frame-advance.
|
||||
static std::atomic_bool frameAdvanceWaiting = false;
|
||||
|
||||
// True if there's a thread waiting to run after a run of frame-advance.
|
||||
static std::atomic_bool inFrameBoundry = false;
|
||||
|
||||
std::mutex mtx;
|
||||
std::condition_variable cv;
|
||||
|
||||
// Python thread object
|
||||
// std::thread python_thread;
|
||||
|
||||
|
||||
void FCEU_PythonFrameBoundary()
|
||||
{
|
||||
std::cout << "in FCEU_PythonFrameBoundary" << std::endl;
|
||||
|
||||
if(!pythonRunning)
|
||||
return;
|
||||
|
||||
// Notify Python thread the main thread is in the frame boundry
|
||||
inFrameBoundry = true;
|
||||
cv.notify_all();
|
||||
|
||||
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
cv.wait(lock, [] { return bool(frameAdvanceWaiting); });
|
||||
frameAdvanceWaiting = false;
|
||||
}
|
||||
|
||||
void emu_frameadvance()
|
||||
{
|
||||
// Can't call if a frameAdvance is already waiting
|
||||
if (frameAdvanceWaiting)
|
||||
return;
|
||||
|
||||
frameAdvanceWaiting = true;
|
||||
|
||||
// Notify main thread it can advance the frame
|
||||
cv.notify_all();
|
||||
|
||||
// Wait until inFrameBoundry is true to continue python script
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
inFrameBoundry = false;
|
||||
cv.wait(lock, [] { return bool(inFrameBoundry); });
|
||||
}
|
||||
|
||||
PYBIND11_EMBEDDED_MODULE(emu, m)
|
||||
{
|
||||
m.def("frameadvance", &emu_frameadvance);
|
||||
// m.def("framecount", [] { return emu_framecount; });
|
||||
}
|
||||
|
||||
void pythonStart(std::string filename)
|
||||
{
|
||||
// Wait until in_frame_boundry is true to start python script
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
cv.wait(lock, [] { return bool(inFrameBoundry); });
|
||||
lock.unlock();
|
||||
|
||||
// Start evaluating the python file
|
||||
py::gil_scoped_acquire acquire;
|
||||
py::eval_file(filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and runs the given Python script.
|
||||
* The emulator MUST be paused for this function to be
|
||||
* called. Otherwise, all frame boundary assumptions go out the window.
|
||||
*
|
||||
* Returns true on success, false on failure.
|
||||
*/
|
||||
void FCEU_LoadPythonCode(const char* filename)
|
||||
{
|
||||
if (filename != pythonScriptName)
|
||||
{
|
||||
if (pythonScriptName)
|
||||
free(pythonScriptName);
|
||||
pythonScriptName = strdup(filename);
|
||||
}
|
||||
|
||||
// Start interpreter
|
||||
pythonRunning = true;
|
||||
py::initialize_interpreter();
|
||||
|
||||
// gil_scoped_release created on heap to not be destroyed on leaving FCEU_LoadPythonCode scope
|
||||
py::gil_scoped_release* release = new py::gil_scoped_release;
|
||||
|
||||
std::thread(pythonStart, std::string(filename)).detach();
|
||||
|
||||
FCEU_PythonFrameBoundary();
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates a running Python scripts by killing the whole Python Interpretor.
|
||||
*/
|
||||
void FCEU_PythonStop()
|
||||
{
|
||||
if (!pythonRunning)
|
||||
return;
|
||||
|
||||
// Stop interpretor
|
||||
pythonRunning = false;
|
||||
py::finalize_interpreter();
|
||||
}
|
Loading…
Reference in New Issue