Skip to content

Commit 728e3f3

Browse files
committed
Started implementing detection of some template strings contained in RPG_RT builds. (DRAFT: rm2k 1.51 Value!) - #3027
1 parent e62c03f commit 728e3f3

11 files changed

Lines changed: 330 additions & 0 deletions

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ add_library(${PROJECT_NAME} OBJECT
113113
src/exe_constants.h
114114
src/exe_patches.h
115115
src/exe_shared.h
116+
src/exe_strings.h
116117
src/exe_reader.cpp
117118
src/exe_reader.h
118119
src/exfont.h

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ libeasyrpg_player_a_SOURCES = \
9393
src/exe_constants.h \
9494
src/exe_patches.h \
9595
src/exe_shared.h \
96+
src/exe_strings.h \
9697
src/exe_reader.cpp \
9798
src/exe_reader.h \
9899
src/exfont.h \

src/battle_message.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,15 @@ static std::string GetHpSpRecoveredMessage(const Game_Battler& target, int value
150150
Utils::MakeSvArray(target.GetName(), std::to_string(value), points)
151151
);
152152
}
153+
154+
StringView template_text;
155+
if (Player::Constants::HasEmbeddedTemplateString(EXE::Shared::EmbeddedStringTypes::Battle_HpSpRecovery, template_text)) {
156+
return Utils::ReplacePlaceholders(
157+
template_text,
158+
Utils::MakeArray('S', 'U', 'V', 'T'),
159+
Utils::MakeSvArray(target.GetName(), points, std::to_string(value), lcf::Data::terms.hp_recovery)
160+
);
161+
}
153162
std::stringstream ss;
154163
std::string particle, particle2, space = "";
155164

@@ -188,6 +197,20 @@ std::string GetParameterAbsorbedMessage(const Game_Battler& source, const Game_B
188197
Utils::MakeSvArray(source.GetName(), target.GetName(), std::to_string(value), points)
189198
);
190199
}
200+
201+
auto embedded_str_type = target_is_ally
202+
? EXE::Shared::EmbeddedStringTypes::Battle_AbsorbAlly
203+
: EXE::Shared::EmbeddedStringTypes::Battle_AbsorbEnemy;
204+
205+
StringView template_text;
206+
if (Player::Constants::HasEmbeddedTemplateString(embedded_str_type, template_text)) {
207+
return Utils::ReplacePlaceholders(
208+
template_text,
209+
Utils::MakeArray('O', 'U', 'V', 'T'),
210+
Utils::MakeSvArray(target.GetName(), points, std::to_string(value), message)
211+
);
212+
}
213+
191214
std::stringstream ss;
192215
std::string particle, particle2, space = "";
193216

@@ -243,6 +266,20 @@ std::string GetDamagedMessage(const Game_Battler& target, int value) {
243266
Utils::MakeSvArray(target.GetName(), std::to_string(value), lcf::Data::terms.health_points)
244267
);
245268
}
269+
270+
auto embedded_str_type = target_is_ally
271+
? EXE::Shared::EmbeddedStringTypes::Battle_DamageToAlly
272+
: EXE::Shared::EmbeddedStringTypes::Battle_DamageToEnemy;
273+
274+
StringView template_text;
275+
if (Player::Constants::HasEmbeddedTemplateString(embedded_str_type, template_text)) {
276+
return Utils::ReplacePlaceholders(
277+
template_text,
278+
Utils::MakeArray('S', 'V', 'T'),
279+
Utils::MakeSvArray(target.GetName(), std::to_string(value), message)
280+
);
281+
}
282+
246283
std::stringstream ss;
247284
std::string particle, space = "";
248285
ss << target.GetName();
@@ -276,6 +313,20 @@ std::string GetParameterChangeMessage(const Game_Battler& target, int value, Str
276313
Utils::MakeSvArray(target.GetName(), std::to_string(value), points)
277314
);
278315
}
316+
317+
auto embedded_str_type = is_positive
318+
? EXE::Shared::EmbeddedStringTypes::Battle_StatIncrease
319+
: EXE::Shared::EmbeddedStringTypes::Battle_StatDecrease;
320+
321+
StringView template_text;
322+
if (Player::Constants::HasEmbeddedTemplateString(embedded_str_type, template_text)) {
323+
return Utils::ReplacePlaceholders(
324+
template_text,
325+
Utils::MakeArray('S', 'U', 'V', 'T'),
326+
Utils::MakeSvArray(target.GetName(), points, std::to_string(value), message)
327+
);
328+
}
329+
279330
std::stringstream ss;
280331
std::string particle, particle2, space = "";
281332
ss << target.GetName();
@@ -437,6 +488,16 @@ std::string GetItemStartMessage2k(const Game_Battler& source, const lcf::rpg::It
437488
Utils::MakeSvArray(source.GetName(), item.name)
438489
);
439490
}
491+
492+
//StringView template_text;
493+
//if (Player::Constants::HasEmbeddedTemplateString(EXE::Shared::EmbeddedStringTypes::Battle_UseItem, template_text)) {
494+
// return Utils::ReplacePlaceholders(
495+
// template_text,
496+
// Utils::MakeArray('S', 'O', 'T'),
497+
// Utils::MakeSvArray(source.GetName(), item.name, ToString(lcf::Data::terms.use_item))
498+
// );
499+
//}
500+
440501
std::string particle;
441502
if (Player::IsCP932())
442503
particle = "";

