mirror of
https://github.com/SwareJonge/mkdd.git
synced 2025-02-26 08:06:02 +00:00
make building partly possible
This commit is contained in:
parent
a48ca9d654
commit
6b626613a3
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,5 +1,10 @@
|
||||
*.o
|
||||
*.s
|
||||
*.dol
|
||||
*.elf
|
||||
*.exe
|
||||
*.MAP
|
||||
*.MAP
|
||||
*.ninja
|
||||
.ninja_log
|
||||
/deps/
|
||||
/include
|
168
build.py
Normal file
168
build.py
Normal file
@ -0,0 +1,168 @@
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import pathlib
|
||||
import shutil
|
||||
|
||||
def deleteDFiles():
|
||||
dirs = os.listdir(os.getcwd())
|
||||
|
||||
for dire in dirs:
|
||||
if dire.endswith(".d"):
|
||||
os.remove(os.path.join(os.getcwd(), dire))
|
||||
|
||||
def main(compile_non_matching, use_ninja, clean_ninja):
|
||||
if not os.path.exists("deps"):
|
||||
print("deps folder not created, please run setup.py!")
|
||||
sys.exit(1)
|
||||
|
||||
isNotWindows = os.name != "nt"
|
||||
|
||||
flags = "-c -Cpp_exceptions off -proc gekko -fp_contract on -fp fmadd -fp hard -lang=c++ -use_lmw_stmw on -inline on -O4 -sdata 4 -sdata2 4 -align powerpc -enum int -DRVL_SDK -DEPPC -DHOLLYWOOD_REV -DTRK_INTEGRATION -DGEKKO -DMTX_USE_PS -D_MSL_USING_MW_C_HEADERS -msgstyle gcc "
|
||||
includes = "-i . -I- -i include "
|
||||
|
||||
default_compiler_path = pathlib.Path("GC/2.5/")
|
||||
|
||||
compiler_exceptions = {
|
||||
#"source\JSystem\JKernel\JKRThread.cpp": "GC/2.5/"
|
||||
}
|
||||
|
||||
compiler_flags = {
|
||||
#"GC/2.5", flags
|
||||
}
|
||||
|
||||
if compile_non_matching:
|
||||
print("Using nonmatching functions")
|
||||
flags = flags + " -DNON_MATCHING "
|
||||
|
||||
trk_path = pathlib.Path("deps/EABI/PowerPC_EABI_Support/MetroTRK")
|
||||
runtime_path = pathlib.Path("deps/EABI/PowerPC_EABI_Support/Runtime/Inc")
|
||||
runtimesrc_path = pathlib.Path("deps/EABI/PowerPC_EABI_Support/Runtime/Src")
|
||||
msl_c_path = pathlib.Path("deps/EABI/PowerPC_EABI_Support/MSL/MSL_C/PPC_EABI/Include")
|
||||
msl_cpp_path = pathlib.Path("deps/EABI/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include")
|
||||
msl_c_common_path = pathlib.Path("deps/EABI/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include")
|
||||
|
||||
|
||||
includes += f"-I- -i {trk_path} -I- -i {runtime_path} -I- -i {runtimesrc_path} -I- -i {msl_c_path} -I- -i {msl_cpp_path} -I- -i {msl_c_common_path} "
|
||||
flags += includes
|
||||
|
||||
tasks = list()
|
||||
|
||||
ninjaFound = shutil.which("ninja") is not None
|
||||
if not ninjaFound and use_ninja:
|
||||
print("Ninja was not found in your PATH. Compilation will be slow!")
|
||||
useNinja = ninjaFound and use_ninja
|
||||
if not useNinja:
|
||||
if os.path.exists("build"):
|
||||
shutil.rmtree("build", ignore_errors=True)
|
||||
|
||||
for root, dirs, files in os.walk("src"):
|
||||
for file in files:
|
||||
if file.endswith(".cpp"):
|
||||
source_path = os.path.join(root, file)
|
||||
build_path = source_path.replace("src", "build", 1).replace(".cpp", ".o")
|
||||
|
||||
os.makedirs(os.path.dirname(build_path), exist_ok=True)
|
||||
|
||||
tasks.append((source_path, build_path))
|
||||
elif file.endswith(".c"):
|
||||
source_path = os.path.join(root, file)
|
||||
build_path = source_path.replace("src", "build", 1).replace(".c", ".o")
|
||||
|
||||
os.makedirs(os.path.dirname(build_path), exist_ok=True)
|
||||
|
||||
tasks.append((source_path, build_path))
|
||||
|
||||
compiler_path = pathlib.Path(f"deps/Compilers/{default_compiler_path}/mwcceppc.exe ")
|
||||
if isNotWindows:
|
||||
compiler_path = pathlib.Path(f"wine {compiler_path} ")
|
||||
|
||||
if useNinja:
|
||||
# Use ninja build system to generate a build script.
|
||||
from ninja import ninja_syntax
|
||||
bo = open("build.ninja", "w")
|
||||
nw = ninja_syntax.Writer(bo)
|
||||
|
||||
# Create main compiler rule and exception compilers.
|
||||
nw.rule("cc", f"{compiler_path} $flags $in -o $out", "Compiling $in...")
|
||||
exceptionsToRules = { "sample": "value" }
|
||||
cc_num = 1
|
||||
for exc in compiler_exceptions.values():
|
||||
if not exc in exceptionsToRules.keys():
|
||||
exceptionsToRules[exc] = f"cc_{cc_num}"
|
||||
cc_num += 1
|
||||
|
||||
nw.newline()
|
||||
for task in tasks:
|
||||
source_path, build_path = task
|
||||
rule = "cc"
|
||||
try:
|
||||
if compiler_exceptions[source_path]:
|
||||
rule = exceptionsToRules[compiler_exceptions[source_path]]
|
||||
except:
|
||||
pass
|
||||
nw.build(build_path, rule, source_path, variables={ 'flags': flags })
|
||||
nw.close()
|
||||
|
||||
# Run clean
|
||||
if clean_ninja:
|
||||
subprocess.call("ninja -t clean", shell=True)
|
||||
|
||||
# Call ninja to run said build script.
|
||||
if subprocess.call("ninja", shell=True) == 1:
|
||||
deleteDFiles()
|
||||
sys.exit(1)
|
||||
|
||||
else:
|
||||
|
||||
for task in tasks:
|
||||
source_path, build_path = task
|
||||
|
||||
try:
|
||||
if compiler_exceptions[source_path]:
|
||||
compiler_path = pathlib.Path(f"deps/Compilers/{compiler_exceptions[source_path]}/mwcceppc.exe ")
|
||||
if isNotWindows:
|
||||
compiler_path = pathlib.Path(f"wine {compiler_path} ")
|
||||
except:
|
||||
pass
|
||||
|
||||
print(f"Compiling {source_path}...")
|
||||
if subprocess.call(f"{compiler_path} {flags} {source_path} -o {build_path}", shell=True) == 1:
|
||||
deleteDFiles()
|
||||
sys.exit(1)
|
||||
|
||||
deleteDFiles()
|
||||
|
||||
print("Complete.")
|
||||
|
||||
def print_help_and_exit():
|
||||
print("Usage: build.py [flags...]")
|
||||
print("\t-non-matching: Compile non-matching code.")
|
||||
print("\t-no-ninja: Do not use ninja even if available.")
|
||||
print("\t-clean: Clean old build files before building new when using ninja.")
|
||||
print("\t-help: Displays this help text")
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
compile_non_matching = False
|
||||
use_ninja = True
|
||||
clean_ninja = False
|
||||
|
||||
for arg in sys.argv[1:]:
|
||||
if arg == "-non-matching":
|
||||
compile_non_matching = True
|
||||
elif arg == "-no-ninja":
|
||||
use_ninja = False
|
||||
elif arg == "-clean":
|
||||
clean_ninja = True
|
||||
elif arg == "-help":
|
||||
print_help_and_exit()
|
||||
else:
|
||||
print(f"Invalid argument: {arg}")
|
||||
print()
|
||||
print_help_and_exit()
|
||||
|
||||
main(compile_non_matching, use_ninja, clean_ninja)
|
559
check.py
Normal file
559
check.py
Normal file
@ -0,0 +1,559 @@
|
||||
# check.py
|
||||
# script that marks functions as decompiled based on matching status
|
||||
|
||||
import os
|
||||
from typing import overload
|
||||
from elftools.elf.elffile import ELFFile
|
||||
from colorama import Fore, Style
|
||||
import glob
|
||||
import hashlib
|
||||
import sys
|
||||
import struct
|
||||
from capstone import *
|
||||
from capstone.ppc import *
|
||||
import pathlib
|
||||
from collections import OrderedDict
|
||||
|
||||
class FunctionLibrary:
|
||||
def __init__(self):
|
||||
self.libraries = dict()
|
||||
self.functions = dict()
|
||||
|
||||
def load(self):
|
||||
self.libraries.clear()
|
||||
self.functions.clear()
|
||||
|
||||
# Load CSV files
|
||||
for file in os.listdir("csv"):
|
||||
library = file[0:file.rfind(".")]
|
||||
symbols = OrderedDict()
|
||||
|
||||
with open(pathlib.Path(f"csv/{file}"), "r") as input:
|
||||
is_first_line = True
|
||||
for line in input:
|
||||
if is_first_line:
|
||||
is_first_line = False
|
||||
continue
|
||||
|
||||
line_split = line.rstrip().split(",")
|
||||
|
||||
symbol = line_split[0]
|
||||
obj_file = line_split[1]
|
||||
library_name = line_split[2]
|
||||
matches = line_split[3] == "true"
|
||||
|
||||
if (symbol, obj_file) in symbols:
|
||||
print(f"Duplicate symbol {symbol} in .o file {obj_file}.")
|
||||
sys.exit(1)
|
||||
|
||||
symbols[(symbol, obj_file)] = (library_name, matches)
|
||||
|
||||
self.libraries[library] = symbols
|
||||
|
||||
# Load addresses from symbol map
|
||||
with open("data/map_for_dol.map", "r") as input:
|
||||
for line in input:
|
||||
line_split = line.rstrip().split("=")
|
||||
|
||||
symbol = line_split[1].split(":")[0]
|
||||
|
||||
number_split = line_split[0].split(" ")
|
||||
address = int(number_split[4], 16)
|
||||
size = int(number_split[3], 16)
|
||||
|
||||
self.functions[symbol] = (address, size)
|
||||
|
||||
def save(self):
|
||||
for library, symbols in self.libraries.items():
|
||||
with open(f"csv/{library}.csv", "w") as output:
|
||||
output.write("Symbol Name, Object File, Library Archive, Matching\n")
|
||||
|
||||
for (symbol, obj_file), values in symbols.items():
|
||||
output.write(f"{symbol},{obj_file},{values[0]},{str(values[1]).lower()}\n")
|
||||
|
||||
def get_obj_names_from_symbol(self, symbol_lookup):
|
||||
names = []
|
||||
|
||||
for symbols in self.libraries.values():
|
||||
for (symbol, obj_name) in symbols.keys():
|
||||
if symbol == symbol_lookup:
|
||||
names.append(obj_name)
|
||||
|
||||
return names
|
||||
|
||||
def is_marked_decompiled(self, library_name, symbol, obj_file):
|
||||
if library_name in self.libraries:
|
||||
library = self.libraries[library_name]
|
||||
|
||||
if (symbol, obj_file) in library:
|
||||
return library[(symbol, obj_file)][1]
|
||||
|
||||
return False
|
||||
|
||||
def mark_symbol_decompiled(self, library_name, symbol, obj_file, decompiled):
|
||||
if library_name in self.libraries:
|
||||
library = self.libraries[library_name]
|
||||
|
||||
if (symbol, obj_file) in library:
|
||||
library[(symbol, obj_file)] = (library[(symbol, obj_file)][0], decompiled)
|
||||
|
||||
def get_library_from_symbol(self, symbol, obj_file):
|
||||
for library, symbols in self.libraries.items():
|
||||
if (symbol, obj_file) in symbols:
|
||||
return library
|
||||
|
||||
return None
|
||||
|
||||
def get_address_from_symbol(self, symbol):
|
||||
if symbol in self.functions:
|
||||
return self.functions[symbol][0]
|
||||
|
||||
return None
|
||||
|
||||
def get_size_from_symbol(self, symbol):
|
||||
if symbol in self.functions:
|
||||
return self.functions[symbol][1]
|
||||
|
||||
return None
|
||||
|
||||
def get_symbols_marked_as_decompiled(self):
|
||||
for symbols in self.libraries.values():
|
||||
for (symbol, obj_file), values in symbols.items():
|
||||
if values[1] == True:
|
||||
yield (symbol, obj_file)
|
||||
|
||||
def print_help_and_exit():
|
||||
print("Usage: check.py [mangled_symbol] [flags...]")
|
||||
print("\t[mangled_symbol]: name of the symbol that should be checked.")
|
||||
print("\t[-all]: run checks on all functions which has been marked as decompiled.")
|
||||
print("\t[-compare]: compares decompiled functions.")
|
||||
print("\t[-help]: displays this help text.")
|
||||
print("\t[-only-errors]: displays only error messages.")
|
||||
print("\t[-no-hints]: don't display hint messages.")
|
||||
print("\t[-no-warnings]: don't display warning messages.")
|
||||
print("\t[-no-errors]: don't display error messages.")
|
||||
print("\t[-readonly]: don't mark or unmark any functions as decompiled.")
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
def is_dol_correct():
|
||||
with open("baserom.dol", "rb") as input:
|
||||
data = input.read()
|
||||
|
||||
hash = hashlib.sha256(data).hexdigest().upper()
|
||||
return hash == "8B7F28D193170F998F92E02EA638107822FB72073691D0893EB18857BE0C6FCF" or hash == "69F93FCC0FA34837347B5AC05168BC783ADCACB3C02697CFDA087A3B63ABC9E0"
|
||||
|
||||
def get_code_from_dol(address, size):
|
||||
with open("baserom.dol", "rb") as input:
|
||||
data = input.read()
|
||||
|
||||
# Grab .text offset and start offset
|
||||
txt_offset, = struct.unpack_from(">I", data, 4)
|
||||
start_address, = struct.unpack_from(">I", data, 0x4C)
|
||||
|
||||
offset = address - start_address
|
||||
|
||||
return data[txt_offset + offset:txt_offset + offset + size]
|
||||
|
||||
def print_error(message):
|
||||
global show_errors
|
||||
|
||||
if show_errors:
|
||||
print(f"ERROR: {message}")
|
||||
|
||||
def print_warning(message):
|
||||
global show_warnings
|
||||
|
||||
if show_warnings:
|
||||
print(f"WARNING: {message}")
|
||||
|
||||
def print_hint(message):
|
||||
global show_hints
|
||||
|
||||
if show_hints:
|
||||
print(f"HINT: {message}")
|
||||
|
||||
def print_instruction_comparison_error(message, original, custom):
|
||||
global show_errors
|
||||
|
||||
if show_errors:
|
||||
print_error(message)
|
||||
print_instruction_comparison(original, custom)
|
||||
|
||||
def print_instruction_comparison_warning(message, original, custom):
|
||||
global show_warnings
|
||||
|
||||
if show_warnings:
|
||||
print_warning(message)
|
||||
print_instruction_comparison(original, custom)
|
||||
|
||||
def print_instruction_comparison_hint(message, original, custom):
|
||||
global show_hints
|
||||
|
||||
if show_hints:
|
||||
print_hint(message)
|
||||
print_instruction_comparison(original, custom)
|
||||
|
||||
def print_instruction_comparison(original, custom):
|
||||
print(f"\tOriginal: {original}")
|
||||
print(f"\tCustom: {custom}")
|
||||
|
||||
def check_symbol(function_library, mangled_symbol, obj_name, readonly):
|
||||
black_listed_instructions = {
|
||||
PPC_INS_VMSUMSHM, PPC_INS_VMHADDSHS, PPC_INS_XXSLDWI, PPC_INS_VSEL,
|
||||
PPC_INS_XVSUBSP, PPC_INS_XXSEL, PPC_INS_XVMULSP, PPC_INS_XVDIVSP,
|
||||
PPC_INS_VADDUHM, PPC_INS_XXPERMDI, PPC_INS_XVMADDASP, PPC_INS_XVMADDMSP,
|
||||
PPC_INS_XVCMPGTSP, PPC_INS_XXMRGHD, PPC_INS_XSMSUBMDP, PPC_INS_XSTDIVDP,
|
||||
PPC_INS_XVADDSP, PPC_INS_XVCMPEQSP, PPC_INS_XVMSUBASP, PPC_INS_XVCMPGESP,
|
||||
PPC_INS_MFESR, PPC_INS_MFDEAR, PPC_INS_MTESR, PPC_INS_MTDEAR, PPC_INS_MFICCR, PPC_INS_MFASR
|
||||
}
|
||||
|
||||
unsupported_libraries = { "TRK_Hollywood_Revolution" }
|
||||
|
||||
library = function_library.get_library_from_symbol(mangled_symbol, obj_name)
|
||||
|
||||
if library == None:
|
||||
print("Could not find library of symbol.")
|
||||
return False
|
||||
|
||||
if library in unsupported_libraries:
|
||||
print(f"Library {library} is currently not supported.")
|
||||
return False
|
||||
|
||||
obj_files = glob.glob(f"build/*/{library}/{obj_name}", recursive=True)
|
||||
|
||||
if len(obj_files) > 1:
|
||||
print("Found multiple .o files. This should not happen.")
|
||||
return False
|
||||
|
||||
if len(obj_files) == 0:
|
||||
print("Could not find any .o files for the function.")
|
||||
return False
|
||||
|
||||
with open(pathlib.Path(obj_files[0]), "rb") as input:
|
||||
elf_file = ELFFile(input)
|
||||
symtab = elf_file.get_section_by_name('.symtab')
|
||||
|
||||
if symtab.get_symbol_by_name(mangled_symbol) is None:
|
||||
print("Could not find symbol in object file. This may be caused by the code not being compiled, the function being in the wrong C++ source file or the function signature being wrong.")
|
||||
return False
|
||||
|
||||
compiled_symbol = symtab.get_symbol_by_name(mangled_symbol)[0]
|
||||
|
||||
# Get custom code
|
||||
custom_offset = compiled_symbol["st_value"]
|
||||
custom_size = compiled_symbol['st_size']
|
||||
|
||||
text = elf_file.get_section_by_name('.text')
|
||||
custom_data = text.data()[custom_offset:custom_offset + custom_size]
|
||||
|
||||
# Get original code
|
||||
original_address = function_library.get_address_from_symbol(mangled_symbol)
|
||||
original_size = function_library.get_size_from_symbol(mangled_symbol)
|
||||
|
||||
if original_address == None or original_size == None:
|
||||
print("Could not find address and/or size for symbol")
|
||||
return False
|
||||
|
||||
original_data = get_code_from_dol(original_address, original_size)
|
||||
|
||||
if original_data == None:
|
||||
print("Could not get data from DOL file.")
|
||||
return False
|
||||
|
||||
cs = Cs(CS_ARCH_PPC, CS_MODE_32 | CS_MODE_BIG_ENDIAN)
|
||||
cs.detail = True
|
||||
cs.imm_unsigned = False
|
||||
|
||||
original_instructions = list(cs.disasm(original_data, 0))
|
||||
custom_instructions = list(cs.disasm(custom_data, 0))
|
||||
|
||||
error_count = 0
|
||||
warning_count = 0
|
||||
hint_count = 0
|
||||
|
||||
# Capstone doesn't seem to handle paired single instructions
|
||||
# If any is found, it just stops disassembling
|
||||
if 4 * len(original_instructions) != original_size:
|
||||
print_warning(f"Only {len(original_instructions)} out of the {original_size // 4} original instructions were loaded.")
|
||||
warning_count += 1
|
||||
|
||||
if 4 * len(custom_instructions) != custom_size:
|
||||
print_warning(f"Only {len(custom_instructions)} out of the {custom_size // 4} custom instructions were loaded.")
|
||||
warning_count += 1
|
||||
|
||||
if original_size > custom_size:
|
||||
print_error("Original code contains more instructions than custom code.")
|
||||
error_count += 1
|
||||
elif original_size < custom_size:
|
||||
print_error("Original code contains less instructions than custom code.")
|
||||
error_count += 1
|
||||
|
||||
for i in range(min(len(original_instructions), len(custom_instructions))):
|
||||
line = i * 4
|
||||
line_string = f"{hex(line)} (Original: {hex(original_address + line)})"
|
||||
|
||||
original_instruction = original_instructions[i]
|
||||
custom_instruction = custom_instructions[i]
|
||||
|
||||
original_operands = original_instruction.operands
|
||||
custom_operands = custom_instruction.operands
|
||||
|
||||
if str(original_instruction) == str(custom_instruction):
|
||||
print(f"{Fore.GREEN}{str(original_instruction):<80}{custom_instruction}{Style.RESET_ALL}")
|
||||
# Fully identical, nothing to be checked
|
||||
continue
|
||||
|
||||
if original_instruction in black_listed_instructions:
|
||||
print_warning(f"Skipping blacklisted instruction at line {line_string}.")
|
||||
warning_count += 1
|
||||
continue
|
||||
|
||||
if original_instruction.id == custom_instruction.id:
|
||||
assert(len(original_operands) == len(custom_operands))
|
||||
|
||||
# First check common r2 and r13 issues
|
||||
if original_instruction.id in { PPC_INS_LBZ, PPC_INS_LWZ, PPC_INS_STW, PPC_INS_LFS }:
|
||||
assert(len(original_operands) == 2 and len(custom_operands) == 2)
|
||||
|
||||
# lbz, lwz, stw and lfs are sometimes used with r13, which is a pointer to a read-write
|
||||
# small data area (SDA). When compiling custom code, this SDA is not generated,
|
||||
# so the register is set to r0 and the displacement is set to 0.
|
||||
|
||||
# Original must be (instr) rX, X(r13) and custom must be (instr) rX, 0(r0)
|
||||
if original_operands[1].reg == PPC_REG_R13 and custom_operands[1].reg == PPC_REG_R0 and\
|
||||
custom_operands[1].mem.disp == 0 and original_operands[0].reg == custom_operands[0].reg:
|
||||
print(f"{Fore.YELLOW}{str(original_instruction):<80}{custom_instruction}{Style.RESET_ALL}")
|
||||
#print_instruction_comparison_hint(f"Skipping r13 issue at line {line_string}.", original_instruction, custom_instruction)
|
||||
hint_count += 1
|
||||
continue
|
||||
|
||||
if original_instruction.id in { PPC_INS_LWZ, PPC_INS_LFS, PPC_INS_LHZ, PPC_INS_LFS }:
|
||||
assert(len(original_operands) == 2 and len(custom_operands) == 2)
|
||||
|
||||
# Same as above, except with r2 instead of r13. r2 is a pointer to a read-only SDA.
|
||||
|
||||
# Original must be (instr) rX, X(r2) and custom must be (instr) rX, 0(0)
|
||||
if original_operands[1].reg == PPC_REG_R2 and custom_operands[1].reg == PPC_REG_R0 and\
|
||||
custom_operands[1].mem.disp == 0 and original_operands[0].reg == custom_operands[0].reg:
|
||||
print(f"{Fore.YELLOW}{str(original_instruction):<80}{custom_instruction}{Style.RESET_ALL}")
|
||||
#print_instruction_comparison_hint(f"Skipping r2 issue at line {line_string}.", original_instruction, custom_instruction)
|
||||
hint_count += 1
|
||||
continue
|
||||
|
||||
# Check if all registers are equal
|
||||
registers_equal = True
|
||||
|
||||
for j in range(len(original_operands)):
|
||||
if original_operands[j].reg != custom_operands[j].reg:
|
||||
registers_equal = False
|
||||
break
|
||||
|
||||
if registers_equal:
|
||||
print(f"{Fore.YELLOW}{str(original_instruction):<80}{custom_instruction}{Style.RESET_ALL}")
|
||||
#print_instruction_comparison_warning(f"Registers are identical but the instruction is not identical at line {line_string}.", original_instruction, custom_instruction)
|
||||
warning_count += 1
|
||||
elif original_instruction.id == PPC_INS_ADDI:
|
||||
# addi is commonly used when loading addresses
|
||||
print(f"{Fore.YELLOW}{str(original_instruction):<80}{custom_instruction}{Style.RESET_ALL}")
|
||||
#print_instruction_comparison_warning(f"Skipping addi instruction at line {line_string}.", original_instruction, custom_instruction)
|
||||
warning_count += 1
|
||||
elif original_instruction.id == PPC_INS_LIS:
|
||||
# Same as addi
|
||||
print(f"{Fore.YELLOW}{str(original_instruction):<80}{custom_instruction}{Style.RESET_ALL}")
|
||||
#print_instruction_comparison_warning(f"Skipping lis instruction at line {line_string}.", original_instruction, custom_instruction)
|
||||
warning_count += 1
|
||||
elif original_instruction.id in { PPC_INS_B, PPC_INS_BL }:
|
||||
# bl is used to call most functions, and since the functions are likely to be placed
|
||||
# differently it's not possible to compare it
|
||||
# If a function ends with a function call, and the returned value from the function, then b is sometimes used for branching
|
||||
# to that function. Then it's not possible to compare this
|
||||
print(f"{Fore.YELLOW}{str(original_instruction):<80}{custom_instruction}{Style.RESET_ALL}")
|
||||
#print_instruction_comparison_warning(f"Skipping branch instruction at line {line_string}.", original_instruction, custom_instruction)
|
||||
warning_count += 1
|
||||
else:
|
||||
print(f"{Fore.RED}{str(original_instruction):<80}{custom_instruction}{Style.RESET_ALL}")
|
||||
#print_instruction_comparison_error(f"Instruction mismatch on line {line_string}.", original_instruction, custom_instruction)
|
||||
error_count += 1
|
||||
elif original_instruction.id == PPC_INS_ADDI and custom_instruction.id == PPC_INS_LI:
|
||||
assert(len(original_operands) == 3 and len(custom_operands) == 2)
|
||||
|
||||
# This is caused by the read-write SDA, pointed by r13, is not generated in the custom code.
|
||||
|
||||
# Original must be addi rX, r13, X and custom must be li rX, 0
|
||||
if original_operands[1].reg == PPC_REG_R13 and custom_operands[1].imm == 0 and\
|
||||
original_operands[0].reg == custom_operands[0].reg:
|
||||
print(f"{Fore.YELLOW}{str(original_instruction):<80}{custom_instruction}{Style.RESET_ALL}")
|
||||
#print_instruction_comparison_hint(f"Found addi / li mismatch at line {line_string}.", original_instruction, custom_instruction)
|
||||
hint_count += 1
|
||||
else:
|
||||
print(f"{Fore.RED}{str(original_instruction):<80}{custom_instruction}{Style.RESET_ALL}")
|
||||
#print_instruction_comparison_error(f"Instruction mismatch on line {line_string}.", original_instruction, custom_instruction)
|
||||
error_count += 1
|
||||
else:
|
||||
print(f"{Fore.RED}{str(original_instruction):<80}{custom_instruction}{Style.RESET_ALL}")
|
||||
#print_instruction_comparison_error(f"Instruction mismatch on line {line_string}.", original_instruction, custom_instruction)
|
||||
error_count += 1
|
||||
|
||||
print()
|
||||
print(f"Check finished with {error_count} error(s), {warning_count} warning(s) and {hint_count} hint(s).")
|
||||
|
||||
is_decompiled = function_library.is_marked_decompiled(library, mangled_symbol, obj_name)
|
||||
passed = error_count == 0
|
||||
|
||||
if not readonly:
|
||||
if passed:
|
||||
if is_decompiled:
|
||||
print("Function already marked as decompiled.")
|
||||
else:
|
||||
print("Marking as decompiled...")
|
||||
function_library.mark_symbol_decompiled(library, mangled_symbol, obj_name, True)
|
||||
else:
|
||||
if is_decompiled:
|
||||
print("Function is marked as decompiled, but does not match.")
|
||||
print("Unmarking as decompiled...")
|
||||
function_library.mark_symbol_decompiled(library, mangled_symbol, obj_name, False)
|
||||
else:
|
||||
print("Function is not marked as decompiled, and does not match either.")
|
||||
|
||||
return passed
|
||||
|
||||
mangled_symbol = None
|
||||
check_all = False
|
||||
compare = False
|
||||
show_hints = True
|
||||
show_warnings = True
|
||||
show_errors = True
|
||||
readonly = False
|
||||
|
||||
for i in range(1, len(sys.argv)):
|
||||
arg = sys.argv[i]
|
||||
|
||||
if arg == "-all":
|
||||
check_all = True
|
||||
elif arg == "-compare":
|
||||
compare = True
|
||||
elif arg == "-help":
|
||||
print_help_and_exit()
|
||||
elif arg == "-only-errors":
|
||||
show_hints = False
|
||||
show_warnings = False
|
||||
show_errors = True
|
||||
elif arg == "-no-hints":
|
||||
show_hints = False
|
||||
elif arg == "-no-warnings":
|
||||
show_warnings = False
|
||||
elif arg == "-no-errors":
|
||||
show_errors = False
|
||||
elif arg == "-readonly":
|
||||
readonly = True
|
||||
elif mangled_symbol == None:
|
||||
mangled_symbol = arg
|
||||
else:
|
||||
print(f"Invalid argument: {arg}")
|
||||
print()
|
||||
print_help_and_exit()
|
||||
|
||||
if mangled_symbol == None and not check_all and not compare:
|
||||
print_help_and_exit()
|
||||
|
||||
if not is_dol_correct():
|
||||
print("DOL file is not valid.")
|
||||
sys.exit(1)
|
||||
|
||||
function_library = FunctionLibrary()
|
||||
function_library.load()
|
||||
|
||||
if check_all:
|
||||
success_count = 0
|
||||
total_count = 0
|
||||
|
||||
for (symbol, obj_name) in function_library.get_symbols_marked_as_decompiled():
|
||||
print(f"Checking {symbol}...")
|
||||
total_count += 1
|
||||
|
||||
if check_symbol(function_library, symbol, obj_name, True):
|
||||
success_count += 1
|
||||
|
||||
print()
|
||||
|
||||
print(f"{success_count} function(s) out of the {total_count} function(s), which were marked as decompiled, passed the check.")
|
||||
print(f"{total_count - success_count} function(s) failed the check.")
|
||||
|
||||
if compare:
|
||||
success_count_a = 0
|
||||
fail_count_a = 0
|
||||
matched_a = set()
|
||||
failed_a = set()
|
||||
|
||||
for (symbol, obj_name) in function_library.get_symbols_marked_as_decompiled():
|
||||
print(f"Checking {symbol}...")
|
||||
|
||||
if check_symbol(function_library, symbol, obj_name, True):
|
||||
success_count_a += 1
|
||||
matched_a.add((symbol, obj_name))
|
||||
else:
|
||||
fail_count_a += 1
|
||||
failed_a.add((symbol, obj_name))
|
||||
|
||||
print()
|
||||
|
||||
print()
|
||||
print()
|
||||
print("First run of tests are now done.")
|
||||
print("Now, please make the code changes you wish to test, and then recompile everything.")
|
||||
input("Press Enter to contiue...")
|
||||
|
||||
success_count_b = 0
|
||||
fail_count_b = 0
|
||||
matched_b = set()
|
||||
failed_b = set()
|
||||
|
||||
for (symbol, obj_name) in function_library.get_symbols_marked_as_decompiled():
|
||||
print(f"Checking {symbol}...")
|
||||
|
||||
if check_symbol(function_library, symbol, obj_name, True):
|
||||
success_count_b += 1
|
||||
matched_b.add((symbol, obj_name))
|
||||
else:
|
||||
fail_count_b += 1
|
||||
failed_b.add((symbol, obj_name))
|
||||
|
||||
print()
|
||||
|
||||
print()
|
||||
print()
|
||||
print("Second run of tests are now done.")
|
||||
print()
|
||||
|
||||
print(f"First run: {success_count_a} matched and {fail_count_a} failed.")
|
||||
print(f"Second run: {success_count_b} matched and {fail_count_b} failed.")
|
||||
print()
|
||||
|
||||
print("The following functions matched during the first run and failed during the second test:")
|
||||
|
||||
for matched in matched_a:
|
||||
if matched in failed_b:
|
||||
print(f"{matched[0]} in {matched[1]}")
|
||||
|
||||
print()
|
||||
print("The following functions failed during the first run and matched during the second test:")
|
||||
|
||||
for failed in failed_a:
|
||||
if failed in matched_b:
|
||||
print(f"{failed[0]} in {failed[1]}")
|
||||
|
||||
|
||||
if mangled_symbol != None:
|
||||
obj_names = function_library.get_obj_names_from_symbol(mangled_symbol)
|
||||
|
||||
if len(obj_names) == 0:
|
||||
print("Could not find any .o files for the specified symbol.")
|
||||
sys.exit(1)
|
||||
elif len(obj_names) > 1:
|
||||
print("There are multiple .o files found for the specified symbol. This is currently not supported by the script.")
|
||||
sys.exit(1)
|
||||
|
||||
check_symbol(function_library, mangled_symbol, obj_names[0], readonly)
|
||||
|
||||
function_library.save()
|
@ -1,8 +0,0 @@
|
||||
#ifndef OSTIME_H
|
||||
#define OSTIME_H
|
||||
|
||||
#include <types>
|
||||
|
||||
u64 OSGetTime();
|
||||
|
||||
#endif // !OSTIME_H
|
@ -1,6 +1,8 @@
|
||||
#ifndef JGEOMETRY_H
|
||||
#define JGEOMETRY_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
// from SMS decomp
|
||||
namespace JGeometry {
|
||||
template <typename T> class TVec3 {
|
||||
@ -21,7 +23,7 @@ namespace JGeometry {
|
||||
void scale(f32 scale);
|
||||
void scale(f32 scale, const TVec3& operand);
|
||||
void scaleAdd(f32 scale, const TVec3& operand, const TVec3& translate);
|
||||
void set(const Vec&);
|
||||
//void set(const Vec&);
|
||||
|
||||
template <typename TY> void set(TY x, TY y, TY z);
|
||||
template <typename TY> void set(const TVec3<TY>&);
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef JKRDISPOSER_H
|
||||
#define JKRDISPOSER_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include "JSystem/JSupport/JSUList.h"
|
||||
|
||||
class JKRHeap;
|
||||
|
@ -1,8 +1,8 @@
|
||||
#ifndef JKRHEAP_H
|
||||
#define JKRHEAP_H
|
||||
|
||||
#include <JSystem/JKernel/JKRDisposer.h>
|
||||
#include <JSystem/JSupport/JSUList.h>
|
||||
#include "types.h"
|
||||
#include "JSystem/JKernel/JKRDisposer.h"
|
||||
|
||||
class JKRHeap : public JKRDisposer {
|
||||
public:
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef JMATRIGONOMETRIC_H
|
||||
#define JMATRIGONOMETRIC_H
|
||||
|
||||
#include <types.h>
|
||||
#include "types.h"
|
||||
#include <utility> // std::pair
|
||||
|
||||
// from TP decomp
|
||||
|
@ -1,15 +1,20 @@
|
||||
#ifndef JMATH_H
|
||||
#define JMATH_H
|
||||
|
||||
#include <types.h>
|
||||
#include "JMATrigonometric.h"
|
||||
#include "types.h"
|
||||
#include "JSystem/JMath/JMATrigonometric.h"
|
||||
|
||||
namespace JMath {
|
||||
TSinCosTable sincosTable_;
|
||||
|
||||
class TRandom_fast_
|
||||
{
|
||||
public:
|
||||
TRandom_fast_(u32 num);
|
||||
inline u32 get();
|
||||
inline TRandom_fast_(u32 num);
|
||||
u32 get() {
|
||||
seed = (seed * 0x19660d) + 0x3c6ef35f;
|
||||
return seed;
|
||||
}
|
||||
|
||||
// from TP decomp
|
||||
float get_ufloat_1() {
|
||||
@ -23,7 +28,9 @@ namespace JMath {
|
||||
return out.f - 1;
|
||||
}
|
||||
|
||||
inline setSeed(u32 Seed);
|
||||
void setSeed(u32 Seed) {
|
||||
seed = Seed;
|
||||
}
|
||||
|
||||
private:
|
||||
u32 seed;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef JSULIST_H
|
||||
#define JSULIST_H
|
||||
|
||||
#include <types.h>
|
||||
#include "types.h"
|
||||
|
||||
class JSUPtrLink;
|
||||
|
||||
@ -11,47 +11,52 @@ public:
|
||||
initiate();
|
||||
}
|
||||
|
||||
JSUPtrList(bool hasBeenInit);
|
||||
JSUPtrList(bool);
|
||||
~JSUPtrList();
|
||||
|
||||
void initiate();
|
||||
void setFirst(JSUPtrLink *pNode);
|
||||
void append(JSUPtrLink *pNode);
|
||||
void prepend(JSUPtrLink *pNode);
|
||||
void insert(JSUPtrLink *, JSUPtrLink *);
|
||||
void remove(JSUPtrLink *pNode);
|
||||
void setFirst(JSUPtrLink *);
|
||||
bool append(JSUPtrLink *);
|
||||
bool prepend(JSUPtrLink *);
|
||||
bool insert(JSUPtrLink *, JSUPtrLink *);
|
||||
bool remove(JSUPtrLink *);
|
||||
|
||||
JSUPtrLink* mHead; // _0
|
||||
JSUPtrLink* mTail; // _4
|
||||
u32 mNodeCount; // _8
|
||||
JSUPtrLink *mHead; // _0
|
||||
JSUPtrLink *mTail; // _4
|
||||
u32 mNodeCount; // _8
|
||||
};
|
||||
|
||||
class JSUPtrLink {
|
||||
public:
|
||||
JSUPtrLink(void *pData);
|
||||
JSUPtrLink(void *);
|
||||
~JSUPtrLink();
|
||||
|
||||
void *mData; // _0
|
||||
JSUPtrList* mPtrList; // _4
|
||||
JSUPtrLink* mPrev; // _8
|
||||
JSUPtrLink* mNext; // _C
|
||||
void *mData; // _0
|
||||
JSUPtrList *mPtrList; // _4
|
||||
JSUPtrLink *mPrev; // _8
|
||||
JSUPtrLink *mNext; // _C
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<class T>
|
||||
class JSULink : public JSUPtrLink {
|
||||
public:
|
||||
JSULink(void *pData) : JSUPtrLink(pData) { }
|
||||
JSULink(void *pData) : JSUPtrLink(pData) {
|
||||
|
||||
}
|
||||
|
||||
~JSULink();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<class T>
|
||||
class JSUList : public JSUPtrList {
|
||||
public:
|
||||
JSUList() : JSUPtrList() { }
|
||||
JSUList(bool hasBeenInit) : JSUPtrList(hasBeenInit) { }
|
||||
JSUList() : JSUPtrList() {
|
||||
|
||||
~JSUList();
|
||||
}
|
||||
|
||||
JSUList(bool thing) : JSUPtrList(thing) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* JSULIST_H */
|
@ -1,6 +0,0 @@
|
||||
#ifndef JUTDBPPRINT_H
|
||||
#define JUTDBPPRINT_H
|
||||
|
||||
void JUTReport(int, int, const char *, ...);
|
||||
|
||||
#endif // !JUTDBPPRINT_H
|
@ -29,4 +29,4 @@ typedef volatile f64 vf64;
|
||||
|
||||
typedef int BOOL;
|
||||
|
||||
#endif // !TYPES_H
|
||||
#endif // !TYPES_H
|
7998
info/Symbols(Game).txt
Normal file
7998
info/Symbols(Game).txt
Normal file
File diff suppressed because it is too large
Load Diff
331
progress.py
Normal file
331
progress.py
Normal file
@ -0,0 +1,331 @@
|
||||
import csv, glob, math, os, sys
|
||||
from pathlib import Path
|
||||
|
||||
libraries = { }
|
||||
|
||||
def truncate(number, digits) -> float:
|
||||
stepper = 10.0 ** digits
|
||||
return math.trunc(stepper * number) / stepper
|
||||
|
||||
class Function:
|
||||
name = ""
|
||||
isCompleted = False
|
||||
funcSize = 0
|
||||
|
||||
def __init__(self, name, isComplete, funcSize):
|
||||
self.name = name
|
||||
self.isCompleted = isComplete
|
||||
self.funcSize = funcSize
|
||||
|
||||
class Object:
|
||||
name = ""
|
||||
functions = []
|
||||
totalFunctions = 0
|
||||
totalCompletedFunctions = 0
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.functions = list()
|
||||
self.totalFunctions = 0
|
||||
self.totalCompletedFunctions = 0
|
||||
|
||||
def addFunction(self, function):
|
||||
self.functions.append(function)
|
||||
|
||||
if function.isCompleted:
|
||||
self.totalCompletedFunctions += 1
|
||||
|
||||
self.totalFunctions += 1
|
||||
|
||||
def getFunctions(self):
|
||||
return self.functions
|
||||
|
||||
def calculateProgress(self):
|
||||
fullSize = 0
|
||||
doneSize = 0
|
||||
for function in self.functions:
|
||||
fullSize += function.funcSize
|
||||
|
||||
if function.isCompleted:
|
||||
doneSize += function.funcSize
|
||||
|
||||
return doneSize, fullSize
|
||||
|
||||
class Library:
|
||||
name = ""
|
||||
objects = []
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.objects = list()
|
||||
|
||||
def addObject(self, object):
|
||||
self.objects.append(object)
|
||||
|
||||
def addFunctionToObject(self, obj, function):
|
||||
if self.containsObject(obj.name):
|
||||
self.findObject(obj.name).addFunction(function)
|
||||
else:
|
||||
self.addObject(obj)
|
||||
self.addFunctionToObject(obj, function)
|
||||
|
||||
def findObject(self, objectName):
|
||||
for obj in self.objects:
|
||||
if obj.name == objectName:
|
||||
return obj
|
||||
|
||||
return None
|
||||
|
||||
def getObjects(self):
|
||||
return self.objects
|
||||
|
||||
def containsObject(self, object):
|
||||
for obj in self.objects:
|
||||
if obj.name == object:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def calculateProgress(self):
|
||||
fullSize = 0
|
||||
doneSize = 0
|
||||
|
||||
for obj in self.objects:
|
||||
d, f = obj.calculateProgress()
|
||||
fullSize += f
|
||||
doneSize += d
|
||||
|
||||
return doneSize, fullSize
|
||||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
def generateJSONTag(self, percent, color):
|
||||
json = []
|
||||
json.append("{\n")
|
||||
json.append("\t\"schemaVersion\": 1,\n")
|
||||
json.append(f"\t\"label\": \"{self.name}\",\n")
|
||||
json.append(f"\t\"message\": \"{truncate(percent, 5)}%\",\n")
|
||||
json.append(f"\t\"color\": \"{color}\"\n")
|
||||
json.append("}")
|
||||
|
||||
with open(f"data/json/{self.name}.json", "w") as w:
|
||||
w.writelines(json)
|
||||
|
||||
def generateMarkdown(self):
|
||||
# first we are going to generate the tables for the object files themselves in the library
|
||||
page = []
|
||||
page.append(f"# {self.name}\n")
|
||||
page.append("| Object | Percentage (of Bytes) | Functions Done / Total Functions | Percentage (Functions) \n")
|
||||
page.append("| ------------- | ------------- | ------------- | ------------- |\n")
|
||||
|
||||
for obj in self.objects:
|
||||
d, f = obj.calculateProgress()
|
||||
prog = (d / f) * 100.0
|
||||
funcProg = (obj.totalCompletedFunctions / obj.totalFunctions) * 100.0
|
||||
page.append(f"| {obj.name} | {prog}% | {obj.totalCompletedFunctions} / {obj.totalFunctions} | {funcProg}% |\n")
|
||||
|
||||
page.append("\n\n")
|
||||
|
||||
# now we can do it per object in the library
|
||||
for obj in self.objects:
|
||||
page.append(f"# {obj.name}\n")
|
||||
page.append("| Symbol | Decompiled? |\n")
|
||||
page.append("| ------------- | ------------- |\n")
|
||||
|
||||
for func in obj.getFunctions():
|
||||
marker = ":x:"
|
||||
|
||||
if func.isCompleted:
|
||||
marker = ":white_check_mark:"
|
||||
|
||||
funcName = func.name.replace("<", "<")
|
||||
funcName = funcName.replace(">", ">")
|
||||
|
||||
page.append(f"| {funcName} | {marker} |\n")
|
||||
|
||||
page.append("\n\n")
|
||||
|
||||
with open(f"docs/lib/{self.name}.md", "w") as w:
|
||||
w.writelines(page)
|
||||
|
||||
excludedLibraries = [
|
||||
"ai.a",
|
||||
"aralt.a",
|
||||
"arc.a",
|
||||
"ax.a",
|
||||
"axfx.a",
|
||||
"base.a",
|
||||
"bte.a",
|
||||
"db.a",
|
||||
"dsp.a",
|
||||
"dvd.a",
|
||||
"esp.a",
|
||||
"euart.a",
|
||||
"exi.a",
|
||||
"fs.a",
|
||||
"gd.a",
|
||||
"gx.a",
|
||||
"ipc.a",
|
||||
"libnw4Fr_ut.a",
|
||||
"libnw4r_db.a",
|
||||
"libnw4r_lyt.a",
|
||||
"libnw4r_math.a",
|
||||
"libnw4r_ut.a",
|
||||
"MSL_C.PPCEABI.bare.H.a",
|
||||
"mem.a",
|
||||
"mtx.a",
|
||||
"nand.a",
|
||||
"net.a",
|
||||
"nwc24.a",
|
||||
"NWC24.a",
|
||||
"os.a",
|
||||
"pad.a",
|
||||
"rso.a",
|
||||
"Runtime.PPCEABI.H.a",
|
||||
"RVLFaceLib.a",
|
||||
"sc.a",
|
||||
"si.a",
|
||||
"thp.a",
|
||||
"tpl.a",
|
||||
"TRK_Hollywood_Revolution.a",
|
||||
"usb.a",
|
||||
"vf.a",
|
||||
"vi.a",
|
||||
"wenc.a",
|
||||
"wpad.a",
|
||||
"wud.a",
|
||||
"JAudio2.a",
|
||||
"JKernel.a",
|
||||
"JSupport.a",
|
||||
"JGadget.a",
|
||||
"JUtility.a",
|
||||
"J2DGraph.a",
|
||||
"J3DGraphBase.a",
|
||||
"J3DGraphAnimator.a",
|
||||
"J3DGraphLoader.a",
|
||||
"JMath.a",
|
||||
"JParticle.a",
|
||||
"NdevExi2A.a"
|
||||
]
|
||||
|
||||
lib_percent_colors = {
|
||||
"Animation": "brightgreen",
|
||||
"AreaObj": "green",
|
||||
"AudioLib": "yellow",
|
||||
"Boss": "orange",
|
||||
"Camera": "red",
|
||||
"Demo": "D65076",
|
||||
"Effect": "pink",
|
||||
"Enemy": "magenta",
|
||||
"GameAudio": "teal",
|
||||
"Gravity": "maroon",
|
||||
"LiveActor": "cyan",
|
||||
"Map": "silver",
|
||||
"MapObj": "tan",
|
||||
"NameObj": "indigo",
|
||||
"NPC": "7fffd4",
|
||||
"Player": "ff7f50",
|
||||
"RhythmLib": "088da5",
|
||||
"Ride": "ffff66",
|
||||
"Scene": "a0db8e",
|
||||
"Screen": "ff4040",
|
||||
"Speaker": "daa520",
|
||||
"System": "696969",
|
||||
"Util": "ff6666"
|
||||
}
|
||||
|
||||
func_sizes = {}
|
||||
|
||||
# start by reading function sizes
|
||||
with open("data/funcSizes.txt", "r") as file:
|
||||
lines = file.readlines()
|
||||
|
||||
for line in lines:
|
||||
spl = line.split('=')
|
||||
sym = spl[0]
|
||||
func_sizes[sym] = spl[1].split(',', 1)[1]
|
||||
|
||||
csv_files = glob.glob("csv/*.csv")
|
||||
|
||||
for csv_file in csv_files:
|
||||
lib_name = Path(csv_file).stem
|
||||
lib_arch_name = Path(csv_file).stem + ".a"
|
||||
# we are just going to ignore non-SMG libraries
|
||||
if lib_arch_name not in excludedLibraries:
|
||||
library = Library(lib_name)
|
||||
|
||||
with open(csv_file, "r") as c:
|
||||
csv_reader = csv.reader(c)
|
||||
|
||||
for row in csv_reader:
|
||||
symbol = row[0]
|
||||
symbol = symbol.replace(",", ",")
|
||||
if symbol == "Symbol Name":
|
||||
continue
|
||||
|
||||
obj = row[1]
|
||||
lib = row[2]
|
||||
done = row[3] == "true"
|
||||
|
||||
funcSize = int(func_sizes[symbol].strip("\n"))
|
||||
func = Function(symbol, done, funcSize)
|
||||
|
||||
obj = Object(obj)
|
||||
library.addFunctionToObject(obj, func)
|
||||
|
||||
libraries[lib_name] = library
|
||||
|
||||
fullSize = 0
|
||||
doneSize = 0
|
||||
|
||||
print("Calculating percentages...")
|
||||
|
||||
for key in libraries:
|
||||
lib = libraries[key]
|
||||
d, f = lib.calculateProgress()
|
||||
fullSize += f
|
||||
doneSize += d
|
||||
lib.generateJSONTag((d / f ) * 100.0, lib_percent_colors[lib.getName()])
|
||||
|
||||
progPercent = (doneSize / fullSize ) * 100.0
|
||||
progNonPercent = int((doneSize / fullSize) * 120.0)
|
||||
|
||||
print(f"Progress: {progPercent}% [{doneSize} / {fullSize}] bytes")
|
||||
print(f"You currently have {progNonPercent} / 120 stars.")
|
||||
|
||||
print("Generating JSON...")
|
||||
|
||||
json = []
|
||||
json.append("{\n")
|
||||
json.append("\t\"schemaVersion\": 1,\n")
|
||||
json.append("\t\"label\": \"decompiled\",\n")
|
||||
json.append(f"\t\"message\": \"{progPercent}%\",\n")
|
||||
json.append("\t\"color\": \"blue\"\n")
|
||||
json.append("}")
|
||||
|
||||
with open("data/percent.json", "w") as w:
|
||||
w.writelines(json)
|
||||
|
||||
print("Generating markdown pages...")
|
||||
|
||||
# now we generate our progress page
|
||||
progressPage = []
|
||||
progressPage.append("| Library | Percentage |\n")
|
||||
progressPage.append("| ------------- | ------------- |\n")
|
||||
|
||||
for key in libraries:
|
||||
lib = libraries[key]
|
||||
d, f = lib.calculateProgress()
|
||||
libprog = (d / f) * 100.0
|
||||
progressPage.append(f"| [{key}](https://github.com/shibbo/Petari/blob/master/docs/lib/{key}.md) | {libprog}% |\n")
|
||||
|
||||
with open("docs/PROGRESS.md", "w") as w:
|
||||
w.writelines(progressPage)
|
||||
|
||||
# now we write the progress page for each library
|
||||
for key in libraries:
|
||||
lib = libraries[key]
|
||||
lib.generateMarkdown()
|
||||
|
||||
print("Done.")
|
17
sanity_check.py
Normal file
17
sanity_check.py
Normal file
@ -0,0 +1,17 @@
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
error_count = 0
|
||||
|
||||
for path, subdirs, files in os.walk(pathlib.Path("include")):
|
||||
for file_name in files:
|
||||
full_name = os.path.join(path, file_name)
|
||||
|
||||
with open(full_name, "r") as input:
|
||||
first_line = input.readline().rstrip()
|
||||
|
||||
if first_line != "#pragma once":
|
||||
print(f"ERROR: Missing pragma once in {full_name}")
|
||||
error_count += 1
|
||||
|
||||
print(f"Check finished with {error_count} error(s).")
|
66
setup.py
Normal file
66
setup.py
Normal file
@ -0,0 +1,66 @@
|
||||
# setup.py -- by shibboleet
|
||||
# Allows for the easy setup of Petari and its dependencies
|
||||
|
||||
import zipfile
|
||||
import urllib.request
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
def install(what):
|
||||
subprocess.check_call([sys.executable, '-m', 'pip', 'install', what])
|
||||
|
||||
if not os.path.exists("baserom.dol"):
|
||||
print("baserom.dol does not exist. Place a SMG1 dol named baserom.dol in the root.")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("Found baserom.dol...")
|
||||
|
||||
try:
|
||||
import capstone
|
||||
print("Found capstone, continuing...")
|
||||
except ModuleNotFoundError:
|
||||
print("Module 'capstone' not installed. Installing...")
|
||||
install("capstone")
|
||||
|
||||
try:
|
||||
import elftools
|
||||
print("Found elftools, continuing...")
|
||||
except ModuleNotFoundError:
|
||||
print("Module `elftools` not found. Installing...")
|
||||
install("pyelftools")
|
||||
|
||||
try:
|
||||
import ninja
|
||||
print("Found ninja, continuing...")
|
||||
except ModuleNotFoundError:
|
||||
print("Module 'ninja' not found. Installing...")
|
||||
install("ninja")
|
||||
|
||||
try:
|
||||
import colorama
|
||||
print("Found colorama, continuing...")
|
||||
except ModuleNotFoundError:
|
||||
print("Module 'colorama' not found. Installing...")
|
||||
install("colorama")
|
||||
|
||||
if not os.path.exists("deps"):
|
||||
print("Dependency folder not found, downloading...")
|
||||
|
||||
with urllib.request.urlopen("http://shibbo.net/smg/deps.zip") as response, open("deps.zip", 'wb') as out:
|
||||
data = response.read()
|
||||
out.write(data)
|
||||
|
||||
if os.path.exists("deps.zip"):
|
||||
os.mkdir("deps")
|
||||
print("Extracting file...")
|
||||
with zipfile.ZipFile("deps.zip", "r") as zip:
|
||||
zip.extractall("deps")
|
||||
|
||||
os.remove("deps.zip")
|
||||
else:
|
||||
print("deps.zip failed to download.")
|
||||
sys.exit(1)
|
||||
|
||||
print("Done.")
|
||||
sys.exit(1)
|
@ -1,16 +1,7 @@
|
||||
#include <JSystem/JMath/JMath.h>
|
||||
#include "JSystem/JMath/JMath.h"
|
||||
|
||||
namespace JMath {
|
||||
TRandom_fast_::TRandom_fast_(u32 num = 0) {
|
||||
random = num;
|
||||
}
|
||||
|
||||
u32 TRandom_fast_::get() {
|
||||
seed = (seed * 0x19660d) + 0x3c6ef35f;
|
||||
return seed;
|
||||
}
|
||||
|
||||
void TRandom_fast_::setSeed(u32 Seed) {
|
||||
seed = Seed;
|
||||
TRandom_fast_::TRandom_fast_(u32 num) {
|
||||
seed = num;
|
||||
}
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
#include "JSystem/JSupport/JSUList.h"
|
||||
|
||||
JSUPtrLink::JSUPtrLink(void *pData) {
|
||||
mData = pData;
|
||||
mPtrList = 0;
|
||||
mPrev = 0;
|
||||
mNext = 0;
|
||||
}
|
||||
|
||||
JSUPtrLink::~JSUPtrLink() {
|
||||
if (mPtrList) {
|
||||
mPtrList->remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
JSUPtrList::JSUPtrList(bool doInitialize) {
|
||||
if (doInitialize) {
|
||||
initiate();
|
||||
}
|
||||
}
|
||||
|
||||
JSUPtrList::~JSUPtrList() {
|
||||
JSUPtrLink* curHead = mHead;
|
||||
|
||||
for (int i = 0; i < mNodeCount; i++) {
|
||||
curHead->mPtrList = 0;
|
||||
curHead = curHead->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
void JSUPtrList::initiate() {
|
||||
mHead = 0;
|
||||
mTail = 0;
|
||||
mNodeCount = 0;
|
||||
}
|
||||
|
||||
void JSUPtrList::setFirst(JSUPtrLink *pLink) {
|
||||
pLink->mPtrList = this;
|
||||
pLink->mPrev = 0;
|
||||
pLink->mNext = 0;
|
||||
mTail = pLink;
|
||||
mHead = pLink;
|
||||
mNodeCount = 1;
|
||||
}
|
||||
|
||||
bool JSUPtrList::append(JSUPtrLink *pLink) {
|
||||
bool validity = (pLink->mPtrList == 0);
|
||||
|
||||
if (!validity) {
|
||||
validity = pLink->mPtrList->remove(pLink);
|
||||
}
|
||||
|
||||
if (validity) {
|
||||
if (!mNodeCount) {
|
||||
setFirst(pLink);
|
||||
}
|
||||
else {
|
||||
pLink->mPtrList = this;
|
||||
pLink->mPrev = mTail;
|
||||
pLink->mNext = 0;
|
||||
mTail->mNext = pLink;
|
||||
mTail = pLink;
|
||||
mNodeCount = mNodeCount + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return validity;
|
||||
}
|
||||
|
||||
bool JSUPtrList::prepend(JSUPtrLink *pLink) {
|
||||
bool validity = (pLink->mPtrList == 0);
|
||||
|
||||
if (!validity) {
|
||||
validity = pLink->mPtrList->remove(pLink);
|
||||
}
|
||||
|
||||
if (validity) {
|
||||
if (!mNodeCount) {
|
||||
setFirst(pLink);
|
||||
}
|
||||
else {
|
||||
pLink->mPtrList = this;
|
||||
pLink->mPrev = 0;
|
||||
pLink->mNext = mHead;
|
||||
mHead->mPrev = pLink;
|
||||
mHead = pLink;
|
||||
mNodeCount = mNodeCount + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return validity;
|
||||
}
|
||||
|
||||
bool JSUPtrList::insert(JSUPtrLink *pLink_1, JSUPtrLink *pLink_2) {
|
||||
if (pLink_1 == mHead) {
|
||||
return prepend(pLink_2);
|
||||
}
|
||||
if (!pLink_1) {
|
||||
return append(pLink_2);
|
||||
}
|
||||
if (pLink_1->mPtrList != this) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSUPtrList* link2PtrList = pLink_2->mPtrList;
|
||||
|
||||
bool validity = (link2PtrList == 0);
|
||||
|
||||
if (!validity) {
|
||||
validity = link2PtrList->remove(pLink_2);
|
||||
}
|
||||
|
||||
if (validity) {
|
||||
JSUPtrLink* prev = pLink_1->mPrev;
|
||||
pLink_2->mPtrList = this;
|
||||
pLink_2->mPrev = prev;
|
||||
pLink_2->mNext = pLink_1;
|
||||
prev->mNext = pLink_2;
|
||||
pLink_1->mPrev = pLink_2;
|
||||
mNodeCount++;
|
||||
}
|
||||
|
||||
return validity;
|
||||
}
|
||||
|
||||
bool JSUPtrList::remove(JSUPtrLink *pLink) {
|
||||
bool isSameList = (pLink->mPtrList == this);
|
||||
|
||||
if (isSameList) {
|
||||
if (mNodeCount == 1) {
|
||||
mHead = 0;
|
||||
mTail = 0;
|
||||
}
|
||||
else if (pLink == mHead) {
|
||||
pLink->mNext->mPrev = 0;
|
||||
mHead = pLink->mNext;
|
||||
}
|
||||
else if (pLink == mTail) {
|
||||
pLink->mPrev->mNext = 0;
|
||||
mTail = pLink->mPrev;
|
||||
}
|
||||
else {
|
||||
pLink->mPrev->mNext = pLink->mNext;
|
||||
pLink->mNext->mPrev = pLink->mPrev;
|
||||
}
|
||||
|
||||
pLink->mPtrList = 0;
|
||||
mNodeCount--;
|
||||
}
|
||||
|
||||
return isSameList;
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
#ifndef KARTCHECKER_H
|
||||
#define KARTCHECKER_H
|
||||
|
||||
#include <types.h>
|
||||
#include <JSystem/JGeometry.h>
|
||||
|
||||
#include "KartInfo.h"
|
||||
#include "RaceTime.h"
|
||||
//#include "JugemPoint.h"
|
||||
//#include "Course.h"
|
||||
//#include "KartGamePad"
|
||||
|
||||
|
||||
class KartChecker {
|
||||
public:
|
||||
KartChecker(int, KartInfo *, int, int);
|
||||
|
||||
//void setPlayerKartColor(KartInfo *);
|
||||
private:
|
||||
u16 raceFlags;
|
||||
s16 kartIndex;
|
||||
s32 sectorCount;
|
||||
s32 bitfieldCnt;
|
||||
s32 trackLapCount;
|
||||
s32 _0x10; // i think this stores the index of the fastest lap
|
||||
RaceTime* laptimes1;
|
||||
RaceTime* laptimes2;
|
||||
s32 playerKartColor;
|
||||
void* kartGamePad1;
|
||||
void* kartGamePad2;
|
||||
bool showLapSplit;
|
||||
bool raceEnd;
|
||||
u8 _0x2a; // only seems to get set in the constructor
|
||||
u8 _0x2b; // probably padding
|
||||
s32 lapIndex;
|
||||
f32 sectorProgression;
|
||||
s32 warpState;
|
||||
s32 _0x38;
|
||||
s32 sectorIndex;
|
||||
Course::Sector * sector1;
|
||||
Course::Sector * sector2;
|
||||
f32 lapProgession;
|
||||
f32 prevlapProgession;
|
||||
f32 lapProgression2; // might be max Lap Progression
|
||||
f32 raceProgression;
|
||||
s32* cpBitfields; // seems to store what checkpoint have been passed
|
||||
TVec3<f32> curPos;
|
||||
TVec3<f32> prevPos;
|
||||
JugemPoint * jugemPoint;
|
||||
bool _0x78; // true = in race | false = finished
|
||||
u8 _0x79[3];
|
||||
s32 curFrame;
|
||||
s32 goalFrame;
|
||||
RaceTime Timer;
|
||||
s32 rank;
|
||||
s16 battleFlags;
|
||||
s16 _0x8e;
|
||||
s16 balloonNumber;
|
||||
u8 _0x92[2]; // this is probaby padding
|
||||
RaceTime deathTime;
|
||||
RaceTime markTime;
|
||||
u8 _0x9c[010];
|
||||
s16 bombPoint;
|
||||
s16 rabbitWinFrame;
|
||||
s32 demoPoint;
|
||||
// these only get set in the constructor?
|
||||
TVec3<f32> _0xb0;
|
||||
s32 _0xbc;
|
||||
};
|
||||
|
||||
#endif // !KARTCHECKER_H
|
@ -1,4 +1,4 @@
|
||||
#include "KartInfo.h"
|
||||
#include "Kaneshige/KartInfo.h"
|
||||
|
||||
void KartInfo::reset() {
|
||||
|
||||
|
@ -1,74 +0,0 @@
|
||||
#ifndef KARTINFO_H
|
||||
#define KARTINFO_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
enum EKartID {
|
||||
RED_FIRE = 0,
|
||||
DK_JUMBO = 1,
|
||||
TURBO_YOSHI = 2,
|
||||
KOOPA_DASHER = 3,
|
||||
HEART_COACH = 4,
|
||||
GOO_GOO_BUGGY = 5,
|
||||
WARIO_CAR = 6,
|
||||
KOOPA_KING = 7,
|
||||
GREEN_FIRE = 8,
|
||||
BARREL_TRAIN = 9,
|
||||
TURBO_BIRDO = 10,
|
||||
PARA_WING = 11,
|
||||
BLOOM_COACH = 12,
|
||||
RATTLE_BUGGY = 13,
|
||||
WALUIGI_RACER = 14,
|
||||
BULLET_BLASTER = 15,
|
||||
TOAD_KART = 16,
|
||||
TOADETTE_KART = 17,
|
||||
BOO_PIPES = 18,
|
||||
PIRANHA_PIPES = 19,
|
||||
PARADE_KART = 20
|
||||
};
|
||||
|
||||
class KartInfo {
|
||||
public:
|
||||
KartInfo();
|
||||
~KartInfo();
|
||||
|
||||
void reset();
|
||||
|
||||
struct SCharDB
|
||||
{
|
||||
s16 id;
|
||||
s16 defaultPartnerID;
|
||||
s16 weight;
|
||||
s16 defaultKartID;
|
||||
u8 _8;
|
||||
u8 _9[3]; // this is padding data most likely
|
||||
};
|
||||
|
||||
struct SKartDB
|
||||
{
|
||||
EKartID id;
|
||||
s32 weight;
|
||||
s16 _08; // not sure if this is a short or 2 bytes
|
||||
s8 _09;
|
||||
s8 _0A; // probably padding
|
||||
s16 defaultDriverID;
|
||||
s8 _0E[2]; // padding bytes most likely
|
||||
};
|
||||
|
||||
class KartCharacter {
|
||||
public:
|
||||
KartCharacter();
|
||||
~KartCharacter();
|
||||
private:
|
||||
void* kartGamePad; // inherited from JUTGamePad
|
||||
SCharDB* charDB;
|
||||
};
|
||||
|
||||
private:
|
||||
SKartDB * kartDB;
|
||||
KartCharacter kartCharacter[2]; // one for the driver, other for the one doing nothing
|
||||
s32 kartType; // if this is set to 1 this means the driver is a ghost, 2 is also used for ghost but for the pad that gets recorded, so that means 2 is invisible?
|
||||
|
||||
};
|
||||
|
||||
#endif // !KARTINFO_H
|
@ -1,13 +1,15 @@
|
||||
#include "RaceInfo.h"
|
||||
#include "Kaneshige/RaceInfo.h"
|
||||
|
||||
#include "JSystem/JMath/JMath.h"
|
||||
|
||||
void RaceInfo::reset() {
|
||||
isTinyProcess = false;
|
||||
isLanMode = false;
|
||||
isTrueEnding = false;
|
||||
randomSeed = 0;
|
||||
gpCup = -1;
|
||||
raceMode = 0;
|
||||
raceLevel = -1;
|
||||
gpCup = INV_CUP;
|
||||
raceMode = INV_MODE;
|
||||
raceLevel = LVL_INV;
|
||||
itemSlotType = 0;
|
||||
vsLapNum = 0;
|
||||
lapNumLAN = 0;
|
||||
@ -17,10 +19,10 @@ void RaceInfo::reset() {
|
||||
statusNum = 0;
|
||||
lod = 0;
|
||||
gpStageNo = 0;
|
||||
_0x28 = 0;
|
||||
inWaitDemo = 0;
|
||||
isMirror = false;
|
||||
_0x298 = 0;
|
||||
hideConsole = 0;
|
||||
HideConsole = 0;
|
||||
|
||||
for (s32 i = 0; i < 8; i++) {
|
||||
kartInfo[i].reset();
|
||||
@ -67,7 +69,7 @@ void RaceInfo::setRace(ERaceMode RaceMode, s32 kartCount, s32 playerCount, s32 c
|
||||
}
|
||||
|
||||
void RaceInfo::setRaceLevel(ERaceLevel raceLvl) {
|
||||
raceLevel = raceLvl;
|
||||
this->raceLevel = raceLvl;
|
||||
if (raceLvl == LVL_MIRROR)
|
||||
isMirror = true;
|
||||
else
|
||||
@ -96,5 +98,5 @@ void RaceInfo::shuffleStartNo() {
|
||||
}
|
||||
|
||||
void RaceInfo::hideConsole(u32 param_2) {
|
||||
hideConsole = hideConsole | (u16)(1 << param_2);
|
||||
HideConsole = HideConsole | (u16)(1 << param_2);
|
||||
}
|
||||
|
@ -1,97 +0,0 @@
|
||||
#ifndef RACEINFO_H
|
||||
#define RACEINFO_H
|
||||
|
||||
#include <types.h>
|
||||
#include <JSystem/JMath/JMath.h>
|
||||
|
||||
#include "KartInfo.h"
|
||||
#include "RaceTime.h"
|
||||
|
||||
enum ERaceMode {
|
||||
TIME_ATTACK = 0x1,
|
||||
GRAND_PRIX = 0x2,
|
||||
VERSUS_RACE = 0x3,
|
||||
BALLOON_BATTLE = 0x4,
|
||||
ROBBERY_BATTLE = 0x5,
|
||||
BOMB_BATTLE = 0x6,
|
||||
ESCAPE_BATTLE = 0x7,
|
||||
AWARD_DEMO = 0x8,
|
||||
STAFF_ROLL = 0x9,
|
||||
};
|
||||
|
||||
enum ERaceLevel { // unsure of this
|
||||
LVL_INV = -1,
|
||||
LVL_50CC = 0,
|
||||
LVL_100CC = 1,
|
||||
LVL_150CC = 2,
|
||||
LVL_MIRROR = 3,
|
||||
};
|
||||
|
||||
enum ERaceGpCup {
|
||||
MUSHROOM_CUP = 0,
|
||||
FLOWER_CUP = 1,
|
||||
STAR_CUP = 2,
|
||||
SPECIAL_CUP = 3,
|
||||
REVERSE2_CUP = 4,
|
||||
};
|
||||
|
||||
class RaceInfo {
|
||||
public:
|
||||
inline RaceInfo(); // this is not inlined in the debug version
|
||||
~RaceInfo();
|
||||
|
||||
void reset();
|
||||
void setConsoleTarget(s32 idx, s16 p2, bool p3);
|
||||
void setRace(ERaceMode RaceMode, s32 kartCount, s32 playerCount, s32 consoleCount, s32 p5);
|
||||
void setRaceLevel(ERaceLevel);
|
||||
|
||||
void shuffleRandomSeed();
|
||||
void shuffleStartNo();
|
||||
void hideConsole(u32 param_2);
|
||||
|
||||
s16 getKartNumber() {
|
||||
return kartNum;
|
||||
}
|
||||
|
||||
private:
|
||||
bool isTinyProcess;
|
||||
bool isLanMode;
|
||||
bool isTrueEnding;
|
||||
u32 randomSeed;
|
||||
ERaceMode raceMode;
|
||||
ERaceGpCup gpCup;
|
||||
ERaceLevel raceLevel;
|
||||
s32 itemSlotType; // perhaps this is an enum too
|
||||
s16 vsLapNum;
|
||||
s16 lapNumLAN;
|
||||
s16 kartNum;
|
||||
s16 playerNum;
|
||||
s16 consoleNum;
|
||||
s16 statusNum;
|
||||
u16 lod;
|
||||
s16 gpStageNo;
|
||||
s32 inWaitDemo;
|
||||
bool isMirror;
|
||||
// padding bytes
|
||||
KartInfo kartInfo[8];
|
||||
s16 startPosIndex[8];
|
||||
s16 pointTable[8];
|
||||
s16 rivalKarts[2];
|
||||
|
||||
s16 _0x114[4];
|
||||
bool _0x11c[4]; // not sure what these two arrays do, setConsoleTarget sets this so maybe this bool array means isActive and the other the console number
|
||||
|
||||
s16 awardKartNo;
|
||||
// padding bytes
|
||||
s32 demoNextPhase;
|
||||
s16 rank[8]; // stores what rank you finished at previous race, basically the same as startPosIndex
|
||||
RaceTime finishTime[8];
|
||||
RaceTime lapTimes[80]; // 10 per player so perhaps it's lapTimes[8][10] or lapTimes[10][8](why do i not know how arrays work)
|
||||
s32 _0x298;
|
||||
s16 hideConsole;
|
||||
s8 _0x29e[0x2e0 - 0x29e]; // unknown
|
||||
};
|
||||
|
||||
RaceInfo gRaceInfo;
|
||||
|
||||
#endif // !RACEINFO_H
|
@ -1,70 +0,0 @@
|
||||
#ifndef RACEMGR_H
|
||||
#define RACEMGR_H
|
||||
|
||||
#include <types.h>
|
||||
#include <JSystem/JKernel/JKRDisposer.h>
|
||||
#include <JSystem/JKernel/JKRHeap.h>
|
||||
|
||||
#include "RaceInfo.h"
|
||||
#include "RaceTime.h"
|
||||
#include "KartChecker.h"
|
||||
|
||||
class RaceMgr : JKRDisposer {
|
||||
public:
|
||||
RaceMgr(RaceInfo *);
|
||||
virtual ~RaceMgr();
|
||||
|
||||
static RaceMgr * sRaceManager;
|
||||
static s16 sForceTotalLapNum;
|
||||
static s16 sDispFrameCounter;
|
||||
|
||||
static s16 sMyStartPointID;
|
||||
|
||||
class Console {
|
||||
public:
|
||||
Console();
|
||||
void changeTargetNo(s32, bool);
|
||||
private:
|
||||
s32 _0x0;
|
||||
u8 _0x4;
|
||||
s32 _0x8;
|
||||
u16 _0xc;
|
||||
};
|
||||
|
||||
private:
|
||||
RaceDirector * raceDirector;
|
||||
RaceDrawer * raceDrawer;
|
||||
u16 areaLight;
|
||||
u8 _0x22;
|
||||
u8 _0x23; // probably padding
|
||||
u32 frame;
|
||||
JKRHeap * raceHeap;
|
||||
s16 replayMode;
|
||||
s16 totalLapNumber;
|
||||
s32 _0x30;
|
||||
bool _0x31;
|
||||
RaceInfo * raceInfo;
|
||||
RaceBGMPlayer * raceBGMPlayer;
|
||||
Console * console;
|
||||
Course * course;
|
||||
KartChecker * kartChecker[8];
|
||||
KartLoader * kartLoader[8];
|
||||
StaffRoll2D * staffRoll2D;
|
||||
RaceTime bestLapTime;
|
||||
RaceTime bestTotalTime[5];
|
||||
s16 events;
|
||||
|
||||
// these values store the amount of time/frames it took to execute a certain set of functions
|
||||
// 0x0 GX Issue
|
||||
// 0x100 Calc
|
||||
// 0x200 update
|
||||
// 0x300 ViewCalc
|
||||
s16 proctime1;
|
||||
s16 proctime2;
|
||||
s16 proctime3;
|
||||
s16 proctime4;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // RACEMGR_H
|
@ -1,4 +1,4 @@
|
||||
#include "RaceTime.h"
|
||||
#include "Kaneshige/RaceTime.h"
|
||||
|
||||
#define MAX_TIME 5999999
|
||||
#define MAX_MS 999
|
||||
@ -68,7 +68,7 @@ void RaceTime::sub(const RaceTime & split1, const RaceTime & split2) {
|
||||
}
|
||||
|
||||
void RaceTime::sub(int p1) {
|
||||
time -= p1;
|
||||
time = time - p1;
|
||||
}
|
||||
|
||||
void RaceTime::zero() {
|
||||
|
@ -1,32 +0,0 @@
|
||||
#ifndef RACETIME_H
|
||||
#define RACETIME_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
class RaceTime
|
||||
{
|
||||
public:
|
||||
inline RaceTime();
|
||||
//inline RaceTime(RaceTime const &);
|
||||
//inline void operator=(const RaceTime &);
|
||||
inline void reset();
|
||||
inline void zero();
|
||||
inline void set(int);
|
||||
inline void set(RaceTime const &);
|
||||
inline bool isAvailable();
|
||||
inline bool isLittle(const RaceTime &) const;
|
||||
|
||||
inline void sub(const RaceTime &, const RaceTime &);
|
||||
inline int get() const;
|
||||
inline int sub(int);
|
||||
|
||||
inline void setFrame(int);
|
||||
inline int getUpwardMSec() const;
|
||||
|
||||
void get(int *, int *, int *) const;
|
||||
|
||||
private:
|
||||
int time;
|
||||
};
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user