Th07/Binary hacks

From Touhou Patch Center
Jump to: navigation, search

Bugs

Fix buffer overflows (safe sprintf)
(sprintf_call)
Address
v1.00b0x4542f1, 0x4543ee, 0x4545ee
Code
  1. 50
  2. e8 [strings_vsprintf]
  3. 8945 b0
  1. push eax
  2. call [strings_vsprintf]
  3. mov dword ptr ss:[ebp-0x50],eax
Safe sprintf (replace EAX)
(sprintf_rep_eax)
Address
v1.00b0x45431e, 0x454527, 0x45472d
Code
  1. 8b45 b0
  1. mov eax, [ebp-0x50]
Safe sprintf (replace ECX)
(sprintf_rep_ecx)
Address
v1.00b0x454493
Code
  1. 8b4d b0
  1. 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
  1. 8b55 0c
  2. 8b92 e4010000
  3. d942 30
  4. d84a 34
  5. d835 708a4900
  6. d842 04
  7. ff75 b0
  8. e8 [GetTextExtent]
  9. 83c0 04
  10. d1e8
  11. 50
  12. db04e4
  13. 58
  14. 8b4d 0c
  15. 8b91 e4010000
  16. d84a 34
  17. eb 3e
  18. 90 90 90 90 90 90 90 90
  19. 90 90 90 90 90 90 90 90
  20. 90 90 90 90 90 90 90 90
  21. 90 90 90 90 90 90 90 90
  22. 90 90 90 90 90 90 90 90
  23. 90 90 90 90 90 90 90 90
  24. 90 90 90 90 90 90 90 90
  25. 90 90 90 90 90 90
  1. mov edx,dword ptr ss:[ebp+0x0c]
  2. mov edx,dword ptr ds:[edx+0x1e4]
  3. fld dword ptr ds:[edx+0x30]
  4. fmul dword ptr ds:[edx+0x34]
  5. fdiv dword ptr ds:[th07.498A70]
  6. fadd dword ptr ds:[edx+0x4]
  7. push dword ptr ss:[ebp-0x50]
  8. call [GetTextExtent]
  9. add eax, 4
  10. shr eax, 1
  11. push eax
  12. fild dword ptr ss:[esp]
  13. pop eax
  14. mov ecx,dword ptr ss:[ebp+0x0c]
  15. mov edx,dword ptr ds:[ecx+0x1e4]
  16. fmul dword ptr ds:[edx+0x34]
  17. jmp short +0x3e
  18. 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
  1. 8b 45  b0
  2. 50
  3. e8 [GetTextExtent]
  4. 83 c0  04
  5. 50
  6. 3e db 04 e4
  7. 58
  8. 90 90 90 90 90 90
  1. mov eax, [ebp-0x50]
  2. push eax
  3. call [GetTextExtent]
  4. add eax, 4
  5. push eax
  6. fild dword ptr ss:[esp]
  7. pop eax
  8. 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
  1. 31f6
  2. eb 07
  3. 89f0
  4. 83c0 01
  5. 89c6
  6. 83fe 30
  7. 73 15
  8. 89f1
  9. 0fb6540d cc
  10. 81f2 aa000000
  11. 89f0
  12. 885405 cc
  13. eb df
  14. 8d4d cc
  15. 90
  16. 8b55 9c
  17. 0fbf42 0e
  18. 9090909090
  19. 51
  1. xor esi, esi
  2. jmp short +7h
  3. mov eax, esi
  4. add eax, 1
  5. mov esi, eax
  6. cmp esi, 30
  7. jae +15h
  8. mov ecx, esi
  9. movzx edx, byte ptr ss:[ecx+ebp-34]
  10. xor edx, aah
  11. mov eax,esi
  12. mov byte ptr ss:[eax+ebp-34], dl
  13. jmp short -21h
  14. lea ecx, [ebp-34]                 ; ECX = decrypted spell card name
  15. nop                               ; don't push it yet, though
  16. mov edx, dword ptr ss:[ebp-64]
  17. movsx eax, word ptr ds:[edx+0x0e] ; EAX = spell card number
  18. nop (*5)                          ; "Insert breakpoint here" - write pointer to translated spell name to ECX
  19. 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
  1. 31c0
  2. 48
  3. 8945 f8
  1. xor eax,eax
  2. dec eax
  3. mov dword ptr ss:[ebp-8],eax
Prepare Music Room comment line number fetching (first comment)
(music_cmt_prepare_first)
Address
v1.00b0x43b30a
Code
  1. 31c0
  2. 48
  3. 8945 fc
  1. xor eax,eax
  2. dec eax
  3. 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
  1. 8b45 fc
  2. 6bc0 78
  3. 05 b3626200
  1. mov eax,dword ptr ss:[ebp-4]
  2. imul eax,eax,78
  3. add eax, 0x6262b3