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
					
				
					 23 changed files with 343 additions and 60 deletions
				
			
		| 
						 | 
				
			
			@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue