mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-04-21 21:52:04 +02:00
Make json config accessible from System::CONFIG
This commit is contained in:
parent
7a9d60cdbc
commit
42b1cdcc21
10 changed files with 118 additions and 154 deletions
|
@ -30,12 +30,12 @@
|
|||
#include "util/boost-hash.h"
|
||||
#include "util/exception.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "binding-util.h"
|
||||
#include "binding.h"
|
||||
|
||||
#include "sharedstate.h"
|
||||
#include "config.h"
|
||||
#include "eventthread.h"
|
||||
|
||||
#include <vector>
|
||||
|
@ -144,6 +144,8 @@ RB_METHOD(mriRgssMain);
|
|||
RB_METHOD(mriRgssStop);
|
||||
RB_METHOD(_kernelCaller);
|
||||
|
||||
VALUE json2rb(json5pp::value const &v);
|
||||
|
||||
static void mriBindingInit() {
|
||||
tableBindingInit();
|
||||
etcBindingInit();
|
||||
|
@ -256,6 +258,8 @@ static void mriBindingInit() {
|
|||
|
||||
rb_gv_set("BTEST", rb_bool_new(shState->config().editor.battleTest));
|
||||
|
||||
rb_define_const(mod, "CONFIG", json2rb(shState->config().raw));
|
||||
|
||||
// Set $stdout and its ilk accordingly on Windows
|
||||
#ifdef __WIN32__
|
||||
if (shState->config().editor.debug)
|
||||
|
|
|
@ -19,11 +19,12 @@
|
|||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "src/config.h"
|
||||
|
||||
#include "binding-util.h"
|
||||
|
||||
#include "filesystem.h"
|
||||
#include "sharedstate.h"
|
||||
#include "src/config.h"
|
||||
#include "src/util/util.h"
|
||||
|
||||
#if RAPI_FULL > 187
|
||||
|
|
|
@ -293,8 +293,8 @@ RB_METHOD(httpJsonParse) {
|
|||
try {
|
||||
v = json5pp::parse5(RSTRING_PTR(jsonv));
|
||||
}
|
||||
catch (...) {
|
||||
raiseRbExc(Exception(Exception::MKXPError, "Failed to parse JSON"));
|
||||
catch (const std::exception &e) {
|
||||
raiseRbExc(Exception(Exception::MKXPError, "Failed to parse JSON: %s", e.what()));
|
||||
}
|
||||
|
||||
return json2rb(v);
|
||||
|
|
|
@ -19,17 +19,18 @@
|
|||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <SDL_joystick.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
#include "eventthread.h"
|
||||
|
||||
#include "binding-util.h"
|
||||
#include "util/exception.h"
|
||||
#include "input/input.h"
|
||||
#include "sharedstate.h"
|
||||
#include "src/util/util.h"
|
||||
|
||||
#include "eventthread.h"
|
||||
|
||||
#include <SDL_joystick.h>
|
||||
#include <string>
|
||||
|
||||
RB_METHOD(inputDelta) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
|
|
|
@ -977,6 +977,7 @@
|
|||
3B5A8463256A46B200BAF2E5 /* systemImplApple.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = systemImplApple.mm; sourceTree = "<group>"; };
|
||||
3B5E1F0925A881FB0086FFDC /* libEGL.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libEGL.dylib; path = Dependencies/Frameworks/ANGLE/libEGL.dylib; sourceTree = "<group>"; };
|
||||
3B5E1F0A25A881FB0086FFDC /* libGLESv2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libGLESv2.dylib; path = Dependencies/Frameworks/ANGLE/libGLESv2.dylib; sourceTree = "<group>"; };
|
||||
3B609374268274CE0038E9D6 /* encoding.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = encoding.h; sourceTree = "<group>"; };
|
||||
3BA08EA4256641ED00449CFF /* Assets.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Assets.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3BA08EA6256641EE00449CFF /* Assets.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Assets.plist; sourceTree = "<group>"; };
|
||||
3BA6944E263DAB53004194EB /* libnsgif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libnsgif.c; sourceTree = "<group>"; };
|
||||
|
@ -1342,6 +1343,7 @@
|
|||
3B10EE1F2569348E00372D13 /* json5pp.hpp */,
|
||||
3B1BC0DF266F7C0C00794D22 /* iniconfig.h */,
|
||||
3B1BC0E0266F7C0C00794D22 /* iniconfig.cpp */,
|
||||
3B609374268274CE0038E9D6 /* encoding.h */,
|
||||
);
|
||||
path = util;
|
||||
sourceTree = "<group>";
|
||||
|
|
146
src/config.cpp
146
src/config.cpp
|
@ -19,95 +19,13 @@
|
|||
#include "util/util.h"
|
||||
|
||||
#include "util/json5pp.hpp"
|
||||
#include "util/iniconfig.h"
|
||||
|
||||
#if defined(MKXPZ_BUILD_XCODE) || defined(MKXPZ_INI_ENCODING)
|
||||
#include <iconv.h>
|
||||
#include <uchardet.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include "util/iniconfig.h"
|
||||
#include "util/encoding.h"
|
||||
|
||||
|
||||
namespace json = json5pp;
|
||||
|
||||
/* http://stackoverflow.com/a/1031773 */
|
||||
static bool validUtf8(const char *string)
|
||||
{
|
||||
const uint8_t *bytes = (uint8_t*) string;
|
||||
|
||||
while(*bytes)
|
||||
{
|
||||
if( (/* ASCII
|
||||
* use bytes[0] <= 0x7F to allow ASCII control characters */
|
||||
bytes[0] == 0x09 ||
|
||||
bytes[0] == 0x0A ||
|
||||
bytes[0] == 0x0D ||
|
||||
(0x20 <= bytes[0] && bytes[0] <= 0x7E)
|
||||
)
|
||||
) {
|
||||
bytes += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( (/* non-overlong 2-byte */
|
||||
(0xC2 <= bytes[0] && bytes[0] <= 0xDF) &&
|
||||
(0x80 <= bytes[1] && bytes[1] <= 0xBF)
|
||||
)
|
||||
) {
|
||||
bytes += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( (/* excluding overlongs */
|
||||
bytes[0] == 0xE0 &&
|
||||
(0xA0 <= bytes[1] && bytes[1] <= 0xBF) &&
|
||||
(0x80 <= bytes[2] && bytes[2] <= 0xBF)
|
||||
) ||
|
||||
(/* straight 3-byte */
|
||||
((0xE1 <= bytes[0] && bytes[0] <= 0xEC) ||
|
||||
bytes[0] == 0xEE ||
|
||||
bytes[0] == 0xEF) &&
|
||||
(0x80 <= bytes[1] && bytes[1] <= 0xBF) &&
|
||||
(0x80 <= bytes[2] && bytes[2] <= 0xBF)
|
||||
) ||
|
||||
(/* excluding surrogates */
|
||||
bytes[0] == 0xED &&
|
||||
(0x80 <= bytes[1] && bytes[1] <= 0x9F) &&
|
||||
(0x80 <= bytes[2] && bytes[2] <= 0xBF)
|
||||
)
|
||||
) {
|
||||
bytes += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( (/* planes 1-3 */
|
||||
bytes[0] == 0xF0 &&
|
||||
(0x90 <= bytes[1] && bytes[1] <= 0xBF) &&
|
||||
(0x80 <= bytes[2] && bytes[2] <= 0xBF) &&
|
||||
(0x80 <= bytes[3] && bytes[3] <= 0xBF)
|
||||
) ||
|
||||
(/* planes 4-15 */
|
||||
(0xF1 <= bytes[0] && bytes[0] <= 0xF3) &&
|
||||
(0x80 <= bytes[1] && bytes[1] <= 0xBF) &&
|
||||
(0x80 <= bytes[2] && bytes[2] <= 0xBF) &&
|
||||
(0x80 <= bytes[3] && bytes[3] <= 0xBF)
|
||||
) ||
|
||||
(/* plane 16 */
|
||||
bytes[0] == 0xF4 &&
|
||||
(0x80 <= bytes[1] && bytes[1] <= 0x8F) &&
|
||||
(0x80 <= bytes[2] && bytes[2] <= 0xBF) &&
|
||||
(0x80 <= bytes[3] && bytes[3] <= 0xBF)
|
||||
)
|
||||
) {
|
||||
bytes += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string prefPath(const char *org, const char *app) {
|
||||
char *path = SDL_GetPrefPath(org, app);
|
||||
if (!path)
|
||||
|
@ -238,7 +156,6 @@ try { exp } catch (...) {}
|
|||
editor.battleTest = true;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
launchArgs.push_back(argv[i]);
|
||||
}
|
||||
}
|
||||
|
@ -247,14 +164,21 @@ try { exp } catch (...) {}
|
|||
|
||||
json::value confData = json::value(0);
|
||||
try {
|
||||
confData = json::parse5(mkxp_fs::contentsOfFileAsString(CONF_FILE));
|
||||
} catch (...) {
|
||||
Debug() << "Failed to parse JSON configuration";
|
||||
std::string cfg = mkxp_fs::contentsOfFileAsString(CONF_FILE);
|
||||
confData = json::parse5(Encoding::convertString(cfg));
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
Debug() << "Failed to parse JSON configuration:" << e.what();
|
||||
}
|
||||
catch (const Exception &e) {
|
||||
Debug() << "Failed to parse JSON configuration: Unknown encoding";
|
||||
}
|
||||
|
||||
if (!confData.is_object())
|
||||
confData = json::object({});
|
||||
|
||||
raw = confData;
|
||||
|
||||
copyObject(optsJ, confData);
|
||||
copyObject(opts["bindingNames"], confData.as_object()["bindingNames"], "bindingNames .");
|
||||
}
|
||||
|
@ -347,6 +271,7 @@ void Config::readGameINI() {
|
|||
std::string iniFileName(execName + ".ini");
|
||||
SDLRWStream iniFile(iniFileName.c_str(), "r");
|
||||
|
||||
bool convSuccess = false;
|
||||
if (iniFile)
|
||||
{
|
||||
INIConfiguration ic;
|
||||
|
@ -368,48 +293,13 @@ void Config::readGameINI() {
|
|||
else
|
||||
Debug() << "Could not read" << iniFileName;
|
||||
|
||||
bool convSuccess = false;
|
||||
|
||||
// Attempt to convert from other encodings to UTF-8
|
||||
if (!validUtf8(game.title.c_str()))
|
||||
{
|
||||
#if defined(MKXPZ_BUILD_XCODE) || defined(MKXPZ_INI_ENCODING)
|
||||
uchardet_t ud = uchardet_new();
|
||||
uchardet_handle_data(ud, game.title.c_str(), game.title.length());
|
||||
uchardet_data_end(ud);
|
||||
const char *charset = uchardet_get_charset(ud);
|
||||
|
||||
Debug() << iniFileName << ": Assuming encoding is" << charset << "...";
|
||||
iconv_t cd = iconv_open("UTF-8", charset);
|
||||
|
||||
uchardet_delete(ud);
|
||||
|
||||
size_t inLen = game.title.size();
|
||||
size_t outLen = inLen * 4;
|
||||
std::string buf(outLen, '\0');
|
||||
char *inPtr = const_cast<char*>(game.title.c_str());
|
||||
char *outPtr = const_cast<char*>(buf.c_str());
|
||||
|
||||
errno = 0;
|
||||
size_t result = iconv(cd, &inPtr, &inLen, &outPtr, &outLen);
|
||||
|
||||
iconv_close(cd);
|
||||
|
||||
if (result != (size_t)-1 && errno == 0)
|
||||
{
|
||||
buf.resize(buf.size()-outLen);
|
||||
game.title = buf;
|
||||
try {
|
||||
game.title = Encoding::convertString(game.title);
|
||||
convSuccess = true;
|
||||
}
|
||||
else {
|
||||
Debug() << iniFileName << ": failed to convert game title to UTF-8";
|
||||
catch (const Exception &e) {
|
||||
Debug() << iniFileName + ": Could not determine encoding of Game.Title";
|
||||
}
|
||||
#else
|
||||
Debug() << iniFileName << ": Game title isn't valid UTF-8";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
convSuccess = true;
|
||||
|
||||
if (game.title.empty() || !convSuccess)
|
||||
game.title = "mkxp-z";
|
||||
|
|
|
@ -22,11 +22,16 @@
|
|||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include "util/json5pp.hpp"
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct Config {
|
||||
// Used for sending the JSON data to Ruby as System::CONFIG
|
||||
json5pp::value raw;
|
||||
|
||||
int rgssVersion;
|
||||
|
||||
bool debugMode;
|
||||
|
|
|
@ -22,11 +22,6 @@
|
|||
#ifndef EVENTTHREAD_H
|
||||
#define EVENTTHREAD_H
|
||||
|
||||
#include "config.h"
|
||||
#include "etc-internal.h"
|
||||
#include "sdl-util.h"
|
||||
#include "keybindings.h"
|
||||
|
||||
#include <SDL_scancode.h>
|
||||
#include <SDL_joystick.h>
|
||||
#include <SDL_mouse.h>
|
||||
|
@ -36,6 +31,11 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "etc-internal.h"
|
||||
#include "sdl-util.h"
|
||||
#include "keybindings.h"
|
||||
|
||||
struct RGSSThreadData;
|
||||
typedef struct MKXPZ_ALCDEVICE ALCdevice;
|
||||
struct SDL_Window;
|
||||
|
|
|
@ -12,6 +12,8 @@ pixman = dependency('pixman-1', static: build_static)
|
|||
png = dependency('libpng', static: build_static)
|
||||
jpeg = dependency('libjpeg', static: build_static)
|
||||
zlib = dependency('zlib', static: build_static)
|
||||
iconv = compilers['cpp'].find_library('iconv', static: build_static)
|
||||
uchardet = dependency('uchardet', static: build_static)
|
||||
|
||||
if host_system == 'windows'
|
||||
bz2 = dependency('bzip2', static: build_static)
|
||||
|
@ -33,15 +35,6 @@ if get_option('enable-https') == true
|
|||
endif
|
||||
endif
|
||||
|
||||
# If iconv is present, mkxp will try to identify and convert the encoding
|
||||
# of the game's title
|
||||
iconv = compilers['cpp'].find_library('iconv', static: build_static, required: false)
|
||||
if iconv.found() == true
|
||||
global_dependencies += iconv
|
||||
global_dependencies += dependency('uchardet', static: build_static)
|
||||
global_args += '-DMKXPZ_INI_ENCODING'
|
||||
endif
|
||||
|
||||
# Windows needs to be treated like a special needs child here
|
||||
explicit_libs = ''
|
||||
if host_system == 'windows'
|
||||
|
@ -85,7 +78,7 @@ global_include_dirs += include_directories('.',
|
|||
'util', 'util/sigslot', 'util/sigslot/adapter'
|
||||
)
|
||||
|
||||
global_dependencies += [openal, zlib, bz2, sdl2, sdl_sound, pixman, physfs, vorbisfile, vorbis, ogg, sdl2_ttf, freetype, sdl2_image, png, jpeg]
|
||||
global_dependencies += [openal, zlib, bz2, sdl2, sdl_sound, pixman, physfs, vorbisfile, vorbis, ogg, sdl2_ttf, freetype, sdl2_image, png, jpeg, iconv, uchardet]
|
||||
if host_system == 'windows'
|
||||
global_dependencies += compilers['cpp'].find_library('wsock32')
|
||||
endif
|
||||
|
|
68
src/util/encoding.h
Normal file
68
src/util/encoding.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// encoding.h
|
||||
// mkxp-z
|
||||
//
|
||||
// Created by ゾロアーク on 6/22/21.
|
||||
//
|
||||
|
||||
#ifndef encoding_h
|
||||
#define encoding_h
|
||||
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
#include "util/encoding.h"
|
||||
#include <iconv.h>
|
||||
#include <uchardet.h>
|
||||
#include <errno.h>
|
||||
|
||||
namespace Encoding {
|
||||
|
||||
static std::string getCharset(std::string &str) {
|
||||
uchardet_t ud = uchardet_new();
|
||||
uchardet_handle_data(ud, str.c_str(), str.length());
|
||||
uchardet_data_end(ud);
|
||||
|
||||
std::string ret(uchardet_get_charset(ud));
|
||||
uchardet_delete(ud);
|
||||
|
||||
if (ret.empty())
|
||||
throw Exception(Exception::MKXPError, "Could not detect encoding of \"%s\"", str.c_str());
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::string convertString(std::string &str) {
|
||||
|
||||
std::string charset = getCharset(str);
|
||||
|
||||
// Conversion doesn't need to happen if it's already UTF-8
|
||||
if (!strcmp(charset.c_str(), "UTF-8") || !strcmp(charset.c_str(), "ASCII")) {
|
||||
return std::string(str);
|
||||
}
|
||||
|
||||
iconv_t cd = iconv_open("UTF-8", getCharset(str).c_str());
|
||||
|
||||
size_t inLen = str.size();
|
||||
size_t outLen = inLen * 4;
|
||||
std::string buf(outLen, '\0');
|
||||
char *inPtr = const_cast<char*>(str.c_str());
|
||||
char *outPtr = const_cast<char*>(buf.c_str());
|
||||
|
||||
errno = 0;
|
||||
size_t result = iconv(cd, &inPtr, &inLen, &outPtr, &outLen);
|
||||
|
||||
iconv_close(cd);
|
||||
|
||||
if (result != (size_t)-1 && errno == 0)
|
||||
{
|
||||
buf.resize(buf.size()-outLen);
|
||||
}
|
||||
else {
|
||||
throw Exception(Exception::MKXPError, "Failed to convert \"%s\" to UTF-8", str.c_str());
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* encoding_h */
|
Loading…
Add table
Reference in a new issue