627 lines
20 KiB
ArmAsm
627 lines
20 KiB
ArmAsm
# This patch changes the number of BB character save slots from 4 to any number
|
|
# up to 127.
|
|
|
|
# This patch is for documentation purposes only; it works when used as a server
|
|
# patch via newserv, but is decidedly inconvenient to use via this method. This
|
|
# is because it affects logic that runs before any patches can be sent by the
|
|
# server, so the player has to connect once to get the patch, then disconnect
|
|
# and connect again to use the additional slots.
|
|
|
|
# As written, this patch changes the slot count from 4 to 12. To use a
|
|
# different slot count, first compute the following values:
|
|
# slot count = your desired number of player slots (must be >= 4, <= 127)
|
|
# total file size = (slot count * 0x2EA4) + 0x14
|
|
# bgm_test_songs_unlocked offset = total file size - 0x10
|
|
# save_count offset = total file size - 8
|
|
# round2_seed offset = total file size - 4
|
|
# Then, for each of the above, search for the string to the left of the = sign
|
|
# and change the values used in all of the matching lines.
|
|
|
|
.meta name="More save slots"
|
|
.meta description=""
|
|
.meta hide_from_patches_menu
|
|
|
|
entry_ptr:
|
|
reloc0:
|
|
.offsetof start
|
|
|
|
# Include a few functions first
|
|
write_call_to_code:
|
|
.include WriteCallToCode-59NL
|
|
memcpy:
|
|
.include CopyData
|
|
ret
|
|
|
|
|
|
|
|
start:
|
|
# Apply all necessary patches
|
|
call apply_enable_scroll_patch
|
|
call apply_fix_scroll_patch1
|
|
call apply_fix_scroll_patch2
|
|
call apply_fix_file_index
|
|
call apply_preview_window_fix
|
|
call apply_static_patches
|
|
# Rewrite the existing char file regions to have the appropriate size; this
|
|
# must be done after the patches are applied because we call the checksum
|
|
# function, which is patched by one of the above calls
|
|
call update_existing_char_file_list
|
|
jmp update_existing_char_file_list_memcard
|
|
|
|
|
|
|
|
apply_enable_scroll_patch:
|
|
# This patch enables scrolling behavior within the character list
|
|
push -5 # Jump size (negative = jmp instead of call)
|
|
push 0x00413B7F # Jump address
|
|
call get_code_size_for_enable_scroll
|
|
.deltaof enable_scroll_start, enable_scroll_end
|
|
get_code_size_for_enable_scroll:
|
|
pop eax
|
|
push dword [eax]
|
|
call enable_scroll_end
|
|
enable_scroll_start:
|
|
mov eax, dword ptr [edi + 0x28] # cursor = char_select_menu->cursor_obj (TAdSelectCurGC*)
|
|
or dword [eax + 0x01F8], 3 # cursor->flags |= 3 # Enable scrolling
|
|
mov eax, [0x00A3B050] # scroll_bar = TAdScrollBarXb_objs[0]
|
|
mov ecx, [eax + 0xEC] # ecx = scroll_bar->client_id
|
|
imul ecx, ecx, 0x24
|
|
# Set up scroll bar graphics (in struct at scroll_bar + 0x1C)
|
|
# TODO: Even though we set this up the same way PSO Xbox does, it still
|
|
# doesn't render. Figure this out and fix it.
|
|
mov dword [eax + ecx + 0x1C], 0x439D0000
|
|
mov dword [eax + ecx + 0x20], 0x43360000
|
|
mov dword [eax + ecx + 0x24], 0x439D0000
|
|
mov dword [eax + ecx + 0x28], 0x4392AB85
|
|
mov dword [eax + ecx + 0x2C], 0x40400000
|
|
mov dword [eax + ecx + 0x30], 0x425EA3D7
|
|
mov dword [eax + ecx + 0x34], 0x00000008
|
|
mov dword [eax + ecx + 0x38], 0x00000000
|
|
mov dword [eax + ecx + 0x2C], 0x00000000
|
|
or dword [eax + 0xF0], 1 # scroll_bar->flags |= 1
|
|
mov ecx, [eax + 0xEC]
|
|
shl ecx, 4
|
|
mov dword [eax + ecx + 0xAC], 0 # scroll_bar->selection_state[client_id].scroll_offset = 0
|
|
mov dword [eax + ecx + 0xB0], 0 # scroll_bar->selection_state[client_id].selected_index = 0
|
|
mov dword [eax + ecx + 0xB4], 4 # scroll_bar->selection_state[client_id].num_items_in_view = 4
|
|
mov dword [eax + ecx + 0xB8], 0x0B # scroll_bar->selection_state[client_id].last_item_index = (slot count - 1)
|
|
pop edi
|
|
ret
|
|
enable_scroll_end:
|
|
call write_call_to_code
|
|
ret
|
|
|
|
|
|
|
|
apply_fix_scroll_patch1:
|
|
# This patch fixes character selection cursor object so it will take the
|
|
# scroll offset into account
|
|
push 6 # Call size
|
|
push 0x00413C38 # Call address
|
|
call get_code_size_for_fix_scroll_patch1
|
|
.deltaof fix_scroll_patch1_start, fix_scroll_patch1_end
|
|
get_code_size_for_fix_scroll_patch1:
|
|
pop eax
|
|
push dword [eax]
|
|
call fix_scroll_patch1_end
|
|
fix_scroll_patch1_start:
|
|
mov edx, [edi + 0x28] # cursor = this->ad_select_cur_obj (TAdSelectCurGC*)
|
|
mov ebp, [edx + 0x44] # ebp = cursor->selected_index_within_view
|
|
mov eax, [0x00A3B050] # scroll_bar = TAdScrollBarXb_objs[0]
|
|
add ebp, [eax + 0xAC] # ebp += scroll_bar->selection_state[0].scroll_offset
|
|
ret
|
|
fix_scroll_patch1_end:
|
|
call write_call_to_code
|
|
ret
|
|
|
|
|
|
|
|
apply_fix_scroll_patch2:
|
|
# This patch changes the TAdSinglePlyChrSelectGC::selected_index_within_view
|
|
# to be the selected character's absolute index (including scroll_offset),
|
|
# not the index only within the displayed four characters
|
|
push 6 # Call size
|
|
push 0x00413CD8 # Call address
|
|
call get_code_size_for_fix_scroll_patch2
|
|
.deltaof fix_scroll_patch2_start, fix_scroll_patch2_end
|
|
get_code_size_for_fix_scroll_patch2:
|
|
pop eax
|
|
push dword [eax]
|
|
call fix_scroll_patch2_end
|
|
fix_scroll_patch2_start:
|
|
mov eax, [0x00A3B050] # scroll_bar = TAdScrollBarXb_objs[0]
|
|
mov eax, [eax + 0xAC] # eax = scroll_bar->selection_state[0].scroll_offset
|
|
mov edx, [edi + 0x28] # cursor = this->ad_select_cur_obj (TAdSelectCurGC*)
|
|
add eax, [edx + 0x44] # eax += cursor->selected_index_within_view
|
|
ret
|
|
fix_scroll_patch2_end:
|
|
call write_call_to_code
|
|
ret
|
|
|
|
|
|
|
|
apply_fix_file_index:
|
|
# This patch fixes the character file indexing so it will account for the
|
|
# scroll position
|
|
push 5 # Call size
|
|
push 0x00413CF0 # Call address
|
|
call get_code_size_for_selection_index_fix2
|
|
.deltaof selection_index_fix2_start, selection_index_fix2_end
|
|
get_code_size_for_selection_index_fix2:
|
|
pop eax
|
|
push dword [eax]
|
|
call selection_index_fix2_end
|
|
selection_index_fix2_start:
|
|
mov eax, [0x00A3B050]
|
|
mov eax, [eax + 0xAC] # eax = TAdScrollBarXb_objs[0]->selection_state[0].scroll_offset
|
|
add ebp, eax # arg0 += eax
|
|
mov [esp + 4], ebp
|
|
mov eax, 0x006C1A80
|
|
jmp eax # set_current_char_slot
|
|
selection_index_fix2_end:
|
|
call write_call_to_code
|
|
ret
|
|
|
|
|
|
|
|
apply_preview_window_fix:
|
|
# This patch fixes the preview display so it will show the correct section
|
|
# ID, level, etc.
|
|
push 5 # Call size
|
|
push 0x0040216C # Call address
|
|
call get_code_size_for_preview_window_fix
|
|
.deltaof preview_window_fix_start, preview_window_fix_end
|
|
get_code_size_for_preview_window_fix:
|
|
pop eax
|
|
push dword [eax]
|
|
call preview_window_fix_end
|
|
preview_window_fix_start:
|
|
mov eax, [0x00A3B050] # scroll_bar = TAdScrollBarXb_objs[0]
|
|
mov eax, [eax + 0xAC] # eax = scroll_bar->selection_state[0].scroll_offset
|
|
add [esp + 4], eax
|
|
mov eax, 0x006C44D0 # get_player_preview_info
|
|
jmp eax
|
|
preview_window_fix_end:
|
|
# This patch applies in two places, so push the second set of args now, then
|
|
# apply it twice
|
|
push 5 # Call size
|
|
push 0x00401842 # Call address
|
|
push dword [esp + 0x10] # Code size
|
|
push dword [esp + 0x10] # Code address
|
|
call write_call_to_code
|
|
call write_call_to_code
|
|
ret
|
|
|
|
|
|
|
|
apply_static_patches:
|
|
.include WriteCodeBlocksBB
|
|
# These patches change various places where the character data size and slot
|
|
# count are referenced
|
|
.data 0x004751A4
|
|
.data 0x00000001
|
|
.binary 0C # slot count; TDataProtocol::handle_E5
|
|
.data 0x0047525B
|
|
.data 0x00000001
|
|
.binary 0C # slot count; import_player_preview
|
|
.data 0x004785E1
|
|
.data 0x00000001
|
|
.binary 0C # slot count; TDataProtocol::handle_E4
|
|
.data 0x0048242D
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C17BF
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C1CCB
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C1CFE
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C1D1C
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C1DD7
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C222E
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C226D
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C228E
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C229E
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C24DB
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C2643
|
|
.data 0x00000004
|
|
.data 0x00022FBC # save_count offset
|
|
.data 0x006C264D
|
|
.data 0x00000004
|
|
.data 0x00022FBC # save_count offset
|
|
.data 0x006C26EF
|
|
.data 0x00000004
|
|
.data 0x00022FBC # save_count offset
|
|
.data 0x006C2705
|
|
.data 0x00000004
|
|
.data 0x00022FC0 # round2_seed offset
|
|
.data 0x006C2793
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C286C
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C3113
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C353F
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C357E
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C35AA
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C35B7
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C35D2
|
|
.data 0x00000004
|
|
.data 0x00022FBC # save_count offset
|
|
.data 0x006C35DB
|
|
.data 0x00000004
|
|
.data 0x00022FBC # save_count offset
|
|
.data 0x006C36E0
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C3B1E
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C4209
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C47EF
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C4826
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C4962
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C4999
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C4A81
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C4ABA
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C4C9A
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C4CD1
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C4DB9
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C4DF2
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C4F58
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C4F94
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C5181
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C51BD
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C5332
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C536C
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C5501
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C553D
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C56B2
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C56EC
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C5872
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C58AC
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C5A41
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C5A7D
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C5B6E
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C5BA8
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C5D2E
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C5D68
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C5EEE
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C5F28
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C60AE
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C60E8
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C6303
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C633D
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C64C1
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C64FD
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C65EE
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C6628
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C67AE
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C67E8
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C696E
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C69A8
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C6B43
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C6B74
|
|
.data 0x00000004
|
|
.data 0x0000005D # memcard block count
|
|
.data 0x006C6BF6
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C6C30
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C6E3E
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C6E78
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C7075
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C70AF
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C7A02
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C7D22
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x006C7D5E
|
|
.data 0x00000001
|
|
.binary 0C # slot count
|
|
.data 0x006C7D7C
|
|
.data 0x00000004
|
|
.data 0x00022FC4 # total file size
|
|
.data 0x0077BE92
|
|
.data 0x00000004
|
|
.data 0x00022FB4 # bgm_test_songs_unlocked offset
|
|
|
|
# Signature check on all save files (rewritten as loop)
|
|
.data 0x006C1C2D
|
|
.deltaof sig_check_begin, sig_check_end
|
|
sig_check_begin:
|
|
mov edx, 0xC87ED5B1 # Expected signature value
|
|
add eax, 0x04E8 # &char_file_list->chars[0].part2.signature
|
|
mov ecx, 0x0C # slot count
|
|
again:
|
|
cmp dword [eax], 0 # signature == 0 (no char in slot)
|
|
je sig_ok
|
|
cmp dword [eax], edx # signature == expected value
|
|
jne sig_bad
|
|
sig_ok:
|
|
add eax, 0x2EA4 # Advance to next slot
|
|
dec ecx
|
|
jnz again
|
|
xor eax, eax # All signatures OK (eax = 0)
|
|
jmp sig_check_end
|
|
sig_bad:
|
|
xor eax, eax # Bad signature (eax = 1)
|
|
inc eax
|
|
jmp sig_check_end
|
|
.binary CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
sig_check_end: # 006C1C76
|
|
|
|
# Send slot count in E3 command
|
|
.data 0x0046EB20 # TDataProtocol::send_E3_for_index
|
|
.deltaof send_slot_count_in_E3_begin, send_slot_count_in_E3_end
|
|
send_slot_count_in_E3_begin:
|
|
# ecx = this (TDataProtocol*)
|
|
# [esp + 4] = slot_index
|
|
push 0
|
|
push dword [esp + 8] # slot_index
|
|
push 0x0C # slot count
|
|
push 0x00E30010
|
|
mov eax, esp
|
|
push 0x10
|
|
push eax
|
|
mov eax, [ecx]
|
|
call [eax + 0x20] # this->send_command(&cmd, 0x10) // ret 8
|
|
add esp, 8
|
|
mov eax, 0x006C1A80
|
|
call eax # set_current_char_slot(slot_index) // ret 0
|
|
add esp, 8
|
|
ret 4
|
|
send_slot_count_in_E3_end:
|
|
|
|
# Show slot number in each menu item
|
|
.data 0x00401D57
|
|
.deltaof show_slot_number_begin, show_slot_number_end
|
|
show_slot_number_begin:
|
|
# Original call (sprintf(line_buf, "LV%d", preview_info->visual.disp.level + 1))
|
|
lea edx, [esp + 0x02C4]
|
|
mov ebx, [ebx + 8]
|
|
inc ebx
|
|
push ebx
|
|
mov ecx, esi
|
|
push edx
|
|
mov eax, 0x00402604
|
|
call eax
|
|
# Find the end of the string
|
|
lea eax, [esp + 0x02C4]
|
|
show_slot_number_strend_again:
|
|
cmp word [eax], 0
|
|
je show_slot_number_strend_done
|
|
add eax, 2
|
|
jmp show_slot_number_strend_again
|
|
show_slot_number_strend_done:
|
|
# Format the slot number and append it to the string
|
|
mov ecx, [0x00A3B050] # scroll_bar = TAdScrollBarXb_objs[0]
|
|
mov ecx, [ecx + 0xAC] # ecx = scroll_bar->selection_state[0].scroll_offset
|
|
lea ecx, [ecx + ebp + 1]
|
|
push ecx # Slot number (scroll_offset + z)
|
|
call get_show_slot_number_suffix_fmt
|
|
.binary 2000280023002500640029000000 # L" (#%d)"
|
|
get_show_slot_number_suffix_fmt:
|
|
push eax # Destination buffer
|
|
mov eax, 0x00857E29 # _swprintf
|
|
call eax
|
|
add esp, 0x0C
|
|
jmp show_slot_number_end
|
|
.zero 0x98
|
|
show_slot_number_end: # 00401E4D
|
|
|
|
# End static patches
|
|
.data 0x00000000
|
|
.data 0x00000000
|
|
|
|
|
|
|
|
update_existing_char_file_list:
|
|
# Replace the existing character list with an appropriately-longer one. This
|
|
# part does not need to be done if the patch is applied statically to the
|
|
# executable; this is only necessary when used as a server patch because the
|
|
# character list is already allocated at the time the patch is applied.
|
|
push 0x00022FC4 # total file size
|
|
mov eax, 0x008581C5 # operator_new
|
|
call eax
|
|
add esp, 4
|
|
mov edx, [0x00A95E44] # edx = old char_file_list
|
|
mov [0x00A95E44], eax
|
|
mov ecx, [edx + 0xBA94] # Copy bgm_test_songs_unlocked_high to new file
|
|
mov [eax + 0x00022FB4], ecx
|
|
mov ecx, [edx + 0xBA98] # Copy bgm_test_songs_unlocked_low to new file
|
|
mov [eax + 0x00022FB8], ecx
|
|
mov ecx, [edx + 0xBA9C] # Copy save_count to new file
|
|
mov [eax + 0x00022FBC], ecx
|
|
mov ecx, [edx + 0xBAA0] # Copy round2_seed to new file
|
|
mov [eax + 0x00022FC0], ecx
|
|
add eax, 4
|
|
add edx, 4
|
|
mov ecx, 0xBA90
|
|
call memcpy # Copy the existing 4 characters over
|
|
mov eax, [0x00A95E44]
|
|
add eax, 0xBA94
|
|
mov ecx, 4
|
|
clear_next_char:
|
|
cmp ecx, 0x0C # slot count
|
|
jge clear_next_char_done
|
|
lea edx, [eax + 0x2EA4] # edx = ptr to next char (or footer)
|
|
clear_next_char_write_again:
|
|
mov dword [eax], 0
|
|
add eax, 4
|
|
cmp eax, edx
|
|
jl clear_next_char_write_again
|
|
clear_next_char_done:
|
|
|
|
# Call eh_vector_constructor_iterator(
|
|
# &char_file_list.chars[4],
|
|
# sizeof(char_file_list.chars[0]),
|
|
# countof(char_file_list.chars) - 4,
|
|
# PSOCharacterFile::init,
|
|
# PSOCharacterFile::destroy)
|
|
push 0x006C1940 # PSOCharacterFile::destroy
|
|
push 0x006C17F0 # PSOCharacterFile::init
|
|
push 0x08 # slot count - 4
|
|
push 0x2EA4 # sizeof(PSOCharacterFile)
|
|
mov eax, [0x00A95E44]
|
|
add eax, 0xBA94
|
|
push eax
|
|
mov eax, 0x00858736
|
|
call eax
|
|
|
|
# Fix the file's checksum
|
|
mov eax, [0x00A95E44]
|
|
mov ecx, 0x006C26FC
|
|
jmp ecx # PSOBBCharacterFileList::checksum(char_file_list)
|
|
|
|
|
|
|
|
update_existing_char_file_list_memcard:
|
|
# Allocate a new memory card file area and copy the data there too. It seems
|
|
# Sega didn't fully strip out the local saving code from PSOBB; instead, they
|
|
# just made it write to a heap-allocated buffer. Since the file is much
|
|
# bigger now, we also have to make that heap-allocated buffer larger. We add
|
|
# a few "blocks" on the end, since the original code in the game does that
|
|
# too, but it's probably not strictly necessary.
|
|
# Like the above, this part is not necessary if this patch is statically
|
|
# applied to the executable.
|
|
mov eax, 0x00022FC4 # total file size
|
|
add eax, 0x0000FFFF
|
|
and eax, 0xFFFFC000
|
|
push eax
|
|
mov eax, 0x0082E940
|
|
call eax # malloc10(total file size)
|
|
add esp, 4
|
|
mov [0x00A95E2C], eax
|
|
mov edx, [0x00A95E44]
|
|
mov ecx, 0x00022FC4 # total file size
|
|
jmp memcpy
|