#include"Cotopha.h" #include"embed_util.h" #define s2_mov_ecx_edi 0xcf8b namespace { // unnamed namespace ScenarioHook { namespace Private { /** * Sample game: お兄ちゃん、右手の使用を禁止します! (old type) * * - Name * * EAX 00000000 * ECX 04A4C058 * EDX 00713FD8 .00713FD8 * EBX 17F90130 * ESP 0012EBBC * EBP 0020C5A8 * ESI 04A4B678 * EDI 04A4C058 * EIP 005C2E20 .005C2E20 * * 0012EBBC 0055D210 RETURN to .0055D210 * 0012EBC0 17F90130 * 0012EBC4 04A4B678 * 0012EBC8 00000000 * 0012EBCC 0020C5A8 * 0012EBD0 00000000 ; jichi: used to identify name * 0012EBD4 00000000 * 0012EBD8 04A4B678 * 0012EBDC 00000000 * 0012EBE0 0020C5A8 * 0012EBE4 00000000 * 0012EBE8 0055C58F RETURN to .0055C58F from .0046CD30 * 0012EBEC 0012EC54 * 0012EBF0 0055C5A3 RETURN to .0055C5A3 from .0055D180 * 0012EBF4 04A4C058 * 0012EBF8 04A4B678 * * - Scenario * * EAX 00000000 * ECX 04A4CC30 * EDX 00713FD8 .00713FD8 * EBX 17F90170 * ESP 0012EBBC * EBP 00000015 * ESI 04A4C250 * EDI 04A4CC30 * EIP 005C2E20 .005C2E20 * * 0012EBBC 0055D210 RETURN to .0055D210 * 0012EBC0 17F90170 * 0012EBC4 04A4C250 * 0012EBC8 0000001E ; jichi: old game arg3 is 1e * 0012EBCC 00000015 * 0012EBD0 00000002 * 0012EBD4 00000002 * 0012EBD8 04A4C250 * 0012EBDC 0000001E * 0012EBE0 00000015 * 0012EBE4 00000000 * 0012EBE8 0055C58F RETURN to .0055C58F from .0046CD30 * 0012EBEC 0012EC54 * 0012EBF0 0055C5A3 RETURN to .0055C5A3 from .0055D180 * * Caller of the scenario/name thread: * 0055D207 8BCF MOV ECX,EDI * 0055D209 897C24 34 MOV DWORD PTR SS:[ESP+0x34],EDI * 0055D20D FF52 14 CALL DWORD PTR DS:[EDX+0x14] ; jichi: called here * 0055D210 8BCF MOV ECX,EDI ; jichi: retaddr is here * 0055D212 894424 18 MOV DWORD PTR SS:[ESP+0x18],EAX * 0055D216 E8 456D0600 CALL .005C3F60 * 0055D21B 33C9 XOR ECX,ECX * 0055D21D 894424 14 MOV DWORD PTR SS:[ESP+0x14],EAX * 0055D221 3BC1 CMP EAX,ECX * 0055D223 76 06 JBE SHORT .0055D22B * * Sample game: キスと魔王と紅茶 (very old type) * * - Name: * * EAX 0A4106C0 ASCII "ゥa" * ECX 0012F594 * EDX 0058032C ASCII "pgM" * EBX 00000000 * ESP 0012F4F4 * EBP 00000003 * ESI 0012F618 * EDI 0012F594 * EIP 004D52B0 .004D52B0 * * 0012F4F4 004DBFF2 RETURN to .004DBFF2 * 0012F4F8 0A4106C0 ASCII "ゥa" * 0012F4FC 0012F698 * 0012F500 0012F618 * 0012F504 0296EA58 * 0012F508 00000000 ; jichi: used to identify name * 0012F50C 0A40EC00 * 0012F510 00000000 * 0012F514 000000F9 * 0012F518 00005DC8 * 0012F51C 00580304 ASCII "PgM" * 0012F520 D90A0DDD * 0012F524 00000018 * 0012F528 00000000 * * - Scenario: * * EAX 00000000 * ECX 01B69134 * EDX 0058032C ASCII "pgM" * EBX 09E82E88 * ESP 0012F548 * EBP 00000016 * ESI 01B68A70 * EDI 01B69134 * EIP 004D52B0 .004D52B0 * * 0012F548 004B5210 RETURN to .004B5210 * 0012F54C 09E82E88 * 0012F550 01B68A70 * 0012F554 00000018 * 0012F558 00000016 * 0012F55C 00000009 * 0012F560 01B69134 * 0012F564 01B68A70 * 0012F568 00000018 * 0012F56C 00000016 * 0012F570 00000000 * 0012F574 004B459F RETURN to .004B459F from .0040DE50 * 0012F578 0012F5E0 * 0012F57C 004B45B3 RETURN to .004B45B3 from .004B5180 * 0012F580 09E82E88 * 0012F584 00000000 * 0012F588 0012FC78 * 0012F58C 00000000 * 0012F590 01B68A70 * 0012F594 005655D0 .005655D0 * 0012F598 0057BB80 .0057BB80 * 0012F59C 0A419628 * * Caller of the name/scenario thread * * 004B517D 90 NOP * 004B517E 90 NOP * 004B517F 90 NOP * 004B5180 83EC 1C SUB ESP,0x1C * 004B5183 53 PUSH EBX * 004B5184 55 PUSH EBP * 004B5185 8B5C24 28 MOV EBX,DWORD PTR SS:[ESP+0x28] * 004B5189 56 PUSH ESI * 004B518A 8BF1 MOV ESI,ECX * 004B518C 57 PUSH EDI * 004B518D 8B86 A0050000 MOV EAX,DWORD PTR DS:[ESI+0x5A0] * 004B5193 85C0 TEST EAX,EAX * 004B5195 74 63 JE SHORT .004B51FA * 004B5197 53 PUSH EBX * 004B5198 8D8E C4060000 LEA ECX,DWORD PTR DS:[ESI+0x6C4] * 004B519E E8 3DFD0100 CALL .004D4EE0 * 004B51A3 8BF8 MOV EDI,EAX * 004B51A5 8D86 D4060000 LEA EAX,DWORD PTR DS:[ESI+0x6D4] * 004B51AB 8B8E EC060000 MOV ECX,DWORD PTR DS:[ESI+0x6EC] * 004B51B1 8BAE F0060000 MOV EBP,DWORD PTR DS:[ESI+0x6F0] * 004B51B7 8B10 MOV EDX,DWORD PTR DS:[EAX] * 004B51B9 895424 1C MOV DWORD PTR SS:[ESP+0x1C],EDX * 004B51BD 8B50 04 MOV EDX,DWORD PTR DS:[EAX+0x4] * 004B51C0 895424 20 MOV DWORD PTR SS:[ESP+0x20],EDX * 004B51C4 8B50 08 MOV EDX,DWORD PTR DS:[EAX+0x8] * 004B51C7 8B40 0C MOV EAX,DWORD PTR DS:[EAX+0xC] * 004B51CA 894424 28 MOV DWORD PTR SS:[ESP+0x28],EAX * 004B51CE 8BC2 MOV EAX,EDX * 004B51D0 2BC1 SUB EAX,ECX * 004B51D2 3BF8 CMP EDI,EAX * 004B51D4 7F 24 JG SHORT .004B51FA * 004B51D6 83BE A0050000 03 CMP DWORD PTR DS:[ESI+0x5A0],0x3 * 004B51DD 75 0B JNZ SHORT .004B51EA * 004B51DF 2BC7 SUB EAX,EDI * 004B51E1 99 CDQ * 004B51E2 2BC2 SUB EAX,EDX * 004B51E4 D1F8 SAR EAX,1 * 004B51E6 03C8 ADD ECX,EAX * 004B51E8 EB 04 JMP SHORT .004B51EE * 004B51EA 2BD7 SUB EDX,EDI * 004B51EC 8BCA MOV ECX,EDX * 004B51EE 898E EC060000 MOV DWORD PTR DS:[ESI+0x6EC],ECX * 004B51F4 89AE F0060000 MOV DWORD PTR DS:[ESI+0x6F0],EBP * 004B51FA 8B96 C4060000 MOV EDX,DWORD PTR DS:[ESI+0x6C4] * 004B5200 8DBE C4060000 LEA EDI,DWORD PTR DS:[ESI+0x6C4] * 004B5206 53 PUSH EBX * 004B5207 8BCF MOV ECX,EDI * 004B5209 897C24 14 MOV DWORD PTR SS:[ESP+0x14],EDI * 004B520D FF52 10 CALL DWORD PTR DS:[EDX+0x10] ; jichi: called here * 004B5210 8BCF MOV ECX,EDI ; jichi: retaddr is here * 004B5212 894424 18 MOV DWORD PTR SS:[ESP+0x18],EAX * 004B5216 E8 85120200 CALL .004D64A0 * 004B521B 33ED XOR EBP,EBP * 004B521D 894424 14 MOV DWORD PTR SS:[ESP+0x14],EAX * 004B5221 3BC5 CMP EAX,EBP * 004B5223 76 06 JBE SHORT .004B522B * 004B5225 89AE A0050000 MOV DWORD PTR DS:[ESI+0x5A0],EBP * 004B522B 85C0 TEST EAX,EAX * 004B522D 896C24 30 MOV DWORD PTR SS:[ESP+0x30],EBP * 004B5231 76 68 JBE SHORT .004B529B * 004B5233 55 PUSH EBP * 004B5234 8BCF MOV ECX,EDI * 004B5236 E8 75120200 CALL .004D64B0 * 004B523B 85C0 TEST EAX,EAX * 004B523D 74 4F JE SHORT .004B528E * 004B523F 50 PUSH EAX * 004B5240 8BCE MOV ECX,ESI * 004B5242 E8 69000000 CALL .004B52B0 * 004B5247 8BD8 MOV EBX,EAX * 004B5249 85DB TEST EBX,EBX * 004B524B 74 41 JE SHORT .004B528E * 004B524D 8B86 C0060000 MOV EAX,DWORD PTR DS:[ESI+0x6C0] * 004B5253 8B8E B0060000 MOV ECX,DWORD PTR DS:[ESI+0x6B0] * 004B5259 8BAE 30070000 MOV EBP,DWORD PTR DS:[ESI+0x730] * 004B525F 8DBE 28070000 LEA EDI,DWORD PTR DS:[ESI+0x728] * 004B5265 03C8 ADD ECX,EAX * 004B5267 6A 00 PUSH 0x0 * 004B5269 8D55 01 LEA EDX,DWORD PTR SS:[EBP+0x1] * 004B526C 898E C0060000 MOV DWORD PTR DS:[ESI+0x6C0],ECX * 004B5272 52 PUSH EDX * 004B5273 8BCF MOV ECX,EDI * 004B5275 8983 C0000000 MOV DWORD PTR DS:[EBX+0xC0],EAX * 004B527B E8 8003F8FF CALL .00435600 * 004B5280 8B47 04 MOV EAX,DWORD PTR DS:[EDI+0x4] * 004B5283 8B7C24 10 MOV EDI,DWORD PTR SS:[ESP+0x10] * 004B5287 891CA8 MOV DWORD PTR DS:[EAX+EBP*4],EBX * 004B528A 8B6C24 30 MOV EBP,DWORD PTR SS:[ESP+0x30] * 004B528E 8B4424 14 MOV EAX,DWORD PTR SS:[ESP+0x14] * 004B5292 45 INC EBP * 004B5293 3BE8 CMP EBP,EAX * 004B5295 896C24 30 MOV DWORD PTR SS:[ESP+0x30],EBP * 004B5299 ^72 98 JB SHORT .004B5233 * 004B529B 8BCF MOV ECX,EDI * 004B529D E8 2E120200 CALL .004D64D0 * 004B52A2 8B4424 18 MOV EAX,DWORD PTR SS:[ESP+0x18] * 004B52A6 5F POP EDI * 004B52A7 5E POP ESI * 004B52A8 5D POP EBP * 004B52A9 5B POP EBX * 004B52AA 83C4 1C ADD ESP,0x1C * 004B52AD C2 0400 RETN 0x4 * 004B52B0 64:A1 00000000 MOV EAX,DWORD PTR FS:[0] * 004B52B6 6A FF PUSH -0x1 * 004B52B8 68 A1F15200 PUSH .0052F1A1 * 004B52BD 50 PUSH EAX * 004B52BE 64:8925 00000000 MOV DWORD PTR FS:[0],ESP * 004B52C5 81EC CC000000 SUB ESP,0xCC * 004B52CB 56 PUSH ESI * 004B52CC 8BF1 MOV ESI,ECX * 004B52CE 8B8C24 E0000000 MOV ECX,DWORD PTR SS:[ESP+0xE0] * 004B52D5 57 PUSH EDI * 004B52D6 85C9 TEST ECX,ECX * 004B52D8 75 07 JNZ SHORT .004B52E1 * 004B52DA 33C0 XOR EAX,EAX * 004B52DC E9 55060000 JMP .004B5936 * 004B52E1 8B79 14 MOV EDI,DWORD PTR DS:[ECX+0x14] * 004B52E4 85FF TEST EDI,EDI * 004B52E6 897C24 18 MOV DWORD PTR SS:[ESP+0x18],EDI * 004B52EA 75 07 JNZ SHORT .004B52F3 * 004B52EC 33C0 XOR EAX,EAX * 004B52EE E9 43060000 JMP .004B5936 * 004B52F3 8A86 AA060000 MOV AL,BYTE PTR DS:[ESI+0x6AA] * 004B52F9 84C0 TEST AL,AL * 004B52FB 74 51 JE SHORT .004B534E * 004B52FD 8B01 MOV EAX,DWORD PTR DS:[ECX] * 004B52FF 8D5424 08 LEA EDX,DWORD PTR SS:[ESP+0x8] * 004B5303 52 PUSH EDX * 004B5304 FF50 34 CALL DWORD PTR DS:[EAX+0x34] * 004B5307 8D86 D4060000 LEA EAX,DWORD PTR DS:[ESI+0x6D4] * 004B530D 8B8E D4060000 MOV ECX,DWORD PTR DS:[ESI+0x6D4] * 004B5313 894C24 48 MOV DWORD PTR SS:[ESP+0x48],ECX * 004B5317 8B50 04 MOV EDX,DWORD PTR DS:[EAX+0x4] * 004B531A 895424 4C MOV DWORD PTR SS:[ESP+0x4C],EDX * 004B531E 8B48 08 MOV ECX,DWORD PTR DS:[EAX+0x8] * 004B5321 894C24 50 MOV DWORD PTR SS:[ESP+0x50],ECX * 004B5325 8A8E 14070000 MOV CL,BYTE PTR DS:[ESI+0x714] * 004B532B 8B40 0C MOV EAX,DWORD PTR DS:[EAX+0xC] * 004B532E 84C9 TEST CL,CL * 004B5330 75 0D JNZ SHORT .004B533F * 004B5332 394424 0C CMP DWORD PTR SS:[ESP+0xC],EAX * 004B5336 7E 16 JLE SHORT .004B534E * 004B5338 33C0 XOR EAX,EAX * 004B533A E9 F7050000 JMP .004B5936 * * Sample game: プライマルハーツ (new type), 0x54bd80 * Name: * 0012EB5C 004DACB0 RETURN to .004DACB0 * 0012EB60 05067E40 * 0012EB64 0000001E ; jichi: new game arg2 is 1e * 0012EB68 0012ECA8 * 0012EB6C 008D3E48 * 0012EB70 004512DB RETURN to .004512DB from .00450FE0 * 0012EB74 0000001E * 0012EB78 00000025 * 0012EB7C 0012ECA8 * 0012EB80 008D3E48 * 0012EB84 0000001E * 0012EB88 004DA1CB RETURN to .004DA1CB from .00451280 * 0012EB8C 004DA1DF RETURN to .004DA1DF from .004DAC20 ; jichi: 004DAC20 is a better place to hook to * 0012EB90 05067E40 * 0012EB94 5D9C7C59 * 0012EB98 00000000 * 0012EB9C 008D3E48 * 0012EBA0 00000000 * 0012EBA4 00000000 * 0012EBA8 1600C8C8 * 0012EBAC 006835B4 .006835B4 * 0012EBB0 1621BBF0 UNICODE "\h:\f;MsgFont:\s:\c;E6ADFA:\v:" * 0012EBB4 00000025 * * 0012EB5C 004DACB0 RETURN to .004DACB0 * 0012EB60 05000420 * 0012EB64 0000001E * 0012EB68 0012ECA8 * 0012EB6C 008D3E48 * 0012EB70 004512DB RETURN to .004512DB from .00450FE0 * 0012EB74 0000001E * 0012EB78 00000022 * 0012EB7C 0012ECA8 * 0012EB80 008D3E48 * 0012EB84 0000001E * 0012EB88 004DA1CB RETURN to .004DA1CB from .00451280 * 0012EB8C 004DA1DF RETURN to .004DA1DF from .004DAC20 * 0012EB90 05000420 * 0012EB94 5D9C7C59 * 0012EB98 00000000 * 0012EB9C 008D3E48 * 0012EBA0 00000000 * 0012EBA4 00000000 * 0012EBA8 05000C90 * 0012EBAC 006835B4 .006835B4 * 0012EBB0 05000F40 UNICODE "\h:\f;MsgFont:\s:\c;DAD4FF:\v:" * 0012EBB4 00000022 * 0012EBB8 00000034 * 0012EBBC 00000022 * 0012EBC0 FFFFFFFF * 0012EBC4 7C00FFFF * 0012EBC8 78000000 * 0012EBCC F8000001 * 0012EBD0 00000000 * 0012EBD4 58001384 * 0012EBD8 28000000 * 0012EBDC 28000000 * 0012EBE0 00000048 * 0012EBE4 00655A28 .00655A28 * 0012EBE8 05000420 * 0012EBEC 00000004 * 0012EBF0 00000007 * 0012EBF4 00210030 * 0012EBF8 00000000 * 0012EBFC 00DAD4FF * 0012EC00 0012EC98 * 0012EC04 00000001 * * EAX 0054BD80 .0054BD80 * ECX 008D4848 * EDX 0069E80C .0069E80C * EBX 05067E40 * ESP 0012EB5C * EBP 0012ECA8 * ESI 008D3E48 * EDI 0000001E * EIP 0054BD80 .0054BD80 * * 004DAC98 89AE 300A0000 MOV DWORD PTR DS:[ESI+0xA30],EBP * 004DAC9E 8B96 000A0000 MOV EDX,DWORD PTR DS:[ESI+0xA00] * 004DACA4 8B42 14 MOV EAX,DWORD PTR DS:[EDX+0x14] * 004DACA7 8D8E 000A0000 LEA ECX,DWORD PTR DS:[ESI+0xA00] * 004DACAD 53 PUSH EBX * 004DACAE FFD0 CALL EAX ; jichi: called here * 004DACB0 8B8E 100A0000 MOV ECX,DWORD PTR DS:[ESI+0xA10] * 004DACB6 894424 14 MOV DWORD PTR SS:[ESP+0x14],EAX * 004DACBA 8B41 08 MOV EAX,DWORD PTR DS:[ECX+0x8] * 004DACBD 33FF XOR EDI,EDI * 004DACBF 3BC7 CMP EAX,EDI * 004DACC1 894424 10 MOV DWORD PTR SS:[ESP+0x10],EAX * * ecx: * 01814848 0C E8 69 00 60 C7 F8 13 00 00 00 00 00 00 00 00 i읠ᏸ.... * 01814858 28 3E 81 01 00 00 00 00 00 00 00 00 80 01 00 00 㸨Ɓ....ƀ. ; jichi: 810 is the width and 26 the height to paint * 01814868 26 00 00 00 FF FF FF 00 00 00 00 00 00 00 00 00 &..ÿ.... * 01814878 00 00 00 00 26 00 00 00 00 00 00 00 00 00 00 00 ..&..... * 01814888 06 00 00 00 03 00 00 00 28 5A 65 00 98 3D 81 01 ..娨e㶘Ɓ * 01814898 2C 00 00 00 43 00 00 00 00 01 01 00 BA C1 1E 77 ,.C.Ā솺眞 * 018148A8 35 FC 1C 77 20 FF 1C 77 90 16 38 0B 64 D5 68 00 ﰵ眜@眜ᚐସ핤h * 018148B8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ * 018148C8 7E 31 00 00 4C 03 00 00 00 00 00 00 00 00 00 00 ㅾ.͌..... * 018148D8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ * 018148E8 00 00 00 00 00 00 F0 3F 00 00 00 00 00 00 F0 3F ...㿰...㿰 * 018148F8 00 00 00 00 00 00 00 00 94 C3 67 00 00 00 00 00 ....쎔g.. * * 01814848 0C E8 69 00 58 EC E4 03 00 00 00 00 00 00 00 00 iϤ.... * 01814858 28 3E 81 01 00 00 00 00 00 00 00 00 80 01 00 00 㸨Ɓ....ƀ. * 01814868 26 00 00 00 FF FF FF 00 00 00 00 00 00 00 00 00 &..ÿ.... * 01814878 00 00 00 00 26 00 00 00 00 00 00 00 00 00 00 00 ..&..... * 01814888 06 00 00 00 03 00 00 00 28 5A 65 00 98 3D 81 01 ..娨e㶘Ɓ * 01814898 2C 00 00 00 43 00 00 00 00 01 01 00 BA C1 1E 77 ,.C.Ā솺眞 * 018148A8 35 FC 1C 77 20 FF 1C 77 90 16 38 0B 64 D5 68 00 ﰵ眜@眜ᚐସ핤h * 018148B8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ * 018148C8 4B 4F 00 00 4C 03 00 00 00 00 00 00 00 00 00 00 佋.͌..... * 018148D8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ * 018148E8 00 00 00 00 00 00 F0 3F 00 00 00 00 00 00 F0 3F ...㿰...㿰 * 018148F8 00 00 00 00 00 00 00 00 94 C3 67 00 00 00 00 00 ....쎔g.. * * Scenario: * EAX 0054BD80 .0054BD80 * ECX 008D3C50 * EDX 0069E80C .0069E80C * EBX 1621C280 * ESP 0012EB5C * EBP 0012ECA8 * ESI 008D3250 * EDI 0000001E * EIP 0054BD80 .0054BD80 * * 0012EB5C 004DACB0 RETURN to .004DACB0 * 0012EB60 1621C280 * 0012EB64 0000001E * 0012EB68 0012ECA8 * 0012EB6C 008D3250 * 0012EB70 004512DB RETURN to .004512DB from .00450FE0 * 0012EB74 0000001E * 0012EB78 00000041 * 0012EB7C 0012ECA8 * 0012EB80 008D3250 * 0012EB84 0000001E * 0012EB88 004DA1CB RETURN to .004DA1CB from .00451280 * 0012EB8C 004DA1DF RETURN to .004DA1DF from .004DAC20 * 0012EB90 1621C280 * * 0012EB5C 004DACB0 RETURN to .004DACB0 * 0012EB60 050003B8 * 0012EB64 0000001E * 0012EB68 0012ECA8 * 0012EB6C 008D3250 * 0012EB70 004512DB RETURN to .004512DB from .00450FE0 * 0012EB74 0000001E * 0012EB78 00000034 * 0012EB7C 0012ECA8 * 0012EB80 008D3250 * 0012EB84 0000001E * 0012EB88 004DA1CB RETURN to .004DA1CB from .00451280 * 0012EB8C 004DA1DF RETURN to .004DA1DF from .004DAC20 * 0012EB90 050003B8 * 0012EB94 5D9C7C59 * 0012EB98 00000000 * 0012EB9C 008D3250 * 0012EBA0 00000000 * 0012EBA4 00000000 * 0012EBA8 05007A68 UNICODE "38" * 0012EBAC 006835B4 .006835B4 * 0012EBB0 0500E910 UNICODE "\h:\f;MsgFont:\s:\c;DAD4FF:\v:" * 0012EBB4 00000034 * 0012EBB8 0000004F * 0012EBBC 00000034 * 0012EBC0 FFFFFFFF * 0012EBC4 7C00FFFF * 0012EBC8 78000000 * 0012EBCC F8000001 * 0012EBD0 00000000 * 0012EBD4 58001384 * 0012EBD8 28000000 * 0012EBDC 28000000 * 0012EBE0 00000040 * 0012EBE4 00655A28 .00655A28 * 0012EBE8 050003B8 * * ecx: * 01813C50 0C E8 69 00 80 E9 F8 13 00 00 00 00 00 00 00 00 iᏸ.... * 01813C60 30 32 81 01 00 00 00 00 00 00 00 00 84 03 00 00 ㈰Ɓ....΄. ; jichi: 384 is the width and 76 the height to paint * 01813C70 76 00 00 00 FF FF FF 00 00 00 00 00 00 00 00 00 v..ÿ.... * 01813C80 00 00 00 00 26 00 00 00 00 00 00 00 00 00 00 00 ..&..... * 01813C90 06 00 00 00 03 00 00 00 28 5A 65 00 A0 31 81 01 ..娨eㆠƁ * 01813CA0 2C 00 00 00 43 00 00 00 00 01 01 00 BA C1 1E 77 ,.C.Ā솺眞 * 01813CB0 35 FC 1C 77 20 FF 1C 77 20 24 34 0B 64 D5 68 00 ﰵ眜@眜␠଴핤h * 01813CC0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ * 01813CD0 7E 31 00 00 50 03 00 00 00 00 00 00 00 00 00 00 ㅾ.͐..... * 01813CE0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ * 01813CF0 00 00 00 00 00 00 F0 3F 00 00 00 00 00 00 F0 3F ...㿰...㿰 * * 01813C50 0C E8 69 00 10 C4 E4 03 00 00 00 00 00 00 00 00 i쐐Ϥ.... * 01813C60 30 32 81 01 00 00 00 00 00 00 00 00 84 03 00 00 ㈰Ɓ....΄. * 01813C70 76 00 00 00 FF FF FF 00 00 00 00 00 00 00 00 00 v..ÿ.... * 01813C80 00 00 00 00 26 00 00 00 00 00 00 00 00 00 00 00 ..&..... * 01813C90 06 00 00 00 03 00 00 00 28 5A 65 00 A0 31 81 01 ..娨eㆠƁ * 01813CA0 2C 00 00 00 43 00 00 00 00 01 01 00 BA C1 1E 77 ,.C.Ā솺眞 * 01813CB0 35 FC 1C 77 20 FF 1C 77 20 24 34 0B 64 D5 68 00 ﰵ眜@眜␠଴핤h */ bool attachCaller(ULONG addr); size_t textSize_; bool hookBefore(hook_stack*s,void* data, size_t* len,uintptr_t*role) { static std::wstring text_; // persistent storage, which makes this function not thread-safe textSize_ = 0; auto text = (LPCWSTR)s->stack[1]; // arg1 if (!text || !*text) return false; if (::wcscmp(text, L"----/--/-- --:--") == 0) return false; textSize_ = ::wcslen(text); if (s->stack[1] == s->stack[13]) // for new games attachCaller(s->stack[12]); else if (s->stack[1] == s->stack[14]) // for old games attachCaller(s->stack[13]); //else // very old or very new games auto retaddr = s->stack[0]; //int textStackIndex = -1; * role = Engine::OtherRole; if (s->stack[2] < 0x100) { // new game, this value is mostly 0x1e //if (s->stack[1] == s->stack[13]) // textStackIndex = 13; // 004DACA7 8D8E 000A0000 LEA ECX,DWORD PTR DS:[ESI+0xA00] // 004DACAD 53 PUSH EBX // 004DACAE FFD0 CALL EAX ; jichi: called here // 004DACB0 8B8E 100A0000 MOV ECX,DWORD PTR DS:[ESI+0xA10] // 004DACB6 894424 14 MOV DWORD PTR SS:[ESP+0x14],EAX // 004DACBA 8B41 08 MOV EAX,DWORD PTR DS:[ECX+0x8] // 004DACBD 33FF XOR EDI,EDI //if (*(WORD *)retaddr == 0x8e8b) { // 004DACB0 8B8E 100A0000 MOV ECX,DWORD PTR DS:[ESI+0xA10] *role = Engine::ScenarioRole; enum : wchar_t { w_open = 0x3010, w_close = 0x3011 }; /* 【】 */ if (text[0] == w_open && text[::wcslen(text) - 1] == w_close) *role = Engine::NameRole; } else if (s->stack[3] < 0x100 // for old game || *(WORD *)retaddr == s2_mov_ecx_edi && *(WORD *)(retaddr - 5) == 0x52ff) { // for very old game // Sample game: お兄ちゃん、右手の使用を禁止します! (old type) // 0055D207 8BCF MOV ECX,EDI // 0055D209 897C24 34 MOV DWORD PTR SS:[ESP+0x34],EDI // 0055D20D FF52 14 CALL DWORD PTR DS:[EDX+0x14] ; jichi: called here // 0055D210 8BCF MOV ECX,EDI ; jichi: retaddr is here // 0055D212 894424 18 MOV DWORD PTR SS:[ESP+0x18],EAX // Sample game: キスと魔王と紅茶 (old type) // name: // 004DBFEC 50 PUSH EAX // 004DBFED 8BCF MOV ECX,EDI // 004DBFEF FF52 10 CALL DWORD PTR DS:[EDX+0x10] ; jichi: called here // 004DBFF2 8B7424 7C MOV ESI,DWORD PTR SS:[ESP+0x7C] // 004DBFF6 33DB XOR EBX,EBX // 004DBFF8 3BF3 CMP ESI,EBX // 004DBFFA 74 4B JE SHORT .004DC047 // 004DBFFC 8BCF MOV ECX,EDI // 004DBFFE E8 9DA4FFFF CALL .004D64A0 // 004DC003 8BE8 MOV EBP,EAX // 004DC005 891E MOV DWORD PTR DS:[ESI],EBX // 004DC007 85ED TEST EBP,EBP // // Scenario: // 004B5207 8BCF MOV ECX,EDI // 004B5209 897C24 14 MOV DWORD PTR SS:[ESP+0x14],EDI // 004B520D FF52 10 CALL DWORD PTR DS:[EDX+0x10] ; jichi: called here // 004B5210 8BCF MOV ECX,EDI // 004B5212 894424 18 MOV DWORD PTR SS:[ESP+0x18],EAX // 004B5216 E8 85120200 CALL .004D64A0 // 004B521B 33ED XOR EBP,EBP *role = s->stack[5] == 0 ? Engine::NameRole : Engine::ScenarioRole; } return write_string_overwrite(data,len,text); } bool hookAfterCaller(hook_stack*s,void* data, size_t* len,uintptr_t*role) { if (textSize_) s->eax = textSize_; return false; } bool attachCaller(ULONG addr) { static std::unordered_set addresses_; if (addresses_.find(addr) != addresses_.end()) return false; addresses_.insert(addr); HookParam hp; hp.type=HOOK_EMPTY|EMBED_ABLE; hp.hook_before=hookAfterCaller; return true; } } // namespace Private } // namespace ScenarioHook } // unnamed namespace bool CotophaFilter(LPVOID data, size_t *size, HookParam *) { auto text = reinterpret_cast(data); auto len = reinterpret_cast(size); if (*len<=2 || text[0] != L'\\') return false; size_t lenPurged = 0; for (size_t i = 0; i < *len/2; i++) { if (text[i] != L'\\') { text[lenPurged++] = text[i]; } else { // start command wchar_t cmd=text[++i]; if (cmd == 'r') { // ruby i++; // skip ';' char while (text[++i] != L':') { if (text[i] == L';') // when we reach '; ' we have the kanji part break; text[lenPurged++] = text[i]; } } else if (cmd == L'n' && lenPurged) // newline text[lenPurged++] = L' '; // for Western language compatibility while (text[++i] != L':') ; } } if (lenPurged) text[lenPurged++] = L' '; // for Western language compatibility *len = lenPurged * 2; return true; } bool InsertCotophaHook1() { enum : DWORD { ins = 0xec8b55 }; // mov ebp,esp, sub esp,* ; jichi 7/12/2014 ULONG addr = MemDbg::findCallerAddress((ULONG)::GetTextMetricsA, ins, processStartAddress, processStopAddress); if (!addr) { ConsoleOutput("Cotopha: pattern not exist"); return false; } HookParam hp; hp.address = addr; hp.offset=get_stack(1); hp.split = get_reg(regs::ebp); hp.type = CODEC_UTF16|USING_SPLIT|USING_STRING|EMBED_ABLE|EMBED_AFTER_NEW; hp.hook_before=ScenarioHook::Private::hookBefore; hp.filter_fun = CotophaFilter; ConsoleOutput("INSERT Cotopha"); //RegisterEngineType(ENGINE_COTOPHA); return NewHook(hp, "Cotopha"); } bool InsertCotophaHook2() { if (void* addr = GetProcAddress(GetModuleHandleW(NULL), "eslHeapFree")) { HookParam hp; hp.address = (uintptr_t)addr; hp.offset=get_stack(2); hp.type = CODEC_UTF16 | USING_STRING; hp.filter_fun = [](void* data, size_t* len, HookParam*) { if(*len > VNR_TEXT_CAPACITY*2)return false; return std::wstring_view((wchar_t*)data, *len / sizeof(wchar_t)).find(L'\\') != std::wstring_view::npos; }; ConsoleOutput("INSERT Cotopha 2"); return NewHook(hp, "Cotopha2"); } return false; } bool InsertCotophaHook3() { const BYTE bytes[] = { 0x8B,0x75,0xB8,0x8B,0xCE,0x50,0xC6,0x45,0xFC,0x01,0xE8 }; ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR); ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range); if (!addr) { ConsoleOutput("Cotopha3: Cotopha3 not found"); return false; } HookParam myhp; myhp.address = addr; myhp.type = CODEC_UTF16 | USING_STRING |EMBED_ABLE|EMBED_BEFORE_SIMPLE|EMBED_AFTER_NEW; myhp.offset=get_reg(regs::eax); return NewHook(myhp, "Cotopha3_EWideString"); } bool InsertCotophaHook4() { /* * https://vndb.org/v32624 */ const BYTE bytes[] = { 0xCC, // int 3 0x55, // push ebp << hook here 0x8B, 0xEC, // mov ebp,esp 0x51, // push ecx 0x53, // push ebx 0x56, // push esi 0x57, // push edi 0x8B, 0x7D, 0x08, // mov edi,[ebp+08] 0x33, 0xF6, // xor esi,esi 0x8B, 0xD9, // mov ebx,ecx 0x85, 0xFF, // test edi,edi 0x74, 0x0D // je ststeady2.glsGetEnabledProcessorType+643F }; ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR); ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range); if (!addr) { ConsoleOutput("Cotopha4: pattern not found"); return false; } HookParam hp = {}; hp.address = addr + 1; hp.offset = get_stack(1); hp.type = CODEC_UTF16 | USING_STRING | NO_CONTEXT ; hp.filter_fun = CotophaFilter; NewHook(hp, "Cotopha4"); return true; } bool InsertCotophaHook() { InsertCotophaHook1(); return (InsertCotophaHook4()|InsertCotophaHook3()) || InsertCotophaHook2(); } bool Cotopha::attach_function() { return InsertCotophaHook(); }