Th09/Binary hacks

From Touhou Patch Center
Jump to navigation Jump to search

Bugs

Safe sprintf (first call)
(sprintf_call_1)
Address
v1.50a0x43bdde
Code
50
e8 [strings_vsprintf]
8945 80
push eax
call [strings_vsprintf]
mov dword ptr ss:[ebp-0x80],eax
Safe sprintf (second call)
(sprintf_call_2)
Address
v1.50a0x43be7d
Code
50
e8 [strings_vsprintf]
8945 b8
push eax
call [strings_vsprintf]
mov dword ptr ss:[ebp-0x48],eax
Safe sprintf (replace pointer)
(sprintf_rep)
Address
v1.50a0x43be01, 0x43beb2
Code
8b
mov ???,dword ptr ss:[ebp-

Music Room

Prepare Music Room title parameter fetching
(music_title_prepare)
Description th09's code optimization certainly was better than those of earlier games, but there's still room for improvement. The original code calculates the same address twice. By optimizing this calculation and spilling the result to the stack, we save 13 bytes - enough to load both the track string and the track number into registers.
Address
v1.50a0x42748a
Code
8d8c0f dca30100
51
53
51
8b8e 901b0100
e8 61c9fdff
59
8b45 ec
803c18 00
74 2b
8d93 61ffffff
8b45 f4
50
68 80203000
68 ffe0d000
90 90 90 90 90 90
lea ecx,[ecx+edi+0x1a3dc]          ; we'll need this address twice
push ecx                           ; spill to stack
push ebx
push ecx
mov ecx,dword ptr ds:[esi+0x11b90] ; yup, this is a function parameter
call th09.00403e00
pop ecx                            ; recover our address to the register expected later
mov eax,dword ptr ss:[ebp-0x14]
cmp byte ptr ds:[ebx+eax],0
je short th09.004274d4
lea edx,[ebx-0x9f]                 ; EDX = track number
mov eax,dword ptr ss:[ebp-0x0c]    ; EAX = string
push eax                           ; insert breakpoint here
push 0x302080
push 0x0d0eff
nop (*6)
Rewrite Music Room comment render calls
(music_cmt_rewrite)
Description Because it would have been completely impossible to add music comment breakpoints to the original function with its 8 case statements, one for each comment line. Turns out that all necessary structure offsets can be easily calculated and the switch statement isn't necessary at all. This removes a total of 391 bytes from the function!
Address
v1.50a0x426e2a
Code
Error: String exceeds 1,000 character limit.
shr eax,1                                              ; frame / 2
jb short +6                                            ; Only display a line on even frames
dec eax                                                ; EAX = line number
cmp eax,7                                              ; maximum of 8 lines
jbe short +5
jmp +0x1ee                                             ; don't print anything
imul edi,eax,0x2a4                                     ; prepare offset to something
mov byte ptr ds:[esi+edi+0x19f02],1                    ; set something to 1
lea edi,[esi+edi+0x19d04]                              ; EDI = pointer to something
mov ebx,dword ptr ds:[esi+0x11b74]                     ; EBX = track number
cmp byte ptr ds:[ebx+th09.music_unlock_table],0        ; Unlocked?
je short +0x19                                         ; No
imul edx,eax,0x42                                      ; Yes; prepare line offset
imul ecx,ebx,0x292                                     ; prepare track offset
add edx,ecx
lea ecx,[esi+edx+0x0c9b6]                              ; ECX = original string
nop (*5)                                               ; insert breakpoint here
jmp short +7
mov ecx,dword ptr ds:[eax*4+th09.music_spoiler_table]  ; ECX = spoiler message
mov eax,edi                                            ; EAX = pointer to something
push ecx                                               ; Push string
xor ebx,ebx                                            ; reset EBX
jmp +0x187
nop (*0x187)