src/exe_buildinfo.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,18 @@ namespace EXE::BuildInfo {
208208
}
209209
};
210210

211+
class CodeAddressStringInfo {
212+
public:
213+
size_t code_offset;
214+
uint32_t crc_jp, crc_en;
215+
validate_const_data pre_data;
216+
217+
template<typename... Args>
218+
constexpr CodeAddressStringInfo(size_t code_offset, uint32_t crc_jp, uint32_t crc_en, Args... args) :
219+
code_offset(code_offset), crc_jp(crc_jp), crc_en(crc_en), pre_data(validate_const_data{ static_cast<const uint8_t>(args)... }) {
220+
}
221+
};
222+
211223
constexpr size_t MAX_SIZE_CHK_PATCH_SEGMENT = 8;
212224

213225
using patch_segment_data = fixed_size_byte_array<MAX_SIZE_CHK_PATCH_SEGMENT>;

src/exe_reader.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,86 @@ std::map<EXE::Shared::GameConstantType, int32_t> EXEReader::GetOverridenGameCons
656656
return game_constants;
657657
}
658658

659+
std::map<EXE::Shared::EmbeddedStringTypes, std::string> EXEReader::GetEmbeddedStrings(std::string encoding) {
660+
constexpr int max_string_size = 32;
661+
constexpr bool debug_string_extraction = true;
662+
663+
std::map<EXE::Shared::EmbeddedStringTypes, std::string> embedded_strings;
664+
int code_offset = file_info.code_ofs - 0x400;
665+
std::array<char, max_string_size> str_data;
666+
667+
auto match_surrounding_data = [&](const EXE::BuildInfo::CodeAddressStringInfo& info, const uint32_t const_ofs) {
668+
for (int i = 0; i < info.pre_data.size(); i++) {
669+
if (info.pre_data[i] != GetU8(const_ofs - info.pre_data.size() + i))
670+
return false;
671+
}
672+
return true;
673+
};
674+
675+
auto check_string_address_map = [&](const EXE::Strings::string_address_map& map) {
676+
uint32_t const_ofs;
677+
bool extract_success = false;
678+
679+
for (auto it = map.begin(); it != map.end(); ++it) {
680+
auto const_type = it->first;
681+
auto& addr_info = it->second;
682+
683+
if (addr_info.code_offset == 0) {
684+
// string is not defined in this map
685+
continue;
686+
}
687+
688+
const_ofs = code_offset + addr_info.code_offset;
689+
690+
bool extract_string = false;
691+
if (match_surrounding_data(addr_info, const_ofs)) {
692+
extract_string = true;
693+
}
694+
695+
if (extract_string) {
696+
int32_t size_str = GetU32(const_ofs);
697+
if (size_str > max_string_size) {
698+
Output::Debug("Unexpected length for embedded string: {} ({})", EXE::Shared::kEmbeddedStringTypes.tag(const_type), size_str);
699+
continue;
700+
}
701+
const_ofs += 4;
702+
for (int i = 0; i < size_str; ++i) {
703+
str_data[i] = GetU8(const_ofs + i);
704+
}
705+
auto crc = static_cast<uint32_t>(crc32(0, reinterpret_cast<unsigned char*>(str_data.data()), size_str));
706+
707+
if ((crc != addr_info.crc_jp && crc != addr_info.crc_en) || debug_string_extraction) {
708+
auto extracted_string = lcf::ReaderUtil::Recode(ToString(lcf::DBString(str_data.data(), static_cast<size_t>(size_str))), encoding);
709+
710+
if (debug_string_extraction && crc == addr_info.crc_jp) {
711+
Output::Debug("Embedded string for '{}' matches JP -> '{}'", EXE::Shared::kEmbeddedStringTypes.tag(const_type), extracted_string);
712+
} else if (debug_string_extraction && crc == addr_info.crc_en) {
713+
Output::Debug("Embedded string for '{}' matches EN -> '{}'", EXE::Shared::kEmbeddedStringTypes.tag(const_type), extracted_string);
714+
} else {
715+
Output::Debug("Read embedded string '{}' -> '{}'", EXE::Shared::kEmbeddedStringTypes.tag(const_type), extracted_string);
716+
717+
//TODO: add to map
718+
}
719+
}
720+
721+
extract_success = true;
722+
} else {
723+
Output::Debug("Could not read embedded string '{}'", EXE::Shared::kEmbeddedStringTypes.tag(const_type));
724+
extract_success = false;
725+
}
726+
}
727+
};
728+
729+
switch (build_version) {
730+
case EXE::BuildInfo::RM2K_20030625:
731+
check_string_address_map(EXE::Strings::string_addresses_rm2k_151);
732+
break;
733+
default:
734+
break;
735+
}
736+
737+
return embedded_strings;
738+
}
659739

