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:
Jonas Kulla 2013-12-11 20:46:54 +01:00
parent 01529c5741
commit 2adf8ab265
40 changed files with 722 additions and 456 deletions

View file

@ -27,12 +27,12 @@
#include "filesystem.h"
#include "exception.h"
#include "al-util.h"
#include <QByteArray>
#include <QHash>
#include "boost-hash.h"
#include "debugwriter.h"
#include <vector>
#include <string>
#include <assert.h>
#include <SDL_audio.h>
#include <SDL_thread.h>
@ -47,8 +47,6 @@
#include <alc.h>
#include <QDebug>
#define AUDIO_SLEEP 10
#define SE_SOURCES 6
#define SE_CACHE_MEM (10*1024*1024) // 10 MB
@ -71,8 +69,8 @@ static uint8_t formatSampleSize(int sdlFormat)
return 4;
default:
qDebug() << "Unhandled sample format";
Q_ASSERT(0);
Debug() << "Unhandled sample format";
abort();
}
return 0;
@ -87,23 +85,23 @@ static ALenum chooseALFormat(int sampleSize, int channelCount)
{
case 1 : return AL_FORMAT_MONO8;
case 2 : return AL_FORMAT_STEREO8;
default: Q_ASSERT(0);
default: abort();
}
case 2 :
switch (channelCount)
{
case 1 : return AL_FORMAT_MONO16;
case 2 : return AL_FORMAT_STEREO16;
default : Q_ASSERT(0);
default : abort();
}
case 4 :
switch (channelCount)
{
case 1 : return AL_FORMAT_MONO_FLOAT32;
case 2 : return AL_FORMAT_STEREO_FLOAT32;
default : Q_ASSERT(0);
default : abort();
}
default : Q_ASSERT(0);
default : abort();
}
return 0;
@ -114,7 +112,7 @@ static const int streamBufSize = 32768;
struct SoundBuffer
{
/* Uniquely identifies this or equal buffer */
QByteArray key;
std::string key;
AL::Buffer::ID alBuffer;
@ -135,11 +133,6 @@ struct SoundBuffer
alBuffer = AL::Buffer::gen();
}
~SoundBuffer()
{
AL::Buffer::del(alBuffer);
}
static SoundBuffer *ref(SoundBuffer *buffer)
{
++buffer->refCount;
@ -152,12 +145,20 @@ struct SoundBuffer
if (--buffer->refCount == 0)
delete buffer;
}
private:
~SoundBuffer()
{
AL::Buffer::del(alBuffer);
}
};
struct SoundEmitter
{
typedef BoostHash<std::string, SoundBuffer*> BufferHash;
IntruList<SoundBuffer> buffers;
QHash<QByteArray, SoundBuffer*> bufferHash;
BufferHash bufferHash;
/* Byte count sum of all cached / playing buffers */
uint32_t bufferBytes;
@ -189,12 +190,12 @@ struct SoundEmitter
SoundBuffer::deref(atchBufs[i]);
}
QHash<QByteArray, SoundBuffer*>::iterator iter;
for (iter = bufferHash.begin(); iter != bufferHash.end(); ++iter)
delete iter.value();
BufferHash::const_iterator iter;
for (iter = bufferHash.cbegin(); iter != bufferHash.cend(); ++iter)
SoundBuffer::deref(iter->second);
}
void play(const QByteArray &filename,
void play(const std::string &filename,
int volume,
int pitch)
{
@ -233,7 +234,7 @@ struct SoundEmitter
}
private:
SoundBuffer *allocateBuffer(const QByteArray &filename)
SoundBuffer *allocateBuffer(const std::string &filename)
{
SoundBuffer *buffer = bufferHash.value(filename, 0);
@ -252,7 +253,7 @@ private:
SDL_RWops dataSource;
const char *extension;
shState->fileSystem().openRead(dataSource, filename.constData(),
shState->fileSystem().openRead(dataSource, filename.c_str(),
FileSystem::Audio, false, &extension);
Sound_Sample *sampleHandle = Sound_NewSample(&dataSource, extension, 0, streamBufSize);
@ -285,7 +286,7 @@ private:
while (wouldBeBytes > SE_CACHE_MEM && !buffers.isEmpty())
{
SoundBuffer *last = buffers.tail();
bufferHash.remove(last->key);
bufferHash.erase(last->key);
buffers.remove(last->link);
wouldBeBytes -= last->bytes;

View file

@ -28,9 +28,6 @@
#include <pixman.h>
#include <QString>
#include <QChar>
#include "gl-util.h"
#include "quad.h"
#include "quadarray.h"
@ -944,6 +941,50 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
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)
{
GUARD_DISPOSED;
@ -955,10 +996,14 @@ IntRect Bitmap::textSize(const char *str)
int 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)
TTF_GlyphMetrics(font, qstr.at(0).unicode(), 0, 0, 0, 0, &w);
/* For cursive characters, returning the advance
* 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);
}

130
src/boost-hash.h Normal file
View file

@ -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

View file

@ -21,12 +21,16 @@
#include "config.h"
#include <QSettings>
#include <QFileInfo>
#include <QString>
#include <QStringList>
#include <QFile>
#include <QRegExp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>
#include <fstream>
#include "debugwriter.h"
#include "util.h"
typedef std::vector<std::string> StringVec;
namespace po = boost::program_options;
Config::Config()
: debugMode(false),
@ -46,68 +50,84 @@ Config::Config()
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);
READ_VAL(winResizable, Bool);
READ_VAL(fullscreen, Bool);
READ_VAL(fixedAspectRatio, Bool);
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);
po::options_description podesc;
podesc.add_options()
PO_DESC_ALL
("RTP", po::value<StringVec>())
;
QStringList _rtps = confFile.value("RTPs").toStringList();
Q_FOREACH(const QString &s, _rtps)
rtps.push_back(s.toUtf8());
std::ifstream confFile;
confFile.open("mkxp.conf");
confFile.beginGroup("Binding");
po::variables_map vm;
po::store(po::parse_config_file(confFile, podesc, true), vm);
po::notify(vm);
QStringList bindingKeys = confFile.childKeys();
Q_FOREACH (const QString &key, bindingKeys)
{
QVariant value = confFile.value(key);
confFile.close();
/* Convert QString to QByteArray */
if (value.type() == QVariant::String)
value = value.toString().toUtf8();
// Not gonna take your shit boost
#define GUARD_ALL( exp ) try { exp } catch(...) {}
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()
{
if (!customScript.isEmpty())
if (!customScript.empty())
{
game.title = basename(customScript.constData());
game.title = basename(customScript.c_str());
return;
}
QSettings gameINI(gameFolder + "/Game.ini", QSettings::IniFormat);
QFileInfo finfo(gameFolder.constData());
game.title = gameINI.value("Game/Title", finfo.baseName()).toByteArray();
po::options_description podesc;
podesc.add_options()
("Game.Title", po::value<std::string>())
("Game.Scripts", po::value<std::string>())
;
/* Gotta read the "Scripts" entry manually because Qt can't handle '\' */
QFile gameINIFile(gameFolder + "/Game.ini");
if (gameINIFile.open(QFile::ReadOnly))
{
QString gameINIContents = gameINIFile.readAll();
QRegExp scriptsRE(".*Scripts=(.*)\r\nTitle=.*");
if (scriptsRE.exactMatch(gameINIContents))
{
game.scripts = scriptsRE.cap(1).toUtf8();
game.scripts.replace('\\', '/');
}
}
std::string iniPath = gameFolder + "/Game.ini";
std::ifstream iniFile;
iniFile.open((iniPath).c_str());
po::variables_map vm;
po::store(po::parse_config_file(iniFile, podesc, true), vm);
po::notify(vm);
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());
}

View file

@ -22,10 +22,7 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <QByteArray>
#include <QHash>
#include <QVariant>
#include <string>
#include <vector>
struct Config
@ -46,20 +43,16 @@ struct Config
bool solidFonts;
QByteArray gameFolder;
std::string gameFolder;
bool allowSymlinks;
QByteArray customScript;
std::vector<QByteArray> rtps;
/* Any values in the [Binding]
* group are collected here */
QHash<QByteArray, QVariant> bindingConf;
std::string customScript;
std::vector<std::string> rtps;
/* Game INI contents */
struct {
QByteArray scripts;
QByteArray title;
std::string scripts;
std::string title;
} game;
Config();

View file

@ -20,42 +20,30 @@
*/
#include "debuglogger.h"
#include "debugwriter.h"
#include <glew.h>
#include <QFile>
#include <QTime>
#include <QTextStream>
#include <QDebug>
#include <iostream>
struct DebugLoggerPrivate
{
QFile logFile;
QTextStream *stream;
std::ostream *stream;
DebugLoggerPrivate(const char *logFilename)
{
if (logFilename)
{
logFile.setFileName(logFilename);
logFile.open(QFile::WriteOnly);
stream = new QTextStream(&logFile);
}
else
{
stream = new QTextStream(stderr, QIODevice::WriteOnly);
}
(void) logFilename;
stream = &std::clog;
}
~DebugLoggerPrivate()
{
delete stream;
}
void writeTimestamp()
{
QTime time = QTime::currentTime();
*stream << "[" << time.toString().toLatin1() << "] ";
// FIXME reintroduce proper time stamps (is this even necessary??)
*stream << "[GLDEBUG] ";
}
void writeLine(const char *line)
@ -114,7 +102,7 @@ DebugLogger::DebugLogger(const char *filename)
else if (GLEW_AMD_debug_output)
glDebugMessageCallbackAMD(amdDebugFunc, p);
else
qDebug() << "DebugLogger: no debug extensions found";
Debug() << "DebugLogger: no debug extensions found";
}
DebugLogger::~DebugLogger()

56
src/debugwriter.h Normal file
View file

@ -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

View file

@ -29,11 +29,10 @@
#include "sharedstate.h"
#include "graphics.h"
#include "debugwriter.h"
#include <string.h>
#include <QDebug>
bool EventThread::keyStates[] = { false };
EventThread::JoyState EventThread::joyState =
@ -97,7 +96,7 @@ void EventThread::process(RGSSThreadData &rtData)
{
if (!SDL_WaitEvent(&event))
{
qDebug() << "EventThread: Event error";
Debug() << "EventThread: Event error";
break;
}
@ -141,7 +140,7 @@ void EventThread::process(RGSSThreadData &rtData)
case SDL_QUIT :
case REQUEST_TERMINATION :
terminate = true;
qDebug() << "EventThread termination requested";
Debug() << "EventThread termination requested";
break;
case SDL_KEYDOWN :
@ -173,13 +172,13 @@ void EventThread::process(RGSSThreadData &rtData)
if (fullscreen)
{
/* Prevent fullscreen flicker */
strncpy(pendingTitle, rtData.config.game.title.constData(),
strncpy(pendingTitle, rtData.config.game.title.c_str(),
sizeof(pendingTitle));
havePendingTitle = true;
break;
}
SDL_SetWindowTitle(win, rtData.config.game.title.constData());
SDL_SetWindowTitle(win, rtData.config.game.title.c_str());
}
break;
@ -201,7 +200,7 @@ void EventThread::process(RGSSThreadData &rtData)
case REQUEST_MESSAGEBOX :
SDL_ShowSimpleMessageBox(event.user.code,
rtData.config.game.title.constData(),
rtData.config.game.title.c_str(),
(const char*) event.user.data1, win);
free(event.user.data1);
msgBoxDone = true;
@ -217,7 +216,7 @@ void EventThread::process(RGSSThreadData &rtData)
break;
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
* mode seems to cause flickering */

View file

@ -30,7 +30,7 @@
#include <SDL_mouse.h>
#include <SDL_mutex.h>
#include <QByteArray>
#include <string>
#include <stdint.h>
@ -173,7 +173,7 @@ struct RGSSThreadData
Config config;
QByteArray rgssErrorMsg;
std::string rgssErrorMsg;
volatile bool rqScreenshot;

View file

@ -22,7 +22,7 @@
#ifndef EXCEPTION_H
#define EXCEPTION_H
#include <QByteArray>
#include <string>
#include <stdio.h>
struct Exception
@ -44,19 +44,19 @@ struct Exception
};
Type type;
QByteArray fmt;
QByteArray arg1;
QByteArray arg2;
std::string fmt;
std::string arg1;
std::string arg2;
Exception(Type type, QByteArray fmt,
QByteArray arg1 = QByteArray(),
QByteArray arg2 = QByteArray())
Exception(Type type, std::string fmt,
std::string arg1 = std::string(),
std::string arg2 = std::string())
: type(type), fmt(fmt), arg1(arg1), arg2(arg2)
{}
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());
}
};

