Th06/Binary hacks

From Touhou Patch Center
< Th06
Revision as of 04:06, 5 November 2013 by NamelessLegacy (talk | contribs) (I implemented persistent string concatenation just for this one instance. Will be available in the next build.)
Jump to navigation Jump to search

Bugs

Fix buffer overflows (remove copy)
(buffer_overflow_rem)
Description This is caused by needlessly copying the string argument to a local variable limited to 64 bytes. If the line exceeds this buffer, the game crashes. We fix it by removing the copy function and simply passing the pointer to the original text data.
Address
v1.02h0x434b85, 0x434c83, 0x434e63
Code
eb 19
90
jmp short +19h
nop
Fix buffer overflows (replace EAX)
(buffer_overflow_rep_eax)
Address
v1.02h0x434ba0, 0x434d8e, 0x434f74
Code
8b45 18
mov eax, [ebp+18]
Fix buffer overflows (replace ECX)
(buffer_overflow_rep_ecx)
Address
v1.02h0x434d17, 0x434ef7
Code
8b4d 18
mov ecx, [ebp+18]

Text alignment

Boss title alignment
(boss_title_align)
Description * Call GetTextExtent on string to render
  • Add 4 to compensate for multiple TextOut layers
  • Convert to float
Address
v1.02h0x434d72
Code
8b 45  18
50
e8 [GetTextExtent]
83 c0  04
50
3e db 04 e4
58
mov eax, [ebp+18]
push eax
call [GetTextExtent]
add eax, 4
push eax
fild dword ptr ds:[esp]
pop eax
Spell card and bomb text alignment
(spell_align)
Description The English patch has its own hackish text length calculation, replacing the original string length loop before the FPU operations. We don't need that loop anyway, so we jump over it.

The rest is the same as above, just with different stack addresses and a jump over nonsensical calculations at the end.

And yes, this is binarily identical for player bombs and enemy spells!
Address
v1.02h0x417b92, 0x417cc8
Code
eb 25
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
8b 45  0c
50
e8 [GetTextExtent]
50
3e db 04 e4
58
eb  0b
jmp +25h
nop (*25h)


mov eax, [ebp+c]
push eax
call [GetTextExtent]
push eax
fild dword ptr ds:[esp]
pop eax
jmp +0bh
Stage title alignment
(stage_title_align)
Description Same, except that we divide the width by 2 here.
Address
v1.02h0x434f3c
Code
8b 45  18
50
e8 [GetTextExtent]
d1 f8
83 c0  04
50
3e db 04 e4
58
eb 18
mov eax, [ebp+18]
push eax
call [GetTextExtent]
sar eax, 1
add eax, 1
push eax
fild dword ptr ds:[esp]
pop eax
jmp short +18
Fix spell align sillyness
(spell_align_sillyness)
Description NOPing out a multiplication with 15 followed by a division by 16 correctly aligns spell card names as expected. Why ZUN did that is beyond me.
Address
v1.02h0x41affc, 0x41b0b0
Code
90 90 90 90 90 90
90 90 90 90 90 90
nop (*0bh)

Spell cards

Prepare ECL instruction register for spell ID fetching
(spell_prepare)
Description Loads ESI with a pointer to the ECL instruction structure and reorders a couple of assignments to not break the code. ESI is not read or modified between this hack and spell_fetch_id where we need it.
Address
v1.02h0x407509
Code
8b75 e4
89f1
83c1 0c
894d e8
0fbf46 04
90
mov esi, dword ptr ss:[ebp-1c]
mov ecx, esi
add ecx, 0ch
mov dword ptr ss:[ebp-18], ecx
movsx eax, word ptr ds:[esi+4]
nop
Fetch spell ID
(spell_fetch_id)
Description With the ECL instruction structure in ESI, we can optimize the element accesses, and end up with just enough space to fetch the spell card number into ECX. (This crashes the game without spell_prepare applied, maybe we should do something about that.)
Address
v1.02h0x409622
Code
0fbf4e 0e
89f0
83c0 10
50
0fbf56 0c
movsx ecx, word ptr ds:[esi+0e] ; ECX = spell card number
mov eax, esi
add eax, 10                     ; EAX = spell card name
push eax                        ; insert breakpoint here
movsx edx, word ptr ds:[esi+0c] ; EDX = face ID

Compatibility

Remove English patch spell translation lookup in the Result screen
(unpatch_result_spell)
Description Necessary because we wouldn't be able to set any spell breakpoint, since the addresses we'd need differ between the original and the English patch. And since we have to do something about it anyway, we also keep the spell number in EAX to save one breakpoint.
Address
v1.02h0x42e2a9
Code
89c1
c1e1 06
81c1 e8bc6900
51
6a 00
68 ffffff00
mov ecx,eax
shl ecx,6
add ecx,0x69bce8
push ecx
push 0
push 0xffffff

Icon th06 custom.png [[th06_custom|]] (th06_custom)

Translate pad input check
(translate_padinput)
Address
v0.13Rx16e1
v1.02hRx16fb
Code
89c3
6a 00
e8 [strings_strclr]


f6c3 10
74 0e
68 dc914000
6a 00
e8 [strings_strcat]
59
59


f6c3 20
74 0e
68 d8914000
6a 00
e8 [strings_strcat]
59
59


f6c3 40
74 0e
68 d4914000
6a 00
e8 [strings_strcat]
59
59


f6c3 80
74 0e
68 d0914000
6a 00
e8 [strings_strcat]
59
59

eb 1a
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 ebx,eax
push 0
call [strings_strclr]

; Up
test bl,10
je short +0xe
push offset custom.004091DC
push 0
call [strings_strcat]
pop ecx
pop ecx

; Down
test bl,20
je short +0xe
push offset custom.004091D8
push 0
call [strings_strcat]
pop ecx
pop ecx

; Left
test bl,40
je +0xe
push offset custom.004091D4
push 0
call [strings_strcat]
pop ecx
pop ecx

; Right
test bl,80
je +0xe
push offset custom.004091D0
push 0
call [strings_strcat]
pop ecx
pop ecx

jmp short +0x1a
nop (*0x1a)