mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-12-25 12:44:13 +08:00
1655 lines
70 KiB
C++
1655 lines
70 KiB
C++
#include"Malie.h"
|
||
namespace { // unnamed Malie
|
||
/********************************************************************************************
|
||
Malie hook:
|
||
Process name is malie.exe.
|
||
This is the most complicate code I have made. Malie engine store text string in
|
||
linked list. We need to insert a hook to where it travels the list. At that point
|
||
EBX should point to a structure. We can find character at -8 and font size at +10.
|
||
Also need to enable ITH suppress function.
|
||
********************************************************************************************/
|
||
bool InsertMalieHook1()
|
||
{
|
||
const DWORD sig1 = 0x05e3c1;
|
||
enum { sig1_size = 3 };
|
||
DWORD i = SearchPattern(processStartAddress, processStopAddress - processStartAddress, &sig1, sig1_size);
|
||
if (!i) {
|
||
ConsoleOutput("MalieHook1: pattern i not exist");
|
||
return false;
|
||
}
|
||
|
||
const WORD sig2 = 0xc383;
|
||
enum { sig2_size = 2 };
|
||
DWORD j = i + processStartAddress + sig1_size;
|
||
i = SearchPattern(j, processStopAddress - j, &sig2, sig2_size);
|
||
//if (!j)
|
||
if (!i) { // jichi 8/19/2013: Change the condition fro J to I
|
||
ConsoleOutput("MalieHook1: pattern j not exist");
|
||
return false;
|
||
}
|
||
HookParam hp;
|
||
hp.address = j + i;
|
||
hp.offset=get_reg(regs::ebx);
|
||
hp.index = -0x8;
|
||
hp.split = get_reg(regs::ebx);
|
||
hp.split_index = 0x10;
|
||
hp.type = CODEC_UTF16|USING_SPLIT|DATA_INDIRECT|SPLIT_INDIRECT;
|
||
ConsoleOutput("INSERT MalieHook1");
|
||
return NewHook(hp, "Malie");
|
||
//RegisterEngineType(ENGINE_MALIE);
|
||
}
|
||
|
||
DWORD malie_furi_flag_; // jichi 8/20/2013: Make it global so that it can be reset
|
||
void SpecialHookMalie(hook_stack* stack, HookParam *, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD ch = stack->eax & 0xffff,
|
||
ptr = stack->edi;
|
||
*data = ch;
|
||
*len = 2;
|
||
if (malie_furi_flag_) {
|
||
DWORD index = stack->edx;
|
||
if (*(WORD *)(ptr + index * 2 - 2) < 0xa)
|
||
malie_furi_flag_ = 0;
|
||
}
|
||
else if (ch == 0xa) {
|
||
malie_furi_flag_ = 1;
|
||
len = 0;
|
||
}
|
||
*split = malie_furi_flag_;
|
||
}
|
||
|
||
bool InsertMalieHook2() // jichi 8/20/2013: Change return type to boolean
|
||
{
|
||
const BYTE bytes[] = {0x66,0x3d,0x1,0x0};
|
||
DWORD start = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||
if (!start) {
|
||
ConsoleOutput("MalieHook2: pattern not exist");
|
||
return false;
|
||
}
|
||
BYTE *ptr = (BYTE *)start;
|
||
while (true) {
|
||
if (*(WORD *)ptr == 0x3d66) {
|
||
ptr += 4;
|
||
if (ptr[0] == 0x75) {
|
||
ptr += ptr[1]+2;
|
||
continue;
|
||
}
|
||
if (*(WORD *)ptr == 0x850f) {
|
||
ptr += *(DWORD *)(ptr + 2) + 6;
|
||
continue;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
malie_furi_flag_ = 0; // reset old malie flag
|
||
HookParam hp;
|
||
hp.address = (DWORD)ptr + 4;
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.text_fun = SpecialHookMalie;
|
||
hp.type = USING_SPLIT|CODEC_UTF16|NO_CONTEXT|USING_CHAR;
|
||
ConsoleOutput("INSERT MalieHook2");
|
||
return NewHook(hp, "Malie");
|
||
//RegisterEngineType(ENGINE_MALIE);
|
||
|
||
}
|
||
|
||
/**
|
||
* jichi 12/17/2013: Added for Electro Arms
|
||
* Observations from Electro Arms:
|
||
* 1. split = 0xC can handle most texts and its dwRetn is always zero
|
||
* 2. The text containing furigana needed to split has non-zero dwRetn when split = 0
|
||
*
|
||
* 3/15/2015: logic modified as the plus operation would create so many threads
|
||
*/
|
||
void SpecialHookMalie2(hook_stack* stack, HookParam *, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
//CC_UNUSED(data);
|
||
//*len = GetHookDataLength(*hp, esp_base, (DWORD)data);
|
||
*len = 2;
|
||
|
||
DWORD s1 = stack->stack[3], // base split, which is stable
|
||
s2 = stack->stack[0]; // used to split out furigana, but un stable
|
||
// http://www.binaryhexconverter.com/decimal-to-binary-converter
|
||
//enum : DWORD { mask = 0x14 };
|
||
*split = s1 + (s2 ? 1 : 0);
|
||
}
|
||
|
||
// static DWORD last_split; // FIXME: This makes the special function stateful
|
||
// DWORD s1 = *(DWORD *)esp_base; // current split at 0x0
|
||
// if (!s1)
|
||
// *split = last_split;
|
||
// else {
|
||
// DWORD s2 = *(DWORD *)(esp_base + 0xc); // second split
|
||
// *split = last_split = s1 + s2; // not sure if plus is a good way
|
||
// }
|
||
|
||
/**
|
||
* jichi 8/20/2013: Add hook for sweet light BRAVA!!
|
||
* See: http://www.hongfire.com/forum/printthread.php?t=36807&pp=10&page=680
|
||
*
|
||
* BRAVA!! /H code: "/HWN-4:C@1A3DF4:malie.exe"
|
||
* - addr: 1719796 = 0x1a3df4
|
||
* - text_fun: 0x0
|
||
* - function: 0
|
||
* - hook_len: 0
|
||
* - ind: 0
|
||
* - length_offset: 1
|
||
* - module: 751199171 = 0x2cc663c3
|
||
* - off: 4294967288 = 0xfffffff8L = -0x8
|
||
* - recover_len: 0
|
||
* - split: 12 = 0xc
|
||
* - split_ind: 0
|
||
* - type: 1106 = 0x452
|
||
*/
|
||
bool InsertMalie2Hook()
|
||
{
|
||
// 001a3dee 6900 70000000 imul eax,dword ptr ds:[eax],70
|
||
// 001a3df4 0200 add al,byte ptr ds:[eax] ; this is the place to hook
|
||
// 001a3df6 50 push eax
|
||
// 001a3df7 0069 00 add byte ptr ds:[ecx],ch
|
||
// 001a3dfa 0000 add byte ptr ds:[eax],al
|
||
const BYTE bytes1[] = {
|
||
0x40, // inc eax
|
||
0x89,0x56, 0x08, // mov dword ptr ds:[esi+0x8],edx
|
||
0x33,0xd2, // xor edx,edx
|
||
0x89,0x46, 0x04 // mov dword ptr ds:[esi+0x4],eax
|
||
};
|
||
ULONG range1 = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||
ULONG addr = MemDbg::findBytes(bytes1, sizeof(bytes1), processStartAddress, processStartAddress + range1);
|
||
//reladdr = 0x1a3df4;
|
||
if (!addr) {
|
||
//ITH_MSG(0, "Wrong1", "t", 0);
|
||
//ConsoleOutput("Not malie2 engine");
|
||
ConsoleOutput("Malie2Hook: pattern p not exist");
|
||
return false;
|
||
}
|
||
|
||
addr += sizeof(bytes1); // skip bytes1
|
||
//const BYTE bytes2[] = { 0x85, 0xc0 }; // test eax,eax
|
||
const WORD bytes2 = 0xc085; // test eax,eax
|
||
enum { range2 = 0x200 };
|
||
addr = MemDbg::findBytes(&bytes2, sizeof(bytes2), addr, addr + range2);
|
||
if (!addr) {
|
||
//ConsoleOutput("Not malie2 engine");
|
||
ConsoleOutput("Malie2Hook: pattern q not exist");
|
||
return false;
|
||
}
|
||
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.offset=get_reg(regs::eax);
|
||
//hp.split = 0xc; // jichi 12/17/2013: Subcontext removed
|
||
//hp.split = -0xc; // jichi 12/17/2013: This could split the furigana, but will mess up the text
|
||
//hp.type = USING_SPLIT|CODEC_UTF16|NO_CONTEXT;
|
||
// jichi 12/17/2013: Need extern func for Electro Arms
|
||
// Though the hook parameter is quit similar to Malie, the original extern function does not work
|
||
hp.type = USING_SPLIT|NO_CONTEXT|CODEC_UTF16|USING_CHAR;
|
||
hp.text_fun = SpecialHookMalie2;
|
||
ConsoleOutput("INSERT Malie2");
|
||
return NewHook(hp, "Malie2");
|
||
|
||
//GROWL_DWORD2(hp.address, reladdr);
|
||
//RegisterEngineType(ENGINE_MALIE);
|
||
}
|
||
|
||
// jichi 2/8/3014: Return the beginning and the end of the text
|
||
// Remove the leading illegal characters
|
||
enum { _MALIE3_MAX_LENGTH = VNR_TEXT_CAPACITY };
|
||
LPCWSTR _Malie3LTrim(LPCWSTR p)
|
||
{
|
||
if (p)
|
||
for (int count = 0; count < _MALIE3_MAX_LENGTH; count++,
|
||
p++)
|
||
if (p[0] == L'v' && p[1] == L'_') { // ex. v_akr0001, v_mzk0001
|
||
p += 9;
|
||
return p; // must return otherwise trimming more will break the ITH repetition elimination
|
||
} else if (p[0] >= 0xa) // ltrim illegal characters less than 0xa
|
||
return p;
|
||
return nullptr;
|
||
}
|
||
// Remove the trailing illegal characters
|
||
LPCWSTR _Malie3RTrim(LPCWSTR p)
|
||
{
|
||
if (p)
|
||
for (int count = 0; count < _MALIE3_MAX_LENGTH; count++,
|
||
p--)
|
||
if (p[-1] >= 0xa) { // trim illegal characters less than 0xa
|
||
if (p[-1] >= L'0' && p[-1] <= L'9'&& p[-1-7] == L'_')
|
||
p -= 9;
|
||
else
|
||
return p;
|
||
}
|
||
return nullptr;
|
||
}
|
||
|
||
// Example section in memory:
|
||
// 0D7D7E00 07 00 08 00 76 00 5F 00 7A 00 65 00 70 00 30 00 v_zep0
|
||
// 0D7D7E10 30 00 37 00 35 00 00 00 0C 30 42 30 41 30 01 30 075.「あぁ<E38182>// 0D7D7E20 41 30 26 20 26 20 07 00 09 00 07 00 06 00 07 00 ぁ…….
|
||
// 0D7D7E30 08 00 76 00 5F 00 7A 00 65 00 70 00 30 00 30 00 v_zep00
|
||
// 0D7D7E40 37 00 36 00 00 00 46 30 01 30 42 30 01 30 41 30 76.<>あ、ぁ
|
||
// 0D7D7E50 41 30 41 30 26 20 26 20 26 20 26 20 01 30 63 30 ぁぁ…………、っ
|
||
// 0D7D7E60 07 00 09 00 0D 30 07 00 06 00 0A 00 0A 00 00 30 .<2E>..
|
||
// 0D7D7E70 16 60 44 30 01 30 16 60 44 30 01 30 4A 30 5E 30 怖い、怖い、お<E38081>// 0D7D7E80 7E 30 57 30 44 30 02 30 55 4F 4C 30 16 60 44 30 ましい。何が怖い
|
||
// 0D7D7E90 6E 30 4B 30 55 30 48 30 01 30 06 52 4B 30 89 30 のかさえ、<E38188>から
|
||
// 0D7D7EA0 6A 30 44 30 02 30 07 00 06 00 0A 00 00 30 8B 89 な. <>// 0D7D7EB0 8B 30 6A 30 88 30 02 30 8B 89 8B 30 6A 30 02 30 るなよ。見るな<E3828B>// 0D7D7EC0 07 00 06 00 8B 89 8B 30 6A 30 01 30 8B 89 8B 30 見るな、見る
|
||
// 0D7D7ED0 6A 30 8B 89 8B 30 6A 30 8B 89 8B 30 6A 30 01 30 な見るな見るな<E3828B>// 0D7D7EE0 1F 75 4D 30 66 30 66 30 AA 60 44 30 4B 30 88 30 生きてて悪ぁ<E682AA><E38181>// 0D7D7EF0 02 30 C5 60 51 30 6A 30 44 30 63 30 66 30 07 00 。情けなぁ<E381AA>て
|
||
// 0D7D7F00 01 00 E4 55 0A 00 8F 30 89 30 00 00 46 30 6A 30 嗤.わら.ぁ<>
|
||
// 0D7D7F10 88 30 02 30 07 00 06 00 BE 7C 00 4E 6F 67 6A 30 よ<>精一杯な
|
||
// 0D7D7F20 93 30 60 30 8B 89 03 90 57 30 66 30 4F 30 8C 30 んだ見送<E8A68B>てくれ
|
||
// 0D7D7F30 02 30 4A 30 58 98 44 30 57 30 7E 30 59 30 01 30 。お願いします<E381BE>// 0D7D7F40 60 30 4B 30 89 30 69 30 46 30 4B 30 5D 30 6E 30 <20>からどぁ<E381A9>そ<EFBFBD>
|
||
// 0D7D7F50 EE 76 92 30 84 30 81 30 66 30 01 30 4F 30 60 30 目をやめて、く<E38081>
|
||
// 0D7D7F60 55 30 44 30 01 30 5D 30 93 30 6A 30 02 30 07 00 さい、そんな<E38293>
|
||
// 0D7D7F70 06 00 0A 00 00 30 07 00 01 00 BA 87 50 5B 0A 00 . 螺<>
|
||
// 0D7D7F80 59 30 4C 30 00 00 8B 30 88 30 46 30 6A 30 EE 76 すが.るよぁ<E38288>目
|
||
// 0D7D7F90 67 30 00 25 00 25 07 00 06 00 BF 30 01 30 B9 30 で──タ、ス
|
||
// 0D7D7FA0 01 30 B1 30 01 30 C6 30 01 30 6A 30 93 30 66 30 、ケ、テ、なんて
|
||
// 0D7D7FB0 02 30 07 00 06 00 00 00 00 00 00 00 00 00 00 00 <20>.....
|
||
// 0D7D7FC0 FC D8 C0 22 00 00 00 80 74 00 00 00 00 00 00 00 .耀t...
|
||
//
|
||
// Return the end of the line
|
||
LPCWSTR _Malie3GetEOL(LPCWSTR p)
|
||
{
|
||
if (p)
|
||
for (int count = 0; count < _MALIE3_MAX_LENGTH; count++,
|
||
p++)
|
||
switch (*p) {
|
||
case 0:
|
||
case 0xa: // stop at \0, or \n where the text after 0xa is furigana
|
||
return p;
|
||
case 0x7:
|
||
// \x07\x00\x01\x00 is used to split furigana, which we want to keep
|
||
// \x07\x00\x04\x00 is used to split sentences, observed in シルヴァリオ ヴェンヂ<E383B3>ヂ<EFBFBD>
|
||
// \x07\x00\x06\x00 is used to split paragraph, observed in シルヴァリオ ヴェンヂ<E383B3>ヂ<EFBFBD>
|
||
if (p[1] < 0xa && p[1] != 0x1)
|
||
return p;
|
||
}
|
||
return nullptr;
|
||
}
|
||
|
||
/**
|
||
* jichi 3/8/2014: Add hook for 相州戦神館學<E9A4A8>八命陣
|
||
* See: http://sakuradite.com/topic/157
|
||
* check 0x5b51ed for ecx+edx*2
|
||
* Also need to skip furigana.
|
||
*/
|
||
|
||
void SpecialHookMalie3(hook_stack* stack, HookParam *, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
//CC_UNUSED(split);
|
||
DWORD ecx = stack->ecx, // *(DWORD *)(esp_base + pusha_ecx_off - 4),
|
||
edx = stack->edx; // *(DWORD *)(esp_base + pusha_edx_off - 4);
|
||
//*data = ecx + edx*2; // [ecx+edx*2];
|
||
//*len = wcslen((LPCWSTR)data) << 2;
|
||
// There are garbage characters
|
||
LPCWSTR start = _Malie3LTrim((LPCWSTR)(ecx + edx*2)),
|
||
stop = _Malie3RTrim(_Malie3GetEOL(start));
|
||
*data = (DWORD)start;
|
||
*len = max(0, stop - start) * 2;
|
||
*split = FIXED_SPLIT_VALUE;
|
||
//GROWL_DWORD5((DWORD)start, (DWORD)stop, *len, (DWORD)*start, (DWORD)_Malie3GetEOL(start));
|
||
}
|
||
|
||
/**
|
||
* jichi 8/20/2013: Add hook for 相州戦神館學<E9A4A8>八命陣
|
||
* See: http://sakuradite.com/topic/157
|
||
* Credits: @ok123
|
||
*
|
||
* Debugging method: insert hardware breakpoint into text
|
||
* There are four matches of text in the memory
|
||
*
|
||
* Sample game: シルヴァリオ ヴェンヂ<E383B3>ヂ<EFBFBD>
|
||
* 0065478B 90 NOP
|
||
* 0065478C 90 NOP
|
||
* 0065478D 90 NOP
|
||
* 0065478E 90 NOP
|
||
* 0065478F 90 NOP
|
||
* 00654790 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+0x4]
|
||
* 00654794 56 PUSH ESI
|
||
* 00654795 57 PUSH EDI
|
||
* 00654796 8B50 08 MOV EDX,DWORD PTR DS:[EAX+0x8]
|
||
* 00654799 8B08 MOV ECX,DWORD PTR DS:[EAX]
|
||
* 0065479B 33F6 XOR ESI,ESI
|
||
* 0065479D 66:8B3451 MOV SI,WORD PTR DS:[ECX+EDX*2] ; jichi: text accessed here
|
||
* 006547A1 42 INC EDX
|
||
* 006547A2 8970 04 MOV DWORD PTR DS:[EAX+0x4],ESI
|
||
* 006547A5 8950 08 MOV DWORD PTR DS:[EAX+0x8],EDX
|
||
* 006547A8 8B50 04 MOV EDX,DWORD PTR DS:[EAX+0x4]
|
||
* 006547AB 83FA 01 CMP EDX,0x1
|
||
* 006547AE 75 2C JNZ SHORT malie.006547DC
|
||
* 006547B0 8B50 08 MOV EDX,DWORD PTR DS:[EAX+0x8]
|
||
* 006547B3 33F6 XOR ESI,ESI
|
||
* 006547B5 66:8B3451 MOV SI,WORD PTR DS:[ECX+EDX*2]
|
||
* 006547B9 42 INC EDX
|
||
* 006547BA 8970 04 MOV DWORD PTR DS:[EAX+0x4],ESI
|
||
* 006547BD 33F6 XOR ESI,ESI
|
||
* 006547BF 8950 08 MOV DWORD PTR DS:[EAX+0x8],EDX
|
||
* 006547C2 66:8B3451 MOV SI,WORD PTR DS:[ECX+EDX*2]
|
||
* 006547C6 8970 04 MOV DWORD PTR DS:[EAX+0x4],ESI
|
||
* 006547C9 42 INC EDX
|
||
* 006547CA 33F6 XOR ESI,ESI
|
||
* 006547CC 8950 08 MOV DWORD PTR DS:[EAX+0x8],EDX
|
||
* 006547CF 66:8B3451 MOV SI,WORD PTR DS:[ECX+EDX*2]
|
||
* 006547D3 42 INC EDX
|
||
* 006547D4 8970 04 MOV DWORD PTR DS:[EAX+0x4],ESI
|
||
* 006547D7 8950 08 MOV DWORD PTR DS:[EAX+0x8],EDX
|
||
* 006547DA ^EB BF JMP SHORT malie.0065479B
|
||
* 006547DC 83FA 02 CMP EDX,0x2
|
||
* 006547DF 0F84 59010000 JE malie.0065493E
|
||
* 006547E5 83FA 03 CMP EDX,0x3
|
||
* 006547E8 75 12 JNZ SHORT malie.006547FC
|
||
* 006547EA 8B50 08 MOV EDX,DWORD PTR DS:[EAX+0x8]
|
||
* 006547ED 33F6 XOR ESI,ESI
|
||
* 006547EF 66:8B3451 MOV SI,WORD PTR DS:[ECX+EDX*2]
|
||
* 006547F3 42 INC EDX
|
||
* 006547F4 8970 04 MOV DWORD PTR DS:[EAX+0x4],ESI
|
||
* 006547F7 8950 08 MOV DWORD PTR DS:[EAX+0x8],EDX
|
||
* 006547FA ^EB 9F JMP SHORT malie.0065479B
|
||
* 006547FC 83FA 04 CMP EDX,0x4
|
||
* 006547FF 0F84 39010000 JE malie.0065493E
|
||
* 00654805 83FA 07 CMP EDX,0x7
|
||
* 00654808 0F85 27010000 JNZ malie.00654935
|
||
* 0065480E 8B50 08 MOV EDX,DWORD PTR DS:[EAX+0x8]
|
||
* 00654811 33F6 XOR ESI,ESI
|
||
* 00654813 66:8B3451 MOV SI,WORD PTR DS:[ECX+EDX*2]
|
||
* 00654817 8970 04 MOV DWORD PTR DS:[EAX+0x4],ESI
|
||
* 0065481A 8D72 01 LEA ESI,DWORD PTR DS:[EDX+0x1]
|
||
* 0065481D 8B50 04 MOV EDX,DWORD PTR DS:[EAX+0x4]
|
||
* 00654820 8970 08 MOV DWORD PTR DS:[EAX+0x8],ESI
|
||
* 00654823 8D7A FF LEA EDI,DWORD PTR DS:[EDX-0x1]
|
||
* 00654826 83FF 3B CMP EDI,0x3B
|
||
* 00654829 ^0F87 79FFFFFF JA malie.006547A8
|
||
* 0065482F 33D2 XOR EDX,EDX
|
||
* 00654831 8A97 9C496500 MOV DL,BYTE PTR DS:[EDI+0x65499C]
|
||
* 00654837 FF2495 80496500 JMP DWORD PTR DS:[EDX*4+0x654980]
|
||
* 0065483E 8B50 0C MOV EDX,DWORD PTR DS:[EAX+0xC]
|
||
* 00654841 85D2 TEST EDX,EDX
|
||
* 00654843 0F8F 2B010000 JG malie.00654974
|
||
* 00654849 33D2 XOR EDX,EDX
|
||
* 0065484B 66:8B1471 MOV DX,WORD PTR DS:[ECX+ESI*2]
|
||
* 0065484F 46 INC ESI
|
||
* 00654850 85D2 TEST EDX,EDX
|
||
* 00654852 8950 04 MOV DWORD PTR DS:[EAX+0x4],EDX
|
||
* 00654855 8970 08 MOV DWORD PTR DS:[EAX+0x8],ESI
|
||
* 00654858 0F84 E0000000 JE malie.0065493E
|
||
* 0065485E 8B50 08 MOV EDX,DWORD PTR DS:[EAX+0x8]
|
||
* 00654861 33F6 XOR ESI,ESI
|
||
* 00654863 66:8B3451 MOV SI,WORD PTR DS:[ECX+EDX*2]
|
||
* 00654867 42 INC EDX
|
||
* 00654868 8950 08 MOV DWORD PTR DS:[EAX+0x8],EDX
|
||
* 0065486B 8BD6 MOV EDX,ESI
|
||
* 0065486D 85D2 TEST EDX,EDX
|
||
* 0065486F 8970 04 MOV DWORD PTR DS:[EAX+0x4],ESI
|
||
* 00654872 ^75 EA JNZ SHORT malie.0065485E
|
||
* 00654874 8B50 08 MOV EDX,DWORD PTR DS:[EAX+0x8]
|
||
*/
|
||
bool InsertMalie3Hook()
|
||
{
|
||
// i.e. 8b44240456578b50088b0833f6668b345142
|
||
const BYTE bytes[] = {
|
||
// 0x90 nop
|
||
0x8b,0x44,0x24, 0x04, // 5b51e0 mov eax,dword ptr ss:[esp+0x4] ; jichi: function starts
|
||
0x56, // 5b51e4 push esi
|
||
0x57, // 5b51e5 push edi
|
||
0x8b,0x50, 0x08, // 5b51e6 mov edx,dword ptr ds:[eax+0x8]
|
||
0x8b,0x08, // 5b51e9 mov ecx,dword ptr ds:[eax]
|
||
0x33,0xf6, // 5b51eb xor esi,esi
|
||
0x66,0x8b,0x34,0x51, // 5b51ed mov si,word ptr ds:[ecx+edx*2] // jichi: hook here
|
||
0x42 // 5b51f1 inc edx
|
||
};
|
||
enum {addr_offset = 0x5b51ed - 0x5b51e0};
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||
if (!addr) {
|
||
ConsoleOutput("Malie3: pattern not found");
|
||
return false;
|
||
}
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
//GROWL(hp.address);
|
||
//hp.address = 0x5b51ed;
|
||
//hp.address = 0x5b51f1;
|
||
//hp.address = 0x5b51f2;
|
||
// jichi 3/15/2015: Remove 0704 in シルヴァリオ ヴェンッ<E383B3>タ
|
||
hp.filter_fun = IllegalCharsFilterW; // remove illegal control chars such as 0x07,0x01
|
||
hp.text_fun = SpecialHookMalie3;
|
||
hp.type = USING_SPLIT|NO_CONTEXT|CODEC_UTF16;
|
||
//hp.filter_fun = Malie3Filter;
|
||
ConsoleOutput("INSERT Malie3");
|
||
return NewHook(hp, "Malie3");
|
||
}
|
||
|
||
bool InsertMalie4Hook()
|
||
{
|
||
// i.e. 50 8B 45 10 D9 9F ?? ?? ?? ?? 0F B7 04 58 50 51 E8 ?? ?? ?? ?? 8B 45 14 83 C4 10
|
||
const BYTE bytes[] = {
|
||
0x50, // 65904E | 50 | push eax | mireado: pattern starts
|
||
0x8B,0x45,0x10, // 65904F | 8B 45 10 | mov eax,dword ptr ss:[ebp+10] |
|
||
0xD9,0x9F,XX4, // 659052 | D9 9F E8 6B 87 00 | fstp dword ptr ds:[edi+876BE8] |
|
||
0x0F,0xB7,0x04,0x58, // 659058 | 0F B7 04 58 | movzx eax,word ptr ds:[eax+ebx*2] |
|
||
0x50, // 65905C | 50 | push eax |
|
||
0x51, // 65905D | 51 | push ecx |
|
||
0xE8,XX4, // 65905E | E8 DD 1D EA FF | call malie.4FAE40 | mireado: hook here
|
||
0x8B,0x45,0x14, // 659063 | 8B 45 14 | mov eax,dword ptr ss:[ebp+14] |
|
||
0x83,0xC4,0x10 // 659066 | 83 C4 10 | add esp,10 |
|
||
};
|
||
enum {addr_offset = 0x65905E - 0x65904E};
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||
if (!addr) {
|
||
ConsoleOutput("Malie4: pattern not found");
|
||
return false;
|
||
}
|
||
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.offset=get_reg(regs::eax); // pusha_eax_off - 4
|
||
//hp.split = 0xc; // jichi 12/17/2013: Subcontext removed
|
||
//hp.type = USING_SPLIT|CODEC_UTF16|NO_CONTEXT;
|
||
// jichi 12/17/2013: Need extern func for Electro Arms
|
||
// Though the hook parameter is quit similar to Malie, the original extern function does not work
|
||
hp.split = get_reg(regs::edx); // jichi 12/17/2013: This could split the furigana, but will mess up the text
|
||
hp.type = USING_SPLIT|NO_CONTEXT|CODEC_UTF16;
|
||
ConsoleOutput("INSERT Malie4");
|
||
return NewHook(hp, "Malie4");
|
||
|
||
//GROWL_DWORD2(hp.address, reladdr);
|
||
//RegisterEngineType(ENGINE_MALIE);
|
||
}
|
||
|
||
// Artikash 1/19/2019: works on https://vndb.org/r52326
|
||
bool InsertMalie5Hook()
|
||
{
|
||
const BYTE bytes[] = {
|
||
0x8b, 0x49, 0x10, // mov ecx,[ecx+10]
|
||
0x03, 0x08, // add ecx,[eax]
|
||
0x51 // push ecx
|
||
};
|
||
|
||
if (DWORD addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress))
|
||
{
|
||
ConsoleOutput("INSERT Malie5");
|
||
HookParam hp;
|
||
hp.address = addr + 5;
|
||
hp.offset=get_reg(regs::ecx);
|
||
hp.type = CODEC_UTF16 | USING_STRING | NO_CONTEXT;
|
||
return NewHook(hp, "Malie5");
|
||
}
|
||
|
||
ConsoleOutput("Malie5 pattern not found");
|
||
return false;
|
||
}
|
||
|
||
// jichi 3/12/2015: Return guessed Malie engine year
|
||
//int GetMalieYear()
|
||
//{
|
||
// if (Util::SearchResourceString(L"2013 light"))
|
||
// return 2013;
|
||
// if (Util::SearchResourceString(L"2014 light"))
|
||
// return 2014;
|
||
// return 2015;
|
||
//}
|
||
|
||
} // unnamed Malie
|
||
|
||
bool InsertMalieHook()
|
||
{
|
||
if (Util::CheckFile(L"tools.dll"))
|
||
return InsertMalieHook1(); // jichi 3/5/2015: For old light games such as Dies irae.
|
||
|
||
else { // For old Malie games before 2015
|
||
// jichi 8/20/2013: Add hook for sweet light engine
|
||
// Insert both malie and malie2 hook.
|
||
bool ok = false;
|
||
|
||
// jichi 3/12/2015: Disable MalieHook2 which will crash シルヴァリオ ヴェンッ<E383B3>タ
|
||
//if (!Util::CheckFile(L"gdiplus.dll"))
|
||
if (Util::CheckFile(L"System\\*")) { // Insert old Malie hook. There are usually System/cursor.cur
|
||
ok = InsertMalieHook2() || ok;
|
||
ok = InsertMalie2Hook() || ok; // jichi 8/20/2013
|
||
}
|
||
|
||
// The main disadvantage of Malie3 is that it cannot find character name
|
||
ok = InsertMalie3Hook() || ok; // jichi 3/7/2014
|
||
ok = InsertMalie4Hook() || ok;
|
||
ok = InsertMalie5Hook() || ok;
|
||
return ok;
|
||
}
|
||
}
|
||
|
||
namespace { // unnamed
|
||
namespace ScenarioHook {
|
||
namespace Private {
|
||
|
||
/**
|
||
* Sample game: シルヴァリオ ヴェンデッタ
|
||
*
|
||
* 0706: long pause, text separator
|
||
* 0704: short pause
|
||
* 0708: voice start.
|
||
* 0701: ruby start, 0a as separator
|
||
*
|
||
* Sample plain unvoiced text:
|
||
*
|
||
* 0706 is used as pause char.
|
||
*
|
||
* 01FFF184 00 30 2A 8A 8C 30 8B 30 21 6B 6E 30 27 59 75 65 訪れる次の大敵
|
||
* 01FFF194 00 25 00 25 21 6B 6E 30 0D 4E 78 5E 02 30 21 6B ──次の不幸。次
|
||
* 01FFF1A4 6E 30 E6 82 E3 96 02 30 21 6B 6E 30 34 78 C5 6E の苦難。次の破滅
|
||
* 01FFF1B4 02 30 07 00 06 00 0A 00 00 30 B4 63 7F 30 D6 53 。. 掴み取
|
||
* 01FFF1C4 63 30 5F 30 6F 30 5A 30 6E 30 2A 67 65 67 6F 30 ったはずの未来は
|
||
* 01FFF1D4 97 66 D2 9E 6B 30 55 87 7E 30 8C 30 5F 30 7E 30 暗黒に蝕まれたま
|
||
* 01FFF1E4 7E 30 9A 7D 4C 88 57 30 66 30 44 30 4F 30 02 30 ま続行していく。
|
||
* 01FFF1F4 07 00 06 00 0A 00 00 30 80 30 57 30 8D 30 4B 62 . むしろ手
|
||
* 01FFF204 6B 30 57 30 5F 30 47 59 E1 8D 92 30 7C 54 73 30 にした奇跡を呼び
|
||
* 01FFF214 34 6C 6B 30 01 30 88 30 8A 30 4A 30 5E 30 7E 30 水に、よりおぞま
|
||
* 01FFF224 57 30 44 30 B0 65 5F 30 6A 30 66 8A F4 7D 92 30 しい新たな試練を
|
||
* 01FFF234 44 7D 7F 30 BC 8F 93 30 67 30 4B 90 7D 54 92 30 組み込んで運命を
|
||
* 01FFF244 C6 99 D5 52 55 30 5B 30 8B 30 6E 30 60 30 02 30 駆動させるのだ。
|
||
* 01FFF254 07 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 ......
|
||
* 01FFF264 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........
|
||
* 01FFF274 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........
|
||
* 01FFF284 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........
|
||
* 01FFF294 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........
|
||
* 01FFF2A4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........
|
||
*
|
||
* Mixed unvoiced text and voiced text list:
|
||
* 01FFF184 00 30 1C 20 DD 52 29 52 1D 20 4B 30 89 30 6F 30 “勝利”からは
|
||
* 01FFF194 03 90 52 30 89 30 8C 30 6A 30 44 30 02 30 07 00 逃げられない。
|
||
* 01FFF1A4 06 00 0A 00 00 30 1C 20 DD 52 29 52 1D 20 4B 30 . “勝利”か
|
||
* 01FFF1B4 89 30 6F 30 03 90 52 30 89 30 8C 30 6A 30 44 30 らは逃げられない
|
||
* 01FFF1C4 02 30 07 00 06 00 0A 00 00 30 1C 20 DD 52 29 52 。. “勝利
|
||
* 01FFF1D4 1D 20 4B 30 89 30 6F 30 03 90 52 30 89 30 8C 30 ”からは逃げられ
|
||
* 01FFF1E4 6A 30 44 30 02 30 07 00 06 00 0A 00 0A 00 07 00 ない。..
|
||
* 01FFF1F4 08 00 76 00 5F 00 76 00 6E 00 64 00 30 00 30 00 v_vnd00
|
||
* 01FFF204 30 00 31 00 00 00 0C 30 6A 30 89 30 70 30 00 25 01.「ならば─
|
||
* 01FFF214 00 25 00 25 00 25 0D 30 07 00 09 00 07 00 06 00 ───」.
|
||
* 01FFF224 0A 00 0A 00 00 30 00 25 00 25 55 30 42 30 01 30 .. ──さあ、
|
||
* 01FFF234 69 30 46 30 59 30 8B 30 4B 30 1F FF 07 00 06 00 どうするか?
|
||
* 01FFF244 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........
|
||
* 01FFF254 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........
|
||
* 01FFF264 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........
|
||
*
|
||
* Sample voiced text:
|
||
*
|
||
* 0269F184 07 00 08 00 76 00 5F 00 7A 00 65 00 70 00 30 00 v_zep0
|
||
* 0269F194 30 00 30 00 31 00 00 00 1C 20 DD 52 29 52 1D 20 001.“勝利”
|
||
* 0269F1A4 68 30 6F 30 01 30 55 4F 60 30 1F FF 07 00 09 00 とは、何だ?.
|
||
* 0269F1B4 07 00 06 00 0A 00 0A 00 07 00 08 00 76 00 5F 00 ..v_
|
||
* 0269F1C4 7A 00 65 00 70 00 30 00 30 00 30 00 32 00 00 00 zep0002.
|
||
* 0269F1D4 1C 20 04 68 49 51 1D 20 68 30 6F 30 01 30 55 4F “栄光”とは、何
|
||
* 0269F1E4 60 30 1F FF 07 00 09 00 07 00 06 00 0A 00 0A 00 だ?...
|
||
* 0269F1F4 07 00 08 00 76 00 5F 00 7A 00 65 00 70 00 30 00 v_zep0
|
||
* 0269F204 30 00 30 00 33 00 00 00 5D 30 8C 30 92 30 97 5F 003.それを得
|
||
* 0269F214 8C 30 70 30 01 30 55 4F 82 30 31 59 8F 30 5A 30 れば、何も失わず
|
||
* 0269F224 6B 30 08 6E 80 30 6E 30 60 30 8D 30 46 30 4B 30 に済むのだろうか
|
||
* 0269F234 07 00 09 00 07 00 06 00 0A 00 0A 00 07 00 08 00 ...
|
||
* 0269F244 76 00 5F 00 7A 00 65 00 70 00 30 00 30 00 30 00 v_zep000
|
||
* 0269F254 34 00 00 00 51 65 48 30 8B 30 6E 30 4B 30 02 30 4.救えるのか。
|
||
* 0269F264 88 5B 8C 30 8B 30 6E 30 4B 30 02 30 2C 67 53 5F 守れるのか。本当
|
||
* 0269F274 6B 30 01 30 78 5E 5B 30 6B 30 6A 30 8C 30 8B 30 に、幸せになれる
|
||
* 0269F284 6E 30 60 30 8D 30 46 30 4B 30 07 00 09 00 07 00 のだろうか.
|
||
* 0269F294 06 00 00 00 00 00 00 00 D1 01 00 00 8C F3 69 02 ...Ǒ.ɩ
|
||
*
|
||
* Ruby:
|
||
*
|
||
* 01FDF2B4 63 30 5F 30 07 00 01 00 14 90 EF 7A 0A 00 68 30 った途端.と
|
||
* 01FDF2C4 5F 30 93 30 00 00 01 30 06 90 6B 30 40 62 09 67 たん.、逆に所有
|
||
*
|
||
* Pause without 0a:
|
||
*
|
||
* 0271F184 07 00 08 00 76 00 5F 00 7A 00 65 00 70 00 30 00 v_zep0
|
||
* 0271F194 30 00 34 00 34 00 00 00 00 30 51 30 8C 30 69 30 044. けれど
|
||
* 0271F1A4 00 25 00 25 07 00 09 00 07 00 06 00 07 00 08 00 ──.
|
||
* 0271F1B4 76 00 5F 00 7A 00 65 00 70 00 30 00 30 00 34 00 v_zep004
|
||
* 0271F1C4 35 00 00 00 5D 30 8C 30 67 30 82 30 01 30 88 5B 5.それでも、守
|
||
* 0271F1D4 89 30 6A 30 51 30 8C 30 70 30 6A 30 89 30 6A 30 らなければならな
|
||
* 0271F1E4 44 30 50 5B 4C 30 FA 51 65 67 5F 30 4B 30 89 30 い子が出来たから
|
||
* 0271F1F4 02 30 07 00 09 00 07 00 06 00 07 00 04 00 00 30 。.
|
||
* 0271F204 07 00 08 00 76 00 5F 00 7A 00 65 00 70 00 30 00 v_zep0
|
||
* 0271F214 30 00 34 00 36 00 00 00 7C 5F 73 59 92 30 51 65 046.彼女を救
|
||
* 0271F224 46 30 5F 30 81 30 6B 30 01 30 53 30 6E 30 61 30 うために、このち
|
||
* 0271F234 63 30 7D 30 51 30 6A 30 7D 54 92 30 F8 61 51 30 っぽけな命を懸け
|
||
* 0271F244 8B 30 68 30 93 8A 63 30 5F 30 02 30 86 30 48 30 ると誓った。ゆえ
|
||
*
|
||
* Scenario caller: 4637bf
|
||
*
|
||
* 0046377D 90 NOP
|
||
* 0046377E 90 NOP
|
||
* 0046377F 90 NOP
|
||
* 00463780 81EC 00080000 SUB ESP,0x800
|
||
* 00463786 56 PUSH ESI
|
||
* 00463787 8BB424 08080000 MOV ESI,DWORD PTR SS:[ESP+0x808]
|
||
* 0046378E 8B46 1C MOV EAX,DWORD PTR DS:[ESI+0x1C]
|
||
* 00463791 8B88 68020000 MOV ECX,DWORD PTR DS:[EAX+0x268]
|
||
* 00463797 57 PUSH EDI
|
||
* 00463798 51 PUSH ECX
|
||
* 00463799 E8 D200FFFF CALL malie.00453870
|
||
* 0046379E 8BBC24 14080000 MOV EDI,DWORD PTR SS:[ESP+0x814]
|
||
* 004637A5 68 C06C4100 PUSH malie.00416CC0
|
||
* 004637AA 8D5424 10 LEA EDX,DWORD PTR SS:[ESP+0x10]
|
||
* 004637AE 57 PUSH EDI
|
||
* 004637AF 52 PUSH EDX
|
||
* 004637B0 E8 AB041F00 CALL malie.00653C60
|
||
* 004637B5 8D4424 18 LEA EAX,DWORD PTR SS:[ESP+0x18]
|
||
* 004637B9 50 PUSH EAX
|
||
* 004637BA E8 21031F00 CALL malie.00653AE0 ; jichi: scenario caller
|
||
* 004637BF 8B4E 1C MOV ECX,DWORD PTR DS:[ESI+0x1C]
|
||
* 004637C2 57 PUSH EDI
|
||
* 004637C3 8981 68020000 MOV DWORD PTR DS:[ECX+0x268],EAX
|
||
* 004637C9 E8 32E61E00 CALL malie.00651E00
|
||
* 004637CE 83C4 18 ADD ESP,0x18
|
||
* 004637D1 33D2 XOR EDX,EDX
|
||
* 004637D3 85C0 TEST EAX,EAX
|
||
* 004637D5 8B46 1C MOV EAX,DWORD PTR DS:[ESI+0x1C]
|
||
* 004637D8 0F9FC2 SETG DL
|
||
* 004637DB 5F POP EDI
|
||
* 004637DC 5E POP ESI
|
||
* 004637DD 8990 7C020000 MOV DWORD PTR DS:[EAX+0x27C],EDX
|
||
* 004637E3 81C4 00080000 ADD ESP,0x800
|
||
* 004637E9 C3 RETN
|
||
* 004637EA 90 NOP
|
||
* 004637EB 90 NOP
|
||
* 004637EC 90 NOP
|
||
*
|
||
* Name caller: 46382e
|
||
*
|
||
* 004637EB 90 NOP
|
||
* 004637EC 90 NOP
|
||
* 004637ED 90 NOP
|
||
* 004637EE 90 NOP
|
||
* 004637EF 90 NOP
|
||
* 004637F0 81EC 00080000 SUB ESP,0x800
|
||
* 004637F6 56 PUSH ESI
|
||
* 004637F7 8BB424 08080000 MOV ESI,DWORD PTR SS:[ESP+0x808]
|
||
* 004637FE 8B46 1C MOV EAX,DWORD PTR DS:[ESI+0x1C]
|
||
* 00463801 8B88 6C020000 MOV ECX,DWORD PTR DS:[EAX+0x26C]
|
||
* 00463807 51 PUSH ECX
|
||
* 00463808 E8 6300FFFF CALL malie.00453870
|
||
* 0046380D 8B9424 10080000 MOV EDX,DWORD PTR SS:[ESP+0x810]
|
||
* 00463814 68 C06C4100 PUSH malie.00416CC0
|
||
* 00463819 52 PUSH EDX
|
||
* 0046381A 8D4424 10 LEA EAX,DWORD PTR SS:[ESP+0x10]
|
||
* 0046381E 50 PUSH EAX
|
||
* 0046381F E8 3C041F00 CALL malie.00653C60
|
||
* 00463824 8D4C24 14 LEA ECX,DWORD PTR SS:[ESP+0x14]
|
||
* 00463828 51 PUSH ECX
|
||
* 00463829 E8 B2021F00 CALL malie.00653AE0 ; jichi: name
|
||
* 0046382E 8B56 1C MOV EDX,DWORD PTR DS:[ESI+0x1C]
|
||
* 00463831 83C4 14 ADD ESP,0x14
|
||
* 00463834 8982 6C020000 MOV DWORD PTR DS:[EDX+0x26C],EAX
|
||
* 0046383A 5E POP ESI
|
||
* 0046383B 81C4 00080000 ADD ESP,0x800
|
||
* 00463841 C3 RETN
|
||
* 00463842 90 NOP
|
||
* 00463843 90 NOP
|
||
* 00463844 90 NOP
|
||
*
|
||
* History caller: 418d0b
|
||
*
|
||
* 00418C9D 90 NOP
|
||
* 00418C9E 90 NOP
|
||
* 00418C9F 90 NOP
|
||
* 00418CA0 81EC 00080000 SUB ESP,0x800
|
||
* 00418CA6 53 PUSH EBX
|
||
* 00418CA7 56 PUSH ESI
|
||
* 00418CA8 57 PUSH EDI
|
||
* 00418CA9 6A 6C PUSH 0x6C
|
||
* 00418CAB FF15 20256900 CALL DWORD PTR DS:[<&MSVCRT.malloc>] ; msvcrt.malloc
|
||
* 00418CB1 8BD8 MOV EBX,EAX
|
||
* 00418CB3 83C4 04 ADD ESP,0x4
|
||
* 00418CB6 85DB TEST EBX,EBX
|
||
* 00418CB8 0F84 D1000000 JE malie.00418D8F
|
||
* 00418CBE 8BB424 10080000 MOV ESI,DWORD PTR SS:[ESP+0x810]
|
||
* 00418CC5 33C0 XOR EAX,EAX
|
||
* 00418CC7 B9 1B000000 MOV ECX,0x1B
|
||
* 00418CCC 8BFB MOV EDI,EBX
|
||
* 00418CCE F3:AB REP STOS DWORD PTR ES:[EDI]
|
||
* 00418CD0 8B06 MOV EAX,DWORD PTR DS:[ESI]
|
||
* 00418CD2 68 C06C4100 PUSH malie.00416CC0
|
||
* 00418CD7 50 PUSH EAX
|
||
* 00418CD8 8D4C24 14 LEA ECX,DWORD PTR SS:[ESP+0x14]
|
||
* 00418CDC 51 PUSH ECX
|
||
* 00418CDD E8 7EAF2300 CALL malie.00653C60
|
||
* 00418CE2 8D5424 18 LEA EDX,DWORD PTR SS:[ESP+0x18]
|
||
* 00418CE6 52 PUSH EDX
|
||
* 00418CE7 E8 F4AD2300 CALL malie.00653AE0
|
||
* 00418CEC 8903 MOV DWORD PTR DS:[EBX],EAX
|
||
* 00418CEE 8B46 04 MOV EAX,DWORD PTR DS:[ESI+0x4]
|
||
* 00418CF1 68 C06C4100 PUSH malie.00416CC0
|
||
* 00418CF6 50 PUSH EAX
|
||
* 00418CF7 8D4C24 24 LEA ECX,DWORD PTR SS:[ESP+0x24]
|
||
* 00418CFB 51 PUSH ECX
|
||
* 00418CFC E8 5FAF2300 CALL malie.00653C60
|
||
* 00418D01 8D5424 28 LEA EDX,DWORD PTR SS:[ESP+0x28]
|
||
* 00418D05 52 PUSH EDX
|
||
* 00418D06 E8 D5AD2300 CALL malie.00653AE0 ; jichi: history caller
|
||
* 00418D0B 8943 04 MOV DWORD PTR DS:[EBX+0x4],EAX
|
||
* 00418D0E 8B46 08 MOV EAX,DWORD PTR DS:[ESI+0x8]
|
||
* 00418D11 83C4 20 ADD ESP,0x20
|
||
* 00418D14 85C0 TEST EAX,EAX
|
||
* 00418D16 75 05 JNZ SHORT malie.00418D1D
|
||
* 00418D18 B8 0CEF7000 MOV EAX,malie.0070EF0C
|
||
* 00418D1D 50 PUSH EAX
|
||
* 00418D1E E8 3D6F2300 CALL malie.0064FC60
|
||
* 00418D23 8943 08 MOV DWORD PTR DS:[EBX+0x8],EAX
|
||
* 00418D26 8B46 0C MOV EAX,DWORD PTR DS:[ESI+0xC]
|
||
* 00418D29 83C4 04 ADD ESP,0x4
|
||
* 00418D2C 85C0 TEST EAX,EAX
|
||
* 00418D2E 75 05 JNZ SHORT malie.00418D35
|
||
* 00418D30 B8 0CEF7000 MOV EAX,malie.0070EF0C
|
||
* 00418D35 50 PUSH EAX
|
||
* 00418D36 E8 256F2300 CALL malie.0064FC60
|
||
* 00418D3B 8943 0C MOV DWORD PTR DS:[EBX+0xC],EAX
|
||
* 00418D3E 8B46 60 MOV EAX,DWORD PTR DS:[ESI+0x60]
|
||
* 00418D41 8943 60 MOV DWORD PTR DS:[EBX+0x60],EAX
|
||
* 00418D44 8B4E 64 MOV ECX,DWORD PTR DS:[ESI+0x64]
|
||
* 00418D47 894B 64 MOV DWORD PTR DS:[EBX+0x64],ECX
|
||
* 00418D4A 8B56 68 MOV EDX,DWORD PTR DS:[ESI+0x68]
|
||
* 00418D4D 8D7E 10 LEA EDI,DWORD PTR DS:[ESI+0x10]
|
||
* 00418D50 83C4 04 ADD ESP,0x4
|
||
* 00418D53 85FF TEST EDI,EDI
|
||
* 00418D55 8953 68 MOV DWORD PTR DS:[EBX+0x68],EDX
|
||
* 00418D58 74 35 JE SHORT malie.00418D8F
|
||
* 00418D5A 55 PUSH EBP
|
||
* 00418D5B 8BEB MOV EBP,EBX
|
||
* 00418D5D 2BEE SUB EBP,ESI
|
||
* 00418D5F BE 14000000 MOV ESI,0x14
|
||
* 00418D64 8B07 MOV EAX,DWORD PTR DS:[EDI]
|
||
* 00418D66 66:8338 00 CMP WORD PTR DS:[EAX],0x0
|
||
* 00418D6A 75 04 JNZ SHORT malie.00418D70
|
||
* 00418D6C 33C0 XOR EAX,EAX
|
||
* 00418D6E EB 09 JMP SHORT malie.00418D79
|
||
* 00418D70 50 PUSH EAX
|
||
* 00418D71 E8 EA6E2300 CALL malie.0064FC60
|
||
* 00418D76 83C4 04 ADD ESP,0x4
|
||
* 00418D79 89042F MOV DWORD PTR DS:[EDI+EBP],EAX
|
||
* 00418D7C 83C7 04 ADD EDI,0x4
|
||
* 00418D7F 4E DEC ESI
|
||
* 00418D80 ^75 E2 JNZ SHORT malie.00418D64
|
||
* 00418D82 5D POP EBP
|
||
* 00418D83 5F POP EDI
|
||
* 00418D84 5E POP ESI
|
||
* 00418D85 8BC3 MOV EAX,EBX
|
||
* 00418D87 5B POP EBX
|
||
* 00418D88 81C4 00080000 ADD ESP,0x800
|
||
* 00418D8E C3 RETN
|
||
* 00418D8F 5F POP EDI
|
||
* 00418D90 5E POP ESI
|
||
* 00418D91 8BC3 MOV EAX,EBX
|
||
* 00418D93 5B POP EBX
|
||
* 00418D94 81C4 00080000 ADD ESP,0x800
|
||
* 00418D9A C3 RETN
|
||
* 00418D9B 90 NOP
|
||
* 00418D9C 90 NOP
|
||
*
|
||
* Exit dialog box caller:
|
||
* 00475A8D 90 NOP
|
||
* 00475A8E 90 NOP
|
||
* 00475A8F 90 NOP
|
||
* 00475A90 56 PUSH ESI
|
||
* 00475A91 68 B09C7500 PUSH malie.00759CB0
|
||
* 00475A96 FF15 F8206900 CALL DWORD PTR DS:[<&KERNEL32.EnterCriti>; ntdll.RtlEnterCriticalSection
|
||
* 00475A9C 8B7424 08 MOV ESI,DWORD PTR SS:[ESP+0x8]
|
||
* 00475AA0 85F6 TEST ESI,ESI
|
||
* 00475AA2 74 4A JE SHORT malie.00475AEE
|
||
* 00475AA4 56 PUSH ESI
|
||
* 00475AA5 E8 56000000 CALL malie.00475B00
|
||
* 00475AAA 8B46 1C MOV EAX,DWORD PTR DS:[ESI+0x1C]
|
||
* 00475AAD 8B08 MOV ECX,DWORD PTR DS:[EAX]
|
||
* 00475AAF 51 PUSH ECX
|
||
* 00475AB0 E8 BBDDFDFF CALL malie.00453870
|
||
* 00475AB5 8B5424 14 MOV EDX,DWORD PTR SS:[ESP+0x14]
|
||
* 00475AB9 52 PUSH EDX
|
||
* 00475ABA E8 21E01D00 CALL malie.00653AE0 ; jichi: called here
|
||
* 00475ABF 8B4E 1C MOV ECX,DWORD PTR DS:[ESI+0x1C]
|
||
* 00475AC2 8901 MOV DWORD PTR DS:[ECX],EAX
|
||
* 00475AC4 8B56 1C MOV EDX,DWORD PTR DS:[ESI+0x1C]
|
||
* 00475AC7 C782 94000000 00>MOV DWORD PTR DS:[EDX+0x94],0x0
|
||
* 00475AD1 8B46 1C MOV EAX,DWORD PTR DS:[ESI+0x1C]
|
||
* 00475AD4 8B08 MOV ECX,DWORD PTR DS:[EAX]
|
||
* 00475AD6 51 PUSH ECX
|
||
* 00475AD7 E8 84C41D00 CALL malie.00651F60
|
||
* 00475ADC 8B56 1C MOV EDX,DWORD PTR DS:[ESI+0x1C]
|
||
* 00475ADF 56 PUSH ESI
|
||
* 00475AE0 8982 98000000 MOV DWORD PTR DS:[EDX+0x98],EAX
|
||
* 00475AE6 E8 C5000000 CALL malie.00475BB0
|
||
* 00475AEB 83C4 14 ADD ESP,0x14
|
||
* 00475AEE 68 B09C7500 PUSH malie.00759CB0
|
||
* 00475AF3 FF15 44226900 CALL DWORD PTR DS:[<&KERNEL32.LeaveCriti>; ntdll.RtlLeaveCriticalSection
|
||
* 00475AF9 5E POP ESI
|
||
* 00475AFA C3 RETN
|
||
* 00475AFB 90 NOP
|
||
* 00475AFC 90 NOP
|
||
* 00475AFD 90 NOP
|
||
*
|
||
* Sample game: 相州戦神館學園 八命陣 (older game0
|
||
* Scenario caller: 46314f
|
||
*
|
||
* 0046310B 90 NOP
|
||
* 0046310C 90 NOP
|
||
* 0046310D 90 NOP
|
||
* 0046310E 90 NOP
|
||
* 0046310F 90 NOP
|
||
* 00463110 81EC 00080000 SUB ESP,0x800
|
||
* 00463116 56 PUSH ESI
|
||
* 00463117 8BB424 08080000 MOV ESI,DWORD PTR SS:[ESP+0x808]
|
||
* 0046311E 8B46 20 MOV EAX,DWORD PTR DS:[ESI+0x20]
|
||
* 00463121 8B88 68020000 MOV ECX,DWORD PTR DS:[EAX+0x268]
|
||
* 00463127 57 PUSH EDI
|
||
* 00463128 51 PUSH ECX
|
||
* 00463129 E8 62240200 CALL .00485590
|
||
* 0046312E 8BBC24 14080000 MOV EDI,DWORD PTR SS:[ESP+0x814]
|
||
* 00463135 68 10634100 PUSH .00416310
|
||
* 0046313A 8D5424 10 LEA EDX,DWORD PTR SS:[ESP+0x10]
|
||
* 0046313E 57 PUSH EDI
|
||
* 0046313F 52 PUSH EDX
|
||
* 00463140 E8 AB841D00 CALL .0063B5F0
|
||
* 00463145 8D4424 18 LEA EAX,DWORD PTR SS:[ESP+0x18]
|
||
* 00463149 50 PUSH EAX
|
||
* 0046314A E8 41831D00 CALL .0063B490
|
||
* 0046314F 8B4E 20 MOV ECX,DWORD PTR DS:[ESI+0x20] ; jichi: scenario retaddr
|
||
* 00463152 57 PUSH EDI
|
||
* 00463153 8981 68020000 MOV DWORD PTR DS:[ECX+0x268],EAX
|
||
* 00463159 E8 82661D00 CALL .006397E0
|
||
* 0046315E 83C4 18 ADD ESP,0x18
|
||
* 00463161 33D2 XOR EDX,EDX
|
||
* 00463163 85C0 TEST EAX,EAX
|
||
* 00463165 8B46 20 MOV EAX,DWORD PTR DS:[ESI+0x20]
|
||
* 00463168 0F9FC2 SETG DL
|
||
* 0046316B 5F POP EDI
|
||
* 0046316C 5E POP ESI
|
||
* 0046316D 8990 7C020000 MOV DWORD PTR DS:[EAX+0x27C],EDX
|
||
* 00463173 81C4 00080000 ADD ESP,0x800
|
||
* 00463179 C3 RETN
|
||
* 0046317A 90 NOP
|
||
* 0046317B 90 NOP
|
||
* 0046317C 90 NOP
|
||
* 0046317D 90 NOP
|
||
* 0046317E 90 NOP
|
||
*
|
||
* Sample game: BRAVA!!
|
||
* Scenario retaddr: 42011f
|
||
*
|
||
* 004200FD 90 NOP
|
||
* 004200FE 90 NOP
|
||
* 004200FF 90 NOP
|
||
* 00420100 56 PUSH ESI
|
||
* 00420101 8B7424 08 MOV ESI,DWORD PTR SS:[ESP+0x8]
|
||
* 00420105 8B46 20 MOV EAX,DWORD PTR DS:[ESI+0x20]
|
||
* 00420108 8B88 F0000000 MOV ECX,DWORD PTR DS:[EAX+0xF0]
|
||
* 0042010E 57 PUSH EDI
|
||
* 0042010F 51 PUSH ECX
|
||
* 00420110 E8 BB240200 CALL .004425D0
|
||
* 00420115 8B7C24 14 MOV EDI,DWORD PTR SS:[ESP+0x14]
|
||
* 00420119 57 PUSH EDI
|
||
* 0042011A E8 01031300 CALL .00550420
|
||
* 0042011F 8B56 20 MOV EDX,DWORD PTR DS:[ESI+0x20] ; jichi: scenario caller
|
||
* 00420122 57 PUSH EDI
|
||
* 00420123 8982 F0000000 MOV DWORD PTR DS:[EDX+0xF0],EAX
|
||
* 00420129 E8 B2E61200 CALL .0054E7E0
|
||
* 0042012E 8B56 20 MOV EDX,DWORD PTR DS:[ESI+0x20]
|
||
* 00420131 83C4 0C ADD ESP,0xC
|
||
* 00420134 33C9 XOR ECX,ECX
|
||
* 00420136 85C0 TEST EAX,EAX
|
||
* 00420138 0F9FC1 SETG CL
|
||
* 0042013B 5F POP EDI
|
||
* 0042013C 5E POP ESI
|
||
* 0042013D 898A FC000000 MOV DWORD PTR DS:[EDX+0xFC],ECX
|
||
* 00420143 C3 RETN
|
||
* 00420144 90 NOP
|
||
*
|
||
* Name retaddr: 415a2c
|
||
*
|
||
* 004159DD 90 NOP
|
||
* 004159DE 90 NOP
|
||
* 004159DF 90 NOP
|
||
* 004159E0 81EC 00080000 SUB ESP,0x800
|
||
* 004159E6 53 PUSH EBX
|
||
* 004159E7 56 PUSH ESI
|
||
* 004159E8 57 PUSH EDI
|
||
* 004159E9 6A 6C PUSH 0x6C
|
||
* 004159EB FF15 40D45800 CALL DWORD PTR DS:[0x58D440] ; msvcrt.malloc
|
||
* 004159F1 8BD8 MOV EBX,EAX
|
||
* 004159F3 83C4 04 ADD ESP,0x4
|
||
* 004159F6 85DB TEST EBX,EBX
|
||
* 004159F8 0F84 D1000000 JE .00415ACF
|
||
* 004159FE 8BB424 10080000 MOV ESI,DWORD PTR SS:[ESP+0x810]
|
||
* 00415A05 33C0 XOR EAX,EAX
|
||
* 00415A07 B9 1B000000 MOV ECX,0x1B
|
||
* 00415A0C 8BFB MOV EDI,EBX
|
||
* 00415A0E F3:AB REP STOS DWORD PTR ES:[EDI]
|
||
* 00415A10 8B06 MOV EAX,DWORD PTR DS:[ESI]
|
||
* 00415A12 68 003B4100 PUSH .00413B00
|
||
* 00415A17 50 PUSH EAX
|
||
* 00415A18 8D4C24 14 LEA ECX,DWORD PTR SS:[ESP+0x14]
|
||
* 00415A1C 51 PUSH ECX
|
||
* 00415A1D E8 5EAB1300 CALL .00550580
|
||
* 00415A22 8D5424 18 LEA EDX,DWORD PTR SS:[ESP+0x18]
|
||
* 00415A26 52 PUSH EDX
|
||
* 00415A27 E8 F4A91300 CALL .00550420
|
||
* 00415A2C 8903 MOV DWORD PTR DS:[EBX],EAX ; jichi: name caller
|
||
* 00415A2E 8B46 04 MOV EAX,DWORD PTR DS:[ESI+0x4]
|
||
* 00415A31 68 003B4100 PUSH .00413B00
|
||
* 00415A36 50 PUSH EAX
|
||
* 00415A37 8D4C24 24 LEA ECX,DWORD PTR SS:[ESP+0x24]
|
||
* 00415A3B 51 PUSH ECX
|
||
* 00415A3C E8 3FAB1300 CALL .00550580
|
||
* 00415A41 8D5424 28 LEA EDX,DWORD PTR SS:[ESP+0x28]
|
||
* 00415A45 52 PUSH EDX
|
||
* 00415A46 E8 D5A91300 CALL .00550420
|
||
* 00415A4B 8943 04 MOV DWORD PTR DS:[EBX+0x4],EAX
|
||
* 00415A4E 8B46 08 MOV EAX,DWORD PTR DS:[ESI+0x8]
|
||
* 00415A51 83C4 20 ADD ESP,0x20
|
||
* 00415A54 85C0 TEST EAX,EAX
|
||
* 00415A56 75 05 JNZ SHORT .00415A5D
|
||
* 00415A58 B8 6C285E00 MOV EAX,.005E286C
|
||
* 00415A5D 50 PUSH EAX
|
||
* 00415A5E E8 DD691300 CALL .0054C440
|
||
* 00415A63 8943 08 MOV DWORD PTR DS:[EBX+0x8],EAX
|
||
* 00415A66 8B46 0C MOV EAX,DWORD PTR DS:[ESI+0xC]
|
||
* 00415A69 83C4 04 ADD ESP,0x4
|
||
* 00415A6C 85C0 TEST EAX,EAX
|
||
* 00415A6E 75 05 JNZ SHORT .00415A75
|
||
* 00415A70 B8 6C285E00 MOV EAX,.005E286C
|
||
* 00415A75 50 PUSH EAX
|
||
* 00415A76 E8 C5691300 CALL .0054C440
|
||
* 00415A7B 8943 0C MOV DWORD PTR DS:[EBX+0xC],EAX
|
||
* 00415A7E 8B46 60 MOV EAX,DWORD PTR DS:[ESI+0x60]
|
||
* 00415A81 8943 60 MOV DWORD PTR DS:[EBX+0x60],EAX
|
||
* 00415A84 8B4E 64 MOV ECX,DWORD PTR DS:[ESI+0x64]
|
||
* 00415A87 894B 64 MOV DWORD PTR DS:[EBX+0x64],ECX
|
||
* 00415A8A 8B56 68 MOV EDX,DWORD PTR DS:[ESI+0x68]
|
||
* 00415A8D 8D7E 10 LEA EDI,DWORD PTR DS:[ESI+0x10]
|
||
* 00415A90 83C4 04 ADD ESP,0x4
|
||
* 00415A93 85FF TEST EDI,EDI
|
||
* 00415A95 8953 68 MOV DWORD PTR DS:[EBX+0x68],EDX
|
||
* 00415A98 74 35 JE SHORT .00415ACF
|
||
* 00415A9A 55 PUSH EBP
|
||
* 00415A9B 8BEB MOV EBP,EBX
|
||
* 00415A9D 2BEE SUB EBP,ESI
|
||
* 00415A9F BE 14000000 MOV ESI,0x14
|
||
* 00415AA4 8B07 MOV EAX,DWORD PTR DS:[EDI]
|
||
* 00415AA6 66:8338 00 CMP WORD PTR DS:[EAX],0x0
|
||
* 00415AAA 75 04 JNZ SHORT .00415AB0
|
||
* 00415AAC 33C0 XOR EAX,EAX
|
||
* 00415AAE EB 09 JMP SHORT .00415AB9
|
||
* 00415AB0 50 PUSH EAX
|
||
* 00415AB1 E8 8A691300 CALL .0054C440
|
||
* 00415AB6 83C4 04 ADD ESP,0x4
|
||
* 00415AB9 89042F MOV DWORD PTR DS:[EDI+EBP],EAX
|
||
* 00415ABC 83C7 04 ADD EDI,0x4
|
||
* 00415ABF 4E DEC ESI
|
||
* 00415AC0 ^75 E2 JNZ SHORT .00415AA4
|
||
* 00415AC2 5D POP EBP
|
||
* 00415AC3 5F POP EDI
|
||
* 00415AC4 5E POP ESI
|
||
* 00415AC5 8BC3 MOV EAX,EBX
|
||
* 00415AC7 5B POP EBX
|
||
* 00415AC8 81C4 00080000 ADD ESP,0x800
|
||
* 00415ACE C3 RETN
|
||
* 00415ACF 5F POP EDI
|
||
* 00415AD0 5E POP ESI
|
||
* 00415AD1 8BC3 MOV EAX,EBX
|
||
* 00415AD3 5B POP EBX
|
||
* 00415AD4 81C4 00080000 ADD ESP,0x800
|
||
* 00415ADA C3 RETN
|
||
* 00415ADB 90 NOP
|
||
* 00415ADC 90 NOP
|
||
* 00415ADD 90 NOP
|
||
* 00415ADE 90 NOP
|
||
*/
|
||
|
||
|
||
|
||
size_t parseTextSize(LPCWSTR text)
|
||
{
|
||
size_t count = 0;
|
||
bool skipNull = false;
|
||
for (; *text || skipNull; text++, count++)
|
||
if (text[0] == 0)
|
||
skipNull = false;
|
||
else if (text[0] == 0x7)
|
||
switch (text[1]) {
|
||
case 0x1: // ruby
|
||
skipNull = true;
|
||
break;
|
||
case 0x8: // voice
|
||
return count;
|
||
case 0x6: // pause
|
||
return count + 2;
|
||
}
|
||
return count;
|
||
}
|
||
|
||
size_t rtrim(LPCWSTR text, size_t size)
|
||
{
|
||
while (size && (text[size - 1] <= 32 || text[size - 1] == 0x3000)) // trim trailing non-printable characters
|
||
size--;
|
||
return size;
|
||
}
|
||
|
||
std::string parseTextData(LPCWSTR text)
|
||
{
|
||
std::string ret;
|
||
if (!wcschr(text, 0x7)) {
|
||
ret=std::string((LPCSTR)text, ::wcslen(text) * sizeof(wchar_t));
|
||
return ret;
|
||
}
|
||
for (; *text; text++) {
|
||
if (text[0] == 0x7)
|
||
switch (text[1]) {
|
||
case 0x1: // ruby
|
||
if (LPCWSTR p = ::wcschr(text + 2, 0xa)) {
|
||
ret.append(LPCSTR(text + 2), (p - text - 2) * sizeof(wchar_t));
|
||
text = p + ::wcslen(p); // text now point to zero
|
||
continue;
|
||
} // mismatched ruby that should never happen
|
||
return std::string();
|
||
case 0x8: // voice
|
||
return ret;
|
||
case 0x6: // pause
|
||
ret.append((LPCSTR)text, 2 * sizeof(wchar_t));
|
||
return ret;
|
||
}
|
||
ret.append((LPCSTR)text, sizeof(wchar_t));
|
||
}
|
||
return ret;
|
||
}
|
||
#define MALIE_0 L"[0]" // represent \0
|
||
void filterTextData(std::string &text)
|
||
{
|
||
// remove short pause
|
||
static std::string shortPause((LPCSTR)L"\x07\x04", 2 * sizeof(wchar_t));
|
||
//text.replace(shortPause, ""); // there is no remove method in std::string
|
||
strReplace(text, shortPause, "");
|
||
}
|
||
// I need a cache retainer here to make sure same text result in same result
|
||
void hookafter(hook_stack*s,void* data1, size_t len)
|
||
{
|
||
static std::string data_;
|
||
static std::unordered_set<uint64_t> hashes_;
|
||
auto text = (LPCWSTR)s->stack[1];
|
||
if (!text || !*text
|
||
|| !(text[0] == 0x7 && text[1] == 0x8) && all_ascii(text) )
|
||
return ;
|
||
std::string data;
|
||
bool update = false;
|
||
|
||
for (size_t size; *text; text += size) {
|
||
if (text[0] == 0x7 && text[1] == 0x8) { // voiced
|
||
size_t len = ::wcslen(text);
|
||
data.append((LPCSTR)text, (len + 1) * sizeof(wchar_t));
|
||
text += len + 1;
|
||
}
|
||
|
||
size = parseTextSize(text);
|
||
std::string oldData = parseTextData(text);
|
||
filterTextData(oldData);
|
||
if (oldData.empty()) // this should never happen
|
||
return ;
|
||
|
||
auto oldTextAddress = (LPCWSTR)oldData.c_str();
|
||
size_t oldTextSize = oldData.size() / sizeof(wchar_t),
|
||
trimmedSize = rtrim(oldTextAddress, oldTextSize);
|
||
if (trimmedSize == 0 || all_ascii(oldTextAddress, trimmedSize))
|
||
data.append(oldData);
|
||
else {
|
||
std::wstring oldText = std::wstring(oldTextAddress, trimmedSize),
|
||
newText = std::wstring((LPWSTR)data1,len/2) ;
|
||
if (newText.empty() || newText == oldText)
|
||
data.append(oldData);
|
||
else {
|
||
update = true;
|
||
data.append((LPCSTR)newText.c_str(), newText.size() * sizeof(wchar_t));
|
||
if (trimmedSize != oldTextSize)
|
||
data.append(LPCSTR(oldTextAddress + trimmedSize), (oldTextSize - trimmedSize) * sizeof(wchar_t));
|
||
}
|
||
}
|
||
}
|
||
if (update) {
|
||
{
|
||
static const std::string zero_bytes(sizeof(wchar_t), '\0'),
|
||
zero_repr((LPCSTR)MALIE_0, sizeof(MALIE_0) - sizeof(wchar_t)); // - \0's size
|
||
//data.replace(zero_repr, zero_bytes);
|
||
strReplace(data, zero_repr, zero_bytes);
|
||
}
|
||
|
||
// make sure there are 5 zeros at the end
|
||
data.push_back(0); data.push_back(0); data.push_back(0); data.push_back(0); data.push_back(0);
|
||
data_ = data;
|
||
text = (LPCWSTR)data_.c_str();
|
||
|
||
s->stack[1] = (ULONG)text;
|
||
}
|
||
}
|
||
bool hookBefore(hook_stack*s,void* data1, size_t* len,uintptr_t*role)
|
||
{
|
||
|
||
static std::string data_;
|
||
static std::unordered_set<uint64_t> hashes_;
|
||
auto text = (LPCWSTR)s->stack[1];
|
||
if (!text || !*text
|
||
|| !(text[0] == 0x7 && text[1] == 0x8) && all_ascii(text) )
|
||
return false;
|
||
|
||
//if (::wcsstr(text, L"\x30DC\x30BF\x30F3")) // ボタン
|
||
// return true;
|
||
//if (::wcsstr(text, L"\x30A4\x30E1\x30FC")) // イメージ
|
||
// return true;
|
||
|
||
// Scenario caller:
|
||
// 004637BA E8 21031F00 CALL malie.00653AE0 ; jichi: scenario caller
|
||
// 004637BF 8B4E 1C MOV ECX,DWORD PTR DS:[ESI+0x1C]
|
||
// 004637C2 57 PUSH EDI
|
||
//
|
||
// 0046314A E8 41831D00 CALL .0063B490
|
||
// 0046314F 8B4E 20 MOV ECX,DWORD PTR DS:[ESI+0x20] ; jichi: scenario retaddr
|
||
// 00463152 57 PUSH EDI
|
||
//
|
||
// (balloon-like)
|
||
// 0042011F 8B56 20 MOV EDX,DWORD PTR DS:[ESI+0x20] ; jichi: scenario caller
|
||
// 00420122 57 PUSH EDI
|
||
//
|
||
// Name caller:
|
||
// 00463829 E8 B2021F00 CALL malie.00653AE0 ; jichi: name
|
||
// 0046382E 8B56 1C MOV EDX,DWORD PTR DS:[ESI+0x1C]
|
||
// 00463831 83C4 14 ADD ESP,0x14
|
||
//
|
||
// (balloon-like)
|
||
// 00415A2C 8903 MOV DWORD PTR DS:[EBX],EAX ; jichi: name caller
|
||
// 00415A2E 8B46 04 MOV EAX,DWORD PTR DS:[ESI+0x4]
|
||
// 00415A31 68 003B4100 PUSH .00413B00
|
||
* role = Engine::OtherRole;
|
||
auto retaddr = s->stack[0];
|
||
switch (*(DWORD *)retaddr & 0xff0000ff) {
|
||
case 0x5700008b: *role = Engine::ScenarioRole; break;
|
||
case 0x8300008b:
|
||
case 0x46000089: *role = Engine::NameRole; break;
|
||
}
|
||
//auto sig = Engine::hashThreadSignature(role, retaddr); // this is not needed as the retaddr is used as split
|
||
auto sig = retaddr;
|
||
|
||
std::string data;
|
||
bool update = false;
|
||
|
||
for (size_t size; *text; text += size) {
|
||
if (text[0] == 0x7 && text[1] == 0x8) { // voiced
|
||
size_t len = ::wcslen(text);
|
||
data.append((LPCSTR)text, (len + 1) * sizeof(wchar_t));
|
||
text += len + 1;
|
||
}
|
||
|
||
size = parseTextSize(text);
|
||
std::string oldData = parseTextData(text);
|
||
filterTextData(oldData);
|
||
if (oldData.empty()) // this should never happen
|
||
return false;
|
||
|
||
auto oldTextAddress = (LPCWSTR)oldData.c_str();
|
||
size_t oldTextSize = oldData.size() / sizeof(wchar_t),
|
||
trimmedSize = rtrim(oldTextAddress, oldTextSize);
|
||
if (trimmedSize == 0 || all_ascii(oldTextAddress, trimmedSize))
|
||
data.append(oldData);
|
||
else {
|
||
std::wstring oldText = std::wstring(oldTextAddress, trimmedSize);
|
||
write_string_overwrite(data1,len,oldText);
|
||
update=true;
|
||
}
|
||
}
|
||
|
||
return update;
|
||
}
|
||
} // namespace Private
|
||
|
||
/**
|
||
* Sample game: シルヴァリオ ヴェンデッタ
|
||
*
|
||
* Text in arg1.
|
||
* Function found by debugging the text being accessed.
|
||
* It is the same as one of the parent call of Malie2.
|
||
*
|
||
* The target text arg1 is on this function's caller's stack.
|
||
*
|
||
* 00653ADC 90 NOP
|
||
* 00653ADD 90 NOP
|
||
* 00653ADE 90 NOP
|
||
* 00653ADF 90 NOP
|
||
* 00653AE0 56 PUSH ESI
|
||
* 00653AE1 8B7424 08 MOV ESI,DWORD PTR SS:[ESP+0x8]
|
||
* 00653AE5 33C0 XOR EAX,EAX
|
||
* 00653AE7 85F6 TEST ESI,ESI
|
||
* 00653AE9 74 47 JE SHORT malie.00653B32
|
||
* 00653AEB 53 PUSH EBX
|
||
* 00653AEC 57 PUSH EDI
|
||
* 00653AED 68 00C47F00 PUSH malie.007FC400
|
||
* 00653AF2 FF15 F8206900 CALL DWORD PTR DS:[<&KERNEL32.EnterCriti>; ntdll.RtlEnterCriticalSection
|
||
* 00653AF8 56 PUSH ESI
|
||
* 00653AF9 E8 C2E4FFFF CALL malie.00651FC0
|
||
* 00653AFE 8D78 02 LEA EDI,DWORD PTR DS:[EAX+0x2]
|
||
* 00653B01 57 PUSH EDI
|
||
* 00653B02 FF15 20256900 CALL DWORD PTR DS:[<&MSVCRT.malloc>] ; msvcrt.malloc
|
||
* 00653B08 8BD8 MOV EBX,EAX
|
||
* 00653B0A 83C4 08 ADD ESP,0x8
|
||
* 00653B0D 85DB TEST EBX,EBX
|
||
* 00653B0F 74 12 JE SHORT malie.00653B23
|
||
* 00653B11 8BCF MOV ECX,EDI
|
||
* 00653B13 8BFB MOV EDI,EBX
|
||
* 00653B15 8BC1 MOV EAX,ECX
|
||
* 00653B17 C1E9 02 SHR ECX,0x2
|
||
* 00653B1A F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
|
||
* 00653B1C 8BC8 MOV ECX,EAX
|
||
* 00653B1E 83E1 03 AND ECX,0x3
|
||
* 00653B21 F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
|
||
* 00653B23 68 00C47F00 PUSH malie.007FC400
|
||
* 00653B28 FF15 44226900 CALL DWORD PTR DS:[<&KERNEL32.LeaveCriti>; ntdll.RtlLeaveCriticalSection
|
||
* 00653B2E 8BC3 MOV EAX,EBX
|
||
* 00653B30 5F POP EDI
|
||
* 00653B31 5B POP EBX
|
||
* 00653B32 5E POP ESI
|
||
* 00653B33 C3 RETN
|
||
* 00653B34 90 NOP
|
||
* 00653B35 90 NOP
|
||
* 00653B36 90 NOP
|
||
* 00653B37 90 NOP
|
||
* 00653B38 90 NOP
|
||
*
|
||
* Malie2's pattern: 4089560833d2894604
|
||
*
|
||
* const BYTE bytes1[] = {
|
||
* 0x40, // inc eax
|
||
* 0x89,0x56, 0x08, // mov dword ptr ds:[esi+0x8],edx
|
||
* 0x33,0xd2, // xor edx,edx
|
||
* 0x89,0x46, 0x04 // mov dword ptr ds:[esi+0x4],eax
|
||
* };
|
||
*
|
||
* Malie2 not used as it produces too many garbage
|
||
*
|
||
* Malie2's call stack:
|
||
*
|
||
* 026DF0D8 026DF0E0
|
||
* 026DF0DC 026DF184 ; jichi: source text
|
||
* 026DF0E0 026DF184
|
||
* 026DF0E4 00000000
|
||
* 026DF0E8 000000B8
|
||
* 026DF0EC 0627DFE8
|
||
* 026DF0F0 016F0000
|
||
* 026DF0F4 0627DFE0
|
||
* 026DF0F8 0180B5E0
|
||
* 026DF0FC 00000001
|
||
* 026DF100 0180B8F0 ASCII ""=VH"
|
||
* 026DF104 /026DF11C
|
||
* 026DF108 |77492CE8 RETURN to ntdll.77492CE8 from ntdll.77492D0B
|
||
* 026DF10C |0180B8F8
|
||
* 026DF110 |FFFFFFFF
|
||
* 026DF114 |04A9103C
|
||
* 026DF118 |0180B8F0 ASCII ""=VH"
|
||
* 026DF11C \026DF168
|
||
* 026DF120 771B98CD RETURN to msvcrt.771B98CD from ntdll.RtlFreeHeap
|
||
* 026DF124 018B0000
|
||
* 026DF128 00000000
|
||
* 026DF12C 00000006
|
||
* 026DF130 FFFFFFFF
|
||
* 026DF134 FFFFFFFF
|
||
* 026DF138 00000000
|
||
* 026DF13C 026DF184 ; jichi: text
|
||
* 026DF140 0000000C
|
||
* 026DF144 062671D8
|
||
* 026DF148 00000000
|
||
* 026DF14C /026DFA08
|
||
* 026DF150 |00653AFE RETURN to malie.00653AFE from malie.00651FC0
|
||
* 026DF154 |026DF184 ; jichi: text
|
||
* 026DF158 |007272A8 malie.007272A8
|
||
* 026DF15C |04A9103C
|
||
* 026DF160 |0183DFE8
|
||
* 026DF164 |004637BF RETURN to malie.004637BF from malie.00653AE0
|
||
* 026DF168 |026DF184 ; jichi: text, two continous scenario text
|
||
* 026DF16C |026DF184 ; jichi: text
|
||
* 026DF170 |007272A8 malie.007272A8
|
||
* 026DF174 |00416CC0 malie.00416CC0
|
||
* 026DF178 |0180B8F8
|
||
* 026DF17C |FFFFFFFF
|
||
* 026DF180 |0183DFE8
|
||
* 026DF184 |00080007
|
||
* 026DF188 |005F0076 malie.005F0076
|
||
* 026DF18C |0065007A malie.0065007A
|
||
* 026DF190 |00300070
|
||
* 026DF194 |00300030
|
||
*
|
||
* Sample game: 相州戦神館學園 八命陣 (older game without critical sections)
|
||
* 0063B48D 90 NOP
|
||
* 0063B48E 90 NOP
|
||
* 0063B48F 90 NOP
|
||
* 0063B490 56 PUSH ESI
|
||
* 0063B491 8B7424 08 MOV ESI,DWORD PTR SS:[ESP+0x8]
|
||
* 0063B495 33C0 XOR EAX,EAX
|
||
* 0063B497 57 PUSH EDI
|
||
* 0063B498 85F6 TEST ESI,ESI
|
||
* 0063B49A 74 29 JE SHORT .0063B4C5
|
||
* 0063B49C 56 PUSH ESI
|
||
* 0063B49D E8 FEE4FFFF CALL .006399A0
|
||
* 0063B4A2 8D78 02 LEA EDI,DWORD PTR DS:[EAX+0x2]
|
||
* 0063B4A5 57 PUSH EDI
|
||
* 0063B4A6 FF15 94946700 CALL DWORD PTR DS:[0x679494] ; msvcrt.malloc
|
||
* 0063B4AC 83C4 08 ADD ESP,0x8
|
||
* 0063B4AF 85C0 TEST EAX,EAX
|
||
* 0063B4B1 74 12 JE SHORT .0063B4C5
|
||
* 0063B4B3 8BCF MOV ECX,EDI
|
||
* 0063B4B5 8BF8 MOV EDI,EAX
|
||
* 0063B4B7 8BD1 MOV EDX,ECX
|
||
* 0063B4B9 C1E9 02 SHR ECX,0x2
|
||
* 0063B4BC F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
|
||
* 0063B4BE 8BCA MOV ECX,EDX
|
||
* 0063B4C0 83E1 03 AND ECX,0x3
|
||
* 0063B4C3 F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
|
||
* 0063B4C5 5F POP EDI
|
||
* 0063B4C6 5E POP ESI
|
||
* 0063B4C7 C3 RETN
|
||
* 0063B4C8 90 NOP
|
||
* 0063B4C9 90 NOP
|
||
* 0063B4CA 90 NOP
|
||
* 0063B4CB 90 NOP
|
||
*
|
||
* Sample game: 神咒神威神楽WEB体験版
|
||
* FIXME: Texts get disappeared
|
||
* 00517A8D 90 NOP
|
||
* 00517A8E 90 NOP
|
||
* 00517A8F 90 NOP
|
||
* 00517A90 56 PUSH ESI
|
||
* 00517A91 8B7424 08 MOV ESI,DWORD PTR SS:[ESP+0x8]
|
||
* 00517A95 57 PUSH EDI
|
||
* 00517A96 56 PUSH ESI
|
||
* 00517A97 E8 64E5FFFF CALL .00516000
|
||
* 00517A9C 8D78 02 LEA EDI,DWORD PTR DS:[EAX+0x2]
|
||
* 00517A9F 57 PUSH EDI
|
||
* 00517AA0 FF15 40745500 CALL DWORD PTR DS:[0x557440] ; msvcrt.malloc
|
||
* 00517AA6 83C4 08 ADD ESP,0x8
|
||
* 00517AA9 85C0 TEST EAX,EAX
|
||
* 00517AAB 74 12 JE SHORT .00517ABF
|
||
* 00517AAD 8BCF MOV ECX,EDI
|
||
* 00517AAF 8BF8 MOV EDI,EAX
|
||
* 00517AB1 8BD1 MOV EDX,ECX
|
||
* 00517AB3 C1E9 02 SHR ECX,0x2
|
||
* 00517AB6 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>
|
||
* 00517AB8 8BCA MOV ECX,EDX
|
||
* 00517ABA 83E1 03 AND ECX,0x3
|
||
* 00517ABD F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
|
||
* 00517ABF 5F POP EDI
|
||
* 00517AC0 5E POP ESI
|
||
* 00517AC1 C3 RETN
|
||
* 00517AC2 90 NOP
|
||
* 00517AC3 90 NOP
|
||
* 00517AC4 90 NOP
|
||
*/
|
||
bool attach(ULONG startAddress, ULONG stopAddress)
|
||
{
|
||
const uint8_t bytes[] = {
|
||
//FF15 20256900 // 00653B02 FF15 20256900 CALL DWORD PTR DS:[<&MSVCRT.malloc>] ; msvcrt.malloc
|
||
//8BD8 // 00653B08 8BD8 MOV EBX,EAX
|
||
0x83,0xC4, 0x08, // 00653B0A 83C4 08 ADD ESP,0x8
|
||
0x85,XX, // 00653B0D 85DB TEST EBX,EBX
|
||
0x74, 0x12, // 00653B0F 74 12 JE SHORT malie.00653B23
|
||
0x8B,XX, // 00653B11 8BCF MOV ECX,EDI
|
||
0x8B,XX, // 00653B13 8BFB MOV EDI,EBX
|
||
0x8B,XX, // 00653B15 8BC1 MOV EAX,ECX
|
||
0xC1,0xE9, 0x02, // 00653B17 C1E9 02 SHR ECX,0x2
|
||
0xF3,0xA5, // 00653B1A F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
|
||
0x8B,XX, // 00653B1C 8BC8 MOV ECX,EAX
|
||
0x83,0xE1, 0x03, // 00653B1E 83E1 03 AND ECX,0x3
|
||
0xF3,0xA4 // 00653B21 F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
|
||
};
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
||
//DOUT(addr);
|
||
if (!addr)
|
||
return false;
|
||
addr = MemDbg::findEnclosingAlignedFunction(addr);
|
||
if (!addr)
|
||
return false;
|
||
//addr = 0x00653AE0; // the actual hooked grant parent call function, text in arg1
|
||
|
||
// Sample game: シルヴァリオ ヴェンデッタ
|
||
// If there are untranslated function, hook to the following location and debug the function stack to find text address
|
||
//addr = 0x006519B0; // the callee function, text in arg2, function called by two functions, including the callee. Hooking to this function causing history to crash
|
||
//return winhook::hook_before(addr, Private::hookBefore);
|
||
HookParam hp;
|
||
hp.address=addr;
|
||
hp.hook_before=Private::hookBefore;
|
||
hp.hook_after=Private::hookafter;
|
||
hp.type=CODEC_UTF16|EMBED_ABLE;
|
||
return NewHook(hp,"EmbedMalie");
|
||
}
|
||
} // namespace ScenarioHook
|
||
|
||
namespace Patch {
|
||
namespace Private {
|
||
bool hookBefore(hook_stack*s,void* data1, size_t* len,uintptr_t*role)
|
||
{
|
||
static std::wstring fontFace_;
|
||
auto fontFamily=std::wstring(embedsharedmem->fontFamily);
|
||
|
||
if (!fontFamily.empty()) {
|
||
if (fontFace_ != fontFamily)
|
||
fontFace_ = fontFamily;
|
||
s->stack[1] = (ULONG)fontFace_.c_str();
|
||
//::memcpy((LPVOID)s->stack[2], fontFace_.utf16(), fontFace_.size() * sizeof(wchar_t));
|
||
}
|
||
return false;
|
||
}
|
||
} // namespace Private
|
||
|
||
/**
|
||
* Sample game: シルヴァリオ ヴェンデッタ
|
||
* Force changing font face, otherwise CreateFontIndirectW won't be invoked.
|
||
*
|
||
* Default font is TelopMinPro.
|
||
*
|
||
* There are two fonts that are needed to be changed for Malie engine.
|
||
* - Text font: can be changed in registry as "FontFace"
|
||
* - UI font: canb be changed in malie.ini using SystemFont
|
||
* Example:
|
||
*
|
||
* ;フォント種類指定
|
||
* ;SystemFont=SimSun
|
||
* ;FONT01=SimSun
|
||
* SystemFont=TelopMinPro
|
||
* FONT01=TelopMinPro
|
||
*
|
||
* This function is found by debugging CreateFontIndirectW.
|
||
* Font face in both arg1 and arg2.
|
||
*
|
||
* 0043A82C 90 NOP
|
||
* 0043A82D 90 NOP
|
||
* 0043A82E 90 NOP
|
||
* 0043A82F 90 NOP
|
||
* 0043A830 53 PUSH EBX
|
||
* 0043A831 55 PUSH EBP
|
||
* 0043A832 56 PUSH ESI
|
||
* 0043A833 57 PUSH EDI
|
||
* 0043A834 E8 C7FFFFFF CALL malie.0043A800
|
||
* 0043A839 8BF8 MOV EDI,EAX
|
||
* 0043A83B 33F6 XOR ESI,ESI
|
||
* 0043A83D 85FF TEST EDI,EDI
|
||
* 0043A83F 7E 20 JLE SHORT malie.0043A861
|
||
* 0043A841 8B5C24 14 MOV EBX,DWORD PTR SS:[ESP+0x14]
|
||
* 0043A845 8B2D 14256900 MOV EBP,DWORD PTR DS:[<&MSVCRT._wcsicmp>>; msvcrt._wcsicmp
|
||
* 0043A84B 56 /PUSH ESI
|
||
* 0043A84C E8 6FFFFFFF |CALL malie.0043A7C0
|
||
* 0043A851 50 |PUSH EAX
|
||
* 0043A852 53 |PUSH EBX
|
||
* 0043A853 FFD5 |CALL EBP
|
||
* 0043A855 83C4 0C |ADD ESP,0xC
|
||
* 0043A858 85C0 |TEST EAX,EAX
|
||
* 0043A85A 74 0D |JE SHORT malie.0043A869
|
||
* 0043A85C 46 |INC ESI
|
||
* 0043A85D 3BF7 |CMP ESI,EDI
|
||
* 0043A85F ^7C EA \JL SHORT malie.0043A84B
|
||
* 0043A861 5F POP EDI
|
||
* 0043A862 5E POP ESI
|
||
* 0043A863 5D POP EBP
|
||
* 0043A864 83C8 FF OR EAX,0xFFFFFFFF
|
||
* 0043A867 5B POP EBX
|
||
* 0043A868 C3 RETN
|
||
* 0043A869 5F POP EDI
|
||
* 0043A86A 8BC6 MOV EAX,ESI
|
||
* 0043A86C 5E POP ESI
|
||
* 0043A86D 5D POP EBP
|
||
* 0043A86E 5B POP EBX
|
||
* 0043A86F C3 RETN
|
||
* 0043A870 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+0x4]
|
||
* 0043A874 83F8 FF CMP EAX,-0x1
|
||
* 0043A877 75 05 JNZ SHORT malie.0043A87E
|
||
* 0043A879 E8 92FFFFFF CALL malie.0043A810
|
||
* 0043A87E 50 PUSH EAX
|
||
* 0043A87F E8 3CFFFFFF CALL malie.0043A7C0
|
||
* 0043A884 33C9 XOR ECX,ECX
|
||
* 0043A886 83C4 04 ADD ESP,0x4
|
||
* 0043A889 66:8338 40 CMP WORD PTR DS:[EAX],0x40
|
||
* 0043A88D 0F94C1 SETE CL
|
||
* 0043A890 8BC1 MOV EAX,ECX
|
||
* 0043A892 C3 RETN
|
||
* 0043A893 90 NOP
|
||
* 0043A894 90 NOP
|
||
* 0043A895 90 NOP
|
||
* 0043A896 90 NOP
|
||
* 0043A897 90 NOP
|
||
* 0043A898 90 NOP
|
||
*
|
||
* 0278F138 0043AB90 RETURN to malie.0043AB90 from malie.0043A830
|
||
* 0278F13C 0278F154 UNICODE "telopminpro"
|
||
* 0278F140 0278F154 UNICODE "telopminpro"
|
||
* 0278F144 006D2AE8 UNICODE "%s"
|
||
* 0278F148 0192C990 UNICODE "telopminpro"
|
||
* 0278F14C 00000000
|
||
* 0278F150 0A33AAE0
|
||
* 0278F154 00650074 malie.00650074
|
||
* 0278F158 006F006C malie.006F006C
|
||
* 0278F15C 006D0070 ASCII "Context"
|
||
* 0278F160 006E0069 malie.006E0069
|
||
* 0278F164 00720070 malie.00720070
|
||
* 0278F168 0000006F
|
||
* 0278F16C 3F088850
|
||
* 0278F170 00000000
|
||
* 0278F174 00000000
|
||
*
|
||
*/
|
||
bool attachFont(ULONG startAddress, ULONG stopAddress)
|
||
{
|
||
const uint8_t bytes[] = {
|
||
0x50, // 0043A851 50 |PUSH EAX
|
||
0x53, // 0043A852 53 |PUSH EBX
|
||
0xFF,0xD5, // 0043A853 FFD5 |CALL EBP
|
||
0x83,0xC4, 0x0C, // 0043A855 83C4 0C |ADD ESP,0xC
|
||
0x85,0xC0, // 0043A858 85C0 |TEST EAX,EAX
|
||
0x74, 0x0D, // 0043A85A 74 0D |JE SHORT malie.0043A869
|
||
0x46, // 0043A85C 46 |INC ESI
|
||
0x3B,0xF7 // 0043A85D 3BF7 |CMP ESI,EDI
|
||
};
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
||
if (!addr)
|
||
return false;
|
||
addr = MemDbg::findEnclosingAlignedFunction(addr);
|
||
if (!addr)
|
||
return false;
|
||
HookParam hp;
|
||
hp.address=addr;
|
||
hp.type=EMBED_ABLE|HOOK_EMPTY;
|
||
hp.hook_before= Private::hookBefore;
|
||
return NewHook(hp,"PatchMalieFont");
|
||
}
|
||
} // namespace Patch
|
||
} // unnamed namespace
|
||
|
||
namespace{
|
||
//Dies irae ~Acta est Fabula~ HD
|
||
//Dies irae ~Interview with Kaziklu Bey~
|
||
|
||
std::wstring readString(DWORD address) {
|
||
std::wstring s = L"";
|
||
uint16_t c;
|
||
//console.log(hexdump(address))
|
||
while ((c = *(uint16_t*)address) != 0) {
|
||
// utf-16 characters
|
||
if (c >= 0x20) {
|
||
s += (wchar_t)c;// String.fromCharCode(c);
|
||
address = address+2;//.add(2);
|
||
}
|
||
else {
|
||
// start command
|
||
if (c == 0x7) {
|
||
address = address+2;//.add(2);
|
||
//let cmd = address.readU16();
|
||
auto cmd=*(uint16_t*)address;
|
||
address = address+2;//.add(2); // skip cmd
|
||
// voice id --> skip
|
||
if (cmd == 0x8) {
|
||
while ((c = *(uint16_t*)address) != 0) {
|
||
address = address+2;//.add(2);
|
||
}
|
||
address = address+2;//.add(2);
|
||
}
|
||
// end line --> return string
|
||
if (cmd == 0x6) {
|
||
return s;
|
||
}
|
||
// ruby
|
||
if (cmd == 0x1) {
|
||
while ((c = *(uint16_t*)address) != 0) {
|
||
// when we reach 0xa we have the kanji part
|
||
if (c == 0xa) {
|
||
address = address+2;//.add(2);
|
||
//let rubi = '';
|
||
while ((c = *(uint16_t*)address) != 0) {
|
||
// rubi += String.fromCharCode(c);
|
||
address = address+2;//.add(2);
|
||
}
|
||
//console.log('rubi: ' + rubi);
|
||
break;
|
||
}
|
||
else {
|
||
s += (wchar_t)c;// String.fromCharCode(c);
|
||
address = address+2;//.add(2);
|
||
}
|
||
}
|
||
address = address+2;//.add(2);
|
||
}
|
||
}
|
||
else {
|
||
address = address+2;//.add(2);
|
||
}
|
||
}
|
||
}
|
||
return {};
|
||
}
|
||
void textfun_light(hook_stack* stack, HookParam*, uintptr_t* data, uintptr_t* split, size_t* len){
|
||
DWORD eax = stack->eax;
|
||
DWORD ecx=*(DWORD*)eax;
|
||
DWORD edx = stack->edx ;
|
||
auto str = readString(ecx+edx*2);
|
||
static std::wstring _ws;
|
||
if(_ws==str)return;
|
||
_ws=str;
|
||
write_string_new(data,len,str);
|
||
*split=0;
|
||
}
|
||
bool malie_light(){
|
||
BYTE pattern[]={
|
||
0x8b,0x08,//往前两个字节,否则jump到下个指令(被hook截断)会崩溃
|
||
0x0f,XX,XX,XX,0x89,XX,XX,0x8d,XX,XX,0x89,XX,XX,0x8d,XX,XX,0x00,0x00,0x00,0x00
|
||
};
|
||
ULONG addr = MemDbg::findBytes(pattern, sizeof(pattern), processStartAddress, processStopAddress);
|
||
if (!addr)
|
||
return false;
|
||
HookParam hp{};
|
||
hp.address=addr;
|
||
hp.text_fun=textfun_light;
|
||
hp.type=CODEC_UTF16|USING_STRING|NO_CONTEXT;
|
||
return NewHook(hp,"malie_6");
|
||
|
||
}
|
||
|
||
}
|
||
|
||
bool Malie::attach_function() {
|
||
bool embed=ScenarioHook::attach(processStartAddress,processStopAddress);
|
||
// if(embed)Patch::attachFont(processStartAddress,processStopAddress); 导致闪退,放弃
|
||
auto b1= InsertMalieHook()||embed;
|
||
b1=malie_light()||b1;
|
||
return b1;
|
||
}
|