Files
vpinball-wasm/patches/vpinball/0006-static-pinmame-plugin-emscripten.patch
T

113 lines
4.7 KiB
Diff
Raw Permalink Normal View History

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 745b91b..edb4112 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -810,8 +810,29 @@ elseif(PLATFORM STREQUAL "emscripten")
src/input/OpenPinDevHandler.cpp
)
+ # PinMAME VPX-side plugin glue (registers VPinMAME.Controller for real
+ # ROM-driven scoring/switches/solenoids) - statically linked and
+ # registered from player.cpp instead of desktop VP's dynamic /plugins
+ # folder scan, same as the built-in "vpx" plugin already is. The real
+ # emulation core it drives (libpinmame.a) is staged into
+ # VPINBALL_WASM_DEPS_DIR by vpinball-wasm's own build-deps.sh (see
+ # patches/pinmame/ for the 3 portability fixes that wasm32 build needed).
+ set(VPX_PINMAME_PLUGIN_SOURCES
+ plugins/pinmame/common.cpp
+ plugins/pinmame/PinMAMEPlugin.cpp
+ plugins/pinmame/Controller.cpp
+ plugins/pinmame/ControllerSettings.cpp
+ plugins/pinmame/Game.cpp
+ plugins/pinmame/Games.cpp
+ plugins/pinmame/GameSettings.cpp
+ plugins/pinmame/Rom.cpp
+ plugins/pinmame/Roms.cpp
+ plugins/pinmame/Settings.cpp
+ )
+
add_executable(vpinball
${VPX_STANDALONE_SOURCES}
+ ${VPX_PINMAME_PLUGIN_SOURCES}
${CMAKE_SOURCE_DIR}/src/core/EmscriptenBridge.cpp
)
@@ -824,6 +845,7 @@ elseif(PLATFORM STREQUAL "emscripten")
${VPINBALL_WASM_DEPS_DIR}/include/libwinevbs/wine/include
src
plugins
+ plugins/pinmame
)
target_compile_definitions(vpinball PRIVATE
@@ -863,6 +885,7 @@ elseif(PLATFORM STREQUAL "emscripten")
freetype
freeimage
winevbs
+ pinmame
glad
)
diff --git a/src/core/player.cpp b/src/core/player.cpp
index 60c7d5f..ec9ebdd 100644
--- a/src/core/player.cpp
+++ b/src/core/player.cpp
@@ -79,6 +79,19 @@ using namespace VPX;
// leave as-is as e.g. VPM relies on this
#define WIN32_PLAYER_WND_CLASSNAME _T("VPPlayer")
+#ifdef __EMSCRIPTEN__
+// Statically-linked player plugin entry points (see the __EMSCRIPTEN__
+// branch in Player::Player below) - same declaration shape used for the
+// iOS/Android static plugin table in lib/src/VPinballLib.cpp, just declared
+// at file scope here since MSGPI_EXPORT's __attribute__((visibility(...)))
+// isn't accepted on a block-scope declaration.
+MSGPI_EXPORT void MSGPIAPI PinMAMEPluginLoad(const uint32_t sessionId, const MsgPluginAPI* api);
+MSGPI_EXPORT void MSGPIAPI PinMAMEPluginUnload();
+
+// For PinmameEmscriptenStep(), called once per frame in EmscriptenStepFrame()
+// below - see that function's own comment.
+#include "pinmame/libpinmame.h"
+#endif
Player::Player(PinTable *const table, const PlayMode playMode)
: m_ptable(table)
@@ -128,6 +141,24 @@ Player::Player(PinTable *const table, const PlayMode playMode)
#ifdef __LIBVPINBALL__
VPinballLib::VPinballLib::SetupStaticPlugins(m_pluginManager);
+#elif defined(__EMSCRIPTEN__)
+ // A browser sandbox has no dynamic-library-loading /plugins folder to
+ // scan (see the ScanPluginFolder call in the #else branch below), so
+ // player plugins have to be statically linked into this same wasm binary
+ // and registered by function pointer instead - the same technique
+ // VPinballLib::SetupStaticPlugins already uses for the iOS/Android
+ // library build (lib/src/VPinballLib.cpp), just scoped here to the one
+ // plugin vpinball-wasm actually ships: PinMAME, which is what lets
+ // table scripts get a real (non-Nothing) VPinMAME.Controller for ROM-
+ // driven scoring/switches/solenoids instead of failing on
+ // CreateObject("VPinMAME.Controller") - see patches/pinmame/ for the
+ // wasm32 portability fixes its emulation core (libpinmame) needed.
+ //
+ // Registered only, not Load()-ed here: the per-plugin enable/Load loop
+ // just below (shared with the dynamic-scan #else branch) already does
+ // that for every entry in m_pluginManager.GetPlugins(), so calling Load()
+ // here too would just load it twice.
+ m_pluginManager.RegisterPlugin("PinMAME", "PinMAME", "PinMAME", "", "", "https://github.com/vpinball/pinmame", &PinMAMEPluginLoad, &PinMAMEPluginUnload);
#else
class SDLModuleLoader final : public MsgPI::MsgModuleLoader
{
@@ -2002,6 +2033,12 @@ bool Player::EmscriptenStepFrame()
if (GetCloseState() != CS_PLAYING && GetCloseState() != CS_USER_INPUT)
return false;
+ // PinMAME (VPinMAME.Controller for ROM-driven tables) is likewise
+ // single-threaded here instead of running on its own real thread - see
+ // PinmameEmscriptenStep's own comment in libpinmame.cpp. A no-op when no
+ // ROM-based table has called Controller.Run().
+ PinmameEmscriptenStep();
+
UpdateGameLogic();
PrepareFrame();
UpdateGameLogic();