diff --git a/CHANGES b/CHANGES index 0a561b62..82295970 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,23 @@ +Refresh 12 + +1.) Debug box improvements (#1066) +2.) Improve 'geo_render_mirror_mario' (#1064) +3.) Cleanup and small labeling (#1063) +4.) Anim renames and other related renames (#1062) +5.) remove do while 0 and make one line comments consistent (#1061) +6.) fixed typo in segments.h (#1060) +7.) Name unknown fields (from public repo) (#1058) +8.) Change 'void *' to 'struct MainPoolState *' (#1057) +9.) Fix type of freeList (#1056) +10.) Newer version of diff script (#1055) +11.) Add stubbed_printfs based on unused audio strings (#1054) +12.) Fix comment in paintings.c (#1053) +13.) Add defines for hardcoded cell/floor height values (#1051) +14.) Update README.md: Remove GitHub specific Markdown syntax (#1052) +15.) Properly label interation status that handle's Bowser's shockwave attack (#1050) + Refresh 11 -1.) (HEAD -> master, origin/master, origin/HEAD) Make geo_process_level_of_detail endian-independent (#1049) +1.) Make geo_process_level_of_detail endian-independent (#1049) 2.) Label oMoveFlags and slight cleanup. (#1046) 3.) Avoid UB in synthesis_resample_and_mix_reverb (#1048) 4.) Change some void * to correct type (#1047) diff --git a/Makefile b/Makefile index cc9cdc96..649abd20 100644 --- a/Makefile +++ b/Makefile @@ -1105,8 +1105,6 @@ $(BUILD_DIR)/actors/%.o: OPT_FLAGS := -g $(BUILD_DIR)/bin/%.o: OPT_FLAGS := -g $(BUILD_DIR)/src/goddard/%.o: OPT_FLAGS := -g $(BUILD_DIR)/src/goddard/%.o: MIPSISET := -mips1 -$(BUILD_DIR)/src/audio/%.o: OPT_FLAGS := -O2 -Wo,-loopunroll,0 -$(BUILD_DIR)/src/audio/load.o: OPT_FLAGS := -O2 -framepointer -Wo,-loopunroll,0 $(BUILD_DIR)/lib/src/%.o: OPT_FLAGS := $(BUILD_DIR)/lib/src/math/ll%.o: MIPSISET := -mips3 -32 $(BUILD_DIR)/lib/src/math/%.o: OPT_FLAGS := -O2 @@ -1122,15 +1120,22 @@ $(BUILD_DIR)/lib/src/_Ldtob.o: OPT_FLAGS := -O3 $(BUILD_DIR)/lib/src/_Printf.o: OPT_FLAGS := -O3 $(BUILD_DIR)/lib/src/sprintf.o: OPT_FLAGS := -O3 -# enable loop unrolling except for external.c (external.c might also have used -# unrolling, but it makes one loop harder to match) -$(BUILD_DIR)/src/audio/%.o: OPT_FLAGS := -O2 -$(BUILD_DIR)/src/audio/load.o: OPT_FLAGS := -O2 +# Enable loop unrolling except for external.c (external.c might also have used +# unrolling, but it makes one loop harder to match). +# For all audio files other than external.c and port_eu.c, put string literals +# in .data. (In Shindou, the port_eu.c string literals also moved to .data.) +$(BUILD_DIR)/src/audio/%.o: OPT_FLAGS := -O2 -use_readwrite_const +$(BUILD_DIR)/src/audio/port_eu.o: OPT_FLAGS := -O2 $(BUILD_DIR)/src/audio/external.o: OPT_FLAGS := -O2 -Wo,-loopunroll,0 else +$(BUILD_DIR)/src/audio/%.o: OPT_FLAGS := -O2 -Wo,-loopunroll,0 +$(BUILD_DIR)/src/audio/load.o: OPT_FLAGS := -O2 -framepointer -Wo,-loopunroll,0 + # The source-to-source optimizer copt is enabled for audio. This makes it use # acpp, which needs -Wp,-+ to handle C++-style comments. +# All other files than external.c should really use copt, but only a few have +# been matched so far. $(BUILD_DIR)/src/audio/effects.o: OPT_FLAGS := -O2 -Wo,-loopunroll,0 -sopt,-inline=sequence_channel_process_sound,-scalaroptimize=1 -Wp,-+ $(BUILD_DIR)/src/audio/synthesis.o: OPT_FLAGS := -O2 -sopt,-scalaroptimize=1 -Wp,-+ #$(BUILD_DIR)/src/audio/seqplayer.o: OPT_FLAGS := -O2 -sopt,-inline_manual,-scalaroptimize=1 -Wp,-+ #-Wo,-v,-bb,-l,seqplayer_list.txt diff --git a/README.md b/README.md index 02b1604a..3bc4b136 100644 --- a/README.md +++ b/README.md @@ -16,4 +16,4 @@ Create a mod for the PC port where multiple people can play online together. Unlike previous online attempts, this one synchronized enemies and events. This allows player to be interacting with the same world at the same time. ## Discord -[https://discord.gg/TJVKHS4](https://discord.gg/TJVKHS4) +[https://discord.gg/TJVKHS4](https://discord.gg/TJVKHS4) \ No newline at end of file diff --git a/asm/non_matchings/eu/audio/sequence_channel_process_script.s b/asm/non_matchings/eu/audio/sequence_channel_process_script.s index 30649af9..4078e3c7 100644 --- a/asm/non_matchings/eu/audio/sequence_channel_process_script.s +++ b/asm/non_matchings/eu/audio/sequence_channel_process_script.s @@ -1,3 +1,17 @@ +.data + .asciiz "Audio:Track :Call Macro Level Over Error!\n" + .balign 4 + .asciiz "Audio:Track :Loops Macro Level Over Error!\n" + .balign 4 + .asciiz "SUB:ERR:BANK %d NOT CACHED.\n" + .balign 4 + .asciiz "SUB:ERR:BANK %d NOT CACHED.\n" + .balign 4 + .asciiz "Audio:Track: CTBLCALL Macro Level Over Error!\n" + .balign 4 + .asciiz "Err :Sub %x ,address %x:Undefined SubTrack Function %x" + .balign 4 + .late_rodata .late_rodata_alignment 4 glabel jtbl_EU_80306714 diff --git a/asm/rom_header.s b/asm/rom_header.s index 88ac440f..c056acdb 100644 --- a/asm/rom_header.s +++ b/asm/rom_header.s @@ -5,7 +5,7 @@ .byte 0x80, 0x37, 0x12, 0x40 /* PI BSD Domain 1 register */ .word 0x0000000F /* Clockrate setting*/ -.word entry_point /* Entrypoint */ +.word entry_point /* Entrypoint */ /* Revision */ .if VERSION_SH == 1 @@ -39,8 +39,7 @@ .endif .if VERSION_SH == 1 - .byte 0x03 /* Version (Shindou) */ + .byte 0x03 /* Version (Shindou) */ .else .byte 0x00 /* Version */ .endif - diff --git a/diff.py b/diff.py index d9d39a1c..869070d6 100755 --- a/diff.py +++ b/diff.py @@ -5,6 +5,7 @@ import os import ast import argparse import subprocess +import collections import difflib import string import itertools @@ -20,7 +21,7 @@ def fail(msg): MISSING_PREREQUISITES = ( "Missing prerequisite python module {}. " - "Run `python3 -m pip install --user colorama ansiwrap attrs watchdog python-Levenshtein` to install prerequisites (python-Levenshtein only needed for --algorithm=levenshtein)." + "Run `python3 -m pip install --user colorama ansiwrap attrs watchdog python-Levenshtein cxxfilt` to install prerequisites (cxxfilt only needed with --source)." ) try: @@ -49,6 +50,21 @@ parser.add_argument( action="store_true", help="Diff .o files rather than a whole binary. This makes it possible to see symbol names. (Recommended)", ) +parser.add_argument( + "--elf", + dest="diff_elf_symbol", + help="Diff a given function in two ELFs, one being stripped and the other one non-stripped. Requires objdump from binutils 2.33+.", +) +parser.add_argument( + "--source", + action="store_true", + help="Show source code (if possible). Only works with -o and -e.", +) +parser.add_argument( + "--inlines", + action="store_true", + help="Show inline function calls (if possible). Only works with -o and -e.", +) parser.add_argument( "--base-asm", dest="base_asm", @@ -126,7 +142,7 @@ parser.add_argument( parser.add_argument( "--algorithm", dest="algorithm", - default="difflib", + default="levenshtein", choices=["levenshtein", "difflib"], help="Diff algorithm to use.", ) @@ -137,7 +153,7 @@ parser.add_argument( dest="max_lines", type=int, default=1024, - help="The maximum length of the diff, in lines. Not recommended when -f is used.", + help="The maximum length of the diff, in lines.", ) # Project-specific flags, e.g. different versions/make arguments. @@ -150,11 +166,13 @@ args = parser.parse_args() config = {} diff_settings.apply(config, args) +arch = config.get("arch", "mips") baseimg = config.get("baseimg", None) myimg = config.get("myimg", None) mapfile = config.get("mapfile", None) makeflags = config.get("makeflags", []) source_directories = config.get("source_directories", None) +objdump_executable = config.get("objdump_executable", None) MAX_FUNCTION_SIZE_LINES = args.max_lines MAX_FUNCTION_SIZE_BYTES = MAX_FUNCTION_SIZE_LINES * 4 @@ -172,7 +190,7 @@ COLOR_ROTATION = [ ] BUFFER_CMD = ["tail", "-c", str(10 ** 9)] -LESS_CMD = ["less", "-Ric"] +LESS_CMD = ["less", "-SRic", "-#6"] DEBOUNCE_DELAY = 0.1 FS_WATCH_EXTENSIONS = [".c", ".h"] @@ -185,25 +203,30 @@ if args.algorithm == "levenshtein": except ModuleNotFoundError as e: fail(MISSING_PREREQUISITES.format(e.name)) -binutils_prefix = None - -for binutils_cand in ["mips-linux-gnu-", "mips64-elf-"]: +if args.source: try: - subprocess.check_call( - [binutils_cand + "objdump", "--version"], - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - ) - binutils_prefix = binutils_cand - break - except subprocess.CalledProcessError: - pass - except FileNotFoundError: - pass + import cxxfilt + except ModuleNotFoundError as e: + fail(MISSING_PREREQUISITES.format(e.name)) -if not binutils_prefix: +if objdump_executable is None: + for objdump_cand in ["mips-linux-gnu-objdump", "mips64-elf-objdump"]: + try: + subprocess.check_call( + [objdump_cand, "--version"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + objdump_executable = objdump_cand + break + except subprocess.CalledProcessError: + pass + except FileNotFoundError: + pass + +if not objdump_executable: fail( - "Missing binutils; please ensure mips-linux-gnu-objdump or mips64-elf-objdump exist." + "Missing binutils; please ensure mips-linux-gnu-objdump or mips64-elf-objdump exist, or configure objdump_executable." ) @@ -219,6 +242,10 @@ def eval_int(expr, emsg=None): return None +def eval_line_num(expr): + return int(expr.strip().replace(":", ""), 16) + + def run_make(target, capture_output=False): if capture_output: return subprocess.run( @@ -244,10 +271,26 @@ def restrict_to_function(dump, fn_name): return "\n".join(out) +def maybe_get_objdump_source_flags(): + if not args.source: + return [] + + flags = [ + "--source", + "--source-comment=| ", + "-l", + ] + + if args.inlines: + flags.append("--inlines") + + return flags + + def run_objdump(cmd): flags, target, restrict = cmd out = subprocess.check_output( - [binutils_prefix + "objdump"] + flags + [target], universal_newlines=True + [objdump_executable] + flags + [target], universal_newlines=True ) if restrict is not None: return restrict_to_function(out, restrict) @@ -300,6 +343,36 @@ def search_map_file(fn_name): return None, None +def dump_elf(): + if not baseimg or not myimg: + fail("Missing myimg/baseimg in config.") + if base_shift: + fail("--base-shift not compatible with -e") + + start_addr = eval_int(args.start, "Start address must be an integer expression.") + + if args.end is not None: + end_addr = eval_int(args.end, "End address must be an integer expression.") + else: + end_addr = start_addr + MAX_FUNCTION_SIZE_BYTES + + flags1 = [ + f"--start-address={start_addr}", + f"--stop-address={end_addr}", + ] + + flags2 = [ + f"--disassemble={args.diff_elf_symbol}", + ] + + objdump_flags = ["-drz", "-j", ".text"] + return ( + myimg, + (objdump_flags + flags1, baseimg, None), + (objdump_flags + flags2 + maybe_get_objdump_source_flags(), myimg, None), + ) + + def dump_objfile(): if base_shift: fail("--base-shift not compatible with -o") @@ -326,7 +399,7 @@ def dump_objfile(): return ( objfile, (objdump_flags, refobjfile, args.start), - (objdump_flags, objfile, args.start), + (objdump_flags + maybe_get_objdump_source_flags(), objfile, args.start), ) @@ -366,29 +439,45 @@ def ansi_ljust(s, width): return s -re_int = re.compile(r"[0-9]+") -re_comments = re.compile(r"<.*?>") -re_regs = re.compile(r"\$?\b(a[0-3]|t[0-9]|s[0-8]|at|v[01]|f[12]?[0-9]|f3[01]|fp)\b") -re_sprel = re.compile(r",([0-9]+|0x[0-9a-f]+)\(sp\)") -re_large_imm = re.compile(r"-?[1-9][0-9]{2,}|-?0x[0-9a-f]{3,}") -re_imm = re.compile(r"(\b|-)([0-9]+|0x[0-9a-fA-F]+)\b(?!\(sp)|%(lo|hi)\([^)]*\)") -forbidden = set(string.ascii_letters + "_") -branch_likely_instructions = { - "beql", - "bnel", - "beqzl", - "bnezl", - "bgezl", - "bgtzl", - "blezl", - "bltzl", - "bc1tl", - "bc1fl", -} -branch_instructions = branch_likely_instructions.union( - {"b", "beq", "bne", "beqz", "bnez", "bgez", "bgtz", "blez", "bltz", "bc1t", "bc1f"} -) -jump_instructions = branch_instructions.union({"jal", "j"}) +if arch == "mips": + re_int = re.compile(r"[0-9]+") + re_comment = re.compile(r"<.*?>") + re_reg = re.compile(r"\$?\b(a[0-3]|t[0-9]|s[0-8]|at|v[01]|f[12]?[0-9]|f3[01]|k[01]|fp|ra)\b") + re_sprel = re.compile(r"(?<=,)([0-9]+|0x[0-9a-f]+)\(sp\)") + re_large_imm = re.compile(r"-?[1-9][0-9]{2,}|-?0x[0-9a-f]{3,}") + re_imm = re.compile(r"(\b|-)([0-9]+|0x[0-9a-fA-F]+)\b(?!\(sp)|%(lo|hi)\([^)]*\)") + forbidden = set(string.ascii_letters + "_") + branch_likely_instructions = { + "beql", + "bnel", + "beqzl", + "bnezl", + "bgezl", + "bgtzl", + "blezl", + "bltzl", + "bc1tl", + "bc1fl", + } + branch_instructions = branch_likely_instructions.union( + {"b", "beq", "bne", "beqz", "bnez", "bgez", "bgtz", "blez", "bltz", "bc1t", "bc1f"} + ) + instructions_with_address_immediates = branch_instructions.union({"jal", "j"}) +elif arch == "aarch64": + re_int = re.compile(r"[0-9]+") + re_comment = re.compile(r"(<.*?>|//.*$)") + # GPRs and FP registers: X0-X30, W0-W30, [DSHQ]0..31 + # The zero registers and SP should not be in this list. + re_reg = re.compile(r"\$?\b([dshq][12]?[0-9]|[dshq]3[01]|[xw][12]?[0-9]|[xw]30)\b") + re_sprel = re.compile(r"sp, #-?(0x[0-9a-fA-F]+|[0-9]+)\b") + re_large_imm = re.compile(r"-?[1-9][0-9]{2,}|-?0x[0-9a-f]{3,}") + re_imm = re.compile(r"(?:" in row or not row): continue - if "R_MIPS_" in row: - # N.B. Don't transform the diff rows, they already ignore immediates - # if diff_rows[-1] != '': - # diff_rows[-1] = process_reloc(row, rows_with_imms[-1]) - originals[-1] = process_reloc(row, originals[-1]) + if args.source and (row and row[0] != " "): + source_lines.append(row) continue - row = re.sub(re_comments, "", row) + if "R_AARCH64_" in row: + # TODO: handle relocation + continue + + if "R_MIPS_" in row: + # N.B. Don't transform the diff rows, they already ignore immediates + # if output[-1].diff_row != "": + # output[-1] = output[-1].replace(diff_row=process_reloc(row, output[-1].row_with_imm)) + new_original = process_reloc(row, output[-1].original) + output[-1] = output[-1]._replace(original=new_original) + continue + + m_comment = re.search(re_comment, row) + comment = m_comment[0] if m_comment else None + row = re.sub(re_comment, "", row) row = row.rstrip() tabs = row.split("\t") row = "\t".join(tabs[2:]) line_num = tabs[0].strip() row_parts = row.split("\t", 1) mnemonic = row_parts[0].strip() - if mnemonic not in jump_instructions: + if mnemonic not in instructions_with_address_immediates: row = re.sub(re_int, lambda s: hexify_int(row, s), row) original = row if skip_next: @@ -480,38 +594,45 @@ def process(lines): mnemonic = "" if mnemonic in branch_likely_instructions: skip_next = True - row = re.sub(re_regs, "", row) - row = re.sub(re_sprel, ",addr(sp)", row) + row = re.sub(re_reg, "", row) + row = re.sub(re_sprel, "addr(sp)", row) row_with_imm = row - if mnemonic in jump_instructions: + if mnemonic in instructions_with_address_immediates: row = row.strip() row, _ = split_off_branch(row) row += "" else: - row = re.sub(re_imm, "", row) + row = normalize_imms(row) - mnemonics.append(mnemonic) - rows_with_imms.append(row_with_imm) - diff_rows.append(row) - originals.append(original) - line_nums.append(line_num) + branch_target = None if mnemonic in branch_instructions: target = row_parts[1].strip().split(",")[-1] if mnemonic in branch_likely_instructions: target = hex(int(target, 16) - 4)[2:] - branch_targets.append(target) - else: - branch_targets.append(None) + branch_target = target.strip() + + output.append( + Line( + mnemonic=mnemonic, + diff_row=row, + original=original, + line_num=line_num, + branch_target=branch_target, + source_lines=source_lines, + comment=comment, + ) + ) + source_lines = [] + if args.stop_jrra and mnemonic == "jr" and row_parts[1].strip() == "ra": break - # Cleanup whitespace - originals = [original.strip() for original in originals] - originals = [ - "".join(f"{o:<8s}" for o in original.split("\t")) for original in originals + # Cleanup whitespace, after relocation fixups have happened + output = [ + line._replace(original=cleanup_whitespace(line.original)) for line in output ] - # return diff_rows, diff_rows, line_nums - return mnemonics, diff_rows, originals, line_nums, branch_targets + + return output def format_single_line_diff(line1, line2, column_width): @@ -545,7 +666,7 @@ def normalize_imms(row): def normalize_stack(row): - return re.sub(re_sprel, ",addr(sp)", row) + return re.sub(re_sprel, "addr(sp)", row) def split_off_branch(line): @@ -614,20 +735,13 @@ def diff_sequences(seq1, seq2): def do_diff(basedump, mydump): - asm_lines1 = basedump.split("\n") - asm_lines2 = mydump.split("\n") - output = [] # TODO: status line? # output.append(sha1sum(mydump)) - mnemonics1, asm_lines1, originals1, line_nums1, branch_targets1 = process( - asm_lines1 - ) - mnemonics2, asm_lines2, originals2, line_nums2, branch_targets2 = process( - asm_lines2 - ) + lines1 = process(basedump.split("\n")) + lines2 = process(mydump.split("\n")) sc1 = SymbolColorer(0) sc2 = SymbolColorer(0) @@ -639,80 +753,74 @@ def do_diff(basedump, mydump): bts2 = set() if args.show_branches: - for (bts, btset, sc) in [ - (branch_targets1, bts1, sc5), - (branch_targets2, bts2, sc6), + for (lines, btset, sc) in [ + (lines1, bts1, sc5), + (lines2, bts2, sc6), ]: - for bt in bts: + for line in lines: + bt = line.branch_target if bt is not None: btset.add(bt + ":") sc.color_symbol(bt + ":") - for (tag, i1, i2, j1, j2) in diff_sequences(mnemonics1, mnemonics2): - lines1 = asm_lines1[i1:i2] - lines2 = asm_lines2[j1:j2] - - for k, (line1, line2) in enumerate(itertools.zip_longest(lines1, lines2)): + for (tag, i1, i2, j1, j2) in diff_sequences( + [line.mnemonic for line in lines1], [line.mnemonic for line in lines2] + ): + for line1, line2 in itertools.zip_longest(lines1[i1:i2], lines2[j1:j2]): if tag == "replace": if line1 is None: tag = "insert" elif line2 is None: tag = "delete" + elif tag == "insert": + assert line1 is None + elif tag == "delete": + assert line2 is None - try: - original1 = originals1[i1 + k] - line_num1 = line_nums1[i1 + k] - except: - original1 = "" - line_num1 = "" - try: - original2 = originals2[j1 + k] - line_num2 = line_nums2[j1 + k] - except: - original2 = "" - line_num2 = "" - - has1 = has2 = True line_color1 = line_color2 = sym_color = Fore.RESET line_prefix = " " - if line1 == line2: - if not line1: - has1 = has2 = False - if maybe_normalize_large_imms(original1) == maybe_normalize_large_imms( - original2 - ): - out1 = original1 - out2 = original2 - elif line1 == "": - out1 = f"{Style.DIM}{original1}" - out2 = f"{Style.DIM}{original2}" + if line1 and line2 and line1.diff_row == line2.diff_row: + if maybe_normalize_large_imms( + line1.original + ) == maybe_normalize_large_imms(line2.original): + out1 = line1.original + out2 = line2.original + elif line1.diff_row == "": + out1 = f"{Style.BRIGHT}{Fore.LIGHTBLACK_EX}{line1.original}" + out2 = f"{Style.BRIGHT}{Fore.LIGHTBLACK_EX}{line2.original}" else: - mnemonic = original1.split()[0] - out1, out2 = original1, original2 + mnemonic = line1.original.split()[0] + out1, out2 = line1.original, line2.original branch1 = branch2 = "" - if mnemonic in jump_instructions: - out1, branch1 = split_off_branch(original1) - out2, branch2 = split_off_branch(original2) + if mnemonic in instructions_with_address_immediates: + out1, branch1 = split_off_branch(line1.original) + out2, branch2 = split_off_branch(line2.original) branchless1 = out1 branchless2 = out2 out1, out2 = color_imms(out1, out2) - branch1, branch2 = color_branch_imms(branch1, branch2) + + same_relative_target = False + if line1.branch_target is not None and line2.branch_target is not None: + relative_target1 = eval_line_num(line1.branch_target) - eval_line_num(line1.line_num) + relative_target2 = eval_line_num(line2.branch_target) - eval_line_num(line2.line_num) + same_relative_target = relative_target1 == relative_target2 + + if not same_relative_target: + branch1, branch2 = color_branch_imms(branch1, branch2) + out1 += branch1 out2 += branch2 if normalize_imms(branchless1) == normalize_imms(branchless2): - # only imms differences - sym_color = Fore.LIGHTBLUE_EX - line_prefix = "i" + if not same_relative_target: + # only imms differences + sym_color = Fore.LIGHTBLUE_EX + line_prefix = "i" else: out1 = re.sub( - re_sprel, - lambda s: "," + sc3.color_symbol(s.group()[1:]), - out1, + re_sprel, lambda s: sc3.color_symbol(s.group()), out1, ) out2 = re.sub( - re_sprel, - lambda s: "," + sc4.color_symbol(s.group()[1:]), - out2, + re_sprel, lambda s: sc4.color_symbol(s.group()), out2, ) if normalize_stack(branchless1) == normalize_stack(branchless2): # only stack differences (luckily stack and imm @@ -723,61 +831,81 @@ def do_diff(basedump, mydump): else: # regs differences and maybe imms as well out1 = re.sub( - re_regs, lambda s: sc1.color_symbol(s.group()), out1 + re_reg, lambda s: sc1.color_symbol(s.group()), out1 ) out2 = re.sub( - re_regs, lambda s: sc2.color_symbol(s.group()), out2 + re_reg, lambda s: sc2.color_symbol(s.group()), out2 ) line_color1 = line_color2 = sym_color = Fore.YELLOW line_prefix = "r" - elif tag in ["replace", "equal"]: + elif line1 and line2: line_prefix = "|" line_color1 = Fore.LIGHTBLUE_EX line_color2 = Fore.LIGHTBLUE_EX sym_color = Fore.LIGHTBLUE_EX - out1 = original1 - out2 = original2 - elif tag == "delete": + out1 = line1.original + out2 = line2.original + elif line1: line_prefix = "<" line_color1 = line_color2 = sym_color = Fore.RED - has2 = False - out1 = original1 + out1 = line1.original out2 = "" - elif tag == "insert": + elif line2: line_prefix = ">" line_color1 = line_color2 = sym_color = Fore.GREEN - has1 = False out1 = "" - out2 = original2 + out2 = line2.original in_arrow1 = " " in_arrow2 = " " out_arrow1 = "" out_arrow2 = "" - line_num1 = line_num1 if has1 else "" - line_num2 = line_num2 if has2 else "" - if sym_color == line_color2: - line_color2 = "" + if args.show_branches and line1: + if line1.line_num in bts1: + in_arrow1 = sc5.color_symbol(line1.line_num, "~>") + line_color1 + if line1.branch_target is not None: + out_arrow1 = " " + sc5.color_symbol(line1.branch_target + ":", "~>") + if args.show_branches and line2: + if line2.line_num in bts2: + in_arrow2 = sc6.color_symbol(line2.line_num, "~>") + line_color2 + if line2.branch_target is not None: + out_arrow2 = " " + sc6.color_symbol(line2.branch_target + ":", "~>") - if args.show_branches and has1: - if line_num1 in bts1: - in_arrow1 = sc5.color_symbol(line_num1, "~>") + line_color1 - if branch_targets1[i1 + k] is not None: - out_arrow1 = " " + sc5.color_symbol( - branch_targets1[i1 + k] + ":", "~>" - ) - if args.show_branches and has2: - if line_num2 in bts2: - in_arrow2 = sc6.color_symbol(line_num2, "~>") + line_color2 - if branch_targets2[j1 + k] is not None: - out_arrow2 = " " + sc6.color_symbol( - branch_targets2[j1 + k] + ":", "~>" - ) + if args.source and line2 and line2.comment: + out2 += f" {line2.comment}" + + line_num1 = line1.line_num if line1 else "" + line_num2 = line2.line_num if line2 else "" out1 = f"{line_color1}{line_num1} {in_arrow1} {out1}{Style.RESET_ALL}{out_arrow1}" out2 = f"{line_color2}{line_num2} {in_arrow2} {out2}{Style.RESET_ALL}{out_arrow2}" mid = f"{sym_color}{line_prefix} " + + if line2: + for source_line in line2.source_lines: + color = Style.DIM + # File names and function names + if source_line and source_line[0] != "|": + color += Style.BRIGHT + # Function names + if source_line.endswith("():"): + # Underline. Colorama does not provide this feature, unfortunately. + color += "\u001b[4m" + try: + source_line = cxxfilt.demangle( + source_line[:-3], external_only=False + ) + except: + pass + output.append( + format_single_line_diff( + "", + f" {color}{source_line}{Style.RESET_ALL}", + args.column_width, + ) + ) + output.append(format_single_line_diff(out1, mid + out2, args.column_width)) return output[args.skip_lines :] @@ -941,7 +1069,9 @@ class Display: def main(): - if args.diff_obj: + if args.diff_elf_symbol: + make_target, basecmd, mycmd = dump_elf() + elif args.diff_obj: make_target, basecmd, mycmd = dump_objfile() else: make_target, basecmd, mycmd = dump_binary() diff --git a/include/eu_translation.h b/include/eu_translation.h index beb6fa7b..19686825 100644 --- a/include/eu_translation.h +++ b/include/eu_translation.h @@ -1,7 +1,7 @@ #ifndef EU_TRANSLATION_H #define EU_TRANSLATION_H -// PAL changes most text to arrays for each language. This define allows these +// EU changes most text to arrays for each language. This define allows these // differences to be combined. #ifdef VERSION_EU #define LANGUAGE_ARRAY(cmd) cmd[LANGUAGE_FUNCTION] diff --git a/include/object_constants.h b/include/object_constants.h index 671894c6..31e1bb5b 100644 --- a/include/object_constants.h +++ b/include/object_constants.h @@ -634,15 +634,15 @@ #define UKIKI_TEXT_DEFAULT 0 #define UKIKI_TEXT_CAGE_TEXTBOX 1 #define UKIKI_TEXT_GO_TO_CAGE 2 - #define UKIKI_TEXT_STOLE_HAT 3 - #define UKIKI_TEXT_HAS_HAT 4 - #define UKIKI_TEXT_GAVE_HAT_BACK 5 + #define UKIKI_TEXT_STOLE_CAP 3 + #define UKIKI_TEXT_HAS_CAP 4 + #define UKIKI_TEXT_GAVE_CAP_BACK 5 #define UKIKI_TEXT_DO_NOT_LET_GO 6 - #define UKIKI_TEXT_STEAL_HAT 7 + #define UKIKI_TEXT_STEAL_CAP 7 /* oBehParams2ndByte */ #define UKIKI_CAGE 0 - #define UKIKI_HAT 1 + #define UKIKI_CAP 1 /* Animations */ #define UKIKI_ANIM_RUN 0 @@ -660,13 +660,12 @@ #define UKIKI_ANIM_HELD 12 /* oAnimState */ - #define UKIKI_ANIM_STATE_DEFAULT 0 - #define UKIKI_ANIM_STATE_EYE_CLOSED 1 // unused - #define UKIKI_ANIM_STATE_HAT_ON 2 - #define UKIKI_ANIM_STATE_UNUSED 3 // unused, HAT_ON+EYE_CLOSED + #define UKIKI_ANIM_STATE_DEFAULT 0 + #define UKIKI_ANIM_STATE_EYE_CLOSED 1 + #define UKIKI_ANIM_STATE_CAP_ON 2 - /* oUkikiHasHat */ - #define UKIKI_HAT_ON 1 + /* oUkikiHasCap */ + #define UKIKI_CAP_ON 1 /* Ukiki Cage Star */ /* oAction */ diff --git a/include/object_fields.h b/include/object_fields.h index 90aba369..99918cc7 100644 --- a/include/object_fields.h +++ b/include/object_fields.h @@ -509,9 +509,9 @@ #define /*0x0F8*/ oBlueFlameUnkF8 OBJECT_FIELD_F32(0x1C) /* Small Piranha Flame */ -#define /*0x0F4*/ oSmallPiranhaFlameUnkF4 OBJECT_FIELD_F32(0x1B) -#define /*0x0F8*/ oSmallPiranhaFlameUnkF8 OBJECT_FIELD_F32(0x1C) -#define /*0x0FC*/ oSmallPiranhaFlameUnkFC OBJECT_FIELD_S32(0x1D) +#define /*0x0F4*/ oSmallPiranhaFlameStartSpeed OBJECT_FIELD_F32(0x1B) +#define /*0x0F8*/ oSmallPiranhaFlameEndSpeed OBJECT_FIELD_F32(0x1C) +#define /*0x0FC*/ oSmallPiranhaFlameModel OBJECT_FIELD_S32(0x1D) #define /*0x100*/ oSmallPiranhaFlameUnk100 OBJECT_FIELD_S32(0x1E) #define /*0x104*/ oSmallPiranhaFlameUnk104 OBJECT_FIELD_F32(0x1F) @@ -970,7 +970,7 @@ #define /*0x10C*/ oTiltingPyramidMarioOnPlatform OBJECT_FIELD_S32(0x21) /* Toad Message */ -#define /*0x108*/ oToadMessageDialogId OBJECT_FIELD_U32(0x20) +#define /*0x108*/ oToadMessageDialogId OBJECT_FIELD_U32(0x20) #define /*0x10C*/ oToadMessageRecentlyTalked OBJECT_FIELD_S32(0x21) #define /*0x110*/ oToadMessageState OBJECT_FIELD_S32(0x22) @@ -1062,7 +1062,7 @@ #define /*0x1AC*/ oUkikiTextState OBJECT_FIELD_S16(0x49, 0) #define /*0x1AE*/ oUkikiTextboxTimer OBJECT_FIELD_S16(0x49, 1) #define /*0x1B0*/ oUkikiCageSpinTimer OBJECT_FIELD_S16(0x4A, 0) -#define /*0x1B2*/ oUkikiHasHat OBJECT_FIELD_S16(0x4A, 1) +#define /*0x1B2*/ oUkikiHasCap OBJECT_FIELD_S16(0x4A, 1) /* Ukiki Cage*/ #define /*0x088*/ oUkikiCageNextAction OBJECT_FIELD_S32(0x00) @@ -1096,7 +1096,7 @@ #define /*0x0F4*/ oCannonBarrelBubblesUnkF4 OBJECT_FIELD_F32(0x1B) /* Water Level Pillar */ -#define /*0x0F8*/ oWaterLevelPillarUnkF8 OBJECT_FIELD_S32(0x1C) +#define /*0x0F8*/ oWaterLevelPillarDrained OBJECT_FIELD_S32(0x1C) /* Water Level Trigger */ #define /*0x0F4*/ oWaterLevelTriggerUnkF4 OBJECT_FIELD_S32(0x1B) diff --git a/include/segments.h b/include/segments.h index ab4c68d7..0c41045d 100644 --- a/include/segments.h +++ b/include/segments.h @@ -49,12 +49,12 @@ #define SEG_BUFFERS 0x8005C000 // 0x0085000 in size #ifdef BETTERCAMERA -#define SEG_MAIN 0x800F1000 // 0x1328000 in size +#define SEG_MAIN 0x800F1000 // 0x0132800 in size #define SEG_ENGINE 0x80223800 // 0x0017000 in size #define SEG_FRAMEBUFFERS 0x8023A800 // 0x0070800 in size #define SEG_POOL_START 0x802AB000 // 0x0165000 in size #else -#define SEG_MAIN 0x800E1000 // 0x1328000 in size +#define SEG_MAIN 0x800E1000 // 0x0132800 in size #define SEG_ENGINE 0x80213800 // 0x0017000 in size #define SEG_FRAMEBUFFERS 0x8022A800 // 0x0070800 in size #define SEG_POOL_START 0x8029B000 // 0x0165000 in size diff --git a/include/sm64.h b/include/sm64.h index 597734c8..ab806a77 100644 --- a/include/sm64.h +++ b/include/sm64.h @@ -132,7 +132,8 @@ #define MARIO_UNKNOWN_30 0x40000000 #define MARIO_UNKNOWN_31 0x80000000 -#define MARIO_CAP_FLAGS 0x0000001F +#define MARIO_SPECIAL_CAPS (MARIO_VANISH_CAP | MARIO_METAL_CAP | MARIO_WING_CAP) +#define MARIO_CAPS (MARIO_NORMAL_CAP | MARIO_SPECIAL_CAPS) #define ACT_ID_MASK 0x000001FF @@ -183,6 +184,7 @@ #define ACT_COUGHING 0x0C40020A // (0x00A | ACT_FLAG_STATIONARY | ACT_FLAG_IDLE | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT) #define ACT_SHIVERING 0x0C40020B // (0x00B | ACT_FLAG_STATIONARY | ACT_FLAG_IDLE | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT) #define ACT_IN_QUICKSAND 0x0002020D // (0x00D | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE) +#define ACT_UNKNOWN_0002020E 0x0002020E // (0x00E | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE) #define ACT_CROUCHING 0x0C008220 // (0x020 | ACT_FLAG_STATIONARY | ACT_FLAG_SHORT_HITBOX | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT) #define ACT_START_CROUCHING 0x0C008221 // (0x021 | ACT_FLAG_STATIONARY | ACT_FLAG_SHORT_HITBOX | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT) #define ACT_STOP_CROUCHING 0x0C008222 // (0x022 | ACT_FLAG_STATIONARY | ACT_FLAG_SHORT_HITBOX | ACT_FLAG_ALLOW_FIRST_PERSON | ACT_FLAG_PAUSE_EXIT) diff --git a/include/types.h b/include/types.h index 88565f50..f2014682 100644 --- a/include/types.h +++ b/include/types.h @@ -92,11 +92,11 @@ struct VblankHandler struct Animation { /*0x00*/ s16 flags; - /*0x02*/ s16 unk02; - /*0x04*/ s16 unk04; - /*0x06*/ s16 unk06; - /*0x08*/ s16 unk08; - /*0x0A*/ s16 unk0A; + /*0x02*/ s16 animYTransDivisor; + /*0x04*/ s16 startFrame; + /*0x06*/ s16 loopStart; + /*0x08*/ s16 loopEnd; + /*0x0A*/ s16 unusedBoneCount; /*0x0C*/ const s16 *values; /*0x10*/ const u16 *index; /*0x14*/ u32 length; // only used with Mario animations to determine how much to load. 0 otherwise. @@ -114,8 +114,7 @@ struct GraphNode /*0x10*/ struct GraphNode *children; }; -// struct AnimInfo? -struct GraphNodeObject_sub +struct AnimInfo { /*0x00 0x38*/ s16 animID; /*0x02 0x3A*/ s16 animYTrans; @@ -134,8 +133,8 @@ struct GraphNodeObject { /*0x00*/ struct GraphNode node; /*0x14*/ struct GraphNode *sharedChild; - /*0x18*/ s8 unk18; - /*0x19*/ s8 unk19; + /*0x18*/ s8 areaIndex; + /*0x19*/ s8 activeAreaIndex; /*0x1A*/ Vec3s angle; /*0x20*/ Vec3f pos; Vec3s prevAngle; @@ -146,7 +145,7 @@ struct GraphNodeObject /*0x2C*/ Vec3f scale; Vec3f prevScale; u32 prevScaleTimestamp; - /*0x38*/ struct GraphNodeObject_sub unk38; + /*0x38*/ struct AnimInfo animInfo; /*0x4C*/ struct SpawnInfo *unk4C; /*0x50*/ Mat4 *throwMatrix; // matrix ptr Mat4 prevThrowMatrix; diff --git a/sm64.ld b/sm64.ld index e6f5c942..382c8422 100755 --- a/sm64.ld +++ b/sm64.ld @@ -420,6 +420,12 @@ SECTIONS /* wildcard doesn't match on EU due to files being moved to engine/ */ BUILD_DIR/src/game*.o(.data*); #endif + BUILD_DIR/src/audio/synthesis.o(.data*); + BUILD_DIR/src/audio/heap.o(.data*); + BUILD_DIR/src/audio/load.o(.data*); + BUILD_DIR/src/audio/playback.o(.data*); + BUILD_DIR/src/audio/effects.o(.data*); + BUILD_DIR/src/audio/seqplayer.o(.data*); BUILD_DIR/src/audio/external.o(.data*); BUILD_DIR/src/audio/port_eu.o(.data*); BUILD_DIR/src/audio/data.o(.data*); diff --git a/src/audio/data.c b/src/audio/data.c index d994f183..15ef5dfa 100644 --- a/src/audio/data.c +++ b/src/audio/data.c @@ -340,11 +340,11 @@ s16 gEuUnknownWave7[256] = { 0x0000, 0x8d2e, 0x4e20, 0xe14e, 0x0000, 0x1eb2, 0xb1e0, 0x72d2, 0x0000, 0x8d2e, 0x4e20, 0xe14e, 0x0000, 0x1eb2, 0xb1e0, 0x72d2, }; -// u8 buffer_remove2[764] = { 0 }; s16 *gWaveSamples[6] = { sSawtoothWaves, sTriangleWaves, sSineWaves, sSquareWaves, sEuUnknownWave6, gEuUnknownWave7 }; -#endif -#ifndef VERSION_EU +#else +// !VERSION_EU + s16 sSineWave[0x40] = { 0, 3211, 6392, 9511, 12539, 15446, 18204, 20787, 23169, 25329, 27244, 28897, 30272, 31356, 32137, 32609, 0x7FFF, 32609, 32137, 31356, 30272, 28897, diff --git a/src/audio/data.h b/src/audio/data.h index 20816d90..b6731145 100644 --- a/src/audio/data.h +++ b/src/audio/data.h @@ -62,8 +62,8 @@ extern f32 gVolRampingRhs128[128]; // non-constant .data extern s16 gTatumsPerBeat; extern s8 gUnusedCount80333EE8; -extern s32 gAudioHeapSize; -extern s32 gAudioInitPoolSize; // amount of heap designated to gAudioInitPool, 0x2500 +extern s32 gAudioHeapSize; // AUDIO_HEAP_SIZE +extern s32 gAudioInitPoolSize; // AUDIO_INIT_POOL_SIZE extern volatile s32 gAudioLoadLock; // .bss diff --git a/src/audio/effects.c b/src/audio/effects.c index bf8c343a..5010cf95 100644 --- a/src/audio/effects.c +++ b/src/audio/effects.c @@ -504,6 +504,7 @@ s32 adsr_update(struct AdsrState *adsr) { return 0.0f; } if (adsr->current > 1.0f) { + eu_stubbed_printf_1("Audio:Envp: overflow %f\n", adsr->current); return 1.0f; } return adsr->current; diff --git a/src/audio/external.c b/src/audio/external.c index 014d3658..ff56563e 100644 --- a/src/audio/external.c +++ b/src/audio/external.c @@ -20,136 +20,6 @@ #define EU_FLOAT(x) x #endif -#ifdef VERSION_EU -u8 audioString1[] = "pitch %x: delaybytes %d : olddelay %d\n"; -u8 audioString2[] = "cont %x: delaybytes %d : olddelay %d\n"; -u8 audioString3[] = "Warning:Kill Note %x \n"; -u8 audioString4[] = "Kill Voice %d (ID %d) %d\n"; -u8 audioString5[] = "Warning: Running Sequence's data disappear!\n"; -u8 audioString6[] = "Heap OverFlow : Not Allocate %d!\n"; -u8 audioString7[] = "DataHeap Not Allocate \n"; -u8 audioString8[] = "StayHeap Not Allocate %d\n"; -u8 audioString9[] = "AutoHeap Not Allocate %d\n"; -u8 audioString10[] = "WARNING: NO FREE AUTOSEQ AREA.\n"; -u8 audioString11[] = "WARNING: NO STOP AUTO AREA.\n"; -u8 audioString12[] = " AND TRY FORCE TO STOP SIDE \n"; -u8 audioString13[] = "TWO SIDES ARE LOADING... ALLOC CANCELED.\n"; -u8 audioString14[] = "WARNING: Before Area Overlaid After."; -u8 audioString15[] = "WARNING: After Area Overlaid Before."; -u8 audioString16[] = "MEMORY:SzHeapAlloc ERROR: sza->side %d\n"; -u8 audioString17[] = "MEMORY:StayHeap OVERFLOW."; -u8 audioString18[] = "MEMORY:StayHeap OVERFLOW (REQ:%d)"; -u8 audioString19[] = "Auto Heap Unhit for ID %d\n"; -u8 audioString20[] = "Cache hit %d at stay %d\n"; -u8 audioString20_[] = "%d "; -u8 audioString20__[] = "\n"; -u8 audioString20___[] = "%d "; -u8 audioString20____[] = "\n"; -u8 audioString21[] = "Heap Reconstruct Start %x\n"; -u8 audioString22[] = "SFrame Sample %d %d %d\n"; -u8 audioString23[] = "AHPBASE %x\n"; -u8 audioString24[] = "AHPCUR %x\n"; -u8 audioString25[] = "HeapTop %x\n"; -u8 audioString26[] = "SynoutRate %d / %d \n"; -u8 audioString27[] = "FXSIZE %d\n"; -u8 audioString28[] = "FXCOMP %d\n"; -u8 audioString29[] = "FXDOWN %d\n"; -u8 audioString30[] = "WaveCacheLen: %d\n"; -u8 audioString31[] = "SpecChange Finished\n"; -u8 audioString31_[] = ""; -u8 audioString32[] = "Romcopy %x -> %x ,size %x\n"; -u8 audioString33[] = "Romcopyend\n"; -u8 audioString34[] = "CAUTION:WAVE CACHE FULL %d"; -u8 audioString35[] = "BASE %x %x\n"; -u8 audioString36[] = "LOAD %x %x %x\n"; -u8 audioString37[] = "INSTTOP %x\n"; -u8 audioString38[] = "INSTMAP[0] %x\n"; -u8 audioString39[] = "already flags %d\n"; -u8 audioString40[] = "already flags %d\n"; -u8 audioString41[] = "ERR:SLOW BANK DMA BUSY\n"; -u8 audioString42[] = "ERR:SLOW DMA BUSY\n"; -u8 audioString43[] = "Check %d bank %d\n"; -u8 audioString44[] = "Cache Check\n"; -u8 audioString45[] = "NO BANK ERROR\n"; -u8 audioString46[] = "BANK %d LOADING START\n"; -u8 audioString47[] = "BANK %d LOAD MISS (NO MEMORY)!\n"; -u8 audioString48[] = "BANK %d ALREADY CACHED\n"; -u8 audioString49[] = "BANK LOAD MISS! FOR %d\n"; -u8 audioString50[] = "Seq %d Loading Start\n"; -u8 audioString51[] = "Heap Overflow Error\n"; -u8 audioString52[] = "SEQ %d ALREADY CACHED\n"; -u8 audioString53[] = "Ok,one bank slow load Start \n"; -u8 audioString54[] = "Sorry,too many %d bank is none.fast load Start \n"; -u8 audioString55[] = "Seq %d:Default Load Id is %d\n"; -u8 audioString56[] = "Seq Loading Start\n"; -u8 audioString57[] = "Error:Before Sequence-SlowDma remain.\n"; -u8 audioString58[] = " Cancel Seq Start.\n"; -u8 audioString59[] = "SEQ %d ALREADY CACHED\n"; -u8 audioString60[] = "Clear Workarea %x -%x size %x \n"; -u8 audioString61[] = "AudioHeap is %x\n"; -u8 audioString62[] = "Heap reset.Synth Change %x \n"; -u8 audioString63[] = "Heap %x %x %x\n"; -u8 audioString64[] = "Main Heap Initialize.\n"; -u8 audioString65[] = "---------- Init Completed. ------------\n"; -u8 audioString66[] = " Syndrv :[%6d]\n"; -u8 audioString67[] = " Seqdrv :[%6d]\n"; -u8 audioString68[] = " audiodata :[%6d]\n"; -u8 audioString69[] = "---------------------------------------\n"; -u8 audioString69_[] = ""; -u8 audioString70[] = "Audio: setvol: volume minus %f\n"; -u8 audioString71[] = "Audio: setvol: volume overflow %f\n"; -u8 audioString72[] = "Audio: setpitch: pitch minus %f\n"; -u8 audioString73[] = "Audio: voiceman: No bank error %d\n"; -u8 audioString74[] = "Audio: voiceman: progNo. overflow %d,%d\n"; -u8 audioString75[] = "Audio: voiceman: progNo. undefined %d,%d\n"; -u8 audioString76[] = "Audio: voiceman: BAD Voicepointer %x,%d,%d\n"; -u8 audioString77[] = "Audio: voiceman: Percussion Overflow %d,%d\n"; -u8 audioString78[] = "Percussion Pointer Error\n"; -u8 audioString79[] = "Audio: voiceman: Percpointer NULL %d,%d\n"; -u8 audioString80[] = "CAUTION:SUB IS SEPARATED FROM GROUP"; -u8 audioString81[] = "Error:Wait Track disappear\n"; -u8 audioString82[] = "Slow Release Batting\n"; -u8 audioString83[] = "Audio:Wavemem: Bad voiceno (%d)\n"; -u8 audioString84[] = "Audio: C-Alloc : Dealloc voice is NULL\n"; -u8 audioString85[] = "Alloc Error:Dim voice-Alloc %d"; -u8 audioString86[] = "Error:Same List Add\n"; -u8 audioString87[] = "Already Cut\n"; -u8 audioString88[] = "Audio: C-Alloc : lowerPrio is NULL\n"; -u8 audioString89[] = "Sub Limited Warning: Drop Voice"; -u8 audioString90[] = "Warning: Drop Voice"; -u8 audioString91[] = "Warning: Drop Voice"; -u8 audioString92[] = "Warning: Drop Voice"; -u8 audioString93[] = "Audio:Envp: overflow %f\n"; -u8 audioString93_[] = ""; -u8 audioString94[] = "Audio:Track:Warning: No Free Notetrack\n"; -u8 audioString95[] = "SUBTRACK DIM\n"; -u8 audioString96[] = "Audio:Track: Warning SUBTRACK PARENT CHANGED\n"; -u8 audioString97[] = "GROUP 0:"; -u8 audioString98[] = "GROUP 1:"; -u8 audioString99[] = "SEQID %d,BANKID %d\n"; -u8 audioString100[] = "ERR:SUBTRACK %d NOT ALLOCATED\n"; -u8 audioString101[] = "Error:Same List Add\n"; -u8 audioString102[] = "Macro Level Over Error!\n"; -u8 audioString103[] = "Macro Level Over Error!\n"; -u8 audioString104[] = "WARNING: NPRG: cannot change %d\n"; -u8 audioString105[] = "Audio:Track:NOTE:UNDEFINED NOTE COM. %x\n"; -u8 audioString106[] = "Audio: Note:Velocity Error %d\n"; -u8 audioString107[] = "Error: Your assignchannel is stolen.\n"; -u8 audioString108[] = "Audio:Track :Call Macro Level Over Error!\n"; -u8 audioString109[] = "Audio:Track :Loops Macro Level Over Error!\n"; -u8 audioString110[] = "SUB:ERR:BANK %d NOT CACHED.\n"; -u8 audioString111[] = "SUB:ERR:BANK %d NOT CACHED.\n"; -u8 audioString112[] = "Audio:Track: CTBLCALL Macro Level Over Error!\n"; -u8 audioString113[] = "Err :Sub %x ,address %x:Undefined SubTrack Function %x"; -u8 audioString114[] = "Disappear Sequence or Bank %d\n"; -u8 audioString115[] = "Macro Level Over Error!\n"; -u8 audioString116[] = "Macro Level Over Error!\n"; -u8 audioString117[] = "Group:Undefine upper C0h command (%x)\n"; -u8 audioString118[] = "Group:Undefined Command\n"; -u8 audioString118_[] = ""; -u8 audioString118__[] = ""; -#endif - // N.B. sound banks are different from the audio banks referred to in other // files. We should really fix our naming to be less ambiguous... #define MAX_BG_MUSIC_QUEUE_SIZE 6 @@ -161,15 +31,6 @@ u8 audioString118__[] = ""; #define SAMPLES_TO_OVERPRODUCE 0x10 #define EXTRA_BUFFERED_AI_SAMPLES_TARGET 0x40 -// No-op printf macro which leaves string literals in rodata in IDO. (IDO -// doesn't support variadic macros, so instead they let the parameter list -// expand to a no-op comma expression.) See also goddard/gd_main.h. -#ifdef __sgi -#define stubbed_printf -#else -#define stubbed_printf(...) -#endif - struct Sound { s32 soundBits; f32 *position; diff --git a/src/audio/external.h b/src/audio/external.h index 32ea3400..340498e7 100644 --- a/src/audio/external.h +++ b/src/audio/external.h @@ -21,6 +21,9 @@ extern s32 gAudioErrorFlags; extern f32 gDefaultSoundArgs[3]; +// defined in data.c, used by the game +extern u32 gAudioRandom; + extern u8 gAudioSPTaskYieldBuffer[]; // ucode yield data ptr; only used in JP struct SPTask *create_next_audio_frame_task(void); diff --git a/src/audio/heap.c b/src/audio/heap.c index 5940f415..7c10991c 100644 --- a/src/audio/heap.c +++ b/src/audio/heap.c @@ -168,11 +168,17 @@ void discard_bank(s32 bankId) { struct Note *note = &gNotes[i]; #ifdef VERSION_EU - if (note->noteSubEu.bankId == bankId) { + if (note->noteSubEu.bankId == bankId) #else - if (note->bankId == bankId) { + if (note->bankId == bankId) #endif + { + // (These prints are unclear. Arguments are picked semi-randomly.) + eu_stubbed_printf_1("Warning:Kill Note %x \n", i); if (note->priority >= NOTE_PRIORITY_MIN) { + eu_stubbed_printf_3("Kill Voice %d (ID %d) %d\n", note->waveId, + bankId, note->priority); + eu_stubbed_printf_0("Warning: Running Sequence's data disappear!\n"); note->parentLayer->enabled = FALSE; note->parentLayer->finished = TRUE; } @@ -310,7 +316,7 @@ static void unused_803163D4(void) { void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg3, s32 id) { // arg3 = 0, 1 or 2? - struct TemporaryPool *tp; // sp30 + struct TemporaryPool *tp; struct PersistentPool *persistent = &arg0->persistent; struct SoundAllocPool *pool; void *ret; @@ -343,17 +349,17 @@ void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg isSound = TRUE; } - firstVal = (tp->entries[0].id == (s8)nullID ? SOUND_LOAD_STATUS_NOT_LOADED : table[tp->entries[0].id]); // a3, a2 - secondVal = (tp->entries[1].id == (s8)nullID ? SOUND_LOAD_STATUS_NOT_LOADED : table[tp->entries[1].id]); // a1 + firstVal = (tp->entries[0].id == (s8)nullID ? SOUND_LOAD_STATUS_NOT_LOADED : table[tp->entries[0].id]); + secondVal = (tp->entries[1].id == (s8)nullID ? SOUND_LOAD_STATUS_NOT_LOADED : table[tp->entries[1].id]); #ifndef VERSION_EU leftNotLoaded = (firstVal == SOUND_LOAD_STATUS_NOT_LOADED); - leftDiscardable = (firstVal == SOUND_LOAD_STATUS_DISCARDABLE); // t0 + leftDiscardable = (firstVal == SOUND_LOAD_STATUS_DISCARDABLE); leftAvail = (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS); rightNotLoaded = (secondVal == SOUND_LOAD_STATUS_NOT_LOADED); rightDiscardable = (secondVal == SOUND_LOAD_STATUS_DISCARDABLE); rightAvail = (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS); - bothDiscardable = (leftDiscardable && rightDiscardable); // a0 + bothDiscardable = (leftDiscardable && rightDiscardable); if (leftNotLoaded) { tp->nextSide = 0; @@ -361,7 +367,7 @@ void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg tp->nextSide = 1; } else if (bothDiscardable) { // Use the opposite side from last time. - } else if (firstVal == SOUND_LOAD_STATUS_DISCARDABLE) { //??! + } else if (firstVal == SOUND_LOAD_STATUS_DISCARDABLE) { // ??! (I blame copt) tp->nextSide = 0; } else if (rightDiscardable) { tp->nextSide = 1; @@ -374,27 +380,42 @@ void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg return NULL; } #else + if (0) { + // It's unclear where these string literals go. + eu_stubbed_printf_0("DataHeap Not Allocate \n"); + eu_stubbed_printf_1("StayHeap Not Allocate %d\n", 0); + eu_stubbed_printf_1("AutoHeap Not Allocate %d\n", 0); + } + if (firstVal == SOUND_LOAD_STATUS_NOT_LOADED) { tp->nextSide = 0; } else if (secondVal == SOUND_LOAD_STATUS_NOT_LOADED) { tp->nextSide = 1; - } else if ((firstVal == SOUND_LOAD_STATUS_DISCARDABLE) && (secondVal == SOUND_LOAD_STATUS_DISCARDABLE)) { - // Use the opposite side from last time. - } else if (firstVal == SOUND_LOAD_STATUS_DISCARDABLE) { - tp->nextSide = 0; - } else if (secondVal == SOUND_LOAD_STATUS_DISCARDABLE) { - tp->nextSide = 1; - } else if (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS) { - tp->nextSide = 0; - } else if (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS) { - tp->nextSide = 1; } else { - // Both left and right sides are being loaded into. - return NULL; + eu_stubbed_printf_0("WARNING: NO FREE AUTOSEQ AREA.\n"); + if ((firstVal == SOUND_LOAD_STATUS_DISCARDABLE) && (secondVal == SOUND_LOAD_STATUS_DISCARDABLE)) { + // Use the opposite side from last time. + } else if (firstVal == SOUND_LOAD_STATUS_DISCARDABLE) { + tp->nextSide = 0; + } else if (secondVal == SOUND_LOAD_STATUS_DISCARDABLE) { + tp->nextSide = 1; + } else { + eu_stubbed_printf_0("WARNING: NO STOP AUTO AREA.\n"); + eu_stubbed_printf_0(" AND TRY FORCE TO STOP SIDE \n"); + if (firstVal != SOUND_LOAD_STATUS_IN_PROGRESS) { + tp->nextSide = 0; + } else if (secondVal != SOUND_LOAD_STATUS_IN_PROGRESS) { + tp->nextSide = 1; + } else { + // Both left and right sides are being loaded into. + eu_stubbed_printf_0("TWO SIDES ARE LOADING... ALLOC CANCELED.\n"); + return NULL; + } + } } #endif - pool = &arg0->temporary.pool; // a1 + pool = &arg0->temporary.pool; if (tp->entries[tp->nextSide].id != (s8)nullID) { table[tp->entries[tp->nextSide].id] = SOUND_LOAD_STATUS_NOT_LOADED; if (isSound == TRUE) { @@ -411,6 +432,8 @@ void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg pool->cur = pool->start + size; if (tp->entries[1].ptr < pool->cur) { + eu_stubbed_printf_0("WARNING: Before Area Overlaid After."); + // Throw out the entry on the other side if it doesn't fit. // (possible @bug: what if it's currently being loaded?) table[tp->entries[1].id] = SOUND_LOAD_STATUS_NOT_LOADED; @@ -445,6 +468,8 @@ void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg tp->entries[1].size = size; if (tp->entries[1].ptr < pool->cur) { + eu_stubbed_printf_0("WARNING: After Area Overlaid Before."); + table[tp->entries[0].id] = SOUND_LOAD_STATUS_NOT_LOADED; switch (isSound) { @@ -464,6 +489,7 @@ void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg break; default: + eu_stubbed_printf_1("MEMORY:SzHeapAlloc ERROR: sza->side %d\n", tp->nextSide); return NULL; } @@ -487,6 +513,7 @@ void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg { switch (arg3) { case 2: + eu_stubbed_printf_0("MEMORY:StayHeap OVERFLOW."); #ifdef VERSION_EU return alloc_bank_or_seq(arg0, arg1, size, 0, id); #else @@ -495,6 +522,7 @@ void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg return ret; #endif case 1: + eu_stubbed_printf_1("MEMORY:StayHeap OVERFLOW (REQ:%d)", arg1 * size); return NULL; } } @@ -524,11 +552,13 @@ void *get_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 id) { temporary->nextSide = 0; return temporary->entries[1].ptr; } + eu_stubbed_printf_1("Auto Heap Unhit for ID %d\n", id); return NULL; } else { struct PersistentPool *persistent = &arg0->persistent; for (i = 0; i < persistent->numEntries; i++) { if (id == persistent->entries[i].id) { + eu_stubbed_printf_2("Cache hit %d at stay %d\n", id, i); return persistent->entries[i].ptr; } } @@ -538,7 +568,7 @@ void *get_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 id) { return get_bank_or_seq(arg0, 0, id); #else // Prevent tail call optimization by using a temporary. - // (Did they compile with -Wo,-notail?) + // Either copt or -Wo,-notail. ret = get_bank_or_seq(arg0, 0, id); return ret; #endif @@ -568,25 +598,27 @@ void func_eu_802e27e4_unused(f32 arg0, f32 arg1, u16 *arg2) { } for (i = 0; i < 8; i++) { + eu_stubbed_printf_1("%d ", arg2[i]); } + eu_stubbed_printf_0("\n"); - for (i = 8; i < 16; i += 4) { + for (i = 8; i < 16; i++) { + eu_stubbed_printf_1("%d ", arg2[i]); } + eu_stubbed_printf_0("\n"); } #endif -#ifdef VERSION_EU void decrease_reverb_gain(void) { +#ifdef VERSION_EU s32 i; for (i = 0; i < gNumSynthesisReverbs; i++) { gSynthesisReverbs[i].reverbGain -= gSynthesisReverbs[i].reverbGain / 8; } -} #else -void decrease_reverb_gain(void) { gSynthesisReverb.reverbGain -= gSynthesisReverb.reverbGain / 4; -} #endif +} #ifdef VERSION_EU s32 audio_shut_down_and_reset_step(void) { @@ -676,10 +708,10 @@ void audio_reset_session(void) { #ifndef VERSION_EU s32 frames; s32 remainingDmas; -#endif -#ifdef VERSION_EU +#else struct SynthesisReverb *reverb; #endif + eu_stubbed_printf_1("Heap Reconstruct Start %x\n", gAudioResetPresetIdToLoad); #ifndef VERSION_EU if (gAudioLoadLock != AUDIO_LOCK_UNINITIALIZED) { @@ -933,3 +965,16 @@ void audio_reset_session(void) { } #endif } + +#ifdef VERSION_EU +u8 audioString22[] = "SFrame Sample %d %d %d\n"; +u8 audioString23[] = "AHPBASE %x\n"; +u8 audioString24[] = "AHPCUR %x\n"; +u8 audioString25[] = "HeapTop %x\n"; +u8 audioString26[] = "SynoutRate %d / %d \n"; +u8 audioString27[] = "FXSIZE %d\n"; +u8 audioString28[] = "FXCOMP %d\n"; +u8 audioString29[] = "FXDOWN %d\n"; +u8 audioString30[] = "WaveCacheLen: %d\n"; +u8 audioString31[] = "SpecChange Finished\n"; +#endif diff --git a/src/audio/internal.h b/src/audio/internal.h index 1fbe2a2e..3faa4c4d 100644 --- a/src/audio/internal.h +++ b/src/audio/internal.h @@ -63,6 +63,29 @@ #define FLOAT_CAST(x) (f32) (s32) (x) #endif +// No-op printf macro which leaves string literals in rodata in IDO. IDO +// doesn't support variadic macros, so instead we let the parameter list +// expand to a no-op comma expression. Another possibility is that it might +// have expanded to something with "if (0)". See also goddard/gd_main.h. +// On US/JP, -sopt optimizes away these except for external.c. +#ifdef __sgi +#define stubbed_printf +#else +#define stubbed_printf(...) +#endif + +#ifdef VERSION_EU +#define eu_stubbed_printf_0(msg) stubbed_printf(msg) +#define eu_stubbed_printf_1(msg, a) stubbed_printf(msg, a) +#define eu_stubbed_printf_2(msg, a, b) stubbed_printf(msg, a, b) +#define eu_stubbed_printf_3(msg, a, b, c) stubbed_printf(msg, a, b, c) +#else +#define eu_stubbed_printf_0(msg) +#define eu_stubbed_printf_1(msg, a) +#define eu_stubbed_printf_2(msg, a, b) +#define eu_stubbed_printf_3(msg, a, b, c) +#endif + struct NotePool; struct AudioListItem @@ -202,6 +225,7 @@ struct M64ScriptState { u8 depth; }; // size = 0x1C +// Also known as a Group, according to debug strings. struct SequencePlayer { /*US/JP, EU */ @@ -327,6 +351,8 @@ struct NoteAttributes #endif }; // size = 0x10 +// Also known as a SubTrack, according to debug strings. +// Confusingly, a SubTrack is a container of Tracks. struct SequenceChannel { /* U/J, EU */ @@ -395,7 +421,8 @@ struct SequenceChannel /*0x80, 0x84*/ struct NotePool notePool; }; // size = 0xC0, 0xC4 in EU -struct SequenceChannelLayer // Maybe SequenceTrack? +// Also known as a Track, according to debug strings. +struct SequenceChannelLayer { /* U/J, EU */ /*0x00, 0x00*/ u8 enabled : 1; @@ -508,6 +535,16 @@ struct Note /* U/J, EU */ /*0xA4, 0x00*/ struct AudioListItem listItem; /* 0x10*/ struct NoteSynthesisState synthesisState; + + // The next members are actually part of a struct (NotePlaybackState), but + // that results in messy US/EU ifdefs. Instead we cast to a struct pointer + // when needed... This breaks alignment on non-N64 platforms, which we hack + // around by skipping the padding in that case. + // TODO: use macros or something instead. +#ifdef TARGET_N64 + u8 pad0[12]; +#endif + /*0x04, 0x30*/ u8 priority; /* 0x31*/ u8 waveId; /* 0x32*/ u8 sampleCountIndex; @@ -525,6 +562,7 @@ struct Note /* , 0xB0*/ struct NoteSubEu noteSubEu; }; // size = 0xC0 #else +// volatile Note, needed in synthesis_process_notes struct vNote { /* U/J, EU */ diff --git a/src/audio/load.c b/src/audio/load.c index d809592c..470de682 100644 --- a/src/audio/load.c +++ b/src/audio/load.c @@ -112,12 +112,33 @@ extern u8 gBankSetsData[]; // bank_sets.s * Performs an immediate DMA copy */ void audio_dma_copy_immediate(uintptr_t devAddr, void *vAddr, size_t nbytes) { + eu_stubbed_printf_3("Romcopy %x -> %x ,size %x\n", devAddr, vAddr, nbytes); osInvalDCache(vAddr, nbytes); osPiStartDma(&gAudioDmaIoMesg, OS_MESG_PRI_HIGH, OS_READ, devAddr, vAddr, nbytes, &gAudioDmaMesgQueue); osRecvMesg(&gAudioDmaMesgQueue, NULL, OS_MESG_BLOCK); + eu_stubbed_printf_0("Romcopyend\n"); } +#ifdef VERSION_EU +u8 audioString34[] = "CAUTION:WAVE CACHE FULL %d"; +u8 audioString35[] = "BASE %x %x\n"; +u8 audioString36[] = "LOAD %x %x %x\n"; +u8 audioString37[] = "INSTTOP %x\n"; +u8 audioString38[] = "INSTMAP[0] %x\n"; +u8 audioString39[] = "already flags %d\n"; +u8 audioString40[] = "already flags %d\n"; +u8 audioString41[] = "ERR:SLOW BANK DMA BUSY\n"; +u8 audioString42[] = "ERR:SLOW DMA BUSY\n"; +u8 audioString43[] = "Check %d bank %d\n"; +u8 audioString44[] = "Cache Check\n"; +u8 audioString45[] = "NO BANK ERROR\n"; +u8 audioString46[] = "BANK %d LOADING START\n"; +u8 audioString47[] = "BANK %d LOAD MISS (NO MEMORY)!\n"; +u8 audioString48[] = "BANK %d ALREADY CACHED\n"; +u8 audioString49[] = "BANK LOAD MISS! FOR %d\n"; +#endif + /** * Performs an asynchronus (normal priority) DMA copy */ @@ -664,11 +685,13 @@ void *sequence_dma_async(s32 seqId, s32 arg1, struct SequencePlayer *seqPlayer) u8 *seqData; OSMesgQueue *mesgQueue; + eu_stubbed_printf_1("Seq %d Loading Start\n", seqId); seqLength = gSeqFileHeader->seqArray[seqId].len + 0xf; seqLength = ALIGN16(seqLength); seqData = gSeqFileHeader->seqArray[seqId].offset; ptr = alloc_bank_or_seq(&gSeqLoadedPool, 1, seqLength, arg1, seqId); if (ptr == NULL) { + eu_stubbed_printf_0("Heap Overflow Error\n"); return NULL; } @@ -676,8 +699,8 @@ void *sequence_dma_async(s32 seqId, s32 arg1, struct SequencePlayer *seqPlayer) // Immediately load short sequenece audio_dma_copy_immediate((uintptr_t) seqData, ptr, seqLength); if (1) { - gSeqLoadStatus[seqId] = SOUND_LOAD_STATUS_COMPLETE; } + gSeqLoadStatus[seqId] = SOUND_LOAD_STATUS_COMPLETE; } else { audio_dma_copy_immediate((uintptr_t) seqData, ptr, 0x40); mesgQueue = &seqPlayer->seqDmaMesgQueue; @@ -740,12 +763,12 @@ struct AudioBank *load_banks_immediate(s32 seqId, u8 *arg1) { u16 offset; u8 i; -#ifdef VERSION_EU offset = ((u16 *) gAlBankSets)[seqId]; +#ifdef VERSION_EU for (i = gAlBankSets[offset++]; i != 0; i--) { bankId = gAlBankSets[offset++]; #else - offset = ((u16 *) gAlBankSets)[seqId] + 1; + offset++; for (i = gAlBankSets[offset - 1]; i != 0; i--) { offset++; bankId = gAlBankSets[offset - 1]; @@ -785,6 +808,7 @@ void preload_sequence(u32 seqId, u8 preloadMask) { if (preloadMask & PRELOAD_SEQUENCE) { // @bug should be IS_SEQ_LOAD_COMPLETE if (IS_BANK_LOAD_COMPLETE(seqId) == TRUE) { + eu_stubbed_printf_1("SEQ %d ALREADY CACHED\n", seqId); sequenceData = get_bank_or_seq(&gSeqLoadedPool, 2, seqId); } else { sequenceData = NULL; @@ -826,6 +850,7 @@ void load_sequence_internal(u32 player, u32 seqId, s32 loadAsync) { s32 dummy = 0; s32 bankId = get_missing_bank(seqId, &dummy, &numMissingBanks); if (numMissingBanks == 1) { + eu_stubbed_printf_0("Ok,one bank slow load Start \n"); if (bank_load_async(bankId, 2, seqPlayer) == NULL) { return; } @@ -833,17 +858,25 @@ void load_sequence_internal(u32 player, u32 seqId, s32 loadAsync) { // as default, not the missing one. This code path never gets // taken, though -- all sequence loading is synchronous. seqPlayer->defaultBank[0] = bankId; - } else if (load_banks_immediate(seqId, &seqPlayer->defaultBank[0]) == NULL) { - return; + } else { + eu_stubbed_printf_1("Sorry,too many %d bank is none.fast load Start \n", numMissingBanks); + if (load_banks_immediate(seqId, &seqPlayer->defaultBank[0]) == NULL) { + return; + } } } else if (load_banks_immediate(seqId, &seqPlayer->defaultBank[0]) == NULL) { return; } + eu_stubbed_printf_2("Seq %d:Default Load Id is %d\n", seqId, seqPlayer->defaultBank[0]); + eu_stubbed_printf_0("Seq Loading Start\n"); + seqPlayer->seqId = seqId; sequenceData = get_bank_or_seq(&gSeqLoadedPool, 2, seqId); if (sequenceData == NULL) { if (seqPlayer->seqDmaInProgress) { + eu_stubbed_printf_0("Error:Before Sequence-SlowDma remain.\n"); + eu_stubbed_printf_0(" Cancel Seq Start.\n"); return; } @@ -858,6 +891,7 @@ void load_sequence_internal(u32 player, u32 seqId, s32 loadAsync) { } } + eu_stubbed_printf_1("SEQ %d ALREADY CACHED\n", seqId); init_sequence_player(player); seqPlayer->scriptState.depth = 0; seqPlayer->delay = 0; @@ -927,6 +961,16 @@ void audio_init() { } #endif +#ifdef TARGET_N64 + eu_stubbed_printf_3("Clear Workarea %x -%x size %x \n", + (uintptr_t) &gAudioGlobalsStartMarker, + (uintptr_t) &gAudioGlobalsEndMarker, + (uintptr_t) &gAudioGlobalsEndMarker - (uintptr_t) &gAudioGlobalsStartMarker + ); +#endif + + eu_stubbed_printf_1("AudioHeap is %x\n", gAudioHeapSize); + for (i = 0; i < NUMAIBUFFERS; i++) { gAiBufferLengths[i] = 0xa0; } @@ -959,6 +1003,11 @@ void audio_init() { audio_reset_session(&gAudioSessionPresets[0]); #endif + // Not sure about these prints + eu_stubbed_printf_1("Heap reset.Synth Change %x \n", 0); + eu_stubbed_printf_3("Heap %x %x %x\n", 0, 0, 0); + eu_stubbed_printf_0("Main Heap Initialize.\n"); + // Load header for sequence data (assets/music_data.sbk.s) gSeqFileHeader = (ALSeqFile *) buf; data = LOAD_DATA(gMusicData); @@ -1003,5 +1052,12 @@ void audio_init() { init_sequence_players(); gAudioLoadLock = AUDIO_LOCK_NOT_LOADING; -} + // Should probably contain the sizes of the data banks, but those aren't + // easily accessible from here. + eu_stubbed_printf_0("---------- Init Completed. ------------\n"); + eu_stubbed_printf_1(" Syndrv :[%6d]\n", 0); // gSoundDataADSR + eu_stubbed_printf_1(" Seqdrv :[%6d]\n", 0); // gMusicData + eu_stubbed_printf_1(" audiodata :[%6d]\n", 0); // gSoundDataRaw + eu_stubbed_printf_0("---------------------------------------\n"); +} diff --git a/src/audio/load.h b/src/audio/load.h index 9003d7a7..d87a6987 100644 --- a/src/audio/load.h +++ b/src/audio/load.h @@ -31,6 +31,7 @@ extern struct NotePool gNoteFreeLists; extern OSMesgQueue gCurrAudioFrameDmaQueue; extern u32 gSampleDmaNumListItems; extern ALSeqFile *gAlTbl; +extern ALSeqFile *gSeqFileHeader; extern u8 *gAlBankSets; extern struct CtlEntry *gCtlEntries; diff --git a/src/audio/playback.c b/src/audio/playback.c index b34089db..afb62305 100644 --- a/src/audio/playback.c +++ b/src/audio/playback.c @@ -55,8 +55,14 @@ void note_set_vel_pan_reverb(struct Note *note, f32 velocity, u8 pan, u8 reverb) volRight = gDefaultPanVolume[127 - pan]; } - velocity = MAX(0.0f, velocity); - velocity = MIN(32767.f, velocity); + if (velocity < 0.0f) { + stubbed_printf("Audio: setvol: volume minus %f\n", velocity); + velocity = 0.0f; + } + if (velocity > 32767.f) { + stubbed_printf("Audio: setvol: volume overflow %f\n", velocity); + velocity = 32767.f; + } sub->targetVolLeft = ((s32) (velocity * volLeft) & 0xffff) >> 5; sub->targetVolRight = ((s32) (velocity * volRight) & 0xffff) >> 5; @@ -79,6 +85,7 @@ void note_set_resampling_rate(struct Note *note, f32 resamplingRateInput) { struct NoteSubEu *tempSub = ¬e->noteSubEu; if (resamplingRateInput < 0.0f) { + stubbed_printf("Audio: setpitch: pitch minus %f\n", resamplingRateInput); resamplingRateInput = 0.0f; } if (resamplingRateInput < 2.0f) { @@ -117,17 +124,21 @@ struct Instrument *get_instrument_inner(s32 bankId, s32 instId) { struct Instrument *inst; if (IS_BANK_LOAD_COMPLETE(bankId) == FALSE) { + stubbed_printf("Audio: voiceman: No bank error %d\n", bankId); gAudioErrorFlags = bankId + 0x10000000; return NULL; } if (instId >= gCtlEntries[bankId].numInstruments) { + stubbed_printf("Audio: voiceman: progNo. overflow %d,%d\n", + instId, gCtlEntries[bankId].numInstruments); gAudioErrorFlags = ((bankId << 8) + instId) + 0x3000000; return NULL; } inst = gCtlEntries[bankId].instruments[instId]; if (inst == NULL) { + stubbed_printf("Audio: voiceman: progNo. undefined %d,%d\n", bankId, instId); gAudioErrorFlags = ((bankId << 8) + instId) + 0x1000000; return inst; } @@ -141,6 +152,7 @@ struct Instrument *get_instrument_inner(s32 bankId, s32 instId) { return inst; } + stubbed_printf("Audio: voiceman: BAD Voicepointer %x,%d,%d\n", inst, bankId, instId); gAudioErrorFlags = ((bankId << 8) + instId) + 0x2000000; return NULL; } @@ -148,11 +160,14 @@ struct Instrument *get_instrument_inner(s32 bankId, s32 instId) { struct Drum *get_drum(s32 bankId, s32 drumId) { struct Drum *drum; if (drumId >= gCtlEntries[bankId].numDrums) { + stubbed_printf("Audio: voiceman: Percussion Overflow %d,%d\n", + drumId, gCtlEntries[bankId].numDrums); gAudioErrorFlags = ((bankId << 8) + drumId) + 0x4000000; - return 0; + return NULL; } drum = gCtlEntries[bankId].drums[drumId]; if (drum == NULL) { + stubbed_printf("Audio: voiceman: Percpointer NULL %d,%d\n", bankId, drumId); gAudioErrorFlags = ((bankId << 8) + drumId) + 0x5000000; } return drum; @@ -227,8 +242,8 @@ void process_notes(void) { #endif s32 i; - // Macro versions of audio_list_push_front and audio_list_remove - // (PREPEND does not actually need to be a macro, but it seems likely.) + // Macro versions of audio_list_push_front and audio_list_remove. + // Should ideally be changed to use copt. #define PREPEND(item, head_arg) \ ((it = (item), it->prev != NULL) \ ? it \ @@ -247,6 +262,7 @@ void process_notes(void) { if (!playbackState->parentLayer->enabled && playbackState->priority >= NOTE_PRIORITY_MIN) { goto c; } else if (playbackState->parentLayer->seqChannel->seqPlayer == NULL) { + eu_stubbed_printf_0("CAUTION:SUB IS SEPARATED FROM GROUP"); sequence_channel_disable(playbackState->parentLayer->seqChannel); playbackState->priority = NOTE_PRIORITY_STOPPING; continue; @@ -282,6 +298,7 @@ void process_notes(void) { playbackState->wantedParentLayer = NO_LAYER; // don't skip } else { + eu_stubbed_printf_0("Error:Wait Track disappear\n"); note_disable(note); audio_list_remove(¬e->listItem); audio_list_push_back(¬e->listItem.pool->disabled, ¬e->listItem); @@ -425,7 +442,10 @@ void seq_channel_layer_decay_release_internal(struct SequenceChannelLayer *seqLa if (note->parentLayer != seqLayer) { #ifdef VERSION_EU - if (note->parentLayer == NO_LAYER && note->wantedParentLayer == NO_LAYER && note->prevParentLayer == seqLayer && target != ADSR_STATE_DECAY) { + if (note->parentLayer == NO_LAYER && note->wantedParentLayer == NO_LAYER && + note->prevParentLayer == seqLayer && target != ADSR_STATE_DECAY) { + // Just guessing that this printf goes here... it's hard to parse. + eu_stubbed_printf_0("Slow Release Batting\n"); note->adsr.fadeOutVel = gAudioBufferParameters.updatesPerFrameInv; note->adsr.action |= ADSR_ACTION_RELEASE; } @@ -493,6 +513,7 @@ s32 build_synthetic_wave(struct Note *note, struct SequenceChannelLayer *seqLaye u8 sampleCountIndex; if (waveId < 128) { + stubbed_printf("Audio:Wavemem: Bad voiceno (%d)\n", waveId); waveId = 128; } @@ -521,6 +542,7 @@ s32 build_synthetic_wave(struct Note *note, struct SequenceChannelLayer *seqLaye return sampleCountIndex; } + #else void build_synthetic_wave(struct Note *note, struct SequenceChannelLayer *seqLayer) { s32 i; @@ -661,7 +683,11 @@ void note_pool_clear(struct NotePool *pool) { #ifdef VERSION_EU for (;;) { cur = source->next; - if (cur == source || cur == NULL) { + if (cur == source) { + break; + } + if (cur == NULL) { + eu_stubbed_printf_0("Audio: C-Alloc : Dealloc voice is NULL\n"); break; } audio_list_remove(cur); @@ -693,6 +719,7 @@ void note_pool_fill(struct NotePool *pool, s32 count) { for (i = 0, j = 0; j < count; i++) { if (i == 4) { + eu_stubbed_printf_1("Alloc Error:Dim voice-Alloc %d", count); return; } @@ -731,7 +758,9 @@ void note_pool_fill(struct NotePool *pool, s32 count) { void audio_list_push_front(struct AudioListItem *list, struct AudioListItem *item) { // add 'item' to the front of the list given by 'list', if it's not in any list - if (item->prev == NULL) { + if (item->prev != NULL) { + eu_stubbed_printf_0("Error:Same List Add\n"); + } else { item->prev = list; item->next = list->next; list->next->prev = item; @@ -743,14 +772,16 @@ void audio_list_push_front(struct AudioListItem *list, struct AudioListItem *ite void audio_list_remove(struct AudioListItem *item) { // remove 'item' from the list it's in, if any - if (item->prev != NULL) { + if (item->prev == NULL) { + eu_stubbed_printf_0("Already Cut\n"); + } else { item->prev->next = item->next; item->next->prev = item->prev; item->prev = NULL; } } -struct Note *pop_node_with_value_less_equal(struct AudioListItem *list, s32 limit) { +struct Note *pop_node_with_lower_prio(struct AudioListItem *list, s32 limit) { struct AudioListItem *cur = list->next; struct AudioListItem *best; @@ -884,8 +915,10 @@ struct Note *alloc_note_from_decaying(struct NotePool *pool, struct SequenceChan struct Note *alloc_note_from_active(struct NotePool *pool, struct SequenceChannelLayer *seqLayer) { struct Note *note = - pop_node_with_value_less_equal(&pool->active, seqLayer->seqChannel->notePriority); - if (note != NULL) { + pop_node_with_lower_prio(&pool->active, seqLayer->seqChannel->notePriority); + if (note == NULL) { + eu_stubbed_printf_0("Audio: C-Alloc : lowerPrio is NULL\n"); + } else { func_80319728(note, seqLayer); audio_list_push_back(&pool->releasing, ¬e->listItem); } @@ -918,6 +951,7 @@ struct Note *alloc_note(struct SequenceChannelLayer *seqLayer) { if (!(ret = alloc_note_from_disabled(&seqLayer->seqChannel->notePool, seqLayer)) && !(ret = alloc_note_from_decaying(&seqLayer->seqChannel->notePool, seqLayer)) && !(ret = alloc_note_from_active(&seqLayer->seqChannel->notePool, seqLayer))) { + eu_stubbed_printf_0("Sub Limited Warning: Drop Voice"); seqLayer->status = SOUND_LOAD_STATUS_NOT_LOADED; return NULL; } @@ -931,6 +965,7 @@ struct Note *alloc_note(struct SequenceChannelLayer *seqLayer) { && !(ret = alloc_note_from_decaying(&seqLayer->seqChannel->seqPlayer->notePool, seqLayer)) && !(ret = alloc_note_from_active(&seqLayer->seqChannel->notePool, seqLayer)) && !(ret = alloc_note_from_active(&seqLayer->seqChannel->seqPlayer->notePool, seqLayer))) { + eu_stubbed_printf_0("Warning: Drop Voice"); seqLayer->status = SOUND_LOAD_STATUS_NOT_LOADED; return NULL; } @@ -941,6 +976,7 @@ struct Note *alloc_note(struct SequenceChannelLayer *seqLayer) { if (!(ret = alloc_note_from_disabled(&gNoteFreeLists, seqLayer)) && !(ret = alloc_note_from_decaying(&gNoteFreeLists, seqLayer)) && !(ret = alloc_note_from_active(&gNoteFreeLists, seqLayer))) { + eu_stubbed_printf_0("Warning: Drop Voice"); seqLayer->status = SOUND_LOAD_STATUS_NOT_LOADED; return NULL; } @@ -956,6 +992,7 @@ struct Note *alloc_note(struct SequenceChannelLayer *seqLayer) { && !(ret = alloc_note_from_active(&seqLayer->seqChannel->notePool, seqLayer)) && !(ret = alloc_note_from_active(&seqLayer->seqChannel->seqPlayer->notePool, seqLayer)) && !(ret = alloc_note_from_active(&gNoteFreeLists, seqLayer))) { + eu_stubbed_printf_0("Warning: Drop Voice"); seqLayer->status = SOUND_LOAD_STATUS_NOT_LOADED; return NULL; } @@ -1001,7 +1038,6 @@ void reclaim_notes(void) { } #endif - void note_init_all(void) { struct Note *note; s32 i; diff --git a/src/audio/port_eu.c b/src/audio/port_eu.c index 4fbc74db..8f221dce 100644 --- a/src/audio/port_eu.c +++ b/src/audio/port_eu.c @@ -69,7 +69,6 @@ void eu_process_audio_cmd(struct EuAudioCmd *cmd) { case 0x82: case 0x88: - // load_sequence(arg1, arg2, 0); load_sequence(cmd->u.s.arg1, cmd->u.s.arg2, cmd->u.s.arg3); func_8031D690(cmd->u.s.arg1, cmd->u2.as_s32); break; diff --git a/src/audio/seqplayer.c b/src/audio/seqplayer.c index 098a15bc..d8f01538 100644 --- a/src/audio/seqplayer.c +++ b/src/audio/seqplayer.c @@ -203,6 +203,7 @@ void sequence_player_init_channels(struct SequencePlayer *seqPlayer, u16 channel } seqChannel = allocate_sequence_channel(); if (IS_SEQUENCE_CHANNEL_VALID(seqChannel) == FALSE) { + eu_stubbed_printf_0("Audio:Track:Warning: No Free Notetrack\n"); gAudioErrorFlags = i + 0x10000; seqPlayer->channels[i] = seqChannel; } else { @@ -226,6 +227,7 @@ void sequence_player_disable_channels(struct SequencePlayer *seqPlayer, u16 chan struct SequenceChannel *seqChannel; s32 i; + eu_stubbed_printf_0("SUBTRACK DIM\n"); for (i = 0; i < CHANNELS_MAX; i++) { if (channelBits & 1) { seqChannel = seqPlayer->channels[i]; @@ -235,7 +237,9 @@ void sequence_player_disable_channels(struct SequencePlayer *seqPlayer, u16 chan seqChannel->seqPlayer = NULL; } #ifdef VERSION_EU - if (0) {} + else { + stubbed_printf("Audio:Track: Warning SUBTRACK PARENT CHANGED\n"); + } #endif seqPlayer->channels[i] = &gSequenceChannelNone; } @@ -321,27 +325,30 @@ void sequence_player_disable_channels_extended(struct SequencePlayer* seqPlayer, } } -void sequence_channel_enable(struct SequencePlayer *seqPlayer, u8 channelIndex, void *arg2) { +void sequence_channel_enable(struct SequencePlayer *seqPlayer, u8 channelIndex, void *script) { struct SequenceChannel *seqChannel = seqPlayer->channels[channelIndex]; s32 i; -#ifdef VERSION_EU if (IS_SEQUENCE_CHANNEL_VALID(seqChannel) == FALSE) { +#ifdef VERSION_EU struct SequencePlayer *bgMusic = &gSequencePlayers[0]; struct SequencePlayer *miscMusic = &gSequencePlayers[1]; if (seqPlayer == bgMusic) { + stubbed_printf("GROUP 0:"); } else if (seqPlayer == miscMusic) { + stubbed_printf("GROUP 1:"); } else { + stubbed_printf("SEQID %d,BANKID %d\n", + seqPlayer->seqId, seqPlayer->defaultBank[0]); } - } else { -#else - if (IS_SEQUENCE_CHANNEL_VALID(seqChannel) != FALSE) { + stubbed_printf("ERR:SUBTRACK %d NOT ALLOCATED\n", channelIndex); #endif + } else { seqChannel->enabled = TRUE; seqChannel->finished = FALSE; seqChannel->scriptState.depth = 0; - seqChannel->scriptState.pc = arg2; + seqChannel->scriptState.pc = script; seqChannel->delay = 0; for (i = 0; i < LAYERS_MAX; i++) { if (seqChannel->layers[i] != NULL) { @@ -387,7 +394,9 @@ void sequence_player_disable(struct SequencePlayer *seqPlayer) { * Add an item to the end of a list, if it's not already in any list. */ void audio_list_push_back(struct AudioListItem *list, struct AudioListItem *item) { - if (item->prev == NULL) { + if (item->prev != NULL) { + eu_stubbed_printf_0("Error:Same List Add\n"); + } else { list->prev->next = item; item->prev = list->prev; item->next = list; @@ -577,12 +586,18 @@ void seq_channel_layer_process_script(struct SequenceChannelLayer *layer) { break; case 0xfc: // layer_call + if (0 && state->depth >= 4) { + eu_stubbed_printf_0("Macro Level Over Error!\n"); + } sp3A = m64_read_s16(state); state->stack[state->depth++] = state->pc; state->pc = seqPlayer->seqData + sp3A; break; case 0xf8: // layer_loop; loop start, N iterations (or 256 if N = 0) + if (0 && state->depth >= 4) { + eu_stubbed_printf_0("Macro Level Over Error!\n"); + } state->remLoopIters[state->depth] = m64_read_u8(state); state->stack[state->depth++] = state->pc; break; @@ -669,9 +684,8 @@ void seq_channel_layer_process_script(struct SequenceChannelLayer *layer) { break; } - cmd = get_instrument(seqChannel, cmd, &layer->instrument, &layer->adsr); - layer->instOrWave = cmd; - if (cmd == 0) { + if ((layer->instOrWave = get_instrument(seqChannel, cmd, &layer->instrument, &layer->adsr)) == 0) { + eu_stubbed_printf_1("WARNING: NPRG: cannot change %d\n", cmd); layer->instOrWave = 0xff; } #endif @@ -725,6 +739,9 @@ void seq_channel_layer_process_script(struct SequenceChannelLayer *layer) { case 0xe0: // layer_setshortnotedurationfromtable layer->noteDuration = seqPlayer->shortNoteDurationTable[cmd & 0xf]; break; + default: + eu_stubbed_printf_1("Audio:Track:NOTE:UNDEFINED NOTE COM. %x\n", cmd); + break; } } } @@ -989,6 +1006,10 @@ void seq_channel_layer_process_script(struct SequenceChannelLayer *layer) { } #endif } + +u8 audioString106[] = "Audio: Note:Velocity Error %d\n"; +u8 audioString107[] = "Error: Your assignchannel is stolen.\n"; + #elif defined(NON_MATCHING) // US/JP version with macros to simulate inlining by copt. Edit if you dare. #include "seq_channel_layer_process_script.h" @@ -1084,7 +1105,6 @@ void sequence_channel_set_volume(struct SequenceChannel *seqChannel, u8 volume) } #ifdef NON_MATCHING -//rodata: 0xf3e30 void sequence_channel_process_script(struct SequenceChannel *seqChannel) { struct M64ScriptState *state; struct SequencePlayer *seqPlayer; @@ -1184,6 +1204,9 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) { goto out; #endif case 0xfc: // chan_call + if (0 && state->depth >= 4) { + eu_stubbed_printf_0("Audio:Track :Call Macro Level Over Error!\n"); + } sp5A = m64_read_s16(state); #ifdef VERSION_EU state->stack[state->depth++] = state->pc; @@ -1194,6 +1217,9 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) { break; case 0xf8: // chan_loop; loop start, N iterations (or 256 if N = 0) + if (0 && state->depth >= 4) { + eu_stubbed_printf_0("Audio:Track :Loops Macro Level Over Error!\n"); + } state->remLoopIters[state->depth] = m64_read_u8(state); #ifdef VERSION_EU state->stack[state->depth++] = state->pc; @@ -1230,9 +1256,9 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) { break; #ifdef VERSION_EU - case 0xf4: - case 0xf3: - case 0xf2: + case 0xf4: // chan_jump_rel + case 0xf3: // chan_beqz_rel + case 0xf2: // chan_bltz_rel tempSigned = m64_read_u8(state); if (cmd == 0xf3 && value != 0) break; @@ -1275,7 +1301,7 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) { break; #ifdef VERSION_EU - case 0xeb: + case 0xeb: // chan_setbankandinstr temp = m64_read_u8(state); // Switch to the temp's (0-indexed) bank in this sequence's // bank set. Note that in the binary format (not in the JSON!) @@ -1286,6 +1312,8 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) { // temp should be in a saved register across this call if (get_bank_or_seq(&gBankLoadedPool, 2, temp) != NULL) { seqChannel->bankId = temp; + } else { + eu_stubbed_printf_1("SUB:ERR:BANK %d NOT CACHED.\n", temp); } // fallthrough #endif @@ -1420,6 +1448,8 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) { // temp should be in a saved register across this call if (get_bank_or_seq(&gBankLoadedPool, 2, temp) != NULL) { seqChannel->bankId = temp; + } else { + eu_stubbed_printf_1("SUB:ERR:BANK %d NOT CACHED.\n", temp); } } break; @@ -1479,6 +1509,9 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) { #endif case 0xe4: // chan_dyncall if (value != -1) { + if (0 && state->depth >= 4) { + eu_stubbed_printf_0("Audio:Track: CTBLCALL Macro Level Over Error!\n"); + } u8(*thingy)[2] = *seqChannel->dynTable; #ifdef VERSION_EU state->stack[state->depth++] = state->pc; @@ -1487,6 +1520,9 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) { #endif sp5A = thingy[value][1] + (thingy[value][0] << 8); state->pc = seqPlayer->seqData + sp5A; + if (0 && sp5A >= gSeqFileHeader->seqArray[seqPlayer->seqId].len) { + eu_stubbed_printf_3("Err :Sub %x ,address %x:Undefined SubTrack Function %x", seqChannel, state->pc, sp5A); + } } break; @@ -1531,7 +1567,7 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) { seqChannel->freqScale = 1.0f; break; - case 0xe9: + case 0xe9: // chan_setnotepriority seqChannel->notePriority = m64_read_u8(state); break; #endif @@ -1568,7 +1604,7 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) { break; #ifdef VERSION_EU - case 0x60: + case 0x60: // chan_delayshort seqChannel->delay = loBits; goto out; #endif @@ -1720,6 +1756,7 @@ void sequence_player_process_sequence(struct SequencePlayer *seqPlayer) { // If discarded, bail out. if (IS_SEQ_LOAD_COMPLETE(seqPlayer->seqId) == FALSE || IS_BANK_LOAD_COMPLETE(seqPlayer->defaultBank[0]) == FALSE) { + eu_stubbed_printf_1("Disappear Sequence or Bank %d\n", seqPlayer->seqId); sequence_player_disable(seqPlayer); return; } @@ -1784,6 +1821,9 @@ void sequence_player_process_sequence(struct SequencePlayer *seqPlayer) { case 0xfc: // seq_call u16v = m64_read_s16(state); + if (0 && state->depth >= 4) { + eu_stubbed_printf_0("Macro Level Over Error!\n"); + } #ifdef VERSION_EU state->stack[state->depth++] = state->pc; #else @@ -1793,6 +1833,9 @@ void sequence_player_process_sequence(struct SequencePlayer *seqPlayer) { break; case 0xf8: // seq_loop; loop start, N iterations (or 256 if N = 0) + if (0 && state->depth >= 4) { + eu_stubbed_printf_0("Macro Level Over Error!\n"); + } state->remLoopIters[state->depth] = m64_read_u8(state); #ifdef VERSION_EU state->stack[state->depth++] = state->pc; @@ -2022,6 +2065,10 @@ void sequence_player_process_sequence(struct SequencePlayer *seqPlayer) { case 0xc8: // seq_subtract value = value - m64_read_u8(state); break; + + default: + eu_stubbed_printf_1("Group:Undefine upper C0h command (%x)\n", cmd); + break; } } else { loBits = cmd & 0xf; @@ -2076,6 +2123,10 @@ void sequence_player_process_sequence(struct SequencePlayer *seqPlayer) { case 0xd9: break; #endif + + default: + eu_stubbed_printf_0("Group:Undefined Command\n"); + break; } } } diff --git a/src/audio/synthesis.c b/src/audio/synthesis.c index 1fdd8510..da67e48b 100644 --- a/src/audio/synthesis.c +++ b/src/audio/synthesis.c @@ -72,11 +72,12 @@ f32 gLeftVolRampings[3][1024]; f32 gRightVolRampings[3][1024]; f32 *gCurrentLeftVolRamping; // Points to any of the three left buffers above f32 *gCurrentRightVolRamping; // Points to any of the three right buffers above + +u8 audioString1[] = "pitch %x: delaybytes %d : olddelay %d\n"; +u8 audioString2[] = "cont %x: delaybytes %d : olddelay %d\n"; + #else struct SynthesisReverb gSynthesisReverb; -#endif - -#ifndef VERSION_EU u8 sAudioSynthesisPad[0x20]; #endif @@ -615,8 +616,6 @@ u64 *synthesis_process_notes(s16 *aiBuf, s32 bufLen, u64 *cmd) { u8 *sampleAddr; // sp120, spF4 #endif - // sp6c is a temporary! - #ifdef VERSION_EU s32 samplesLenAdjusted; // 108, spEC // Might have been used to store (samplesLenFixedPoint >> 0x10), but doing so causes strange diff --git a/src/engine/graph_node.c b/src/engine/graph_node.c index 44379e0f..150092e8 100644 --- a/src/engine/graph_node.c +++ b/src/engine/graph_node.c @@ -314,12 +314,12 @@ struct GraphNodeObject *init_graph_node_object(struct AllocOnlyPool *pool, vec3s_copy(graphNode->angle, angle); graphNode->sharedChild = sharedChild; graphNode->throwMatrix = NULL; - graphNode->unk38.animID = 0; - graphNode->unk38.curAnim = NULL; - graphNode->unk38.animFrame = 0; - graphNode->unk38.animFrameAccelAssist = 0; - graphNode->unk38.animAccel = 0x10000; - graphNode->unk38.animTimer = 0; + graphNode->animInfo.animID = 0; + graphNode->animInfo.curAnim = NULL; + graphNode->animInfo.animFrame = 0; + graphNode->animInfo.animFrameAccelAssist = 0; + graphNode->animInfo.animAccel = 0x10000; + graphNode->animInfo.animTimer = 0; graphNode->node.flags |= GRAPH_RENDER_HAS_ANIMATION; } @@ -720,7 +720,7 @@ void geo_obj_init(struct GraphNodeObject *graphNode, void *sharedChild, Vec3f po graphNode->sharedChild = sharedChild; graphNode->unk4C = 0; graphNode->throwMatrix = NULL; - graphNode->unk38.curAnim = NULL; + graphNode->animInfo.curAnim = NULL; graphNode->node.flags |= GRAPH_RENDER_ACTIVE; graphNode->node.flags &= ~GRAPH_RENDER_INVISIBLE; @@ -739,12 +739,12 @@ void geo_obj_init_spawninfo(struct GraphNodeObject *graphNode, struct SpawnInfo graphNode->pos[1] = (f32) spawn->startPos[1]; graphNode->pos[2] = (f32) spawn->startPos[2]; - graphNode->unk18 = spawn->areaIndex; - graphNode->unk19 = spawn->activeAreaIndex; + graphNode->areaIndex = spawn->areaIndex; + graphNode->activeAreaIndex = spawn->activeAreaIndex; graphNode->sharedChild = spawn->unk18; graphNode->unk4C = spawn; graphNode->throwMatrix = NULL; - graphNode->unk38.curAnim = 0; + graphNode->animInfo.curAnim = 0; graphNode->node.flags |= GRAPH_RENDER_ACTIVE; graphNode->node.flags &= ~GRAPH_RENDER_INVISIBLE; @@ -763,11 +763,11 @@ void geo_obj_init_animation(struct GraphNodeObject *graphNode, struct Animation struct Animation **animSegmented = segmented_to_virtual(animPtrAddr); struct Animation *anim = segmented_to_virtual(*animSegmented); - if (graphNode->unk38.curAnim != anim) { - graphNode->unk38.curAnim = anim; - graphNode->unk38.animFrame = anim->unk04 + ((anim->flags & ANIM_FLAG_FORWARD) ? 1 : -1); - graphNode->unk38.animAccel = 0; - graphNode->unk38.animYTrans = 0; + if (graphNode->animInfo.curAnim != anim) { + graphNode->animInfo.curAnim = anim; + graphNode->animInfo.animFrame = anim->startFrame + ((anim->flags & ANIM_FLAG_FORWARD) ? 1 : -1); + graphNode->animInfo.animAccel = 0; + graphNode->animInfo.animYTrans = 0; } } @@ -782,15 +782,15 @@ void geo_obj_init_animation_accel(struct GraphNodeObject *graphNode, struct Anim struct Animation **animSegmented = segmented_to_virtual(animPtrAddr); struct Animation *anim = segmented_to_virtual(*animSegmented); - if (graphNode->unk38.curAnim != anim) { - graphNode->unk38.curAnim = anim; - graphNode->unk38.animYTrans = 0; - graphNode->unk38.animFrameAccelAssist = - (anim->unk04 << 16) + ((anim->flags & ANIM_FLAG_FORWARD) ? animAccel : -animAccel); - graphNode->unk38.animFrame = graphNode->unk38.animFrameAccelAssist >> 16; + if (graphNode->animInfo.curAnim != anim) { + graphNode->animInfo.curAnim = anim; + graphNode->animInfo.animYTrans = 0; + graphNode->animInfo.animFrameAccelAssist = + (anim->startFrame << 16) + ((anim->flags & ANIM_FLAG_FORWARD) ? animAccel : -animAccel); + graphNode->animInfo.animFrame = graphNode->animInfo.animFrameAccelAssist >> 16; } - graphNode->unk38.animAccel = animAccel; + graphNode->animInfo.animAccel = animAccel; } /** @@ -819,7 +819,7 @@ s32 retrieve_animation_index(s32 frame, u16 **attributes) { * whether it plays forwards or backwards, and whether it stops or loops at * the end etc. */ -s16 geo_update_animation_frame(struct GraphNodeObject_sub *obj, s32 *accelAssist) { +s16 geo_update_animation_frame(struct AnimInfo *obj, s32 *accelAssist) { s32 result; struct Animation *anim; @@ -841,11 +841,11 @@ s16 geo_update_animation_frame(struct GraphNodeObject_sub *obj, s32 *accelAssist result = (obj->animFrame - 1) << 16; } - if (GET_HIGH_S16_OF_32(result) < anim->unk06) { + if (GET_HIGH_S16_OF_32(result) < anim->loopStart) { if (anim->flags & ANIM_FLAG_NOLOOP) { - SET_HIGH_S16_OF_32(result, anim->unk06); + SET_HIGH_S16_OF_32(result, anim->loopStart); } else { - SET_HIGH_S16_OF_32(result, anim->unk08 - 1); + SET_HIGH_S16_OF_32(result, anim->loopEnd - 1); } } } else { @@ -855,11 +855,11 @@ s16 geo_update_animation_frame(struct GraphNodeObject_sub *obj, s32 *accelAssist result = (obj->animFrame + 1) << 16; } - if (GET_HIGH_S16_OF_32(result) >= anim->unk08) { + if (GET_HIGH_S16_OF_32(result) >= anim->loopEnd) { if (anim->flags & ANIM_FLAG_NOLOOP) { - SET_HIGH_S16_OF_32(result, anim->unk08 - 1); + SET_HIGH_S16_OF_32(result, anim->loopEnd - 1); } else { - SET_HIGH_S16_OF_32(result, anim->unk06); + SET_HIGH_S16_OF_32(result, anim->loopStart); } } } @@ -880,7 +880,7 @@ s16 geo_update_animation_frame(struct GraphNodeObject_sub *obj, s32 *accelAssist * animations without lateral translation. */ void geo_retreive_animation_translation(struct GraphNodeObject *obj, Vec3f position) { - struct Animation *animation = obj->unk38.curAnim; + struct Animation *animation = obj->animInfo.curAnim; u16 *attribute; s16 *values; s16 frame; @@ -889,7 +889,7 @@ void geo_retreive_animation_translation(struct GraphNodeObject *obj, Vec3f posit attribute = segmented_to_virtual((void *) animation->index); values = segmented_to_virtual((void *) animation->values); - frame = obj->unk38.animFrame; + frame = obj->animInfo.animFrame; if (frame < 0) { frame = 0; diff --git a/src/engine/graph_node.h b/src/engine/graph_node.h index ea800424..0eb5b44b 100644 --- a/src/engine/graph_node.h +++ b/src/engine/graph_node.h @@ -437,7 +437,7 @@ void geo_obj_init_animation_accel(struct GraphNodeObject *graphNode, struct Anim s32 retrieve_animation_index(s32 frame, u16 **attributes); -s16 geo_update_animation_frame(struct GraphNodeObject_sub *obj, s32 *accelAssist); +s16 geo_update_animation_frame(struct AnimInfo *obj, s32 *accelAssist); void geo_retreive_animation_translation(struct GraphNodeObject *obj, Vec3f position); struct GraphNodeRoot *geo_find_root(struct GraphNode *graphNode); diff --git a/src/engine/math_util.c b/src/engine/math_util.c index 19b1e79a..f1e95878 100644 --- a/src/engine/math_util.c +++ b/src/engine/math_util.c @@ -175,7 +175,8 @@ void mtxf_copy(Mat4 dest, Mat4 src) { void mtxf_identity(Mat4 mtx) { register s32 i; register f32 *dest; - // Note: These loops need to be on one line to match on PAL + // These loops must be one line to match on -O2 + // initialize everything except the first and last cells to 0 for (dest = (f32 *) mtx + 1, i = 0; i < 14; dest++, i++) *dest = 0; diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c index f85a2329..dfc1a646 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c @@ -206,8 +206,8 @@ s32 find_wall_collisions(struct WallCollisionData *colData) { // World (level) consists of a 16x16 grid. Find where the collision is on // the grid (round toward -inf) - cellX = ((x + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & 0x0F; - cellZ = ((z + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & 0x0F; + cellX = ((x + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & (NUM_CELLS - 1); + cellZ = ((z + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & (NUM_CELLS - 1); // Check for surfaces belonging to objects. node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS].next; @@ -314,8 +314,8 @@ f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct Surface **pceil) { s16 cellZ, cellX; struct Surface *ceil, *dynamicCeil; struct SurfaceNode *surfaceList; - f32 height = 20000.0f; - f32 dynamicHeight = 20000.0f; + f32 height = CELL_HEIGHT_LIMIT; + f32 dynamicHeight = CELL_HEIGHT_LIMIT; s16 x, y, z; //! (Parallel Universes) Because position is casted to an s16, reaching higher @@ -334,8 +334,8 @@ f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct Surface **pceil) { } // Each level is split into cells to limit load, find the appropriate cell. - cellX = ((x + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & 0xF; - cellZ = ((z + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & 0xF; + cellX = ((x + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & (NUM_CELLS - 1); + cellZ = ((z + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & (NUM_CELLS - 1); // Check for surfaces belonging to objects. surfaceList = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS].next; @@ -550,7 +550,7 @@ f32 find_floor_height(f32 x, f32 y, f32 z) { f32 unused_find_dynamic_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor) { struct SurfaceNode *surfaceList; struct Surface *floor; - f32 floorHeight = -11000.0f; + f32 floorHeight = FLOOR_LOWER_LIMIT; // Would normally cause PUs, but dynamic floors unload at that range. s16 x = (s16) xPos; @@ -558,8 +558,8 @@ f32 unused_find_dynamic_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfl s16 z = (s16) zPos; // Each level is split into cells to limit load, find the appropriate cell. - s16 cellX = ((x + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & 0x0F; - s16 cellZ = ((z + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & 0x0F; + s16 cellX = ((x + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & (NUM_CELLS - 1); + s16 cellZ = ((z + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & (NUM_CELLS - 1); surfaceList = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; floor = find_floor_from_list(surfaceList, x, y, z, &floorHeight); @@ -578,8 +578,8 @@ f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor) { struct Surface *floor, *dynamicFloor; struct SurfaceNode *surfaceList; - f32 height = -11000.0f; - f32 dynamicHeight = -11000.0f; + f32 height = FLOOR_LOWER_LIMIT; + f32 dynamicHeight = FLOOR_LOWER_LIMIT; //! (Parallel Universes) Because position is casted to an s16, reaching higher // float locations can return floors despite them not existing there. @@ -598,8 +598,8 @@ f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor) { } // Each level is split into cells to limit load, find the appropriate cell. - cellX = ((x + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & 0xF; - cellZ = ((z + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & 0xF; + cellX = ((x + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & (NUM_CELLS - 1); + cellZ = ((z + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & (NUM_CELLS - 1); // Check for surfaces belonging to objects. surfaceList = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; @@ -655,7 +655,7 @@ f32 find_water_level(f32 x, f32 z) { s32 numRegions; s16 val; f32 loX, hiX, loZ, hiZ; - f32 waterLevel = -11000.0f; + f32 waterLevel = FLOOR_LOWER_LIMIT; s16 *p = gEnvironmentRegions; if (p != NULL) { @@ -691,7 +691,7 @@ f32 find_poison_gas_level(f32 x, f32 z) { UNUSED s32 unused; s16 val; f32 loX, hiX, loZ, hiZ; - f32 gasLevel = -11000.0f; + f32 gasLevel = FLOOR_LOWER_LIMIT; s16 *p = gEnvironmentRegions; if (p != NULL) { @@ -753,25 +753,25 @@ void debug_surface_list_info(f32 xPos, f32 zPos) { s32 cellX = (xPos + LEVEL_BOUNDARY_MAX) / CELL_SIZE; s32 cellZ = (zPos + LEVEL_BOUNDARY_MAX) / CELL_SIZE; - list = gStaticSurfacePartition[cellZ & 0x0F][cellX & 0x0F][SPATIAL_PARTITION_FLOORS].next; + list = gStaticSurfacePartition[cellZ & (NUM_CELLS - 1)][cellX & (NUM_CELLS - 1)][SPATIAL_PARTITION_FLOORS].next; numFloors += surface_list_length(list); - list = gDynamicSurfacePartition[cellZ & 0x0F][cellX & 0x0F][SPATIAL_PARTITION_FLOORS].next; + list = gDynamicSurfacePartition[cellZ & (NUM_CELLS - 1)][cellX & (NUM_CELLS - 1)][SPATIAL_PARTITION_FLOORS].next; numFloors += surface_list_length(list); - list = gStaticSurfacePartition[cellZ & 0x0F][cellX & 0x0F][SPATIAL_PARTITION_WALLS].next; + list = gStaticSurfacePartition[cellZ & (NUM_CELLS - 1)][cellX & (NUM_CELLS - 1)][SPATIAL_PARTITION_WALLS].next; numWalls += surface_list_length(list); - list = gDynamicSurfacePartition[cellZ & 0x0F][cellX & 0x0F][SPATIAL_PARTITION_WALLS].next; + list = gDynamicSurfacePartition[cellZ & (NUM_CELLS - 1)][cellX & (NUM_CELLS - 1)][SPATIAL_PARTITION_WALLS].next; numWalls += surface_list_length(list); - list = gStaticSurfacePartition[cellZ & 0x0F][cellX & 0x0F][SPATIAL_PARTITION_CEILS].next; + list = gStaticSurfacePartition[cellZ & (NUM_CELLS - 1)][cellX & (NUM_CELLS - 1)][SPATIAL_PARTITION_CEILS].next; numCeils += surface_list_length(list); - list = gDynamicSurfacePartition[cellZ & 0x0F][cellX & 0x0F][SPATIAL_PARTITION_CEILS].next; + list = gDynamicSurfacePartition[cellZ & (NUM_CELLS - 1)][cellX & (NUM_CELLS - 1)][SPATIAL_PARTITION_CEILS].next; numCeils += surface_list_length(list); - print_debug_top_down_mapinfo("area %x", cellZ * 16 + cellX); + print_debug_top_down_mapinfo("area %x", cellZ * NUM_CELLS + cellX); // Names represent ground, walls, and roofs as found in SMS. print_debug_top_down_mapinfo("dg %d", numFloors); diff --git a/src/engine/surface_collision.h b/src/engine/surface_collision.h index 6332c481..b73d780f 100644 --- a/src/engine/surface_collision.h +++ b/src/engine/surface_collision.h @@ -5,8 +5,11 @@ #include "types.h" -#define LEVEL_BOUNDARY_MAX 0x2000 -#define CELL_SIZE 0x400 +#define LEVEL_BOUNDARY_MAX 0x2000 +#define CELL_SIZE 0x400 + +#define CELL_HEIGHT_LIMIT 20000.f +#define FLOOR_LOWER_LIMIT -11000.f struct WallCollisionData { diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index d0f3254d..2712efa3 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -24,8 +24,8 @@ s32 unused8038BE90; * Partitions for course and object surfaces. The arrays represent * the 16x16 cells that each level is split into. */ -SpatialPartitionCell gStaticSurfacePartition[16][16]; -SpatialPartitionCell gDynamicSurfacePartition[16][16]; +SpatialPartitionCell gStaticSurfacePartition[NUM_CELLS][NUM_CELLS]; +SpatialPartitionCell gDynamicSurfacePartition[NUM_CELLS][NUM_CELLS]; /** * Pools of data to contain either surface nodes or surfaces. @@ -86,7 +86,7 @@ static struct Surface *alloc_surface(void) { * Iterates through the entire partition, clearing the surfaces. */ static void clear_spatial_partition(SpatialPartitionCell *cells) { - register s32 i = 16 * 16; + register s32 i = NUM_CELLS * NUM_CELLS; while (i--) { (*cells)[SPATIAL_PARTITION_FLOORS].next = NULL; @@ -204,18 +204,18 @@ static s16 lower_cell_index(s16 coord) { s16 index; // Move from range [-0x2000, 0x2000) to [0, 0x4000) - coord += 0x2000; + coord += LEVEL_BOUNDARY_MAX; if (coord < 0) { coord = 0; } // [0, 16) - index = coord / 0x400; + index = coord / CELL_SIZE; // Include extra cell if close to boundary //! Some wall checks are larger than the buffer, meaning wall checks can // miss walls that are near a cell border. - if (coord % 0x400 < 50) { + if (coord % CELL_SIZE < 50) { index -= 1; } @@ -236,23 +236,23 @@ static s16 upper_cell_index(s16 coord) { s16 index; // Move from range [-0x2000, 0x2000) to [0, 0x4000) - coord += 0x2000; + coord += LEVEL_BOUNDARY_MAX; if (coord < 0) { coord = 0; } // [0, 16) - index = coord / 0x400; + index = coord / CELL_SIZE; // Include extra cell if close to boundary //! Some wall checks are larger than the buffer, meaning wall checks can // miss walls that are near a cell border. - if (coord % 0x400 > 0x400 - 50) { + if (coord % CELL_SIZE > CELL_SIZE - 50) { index += 1; } - if (index > 15) { - index = 15; + if (index > (NUM_CELLS - 1)) { + index = (NUM_CELLS - 1); } // Potentially < 0, but since lower index is >= 0, not exploitable diff --git a/src/engine/surface_load.h b/src/engine/surface_load.h index 7d541361..88654561 100644 --- a/src/engine/surface_load.h +++ b/src/engine/surface_load.h @@ -5,6 +5,10 @@ #include "types.h" +// NUM_CELLS needs to be a power of 2 so that the bitwise +// in surface_collision.c functions can work properly +#define NUM_CELLS 16 + struct SurfaceNode { struct SurfaceNode *next; @@ -23,8 +27,8 @@ typedef struct SurfaceNode SpatialPartitionCell[3]; // Needed for bs bss reordering memes. extern s32 unused8038BE90; -extern SpatialPartitionCell gStaticSurfacePartition[16][16]; -extern SpatialPartitionCell gDynamicSurfacePartition[16][16]; +extern SpatialPartitionCell gStaticSurfacePartition[NUM_CELLS][NUM_CELLS]; +extern SpatialPartitionCell gDynamicSurfacePartition[NUM_CELLS][NUM_CELLS]; extern struct SurfaceNode *sSurfaceNodePool; extern struct Surface *sSurfacePool; extern s16 sSurfacePoolSize; diff --git a/src/game/area.c b/src/game/area.c index 841d4803..8245f4d6 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -71,7 +71,6 @@ u8 gSpawnedStarHiddenCount = 0; * the spawn behavior executed, the index of that behavior is used with sSpawnTypeFromWarpBhv */ -// D_8032CE9C const BehaviorScript *sWarpBhvSpawnTable[] = { bhvDoorWarp, bhvStar, bhvExitPodiumWarp, bhvWarp, bhvWarpPipe, bhvFadingWarp, bhvInstantActiveWarp, bhvAirborneWarp, @@ -80,7 +79,6 @@ const BehaviorScript *sWarpBhvSpawnTable[] = { bhvAirborneStarCollectWarp, bhvAirborneDeathWarp, bhvLaunchStarCollectWarp, bhvLaunchDeathWarp, }; -// D_8032CEEC u8 sSpawnTypeFromWarpBhv[] = { MARIO_SPAWN_DOOR_WARP, MARIO_SPAWN_UNKNOWN_02, MARIO_SPAWN_UNKNOWN_03, MARIO_SPAWN_UNKNOWN_03, MARIO_SPAWN_UNKNOWN_03, MARIO_SPAWN_TELEPORT, MARIO_SPAWN_INSTANT_ACTIVE, MARIO_SPAWN_AIRBORNE, @@ -126,7 +124,7 @@ static int scale_x_to_correct_aspect_center(int x) { void print_intro_text(void) { #ifdef VERSION_EU - int language = eu_get_language(); + s32 language = eu_get_language(); #endif if ((gGlobalTimer & 0x1F) < 20) { if (gControllerBits == 0) { @@ -325,7 +323,7 @@ void change_area(s32 index) { if (areaFlags & 0x01) { for (int i = 0; i < MAX_PLAYERS; i++) { - gMarioStates[i].marioObj->header.gfx.unk18 = index; + gMarioStates[i].marioObj->header.gfx.areaIndex = index; gMarioStates[i].spawnInfo->areaIndex = index; } } @@ -434,7 +432,7 @@ void render_game(void) { if (gWarpTransition.isActive) { if (gWarpTransDelay == 0) { gWarpTransition.isActive = !render_screen_transition(0, gWarpTransition.type, gWarpTransition.time, - &gWarpTransition.data); + &gWarpTransition.data); if (!gWarpTransition.isActive) { if (gWarpTransition.type & 1) { gWarpTransition.pauseRendering = TRUE; @@ -448,7 +446,7 @@ void render_game(void) { } } else { render_text_labels(); - if (D_8032CE78 != 0) { + if (D_8032CE78 != NULL) { clear_viewport(D_8032CE78, gWarpTransFBSetColor); } else { clear_frame_buffer(gWarpTransFBSetColor); @@ -456,7 +454,7 @@ void render_game(void) { } D_8032CE74 = NULL; - D_8032CE78 = 0; + D_8032CE78 = NULL; } void get_area_minimum_y(u8* hasMinY, f32* minY) { diff --git a/src/game/behavior_actions.c b/src/game/behavior_actions.c index 0e5d0706..552c9f8d 100644 --- a/src/game/behavior_actions.c +++ b/src/game/behavior_actions.c @@ -247,7 +247,7 @@ void vec3f_copy_2(Vec3f dest, Vec3f src) { s32 set_obj_anim_with_accel_and_sound(s16 a0, s16 a1, s32 a2) { f32 sp1C; - if ((sp1C = o->header.gfx.unk38.animAccel / (f32) 0x10000) == 0) + if ((sp1C = o->header.gfx.animInfo.animAccel / (f32) 0x10000) == 0) sp1C = 1.0f; if (cur_obj_check_anim_frame_in_range(a0, sp1C) || cur_obj_check_anim_frame_in_range(a1, sp1C)) { cur_obj_play_sound_2(a2); diff --git a/src/game/behaviors/amp.inc.c b/src/game/behaviors/amp.inc.c index 225c63b5..c3ed5e9e 100644 --- a/src/game/behaviors/amp.inc.c +++ b/src/game/behaviors/amp.inc.c @@ -152,7 +152,7 @@ static void homing_amp_chase_loop(void) { check_amp_attack(); // Give up if Mario goes further than 1500 units from the amp's original position - if (is_point_within_radius_of_mario(o->oHomeX, o->oHomeY, o->oHomeZ, 1500) == FALSE) { + if (!is_point_within_radius_of_mario(o->oHomeX, o->oHomeY, o->oHomeZ, 1500)) { o->oAction = HOMING_AMP_ACT_GIVE_UP; } } @@ -184,7 +184,7 @@ static void homing_amp_give_up_loop(void) { */ static void amp_attack_cooldown_loop(void) { // Turn intangible and wait for 90 frames before chasing Mario again after hitting him. - o->header.gfx.unk38.animFrame += 2; + o->header.gfx.animInfo.animFrame += 2; o->oForwardVel = 0; cur_obj_become_intangible(); diff --git a/src/game/behaviors/bbh_merry_go_round.inc.c b/src/game/behaviors/bbh_merry_go_round.inc.c index babf015e..5cdc785b 100644 --- a/src/game/behaviors/bbh_merry_go_round.inc.c +++ b/src/game/behaviors/bbh_merry_go_round.inc.c @@ -87,7 +87,7 @@ void bhv_merry_go_round_loop(void) { } // Rotate the merry-go-round and play appropriate music if it's not stopped. - if (o->oMerryGoRoundStopped == FALSE) { + if (!o->oMerryGoRoundStopped) { o->oAngleVelYaw = 0x80; o->oMoveAngleYaw += o->oAngleVelYaw; o->oFaceAngleYaw += o->oAngleVelYaw; diff --git a/src/game/behaviors/bobomb.inc.c b/src/game/behaviors/bobomb.inc.c index 0eb3944e..aae5c6ed 100644 --- a/src/game/behaviors/bobomb.inc.c +++ b/src/game/behaviors/bobomb.inc.c @@ -73,13 +73,13 @@ void bobomb_act_patrol(void) { UNUSED s16 sp22; s16 collisionFlags; - sp22 = o->header.gfx.unk38.animFrame; + sp22 = o->header.gfx.animInfo.animFrame; o->oForwardVel = 5.0; collisionFlags = object_step(); struct Object* player = nearest_player_to_object(o); if ((obj_return_home_if_safe(o, o->oHomeX, o->oHomeY, o->oHomeZ, 400) == 1) - && (obj_check_if_facing_toward_angle(o->oMoveAngleYaw, obj_angle_to_object(o, player), 0x2000) == 1)) { + && (obj_check_if_facing_toward_angle(o->oMoveAngleYaw, obj_angle_to_object(o, player), 0x2000) == TRUE)) { o->oBobombFuseLit = 1; o->oAction = BOBOMB_ACT_CHASE_MARIO; } @@ -90,7 +90,7 @@ void bobomb_act_chase_mario(void) { UNUSED u8 filler[4]; s16 sp1a, collisionFlags; - sp1a = ++o->header.gfx.unk38.animFrame; + sp1a = ++o->header.gfx.animInfo.animFrame; o->oForwardVel = 20.0; collisionFlags = object_step(); @@ -300,7 +300,7 @@ void bhv_bobomb_buddy_init(void) { void bobomb_buddy_act_idle(void) { UNUSED u8 filler[4]; - s16 sp1a = o->header.gfx.unk38.animFrame; + s16 sp1a = o->header.gfx.animInfo.animFrame; UNUSED s16 collisionFlags = 0; o->oBobombBuddyPosXCopy = o->oPosX; @@ -408,7 +408,7 @@ void bobomb_buddy_act_talk(void) { } void bobomb_buddy_act_turn_to_talk(void) { - s16 sp1e = o->header.gfx.unk38.animFrame; + s16 sp1e = o->header.gfx.animInfo.animFrame; if ((sp1e == 5) || (sp1e == 16)) cur_obj_play_sound_2(SOUND_OBJ_BOBOMB_WALK); diff --git a/src/game/behaviors/boo.inc.c b/src/game/behaviors/boo.inc.c index f85d75d6..0239d723 100644 --- a/src/game/behaviors/boo.inc.c +++ b/src/game/behaviors/boo.inc.c @@ -60,7 +60,7 @@ static s32 boo_should_be_stopped(void) { if (gMarioStates[i].currentRoom == BBH_DYNAMIC_SURFACE_ROOM || gMarioStates[i].currentRoom == BBH_NEAR_MERRY_GO_ROUND_ROOM) { return FALSE; } } return TRUE; - /*if (gMarioOnMerryGoRound == FALSE) { + /*if (!gMarioOnMerryGoRound) { return TRUE; } else { return FALSE; @@ -352,7 +352,7 @@ static s32 boo_get_attack_status(void) { s32 attackStatus = BOO_NOT_ATTACKED; if (o->oInteractStatus & INT_STATUS_INTERACTED) { - if ((o->oInteractStatus & INT_STATUS_WAS_ATTACKED) && obj_has_attack_type(ATTACK_FROM_ABOVE) == FALSE) { + if ((o->oInteractStatus & INT_STATUS_WAS_ATTACKED) && !obj_has_attack_type(ATTACK_FROM_ABOVE)) { cur_obj_become_intangible(); o->oInteractStatus = 0; @@ -625,7 +625,7 @@ static void big_boo_act_1(void) { if (gMarioStates[i].currentRoom == BBH_DYNAMIC_SURFACE_ROOM || gMarioStates[i].currentRoom == BBH_NEAR_MERRY_GO_ROUND_ROOM) { inRoom = TRUE; } } - //if (gMarioOnMerryGoRound == FALSE) { + //if (!gMarioOnMerryGoRound) { if (!inRoom) { o->oAction = 0; } diff --git a/src/game/behaviors/bowser.inc.c b/src/game/behaviors/bowser.inc.c index f579b215..cfec5a40 100644 --- a/src/game/behaviors/bowser.inc.c +++ b/src/game/behaviors/bowser.inc.c @@ -71,8 +71,8 @@ void bhv_bowser_flame_spawn_loop(void) { f32 sp20 = sins(bowser->oMoveAngleYaw); s16 *sp1C = segmented_to_virtual(bowser_seg6_unkmoveshorts_060576FC); if (bowser->oSoundStateID == 6) { - sp30 = bowser->header.gfx.unk38.animFrame + 1.0f; - if (bowser->header.gfx.unk38.curAnim->unk08 == sp30) + sp30 = bowser->header.gfx.animInfo.animFrame + 1.0f; + if (bowser->header.gfx.animInfo.curAnim->loopEnd == sp30) sp30 = 0; if (sp30 > 45 && sp30 < 85) { cur_obj_play_sound_1(SOUND_AIR_BOWSER_SPIT_FIRE); @@ -467,7 +467,7 @@ void bowser_act_spit_fire_into_sky(void) // only in sky { s32 frame; cur_obj_init_animation_with_sound(11); - frame = o->header.gfx.unk38.animFrame; + frame = o->header.gfx.animInfo.animFrame; if (frame > 24 && frame < 36) { cur_obj_play_sound_1(SOUND_AIR_BOWSER_SPIT_FIRE); struct MarioState* marioState = nearest_mario_state_to_object(o); @@ -540,7 +540,7 @@ s32 bowser_land(void) { o->oVelY = 0; spawn_mist_particles_variable(0, 0, 60.0f); cur_obj_init_animation_with_sound(8); - o->header.gfx.unk38.animFrame = 0; + o->header.gfx.animInfo.animFrame = 0; cur_obj_start_cam_event(o, CAM_EVENT_BOWSER_JUMP); if (BITDW) { if (distanceToPlayer < 850.0f) @@ -1167,7 +1167,7 @@ void bowser_free_update(void) { struct Object *platform; UNUSED f32 floorHeight; if ((platform = o->platform) != NULL) - apply_platform_displacement((u32)-1, platform); + apply_platform_displacement(FALSE, platform); o->oBowserUnk10E = 0; cur_obj_update_floor_and_walls(); @@ -1249,7 +1249,7 @@ void bhv_bowser_loop(void) { struct Animation* anim = NULL; if (o->oAnimations != NULL && networkBowserAnimationIndex <= 26) { anim = o->oAnimations[networkBowserAnimationIndex]; - if (anim != NULL && o->header.gfx.unk38.curAnim != anim) { + if (anim != NULL && o->header.gfx.animInfo.curAnim != anim) { geo_obj_init_animation(&o->header.gfx, &anim); } } @@ -1300,9 +1300,9 @@ void bhv_bowser_loop(void) { // update animation index anim = o->oAnimations[networkBowserAnimationIndex]; - if (o->header.gfx.unk38.curAnim != anim) { + if (o->header.gfx.animInfo.curAnim != anim) { for (int i = 0; i < 32; i++) { - if (o->header.gfx.unk38.curAnim == o->oAnimations[i]) { + if (o->header.gfx.animInfo.curAnim == o->oAnimations[i]) { networkBowserAnimationIndex = i; } } @@ -1352,7 +1352,7 @@ void bhv_bowser_init(void) { so->fullObjectSync = TRUE; network_init_object_field(o, &o->header.gfx.node.flags); network_init_object_field(o, &networkBowserAnimationIndex); - network_init_object_field(o, &o->header.gfx.unk38.animFrame); + network_init_object_field(o, &o->header.gfx.animInfo.animFrame); } #undef BITDW diff --git a/src/game/behaviors/bowser_key_cutscene.inc.c b/src/game/behaviors/bowser_key_cutscene.inc.c index d3fa47f4..e840b893 100644 --- a/src/game/behaviors/bowser_key_cutscene.inc.c +++ b/src/game/behaviors/bowser_key_cutscene.inc.c @@ -11,7 +11,7 @@ Gfx *geo_scale_bowser_key(s32 run, struct GraphNode *node, UNUSED f32 mtx[4][4]) void bhv_bowser_key_unlock_door_loop(void) { s32 animTimer; - animTimer = o->header.gfx.unk38.animFrame; + animTimer = o->header.gfx.animInfo.animFrame; cur_obj_init_animation_with_sound(0); if (animTimer < 38) o->oBowserKeyScale = 0.0f; @@ -30,7 +30,7 @@ void bhv_bowser_key_unlock_door_loop(void) { } void bhv_bowser_key_course_exit_loop(void) { - s32 animTimer = o->header.gfx.unk38.animFrame; + s32 animTimer = o->header.gfx.animInfo.animFrame; cur_obj_init_animation_with_sound(1); if (animTimer < 38) o->oBowserKeyScale = 0.2f; diff --git a/src/game/behaviors/bully.inc.c b/src/game/behaviors/bully.inc.c index 9e35124f..e929b049 100644 --- a/src/game/behaviors/bully.inc.c +++ b/src/game/behaviors/bully.inc.c @@ -136,7 +136,7 @@ void bully_act_knockback(void) { o->oMoveAngleYaw = o->oFaceAngleYaw; obj_turn_toward_object(o, player, 16, 1280); } else - o->header.gfx.unk38.animFrame = 0; + o->header.gfx.animInfo.animFrame = 0; if (o->oBullyKBTimerAndMinionKOCounter == 18) { o->oAction = BULLY_ACT_CHASE_MARIO; @@ -177,7 +177,7 @@ void bully_backup_check(s16 collisionFlags) { } void bully_play_stomping_sound(void) { - s16 sp26 = o->header.gfx.unk38.animFrame; + s16 sp26 = o->header.gfx.animInfo.animFrame; switch (o->oAction) { case BULLY_ACT_PATROL: if (sp26 == 0 || sp26 == 12) { diff --git a/src/game/behaviors/butterfly.inc.c b/src/game/behaviors/butterfly.inc.c index 21d797a1..d389f849 100644 --- a/src/game/behaviors/butterfly.inc.c +++ b/src/game/behaviors/butterfly.inc.c @@ -4,7 +4,7 @@ void bhv_butterfly_init(void) { cur_obj_init_animation(1); o->oButterflyYPhase = random_float() * 100.0f; - o->header.gfx.unk38.animFrame = random_float() * 7.0f; + o->header.gfx.animInfo.animFrame = random_float() * 7.0f; o->oHomeX = o->oPosX; o->oHomeY = o->oPosY; o->oHomeZ = o->oPosZ; diff --git a/src/game/behaviors/camera_lakitu.inc.c b/src/game/behaviors/camera_lakitu.inc.c index 386c55bb..fdbb4d46 100644 --- a/src/game/behaviors/camera_lakitu.inc.c +++ b/src/game/behaviors/camera_lakitu.inc.c @@ -30,7 +30,7 @@ static void bhv_camera_lakitu_on_received_post(u8 localIndex) { void bhv_camera_lakitu_init(void) { if (o->oBehParams2ndByte != CAMERA_LAKITU_BP_FOLLOW_CAMERA) { // Despawn unless this is the very beginning of the game - if (gShouldNotPlayCastleMusic != TRUE) { + if (gNeverEnteredCastle != TRUE) { obj_mark_for_deletion(o); return; } diff --git a/src/game/behaviors/castle_cannon_grate.inc.c b/src/game/behaviors/castle_cannon_grate.inc.c index cc0c8b31..64bd924b 100644 --- a/src/game/behaviors/castle_cannon_grate.inc.c +++ b/src/game/behaviors/castle_cannon_grate.inc.c @@ -1,6 +1,7 @@ // castle_cannon_grate.inc.c void bhv_castle_cannon_grate_init(void) { - if (save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 24) >= 120) + if (save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1) >= 120) { o->activeFlags = ACTIVE_FLAG_DEACTIVATED; + } } diff --git a/src/game/behaviors/castle_flag.inc.c b/src/game/behaviors/castle_flag.inc.c index 6872621b..d589ff3b 100644 --- a/src/game/behaviors/castle_flag.inc.c +++ b/src/game/behaviors/castle_flag.inc.c @@ -1,5 +1,5 @@ // castle_flag.inc.c void bhv_castle_flag_init(void) { - o->header.gfx.unk38.animFrame = random_float() * 28.0f; + o->header.gfx.animInfo.animFrame = random_float() * 28.0f; } diff --git a/src/game/behaviors/chain_chomp.inc.c b/src/game/behaviors/chain_chomp.inc.c index b6835f0d..4d8fe89a 100644 --- a/src/game/behaviors/chain_chomp.inc.c +++ b/src/game/behaviors/chain_chomp.inc.c @@ -466,7 +466,7 @@ void bhv_chain_chomp_update(void) { struct SyncObject* so = network_init_object(o, 1000.0f); so->syncDeathEvent = FALSE; network_init_object_field(o, &o->oChainChompUnk104); - network_init_object_field(o, &o->header.gfx.unk38.animFrame); + network_init_object_field(o, &o->header.gfx.animInfo.animFrame); } switch (o->oAction) { diff --git a/src/game/behaviors/coin.inc.c b/src/game/behaviors/coin.inc.c index e5d4c3e4..7e4b8f8e 100644 --- a/src/game/behaviors/coin.inc.c +++ b/src/game/behaviors/coin.inc.c @@ -140,9 +140,7 @@ void spawn_coin_in_formation(s32 sp50, s32 sp54) { Vec3i sp40; s32 sp3C = 1; s32 sp38 = 1; - UNUSED s32 unused; - sp40[2] = 0; - sp40[0] = (sp40[1] = sp40[2]); + sp40[0] = sp40[1] = sp40[2] = 0; switch (sp54 & 7) { case 0: sp40[2] = 160 * (sp50 - 2); diff --git a/src/game/behaviors/door.inc.c b/src/game/behaviors/door.inc.c index 9787d9f3..b7a55a1b 100644 --- a/src/game/behaviors/door.inc.c +++ b/src/game/behaviors/door.inc.c @@ -29,8 +29,8 @@ u8 door_allow_walk_through(void) { if (gCamera->mode != CAMERA_MODE_NEWCAM) { return FALSE; } } - s32 cur = o->header.gfx.unk38.animFrame; - s32 max = o->header.gfx.unk38.curAnim->unk08 - 2; + s32 cur = o->header.gfx.animInfo.animFrame; + s32 max = o->header.gfx.animInfo.curAnim->loopEnd - 2; s32 min = max / 4; // make non-solid immediately for local actions so the camera doesn't glitch out diff --git a/src/game/behaviors/dorrie.inc.c b/src/game/behaviors/dorrie.inc.c index 573f953d..fe38137f 100644 --- a/src/game/behaviors/dorrie.inc.c +++ b/src/game/behaviors/dorrie.inc.c @@ -132,7 +132,7 @@ void dorrie_act_raise_head(void) { if (cur_obj_check_if_near_animation_end()) { o->oAction = DORRIE_ACT_MOVE; for (int i = 0; i < MAX_PLAYERS; i++) { dorrieLiftingPlayer[i] = FALSE; } - } else if (o->oDorrieLiftingMario && o->header.gfx.unk38.animFrame < 74) { + } else if (o->oDorrieLiftingMario && o->header.gfx.animInfo.animFrame < 74) { for (int i = 0; i < MAX_PLAYERS; i++) { if (!is_player_active(&gMarioStates[i])) { continue; } diff --git a/src/game/behaviors/fish.inc.c b/src/game/behaviors/fish.inc.c index 7b072024..e76607f1 100644 --- a/src/game/behaviors/fish.inc.c +++ b/src/game/behaviors/fish.inc.c @@ -235,7 +235,7 @@ void fish_group_act_move(void) { */ void fish_group_act_animate(void) { cur_obj_init_animation_with_accel_and_sound(0, 1.0f); - o->header.gfx.unk38.animFrame = (s16)(random_float() * 28.0f); + o->header.gfx.animInfo.animFrame = (s16)(random_float() * 28.0f); o->oFishDepthDistance = random_float() * 300.0f; cur_obj_scale(random_float() * 0.4 + 0.8); o->oAction = FISH_ACT_ACTIVE; diff --git a/src/game/behaviors/flame.inc.c b/src/game/behaviors/flame.inc.c index 0ab67ee7..30346894 100644 --- a/src/game/behaviors/flame.inc.c +++ b/src/game/behaviors/flame.inc.c @@ -18,24 +18,24 @@ void bhv_small_piranha_flame_loop(void) { } } else { cur_obj_update_floor_and_walls(); - if (approach_f32_ptr(&o->oSmallPiranhaFlameUnkF4, o->oSmallPiranhaFlameUnkF8, 0.6f)) { + if (approach_f32_ptr(&o->oSmallPiranhaFlameStartSpeed, o->oSmallPiranhaFlameEndSpeed, 0.6f)) { cur_obj_rotate_yaw_toward(angleToPlayer, 0x200); } - obj_compute_vel_from_move_pitch(o->oSmallPiranhaFlameUnkF4); + obj_compute_vel_from_move_pitch(o->oSmallPiranhaFlameStartSpeed); cur_obj_move_standard(-78); - spawn_object_with_scale(o, o->oSmallPiranhaFlameUnkFC, bhvSmallPiranhaFlame, + spawn_object_with_scale(o, o->oSmallPiranhaFlameModel, bhvSmallPiranhaFlame, 0.4f * o->header.gfx.scale[0]); if (o->oTimer > o->oSmallPiranhaFlameUnk100) { spawn_object_relative_with_scale(1, 0, o->oGraphYOffset, 0, o->header.gfx.scale[0], o, - o->oSmallPiranhaFlameUnkFC, bhvFlyguyFlame); + o->oSmallPiranhaFlameModel, bhvFlyguyFlame); o->oSmallPiranhaFlameUnk100 = random_linear_offset(8, 15); o->oTimer = 0; } obj_check_attacks(&sPiranhaPlantFireHitbox, o->oAction); - o->oSmallPiranhaFlameUnk104 += o->oSmallPiranhaFlameUnkF4; + o->oSmallPiranhaFlameUnk104 += o->oSmallPiranhaFlameStartSpeed; if (o->oSmallPiranhaFlameUnk104 > 1500.0f || (o->oMoveFlags & (OBJ_MOVE_HIT_WALL | OBJ_MOVE_MASK_IN_WATER))) { obj_die_if_health_non_positive(); diff --git a/src/game/behaviors/flamethrower.inc.c b/src/game/behaviors/flamethrower.inc.c index 9a44f6fa..2fb3ba17 100644 --- a/src/game/behaviors/flamethrower.inc.c +++ b/src/game/behaviors/flamethrower.inc.c @@ -50,7 +50,7 @@ void bhv_flamethrower_loop(void) { s32 model; UNUSED u8 pad[8]; if (o->oAction == 0) { - if (gCurrLevelNum != LEVEL_BBH || gMarioOnMerryGoRound == 1) { + if (gCurrLevelNum != LEVEL_BBH || gMarioOnMerryGoRound == TRUE) { if (marioState->playerIndex == 0 && distanceToPlayer < 2000.0f) { o->oAction++; network_send_object(o); diff --git a/src/game/behaviors/heave_ho.inc.c b/src/game/behaviors/heave_ho.inc.c index d1784f6f..566c6be8 100644 --- a/src/game/behaviors/heave_ho.inc.c +++ b/src/game/behaviors/heave_ho.inc.c @@ -29,7 +29,7 @@ void heave_ho_act_1(void) { s32 sp1C = 0; o->oForwardVel = 0.0f; cur_obj_reverse_animation(); - while (1) { + while (TRUE) { if (D_8032F460[sp1C][0] == -1) { o->oAction = 2; break; diff --git a/src/game/behaviors/hoot.inc.c b/src/game/behaviors/hoot.inc.c index 259455b3..30ad3ce7 100644 --- a/src/game/behaviors/hoot.inc.c +++ b/src/game/behaviors/hoot.inc.c @@ -21,7 +21,7 @@ void bhv_hoot_init(void) { so->ignore_if_true = bhv_hoot_ignore_if_true; network_init_object_field(o, &o->oHootAvailability); network_init_object_field(o, &o->oMoveAnglePitch); - network_init_object_field(o, &o->header.gfx.unk38.animFrame); + network_init_object_field(o, &o->header.gfx.animInfo.animFrame); } // sp28 = arg0 @@ -62,7 +62,7 @@ void hoot_free_step(s16 fastOscY, s32 speed) { struct FloorGeometry *sp2c; s16 yaw = o->oMoveAngleYaw; s16 pitch = o->oMoveAnglePitch; - s16 sp26 = o->header.gfx.unk38.animFrame; + s16 sp26 = o->header.gfx.animInfo.animFrame; f32 xPrev = o->oPosX; f32 zPrev = o->oPosZ; f32 hSpeed; @@ -109,7 +109,7 @@ void hoot_player_set_yaw(void) { void hoot_carry_step(s32 speed, UNUSED f32 xPrev, UNUSED f32 zPrev) { s16 yaw = o->oMoveAngleYaw; s16 pitch = o->oMoveAnglePitch; - s16 sp22 = o->header.gfx.unk38.animFrame; + s16 sp22 = o->header.gfx.animInfo.animFrame; f32 hSpeed; o->oVelY = sins(pitch) * speed; @@ -176,7 +176,7 @@ void hoot_act_ascent(f32 xPrev, f32 zPrev) { if (o->oTimer >= 29) { cur_obj_play_sound_1(SOUND_ENV_WIND2); - o->header.gfx.unk38.animFrame = 1; + o->header.gfx.animInfo.animFrame = 1; } if (o->oPosY > 6500.0f) diff --git a/src/game/behaviors/intro_peach.inc.c b/src/game/behaviors/intro_peach.inc.c index eb32d1c9..2838a910 100644 --- a/src/game/behaviors/intro_peach.inc.c +++ b/src/game/behaviors/intro_peach.inc.c @@ -29,7 +29,7 @@ void bhv_intro_peach_loop(void) { gCurrentObject->oIntroPeachPitchFromFocus = -9984.f; gCurrentObject->oIntroPeachYawFromFocus = -768.f; gCurrentObject->oOpacity = 255; - gCurrentObject->header.gfx.unk38.animFrame = 100; + gCurrentObject->header.gfx.animInfo.animFrame = 100; break; case 1: intro_peach_set_pos_and_opacity(gCurrentObject, 0.f, 0.f); diff --git a/src/game/behaviors/intro_scene.inc.c b/src/game/behaviors/intro_scene.inc.c index 7b3498ba..7b6a2475 100644 --- a/src/game/behaviors/intro_scene.inc.c +++ b/src/game/behaviors/intro_scene.inc.c @@ -5,7 +5,7 @@ void spawn_child_obj_relative(struct Object *parent, s16 xOffset, s16 yOffset, s s32 model, const BehaviorScript *behavior) { struct Object *sp1C = spawn_object(parent, model, behavior); - sp1C->header.gfx.unk38.animFrame = random_float() * 6.f; + sp1C->header.gfx.animInfo.animFrame = random_float() * 6.f; sp1C->oEndBirdUnk104 = sCutsceneVars[9].point[0]; sCutsceneVars[9].point[0] += 1.f; sp1C->oPosX += xOffset; diff --git a/src/game/behaviors/king_bobomb.inc.c b/src/game/behaviors/king_bobomb.inc.c index 380016d1..3541ad08 100644 --- a/src/game/behaviors/king_bobomb.inc.c +++ b/src/game/behaviors/king_bobomb.inc.c @@ -47,8 +47,8 @@ u8 king_bobomb_act_0_continue_dialog(void) { return o->oAction == 0 && o->oSubAc void king_bobomb_act_0(void) { #ifndef VERSION_JP - o->oForwardVel = 0; - o->oVelY = 0; + o->oForwardVel = 0.0f; + o->oVelY = 0.0f; #endif struct MarioState* marioState = nearest_mario_state_to_object(o); if (o->oSubAction == 0) { @@ -67,7 +67,7 @@ void king_bobomb_act_0(void) { } } -int mario_is_far_below_object(f32 arg0) { +s32 mario_is_far_below_object(f32 arg0) { for (int i = 0; i < MAX_PLAYERS; i++) { if (!is_player_active(&gMarioStates[i])) { continue; } if (arg0 >= o->oPosY - gMarioStates[i].marioObj->oPosY) { return FALSE; } diff --git a/src/game/behaviors/klepto.inc.c b/src/game/behaviors/klepto.inc.c index 109ec3b4..b4eeeb2a 100644 --- a/src/game/behaviors/klepto.inc.c +++ b/src/game/behaviors/klepto.inc.c @@ -34,7 +34,7 @@ static s32 klepto_set_and_check_if_anim_at_end(void) { } else if (o->oSoundStateID == 5) { if (cur_obj_set_anim_if_at_end(0)) { cur_obj_play_sound_2(SOUND_GENERAL_SWISH_WATER); - o->header.gfx.unk38.animFrame = 9; + o->header.gfx.animInfo.animFrame = 9; } } else { if (cur_obj_check_anim_frame(9)) { diff --git a/src/game/behaviors/manta_ray.inc.c b/src/game/behaviors/manta_ray.inc.c index a53dcf20..44162469 100644 --- a/src/game/behaviors/manta_ray.inc.c +++ b/src/game/behaviors/manta_ray.inc.c @@ -44,7 +44,7 @@ void manta_ray_move(void) { s16 sp1E; s32 sp18; - sp1E = o->header.gfx.unk38.animFrame; + sp1E = o->header.gfx.animInfo.animFrame; gCurrentObject->oPathedStartWaypoint = (struct Waypoint *) sMantaRayTraj; sp18 = cur_obj_follow_path(sp18); o->oMantaUnkF8 = o->oPathedTargetYaw; diff --git a/src/game/behaviors/metal_box.inc.c b/src/game/behaviors/metal_box.inc.c index f41dcd19..c36189eb 100644 --- a/src/game/behaviors/metal_box.inc.c +++ b/src/game/behaviors/metal_box.inc.c @@ -37,7 +37,7 @@ void bhv_pushable_loop(void) { s16 sp1C; obj_set_hitbox(o, &sMetalBoxHitbox); o->oForwardVel = 0.0f; - if (obj_check_if_collided_with_object(o, player) && marioState->flags & 0x80000000) { + if (obj_check_if_collided_with_object(o, player) && marioState->flags & MARIO_UNKNOWN_31) { sp1C = obj_angle_to_object(o, player); if (abs_angle_diff(sp1C, player->oMoveAngleYaw) > 0x4000) { o->oMoveAngleYaw = (s16)((player->oMoveAngleYaw + 0x2000) & 0xc000); diff --git a/src/game/behaviors/mips.inc.c b/src/game/behaviors/mips.inc.c index f9920955..620f4be6 100644 --- a/src/game/behaviors/mips.inc.c +++ b/src/game/behaviors/mips.inc.c @@ -20,19 +20,19 @@ static void bhv_mips_on_received_post(UNUSED u8 fromLocalIndex) { */ void bhv_mips_init(void) { // Retrieve star flags for Castle Secret Stars on current save file. - u8 starFlags; - starFlags = save_file_get_star_flags(gCurrSaveFileNum - 1, -1); + u8 starFlags = save_file_get_star_flags(gCurrSaveFileNum - 1, -1); // If the player has >= 15 stars and hasn't collected first MIPS star... - if (save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 24) >= 15 && (starFlags & 0x08) == 0) { + if (save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1) >= 15 + && !(starFlags & SAVE_FLAG_TO_STAR_FLAG(SAVE_FLAG_COLLECTED_MIPS_STAR_1))) { o->oBehParams2ndByte = 0; #ifndef VERSION_JP o->oMipsForwardVelocity = 40.0f; #endif } // If the player has >= 50 stars and hasn't collected second MIPS star... - else if (save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 24) >= 50 - && (starFlags & 0x10) == 0) { + else if (save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1) >= 50 + && !(starFlags & SAVE_FLAG_TO_STAR_FLAG(SAVE_FLAG_COLLECTED_MIPS_STAR_2))) { o->oBehParams2ndByte = 1; #ifndef VERSION_JP o->oMipsForwardVelocity = 45.0f; @@ -187,7 +187,7 @@ void bhv_mips_act_fall_down(void) { s16 collisionFlags = 0; collisionFlags = object_step(); - o->header.gfx.unk38.animFrame = 0; + o->header.gfx.animInfo.animFrame = 0; if ((collisionFlags & OBJ_COL_FLAG_GROUNDED) == 1) { o->oAction = MIPS_ACT_WAIT_FOR_ANIMATION_DONE; diff --git a/src/game/behaviors/moneybag.inc.c b/src/game/behaviors/moneybag.inc.c index 333ed397..a3e3941d 100644 --- a/src/game/behaviors/moneybag.inc.c +++ b/src/game/behaviors/moneybag.inc.c @@ -65,7 +65,7 @@ void moneybag_check_mario_collision(void) { // sp20 = collisionFlags void moneybag_jump(s8 collisionFlags) { - s16 animFrame = o->header.gfx.unk38.animFrame; + s16 animFrame = o->header.gfx.animInfo.animFrame; switch (o->oMoneybagJumpState) { case MONEYBAG_JUMP_PREPARE: @@ -106,7 +106,7 @@ void moneybag_jump(s8 collisionFlags) { if (o->oTimer >= 61) { o->oMoneybagJumpState = MONEYBAG_JUMP_LANDING; o->oForwardVel = 0; - o->header.gfx.unk38.animFrame = 0; + o->header.gfx.animInfo.animFrame = 0; } break; diff --git a/src/game/behaviors/mushroom_1up.inc.c b/src/game/behaviors/mushroom_1up.inc.c index e7231383..41f58789 100644 --- a/src/game/behaviors/mushroom_1up.inc.c +++ b/src/game/behaviors/mushroom_1up.inc.c @@ -20,11 +20,13 @@ void bhv_1up_common_init(void) { void bhv_1up_init(void) { bhv_1up_common_init(); if (o->oBehParams2ndByte == 1) { - if ((save_file_get_flags() & 0x50) == 0) + if (!(save_file_get_flags() & (SAVE_FLAG_HAVE_KEY_1 | SAVE_FLAG_UNLOCKED_BASEMENT_DOOR))) { o->activeFlags = ACTIVE_FLAG_DEACTIVATED; + } } else if (o->oBehParams2ndByte == 2) { - if ((save_file_get_flags() & 0xa0) == 0) + if (!(save_file_get_flags() & (SAVE_FLAG_HAVE_KEY_2 | SAVE_FLAG_UNLOCKED_UPSTAIRS_DOOR))) { o->activeFlags = ACTIVE_FLAG_DEACTIVATED; + } } } diff --git a/src/game/behaviors/piranha_bubbles.inc.c b/src/game/behaviors/piranha_bubbles.inc.c index 0b3806ec..f6fcbe88 100644 --- a/src/game/behaviors/piranha_bubbles.inc.c +++ b/src/game/behaviors/piranha_bubbles.inc.c @@ -30,9 +30,9 @@ void bhv_piranha_plant_bubble_loop(void) { struct Object *parent = o->parentObj; // the Piranha Plant f32 scale = 0; s32 i; - s32 frame = parent->header.gfx.unk38.animFrame; + s32 frame = parent->header.gfx.animInfo.animFrame; // TODO: rename lastFrame if it is inaccurate - s32 lastFrame = parent->header.gfx.unk38.curAnim->unk08 - 2; + s32 lastFrame = parent->header.gfx.animInfo.curAnim->loopEnd - 2; s32 UNUSED unused; f32 doneShrinkingFrame; // the first frame after shrinking is done f32 beginGrowingFrame; // the frame just before growing begins diff --git a/src/game/behaviors/piranha_plant.inc.c b/src/game/behaviors/piranha_plant.inc.c index 4615a64c..07030ebb 100644 --- a/src/game/behaviors/piranha_plant.inc.c +++ b/src/game/behaviors/piranha_plant.inc.c @@ -260,7 +260,7 @@ void piranha_plant_act_biting(void) { int distanceToPlayer = dist_between_objects(o, player); int angleToPlayer = obj_angle_to_object(o, player); - s32 frame = o->header.gfx.unk38.animFrame; + s32 frame = o->header.gfx.animInfo.animFrame; cur_obj_become_tangible(); diff --git a/src/game/behaviors/seaweed.inc.c b/src/game/behaviors/seaweed.inc.c index d1dc2b46..4a9528d2 100644 --- a/src/game/behaviors/seaweed.inc.c +++ b/src/game/behaviors/seaweed.inc.c @@ -1,7 +1,7 @@ // seaweed.c.inc void bhv_seaweed_init(void) { - o->header.gfx.unk38.animFrame = random_float() * 80.0f; + o->header.gfx.animInfo.animFrame = random_float() * 80.0f; } void bhv_seaweed_bundle_init(void) { @@ -23,7 +23,7 @@ void bhv_seaweed_bundle_init(void) { seaweed->header.gfx.scale[0] = 0.8; seaweed->header.gfx.scale[1] = 0.9; seaweed->header.gfx.scale[2] = 0.8; - seaweed->header.gfx.unk38.animFrame = random_float() * 80.0f; + seaweed->header.gfx.animInfo.animFrame = random_float() * 80.0f; seaweed = spawn_object(o, MODEL_SEAWEED, bhvSeaweed); seaweed->oFaceAngleYaw = 40500; @@ -32,7 +32,7 @@ void bhv_seaweed_bundle_init(void) { seaweed->header.gfx.scale[0] = 0.8; seaweed->header.gfx.scale[1] = 0.8; seaweed->header.gfx.scale[2] = 0.8; - seaweed->header.gfx.unk38.animFrame = random_float() * 80.0f; + seaweed->header.gfx.animInfo.animFrame = random_float() * 80.0f; seaweed = spawn_object(o, MODEL_SEAWEED, bhvSeaweed); seaweed->oFaceAngleYaw = 57236; @@ -41,5 +41,5 @@ void bhv_seaweed_bundle_init(void) { seaweed->header.gfx.scale[0] = 1.2; seaweed->header.gfx.scale[1] = 1.2; seaweed->header.gfx.scale[2] = 1.2; - seaweed->header.gfx.unk38.animFrame = random_float() * 80.0f; + seaweed->header.gfx.animInfo.animFrame = random_float() * 80.0f; } diff --git a/src/game/behaviors/shock_wave.inc.c b/src/game/behaviors/shock_wave.inc.c index 6e6cd644..ba249442 100644 --- a/src/game/behaviors/shock_wave.inc.c +++ b/src/game/behaviors/shock_wave.inc.c @@ -20,7 +20,6 @@ void bhv_bowser_shock_wave_loop(void) { sp20 = o->oBowserShockWaveUnkF4 * D_8032F420[3]; if ((sp2C < o->oDistanceToMario && o->oDistanceToMario < sp28) || (sp24 < o->oDistanceToMario && o->oDistanceToMario < sp20)) - gMarioStates[0].marioObj->oInteractStatus |= - 0x10; // This is interact_coin, but the name sounds wrong in this behiavor + gMarioStates[0].marioObj->oInteractStatus |= INT_STATUS_HIT_BY_SHOCKWAVE; } } diff --git a/src/game/behaviors/snowman.inc.c b/src/game/behaviors/snowman.inc.c index 6ec9b522..ec6e55b2 100644 --- a/src/game/behaviors/snowman.inc.c +++ b/src/game/behaviors/snowman.inc.c @@ -73,7 +73,8 @@ void snowmans_bottom_act_1(void) { if (sp20 == -1) { sp1E = (u16)angleToPlayer - (u16) o->oMoveAngleYaw; - if (obj_check_if_facing_toward_angle(o->oMoveAngleYaw, angleToPlayer, 0x2000) == 1 && o->oSnowmansBottomUnk1AC == 1) { + if (obj_check_if_facing_toward_angle(o->oMoveAngleYaw, angleToPlayer, 0x2000) == TRUE + && o->oSnowmansBottomUnk1AC == 1) { o->oSnowmansBottomUnkF8 = angleToPlayer; } else { o->oSnowmansBottomUnkF8 = o->oMoveAngleYaw; diff --git a/src/game/behaviors/ukiki.inc.c b/src/game/behaviors/ukiki.inc.c index f61e2f8f..a182aa8c 100644 --- a/src/game/behaviors/ukiki.inc.c +++ b/src/game/behaviors/ukiki.inc.c @@ -3,16 +3,16 @@ /** * @file Contains behavior for the ukiki objects. * - * Hat ukiki is the ukiki that steals Mario's hat. + * Cap ukiki is the ukiki that steals Mario's cap. * Cage ukiki is the ukiki that triggers the cage star. */ /** - * Sets the hat ukiki to its home if Mario is far away + * Sets the cap ukiki to its home if Mario is far away * or makes him wait to respawn if in water. */ -void handle_hat_ukiki_reset(void) { - if (o->oBehParams2ndByte == UKIKI_HAT) { +void handle_cap_ukiki_reset(void) { + if (o->oBehParams2ndByte == UKIKI_CAP) { if (cur_obj_mario_far_away()) { cur_obj_set_pos_to_home_and_stop(); o->oAction = UKIKI_ACT_IDLE; @@ -23,14 +23,14 @@ void handle_hat_ukiki_reset(void) { } /** - * Returns TRUE if Mario has his hat and ukiki is - * the hat ukiki. + * Returns TRUE if Mario has his cap and ukiki is + * the cap ukiki. */ -s32 is_hat_ukiki_and_mario_has_hat(void) { - if (o->oBehParams2ndByte == UKIKI_HAT) { +s32 is_cap_ukiki_and_mario_has_normal_cap_on_head(void) { + if (o->oBehParams2ndByte == UKIKI_CAP) { for (int i = 0; i < MAX_PLAYERS; i++) { if (!is_player_active(&gMarioStates[i])) { continue; } - if (!does_mario_have_hat(&gMarioStates[i])) { return FALSE; } + if (!does_mario_have_normal_cap_on_head(&gMarioStates[i])) { return FALSE; } } return TRUE; } @@ -130,7 +130,7 @@ void ukiki_act_idle(void) { idle_ukiki_taunt(); - if (is_hat_ukiki_and_mario_has_hat()) { + if (is_cap_ukiki_and_mario_has_normal_cap_on_head()) { if (distanceToPlayer > 700.0f && distanceToPlayer < 1000.0f) { o->oAction = UKIKI_ACT_RUN; } else if (distanceToPlayer <= 700.0f && 200.0f < distanceToPlayer) { @@ -146,8 +146,8 @@ void ukiki_act_idle(void) { o->oAction = UKIKI_ACT_GO_TO_CAGE; } - // Jump away from Mario after stealing his hat. - if (o->oUkikiTextState == UKIKI_TEXT_STOLE_HAT) { + // Jump away from Mario after stealing his cap. + if (o->oUkikiTextState == UKIKI_TEXT_STOLE_CAP) { o->oMoveAngleYaw = player->oMoveAngleYaw + 0x8000; if (check_if_moving_over_floor(50.0f, 150.0f)) { @@ -165,10 +165,10 @@ void ukiki_act_idle(void) { } } - o->oUkikiTextState = UKIKI_TEXT_HAS_HAT; + o->oUkikiTextState = UKIKI_TEXT_HAS_CAP; } - if (o->oBehParams2ndByte == UKIKI_HAT) { + if (o->oBehParams2ndByte == UKIKI_CAP) { if (o->oPosY < -1550.0f) { o->oAction = UKIKI_ACT_RETURN_HOME; } @@ -177,7 +177,7 @@ void ukiki_act_idle(void) { /** * Ukiki attempts to run home, which is often impossible depending on terrain. - * Only used for the hat ukiki. + * Only used for the cap ukiki. */ void ukiki_act_return_home(void) { UNUSED s32 unused; @@ -243,7 +243,7 @@ void ukiki_act_turn_to_mario(void) { o->oAction = UKIKI_ACT_IDLE; } - if (is_hat_ukiki_and_mario_has_hat()){ + if (is_cap_ukiki_and_mario_has_normal_cap_on_head()){ if (distanceToPlayer > 500.0f) { o->oAction = UKIKI_ACT_RUN; } @@ -264,7 +264,7 @@ void ukiki_act_run(void) { s32 fleeMario = TRUE; s16 goalYaw = angleToPlayer + 0x8000; - if (is_hat_ukiki_and_mario_has_hat()) { + if (is_cap_ukiki_and_mario_has_normal_cap_on_head()) { fleeMario = FALSE; goalYaw = angleToPlayer; } @@ -511,7 +511,7 @@ void ukiki_free_loop(void) { } cur_obj_move_standard(steepSlopeAngleDegrees); - handle_hat_ukiki_reset(); + handle_cap_ukiki_reset(); if(!(o->oMoveFlags & OBJ_MOVE_MASK_IN_WATER)) { exec_anim_sound_state(sUkikiSoundStates); @@ -522,7 +522,7 @@ void ukiki_free_loop(void) { * Unused function for timing ukiki's blinking. * Image still present in Ukiki's actor graphics. * - * Possibly unused so AnimState could be used for wearing a hat? + * Possibly unused so AnimState could be used for wearing a cap? */ static void ukiki_blink_timer(void) { if (gGlobalTimer % 50 < 7) { @@ -584,18 +584,18 @@ void cage_ukiki_held_loop(void) { } } -u8 hat_ukiki_held_loop_1(void) { return o->oHeldState == HELD_HELD && o->oUkikiTextState == UKIKI_TEXT_STEAL_HAT; } -u8 hat_ukiki_held_loop_2(void) { return o->oHeldState == HELD_HELD && o->oUkikiTextState == UKIKI_TEXT_HAS_HAT; } +u8 hat_ukiki_held_loop_1(void) { return o->oHeldState == HELD_HELD && o->oUkikiTextState == UKIKI_TEXT_STEAL_CAP; } +u8 hat_ukiki_held_loop_2(void) { return o->oHeldState == HELD_HELD && o->oUkikiTextState == UKIKI_TEXT_HAS_CAP; } /** - * Called by the main behavior function for the hat ukiki whenever it is held. + * Called by the main behavior function for the cap ukiki whenever it is held. */ -void hat_ukiki_held_loop(void) { +void cap_ukiki_held_loop(void) { struct MarioState* heldByMario = &gMarioStates[o->heldByPlayerIndex]; if (heldByMario->playerIndex != 0) { return; } // other player must catch ukiki - if ((o->oUkikiHasHat & UKIKI_HAT_ON) && does_mario_have_hat(heldByMario)) { + if ((o->oUkikiHasCap & UKIKI_CAP_ON) && does_mario_have_normal_cap_on_head(heldByMario)) { o->oInteractionSubtype |= INT_SUBTYPE_DROP_IMMEDIATELY; return; } @@ -603,35 +603,35 @@ void hat_ukiki_held_loop(void) { switch(o->oUkikiTextState) { case UKIKI_TEXT_DEFAULT: if (mario_lose_cap_to_enemy(heldByMario, 2)) { - o->oUkikiTextState = UKIKI_TEXT_STEAL_HAT; - o->oUkikiHasHat |= UKIKI_HAT_ON; + o->oUkikiTextState = UKIKI_TEXT_STEAL_CAP; + o->oUkikiHasCap |= UKIKI_CAP_ON; o->globalPlayerIndex = gNetworkPlayers[heldByMario->playerIndex].globalIndex; network_send_object(o); } else {} break; - case UKIKI_TEXT_STEAL_HAT: + case UKIKI_TEXT_STEAL_CAP: if (should_start_or_continue_dialog(heldByMario, o) && cur_obj_update_dialog(heldByMario, 2, 2, DIALOG_100, 0, hat_ukiki_held_loop_1)) { o->oInteractionSubtype |= INT_SUBTYPE_DROP_IMMEDIATELY; - o->oUkikiTextState = UKIKI_TEXT_STOLE_HAT; + o->oUkikiTextState = UKIKI_TEXT_STOLE_CAP; network_send_object(o); } break; - case UKIKI_TEXT_STOLE_HAT: + case UKIKI_TEXT_STOLE_CAP: break; - case UKIKI_TEXT_HAS_HAT: + case UKIKI_TEXT_HAS_CAP: if (should_start_or_continue_dialog(heldByMario, o) && cur_obj_update_dialog(heldByMario, 2, 18, DIALOG_101, 0, hat_ukiki_held_loop_2)) { mario_retrieve_cap(heldByMario); set_mario_npc_dialog(heldByMario, 0, NULL); - o->oUkikiHasHat &= ~UKIKI_HAT_ON; - o->oUkikiTextState = UKIKI_TEXT_GAVE_HAT_BACK; + o->oUkikiHasCap &= ~UKIKI_CAP_ON; + o->oUkikiTextState = UKIKI_TEXT_GAVE_CAP_BACK; network_send_object(o); } break; - case UKIKI_TEXT_GAVE_HAT_BACK: + case UKIKI_TEXT_GAVE_CAP_BACK: o->oUkikiTextState = UKIKI_TEXT_DEFAULT; o->oAction = UKIKI_ACT_IDLE; break; @@ -639,14 +639,14 @@ void hat_ukiki_held_loop(void) { } /** - * Initializatation for ukiki, determines if it has Mario's hat. + * Initializatation for ukiki, determines if it has Mario's cap. */ void bhv_ukiki_init(void) { // skip hat save flags - //if (o->oBehParams2ndByte == UKIKI_HAT) { + //if (o->oBehParams2ndByte == UKIKI_CAP) { // if (save_file_get_flags() & SAVE_FLAG_CAP_ON_UKIKI) { - // o->oUkikiTextState = UKIKI_TEXT_HAS_HAT; - // o->oUkikiHasHat |= UKIKI_HAT_ON; + // o->oUkikiTextState = UKIKI_TEXT_HAS_CAP; + // o->oUkikiHasCap |= UKIKI_CAP_ON; // } //} @@ -660,7 +660,7 @@ void bhv_ukiki_init(void) { /** * The main behavior function for ukiki. Chooses which behavior to use - * dependent on the held state and whick ukiki it is (cage or hat). + * dependent on the held state and whick ukiki it is (cage or cap). */ void bhv_ukiki_loop(void) { struct Object* heldByPlayer = gMarioStates[o->heldByPlayerIndex].marioObj; @@ -676,8 +676,8 @@ void bhv_ukiki_loop(void) { cur_obj_unrender_and_reset_state(UKIKI_ANIM_HELD, 0); obj_copy_pos(o, heldByPlayer); - if (o->oBehParams2ndByte == UKIKI_HAT) { - hat_ukiki_held_loop(); + if (o->oBehParams2ndByte == UKIKI_CAP) { + cap_ukiki_held_loop(); } else { cage_ukiki_held_loop(); } @@ -689,11 +689,11 @@ void bhv_ukiki_loop(void) { break; } - if (o->oUkikiHasHat & UKIKI_HAT_ON) { + if (o->oUkikiHasCap & UKIKI_CAP_ON) { for (int i = 0; i < MAX_PLAYERS; i++) { if (!is_player_active(&gMarioStates[i])) { continue; } - if (!does_mario_have_hat(&gMarioStates[i])) { - o->oAnimState = UKIKI_ANIM_STATE_HAT_ON; + if (!does_mario_have_normal_cap_on_head(&gMarioStates[i])) { + o->oAnimState = UKIKI_ANIM_STATE_CAP_ON; break; } } diff --git a/src/game/behaviors/water_pillar.inc.c b/src/game/behaviors/water_pillar.inc.c index 5eee4deb..c9a23e67 100644 --- a/src/game/behaviors/water_pillar.inc.c +++ b/src/game/behaviors/water_pillar.inc.c @@ -59,23 +59,23 @@ void water_level_pillar_drained(void) { } static u8 bhv_water_level_pillar_ignore_if_true(void) { - return (o->oWaterLevelPillarUnkF8) || (o->oAction != 0); + return (o->oWaterLevelPillarDrained) || (o->oAction != 0); } void bhv_water_level_pillar_init(void) { if (save_file_get_flags() & SAVE_FLAG_MOAT_DRAINED) - o->oWaterLevelPillarUnkF8 = 1; + o->oWaterLevelPillarDrained = 1; struct SyncObject* so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS); so->ignore_if_true = bhv_water_level_pillar_ignore_if_true; network_init_object_field(o, &o->oAction); network_init_object_field(o, &o->oPrevAction); network_init_object_field(o, &o->oTimer); - network_init_object_field(o, &o->oWaterLevelPillarUnkF8); + network_init_object_field(o, &o->oWaterLevelPillarDrained); } void bhv_water_level_pillar_loop(void) { - if (o->oWaterLevelPillarUnkF8) + if (o->oWaterLevelPillarDrained) water_level_pillar_drained(); else water_level_pillar_undrained(); diff --git a/src/game/behaviors/whomp.inc.c b/src/game/behaviors/whomp.inc.c index 407924ae..781cb5fd 100644 --- a/src/game/behaviors/whomp.inc.c +++ b/src/game/behaviors/whomp.inc.c @@ -1,7 +1,7 @@ // whomp.c.inc void whomp_play_sfx_from_pound_animation(void) { - UNUSED s32 sp2C = o->header.gfx.unk38.animFrame; + UNUSED s32 sp2C = o->header.gfx.animInfo.animFrame; s32 sp28 = 0; if (o->oForwardVel < 5.0f) { sp28 = cur_obj_check_anim_frame(0); diff --git a/src/game/behaviors/wiggler.inc.c b/src/game/behaviors/wiggler.inc.c index a6bebcd6..605bd25b 100644 --- a/src/game/behaviors/wiggler.inc.c +++ b/src/game/behaviors/wiggler.inc.c @@ -138,7 +138,7 @@ void wiggler_init_segments(void) { (segments + i)->yaw = o->oFaceAngleYaw; } - o->header.gfx.unk38.animFrame = -1; + o->header.gfx.animInfo.animFrame = -1; // Spawn each body part for (i = 1; i <= 3; i++) { @@ -146,7 +146,7 @@ void wiggler_init_segments(void) { spawn_object_relative(i, 0, 0, 0, o, MODEL_WIGGLER_BODY, bhvWigglerBody); if (bodyPart != NULL) { obj_init_animation_with_sound(bodyPart, wiggler_seg5_anims_0500C874, 0); - bodyPart->header.gfx.unk38.animFrame = (23 * i) % 26 - 1; + bodyPart->header.gfx.animInfo.animFrame = (23 * i) % 26 - 1; } } diff --git a/src/game/behaviors/yoshi.inc.c b/src/game/behaviors/yoshi.inc.c index 5fe9bff1..2a2937a0 100644 --- a/src/game/behaviors/yoshi.inc.c +++ b/src/game/behaviors/yoshi.inc.c @@ -17,7 +17,8 @@ void bhv_yoshi_init(void) { o->oBuoyancy = 1.3f; o->oInteractionSubtype = INT_SUBTYPE_NPC; - if (save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 24) < 120 || sYoshiDead == TRUE) { + if (save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1) < 120 + || sYoshiDead == TRUE) { o->activeFlags = ACTIVE_FLAG_DEACTIVATED; } @@ -32,7 +33,7 @@ void bhv_yoshi_init(void) { void yoshi_walk_loop(void) { UNUSED s16 sp26; - s16 sp24 = o->header.gfx.unk38.animFrame; + s16 sp24 = o->header.gfx.animInfo.animFrame; o->oForwardVel = 10.0f; sp26 = object_step(); @@ -56,7 +57,7 @@ void yoshi_walk_loop(void) { void yoshi_idle_loop(void) { s16 chosenHome; - UNUSED s16 sp1C = o->header.gfx.unk38.animFrame; + UNUSED s16 sp1C = o->header.gfx.animInfo.animFrame; if (o->oTimer > 90) { chosenHome = random_float() * 3.99; @@ -109,7 +110,7 @@ void yoshi_talk_loop(void) { } void yoshi_walk_and_jump_off_roof_loop(void) { - s16 sp26 = o->header.gfx.unk38.animFrame; + s16 sp26 = o->header.gfx.animInfo.animFrame; o->oForwardVel = 10.0f; object_step(); @@ -139,7 +140,7 @@ void yoshi_finish_jumping_and_despawn_loop(void) { if (o->oPosY < 2100.0f) { set_mario_npc_dialog(&gMarioStates[0], 0, yoshi_talk_loop_continue_dialog); gObjCutsceneDone = TRUE; - sYoshiDead = 1; + sYoshiDead = TRUE; o->activeFlags = ACTIVE_FLAG_DEACTIVATED; } } @@ -149,7 +150,7 @@ void yoshi_give_present_loop(void) { if (gHudDisplay.lives == 100) { play_sound(SOUND_GENERAL_COLLECT_1UP, gDefaultSoundArgs); - gSpecialTripleJump = 1; + gSpecialTripleJump = TRUE; o->oAction = YOSHI_ACT_WALK_JUMP_OFF_ROOF; return; } diff --git a/src/game/camera.c b/src/game/camera.c index 8556772f..dc5aec95 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -666,9 +666,9 @@ void unused_set_camera_pitch_shake_env(s16 shake) { * both ranges are always 200.f * Since focMul is 0.9, `focOff` is closer to the floor than `posOff` * posOff and focOff are sometimes the same address, which just ignores the pos calculation - *! Doesn't return anything, but required to match EU + *! Doesn't return anything, but required to match on -O2 */ -f32 calc_y_to_curr_floor(f32 *posOff, f32 posMul, f32 posBound, f32 *focOff, f32 focMul, f32 focBound) { +BAD_RETURN(f32) calc_y_to_curr_floor(f32 *posOff, f32 posMul, f32 posBound, f32 *focOff, f32 focMul, f32 focBound) { f32 floorHeight = sMarioGeometry.currFloorHeight; f32 waterHeight; UNUSED s32 filler; @@ -797,10 +797,10 @@ void set_camera_height(struct Camera *c, f32 goalHeight) { } } approach_camera_height(c, goalHeight, 20.f); - if (camCeilHeight != 20000.f) { + if (camCeilHeight != CELL_HEIGHT_LIMIT) { camCeilHeight -= baseOff; if ((c->pos[1] > camCeilHeight && sMarioGeometry.currFloorHeight + baseOff < camCeilHeight) - || (sMarioGeometry.currCeilHeight != 20000.f + || (sMarioGeometry.currCeilHeight != CELL_HEIGHT_LIMIT && sMarioGeometry.currCeilHeight > camCeilHeight && c->pos[1] > camCeilHeight)) { c->pos[1] = camCeilHeight; } @@ -1495,7 +1495,7 @@ s32 update_fixed_camera(struct Camera *c, Vec3f focus, UNUSED Vec3f pos) { vec3f_add(basePos, sCastleEntranceOffset); if (sMarioGeometry.currFloorType != SURFACE_DEATH_PLANE - && sMarioGeometry.currFloorHeight != -11000.f) { + && sMarioGeometry.currFloorHeight != FLOOR_LOWER_LIMIT) { goalHeight = sMarioGeometry.currFloorHeight + basePos[1] + heightOffset; } else { goalHeight = gLakituState.goalPos[1]; @@ -1506,7 +1506,7 @@ s32 update_fixed_camera(struct Camera *c, Vec3f focus, UNUSED Vec3f pos) { } ceilHeight = find_ceil(c->pos[0], goalHeight - 100.f, c->pos[2], &ceiling); - if (ceilHeight != 20000.f) { + if (ceilHeight != CELL_HEIGHT_LIMIT) { if (goalHeight > (ceilHeight -= 125.f)) { goalHeight = ceilHeight; } @@ -1605,7 +1605,7 @@ s32 update_boss_fight_camera(struct Camera *c, Vec3f focus, Vec3f pos) { // When C-Down is not active, this vec3f_set_dist_and_angle(focus, pos, focusDistance, 0x1000, yaw); // Find the floor of the arena - pos[1] = find_floor(c->areaCenX, 20000.f, c->areaCenZ, &floor); + pos[1] = find_floor(c->areaCenX, CELL_HEIGHT_LIMIT, c->areaCenZ, &floor); if (floor != NULL) { nx = floor->normal.x; ny = floor->normal.y; @@ -1621,7 +1621,7 @@ s32 update_boss_fight_camera(struct Camera *c, Vec3f focus, Vec3f pos) { } } - //! Must be same line to match EU + //! Must be same line to match on -O2 // Prevent the camera from going to the ground in the outside boss fight if (gCurrLevelNum == LEVEL_BBH) { pos[1] = 2047.f; } @@ -2279,7 +2279,7 @@ s16 update_default_camera(struct Camera *c) { // If there's water below the camera, decide whether to keep the camera above the water surface waterHeight = find_water_level(cPos[0], cPos[2]); - if (waterHeight != -11000.f) { + if (waterHeight != FLOOR_LOWER_LIMIT) { waterHeight += 125.f; distFromWater = waterHeight - marioFloorHeight; if (!(gCameraMovementFlags & CAM_MOVE_METAL_BELOW_WATER)) { @@ -2329,7 +2329,7 @@ s16 update_default_camera(struct Camera *c) { // Make Lakitu fly above the gas gasHeight = find_poison_gas_level(cPos[0], cPos[2]); - if (gasHeight != -11000.f) { + if (gasHeight != FLOOR_LOWER_LIMIT) { if ((gasHeight += 130.f) > c->pos[1]) { c->pos[1] = gasHeight; } @@ -2340,7 +2340,7 @@ s16 update_default_camera(struct Camera *c) { if (c->mode == CAMERA_MODE_FREE_ROAM) { camFloorHeight -= 100.f; } - ceilHeight = 20000.f; + ceilHeight = CELL_HEIGHT_LIMIT; vec3f_copy(c->focus, sMarioCamState->pos); } @@ -2349,10 +2349,10 @@ s16 update_default_camera(struct Camera *c) { if (sMarioCamState->pos[1] - 100.f > camFloorHeight) { camFloorHeight = sMarioCamState->pos[1] - 100.f; } - ceilHeight = 20000.f; + ceilHeight = CELL_HEIGHT_LIMIT; vec3f_copy(c->focus, sMarioCamState->pos); } - if (camFloorHeight != -11000.f) { + if (camFloorHeight != FLOOR_LOWER_LIMIT) { camFloorHeight += posHeight; approach_camera_height(c, camFloorHeight, 20.f); } @@ -2374,7 +2374,7 @@ s16 update_default_camera(struct Camera *c) { vec3f_set_dist_and_angle(c->focus, c->pos, dist, tempPitch, tempYaw); } } - if (ceilHeight != 20000.f) { + if (ceilHeight != CELL_HEIGHT_LIMIT) { if (c->pos[1] > (ceilHeight -= 150.f) && (avoidStatus = is_range_behind_surface(c->pos, sMarioCamState->pos, ceil, 0, -1)) == 1) { c->pos[1] = ceilHeight; @@ -2472,7 +2472,7 @@ s32 update_spiral_stairs_camera(struct Camera *c, Vec3f focus, Vec3f pos) { checkPos[2] = focus[2] + (cPos[2] - focus[2]) * 0.7f; floorHeight = find_floor(checkPos[0], checkPos[1] + 50.f, checkPos[2], &floor); - if (floorHeight != -11000.f) { + if (floorHeight != FLOOR_LOWER_LIMIT) { if (floorHeight < sMarioGeometry.currFloorHeight) { floorHeight = sMarioGeometry.currFloorHeight; } @@ -3013,7 +3013,7 @@ void update_lakitu(struct Camera *c) { distToFloor = find_floor(gLakituState.pos[0], gLakituState.pos[1] + 20.0f, gLakituState.pos[2], &floor); - if (distToFloor != -11000.f) { + if (distToFloor != FLOOR_LOWER_LIMIT) { if (gLakituState.pos[1] < (distToFloor += 100.0f)) { gLakituState.pos[1] = distToFloor; } else { @@ -4347,7 +4347,7 @@ s16 reduce_by_dist_from_camera(s16 value, f32 maxDist, f32 posX, f32 posY, f32 p vec3f_get_dist_and_angle(gLakituState.goalPos, pos, &dist, &pitch, &yaw); if (dist < maxDist) { calculate_angles(gLakituState.goalPos, gLakituState.goalFocus, &goalPitch, &goalYaw); - //! Must be same line to match EU + //! Must be same line to match on -O2 pitch -= goalPitch; yaw -= goalYaw; dist -= 2000.f; if (dist < 0.f) { @@ -5527,7 +5527,7 @@ s16 next_lakitu_state(Vec3f newPos, Vec3f newFoc, Vec3f curPos, Vec3f curFoc, if (gCamera->cutscene != 0 || !(gCameraMovementFlags & CAM_MOVE_C_UP_MODE)) { floorHeight = find_floor(newPos[0], newPos[1], newPos[2], &floor); - if (floorHeight != -11000.f) { + if (floorHeight != FLOOR_LOWER_LIMIT) { if ((floorHeight += 125.f) > newPos[1]) { newPos[1] = floorHeight; } @@ -6773,19 +6773,19 @@ void resolve_geometry_collisions(Vec3f pos, UNUSED Vec3f lastGood) { floorY = find_floor(pos[0], pos[1] + 50.f, pos[2], &surf); ceilY = find_ceil(pos[0], pos[1] - 50.f, pos[2], &surf); - if ((-11000.f != floorY) && (20000.f == ceilY)) { + if ((FLOOR_LOWER_LIMIT != floorY) && (CELL_HEIGHT_LIMIT == ceilY)) { if (pos[1] < (floorY += 125.f)) { pos[1] = floorY; } } - if ((-11000.f == floorY) && (20000.f != ceilY)) { + if ((FLOOR_LOWER_LIMIT == floorY) && (CELL_HEIGHT_LIMIT != ceilY)) { if (pos[1] > (ceilY -= 125.f)) { pos[1] = ceilY; } } - if ((-11000.f != floorY) && (20000.f != ceilY)) { + if ((FLOOR_LOWER_LIMIT != floorY) && (CELL_HEIGHT_LIMIT != ceilY)) { floorY += 125.f; ceilY -= 125.f; @@ -6912,14 +6912,14 @@ void find_mario_floor_and_ceil(struct PlayerGeometry *pg) { gCheckingSurfaceCollisionsForCamera = TRUE; if (find_floor(sMarioCamState->pos[0], sMarioCamState->pos[1] + 10.f, - sMarioCamState->pos[2], &surf) != -11000.f) { + sMarioCamState->pos[2], &surf) != FLOOR_LOWER_LIMIT) { pg->currFloorType = surf->type; } else { pg->currFloorType = 0; } if (find_ceil(sMarioCamState->pos[0], sMarioCamState->pos[1] - 10.f, - sMarioCamState->pos[2], &surf) != 20000.f) { + sMarioCamState->pos[2], &surf) != CELL_HEIGHT_LIMIT) { pg->currCeilType = surf->type; } else { pg->currCeilType = 0; @@ -7453,7 +7453,7 @@ BAD_RETURN(s32) cutscene_ending_peach_descends(struct Camera *c) { } /** - * Mario runs across the bridge to peach, and takes off his hat. + * Mario runs across the bridge to peach, and takes off his cap. * Follow the sEndingMarioToPeach* splines while Mario runs across. */ BAD_RETURN(s32) cutscene_ending_mario_to_peach(struct Camera *c) { @@ -8791,7 +8791,7 @@ BAD_RETURN(s32) cutscene_suffocation_stay_above_gas(struct Camera *c) { cutscene_goto_cvar_pos(c, 400.f, 0x2800, 0x200, 0); gasLevel = find_poison_gas_level(sMarioCamState->pos[0], sMarioCamState->pos[2]); - if (gasLevel != -11000.f) { + if (gasLevel != FLOOR_LOWER_LIMIT) { if ((gasLevel += 130.f) > c->pos[1]) { c->pos[1] = gasLevel; } @@ -10178,7 +10178,7 @@ BAD_RETURN(s32) cutscene_exit_painting_start(struct Camera *c) { offset_rotated(c->pos, sCutsceneVars[0].point, sCutsceneVars[2].point, sCutsceneVars[0].angle); floorHeight = find_floor(c->pos[0], c->pos[1] + 10.f, c->pos[2], &floor); - if (floorHeight != -11000.f) { + if (floorHeight != FLOOR_LOWER_LIMIT) { if (c->pos[1] < (floorHeight += 60.f)) { c->pos[1] = floorHeight; } diff --git a/src/game/characters.c b/src/game/characters.c index 937d5e5e..7c7449dc 100644 --- a/src/game/characters.c +++ b/src/game/characters.c @@ -480,7 +480,7 @@ f32 get_character_anim_offset(struct MarioState* m) { struct Object* marioObj = m->marioObj; struct Character* c = get_character(m); if (!c->animOffsetEnabled) { return 0; } - s32 animID = marioObj->header.gfx.unk38.animID; + s32 animID = marioObj->header.gfx.animInfo.animID; if (animID < 0 || animID >= ANIM_TYPE_MAX) { return 0; } switch (sAnimTypes[animID]) { @@ -515,7 +515,7 @@ void update_character_anim_offset(struct MarioState* m) { if (m->curAnimOffset > 40) { m->curAnimOffset = 40; } if (m->curAnimOffset < -40) { m->curAnimOffset = -40; } - //s32 animID = marioObj->header.gfx.unk38.animID; + //s32 animID = marioObj->header.gfx.animInfo.animID; //LOG_INFO(">>> [%d] : %d :: %f, %f", animID, sAnimTypes[animID], m->curAnimOffset, m->minimumBoneY); marioObj->header.gfx.pos[1] = m->pos[1] + m->curAnimOffset; diff --git a/src/game/debug.c b/src/game/debug.c index 66d808ed..528a5e30 100644 --- a/src/game/debug.c +++ b/src/game/debug.c @@ -256,7 +256,7 @@ void print_stageinfo(void) { void print_string_array_info(const char **strArr) { s32 i; - if (sDebugStringArrPrinted == FALSE) { + if (!sDebugStringArrPrinted) { sDebugStringArrPrinted += 1; // again, why not = TRUE... for (i = 0; i < 8; i++) { // sDebugPage is assumed to be 4 or 5 here. @@ -401,7 +401,7 @@ void try_modify_debug_controls(void) { if (gPlayer1Controller->buttonPressed & Z_TRIG) { sNoExtraDebug ^= 1; } - if (!(gPlayer1Controller->buttonDown & (L_TRIG | R_TRIG)) && sNoExtraDebug == FALSE) { + if (!(gPlayer1Controller->buttonDown & (L_TRIG | R_TRIG)) && !sNoExtraDebug) { sp4 = 1; if (gPlayer1Controller->buttonDown & B_BUTTON) { sp4 = 100; diff --git a/src/game/game_init.c b/src/game/game_init.c index 98be2f9a..62ce6832 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -56,7 +56,7 @@ struct MarioAnimation D_80339D10[MAX_PLAYERS]; struct MarioAnimation gDemo; UNUSED u8 filler80339D30[0x90]; -int unused8032C690 = 0; +s32 unused8032C690 = 0; u32 gGlobalTimer = 0; static u16 sCurrFBNum = 0; diff --git a/src/game/geo_misc.c b/src/game/geo_misc.c index 72dd0bf0..11bb44c0 100644 --- a/src/game/geo_misc.c +++ b/src/game/geo_misc.c @@ -82,7 +82,7 @@ Gfx *geo_exec_inside_castle_light(s32 callContext, struct GraphNode *node, UNUSE if (callContext == GEO_CONTEXT_RENDER) { flags = save_file_get_flags(); - if (gHudDisplay.stars >= 10 && (flags & SAVE_FLAG_HAVE_WING_CAP) == 0) { + if (gHudDisplay.stars >= 10 && !(flags & SAVE_FLAG_HAVE_WING_CAP)) { displayList = alloc_display_list(2 * sizeof(*displayList)); if (displayList == NULL) { diff --git a/src/game/hud.h b/src/game/hud.h index fa450f9c..fb0da74c 100644 --- a/src/game/hud.h +++ b/src/game/hud.h @@ -25,7 +25,6 @@ enum CameraHUDLut { GLYPH_CAM_WARIO_HEAD, }; -// Functions void set_hud_camera_status(s16 status); void render_hud(void); diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index cef4aedc..5d61e3b0 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -1045,7 +1045,7 @@ void create_dialog_box_with_response(s16 dialog) { } void reset_dialog_render_state(void) { - level_set_transition(0, 0); + level_set_transition(0, NULL); if (gDialogBoxType == DIALOG_TYPE_ZOOM) { trigger_cutscene_dialog(2); @@ -1908,7 +1908,7 @@ void render_dialog_entries(void) { break; case DIALOG_STATE_CLOSING: if (gDialogBoxOpenTimer == 20.0f) { - level_set_transition(0, 0); + level_set_transition(0, NULL); play_sound(SOUND_MENU_MESSAGE_DISAPPEAR, gDefaultSoundArgs); if (gDialogBoxType == DIALOG_TYPE_ZOOM) { @@ -2742,7 +2742,7 @@ s16 render_pause_courses_and_castle(void) { case DIALOG_STATE_OPENING: gDialogLineNum = 1; gDialogTextAlpha = 0; - //level_set_transition(-1, 0); + //level_set_transition(-1, NULL); #if defined(VERSION_JP) || defined(VERSION_SH) play_sound(SOUND_MENU_PAUSE, gDefaultSoundArgs); #else @@ -2774,7 +2774,7 @@ s16 render_pause_courses_and_castle(void) { || gPlayer1Controller->buttonPressed & START_BUTTON) #endif { - level_set_transition(0, 0); + level_set_transition(0, NULL); play_sound(SOUND_MENU_PAUSE_2, gDefaultSoundArgs); gDialogBoxState = DIALOG_STATE_OPENING; gMenuMode = -1; @@ -2801,7 +2801,7 @@ s16 render_pause_courses_and_castle(void) { || gPlayer1Controller->buttonPressed & START_BUTTON) #endif { - level_set_transition(0, 0); + level_set_transition(0, NULL); play_sound(SOUND_MENU_PAUSE_2, gDefaultSoundArgs); gMenuMode = -1; gDialogBoxState = DIALOG_STATE_OPENING; @@ -2896,7 +2896,7 @@ void print_hud_course_complete_coins(s16 x, s16 y) { gCourseCompleteCoinsEqual = 1; gCourseCompleteCoins = gHudDisplay.coins; - if (gGotFileCoinHiScore != 0) { + if (gGotFileCoinHiScore) { print_hud_course_complete_string(HUD_PRINT_HISCORE); } } else { @@ -2910,7 +2910,7 @@ void print_hud_course_complete_coins(s16 x, s16 y) { } } - if (gHudDisplay.coins == gCourseCompleteCoins && gGotFileCoinHiScore != 0) { + if (gHudDisplay.coins == gCourseCompleteCoins && gGotFileCoinHiScore) { play_sound(SOUND_MENU_MARIO_CASTLE_WARP2, gDefaultSoundArgs); } } @@ -3144,7 +3144,7 @@ s16 render_course_complete_screen(void) { render_course_complete_lvl_info_and_hud_str(); if (gCourseDoneMenuTimer > 100 && gCourseCompleteCoinsEqual == 1) { gDialogBoxState = DIALOG_STATE_VERTICAL; - //level_set_transition(-1, 0); + //level_set_transition(-1, NULL); gDialogTextAlpha = 0; gDialogLineNum = 1; } @@ -3164,7 +3164,7 @@ s16 render_course_complete_screen(void) { || gPlayer1Controller->buttonPressed & Z_TRIG #endif )) { - level_set_transition(0, 0); + level_set_transition(0, NULL); play_sound(SOUND_MENU_STAR_SOUND, gDefaultSoundArgs); gDialogBoxState = DIALOG_STATE_OPENING; gMenuMode = -1; diff --git a/src/game/interaction.c b/src/game/interaction.c index 4c272da7..6362be37 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -144,10 +144,10 @@ static u8 sJustTeleported = FALSE; u8 gPssSlideStarted = FALSE; /** - * Returns the type of hat Mario is wearing. + * Returns the type of cap Mario is wearing. */ u32 get_mario_cap_flag(struct Object *capObject) { - void *script = virtual_to_segmented(0x13, capObject->behavior); + const BehaviorScript *script = virtual_to_segmented(0x13, capObject->behavior); if (script == bhvNormalCap) { return MARIO_NORMAL_CAP; @@ -161,6 +161,7 @@ u32 get_mario_cap_flag(struct Object *capObject) { return 0; } + /** * Returns true if the passed in object has a moving angle yaw * in the angular range given towards Mario. @@ -381,15 +382,15 @@ void mario_stop_riding_and_holding(struct MarioState *m) { } } -u32 does_mario_have_hat(struct MarioState *m) { - return (m->flags & MARIO_CAP_FLAGS) == (MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD); +u32 does_mario_have_normal_cap_on_head(struct MarioState *m) { + return (m->flags & (MARIO_CAPS | MARIO_CAP_ON_HEAD)) == (MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD); } void mario_blow_off_cap(struct MarioState *m, f32 capSpeed) { if (m->playerIndex != 0) { return; } struct Object *capObject; - if (does_mario_have_hat(m)) { + if (does_mario_have_normal_cap_on_head(m)) { save_file_set_cap_pos(m->pos[0], m->pos[1], m->pos[2]); m->flags &= ~(MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD); @@ -420,7 +421,7 @@ u32 mario_lose_cap_to_enemy(struct MarioState* m, u32 arg) { if (m->playerIndex != 0) { return FALSE; } u32 wasWearingCap = FALSE; - if (does_mario_have_hat(m)) { + if (does_mario_have_normal_cap_on_head(m)) { save_file_set_flags(arg == 1 ? SAVE_FLAG_CAP_ON_KLEPTO : SAVE_FLAG_CAP_ON_UKIKI); m->flags &= ~(MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD); wasWearingCap = TRUE; @@ -469,7 +470,7 @@ struct Object *mario_get_collided_object(struct MarioState *m, u32 interactType) u32 mario_check_object_grab(struct MarioState *m) { u32 result = FALSE; - void *script; + const BehaviorScript *script; if (m->playerIndex != 0) { return FALSE; } if (m->interactObj == NULL || m->interactObj->oHeldState == HELD_HELD) { return FALSE; } @@ -937,7 +938,6 @@ u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct O play_sound(SOUND_MENU_STAR_SOUND, m->marioObj->header.gfx.cameraToObject); #ifndef VERSION_JP update_mario_sound_and_camera(m); - // func_802521A0 #endif if (grandStar) { @@ -1551,6 +1551,7 @@ u32 interact_clam_or_bubba(struct MarioState *m, UNUSED u32 interactType, struct if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { sDelayInvincTimer = TRUE; } + return TRUE; } @@ -1621,6 +1622,7 @@ u32 interact_shock(struct MarioState *m, UNUSED u32 interactType, struct Object if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { sDelayInvincTimer = TRUE; } + return FALSE; } @@ -1681,6 +1683,7 @@ u32 interact_hit_from_below(struct MarioState *m, UNUSED u32 interactType, struc if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { sDelayInvincTimer = TRUE; } + return FALSE; } @@ -1716,6 +1719,7 @@ u32 interact_bounce_top(struct MarioState *m, UNUSED u32 interactType, struct Ob if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { sDelayInvincTimer = TRUE; } + return FALSE; } @@ -1732,6 +1736,7 @@ u32 interact_unknown_08(struct MarioState *m, UNUSED u32 interactType, struct Ob if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { sDelayInvincTimer = TRUE; } + return FALSE; } @@ -1743,6 +1748,7 @@ u32 interact_damage(struct MarioState *m, UNUSED u32 interactType, struct Object if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { sDelayInvincTimer = TRUE; } + return FALSE; } @@ -1963,7 +1969,7 @@ u32 interact_cap(struct MarioState *m, UNUSED u32 interactType, struct Object *o } u32 interact_grabbable(struct MarioState *m, u32 interactType, struct Object *o) { - void *script = virtual_to_segmented(0x13, o->behavior); + const BehaviorScript *script = virtual_to_segmented(0x13, o->behavior); if (m->playerIndex != 0) { return FALSE; } @@ -1995,6 +2001,7 @@ u32 interact_grabbable(struct MarioState *m, u32 interactType, struct Object *o) if (script != bhvBowser) { push_mario_out_of_object(m, o, -5.0f); } + return FALSE; } @@ -2010,7 +2017,7 @@ u32 mario_can_talk(struct MarioState *m, u32 arg) { return TRUE; } - val6 = m->marioObj->header.gfx.unk38.animID; + val6 = m->marioObj->header.gfx.animInfo.animID; if (val6 == 0x0080 || val6 == 0x007F || val6 == 0x006C) { return TRUE; diff --git a/src/game/interaction.h b/src/game/interaction.h index baa9e2b7..3069adea 100644 --- a/src/game/interaction.h +++ b/src/game/interaction.h @@ -85,7 +85,7 @@ enum InteractionType { #define INT_STATUS_MARIO_UNK1 (1 << 1) /* 0x00000002 */ #define INT_STATUS_MARIO_UNK2 (1 << 2) /* 0x00000004 */ #define INT_STATUS_MARIO_DROP_OBJECT (1 << 3) /* 0x00000008 */ -#define INT_STATUS_MARIO_UNK4 (1 << 4) /* 0x00000010 */ +#define INT_STATUS_HIT_BY_SHOCKWAVE (1 << 4) /* 0x00000010 */ #define INT_STATUS_MARIO_UNK5 (1 << 5) /* 0x00000020 */ #define INT_STATUS_MARIO_UNK6 (1 << 6) /* 0x00000040 */ #define INT_STATUS_MARIO_UNK7 (1 << 7) /* 0x00000080 */ @@ -106,7 +106,7 @@ void mario_grab_used_object(struct MarioState *m); void mario_drop_held_object(struct MarioState *m); void mario_throw_held_object(struct MarioState *m); void mario_stop_riding_and_holding(struct MarioState *m); -u32 does_mario_have_hat(struct MarioState *m); +u32 does_mario_have_normal_cap_on_head(struct MarioState *m); void mario_blow_off_cap(struct MarioState *m, f32 capSpeed); u32 mario_lose_cap_to_enemy(struct MarioState* m, u32 arg); void mario_retrieve_cap(struct MarioState* m); diff --git a/src/game/level_geo.c b/src/game/level_geo.c index 19e009d0..b6674b72 100644 --- a/src/game/level_geo.c +++ b/src/game/level_geo.c @@ -55,6 +55,7 @@ Gfx *geo_envfx_main(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtxf) { vec3s_copy(marioPos, gVec3sZero); envfx_update_particles(ENVFX_MODE_NONE, marioPos, camTo, camFrom); } + return gfx; } @@ -77,5 +78,6 @@ Gfx *geo_skybox_main(s32 callContext, struct GraphNode *node, UNUSED Mat4 *mtx) gLakituState.pos[1], gLakituState.pos[2], gLakituState.focus[0], gLakituState.focus[1], gLakituState.focus[2]); } + return gfx; } diff --git a/src/game/level_update.c b/src/game/level_update.c index 977224bb..fd837ca4 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -173,11 +173,11 @@ s32 sDelayedWarpArg; s16 unusedEULevelUpdateBss1; #endif s8 sTimerRunning; -s8 gShouldNotPlayCastleMusic; +s8 gNeverEnteredCastle; struct MarioState *gMarioState = &gMarioStates[0]; u8 unused1[4] = { 0 }; -s8 gInWarpCheckpoint = 0; +s8 sWarpCheckpointActive = FALSE; u8 unused3[4]; u8 unused4[2]; @@ -491,7 +491,7 @@ void init_mario_after_warp(void) { #ifndef VERSION_JP if (gCurrLevelNum == LEVEL_BOB && get_current_background_music() != SEQUENCE_ARGS(4, SEQ_LEVEL_SLIDE) - && sTimerRunning != 0) { + && sTimerRunning) { play_music(SEQ_PLAYER_LEVEL, SEQUENCE_ARGS(4, SEQ_LEVEL_SLIDE), 0); } #endif @@ -737,7 +737,7 @@ static void initiate_painting_warp_node(struct WarpNode *pWarpNode) { struct WarpNode warpNode = *pWarpNode; if (!(warpNode.destLevel & 0x80)) { - gInWarpCheckpoint = check_warp_checkpoint(&warpNode); + sWarpCheckpointActive = check_warp_checkpoint(&warpNode); } initiate_warp(warpNode.destLevel & 0x7F, warpNode.destArea, warpNode.destNode, 0); @@ -764,6 +764,7 @@ void initiate_painting_warp(void) { play_painting_eject_sound(); } else if (pWarpNode->id != 0) { initiate_painting_warp_node(pWarpNode); + set_mario_action(gMarioState, ACT_DISAPPEARED, 0); gMarioState->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE; } @@ -790,8 +791,7 @@ s16 level_trigger_warp(struct MarioState *m, s32 warpOp) { switch (warpOp) { case WARP_OP_DEMO_NEXT: - case WARP_OP_DEMO_END: - do {sDelayedWarpTimer = 20;} while (0); + case WARP_OP_DEMO_END: sDelayedWarpTimer = 20; // Must be one line to match on -O2 sSourceWarpNodeId = WARP_NODE_F0; gSavedCourseNum = COURSE_NONE; val04 = FALSE; @@ -987,7 +987,7 @@ void update_hud_values(void) { if (gCurrCreditsEntry == NULL) { s16 numHealthWedges = gMarioState->health > 0 ? gMarioState->health >> 8 : 0; - if (gCurrCourseNum > 0) { + if (gCurrCourseNum >= COURSE_MIN) { gHudDisplay.flags |= HUD_DISPLAY_FLAG_COIN_COUNT; } else { gHudDisplay.flags &= ~HUD_DISPLAY_FLAG_COIN_COUNT; @@ -1206,7 +1206,6 @@ s32 play_mode_change_area(void) { sTransitionTimer -= 1; } - //! If sTransitionTimer is -1, this will miss. if (sTransitionTimer == 0) { sTransitionUpdate = NULL; set_play_mode(PLAY_MODE_NORMAL); @@ -1228,7 +1227,6 @@ s32 play_mode_change_level(void) { sTransitionUpdate(&sTransitionTimer); } - //! If sTransitionTimer is -1, this will miss. if (--sTransitionTimer == -1) { gHudDisplay.flags = HUD_DISPLAY_NONE; sTransitionTimer = 0; @@ -1344,7 +1342,7 @@ s32 init_level(void) { gHudDisplay.flags = HUD_DISPLAY_NONE; } - sTimerRunning = 0; + sTimerRunning = FALSE; if (sWarpDest.type != WARP_TYPE_NOT_WARPING) { if (sWarpDest.nodeId >= WARP_NODE_CREDITS_MIN) { @@ -1363,7 +1361,7 @@ s32 init_level(void) { if (gCurrDemoInput != NULL) { set_mario_action(gMarioState, ACT_IDLE, 0); - } else if (gDebugLevelSelect == 0) { + } else if (!gDebugLevelSelect) { if (gMarioState->action != ACT_UNINITIALIZED) { bool skipIntro = (gNetworkType == NT_NONE || gServerSettings.skipIntro != 0); if (gDjuiInMainMenu && (gNetworkType == NT_NONE)) { @@ -1445,14 +1443,14 @@ s32 lvl_init_from_save_file(UNUSED s16 arg0, s32 levelNum) { #endif sWarpDest.type = WARP_TYPE_NOT_WARPING; sDelayedWarpOp = WARP_OP_NONE; - gShouldNotPlayCastleMusic = !save_file_exists(gCurrSaveFileNum - 1) && gCLIOpts.SkipIntro == 0 && configSkipIntro == 0; - if (gNetworkType == NT_NONE) { gShouldNotPlayCastleMusic = true; } + gNeverEnteredCastle = !save_file_exists(gCurrSaveFileNum - 1) && gCLIOpts.SkipIntro == 0 && configSkipIntro == 0; + if (gNetworkType == NT_NONE) { gNeverEnteredCastle = true; } gCurrLevelNum = levelNum; gCurrCourseNum = COURSE_NONE; gSavedCourseNum = COURSE_NONE; gCurrCreditsEntry = NULL; - gSpecialTripleJump = 0; + gSpecialTripleJump = FALSE; init_mario_from_save_file(); disable_warp_checkpoint(); @@ -1464,9 +1462,9 @@ s32 lvl_init_from_save_file(UNUSED s16 arg0, s32 levelNum) { } s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum) { - s32 val4 = gInWarpCheckpoint; + s32 warpCheckpointActive = sWarpCheckpointActive; - gInWarpCheckpoint = 0; + sWarpCheckpointActive = FALSE; gCurrLevelNum = levelNum; gCurrCourseNum = gLevelToCourseNumTable[levelNum - 1]; @@ -1487,11 +1485,11 @@ s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum) { disable_warp_checkpoint(); } - if (gCurrCourseNum > COURSE_STAGES_MAX || val4 != 0) { + if (gCurrCourseNum > COURSE_STAGES_MAX || warpCheckpointActive) { return 0; } - if (gDebugLevelSelect != 0 && gShowProfiler == 0) { + if (gDebugLevelSelect && !gShowProfiler) { return 0; } @@ -1515,8 +1513,8 @@ s32 lvl_exiting_credits(UNUSED s16 arg0, UNUSED s32 arg1) { void fake_lvl_init_from_save_file(void) { sWarpDest.type = WARP_TYPE_NOT_WARPING; sDelayedWarpOp = WARP_OP_NONE; - gShouldNotPlayCastleMusic = !save_file_exists(gCurrSaveFileNum - 1) && gServerSettings.skipIntro; - if (gNetworkType == NT_NONE) { gShouldNotPlayCastleMusic = true; } + gNeverEnteredCastle = !save_file_exists(gCurrSaveFileNum - 1) && gServerSettings.skipIntro; + if (gNetworkType == NT_NONE) { gNeverEnteredCastle = true; } gCurrCreditsEntry = NULL; gSpecialTripleJump = 0; diff --git a/src/game/level_update.h b/src/game/level_update.h index 3ae895d1..8a622577 100644 --- a/src/game/level_update.h +++ b/src/game/level_update.h @@ -99,7 +99,7 @@ struct SavedWarpValues { }; extern struct WarpDest sWarpDest; -extern s8 gInWarpCheckpoint; +extern s8 sWarpCheckpointActive; extern u8 gRejectInstantWarp; extern s16 D_80339EE0; @@ -121,7 +121,7 @@ struct HudDisplay { }; extern struct HudDisplay gHudDisplay; -extern s8 gShouldNotPlayCastleMusic; +extern s8 gNeverEnteredCastle; extern u32 gControlTimerStartNat; extern u32 gControlTimerStopNat; diff --git a/src/game/macro_special_objects.c b/src/game/macro_special_objects.c index 17e4e6c4..b95142d6 100644 --- a/src/game/macro_special_objects.c +++ b/src/game/macro_special_objects.c @@ -112,8 +112,8 @@ void spawn_macro_objects(s16 areaIndex, s16 *macroObjList) { struct Object *newObj; struct LoadedPreset preset; - gMacroObjectDefaultParent.header.gfx.unk18 = areaIndex; - gMacroObjectDefaultParent.header.gfx.unk19 = areaIndex; + gMacroObjectDefaultParent.header.gfx.areaIndex = areaIndex; + gMacroObjectDefaultParent.header.gfx.activeAreaIndex = areaIndex; while (TRUE) { if (*macroObjList == -1) { // An encountered value of -1 means the list has ended. @@ -184,8 +184,8 @@ void spawn_macro_objects_hardcoded(s16 areaIndex, s16 *macroObjList) { UNUSED u8 pad2[10]; - gMacroObjectDefaultParent.header.gfx.unk18 = areaIndex; - gMacroObjectDefaultParent.header.gfx.unk19 = areaIndex; + gMacroObjectDefaultParent.header.gfx.areaIndex = areaIndex; + gMacroObjectDefaultParent.header.gfx.activeAreaIndex = areaIndex; while (TRUE) { macroObjPreset = *macroObjList++; @@ -258,8 +258,8 @@ void spawn_special_objects(s16 areaIndex, s16 **specialObjList) { numOfSpecialObjects = **specialObjList; (*specialObjList)++; - gMacroObjectDefaultParent.header.gfx.unk18 = areaIndex; - gMacroObjectDefaultParent.header.gfx.unk19 = areaIndex; + gMacroObjectDefaultParent.header.gfx.areaIndex = areaIndex; + gMacroObjectDefaultParent.header.gfx.activeAreaIndex = areaIndex; for (i = 0; i < numOfSpecialObjects; i++) { presetID = (u8) * *specialObjList; diff --git a/src/game/macro_special_objects.h b/src/game/macro_special_objects.h index c2ba81f4..8d836b4b 100644 --- a/src/game/macro_special_objects.h +++ b/src/game/macro_special_objects.h @@ -5,7 +5,6 @@ #include "types.h" -/* Functions */ s16 convert_rotation(s16 inRotation); void spawn_macro_abs_yrot_2params(u32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 ry, s16 params); diff --git a/src/game/main.c b/src/game/main.c index 3c6d863c..8fb47ac0 100644 --- a/src/game/main.c +++ b/src/game/main.c @@ -63,11 +63,11 @@ struct SPTask *sCurrentAudioSPTask = NULL; struct SPTask *sCurrentDisplaySPTask = NULL; struct SPTask *sNextAudioSPTask = NULL; struct SPTask *sNextDisplaySPTask = NULL; -s8 sAudioEnabled = 1; +s8 sAudioEnabled = TRUE; u32 sNumVblanks = 0; s8 gResetTimer = 0; s8 D_8032C648 = 0; -s8 gDebugLevelSelect = 0; +s8 gDebugLevelSelect = FALSE; s8 D_8032C650 = 0; s8 gShowProfiler = FALSE; @@ -256,7 +256,7 @@ void handle_vblank(void) { interrupt_gfx_sptask(); } else { profiler_log_vblank_time(); - if (sAudioEnabled != 0) { + if (sAudioEnabled) { start_sptask(M_AUDTASK); } else { pretend_audio_sptask_done(); @@ -299,7 +299,7 @@ void handle_sp_complete(void) { // Start the audio task, as expected by handle_vblank. profiler_log_vblank_time(); - if (sAudioEnabled != 0) { + if (sAudioEnabled) { start_sptask(M_AUDTASK); } else { pretend_audio_sptask_done(); @@ -350,7 +350,7 @@ void thread3_main(UNUSED void *arg) { create_thread(&gGameLoopThread, 5, thread5_game_loop, NULL, gThread5Stack + 0x2000, 10); osStartThread(&gGameLoopThread); - while (1) { + while (TRUE) { OSMesg msg; osRecvMesg(&gIntrMesgQueue, &msg, OS_MESG_BLOCK); @@ -395,7 +395,7 @@ void send_sp_task_message(OSMesg *msg) { } void dispatch_audio_sptask(struct SPTask *spTask) { - if (sAudioEnabled != 0 && spTask != NULL) { + if (sAudioEnabled && spTask != NULL) { osWritebackDCacheAll(); osSendMesg(&gSPTaskMesgQueue, spTask, OS_MESG_NOBLOCK); } @@ -416,11 +416,11 @@ void send_display_list(struct SPTask *spTask) { } void turn_on_audio(void) { - sAudioEnabled = 1; + sAudioEnabled = TRUE; } void turn_off_audio(void) { - sAudioEnabled = 0; + sAudioEnabled = FALSE; while (sCurrentAudioSPTask != NULL) { ; } @@ -457,7 +457,7 @@ void thread1_idle(UNUSED void *arg) { osSetThreadPri(NULL, 0); // halt - while (1) { + while (TRUE) { ; } } diff --git a/src/game/mario.c b/src/game/mario.c index 86a2f00d..a4bceb18 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -6,7 +6,6 @@ #include "sm64.h" #include "area.h" -#include "audio/data.h" #include "audio/external.h" #include "behavior_actions.h" #include "behavior_data.h" @@ -62,8 +61,9 @@ u16 gLocalBubbleCounter = 0; */ s32 is_anim_at_end(struct MarioState *m) { struct Object *o = m->marioObj; - if (o->header.gfx.unk38.curAnim == NULL) { return TRUE; } - return (o->header.gfx.unk38.animFrame + 1) == o->header.gfx.unk38.curAnim->unk08; + + if (o->header.gfx.animInfo.curAnim == NULL) { return TRUE; } + return (o->header.gfx.animInfo.animFrame + 1) == o->header.gfx.animInfo.curAnim->loopEnd; } /** @@ -72,7 +72,7 @@ s32 is_anim_at_end(struct MarioState *m) { s32 is_anim_past_end(struct MarioState *m) { struct Object *o = m->marioObj; - return o->header.gfx.unk38.animFrame >= (o->header.gfx.unk38.curAnim->unk08 - 2); + return o->header.gfx.animInfo.animFrame >= (o->header.gfx.animInfo.curAnim->loopEnd - 2); } /** @@ -87,24 +87,24 @@ s16 set_mario_animation(struct MarioState *m, s32 targetAnimID) { targetAnim->index = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->index); } - if (o->header.gfx.unk38.animID != targetAnimID) { - o->header.gfx.unk38.animID = targetAnimID; - o->header.gfx.unk38.curAnim = targetAnim; - o->header.gfx.unk38.animAccel = 0; - o->header.gfx.unk38.animYTrans = m->unkB0; + if (o->header.gfx.animInfo.animID != targetAnimID) { + o->header.gfx.animInfo.animID = targetAnimID; + o->header.gfx.animInfo.curAnim = targetAnim; + o->header.gfx.animInfo.animAccel = 0; + o->header.gfx.animInfo.animYTrans = m->unkB0; if (targetAnim->flags & ANIM_FLAG_2) { - o->header.gfx.unk38.animFrame = targetAnim->unk04; + o->header.gfx.animInfo.animFrame = targetAnim->startFrame; } else { if (targetAnim->flags & ANIM_FLAG_FORWARD) { - o->header.gfx.unk38.animFrame = targetAnim->unk04 + 1; + o->header.gfx.animInfo.animFrame = targetAnim->startFrame + 1; } else { - o->header.gfx.unk38.animFrame = targetAnim->unk04 - 1; + o->header.gfx.animInfo.animFrame = targetAnim->startFrame - 1; } } } - return o->header.gfx.unk38.animFrame; + return o->header.gfx.animInfo.animFrame; } /** @@ -120,34 +120,34 @@ s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel) targetAnim->index = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->index); } - if (o->header.gfx.unk38.animID != targetAnimID) { - o->header.gfx.unk38.animID = targetAnimID; - o->header.gfx.unk38.curAnim = targetAnim; - o->header.gfx.unk38.animYTrans = m->unkB0; + if (o->header.gfx.animInfo.animID != targetAnimID) { + o->header.gfx.animInfo.animID = targetAnimID; + o->header.gfx.animInfo.curAnim = targetAnim; + o->header.gfx.animInfo.animYTrans = m->unkB0; if (targetAnim->flags & ANIM_FLAG_2) { - o->header.gfx.unk38.animFrameAccelAssist = (targetAnim->unk04 << 0x10); + o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10); } else { if (targetAnim->flags & ANIM_FLAG_FORWARD) { - o->header.gfx.unk38.animFrameAccelAssist = (targetAnim->unk04 << 0x10) + accel; + o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10) + accel; } else { - o->header.gfx.unk38.animFrameAccelAssist = (targetAnim->unk04 << 0x10) - accel; + o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10) - accel; } } - o->header.gfx.unk38.animFrame = (o->header.gfx.unk38.animFrameAccelAssist >> 0x10); + o->header.gfx.animInfo.animFrame = (o->header.gfx.animInfo.animFrameAccelAssist >> 0x10); } - o->header.gfx.unk38.animAccel = accel; + o->header.gfx.animInfo.animAccel = accel; - return o->header.gfx.unk38.animFrame; + return o->header.gfx.animInfo.animFrame; } /** * Sets the animation to a specific "next" frame from the frame given. */ void set_anim_to_frame(struct MarioState *m, s16 animFrame) { - struct GraphNodeObject_sub *animInfo = &m->marioObj->header.gfx.unk38; + struct AnimInfo *animInfo = &m->marioObj->header.gfx.animInfo; struct Animation *curAnim = animInfo->curAnim; if (animInfo->animAccel) { @@ -168,7 +168,7 @@ void set_anim_to_frame(struct MarioState *m, s16 animFrame) { s32 is_anim_past_frame(struct MarioState *m, s16 animFrame) { s32 isPastFrame; s32 acceleratedFrame = animFrame << 0x10; - struct GraphNodeObject_sub *animInfo = &m->marioObj->header.gfx.unk38; + struct AnimInfo *animInfo = &m->marioObj->header.gfx.animInfo; struct Animation *curAnim = animInfo->curAnim; if (animInfo->animAccel) { @@ -200,9 +200,9 @@ s16 find_mario_anim_flags_and_translation(struct Object *obj, s32 yaw, Vec3s tra f32 dx; f32 dz; - struct Animation *curAnim = (void *) obj->header.gfx.unk38.curAnim; + struct Animation *curAnim = (void *) obj->header.gfx.animInfo.curAnim; if (curAnim == NULL) { return 0; } - s16 animFrame = geo_update_animation_frame(&obj->header.gfx.unk38, NULL); + s16 animFrame = geo_update_animation_frame(&obj->header.gfx.animInfo, NULL); u16 *animIndex = segmented_to_virtual((void *) curAnim->index); s16 *animValues = segmented_to_virtual((void *) curAnim->values); @@ -256,7 +256,7 @@ s16 return_mario_anim_y_translation(struct MarioState *m) { * Plays a sound if if Mario doesn't have the flag being checked. */ void play_sound_if_no_flag(struct MarioState *m, u32 soundBits, u32 flags) { - if ((m->flags & flags) == 0) { + if (!(m->flags & flags)) { play_sound(soundBits, m->marioObj->header.gfx.cameraToObject); m->flags |= flags; } @@ -276,7 +276,6 @@ void play_mario_jump_sound(struct MarioState *m) { #ifndef VERSION_JP } #endif - m->flags |= MARIO_MARIO_SOUND_PLAYED; } } @@ -324,7 +323,7 @@ void play_sound_and_spawn_particles(struct MarioState *m, u32 soundBits, u32 wav * Plays an environmental sound if one has not been played since the last action change. */ void play_mario_action_sound(struct MarioState *m, u32 soundBits, u32 waveParticleType) { - if ((m->flags & MARIO_ACTION_SOUND_PLAYED) == 0) { + if (!(m->flags & MARIO_ACTION_SOUND_PLAYED)) { play_sound_and_spawn_particles(m, soundBits, waveParticleType); m->flags |= MARIO_ACTION_SOUND_PLAYED; } @@ -344,8 +343,8 @@ void play_mario_landing_sound(struct MarioState *m, u32 soundBits) { * played once per action. */ void play_mario_landing_sound_once(struct MarioState *m, u32 soundBits) { - play_mario_action_sound(m, (m->flags & MARIO_METAL_CAP) ? SOUND_ACTION_METAL_LANDING : soundBits, - 1); + play_mario_action_sound( + m, (m->flags & MARIO_METAL_CAP) ? SOUND_ACTION_METAL_LANDING : soundBits, 1); } /** @@ -371,9 +370,8 @@ void play_mario_heavy_landing_sound_once(struct MarioState *m, u32 soundBits) { */ void play_mario_sound(struct MarioState *m, s32 actionSound, s32 marioSound) { if (actionSound == SOUND_ACTION_TERRAIN_JUMP) { - play_mario_action_sound( - m, (m->flags & MARIO_METAL_CAP) ? (s32)SOUND_ACTION_METAL_JUMP - : (s32)SOUND_ACTION_TERRAIN_JUMP, 1); + play_mario_action_sound(m, (m->flags & MARIO_METAL_CAP) ? (s32) SOUND_ACTION_METAL_JUMP + : (s32) SOUND_ACTION_TERRAIN_JUMP, 1); } else { play_sound_if_no_flag(m, actionSound, MARIO_ACTION_SOUND_PLAYED); } @@ -447,7 +445,7 @@ s32 mario_get_floor_class(struct MarioState *m) { floorClass = SURFACE_CLASS_DEFAULT; } - if (m->floor) { + if (m->floor != NULL) { switch (m->floor->type) { case SURFACE_NOT_SLIPPERY: case SURFACE_HARD_NOT_SLIPPERY: @@ -513,7 +511,7 @@ u32 mario_get_terrain_sound_addend(struct MarioState *m) { s32 ret = SOUND_TERRAIN_DEFAULT << 16; s32 floorType; - if (m->floor) { + if (m->floor != NULL) { floorType = m->floor->type; if ((gCurrLevelNum != LEVEL_LLL) && (m->floorHeight < (m->waterLevel - 10))) { @@ -658,26 +656,25 @@ s32 mario_floor_is_slope(struct MarioState *m) { f32 normY; if ((m->area->terrainType & TERRAIN_MASK) == TERRAIN_SLIDE - && m->floor->normal.y < 0.9998477f //~cos(1 deg) - ) { + && m->floor->normal.y < 0.9998477f) { // ~cos(1 deg) return TRUE; } switch (mario_get_floor_class(m)) { case SURFACE_VERY_SLIPPERY: - normY = 0.9961947f; //~cos(5 deg) + normY = 0.9961947f; // ~cos(5 deg) break; case SURFACE_SLIPPERY: - normY = 0.9848077f; //~cos(10 deg) + normY = 0.9848077f; // ~cos(10 deg) break; default: - normY = 0.9659258f; //~cos(15 deg) + normY = 0.9659258f; // ~cos(15 deg) break; case SURFACE_NOT_SLIPPERY: - normY = 0.9396926f; //~cos(20 deg) + normY = 0.9396926f; // ~cos(20 deg) break; } @@ -698,19 +695,19 @@ s32 mario_floor_is_steep(struct MarioState *m) { if (!mario_facing_downhill(m, FALSE)) { switch (mario_get_floor_class(m)) { case SURFACE_VERY_SLIPPERY: - normY = 0.9659258f; //~cos(15 deg) + normY = 0.9659258f; // ~cos(15 deg) break; case SURFACE_SLIPPERY: - normY = 0.9396926f; //~cos(20 deg) + normY = 0.9396926f; // ~cos(20 deg) break; default: - normY = 0.8660254f; //~cos(30 deg) + normY = 0.8660254f; // ~cos(30 deg) break; case SURFACE_NOT_SLIPPERY: - normY = 0.8660254f; //~cos(30 deg) + normY = 0.8660254f; // ~cos(30 deg) break; } @@ -837,10 +834,9 @@ static void set_mario_y_vel_based_on_fspeed(struct MarioState *m, f32 initialVel static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actionArg) { f32 fowardVel; - if (m->squishTimer != 0 || m->quicksandDepth >= 1.0f) { - if (action == ACT_DOUBLE_JUMP || action == ACT_TWIRLING) { - action = ACT_JUMP; - } + if ((m->squishTimer != 0 || m->quicksandDepth >= 1.0f) + && (action == ACT_DOUBLE_JUMP || action == ACT_TWIRLING)) { + action = ACT_JUMP; } switch (action) { @@ -850,7 +846,7 @@ static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actio break; case ACT_BACKFLIP: - m->marioObj->header.gfx.unk38.animID = -1; + m->marioObj->header.gfx.animInfo.animID = -1; m->forwardVel = -16.0f; set_mario_y_vel_based_on_fspeed(m, 62.0f, 0.0f); break; @@ -882,7 +878,7 @@ static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actio case ACT_JUMP: case ACT_HOLD_JUMP: - m->marioObj->header.gfx.unk38.animID = -1; + m->marioObj->header.gfx.animInfo.animID = -1; set_mario_y_vel_based_on_fspeed(m, 42.0f, 0.25f); m->forwardVel *= 0.8f; break; @@ -903,7 +899,7 @@ static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actio break; case ACT_STEEP_JUMP: - m->marioObj->header.gfx.unk38.animID = -1; + m->marioObj->header.gfx.animInfo.animID = -1; set_mario_y_vel_based_on_fspeed(m, 42.0f, 0.25f); m->faceAngle[0] = -0x2000; break; @@ -923,7 +919,7 @@ static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actio break; case ACT_LONG_JUMP: - m->marioObj->header.gfx.unk38.animID = -1; + m->marioObj->header.gfx.animInfo.animID = -1; set_mario_y_vel_based_on_fspeed(m, 30.0f, 0.0f); m->marioObj->oMarioLongJumpIsSlow = m->forwardVel > 16.0f ? FALSE : TRUE; @@ -1249,7 +1245,7 @@ s32 set_water_plunge_action(struct MarioState *m) { vec3s_set(m->angleVel, 0, 0, 0); - if ((m->action & ACT_FLAG_DIVING) == 0) { + if (!(m->action & ACT_FLAG_DIVING)) { m->faceAngle[0] = 0; } @@ -1354,7 +1350,7 @@ void update_mario_button_inputs(struct MarioState *m) { if (m->input & INPUT_B_PRESSED) { m->framesSinceB = 0; - } else if (m->framesSinceB < 0xff) { + } else if (m->framesSinceB < 0xFF) { m->framesSinceB += 1; } } @@ -1418,7 +1414,7 @@ copyPlayerGoto:; gasLevel = find_poison_gas_level(m->pos[0], m->pos[2]); m->waterLevel = find_water_level(m->pos[0], m->pos[2]); - if (m->floor) { + if (m->floor != NULL) { m->floorAngle = atan2s(m->floor->normal.z, m->floor->normal.x); m->terrainSoundAddend = mario_get_terrain_sound_addend(m); @@ -1522,7 +1518,7 @@ void update_mario_inputs(struct MarioState *m) { } if (m->marioObj->oInteractStatus - & (INT_STATUS_HOOT_GRABBED_BY_MARIO | INT_STATUS_MARIO_UNK1 | INT_STATUS_MARIO_UNK4)) { + & (INT_STATUS_HOOT_GRABBED_BY_MARIO | INT_STATUS_MARIO_UNK1 | INT_STATUS_HIT_BY_SHOCKWAVE)) { m->input |= INPUT_UNKNOWN_10; } if (m->heldObj != NULL) { @@ -1554,7 +1550,7 @@ void set_submerged_cam_preset_and_spawn_bubbles(struct MarioState *m) { heightBelowWater = (f32)(m->waterLevel - 80) - m->pos[1]; camPreset = m->area->camera->mode; - if ((m->action & ACT_FLAG_METAL_WATER)) { + if (m->action & ACT_FLAG_METAL_WATER) { if (m->playerIndex == 0 && camPreset != CAMERA_MODE_CLOSE) { set_camera_mode(m->area->camera, CAMERA_MODE_CLOSE, 1); } @@ -1569,7 +1565,7 @@ void set_submerged_cam_preset_and_spawn_bubbles(struct MarioState *m) { // As long as Mario isn't drowning or at the top // of the water with his head out, spawn bubbles. - if ((m->action & ACT_FLAG_INTANGIBLE) == 0) { + if (!(m->action & ACT_FLAG_INTANGIBLE)) { if ((m->pos[1] < (f32)(m->waterLevel - 160)) || (m->faceAngle[0] < -0x800)) { m->particleFlags |= PARTICLE_BUBBLE; } @@ -1587,12 +1583,12 @@ void update_mario_health(struct MarioState *m) { if (m->health >= 0x100) { // When already healing or hurting Mario, Mario's HP is not changed any more here. if (((u32) m->healCounter | (u32) m->hurtCounter) == 0) { - if ((m->input & INPUT_IN_POISON_GAS) && ((m->action & ACT_FLAG_INTANGIBLE) == 0)) { - if (((m->flags & MARIO_METAL_CAP) == 0) && (gDebugLevelSelect == 0)) { + if ((m->input & INPUT_IN_POISON_GAS) && !(m->action & ACT_FLAG_INTANGIBLE)) { + if (!(m->flags & MARIO_METAL_CAP) && !gDebugLevelSelect) { m->health -= 4; } } else { - if ((m->action & ACT_FLAG_SWIMMING) && ((m->action & ACT_FLAG_INTANGIBLE) == 0)) { + if ((m->action & ACT_FLAG_SWIMMING) && !(m->action & ACT_FLAG_INTANGIBLE)) { terrainIsSnow = (m->area->terrainType & TERRAIN_MASK) == TERRAIN_SNOW; // When Mario is near the water surface, recover health (unless in snow), @@ -1600,7 +1596,7 @@ void update_mario_health(struct MarioState *m) { // If using the debug level select, do not lose any HP to water. if ((m->pos[1] >= (m->waterLevel - 140)) && !terrainIsSnow) { m->health += 0x1A; - } else if (gDebugLevelSelect == 0) { + } else if (!gDebugLevelSelect) { m->health -= (terrainIsSnow ? 3 : 1); } } @@ -1616,7 +1612,7 @@ void update_mario_health(struct MarioState *m) { m->hurtCounter--; } - if (m->health >= 0x881) { + if (m->health > 0x880) { m->health = 0x880; } if (m->health < 0x100) { @@ -1655,7 +1651,7 @@ void update_mario_info_for_cam(struct MarioState *m) { vec3s_copy(m->statusForCamera->faceAngle, m->faceAngle); - if ((m->flags & MARIO_UNKNOWN_25) == 0) { + if (!(m->flags & MARIO_UNKNOWN_25)) { vec3f_copy(m->statusForCamera->pos, m->pos); } } @@ -1716,23 +1712,21 @@ u32 update_and_return_cap_flags(struct MarioState *m) { if (m->capTimer == 0) { stop_cap_music(); - m->flags &= ~(MARIO_VANISH_CAP | MARIO_METAL_CAP | MARIO_WING_CAP); - if ((m->flags & (MARIO_NORMAL_CAP | MARIO_VANISH_CAP | MARIO_METAL_CAP | MARIO_WING_CAP)) - == 0) { + m->flags &= ~MARIO_SPECIAL_CAPS; + if (!(m->flags & MARIO_CAPS)) { m->flags &= ~MARIO_CAP_ON_HEAD; } } - if (m->capTimer == 0x3C) { + if (m->capTimer == 60) { fadeout_cap_music(); } // This code flickers the cap through a long binary string, increasing in how // common it flickers near the end. - if ((m->capTimer < 0x40) && ((1ULL << m->capTimer) & sCapFlickerFrames)) { - flags &= ~(MARIO_VANISH_CAP | MARIO_METAL_CAP | MARIO_WING_CAP); - if ((flags & (MARIO_NORMAL_CAP | MARIO_VANISH_CAP | MARIO_METAL_CAP | MARIO_WING_CAP)) - == 0) { + if ((m->capTimer < 64) && ((1ULL << m->capTimer) & sCapFlickerFrames)) { + flags &= ~MARIO_SPECIAL_CAPS; + if (!(flags & MARIO_CAPS)) { flags &= ~MARIO_CAP_ON_HEAD; } } @@ -1760,13 +1754,11 @@ void mario_update_hitbox_and_cap_model(struct MarioState *m) { bodyState->modelState |= MODEL_STATE_METAL; } - if (m->invincTimer >= 3) { - //! (Pause buffered hitstun) Since the global timer increments while paused, - // this can be paused through to give continual invisibility. This leads to - // no interaction with objects. - if (gGlobalTimer & 1) { - m->marioObj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE; - } + //! (Pause buffered hitstun) Since the global timer increments while paused, + // this can be paused through to give continual invisibility. This leads to + // no interaction with objects. + if ((m->invincTimer >= 3) && (gGlobalTimer & 1)) { + m->marioObj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE; } if (flags & MARIO_CAP_IN_HAND) { @@ -1809,7 +1801,7 @@ static void debug_update_mario_cap(u16 button, s32 flags, u16 capTimer, u16 capM // (which is also what other debug functions do), // so likely debug behavior rather than unused behavior. if ((gPlayer1Controller->buttonDown & Z_TRIG) && (gPlayer1Controller->buttonPressed & button) - && ((gMarioState->flags & flags) == 0)) { + && !(gMarioState->flags & flags)) { gMarioState->flags |= (flags + MARIO_CAP_ON_HEAD); if (capTimer > gMarioState->capTimer) { @@ -2121,7 +2113,7 @@ static void init_single_mario(struct MarioState* m) { m->area = gCurrentArea; m->marioObj = gMarioObjects[m->playerIndex]; if (m->marioObj == NULL) { return; } - m->marioObj->header.gfx.unk38.animID = -1; + m->marioObj->header.gfx.animInfo.animID = -1; vec3s_copy(m->faceAngle, spawnInfo->startAngle); vec3s_set(m->angleVel, 0, 0, 0); vec3s_to_vec3f(m->pos, spawnInfo->startPos); diff --git a/src/game/mario_actions_airborne.c b/src/game/mario_actions_airborne.c index 35fadfa3..f9f79e2e 100644 --- a/src/game/mario_actions_airborne.c +++ b/src/game/mario_actions_airborne.c @@ -2,7 +2,6 @@ #include "sm64.h" #include "area.h" -#include "audio/data.h" #include "audio/external.h" #include "camera.h" #include "engine/graph_node.h" @@ -25,7 +24,7 @@ #include "pc/lua/smlua.h" void play_flip_sounds(struct MarioState *m, s16 frame1, s16 frame2, s16 frame3) { - s32 animFrame = m->marioObj->header.gfx.unk38.animFrame; + s32 animFrame = m->marioObj->header.gfx.animInfo.animFrame; if (animFrame == frame1 || animFrame == frame2 || animFrame == frame3) { play_sound(SOUND_ACTION_SPIN, m->marioObj->header.gfx.cameraToObject); } @@ -609,9 +608,9 @@ s32 act_side_flip(struct MarioState *m) { m->marioObj->header.gfx.angle[1] += 0x8000; } - // (this need to be on one line to match on PAL) + // This must be one line to match on -O2 // clang-format off - if (m->marioObj->header.gfx.unk38.animFrame == 6) play_sound(SOUND_ACTION_SIDE_FLIP_UNK, m->marioObj->header.gfx.cameraToObject); + if (m->marioObj->header.gfx.animInfo.animFrame == 6) play_sound(SOUND_ACTION_SIDE_FLIP_UNK, m->marioObj->header.gfx.cameraToObject); // clang-format on return FALSE; } @@ -938,7 +937,7 @@ s32 act_ground_pound(struct MarioState *m) { } m->actionTimer++; - if (m->actionTimer >= m->marioObj->header.gfx.unk38.curAnim->unk08 + 4) { + if (m->actionTimer >= m->marioObj->header.gfx.animInfo.curAnim->loopEnd + 4) { play_character_sound(m, CHAR_SOUND_GROUND_POUND_WAH); m->actionState = 1; } @@ -1158,7 +1157,7 @@ s32 check_wall_kick(struct MarioState *m) { s32 act_backward_air_kb(struct MarioState *m) { if (check_wall_kick(m)) { - return 1; + return TRUE; } #ifndef VERSION_JP @@ -1172,7 +1171,7 @@ s32 act_backward_air_kb(struct MarioState *m) { s32 act_forward_air_kb(struct MarioState *m) { if (check_wall_kick(m)) { - return 1; + return TRUE; } #ifndef VERSION_JP @@ -1249,7 +1248,7 @@ s32 act_thrown_forward(struct MarioState *m) { s32 act_soft_bonk(struct MarioState *m) { if (check_wall_kick(m)) { - return 1; + return TRUE; } #ifndef VERSION_JP @@ -1348,10 +1347,9 @@ s32 act_air_hit_wall(struct MarioState *m) { //! Missing return statement. The returned value is the result of the call // to set_mario_animation. In practice, this value is nonzero. // This results in this action "cancelling" into itself. It is supposed to - // execute three times, each on a separate frame, but instead it executes - // three times on the same frame. + // execute on two frames, but instead it executes twice on the same frame. // This results in firsties only being possible for a single frame, instead - // of three. + // of two. } s32 act_forward_rollout(struct MarioState *m) { @@ -1430,7 +1428,7 @@ s32 act_backward_rollout(struct MarioState *m) { break; } - if (m->actionState == 1 && m->marioObj->header.gfx.unk38.animFrame == 2) { + if (m->actionState == 1 && m->marioObj->header.gfx.animInfo.animFrame == 2) { m->actionState = 2; } return FALSE; @@ -1641,12 +1639,12 @@ s32 act_jump_kick(struct MarioState *m) { if (m->actionState == 0) { play_character_sound_if_no_flag(m, CHAR_SOUND_PUNCH_HOO, MARIO_ACTION_SOUND_PLAYED); - m->marioObj->header.gfx.unk38.animID = -1; + m->marioObj->header.gfx.animInfo.animID = -1; set_mario_animation(m, MARIO_ANIM_AIR_KICK); m->actionState = 1; } - animFrame = m->marioObj->header.gfx.unk38.animFrame; + animFrame = m->marioObj->header.gfx.animInfo.animFrame; if (animFrame == 0) { m->marioBodyState->punchState = (2 << 6) | 6; } @@ -1819,7 +1817,7 @@ s32 act_flying(struct MarioState *m) { set_mario_animation(m, MARIO_ANIM_FLY_FROM_CANNON); } else { set_mario_animation(m, MARIO_ANIM_FORWARD_SPINNING_FLIP); - if (m->marioObj->header.gfx.unk38.animFrame == 1) { + if (m->marioObj->header.gfx.animInfo.animFrame == 1) { play_sound(SOUND_ACTION_SPIN, m->marioObj->header.gfx.cameraToObject); } } @@ -2014,7 +2012,7 @@ s32 act_flying_triple_jump(struct MarioState *m) { if (m->actionState == 0) { set_mario_animation(m, MARIO_ANIM_TRIPLE_JUMP_FLY); - if (m->marioObj->header.gfx.unk38.animFrame == 7) { + if (m->marioObj->header.gfx.animInfo.animFrame == 7) { play_sound(SOUND_ACTION_SPIN, m->marioObj->header.gfx.cameraToObject); } @@ -2025,7 +2023,7 @@ s32 act_flying_triple_jump(struct MarioState *m) { } } - if (m->actionState == 1 && m->marioObj->header.gfx.unk38.animFrame == 1) { + if (m->actionState == 1 && m->marioObj->header.gfx.animInfo.animFrame == 1) { play_sound(SOUND_ACTION_SPIN, m->marioObj->header.gfx.cameraToObject); } @@ -2091,7 +2089,7 @@ s32 act_vertical_wind(struct MarioState *m) { play_character_sound_if_no_flag(m, CHAR_SOUND_HERE_WE_GO, MARIO_MARIO_SOUND_PLAYED); if (m->actionState == 0) { set_mario_animation(m, MARIO_ANIM_FORWARD_SPINNING_FLIP); - if (m->marioObj->header.gfx.unk38.animFrame == 1) { + if (m->marioObj->header.gfx.animInfo.animFrame == 1) { play_sound(SOUND_ACTION_SPIN, m->marioObj->header.gfx.cameraToObject); queue_rumble_data_mario(m, 8, 80); } diff --git a/src/game/mario_actions_automatic.c b/src/game/mario_actions_automatic.c index fe9433e2..c440e23b 100644 --- a/src/game/mario_actions_automatic.c +++ b/src/game/mario_actions_automatic.c @@ -25,13 +25,13 @@ #include "pc/network/network.h" #include "pc/lua/smlua.h" -#define POLE_NONE 0 +#define POLE_NONE 0 #define POLE_TOUCHED_FLOOR 1 -#define POLE_FELL_OFF 2 +#define POLE_FELL_OFF 2 -#define HANG_NONE 0 +#define HANG_NONE 0 #define HANG_HIT_CEIL_OR_OOB 1 -#define HANG_LEFT_CEIL 2 +#define HANG_LEFT_CEIL 2 void add_tree_leaf_particles(struct MarioState *m) { f32 leafHeight; @@ -156,7 +156,7 @@ s32 act_holding_pole(struct MarioState *m) { if (m->controller->stickY > 16.0f) { f32 poleTop = m->usedObj->hitboxHeight - 100.0f; - void *poleBehavior = virtual_to_segmented(0x13, m->usedObj->behavior); + const BehaviorScript *poleBehavior = virtual_to_segmented(0x13, m->usedObj->behavior); if (marioObj->oMarioPolePos < poleTop - 0.4f) { return set_mario_action(m, ACT_CLIMBING_POLE, 0); @@ -264,7 +264,7 @@ s32 act_grab_pole_fast(struct MarioState *m) { set_mario_animation(m, MARIO_ANIM_GRAB_POLE_SWING_PART1); } else { set_mario_animation(m, MARIO_ANIM_GRAB_POLE_SWING_PART2); - if (is_anim_at_end(m) != 0) { + if (is_anim_at_end(m)) { marioObj->oMarioPoleYawVel = 0; set_mario_action(m, ACT_HOLDING_POLE, 0); } @@ -287,7 +287,7 @@ s32 act_top_of_pole_transition(struct MarioState *m) { } } else { set_mario_animation(m, MARIO_ANIM_RETURN_FROM_HANDSTAND); - if (m->marioObj->header.gfx.unk38.animFrame == 0) { + if (m->marioObj->header.gfx.animInfo.animFrame == 0) { return set_mario_action(m, ACT_HOLDING_POLE, 0); } } @@ -481,7 +481,7 @@ s32 act_hang_moving(struct MarioState *m) { set_mario_animation(m, MARIO_ANIM_MOVE_ON_WIRE_NET_LEFT); } - if (m->marioObj->header.gfx.unk38.animFrame == 12) { + if (m->marioObj->header.gfx.animInfo.animFrame == 12) { play_sound(SOUND_ACTION_HANGING_STEP, m->marioObj->header.gfx.cameraToObject); queue_rumble_data_mario(m, 5, 30); } @@ -581,7 +581,7 @@ s32 act_ledge_grab(struct MarioState *m) { return let_go_of_ledge(m); } #ifdef VERSION_EU - // On PAL, you can't slow climb up ledges while holding A. + // On EU, you can't slow climb up ledges while holding A. if (m->actionTimer == 10 && (m->input & INPUT_NONZERO_ANALOG) && !(m->input & INPUT_A_DOWN)) #else if (m->actionTimer == 10 && (m->input & INPUT_NONZERO_ANALOG)) @@ -630,7 +630,7 @@ s32 act_ledge_climb_slow(struct MarioState *m) { update_ledge_climb(m, MARIO_ANIM_SLOW_LEDGE_GRAB, ACT_IDLE); update_ledge_climb_camera(m); - if (m->marioObj->header.gfx.unk38.animFrame == 17) { + if (m->marioObj->header.gfx.animInfo.animFrame == 17) { m->action = ACT_LEDGE_CLIMB_SLOW_2; } @@ -659,7 +659,7 @@ s32 act_ledge_climb_fast(struct MarioState *m) { update_ledge_climb(m, MARIO_ANIM_FAST_LEDGE_GRAB, ACT_IDLE); - if (m->marioObj->header.gfx.unk38.animFrame == 8) { + if (m->marioObj->header.gfx.animInfo.animFrame == 8) { play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING); } update_ledge_climb_camera(m); diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index 62d11fa9..6f93ed60 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -3,7 +3,6 @@ #include "prevent_bss_reordering.h" #include "sm64.h" #include "area.h" -#include "audio/data.h" #include "audio/external.h" #include "behavior_data.h" #include "camera.h" @@ -56,7 +55,7 @@ static s8 D_8032CBE4 = 0; static s8 D_8032CBE8 = 0; static s8 D_8032CBEC[7] = { 2, 3, 2, 1, 2, 3, 2 }; -static u8 sStarsNeededForDialog[6] = { 1, 3, 8, 30, 50, 70 }; +static u8 sStarsNeededForDialog[] = { 1, 3, 8, 30, 50, 70 }; static BehaviorScript* localDialogNPCBehavior = NULL; @@ -244,7 +243,7 @@ s32 get_star_collection_dialog(struct MarioState *m) { s32 dialogID = 0; s32 numStarsRequired; - for (i = 0; i < 6; i++) { + for (i = 0; i < ARRAY_COUNT(sStarsNeededForDialog); i++) { numStarsRequired = sStarsNeededForDialog[i]; if (m->prevNumStarsForDialog < numStarsRequired && m->numStars >= numStarsRequired) { dialogID = i + DIALOG_141; @@ -462,7 +461,7 @@ s32 act_reading_npc_dialog(struct MarioState *m) { m->actionState++; } - if (m->playerIndex != 0 && gCurrentObject->header.gfx.unk38.animID == -1) { + if (m->playerIndex != 0 && gCurrentObject->header.gfx.animInfo.animID == -1) { // set animation set_mario_animation(m, m->heldObj == NULL ? MARIO_ANIM_FIRST_PERSON : MARIO_ANIM_IDLE_WITH_LIGHT_OBJ); @@ -473,8 +472,8 @@ s32 act_reading_npc_dialog(struct MarioState *m) { // puts Mario in a state where he's waiting for (npc) dialog; doesn't do much s32 act_waiting_for_dialog(struct MarioState *m) { - set_mario_animation(m, - m->heldObj == NULL ? MARIO_ANIM_FIRST_PERSON : MARIO_ANIM_IDLE_WITH_LIGHT_OBJ); + set_mario_animation(m, m->heldObj == NULL ? MARIO_ANIM_FIRST_PERSON + : MARIO_ANIM_IDLE_WITH_LIGHT_OBJ); vec3f_copy(m->marioObj->header.gfx.pos, m->pos); vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1], 0); return FALSE; @@ -533,8 +532,8 @@ s32 act_reading_automatic_dialog(struct MarioState *m) { // finished action else if (m->actionState == 25) { disable_time_stop(); - if (gShouldNotPlayCastleMusic) { - gShouldNotPlayCastleMusic = FALSE; + if (gNeverEnteredCastle) { + gNeverEnteredCastle = FALSE; play_cutscene_music(SEQUENCE_ARGS(0, SEQ_LEVEL_INSIDE_CASTLE)); } if (m->prevAction == ACT_STAR_DANCE_WATER) { @@ -601,7 +600,6 @@ s32 act_reading_sign(struct MarioState *m) { return FALSE; } -// debug free move action s32 act_debug_free_move(struct MarioState *m) { struct Surface *surf; f32 floorHeight; @@ -653,7 +651,6 @@ s32 act_debug_free_move(struct MarioState *m) { return FALSE; } -// star dance handler void general_star_dance_handler(struct MarioState *m, s32 isInWater) { s32 dialogID; if (m->actionState == 0) { @@ -761,7 +758,6 @@ s32 act_fall_after_star_grab(struct MarioState *m) { return FALSE; } -// general death hander s32 common_death_handler(struct MarioState *m, s32 animation, s32 frameToDeathWarp) { s32 animFrame = set_mario_animation(m, animation); if (animFrame == frameToDeathWarp) { @@ -783,7 +779,7 @@ s32 act_standing_death(struct MarioState *m) { play_character_sound_if_no_flag(m, CHAR_SOUND_DYING, MARIO_ACTION_SOUND_PLAYED); common_death_handler(m, MARIO_ANIM_DYING_FALL_OVER, 80); - if (m->marioObj->header.gfx.unk38.animFrame == 77) { + if (m->marioObj->header.gfx.animInfo.animFrame == 77) { play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_BODY_HIT_GROUND); } return FALSE; @@ -888,12 +884,12 @@ s32 act_unlocking_key_door(struct MarioState *m) { m->faceAngle[1] += 0x8000; } - if ((m->actionTimer == 0) || (m->playerIndex != 0 && gCurrentObject->header.gfx.unk38.animID == -1)) { + if ((m->actionTimer == 0) || (m->playerIndex != 0 && gCurrentObject->header.gfx.animInfo.animID == -1)) { spawn_obj_at_mario_rel_yaw(m, MODEL_BOWSER_KEY_CUTSCENE, bhvBowserKeyUnlockDoor, 0); set_mario_animation(m, MARIO_ANIM_UNLOCK_DOOR); } - switch (m->marioObj->header.gfx.unk38.animFrame) { + switch (m->marioObj->header.gfx.animInfo.animFrame) { case 79: play_sound(SOUND_GENERAL_DOOR_INSERT_KEY, m->marioObj->header.gfx.cameraToObject); break; @@ -969,7 +965,6 @@ s32 act_unlocking_star_door(struct MarioState *m) { return FALSE; } -// not sure what kind of door this is s32 act_entering_star_door(struct MarioState *m) { f32 targetDX; f32 targetDZ; @@ -1064,13 +1059,11 @@ s32 act_going_through_door(struct MarioState *m) { if (m->actionTimer == 16) { level_trigger_warp(m, WARP_OP_WARP_DOOR); } - } else { - if (is_anim_at_end(m)) { - if (m->actionArg & 2) { - m->faceAngle[1] += 0x8000; - } - set_mario_action(m, ACT_IDLE, 0); + } else if (is_anim_at_end(m)) { + if (m->actionArg & 2) { + m->faceAngle[1] += 0x8000; } + set_mario_action(m, ACT_IDLE, 0); } m->actionTimer++; @@ -1090,7 +1083,7 @@ s32 act_warp_door_spawn(struct MarioState *m) { } } else if (m->usedObj == NULL || (m->usedObj->oAction == 0 || m->usedObj->oAction == 100)) { if (m->playerIndex == 0) { - if (gShouldNotPlayCastleMusic == TRUE && gCurrLevelNum == LEVEL_CASTLE) { + if (gNeverEnteredCastle == TRUE && gCurrLevelNum == LEVEL_CASTLE) { set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, DIALOG_021); } else { set_mario_action(m, ACT_IDLE, 0); @@ -1477,7 +1470,7 @@ s32 act_bbh_enter_spin(struct MarioState *m) { m->actionState = 4; } if (m->actionState == 2) { - if (m->marioObj->header.gfx.unk38.animFrame == 0) { + if (m->marioObj->header.gfx.animInfo.animFrame == 0) { m->actionState = 3; } } else { @@ -1666,7 +1659,7 @@ s32 act_squished(struct MarioState *m) { } // Both of the 1.8's are really floats, but one of them has to - // be written as a double for this to match on EU. + // be written as a double for this to match on -O2. vec3f_set(m->marioObj->header.gfx.scale, 1.8, 0.05f, 1.8f); queue_rumble_data_mario(m, 10, 80); m->actionState = 1; @@ -2814,7 +2807,7 @@ static s32 act_credits_cutscene(struct MarioState *m) { } if (m->actionTimer++ == TIMER_CREDITS_WARP && m->playerIndex == 0) { - level_trigger_warp(m, 24); + level_trigger_warp(m, WARP_OP_CREDITS_NEXT); } m->marioObj->header.gfx.angle[1] += (gCurrCreditsEntry->unk02 & 0xC0) << 8; @@ -2941,10 +2934,8 @@ s32 mario_execute_cutscene_action(struct MarioState *m) { /* clang-format on */ } - if (!cancel) { - if (m->input & INPUT_IN_WATER) { - m->particleFlags |= PARTICLE_IDLE_WATER_WAVE; - } + if (!cancel && (m->input & INPUT_IN_WATER)) { + m->particleFlags |= PARTICLE_IDLE_WATER_WAVE; } return cancel; diff --git a/src/game/mario_actions_moving.c b/src/game/mario_actions_moving.c index b5948ae9..96445697 100644 --- a/src/game/mario_actions_moving.c +++ b/src/game/mario_actions_moving.c @@ -75,14 +75,14 @@ s16 tilt_body_running(struct MarioState *m) { void play_step_sound(struct MarioState *m, s16 frame1, s16 frame2) { if (is_anim_past_frame(m, frame1) || is_anim_past_frame(m, frame2)) { if (m->flags & MARIO_METAL_CAP) { - if (m->marioObj->header.gfx.unk38.animID == MARIO_ANIM_TIPTOE) { + if (m->marioObj->header.gfx.animInfo.animID == MARIO_ANIM_TIPTOE) { play_sound_and_spawn_particles(m, SOUND_ACTION_METAL_STEP_TIPTOE, 0); } else { play_sound_and_spawn_particles(m, SOUND_ACTION_METAL_STEP, 0); } } else if (m->quicksandDepth > 50.0f) { play_sound(SOUND_ACTION_QUICKSAND_STEP, m->marioObj->header.gfx.cameraToObject); - } else if (m->marioObj->header.gfx.unk38.animID == MARIO_ANIM_TIPTOE) { + } else if (m->marioObj->header.gfx.animInfo.animID == MARIO_ANIM_TIPTOE) { play_sound_and_spawn_particles(m, SOUND_ACTION_TERRAIN_STEP_TIPTOE, 0); } else { play_sound_and_spawn_particles(m, SOUND_ACTION_TERRAIN_STEP, 0); @@ -119,22 +119,20 @@ void check_ledge_climb_down(struct MarioState *m) { if (find_wall_collisions(&wallCols) != 0) { floorHeight = find_floor(wallCols.x, wallCols.y, wallCols.z, &floor); - if (floor != NULL) { - if (wallCols.y - floorHeight > 160.0f) { - wall = wallCols.walls[wallCols.numWalls - 1]; - wallAngle = atan2s(wall->normal.z, wall->normal.x); - wallDYaw = wallAngle - m->faceAngle[1]; + if (floor != NULL && (wallCols.y - floorHeight > 160.0f)) { + wall = wallCols.walls[wallCols.numWalls - 1]; + wallAngle = atan2s(wall->normal.z, wall->normal.x); + wallDYaw = wallAngle - m->faceAngle[1]; - if (wallDYaw > -0x4000 && wallDYaw < 0x4000) { - m->pos[0] = wallCols.x - 20.0f * wall->normal.x; - m->pos[2] = wallCols.z - 20.0f * wall->normal.z; + if (wallDYaw > -0x4000 && wallDYaw < 0x4000) { + m->pos[0] = wallCols.x - 20.0f * wall->normal.x; + m->pos[2] = wallCols.z - 20.0f * wall->normal.z; - m->faceAngle[0] = 0; - m->faceAngle[1] = wallAngle + 0x8000; + m->faceAngle[0] = 0; + m->faceAngle[1] = wallAngle + 0x8000; - set_mario_action(m, ACT_LEDGE_CLIMB_DOWN, 0); - set_mario_animation(m, MARIO_ANIM_CLIMB_DOWN_LEDGE); - } + set_mario_action(m, ACT_LEDGE_CLIMB_DOWN, 0); + set_mario_animation(m, MARIO_ANIM_CLIMB_DOWN_LEDGE); } } } @@ -160,7 +158,7 @@ s32 set_triple_jump_action(struct MarioState *m, UNUSED u32 action, UNUSED u32 a return set_mario_action(m, ACT_JUMP, 0); } - return 0; + return FALSE; } void update_sliding_angle(struct MarioState *m, f32 accel, f32 lossFactor) { @@ -709,7 +707,7 @@ void push_or_sidle_wall(struct MarioState *m, Vec3f startPos) { set_mario_anim_with_accel(m, MARIO_ANIM_SIDESTEP_LEFT, val04); } - if (m->marioObj->header.gfx.unk38.animFrame < 20) { + if (m->marioObj->header.gfx.animInfo.animFrame < 20) { play_sound(SOUND_MOVING_TERRAIN_SLIDE + m->terrainSoundAddend, m->marioObj->header.gfx.cameraToObject); m->particleFlags |= PARTICLE_DUST; } @@ -724,7 +722,7 @@ void push_or_sidle_wall(struct MarioState *m, Vec3f startPos) { void tilt_body_walking(struct MarioState *m, s16 startYaw) { struct MarioBodyState *val0C = m->marioBodyState; UNUSED struct Object *marioObj = m->marioObj; - s16 animID = m->marioObj->header.gfx.unk38.animID; + s16 animID = m->marioObj->header.gfx.animInfo.animID; s16 dYaw; s16 val02; s16 val00; @@ -1215,7 +1213,7 @@ s32 act_hold_decelerating(struct MarioState *m) { } s32 act_riding_shell_ground(struct MarioState *m) { - /*06*/ s16 startYaw = m->faceAngle[1]; + s16 startYaw = m->faceAngle[1]; if (m->input & INPUT_A_PRESSED) { return set_mario_action(m, ACT_RIDING_SHELL_JUMP, 0); @@ -1376,9 +1374,9 @@ void tilt_body_butt_slide(struct MarioState *m) { } void common_slide_action(struct MarioState *m, u32 endAction, u32 airAction, s32 animation) { - Vec3f val14; + Vec3f pos; - vec3f_copy(val14, m->pos); + vec3f_copy(pos, m->pos); play_sound(SOUND_MOVING_TERRAIN_SLIDE + m->terrainSoundAddend, m->marioObj->header.gfx.cameraToObject); reset_rumble_timers(m); @@ -1602,7 +1600,7 @@ s32 act_dive_slide(struct MarioState *m) { } s32 common_ground_knockback_action(struct MarioState *m, s32 animation, s32 arg2, s32 arg3, s32 arg4) { - s32 val04; + s32 animFrame; if (arg3) { play_mario_heavy_landing_sound_once(m, SOUND_ACTION_TERRAIN_BODY_HIT_GROUND); @@ -1627,8 +1625,8 @@ s32 common_ground_knockback_action(struct MarioState *m, s32 animation, s32 arg2 } } - val04 = set_mario_animation(m, animation); - if (val04 < arg2) { + animFrame = set_mario_animation(m, animation); + if (animFrame < arg2) { apply_landing_accel(m, 0.9f); } else if (m->forwardVel >= 0.0f) { mario_set_forward_vel(m, 0.1f); @@ -1653,23 +1651,23 @@ s32 common_ground_knockback_action(struct MarioState *m, s32 animation, s32 arg2 } } - return val04; + return animFrame; } s32 act_hard_backward_ground_kb(struct MarioState *m) { - s32 val04 = - common_ground_knockback_action(m, MARIO_ANIM_FALL_OVER_BACKWARDS, 0x2B, TRUE, m->actionArg); - if (val04 == 0x2B && m->health < 0x100) { + s32 animFrame = + common_ground_knockback_action(m, MARIO_ANIM_FALL_OVER_BACKWARDS, 43, TRUE, m->actionArg); + if (animFrame == 43 && m->health < 0x100) { set_mario_action(m, ACT_DEATH_ON_BACK, 0); } #ifndef VERSION_JP - if (val04 == 0x36 && m->prevAction == ACT_SPECIAL_DEATH_EXIT) { + if (animFrame == 54 && m->prevAction == ACT_SPECIAL_DEATH_EXIT) { play_character_sound(m, CHAR_SOUND_MAMA_MIA); } #endif - if (val04 == 0x45) { + if (animFrame == 69) { play_mario_landing_sound_once(m, SOUND_ACTION_TERRAIN_LANDING); } @@ -1677,8 +1675,9 @@ s32 act_hard_backward_ground_kb(struct MarioState *m) { } s32 act_hard_forward_ground_kb(struct MarioState *m) { - s32 val04 = common_ground_knockback_action(m, MARIO_ANIM_LAND_ON_STOMACH, 0x15, TRUE, m->actionArg); - if (val04 == 0x17 && m->health < 0x100) { + s32 animFrame = + common_ground_knockback_action(m, MARIO_ANIM_LAND_ON_STOMACH, 21, TRUE, m->actionArg); + if (animFrame == 23 && m->health < 0x100) { set_mario_action(m, ACT_DEATH_ON_STOMACH, 0); } @@ -1686,45 +1685,46 @@ s32 act_hard_forward_ground_kb(struct MarioState *m) { } s32 act_backward_ground_kb(struct MarioState *m) { - common_ground_knockback_action(m, MARIO_ANIM_BACKWARD_KB, 0x16, TRUE, m->actionArg); + common_ground_knockback_action(m, MARIO_ANIM_BACKWARD_KB, 22, TRUE, m->actionArg); return FALSE; } s32 act_forward_ground_kb(struct MarioState *m) { - common_ground_knockback_action(m, MARIO_ANIM_FORWARD_KB, 0x14, TRUE, m->actionArg); + common_ground_knockback_action(m, MARIO_ANIM_FORWARD_KB, 20, TRUE, m->actionArg); return FALSE; } s32 act_soft_backward_ground_kb(struct MarioState *m) { - common_ground_knockback_action(m, MARIO_ANIM_SOFT_BACK_KB, 0x64, FALSE, m->actionArg); + common_ground_knockback_action(m, MARIO_ANIM_SOFT_BACK_KB, 100, FALSE, m->actionArg); return FALSE; } s32 act_soft_forward_ground_kb(struct MarioState *m) { - common_ground_knockback_action(m, MARIO_ANIM_SOFT_FRONT_KB, 0x64, FALSE, m->actionArg); + common_ground_knockback_action(m, MARIO_ANIM_SOFT_FRONT_KB, 100, FALSE, m->actionArg); return FALSE; } s32 act_ground_bonk(struct MarioState *m) { - s32 val04 = common_ground_knockback_action(m, MARIO_ANIM_GROUND_BONK, 0x20, TRUE, m->actionArg); - if (val04 == 0x20) { + s32 animFrame = + common_ground_knockback_action(m, MARIO_ANIM_GROUND_BONK, 32, TRUE, m->actionArg); + if (animFrame == 32) { play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING); } return FALSE; } s32 act_death_exit_land(struct MarioState *m) { - s32 val04; + s32 animFrame; apply_landing_accel(m, 0.9f); play_mario_heavy_landing_sound_once(m, SOUND_ACTION_TERRAIN_BODY_HIT_GROUND); - val04 = set_mario_animation(m, MARIO_ANIM_FALL_OVER_BACKWARDS); + animFrame = set_mario_animation(m, MARIO_ANIM_FALL_OVER_BACKWARDS); - if (val04 == 0x36) { + if (animFrame == 54) { play_character_sound(m, CHAR_SOUND_MAMA_MIA); } - if (val04 == 0x44) { + if (animFrame == 68) { play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING); } diff --git a/src/game/mario_actions_object.c b/src/game/mario_actions_object.c index b14da9b2..4bf9e266 100644 --- a/src/game/mario_actions_object.c +++ b/src/game/mario_actions_object.c @@ -53,7 +53,7 @@ s32 mario_update_punch_sequence(struct MarioState *m) { m->actionArg = 1; } - if (m->marioObj->header.gfx.unk38.animFrame >= 2) { + if (m->marioObj->header.gfx.animInfo.animFrame >= 2) { if (mario_check_object_grab(m)) { return TRUE; } @@ -69,7 +69,7 @@ s32 mario_update_punch_sequence(struct MarioState *m) { case 2: set_mario_animation(m, MARIO_ANIM_FIRST_PUNCH_FAST); - if (m->marioObj->header.gfx.unk38.animFrame <= 0) { + if (m->marioObj->header.gfx.animInfo.animFrame <= 0) { m->flags |= MARIO_PUNCHING; } @@ -93,7 +93,7 @@ s32 mario_update_punch_sequence(struct MarioState *m) { m->actionArg = 4; } - if (m->marioObj->header.gfx.unk38.animFrame > 0) { + if (m->marioObj->header.gfx.animInfo.animFrame > 0) { m->flags |= MARIO_PUNCHING; } @@ -104,7 +104,7 @@ s32 mario_update_punch_sequence(struct MarioState *m) { case 5: set_mario_animation(m, MARIO_ANIM_SECOND_PUNCH_FAST); - if (m->marioObj->header.gfx.unk38.animFrame <= 0) { + if (m->marioObj->header.gfx.animInfo.animFrame <= 0) { m->flags |= MARIO_PUNCHING; } @@ -136,7 +136,7 @@ s32 mario_update_punch_sequence(struct MarioState *m) { case 9: play_mario_action_sound(m, CHAR_SOUND_PUNCH_HOO, 1); set_mario_animation(m, MARIO_ANIM_BREAKDANCE); - animFrame = m->marioObj->header.gfx.unk38.animFrame; + animFrame = m->marioObj->header.gfx.animInfo.animFrame; if (animFrame >= 2 && animFrame < 8) { m->flags |= MARIO_TRIPPING; diff --git a/src/game/mario_actions_stationary.c b/src/game/mario_actions_stationary.c index 1a328c06..ccb56ca8 100644 --- a/src/game/mario_actions_stationary.c +++ b/src/game/mario_actions_stationary.c @@ -2,7 +2,6 @@ #include "sm64.h" #include "area.h" -#include "audio/data.h" #include "audio/external.h" #include "behavior_data.h" #include "camera.h" @@ -61,7 +60,7 @@ s32 check_common_idle_cancels(struct MarioState *m) { return set_mario_action(m, ACT_START_CROUCHING, 0); } - return 0; + return FALSE; } s32 check_common_hold_idle_cancels(struct MarioState *m) { @@ -104,7 +103,7 @@ s32 check_common_hold_idle_cancels(struct MarioState *m) { return drop_and_set_mario_action(m, ACT_START_CROUCHING, 0); } - return 0; + return FALSE; } s32 act_idle(struct MarioState *m) { @@ -121,7 +120,7 @@ s32 act_idle(struct MarioState *m) { } if (check_common_idle_cancels(m)) { - return 1; + return TRUE; } if (m->actionState == 3) { @@ -174,22 +173,22 @@ s32 act_idle(struct MarioState *m) { stationary_ground_step(m); - return 0; + return FALSE; } void play_anim_sound(struct MarioState *m, u32 actionState, s32 animFrame, u32 sound) { - if (m->actionState == actionState && m->marioObj->header.gfx.unk38.animFrame == animFrame) { + if (m->actionState == actionState && m->marioObj->header.gfx.animInfo.animFrame == animFrame) { play_sound(sound, m->marioObj->header.gfx.cameraToObject); } } s32 act_start_sleeping(struct MarioState *m) { #ifndef VERSION_JP - s32 sp24; + s32 animFrame; #endif if (check_common_idle_cancels(m)) { - return 1; + return TRUE; } if (m->quicksandDepth > 30.0f) { @@ -203,35 +202,31 @@ s32 act_start_sleeping(struct MarioState *m) { switch (m->actionState) { case 0: #ifndef VERSION_JP - sp24 = set_mario_animation(m, MARIO_ANIM_START_SLEEP_IDLE); -#else - set_mario_animation(m, MARIO_ANIM_START_SLEEP_IDLE); + animFrame = #endif + set_mario_animation(m, MARIO_ANIM_START_SLEEP_IDLE); break; case 1: #ifndef VERSION_JP - sp24 = set_mario_animation(m, MARIO_ANIM_START_SLEEP_SCRATCH); -#else - set_mario_animation(m, MARIO_ANIM_START_SLEEP_SCRATCH); + animFrame = #endif + set_mario_animation(m, MARIO_ANIM_START_SLEEP_SCRATCH); break; case 2: #ifndef VERSION_JP - sp24 = set_mario_animation(m, MARIO_ANIM_START_SLEEP_YAWN); -#else - set_mario_animation(m, MARIO_ANIM_START_SLEEP_YAWN); + animFrame = #endif + set_mario_animation(m, MARIO_ANIM_START_SLEEP_YAWN); m->marioBodyState->eyeState = MARIO_EYES_HALF_CLOSED; break; case 3: #ifndef VERSION_JP - sp24 = set_mario_animation(m, MARIO_ANIM_START_SLEEP_SITTING); -#else - set_mario_animation(m, MARIO_ANIM_START_SLEEP_SITTING); + animFrame = #endif + set_mario_animation(m, MARIO_ANIM_START_SLEEP_SITTING); m->marioBodyState->eyeState = MARIO_EYES_HALF_CLOSED; break; } @@ -245,16 +240,12 @@ s32 act_start_sleeping(struct MarioState *m) { } #ifndef VERSION_JP - if (m->actionState == 2) { - if (sp24 == -1) { - play_character_sound(m, CHAR_SOUND_YAWNING); - } + if (m->actionState == 2 && animFrame == -1) { + play_character_sound(m, CHAR_SOUND_YAWNING); } - if (m->actionState == 1) { - if (sp24 == -1) { - play_character_sound(m, CHAR_SOUND_IMA_TIRED); - } + if (m->actionState == 2 && animFrame == -1) { + play_character_sound(m, CHAR_SOUND_IMA_TIRED); } #else if (m->actionState == 2) { @@ -263,13 +254,15 @@ s32 act_start_sleeping(struct MarioState *m) { #endif stationary_ground_step(m); - return 0; + return FALSE; } s32 act_sleeping(struct MarioState *m) { - s32 sp24; + s32 animFrame; if (m->playerIndex == 0) { - if (m->input & INPUT_UNKNOWN_A41F /* ? */) { + if (m->input + & (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED | INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE + | INPUT_FIRST_PERSON | INPUT_UNKNOWN_10 | INPUT_B_PRESSED | INPUT_Z_PRESSED)) { return set_mario_action(m, ACT_WAKING_UP, m->actionState); } @@ -285,19 +278,19 @@ s32 act_sleeping(struct MarioState *m) { m->marioBodyState->eyeState = MARIO_EYES_CLOSED; stationary_ground_step(m); switch (m->actionState) { - case 0: { - sp24 = set_mario_animation(m, MARIO_ANIM_SLEEP_IDLE); + case 0: + animFrame = set_mario_animation(m, MARIO_ANIM_SLEEP_IDLE); - if (m->playerIndex == 0 && sp24 == -1 && !m->actionTimer) { + if (m->playerIndex == 0 && animFrame == -1 && !m->actionTimer) { lower_background_noise(2); } - if (sp24 == 2) { + if (animFrame == 2) { play_character_sound(m, CHAR_SOUND_SNORING1); m->isSnoring = TRUE; } - if (sp24 == 20) { + if (animFrame == 20) { play_character_sound(m, CHAR_SOUND_SNORING2); m->isSnoring = TRUE; } @@ -309,8 +302,8 @@ s32 act_sleeping(struct MarioState *m) { } } break; - } - case 1: { + + case 1: if (set_mario_animation(m, MARIO_ANIM_SLEEP_START_LYING) == 18) { play_mario_heavy_landing_sound(m, SOUND_ACTION_TERRAIN_BODY_HIT_GROUND); } @@ -319,27 +312,26 @@ s32 act_sleeping(struct MarioState *m) { m->actionState++; } break; - } - case 2: { - sp24 = set_mario_animation(m, MARIO_ANIM_SLEEP_LYING); + + case 2: + animFrame = set_mario_animation(m, MARIO_ANIM_SLEEP_LYING); #ifndef VERSION_JP play_character_sound_if_no_flag(m, CHAR_SOUND_SNORING3, MARIO_MARIO_SOUND_PLAYED); m->isSnoring = TRUE; #else - if (sp24 == 2) { + if (animFrame == 2) { play_character_sound(m, CHAR_SOUND_SNORING2); m->isSnoring = TRUE; } - if (sp24 == 25) { + if (animFrame == 25) { play_character_sound(m, CHAR_SOUND_SNORING1); m->isSnoring = TRUE; } #endif break; - } } - return 0; + return FALSE; } s32 act_waking_up(struct MarioState *m) { @@ -376,11 +368,11 @@ s32 act_waking_up(struct MarioState *m) { set_mario_animation(m, !m->actionArg ? MARIO_ANIM_WAKE_FROM_SLEEP : MARIO_ANIM_WAKE_FROM_LYING); - return 0; + return FALSE; } s32 act_shivering(struct MarioState *m) { - s32 sp24; + s32 animFrame; if (m->input & INPUT_UNKNOWN_10) { return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0); @@ -394,66 +386,67 @@ s32 act_shivering(struct MarioState *m) { return set_mario_action(m, ACT_BEGIN_SLIDING, 0); } - if (m->input & INPUT_UNKNOWN_A41F) { + if (m->input + & (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED | INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE + | INPUT_FIRST_PERSON | INPUT_UNKNOWN_10 | INPUT_B_PRESSED | INPUT_Z_PRESSED)) { m->actionState = 2; } stationary_ground_step(m); switch (m->actionState) { - case 0: { - sp24 = set_mario_animation(m, MARIO_ANIM_SHIVERING_WARMING_HAND); - if (sp24 == 0x31) { + case 0: + animFrame = set_mario_animation(m, MARIO_ANIM_SHIVERING_WARMING_HAND); + if (animFrame == 49) { m->particleFlags |= PARTICLE_BREATH; play_character_sound(m, CHAR_SOUND_PANTING_COLD); } - if (sp24 == 7 || sp24 == 0x51) { + if (animFrame == 7 || animFrame == 81) { play_sound(SOUND_ACTION_CLAP_HANDS_COLD, m->marioObj->header.gfx.cameraToObject); } if (is_anim_past_end(m)) { m->actionState = 1; } break; - } - case 1: { - sp24 = set_mario_animation(m, MARIO_ANIM_SHIVERING); - if (sp24 == 9 || sp24 == 0x19 || sp24 == 0x2C) { + + case 1: + animFrame = set_mario_animation(m, MARIO_ANIM_SHIVERING); + if (animFrame == 9 || animFrame == 25 || animFrame == 44) { play_sound(SOUND_ACTION_CLAP_HANDS_COLD, m->marioObj->header.gfx.cameraToObject); } break; - } - case 2: { + + case 2: set_mario_animation(m, MARIO_ANIM_SHIVERING_RETURN_TO_IDLE); if (is_anim_past_end(m)) { set_mario_action(m, ACT_IDLE, 0); } break; - } } - return 0; + return FALSE; } s32 act_coughing(struct MarioState *m) { - s32 sp1C; + s32 animFrame; if (check_common_idle_cancels(m)) { - return 1; + return TRUE; } stationary_ground_step(m); - sp1C = set_mario_animation(m, MARIO_ANIM_COUGHING); - if (sp1C == 0x19 || sp1C == 0x23) { + animFrame = set_mario_animation(m, MARIO_ANIM_COUGHING); + if (animFrame == 25 || animFrame == 35) { play_character_sound(m, CHAR_SOUND_COUGHING3); } - if (sp1C == 0x32 || sp1C == 0x3A) { + if (animFrame == 50 || animFrame == 58) { play_character_sound(m, CHAR_SOUND_COUGHING2); } - if (sp1C == 0x47 || sp1C == 0x50) { + if (animFrame == 71 || animFrame == 80) { play_character_sound(m, CHAR_SOUND_COUGHING1); } - return 0; + return FALSE; } s32 act_hold_idle(struct MarioState *m) { @@ -470,12 +463,12 @@ s32 act_hold_idle(struct MarioState *m) { } if (check_common_hold_idle_cancels(m)) { - return 1; + return TRUE; } stationary_ground_step(m); set_mario_animation(m, MARIO_ANIM_IDLE_WITH_LIGHT_OBJ); - return 0; + return FALSE; } s32 act_hold_heavy_idle(struct MarioState *m) { @@ -501,7 +494,7 @@ s32 act_hold_heavy_idle(struct MarioState *m) { stationary_ground_step(m); set_mario_animation(m, MARIO_ANIM_IDLE_HEAVY_OBJ); - return 0; + return FALSE; } s32 act_standing_against_wall(struct MarioState *m) { @@ -523,7 +516,7 @@ s32 act_standing_against_wall(struct MarioState *m) { set_mario_animation(m, MARIO_ANIM_STAND_AGAINST_WALL); stationary_ground_step(m); - return 0; + return FALSE; } s32 act_in_quicksand(struct MarioState *m) { @@ -531,8 +524,8 @@ s32 act_in_quicksand(struct MarioState *m) { return set_mario_action(m, ACT_IDLE, 0); } - if (check_common_idle_cancels(m) != 0) { - return 1; + if (check_common_idle_cancels(m)) { + return TRUE; } if (m->quicksandDepth > 70.0f) { @@ -542,7 +535,7 @@ s32 act_in_quicksand(struct MarioState *m) { } stationary_ground_step(m); - return 0; + return FALSE; } s32 act_crouching(struct MarioState *m) { @@ -580,7 +573,7 @@ s32 act_crouching(struct MarioState *m) { stationary_ground_step(m); set_mario_animation(m, MARIO_ANIM_CROUCHING); - return 0; + return FALSE; } s32 act_panting(struct MarioState *m) { @@ -593,7 +586,7 @@ s32 act_panting(struct MarioState *m) { } if (check_common_idle_cancels(m)) { - return 1; + return TRUE; } if (set_mario_animation(m, MARIO_ANIM_WALK_PANTING) == 1) { @@ -602,7 +595,7 @@ s32 act_panting(struct MarioState *m) { stationary_ground_step(m); m->marioBodyState->eyeState = MARIO_EYES_HALF_CLOSED; - return 0; + return FALSE; } s32 act_hold_panting_unused(struct MarioState *m) { @@ -618,20 +611,20 @@ s32 act_hold_panting_unused(struct MarioState *m) { return set_mario_action(m, ACT_HOLD_IDLE, 0); } - if (check_common_hold_idle_cancels(m) != 0) { - return 1; + if (check_common_hold_idle_cancels(m)) { + return TRUE; } set_mario_animation(m, MARIO_ANIM_WALK_PANTING); stationary_ground_step(m); m->marioBodyState->eyeState = MARIO_EYES_HALF_CLOSED; - return 0; + return FALSE; } void stopping_step(struct MarioState *m, s32 animID, u32 action) { stationary_ground_step(m); set_mario_animation(m, animID); - if (is_anim_at_end(m) != 0) { + if (is_anim_at_end(m)) { set_mario_action(m, action, 0); } } @@ -655,7 +648,7 @@ s32 act_braking_stop(struct MarioState *m) { } stopping_step(m, MARIO_ANIM_STOP_SKID, ACT_IDLE); - return 0; + return FALSE; } s32 act_butt_slide_stop(struct MarioState *m) { @@ -668,11 +661,11 @@ s32 act_butt_slide_stop(struct MarioState *m) { } stopping_step(m, MARIO_ANIM_STOP_SLIDE, ACT_IDLE); - if (m->marioObj->header.gfx.unk38.animFrame == 6) { + if (m->marioObj->header.gfx.animInfo.animFrame == 6) { play_mario_landing_sound(m, SOUND_ACTION_TERRAIN_LANDING); } - return 0; + return FALSE; } s32 act_hold_butt_slide_stop(struct MarioState *m) { @@ -693,7 +686,7 @@ s32 act_hold_butt_slide_stop(struct MarioState *m) { } stopping_step(m, MARIO_ANIM_STAND_UP_FROM_SLIDING_WITH_LIGHT_OBJ, ACT_HOLD_IDLE); - return 0; + return FALSE; } s32 act_slide_kick_slide_stop(struct MarioState *m) { @@ -706,7 +699,7 @@ s32 act_slide_kick_slide_stop(struct MarioState *m) { } stopping_step(m, MARIO_ANIM_CROUCH_FROM_SLIDE_KICK, ACT_CROUCHING); - return 0; + return FALSE; } s32 act_start_crouching(struct MarioState *m) { @@ -731,7 +724,7 @@ s32 act_start_crouching(struct MarioState *m) { if (is_anim_past_end(m)) { set_mario_action(m, ACT_CROUCHING, 0); } - return 0; + return FALSE; } s32 act_stop_crouching(struct MarioState *m) { @@ -756,7 +749,7 @@ s32 act_stop_crouching(struct MarioState *m) { if (is_anim_past_end(m)) { set_mario_action(m, ACT_IDLE, 0); } - return 0; + return FALSE; } s32 act_start_crawling(struct MarioState *m) { @@ -782,7 +775,7 @@ s32 act_start_crawling(struct MarioState *m) { set_mario_action(m, ACT_CRAWLING, 0); } - return 0; + return FALSE; } s32 act_stop_crawling(struct MarioState *m) { @@ -803,14 +796,14 @@ s32 act_stop_crawling(struct MarioState *m) { if (is_anim_past_end(m)) { set_mario_action(m, ACT_CROUCHING, 0); } - return 0; + return FALSE; } s32 act_shockwave_bounce(struct MarioState *m) { s16 sp1E; f32 sp18; - if (m->marioObj->oInteractStatus & 0x10) { + if (m->marioObj->oInteractStatus & INT_STATUS_HIT_BY_SHOCKWAVE) { queue_rumble_data_mario(m, 70, 40); return hurt_and_set_mario_action(m, ACT_SHOCKED, 0, 4); } @@ -822,11 +815,11 @@ s32 act_shockwave_bounce(struct MarioState *m) { } } - if (++m->actionTimer == 0x30) { + if (++m->actionTimer == 48) { return set_mario_action(m, ACT_IDLE, 0); } - sp1E = (m->actionTimer % 0x10) << 0xC; + sp1E = (m->actionTimer % 16) << 12; sp18 = (f32)(((f32)(6 - m->actionTimer / 8) * 8.0f) + 4.0f); mario_set_forward_vel(m, 0); vec3f_set(m->vel, 0.0f, 0.0f, 0.0f); @@ -839,7 +832,7 @@ s32 act_shockwave_bounce(struct MarioState *m) { vec3f_copy(m->marioObj->header.gfx.pos, m->pos); vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1], 0); set_mario_animation(m, MARIO_ANIM_A_POSE); - return 0; + return FALSE; } s32 landing_step(struct MarioState *m, s32 arg1, u32 action) { @@ -848,7 +841,7 @@ s32 landing_step(struct MarioState *m, s32 arg1, u32 action) { if (is_anim_at_end(m)) { return set_mario_action(m, action, 0); } - return 0; + return FALSE; } s32 check_common_landing_cancels(struct MarioState *m, u32 action) { @@ -876,90 +869,89 @@ s32 check_common_landing_cancels(struct MarioState *m, u32 action) { return set_mario_action(m, ACT_PUNCHING, 0); } - return 0; + return FALSE; } s32 act_jump_land_stop(struct MarioState *m) { if (check_common_landing_cancels(m, 0)) { - return 1; + return TRUE; } landing_step(m, MARIO_ANIM_LAND_FROM_SINGLE_JUMP, ACT_IDLE); - return 0; + return FALSE; } s32 act_double_jump_land_stop(struct MarioState *m) { if (check_common_landing_cancels(m, 0)) { - return 1; + return TRUE; } landing_step(m, MARIO_ANIM_LAND_FROM_DOUBLE_JUMP, ACT_IDLE); - return 0; + return FALSE; } s32 act_side_flip_land_stop(struct MarioState *m) { if (check_common_landing_cancels(m, 0)) { - return 1; + return TRUE; } landing_step(m, MARIO_ANIM_SLIDEFLIP_LAND, ACT_IDLE); m->marioObj->header.gfx.angle[1] += 0x8000; - return 0; + return FALSE; } s32 act_freefall_land_stop(struct MarioState *m) { if (check_common_landing_cancels(m, 0)) { - return 1; + return TRUE; } landing_step(m, MARIO_ANIM_GENERAL_LAND, ACT_IDLE); - return 0; + return FALSE; } s32 act_triple_jump_land_stop(struct MarioState *m) { if (check_common_landing_cancels(m, ACT_JUMP)) { - return 1; + return TRUE; } landing_step(m, MARIO_ANIM_TRIPLE_JUMP_LAND, ACT_IDLE); - return 0; + return FALSE; } s32 act_backflip_land_stop(struct MarioState *m) { - if (!(m->input & INPUT_Z_DOWN) || m->marioObj->header.gfx.unk38.animFrame >= 6) { - m->input &= -3; + if (!(m->input & INPUT_Z_DOWN) || m->marioObj->header.gfx.animInfo.animFrame >= 6) { + m->input &= ~INPUT_A_PRESSED; } if (check_common_landing_cancels(m, ACT_BACKFLIP)) { - return 1; + return TRUE; } landing_step(m, MARIO_ANIM_TRIPLE_JUMP_LAND, ACT_IDLE); - return 0; + return FALSE; } s32 act_lava_boost_land(struct MarioState *m) { - m->input &= -0x2011; + m->input &= ~(INPUT_FIRST_PERSON | INPUT_B_PRESSED); if (check_common_landing_cancels(m, 0)) { - return 1; + return TRUE; } landing_step(m, MARIO_ANIM_STAND_UP_FROM_LAVA_BOOST, ACT_IDLE); - return 0; + return FALSE; } s32 act_long_jump_land_stop(struct MarioState *m) { - m->input &= -0x2001; + m->input &= ~INPUT_B_PRESSED; if (check_common_landing_cancels(m, ACT_JUMP)) { - return 1; + return TRUE; } - landing_step(m, - !m->marioObj->oMarioLongJumpIsSlow ? MARIO_ANIM_CROUCH_FROM_FAST_LONGJUMP - : MARIO_ANIM_CROUCH_FROM_SLOW_LONGJUMP, - ACT_CROUCHING); - return 0; + landing_step(m, !m->marioObj->oMarioLongJumpIsSlow ? MARIO_ANIM_CROUCH_FROM_FAST_LONGJUMP + : MARIO_ANIM_CROUCH_FROM_SLOW_LONGJUMP, + ACT_CROUCHING); + return FALSE; } s32 act_hold_jump_land_stop(struct MarioState *m) { @@ -980,7 +972,7 @@ s32 act_hold_jump_land_stop(struct MarioState *m) { } landing_step(m, MARIO_ANIM_JUMP_LAND_WITH_LIGHT_OBJ, ACT_HOLD_IDLE); - return 0; + return FALSE; } s32 act_hold_freefall_land_stop(struct MarioState *m) { @@ -1000,7 +992,7 @@ s32 act_hold_freefall_land_stop(struct MarioState *m) { return set_mario_action(m, ACT_THROWING, 0); } landing_step(m, MARIO_ANIM_FALL_LAND_WITH_LIGHT_OBJ, ACT_HOLD_IDLE); - return 0; + return FALSE; } s32 act_air_throw_land(struct MarioState *m) { @@ -1017,7 +1009,7 @@ s32 act_air_throw_land(struct MarioState *m) { } landing_step(m, MARIO_ANIM_THROW_LIGHT_OBJECT, ACT_IDLE); - return 0; + return FALSE; } s32 act_twirl_land(struct MarioState *m) { @@ -1042,14 +1034,12 @@ s32 act_twirl_land(struct MarioState *m) { } m->marioObj->header.gfx.angle[1] += m->twirlYaw; - if (is_anim_at_end(m)) { - if (m->angleVel[1] == 0) { - m->faceAngle[1] += m->twirlYaw; - set_mario_action(m, ACT_IDLE, 0); - } + if (is_anim_at_end(m) && m->angleVel[1] == 0) { + m->faceAngle[1] += m->twirlYaw; + set_mario_action(m, ACT_IDLE, 0); } - return 0; + return FALSE; } s32 act_ground_pound_land(struct MarioState *m) { @@ -1067,47 +1057,39 @@ s32 act_ground_pound_land(struct MarioState *m) { } landing_step(m, MARIO_ANIM_GROUND_POUND_LANDING, ACT_BUTT_SLIDE_STOP); - return 0; + return FALSE; } s32 act_first_person(struct MarioState *m) { - s32 sp1C; - s16 sp1A; - s16 sp18; + s32 sp1C = (m->input & (INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE | INPUT_UNKNOWN_10)) != 0; - sp1C = 0 != (m->input & (INPUT_UNKNOWN_10 | 0xC)); if (m->actionState == 0) { if (m->playerIndex == 0) { lower_background_noise(2); set_camera_mode(m->area->camera, CAMERA_MODE_C_UP, 0x10); } m->actionState = 1; - } else { - if (!(m->input & INPUT_FIRST_PERSON) || sp1C) { - if (m->playerIndex == 0) { - raise_background_noise(2); - // Go back to the last camera mode - set_camera_mode(m->area->camera, -1, 1); - } - return set_mario_action(m, ACT_IDLE, 0); + } else if (!(m->input & INPUT_FIRST_PERSON) || sp1C) { + if (m->playerIndex == 0) { + raise_background_noise(2); + // Go back to the last camera mode + set_camera_mode(m->area->camera, -1, 1); } + return set_mario_action(m, ACT_IDLE, 0); } - if (m->floor->type == SURFACE_LOOK_UP_WARP) { - if (save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 0x18) >= 10) { - sp1A = m->statusForCamera->headRotation[0]; - sp18 = ((m->statusForCamera->headRotation[1] * 4) / 3) + m->faceAngle[1]; - if (sp1A == -0x1800) { - if (sp18 < -0x6FFF || sp18 >= 0x7000) { - level_trigger_warp(m, 1); - } - } + if (m->floor->type == SURFACE_LOOK_UP_WARP + && save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1) >= 10) { + s16 sp1A = m->statusForCamera->headRotation[0]; + s16 sp18 = ((m->statusForCamera->headRotation[1] * 4) / 3) + m->faceAngle[1]; + if (sp1A == -0x1800 && (sp18 < -0x6FFF || sp18 >= 0x7000)) { + level_trigger_warp(m, WARP_OP_UNKNOWN_01); } } stationary_ground_step(m); set_mario_animation(m, MARIO_ANIM_FIRST_PERSON); - return 0; + return FALSE; } s32 check_common_stationary_cancels(struct MarioState *m) { @@ -1128,75 +1110,73 @@ s32 check_common_stationary_cancels(struct MarioState *m) { return drop_and_set_mario_action(m, ACT_SQUISHED, 0); } - if (m->action != 0x0002020E) { + if (m->action != ACT_UNKNOWN_0002020E) { if (m->health < 0x100) { update_mario_sound_and_camera(m); return drop_and_set_mario_action(m, ACT_STANDING_DEATH, 0); } } - return 0; + return FALSE; } s32 mario_execute_stationary_action(struct MarioState *m) { - s32 sp24; + s32 cancel; if (check_common_stationary_cancels(m)) { - return 1; + return TRUE; } if (mario_update_quicksand(m, 0.5f)) { - return 1; + return TRUE; } - if (!smlua_call_action_hook(m, &sp24)) { + if (!smlua_call_action_hook(m, &cancel)) { /* clang-format off */ switch (m->action) { - case ACT_IDLE: sp24 = act_idle(m); break; - case ACT_START_SLEEPING: sp24 = act_start_sleeping(m); break; - case ACT_SLEEPING: sp24 = act_sleeping(m); break; - case ACT_WAKING_UP: sp24 = act_waking_up(m); break; - case ACT_PANTING: sp24 = act_panting(m); break; - case ACT_HOLD_PANTING_UNUSED: sp24 = act_hold_panting_unused(m); break; - case ACT_HOLD_IDLE: sp24 = act_hold_idle(m); break; - case ACT_HOLD_HEAVY_IDLE: sp24 = act_hold_heavy_idle(m); break; - case ACT_IN_QUICKSAND: sp24 = act_in_quicksand(m); break; - case ACT_STANDING_AGAINST_WALL: sp24 = act_standing_against_wall(m); break; - case ACT_COUGHING: sp24 = act_coughing(m); break; - case ACT_SHIVERING: sp24 = act_shivering(m); break; - case ACT_CROUCHING: sp24 = act_crouching(m); break; - case ACT_START_CROUCHING: sp24 = act_start_crouching(m); break; - case ACT_STOP_CROUCHING: sp24 = act_stop_crouching(m); break; - case ACT_START_CRAWLING: sp24 = act_start_crawling(m); break; - case ACT_STOP_CRAWLING: sp24 = act_stop_crawling(m); break; - case ACT_SLIDE_KICK_SLIDE_STOP: sp24 = act_slide_kick_slide_stop(m); break; - case ACT_SHOCKWAVE_BOUNCE: sp24 = act_shockwave_bounce(m); break; - case ACT_FIRST_PERSON: sp24 = act_first_person(m); break; - case ACT_JUMP_LAND_STOP: sp24 = act_jump_land_stop(m); break; - case ACT_DOUBLE_JUMP_LAND_STOP: sp24 = act_double_jump_land_stop(m); break; - case ACT_FREEFALL_LAND_STOP: sp24 = act_freefall_land_stop(m); break; - case ACT_SIDE_FLIP_LAND_STOP: sp24 = act_side_flip_land_stop(m); break; - case ACT_HOLD_JUMP_LAND_STOP: sp24 = act_hold_jump_land_stop(m); break; - case ACT_HOLD_FREEFALL_LAND_STOP: sp24 = act_hold_freefall_land_stop(m); break; - case ACT_AIR_THROW_LAND: sp24 = act_air_throw_land(m); break; - case ACT_LAVA_BOOST_LAND: sp24 = act_lava_boost_land(m); break; - case ACT_TWIRL_LAND: sp24 = act_twirl_land(m); break; - case ACT_TRIPLE_JUMP_LAND_STOP: sp24 = act_triple_jump_land_stop(m); break; - case ACT_BACKFLIP_LAND_STOP: sp24 = act_backflip_land_stop(m); break; - case ACT_LONG_JUMP_LAND_STOP: sp24 = act_long_jump_land_stop(m); break; - case ACT_GROUND_POUND_LAND: sp24 = act_ground_pound_land(m); break; - case ACT_BRAKING_STOP: sp24 = act_braking_stop(m); break; - case ACT_BUTT_SLIDE_STOP: sp24 = act_butt_slide_stop(m); break; - case ACT_HOLD_BUTT_SLIDE_STOP: sp24 = act_hold_butt_slide_stop(m); break; + case ACT_IDLE: cancel = act_idle(m); break; + case ACT_START_SLEEPING: cancel = act_start_sleeping(m); break; + case ACT_SLEEPING: cancel = act_sleeping(m); break; + case ACT_WAKING_UP: cancel = act_waking_up(m); break; + case ACT_PANTING: cancel = act_panting(m); break; + case ACT_HOLD_PANTING_UNUSED: cancel = act_hold_panting_unused(m); break; + case ACT_HOLD_IDLE: cancel = act_hold_idle(m); break; + case ACT_HOLD_HEAVY_IDLE: cancel = act_hold_heavy_idle(m); break; + case ACT_IN_QUICKSAND: cancel = act_in_quicksand(m); break; + case ACT_STANDING_AGAINST_WALL: cancel = act_standing_against_wall(m); break; + case ACT_COUGHING: cancel = act_coughing(m); break; + case ACT_SHIVERING: cancel = act_shivering(m); break; + case ACT_CROUCHING: cancel = act_crouching(m); break; + case ACT_START_CROUCHING: cancel = act_start_crouching(m); break; + case ACT_STOP_CROUCHING: cancel = act_stop_crouching(m); break; + case ACT_START_CRAWLING: cancel = act_start_crawling(m); break; + case ACT_STOP_CRAWLING: cancel = act_stop_crawling(m); break; + case ACT_SLIDE_KICK_SLIDE_STOP: cancel = act_slide_kick_slide_stop(m); break; + case ACT_SHOCKWAVE_BOUNCE: cancel = act_shockwave_bounce(m); break; + case ACT_FIRST_PERSON: cancel = act_first_person(m); break; + case ACT_JUMP_LAND_STOP: cancel = act_jump_land_stop(m); break; + case ACT_DOUBLE_JUMP_LAND_STOP: cancel = act_double_jump_land_stop(m); break; + case ACT_FREEFALL_LAND_STOP: cancel = act_freefall_land_stop(m); break; + case ACT_SIDE_FLIP_LAND_STOP: cancel = act_side_flip_land_stop(m); break; + case ACT_HOLD_JUMP_LAND_STOP: cancel = act_hold_jump_land_stop(m); break; + case ACT_HOLD_FREEFALL_LAND_STOP: cancel = act_hold_freefall_land_stop(m); break; + case ACT_AIR_THROW_LAND: cancel = act_air_throw_land(m); break; + case ACT_LAVA_BOOST_LAND: cancel = act_lava_boost_land(m); break; + case ACT_TWIRL_LAND: cancel = act_twirl_land(m); break; + case ACT_TRIPLE_JUMP_LAND_STOP: cancel = act_triple_jump_land_stop(m); break; + case ACT_BACKFLIP_LAND_STOP: cancel = act_backflip_land_stop(m); break; + case ACT_LONG_JUMP_LAND_STOP: cancel = act_long_jump_land_stop(m); break; + case ACT_GROUND_POUND_LAND: cancel = act_ground_pound_land(m); break; + case ACT_BRAKING_STOP: cancel = act_braking_stop(m); break; + case ACT_BUTT_SLIDE_STOP: cancel = act_butt_slide_stop(m); break; + case ACT_HOLD_BUTT_SLIDE_STOP: cancel = act_hold_butt_slide_stop(m); break; default: LOG_ERROR("Attempted to execute unimplemented action '%04X'", m->action); return true; } /* clang-format on */ } - if (!sp24) { - if (m->input & INPUT_IN_WATER) { - m->particleFlags |= PARTICLE_IDLE_WATER_WAVE; - } + if (!cancel && (m->input & INPUT_IN_WATER)) { + m->particleFlags |= PARTICLE_IDLE_WATER_WAVE; } - return sp24; + return cancel; } diff --git a/src/game/mario_actions_stationary.h b/src/game/mario_actions_stationary.h index a4633c7c..c4b4c069 100644 --- a/src/game/mario_actions_stationary.h +++ b/src/game/mario_actions_stationary.h @@ -5,8 +5,6 @@ #include "types.h" -#define INPUT_UNKNOWN_A41F 0xA41F - s32 check_common_idle_cancels(struct MarioState *m); s32 check_common_hold_idle_cancels(struct MarioState *m); s32 act_idle(struct MarioState *m); diff --git a/src/game/mario_actions_submerged.c b/src/game/mario_actions_submerged.c index 6857f759..d806c1b1 100644 --- a/src/game/mario_actions_submerged.c +++ b/src/game/mario_actions_submerged.c @@ -486,9 +486,9 @@ static void common_swimming_step(struct MarioState *m, s16 swimStrength) { } static void play_swimming_noise(struct MarioState *m) { - s16 animFrame = m->marioObj->header.gfx.unk38.animFrame; + s16 animFrame = m->marioObj->header.gfx.animInfo.animFrame; - // (this need to be on one line to match on PAL) + // This must be one line to match on -O2 if (animFrame == 0 || animFrame == 12) play_sound(SOUND_ACTION_UNKNOWN434, m->marioObj->header.gfx.cameraToObject); } @@ -927,7 +927,7 @@ static s32 act_drowning(struct MarioState *m) { case 1: set_mario_animation(m, MARIO_ANIM_DROWNING_PART2); m->marioBodyState->eyeState = MARIO_EYES_DEAD; - if (m->marioObj->header.gfx.unk38.animFrame == 30) { + if (m->marioObj->header.gfx.animInfo.animFrame == 30) { if (gServerSettings.bubbleDeath) { mario_set_bubbled(m); } else { @@ -1272,7 +1272,7 @@ static s32 act_metal_water_walking(struct MarioState *m) { break; case GROUND_STEP_HIT_WALL: - m->forwardVel = 0; + m->forwardVel = 0.0f; break; } diff --git a/src/game/mario_misc.c b/src/game/mario_misc.c index 9af19759..ba71e4dc 100644 --- a/src/game/mario_misc.c +++ b/src/game/mario_misc.c @@ -159,7 +159,7 @@ Gfx *geo_draw_mario_head_goddard(s32 callContext, struct GraphNode *node, Mat4 * UNUSED Mat4 *transform = c; if (callContext == GEO_CONTEXT_RENDER) { - if (gPlayer1Controller->controllerData != NULL && gWarpTransition.isActive == 0) { + if (gPlayer1Controller->controllerData != NULL && !gWarpTransition.isActive) { gd_copy_p1_contpad(gPlayer1Controller->controllerData); } gfx = (Gfx *) PHYSICAL_TO_VIRTUAL(gdm_gettestdl(asGenerated->parameter)); @@ -172,9 +172,9 @@ Gfx *geo_draw_mario_head_goddard(s32 callContext, struct GraphNode *node, Mat4 * static void toad_message_faded(void) { if (gCurrentObject->oDistanceToMario > 700.0f) { - gCurrentObject->oToadMessageRecentlyTalked = 0; + gCurrentObject->oToadMessageRecentlyTalked = FALSE; } - if (gCurrentObject->oToadMessageRecentlyTalked == 0 && gCurrentObject->oDistanceToMario < 600.0f) { + if (!gCurrentObject->oToadMessageRecentlyTalked && gCurrentObject->oDistanceToMario < 600.0f) { gCurrentObject->oToadMessageState = TOAD_MESSAGE_OPACIFYING; } } @@ -182,14 +182,12 @@ static void toad_message_faded(void) { static void toad_message_opaque(void) { if (gCurrentObject->oDistanceToMario > 700.0f) { gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADING; - } else { - if (gCurrentObject->oToadMessageRecentlyTalked == 0) { - gCurrentObject->oInteractionSubtype = INT_SUBTYPE_NPC; - if (gCurrentObject->oInteractStatus & INT_STATUS_INTERACTED) { - gCurrentObject->oInteractStatus = 0; - gCurrentObject->oToadMessageState = TOAD_MESSAGE_TALKING; - play_toads_jingle(); - } + } else if (!gCurrentObject->oToadMessageRecentlyTalked) { + gCurrentObject->oInteractionSubtype = INT_SUBTYPE_NPC; + if (gCurrentObject->oInteractStatus & INT_STATUS_INTERACTED) { + gCurrentObject->oInteractStatus = 0; + gCurrentObject->oToadMessageState = TOAD_MESSAGE_TALKING; + play_toads_jingle(); } } } @@ -197,7 +195,7 @@ static void toad_message_opaque(void) { static void toad_message_talking(void) { if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 3, 1, CUTSCENE_DIALOG, gCurrentObject->oToadMessageDialogId, NULL) != 0) { - gCurrentObject->oToadMessageRecentlyTalked = 1; + gCurrentObject->oToadMessageRecentlyTalked = TRUE; gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADING; switch (gCurrentObject->oToadMessageDialogId) { case TOAD_STAR_1_DIALOG: @@ -253,33 +251,33 @@ void bhv_toad_message_loop(void) { void bhv_toad_message_init(void) { s32 saveFlags = save_file_get_flags(); - s32 starCount = save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 24); + s32 starCount = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1); s32 dialogId = (gCurrentObject->oBehParams >> 24) & 0xFF; s32 enoughStars = TRUE; switch (dialogId) { case TOAD_STAR_1_DIALOG: enoughStars = (starCount >= TOAD_STAR_1_REQUIREMENT); - if (saveFlags & (1 << 24)) { + if (saveFlags & SAVE_FLAG_COLLECTED_TOAD_STAR_1) { dialogId = TOAD_STAR_1_DIALOG_AFTER; } break; case TOAD_STAR_2_DIALOG: enoughStars = (starCount >= TOAD_STAR_2_REQUIREMENT); - if (saveFlags & (1 << 25)) { + if (saveFlags & SAVE_FLAG_COLLECTED_TOAD_STAR_2) { dialogId = TOAD_STAR_2_DIALOG_AFTER; } break; case TOAD_STAR_3_DIALOG: enoughStars = (starCount >= TOAD_STAR_3_REQUIREMENT); - if (saveFlags & (1 << 26)) { + if (saveFlags & SAVE_FLAG_COLLECTED_TOAD_STAR_3) { dialogId = TOAD_STAR_3_DIALOG_AFTER; } break; } if (enoughStars) { gCurrentObject->oToadMessageDialogId = dialogId; - gCurrentObject->oToadMessageRecentlyTalked = 0; + gCurrentObject->oToadMessageRecentlyTalked = FALSE; gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADED; gCurrentObject->oOpacity = 81; } else { @@ -442,7 +440,7 @@ Gfx* geo_switch_mario_stand_run(s32 callContext, struct GraphNode* node, UNUSED if (callContext == GEO_CONTEXT_RENDER) { // assign result. 0 if moving, 1 if stationary. - switchCase->selectedCase = ((bodyState->action & ACT_FLAG_STATIONARY) == FALSE); + switchCase->selectedCase = ((bodyState->action & ACT_FLAG_STATIONARY) == 0); } return NULL; } @@ -658,16 +656,14 @@ Gfx* geo_mario_rotate_wing_cap_wings(s32 callContext, struct GraphNode* node, UN if (callContext == GEO_CONTEXT_RENDER) { struct GraphNodeRotation* rotNode = (struct GraphNodeRotation*) node->next; - if (bodyState->wingFlutter == FALSE) { + if (!bodyState->wingFlutter) { rotX = (coss((gAreaUpdateCounter & 0xF) << 12) + 1.0f) * 4096.0f; - } - else { + } else { rotX = (coss((gAreaUpdateCounter & 7) << 13) + 1.0f) * 6144.0f; } if (!(asGenerated->parameter & 1)) { rotNode->rotation[0] = -rotX; - } - else { + } else { rotNode->rotation[0] = rotX; } } @@ -741,25 +737,20 @@ Gfx* geo_render_mirror_mario(s32 callContext, struct GraphNode* node, UNUSED Mat if (mario->header.gfx.pos[0] > 1700.0f) { // TODO: Is this a geo layout copy or a graph node copy? gMirrorMario[i].sharedChild = mario->header.gfx.sharedChild; - gMirrorMario[i].unk18 = mario->header.gfx.unk18; + gMirrorMario[i].areaIndex = mario->header.gfx.areaIndex; vec3s_copy(gMirrorMario[i].angle, mario->header.gfx.angle); vec3f_copy(gMirrorMario[i].pos, mario->header.gfx.pos); vec3f_copy(gMirrorMario[i].scale, mario->header.gfx.scale); // FIXME: why does this set unk38, an inline struct, to a ptr to another one? wrong // GraphNode types again? - gMirrorMario[i].unk38 = *(struct GraphNodeObject_sub*) & mario->header.gfx.unk38.animID; + gMirrorMario[i].animInfo = *(struct AnimInfo*) & mario->header.gfx.animInfo.animID; mirroredX = MIRROR_X - gMirrorMario[i].pos[0]; gMirrorMario[i].pos[0] = mirroredX + MIRROR_X; gMirrorMario[i].angle[1] = -gMirrorMario[i].angle[1]; gMirrorMario[i].scale[0] *= -1.0f; - // FIXME: Why doesn't this match? - // gMirrorMario.node.flags |= 1; - ((s16*)&gMirrorMario[i])[1] |= 1; - } - else { - // FIXME: Why doesn't this match? - // gMirrorMario.node.flags &= ~1; - ((s16*)&gMirrorMario[i])[1] &= ~1; + ((struct GraphNode *) &gMirrorMario)->flags |= 1; + } else { + ((struct GraphNode *) &gMirrorMario)->flags &= ~1; } break; } diff --git a/src/game/mario_step.c b/src/game/mario_step.c index 24f417f0..c05039a8 100644 --- a/src/game/mario_step.c +++ b/src/game/mario_step.c @@ -154,7 +154,7 @@ u32 mario_update_quicksand(struct MarioState *m, f32 sinkingSpeed) { } } - return 0; + return FALSE; } u32 mario_push_off_steep_floor(struct MarioState *m, u32 action, u32 actionArg) { @@ -183,10 +183,10 @@ u32 mario_update_moving_sand(struct MarioState *m) { m->vel[0] += pushSpeed * sins(pushAngle); m->vel[2] += pushSpeed * coss(pushAngle); - return 1; + return TRUE; } - return 0; + return FALSE; } u32 mario_update_windy_ground(struct MarioState *m) { @@ -216,10 +216,10 @@ u32 mario_update_windy_ground(struct MarioState *m) { #if VERSION_JP play_sound(SOUND_ENV_WIND2, m->marioObj->header.gfx.cameraToObject); #endif - return 1; + return TRUE; } - return 0; + return FALSE; } void stop_and_set_height_to_floor(struct MarioState *m) { @@ -356,7 +356,7 @@ u32 check_ledge_grab(struct MarioState *m, struct Surface *wall, Vec3f intendedP f32 displacementZ; if (m->vel[1] > 0) { - return 0; + return FALSE; } displacementX = nextPos[0] - intendedPos[0]; @@ -365,7 +365,7 @@ u32 check_ledge_grab(struct MarioState *m, struct Surface *wall, Vec3f intendedP // Only ledge grab if the wall displaced Mario in the opposite direction of // his velocity. if (displacementX * m->vel[0] + displacementZ * m->vel[2] > 0.0f) { - return 0; + return FALSE; } //! Since the search for floors starts at y + 160, we will sometimes grab @@ -375,7 +375,7 @@ u32 check_ledge_grab(struct MarioState *m, struct Surface *wall, Vec3f intendedP ledgePos[1] = find_floor(ledgePos[0], nextPos[1] + 160.0f, ledgePos[2], &ledgeFloor); if (ledgePos[1] - nextPos[1] <= 100.0f) { - return 0; + return FALSE; } vec3f_copy(m->pos, ledgePos); @@ -386,7 +386,7 @@ u32 check_ledge_grab(struct MarioState *m, struct Surface *wall, Vec3f intendedP m->faceAngle[0] = 0; m->faceAngle[1] = atan2s(wall->normal.z, wall->normal.x) + 0x8000; - return 1; + return TRUE; } s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepArg) { diff --git a/src/game/memory.c b/src/game/memory.c index 7305c0b2..788609f5 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -22,7 +22,7 @@ struct MainPoolState { u32 freeSpace; struct MainPoolBlock *listHeadL; struct MainPoolBlock *listHeadR; - void *prev; + struct MainPoolState *prev; }; struct MainPoolBlock { @@ -30,17 +30,17 @@ struct MainPoolBlock { struct MainPoolBlock *next; }; -struct MemoryPool { - u32 totalSpace; - struct MemoryBlock *firstBlock; - struct MemoryBlock *freeList; -}; - struct MemoryBlock { struct MemoryBlock *next; u32 size; }; +struct MemoryPool { + u32 totalSpace; + struct MemoryBlock *firstBlock; + struct MemoryBlock freeList; +}; + extern uintptr_t sSegmentTable[32]; extern u32 sPoolFreeSpace; extern u8 *sPoolStart; @@ -137,7 +137,8 @@ void *main_pool_alloc(u32 size, u32 side) { /** * Free a block of memory that was allocated from the pool. The block must be - * the most recently allocated block from its end of the pool. + * the most recently allocated block from its end of the pool, otherwise all + * newer blocks are freed as well. * Return the amount of free space left in the pool. */ u32 main_pool_free(void *addr) { @@ -192,7 +193,7 @@ u32 main_pool_available(void) { * in the pool. */ u32 main_pool_push_state(void) { - void *prevState = gMainPoolState; + struct MainPoolState *prevState = gMainPoolState; u32 freeSpace = sPoolFreeSpace; struct MainPoolBlock *lhead = sPoolListHeadL; struct MainPoolBlock *rhead = sPoolListHeadR; @@ -305,13 +306,13 @@ struct MemoryPool *mem_pool_init(u32 size, u32 side) { struct MemoryPool *pool = NULL; size = ALIGN4(size); - addr = main_pool_alloc(size + ALIGN16(sizeof(struct MemoryPool)), side); + addr = main_pool_alloc(size + sizeof(struct MemoryPool), side); if (addr != NULL) { pool = (struct MemoryPool *) addr; pool->totalSpace = size; - pool->firstBlock = (struct MemoryBlock *) ((u8 *) addr + ALIGN16(sizeof(struct MemoryPool))); - pool->freeList = (struct MemoryBlock *) ((u8 *) addr + ALIGN16(sizeof(struct MemoryPool))); + pool->firstBlock = (struct MemoryBlock *) ((u8 *) addr + sizeof(struct MemoryPool)); + pool->freeList.next = (struct MemoryBlock *) ((u8 *) addr + sizeof(struct MemoryPool)); block = pool->firstBlock; block->next = NULL; @@ -324,7 +325,7 @@ struct MemoryPool *mem_pool_init(u32 size, u32 side) { * Allocate from a memory pool. Return NULL if there is not enough space. */ void *mem_pool_alloc(struct MemoryPool *pool, u32 size) { - struct MemoryBlock *freeBlock = (struct MemoryBlock *) &pool->freeList; + struct MemoryBlock *freeBlock = &pool->freeList; void *addr = NULL; size = ALIGN4(size) + sizeof(struct MemoryBlock); @@ -352,20 +353,20 @@ void *mem_pool_alloc(struct MemoryPool *pool, u32 size) { */ void mem_pool_free(struct MemoryPool *pool, void *addr) { struct MemoryBlock *block = (struct MemoryBlock *) ((u8 *) addr - sizeof(struct MemoryBlock)); - struct MemoryBlock *freeList = pool->freeList; + struct MemoryBlock *freeList = pool->freeList.next; - if (pool->freeList == NULL) { - pool->freeList = block; + if (pool->freeList.next == NULL) { + pool->freeList.next = block; block->next = NULL; } else { - if (block < pool->freeList) { - if ((u8 *) pool->freeList == (u8 *) block + block->size) { + if (block < pool->freeList.next) { + if ((u8 *) pool->freeList.next == (u8 *) block + block->size) { block->size += freeList->size; block->next = freeList->next; - pool->freeList = block; + pool->freeList.next = block; } else { - block->next = pool->freeList; - pool->freeList = block; + block->next = pool->freeList.next; + pool->freeList.next = block; } } else { while (freeList->next != NULL) { diff --git a/src/game/moving_texture.c b/src/game/moving_texture.c index 4946508b..0ef991e4 100644 --- a/src/game/moving_texture.c +++ b/src/game/moving_texture.c @@ -308,9 +308,9 @@ Gfx *geo_wdw_set_initial_water_level(s32 callContext, UNUSED struct GraphNode *n // Why was this global variable needed when they could just check for GEO_CONTEXT_AREA_LOAD? if (callContext != GEO_CONTEXT_RENDER) { - gWdwWaterLevelSet = 0; + gWdwWaterLevelSet = FALSE; } else if (callContext == GEO_CONTEXT_RENDER && gEnvironmentRegions != NULL - && gWdwWaterLevelSet == 0) { + && !gWdwWaterLevelSet) { if (gPaintingMarioYEntry <= 1382.4) { wdwWaterHeight = 31; } else if (gPaintingMarioYEntry >= 1600.0) { @@ -321,7 +321,7 @@ Gfx *geo_wdw_set_initial_water_level(s32 callContext, UNUSED struct GraphNode *n for (i = 0; i < *gEnvironmentRegions; i++) { gEnvironmentRegions[i * 6 + 6] = wdwWaterHeight; } - gWdwWaterLevelSet = 1; + gWdwWaterLevelSet = TRUE; } return NULL; } @@ -648,7 +648,7 @@ Gfx *geo_movtex_draw_water_regions(s32 callContext, struct GraphNode *node, UNUS if (gLakituState.goalPos[1] < 1024.0) { // if camera under water return NULL; } - if (save_file_get_star_flags(gCurrSaveFileNum - 1, 2) & 1) { // first level in JRB complete + if (save_file_get_star_flags(gCurrSaveFileNum - 1, COURSE_JRB - 1) & 1) { // first star in JRB complete return NULL; } } else if (asGenerated->parameter == HMC_MOVTEX_TOXIC_MAZE_MIST) { diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c index e3857742..36b36a3e 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -111,7 +111,7 @@ Gfx UNUSED *geo_obj_transparency_something(s32 callContext, struct GraphNode *no gfxHead = alloc_display_list(3 * sizeof(Gfx)); gfx = gfxHead; obj->header.gfx.node.flags = - (obj->header.gfx.node.flags & 0xFF) | (GRAPH_NODE_TYPE_FUNCTIONAL | GRAPH_NODE_TYPE_400); // sets bits 8, 10 and zeros upper byte + (obj->header.gfx.node.flags & 0xFF) | (GRAPH_NODE_TYPE_FUNCTIONAL | GRAPH_NODE_TYPE_400); gDPSetEnvColor(gfx++, 255, 255, 255, heldObject->oOpacity); @@ -218,12 +218,12 @@ void obj_orient_graph(struct Object *obj, f32 normalX, f32 normalY, f32 normalZ) Mat4 *throwMatrix; // Passes on orienting certain objects that shouldn't be oriented, like boulders. - if (sOrientObjWithFloor == FALSE) { + if (!sOrientObjWithFloor) { return; } // Passes on orienting billboard objects, i.e. coins, trees, etc. - if ((obj->header.gfx.node.flags & GRAPH_RENDER_BILLBOARD) != 0) { + if (obj->header.gfx.node.flags & GRAPH_RENDER_BILLBOARD) { return; } @@ -746,9 +746,9 @@ s16 trigger_obj_dialog_when_facing(struct MarioState* m, s32 *inDialog, s16 dial int angleToPlayer = obj_angle_to_object(o, m->marioObj); - if ((is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, (s32) dist) == 1 - && obj_check_if_facing_toward_angle(o->oFaceAngleYaw, m->marioObj->header.gfx.angle[1] + 0x8000, 0x1000) == 1 - && obj_check_if_facing_toward_angle(o->oMoveAngleYaw, angleToPlayer, 0x1000) == 1) + if ((is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, (s32) dist) == TRUE + && obj_check_if_facing_toward_angle(o->oFaceAngleYaw, m->marioObj->header.gfx.angle[1] + 0x8000, 0x1000) == TRUE + && obj_check_if_facing_toward_angle(o->oMoveAngleYaw, angleToPlayer, 0x1000) == TRUE) || (*inDialog == 1)) { *inDialog = 1; @@ -774,8 +774,7 @@ void obj_check_floor_death(s16 collisionFlags, struct Surface *floor) { return; } - if ((collisionFlags & OBJ_COL_FLAG_GROUNDED) == 1) - { + if ((collisionFlags & OBJ_COL_FLAG_GROUNDED) == OBJ_COL_FLAG_GROUNDED) { switch (floor->type) { case SURFACE_BURNING: o->oAction = OBJ_ACT_LAVA_DEATH; @@ -848,7 +847,7 @@ s32 UNUSED debug_sequence_tracker(s16 debugInputSequence[]) { } // If the third controller button pressed is next in sequence, reset timer and progress to next value. - if ((debugInputSequence[sDebugSequenceTracker] & gPlayer1Controller->buttonPressed) != 0) { + if (debugInputSequence[sDebugSequenceTracker] & gPlayer1Controller->buttonPressed) { sDebugSequenceTracker++; sDebugTimer = 0; // If wrong input or timer reaches 10, reset sequence progress. diff --git a/src/game/obj_behaviors_2.c b/src/game/obj_behaviors_2.c index a6abc326..5602679f 100644 --- a/src/game/obj_behaviors_2.c +++ b/src/game/obj_behaviors_2.c @@ -367,7 +367,7 @@ static s32 cur_obj_set_anim_if_at_end(s32 arg0) { static s32 cur_obj_play_sound_at_anim_range(s8 arg0, s8 arg1, u32 sound) { s32 val04; - if ((val04 = o->header.gfx.unk38.animAccel / 0x10000) <= 0) { + if ((val04 = o->header.gfx.animInfo.animAccel / 0x10000) <= 0) { val04 = 1; } @@ -767,7 +767,7 @@ static s32 obj_handle_attacks(struct ObjectHitbox *hitbox, s32 attackedMarioActi static void obj_act_knockback(UNUSED f32 baseScale) { cur_obj_update_floor_and_walls(); - if (o->header.gfx.unk38.curAnim != NULL) { + if (o->header.gfx.animInfo.curAnim != NULL) { cur_obj_extend_animation_if_at_end(); } @@ -786,7 +786,7 @@ static void obj_act_squished(f32 baseScale) { cur_obj_update_floor_and_walls(); - if (o->header.gfx.unk38.curAnim != NULL) { + if (o->header.gfx.animInfo.curAnim != NULL) { cur_obj_extend_animation_if_at_end(); } @@ -950,19 +950,17 @@ static void treat_far_home_as_mario(f32 threshold, int* distanceToPlayer, int* a #include "behaviors/flying_bookend_switch.inc.c" /** - * Used by fly guy, piranha plant, and fire spitters. + * Used by bowser, fly guy, piranha plant, and fire spitters. */ struct Object* obj_spit_fire(s16 relativePosX, s16 relativePosY, s16 relativePosZ, f32 scale, s32 model, f32 startSpeed, f32 endSpeed, s16 movePitch) { - struct Object *sp2C; - - sp2C = spawn_object_relative_with_scale(1, relativePosX, relativePosY, relativePosZ, scale, o, - model, bhvSmallPiranhaFlame); + struct Object *sp2C = spawn_object_relative_with_scale(1, relativePosX, relativePosY, relativePosZ, + scale, o, model, bhvSmallPiranhaFlame); if (sp2C != NULL) { - sp2C->oSmallPiranhaFlameUnkF4 = startSpeed; - sp2C->oSmallPiranhaFlameUnkF8 = endSpeed; - sp2C->oSmallPiranhaFlameUnkFC = model; + sp2C->oSmallPiranhaFlameStartSpeed = startSpeed; + sp2C->oSmallPiranhaFlameEndSpeed = endSpeed; + sp2C->oSmallPiranhaFlameModel = model; sp2C->oMoveAnglePitch = movePitch; } return sp2C; diff --git a/src/game/object_collision.c b/src/game/object_collision.c index da46ace7..f899ea08 100644 --- a/src/game/object_collision.c +++ b/src/game/object_collision.c @@ -69,7 +69,7 @@ int detect_player_hitbox_overlap(struct MarioState* local, struct MarioState* re return FALSE; } -int detect_object_hitbox_overlap(struct Object *a, struct Object *b) { +s32 detect_object_hitbox_overlap(struct Object *a, struct Object *b) { f32 sp3C = a->oPosY - a->hitboxDownOffset; f32 sp38 = b->oPosY - b->hitboxDownOffset; f32 dx = a->oPosX - b->oPosX; @@ -111,7 +111,7 @@ int detect_object_hitbox_overlap(struct Object *a, struct Object *b) { //! no return value } -int detect_object_hurtbox_overlap(struct Object *a, struct Object *b) { +s32 detect_object_hurtbox_overlap(struct Object *a, struct Object *b) { f32 sp3C = a->oPosY - a->hitboxDownOffset; f32 sp38 = b->oPosY - b->hitboxDownOffset; f32 sp34 = a->oPosX - b->oPosX; diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index 7c65739e..345bf3d7 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -31,7 +31,7 @@ u8 (*gContinueDialogFunction)(void) = NULL; struct Object* gContinueDialogFunctionObject = NULL; -s8 D_8032F0A0[] = { 0xF8, 0x08, 0xFC, 0x04 }; +s8 D_8032F0A0[] = { -8, 8, -4, 4 }; s16 D_8032F0A4[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; static s8 sLevelsWithRooms[] = { LEVEL_BBH, LEVEL_CASTLE, LEVEL_HMC, -1 }; @@ -230,11 +230,9 @@ Gfx *geo_switch_area(s32 callContext, struct GraphNode *node) { } void obj_update_pos_from_parent_transformation(Mat4 a0, struct Object *a1) { - f32 spC, sp8, sp4; - - spC = a1->oParentRelativePosX; - sp8 = a1->oParentRelativePosY; - sp4 = a1->oParentRelativePosZ; + f32 spC = a1->oParentRelativePosX; + f32 sp8 = a1->oParentRelativePosY; + f32 sp4 = a1->oParentRelativePosZ; a1->oPosX = spC * a0[0][0] + sp8 * a0[1][0] + sp4 * a0[2][0] + a0[3][0]; a1->oPosY = spC * a0[0][1] + sp8 * a0[1][1] + sp4 * a0[2][1] + a0[3][1]; @@ -423,7 +421,7 @@ s16 obj_angle_to_object(struct Object *obj1, struct Object *obj2) { f32 z1, x1, z2, x2; s16 angle; - z1 = obj1->oPosZ; z2 = obj2->oPosZ; //ordering of instructions.. + z1 = obj1->oPosZ; z2 = obj2->oPosZ; // ordering of instructions.. x1 = obj1->oPosX; x2 = obj2->oPosX; angle = atan2s(z2 - z1, x2 - x1); @@ -592,8 +590,8 @@ struct Object *spawn_object_at_origin(struct Object *parent, UNUSED s32 unusedAr obj = create_object(behaviorAddr); obj->parentObj = parent; - obj->header.gfx.unk18 = parent->header.gfx.unk18; - obj->header.gfx.unk19 = parent->header.gfx.unk18; + obj->header.gfx.areaIndex = parent->header.gfx.areaIndex; + obj->header.gfx.activeAreaIndex = parent->header.gfx.areaIndex; obj->globalPlayerIndex = 0; geo_obj_init((struct GraphNodeObject *) &obj->header.gfx, gLoadedGraphNodes[model], gVec3fZero, @@ -603,9 +601,8 @@ struct Object *spawn_object_at_origin(struct Object *parent, UNUSED s32 unusedAr } struct Object *spawn_object(struct Object *parent, s32 model, const BehaviorScript *behavior) { - struct Object *obj; + struct Object *obj = spawn_object_at_origin(parent, 0, model, behavior); - obj = spawn_object_at_origin(parent, 0, model, behavior); obj_copy_pos_and_angle(obj, parent); return obj; @@ -626,9 +623,8 @@ struct Object *try_to_spawn_object(s16 offsetY, f32 scale, struct Object *parent } struct Object *spawn_object_with_scale(struct Object *parent, s32 model, const BehaviorScript *behavior, f32 scale) { - struct Object *obj; + struct Object *obj = spawn_object_at_origin(parent, 0, model, behavior); - obj = spawn_object_at_origin(parent, 0, model, behavior); obj_copy_pos_and_angle(obj, parent); obj_scale(obj, scale); @@ -657,10 +653,8 @@ struct Object *spawn_object_relative(s16 behaviorParam, s16 relativePosX, s16 re struct Object *spawn_object_relative_with_scale(s16 behaviorParam, s16 relativePosX, s16 relativePosY, s16 relativePosZ, f32 scale, struct Object *parent, s32 model, const BehaviorScript *behavior) { - struct Object *obj; - - obj = spawn_object_relative(behaviorParam, relativePosX, relativePosY, relativePosZ, parent, model, - behavior); + struct Object *obj = spawn_object_relative(behaviorParam, relativePosX, relativePosY, relativePosZ, + parent, model, behavior); obj_scale(obj, scale); return obj; @@ -739,11 +733,9 @@ void linear_mtxf_transpose_mul_vec3f(Mat4 m, Vec3f dst, Vec3f v) { } void obj_apply_scale_to_transform(struct Object *obj) { - f32 scaleX, scaleY, scaleZ; - - scaleX = obj->header.gfx.scale[0]; - scaleY = obj->header.gfx.scale[1]; - scaleZ = obj->header.gfx.scale[2]; + f32 scaleX = obj->header.gfx.scale[0]; + f32 scaleY = obj->header.gfx.scale[1]; + f32 scaleZ = obj->header.gfx.scale[2]; obj->transform[0][0] *= scaleX; obj->transform[0][1] *= scaleX; @@ -787,7 +779,6 @@ void cur_obj_init_animation(s32 animIndex) { geo_obj_init_animation(&o->header.gfx, &anims[animIndex]); } - void cur_obj_init_animation_with_sound(s32 animIndex) { struct Animation **anims = o->oAnimations; geo_obj_init_animation(&o->header.gfx, &anims[animIndex]); @@ -1077,42 +1068,40 @@ void cur_obj_set_vel_from_mario_vel(struct MarioState* m, f32 f12, f32 f14) { } BAD_RETURN(s16) cur_obj_reverse_animation(void) { - if (o->header.gfx.unk38.animFrame >= 0) { - o->header.gfx.unk38.animFrame--; + if (o->header.gfx.animInfo.animFrame >= 0) { + o->header.gfx.animInfo.animFrame--; } } BAD_RETURN(s32) cur_obj_extend_animation_if_at_end(void) { - s32 sp4 = o->header.gfx.unk38.animFrame; - s32 sp0 = o->header.gfx.unk38.curAnim->unk08 - 2; + s32 sp4 = o->header.gfx.animInfo.animFrame; + s32 sp0 = o->header.gfx.animInfo.curAnim->loopEnd - 2; - if (sp4 == sp0) o->header.gfx.unk38.animFrame--; + if (sp4 == sp0) o->header.gfx.animInfo.animFrame--; } s32 cur_obj_check_if_near_animation_end(void) { - u32 spC = (s32) o->header.gfx.unk38.curAnim->flags; - s32 sp8 = o->header.gfx.unk38.animFrame; - s32 sp4 = o->header.gfx.unk38.curAnim->unk08 - 2; - s32 sp0 = FALSE; + u32 animFlags = (s32) o->header.gfx.animInfo.curAnim->flags; + s32 animFrame = o->header.gfx.animInfo.animFrame; + s32 nearLoopEnd = o->header.gfx.animInfo.curAnim->loopEnd - 2; + s32 isNearEnd = FALSE; - if (spC & 0x01) { - if (sp4 + 1 == sp8) { - sp0 = TRUE; - } + if (animFlags & ANIM_FLAG_NOLOOP && nearLoopEnd + 1 == animFrame) { + isNearEnd = TRUE; } - if (sp8 == sp4) { - sp0 = TRUE; + if (animFrame == nearLoopEnd) { + isNearEnd = TRUE; } - return sp0; + return isNearEnd; } s32 cur_obj_check_if_at_animation_end(void) { - s32 sp4 = o->header.gfx.unk38.animFrame; - s32 sp0 = o->header.gfx.unk38.curAnim->unk08 - 1; + s32 animFrame = o->header.gfx.animInfo.animFrame; + s32 lastFrame = o->header.gfx.animInfo.curAnim->loopEnd - 1; - if (sp4 == sp0) { + if (animFrame == lastFrame) { return TRUE; } else { return FALSE; @@ -1120,7 +1109,7 @@ s32 cur_obj_check_if_at_animation_end(void) { } s32 cur_obj_check_anim_frame(s32 frame) { - s32 animFrame = o->header.gfx.unk38.animFrame; + s32 animFrame = o->header.gfx.animInfo.animFrame; if (animFrame == frame) { return TRUE; @@ -1130,7 +1119,7 @@ s32 cur_obj_check_anim_frame(s32 frame) { } s32 cur_obj_check_anim_frame_in_range(s32 startFrame, s32 rangeLength) { - s32 animFrame = o->header.gfx.unk38.animFrame; + s32 animFrame = o->header.gfx.animInfo.animFrame; if (animFrame >= startFrame && animFrame < startFrame + rangeLength) { return TRUE; @@ -1140,7 +1129,7 @@ s32 cur_obj_check_anim_frame_in_range(s32 startFrame, s32 rangeLength) { } s32 cur_obj_check_frame_prior_current_frame(s16 *a0) { - s16 sp6 = o->header.gfx.unk38.animFrame; + s16 sp6 = o->header.gfx.animInfo.animFrame; while (*a0 != -1) { if (*a0 == sp6) { @@ -1655,7 +1644,7 @@ s32 cur_obj_outside_home_square(f32 halfLength) { return TRUE; } - return 0; + return FALSE; } s32 cur_obj_outside_home_rectangle(f32 minX, f32 maxX, f32 minZ, f32 maxZ) { @@ -1708,7 +1697,7 @@ void cur_obj_start_cam_event(UNUSED struct Object *obj, s32 cameraEvent) { void set_mario_interact_hoot_if_in_range(UNUSED s32 sp0, UNUSED s32 sp4, f32 sp8) { if (o->oDistanceToMario < sp8) { - gMarioObject->oInteractStatus = 1; + gMarioObject->oInteractStatus = INT_STATUS_HOOT_GRABBED_BY_MARIO; } } @@ -1790,21 +1779,21 @@ f32 cur_obj_abs_y_dist_to_home(void) { } s32 cur_obj_advance_looping_anim(void) { - s32 spC = o->header.gfx.unk38.animFrame; - s32 sp8 = o->header.gfx.unk38.curAnim->unk08; - s32 sp4; + s32 animFrame = o->header.gfx.animInfo.animFrame; + s32 loopEnd = o->header.gfx.animInfo.curAnim->loopEnd; + s32 result; - if (spC < 0) { - spC = 0; - } else if (sp8 - 1 == spC) { - spC = 0; + if (animFrame < 0) { + animFrame = 0; + } else if (loopEnd - 1 == animFrame) { + animFrame = 0; } else { - spC++; + animFrame++; } - sp4 = (spC << 16) / sp8; + result = (animFrame << 16) / loopEnd; - return sp4; + return result; } static s32 cur_obj_detect_steep_floor(s16 steepAngleDegrees) { @@ -1813,7 +1802,7 @@ static s32 cur_obj_detect_steep_floor(s16 steepAngleDegrees) { f32 deltaFloorHeight; f32 steepNormalY = coss((s16)(steepAngleDegrees * (0x10000 / 360))); - if (o->oForwardVel != 0) { + if (o->oForwardVel != 0.0f) { intendedX = o->oPosX + o->oVelX; intendedZ = o->oPosZ + o->oVelZ; intendedFloorHeight = find_floor(intendedX, o->oPosY, intendedZ, &intendedFloor); @@ -1858,14 +1847,14 @@ s32 cur_obj_resolve_wall_collisions(void) { o->oWallAngle = atan2s(wall->normal.z, wall->normal.x); if (abs_angle_diff(o->oWallAngle, o->oMoveAngleYaw) > 0x4000) { - return 1; + return TRUE; } else { - return 0; + return FALSE; } } } - return 0; + return FALSE; } static void cur_obj_update_floor(void) { @@ -1957,7 +1946,7 @@ void cur_obj_move_standard(s16 steepSlopeAngleDegrees) { cur_obj_move_xz(steepSlopeNormalY, careAboutEdgesAndSteepSlopes); cur_obj_move_y(gravity, bounciness, buoyancy); - if (o->oForwardVel < 0) { + if (o->oForwardVel < 0.0f) { negativeSpeed = TRUE; } o->oForwardVel = sqrtf(sqr(o->oVelX) + sqr(o->oVelZ)); @@ -2294,11 +2283,11 @@ f32 absf(f32 x) { } } -s32 absi(s32 a0) { - if (a0 >= 0) { - return a0; +s32 absi(s32 x) { + if (x >= 0) { + return x; } else { - return -a0; + return -x; } } @@ -2363,7 +2352,7 @@ void cur_obj_push_mario_away_from_cylinder(f32 radius, f32 extentY) { struct Object* player = gMarioStates[i].marioObj; f32 marioRelY = player->oPosY - o->oPosY; - if (marioRelY < 0) { + if (marioRelY < 0.0f) { marioRelY = -marioRelY; } @@ -2484,11 +2473,11 @@ s32 cur_obj_shake_y_until(s32 cycles, s32 amount) { s32 cur_obj_move_up_and_down(s32 a0) { if (a0 >= 4 || a0 < 0) { - return 1; + return TRUE; } o->oPosY += D_8032F0A0[a0]; - return 0; + return FALSE; } void cur_obj_call_action_function(void (*actionFunctions[])(void)) { @@ -2718,12 +2707,9 @@ void clear_time_stop_flags(s32 flags) { } s32 cur_obj_can_mario_activate_textbox(struct MarioState* m, f32 radius, f32 height, UNUSED s32 unused) { - f32 latDistToMario; - UNUSED s16 angleFromMario; - if (o->oDistanceToMario < 1500.0f) { - latDistToMario = lateral_dist_between_objects(o, m->marioObj); - angleFromMario = obj_angle_to_object(m->marioObj, o); + f32 latDistToMario = lateral_dist_between_objects(o, m->marioObj); + UNUSED s16 angleFromMario = obj_angle_to_object(m->marioObj, o); if (latDistToMario < radius && o->oPosY < m->marioObj->oPosY + 160.0f && m->marioObj->oPosY < o->oPosY + height && !(m->action & ACT_FLAG_AIR) @@ -2867,7 +2853,7 @@ s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32 case DIALOG_UNK2_TURN_AND_INTERRUPT_MARIO_ACTION: if (dialogFlags & DIALOG_UNK2_FLAG_0) { doneTurning = cur_obj_rotate_yaw_toward(obj_angle_to_object(o, m->marioObj), 0x800); - if (o->oDialogResponse >= 0x21) { + if (o->oDialogResponse >= 33) { doneTurning = TRUE; } } @@ -2996,7 +2982,7 @@ void obj_copy_behavior_params(struct Object *dst, struct Object *src) { void cur_obj_init_animation_and_anim_frame(s32 animIndex, s32 animFrame) { cur_obj_init_animation_with_sound(animIndex); - o->header.gfx.unk38.animFrame = animFrame; + o->header.gfx.animInfo.animFrame = animFrame; } s32 cur_obj_init_animation_and_check_if_near_end(s32 animIndex) { diff --git a/src/game/object_list_processor.c b/src/game/object_list_processor.c index 2bd3da8f..ec765d41 100644 --- a/src/game/object_list_processor.c +++ b/src/game/object_list_processor.c @@ -474,7 +474,7 @@ void unload_objects_from_area(UNUSED s32 unused, s32 areaIndex) { obj = (struct Object *) node; node = node->next; - if (obj->header.gfx.unk19 == areaIndex) { + if (obj->header.gfx.activeAreaIndex == areaIndex) { unload_object(obj); } } @@ -489,7 +489,7 @@ void spawn_objects_from_info(UNUSED s32 unused, struct SpawnInfo *spawnInfo) { gTimeStopState = 0; gWDWWaterLevelChanging = FALSE; - gMarioOnMerryGoRound = 0; + gMarioOnMerryGoRound = FALSE; //! (Spawning Displacement) On the Japanese version, Mario's platform object // isn't cleared when transitioning between areas. This can cause Mario to diff --git a/src/game/paintings.c b/src/game/paintings.c index 5301901e..f8cab691 100644 --- a/src/game/paintings.c +++ b/src/game/paintings.c @@ -603,7 +603,7 @@ void painting_update_ripple_state(struct Painting *painting) { //! After ~6.47 days, paintings with RIPPLE_TRIGGER_CONTINUOUS will increment this to //! 16777216 (1 << 24), at which point it will freeze (due to floating-point //! imprecision?) and the painting will stop rippling. This happens to HMC, DDD, and - //! CotMC. This happens on Wii VC. Untested on N64 and Wii U VC. + //! CotMC. painting->rippleTimer += 1.0; } if (painting->rippleTrigger == RIPPLE_TRIGGER_PROXIMITY) { diff --git a/src/game/platform_displacement.c b/src/game/platform_displacement.c index a006fde0..4f6b1a4d 100644 --- a/src/game/platform_displacement.c +++ b/src/game/platform_displacement.c @@ -90,7 +90,7 @@ void set_mario_pos(struct MarioState* m, f32 x, f32 y, f32 z) { /** * Apply one frame of platform rotation to Mario or an object using the given - * platform. If isMario is 0, use gCurrentObject. + * platform. If isMario is false, use gCurrentObject. */ void apply_platform_displacement(u32 playerIndex, struct Object *platform) { f32 x; diff --git a/src/game/print.c b/src/game/print.c index f7a83865..09662b06 100644 --- a/src/game/print.c +++ b/src/game/print.c @@ -67,7 +67,7 @@ void format_integer(s32 n, s32 base, char *dest, s32 *totalLength, u8 width, s8 } // Increments the number of digits until length is long enough. - while (1) { + while (TRUE) { powBase = int_pow(base, numDigits); if (powBase > (u32) n) { diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index a844624f..d2964668 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -651,7 +651,7 @@ static void geo_process_generated_list(struct GraphNodeGenerated *node) { Gfx *list = node->fnNode.func(GEO_CONTEXT_RENDER, &node->fnNode.node, (struct AllocOnlyPool *) gMatStack[gMatStackIndex]); - if (list != 0) { + if (list != NULL) { geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(list), node->fnNode.node.flags >> 8); } } @@ -697,9 +697,8 @@ static void geo_process_background(struct GraphNodeBackground *node) { vec3f_copy(gLakituState.pos, posCopy); vec3f_copy(gLakituState.focus, focusCopy); } - if (list != 0) { - geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(list), - (void *) VIRTUAL_TO_PHYSICAL(listInterpolated), node->fnNode.node.flags >> 8); + if (list != NULL) { + geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(list), (void *) VIRTUAL_TO_PHYSICAL(listInterpolated), node->fnNode.node.flags >> 8); } else if (gCurGraphNodeMasterList != NULL) { #ifndef F3DEX_GBI_2E Gfx *gfxStart = alloc_display_list(sizeof(Gfx) * 7); @@ -818,10 +817,10 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) { * Initialize the animation-related global variables for the currently drawn * object's animation. */ -void geo_set_animation_globals(struct GraphNodeObject_sub *node, s32 hasAnimation) { +void geo_set_animation_globals(struct AnimInfo *node, s32 hasAnimation) { struct Animation *anim = node->curAnim; - if (hasAnimation != 0) { + if (hasAnimation) { node->animFrame = geo_update_animation_frame(node, &node->animFrameAccelAssist); } node->animTimer = gAreaUpdateCounter; @@ -851,10 +850,10 @@ void geo_set_animation_globals(struct GraphNodeObject_sub *node, s32 hasAnimatio gCurrAnimAttribute = segmented_to_virtual((void *) anim->index); gCurAnimData = segmented_to_virtual((void *) anim->values); - if (anim->unk02 == 0) { + if (anim->animYTransDivisor == 0) { gCurAnimTranslationMultiplier = 1.0f; } else { - gCurAnimTranslationMultiplier = (f32) node->animYTrans / (f32) anim->unk02; + gCurAnimTranslationMultiplier = (f32) node->animYTrans / (f32) anim->animYTransDivisor; } } @@ -889,7 +888,7 @@ static void geo_process_shadow(struct GraphNodeShadow *node) { } objScale = 1.0f; - if (gCurAnimEnabled != 0) { + if (gCurAnimEnabled) { if (gCurAnimType == ANIM_TYPE_TRANSLATION || gCurAnimType == ANIM_TYPE_LATERAL_TRANSLATION) { geo = node->node.children; @@ -958,10 +957,10 @@ static void geo_process_shadow(struct GraphNodeShadow *node) { mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]); gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated; - if (gShadowAboveWaterOrLava == 1) { + if (gShadowAboveWaterOrLava == TRUE) { geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList), (void *) VIRTUAL_TO_PHYSICAL(shadowListInterpolated), 4); - } else if (gMarioOnIceOrCarpet == 1) { + } else if (gMarioOnIceOrCarpet == TRUE) { geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList), (void *) VIRTUAL_TO_PHYSICAL(shadowListInterpolated), 5); } else { @@ -1007,7 +1006,7 @@ static void geo_process_shadow(struct GraphNodeShadow *node) { * * Since (0,0,0) is unaffected by rotation, columns 0, 1 and 2 are ignored. */ -static int obj_is_in_view(struct GraphNodeObject *node, Mat4 matrix) { +static s32 obj_is_in_view(struct GraphNodeObject *node, Mat4 matrix) { s16 cullingRadius; s16 halfFov; // half of the fov in in-game angle units instead of degrees struct GraphNode *geo; @@ -1094,7 +1093,8 @@ static void geo_process_object(struct Object *node) { gCurGraphNodeMarioState->minimumBoneY = 999; } } - if (node->header.gfx.unk18 == gCurGraphNodeRoot->areaIndex) { + + if (node->header.gfx.areaIndex == gCurGraphNodeRoot->areaIndex) { if (node->header.gfx.throwMatrix != NULL) { mtxf_mul(gMatStack[gMatStackIndex + 1], *node->header.gfx.throwMatrix, gMatStack[gMatStackIndex]); @@ -1182,8 +1182,8 @@ static void geo_process_object(struct Object *node) { node->header.gfx.cameraToObject[2] = gMatStack[gMatStackIndex][3][2]; // FIXME: correct types - if (node->header.gfx.unk38.curAnim != NULL) { - geo_set_animation_globals(&node->header.gfx.unk38, hasAnimation); + if (node->header.gfx.animInfo.curAnim != NULL) { + geo_set_animation_globals(&node->header.gfx.animInfo, hasAnimation); } if (obj_is_in_view(&node->header.gfx, gMatStack[gMatStackIndex])) { Mtx *mtx = alloc_display_list(sizeof(*mtx)); @@ -1299,8 +1299,8 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { gGeoTempState.prevFrame = gPrevAnimFrame; gCurAnimType = 0; gCurGraphNodeHeldObject = (void *) node; - if (node->objNode->header.gfx.unk38.curAnim != NULL) { - geo_set_animation_globals(&node->objNode->header.gfx.unk38, hasAnimation); + if (node->objNode->header.gfx.animInfo.curAnim != NULL) { + geo_set_animation_globals(&node->objNode->header.gfx.animInfo, hasAnimation); } geo_process_node_and_siblings(node->objNode->header.gfx.sharedChild); diff --git a/src/game/save_file.c b/src/game/save_file.c index 408ab1d7..0cca7d97 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -32,10 +32,10 @@ s8 gSaveFileModified; u8 gLastCompletedCourseNum = COURSE_NONE; u8 gLastCompletedStarNum = 0; s8 sUnusedGotGlobalCoinHiScore = 0; -u8 gGotFileCoinHiScore = 0; +u8 gGotFileCoinHiScore = FALSE; u8 gCurrCourseStarFlags = 0; -u8 gSpecialTripleJump = 0; +u8 gSpecialTripleJump = FALSE; #define STUB_LEVEL(_0, _1, courseenum, _3, _4, _5, _6, _7, _8) courseenum, #define DEFINE_LEVEL(_0, _1, courseenum, _3, _4, _5, _6, _7, _8, _9, _10) courseenum, @@ -497,7 +497,7 @@ void save_file_collect_star_or_key(s16 coinScore, s16 starIndex, u8 fromNetwork) gLastCompletedCourseNum = courseIndex + 1; gLastCompletedStarNum = starIndex + 1; sUnusedGotGlobalCoinHiScore = 0; - gGotFileCoinHiScore = 0; + gGotFileCoinHiScore = FALSE; } if (courseIndex >= 0 && courseIndex < COURSE_STAGES_COUNT && !fromNetwork) { @@ -512,7 +512,7 @@ void save_file_collect_star_or_key(s16 coinScore, s16 starIndex, u8 fromNetwork) gSaveBuffer.files[fileIndex][0].courseCoinScores[courseIndex] = coinScore; touch_coin_score_age(fileIndex, courseIndex); - gGotFileCoinHiScore = 1; + gGotFileCoinHiScore = TRUE; gSaveFileModified = TRUE; } } @@ -614,7 +614,7 @@ void save_file_clear_flags(u32 flags) { } u32 save_file_get_flags(void) { - if (gCurrCreditsEntry != 0 || gCurrDemoInput != NULL) { + if (gCurrCreditsEntry != NULL || gCurrDemoInput != NULL) { return 0; } return gSaveBuffer.files[gCurrSaveFileNum - 1][0].flags; @@ -628,7 +628,7 @@ u32 save_file_get_star_flags(s32 fileIndex, s32 courseIndex) { u32 starFlags; if (courseIndex == -1) { - starFlags = (gSaveBuffer.files[fileIndex][0].flags >> 24) & 0x7F; + starFlags = SAVE_FLAG_TO_STAR_FLAG(gSaveBuffer.files[fileIndex][0].flags); } else { starFlags = gSaveBuffer.files[fileIndex][0].courseStars[courseIndex] & 0x7F; } @@ -642,8 +642,8 @@ u32 save_file_get_star_flags(s32 fileIndex, s32 courseIndex) { */ void save_file_set_star_flags(s32 fileIndex, s32 courseIndex, u32 starFlags) { if (courseIndex == -1) { - gSaveBuffer.files[fileIndex][0].flags |= starFlags << 24; - network_send_save_set_flag(fileIndex, courseIndex, 0, ((starFlags << 24) | SAVE_FLAG_FILE_EXISTS)); + gSaveBuffer.files[fileIndex][0].flags |= STAR_FLAG_TO_SAVE_FLAG(starFlags); + network_send_save_set_flag(fileIndex, courseIndex, 0, (STAR_FLAG_TO_SAVE_FLAG(starFlags) | SAVE_FLAG_FILE_EXISTS)); } else { gSaveBuffer.files[fileIndex][0].courseStars[courseIndex] |= starFlags; network_send_save_set_flag(fileIndex, courseIndex, starFlags, SAVE_FLAG_FILE_EXISTS); @@ -765,7 +765,7 @@ void check_if_should_set_warp_checkpoint(struct WarpNode *warpNode) { * returns TRUE if input WarpNode was updated, and FALSE if not. */ s32 check_warp_checkpoint(struct WarpNode *warpNode) { - s16 isWarpCheckpointActive = FALSE; + s16 warpCheckpointActive = FALSE; s16 currCourseNum = gLevelToCourseNumTable[(warpNode->destLevel & 0x7F) - 1]; // gSavedCourseNum is only used in this function. @@ -774,11 +774,11 @@ s32 check_warp_checkpoint(struct WarpNode *warpNode) { warpNode->destLevel = gWarpCheckpoint.levelID; warpNode->destArea = gWarpCheckpoint.areaNum; warpNode->destNode = gWarpCheckpoint.warpNode; - isWarpCheckpointActive = TRUE; + warpCheckpointActive = TRUE; } else { // Disable the warp checkpoint just in case the other 2 conditions failed? gWarpCheckpoint.courseNum = COURSE_NONE; } - return isWarpCheckpointActive; + return warpCheckpointActive; } diff --git a/src/game/save_file.h b/src/game/save_file.h index bc86ddfc..18d33d21 100644 --- a/src/game/save_file.h +++ b/src/game/save_file.h @@ -83,27 +83,35 @@ extern u8 gSpecialTripleJump; extern s8 gLevelToCourseNumTable[]; // game progress flags -#define SAVE_FLAG_FILE_EXISTS /* 0x000001 */ (1 << 0) -#define SAVE_FLAG_HAVE_WING_CAP /* 0x000002 */ (1 << 1) -#define SAVE_FLAG_HAVE_METAL_CAP /* 0x000004 */ (1 << 2) -#define SAVE_FLAG_HAVE_VANISH_CAP /* 0x000008 */ (1 << 3) -#define SAVE_FLAG_HAVE_KEY_1 /* 0x000010 */ (1 << 4) -#define SAVE_FLAG_HAVE_KEY_2 /* 0x000020 */ (1 << 5) -#define SAVE_FLAG_UNLOCKED_BASEMENT_DOOR /* 0x000040 */ (1 << 6) -#define SAVE_FLAG_UNLOCKED_UPSTAIRS_DOOR /* 0x000080 */ (1 << 7) -#define SAVE_FLAG_DDD_MOVED_BACK /* 0x000100 */ (1 << 8) -#define SAVE_FLAG_MOAT_DRAINED /* 0x000200 */ (1 << 9) -#define SAVE_FLAG_UNLOCKED_PSS_DOOR /* 0x000400 */ (1 << 10) -#define SAVE_FLAG_UNLOCKED_WF_DOOR /* 0x000800 */ (1 << 11) -#define SAVE_FLAG_UNLOCKED_CCM_DOOR /* 0x001000 */ (1 << 12) -#define SAVE_FLAG_UNLOCKED_JRB_DOOR /* 0x002000 */ (1 << 13) -#define SAVE_FLAG_UNLOCKED_BITDW_DOOR /* 0x004000 */ (1 << 14) -#define SAVE_FLAG_UNLOCKED_BITFS_DOOR /* 0x008000 */ (1 << 15) -#define SAVE_FLAG_CAP_ON_GROUND /* 0x010000 */ (1 << 16) -#define SAVE_FLAG_CAP_ON_KLEPTO /* 0x020000 */ (1 << 17) -#define SAVE_FLAG_CAP_ON_UKIKI /* 0x040000 */ (1 << 18) -#define SAVE_FLAG_CAP_ON_MR_BLIZZARD /* 0x080000 */ (1 << 19) -#define SAVE_FLAG_UNLOCKED_50_STAR_DOOR /* 0x100000 */ (1 << 20) +#define SAVE_FLAG_FILE_EXISTS /* 0x00000001 */ (1 << 0) +#define SAVE_FLAG_HAVE_WING_CAP /* 0x00000002 */ (1 << 1) +#define SAVE_FLAG_HAVE_METAL_CAP /* 0x00000004 */ (1 << 2) +#define SAVE_FLAG_HAVE_VANISH_CAP /* 0x00000008 */ (1 << 3) +#define SAVE_FLAG_HAVE_KEY_1 /* 0x00000010 */ (1 << 4) +#define SAVE_FLAG_HAVE_KEY_2 /* 0x00000020 */ (1 << 5) +#define SAVE_FLAG_UNLOCKED_BASEMENT_DOOR /* 0x00000040 */ (1 << 6) +#define SAVE_FLAG_UNLOCKED_UPSTAIRS_DOOR /* 0x00000080 */ (1 << 7) +#define SAVE_FLAG_DDD_MOVED_BACK /* 0x00000100 */ (1 << 8) +#define SAVE_FLAG_MOAT_DRAINED /* 0x00000200 */ (1 << 9) +#define SAVE_FLAG_UNLOCKED_PSS_DOOR /* 0x00000400 */ (1 << 10) +#define SAVE_FLAG_UNLOCKED_WF_DOOR /* 0x00000800 */ (1 << 11) +#define SAVE_FLAG_UNLOCKED_CCM_DOOR /* 0x00001000 */ (1 << 12) +#define SAVE_FLAG_UNLOCKED_JRB_DOOR /* 0x00002000 */ (1 << 13) +#define SAVE_FLAG_UNLOCKED_BITDW_DOOR /* 0x00004000 */ (1 << 14) +#define SAVE_FLAG_UNLOCKED_BITFS_DOOR /* 0x00008000 */ (1 << 15) +#define SAVE_FLAG_CAP_ON_GROUND /* 0x00010000 */ (1 << 16) +#define SAVE_FLAG_CAP_ON_KLEPTO /* 0x00020000 */ (1 << 17) +#define SAVE_FLAG_CAP_ON_UKIKI /* 0x00040000 */ (1 << 18) +#define SAVE_FLAG_CAP_ON_MR_BLIZZARD /* 0x00080000 */ (1 << 19) +#define SAVE_FLAG_UNLOCKED_50_STAR_DOOR /* 0x00100000 */ (1 << 20) +#define SAVE_FLAG_COLLECTED_TOAD_STAR_1 /* 0x01000000 */ (1 << 24) +#define SAVE_FLAG_COLLECTED_TOAD_STAR_2 /* 0x02000000 */ (1 << 25) +#define SAVE_FLAG_COLLECTED_TOAD_STAR_3 /* 0x04000000 */ (1 << 26) +#define SAVE_FLAG_COLLECTED_MIPS_STAR_1 /* 0x08000000 */ (1 << 27) +#define SAVE_FLAG_COLLECTED_MIPS_STAR_2 /* 0x10000000 */ (1 << 28) + +#define SAVE_FLAG_TO_STAR_FLAG(cmd) (((cmd) >> 24) & 0x7F) +#define STAR_FLAG_TO_SAVE_FLAG(cmd) ((cmd) << 24) // Variable for setting a warp checkpoint. diff --git a/src/game/screen_transition.c b/src/game/screen_transition.c index fd338037..ab36bbc6 100644 --- a/src/game/screen_transition.c +++ b/src/game/screen_transition.c @@ -291,7 +291,7 @@ s32 render_textured_transition(s8 fadeTimer, s8 transTime, struct WarpTransition #endif -int render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct WarpTransitionData *transData) { +s32 render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct WarpTransitionData *transData) { switch (transType) { case WARP_TRANSITION_FADE_FROM_COLOR: return render_fade_transition_from_color(fadeTimer, transTime, transData); diff --git a/src/game/screen_transition.h b/src/game/screen_transition.h index e3e9adde..2ebb447b 100644 --- a/src/game/screen_transition.h +++ b/src/game/screen_transition.h @@ -22,7 +22,7 @@ enum TextureTransitionType }; void reset_screen_transition_timers(void); -int render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct WarpTransitionData *transData); +s32 render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct WarpTransitionData *transData); Gfx *geo_cannon_circle_base(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx); #endif // SCREEN_TRANSITION_H diff --git a/src/game/shadow.c b/src/game/shadow.c index c6315c63..c5ca7545 100644 --- a/src/game/shadow.c +++ b/src/game/shadow.c @@ -430,7 +430,7 @@ void make_shadow_vertex(Vtx *vertices, s8 index, struct Shadow s, s8 shadowVerte f32 relX, relY, relZ; u8 solidity = s.solidity; - if (gShadowAboveWaterOrLava != 0) { + if (gShadowAboveWaterOrLava) { solidity = 200; } @@ -532,8 +532,8 @@ s8 correct_shadow_solidity_for_animations(s32 playerIndex, u8 initialSolidity, s extern struct MarioState gMarioStates[]; player = gMarioStates[playerIndex].marioObj; - animFrame = player->header.gfx.unk38.animFrame; - switch (player->header.gfx.unk38.animID) { + animFrame = player->header.gfx.animInfo.animFrame; + switch (player->header.gfx.animInfo.animID) { case MARIO_ANIM_IDLE_ON_LEDGE: ret = SHADOW_SOLIDITY_NO_SHADOW; break; diff --git a/src/game/skybox.c b/src/game/skybox.c index 233a1aa7..7dd2e00d 100644 --- a/src/game/skybox.c +++ b/src/game/skybox.c @@ -135,7 +135,7 @@ u8 sSkyboxColors[][3] = { * (how far is the camera rotated from 0, scaled 0 to 1) * * (the screen width) */ -f32 calculate_skybox_scaled_x(s8 player, f32 fov) { +s32 calculate_skybox_scaled_x(s8 player, f32 fov) { f32 yaw = sSkyBoxInfo[player].yaw; //! double literals are used instead of floats @@ -153,7 +153,7 @@ f32 calculate_skybox_scaled_x(s8 player, f32 fov) { * fov may have been used in an earlier version, but the developers changed the function to always use * 90 degrees. */ -f32 calculate_skybox_scaled_y(s8 player, UNUSED f32 fov) { +s32 calculate_skybox_scaled_y(s8 player, UNUSED f32 fov) { // Convert pitch to degrees. Pitch is bounded between -90 (looking down) and 90 (looking up). f32 pitchInDegrees = (f32) sSkyBoxInfo[player].pitch * 360.0 / 65535.0; @@ -176,7 +176,7 @@ f32 calculate_skybox_scaled_y(s8 player, UNUSED f32 fov) { /** * Converts the upper left xPos and yPos to the index of the upper left tile in the skybox. */ -static int get_top_left_tile_idx(s8 player) { +static s32 get_top_left_tile_idx(s8 player) { s32 tileCol = sSkyBoxInfo[player].scaledX / SKYBOX_TILE_WIDTH; s32 tileRow = (SKYBOX_HEIGHT - sSkyBoxInfo[player].scaledY) / SKYBOX_TILE_HEIGHT; diff --git a/src/game/sound_init.c b/src/game/sound_init.c index e8627562..70ddf3da 100644 --- a/src/game/sound_init.c +++ b/src/game/sound_init.c @@ -32,7 +32,7 @@ static u8 sPlayingInfiniteStairs = FALSE; static u8 unused8032C6D8[16] = { 0 }; static s16 sSoundMenuModeToSoundMode[] = { SOUND_MODE_STEREO, SOUND_MODE_MONO, SOUND_MODE_HEADSET }; // Only the 20th array element is used. -static u32 menuSoundsExtra[] = { +static u32 sMenuSoundsExtra[] = { SOUND_MOVING_TERRAIN_SLIDE + (0 << 16), SOUND_MOVING_TERRAIN_SLIDE + (1 << 16), SOUND_MOVING_TERRAIN_SLIDE + (2 << 16), @@ -70,9 +70,9 @@ static u32 menuSoundsExtra[] = { SOUND_AIR_BLOW_FIRE, SOUND_ENV_ELEVATOR4, }; -static s8 paintingEjectSoundPlayed = FALSE; +static s8 sPaintingEjectSoundPlayed = FALSE; -void play_menu_sounds_extra(int a, void *b); +void play_menu_sounds_extra(s32 a, void *b); void reset_volume(void) { D_8032C6C0 = 0; @@ -165,13 +165,13 @@ void play_menu_sounds(s16 soundMenuFlags) { void play_painting_eject_sound(void) { if (gRipplingPainting != NULL && gRipplingPainting->state == PAINTING_ENTERED) { // ripple when Mario enters painting - if (paintingEjectSoundPlayed == FALSE) { + if (!sPaintingEjectSoundPlayed) { play_sound(SOUND_GENERAL_PAINTING_EJECT, gMarioStates[0].marioObj->header.gfx.cameraToObject); } - paintingEjectSoundPlayed = TRUE; + sPaintingEjectSoundPlayed = TRUE; } else { - paintingEjectSoundPlayed = FALSE; + sPaintingEjectSoundPlayed = FALSE; } } @@ -199,13 +199,13 @@ void play_infinite_stairs_music(void) { void set_background_music(u16 a, u16 seqArgs, s16 fadeTimer) { if (gResetTimer == 0 && seqArgs != sCurrentMusic) { - if (gCurrCreditsEntry != 0) { + if (gCurrCreditsEntry != NULL) { sound_reset(7); } else { sound_reset(a); } - if (!(gShouldNotPlayCastleMusic && seqArgs == SEQ_LEVEL_INSIDE_CASTLE)) { + if (!gNeverEnteredCastle || seqArgs != SEQ_LEVEL_INSIDE_CASTLE) { play_music(SEQ_PLAYER_LEVEL, seqArgs, fadeTimer); sCurrentMusic = seqArgs; } @@ -265,7 +265,7 @@ void stop_cap_music(void) { } void play_menu_sounds_extra(s32 a, void *b) { - play_sound(menuSoundsExtra[a], b); + play_sound(sMenuSoundsExtra[a], b); } void audio_game_loop_tick(void) { diff --git a/src/game/spawn_sound.c b/src/game/spawn_sound.c index 6bf6c457..924da19a 100644 --- a/src/game/spawn_sound.c +++ b/src/game/spawn_sound.c @@ -92,7 +92,7 @@ void cur_obj_play_sound_2(s32 soundMagic) { * Technically, these functions are only educated guesses. Trust these * interpretations at your own discretion. */ -int calc_dist_to_volume_range_1(f32 distance) // range from 60-124 +s32 calc_dist_to_volume_range_1(f32 distance) // range from 60-124 { s32 volume; @@ -107,7 +107,7 @@ int calc_dist_to_volume_range_1(f32 distance) // range from 60-124 return volume; } -int calc_dist_to_volume_range_2(f32 distance) // range from 79.2-143.2 +s32 calc_dist_to_volume_range_2(f32 distance) // range from 79.2-143.2 { s32 volume; diff --git a/src/goddard/dynlists/anim_group_1.c b/src/goddard/dynlists/anim_group_1.c index a3906796..ce05c210 100644 --- a/src/goddard/dynlists/anim_group_1.c +++ b/src/goddard/dynlists/anim_group_1.c @@ -1417,7 +1417,7 @@ struct AnimDataInfo anim_mario_eye_right[3] = { }; /* @ 0401BB14 */ -s16 animdata_mario_hat_1[820][3] = { +s16 animdata_mario_cap_1[820][3] = { { 0, 0, 1539 }, { 0, 0, 1539 }, { 0, 0, 1539 }, { 0, 0, 1538 }, { 0, 0, 1538 }, { 0, 0, 1537 }, { 0, 0, 1537 }, { 0, 0, 1536 }, { 0, 0, 1536 }, { 0, 0, 1535 }, { 0, 0, 1535 }, { 0, 0, 1534 }, { 0, 0, 1534 }, { 0, 0, 1534 }, { 0, 0, 1534 }, @@ -1585,7 +1585,7 @@ s16 animdata_mario_hat_1[820][3] = { }; /* @ 0401CE4C */ -s16 animdata_mario_hat_2[166][3] = { +s16 animdata_mario_cap_2[166][3] = { { 0, 0, 1539 }, { 0, 0, 1539 }, { 0, 0, 1539 }, { 0, 0, 1538 }, { 0, 0, 1538 }, { 0, 0, 1538 }, { 0, 0, 1537 }, { 0, 0, 1537 }, { 0, 0, 1536 }, { 0, 0, 1536 }, { 0, 0, 1535 }, { 0, 0, 1535 }, { 0, 0, 1535 }, { 0, 0, 1534 }, { 0, 0, 1534 }, { 0, 0, 1534 }, { 0, 0, 1534 }, { 0, 0, 1534 }, @@ -1617,9 +1617,9 @@ s16 animdata_mario_hat_2[166][3] = { }; /* @ 0401D230 */ -struct AnimDataInfo anim_mario_hat[3] = { - { 820, GD_ANIM_3H_SCALED, animdata_mario_hat_1 }, - { 166, GD_ANIM_3H_SCALED, animdata_mario_hat_2 }, +struct AnimDataInfo anim_mario_cap[3] = { + { 820, GD_ANIM_3H_SCALED, animdata_mario_cap_1 }, + { 166, GD_ANIM_3H_SCALED, animdata_mario_cap_2 }, END_ANIMDATA_INFO_ARR, }; diff --git a/src/goddard/dynlists/animdata.h b/src/goddard/dynlists/animdata.h index 5e0d01cf..192d9fad 100644 --- a/src/goddard/dynlists/animdata.h +++ b/src/goddard/dynlists/animdata.h @@ -16,7 +16,7 @@ extern struct AnimDataInfo anim_mario_eyebrows_4[3]; extern struct AnimDataInfo anim_mario_eyebrows_5[3]; extern struct AnimDataInfo anim_mario_eye_left[3]; extern struct AnimDataInfo anim_mario_eye_right[3]; -extern struct AnimDataInfo anim_mario_hat[3]; +extern struct AnimDataInfo anim_mario_cap[3]; extern struct AnimDataInfo anim_mario_lips_3[3]; extern struct AnimDataInfo anim_mario_lips_4[3]; extern struct AnimDataInfo anim_mario_ear_left[3]; diff --git a/src/goddard/dynlists/dynlist_mario_master.c b/src/goddard/dynlists/dynlist_mario_master.c index 716e07b4..9c321343 100644 --- a/src/goddard/dynlists/dynlist_mario_master.c +++ b/src/goddard/dynlists/dynlist_mario_master.c @@ -965,8 +965,8 @@ struct DynList dynlist_mario_master[1026] = { SetNodeGroup(0x7B), LinkWith(0x7A), - MakeDynObj(D_DATA_GRP, 0x84), // hat - LinkWithPtr(&anim_mario_hat), + MakeDynObj(D_DATA_GRP, 0x84), // cap + LinkWithPtr(&anim_mario_cap), MakeDynObj(D_ANIMATOR, 0x85), AttachTo(0x0, 0x3E9), SetNodeGroup(0x84), diff --git a/src/menu/file_select.c b/src/menu/file_select.c index 9bdb3185..4d7dd9fb 100644 --- a/src/menu/file_select.c +++ b/src/menu/file_select.c @@ -43,7 +43,7 @@ static s16 sSoundTextX; static s16 sSoundTextY; #endif -//! @Bug (UB Array Access) For PAL, more buttons were added than the array was extended. +//! @Bug (UB Array Access) For EU, more buttons were added than the array was extended. //! This causes no currently known issues on console (as the other variables are not changed //! while this is used) but can cause issues with other compilers. #ifdef VERSION_EU @@ -119,7 +119,7 @@ static s16 sMainMenuTimer = 0; // 0: gSoundMode = 0 (Stereo) | 1: gSoundMode = 3 (Mono) | 2: gSoundMode = 1 (Headset) static s8 sSoundMode = 0; -// Active language for PAL arrays, values defined similar to sSoundMode +// Active language for EU arrays, values defined similar to sSoundMode // 0: English | 1: French | 2: German #ifdef VERSION_EU static s8 sLanguageMode = LANGUAGE_ENGLISH; @@ -140,7 +140,7 @@ s8 sSelectedFileNum = 0; // coin high score, 1 for high score across all files. static s8 sScoreFileCoinScoreMode = 0; -// In PAL, if no save file exists, open the language menu so the user can find it. +// In EU, if no save file exists, open the language menu so the user can find it. #ifdef VERSION_EU static s8 sOpenLangSettings = FALSE; #endif @@ -1704,7 +1704,7 @@ void print_save_file_star_count(s8 fileIndex, s16 x, s16 y) { s16 starCount; if (save_file_exists(fileIndex) == TRUE) { - starCount = save_file_get_total_star_count(fileIndex, 0, 24); + starCount = save_file_get_total_star_count(fileIndex, COURSE_MIN - 1, COURSE_MAX - 1); // Print star icon print_hud_lut_string(HUD_LUT_GLOBAL, x, y, starIcon); // If star count is less than 100, print x icon and move @@ -2491,7 +2491,8 @@ void print_score_file_castle_secret_stars(s8 fileIndex, s16 x, s16 y) { // Print "[star] x" print_menu_generic_string(x, y, textStarX); // Print number of castle secret stars - int_to_str(save_file_get_total_star_count(fileIndex, 15, 24), secretStarsText); + int_to_str(save_file_get_total_star_count(fileIndex, COURSE_BONUS_STAGES - 1, COURSE_MAX - 1), + secretStarsText); #ifdef VERSION_EU print_menu_generic_string(x + 20, y, secretStarsText); #else diff --git a/src/menu/file_select.h b/src/menu/file_select.h index 62235995..a2850697 100644 --- a/src/menu/file_select.h +++ b/src/menu/file_select.h @@ -71,7 +71,7 @@ enum MenuButtonTypes { MENU_BUTTON_ERASE_MAX, // Sound Mode Menu (SOUND SELECT) - // This menu includes language settings on PAL + // This menu includes language settings on EU MENU_BUTTON_SOUND_MODE = MENU_BUTTON_ERASE_MAX, MENU_BUTTON_OPTION_MIN, MENU_BUTTON_STEREO = MENU_BUTTON_OPTION_MIN, diff --git a/src/menu/level_select_menu.c b/src/menu/level_select_menu.c index df8b1a6c..f83f220d 100644 --- a/src/menu/level_select_menu.c +++ b/src/menu/level_select_menu.c @@ -38,7 +38,7 @@ static s16 gameOverNotPlayed = 1; // don't shift this function from being the first function in the segment. // the level scripts assume this function is the first, so it cant be moved. -int run_press_start_demo_timer(s32 timer) { +s32 run_press_start_demo_timer(s32 timer) { gCurrDemoInput = NULL; if (timer == 0) { @@ -148,7 +148,7 @@ s16 level_select_input_loop(void) { // ... the level select quit combo is being pressed, which uses START. If this // is the case, quit the menu instead. if (gPlayer1Controller->buttonDown == QUIT_LEVEL_SELECT_COMBO) { - gDebugLevelSelect = 0; + gDebugLevelSelect = FALSE; return -1; } play_sound(SOUND_MENU_STAR_SOUND, gDefaultSoundArgs); @@ -157,8 +157,7 @@ s16 level_select_input_loop(void) { return 0; } - -int intro_default(void) { +s32 intro_default(void) { s32 sp1C = 0; #ifndef VERSION_JP @@ -179,7 +178,7 @@ int intro_default(void) { return run_press_start_demo_timer(sp1C); } -int intro_game_over(void) { +s32 intro_game_over(void) { s32 sp1C = 0; #ifndef VERSION_JP @@ -201,7 +200,7 @@ int intro_game_over(void) { return run_press_start_demo_timer(sp1C); } -int intro_play_its_a_me_mario(void) { +s32 intro_play_its_a_me_mario(void) { set_background_music(0, SEQ_SOUND_PLAYER, 0); play_sound(SOUND_MENU_COIN_ITS_A_ME_MARIO, gDefaultSoundArgs); return 1; diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index 8362c44c..0e14a0a4 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -11,14 +11,14 @@ #define LUA_ANIMATION_FIELD_COUNT 9 static struct LuaObjectField sAnimationFields[LUA_ANIMATION_FIELD_COUNT] = { - { "flags", LVT_S16, offsetof(struct Animation, flags), false, LOT_NONE }, - { "index", LVT_U16_P, offsetof(struct Animation, index), true, LOT_POINTER }, - { "length", LVT_U32, offsetof(struct Animation, length), false, LOT_NONE }, - { "animYTransDivisor", LVT_S16, offsetof(struct Animation, unk02), false, LOT_NONE }, - { "startFrame", LVT_S16, offsetof(struct Animation, unk04), false, LOT_NONE }, - { "loopStart", LVT_S16, offsetof(struct Animation, unk06), false, LOT_NONE }, - { "loopEnd", LVT_S16, offsetof(struct Animation, unk08), false, LOT_NONE }, - { "unusedBoneCount", LVT_S16, offsetof(struct Animation, unk0A), false, LOT_NONE }, + { "flags", LVT_S16, offsetof(struct Animation, flags), false, LOT_NONE }, + { "index", LVT_U16_P, offsetof(struct Animation, index), true, LOT_POINTER }, + { "length", LVT_U32, offsetof(struct Animation, length), false, LOT_NONE }, + { "animYTransDivisor", LVT_S16, offsetof(struct Animation, animYTransDivisor), false, LOT_NONE }, + { "startFrame", LVT_S16, offsetof(struct Animation, startFrame), false, LOT_NONE }, + { "loopStart", LVT_S16, offsetof(struct Animation, loopStart), false, LOT_NONE }, + { "loopEnd", LVT_S16, offsetof(struct Animation, loopEnd), false, LOT_NONE }, + { "unusedBoneCount", LVT_S16, offsetof(struct Animation, unusedBoneCount), false, LOT_NONE }, { "values", LVT_S16_P, offsetof(struct Animation, values), true, LOT_POINTER }, }; @@ -249,25 +249,25 @@ static struct LuaObjectField sGraphNodeObjectFields[LUA_GRAPH_NODE_OBJECT_FIELD_ { "skipInterpolationTimestamp", LVT_U32, offsetof(struct GraphNodeObject, skipInterpolationTimestamp), false, LOT_NONE }, // { "throwMatrix", LVT_???, offsetof(struct GraphNodeObject, throwMatrix), false, LOT_??? }, <--- UNIMPLEMENTED // { "throwMatrixInterpolated", LVT_???, offsetof(struct GraphNodeObject, throwMatrixInterpolated), false, LOT_??? }, <--- UNIMPLEMENTED - { "unk18", LVT_S8, offsetof(struct GraphNodeObject, unk18), false, LOT_NONE }, - { "unk19", LVT_S8, offsetof(struct GraphNodeObject, unk19), false, LOT_NONE }, - { "animInfo", LVT_COBJECT, offsetof(struct GraphNodeObject, unk38), true, LOT_GRAPHNODEOBJECT_SUB }, + { "animInfo", LVT_S8, offsetof(struct GraphNodeObject, animInfo), false, LOT_NONE }, + { "activeAreaIndex", LVT_S8, offsetof(struct GraphNodeObject, activeAreaIndex), false, LOT_NONE }, + { "animInfo", LVT_COBJECT, offsetof(struct GraphNodeObject, animInfo), true, LOT_GRAPHNODEOBJECT_SUB }, { "unk4C", LVT_COBJECT_P, offsetof(struct GraphNodeObject, unk4C), true, LOT_SPAWNINFO }, }; #define LUA_GRAPH_NODE_OBJECT_SUB_FIELD_COUNT 11 -static struct LuaObjectField sGraphNodeObject_subFields[LUA_GRAPH_NODE_OBJECT_SUB_FIELD_COUNT] = { - { "animAccel", LVT_S32, offsetof(struct GraphNodeObject_sub, animAccel), false, LOT_NONE }, - { "animFrame", LVT_S16, offsetof(struct GraphNodeObject_sub, animFrame), false, LOT_NONE }, - { "animFrameAccelAssist", LVT_S32, offsetof(struct GraphNodeObject_sub, animFrameAccelAssist), false, LOT_NONE }, - { "animID", LVT_S16, offsetof(struct GraphNodeObject_sub, animID), false, LOT_NONE }, - { "animTimer", LVT_U16, offsetof(struct GraphNodeObject_sub, animTimer), false, LOT_NONE }, - { "animYTrans", LVT_S16, offsetof(struct GraphNodeObject_sub, animYTrans), false, LOT_NONE }, - { "curAnim", LVT_COBJECT_P, offsetof(struct GraphNodeObject_sub, curAnim), true, LOT_ANIMATION }, - { "prevAnimFrame", LVT_S16, offsetof(struct GraphNodeObject_sub, prevAnimFrame), false, LOT_NONE }, - { "prevAnimFrameTimestamp", LVT_U32, offsetof(struct GraphNodeObject_sub, prevAnimFrameTimestamp), false, LOT_NONE }, - { "prevAnimID", LVT_S16, offsetof(struct GraphNodeObject_sub, prevAnimID), false, LOT_NONE }, - { "prevAnimPtr", LVT_COBJECT_P, offsetof(struct GraphNodeObject_sub, prevAnimPtr), true, LOT_ANIMATION }, +static struct LuaObjectField sAnimInfoFields[LUA_GRAPH_NODE_OBJECT_SUB_FIELD_COUNT] = { + { "animAccel", LVT_S32, offsetof(struct AnimInfo, animAccel), false, LOT_NONE }, + { "animFrame", LVT_S16, offsetof(struct AnimInfo, animFrame), false, LOT_NONE }, + { "animFrameAccelAssist", LVT_S32, offsetof(struct AnimInfo, animFrameAccelAssist), false, LOT_NONE }, + { "animID", LVT_S16, offsetof(struct AnimInfo, animID), false, LOT_NONE }, + { "animTimer", LVT_U16, offsetof(struct AnimInfo, animTimer), false, LOT_NONE }, + { "animYTrans", LVT_S16, offsetof(struct AnimInfo, animYTrans), false, LOT_NONE }, + { "curAnim", LVT_COBJECT_P, offsetof(struct AnimInfo, curAnim), true, LOT_ANIMATION }, + { "prevAnimFrame", LVT_S16, offsetof(struct AnimInfo, prevAnimFrame), false, LOT_NONE }, + { "prevAnimFrameTimestamp", LVT_U32, offsetof(struct AnimInfo, prevAnimFrameTimestamp), false, LOT_NONE }, + { "prevAnimID", LVT_S16, offsetof(struct AnimInfo, prevAnimID), false, LOT_NONE }, + { "prevAnimPtr", LVT_COBJECT_P, offsetof(struct AnimInfo, prevAnimPtr), true, LOT_ANIMATION }, }; #define LUA_HANDHELD_SHAKE_POINT_FIELD_COUNT 3 @@ -703,7 +703,7 @@ struct LuaObjectTable sLuaObjectAutogenTable[LOT_AUTOGEN_MAX - LOT_AUTOGEN_MIN] { LOT_GLOBALTEXTURES, sGlobalTexturesFields, LUA_GLOBAL_TEXTURES_FIELD_COUNT }, { LOT_GRAPHNODE, sGraphNodeFields, LUA_GRAPH_NODE_FIELD_COUNT }, { LOT_GRAPHNODEOBJECT, sGraphNodeObjectFields, LUA_GRAPH_NODE_OBJECT_FIELD_COUNT }, - { LOT_GRAPHNODEOBJECT_SUB, sGraphNodeObject_subFields, LUA_GRAPH_NODE_OBJECT_SUB_FIELD_COUNT }, + { LOT_GRAPHNODEOBJECT_SUB, sAnimInfoFields, LUA_GRAPH_NODE_OBJECT_SUB_FIELD_COUNT }, { LOT_HANDHELDSHAKEPOINT, sHandheldShakePointFields, LUA_HANDHELD_SHAKE_POINT_FIELD_COUNT }, { LOT_INSTANTWARP, sInstantWarpFields, LUA_INSTANT_WARP_FIELD_COUNT }, { LOT_LAKITUSTATE, sLakituStateFields, LUA_LAKITU_STATE_FIELD_COUNT }, diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 1707e54c..dd073485 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -563,13 +563,13 @@ int smlua_func_sequence_player_unlower(lua_State* L) { // interaction.h // /////////////////// -int smlua_func_does_mario_have_hat(lua_State* L) { +int smlua_func_does_mario_have_normal_cap_on_head(lua_State* L) { if(!smlua_functions_valid_param_count(L, 1)) { return 0; } struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIOSTATE); if (!gSmLuaConvertSuccess) { return 0; } - lua_pushinteger(L, does_mario_have_hat(m)); + lua_pushinteger(L, does_mario_have_normal_cap_on_head(m)); return 1; } @@ -3616,7 +3616,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "sequence_player_unlower", smlua_func_sequence_player_unlower); // interaction.h - smlua_bind_function(L, "does_mario_have_hat", smlua_func_does_mario_have_hat); + smlua_bind_function(L, "does_mario_have_normal_cap_on_head", smlua_func_does_mario_have_normal_cap_on_head); smlua_bind_function(L, "get_door_save_file_flag", smlua_func_get_door_save_file_flag); smlua_bind_function(L, "mario_blow_off_cap", smlua_func_mario_blow_off_cap); smlua_bind_function(L, "mario_check_object_grab", smlua_func_mario_check_object_grab); diff --git a/tools/asm_processor/asm-processor.py b/tools/asm_processor/asm-processor.py index b7ddbdf2..04b94316 100644 --- a/tools/asm_processor/asm-processor.py +++ b/tools/asm_processor/asm-processor.py @@ -6,8 +6,11 @@ import copy import sys import re import os +from collections import namedtuple +from io import StringIO MAX_FN_SIZE = 100 +SLOW_CHECKS = False EI_NIDENT = 16 EI_CLASS = 4 @@ -197,12 +200,12 @@ class Section: assert self.sh_type == SHT_STRTAB to = self.data.find(b'\0', index) assert to != -1 - return self.data[index:to].decode('utf-8') + return self.data[index:to].decode('latin1') def add_str(self, string): assert self.sh_type == SHT_STRTAB ret = len(self.data) - self.data += bytes(string, 'utf-8') + b'\0' + self.data += string.encode('latin1') + b'\0' return ret def is_rel(self): @@ -228,6 +231,12 @@ class Section: return (s.st_shndx, s.st_value) return None + def find_symbol_in_section(self, name, section): + pos = self.find_symbol(name) + assert pos is not None + assert pos[0] == section.index + return pos[1] + def init_symbols(self, sections): assert self.sh_type == SHT_SYMTAB assert self.sh_entsize == 16 @@ -339,25 +348,63 @@ class ElfFile: def is_temp_name(name): return name.startswith('_asmpp_') + +# https://stackoverflow.com/a/241506 +def re_comment_replacer(match): + s = match.group(0) + if s[0] in "/#": + return " " + else: + return s + + +re_comment_or_string = re.compile( + r'#.*|/\*.*?\*/|"(?:\\.|[^\\"])*"' +) + + +class Failure(Exception): + def __init__(self, message): + self.message = message + + def __str__(self): + return self.message + + class GlobalState: - def __init__(self, min_instr_count, skip_instr_count): + def __init__(self, min_instr_count, skip_instr_count, use_jtbl_for_rodata): # A value that hopefully never appears as a 32-bit rodata constant (or we # miscompile late rodata). Increases by 1 in each step. self.late_rodata_hex = 0xE0123456 self.namectr = 0 self.min_instr_count = min_instr_count self.skip_instr_count = skip_instr_count + self.use_jtbl_for_rodata = use_jtbl_for_rodata + + def next_late_rodata_hex(self): + dummy_bytes = struct.pack('>I', self.late_rodata_hex) + if (self.late_rodata_hex & 0xffff) == 0: + # Avoid lui + self.late_rodata_hex += 1 + self.late_rodata_hex += 1 + return dummy_bytes def make_name(self, cat): self.namectr += 1 return '_asmpp_{}{}'.format(cat, self.namectr) + +Function = namedtuple('Function', ['text_glabels', 'asm_conts', 'late_rodata_dummy_bytes', 'jtbl_rodata_size', 'late_rodata_asm_conts', 'fn_desc', 'data']) + + class GlobalAsmBlock: - def __init__(self): + def __init__(self, fn_desc): + self.fn_desc = fn_desc self.cur_section = '.text' self.asm_conts = [] self.late_rodata_asm_conts = [] self.late_rodata_alignment = 0 + self.late_rodata_alignment_from_content = False self.text_glabels = [] self.fn_section_sizes = { '.text': 0, @@ -367,22 +414,89 @@ class GlobalAsmBlock: '.late_rodata': 0, } self.fn_ins_inds = [] + self.glued_line = '' self.num_lines = 0 + def fail(self, message, line=None): + context = self.fn_desc + if line: + context += ", at line \"" + line + "\"" + raise Failure(message + "\nwithin " + context) + + def count_quoted_size(self, line, z, real_line, output_enc): + line = line.encode(output_enc).decode('latin1') + in_quote = False + num_parts = 0 + ret = 0 + i = 0 + digits = "0123456789" # 0-7 would be more sane, but this matches GNU as + while i < len(line): + c = line[i] + i += 1 + if not in_quote: + if c == '"': + in_quote = True + num_parts += 1 + else: + if c == '"': + in_quote = False + continue + ret += 1 + if c != '\\': + continue + if i == len(line): + self.fail("backslash at end of line not supported", real_line) + c = line[i] + i += 1 + # (if c is in "bfnrtv", we have a real escaped literal) + if c == 'x': + # hex literal, consume any number of hex chars, possibly none + while i < len(line) and line[i] in digits + "abcdefABCDEF": + i += 1 + elif c in digits: + # octal literal, consume up to two more digits + it = 0 + while i < len(line) and line[i] in digits and it < 2: + i += 1 + it += 1 + + if in_quote: + self.fail("unterminated string literal", real_line) + if num_parts == 0: + self.fail(".ascii with no string", real_line) + return ret + num_parts if z else ret + + + def align4(self): + while self.fn_section_sizes[self.cur_section] % 4 != 0: + self.fn_section_sizes[self.cur_section] += 1 + def add_sized(self, size, line): if self.cur_section in ['.text', '.late_rodata']: - assert size % 4 == 0, "size must be a multiple of 4 on line: " + line - assert size >= 0 + if size % 4 != 0: + self.fail("size must be a multiple of 4", line) + if size < 0: + self.fail("size cannot be negative", line) self.fn_section_sizes[self.cur_section] += size if self.cur_section == '.text': - assert self.text_glabels, ".text block without an initial glabel" - self.fn_ins_inds.append((self.num_lines, size // 4)) + if not self.text_glabels: + self.fail(".text block without an initial glabel", line) + self.fn_ins_inds.append((self.num_lines - 1, size // 4)) - def process_line(self, line): - line = re.sub(r'/\*.*?\*/', '', line) - line = re.sub(r'#.*', '', line) + def process_line(self, line, output_enc): + self.num_lines += 1 + if line.endswith('\\'): + self.glued_line += line[:-1] + return + line = self.glued_line + line + self.glued_line = '' + + real_line = line + line = re.sub(re_comment_or_string, re_comment_replacer, line) line = line.strip() + line = re.sub(r'^[a-zA-Z0-9_]+:\s*', '', line) changed_section = False + emitting_double = False if line.startswith('glabel ') and self.cur_section == '.text': self.text_glabels.append(line.split()[1]) if not line: @@ -392,25 +506,56 @@ class GlobalAsmBlock: elif line.startswith('.section') or line in ['.text', '.data', '.rdata', '.rodata', '.bss', '.late_rodata']: # section change self.cur_section = '.rodata' if line == '.rdata' else line.split(',')[0].split()[-1] - assert self.cur_section in ['.data', '.text', '.rodata', '.late_rodata', '.bss'], \ - "unrecognized .section directive" + if self.cur_section not in ['.data', '.text', '.rodata', '.late_rodata', '.bss']: + self.fail("unrecognized .section directive", real_line) changed_section = True elif line.startswith('.late_rodata_alignment'): - assert self.cur_section == '.late_rodata' - self.late_rodata_alignment = int(line.split()[1]) - assert self.late_rodata_alignment in [4, 8] + if self.cur_section != '.late_rodata': + self.fail(".late_rodata_alignment must occur within .late_rodata section", real_line) + value = int(line.split()[1]) + if value not in [4, 8]: + self.fail(".late_rodata_alignment argument must be 4 or 8", real_line) + if self.late_rodata_alignment and self.late_rodata_alignment != value: + self.fail(".late_rodata_alignment alignment assumption conflicts with earlier .double directive. Make sure to provide explicit alignment padding.") + self.late_rodata_alignment = value changed_section = True elif line.startswith('.incbin'): - self.add_sized(int(line.split(',')[-1].strip(), 0), line) + self.add_sized(int(line.split(',')[-1].strip(), 0), real_line) elif line.startswith('.word') or line.startswith('.float'): - self.add_sized(4 * len(line.split(',')), line) + self.align4() + self.add_sized(4 * len(line.split(',')), real_line) elif line.startswith('.double'): - self.add_sized(8 * len(line.split(',')), line) + self.align4() + if self.cur_section == '.late_rodata': + align8 = self.fn_section_sizes[self.cur_section] % 8 + # Automatically set late_rodata_alignment, so the generated C code uses doubles. + # This gives us correct alignment for the transferred doubles even when the + # late_rodata_alignment is wrong, e.g. for non-matching compilation. + if not self.late_rodata_alignment: + self.late_rodata_alignment = 8 - align8 + self.late_rodata_alignment_from_content = True + elif self.late_rodata_alignment != 8 - align8: + if self.late_rodata_alignment_from_content: + self.fail("found two .double directives with different start addresses mod 8. Make sure to provide explicit alignment padding.", real_line) + else: + self.fail(".double at address that is not 0 mod 8 (based on .late_rodata_alignment assumption). Make sure to provide explicit alignment padding.", real_line) + self.add_sized(8 * len(line.split(',')), real_line) + emitting_double = True elif line.startswith('.space'): - self.add_sized(int(line.split()[1], 0), line) + self.add_sized(int(line.split()[1], 0), real_line) + elif line.startswith('.balign') or line.startswith('.align'): + align = int(line.split()[1]) + if align != 4: + self.fail("only .balign 4 is supported", real_line) + self.align4() + elif line.startswith('.asci'): + z = (line.startswith('.asciz') or line.startswith('.asciiz')) + self.add_sized(self.count_quoted_size(line, z, real_line, output_enc), real_line) + elif line.startswith('.byte'): + self.add_sized(len(line.split(',')), real_line) elif line.startswith('.'): - # .macro, .ascii, .asciiz, .balign, .align, ... - assert False, 'not supported yet: ' + line + # .macro, ... + self.fail("asm directive not supported", real_line) else: # Unfortunately, macros are hard to support for .rodata -- # we don't know how how space they will expand to before @@ -420,20 +565,27 @@ class GlobalAsmBlock: # cases), or change how this program is invoked. # Similarly, we can't currently deal with pseudo-instructions # that expand to several real instructions. - assert self.cur_section == '.text', "instruction or macro call in non-.text section? not supported: " + line - self.add_sized(4, line) + if self.cur_section != '.text': + self.fail("instruction or macro call in non-.text section? not supported", real_line) + self.add_sized(4, real_line) if self.cur_section == '.late_rodata': if not changed_section: - self.late_rodata_asm_conts.append(line) + if emitting_double: + self.late_rodata_asm_conts.append(".align 0") + self.late_rodata_asm_conts.append(real_line) + if emitting_double: + self.late_rodata_asm_conts.append(".align 2") else: - self.asm_conts.append(line) - self.num_lines += 1 + self.asm_conts.append(real_line) def finish(self, state): src = [''] * (self.num_lines + 1) - late_rodata = [] + late_rodata_dummy_bytes = [] + jtbl_rodata_size = 0 late_rodata_fn_output = [] + num_instr = self.fn_section_sizes['.text'] // 4 + if self.fn_section_sizes['.late_rodata'] > 0: # Generate late rodata by emitting unique float constants. # This requires 3 instructions for each 4 bytes of rodata. @@ -441,21 +593,38 @@ class GlobalAsmBlock: # instructions for 8 bytes of rodata. size = self.fn_section_sizes['.late_rodata'] // 4 skip_next = False + needs_double = (self.late_rodata_alignment != 0) for i in range(size): if skip_next: skip_next = False continue - if (state.late_rodata_hex & 0xffff) == 0: - # Avoid lui - state.late_rodata_hex += 1 - dummy_bytes = struct.pack('>I', state.late_rodata_hex) - state.late_rodata_hex += 1 - late_rodata.append(dummy_bytes) + # Jump tables give 9 instructions for >= 5 words of rodata, and should be + # emitted when: + # - -O2 or -O2 -g3 are used, which give the right codegen + # - we have emitted our first .float/.double (to ensure that we find the + # created rodata in the binary) + # - we have emitted our first .double, if any (to ensure alignment of doubles + # in shifted rodata sections) + # - we have at least 5 words of rodata left to emit (otherwise IDO does not + # generate a jump table) + # - we have at least 10 more instructions to go in this function (otherwise our + # function size computation will be wrong since the delay slot goes unused) + if (not needs_double and state.use_jtbl_for_rodata and i >= 1 and + size - i >= 5 and num_instr - len(late_rodata_fn_output) >= 10): + cases = " ".join("case {}:".format(case) for case in range(size - i)) + late_rodata_fn_output.append("switch (*(volatile int*)0) { " + cases + " ; }") + late_rodata_fn_output.extend([""] * 8) + jtbl_rodata_size = (size - i) * 4 + break + dummy_bytes = state.next_late_rodata_hex() + late_rodata_dummy_bytes.append(dummy_bytes) if self.late_rodata_alignment == 4 * ((i + 1) % 2 + 1) and i + 1 < size: - late_rodata.append(dummy_bytes) - fval, = struct.unpack('>d', dummy_bytes * 2) + dummy_bytes2 = state.next_late_rodata_hex() + late_rodata_dummy_bytes.append(dummy_bytes2) + fval, = struct.unpack('>d', dummy_bytes + dummy_bytes2) late_rodata_fn_output.append('*(volatile double*)0 = {};'.format(fval)) skip_next = True + needs_double = True else: fval, = struct.unpack('>f', dummy_bytes) late_rodata_fn_output.append('*(volatile float*)0 = {}f;'.format(fval)) @@ -468,7 +637,8 @@ class GlobalAsmBlock: src[0] = 'void {}(void) {{'.format(text_name) src[self.num_lines] = '}' instr_count = self.fn_section_sizes['.text'] // 4 - assert instr_count >= state.min_instr_count, "too short .text block" + if instr_count < state.min_instr_count: + self.fail("too short .text block") tot_emitted = 0 tot_skipped = 0 fn_emitted = 0 @@ -496,38 +666,50 @@ class GlobalAsmBlock: if rodata_stack: size = len(late_rodata_fn_output) // 3 available = instr_count - tot_skipped - print("late rodata to text ratio is too high: {} / {} must be <= 1/3" - .format(size, available), file=sys.stderr) - print("add a .late_rodata_alignment (4|8) to the .late_rodata " - "block to double the allowed ratio.", file=sys.stderr) - exit(1) + self.fail( + "late rodata to text ratio is too high: {} / {} must be <= 1/3\n" + "add .late_rodata_alignment (4|8) to the .late_rodata " + "block to double the allowed ratio." + .format(size, available)) rodata_name = None if self.fn_section_sizes['.rodata'] > 0: rodata_name = state.make_name('rodata') - output_line += ' const char {}[{}] = {{1}};'.format(rodata_name, self.fn_section_sizes['.rodata']) + src[self.num_lines] += ' const char {}[{}] = {{1}};'.format(rodata_name, self.fn_section_sizes['.rodata']) data_name = None if self.fn_section_sizes['.data'] > 0: data_name = state.make_name('data') - output_line += ' char {}[{}] = {{1}};'.format(data_name, self.fn_section_sizes['.data']) + src[self.num_lines] += ' char {}[{}] = {{1}};'.format(data_name, self.fn_section_sizes['.data']) bss_name = None if self.fn_section_sizes['.bss'] > 0: bss_name = state.make_name('bss') - output_line += ' char {}[{}];'.format(bss_name, self.fn_section_sizes['.bss']) + src[self.num_lines] += ' char {}[{}];'.format(bss_name, self.fn_section_sizes['.bss']) - fn = (self.text_glabels, self.asm_conts, late_rodata, self.late_rodata_asm_conts, - { - '.text': (text_name, self.fn_section_sizes['.text']), - '.data': (data_name, self.fn_section_sizes['.data']), - '.rodata': (rodata_name, self.fn_section_sizes['.rodata']), - '.bss': (bss_name, self.fn_section_sizes['.bss']), - }) + fn = Function( + text_glabels=self.text_glabels, + asm_conts=self.asm_conts, + late_rodata_dummy_bytes=late_rodata_dummy_bytes, + jtbl_rodata_size=jtbl_rodata_size, + late_rodata_asm_conts=self.late_rodata_asm_conts, + fn_desc=self.fn_desc, + data={ + '.text': (text_name, self.fn_section_sizes['.text']), + '.data': (data_name, self.fn_section_sizes['.data']), + '.rodata': (rodata_name, self.fn_section_sizes['.rodata']), + '.bss': (bss_name, self.fn_section_sizes['.bss']), + }) return src, fn -def parse_source(f, print_source, opt, framepointer): - if opt == 'O2': +cutscene_data_regexpr = re.compile(r"CutsceneData (.|\n)*\[\] = {") +float_regexpr = re.compile(r"[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?f") + +def repl_float_hex(m): + return str(struct.unpack(">I", struct.pack(">f", float(m.group(0).strip().rstrip("f"))))[0]) + +def parse_source(f, opt, framepointer, input_enc, output_enc, print_source=None): + if opt in ['O2', 'O1']: if framepointer: min_instr_count = 6 skip_instr_count = 5 @@ -542,7 +724,8 @@ def parse_source(f, print_source, opt, framepointer): min_instr_count = 4 skip_instr_count = 4 else: - assert opt == 'g3' + if opt != 'g3': + raise Failure("must pass one of -g, -O1, -O2, -O2 -g3") if framepointer: min_instr_count = 4 skip_instr_count = 4 @@ -550,13 +733,19 @@ def parse_source(f, print_source, opt, framepointer): min_instr_count = 2 skip_instr_count = 2 - state = GlobalState(min_instr_count, skip_instr_count) + use_jtbl_for_rodata = False + if opt in ['O2', 'g3'] and not framepointer: + use_jtbl_for_rodata = True + + state = GlobalState(min_instr_count, skip_instr_count, use_jtbl_for_rodata) global_asm = None asm_functions = [] output_lines = [] - for raw_line in f: + is_cutscene_data = False + + for line_no, raw_line in enumerate(f, 1): raw_line = raw_line.rstrip() line = raw_line.lstrip() @@ -573,31 +762,58 @@ def parse_source(f, print_source, opt, framepointer): asm_functions.append(fn) global_asm = None else: - global_asm.process_line(line) + global_asm.process_line(raw_line, output_enc) else: - if line == 'GLOBAL_ASM(': - global_asm = GlobalAsmBlock() + if line in ['GLOBAL_ASM(', '#pragma GLOBAL_ASM(']: + global_asm = GlobalAsmBlock("GLOBAL_ASM block at line " + str(line_no)) start_index = len(output_lines) - elif line.startswith('GLOBAL_ASM("') and line.endswith('")'): - global_asm = GlobalAsmBlock() - fname = line[len('GLOBAL_ASM') + 2 : -2] - with open(fname) as f: + elif ((line.startswith('GLOBAL_ASM("') or line.startswith('#pragma GLOBAL_ASM("')) + and line.endswith('")')): + fname = line[line.index('(') + 2 : -2] + global_asm = GlobalAsmBlock(fname) + with open(fname, encoding=input_enc) as f: for line2 in f: - global_asm.process_line(line2) + global_asm.process_line(line2.rstrip(), output_enc) src, fn = global_asm.finish(state) output_lines[-1] = ''.join(src) asm_functions.append(fn) global_asm = None + elif ((line.startswith('#include "')) and line.endswith('" EARLY')): + # C includes qualified with EARLY (i.e. #include "file.c" EARLY) will be + # processed recursively when encountered + fpath = os.path.dirname(f.name) + fname = line[line.index(' ') + 2 : -7] + include_src = StringIO() + with open(fpath + os.path.sep + fname, encoding=input_enc) as include_file: + parse_source(include_file, opt, framepointer, input_enc, output_enc, include_src) + output_lines[-1] = include_src.getvalue() + include_src.write('#line ' + str(line_no) + '\n') + include_src.close() else: + # This is a hack to replace all floating-point numbers in an array of a particular type + # (in this case CutsceneData) with their corresponding IEEE-754 hexadecimal representation + if cutscene_data_regexpr.search(line) is not None: + is_cutscene_data = True + elif line.endswith("};"): + is_cutscene_data = False + if is_cutscene_data: + raw_line = re.sub(float_regexpr, repl_float_hex, raw_line) output_lines[-1] = raw_line if print_source: - for line in output_lines: - print(line) + if isinstance(print_source, StringIO): + for line in output_lines: + print_source.write(line + '\n') + else: + for line in output_lines: + print_source.write(line.encode(output_enc) + b'\n') + print_source.flush() + if print_source != sys.stdout.buffer: + print_source.close() return asm_functions -def fixup_objfile(objfile_name, functions, asm_prelude, assembler): +def fixup_objfile(objfile_name, functions, asm_prelude, assembler, output_enc): SECTIONS = ['.data', '.text', '.rodata', '.bss'] with open(objfile_name, 'rb') as f: @@ -613,19 +829,22 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler): '.text': [], '.data': [], '.rodata': [], + '.bss': [], } asm = [] - late_rodata = [] + all_late_rodata_dummy_bytes = [] + all_jtbl_rodata_size = [] late_rodata_asm = [] - late_rodata_source_name = None + late_rodata_source_name_start = None + late_rodata_source_name_end = None # Generate an assembly file with all the assembly we need to fill in. For # simplicity we pad with nops/.space so that addresses match exactly, so we # don't have to fix up relocations/symbol references. all_text_glabels = set() - for (text_glabels, body, fn_late_rodata, fn_late_rodata_body, data) in functions: + for function in functions: ifdefed = False - for sectype, (temp_name, size) in data.items(): + for sectype, (temp_name, size) in function.data.items(): if temp_name is None: continue assert size > 0 @@ -635,7 +854,8 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler): break loc = loc[1] prev_loc = prev_locs[sectype] - assert loc >= prev_loc, sectype + if loc < prev_loc: + raise Failure("Wrongly computed size for section {} (diff {}). This is an asm-processor bug!".format(sectype, prev_loc- loc)) if loc != prev_loc: asm.append('.section ' + sectype) if sectype == '.text': @@ -643,21 +863,32 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler): asm.append('nop') else: asm.append('.space {}'.format(loc - prev_loc)) - if sectype != '.bss': - to_copy[sectype].append((loc, size)) + to_copy[sectype].append((loc, size, temp_name, function.fn_desc)) prev_locs[sectype] = loc + size if not ifdefed: - all_text_glabels.update(text_glabels) - late_rodata.extend(fn_late_rodata) - late_rodata_asm.extend(fn_late_rodata_body) + all_text_glabels.update(function.text_glabels) + all_late_rodata_dummy_bytes.append(function.late_rodata_dummy_bytes) + all_jtbl_rodata_size.append(function.jtbl_rodata_size) + late_rodata_asm.append(function.late_rodata_asm_conts) + for sectype, (temp_name, size) in function.data.items(): + if temp_name is not None: + asm.append('.section ' + sectype) + asm.append('glabel ' + temp_name + '_asm_start') asm.append('.text') - for line in body: + for line in function.asm_conts: asm.append(line) - if late_rodata_asm: - late_rodata_source_name = '_asmpp_late_rodata' + for sectype, (temp_name, size) in function.data.items(): + if temp_name is not None: + asm.append('.section ' + sectype) + asm.append('glabel ' + temp_name + '_asm_end') + if any(late_rodata_asm): + late_rodata_source_name_start = '_asmpp_late_rodata_start' + late_rodata_source_name_end = '_asmpp_late_rodata_end' asm.append('.rdata') - asm.append('glabel {}'.format(late_rodata_source_name)) - asm.extend(late_rodata_asm) + asm.append('glabel {}'.format(late_rodata_source_name_start)) + for conts in late_rodata_asm: + asm.extend(conts) + asm.append('glabel {}'.format(late_rodata_source_name_end)) o_file = tempfile.NamedTemporaryFile(prefix='asm-processor', suffix='.o', delete=False) o_name = o_file.name @@ -667,11 +898,11 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler): try: s_file.write(asm_prelude + b'\n') for line in asm: - s_file.write(line.encode('utf-8') + b'\n') + s_file.write(line.encode(output_enc) + b'\n') s_file.close() ret = os.system(assembler + " " + s_name + " -o " + o_name) if ret != 0: - raise Exception("failed to assemble") + raise Failure("failed to assemble") with open(o_name, 'rb') as f: asm_objfile = ElfFile(f.read()) @@ -688,17 +919,25 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler): # Move over section contents modified_text_positions = set() + jtbl_rodata_positions = set() last_rodata_pos = 0 for sectype in SECTIONS: - if sectype == '.bss': + if not to_copy[sectype]: continue source = asm_objfile.find_section(sectype) - target = objfile.find_section(sectype) - if source is None or not to_copy[sectype]: + assert source is not None, "didn't find source section: " + sectype + for (pos, count, temp_name, fn_desc) in to_copy[sectype]: + loc1 = asm_objfile.symtab.find_symbol_in_section(temp_name + '_asm_start', source) + loc2 = asm_objfile.symtab.find_symbol_in_section(temp_name + '_asm_end', source) + assert loc1 == pos, "assembly and C files don't line up for section " + sectype + ", " + fn_desc + if loc2 - loc1 != count: + raise Failure("incorrectly computed size for section " + sectype + ", " + fn_desc + ". If using .double, make sure to provide explicit alignment padding.") + if sectype == '.bss': continue - assert target is not None, "must have a section to overwrite: " + sectype + target = objfile.find_section(sectype) + assert target is not None, "missing target section of type " + sectype data = list(target.data) - for (pos, count) in to_copy[sectype]: + for (pos, count, _, _) in to_copy[sectype]: data[pos:pos + count] = source.data[pos:pos + count] if sectype == '.text': assert count % 4 == 0 @@ -712,19 +951,43 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler): # Move over late rodata. This is heuristic, sadly, since I can't think # of another way of doing it. moved_late_rodata = {} - if late_rodata: + if any(all_late_rodata_dummy_bytes) or any(all_jtbl_rodata_size): source = asm_objfile.find_section('.rodata') target = objfile.find_section('.rodata') - source_pos = asm_objfile.symtab.find_symbol(late_rodata_source_name) - assert source_pos is not None and source_pos[0] == source.index - source_pos = source_pos[1] + source_pos = asm_objfile.symtab.find_symbol_in_section(late_rodata_source_name_start, source) + source_end = asm_objfile.symtab.find_symbol_in_section(late_rodata_source_name_end, source) + if source_end - source_pos != sum(map(len, all_late_rodata_dummy_bytes)) * 4 + sum(all_jtbl_rodata_size): + raise Failure("computed wrong size of .late_rodata") new_data = list(target.data) - for dummy_bytes in late_rodata: - pos = target.data.index(dummy_bytes, last_rodata_pos) - new_data[pos:pos+4] = source.data[source_pos:source_pos+4] - moved_late_rodata[source_pos] = pos - last_rodata_pos = pos + 4 - source_pos += 4 + for dummy_bytes_list, jtbl_rodata_size in zip(all_late_rodata_dummy_bytes, all_jtbl_rodata_size): + for index, dummy_bytes in enumerate(dummy_bytes_list): + pos = target.data.index(dummy_bytes, last_rodata_pos) + # This check is nice, but makes time complexity worse for large files: + if SLOW_CHECKS and target.data.find(dummy_bytes, pos + 4) != -1: + raise Failure("multiple occurrences of late_rodata hex magic. Change asm-processor to use something better than 0xE0123456!") + if index == 0 and len(dummy_bytes_list) > 1 and target.data[pos+4:pos+8] == b'\0\0\0\0': + # Ugly hack to handle double alignment for non-matching builds. + # We were told by .late_rodata_alignment (or deduced from a .double) + # that a function's late_rodata started out 4 (mod 8), and emitted + # a float and then a double. But it was actually 0 (mod 8), so our + # double was moved by 4 bytes. To make them adjacent to keep jump + # tables correct, move the float by 4 bytes as well. + new_data[pos:pos+4] = b'\0\0\0\0' + pos += 4 + new_data[pos:pos+4] = source.data[source_pos:source_pos+4] + moved_late_rodata[source_pos] = pos + last_rodata_pos = pos + 4 + source_pos += 4 + if jtbl_rodata_size > 0: + assert dummy_bytes_list, "should always have dummy bytes before jtbl data" + pos = last_rodata_pos + new_data[pos : pos + jtbl_rodata_size] = \ + source.data[source_pos : source_pos + jtbl_rodata_size] + for i in range(0, jtbl_rodata_size, 4): + moved_late_rodata[source_pos + i] = pos + i + jtbl_rodata_positions.add(pos + i) + last_rodata_pos += jtbl_rodata_size + source_pos += jtbl_rodata_size target.data = bytes(new_data) # Merge strtab data. @@ -757,7 +1020,8 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler): continue if s.st_shndx not in [SHN_UNDEF, SHN_ABS]: section_name = asm_objfile.sections[s.st_shndx].name - assert section_name in SECTIONS, "Generated assembly .o must only have symbols for .text, .data, .rodata, ABS and UNDEF, but found {}".format(section_name) + if section_name not in SECTIONS: + raise Failure("generated assembly .o must only have symbols for .text, .data, .rodata, ABS and UNDEF, but found " + section_name) s.st_shndx = objfile.find_section(section_name).index # glabel's aren't marked as functions, making objdump output confusing. Fix that. if s.name in all_text_glabels: @@ -785,7 +1049,8 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler): for reltab in target.relocated_by: nrels = [] for rel in reltab.relocations: - if sectype == '.text' and rel.r_offset in modified_text_positions: + if (sectype == '.text' and rel.r_offset in modified_text_positions or + sectype == '.rodata' and rel.r_offset in jtbl_rodata_positions): # don't include relocations for late_rodata dummy code continue # hopefully we don't have relocations for local or @@ -830,39 +1095,49 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler): except: pass -def main(): +def run_wrapped(argv, outfile): parser = argparse.ArgumentParser(description="Pre-process .c files and post-process .o files to enable embedding assembly into C.") parser.add_argument('filename', help="path to .c code") parser.add_argument('--post-process', dest='objfile', help="path to .o file to post-process") parser.add_argument('--assembler', dest='assembler', help="assembler command (e.g. \"mips-linux-gnu-as -march=vr4300 -mabi=32\")") parser.add_argument('--asm-prelude', dest='asm_prelude', help="path to a file containing a prelude to the assembly file (with .set and .macro directives, e.g.)") + parser.add_argument('--input-enc', default='latin1', help="Input encoding (default: latin1)") + parser.add_argument('--output-enc', default='latin1', help="Output encoding (default: latin1)") parser.add_argument('-framepointer', dest='framepointer', action='store_true') parser.add_argument('-g3', dest='g3', action='store_true') group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-O2', dest='o2', action='store_true') - group.add_argument('-g', dest='o2', action='store_false') - args = parser.parse_args() - opt = 'O2' if args.o2 else 'g' + group.add_argument('-O1', dest='opt', action='store_const', const='O1') + group.add_argument('-O2', dest='opt', action='store_const', const='O2') + group.add_argument('-g', dest='opt', action='store_const', const='g') + args = parser.parse_args(argv) + opt = args.opt if args.g3: if opt != 'O2': - print("-g3 is only supported together with -O2", file=sys.stderr) - exit(1) + raise Failure("-g3 is only supported together with -O2") opt = 'g3' if args.objfile is None: - with open(args.filename) as f: - parse_source(f, print_source=True, opt=opt, framepointer=args.framepointer) + with open(args.filename, encoding=args.input_enc) as f: + parse_source(f, opt=opt, framepointer=args.framepointer, input_enc=args.input_enc, output_enc=args.output_enc, print_source=outfile) else: - assert args.assembler is not None, "must pass assembler command" - with open(args.filename) as f: - functions = parse_source(f, print_source=False, opt=opt, framepointer=args.framepointer) + if args.assembler is None: + raise Failure("must pass assembler command") + with open(args.filename, encoding=args.input_enc) as f: + functions = parse_source(f, opt=opt, framepointer=args.framepointer, input_enc=args.input_enc, output_enc=args.output_enc) if not functions: return asm_prelude = b'' if args.asm_prelude: with open(args.asm_prelude, 'rb') as f: asm_prelude = f.read() - fixup_objfile(args.objfile, functions, asm_prelude, args.assembler) + fixup_objfile(args.objfile, functions, asm_prelude, args.assembler, args.output_enc) + +def run(argv, outfile=sys.stdout.buffer): + try: + run_wrapped(argv, outfile) + except Failure as e: + print("Error:", e, file=sys.stderr) + sys.exit(1) if __name__ == "__main__": - main() + run(sys.argv[1:])