View file

@ -23,22 +23,18 @@
#include "util.h"
#include "exception.h"
#include "boost-hash.h"
#include "debugwriter.h"
#include <physfs.h>
#include <SDL_sound.h>
#include <QHash>
#include <QSet>
#include <QByteArray>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <QDebug>
struct RGSS_entryData
{
int64_t offset;
@ -73,11 +69,11 @@ struct RGSS_archiveData
/* Maps: file path
* to: entry data */
QHash<QByteArray, RGSS_entryData> entryHash;
BoostHash<std::string, RGSS_entryData> entryHash;
/* Maps: directory path,
* to: list of contained entries */
QHash<QByteArray, QSet<QByteArray> > dirHash;
BoostHash<std::string, BoostSet<std::string> > dirHash;
};
static bool
@ -313,7 +309,7 @@ RGSS_openArchive(PHYSFS_Io *io, const char *, int forWrite)
uint32_t magic = RGSS_MAGIC;
/* Top level entry list */
QSet<QByteArray> &topLevel = data->dirHash["."];
BoostSet<std::string> &topLevel = data->dirHash["."];
while (true)
{
@ -373,7 +369,7 @@ RGSS_openArchive(PHYSFS_Io *io, const char *, int forWrite)
const char *dir = nameBuf;
const char *entry = &nameBuf[i+1];
QSet<QByteArray> &entryList = data->dirHash[dir];
BoostSet<std::string> &entryList = data->dirHash[dir];
entryList.insert(entry);
}
@ -390,16 +386,16 @@ RGSS_enumerateFiles(void *opaque, const char *dirname,
{
RGSS_archiveData *data = static_cast<RGSS_archiveData*>(opaque);
QByteArray _dirname(dirname);
std::string _dirname(dirname);
if (!data->dirHash.contains(_dirname))
return;
const QSet<QByteArray> &entries = data->dirHash.value(_dirname);
const BoostSet<std::string> &entries = data->dirHash[_dirname];
QSet<QByteArray>::const_iterator iter;
for (iter = entries.begin(); iter != entries.end(); ++iter)
cb(callbackdata, origdir, iter->constData());
BoostSet<std::string>::const_iterator iter;
for (iter = entries.cbegin(); iter != entries.cend(); ++iter)
cb(callbackdata, origdir, iter->c_str());
}
static PHYSFS_Io*
@ -500,9 +496,9 @@ static const PHYSFS_Archiver RGSS_Archiver =
struct FileSystemPrivate
{
/* 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.
* Either a pointer into the input string pointing at the
@ -535,7 +531,7 @@ struct FileSystemPrivate
buff[i] = '\0';
QByteArray key(buff);
std::string key(buff);
if (pathCache.contains(key))
{
@ -544,17 +540,17 @@ struct FileSystemPrivate
if (foundExt)
*foundExt = findExt(filename);
return pathCache[key].constData();
return pathCache[key].c_str();
}
char buff2[512];
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)
{
const char *ext = extList[i].constData();
const char *ext = extList[i].c_str();
snprintf(buff2, sizeof(buff2), "%s.%s", buff, ext);
key = buff2;
@ -564,7 +560,7 @@ struct FileSystemPrivate
if (foundExt)
*foundExt = ext;
return pathCache[key].constData();
return pathCache[key].c_str();
}
}
}
@ -640,7 +636,7 @@ FileSystem::~FileSystem()
delete p;
if (PHYSFS_deinit() == 0)
qDebug() << "PhyFS failed to deinit.";
Debug() << "PhyFS failed to deinit.";
}
void FileSystem::addPath(const char *path)
@ -660,16 +656,16 @@ static void cacheEnumCB(void *d, const char *origdir,
else
strncpy(buf, fname, sizeof(buf));
QByteArray mixedCase(buf);
std::string mixedCase(buf);
for (char *p = buf; *p; ++p)
*p = tolower(*p);
QByteArray lowerCase(buf);
std::string lowerCase(buf);
p->pathCache.insert(lowerCase, mixedCase);
PHYSFS_enumerateFilesCallback(mixedCase.constData(), cacheEnumCB, p);
PHYSFS_enumerateFilesCallback(mixedCase.c_str(), cacheEnumCB, p);
}
void FileSystem::createPathCache()

View file

@ -25,8 +25,6 @@
#include "etc.h"
#include "etc-internal.h"
#include <QDebug>
class Flashable
{
public:

View file

@ -24,17 +24,16 @@
#include "sharedstate.h"
#include "filesystem.h"
#include "exception.h"
#include "boost-hash.h"
#include "util.h"
#include <string>
#include <utility>
#include "../liberation.ttf.xxd"
#include <SDL_ttf.h>
#include <QHash>
#include <QByteArray>
#include <QPair>
#include <QDebug>
#define BUNDLED_FONT liberation
#define BUNDLED_FONT_D(f) assets_## f ##_ttf
@ -44,11 +43,17 @@
#define BNDL_F_D(f) BUNDLED_FONT_D(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
{
QHash<FontKey, TTF_Font*> hash;
BoostHash<FontKey, TTF_Font*> hash;
};
FontPool::FontPool()
@ -58,9 +63,9 @@ FontPool::FontPool()
FontPool::~FontPool()
{
QHash<FontKey, TTF_Font*>::const_iterator iter;
for (iter = p->hash.begin(); iter != p->hash.end(); ++iter)
TTF_CloseFont(iter.value());
BoostHash<FontKey, TTF_Font*>::const_iterator iter;
for (iter = p->hash.cbegin(); iter != p->hash.cend(); ++iter)
TTF_CloseFont(iter->second);
delete p;
}
@ -71,16 +76,22 @@ static SDL_RWops *openBundledFont()
}
_TTF_Font *FontPool::request(const char *filename,
int size)
int size)
{
// FIXME Find out how font path resolution is done in VX/Ace
QByteArray nameKey = QByteArray(filename).toLower();
nameKey.replace(' ', '_');
std::string nameKey(filename);
strToLower(nameKey);
strReplace(nameKey, ' ', '_');
bool useBundled = false;
QByteArray path = QByteArray("Fonts/") + nameKey;
if (!shState->fileSystem().exists(path.constData(), FileSystem::Font))
std::string path = std::string("Fonts/") + nameKey;
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;
nameKey = " bundled";
}
@ -90,14 +101,9 @@ _TTF_Font *FontPool::request(const char *filename,
TTF_Font *font = p->hash.value(key, 0);
if (font)
{
// static int i=0;qDebug() << "FontPool: <?+>" << i++;
return font;
}
// qDebug() << "FontPool: <?->";
/* Not in hash, create */
/* Not in hash, open */
SDL_RWops *ops;
if (useBundled)
@ -107,7 +113,7 @@ _TTF_Font *FontPool::request(const char *filename,
else
{
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
@ -124,7 +130,7 @@ _TTF_Font *FontPool::request(const char *filename,
struct FontPrivate
{
QByteArray name;
std::string name;
int size;
bool bold;
bool italic;
@ -132,7 +138,7 @@ struct FontPrivate
Color colorTmp;
static QByteArray defaultName;
static std::string defaultName;
static int defaultSize;
static bool defaultBold;
static bool defaultItalic;
@ -144,15 +150,15 @@ struct FontPrivate
FontPrivate(const char *name = 0,
int size = 0)
: name(name ? QByteArray(name) : defaultName),
: name(name ? std::string(name) : defaultName),
size(size ? size : defaultSize),
bold(defaultBold),
italic(defaultItalic),
color(&colorTmp),
colorTmp(*defaultColor)
{
sdlFont = shState->fontPool().request(this->name.constData(),
this->size);
sdlFont = shState->fontPool().request(this->name.c_str(),
this->size);
}
FontPrivate(const FontPrivate &other)
@ -166,19 +172,19 @@ struct FontPrivate
{}
};
QByteArray FontPrivate::defaultName = "Arial";
int FontPrivate::defaultSize = 22;
bool FontPrivate::defaultBold = false;
bool FontPrivate::defaultItalic = false;
Color *FontPrivate::defaultColor = &FontPrivate::defaultColorTmp;
std::string FontPrivate::defaultName = "Arial";
int FontPrivate::defaultSize = 22;
bool FontPrivate::defaultBold = false;
bool FontPrivate::defaultItalic = false;
Color *FontPrivate::defaultColor = &FontPrivate::defaultColorTmp;
Color FontPrivate::defaultColorTmp(255, 255, 255, 255);
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,
@ -199,7 +205,7 @@ Font::~Font()
const char *Font::getName() const
{
return p->name.constData();
return p->name.c_str();
}
void Font::setName(const char *value)
@ -213,7 +219,7 @@ void Font::setSize(int value)
return;
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
@ -231,7 +237,7 @@ DEF_ATTR_SIMPLE_STATIC(Font, DefaultColor, Color*, FontPrivate::defaultColor)
const char *Font::getDefaultName()
{
return FontPrivate::defaultName.constData();
return FontPrivate::defaultName.c_str();
}
void Font::setDefaultName(const char *value)

View file

@ -27,14 +27,15 @@
#include <SDL_ttf.h>
#include <SDL_sound.h>
#include <string>
#include "sharedstate.h"
#include "eventthread.h"
#include "debuglogger.h"
#include "debugwriter.h"
#include "binding.h"
#include <QDebug>
static const char *reqExt[] =
{
"GL_ARB_fragment_shader",
@ -53,7 +54,7 @@ static const char *reqExt[] =
};
static void
rgssThreadError(RGSSThreadData *rtData, const QByteArray &msg)
rgssThreadError(RGSSThreadData *rtData, const std::string &msg)
{
rtData->rgssErrorMsg = msg;
rtData->ethread->requestTerminate();
@ -69,10 +70,10 @@ glGetStringInt(GLenum name)
static void
printGLInfo()
{
qDebug() << "GL Vendor :" << glGetStringInt(GL_VENDOR);
qDebug() << "GL Renderer :" << glGetStringInt(GL_RENDERER);
qDebug() << "GL Version :" << glGetStringInt(GL_VERSION);
qDebug() << "GLSL Version :" << glGetStringInt(GL_SHADING_LANGUAGE_VERSION);
Debug() << "GL Vendor :" << glGetStringInt(GL_VENDOR);
Debug() << "GL Renderer :" << glGetStringInt(GL_RENDERER);
Debug() << "GL Version :" << glGetStringInt(GL_VERSION);
Debug() << "GLSL Version :" << glGetStringInt(GL_SHADING_LANGUAGE_VERSION);
}
int rgssThreadFun(void *userdata)
@ -91,7 +92,7 @@ int rgssThreadFun(void *userdata)
if (!glCtx)
{
rgssThreadError(threadData, QByteArray("Error creating context: ") + SDL_GetError());
rgssThreadError(threadData, std::string("Error creating context: ") + SDL_GetError());
return 0;
}
@ -121,7 +122,7 @@ int rgssThreadFun(void *userdata)
{
if (!glewIsSupported(reqExt[i]))
{
rgssThreadError(threadData, QByteArray("Required GL extension \"")
rgssThreadError(threadData, std::string("Required GL extension \"")
+ reqExt[i] + "\" not present");
SDL_GL_DeleteContext(glCtx);
return 0;
@ -181,7 +182,7 @@ int main(int, char *argv[])
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
{
qDebug() << "Error initializing SDL:" << SDL_GetError();
Debug() << "Error initializing SDL:" << SDL_GetError();
return 0;
}
@ -189,7 +190,7 @@ int main(int, char *argv[])
int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG;
if (IMG_Init(imgFlags) != imgFlags)
{
qDebug() << "Error initializing SDL_image:" << SDL_GetError();
Debug() << "Error initializing SDL_image:" << SDL_GetError();
SDL_Quit();
return 0;
@ -197,7 +198,7 @@ int main(int, char *argv[])
if (TTF_Init() < 0)
{
qDebug() << "Error initializing SDL_ttf:" << SDL_GetError();
Debug() << "Error initializing SDL_ttf:" << SDL_GetError();
IMG_Quit();
SDL_Quit();
@ -206,7 +207,7 @@ int main(int, char *argv[])
if (Sound_Init() == 0)
{
qDebug() << "Error initializing SDL_sound:" << Sound_GetError();
Debug() << "Error initializing SDL_sound:" << Sound_GetError();
TTF_Quit();
IMG_Quit();
SDL_Quit();
@ -224,13 +225,13 @@ int main(int, char *argv[])
if (conf.fullscreen)
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,
conf.defScreenW, conf.defScreenH, winFlags);
if (!win)
{
qDebug() << "Error creating window";
Debug() << "Error creating window";
return 0;
}
@ -254,7 +255,7 @@ int main(int, char *argv[])
/* We can stop waiting when the request was ack'd */
if (rtData.rqTermAck)
{
qDebug() << "RGSS thread ack'd request after" << i*10 << "ms";
Debug() << "RGSS thread ack'd request after" << i*10 << "ms";
break;
}
@ -267,17 +268,17 @@ int main(int, char *argv[])
if (rtData.rqTermAck)
SDL_WaitThread(rgssThread, 0);
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);
if (!rtData.rgssErrorMsg.isEmpty())
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.constData(),
rtData.rgssErrorMsg.constData(), win);
if (!rtData.rgssErrorMsg.empty())
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.c_str(),
rtData.rgssErrorMsg.c_str(), win);
/* Clean up any remainin events */
eventThread.cleanup();
qDebug() << "Shutting down.";
Debug() << "Shutting down.";
SDL_DestroyWindow(win);

View file

@ -3,7 +3,7 @@
#include <SDL_timer.h>
#include <glew.h>
#include <QDebug>
#include "debugwriter.h"
struct TimerQuery
{
@ -132,7 +132,7 @@ struct GPUTimerGLQuery : public PerfTimer
if (++counter < iter)
return;
qDebug() << " "
Debug() << " "
"Avg. GPU time:" << ((double) acc / (iter * 1000 * 1000)) << "ms";
acc = counter = 0;
@ -181,7 +181,7 @@ struct CPUTimer : public PerfTimer
if (++counter < iter)
return;
qDebug() << "Avg. CPU time:" << ((double) acc / (iter * (perfFreq / 1000))) << "ms";
Debug() << "Avg. CPU time:" << ((double) acc / (iter * (perfFreq / 1000))) << "ms";
acc = counter = 0;
}
};
@ -199,7 +199,7 @@ PerfTimer *createGPUTimer(int iter)
}
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();
}
}

View file

@ -22,8 +22,6 @@
#include "scene.h"
#include "sharedstate.h"
#include <QDebug>
Scene::Scene()
{
geometry.xOrigin = geometry.yOrigin = 0;

View file

@ -22,10 +22,11 @@
#include "shader.h"
#include "sharedstate.h"
#include "glstate.h"
#include "debugwriter.h"
#include <glew.h>
#include <QFile>
#include <assert.h>
#include "../sprite.frag.xxd"
#include "../hue.frag.xxd"
@ -48,16 +49,14 @@
#include "../blurV.vert.xxd"
#endif
#include <QDebug>
#define INIT_SHADER(vert, frag) \
{ \
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)
@ -98,14 +97,14 @@ void Shader::init(const unsigned char *vert, int vertSize,
glCompileShader(vertShader);
glGetObjectParameterivARB(vertShader, GL_COMPILE_STATUS, &success);
Q_ASSERT(success);
assert(success); // FIXME should really throw here instead
/* Compile fragment shader */
glShaderSource(fragShader, 1, (const GLchar**) &frag, (const GLint*) &fragSize);
glCompileShader(fragShader);
glGetObjectParameterivARB(fragShader, GL_COMPILE_STATUS, &success);
Q_ASSERT(success);
assert(success);
/* Link shader program */
glAttachShader(program, vertShader);
@ -118,23 +117,17 @@ void Shader::init(const unsigned char *vert, int vertSize,
glLinkProgram(program);
glGetObjectParameterivARB(program, GL_LINK_STATUS, &success);
Q_ASSERT(success);
assert(success);
}
void Shader::initFromFile(const char *_vertFile, const char *_fragFile)
{
QFile vertFile(_vertFile);
vertFile.open(QFile::ReadOnly);
QByteArray vertContents = vertFile.readAll();
vertFile.close();
std::string vertContents, fragContents;
readFile(_vertFile, vertContents);
readFile(_fragFile, fragContents);
QFile fragFile(_fragFile);
fragFile.open(QFile::ReadOnly);
QByteArray fragContents = fragFile.readAll();
fragFile.close();
init((const unsigned char*) vertContents.constData(), vertContents.size(),
(const unsigned char*) fragContents.constData(), fragContents.size());
init((const unsigned char*) vertContents.c_str(), vertContents.size(),
(const unsigned char*) fragContents.c_str(), fragContents.size());
}
void Shader::setVec4Uniform(GLint location, const Vec4 &vec)

View file

@ -36,11 +36,9 @@
#include "quad.h"
#include "binding.h"
#include <QFile>
#include <unistd.h>
#include <QDebug>
#include <stdio.h>
#include <string>
SharedState *SharedState::instance = 0;
static GlobalIBO *globalIBO = 0;
@ -93,21 +91,26 @@ struct SharedStatePrivate
graphics(threadData),
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;
fileSystem.addPath(".");
}
// FIXME find out correct archive filename
QByteArray archPath = GAME_ARCHIVE;
std::string archPath = GAME_ARCHIVE;
if (QFile::exists(archPath.constData()))
fileSystem.addPath(archPath.constData());
/* Check if a game archive exists */
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)
fileSystem.addPath(config.rtps[i].constData());
fileSystem.addPath(config.rtps[i].c_str());
fileSystem.createPathCache();

View file

@ -37,8 +37,6 @@
#include <sigc++/connection.h>
#include <QDebug>
struct SpritePrivate
{
Bitmap *bitmap;

View file

@ -23,17 +23,15 @@
#include "exception.h"
#include "sharedstate.h"
#include "glstate.h"
#include "boost-hash.h"
#include "debugwriter.h"
#include <QHash>
#include <QQueue>
#include <QList>
#include <QLinkedList>
#include <QPair>
#include <list>
#include <utility>
#include <assert.h>
#include <string.h>
#include <QDebug>
typedef QPair<uint16_t, uint16_t> Size;
typedef QQueue<TEXFBO> ObjList;
typedef std::pair<uint16_t, uint16_t> Size;
static uint32_t byteCount(Size &s)
{
@ -43,23 +41,23 @@ static uint32_t byteCount(Size &s)
struct CacheNode
{
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;
}
};
typedef QList<CacheNode> CNodeList;
typedef std::list<CacheNode> CNodeList;
struct TexPoolPrivate
{
/* Contains all cached TexFBOs, grouped by size */
QHash<Size, CNodeList> poolHash;
BoostHash<Size, CNodeList> poolHash;
/* Contains all cached TexFBOs, sorted by release time */
QLinkedList<TEXFBO> priorityQueue;
std::list<TEXFBO> priorityQueue;
/* Maximal allowed cache memory */
const uint32_t maxMemSize;
@ -88,14 +86,18 @@ TexPool::TexPool(uint32_t maxMemSize)
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);
--p->objCount;
}
Q_ASSERT(p->objCount == 0);
assert(p->objCount == 0);
delete p;
}
@ -108,33 +110,39 @@ TEXFBO TexPool::request(int width, int height)
/* See if we can statisfy request from cache */
CNodeList &bucket = p->poolHash[size];
if (!bucket.isEmpty())
if (!bucket.empty())
{
/* Found one! */
cnode = bucket.takeLast();
cnode = bucket.back();
bucket.pop_back();
p->priorityQueue.erase(cnode.prioIter);
p->memSize -= byteCount(size);
--p->objCount;
// qDebug() << "TexPool: <?+> (" << width << height << ")";
// Debug() << "TexPool: <?+> (" << width << height << ")";
return cnode.obj;
}
int maxSize = glState.caps.maxTexSize;
if (width > maxSize || height > maxSize)
throw Exception(Exception::MKXPError,
"Texture dimensions [%s, %s] exceed hardware capabilities",
QByteArray::number(width), QByteArray::number(height));
{
char buffer[128];
snprintf(buffer, sizeof(buffer),
"Texture dimensions [%d, %d] exceed hardware capabilities",
width, height);
throw Exception(Exception::MKXPError, buffer);
}
/* Nope, create it instead */
TEXFBO::init(cnode.obj);
TEXFBO::allocEmpty(cnode.obj, width, height);
TEXFBO::linkFBO(cnode.obj);
// qDebug() << "TexPool: <?-> (" << width << height << ")";
// Debug() << "TexPool: <?-> (" << width << height << ")";
return cnode.obj;
}
@ -150,7 +158,7 @@ void TexPool::release(TEXFBO &obj)
if (p->disabled)
{
/* If we're disabled, delete without caching */
// qDebug() << "TexPool: <!#> (" << obj.width << obj.height << ")";
// Debug() << "TexPool: <!#> (" << obj.width << obj.height << ")";
TEXFBO::fini(obj);
return;
}
@ -166,39 +174,43 @@ void TexPool::release(TEXFBO &obj)
if (p->objCount == 0)
break;
// qDebug() << "TexPool: <!~> Size:" << p->memSize;
// Debug() << "TexPool: <!~> Size:" << p->memSize;
/* Retrieve object with lowest priority for deletion */
CacheNode last;
last.obj = p->priorityQueue.last();
last.obj = p->priorityQueue.back();
Size removedSize(last.obj.width, last.obj.height);
CNodeList &bucket = p->poolHash[removedSize];
Q_ASSERT(bucket.contains(last));
bucket.removeOne(last);
p->priorityQueue.removeLast();
std::list<CacheNode>::iterator toRemove =
std::find(bucket.begin(), bucket.end(), last);
assert(toRemove != bucket.end());
bucket.erase(toRemove);
p->priorityQueue.pop_back();
TEXFBO::fini(last.obj);
newMemSize -= byteCount(removedSize);;
newMemSize -= byteCount(removedSize);
--p->objCount;
// qDebug() << "TexPool: <!-> (" << last.obj.tex << last.obj.fbo << ")";
// Debug() << "TexPool: <!-> (" << last.obj.width << last.obj.height << ")";
}
p->memSize = newMemSize;
/* Retain object */
p->priorityQueue.prepend(obj);
p->priorityQueue.push_front(obj);
CacheNode cnode;
cnode.obj = obj;
cnode.prioIter = p->priorityQueue.begin();
CNodeList &bucket = p->poolHash[size];
bucket.append(cnode);
bucket.push_back(cnode);
++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()

View file

@ -22,6 +22,9 @@
#ifndef UTIL_H
#define UTIL_H
#include <stdio.h>
#include <string>
static inline int
wrapRange(int value, int min, int max)
{
@ -56,6 +59,40 @@ findNextPow2(int start)
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 elementsN(obj) const int obj##N = ARRAY_SIZE(obj)

View file

@ -31,8 +31,6 @@
#include <sigc++/connection.h>
#include <QDebug>
struct ViewportPrivate
{
/* Needed for geometry changes */

View file

@ -36,8 +36,6 @@
#include <sigc++/connection.h>
#include <QDebug>
template<typename T>
struct Sides
{