660740
std::vector<EXE::Shared::PatchSetupInfo> EXEReader::CheckForPatches() {
661741
std::vector<EXE::Shared::PatchSetupInfo> patches;

src/exe_reader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "exe_buildinfo.h"
2727
#include "exe_constants.h"
2828
#include "exe_patches.h"
29+
#include "exe_strings.h"
2930
#include "player.h"
3031

3132
/**
@@ -78,6 +79,8 @@ class EXEReader {
7879

7980
std::map<EXE::Shared::GameConstantType, int32_t> GetOverridenGameConstants();
8081

82+
std::map<EXE::Shared::EmbeddedStringTypes, std::string> GetEmbeddedStrings(std::string encoding);
83+
8184
std::vector<EXE::Shared::PatchSetupInfo> CheckForPatches();
8285

8386
private:

src/exe_shared.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,37 @@ namespace EXE::Shared {
9191

9292
static_assert(kGameConstantType.size() == static_cast<size_t>(GameConstantType::LAST));
9393

94+
enum class EmbeddedStringTypes {
95+
Battle_DamageToEnemy,
96+
Battle_DamageToAlly,
97+
Battle_HpSpRecovery,
98+
Battle_StatDecrease,
99+
Battle_StatIncrease,
100+
Battle_AbsorbEnemy,
101+
Battle_AbsorbAlly,
102+
Battle_UseItem,
103+
Msg_LevelUp,
104+
Menu_ExpMaxedOut,
105+
Menu_2k3ActorStatus_ExpMaxedOut,
106+
LAST
107+
};
108+
109+
static constexpr auto kEmbeddedStringTypes = lcf::makeEnumTags<EmbeddedStringTypes>(
110+
"Battle_DamageToEnemy",
111+
"Battle_DamageToAlly",
112+
"Battle_HpSpRecovery",
113+
"Battle_StatDecrease",
114+
"Battle_StatIncrease",
115+
"Battle_AbsorbEnemy",
116+
"Battle_AbsorbAlly",
117+
"Battle_UseItem",
118+
"Msg_LevelUp",
119+
"Menu_ExpMaxedOut",
120+
"Menu_2k3ActorStatus_ExpMaxedOut"
121+
);
122+
123+
static_assert(kEmbeddedStringTypes.size() == static_cast<size_t>(EmbeddedStringTypes::LAST));
124+
94125
enum class KnownPatches {
95126
UnlockPics,
96127
CommonThisEvent,

src/exe_strings.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* This file is part of EasyRPG Player.
3+
*
4+
* EasyRPG Player is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* EasyRPG Player is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#ifndef EP_EXE_STRINGS_H
19+
#define EP_EXE_STRINGS_H
20+
21+
#include "exe_buildinfo.h"
22+
#include "exe_shared.h"
23+
24+
namespace EXE::Strings {
25+
using namespace BuildInfo;
26+
using EmbeddedStringTypes = EXE::Shared::EmbeddedStringTypes;
27+
28+
using string_address = std::pair<EmbeddedStringTypes, CodeAddressStringInfo>;
29+
using string_address_map = std::array<string_address, static_cast<size_t>(EmbeddedStringTypes::LAST)>;
30+
31+
template<EmbeddedStringTypes C, typename... Args>
32+
constexpr string_address map(size_t code_offset, uint32_t crc_jp, uint32_t crc_en, Args&&... args) {
33+
return { C, CodeAddressStringInfo(code_offset, crc_jp, crc_en, std::forward<decltype(args)>(args)...) };
34+
}
35+
36+
template<EmbeddedStringTypes C>
37+
constexpr string_address not_def() {
38+
return { C, CodeAddressStringInfo(0, 0, 0, 0) };
39+
}
40+
41+
using Str = EmbeddedStringTypes;
42+
43+
#define FFFFFFFF 0xFF, 0xFF, 0xFF, 0xFF
44+
45+
//TODO: offsets: 0x07B848, 0x07B860 (are these strings used anywhere?)
46+
constexpr string_address_map string_addresses_rm2k_151 = {{
47+
map<Str::Battle_DamageToEnemy>(0x07AEA4, 0x9D4F8EDE, 0xB55355BF, FFFFFFFF),
48+
map<Str::Battle_DamageToAlly>(0x07AEB8, 0x6900AACD, 0xB55355BF, FFFFFFFF),
49+
map<Str::Battle_HpSpRecovery>(0x07AFF0, 0x7C968020, 0x5299B765, FFFFFFFF),
50+
map<Str::Battle_StatDecrease>(0x07B1E0, 0x7C968020, 0x5299B765, FFFFFFFF),
51+
map<Str::Battle_StatIncrease>(0x07B43C, 0x7C968020, 0x5299B765, FFFFFFFF),
52+
map<Str::Battle_AbsorbEnemy>(0x07B65C, 0xFB3336D9, 0x5299B765, FFFFFFFF),
53+
map<Str::Battle_AbsorbAlly>(0x07B674, 0x3ABDE919, 0x5299B765, FFFFFFFF),
54+
not_def<Str::Battle_UseItem>(),
55+
map<Str::Msg_LevelUp>(0x0882CC, 0x0DED4C01, 0x5299B765, FFFFFFFF),
56+
map<Str::Menu_ExpMaxedOut>(0x07C678, 0x2770FF3E, 0x2770FF3E, FFFFFFFF), //TODO
57+
not_def<Str::Menu_2k3ActorStatus_ExpMaxedOut>()
58+
}};
59+
}
60+
61+
#endif

src/game_actor.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,15 @@ std::string Game_Actor::GetLevelUpMessage(int new_level) const {
770770
Utils::MakeSvArray(GetName(), ss.str(), lcf::Data::terms.level)
771771
);
772772
} else {
773+
StringView template_text;
774+
if (Player::Constants::HasEmbeddedTemplateString(EXE::Shared::EmbeddedStringTypes::Msg_LevelUp, template_text)) {
775+
return Utils::ReplacePlaceholders(
776+
template_text,
777+
Utils::MakeArray('S', 'L', 'V', 'T'),
778+
Utils::MakeSvArray(GetName(), ToString(lcf::Data::terms.use_item), std::to_string(new_level), ToString(lcf::Data::terms.level_up))
779+
);
780+
}
781+
773782
std::string particle, space = "";
774783
if (Player::IsCP932()) {
775784
particle = "";

0 commit comments

Comments
 (0)