From d94557bdb149334e96605888ecd0b7a45bd73cb1 Mon Sep 17 00:00:00 2001 From: drxgb Date: Mon, 23 Oct 2023 19:58:39 -0300 Subject: [PATCH 1/9] Destiny Patch support --- src/destiny.cpp | 137 +++++++++++++++++++++++++++++++++++++++ src/destiny.h | 39 +++++++++++ src/game_config_game.h | 1 + src/game_interpreter.cpp | 1 + src/player.cpp | 13 +++- src/player.h | 9 +++ 6 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 src/destiny.cpp create mode 100644 src/destiny.h diff --git a/src/destiny.cpp b/src/destiny.cpp new file mode 100644 index 0000000000..1747303d48 --- /dev/null +++ b/src/destiny.cpp @@ -0,0 +1,137 @@ +/* + * This file is part of EasyRPG Player. + * + * EasyRPG Player 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 3 of the License, or + * (at your option) any later version. + * + * EasyRPG Player 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 EasyRPG Player. If not, see . + */ + +// Headers +#include "destiny.h" + +#include +#include + +#ifndef EMSCRIPTEN +#include "exe_reader.h" +#endif // !EMSCRIPTEN +#include "output.h" + + + +// Definitions +using destiny_dword_list = std::vector; +using destiny_float_list = std::vector; +using destiny_string_list = std::vector; + + +namespace Destiny { + enum Language { + DEUTSCH = 0, + ENGLISH, + }; + + struct Version { + uint16_t major; + uint16_t minor; + + Version() + : major(0), minor(0) {} + Version(uint32_t version) { + major = version >> 0x10; + minor = version & 0xFFFF; + } + + std::string toString() { + std::stringstream ss; + + ss << major << '.' << minor; + return ss.str(); + } + }; + + // Destiny containers + static destiny_dword_list dwords; + static destiny_float_list floats; + static destiny_string_list strings; + + // Destiny data + static Version dllVersion; + static Version gameVersion; + static Language language; + static uint32_t extra; +} + + +// Implementations +void Destiny::Load() +{ + // Do not load Destiny whether player cannot find "Destiny.dll" + if (!FileFinder::Game().Exists(DESTINY_DLL)) + return; + + uint32_t dllVersion = 0; + uint32_t language = 0; + uint32_t gameVersion = 0; + uint32_t extra = 0; + uint32_t dwordSize = 0; + uint32_t floatSize = 0; + uint32_t stringSize = 0; + +#ifndef EMSCRIPTEN + Filesystem_Stream::InputStream exe = FileFinder::Game().OpenFile(EXE_NAME); + + if (exe) { + exe.seekg(0x00030689, std::ios_base::beg); + exe.read(reinterpret_cast(&stringSize), sizeof(uint32_t)); + exe.seekg(1, std::ios_base::cur); + exe.read(reinterpret_cast(&floatSize), sizeof(uint32_t)); + exe.seekg(1, std::ios_base::cur); + exe.read(reinterpret_cast(&dwordSize), sizeof(uint32_t)); + exe.seekg(1, std::ios_base::cur); + exe.read(reinterpret_cast(&extra), sizeof(uint32_t)); + exe.seekg(1, std::ios_base::cur); + exe.read(reinterpret_cast(&gameVersion), sizeof(uint32_t)); + exe.seekg(1, std::ios_base::cur); + exe.read(reinterpret_cast(&language), sizeof(uint32_t)); + exe.seekg(1, std::ios_base::cur); + exe.read(reinterpret_cast(&dllVersion), sizeof(uint32_t)); + exe.seekg(1, std::ios_base::cur); + } +#else + // TODO [Dr.XGB]: Find to manage Destiny initialization parameters on emscripten + dllVersion = 0x20000; + language = ENGLISH; + gameVersion = 0x20000107; + extra = 0x01; + dwordSize = floatSize = stringSize = 0x64; +#endif // !EMSCRIPTEN + + Initialize(dllVersion, language, gameVersion, extra, dwordSize, floatSize, stringSize); +} + +void Destiny::Initialize(uint32_t _dllVersion, uint32_t _language, uint32_t _gameVersion, uint32_t _extra, uint32_t _dwordSize, uint32_t _floatSize, uint32_t _stringSize) +{ + dllVersion = Version(_dllVersion); + gameVersion = Version(_gameVersion); + language = (Language)_language; + extra = _extra; + dwords.resize(_dwordSize); + floats.resize(_floatSize); + strings.resize(_stringSize); + + Output::Debug("Destiny Initialized"); + Output::Debug("DLL Version: {}", dllVersion.toString()); + Output::Debug("Dwords: {}", _dwordSize); + Output::Debug("Floats: {}", _floatSize); + Output::Debug("Strings: {}", _stringSize); +} diff --git a/src/destiny.h b/src/destiny.h new file mode 100644 index 0000000000..046fbd17b1 --- /dev/null +++ b/src/destiny.h @@ -0,0 +1,39 @@ +/* + * This file is part of EasyRPG Player. + * + * EasyRPG Player 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 3 of the License, or + * (at your option) any later version. + * + * EasyRPG Player 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 EasyRPG Player. If not, see . + */ + +#ifndef EP_DESTINY_H +#define EP_DESTINY_H + +#include + + +namespace Destiny { + constexpr const char* DESTINY_DLL = "Destiny.dll"; + + void Load(); + void Initialize( + uint32_t _dllVersion, + uint32_t _language, + uint32_t _gameVersion, + uint32_t _extra, + uint32_t _dwordSize, + uint32_t _floatSize, + uint32_t _stringSize + ); +} + +#endif // !EP_DESTINY_H diff --git a/src/game_config_game.h b/src/game_config_game.h index 3064a2d3cb..9095ff6718 100644 --- a/src/game_config_game.h +++ b/src/game_config_game.h @@ -38,6 +38,7 @@ struct Game_ConfigGame { BoolConfigParam new_game{ "Start new game", "Skips the title screen and starts a new game directly", "Game", "NewGame", false }; StringConfigParam engine_str{ "Engine", "", "Game", "Engine", std::string() }; BoolConfigParam fake_resolution{ "Fake Metrics", "Makes games run on higher resolutions (with some success)", "Game", "FakeResolution", false }; + BoolConfigParam patch_destiny{ "Destiny Patch", "", "Patch", "Destiny", false }; BoolConfigParam patch_dynrpg{ "DynRPG", "", "Patch", "DynRPG", false }; BoolConfigParam patch_maniac{ "Maniac Patch", "", "Patch", "Maniac", false }; BoolConfigParam patch_common_this_event{ "Common This Event", "Support \"This Event\" in Common Events", "Patch", "CommonThisEvent", false }; diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index 0b61a59070..823584c77b 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -26,6 +26,7 @@ #include #include "game_interpreter.h" #include "audio.h" +#include "destiny.h" #include "dynrpg.h" #include "filefinder.h" #include "game_map.h" diff --git a/src/player.cpp b/src/player.cpp index 75a8bfd042..1cd04335f8 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -38,6 +38,7 @@ #include "cache.h" #include "rand.h" #include "cmdline_parser.h" +#include "destiny.h" #include "dynrpg.h" #include "filefinder.h" #include "filefinder_rtp.h" @@ -832,10 +833,14 @@ void Player::CreateGameObjects() { if (!FileFinder::Game().FindFile("accord.dll").empty()) { game_config.patch_maniac.Set(true); } + + if (!FileFinder::Game().FindFile(Destiny::DESTINY_DLL).empty()) { + game_config.patch_destiny.Set(true); + } } - Output::Debug("Patch configuration: dynrpg={} maniac={} key-patch={} common-this={} pic-unlock={} 2k3-commands={}", - Player::IsPatchDynRpg(), Player::IsPatchManiac(), Player::IsPatchKeyPatch(), game_config.patch_common_this_event.Get(), game_config.patch_unlock_pics.Get(), game_config.patch_rpg2k3_commands.Get()); + Output::Debug("Patch configuration: dynrpg={} maniac={} key-patch={} common-this={} pic-unlock={} 2k3-commands={} destiny={}", + Player::IsPatchDynRpg(), Player::IsPatchManiac(), Player::IsPatchKeyPatch(), game_config.patch_common_this_event.Get(), game_config.patch_unlock_pics.Get(), game_config.patch_rpg2k3_commands.Get(), Player::IsPatchDestiny()); ResetGameObjects(); @@ -844,6 +849,10 @@ void Player::CreateGameObjects() { if (Player::IsPatchKeyPatch()) { Main_Data::game_ineluki->ExecuteScriptList(FileFinder::Game().FindFile("autorun.script")); } + + if (Player::IsPatchDestiny()) { + Destiny::Load(); + } } bool Player::ChangeResolution(int width, int height) { diff --git a/src/player.h b/src/player.h index 86d0ccff2d..38d413d71d 100644 --- a/src/player.h +++ b/src/player.h @@ -292,6 +292,11 @@ namespace Player { */ bool IsPatchKeyPatch(); + /** + * @return True when Destiny Patch is active + */ + bool IsPatchDestiny(); + /** * @return Running engine version. 2000 for RPG2k and 2003 for RPG2k3 */ @@ -480,4 +485,8 @@ inline bool Player::IsPatchKeyPatch() { return game_config.patch_key_patch.Get(); } +inline bool Player::IsPatchDestiny() { + return game_config.patch_destiny.Get(); +} + #endif From 401582db55c4d04acf3a7584cf686aa4b8ba23ad Mon Sep 17 00:00:00 2001 From: drxgb Date: Tue, 24 Oct 2023 22:59:12 -0300 Subject: [PATCH 2/9] Make DestinyScript command --- src/destiny.cpp | 77 ++++++++++++++++++++++++++++++++----------------- src/destiny.h | 62 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 111 insertions(+), 28 deletions(-) diff --git a/src/destiny.cpp b/src/destiny.cpp index 1747303d48..eb2731f802 100644 --- a/src/destiny.cpp +++ b/src/destiny.cpp @@ -18,7 +18,6 @@ // Headers #include "destiny.h" -#include #include #ifndef EMSCRIPTEN @@ -27,6 +26,9 @@ #include "output.h" +using lcf::ToString; +using lcf::rpg::EventCommand; + // Definitions using destiny_dword_list = std::vector; @@ -35,30 +37,6 @@ using destiny_string_list = std::vector; namespace Destiny { - enum Language { - DEUTSCH = 0, - ENGLISH, - }; - - struct Version { - uint16_t major; - uint16_t minor; - - Version() - : major(0), minor(0) {} - Version(uint32_t version) { - major = version >> 0x10; - minor = version & 0xFFFF; - } - - std::string toString() { - std::stringstream ss; - - ss << major << '.' << minor; - return ss.str(); - } - }; - // Destiny containers static destiny_dword_list dwords; static destiny_float_list floats; @@ -69,6 +47,9 @@ namespace Destiny { static Version gameVersion; static Language language; static uint32_t extra; + + // Settings + static bool decimalComma; } @@ -108,7 +89,7 @@ void Destiny::Load() exe.seekg(1, std::ios_base::cur); } #else - // TODO [Dr.XGB]: Find to manage Destiny initialization parameters on emscripten + // TODO [Dr.XGB]: Find to manage Destiny initialization parameters on Emscripten dllVersion = 0x20000; language = ENGLISH; gameVersion = 0x20000107; @@ -123,15 +104,57 @@ void Destiny::Initialize(uint32_t _dllVersion, uint32_t _language, uint32_t _gam { dllVersion = Version(_dllVersion); gameVersion = Version(_gameVersion); - language = (Language)_language; + language = static_cast(_language); extra = _extra; + decimalComma = language == ENGLISH; + + // Init containers dwords.resize(_dwordSize); floats.resize(_floatSize); strings.resize(_stringSize); + // TODO: Init File container + // TODO: Init ClientSocket container + + // Debug Output::Debug("Destiny Initialized"); + Output::Debug("Language: {}", decimalComma ? "English" : "Deutsch"); Output::Debug("DLL Version: {}", dllVersion.toString()); Output::Debug("Dwords: {}", _dwordSize); Output::Debug("Floats: {}", _floatSize); Output::Debug("Strings: {}", _stringSize); } + +void Destiny::Terminate() +{ + dwords.clear(); + floats.clear(); + strings.clear(); + + // TODO: Clear File container + // TODO: Clear ClientSocket container +} + +std::string Destiny::MakeString(lcf::rpg::SaveEventExecFrame& scriptData) +{ + std::string code; + + int32_t& current = scriptData.current_command; + const std::vector& cmdList = scriptData.commands; + std::vector::const_iterator it = cmdList.begin() + current++; + + code = ToString((*it++).string); + while (it != cmdList.cend() && it->code == static_cast(EventCommand::Code::Comment_2)) { + code += '\n'; + code += ToString((*it++).string); + ++current; + } + + return code; +} + +bool Destiny::Interpret(const std::string& code) +{ + // TODO [Dr.XGB]: DestinyScript Interpret + return true; +} diff --git a/src/destiny.h b/src/destiny.h index 046fbd17b1..d516b84dd0 100644 --- a/src/destiny.h +++ b/src/destiny.h @@ -19,12 +19,53 @@ #define EP_DESTINY_H #include +#include + +#include "lcf/rpg/saveeventexecframe.h" namespace Destiny { + // Constants constexpr const char* DESTINY_DLL = "Destiny.dll"; + + // Enums + enum Language { + DEUTSCH = 0, + ENGLISH, + }; + + + // Structs + struct Version { + uint16_t major; + uint16_t minor; + + Version() + : major(0), minor(0) {} + Version(uint32_t version) { + major = version >> 0x10; + minor = version & 0xFFFF; + } + + std::string toString() { + std::stringstream ss; + + ss << major << '.' << minor; + return ss.str(); + } + }; + + + // Functions + /** + * Load the Destiny module + */ void Load(); + + /** + * Initialize and apply the patch to the game interpreter + */ void Initialize( uint32_t _dllVersion, uint32_t _language, @@ -34,6 +75,25 @@ namespace Destiny { uint32_t _floatSize, uint32_t _stringSize ); -} + /** + * Clear Destiny patch before close + */ + void Terminate(); + + + // Interpret functions + + /* + * Make the DestinyScript code exctracting from the event script's comment command + */ + std::string MakeString(lcf::rpg::SaveEventExecFrame& scriptData); + + + /* + * Evaluate DestinyScript code + */ + bool Interpret(const std::string& code); + +} #endif // !EP_DESTINY_H From 9695f59a80c1451b65d1fc78a623bf89d603f4eb Mon Sep 17 00:00:00 2001 From: drxgb Date: Tue, 24 Oct 2023 22:59:52 -0300 Subject: [PATCH 3/9] Call Destiny Interpreter by comment event command --- src/game_interpreter.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index 823584c77b..e049d0db80 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -2094,6 +2094,7 @@ bool Game_Interpreter::CommandEndEventProcessing(lcf::rpg::EventCommand const& / } bool Game_Interpreter::CommandComment(const lcf::rpg::EventCommand &com) { + // DynRpg command if (Player::IsPatchDynRpg()) { if (com.string.empty() || com.string[0] != '@') { // Not a DynRPG command @@ -2118,6 +2119,20 @@ bool Game_Interpreter::CommandComment(const lcf::rpg::EventCommand &com) { return DynRpg::Invoke(command); } + + + // DestinyScript + if (Player::IsPatchDestiny()) { + if (com.string.empty() || com.string[0] != '$') { + // Not a DestinyScript + return true; + } + + const std::string& code = Destiny::MakeString(GetFrame()); + Output::Debug("DestinyScript Code:\n{}", code); + return Destiny::Interpret(code); + } + return true; } From 7e23f12ca7ac6cc6f3078defa3fac0da829368aa Mon Sep 17 00:00:00 2001 From: drxgb Date: Wed, 25 Oct 2023 22:08:58 -0300 Subject: [PATCH 4/9] Destiny: OOP approach --- src/{destiny.cpp => game_destiny.cpp} | 95 +++++++++++++-------------- src/{destiny.h => game_destiny.h} | 78 +++++++++++++++++----- src/game_interpreter.cpp | 6 +- src/player.cpp | 7 +- 4 files changed, 114 insertions(+), 72 deletions(-) rename src/{destiny.cpp => game_destiny.cpp} (67%) rename src/{destiny.h => game_destiny.h} (53%) diff --git a/src/destiny.cpp b/src/game_destiny.cpp similarity index 67% rename from src/destiny.cpp rename to src/game_destiny.cpp index eb2731f802..61192c4008 100644 --- a/src/destiny.cpp +++ b/src/game_destiny.cpp @@ -16,9 +16,7 @@ */ // Headers -#include "destiny.h" - -#include +#include "game_destiny.h" #ifndef EMSCRIPTEN #include "exe_reader.h" @@ -30,31 +28,11 @@ using lcf::ToString; using lcf::rpg::EventCommand; -// Definitions -using destiny_dword_list = std::vector; -using destiny_float_list = std::vector; -using destiny_string_list = std::vector; - - -namespace Destiny { - // Destiny containers - static destiny_dword_list dwords; - static destiny_float_list floats; - static destiny_string_list strings; - - // Destiny data - static Version dllVersion; - static Version gameVersion; - static Language language; - static uint32_t extra; - - // Settings - static bool decimalComma; -} - +// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// Game_Destiny implementations +// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// Implementations -void Destiny::Load() +void Game_Destiny::Load() { // Do not load Destiny whether player cannot find "Destiny.dll" if (!FileFinder::Game().Exists(DESTINY_DLL)) @@ -100,42 +78,63 @@ void Destiny::Load() Initialize(dllVersion, language, gameVersion, extra, dwordSize, floatSize, stringSize); } -void Destiny::Initialize(uint32_t _dllVersion, uint32_t _language, uint32_t _gameVersion, uint32_t _extra, uint32_t _dwordSize, uint32_t _floatSize, uint32_t _stringSize) +Game_Destiny::Game_Destiny() +{ + _dllVersion = {}; + _gameVersion = {}; + _language = Destiny::Language::DEUTSCH; + _extra = 0U; + _decimalComma = false; +} + +Game_Destiny::~Game_Destiny() +{ + Terminate(); +} + +void Game_Destiny::Initialize( + uint32_t dllVersion, + uint32_t language, + uint32_t gameVersion, + uint32_t extra, + uint32_t dwordSize, + uint32_t floatSize, + uint32_t stringSize) { - dllVersion = Version(_dllVersion); - gameVersion = Version(_gameVersion); - language = static_cast(_language); - extra = _extra; - decimalComma = language == ENGLISH; + _dllVersion = Destiny::Version(dllVersion); + _gameVersion = Destiny::Version(gameVersion); + _language = static_cast(language); + _extra = extra; + _decimalComma = _language == Destiny::Language::ENGLISH; // Init containers - dwords.resize(_dwordSize); - floats.resize(_floatSize); - strings.resize(_stringSize); + _dwords.resize(dwordSize); + _floats.resize(floatSize); + _strings.resize(stringSize); // TODO: Init File container // TODO: Init ClientSocket container // Debug Output::Debug("Destiny Initialized"); - Output::Debug("Language: {}", decimalComma ? "English" : "Deutsch"); - Output::Debug("DLL Version: {}", dllVersion.toString()); - Output::Debug("Dwords: {}", _dwordSize); - Output::Debug("Floats: {}", _floatSize); - Output::Debug("Strings: {}", _stringSize); + Output::Debug("Language: {}", _decimalComma ? "English" : "Deutsch"); + Output::Debug("DLL Version: {}", _dllVersion.toString()); + Output::Debug("Dwords: {}", dwordSize); + Output::Debug("Floats: {}", floatSize); + Output::Debug("Strings: {}", stringSize); } -void Destiny::Terminate() +void Game_Destiny::Terminate() { - dwords.clear(); - floats.clear(); - strings.clear(); + _dwords.clear(); + _floats.clear(); + _strings.clear(); // TODO: Clear File container // TODO: Clear ClientSocket container } -std::string Destiny::MakeString(lcf::rpg::SaveEventExecFrame& scriptData) +std::string Game_Destiny::MakeString(lcf::rpg::SaveEventExecFrame& scriptData) { std::string code; @@ -143,7 +142,7 @@ std::string Destiny::MakeString(lcf::rpg::SaveEventExecFrame& scriptData) const std::vector& cmdList = scriptData.commands; std::vector::const_iterator it = cmdList.begin() + current++; - code = ToString((*it++).string); + code = ToString((*it++).string).substr(1); while (it != cmdList.cend() && it->code == static_cast(EventCommand::Code::Comment_2)) { code += '\n'; code += ToString((*it++).string); @@ -153,7 +152,7 @@ std::string Destiny::MakeString(lcf::rpg::SaveEventExecFrame& scriptData) return code; } -bool Destiny::Interpret(const std::string& code) +bool Game_Destiny::Interpret(const std::string& code) { // TODO [Dr.XGB]: DestinyScript Interpret return true; diff --git a/src/destiny.h b/src/game_destiny.h similarity index 53% rename from src/destiny.h rename to src/game_destiny.h index d516b84dd0..055820aaf8 100644 --- a/src/destiny.h +++ b/src/game_destiny.h @@ -15,20 +15,21 @@ * along with EasyRPG Player. If not, see . */ -#ifndef EP_DESTINY_H -#define EP_DESTINY_H +#ifndef EP_GAME_DESTINY_H +#define EP_GAME_DESTINY_H #include #include +#include #include "lcf/rpg/saveeventexecframe.h" -namespace Destiny { - // Constants - constexpr const char* DESTINY_DLL = "Destiny.dll"; +// Constants +constexpr const char* DESTINY_DLL = "Destiny.dll"; +namespace Destiny { // Enums enum Language { DEUTSCH = 0, @@ -55,25 +56,45 @@ namespace Destiny { return ss.str(); } }; +} + + +/** + * The Destiny Patch class + */ +class Game_Destiny { +public: + // ctor and dtor + Game_Destiny(); + ~Game_Destiny(); +public: + // Member functions - // Functions /** - * Load the Destiny module + * Load the Destiny Patch */ void Load(); /** * Initialize and apply the patch to the game interpreter + * + * @param dllVersion The Destiny.dll version + * @param language The DLL language. Usually for displaying errors and for decimal format. + * @param gameVersion The RPG_RT version + * @param extra Extra flags + * @param dwordSize Length of dowrd container + * @param floatSize Length of float container + * @param stringSize Length of string container */ void Initialize( - uint32_t _dllVersion, - uint32_t _language, - uint32_t _gameVersion, - uint32_t _extra, - uint32_t _dwordSize, - uint32_t _floatSize, - uint32_t _stringSize + uint32_t dllVersion, + uint32_t language, + uint32_t gameVersion, + uint32_t extra, + uint32_t dwordSize, + uint32_t floatSize, + uint32_t stringSize ); /** @@ -82,18 +103,39 @@ namespace Destiny { void Terminate(); - // Interpret functions - /* * Make the DestinyScript code exctracting from the event script's comment command + * + * @param scriptData The event script data + * @return A full DestinyScript code extracted from the comment event command */ std::string MakeString(lcf::rpg::SaveEventExecFrame& scriptData); /* * Evaluate DestinyScript code + * + * @param code The DestinyScript code to evaluate + * @return Whether evaluation is successful */ bool Interpret(const std::string& code); -} -#endif // !EP_DESTINY_H + +private: + // Member data + + // Destiny containers + std::vector _dwords; + std::vector _floats; + std::vector _strings; + + // Destiny data + Destiny::Version _dllVersion; + Destiny::Version _gameVersion; + Destiny::Language _language; + uint32_t _extra; + + // Settings + bool _decimalComma; +}; +#endif // !EP_GAME_DESTINY_H diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index e049d0db80..4deccd0030 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -26,9 +26,9 @@ #include #include "game_interpreter.h" #include "audio.h" -#include "destiny.h" #include "dynrpg.h" #include "filefinder.h" +#include "game_destiny.h" #include "game_map.h" #include "game_event.h" #include "game_enemyparty.h" @@ -2128,9 +2128,9 @@ bool Game_Interpreter::CommandComment(const lcf::rpg::EventCommand &com) { return true; } - const std::string& code = Destiny::MakeString(GetFrame()); + const std::string& code = Main_Data::game_destiny->MakeString(GetFrame()); Output::Debug("DestinyScript Code:\n{}", code); - return Destiny::Interpret(code); + return Main_Data::game_destiny->Interpret(code); } return true; diff --git a/src/player.cpp b/src/player.cpp index 1cd04335f8..cb57cac2cb 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -38,13 +38,13 @@ #include "cache.h" #include "rand.h" #include "cmdline_parser.h" -#include "destiny.h" #include "dynrpg.h" #include "filefinder.h" #include "filefinder_rtp.h" #include "fileext_guesser.h" #include "game_actors.h" #include "game_battle.h" +#include "game_destiny.h" #include "game_map.h" #include "game_message.h" #include "game_enemyparty.h" @@ -834,7 +834,7 @@ void Player::CreateGameObjects() { game_config.patch_maniac.Set(true); } - if (!FileFinder::Game().FindFile(Destiny::DESTINY_DLL).empty()) { + if (!FileFinder::Game().FindFile(DESTINY_DLL).empty()) { game_config.patch_destiny.Set(true); } } @@ -851,7 +851,7 @@ void Player::CreateGameObjects() { } if (Player::IsPatchDestiny()) { - Destiny::Load(); + Main_Data::game_destiny->Load(); } } @@ -935,6 +935,7 @@ void Player::ResetGameObjects() { Main_Data::game_switches_global = std::make_unique(); Main_Data::game_variables_global = std::make_unique(min_var, max_var); Main_Data::game_ineluki = std::make_unique(); + Main_Data::game_destiny = std::make_unique(); DynRpg::Reset(); From b59b5a750da6307478e957cc7111c1d398a256cc Mon Sep 17 00:00:00 2001 From: drxgb Date: Wed, 25 Oct 2023 22:09:25 -0300 Subject: [PATCH 5/9] Include Game_Destiny instance to main_data --- src/main_data.cpp | 3 +++ src/main_data.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/main_data.cpp b/src/main_data.cpp index 8a57dd79ff..be4cc087a5 100644 --- a/src/main_data.cpp +++ b/src/main_data.cpp @@ -21,6 +21,7 @@ #include "filefinder.h" #include "filefinder_rtp.h" #include "filesystem.h" +#include "game_destiny.h" #include "game_system.h" #include "game_actors.h" #include "game_party.h" @@ -71,6 +72,7 @@ namespace Main_Data { std::unique_ptr game_targets; std::unique_ptr game_quit; std::unique_ptr game_ineluki; + std::unique_ptr game_destiny; std::unique_ptr game_switches_global; std::unique_ptr game_variables_global; @@ -125,6 +127,7 @@ void Main_Data::Cleanup() { game_quit.reset(); game_system.reset(); game_ineluki.reset(); + game_destiny.reset(); } const std::string& Main_Data::GetDefaultProjectPath() { diff --git a/src/main_data.h b/src/main_data.h index e2d199eb96..086ecd3a37 100644 --- a/src/main_data.h +++ b/src/main_data.h @@ -40,6 +40,7 @@ class Game_Strings; class Game_Targets; class Game_Quit; class Game_Ineluki; +class Game_Destiny; class FileFinder_RTP; namespace Main_Data { @@ -58,6 +59,7 @@ namespace Main_Data { extern std::unique_ptr game_targets; extern std::unique_ptr game_quit; extern std::unique_ptr game_ineluki; + extern std::unique_ptr game_destiny; extern std::unique_ptr game_switches_global; // Used by Global Save command extern std::unique_ptr game_variables_global; From c6c1f56494a1eeabc334cfb55ee23d2f12c41b41 Mon Sep 17 00:00:00 2001 From: drxgb Date: Wed, 25 Oct 2023 22:09:52 -0300 Subject: [PATCH 6/9] Add game_destiny.h/cpp to CMake --- CMakeLists.txt | 2 ++ Makefile.am | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index edb60d5de5..9579edb261 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,6 +158,8 @@ add_library(${PROJECT_NAME} OBJECT src/game_config.h src/game_config_game.cpp src/game_config_game.h + src/game_destiny.cpp + src/game_destiny.h src/game_enemy.cpp src/game_enemy.h src/game_enemyparty.cpp diff --git a/Makefile.am b/Makefile.am index 2c2c339015..c976b5f70b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -139,6 +139,8 @@ libeasyrpg_player_a_SOURCES = \ src/game_config.h \ src/game_config_game.cpp \ src/game_config_game.h \ + src/game_destiny.cpp \ + src/game_destiny.h \ src/game_enemy.cpp \ src/game_enemy.h \ src/game_enemyparty.cpp \ From c677c7091e5eaa52048078412ccfcbf1b750087b Mon Sep 17 00:00:00 2001 From: drxgb Date: Mon, 11 Nov 2024 08:39:41 -0300 Subject: [PATCH 7/9] Destiny: Issues corrected based on the new EasyRpg changes. --- src/game_config_game.cpp | 1 + src/game_destiny.cpp | 18 +++++------------- src/game_destiny.h | 9 +++++++-- src/player.cpp | 2 -- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/game_config_game.cpp b/src/game_config_game.cpp index 9cb133e4af..4a719b5556 100644 --- a/src/game_config_game.cpp +++ b/src/game_config_game.cpp @@ -241,6 +241,7 @@ void Game_ConfigGame::PrintActivePatches() { }; add_bool(patch_easyrpg); + add_bool(patch_destiny); add_bool(patch_dynrpg); add_bool(patch_common_this_event); add_bool(patch_unlock_pics); diff --git a/src/game_destiny.cpp b/src/game_destiny.cpp index de4fb24b18..8a79019d66 100644 --- a/src/game_destiny.cpp +++ b/src/game_destiny.cpp @@ -17,7 +17,6 @@ // Headers #include "game_destiny.h" -#include #ifndef EMSCRIPTEN #include "exe_reader.h" @@ -210,15 +209,12 @@ void Game_Destiny::CheckVersionInfo() Interpreter::Interpreter() { CleanUpData(); - _destinyScript = nullptr; _scriptPtr = nullptr; } const char* Interpreter::MakeString(SaveEventExecFrame& frame) { std::string code; - size_t length; - char* destinyScript; int32_t& current = frame.current_command; const std::vector& cmdList = frame.commands; @@ -233,18 +229,14 @@ const char* Interpreter::MakeString(SaveEventExecFrame& frame) ++current; } - length = code.length() + 1; - destinyScript = new char[length]; - strcpy_s(destinyScript, length, code.c_str()); - - return _destinyScript = _scriptPtr = destinyScript; + _destinyScript = code; + return _scriptPtr = _destinyScript.data(); } void Interpreter::FreeString() { - delete[] _destinyScript; - _destinyScript = nullptr; - _scriptPtr = nullptr; + _destinyScript = ""; + _scriptPtr = _destinyScript.data(); } void Interpreter::SkipWhiteSpace() @@ -270,7 +262,7 @@ const size_t Interpreter::GetWordLen() const InterpretFlag Interpreter::Interpret() { char* code; - uint8_t flags[4]; + //uint8_t flags[4]; InterpretFlag returnType; size_t wordLen; diff --git a/src/game_destiny.h b/src/game_destiny.h index 2692d65f3f..341494bd86 100644 --- a/src/game_destiny.h +++ b/src/game_destiny.h @@ -304,7 +304,7 @@ namespace Destiny private: // Member data - char* _destinyScript; + std::string _destinyScript; char* _scriptPtr; uint32_t _breaks; uint32_t _continues; @@ -335,7 +335,7 @@ namespace Destiny const bool BlockComment(); /** - * Check whether character is a whitespace.. + * Check whether character is a whitespace. * * @return Flag of whitespace character. */ @@ -348,6 +348,11 @@ namespace Destiny ch == 0x0B; // Vertical Tabulator (VT) } + /** + * Check whether character is a part of a word. + * + * @return Flag of word character. + */ inline const bool IsWordChar(const char ch) const { return ch == '_' || diff --git a/src/player.cpp b/src/player.cpp index 60d8e6ee86..494f09a052 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -833,8 +833,6 @@ void Player::CreateGameObjects() { } } - Output::Debug("Patch configuration: dynrpg={} maniac={} key-patch={} common-this={} pic-unlock={} 2k3-commands={} destiny={}", - Player::IsPatchDynRpg(), Player::IsPatchManiac(), Player::IsPatchKeyPatch(), game_config.patch_common_this_event.Get(), game_config.patch_unlock_pics.Get(), game_config.patch_rpg2k3_commands.Get(), Player::IsPatchDestiny()); game_config.PrintActivePatches(); ResetGameObjects(); From b4285ea31888dcb3b1bfa3e15e283a0a38e91356 Mon Sep 17 00:00:00 2001 From: drxgb Date: Mon, 11 Nov 2024 21:57:40 -0300 Subject: [PATCH 8/9] Destiny: Test cases added --- Makefile.am | 1 + src/game_destiny.h | 13 +++++++++ tests/game_destiny.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 tests/game_destiny.cpp diff --git a/Makefile.am b/Makefile.am index e2f3d7064e..28b8b8e006 100644 --- a/Makefile.am +++ b/Makefile.am @@ -738,6 +738,7 @@ test_runner_SOURCES = \ tests/game_character_flash.cpp \ tests/game_character_move.cpp \ tests/game_character_moveto.cpp \ + tests/game_destiny.cpp \ tests/game_enemy.cpp \ tests/game_event.cpp \ tests/game_player_input.cpp \ diff --git a/src/game_destiny.h b/src/game_destiny.h index 341494bd86..b6cf5e5fad 100644 --- a/src/game_destiny.h +++ b/src/game_destiny.h @@ -425,6 +425,19 @@ class Game_Destiny */ bool Main(lcf::rpg::SaveEventExecFrame& frame); + + // Inline functions + + /** + * Retrieves the Destiny interpreter. + * + * @returns The Destiny interpreter. + */ + inline Destiny::MainFunctions::Interpreter& Interpreter() + { + return _interpreter; + } + private: // Member data diff --git a/tests/game_destiny.cpp b/tests/game_destiny.cpp new file mode 100644 index 0000000000..550c817108 --- /dev/null +++ b/tests/game_destiny.cpp @@ -0,0 +1,66 @@ +#include "doctest.h" +#include "game_destiny.h" +#include + + +TEST_SUITE_BEGIN("Game_Destiny"); + + +static const lcf::rpg::EventCommand* MakeCommand( + const lcf::rpg::EventCommand::Code code, + const std::string& string +) +{ + lcf::rpg::EventCommand* cmd = new lcf::rpg::EventCommand; + lcf::DBString dbStr(string); + + cmd->code = static_cast(code); + cmd->string = dbStr; + + return cmd; +} + +static lcf::rpg::SaveEventExecFrame* MakeFrame( + std::vector::const_iterator begin, + std::vector::const_iterator end +) +{ + lcf::rpg::SaveEventExecFrame* frame = new lcf::rpg::SaveEventExecFrame; + lcf::rpg::EventCommand::Code code; + + code = lcf::rpg::EventCommand::Code::Comment; + + while (begin != end) + { + const std::string& str = *begin++; + + frame->commands.push_back(*MakeCommand(code, str)); + code = lcf::rpg::EventCommand::Code::Comment_2; + } + + return frame; +} + + +TEST_CASE("AssertDestinyScript") +{ + Game_Destiny destiny; + std::vector lines { + "$", + "v[1] = 10;", + }; + lcf::rpg::SaveEventExecFrame* frame; + const char* destinyScript; + + frame = MakeFrame(lines.begin(), lines.end()); + destinyScript = destiny.Interpreter().MakeString(*frame); + + CHECK_EQ(*destinyScript, '$'); + + destiny.Interpreter().FreeString(); + delete frame; + frame = nullptr; +} + + +TEST_SUITE_END(); From c079b72b0518814388367c1ac9d20ecc6431702a Mon Sep 17 00:00:00 2001 From: "Dr.XGB" <53436553+drxgb@users.noreply.github.com> Date: Mon, 18 Nov 2024 14:26:11 -0300 Subject: [PATCH 9/9] Destiny: Include filefinder.h to work on emscripten --- src/game_destiny.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game_destiny.cpp b/src/game_destiny.cpp index 8a79019d66..268c459d67 100644 --- a/src/game_destiny.cpp +++ b/src/game_destiny.cpp @@ -17,6 +17,7 @@ // Headers #include "game_destiny.h" +#include "filefinder.h" #ifndef EMSCRIPTEN #include "exe_reader.h" @@ -75,7 +76,7 @@ void Game_Destiny::Load() #else // TODO [XGB]: Find to manage Destiny initialization parameters on Emscripten dllVersion = 0x20000; - language = ENGLISH; + language = Destiny::Language::ENGLISH; gameVersion = 0x20000107; extra = 0x01; dwordSize = floatSize = stringSize = 0x64;