diff --git a/binding/binding-mri.cpp b/binding/binding-mri.cpp index 882eede8..18f5341d 100644 --- a/binding/binding-mri.cpp +++ b/binding/binding-mri.cpp @@ -19,24 +19,23 @@ ** along with mkxp. If not, see . */ -#include "binding.h" +#include "audio.h" #include "binding-util.h" -#include "sharedstate.h" +#include "binding.h" +#include "config.h" +#include "debugwriter.h" #include "eventthread.h" #include "filesystem.h" -#include "util.h" -#include "sdl-util.h" -#include "debugwriter.h" #include "graphics.h" -#include "config.h" -#include "audio.h" #include "lang-fun.h" +#include "sdl-util.h" +#include "sharedstate.h" +#include "util.h" #include "boost-hash.h" #include -extern "C" -{ +extern "C" { #include #ifndef OLD_RUBY @@ -48,9 +47,9 @@ extern "C" #include #include +#include #include #include -#include #ifdef __WIN32__ #define NULL_IO "NUL" @@ -66,12 +65,8 @@ static void mriBindingExecute(); static void mriBindingTerminate(); static void mriBindingReset(); -ScriptBinding scriptBindingImpl = -{ - mriBindingExecute, - mriBindingTerminate, - mriBindingReset -}; +ScriptBinding scriptBindingImpl = {mriBindingExecute, mriBindingTerminate, + mriBindingReset}; ScriptBinding *scriptBinding = &scriptBindingImpl; @@ -93,7 +88,7 @@ void graphicsBindingInit(); void fileIntBindingInit(); -#ifdef OLD_RUBY +#ifdef USE_MINIFFI void MiniFFIBindingInit(); #endif @@ -120,707 +115,650 @@ RB_METHOD(mriRgssMain); RB_METHOD(mriRgssStop); RB_METHOD(_kernelCaller); -static void mriBindingInit() -{ - tableBindingInit(); - etcBindingInit(); - fontBindingInit(); - bitmapBindingInit(); - spriteBindingInit(); - viewportBindingInit(); - planeBindingInit(); +static void mriBindingInit() { + tableBindingInit(); + etcBindingInit(); + fontBindingInit(); + bitmapBindingInit(); + spriteBindingInit(); + viewportBindingInit(); + planeBindingInit(); - if (rgssVer == 1) - { - windowBindingInit(); - tilemapBindingInit(); - } - else - { - windowVXBindingInit(); - tilemapVXBindingInit(); - } + if (rgssVer == 1) { + windowBindingInit(); + tilemapBindingInit(); + } else { + windowVXBindingInit(); + tilemapVXBindingInit(); + } - inputBindingInit(); - audioBindingInit(); - graphicsBindingInit(); + inputBindingInit(); + audioBindingInit(); + graphicsBindingInit(); - fileIntBindingInit(); + fileIntBindingInit(); -#ifdef OLD_RUBY - MiniFFIBindingInit(); +#ifdef USE_MINIFFI + MiniFFIBindingInit(); #endif - + #ifdef HAVE_DISCORDSDK - DiscordBindingInit(); + DiscordBindingInit(); #endif - if (rgssVer >= 3) - { - _rb_define_module_function(rb_mKernel, "rgss_main", mriRgssMain); - _rb_define_module_function(rb_mKernel, "rgss_stop", mriRgssStop); + if (rgssVer >= 3) { + _rb_define_module_function(rb_mKernel, "rgss_main", mriRgssMain); + _rb_define_module_function(rb_mKernel, "rgss_stop", mriRgssStop); - _rb_define_module_function(rb_mKernel, "msgbox", mriPrint); - _rb_define_module_function(rb_mKernel, "msgbox_p", mriP); + _rb_define_module_function(rb_mKernel, "msgbox", mriPrint); + _rb_define_module_function(rb_mKernel, "msgbox_p", mriP); - rb_define_global_const("RGSS_VERSION", rb_str_new_cstr("3.0.1")); - } - else - { - _rb_define_module_function(rb_mKernel, "print", mriPrint); - _rb_define_module_function(rb_mKernel, "p", mriP); + rb_define_global_const("RGSS_VERSION", rb_str_new_cstr("3.0.1")); + } else { + _rb_define_module_function(rb_mKernel, "print", mriPrint); + _rb_define_module_function(rb_mKernel, "p", mriP); - rb_define_alias(rb_singleton_class(rb_mKernel), "_mkxp_kernel_caller_alias", "caller"); - _rb_define_module_function(rb_mKernel, "caller", _kernelCaller); - } + rb_define_alias(rb_singleton_class(rb_mKernel), "_mkxp_kernel_caller_alias", + "caller"); + _rb_define_module_function(rb_mKernel, "caller", _kernelCaller); + } - if (rgssVer == 1) - rb_eval_string(module_rpg1); - else if (rgssVer == 2) - rb_eval_string(module_rpg2); - else if (rgssVer == 3) - rb_eval_string(module_rpg3); - else - assert(!"unreachable"); + if (rgssVer == 1) + rb_eval_string(module_rpg1); + else if (rgssVer == 2) + rb_eval_string(module_rpg2); + else if (rgssVer == 3) + rb_eval_string(module_rpg3); + else + assert(!"unreachable"); - VALUE mod = rb_define_module("System"); - _rb_define_module_function(mod, "data_directory", mkxpDataDirectory); - _rb_define_module_function(mod, "set_window_title", mkxpSetTitle); - _rb_define_module_function(mod, "show_settings", mkxpSettingsMenu); - _rb_define_module_function(mod, "puts", mkxpPuts); - _rb_define_module_function(mod, "raw_key_states", mkxpRawKeyStates); - _rb_define_module_function(mod, "mouse_in_window", mkxpMouseInWindow); - _rb_define_module_function(mod, "platform", mkxpPlatform); - _rb_define_module_function(mod, "user_language", mkxpUserLanguage); - _rb_define_module_function(mod, "game_title", mkxpGameTitle); - _rb_define_module_function(mod, "power_state", mkxpPowerState); - _rb_define_module_function(mod, "nproc", mkxpCpuCount); - _rb_define_module_function(mod, "memory", mkxpSystemMemory); + VALUE mod = rb_define_module("System"); + _rb_define_module_function(mod, "data_directory", mkxpDataDirectory); + _rb_define_module_function(mod, "set_window_title", mkxpSetTitle); + _rb_define_module_function(mod, "show_settings", mkxpSettingsMenu); + _rb_define_module_function(mod, "puts", mkxpPuts); + _rb_define_module_function(mod, "raw_key_states", mkxpRawKeyStates); + _rb_define_module_function(mod, "mouse_in_window", mkxpMouseInWindow); + _rb_define_module_function(mod, "platform", mkxpPlatform); + _rb_define_module_function(mod, "user_language", mkxpUserLanguage); + _rb_define_module_function(mod, "game_title", mkxpGameTitle); + _rb_define_module_function(mod, "power_state", mkxpPowerState); + _rb_define_module_function(mod, "nproc", mkxpCpuCount); + _rb_define_module_function(mod, "memory", mkxpSystemMemory); - /* Load global constants */ - rb_gv_set("MKXP", Qtrue); + /* Load global constants */ + rb_gv_set("MKXP", Qtrue); - VALUE debug = rb_bool_new(shState->config().editor.debug); - if (rgssVer == 1) - rb_gv_set("DEBUG", debug); - else if (rgssVer >= 2) - rb_gv_set("TEST", debug); + VALUE debug = rb_bool_new(shState->config().editor.debug); + if (rgssVer == 1) + rb_gv_set("DEBUG", debug); + else if (rgssVer >= 2) + rb_gv_set("TEST", debug); - rb_gv_set("BTEST", rb_bool_new(shState->config().editor.battleTest)); + rb_gv_set("BTEST", rb_bool_new(shState->config().editor.battleTest)); } -static void -showMsg(const std::string &msg) -{ - shState->eThread().showMessageBox(msg.c_str()); +static void showMsg(const std::string &msg) { + shState->eThread().showMessageBox(msg.c_str()); } -static void printP(int argc, VALUE *argv, - const char *convMethod, const char *sep) -{ - VALUE dispString = rb_str_buf_new(128); - ID conv = rb_intern(convMethod); +static void printP(int argc, VALUE *argv, const char *convMethod, + const char *sep) { + VALUE dispString = rb_str_buf_new(128); + ID conv = rb_intern(convMethod); - for (int i = 0; i < argc; ++i) - { - VALUE str = rb_funcall2(argv[i], conv, 0, NULL); - rb_str_buf_append(dispString, str); + for (int i = 0; i < argc; ++i) { + VALUE str = rb_funcall2(argv[i], conv, 0, NULL); + rb_str_buf_append(dispString, str); - if (i < argc) - rb_str_buf_cat2(dispString, sep); - } + if (i < argc) + rb_str_buf_cat2(dispString, sep); + } - showMsg(RSTRING_PTR(dispString)); + showMsg(RSTRING_PTR(dispString)); } -RB_METHOD(mriPrint) -{ - RB_UNUSED_PARAM; +RB_METHOD(mriPrint) { + RB_UNUSED_PARAM; - printP(argc, argv, "to_s", ""); + printP(argc, argv, "to_s", ""); - return Qnil; + return Qnil; } -RB_METHOD(mriP) -{ - RB_UNUSED_PARAM; +RB_METHOD(mriP) { + RB_UNUSED_PARAM; - printP(argc, argv, "inspect", "\n"); + printP(argc, argv, "inspect", "\n"); - return Qnil; + return Qnil; } -RB_METHOD(mkxpDataDirectory) -{ - RB_UNUSED_PARAM; - - const std::string &path = shState->config().customDataPath; - const char *s = path.empty() ? "." : path.c_str(); - - char *s_nml = shState->fileSystem().normalize(s, 1, 1); - VALUE ret = rb_str_new_cstr(s_nml); - delete s_nml; +RB_METHOD(mkxpDataDirectory) { + RB_UNUSED_PARAM; - return ret; + const std::string &path = shState->config().customDataPath; + const char *s = path.empty() ? "." : path.c_str(); + + char *s_nml = shState->fileSystem().normalize(s, 1, 1); + VALUE ret = rb_str_new_cstr(s_nml); + delete s_nml; + + return ret; } -RB_METHOD(mkxpSetTitle) -{ - RB_UNUSED_PARAM; - - VALUE s; - rb_scan_args(argc, argv, "1", &s); - SafeStringValue(s); - - shState->eThread().requestWindowRename(RSTRING_PTR(s)); - return s; +RB_METHOD(mkxpSetTitle) { + RB_UNUSED_PARAM; + + VALUE s; + rb_scan_args(argc, argv, "1", &s); + SafeStringValue(s); + + shState->eThread().requestWindowRename(RSTRING_PTR(s)); + return s; } -RB_METHOD(mkxpPuts) -{ - RB_UNUSED_PARAM; +RB_METHOD(mkxpPuts) { + RB_UNUSED_PARAM; - const char *str; - rb_get_args(argc, argv, "z", &str RB_ARG_END); + const char *str; + rb_get_args(argc, argv, "z", &str RB_ARG_END); - Debug() << str; + Debug() << str; - return Qnil; + return Qnil; } -RB_METHOD(mkxpRawKeyStates) -{ - RB_UNUSED_PARAM; +RB_METHOD(mkxpRawKeyStates) { + RB_UNUSED_PARAM; - VALUE str = rb_str_new(0, sizeof(EventThread::keyStates)); - memcpy(RSTRING_PTR(str), EventThread::keyStates, sizeof(EventThread::keyStates)); + VALUE str = rb_str_new(0, sizeof(EventThread::keyStates)); + memcpy(RSTRING_PTR(str), EventThread::keyStates, + sizeof(EventThread::keyStates)); - return str; + return str; } -RB_METHOD(mkxpMouseInWindow) -{ - RB_UNUSED_PARAM; +RB_METHOD(mkxpMouseInWindow) { + RB_UNUSED_PARAM; - return rb_bool_new(EventThread::mouseState.inWindow); + return rb_bool_new(EventThread::mouseState.inWindow); } -RB_METHOD(mkxpPlatform) -{ - RB_UNUSED_PARAM; - - return rb_str_new_cstr(SDL_GetPlatform()); +RB_METHOD(mkxpPlatform) { + RB_UNUSED_PARAM; + + return rb_str_new_cstr(SDL_GetPlatform()); } -RB_METHOD(mkxpUserLanguage) -{ - RB_UNUSED_PARAM; - - return rb_str_new_cstr(getUserLanguage()); +RB_METHOD(mkxpUserLanguage) { + RB_UNUSED_PARAM; + + return rb_str_new_cstr(getUserLanguage()); } -RB_METHOD(mkxpGameTitle) -{ - RB_UNUSED_PARAM; - - return rb_str_new_cstr(shState->config().game.title.c_str()); +RB_METHOD(mkxpGameTitle) { + RB_UNUSED_PARAM; + + return rb_str_new_cstr(shState->config().game.title.c_str()); } -RB_METHOD(mkxpPowerState) -{ - RB_UNUSED_PARAM; - - int secs, pct; - SDL_PowerState ps = SDL_GetPowerInfo(&secs, &pct); - - VALUE hash = rb_hash_new(); - - rb_hash_aset(hash, ID2SYM(rb_intern("seconds")), (secs > -1) ? INT2NUM(secs) : RUBY_Qnil); - - rb_hash_aset(hash, ID2SYM(rb_intern("percent")), (pct > -1) ? INT2NUM(pct) : RUBY_Qnil); - - rb_hash_aset(hash, ID2SYM(rb_intern("discharging")), rb_bool_new(ps == SDL_POWERSTATE_ON_BATTERY)); - - return hash; +RB_METHOD(mkxpPowerState) { + RB_UNUSED_PARAM; + + int secs, pct; + SDL_PowerState ps = SDL_GetPowerInfo(&secs, &pct); + + VALUE hash = rb_hash_new(); + + rb_hash_aset(hash, ID2SYM(rb_intern("seconds")), + (secs > -1) ? INT2NUM(secs) : RUBY_Qnil); + + rb_hash_aset(hash, ID2SYM(rb_intern("percent")), + (pct > -1) ? INT2NUM(pct) : RUBY_Qnil); + + rb_hash_aset(hash, ID2SYM(rb_intern("discharging")), + rb_bool_new(ps == SDL_POWERSTATE_ON_BATTERY)); + + return hash; } -RB_METHOD(mkxpSettingsMenu) -{ - RB_UNUSED_PARAM; - - shState->eThread().requestSettingsMenu(); - - return Qnil; +RB_METHOD(mkxpSettingsMenu) { + RB_UNUSED_PARAM; + + shState->eThread().requestSettingsMenu(); + + return Qnil; } -RB_METHOD(mkxpCpuCount) -{ - RB_UNUSED_PARAM; - - return INT2NUM(SDL_GetCPUCount()); +RB_METHOD(mkxpCpuCount) { + RB_UNUSED_PARAM; + + return INT2NUM(SDL_GetCPUCount()); } -RB_METHOD(mkxpSystemMemory) -{ - RB_UNUSED_PARAM; - - return INT2NUM(SDL_GetSystemRAM()); +RB_METHOD(mkxpSystemMemory) { + RB_UNUSED_PARAM; + + return INT2NUM(SDL_GetSystemRAM()); } -static VALUE rgssMainCb(VALUE block) -{ - rb_funcall2(block, rb_intern("call"), 0, 0); - return Qnil; +static VALUE rgssMainCb(VALUE block) { + rb_funcall2(block, rb_intern("call"), 0, 0); + return Qnil; } -static VALUE rgssMainRescue(VALUE arg, VALUE exc) -{ - VALUE *excRet = (VALUE*) arg; +static VALUE rgssMainRescue(VALUE arg, VALUE exc) { + VALUE *excRet = (VALUE *)arg; - *excRet = exc; + *excRet = exc; - return Qnil; + return Qnil; } -static void processReset() -{ - shState->graphics().reset(); - shState->audio().reset(); +static void processReset() { + shState->graphics().reset(); + shState->audio().reset(); - shState->rtData().rqReset.clear(); - shState->graphics().repaintWait(shState->rtData().rqResetFinish, - false); + shState->rtData().rqReset.clear(); + shState->graphics().repaintWait(shState->rtData().rqResetFinish, false); } -RB_METHOD(mriRgssMain) -{ - RB_UNUSED_PARAM; +RB_METHOD(mriRgssMain) { + RB_UNUSED_PARAM; - while (true) - { - VALUE exc = Qnil; + while (true) { + VALUE exc = Qnil; - rb_rescue2((VALUE(*)(ANYARGS)) rgssMainCb, rb_block_proc(), - (VALUE(*)(ANYARGS)) rgssMainRescue, (VALUE) &exc, - rb_eException, (VALUE) 0); + rb_rescue2((VALUE(*)(ANYARGS))rgssMainCb, rb_block_proc(), + (VALUE(*)(ANYARGS))rgssMainRescue, (VALUE)&exc, rb_eException, + (VALUE)0); - if (NIL_P(exc)) - break; + if (NIL_P(exc)) + break; - if (rb_obj_class(exc) == getRbData()->exc[Reset]) - processReset(); - else - rb_exc_raise(exc); - } + if (rb_obj_class(exc) == getRbData()->exc[Reset]) + processReset(); + else + rb_exc_raise(exc); + } - return Qnil; + return Qnil; } -RB_METHOD(mriRgssStop) -{ - RB_UNUSED_PARAM; +RB_METHOD(mriRgssStop) { + RB_UNUSED_PARAM; - while (true) - shState->graphics().update(); + while (true) + shState->graphics().update(); - return Qnil; + return Qnil; } -RB_METHOD(_kernelCaller) -{ - RB_UNUSED_PARAM; +RB_METHOD(_kernelCaller) { + RB_UNUSED_PARAM; - VALUE trace = rb_funcall2(rb_mKernel, rb_intern("_mkxp_kernel_caller_alias"), 0, 0); + VALUE trace = + rb_funcall2(rb_mKernel, rb_intern("_mkxp_kernel_caller_alias"), 0, 0); - if (!RB_TYPE_P(trace, RUBY_T_ARRAY)) - return trace; + if (!RB_TYPE_P(trace, RUBY_T_ARRAY)) + return trace; - long len = RARRAY_LEN(trace); + long len = RARRAY_LEN(trace); - if (len < 2) - return trace; + if (len < 2) + return trace; - /* Remove useless "ruby:1:in 'eval'" */ - rb_ary_pop(trace); + /* Remove useless "ruby:1:in 'eval'" */ + rb_ary_pop(trace); - /* Also remove trace of this helper function */ - rb_ary_shift(trace); + /* Also remove trace of this helper function */ + rb_ary_shift(trace); - len -= 2; + len -= 2; - if (len == 0) - return trace; + if (len == 0) + return trace; - /* RMXP does this, not sure if specific or 1.8 related */ - VALUE args[] = { rb_str_new_cstr(":in `
'"), rb_str_new_cstr("") }; - rb_funcall2(rb_ary_entry(trace, len-1), rb_intern("gsub!"), 2, args); + /* RMXP does this, not sure if specific or 1.8 related */ + VALUE args[] = {rb_str_new_cstr(":in `
'"), rb_str_new_cstr("")}; + rb_funcall2(rb_ary_entry(trace, len - 1), rb_intern("gsub!"), 2, args); - return trace; + return trace; } #ifndef OLD_RUBY -static VALUE newStringUTF8(const char *string, long length) -{ - return rb_enc_str_new(string, length, rb_utf8_encoding()); +static VALUE newStringUTF8(const char *string, long length) { + return rb_enc_str_new(string, length, rb_utf8_encoding()); } #else #define newStringUTF8 rb_str_new #endif -struct evalArg -{ - VALUE string; - VALUE filename; +struct evalArg { + VALUE string; + VALUE filename; }; -static VALUE evalHelper(evalArg *arg) -{ - VALUE argv[] = { arg->string, Qnil, arg->filename }; - return rb_funcall2(Qnil, rb_intern("eval"), ARRAY_SIZE(argv), argv); +static VALUE evalHelper(evalArg *arg) { + VALUE argv[] = {arg->string, Qnil, arg->filename}; + return rb_funcall2(Qnil, rb_intern("eval"), ARRAY_SIZE(argv), argv); } -static VALUE evalString(VALUE string, VALUE filename, int *state) -{ - evalArg arg = { string, filename }; - return rb_protect((VALUE (*)(VALUE))evalHelper, (VALUE)&arg, state); +static VALUE evalString(VALUE string, VALUE filename, int *state) { + evalArg arg = {string, filename}; + return rb_protect((VALUE(*)(VALUE))evalHelper, (VALUE)&arg, state); } -static void runCustomScript(const std::string &filename) -{ - std::string scriptData; +static void runCustomScript(const std::string &filename) { + std::string scriptData; - if (!readFileSDL(filename.c_str(), scriptData)) - { - showMsg(std::string("Unable to open '") + filename + "'"); - return; - } + if (!readFileSDL(filename.c_str(), scriptData)) { + showMsg(std::string("Unable to open '") + filename + "'"); + return; + } - evalString(newStringUTF8(scriptData.c_str(), scriptData.size()), - newStringUTF8(filename.c_str(), filename.size()), NULL); + evalString(newStringUTF8(scriptData.c_str(), scriptData.size()), + newStringUTF8(filename.c_str(), filename.size()), NULL); } VALUE kernelLoadDataInt(const char *filename, bool rubyExc, bool raw); -struct BacktraceData -{ - /* Maps: Ruby visible filename, To: Actual script name */ - BoostHash scriptNames; +struct BacktraceData { + /* Maps: Ruby visible filename, To: Actual script name */ + BoostHash scriptNames; }; #ifndef MARIN #define SCRIPT_SECTION_FMT (rgssVer >= 3 ? "{%04ld}" : "Section%03ld") -static void runRMXPScripts(BacktraceData &btData) -{ - const Config &conf = shState->rtData().config; - const std::string &scriptPack = conf.game.scripts; - const char *platform = SDL_GetPlatform(); +static void runRMXPScripts(BacktraceData &btData) { + const Config &conf = shState->rtData().config; + const std::string &scriptPack = conf.game.scripts; + const char *platform = SDL_GetPlatform(); - if (scriptPack.empty()) - { - showMsg("No game scripts specified (missing Game.ini?)"); - return; - } + if (scriptPack.empty()) { + showMsg("No game scripts specified (missing Game.ini?)"); + return; + } - if (!shState->fileSystem().exists(scriptPack.c_str())) - { - showMsg("Unable to open '" + scriptPack + "'"); - return; - } + if (!shState->fileSystem().exists(scriptPack.c_str())) { + showMsg("Unable to open '" + scriptPack + "'"); + return; + } - VALUE scriptArray; + VALUE scriptArray; - /* We checked if Scripts.rxdata exists, but something might - * still go wrong */ - try - { - scriptArray = kernelLoadDataInt(scriptPack.c_str(), false, false); - } - catch (const Exception &e) - { - showMsg(std::string("Failed to read script data: ") + e.msg); - return; - } + /* We checked if Scripts.rxdata exists, but something might + * still go wrong */ + try { + scriptArray = kernelLoadDataInt(scriptPack.c_str(), false, false); + } catch (const Exception &e) { + showMsg(std::string("Failed to read script data: ") + e.msg); + return; + } - if (!RB_TYPE_P(scriptArray, RUBY_T_ARRAY)) - { - showMsg("Failed to read script data"); - return; - } + if (!RB_TYPE_P(scriptArray, RUBY_T_ARRAY)) { + showMsg("Failed to read script data"); + return; + } - rb_gv_set("$RGSS_SCRIPTS", scriptArray); + rb_gv_set("$RGSS_SCRIPTS", scriptArray); - long scriptCount = RARRAY_LEN(scriptArray); + long scriptCount = RARRAY_LEN(scriptArray); - std::string decodeBuffer; - decodeBuffer.resize(0x1000); + std::string decodeBuffer; + decodeBuffer.resize(0x1000); - for (long i = 0; i < scriptCount; ++i) - { - VALUE script = rb_ary_entry(scriptArray, i); + for (long i = 0; i < scriptCount; ++i) { + VALUE script = rb_ary_entry(scriptArray, i); - if (!RB_TYPE_P(script, RUBY_T_ARRAY)) - continue; + if (!RB_TYPE_P(script, RUBY_T_ARRAY)) + continue; - VALUE scriptName = rb_ary_entry(script, 1); - VALUE scriptString = rb_ary_entry(script, 2); + VALUE scriptName = rb_ary_entry(script, 1); + VALUE scriptString = rb_ary_entry(script, 2); - int result = Z_OK; - unsigned long bufferLen; + int result = Z_OK; + unsigned long bufferLen; - while (true) - { - unsigned char *bufferPtr = - reinterpret_cast(const_cast(decodeBuffer.c_str())); - const unsigned char *sourcePtr = - reinterpret_cast(RSTRING_PTR(scriptString)); + while (true) { + unsigned char *bufferPtr = reinterpret_cast( + const_cast(decodeBuffer.c_str())); + const unsigned char *sourcePtr = + reinterpret_cast(RSTRING_PTR(scriptString)); - bufferLen = decodeBuffer.length(); + bufferLen = decodeBuffer.length(); - result = uncompress(bufferPtr, &bufferLen, - sourcePtr, RSTRING_LEN(scriptString)); + result = uncompress(bufferPtr, &bufferLen, sourcePtr, + RSTRING_LEN(scriptString)); - bufferPtr[bufferLen] = '\0'; + bufferPtr[bufferLen] = '\0'; - if (result != Z_BUF_ERROR) - break; + if (result != Z_BUF_ERROR) + break; - decodeBuffer.resize(decodeBuffer.size()*2); - } - - if (result != Z_OK) - { - static char buffer[256]; - snprintf(buffer, sizeof(buffer), "Error decoding script %ld: '%s'", - i, RSTRING_PTR(scriptName)); - - showMsg(buffer); - - break; - } - - rb_ary_store(script, 3, rb_str_new_cstr(decodeBuffer.c_str())); - } - - // Can be force-disabled similarly to framerate options -#ifndef NO_PRELOAD_SCRIPTS - /* Execute preloaded scripts */ - for (std::vector::const_iterator i = conf.preloadScripts.begin(); - i != conf.preloadScripts.end(); ++i) - runCustomScript(*i); - - VALUE exc = rb_gv_get("$!"); - if (exc != Qnil) - return; -#endif - - while (true) - { -#if defined(OLD_RUBY) && defined(NO_CONSOLE) - VALUE iostr = rb_str_new2(NULL_IO); - // Sysinit isn't a thing yet, so send io to /dev/null instead - rb_funcall(rb_gv_get("$stderr"), rb_intern("reopen"), 1, iostr); - rb_funcall(rb_gv_get("$stdout"), rb_intern("reopen"), 1, iostr); -#endif - for (long i = 0; i < scriptCount; ++i) - { - VALUE script = rb_ary_entry(scriptArray, i); - VALUE scriptDecoded = rb_ary_entry(script, 3); - VALUE string = newStringUTF8(RSTRING_PTR(scriptDecoded), - RSTRING_LEN(scriptDecoded)); - - VALUE fname; - const char *scriptName = RSTRING_PTR(rb_ary_entry(script, 1)); - char buf[512]; - int len; - - if (conf.useScriptNames) - len = snprintf(buf, sizeof(buf), "%03ld:%s", i, scriptName); - else - len = snprintf(buf, sizeof(buf), SCRIPT_SECTION_FMT, i); - - fname = newStringUTF8(buf, len); - btData.scriptNames.insert(buf, scriptName); - - // if the script name starts with |s|, only execute - // it if "s" is the same first letter as the platform - // we're running on - - // |W| - Windows, |M| - Mac OS X, |L| - Linux - - // Adding a 'not' symbol means it WON'T run on that - // platform (i.e. |!W| won't run on Windows) - - if (scriptName[0] == '|') - { - int len = strlen(scriptName); - if (len > 2) - { - if (scriptName[1] == '!' && len > 3 && scriptName[3] == scriptName[0]) - { - if (toupper(scriptName[2]) == platform[0]) - continue; - } - if (scriptName[2] == scriptName[0] && toupper(scriptName[1]) != platform[0]) - continue; - } - } - - int state; - - evalString(string, fname, &state); - if (state) - break; - } - - VALUE exc = rb_gv_get("$!"); - if (rb_obj_class(exc) != getRbData()->exc[Reset]) - break; - - processReset(); - } -} -#endif - -static void showExc(VALUE exc, const BacktraceData &btData) -{ - VALUE bt = rb_funcall2(exc, rb_intern("backtrace"), 0, NULL); - VALUE msg = rb_funcall2(exc, rb_intern("message"), 0, NULL); - VALUE bt0 = rb_ary_entry(bt, 0); - VALUE name = rb_class_path(rb_obj_class(exc)); - - VALUE ds = rb_sprintf("%" PRIsVALUE ": %" PRIsVALUE " (%" PRIsVALUE ")", - bt0, exc, name); - /* omit "useless" last entry (from ruby:1:in `eval') */ - for (long i = 1, btlen = RARRAY_LEN(bt) - 1; i < btlen; ++i) - rb_str_catf(ds, "\n\tfrom %" PRIsVALUE, rb_ary_entry(bt, i)); - Debug() << StringValueCStr(ds); - - char *s = RSTRING_PTR(bt0); - - char line[16]; - std::string file(512, '\0'); - - char *p = s + strlen(s); - char *e; - - while (p != s) - if (*--p == ':') - break; - - e = p; - - while (p != s) - if (*--p == ':') - break; - - /* s p e - * SectionXXX:YY: in 'blabla' */ - - *e = '\0'; - strncpy(line, *p ? p+1 : p, sizeof(line)); - line[sizeof(line)-1] = '\0'; - *e = ':'; - e = p; - - /* s e - * SectionXXX:YY: in 'blabla' */ - - *e = '\0'; - strncpy(&file[0], s, file.size()); - *e = ':'; - - /* Shrink to fit */ - file.resize(strlen(file.c_str())); - file = btData.scriptNames.value(file, file); - - std::string ms(640, '\0'); - snprintf(&ms[0], ms.size(), "Script '%s' line %s: %s occured.\n\n%s", - file.c_str(), line, RSTRING_PTR(name), RSTRING_PTR(msg)); - - showMsg(ms); -} - -static void mriBindingExecute() -{ -#ifndef OLD_RUBY - /* Normally only a ruby executable would do a sysinit, - * but not doing it will lead to crashes due to closed - * stdio streams on some platforms (eg. Windows) */ - int argc = 0; - char **argv = 0; - ruby_sysinit(&argc, &argv); - - ruby_setup(); - rb_enc_set_default_external(rb_enc_from_encoding(rb_utf8_encoding())); -#else - ruby_init(); - rb_eval_string("$KCODE='U'"); -#endif - -#if defined(USE_FAKEAPI) && !defined(__WIN32__) - char *tmpdir = getenv("TMPDIR"); - if (tmpdir) setenv("TEMP", tmpdir, false); -#endif - - Config &conf = shState->rtData().config; - - VALUE lpaths = rb_gv_get(":"); - if (!conf.rubyLoadpaths.empty()) - { - /* Setup custom load paths */ - for (size_t i = 0; i < conf.rubyLoadpaths.size(); ++i) - { - std::string &path = conf.rubyLoadpaths[i]; - - VALUE pathv = rb_str_new(path.c_str(), path.size()); - rb_ary_push(lpaths, pathv); - } - } -#ifdef MARIN - else - { - rb_ary_push(lpaths, rb_str_new_cstr("ruby/extensions/2.5.0")); - rb_ary_push(lpaths, rb_str_new_cstr("ruby/extensions/2.5.0/i386-mingw32")); + decodeBuffer.resize(decodeBuffer.size() * 2); } + + if (result != Z_OK) { + static char buffer[256]; + snprintf(buffer, sizeof(buffer), "Error decoding script %ld: '%s'", i, + RSTRING_PTR(scriptName)); + + showMsg(buffer); + + break; + } + + rb_ary_store(script, 3, rb_str_new_cstr(decodeBuffer.c_str())); + } + + // Can be force-disabled similarly to framerate options +#ifndef NO_PRELOAD_SCRIPTS + /* Execute preloaded scripts */ + for (std::vector::const_iterator i = conf.preloadScripts.begin(); + i != conf.preloadScripts.end(); ++i) + runCustomScript(*i); + + VALUE exc = rb_gv_get("$!"); + if (exc != Qnil) + return; #endif - RbData rbData; - shState->setBindingData(&rbData); - BacktraceData btData; + while (true) { +#if defined(OLD_RUBY) && defined(NO_CONSOLE) + VALUE iostr = rb_str_new2(NULL_IO); + // Sysinit isn't a thing yet, so send io to /dev/null instead + rb_funcall(rb_gv_get("$stderr"), rb_intern("reopen"), 1, iostr); + rb_funcall(rb_gv_get("$stdout"), rb_intern("reopen"), 1, iostr); +#endif + for (long i = 0; i < scriptCount; ++i) { + VALUE script = rb_ary_entry(scriptArray, i); + VALUE scriptDecoded = rb_ary_entry(script, 3); + VALUE string = + newStringUTF8(RSTRING_PTR(scriptDecoded), RSTRING_LEN(scriptDecoded)); - mriBindingInit(); + VALUE fname; + const char *scriptName = RSTRING_PTR(rb_ary_entry(script, 1)); + char buf[512]; + int len; - std::string &customScript = conf.customScript; - if (!customScript.empty()) - runCustomScript(customScript); - else -#ifdef MARIN - runCustomScript("ruby/scripts/requires.rb"); + if (conf.useScriptNames) + len = snprintf(buf, sizeof(buf), "%03ld:%s", i, scriptName); + else + len = snprintf(buf, sizeof(buf), SCRIPT_SECTION_FMT, i); + + fname = newStringUTF8(buf, len); + btData.scriptNames.insert(buf, scriptName); + + // if the script name starts with |s|, only execute + // it if "s" is the same first letter as the platform + // we're running on + + // |W| - Windows, |M| - Mac OS X, |L| - Linux + + // Adding a 'not' symbol means it WON'T run on that + // platform (i.e. |!W| won't run on Windows) + + if (scriptName[0] == '|') { + int len = strlen(scriptName); + if (len > 2) { + if (scriptName[1] == '!' && len > 3 && + scriptName[3] == scriptName[0]) { + if (toupper(scriptName[2]) == platform[0]) + continue; + } + if (scriptName[2] == scriptName[0] && + toupper(scriptName[1]) != platform[0]) + continue; + } + } + + int state; + + evalString(string, fname, &state); + if (state) + break; + } + + VALUE exc = rb_gv_get("$!"); + if (rb_obj_class(exc) != getRbData()->exc[Reset]) + break; + + processReset(); + } +} +#endif + +static void showExc(VALUE exc, const BacktraceData &btData) { + VALUE bt = rb_funcall2(exc, rb_intern("backtrace"), 0, NULL); + VALUE msg = rb_funcall2(exc, rb_intern("message"), 0, NULL); + VALUE bt0 = rb_ary_entry(bt, 0); + VALUE name = rb_class_path(rb_obj_class(exc)); + + VALUE ds = rb_sprintf("%" PRIsVALUE ": %" PRIsVALUE " (%" PRIsVALUE ")", bt0, + exc, name); + /* omit "useless" last entry (from ruby:1:in `eval') */ + for (long i = 1, btlen = RARRAY_LEN(bt) - 1; i < btlen; ++i) + rb_str_catf(ds, "\n\tfrom %" PRIsVALUE, rb_ary_entry(bt, i)); + Debug() << StringValueCStr(ds); + + char *s = RSTRING_PTR(bt0); + + char line[16]; + std::string file(512, '\0'); + + char *p = s + strlen(s); + char *e; + + while (p != s) + if (*--p == ':') + break; + + e = p; + + while (p != s) + if (*--p == ':') + break; + + /* s p e + * SectionXXX:YY: in 'blabla' */ + + *e = '\0'; + strncpy(line, *p ? p + 1 : p, sizeof(line)); + line[sizeof(line) - 1] = '\0'; + *e = ':'; + e = p; + + /* s e + * SectionXXX:YY: in 'blabla' */ + + *e = '\0'; + strncpy(&file[0], s, file.size()); + *e = ':'; + + /* Shrink to fit */ + file.resize(strlen(file.c_str())); + file = btData.scriptNames.value(file, file); + + std::string ms(640, '\0'); + snprintf(&ms[0], ms.size(), "Script '%s' line %s: %s occured.\n\n%s", + file.c_str(), line, RSTRING_PTR(name), RSTRING_PTR(msg)); + + showMsg(ms); +} + +static void mriBindingExecute() { +#ifndef OLD_RUBY + /* Normally only a ruby executable would do a sysinit, + * but not doing it will lead to crashes due to closed + * stdio streams on some platforms (eg. Windows) */ + int argc = 0; + char **argv = 0; + ruby_sysinit(&argc, &argv); + + ruby_setup(); + rb_enc_set_default_external(rb_enc_from_encoding(rb_utf8_encoding())); #else - runRMXPScripts(btData); + ruby_init(); + rb_eval_string("$KCODE='U'"); +#endif + +#if defined(USE_FAKEAPI) && !defined(__WIN32__) + char *tmpdir = getenv("TMPDIR"); + if (tmpdir) + setenv("TEMP", tmpdir, false); +#endif + + Config &conf = shState->rtData().config; + + VALUE lpaths = rb_gv_get(":"); + if (!conf.rubyLoadpaths.empty()) { + /* Setup custom load paths */ + for (size_t i = 0; i < conf.rubyLoadpaths.size(); ++i) { + std::string &path = conf.rubyLoadpaths[i]; + + VALUE pathv = rb_str_new(path.c_str(), path.size()); + rb_ary_push(lpaths, pathv); + } + } +#ifdef MARIN + else { + rb_ary_push(lpaths, rb_str_new_cstr("ruby/extensions/2.5.0")); + rb_ary_push(lpaths, rb_str_new_cstr("ruby/extensions/2.5.0/i386-mingw32")); + } +#endif + + RbData rbData; + shState->setBindingData(&rbData); + BacktraceData btData; + + mriBindingInit(); + + std::string &customScript = conf.customScript; + if (!customScript.empty()) + runCustomScript(customScript); + else +#ifdef MARIN + runCustomScript("ruby/scripts/requires.rb"); +#else + runRMXPScripts(btData); #endif #ifndef OLD_RUBY - VALUE exc = rb_errinfo(); + VALUE exc = rb_errinfo(); #else - VALUE exc = rb_gv_get("$!"); + VALUE exc = rb_gv_get("$!"); #endif - if (!NIL_P(exc) && !rb_obj_is_kind_of(exc, rb_eSystemExit)) - showExc(exc, btData); + if (!NIL_P(exc) && !rb_obj_is_kind_of(exc, rb_eSystemExit)) + showExc(exc, btData); - ruby_cleanup(0); + ruby_cleanup(0); - shState->rtData().rqTermAck.set(); + shState->rtData().rqTermAck.set(); } -static void mriBindingTerminate() -{ - rb_raise(rb_eSystemExit, " "); -} +static void mriBindingTerminate() { rb_raise(rb_eSystemExit, " "); } -static void mriBindingReset() -{ - rb_raise(getRbData()->exc[Reset], " "); -} +static void mriBindingReset() { rb_raise(getRbData()->exc[Reset], " "); } diff --git a/binding/meson.build b/binding/meson.build index 75abda5d..9981166a 100644 --- a/binding/meson.build +++ b/binding/meson.build @@ -29,12 +29,15 @@ binding_source = [files( 'module_rpg.cpp', 'filesystem-binding.cpp', 'windowvx-binding.cpp', - 'tilemapvx-binding.cpp', - 'miniffi-binding.cpp' + 'tilemapvx-binding.cpp' )] if discord == true binding_source += files('discord-binding.cpp') endif +if miniffi == true + binding_source += files('miniffi-binding.cpp') +endif + global_sources += binding_source diff --git a/meson.build b/meson.build index 9f835b39..0c7b92d4 100644 --- a/meson.build +++ b/meson.build @@ -53,6 +53,20 @@ if compilers['objc'].get_id() == 'clang' global_args += ['-Wno-undefined-var-template', '-Wno-delete-non-abstract-non-virtual-dtor'] endif +# Decide whether or not to use MiniFFI +miniffi = get_option('use_miniffi') +if miniffi == true + if compilers['cpp'].sizeof('void*') == compilers['cpp'].sizeof('long') + miniffi = true + global_args += '-DUSE_MINIFFI' + else + warning('64-bit MiniFFI is only supported on Linux and macOS.') + warning('To use MiniFFI/Win32API on Windows, target 32-bit.') + miniffi = false + endif +endif + +# Defines if get_option('workdir_current') global_args += '-DWORKDIR_CURRENT' endif @@ -61,7 +75,7 @@ if get_option('independent_appimage') global_args += '-DINDEPENDENT_APPIMAGE' endif -if get_option('use_fakeapi') +if get_option('use_fakeapi') == true and miniffi == true global_args += '-DUSE_FAKEAPI' endif @@ -73,6 +87,7 @@ if get_option('mk') global_args += '-DMARIN' endif + # Objectify our C global_args += run_command(objfw,'--cppflags').stdout().split() add_project_arguments(run_command(objfw,'--objcflags').stdout().split(), language:['objc','objcpp']) diff --git a/meson_options.txt b/meson_options.txt index efbb0fb8..e971a1fd 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -6,7 +6,8 @@ option('macos_min_version', type: 'string', value: '10.10', description: 'Minimu option('shared_fluid', type: 'boolean', value: false, description: 'Dynamically link fluidsynth at build time') option('cjk_fallback_font', type: 'boolean', value: false, description: 'Use WenQuanYi Micro Hei as the fallback font') -option('use_fakeapi', type: 'boolean', value: false, description: 'Attempt to repair Win32API calls that do not work with MKXP') +option('use_miniffi', type: 'boolean', value: true, description: 'Enable MiniFFI Ruby module (Win32API)') +option('use_fakeapi', type: 'boolean', value: false, description: 'Attempt to repair Win32API calls that do not work with MKXP. Requires MiniFFI') option('default_framerate', type: 'boolean', value: false, description: 'Disable syncToRefreshrate and fixedFramerate configuration options') option('no_preload_scripts', type: 'boolean', value: false, description: 'Disable the preloadScript configuration option') option('workdir_current', type: 'boolean', value: false, description: 'Keep current directory on startup') diff --git a/src/meson.build b/src/meson.build index 60c621a4..9321d9ca 100644 --- a/src/meson.build +++ b/src/meson.build @@ -83,7 +83,7 @@ main_source = files( 'lang-fun.mm' ) -if get_option('use_fakeapi') == true +if get_option('use_fakeapi') == true and miniffi == true main_source += files('fake-api.mm') endif