1616 */
1717
1818// All of this code is unused on EMSCRIPTEN. *Do not use it*!
19+
1920#ifndef EMSCRIPTEN
2021
2122#include " exe_reader.h"
2223#include " image_bmp.h"
2324#include " output.h"
24- #include " utils .h"
25+ #include " player .h"
2526#include < algorithm>
2627#include < iostream>
27- #include < fstream>
2828#include < zlib.h>
29+ #include < unordered_map>
2930
3031namespace {
3132 // hashes of known RPG_RT startup logos
@@ -122,6 +123,7 @@ EXEReader::EXEReader(Filesystem_Stream::InputStream core) : corefile(std::move(c
122123 uint32_t sectionsOfs = optional_header + GetU16 (ofs + 0x14 ); // skip opt header
123124 uint32_t data_directory_ofs = (format_pe32 ? 0x60 : 0x70 );
124125 resource_rva = GetU32 (optional_header + data_directory_ofs + 16 );
126+
125127 if (!resource_rva) {
126128 // Is some kind of encrypted EXE -> Give up
127129 return ;
@@ -138,6 +140,7 @@ EXEReader::EXEReader(Filesystem_Stream::InputStream core) : corefile(std::move(c
138140
139141 if (secName == 0x45444F43 ) { // CODE
140142 file_info.code_size = sectVs;
143+ file_info.code_ofs = GetU32 (sectionsOfs + 0x14 );
141144 } else if (secName == 0x52454843 ) { // CHER(RY)
142145 file_info.cherry_size = sectVs;
143146 } else if (secName == 0x50454547 ) { // GEEP
@@ -563,4 +566,52 @@ int EXEReader::FileInfo::GetEngineType(int& mp_version) const {
563566 return Player::EngineNone;
564567}
565568
569+ std::unordered_map<Game_Constants::ConstantType, int32_t > EXEReader::GetOverriddenGameConstants () {
570+ std::unordered_map<Game_Constants::ConstantType, int32_t > game_constants;
571+
572+ auto apply_known_config = [&](Game_Constants::KnownPatchConfigurations conf) {
573+ Output::Debug (" Assuming known patch config '{}'" , Game_Constants::kKnownPatchConfigurations .tag (static_cast <int >(conf)));
574+ auto it_conf = Game_Constants::known_patch_configurations.find (conf);
575+ assert (it_conf != Game_Constants::known_patch_configurations.end ());
576+
577+ for (auto it = it_conf->second .begin (); it != it_conf->second .end (); ++it) {
578+ game_constants[it->first ] = it->second ;
579+ }
580+ };
581+
582+ auto check_for_string = [&](uint32_t offset, const char * p) {
583+ while (*p) {
584+ if (GetU8 (offset++) != *p++)
585+ return false ;
586+ }
587+ return true ;
588+ };
589+
590+ switch (file_info.code_size ) {
591+ case 0x9CC00 : // RM2K 1.62
592+ if (check_for_string (file_info.code_ofs + 0x07DAA6 , " XXX" /* 3x "POP EAX" */ )) {
593+ apply_known_config (Game_Constants::KnownPatchConfigurations::StatDelimiter);
594+ }
595+ break ;
596+ case 0xC8E00 : // RM2K3 1.0.8.0
597+ // For all known Italian translations, the "WhiteDragon" patch seems to be the only one
598+ // to translate this string in RPG_RT. So this segment can be used to reliably detect
599+ // the patch without having to read all individual constant values from the EXE
600+ if (check_for_string (file_info.code_ofs + 0x08EBE0 , " NoTitolo" )) {
601+ apply_known_config (Game_Constants::KnownPatchConfigurations::Rm2k3_Italian_WD_108);
602+ }
603+ if (check_for_string (file_info.code_ofs + 0x09D279 , " XXX" /* 3x "POP EAX" */ )) {
604+ apply_known_config (Game_Constants::KnownPatchConfigurations::StatDelimiter);
605+ }
606+ break ;
607+ case 0xC9000 : // RM2K3 1.0.9.1
608+ if (check_for_string (file_info.code_ofs + 0x09C5AD , " XXX" /* 3x "POP EAX" */ )) {
609+ apply_known_config (Game_Constants::KnownPatchConfigurations::StatDelimiter);
610+ }
611+ break ;
612+ }
613+
614+ return game_constants;
615+ }
616+
566617#endif
0 commit comments