mirror of
https://github.com/pret/pmd-sky.git
synced 2026-09-26 20:27:50 -05:00
Decomped IsChargingAnyTwoTurnMove
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from typing import List
|
||||
from write_inc_file import write_inc_file
|
||||
|
||||
# Use this script to extract a function out of assembly and create a blank C function as a placeholder.
|
||||
# If the function is in the middle, the assembly file is split in two. If the function is at either end, it is added to the next/previous source file.
|
||||
@@ -128,56 +128,6 @@ for i, line in enumerate(lsf_lines):
|
||||
lsf_lines[i] += f'\tObject asm/{new_asm_base_name}.o\n'
|
||||
break
|
||||
|
||||
BRANCH_LINK_INSTRUCTION = '\tbl '
|
||||
BRANCH_LINK_EXCHANGE_INSTRUCTION = '\tblx '
|
||||
BRANCH_INSTRUCTION = '\tb '
|
||||
WORD_KEY = '.word '
|
||||
WORD_PLUS_OFFSET = ' + 0x'
|
||||
"""
|
||||
Searches through an ASM file's contents for all external symbols, then populates a .inc file with all the necessary .public definitions.
|
||||
"""
|
||||
def write_inc_file(lines: List[str], file_path: str):
|
||||
defined_functions = set()
|
||||
used_functions = set()
|
||||
for line in lines:
|
||||
if line.startswith(ARM_FUNC_START):
|
||||
defined_functions.add(line[len(ARM_FUNC_START) : -1])
|
||||
elif line.startswith(BRANCH_LINK_INSTRUCTION):
|
||||
used_functions.add(line[len(BRANCH_LINK_INSTRUCTION) : -1])
|
||||
elif line.startswith(BRANCH_INSTRUCTION):
|
||||
function = line[len(BRANCH_INSTRUCTION) : -1]
|
||||
if function[0] != '_':
|
||||
semicolon_index = function.index(' ; ')
|
||||
used_functions.add(function[:semicolon_index])
|
||||
elif line.startswith(BRANCH_LINK_EXCHANGE_INSTRUCTION):
|
||||
function = line[len(BRANCH_LINK_EXCHANGE_INSTRUCTION) : -1]
|
||||
if function not in {'fp', 'ip', 'lr', 'sb', 'sl'} and not (
|
||||
function.startswith('r') and function[1:].isdigit() # rN
|
||||
):
|
||||
used_functions.add(function)
|
||||
else:
|
||||
word_index = line.find(WORD_KEY)
|
||||
if word_index >= 0 and f'{WORD_KEY}0x' not in line:
|
||||
word_plus_offset_index = line.find(WORD_PLUS_OFFSET)
|
||||
if word_plus_offset_index >= 0:
|
||||
new_word = line[word_index + len(WORD_KEY) : word_plus_offset_index]
|
||||
else:
|
||||
new_word = line[word_index + len(WORD_KEY) : -1]
|
||||
|
||||
if new_word[0] < '0' or new_word > '9':
|
||||
used_functions.add(new_word)
|
||||
|
||||
for function in defined_functions:
|
||||
if function in used_functions:
|
||||
used_functions.remove(function)
|
||||
|
||||
write_lines = ['#pragma once\n']
|
||||
for function in sorted(used_functions):
|
||||
write_lines.append(f'.public {function}\n')
|
||||
|
||||
with open(file_path, 'w') as inc_file:
|
||||
inc_file.writelines(write_lines)
|
||||
|
||||
print('Updating', LSF_FILE_PATH)
|
||||
with open(LSF_FILE_PATH, 'w') as lsf_file:
|
||||
lsf_file.writelines(lsf_lines)
|
||||
|
||||
95
tools/extract_function/split_data.py
Normal file
95
tools/extract_function/split_data.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from write_inc_file import write_inc_file
|
||||
|
||||
# Use this script to split a data file at a certain symbol.
|
||||
# Example usage: python split_data.py overlay_29_0234EC38 MULTI_TURN_BIDE_CLASS_STATUSES
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
print('Usage: python extract_function.py <asm_file> <split_symbol_name>')
|
||||
exit(1)
|
||||
|
||||
_, symbol_location, symbol_name = sys.argv[0:3]
|
||||
|
||||
|
||||
if symbol_location.endswith('.s'):
|
||||
symbol_location = symbol_location[:-2]
|
||||
if symbol_location.startswith("./asm/"):
|
||||
symbol_location = symbol_location[6:]
|
||||
|
||||
ASM_FOLDER = 'asm'
|
||||
INCLUDE_FOLDER = os.path.join(ASM_FOLDER, 'include')
|
||||
original_file_path = os.path.join(ASM_FOLDER, f'{symbol_location}.s')
|
||||
original_inc_path = os.path.join(INCLUDE_FOLDER, f'{symbol_location}.inc')
|
||||
with open(original_file_path, 'r') as original_file:
|
||||
original_lines = original_file.readlines()
|
||||
|
||||
SYMBOL_START = '\t.global '
|
||||
symbol_line = None
|
||||
new_symbol_address = None
|
||||
hex_regex = re.compile('_[0-9A-F]{8}$')
|
||||
for i, line in enumerate(original_lines):
|
||||
if line.startswith(f'{SYMBOL_START}{symbol_name}'):
|
||||
symbol_line = i
|
||||
|
||||
if symbol_line is not None and line.startswith(SYMBOL_START) and hex_regex.search(line) is not None:
|
||||
new_symbol_address = line[-9:-1]
|
||||
|
||||
if symbol_line is None:
|
||||
print(f'Failed to find symbol {symbol_name}.')
|
||||
exit(1)
|
||||
|
||||
new_asm_lines = original_lines[symbol_line:]
|
||||
original_asm_lines = original_lines[:symbol_line]
|
||||
|
||||
if symbol_location.startswith('main'):
|
||||
file_prefix = 'main_'
|
||||
else:
|
||||
file_prefix = symbol_location[:len('overlay_00_')]
|
||||
if file_prefix[-1] != '_':
|
||||
file_prefix += '_'
|
||||
|
||||
LSF_FILE_PATH = 'main.lsf'
|
||||
with open(LSF_FILE_PATH, 'r') as lsf_file:
|
||||
lsf_lines = lsf_file.readlines()
|
||||
|
||||
extract_file_name = f'{file_prefix}{new_symbol_address}'
|
||||
|
||||
new_asm_base_name = f"{file_prefix}{new_symbol_address}"
|
||||
|
||||
# If needed, add the extracted function's new .o file to main.lsf.
|
||||
merge_prev_file = None
|
||||
merge_next_file = None
|
||||
SRC_LSF_PREFIX = '\tObject src/'
|
||||
for i, line in enumerate(lsf_lines):
|
||||
if line.endswith(f'{symbol_location}.o\n'):
|
||||
lsf_lines[i] += f'\tObject asm/{new_asm_base_name}.o\n'
|
||||
|
||||
print('Updating', LSF_FILE_PATH)
|
||||
with open(LSF_FILE_PATH, 'w') as lsf_file:
|
||||
lsf_file.writelines(lsf_lines)
|
||||
|
||||
print('Updating', original_file_path)
|
||||
with open(original_file_path, 'w') as original_file:
|
||||
original_file.writelines(original_asm_lines)
|
||||
print('Updating', original_inc_path)
|
||||
write_inc_file(original_asm_lines, original_inc_path)
|
||||
|
||||
new_inc_file_name = f"{new_asm_base_name}.inc"
|
||||
new_asm_name = f'{new_asm_base_name}.s'
|
||||
new_asm_header = f"""\t.include "asm/macros.inc"
|
||||
\t.include "{new_inc_file_name}"
|
||||
|
||||
\t.rodata
|
||||
"""
|
||||
new_asm_file_path = os.path.join(ASM_FOLDER, new_asm_name)
|
||||
print('Creating', new_asm_file_path)
|
||||
with open(os.path.join(ASM_FOLDER, new_asm_name), 'w') as new_asm_file:
|
||||
new_asm_file.write(new_asm_header)
|
||||
new_asm_file.writelines(new_asm_lines)
|
||||
|
||||
new_asm_inc_path = os.path.join(INCLUDE_FOLDER, f'{new_asm_base_name}.inc')
|
||||
print('Creating', new_asm_inc_path)
|
||||
write_inc_file(new_asm_lines, new_asm_inc_path)
|
||||
52
tools/extract_function/write_inc_file.py
Normal file
52
tools/extract_function/write_inc_file.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from typing import List
|
||||
|
||||
ARM_FUNC_START = '\tarm_func_start '
|
||||
BRANCH_LINK_INSTRUCTION = '\tbl '
|
||||
BRANCH_LINK_EXCHANGE_INSTRUCTION = '\tblx '
|
||||
BRANCH_INSTRUCTION = '\tb '
|
||||
WORD_KEY = '.word '
|
||||
WORD_PLUS_OFFSET = ' + 0x'
|
||||
"""
|
||||
Searches through an ASM file's contents for all external symbols, then populates a .inc file with all the necessary .public definitions.
|
||||
"""
|
||||
def write_inc_file(lines: List[str], file_path: str):
|
||||
defined_functions = set()
|
||||
used_functions = set()
|
||||
for line in lines:
|
||||
if line.startswith(ARM_FUNC_START):
|
||||
defined_functions.add(line[len(ARM_FUNC_START) : -1])
|
||||
elif line.startswith(BRANCH_LINK_INSTRUCTION):
|
||||
used_functions.add(line[len(BRANCH_LINK_INSTRUCTION) : -1])
|
||||
elif line.startswith(BRANCH_INSTRUCTION):
|
||||
function = line[len(BRANCH_INSTRUCTION) : -1]
|
||||
if function[0] != '_':
|
||||
semicolon_index = function.index(' ; ')
|
||||
used_functions.add(function[:semicolon_index])
|
||||
elif line.startswith(BRANCH_LINK_EXCHANGE_INSTRUCTION):
|
||||
function = line[len(BRANCH_LINK_EXCHANGE_INSTRUCTION) : -1]
|
||||
if function not in {'fp', 'ip', 'lr', 'sb', 'sl'} and not (
|
||||
function.startswith('r') and function[1:].isdigit() # rN
|
||||
):
|
||||
used_functions.add(function)
|
||||
else:
|
||||
word_index = line.find(WORD_KEY)
|
||||
if word_index >= 0 and f'{WORD_KEY}0x' not in line:
|
||||
word_plus_offset_index = line.find(WORD_PLUS_OFFSET)
|
||||
if word_plus_offset_index >= 0:
|
||||
new_word = line[word_index + len(WORD_KEY) : word_plus_offset_index]
|
||||
else:
|
||||
new_word = line[word_index + len(WORD_KEY) : -1]
|
||||
|
||||
if new_word[0] < '0' or new_word > '9':
|
||||
used_functions.add(new_word)
|
||||
|
||||
for function in defined_functions:
|
||||
if function in used_functions:
|
||||
used_functions.remove(function)
|
||||
|
||||
write_lines = ['#pragma once\n']
|
||||
for function in sorted(used_functions):
|
||||
write_lines.append(f'.public {function}\n')
|
||||
|
||||
with open(file_path, 'w') as inc_file:
|
||||
inc_file.writelines(write_lines)
|
||||
Reference in New Issue
Block a user