Transition from QtCore to stdc++ / STL / boost
This looks like a pretty major change, but in reality, 80% of it is just renames of types and corresponding methods. The config parsing code has been completely replaced with a boost::program_options based version. This means that the config file format slightly changed (checkout the updated README). I still expect there to be bugs / unforseen events. Those should be fixed in follow up commits. Also, finally reverted back to using pkg-config to locate and link libruby. Yay for less hacks!
This commit is contained in:
parent
01529c5741
commit
2adf8ab265
51
README.md
51
README.md
|
@ -5,7 +5,7 @@ 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+.
|
It is licensed under the GNU General Public License v2+.
|
||||||
|
|
||||||
## Bindings
|
## Bindings
|
||||||
Bindings provide the glue code for an interpreted language environment to run game scripts in. As of right now, they are compiled directly into the executable (however, the scripting language itself might not be). Currently there are three bindings:
|
Bindings provide the glue code for an interpreted language environment to run game scripts in. Currently there are three bindings:
|
||||||
|
|
||||||
### MRI
|
### MRI
|
||||||
Website: https://www.ruby-lang.org/en/
|
Website: https://www.ruby-lang.org/en/
|
||||||
|
@ -15,8 +15,6 @@ Matz's Ruby Interpreter, also called CRuby, is the most widely deployed version
|
||||||
For a list of differences, see:
|
For a list of differences, see:
|
||||||
http://stackoverflow.com/questions/21574/what-is-the-difference-between-ruby-1-8-and-ruby-1-9
|
http://stackoverflow.com/questions/21574/what-is-the-difference-between-ruby-1-8-and-ruby-1-9
|
||||||
|
|
||||||
To select this binding, run `qmake BINDING=BINDING_MRI`
|
|
||||||
|
|
||||||
### mruby (Lightweight Ruby)
|
### mruby (Lightweight Ruby)
|
||||||
Website: https://github.com/mruby/mruby
|
Website: https://github.com/mruby/mruby
|
||||||
|
|
||||||
|
@ -24,23 +22,20 @@ mruby is a new endeavor by Matz and others to create a more lightweight, spec-ad
|
||||||
|
|
||||||
Due to heavy differences between mruby and MRI as well as lacking modules, running RPG Maker games with this binding will most likely not work correctly. It is provided as experimental code. You can eg. write your own ruby scripts and run them.
|
Due to heavy differences between mruby and MRI as well as lacking modules, running RPG Maker games with this binding will most likely not work correctly. It is provided as experimental code. You can eg. write your own ruby scripts and run them.
|
||||||
|
|
||||||
Some extensions to the standard classes/modules are provided taking the RPG Maker XP helpfile as a quasi "standard". These include Marshal, File, FileTest and Time.
|
Some extensions to the standard classes/modules are provided, taking the RPG Maker XP helpfile as a quasi "reference". These include Marshal, File, FileTest and Time.
|
||||||
|
|
||||||
**Important:** If you decide to use [mattn's oniguruma regexp gem](https://github.com/mattn/mruby-onig-regexp), don't forget to add `-lonig` to the linker flags to avoid ugly symbol overlaps with libc.
|
**Important:** If you decide to use [mattn's oniguruma regexp gem](https://github.com/mattn/mruby-onig-regexp), don't forget to add `-lonig` to the linker flags to avoid ugly symbol overlaps with libc.
|
||||||
|
|
||||||
To select this binding, run `qmake BINDING=BINDING_MRUBY`
|
|
||||||
|
|
||||||
### null
|
### null
|
||||||
This binding only exists for testing purposes and does nothing (the engine quits immediately). It can be used to eg. run a minimal RGSS game loop directly in C++.
|
This binding only exists for testing purposes and does nothing (the engine quits immediately). It can be used to eg. run a minimal RGSS game loop directly in C++.
|
||||||
|
|
||||||
To select this binding, run `qmake BINDING=BINDING_NULL`
|
## Dependencies / Building
|
||||||
|
|
||||||
## Dependencies
|
* Boost.Unordered (headers only)
|
||||||
|
* Boost.Program_options
|
||||||
* QtCore 4.8
|
* libsigc++ 2.0
|
||||||
* libsigc++
|
* PhysFS (latest hg)
|
||||||
* PhysFS
|
* GLEW >= 1.7
|
||||||
* glew
|
|
||||||
* OpenAL
|
* OpenAL
|
||||||
* SDL2
|
* SDL2
|
||||||
* SDL2_image
|
* SDL2_image
|
||||||
|
@ -49,29 +44,29 @@ To select this binding, run `qmake BINDING=BINDING_NULL`
|
||||||
* pixman
|
* pixman
|
||||||
* zlib (only ruby bindings)
|
* zlib (only ruby bindings)
|
||||||
|
|
||||||
(If no version specified, assume latest *development version*, ie. freshest one from git/hg/svn)
|
mkxp employs Qt's qmake build system, so you'll need to install that beforehand.
|
||||||
|
|
||||||
|
qmake will use pkg-config to locate the respective include/library paths. If you installed any dependencies into non-standard prefixes, make sure to adjust your `PKG_CONFIG_PATH` variable accordingly.
|
||||||
|
|
||||||
|
The exception is boost, which is weird in that it still hasn't managed to pull off pkg-config support (seriously?). *If you installed boost in a non-standard prefix*, you will need to pass its include path via `BOOST_I` and library path via `BOOST_L`, either as direct arguments to qmake (`qmake BOOST_I="/usr/include" ...`) or via environment variables.
|
||||||
|
|
||||||
|
**MRI-Binding**: pkg-config will look for `ruby-2.1.pc`, but you can modify mkxp.pro to use 2.0 instead. This is the default binding, so no arguments to qmake needed (`BINDING=BINDING_MRI` to be explicit).
|
||||||
|
|
||||||
|
**MRuby-Binding**: place the "mruby" folder into the project folder and build it first. Add `BINDING=BINDING_MRUBY` to qmake's arguments.
|
||||||
|
|
||||||
|
**Null-Binding**: Add `BINDING=BINDING_NULL` to qmake's arguments.
|
||||||
|
|
||||||
### Supported image/audio formats
|
### Supported image/audio formats
|
||||||
These depend on the auxiliary libraries. For maximum RGSS compliance, build SDL2_image with png/jpg support, and SDL_sound with oggvorbis/wav/mp3 support.
|
These depend on the SDL auxiliary libraries. For maximum RGSS compliance, build SDL2_image with png/jpg support, and SDL_sound with oggvorbis/wav/mp3 support.
|
||||||
|
|
||||||
### MRI binding:
|
|
||||||
Place a recent version of ruby in the project folder, apply all patches from "patches/ruby" and build it.
|
|
||||||
|
|
||||||
### mruby binding:
|
|
||||||
Place a recent version of mruby in the project folder and build it.
|
|
||||||
|
|
||||||
To run mkxp, you should have a graphics card capable of at least **OpenGL 2.0** with an up-to-date driver installed.
|
To run mkxp, you should have a graphics card capable of at least **OpenGL 2.0** with an up-to-date driver installed.
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
mkxp employs Qt's qmake build system, so you'll need to install that beforehand. After cloning mkxp, run one of the above qmake calls, or simply `qmake` to select the default binding (currently MRI), then `make`.
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
mkxp reads configuration data from the file "mkxp.conf" contained in the current directory. The format is ini-style. The "[General]" group may contain following entries:
|
mkxp reads configuration data from the file "mkxp.conf" contained in the current directory. The format is ini-style. Do *not* use quotes around file paths (spaces won't break). Following entries are interpreted:
|
||||||
|
|
||||||
| Key | Type | Default | Description |
|
| Key | Type | Default | Description |
|
||||||
| ---------------- | ----------- | ------- | ------------------------------------------------------------------------------- |
|
| ---------------- | ------ | ------- | ------------------------------------------------------------------------------- |
|
||||||
| debugMode | bool | false | Log OpenGL debug information to the console |
|
| debugMode | bool | false | Log OpenGL debug information to the console |
|
||||||
| winResizable | bool | false | Game window is resizable |
|
| winResizable | bool | false | Game window is resizable |
|
||||||
| fullscreen | bool | false | Start game in fullscreen (this can always be toggled with Alt-Enter at runtime) |
|
| fullscreen | bool | false | Start game in fullscreen (this can always be toggled with Alt-Enter at runtime) |
|
||||||
|
@ -86,7 +81,7 @@ mkxp reads configuration data from the file "mkxp.conf" contained in the current
|
||||||
| gameFolder | string | "." | mkxp will look for all game related files here |
|
| gameFolder | string | "." | mkxp will look for all game related files here |
|
||||||
| allowSymlinks | bool | false | Allow symlinks to be followed in the game folder. |
|
| allowSymlinks | bool | false | Allow symlinks to be followed in the game folder. |
|
||||||
| customScript | string | "" | Execute a raw ruby script file instead of an RPG Maker game. |
|
| customScript | string | "" | Execute a raw ruby script file instead of an RPG Maker game. |
|
||||||
| RTPs | string list | "" | A list of space separated paths to RTPs to be used (See next section) |
|
| RTP | string | "" | Path to a Run Time Package to be used. Can be specified multiple times. |
|
||||||
|
|
||||||
## RTPs
|
## RTPs
|
||||||
|
|
||||||
|
|
|
@ -24,19 +24,18 @@
|
||||||
#include "sharedstate.h"
|
#include "sharedstate.h"
|
||||||
#include "eventthread.h"
|
#include "eventthread.h"
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "debugwriter.h"
|
||||||
|
|
||||||
#include "./ruby/include/ruby.h"
|
#include <ruby.h>
|
||||||
#include "./ruby/include/ruby/encoding.h"
|
#include <ruby/encoding.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
#include <SDL_filesystem.h>
|
#include <SDL_filesystem.h>
|
||||||
|
|
||||||
#include <QFile>
|
|
||||||
#include <QByteArray>
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
extern const char module_rpg[];
|
extern const char module_rpg[];
|
||||||
|
|
||||||
static void mriBindingExecute();
|
static void mriBindingExecute();
|
||||||
|
@ -102,9 +101,9 @@ static void mriBindingInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
showMsg(const QByteArray &msg)
|
showMsg(const std::string &msg)
|
||||||
{
|
{
|
||||||
shState->eThread().showMessageBox(msg.constData());
|
shState->eThread().showMessageBox(msg.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
RB_METHOD(mkxpPuts)
|
RB_METHOD(mkxpPuts)
|
||||||
|
@ -114,7 +113,7 @@ RB_METHOD(mkxpPuts)
|
||||||
const char *str;
|
const char *str;
|
||||||
rb_get_args(argc, argv, "z", &str RB_ARG_END);
|
rb_get_args(argc, argv, "z", &str RB_ARG_END);
|
||||||
|
|
||||||
qDebug() << str;
|
Debug() << str;
|
||||||
|
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
@ -174,49 +173,45 @@ RB_METHOD(mriDataDirectory)
|
||||||
|
|
||||||
static void runCustomScript(const char *filename)
|
static void runCustomScript(const char *filename)
|
||||||
{
|
{
|
||||||
QFile scriptFile(filename);
|
std::string scriptData("#encoding:utf-8\n");
|
||||||
if (!scriptFile.open(QFile::ReadOnly))
|
|
||||||
|
if (!readFile(filename, scriptData))
|
||||||
{
|
{
|
||||||
showMsg(QByteArray("Unable to open '") + filename + "'");
|
showMsg(std::string("Unable to open '") + filename + "'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray scriptData = scriptFile.readAll();
|
rb_eval_string_protect(scriptData.c_str(), 0);
|
||||||
scriptFile.close();
|
|
||||||
|
|
||||||
scriptData.prepend("#encoding:utf-8\n");
|
|
||||||
|
|
||||||
rb_eval_string_protect(scriptData.constData(), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE kernelLoadDataInt(const char *filename);
|
VALUE kernelLoadDataInt(const char *filename);
|
||||||
|
|
||||||
struct Script
|
struct Script
|
||||||
{
|
{
|
||||||
QByteArray name;
|
std::string name;
|
||||||
QByteArray encData;
|
std::string encData;
|
||||||
uint32_t unknown;
|
uint32_t unknown;
|
||||||
|
|
||||||
QByteArray decData;
|
std::string decData;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void runRMXPScripts()
|
static void runRMXPScripts()
|
||||||
{
|
{
|
||||||
const QByteArray &scriptPack = shState->rtData().config.game.scripts;
|
const std::string &scriptPack = shState->rtData().config.game.scripts;
|
||||||
|
|
||||||
if (scriptPack.isEmpty())
|
if (scriptPack.empty())
|
||||||
{
|
{
|
||||||
showMsg("No game scripts specified (missing Game.ini?)");
|
showMsg("No game scripts specified (missing Game.ini?)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shState->fileSystem().exists(scriptPack.constData()))
|
if (!shState->fileSystem().exists(scriptPack.c_str()))
|
||||||
{
|
{
|
||||||
showMsg("Unable to open '" + scriptPack + "'");
|
showMsg("Unable to open '" + scriptPack + "'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE scriptArray = kernelLoadDataInt(scriptPack.constData());
|
VALUE scriptArray = kernelLoadDataInt(scriptPack.c_str());
|
||||||
|
|
||||||
if (rb_type(scriptArray) != RUBY_T_ARRAY)
|
if (rb_type(scriptArray) != RUBY_T_ARRAY)
|
||||||
{
|
{
|
||||||
|
@ -226,7 +221,7 @@ static void runRMXPScripts()
|
||||||
|
|
||||||
size_t scriptCount = RARRAY_LEN(scriptArray);
|
size_t scriptCount = RARRAY_LEN(scriptArray);
|
||||||
|
|
||||||
QByteArray decodeBuffer;
|
std::string decodeBuffer;
|
||||||
decodeBuffer.resize(0x1000);
|
decodeBuffer.resize(0x1000);
|
||||||
|
|
||||||
std::vector<Script> encScripts(scriptCount);
|
std::vector<Script> encScripts(scriptCount);
|
||||||
|
@ -246,7 +241,7 @@ static void runRMXPScripts()
|
||||||
|
|
||||||
Script &sc = encScripts[i];
|
Script &sc = encScripts[i];
|
||||||
sc.name = RSTRING_PTR(scriptName);
|
sc.name = RSTRING_PTR(scriptName);
|
||||||
sc.encData = QByteArray(RSTRING_PTR(scriptString), RSTRING_LEN(scriptString));
|
sc.encData = std::string(RSTRING_PTR(scriptString), RSTRING_LEN(scriptString));
|
||||||
sc.unknown = FIX2UINT(scriptUnknown);
|
sc.unknown = FIX2UINT(scriptUnknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,9 +255,9 @@ static void runRMXPScripts()
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
unsigned char *bufferPtr =
|
unsigned char *bufferPtr =
|
||||||
reinterpret_cast<unsigned char*>(const_cast<char*>(decodeBuffer.constData()));
|
reinterpret_cast<unsigned char*>(const_cast<char*>(decodeBuffer.c_str()));
|
||||||
const unsigned char *sourcePtr =
|
const unsigned char *sourcePtr =
|
||||||
reinterpret_cast<const unsigned char*>(sc.encData.constData());
|
reinterpret_cast<const unsigned char*>(sc.encData.c_str());
|
||||||
|
|
||||||
bufferLen = decodeBuffer.length();
|
bufferLen = decodeBuffer.length();
|
||||||
|
|
||||||
|
@ -282,21 +277,25 @@ static void runRMXPScripts()
|
||||||
static char buffer[256];
|
static char buffer[256];
|
||||||
/* FIXME: '%zu' apparently gcc only? */
|
/* FIXME: '%zu' apparently gcc only? */
|
||||||
snprintf(buffer, sizeof(buffer), "Error decoding script %zu: '%s'",
|
snprintf(buffer, sizeof(buffer), "Error decoding script %zu: '%s'",
|
||||||
i, sc.name.constData());
|
i, sc.name.c_str());
|
||||||
|
|
||||||
showMsg(buffer);
|
showMsg(buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc.decData = QByteArray(decodeBuffer.constData(), bufferLen);
|
/* Store encoding header + the decoded script
|
||||||
sc.decData.prepend("#encoding:utf-8\n");
|
* in 'sc.decData' */
|
||||||
|
sc.decData = "#encoding:utf-8\n";
|
||||||
|
size_t hdSize = sc.decData.size();
|
||||||
|
sc.decData.resize(hdSize + bufferLen);
|
||||||
|
memcpy(&sc.decData[hdSize], decodeBuffer.c_str(), bufferLen);
|
||||||
|
|
||||||
ruby_script(sc.name.constData());
|
ruby_script(sc.name.c_str());
|
||||||
|
|
||||||
rb_gc_start();
|
rb_gc_start();
|
||||||
|
|
||||||
/* Execute code */
|
/* Execute code */
|
||||||
rb_eval_string_protect(sc.decData.constData(), 0);
|
rb_eval_string_protect(sc.decData.c_str(), 0);
|
||||||
|
|
||||||
VALUE exc = rb_gv_get("$!");
|
VALUE exc = rb_gv_get("$!");
|
||||||
if (rb_type(exc) != RUBY_T_NIL)
|
if (rb_type(exc) != RUBY_T_NIL)
|
||||||
|
@ -314,23 +313,23 @@ static void mriBindingExecute()
|
||||||
|
|
||||||
mriBindingInit();
|
mriBindingInit();
|
||||||
|
|
||||||
QByteArray &customScript = shState->rtData().config.customScript;
|
std::string &customScript = shState->rtData().config.customScript;
|
||||||
if (!customScript.isEmpty())
|
if (!customScript.empty())
|
||||||
runCustomScript(customScript.constData());
|
runCustomScript(customScript.c_str());
|
||||||
else
|
else
|
||||||
runRMXPScripts();
|
runRMXPScripts();
|
||||||
|
|
||||||
VALUE exc = rb_gv_get("$!");
|
VALUE exc = rb_gv_get("$!");
|
||||||
if (rb_type(exc) != RUBY_T_NIL && !rb_eql(rb_obj_class(exc), rb_eSystemExit))
|
if (rb_type(exc) != RUBY_T_NIL && !rb_eql(rb_obj_class(exc), rb_eSystemExit))
|
||||||
{
|
{
|
||||||
qDebug() << "Had exception:" << rb_class2name(rb_obj_class(exc));
|
Debug() << "Had exception:" << rb_class2name(rb_obj_class(exc));
|
||||||
VALUE bt = rb_funcall(exc, rb_intern("backtrace"), 0);
|
VALUE bt = rb_funcall(exc, rb_intern("backtrace"), 0);
|
||||||
rb_p(bt);
|
rb_p(bt);
|
||||||
VALUE msg = rb_funcall(exc, rb_intern("message"), 0);
|
VALUE msg = rb_funcall(exc, rb_intern("message"), 0);
|
||||||
if (RSTRING_LEN(msg) < 256)
|
if (RSTRING_LEN(msg) < 256)
|
||||||
showMsg(RSTRING_PTR(msg));
|
showMsg(RSTRING_PTR(msg));
|
||||||
else
|
else
|
||||||
qDebug() << (RSTRING_PTR(msg));
|
Debug() << (RSTRING_PTR(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
ruby_cleanup(0);
|
ruby_cleanup(0);
|
||||||
|
|
|
@ -26,8 +26,7 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
void initType(rb_data_type_struct &type,
|
void initType(rb_data_type_struct &type,
|
||||||
const char *name,
|
const char *name,
|
||||||
|
@ -244,7 +243,7 @@ rb_get_args(int argc, VALUE *argv, const char *format, ...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef NDEBUG
|
||||||
|
|
||||||
/* Pop remaining arg pointers off
|
/* Pop remaining arg pointers off
|
||||||
* the stack to check for RB_ARG_END */
|
* the stack to check for RB_ARG_END */
|
||||||
|
@ -288,8 +287,8 @@ rb_get_args(int argc, VALUE *argv, const char *format, ...)
|
||||||
|
|
||||||
/* Verify correct termination */
|
/* Verify correct termination */
|
||||||
void *argEnd = va_arg(ap, void*);
|
void *argEnd = va_arg(ap, void*);
|
||||||
Q_UNUSED(argEnd);
|
(void) argEnd;
|
||||||
Q_ASSERT(argEnd == RB_ARG_END_VAL);
|
assert(argEnd == RB_ARG_END_VAL);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#ifndef BINDING_UTIL_H
|
#ifndef BINDING_UTIL_H
|
||||||
#define BINDING_UTIL_H
|
#define BINDING_UTIL_H
|
||||||
|
|
||||||
#include "./ruby/ruby.h"
|
#include <ruby.h>
|
||||||
|
|
||||||
enum RbException
|
enum RbException
|
||||||
{
|
{
|
||||||
|
@ -134,7 +134,7 @@ int
|
||||||
rb_get_args(int argc, VALUE *argv, const char *format, ...);
|
rb_get_args(int argc, VALUE *argv, const char *format, ...);
|
||||||
|
|
||||||
/* Always terminate 'rb_get_args' with this */
|
/* Always terminate 'rb_get_args' with this */
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef NDEBUG
|
||||||
# define RB_ARG_END_VAL ((void*) -1)
|
# define RB_ARG_END_VAL ((void*) -1)
|
||||||
# define RB_ARG_END ,RB_ARG_END_VAL
|
# define RB_ARG_END ,RB_ARG_END_VAL
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -26,8 +26,6 @@
|
||||||
#include "binding-util.h"
|
#include "binding-util.h"
|
||||||
#include "binding-types.h"
|
#include "binding-types.h"
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
#define DISP_CLASS_NAME "bitmap"
|
#define DISP_CLASS_NAME "bitmap"
|
||||||
|
|
||||||
DEF_TYPE(Bitmap);
|
DEF_TYPE(Bitmap);
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
#include "binding-util.h"
|
#include "binding-util.h"
|
||||||
#include "serializable-binding.h"
|
#include "serializable-binding.h"
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
DEF_TYPE(Color);
|
DEF_TYPE(Color);
|
||||||
DEF_TYPE(Tone);
|
DEF_TYPE(Tone);
|
||||||
DEF_TYPE(Rect);
|
DEF_TYPE(Rect);
|
||||||
|
|
|
@ -27,8 +27,6 @@
|
||||||
#include "ruby/encoding.h"
|
#include "ruby/encoding.h"
|
||||||
#include "ruby/intern.h"
|
#include "ruby/intern.h"
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
DEF_TYPE(FileInt);
|
DEF_TYPE(FileInt);
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
|
|
@ -30,11 +30,11 @@
|
||||||
#include <mruby/proc.h>
|
#include <mruby/proc.h>
|
||||||
#include <mruby/dump.h>
|
#include <mruby/dump.h>
|
||||||
|
|
||||||
#include "binding-util.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <SDL_messagebox.h>
|
#include <SDL_messagebox.h>
|
||||||
#include <SDL_rwops.h>
|
#include <SDL_rwops.h>
|
||||||
#include <SDL_timer.h>
|
#include <SDL_timer.h>
|
||||||
|
@ -45,6 +45,7 @@
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
|
||||||
|
#include "binding-util.h"
|
||||||
#include "binding-types.h"
|
#include "binding-types.h"
|
||||||
#include "mrb-ext/marshal.h"
|
#include "mrb-ext/marshal.h"
|
||||||
|
|
||||||
|
@ -180,9 +181,9 @@ checkException(mrb_state *mrb)
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
showError(const QByteArray &msg)
|
showError(const std::string &msg)
|
||||||
{
|
{
|
||||||
shState->eThread().showMessageBox(msg.constData());
|
shState->eThread().showMessageBox(msg.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -245,17 +246,17 @@ runMrbFile(mrb_state *mrb, const char *filename)
|
||||||
static void
|
static void
|
||||||
runRMXPScripts(mrb_state *mrb, mrbc_context *ctx)
|
runRMXPScripts(mrb_state *mrb, mrbc_context *ctx)
|
||||||
{
|
{
|
||||||
const QByteArray &scriptPack = shState->rtData().config.game.scripts;
|
const std::string &scriptPack = shState->rtData().config.game.scripts;
|
||||||
|
|
||||||
if (scriptPack.isEmpty())
|
if (scriptPack.empty())
|
||||||
{
|
{
|
||||||
showError("No game scripts specified (missing Game.ini?)");
|
showError("No game scripts specified (missing Game.ini?)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shState->fileSystem().exists(scriptPack.constData()))
|
if (!shState->fileSystem().exists(scriptPack.c_str()))
|
||||||
{
|
{
|
||||||
showError("Unable to open '" + scriptPack + "'");
|
showError(std::string("Unable to open '") + scriptPack + "'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,10 +264,10 @@ runRMXPScripts(mrb_state *mrb, mrbc_context *ctx)
|
||||||
mrb_state *scriptMrb = mrb_open();
|
mrb_state *scriptMrb = mrb_open();
|
||||||
SDL_RWops ops;
|
SDL_RWops ops;
|
||||||
|
|
||||||
shState->fileSystem().openRead(ops, scriptPack.constData());
|
shState->fileSystem().openRead(ops, scriptPack.c_str());
|
||||||
|
|
||||||
mrb_value scriptArray = mrb_nil_value();
|
mrb_value scriptArray = mrb_nil_value();
|
||||||
QByteArray readError;
|
std::string readError;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -275,22 +276,22 @@ runRMXPScripts(mrb_state *mrb, mrbc_context *ctx)
|
||||||
catch (const Exception &e)
|
catch (const Exception &e)
|
||||||
{
|
{
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
snprintf(buffer, sizeof(buffer), e.fmt.constData(), e.arg1.constData(), e.arg2.constData());
|
snprintf(buffer, sizeof(buffer), e.fmt.c_str(), e.arg1.c_str(), e.arg2.c_str());
|
||||||
readError = QByteArray(": ") + QByteArray(buffer);
|
readError = std::string(": ") + std::string(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_RWclose(&ops);
|
SDL_RWclose(&ops);
|
||||||
|
|
||||||
if (!mrb_array_p(scriptArray))
|
if (!mrb_array_p(scriptArray))
|
||||||
{
|
{
|
||||||
showError(QByteArray("Failed to read script data") + readError);
|
showError(std::string("Failed to read script data") + readError);
|
||||||
mrb_close(scriptMrb);
|
mrb_close(scriptMrb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int scriptCount = mrb_ary_len(scriptMrb, scriptArray);
|
int scriptCount = mrb_ary_len(scriptMrb, scriptArray);
|
||||||
|
|
||||||
QByteArray decodeBuffer;
|
std::string decodeBuffer;
|
||||||
decodeBuffer.resize(0x1000);
|
decodeBuffer.resize(0x1000);
|
||||||
|
|
||||||
for (int i = 0; i < scriptCount; ++i)
|
for (int i = 0; i < scriptCount; ++i)
|
||||||
|
@ -309,7 +310,7 @@ runRMXPScripts(mrb_state *mrb, mrbc_context *ctx)
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
unsigned char *bufferPtr =
|
unsigned char *bufferPtr =
|
||||||
reinterpret_cast<unsigned char*>(const_cast<char*>(decodeBuffer.constData()));
|
reinterpret_cast<unsigned char*>(const_cast<char*>(decodeBuffer.c_str()));
|
||||||
unsigned char *sourcePtr =
|
unsigned char *sourcePtr =
|
||||||
reinterpret_cast<unsigned char*>(RSTRING_PTR(scriptString));
|
reinterpret_cast<unsigned char*>(RSTRING_PTR(scriptString));
|
||||||
|
|
||||||
|
@ -342,7 +343,7 @@ runRMXPScripts(mrb_state *mrb, mrbc_context *ctx)
|
||||||
int ai = mrb_gc_arena_save(mrb);
|
int ai = mrb_gc_arena_save(mrb);
|
||||||
|
|
||||||
/* Execute code */
|
/* Execute code */
|
||||||
mrb_load_nstring_cxt(mrb, decodeBuffer.constData(), bufferLen, ctx);
|
mrb_load_nstring_cxt(mrb, decodeBuffer.c_str(), bufferLen, ctx);
|
||||||
|
|
||||||
mrb_gc_arena_restore(mrb, ai);
|
mrb_gc_arena_restore(mrb, ai);
|
||||||
|
|
||||||
|
@ -370,14 +371,15 @@ static void mrbBindingExecute()
|
||||||
mrbc_context *ctx = mrbc_context_new(mrb);
|
mrbc_context *ctx = mrbc_context_new(mrb);
|
||||||
ctx->capture_errors = 1;
|
ctx->capture_errors = 1;
|
||||||
|
|
||||||
Config &conf = shState->rtData().config;
|
const Config &conf = shState->rtData().config;
|
||||||
QByteArray &customScript = conf.customScript;
|
const std::string &customScript = conf.customScript;
|
||||||
QByteArray mrbFile = conf.bindingConf.value("mrbFile").toByteArray();
|
// const std::string &mrbFile = conf.mrbFile;
|
||||||
|
(void) runMrbFile; // FIXME mrbFile support on ice for now
|
||||||
|
|
||||||
if (!customScript.isEmpty())
|
if (!customScript.empty())
|
||||||
runCustomScript(mrb, ctx, customScript.constData());
|
runCustomScript(mrb, ctx, customScript.c_str());
|
||||||
else if (!mrbFile.isEmpty())
|
// else if (!mrbFile.empty())
|
||||||
runMrbFile(mrb, mrbFile.constData());
|
// runMrbFile(mrb, mrbFile.c_str());
|
||||||
else
|
else
|
||||||
runRMXPScripts(mrb, ctx);
|
runRMXPScripts(mrb, ctx);
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,6 @@
|
||||||
#include "binding-util.h"
|
#include "binding-util.h"
|
||||||
#include "binding-types.h"
|
#include "binding-types.h"
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
#define DISP_CLASS_NAME "bitmap"
|
#define DISP_CLASS_NAME "bitmap"
|
||||||
|
|
||||||
DEF_TYPE(Bitmap);
|
DEF_TYPE(Bitmap);
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include "disposable.h"
|
#include "disposable.h"
|
||||||
#include "binding-util.h"
|
#include "binding-util.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
template<class C>
|
template<class C>
|
||||||
MRB_METHOD(disposableDispose)
|
MRB_METHOD(disposableDispose)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
#include "binding-types.h"
|
#include "binding-types.h"
|
||||||
#include "serializable-binding.h"
|
#include "serializable-binding.h"
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
#define ATTR_RW(Type, attr, arg_type, mrb_val, arg_t_s) \
|
#define ATTR_RW(Type, attr, arg_type, mrb_val, arg_t_s) \
|
||||||
MRB_METHOD(Type##Get_##attr) \
|
MRB_METHOD(Type##Get_##attr) \
|
||||||
{ \
|
{ \
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
|
||||||
|
#include "debugwriter.h"
|
||||||
|
|
||||||
#include "../binding-util.h"
|
#include "../binding-util.h"
|
||||||
#include <mruby/string.h>
|
#include <mruby/string.h>
|
||||||
#include <mruby/array.h>
|
#include <mruby/array.h>
|
||||||
|
@ -36,8 +38,6 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
extern mrb_value timeFromSecondsInt(mrb_state *mrb, time_t seconds);
|
extern mrb_value timeFromSecondsInt(mrb_state *mrb, time_t seconds);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -87,7 +87,7 @@ getOpenMode(const char *mode)
|
||||||
STR_CASE("a", Write)
|
STR_CASE("a", Write)
|
||||||
STR_CASE("a+", ReadWrite)
|
STR_CASE("a+", ReadWrite)
|
||||||
|
|
||||||
qDebug() << "getOpenMode failed for:" << mode;
|
Debug() << "getOpenMode failed for:" << mode;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ MRB_FUNCTION(fileExpandPath)
|
||||||
|
|
||||||
// FIXME No idea how to integrate 'default_dir' right now
|
// FIXME No idea how to integrate 'default_dir' right now
|
||||||
if (defDir)
|
if (defDir)
|
||||||
qDebug() << "FIXME: File.expand_path: default_dir not implemented";
|
Debug() << "FIXME: File.expand_path: default_dir not implemented";
|
||||||
|
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
char *unused = realpath(path, buffer);
|
char *unused = realpath(path, buffer);
|
||||||
|
@ -457,7 +457,7 @@ MRB_METHOD(fileReadLines)
|
||||||
const char *rs = "\n"; (void) rs;
|
const char *rs = "\n"; (void) rs;
|
||||||
if (mrb->c->ci->argc > 0)
|
if (mrb->c->ci->argc > 0)
|
||||||
{
|
{
|
||||||
qDebug() << "FIXME: File.readlines: rs not implemented";
|
Debug() << "FIXME: File.readlines: rs not implemented";
|
||||||
|
|
||||||
if (mrb_string_p(arg))
|
if (mrb_string_p(arg))
|
||||||
rs = RSTRING_PTR(arg);
|
rs = RSTRING_PTR(arg);
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "binding.h"
|
#include "binding.h"
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
void mrbBindingTerminate();
|
void mrbBindingTerminate();
|
||||||
|
|
||||||
MRB_FUNCTION(kernelEval)
|
MRB_FUNCTION(kernelEval)
|
||||||
|
|
|
@ -38,14 +38,11 @@
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "rwmem.h"
|
#include "rwmem.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
#include "boost-hash.h"
|
||||||
|
#include "debugwriter.h"
|
||||||
|
|
||||||
#include <SDL_timer.h>
|
#include <SDL_timer.h>
|
||||||
|
|
||||||
#include <QHash>
|
|
||||||
#include <QByteArray>
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
|
|
||||||
#define MARSHAL_MAJOR 4
|
#define MARSHAL_MAJOR 4
|
||||||
#define MARSHAL_MINOR 8
|
#define MARSHAL_MINOR 8
|
||||||
|
@ -76,9 +73,9 @@
|
||||||
// FIXME make these dynamically allocatd, per MarshalContext
|
// FIXME make these dynamically allocatd, per MarshalContext
|
||||||
static char gpbuffer[512];
|
static char gpbuffer[512];
|
||||||
|
|
||||||
inline uint qHash(mrb_value key)
|
inline size_t hash_value(mrb_value key)
|
||||||
{
|
{
|
||||||
return qHash(key.value.p);
|
return boost::hash_value(key.value.p);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator==(mrb_value v1, mrb_value v2)
|
inline bool operator==(mrb_value v1, mrb_value v2)
|
||||||
|
@ -109,7 +106,7 @@ template<typename T>
|
||||||
struct LinkBuffer
|
struct LinkBuffer
|
||||||
{
|
{
|
||||||
/* Key: val, Value: idx in vec */
|
/* Key: val, Value: idx in vec */
|
||||||
QHash<T, int> hash;
|
BoostHash<T, int> hash;
|
||||||
std::vector<T> vec;
|
std::vector<T> vec;
|
||||||
|
|
||||||
bool contains(T value)
|
bool contains(T value)
|
||||||
|
@ -551,9 +548,8 @@ read_value(MarshalContext *ctx)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default :
|
default :
|
||||||
qDebug() << "Value type" << (char)type << "not supported!";
|
|
||||||
throw Exception(Exception::MKXPError, "Marshal.load: unsupported value type '%s'",
|
throw Exception(Exception::MKXPError, "Marshal.load: unsupported value type '%s'",
|
||||||
QByteArray(1, (char)type));
|
std::string(1, (char)type));
|
||||||
}
|
}
|
||||||
|
|
||||||
mrb_gc_arena_restore(mrb, arena);
|
mrb_gc_arena_restore(mrb, arena);
|
||||||
|
@ -973,7 +969,7 @@ MRB_FUNCTION(marshalLoad)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "FIXME: Marshal.load: generic IO port not implemented";
|
Debug() << "FIXME: Marshal.load: generic IO port not implemented";
|
||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
#include "binding-types.h"
|
#include "binding-types.h"
|
||||||
#include "serializable-binding.h"
|
#include "serializable-binding.h"
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
DEF_TYPE(Table);
|
DEF_TYPE(Table);
|
||||||
|
|
||||||
MRB_METHOD(tableInitialize)
|
MRB_METHOD(tableInitialize)
|
||||||
|
|
|
@ -22,12 +22,11 @@
|
||||||
#include "binding.h"
|
#include "binding.h"
|
||||||
#include "sharedstate.h"
|
#include "sharedstate.h"
|
||||||
#include "eventthread.h"
|
#include "eventthread.h"
|
||||||
|
#include "debugwriter.h"
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
static void nullBindingExecute()
|
static void nullBindingExecute()
|
||||||
{
|
{
|
||||||
qDebug() << "The null binding doesn't do anything, so we're done!";
|
Debug() << "The null binding doesn't do anything, so we're done!";
|
||||||
shState->rtData().rqTermAck = true;
|
shState->rtData().rqTermAck = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
40
mkxp.pro
40
mkxp.pro
|
@ -5,7 +5,29 @@ QT =
|
||||||
TARGET = mkxp
|
TARGET = mkxp
|
||||||
DEPENDPATH += src shader assets
|
DEPENDPATH += src shader assets
|
||||||
INCLUDEPATH += . src
|
INCLUDEPATH += . src
|
||||||
QMAKE_LFLAGS += '-Wl,-rpath,\'\$$ORIGIN/lib\''
|
LIBS += -lGL
|
||||||
|
|
||||||
|
# Deal with boost paths...
|
||||||
|
isEmpty(BOOST_I) {
|
||||||
|
BOOST_I = $$(BOOST_I)
|
||||||
|
}
|
||||||
|
isEmpty(BOOST_I) {}
|
||||||
|
else {
|
||||||
|
INCLUDEPATH += $$BOOST_I
|
||||||
|
}
|
||||||
|
|
||||||
|
isEmpty(BOOST_L) {
|
||||||
|
BOOST_L = $$(BOOST_L)
|
||||||
|
}
|
||||||
|
isEmpty(BOOST_L) {}
|
||||||
|
else {
|
||||||
|
LIBS += -L$$BOOST_L
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBS += -lboost_program_options
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG(release, debug|release): DEFINES += NDEBUG
|
||||||
|
|
||||||
isEmpty(BINDING) {
|
isEmpty(BINDING) {
|
||||||
BINDING = BINDING_MRI
|
BINDING = BINDING_MRI
|
||||||
|
@ -19,18 +41,14 @@ RGSS2 {
|
||||||
|
|
||||||
unix {
|
unix {
|
||||||
CONFIG += link_pkgconfig
|
CONFIG += link_pkgconfig
|
||||||
PKGCONFIG += QtCore sigc++-2.0 glew pixman-1 zlib \
|
PKGCONFIG += sigc++-2.0 glew pixman-1 zlib physfs \
|
||||||
physfs sdl2 SDL2_image SDL2_ttf SDL_sound \
|
sdl2 SDL2_image SDL2_ttf SDL_sound openal
|
||||||
openal
|
|
||||||
|
|
||||||
RGSS2 {
|
RGSS2 {
|
||||||
PKGCONFIG += vorbisfile
|
PKGCONFIG += vorbisfile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 'slots' keyword fucks with libsigc++
|
|
||||||
DEFINES += QT_NO_KEYWORDS
|
|
||||||
|
|
||||||
# Input
|
# Input
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
src/quadarray.h \
|
src/quadarray.h \
|
||||||
|
@ -72,7 +90,9 @@ HEADERS += \
|
||||||
src/tileatlas.h \
|
src/tileatlas.h \
|
||||||
src/perftimer.h \
|
src/perftimer.h \
|
||||||
src/sharedstate.h \
|
src/sharedstate.h \
|
||||||
src/al-util.h
|
src/al-util.h \
|
||||||
|
src/boost-hash.h \
|
||||||
|
src/debugwriter.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
src/main.cpp \
|
src/main.cpp \
|
||||||
|
@ -185,9 +205,7 @@ BINDING_MRUBY {
|
||||||
}
|
}
|
||||||
|
|
||||||
BINDING_MRI {
|
BINDING_MRI {
|
||||||
LIBS += ./ruby/libruby.so
|
PKGCONFIG += ruby-2.1
|
||||||
INCLUDEPATH += ruby/include ruby/.ext/include/x86_64-linux # need i386 paths here too!
|
|
||||||
DEPENDPATH += ruby/include ruby/.ext/include/x86_64-linux
|
|
||||||
DEFINES += BINDING_MRI
|
DEFINES += BINDING_MRI
|
||||||
|
|
||||||
# EMBED2 = binding-mri/module_rpg.rb
|
# EMBED2 = binding-mri/module_rpg.rb
|
||||||
|
|
|
@ -27,12 +27,12 @@
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
#include "al-util.h"
|
#include "al-util.h"
|
||||||
|
#include "boost-hash.h"
|
||||||
#include <QByteArray>
|
#include "debugwriter.h"
|
||||||
#include <QHash>
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <SDL_audio.h>
|
#include <SDL_audio.h>
|
||||||
#include <SDL_thread.h>
|
#include <SDL_thread.h>
|
||||||
|
@ -47,8 +47,6 @@
|
||||||
|
|
||||||
#include <alc.h>
|
#include <alc.h>
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
#define AUDIO_SLEEP 10
|
#define AUDIO_SLEEP 10
|
||||||
#define SE_SOURCES 6
|
#define SE_SOURCES 6
|
||||||
#define SE_CACHE_MEM (10*1024*1024) // 10 MB
|
#define SE_CACHE_MEM (10*1024*1024) // 10 MB
|
||||||
|
@ -71,8 +69,8 @@ static uint8_t formatSampleSize(int sdlFormat)
|
||||||
return 4;
|
return 4;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
qDebug() << "Unhandled sample format";
|
Debug() << "Unhandled sample format";
|
||||||
Q_ASSERT(0);
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -87,23 +85,23 @@ static ALenum chooseALFormat(int sampleSize, int channelCount)
|
||||||
{
|
{
|
||||||
case 1 : return AL_FORMAT_MONO8;
|
case 1 : return AL_FORMAT_MONO8;
|
||||||
case 2 : return AL_FORMAT_STEREO8;
|
case 2 : return AL_FORMAT_STEREO8;
|
||||||
default: Q_ASSERT(0);
|
default: abort();
|
||||||
}
|
}
|
||||||
case 2 :
|
case 2 :
|
||||||
switch (channelCount)
|
switch (channelCount)
|
||||||
{
|
{
|
||||||
case 1 : return AL_FORMAT_MONO16;
|
case 1 : return AL_FORMAT_MONO16;
|
||||||
case 2 : return AL_FORMAT_STEREO16;
|
case 2 : return AL_FORMAT_STEREO16;
|
||||||
default : Q_ASSERT(0);
|
default : abort();
|
||||||
}
|
}
|
||||||
case 4 :
|
case 4 :
|
||||||
switch (channelCount)
|
switch (channelCount)
|
||||||
{
|
{
|
||||||
case 1 : return AL_FORMAT_MONO_FLOAT32;
|
case 1 : return AL_FORMAT_MONO_FLOAT32;
|
||||||
case 2 : return AL_FORMAT_STEREO_FLOAT32;
|
case 2 : return AL_FORMAT_STEREO_FLOAT32;
|
||||||
default : Q_ASSERT(0);
|
default : abort();
|
||||||
}
|
}
|
||||||
default : Q_ASSERT(0);
|
default : abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -114,7 +112,7 @@ static const int streamBufSize = 32768;
|
||||||
struct SoundBuffer
|
struct SoundBuffer
|
||||||
{
|
{
|
||||||
/* Uniquely identifies this or equal buffer */
|
/* Uniquely identifies this or equal buffer */
|
||||||
QByteArray key;
|
std::string key;
|
||||||
|
|
||||||
AL::Buffer::ID alBuffer;
|
AL::Buffer::ID alBuffer;
|
||||||
|
|
||||||
|
@ -135,11 +133,6 @@ struct SoundBuffer
|
||||||
alBuffer = AL::Buffer::gen();
|
alBuffer = AL::Buffer::gen();
|
||||||
}
|
}
|
||||||
|
|
||||||
~SoundBuffer()
|
|
||||||
{
|
|
||||||
AL::Buffer::del(alBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static SoundBuffer *ref(SoundBuffer *buffer)
|
static SoundBuffer *ref(SoundBuffer *buffer)
|
||||||
{
|
{
|
||||||
++buffer->refCount;
|
++buffer->refCount;
|
||||||
|
@ -152,12 +145,20 @@ struct SoundBuffer
|
||||||
if (--buffer->refCount == 0)
|
if (--buffer->refCount == 0)
|
||||||
delete buffer;
|
delete buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
~SoundBuffer()
|
||||||
|
{
|
||||||
|
AL::Buffer::del(alBuffer);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SoundEmitter
|
struct SoundEmitter
|
||||||
{
|
{
|
||||||
|
typedef BoostHash<std::string, SoundBuffer*> BufferHash;
|
||||||
|
|
||||||
IntruList<SoundBuffer> buffers;
|
IntruList<SoundBuffer> buffers;
|
||||||
QHash<QByteArray, SoundBuffer*> bufferHash;
|
BufferHash bufferHash;
|
||||||
|
|
||||||
/* Byte count sum of all cached / playing buffers */
|
/* Byte count sum of all cached / playing buffers */
|
||||||
uint32_t bufferBytes;
|
uint32_t bufferBytes;
|
||||||
|
@ -189,12 +190,12 @@ struct SoundEmitter
|
||||||
SoundBuffer::deref(atchBufs[i]);
|
SoundBuffer::deref(atchBufs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<QByteArray, SoundBuffer*>::iterator iter;
|
BufferHash::const_iterator iter;
|
||||||
for (iter = bufferHash.begin(); iter != bufferHash.end(); ++iter)
|
for (iter = bufferHash.cbegin(); iter != bufferHash.cend(); ++iter)
|
||||||
delete iter.value();
|
SoundBuffer::deref(iter->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
void play(const QByteArray &filename,
|
void play(const std::string &filename,
|
||||||
int volume,
|
int volume,
|
||||||
int pitch)
|
int pitch)
|
||||||
{
|
{
|
||||||
|
@ -233,7 +234,7 @@ struct SoundEmitter
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SoundBuffer *allocateBuffer(const QByteArray &filename)
|
SoundBuffer *allocateBuffer(const std::string &filename)
|
||||||
{
|
{
|
||||||
SoundBuffer *buffer = bufferHash.value(filename, 0);
|
SoundBuffer *buffer = bufferHash.value(filename, 0);
|
||||||
|
|
||||||
|
@ -252,7 +253,7 @@ private:
|
||||||
SDL_RWops dataSource;
|
SDL_RWops dataSource;
|
||||||
const char *extension;
|
const char *extension;
|
||||||
|
|
||||||
shState->fileSystem().openRead(dataSource, filename.constData(),
|
shState->fileSystem().openRead(dataSource, filename.c_str(),
|
||||||
FileSystem::Audio, false, &extension);
|
FileSystem::Audio, false, &extension);
|
||||||
|
|
||||||
Sound_Sample *sampleHandle = Sound_NewSample(&dataSource, extension, 0, streamBufSize);
|
Sound_Sample *sampleHandle = Sound_NewSample(&dataSource, extension, 0, streamBufSize);
|
||||||
|
@ -285,7 +286,7 @@ private:
|
||||||
while (wouldBeBytes > SE_CACHE_MEM && !buffers.isEmpty())
|
while (wouldBeBytes > SE_CACHE_MEM && !buffers.isEmpty())
|
||||||
{
|
{
|
||||||
SoundBuffer *last = buffers.tail();
|
SoundBuffer *last = buffers.tail();
|
||||||
bufferHash.remove(last->key);
|
bufferHash.erase(last->key);
|
||||||
buffers.remove(last->link);
|
buffers.remove(last->link);
|
||||||
|
|
||||||
wouldBeBytes -= last->bytes;
|
wouldBeBytes -= last->bytes;
|
||||||
|
|
|
@ -28,9 +28,6 @@
|
||||||
|
|
||||||
#include <pixman.h>
|
#include <pixman.h>
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QChar>
|
|
||||||
|
|
||||||
#include "gl-util.h"
|
#include "gl-util.h"
|
||||||
#include "quad.h"
|
#include "quad.h"
|
||||||
#include "quadarray.h"
|
#include "quadarray.h"
|
||||||
|
@ -944,6 +941,50 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
|
||||||
modified();
|
modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* http://www.lemoda.net/c/utf8-to-ucs2/index.html */
|
||||||
|
static uint16_t utf8_to_ucs2(const char *_input,
|
||||||
|
const char **end_ptr)
|
||||||
|
{
|
||||||
|
const unsigned char *input =
|
||||||
|
reinterpret_cast<const unsigned char*>(_input);
|
||||||
|
*end_ptr = _input;
|
||||||
|
|
||||||
|
if (input[0] == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (input[0] < 0x80)
|
||||||
|
{
|
||||||
|
*end_ptr = _input + 1;
|
||||||
|
|
||||||
|
return input[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((input[0] & 0xE0) == 0xE0)
|
||||||
|
{
|
||||||
|
if (input[1] == 0 || input[2] == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*end_ptr = _input + 3;
|
||||||
|
|
||||||
|
return (input[0] & 0x0F)<<12 |
|
||||||
|
(input[1] & 0x3F)<<6 |
|
||||||
|
(input[2] & 0x3F);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((input[0] & 0xC0) == 0xC0)
|
||||||
|
{
|
||||||
|
if (input[1] == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*end_ptr = _input + 2;
|
||||||
|
|
||||||
|
return (input[0] & 0x1F)<<6 |
|
||||||
|
(input[1] & 0x3F);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
IntRect Bitmap::textSize(const char *str)
|
IntRect Bitmap::textSize(const char *str)
|
||||||
{
|
{
|
||||||
GUARD_DISPOSED;
|
GUARD_DISPOSED;
|
||||||
|
@ -955,10 +996,14 @@ IntRect Bitmap::textSize(const char *str)
|
||||||
int w, h;
|
int w, h;
|
||||||
TTF_SizeUTF8(font, str, &w, &h);
|
TTF_SizeUTF8(font, str, &w, &h);
|
||||||
|
|
||||||
QString qstr = QString::fromUtf8(str);
|
/* If str is one character long, *endPtr == 0 */
|
||||||
|
const char *endPtr;
|
||||||
|
uint16_t ucs2 = utf8_to_ucs2(str, &endPtr);
|
||||||
|
|
||||||
if (p->font->getItalic() && qstr.length() == 1)
|
/* For cursive characters, returning the advance
|
||||||
TTF_GlyphMetrics(font, qstr.at(0).unicode(), 0, 0, 0, 0, &w);
|
* as width yields better results */
|
||||||
|
if (p->font->getItalic() && *endPtr == '\0')
|
||||||
|
TTF_GlyphMetrics(font, ucs2, 0, 0, 0, 0, &w);
|
||||||
|
|
||||||
return IntRect(0, 0, w, h);
|
return IntRect(0, 0, w, h);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
** boost-hash.h
|
||||||
|
**
|
||||||
|
** This file is part of mkxp.
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||||
|
**
|
||||||
|
** mkxp is free software: you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation, either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** mkxp is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOSTHASH_H
|
||||||
|
#define BOOSTHASH_H
|
||||||
|
|
||||||
|
#include <boost/unordered/unordered_map.hpp>
|
||||||
|
#include <boost/unordered/unordered_set.hpp>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
/* Wrappers around the boost unordered template classes,
|
||||||
|
* exposing an interface similar to Qt's QHash/QSet */
|
||||||
|
|
||||||
|
template<typename K, typename V>
|
||||||
|
class BoostHash
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef boost::unordered_map<K, V> BoostType;
|
||||||
|
typedef std::pair<K, V> PairType;
|
||||||
|
BoostType p;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename BoostType::const_iterator const_iterator;
|
||||||
|
|
||||||
|
inline bool contains(const K &key) const
|
||||||
|
{
|
||||||
|
const_iterator iter = p.find(key);
|
||||||
|
|
||||||
|
return (iter != p.cend());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void insert(const K &key, const V &value)
|
||||||
|
{
|
||||||
|
p.insert(PairType(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void erase(const K &key)
|
||||||
|
{
|
||||||
|
p.erase(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const V value(const K &key) const
|
||||||
|
{
|
||||||
|
const_iterator iter = p.find(key);
|
||||||
|
|
||||||
|
if (iter == p.cend())
|
||||||
|
return V();
|
||||||
|
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const V value(const K &key, const V &defaultValue) const
|
||||||
|
{
|
||||||
|
const_iterator iter = p.find(key);
|
||||||
|
|
||||||
|
if (iter == p.cend())
|
||||||
|
return defaultValue;
|
||||||
|
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline V &operator[](const K &key)
|
||||||
|
{
|
||||||
|
return p[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_iterator cbegin() const
|
||||||
|
{
|
||||||
|
return p.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_iterator cend() const
|
||||||
|
{
|
||||||
|
return p.cend();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename K>
|
||||||
|
class BoostSet
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef boost::unordered_set<K> BoostType;
|
||||||
|
BoostType p;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename BoostType::const_iterator const_iterator;
|
||||||
|
|
||||||
|
inline bool contains(const K &key)
|
||||||
|
{
|
||||||
|
const_iterator iter = p.find(key);
|
||||||
|
|
||||||
|
return (iter != p.cend());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void insert(const K &key)
|
||||||
|
{
|
||||||
|
p.insert(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_iterator cbegin() const
|
||||||
|
{
|
||||||
|
return p.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_iterator cend() const
|
||||||
|
{
|
||||||
|
return p.cend();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BOOSTHASH_H
|
126
src/config.cpp
126
src/config.cpp
|
@ -21,12 +21,16 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <QSettings>
|
#include <boost/program_options/options_description.hpp>
|
||||||
#include <QFileInfo>
|
#include <boost/program_options/parsers.hpp>
|
||||||
#include <QString>
|
#include <boost/program_options/variables_map.hpp>
|
||||||
#include <QStringList>
|
#include <fstream>
|
||||||
#include <QFile>
|
|
||||||
#include <QRegExp>
|
#include "debugwriter.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
typedef std::vector<std::string> StringVec;
|
||||||
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
Config::Config()
|
Config::Config()
|
||||||
: debugMode(false),
|
: debugMode(false),
|
||||||
|
@ -46,68 +50,84 @@ Config::Config()
|
||||||
|
|
||||||
void Config::read()
|
void Config::read()
|
||||||
{
|
{
|
||||||
QSettings confFile("mkxp.conf", QSettings::IniFormat);
|
#define PO_DESC_ALL \
|
||||||
|
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(allowSymlinks, bool) \
|
||||||
|
PO_DESC(customScript, std::string)
|
||||||
|
|
||||||
#define READ_VAL(key, Type) key = confFile.value(#key, key).to##Type()
|
#define PO_DESC(key, type) (#key, po::value< type >()->default_value(key))
|
||||||
|
|
||||||
READ_VAL(debugMode, Bool);
|
po::options_description podesc;
|
||||||
READ_VAL(winResizable, Bool);
|
podesc.add_options()
|
||||||
READ_VAL(fullscreen, Bool);
|
PO_DESC_ALL
|
||||||
READ_VAL(fixedAspectRatio, Bool);
|
("RTP", po::value<StringVec>())
|
||||||
READ_VAL(smoothScaling, Bool);
|
;
|
||||||
READ_VAL(vsync, Bool);
|
|
||||||
READ_VAL(defScreenW, Int);
|
|
||||||
READ_VAL(defScreenH, Int);
|
|
||||||
READ_VAL(fixedFramerate, Int);
|
|
||||||
READ_VAL(frameSkip, Bool);
|
|
||||||
READ_VAL(solidFonts, Bool);
|
|
||||||
READ_VAL(gameFolder, ByteArray);
|
|
||||||
READ_VAL(allowSymlinks, Bool);
|
|
||||||
READ_VAL(customScript, ByteArray);
|
|
||||||
|
|
||||||
QStringList _rtps = confFile.value("RTPs").toStringList();
|
std::ifstream confFile;
|
||||||
Q_FOREACH(const QString &s, _rtps)
|
confFile.open("mkxp.conf");
|
||||||
rtps.push_back(s.toUtf8());
|
|
||||||
|
|
||||||
confFile.beginGroup("Binding");
|
po::variables_map vm;
|
||||||
|
po::store(po::parse_config_file(confFile, podesc, true), vm);
|
||||||
|
po::notify(vm);
|
||||||
|
|
||||||
QStringList bindingKeys = confFile.childKeys();
|
confFile.close();
|
||||||
Q_FOREACH (const QString &key, bindingKeys)
|
|
||||||
{
|
|
||||||
QVariant value = confFile.value(key);
|
|
||||||
|
|
||||||
/* Convert QString to QByteArray */
|
// Not gonna take your shit boost
|
||||||
if (value.type() == QVariant::String)
|
#define GUARD_ALL( exp ) try { exp } catch(...) {}
|
||||||
value = value.toString().toUtf8();
|
|
||||||
|
|
||||||
bindingConf.insert(key.toLatin1(), value);
|
#undef PO_DESC
|
||||||
}
|
#define PO_DESC(key, type) GUARD_ALL( key = vm[#key].as< type >(); )
|
||||||
|
|
||||||
confFile.endGroup();
|
PO_DESC_ALL;
|
||||||
|
|
||||||
|
GUARD_ALL( rtps = vm["RTP"].as<StringVec>(); );
|
||||||
|
|
||||||
|
#undef PO_DESC
|
||||||
|
#undef PO_DESC_ALL
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::readGameINI()
|
void Config::readGameINI()
|
||||||
{
|
{
|
||||||
if (!customScript.isEmpty())
|
if (!customScript.empty())
|
||||||
{
|
{
|
||||||
game.title = basename(customScript.constData());
|
game.title = basename(customScript.c_str());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSettings gameINI(gameFolder + "/Game.ini", QSettings::IniFormat);
|
po::options_description podesc;
|
||||||
QFileInfo finfo(gameFolder.constData());
|
podesc.add_options()
|
||||||
game.title = gameINI.value("Game/Title", finfo.baseName()).toByteArray();
|
("Game.Title", po::value<std::string>())
|
||||||
|
("Game.Scripts", po::value<std::string>())
|
||||||
|
;
|
||||||
|
|
||||||
/* Gotta read the "Scripts" entry manually because Qt can't handle '\' */
|
std::string iniPath = gameFolder + "/Game.ini";
|
||||||
QFile gameINIFile(gameFolder + "/Game.ini");
|
|
||||||
if (gameINIFile.open(QFile::ReadOnly))
|
std::ifstream iniFile;
|
||||||
{
|
iniFile.open((iniPath).c_str());
|
||||||
QString gameINIContents = gameINIFile.readAll();
|
|
||||||
QRegExp scriptsRE(".*Scripts=(.*)\r\nTitle=.*");
|
po::variables_map vm;
|
||||||
if (scriptsRE.exactMatch(gameINIContents))
|
po::store(po::parse_config_file(iniFile, podesc, true), vm);
|
||||||
{
|
po::notify(vm);
|
||||||
game.scripts = scriptsRE.cap(1).toUtf8();
|
|
||||||
game.scripts.replace('\\', '/');
|
iniFile.close();
|
||||||
}
|
|
||||||
}
|
GUARD_ALL( game.title = vm["Game.Title"].as<std::string>(); );
|
||||||
|
GUARD_ALL( game.scripts = vm["Game.Scripts"].as<std::string>(); );
|
||||||
|
|
||||||
|
strReplace(game.scripts, '\\', '/');
|
||||||
|
|
||||||
|
if (game.title.empty())
|
||||||
|
game.title = basename(gameFolder.c_str());
|
||||||
}
|
}
|
||||||
|
|
19
src/config.h
19
src/config.h
|
@ -22,10 +22,7 @@
|
||||||
#ifndef CONFIG_H
|
#ifndef CONFIG_H
|
||||||
#define CONFIG_H
|
#define CONFIG_H
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <string>
|
||||||
#include <QHash>
|
|
||||||
#include <QVariant>
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct Config
|
struct Config
|
||||||
|
@ -46,20 +43,16 @@ struct Config
|
||||||
|
|
||||||
bool solidFonts;
|
bool solidFonts;
|
||||||
|
|
||||||
QByteArray gameFolder;
|
std::string gameFolder;
|
||||||
bool allowSymlinks;
|
bool allowSymlinks;
|
||||||
|
|
||||||
QByteArray customScript;
|
std::string customScript;
|
||||||
std::vector<QByteArray> rtps;
|
std::vector<std::string> rtps;
|
||||||
|
|
||||||
/* Any values in the [Binding]
|
|
||||||
* group are collected here */
|
|
||||||
QHash<QByteArray, QVariant> bindingConf;
|
|
||||||
|
|
||||||
/* Game INI contents */
|
/* Game INI contents */
|
||||||
struct {
|
struct {
|
||||||
QByteArray scripts;
|
std::string scripts;
|
||||||
QByteArray title;
|
std::string title;
|
||||||
} game;
|
} game;
|
||||||
|
|
||||||
Config();
|
Config();
|
||||||
|
|
|
@ -20,42 +20,30 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "debuglogger.h"
|
#include "debuglogger.h"
|
||||||
|
#include "debugwriter.h"
|
||||||
|
|
||||||
#include <glew.h>
|
#include <glew.h>
|
||||||
|
#include <iostream>
|
||||||
#include <QFile>
|
|
||||||
#include <QTime>
|
|
||||||
#include <QTextStream>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
struct DebugLoggerPrivate
|
struct DebugLoggerPrivate
|
||||||
{
|
{
|
||||||
QFile logFile;
|
std::ostream *stream;
|
||||||
QTextStream *stream;
|
|
||||||
|
|
||||||
DebugLoggerPrivate(const char *logFilename)
|
DebugLoggerPrivate(const char *logFilename)
|
||||||
{
|
{
|
||||||
if (logFilename)
|
(void) logFilename;
|
||||||
{
|
|
||||||
logFile.setFileName(logFilename);
|
stream = &std::clog;
|
||||||
logFile.open(QFile::WriteOnly);
|
|
||||||
stream = new QTextStream(&logFile);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream = new QTextStream(stderr, QIODevice::WriteOnly);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~DebugLoggerPrivate()
|
~DebugLoggerPrivate()
|
||||||
{
|
{
|
||||||
delete stream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeTimestamp()
|
void writeTimestamp()
|
||||||
{
|
{
|
||||||
QTime time = QTime::currentTime();
|
// FIXME reintroduce proper time stamps (is this even necessary??)
|
||||||
*stream << "[" << time.toString().toLatin1() << "] ";
|
*stream << "[GLDEBUG] ";
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeLine(const char *line)
|
void writeLine(const char *line)
|
||||||
|
@ -114,7 +102,7 @@ DebugLogger::DebugLogger(const char *filename)
|
||||||
else if (GLEW_AMD_debug_output)
|
else if (GLEW_AMD_debug_output)
|
||||||
glDebugMessageCallbackAMD(amdDebugFunc, p);
|
glDebugMessageCallbackAMD(amdDebugFunc, p);
|
||||||
else
|
else
|
||||||
qDebug() << "DebugLogger: no debug extensions found";
|
Debug() << "DebugLogger: no debug extensions found";
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugLogger::~DebugLogger()
|
DebugLogger::~DebugLogger()
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
** debugwriter.h
|
||||||
|
**
|
||||||
|
** This file is part of mkxp.
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||||
|
**
|
||||||
|
** mkxp is free software: you can redistribute it and/or modify
|
||||||
|
** it under the terms of the GNU General Public License as published by
|
||||||
|
** the Free Software Foundation, either version 2 of the License, or
|
||||||
|
** (at your option) any later version.
|
||||||
|
**
|
||||||
|
** mkxp is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
** GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License
|
||||||
|
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEBUGWRITER_H
|
||||||
|
#define DEBUGWRITER_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
/* A cheap replacement for Debug() */
|
||||||
|
|
||||||
|
class Debug
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Debug()
|
||||||
|
{
|
||||||
|
buf << std::boolalpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Debug &operator<<(const T &t)
|
||||||
|
{
|
||||||
|
buf << t;
|
||||||
|
buf << " ";
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Debug()
|
||||||
|
{
|
||||||
|
std::clog << buf.str() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::stringstream buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DEBUGWRITER_H
|
|
@ -29,11 +29,10 @@
|
||||||
|
|
||||||
#include "sharedstate.h"
|
#include "sharedstate.h"
|
||||||
#include "graphics.h"
|
#include "graphics.h"
|
||||||
|
#include "debugwriter.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
bool EventThread::keyStates[] = { false };
|
bool EventThread::keyStates[] = { false };
|
||||||
|
|
||||||
EventThread::JoyState EventThread::joyState =
|
EventThread::JoyState EventThread::joyState =
|
||||||
|
@ -97,7 +96,7 @@ void EventThread::process(RGSSThreadData &rtData)
|
||||||
{
|
{
|
||||||
if (!SDL_WaitEvent(&event))
|
if (!SDL_WaitEvent(&event))
|
||||||
{
|
{
|
||||||
qDebug() << "EventThread: Event error";
|
Debug() << "EventThread: Event error";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +140,7 @@ void EventThread::process(RGSSThreadData &rtData)
|
||||||
case SDL_QUIT :
|
case SDL_QUIT :
|
||||||
case REQUEST_TERMINATION :
|
case REQUEST_TERMINATION :
|
||||||
terminate = true;
|
terminate = true;
|
||||||
qDebug() << "EventThread termination requested";
|
Debug() << "EventThread termination requested";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_KEYDOWN :
|
case SDL_KEYDOWN :
|
||||||
|
@ -173,13 +172,13 @@ void EventThread::process(RGSSThreadData &rtData)
|
||||||
if (fullscreen)
|
if (fullscreen)
|
||||||
{
|
{
|
||||||
/* Prevent fullscreen flicker */
|
/* Prevent fullscreen flicker */
|
||||||
strncpy(pendingTitle, rtData.config.game.title.constData(),
|
strncpy(pendingTitle, rtData.config.game.title.c_str(),
|
||||||
sizeof(pendingTitle));
|
sizeof(pendingTitle));
|
||||||
havePendingTitle = true;
|
havePendingTitle = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_SetWindowTitle(win, rtData.config.game.title.constData());
|
SDL_SetWindowTitle(win, rtData.config.game.title.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -201,7 +200,7 @@ void EventThread::process(RGSSThreadData &rtData)
|
||||||
|
|
||||||
case REQUEST_MESSAGEBOX :
|
case REQUEST_MESSAGEBOX :
|
||||||
SDL_ShowSimpleMessageBox(event.user.code,
|
SDL_ShowSimpleMessageBox(event.user.code,
|
||||||
rtData.config.game.title.constData(),
|
rtData.config.game.title.c_str(),
|
||||||
(const char*) event.user.data1, win);
|
(const char*) event.user.data1, win);
|
||||||
free(event.user.data1);
|
free(event.user.data1);
|
||||||
msgBoxDone = true;
|
msgBoxDone = true;
|
||||||
|
@ -217,7 +216,7 @@ void EventThread::process(RGSSThreadData &rtData)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
snprintf(buffer, sizeof(buffer), "%s - %d FPS",
|
snprintf(buffer, sizeof(buffer), "%s - %d FPS",
|
||||||
rtData.config.game.title.constData(), event.user.code);
|
rtData.config.game.title.c_str(), event.user.code);
|
||||||
|
|
||||||
/* Updating the window title in fullscreen
|
/* Updating the window title in fullscreen
|
||||||
* mode seems to cause flickering */
|
* mode seems to cause flickering */
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include <SDL_mouse.h>
|
#include <SDL_mouse.h>
|
||||||
#include <SDL_mutex.h>
|
#include <SDL_mutex.h>
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <string>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ struct RGSSThreadData
|
||||||
|
|
||||||
Config config;
|
Config config;
|
||||||
|
|
||||||
QByteArray rgssErrorMsg;
|
std::string rgssErrorMsg;
|
||||||
|
|
||||||
volatile bool rqScreenshot;
|
volatile bool rqScreenshot;
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#ifndef EXCEPTION_H
|
#ifndef EXCEPTION_H
|
||||||
#define EXCEPTION_H
|
#define EXCEPTION_H
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <string>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
struct Exception
|
struct Exception
|
||||||
|
@ -44,19 +44,19 @@ struct Exception
|
||||||
};
|
};
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
QByteArray fmt;
|
std::string fmt;
|
||||||
QByteArray arg1;
|
std::string arg1;
|
||||||
QByteArray arg2;
|
std::string arg2;
|
||||||
|
|
||||||
Exception(Type type, QByteArray fmt,
|
Exception(Type type, std::string fmt,
|
||||||
QByteArray arg1 = QByteArray(),
|
std::string arg1 = std::string(),
|
||||||
QByteArray arg2 = QByteArray())
|
std::string arg2 = std::string())
|
||||||
: type(type), fmt(fmt), arg1(arg1), arg2(arg2)
|
: type(type), fmt(fmt), arg1(arg1), arg2(arg2)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void snprintf(char *buffer, size_t bufSize) const
|
void snprintf(char *buffer, size_t bufSize) const
|
||||||
{
|
{
|
||||||
::snprintf(buffer, bufSize, fmt.constData(), arg1.constData(), arg2.constData());
|
::snprintf(buffer, bufSize, fmt.c_str(), arg1.c_str(), arg2.c_str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,22 +23,18 @@
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
#include "boost-hash.h"
|
||||||
|
#include "debugwriter.h"
|
||||||
|
|
||||||
#include <physfs.h>
|
#include <physfs.h>
|
||||||
|
|
||||||
#include <SDL_sound.h>
|
#include <SDL_sound.h>
|
||||||
|
|
||||||
#include <QHash>
|
|
||||||
#include <QSet>
|
|
||||||
#include <QByteArray>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
struct RGSS_entryData
|
struct RGSS_entryData
|
||||||
{
|
{
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
|
@ -73,11 +69,11 @@ struct RGSS_archiveData
|
||||||
|
|
||||||
/* Maps: file path
|
/* Maps: file path
|
||||||
* to: entry data */
|
* to: entry data */
|
||||||
QHash<QByteArray, RGSS_entryData> entryHash;
|
BoostHash<std::string, RGSS_entryData> entryHash;
|
||||||
|
|
||||||
/* Maps: directory path,
|
/* Maps: directory path,
|
||||||
* to: list of contained entries */
|
* to: list of contained entries */
|
||||||
QHash<QByteArray, QSet<QByteArray> > dirHash;
|
BoostHash<std::string, BoostSet<std::string> > dirHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -313,7 +309,7 @@ RGSS_openArchive(PHYSFS_Io *io, const char *, int forWrite)
|
||||||
uint32_t magic = RGSS_MAGIC;
|
uint32_t magic = RGSS_MAGIC;
|
||||||
|
|
||||||
/* Top level entry list */
|
/* Top level entry list */
|
||||||
QSet<QByteArray> &topLevel = data->dirHash["."];
|
BoostSet<std::string> &topLevel = data->dirHash["."];
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -373,7 +369,7 @@ RGSS_openArchive(PHYSFS_Io *io, const char *, int forWrite)
|
||||||
const char *dir = nameBuf;
|
const char *dir = nameBuf;
|
||||||
const char *entry = &nameBuf[i+1];
|
const char *entry = &nameBuf[i+1];
|
||||||
|
|
||||||
QSet<QByteArray> &entryList = data->dirHash[dir];
|
BoostSet<std::string> &entryList = data->dirHash[dir];
|
||||||
entryList.insert(entry);
|
entryList.insert(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,16 +386,16 @@ RGSS_enumerateFiles(void *opaque, const char *dirname,
|
||||||
{
|
{
|
||||||
RGSS_archiveData *data = static_cast<RGSS_archiveData*>(opaque);
|
RGSS_archiveData *data = static_cast<RGSS_archiveData*>(opaque);
|
||||||
|
|
||||||
QByteArray _dirname(dirname);
|
std::string _dirname(dirname);
|
||||||
|
|
||||||
if (!data->dirHash.contains(_dirname))
|
if (!data->dirHash.contains(_dirname))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QSet<QByteArray> &entries = data->dirHash.value(_dirname);
|
const BoostSet<std::string> &entries = data->dirHash[_dirname];
|
||||||
|
|
||||||
QSet<QByteArray>::const_iterator iter;
|
BoostSet<std::string>::const_iterator iter;
|
||||||
for (iter = entries.begin(); iter != entries.end(); ++iter)
|
for (iter = entries.cbegin(); iter != entries.cend(); ++iter)
|
||||||
cb(callbackdata, origdir, iter->constData());
|
cb(callbackdata, origdir, iter->c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
static PHYSFS_Io*
|
static PHYSFS_Io*
|
||||||
|
@ -500,9 +496,9 @@ static const PHYSFS_Archiver RGSS_Archiver =
|
||||||
struct FileSystemPrivate
|
struct FileSystemPrivate
|
||||||
{
|
{
|
||||||
/* All keys are lower case */
|
/* All keys are lower case */
|
||||||
QHash<QByteArray, QByteArray> pathCache;
|
BoostHash<std::string, std::string> pathCache;
|
||||||
|
|
||||||
std::vector<QByteArray> extensions[FileSystem::Undefined];
|
std::vector<std::string> extensions[FileSystem::Undefined];
|
||||||
|
|
||||||
/* Attempt to locate an extension string in a filename.
|
/* Attempt to locate an extension string in a filename.
|
||||||
* Either a pointer into the input string pointing at the
|
* Either a pointer into the input string pointing at the
|
||||||
|
@ -535,7 +531,7 @@ struct FileSystemPrivate
|
||||||
|
|
||||||
buff[i] = '\0';
|
buff[i] = '\0';
|
||||||
|
|
||||||
QByteArray key(buff);
|
std::string key(buff);
|
||||||
|
|
||||||
if (pathCache.contains(key))
|
if (pathCache.contains(key))
|
||||||
{
|
{
|
||||||
|
@ -544,17 +540,17 @@ struct FileSystemPrivate
|
||||||
if (foundExt)
|
if (foundExt)
|
||||||
*foundExt = findExt(filename);
|
*foundExt = findExt(filename);
|
||||||
|
|
||||||
return pathCache[key].constData();
|
return pathCache[key].c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
char buff2[512];
|
char buff2[512];
|
||||||
|
|
||||||
if (type != FileSystem::Undefined)
|
if (type != FileSystem::Undefined)
|
||||||
{
|
{
|
||||||
std::vector<QByteArray> &extList = extensions[type];
|
std::vector<std::string> &extList = extensions[type];
|
||||||
for (size_t i = 0; i < extList.size(); ++i)
|
for (size_t i = 0; i < extList.size(); ++i)
|
||||||
{
|
{
|
||||||
const char *ext = extList[i].constData();
|
const char *ext = extList[i].c_str();
|
||||||
|
|
||||||
snprintf(buff2, sizeof(buff2), "%s.%s", buff, ext);
|
snprintf(buff2, sizeof(buff2), "%s.%s", buff, ext);
|
||||||
key = buff2;
|
key = buff2;
|
||||||
|
@ -564,7 +560,7 @@ struct FileSystemPrivate
|
||||||
if (foundExt)
|
if (foundExt)
|
||||||
*foundExt = ext;
|
*foundExt = ext;
|
||||||
|
|
||||||
return pathCache[key].constData();
|
return pathCache[key].c_str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -640,7 +636,7 @@ FileSystem::~FileSystem()
|
||||||
delete p;
|
delete p;
|
||||||
|
|
||||||
if (PHYSFS_deinit() == 0)
|
if (PHYSFS_deinit() == 0)
|
||||||
qDebug() << "PhyFS failed to deinit.";
|
Debug() << "PhyFS failed to deinit.";
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSystem::addPath(const char *path)
|
void FileSystem::addPath(const char *path)
|
||||||
|
@ -660,16 +656,16 @@ static void cacheEnumCB(void *d, const char *origdir,
|
||||||
else
|
else
|
||||||
strncpy(buf, fname, sizeof(buf));
|
strncpy(buf, fname, sizeof(buf));
|
||||||
|
|
||||||
QByteArray mixedCase(buf);
|
std::string mixedCase(buf);
|
||||||
|
|
||||||
for (char *p = buf; *p; ++p)
|
for (char *p = buf; *p; ++p)
|
||||||
*p = tolower(*p);
|
*p = tolower(*p);
|
||||||
|
|
||||||
QByteArray lowerCase(buf);
|
std::string lowerCase(buf);
|
||||||
|
|
||||||
p->pathCache.insert(lowerCase, mixedCase);
|
p->pathCache.insert(lowerCase, mixedCase);
|
||||||
|
|
||||||
PHYSFS_enumerateFilesCallback(mixedCase.constData(), cacheEnumCB, p);
|
PHYSFS_enumerateFilesCallback(mixedCase.c_str(), cacheEnumCB, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSystem::createPathCache()
|
void FileSystem::createPathCache()
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
#include "etc.h"
|
#include "etc.h"
|
||||||
#include "etc-internal.h"
|
#include "etc-internal.h"
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
class Flashable
|
class Flashable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
70
src/font.cpp
70
src/font.cpp
|
@ -24,17 +24,16 @@
|
||||||
#include "sharedstate.h"
|
#include "sharedstate.h"
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
#include "boost-hash.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "../liberation.ttf.xxd"
|
#include "../liberation.ttf.xxd"
|
||||||
|
|
||||||
#include <SDL_ttf.h>
|
#include <SDL_ttf.h>
|
||||||
|
|
||||||
#include <QHash>
|
|
||||||
#include <QByteArray>
|
|
||||||
#include <QPair>
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
#define BUNDLED_FONT liberation
|
#define BUNDLED_FONT liberation
|
||||||
|
|
||||||
#define BUNDLED_FONT_D(f) assets_## f ##_ttf
|
#define BUNDLED_FONT_D(f) assets_## f ##_ttf
|
||||||
|
@ -44,11 +43,17 @@
|
||||||
#define BNDL_F_D(f) BUNDLED_FONT_D(f)
|
#define BNDL_F_D(f) BUNDLED_FONT_D(f)
|
||||||
#define BNDL_F_L(f) BUNDLED_FONT_L(f)
|
#define BNDL_F_L(f) BUNDLED_FONT_L(f)
|
||||||
|
|
||||||
typedef QPair<QByteArray, int> FontKey;
|
typedef std::pair<std::string, int> FontKey;
|
||||||
|
|
||||||
|
static void strToLower(std::string &str)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < str.size(); ++i)
|
||||||
|
str[i] = tolower(str[i]);
|
||||||
|
}
|
||||||
|
|
||||||
struct FontPoolPrivate
|
struct FontPoolPrivate
|
||||||
{
|
{
|
||||||
QHash<FontKey, TTF_Font*> hash;
|
BoostHash<FontKey, TTF_Font*> hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
FontPool::FontPool()
|
FontPool::FontPool()
|
||||||
|
@ -58,9 +63,9 @@ FontPool::FontPool()
|
||||||
|
|
||||||
FontPool::~FontPool()
|
FontPool::~FontPool()
|
||||||
{
|
{
|
||||||
QHash<FontKey, TTF_Font*>::const_iterator iter;
|
BoostHash<FontKey, TTF_Font*>::const_iterator iter;
|
||||||
for (iter = p->hash.begin(); iter != p->hash.end(); ++iter)
|
for (iter = p->hash.cbegin(); iter != p->hash.cend(); ++iter)
|
||||||
TTF_CloseFont(iter.value());
|
TTF_CloseFont(iter->second);
|
||||||
|
|
||||||
delete p;
|
delete p;
|
||||||
}
|
}
|
||||||
|
@ -74,13 +79,19 @@ _TTF_Font *FontPool::request(const char *filename,
|
||||||
int size)
|
int size)
|
||||||
{
|
{
|
||||||
// FIXME Find out how font path resolution is done in VX/Ace
|
// FIXME Find out how font path resolution is done in VX/Ace
|
||||||
QByteArray nameKey = QByteArray(filename).toLower();
|
std::string nameKey(filename);
|
||||||
nameKey.replace(' ', '_');
|
strToLower(nameKey);
|
||||||
|
strReplace(nameKey, ' ', '_');
|
||||||
|
|
||||||
bool useBundled = false;
|
bool useBundled = false;
|
||||||
QByteArray path = QByteArray("Fonts/") + nameKey;
|
std::string path = std::string("Fonts/") + nameKey;
|
||||||
if (!shState->fileSystem().exists(path.constData(), FileSystem::Font))
|
if (!shState->fileSystem().exists(path.c_str(), FileSystem::Font))
|
||||||
{
|
{
|
||||||
|
/* Use the same name key for the bundled font
|
||||||
|
* even when it resulted from multiple different
|
||||||
|
* font name requests. The space at the front is
|
||||||
|
* to prevent collisions (spaces are normally
|
||||||
|
* replaced with '_' */
|
||||||
useBundled = true;
|
useBundled = true;
|
||||||
nameKey = " bundled";
|
nameKey = " bundled";
|
||||||
}
|
}
|
||||||
|
@ -90,14 +101,9 @@ _TTF_Font *FontPool::request(const char *filename,
|
||||||
TTF_Font *font = p->hash.value(key, 0);
|
TTF_Font *font = p->hash.value(key, 0);
|
||||||
|
|
||||||
if (font)
|
if (font)
|
||||||
{
|
|
||||||
// static int i=0;qDebug() << "FontPool: <?+>" << i++;
|
|
||||||
return font;
|
return font;
|
||||||
}
|
|
||||||
|
|
||||||
// qDebug() << "FontPool: <?->";
|
/* Not in hash, open */
|
||||||
|
|
||||||
/* Not in hash, create */
|
|
||||||
SDL_RWops *ops;
|
SDL_RWops *ops;
|
||||||
|
|
||||||
if (useBundled)
|
if (useBundled)
|
||||||
|
@ -107,7 +113,7 @@ _TTF_Font *FontPool::request(const char *filename,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ops = SDL_AllocRW();
|
ops = SDL_AllocRW();
|
||||||
shState->fileSystem().openRead(*ops, path.constData(), FileSystem::Font, true);
|
shState->fileSystem().openRead(*ops, path.c_str(), FileSystem::Font, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME 0.9 is guesswork at this point
|
// FIXME 0.9 is guesswork at this point
|
||||||
|
@ -124,7 +130,7 @@ _TTF_Font *FontPool::request(const char *filename,
|
||||||
|
|
||||||
struct FontPrivate
|
struct FontPrivate
|
||||||
{
|
{
|
||||||
QByteArray name;
|
std::string name;
|
||||||
int size;
|
int size;
|
||||||
bool bold;
|
bool bold;
|
||||||
bool italic;
|
bool italic;
|
||||||
|
@ -132,7 +138,7 @@ struct FontPrivate
|
||||||
|
|
||||||
Color colorTmp;
|
Color colorTmp;
|
||||||
|
|
||||||
static QByteArray defaultName;
|
static std::string defaultName;
|
||||||
static int defaultSize;
|
static int defaultSize;
|
||||||
static bool defaultBold;
|
static bool defaultBold;
|
||||||
static bool defaultItalic;
|
static bool defaultItalic;
|
||||||
|
@ -144,14 +150,14 @@ struct FontPrivate
|
||||||
|
|
||||||
FontPrivate(const char *name = 0,
|
FontPrivate(const char *name = 0,
|
||||||
int size = 0)
|
int size = 0)
|
||||||
: name(name ? QByteArray(name) : defaultName),
|
: name(name ? std::string(name) : defaultName),
|
||||||
size(size ? size : defaultSize),
|
size(size ? size : defaultSize),
|
||||||
bold(defaultBold),
|
bold(defaultBold),
|
||||||
italic(defaultItalic),
|
italic(defaultItalic),
|
||||||
color(&colorTmp),
|
color(&colorTmp),
|
||||||
colorTmp(*defaultColor)
|
colorTmp(*defaultColor)
|
||||||
{
|
{
|
||||||
sdlFont = shState->fontPool().request(this->name.constData(),
|
sdlFont = shState->fontPool().request(this->name.c_str(),
|
||||||
this->size);
|
this->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +172,7 @@ struct FontPrivate
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
QByteArray FontPrivate::defaultName = "Arial";
|
std::string FontPrivate::defaultName = "Arial";
|
||||||
int FontPrivate::defaultSize = 22;
|
int FontPrivate::defaultSize = 22;
|
||||||
bool FontPrivate::defaultBold = false;
|
bool FontPrivate::defaultBold = false;
|
||||||
bool FontPrivate::defaultItalic = false;
|
bool FontPrivate::defaultItalic = false;
|
||||||
|
@ -176,9 +182,9 @@ Color FontPrivate::defaultColorTmp(255, 255, 255, 255);
|
||||||
|
|
||||||
bool Font::doesExist(const char *name)
|
bool Font::doesExist(const char *name)
|
||||||
{
|
{
|
||||||
QByteArray path = QByteArray("fonts/") + QByteArray(name);
|
std::string path = std::string("fonts/") + std::string(name);
|
||||||
|
|
||||||
return shState->fileSystem().exists(path.constData(), FileSystem::Font);
|
return shState->fileSystem().exists(path.c_str(), FileSystem::Font);
|
||||||
}
|
}
|
||||||
|
|
||||||
Font::Font(const char *name,
|
Font::Font(const char *name,
|
||||||
|
@ -199,7 +205,7 @@ Font::~Font()
|
||||||
|
|
||||||
const char *Font::getName() const
|
const char *Font::getName() const
|
||||||
{
|
{
|
||||||
return p->name.constData();
|
return p->name.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::setName(const char *value)
|
void Font::setName(const char *value)
|
||||||
|
@ -213,7 +219,7 @@ void Font::setSize(int value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p->size = value;
|
p->size = value;
|
||||||
p->sdlFont = shState->fontPool().request(p->name.constData(), value);
|
p->sdlFont = shState->fontPool().request(p->name.c_str(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef CHK_DISP
|
#undef CHK_DISP
|
||||||
|
@ -231,7 +237,7 @@ DEF_ATTR_SIMPLE_STATIC(Font, DefaultColor, Color*, FontPrivate::defaultColor)
|
||||||
|
|
||||||
const char *Font::getDefaultName()
|
const char *Font::getDefaultName()
|
||||||
{
|
{
|
||||||
return FontPrivate::defaultName.constData();
|
return FontPrivate::defaultName.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::setDefaultName(const char *value)
|
void Font::setDefaultName(const char *value)
|
||||||
|
|
43
src/main.cpp
43
src/main.cpp
|
@ -27,14 +27,15 @@
|
||||||
#include <SDL_ttf.h>
|
#include <SDL_ttf.h>
|
||||||
#include <SDL_sound.h>
|
#include <SDL_sound.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "sharedstate.h"
|
#include "sharedstate.h"
|
||||||
#include "eventthread.h"
|
#include "eventthread.h"
|
||||||
#include "debuglogger.h"
|
#include "debuglogger.h"
|
||||||
|
#include "debugwriter.h"
|
||||||
|
|
||||||
#include "binding.h"
|
#include "binding.h"
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
static const char *reqExt[] =
|
static const char *reqExt[] =
|
||||||
{
|
{
|
||||||
"GL_ARB_fragment_shader",
|
"GL_ARB_fragment_shader",
|
||||||
|
@ -53,7 +54,7 @@ static const char *reqExt[] =
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rgssThreadError(RGSSThreadData *rtData, const QByteArray &msg)
|
rgssThreadError(RGSSThreadData *rtData, const std::string &msg)
|
||||||
{
|
{
|
||||||
rtData->rgssErrorMsg = msg;
|
rtData->rgssErrorMsg = msg;
|
||||||
rtData->ethread->requestTerminate();
|
rtData->ethread->requestTerminate();
|
||||||
|
@ -69,10 +70,10 @@ glGetStringInt(GLenum name)
|
||||||
static void
|
static void
|
||||||
printGLInfo()
|
printGLInfo()
|
||||||
{
|
{
|
||||||
qDebug() << "GL Vendor :" << glGetStringInt(GL_VENDOR);
|
Debug() << "GL Vendor :" << glGetStringInt(GL_VENDOR);
|
||||||
qDebug() << "GL Renderer :" << glGetStringInt(GL_RENDERER);
|
Debug() << "GL Renderer :" << glGetStringInt(GL_RENDERER);
|
||||||
qDebug() << "GL Version :" << glGetStringInt(GL_VERSION);
|
Debug() << "GL Version :" << glGetStringInt(GL_VERSION);
|
||||||
qDebug() << "GLSL Version :" << glGetStringInt(GL_SHADING_LANGUAGE_VERSION);
|
Debug() << "GLSL Version :" << glGetStringInt(GL_SHADING_LANGUAGE_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rgssThreadFun(void *userdata)
|
int rgssThreadFun(void *userdata)
|
||||||
|
@ -91,7 +92,7 @@ int rgssThreadFun(void *userdata)
|
||||||
|
|
||||||
if (!glCtx)
|
if (!glCtx)
|
||||||
{
|
{
|
||||||
rgssThreadError(threadData, QByteArray("Error creating context: ") + SDL_GetError());
|
rgssThreadError(threadData, std::string("Error creating context: ") + SDL_GetError());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +122,7 @@ int rgssThreadFun(void *userdata)
|
||||||
{
|
{
|
||||||
if (!glewIsSupported(reqExt[i]))
|
if (!glewIsSupported(reqExt[i]))
|
||||||
{
|
{
|
||||||
rgssThreadError(threadData, QByteArray("Required GL extension \"")
|
rgssThreadError(threadData, std::string("Required GL extension \"")
|
||||||
+ reqExt[i] + "\" not present");
|
+ reqExt[i] + "\" not present");
|
||||||
SDL_GL_DeleteContext(glCtx);
|
SDL_GL_DeleteContext(glCtx);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -181,7 +182,7 @@ int main(int, char *argv[])
|
||||||
|
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
|
||||||
{
|
{
|
||||||
qDebug() << "Error initializing SDL:" << SDL_GetError();
|
Debug() << "Error initializing SDL:" << SDL_GetError();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -189,7 +190,7 @@ int main(int, char *argv[])
|
||||||
int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG;
|
int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG;
|
||||||
if (IMG_Init(imgFlags) != imgFlags)
|
if (IMG_Init(imgFlags) != imgFlags)
|
||||||
{
|
{
|
||||||
qDebug() << "Error initializing SDL_image:" << SDL_GetError();
|
Debug() << "Error initializing SDL_image:" << SDL_GetError();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -197,7 +198,7 @@ int main(int, char *argv[])
|
||||||
|
|
||||||
if (TTF_Init() < 0)
|
if (TTF_Init() < 0)
|
||||||
{
|
{
|
||||||
qDebug() << "Error initializing SDL_ttf:" << SDL_GetError();
|
Debug() << "Error initializing SDL_ttf:" << SDL_GetError();
|
||||||
IMG_Quit();
|
IMG_Quit();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
|
||||||
|
@ -206,7 +207,7 @@ int main(int, char *argv[])
|
||||||
|
|
||||||
if (Sound_Init() == 0)
|
if (Sound_Init() == 0)
|
||||||
{
|
{
|
||||||
qDebug() << "Error initializing SDL_sound:" << Sound_GetError();
|
Debug() << "Error initializing SDL_sound:" << Sound_GetError();
|
||||||
TTF_Quit();
|
TTF_Quit();
|
||||||
IMG_Quit();
|
IMG_Quit();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
@ -224,13 +225,13 @@ int main(int, char *argv[])
|
||||||
if (conf.fullscreen)
|
if (conf.fullscreen)
|
||||||
winFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
winFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||||
|
|
||||||
win = SDL_CreateWindow(conf.game.title.constData(),
|
win = SDL_CreateWindow(conf.game.title.c_str(),
|
||||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||||
conf.defScreenW, conf.defScreenH, winFlags);
|
conf.defScreenW, conf.defScreenH, winFlags);
|
||||||
|
|
||||||
if (!win)
|
if (!win)
|
||||||
{
|
{
|
||||||
qDebug() << "Error creating window";
|
Debug() << "Error creating window";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +255,7 @@ int main(int, char *argv[])
|
||||||
/* We can stop waiting when the request was ack'd */
|
/* We can stop waiting when the request was ack'd */
|
||||||
if (rtData.rqTermAck)
|
if (rtData.rqTermAck)
|
||||||
{
|
{
|
||||||
qDebug() << "RGSS thread ack'd request after" << i*10 << "ms";
|
Debug() << "RGSS thread ack'd request after" << i*10 << "ms";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,17 +268,17 @@ int main(int, char *argv[])
|
||||||
if (rtData.rqTermAck)
|
if (rtData.rqTermAck)
|
||||||
SDL_WaitThread(rgssThread, 0);
|
SDL_WaitThread(rgssThread, 0);
|
||||||
else
|
else
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.constData(),
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.c_str(),
|
||||||
"The RGSS script seems to be stuck and mkxp will now force quit", win);
|
"The RGSS script seems to be stuck and mkxp will now force quit", win);
|
||||||
|
|
||||||
if (!rtData.rgssErrorMsg.isEmpty())
|
if (!rtData.rgssErrorMsg.empty())
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.constData(),
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.c_str(),
|
||||||
rtData.rgssErrorMsg.constData(), win);
|
rtData.rgssErrorMsg.c_str(), win);
|
||||||
|
|
||||||
/* Clean up any remainin events */
|
/* Clean up any remainin events */
|
||||||
eventThread.cleanup();
|
eventThread.cleanup();
|
||||||
|
|
||||||
qDebug() << "Shutting down.";
|
Debug() << "Shutting down.";
|
||||||
|
|
||||||
SDL_DestroyWindow(win);
|
SDL_DestroyWindow(win);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <SDL_timer.h>
|
#include <SDL_timer.h>
|
||||||
#include <glew.h>
|
#include <glew.h>
|
||||||
|
|
||||||
#include <QDebug>
|
#include "debugwriter.h"
|
||||||
|
|
||||||
struct TimerQuery
|
struct TimerQuery
|
||||||
{
|
{
|
||||||
|
@ -132,7 +132,7 @@ struct GPUTimerGLQuery : public PerfTimer
|
||||||
if (++counter < iter)
|
if (++counter < iter)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << " "
|
Debug() << " "
|
||||||
"Avg. GPU time:" << ((double) acc / (iter * 1000 * 1000)) << "ms";
|
"Avg. GPU time:" << ((double) acc / (iter * 1000 * 1000)) << "ms";
|
||||||
|
|
||||||
acc = counter = 0;
|
acc = counter = 0;
|
||||||
|
@ -181,7 +181,7 @@ struct CPUTimer : public PerfTimer
|
||||||
if (++counter < iter)
|
if (++counter < iter)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << "Avg. CPU time:" << ((double) acc / (iter * (perfFreq / 1000))) << "ms";
|
Debug() << "Avg. CPU time:" << ((double) acc / (iter * (perfFreq / 1000))) << "ms";
|
||||||
acc = counter = 0;
|
acc = counter = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -199,7 +199,7 @@ PerfTimer *createGPUTimer(int iter)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "GL_EXT_timer_query not present: cannot measure GPU performance";
|
Debug() << "GL_EXT_timer_query not present: cannot measure GPU performance";
|
||||||
return new GPUTimerDummy();
|
return new GPUTimerDummy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,6 @@
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
#include "sharedstate.h"
|
#include "sharedstate.h"
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
Scene::Scene()
|
Scene::Scene()
|
||||||
{
|
{
|
||||||
geometry.xOrigin = geometry.yOrigin = 0;
|
geometry.xOrigin = geometry.yOrigin = 0;
|
||||||
|
|
|
@ -22,10 +22,11 @@
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "sharedstate.h"
|
#include "sharedstate.h"
|
||||||
#include "glstate.h"
|
#include "glstate.h"
|
||||||
|
#include "debugwriter.h"
|
||||||
|
|
||||||
#include <glew.h>
|
#include <glew.h>
|
||||||
|
|
||||||
#include <QFile>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "../sprite.frag.xxd"
|
#include "../sprite.frag.xxd"
|
||||||
#include "../hue.frag.xxd"
|
#include "../hue.frag.xxd"
|
||||||
|
@ -48,16 +49,14 @@
|
||||||
#include "../blurV.vert.xxd"
|
#include "../blurV.vert.xxd"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
|
|
||||||
#define INIT_SHADER(vert, frag) \
|
#define INIT_SHADER(vert, frag) \
|
||||||
{ \
|
{ \
|
||||||
Shader::init(shader_##vert##_vert, shader_##vert##_vert_len, shader_##frag##_frag, shader_##frag##_frag_len); \
|
Shader::init(shader_##vert##_vert, shader_##vert##_vert_len, shader_##frag##_frag, shader_##frag##_frag_len); \
|
||||||
qDebug() << " From:" << #vert ".vert" << #frag ".frag"; \
|
Debug() << " From:" << #vert ".vert" << #frag ".frag"; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COMP(shader) qDebug() << "--- Compiling " #shader
|
#define COMP(shader) Debug() << "--- Compiling " #shader
|
||||||
|
|
||||||
#define GET_U(name) u_##name = glGetUniformLocation(program, #name)
|
#define GET_U(name) u_##name = glGetUniformLocation(program, #name)
|
||||||
|
|
||||||
|
@ -98,14 +97,14 @@ void Shader::init(const unsigned char *vert, int vertSize,
|
||||||
glCompileShader(vertShader);
|
glCompileShader(vertShader);
|
||||||
|
|
||||||
glGetObjectParameterivARB(vertShader, GL_COMPILE_STATUS, &success);
|
glGetObjectParameterivARB(vertShader, GL_COMPILE_STATUS, &success);
|
||||||
Q_ASSERT(success);
|
assert(success); // FIXME should really throw here instead
|
||||||
|
|
||||||
/* Compile fragment shader */
|
/* Compile fragment shader */
|
||||||
glShaderSource(fragShader, 1, (const GLchar**) &frag, (const GLint*) &fragSize);
|
glShaderSource(fragShader, 1, (const GLchar**) &frag, (const GLint*) &fragSize);
|
||||||
glCompileShader(fragShader);
|
glCompileShader(fragShader);
|
||||||
|
|
||||||
glGetObjectParameterivARB(fragShader, GL_COMPILE_STATUS, &success);
|
glGetObjectParameterivARB(fragShader, GL_COMPILE_STATUS, &success);
|
||||||
Q_ASSERT(success);
|
assert(success);
|
||||||
|
|
||||||
/* Link shader program */
|
/* Link shader program */
|
||||||
glAttachShader(program, vertShader);
|
glAttachShader(program, vertShader);
|
||||||
|
@ -118,23 +117,17 @@ void Shader::init(const unsigned char *vert, int vertSize,
|
||||||
glLinkProgram(program);
|
glLinkProgram(program);
|
||||||
|
|
||||||
glGetObjectParameterivARB(program, GL_LINK_STATUS, &success);
|
glGetObjectParameterivARB(program, GL_LINK_STATUS, &success);
|
||||||
Q_ASSERT(success);
|
assert(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::initFromFile(const char *_vertFile, const char *_fragFile)
|
void Shader::initFromFile(const char *_vertFile, const char *_fragFile)
|
||||||
{
|
{
|
||||||
QFile vertFile(_vertFile);
|
std::string vertContents, fragContents;
|
||||||
vertFile.open(QFile::ReadOnly);
|
readFile(_vertFile, vertContents);
|
||||||
QByteArray vertContents = vertFile.readAll();
|
readFile(_fragFile, fragContents);
|
||||||
vertFile.close();
|
|
||||||
|
|
||||||
QFile fragFile(_fragFile);
|
init((const unsigned char*) vertContents.c_str(), vertContents.size(),
|
||||||
fragFile.open(QFile::ReadOnly);
|
(const unsigned char*) fragContents.c_str(), fragContents.size());
|
||||||
QByteArray fragContents = fragFile.readAll();
|
|
||||||
fragFile.close();
|
|
||||||
|
|
||||||
init((const unsigned char*) vertContents.constData(), vertContents.size(),
|
|
||||||
(const unsigned char*) fragContents.constData(), fragContents.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setVec4Uniform(GLint location, const Vec4 &vec)
|
void Shader::setVec4Uniform(GLint location, const Vec4 &vec)
|
||||||
|
|
|
@ -36,11 +36,9 @@
|
||||||
#include "quad.h"
|
#include "quad.h"
|
||||||
#include "binding.h"
|
#include "binding.h"
|
||||||
|
|
||||||
#include <QFile>
|
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <QDebug>
|
#include <string>
|
||||||
|
|
||||||
SharedState *SharedState::instance = 0;
|
SharedState *SharedState::instance = 0;
|
||||||
static GlobalIBO *globalIBO = 0;
|
static GlobalIBO *globalIBO = 0;
|
||||||
|
@ -93,21 +91,26 @@ struct SharedStatePrivate
|
||||||
graphics(threadData),
|
graphics(threadData),
|
||||||
stampCounter(0)
|
stampCounter(0)
|
||||||
{
|
{
|
||||||
if (!config.gameFolder.isEmpty())
|
if (!config.gameFolder.empty())
|
||||||
{
|
{
|
||||||
int unused = chdir(config.gameFolder.constData());
|
int unused = chdir(config.gameFolder.c_str());
|
||||||
(void) unused;
|
(void) unused;
|
||||||
fileSystem.addPath(".");
|
fileSystem.addPath(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME find out correct archive filename
|
// FIXME find out correct archive filename
|
||||||
QByteArray archPath = GAME_ARCHIVE;
|
std::string archPath = GAME_ARCHIVE;
|
||||||
|
|
||||||
if (QFile::exists(archPath.constData()))
|
/* Check if a game archive exists */
|
||||||
fileSystem.addPath(archPath.constData());
|
FILE *tmp = fopen(archPath.c_str(), "r");
|
||||||
|
if (tmp)
|
||||||
|
{
|
||||||
|
fileSystem.addPath(archPath.c_str());
|
||||||
|
fclose(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < config.rtps.size(); ++i)
|
for (size_t i = 0; i < config.rtps.size(); ++i)
|
||||||
fileSystem.addPath(config.rtps[i].constData());
|
fileSystem.addPath(config.rtps[i].c_str());
|
||||||
|
|
||||||
fileSystem.createPathCache();
|
fileSystem.createPathCache();
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,6 @@
|
||||||
|
|
||||||
#include <sigc++/connection.h>
|
#include <sigc++/connection.h>
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
struct SpritePrivate
|
struct SpritePrivate
|
||||||
{
|
{
|
||||||
Bitmap *bitmap;
|
Bitmap *bitmap;
|
||||||
|
|
|
@ -23,17 +23,15 @@
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
#include "sharedstate.h"
|
#include "sharedstate.h"
|
||||||
#include "glstate.h"
|
#include "glstate.h"
|
||||||
|
#include "boost-hash.h"
|
||||||
|
#include "debugwriter.h"
|
||||||
|
|
||||||
#include <QHash>
|
#include <list>
|
||||||
#include <QQueue>
|
#include <utility>
|
||||||
#include <QList>
|
#include <assert.h>
|
||||||
#include <QLinkedList>
|
#include <string.h>
|
||||||
#include <QPair>
|
|
||||||
|
|
||||||
#include <QDebug>
|
typedef std::pair<uint16_t, uint16_t> Size;
|
||||||
|
|
||||||
typedef QPair<uint16_t, uint16_t> Size;
|
|
||||||
typedef QQueue<TEXFBO> ObjList;
|
|
||||||
|
|
||||||
static uint32_t byteCount(Size &s)
|
static uint32_t byteCount(Size &s)
|
||||||
{
|
{
|
||||||
|
@ -43,23 +41,23 @@ static uint32_t byteCount(Size &s)
|
||||||
struct CacheNode
|
struct CacheNode
|
||||||
{
|
{
|
||||||
TEXFBO obj;
|
TEXFBO obj;
|
||||||
QLinkedList<TEXFBO>::iterator prioIter;
|
std::list<TEXFBO>::iterator prioIter;
|
||||||
|
|
||||||
bool operator==(const CacheNode &o)
|
bool operator==(const CacheNode &o) const
|
||||||
{
|
{
|
||||||
return obj == o.obj;
|
return obj == o.obj;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QList<CacheNode> CNodeList;
|
typedef std::list<CacheNode> CNodeList;
|
||||||
|
|
||||||
struct TexPoolPrivate
|
struct TexPoolPrivate
|
||||||
{
|
{
|
||||||
/* Contains all cached TexFBOs, grouped by size */
|
/* Contains all cached TexFBOs, grouped by size */
|
||||||
QHash<Size, CNodeList> poolHash;
|
BoostHash<Size, CNodeList> poolHash;
|
||||||
|
|
||||||
/* Contains all cached TexFBOs, sorted by release time */
|
/* Contains all cached TexFBOs, sorted by release time */
|
||||||
QLinkedList<TEXFBO> priorityQueue;
|
std::list<TEXFBO> priorityQueue;
|
||||||
|
|
||||||
/* Maximal allowed cache memory */
|
/* Maximal allowed cache memory */
|
||||||
const uint32_t maxMemSize;
|
const uint32_t maxMemSize;
|
||||||
|
@ -88,14 +86,18 @@ TexPool::TexPool(uint32_t maxMemSize)
|
||||||
|
|
||||||
TexPool::~TexPool()
|
TexPool::~TexPool()
|
||||||
{
|
{
|
||||||
while (!p->priorityQueue.isEmpty())
|
std::list<TEXFBO>::iterator iter;
|
||||||
|
|
||||||
|
for (iter = p->priorityQueue.begin();
|
||||||
|
iter != p->priorityQueue.end();
|
||||||
|
++iter)
|
||||||
{
|
{
|
||||||
TEXFBO obj = p->priorityQueue.takeFirst();
|
TEXFBO obj = *iter;
|
||||||
TEXFBO::fini(obj);
|
TEXFBO::fini(obj);
|
||||||
--p->objCount;
|
--p->objCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT(p->objCount == 0);
|
assert(p->objCount == 0);
|
||||||
|
|
||||||
delete p;
|
delete p;
|
||||||
}
|
}
|
||||||
|
@ -108,33 +110,39 @@ TEXFBO TexPool::request(int width, int height)
|
||||||
/* See if we can statisfy request from cache */
|
/* See if we can statisfy request from cache */
|
||||||
CNodeList &bucket = p->poolHash[size];
|
CNodeList &bucket = p->poolHash[size];
|
||||||
|
|
||||||
if (!bucket.isEmpty())
|
if (!bucket.empty())
|
||||||
{
|
{
|
||||||
/* Found one! */
|
/* Found one! */
|
||||||
cnode = bucket.takeLast();
|
cnode = bucket.back();
|
||||||
|
bucket.pop_back();
|
||||||
|
|
||||||
p->priorityQueue.erase(cnode.prioIter);
|
p->priorityQueue.erase(cnode.prioIter);
|
||||||
|
|
||||||
p->memSize -= byteCount(size);
|
p->memSize -= byteCount(size);
|
||||||
--p->objCount;
|
--p->objCount;
|
||||||
|
|
||||||
// qDebug() << "TexPool: <?+> (" << width << height << ")";
|
// Debug() << "TexPool: <?+> (" << width << height << ")";
|
||||||
|
|
||||||
return cnode.obj;
|
return cnode.obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxSize = glState.caps.maxTexSize;
|
int maxSize = glState.caps.maxTexSize;
|
||||||
if (width > maxSize || height > maxSize)
|
if (width > maxSize || height > maxSize)
|
||||||
throw Exception(Exception::MKXPError,
|
{
|
||||||
"Texture dimensions [%s, %s] exceed hardware capabilities",
|
char buffer[128];
|
||||||
QByteArray::number(width), QByteArray::number(height));
|
snprintf(buffer, sizeof(buffer),
|
||||||
|
"Texture dimensions [%d, %d] exceed hardware capabilities",
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
throw Exception(Exception::MKXPError, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
/* Nope, create it instead */
|
/* Nope, create it instead */
|
||||||
TEXFBO::init(cnode.obj);
|
TEXFBO::init(cnode.obj);
|
||||||
TEXFBO::allocEmpty(cnode.obj, width, height);
|
TEXFBO::allocEmpty(cnode.obj, width, height);
|
||||||
TEXFBO::linkFBO(cnode.obj);
|
TEXFBO::linkFBO(cnode.obj);
|
||||||
|
|
||||||
// qDebug() << "TexPool: <?-> (" << width << height << ")";
|
// Debug() << "TexPool: <?-> (" << width << height << ")";
|
||||||
|
|
||||||
return cnode.obj;
|
return cnode.obj;
|
||||||
}
|
}
|
||||||
|
@ -150,7 +158,7 @@ void TexPool::release(TEXFBO &obj)
|
||||||
if (p->disabled)
|
if (p->disabled)
|
||||||
{
|
{
|
||||||
/* If we're disabled, delete without caching */
|
/* If we're disabled, delete without caching */
|
||||||
// qDebug() << "TexPool: <!#> (" << obj.width << obj.height << ")";
|
// Debug() << "TexPool: <!#> (" << obj.width << obj.height << ")";
|
||||||
TEXFBO::fini(obj);
|
TEXFBO::fini(obj);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -166,39 +174,43 @@ void TexPool::release(TEXFBO &obj)
|
||||||
if (p->objCount == 0)
|
if (p->objCount == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// qDebug() << "TexPool: <!~> Size:" << p->memSize;
|
// Debug() << "TexPool: <!~> Size:" << p->memSize;
|
||||||
|
|
||||||
/* Retrieve object with lowest priority for deletion */
|
/* Retrieve object with lowest priority for deletion */
|
||||||
CacheNode last;
|
CacheNode last;
|
||||||
last.obj = p->priorityQueue.last();
|
last.obj = p->priorityQueue.back();
|
||||||
Size removedSize(last.obj.width, last.obj.height);
|
Size removedSize(last.obj.width, last.obj.height);
|
||||||
|
|
||||||
CNodeList &bucket = p->poolHash[removedSize];
|
CNodeList &bucket = p->poolHash[removedSize];
|
||||||
Q_ASSERT(bucket.contains(last));
|
|
||||||
bucket.removeOne(last);
|
std::list<CacheNode>::iterator toRemove =
|
||||||
p->priorityQueue.removeLast();
|
std::find(bucket.begin(), bucket.end(), last);
|
||||||
|
assert(toRemove != bucket.end());
|
||||||
|
bucket.erase(toRemove);
|
||||||
|
|
||||||
|
p->priorityQueue.pop_back();
|
||||||
|
|
||||||
TEXFBO::fini(last.obj);
|
TEXFBO::fini(last.obj);
|
||||||
|
|
||||||
newMemSize -= byteCount(removedSize);;
|
newMemSize -= byteCount(removedSize);
|
||||||
--p->objCount;
|
--p->objCount;
|
||||||
|
|
||||||
// qDebug() << "TexPool: <!-> (" << last.obj.tex << last.obj.fbo << ")";
|
// Debug() << "TexPool: <!-> (" << last.obj.width << last.obj.height << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
p->memSize = newMemSize;
|
p->memSize = newMemSize;
|
||||||
|
|
||||||
/* Retain object */
|
/* Retain object */
|
||||||
p->priorityQueue.prepend(obj);
|
p->priorityQueue.push_front(obj);
|
||||||
CacheNode cnode;
|
CacheNode cnode;
|
||||||
cnode.obj = obj;
|
cnode.obj = obj;
|
||||||
cnode.prioIter = p->priorityQueue.begin();
|
cnode.prioIter = p->priorityQueue.begin();
|
||||||
CNodeList &bucket = p->poolHash[size];
|
CNodeList &bucket = p->poolHash[size];
|
||||||
bucket.append(cnode);
|
bucket.push_back(cnode);
|
||||||
|
|
||||||
++p->objCount;
|
++p->objCount;
|
||||||
|
|
||||||
// qDebug() << "TexPool: <!+> (" << obj.width << obj.height << ") Current size:" << p->memSize;
|
// Debug() << "TexPool: <!+> (" << obj.width << obj.height << ") Current size:" << p->memSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TexPool::disable()
|
void TexPool::disable()
|
||||||
|
|
37
src/util.h
37
src/util.h
|
@ -22,6 +22,9 @@
|
||||||
#ifndef UTIL_H
|
#ifndef UTIL_H
|
||||||
#define UTIL_H
|
#define UTIL_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
wrapRange(int value, int min, int max)
|
wrapRange(int value, int min, int max)
|
||||||
{
|
{
|
||||||
|
@ -56,6 +59,40 @@ findNextPow2(int start)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reads the contents of the file at 'path' and
|
||||||
|
* appends them to 'out'. Returns false on failure */
|
||||||
|
inline bool readFile(const char *path,
|
||||||
|
std::string &out)
|
||||||
|
{
|
||||||
|
FILE *f = fopen(path, "r");
|
||||||
|
|
||||||
|
if (!f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long size = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
size_t back = out.size();
|
||||||
|
|
||||||
|
out.resize(back+size);
|
||||||
|
size_t read = fread(&out[back], 1, size, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if (read != (size_t) size)
|
||||||
|
out.resize(back+read);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void strReplace(std::string &str,
|
||||||
|
char before, char after)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < str.size(); ++i)
|
||||||
|
if (str[i] == before)
|
||||||
|
str[i] = after;
|
||||||
|
}
|
||||||
|
|
||||||
#define ARRAY_SIZE(obj) (sizeof(obj) / sizeof((obj)[0]))
|
#define ARRAY_SIZE(obj) (sizeof(obj) / sizeof((obj)[0]))
|
||||||
|
|
||||||
#define elementsN(obj) const int obj##N = ARRAY_SIZE(obj)
|
#define elementsN(obj) const int obj##N = ARRAY_SIZE(obj)
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
|
|
||||||
#include <sigc++/connection.h>
|
#include <sigc++/connection.h>
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
struct ViewportPrivate
|
struct ViewportPrivate
|
||||||
{
|
{
|
||||||
/* Needed for geometry changes */
|
/* Needed for geometry changes */
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
|
|
||||||
#include <sigc++/connection.h>
|
#include <sigc++/connection.h>
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Sides
|
struct Sides
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue