diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e9ebb1..25522a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -217,6 +217,11 @@ set(MAIN_SOURCE src/fluid-fun.cpp ) +if(WIN32) + list(APPEND MAIN_HEADERS windows/resource.h) + list(APPEND MAIN_SOURCE windows/resource.rc) +endif() + source_group("MKXP Source" FILES ${MAIN_SOURCE} ${MAIN_HEADERS}) ## Setup embedded source ## @@ -417,6 +422,7 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE ) target_include_directories(${PROJECT_NAME} PRIVATE src + windows ${SIGCXX_INCLUDE_DIRS} ${PIXMAN_INCLUDE_DIRS} ${PHYSFS_INCLUDE_DIRS} diff --git a/binding-mri/binding-mri.cpp b/binding-mri/binding-mri.cpp index 2054900..84536d3 100644 --- a/binding-mri/binding-mri.cpp +++ b/binding-mri/binding-mri.cpp @@ -149,7 +149,16 @@ static void mriBindingInit() _rb_define_module_function(mod, "raw_key_states", mkxpRawKeyStates); _rb_define_module_function(mod, "mouse_in_window", mkxpMouseInWindow); + /* Load global constants */ rb_gv_set("MKXP", Qtrue); + + VALUE debug = rb_bool_new(shState->config().editor.debug); + if (rgssVer == 1) + rb_gv_set("DEBUG", debug); + else if (rgssVer >= 2) + rb_gv_set("TEST", debug); + + rb_gv_set("BTEST", rb_bool_new(shState->config().editor.battleTest)); } static void diff --git a/binding-mri/binding-util.h b/binding-mri/binding-util.h index 3165739..53e2717 100644 --- a/binding-mri/binding-util.h +++ b/binding-mri/binding-util.h @@ -188,7 +188,8 @@ raiseRbExc(const Exception &exc); extern rb_data_type_t Klass##Type /* 2.1 has added a new field (flags) to rb_data_type_t */ -#if RUBY_API_VERSION_MAJOR > 1 && RUBY_API_VERSION_MINOR > 0 +#include +#if RUBY_API_VERSION_MAJOR >= 2 && RUBY_API_VERSION_MINOR >= 1 /* TODO: can mkxp use RUBY_TYPED_FREE_IMMEDIATELY here? */ #define DEF_TYPE_FLAGS 0 #else @@ -211,7 +212,12 @@ raiseRbExc(const Exception &exc); template static VALUE classAllocate(VALUE klass) { +/* 2.3 has changed the name of this function */ +#if RUBY_API_VERSION_MAJOR >= 2 && RUBY_API_VERSION_MINOR >= 3 + return rb_data_typed_object_wrap(klass, 0, rbType); +#else return rb_data_typed_object_alloc(klass, 0, rbType); +#endif } template diff --git a/binding-mruby/binding-mruby.cpp b/binding-mruby/binding-mruby.cpp index d09c876..0c95fd6 100644 --- a/binding-mruby/binding-mruby.cpp +++ b/binding-mruby/binding-mruby.cpp @@ -118,8 +118,17 @@ static void mrbBindingInit(mrb_state *mrb) /* Load RPG module */ mrb_load_irep(mrb, mrbModuleRPG); + /* Load global constants */ mrb_define_global_const(mrb, "MKXP", mrb_true_value()); + mrb_value debug = rb_bool_new(shState->config().editor.debug); + if (rgssVer == 1) + mrb_define_global_const(mrb, "DEBUG", debug); + else if (rgssVer >= 2) + mrb_define_global_const(mrb, "TEST", debug); + + mrb_define_global_const(mrb, "BTEST", mrb_bool_value(shState->config().editor.battleTest)); + mrb_gc_arena_restore(mrb, arena); } diff --git a/mkxp.conf.sample b/mkxp.conf.sample index 500dcc6..9863eaf 100644 --- a/mkxp.conf.sample +++ b/mkxp.conf.sample @@ -86,6 +86,12 @@ # defScreenH=480 +# Override the game window title +# (default: none) +# +# windowTitle=Custom Title + + # Enforce a static frame rate # (0 = disabled) # diff --git a/src/config.cpp b/src/config.cpp index b0e1547..d7b106a 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -163,6 +163,7 @@ void Config::read(int argc, char *argv[]) PO_DESC(vsync, bool, false) \ PO_DESC(defScreenW, int, 0) \ PO_DESC(defScreenH, int, 0) \ + PO_DESC(windowTitle, std::string, "") \ PO_DESC(fixedFramerate, int, 0) \ PO_DESC(frameSkip, bool, true) \ PO_DESC(syncToRefreshrate, bool, false) \ @@ -190,6 +191,27 @@ void Config::read(int argc, char *argv[]) // Not gonna take your shit boost #define GUARD_ALL( exp ) try { exp } catch(...) {} + editor.debug = false; + editor.battleTest = false; + + /* Read arguments sent from the editor */ + if (argc > 1) + { + std::string argv1 = argv[1]; + /* RGSS1 uses "debug", 2 and 3 use "test" */ + if (argv1 == "debug" || argv1 == "test") + editor.debug = true; + else if (argv1 == "btest") + editor.battleTest = true; + + /* Fix offset */ + if (editor.debug || editor.battleTest) + { + argc--; + argv++; + } + } + #define PO_DESC(key, type, def) (#key, po::value< type >()->default_value(def)) po::options_description podesc; diff --git a/src/config.h b/src/config.h index 2889b6a..2bbd2d5 100644 --- a/src/config.h +++ b/src/config.h @@ -41,6 +41,7 @@ struct Config int defScreenW = 0; int defScreenH = 0; + std::string windowTitle; int fixedFramerate = 0; bool frameSkip =false; @@ -87,6 +88,12 @@ struct Config std::vector rubyLoadpaths; + /* Editor flags */ + struct { + bool debug; + bool battleTest; + } editor; + /* Game INI contents */ struct { std::string scripts; diff --git a/src/eventthread.cpp b/src/eventthread.cpp index 6749767..beec9b7 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -277,14 +277,14 @@ void EventThread::process(RGSSThreadData &rtData) if (fullscreen) { /* Prevent fullscreen flicker */ - strncpy(pendingTitle, rtData.config.game.title.c_str(), + strncpy(pendingTitle, rtData.config.windowTitle.c_str(), sizeof(pendingTitle)); havePendingTitle = true; break; } - SDL_SetWindowTitle(win, rtData.config.game.title.c_str()); + SDL_SetWindowTitle(win, rtData.config.windowTitle.c_str()); } break; @@ -391,7 +391,7 @@ void EventThread::process(RGSSThreadData &rtData) case REQUEST_MESSAGEBOX : SDL_ShowSimpleMessageBox(event.user.code, - rtData.config.game.title.c_str(), + rtData.config.windowTitle.c_str(), (const char*) event.user.data1, win); free(event.user.data1); msgBoxDone.set(); @@ -410,7 +410,7 @@ void EventThread::process(RGSSThreadData &rtData) break; snprintf(buffer, sizeof(buffer), "%s - %d FPS", - rtData.config.game.title.c_str(), event.user.code); + rtData.config.windowTitle.c_str(), event.user.code); /* Updating the window title in fullscreen * mode seems to cause flickering */ diff --git a/src/filesystem.cpp b/src/filesystem.cpp index 5fc5eae..a6b9b8f 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -398,8 +398,8 @@ struct CacheEnumData } }; -static void cacheEnumCB(void *d, const char *origdir, - const char *fname) +static PHYSFS_EnumerateCallbackResult +cacheEnumCB(void *d, const char *origdir, const char *fname) { CacheEnumData &data = *static_cast(d); char fullPath[512]; @@ -426,7 +426,7 @@ static void cacheEnumCB(void *d, const char *origdir, /* Iterate over its contents */ data.fileLists.push(&list); - PHYSFS_enumerateFilesCallback(fullPath, cacheEnumCB, d); + PHYSFS_enumerate(fullPath, cacheEnumCB, d); data.fileLists.pop(); } else @@ -441,13 +441,15 @@ static void cacheEnumCB(void *d, const char *origdir, /* Add the lower -> mixed mapping of the file's full path */ data.p->pathCache.insert(lowerCase, mixedCase); } + + return PHYSFS_ENUM_OK; } void FileSystem::createPathCache() { CacheEnumData data(p); data.fileLists.push(&p->fileLists[""]); - PHYSFS_enumerateFilesCallback("", cacheEnumCB, &data); + PHYSFS_enumerate("", cacheEnumCB, &data); p->havePathCache = true; } @@ -458,8 +460,8 @@ struct FontSetsCBData SharedFontState *sfs; }; -static void fontSetEnumCB(void *data, const char *dir, - const char *fname) +static PHYSFS_EnumerateCallbackResult +fontSetEnumCB (void *data, const char *dir, const char *fname) { FontSetsCBData *d = static_cast(data); @@ -467,7 +469,7 @@ static void fontSetEnumCB(void *data, const char *dir, const char *ext = findExt(fname); if (!ext) - return; + return PHYSFS_ENUM_STOP; char lowExt[8]; size_t i; @@ -477,7 +479,7 @@ static void fontSetEnumCB(void *data, const char *dir, lowExt[i] = '\0'; if (strcmp(lowExt, "ttf") && strcmp(lowExt, "otf")) - return; + return PHYSFS_ENUM_STOP; char filename[512]; snprintf(filename, sizeof(filename), "%s/%s", dir, fname); @@ -485,7 +487,7 @@ static void fontSetEnumCB(void *data, const char *dir, PHYSFS_File *handle = PHYSFS_openRead(filename); if (!handle) - return; + return PHYSFS_ENUM_ERROR; SDL_RWops ops; initReadOps(handle, ops, false); @@ -493,31 +495,35 @@ static void fontSetEnumCB(void *data, const char *dir, d->sfs->initFontSetCB(ops, filename); SDL_RWclose(&ops); + + return PHYSFS_ENUM_OK; } /* Basically just a case-insensitive search * for the folder "Fonts"... */ -static void findFontsFolderCB(void *data, const char *, - const char *fname) +static PHYSFS_EnumerateCallbackResult +findFontsFolderCB(void *data, const char *, const char *fname) { size_t i = 0; char buffer[512]; const char *s = fname; - while (s && i < sizeof(buffer)) + while (*s && i < sizeof(buffer)) buffer[i++] = tolower(*s++); buffer[i] = '\0'; if (strcmp(buffer, "fonts") == 0) - PHYSFS_enumerateFilesCallback(fname, fontSetEnumCB, data); + PHYSFS_enumerate(fname, fontSetEnumCB, data); + + return PHYSFS_ENUM_OK; } void FileSystem::initFontSets(SharedFontState &sfs) { FontSetsCBData d = { p, &sfs }; - PHYSFS_enumerateFilesCallback(".", findFontsFolderCB, &d); + PHYSFS_enumerate("", findFontsFolderCB, &d); } struct OpenReadEnumData @@ -550,19 +556,19 @@ struct OpenReadEnumData {} }; -static void openReadEnumCB(void *d, const char *dirpath, - const char *filename) +static PHYSFS_EnumerateCallbackResult +openReadEnumCB(void *d, const char *dirpath, const char *filename) { OpenReadEnumData &data = *static_cast(d); char buffer[512]; const char *fullPath; if (data.stopSearching) - return; + return PHYSFS_ENUM_STOP; /* If there's not even a partial match, continue searching */ if (strncmp(filename, data.filename, data.filenameN) != 0) - return; + return PHYSFS_ENUM_OK; if (!*dirpath) { @@ -580,7 +586,7 @@ static void openReadEnumCB(void *d, const char *dirpath, * of the extension), or up to a following '\0' (full match), we've * found our file */ if (last != '.' && last != '\0') - return; + return PHYSFS_ENUM_STOP; /* If the path cache is active, translate from lower case * to mixed case path */ @@ -595,9 +601,9 @@ static void openReadEnumCB(void *d, const char *dirpath, * be a deeper rooted problem somewhere within PhysFS. * Just abort alltogether. */ data.stopSearching = true; - data.physfsError = PHYSFS_getLastError(); + data.physfsError = PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()); - return; + return PHYSFS_ENUM_ERROR; } initReadOps(phys, data.ops, false); @@ -608,6 +614,7 @@ static void openReadEnumCB(void *d, const char *dirpath, data.stopSearching = true; ++data.matchCount; + return PHYSFS_ENUM_OK; } void FileSystem::openRead(OpenHandler &handler, const char *filename) @@ -653,7 +660,7 @@ void FileSystem::openRead(OpenHandler &handler, const char *filename) } else { - PHYSFS_enumerateFilesCallback(dir, openReadEnumCB, &data); + PHYSFS_enumerate(dir, openReadEnumCB, &data); } if (data.physfsError) diff --git a/src/graphics.cpp b/src/graphics.cpp index df194cf..e640042 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -92,11 +92,9 @@ struct PingPong { screenW = width; screenH = height; + for (int i = 0; i < 2; ++i) - { - TEX::bind(rt[i].tex); - TEX::allocEmpty(width, height); - } + TEXFBO::allocEmpty(rt[i], width, height); } void startRender() @@ -483,9 +481,7 @@ struct GraphicsPrivate bool frozen; TEXFBO frozenScene; - TEXFBO currentScene; Quad screenQuad; - TEXFBO transBuffer; /* Global list of all live Disposables * (disposed on reset) */ @@ -511,26 +507,15 @@ struct GraphicsPrivate TEXFBO::allocEmpty(frozenScene, scRes.x, scRes.y); TEXFBO::linkFBO(frozenScene); - TEXFBO::init(currentScene); - TEXFBO::allocEmpty(currentScene, scRes.x, scRes.y); - TEXFBO::linkFBO(currentScene); - FloatRect screenRect(0, 0, scRes.x, scRes.y); screenQuad.setTexPosRect(screenRect, screenRect); - TEXFBO::init(transBuffer); - TEXFBO::allocEmpty(transBuffer, scRes.x, scRes.y); - TEXFBO::linkFBO(transBuffer); - fpsLimiter.resetFrameAdjust(); } ~GraphicsPrivate() { TEXFBO::fini(frozenScene); - TEXFBO::fini(currentScene); - - TEXFBO::fini(transBuffer); } void updateScreenResoRatio(RGSSThreadData *rtData) @@ -730,8 +715,15 @@ void Graphics::transition(int duration, setBrightness(255); + /* The PP frontbuffer will hold the current scene after the + * composition step. Since the backbuffer is unused during + * the transition, we can reuse it as the target buffer for + * the final rendered image. */ + TEXFBO ¤tScene = p->screen.getPP().frontBuffer(); + TEXFBO &transBuffer = p->screen.getPP().backBuffer(); + /* Capture new scene */ - p->compositeToBuffer(p->currentScene); + p->screen.composite(); /* If no transition bitmap is provided, * we can use a simplified shader */ @@ -744,7 +736,7 @@ void Graphics::transition(int duration, shader.bind(); shader.applyViewportProj(); shader.setFrozenScene(p->frozenScene.tex); - shader.setCurrentScene(p->currentScene.tex); + shader.setCurrentScene(currentScene.tex); shader.setTransMap(transMap->getGLTypes().tex); shader.setVague(vague / 256.0f); shader.setTexSize(p->scRes); @@ -755,7 +747,7 @@ void Graphics::transition(int duration, shader.bind(); shader.applyViewportProj(); shader.setFrozenScene(p->frozenScene.tex); - shader.setCurrentScene(p->currentScene.tex); + shader.setCurrentScene(currentScene.tex); shader.setTexSize(p->scRes); } @@ -799,7 +791,7 @@ void Graphics::transition(int duration, /* Draw the composed frame to a buffer first * (we need this because we're skipping PingPong) */ - FBO::bind(p->transBuffer.fbo); + FBO::bind(transBuffer.fbo); FBO::clear(); p->screenQuad.draw(); @@ -810,7 +802,7 @@ void Graphics::transition(int duration, FBO::clear(); GLMeta::blitBeginScreen(Vec2i(p->winSize)); - GLMeta::blitSource(p->transBuffer); + GLMeta::blitSource(transBuffer); p->metaBlitBufferFlippedScaled(); GLMeta::blitEnd(); @@ -953,17 +945,11 @@ void Graphics::resizeScreen(int width, int height) p->screen.setResolution(width, height); - TEX::bind(p->frozenScene.tex); - TEX::allocEmpty(width, height); - TEX::bind(p->currentScene.tex); - TEX::allocEmpty(width, height); + TEXFBO::allocEmpty(p->frozenScene, width, height); FloatRect screenRect(0, 0, width, height); p->screenQuad.setTexPosRect(screenRect, screenRect); - TEX::bind(p->transBuffer.tex); - TEX::allocEmpty(width, height); - shState->eThread().requestWindowResize(width, height); } diff --git a/src/main.cpp b/src/main.cpp index fc61f26..d35fd92 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -237,7 +237,10 @@ int main(int argc, char *argv[]) } conf.readGameINI(); - printf("%s\n", conf.gameFolder.c_str()); + + if (conf.windowTitle.empty()) + conf.windowTitle = conf.game.title; + assert(conf.rgssVersion >= 1 && conf.rgssVersion <= 3); printRgssVersion(conf.rgssVersion); @@ -277,7 +280,7 @@ int main(int argc, char *argv[]) if (conf.fullscreen) winFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP; - win = SDL_CreateWindow(conf.game.title.c_str(), + win = SDL_CreateWindow(conf.windowTitle.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, conf.defScreenW, conf.defScreenH, winFlags); @@ -360,13 +363,13 @@ int main(int argc, char *argv[]) if (rtData.rqTermAck){} //SDL_WaitThread(rgssThread, 0); else - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.c_str(), + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.windowTitle.c_str(), "The RGSS script seems to be stuck and mkxp will now force quit", win); if (!rtData.rgssErrorMsg.empty()) { Debug() << rtData.rgssErrorMsg; - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.c_str(), + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.windowTitle.c_str(), rtData.rgssErrorMsg.c_str(), win); } diff --git a/src/rgssad.cpp b/src/rgssad.cpp index 17e8417..ac8772a 100644 --- a/src/rgssad.cpp +++ b/src/rgssad.cpp @@ -297,6 +297,8 @@ processDirectories(RGSS_archiveData *data, BoostSet &topLevel, if (slash) nameBuf[i] = '/'; + + break; } /* Check for more entries */ @@ -331,14 +333,16 @@ verifyHeader(PHYSFS_Io *io, char version) } static void* -RGSS_openArchive(PHYSFS_Io *io, const char *, int forWrite) +RGSS_openArchive(PHYSFS_Io *io, const char *, int forWrite, int *claimed) { if (forWrite) - return 0; + return NULL; /* Version 1 */ if (!verifyHeader(io, 1)) - return 0; + return NULL; + else + *claimed = 1; RGSS_archiveData *data = new RGSS_archiveData; data->archiveIo = io; @@ -389,9 +393,9 @@ RGSS_openArchive(PHYSFS_Io *io, const char *, int forWrite) return data; } -static void +static PHYSFS_EnumerateCallbackResult RGSS_enumerateFiles(void *opaque, const char *dirname, - PHYSFS_EnumFilesCallback cb, + PHYSFS_EnumerateCallback cb, const char *origdir, void *callbackdata) { RGSS_archiveData *data = static_cast(opaque); @@ -399,13 +403,15 @@ RGSS_enumerateFiles(void *opaque, const char *dirname, std::string _dirname(dirname); if (!data->dirHash.contains(_dirname)) - return; + return PHYSFS_ENUM_STOP; const BoostSet &entries = data->dirHash[_dirname]; BoostSet::const_iterator iter; for (iter = entries.cbegin(); iter != entries.cend(); ++iter) cb(callbackdata, origdir, iter->c_str()); + + return PHYSFS_ENUM_OK; } static PHYSFS_Io* @@ -536,19 +542,21 @@ readUint32AndXor(PHYSFS_Io *io, uint32_t &result, uint32_t key) } static void* -RGSS3_openArchive(PHYSFS_Io *io, const char *, int forWrite) +RGSS3_openArchive(PHYSFS_Io *io, const char *, int forWrite, int *claimed) { if (forWrite) - return 0; + return NULL; /* Version 3 */ if (!verifyHeader(io, 3)) - return 0; + return NULL; + else + *claimed = 1; uint32_t baseMagic; if (!readUint32(io, baseMagic)) - return 0; + return NULL; baseMagic = (baseMagic * 9) + 3; @@ -605,7 +613,7 @@ RGSS3_openArchive(PHYSFS_Io *io, const char *, int forWrite) error: delete data; - return 0; + return NULL; } return data; diff --git a/src/sprite.cpp b/src/sprite.cpp index 7999546..26eb297 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp @@ -121,7 +121,7 @@ struct SpritePrivate void recomputeBushDepth() { - if (!bitmap) + if (nullOrDisposed(bitmap)) return; /* Calculate effective (normalized) bush depth */ @@ -137,18 +137,15 @@ struct SpritePrivate FloatRect rect = srcRect->toFloatRect(); Vec2i bmSize; - if (bitmap) + if (!nullOrDisposed(bitmap)) bmSize = Vec2i(bitmap->width(), bitmap->height()); - if (mirrored) - rect = rect.hFlipped(); - /* Clamp the rectangle so it doesn't reach outside * the bitmap bounds */ rect.w = clamp(rect.w, 0, bmSize.x-rect.x); rect.h = clamp(rect.h, 0, bmSize.y-rect.y); - quad.setTexRect(rect); + quad.setTexRect(mirrored ? rect.hFlipped() : rect); quad.setPosRect(FloatRect(0, 0, rect.w, rect.h)); recomputeBushDepth(); diff --git a/assets/icon.ico b/windows/icon.ico similarity index 100% rename from assets/icon.ico rename to windows/icon.ico diff --git a/assets/resource.h b/windows/resource.h similarity index 100% rename from assets/resource.h rename to windows/resource.h diff --git a/assets/resource.rc b/windows/resource.rc similarity index 100% rename from assets/resource.rc rename to windows/resource.rc