2024-02-07 20:59:24 +08:00
# 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 相 州 戦 神 館 學 <EFBFBD> 八 命 陣
* 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 相 州 戦 神 館 學 <EFBFBD> 八 命 陣
* 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 : シ ル ウ ゙ ァ リ オ ウ ゙ ェ ン ヂ <EFBFBD> ヂ <EFBFBD>
* 006547 8 B 90 NOP
* 006547 8 C 90 NOP
* 006547 8 D 90 NOP
* 006547 8 E 90 NOP
* 0065478F 90 NOP
* 006547 90 8 B4424 04 MOV EAX , DWORD PTR SS : [ ESP + 0x4 ]
* 006547 94 56 PUSH ESI
* 006547 95 57 PUSH EDI
* 006547 96 8 B50 08 MOV EDX , DWORD PTR DS : [ EAX + 0x8 ]
* 006547 99 8 B08 MOV ECX , DWORD PTR DS : [ EAX ]
* 006547 9 B 33F 6 XOR ESI , ESI
* 006547 9 D 66 : 8 B3451 MOV SI , WORD PTR DS : [ ECX + EDX * 2 ] ; jichi : text accessed here
* 006547 A1 42 INC EDX
* 006547 A2 8970 04 MOV DWORD PTR DS : [ EAX + 0x4 ] , ESI
* 006547 A5 8950 08 MOV DWORD PTR DS : [ EAX + 0x8 ] , EDX
* 006547 A8 8 B50 04 MOV EDX , DWORD PTR DS : [ EAX + 0x4 ]
* 006547 AB 83F A 01 CMP EDX , 0x1
* 006547 AE 75 2 C JNZ SHORT malie .006547 DC
* 006547 B0 8 B50 08 MOV EDX , DWORD PTR DS : [ EAX + 0x8 ]
* 006547 B3 33F 6 XOR ESI , ESI
* 006547 B5 66 : 8 B3451 MOV SI , WORD PTR DS : [ ECX + EDX * 2 ]
* 006547 B9 42 INC EDX
* 006547 BA 8970 04 MOV DWORD PTR DS : [ EAX + 0x4 ] , ESI
* 006547 BD 33F 6 XOR ESI , ESI
* 006547 BF 8950 08 MOV DWORD PTR DS : [ EAX + 0x8 ] , EDX
* 006547 C2 66 : 8 B3451 MOV SI , WORD PTR DS : [ ECX + EDX * 2 ]
* 006547 C6 8970 04 MOV DWORD PTR DS : [ EAX + 0x4 ] , ESI
* 006547 C9 42 INC EDX
* 006547 CA 33F 6 XOR ESI , ESI
* 006547 CC 8950 08 MOV DWORD PTR DS : [ EAX + 0x8 ] , EDX
* 006547 CF 66 : 8 B3451 MOV SI , WORD PTR DS : [ ECX + EDX * 2 ]
* 006547 D3 42 INC EDX
* 006547 D4 8970 04 MOV DWORD PTR DS : [ EAX + 0x4 ] , ESI
* 006547 D7 8950 08 MOV DWORD PTR DS : [ EAX + 0x8 ] , EDX
* 006547 DA ^ EB BF JMP SHORT malie .0065479 B
* 006547 DC 83F A 02 CMP EDX , 0x2
* 006547 DF 0F 84 59010000 JE malie .0065493 E
* 006547E5 83F A 03 CMP EDX , 0x3
* 006547E8 75 12 JNZ SHORT malie .006547F C
* 006547 EA 8 B50 08 MOV EDX , DWORD PTR DS : [ EAX + 0x8 ]
* 006547 ED 33F 6 XOR ESI , ESI
* 006547 EF 66 : 8 B3451 MOV SI , WORD PTR DS : [ ECX + EDX * 2 ]
* 006547F 3 42 INC EDX
* 006547F 4 8970 04 MOV DWORD PTR DS : [ EAX + 0x4 ] , ESI
* 006547F 7 8950 08 MOV DWORD PTR DS : [ EAX + 0x8 ] , EDX
* 006547F A ^ EB 9F JMP SHORT malie .0065479 B
* 006547F C 83F A 04 CMP EDX , 0x4
* 006547FF 0F 84 39010000 JE malie .0065493 E
* 00654 805 83F A 07 CMP EDX , 0x7
* 00654 808 0F 85 27010000 JNZ malie .00654935
* 00654 80 E 8 B50 08 MOV EDX , DWORD PTR DS : [ EAX + 0x8 ]
* 00654 811 33F 6 XOR ESI , ESI
* 00654 813 66 : 8 B3451 MOV SI , WORD PTR DS : [ ECX + EDX * 2 ]
* 00654 817 8970 04 MOV DWORD PTR DS : [ EAX + 0x4 ] , ESI
* 00654 81 A 8 D72 01 LEA ESI , DWORD PTR DS : [ EDX + 0x1 ]
* 00654 81 D 8 B50 04 MOV EDX , DWORD PTR DS : [ EAX + 0x4 ]
* 00654 820 8970 08 MOV DWORD PTR DS : [ EAX + 0x8 ] , ESI
* 00654 823 8 D7A FF LEA EDI , DWORD PTR DS : [ EDX - 0x1 ]
* 00654 826 83FF 3 B CMP EDI , 0x3B
* 00654 829 ^ 0F 87 79FF FFFF JA malie .006547 A8
* 0065482F 33 D2 XOR EDX , EDX
* 00654 831 8 A97 9 C496500 MOV DL , BYTE PTR DS : [ EDI + 0x65499C ]
* 00654 837 FF2495 80496500 JMP DWORD PTR DS : [ EDX * 4 + 0x654980 ]
* 00654 83 E 8 B50 0 C MOV EDX , DWORD PTR DS : [ EAX + 0xC ]
* 00654 841 85 D2 TEST EDX , EDX
* 00654 843 0F 8F 2 B010000 JG malie .00654974
* 00654 849 33 D2 XOR EDX , EDX
* 00654 84 B 66 : 8 B1471 MOV DX , WORD PTR DS : [ ECX + ESI * 2 ]
* 0065484F 46 INC ESI
* 00654 850 85 D2 TEST EDX , EDX
* 00654 852 8950 04 MOV DWORD PTR DS : [ EAX + 0x4 ] , EDX
* 00654 855 8970 08 MOV DWORD PTR DS : [ EAX + 0x8 ] , ESI
* 00654 858 0F 84 E0000000 JE malie .0065493 E
* 00654 85 E 8 B50 08 MOV EDX , DWORD PTR DS : [ EAX + 0x8 ]
* 00654 861 33F 6 XOR ESI , ESI
* 00654 863 66 : 8 B3451 MOV SI , WORD PTR DS : [ ECX + EDX * 2 ]
* 00654 867 42 INC EDX
* 00654 868 8950 08 MOV DWORD PTR DS : [ EAX + 0x8 ] , EDX
* 00654 86 B 8 BD6 MOV EDX , ESI
* 00654 86 D 85 D2 TEST EDX , EDX
* 0065486F 8970 04 MOV DWORD PTR DS : [ EAX + 0x4 ] , ESI
* 00654 872 ^ 75 EA JNZ SHORT malie .0065485 E
* 00654 874 8 B50 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
* 070 8 : voice start .
* 0701 : ruby start , 0 a as separator
*
* Sample plain unvoiced text :
*
* 0706 is used as pause char .
*
* 01FF F184 00 30 2 A 8 A 8 C 30 8 B 30 21 6 B 6 E 30 27 59 75 65 訪 れ る 次 の 大 敵
* 01FF F194 00 25 00 25 21 6 B 6 E 30 0 D 4 E 78 5 E 02 30 21 6 B ─ ─ 次 の 不 幸 。 次
* 01FF F1A4 6 E 30 E6 82 E3 96 02 30 21 6 B 6 E 30 34 78 C5 6 E の 苦 難 。 次 の 破 滅
* 01FF F1B4 02 30 07 00 06 00 0 A 00 00 30 B4 63 7F 30 D6 53 。 . 掴 み 取
* 01FF F1C4 63 30 5F 30 6F 30 5 A 30 6 E 30 2 A 67 65 67 6F 30 っ た は ず の 未 来 は
* 01FF F1D4 97 66 D2 9 E 6 B 30 55 87 7 E 30 8 C 30 5F 30 7 E 30 暗 黒 に 蝕 ま れ た ま
* 01FF F1E4 7 E 30 9 A 7 D 4 C 88 57 30 66 30 44 30 4F 30 02 30 ま 続 行 し て い く 。
* 01FF F1F4 07 00 06 00 0 A 00 00 30 80 30 57 30 8 D 30 4 B 62 . む し ろ 手
* 01FF F204 6 B 30 57 30 5F 30 47 59 E1 8 D 92 30 7 C 54 73 30 に し た 奇 跡 を 呼 び
* 01FF F214 34 6 C 6 B 30 01 30 88 30 8 A 30 4 A 30 5 E 30 7 E 30 水 に 、 よ り お ぞ ま
* 01FF F224 57 30 44 30 B0 65 5F 30 6 A 30 66 8 A F4 7 D 92 30 し い 新 た な 試 練 を
* 01FF F234 44 7 D 7F 30 BC 8F 93 30 67 30 4 B 90 7 D 54 92 30 組 み 込 ん で 運 命 を
* 01FF F244 C6 99 D5 52 55 30 5 B 30 8 B 30 6 E 30 60 30 02 30 駆 動 さ せ る の だ 。
* 01FF F254 07 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . .
* 01FF F264 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . .
* 01FF F274 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . .
* 01FF F284 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . .
* 01FF F294 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . .
* 01FF F2A4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . .
*
* Mixed unvoiced text and voiced text list :
* 01FF F184 00 30 1 C 20 DD 52 29 52 1 D 20 4 B 30 89 30 6F 30 “ 勝 利 ” か ら は
* 01FF F194 03 90 52 30 89 30 8 C 30 6 A 30 44 30 02 30 07 00 逃 げ ら れ な い 。
* 01FF F1A4 06 00 0 A 00 00 30 1 C 20 DD 52 29 52 1 D 20 4 B 30 . “ 勝 利 ” か
* 01FF F1B4 89 30 6F 30 03 90 52 30 89 30 8 C 30 6 A 30 44 30 ら は 逃 げ ら れ な い
* 01FF F1C4 02 30 07 00 06 00 0 A 00 00 30 1 C 20 DD 52 29 52 。 . “ 勝 利
* 01FF F1D4 1 D 20 4 B 30 89 30 6F 30 03 90 52 30 89 30 8 C 30 ” か ら は 逃 げ ら れ
* 01FF F1E4 6 A 30 44 30 02 30 07 00 06 00 0 A 00 0 A 00 07 00 な い 。 . .
* 01FF F1F4 08 00 76 00 5F 00 76 00 6 E 00 64 00 30 00 30 00 v_vnd00
* 01FF F204 30 00 31 00 00 00 0 C 30 6 A 30 89 30 70 30 00 25 01. 「 な ら ば ─
* 01FF F214 00 25 00 25 00 25 0 D 30 07 00 09 00 07 00 06 00 ─ ─ ─ 」 .
* 01FF F224 0 A 00 0 A 00 00 30 00 25 00 25 55 30 42 30 01 30 . . ─ ─ さ あ 、
* 01FF F234 69 30 46 30 59 30 8 B 30 4 B 30 1F FF 07 00 06 00 ど う す る か ?
* 01FF F244 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . .
* 01FF F254 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . .
* 01FF F264 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . .
*
* Sample voiced text :
*
* 0269F 184 07 00 08 00 76 00 5F 00 7 A 00 65 00 70 00 30 00 v_zep0
* 0269F 194 30 00 30 00 31 00 00 00 1 C 20 DD 52 29 52 1 D 20 001. “ 勝 利 ”
* 0269F 1 A4 68 30 6F 30 01 30 55 4F 60 30 1F FF 07 00 09 00 と は 、 何 だ ? .
* 0269F 1 B4 07 00 06 00 0 A 00 0 A 00 07 00 08 00 76 00 5F 00 . . v_
* 0269F 1 C4 7 A 00 65 00 70 00 30 00 30 00 30 00 32 00 00 00 zep0002 .
* 0269F 1 D4 1 C 20 04 68 49 51 1 D 20 68 30 6F 30 01 30 55 4F “ 栄 光 ” と は 、 何
* 0269F 1E4 60 30 1F FF 07 00 09 00 07 00 06 00 0 A 00 0 A 00 だ ? . . .
* 0269F 1F 4 07 00 08 00 76 00 5F 00 7 A 00 65 00 70 00 30 00 v_zep0
* 0269F 204 30 00 30 00 33 00 00 00 5 D 30 8 C 30 92 30 97 5F 003. そ れ を 得
* 0269F 214 8 C 30 70 30 01 30 55 4F 82 30 31 59 8F 30 5 A 30 れ ば 、 何 も 失 わ ず
* 0269F 224 6 B 30 08 6 E 80 30 6 E 30 60 30 8 D 30 46 30 4 B 30 に 済 む の だ ろ う か
* 0269F 234 07 00 09 00 07 00 06 00 0 A 00 0 A 00 07 00 08 00 . . .
* 0269F 244 76 00 5F 00 7 A 00 65 00 70 00 30 00 30 00 30 00 v_zep000
* 0269F 254 34 00 00 00 51 65 48 30 8 B 30 6 E 30 4 B 30 02 30 4. 救 え る の か 。
* 0269F 264 88 5 B 8 C 30 8 B 30 6 E 30 4 B 30 02 30 2 C 67 53 5F 守 れ る の か 。 本 当
* 0269F 274 6 B 30 01 30 78 5 E 5 B 30 6 B 30 6 A 30 8 C 30 8 B 30 に 、 幸 せ に な れ る
* 0269F 284 6 E 30 60 30 8 D 30 46 30 4 B 30 07 00 09 00 07 00 の だ ろ う か .
* 0269F 294 06 00 00 00 00 00 00 00 D1 01 00 00 8 C F3 69 02 . . . Ǒ . ɩ
*
* Ruby :
*
* 01F DF2B4 63 30 5F 30 07 00 01 00 14 90 EF 7 A 0 A 00 68 30 っ た 途 端 . と
* 01F DF2C4 5F 30 93 30 00 00 01 30 06 90 6 B 30 40 62 09 67 た ん . 、 逆 に 所 有
*
* Pause without 0 a :
*
* 0271F 184 07 00 08 00 76 00 5F 00 7 A 00 65 00 70 00 30 00 v_zep0
* 0271F 194 30 00 34 00 34 00 00 00 00 30 51 30 8 C 30 69 30 044. け れ ど
* 0271F 1 A4 00 25 00 25 07 00 09 00 07 00 06 00 07 00 08 00 ─ ─ .
* 0271F 1 B4 76 00 5F 00 7 A 00 65 00 70 00 30 00 30 00 34 00 v_zep004
* 0271F 1 C4 35 00 00 00 5 D 30 8 C 30 67 30 82 30 01 30 88 5 B 5. そ れ で も 、 守
* 0271F 1 D4 89 30 6 A 30 51 30 8 C 30 70 30 6 A 30 89 30 6 A 30 ら な け れ ば な ら な
* 0271F 1E4 44 30 50 5 B 4 C 30 FA 51 65 67 5F 30 4 B 30 89 30 い 子 が 出 来 た か ら
* 0271F 1F 4 02 30 07 00 09 00 07 00 06 00 07 00 04 00 00 30 。 .
* 0271F 204 07 00 08 00 76 00 5F 00 7 A 00 65 00 70 00 30 00 v_zep0
* 0271F 214 30 00 34 00 36 00 00 00 7 C 5F 73 59 92 30 51 65 046. 彼 女 を 救
* 0271F 224 46 30 5F 30 81 30 6 B 30 01 30 53 30 6 E 30 61 30 う た め に 、 こ の ち
* 0271F 234 63 30 7 D 30 51 30 6 A 30 7 D 54 92 30 F8 61 51 30 っ ぽ け な 命 を 懸 け
* 0271F 244 8 B 30 68 30 93 8 A 63 30 5F 30 02 30 86 30 48 30 る と 誓 っ た 。 ゆ え
*
* Scenario caller : 4637 bf
*
* 0046377 D 90 NOP
* 0046377 E 90 NOP
* 0046377F 90 NOP
* 004637 80 81 EC 000 80000 SUB ESP , 0x800
* 004637 86 56 PUSH ESI
* 004637 87 8 BB424 08080000 MOV ESI , DWORD PTR SS : [ ESP + 0x808 ]
* 004637 8 E 8 B46 1 C MOV EAX , DWORD PTR DS : [ ESI + 0x1C ]
* 004637 91 8 B88 68020000 MOV ECX , DWORD PTR DS : [ EAX + 0x268 ]
* 004637 97 57 PUSH EDI
* 004637 98 51 PUSH ECX
* 004637 99 E8 D200FFFF CALL malie .00453870
* 004637 9 E 8 BBC24 14080000 MOV EDI , DWORD PTR SS : [ ESP + 0x814 ]
* 004637 A5 68 C06C4100 PUSH malie .00416 CC0
* 004637 AA 8 D5424 10 LEA EDX , DWORD PTR SS : [ ESP + 0x10 ]
* 004637 AE 57 PUSH EDI
* 004637 AF 52 PUSH EDX
* 004637 B0 E8 AB041F00 CALL malie .00653 C60
* 004637 B5 8 D4424 18 LEA EAX , DWORD PTR SS : [ ESP + 0x18 ]
* 004637 B9 50 PUSH EAX
* 004637 BA E8 21031F 00 CALL malie .00653 AE0 ; jichi : scenario caller
* 004637 BF 8 B4E 1 C MOV ECX , DWORD PTR DS : [ ESI + 0x1C ]
* 004637 C2 57 PUSH EDI
* 004637 C3 8981 68020000 MOV DWORD PTR DS : [ ECX + 0x268 ] , EAX
* 004637 C9 E8 32E61 E00 CALL malie .00651E00
* 004637 CE 83 C4 18 ADD ESP , 0x18
* 004637 D1 33 D2 XOR EDX , EDX
* 004637 D3 85 C0 TEST EAX , EAX
* 004637 D5 8 B46 1 C MOV EAX , DWORD PTR DS : [ ESI + 0x1C ]
* 004637 D8 0F 9F C2 SETG DL
* 004637 DB 5F POP EDI
* 004637 DC 5 E POP ESI
* 004637 DD 8990 7 C020000 MOV DWORD PTR DS : [ EAX + 0x27C ] , EDX
* 004637E3 81 C4 000 80000 ADD ESP , 0x800
* 004637E9 C3 RETN
* 004637 EA 90 NOP
* 004637 EB 90 NOP
* 004637 EC 90 NOP
*
* Name caller : 46382 e
*
* 004637 EB 90 NOP
* 004637 EC 90 NOP
* 004637 ED 90 NOP
* 004637 EE 90 NOP
* 004637 EF 90 NOP
* 004637F 0 81 EC 000 80000 SUB ESP , 0x800
* 004637F 6 56 PUSH ESI
* 004637F 7 8 BB424 08080000 MOV ESI , DWORD PTR SS : [ ESP + 0x808 ]
* 004637F E 8 B46 1 C MOV EAX , DWORD PTR DS : [ ESI + 0x1C ]
* 00463 801 8 B88 6 C020000 MOV ECX , DWORD PTR DS : [ EAX + 0x26C ]
* 00463 807 51 PUSH ECX
* 00463 808 E8 6300FF FF CALL malie .00453870
* 00463 80 D 8 B9424 10080000 MOV EDX , DWORD PTR SS : [ ESP + 0x810 ]
* 00463 814 68 C06C4100 PUSH malie .00416 CC0
* 00463 819 52 PUSH EDX
* 00463 81 A 8 D4424 10 LEA EAX , DWORD PTR SS : [ ESP + 0x10 ]
* 00463 81 E 50 PUSH EAX
* 0046381F E8 3 C041F00 CALL malie .00653 C60
* 00463 824 8 D4C24 14 LEA ECX , DWORD PTR SS : [ ESP + 0x14 ]
* 00463 828 51 PUSH ECX
* 00463 829 E8 B2021F00 CALL malie .00653 AE0 ; jichi : name
* 00463 82 E 8 B56 1 C MOV EDX , DWORD PTR DS : [ ESI + 0x1C ]
* 00463 831 83 C4 14 ADD ESP , 0x14
* 00463 834 8982 6 C020000 MOV DWORD PTR DS : [ EDX + 0x26C ] , EAX
* 00463 83 A 5 E POP ESI
* 00463 83 B 81 C4 000 80000 ADD ESP , 0x800
* 00463 841 C3 RETN
* 00463 842 90 NOP
* 00463 843 90 NOP
* 00463 844 90 NOP
*
* History caller : 418 d0b
*
* 0041 8 C9D 90 NOP
* 0041 8 C9E 90 NOP
* 0041 8 C9F 90 NOP
* 0041 8 CA0 81 EC 000 80000 SUB ESP , 0x800
* 0041 8 CA6 53 PUSH EBX
* 0041 8 CA7 56 PUSH ESI
* 0041 8 CA8 57 PUSH EDI
* 0041 8 CA9 6 A 6 C PUSH 0x6C
* 0041 8 CAB FF15 20256900 CALL DWORD PTR DS : [ < & MSVCRT . malloc > ] ; msvcrt . malloc
* 0041 8 CB1 8 BD8 MOV EBX , EAX
* 0041 8 CB3 83 C4 04 ADD ESP , 0x4
* 0041 8 CB6 85 DB TEST EBX , EBX
* 0041 8 CB8 0F 84 D1000000 JE malie .00418 D8F
* 0041 8 CBE 8 BB424 10080000 MOV ESI , DWORD PTR SS : [ ESP + 0x810 ]
* 0041 8 CC5 33 C0 XOR EAX , EAX
* 0041 8 CC7 B9 1 B000000 MOV ECX , 0x1B
* 0041 8 CCC 8 BFB MOV EDI , EBX
* 0041 8 CCE F3 : AB REP STOS DWORD PTR ES : [ EDI ]
* 0041 8 CD0 8 B06 MOV EAX , DWORD PTR DS : [ ESI ]
* 0041 8 CD2 68 C06C4100 PUSH malie .00416 CC0
* 0041 8 CD7 50 PUSH EAX
* 0041 8 CD8 8 D4C24 14 LEA ECX , DWORD PTR SS : [ ESP + 0x14 ]
* 0041 8 CDC 51 PUSH ECX
* 0041 8 CDD E8 7 EAF2300 CALL malie .00653 C60
* 0041 8 CE2 8 D5424 18 LEA EDX , DWORD PTR SS : [ ESP + 0x18 ]
* 0041 8 CE6 52 PUSH EDX
* 0041 8 CE7 E8 F4AD2300 CALL malie .00653 AE0
* 0041 8 CEC 8903 MOV DWORD PTR DS : [ EBX ] , EAX
* 0041 8 CEE 8 B46 04 MOV EAX , DWORD PTR DS : [ ESI + 0x4 ]
* 0041 8 CF1 68 C06C4100 PUSH malie .00416 CC0
* 0041 8 CF6 50 PUSH EAX
* 0041 8 CF7 8 D4C24 24 LEA ECX , DWORD PTR SS : [ ESP + 0x24 ]
* 0041 8 CFB 51 PUSH ECX
* 0041 8 CFC E8 5F AF2300 CALL malie .00653 C60
* 0041 8 D01 8 D5424 28 LEA EDX , DWORD PTR SS : [ ESP + 0x28 ]
* 0041 8 D05 52 PUSH EDX
* 0041 8 D06 E8 D5AD2300 CALL malie .00653 AE0 ; jichi : history caller
* 0041 8 D0B 8943 04 MOV DWORD PTR DS : [ EBX + 0x4 ] , EAX
* 0041 8 D0E 8 B46 08 MOV EAX , DWORD PTR DS : [ ESI + 0x8 ]
* 0041 8 D11 83 C4 20 ADD ESP , 0x20
* 0041 8 D14 85 C0 TEST EAX , EAX
* 0041 8 D16 75 05 JNZ SHORT malie .00418 D1D
* 0041 8 D18 B8 0 CEF7000 MOV EAX , malie .0070 EF0C
* 0041 8 D1D 50 PUSH EAX
* 0041 8 D1E E8 3 D6F2300 CALL malie .0064F C60
* 0041 8 D23 8943 08 MOV DWORD PTR DS : [ EBX + 0x8 ] , EAX
* 0041 8 D26 8 B46 0 C MOV EAX , DWORD PTR DS : [ ESI + 0xC ]
* 0041 8 D29 83 C4 04 ADD ESP , 0x4
* 0041 8 D2C 85 C0 TEST EAX , EAX
* 0041 8 D2E 75 05 JNZ SHORT malie .00418 D35
* 0041 8 D30 B8 0 CEF7000 MOV EAX , malie .0070 EF0C
* 0041 8 D35 50 PUSH EAX
* 0041 8 D36 E8 256F 2300 CALL malie .0064F C60
* 0041 8 D3B 8943 0 C MOV DWORD PTR DS : [ EBX + 0xC ] , EAX
* 0041 8 D3E 8 B46 60 MOV EAX , DWORD PTR DS : [ ESI + 0x60 ]
* 0041 8 D41 8943 60 MOV DWORD PTR DS : [ EBX + 0x60 ] , EAX
* 0041 8 D44 8 B4E 64 MOV ECX , DWORD PTR DS : [ ESI + 0x64 ]
* 0041 8 D47 894 B 64 MOV DWORD PTR DS : [ EBX + 0x64 ] , ECX
* 0041 8 D4A 8 B56 68 MOV EDX , DWORD PTR DS : [ ESI + 0x68 ]
* 0041 8 D4D 8 D7E 10 LEA EDI , DWORD PTR DS : [ ESI + 0x10 ]
* 0041 8 D50 83 C4 04 ADD ESP , 0x4
* 0041 8 D53 85FF TEST EDI , EDI
* 0041 8 D55 8953 68 MOV DWORD PTR DS : [ EBX + 0x68 ] , EDX
* 0041 8 D58 74 35 JE SHORT malie .00418 D8F
* 0041 8 D5A 55 PUSH EBP
* 0041 8 D5B 8 BEB MOV EBP , EBX
* 0041 8 D5D 2 BEE SUB EBP , ESI
* 0041 8 D5F BE 14000000 MOV ESI , 0x14
* 0041 8 D64 8 B07 MOV EAX , DWORD PTR DS : [ EDI ]
* 0041 8 D66 66 : 8338 00 CMP WORD PTR DS : [ EAX ] , 0x0
* 0041 8 D6A 75 04 JNZ SHORT malie .00418 D70
* 0041 8 D6C 33 C0 XOR EAX , EAX
* 0041 8 D6E EB 09 JMP SHORT malie .00418 D79
* 0041 8 D70 50 PUSH EAX
* 0041 8 D71 E8 EA6E2300 CALL malie .0064F C60
* 0041 8 D76 83 C4 04 ADD ESP , 0x4
* 0041 8 D79 89042F MOV DWORD PTR DS : [ EDI + EBP ] , EAX
* 0041 8 D7C 83 C7 04 ADD EDI , 0x4
* 0041 8 D7F 4 E DEC ESI
* 0041 8 D80 ^ 75 E2 JNZ SHORT malie .00418 D64
* 0041 8 D82 5 D POP EBP
* 0041 8 D83 5F POP EDI
* 0041 8 D84 5 E POP ESI
* 0041 8 D85 8 BC3 MOV EAX , EBX
* 0041 8 D87 5 B POP EBX
* 0041 8 D88 81 C4 000 80000 ADD ESP , 0x800
* 0041 8 D8E C3 RETN
* 0041 8 D8F 5F POP EDI
* 0041 8 D90 5 E POP ESI
* 0041 8 D91 8 BC3 MOV EAX , EBX
* 0041 8 D93 5 B POP EBX
* 0041 8 D94 81 C4 000 80000 ADD ESP , 0x800
* 0041 8 D9A C3 RETN
* 0041 8 D9B 90 NOP
* 0041 8 D9C 90 NOP
*
* Exit dialog box caller :
* 00475 A8D 90 NOP
* 00475 A8E 90 NOP
* 00475 A8F 90 NOP
* 00475 A90 56 PUSH ESI
* 00475 A91 68 B09C7500 PUSH malie .00759 CB0
* 00475 A96 FF15 F8206900 CALL DWORD PTR DS : [ < & KERNEL32 . EnterCriti > ; ntdll . RtlEnterCriticalSection
* 00475 A9C 8 B7424 08 MOV ESI , DWORD PTR SS : [ ESP + 0x8 ]
* 00475 AA0 85F 6 TEST ESI , ESI
* 00475 AA2 74 4 A JE SHORT malie .00475 AEE
* 00475 AA4 56 PUSH ESI
* 00475 AA5 E8 56000000 CALL malie .00475 B00
* 00475 AAA 8 B46 1 C MOV EAX , DWORD PTR DS : [ ESI + 0x1C ]
* 00475 AAD 8 B08 MOV ECX , DWORD PTR DS : [ EAX ]
* 00475 AAF 51 PUSH ECX
* 00475 AB0 E8 BBDDFDFF CALL malie .00453870
* 00475 AB5 8 B5424 14 MOV EDX , DWORD PTR SS : [ ESP + 0x14 ]
* 00475 AB9 52 PUSH EDX
* 00475 ABA E8 21E01 D00 CALL malie .00653 AE0 ; jichi : called here
* 00475 ABF 8 B4E 1 C MOV ECX , DWORD PTR DS : [ ESI + 0x1C ]
* 00475 AC2 8901 MOV DWORD PTR DS : [ ECX ] , EAX
* 00475 AC4 8 B56 1 C MOV EDX , DWORD PTR DS : [ ESI + 0x1C ]
* 00475 AC7 C782 94000000 00 > MOV DWORD PTR DS : [ EDX + 0x94 ] , 0x0
* 00475 AD1 8 B46 1 C MOV EAX , DWORD PTR DS : [ ESI + 0x1C ]
* 00475 AD4 8 B08 MOV ECX , DWORD PTR DS : [ EAX ]
* 00475 AD6 51 PUSH ECX
* 00475 AD7 E8 84 C41D00 CALL malie .00651F 60
* 00475 ADC 8 B56 1 C MOV EDX , DWORD PTR DS : [ ESI + 0x1C ]
* 00475 ADF 56 PUSH ESI
* 00475 AE0 8982 98000000 MOV DWORD PTR DS : [ EDX + 0x98 ] , EAX
* 00475 AE6 E8 C5000000 CALL malie .00475 BB0
* 00475 AEB 83 C4 14 ADD ESP , 0x14
* 00475 AEE 68 B09C7500 PUSH malie .00759 CB0
* 00475 AF3 FF15 44226900 CALL DWORD PTR DS : [ < & KERNEL32 . LeaveCriti > ; ntdll . RtlLeaveCriticalSection
* 00475 AF9 5 E POP ESI
* 00475 AFA C3 RETN
* 00475 AFB 90 NOP
* 00475 AFC 90 NOP
* 00475 AFD 90 NOP
*
* Sample game : 相 州 戦 神 館 學 園 八 命 陣 ( older game0
* Scenario caller : 46314f
*
* 0046310 B 90 NOP
* 0046310 C 90 NOP
* 0046310 D 90 NOP
* 0046310 E 90 NOP
* 0046310F 90 NOP
* 00463110 81 EC 000 80000 SUB ESP , 0x800
* 00463116 56 PUSH ESI
* 00463117 8 BB424 08080000 MOV ESI , DWORD PTR SS : [ ESP + 0x808 ]
* 0046311 E 8 B46 20 MOV EAX , DWORD PTR DS : [ ESI + 0x20 ]
* 00463121 8 B88 68020000 MOV ECX , DWORD PTR DS : [ EAX + 0x268 ]
* 00463127 57 PUSH EDI
* 0046312 8 51 PUSH ECX
* 0046312 9 E8 62240200 CALL .00485590
* 0046312 E 8 BBC24 14080000 MOV EDI , DWORD PTR SS : [ ESP + 0x814 ]
* 00463135 68 10634100 PUSH .00416310
* 0046313 A 8 D5424 10 LEA EDX , DWORD PTR SS : [ ESP + 0x10 ]
* 0046313 E 57 PUSH EDI
* 0046313F 52 PUSH EDX
* 00463140 E8 AB841D00 CALL .0063 B5F0
* 00463145 8 D4424 18 LEA EAX , DWORD PTR SS : [ ESP + 0x18 ]
* 0046314 9 50 PUSH EAX
* 0046314 A E8 41831 D00 CALL .0063 B490
* 0046314F 8 B4E 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
* 0046315 9 E8 82661 D00 CALL .006397E0
* 0046315 E 83 C4 18 ADD ESP , 0x18
* 00463161 33 D2 XOR EDX , EDX
* 00463163 85 C0 TEST EAX , EAX
* 00463165 8 B46 20 MOV EAX , DWORD PTR DS : [ ESI + 0x20 ]
* 0046316 8 0F 9F C2 SETG DL
* 0046316 B 5F POP EDI
* 0046316 C 5 E POP ESI
* 0046316 D 8990 7 C020000 MOV DWORD PTR DS : [ EAX + 0x27C ] , EDX
* 00463173 81 C4 000 80000 ADD ESP , 0x800
* 0046317 9 C3 RETN
* 0046317 A 90 NOP
* 0046317 B 90 NOP
* 0046317 C 90 NOP
* 0046317 D 90 NOP
* 0046317 E 90 NOP
*
* Sample game : BRAVA ! !
* Scenario retaddr : 42011f
*
* 004200F D 90 NOP
* 004200F E 90 NOP
* 004200FF 90 NOP
* 00420100 56 PUSH ESI
* 00420101 8 B7424 08 MOV ESI , DWORD PTR SS : [ ESP + 0x8 ]
* 00420105 8 B46 20 MOV EAX , DWORD PTR DS : [ ESI + 0x20 ]
* 0042010 8 8 B88 F0000000 MOV ECX , DWORD PTR DS : [ EAX + 0xF0 ]
* 0042010 E 57 PUSH EDI
* 0042010F 51 PUSH ECX
* 00420110 E8 BB240200 CALL .004425 D0
* 00420115 8 B7C24 14 MOV EDI , DWORD PTR SS : [ ESP + 0x14 ]
* 0042011 9 57 PUSH EDI
* 0042011 A E8 01031300 CALL .00550420
* 0042011F 8 B56 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
* 0042012 9 E8 B2E61200 CALL .0054E7 E0
* 0042012 E 8 B56 20 MOV EDX , DWORD PTR DS : [ ESI + 0x20 ]
* 00420131 83 C4 0 C ADD ESP , 0xC
* 00420134 33 C9 XOR ECX , ECX
* 00420136 85 C0 TEST EAX , EAX
* 0042013 8 0F 9F C1 SETG CL
* 0042013 B 5F POP EDI
* 0042013 C 5 E POP ESI
* 0042013 D 898 A FC000000 MOV DWORD PTR DS : [ EDX + 0xFC ] , ECX
* 00420143 C3 RETN
* 00420144 90 NOP
*
* Name retaddr : 415 a2c
*
* 00415 9 DD 90 NOP
* 00415 9 DE 90 NOP
* 00415 9 DF 90 NOP
* 004159E0 81 EC 000 80000 SUB ESP , 0x800
* 004159E6 53 PUSH EBX
* 004159E7 56 PUSH ESI
* 004159E8 57 PUSH EDI
* 004159E9 6 A 6 C PUSH 0x6C
* 00415 9 EB FF15 40 D45800 CALL DWORD PTR DS : [ 0x58D440 ] ; msvcrt . malloc
* 004159F 1 8 BD8 MOV EBX , EAX
* 004159F 3 83 C4 04 ADD ESP , 0x4
* 004159F 6 85 DB TEST EBX , EBX
* 004159F 8 0F 84 D1000000 JE .00415 ACF
* 004159F E 8 BB424 10080000 MOV ESI , DWORD PTR SS : [ ESP + 0x810 ]
* 00415 A05 33 C0 XOR EAX , EAX
* 00415 A07 B9 1 B000000 MOV ECX , 0x1B
* 00415 A0C 8 BFB MOV EDI , EBX
* 00415 A0E F3 : AB REP STOS DWORD PTR ES : [ EDI ]
* 00415 A10 8 B06 MOV EAX , DWORD PTR DS : [ ESI ]
* 00415 A12 68 003 B4100 PUSH .00413 B00
* 00415 A17 50 PUSH EAX
* 00415 A18 8 D4C24 14 LEA ECX , DWORD PTR SS : [ ESP + 0x14 ]
* 00415 A1C 51 PUSH ECX
* 00415 A1D E8 5 EAB1300 CALL .00550580
* 00415 A22 8 D5424 18 LEA EDX , DWORD PTR SS : [ ESP + 0x18 ]
* 00415 A26 52 PUSH EDX
* 00415 A27 E8 F4A91300 CALL .00550420
* 00415 A2C 8903 MOV DWORD PTR DS : [ EBX ] , EAX ; jichi : name caller
* 00415 A2E 8 B46 04 MOV EAX , DWORD PTR DS : [ ESI + 0x4 ]
* 00415 A31 68 003 B4100 PUSH .00413 B00
* 00415 A36 50 PUSH EAX
* 00415 A37 8 D4C24 24 LEA ECX , DWORD PTR SS : [ ESP + 0x24 ]
* 00415 A3B 51 PUSH ECX
* 00415 A3C E8 3F AB1300 CALL .00550580
* 00415 A41 8 D5424 28 LEA EDX , DWORD PTR SS : [ ESP + 0x28 ]
* 00415 A45 52 PUSH EDX
* 00415 A46 E8 D5A91300 CALL .00550420
* 00415 A4B 8943 04 MOV DWORD PTR DS : [ EBX + 0x4 ] , EAX
* 00415 A4E 8 B46 08 MOV EAX , DWORD PTR DS : [ ESI + 0x8 ]
* 00415 A51 83 C4 20 ADD ESP , 0x20
* 00415 A54 85 C0 TEST EAX , EAX
* 00415 A56 75 05 JNZ SHORT .00415 A5D
* 00415 A58 B8 6 C285E00 MOV EAX , .005E286 C
* 00415 A5D 50 PUSH EAX
* 00415 A5E E8 DD691300 CALL .0054 C440
* 00415 A63 8943 08 MOV DWORD PTR DS : [ EBX + 0x8 ] , EAX
* 00415 A66 8 B46 0 C MOV EAX , DWORD PTR DS : [ ESI + 0xC ]
* 00415 A69 83 C4 04 ADD ESP , 0x4
* 00415 A6C 85 C0 TEST EAX , EAX
* 00415 A6E 75 05 JNZ SHORT .00415 A75
* 00415 A70 B8 6 C285E00 MOV EAX , .005E286 C
* 00415 A75 50 PUSH EAX
* 00415 A76 E8 C5691300 CALL .0054 C440
* 00415 A7B 8943 0 C MOV DWORD PTR DS : [ EBX + 0xC ] , EAX
* 00415 A7E 8 B46 60 MOV EAX , DWORD PTR DS : [ ESI + 0x60 ]
* 00415 A81 8943 60 MOV DWORD PTR DS : [ EBX + 0x60 ] , EAX
* 00415 A84 8 B4E 64 MOV ECX , DWORD PTR DS : [ ESI + 0x64 ]
* 00415 A87 894 B 64 MOV DWORD PTR DS : [ EBX + 0x64 ] , ECX
* 00415 A8A 8 B56 68 MOV EDX , DWORD PTR DS : [ ESI + 0x68 ]
* 00415 A8D 8 D7E 10 LEA EDI , DWORD PTR DS : [ ESI + 0x10 ]
* 00415 A90 83 C4 04 ADD ESP , 0x4
* 00415 A93 85FF TEST EDI , EDI
* 00415 A95 8953 68 MOV DWORD PTR DS : [ EBX + 0x68 ] , EDX
* 00415 A98 74 35 JE SHORT .00415 ACF
* 00415 A9A 55 PUSH EBP
* 00415 A9B 8 BEB MOV EBP , EBX
* 00415 A9D 2 BEE SUB EBP , ESI
* 00415 A9F BE 14000000 MOV ESI , 0x14
* 00415 AA4 8 B07 MOV EAX , DWORD PTR DS : [ EDI ]
* 00415 AA6 66 : 8338 00 CMP WORD PTR DS : [ EAX ] , 0x0
* 00415 AAA 75 04 JNZ SHORT .00415 AB0
* 00415 AAC 33 C0 XOR EAX , EAX
* 00415 AAE EB 09 JMP SHORT .00415 AB9
* 00415 AB0 50 PUSH EAX
* 00415 AB1 E8 8 A691300 CALL .0054 C440
* 00415 AB6 83 C4 04 ADD ESP , 0x4
* 00415 AB9 89042F MOV DWORD PTR DS : [ EDI + EBP ] , EAX
* 00415 ABC 83 C7 04 ADD EDI , 0x4
* 00415 ABF 4 E DEC ESI
* 00415 AC0 ^ 75 E2 JNZ SHORT .00415 AA4
* 00415 AC2 5 D POP EBP
* 00415 AC3 5F POP EDI
* 00415 AC4 5 E POP ESI
* 00415 AC5 8 BC3 MOV EAX , EBX
* 00415 AC7 5 B POP EBX
* 00415 AC8 81 C4 000 80000 ADD ESP , 0x800
* 00415 ACE C3 RETN
* 00415 ACF 5F POP EDI
* 00415 AD0 5 E POP ESI
* 00415 AD1 8 BC3 MOV EAX , EBX
* 00415 AD3 5 B POP EBX
* 00415 AD4 81 C4 000 80000 ADD ESP , 0x800
* 00415 ADA C3 RETN
* 00415 ADB 90 NOP
* 00415 ADC 90 NOP
* 00415 ADD 90 NOP
* 00415 ADE 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 ) ;
2024-03-21 17:57:04 +08:00
write_string_overwrite ( data1 , len , oldText ) ;
2024-02-07 20:59:24 +08:00
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 .
*
* 00653 ADC 90 NOP
* 00653 ADD 90 NOP
* 00653 ADE 90 NOP
* 00653 ADF 90 NOP
* 00653 AE0 56 PUSH ESI
* 00653 AE1 8 B7424 08 MOV ESI , DWORD PTR SS : [ ESP + 0x8 ]
* 00653 AE5 33 C0 XOR EAX , EAX
* 00653 AE7 85F 6 TEST ESI , ESI
* 00653 AE9 74 47 JE SHORT malie .00653 B32
* 00653 AEB 53 PUSH EBX
* 00653 AEC 57 PUSH EDI
* 00653 AED 68 00 C47F00 PUSH malie .007F C400
* 00653 AF2 FF15 F8206900 CALL DWORD PTR DS : [ < & KERNEL32 . EnterCriti > ; ntdll . RtlEnterCriticalSection
* 00653 AF8 56 PUSH ESI
* 00653 AF9 E8 C2E4FFFF CALL malie .00651F C0
* 00653 AFE 8 D78 02 LEA EDI , DWORD PTR DS : [ EAX + 0x2 ]
* 00653 B01 57 PUSH EDI
* 00653 B02 FF15 20256900 CALL DWORD PTR DS : [ < & MSVCRT . malloc > ] ; msvcrt . malloc
* 00653 B08 8 BD8 MOV EBX , EAX
* 00653 B0A 83 C4 08 ADD ESP , 0x8
* 00653 B0D 85 DB TEST EBX , EBX
* 00653 B0F 74 12 JE SHORT malie .00653 B23
* 00653 B11 8 BCF MOV ECX , EDI
* 00653 B13 8 BFB MOV EDI , EBX
* 00653 B15 8 BC1 MOV EAX , ECX
* 00653 B17 C1E9 02 SHR ECX , 0x2
* 00653 B1A F3 : A5 REP MOVS DWORD PTR ES : [ EDI ] , DWORD PTR DS : [ ESI ]
* 00653 B1C 8 BC8 MOV ECX , EAX
* 00653 B1E 83E1 03 AND ECX , 0x3
* 00653 B21 F3 : A4 REP MOVS BYTE PTR ES : [ EDI ] , BYTE PTR DS : [ ESI ]
* 00653 B23 68 00 C47F00 PUSH malie .007F C400
* 00653 B28 FF15 44226900 CALL DWORD PTR DS : [ < & KERNEL32 . LeaveCriti > ; ntdll . RtlLeaveCriticalSection
* 00653 B2E 8 BC3 MOV EAX , EBX
* 00653 B30 5F POP EDI
* 00653 B31 5 B POP EBX
* 00653 B32 5 E POP ESI
* 00653 B33 C3 RETN
* 00653 B34 90 NOP
* 00653 B35 90 NOP
* 00653 B36 90 NOP
* 00653 B37 90 NOP
* 00653 B38 90 NOP
*
* Malie2 ' s pattern : 4089560833 d2894604
*
* 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 :
*
* 026 DF0D8 026 DF0E0
* 026 DF0DC 026 DF184 ; jichi : source text
* 026 DF0E0 026 DF184
* 026 DF0E4 00000000
* 026 DF0E8 000000 B8
* 026 DF0EC 0627 DFE8
* 026 DF0F0 016F 0000
* 026 DF0F4 0627 DFE0
* 026 DF0F8 01 80 B5E0
* 026 DF0FC 00000001
* 026 DF100 01 80 B8F0 ASCII " " = VH "
* 026 DF104 / 026 DF11C
* 026 DF108 | 77492 CE8 RETURN to ntdll .77492 CE8 from ntdll .77492 D0B
* 026 DF10C | 01 80 B8F8
* 026 DF110 | FFFFFFFF
* 026 DF114 | 04 A9103C
* 026 DF118 | 01 80 B8F0 ASCII " " = VH "
* 026 DF11C \ 026 DF168
* 026 DF120 771 B98CD RETURN to msvcrt .771 B98CD from ntdll . RtlFreeHeap
* 026 DF124 01 8 B0000
* 026 DF128 00000000
* 026 DF12C 00000006
* 026 DF130 FFFFFFFF
* 026 DF134 FFFFFFFF
* 026 DF138 00000000
* 026 DF13C 026 DF184 ; jichi : text
* 026 DF140 0000000 C
* 026 DF144 062671 D8
* 026 DF148 00000000
* 026 DF14C / 026 DFA08
* 026 DF150 | 00653 AFE RETURN to malie .00653 AFE from malie .00651F C0
* 026 DF154 | 026 DF184 ; jichi : text
* 026 DF158 | 007272 A8 malie .007272 A8
* 026 DF15C | 04 A9103C
* 026 DF160 | 01 83 DFE8
* 026 DF164 | 004637 BF RETURN to malie .004637 BF from malie .00653 AE0
* 026 DF168 | 026 DF184 ; jichi : text , two continous scenario text
* 026 DF16C | 026 DF184 ; jichi : text
* 026 DF170 | 007272 A8 malie .007272 A8
* 026 DF174 | 00416 CC0 malie .00416 CC0
* 026 DF178 | 01 80 B8F8
* 026 DF17C | FFFFFFFF
* 026 DF180 | 01 83 DFE8
* 026 DF184 | 000 80007
* 026 DF188 | 005F 0076 malie .005F 0076
* 026 DF18C | 0065007 A malie .0065007 A
* 026 DF190 | 00300070
* 026 DF194 | 00300030
*
* Sample game : 相 州 戦 神 館 學 園 八 命 陣 ( older game without critical sections )
* 0063 B48D 90 NOP
* 0063 B48E 90 NOP
* 0063 B48F 90 NOP
* 0063 B490 56 PUSH ESI
* 0063 B491 8 B7424 08 MOV ESI , DWORD PTR SS : [ ESP + 0x8 ]
* 0063 B495 33 C0 XOR EAX , EAX
* 0063 B497 57 PUSH EDI
* 0063 B498 85F 6 TEST ESI , ESI
* 0063 B49A 74 29 JE SHORT .0063 B4C5
* 0063 B49C 56 PUSH ESI
* 0063 B49D E8 FEE4FFFF CALL .006399 A0
* 0063 B4A2 8 D78 02 LEA EDI , DWORD PTR DS : [ EAX + 0x2 ]
* 0063 B4A5 57 PUSH EDI
* 0063 B4A6 FF15 94946700 CALL DWORD PTR DS : [ 0x679494 ] ; msvcrt . malloc
* 0063 B4AC 83 C4 08 ADD ESP , 0x8
* 0063 B4AF 85 C0 TEST EAX , EAX
* 0063 B4B1 74 12 JE SHORT .0063 B4C5
* 0063 B4B3 8 BCF MOV ECX , EDI
* 0063 B4B5 8 BF8 MOV EDI , EAX
* 0063 B4B7 8 BD1 MOV EDX , ECX
* 0063 B4B9 C1E9 02 SHR ECX , 0x2
* 0063 B4BC F3 : A5 REP MOVS DWORD PTR ES : [ EDI ] , DWORD PTR DS : [ ESI ]
* 0063 B4BE 8 BCA MOV ECX , EDX
* 0063 B4C0 83E1 03 AND ECX , 0x3
* 0063 B4C3 F3 : A4 REP MOVS BYTE PTR ES : [ EDI ] , BYTE PTR DS : [ ESI ]
* 0063 B4C5 5F POP EDI
* 0063 B4C6 5 E POP ESI
* 0063 B4C7 C3 RETN
* 0063 B4C8 90 NOP
* 0063 B4C9 90 NOP
* 0063 B4CA 90 NOP
* 0063 B4CB 90 NOP
*
* Sample game : 神 咒 神 威 神 楽 WEB体験版
* FIXME : Texts get disappeared
* 00517 A8D 90 NOP
* 00517 A8E 90 NOP
* 00517 A8F 90 NOP
* 00517 A90 56 PUSH ESI
* 00517 A91 8 B7424 08 MOV ESI , DWORD PTR SS : [ ESP + 0x8 ]
* 00517 A95 57 PUSH EDI
* 00517 A96 56 PUSH ESI
* 00517 A97 E8 64E5 FFFF CALL .00516000
* 00517 A9C 8 D78 02 LEA EDI , DWORD PTR DS : [ EAX + 0x2 ]
* 00517 A9F 57 PUSH EDI
* 00517 AA0 FF15 40745500 CALL DWORD PTR DS : [ 0x557440 ] ; msvcrt . malloc
* 00517 AA6 83 C4 08 ADD ESP , 0x8
* 00517 AA9 85 C0 TEST EAX , EAX
* 00517 AAB 74 12 JE SHORT .00517 ABF
* 00517 AAD 8 BCF MOV ECX , EDI
* 00517 AAF 8 BF8 MOV EDI , EAX
* 00517 AB1 8 BD1 MOV EDX , ECX
* 00517 AB3 C1E9 02 SHR ECX , 0x2
* 00517 AB6 F3 : A5 REP MOVS DWORD PTR ES : [ EDI ] , DWORD PTR DS >
* 00517 AB8 8 BCA MOV ECX , EDX
* 00517 ABA 83E1 03 AND ECX , 0x3
* 00517 ABD F3 : A4 REP MOVS BYTE PTR ES : [ EDI ] , BYTE PTR DS : [ >
* 00517 ABF 5F POP EDI
* 00517 AC0 5 E POP ESI
* 00517 AC1 C3 RETN
* 00517 AC2 90 NOP
* 00517 AC3 90 NOP
* 00517 AC4 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 .
*
* 0043 A82C 90 NOP
* 0043 A82D 90 NOP
* 0043 A82E 90 NOP
* 0043 A82F 90 NOP
* 0043 A830 53 PUSH EBX
* 0043 A831 55 PUSH EBP
* 0043 A832 56 PUSH ESI
* 0043 A833 57 PUSH EDI
* 0043 A834 E8 C7FFFFFF CALL malie .0043 A800
* 0043 A839 8 BF8 MOV EDI , EAX
* 0043 A83B 33F 6 XOR ESI , ESI
* 0043 A83D 85FF TEST EDI , EDI
* 0043 A83F 7 E 20 JLE SHORT malie .0043 A861
* 0043 A841 8 B5C24 14 MOV EBX , DWORD PTR SS : [ ESP + 0x14 ]
* 0043 A845 8 B2D 14256900 MOV EBP , DWORD PTR DS : [ < & MSVCRT . _wcsicmp > > ; msvcrt . _wcsicmp
* 0043 A84B 56 / PUSH ESI
* 0043 A84C E8 6FF FFFFF | CALL malie .0043 A7C0
* 0043 A851 50 | PUSH EAX
* 0043 A852 53 | PUSH EBX
* 0043 A853 FFD5 | CALL EBP
* 0043 A855 83 C4 0 C | ADD ESP , 0xC
* 0043 A858 85 C0 | TEST EAX , EAX
* 0043 A85A 74 0 D | JE SHORT malie .0043 A869
* 0043 A85C 46 | INC ESI
* 0043 A85D 3 BF7 | CMP ESI , EDI
* 0043 A85F ^ 7 C EA \ JL SHORT malie .0043 A84B
* 0043 A861 5F POP EDI
* 0043 A862 5 E POP ESI
* 0043 A863 5 D POP EBP
* 0043 A864 83 C8 FF OR EAX , 0xFFFFFFFF
* 0043 A867 5 B POP EBX
* 0043 A868 C3 RETN
* 0043 A869 5F POP EDI
* 0043 A86A 8 BC6 MOV EAX , ESI
* 0043 A86C 5 E POP ESI
* 0043 A86D 5 D POP EBP
* 0043 A86E 5 B POP EBX
* 0043 A86F C3 RETN
* 0043 A870 8 B4424 04 MOV EAX , DWORD PTR SS : [ ESP + 0x4 ]
* 0043 A874 83F 8 FF CMP EAX , - 0x1
* 0043 A877 75 05 JNZ SHORT malie .0043 A87E
* 0043 A879 E8 92FF FFFF CALL malie .0043 A810
* 0043 A87E 50 PUSH EAX
* 0043 A87F E8 3 CFFFFFF CALL malie .0043 A7C0
* 0043 A884 33 C9 XOR ECX , ECX
* 0043 A886 83 C4 04 ADD ESP , 0x4
* 0043 A889 66 : 8338 40 CMP WORD PTR DS : [ EAX ] , 0x40
* 0043 A88D 0F 94 C1 SETE CL
* 0043 A890 8 BC1 MOV EAX , ECX
* 0043 A892 C3 RETN
* 0043 A893 90 NOP
* 0043 A894 90 NOP
* 0043 A895 90 NOP
* 0043 A896 90 NOP
* 0043 A897 90 NOP
* 0043 A898 90 NOP
*
* 0278F 138 0043 AB90 RETURN to malie .0043 AB90 from malie .0043 A830
* 0278F 13 C 0278F 154 UNICODE " telopminpro "
* 0278F 140 0278F 154 UNICODE " telopminpro "
* 0278F 144 006 D2AE8 UNICODE " %s "
* 0278F 148 01 92 C990 UNICODE " telopminpro "
* 0278F 14 C 00000000
* 0278F 150 0 A33AAE0
* 0278F 154 00650074 malie .00650074
* 0278F 158 006F 006 C malie .006F 006 C
* 0278F 15 C 006 D0070 ASCII " Context "
* 0278F 160 006E0069 malie .006E0069
* 0278F 164 00720070 malie .00720070
* 0278F 168 0000006F
* 0278F 16 C 3F 088850
* 0278F 170 00000000
* 0278F 174 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 ;
2024-03-21 17:57:04 +08:00
write_string_new ( data , len , str ) ;
2024-02-07 20:59:24 +08:00
* 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 ;
}