diff --git a/solution/ed_voice/ed_voice.vcxproj b/solution/ed_voice/ed_voice.vcxproj
index 0e01602..c9304b2 100644
--- a/solution/ed_voice/ed_voice.vcxproj
+++ b/solution/ed_voice/ed_voice.vcxproj
@@ -55,6 +55,7 @@
+
@@ -72,6 +73,7 @@
+
diff --git a/solution/ed_voice/ed_voice.vcxproj.filters b/solution/ed_voice/ed_voice.vcxproj.filters
index 8b6cfdf..d7af0c6 100644
--- a/solution/ed_voice/ed_voice.vcxproj.filters
+++ b/solution/ed_voice/ed_voice.vcxproj.filters
@@ -228,5 +228,11 @@
src\player
+
+ src\asm
+
+
+ src\startup
+
\ No newline at end of file
diff --git a/src/ed_voice/asm/asm.h b/src/ed_voice/asm/asm.h
index 2a4efa6..3ba4fdd 100644
--- a/src/ed_voice/asm/asm.h
+++ b/src/ed_voice/asm/asm.h
@@ -9,6 +9,14 @@ void textse();
void dlgse();
} // namespace asm_tits
+namespace asm_titsl {
+ void text();
+ void ldat();
+ void dcdat();
+ void textse();
+ void dlgse();
+} // namespace asm_titsl
+
namespace asm_sora {
void text();
void ldat();
diff --git a/src/ed_voice/asm/asm_tits.cpp b/src/ed_voice/asm/asm_tits.cpp
index 0bd3428..b82eb4f 100644
--- a/src/ed_voice/asm/asm_tits.cpp
+++ b/src/ed_voice/asm/asm_tits.cpp
@@ -13,7 +13,7 @@ __declspec(naked) void asm_tits::text() {
jmp common
fc:
- push ebx
+ push esi
common:
call bridge::Play
@@ -28,8 +28,12 @@ __declspec(naked) void asm_tits::text() {
__declspec(naked) void asm_tits::ldat() {
__asm {
- call bridge::LoadDat
+ push edx
+ push ecx
+ call bridge::LoadDatF
test eax, eax
+ pop ecx
+ pop edx
je short next
ret
@@ -40,12 +44,14 @@ __declspec(naked) void asm_tits::ldat() {
__declspec(naked) void asm_tits::dcdat() {
__asm {
- push edi
- push ebx
+ pushad
+ push edx
+ push ecx
push 0
call bridge::DecompressDat
add esp, 12
test eax, eax
+ popad
je short next
ret
@@ -69,22 +75,20 @@ __declspec(naked) void asm_tits::textse() {
__declspec(naked) void asm_tits::dlgse() {
__asm {
+ pushad
+ call bridge::Stop
+ popad
+
cmp dword ptr[global.sigs.no_dlgse], 0
- je short next
+ je short jump
mov dword ptr[global.sigs.no_dlgse], 0
cmp dword ptr[global.config.disable_dialog_se], 0
- je short next
+ je short jump
- pushad
- call bridge::Stop
- popad
- jmp dword ptr[global.addrs.dlgse_jmp]
+ ret
- next :
- pushad
- call bridge::Stop
- popad
- jmp dword ptr[global.addrs.dlgse_next]
+ jump :
+ jmp dword ptr[global.addrs.dlgse_jmp]
}
}
diff --git a/src/ed_voice/asm/asm_titsl.cpp b/src/ed_voice/asm/asm_titsl.cpp
new file mode 100644
index 0000000..2087322
--- /dev/null
+++ b/src/ed_voice/asm/asm_titsl.cpp
@@ -0,0 +1,90 @@
+#include "asm/asm.h"
+#include "bridge/bridge.h"
+#include "global/global.h"
+
+__declspec(naked) void asm_titsl::text() {
+ __asm {
+ jne short next
+ pushad
+
+ cmp dword ptr[global.info.game], GameTitsFC
+ je short fc
+ push edi
+ jmp common
+
+ fc:
+ push ebx
+
+ common:
+ call bridge::Play
+
+ popad
+ jmp dword ptr[global.addrs.text_next]
+
+ next :
+ jmp dword ptr[global.addrs.text_jmp]
+ }
+}
+
+__declspec(naked) void asm_titsl::ldat() {
+ __asm {
+ call bridge::LoadDat
+ test eax, eax
+ je short next
+ ret
+
+ next :
+ jmp dword ptr[global.addrs.ldat_next];
+ }
+}
+
+__declspec(naked) void asm_titsl::dcdat() {
+ __asm {
+ push edi
+ push ebx
+ push 0
+ call bridge::DecompressDat
+ add esp, 12
+ test eax, eax
+ je short next
+ ret
+
+ next :
+ jmp dword ptr[global.addrs.dcdat_next]
+ }
+}
+
+__declspec(naked) void asm_titsl::textse() {
+ __asm {
+ cmp dword ptr[global.sigs.no_textse], 0
+ je short next
+ cmp dword ptr[global.config.disable_text_se], 0
+ je short next
+ jmp dword ptr[global.addrs.textse_jmp]
+
+ next :
+ jmp dword ptr[global.addrs.textse_next]
+ }
+}
+
+__declspec(naked) void asm_titsl::dlgse() {
+ __asm {
+ cmp dword ptr[global.sigs.no_dlgse], 0
+ je short next
+ mov dword ptr[global.sigs.no_dlgse], 0
+ cmp dword ptr[global.config.disable_dialog_se], 0
+ je short next
+
+ pushad
+ call bridge::Stop
+ popad
+ jmp dword ptr[global.addrs.dlgse_jmp]
+
+ next :
+ pushad
+ call bridge::Stop
+ popad
+ jmp dword ptr[global.addrs.dlgse_next]
+ }
+}
+
diff --git a/src/ed_voice/bridge/bridge.h b/src/ed_voice/bridge/bridge.h
index 777b358..8dda8cf 100644
--- a/src/ed_voice/bridge/bridge.h
+++ b/src/ed_voice/bridge/bridge.h
@@ -7,6 +7,7 @@ int __stdcall Play(void* b);
int __cdecl Stop();
int __cdecl LoadDat(void*, void* buff, int idx, unsigned offset, unsigned size);
+int __cdecl LoadDatF(void* buff, int idx, void*, unsigned offset, unsigned size);
int __cdecl LoadDat2(void*, void* buff, int idx);
int __cdecl DecompressDat(void*, void** uncompressed, void** compressed);
diff --git a/src/ed_voice/bridge/bridge_dat.cpp b/src/ed_voice/bridge/bridge_dat.cpp
index 587df92..ba86f5c 100644
--- a/src/ed_voice/bridge/bridge_dat.cpp
+++ b/src/ed_voice/bridge/bridge_dat.cpp
@@ -75,6 +75,10 @@ inline const char* GetDir(int idx) {
} // namespace
+int __cdecl bridge::LoadDatF(void* buff, int idx, void*, unsigned offset, unsigned size) {
+ return bridge::LoadDat(nullptr, buff, idx, offset, size);
+}
+
int __cdecl bridge::LoadDat(void*, void* buff, int idx, unsigned offset, unsigned size) {
const char* dir = GetDir(idx);
if (!dir) {
diff --git a/src/ed_voice/startup/scan_group_common.h b/src/ed_voice/startup/scan_group_common.h
index 13d0711..f389c57 100644
--- a/src/ed_voice/startup/scan_group_common.h
+++ b/src/ed_voice/startup/scan_group_common.h
@@ -72,6 +72,8 @@ class ScanGroupCommon : public ScanGroup {
strings_.push_back(std::make_unique(kCodeBackupBlockSize));
code_bak_ = (byte*)strings_.back().get();
code_bak_remian = kCodeBackupBlockSize;
+ utils::MemProtection proction_bak;
+ utils::ChangeMemProtection(code_bak_, kCodeBackupBlockSize, utils::kMemProtectionRWE, &proction_bak);
}
bool InSection(const char* sec_name, byte* begin, std::size_t length) const {
@@ -83,7 +85,11 @@ class ScanGroupCommon : public ScanGroup {
return false;
}
const auto& sec = it->second;
- return begin >= sec.start && begin + length <= sec.end;
+ if (length > sec.size) {
+ return false;
+ }
+ return (unsigned long long)begin >= (unsigned long long)sec.start
+ && (unsigned long long)begin <= (unsigned long long)sec.end - length;
}
byte* GetCodeBackupBlock(std::size_t length) {
@@ -228,21 +234,6 @@ class ScanGroupCommon : public ScanGroup {
ScanGroupCommon& operator=(const ScanGroupCommon&) = delete;
}; // ScanGroupCommon
-class PieceCommon : public ScanGroupCommon::BasicPiece {
-public:
- PieceCommon(std::string_view pattern, ScanGroupCommon::PatternType pattern_type,
- ScanGroupCommon* group)
- : ScanGroupCommon::BasicPiece(pattern, pattern_type), Group{ group } {
- }
-
- bool InSection(byte* p, std::size_t len) {
-
- }
-
-protected:
- ScanGroupCommon* const Group;
-};
-
} // namespace startup
#define DEFINE_GROUP_BEGIN(GroupName_) \
diff --git a/src/ed_voice/startup/scan_group_tits.cpp b/src/ed_voice/startup/scan_group_tits.cpp
index 46a5fd5..177660a 100644
--- a/src/ed_voice/startup/scan_group_tits.cpp
+++ b/src/ed_voice/startup/scan_group_tits.cpp
@@ -30,24 +30,31 @@ DEFINE_APPLY_BEGIN()
void** addr = *(void***)(results.front() + 17);
global.addrs.pHwnd = addr;
LOG("pHwnd = 0x%08X", (unsigned)global.addrs.pHwnd);
-DEFINE_APPLY_END(true)
-DEFINE_PIECE_END(Hwnd)
+ DEFINE_APPLY_END(true)
+ DEFINE_PIECE_END(Hwnd)
-DEFINE_PIECE_BEGIN(Tits, Text, ".text", PatternType::Bytes,
- "80 F9 23 0F 85 ?? ?? ?? ?? ?? ?? ?? ??")
+ DEFINE_PIECE_BEGIN(Tits, Text, ".text", PatternType::Bytes,
+ "23 " "0F 85 ?? ?? ?? ??")
+ const utils::MemMatcher matcher_fc = utils::MemMatcher(
+ "80 F9 23", PatternType::Bytes);
+ const utils::MemMatcher matcher_sc = utils::MemMatcher(
+ "8B 74 24 20 E9 ?? ?? ?? ?? 3C 23", PatternType::Bytes);
+ const utils::MemMatcher matcher_3rd = utils::MemMatcher(
+ "89 B3 ?? ?? ?? ?? E9 ?? ?? ?? ?? 3C 23", PatternType::Bytes);
DEFINE_ADDITIONAL_MATCH_BEGIN(b, e)
- byte* dst = utils::GetCallJmpDest(b + 3, 6);
- bool rst = Group->InSection(".text", dst, 1);
+ byte* dst = utils::GetCallJmpDest(b + 1, 6);
+ bool rst = Group->InSection(".text", dst, 1)
+ && (matcher_fc.Match(b - 2) || matcher_sc.Match(b - 10) || matcher_3rd.Match(b - 12));
DEFINE_ADDITIONAL_MATCH_END(rst)
DEFINE_CHECK_RESULTS_BEGIN()
bool rst = !GetResults().empty();
DEFINE_CHECK_RESULTS_END(rst)
DEFINE_APPLY_BEGIN()
const auto& results = GetResults();
- byte* p = results.front() + 3;
+ byte* p = results.back() + 1;
bool rst = Group->RedirectWithJmp(
p, 6, asm_tits::text, &global.addrs.text_next, &global.addrs.text_jmp);
- if (*(p + 9) == 0x43) {
+ if (*(p + 9) == 0x46) {
global.info.game = GameTitsFC;
} else {
global.info.game = GameTitsSC3rd;
@@ -65,32 +72,45 @@ DEFINE_PIECE_BEGIN(Tits, Ldat, ".text", PatternType::Bytes,
const utils::MemMatcher matcher_en = utils::MemMatcher(
"81 EC 84 02 00 00", PatternType::Bytes);
DEFINE_ADDITIONAL_MATCH_BEGIN(b, e)
- bool rst = (matcher_cn.Match(b - 0x19) || matcher_en.Match(b - 0x19))
- && REF_STRING(".text", b + 1, ".rdata", L"ED6_DT%02x.DAT");
+ bool rst = REF_STRING(".text", b + 1, ".rdata", L"ED6_DT%02x.DAT");
+ if (rst) {
+ for (int i = 5; i <= 0x20; i++) {
+ if (matcher_cn.Match(b - i) || matcher_en.Match(b - i)) {
+ rst = true;
+ break;
+ }
+ }
+ }
DEFINE_ADDITIONAL_MATCH_END(rst)
DEFINE_CHECK_RESULTS_BEGIN()
bool rst = !GetResults().empty();
DEFINE_CHECK_RESULTS_END(rst)
DEFINE_APPLY_BEGIN()
const auto& results = GetResults();
- byte* p = results.front() - 0x19;
+ byte* p = results.front();
bool rst = false;
- if (*p == 0x81) {
- rst = Group->BackupCode(p, 6, asm_tits::ldat, &global.addrs.ldat_next);
- } else {
- rst = Group->RedirectWithJmp(p, 5, asm_tits::ldat, nullptr, &global.addrs.ldat_next);
+ for (int i = 5; i <= 0x20; i++) {
+ if (matcher_cn.Match(p - i)) {
+ rst = Group->RedirectWithJmp(p - i, 5, asm_tits::ldat, nullptr, &global.addrs.ldat_next);
+ LOG("Apply at 0x%08X", unsigned(p - i));
+ LOG("ldat_next = 0x%08X", (unsigned)global.addrs.ldat_next);
+ break;
+ } else if (matcher_en.Match(p - i)) {
+ rst = Group->BackupCode(p - i, 6, asm_tits::ldat, &global.addrs.ldat_next);
+ LOG("Apply at 0x%08X", unsigned(p - i));
+ LOG("ldat_next = 0x%08X", (unsigned)global.addrs.ldat_next);
+ break;
+ }
}
- LOG("Apply at 0x%08X", unsigned(p));
- LOG("ldat_next = 0x%08X", (unsigned)global.addrs.ldat_next);
DEFINE_APPLY_END(rst)
DEFINE_PIECE_END(Ldat)
DEFINE_PIECE_BEGIN(Tits, Dcdat, ".text", PatternType::Bytes,
- "89 44 24 04 8B 07 56")
+ "57 8B D9 C7 44 24 18 00 00 00 00")
const utils::MemMatcher matcher_cn = utils::MemMatcher(
"E9 ?? ?? ?? ??", PatternType::Bytes);
const utils::MemMatcher matcher_en = utils::MemMatcher(
- "83 EC 18 8B 03", PatternType::Bytes);
+ "83 EC 18 53 56", PatternType::Bytes);
DEFINE_ADDITIONAL_MATCH_BEGIN(b, e)
bool rst = matcher_cn.Match(b - 5) || matcher_en.Match(b - 5);
DEFINE_ADDITIONAL_MATCH_END(rst)
@@ -112,7 +132,7 @@ DEFINE_APPLY_END(rst)
DEFINE_PIECE_END(Dcdat)
DEFINE_PIECE_BEGIN(Tits, Pdirs, ".text", PatternType::Bytes,
- "C1 E9 10 8B 3C 8D ?? ?? ?? 00")
+ "8D 0C C0 8B 04 95 ?? ?? ?? 00")
DEFINE_ADDITIONAL_MATCH_BEGIN(b, e)
bool rst = Group->InSection(".data", *(byte**)(b + 6), sizeof(byte*) * 0x20)
&& REF_STRING(".data", *(byte**)(b + 6) + 6 * sizeof(byte*), "", "CH20000 ._CH")
@@ -132,11 +152,9 @@ DEFINE_APPLY_END(rst)
DEFINE_PIECE_END(Pdirs)
DEFINE_PIECE_BEGIN(Tits, Textse, ".text", PatternType::Bytes,
- "57 " "FF D2 " "80 3D ?? ?? ?? ?? 00 " "75 11")
+ "74 1E " "80 3D ?? ?? ?? ?? 00 " "75 ?? " "6A 00")
DEFINE_ADDITIONAL_MATCH_BEGIN(b, e)
- bool rst = Group->InSection(".data", *(byte**)(b + 5), sizeof(byte*))
- && Group->InSection(".text", b + 0x2C, sizeof(byte*))
- && *(b + 0x2C) == 0xC3;
+ bool rst = Group->InSection(".data", *(byte**)(b + 4), sizeof(byte*));
DEFINE_ADDITIONAL_MATCH_END(rst)
DEFINE_CHECK_RESULTS_BEGIN()
bool rst = !GetResults().empty();
@@ -144,18 +162,18 @@ DEFINE_CHECK_RESULTS_END(rst)
DEFINE_APPLY_BEGIN()
const auto& results = GetResults();
byte* p = results.front();
- global.addrs.textse_jmp = utils::GetCallJmpDest(p + 10, 2);
- bool rst = Group->BackupCode(p + 12, 6, asm_tits::textse, &global.addrs.textse_next);
- LOG("Apply at 0x%08X", unsigned(p + 12));
+ global.addrs.textse_jmp = utils::GetCallJmpDest(p + 9, 2);
+ bool rst = Group->BackupCode(p + 2, 7, asm_tits::textse, &global.addrs.textse_next);
+ LOG("Apply at 0x%08X", unsigned(p + 2));
LOG("textse_jmp = 0x%08X", (unsigned)global.addrs.textse_jmp);
LOG("textse_next = 0x%08X", (unsigned)global.addrs.textse_next);
DEFINE_APPLY_END(rst)
DEFINE_PIECE_END(Textse)
DEFINE_PIECE_BEGIN(Tits, Dlgse, ".text", PatternType::Bytes,
- "57 " "FF D0 " "80 3D ?? ?? ?? ?? 00 " "75 11")
+ "6A 00 " "89 86 ?? ?? ?? ?? " "E8 ?? ?? ?? ?? " "83 C4 0C")
DEFINE_ADDITIONAL_MATCH_BEGIN(b, e)
- bool rst = Group->InSection(".data", *(byte**)(b + 5), sizeof(byte*));
+ bool rst = true;
DEFINE_ADDITIONAL_MATCH_END(rst)
DEFINE_CHECK_RESULTS_BEGIN()
bool rst = !GetResults().empty();
@@ -163,15 +181,14 @@ DEFINE_CHECK_RESULTS_END(rst)
DEFINE_APPLY_BEGIN()
const auto& results = GetResults();
byte* p = results.front();
- global.addrs.dlgse_jmp = utils::GetCallJmpDest(p + 10, 2);
- bool rst = Group->BackupCode(p + 3, 7, asm_tits::dlgse, &global.addrs.dlgse_next);
- LOG("Apply at 0x%08X", unsigned(p + 3));
+ bool rst = Group->RedirectWithCall(p + 8, 5, asm_tits::dlgse, &global.addrs.dlgse_next, &global.addrs.dlgse_jmp);
+ LOG("Apply at 0x%08X", unsigned(p + 8));
LOG("dlgse_jmp = 0x%08X", (unsigned)global.addrs.dlgse_jmp);
LOG("dlgse_next = 0x%08X", (unsigned)global.addrs.dlgse_next);
DEFINE_APPLY_END(rst)
DEFINE_PIECE_END(Dlgse)
-DEFINE_PIECE_BEGIN(Tits, Strpatch, ".text", PatternType::Bytes, "68 ?? ?? ?? 00")
+DEFINE_PIECE_BEGIN(Tits, Strpatch, ".text", PatternType::Bytes, "?? ?? ?? ?? 00")
const startup::PatchingStrings strs_map_ = startup::LoadPatchingStrings();
mutable std::unordered_map to_patch_;
DEFINE_ADDITIONAL_MATCH_BEGIN(b, e)
@@ -203,7 +220,7 @@ DEFINE_APPLY_BEGIN()
DEFINE_APPLY_END(true)
DEFINE_PIECE_END(Strpatch)
-DEFINE_PIECE_BEGIN(Tits, Strpatch2, ".text", PatternType::Bytes, "68 ?? ?? ?? 00")
+DEFINE_PIECE_BEGIN(Tits, Strpatch2, ".text", PatternType::Bytes, "?? ?? ?? ?? 00")
const startup::RefPatchingStrings strs_map_
= startup::LoadRefPatchingStrings("voice/scena/Z_POKER9._DT");
mutable int diff = std::numeric_limits::max();
@@ -244,15 +261,20 @@ DEFINE_APPLY_BEGIN()
LOG("%d Strings Patched.", count);
#ifdef LOG
if (!GetResults().empty()) {
- std::string zero;
+ std::string zero, mul;
for (const auto& kv : cnts) {
if (kv.second == 0) {
zero += std::to_string(kv.first) + ",";
+ } else if (kv.second > 1) {
+ mul += std::to_string(kv.first) + ",";
}
}
if (!zero.empty()) {
LOG("These strings loaded, but not used: \n%s", zero.c_str());
}
+ if (!mul.empty()) {
+ LOG("These strings used more than once: \n%s", mul.c_str());
+ }
}
#endif
DEFINE_APPLY_END(true)
diff --git a/src/ed_voice/startup/scan_group_titsl.cpp b/src/ed_voice/startup/scan_group_titsl.cpp
new file mode 100644
index 0000000..6d46260
--- /dev/null
+++ b/src/ed_voice/startup/scan_group_titsl.cpp
@@ -0,0 +1,278 @@
+#include "startup/scan_group_common.h"
+
+#include