From d223d83cbf8240677049c8334ffb347b948f7a2b Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Sun, 24 Aug 2014 07:36:19 +0200 Subject: [PATCH] Implement F12 game reset (MRI only) Can be disabled with "enableReset=false". While at it, also replace the flakey volatile bool flags with proper atomics. --- README.md | 2 - binding-mri/audio-binding.cpp | 11 ++++ binding-mri/binding-mri.cpp | 100 ++++++++++++++++++++++++------- binding-mri/binding-util.cpp | 2 + binding-mri/binding-util.h | 1 + binding-mri/graphics-binding.cpp | 11 ++++ binding-mruby/binding-mruby.cpp | 11 +++- binding-null/binding-null.cpp | 10 +++- mkxp.conf.sample | 6 ++ src/audio.cpp | 8 +++ src/audio.h | 2 + src/binding.h | 4 ++ src/config.cpp | 2 + src/config.h | 1 + src/disposable.h | 15 ++++- src/eventthread.cpp | 32 +++++++++- src/eventthread.h | 54 +++++++++++++---- src/graphics.cpp | 89 ++++++++++++++++++++++++--- src/graphics.h | 14 ++++- src/intrulist.h | 9 +++ src/main.cpp | 6 +- src/sharedstate.cpp | 11 +++- src/sharedstate.h | 2 + 23 files changed, 343 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index beea7dd..a29f067 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,6 @@ Missing RGSS3 functionality: * Text outline * Movie playback -* F12 reset * Audio fade-in Some other things might be implemented, but simply not bound yet. @@ -116,7 +115,6 @@ If a requested font is not found, no error is generated. Instead, a built-in fon * wma audio files * The Win32API ruby class (for obvious reasons) -* Restarting the game with F12 * Creating Bitmaps with sizes greater than the OpenGL texture size limit (around 8192 on modern cards)* \* There is an exception to this, called *mega surface*. When a Bitmap bigger than the texture limit is created from a file, it is not stored in VRAM, but regular RAM. Its sole purpose is to be used as a tileset bitmap. Any other operation to it (besides blitting to a regular Bitmap) will result in an error. diff --git a/binding-mri/audio-binding.cpp b/binding-mri/audio-binding.cpp index 4c8952e..262f5c7 100644 --- a/binding-mri/audio-binding.cpp +++ b/binding-mri/audio-binding.cpp @@ -97,6 +97,15 @@ DEF_FADE( me ) DEF_PLAY_STOP( se ) +RB_METHOD(audioReset) +{ + RB_UNUSED_PARAM; + + shState->audio().reset(); + + return Qnil; +} + #define BIND_PLAY_STOP(entity) \ _rb_define_module_function(module, #entity "_play", audio_##entity##Play); \ @@ -129,4 +138,6 @@ audioBindingInit() } BIND_PLAY_STOP( se ) + + _rb_define_module_function(module, "__reset__", audioReset); } diff --git a/binding-mri/binding-mri.cpp b/binding-mri/binding-mri.cpp index 7178d75..b8d4445 100644 --- a/binding-mri/binding-mri.cpp +++ b/binding-mri/binding-mri.cpp @@ -27,6 +27,7 @@ #include "util.h" #include "debugwriter.h" #include "graphics.h" +#include "audio.h" #include "boost-hash.h" #include @@ -44,11 +45,13 @@ extern const char module_rpg3[]; static void mriBindingExecute(); static void mriBindingTerminate(); +static void mriBindingReset(); ScriptBinding scriptBindingImpl = { mriBindingExecute, - mriBindingTerminate + mriBindingTerminate, + mriBindingReset }; ScriptBinding *scriptBinding = &scriptBindingImpl; @@ -213,12 +216,51 @@ RB_METHOD(mriDataDirectory) return pathStr; } +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; + + *excRet = exc; + + return Qnil; +} + +static void processReset() +{ + shState->graphics().reset(); + shState->audio().reset(); + + shState->rtData().rqReset.clear(); + shState->graphics().repaintWait(shState->rtData().rqResetFinish, + false); +} + RB_METHOD(mriRgssMain) { RB_UNUSED_PARAM; - // TODO: Implement F12 reset - rb_yield(Qnil); + while (true) + { + VALUE exc = Qnil; + + rb_rescue2((VALUE(*)(ANYARGS)) rgssMainCb, rb_block_proc(), + (VALUE(*)(ANYARGS)) rgssMainRescue, (VALUE) &exc, + rb_eException, (VALUE) 0); + + if (NIL_P(exc)) + break; + + if (rb_obj_class(exc) == getRbData()->exc[Reset]) + processReset(); + else + rb_exc_raise(exc); + } return Qnil; } @@ -395,30 +437,39 @@ static void runRMXPScripts(BacktraceData &btData) for (size_t i = 0; i < conf.preloadScripts.size(); ++i) runCustomScript(conf.preloadScripts[i]); - for (long i = 0; i < scriptCount; ++i) + while (true) { - VALUE script = rb_ary_entry(scriptArray, i); - VALUE scriptDecoded = rb_ary_entry(script, 3); - VALUE string = newStringUTF8(RSTRING_PTR(scriptDecoded), - RSTRING_LEN(scriptDecoded)); + 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; + 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); + 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); + fname = newStringUTF8(buf, len); + btData.scriptNames.insert(buf, scriptName); - int state; - evalString(string, fname, &state); - if (state) + int state; + evalString(string, fname, &state); + if (state) + break; + } + + VALUE exc = rb_gv_get("$!"); + if (rb_obj_class(exc) != getRbData()->exc[Reset]) break; + + processReset(); } } @@ -520,10 +571,15 @@ static void mriBindingExecute() ruby_cleanup(0); - shState->rtData().rqTermAck = true; + shState->rtData().rqTermAck.set(); } static void mriBindingTerminate() { rb_raise(rb_eSystemExit, " "); } + +static void mriBindingReset() +{ + rb_raise(getRbData()->exc[Reset], " "); +} diff --git a/binding-mri/binding-util.cpp b/binding-mri/binding-util.cpp index 5843ad3..33438b1 100644 --- a/binding-mri/binding-util.cpp +++ b/binding-mri/binding-util.cpp @@ -51,6 +51,8 @@ RbData::RbData() for (size_t i = 0; i < ARRAY_SIZE(customExc); ++i) exc[customExc[i].id] = rb_define_class(customExc[i].name, rb_eException); + exc[Reset] = rb_define_class(rgssVer >= 3 ? "RGSSReset" : "Reset", rb_eException); + exc[ErrnoENOENT] = rb_const_get(rb_const_get(rb_cObject, rb_intern("Errno")), rb_intern("ENOENT")); exc[IOError] = rb_eIOError; exc[TypeError] = rb_eTypeError; diff --git a/binding-mri/binding-util.h b/binding-mri/binding-util.h index b84a50b..6deac5d 100644 --- a/binding-mri/binding-util.h +++ b/binding-mri/binding-util.h @@ -29,6 +29,7 @@ enum RbException { RGSS = 0, + Reset, PHYSFS, SDL, MKXP, diff --git a/binding-mri/graphics-binding.cpp b/binding-mri/graphics-binding.cpp index 20bf593..c28be77 100644 --- a/binding-mri/graphics-binding.cpp +++ b/binding-mri/graphics-binding.cpp @@ -174,6 +174,15 @@ RB_METHOD(graphicsResizeScreen) return Qnil; } +RB_METHOD(graphicsReset) +{ + RB_UNUSED_PARAM; + + shState->graphics().reset(); + + return Qnil; +} + DEF_GRA_PROP_I(FrameRate) DEF_GRA_PROP_I(FrameCount) DEF_GRA_PROP_I(Brightness) @@ -196,6 +205,8 @@ void graphicsBindingInit() _rb_define_module_function(module, "transition", graphicsTransition); _rb_define_module_function(module, "frame_reset", graphicsFrameReset); + _rb_define_module_function(module, "__reset__", graphicsReset); + INIT_GRA_PROP_BIND( FrameRate, "frame_rate" ); INIT_GRA_PROP_BIND( FrameCount, "frame_count" ); diff --git a/binding-mruby/binding-mruby.cpp b/binding-mruby/binding-mruby.cpp index ad092db..dc1eb40 100644 --- a/binding-mruby/binding-mruby.cpp +++ b/binding-mruby/binding-mruby.cpp @@ -51,11 +51,13 @@ static void mrbBindingExecute(); static void mrbBindingTerminate(); +static void mrbBindingReset(); ScriptBinding scriptBindingImpl = { mrbBindingExecute, - mrbBindingTerminate + mrbBindingTerminate, + mrbBindingReset }; ScriptBinding *scriptBinding = &scriptBindingImpl; @@ -384,7 +386,7 @@ static void mrbBindingExecute() checkException(mrb); - shState->rtData().rqTermAck = true; + shState->rtData().rqTermAck.set(); shState->texPool().disable(); mrbc_context_free(mrb, ctx); @@ -398,3 +400,8 @@ static void mrbBindingTerminate() mrb_raise(mrb, data->exc[Shutdown], ""); } + +static void mrbBindingReset() +{ + // No idea how to do this with mruby yet +} diff --git a/binding-null/binding-null.cpp b/binding-null/binding-null.cpp index 62f4edb..a4799e3 100644 --- a/binding-null/binding-null.cpp +++ b/binding-null/binding-null.cpp @@ -27,7 +27,7 @@ static void nullBindingExecute() { Debug() << "The null binding doesn't do anything, so we're done!"; - shState->rtData().rqTermAck = true; + shState->rtData().rqTermAck.set(); } static void nullBindingTerminate() @@ -35,10 +35,16 @@ static void nullBindingTerminate() } +static void nullBindingReset() +{ + +} + ScriptBinding scriptBindingImpl = { nullBindingExecute, - nullBindingTerminate + nullBindingTerminate, + nullBindingReset }; ScriptBinding *scriptBinding = &scriptBindingImpl; diff --git a/mkxp.conf.sample b/mkxp.conf.sample index 78c0ffc..2f119f4 100644 --- a/mkxp.conf.sample +++ b/mkxp.conf.sample @@ -99,6 +99,12 @@ # anyAltToggleFS=false +# Enable F12 game reset +# (default: enabled) +# +# enableReset=true + + # Allow symlinks for game assets to be followed # (default: disabled) # diff --git a/src/audio.cpp b/src/audio.cpp index b99ab04..dcc0b90 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -327,4 +327,12 @@ float Audio::bgsPos() return p->bgs.playingOffset(); } +void Audio::reset() +{ + p->bgm.stop(); + p->bgs.stop(); + p->me.stop(); + p->se.stop(); +} + Audio::~Audio() { delete p; } diff --git a/src/audio.h b/src/audio.h index b600f54..ea2a357 100644 --- a/src/audio.h +++ b/src/audio.h @@ -67,6 +67,8 @@ public: float bgmPos(); float bgsPos(); + void reset(); + private: Audio(const Config &conf); ~Audio(); diff --git a/src/binding.h b/src/binding.h index 7b839e0..4f20b35 100644 --- a/src/binding.h +++ b/src/binding.h @@ -35,6 +35,10 @@ struct ScriptBinding * function will perform a longjmp instead of returning, * so be careful about any variables with local storage */ void (*terminate) (void); + + /* Instructs the binding to issue a game reset. + * Same conditions as for terminate apply */ + void (*reset) (void); }; /* VTable defined in the binding source */ diff --git a/src/config.cpp b/src/config.cpp index 8abc66b..62d0676 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -138,6 +138,7 @@ Config::Config() solidFonts(false), gameFolder("."), anyAltToggleFS(false), + enableReset(true), allowSymlinks(false), pathCache(true), useScriptNames(false) @@ -164,6 +165,7 @@ void Config::read(int argc, char *argv[]) PO_DESC(solidFonts, bool) \ PO_DESC(gameFolder, std::string) \ PO_DESC(anyAltToggleFS, bool) \ + PO_DESC(enableReset, bool) \ PO_DESC(allowSymlinks, bool) \ PO_DESC(iconPath, std::string) \ PO_DESC(titleLanguage, std::string) \ diff --git a/src/config.h b/src/config.h index e47cc32..78d75f7 100644 --- a/src/config.h +++ b/src/config.h @@ -47,6 +47,7 @@ struct Config std::string gameFolder; bool anyAltToggleFS; + bool enableReset; bool allowSymlinks; bool pathCache; diff --git a/src/disposable.h b/src/disposable.h index 412b058..afa39be 100644 --- a/src/disposable.h +++ b/src/disposable.h @@ -22,7 +22,10 @@ #ifndef DISPOSABLE_H #define DISPOSABLE_H +#include "intrulist.h" #include "exception.h" +#include "sharedstate.h" +#include "graphics.h" #include #include @@ -32,12 +35,15 @@ class Disposable { public: Disposable() - : disposed(false) - {} + : disposed(false), + link(this) + { + shState->graphics().addDisposable(this); + } virtual ~Disposable() { - assert(disposed); + shState->graphics().remDisposable(this); } void dispose() @@ -69,7 +75,10 @@ private: virtual void releaseResources() = 0; virtual const char *klassName() const = 0; + friend class Graphics; + bool disposed; + IntruListLink link; }; template diff --git a/src/eventthread.cpp b/src/eventthread.cpp index 7348c32..fec1e5b 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -106,6 +106,8 @@ void EventThread::process(RGSSThreadData &rtData) char pendingTitle[128]; bool havePendingTitle = false; + bool resetting = false; + while (true) { if (!SDL_WaitEvent(&event)) @@ -206,10 +208,34 @@ void EventThread::process(RGSSThreadData &rtData) break; } + if (event.key.keysym.scancode == SDL_SCANCODE_F12) + { + if (!rtData.config.enableReset) + break; + + if (resetting) + break; + + resetting = true; + rtData.rqResetFinish.clear(); + rtData.rqReset.set(); + break; + } + keyStates[event.key.keysym.scancode] = true; break; case SDL_KEYUP : + if (event.key.keysym.scancode == SDL_SCANCODE_F12) + { + if (!rtData.config.enableReset) + break; + + resetting = false; + rtData.rqResetFinish.set(); + break; + } + keyStates[event.key.keysym.scancode] = false; break; @@ -271,7 +297,7 @@ void EventThread::process(RGSSThreadData &rtData) rtData.config.game.title.c_str(), (const char*) event.user.data1, win); free(event.user.data1); - msgBoxDone = true; + msgBoxDone.set(); break; case REQUEST_SETCURSORVISIBLE : @@ -377,7 +403,7 @@ void EventThread::requestShowCursor(bool mode) void EventThread::showMessageBox(const char *body, int flags) { - msgBoxDone = false; + msgBoxDone.clear(); SDL_Event event; event.user.code = flags; @@ -386,7 +412,7 @@ void EventThread::showMessageBox(const char *body, int flags) SDL_PushEvent(&event); /* Keep repainting screen while box is open */ - shState->graphics().repaintWait(&msgBoxDone); + shState->graphics().repaintWait(msgBoxDone); /* Prevent endless loops */ resetInputStates(); } diff --git a/src/eventthread.h b/src/eventthread.h index 79ac199..23402c5 100644 --- a/src/eventthread.h +++ b/src/eventthread.h @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -38,6 +39,32 @@ struct RGSSThreadData; struct SDL_Thread; struct SDL_Window; +struct AtomicFlag +{ + AtomicFlag() + { + clear(); + } + + void set() + { + SDL_AtomicSet(&atom, 1); + } + + void clear() + { + SDL_AtomicSet(&atom, 0); + } + + operator bool() const + { + return SDL_AtomicGet(&atom); + } + +private: + mutable SDL_atomic_t atom; +}; + class EventThread { public: @@ -91,7 +118,7 @@ private: bool fullscreen; bool showCursor; - volatile bool msgBoxDone; + AtomicFlag msgBoxDone; struct { @@ -111,13 +138,12 @@ struct WindowSizeNotify { SDL_mutex *mutex; - volatile bool changedFlag; - volatile int w, h; + AtomicFlag changed; + int w, h; WindowSizeNotify() { mutex = SDL_CreateMutex(); - changedFlag = false; w = h = 0; } @@ -133,7 +159,7 @@ struct WindowSizeNotify this->w = w; this->h = h; - changedFlag = true; + changed.set(); SDL_UnlockMutex(mutex); } @@ -141,14 +167,14 @@ struct WindowSizeNotify /* Done from the receiving side */ bool pollChange(int *w, int *h) { - if (!changedFlag) + if (!changed) return false; SDL_LockMutex(mutex); *w = this->w; *h = this->h; - changedFlag = false; + changed.clear(); SDL_UnlockMutex(mutex); @@ -159,10 +185,16 @@ struct WindowSizeNotify struct RGSSThreadData { /* Main thread sets this to request RGSS thread to terminate */ - volatile bool rqTerm; + AtomicFlag rqTerm; /* In response, RGSS thread sets this to confirm * that it received the request and isn't stuck */ - volatile bool rqTermAck; + AtomicFlag rqTermAck; + + /* Set when F12 is pressed */ + AtomicFlag rqReset; + + /* Set when F12 is released */ + AtomicFlag rqResetFinish; EventThread *ethread; WindowSizeNotify windowSizeMsg; @@ -182,9 +214,7 @@ struct RGSSThreadData const char *argv0, SDL_Window *window, const Config& newconf) - : rqTerm(false), - rqTermAck(false), - ethread(ethread), + : ethread(ethread), argv0(argv0), window(window), sizeResoRatio(1, 1), diff --git a/src/graphics.cpp b/src/graphics.cpp index ebcc456..ecf850f 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -33,6 +33,8 @@ #include "texpool.h" #include "bitmap.h" #include "etc-internal.h" +#include "disposable.h" +#include "intrulist.h" #include "binding.h" #include "debugwriter.h" @@ -109,6 +111,19 @@ struct PingPong bind(); } + void clearBuffers() + { + glState.clearColor.pushSet(Vec4(0, 0, 0, 1)); + + for (int i = 0; i < 2; ++i) + { + FBO::bind(rt[i].fbo); + FBO::clear(); + } + + glState.clearColor.pop(); + } + private: void bind() { @@ -388,6 +403,10 @@ struct GraphicsPrivate Quad screenQuad; TEXFBO transBuffer; + /* Global list of all live Disposables + * (disposed on reset) */ + IntruList dispList; + GraphicsPrivate(RGSSThreadData *rtData) : scRes(DEF_SCREEN_W, DEF_SCREEN_H), scSize(scRes), @@ -472,9 +491,15 @@ struct GraphicsPrivate } } + void checkShutDownReset() + { + shState->checkShutdown(); + shState->checkReset(); + } + void shutdown() { - threadData->rqTermAck = true; + threadData->rqTermAck.set(); shState->texPool().disable(); scriptBinding->terminate(); @@ -540,7 +565,7 @@ Graphics::~Graphics() void Graphics::update() { - shState->checkShutdown(); + p->checkShutDownReset(); if (p->frozen) return; @@ -571,7 +596,7 @@ void Graphics::freeze() { p->frozen = true; - shState->checkShutdown(); + p->checkShutDownReset(); p->checkResize(); /* Capture scene into frozen buffer */ @@ -623,10 +648,23 @@ void Graphics::transition(int duration, for (int i = 0; i < duration; ++i) { + /* We need to clean up transMap properly before + * a possible longjmp, so we manually test for + * shutdown/reset here */ if (p->threadData->rqTerm) { + glState.blend.pop(); delete transMap; p->shutdown(); + return; + } + + if (p->threadData->rqReset) + { + glState.blend.pop(); + delete transMap; + scriptBinding->reset(); + return; } const float prog = i * (1.0 / duration); @@ -694,8 +732,7 @@ void Graphics::wait(int duration) { for (int i = 0; i < duration; ++i) { - shState->checkShutdown(); - p->checkResize(); + p->checkShutDownReset(); p->redrawScreen(); } } @@ -823,6 +860,29 @@ void Graphics::setBrightness(int value) p->screen.setBrightness(value / 255.0); } +void Graphics::reset() +{ + /* Dispose all live Disposables */ + IntruListLink *iter; + + for (iter = p->dispList.begin(); + iter != p->dispList.end(); + iter = iter->next) + { + iter->data->dispose(); + } + + p->dispList.clear(); + + /* Reset attributes (frame count not included) */ + p->fpsLimiter.resetFrameAdjust(); + p->frozen = false; + p->screen.getPP().clearBuffers(); + + setFrameRate(DEF_FRAMERATE); + setBrightness(255); +} + bool Graphics::getFullscreen() const { return p->threadData->ethread->getFullscreen(); @@ -848,9 +908,9 @@ Scene *Graphics::getScreen() const return &p->screen; } -void Graphics::repaintWait(volatile bool *exitCond) +void Graphics::repaintWait(const AtomicFlag &exitCond, bool checkReset) { - if (*exitCond) + if (exitCond) return; /* Repaint the screen with the last good frame we drew */ @@ -858,10 +918,13 @@ void Graphics::repaintWait(volatile bool *exitCond) GLMeta::blitBeginScreen(p->winSize); GLMeta::blitSource(lastFrame); - while (!*exitCond) + while (!exitCond) { shState->checkShutdown(); + if (checkReset) + shState->checkReset(); + FBO::clear(); p->metaBlitBufferFlippedScaled(); SDL_GL_SwapWindow(p->threadData->window); @@ -872,3 +935,13 @@ void Graphics::repaintWait(volatile bool *exitCond) GLMeta::blitEnd(); } + +void Graphics::addDisposable(Disposable *d) +{ + p->dispList.append(d->link); +} + +void Graphics::remDisposable(Disposable *d) +{ + p->dispList.remove(d->link); +} diff --git a/src/graphics.h b/src/graphics.h index b1ce016..05436bc 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -26,8 +26,10 @@ class Scene; class Bitmap; +class Disposable; struct RGSSThreadData; struct GraphicsPrivate; +struct AtomicFlag; class Graphics { @@ -53,6 +55,8 @@ public: int height() const; void resizeScreen(int width, int height); + void reset(); + /* Non-standard extension */ DECL_ATTR( Fullscreen, bool ) DECL_ATTR( ShowCursor, bool ) @@ -60,14 +64,20 @@ public: /* */ Scene *getScreen() const; /* Repaint screen with static image until exitCond - * turns true. Used in EThread::showMessageBox() */ - void repaintWait(volatile bool *exitCond); + * is set. Observes reset flag on top of shutdown + * if "checkReset" */ + void repaintWait(const AtomicFlag &exitCond, + bool checkReset = true); private: Graphics(RGSSThreadData *data); ~Graphics(); + void addDisposable(Disposable *); + void remDisposable(Disposable *); + friend struct SharedStatePrivate; + friend class Disposable; GraphicsPrivate *p; }; diff --git a/src/intrulist.h b/src/intrulist.h index fa691f6..040fb9b 100644 --- a/src/intrulist.h +++ b/src/intrulist.h @@ -105,6 +105,15 @@ public: size--; } + void clear() + { + remove(root); + root.prev = &root; + root.next = &root; + + size = 0; + } + T *tail() const { IntruListLink *node = root.prev; diff --git a/src/main.cpp b/src/main.cpp index b1403df..ae3def8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -46,7 +46,7 @@ rgssThreadError(RGSSThreadData *rtData, const std::string &msg) { rtData->rgssErrorMsg = msg; rtData->ethread->requestTerminate(); - rtData->rqTermAck = true; + rtData->rqTermAck.set(); } static inline const char* @@ -147,7 +147,7 @@ int rgssThreadFun(void *userdata) /* Start script execution */ scriptBinding->execute(); - threadData->rqTermAck = true; + threadData->rqTermAck.set(); threadData->ethread->requestTerminate(); SharedState::finiInstance(); @@ -276,7 +276,7 @@ int main(int argc, char *argv[]) eventThread.process(rtData); /* Request RGSS thread to stop */ - rtData.rqTerm = true; + rtData.rqTerm.set(); /* Wait for RGSS thread response */ for (int i = 0; i < 1000; ++i) diff --git a/src/sharedstate.cpp b/src/sharedstate.cpp index 27a632d..f28f30d 100644 --- a/src/sharedstate.cpp +++ b/src/sharedstate.cpp @@ -330,11 +330,20 @@ void SharedState::checkShutdown() if (!p->rtData.rqTerm) return; - p->rtData.rqTermAck = true; + p->rtData.rqTermAck.set(); p->texPool.disable(); scriptBinding->terminate(); } +void SharedState::checkReset() +{ + if (!p->rtData.rqReset) + return; + + p->rtData.rqReset.clear(); + scriptBinding->reset(); +} + Font &SharedState::defaultFont() const { return *p->defaultFont; diff --git a/src/sharedstate.h b/src/sharedstate.h index c713b26..d2d6f29 100644 --- a/src/sharedstate.h +++ b/src/sharedstate.h @@ -109,6 +109,8 @@ struct SharedState * function will most likely not return */ void checkShutdown(); + void checkReset(); + static SharedState *instance; static int rgssVersion;