Th07/Binary hacks

From Touhou Patch Center
Jump to navigation Jump to search

Bugs

Fix buffer overflows (safe sprintf)
(sprintf_call)
Address
v1.00b0x4542f1, 0x4543ee, 0x4545ee
Code
50
e8 [strings_vsprintf]
8945 b0
push eax
call [strings_vsprintf]
mov dword ptr ss:[ebp-0x50],eax
Safe sprintf (replace EAX)
(sprintf_rep_eax)
Address
v1.00b0x45431e, 0x454527, 0x45472d
Code
8b45 b0
mov eax, [ebp-0x50]
Safe sprintf (replace ECX)
(sprintf_rep_ecx)
Address
v1.00b0x454493
Code
8b4d b0
mov ecx, [ebp-0x50]

Text alignment

(menu_desc_align)
Description Optimizing some stuff, we end up with 64 bytes to remove.
Address
v1.00b0x454693
Code
8b55 0c
8b92 e4010000
d942 30
d84a 34
d835 708a4900
d842 04
ff75 b0
e8 [GetTextExtent]
83c0 04
d1e8
50
db04e4
58
8b4d 0c
8b91 e4010000
d84a 34
eb 3e
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
90 90 90 90 90 90
mov edx,dword ptr ss:[ebp+0x0c]
mov edx,dword ptr ds:[edx+0x1e4]
fld dword ptr ds:[edx+0x30]
fmul dword ptr ds:[edx+0x34]
fdiv dword ptr ds:[th07.498A70]
fadd dword ptr ds:[edx+0x4]
push dword ptr ss:[ebp-0x50]
call [GetTextExtent]
add eax, 4
shr eax, 1
push eax
fild dword ptr ss:[esp]
pop eax
mov ecx,dword ptr ss:[ebp+0x0c]
mov edx,dword ptr ds:[ecx+0x1e4]
fmul dword ptr ds:[edx+0x34]
jmp short +0x3e
nop (*0x3e)
Boss title alignment
(boss_title_align)
Description Same as the th06 version, but NOPs out an additional FPU division at the end.
Address
v1.00b0x4544eb
Code
8b 45  b0
50
e8 [GetTextExtent]
83 c0  04
50
3e db 04 e4
58
90 90 90 90 90 90
mov eax, [ebp-0x50]
push eax
call [GetTextExtent]
add eax, 4
push eax
fild dword ptr ss:[esp]
pop eax
nop (*6)

Spell cards

Rewrite spell card name decryption loop
(spell_loop)
Description ... in order to squeeze in an instruction to fetch the spell card number from the stack.

Because the game does not do this until it has long printed the spell card name.

This is possible because the code, luckily, uses only three registers in the original. This hack replaces [ebp-4] with ESI, which is unused otherwise.

This does not affect the result screen, though.
Address
v1.00b0x40fcb1
Code
31f6
eb 07
89f0
83c0 01
89c6
83fe 30
73 15
89f1
0fb6540d cc
81f2 aa000000
89f0
885405 cc
eb df
8d4d cc
90
8b55 9c
0fbf42 0e
9090909090
51
xor esi, esi
jmp short +7h
mov eax, esi
add eax, 1
mov esi, eax
cmp esi, 30
jae +15h
mov ecx, esi
movzx edx, byte ptr ss:[ecx+ebp-34]
xor edx, aah
mov eax,esi
mov byte ptr ss:[eax+ebp-34], dl
jmp short -21h
lea ecx, [ebp-34]                 ; ECX = decrypted spell card name
nop                               ; don't push it yet, though
mov edx, dword ptr ss:[ebp-64]
movsx eax, word ptr ds:[edx+0x0e] ; EAX = spell card number
nop (*5)                          ; "Insert breakpoint here" - write pointer to translated spell name to ECX
push ecx                          ; And away we go

Music Room

Prepare Music Room comment line number fetching
(music_cmt_prepare)
Description So, in order to make enough room for the music_cmt#line_num breakpoint, we would need to somehow scrape together one more byte to be able to put it at the only position possible...

Or we simply remove the initial jump to the looping condition, which would target to the final byte of the breakpoint call. Since this would skip the first loop ([ebp-8] == 0), we have to start out with ([ebp-8] == -1) instead... and this assignment just happens to fit into the space we're given.

This is probably the most beautiful binary hack ever.
Address
v1.00b0x43aa32
Code
31c0
48
8945 f8
xor eax,eax
dec eax
mov dword ptr ss:[ebp-8],eax
Prepare Music Room comment line number fetching (first comment)
(music_cmt_prepare_first)
Address
v1.00b0x43b30a
Code
31c0
48
8945 fc
xor eax,eax
dec eax
mov dword ptr ss:[ebp-4],eax

Compatibility

Remove English patch spell translation lookup in the Result screen
(unpatch_result_spell)
Address
v1.00bRx467ea
Code
8b45 fc
6bc0 78
05 b3626200
mov eax,dword ptr ss:[ebp-4]
imul eax,eax,78
add eax, 0x6262b3