Merge branch 'master' of /home/Ancurio/programming/C++/mkxp
Conflicts: src/config.h
This commit is contained in:
		
						commit
						d07309c8f9
					
				
					 85 changed files with 4901 additions and 3428 deletions
				
			
		| 
						 | 
				
			
			@ -124,9 +124,9 @@ set(MAIN_HEADERS
 | 
			
		|||
	src/glstate.h
 | 
			
		||||
	src/quad.h
 | 
			
		||||
	src/tilemap.h
 | 
			
		||||
	src/flashmap.h
 | 
			
		||||
	src/tilemap-common.h
 | 
			
		||||
	src/graphics.h
 | 
			
		||||
	src/debuglogger.h
 | 
			
		||||
	src/gl-debug.h
 | 
			
		||||
	src/global-ibo.h
 | 
			
		||||
	src/exception.h
 | 
			
		||||
	src/filesystem.h
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +180,7 @@ set(MAIN_SOURCE
 | 
			
		|||
	src/tilemap.cpp
 | 
			
		||||
	src/autotiles.cpp
 | 
			
		||||
	src/graphics.cpp
 | 
			
		||||
	src/debuglogger.cpp
 | 
			
		||||
	src/gl-debug.cpp
 | 
			
		||||
	src/etc.cpp
 | 
			
		||||
	src/config.cpp
 | 
			
		||||
	src/settingsmenu.cpp
 | 
			
		||||
| 
						 | 
				
			
			@ -210,16 +210,21 @@ source_group("MKXP Source" FILES ${MAIN_SOURCE} ${MAIN_HEADERS})
 | 
			
		|||
## Setup embedded source ##
 | 
			
		||||
 | 
			
		||||
set(EMBEDDED_INPUT
 | 
			
		||||
	shader/common.h
 | 
			
		||||
	shader/transSimple.frag
 | 
			
		||||
	shader/trans.frag
 | 
			
		||||
	shader/hue.frag
 | 
			
		||||
	shader/sprite.frag
 | 
			
		||||
	shader/plane.frag
 | 
			
		||||
	shader/gray.frag
 | 
			
		||||
	shader/bitmapBlit.frag
 | 
			
		||||
	shader/flatColor.frag
 | 
			
		||||
	shader/simple.frag
 | 
			
		||||
	shader/simpleColor.frag
 | 
			
		||||
	shader/simpleAlpha.frag
 | 
			
		||||
	shader/simpleAlphaUni.frag
 | 
			
		||||
	shader/flashMap.frag
 | 
			
		||||
	shader/minimal.vert
 | 
			
		||||
	shader/simple.vert
 | 
			
		||||
	shader/simpleColor.vert
 | 
			
		||||
	shader/sprite.vert
 | 
			
		||||
| 
						 | 
				
			
			@ -230,6 +235,7 @@ set(EMBEDDED_INPUT
 | 
			
		|||
	shader/blurV.vert
 | 
			
		||||
	shader/simpleMatrix.vert
 | 
			
		||||
	assets/liberation.ttf
 | 
			
		||||
	assets/icon.png
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if (RGSS2)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -4,8 +4,10 @@ mkxp is a project that seeks to provide a fully open source implementation of th
 | 
			
		|||
 | 
			
		||||
It is licensed under the GNU General Public License v2+.
 | 
			
		||||
 | 
			
		||||
[**Prebuilt binaries for Linux (32/64)**](http://ancurio.bplaced.net/mkxp/generic/)  
 | 
			
		||||
[**Prebuilt binaries for OSX by Ali**](https://app.box.com/mkxpmacbuilds)
 | 
			
		||||
## Prebuilt binaries
 | 
			
		||||
[**Linux (32bit/64bit)**](http://ancurio.bplaced.net/mkxp/generic/)  
 | 
			
		||||
[**OSX**](https://app.box.com/mkxpmacbuilds) by Ali  
 | 
			
		||||
[**Windows (mingw-w64 32bit)**](http://ancurio.bplaced.net/mkxp/mingw32/)
 | 
			
		||||
 | 
			
		||||
## Bindings
 | 
			
		||||
Bindings provide the glue code for an interpreted language environment to run game scripts in. Currently there are three bindings:
 | 
			
		||||
| 
						 | 
				
			
			@ -85,13 +87,11 @@ The syntax is: `--<option>=<value>`
 | 
			
		|||
 | 
			
		||||
Example: `./mkxp --gameFolder="my game" --vsync=true --fixedFramerate=60`
 | 
			
		||||
 | 
			
		||||
## Midi music (*ALPHA STATUS*)
 | 
			
		||||
## Midi music
 | 
			
		||||
 | 
			
		||||
mkxp doesn't come with a soundfont by default, so you will have to supply it yourself (set its path in the config). Playback has been tested and should work reasonably well with all RTP assets.
 | 
			
		||||
 | 
			
		||||
Known issues with midi playback:
 | 
			
		||||
 | 
			
		||||
* Some songs' instruments become mute after looping
 | 
			
		||||
You can use this public domain soundfont: [GMGSx.sf2](https://www.dropbox.com/s/qxdvoxxcexsvn43/GMGSx.sf2?dl=0)
 | 
			
		||||
 | 
			
		||||
## Fonts
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +101,6 @@ If a requested font is not found, no error is generated. Instead, a built-in fon
 | 
			
		|||
 | 
			
		||||
## What doesn't work (yet)
 | 
			
		||||
 | 
			
		||||
* Text outline
 | 
			
		||||
* Movie playback
 | 
			
		||||
* wma audio files
 | 
			
		||||
* The Win32API ruby class (for obvious reasons)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										
											BIN
										
									
								
								assets/icon.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icon.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.2 KiB  | 
							
								
								
									
										50
									
								
								assets/icon.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								assets/icon.svg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   width="100"
 | 
			
		||||
   height="100"
 | 
			
		||||
   id="svg2">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs4">
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       id="linearGradient3821">
 | 
			
		||||
      <stop
 | 
			
		||||
         id="stop3823"
 | 
			
		||||
         style="stop-color:#00ff88;stop-opacity:1"
 | 
			
		||||
         offset="0" />
 | 
			
		||||
      <stop
 | 
			
		||||
         id="stop3825"
 | 
			
		||||
         style="stop-color:#00ff86;stop-opacity:1"
 | 
			
		||||
         offset="1" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata7">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title />
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     transform="translate(-323.76562,-436.67187)"
 | 
			
		||||
     id="layer1">
 | 
			
		||||
    <path
 | 
			
		||||
       d="m 373.76195,439.49229 c -26.05643,0 -47.17591,21.12683 -47.17591,47.18326 0,26.05643 21.11948,47.17591 47.17591,47.17591 26.05643,0 47.18326,-21.11948 47.18326,-47.17591 0,-26.05643 -21.12683,-47.18326 -47.18326,-47.18326 z m 0,26.80867 c 11.25095,0 20.37459,9.12364 20.37459,20.37459 0,11.25094 -9.12364,20.36724 -20.37459,20.36724 -11.25094,0 -20.36724,-9.1163 -20.36724,-20.36724 0,-11.25095 9.1163,-20.37459 20.36724,-20.37459 z"
 | 
			
		||||
       inkscape:connector-curvature="0"
 | 
			
		||||
       id="path2985"
 | 
			
		||||
       style="fill:#00ff87;fill-opacity:1;stroke:#000000;stroke-width:5.64083672;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 1.8 KiB  | 
| 
						 | 
				
			
			@ -25,6 +25,7 @@
 | 
			
		|||
#include "eventthread.h"
 | 
			
		||||
#include "filesystem.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "sdl-util.h"
 | 
			
		||||
#include "debugwriter.h"
 | 
			
		||||
#include "graphics.h"
 | 
			
		||||
#include "audio.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -193,7 +194,10 @@ RB_METHOD(mkxpDataDirectory)
 | 
			
		|||
{
 | 
			
		||||
	RB_UNUSED_PARAM;
 | 
			
		||||
	
 | 
			
		||||
	return rb_str_new_cstr(shState->config().customDataPath.c_str());
 | 
			
		||||
	const std::string &path = shState->config().customDataPath;
 | 
			
		||||
	const char *s = path.empty() ? "." : path.c_str();
 | 
			
		||||
 | 
			
		||||
	return rb_str_new_cstr(s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RB_METHOD(mkxpPuts)
 | 
			
		||||
| 
						 | 
				
			
			@ -336,7 +340,7 @@ static void runCustomScript(const std::string &filename)
 | 
			
		|||
{
 | 
			
		||||
	std::string scriptData;
 | 
			
		||||
 | 
			
		||||
	if (!readFile(filename.c_str(), scriptData))
 | 
			
		||||
	if (!readFileSDL(filename.c_str(), scriptData))
 | 
			
		||||
	{
 | 
			
		||||
		showMsg(std::string("Unable to open '") + filename + "'");
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -346,7 +350,7 @@ static void runCustomScript(const std::string &filename)
 | 
			
		|||
	           newStringUTF8(filename.c_str(), filename.size()), NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE kernelLoadDataInt(const char *filename);
 | 
			
		||||
VALUE kernelLoadDataInt(const char *filename, bool rubyExc);
 | 
			
		||||
 | 
			
		||||
struct BacktraceData
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -373,7 +377,19 @@ static void runRMXPScripts(BacktraceData &btData)
 | 
			
		|||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	VALUE scriptArray = kernelLoadDataInt(scriptPack.c_str());
 | 
			
		||||
	VALUE scriptArray;
 | 
			
		||||
 | 
			
		||||
	/* We checked if Scripts.rxdata exists, but something might
 | 
			
		||||
	 * still go wrong */
 | 
			
		||||
	try
 | 
			
		||||
	{
 | 
			
		||||
		scriptArray = kernelLoadDataInt(scriptPack.c_str(), false);
 | 
			
		||||
	}
 | 
			
		||||
	catch (const Exception &e)
 | 
			
		||||
	{
 | 
			
		||||
		showMsg(std::string("Failed to read script data: ") + e.msg);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!RB_TYPE_P(scriptArray, RUBY_T_ARRAY))
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -540,6 +556,13 @@ static void showExc(VALUE exc, const BacktraceData &btData)
 | 
			
		|||
 | 
			
		||||
static void mriBindingExecute()
 | 
			
		||||
{
 | 
			
		||||
	/* Normally only a ruby executable would do a sysinit,
 | 
			
		||||
	 * but not doing it will lead to crashes due to closed
 | 
			
		||||
	 * stdio streams on some platforms (eg. Windows) */
 | 
			
		||||
	int argc = 0;
 | 
			
		||||
	char **argv = 0;
 | 
			
		||||
	ruby_sysinit(&argc, &argv);
 | 
			
		||||
 | 
			
		||||
	ruby_setup();
 | 
			
		||||
	rb_enc_set_default_external(rb_enc_from_encoding(rb_utf8_encoding()));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ fileIntFreeInstance(void *inst)
 | 
			
		|||
DEF_TYPE_CUSTOMFREE(FileInt, fileIntFreeInstance);
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
fileIntForPath(const char *path)
 | 
			
		||||
fileIntForPath(const char *path, bool rubyExc)
 | 
			
		||||
{
 | 
			
		||||
	SDL_RWops *ops = SDL_AllocRW();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +51,11 @@ fileIntForPath(const char *path)
 | 
			
		|||
	catch (const Exception &e)
 | 
			
		||||
	{
 | 
			
		||||
		SDL_FreeRW(ops);
 | 
			
		||||
		raiseRbExc(e);
 | 
			
		||||
 | 
			
		||||
		if (rubyExc)
 | 
			
		||||
			raiseRbExc(e);
 | 
			
		||||
		else
 | 
			
		||||
			throw e;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	VALUE klass = rb_const_get(rb_cObject, rb_intern("FileInt"));
 | 
			
		||||
| 
						 | 
				
			
			@ -119,11 +123,11 @@ RB_METHOD(fileIntBinmode)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
VALUE
 | 
			
		||||
kernelLoadDataInt(const char *filename)
 | 
			
		||||
kernelLoadDataInt(const char *filename, bool rubyExc)
 | 
			
		||||
{
 | 
			
		||||
	rb_gc_start();
 | 
			
		||||
 | 
			
		||||
	VALUE port = fileIntForPath(filename);
 | 
			
		||||
	VALUE port = fileIntForPath(filename, rubyExc);
 | 
			
		||||
 | 
			
		||||
	VALUE marsh = rb_const_get(rb_cObject, rb_intern("Marshal"));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +146,7 @@ RB_METHOD(kernelLoadData)
 | 
			
		|||
	const char *filename;
 | 
			
		||||
	rb_get_args(argc, argv, "z", &filename RB_ARG_END);
 | 
			
		||||
 | 
			
		||||
	return kernelLoadDataInt(filename);
 | 
			
		||||
	return kernelLoadDataInt(filename, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RB_METHOD(kernelSaveData)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,17 +38,22 @@ static int getButtonArg(int argc, VALUE *argv)
 | 
			
		|||
{
 | 
			
		||||
	int num;
 | 
			
		||||
 | 
			
		||||
	if (rgssVer >= 3)
 | 
			
		||||
	{
 | 
			
		||||
		ID sym;
 | 
			
		||||
		rb_get_args(argc, argv, "n", &sym RB_ARG_END);
 | 
			
		||||
	rb_check_argc(argc, 1);
 | 
			
		||||
 | 
			
		||||
	if (FIXNUM_P(argv[0]))
 | 
			
		||||
	{
 | 
			
		||||
		num = FIX2INT(argv[0]);
 | 
			
		||||
	}
 | 
			
		||||
	else if (SYMBOL_P(argv[0]) && rgssVer >= 3)
 | 
			
		||||
	{
 | 
			
		||||
		VALUE symHash = getRbData()->buttoncodeHash;
 | 
			
		||||
		num = FIX2INT(rb_hash_lookup2(symHash, ID2SYM(sym), INT2FIX(Input::None)));
 | 
			
		||||
		num = FIX2INT(rb_hash_lookup2(symHash, argv[0], INT2FIX(Input::None)));
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		rb_get_args(argc, argv, "i", &num RB_ARG_END);
 | 
			
		||||
		// FIXME: RMXP allows only few more types that
 | 
			
		||||
		// don't make sense (symbols in pre 3, floats)
 | 
			
		||||
		num = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return num;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -192,7 +192,7 @@ static void
 | 
			
		|||
runCustomScript(mrb_state *mrb, mrbc_context *ctx, const char *filename)
 | 
			
		||||
{
 | 
			
		||||
	/* Execute custom script */
 | 
			
		||||
	FILE *f = fopen(filename, "r");
 | 
			
		||||
	FILE *f = fopen(filename, "rb");
 | 
			
		||||
 | 
			
		||||
	if (!f)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -217,7 +217,7 @@ static void
 | 
			
		|||
runMrbFile(mrb_state *mrb, const char *filename)
 | 
			
		||||
{
 | 
			
		||||
	/* Execute compiled script */
 | 
			
		||||
	FILE *f = fopen(filename, "r");
 | 
			
		||||
	FILE *f = fopen(filename, "rb");
 | 
			
		||||
 | 
			
		||||
	if (!f)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,20 +40,26 @@ MRB_FUNCTION(inputUpdate)
 | 
			
		|||
static mrb_int getButtonArg(mrb_state *mrb)
 | 
			
		||||
{
 | 
			
		||||
	mrb_int num;
 | 
			
		||||
	mrb_value arg;
 | 
			
		||||
 | 
			
		||||
	if (rgssVer >= 3)
 | 
			
		||||
	mrb_get_args(mrb, "o", &arg);
 | 
			
		||||
 | 
			
		||||
	if (mrb_fixnum_p(arg))
 | 
			
		||||
	{
 | 
			
		||||
		num = mrb_fixnum(arg);
 | 
			
		||||
	}
 | 
			
		||||
	else if (mrb_symbol_p(arg) && rgssVer >= 3)
 | 
			
		||||
	{
 | 
			
		||||
		mrb_sym sym;
 | 
			
		||||
		mrb_get_args(mrb, "n", &sym);
 | 
			
		||||
 | 
			
		||||
		mrb_value symHash = getMrbData(mrb)->buttoncodeHash;
 | 
			
		||||
		mrb_value numVal = mrb_hash_fetch(mrb, symHash, mrb_symbol_value(sym),
 | 
			
		||||
		mrb_value numVal = mrb_hash_fetch(mrb, symHash, arg,
 | 
			
		||||
										  mrb_fixnum_value(Input::None));
 | 
			
		||||
		num = mrb_fixnum(numVal);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		mrb_get_args(mrb, "i", &num);
 | 
			
		||||
		// FIXME: RMXP allows only few more types that
 | 
			
		||||
		// don't make sense (symbols in pre 3, floats)
 | 
			
		||||
		num = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return num;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,4 +1,14 @@
 | 
			
		|||
# Lines starting with '#' are comments
 | 
			
		||||
# Lines starting with '#' are comments.
 | 
			
		||||
#
 | 
			
		||||
# About filesystem paths specified in this config:
 | 
			
		||||
# The "gameFolder" path is resolved either relative
 | 
			
		||||
# to the directory containing the mkxp executable
 | 
			
		||||
# (the default behavior), or relative to the current
 | 
			
		||||
# working directory (when compiled with 
 | 
			
		||||
# -DWORKDIR_CURRENT). All other paths are resolved
 | 
			
		||||
# relative to gameFolder and ignoring both RTPs and
 | 
			
		||||
# encrypted archives.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Specify the RGSS version to run under.
 | 
			
		||||
# Possible values are 0, 1, 2, 3. If set to 0,
 | 
			
		||||
| 
						 | 
				
			
			@ -17,6 +27,14 @@
 | 
			
		|||
# debugMode=false
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Continuously print average FPS to console.
 | 
			
		||||
# This setting does not affect the window title
 | 
			
		||||
# FPS display toggled via F2
 | 
			
		||||
# (default: disabled)
 | 
			
		||||
#
 | 
			
		||||
# printFPS=false
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Game window is resizable
 | 
			
		||||
# (default: disabled)
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -80,12 +98,32 @@
 | 
			
		|||
# frameSkip=true
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Use a fixed framerate that is approx. equal to the
 | 
			
		||||
# native screen refresh rate. This is different from
 | 
			
		||||
# "fixedFramerate" because the actual frame rate is
 | 
			
		||||
# reported back to the game, ensuring correct timers.
 | 
			
		||||
# If the screen refresh rate cannot be determined,
 | 
			
		||||
# this option is force-disabled
 | 
			
		||||
# (default: disabled)
 | 
			
		||||
#
 | 
			
		||||
# syncToRefreshrate=false
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Don't use alpha blending when rendering text
 | 
			
		||||
# (default: disabled)
 | 
			
		||||
#
 | 
			
		||||
# solidFonts=false
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Work around buggy graphics drivers which don't
 | 
			
		||||
# properly synchronize texture access, most
 | 
			
		||||
# apparent when text doesn't show up or the map
 | 
			
		||||
# tileset doesn't render at all
 | 
			
		||||
# (default: disabled)
 | 
			
		||||
#
 | 
			
		||||
# subImageFix=false
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Set the base path of the game to '/path/to/game'
 | 
			
		||||
# (default: executable directory)
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -218,6 +256,19 @@
 | 
			
		|||
# SE.sourceCount=6
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# The Windows game executable name minus ".exe". By default
 | 
			
		||||
# this is "Game", but some developers manually rename it.
 | 
			
		||||
# mkxp needs this name because both the .ini (game
 | 
			
		||||
# configuration) and .rgssad (encrypted data archive) must
 | 
			
		||||
# carry the same name minus their extension, and we cannot
 | 
			
		||||
# guess the executable's name.
 | 
			
		||||
# You could just as well rename them both to "Game.ini" and
 | 
			
		||||
# "Game.rgssad", but specifying the executable name here
 | 
			
		||||
# is a tiny bit less intrusive.
 | 
			
		||||
#
 | 
			
		||||
# execName=Game
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Give a hint on which language the game title as
 | 
			
		||||
# specified in the Game.ini is, useful if the encoding
 | 
			
		||||
# is being falsely detected. Relevant only if mkxp was
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								mkxp.pro
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								mkxp.pro
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -103,9 +103,9 @@ HEADERS += \
 | 
			
		|||
	src/glstate.h \
 | 
			
		||||
	src/quad.h \
 | 
			
		||||
	src/tilemap.h \
 | 
			
		||||
	src/flashmap.h \
 | 
			
		||||
	src/tilemap-common.h \
 | 
			
		||||
	src/graphics.h \
 | 
			
		||||
	src/debuglogger.h \
 | 
			
		||||
	src/gl-debug.h \
 | 
			
		||||
	src/global-ibo.h \
 | 
			
		||||
	src/exception.h \
 | 
			
		||||
	src/filesystem.h \
 | 
			
		||||
| 
						 | 
				
			
			@ -158,7 +158,7 @@ SOURCES += \
 | 
			
		|||
	src/tilemap.cpp \
 | 
			
		||||
	src/autotiles.cpp \
 | 
			
		||||
	src/graphics.cpp \
 | 
			
		||||
	src/debuglogger.cpp \
 | 
			
		||||
	src/gl-debug.cpp \
 | 
			
		||||
	src/etc.cpp \
 | 
			
		||||
	src/config.cpp \
 | 
			
		||||
	src/settingsmenu.cpp \
 | 
			
		||||
| 
						 | 
				
			
			@ -183,16 +183,21 @@ SOURCES += \
 | 
			
		|||
	src/fluid-fun.cpp
 | 
			
		||||
 | 
			
		||||
EMBED = \
 | 
			
		||||
	shader/common.h \
 | 
			
		||||
	shader/transSimple.frag \
 | 
			
		||||
	shader/trans.frag \
 | 
			
		||||
	shader/hue.frag \
 | 
			
		||||
	shader/sprite.frag \
 | 
			
		||||
	shader/plane.frag \
 | 
			
		||||
	shader/gray.frag \
 | 
			
		||||
	shader/bitmapBlit.frag \
 | 
			
		||||
	shader/flatColor.frag \
 | 
			
		||||
	shader/simple.frag \
 | 
			
		||||
	shader/simpleColor.frag \
 | 
			
		||||
	shader/simpleAlpha.frag \
 | 
			
		||||
	shader/simpleAlphaUni.frag \
 | 
			
		||||
	shader/flashMap.frag \
 | 
			
		||||
	shader/minimal.vert \
 | 
			
		||||
	shader/simple.vert \
 | 
			
		||||
	shader/simpleColor.vert \
 | 
			
		||||
	shader/sprite.vert \
 | 
			
		||||
| 
						 | 
				
			
			@ -202,7 +207,8 @@ EMBED = \
 | 
			
		|||
	shader/blurV.vert \
 | 
			
		||||
	shader/simpleMatrix.vert \
 | 
			
		||||
	shader/tilemapvx.vert \
 | 
			
		||||
	assets/liberation.ttf
 | 
			
		||||
	assets/liberation.ttf \
 | 
			
		||||
	assets/icon.png
 | 
			
		||||
 | 
			
		||||
SHARED_FLUID {
 | 
			
		||||
	DEFINES += SHARED_FLUID
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										43
									
								
								patches/ruby/static_zlib.patch
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								patches/ruby/static_zlib.patch
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
--- a/common.mk
 | 
			
		||||
+++ b/common.mk
 | 
			
		||||
@@ -95,6 +95,7 @@ COMMONOBJS    = array.$(OBJEXT) \
 | 
			
		||||
 		vm_trace.$(OBJEXT) \
 | 
			
		||||
 		thread.$(OBJEXT) \
 | 
			
		||||
 		cont.$(OBJEXT) \
 | 
			
		||||
+		ext/zlib/zlib.$(OBJEXT) \
 | 
			
		||||
 		$(BUILTIN_ENCOBJS) \
 | 
			
		||||
 		$(BUILTIN_TRANSOBJS) \
 | 
			
		||||
 		$(MISSING)
 | 
			
		||||
diff --git a/ruby-2.1.5.orig/configure b/ruby-2.1.5/configure
 | 
			
		||||
index d0f1f68..45ab642 100755
 | 
			
		||||
--- a/configure
 | 
			
		||||
+++ b/configure
 | 
			
		||||
@@ -2838,6 +2838,8 @@ ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
+LIBS="$LIBS -lz"
 | 
			
		||||
+
 | 
			
		||||
 { # environment section
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
--- a/configure.in
 | 
			
		||||
+++ b/configure.in
 | 
			
		||||
@@ -31,6 +31,8 @@ rm() {
 | 
			
		||||
 }
 | 
			
		||||
 ])])])
 | 
			
		||||
 
 | 
			
		||||
+LIBS="$LIBS -lz"
 | 
			
		||||
+
 | 
			
		||||
 { # environment section
 | 
			
		||||
 
 | 
			
		||||
 AC_ARG_WITH(baseruby,
 | 
			
		||||
--- a/inits.c
 | 
			
		||||
+++ b/inits.c
 | 
			
		||||
@@ -61,5 +61,6 @@ rb_call_inits(void)
 | 
			
		||||
     CALL(Complex);
 | 
			
		||||
     CALL(version);
 | 
			
		||||
     CALL(vm_trace);
 | 
			
		||||
+    CALL(zlib);
 | 
			
		||||
 }
 | 
			
		||||
 #undef CALL
 | 
			
		||||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ uniform sampler2D destination;
 | 
			
		|||
 | 
			
		||||
uniform vec4 subRect;
 | 
			
		||||
 | 
			
		||||
uniform float opacity;
 | 
			
		||||
uniform lowp float opacity;
 | 
			
		||||
 | 
			
		||||
varying vec2 v_texCoord;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ varying vec2 v_blurCoord[2];
 | 
			
		|||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	vec4 frag = vec4(0, 0, 0, 0);
 | 
			
		||||
	lowp vec4 frag = vec4(0, 0, 0, 0);
 | 
			
		||||
 | 
			
		||||
	frag += texture2D(texture, v_texCoord);
 | 
			
		||||
	frag += texture2D(texture, v_blurCoord[0]);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								shader/common.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								shader/common.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
#ifdef GLSLES
 | 
			
		||||
 | 
			
		||||
#ifdef FRAGMENT_SHADER
 | 
			
		||||
/* Only the fragment shader has no default float precision */
 | 
			
		||||
precision mediump float;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
/* Desktop GLSL doesn't know about these */
 | 
			
		||||
#define highp
 | 
			
		||||
#define mediump
 | 
			
		||||
#define lowp
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
 | 
			
		||||
uniform float alpha;
 | 
			
		||||
uniform lowp float alpha;
 | 
			
		||||
 | 
			
		||||
varying vec4 v_color;
 | 
			
		||||
varying lowp vec4 v_color;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										7
									
								
								shader/flatColor.frag
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								shader/flatColor.frag
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
 | 
			
		||||
uniform lowp vec4 color;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	gl_FragColor = color;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								shader/gray.frag
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								shader/gray.frag
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
 | 
			
		||||
uniform sampler2D texture;
 | 
			
		||||
uniform lowp float gray;
 | 
			
		||||
 | 
			
		||||
varying vec2 v_texCoord;
 | 
			
		||||
 | 
			
		||||
const vec3 lumaF = vec3(.299, .587, .114);
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	/* Sample source color */
 | 
			
		||||
	vec4 frag = texture2D(texture, v_texCoord);
 | 
			
		||||
 | 
			
		||||
	/* Apply gray */
 | 
			
		||||
	float luma = dot(frag.rgb, lumaF);
 | 
			
		||||
	frag.rgb = mix(frag.rgb, vec3(luma), gray);
 | 
			
		||||
 | 
			
		||||
	gl_FragColor = frag;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +29,11 @@ void main ()
 | 
			
		|||
	/* Make the user's adjustments */
 | 
			
		||||
	hue += hueAdjust;
 | 
			
		||||
 | 
			
		||||
	// Convert back to YIQ
 | 
			
		||||
	/* Remember old I and color */
 | 
			
		||||
	float IOriginal = I;
 | 
			
		||||
	vec4 coOriginal = color;
 | 
			
		||||
 | 
			
		||||
	/* Convert back to YIQ */
 | 
			
		||||
	Q = chroma * sin (hue);
 | 
			
		||||
	I = chroma * cos (hue);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,5 +44,5 @@ void main ()
 | 
			
		|||
	color.b  = dot  (yIQ, kYIQToB);
 | 
			
		||||
 | 
			
		||||
	/* Save the result */
 | 
			
		||||
	gl_FragColor = color;
 | 
			
		||||
	gl_FragColor = (IOriginal == 0.0) ? coOriginal : color;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								shader/minimal.vert
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								shader/minimal.vert
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
 | 
			
		||||
uniform mat4 projMat;
 | 
			
		||||
attribute vec2 position;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	gl_Position = projMat * vec4(position, 0, 1);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +1,11 @@
 | 
			
		|||
 | 
			
		||||
uniform sampler2D texture;
 | 
			
		||||
 | 
			
		||||
uniform vec4 tone;
 | 
			
		||||
uniform lowp vec4 tone;
 | 
			
		||||
 | 
			
		||||
uniform float opacity;
 | 
			
		||||
uniform vec4 color;
 | 
			
		||||
uniform vec4 flash;
 | 
			
		||||
uniform lowp float opacity;
 | 
			
		||||
uniform lowp vec4 color;
 | 
			
		||||
uniform lowp vec4 flash;
 | 
			
		||||
 | 
			
		||||
varying vec2 v_texCoord;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
uniform sampler2D texture;
 | 
			
		||||
 | 
			
		||||
varying vec2 v_texCoord;
 | 
			
		||||
varying vec4 v_color;
 | 
			
		||||
varying lowp vec4 v_color;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								shader/simpleAlphaUni.frag
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								shader/simpleAlphaUni.frag
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
 | 
			
		||||
uniform sampler2D texture;
 | 
			
		||||
uniform lowp float alpha;
 | 
			
		||||
 | 
			
		||||
varying vec2 v_texCoord;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	gl_FragColor = texture2D(texture, v_texCoord);
 | 
			
		||||
	gl_FragColor.a *= alpha;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
 | 
			
		||||
varying vec4 v_color;
 | 
			
		||||
varying lowp vec4 v_color;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,10 +6,10 @@ uniform vec2 translation;
 | 
			
		|||
 | 
			
		||||
attribute vec2 position;
 | 
			
		||||
attribute vec2 texCoord;
 | 
			
		||||
attribute vec4 color;
 | 
			
		||||
attribute lowp vec4 color;
 | 
			
		||||
 | 
			
		||||
varying vec2 v_texCoord;
 | 
			
		||||
varying vec4 v_color;
 | 
			
		||||
varying lowp vec4 v_color;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,10 +6,10 @@ uniform vec2 texSizeInv;
 | 
			
		|||
 | 
			
		||||
attribute vec2 position;
 | 
			
		||||
attribute vec2 texCoord;
 | 
			
		||||
attribute vec4 color;
 | 
			
		||||
attribute lowp vec4 color;
 | 
			
		||||
 | 
			
		||||
varying vec2 v_texCoord;
 | 
			
		||||
varying vec4 v_color;
 | 
			
		||||
varying lowp vec4 v_color;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +1,13 @@
 | 
			
		|||
 | 
			
		||||
uniform sampler2D texture;
 | 
			
		||||
 | 
			
		||||
uniform vec4 tone;
 | 
			
		||||
uniform lowp vec4 tone;
 | 
			
		||||
 | 
			
		||||
uniform float opacity;
 | 
			
		||||
uniform vec4 color;
 | 
			
		||||
uniform lowp float opacity;
 | 
			
		||||
uniform lowp vec4 color;
 | 
			
		||||
 | 
			
		||||
uniform float bushDepth;
 | 
			
		||||
uniform float bushOpacity;
 | 
			
		||||
uniform lowp float bushOpacity;
 | 
			
		||||
 | 
			
		||||
varying vec2 v_texCoord;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +32,7 @@ void main()
 | 
			
		|||
	frag.rgb = mix(frag.rgb, color.rgb, color.a);
 | 
			
		||||
 | 
			
		||||
	/* Apply bush alpha by mathematical if */
 | 
			
		||||
	float underBush = float(v_texCoord.y < bushDepth);
 | 
			
		||||
	lowp float underBush = float(v_texCoord.y < bushDepth);
 | 
			
		||||
	frag.a *= clamp(bushOpacity + underBush, 0.0, 1.0);
 | 
			
		||||
	
 | 
			
		||||
	gl_FragColor = frag;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,8 +18,9 @@ const float atAniOffset = 32.0*3.0;
 | 
			
		|||
void main()
 | 
			
		||||
{
 | 
			
		||||
	vec2 tex = texCoord;
 | 
			
		||||
	if (tex.x <= atAreaW && tex.y <= atAreaH)
 | 
			
		||||
		tex.x += aniIndex * atAniOffset;
 | 
			
		||||
 | 
			
		||||
	lowp float pred = float(tex.x <= atAreaW && tex.y <= atAreaH);
 | 
			
		||||
	tex.x += aniIndex * atAniOffset * pred;
 | 
			
		||||
 | 
			
		||||
	gl_Position = projMat * vec4(position + translation, 0, 1);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,14 +18,15 @@ const float atAreaCW = 4.0*32.0;
 | 
			
		|||
void main()
 | 
			
		||||
{
 | 
			
		||||
	vec2 tex = texCoord;
 | 
			
		||||
	lowp float pred;
 | 
			
		||||
 | 
			
		||||
	/* Type A autotiles shift horizontally */
 | 
			
		||||
	if (tex.x <= atAreaA.x && tex.y <= atAreaA.y)
 | 
			
		||||
		tex.x += aniOffset.x;
 | 
			
		||||
	pred = float(tex.x <= atAreaA.x && tex.y <= atAreaA.y);
 | 
			
		||||
	tex.x += aniOffset.x * pred;
 | 
			
		||||
 | 
			
		||||
	/* Type C autotiles shift vertically */
 | 
			
		||||
	if (tex.x >= atAreaCX && tex.x <= (atAreaCX+atAreaCW) && tex.y <= atAreaA.y)
 | 
			
		||||
		tex.y += aniOffset.y;
 | 
			
		||||
	pred = float(tex.x >= atAreaCX && tex.x <= (atAreaCX+atAreaCW) && tex.y <= atAreaA.y);
 | 
			
		||||
	tex.y += aniOffset.y * pred;
 | 
			
		||||
 | 
			
		||||
	gl_Position = projMat * vec4(position + translation, 0, 1);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ void main()
 | 
			
		|||
{
 | 
			
		||||
    float transV = texture2D(transMap, v_texCoord).r;
 | 
			
		||||
    float cTransV = clamp(transV, prog, prog+vague);
 | 
			
		||||
    float alpha = (cTransV - prog) / vague;
 | 
			
		||||
    lowp float alpha = (cTransV - prog) / vague;
 | 
			
		||||
    
 | 
			
		||||
    vec4 newFrag = texture2D(currentScene, v_texCoord);
 | 
			
		||||
    vec4 oldFrag = texture2D(frozenScene, v_texCoord);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -238,5 +238,6 @@ inline ALenum chooseALFormat(int sampleSize, int channelCount)
 | 
			
		|||
 | 
			
		||||
#define AUDIO_SLEEP 10
 | 
			
		||||
#define STREAM_BUF_SIZE 32768
 | 
			
		||||
#define GLOBAL_VOLUME 0.8
 | 
			
		||||
 | 
			
		||||
#endif // ALUTIL_H
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,10 +23,13 @@
 | 
			
		|||
 | 
			
		||||
#include "sharedstate.h"
 | 
			
		||||
#include "sharedmidistate.h"
 | 
			
		||||
#include "eventthread.h"
 | 
			
		||||
#include "filesystem.h"
 | 
			
		||||
#include "exception.h"
 | 
			
		||||
#include "aldatasource.h"
 | 
			
		||||
#include "fluid-fun.h"
 | 
			
		||||
#include "sdl-util.h"
 | 
			
		||||
#include "debugwriter.h"
 | 
			
		||||
 | 
			
		||||
#include <SDL_mutex.h>
 | 
			
		||||
#include <SDL_thread.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -122,6 +125,9 @@ void ALStream::stop()
 | 
			
		|||
 | 
			
		||||
void ALStream::play(float offset)
 | 
			
		||||
{
 | 
			
		||||
	if (!source)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	checkStopped();
 | 
			
		||||
 | 
			
		||||
	switch (state)
 | 
			
		||||
| 
						 | 
				
			
			@ -195,8 +201,8 @@ void ALStream::closeSource()
 | 
			
		|||
 | 
			
		||||
void ALStream::openSource(const std::string &filename)
 | 
			
		||||
{
 | 
			
		||||
	const char *ext;
 | 
			
		||||
	shState->fileSystem().openRead(srcOps, filename.c_str(), FileSystem::Audio, false, &ext);
 | 
			
		||||
	char ext[8];
 | 
			
		||||
	shState->fileSystem().openRead(srcOps, filename.c_str(), false, ext, sizeof(ext));
 | 
			
		||||
	needsRewind.clear();
 | 
			
		||||
 | 
			
		||||
	/* Try to read ogg file signature */
 | 
			
		||||
| 
						 | 
				
			
			@ -204,24 +210,36 @@ void ALStream::openSource(const std::string &filename)
 | 
			
		|||
	SDL_RWread(&srcOps, sig, 1, 4);
 | 
			
		||||
	SDL_RWseek(&srcOps, 0, RW_SEEK_SET);
 | 
			
		||||
 | 
			
		||||
	if (!strcmp(sig, "OggS"))
 | 
			
		||||
	try
 | 
			
		||||
	{
 | 
			
		||||
		source = createVorbisSource(srcOps, looped);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!strcmp(sig, "MThd"))
 | 
			
		||||
	{
 | 
			
		||||
		shState->midiState().initIfNeeded(shState->config());
 | 
			
		||||
 | 
			
		||||
		if (HAVE_FLUID)
 | 
			
		||||
		if (!strcmp(sig, "OggS"))
 | 
			
		||||
		{
 | 
			
		||||
			source = createMidiSource(srcOps, looped);
 | 
			
		||||
			source = createVorbisSource(srcOps, looped);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	source = createSDLSource(srcOps, ext, STREAM_BUF_SIZE, looped);
 | 
			
		||||
		if (!strcmp(sig, "MThd"))
 | 
			
		||||
		{
 | 
			
		||||
			shState->midiState().initIfNeeded(shState->config());
 | 
			
		||||
 | 
			
		||||
			if (HAVE_FLUID)
 | 
			
		||||
			{
 | 
			
		||||
				source = createMidiSource(srcOps, looped);
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		source = createSDLSource(srcOps, ext, STREAM_BUF_SIZE, looped);
 | 
			
		||||
	}
 | 
			
		||||
	catch (const Exception &e)
 | 
			
		||||
	{
 | 
			
		||||
		char buf[512];
 | 
			
		||||
		snprintf(buf, sizeof(buf), "Unable to decode audio stream: %s.%s: %s",
 | 
			
		||||
		         filename.c_str(), ext, e.msg.c_str());
 | 
			
		||||
		buf[sizeof(buf)-1] = '\0';
 | 
			
		||||
 | 
			
		||||
		Debug() << buf;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ALStream::stopStream()
 | 
			
		||||
| 
						 | 
				
			
			@ -361,6 +379,8 @@ void ALStream::streamData()
 | 
			
		|||
	 * refill and queue them up again */
 | 
			
		||||
	while (true)
 | 
			
		||||
	{
 | 
			
		||||
		shState->rtData().syncPoint.passSecondarySync();
 | 
			
		||||
 | 
			
		||||
		ALint procBufs = AL::Source::getProcBufferCount(alSrc);
 | 
			
		||||
 | 
			
		||||
		while (procBufs--)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@
 | 
			
		|||
#include "soundemitter.h"
 | 
			
		||||
#include "sharedstate.h"
 | 
			
		||||
#include "sharedmidistate.h"
 | 
			
		||||
#include "eventthread.h"
 | 
			
		||||
#include "sdl-util.h"
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +41,8 @@ struct AudioPrivate
 | 
			
		|||
 | 
			
		||||
	SoundEmitter se;
 | 
			
		||||
 | 
			
		||||
	SyncPoint &syncPoint;
 | 
			
		||||
 | 
			
		||||
	/* The 'MeWatch' is responsible for detecting
 | 
			
		||||
	 * a playing ME, quickly fading out the BGM and
 | 
			
		||||
	 * keeping it paused/stopped while the ME plays,
 | 
			
		||||
| 
						 | 
				
			
			@ -60,11 +63,12 @@ struct AudioPrivate
 | 
			
		|||
		MeWatchState state;
 | 
			
		||||
	} meWatch;
 | 
			
		||||
 | 
			
		||||
	AudioPrivate(const Config &conf)
 | 
			
		||||
	AudioPrivate(RGSSThreadData &rtData)
 | 
			
		||||
	    : bgm(ALStream::Looped, "bgm"),
 | 
			
		||||
	      bgs(ALStream::Looped, "bgs"),
 | 
			
		||||
	      me(ALStream::NotLooped, "me"),
 | 
			
		||||
	      se(conf)
 | 
			
		||||
	      se(rtData.config),
 | 
			
		||||
	      syncPoint(rtData.syncPoint)
 | 
			
		||||
	{
 | 
			
		||||
		meWatch.state = MeNotPlaying;
 | 
			
		||||
		meWatch.thread = createSDLThread
 | 
			
		||||
| 
						 | 
				
			
			@ -84,6 +88,8 @@ struct AudioPrivate
 | 
			
		|||
 | 
			
		||||
		while (true)
 | 
			
		||||
		{
 | 
			
		||||
			syncPoint.passSecondarySync();
 | 
			
		||||
 | 
			
		||||
			if (meWatch.termReq)
 | 
			
		||||
				return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -231,8 +237,8 @@ struct AudioPrivate
 | 
			
		|||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Audio::Audio(const Config &conf)
 | 
			
		||||
	: p(new AudioPrivate(conf))
 | 
			
		||||
Audio::Audio(RGSSThreadData &rtData)
 | 
			
		||||
	: p(new AudioPrivate(rtData))
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,7 +33,7 @@
 | 
			
		|||
 *   quite make out their meaning yet) */
 | 
			
		||||
 | 
			
		||||
struct AudioPrivate;
 | 
			
		||||
struct Config;
 | 
			
		||||
struct RGSSThreadData;
 | 
			
		||||
 | 
			
		||||
class Audio
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +70,7 @@ public:
 | 
			
		|||
	void reset();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	Audio(const Config &conf);
 | 
			
		||||
	Audio(RGSSThreadData &rtData);
 | 
			
		||||
	~Audio();
 | 
			
		||||
 | 
			
		||||
	friend struct SharedStatePrivate;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -252,7 +252,7 @@ float AudioStream::playingOffset()
 | 
			
		|||
 | 
			
		||||
void AudioStream::updateVolume()
 | 
			
		||||
{
 | 
			
		||||
	float vol = 1.0;
 | 
			
		||||
	float vol = GLOBAL_VOLUME;
 | 
			
		||||
 | 
			
		||||
	for (size_t i = 0; i < VolumeTypeCount; ++i)
 | 
			
		||||
		vol *= volumes[i];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,196 +4,196 @@ extern const StaticRect autotileRects[] =
 | 
			
		|||
{
 | 
			
		||||
	{ 32.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 96.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 96.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 96.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 96.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 64.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 80.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 32.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 48.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 96.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 96.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 96.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 96.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 96.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 96.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 48.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 96.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 96.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 64.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 32.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 80.5, 112.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 0.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 0.5, 16.5, 15, 15 }
 | 
			
		||||
	{ 0.5, 16.5, 15, 15 },
 | 
			
		||||
	{ 16.5, 16.5, 15, 15 }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern const int autotileRectsN = sizeof(autotileRects) / sizeof(autotileRects[0]);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,6 +52,8 @@
 | 
			
		|||
                            "Operation not supported for mega surfaces"); \
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#define OUTLINE_SIZE 1
 | 
			
		||||
 | 
			
		||||
/* Normalize (= ensure width and
 | 
			
		||||
 * height are positive) */
 | 
			
		||||
static IntRect normalizedRect(const IntRect &rect)
 | 
			
		||||
| 
						 | 
				
			
			@ -248,9 +250,10 @@ struct BitmapPrivate
 | 
			
		|||
Bitmap::Bitmap(const char *filename)
 | 
			
		||||
{
 | 
			
		||||
	SDL_RWops ops;
 | 
			
		||||
	const char *extension;
 | 
			
		||||
	shState->fileSystem().openRead(ops, filename, FileSystem::Image, false, &extension);
 | 
			
		||||
	SDL_Surface *imgSurf = IMG_LoadTyped_RW(&ops, 1, extension);
 | 
			
		||||
	char ext[8];
 | 
			
		||||
 | 
			
		||||
	shState->fileSystem().openRead(ops, filename, false, ext, sizeof(ext));
 | 
			
		||||
	SDL_Surface *imgSurf = IMG_LoadTyped_RW(&ops, 1, ext);
 | 
			
		||||
 | 
			
		||||
	if (!imgSurf)
 | 
			
		||||
		throw Exception(Exception::SDLError, "Error loading image '%s': %s",
 | 
			
		||||
| 
						 | 
				
			
			@ -317,6 +320,7 @@ Bitmap::Bitmap(const char *filename)
 | 
			
		|||
		/* Mega surface */
 | 
			
		||||
		p = new BitmapPrivate(this);
 | 
			
		||||
		p->megaSurface = imgSurf;
 | 
			
		||||
		SDL_SetSurfaceBlendMode(p->megaSurface, SDL_BLENDMODE_NONE);
 | 
			
		||||
	}
 | 
			
		||||
	else if (isCrop)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -487,14 +491,46 @@ void Bitmap::stretchBlt(const IntRect &destRect,
 | 
			
		|||
	if (opacity == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (source.megaSurface())
 | 
			
		||||
	SDL_Surface *srcSurf = source.megaSurface();
 | 
			
		||||
 | 
			
		||||
	if (srcSurf && shState->config().subImageFix)
 | 
			
		||||
	{
 | 
			
		||||
		/* Blit from software surface, for broken GL drivers */
 | 
			
		||||
		Vec2i gpTexSize;
 | 
			
		||||
		shState->ensureTexSize(sourceRect.w, sourceRect.h, gpTexSize);
 | 
			
		||||
		shState->bindTex();
 | 
			
		||||
 | 
			
		||||
		GLMeta::subRectImageUpload(srcSurf->w, sourceRect.x, sourceRect.y, 0, 0,
 | 
			
		||||
		                           sourceRect.w, sourceRect.h, srcSurf, GL_RGBA);
 | 
			
		||||
		GLMeta::subRectImageEnd();
 | 
			
		||||
 | 
			
		||||
		SimpleShader &shader = shState->shaders().simple;
 | 
			
		||||
		shader.bind();
 | 
			
		||||
		shader.setTranslation(Vec2i());
 | 
			
		||||
		shader.setTexSize(gpTexSize);
 | 
			
		||||
 | 
			
		||||
		p->pushSetViewport(shader);
 | 
			
		||||
		p->bindFBO();
 | 
			
		||||
 | 
			
		||||
		Quad &quad = shState->gpQuad();
 | 
			
		||||
		quad.setTexRect(FloatRect(0, 0, sourceRect.w, sourceRect.h));
 | 
			
		||||
		quad.setPosRect(destRect);
 | 
			
		||||
 | 
			
		||||
		p->blitQuad(quad);
 | 
			
		||||
		p->popViewport();
 | 
			
		||||
 | 
			
		||||
		p->addTaintedArea(destRect);
 | 
			
		||||
		p->onModified();
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	else if (srcSurf)
 | 
			
		||||
	{
 | 
			
		||||
		/* Blit from software surface */
 | 
			
		||||
		/* Don't do transparent blits for now */
 | 
			
		||||
		if (opacity < 255)
 | 
			
		||||
			source.ensureNonMega();
 | 
			
		||||
 | 
			
		||||
		SDL_Surface *srcSurf = source.megaSurface();
 | 
			
		||||
 | 
			
		||||
		SDL_Rect srcRect = sourceRect;
 | 
			
		||||
		SDL_Rect dstRect = destRect;
 | 
			
		||||
		SDL_Rect btmRect = { 0, 0, width(), height() };
 | 
			
		||||
| 
						 | 
				
			
			@ -510,26 +546,25 @@ void Bitmap::stretchBlt(const IntRect &destRect,
 | 
			
		|||
		SDL_Surface *blitTemp =
 | 
			
		||||
			SDL_CreateRGBSurface(0, destRect.w, destRect.h, bpp, rMask, gMask, bMask, aMask);
 | 
			
		||||
 | 
			
		||||
		// FXIME: This is supposed to be a scaled blit, put SDL2 for some reason
 | 
			
		||||
		// makes the source surface unusable after BlitScaled() is called. Investigate!
 | 
			
		||||
		SDL_BlitSurface(srcSurf, &srcRect, blitTemp, 0);
 | 
			
		||||
		SDL_BlitScaled(srcSurf, &srcRect, blitTemp, 0);
 | 
			
		||||
 | 
			
		||||
		TEX::bind(p->gl.tex);
 | 
			
		||||
 | 
			
		||||
		if (bltRect.w == dstRect.w && bltRect.h == dstRect.h)
 | 
			
		||||
		{
 | 
			
		||||
			/* Dest rectangle lies within bounding box */
 | 
			
		||||
			TEX::uploadSubImage(destRect.x, destRect.y,
 | 
			
		||||
			                    destRect.w, destRect.h,
 | 
			
		||||
			                    blitTemp->pixels, GL_RGBA);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			/* Clipped blit */
 | 
			
		||||
			GLMeta::subRectImageUpload(blitTemp->w, bltRect.x - dstRect.x, bltRect.y - dstRect.y,
 | 
			
		||||
			                           bltRect.x, bltRect.y, bltRect.w, bltRect.h, blitTemp, GL_RGBA);
 | 
			
		||||
			GLMeta::subRectImageEnd();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		SDL_FreeSurface(blitTemp);
 | 
			
		||||
 | 
			
		||||
		p->onModified();
 | 
			
		||||
| 
						 | 
				
			
			@ -581,7 +616,6 @@ void Bitmap::stretchBlt(const IntRect &destRect,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	p->addTaintedArea(destRect);
 | 
			
		||||
 | 
			
		||||
	p->onModified();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1057,6 +1091,7 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
 | 
			
		|||
 | 
			
		||||
	TTF_Font *font = p->font->getSdlFont();
 | 
			
		||||
	const Color &fontColor = p->font->getColor();
 | 
			
		||||
	const Color &outColor = p->font->getOutColor();
 | 
			
		||||
 | 
			
		||||
	SDL_Color c = fontColor.toSDLColor();
 | 
			
		||||
	c.a = 255;
 | 
			
		||||
| 
						 | 
				
			
			@ -1072,11 +1107,34 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
 | 
			
		|||
 | 
			
		||||
	p->ensureFormat(txtSurf, SDL_PIXELFORMAT_ABGR8888);
 | 
			
		||||
 | 
			
		||||
	// While real outlining is not yet here, use shadow
 | 
			
		||||
	// as a replacement to at least make text legible
 | 
			
		||||
	if (p->font->getShadow() || p->font->getOutline())
 | 
			
		||||
	if (p->font->getShadow())
 | 
			
		||||
		applyShadow(txtSurf, *p->format, c);
 | 
			
		||||
 | 
			
		||||
	/* outline using TTF_Outline and blending it together with SDL_BlitSurface
 | 
			
		||||
	 * FIXME: outline is forced to have the same opacity as the font color */
 | 
			
		||||
	if (p->font->getOutline())
 | 
			
		||||
	{
 | 
			
		||||
		SDL_Color co = outColor.toSDLColor();
 | 
			
		||||
		co.a = 255;
 | 
			
		||||
		SDL_Surface *outline;
 | 
			
		||||
		/* set the next font render to render the outline */
 | 
			
		||||
		TTF_SetFontOutline(font, OUTLINE_SIZE);
 | 
			
		||||
		if (shState->rtData().config.solidFonts)
 | 
			
		||||
			outline = TTF_RenderUTF8_Solid(font, str, co);
 | 
			
		||||
		else
 | 
			
		||||
			outline = TTF_RenderUTF8_Blended(font, str, co);
 | 
			
		||||
 | 
			
		||||
		p->ensureFormat(outline, SDL_PIXELFORMAT_ABGR8888);
 | 
			
		||||
		SDL_Rect outRect = {OUTLINE_SIZE, OUTLINE_SIZE, txtSurf->w, txtSurf->h}; 
 | 
			
		||||
 | 
			
		||||
		SDL_SetSurfaceBlendMode(txtSurf, SDL_BLENDMODE_BLEND);
 | 
			
		||||
		SDL_BlitSurface(txtSurf, NULL, outline, &outRect);
 | 
			
		||||
		SDL_FreeSurface(txtSurf);
 | 
			
		||||
		txtSurf = outline;
 | 
			
		||||
		/* reset outline to 0 */
 | 
			
		||||
		TTF_SetFontOutline(font, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int alignX = rect.x;
 | 
			
		||||
 | 
			
		||||
	switch (align)
 | 
			
		||||
| 
						 | 
				
			
			@ -1113,7 +1171,7 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
 | 
			
		|||
 | 
			
		||||
	if (fastBlit)
 | 
			
		||||
	{
 | 
			
		||||
		if (squeeze == 1.0)
 | 
			
		||||
		if (squeeze == 1.0 && !shState->config().subImageFix)
 | 
			
		||||
		{
 | 
			
		||||
			/* Even faster: upload directly to bitmap texture.
 | 
			
		||||
			 * We have to make sure the posRect lies within the texture
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1 @@
 | 
			
		|||
#include "../liberation.ttf.xxd"
 | 
			
		||||
#include "liberation.ttf.xxd"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										124
									
								
								src/config.cpp
									
										
									
									
									
								
							
							
						
						
									
										124
									
								
								src/config.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -32,6 +32,7 @@
 | 
			
		|||
 | 
			
		||||
#include "debugwriter.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "sdl-util.h"
 | 
			
		||||
 | 
			
		||||
#ifdef INI_ENCODING
 | 
			
		||||
extern "C" {
 | 
			
		||||
| 
						 | 
				
			
			@ -123,6 +124,10 @@ static bool validUtf8(const char *string)
 | 
			
		|||
static std::string prefPath(const char *org, const char *app)
 | 
			
		||||
{
 | 
			
		||||
	char *path = SDL_GetPrefPath(org, app);
 | 
			
		||||
 | 
			
		||||
	if (!path)
 | 
			
		||||
		return std::string();
 | 
			
		||||
 | 
			
		||||
	std::string str(path);
 | 
			
		||||
	SDL_free(path);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -135,65 +140,47 @@ namespace po = boost::program_options;
 | 
			
		|||
#define CONF_FILE "mkxp.conf"
 | 
			
		||||
 | 
			
		||||
Config::Config()
 | 
			
		||||
    : rgssVersion(0),
 | 
			
		||||
      debugMode(false),
 | 
			
		||||
      winResizable(false),
 | 
			
		||||
      fullscreen(false),
 | 
			
		||||
      fixedAspectRatio(true),
 | 
			
		||||
      smoothScaling(false),
 | 
			
		||||
      vsync(false),
 | 
			
		||||
      defScreenW(0),
 | 
			
		||||
      defScreenH(0),
 | 
			
		||||
      fixedFramerate(0),
 | 
			
		||||
      frameSkip(true),
 | 
			
		||||
      solidFonts(false),
 | 
			
		||||
      gameFolder("."),
 | 
			
		||||
      anyAltToggleFS(false),
 | 
			
		||||
      enableReset(true),
 | 
			
		||||
      allowSymlinks(false),
 | 
			
		||||
      pathCache(true),
 | 
			
		||||
      useScriptNames(false)
 | 
			
		||||
{
 | 
			
		||||
	midi.chorus = false;
 | 
			
		||||
	midi.reverb = false;
 | 
			
		||||
	SE.sourceCount = 6;
 | 
			
		||||
}
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
void Config::read(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
#define PO_DESC_ALL \
 | 
			
		||||
	PO_DESC(rgssVersion, int) \
 | 
			
		||||
	PO_DESC(debugMode, bool) \
 | 
			
		||||
	PO_DESC(winResizable, bool) \
 | 
			
		||||
	PO_DESC(fullscreen, bool) \
 | 
			
		||||
	PO_DESC(fixedAspectRatio, bool) \
 | 
			
		||||
	PO_DESC(smoothScaling, bool) \
 | 
			
		||||
	PO_DESC(vsync, bool) \
 | 
			
		||||
	PO_DESC(defScreenW, int) \
 | 
			
		||||
	PO_DESC(defScreenH, int) \
 | 
			
		||||
	PO_DESC(fixedFramerate, int) \
 | 
			
		||||
	PO_DESC(frameSkip, bool) \
 | 
			
		||||
	PO_DESC(solidFonts, bool) \
 | 
			
		||||
	PO_DESC(gameFolder, std::string) \
 | 
			
		||||
	PO_DESC(anyAltToggleFS, bool) \
 | 
			
		||||
	PO_DESC(enableReset, bool) \
 | 
			
		||||
	PO_DESC(allowSymlinks, bool) \
 | 
			
		||||
	PO_DESC(dataPathOrg, std::string) \
 | 
			
		||||
	PO_DESC(dataPathApp, std::string) \
 | 
			
		||||
	PO_DESC(iconPath, std::string) \
 | 
			
		||||
	PO_DESC(titleLanguage, std::string) \
 | 
			
		||||
	PO_DESC(midi.soundFont, std::string) \
 | 
			
		||||
	PO_DESC(midi.chorus, bool) \
 | 
			
		||||
	PO_DESC(midi.reverb, bool) \
 | 
			
		||||
	PO_DESC(SE.sourceCount, int) \
 | 
			
		||||
	PO_DESC(customScript, std::string) \
 | 
			
		||||
	PO_DESC(pathCache, bool) \
 | 
			
		||||
	PO_DESC(useScriptNames, bool)
 | 
			
		||||
	PO_DESC(rgssVersion, int, 0) \
 | 
			
		||||
	PO_DESC(debugMode, bool, false) \
 | 
			
		||||
	PO_DESC(printFPS, bool, false) \
 | 
			
		||||
	PO_DESC(winResizable, bool, false) \
 | 
			
		||||
	PO_DESC(fullscreen, bool, false) \
 | 
			
		||||
	PO_DESC(fixedAspectRatio, bool, true) \
 | 
			
		||||
	PO_DESC(smoothScaling, bool, false) \
 | 
			
		||||
	PO_DESC(vsync, bool, false) \
 | 
			
		||||
	PO_DESC(defScreenW, int, 0) \
 | 
			
		||||
	PO_DESC(defScreenH, int, 0) \
 | 
			
		||||
	PO_DESC(fixedFramerate, int, 0) \
 | 
			
		||||
	PO_DESC(frameSkip, bool, true) \
 | 
			
		||||
	PO_DESC(syncToRefreshrate, bool, false) \
 | 
			
		||||
	PO_DESC(solidFonts, bool, false) \
 | 
			
		||||
	PO_DESC(subImageFix, bool, false) \
 | 
			
		||||
	PO_DESC(gameFolder, std::string, ".") \
 | 
			
		||||
	PO_DESC(anyAltToggleFS, bool, false) \
 | 
			
		||||
	PO_DESC(enableReset, bool, true) \
 | 
			
		||||
	PO_DESC(allowSymlinks, bool, false) \
 | 
			
		||||
	PO_DESC(dataPathOrg, std::string, "") \
 | 
			
		||||
	PO_DESC(dataPathApp, std::string, "") \
 | 
			
		||||
	PO_DESC(iconPath, std::string, "") \
 | 
			
		||||
	PO_DESC(execName, std::string, "Game") \
 | 
			
		||||
	PO_DESC(titleLanguage, std::string, "") \
 | 
			
		||||
	PO_DESC(midi.soundFont, std::string, "") \
 | 
			
		||||
	PO_DESC(midi.chorus, bool, false) \
 | 
			
		||||
	PO_DESC(midi.reverb, bool, false) \
 | 
			
		||||
	PO_DESC(SE.sourceCount, int, 6) \
 | 
			
		||||
	PO_DESC(customScript, std::string, "") \
 | 
			
		||||
	PO_DESC(pathCache, bool, true) \
 | 
			
		||||
	PO_DESC(useScriptNames, bool, false)
 | 
			
		||||
 | 
			
		||||
// Not gonna take your shit boost
 | 
			
		||||
#define GUARD_ALL( exp ) try { exp } catch(...) {}
 | 
			
		||||
 | 
			
		||||
#define PO_DESC(key, type) (#key, po::value< type >()->default_value(key))
 | 
			
		||||
#define PO_DESC(key, type, def) (#key, po::value< type >()->default_value(def))
 | 
			
		||||
 | 
			
		||||
	po::options_description podesc;
 | 
			
		||||
	podesc.add_options()
 | 
			
		||||
| 
						 | 
				
			
			@ -219,26 +206,23 @@ void Config::read(int argc, char *argv[])
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/* Parse configuration file */
 | 
			
		||||
	std::ifstream confFile;
 | 
			
		||||
	confFile.open(CONF_FILE);
 | 
			
		||||
	SDLRWStream confFile(CONF_FILE, "r");
 | 
			
		||||
 | 
			
		||||
	if (confFile)
 | 
			
		||||
	{
 | 
			
		||||
		try
 | 
			
		||||
		{
 | 
			
		||||
			po::store(po::parse_config_file(confFile, podesc, true), vm);
 | 
			
		||||
			po::store(po::parse_config_file(confFile.stream(), podesc, true), vm);
 | 
			
		||||
			po::notify(vm);
 | 
			
		||||
		}
 | 
			
		||||
		catch (po::error &error)
 | 
			
		||||
		{
 | 
			
		||||
			Debug() << CONF_FILE":" << error.what();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		confFile.close();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#undef PO_DESC
 | 
			
		||||
#define PO_DESC(key, type) GUARD_ALL( key = vm[#key].as< type >(); )
 | 
			
		||||
#define PO_DESC(key, type, def) GUARD_ALL( key = vm[#key].as< type >(); )
 | 
			
		||||
 | 
			
		||||
	PO_DESC_ALL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -349,16 +333,26 @@ void Config::readGameINI()
 | 
			
		|||
	        ("Game.Scripts", po::value<std::string>())
 | 
			
		||||
	        ;
 | 
			
		||||
 | 
			
		||||
	std::string iniPath = gameFolder + "/Game.ini";
 | 
			
		||||
 | 
			
		||||
	std::ifstream iniFile;
 | 
			
		||||
	iniFile.open((iniPath).c_str());
 | 
			
		||||
 | 
			
		||||
	po::variables_map vm;
 | 
			
		||||
	po::store(po::parse_config_file(iniFile, podesc, true), vm);
 | 
			
		||||
	po::notify(vm);
 | 
			
		||||
	std::string iniFilename = execName + ".ini";
 | 
			
		||||
	SDLRWStream iniFile(iniFilename.c_str(), "r");
 | 
			
		||||
 | 
			
		||||
	iniFile.close();
 | 
			
		||||
	if (iniFile)
 | 
			
		||||
	{
 | 
			
		||||
		try
 | 
			
		||||
		{
 | 
			
		||||
			po::store(po::parse_config_file(iniFile.stream(), podesc, true), vm);
 | 
			
		||||
			po::notify(vm);
 | 
			
		||||
		}
 | 
			
		||||
		catch (po::error &error)
 | 
			
		||||
		{
 | 
			
		||||
			Debug() << iniFilename + ":" << error.what();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		Debug() << "FAILED to open" << iniFilename;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	GUARD_ALL( game.title = vm["Game.Title"].as<std::string>(); );
 | 
			
		||||
	GUARD_ALL( game.scripts = vm["Game.Scripts"].as<std::string>(); );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										48
									
								
								src/config.h
									
										
									
									
									
								
							
							
						
						
									
										48
									
								
								src/config.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -29,6 +29,49 @@ struct CropTexture
 | 
			
		|||
{
 | 
			
		||||
	std::string filename;
 | 
			
		||||
	int w, h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct TouchOverlay
 | 
			
		||||
{
 | 
			
		||||
	std::string image;
 | 
			
		||||
 | 
			
		||||
	struct Button
 | 
			
		||||
	{
 | 
			
		||||
		enum Shape
 | 
			
		||||
		{
 | 
			
		||||
			Rectangle,
 | 
			
		||||
			Circle,
 | 
			
		||||
			Triangle
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		std::string id;
 | 
			
		||||
		std::string target;
 | 
			
		||||
		Shape shape;
 | 
			
		||||
 | 
			
		||||
		int x;
 | 
			
		||||
		int y;
 | 
			
		||||
 | 
			
		||||
		union
 | 
			
		||||
		{
 | 
			
		||||
			struct
 | 
			
		||||
			{
 | 
			
		||||
				int width;
 | 
			
		||||
				int height;
 | 
			
		||||
			} r;
 | 
			
		||||
 | 
			
		||||
			struct
 | 
			
		||||
			{
 | 
			
		||||
				int radius;
 | 
			
		||||
			} c;
 | 
			
		||||
			struct
 | 
			
		||||
			{
 | 
			
		||||
				int x1, y1;
 | 
			
		||||
				int x2, y2;
 | 
			
		||||
			} t;
 | 
			
		||||
		} u;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	std::vector<Button> buttons;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Config
 | 
			
		||||
| 
						 | 
				
			
			@ -36,6 +79,7 @@ struct Config
 | 
			
		|||
	int rgssVersion;
 | 
			
		||||
 | 
			
		||||
	bool debugMode;
 | 
			
		||||
	bool printFPS;
 | 
			
		||||
 | 
			
		||||
	bool winResizable;
 | 
			
		||||
	bool fullscreen;
 | 
			
		||||
| 
						 | 
				
			
			@ -48,9 +92,12 @@ struct Config
 | 
			
		|||
 | 
			
		||||
	int fixedFramerate;
 | 
			
		||||
	bool frameSkip;
 | 
			
		||||
	bool syncToRefreshrate;
 | 
			
		||||
 | 
			
		||||
	bool solidFonts;
 | 
			
		||||
 | 
			
		||||
	bool subImageFix;
 | 
			
		||||
 | 
			
		||||
	std::string gameFolder;
 | 
			
		||||
	bool anyAltToggleFS;
 | 
			
		||||
	bool enableReset;
 | 
			
		||||
| 
						 | 
				
			
			@ -61,6 +108,7 @@ struct Config
 | 
			
		|||
	std::string dataPathApp;
 | 
			
		||||
 | 
			
		||||
	std::string iconPath;
 | 
			
		||||
	std::string execName;
 | 
			
		||||
	std::string titleLanguage;
 | 
			
		||||
 | 
			
		||||
	struct
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,11 @@
 | 
			
		|||
#include <sstream>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
#include <android/log.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* A cheap replacement for qDebug() */
 | 
			
		||||
 | 
			
		||||
class Debug
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +61,11 @@ public:
 | 
			
		|||
 | 
			
		||||
	~Debug()
 | 
			
		||||
	{
 | 
			
		||||
		std::clog << buf.str() << std::endl;
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
		__android_log_write(ANDROID_LOG_DEBUG, "mkxp", buf.str().c_str());
 | 
			
		||||
#else
 | 
			
		||||
		std::cerr << buf.str() << std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,6 +60,11 @@ struct Vec4
 | 
			
		|||
	{
 | 
			
		||||
		return (x == other.x && y == other.y && z == other.z && w == other.w);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool xyzHasEffect() const
 | 
			
		||||
	{
 | 
			
		||||
		return (x != 0.0 || y != 0.0 || z != 0.0);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct Vec2i
 | 
			
		||||
| 
						 | 
				
			
			@ -74,19 +79,68 @@ struct Vec2i
 | 
			
		|||
	    : x(x), y(y)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	explicit Vec2i(int xy)
 | 
			
		||||
	    : x(xy), y(xy)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	bool operator==(const Vec2i &other) const
 | 
			
		||||
	{
 | 
			
		||||
		return x == other.x && y == other.y;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vec2i &operator+=(const Vec2i &other)
 | 
			
		||||
	Vec2i &operator+=(const Vec2i &value)
 | 
			
		||||
	{
 | 
			
		||||
		x += other.x;
 | 
			
		||||
		y += other.y;
 | 
			
		||||
		x += value.x;
 | 
			
		||||
		y += value.y;
 | 
			
		||||
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vec2i &operator-=(const Vec2i &value)
 | 
			
		||||
	{
 | 
			
		||||
		x -= value.x;
 | 
			
		||||
		y -= value.y;
 | 
			
		||||
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vec2i operator+(const Vec2i &value) const
 | 
			
		||||
	{
 | 
			
		||||
		return Vec2i(x + value.x, y + value.y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vec2i operator-(const Vec2i &value) const
 | 
			
		||||
	{
 | 
			
		||||
		return Vec2i(x - value.x, y - value.y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template<typename T>
 | 
			
		||||
	Vec2i operator*(T value) const
 | 
			
		||||
	{
 | 
			
		||||
		return Vec2i(x * value, y * value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	template<typename T>
 | 
			
		||||
	Vec2i operator/(T value) const
 | 
			
		||||
	{
 | 
			
		||||
		return Vec2i(x / value, y / value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vec2i operator%(int value) const
 | 
			
		||||
	{
 | 
			
		||||
		return Vec2i(x % value, y % value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vec2i operator-() const
 | 
			
		||||
	{
 | 
			
		||||
		return Vec2i(-x, -y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vec2i operator!() const
 | 
			
		||||
	{
 | 
			
		||||
		return Vec2i(!x, !y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	operator Vec2() const
 | 
			
		||||
	{
 | 
			
		||||
		return Vec2(x, y);
 | 
			
		||||
| 
						 | 
				
			
			@ -108,6 +162,14 @@ struct IntRect : SDL_Rect
 | 
			
		|||
		this->h = h;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	IntRect(const Vec2i &pos, const Vec2i &size)
 | 
			
		||||
	{
 | 
			
		||||
		x = pos.x;
 | 
			
		||||
		y = pos.y;
 | 
			
		||||
		w = size.x;
 | 
			
		||||
		h = size.y;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool operator==(const IntRect &other) const
 | 
			
		||||
	{
 | 
			
		||||
		return (x == other.x && y == other.y &&
 | 
			
		||||
| 
						 | 
				
			
			@ -124,10 +186,24 @@ struct IntRect : SDL_Rect
 | 
			
		|||
		return Vec2i(w, h);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	operator SDL_Rect() const
 | 
			
		||||
	void setPos(const Vec2i &value)
 | 
			
		||||
	{
 | 
			
		||||
		SDL_Rect r = { x, y, w, h };
 | 
			
		||||
		return r;
 | 
			
		||||
		x = value.x;
 | 
			
		||||
		y = value.y;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setSize(const Vec2i &value)
 | 
			
		||||
	{
 | 
			
		||||
		w = value.x;
 | 
			
		||||
		h = value.y;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool encloses(const IntRect &o) const
 | 
			
		||||
	{
 | 
			
		||||
		return (x   <= o.x &&
 | 
			
		||||
		        y   <= o.y &&
 | 
			
		||||
		        x+w >= o.x+o.w &&
 | 
			
		||||
		        y+h >= o.y+o.h);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -163,35 +239,10 @@ struct FloatRect
 | 
			
		|||
	Vec2 topRight() const { return Vec2(x+w, y); }
 | 
			
		||||
	Vec2 bottomRight() const { return Vec2(x+w, y+h); }
 | 
			
		||||
 | 
			
		||||
	void shrinkHalf()
 | 
			
		||||
	{
 | 
			
		||||
		x += 0.5;
 | 
			
		||||
		y += 0.5;
 | 
			
		||||
		w -= 1.0;
 | 
			
		||||
		h -= 1.0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	FloatRect vFlipped() const
 | 
			
		||||
	{
 | 
			
		||||
		return FloatRect(x, y+h, w, -h);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	FloatRect hFlipped() const
 | 
			
		||||
	{
 | 
			
		||||
		return FloatRect(x+w, y, -w, h);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vec2 corner(int i) const
 | 
			
		||||
	{
 | 
			
		||||
		switch (i)
 | 
			
		||||
		{
 | 
			
		||||
		case 0 : return topLeft();
 | 
			
		||||
		case 1 : return topRight();
 | 
			
		||||
		case 2 : return bottomRight();
 | 
			
		||||
		case 3 : return bottomLeft();
 | 
			
		||||
		default : return Vec2();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Value between 0 and 255 with internal
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										57
									
								
								src/etc.cpp
									
										
									
									
									
								
							
							
						
						
									
										57
									
								
								src/etc.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -105,12 +105,10 @@ int Color::serialSize() const
 | 
			
		|||
 | 
			
		||||
void Color::serialize(char *buffer) const
 | 
			
		||||
{
 | 
			
		||||
	char *buf = buffer;
 | 
			
		||||
 | 
			
		||||
	write_double(&buf, red);
 | 
			
		||||
	write_double(&buf, green);
 | 
			
		||||
	write_double(&buf, blue);
 | 
			
		||||
	write_double(&buf, alpha);
 | 
			
		||||
	writeDouble(&buffer, red);
 | 
			
		||||
	writeDouble(&buffer, green);
 | 
			
		||||
	writeDouble(&buffer, blue);
 | 
			
		||||
	writeDouble(&buffer, alpha);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Color *Color::deserialize(const char *data, int len)
 | 
			
		||||
| 
						 | 
				
			
			@ -119,12 +117,11 @@ Color *Color::deserialize(const char *data, int len)
 | 
			
		|||
		throw Exception(Exception::ArgumentError, "Color: Serialized data invalid");
 | 
			
		||||
 | 
			
		||||
	Color *c = new Color();
 | 
			
		||||
	uint i = 0;
 | 
			
		||||
 | 
			
		||||
	c->red   = read_double(data, i);
 | 
			
		||||
	c->green = read_double(data, i);
 | 
			
		||||
	c->blue  = read_double(data, i);
 | 
			
		||||
	c->alpha = read_double(data, i);
 | 
			
		||||
	c->red   = readDouble(&data);
 | 
			
		||||
	c->green = readDouble(&data);
 | 
			
		||||
	c->blue  = readDouble(&data);
 | 
			
		||||
	c->alpha = readDouble(&data);
 | 
			
		||||
	c->updateInternal();
 | 
			
		||||
 | 
			
		||||
	return c;
 | 
			
		||||
| 
						 | 
				
			
			@ -241,12 +238,10 @@ int Tone::serialSize() const
 | 
			
		|||
 | 
			
		||||
void Tone::serialize(char *buffer) const
 | 
			
		||||
{
 | 
			
		||||
	char *buf = buffer;
 | 
			
		||||
 | 
			
		||||
	write_double(&buf, red);
 | 
			
		||||
	write_double(&buf, green);
 | 
			
		||||
	write_double(&buf, blue);
 | 
			
		||||
	write_double(&buf, gray);
 | 
			
		||||
	writeDouble(&buffer, red);
 | 
			
		||||
	writeDouble(&buffer, green);
 | 
			
		||||
	writeDouble(&buffer, blue);
 | 
			
		||||
	writeDouble(&buffer, gray);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Tone *Tone::deserialize(const char *data, int len)
 | 
			
		||||
| 
						 | 
				
			
			@ -255,12 +250,11 @@ Tone *Tone::deserialize(const char *data, int len)
 | 
			
		|||
		throw Exception(Exception::ArgumentError, "Tone: Serialized data invalid");
 | 
			
		||||
 | 
			
		||||
	Tone *t = new Tone();
 | 
			
		||||
	uint i = 0;
 | 
			
		||||
 | 
			
		||||
	t->red   = read_double(data, i);
 | 
			
		||||
	t->green = read_double(data, i);
 | 
			
		||||
	t->blue  = read_double(data, i);
 | 
			
		||||
	t->gray  = read_double(data, i);
 | 
			
		||||
	t->red   = readDouble(&data);
 | 
			
		||||
	t->green = readDouble(&data);
 | 
			
		||||
	t->blue  = readDouble(&data);
 | 
			
		||||
	t->gray  = readDouble(&data);
 | 
			
		||||
	t->updateInternal();
 | 
			
		||||
 | 
			
		||||
	return t;
 | 
			
		||||
| 
						 | 
				
			
			@ -390,12 +384,10 @@ int Rect::serialSize() const
 | 
			
		|||
 | 
			
		||||
void Rect::serialize(char *buffer) const
 | 
			
		||||
{
 | 
			
		||||
	char *buf = buffer;
 | 
			
		||||
 | 
			
		||||
	write_int32(&buf, x);
 | 
			
		||||
	write_int32(&buf, y);
 | 
			
		||||
	write_int32(&buf, width);
 | 
			
		||||
	write_int32(&buf, height);
 | 
			
		||||
	writeInt32(&buffer, x);
 | 
			
		||||
	writeInt32(&buffer, y);
 | 
			
		||||
	writeInt32(&buffer, width);
 | 
			
		||||
	writeInt32(&buffer, height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Rect *Rect::deserialize(const char *data, int len)
 | 
			
		||||
| 
						 | 
				
			
			@ -404,12 +396,11 @@ Rect *Rect::deserialize(const char *data, int len)
 | 
			
		|||
		throw Exception(Exception::ArgumentError, "Rect: Serialized data invalid");
 | 
			
		||||
 | 
			
		||||
	Rect *r = new Rect();
 | 
			
		||||
	uint i = 0;
 | 
			
		||||
 | 
			
		||||
	r->x      = read_int32(data, i);
 | 
			
		||||
	r->y      = read_int32(data, i);
 | 
			
		||||
	r->width  = read_int32(data, i);
 | 
			
		||||
	r->height = read_int32(data, i);
 | 
			
		||||
	r->x      = readInt32(&data);
 | 
			
		||||
	r->y      = readInt32(&data);
 | 
			
		||||
	r->width  = readInt32(&data);
 | 
			
		||||
	r->height = readInt32(&data);
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,25 +26,51 @@
 | 
			
		|||
#include <SDL_messagebox.h>
 | 
			
		||||
#include <SDL_timer.h>
 | 
			
		||||
#include <SDL_thread.h>
 | 
			
		||||
#include <SDL_touch.h>
 | 
			
		||||
 | 
			
		||||
#include <alext.h>
 | 
			
		||||
 | 
			
		||||
#include "sharedstate.h"
 | 
			
		||||
#include "graphics.h"
 | 
			
		||||
#include "settingsmenu.h"
 | 
			
		||||
#include "al-util.h"
 | 
			
		||||
#include "debugwriter.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
uint8_t EventThread::keyStates[] = { false };
 | 
			
		||||
typedef void (ALC_APIENTRY *LPALCDEVICEPAUSESOFT) (ALCdevice *device);
 | 
			
		||||
typedef void (ALC_APIENTRY *LPALCDEVICERESUMESOFT) (ALCdevice *device);
 | 
			
		||||
 | 
			
		||||
EventThread::JoyState EventThread::joyState =
 | 
			
		||||
{
 | 
			
		||||
	{ 0 }, { false }
 | 
			
		||||
};
 | 
			
		||||
#define AL_DEVICE_PAUSE_FUN \
 | 
			
		||||
	AL_FUN(DevicePause, LPALCDEVICEPAUSESOFT) \
 | 
			
		||||
	AL_FUN(DeviceResume, LPALCDEVICERESUMESOFT)
 | 
			
		||||
 | 
			
		||||
EventThread::MouseState EventThread::mouseState =
 | 
			
		||||
struct ALCFunctions
 | 
			
		||||
{
 | 
			
		||||
	0, 0, false, { false }
 | 
			
		||||
};
 | 
			
		||||
#define AL_FUN(name, type) type name;
 | 
			
		||||
	AL_DEVICE_PAUSE_FUN
 | 
			
		||||
#undef AL_FUN
 | 
			
		||||
} static alc;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
initALCFunctions(ALCdevice *alcDev)
 | 
			
		||||
{
 | 
			
		||||
	if (!strstr(alcGetString(alcDev, ALC_EXTENSIONS), "ALC_SOFT_pause_device"))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	Debug() << "ALC_SOFT_pause_device present";
 | 
			
		||||
 | 
			
		||||
#define AL_FUN(name, type) alc. name = (type) alcGetProcAddress(alcDev, "alc" #name "SOFT");
 | 
			
		||||
	AL_DEVICE_PAUSE_FUN;
 | 
			
		||||
#undef AL_FUN
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define HAVE_ALC_DEVICE_PAUSE alc.DevicePause
 | 
			
		||||
 | 
			
		||||
uint8_t EventThread::keyStates[];
 | 
			
		||||
EventThread::JoyState EventThread::joyState;
 | 
			
		||||
EventThread::MouseState EventThread::mouseState;
 | 
			
		||||
EventThread::TouchState EventThread::touchState;
 | 
			
		||||
 | 
			
		||||
/* User event codes */
 | 
			
		||||
enum
 | 
			
		||||
| 
						 | 
				
			
			@ -80,19 +106,24 @@ void EventThread::process(RGSSThreadData &rtData)
 | 
			
		|||
{
 | 
			
		||||
	SDL_Event event;
 | 
			
		||||
	SDL_Window *win = rtData.window;
 | 
			
		||||
	WindowSizeNotify &windowSizeMsg = rtData.windowSizeMsg;
 | 
			
		||||
	UnidirMessage<Vec2i> &windowSizeMsg = rtData.windowSizeMsg;
 | 
			
		||||
 | 
			
		||||
	initALCFunctions(rtData.alcDev);
 | 
			
		||||
	SDL_SetEventFilter(eventFilter, &rtData);
 | 
			
		||||
 | 
			
		||||
	fullscreen = rtData.config.fullscreen;
 | 
			
		||||
	int toggleFSMod = rtData.config.anyAltToggleFS ? KMOD_ALT : KMOD_LALT;
 | 
			
		||||
 | 
			
		||||
	fps.lastFrame = SDL_GetPerformanceCounter();
 | 
			
		||||
	fps.displayCounter = 0;
 | 
			
		||||
	fps.displaying = false;
 | 
			
		||||
	fps.immInitFlag = false;
 | 
			
		||||
	fps.immFiniFlag = false;
 | 
			
		||||
	fps.acc = 0;
 | 
			
		||||
	fps.accDiv = 0;
 | 
			
		||||
 | 
			
		||||
	if (rtData.config.printFPS)
 | 
			
		||||
		fps.sendUpdates.set();
 | 
			
		||||
 | 
			
		||||
	bool displayingFPS = false;
 | 
			
		||||
 | 
			
		||||
	bool cursorInWindow = false;
 | 
			
		||||
	bool windowFocused = false;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +140,11 @@ void EventThread::process(RGSSThreadData &rtData)
 | 
			
		|||
 | 
			
		||||
	bool resetting = false;
 | 
			
		||||
 | 
			
		||||
	int winW, winH;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	SDL_GetWindowSize(win, &winW, &winH);
 | 
			
		||||
 | 
			
		||||
	SettingsMenu *sMenu = 0;
 | 
			
		||||
 | 
			
		||||
	while (true)
 | 
			
		||||
| 
						 | 
				
			
			@ -132,14 +168,36 @@ void EventThread::process(RGSSThreadData &rtData)
 | 
			
		|||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Preselect and discard unwanted events here */
 | 
			
		||||
		switch (event.type)
 | 
			
		||||
		{
 | 
			
		||||
		case SDL_MOUSEBUTTONDOWN :
 | 
			
		||||
		case SDL_MOUSEBUTTONUP :
 | 
			
		||||
		case SDL_MOUSEMOTION :
 | 
			
		||||
			if (event.button.which == SDL_TOUCH_MOUSEID)
 | 
			
		||||
				continue;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case SDL_FINGERDOWN :
 | 
			
		||||
		case SDL_FINGERUP :
 | 
			
		||||
		case SDL_FINGERMOTION :
 | 
			
		||||
			if (event.tfinger.fingerId >= MAX_FINGERS)
 | 
			
		||||
				continue;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Now process the rest */
 | 
			
		||||
		switch (event.type)
 | 
			
		||||
		{
 | 
			
		||||
		case SDL_WINDOWEVENT :
 | 
			
		||||
			switch (event.window.event)
 | 
			
		||||
			{
 | 
			
		||||
			case SDL_WINDOWEVENT_SIZE_CHANGED :
 | 
			
		||||
				windowSizeMsg.notifyChange(event.window.data1,
 | 
			
		||||
				                           event.window.data2);
 | 
			
		||||
				winW = event.window.data1;
 | 
			
		||||
				winH = event.window.data2;
 | 
			
		||||
 | 
			
		||||
				windowSizeMsg.post(Vec2i(winW, winH));
 | 
			
		||||
				resetInputStates();
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case SDL_WINDOWEVENT_ENTER :
 | 
			
		||||
| 
						 | 
				
			
			@ -210,14 +268,18 @@ void EventThread::process(RGSSThreadData &rtData)
 | 
			
		|||
 | 
			
		||||
			if (event.key.keysym.scancode == SDL_SCANCODE_F2)
 | 
			
		||||
			{
 | 
			
		||||
				if (!fps.displaying)
 | 
			
		||||
				if (!displayingFPS)
 | 
			
		||||
				{
 | 
			
		||||
					fps.immInitFlag = true;
 | 
			
		||||
					fps.displaying = true;
 | 
			
		||||
					fps.immInitFlag.set();
 | 
			
		||||
					fps.sendUpdates.set();
 | 
			
		||||
					displayingFPS = true;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					fps.displaying = false;
 | 
			
		||||
					displayingFPS = false;
 | 
			
		||||
 | 
			
		||||
					if (!rtData.config.printFPS)
 | 
			
		||||
						fps.sendUpdates.clear();
 | 
			
		||||
 | 
			
		||||
					if (fullscreen)
 | 
			
		||||
					{
 | 
			
		||||
| 
						 | 
				
			
			@ -274,8 +336,12 @@ void EventThread::process(RGSSThreadData &rtData)
 | 
			
		|||
			joyState.buttons[event.jbutton.button] = false;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case SDL_JOYHATMOTION :
 | 
			
		||||
			joyState.hats[event.jhat.hat] = event.jhat.value;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case SDL_JOYAXISMOTION :
 | 
			
		||||
			joyState.axis[event.jaxis.axis] = event.jaxis.value;
 | 
			
		||||
			joyState.axes[event.jaxis.axis] = event.jaxis.value;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case SDL_JOYDEVICEADDED :
 | 
			
		||||
| 
						 | 
				
			
			@ -300,7 +366,21 @@ void EventThread::process(RGSSThreadData &rtData)
 | 
			
		|||
		case SDL_MOUSEMOTION :
 | 
			
		||||
			mouseState.x = event.motion.x;
 | 
			
		||||
			mouseState.y = event.motion.y;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case SDL_FINGERDOWN :
 | 
			
		||||
			i = event.tfinger.fingerId;
 | 
			
		||||
			touchState.fingers[i].down = true;
 | 
			
		||||
 | 
			
		||||
		case SDL_FINGERMOTION :
 | 
			
		||||
			i = event.tfinger.fingerId;
 | 
			
		||||
			touchState.fingers[i].x = event.tfinger.x * winW;
 | 
			
		||||
			touchState.fingers[i].y = event.tfinger.y * winH;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case SDL_FINGERUP :
 | 
			
		||||
			i = event.tfinger.fingerId;
 | 
			
		||||
			memset(&touchState.fingers[i], 0, sizeof(touchState.fingers[0]));
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		default :
 | 
			
		||||
| 
						 | 
				
			
			@ -329,7 +409,10 @@ void EventThread::process(RGSSThreadData &rtData)
 | 
			
		|||
				break;
 | 
			
		||||
 | 
			
		||||
			case UPDATE_FPS :
 | 
			
		||||
				if (!fps.displaying)
 | 
			
		||||
				if (rtData.config.printFPS)
 | 
			
		||||
					Debug() << "FPS:" << event.user.code;
 | 
			
		||||
 | 
			
		||||
				if (!fps.sendUpdates)
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				snprintf(buffer, sizeof(buffer), "%s - %d FPS",
 | 
			
		||||
| 
						 | 
				
			
			@ -354,12 +437,69 @@ void EventThread::process(RGSSThreadData &rtData)
 | 
			
		|||
			break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Just in case */
 | 
			
		||||
	rtData.syncPoint.resumeThreads();
 | 
			
		||||
 | 
			
		||||
	if (SDL_JoystickGetAttached(js))
 | 
			
		||||
		SDL_JoystickClose(js);
 | 
			
		||||
 | 
			
		||||
	delete sMenu;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int EventThread::eventFilter(void *data, SDL_Event *event)
 | 
			
		||||
{
 | 
			
		||||
	RGSSThreadData &rtData = *static_cast<RGSSThreadData*>(data);
 | 
			
		||||
 | 
			
		||||
	switch (event->type)
 | 
			
		||||
	{
 | 
			
		||||
	case SDL_APP_WILLENTERBACKGROUND :
 | 
			
		||||
		Debug() << "SDL_APP_WILLENTERBACKGROUND";
 | 
			
		||||
 | 
			
		||||
		if (HAVE_ALC_DEVICE_PAUSE)
 | 
			
		||||
			alc.DevicePause(rtData.alcDev);
 | 
			
		||||
 | 
			
		||||
		rtData.syncPoint.haltThreads();
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case SDL_APP_DIDENTERBACKGROUND :
 | 
			
		||||
		Debug() << "SDL_APP_DIDENTERBACKGROUND";
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case SDL_APP_WILLENTERFOREGROUND :
 | 
			
		||||
		Debug() << "SDL_APP_WILLENTERFOREGROUND";
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case SDL_APP_DIDENTERFOREGROUND :
 | 
			
		||||
		Debug() << "SDL_APP_DIDENTERFOREGROUND";
 | 
			
		||||
 | 
			
		||||
		if (HAVE_ALC_DEVICE_PAUSE)
 | 
			
		||||
			alc.DeviceResume(rtData.alcDev);
 | 
			
		||||
 | 
			
		||||
		rtData.syncPoint.resumeThreads();
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case SDL_APP_TERMINATING :
 | 
			
		||||
		Debug() << "SDL_APP_TERMINATING";
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case SDL_APP_LOWMEMORY :
 | 
			
		||||
		Debug() << "SDL_APP_LOWMEMORY";
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case SDL_RENDER_TARGETS_RESET :
 | 
			
		||||
		Debug() << "****** SDL_RENDER_TARGETS_RESET";
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case SDL_RENDER_DEVICE_RESET :
 | 
			
		||||
		Debug() << "****** SDL_RENDER_DEVICE_RESET";
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EventThread::cleanup()
 | 
			
		||||
{
 | 
			
		||||
	SDL_Event event;
 | 
			
		||||
| 
						 | 
				
			
			@ -374,6 +514,7 @@ void EventThread::resetInputStates()
 | 
			
		|||
	memset(&keyStates, 0, sizeof(keyStates));
 | 
			
		||||
	memset(&joyState, 0, sizeof(joyState));
 | 
			
		||||
	memset(&mouseState.buttons, 0, sizeof(mouseState.buttons));
 | 
			
		||||
	memset(&touchState, 0, sizeof(touchState));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EventThread::setFullscreen(SDL_Window *win, bool mode)
 | 
			
		||||
| 
						 | 
				
			
			@ -454,7 +595,7 @@ bool EventThread::getShowCursor() const
 | 
			
		|||
 | 
			
		||||
void EventThread::notifyFrame()
 | 
			
		||||
{
 | 
			
		||||
	if (!fps.displaying)
 | 
			
		||||
	if (!fps.sendUpdates)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	uint64_t current = SDL_GetPerformanceCounter();
 | 
			
		||||
| 
						 | 
				
			
			@ -463,8 +604,8 @@ void EventThread::notifyFrame()
 | 
			
		|||
 | 
			
		||||
	if (fps.immInitFlag)
 | 
			
		||||
	{
 | 
			
		||||
		fps.immInitFlag = false;
 | 
			
		||||
		fps.immFiniFlag = true;
 | 
			
		||||
		fps.immInitFlag.clear();
 | 
			
		||||
		fps.immFiniFlag.set();
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -480,7 +621,7 @@ void EventThread::notifyFrame()
 | 
			
		|||
		return;
 | 
			
		||||
 | 
			
		||||
	fps.displayCounter = 0;
 | 
			
		||||
	fps.immFiniFlag = false;
 | 
			
		||||
	fps.immFiniFlag.clear();
 | 
			
		||||
 | 
			
		||||
	int32_t avgFPS = fps.acc / fps.accDiv;
 | 
			
		||||
	fps.acc = fps.accDiv = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -490,3 +631,87 @@ void EventThread::notifyFrame()
 | 
			
		|||
	event.user.type = usrIdStart + UPDATE_FPS;
 | 
			
		||||
	SDL_PushEvent(&event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SyncPoint::haltThreads()
 | 
			
		||||
{
 | 
			
		||||
	if (mainSync.locked)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* Lock the reply sync first to avoid races */
 | 
			
		||||
	reply.lock();
 | 
			
		||||
 | 
			
		||||
	/* Lock main sync and sleep until RGSS thread
 | 
			
		||||
	 * reports back */
 | 
			
		||||
	mainSync.lock();
 | 
			
		||||
	reply.waitForUnlock();
 | 
			
		||||
 | 
			
		||||
	/* Now that the RGSS thread is asleep, we can
 | 
			
		||||
	 * safely put the other threads to sleep as well
 | 
			
		||||
	 * without causing deadlocks */
 | 
			
		||||
	secondSync.lock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SyncPoint::resumeThreads()
 | 
			
		||||
{
 | 
			
		||||
	if (!mainSync.locked)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	mainSync.unlock(false);
 | 
			
		||||
	secondSync.unlock(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SyncPoint::mainSyncLocked()
 | 
			
		||||
{
 | 
			
		||||
	return mainSync.locked;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SyncPoint::waitMainSync()
 | 
			
		||||
{
 | 
			
		||||
	reply.unlock(false);
 | 
			
		||||
	mainSync.waitForUnlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SyncPoint::passSecondarySync()
 | 
			
		||||
{
 | 
			
		||||
	if (!secondSync.locked)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	secondSync.waitForUnlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SyncPoint::Util::Util()
 | 
			
		||||
{
 | 
			
		||||
	mut = SDL_CreateMutex();
 | 
			
		||||
	cond = SDL_CreateCond();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SyncPoint::Util::~Util()
 | 
			
		||||
{
 | 
			
		||||
	SDL_DestroyCond(cond);
 | 
			
		||||
	SDL_DestroyMutex(mut);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SyncPoint::Util::lock()
 | 
			
		||||
{
 | 
			
		||||
	locked.set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SyncPoint::Util::unlock(bool multi)
 | 
			
		||||
{
 | 
			
		||||
	locked.clear();
 | 
			
		||||
 | 
			
		||||
	if (multi)
 | 
			
		||||
		SDL_CondBroadcast(cond);
 | 
			
		||||
	else
 | 
			
		||||
		SDL_CondSignal(cond);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SyncPoint::Util::waitForUnlock()
 | 
			
		||||
{
 | 
			
		||||
	SDL_LockMutex(mut);
 | 
			
		||||
 | 
			
		||||
	while (locked)
 | 
			
		||||
		SDL_CondWait(cond, mut);
 | 
			
		||||
 | 
			
		||||
	SDL_UnlockMutex(mut);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,21 +37,22 @@
 | 
			
		|||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
struct RGSSThreadData;
 | 
			
		||||
typedef struct ALCdevice_struct ALCdevice;
 | 
			
		||||
struct SDL_Window;
 | 
			
		||||
union SDL_Event;
 | 
			
		||||
 | 
			
		||||
#define MAX_FINGERS 4
 | 
			
		||||
 | 
			
		||||
class EventThread
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	static uint8_t keyStates[SDL_NUM_SCANCODES];
 | 
			
		||||
 | 
			
		||||
	struct JoyState
 | 
			
		||||
	{
 | 
			
		||||
		int axis[256];
 | 
			
		||||
		int axes[256];
 | 
			
		||||
		uint8_t hats[256];
 | 
			
		||||
		bool buttons[256];
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	static JoyState joyState;
 | 
			
		||||
 | 
			
		||||
	struct MouseState
 | 
			
		||||
	{
 | 
			
		||||
		int x, y;
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +60,21 @@ public:
 | 
			
		|||
		bool buttons[32];
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct FingerState
 | 
			
		||||
	{
 | 
			
		||||
		bool down;
 | 
			
		||||
		int x, y;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct TouchState
 | 
			
		||||
	{
 | 
			
		||||
		FingerState fingers[MAX_FINGERS];
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	static uint8_t keyStates[SDL_NUM_SCANCODES];
 | 
			
		||||
	static JoyState joyState;
 | 
			
		||||
	static MouseState mouseState;
 | 
			
		||||
	static TouchState touchState;
 | 
			
		||||
 | 
			
		||||
	static bool allocUserEvents();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -84,6 +99,8 @@ public:
 | 
			
		|||
	void notifyFrame();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	static int eventFilter(void *, SDL_Event*);
 | 
			
		||||
 | 
			
		||||
	void resetInputStates();
 | 
			
		||||
	void setFullscreen(SDL_Window *, bool mode);
 | 
			
		||||
	void updateCursorState(bool inWindow);
 | 
			
		||||
| 
						 | 
				
			
			@ -96,111 +113,101 @@ private:
 | 
			
		|||
	{
 | 
			
		||||
		uint64_t lastFrame;
 | 
			
		||||
		uint64_t displayCounter;
 | 
			
		||||
		bool displaying;
 | 
			
		||||
		bool immInitFlag;
 | 
			
		||||
		bool immFiniFlag;
 | 
			
		||||
		AtomicFlag sendUpdates;
 | 
			
		||||
		AtomicFlag immInitFlag;
 | 
			
		||||
		AtomicFlag immFiniFlag;
 | 
			
		||||
		double acc;
 | 
			
		||||
		uint32_t accDiv;
 | 
			
		||||
	} fps;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Used to asynchronously inform the RGSS thread
 | 
			
		||||
 * about window size changes */
 | 
			
		||||
struct WindowSizeNotify
 | 
			
		||||
 * about certain value changes */
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct UnidirMessage
 | 
			
		||||
{
 | 
			
		||||
	SDL_mutex *mutex;
 | 
			
		||||
	UnidirMessage()
 | 
			
		||||
	    : mutex(SDL_CreateMutex()),
 | 
			
		||||
	      current(T())
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	AtomicFlag changed;
 | 
			
		||||
	int w, h;
 | 
			
		||||
 | 
			
		||||
	WindowSizeNotify()
 | 
			
		||||
	{
 | 
			
		||||
		mutex = SDL_CreateMutex();
 | 
			
		||||
		w = h = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	~WindowSizeNotify()
 | 
			
		||||
	~UnidirMessage()
 | 
			
		||||
	{
 | 
			
		||||
		SDL_DestroyMutex(mutex);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Done from the sending side */
 | 
			
		||||
	void notifyChange(int w, int h)
 | 
			
		||||
	void post(const T &value)
 | 
			
		||||
	{
 | 
			
		||||
		SDL_LockMutex(mutex);
 | 
			
		||||
 | 
			
		||||
		this->w = w;
 | 
			
		||||
		this->h = h;
 | 
			
		||||
		changed.set();
 | 
			
		||||
		current = value;
 | 
			
		||||
 | 
			
		||||
		SDL_UnlockMutex(mutex);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Done from the receiving side */
 | 
			
		||||
	bool pollChange(int *w, int *h)
 | 
			
		||||
	bool poll(T &out) const
 | 
			
		||||
	{
 | 
			
		||||
		if (!changed)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		SDL_LockMutex(mutex);
 | 
			
		||||
 | 
			
		||||
		*w = this->w;
 | 
			
		||||
		*h = this->h;
 | 
			
		||||
		out = current;
 | 
			
		||||
		changed.clear();
 | 
			
		||||
 | 
			
		||||
		SDL_UnlockMutex(mutex);
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct BindingNotify
 | 
			
		||||
{
 | 
			
		||||
	BindingNotify()
 | 
			
		||||
	/* Done from either */
 | 
			
		||||
	void get(T &out) const
 | 
			
		||||
	{
 | 
			
		||||
		mut = SDL_CreateMutex();
 | 
			
		||||
	}
 | 
			
		||||
	~BindingNotify()
 | 
			
		||||
	{
 | 
			
		||||
		SDL_DestroyMutex(mut);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool poll(BDescVec &out) const
 | 
			
		||||
	{
 | 
			
		||||
		if (!changed)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		SDL_LockMutex(mut);
 | 
			
		||||
 | 
			
		||||
		out = data;
 | 
			
		||||
		changed.clear();
 | 
			
		||||
 | 
			
		||||
		SDL_UnlockMutex(mut);
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void get(BDescVec &out) const
 | 
			
		||||
	{
 | 
			
		||||
		SDL_LockMutex(mut);
 | 
			
		||||
		out = data;
 | 
			
		||||
		SDL_UnlockMutex(mut);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void post(const BDescVec &d)
 | 
			
		||||
	{
 | 
			
		||||
		SDL_LockMutex(mut);
 | 
			
		||||
 | 
			
		||||
		changed.set();
 | 
			
		||||
		data = d;
 | 
			
		||||
 | 
			
		||||
		SDL_UnlockMutex(mut);
 | 
			
		||||
		SDL_LockMutex(mutex);
 | 
			
		||||
		out = current;
 | 
			
		||||
		SDL_UnlockMutex(mutex);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	SDL_mutex *mut;
 | 
			
		||||
	BDescVec data;
 | 
			
		||||
	SDL_mutex *mutex;
 | 
			
		||||
	mutable AtomicFlag changed;
 | 
			
		||||
	T current;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct SyncPoint
 | 
			
		||||
{
 | 
			
		||||
	/* Used by eventFilter to control sleep/wakeup */
 | 
			
		||||
	void haltThreads();
 | 
			
		||||
	void resumeThreads();
 | 
			
		||||
 | 
			
		||||
	/* Used by RGSS thread */
 | 
			
		||||
	bool mainSyncLocked();
 | 
			
		||||
	void waitMainSync();
 | 
			
		||||
 | 
			
		||||
	/* Used by secondary (audio) threads */
 | 
			
		||||
	void passSecondarySync();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	struct Util
 | 
			
		||||
	{
 | 
			
		||||
		Util();
 | 
			
		||||
		~Util();
 | 
			
		||||
 | 
			
		||||
		void lock();
 | 
			
		||||
		void unlock(bool multi);
 | 
			
		||||
		void waitForUnlock();
 | 
			
		||||
 | 
			
		||||
		AtomicFlag locked;
 | 
			
		||||
		SDL_mutex *mut;
 | 
			
		||||
		SDL_cond *cond;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Util mainSync;
 | 
			
		||||
	Util reply;
 | 
			
		||||
	Util secondSync;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct RGSSThreadData
 | 
			
		||||
| 
						 | 
				
			
			@ -218,15 +225,18 @@ struct RGSSThreadData
 | 
			
		|||
	AtomicFlag rqResetFinish;
 | 
			
		||||
 | 
			
		||||
	EventThread *ethread;
 | 
			
		||||
	WindowSizeNotify windowSizeMsg;
 | 
			
		||||
	BindingNotify bindingUpdateMsg;
 | 
			
		||||
	UnidirMessage<Vec2i> windowSizeMsg;
 | 
			
		||||
	UnidirMessage<BDescVec> bindingUpdateMsg;
 | 
			
		||||
	SyncPoint syncPoint;
 | 
			
		||||
 | 
			
		||||
	const char *argv0;
 | 
			
		||||
 | 
			
		||||
	SDL_Window *window;
 | 
			
		||||
	ALCdevice *alcDev;
 | 
			
		||||
 | 
			
		||||
	Vec2 sizeResoRatio;
 | 
			
		||||
	Vec2i screenOffset;
 | 
			
		||||
	const int refreshRate;
 | 
			
		||||
 | 
			
		||||
	Config config;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -235,11 +245,15 @@ struct RGSSThreadData
 | 
			
		|||
	RGSSThreadData(EventThread *ethread,
 | 
			
		||||
	               const char *argv0,
 | 
			
		||||
	               SDL_Window *window,
 | 
			
		||||
	               ALCdevice *alcDev,
 | 
			
		||||
	               int refreshRate,
 | 
			
		||||
	               const Config& newconf)
 | 
			
		||||
	    : ethread(ethread),
 | 
			
		||||
	      argv0(argv0),
 | 
			
		||||
	      window(window),
 | 
			
		||||
	      alcDev(alcDev),
 | 
			
		||||
	      sizeResoRatio(1, 1),
 | 
			
		||||
	      refreshRate(refreshRate),
 | 
			
		||||
	      config(newconf)
 | 
			
		||||
	{}
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,6 +42,105 @@
 | 
			
		|||
#include <iconv.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct SDLRWIoContext
 | 
			
		||||
{
 | 
			
		||||
	SDL_RWops *ops;
 | 
			
		||||
	std::string filename;
 | 
			
		||||
 | 
			
		||||
	SDLRWIoContext(const char *filename)
 | 
			
		||||
	    : ops(SDL_RWFromFile(filename, "r")),
 | 
			
		||||
	      filename(filename)
 | 
			
		||||
	{
 | 
			
		||||
		if (!ops)
 | 
			
		||||
			throw Exception(Exception::SDLError,
 | 
			
		||||
			                "Failed to open file: %s", SDL_GetError());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	~SDLRWIoContext()
 | 
			
		||||
	{
 | 
			
		||||
		SDL_RWclose(ops);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static PHYSFS_Io *createSDLRWIo(const char *filename);
 | 
			
		||||
 | 
			
		||||
static SDL_RWops *getSDLRWops(PHYSFS_Io *io)
 | 
			
		||||
{
 | 
			
		||||
	return static_cast<SDLRWIoContext*>(io->opaque)->ops;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PHYSFS_sint64 SDLRWIoRead(struct PHYSFS_Io *io, void *buf, PHYSFS_uint64 len)
 | 
			
		||||
{
 | 
			
		||||
	return SDL_RWread(getSDLRWops(io), buf, 1, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int SDLRWIoSeek(struct PHYSFS_Io *io, PHYSFS_uint64 offset)
 | 
			
		||||
{
 | 
			
		||||
	return (SDL_RWseek(getSDLRWops(io), offset, RW_SEEK_SET) != -1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PHYSFS_sint64 SDLRWIoTell(struct PHYSFS_Io *io)
 | 
			
		||||
{
 | 
			
		||||
	return SDL_RWseek(getSDLRWops(io), 0, RW_SEEK_CUR);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PHYSFS_sint64 SDLRWIoLength(struct PHYSFS_Io *io)
 | 
			
		||||
{
 | 
			
		||||
	return SDL_RWsize(getSDLRWops(io));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct PHYSFS_Io *SDLRWIoDuplicate(struct PHYSFS_Io *io)
 | 
			
		||||
{
 | 
			
		||||
	SDLRWIoContext *ctx = static_cast<SDLRWIoContext*>(io->opaque);
 | 
			
		||||
	int64_t offset = io->tell(io);
 | 
			
		||||
	PHYSFS_Io *dup = createSDLRWIo(ctx->filename.c_str());
 | 
			
		||||
 | 
			
		||||
	if (dup)
 | 
			
		||||
		SDLRWIoSeek(dup, offset);
 | 
			
		||||
 | 
			
		||||
	return dup;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void SDLRWIoDestroy(struct PHYSFS_Io *io)
 | 
			
		||||
{
 | 
			
		||||
	delete static_cast<SDLRWIoContext*>(io->opaque);
 | 
			
		||||
	delete io;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PHYSFS_Io SDLRWIoTemplate =
 | 
			
		||||
{
 | 
			
		||||
	0, 0, /* version, opaque */
 | 
			
		||||
	SDLRWIoRead,
 | 
			
		||||
	0, /* write */
 | 
			
		||||
	SDLRWIoSeek,
 | 
			
		||||
	SDLRWIoTell,
 | 
			
		||||
	SDLRWIoLength,
 | 
			
		||||
	SDLRWIoDuplicate,
 | 
			
		||||
	0, /* flush */
 | 
			
		||||
	SDLRWIoDestroy
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static PHYSFS_Io *createSDLRWIo(const char *filename)
 | 
			
		||||
{
 | 
			
		||||
	SDLRWIoContext *ctx;
 | 
			
		||||
 | 
			
		||||
	try
 | 
			
		||||
	{
 | 
			
		||||
		ctx = new SDLRWIoContext(filename);
 | 
			
		||||
	}
 | 
			
		||||
	catch (const Exception &e)
 | 
			
		||||
	{
 | 
			
		||||
		Debug() << "Failed mounting" << filename;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	PHYSFS_Io *io = new PHYSFS_Io;
 | 
			
		||||
	*io = SDLRWIoTemplate;
 | 
			
		||||
	io->opaque = ctx;
 | 
			
		||||
 | 
			
		||||
	return io;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline PHYSFS_File *sdlPHYS(SDL_RWops *ops)
 | 
			
		||||
{
 | 
			
		||||
	return static_cast<PHYSFS_File*>(ops->hidden.unknown.data1);
 | 
			
		||||
| 
						 | 
				
			
			@ -131,18 +230,36 @@ static int SDL_RWopsCloseFree(SDL_RWops *ops)
 | 
			
		|||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Copies the first srcN characters from src into dst,
 | 
			
		||||
 * or the full string if srcN == -1. Never writes more
 | 
			
		||||
 * than dstMax, and guarantees dst to be null terminated.
 | 
			
		||||
 * Returns copied bytes (minus terminating null) */
 | 
			
		||||
static size_t
 | 
			
		||||
strcpySafe(char *dst, const char *src,
 | 
			
		||||
           size_t dstMax, int srcN)
 | 
			
		||||
{
 | 
			
		||||
	if (srcN < 0)
 | 
			
		||||
		srcN = strlen(src);
 | 
			
		||||
 | 
			
		||||
	size_t cpyMax = std::min<size_t>(dstMax-1, srcN);
 | 
			
		||||
 | 
			
		||||
	memcpy(dst, src, cpyMax);
 | 
			
		||||
	dst[cpyMax] = '\0';
 | 
			
		||||
 | 
			
		||||
	return cpyMax;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Uint32 SDL_RWOPS_PHYSFS = SDL_RWOPS_UNKNOWN+10;
 | 
			
		||||
 | 
			
		||||
struct FileSystemPrivate
 | 
			
		||||
{
 | 
			
		||||
	/* Maps: lower case filename, To: actual (mixed case) filename.
 | 
			
		||||
	/* Maps: lower case filepath without extension,
 | 
			
		||||
	 * To:   mixed case full filepath
 | 
			
		||||
	 * This is for compatibility with games that take Windows'
 | 
			
		||||
	 * case insensitivity for granted */
 | 
			
		||||
	BoostHash<std::string, std::string> pathCache;
 | 
			
		||||
	bool havePathCache;
 | 
			
		||||
 | 
			
		||||
	std::vector<std::string> extensions[FileSystem::Undefined+1];
 | 
			
		||||
 | 
			
		||||
	/* Attempt to locate an extension string in a filename.
 | 
			
		||||
	 * Either a pointer into the input string pointing at the
 | 
			
		||||
	 * extension, or null is returned */
 | 
			
		||||
| 
						 | 
				
			
			@ -162,120 +279,129 @@ struct FileSystemPrivate
 | 
			
		|||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Complete filename via regular physfs lookup */
 | 
			
		||||
	bool completeFilenameReg(const char *filename,
 | 
			
		||||
	                         FileSystem::FileType type,
 | 
			
		||||
	struct CompleteFilenameData
 | 
			
		||||
	{
 | 
			
		||||
		bool found;
 | 
			
		||||
		/* Contains the incomplete filename we're looking for;
 | 
			
		||||
		 * when found, we write the complete filename into this
 | 
			
		||||
		 * same buffer */
 | 
			
		||||
		char *outBuf;
 | 
			
		||||
		/* Length of incomplete file name */
 | 
			
		||||
		size_t filenameLen;
 | 
			
		||||
		/* Maximum we can write into outBuf */
 | 
			
		||||
		size_t outBufN;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	static void completeFilenameRegCB(void *data, const char *,
 | 
			
		||||
	                                  const char *fname)
 | 
			
		||||
	{
 | 
			
		||||
		CompleteFilenameData &d = *static_cast<CompleteFilenameData*>(data);
 | 
			
		||||
 | 
			
		||||
		if (d.found)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		if (strncmp(d.outBuf, fname, d.filenameLen) != 0)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		/* If fname matches up to a following '.' (meaning the rest is part
 | 
			
		||||
		 * of the extension), or up to a following '\0' (full match), we've
 | 
			
		||||
		 * found our file */
 | 
			
		||||
		switch (fname[d.filenameLen])
 | 
			
		||||
		{
 | 
			
		||||
		case '.' :
 | 
			
		||||
			/* Overwrite the incomplete file name we looked for with
 | 
			
		||||
			 * the full version containing any extensions */
 | 
			
		||||
			strcpySafe(d.outBuf, fname, d.outBufN, -1);
 | 
			
		||||
		case '\0' :
 | 
			
		||||
			d.found = true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool completeFilenameReg(const char *filepath,
 | 
			
		||||
	                         char *outBuffer,
 | 
			
		||||
	                         size_t outN,
 | 
			
		||||
	                         const char **foundExt)
 | 
			
		||||
	                         size_t outN)
 | 
			
		||||
	{
 | 
			
		||||
		/* Try supplementing extensions to find an existing path */
 | 
			
		||||
		const std::vector<std::string> &extList = extensions[type];
 | 
			
		||||
		strcpySafe(outBuffer, filepath, outN, -1);
 | 
			
		||||
 | 
			
		||||
		for (size_t i = 0; i < extList.size(); ++i)
 | 
			
		||||
		size_t len = strlen(outBuffer);
 | 
			
		||||
		char *delim;
 | 
			
		||||
 | 
			
		||||
		/* Find the deliminator separating directory and file name */
 | 
			
		||||
		for (delim = outBuffer + len; delim > outBuffer; --delim)
 | 
			
		||||
			if (*delim == '/')
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
		bool root = (delim == outBuffer);
 | 
			
		||||
		CompleteFilenameData d;
 | 
			
		||||
 | 
			
		||||
		if (!root)
 | 
			
		||||
		{
 | 
			
		||||
			const char *ext = extList[i].c_str();
 | 
			
		||||
			/* If we have such a deliminator, we set it to '\0' so we
 | 
			
		||||
			 * can pass the first half to PhysFS as the directory name,
 | 
			
		||||
			 * and compare all filenames against the second half */
 | 
			
		||||
			d.outBuf = delim+1;
 | 
			
		||||
			d.filenameLen = len - (delim - outBuffer + 1);
 | 
			
		||||
 | 
			
		||||
			snprintf(outBuffer, outN, "%s.%s", filename, ext);
 | 
			
		||||
 | 
			
		||||
			if (PHYSFS_exists(outBuffer))
 | 
			
		||||
			{
 | 
			
		||||
				if (foundExt)
 | 
			
		||||
					*foundExt = ext;
 | 
			
		||||
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
			*delim = '\0';
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			/* Otherwise the file is in the root directory */
 | 
			
		||||
			d.outBuf = outBuffer;
 | 
			
		||||
			d.filenameLen = len - (delim - outBuffer);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Doing the check without supplemented extension
 | 
			
		||||
		 * fits the usage pattern of RMXP games */
 | 
			
		||||
		if (PHYSFS_exists(filename))
 | 
			
		||||
		{
 | 
			
		||||
			strncpy(outBuffer, filename, outN);
 | 
			
		||||
		d.found = false;
 | 
			
		||||
		d.outBufN = outN - (d.outBuf - outBuffer);
 | 
			
		||||
 | 
			
		||||
			if (foundExt)
 | 
			
		||||
				*foundExt = findExt(filename);
 | 
			
		||||
		PHYSFS_enumerateFilesCallback(root ? "" : outBuffer, completeFilenameRegCB, &d);
 | 
			
		||||
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
		if (!d.found)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		return false;
 | 
			
		||||
		/* Now we put the deliminator back in to form the completed
 | 
			
		||||
		 * file path (if required) */
 | 
			
		||||
		if (delim != outBuffer)
 | 
			
		||||
			*delim = '/';
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Complete filename via path cache */
 | 
			
		||||
	bool completeFilenamePC(const char *filename,
 | 
			
		||||
	                        FileSystem::FileType type,
 | 
			
		||||
	bool completeFilenamePC(const char *filepath,
 | 
			
		||||
	                        char *outBuffer,
 | 
			
		||||
	                        size_t outN,
 | 
			
		||||
	                        const char **foundExt)
 | 
			
		||||
	                        size_t outN)
 | 
			
		||||
	{
 | 
			
		||||
		size_t i;
 | 
			
		||||
		char lowCase[512];
 | 
			
		||||
		std::string lowCase(filepath);
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < sizeof(lowCase)-1 && filename[i]; ++i)
 | 
			
		||||
			lowCase[i] = tolower(filename[i]);
 | 
			
		||||
		for (size_t i = 0; i < lowCase.size(); ++i)
 | 
			
		||||
			lowCase[i] = tolower(lowCase[i]);
 | 
			
		||||
 | 
			
		||||
		lowCase[i] = '\0';
 | 
			
		||||
		if (!pathCache.contains(lowCase))
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		std::string key;
 | 
			
		||||
		const std::string &fullPath = pathCache[lowCase];
 | 
			
		||||
		strcpySafe(outBuffer, fullPath.c_str(), outN, fullPath.size());
 | 
			
		||||
 | 
			
		||||
		const std::vector<std::string> &extList = extensions[type];
 | 
			
		||||
 | 
			
		||||
		for (size_t i = 0; i < extList.size(); ++i)
 | 
			
		||||
		{
 | 
			
		||||
			const char *ext = extList[i].c_str();
 | 
			
		||||
 | 
			
		||||
			snprintf(outBuffer, outN, "%s.%s", lowCase, ext);
 | 
			
		||||
			key = outBuffer;
 | 
			
		||||
 | 
			
		||||
			if (pathCache.contains(key))
 | 
			
		||||
			{
 | 
			
		||||
				strncpy(outBuffer, pathCache[key].c_str(), outN);
 | 
			
		||||
 | 
			
		||||
				if (foundExt)
 | 
			
		||||
					*foundExt = ext;
 | 
			
		||||
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		key = lowCase;
 | 
			
		||||
 | 
			
		||||
		if (pathCache.contains(key))
 | 
			
		||||
		{
 | 
			
		||||
			strncpy(outBuffer, pathCache[key].c_str(), outN);
 | 
			
		||||
 | 
			
		||||
			if (foundExt)
 | 
			
		||||
				*foundExt = findExt(filename);
 | 
			
		||||
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return false;
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Try to complete 'filename' with file extensions
 | 
			
		||||
	 * based on 'type'. If no combination could be found,
 | 
			
		||||
	 * returns false, and 'foundExt' is untouched */
 | 
			
		||||
	bool completeFileName(const char *filename,
 | 
			
		||||
	                      FileSystem::FileType type,
 | 
			
		||||
	bool completeFilename(const char *filepath,
 | 
			
		||||
	                      char *outBuffer,
 | 
			
		||||
	                      size_t outN,
 | 
			
		||||
	                      const char **foundExt)
 | 
			
		||||
	                      size_t outN)
 | 
			
		||||
	{
 | 
			
		||||
		if (havePathCache)
 | 
			
		||||
			return completeFilenamePC(filename, type, outBuffer, outN, foundExt);
 | 
			
		||||
			return completeFilenamePC(filepath, outBuffer, outN);
 | 
			
		||||
		else
 | 
			
		||||
			return completeFilenameReg(filename, type, outBuffer, outN, foundExt);
 | 
			
		||||
			return completeFilenameReg(filepath, outBuffer, outN);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	PHYSFS_File *openReadHandle(const char *filename,
 | 
			
		||||
	                            FileSystem::FileType type,
 | 
			
		||||
	                            const char **foundExt)
 | 
			
		||||
	                            char *extBuf,
 | 
			
		||||
	                            size_t extBufN)
 | 
			
		||||
	{
 | 
			
		||||
		char found[512];
 | 
			
		||||
 | 
			
		||||
		if (!completeFileName(filename, type, found, sizeof(found), foundExt))
 | 
			
		||||
		if (!completeFilename(filename, found, sizeof(found)))
 | 
			
		||||
			throw Exception(Exception::NoFileError, "%s", filename);
 | 
			
		||||
 | 
			
		||||
		PHYSFS_File *handle = PHYSFS_openRead(found);
 | 
			
		||||
| 
						 | 
				
			
			@ -283,6 +409,21 @@ struct FileSystemPrivate
 | 
			
		|||
		if (!handle)
 | 
			
		||||
			throw Exception(Exception::PHYSFSError, "PhysFS: %s", PHYSFS_getLastError());
 | 
			
		||||
 | 
			
		||||
		if (!extBuf)
 | 
			
		||||
			return handle;
 | 
			
		||||
 | 
			
		||||
		for (char *q = found+strlen(found); q > found; --q)
 | 
			
		||||
		{
 | 
			
		||||
			if (*q == '/')
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			if (*q != '.')
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			strcpySafe(extBuf, q+1, extBufN, -1);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return handle;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -309,45 +450,8 @@ FileSystem::FileSystem(const char *argv0,
 | 
			
		|||
                       bool allowSymlinks)
 | 
			
		||||
{
 | 
			
		||||
	p = new FileSystemPrivate;
 | 
			
		||||
 | 
			
		||||
	p->havePathCache = false;
 | 
			
		||||
 | 
			
		||||
	/* Image extensions */
 | 
			
		||||
	p->extensions[Image].push_back("jpg");
 | 
			
		||||
	p->extensions[Image].push_back("png");
 | 
			
		||||
 | 
			
		||||
	/* Audio extensions */
 | 
			
		||||
	const Sound_DecoderInfo **di;
 | 
			
		||||
	for (di = Sound_AvailableDecoders(); *di; ++di)
 | 
			
		||||
	{
 | 
			
		||||
		const char **ext;
 | 
			
		||||
		for (ext = (*di)->extensions; *ext; ++ext)
 | 
			
		||||
		{
 | 
			
		||||
			/* All reported extensions are uppercase,
 | 
			
		||||
			 * so we need to hammer them down first */
 | 
			
		||||
			char buf[16];
 | 
			
		||||
			for (size_t i = 0; i < sizeof(buf); ++i)
 | 
			
		||||
			{
 | 
			
		||||
				buf[i] = tolower((*ext)[i]);
 | 
			
		||||
 | 
			
		||||
				if (!buf[i])
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			p->extensions[Audio].push_back(buf);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (rgssVer >= 2 && !contains(p->extensions[Audio], std::string("ogg")))
 | 
			
		||||
		p->extensions[Audio].push_back("ogg");
 | 
			
		||||
 | 
			
		||||
	p->extensions[Audio].push_back("mid");
 | 
			
		||||
	p->extensions[Audio].push_back("midi");
 | 
			
		||||
 | 
			
		||||
	/* Font extensions */
 | 
			
		||||
	p->extensions[Font].push_back("ttf");
 | 
			
		||||
	p->extensions[Font].push_back("otf");
 | 
			
		||||
 | 
			
		||||
	PHYSFS_init(argv0);
 | 
			
		||||
 | 
			
		||||
	PHYSFS_registerArchiver(&RGSS1_Archiver);
 | 
			
		||||
| 
						 | 
				
			
			@ -368,7 +472,16 @@ FileSystem::~FileSystem()
 | 
			
		|||
 | 
			
		||||
void FileSystem::addPath(const char *path)
 | 
			
		||||
{
 | 
			
		||||
	PHYSFS_mount(path, 0, 1);
 | 
			
		||||
	/* Try the normal mount first */
 | 
			
		||||
	if (!PHYSFS_mount(path, 0, 1))
 | 
			
		||||
	{
 | 
			
		||||
		/* If it didn't work, try mounting via a wrapped
 | 
			
		||||
		 * SDL_RWops */
 | 
			
		||||
		PHYSFS_Io *io = createSDLRWIo(path);
 | 
			
		||||
 | 
			
		||||
		if (io)
 | 
			
		||||
			PHYSFS_mountIo(io, path, 0, 1);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __APPLE__
 | 
			
		||||
| 
						 | 
				
			
			@ -436,12 +549,22 @@ static void cacheEnumCB(void *d, const char *origdir,
 | 
			
		|||
 | 
			
		||||
	std::string mixedCase(ptr);
 | 
			
		||||
 | 
			
		||||
	for (char *p = bufNfc; *p; ++p)
 | 
			
		||||
		*p = tolower(*p);
 | 
			
		||||
	for (char *q = bufNfc; *q; ++q)
 | 
			
		||||
		*q = tolower(*q);
 | 
			
		||||
 | 
			
		||||
	std::string lowerCase(ptr);
 | 
			
		||||
	p->pathCache.insert(std::string(ptr), mixedCase);
 | 
			
		||||
 | 
			
		||||
	p->pathCache.insert(lowerCase, mixedCase);
 | 
			
		||||
	for (char *q = ptr+strlen(ptr); q > ptr; --q)
 | 
			
		||||
	{
 | 
			
		||||
		if (*q == '/')
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		if (*q != '.')
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		*q = '\0';
 | 
			
		||||
		p->pathCache.insert(std::string(ptr), mixedCase);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	PHYSFS_enumerateFilesCallback(mixedCase.c_str(), cacheEnumCB, d);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -450,7 +573,7 @@ void FileSystem::createPathCache()
 | 
			
		|||
{
 | 
			
		||||
#ifdef __APPLE__
 | 
			
		||||
	CacheEnumCBData data(p);
 | 
			
		||||
	PHYSFS_enumerateFilesCallback("", cacheEnumCB, &data);
 | 
			
		||||
	PHYSFS_enumerateFilesCallback("", cacheEnumCB2, &data);
 | 
			
		||||
#else
 | 
			
		||||
	PHYSFS_enumerateFilesCallback("", cacheEnumCB, p);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -458,12 +581,6 @@ void FileSystem::createPathCache()
 | 
			
		|||
	p->havePathCache = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void strToLower(std::string &str)
 | 
			
		||||
{
 | 
			
		||||
	for (size_t i = 0; i < str.size(); ++i)
 | 
			
		||||
		str[i] = tolower(str[i]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct FontSetsCBData
 | 
			
		||||
{
 | 
			
		||||
	FileSystemPrivate *p;
 | 
			
		||||
| 
						 | 
				
			
			@ -482,16 +599,21 @@ static void fontSetEnumCB(void *data, const char *,
 | 
			
		|||
	if (!ext)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	std::string lower(ext);
 | 
			
		||||
	strToLower(lower);
 | 
			
		||||
	char lowExt[8];
 | 
			
		||||
	size_t i;
 | 
			
		||||
 | 
			
		||||
	if (!contains(p->extensions[FileSystem::Font], lower))
 | 
			
		||||
	for (i = 0; i < sizeof(lowExt)-1 && ext[i]; ++i)
 | 
			
		||||
		lowExt[i] = tolower(ext[i]);
 | 
			
		||||
	lowExt[i] = '\0';
 | 
			
		||||
 | 
			
		||||
	if (strcmp(lowExt, "ttf") && strcmp(lowExt, "otf"))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	std::string filename("Fonts/");
 | 
			
		||||
	filename += fname;
 | 
			
		||||
	char filename[512];
 | 
			
		||||
	snprintf(filename, sizeof(filename), "Fonts/%s", fname);
 | 
			
		||||
	filename[sizeof(filename)-1] = '\0';
 | 
			
		||||
 | 
			
		||||
	PHYSFS_File *handle = PHYSFS_openRead(filename.c_str());
 | 
			
		||||
	PHYSFS_File *handle = PHYSFS_openRead(filename);
 | 
			
		||||
 | 
			
		||||
	if (!handle)
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -513,11 +635,11 @@ void FileSystem::initFontSets(SharedFontState &sfs)
 | 
			
		|||
 | 
			
		||||
void FileSystem::openRead(SDL_RWops &ops,
 | 
			
		||||
                          const char *filename,
 | 
			
		||||
                          FileType type,
 | 
			
		||||
                          bool freeOnClose,
 | 
			
		||||
                          const char **foundExt)
 | 
			
		||||
                          char *extBuf,
 | 
			
		||||
                          size_t extBufN)
 | 
			
		||||
{
 | 
			
		||||
	PHYSFS_File *handle = p->openReadHandle(filename, type, foundExt);
 | 
			
		||||
 	PHYSFS_File *handle = p->openReadHandle(filename, extBuf, extBufN);
 | 
			
		||||
 | 
			
		||||
	p->initReadOps(handle, ops, freeOnClose);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -532,9 +654,9 @@ void FileSystem::openReadRaw(SDL_RWops &ops,
 | 
			
		|||
	p->initReadOps(handle, ops, freeOnClose);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FileSystem::exists(const char *filename, FileType type)
 | 
			
		||||
bool FileSystem::exists(const char *filename)
 | 
			
		||||
{
 | 
			
		||||
	char found[512];
 | 
			
		||||
 | 
			
		||||
	return p->completeFileName(filename, type, found, sizeof(found), 0);
 | 
			
		||||
	return p->completeFilename(filename, found, sizeof(found));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,28 +43,18 @@ public:
 | 
			
		|||
	 * available font assets */
 | 
			
		||||
	void initFontSets(SharedFontState &sfs);
 | 
			
		||||
 | 
			
		||||
	/* For extension supplementing */
 | 
			
		||||
	enum FileType
 | 
			
		||||
	{
 | 
			
		||||
		Image = 0,
 | 
			
		||||
		Audio,
 | 
			
		||||
		Font,
 | 
			
		||||
		Undefined
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	void openRead(SDL_RWops &ops,
 | 
			
		||||
	              const char *filename,
 | 
			
		||||
	              FileType type = Undefined,
 | 
			
		||||
	              bool freeOnClose = false,
 | 
			
		||||
	              const char **foundExt = 0);
 | 
			
		||||
	              char *extBuf = 0,
 | 
			
		||||
	              size_t extBufN = 0);
 | 
			
		||||
 | 
			
		||||
	/* Circumvents extension supplementing */
 | 
			
		||||
	void openReadRaw(SDL_RWops &ops,
 | 
			
		||||
	                 const char *filename,
 | 
			
		||||
	                 bool freeOnClose = false);
 | 
			
		||||
 | 
			
		||||
	bool exists(const char *filename,
 | 
			
		||||
	            FileType type = Undefined);
 | 
			
		||||
	bool exists(const char *filename);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	FileSystemPrivate *p;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@
 | 
			
		|||
#include <fluidsynth.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __LINUX__
 | 
			
		||||
#if __LINUX__ || __ANDROID__
 | 
			
		||||
#define FLUID_LIB "libfluidsynth.so.1"
 | 
			
		||||
#elif __MACOSX__
 | 
			
		||||
#define FLUID_LIB "libfluidsynth.1.dylib"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										20
									
								
								src/font.h
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								src/font.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -86,16 +86,14 @@ public:
 | 
			
		|||
 | 
			
		||||
	const Font &operator=(const Font &o);
 | 
			
		||||
 | 
			
		||||
	const char *getName() const;
 | 
			
		||||
	void setName(const char *value);
 | 
			
		||||
 | 
			
		||||
	DECL_ATTR( Size,     int    )
 | 
			
		||||
	DECL_ATTR( Bold,     bool   )
 | 
			
		||||
	DECL_ATTR( Italic,   bool   )
 | 
			
		||||
	DECL_ATTR( Color,    Color& )
 | 
			
		||||
	DECL_ATTR( Shadow,   bool   )
 | 
			
		||||
	DECL_ATTR( Outline,  bool   )
 | 
			
		||||
	DECL_ATTR( OutColor, Color& )
 | 
			
		||||
	DECL_ATTR( Name,     const char * )
 | 
			
		||||
	DECL_ATTR( Size,     int          )
 | 
			
		||||
	DECL_ATTR( Bold,     bool         )
 | 
			
		||||
	DECL_ATTR( Italic,   bool         )
 | 
			
		||||
	DECL_ATTR( Color,    Color&       )
 | 
			
		||||
	DECL_ATTR( Shadow,   bool         )
 | 
			
		||||
	DECL_ATTR( Outline,  bool         )
 | 
			
		||||
	DECL_ATTR( OutColor, Color&       )
 | 
			
		||||
 | 
			
		||||
	DECL_ATTR_STATIC( DefaultName,     const char* )
 | 
			
		||||
	DECL_ATTR_STATIC( DefaultSize,     int         )
 | 
			
		||||
| 
						 | 
				
			
			@ -108,7 +106,7 @@ public:
 | 
			
		|||
 | 
			
		||||
	/* Assigns heap allocated objects to object properties;
 | 
			
		||||
	 * using this in pure C++ will cause memory leaks
 | 
			
		||||
	 * (ie. only to be used in GCed language bindings */
 | 
			
		||||
	 * (ie. only to be used in GCed language bindings) */
 | 
			
		||||
	void initDynAttribs();
 | 
			
		||||
	static void initDefaultDynAttribs();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
/*
 | 
			
		||||
** debuglogger.cpp
 | 
			
		||||
** gl-debug.cpp
 | 
			
		||||
**
 | 
			
		||||
** This file is part of mkxp.
 | 
			
		||||
**
 | 
			
		||||
| 
						 | 
				
			
			@ -19,25 +19,25 @@
 | 
			
		|||
** along with mkxp.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "debuglogger.h"
 | 
			
		||||
#include "gl-debug.h"
 | 
			
		||||
#include "debugwriter.h"
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
#include "gl-fun.h"
 | 
			
		||||
 | 
			
		||||
struct DebugLoggerPrivate
 | 
			
		||||
struct GLDebugLoggerPrivate
 | 
			
		||||
{
 | 
			
		||||
	std::ostream *stream;
 | 
			
		||||
 | 
			
		||||
	DebugLoggerPrivate(const char *logFilename)
 | 
			
		||||
	GLDebugLoggerPrivate(const char *logFilename)
 | 
			
		||||
	{
 | 
			
		||||
		(void) logFilename;
 | 
			
		||||
 | 
			
		||||
		stream = &std::clog;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	~DebugLoggerPrivate()
 | 
			
		||||
	~GLDebugLoggerPrivate()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -62,8 +62,8 @@ static void APIENTRY arbDebugFunc(GLenum source,
 | 
			
		|||
                                  const GLchar* message,
 | 
			
		||||
                                  const void* userParam)
 | 
			
		||||
{
 | 
			
		||||
	DebugLoggerPrivate *p =
 | 
			
		||||
		static_cast<DebugLoggerPrivate*>(const_cast<void*>(userParam));
 | 
			
		||||
	GLDebugLoggerPrivate *p =
 | 
			
		||||
		static_cast<GLDebugLoggerPrivate*>(const_cast<void*>(userParam));
 | 
			
		||||
 | 
			
		||||
	(void) source;
 | 
			
		||||
	(void) type;
 | 
			
		||||
| 
						 | 
				
			
			@ -75,9 +75,9 @@ static void APIENTRY arbDebugFunc(GLenum source,
 | 
			
		|||
	p->writeLine(message);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DebugLogger::DebugLogger(const char *filename)
 | 
			
		||||
GLDebugLogger::GLDebugLogger(const char *filename)
 | 
			
		||||
{
 | 
			
		||||
	p = new DebugLoggerPrivate(filename);
 | 
			
		||||
	p = new GLDebugLoggerPrivate(filename);
 | 
			
		||||
 | 
			
		||||
	if (gl.DebugMessageCallback)
 | 
			
		||||
		gl.DebugMessageCallback(arbDebugFunc, p);
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +85,7 @@ DebugLogger::DebugLogger(const char *filename)
 | 
			
		|||
		Debug() << "DebugLogger: no debug extensions found";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DebugLogger::~DebugLogger()
 | 
			
		||||
GLDebugLogger::~GLDebugLogger()
 | 
			
		||||
{
 | 
			
		||||
	delete p;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
/*
 | 
			
		||||
** debuglogger.h
 | 
			
		||||
** gl-debug.h
 | 
			
		||||
**
 | 
			
		||||
** This file is part of mkxp.
 | 
			
		||||
**
 | 
			
		||||
| 
						 | 
				
			
			@ -22,16 +22,30 @@
 | 
			
		|||
#ifndef DEBUGLOGGER_H
 | 
			
		||||
#define DEBUGLOGGER_H
 | 
			
		||||
 | 
			
		||||
struct DebugLoggerPrivate;
 | 
			
		||||
#include "gl-fun.h"
 | 
			
		||||
 | 
			
		||||
class DebugLogger
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
struct GLDebugLoggerPrivate;
 | 
			
		||||
 | 
			
		||||
class GLDebugLogger
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	DebugLogger(const char *filename = 0);
 | 
			
		||||
	~DebugLogger();
 | 
			
		||||
	GLDebugLogger(const char *filename = 0);
 | 
			
		||||
	~GLDebugLogger();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	DebugLoggerPrivate *p;
 | 
			
		||||
	GLDebugLoggerPrivate *p;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define GL_MARKER(format, ...) \
 | 
			
		||||
	if (gl.StringMarker) \
 | 
			
		||||
	{ \
 | 
			
		||||
		char buf[128]; \
 | 
			
		||||
		int len = snprintf(buf, sizeof(buf), format, ##__VA_ARGS__); \
 | 
			
		||||
		gl.StringMarker(std::min<size_t>(len, sizeof(buf)), buf); \
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // DEBUGLOGGER_H
 | 
			
		||||
| 
						 | 
				
			
			@ -29,12 +29,12 @@
 | 
			
		|||
 | 
			
		||||
GLFunctions gl;
 | 
			
		||||
 | 
			
		||||
typedef const GLubyte* (APIENTRYP PFNGLGETSTRINGIPROC) (GLenum, GLuint);
 | 
			
		||||
typedef const GLubyte* (APIENTRYP _PFNGLGETSTRINGIPROC) (GLenum, GLuint);
 | 
			
		||||
 | 
			
		||||
static void parseExtensionsCore(PFNGLGETINTEGERVPROC GetIntegerv, BoostSet<std::string> &out)
 | 
			
		||||
static void parseExtensionsCore(_PFNGLGETINTEGERVPROC GetIntegerv, BoostSet<std::string> &out)
 | 
			
		||||
{
 | 
			
		||||
	PFNGLGETSTRINGIPROC GetStringi =
 | 
			
		||||
		(PFNGLGETSTRINGIPROC) SDL_GL_GetProcAddress("glGetStringi");
 | 
			
		||||
	_PFNGLGETSTRINGIPROC GetStringi =
 | 
			
		||||
		(_PFNGLGETSTRINGIPROC) SDL_GL_GetProcAddress("glGetStringi");
 | 
			
		||||
 | 
			
		||||
	GLint extCount = 0;
 | 
			
		||||
	GetIntegerv(GL_NUM_EXTENSIONS, &extCount);
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ static void parseExtensionsCore(PFNGLGETINTEGERVPROC GetIntegerv, BoostSet<std::
 | 
			
		|||
		out.insert((const char*) GetStringi(GL_EXTENSIONS, i));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void parseExtensionsCompat(PFNGLGETSTRINGPROC GetString, BoostSet<std::string> &out)
 | 
			
		||||
static void parseExtensionsCompat(_PFNGLGETSTRINGPROC GetString, BoostSet<std::string> &out)
 | 
			
		||||
{
 | 
			
		||||
	const char *ext = (const char*) GetString(GL_EXTENSIONS);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -82,8 +82,8 @@ void initGLFunctions()
 | 
			
		|||
	/* Determine GL version */
 | 
			
		||||
	const char *ver = (const char*) gl.GetString(GL_VERSION);
 | 
			
		||||
 | 
			
		||||
	const char *glesPrefix = "OpenGL ES ";
 | 
			
		||||
	size_t glesPrefixN = strlen(glesPrefix);
 | 
			
		||||
	const char glesPrefix[] = "OpenGL ES ";
 | 
			
		||||
	const size_t glesPrefixN = sizeof(glesPrefix)-1;
 | 
			
		||||
 | 
			
		||||
	bool gles = false;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -101,6 +101,11 @@ void initGLFunctions()
 | 
			
		|||
	if (glMajor < 2)
 | 
			
		||||
		throw EXC("At least OpenGL (ES) 2.0 is required");
 | 
			
		||||
 | 
			
		||||
	if (gles)
 | 
			
		||||
	{
 | 
			
		||||
		GL_ES_FUN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	BoostSet<std::string> ext;
 | 
			
		||||
 | 
			
		||||
	if (glMajor >= 3)
 | 
			
		||||
| 
						 | 
				
			
			@ -172,6 +177,13 @@ void initGLFunctions()
 | 
			
		|||
		GL_DEBUG_KHR_FUN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (HAVE_EXT(GREMEDY_string_marker))
 | 
			
		||||
	{
 | 
			
		||||
#undef EXT_SUFFIX
 | 
			
		||||
#define EXT_SUFFIX "GREMEDY"
 | 
			
		||||
		GL_GREMEMDY_FUN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Misc caps */
 | 
			
		||||
	if (!gles || glMajor >= 3 || HAVE_EXT(EXT_unpack_subimage))
 | 
			
		||||
		gl.unpack_subimage = true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										249
									
								
								src/gl-fun.h
									
										
									
									
									
								
							
							
						
						
									
										249
									
								
								src/gl-fun.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -30,179 +30,194 @@
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
/* Etc */
 | 
			
		||||
typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
 | 
			
		||||
typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
 | 
			
		||||
typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
 | 
			
		||||
typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params);
 | 
			
		||||
typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
 | 
			
		||||
typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
 | 
			
		||||
typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
 | 
			
		||||
typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
 | 
			
		||||
typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
 | 
			
		||||
typedef GLenum (APIENTRYP _PFNGLGETERRORPROC) (void);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLCLEARCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLCLEARPROC) (GLbitfield mask);
 | 
			
		||||
typedef const GLubyte * (APIENTRYP _PFNGLGETSTRINGPROC) (GLenum name);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLENABLEPROC) (GLenum cap);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLDISABLEPROC) (GLenum cap);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLBLENDEQUATIONPROC) (GLenum mode);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
 | 
			
		||||
 | 
			
		||||
/* Texture */
 | 
			
		||||
typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
 | 
			
		||||
typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
 | 
			
		||||
typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
 | 
			
		||||
typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
 | 
			
		||||
typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLACTIVETEXTUREPROC) (GLenum texture);
 | 
			
		||||
 | 
			
		||||
/* Debug callback */
 | 
			
		||||
/* Debugging */
 | 
			
		||||
typedef void (APIENTRY * _GLDEBUGPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void *userParam);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLDEBUGMESSAGECALLBACKPROC) (_GLDEBUGPROC callback, const void *userParam);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLSTRINGMARKERPROC) (GLsizei len, const GLvoid *string);
 | 
			
		||||
 | 
			
		||||
/* Buffer object */
 | 
			
		||||
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
 | 
			
		||||
 | 
			
		||||
/* Shader */
 | 
			
		||||
typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
 | 
			
		||||
typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* const* strings, const GLint* lengths);
 | 
			
		||||
typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
 | 
			
		||||
typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
 | 
			
		||||
typedef GLuint (APIENTRYP _PFNGLCREATESHADERPROC) (GLenum type);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLDELETESHADERPROC) (GLuint shader);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* const* strings, const GLint* lengths);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLCOMPILESHADERPROC) (GLuint shader);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
 | 
			
		||||
 | 
			
		||||
/* Program */
 | 
			
		||||
typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
 | 
			
		||||
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
 | 
			
		||||
typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
 | 
			
		||||
typedef GLuint (APIENTRYP _PFNGLCREATEPROGRAMPROC) (void);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLDELETEPROGRAMPROC) (GLuint program);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLUSEPROGRAMPROC) (GLuint program);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLLINKPROGRAMPROC) (GLuint program);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
 | 
			
		||||
 | 
			
		||||
/* Uniform */
 | 
			
		||||
typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name);
 | 
			
		||||
typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
 | 
			
		||||
typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
 | 
			
		||||
typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
 | 
			
		||||
typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
 | 
			
		||||
typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
 | 
			
		||||
typedef GLint (APIENTRYP _PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
 | 
			
		||||
 | 
			
		||||
/* Vertex attribute */
 | 
			
		||||
typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name);
 | 
			
		||||
typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint);
 | 
			
		||||
typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);
 | 
			
		||||
 | 
			
		||||
/* Framebuffer object */
 | 
			
		||||
typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
 | 
			
		||||
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
 | 
			
		||||
 | 
			
		||||
/* Vertex array object */
 | 
			
		||||
typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays);
 | 
			
		||||
typedef void (APIENTRYP _PFNGLBINDVERTEXARRAYPROC) (GLuint array);
 | 
			
		||||
 | 
			
		||||
/* GLES only */
 | 
			
		||||
typedef void (APIENTRYP _PFNGLRELEASESHADERCOMPILERPROC) (void);
 | 
			
		||||
 | 
			
		||||
#ifdef GLES2_HEADER
 | 
			
		||||
#define GL_NUM_EXTENSIONS 0x821D
 | 
			
		||||
#define GL_READ_FRAMEBUFFER 0x8CA8
 | 
			
		||||
#define GL_DRAW_FRAMEBUFFER 0x8CA9
 | 
			
		||||
#define GL_UNPACK_ROW_LENGTH 0x0CF2
 | 
			
		||||
#define GL_UNPACK_SKIP_PIXELS 0x0CF4
 | 
			
		||||
#define GL_UNPACK_SKIP_ROWS 0x0CF3
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define GL_20_FUN \
 | 
			
		||||
	/* Etc */ \
 | 
			
		||||
	GL_FUN(GetError, PFNGLGETERRORPROC) \
 | 
			
		||||
	GL_FUN(ClearColor, PFNGLCLEARCOLORPROC) \
 | 
			
		||||
	GL_FUN(Clear, PFNGLCLEARPROC) \
 | 
			
		||||
	GL_FUN(GetString, PFNGLGETSTRINGPROC) \
 | 
			
		||||
	GL_FUN(GetIntegerv, PFNGLGETINTEGERVPROC) \
 | 
			
		||||
	GL_FUN(PixelStorei, PFNGLPIXELSTOREIPROC) \
 | 
			
		||||
	GL_FUN(ReadPixels, PFNGLREADPIXELSPROC) \
 | 
			
		||||
	GL_FUN(Enable, PFNGLENABLEPROC) \
 | 
			
		||||
	GL_FUN(Disable, PFNGLDISABLEPROC) \
 | 
			
		||||
	GL_FUN(Scissor, PFNGLSCISSORPROC) \
 | 
			
		||||
	GL_FUN(Viewport, PFNGLVIEWPORTPROC) \
 | 
			
		||||
	GL_FUN(BlendFunc, PFNGLBLENDFUNCPROC) \
 | 
			
		||||
	GL_FUN(BlendFuncSeparate, PFNGLBLENDFUNCSEPARATEPROC) \
 | 
			
		||||
	GL_FUN(BlendEquation, PFNGLBLENDEQUATIONPROC) \
 | 
			
		||||
	GL_FUN(DrawElements, PFNGLDRAWELEMENTSPROC) \
 | 
			
		||||
	GL_FUN(GetError, _PFNGLGETERRORPROC) \
 | 
			
		||||
	GL_FUN(ClearColor, _PFNGLCLEARCOLORPROC) \
 | 
			
		||||
	GL_FUN(Clear, _PFNGLCLEARPROC) \
 | 
			
		||||
	GL_FUN(GetString, _PFNGLGETSTRINGPROC) \
 | 
			
		||||
	GL_FUN(GetIntegerv, _PFNGLGETINTEGERVPROC) \
 | 
			
		||||
	GL_FUN(PixelStorei, _PFNGLPIXELSTOREIPROC) \
 | 
			
		||||
	GL_FUN(ReadPixels, _PFNGLREADPIXELSPROC) \
 | 
			
		||||
	GL_FUN(Enable, _PFNGLENABLEPROC) \
 | 
			
		||||
	GL_FUN(Disable, _PFNGLDISABLEPROC) \
 | 
			
		||||
	GL_FUN(Scissor, _PFNGLSCISSORPROC) \
 | 
			
		||||
	GL_FUN(Viewport, _PFNGLVIEWPORTPROC) \
 | 
			
		||||
	GL_FUN(BlendFunc, _PFNGLBLENDFUNCPROC) \
 | 
			
		||||
	GL_FUN(BlendFuncSeparate, _PFNGLBLENDFUNCSEPARATEPROC) \
 | 
			
		||||
	GL_FUN(BlendEquation, _PFNGLBLENDEQUATIONPROC) \
 | 
			
		||||
	GL_FUN(DrawElements, _PFNGLDRAWELEMENTSPROC) \
 | 
			
		||||
	/* Texture */ \
 | 
			
		||||
	GL_FUN(GenTextures, PFNGLGENTEXTURESPROC) \
 | 
			
		||||
	GL_FUN(DeleteTextures, PFNGLDELETETEXTURESPROC) \
 | 
			
		||||
	GL_FUN(BindTexture, PFNGLBINDTEXTUREPROC) \
 | 
			
		||||
	GL_FUN(TexImage2D, PFNGLTEXIMAGE2DPROC) \
 | 
			
		||||
	GL_FUN(TexSubImage2D, PFNGLTEXSUBIMAGE2DPROC) \
 | 
			
		||||
	GL_FUN(TexParameteri, PFNGLTEXPARAMETERIPROC) \
 | 
			
		||||
	GL_FUN(ActiveTexture, PFNGLACTIVETEXTUREPROC) \
 | 
			
		||||
	GL_FUN(GenTextures, _PFNGLGENTEXTURESPROC) \
 | 
			
		||||
	GL_FUN(DeleteTextures, _PFNGLDELETETEXTURESPROC) \
 | 
			
		||||
	GL_FUN(BindTexture, _PFNGLBINDTEXTUREPROC) \
 | 
			
		||||
	GL_FUN(TexImage2D, _PFNGLTEXIMAGE2DPROC) \
 | 
			
		||||
	GL_FUN(TexSubImage2D, _PFNGLTEXSUBIMAGE2DPROC) \
 | 
			
		||||
	GL_FUN(TexParameteri, _PFNGLTEXPARAMETERIPROC) \
 | 
			
		||||
	GL_FUN(ActiveTexture, _PFNGLACTIVETEXTUREPROC) \
 | 
			
		||||
	/* Buffer object */ \
 | 
			
		||||
	GL_FUN(GenBuffers, PFNGLGENBUFFERSPROC) \
 | 
			
		||||
	GL_FUN(DeleteBuffers, PFNGLDELETEBUFFERSPROC) \
 | 
			
		||||
	GL_FUN(BindBuffer, PFNGLBINDBUFFERPROC) \
 | 
			
		||||
	GL_FUN(BufferData, PFNGLBUFFERDATAPROC) \
 | 
			
		||||
	GL_FUN(BufferSubData, PFNGLBUFFERSUBDATAPROC) \
 | 
			
		||||
	GL_FUN(GenBuffers, _PFNGLGENBUFFERSPROC) \
 | 
			
		||||
	GL_FUN(DeleteBuffers, _PFNGLDELETEBUFFERSPROC) \
 | 
			
		||||
	GL_FUN(BindBuffer, _PFNGLBINDBUFFERPROC) \
 | 
			
		||||
	GL_FUN(BufferData, _PFNGLBUFFERDATAPROC) \
 | 
			
		||||
	GL_FUN(BufferSubData, _PFNGLBUFFERSUBDATAPROC) \
 | 
			
		||||
	/* Shader */ \
 | 
			
		||||
	GL_FUN(CreateShader, PFNGLCREATESHADERPROC) \
 | 
			
		||||
	GL_FUN(DeleteShader, PFNGLDELETESHADERPROC) \
 | 
			
		||||
	GL_FUN(ShaderSource, PFNGLSHADERSOURCEPROC) \
 | 
			
		||||
	GL_FUN(CompileShader, PFNGLCOMPILESHADERPROC) \
 | 
			
		||||
	GL_FUN(AttachShader, PFNGLATTACHSHADERPROC) \
 | 
			
		||||
	GL_FUN(GetShaderiv, PFNGLGETSHADERIVPROC) \
 | 
			
		||||
	GL_FUN(GetShaderInfoLog, PFNGLGETSHADERINFOLOGPROC) \
 | 
			
		||||
	GL_FUN(CreateShader, _PFNGLCREATESHADERPROC) \
 | 
			
		||||
	GL_FUN(DeleteShader, _PFNGLDELETESHADERPROC) \
 | 
			
		||||
	GL_FUN(ShaderSource, _PFNGLSHADERSOURCEPROC) \
 | 
			
		||||
	GL_FUN(CompileShader, _PFNGLCOMPILESHADERPROC) \
 | 
			
		||||
	GL_FUN(AttachShader, _PFNGLATTACHSHADERPROC) \
 | 
			
		||||
	GL_FUN(GetShaderiv, _PFNGLGETSHADERIVPROC) \
 | 
			
		||||
	GL_FUN(GetShaderInfoLog, _PFNGLGETSHADERINFOLOGPROC) \
 | 
			
		||||
	/* Program */ \
 | 
			
		||||
	GL_FUN(CreateProgram, PFNGLCREATEPROGRAMPROC) \
 | 
			
		||||
	GL_FUN(DeleteProgram, PFNGLDELETEPROGRAMPROC) \
 | 
			
		||||
	GL_FUN(UseProgram, PFNGLUSEPROGRAMPROC) \
 | 
			
		||||
	GL_FUN(LinkProgram, PFNGLLINKPROGRAMPROC) \
 | 
			
		||||
	GL_FUN(GetProgramiv, PFNGLGETPROGRAMIVPROC) \
 | 
			
		||||
	GL_FUN(GetProgramInfoLog, PFNGLGETPROGRAMINFOLOGPROC) \
 | 
			
		||||
	GL_FUN(CreateProgram, _PFNGLCREATEPROGRAMPROC) \
 | 
			
		||||
	GL_FUN(DeleteProgram, _PFNGLDELETEPROGRAMPROC) \
 | 
			
		||||
	GL_FUN(UseProgram, _PFNGLUSEPROGRAMPROC) \
 | 
			
		||||
	GL_FUN(LinkProgram, _PFNGLLINKPROGRAMPROC) \
 | 
			
		||||
	GL_FUN(GetProgramiv, _PFNGLGETPROGRAMIVPROC) \
 | 
			
		||||
	GL_FUN(GetProgramInfoLog, _PFNGLGETPROGRAMINFOLOGPROC) \
 | 
			
		||||
	/* Uniform */ \
 | 
			
		||||
	GL_FUN(GetUniformLocation, PFNGLGETUNIFORMLOCATIONPROC) \
 | 
			
		||||
	GL_FUN(Uniform1f, PFNGLUNIFORM1FPROC) \
 | 
			
		||||
	GL_FUN(Uniform2f, PFNGLUNIFORM2FPROC) \
 | 
			
		||||
	GL_FUN(Uniform4f, PFNGLUNIFORM4FPROC) \
 | 
			
		||||
	GL_FUN(Uniform1i, PFNGLUNIFORM1IPROC) \
 | 
			
		||||
	GL_FUN(UniformMatrix4fv, PFNGLUNIFORMMATRIX4FVPROC) \
 | 
			
		||||
	GL_FUN(GetUniformLocation, _PFNGLGETUNIFORMLOCATIONPROC) \
 | 
			
		||||
	GL_FUN(Uniform1f, _PFNGLUNIFORM1FPROC) \
 | 
			
		||||
	GL_FUN(Uniform2f, _PFNGLUNIFORM2FPROC) \
 | 
			
		||||
	GL_FUN(Uniform4f, _PFNGLUNIFORM4FPROC) \
 | 
			
		||||
	GL_FUN(Uniform1i, _PFNGLUNIFORM1IPROC) \
 | 
			
		||||
	GL_FUN(UniformMatrix4fv, _PFNGLUNIFORMMATRIX4FVPROC) \
 | 
			
		||||
	/* Vertex attribute */ \
 | 
			
		||||
	GL_FUN(BindAttribLocation, PFNGLBINDATTRIBLOCATIONPROC) \
 | 
			
		||||
	GL_FUN(EnableVertexAttribArray, PFNGLENABLEVERTEXATTRIBARRAYPROC) \
 | 
			
		||||
	GL_FUN(DisableVertexAttribArray, PFNGLDISABLEVERTEXATTRIBARRAYPROC) \
 | 
			
		||||
	GL_FUN(VertexAttribPointer, PFNGLVERTEXATTRIBPOINTERPROC)
 | 
			
		||||
	GL_FUN(BindAttribLocation, _PFNGLBINDATTRIBLOCATIONPROC) \
 | 
			
		||||
	GL_FUN(EnableVertexAttribArray, _PFNGLENABLEVERTEXATTRIBARRAYPROC) \
 | 
			
		||||
	GL_FUN(DisableVertexAttribArray, _PFNGLDISABLEVERTEXATTRIBARRAYPROC) \
 | 
			
		||||
	GL_FUN(VertexAttribPointer, _PFNGLVERTEXATTRIBPOINTERPROC)
 | 
			
		||||
 | 
			
		||||
#define GL_ES_FUN \
 | 
			
		||||
	GL_FUN(ReleaseShaderCompiler, _PFNGLRELEASESHADERCOMPILERPROC)
 | 
			
		||||
 | 
			
		||||
#define GL_FBO_FUN \
 | 
			
		||||
	/* Framebuffer object */ \
 | 
			
		||||
	GL_FUN(GenFramebuffers, PFNGLGENFRAMEBUFFERSPROC) \
 | 
			
		||||
	GL_FUN(DeleteFramebuffers, PFNGLDELETEFRAMEBUFFERSPROC) \
 | 
			
		||||
	GL_FUN(BindFramebuffer, PFNGLBINDFRAMEBUFFERPROC) \
 | 
			
		||||
	GL_FUN(FramebufferTexture2D, PFNGLFRAMEBUFFERTEXTURE2DPROC)
 | 
			
		||||
	GL_FUN(GenFramebuffers, _PFNGLGENFRAMEBUFFERSPROC) \
 | 
			
		||||
	GL_FUN(DeleteFramebuffers, _PFNGLDELETEFRAMEBUFFERSPROC) \
 | 
			
		||||
	GL_FUN(BindFramebuffer, _PFNGLBINDFRAMEBUFFERPROC) \
 | 
			
		||||
	GL_FUN(FramebufferTexture2D, _PFNGLFRAMEBUFFERTEXTURE2DPROC)
 | 
			
		||||
 | 
			
		||||
#define GL_FBO_BLIT_FUN \
 | 
			
		||||
	GL_FUN(BlitFramebuffer, PFNGLBLITFRAMEBUFFERPROC)
 | 
			
		||||
	GL_FUN(BlitFramebuffer, _PFNGLBLITFRAMEBUFFERPROC)
 | 
			
		||||
 | 
			
		||||
#define GL_VAO_FUN \
 | 
			
		||||
	/* Vertex array object */ \
 | 
			
		||||
	GL_FUN(GenVertexArrays, PFNGLGENVERTEXARRAYSPROC) \
 | 
			
		||||
	GL_FUN(DeleteVertexArrays, PFNGLDELETEVERTEXARRAYSPROC) \
 | 
			
		||||
	GL_FUN(BindVertexArray, PFNGLBINDVERTEXARRAYPROC)
 | 
			
		||||
	GL_FUN(GenVertexArrays, _PFNGLGENVERTEXARRAYSPROC) \
 | 
			
		||||
	GL_FUN(DeleteVertexArrays, _PFNGLDELETEVERTEXARRAYSPROC) \
 | 
			
		||||
	GL_FUN(BindVertexArray, _PFNGLBINDVERTEXARRAYPROC)
 | 
			
		||||
 | 
			
		||||
#define GL_DEBUG_KHR_FUN \
 | 
			
		||||
	GL_FUN(DebugMessageCallback, _PFNGLDEBUGMESSAGECALLBACKPROC)
 | 
			
		||||
 | 
			
		||||
#define GL_GREMEMDY_FUN \
 | 
			
		||||
	GL_FUN(StringMarker, _PFNGLSTRINGMARKERPROC)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct GLFunctions
 | 
			
		||||
{
 | 
			
		||||
#define GL_FUN(name, type) type name;
 | 
			
		||||
 | 
			
		||||
	GL_20_FUN
 | 
			
		||||
	GL_ES_FUN
 | 
			
		||||
	GL_FBO_FUN
 | 
			
		||||
	GL_FBO_BLIT_FUN
 | 
			
		||||
	GL_VAO_FUN
 | 
			
		||||
	GL_DEBUG_KHR_FUN
 | 
			
		||||
	GL_GREMEMDY_FUN
 | 
			
		||||
 | 
			
		||||
	bool glsles;
 | 
			
		||||
	bool unpack_subimage;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,43 +61,43 @@ namespace TEX
 | 
			
		|||
		return id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void del(ID id)
 | 
			
		||||
	static inline void del(ID id)
 | 
			
		||||
	{
 | 
			
		||||
		gl.DeleteTextures(1, &id.gl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void bind(ID id)
 | 
			
		||||
	static inline void bind(ID id)
 | 
			
		||||
	{
 | 
			
		||||
		gl.BindTexture(GL_TEXTURE_2D, id.gl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void unbind()
 | 
			
		||||
	static inline void unbind()
 | 
			
		||||
	{
 | 
			
		||||
		bind(ID(0));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void uploadImage(GLsizei width, GLsizei height, const void *data, GLenum format)
 | 
			
		||||
	static inline void uploadImage(GLsizei width, GLsizei height, const void *data, GLenum format)
 | 
			
		||||
	{
 | 
			
		||||
		gl.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_BYTE, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void uploadSubImage(GLint x, GLint y, GLsizei width, GLsizei height, const void *data, GLenum format)
 | 
			
		||||
	static inline void uploadSubImage(GLint x, GLint y, GLsizei width, GLsizei height, const void *data, GLenum format)
 | 
			
		||||
	{
 | 
			
		||||
		gl.TexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, format, GL_UNSIGNED_BYTE, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void allocEmpty(GLsizei width, GLsizei height)
 | 
			
		||||
	static inline void allocEmpty(GLsizei width, GLsizei height)
 | 
			
		||||
	{
 | 
			
		||||
		gl.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void setRepeat(bool mode)
 | 
			
		||||
	static inline void setRepeat(bool mode)
 | 
			
		||||
	{
 | 
			
		||||
		gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode ? GL_REPEAT : GL_CLAMP_TO_EDGE);
 | 
			
		||||
		gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode ? GL_REPEAT : GL_CLAMP_TO_EDGE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void setSmooth(bool mode)
 | 
			
		||||
	static inline void setSmooth(bool mode)
 | 
			
		||||
	{
 | 
			
		||||
		gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mode ? GL_LINEAR : GL_NEAREST);
 | 
			
		||||
		gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mode ? GL_LINEAR : GL_NEAREST);
 | 
			
		||||
| 
						 | 
				
			
			@ -117,27 +117,27 @@ namespace FBO
 | 
			
		|||
		return id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void del(ID id)
 | 
			
		||||
	static inline void del(ID id)
 | 
			
		||||
	{
 | 
			
		||||
		gl.DeleteFramebuffers(1, &id.gl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void bind(ID id)
 | 
			
		||||
	static inline void bind(ID id)
 | 
			
		||||
	{
 | 
			
		||||
		gl.BindFramebuffer(GL_FRAMEBUFFER, id.gl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void unbind()
 | 
			
		||||
	static inline void unbind()
 | 
			
		||||
	{
 | 
			
		||||
		bind(ID(0));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void setTarget(TEX::ID target, unsigned colorAttach = 0)
 | 
			
		||||
	static inline void setTarget(TEX::ID target, unsigned colorAttach = 0)
 | 
			
		||||
	{
 | 
			
		||||
		gl.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttach, GL_TEXTURE_2D, target.gl, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void clear()
 | 
			
		||||
	static inline void clear()
 | 
			
		||||
	{
 | 
			
		||||
		gl.Clear(GL_COLOR_BUFFER_BIT);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -148,7 +148,7 @@ struct GenericBO
 | 
			
		|||
{
 | 
			
		||||
	DEF_GL_ID
 | 
			
		||||
 | 
			
		||||
	inline static ID gen()
 | 
			
		||||
	static inline ID gen()
 | 
			
		||||
	{
 | 
			
		||||
		ID id;
 | 
			
		||||
		gl.GenBuffers(1, &id.gl);
 | 
			
		||||
| 
						 | 
				
			
			@ -156,32 +156,32 @@ struct GenericBO
 | 
			
		|||
		return id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline static void del(ID id)
 | 
			
		||||
	static inline void del(ID id)
 | 
			
		||||
	{
 | 
			
		||||
		gl.DeleteBuffers(1, &id.gl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline static void bind(ID id)
 | 
			
		||||
	static inline void bind(ID id)
 | 
			
		||||
	{
 | 
			
		||||
		gl.BindBuffer(target, id.gl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline static void unbind()
 | 
			
		||||
	static inline void unbind()
 | 
			
		||||
	{
 | 
			
		||||
		bind(ID(0));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline static void uploadData(GLsizeiptr size, const GLvoid *data, GLenum usage = GL_STATIC_DRAW)
 | 
			
		||||
	static inline void uploadData(GLsizeiptr size, const GLvoid *data, GLenum usage = GL_STATIC_DRAW)
 | 
			
		||||
	{
 | 
			
		||||
		gl.BufferData(target, size, data, usage);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline static void uploadSubData(GLintptr offset, GLsizeiptr size, const GLvoid *data)
 | 
			
		||||
	static inline void uploadSubData(GLintptr offset, GLsizeiptr size, const GLvoid *data)
 | 
			
		||||
	{
 | 
			
		||||
		gl.BufferSubData(target, offset, size, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline static void allocEmpty(GLsizeiptr size, GLenum usage = GL_STATIC_DRAW)
 | 
			
		||||
	static inline void allocEmpty(GLsizeiptr size, GLenum usage = GL_STATIC_DRAW)
 | 
			
		||||
	{
 | 
			
		||||
		uploadData(size, 0, usage);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ void GLScissorBox::apply(const IntRect &value)
 | 
			
		|||
 | 
			
		||||
void GLScissorBox::setIntersect(const IntRect &value)
 | 
			
		||||
{
 | 
			
		||||
	IntRect ¤t = get();
 | 
			
		||||
	const IntRect ¤t = get();
 | 
			
		||||
 | 
			
		||||
	SDL_Rect r1 = { current.x, current.y, current.w, current.h };
 | 
			
		||||
	SDL_Rect r2 = { value.x,   value.y,   value.w,   value.h };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ struct GLProperty
 | 
			
		|||
 | 
			
		||||
	void push() { stack.push(current); }
 | 
			
		||||
	void pop()  { set(stack.top()); stack.pop(); }
 | 
			
		||||
	T &get()    { return current; }
 | 
			
		||||
	const T &get()    { return current; }
 | 
			
		||||
	void set(const T &value)
 | 
			
		||||
	{
 | 
			
		||||
		if (value == current)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										162
									
								
								src/graphics.cpp
									
										
									
									
									
								
							
							
						
						
									
										162
									
								
								src/graphics.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -171,36 +171,112 @@ public:
 | 
			
		|||
 | 
			
		||||
	void requestViewportRender(Vec4 &c, Vec4 &f, Vec4 &t)
 | 
			
		||||
	{
 | 
			
		||||
		pp.swapRender();
 | 
			
		||||
		const IntRect &viewpRect = glState.scissorBox.get();
 | 
			
		||||
		const IntRect &screenRect = geometry.rect;
 | 
			
		||||
 | 
			
		||||
		/* Scissor test _does_ affect FBO blit operations,
 | 
			
		||||
		 * and since we're inside the draw cycle, it will
 | 
			
		||||
		 * be turned on, so turn it off temporarily */
 | 
			
		||||
		glState.scissorTest.pushSet(false);
 | 
			
		||||
		if (t.w != 0.0)
 | 
			
		||||
		{
 | 
			
		||||
			pp.swapRender();
 | 
			
		||||
 | 
			
		||||
		GLMeta::blitBegin(pp.frontBuffer());
 | 
			
		||||
		GLMeta::blitSource(pp.backBuffer());
 | 
			
		||||
		GLMeta::blitRectangle(geometry.rect, Vec2i());
 | 
			
		||||
		GLMeta::blitEnd();
 | 
			
		||||
			if (!viewpRect.encloses(screenRect))
 | 
			
		||||
			{
 | 
			
		||||
				/* Scissor test _does_ affect FBO blit operations,
 | 
			
		||||
				 * and since we're inside the draw cycle, it will
 | 
			
		||||
				 * be turned on, so turn it off temporarily */
 | 
			
		||||
				glState.scissorTest.pushSet(false);
 | 
			
		||||
 | 
			
		||||
		glState.scissorTest.pop();
 | 
			
		||||
				GLMeta::blitBegin(pp.frontBuffer());
 | 
			
		||||
				GLMeta::blitSource(pp.backBuffer());
 | 
			
		||||
				GLMeta::blitRectangle(geometry.rect, Vec2i());
 | 
			
		||||
				GLMeta::blitEnd();
 | 
			
		||||
 | 
			
		||||
		PlaneShader &shader = shState->shaders().plane;
 | 
			
		||||
				glState.scissorTest.pop();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			GrayShader &shader = shState->shaders().gray;
 | 
			
		||||
			shader.bind();
 | 
			
		||||
			shader.setGray(t.w);
 | 
			
		||||
			shader.applyViewportProj();
 | 
			
		||||
			shader.setTexSize(screenRect.size());
 | 
			
		||||
 | 
			
		||||
			TEX::bind(pp.backBuffer().tex);
 | 
			
		||||
 | 
			
		||||
			glState.blend.pushSet(false);
 | 
			
		||||
			screenQuad.draw();
 | 
			
		||||
			glState.blend.pop();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bool toneEffect = t.xyzHasEffect();
 | 
			
		||||
		bool colorEffect = c.xyzHasEffect();
 | 
			
		||||
		bool flashEffect = f.xyzHasEffect();
 | 
			
		||||
 | 
			
		||||
		if (!toneEffect && !colorEffect && !flashEffect)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		FlatColorShader &shader = shState->shaders().flatColor;
 | 
			
		||||
		shader.bind();
 | 
			
		||||
		shader.setColor(c);
 | 
			
		||||
		shader.setFlash(f);
 | 
			
		||||
		shader.setTone(t);
 | 
			
		||||
		shader.setOpacity(1.0);
 | 
			
		||||
		shader.applyViewportProj();
 | 
			
		||||
		shader.setTexSize(geometry.rect.size());
 | 
			
		||||
 | 
			
		||||
		TEX::bind(pp.backBuffer().tex);
 | 
			
		||||
		/* Apply tone */
 | 
			
		||||
		if (toneEffect)
 | 
			
		||||
		{
 | 
			
		||||
			/* First split up additive / substractive components */
 | 
			
		||||
			Vec4 add, sub;
 | 
			
		||||
 | 
			
		||||
		glState.blend.pushSet(false);
 | 
			
		||||
			if (t.x > 0)
 | 
			
		||||
				add.x = t.x;
 | 
			
		||||
			if (t.y > 0)
 | 
			
		||||
				add.y = t.y;
 | 
			
		||||
			if (t.z > 0)
 | 
			
		||||
				add.z = t.z;
 | 
			
		||||
 | 
			
		||||
		screenQuad.draw();
 | 
			
		||||
			if (t.x < 0)
 | 
			
		||||
				sub.x = -t.x;
 | 
			
		||||
			if (t.y < 0)
 | 
			
		||||
				sub.y = -t.y;
 | 
			
		||||
			if (t.z < 0)
 | 
			
		||||
				sub.z = -t.z;
 | 
			
		||||
 | 
			
		||||
		glState.blend.pop();
 | 
			
		||||
			/* Then apply them using hardware blending */
 | 
			
		||||
			gl.BlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ONE);
 | 
			
		||||
 | 
			
		||||
			if (add.xyzHasEffect())
 | 
			
		||||
			{
 | 
			
		||||
				gl.BlendEquation(GL_FUNC_ADD);
 | 
			
		||||
				shader.setColor(add);
 | 
			
		||||
 | 
			
		||||
				screenQuad.draw();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (sub.xyzHasEffect())
 | 
			
		||||
			{
 | 
			
		||||
				gl.BlendEquation(GL_FUNC_REVERSE_SUBTRACT);
 | 
			
		||||
				shader.setColor(sub);
 | 
			
		||||
 | 
			
		||||
				screenQuad.draw();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (colorEffect || flashEffect)
 | 
			
		||||
		{
 | 
			
		||||
			gl.BlendEquation(GL_FUNC_ADD);
 | 
			
		||||
			gl.BlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
 | 
			
		||||
			                     GL_ZERO, GL_ONE);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (colorEffect)
 | 
			
		||||
		{
 | 
			
		||||
			shader.setColor(c);
 | 
			
		||||
			screenQuad.draw();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (flashEffect)
 | 
			
		||||
		{
 | 
			
		||||
			shader.setColor(f);
 | 
			
		||||
			screenQuad.draw();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		glState.blendMode.refresh();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setBrightness(float norm)
 | 
			
		||||
| 
						 | 
				
			
			@ -390,6 +466,7 @@ struct GraphicsPrivate
 | 
			
		|||
 | 
			
		||||
	ScreenScene screen;
 | 
			
		||||
	RGSSThreadData *threadData;
 | 
			
		||||
	SDL_GLContext glCtx;
 | 
			
		||||
 | 
			
		||||
	int frameRate;
 | 
			
		||||
	int frameCount;
 | 
			
		||||
| 
						 | 
				
			
			@ -413,6 +490,7 @@ struct GraphicsPrivate
 | 
			
		|||
	      winSize(rtData->config.defScreenW, rtData->config.defScreenH),
 | 
			
		||||
	      screen(scRes.x, scRes.y),
 | 
			
		||||
	      threadData(rtData),
 | 
			
		||||
	      glCtx(SDL_GL_GetCurrentContext()),
 | 
			
		||||
	      frameRate(DEF_FRAMERATE),
 | 
			
		||||
	      frameCount(0),
 | 
			
		||||
	      brightness(255),
 | 
			
		||||
| 
						 | 
				
			
			@ -482,7 +560,7 @@ struct GraphicsPrivate
 | 
			
		|||
 | 
			
		||||
	void checkResize()
 | 
			
		||||
	{
 | 
			
		||||
		if (threadData->windowSizeMsg.pollChange(&winSize.x, &winSize.y))
 | 
			
		||||
		if (threadData->windowSizeMsg.poll(winSize))
 | 
			
		||||
		{
 | 
			
		||||
			/* some GL drivers change the viewport on window resize */
 | 
			
		||||
			glState.viewport.refresh();
 | 
			
		||||
| 
						 | 
				
			
			@ -552,16 +630,40 @@ struct GraphicsPrivate
 | 
			
		|||
 | 
			
		||||
		swapGLBuffer();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void checkSyncLock()
 | 
			
		||||
	{
 | 
			
		||||
		if (!threadData->syncPoint.mainSyncLocked())
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		/* Releasing the GL context before sleeping and making it
 | 
			
		||||
		 * current again on wakeup seems to avoid the context loss
 | 
			
		||||
		 * when the app moves into the background on Android */
 | 
			
		||||
		SDL_GL_MakeCurrent(threadData->window, 0);
 | 
			
		||||
		threadData->syncPoint.waitMainSync();
 | 
			
		||||
		SDL_GL_MakeCurrent(threadData->window, glCtx);
 | 
			
		||||
 | 
			
		||||
		fpsLimiter.resetFrameAdjust();
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Graphics::Graphics(RGSSThreadData *data)
 | 
			
		||||
{
 | 
			
		||||
	p = new GraphicsPrivate(data);
 | 
			
		||||
 | 
			
		||||
	if (data->config.fixedFramerate > 0)
 | 
			
		||||
		p->fpsLimiter.setDesiredFPS(data->config.fixedFramerate);
 | 
			
		||||
	else if (data->config.fixedFramerate < 0)
 | 
			
		||||
	if (data->config.syncToRefreshrate)
 | 
			
		||||
	{
 | 
			
		||||
		p->frameRate = data->refreshRate;
 | 
			
		||||
		p->fpsLimiter.disabled = true;
 | 
			
		||||
	}
 | 
			
		||||
	else if (data->config.fixedFramerate > 0)
 | 
			
		||||
	{
 | 
			
		||||
		p->fpsLimiter.setDesiredFPS(data->config.fixedFramerate);
 | 
			
		||||
	}
 | 
			
		||||
	else if (data->config.fixedFramerate < 0)
 | 
			
		||||
	{
 | 
			
		||||
		p->fpsLimiter.disabled = true;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Graphics::~Graphics()
 | 
			
		||||
| 
						 | 
				
			
			@ -572,6 +674,7 @@ Graphics::~Graphics()
 | 
			
		|||
void Graphics::update()
 | 
			
		||||
{
 | 
			
		||||
	p->checkShutDownReset();
 | 
			
		||||
	p->checkSyncLock();
 | 
			
		||||
 | 
			
		||||
	if (p->frozen)
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -613,10 +716,12 @@ void Graphics::transition(int duration,
 | 
			
		|||
                          const char *filename,
 | 
			
		||||
                          int vague)
 | 
			
		||||
{
 | 
			
		||||
	p->checkSyncLock();
 | 
			
		||||
 | 
			
		||||
	if (!p->frozen)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	vague = clamp(vague, 0, 512);
 | 
			
		||||
	vague = clamp(vague, 1, 256);
 | 
			
		||||
	Bitmap *transMap = filename ? new Bitmap(filename) : 0;
 | 
			
		||||
 | 
			
		||||
	setBrightness(255);
 | 
			
		||||
| 
						 | 
				
			
			@ -637,7 +742,7 @@ void Graphics::transition(int duration,
 | 
			
		|||
		shader.setFrozenScene(p->frozenScene.tex);
 | 
			
		||||
		shader.setCurrentScene(p->currentScene.tex);
 | 
			
		||||
		shader.setTransMap(transMap->getGLTypes().tex);
 | 
			
		||||
		shader.setVague(vague / 512.0f);
 | 
			
		||||
		shader.setVague(vague / 256.0);
 | 
			
		||||
		shader.setTexSize(p->scRes);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
| 
						 | 
				
			
			@ -673,6 +778,8 @@ void Graphics::transition(int duration,
 | 
			
		|||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p->checkSyncLock();
 | 
			
		||||
 | 
			
		||||
		const float prog = i * (1.0 / duration);
 | 
			
		||||
 | 
			
		||||
		if (transMap)
 | 
			
		||||
| 
						 | 
				
			
			@ -728,6 +835,9 @@ void Graphics::setFrameRate(int value)
 | 
			
		|||
{
 | 
			
		||||
	p->frameRate = clamp(value, 10, 120);
 | 
			
		||||
 | 
			
		||||
	if (p->threadData->config.syncToRefreshrate)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (p->threadData->config.fixedFramerate > 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -133,7 +133,7 @@ struct JsAxisBinding : public Binding
 | 
			
		|||
 | 
			
		||||
	bool sourceActive() const
 | 
			
		||||
	{
 | 
			
		||||
		int val = EventThread::joyState.axis[source];
 | 
			
		||||
		int val = EventThread::joyState.axes[source];
 | 
			
		||||
 | 
			
		||||
		if (dir == Negative)
 | 
			
		||||
			return val < -JAXIS_THRESHOLD;
 | 
			
		||||
| 
						 | 
				
			
			@ -150,6 +150,34 @@ struct JsAxisBinding : public Binding
 | 
			
		|||
	AxisDir dir;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Joystick hat binding */
 | 
			
		||||
struct JsHatBinding : public Binding
 | 
			
		||||
{
 | 
			
		||||
	JsHatBinding() {}
 | 
			
		||||
 | 
			
		||||
	JsHatBinding(uint8_t source,
 | 
			
		||||
	              uint8_t pos,
 | 
			
		||||
	              Input::ButtonCode target)
 | 
			
		||||
	    : Binding(target),
 | 
			
		||||
	      source(source),
 | 
			
		||||
	      pos(pos)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	bool sourceActive() const
 | 
			
		||||
	{
 | 
			
		||||
		/* For a diagonal input accept it as an input for both the axes */
 | 
			
		||||
		return (pos & EventThread::joyState.hats[source]) != 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool sourceRepeatable() const
 | 
			
		||||
	{
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uint8_t source;
 | 
			
		||||
	uint8_t pos;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Mouse button binding */
 | 
			
		||||
struct MsBinding : public Binding
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -241,6 +269,7 @@ struct InputPrivate
 | 
			
		|||
	std::vector<KbBinding> kbStatBindings;
 | 
			
		||||
	std::vector<KbBinding> kbBindings;
 | 
			
		||||
	std::vector<JsAxisBinding> jsABindings;
 | 
			
		||||
	std::vector<JsHatBinding> jsHBindings;
 | 
			
		||||
	std::vector<JsButtonBinding> jsBBindings;
 | 
			
		||||
	std::vector<MsBinding> msBindings;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -348,6 +377,7 @@ struct InputPrivate
 | 
			
		|||
	{
 | 
			
		||||
		kbBindings.clear();
 | 
			
		||||
		jsABindings.clear();
 | 
			
		||||
		jsHBindings.clear();
 | 
			
		||||
		jsBBindings.clear();
 | 
			
		||||
 | 
			
		||||
		for (size_t i = 0; i < d.size(); ++i)
 | 
			
		||||
| 
						 | 
				
			
			@ -381,6 +411,16 @@ struct InputPrivate
 | 
			
		|||
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			case JHat :
 | 
			
		||||
			{
 | 
			
		||||
				JsHatBinding bind;
 | 
			
		||||
				bind.source = src.d.jh.hat;
 | 
			
		||||
				bind.pos = src.d.jh.pos;
 | 
			
		||||
				bind.target = desc.target;
 | 
			
		||||
				jsHBindings.push_back(bind);
 | 
			
		||||
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			case JButton :
 | 
			
		||||
			{
 | 
			
		||||
				JsButtonBinding bind;
 | 
			
		||||
| 
						 | 
				
			
			@ -402,6 +442,7 @@ struct InputPrivate
 | 
			
		|||
 | 
			
		||||
		appendBindings(kbBindings);
 | 
			
		||||
		appendBindings(jsABindings);
 | 
			
		||||
		appendBindings(jsHBindings);
 | 
			
		||||
		appendBindings(jsBBindings);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -129,6 +129,20 @@ static void addAxisBinding(BDescVec &d, uint8_t axis, AxisDir dir, Input::Button
 | 
			
		|||
	d.push_back(desc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void addHatBinding(BDescVec &d, uint8_t hat, uint8_t pos, Input::ButtonCode target)
 | 
			
		||||
{
 | 
			
		||||
	SourceDesc src;
 | 
			
		||||
	src.type = JHat;
 | 
			
		||||
	src.d.jh.hat = hat;
 | 
			
		||||
	src.d.jh.pos = pos;
 | 
			
		||||
 | 
			
		||||
	BindingDesc desc;
 | 
			
		||||
	desc.src = src;
 | 
			
		||||
	desc.target = target;
 | 
			
		||||
 | 
			
		||||
	d.push_back(desc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BDescVec genDefaultBindings(const Config &conf)
 | 
			
		||||
{
 | 
			
		||||
	BDescVec d;
 | 
			
		||||
| 
						 | 
				
			
			@ -151,10 +165,15 @@ BDescVec genDefaultBindings(const Config &conf)
 | 
			
		|||
	addAxisBinding(d, 1, Negative, Input::Up   );
 | 
			
		||||
	addAxisBinding(d, 1, Positive, Input::Down );
 | 
			
		||||
	
 | 
			
		||||
	addHatBinding(d, 0, SDL_HAT_LEFT,  Input::Left );
 | 
			
		||||
	addHatBinding(d, 0, SDL_HAT_RIGHT, Input::Right);
 | 
			
		||||
	addHatBinding(d, 0, SDL_HAT_UP,    Input::Up   );
 | 
			
		||||
	addHatBinding(d, 0, SDL_HAT_DOWN,  Input::Down );
 | 
			
		||||
 | 
			
		||||
	return d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define FORMAT_VER 1
 | 
			
		||||
#define FORMAT_VER 2
 | 
			
		||||
 | 
			
		||||
struct Header
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +185,7 @@ struct Header
 | 
			
		|||
static void buildPath(const std::string &dir, uint32_t rgssVersion,
 | 
			
		||||
                      char *out, size_t outSize)
 | 
			
		||||
{
 | 
			
		||||
	snprintf(out, outSize, "%s/keybindings.mkxp%u", dir.c_str(), rgssVersion);
 | 
			
		||||
	snprintf(out, outSize, "%skeybindings.mkxp%u", dir.c_str(), rgssVersion);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool writeBindings(const BDescVec &d, const std::string &dir,
 | 
			
		||||
| 
						 | 
				
			
			@ -178,7 +197,7 @@ static bool writeBindings(const BDescVec &d, const std::string &dir,
 | 
			
		|||
	char path[1024];
 | 
			
		||||
	buildPath(dir, rgssVersion, path, sizeof(path));
 | 
			
		||||
 | 
			
		||||
	FILE *f = fopen(path, "w");
 | 
			
		||||
	FILE *f = fopen(path, "wb");
 | 
			
		||||
 | 
			
		||||
	if (!f)
 | 
			
		||||
		return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -247,6 +266,10 @@ static bool verifyDesc(const BindingDesc &desc)
 | 
			
		|||
		return src.d.scan < SDL_NUM_SCANCODES;
 | 
			
		||||
	case JButton:
 | 
			
		||||
		return true;
 | 
			
		||||
	case JHat:
 | 
			
		||||
		/* Only accept single directional binds */
 | 
			
		||||
		return src.d.jh.pos == SDL_HAT_LEFT || src.d.jh.pos == SDL_HAT_RIGHT ||
 | 
			
		||||
		       src.d.jh.pos == SDL_HAT_UP   || src.d.jh.pos == SDL_HAT_DOWN;
 | 
			
		||||
	case JAxis:
 | 
			
		||||
		return src.d.ja.dir == Negative || src.d.ja.dir == Positive;
 | 
			
		||||
	default:
 | 
			
		||||
| 
						 | 
				
			
			@ -263,7 +286,7 @@ static bool readBindings(BDescVec &out, const std::string &dir,
 | 
			
		|||
	char path[1024];
 | 
			
		||||
	buildPath(dir, rgssVersion, path, sizeof(path));
 | 
			
		||||
 | 
			
		||||
	FILE *f = fopen(path, "r");
 | 
			
		||||
	FILE *f = fopen(path, "rb");
 | 
			
		||||
 | 
			
		||||
	if (!f)
 | 
			
		||||
		return false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@
 | 
			
		|||
#include "input.h"
 | 
			
		||||
 | 
			
		||||
#include <SDL_scancode.h>
 | 
			
		||||
#include <SDL_joystick.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +41,8 @@ enum SourceType
 | 
			
		|||
	Invalid,
 | 
			
		||||
	Key,
 | 
			
		||||
	JButton,
 | 
			
		||||
	JAxis
 | 
			
		||||
	JAxis,
 | 
			
		||||
	JHat
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct SourceDesc
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +62,13 @@ struct SourceDesc
 | 
			
		|||
			/* Joystick axis direction */
 | 
			
		||||
			AxisDir dir;
 | 
			
		||||
		} ja;
 | 
			
		||||
		struct
 | 
			
		||||
		{
 | 
			
		||||
			/* Joystick axis index */
 | 
			
		||||
			uint8_t hat;
 | 
			
		||||
			/* Joystick axis direction */
 | 
			
		||||
			uint8_t pos;
 | 
			
		||||
		} jh;
 | 
			
		||||
	} d;
 | 
			
		||||
 | 
			
		||||
	bool operator==(const SourceDesc &o) const
 | 
			
		||||
| 
						 | 
				
			
			@ -77,6 +86,8 @@ struct SourceDesc
 | 
			
		|||
			return d.jb == o.d.jb;
 | 
			
		||||
		case JAxis:
 | 
			
		||||
			return (d.ja.axis == o.d.ja.axis) && (d.ja.dir == o.d.ja.dir);
 | 
			
		||||
		case JHat:
 | 
			
		||||
			return (d.jh.hat == o.d.jh.hat) && (d.jh.pos == o.d.jh.pos);
 | 
			
		||||
		default:
 | 
			
		||||
			assert(!"unreachable");
 | 
			
		||||
			return false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										118
									
								
								src/main.cpp
									
										
									
									
									
								
							
							
						
						
									
										118
									
								
								src/main.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -26,20 +26,21 @@
 | 
			
		|||
#include <SDL_ttf.h>
 | 
			
		||||
#include <SDL_sound.h>
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "sharedstate.h"
 | 
			
		||||
#include "eventthread.h"
 | 
			
		||||
#include "debuglogger.h"
 | 
			
		||||
#include "gl-debug.h"
 | 
			
		||||
#include "debugwriter.h"
 | 
			
		||||
#include "exception.h"
 | 
			
		||||
#include "gl-fun.h"
 | 
			
		||||
 | 
			
		||||
#include "binding.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include "icon.png.xxd"
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
rgssThreadError(RGSSThreadData *rtData, const std::string &msg)
 | 
			
		||||
| 
						 | 
				
			
			@ -67,13 +68,14 @@ printGLInfo()
 | 
			
		|||
int rgssThreadFun(void *userdata)
 | 
			
		||||
{
 | 
			
		||||
	RGSSThreadData *threadData = static_cast<RGSSThreadData*>(userdata);
 | 
			
		||||
	const Config &conf = threadData->config;
 | 
			
		||||
	SDL_Window *win = threadData->window;
 | 
			
		||||
	SDL_GLContext glCtx;
 | 
			
		||||
 | 
			
		||||
	/* Setup GL context */
 | 
			
		||||
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
 | 
			
		||||
 | 
			
		||||
	if (threadData->config.debugMode)
 | 
			
		||||
	if (conf.debugMode)
 | 
			
		||||
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
 | 
			
		||||
 | 
			
		||||
	glCtx = SDL_GL_CreateContext(win);
 | 
			
		||||
| 
						 | 
				
			
			@ -102,27 +104,17 @@ int rgssThreadFun(void *userdata)
 | 
			
		|||
 | 
			
		||||
	printGLInfo();
 | 
			
		||||
 | 
			
		||||
	SDL_GL_SetSwapInterval(threadData->config.vsync ? 1 : 0);
 | 
			
		||||
	bool vsync = conf.vsync || conf.syncToRefreshrate;
 | 
			
		||||
	SDL_GL_SetSwapInterval(vsync ? 1 : 0);
 | 
			
		||||
 | 
			
		||||
	DebugLogger dLogger;
 | 
			
		||||
	GLDebugLogger dLogger;
 | 
			
		||||
 | 
			
		||||
	/* Setup AL context */
 | 
			
		||||
	ALCdevice *alcDev = alcOpenDevice(0);
 | 
			
		||||
 | 
			
		||||
	if (!alcDev)
 | 
			
		||||
	{
 | 
			
		||||
		rgssThreadError(threadData, "Error opening OpenAL device");
 | 
			
		||||
		SDL_GL_DeleteContext(glCtx);
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ALCcontext *alcCtx = alcCreateContext(alcDev, 0);
 | 
			
		||||
	ALCcontext *alcCtx = alcCreateContext(threadData->alcDev, 0);
 | 
			
		||||
 | 
			
		||||
	if (!alcCtx)
 | 
			
		||||
	{
 | 
			
		||||
		rgssThreadError(threadData, "Error creating OpenAL context");
 | 
			
		||||
		alcCloseDevice(alcDev);
 | 
			
		||||
		SDL_GL_DeleteContext(glCtx);
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -138,7 +130,6 @@ int rgssThreadFun(void *userdata)
 | 
			
		|||
	{
 | 
			
		||||
		rgssThreadError(threadData, exc.msg);
 | 
			
		||||
		alcDestroyContext(alcCtx);
 | 
			
		||||
		alcCloseDevice(alcDev);
 | 
			
		||||
		SDL_GL_DeleteContext(glCtx);
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -153,8 +144,6 @@ int rgssThreadFun(void *userdata)
 | 
			
		|||
	SharedState::finiInstance();
 | 
			
		||||
 | 
			
		||||
	alcDestroyContext(alcCtx);
 | 
			
		||||
	alcCloseDevice(alcDev);
 | 
			
		||||
 | 
			
		||||
	SDL_GL_DeleteContext(glCtx);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -171,20 +160,27 @@ static void printRgssVersion(int ver)
 | 
			
		|||
	Debug() << buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void showInitError(const std::string &msg)
 | 
			
		||||
{
 | 
			
		||||
	Debug() << msg;
 | 
			
		||||
	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "mkxp", msg.c_str(), 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
 | 
			
		||||
	SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
 | 
			
		||||
 | 
			
		||||
	/* initialize SDL first */
 | 
			
		||||
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
 | 
			
		||||
	{
 | 
			
		||||
		Debug() << "Error initializing SDL:" << SDL_GetError();
 | 
			
		||||
 | 
			
		||||
		showInitError(std::string("Error initializing SDL: ") + SDL_GetError());
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!EventThread::allocUserEvents())
 | 
			
		||||
	{
 | 
			
		||||
		Debug() << "Error allocating SDL user events";
 | 
			
		||||
 | 
			
		||||
		showInitError("Error allocating SDL user events");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -201,8 +197,15 @@ int main(int argc, char *argv[])
 | 
			
		|||
 | 
			
		||||
	/* now we load the config */
 | 
			
		||||
	Config conf;
 | 
			
		||||
 | 
			
		||||
	conf.read(argc, argv);
 | 
			
		||||
 | 
			
		||||
	if (!conf.gameFolder.empty())
 | 
			
		||||
		if (chdir(conf.gameFolder.c_str()) != 0)
 | 
			
		||||
		{
 | 
			
		||||
			showInitError(std::string("Unable to switch into gameFolder ") + conf.gameFolder);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	conf.readGameINI();
 | 
			
		||||
 | 
			
		||||
	assert(conf.rgssVersion >= 1 && conf.rgssVersion <= 3);
 | 
			
		||||
| 
						 | 
				
			
			@ -211,7 +214,7 @@ int main(int argc, char *argv[])
 | 
			
		|||
	int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG;
 | 
			
		||||
	if (IMG_Init(imgFlags) != imgFlags)
 | 
			
		||||
	{
 | 
			
		||||
		Debug() << "Error initializing SDL_image:" << SDL_GetError();
 | 
			
		||||
		showInitError(std::string("Error initializing SDL_image: ") + SDL_GetError());
 | 
			
		||||
		SDL_Quit();
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -219,7 +222,7 @@ int main(int argc, char *argv[])
 | 
			
		|||
 | 
			
		||||
	if (TTF_Init() < 0)
 | 
			
		||||
	{
 | 
			
		||||
		Debug() << "Error initializing SDL_ttf:" << SDL_GetError();
 | 
			
		||||
		showInitError(std::string("Error initializing SDL_ttf: ") + SDL_GetError());
 | 
			
		||||
		IMG_Quit();
 | 
			
		||||
		SDL_Quit();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -228,7 +231,7 @@ int main(int argc, char *argv[])
 | 
			
		|||
 | 
			
		||||
	if (Sound_Init() == 0)
 | 
			
		||||
	{
 | 
			
		||||
		Debug() << "Error initializing SDL_sound:" << Sound_GetError();
 | 
			
		||||
		showInitError(std::string("Error initializing SDL_sound: ") + Sound_GetError());
 | 
			
		||||
		TTF_Quit();
 | 
			
		||||
		IMG_Quit();
 | 
			
		||||
		SDL_Quit();
 | 
			
		||||
| 
						 | 
				
			
			@ -236,7 +239,15 @@ int main(int argc, char *argv[])
 | 
			
		|||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SDL_SetHint("SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS", "0");
 | 
			
		||||
	/* Setup application icon */
 | 
			
		||||
	SDL_RWops *iconSrc;
 | 
			
		||||
 | 
			
		||||
	if (conf.iconPath.empty())
 | 
			
		||||
		iconSrc = SDL_RWFromConstMem(assets_icon_png, assets_icon_png_len);
 | 
			
		||||
	else
 | 
			
		||||
		iconSrc = SDL_RWFromFile(conf.iconPath.c_str(), "rb");
 | 
			
		||||
 | 
			
		||||
	SDL_Surface *iconImg = IMG_Load_RW(iconSrc, SDL_TRUE);
 | 
			
		||||
 | 
			
		||||
	SDL_Window *win;
 | 
			
		||||
	Uint32 winFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_INPUT_FOCUS;
 | 
			
		||||
| 
						 | 
				
			
			@ -252,22 +263,43 @@ int main(int argc, char *argv[])
 | 
			
		|||
 | 
			
		||||
	if (!win)
 | 
			
		||||
	{
 | 
			
		||||
		Debug() << "Error creating window:" << SDL_GetError();
 | 
			
		||||
		showInitError(std::string("Error creating window: ") + SDL_GetError());
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!conf.iconPath.empty())
 | 
			
		||||
	if (iconImg)
 | 
			
		||||
	{
 | 
			
		||||
		SDL_Surface *iconImg = IMG_Load(conf.iconPath.c_str());
 | 
			
		||||
		if (iconImg)
 | 
			
		||||
		{
 | 
			
		||||
			SDL_SetWindowIcon(win, iconImg);
 | 
			
		||||
			SDL_FreeSurface(iconImg);
 | 
			
		||||
		}
 | 
			
		||||
		SDL_SetWindowIcon(win, iconImg);
 | 
			
		||||
		SDL_FreeSurface(iconImg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ALCdevice *alcDev = alcOpenDevice(0);
 | 
			
		||||
 | 
			
		||||
	if (!alcDev)
 | 
			
		||||
	{
 | 
			
		||||
		showInitError("Error opening OpenAL device");
 | 
			
		||||
		SDL_DestroyWindow(win);
 | 
			
		||||
		TTF_Quit();
 | 
			
		||||
		IMG_Quit();
 | 
			
		||||
		SDL_Quit();
 | 
			
		||||
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SDL_DisplayMode mode;
 | 
			
		||||
	SDL_GetDisplayMode(0, 0, &mode);
 | 
			
		||||
 | 
			
		||||
	/* Can't sync to display refresh rate if its value is unknown */
 | 
			
		||||
	if (!mode.refresh_rate)
 | 
			
		||||
		conf.syncToRefreshrate = false;
 | 
			
		||||
 | 
			
		||||
	EventThread eventThread;
 | 
			
		||||
	RGSSThreadData rtData(&eventThread, argv[0], win, conf);
 | 
			
		||||
	RGSSThreadData rtData(&eventThread, argv[0], win,
 | 
			
		||||
	                      alcDev, mode.refresh_rate, conf);
 | 
			
		||||
 | 
			
		||||
	int winW, winH;
 | 
			
		||||
	SDL_GetWindowSize(win, &winW, &winH);
 | 
			
		||||
	rtData.windowSizeMsg.post(Vec2i(winW, winH));
 | 
			
		||||
 | 
			
		||||
	/* Load and post key bindings */
 | 
			
		||||
	rtData.bindingUpdateMsg.post(loadBindings(conf));
 | 
			
		||||
| 
						 | 
				
			
			@ -314,13 +346,9 @@ int main(int argc, char *argv[])
 | 
			
		|||
	/* Clean up any remainin events */
 | 
			
		||||
	eventThread.cleanup();
 | 
			
		||||
 | 
			
		||||
	/* Store key bindings */
 | 
			
		||||
	BDescVec keyBinds;
 | 
			
		||||
	rtData.bindingUpdateMsg.get(keyBinds);
 | 
			
		||||
	storeBindings(keyBinds, rtData.config);
 | 
			
		||||
 | 
			
		||||
	Debug() << "Shutting down.";
 | 
			
		||||
 | 
			
		||||
	alcCloseDevice(alcDev);
 | 
			
		||||
	SDL_DestroyWindow(win);
 | 
			
		||||
 | 
			
		||||
	Sound_Quit();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,7 +55,13 @@
 | 
			
		|||
#define TICK_FRAMES 32
 | 
			
		||||
#define BUF_TICKS (STREAM_BUF_SIZE / TICK_FRAMES)
 | 
			
		||||
#define DEFAULT_BPM 120
 | 
			
		||||
#define LOOP_MARKER 111
 | 
			
		||||
#define MAX_CHANNELS 16
 | 
			
		||||
 | 
			
		||||
#define CC_CTRL_VOLUME       7
 | 
			
		||||
#define CC_CTRL_EXPRESSION  11
 | 
			
		||||
#define CC_CTRL_LOOP       111
 | 
			
		||||
 | 
			
		||||
#define CC_VAL_DEFAULT 127
 | 
			
		||||
 | 
			
		||||
enum MidiEventType
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -522,6 +528,59 @@ struct Track
 | 
			
		|||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Some songs use CC events for effects like fade-out,
 | 
			
		||||
 * slowly decreasing a channel's volume to 0. The problem is that
 | 
			
		||||
 * for looped songs, events are continuously fed into the synth
 | 
			
		||||
 * without restoring those controls back to their default value.
 | 
			
		||||
 * We can't reset them at the very beginning of tracks because it
 | 
			
		||||
 * might cause audible interactions with notes which are still decaying
 | 
			
		||||
 * past the end of the song. Therefore, we insert a fake CC event right
 | 
			
		||||
 * after the first NoteOn event for each channel which resets the
 | 
			
		||||
 * control to its default state while avoiding audible glitches.
 | 
			
		||||
 * If there is already a CC event for this control before the first
 | 
			
		||||
 * NoteOn event, we don't clobber it by not inserting our fake event. */
 | 
			
		||||
template<uint8_t ctrl>
 | 
			
		||||
struct CCResetter
 | 
			
		||||
{
 | 
			
		||||
	bool chanHandled[MAX_CHANNELS];
 | 
			
		||||
 | 
			
		||||
	CCResetter()
 | 
			
		||||
	{
 | 
			
		||||
		memset(&chanHandled, 0, sizeof(chanHandled));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void handleEvent(const MidiEvent &e, Track &track)
 | 
			
		||||
	{
 | 
			
		||||
		if (e.type != NoteOn && e.type != CC)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		uint8_t chan = e.e.chan.chan;
 | 
			
		||||
 | 
			
		||||
		if (chanHandled[chan])
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		if (e.type == CC && e.e.cc.ctrl == ctrl)
 | 
			
		||||
		{
 | 
			
		||||
			/* Don't clobber the existing CC value */
 | 
			
		||||
			chanHandled[chan] = true;
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		else if (e.type == NoteOn)
 | 
			
		||||
		{
 | 
			
		||||
			chanHandled[chan] = true;
 | 
			
		||||
 | 
			
		||||
			MidiEvent re;
 | 
			
		||||
			re.delta = 0;
 | 
			
		||||
			re.type = CC;
 | 
			
		||||
			re.e.cc.chan = chan;
 | 
			
		||||
			re.e.cc.ctrl = ctrl;
 | 
			
		||||
			re.e.cc.val = CC_VAL_DEFAULT;
 | 
			
		||||
 | 
			
		||||
			track.appendEvent(re);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct MidiSource : ALDataSource, MidiReadHandler
 | 
			
		||||
{
 | 
			
		||||
	const uint16_t freq;
 | 
			
		||||
| 
						 | 
				
			
			@ -530,6 +589,8 @@ struct MidiSource : ALDataSource, MidiReadHandler
 | 
			
		|||
	int16_t synthBuf[BUF_TICKS*TICK_FRAMES*2];
 | 
			
		||||
 | 
			
		||||
	std::vector<Track> tracks;
 | 
			
		||||
	CCResetter<CC_CTRL_VOLUME>     volReset;
 | 
			
		||||
	CCResetter<CC_CTRL_EXPRESSION> expReset;
 | 
			
		||||
 | 
			
		||||
	/* Index of longest track */
 | 
			
		||||
	uint8_t longestI;
 | 
			
		||||
| 
						 | 
				
			
			@ -631,7 +692,7 @@ struct MidiSource : ALDataSource, MidiReadHandler
 | 
			
		|||
		playbackSpeed = TICK_FRAMES / (deltaLength * freq);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void activateEvent(MidiEvent &e)
 | 
			
		||||
	void activateEvent(const MidiEvent &e)
 | 
			
		||||
	{
 | 
			
		||||
		int16_t key = e.e.note.key;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -705,9 +766,14 @@ struct MidiSource : ALDataSource, MidiReadHandler
 | 
			
		|||
	void onMidiEvent(const MidiEvent &e, uint32_t absDelta)
 | 
			
		||||
	{
 | 
			
		||||
		assert(curTrack >= 0 && curTrack < (int16_t) tracks.size());
 | 
			
		||||
		tracks[curTrack].appendEvent(e);
 | 
			
		||||
 | 
			
		||||
		if (e.type == CC && e.e.cc.ctrl == LOOP_MARKER)
 | 
			
		||||
		Track &track = tracks[curTrack];
 | 
			
		||||
 | 
			
		||||
		track.appendEvent(e);
 | 
			
		||||
		volReset.handleEvent(e, track);
 | 
			
		||||
		expReset.handleEvent(e, track);
 | 
			
		||||
 | 
			
		||||
		if (e.type == CC && e.e.cc.ctrl == CC_CTRL_LOOP)
 | 
			
		||||
			loopDelta = absDelta;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -90,8 +90,8 @@ struct PlanePrivate
 | 
			
		|||
		if (gl.npot_repeat)
 | 
			
		||||
		{
 | 
			
		||||
			FloatRect srcRect;
 | 
			
		||||
			srcRect.x = (sceneGeo.xOrigin + ox) / zoomX;
 | 
			
		||||
			srcRect.y = (sceneGeo.yOrigin + oy) / zoomY;
 | 
			
		||||
			srcRect.x = (sceneGeo.orig.x + ox) / zoomX;
 | 
			
		||||
			srcRect.y = (sceneGeo.orig.y + oy) / zoomY;
 | 
			
		||||
			srcRect.w = sceneGeo.rect.w / zoomX;
 | 
			
		||||
			srcRect.h = sceneGeo.rect.h / zoomY;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,10 +23,7 @@
 | 
			
		|||
#include "sharedstate.h"
 | 
			
		||||
 | 
			
		||||
Scene::Scene()
 | 
			
		||||
{
 | 
			
		||||
	geometry.xOrigin = geometry.yOrigin = 0;
 | 
			
		||||
	geometry.rect = IntRect();
 | 
			
		||||
}
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
Scene::~Scene()
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								src/scene.h
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/scene.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -39,8 +39,16 @@ class Scene
 | 
			
		|||
public:
 | 
			
		||||
	struct Geometry
 | 
			
		||||
	{
 | 
			
		||||
		int xOrigin, yOrigin;
 | 
			
		||||
		/* Position and size relative to parent */
 | 
			
		||||
		IntRect rect;
 | 
			
		||||
 | 
			
		||||
		/* Origin of contents */
 | 
			
		||||
		Vec2i orig;
 | 
			
		||||
 | 
			
		||||
		Vec2i offset() const
 | 
			
		||||
		{
 | 
			
		||||
			return rect.pos() - orig;
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Scene();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										113
									
								
								src/sdl-util.h
									
										
									
									
									
								
							
							
						
						
									
										113
									
								
								src/sdl-util.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -3,8 +3,10 @@
 | 
			
		|||
 | 
			
		||||
#include <SDL_atomic.h>
 | 
			
		||||
#include <SDL_thread.h>
 | 
			
		||||
#include <SDL_rwops.h>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
struct AtomicFlag
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -45,4 +47,115 @@ SDL_Thread *createSDLThread(C *obj, const std::string &name = std::string())
 | 
			
		|||
	return SDL_CreateThread(__sdlThreadFun<C, func>, name.c_str(), obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* On Android, SDL_RWFromFile always opens files from inside
 | 
			
		||||
 * the apk asset folder even when a file with same name exists
 | 
			
		||||
 * on the physical filesystem. This wrapper attempts to open a
 | 
			
		||||
 * real file first before falling back to the assets folder */
 | 
			
		||||
static inline
 | 
			
		||||
SDL_RWops *RWFromFile(const char *filename,
 | 
			
		||||
                      const char *mode)
 | 
			
		||||
{
 | 
			
		||||
	FILE *f = fopen(filename, mode);
 | 
			
		||||
 | 
			
		||||
	if (!f)
 | 
			
		||||
		return SDL_RWFromFile(filename, mode);
 | 
			
		||||
 | 
			
		||||
	return SDL_RWFromFP(f, SDL_TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool readFileSDL(const char *path,
 | 
			
		||||
                        std::string &out)
 | 
			
		||||
{
 | 
			
		||||
	SDL_RWops *f = RWFromFile(path, "rb");
 | 
			
		||||
 | 
			
		||||
	if (!f)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	long size = SDL_RWsize(f);
 | 
			
		||||
	size_t back = out.size();
 | 
			
		||||
 | 
			
		||||
	out.resize(back+size);
 | 
			
		||||
	size_t read = SDL_RWread(f, &out[back], 1, size);
 | 
			
		||||
	SDL_RWclose(f);
 | 
			
		||||
 | 
			
		||||
	if (read != (size_t) size)
 | 
			
		||||
		out.resize(back+read);
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<size_t bufSize = 248, size_t pbSize = 8>
 | 
			
		||||
class SDLRWBuf : public std::streambuf
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	SDLRWBuf(SDL_RWops *ops)
 | 
			
		||||
	    : ops(ops)
 | 
			
		||||
	{
 | 
			
		||||
		char *end = buf + bufSize + pbSize;
 | 
			
		||||
		setg(end, end, end);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	int_type underflow()
 | 
			
		||||
	{
 | 
			
		||||
		if (!ops)
 | 
			
		||||
			return traits_type::eof();
 | 
			
		||||
 | 
			
		||||
		if (gptr() < egptr())
 | 
			
		||||
			return traits_type::to_int_type(*gptr());
 | 
			
		||||
 | 
			
		||||
		char *base = buf;
 | 
			
		||||
		char *start = base;
 | 
			
		||||
 | 
			
		||||
		if (eback() == base)
 | 
			
		||||
		{
 | 
			
		||||
			memmove(base, egptr() - pbSize, pbSize);
 | 
			
		||||
			start += pbSize;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		size_t n = SDL_RWread(ops, start, 1, bufSize - (start - base));
 | 
			
		||||
		if (n == 0)
 | 
			
		||||
			return traits_type::eof();
 | 
			
		||||
 | 
			
		||||
		setg(base, start, start + n);
 | 
			
		||||
 | 
			
		||||
		return underflow();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SDL_RWops *ops;
 | 
			
		||||
	char buf[bufSize+pbSize];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class SDLRWStream
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	SDLRWStream(const char *filename,
 | 
			
		||||
	            const char *mode)
 | 
			
		||||
	    : ops(RWFromFile(filename, mode)),
 | 
			
		||||
	      buf(ops),
 | 
			
		||||
	      s(&buf)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	~SDLRWStream()
 | 
			
		||||
	{
 | 
			
		||||
		if (ops)
 | 
			
		||||
			SDL_RWclose(ops);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	operator bool() const
 | 
			
		||||
	{
 | 
			
		||||
		return ops != 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::istream &stream()
 | 
			
		||||
	{
 | 
			
		||||
		return s;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	SDL_RWops *ops;
 | 
			
		||||
	SDLRWBuf<> buf;
 | 
			
		||||
	std::istream s;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // SDLUTIL_H
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,67 +27,44 @@
 | 
			
		|||
 | 
			
		||||
#include <SDL_endian.h>
 | 
			
		||||
 | 
			
		||||
typedef unsigned uint;
 | 
			
		||||
 | 
			
		||||
#if SDL_BYTEORDER != SDL_LIL_ENDIAN
 | 
			
		||||
#error "Non little endian systems not supported"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static inline int16_t
 | 
			
		||||
read_int16(const char *data, uint &i)
 | 
			
		||||
{
 | 
			
		||||
	int16_t result;
 | 
			
		||||
 | 
			
		||||
	memcpy(&result, &data[i], 2);
 | 
			
		||||
	i += 2;
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int32_t
 | 
			
		||||
read_int32(const char *data, uint &i)
 | 
			
		||||
readInt32(const char **dataP)
 | 
			
		||||
{
 | 
			
		||||
	int32_t result;
 | 
			
		||||
 | 
			
		||||
	memcpy(&result, &data[i], 4);
 | 
			
		||||
	i += 4;
 | 
			
		||||
	memcpy(&result, *dataP, 4);
 | 
			
		||||
	*dataP += 4;
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline double
 | 
			
		||||
read_double(const char *data, uint &i)
 | 
			
		||||
readDouble(const char **dataP)
 | 
			
		||||
{
 | 
			
		||||
	double result;
 | 
			
		||||
 | 
			
		||||
	memcpy(&result, &data[i], 8);
 | 
			
		||||
	i += 8;
 | 
			
		||||
	memcpy(&result, *dataP, 8);
 | 
			
		||||
	*dataP += 8;
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
write_int16(char **data, int16_t value)
 | 
			
		||||
writeInt32(char **dataP, int32_t value)
 | 
			
		||||
{
 | 
			
		||||
	memcpy(*data, &value, 2);
 | 
			
		||||
 | 
			
		||||
	*data += 2;
 | 
			
		||||
	memcpy(*dataP, &value, 4);
 | 
			
		||||
	*dataP += 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
write_int32(char **data, int32_t value)
 | 
			
		||||
writeDouble(char **dataP, double value)
 | 
			
		||||
{
 | 
			
		||||
	memcpy(*data, &value, 4);
 | 
			
		||||
 | 
			
		||||
	*data += 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
write_double(char **data, double value)
 | 
			
		||||
{
 | 
			
		||||
	memcpy(*data, &value, 8);
 | 
			
		||||
 | 
			
		||||
	*data += 8;
 | 
			
		||||
	memcpy(*dataP, &value, 8);
 | 
			
		||||
	*dataP += 8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // SERIALUTIL_H
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -81,6 +81,7 @@ static elementsN(vButtons);
 | 
			
		|||
std::string sourceDescString(const SourceDesc &src)
 | 
			
		||||
{
 | 
			
		||||
	char buf[128];
 | 
			
		||||
	char pos;
 | 
			
		||||
 | 
			
		||||
	switch (src.type)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -104,6 +105,32 @@ std::string sourceDescString(const SourceDesc &src)
 | 
			
		|||
		snprintf(buf, sizeof(buf), "JS %d", src.d.jb);
 | 
			
		||||
		return buf;
 | 
			
		||||
 | 
			
		||||
	case JHat:
 | 
			
		||||
		switch(src.d.jh.pos)
 | 
			
		||||
		{
 | 
			
		||||
		case SDL_HAT_UP:
 | 
			
		||||
			pos = 'U';
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case SDL_HAT_DOWN:
 | 
			
		||||
			pos = 'D';
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case SDL_HAT_LEFT:
 | 
			
		||||
			pos = 'L';
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case SDL_HAT_RIGHT:
 | 
			
		||||
			pos = 'R';
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			pos = '-';
 | 
			
		||||
		}
 | 
			
		||||
		snprintf(buf, sizeof(buf), "Hat %d:%c",
 | 
			
		||||
		         src.d.jh.hat, pos);
 | 
			
		||||
		return buf;
 | 
			
		||||
 | 
			
		||||
	case JAxis:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "Axis %d%c",
 | 
			
		||||
		         src.d.ja.axis, src.d.ja.dir == Negative ? '-' : '+');
 | 
			
		||||
| 
						 | 
				
			
			@ -204,7 +231,8 @@ struct Label : Widget
 | 
			
		|||
	Label(SMP *p, const IntRect &rect,
 | 
			
		||||
	      const char *str, uint8_t r, uint8_t g, uint8_t b)
 | 
			
		||||
	    : Widget(p, rect),
 | 
			
		||||
	      str(str)
 | 
			
		||||
	      str(str),
 | 
			
		||||
	      visible(true)
 | 
			
		||||
	{
 | 
			
		||||
		c.r = r;
 | 
			
		||||
		c.g = g;
 | 
			
		||||
| 
						 | 
				
			
			@ -615,6 +643,21 @@ struct SettingsMenuPrivate
 | 
			
		|||
			desc.d.jb = event.jbutton.button;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case SDL_JOYHATMOTION:
 | 
			
		||||
		{
 | 
			
		||||
			int v = event.jhat.value;
 | 
			
		||||
 | 
			
		||||
			/* Only register if single directional input */
 | 
			
		||||
			if (v != SDL_HAT_LEFT && v != SDL_HAT_RIGHT &&
 | 
			
		||||
			    v != SDL_HAT_UP   && v != SDL_HAT_DOWN)
 | 
			
		||||
				return true;
 | 
			
		||||
 | 
			
		||||
			desc.type = JHat;
 | 
			
		||||
			desc.d.jh.hat = event.jhat.hat;
 | 
			
		||||
			desc.d.jh.pos = v;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case SDL_JOYAXISMOTION:
 | 
			
		||||
		{
 | 
			
		||||
			int v = event.jaxis.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -677,6 +720,9 @@ struct SettingsMenuPrivate
 | 
			
		|||
 | 
			
		||||
		rtData.bindingUpdateMsg.post(binds);
 | 
			
		||||
 | 
			
		||||
		/* Store the key bindings to disk as well to prevent config loss */
 | 
			
		||||
		storeBindings(binds, rtData.config);
 | 
			
		||||
 | 
			
		||||
		destroyReq = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1007,6 +1053,7 @@ bool SettingsMenu::onEvent(const SDL_Event &event)
 | 
			
		|||
 | 
			
		||||
	case SDL_JOYBUTTONDOWN :
 | 
			
		||||
	case SDL_JOYBUTTONUP :
 | 
			
		||||
	case SDL_JOYHATMOTION :
 | 
			
		||||
	case SDL_JOYAXISMOTION :
 | 
			
		||||
		if (!p->hasFocus)
 | 
			
		||||
			return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -1083,6 +1130,7 @@ bool SettingsMenu::onEvent(const SDL_Event &event)
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
	case SDL_JOYBUTTONDOWN:
 | 
			
		||||
	case SDL_JOYHATMOTION:
 | 
			
		||||
	case SDL_JOYAXISMOTION:
 | 
			
		||||
		if (p->state != AwaitingInput)
 | 
			
		||||
			return true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										145
									
								
								src/shader.cpp
									
										
									
									
									
								
							
							
						
						
									
										145
									
								
								src/shader.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -28,25 +28,30 @@
 | 
			
		|||
#include <string.h>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
#include "../sprite.frag.xxd"
 | 
			
		||||
#include "../hue.frag.xxd"
 | 
			
		||||
#include "../trans.frag.xxd"
 | 
			
		||||
#include "../transSimple.frag.xxd"
 | 
			
		||||
#include "../bitmapBlit.frag.xxd"
 | 
			
		||||
#include "../plane.frag.xxd"
 | 
			
		||||
#include "../simple.frag.xxd"
 | 
			
		||||
#include "../simpleColor.frag.xxd"
 | 
			
		||||
#include "../simpleAlpha.frag.xxd"
 | 
			
		||||
#include "../flashMap.frag.xxd"
 | 
			
		||||
#include "../simple.vert.xxd"
 | 
			
		||||
#include "../simpleColor.vert.xxd"
 | 
			
		||||
#include "../sprite.vert.xxd"
 | 
			
		||||
#include "../tilemap.vert.xxd"
 | 
			
		||||
#include "../blur.frag.xxd"
 | 
			
		||||
#include "../simpleMatrix.vert.xxd"
 | 
			
		||||
#include "../blurH.vert.xxd"
 | 
			
		||||
#include "../blurV.vert.xxd"
 | 
			
		||||
#include "../tilemapvx.vert.xxd"
 | 
			
		||||
#include "common.h.xxd"
 | 
			
		||||
#include "sprite.frag.xxd"
 | 
			
		||||
#include "hue.frag.xxd"
 | 
			
		||||
#include "trans.frag.xxd"
 | 
			
		||||
#include "transSimple.frag.xxd"
 | 
			
		||||
#include "bitmapBlit.frag.xxd"
 | 
			
		||||
#include "plane.frag.xxd"
 | 
			
		||||
#include "gray.frag.xxd"
 | 
			
		||||
#include "flatColor.frag.xxd"
 | 
			
		||||
#include "simple.frag.xxd"
 | 
			
		||||
#include "simpleColor.frag.xxd"
 | 
			
		||||
#include "simpleAlpha.frag.xxd"
 | 
			
		||||
#include "simpleAlphaUni.frag.xxd"
 | 
			
		||||
#include "flashMap.frag.xxd"
 | 
			
		||||
#include "minimal.vert.xxd"
 | 
			
		||||
#include "simple.vert.xxd"
 | 
			
		||||
#include "simpleColor.vert.xxd"
 | 
			
		||||
#include "sprite.vert.xxd"
 | 
			
		||||
#include "tilemap.vert.xxd"
 | 
			
		||||
#include "blur.frag.xxd"
 | 
			
		||||
#include "simpleMatrix.vert.xxd"
 | 
			
		||||
#include "blurH.vert.xxd"
 | 
			
		||||
#include "blurV.vert.xxd"
 | 
			
		||||
#include "tilemapvx.vert.xxd"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define INIT_SHADER(vert, frag, name) \
 | 
			
		||||
| 
						 | 
				
			
			@ -106,32 +111,39 @@ void Shader::unbind()
 | 
			
		|||
	glState.program.set(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *glesHeader = "precision mediump float;\n";
 | 
			
		||||
static const size_t glesHeaderSize = strlen(glesHeader);
 | 
			
		||||
 | 
			
		||||
static void setupShaderSource(GLuint shader,
 | 
			
		||||
                              const unsigned char *src, int srcSize)
 | 
			
		||||
static void setupShaderSource(GLuint shader, GLenum type,
 | 
			
		||||
                              const unsigned char *body, int bodySize)
 | 
			
		||||
{
 | 
			
		||||
	GLuint shaderSrcN;
 | 
			
		||||
	const GLchar *shaderSrc[2];
 | 
			
		||||
	GLint shaderSrcSize[2];
 | 
			
		||||
	static const char glesDefine[] = "#define GLSLES\n";
 | 
			
		||||
	static const char fragDefine[] = "#define FRAGMENT_SHADER\n";
 | 
			
		||||
 | 
			
		||||
	const GLchar *shaderSrc[4];
 | 
			
		||||
	GLint shaderSrcSize[4];
 | 
			
		||||
	size_t i = 0;
 | 
			
		||||
 | 
			
		||||
	if (gl.glsles)
 | 
			
		||||
	{
 | 
			
		||||
		shaderSrcN = 2;
 | 
			
		||||
		shaderSrc[0] = glesHeader;
 | 
			
		||||
		shaderSrc[1] = (const GLchar*) src;
 | 
			
		||||
		shaderSrcSize[0] = glesHeaderSize;
 | 
			
		||||
		shaderSrcSize[1] = srcSize;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		shaderSrcN = 1;
 | 
			
		||||
		shaderSrc[0] = (const GLchar*) src;
 | 
			
		||||
		shaderSrcSize[0] = srcSize;
 | 
			
		||||
		shaderSrc[i] = glesDefine;
 | 
			
		||||
		shaderSrcSize[i] = sizeof(glesDefine)-1;
 | 
			
		||||
		++i;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gl.ShaderSource(shader, shaderSrcN, shaderSrc, shaderSrcSize);
 | 
			
		||||
	if (type == GL_FRAGMENT_SHADER)
 | 
			
		||||
	{
 | 
			
		||||
		shaderSrc[i] = fragDefine;
 | 
			
		||||
		shaderSrcSize[i] = sizeof(fragDefine)-1;
 | 
			
		||||
		++i;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	shaderSrc[i] = (const GLchar*) shader_common_h;
 | 
			
		||||
	shaderSrcSize[i] = shader_common_h_len;
 | 
			
		||||
	++i;
 | 
			
		||||
 | 
			
		||||
	shaderSrc[i] = (const GLchar*) body;
 | 
			
		||||
	shaderSrcSize[i] = bodySize;
 | 
			
		||||
	++i;
 | 
			
		||||
 | 
			
		||||
	gl.ShaderSource(shader, i, shaderSrc, shaderSrcSize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Shader::init(const unsigned char *vert, int vertSize,
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +154,7 @@ void Shader::init(const unsigned char *vert, int vertSize,
 | 
			
		|||
	GLint success;
 | 
			
		||||
 | 
			
		||||
	/* Compile vertex shader */
 | 
			
		||||
	setupShaderSource(vertShader, vert, vertSize);
 | 
			
		||||
	setupShaderSource(vertShader, GL_VERTEX_SHADER, vert, vertSize);
 | 
			
		||||
	gl.CompileShader(vertShader);
 | 
			
		||||
 | 
			
		||||
	gl.GetShaderiv(vertShader, GL_COMPILE_STATUS, &success);
 | 
			
		||||
| 
						 | 
				
			
			@ -156,7 +168,7 @@ void Shader::init(const unsigned char *vert, int vertSize,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/* Compile fragment shader */
 | 
			
		||||
	setupShaderSource(fragShader, frag, fragSize);
 | 
			
		||||
	setupShaderSource(fragShader, GL_FRAGMENT_SHADER, frag, fragSize);
 | 
			
		||||
	gl.CompileShader(fragShader);
 | 
			
		||||
 | 
			
		||||
	gl.GetShaderiv(fragShader, GL_COMPILE_STATUS, &success);
 | 
			
		||||
| 
						 | 
				
			
			@ -260,6 +272,21 @@ void ShaderBase::setTranslation(const Vec2i &value)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
FlatColorShader::FlatColorShader()
 | 
			
		||||
{
 | 
			
		||||
	INIT_SHADER(minimal, flatColor, FlatColorShader);
 | 
			
		||||
 | 
			
		||||
	ShaderBase::init();
 | 
			
		||||
 | 
			
		||||
	GET_U(color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FlatColorShader::setColor(const Vec4 &value)
 | 
			
		||||
{
 | 
			
		||||
	setVec4Uniform(u_color, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SimpleShader::SimpleShader()
 | 
			
		||||
{
 | 
			
		||||
	INIT_SHADER(simple, simple, SimpleShader);
 | 
			
		||||
| 
						 | 
				
			
			@ -306,6 +333,27 @@ void SimpleSpriteShader::setSpriteMat(const float value[16])
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
AlphaSpriteShader::AlphaSpriteShader()
 | 
			
		||||
{
 | 
			
		||||
	INIT_SHADER(sprite, simpleAlphaUni, AlphaSpriteShader);
 | 
			
		||||
 | 
			
		||||
	ShaderBase::init();
 | 
			
		||||
 | 
			
		||||
	GET_U(spriteMat);
 | 
			
		||||
	GET_U(alpha);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AlphaSpriteShader::setSpriteMat(const float value[16])
 | 
			
		||||
{
 | 
			
		||||
	gl.UniformMatrix4fv(u_spriteMat, 1, GL_FALSE, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AlphaSpriteShader::setAlpha(float value)
 | 
			
		||||
{
 | 
			
		||||
	gl.Uniform1f(u_alpha, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TransShader::TransShader()
 | 
			
		||||
{
 | 
			
		||||
	INIT_SHADER(simple, trans, TransShader);
 | 
			
		||||
| 
						 | 
				
			
			@ -450,6 +498,21 @@ void PlaneShader::setOpacity(float value)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
GrayShader::GrayShader()
 | 
			
		||||
{
 | 
			
		||||
	INIT_SHADER(simple, gray, GrayShader);
 | 
			
		||||
 | 
			
		||||
	ShaderBase::init();
 | 
			
		||||
 | 
			
		||||
	GET_U(gray);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GrayShader::setGray(float value)
 | 
			
		||||
{
 | 
			
		||||
	gl.Uniform1f(u_gray, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TilemapShader::TilemapShader()
 | 
			
		||||
{
 | 
			
		||||
	INIT_SHADER(tilemap, simple, TilemapShader);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										37
									
								
								src/shader.h
									
										
									
									
									
								
							
							
						
						
									
										37
									
								
								src/shader.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -87,6 +87,17 @@ protected:
 | 
			
		|||
	GLint u_texSizeInv, u_translation;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class FlatColorShader : public ShaderBase
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	FlatColorShader();
 | 
			
		||||
 | 
			
		||||
	void setColor(const Vec4 &value);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	GLint u_color;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class SimpleShader : public ShaderBase
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +132,18 @@ private:
 | 
			
		|||
	GLint u_spriteMat;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class AlphaSpriteShader : public ShaderBase
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	AlphaSpriteShader();
 | 
			
		||||
 | 
			
		||||
	void setSpriteMat(const float value[16]);
 | 
			
		||||
	void setAlpha(float value);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	GLint u_spriteMat, u_alpha;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class TransShader : public ShaderBase
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -179,6 +202,17 @@ private:
 | 
			
		|||
	GLint u_tone, u_color, u_flash, u_opacity;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class GrayShader : public ShaderBase
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	GrayShader();
 | 
			
		||||
 | 
			
		||||
	void setGray(float value);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	GLint u_gray;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class TilemapShader : public ShaderBase
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -273,12 +307,15 @@ private:
 | 
			
		|||
/* Global object containing all available shaders */
 | 
			
		||||
struct ShaderSet
 | 
			
		||||
{
 | 
			
		||||
	FlatColorShader flatColor;
 | 
			
		||||
	SimpleShader simple;
 | 
			
		||||
	SimpleColorShader simpleColor;
 | 
			
		||||
	SimpleAlphaShader simpleAlpha;
 | 
			
		||||
	SimpleSpriteShader simpleSprite;
 | 
			
		||||
	AlphaSpriteShader alphaSprite;
 | 
			
		||||
	SpriteShader sprite;
 | 
			
		||||
	PlaneShader plane;
 | 
			
		||||
	GrayShader gray;
 | 
			
		||||
	TilemapShader tilemap;
 | 
			
		||||
	FlashMapShader flashMap;
 | 
			
		||||
	TransShader trans;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,14 +46,14 @@ SharedState *SharedState::instance = 0;
 | 
			
		|||
int SharedState::rgssVersion = 0;
 | 
			
		||||
static GlobalIBO *_globalIBO = 0;
 | 
			
		||||
 | 
			
		||||
static const char *defGameArchive()
 | 
			
		||||
static const char *gameArchExt()
 | 
			
		||||
{
 | 
			
		||||
	if (rgssVer == 1)
 | 
			
		||||
		return "Game.rgssad";
 | 
			
		||||
		return ".rgssad";
 | 
			
		||||
	else if (rgssVer == 2)
 | 
			
		||||
		return "Game.rgss2a";
 | 
			
		||||
		return ".rgss2a";
 | 
			
		||||
	else if (rgssVer == 3)
 | 
			
		||||
		return "Game.rgss3a";
 | 
			
		||||
		return ".rgss3a";
 | 
			
		||||
 | 
			
		||||
	assert(!"unreachable");
 | 
			
		||||
	return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -88,6 +88,7 @@ struct SharedStatePrivate
 | 
			
		|||
 | 
			
		||||
	TEX::ID globalTex;
 | 
			
		||||
	int globalTexW, globalTexH;
 | 
			
		||||
	bool globalTexDirty;
 | 
			
		||||
 | 
			
		||||
	TEXFBO gpTexFBO;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -107,25 +108,18 @@ struct SharedStatePrivate
 | 
			
		|||
	      midiState(threadData->config),
 | 
			
		||||
	      graphics(threadData),
 | 
			
		||||
	      input(*threadData),
 | 
			
		||||
	      audio(threadData->config),
 | 
			
		||||
	      audio(*threadData),
 | 
			
		||||
	      fontState(threadData->config),
 | 
			
		||||
	      stampCounter(0)
 | 
			
		||||
	{
 | 
			
		||||
		if (!config.gameFolder.empty())
 | 
			
		||||
		{
 | 
			
		||||
			int result = chdir(config.gameFolder.c_str());
 | 
			
		||||
		/* Shaders have been compiled in ShaderSet's constructor */
 | 
			
		||||
		if (gl.ReleaseShaderCompiler)
 | 
			
		||||
			gl.ReleaseShaderCompiler();
 | 
			
		||||
 | 
			
		||||
			if (result != 0)
 | 
			
		||||
				throw Exception(Exception::MKXPError,
 | 
			
		||||
			                    "Unable to switch into gameFolder '%s'",
 | 
			
		||||
			                    config.gameFolder.c_str());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// FIXME find out correct archive filename
 | 
			
		||||
		std::string archPath = defGameArchive();
 | 
			
		||||
		std::string archPath = config.execName + gameArchExt();
 | 
			
		||||
 | 
			
		||||
		/* Check if a game archive exists */
 | 
			
		||||
		FILE *tmp = fopen(archPath.c_str(), "r");
 | 
			
		||||
		FILE *tmp = fopen(archPath.c_str(), "rb");
 | 
			
		||||
		if (tmp)
 | 
			
		||||
		{
 | 
			
		||||
			fileSystem.addPath(archPath.c_str());
 | 
			
		||||
| 
						 | 
				
			
			@ -150,6 +144,7 @@ struct SharedStatePrivate
 | 
			
		|||
		TEX::setRepeat(false);
 | 
			
		||||
		TEX::setSmooth(false);
 | 
			
		||||
		TEX::allocEmpty(globalTexW, globalTexH);
 | 
			
		||||
		globalTexDirty = false;
 | 
			
		||||
 | 
			
		||||
		TEXFBO::init(gpTexFBO);
 | 
			
		||||
		/* Reuse starting values */
 | 
			
		||||
| 
						 | 
				
			
			@ -257,16 +252,27 @@ GlobalIBO &SharedState::globalIBO()
 | 
			
		|||
void SharedState::bindTex()
 | 
			
		||||
{
 | 
			
		||||
	TEX::bind(p->globalTex);
 | 
			
		||||
	TEX::allocEmpty(p->globalTexW, p->globalTexH);
 | 
			
		||||
 | 
			
		||||
	if (p->globalTexDirty)
 | 
			
		||||
	{
 | 
			
		||||
		TEX::allocEmpty(p->globalTexW, p->globalTexH);
 | 
			
		||||
		p->globalTexDirty = false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SharedState::ensureTexSize(int minW, int minH, Vec2i ¤tSizeOut)
 | 
			
		||||
{
 | 
			
		||||
	if (minW > p->globalTexW)
 | 
			
		||||
	{
 | 
			
		||||
		p->globalTexDirty = true;
 | 
			
		||||
		p->globalTexW = findNextPow2(minW);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (minH > p->globalTexH)
 | 
			
		||||
	{
 | 
			
		||||
		p->globalTexDirty = true;
 | 
			
		||||
		p->globalTexH = findNextPow2(minH);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	currentSizeOut = Vec2i(p->globalTexW, p->globalTexH);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,7 @@
 | 
			
		|||
#include "exception.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "debugwriter.h"
 | 
			
		||||
 | 
			
		||||
#include <SDL_sound.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -120,13 +121,16 @@ SoundEmitter::~SoundEmitter()
 | 
			
		|||
 | 
			
		||||
void SoundEmitter::play(const std::string &filename,
 | 
			
		||||
                        int volume,
 | 
			
		||||
					    int pitch)
 | 
			
		||||
                        int pitch)
 | 
			
		||||
{
 | 
			
		||||
	float _volume = clamp<int>(volume, 0, 100) / 100.f;
 | 
			
		||||
	float _pitch  = clamp<int>(pitch, 50, 150) / 100.f;
 | 
			
		||||
 | 
			
		||||
	SoundBuffer *buffer = allocateBuffer(filename);
 | 
			
		||||
 | 
			
		||||
	if (!buffer)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* Try to find first free source */
 | 
			
		||||
	size_t i;
 | 
			
		||||
	for (i = 0; i < srcCount; ++i)
 | 
			
		||||
| 
						 | 
				
			
			@ -168,7 +172,7 @@ void SoundEmitter::play(const std::string &filename,
 | 
			
		|||
	if (switchBuffer)
 | 
			
		||||
		AL::Source::attachBuffer(src, buffer->alBuffer);
 | 
			
		||||
 | 
			
		||||
	AL::Source::setVolume(src, _volume);
 | 
			
		||||
	AL::Source::setVolume(src, _volume * GLOBAL_VOLUME);
 | 
			
		||||
	AL::Source::setPitch(src, _pitch);
 | 
			
		||||
 | 
			
		||||
	AL::Source::play(src);
 | 
			
		||||
| 
						 | 
				
			
			@ -197,18 +201,22 @@ SoundBuffer *SoundEmitter::allocateBuffer(const std::string &filename)
 | 
			
		|||
	{
 | 
			
		||||
		/* Buffer not in cashe, needs to be loaded */
 | 
			
		||||
		SDL_RWops dataSource;
 | 
			
		||||
		const char *extension;
 | 
			
		||||
		char ext[8];
 | 
			
		||||
 | 
			
		||||
		shState->fileSystem().openRead(dataSource, filename.c_str(),
 | 
			
		||||
									   FileSystem::Audio, false, &extension);
 | 
			
		||||
		                               false, ext, sizeof(ext));
 | 
			
		||||
 | 
			
		||||
		Sound_Sample *sampleHandle = Sound_NewSample(&dataSource, extension, 0, STREAM_BUF_SIZE);
 | 
			
		||||
		Sound_Sample *sampleHandle = Sound_NewSample(&dataSource, ext, 0, STREAM_BUF_SIZE);
 | 
			
		||||
 | 
			
		||||
		if (!sampleHandle)
 | 
			
		||||
		{
 | 
			
		||||
			SDL_RWclose(&dataSource);
 | 
			
		||||
			throw Exception(Exception::SDLError, "%s.%s: %s",
 | 
			
		||||
			                filename.c_str(), extension, Sound_GetError());
 | 
			
		||||
			char buf[512];
 | 
			
		||||
			snprintf(buf, sizeof(buf), "Unable to decode sound: %s.%s: %s",
 | 
			
		||||
			         filename.c_str(), ext, Sound_GetError());
 | 
			
		||||
			buf[sizeof(buf)-1] = '\0';
 | 
			
		||||
			Debug() << buf;
 | 
			
		||||
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		uint32_t decBytes = Sound_DecodeAll(sampleHandle);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,7 +57,8 @@ struct SpritePrivate
 | 
			
		|||
	NormValue opacity;
 | 
			
		||||
	BlendType blendType;
 | 
			
		||||
 | 
			
		||||
	SDL_Rect sceneRect;
 | 
			
		||||
	IntRect sceneRect;
 | 
			
		||||
	Vec2i sceneOrig;
 | 
			
		||||
 | 
			
		||||
	/* Would this sprite be visible on
 | 
			
		||||
	 * the screen if drawn? */
 | 
			
		||||
| 
						 | 
				
			
			@ -182,9 +183,8 @@ struct SpritePrivate
 | 
			
		|||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		SDL_Rect self;
 | 
			
		||||
		self.x = trans.getPosition().x - trans.getOrigin().x;
 | 
			
		||||
		self.y = trans.getPosition().y - trans.getOrigin().y;
 | 
			
		||||
		IntRect self;
 | 
			
		||||
		self.setPos(trans.getPositionI() - (trans.getOriginI() + sceneOrig));
 | 
			
		||||
		self.w = bitmap->width();
 | 
			
		||||
		self.h = bitmap->height();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -332,7 +332,7 @@ void Sprite::setBitmap(Bitmap *bitmap)
 | 
			
		|||
 | 
			
		||||
	p->bitmap = bitmap;
 | 
			
		||||
 | 
			
		||||
	if (!bitmap)
 | 
			
		||||
	if (nullOrDisposed(bitmap))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	bitmap->ensureNonMega();
 | 
			
		||||
| 
						 | 
				
			
			@ -515,7 +515,6 @@ void Sprite::draw()
 | 
			
		|||
 | 
			
		||||
	bool renderEffect = p->color->hasEffect() ||
 | 
			
		||||
	                    p->tone->hasEffect()  ||
 | 
			
		||||
	                    p->opacity != 255     ||
 | 
			
		||||
	                    flashing              ||
 | 
			
		||||
	                    p->bushDepth != 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -541,6 +540,16 @@ void Sprite::draw()
 | 
			
		|||
 | 
			
		||||
		base = &shader;
 | 
			
		||||
	}
 | 
			
		||||
	else if (p->opacity != 255)
 | 
			
		||||
	{
 | 
			
		||||
		AlphaSpriteShader &shader = shState->shaders().alphaSprite;
 | 
			
		||||
		shader.bind();
 | 
			
		||||
 | 
			
		||||
		shader.setSpriteMat(p->trans.getMatrix());
 | 
			
		||||
		shader.setAlpha(p->opacity.norm);
 | 
			
		||||
		shader.applyViewportProj();
 | 
			
		||||
		base = &shader;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		SimpleSpriteShader &shader = shState->shaders().simpleSprite;
 | 
			
		||||
| 
						 | 
				
			
			@ -567,13 +576,10 @@ void Sprite::onGeometryChange(const Scene::Geometry &geo)
 | 
			
		|||
{
 | 
			
		||||
	/* Offset at which the sprite will be drawn
 | 
			
		||||
	 * relative to screen origin */
 | 
			
		||||
	int xOffset = geo.rect.x - geo.xOrigin;
 | 
			
		||||
	int yOffset = geo.rect.y - geo.yOrigin;
 | 
			
		||||
	p->trans.setGlobalOffset(geo.offset());
 | 
			
		||||
 | 
			
		||||
	p->trans.setGlobalOffset(xOffset, yOffset);
 | 
			
		||||
 | 
			
		||||
	p->sceneRect.w = geo.rect.w;
 | 
			
		||||
	p->sceneRect.h = geo.rect.h;
 | 
			
		||||
	p->sceneRect.setSize(geo.rect.size());
 | 
			
		||||
	p->sceneOrig = geo.orig;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Sprite::releaseResources()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,94 +30,92 @@
 | 
			
		|||
 | 
			
		||||
/* Init normally */
 | 
			
		||||
Table::Table(int x, int y /*= 1*/, int z /*= 1*/)
 | 
			
		||||
	: m_x(x), m_y(y), m_z(z),
 | 
			
		||||
    : xs(x), ys(y), zs(z),
 | 
			
		||||
      data(x*y*z)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
Table::Table(const Table &other)
 | 
			
		||||
    : m_x(other.m_x), m_y(other.m_y), m_z(other.m_z),
 | 
			
		||||
    : xs(other.xs), ys(other.ys), zs(other.zs),
 | 
			
		||||
      data(other.data)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
int16_t Table::get(int x, int y, int z) const
 | 
			
		||||
{
 | 
			
		||||
	return data[m_x*m_y*z + m_x*y + x];
 | 
			
		||||
	return data[xs*ys*z + xs*y + x];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Table::set(int16_t value, int x, int y, int z)
 | 
			
		||||
{
 | 
			
		||||
	if (x < 0 || x >= m_x
 | 
			
		||||
	||  y < 0 || y >= m_y
 | 
			
		||||
	||  z < 0 || z >= m_z)
 | 
			
		||||
	if (x < 0 || x >= xs
 | 
			
		||||
	||  y < 0 || y >= ys
 | 
			
		||||
	||  z < 0 || z >= zs)
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data[m_x*m_y*z + m_x*y + x] = value;
 | 
			
		||||
	data[xs*ys*z + xs*y + x] = value;
 | 
			
		||||
 | 
			
		||||
	modified();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Table::resize(int x, int y, int z)
 | 
			
		||||
{
 | 
			
		||||
	if (x == m_x && y == m_y && z == m_z)
 | 
			
		||||
	if (x == xs && y == ys && z == zs)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	std::vector<int16_t> newData(x*y*z);
 | 
			
		||||
 | 
			
		||||
	for (int k = 0; k < std::min(z, m_z); ++k)
 | 
			
		||||
		for (int j = 0; j < std::min(y, m_y); ++j)
 | 
			
		||||
			for (int i = 0; i < std::min(x, m_x); ++i)
 | 
			
		||||
	for (int k = 0; k < std::min(z, zs); ++k)
 | 
			
		||||
		for (int j = 0; j < std::min(y, ys); ++j)
 | 
			
		||||
			for (int i = 0; i < std::min(x, xs); ++i)
 | 
			
		||||
				newData[x*y*k + x*j + i] = at(i, j, k);
 | 
			
		||||
 | 
			
		||||
	data.swap(newData);
 | 
			
		||||
 | 
			
		||||
	m_x = x;
 | 
			
		||||
	m_y = y;
 | 
			
		||||
	m_z = z;
 | 
			
		||||
	xs = x;
 | 
			
		||||
	ys = y;
 | 
			
		||||
	zs = z;
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Table::resize(int x, int y)
 | 
			
		||||
{
 | 
			
		||||
	resize(x, y, m_z);
 | 
			
		||||
	resize(x, y, zs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Table::resize(int x)
 | 
			
		||||
{
 | 
			
		||||
	resize(x, m_y, m_z);
 | 
			
		||||
	resize(x, ys, zs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Serializable */
 | 
			
		||||
int Table::serialSize() const
 | 
			
		||||
{
 | 
			
		||||
	/* header + data */
 | 
			
		||||
	return 20 + (m_x * m_y * m_z) * 2;
 | 
			
		||||
	return 20 + (xs * ys * zs) * 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Table::serialize(char *buffer) const
 | 
			
		||||
{
 | 
			
		||||
	char *buff_p = buffer;
 | 
			
		||||
 | 
			
		||||
	/* Table dimensions: we don't care
 | 
			
		||||
	 * about them but RMXP needs them */
 | 
			
		||||
	int dim = 1;
 | 
			
		||||
	int size = m_x * m_y * m_z;
 | 
			
		||||
	int size = xs * ys * zs;
 | 
			
		||||
 | 
			
		||||
	if (m_y > 1)
 | 
			
		||||
	if (ys > 1)
 | 
			
		||||
		dim = 2;
 | 
			
		||||
 | 
			
		||||
	if (m_z > 1)
 | 
			
		||||
	if (zs > 1)
 | 
			
		||||
		dim = 3;
 | 
			
		||||
 | 
			
		||||
	write_int32(&buff_p, dim);
 | 
			
		||||
	write_int32(&buff_p, m_x);
 | 
			
		||||
	write_int32(&buff_p, m_y);
 | 
			
		||||
	write_int32(&buff_p, m_z);
 | 
			
		||||
	write_int32(&buff_p, size);
 | 
			
		||||
	writeInt32(&buffer, dim);
 | 
			
		||||
	writeInt32(&buffer, xs);
 | 
			
		||||
	writeInt32(&buffer, ys);
 | 
			
		||||
	writeInt32(&buffer, zs);
 | 
			
		||||
	writeInt32(&buffer, size);
 | 
			
		||||
 | 
			
		||||
	memcpy(buff_p, dataPtr(data), sizeof(int16_t)*size);
 | 
			
		||||
	memcpy(buffer, dataPtr(data), sizeof(int16_t)*size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -126,13 +124,11 @@ Table *Table::deserialize(const char *data, int len)
 | 
			
		|||
	if (len < 20)
 | 
			
		||||
		throw Exception(Exception::RGSSError, "Marshal: Table: bad file format");
 | 
			
		||||
 | 
			
		||||
	uint idx = 0;
 | 
			
		||||
 | 
			
		||||
	read_int32(data, idx);
 | 
			
		||||
	int x = read_int32(data, idx);
 | 
			
		||||
	int y = read_int32(data, idx);
 | 
			
		||||
	int z = read_int32(data, idx);
 | 
			
		||||
	int size = read_int32(data, idx);
 | 
			
		||||
	readInt32(&data);
 | 
			
		||||
	int x = readInt32(&data);
 | 
			
		||||
	int y = readInt32(&data);
 | 
			
		||||
	int z = readInt32(&data);
 | 
			
		||||
	int size = readInt32(&data);
 | 
			
		||||
 | 
			
		||||
	if (size != x*y*z)
 | 
			
		||||
		throw Exception(Exception::RGSSError, "Marshal: Table: bad file format");
 | 
			
		||||
| 
						 | 
				
			
			@ -141,7 +137,7 @@ Table *Table::deserialize(const char *data, int len)
 | 
			
		|||
		throw Exception(Exception::RGSSError, "Marshal: Table: bad file format");
 | 
			
		||||
 | 
			
		||||
	Table *t = new Table(x, y, z);
 | 
			
		||||
	memcpy(dataPtr(t->data), &data[idx], sizeof(int16_t)*size);
 | 
			
		||||
	memcpy(dataPtr(t->data), data, sizeof(int16_t)*size);
 | 
			
		||||
 | 
			
		||||
	return t;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								src/table.h
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								src/table.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -36,9 +36,9 @@ public:
 | 
			
		|||
	Table(const Table &other);
 | 
			
		||||
	virtual ~Table() {}
 | 
			
		||||
 | 
			
		||||
	int xSize() const { return m_x; }
 | 
			
		||||
	int ySize() const { return m_y; }
 | 
			
		||||
	int zSize() const { return m_z; }
 | 
			
		||||
	int xSize() const { return xs; }
 | 
			
		||||
	int ySize() const { return ys; }
 | 
			
		||||
	int zSize() const { return zs; }
 | 
			
		||||
 | 
			
		||||
	int16_t get(int x, int y = 0, int z = 0) const;
 | 
			
		||||
	void set(int16_t value, int x, int y = 0, int z = 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -54,18 +54,18 @@ public:
 | 
			
		|||
	/* <internal */
 | 
			
		||||
	inline int16_t &at(int x, int y = 0, int z = 0)
 | 
			
		||||
	{
 | 
			
		||||
		return data[m_x*m_y*z + m_x*y + x];
 | 
			
		||||
		return data[xs*ys*z + xs*y + x];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline const int16_t &at(int x, int y = 0, int z = 0) const
 | 
			
		||||
	{
 | 
			
		||||
		return data[m_x*m_y*z + m_x*y + x];
 | 
			
		||||
		return data[xs*ys*z + xs*y + x];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sigc::signal<void> modified;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	int m_x, m_y, m_z;
 | 
			
		||||
	int xs, ys, zs;
 | 
			
		||||
	std::vector<int16_t> data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@
 | 
			
		|||
 | 
			
		||||
#include "tileatlasvx.h"
 | 
			
		||||
 | 
			
		||||
#include "tilemap-common.h"
 | 
			
		||||
#include "bitmap.h"
 | 
			
		||||
#include "table.h"
 | 
			
		||||
#include "etc-internal.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -65,21 +66,6 @@ static elementsN(autotileVXRectsC);
 | 
			
		|||
namespace TileAtlasVX
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
wrap(int value, int range)
 | 
			
		||||
{
 | 
			
		||||
	int res = value % range;
 | 
			
		||||
	return res < 0 ? res + range : res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int16_t
 | 
			
		||||
tableGetWrapped(const Table &t, int x, int y, int z = 0)
 | 
			
		||||
{
 | 
			
		||||
	return t.at(wrap(x, t.xSize()),
 | 
			
		||||
	            wrap(y, t.ySize()),
 | 
			
		||||
	            z);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int16_t
 | 
			
		||||
tableGetSafe(const Table *t, int x)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -333,35 +319,6 @@ void build(TEXFBO &tf, Bitmap *bitmaps[BM_COUNT])
 | 
			
		|||
#define OVER_PLAYER_FLAG (1 << 4)
 | 
			
		||||
#define TABLE_FLAG       (1 << 7)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
atSelectSubPos(FloatRect &pos, int i)
 | 
			
		||||
{
 | 
			
		||||
	switch (i)
 | 
			
		||||
	{
 | 
			
		||||
	case 0:
 | 
			
		||||
		return;
 | 
			
		||||
	case 1:
 | 
			
		||||
		pos.x += 16;
 | 
			
		||||
		return;
 | 
			
		||||
	case 2:
 | 
			
		||||
		pos.y += 16;
 | 
			
		||||
		return;
 | 
			
		||||
	case 3:
 | 
			
		||||
		pos.x += 16;
 | 
			
		||||
		pos.y += 16;
 | 
			
		||||
		return;
 | 
			
		||||
	case 4:
 | 
			
		||||
		pos.y += 24;
 | 
			
		||||
		return;
 | 
			
		||||
	case 5:
 | 
			
		||||
		pos.x += 16;
 | 
			
		||||
		pos.y += 24;
 | 
			
		||||
		return;
 | 
			
		||||
	default:
 | 
			
		||||
		assert(!"Unreachable");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Reference: http://www.tktkgame.com/tkool/memo/vx/tile_id.html */
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
/*
 | 
			
		||||
** flashmap.h
 | 
			
		||||
** tilemap-common.h
 | 
			
		||||
**
 | 
			
		||||
** This file is part of mkxp.
 | 
			
		||||
**
 | 
			
		||||
| 
						 | 
				
			
			@ -19,8 +19,8 @@
 | 
			
		|||
** along with mkxp.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef FLASHMAP_H
 | 
			
		||||
#define FLASHMAP_H
 | 
			
		||||
#ifndef TILEMAPCOMMON_H
 | 
			
		||||
#define TILEMAPCOMMON_H
 | 
			
		||||
 | 
			
		||||
#include "table.h"
 | 
			
		||||
#include "gl-util.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -30,8 +30,11 @@
 | 
			
		|||
#include "glstate.h"
 | 
			
		||||
#include "shader.h"
 | 
			
		||||
#include "vertex.h"
 | 
			
		||||
#include "quad.h"
 | 
			
		||||
#include "etc-internal.h"
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include <sigc++/connection.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -44,11 +47,50 @@ wrap(int value, int range)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static inline int16_t
 | 
			
		||||
tableGetWrapped(const Table *t, int x, int y, int z = 0)
 | 
			
		||||
tableGetWrapped(const Table &t, int x, int y, int z = 0)
 | 
			
		||||
{
 | 
			
		||||
	return t->get(wrap(x, t->xSize()),
 | 
			
		||||
	              wrap(y, t->ySize()),
 | 
			
		||||
	              z);
 | 
			
		||||
	return t.get(wrap(x, t.xSize()),
 | 
			
		||||
	             wrap(y, t.ySize()),
 | 
			
		||||
	             z);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum AtSubPos
 | 
			
		||||
{
 | 
			
		||||
	TopLeft          = 0,
 | 
			
		||||
	TopRight         = 1,
 | 
			
		||||
	BottomLeft       = 2,
 | 
			
		||||
	BottomRight      = 3,
 | 
			
		||||
	BottomLeftTable  = 4,
 | 
			
		||||
	BottomRightTable = 5
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
atSelectSubPos(FloatRect &pos, int i)
 | 
			
		||||
{
 | 
			
		||||
	switch (i)
 | 
			
		||||
	{
 | 
			
		||||
	case TopLeft:
 | 
			
		||||
		return;
 | 
			
		||||
	case TopRight:
 | 
			
		||||
		pos.x += 16;
 | 
			
		||||
		return;
 | 
			
		||||
	case BottomLeft:
 | 
			
		||||
		pos.y += 16;
 | 
			
		||||
		return;
 | 
			
		||||
	case BottomRight:
 | 
			
		||||
		pos.x += 16;
 | 
			
		||||
		pos.y += 16;
 | 
			
		||||
		return;
 | 
			
		||||
	case BottomLeftTable:
 | 
			
		||||
		pos.y += 24;
 | 
			
		||||
		return;
 | 
			
		||||
	case BottomRightTable:
 | 
			
		||||
		pos.x += 16;
 | 
			
		||||
		pos.y += 24;
 | 
			
		||||
		return;
 | 
			
		||||
	default:
 | 
			
		||||
		assert(!"Unreachable");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct FlashMap
 | 
			
		||||
| 
						 | 
				
			
			@ -144,7 +186,7 @@ private:
 | 
			
		|||
 | 
			
		||||
	bool sampleFlashColor(Vec4 &out, int x, int y) const
 | 
			
		||||
	{
 | 
			
		||||
		int16_t packed = tableGetWrapped(data, x, y);
 | 
			
		||||
		int16_t packed = tableGetWrapped(*data, x, y);
 | 
			
		||||
 | 
			
		||||
		if (packed == 0)
 | 
			
		||||
			return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -216,4 +258,4 @@ private:
 | 
			
		|||
	std::vector<CVertex> vertices;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // FLASHMAP_H
 | 
			
		||||
#endif // TILEMAPCOMMON_H
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +26,7 @@
 | 
			
		|||
#include "table.h"
 | 
			
		||||
 | 
			
		||||
#include "sharedstate.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "glstate.h"
 | 
			
		||||
#include "gl-util.h"
 | 
			
		||||
#include "gl-meta.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +37,7 @@
 | 
			
		|||
#include "quad.h"
 | 
			
		||||
#include "vertex.h"
 | 
			
		||||
#include "tileatlas.h"
 | 
			
		||||
#include "flashmap.h"
 | 
			
		||||
#include "tilemap-common.h"
 | 
			
		||||
 | 
			
		||||
#include <sigc++/connection.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -441,15 +442,13 @@ struct TilemapPrivate
 | 
			
		|||
 | 
			
		||||
	void updateSceneGeometry(const Scene::Geometry &geo)
 | 
			
		||||
	{
 | 
			
		||||
		elem.sceneOffset.x = geo.rect.x - geo.xOrigin;
 | 
			
		||||
		elem.sceneOffset.y = geo.rect.y - geo.yOrigin;
 | 
			
		||||
		elem.sceneOffset = geo.offset();
 | 
			
		||||
		elem.sceneGeo = geo;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void updatePosition()
 | 
			
		||||
	{
 | 
			
		||||
		dispPos.x = -(offset.x - viewpPos.x * 32) + elem.sceneOffset.x;
 | 
			
		||||
		dispPos.y = -(offset.y - viewpPos.y * 32) + elem.sceneOffset.y;
 | 
			
		||||
		dispPos = -(offset - viewpPos * 32) + elem.sceneOffset;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void invalidateAtlasSize()
 | 
			
		||||
| 
						 | 
				
			
			@ -542,19 +541,59 @@ struct TilemapPrivate
 | 
			
		|||
		if (tileset->megaSurface())
 | 
			
		||||
		{
 | 
			
		||||
			/* Mega surface tileset */
 | 
			
		||||
			TEX::bind(atlas.gl.tex);
 | 
			
		||||
 | 
			
		||||
			SDL_Surface *tsSurf = tileset->megaSurface();
 | 
			
		||||
 | 
			
		||||
			for (size_t i = 0; i < blits.size(); ++i)
 | 
			
		||||
			if (shState->config().subImageFix)
 | 
			
		||||
			{
 | 
			
		||||
				const TileAtlas::Blit &blitOp = blits[i];
 | 
			
		||||
				/* Implementation for broken GL drivers */
 | 
			
		||||
				FBO::bind(atlas.gl.fbo);
 | 
			
		||||
				glState.blend.pushSet(false);
 | 
			
		||||
				glState.viewport.pushSet(IntRect(0, 0, atlas.size.x, atlas.size.y));
 | 
			
		||||
 | 
			
		||||
				GLMeta::subRectImageUpload(tsSurf->w, blitOp.src.x, blitOp.src.y,
 | 
			
		||||
				                           blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h, tsSurf, GL_RGBA);
 | 
			
		||||
				SimpleShader &shader = shState->shaders().simple;
 | 
			
		||||
				shader.bind();
 | 
			
		||||
				shader.applyViewportProj();
 | 
			
		||||
				shader.setTranslation(Vec2i());
 | 
			
		||||
 | 
			
		||||
				Quad &quad = shState->gpQuad();
 | 
			
		||||
 | 
			
		||||
				for (size_t i = 0; i < blits.size(); ++i)
 | 
			
		||||
				{
 | 
			
		||||
					const TileAtlas::Blit &blitOp = blits[i];
 | 
			
		||||
 | 
			
		||||
					Vec2i texSize;
 | 
			
		||||
					shState->ensureTexSize(tsLaneW, blitOp.h, texSize);
 | 
			
		||||
					shState->bindTex();
 | 
			
		||||
					GLMeta::subRectImageUpload(tsSurf->w, blitOp.src.x, blitOp.src.y,
 | 
			
		||||
					                           0, 0, tsLaneW, blitOp.h, tsSurf, GL_RGBA);
 | 
			
		||||
 | 
			
		||||
					shader.setTexSize(texSize);
 | 
			
		||||
					quad.setTexRect(FloatRect(0, 0, tsLaneW, blitOp.h));
 | 
			
		||||
					quad.setPosRect(FloatRect(blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h));
 | 
			
		||||
 | 
			
		||||
					quad.draw();
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				GLMeta::subRectImageEnd();
 | 
			
		||||
				glState.viewport.pop();
 | 
			
		||||
				glState.blend.pop();
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				/* Clean implementation */
 | 
			
		||||
				TEX::bind(atlas.gl.tex);
 | 
			
		||||
 | 
			
		||||
				for (size_t i = 0; i < blits.size(); ++i)
 | 
			
		||||
				{
 | 
			
		||||
					const TileAtlas::Blit &blitOp = blits[i];
 | 
			
		||||
 | 
			
		||||
					GLMeta::subRectImageUpload(tsSurf->w, blitOp.src.x, blitOp.src.y,
 | 
			
		||||
					                           blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h, tsSurf, GL_RGBA);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				GLMeta::subRectImageEnd();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			GLMeta::subRectImageEnd();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -590,21 +629,6 @@ struct TilemapPrivate
 | 
			
		|||
		return value;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	FloatRect getAutotilePieceRect(int x, int y, /* in pixel coords */
 | 
			
		||||
	                               int corner)
 | 
			
		||||
	{
 | 
			
		||||
		switch (corner)
 | 
			
		||||
		{
 | 
			
		||||
		case 0 : break;
 | 
			
		||||
		case 1 : x += 16; break;
 | 
			
		||||
		case 2 : x += 16; y += 16; break;
 | 
			
		||||
		case 3 : y += 16; break;
 | 
			
		||||
		default: abort();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return FloatRect(x, y, 16, 16);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void handleAutotile(int x, int y, int tileInd, SVVector *array)
 | 
			
		||||
	{
 | 
			
		||||
		/* Which autotile [0-7] */
 | 
			
		||||
| 
						 | 
				
			
			@ -617,7 +641,9 @@ struct TilemapPrivate
 | 
			
		|||
		/* Iterate over the 4 tile pieces */
 | 
			
		||||
		for (int i = 0; i < 4; ++i)
 | 
			
		||||
		{
 | 
			
		||||
			FloatRect posRect = getAutotilePieceRect(x*32, y*32, i);
 | 
			
		||||
			FloatRect posRect(x*32, y*32, 16, 16);
 | 
			
		||||
			atSelectSubPos(posRect, i);
 | 
			
		||||
 | 
			
		||||
			FloatRect texRect = pieceRect[i];
 | 
			
		||||
 | 
			
		||||
			/* Adjust to atlas coordinates */
 | 
			
		||||
| 
						 | 
				
			
			@ -635,7 +661,7 @@ struct TilemapPrivate
 | 
			
		|||
	void handleTile(int x, int y, int z)
 | 
			
		||||
	{
 | 
			
		||||
		int tileInd =
 | 
			
		||||
			tableGetWrapped(mapData, x + viewpPos.x, y + viewpPos.y, z);
 | 
			
		||||
			tableGetWrapped(*mapData, x + viewpPos.x, y + viewpPos.y, z);
 | 
			
		||||
 | 
			
		||||
		/* Check for empty space */
 | 
			
		||||
		if (tileInd < 48)
 | 
			
		||||
| 
						 | 
				
			
			@ -972,6 +998,9 @@ void GroundLayer::updateVboCount()
 | 
			
		|||
 | 
			
		||||
void GroundLayer::draw()
 | 
			
		||||
{
 | 
			
		||||
	if (p->groundVert.size() == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	ShaderBase *shader;
 | 
			
		||||
 | 
			
		||||
	p->bindShader(shader);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,7 +33,7 @@
 | 
			
		|||
#include "quad.h"
 | 
			
		||||
#include "quadarray.h"
 | 
			
		||||
#include "shader.h"
 | 
			
		||||
#include "flashmap.h"
 | 
			
		||||
#include "tilemap-common.h"
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <sigc++/connection.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -366,11 +366,10 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
 | 
			
		|||
 | 
			
		||||
	void onGeometryChange(const Scene::Geometry &geo)
 | 
			
		||||
	{
 | 
			
		||||
		mapViewp.w = (geo.rect.w / 32) + !!(geo.rect.w % 32) + 1;
 | 
			
		||||
		mapViewp.h = (geo.rect.h / 32) + !!(geo.rect.h % 32) + 1;
 | 
			
		||||
		const Vec2i geoSize = geo.rect.size();
 | 
			
		||||
		mapViewp.setSize((geoSize / 32) + !!(geoSize % 32) + Vec2i(1));
 | 
			
		||||
 | 
			
		||||
		sceneOffset.x = geo.rect.x - geo.xOrigin;
 | 
			
		||||
		sceneOffset.y = geo.rect.y - geo.yOrigin;
 | 
			
		||||
		sceneOffset = geo.offset();
 | 
			
		||||
		sceneGeo = geo;
 | 
			
		||||
 | 
			
		||||
		buffersDirty = true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,7 +58,6 @@ public:
 | 
			
		|||
	Transform()
 | 
			
		||||
	    : scale(1, 1),
 | 
			
		||||
	      rotation(0),
 | 
			
		||||
	      xOffset(0), yOffset(0),
 | 
			
		||||
	      dirty(true)
 | 
			
		||||
	{
 | 
			
		||||
		memset(matrix, 0, sizeof(matrix));
 | 
			
		||||
| 
						 | 
				
			
			@ -68,38 +67,47 @@ public:
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	Vec2 &getPosition() { return position; }
 | 
			
		||||
	Vec2 &getScale()    { return scale;    }
 | 
			
		||||
	Vec2 &getOrigin()   { return origin;   }
 | 
			
		||||
	Vec2 &getScale()    { return scale;    }
 | 
			
		||||
	float getRotation() { return rotation; }
 | 
			
		||||
 | 
			
		||||
	Vec2i getPositionI() const
 | 
			
		||||
	{
 | 
			
		||||
		return Vec2i(position.x, position.y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vec2i getOriginI() const
 | 
			
		||||
	{
 | 
			
		||||
		return Vec2i(origin.x, origin.y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setPosition(const Vec2 &value)
 | 
			
		||||
	{
 | 
			
		||||
		position = value;
 | 
			
		||||
		dirty = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setScale(const Vec2 &value)
 | 
			
		||||
	{
 | 
			
		||||
		scale = value;
 | 
			
		||||
		dirty = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setOrigin(const Vec2 &value)
 | 
			
		||||
	{
 | 
			
		||||
		origin = value;
 | 
			
		||||
		dirty = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setScale(const Vec2 &value)
 | 
			
		||||
	{
 | 
			
		||||
		scale = value;
 | 
			
		||||
		dirty = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setRotation(float value)
 | 
			
		||||
	{
 | 
			
		||||
		rotation = value;
 | 
			
		||||
		dirty = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setGlobalOffset(int x, int y)
 | 
			
		||||
	void setGlobalOffset(const Vec2i &value)
 | 
			
		||||
	{
 | 
			
		||||
		xOffset = x;
 | 
			
		||||
		yOffset = y;
 | 
			
		||||
		offset = value;
 | 
			
		||||
		dirty = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -129,8 +137,8 @@ private:
 | 
			
		|||
		float syc    = scale.y * cosine;
 | 
			
		||||
		float sxs    = scale.x * sine;
 | 
			
		||||
		float sys    = scale.y * sine;
 | 
			
		||||
		float tx     = -origin.x * sxc - origin.y * sys + position.x + xOffset;
 | 
			
		||||
		float ty     =  origin.x * sxs - origin.y * syc + position.y + yOffset;
 | 
			
		||||
		float tx     = -origin.x * sxc - origin.y * sys + position.x + offset.x;
 | 
			
		||||
		float ty     =  origin.x * sxs - origin.y * syc + position.y + offset.y;
 | 
			
		||||
 | 
			
		||||
		matrix[0]  =  sxc;
 | 
			
		||||
		matrix[1]  = -sxs;
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +154,7 @@ private:
 | 
			
		|||
	float rotation;
 | 
			
		||||
 | 
			
		||||
	/* Silently added to position */
 | 
			
		||||
	int xOffset, yOffset;
 | 
			
		||||
	Vec2i offset;
 | 
			
		||||
 | 
			
		||||
	float matrix[16];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,7 +66,7 @@ findNextPow2(int start)
 | 
			
		|||
inline bool readFile(const char *path,
 | 
			
		||||
                     std::string &out)
 | 
			
		||||
{
 | 
			
		||||
	FILE *f = fopen(path, "r");
 | 
			
		||||
	FILE *f = fopen(path, "rb");
 | 
			
		||||
 | 
			
		||||
	if (!f)
 | 
			
		||||
		return false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -144,8 +144,8 @@ void Viewport::update()
 | 
			
		|||
	Flashable::update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEF_ATTR_RD_SIMPLE(Viewport, OX,   int,   geometry.xOrigin)
 | 
			
		||||
DEF_ATTR_RD_SIMPLE(Viewport, OY,   int,   geometry.yOrigin)
 | 
			
		||||
DEF_ATTR_RD_SIMPLE(Viewport, OX,   int,   geometry.orig.x)
 | 
			
		||||
DEF_ATTR_RD_SIMPLE(Viewport, OY,   int,   geometry.orig.y)
 | 
			
		||||
 | 
			
		||||
DEF_ATTR_SIMPLE(Viewport, Rect,  Rect&,  *p->rect)
 | 
			
		||||
DEF_ATTR_SIMPLE(Viewport, Color, Color&, *p->color)
 | 
			
		||||
| 
						 | 
				
			
			@ -155,10 +155,10 @@ void Viewport::setOX(int value)
 | 
			
		|||
{
 | 
			
		||||
	guardDisposed();
 | 
			
		||||
 | 
			
		||||
	if (geometry.xOrigin == value)
 | 
			
		||||
	if (geometry.orig.x == value)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	geometry.xOrigin = value;
 | 
			
		||||
	geometry.orig.x = value;
 | 
			
		||||
	notifyGeometryChange();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -166,10 +166,10 @@ void Viewport::setOY(int value)
 | 
			
		|||
{
 | 
			
		||||
	guardDisposed();
 | 
			
		||||
 | 
			
		||||
	if (geometry.yOrigin == value)
 | 
			
		||||
	if (geometry.orig.y == value)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	geometry.yOrigin = value;
 | 
			
		||||
	geometry.orig.y = value;
 | 
			
		||||
	notifyGeometryChange();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -471,16 +471,15 @@ struct WindowPrivate
 | 
			
		|||
			i += TileQuads::buildFrame(effectRect, cursorVert.vert);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Scroll arrows */
 | 
			
		||||
		int scrollLRY = (size.y - 16) / 2;
 | 
			
		||||
		int scrollTBX = (size.x - 16) / 2;
 | 
			
		||||
		/* Scroll arrow position: Top Bottom X, Left Right Y */
 | 
			
		||||
		const Vec2i scroll = (size - Vec2i(16)) / 2;
 | 
			
		||||
 | 
			
		||||
		Sides<IntRect> scrollArrows;
 | 
			
		||||
 | 
			
		||||
		scrollArrows.l = IntRect(4, scrollLRY, 8, 16);
 | 
			
		||||
		scrollArrows.r = IntRect(size.x - 12, scrollLRY, 8, 16);
 | 
			
		||||
		scrollArrows.t = IntRect(scrollTBX, 4, 16, 8);
 | 
			
		||||
		scrollArrows.b = IntRect(scrollTBX, size.y - 12, 16, 8);
 | 
			
		||||
		scrollArrows.l = IntRect(4, scroll.y, 8, 16);
 | 
			
		||||
		scrollArrows.r = IntRect(size.x - 12, scroll.y, 8, 16);
 | 
			
		||||
		scrollArrows.t = IntRect(scroll.x, 4, 16, 8);
 | 
			
		||||
		scrollArrows.b = IntRect(scroll.x, size.y - 12, 16, 8);
 | 
			
		||||
 | 
			
		||||
		if (contents)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -557,13 +556,10 @@ struct WindowPrivate
 | 
			
		|||
		if (size == Vec2i(0, 0))
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		Vec2i trans(position.x + sceneOffset.x,
 | 
			
		||||
		            position.y + sceneOffset.y);
 | 
			
		||||
 | 
			
		||||
		SimpleAlphaShader &shader = shState->shaders().simpleAlpha;
 | 
			
		||||
		shader.bind();
 | 
			
		||||
		shader.applyViewportProj();
 | 
			
		||||
		shader.setTranslation(trans);
 | 
			
		||||
		shader.setTranslation(position + sceneOffset);
 | 
			
		||||
 | 
			
		||||
		if (useBaseTex)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -598,12 +594,11 @@ struct WindowPrivate
 | 
			
		|||
			controlsVertDirty = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Actual on screen coordinates */
 | 
			
		||||
		int effectX = position.x + sceneOffset.x;
 | 
			
		||||
		int effectY = position.y + sceneOffset.y;
 | 
			
		||||
		/* Effective on screen coordinates */
 | 
			
		||||
		const Vec2i efPos = position + sceneOffset;
 | 
			
		||||
 | 
			
		||||
		IntRect windowRect(effectX, effectY, size.x, size.y);
 | 
			
		||||
		IntRect contentsRect(effectX+16, effectY+16, size.x-32, size.y-32);
 | 
			
		||||
		const IntRect windowRect(efPos, size);
 | 
			
		||||
		const IntRect contentsRect(efPos + Vec2i(16), size - Vec2i(32));
 | 
			
		||||
 | 
			
		||||
		glState.scissorTest.pushSet(true);
 | 
			
		||||
		glState.scissorBox.push();
 | 
			
		||||
| 
						 | 
				
			
			@ -615,7 +610,7 @@ struct WindowPrivate
 | 
			
		|||
 | 
			
		||||
		if (!nullOrDisposed(windowskin))
 | 
			
		||||
		{
 | 
			
		||||
			shader.setTranslation(Vec2i(effectX, effectY));
 | 
			
		||||
			shader.setTranslation(efPos);
 | 
			
		||||
 | 
			
		||||
			/* Draw arrows / cursors */
 | 
			
		||||
			windowskin->bindTex(shader);
 | 
			
		||||
| 
						 | 
				
			
			@ -631,9 +626,7 @@ struct WindowPrivate
 | 
			
		|||
			/* Draw contents bitmap */
 | 
			
		||||
			glState.scissorBox.setIntersect(contentsRect);
 | 
			
		||||
 | 
			
		||||
			effectX += 16-contentsOffset.x;
 | 
			
		||||
			effectY += 16-contentsOffset.y;
 | 
			
		||||
			shader.setTranslation(Vec2i(effectX, effectY));
 | 
			
		||||
			shader.setTranslation(efPos + (Vec2i(16) - contentsOffset));
 | 
			
		||||
 | 
			
		||||
			contents->bindTex(shader);
 | 
			
		||||
			contentsQuad.draw();
 | 
			
		||||
| 
						 | 
				
			
			@ -727,7 +720,7 @@ void Window::setWindowskin(Bitmap *value)
 | 
			
		|||
 | 
			
		||||
	p->windowskin = value;
 | 
			
		||||
 | 
			
		||||
	if (!value)
 | 
			
		||||
	if (nullOrDisposed(value))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	value->ensureNonMega();
 | 
			
		||||
| 
						 | 
				
			
			@ -743,7 +736,7 @@ void Window::setContents(Bitmap *value)
 | 
			
		|||
	p->contents = value;
 | 
			
		||||
	p->controlsVertDirty = true;
 | 
			
		||||
 | 
			
		||||
	if (!value)
 | 
			
		||||
	if (nullOrDisposed(value))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	value->ensureNonMega();
 | 
			
		||||
| 
						 | 
				
			
			@ -876,8 +869,7 @@ void Window::draw()
 | 
			
		|||
 | 
			
		||||
void Window::onGeometryChange(const Scene::Geometry &geo)
 | 
			
		||||
{
 | 
			
		||||
	p->sceneOffset.x = geo.rect.x - geo.xOrigin;
 | 
			
		||||
	p->sceneOffset.y = geo.rect.y - geo.yOrigin;
 | 
			
		||||
	p->sceneOffset = geo.offset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Window::setZ(int value)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -506,15 +506,15 @@ struct WindowVXPrivate
 | 
			
		|||
 | 
			
		||||
	void rebuildCtrlVert()
 | 
			
		||||
	{
 | 
			
		||||
		const int arrowTBX = (geo.w - 16) / 2;
 | 
			
		||||
		const int arrowLRY = (geo.h - 16) / 2;
 | 
			
		||||
		/* Scroll arrow position: Top Bottom X, Left Right Y */
 | 
			
		||||
		const Vec2i arrow = (geo.size() - Vec2i(16)) / 2;
 | 
			
		||||
 | 
			
		||||
		const Sides<FloatRect> arrowPos =
 | 
			
		||||
		{
 | 
			
		||||
			FloatRect(          4,   arrowLRY, 8, 16 ), /* Left */
 | 
			
		||||
			FloatRect( geo.w - 12,   arrowLRY, 8, 16 ), /* Right */
 | 
			
		||||
			FloatRect(   arrowTBX,          4, 16, 8 ), /* Top */
 | 
			
		||||
			FloatRect(   arrowTBX, geo.h - 12, 16, 8 )  /* Bottom */
 | 
			
		||||
			FloatRect(          4,    arrow.y, 8, 16 ), /* Left */
 | 
			
		||||
			FloatRect( geo.w - 12,    arrow.y, 8, 16 ), /* Right */
 | 
			
		||||
			FloatRect(    arrow.x,          4, 16, 8 ), /* Top */
 | 
			
		||||
			FloatRect(    arrow.x, geo.h - 12, 16, 8 )  /* Bottom */
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		size_t i = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -538,7 +538,7 @@ struct WindowVXPrivate
 | 
			
		|||
 | 
			
		||||
		if (pause)
 | 
			
		||||
		{
 | 
			
		||||
			const FloatRect pausePos(arrowTBX, geo.h - 16, 16, 16);
 | 
			
		||||
			const FloatRect pausePos(arrow.x, geo.h - 16, 16, 16);
 | 
			
		||||
			pauseVert = &vert[i*4];
 | 
			
		||||
 | 
			
		||||
			i += Quad::setTexPosRect(&vert[i*4], pauseSrc[0], pausePos);
 | 
			
		||||
| 
						 | 
				
			
			@ -730,8 +730,7 @@ struct WindowVXPrivate
 | 
			
		|||
		bool windowskinValid = !nullOrDisposed(windowskin);
 | 
			
		||||
		bool contentsValid = !nullOrDisposed(contents);
 | 
			
		||||
 | 
			
		||||
		Vec2i trans(geo.x + sceneOffset.x,
 | 
			
		||||
		            geo.y + sceneOffset.y);
 | 
			
		||||
		Vec2i trans = geo.pos() + sceneOffset;
 | 
			
		||||
 | 
			
		||||
		SimpleAlphaShader &shader = shState->shaders().simpleAlpha;
 | 
			
		||||
		shader.bind();
 | 
			
		||||
| 
						 | 
				
			
			@ -764,8 +763,7 @@ struct WindowVXPrivate
 | 
			
		|||
		{
 | 
			
		||||
			/* Translate cliprect from local into screen space */
 | 
			
		||||
			IntRect clip = clipRect;
 | 
			
		||||
			clip.x += trans.x;
 | 
			
		||||
			clip.y += trans.y;
 | 
			
		||||
			clip.setPos(clip.pos() + trans);
 | 
			
		||||
 | 
			
		||||
			glState.scissorBox.push();
 | 
			
		||||
			glState.scissorTest.pushSet(true);
 | 
			
		||||
| 
						 | 
				
			
			@ -773,11 +771,10 @@ struct WindowVXPrivate
 | 
			
		|||
			if (rgssVer >= 3)
 | 
			
		||||
				glState.scissorBox.setIntersect(clip);
 | 
			
		||||
			else
 | 
			
		||||
				glState.scissorBox.setIntersect(IntRect(trans.x, trans.y, geo.w, geo.h));
 | 
			
		||||
				glState.scissorBox.setIntersect(IntRect(trans, geo.size()));
 | 
			
		||||
 | 
			
		||||
			IntRect pad = padRect;
 | 
			
		||||
			pad.x += trans.x;
 | 
			
		||||
			pad.y += trans.y;
 | 
			
		||||
			pad.setPos(pad.pos() + trans);
 | 
			
		||||
 | 
			
		||||
			if (drawCursor)
 | 
			
		||||
			{
 | 
			
		||||
| 
						 | 
				
			
			@ -786,10 +783,7 @@ struct WindowVXPrivate
 | 
			
		|||
				contTrans.y += cursorRect->y;
 | 
			
		||||
 | 
			
		||||
				if (rgssVer >= 3)
 | 
			
		||||
				{
 | 
			
		||||
					contTrans.x -= contentsOff.x;
 | 
			
		||||
					contTrans.y -= contentsOff.y;
 | 
			
		||||
				}
 | 
			
		||||
					contTrans -= contentsOff;
 | 
			
		||||
 | 
			
		||||
				shader.setTranslation(contTrans);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -804,8 +798,7 @@ struct WindowVXPrivate
 | 
			
		|||
					glState.scissorBox.setIntersect(clip);
 | 
			
		||||
 | 
			
		||||
				Vec2i contTrans = pad.pos();
 | 
			
		||||
				contTrans.x -= contentsOff.x;
 | 
			
		||||
				contTrans.y -= contentsOff.y;
 | 
			
		||||
				contTrans -= contentsOff;
 | 
			
		||||
				shader.setTranslation(contTrans);
 | 
			
		||||
 | 
			
		||||
				TEX::setSmooth(false); // XXX
 | 
			
		||||
| 
						 | 
				
			
			@ -921,6 +914,9 @@ void WindowVX::setContents(Bitmap *value)
 | 
			
		|||
 | 
			
		||||
	p->contents = value;
 | 
			
		||||
 | 
			
		||||
	if (nullOrDisposed(value))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	FloatRect rect = p->contents->rect();
 | 
			
		||||
	p->contentsQuad.setTexPosRect(rect, rect);
 | 
			
		||||
	p->ctrlVertDirty = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -1102,8 +1098,7 @@ void WindowVX::draw()
 | 
			
		|||
 | 
			
		||||
void WindowVX::onGeometryChange(const Scene::Geometry &geo)
 | 
			
		||||
{
 | 
			
		||||
	p->sceneOffset.x = geo.rect.x - geo.xOrigin;
 | 
			
		||||
	p->sceneOffset.y = geo.rect.y - geo.yOrigin;
 | 
			
		||||
	p->sceneOffset = geo.offset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WindowVX::releaseResources()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue