From cab453ac3a230c1bb06488540f4706f6dad5b39a Mon Sep 17 00:00:00 2001
From: Jonas Kulla <Nyocurio@gmail.com>
Date: Thu, 11 May 2017 12:20:08 +0200
Subject: [PATCH 01/16] Graphics: Use proper resizing function for TEXFBOs

Manually resizing the contained TEX objects skips updating the
width/height TEXFBO properties, which GLMeta::blit relies on.
---
 src/graphics.cpp | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/src/graphics.cpp b/src/graphics.cpp
index d205697..8a6301a 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -92,11 +92,9 @@ struct PingPong
 	{
 		screenW = width;
 		screenH = height;
+
 		for (int i = 0; i < 2; ++i)
-		{
-			TEX::bind(rt[i].tex);
-			TEX::allocEmpty(width, height);
-		}
+			TEXFBO::allocEmpty(rt[i], width, height);
 	}
 
 	void startRender()
@@ -946,16 +944,13 @@ void Graphics::resizeScreen(int width, int height)
 
 	p->screen.setResolution(width, height);
 
-	TEX::bind(p->frozenScene.tex);
-	TEX::allocEmpty(width, height);
-	TEX::bind(p->currentScene.tex);
-	TEX::allocEmpty(width, height);
+	TEXFBO::allocEmpty(p->frozenScene, width, height);
+	TEXFBO::allocEmpty(p->currentScene, width, height);
 
 	FloatRect screenRect(0, 0, width, height);
 	p->screenQuad.setTexPosRect(screenRect, screenRect);
 
-	TEX::bind(p->transBuffer.tex);
-	TEX::allocEmpty(width, height);
+	TEXFBO::allocEmpty(p->transBuffer, width, height);
 
 	shState->eThread().requestWindowResize(width, height);
 }

From bd694f9f99566de6de98be48d75bee826f5103bb Mon Sep 17 00:00:00 2001
From: Jonas Kulla <Nyocurio@gmail.com>
Date: Thu, 11 May 2017 12:37:15 +0200
Subject: [PATCH 02/16] Graphics: Remove superfluous TEXFBOs while reusing
 existing ones

While the PingPong buffers were always texture-backed, currentScene
and transBuffer used to be backed by renderbuffers, which might have
been more optimized as render targets on older hardware; but since
all buffers in Graphics got switched to being texture backed to allow
blitting via rendering (when hardware blitting isn't available or broken,
eg. on mobile platforms), their reason to exist vanished.

For transBuffer, we can reuse the backbuffer of the PingPong structure,
while currentScene might have been useless from the start.
---
 src/graphics.cpp | 33 ++++++++++++---------------------
 1 file changed, 12 insertions(+), 21 deletions(-)

diff --git a/src/graphics.cpp b/src/graphics.cpp
index 8a6301a..6a12cb3 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -474,9 +474,7 @@ struct GraphicsPrivate
 
 	bool frozen;
 	TEXFBO frozenScene;
-	TEXFBO currentScene;
 	Quad screenQuad;
-	TEXFBO transBuffer;
 
 	/* Global list of all live Disposables
 	 * (disposed on reset) */
@@ -502,26 +500,15 @@ struct GraphicsPrivate
 		TEXFBO::allocEmpty(frozenScene, scRes.x, scRes.y);
 		TEXFBO::linkFBO(frozenScene);
 
-		TEXFBO::init(currentScene);
-		TEXFBO::allocEmpty(currentScene, scRes.x, scRes.y);
-		TEXFBO::linkFBO(currentScene);
-
 		FloatRect screenRect(0, 0, scRes.x, scRes.y);
 		screenQuad.setTexPosRect(screenRect, screenRect);
 
-		TEXFBO::init(transBuffer);
-		TEXFBO::allocEmpty(transBuffer, scRes.x, scRes.y);
-		TEXFBO::linkFBO(transBuffer);
-
 		fpsLimiter.resetFrameAdjust();
 	}
 
 	~GraphicsPrivate()
 	{
 		TEXFBO::fini(frozenScene);
-		TEXFBO::fini(currentScene);
-
-		TEXFBO::fini(transBuffer);
 	}
 
 	void updateScreenResoRatio(RGSSThreadData *rtData)
