-
Notifications
You must be signed in to change notification settings - Fork 221
Comments
Engine detection: Patched RPG_RT constants / strings / PatchDetection / WhiteDragon patch compatibility#3352
Draft
florianessl wants to merge 27 commits intoEasyRPG:master from
Draft
Engine detection: Patched RPG_RT constants / strings / PatchDetection / WhiteDragon patch compatibility #3352florianessl wants to merge 27 commits intoEasyRPG:master from
florianessl wants to merge 27 commits intoEasyRPG:master from
Conversation
...mespace "Player::Constants"
... Rm2k3 & implemented some of the limits of this particular patch
...o be able to possibly read out patched game constants from known engine versions
...ng of patch overrides & implement patch detection for custom title screen positions in rm2k3 v1.08
...ch is to be used by the engine detection (EasyRPG#3166)
...only encountered engine versions (DonM 1.03b/1.05b/1.06, Advo 1.04/1.06/1.08)
- Structured code to make it easier to manage - Made the code maps constexpr - Added code addresses for Min/Max Variable limits - Added some additional debug output
... to mismatch of ref variable.
@github-actions
github-actions
bot
added
Window/Scenes
Building
Battle
Tests
Settings
All about customizable features, storing and applying them
labels
Feb 19, 2025
...ck to automatically apply the known patch config for WhiteDragon patch (EasyRPG#3292)
...ctually just another reskin of an offical VALUE! update)
...; Implemented constant reading for 1.08 constants "MaxItemCount" & "MaxSaveFiles" (8 bit)
- Properly inlined declaration of constants without much code overhead - Relocation of build-related info into a new file "exe_buildinfo.h" - Relocation of patch-related info into "exe_shared.h"
... extraction out of Player::CreateGameObjects() & into a new function "Player::DetectEngine"
...patches: - UnlockPics, CommonThisEvent, DirectMenuPatch (Fully supported via this detection) - BreakLoopFix (Was previously only part of "ManiacPatch", but can now be detected & applied via ExeReader) - AutoEnterPatch/BetterAEP (Just for support of the "NewGame" option; extended functionality remains unimplemented!) - PicPointer 2.5b / PicPointer Restruct (Detection only - this patch is still enabled by default)
...RPG_RT builds. (DRAFT: rm2k 1.51 Value!) - EasyRPG#3027
@florianessl
florianessl
force-pushed
the
compat/PlayerLimits
branch
from
February 25, 2025 17:47
c3ec786 to
728e3f3
Compare
Member
Ghabry
commented
Feb 25, 2025
This work could be also useful for some kind of patch detection tool inside the Tools repo
@florianessl
florianessl
changed the title
(削除) Extracting patched constants from RPG_RT / WhiteDragon patch compatibility (削除ここまで)
(追記) Engine detection: Patched RPG_RT constants / strings / PatchDetection / WhiteDragon patch compatibility (追記ここまで)
Feb 25, 2025
Member
Author
florianessl
commented
Feb 25, 2025
This work could be also useful for some kind of patch detection tool inside the Tools repo
Yup, I also thought about that.
It would be nice to have a tool that extracts all the information about RPG_RT/build-related customizations + packages them into its own file format that can be used by the web player. (Which would otherwise be unable to use the ExeReader)
...PS Patches + QuickPatches (DynRPG compatibility)
Member
Author
florianessl
commented
Feb 27, 2025
oops, the last commit is missing some changes for liblcf. Here's a "quick patch" (get it?):
--- src/inireader.cpp | 17 +++++++++++++++++ src/lcf/inireader.h | 2 ++ 2 files changed, 19 insertions(+) diff --git a/src/inireader.cpp b/src/inireader.cpp index 6222ae2..679559d 100644 --- a/src/inireader.cpp +++ b/src/inireader.cpp @@ -151,6 +151,23 @@ bool INIReader::HasValue(const std::string& section, const std::string& name) co return _values.count(key); } + +std::map<std::string, std::string> INIReader::GetSection(const std::string& section) const { + std::map<std::string, std::string> result; + + std::string section_lc = section; + std::transform(section_lc.begin(), section_lc.end(), section_lc.begin(), ::tolower); + + for (auto it = _values.begin(); it != _values.end(); ++it) { + auto& key = it->first; + if (key.size() > section_lc.size() + 2 && key.rfind(section_lc, 0) == 0 && key[section_lc.size()] == '=') { + auto name = key.substr(section_lc.size() + 1); + result[name] = it->second; + } + } + return result; +} + std::string INIReader::MakeKey(const std::string& section, const std::string& name) { std::string key = section + "=" + name; diff --git a/src/lcf/inireader.h b/src/lcf/inireader.h index e3d62a8..980b278 100644 --- a/src/lcf/inireader.h +++ b/src/lcf/inireader.h @@ -81,6 +81,8 @@ public: // Return true if a value exists with the given section and field names. bool HasValue(const std::string& section, const std::string& name) const; + std::map<std::string, std::string> GetSection(const std::string& section) const; + private: int _error; std::map<std::string, std::string> _values; -- 2.47.1.windows.2
Member
Ghabry
commented
Feb 27, 2025
If you want you can PR the liblcf part. Could be also useful for other applications.
- forgot to validate segment data for patches to rule out false positives - read_int32 had wrong return type - skip on liblcf's IniReader
... engines than just RPG2003 v1.08
... variables & constants
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR moves some of the commonly patched constant values inside a new namespace "Player::Constants" and adds a new mechanism to the ExeReader, which tries to extract these from several known RPG_RT versions.
The validity of the values is verified by checking some of the previous bytes in the .CODE segment, whenever the reader is trying to extract a constant value from a known Hex location.
Because many of the disassembled code segments look very similar across versions, it should prove quite easy to determine the exact code locations for other RPG_RT versions.
Starting the Player with custom runtime versions
To make it easier to test this feature, I also implemented a new command argument "--engine-path" (See Issue #3166 )
Usage:
Player.exe --test-play --engine-path RT_rm2k3_advo_108_en.dat(At least for the way I organized my different RPG_RT versions. Supply any path to a custom .EXE here)
Constants supported in this DRAFT:
Versions of RPG_RT supported:
Constant values extracted:
Documentation used for this feature:
Observations regarding the battle stats:
These took some effort to debug & extract, and all of the code locations should definitely be verified by some other person who has more experience in the inner workings of the battle system.
At the moment, battle-related constant locations are only supplied for rm2k3 v1.08 .
Battle Stat Split
Even though they all share the same value, RPG_RT has different constant locations for the base stats: Atk, Def, Agi, Spi.
Thus they can be individually patched. Tools like "RM Limit Changer" make it even possible to change these values individually.
So I decided to split the Player constants for "MaxBaseStatValue" & "MaxBattleStatValue" into those 4 types each.
But: If I understood the disassembly correctly, the code which would be responsible for calculating skill effects uses a single constant location for all of these. So some battle-related calculations might differ in EasyRPG when these values are patched.
Inconsistent clamping of bounds
When applying a modifier to a base stat ("SetBaseAtk", etc.. in EasyRPG code), the resulting value is clamped between -999 & 999. EasyRPG ́s code uses a single value to represent both the lower & upper bounds of this operation.
But it might be possible for patches (And I verified this for the WhiteDragon patch) to omit patching one of these values. WhiteDragon only patches the positive values, so setting a new Atk value would actually clamp the modifier value between -999 & 9999 instead in RPG_RT. I chose not to extract the negative values individually, to make the result more correct. But there might be edge cases where calculations would differ from RPG_RT. :/
Max Enemy HP/SP just editor limitations?
I was looking for these values in my disassembly but wasn't able to find a candidate. Maybe these upper bounds should be removed from the Player code?
Rm2k3: CommandChangeClass actually uses the effective "Battle" stats instead of "Base" stats?
This might be one of countless bugs related to the Rm2k3 battle system. It looks like whenever a class is changed in RPG_RT, a constant of '9999' is used for clamping, instead of the proper '999' which would be used for base stats. I could be wrong, because I barely have any documentation on this mangled code, and the values used here might actually be the right ones (so that only the wrong upper bound is used here). Can anyone with more knowledge on the inner workings of the battle system verify that?