#include "RPGMakerRGSS3.h" namespace { // unnamed namespace RGSS3 { namespace Private { std::vector glob(const std::wstring &relpath) { std::wstring path = std::wstring(MAX_PATH, 0); GetModuleFileNameW(nullptr, &path[0], MAX_PATH); size_t i = relpath.rfind(L'/'); if (i != std::wstring::npos) { std::wstring dir_path = path + L"/" + relpath.substr(0, i); WIN32_FIND_DATAW find_data; HANDLE hFind = FindFirstFileW((dir_path + L"/*").c_str(), &find_data); if (hFind == INVALID_HANDLE_VALUE) return {}; std::vector results; do { if ((find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || PathMatchSpecW(find_data.cFileName, relpath.substr(i + 1).c_str())) { results.push_back(dir_path + L"/" + find_data.cFileName); } } while (FindNextFileW(hFind, &find_data)); FindClose(hFind); return results; } else { WIN32_FIND_DATAW find_data; HANDLE hFind = FindFirstFileW(relpath.c_str(), &find_data); if (hFind == INVALID_HANDLE_VALUE) return {}; std::vector results; do { if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) results.push_back(find_data.cFileName); } while (FindNextFileW(hFind, &find_data)); FindClose(hFind); return results; } } std::wstring getDllModuleName() { for (const auto &dll : glob(L"System/RGSS3*.dll")) if (::GetModuleHandleW((LPCWSTR)dll.c_str())) return dll; return {}; } } // namespace Private bool getMemoryRange(ULONG *startAddress, ULONG *stopAddress) { std::wstring module = Private::getDllModuleName(); if (module.empty()) return false; auto [_1, _2] = Util::QueryModuleLimits(GetModuleHandle(module.c_str())); *startAddress = _1; *stopAddress = _2; return 1; } namespace ScenarioHook { /** * Sample game: * - Mogeko Castle with RGSS 3.01 * - 魔鎧の少女騎士エルトリンデ with RGSS 3.02 * * 1004149D CC INT3 * 1004149E CC INT3 * 1004149F CC INT3 * 100414A0 8B4C24 08 MOV ECX,DWORD PTR SS:[ESP+0x8] * 100414A4 8BC1 MOV EAX,ECX * 100414A6 E8 75030500 CALL RGSS301.10091820 * 100414AB 83F8 05 CMP EAX,0x5 * 100414AE 74 19 JE SHORT RGSS301.100414C9 * 100414B0 68 649D1A10 PUSH RGSS301.101A9D64 ; ASCII "to_str" * 100414B5 68 74931A10 PUSH RGSS301.101A9374 ; ASCII "String" * 100414BA 6A 05 PUSH 0x5 * 100414BC 51 PUSH ECX * 100414BD E8 AE2FFFFF CALL RGSS301.10034470 * 100414C2 83C4 10 ADD ESP,0x10 * 100414C5 894424 08 MOV DWORD PTR SS:[ESP+0x8],EAX * 100414C9 53 PUSH EBX * 100414CA 55 PUSH EBP * 100414CB 56 PUSH ESI * 100414CC 8B7424 10 MOV ESI,DWORD PTR SS:[ESP+0x10] * 100414D0 57 PUSH EDI * 100414D1 8B7C24 18 MOV EDI,DWORD PTR SS:[ESP+0x18] * 100414D5 57 PUSH EDI * 100414D6 56 PUSH ESI * 100414D7 E8 B4490100 CALL RGSS301.10055E90 * 100414DC 8BE8 MOV EBP,EAX * 100414DE 8B06 MOV EAX,DWORD PTR DS:[ESI] * 100414E0 83C4 08 ADD ESP,0x8 * 100414E3 A9 00200000 TEST EAX,0x2000 * 100414E8 75 08 JNZ SHORT RGSS301.100414F2 * 100414EA C1E8 0E SHR EAX,0xE * 100414ED 83E0 1F AND EAX,0x1F * 100414F0 EB 03 JMP SHORT RGSS301.100414F5 * 100414F2 8B46 08 MOV EAX,DWORD PTR DS:[ESI+0x8] * 100414F5 8B0F MOV ECX,DWORD PTR DS:[EDI] * 100414F7 F7C1 00200000 TEST ECX,0x2000 * 100414FD 75 08 JNZ SHORT RGSS301.10041507 * 100414FF C1E9 0E SHR ECX,0xE * 10041502 83E1 1F AND ECX,0x1F * 10041505 EB 03 JMP SHORT RGSS301.1004150A * 10041507 8B4F 08 MOV ECX,DWORD PTR DS:[EDI+0x8] * 1004150A 8D3401 LEA ESI,DWORD PTR DS:[ECX+EAX] * 1004150D A1 70C02A10 MOV EAX,DWORD PTR DS:[0x102AC070] * 10041512 50 PUSH EAX * 10041513 33FF XOR EDI,EDI * 10041515 E8 B64EFFFF CALL RGSS301.100363D0 * 1004151A 8B5424 18 MOV EDX,DWORD PTR SS:[ESP+0x18] ; jichi: edx = arg1 on the stack * 1004151E 8BD8 MOV EBX,EAX * 10041520 8B02 MOV EAX,DWORD PTR DS:[EDX] ; jichi: eax = ecx = [arg1] * 10041522 8BC8 MOV ECX,EAX * 10041524 83C4 04 ADD ESP,0x4 * 10041527 81E1 00200000 AND ECX,0x2000 * 1004152D 75 08 JNZ SHORT RGSS301.10041537 * 1004152F C1E8 0E SHR EAX,0xE * 10041532 83E0 1F AND EAX,0x1F * 10041535 EB 03 JMP SHORT RGSS301.1004153A * 10041537 8B42 08 MOV EAX,DWORD PTR DS:[EDX+0x8] ; jichi: [edx+0x8] text length * 1004153A 85C9 TEST ECX,ECX * 1004153C 75 05 JNZ SHORT RGSS301.10041543 * 1004153E 83C2 08 ADD EDX,0x8 * 10041541 EB 03 JMP SHORT RGSS301.10041546 * 10041543 8B52 0C MOV EDX,DWORD PTR DS:[EDX+0xC] ; jichi: [edx + 0xc] could be the text address * 10041546 F703 00200000 TEST DWORD PTR DS:[EBX],0x2000 * 1004154C 8D4B 08 LEA ECX,DWORD PTR DS:[EBX+0x8] * 1004154F 74 03 JE SHORT RGSS301.10041554 * 10041551 8B4B 0C MOV ECX,DWORD PTR DS:[EBX+0xC] * 10041554 50 PUSH EAX * 10041555 52 PUSH EDX * 10041556 51 PUSH ECX * 10041557 E8 E4F21300 CALL RGSS301.10180840 ; jichi: text is in edx * 1004155C 8B5424 24 MOV EDX,DWORD PTR SS:[ESP+0x24] * 10041560 8B02 MOV EAX,DWORD PTR DS:[EDX] * 10041562 8BC8 MOV ECX,EAX * 10041564 83C4 0C ADD ESP,0xC * 10041567 81E1 00200000 AND ECX,0x2000 * 1004156D 75 08 JNZ SHORT RGSS301.10041577 * * Stack: * 00828EB4 1002E5E6 RETURN to RGSS301.1002E5E6 from RGSS301.100414A0 * 00828EB8 03F13B20 * 00828EBC 069F42CC * 00828EC0 00000000 * 00828EC4 01699298 * 00828EC8 01699298 * 00828ECC 03EB41B8 * 00828ED0 01692A00 * 00828ED4 06A34548 * 00828ED8 00000000 * 00828EDC 00000168 * 00828EE0 00000280 * 00828EE4 000001E0 * 00828EE8 1019150F RETURN to RGSS301.1019150F from RGSS301.1018DF45 * * Here's the strncpy-like function for UTF8 strings, which is found using hardware breakpoints * Parameters: * - arg1 char *dest * - arg2 const char *src * - arg3 size_t size length of src excluding \0 at the end * * 1018083A CC INT3 * 1018083B CC INT3 * 1018083C CC INT3 * 1018083D CC INT3 * 1018083E CC INT3 * 1018083F CC INT3 * 10180840 55 PUSH EBP * 10180841 8BEC MOV EBP,ESP * 10180843 57 PUSH EDI * 10180844 56 PUSH ESI * 10180845 8B75 0C MOV ESI,DWORD PTR SS:[EBP+0xC] * 10180848 8B4D 10 MOV ECX,DWORD PTR SS:[EBP+0x10] * 1018084B 8B7D 08 MOV EDI,DWORD PTR SS:[EBP+0x8] * 1018084E 8BC1 MOV EAX,ECX * 10180850 8BD1 MOV EDX,ECX * 10180852 03C6 ADD EAX,ESI * 10180854 3BFE CMP EDI,ESI * 10180856 76 08 JBE SHORT RGSS301.10180860 * 10180858 3BF8 CMP EDI,EAX * 1018085A 0F82 A4010000 JB RGSS301.10180A04 * 10180860 81F9 00010000 CMP ECX,0x100 * 10180866 72 1F JB SHORT RGSS301.10180887 * 10180868 833D 4CC12A10 00 CMP DWORD PTR DS:[0x102AC14C],0x0 * 1018086F 74 16 JE SHORT RGSS301.10180887 * 10180871 57 PUSH EDI * 10180872 56 PUSH ESI * 10180873 83E7 0F AND EDI,0xF * 10180876 83E6 0F AND ESI,0xF * 10180879 3BFE CMP EDI,ESI * 1018087B 5E POP ESI * 1018087C 5F POP EDI * 1018087D 75 08 JNZ SHORT RGSS301.10180887 * 1018087F 5E POP ESI * 10180880 5F POP EDI * 10180881 5D POP EBP * 10180882 E9 05F80000 JMP RGSS301.1019008C * 10180887 F7C7 03000000 TEST EDI,0x3 * 1018088D 75 15 JNZ SHORT RGSS301.101808A4 * 1018088F C1E9 02 SHR ECX,0x2 * 10180892 83E2 03 AND EDX,0x3 * 10180895 83F9 08 CMP ECX,0x8 * 10180898 72 2A JB SHORT RGSS301.101808C4 * 1018089A F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS> * 1018089C FF2495 B4091810 JMP DWORD PTR DS:[EDX*4+0x101809B4] * 101808A3 90 NOP * 101808A4 8BC7 MOV EAX,EDI * 101808A6 BA 03000000 MOV EDX,0x3 * 101808AB 83E9 04 SUB ECX,0x4 * 101808AE 72 0C JB SHORT RGSS301.101808BC * 101808B0 83E0 03 AND EAX,0x3 * 101808B3 03C8 ADD ECX,EAX * 101808B5 FF2485 C8081810 JMP DWORD PTR DS:[EAX*4+0x101808C8] * 101808BC FF248D C4091810 JMP DWORD PTR DS:[ECX*4+0x101809C4] * 101808C3 90 NOP * 101808C4 FF248D 48091810 JMP DWORD PTR DS:[ECX*4+0x10180948] * 101808CB 90 NOP * 101808CC D808 FMUL DWORD PTR DS:[EAX] * 101808CE 1810 SBB BYTE PTR DS:[EAX],DL * 101808D0 04 09 ADD AL,0x9 * 101808D2 1810 SBB BYTE PTR DS:[EAX],DL * 101808D4 2809 SUB BYTE PTR DS:[ECX],CL * 101808D6 1810 SBB BYTE PTR DS:[EAX],DL * 101808D8 23D1 AND EDX,ECX * 101808DA 8A06 MOV AL,BYTE PTR DS:[ESI] * 101808DC 8807 MOV BYTE PTR DS:[EDI],AL * 101808DE 8A46 01 MOV AL,BYTE PTR DS:[ESI+0x1] * 101808E1 8847 01 MOV BYTE PTR DS:[EDI+0x1],AL * 101808E4 8A46 02 MOV AL,BYTE PTR DS:[ESI+0x2] * 101808E7 C1E9 02 SHR ECX,0x2 * 101808EA 8847 02 MOV BYTE PTR DS:[EDI+0x2],AL * 101808ED 83C6 03 ADD ESI,0x3 * 101808F0 83C7 03 ADD EDI,0x3 * 101808F3 83F9 08 CMP ECX,0x8 * 101808F6 ^72 CC JB SHORT RGSS301.101808C4 * 101808F8 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS> * 101808FA FF2495 B4091810 JMP DWORD PTR DS:[EDX*4+0x101809B4] * 10180901 8D49 00 LEA ECX,DWORD PTR DS:[ECX] * 10180904 23D1 AND EDX,ECX * 10180906 8A06 MOV AL,BYTE PTR DS:[ESI] * 10180908 8807 MOV BYTE PTR DS:[EDI],AL * 1018090A 8A46 01 MOV AL,BYTE PTR DS:[ESI+0x1] * 1018090D C1E9 02 SHR ECX,0x2 * 10180910 8847 01 MOV BYTE PTR DS:[EDI+0x1],AL * 10180913 83C6 02 ADD ESI,0x2 * 10180916 83C7 02 ADD EDI,0x2 * 10180919 83F9 08 CMP ECX,0x8 * 1018091C ^72 A6 JB SHORT RGSS301.101808C4 * 1018091E F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS> * 10180920 FF2495 B4091810 JMP DWORD PTR DS:[EDX*4+0x101809B4] * 10180927 90 NOP * 10180928 23D1 AND EDX,ECX * 1018092A 8A06 MOV AL,BYTE PTR DS:[ESI] * 1018092C 8807 MOV BYTE PTR DS:[EDI],AL * 1018092E 83C6 01 ADD ESI,0x1 * 10180931 C1E9 02 SHR ECX,0x2 * 10180934 83C7 01 ADD EDI,0x1 * 10180937 83F9 08 CMP ECX,0x8 * 1018093A ^72 88 JB SHORT RGSS301.101808C4 * 1018093C F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS> * 1018093E FF2495 B4091810 JMP DWORD PTR DS:[EDX*4+0x101809B4] * 10180945 8D49 00 LEA ECX,DWORD PTR DS:[ECX] * 10180948 AB STOS DWORD PTR ES:[EDI] * 10180949 0918 OR DWORD PTR DS:[EAX],EBX * 1018094B 1098 09181090 ADC BYTE PTR DS:[EAX+0x90101809],BL * 10180951 0918 OR DWORD PTR DS:[EAX],EBX * 10180953 1088 09181080 ADC BYTE PTR DS:[EAX+0x80101809],CL * 10180959 0918 OR DWORD PTR DS:[EAX],EBX * 1018095B 1078 09 ADC BYTE PTR DS:[EAX+0x9],BH * 1018095E 1810 SBB BYTE PTR DS:[EAX],DL * 10180960 70 09 JO SHORT RGSS301.1018096B * 10180962 1810 SBB BYTE PTR DS:[EAX],DL * 10180964 68 0918108B PUSH 0x8B101809 * 10180969 44 INC ESP * 1018096A 8EE4 MOV FS,SP ; Modification of segment register * 1018096C 89448F E4 MOV DWORD PTR DS:[EDI+ECX*4-0x1C],EAX * 10180970 8B448E E8 MOV EAX,DWORD PTR DS:[ESI+ECX*4-0x18] * 10180974 89448F E8 MOV DWORD PTR DS:[EDI+ECX*4-0x18],EAX * 10180978 8B448E EC MOV EAX,DWORD PTR DS:[ESI+ECX*4-0x14] * 1018097C 89448F EC MOV DWORD PTR DS:[EDI+ECX*4-0x14],EAX * 10180980 8B448E F0 MOV EAX,DWORD PTR DS:[ESI+ECX*4-0x10] * 10180984 89448F F0 MOV DWORD PTR DS:[EDI+ECX*4-0x10],EAX * 10180988 8B448E F4 MOV EAX,DWORD PTR DS:[ESI+ECX*4-0xC] * 1018098C 89448F F4 MOV DWORD PTR DS:[EDI+ECX*4-0xC],EAX * 10180990 8B448E F8 MOV EAX,DWORD PTR DS:[ESI+ECX*4-0x8] * 10180994 89448F F8 MOV DWORD PTR DS:[EDI+ECX*4-0x8],EAX * 10180998 8B448E FC MOV EAX,DWORD PTR DS:[ESI+ECX*4-0x4] * 1018099C 89448F FC MOV DWORD PTR DS:[EDI+ECX*4-0x4],EAX * 101809A0 8D048D 00000000 LEA EAX,DWORD PTR DS:[ECX*4] * 101809A7 03F0 ADD ESI,EAX * 101809A9 03F8 ADD EDI,EAX * 101809AB FF2495 B4091810 JMP DWORD PTR DS:[EDX*4+0x101809B4] * 101809B2 8BFF MOV EDI,EDI * 101809B4 C409 LES ECX,FWORD PTR DS:[ECX] ; Modification of segment register * 101809B6 1810 SBB BYTE PTR DS:[EAX],DL * 101809B8 CC INT3 * 101809B9 0918 OR DWORD PTR DS:[EAX],EBX * 101809BB 10D8 ADC AL,BL * 101809BD 0918 OR DWORD PTR DS:[EAX],EBX * 101809BF 10EC ADC AH,CH * 101809C1 0918 OR DWORD PTR DS:[EAX],EBX * 101809C3 108B 45085E5F ADC BYTE PTR DS:[EBX+0x5F5E0845],CL * 101809C9 C9 LEAVE * 101809CA C3 RETN * 101809CB 90 NOP * 101809CC 8A06 MOV AL,BYTE PTR DS:[ESI] * 101809CE 8807 MOV BYTE PTR DS:[EDI],AL * 101809D0 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8] * 101809D3 5E POP ESI * 101809D4 5F POP EDI * 101809D5 C9 LEAVE * 101809D6 C3 RETN * 101809D7 90 NOP * 101809D8 8A06 MOV AL,BYTE PTR DS:[ESI] * 101809DA 8807 MOV BYTE PTR DS:[EDI],AL * 101809DC 8A46 01 MOV AL,BYTE PTR DS:[ESI+0x1] * 101809DF 8847 01 MOV BYTE PTR DS:[EDI+0x1],AL * 101809E2 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8] * 101809E5 5E POP ESI * 101809E6 5F POP EDI * 101809E7 C9 LEAVE * 101809E8 C3 RETN * 101809E9 8D49 00 LEA ECX,DWORD PTR DS:[ECX] * 101809EC 8A06 MOV AL,BYTE PTR DS:[ESI] * 101809EE 8807 MOV BYTE PTR DS:[EDI],AL * 101809F0 8A46 01 MOV AL,BYTE PTR DS:[ESI+0x1] * 101809F3 8847 01 MOV BYTE PTR DS:[EDI+0x1],AL * 101809F6 8A46 02 MOV AL,BYTE PTR DS:[ESI+0x2] * 101809F9 8847 02 MOV BYTE PTR DS:[EDI+0x2],AL * 101809FC 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8] * 101809FF 5E POP ESI * 10180A00 5F POP EDI * 10180A01 C9 LEAVE * 10180A02 C3 RETN * 10180A03 90 NOP * 10180A04 8D7431 FC LEA ESI,DWORD PTR DS:[ECX+ESI-0x4] * 10180A08 8D7C39 FC LEA EDI,DWORD PTR DS:[ECX+EDI-0x4] * 10180A0C F7C7 03000000 TEST EDI,0x3 * 10180A12 75 24 JNZ SHORT RGSS301.10180A38 * 10180A14 C1E9 02 SHR ECX,0x2 * 10180A17 83E2 03 AND EDX,0x3 * 10180A1A 83F9 08 CMP ECX,0x8 * 10180A1D 72 0D JB SHORT RGSS301.10180A2C * 10180A1F FD STD * 10180A20 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS> * 10180A22 FC CLD * 10180A23 FF2495 500B1810 JMP DWORD PTR DS:[EDX*4+0x10180B50] * 10180A2A 8BFF MOV EDI,EDI * 10180A2C F7D9 NEG ECX * 10180A2E FF248D 000B1810 JMP DWORD PTR DS:[ECX*4+0x10180B00] * 10180A35 8D49 00 LEA ECX,DWORD PTR DS:[ECX] * 10180A38 8BC7 MOV EAX,EDI * 10180A3A BA 03000000 MOV EDX,0x3 * 10180A3F 83F9 04 CMP ECX,0x4 * 10180A42 72 0C JB SHORT RGSS301.10180A50 * 10180A44 83E0 03 AND EAX,0x3 * 10180A47 2BC8 SUB ECX,EAX * 10180A49 FF2485 540A1810 JMP DWORD PTR DS:[EAX*4+0x10180A54] * 10180A50 FF248D 500B1810 JMP DWORD PTR DS:[ECX*4+0x10180B50] * 10180A57 90 NOP * 10180A58 64:0A18 OR BL,BYTE PTR FS:[EAX] * 10180A5B 1088 0A1810B0 ADC BYTE PTR DS:[EAX+0xB010180A],CL * 10180A61 0A18 OR BL,BYTE PTR DS:[EAX] * 10180A63 108A 460323D1 ADC BYTE PTR DS:[EDX+0xD1230346],CL * 10180A69 8847 03 MOV BYTE PTR DS:[EDI+0x3],AL * 10180A6C 83EE 01 SUB ESI,0x1 * 10180A6F C1E9 02 SHR ECX,0x2 * 10180A72 83EF 01 SUB EDI,0x1 * 10180A75 83F9 08 CMP ECX,0x8 * 10180A78 ^72 B2 JB SHORT RGSS301.10180A2C * 10180A7A FD STD * 10180A7B F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS> * 10180A7D FC CLD * 10180A7E FF2495 500B1810 JMP DWORD PTR DS:[EDX*4+0x10180B50] * 10180A85 8D49 00 LEA ECX,DWORD PTR DS:[ECX] * 10180A88 8A46 03 MOV AL,BYTE PTR DS:[ESI+0x3] * 10180A8B 23D1 AND EDX,ECX * 10180A8D 8847 03 MOV BYTE PTR DS:[EDI+0x3],AL * 10180A90 8A46 02 MOV AL,BYTE PTR DS:[ESI+0x2] * 10180A93 C1E9 02 SHR ECX,0x2 * 10180A96 8847 02 MOV BYTE PTR DS:[EDI+0x2],AL * 10180A99 83EE 02 SUB ESI,0x2 * 10180A9C 83EF 02 SUB EDI,0x2 * 10180A9F 83F9 08 CMP ECX,0x8 * 10180AA2 ^72 88 JB SHORT RGSS301.10180A2C * 10180AA4 FD STD * 10180AA5 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS> * 10180AA7 FC CLD * 10180AA8 FF2495 500B1810 JMP DWORD PTR DS:[EDX*4+0x10180B50] * 10180AAF 90 NOP * 10180AB0 8A46 03 MOV AL,BYTE PTR DS:[ESI+0x3] * 10180AB3 23D1 AND EDX,ECX * 10180AB5 8847 03 MOV BYTE PTR DS:[EDI+0x3],AL * 10180AB8 8A46 02 MOV AL,BYTE PTR DS:[ESI+0x2] * 10180ABB 8847 02 MOV BYTE PTR DS:[EDI+0x2],AL * 10180ABE 8A46 01 MOV AL,BYTE PTR DS:[ESI+0x1] * 10180AC1 C1E9 02 SHR ECX,0x2 * 10180AC4 8847 01 MOV BYTE PTR DS:[EDI+0x1],AL * 10180AC7 83EE 03 SUB ESI,0x3 * 10180ACA 83EF 03 SUB EDI,0x3 * 10180ACD 83F9 08 CMP ECX,0x8 * 10180AD0 ^0F82 56FFFFFF JB RGSS301.10180A2C * 10180AD6 FD STD * 10180AD7 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS> * 10180AD9 FC CLD * 10180ADA FF2495 500B1810 JMP DWORD PTR DS:[EDX*4+0x10180B50] * 10180AE1 8D49 00 LEA ECX,DWORD PTR DS:[ECX] * 10180AE4 04 0B ADD AL,0xB * 10180AE6 1810 SBB BYTE PTR DS:[EAX],DL * 10180AE8 0C 0B OR AL,0xB * 10180AEA 1810 SBB BYTE PTR DS:[EAX],DL * 10180AEC 14 0B ADC AL,0xB * 10180AEE 1810 SBB BYTE PTR DS:[EAX],DL * 10180AF0 1C 0B SBB AL,0xB * 10180AF2 1810 SBB BYTE PTR DS:[EAX],DL * 10180AF4 24 0B AND AL,0xB * 10180AF6 1810 SBB BYTE PTR DS:[EAX],DL * 10180AF8 2C 0B SUB AL,0xB * 10180AFA 1810 SBB BYTE PTR DS:[EAX],DL * 10180AFC 34 0B XOR AL,0xB * 10180AFE 1810 SBB BYTE PTR DS:[EAX],DL * 10180B00 47 INC EDI * 10180B01 0B18 OR EBX,DWORD PTR DS:[EAX] * 10180B03 108B 448E1C89 ADC BYTE PTR DS:[EBX+0x891C8E44],CL * 10180B09 44 INC ESP * 10180B0A 8F ??? ; Unknown command * 10180B0B 1C 8B SBB AL,0x8B * 10180B0D 44 INC ESP * 10180B0E 8E18 MOV DS,WORD PTR DS:[EAX] ; Modification of segment register * 10180B10 89448F 18 MOV DWORD PTR DS:[EDI+ECX*4+0x18],EAX * 10180B14 8B448E 14 MOV EAX,DWORD PTR DS:[ESI+ECX*4+0x14] * 10180B18 89448F 14 MOV DWORD PTR DS:[EDI+ECX*4+0x14],EAX * 10180B1C 8B448E 10 MOV EAX,DWORD PTR DS:[ESI+ECX*4+0x10] * 10180B20 89448F 10 MOV DWORD PTR DS:[EDI+ECX*4+0x10],EAX * 10180B24 8B448E 0C MOV EAX,DWORD PTR DS:[ESI+ECX*4+0xC] * 10180B28 89448F 0C MOV DWORD PTR DS:[EDI+ECX*4+0xC],EAX * 10180B2C 8B448E 08 MOV EAX,DWORD PTR DS:[ESI+ECX*4+0x8] * 10180B30 89448F 08 MOV DWORD PTR DS:[EDI+ECX*4+0x8],EAX * 10180B34 8B448E 04 MOV EAX,DWORD PTR DS:[ESI+ECX*4+0x4] * 10180B38 89448F 04 MOV DWORD PTR DS:[EDI+ECX*4+0x4],EAX * 10180B3C 8D048D 00000000 LEA EAX,DWORD PTR DS:[ECX*4] * 10180B43 03F0 ADD ESI,EAX * 10180B45 03F8 ADD EDI,EAX * 10180B47 FF2495 500B1810 JMP DWORD PTR DS:[EDX*4+0x10180B50] * 10180B4E 8BFF MOV EDI,EDI * 10180B50 60 PUSHAD * 10180B51 0B18 OR EBX,DWORD PTR DS:[EAX] * 10180B53 1068 0B ADC BYTE PTR DS:[EAX+0xB],CH * 10180B56 1810 SBB BYTE PTR DS:[EAX],DL * 10180B58 78 0B JS SHORT RGSS301.10180B65 * 10180B5A 1810 SBB BYTE PTR DS:[EAX],DL * 10180B5C 8C0B MOV WORD PTR DS:[EBX],CS * 10180B5E 1810 SBB BYTE PTR DS:[EAX],DL * 10180B60 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8] * 10180B63 5E POP ESI * 10180B64 5F POP EDI * 10180B65 C9 LEAVE * 10180B66 C3 RETN * 10180B67 90 NOP * 10180B68 8A46 03 MOV AL,BYTE PTR DS:[ESI+0x3] * 10180B6B 8847 03 MOV BYTE PTR DS:[EDI+0x3],AL * 10180B6E 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8] * 10180B71 5E POP ESI * 10180B72 5F POP EDI * 10180B73 C9 LEAVE * 10180B74 C3 RETN * 10180B75 8D49 00 LEA ECX,DWORD PTR DS:[ECX] * 10180B78 8A46 03 MOV AL,BYTE PTR DS:[ESI+0x3] * 10180B7B 8847 03 MOV BYTE PTR DS:[EDI+0x3],AL * 10180B7E 8A46 02 MOV AL,BYTE PTR DS:[ESI+0x2] * 10180B81 8847 02 MOV BYTE PTR DS:[EDI+0x2],AL * 10180B84 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8] * 10180B87 5E POP ESI * 10180B88 5F POP EDI * 10180B89 C9 LEAVE * 10180B8A C3 RETN * 10180B8B 90 NOP * 10180B8C 8A46 03 MOV AL,BYTE PTR DS:[ESI+0x3] * 10180B8F 8847 03 MOV BYTE PTR DS:[EDI+0x3],AL * 10180B92 8A46 02 MOV AL,BYTE PTR DS:[ESI+0x2] * 10180B95 8847 02 MOV BYTE PTR DS:[EDI+0x2],AL * 10180B98 8A46 01 MOV AL,BYTE PTR DS:[ESI+0x1] * 10180B9B 8847 01 MOV BYTE PTR DS:[EDI+0x1],AL * 10180B9E 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8] * 10180BA1 5E POP ESI * 10180BA2 5F POP EDI * 10180BA3 C9 LEAVE * 10180BA4 C3 RETN * 10180BA5 CC INT3 * 10180BA6 CC INT3 * 10180BA7 CC INT3 * 10180BA8 CC INT3 * 10180BA9 CC INT3 * 10180BAA CC INT3 * 10180BAB CC INT3 */ namespace Private { // enum { MaxTextSize = 0x1000 }; // char oldText_[MaxTextSize + 1]; // 1 extra 0 that is always 0 // size_t oldSize_; struct HookArgument { LPDWORD type; // 0x0 LPDWORD unknown; // 0x4 size_t size; // 0x8 LPCSTR text; // 0xc, editable though bool isValid() const { return Engine::isAddressReadable(type) && *type && size && size < 1500 && Engine::isAddressWritable(text, size + 1) && *text && text[size] == 0 && ::strlen(text) == size // validate size //&& !::strchr(text, '/') && !all_ascii(text); } // int size() const { return (*type >> 0xe) & 0x1f; } }; inline bool _trims(const wchar_t &ch) { return ch <= 127 || std::isspace(ch, std::locale("ja_JP.SJIS")); } std::wstring trim(const std::wstring &text, std::wstring *prefix = nullptr, std::wstring *suffix = nullptr) { if (text.empty() || !_trims(text[0]) && !_trims(text[text.size() - 1])) return text; std::wstring ret = text; if (_trims(ret[0])) { int pos = 1; for (; pos < ret.size() && _trims(ret[pos]); pos++) ; if (prefix) *prefix = ret.substr(0, pos); ret = ret.substr(pos); } if (!ret.empty() && _trims(ret[ret.size() - 1])) { int pos = ret.size() - 2; for (; pos >= 0 && _trims(ret[pos]); pos--) ; if (suffix) *suffix = ret.substr(pos + 1); ret = ret.substr(0, pos + 1); } return ret; } // bool textsContains(const QSet &texts, const QString &text) //{ // if (texts.contains(text)) // return true; // if (text.contains('\n')) // 0xa, skip translation if any of the part has been translated // foreach (const QString &it, text.split('\n', QString::SkipEmptyParts)) // if (texts.contains(it)) // return true; // return false; // } int guessTextRole(const std::wstring &text) { enum { MaxNameSize = 100 }; enum : wchar_t { w_square_open = 0x3010 /* 【 */ , w_square_close = 0x3011 /* 】 */ }; if (text.size() > 2 && text.size() < MaxNameSize && text[0] == w_square_open && text[text.size() - 1] == w_square_close) return Engine::NameRole; return Engine::ScenarioRole; } std::string data_; HookArgument *arg_; LPCSTR oldText_; size_t oldSize_; std::unordered_set texts_; void hookafter2(hook_stack *s, void *data1, size_t len) { enum { RecentTextCapacity = 4 }; static std::vector recentTexts_; // used to eliminate recent duplicates auto arg = (HookArgument *)s->stack[0]; // arg1 if (arg && arg->isValid()) { // && (quint8)arg->text[0] > 127) { // skip translate text beginning with ascii character std::wstring oldText = StringToWideString(std::string(arg->text, arg->size), CP_UTF8).value(), // QString::fromUtf8(arg->text, arg->size), prefix, suffix, trimmedText = trim(oldText, &prefix, &suffix); if (!trimmedText.empty() && (texts_.find(trimmedText) == texts_.end())) { // skip text beginning with ascii character // ULONG split = arg->unknown2[0]; // always 2 // ULONG split = s->stack[0]; // return address std::wstring newText = std::wstring((wchar_t *)data1, len / 2); if (newText != trimmedText) { texts_.insert(newText); texts_.insert(trim(newText)); // in case there are leading/trailing English letters in the translation if (!prefix.empty()) newText.insert(0, prefix); if (!suffix.empty()) newText.append(suffix); // texts_.insert(newText); data_ = WideStringToString(newText, CP_UTF8); // newText.toUtf8(); arg_ = arg; oldSize_ = arg->size; oldText_ = arg->text; //::memcpy(oldText_, arg->text, qMin(arg->size + 1, MaxTextSize)); // memcpy also works arg->size = data_.size(); arg->text = data_.c_str(); } } } } bool hookBefore(hook_stack *s, void *data1, size_t *len1, uintptr_t *role) { enum { RecentTextCapacity = 4 }; static std::vector recentTexts_; // used to eliminate recent duplicates auto arg = (HookArgument *)s->stack[0]; // arg1 if (arg && arg->isValid()) { // && (quint8)arg->text[0] > 127) { // skip translate text beginning with ascii character std::wstring oldText = StringToWideString(std::string(arg->text, arg->size), CP_UTF8).value(), // QString::fromUtf8(arg->text, arg->size), prefix, suffix, trimmedText = trim(oldText, &prefix, &suffix); if (!trimmedText.empty() && (texts_.find(trimmedText) == texts_.end())) { // skip text beginning with ascii character const bool sendAllowed = (std::find(recentTexts_.begin(), recentTexts_.end(), oldText) == recentTexts_.end()); if (sendAllowed) { recentTexts_.push_back(oldText); if (recentTexts_.size() > RecentTextCapacity) recentTexts_.erase(recentTexts_.begin()); } // ULONG split = arg->unknown2[0]; // always 2 // ULONG split = s->stack[0]; // return address std::wstring newText; write_string_overwrite(data1, len1, trimmedText); return 1; if (newText != trimmedText) { texts_.insert(newText); texts_.insert(trim(newText)); // in case there are leading/trailing English letters in the translation if (!prefix.empty()) newText.insert(0, prefix); if (!suffix.empty()) newText.append(suffix); // texts_.insert(newText); data_ = WideStringToString(newText, CP_UTF8); // newText.toUtf8(); arg_ = arg; oldSize_ = arg->size; oldText_ = arg->text; //::memcpy(oldText_, arg->text, qMin(arg->size + 1, MaxTextSize)); // memcpy also works arg->size = data_.size(); arg->text = data_.c_str(); } } } return 0; } bool hookAfter(hook_stack *s, void *data1, size_t *len1, uintptr_t *role) { if (arg_) { arg_->size = oldSize_; arg_->text = oldText_; //::strcpy(arg_->text, oldText_); arg_ = nullptr; } return 0; } } // namespace Private bool attach(ULONG startAddress, ULONG stopAddress) // attach scenario { const uint8_t bytes[] = { 0x8b, 0x54, 0x24, 0x24, // 1004155c 8b5424 24 mov edx,dword ptr ss:[esp+0x24] 0x8b, 0x02, // 10041560 8b02 mov eax,dword ptr ds:[edx] 0x8b, 0xc8, // 10041562 8bc8 mov ecx,eax 0x83, 0xc4, 0x0c, // 10041564 83c4 0c add esp,0xc 0x81, 0xe1, 0x00, 0x20, 0x00, 0x00 // 10041567 81e1 00200000 and ecx,0x2000 }; ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress); if (!addr) return false; addr = MemDbg::findEnclosingAlignedFunction(addr); if (!addr) return false; // addr = MemDbg::findPushAddress(addr, startAddress, stopAddress); // addr = 0x10041557; // addr = 0x100414a0; // addr = 0x10056BC0; // addr = 0x1002e5e1; addr = MemDbg::findNearCallAddress(addr, startAddress, stopAddress); if (!addr) return false; // return winhook::hook_both(addr, Private::hookBefore, Private::hookAfter); HookParam hp; hp.address = addr; hp.hook_before = Private::hookBefore; hp.hook_after = Private::hookafter2; hp.type = USING_STRING | CODEC_UTF16 | EMBED_ABLE; hp.hook_font = F_GetGlyphOutlineW; auto succ = NewHook(hp, "EmbedRGSS3"); hp.address = addr + 5; hp.hook_before = Private::hookAfter; hp.type = HOOK_EMPTY | EMBED_ABLE; succ |= NewHook(hp, "EmbedRGSS3"); return succ; } } // namespace ScenarioHook namespace ChoiceHook { namespace Private { struct HookArgument { LPDWORD unknown1, unknown2, unknown3; LPSTR text; // arg2 + 0xc bool isValid() const { return text && Engine::isAddressReadable(text) && *text && Engine::isAddressWritable(text, ::strlen(text)); } // int size() const { return (*type >> 0xe) & 0x1f; } }; bool hookBefore(hook_stack *s, void *data1, size_t *len1, uintptr_t *role) { *role = Engine::OtherRole; auto arg = (HookArgument *)s->stack[2]; // arg2 if (arg->isValid()) { auto oldText = StringToWideString(std::string(arg->text), CP_UTF8).value(); auto split = s->stack[0]; // return address write_string_overwrite(data1, len1, oldText); return 1; // std::wstring newText = EngineController::instance()->dispatchTextWSTD(oldText, role, sig); // if (newText != oldText) { // if (newText.size() < oldText.size()) // ::memset(arg->text, 0, ::strlen(arg->text)); // ::strcpy(arg->text, WideStringToString(newText, CP_UTF8).c_str());// newText.toUtf8()); // } } return 0; } void hookafter2(hook_stack *s, void *data1, size_t len) { { auto arg = (HookArgument *)s->stack[2]; // arg2 if (arg->isValid()) { auto oldText = StringToWideString(std::string(arg->text), CP_UTF8).value(); auto split = s->stack[0]; // return address std::wstring old = oldText; std::wstring newText = std::wstring((wchar_t *)data1, len / 2); if (newText != oldText) { if (newText.size() < oldText.size()) ::memset(arg->text, 0, ::strlen(arg->text)); ::strcpy(arg->text, WideStringToString(newText, CP_UTF8).c_str()); // newText.toUtf8()); } } } } // namespace Private /** * Sample game: Mogeko Castle * * One of the caller of the three GetGlyphOutlineW * * The paint function, where text get lost. Text in [[arg2]+0xc] in UTF8 encoding. * 1000751D CC INT3 * 1000751E CC INT3 * 1000751F CC INT3 * 10007520 55 PUSH EBP * 10007521 8BEC MOV EBP,ESP * 10007523 83EC 28 SUB ESP,0x28 * 10007526 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8] * 10007529 50 PUSH EAX * 1000752A E8 51E6FFFF CALL RGSS301.10005B80 * 1000752F 83C4 04 ADD ESP,0x4 * 10007532 8945 D8 MOV DWORD PTR SS:[EBP-0x28],EAX * 10007535 68 08781A10 PUSH RGSS301.101A7808 ; ASCII "font" * 1000753A 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+0x8] * 1000753D 51 PUSH ECX * 1000753E E8 6D0E0600 CALL RGSS301.100683B0 * 10007543 83C4 08 ADD ESP,0x8 * 10007546 8945 E4 MOV DWORD PTR SS:[EBP-0x1C],EAX * 10007549 8B55 E4 MOV EDX,DWORD PTR SS:[EBP-0x1C] * 1000754C 8B42 10 MOV EAX,DWORD PTR DS:[EDX+0x10] * 1000754F 8945 F8 MOV DWORD PTR SS:[EBP-0x8],EAX * 10007552 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+0xC] * 10007555 51 PUSH ECX * 10007556 E8 15F90200 CALL RGSS301.10036E70 * 1000755B 83C4 04 ADD ESP,0x4 * 1000755E 8945 E0 MOV DWORD PTR SS:[EBP-0x20],EAX * 10007561 8D55 E0 LEA EDX,DWORD PTR SS:[EBP-0x20] * 10007564 52 PUSH EDX * 10007565 E8 36070300 CALL RGSS301.10037CA0 * 1000756A 83C4 04 ADD ESP,0x4 * 1000756D 8945 DC MOV DWORD PTR SS:[EBP-0x24],EAX * 10007570 8B45 D8 MOV EAX,DWORD PTR SS:[EBP-0x28] * 10007573 8B48 08 MOV ECX,DWORD PTR DS:[EAX+0x8] * 10007576 E8 651F0100 CALL RGSS301.100194E0 * 1000757B 8945 F4 MOV DWORD PTR SS:[EBP-0xC],EAX * 1000757E 83EC 08 SUB ESP,0x8 * 10007581 D9E8 FLD1 * 10007583 DD1C24 FSTP QWORD PTR SS:[ESP] * 10007586 8B4D F4 MOV ECX,DWORD PTR SS:[EBP-0xC] * 10007589 E8 A2210100 CALL RGSS301.10019730 * 1000758E 6A 00 PUSH 0x0 * 10007590 6A 00 PUSH 0x0 * 10007592 6A 00 PUSH 0x0 * 10007594 8D4D EC LEA ECX,DWORD PTR SS:[EBP-0x14] * 10007597 51 PUSH ECX * 10007598 8B55 DC MOV EDX,DWORD PTR SS:[EBP-0x24] * 1000759B 52 PUSH EDX * 1000759C E8 CF500000 CALL RGSS301.1000C670 ; jichi: convert utf8 text in edx to utf16 in eax * 100075A1 83C4 04 ADD ESP,0x4 * 100075A4 50 PUSH EAX * 100075A5 8B45 D8 MOV EAX,DWORD PTR SS:[EBP-0x28] * 100075A8 8B48 08 MOV ECX,DWORD PTR DS:[EAX+0x8] * 100075AB E8 A07B0100 CALL RGSS301.1001F150 ; jichi: utf16 text paint here * 100075B0 E8 7BAB0000 CALL RGSS301.10012130 * 100075B5 8945 FC MOV DWORD PTR SS:[EBP-0x4],EAX * 100075B8 8B4D FC MOV ECX,DWORD PTR SS:[EBP-0x4] * 100075BB 8B51 10 MOV EDX,DWORD PTR DS:[ECX+0x10] * 100075BE 8955 E8 MOV DWORD PTR SS:[EBP-0x18],EDX * 100075C1 8B45 E8 MOV EAX,DWORD PTR SS:[EBP-0x18] * 100075C4 C740 08 00000000 MOV DWORD PTR DS:[EAX+0x8],0x0 * 100075CB 8B4D E8 MOV ECX,DWORD PTR SS:[EBP-0x18] * 100075CE C741 0C 00000000 MOV DWORD PTR DS:[ECX+0xC],0x0 * 100075D5 8B55 E8 MOV EDX,DWORD PTR SS:[EBP-0x18] * 100075D8 8B45 EC MOV EAX,DWORD PTR SS:[EBP-0x14] * 100075DB 8942 10 MOV DWORD PTR DS:[EDX+0x10],EAX * 100075DE 8B4D E8 MOV ECX,DWORD PTR SS:[EBP-0x18] * 100075E1 8B55 F0 MOV EDX,DWORD PTR SS:[EBP-0x10] * 100075E4 8951 14 MOV DWORD PTR DS:[ECX+0x14],EDX * 100075E7 8B45 FC MOV EAX,DWORD PTR SS:[EBP-0x4] * 100075EA 8BE5 MOV ESP,EBP * 100075EC 5D POP EBP * 100075ED C3 RETN * 100075EE CC INT3 */ ULONG functionAddress; // the function address being hooked bool attach(ULONG startAddress, ULONG stopAddress) // attach other text { const uint8_t bytes[] = { 0x89, 0x45, 0xfc, // 100075b5 8945 fc mov dword ptr ss:[ebp-0x4],eax 0x8b, 0x4d, 0xfc, // 100075b8 8b4d fc mov ecx,dword ptr ss:[ebp-0x4] 0x8b, 0x51, 0x10, // 100075bb 8b51 10 mov edx,dword ptr ds:[ecx+0x10] 0x89, 0x55, 0xe8, // 100075be 8955 e8 mov dword ptr ss:[ebp-0x18],edx 0x8b, 0x45, 0xe8 // 100075c1 8b45 e8 mov eax,dword ptr ss:[ebp-0x18] }; if (ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress)) if (addr = MemDbg::findEnclosingAlignedFunction(addr)) { HookParam hp; hp.address = addr; hp.hook_before = Private::hookBefore; hp.hook_after = Private::hookafter2; hp.type = USING_STRING | CODEC_UTF16 | EMBED_ABLE; hp.hook_font = F_GetGlyphOutlineW; functionAddress = addr; return NewHook(hp, "EmbedRGSS3Choice"); } return false; } } // namespace ChoiceHook } namespace OtherHook { namespace Private { bool hookBefore(hook_stack *s, void *data1, size_t *len1, uintptr_t *role) { { *role = Engine::OtherRole; }; auto retaddr = s->stack[0]; if (retaddr > ChoiceHook::Private::functionAddress && retaddr - ChoiceHook::Private::functionAddress < 0xff) return 0; // skip translate already-hooked function auto text = (LPWSTR)s->stack[1]; // arg1 if (text && *text) { std::wstring oldText(text); if (oldText.size() > 1) { write_string_overwrite(data1, len1, oldText); return 1; } } return 0; } void hookafter2(hook_stack *s, void *data1, size_t len) { { auto retaddr = s->stack[0]; if (retaddr > ChoiceHook::Private::functionAddress && retaddr - ChoiceHook::Private::functionAddress < 0xff) return; // skip translate already-hooked function auto text = (LPWSTR)s->stack[1]; // arg1 if (text && *text) { std::wstring oldText(text); if (oldText.size() > 1) { std::wstring newText = std::wstring((wchar_t *)data1, len / 2); ; if (newText != oldText) ::wcscpy(text, (LPCWSTR)newText.c_str()); } } } } // namespace Private /** * Sample game: Mogeko Castle * * There are three GetGlyphIndicesW. * The caller of the first one is hooked. * * The first caller of GetGlyphOutlineW, text in arg1, which is other thread: * * 00826D48 10007251 RETURN to RGSS301.10007251 from RGSS301.1001F150 * 00826D4C 00826D9C ; jichi: text here * 00826D50 00828DC8 ASCII "H?" * 00826D54 00000001 * 00826D58 00000001 * 00826D5C 00828DEC * 00826D60 40000000 * 00826D64 008283A8 * 00826D68 1018DF60 RGSS301.1018DF60 * * 1001F14B CC INT3 * 1001F14C CC INT3 * 1001F14D CC INT3 * 1001F14E CC INT3 * 1001F14F CC INT3 * 1001F150 55 PUSH EBP * 1001F151 8BEC MOV EBP,ESP * 1001F153 81EC 88000000 SUB ESP,0x88 * 1001F159 894D 8C MOV DWORD PTR SS:[EBP-0x74],ECX * 1001F15C 837D 18 00 CMP DWORD PTR SS:[EBP+0x18],0x0 * 1001F160 74 09 JE SHORT RGSS301.1001F16B * 1001F162 8B45 18 MOV EAX,DWORD PTR SS:[EBP+0x18] * 1001F165 C700 01000000 MOV DWORD PTR DS:[EAX],0x1 * 1001F16B 8B4D 8C MOV ECX,DWORD PTR SS:[EBP-0x74] * 1001F16E E8 6DA3FFFF CALL RGSS301.100194E0 * 1001F173 85C0 TEST EAX,EAX * 1001F175 75 07 JNZ SHORT RGSS301.1001F17E * 1001F177 33C0 XOR EAX,EAX * 1001F179 E9 D1010000 JMP RGSS301.1001F34F * 1001F17E 8B4D 8C MOV ECX,DWORD PTR SS:[EBP-0x74] * 1001F181 E8 5AA3FFFF CALL RGSS301.100194E0 * 1001F186 8BC8 MOV ECX,EAX * 1001F188 E8 D3A6FFFF CALL RGSS301.10019860 * 1001F18D 8945 FC MOV DWORD PTR SS:[EBP-0x4],EAX * 1001F190 837D FC 00 CMP DWORD PTR SS:[EBP-0x4],0x0 * 1001F194 75 07 JNZ SHORT RGSS301.1001F19D * 1001F196 33C0 XOR EAX,EAX * 1001F198 E9 B2010000 JMP RGSS301.1001F34F * 1001F19D 8D4D BC LEA ECX,DWORD PTR SS:[EBP-0x44] * 1001F1A0 51 PUSH ECX * 1001F1A1 8B55 FC MOV EDX,DWORD PTR SS:[EBP-0x4] * 1001F1A4 52 PUSH EDX * 1001F1A5 FF15 3C201A10 CALL DWORD PTR DS:[0x101A203C] ; gdi32.GetTextMetricsW * 1001F1AB 8B45 0C MOV EAX,DWORD PTR SS:[EBP+0xC] * 1001F1AE C700 00000000 MOV DWORD PTR DS:[EAX],0x0 * 1001F1B4 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+0xC] * 1001F1B7 C741 04 00000000 MOV DWORD PTR DS:[ECX+0x4],0x0 * 1001F1BE 33D2 XOR EDX,EDX * 1001F1C0 66:8955 AC MOV WORD PTR SS:[EBP-0x54],DX * 1001F1C4 B8 01000000 MOV EAX,0x1 * 1001F1C9 66:8945 AE MOV WORD PTR SS:[EBP-0x52],AX * 1001F1CD 33C9 XOR ECX,ECX * 1001F1CF 66:894D B0 MOV WORD PTR SS:[EBP-0x50],CX * 1001F1D3 33D2 XOR EDX,EDX * 1001F1D5 66:8955 B2 MOV WORD PTR SS:[EBP-0x4E],DX * 1001F1D9 33C0 XOR EAX,EAX * 1001F1DB 66:8945 B4 MOV WORD PTR SS:[EBP-0x4C],AX * 1001F1DF 33C9 XOR ECX,ECX * 1001F1E1 66:894D B6 MOV WORD PTR SS:[EBP-0x4A],CX * 1001F1E5 33D2 XOR EDX,EDX * 1001F1E7 66:8955 B8 MOV WORD PTR SS:[EBP-0x48],DX * 1001F1EB B8 01000000 MOV EAX,0x1 * 1001F1F0 66:8945 BA MOV WORD PTR SS:[EBP-0x46],AX * 1001F1F4 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+0x8] * 1001F1F7 894D 88 MOV DWORD PTR SS:[EBP-0x78],ECX * 1001F1FA 8B55 88 MOV EDX,DWORD PTR SS:[EBP-0x78] * 1001F1FD 83C2 02 ADD EDX,0x2 * 1001F200 8955 84 MOV DWORD PTR SS:[EBP-0x7C],EDX * 1001F203 8B45 88 MOV EAX,DWORD PTR SS:[EBP-0x78] * 1001F206 66:8B08 MOV CX,WORD PTR DS:[EAX] * 1001F209 66:894D 82 MOV WORD PTR SS:[EBP-0x7E],CX * 1001F20D 8345 88 02 ADD DWORD PTR SS:[EBP-0x78],0x2 * 1001F211 66:837D 82 00 CMP WORD PTR SS:[EBP-0x7E],0x0 * 1001F216 ^75 EB JNZ SHORT RGSS301.1001F203 * 1001F218 8B55 88 MOV EDX,DWORD PTR SS:[EBP-0x78] * 1001F21B 2B55 84 SUB EDX,DWORD PTR SS:[EBP-0x7C] * 1001F21E D1FA SAR EDX,1 * 1001F220 8995 7CFFFFFF MOV DWORD PTR SS:[EBP-0x84],EDX * 1001F226 8B85 7CFFFFFF MOV EAX,DWORD PTR SS:[EBP-0x84] * 1001F22C 8945 F8 MOV DWORD PTR SS:[EBP-0x8],EAX * 1001F22F C745 A8 00000000 MOV DWORD PTR SS:[EBP-0x58],0x0 * 1001F236 EB 09 JMP SHORT RGSS301.1001F241 * 1001F238 8B4D A8 MOV ECX,DWORD PTR SS:[EBP-0x58] * 1001F23B 83C1 01 ADD ECX,0x1 * 1001F23E 894D A8 MOV DWORD PTR SS:[EBP-0x58],ECX * 1001F241 8B55 A8 MOV EDX,DWORD PTR SS:[EBP-0x58] * 1001F244 3B55 F8 CMP EDX,DWORD PTR SS:[EBP-0x8] * 1001F247 0F8D C2000000 JGE RGSS301.1001F30F * 1001F24D 8D45 AC LEA EAX,DWORD PTR SS:[EBP-0x54] * 1001F250 50 PUSH EAX * 1001F251 6A 00 PUSH 0x0 * 1001F253 6A 00 PUSH 0x0 * 1001F255 8D4D 90 LEA ECX,DWORD PTR SS:[EBP-0x70] * 1001F258 51 PUSH ECX * 1001F259 6A 06 PUSH 0x6 * 1001F25B 8B55 A8 MOV EDX,DWORD PTR SS:[EBP-0x58] * 1001F25E 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8] * 1001F261 0FB70C50 MOVZX ECX,WORD PTR DS:[EAX+EDX*2] * 1001F265 51 PUSH ECX * 1001F266 8B55 FC MOV EDX,DWORD PTR SS:[EBP-0x4] * 1001F269 52 PUSH EDX * 1001F26A FF15 30201A10 CALL DWORD PTR DS:[0x101A2030] ; gdi32.GetGlyphOutlineW * 1001F270 8945 A4 MOV DWORD PTR SS:[EBP-0x5C],EAX * 1001F273 837D 18 00 CMP DWORD PTR SS:[EBP+0x18],0x0 * 1001F277 74 12 JE SHORT RGSS301.1001F28B * 1001F279 8B45 18 MOV EAX,DWORD PTR SS:[EBP+0x18] * 1001F27C 8B4D A4 MOV ECX,DWORD PTR SS:[EBP-0x5C] * 1001F27F 3B08 CMP ECX,DWORD PTR DS:[EAX] * 1001F281 76 08 JBE SHORT RGSS301.1001F28B * 1001F283 8B55 18 MOV EDX,DWORD PTR SS:[EBP+0x18] * 1001F286 8B45 A4 MOV EAX,DWORD PTR SS:[EBP-0x5C] * 1001F289 8902 MOV DWORD PTR DS:[EDX],EAX * 1001F28B 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+0xC] * 1001F28E 8B11 MOV EDX,DWORD PTR DS:[ECX] * 1001F290 0355 98 ADD EDX,DWORD PTR SS:[EBP-0x68] * 1001F293 79 0A JNS SHORT RGSS301.1001F29F * * Caller of the other two GetGlyphOutlineW, where text is in arg5. * * 00826D34 100074F7 RETURN to RGSS301.100074F7 from RGSS301.1001F360 * 00826D38 00000088 * 00826D3C 000000E8 * 00826D40 00000058 * 00826D44 00000018 * 00826D48 00826D9C ; jichi: text here * 00826D4C FFFFFFFF * 00826D50 80000000 * 00826D54 00000001 * 00826D58 00000000 * 00826D5C 00000140 * 00826D60 000000C0 * 00826D64 008283A8 * 00826D68 1018DF60 RGSS301.1018DF60 * * 1001F35C CC INT3 * 1001F35D CC INT3 * 1001F35E CC INT3 * 1001F35F CC INT3 * 1001F360 55 PUSH EBP * 1001F361 8BEC MOV EBP,ESP * 1001F363 81EC 4C010000 SUB ESP,0x14C * 1001F369 898D C4FEFFFF MOV DWORD PTR SS:[EBP-0x13C],ECX * 1001F36F 8B8D C4FEFFFF MOV ECX,DWORD PTR SS:[EBP-0x13C] * 1001F375 E8 66A1FFFF CALL RGSS301.100194E0 * 1001F37A 85C0 TEST EAX,EAX * 1001F37C 75 07 JNZ SHORT RGSS301.1001F385 * 1001F37E 33C0 XOR EAX,EAX * 1001F380 E9 12060000 JMP RGSS301.1001F997 * 1001F385 8B8D C4FEFFFF MOV ECX,DWORD PTR SS:[EBP-0x13C] * 1001F38B E8 50A1FFFF CALL RGSS301.100194E0 * 1001F390 8BC8 MOV ECX,EAX * 1001F392 E8 C9A4FFFF CALL RGSS301.10019860 * 1001F397 8945 F8 MOV DWORD PTR SS:[EBP-0x8],EAX * 1001F39A 837D F8 00 CMP DWORD PTR SS:[EBP-0x8],0x0 * 1001F39E 75 07 JNZ SHORT RGSS301.1001F3A7 * 1001F3A0 33C0 XOR EAX,EAX * 1001F3A2 E9 F0050000 JMP RGSS301.1001F997 * 1001F3A7 8D45 A0 LEA EAX,DWORD PTR SS:[EBP-0x60] * 1001F3AA 50 PUSH EAX * 1001F3AB 8B4D F8 MOV ECX,DWORD PTR SS:[EBP-0x8] * 1001F3AE 51 PUSH ECX * 1001F3AF FF15 3C201A10 CALL DWORD PTR DS:[0x101A203C] ; gdi32.GetTextMetricsW * 1001F3B5 837D 2C 00 CMP DWORD PTR SS:[EBP+0x2C],0x0 * 1001F3B9 77 4C JA SHORT RGSS301.1001F407 * 1001F3BB 8D55 2C LEA EDX,DWORD PTR SS:[EBP+0x2C] * 1001F3BE 52 PUSH EDX * 1001F3BF 8B45 24 MOV EAX,DWORD PTR SS:[EBP+0x24] * 1001F3C2 50 PUSH EAX * 1001F3C3 6A 01 PUSH 0x1 * 1001F3C5 8D8D 3CFFFFFF LEA ECX,DWORD PTR SS:[EBP-0xC4] * 1001F3CB 51 PUSH ECX * 1001F3CC 8B55 18 MOV EDX,DWORD PTR SS:[EBP+0x18] * 1001F3CF 52 PUSH EDX * 1001F3D0 8B8D C4FEFFFF MOV ECX,DWORD PTR SS:[EBP-0x13C] * 1001F3D6 E8 75FDFFFF CALL RGSS301.1001F150 * 1001F3DB 83BD 3CFFFFFF 00 CMP DWORD PTR SS:[EBP-0xC4],0x0 * 1001F3E2 74 09 JE SHORT RGSS301.1001F3ED * 1001F3E4 83BD 40FFFFFF 00 CMP DWORD PTR SS:[EBP-0xC0],0x0 * 1001F3EB 75 0A JNZ SHORT RGSS301.1001F3F7 * 1001F3ED B8 01000000 MOV EAX,0x1 * 1001F3F2 E9 A0050000 JMP RGSS301.1001F997 * 1001F3F7 837D 2C 00 CMP DWORD PTR SS:[EBP+0x2C],0x0 * 1001F3FB 77 0A JA SHORT RGSS301.1001F407 * 1001F3FD B8 01000000 MOV EAX,0x1 * 1001F402 E9 90050000 JMP RGSS301.1001F997 * 1001F407 8B45 0C MOV EAX,DWORD PTR SS:[EBP+0xC] * 1001F40A 8985 58FFFFFF MOV DWORD PTR SS:[EBP-0xA8],EAX * 1001F410 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+0x8] * 1001F413 898D 54FFFFFF MOV DWORD PTR SS:[EBP-0xAC],ECX * 1001F419 8B95 54FFFFFF MOV EDX,DWORD PTR SS:[EBP-0xAC] * 1001F41F 0355 10 ADD EDX,DWORD PTR SS:[EBP+0x10] * 1001F422 8995 5CFFFFFF MOV DWORD PTR SS:[EBP-0xA4],EDX * 1001F428 8B85 58FFFFFF MOV EAX,DWORD PTR SS:[EBP-0xA8] * 1001F42E 0345 14 ADD EAX,DWORD PTR SS:[EBP+0x14] * 1001F431 8985 60FFFFFF MOV DWORD PTR SS:[EBP-0xA0],EAX * 1001F437 C745 E0 00000000 MOV DWORD PTR SS:[EBP-0x20],0x0 * 1001F43E C745 DC 00000000 MOV DWORD PTR SS:[EBP-0x24],0x0 * 1001F445 8B4D 10 MOV ECX,DWORD PTR SS:[EBP+0x10] * 1001F448 894D E4 MOV DWORD PTR SS:[EBP-0x1C],ECX * 1001F44B 8B55 14 MOV EDX,DWORD PTR SS:[EBP+0x14] * 1001F44E 8955 E8 MOV DWORD PTR SS:[EBP-0x18],EDX * 1001F451 837D 24 00 CMP DWORD PTR SS:[EBP+0x24],0x0 * 1001F455 74 1F JE SHORT RGSS301.1001F476 * 1001F457 6A FF PUSH -0x1 * 1001F459 6A FF PUSH -0x1 * 1001F45B 8D85 54FFFFFF LEA EAX,DWORD PTR SS:[EBP-0xAC] * 1001F461 50 PUSH EAX * 1001F462 FF15 E8231A10 CALL DWORD PTR DS:[0x101A23E8] ; user32.InflateRect * 1001F468 6A FF PUSH -0x1 * 1001F46A 6A FF PUSH -0x1 * 1001F46C 8D4D DC LEA ECX,DWORD PTR SS:[EBP-0x24] * 1001F46F 51 PUSH ECX * 1001F470 FF15 E8231A10 CALL DWORD PTR DS:[0x101A23E8] ; user32.InflateRect * 1001F476 68 E0010000 PUSH 0x1E0 * 1001F47B 68 80020000 PUSH 0x280 * 1001F480 E8 DBFF0E00 CALL RGSS301.1010F460 * 1001F485 8BC8 MOV ECX,EAX * 1001F487 E8 54010F00 CALL RGSS301.1010F5E0 * 1001F48C 8945 F0 MOV DWORD PTR SS:[EBP-0x10],EAX * 1001F48F 837D F0 00 CMP DWORD PTR SS:[EBP-0x10],0x0 * 1001F493 75 07 JNZ SHORT RGSS301.1001F49C * 1001F495 33C0 XOR EAX,EAX * 1001F497 E9 FB040000 JMP RGSS301.1001F997 * 1001F49C 6A 00 PUSH 0x0 * 1001F49E 8D55 DC LEA EDX,DWORD PTR SS:[EBP-0x24] * 1001F4A1 52 PUSH EDX * 1001F4A2 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-0x10] * 1001F4A5 E8 A6CF0E00 CALL RGSS301.1010C450 * 1001F4AA 8B45 18 MOV EAX,DWORD PTR SS:[EBP+0x18] * 1001F4AD 8985 C0FEFFFF MOV DWORD PTR SS:[EBP-0x140],EAX * 1001F4B3 8B8D C0FEFFFF MOV ECX,DWORD PTR SS:[EBP-0x140] * 1001F4B9 83C1 02 ADD ECX,0x2 * 1001F4BC 898D BCFEFFFF MOV DWORD PTR SS:[EBP-0x144],ECX * 1001F4C2 8B95 C0FEFFFF MOV EDX,DWORD PTR SS:[EBP-0x140] * 1001F4C8 66:8B02 MOV AX,WORD PTR DS:[EDX] * 1001F4CB 66:8985 BAFEFFFF MOV WORD PTR SS:[EBP-0x146],AX * 1001F4D2 8385 C0FEFFFF 02 ADD DWORD PTR SS:[EBP-0x140],0x2 * 1001F4D9 66:83BD BAFEFFFF>CMP WORD PTR SS:[EBP-0x146],0x0 * 1001F4E1 ^75 DF JNZ SHORT RGSS301.1001F4C2 * 1001F4E3 8B8D C0FEFFFF MOV ECX,DWORD PTR SS:[EBP-0x140] * 1001F4E9 2B8D BCFEFFFF SUB ECX,DWORD PTR SS:[EBP-0x144] * 1001F4EF D1F9 SAR ECX,1 * 1001F4F1 898D B4FEFFFF MOV DWORD PTR SS:[EBP-0x14C],ECX * 1001F4F7 8B95 B4FEFFFF MOV EDX,DWORD PTR SS:[EBP-0x14C] * 1001F4FD 8955 EC MOV DWORD PTR SS:[EBP-0x14],EDX * 1001F500 C745 F4 00000000 MOV DWORD PTR SS:[EBP-0xC],0x0 * 1001F507 33C0 XOR EAX,EAX * 1001F509 66:8985 44FFFFFF MOV WORD PTR SS:[EBP-0xBC],AX * 1001F510 B9 01000000 MOV ECX,0x1 * 1001F515 66:898D 46FFFFFF MOV WORD PTR SS:[EBP-0xBA],CX * 1001F51C 33D2 XOR EDX,EDX * 1001F51E 66:8995 48FFFFFF MOV WORD PTR SS:[EBP-0xB8],DX * 1001F525 33C0 XOR EAX,EAX * 1001F527 66:8985 4AFFFFFF MOV WORD PTR SS:[EBP-0xB6],AX * 1001F52E 33C9 XOR ECX,ECX * 1001F530 66:898D 4CFFFFFF MOV WORD PTR SS:[EBP-0xB4],CX * 1001F537 33D2 XOR EDX,EDX * 1001F539 66:8995 4EFFFFFF MOV WORD PTR SS:[EBP-0xB2],DX * 1001F540 33C0 XOR EAX,EAX * 1001F542 66:8985 50FFFFFF MOV WORD PTR SS:[EBP-0xB0],AX * 1001F549 B9 01000000 MOV ECX,0x1 * 1001F54E 66:898D 52FFFFFF MOV WORD PTR SS:[EBP-0xAE],CX * 1001F555 8B55 2C MOV EDX,DWORD PTR SS:[EBP+0x2C] * 1001F558 52 PUSH EDX * 1001F559 E8 0EF31500 CALL RGSS301.1017E86C * 1001F55E 83C4 04 ADD ESP,0x4 * 1001F561 8985 D0FEFFFF MOV DWORD PTR SS:[EBP-0x130],EAX * 1001F567 8B85 D0FEFFFF MOV EAX,DWORD PTR SS:[EBP-0x130] * 1001F56D 8985 64FFFFFF MOV DWORD PTR SS:[EBP-0x9C],EAX * 1001F573 C785 38FFFFFF 00>MOV DWORD PTR SS:[EBP-0xC8],0x0 * 1001F57D EB 0F JMP SHORT RGSS301.1001F58E * 1001F57F 8B8D 38FFFFFF MOV ECX,DWORD PTR SS:[EBP-0xC8] * 1001F585 83C1 01 ADD ECX,0x1 * 1001F588 898D 38FFFFFF MOV DWORD PTR SS:[EBP-0xC8],ECX * 1001F58E 8B95 38FFFFFF MOV EDX,DWORD PTR SS:[EBP-0xC8] * 1001F594 3B55 EC CMP EDX,DWORD PTR SS:[EBP-0x14] * 1001F597 0F8D E6010000 JGE RGSS301.1001F783 * 1001F59D 8B45 2C MOV EAX,DWORD PTR SS:[EBP+0x2C] * 1001F5A0 50 PUSH EAX * 1001F5A1 6A 00 PUSH 0x0 * 1001F5A3 8B8D 64FFFFFF MOV ECX,DWORD PTR SS:[EBP-0x9C] * 1001F5A9 51 PUSH ECX * 1001F5AA E8 E1FC1500 CALL RGSS301.1017F290 * 1001F5AF 83C4 0C ADD ESP,0xC * 1001F5B2 8D95 44FFFFFF LEA EDX,DWORD PTR SS:[EBP-0xBC] * 1001F5B8 52 PUSH EDX * 1001F5B9 6A 00 PUSH 0x0 * 1001F5BB 6A 00 PUSH 0x0 * 1001F5BD 8D85 08FFFFFF LEA EAX,DWORD PTR SS:[EBP-0xF8] * 1001F5C3 50 PUSH EAX * 1001F5C4 6A 00 PUSH 0x0 * 1001F5C6 8B8D 38FFFFFF MOV ECX,DWORD PTR SS:[EBP-0xC8] * 1001F5CC 8B55 18 MOV EDX,DWORD PTR SS:[EBP+0x18] * 1001F5CF 0FB7044A MOVZX EAX,WORD PTR DS:[EDX+ECX*2] * 1001F5D3 50 PUSH EAX * 1001F5D4 8B4D F8 MOV ECX,DWORD PTR SS:[EBP-0x8] * 1001F5D7 51 PUSH ECX * 1001F5D8 FF15 30201A10 CALL DWORD PTR DS:[0x101A2030] ; gdi32.GetGlyphOutlineW * 1001F5DE 8D95 44FFFFFF LEA EDX,DWORD PTR SS:[EBP-0xBC] * 1001F5E4 52 PUSH EDX * 1001F5E5 8B85 64FFFFFF MOV EAX,DWORD PTR SS:[EBP-0x9C] * 1001F5EB 50 PUSH EAX * 1001F5EC 8B4D 2C MOV ECX,DWORD PTR SS:[EBP+0x2C] * 1001F5EF 51 PUSH ECX * 1001F5F0 8D95 08FFFFFF LEA EDX,DWORD PTR SS:[EBP-0xF8] * 1001F5F6 52 PUSH EDX * 1001F5F7 6A 06 PUSH 0x6 * 1001F5F9 8B85 38FFFFFF MOV EAX,DWORD PTR SS:[EBP-0xC8] * 1001F5FF 8B4D 18 MOV ECX,DWORD PTR SS:[EBP+0x18] * 1001F602 0FB71441 MOVZX EDX,WORD PTR DS:[ECX+EAX*2] * 1001F606 52 PUSH EDX * 1001F607 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-0x8] * 1001F60A 50 PUSH EAX * 1001F60B FF15 30201A10 CALL DWORD PTR DS:[0x101A2030] ; gdi32.GetGlyphOutlineW * 1001F611 8B4D F4 MOV ECX,DWORD PTR SS:[EBP-0xC] * 1001F614 038D 10FFFFFF ADD ECX,DWORD PTR SS:[EBP-0xF0] * 1001F61A 79 0B JNS SHORT RGSS301.1001F627 * 1001F61C 8B95 10FFFFFF MOV EDX,DWORD PTR SS:[EBP-0xF0] * 1001F622 F7DA NEG EDX * 1001F624 8955 F4 MOV DWORD PTR SS:[EBP-0xC],EDX * 1001F627 8B85 08FFFFFF MOV EAX,DWORD PTR SS:[EBP-0xF8] * 1001F62D 8985 28FFFFFF MOV DWORD PTR SS:[EBP-0xD8],EAX * * Additionally, text to paint is converted here from UTF-8 to UTF-16: * 1000C62D CC INT3 * 1000C62E CC INT3 * 1000C62F CC INT3 * 1000C630 55 PUSH EBP * 1000C631 8BEC MOV EBP,ESP * 1000C633 8B45 10 MOV EAX,DWORD PTR SS:[EBP+0x10] * 1000C636 D1E0 SHL EAX,1 * 1000C638 50 PUSH EAX * 1000C639 6A 00 PUSH 0x0 * 1000C63B 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+0xC] * 1000C63E 51 PUSH ECX * 1000C63F E8 4C2C1700 CALL RGSS301.1017F290 * 1000C644 83C4 0C ADD ESP,0xC * 1000C647 8B55 10 MOV EDX,DWORD PTR SS:[EBP+0x10] * 1000C64A 52 PUSH EDX * 1000C64B 8B45 0C MOV EAX,DWORD PTR SS:[EBP+0xC] * 1000C64E 50 PUSH EAX * 1000C64F 6A FF PUSH -0x1 * 1000C651 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+0x8] * 1000C654 51 PUSH ECX * 1000C655 6A 00 PUSH 0x0 * 1000C657 68 E9FD0000 PUSH 0xFDE9 * 1000C65C FF15 38221A10 CALL DWORD PTR DS:[0x101A2238] ; kernel32.MultiByteToWideChar * 1000C662 5D POP EBP * 1000C663 C3 RETN * 1000C664 CC INT3 * 1000C665 CC INT3 * 1000C666 CC INT3 * 1000C667 CC INT3 * 1000C668 CC INT3 * 1000C669 CC INT3 * 1000C66A CC INT3 * 1000C66B CC INT3 * 1000C66C CC INT3 * 1000C66D CC INT3 * 1000C66E CC INT3 * 1000C66F CC INT3 * 1000C670 55 PUSH EBP * 1000C671 8BEC MOV EBP,ESP * 1000C673 68 00100000 PUSH 0x1000 * 1000C678 68 68302610 PUSH RGSS301.10263068 * 1000C67D 8B45 08 MOV EAX,DWORD PTR SS:[EBP+0x8] * 1000C680 50 PUSH EAX * 1000C681 E8 AAFFFFFF CALL RGSS301.1000C630 * 1000C686 83C4 0C ADD ESP,0xC * 1000C689 33C9 XOR ECX,ECX * 1000C68B 66:890D 66502610 MOV WORD PTR DS:[0x10265066],CX * 1000C692 B8 68302610 MOV EAX,RGSS301.10263068 * 1000C697 5D POP EBP * 1000C698 C3 RETN * 1000C699 CC INT3 * 1000C69A CC INT3 * 1000C69B CC INT3 * 1000C69C CC INT3 * 1000C69D CC INT3 */ ULONG functionAddress; // the beginning of the function being hooked bool attach(ULONG startAddress, ULONG stopAddress) // attach other text { ULONG addr = MemDbg::findCallerAddressAfterInt3((ULONG)::GetGlyphOutlineW, startAddress, stopAddress); if (addr == 0) return 0; HookParam hp; hp.address = addr; hp.hook_before = Private::hookBefore; hp.hook_after = Private::hookafter2; hp.type = USING_STRING | CODEC_UTF16 | EMBED_ABLE; hp.hook_font = F_GetGlyphOutlineW; return NewHook(hp, "EmbedRGSS3Other"); } } } // namespace OtherHook } // namespace RGSS3Hook #if 0 /** * Sample game: Mogeko Castle with RGSS 3.01 * 0x10036758: LOAD * 0x1004155c: DATA * * Text accessed character by character * 0x10036463: LOAD character by character * * 0x100378ed: $100 * 0x100378ed: キャンセル * * 0x10038a44: 駅のホーム */ namespace DebugHook { bool beforeStrcpy(winhook::hook_stack *s) { auto arg = (LPCSTR)s->stack[1]; // arg1 auto sig = s->stack[0]; // retaddr //enum { role = Engine::OtherRole }; //if (!::strstr(arg, "\xe3\x82\xaa\xe3\x83\xac\xe3\x83\xb3\xe7\x97\x94")) // return true; QString text = QString::fromUtf16((LPCWSTR)arg); //QString text = QString::fromUtf8((LPCSTR)arg, s->stack[3]); //if (!text.isEmpty() && text[0].unicode() >= 128 && text.size() == 5) //if (!text.isEmpty() && sig == 0x100378ed) EngineController::instance()->dispatchTextW(text, role, sig); return true; } bool attach() { //ULONG addr = 0x10180840; ULONG addr = 0x1001f150; winhook::hook_before(addr, beforeStrcpy); return true; } } // namespace DebugHook #endif // 0 } // unnamed namespace bool RPGMakerRGSS3::attach_function() { ULONG startAddress, stopAddress; if (!RGSS3::getMemoryRange(&startAddress, &stopAddress)) return false; if (!RGSS3::ScenarioHook::attach(startAddress, stopAddress)) return false; RGSS3::ChoiceHook::Private::attach(startAddress, stopAddress); RGSS3::OtherHook::Private::attach(startAddress, stopAddress); return true; } bool RPGMakerRGSS300::attach_function() { trigger_fun = [](LPVOID addr1, hook_stack *stack) { if (addr1 != GetGlyphOutlineW) return false; auto addr = stack->retaddr; addr = MemDbg::findEnclosingAlignedFunction(addr); if (addr == 0) return false; HookParam hp; hp.address = addr; hp.type = USING_STRING | CODEC_UTF16; hp.offset = get_stack(1); NewHook(hp, "RGSS30x.dll"); return true; }; return GetModuleHandle(L"RGSS300.dll") || GetModuleHandle(L"RGSS301.dll"); }