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.
This commit is contained in:
parent
3a2e560139
commit
d223d83cbf
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "util.h"
|
||||
#include "debugwriter.h"
|
||||
#include "graphics.h"
|
||||
#include "audio.h"
|
||||
#include "boost-hash.h"
|
||||
|
||||
#include <ruby.h>
|
||||
|
@ -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,6 +437,8 @@ static void runRMXPScripts(BacktraceData &btData)
|
|||
for (size_t i = 0; i < conf.preloadScripts.size(); ++i)
|
||||
runCustomScript(conf.preloadScripts[i]);
|
||||
|
||||
while (true)
|
||||
{
|
||||
for (long i = 0; i < scriptCount; ++i)
|
||||
{
|
||||
VALUE script = rb_ary_entry(scriptArray, i);
|
||||
|
@ -420,6 +464,13 @@ static void runRMXPScripts(BacktraceData &btData)
|
|||
if (state)
|
||||
break;
|
||||
}
|
||||
|
||||
VALUE exc = rb_gv_get("$!");
|
||||
if (rb_obj_class(exc) != getRbData()->exc[Reset])
|
||||
break;
|
||||
|
||||
processReset();
|
||||
}
|
||||
}
|
||||
|
||||
static void showExc(VALUE exc, const BacktraceData &btData)
|
||||
|
@ -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], " ");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
enum RbException
|
||||
{
|
||||
RGSS = 0,
|
||||
Reset,
|
||||
PHYSFS,
|
||||
SDL,
|
||||
MKXP,
|
||||
|
|
|
@ -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" );
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -99,6 +99,12 @@
|
|||
# anyAltToggleFS=false
|
||||
|
||||
|
||||
# Enable F12 game reset
|
||||
# (default: enabled)
|
||||
#
|
||||
# enableReset=true
|
||||
|
||||
|
||||
# Allow symlinks for game assets to be followed
|
||||
# (default: disabled)
|
||||
#
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -67,6 +67,8 @@ public:
|
|||
float bgmPos();
|
||||
float bgsPos();
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
Audio(const Config &conf);
|
||||
~Audio();
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -47,6 +47,7 @@ struct Config
|
|||
|
||||
std::string gameFolder;
|
||||
bool anyAltToggleFS;
|
||||
bool enableReset;
|
||||
bool allowSymlinks;
|
||||
bool pathCache;
|
||||
|
||||
|
|
|
@ -22,7 +22,10 @@
|
|||
#ifndef DISPOSABLE_H
|
||||
#define DISPOSABLE_H
|
||||
|
||||
#include "intrulist.h"
|
||||
#include "exception.h"
|
||||
#include "sharedstate.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <sigc++/signal.h>
|
||||
|
@ -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<Disposable> link;
|
||||
};
|
||||
|
||||
template<class C>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <SDL_joystick.h>
|
||||
#include <SDL_mouse.h>
|
||||
#include <SDL_mutex.h>
|
||||
#include <SDL_atomic.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -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),
|
||||
|
|
|
@ -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<Disposable> 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<Disposable> *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);
|
||||
}
|
||||
|
|
|
@ -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:
|
|||
/* <internal> */
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -105,6 +105,15 @@ public:
|
|||
size--;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
remove(root);
|
||||
root.prev = &root;
|
||||
root.next = &root;
|
||||
|
||||
size = 0;
|
||||
}
|
||||
|
||||
T *tail() const
|
||||
{
|
||||
IntruListLink<T> *node = root.prev;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -109,6 +109,8 @@ struct SharedState
|
|||
* function will most likely not return */
|
||||
void checkShutdown();
|
||||
|
||||
void checkReset();
|
||||
|
||||
static SharedState *instance;
|
||||
static int rgssVersion;
|
||||
|
||||
|
|
Loading…
Reference in New Issue