diff --git a/CHANGES b/CHANGES index 0a561b626c..82295970f5 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 cdb4b34692..81804d4e3b 100644 --- a/Makefile +++ b/Makefile @@ -528,8 +528,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 @@ -545,15 +543,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 75cb4f0132..884546eed2 100644 --- a/README.md +++ b/README.md @@ -138,36 +138,34 @@ docker run --rm --mount type=bind,source="$(pwd)",destination=/sm64 --user $UID: Resulting artifacts can be found in the `build` directory. ## Project Structure - -``` -sm64 -├── actors: object behaviors, geo layout, and display lists -├── asm: handwritten assembly code, rom header -│ └── non_matchings: asm for non-matching sections -├── assets: animation and demo data -│ ├── anims: animation data -│ └── demos: demo data -├── bin: C files for ordering display lists and textures -├── build: output directory -├── data: behavior scripts, misc. data -├── doxygen: documentation infrastructure -├── enhancements: example source modifications -├── include: header files -├── levels: level scripts, geo layout, and display lists -├── lib: SDK library code -├── rsp: audio and Fast3D RSP assembly code -├── sound: sequences, sound samples, and sound banks -├── src: C source code for game -│ ├── audio: audio code -│ ├── buffers: stacks, heaps, and task buffers -│ ├── engine: script processing engines and utils -│ ├── game: behaviors and rest of game source -│ ├── goddard: Mario intro screen -│ └── menu: title screen and file, act, and debug level selection menus -├── text: dialog, level names, act names -├── textures: skybox and generic texture data -└── tools: build tools -``` + + sm64 + ├── actors: object behaviors, geo layout, and display lists + ├── asm: handwritten assembly code, rom header + │ └── non_matchings: asm for non-matching sections + ├── assets: animation and demo data + │ ├── anims: animation data + │ └── demos: demo data + ├── bin: C files for ordering display lists and textures + ├── build: output directory + ├── data: behavior scripts, misc. data + ├── doxygen: documentation infrastructure + ├── enhancements: example source modifications + ├── include: header files + ├── levels: level scripts, geo layout, and display lists + ├── lib: SDK library code + ├── rsp: audio and Fast3D RSP assembly code + ├── sound: sequences, sound samples, and sound banks + ├── src: C source code for game + │ ├── audio: audio code + │ ├── buffers: stacks, heaps, and task buffers + │ ├── engine: script processing engines and utils + │ ├── game: behaviors and rest of game source + │ ├── goddard: Mario intro screen + │ └── menu: title screen and file, act, and debug level selection menus + ├── text: dialog, level names, act names + ├── textures: skybox and generic texture data + └── tools: build tools ## Contributing @@ -176,4 +174,4 @@ discuss what you would like to change. Run `clang-format` on your code to ensure it meets the project's coding standards. -Official Discord: https://discord.gg/DuYH3Fh +Official Discord: [discord.gg/DuYH3Fh](https://discord.gg/DuYH3Fh) 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 30649af9b5..4078e3c73c 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 88ac440fdb..c056acdbb1 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 d9d39a1c2e..869070d683 100755 --- a/diff.py +++ b/diff.py @@ -5,6 +5,7 @@ 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 @@ def fail(msg): 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 @@ def fail(msg): parser.add_argument( "--algorithm", dest="algorithm", - default="difflib", + default="levenshtein", choices=["levenshtein", "difflib"], help="Diff algorithm to use.", ) @@ -137,7 +153,7 @@ def fail(msg): 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 @@ def fail(msg): 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 @@ def fail(msg): ] 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 @@ def fail(msg): 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 - -if not binutils_prefix: + import cxxfilt + except ModuleNotFoundError as e: + fail(MISSING_PREREQUISITES.format(e.name)) + +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 args.source and (row and row[0] != " "): + source_lines.append(row) + continue + + 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 diff_rows[-1] != '': - # diff_rows[-1] = process_reloc(row, rows_with_imms[-1]) - originals[-1] = process_reloc(row, originals[-1]) + # 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 - row = re.sub(re_comments, "", row) + 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 remap(seq): 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 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.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.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 @@ def terminate(self): 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/enhancements/debug_box.patch b/enhancements/debug_box.patch index e02bbf4387..d6f846bef8 100644 --- a/enhancements/debug_box.patch +++ b/enhancements/debug_box.patch @@ -8,24 +8,24 @@ index 240605d8..88c1a314 100644 #include "save_file.h" #include "level_table.h" +#include "debug_box.h" - + struct SpawnInfo gPlayerSpawnInfos[1]; struct GraphNode *D_8033A160[0x100]; @@ -353,6 +354,8 @@ void render_game(void) { if (gCurrentArea != NULL && !gWarpTransition.pauseRendering) { geo_process_root(gCurrentArea->unk04, D_8032CE74, D_8032CE78, gFBSetColor); - + + render_debug_boxes(); + gSPViewport(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&D_8032CF00)); - + gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH, diff --git a/src/game/debug_box.c b/src/game/debug_box.c new file mode 100644 index 00000000..0ee87ec7 --- /dev/null +++ b/src/game/debug_box.c -@@ -0,0 +1,244 @@ +@@ -0,0 +1,281 @@ +#include + +#include "sm64.h" @@ -52,7 +52,7 @@ index 00000000..0ee87ec7 + * gSPViewport(...); + * gDPSetScissor(...); + * //... -+ * ++ * + * Now just call debug_box() whenever you want to draw one! + * + * debug_box by default takes two arguments: a center and bounds vec3f. @@ -67,24 +67,39 @@ index 00000000..0ee87ec7 + * Internal struct containing box info + */ +struct DebugBox { ++ u32 color; + Vec3s center; + Vec3s bounds; + s16 yaw; +}; + -+struct DebugBox *sBoxes[MAX_DEBUG_BOXES]; ++struct DebugBox sBoxes[MAX_DEBUG_BOXES]; +s16 sNumBoxes = 0; + +extern Mat4 gMatStack[32]; //XXX: Hack + +/** -+ * The debug boxes' transparency ++ * The debug boxes' default transparency ++ */ ++#define DBG_BOX_ALPHA 0x7F ++/** ++ * The debug boxes' default color. sCurBoxColor is reset to this every frame. ++ */ ++#define DBG_BOX_DEF_COLOR 0xFF0000 ++ ++/** ++ * The color that new boxes will be drawn with. + */ -+#define DBG_BOX_ALPHA 0x7F ++u32 sCurBoxColor = DBG_BOX_ALPHA << 24 | DBG_BOX_DEF_COLOR; ++ ++/** ++ * The allocated size of a rotated box's dl ++ */ ++#define DBG_BOX_ROT_DLSIZE ((s32)(6 * sizeof(Gfx) + 8 * sizeof(Vtx))) +/** -+ * The debug boxes' color ++ * The allocated size of a normal box's dl + */ -+#define DBG_BOX_COL 0xFF, 0x00, 0x00, DBG_BOX_ALPHA ++#define DBG_BOX_DLSIZE ((s32)(2 * sizeof(Gfx) + 8 * sizeof(Vtx))) + +/** + * Sets up the RCP for drawing the boxes @@ -107,14 +122,14 @@ index 00000000..0ee87ec7 + * Actually draws the box + */ +static const Gfx dl_debug_draw_box[] = { -+ gsSP2Triangles( 0, 1, 2, 0x0, 2, 1, 3, 0x0), -+ gsSP2Triangles( 2, 3, 6, 0x0, 6, 3, 7, 0x0), ++ gsSP2Triangles(5, 4, 6, 0x0, 5, 6, 7, 0x0), // front ++ gsSP2Triangles(0, 1, 2, 0x0, 2, 1, 3, 0x0), // back + -+ gsSP2Triangles( 4, 0, 2, 0x0, 2, 6, 4, 0x0), -+ gsSP2Triangles( 1, 5, 3, 0x0, 3, 5, 7, 0x0), -+ -+ gsSP2Triangles( 1, 0, 4, 0x0, 1, 4, 5, 0x0), -+ gsSP2Triangles( 5, 4, 6, 0x0, 5, 6, 7, 0x0), ++ gsSP2Triangles(4, 0, 2, 0x0, 2, 6, 4, 0x0), // left ++ gsSP2Triangles(1, 5, 3, 0x0, 3, 5, 7, 0x0), // right ++ ++ gsSP2Triangles(1, 0, 4, 0x0, 1, 4, 5, 0x0), // top ++ gsSP2Triangles(2, 3, 6, 0x0, 6, 3, 7, 0x0), // bottom + + gsSPEndDisplayList(), +}; @@ -126,20 +141,32 @@ index 00000000..0ee87ec7 + */ +static void append_debug_box(Vec3f center, Vec3f bounds, s16 yaw) +{ -+ if (sNumBoxes >= MAX_DEBUG_BOXES || -+ (sBoxes[sNumBoxes] = mem_pool_alloc(gEffectsMemoryPool, sizeof(struct DebugBox))) == NULL) { ++ if (sNumBoxes >= MAX_DEBUG_BOXES) { + return; + } + -+ vec3f_to_vec3s(sBoxes[sNumBoxes]->center, center); -+ vec3f_to_vec3s(sBoxes[sNumBoxes]->bounds, bounds); ++ vec3f_to_vec3s(sBoxes[sNumBoxes].center, center); ++ vec3f_to_vec3s(sBoxes[sNumBoxes].bounds, bounds); + -+ sBoxes[sNumBoxes]->yaw = yaw; ++ sBoxes[sNumBoxes].yaw = yaw; ++ sBoxes[sNumBoxes].color = sCurBoxColor; + + ++sNumBoxes; +} + +/** ++ * Draw new boxes with the given color. ++ * Color format is 32-bit ARGB. ++ * If the alpha component is zero, DBG_BOX_ALPHA (0x7f) will be used instead. ++ * Ex: 0xFF0000 becomes 0x7FFF0000 ++ */ ++void debug_box_color(u32 color) ++{ ++ if ((color >> 24) == 0) color |= (DBG_BOX_ALPHA << 24); ++ sCurBoxColor = color; ++} ++ ++/** + * Draws a debug box from (center - bounds) to (center + bounds) + * To draw a rotated box, use debug_box_rot() + * @@ -176,9 +203,9 @@ index 00000000..0ee87ec7 +{ + Vec3f center, bounds; + -+ bounds[0] = pMax[0] - pMin[0] / 2.0f; -+ bounds[1] = pMax[1] - pMin[1] / 2.0f; -+ bounds[2] = pMax[2] - pMin[2] / 2.0f; ++ bounds[0] = (pMax[0] - pMin[0]) / 2.0f; ++ bounds[1] = (pMax[1] - pMin[1]) / 2.0f; ++ bounds[2] = (pMax[2] - pMin[2]) / 2.0f; + + center[0] = pMin[0] + bounds[0]; + center[1] = pMin[1] + bounds[1]; @@ -187,12 +214,15 @@ index 00000000..0ee87ec7 + append_debug_box(center, bounds, yaw); +} + -+static void render_box(struct DebugBox *box) ++static void render_box(int index) +{ -+ Vtx *verts = alloc_display_list(8 * sizeof(Vtx)); ++ Vtx *verts; + Mtx *translate; + Mtx *rotate; + Mtx *translateback; ++ struct DebugBox *box = &sBoxes[index]; ++ u32 color = box->color; ++ + s32 x0 = box->center[0], + y0 = box->center[1], + z0 = box->center[2]; @@ -201,6 +231,13 @@ index 00000000..0ee87ec7 + yb = box->bounds[1], + zb = box->bounds[2]; + ++ if (box->yaw != 0 && (Gfx*)gGfxPoolEnd - gDisplayListHead < DBG_BOX_ROT_DLSIZE) ++ return; ++ else if ((Gfx*)gGfxPoolEnd - gDisplayListHead < DBG_BOX_DLSIZE) ++ return; ++ ++ verts = alloc_display_list(8 * sizeof(Vtx)); ++ + if (verts != NULL) { + if (box->yaw != 0) { + // Translate to the origin, rotate, then translate back, effectively rotating the box about @@ -217,7 +254,8 @@ index 00000000..0ee87ec7 + gSPMatrix(gDisplayListHead++, rotate, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH); + gSPMatrix(gDisplayListHead++, translateback, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH); + } -+ ++ ++#define DBG_BOX_COL /**/ (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, (color >> 24) & 0xff +#define DBG_BOX_VTX(i, x, y, z) make_vertex(verts, i, x, y, z, 0, 0, DBG_BOX_COL) + DBG_BOX_VTX(0, x0 - xb, y0 + yb, z0 - zb); + DBG_BOX_VTX(1, x0 + xb, y0 + yb, z0 - zb); @@ -228,7 +266,7 @@ index 00000000..0ee87ec7 + DBG_BOX_VTX(6, x0 - xb, y0 - yb, z0 + zb); + DBG_BOX_VTX(7, x0 + xb, y0 - yb, z0 + zb); +#undef DBG_BOX_VTX -+ ++ + gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(verts), 8, 0); + + gSPDisplayList(gDisplayListHead++, dl_debug_draw_box); @@ -244,15 +282,15 @@ index 00000000..0ee87ec7 + s32 i; + Mtx *mtx; + ++ debug_box_color(DBG_BOX_DEF_COLOR); ++ + if (sNumBoxes == 0) { + return; + } + + mtx = alloc_display_list(sizeof(Mtx)); -+ if (mtx == NULL) { -+ for (i = 0; i < sNumBoxes; ++i) { -+ mem_pool_free(gEffectsMemoryPool, sBoxes[i]); -+ } ++ // Don't draw if there isn't space for the configuration + at least one box ++ if (mtx == NULL || ((Gfx*)gGfxPoolEnd - gDisplayListHead) <= (s32)(2 * sizeof(Gfx)) + DBG_BOX_DLSIZE) { + sNumBoxes = 0; + return; + } @@ -264,8 +302,7 @@ index 00000000..0ee87ec7 + gSPDisplayList(gDisplayListHead++, dl_debug_box_begin); + + for (i = 0; i < sNumBoxes; ++i) { -+ render_box(sBoxes[i]); -+ mem_pool_free(gEffectsMemoryPool, sBoxes[i]); ++ render_box(i); + } + + sNumBoxes = 0; @@ -275,23 +312,24 @@ new file mode 100644 index 00000000..cdb3dc9d --- /dev/null +++ b/src/game/debug_box.h -@@ -0,0 +1,25 @@ -+#ifndef _DEBUG_DRAW_CUBE_H -+#define _DEBUG_DRAW_CUBE_H +@@ -0,0 +1,26 @@ ++#ifndef DEBUG_BOX_H ++#define DEBUG_BOX_H + +/** + * @file debug_box.h -+ * Draws debug boxes, see debug_box.inc.c for details ++ * Draws debug boxes, see debug_box.c for details + */ + +#include "types.h" + +/** + * The max amount of debug boxes before debug_box() just returns. -+ * You can set this to something higher like 1000, but things like text will stop rendering. ++ * You can set this to something higher, but you might run out of space in the gfx pool. + */ -+#define MAX_DEBUG_BOXES 100 ++#define MAX_DEBUG_BOXES 512 + ++void debug_box_color(u32 color); +void debug_box(Vec3f center, Vec3f bounds); +void debug_box_rot(Vec3f center, Vec3f bounds, s16 yaw); + @@ -300,4 +338,4 @@ index 00000000..cdb3dc9d + +void render_debug_boxes(void); + -+#endif /* _DEBUG_DRAW_CUBE_H */ ++#endif /* DEBUG_BOX_H */ diff --git a/enhancements/mem_error_screen.patch b/enhancements/mem_error_screen.patch index 87d995d684..4f1335f39d 100644 --- a/enhancements/mem_error_screen.patch +++ b/enhancements/mem_error_screen.patch @@ -170,7 +170,7 @@ index a3afffee..8b05fcf1 100644 + create_thread(&gGameLoopThread, 5, thread5_mem_error_message_loop, NULL, gThread5Stack + 0x2000, 10); osStartThread(&gGameLoopThread); - while (1) { + while (TRUE) { diff --git a/src/game/mem_error_screen.c b/src/game/mem_error_screen.c new file mode 100644 index 00000000..81efaf91 diff --git a/include/eu_translation.h b/include/eu_translation.h index beb6fa7b18..196868250f 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 82a1676974..d393aeb55a 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 @@ -662,10 +662,10 @@ /* oAnimState */ #define UKIKI_ANIM_STATE_DEFAULT 0 #define UKIKI_ANIM_STATE_EYE_CLOSED 1 - #define UKIKI_ANIM_STATE_HAT_ON 2 + #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 9f2661ce06..5914a5a06d 100644 --- a/include/object_fields.h +++ b/include/object_fields.h @@ -504,9 +504,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) @@ -959,7 +959,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) @@ -1050,7 +1050,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) @@ -1084,7 +1084,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 89634464ed..a8c1bf9717 100644 --- a/include/segments.h +++ b/include/segments.h @@ -44,7 +44,7 @@ */ #define SEG_BUFFERS 0x8005C000 // 0x0085000 in size -#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 632224e079..d5bc30abf7 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 a33dc721fb..5132a4ed88 100644 --- a/include/types.h +++ b/include/types.h @@ -86,11 +86,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. @@ -108,8 +108,7 @@ struct GraphNode /*0x10*/ struct GraphNode *children; }; -// struct AnimInfo? -struct GraphNodeObject_sub +struct AnimInfo { /*0x00 0x38*/ s16 animID; /*0x02 0x3A*/ s16 animYTrans; @@ -124,12 +123,12 @@ 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; /*0x2C*/ Vec3f scale; - /*0x38*/ struct GraphNodeObject_sub unk38; + /*0x38*/ struct AnimInfo animInfo; /*0x4C*/ struct SpawnInfo *unk4C; /*0x50*/ Mat4 *throwMatrix; // matrix ptr /*0x54*/ Vec3f cameraToObject; diff --git a/lib/src/osViSetSpecialFeatures.c b/lib/src/osViSetSpecialFeatures.c index 590bfad8a1..b486896e2d 100644 --- a/lib/src/osViSetSpecialFeatures.c +++ b/lib/src/osViSetSpecialFeatures.c @@ -12,15 +12,12 @@ void osViSetSpecialFeatures(u32 func) { D_80334914->features |= OS_VI_GAMMA_DITHER; } if (func & OS_VI_GAMMA_DITHER_OFF) { - D_80334914->features &= ~OS_VI_GAMMA_DITHER; } if (func & OS_VI_DIVOT_ON) { - D_80334914->features |= OS_VI_DIVOT; } if (func & OS_VI_DIVOT_OFF) { - D_80334914->features &= ~OS_VI_DIVOT; } if (func & OS_VI_DITHER_FILTER_ON) { diff --git a/sm64.ld b/sm64.ld index e6f5c94276..382c84225e 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 fb75a89dbe..9866e9f810 100644 --- a/src/audio/data.c +++ b/src/audio/data.c @@ -333,11 +333,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, @@ -584,7 +584,7 @@ f32 gVolRampingRhs128[128] = { s16 gTatumsPerBeat = TATUMS_PER_BEAT; s8 gUnusedCount80333EE8 = UNUSED_COUNT_80333EE8; s32 gAudioHeapSize = DOUBLE_SIZE_ON_64_BIT(AUDIO_HEAP_SIZE); -s32 D_80333EF0 = DOUBLE_SIZE_ON_64_BIT(D_80333EF0_VAL); +s32 gAudioInitPoolSize = DOUBLE_SIZE_ON_64_BIT(AUDIO_INIT_POOL_SIZE); volatile s32 gAudioLoadLock = AUDIO_LOCK_UNINITIALIZED; #ifdef VERSION_EU diff --git a/src/audio/data.h b/src/audio/data.h index d2a8b4db3b..fb60bc5c4c 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 D_80333EF0; // 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 @@ -103,15 +103,14 @@ extern u16 gUnused80226E98[0x10]; extern u32 gAudioRandom; -//make my life easier #ifdef VERSION_EU #define UNUSED_COUNT_80333EE8 24 #define AUDIO_HEAP_SIZE 0x2c500 -#define D_80333EF0_VAL 0x2c00 +#define AUDIO_INIT_POOL_SIZE 0x2c00 #else #define UNUSED_COUNT_80333EE8 16 #define AUDIO_HEAP_SIZE 0x31150 -#define D_80333EF0_VAL 0x2500 +#define AUDIO_INIT_POOL_SIZE 0x2500 #endif diff --git a/src/audio/effects.c b/src/audio/effects.c index 80cdbeda4a..66b131e59e 100644 --- a/src/audio/effects.c +++ b/src/audio/effects.c @@ -502,6 +502,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 66325a4659..1e3dc57e0b 100644 --- a/src/audio/external.c +++ b/src/audio/external.c @@ -19,136 +19,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 @@ -160,15 +30,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 284a192570..63c988f7b7 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 ce580d4e84..f34eaa65ef 100644 --- a/src/audio/heap.c +++ b/src/audio/heap.c @@ -167,11 +167,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; } @@ -209,6 +215,7 @@ void *soundAlloc(struct SoundAllocPool *pool, u32 size) { *pos = 0; } } else { + eu_stubbed_printf_1("Heap OverFlow : Not Allocate %d!\n", size); return NULL; } return start; @@ -309,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; @@ -342,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; @@ -360,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; @@ -373,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) { @@ -410,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; @@ -444,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) { @@ -463,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; } @@ -486,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 @@ -494,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; } } @@ -523,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; } } @@ -537,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 @@ -567,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) { @@ -679,10 +712,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) { @@ -936,3 +969,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 b042f74f14..70e86d4e73 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 */ @@ -326,6 +350,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 */ @@ -394,7 +420,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; @@ -507,6 +534,11 @@ 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 @@ -527,6 +559,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 fcea6d9d9f..d60b61a315 100644 --- a/src/audio/load.c +++ b/src/audio/load.c @@ -107,12 +107,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 */ @@ -666,11 +687,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; } @@ -678,8 +701,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; @@ -742,12 +765,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]; @@ -787,6 +810,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; @@ -828,6 +852,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; } @@ -835,17 +860,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; } @@ -860,6 +893,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; @@ -935,6 +969,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; } @@ -952,7 +996,7 @@ void audio_init() { gCurrAudioFrameDmaCount = 0; gSampleDmaNumListItems = 0; - sound_init_main_pools(D_80333EF0); + sound_init_main_pools(gAudioInitPoolSize); for (i = 0; i < NUMAIBUFFERS; i++) { gAiBuffers[i] = soundAlloc(&gAudioInitPool, AIBUFFER_LEN); @@ -970,6 +1014,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 = gMusicData; @@ -1011,5 +1060,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 d11620776d..e0928e4f43 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 979d5b2c75..e997f276a0 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,16 +160,20 @@ 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; } #ifndef NO_SEGMENTED_MEMORY if ((uintptr_t) gCtlEntries[bankId].drums < 0x80000000U) { - return 0; + stubbed_printf("Percussion Pointer Error\n"); + return NULL; } #endif 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; @@ -232,8 +248,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 \ @@ -257,6 +273,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; @@ -292,6 +309,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); @@ -435,7 +453,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; } @@ -503,6 +524,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; } @@ -531,6 +553,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; @@ -671,7 +694,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); @@ -703,6 +730,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; } @@ -741,7 +769,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; @@ -753,14 +783,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; @@ -894,8 +926,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); } @@ -928,6 +962,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; } @@ -941,6 +976,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; } @@ -951,6 +987,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; } @@ -966,6 +1003,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; } @@ -1011,7 +1049,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 85476cf7f4..f6a405a318 100644 --- a/src/audio/port_eu.c +++ b/src/audio/port_eu.c @@ -141,7 +141,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 7d0cf92999..0a4284572e 100644 --- a/src/audio/seqplayer.c +++ b/src/audio/seqplayer.c @@ -198,6 +198,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 { @@ -221,6 +222,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]; @@ -230,7 +232,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; } @@ -243,27 +247,30 @@ void sequence_player_disable_channels(struct SequencePlayer *seqPlayer, u16 chan } } -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) { @@ -309,7 +316,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; @@ -479,12 +488,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; @@ -571,9 +586,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 @@ -627,6 +641,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; } } } @@ -891,6 +908,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" @@ -986,7 +1007,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; @@ -1086,6 +1106,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; @@ -1096,6 +1119,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; @@ -1132,9 +1158,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; @@ -1177,7 +1203,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!) @@ -1188,6 +1214,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 @@ -1322,6 +1350,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; @@ -1381,6 +1411,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; @@ -1389,6 +1422,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; @@ -1433,7 +1469,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 @@ -1470,7 +1506,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 @@ -1621,6 +1657,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; } @@ -1685,6 +1722,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 @@ -1694,6 +1734,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; @@ -1913,6 +1956,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; @@ -1967,6 +2014,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 f2631f6f55..6ff676155f 100644 --- a/src/audio/synthesis.c +++ b/src/audio/synthesis.c @@ -71,11 +71,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 @@ -614,8 +615,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 4a6495c083..4f957c7d9f 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; } @@ -698,7 +698,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; @@ -717,12 +717,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; @@ -737,11 +737,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; } } @@ -752,15 +752,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; } /** @@ -789,7 +789,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; @@ -810,11 +810,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 { @@ -824,11 +824,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); } } } @@ -849,7 +849,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; @@ -858,7 +858,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 a680f70e7d..22ab70cea5 100644 --- a/src/engine/graph_node.h +++ b/src/engine/graph_node.h @@ -420,7 +420,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 58c5e3f010..e5d59d8b5c 100644 --- a/src/engine/math_util.c +++ b/src/engine/math_util.c @@ -159,7 +159,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 9aff62f936..69f40c9c09 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c @@ -199,8 +199,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; @@ -307,8 +307,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 @@ -327,8 +327,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; @@ -486,7 +486,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; @@ -494,8 +494,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); @@ -514,8 +514,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. @@ -534,8 +534,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; @@ -591,7 +591,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) { @@ -627,7 +627,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) { @@ -689,25 +689,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 71898d3309..67a436b1a9 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 6936d8a13d..114d4f0ad1 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -21,8 +21,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. @@ -83,7 +83,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; @@ -201,18 +201,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; } @@ -233,23 +233,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 5e77e92974..b7b3a5a3b9 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 d458bf7129..f597cfee78 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -58,7 +58,6 @@ s16 gCurrLevelNum = LEVEL_MIN; * 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, @@ -67,7 +66,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, @@ -108,7 +106,7 @@ void set_warp_transition_rgb(u8 red, u8 green, u8 blue) { 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) { @@ -285,7 +283,7 @@ void change_area(s32 index) { } if (areaFlags & 0x01) { - gMarioObject->header.gfx.unk18 = index, gMarioSpawnInfo->areaIndex = index; + gMarioObject->header.gfx.areaIndex = index, gMarioSpawnInfo->areaIndex = index; } } @@ -392,7 +390,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; @@ -406,7 +404,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); @@ -414,5 +412,5 @@ void render_game(void) { } D_8032CE74 = NULL; - D_8032CE78 = 0; + D_8032CE78 = NULL; } diff --git a/src/game/behavior_actions.c b/src/game/behavior_actions.c index b40408b3c3..a9bcd56df8 100644 --- a/src/game/behavior_actions.c +++ b/src/game/behavior_actions.c @@ -244,7 +244,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 29583c4068..1a63bbb230 100644 --- a/src/game/behaviors/amp.inc.c +++ b/src/game/behaviors/amp.inc.c @@ -146,7 +146,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; } } @@ -178,7 +178,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 827b2e6ce6..13b33df716 100644 --- a/src/game/behaviors/bbh_merry_go_round.inc.c +++ b/src/game/behaviors/bbh_merry_go_round.inc.c @@ -88,7 +88,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/blue_coin.inc.c b/src/game/behaviors/blue_coin.inc.c index 6f90fa5e74..de05e22283 100644 --- a/src/game/behaviors/blue_coin.inc.c +++ b/src/game/behaviors/blue_coin.inc.c @@ -68,7 +68,7 @@ void bhv_blue_coin_switch_loop(void) { // If Mario is on the switch and has ground-pounded, // recede and get ready to start ticking. if (gMarioObject->platform == o) { - if (gMarioStates->action == ACT_GROUND_POUND_LAND) { + if (gMarioStates[0].action == ACT_GROUND_POUND_LAND) { // Set to BLUE_COIN_SWITCH_ACT_RECEDING o->oAction++; diff --git a/src/game/behaviors/bobomb.inc.c b/src/game/behaviors/bobomb.inc.c index 4d10d978ed..2e3a314ca9 100644 --- a/src/game/behaviors/bobomb.inc.c +++ b/src/game/behaviors/bobomb.inc.c @@ -69,12 +69,12 @@ 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(); if ((obj_return_home_if_safe(o, o->oHomeX, o->oHomeY, o->oHomeZ, 400) == 1) - && (obj_check_if_facing_toward_angle(o->oMoveAngleYaw, o->oAngleToMario, 0x2000) == 1)) { + && (obj_check_if_facing_toward_angle(o->oMoveAngleYaw, o->oAngleToMario, 0x2000) == TRUE)) { o->oBobombFuseLit = 1; o->oAction = BOBOMB_ACT_CHASE_MARIO; } @@ -85,7 +85,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(); @@ -286,7 +286,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; @@ -383,7 +383,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 abfaba866b..ec522d06c6 100644 --- a/src/game/behaviors/boo.inc.c +++ b/src/game/behaviors/boo.inc.c @@ -31,7 +31,7 @@ void bhv_boo_init(void) { static s32 boo_should_be_stopped(void) { if (cur_obj_has_behavior(bhvMerryGoRoundBigBoo) || cur_obj_has_behavior(bhvMerryGoRoundBoo)) { - if (gMarioOnMerryGoRound == FALSE) { + if (!gMarioOnMerryGoRound) { return TRUE; } else { return FALSE; @@ -312,7 +312,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; @@ -554,7 +554,7 @@ static void big_boo_act_1(void) { // redundant; this check is in boo_should_be_stopped if (cur_obj_has_behavior(bhvMerryGoRoundBigBoo)) { - if (gMarioOnMerryGoRound == FALSE) { + if (!gMarioOnMerryGoRound) { o->oAction = 0; } } else if (boo_should_be_stopped()) { diff --git a/src/game/behaviors/bowser.inc.c b/src/game/behaviors/bowser.inc.c index ebc6bf475c..99d359bbda 100644 --- a/src/game/behaviors/bowser.inc.c +++ b/src/game/behaviors/bowser.inc.c @@ -54,8 +54,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); @@ -398,7 +398,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); if (frame == 35) @@ -458,7 +458,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 (o->oDistanceToMario < 850.0f) @@ -1033,7 +1033,7 @@ void bowser_free_update(void) { struct Object *platform; UNUSED f32 floorHeight; if ((platform = o->platform) != NULL) - apply_platform_displacement(0, platform); + apply_platform_displacement(FALSE, platform); o->oBowserUnk10E = 0; cur_obj_update_floor_and_walls(); cur_obj_call_action_function(sBowserActions); diff --git a/src/game/behaviors/bowser_key_cutscene.inc.c b/src/game/behaviors/bowser_key_cutscene.inc.c index d3fa47f4fd..e840b893ac 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/breakable_wall.inc.c b/src/game/behaviors/breakable_wall.inc.c index 997d220800..dbb92c8dab 100644 --- a/src/game/behaviors/breakable_wall.inc.c +++ b/src/game/behaviors/breakable_wall.inc.c @@ -1,7 +1,7 @@ // breakable_wall.c.inc void bhv_wf_breakable_wall_loop(void) { - if (gMarioStates->action == ACT_SHOT_FROM_CANNON) { + if (gMarioStates[0].action == ACT_SHOT_FROM_CANNON) { cur_obj_become_tangible(); if (obj_check_if_collided_with_object(o, gMarioObject)) { if (cur_obj_has_behavior(bhvWfBreakableWallRight)) diff --git a/src/game/behaviors/bully.inc.c b/src/game/behaviors/bully.inc.c index efe0ee1800..ddabf8499e 100644 --- a/src/game/behaviors/bully.inc.c +++ b/src/game/behaviors/bully.inc.c @@ -98,7 +98,7 @@ void bully_act_knockback(void) { o->oMoveAngleYaw = o->oFaceAngleYaw; obj_turn_toward_object(o, gMarioObject, 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; @@ -139,7 +139,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 d435d8d88c..2b530d810a 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 0f70c3398f..c3e7f44108 100644 --- a/src/game/behaviors/camera_lakitu.inc.c +++ b/src/game/behaviors/camera_lakitu.inc.c @@ -13,7 +13,7 @@ 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); } } else { diff --git a/src/game/behaviors/castle_cannon_grate.inc.c b/src/game/behaviors/castle_cannon_grate.inc.c index cc0c8b31a2..64bd924b66 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 6872621b07..d589ff3b75 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/castle_floor_trap.inc.c b/src/game/behaviors/castle_floor_trap.inc.c index 9eeddbb4c4..4bceb9e4c2 100644 --- a/src/game/behaviors/castle_floor_trap.inc.c +++ b/src/game/behaviors/castle_floor_trap.inc.c @@ -14,8 +14,8 @@ void bhv_castle_floor_trap_init(void) { } void bhv_castle_floor_trap_open_detect(void) { - if (gMarioStates->action == ACT_SPECIAL_EXIT_AIRBORNE - || gMarioStates->action == ACT_SPECIAL_DEATH_EXIT) + if (gMarioStates[0].action == ACT_SPECIAL_EXIT_AIRBORNE + || gMarioStates[0].action == ACT_SPECIAL_DEATH_EXIT) o->oAction = 4; // rotates trapdoor so it looks always open else { o->oAngleVelRoll = 0x400; diff --git a/src/game/behaviors/chuckya.inc.c b/src/game/behaviors/chuckya.inc.c index 99a1b5f1db..1be8da8098 100644 --- a/src/game/behaviors/chuckya.inc.c +++ b/src/game/behaviors/chuckya.inc.c @@ -9,15 +9,15 @@ void common_anchor_mario_behavior(f32 sp28, f32 sp2C, s32 sp30) { break; case 2: gMarioObject->oInteractStatus |= (sp30 + INT_STATUS_MARIO_UNK2); - gMarioStates->forwardVel = sp28; - gMarioStates->vel[1] = sp2C; + gMarioStates[0].forwardVel = sp28; + gMarioStates[0].vel[1] = sp2C; o->parentObj->oChuckyaUnk88 = 0; break; case 3: gMarioObject->oInteractStatus |= (INT_STATUS_MARIO_UNK2 + INT_STATUS_MARIO_UNK6); // loads 2 interactions at once? - gMarioStates->forwardVel = 10.0f; - gMarioStates->vel[1] = 10.0f; + gMarioStates[0].forwardVel = 10.0f; + gMarioStates[0].vel[1] = 10.0f; o->parentObj->oChuckyaUnk88 = 0; break; } diff --git a/src/game/behaviors/coin.inc.c b/src/game/behaviors/coin.inc.c index 2afc169278..3110b4fe5d 100644 --- a/src/game/behaviors/coin.inc.c +++ b/src/game/behaviors/coin.inc.c @@ -138,9 +138,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/dorrie.inc.c b/src/game/behaviors/dorrie.inc.c index abe7ad3129..3eb3c04e81 100644 --- a/src/game/behaviors/dorrie.inc.c +++ b/src/game/behaviors/dorrie.inc.c @@ -96,7 +96,7 @@ void dorrie_act_raise_head(void) { o->collisionData = segmented_to_virtual(dorrie_seg6_collision_0600F644); if (cur_obj_check_if_near_animation_end()) { o->oAction = DORRIE_ACT_MOVE; - } else if (o->oDorrieLiftingMario && o->header.gfx.unk38.animFrame < 74) { + } else if (o->oDorrieLiftingMario && o->header.gfx.animInfo.animFrame < 74) { if (set_mario_npc_dialog(2) == 2) { o->oDorrieHeadRaiseSpeed += 0x1CC; if (cur_obj_check_anim_frame(73)) { diff --git a/src/game/behaviors/fish.inc.c b/src/game/behaviors/fish.inc.c index c771176ac4..59e771dbd6 100644 --- a/src/game/behaviors/fish.inc.c +++ b/src/game/behaviors/fish.inc.c @@ -226,7 +226,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 873523d8dd..3ba7590e36 100644 --- a/src/game/behaviors/flame.inc.c +++ b/src/game/behaviors/flame.inc.c @@ -15,24 +15,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(o->oAngleToMario, 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 3ef046ae64..8d78349e53 100644 --- a/src/game/behaviors/flamethrower.inc.c +++ b/src/game/behaviors/flamethrower.inc.c @@ -40,7 +40,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 (o->oDistanceToMario < 2000.0f) o->oAction++; } else if (o->oAction == 1) { diff --git a/src/game/behaviors/heave_ho.inc.c b/src/game/behaviors/heave_ho.inc.c index 81123f58a6..9afe9c5845 100644 --- a/src/game/behaviors/heave_ho.inc.c +++ b/src/game/behaviors/heave_ho.inc.c @@ -16,8 +16,8 @@ void bhv_heave_ho_throw_mario_loop(void) { case 2: cur_obj_play_sound_2(SOUND_OBJ_HEAVEHO_TOSSED); gMarioObject->oInteractStatus |= INT_STATUS_MARIO_UNK2; - gMarioStates->forwardVel = -45.0f; - gMarioStates->vel[1] = 95.0f; + gMarioStates[0].forwardVel = -45.0f; + gMarioStates[0].vel[1] = 95.0f; o->parentObj->oHeaveHoUnk88 = 0; break; } @@ -27,7 +27,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 481b64330e..f43f0ffd75 100644 --- a/src/game/behaviors/hoot.inc.c +++ b/src/game/behaviors/hoot.inc.c @@ -49,7 +49,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; @@ -95,7 +95,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; @@ -161,7 +161,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 eb32d1c9f5..2838a9105a 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 7b3498ba30..7b6a247587 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/kickable_board.inc.c b/src/game/behaviors/kickable_board.inc.c index 7be9b21272..8ba05e54a2 100644 --- a/src/game/behaviors/kickable_board.inc.c +++ b/src/game/behaviors/kickable_board.inc.c @@ -3,17 +3,17 @@ s32 check_mario_attacking(UNUSED s32 sp18) { if (obj_check_if_collided_with_object(o, gMarioObject)) { if (abs_angle_diff(o->oMoveAngleYaw, gMarioObject->oMoveAngleYaw) > 0x6000) { - if (gMarioStates->action == ACT_SLIDE_KICK) + if (gMarioStates[0].action == ACT_SLIDE_KICK) return 1; - if (gMarioStates->action == ACT_PUNCHING) + if (gMarioStates[0].action == ACT_PUNCHING) return 1; - if (gMarioStates->action == ACT_MOVE_PUNCHING) + if (gMarioStates[0].action == ACT_MOVE_PUNCHING) return 1; - if (gMarioStates->action == ACT_SLIDE_KICK_SLIDE) + if (gMarioStates[0].action == ACT_SLIDE_KICK_SLIDE) return 1; - if (gMarioStates->action == ACT_JUMP_KICK) + if (gMarioStates[0].action == ACT_JUMP_KICK) return 2; - if (gMarioStates->action == ACT_WALL_KICK_AIR) + if (gMarioStates[0].action == ACT_WALL_KICK_AIR) return 2; } } diff --git a/src/game/behaviors/king_bobomb.inc.c b/src/game/behaviors/king_bobomb.inc.c index e6e824dc99..1d1a7b5845 100644 --- a/src/game/behaviors/king_bobomb.inc.c +++ b/src/game/behaviors/king_bobomb.inc.c @@ -22,8 +22,8 @@ void bhv_bobomb_anchor_mario_loop(void) { void king_bobomb_act_0(void) { #ifndef VERSION_JP - o->oForwardVel = 0; - o->oVelY = 0; + o->oForwardVel = 0.0f; + o->oVelY = 0.0f; #endif if (o->oSubAction == 0) { cur_obj_become_intangible(); @@ -41,11 +41,12 @@ void king_bobomb_act_0(void) { } } -int mario_is_far_below_object(f32 arg0) { - if (arg0 < o->oPosY - gMarioObject->oPosY) - return 1; - else - return 0; +s32 mario_is_far_below_object(f32 arg0) { + if (arg0 < o->oPosY - gMarioObject->oPosY) { + return TRUE; + } else { + return FALSE; + } } void king_bobomb_act_2(void) { diff --git a/src/game/behaviors/klepto.inc.c b/src/game/behaviors/klepto.inc.c index 22ab3e8fb7..46d7ffcc67 100644 --- a/src/game/behaviors/klepto.inc.c +++ b/src/game/behaviors/klepto.inc.c @@ -31,7 +31,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/koopa_shell.inc.c b/src/game/behaviors/koopa_shell.inc.c index c408bed768..1fcbf40642 100644 --- a/src/game/behaviors/koopa_shell.inc.c +++ b/src/game/behaviors/koopa_shell.inc.c @@ -16,7 +16,7 @@ void koopa_shell_spawn_water_drop(void) { UNUSED s32 unused; struct Object *drop; spawn_object(o, MODEL_WAVE_TRAIL, bhvObjectWaveTrail); - if (gMarioStates->forwardVel > 10.0f) { + if (gMarioStates[0].forwardVel > 10.0f) { drop = spawn_object_with_scale(o, MODEL_WHITE_PARTICLE_SMALL, bhvWaterDroplet, 1.5f); drop->oVelY = random_float() * 30.0f; obj_translate_xz_random(drop, 110.0f); diff --git a/src/game/behaviors/manta_ray.inc.c b/src/game/behaviors/manta_ray.inc.c index 35e5e2e69f..ba5d911557 100644 --- a/src/game/behaviors/manta_ray.inc.c +++ b/src/game/behaviors/manta_ray.inc.c @@ -36,7 +36,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 851dfedef1..ce3957bfa3 100644 --- a/src/game/behaviors/metal_box.inc.c +++ b/src/game/behaviors/metal_box.inc.c @@ -29,7 +29,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, gMarioObject) && gMarioStates->flags & 0x80000000) { + if (obj_check_if_collided_with_object(o, gMarioObject) && gMarioStates[0].flags & MARIO_UNKNOWN_31) { sp1C = obj_angle_to_object(o, gMarioObject); if (abs_angle_diff(sp1C, gMarioObject->oMoveAngleYaw) > 0x4000) { o->oMoveAngleYaw = (s16)((gMarioObject->oMoveAngleYaw + 0x2000) & 0xc000); diff --git a/src/game/behaviors/mips.inc.c b/src/game/behaviors/mips.inc.c index a24cecd13e..613bcdaff1 100644 --- a/src/game/behaviors/mips.inc.c +++ b/src/game/behaviors/mips.inc.c @@ -8,19 +8,19 @@ */ 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; @@ -164,7 +164,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 209aa5ea94..7c366632e1 100644 --- a/src/game/behaviors/moneybag.inc.c +++ b/src/game/behaviors/moneybag.inc.c @@ -55,7 +55,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: @@ -96,7 +96,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 103534df44..69b772b7dd 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 581a4d0e84..447c27511e 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 e8abe089aa..17f298dd58 100644 --- a/src/game/behaviors/piranha_plant.inc.c +++ b/src/game/behaviors/piranha_plant.inc.c @@ -240,7 +240,7 @@ static s8 sPiranhaPlantBiteSoundFrames[] = { 12, 28, 50, 64, -1 }; * Piranha Plant will move to the attacked state. */ void piranha_plant_act_biting(void) { - s32 frame = o->header.gfx.unk38.animFrame; + s32 frame = o->header.gfx.animInfo.animFrame; cur_obj_become_tangible(); @@ -277,9 +277,9 @@ void piranha_plant_act_biting(void) { * This is called from both the "stopped biting" state and the "sleeping" state. */ s32 mario_moving_fast_enough_to_make_piranha_plant_bite(void) { - if (gMarioStates->vel[1] > 10.0f) + if (gMarioStates[0].vel[1] > 10.0f) return 1; - if (gMarioStates->forwardVel > 10.0f) + if (gMarioStates[0].forwardVel > 10.0f) return 1; return 0; } diff --git a/src/game/behaviors/pole_base.inc.c b/src/game/behaviors/pole_base.inc.c index 3ae63fefb4..543fa28d0c 100644 --- a/src/game/behaviors/pole_base.inc.c +++ b/src/game/behaviors/pole_base.inc.c @@ -4,6 +4,6 @@ void bhv_pole_base_loop(void) { if (o->oPosY - 10.0f < gMarioObject->oPosY && gMarioObject->oPosY < o->oPosY + o->hitboxHeight + 30.0f) if (o->oTimer > 10) - if (!(gMarioStates->action & MARIO_PUNCHING)) + if (!(gMarioStates[0].action & MARIO_PUNCHING)) cur_obj_push_mario_away(70.0f); } diff --git a/src/game/behaviors/purple_switch.inc.c b/src/game/behaviors/purple_switch.inc.c index 3035bd6b5b..6d37030481 100644 --- a/src/game/behaviors/purple_switch.inc.c +++ b/src/game/behaviors/purple_switch.inc.c @@ -16,7 +16,7 @@ void bhv_purple_switch_loop(void) { case PURPLE_SWITCH_IDLE: cur_obj_set_model(MODEL_PURPLE_SWITCH); cur_obj_scale(1.5f); - if (gMarioObject->platform == o && !(gMarioStates->action & MARIO_UNKNOWN_13)) { + if (gMarioObject->platform == o && !(gMarioStates[0].action & MARIO_UNKNOWN_13)) { if (lateral_dist_between_objects(o, gMarioObject) < 127.5) { o->oAction = PURPLE_SWITCH_PRESSED; } diff --git a/src/game/behaviors/seaweed.inc.c b/src/game/behaviors/seaweed.inc.c index d1dc2b469e..4a9528d204 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 e40c7eff60..c714e91aed 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)) - gMarioObject->oInteractStatus |= - 0x10; // This is interact_coin, but the name sounds wrong in this behiavor + gMarioObject->oInteractStatus |= INT_STATUS_HIT_BY_SHOCKWAVE; } } diff --git a/src/game/behaviors/snowman.inc.c b/src/game/behaviors/snowman.inc.c index 174123d187..97374f9369 100644 --- a/src/game/behaviors/snowman.inc.c +++ b/src/game/behaviors/snowman.inc.c @@ -66,7 +66,8 @@ void snowmans_bottom_act_1(void) { if (sp20 == -1) { sp1E = (u16) o->oAngleToMario - (u16) o->oMoveAngleYaw; - if (obj_check_if_facing_toward_angle(o->oMoveAngleYaw, o->oAngleToMario, 0x2000) == 1 && o->oSnowmansBottomUnk1AC == 1) { + if (obj_check_if_facing_toward_angle(o->oMoveAngleYaw, o->oAngleToMario, 0x2000) == TRUE + && o->oSnowmansBottomUnk1AC == 1) { o->oSnowmansBottomUnkF8 = o->oAngleToMario; } else { o->oSnowmansBottomUnkF8 = o->oMoveAngleYaw; diff --git a/src/game/behaviors/thi_top.inc.c b/src/game/behaviors/thi_top.inc.c index 13b847b143..23c97a0634 100644 --- a/src/game/behaviors/thi_top.inc.c +++ b/src/game/behaviors/thi_top.inc.c @@ -19,7 +19,7 @@ void bhv_thi_tiny_island_top_loop(void) { if (!(gTHIWaterDrained & 1)) { if (o->oAction == 0) { if (o->oDistanceToMario < 500.0f) - if (gMarioStates->action == ACT_GROUND_POUND_LAND) { + if (gMarioStates[0].action == ACT_GROUND_POUND_LAND) { o->oAction++; cur_obj_spawn_particles(&D_8032F134); spawn_triangle_break_particles(20, 138, 0.3f, 3); diff --git a/src/game/behaviors/tweester.inc.c b/src/game/behaviors/tweester.inc.c index 69738145fc..67ad5f2da9 100644 --- a/src/game/behaviors/tweester.inc.c +++ b/src/game/behaviors/tweester.inc.c @@ -81,7 +81,7 @@ void tweester_act_chase(void) { cur_obj_rotate_yaw_toward(o->oAngleToMario, 0x200); print_debug_top_down_objectinfo("off ", 0); - if (gMarioStates->action == ACT_TWIRLING) + if (gMarioStates[0].action == ACT_TWIRLING) o->oSubAction++; } else { o->oForwardVel = 20.0f; diff --git a/src/game/behaviors/ukiki.inc.c b/src/game/behaviors/ukiki.inc.c index e7598253b7..2e6ce83630 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,12 +23,12 @@ 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) { - if (does_mario_have_hat(gMarioState)) { +s32 is_cap_ukiki_and_mario_has_normal_cap_on_head(void) { + if (o->oBehParams2ndByte == UKIKI_CAP) { + if (does_mario_have_normal_cap_on_head(gMarioState)) { return TRUE; } } @@ -124,7 +124,7 @@ void idle_ukiki_taunt(void) { 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 (o->oDistanceToMario > 700.0f && o->oDistanceToMario < 1000.0f) { o->oAction = UKIKI_ACT_RUN; } else if (o->oDistanceToMario <= 700.0f && 200.0f < o->oDistanceToMario) { @@ -140,8 +140,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 = gMarioObject->oMoveAngleYaw + 0x8000; if (check_if_moving_over_floor(50.0f, 150.0f)) { @@ -159,10 +159,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; } @@ -171,7 +171,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; @@ -232,7 +232,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 (o->oDistanceToMario > 500.0f) { o->oAction = UKIKI_ACT_RUN; } @@ -248,7 +248,7 @@ void ukiki_act_run(void) { s32 fleeMario = TRUE; s16 goalYaw = o->oAngleToMario + 0x8000; - if (is_hat_ukiki_and_mario_has_hat()) { + if (is_cap_ukiki_and_mario_has_normal_cap_on_head()) { fleeMario = FALSE; goalYaw = o->oAngleToMario; } @@ -488,7 +488,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); @@ -499,7 +499,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) { @@ -555,37 +555,37 @@ void cage_ukiki_held_loop(void) { } /** - * 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) { switch(o->oUkikiTextState) { case UKIKI_TEXT_DEFAULT: if (mario_lose_cap_to_enemy(2)) { - o->oUkikiTextState = UKIKI_TEXT_STEAL_HAT; - o->oUkikiHasHat |= UKIKI_HAT_ON; + o->oUkikiTextState = UKIKI_TEXT_STEAL_CAP; + o->oUkikiHasCap |= UKIKI_CAP_ON; } else {} break; - case UKIKI_TEXT_STEAL_HAT: + case UKIKI_TEXT_STEAL_CAP: if (cur_obj_update_dialog(2, 2, DIALOG_100, 0)) { o->oInteractionSubtype |= INT_SUBTYPE_DROP_IMMEDIATELY; - o->oUkikiTextState = UKIKI_TEXT_STOLE_HAT; + o->oUkikiTextState = UKIKI_TEXT_STOLE_CAP; } break; - case UKIKI_TEXT_STOLE_HAT: + case UKIKI_TEXT_STOLE_CAP: break; - case UKIKI_TEXT_HAS_HAT: + case UKIKI_TEXT_HAS_CAP: if (cur_obj_update_dialog(2, 18, DIALOG_101, 0)) { mario_retrieve_cap(); set_mario_npc_dialog(0); - o->oUkikiHasHat &= ~UKIKI_HAT_ON; - o->oUkikiTextState = UKIKI_TEXT_GAVE_HAT_BACK; + o->oUkikiHasCap &= ~UKIKI_CAP_ON; + o->oUkikiTextState = UKIKI_TEXT_GAVE_CAP_BACK; } break; - case UKIKI_TEXT_GAVE_HAT_BACK: + case UKIKI_TEXT_GAVE_CAP_BACK: o->oUkikiTextState = UKIKI_TEXT_DEFAULT; o->oAction = UKIKI_ACT_IDLE; break; @@ -593,20 +593,20 @@ 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) { - 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; } } } /** * 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) { switch(o->oHeldState) { @@ -620,8 +620,8 @@ void bhv_ukiki_loop(void) { cur_obj_unrender_and_reset_state(UKIKI_ANIM_HELD, 0); obj_copy_pos(o, gMarioObject); - if (o->oBehParams2ndByte == UKIKI_HAT) { - hat_ukiki_held_loop(); + if (o->oBehParams2ndByte == UKIKI_CAP) { + cap_ukiki_held_loop(); } else { cage_ukiki_held_loop(); } @@ -633,8 +633,8 @@ void bhv_ukiki_loop(void) { break; } - if (o->oUkikiHasHat & UKIKI_HAT_ON) { - o->oAnimState = UKIKI_ANIM_STATE_HAT_ON; + if (o->oUkikiHasCap & UKIKI_CAP_ON) { + o->oAnimState = UKIKI_ANIM_STATE_CAP_ON; } else { o->oAnimState = UKIKI_ANIM_STATE_DEFAULT; } diff --git a/src/game/behaviors/water_pillar.inc.c b/src/game/behaviors/water_pillar.inc.c index 801069cac6..046318d6c1 100644 --- a/src/game/behaviors/water_pillar.inc.c +++ b/src/game/behaviors/water_pillar.inc.c @@ -61,11 +61,11 @@ void water_level_pillar_drained(void) { void bhv_water_level_pillar_init(void) { if (save_file_get_flags() & SAVE_FLAG_MOAT_DRAINED) - o->oWaterLevelPillarUnkF8 = 1; + o->oWaterLevelPillarDrained = 1; } 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/water_splashes_and_waves.inc.c b/src/game/behaviors/water_splashes_and_waves.inc.c index c70a95ae19..cac575a195 100644 --- a/src/game/behaviors/water_splashes_and_waves.inc.c +++ b/src/game/behaviors/water_splashes_and_waves.inc.c @@ -85,7 +85,7 @@ void bhv_water_droplet_loop(void) { void bhv_idle_water_wave_loop(void) { obj_copy_pos(o, gMarioObject); - o->oPosY = gMarioStates->waterLevel + 5; + o->oPosY = gMarioStates[0].waterLevel + 5; if (!(gMarioObject->oMarioParticleFlags & ACTIVE_PARTICLE_IDLE_WATER_WAVE)) { gMarioObject->oActiveParticleFlags &= (u16)~ACTIVE_PARTICLE_IDLE_WATER_WAVE; o->activeFlags = ACTIVE_FLAG_DEACTIVATED; diff --git a/src/game/behaviors/whomp.inc.c b/src/game/behaviors/whomp.inc.c index 4192680849..477341846f 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 4c465f8097..18fd6e20a7 100644 --- a/src/game/behaviors/wiggler.inc.c +++ b/src/game/behaviors/wiggler.inc.c @@ -137,7 +137,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++) { @@ -145,7 +145,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 136a2bda04..bd4c4f317e 100644 --- a/src/game/behaviors/yoshi.inc.c +++ b/src/game/behaviors/yoshi.inc.c @@ -11,14 +11,15 @@ 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; } } 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(); @@ -41,7 +42,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; @@ -94,7 +95,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(); @@ -124,7 +125,7 @@ void yoshi_finish_jumping_and_despawn_loop(void) { if (o->oPosY < 2100.0f) { set_mario_npc_dialog(0); gObjCutsceneDone = TRUE; - sYoshiDead = 1; + sYoshiDead = TRUE; o->activeFlags = ACTIVE_FLAG_DEACTIVATED; } } @@ -134,7 +135,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 60bfb86584..8082ef5eb7 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -659,9 +659,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; @@ -786,10 +786,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; } @@ -1484,7 +1484,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]; @@ -1495,7 +1495,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; } @@ -1594,7 +1594,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; @@ -1610,7 +1610,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; } @@ -2268,7 +2268,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)) { @@ -2318,7 +2318,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; } @@ -2329,7 +2329,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); } @@ -2338,10 +2338,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); } @@ -2363,7 +2363,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; @@ -2461,7 +2461,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; } @@ -2984,7 +2984,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 { @@ -4277,7 +4277,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) { @@ -5456,7 +5456,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; } @@ -6687,19 +6687,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; @@ -6826,14 +6826,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; @@ -7352,7 +7352,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) { @@ -8687,7 +8687,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; } @@ -10060,7 +10060,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/debug.c b/src/game/debug.c index a39da00401..e735035deb 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 a43021244c..2a4d14bb5e 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -45,7 +45,7 @@ struct MarioAnimation D_80339D10; struct MarioAnimation gDemo; UNUSED u8 filler80339D30[0x90]; -int unused8032C690 = 0; +s32 unused8032C690 = 0; u32 gGlobalTimer = 0; static u16 sCurrFBNum = 0; @@ -278,7 +278,7 @@ void draw_reset_bars(void) { sp18 += D_8032C648++ * (SCREEN_WIDTH / 4); for (sp24 = 0; sp24 < ((SCREEN_HEIGHT / 16) + 1); sp24++) { - // Must be on one line to match -O2 + // Loop must be one line to match on -O2 for (sp20 = 0; sp20 < (SCREEN_WIDTH / 4); sp20++) *sp18++ = 0; sp18 += ((SCREEN_WIDTH / 4) * 14); } @@ -603,7 +603,7 @@ void thread5_game_loop(UNUSED void *arg) { set_sound_mode(save_file_get_sound_mode()); rendering_init(); - while (1) { + while (TRUE) { // if the reset timer is active, run the process to reset the game. if (gResetTimer) { draw_reset_bars(); diff --git a/src/game/geo_misc.c b/src/game/geo_misc.c index e1991503ee..2fb8c5efac 100644 --- a/src/game/geo_misc.c +++ b/src/game/geo_misc.c @@ -86,7 +86,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 cbcbdeb8dc..bfa44fa5a3 100644 --- a/src/game/hud.h +++ b/src/game/hud.h @@ -21,7 +21,6 @@ enum CameraHUDLut { GLYPH_CAM_ARROW_DOWN }; -// 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 b9a43df2e2..35df1cf90d 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -913,7 +913,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); @@ -1760,7 +1760,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) { @@ -2608,7 +2608,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 @@ -2639,7 +2639,7 @@ s16 render_pause_courses_and_castle(void) { || gPlayer3Controller->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; @@ -2666,7 +2666,7 @@ s16 render_pause_courses_and_castle(void) { || gPlayer3Controller->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; @@ -2757,7 +2757,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 { @@ -2771,7 +2771,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); } } @@ -2992,7 +2992,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; } @@ -3013,7 +3013,7 @@ s16 render_course_complete_screen(void) { || gPlayer3Controller->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 d27b48882f..3aab33a15a 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -132,10 +132,10 @@ static u8 sJustTeleported = FALSE; static u8 sPssSlideStarted = 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; @@ -149,6 +149,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. @@ -340,14 +341,14 @@ 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) { 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); @@ -367,7 +368,7 @@ void mario_blow_off_cap(struct MarioState *m, f32 capSpeed) { u32 mario_lose_cap_to_enemy(u32 arg) { u32 wasWearingCap = FALSE; - if (does_mario_have_hat(gMarioState)) { + if (does_mario_have_normal_cap_on_head(gMarioState)) { save_file_set_flags(arg == 1 ? SAVE_FLAG_CAP_ON_KLEPTO : SAVE_FLAG_CAP_ON_UKIKI); gMarioState->flags &= ~(MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD); wasWearingCap = TRUE; @@ -416,7 +417,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->input & INPUT_INTERACT_OBJ_GRABBABLE) { script = virtual_to_segmented(0x13, m->interactObj->behavior); @@ -702,6 +703,7 @@ u32 take_damage_from_interact_object(struct MarioState *m) { queue_rumble_data(5, 80); #endif set_camera_shake_from_hit(shake); + return damage; } @@ -819,7 +821,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) { @@ -1220,6 +1221,7 @@ u32 interact_clam_or_bubba(struct MarioState *m, UNUSED u32 interactType, struct if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { sDelayInvincTimer = TRUE; } + return TRUE; } @@ -1295,6 +1297,7 @@ u32 interact_shock(struct MarioState *m, UNUSED u32 interactType, struct Object if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { sDelayInvincTimer = TRUE; } + return FALSE; } @@ -1357,6 +1360,7 @@ u32 interact_hit_from_below(struct MarioState *m, UNUSED u32 interactType, struc if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { sDelayInvincTimer = TRUE; } + return FALSE; } @@ -1394,6 +1398,7 @@ u32 interact_bounce_top(struct MarioState *m, UNUSED u32 interactType, struct Ob if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { sDelayInvincTimer = TRUE; } + return FALSE; } @@ -1410,6 +1415,7 @@ u32 interact_unknown_08(struct MarioState *m, UNUSED u32 interactType, struct Ob if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { sDelayInvincTimer = TRUE; } + return FALSE; } @@ -1421,6 +1427,7 @@ u32 interact_damage(struct MarioState *m, UNUSED u32 interactType, struct Object if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { sDelayInvincTimer = TRUE; } + return FALSE; } @@ -1625,7 +1632,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 (o->oInteractionSubtype & INT_SUBTYPE_KICKABLE) { u32 interaction = determine_interaction(m, o); @@ -1653,6 +1660,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; } @@ -1668,7 +1676,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 4d1aba968b..dd27aad8ac 100644 --- a/src/game/interaction.h +++ b/src/game/interaction.h @@ -84,7 +84,7 @@ #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 */ @@ -104,7 +104,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(u32 arg); void mario_retrieve_cap(void); diff --git a/src/game/level_geo.c b/src/game/level_geo.c index 4c98e70520..1fc4b88e65 100644 --- a/src/game/level_geo.c +++ b/src/game/level_geo.c @@ -51,6 +51,7 @@ Gfx *geo_envfx_main(s32 callContext, struct GraphNode *node, Mat4 mtxf) { vec3s_copy(marioPos, gVec3sZero); envfx_update_particles(ENVFX_MODE_NONE, marioPos, camTo, camFrom); } + return gfx; } @@ -73,5 +74,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 5ecc48d050..0517cf4670 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -165,11 +165,11 @@ s32 sDelayedWarpArg; s16 unusedEULevelUpdateBss1; #endif s8 sTimerRunning; -s8 gShouldNotPlayCastleMusic; +s8 gNeverEnteredCastle; struct MarioState *gMarioState = &gMarioStates[0]; u8 unused1[4] = { 0 }; -s8 D_8032C9E0 = 0; +s8 sWarpCheckpointActive = FALSE; u8 unused3[4]; u8 unused4[2]; @@ -432,7 +432,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 @@ -663,7 +663,7 @@ void initiate_painting_warp(void) { warpNode = *pWarpNode; if (!(warpNode.destLevel & 0x80)) { - D_8032C9E0 = check_warp_checkpoint(&warpNode); + sWarpCheckpointActive = check_warp_checkpoint(&warpNode); } initiate_warp(warpNode.destLevel & 0x7F, warpNode.destArea, warpNode.destNode, 0); @@ -702,8 +702,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; @@ -885,7 +884,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; @@ -1073,7 +1072,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); @@ -1090,7 +1088,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; @@ -1167,7 +1164,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) { @@ -1186,7 +1183,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) { if (save_file_exists(gCurrSaveFileNum - 1)) { set_mario_action(gMarioState, ACT_IDLE, 0); @@ -1259,13 +1256,13 @@ 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); + gNeverEnteredCastle = !save_file_exists(gCurrSaveFileNum - 1); gCurrLevelNum = levelNum; gCurrCourseNum = COURSE_NONE; gSavedCourseNum = COURSE_NONE; gCurrCreditsEntry = NULL; - gSpecialTripleJump = 0; + gSpecialTripleJump = FALSE; init_mario_from_save_file(); disable_warp_checkpoint(); @@ -1277,9 +1274,9 @@ s32 lvl_init_from_save_file(UNUSED s16 arg0, s32 levelNum) { } s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum) { - s32 val4 = D_8032C9E0; + s32 warpCheckpointActive = sWarpCheckpointActive; - D_8032C9E0 = 0; + sWarpCheckpointActive = FALSE; gCurrLevelNum = levelNum; gCurrCourseNum = gLevelToCourseNumTable[levelNum - 1]; @@ -1300,11 +1297,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; } diff --git a/src/game/level_update.h b/src/game/level_update.h index ecf9c3a35e..521b4efee6 100644 --- a/src/game/level_update.h +++ b/src/game/level_update.h @@ -100,7 +100,7 @@ struct HudDisplay { }; extern struct HudDisplay gHudDisplay; -extern s8 gShouldNotPlayCastleMusic; +extern s8 gNeverEnteredCastle; enum HUDDisplayFlag { HUD_DISPLAY_FLAG_LIVES = 0x0001, diff --git a/src/game/macro_special_objects.c b/src/game/macro_special_objects.c index 0b3bb3c429..c280352f0c 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 7743df1157..c545c63c53 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 9e53e50b2a..a185fef913 100644 --- a/src/game/main.c +++ b/src/game/main.c @@ -61,11 +61,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; @@ -254,7 +254,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(); @@ -298,7 +298,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(); @@ -349,7 +349,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); @@ -394,7 +394,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); } @@ -415,11 +415,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) { ; } @@ -456,7 +456,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 5b103fa2d9..7edc2eb37d 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -2,7 +2,6 @@ #include "sm64.h" #include "area.h" -#include "audio/data.h" #include "audio/external.h" #include "behavior_actions.h" #include "behavior_data.h" @@ -47,7 +46,7 @@ s8 filler80339F1C[20]; s32 is_anim_at_end(struct MarioState *m) { struct Object *o = m->marioObj; - return (o->header.gfx.unk38.animFrame + 1) == o->header.gfx.unk38.curAnim->unk08; + return (o->header.gfx.animInfo.animFrame + 1) == o->header.gfx.animInfo.curAnim->loopEnd; } /** @@ -56,7 +55,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); } /** @@ -71,24 +70,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; } /** @@ -104,34 +103,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) { @@ -152,7 +151,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) { @@ -184,8 +183,8 @@ 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; - s16 animFrame = geo_update_animation_frame(&obj->header.gfx.unk38, NULL); + struct Animation *curAnim = (void *) obj->header.gfx.animInfo.curAnim; + 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); @@ -239,7 +238,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; } @@ -261,7 +260,6 @@ void play_mario_jump_sound(struct MarioState *m) { #ifndef VERSION_JP } #endif - m->flags |= MARIO_MARIO_SOUND_PLAYED; } } @@ -304,7 +302,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; } @@ -324,8 +322,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); } /** @@ -351,9 +349,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); } @@ -399,7 +396,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: @@ -465,7 +462,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))) { @@ -610,26 +607,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; } @@ -650,19 +646,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; } @@ -780,10 +776,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) { @@ -793,7 +788,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; @@ -825,7 +820,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; @@ -846,7 +841,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; @@ -866,7 +861,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; @@ -1186,7 +1181,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; } @@ -1287,7 +1282,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; } } @@ -1338,7 +1333,7 @@ void update_mario_geometry_inputs(struct MarioState *m) { 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); @@ -1400,7 +1395,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; } @@ -1428,7 +1423,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 (camPreset != CAMERA_MODE_CLOSE) { set_camera_mode(m->area->camera, CAMERA_MODE_CLOSE, 1); } @@ -1443,7 +1438,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; } @@ -1461,12 +1456,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), @@ -1474,7 +1469,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); } } @@ -1490,7 +1485,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) { @@ -1523,7 +1518,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); } } @@ -1584,23 +1579,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; } } @@ -1628,13 +1621,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) { - gMarioState->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)) { + gMarioState->marioObj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE; } if (flags & MARIO_CAP_IN_HAND) { @@ -1675,7 +1666,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) { @@ -1810,7 +1801,7 @@ void init_mario(void) { | SAVE_FLAG_CAP_ON_MR_BLIZZARD)) { gMarioState->flags = 0; } else { - gMarioState->flags = (MARIO_CAP_ON_HEAD | MARIO_NORMAL_CAP); + gMarioState->flags = (MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD); } gMarioState->forwardVel = 0.0f; @@ -1831,7 +1822,7 @@ void init_mario(void) { gMarioState->area = gCurrentArea; gMarioState->marioObj = gMarioObject; - gMarioState->marioObj->header.gfx.unk38.animID = -1; + gMarioState->marioObj->header.gfx.animInfo.animID = -1; vec3s_copy(gMarioState->faceAngle, gMarioSpawnInfo->startAngle); vec3s_set(gMarioState->angleVel, 0, 0, 0); vec3s_to_vec3f(gMarioState->pos, gMarioSpawnInfo->startPos); diff --git a/src/game/mario_actions_airborne.c b/src/game/mario_actions_airborne.c index a9f00890c8..ae0ee4d4b9 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" @@ -16,7 +15,7 @@ #include "thread6.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); } @@ -605,9 +604,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; } @@ -935,7 +934,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_sound(SOUND_MARIO_GROUND_POUND_WAH, m->marioObj->header.gfx.cameraToObject); m->actionState = 1; } @@ -1149,7 +1148,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 @@ -1163,7 +1162,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 @@ -1240,7 +1239,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 @@ -1339,10 +1338,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) { @@ -1421,7 +1419,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; @@ -1628,12 +1626,12 @@ s32 act_jump_kick(struct MarioState *m) { if (m->actionState == 0) { play_sound_if_no_flag(m, SOUND_MARIO_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; } @@ -1744,7 +1742,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); } } @@ -1900,7 +1898,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); } @@ -1913,7 +1911,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); } @@ -1967,7 +1965,7 @@ s32 act_vertical_wind(struct MarioState *m) { play_sound_if_no_flag(m, SOUND_MARIO_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); #ifdef VERSION_SH queue_rumble_data(8, 80); diff --git a/src/game/mario_actions_automatic.c b/src/game/mario_actions_automatic.c index ee6720bd07..76dc5c4186 100644 --- a/src/game/mario_actions_automatic.c +++ b/src/game/mario_actions_automatic.c @@ -17,13 +17,13 @@ #include "level_table.h" #include "thread6.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; @@ -143,7 +143,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); @@ -250,7 +250,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); } @@ -272,7 +272,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); } } @@ -468,7 +468,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); #ifdef VERSION_SH queue_rumble_data(5, 30); @@ -570,7 +570,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)) @@ -619,7 +619,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; } @@ -648,7 +648,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); @@ -749,13 +749,11 @@ s32 act_in_cannon(struct MarioState *m) { #endif m->usedObj->oAction = 2; return FALSE; - } else { - if (m->faceAngle[0] != startFacePitch || m->faceAngle[1] != startFaceYaw) { - play_sound(SOUND_MOVING_AIM_CANNON, m->marioObj->header.gfx.cameraToObject); + } else if (m->faceAngle[0] != startFacePitch || m->faceAngle[1] != startFaceYaw) { + play_sound(SOUND_MOVING_AIM_CANNON, m->marioObj->header.gfx.cameraToObject); #ifdef VERSION_SH - reset_rumble_timers_2(0); + reset_rumble_timers_2(0); #endif - } } } diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index 3817fd19d7..8d9f515e7b 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" @@ -49,7 +48,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 }; /** * Data for the jumbo star cutscene. It specifies the flight path after triple @@ -235,7 +234,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; @@ -422,8 +421,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; @@ -478,8 +477,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) { @@ -536,7 +535,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; @@ -591,7 +589,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) { @@ -682,7 +679,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) { @@ -700,7 +696,7 @@ s32 act_standing_death(struct MarioState *m) { play_sound_if_no_flag(m, SOUND_MARIO_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; @@ -793,7 +789,7 @@ s32 act_unlocking_key_door(struct MarioState *m) { 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; @@ -861,7 +857,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; @@ -944,13 +939,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++; @@ -966,7 +959,7 @@ s32 act_warp_door_spawn(struct MarioState *m) { m->usedObj->oInteractStatus = 0x00080000; } } else if (m->usedObj->oAction == 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); @@ -1344,7 +1337,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 { @@ -1523,7 +1516,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); #ifdef VERSION_SH queue_rumble_data(10, 80); @@ -2583,7 +2576,7 @@ static s32 act_credits_cutscene(struct MarioState *m) { } if (m->actionTimer++ == TIMER_CREDITS_WARP) { - level_trigger_warp(m, 24); + level_trigger_warp(m, WARP_OP_CREDITS_NEXT); } m->marioObj->header.gfx.angle[1] += (gCurrCreditsEntry->unk02 & 0xC0) << 8; @@ -2701,10 +2694,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 7dd3097103..51b8143b26 100644 --- a/src/game/mario_actions_moving.c +++ b/src/game/mario_actions_moving.c @@ -70,14 +70,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); @@ -114,22 +114,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); } } } @@ -155,7 +153,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) { @@ -698,7 +696,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; } @@ -713,7 +711,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; @@ -1204,7 +1202,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); @@ -1363,9 +1361,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); #ifdef VERSION_SH @@ -1592,7 +1590,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); @@ -1615,8 +1613,8 @@ s32 common_ground_knockback_action(struct MarioState *m, s32 animation, s32 arg2 m->forwardVel = -32.0f; } - 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); @@ -1641,23 +1639,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_sound(SOUND_MARIO_MAMA_MIA, m->marioObj->header.gfx.cameraToObject); } #endif - if (val04 == 0x45) { + if (animFrame == 69) { play_mario_landing_sound_once(m, SOUND_ACTION_TERRAIN_LANDING); } @@ -1665,8 +1663,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); } @@ -1674,45 +1673,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_sound(SOUND_MARIO_MAMA_MIA, m->marioObj->header.gfx.cameraToObject); } - 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 2c6099a2e9..391a7a98d7 100644 --- a/src/game/mario_actions_object.c +++ b/src/game/mario_actions_object.c @@ -47,7 +47,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; } @@ -63,7 +63,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; } @@ -87,7 +87,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; } @@ -98,7 +98,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; } @@ -130,7 +130,7 @@ s32 mario_update_punch_sequence(struct MarioState *m) { case 9: play_mario_action_sound(m, SOUND_MARIO_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 3791d11318..7a3ccd069b 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" @@ -57,7 +56,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) { @@ -100,7 +99,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) { @@ -117,7 +116,7 @@ s32 act_idle(struct MarioState *m) { } if (check_common_idle_cancels(m)) { - return 1; + return TRUE; } if (m->actionState == 3) { @@ -170,22 +169,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) { @@ -199,35 +198,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; } @@ -241,16 +236,12 @@ s32 act_start_sleeping(struct MarioState *m) { } #ifndef VERSION_JP - if (m->actionState == 2) { - if (sp24 == -1) { - play_sound(SOUND_MARIO_YAWNING, m->marioObj->header.gfx.cameraToObject); - } + if (m->actionState == 2 && animFrame == -1) { + play_sound(SOUND_MARIO_YAWNING, m->marioObj->header.gfx.cameraToObject); } - if (m->actionState == 1) { - if (sp24 == -1) { - play_sound(SOUND_MARIO_IMA_TIRED, m->marioObj->header.gfx.cameraToObject); - } + if (m->actionState == 1 && animFrame == -1) { + play_sound(SOUND_MARIO_IMA_TIRED, m->marioObj->header.gfx.cameraToObject); } #else if (m->actionState == 2) { @@ -259,12 +250,14 @@ s32 act_start_sleeping(struct MarioState *m) { #endif stationary_ground_step(m); - return 0; + return FALSE; } s32 act_sleeping(struct MarioState *m) { - s32 sp24; - if (m->input & INPUT_UNKNOWN_A41F /* ? */) { + s32 animFrame; + 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); } @@ -279,18 +272,18 @@ 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 (sp24 == -1 && !m->actionTimer) { + if (animFrame == -1 && !m->actionTimer) { lower_background_noise(2); } - if (sp24 == 2) { + if (animFrame == 2) { play_sound(SOUND_MARIO_SNORING1, m->marioObj->header.gfx.cameraToObject); } - if (sp24 == 20) { + if (animFrame == 20) { play_sound(SOUND_MARIO_SNORING2, m->marioObj->header.gfx.cameraToObject); } @@ -301,8 +294,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); } @@ -311,24 +304,23 @@ 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_sound_if_no_flag(m, SOUND_MARIO_SNORING3, MARIO_ACTION_SOUND_PLAYED); #else - if (sp24 == 2) { + if (animFrame == 2) { play_sound(SOUND_MARIO_SNORING2, m->marioObj->header.gfx.cameraToObject); } - if (sp24 == 25) { + if (animFrame == 25) { play_sound(SOUND_MARIO_SNORING1, m->marioObj->header.gfx.cameraToObject); } #endif break; - } } - return 0; + return FALSE; } s32 act_waking_up(struct MarioState *m) { @@ -363,11 +355,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); @@ -381,66 +373,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_sound(SOUND_MARIO_PANTING_COLD, m->marioObj->header.gfx.cameraToObject); } - 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_sound(SOUND_MARIO_COUGHING3, m->marioObj->header.gfx.cameraToObject); } - if (sp1C == 0x32 || sp1C == 0x3A) { + if (animFrame == 50 || animFrame == 58) { play_sound(SOUND_MARIO_COUGHING2, m->marioObj->header.gfx.cameraToObject); } - if (sp1C == 0x47 || sp1C == 0x50) { + if (animFrame == 71 || animFrame == 80) { play_sound(SOUND_MARIO_COUGHING1, m->marioObj->header.gfx.cameraToObject); } - return 0; + return FALSE; } s32 act_hold_idle(struct MarioState *m) { @@ -457,12 +450,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) { @@ -488,7 +481,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) { @@ -510,7 +503,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) { @@ -518,8 +511,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) { @@ -529,7 +522,7 @@ s32 act_in_quicksand(struct MarioState *m) { } stationary_ground_step(m); - return 0; + return FALSE; } s32 act_crouching(struct MarioState *m) { @@ -567,7 +560,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) { @@ -580,7 +573,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) { @@ -590,7 +583,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) { @@ -606,20 +599,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); } } @@ -643,7 +636,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) { @@ -656,11 +649,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) { @@ -681,7 +674,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) { @@ -694,7 +687,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) { @@ -719,7 +712,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) { @@ -744,7 +737,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) { @@ -770,7 +763,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) { @@ -791,14 +784,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) { #ifdef VERSION_SH queue_rumble_data(70, 40); #endif @@ -814,11 +807,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); @@ -831,7 +824,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) { @@ -840,7 +833,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) { @@ -868,90 +861,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) { @@ -972,7 +964,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) { @@ -992,7 +984,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) { @@ -1009,7 +1001,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) { @@ -1034,14 +1026,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) { @@ -1059,43 +1049,35 @@ 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) { 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) { - 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) { + 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) { @@ -1112,72 +1094,70 @@ 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; } /* 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; } /* 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 a4633c7c52..c4b4c06932 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 72e845f516..cae02fab66 100644 --- a/src/game/mario_actions_submerged.c +++ b/src/game/mario_actions_submerged.c @@ -480,9 +480,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); } @@ -920,7 +920,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) { level_trigger_warp(m, WARP_OP_DEATH); } break; @@ -1257,7 +1257,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 e6354e89a0..0d9c0e1eb6 100644 --- a/src/game/mario_misc.c +++ b/src/game/mario_misc.c @@ -88,7 +88,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)); @@ -101,9 +101,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; } } @@ -111,14 +111,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(); } } } @@ -126,7 +124,7 @@ static void toad_message_opaque(void) { static void toad_message_talking(void) { if (cur_obj_update_dialog_with_cutscene(3, 1, CUTSCENE_DIALOG, gCurrentObject->oToadMessageDialogId) != 0) { - gCurrentObject->oToadMessageRecentlyTalked = 1; + gCurrentObject->oToadMessageRecentlyTalked = TRUE; gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADING; switch (gCurrentObject->oToadMessageDialogId) { case TOAD_STAR_1_DIALOG: @@ -182,33 +180,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 { @@ -347,7 +345,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; } @@ -527,7 +525,7 @@ 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 (gBodyStates[asGenerated->parameter >> 1].wingFlutter == FALSE) { + if (!gBodyStates[asGenerated->parameter >> 1].wingFlutter) { rotX = (coss((gAreaUpdateCounter & 0xF) << 12) + 1.0f) * 4096.0f; } else { rotX = (coss((gAreaUpdateCounter & 7) << 13) + 1.0f) * 6144.0f; @@ -588,7 +586,7 @@ Gfx *geo_switch_mario_hand_grab_pos(s32 callContext, struct GraphNode *b, Mat4 * */ Gfx *geo_render_mirror_mario(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c) { f32 mirroredX; - struct Object *mario = gMarioStates->marioObj; + struct Object *mario = gMarioStates[0].marioObj; switch (callContext) { case GEO_CONTEXT_CREATE: @@ -604,24 +602,19 @@ 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.sharedChild = mario->header.gfx.sharedChild; - gMirrorMario.unk18 = mario->header.gfx.unk18; + gMirrorMario.areaIndex = mario->header.gfx.areaIndex; vec3s_copy(gMirrorMario.angle, mario->header.gfx.angle); vec3f_copy(gMirrorMario.pos, mario->header.gfx.pos); vec3f_copy(gMirrorMario.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.unk38 = *(struct GraphNodeObject_sub *) &mario->header.gfx.unk38.animID; + + gMirrorMario.animInfo = mario->header.gfx.animInfo; mirroredX = MIRROR_X - gMirrorMario.pos[0]; gMirrorMario.pos[0] = mirroredX + MIRROR_X; gMirrorMario.angle[1] = -gMirrorMario.angle[1]; gMirrorMario.scale[0] *= -1.0f; - // FIXME: Why doesn't this match? - // gMirrorMario.node.flags |= 1; - ((s16 *) &gMirrorMario)[1] |= 1; + ((struct GraphNode *) &gMirrorMario)->flags |= 1; } else { - // FIXME: Why doesn't this match? - // gMirrorMario.node.flags &= ~1; - ((s16 *) &gMirrorMario)[1] &= ~1; + ((struct GraphNode *) &gMirrorMario)->flags &= ~1; } break; } diff --git a/src/game/mario_step.c b/src/game/mario_step.c index ba8315ca19..58698454b0 100644 --- a/src/game/mario_step.c +++ b/src/game/mario_step.c @@ -152,7 +152,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) { @@ -181,10 +181,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) { @@ -214,10 +214,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) { @@ -352,7 +352,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]; @@ -361,7 +361,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 @@ -371,7 +371,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); @@ -382,7 +382,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 5a17ae934a..984d4a7619 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -21,7 +21,7 @@ struct MainPoolState { u32 freeSpace; struct MainPoolBlock *listHeadL; struct MainPoolBlock *listHeadR; - void *prev; + struct MainPoolState *prev; }; struct MainPoolBlock { @@ -29,17 +29,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; @@ -90,8 +90,9 @@ void *virtual_to_segmented(u32 segment, const void *addr) { void move_segment_table_to_dmem(void) { s32 i; - for (i = 0; i < 16; i++) + for (i = 0; i < 16; i++) { gSPSegment(gDisplayListHead++, i, sSegmentTable[i]); + } } #else void *segmented_to_virtual(const void *addr) { @@ -157,7 +158,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) { @@ -212,7 +214,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; @@ -434,13 +436,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; @@ -453,7 +455,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); @@ -481,20 +483,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 4946508b46..0ef991e472 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 2c48174e31..c2dac3e9c7 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -107,7 +107,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); @@ -212,12 +212,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; } @@ -681,9 +681,9 @@ s8 current_mario_room_check(s16 room) { s16 trigger_obj_dialog_when_facing(s32 *inDialog, s16 dialogID, f32 dist, s32 actionArg) { s16 dialogueResponse; - if ((is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, (s32) dist) == 1 - && obj_check_if_facing_toward_angle(o->oFaceAngleYaw, gMarioObject->header.gfx.angle[1] + 0x8000, 0x1000) == 1 - && obj_check_if_facing_toward_angle(o->oMoveAngleYaw, o->oAngleToMario, 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, gMarioObject->header.gfx.angle[1] + 0x8000, 0x1000) == TRUE + && obj_check_if_facing_toward_angle(o->oMoveAngleYaw, o->oAngleToMario, 0x1000) == TRUE) || (*inDialog == 1)) { *inDialog = 1; @@ -709,8 +709,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; @@ -783,7 +782,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] & gPlayer3Controller->buttonPressed) != 0) { + if (debugInputSequence[sDebugSequenceTracker] & gPlayer3Controller->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 28461d5dfc..0b8a629eb2 100644 --- a/src/game/obj_behaviors_2.c +++ b/src/game/obj_behaviors_2.c @@ -362,7 +362,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; } @@ -759,7 +759,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(); } @@ -778,7 +778,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(); } @@ -932,19 +932,17 @@ static void treat_far_home_as_mario(f32 threshold) { #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. */ void 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; } } diff --git a/src/game/object_collision.c b/src/game/object_collision.c index 71f3268b9b..c8d867aec5 100644 --- a/src/game/object_collision.c +++ b/src/game/object_collision.c @@ -22,7 +22,7 @@ struct Object *debug_print_obj_collision(struct Object *a) { return NULL; } -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; @@ -59,7 +59,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 2cc022484a..0d86000b88 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -27,7 +27,7 @@ #include "spawn_object.h" #include "spawn_sound.h" -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 }; @@ -203,11 +203,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]; @@ -386,7 +384,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); @@ -532,8 +530,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; geo_obj_init((struct GraphNodeObject *) &obj->header.gfx, gLoadedGraphNodes[model], gVec3fZero, gVec3sZero); @@ -542,9 +540,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; @@ -565,9 +562,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); @@ -596,10 +592,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; @@ -678,11 +672,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; @@ -726,7 +718,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]); @@ -967,42 +958,40 @@ void cur_obj_set_vel_from_mario_vel(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; - - if (spC & 0x01) { - if (sp4 + 1 == sp8) { - sp0 = TRUE; - } + 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 (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; @@ -1010,7 +999,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; @@ -1020,7 +1009,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; @@ -1030,7 +1019,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) { @@ -1527,7 +1516,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) { @@ -1579,7 +1568,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; } } @@ -1657,21 +1646,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; - - if (spC < 0) { - spC = 0; - } else if (sp8 - 1 == spC) { - spC = 0; + s32 animFrame = o->header.gfx.animInfo.animFrame; + s32 loopEnd = o->header.gfx.animInfo.curAnim->loopEnd; + s32 result; + + 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) { @@ -1680,7 +1669,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); @@ -1725,14 +1714,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) { @@ -1824,7 +1813,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)); @@ -2161,11 +2150,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; } } @@ -2222,7 +2211,7 @@ void cur_obj_push_mario_away(f32 radius) { void cur_obj_push_mario_away_from_cylinder(f32 radius, f32 extentY) { f32 marioRelY = gMarioObject->oPosY - o->oPosY; - if (marioRelY < 0) { + if (marioRelY < 0.0f) { marioRelY = -marioRelY; } @@ -2323,11 +2312,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)) { @@ -2550,12 +2539,9 @@ void clear_time_stop_flags(s32 flags) { } s32 cur_obj_can_mario_activate_textbox(f32 radius, f32 height, UNUSED s32 unused) { - f32 latDistToMario; - UNUSED s16 angleFromMario; - if (o->oDistanceToMario < 1500.0f) { - latDistToMario = lateral_dist_between_objects(o, gMarioObject); - angleFromMario = obj_angle_to_object(gMarioObject, o); + f32 latDistToMario = lateral_dist_between_objects(o, gMarioObject); + UNUSED s16 angleFromMario = obj_angle_to_object(gMarioObject, o); if (latDistToMario < radius && o->oPosY < gMarioObject->oPosY + 160.0f && gMarioObject->oPosY < o->oPosY + height && !(gMarioStates[0].action & ACT_FLAG_AIR) @@ -2693,7 +2679,7 @@ s32 cur_obj_update_dialog_with_cutscene(s32 actionArg, s32 dialogFlags, s32 cuts 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, gMarioObject), 0x800); - if (o->oDialogResponse >= 0x21) { + if (o->oDialogResponse >= 33) { doneTurning = TRUE; } } @@ -2822,7 +2808,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 7113e7c816..d01f5eb4e2 100644 --- a/src/game/object_list_processor.c +++ b/src/game/object_list_processor.c @@ -440,7 +440,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); } } @@ -455,7 +455,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 205a9eac0f..83bd2ce945 100644 --- a/src/game/paintings.c +++ b/src/game/paintings.c @@ -577,7 +577,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 29a741c23d..9153bc4db0 100644 --- a/src/game/platform_displacement.c +++ b/src/game/platform_displacement.c @@ -86,7 +86,7 @@ void set_mario_pos(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 isMario, struct Object *platform) { f32 x; @@ -169,11 +169,10 @@ void apply_platform_displacement(u32 isMario, struct Object *platform) { * If Mario's platform is not null, apply platform displacement. */ void apply_mario_platform_displacement(void) { - struct Object *platform; + struct Object *platform = gMarioPlatform; - platform = gMarioPlatform; if (!(gTimeStopState & TIME_STOP_ACTIVE) && gMarioObject != NULL && platform != NULL) { - apply_platform_displacement(1, platform); + apply_platform_displacement(TRUE, platform); } } diff --git a/src/game/print.c b/src/game/print.c index ca5615b975..e597227152 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 bd6f5660cd..58238e83f1 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -487,7 +487,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); } } @@ -508,7 +508,7 @@ static void geo_process_background(struct GraphNodeBackground *node) { 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); } else if (gCurGraphNodeMasterList != NULL) { #ifndef F3DEX_GBI_2E @@ -602,10 +602,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; @@ -624,10 +624,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; } } @@ -659,7 +659,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; @@ -694,7 +694,7 @@ static void geo_process_shadow(struct GraphNodeShadow *node) { mtxf_mul(gMatStack[gMatStackIndex], mtxf, *gCurGraphNodeCamera->matrixPtr); mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); gMatStackFixed[gMatStackIndex] = mtx; - if (gShadowAboveWaterOrLava == 1) { + if (gShadowAboveWaterOrLava == TRUE) { geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(shadowList), 4); } else if (gMarioOnIceOrCarpet == 1) { geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(shadowList), 5); @@ -740,7 +740,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; @@ -805,7 +805,7 @@ static void geo_process_object(struct Object *node) { Mat4 mtxf; s32 hasAnimation = (node->header.gfx.node.flags & GRAPH_RENDER_HAS_ANIMATION) != 0; - 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]); @@ -825,8 +825,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)); @@ -912,8 +912,8 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { gGeoTempState.data = gCurAnimData; 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 4748b998b8..9ef0b63bad 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -27,10 +27,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, @@ -364,7 +364,7 @@ void save_file_collect_star_or_key(s16 coinScore, s16 starIndex) { gLastCompletedCourseNum = courseIndex + 1; gLastCompletedStarNum = starIndex + 1; sUnusedGotGlobalCoinHiScore = 0; - gGotFileCoinHiScore = 0; + gGotFileCoinHiScore = FALSE; if (courseIndex >= 0 && courseIndex < COURSE_STAGES_COUNT) { //! Compares the coin score as a 16 bit value, but only writes the 8 bit @@ -378,7 +378,7 @@ void save_file_collect_star_or_key(s16 coinScore, s16 starIndex) { gSaveBuffer.files[fileIndex][0].courseCoinScores[courseIndex] = coinScore; touch_coin_score_age(fileIndex, courseIndex); - gGotFileCoinHiScore = 1; + gGotFileCoinHiScore = TRUE; gSaveFileModified = TRUE; } } @@ -475,7 +475,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; @@ -489,7 +489,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; } @@ -503,7 +503,7 @@ 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; + gSaveBuffer.files[fileIndex][0].flags |= STAR_FLAG_TO_SAVE_FLAG(starFlags); } else { gSaveBuffer.files[fileIndex][0].courseStars[courseIndex] |= starFlags; } @@ -620,7 +620,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. @@ -629,11 +629,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 3ee5a19ac6..ae6fcf35d5 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 3673a1a819..5d36905c10 100644 --- a/src/game/screen_transition.c +++ b/src/game/screen_transition.c @@ -206,7 +206,7 @@ s32 render_textured_transition(s8 fadeTimer, s8 transTime, struct WarpTransition return set_and_reset_transition_fade_timer(fadeTimer, transTime); } -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 aeee7fc822..70b3c21a00 100644 --- a/src/game/screen_transition.h +++ b/src/game/screen_transition.h @@ -21,7 +21,7 @@ enum TextureTransitionType TRANS_TYPE_CLAMP }; -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 5ff6bedaa7..aeae215e8a 100644 --- a/src/game/shadow.c +++ b/src/game/shadow.c @@ -424,7 +424,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; } @@ -540,8 +540,8 @@ s8 correct_shadow_solidity_for_animations(s32 isLuigi, u8 initialSolidity, struc break; } - 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 755fae5b3c..1cf58f5c4e 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) */ -int 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 @@ -155,7 +155,7 @@ int 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. */ -int 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; @@ -179,7 +179,7 @@ int 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 4718c4528d..c1717e63ab 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; @@ -166,13 +166,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; } } @@ -200,13 +200,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; } @@ -266,7 +266,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 a8f52f7205..f0b18bac14 100644 --- a/src/game/spawn_sound.c +++ b/src/game/spawn_sound.c @@ -93,7 +93,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; @@ -108,7 +108,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 a39067962d..ce05c2105f 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 5e0d01cf1c..192d9fad7d 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 716e07b488..9c32134375 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 df28306a96..f9f962ac9e 100644 --- a/src/menu/file_select.c +++ b/src/menu/file_select.c @@ -42,7 +42,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 @@ -118,7 +118,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; @@ -139,7 +139,7 @@ static 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 @@ -1708,7 +1708,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 @@ -2495,7 +2495,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 359677eb76..d4d75b6574 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 c1a6ec608b..2746218ae3 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) { @@ -125,7 +125,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); @@ -134,7 +134,7 @@ s16 level_select_input_loop(void) { return 0; } -int intro_default(void) { +s32 intro_default(void) { s32 sp1C = 0; #ifndef VERSION_JP @@ -150,19 +150,16 @@ int intro_default(void) { print_intro_text(); if (gPlayer1Controller->buttonPressed & START_BUTTON) { -#ifdef VERSION_JP - play_sound(SOUND_MENU_STAR_SOUND, gDefaultSoundArgs); - sp1C = 100 + gDebugLevelSelect; -#else play_sound(SOUND_MENU_STAR_SOUND, gDefaultSoundArgs); sp1C = 100 + gDebugLevelSelect; +#ifndef VERSION_JP D_U_801A7C34 = 1; #endif } return run_press_start_demo_timer(sp1C); } -int intro_game_over(void) { +s32 intro_game_over(void) { s32 sp1C = 0; #ifndef VERSION_JP @@ -184,7 +181,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/tools/asm_processor/asm-processor.py b/tools/asm_processor/asm-processor.py index b7ddbdf26c..04b94316b6 100644 --- a/tools/asm_processor/asm-processor.py +++ b/tools/asm_processor/asm-processor.py @@ -6,8 +6,11 @@ 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 @@ def lookup_str(self, index): 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 @@ def find_symbol(self, name): 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 @@ def pad_out(align): 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 @@ def __init__(self): '.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 @@ def process_line(self, line): 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 @@ def process_line(self, line): # 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 @@ def finish(self, state): # 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 @@ def finish(self, state): 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 @@ def finish(self, state): 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']) - - 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']), - }) + src[self.num_lines] += ' char {}[{}];'.format(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:])