Th06/Binary hacks

From Touhou Patch Center
Jump to: navigation, 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
  1. eb 19
  2. 90
  1. jmp short +19h
  2. nop
Fix buffer overflows (replace EAX)
(buffer_overflow_rep_eax)
Address
v1.02h0x434ba0, 0x434d8e, 0x434f74
Code
  1. 8b45 18
  1. mov eax, [ebp+18]
Fix buffer overflows (replace ECX)
(buffer_overflow_rep_ecx)
Address
v1.02h0x434d17, 0x434ef7
Code
  1. 8b4d 18
  1. 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
  1. 8b 45  18
  2. 50
  3. e8 [GetTextExtent]
  4. 83 c0  04
  5. 50
  6. 3e db 04 e4
  7. 58
  1. mov eax, [ebp+18]
  2. push eax
  3. call [GetTextExtent]
  4. add eax, 4
  5. push eax
  6. fild dword ptr ds:[esp]
  7. 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
  1. eb 25
  2. 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
  3. 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
  4. 90 90 90 90 90
  5. 8b 45  0c
  6. 50
  7. e8 [GetTextExtent]
  8. 50
  9. 3e db 04 e4
  10. 58
  11. eb  0b
  1. jmp +25h
  2. nop (*25h)
  3.  
  4.  
  5. mov eax, [ebp+c]
  6. push eax
  7. call [GetTextExtent]
  8. push eax
  9. fild dword ptr ds:[esp]
  10. pop eax
  11. jmp +0bh
Stage title alignment
(stage_title_align)
Description Same, except that we divide the width by 2 here.
Address
v1.02h0x434f3c
Code
  1. 8b 45  18
  2. 50
  3. e8 [GetTextExtent]
  4. d1 f8
  5. 83 c0  04
  6. 50
  7. 3e db 04 e4
  8. 58
  9. eb 18
  1. mov eax, [ebp+18]
  2. push eax
  3. call [GetTextExtent]
  4. sar eax, 1
  5. add eax, 1
  6. push eax
  7. fild dword ptr ds:[esp]
  8. pop eax
  9. 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
  1. 90 90 90 90 90 90
  2. 90 90 90 90 90 90
  1. 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
  1. 8b75 e4
  2. 89f1
  3. 83c1 0c
  4. 894d e8
  5. 0fbf46 04
  6. 90
  1. mov esi, dword ptr ss:[ebp-1c]
  2. mov ecx, esi
  3. add ecx, 0ch
  4. mov dword ptr ss:[ebp-18], ecx
  5. movsx eax, word ptr ds:[esi+4]
  6. 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
  1. 0fbf4e 0e
  2. 89f0
  3. 83c0 10
  4. 50
  5. 0fbf56 0c
  1. movsx ecx, word ptr ds:[esi+0e] ; ECX = spell card number
  2. mov eax, esi
  3. add eax, 10                     ; EAX = spell card name
  4. push eax                        ; insert breakpoint here
  5. 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
  1. 89c1
  2. c1e1 06
  3. 81c1 e8bc6900
  4. 51
  5. 6a 00
  6. 68 ffffff00
  1. mov ecx,eax
  2. shl ecx,6
  3. add ecx,0x69bce8
  4. push ecx
  5. push 0
  6. push 0xffffff

Icon th06 custom.png Configuration tool (th06_custom)

Translate pad input check
(translate_padinput)
Address
v0.13Rx16e1
v1.02hRx16fb
Code
  1. 89c3
  2. 6a 00
  3. e8 [strings_strclr]
  4.  
  5.  
  6. f6c3 10
  7. 74 0e
  8. 68 dc914000
  9. 6a 00
  10. e8 [strings_strcat]
  11. 59
  12. 59
  13.  
  14.  
  15. f6c3 20
  16. 74 0e
  17. 68 d8914000
  18. 6a 00
  19. e8 [strings_strcat]
  20. 59
  21. 59
  22.  
  23.  
  24. f6c3 40
  25. 74 0e
  26. 68 d4914000
  27. 6a 00
  28. e8 [strings_strcat]
  29. 59
  30. 59
  31.  
  32.  
  33. f6c3 80
  34. 74 0e
  35. 68 d0914000
  36. 6a 00
  37. e8 [strings_strcat]
  38. 59
  39. 59
  40.  
  41. eb 1a
  42. 90 90 90 90 90 90
  43. 90 90 90 90 90 90
  44. 90 90 90 90 90 90
  45. 90 90 90 90 90 90
  46. 90 90
  1. mov ebx,eax
  2. push 0
  3. call [strings_strclr]
  4.  
  5. ; Up
  6. test bl,10
  7. je short +0xe
  8. push offset custom.004091DC
  9. push 0
  10. call [strings_strcat]
  11. pop ecx
  12. pop ecx
  13.  
  14. ; Down
  15. test bl,20
  16. je short +0xe
  17. push offset custom.004091D8
  18. push 0
  19. call [strings_strcat]
  20. pop ecx
  21. pop ecx
  22.  
  23. ; Left
  24. test bl,40
  25. je +0xe
  26. push offset custom.004091D4
  27. push 0
  28. call [strings_strcat]
  29. pop ecx
  30. pop ecx
  31.  
  32. ; Right
  33. test bl,80
  34. je +0xe
  35. push offset custom.004091D0
  36. push 0
  37. call [strings_strcat]
  38. pop ecx
  39. pop ecx
  40.  
  41. jmp short +0x1a
  42. nop (*0x1a)