@@ -721,8 +708,15 @@ void Graphics::transition(int duration,
 
 	setBrightness(255);
 
+	/* The PP frontbuffer will hold the current scene after the
+	 * composition step. Since the backbuffer is unused during
+	 * the transition, we can reuse it as the target buffer for
+	 * the final rendered image. */
+	TEXFBO &currentScene = p->screen.getPP().frontBuffer();
+	TEXFBO &transBuffer  = p->screen.getPP().backBuffer();
+
 	/* Capture new scene */
-	p->compositeToBuffer(p->currentScene);
+	p->screen.composite();
 
 	/* If no transition bitmap is provided,
 	 * we can use a simplified shader */
@@ -735,7 +729,7 @@ void Graphics::transition(int duration,
 		shader.bind();
 		shader.applyViewportProj();
 		shader.setFrozenScene(p->frozenScene.tex);
-		shader.setCurrentScene(p->currentScene.tex);
+		shader.setCurrentScene(currentScene.tex);
 		shader.setTransMap(transMap->getGLTypes().tex);
 		shader.setVague(vague / 256.0f);
 		shader.setTexSize(p->scRes);
@@ -746,7 +740,7 @@ void Graphics::transition(int duration,
 		shader.bind();
 		shader.applyViewportProj();
 		shader.setFrozenScene(p->frozenScene.tex);
-		shader.setCurrentScene(p->currentScene.tex);
+		shader.setCurrentScene(currentScene.tex);
 		shader.setTexSize(p->scRes);
 	}
 
@@ -790,7 +784,7 @@ void Graphics::transition(int duration,
 
 		/* Draw the composed frame to a buffer first
 		 * (we need this because we're skipping PingPong) */
-		FBO::bind(p->transBuffer.fbo);
+		FBO::bind(transBuffer.fbo);
 		FBO::clear();
 		p->screenQuad.draw();
 
@@ -801,7 +795,7 @@ void Graphics::transition(int duration,
 		FBO::clear();
 
 		GLMeta::blitBeginScreen(Vec2i(p->winSize));
-		GLMeta::blitSource(p->transBuffer);
+		GLMeta::blitSource(transBuffer);
 		p->metaBlitBufferFlippedScaled();
 		GLMeta::blitEnd();
 
@@ -945,13 +939,10 @@ void Graphics::resizeScreen(int width, int height)
 	p->screen.setResolution(width, height);
 
 	TEXFBO::allocEmpty(p->frozenScene, width, height);
-	TEXFBO::allocEmpty(p->currentScene, width, height);
 
 	FloatRect screenRect(0, 0, width, height);
 	p->screenQuad.setTexPosRect(screenRect, screenRect);
 
-	TEXFBO::allocEmpty(p->transBuffer, width, height);
-
 	shState->eThread().requestWindowResize(width, height);
 }
 

From f5c30affaaa8f09187ebffebde44033d564b8e2e Mon Sep 17 00:00:00 2001
From: Marty Plummer <ntzrmtthihu777@gmail.com>
Date: Thu, 25 May 2017 04:39:45 -0500
Subject: [PATCH 03/16] mingw-w64: allow cmake cross-compile

Tested on gentoo with x86_64-w64-mingw32 toolchain and libraries.

Signed-off-by: Marty Plummer <ntzrmtthihu777@gmail.com>
---
 CMakeLists.txt | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d875826..7029f79 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -99,6 +99,7 @@ find_package(ZLIB REQUIRED)
 ## Setup main source ##
 
 set(MAIN_HEADERS
+	assets/resource.h
 	src/quadarray.h
 	src/audio.h
 	src/binding.h
@@ -205,6 +206,10 @@ set(MAIN_SOURCE
 	src/fluid-fun.cpp
 )
 
+if(WIN32)
+	list(APPEND MAIN_SOURCE assets/resource.rc)
+endif()
+
 source_group("MKXP Source" FILES ${MAIN_SOURCE} ${MAIN_HEADERS})
 
 ## Setup embedded source ##
@@ -404,6 +409,7 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE
 	${DEFINES}
 )
 target_include_directories(${PROJECT_NAME} PRIVATE
+	assets
 	src
 	${SIGCXX_INCLUDE_DIRS}
 	${PIXMAN_INCLUDE_DIRS}

From fba20e62944671c4b18d5ade5b61ccb534a03375 Mon Sep 17 00:00:00 2001
From: Jonas Kulla <Nyocurio@gmail.com>
Date: Sun, 30 Jul 2017 23:00:18 +0200
Subject: [PATCH 04/16] Sprite: Check for disposed state before accessing
 bitmap

---
 src/sprite.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/sprite.cpp b/src/sprite.cpp
index 7999546..2cfe13a 100644
--- a/src/sprite.cpp
+++ b/src/sprite.cpp
@@ -121,7 +121,7 @@ struct SpritePrivate
 
 	void recomputeBushDepth()
 	{
-		if (!bitmap)
+		if (nullOrDisposed(bitmap))
 			return;
 
 		/* Calculate effective (normalized) bush depth */
@@ -137,7 +137,7 @@ struct SpritePrivate
 		FloatRect rect = srcRect->toFloatRect();
 		Vec2i bmSize;
 
-		if (bitmap)
+		if (!nullOrDisposed(bitmap))
 			bmSize = Vec2i(bitmap->width(), bitmap->height());
 
 		if (mirrored)

From f172f58c747240599e212f2ede57f37bd393a170 Mon Sep 17 00:00:00 2001
From: Jonas Kulla <Nyocurio@gmail.com>
Date: Thu, 10 Aug 2017 21:39:17 +0200
Subject: [PATCH 05/16] Sprite: Fix regression with "mirror" attribute

FloatRect::hFlipped() returns a rectangle with negative width,
which was clobbered by the clamping further down.

Regression introduced in 55cec53911f6706f6ad7ae58095644235e2259ba.
---
 src/sprite.cpp | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/sprite.cpp b/src/sprite.cpp
index 2cfe13a..26eb297 100644
--- a/src/sprite.cpp
+++ b/src/sprite.cpp
@@ -140,15 +140,12 @@ struct SpritePrivate
 		if (!nullOrDisposed(bitmap))
 			bmSize = Vec2i(bitmap->width(), bitmap->height());
 
-		if (mirrored)
-			rect = rect.hFlipped();
-
 		/* Clamp the rectangle so it doesn't reach outside
 		 * the bitmap bounds */
 		rect.w = clamp<int>(rect.w, 0, bmSize.x-rect.x);
 		rect.h = clamp<int>(rect.h, 0, bmSize.y-rect.y);
 
-		quad.setTexRect(rect);
+		quad.setTexRect(mirrored ? rect.hFlipped() : rect);
 
 		quad.setPosRect(FloatRect(0, 0, rect.w, rect.h));
 		recomputeBushDepth();

From 01e17ed5c64553a08ba3eb04df0b4c29a377c026 Mon Sep 17 00:00:00 2001
From: Marty Plummer <ntzrmtthihu777@gmail.com>
Date: Sat, 22 Jul 2017 16:50:50 -0500
Subject: [PATCH 06/16] windows: move windows specific files

Moved the windows-specific files into their own subdir for
cleanliness's sake and mesonbuild organization.

Signed-off-by: Marty Plummer <ntzrmtthihu777@gmail.com>
---
 CMakeLists.txt                  |   4 ++--
 {assets => windows}/icon.ico    | Bin
 {assets => windows}/resource.h  |   0
 {assets => windows}/resource.rc |   0
 4 files changed, 2 insertions(+), 2 deletions(-)
 rename {assets => windows}/icon.ico (100%)
 rename {assets => windows}/resource.h (100%)
 rename {assets => windows}/resource.rc (100%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7029f79..7c29f7d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -207,7 +207,7 @@ set(MAIN_SOURCE
 )
 
 if(WIN32)
-	list(APPEND MAIN_SOURCE assets/resource.rc)
+	list(APPEND MAIN_SOURCE windows/resource.rc)
 endif()
 
 source_group("MKXP Source" FILES ${MAIN_SOURCE} ${MAIN_HEADERS})
@@ -409,8 +409,8 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE
 	${DEFINES}
 )
 target_include_directories(${PROJECT_NAME} PRIVATE
-	assets
 	src
+	windows
 	${SIGCXX_INCLUDE_DIRS}
 	${PIXMAN_INCLUDE_DIRS}
 	${PHYSFS_INCLUDE_DIRS}
diff --git a/assets/icon.ico b/windows/icon.ico
similarity index 100%
rename from assets/icon.ico
rename to windows/icon.ico
diff --git a/assets/resource.h b/windows/resource.h
similarity index 100%
rename from assets/resource.h
rename to windows/resource.h
diff --git a/assets/resource.rc b/windows/resource.rc
similarity index 100%
rename from assets/resource.rc
rename to windows/resource.rc

From fde6a92197d3c0b646f19e443d4618ac47044fff Mon Sep 17 00:00:00 2001
From: Carsten Teibes <dev@f4ke.de>
Date: Fri, 18 Aug 2017 19:45:57 +0200
Subject: [PATCH 07/16] Fix deprecation warning on build with MRI>2.3 Fixes
 #158.

The old alias is deprecated since: ruby/ruby@fdb957925f2f.
---
 binding-mri/binding-util.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/binding-mri/binding-util.h b/binding-mri/binding-util.h
index 83589f7..1b758be 100644
--- a/binding-mri/binding-util.h
+++ b/binding-mri/binding-util.h
@@ -67,7 +67,7 @@ raiseRbExc(const Exception &exc);
 
 /* 2.1 has added a new field (flags) to rb_data_type_t */
 #include <ruby/version.h>
-#if RUBY_API_VERSION_MINOR > 0
+#if RUBY_API_VERSION_MAJOR >= 2 && RUBY_API_VERSION_MINOR >= 1
 /* TODO: can mkxp use RUBY_TYPED_FREE_IMMEDIATELY here? */
 #define DEF_TYPE_FLAGS 0
 #else
@@ -90,7 +90,12 @@ raiseRbExc(const Exception &exc);
 template<rb_data_type_t *rbType>
 static VALUE classAllocate(VALUE klass)
 {
+/* 2.3 has changed the name of this function */
+#if RUBY_API_VERSION_MAJOR >= 2 && RUBY_API_VERSION_MINOR >= 3
+	return rb_data_typed_object_wrap(klass, 0, rbType);
+#else
 	return rb_data_typed_object_alloc(klass, 0, rbType);
+#endif
 }
 
 template<class C>

From b1bdf1e44509765758fdfba03aae8d0b83841e57 Mon Sep 17 00:00:00 2001
From: Carsten Teibes <dev@f4ke.de>
Date: Fri, 18 Aug 2017 19:06:11 +0200
Subject: [PATCH 08/16] Fix CMake build, only use `resource.h` on Windows This
 was broken in commit 01e17ed5c645 (move windows specific files).

---
 CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7c29f7d..cdfcd32 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -99,7 +99,6 @@ find_package(ZLIB REQUIRED)
 ## Setup main source ##
 
 set(MAIN_HEADERS
-	assets/resource.h
 	src/quadarray.h
 	src/audio.h
 	src/binding.h
@@ -207,6 +206,7 @@ set(MAIN_SOURCE
 )
 
 if(WIN32)
+	list(APPEND MAIN_HEADERS windows/resource.h)
 	list(APPEND MAIN_SOURCE windows/resource.rc)
 endif()
 

From d427df0c2bc7775d61da7e6bcbbe92b3e0c074ae Mon Sep 17 00:00:00 2001
From: Carsten Teibes <dev@f4ke.de>
Date: Sun, 8 Oct 2017 23:11:18 +0200
Subject: [PATCH 09/16] Adapt RGSS archivers and filesystem to physfs 3.0 API

---
 src/filesystem.cpp | 49 ++++++++++++++++++++++++++--------------------
 src/rgssad.cpp     | 28 +++++++++++++++-----------
 2 files changed, 45 insertions(+), 32 deletions(-)

diff --git a/src/filesystem.cpp b/src/filesystem.cpp
index d7fd36b..f27b3bd 100644
--- a/src/filesystem.cpp
+++ b/src/filesystem.cpp
@@ -398,8 +398,8 @@ struct CacheEnumData
 	}
 };
 
-static void cacheEnumCB(void *d, const char *origdir,
-                        const char *fname)
+static PHYSFS_EnumerateCallbackResult
+cacheEnumCB(void *d, const char *origdir, const char *fname)
 {
 	CacheEnumData &data = *static_cast<CacheEnumData*>(d);
 	char fullPath[512];
@@ -426,7 +426,7 @@ static void cacheEnumCB(void *d, const char *origdir,
 
 		/* Iterate over its contents */
 		data.fileLists.push(&list);
-		PHYSFS_enumerateFilesCallback(fullPath, cacheEnumCB, d);
+		PHYSFS_enumerate(fullPath, cacheEnumCB, d);
 		data.fileLists.pop();
 	}
 	else
@@ -441,13 +441,15 @@ static void cacheEnumCB(void *d, const char *origdir,
 		/* Add the lower -> mixed mapping of the file's full path */
 		data.p->pathCache.insert(lowerCase, mixedCase);
 	}
+
+	return PHYSFS_ENUM_OK;
 }
 
 void FileSystem::createPathCache()
 {
 	CacheEnumData data(p);
 	data.fileLists.push(&p->fileLists[""]);
-	PHYSFS_enumerateFilesCallback("", cacheEnumCB, &data);
+	PHYSFS_enumerate("", cacheEnumCB, &data);
 
 	p->havePathCache = true;
 }
@@ -458,8 +460,8 @@ struct FontSetsCBData
 	SharedFontState *sfs;
 };
 
-static void fontSetEnumCB(void *data, const char *dir,
-                          const char *fname)
+static PHYSFS_EnumerateCallbackResult
+fontSetEnumCB (void *data, const char *dir, const char *fname)
 {
 	FontSetsCBData *d = static_cast<FontSetsCBData*>(data);
 
@@ -467,7 +469,7 @@ static void fontSetEnumCB(void *data, const char *dir,
 	const char *ext = findExt(fname);
 
 	if (!ext)
-		return;
+		return PHYSFS_ENUM_STOP;
 
 	char lowExt[8];
 	size_t i;
@@ -477,7 +479,7 @@ static void fontSetEnumCB(void *data, const char *dir,
 	lowExt[i] = '\0';
 
 	if (strcmp(lowExt, "ttf") && strcmp(lowExt, "otf"))
-		return;
+		return PHYSFS_ENUM_STOP;
 
 	char filename[512];
 	snprintf(filename, sizeof(filename), "%s/%s", dir, fname);
@@ -485,7 +487,7 @@ static void fontSetEnumCB(void *data, const char *dir,
 	PHYSFS_File *handle = PHYSFS_openRead(filename);
 
 	if (!handle)
-		return;
+		return PHYSFS_ENUM_ERROR;
 
 	SDL_RWops ops;
 	initReadOps(handle, ops, false);
@@ -493,12 +495,14 @@ static void fontSetEnumCB(void *data, const char *dir,
 	d->sfs->initFontSetCB(ops, filename);
 
 	SDL_RWclose(&ops);
+
+	return PHYSFS_ENUM_OK;
 }
 
 /* Basically just a case-insensitive search
  * for the folder "Fonts"... */
-static void findFontsFolderCB(void *data, const char *,
-                              const char *fname)
+static PHYSFS_EnumerateCallbackResult
+findFontsFolderCB(void *data, const char *, const char *fname)
 {
 	size_t i = 0;
 	char buffer[512];
@@ -510,14 +514,16 @@ static void findFontsFolderCB(void *data, const char *,
 	buffer[i] = '\0';
 
 	if (strcmp(buffer, "fonts") == 0)
-		PHYSFS_enumerateFilesCallback(fname, fontSetEnumCB, data);
+		PHYSFS_enumerate(fname, fontSetEnumCB, data);
+
+	return PHYSFS_ENUM_OK;
 }
 
 void FileSystem::initFontSets(SharedFontState &sfs)
 {
 	FontSetsCBData d = { p, &sfs };
 
-	PHYSFS_enumerateFilesCallback(".", findFontsFolderCB, &d);
+	PHYSFS_enumerate(".", findFontsFolderCB, &d);
 }
 
 struct OpenReadEnumData
@@ -550,19 +556,19 @@ struct OpenReadEnumData
 	{}
 };
 
-static void openReadEnumCB(void *d, const char *dirpath,
-                           const char *filename)
+static PHYSFS_EnumerateCallbackResult
+openReadEnumCB(void *d, const char *dirpath, const char *filename)
 {
 	OpenReadEnumData &data = *static_cast<OpenReadEnumData*>(d);
 	char buffer[512];
 	const char *fullPath;
 
 	if (data.stopSearching)
-		return;
+		return PHYSFS_ENUM_STOP;
 
 	/* If there's not even a partial match, continue searching */
 	if (strncmp(filename, data.filename, data.filenameN) != 0)
-		return;
+		return PHYSFS_ENUM_OK;
 
 	if (!*dirpath)
 	{
@@ -580,7 +586,7 @@ static void openReadEnumCB(void *d, const char *dirpath,
 	 * of the extension), or up to a following '\0' (full match), we've
 	 * found our file */
 	if (last != '.' && last != '\0')
-		return;
+		return PHYSFS_ENUM_STOP;
 
 	/* If the path cache is active, translate from lower case
 	 * to mixed case path */
@@ -595,9 +601,9 @@ static void openReadEnumCB(void *d, const char *dirpath,
 		 * be a deeper rooted problem somewhere within PhysFS.
 		 * Just abort alltogether. */
 		data.stopSearching = true;
-		data.physfsError = PHYSFS_getLastError();
+		data.physfsError = PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode());
 
-		return;
+		return PHYSFS_ENUM_ERROR;
 	}
 
 	initReadOps(phys, data.ops, false);
@@ -608,6 +614,7 @@ static void openReadEnumCB(void *d, const char *dirpath,
 		data.stopSearching = true;
 
 	++data.matchCount;
+	return PHYSFS_ENUM_OK;
 }
 
 void FileSystem::openRead(OpenHandler &handler, const char *filename)
@@ -653,7 +660,7 @@ void FileSystem::openRead(OpenHandler &handler, const char *filename)
 	}
 	else
 	{
-		PHYSFS_enumerateFilesCallback(dir, openReadEnumCB, &data);
+		PHYSFS_enumerate(dir, openReadEnumCB, &data);
 	}
 
 	if (data.physfsError)
diff --git a/src/rgssad.cpp b/src/rgssad.cpp
index 17e8417..4b51472 100644
--- a/src/rgssad.cpp
+++ b/src/rgssad.cpp
@@ -331,14 +331,16 @@ verifyHeader(PHYSFS_Io *io, char version)
 }
 
 static void*
-RGSS_openArchive(PHYSFS_Io *io, const char *, int forWrite)
+RGSS_openArchive(PHYSFS_Io *io, const char *, int forWrite, int *claimed)
 {
 	if (forWrite)
-		return 0;
+		return NULL;
 
 	/* Version 1 */
 	if (!verifyHeader(io, 1))
-		return 0;
+		return NULL;
+	else
+		*claimed = 1;
 
 	RGSS_archiveData *data = new RGSS_archiveData;
 	data->archiveIo = io;
@@ -389,9 +391,9 @@ RGSS_openArchive(PHYSFS_Io *io, const char *, int forWrite)
 	return data;
 }
 
-static void
+static PHYSFS_EnumerateCallbackResult
 RGSS_enumerateFiles(void *opaque, const char *dirname,
-                    PHYSFS_EnumFilesCallback cb,
+                    PHYSFS_EnumerateCallback cb,
                     const char *origdir, void *callbackdata)
 {
 	RGSS_archiveData *data = static_cast<RGSS_archiveData*>(opaque);
@@ -399,13 +401,15 @@ RGSS_enumerateFiles(void *opaque, const char *dirname,
 	std::string _dirname(dirname);
 
 	if (!data->dirHash.contains(_dirname))
-		return;
+		return PHYSFS_ENUM_STOP;
 
 	const BoostSet<std::string> &entries = data->dirHash[_dirname];
 
 	BoostSet<std::string>::const_iterator iter;
 	for (iter = entries.cbegin(); iter != entries.cend(); ++iter)
 		cb(callbackdata, origdir, iter->c_str());
+
+	return PHYSFS_ENUM_OK;
 }
 
 static PHYSFS_Io*
@@ -536,19 +540,21 @@ readUint32AndXor(PHYSFS_Io *io, uint32_t &result, uint32_t key)
 }
 
 static void*
-RGSS3_openArchive(PHYSFS_Io *io, const char *, int forWrite)
+RGSS3_openArchive(PHYSFS_Io *io, const char *, int forWrite, int *claimed)
 {
 	if (forWrite)
-		return 0;
+		return NULL;
 
 	/* Version 3 */
 	if (!verifyHeader(io, 3))
-		return 0;
+		return NULL;
+	else
+		*claimed = 1;
 
 	uint32_t baseMagic;
 
 	if (!readUint32(io, baseMagic))
-		return 0;
+		return NULL;
 
 	baseMagic = (baseMagic * 9) + 3;
 
@@ -605,7 +611,7 @@ RGSS3_openArchive(PHYSFS_Io *io, const char *, int forWrite)
 
 	error:
 		delete data;
-		return 0;
+		return NULL;
 	}
 
 	return data;

From 7d9a85dbbd43f7dd26ef5ce07b2772bbd1e59a3a Mon Sep 17 00:00:00 2001
From: Jonas Kulla <Nyocurio@gmail.com>
Date: Mon, 11 Dec 2017 00:48:35 +0100
Subject: [PATCH 10/16] Config: Add entry to override the game window title

---
 mkxp.conf.sample | 6 ++++++
 src/config.cpp   | 1 +
 src/config.h     | 1 +
 src/main.cpp     | 5 ++++-
 4 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/mkxp.conf.sample b/mkxp.conf.sample
index 500dcc6..2d9ad45 100644
--- a/mkxp.conf.sample
+++ b/mkxp.conf.sample
@@ -77,6 +77,12 @@
 # defScreenW=640
 
 
+# Override the game window title
+# (default: none)
+#
+# windowTitle=Custom Title
+
+
 # Specify the window height on startup. If set to 0,
 # it will default to the default resolution height
 # specific to the RGSS version (480 in RGSS1, 416
diff --git a/src/config.cpp b/src/config.cpp
index 33d8160..4d47152 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -161,6 +161,7 @@ void Config::read(int argc, char *argv[])
 	PO_DESC(vsync, bool, false) \
 	PO_DESC(defScreenW, int, 0) \
 	PO_DESC(defScreenH, int, 0) \
+	PO_DESC(windowTitle, std::string, "") \
 	PO_DESC(fixedFramerate, int, 0) \
 	PO_DESC(frameSkip, bool, true) \
 	PO_DESC(syncToRefreshrate, bool, false) \
diff --git a/src/config.h b/src/config.h
index d2d4650..5cc8bb7 100644
--- a/src/config.h
+++ b/src/config.h
@@ -41,6 +41,7 @@ struct Config
 
 	int defScreenW;
 	int defScreenH;
+	std::string windowTitle;
 
 	int fixedFramerate;
 	bool frameSkip;
diff --git a/src/main.cpp b/src/main.cpp
index 1a3fc4e..40ae391 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -233,6 +233,9 @@ int main(int argc, char *argv[])
 
 	conf.readGameINI();
 
+	if (conf.windowTitle.empty())
+		conf.windowTitle = conf.game.title;
+
 	assert(conf.rgssVersion >= 1 && conf.rgssVersion <= 3);
 	printRgssVersion(conf.rgssVersion);
 
@@ -272,7 +275,7 @@ int main(int argc, char *argv[])
 	if (conf.fullscreen)
 		winFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
 
-	win = SDL_CreateWindow(conf.game.title.c_str(),
+	win = SDL_CreateWindow(conf.windowTitle.c_str(),
 	                       SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
 	                       conf.defScreenW, conf.defScreenH, winFlags);
 

From 2f81fbbf4b9871d8443477262f475ee52fed14a2 Mon Sep 17 00:00:00 2001
From: Jonas Kulla <Nyocurio@gmail.com>
Date: Mon, 11 Dec 2017 00:51:21 +0100
Subject: [PATCH 11/16] Fix ordering

---
 mkxp.conf.sample | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/mkxp.conf.sample b/mkxp.conf.sample
index 2d9ad45..9863eaf 100644
--- a/mkxp.conf.sample
+++ b/mkxp.conf.sample
@@ -77,12 +77,6 @@
 # defScreenW=640
 
 
-# Override the game window title
-# (default: none)
-#
-# windowTitle=Custom Title
-
-
 # Specify the window height on startup. If set to 0,
 # it will default to the default resolution height
 # specific to the RGSS version (480 in RGSS1, 416
@@ -92,6 +86,12 @@
 # defScreenH=480
 
 
+# Override the game window title
+# (default: none)
+#
+# windowTitle=Custom Title
+
+
 # Enforce a static frame rate
 # (0 = disabled)
 #

From 947974cac649769a9c569162e5f16022896a2652 Mon Sep 17 00:00:00 2001
From: Jonas Kulla <Nyocurio@gmail.com>
Date: Tue, 12 Dec 2017 17:57:02 +0100
Subject: [PATCH 12/16] Config: Properly use windowTitle everywhere instead of
 game.title

---
 src/eventthread.cpp | 8 ++++----
 src/main.cpp        | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/eventthread.cpp b/src/eventthread.cpp
index 08b6c29..6ffdb29 100644
--- a/src/eventthread.cpp
+++ b/src/eventthread.cpp
@@ -296,14 +296,14 @@ void EventThread::process(RGSSThreadData &rtData)
 					if (fullscreen)
 					{
 						/* Prevent fullscreen flicker */
-						strncpy(pendingTitle, rtData.config.game.title.c_str(),
+						strncpy(pendingTitle, rtData.config.windowTitle.c_str(),
 						        sizeof(pendingTitle));
 						havePendingTitle = true;
 
 						break;
 					}
 
-					SDL_SetWindowTitle(win, rtData.config.game.title.c_str());
+					SDL_SetWindowTitle(win, rtData.config.windowTitle.c_str());
 				}
 
 				break;
@@ -410,7 +410,7 @@ void EventThread::process(RGSSThreadData &rtData)
 
 			case REQUEST_MESSAGEBOX :
 				SDL_ShowSimpleMessageBox(event.user.code,
-				                         rtData.config.game.title.c_str(),
+				                         rtData.config.windowTitle.c_str(),
 				                         (const char*) event.user.data1, win);
 				free(event.user.data1);
 				msgBoxDone.set();
@@ -429,7 +429,7 @@ void EventThread::process(RGSSThreadData &rtData)
 					break;
 
 				snprintf(buffer, sizeof(buffer), "%s - %d FPS",
-				         rtData.config.game.title.c_str(), event.user.code);
+				         rtData.config.windowTitle.c_str(), event.user.code);
 
 				/* Updating the window title in fullscreen
 				 * mode seems to cause flickering */
diff --git a/src/main.cpp b/src/main.cpp
index 40ae391..e457639 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -353,13 +353,13 @@ int main(int argc, char *argv[])
 	if (rtData.rqTermAck)
 		SDL_WaitThread(rgssThread, 0);
 	else
-		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.c_str(),
+		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.windowTitle.c_str(),
 		                         "The RGSS script seems to be stuck and mkxp will now force quit", win);
 
 	if (!rtData.rgssErrorMsg.empty())
 	{
 		Debug() << rtData.rgssErrorMsg;
-		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.c_str(),
+		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.windowTitle.c_str(),
 		                         rtData.rgssErrorMsg.c_str(), win);
 	}
 

From 7902d0942d17627e2ada58bfa3ce1898003c951d Mon Sep 17 00:00:00 2001
From: Jonas Kulla <Nyocurio@gmail.com>
Date: Tue, 12 Dec 2017 22:45:01 +0100
Subject: [PATCH 13/16] Filesystem: Properly iterate top level dir entries

"." seemed to have worked in earlier PhysFS versions,
but it was never the correct way.
---
 src/filesystem.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/filesystem.cpp b/src/filesystem.cpp
index f27b3bd..8e50ee8 100644
--- a/src/filesystem.cpp
+++ b/src/filesystem.cpp
@@ -523,7 +523,7 @@ void FileSystem::initFontSets(SharedFontState &sfs)
 {
 	FontSetsCBData d = { p, &sfs };
 
-	PHYSFS_enumerate(".", findFontsFolderCB, &d);
+	PHYSFS_enumerate("", findFontsFolderCB, &d);
 }
 
 struct OpenReadEnumData

From 183ebbed65687c4074b8431765b7d6ac4d8d2d35 Mon Sep 17 00:00:00 2001
From: Jonas Kulla <Nyocurio@gmail.com>
Date: Tue, 12 Dec 2017 22:46:25 +0100
Subject: [PATCH 14/16] RGSSAD: Fix parsing of top level directory entries

We were spamming every path into the hash (including the top
level ones) without noticing... oh well.
---
 src/rgssad.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/rgssad.cpp b/src/rgssad.cpp
index 4b51472..ac8772a 100644
--- a/src/rgssad.cpp
+++ b/src/rgssad.cpp
@@ -297,6 +297,8 @@ processDirectories(RGSS_archiveData *data, BoostSet<std::string> &topLevel,
 
 		if (slash)
 			nameBuf[i] = '/';
+
+		break;
 	}
 
 	/* Check for more entries */

From 9f44ee50688fe1fda3a3a17226d351da8da98405 Mon Sep 17 00:00:00 2001
From: Jonas Kulla <Nyocurio@gmail.com>
Date: Mon, 22 Jan 2018 10:54:21 +0100
Subject: [PATCH 15/16] FileSystem: Fix while termination condition

---
 src/filesystem.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/filesystem.cpp b/src/filesystem.cpp
index 8e50ee8..33d383d 100644
--- a/src/filesystem.cpp
+++ b/src/filesystem.cpp
@@ -508,7 +508,7 @@ findFontsFolderCB(void *data, const char *, const char *fname)
 	char buffer[512];
 	const char *s = fname;
 
-	while (s && i < sizeof(buffer))
+	while (*s && i < sizeof(buffer))
 		buffer[i++] = tolower(*s++);
 
 	buffer[i] = '\0';

From b5e5a26d8b0b1a8ea1b502cba3b432e7fac088a4 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Thu, 22 Feb 2018 04:37:47 -0300
Subject: [PATCH 16/16] Config: Set debug editor's debug variables into ruby

---
 binding-mri/binding-mri.cpp     |  9 +++++++++
 binding-mruby/binding-mruby.cpp |  9 +++++++++
 src/config.cpp                  | 21 +++++++++++++++++++++
 src/config.h                    |  6 ++++++
 4 files changed, 45 insertions(+)

diff --git a/binding-mri/binding-mri.cpp b/binding-mri/binding-mri.cpp
index f0a4bb4..1c0057b 100644
--- a/binding-mri/binding-mri.cpp
+++ b/binding-mri/binding-mri.cpp
@@ -147,7 +147,16 @@ static void mriBindingInit()
 	_rb_define_module_function(mod, "raw_key_states", mkxpRawKeyStates);
 	_rb_define_module_function(mod, "mouse_in_window", mkxpMouseInWindow);
 
+	/* 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);
+
+	rb_gv_set("BTEST", rb_bool_new(shState->config().editor.battleTest));
 }
 
 static void
diff --git a/binding-mruby/binding-mruby.cpp b/binding-mruby/binding-mruby.cpp
index 867d2d6..a713d73 100644
--- a/binding-mruby/binding-mruby.cpp
+++ b/binding-mruby/binding-mruby.cpp
@@ -114,8 +114,17 @@ static void mrbBindingInit(mrb_state *mrb)
 	/* Load RPG module */
 	mrb_load_irep(mrb, mrbModuleRPG);
 
+	/* Load global constants */
 	mrb_define_global_const(mrb, "MKXP", mrb_true_value());
 
+	mrb_value debug = rb_bool_new(shState->config().editor.debug);
+	if (rgssVer == 1)
+		mrb_define_global_const(mrb, "DEBUG", debug);
+	else if (rgssVer >= 2)
+		mrb_define_global_const(mrb, "TEST", debug);
+
+	mrb_define_global_const(mrb, "BTEST", mrb_bool_value(shState->config().editor.battleTest));
+
 	mrb_gc_arena_restore(mrb, arena);
 }
 
diff --git a/src/config.cpp b/src/config.cpp
index 4d47152..fee3b5a 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -189,6 +189,27 @@ void Config::read(int argc, char *argv[])
 // Not gonna take your shit boost
 #define GUARD_ALL( exp ) try { exp } catch(...) {}
 
+	editor.debug = false;
+	editor.battleTest = false;
+
+	/* Read arguments sent from the editor */
+	if (argc > 1)
+	{
+		std::string argv1 = argv[1];
+		/* RGSS1 uses "debug", 2 and 3 use "test" */
+		if (argv1 == "debug" || argv1 == "test")
+			editor.debug = true;
+		else if (argv1 == "btest")
+			editor.battleTest = true;
+
+		/* Fix offset */
+		if (editor.debug || editor.battleTest)
+		{
+			argc--;
+			argv++;
+		}
+	}
+
 #define PO_DESC(key, type, def) (#key, po::value< type >()->default_value(def))
 
 	po::options_description podesc;
diff --git a/src/config.h b/src/config.h
index 5cc8bb7..e380250 100644
--- a/src/config.h
+++ b/src/config.h
@@ -88,6 +88,12 @@ struct Config
 
 	std::vector<std::string> rubyLoadpaths;
 
+	/* Editor flags */
+	struct {
+		bool debug;
+		bool battleTest;
+	} editor;
+
 	/* Game INI contents */
 	struct {
 		std::string scripts;