diff --git a/src/core/VPApp.cpp b/src/core/VPApp.cpp index 7175dd2..f05a324 100644 --- a/src/core/VPApp.cpp +++ b/src/core/VPApp.cpp @@ -36,6 +36,10 @@ #include #endif +#ifdef __EMSCRIPTEN__ +#include +#endif + #include "parts/ball.h" #include "parts/timer.h" #include "parts/flipper.h" @@ -273,6 +277,34 @@ int VPApp::GetLogicalNumberOfProcessors() const return m_logicalNumberOfProcessors; } +#ifdef __EMSCRIPTEN__ +// VBScript's MsgBox() must return synchronously (its VARIANT result is used +// right after the call, in the same script statement) - window.confirm()/ +// alert() are the only browser APIs that block JS execution and return a +// value synchronously, so they're used here directly rather than routing +// through any async/JS-callback mechanism the host page might otherwise want +// to customize the look of (which would require Asyncify to suspend the +// call, since single-threaded builds have no other way to block for it). +// type is the raw VBScript "buttons" argument (MB_OK=0, MB_OKCANCEL=1, +// MB_ABORTRETRYIGNORE=2, MB_YESNOCANCEL=3, MB_YESNO=4, MB_RETRYCANCEL=5). +// The returned id matches vbOK(1)/vbCancel(2)/vbYes(6)/vbNo(7). +static int EmscriptenMsgBox(const char* prompt, int type, const char* title) +{ + const string message = (title && title[0]) ? (string(title) + "\n\n" + prompt) : string(prompt); + switch (type & 0x0F) + { + case 1: // MB_OKCANCEL + return EM_ASM_INT({ return confirm(UTF8ToString($0)) ? 1 : 0; }, message.c_str()) ? 1 /* IDOK */ : 2 /* IDCANCEL */; + case 3: // MB_YESNOCANCEL - Cancel isn't distinguishable from No via confirm(), best effort + case 4: // MB_YESNO + return EM_ASM_INT({ return confirm(UTF8ToString($0)) ? 1 : 0; }, message.c_str()) ? 6 /* IDYES */ : 7 /* IDNO */; + default: + EM_ASM_({ alert(UTF8ToString($0)); }, message.c_str()); + return 1; // IDOK + } +} +#endif + void VPApp::InitInstance() { std::filesystem::path iniFileName = m_commandLineCustomSettingsFileName; @@ -325,6 +357,9 @@ void VPApp::InitInstance() delete[] buffer; } }; +#ifdef __EMSCRIPTEN__ + callbacks.msgbox = &EmscriptenMsgBox; +#endif libwinevbs_init(&callbacks); #endif