-
Notifications
You must be signed in to change notification settings - Fork 198
Engine detection: Patched RPG_RT constants / strings / PatchDetection / WhiteDragon patch compatibility #3352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
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.
…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
c3ec786
to
728e3f3
Compare
This work could be also useful for some kind of patch detection tool inside the Tools repo |
Yup, I also thought about that. |
…PS Patches + QuickPatches (DynRPG compatibility)
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
|
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 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?