byte/flag stuff

This commit is contained in:
Ethan Roseman 2020-09-19 11:16:02 -04:00
parent 084a0ab0b6
commit 4e6a401484
15 changed files with 450 additions and 260 deletions

View File

@ -1,16 +0,0 @@
.set noat # allow manual use of $at
.set noreorder # don't insert nops after branches
glabel get_area_byte
/* 0DBD50 80145650 3C02800E */ lui $v0, 0x800e
/* 0DBD54 80145654 00441021 */ addu $v0, $v0, $a0
/* 0DBD58 80145658 8042BF90 */ lb $v0, -0x4070($v0)
/* 0DBD5C 8014565C 03E00008 */ jr $ra
/* 0DBD60 80145660 00000000 */ nop
/* 0DBD64 80145664 00000000 */ nop
/* 0DBD68 80145668 00000000 */ nop
/* 0DBD6C 8014566C 00000000 */ nop

View File

@ -1,26 +0,0 @@
.set noat # allow manual use of $at
.set noreorder # don't insert nops after branches
glabel get_area_flag
/* 0DBCF0 801455F0 0080102D */ daddu $v0, $a0, $zero
/* 0DBCF4 801455F4 04410002 */ bgez $v0, .L80145600
/* 0DBCF8 801455F8 0040182D */ daddu $v1, $v0, $zero
/* 0DBCFC 801455FC 2443001F */ addiu $v1, $v0, 0x1f
.L80145600:
/* 0DBD00 80145600 00031943 */ sra $v1, $v1, 5
/* 0DBD04 80145604 00032140 */ sll $a0, $v1, 5
/* 0DBD08 80145608 00442023 */ subu $a0, $v0, $a0
/* 0DBD0C 8014560C 00031880 */ sll $v1, $v1, 2
/* 0DBD10 80145610 24020001 */ addiu $v0, $zero, 1
/* 0DBD14 80145614 3C01800E */ lui $at, 0x800e
/* 0DBD18 80145618 00230821 */ addu $at, $at, $v1
/* 0DBD1C 8014561C 8C23BF70 */ lw $v1, -0x4090($at)
/* 0DBD20 80145620 00821004 */ sllv $v0, $v0, $a0
/* 0DBD24 80145624 00621024 */ and $v0, $v1, $v0
/* 0DBD28 80145628 54400001 */ bnel $v0, $zero, .L80145630
/* 0DBD2C 8014562C 24020001 */ addiu $v0, $zero, 1
.L80145630:
/* 0DBD30 80145630 03E00008 */ jr $ra
/* 0DBD34 80145634 00000000 */ nop

View File

@ -1,11 +0,0 @@
.set noat # allow manual use of $at
.set noreorder # don't insert nops after branches
glabel get_global_byte
/* 0DBC38 80145538 3C02800E */ lui $v0, 0x800e
/* 0DBC3C 8014553C 00441021 */ addu $v0, $v0, $a0
/* 0DBC40 80145540 8042BD70 */ lb $v0, -0x4290($v0)
/* 0DBC44 80145544 03E00008 */ jr $ra
/* 0DBC48 80145548 00000000 */ nop

View File

@ -1,12 +0,0 @@
.set noat # allow manual use of $at
.set noreorder # don't insert nops after branches
glabel set_area_byte
/* 0DBD38 80145638 3C02800E */ lui $v0, 0x800e
/* 0DBD3C 8014563C 2442ACC0 */ addiu $v0, $v0, -0x5340
/* 0DBD40 80145640 00822021 */ addu $a0, $a0, $v0
/* 0DBD44 80145644 808212D0 */ lb $v0, 0x12d0($a0)
/* 0DBD48 80145648 03E00008 */ jr $ra
/* 0DBD4C 8014564C A08512D0 */ sb $a1, 0x12d0($a0)

View File

@ -1,12 +0,0 @@
.set noat # allow manual use of $at
.set noreorder # don't insert nops after branches
glabel set_global_byte
/* 0DBC20 80145520 3C02800E */ lui $v0, 0x800e
/* 0DBC24 80145524 2442ACC0 */ addiu $v0, $v0, -0x5340
/* 0DBC28 80145528 00822021 */ addu $a0, $a0, $v0
/* 0DBC2C 8014552C 808210B0 */ lb $v0, 0x10b0($a0)
/* 0DBC30 80145530 03E00008 */ jr $ra
/* 0DBC34 80145534 A08510B0 */ sb $a1, 0x10b0($a0)

View File

@ -1,41 +0,0 @@
.set noat # allow manual use of $at
.set noreorder # don't insert nops after branches
glabel EnableModel
/* 0EDC38 802C9288 27BDFFE0 */ addiu $sp, $sp, -0x20
/* 0EDC3C 802C928C AFB10014 */ sw $s1, 0x14($sp)
/* 0EDC40 802C9290 0080882D */ daddu $s1, $a0, $zero
/* 0EDC44 802C9294 AFBF0018 */ sw $ra, 0x18($sp)
/* 0EDC48 802C9298 AFB00010 */ sw $s0, 0x10($sp)
/* 0EDC4C 802C929C 8E30000C */ lw $s0, 0xc($s1)
/* 0EDC50 802C92A0 8E050000 */ lw $a1, ($s0)
/* 0EDC54 802C92A4 0C0B1EAF */ jal get_variable
/* 0EDC58 802C92A8 26100004 */ addiu $s0, $s0, 4
/* 0EDC5C 802C92AC 0C046C04 */ jal get_model_list_index_from_tree_index
/* 0EDC60 802C92B0 0040202D */ daddu $a0, $v0, $zero
/* 0EDC64 802C92B4 0220202D */ daddu $a0, $s1, $zero
/* 0EDC68 802C92B8 8E050000 */ lw $a1, ($s0)
/* 0EDC6C 802C92BC 0C0B1EAF */ jal get_variable
/* 0EDC70 802C92C0 0040802D */ daddu $s0, $v0, $zero
/* 0EDC74 802C92C4 0200202D */ daddu $a0, $s0, $zero
/* 0EDC78 802C92C8 0C046B4C */ jal get_model_from_list_index
/* 0EDC7C 802C92CC 0040802D */ daddu $s0, $v0, $zero
/* 0EDC80 802C92D0 12000004 */ beqz $s0, .L802C92E4
/* 0EDC84 802C92D4 0040182D */ daddu $v1, $v0, $zero
/* 0EDC88 802C92D8 94620000 */ lhu $v0, ($v1)
/* 0EDC8C 802C92DC 080B24BB */ j .L802C92EC
/* 0EDC90 802C92E0 3042FFFD */ andi $v0, $v0, 0xfffd
.L802C92E4:
/* 0EDC94 802C92E4 94620000 */ lhu $v0, ($v1)
/* 0EDC98 802C92E8 34420002 */ ori $v0, $v0, 2
.L802C92EC:
/* 0EDC9C 802C92EC A4620000 */ sh $v0, ($v1)
/* 0EDCA0 802C92F0 8FBF0018 */ lw $ra, 0x18($sp)
/* 0EDCA4 802C92F4 8FB10014 */ lw $s1, 0x14($sp)
/* 0EDCA8 802C92F8 8FB00010 */ lw $s0, 0x10($sp)
/* 0EDCAC 802C92FC 24020002 */ addiu $v0, $zero, 2
/* 0EDCB0 802C9300 03E00008 */ jr $ra
/* 0EDCB4 802C9304 27BD0020 */ addiu $sp, $sp, 0x20

View File

@ -1,38 +0,0 @@
.set noat # allow manual use of $at
.set noreorder # don't insert nops after branches
glabel GetModelCenter
/* 0ED930 802C8F80 27BDFFC0 */ addiu $sp, $sp, -0x40
/* 0ED934 802C8F84 AFB00038 */ sw $s0, 0x38($sp)
/* 0ED938 802C8F88 0080802D */ daddu $s0, $a0, $zero
/* 0ED93C 802C8F8C AFBF003C */ sw $ra, 0x3c($sp)
/* 0ED940 802C8F90 8E02000C */ lw $v0, 0xc($s0)
/* 0ED944 802C8F94 0C0B1EAF */ jal get_variable
/* 0ED948 802C8F98 8C450000 */ lw $a1, ($v0)
/* 0ED94C 802C8F9C 3044FFFF */ andi $a0, $v0, 0xffff
/* 0ED950 802C8FA0 27A50020 */ addiu $a1, $sp, 0x20
/* 0ED954 802C8FA4 27A2002C */ addiu $v0, $sp, 0x2c
/* 0ED958 802C8FA8 AFA20010 */ sw $v0, 0x10($sp)
/* 0ED95C 802C8FAC 27A20030 */ addiu $v0, $sp, 0x30
/* 0ED960 802C8FB0 AFA20014 */ sw $v0, 0x14($sp)
/* 0ED964 802C8FB4 27A20034 */ addiu $v0, $sp, 0x34
/* 0ED968 802C8FB8 27A60024 */ addiu $a2, $sp, 0x24
/* 0ED96C 802C8FBC 27A70028 */ addiu $a3, $sp, 0x28
/* 0ED970 802C8FC0 0C046C3B */ jal get_model_center_and_size
/* 0ED974 802C8FC4 AFA20018 */ sw $v0, 0x18($sp)
/* 0ED978 802C8FC8 C7A00020 */ lwc1 $f0, 0x20($sp)
/* 0ED97C 802C8FCC 4600010D */ trunc.w.s $f4, $f0
/* 0ED980 802C8FD0 E6040084 */ swc1 $f4, 0x84($s0)
/* 0ED984 802C8FD4 C7A00024 */ lwc1 $f0, 0x24($sp)
/* 0ED988 802C8FD8 C7A20028 */ lwc1 $f2, 0x28($sp)
/* 0ED98C 802C8FDC 4600010D */ trunc.w.s $f4, $f0
/* 0ED990 802C8FE0 E6040088 */ swc1 $f4, 0x88($s0)
/* 0ED994 802C8FE4 4600110D */ trunc.w.s $f4, $f2
/* 0ED998 802C8FE8 E604008C */ swc1 $f4, 0x8c($s0)
/* 0ED99C 802C8FEC 8FBF003C */ lw $ra, 0x3c($sp)
/* 0ED9A0 802C8FF0 8FB00038 */ lw $s0, 0x38($sp)
/* 0ED9A4 802C8FF4 24020002 */ addiu $v0, $zero, 2
/* 0ED9A8 802C8FF8 03E00008 */ jr $ra
/* 0ED9AC 802C8FFC 27BD0040 */ addiu $sp, $sp, 0x40

328
diff.py
View File

@ -1,48 +1,71 @@
#!/usr/bin/env python3
import sys
import re
import os
import ast
import argparse
import subprocess
import collections
import difflib
import string
import itertools
import threading
import queue
import time
def fail(msg):
print(msg, file=sys.stderr)
sys.exit(1)
MISSING_PREREQUISITES = (
"Missing prerequisite python module {}. "
"Run `python3 -m pip install --user colorama ansiwrap attrs watchdog python-Levenshtein cxxfilt` to install prerequisites (cxxfilt only needed with --source)."
)
try:
import attr
from colorama import Fore, Style, Back
import ansiwrap
import watchdog
except ModuleNotFoundError as e:
fail(MISSING_PREREQUISITES.format(e.name))
# Prefer to use diff_settings.py from the current working directory
sys.path.insert(0, ".")
try:
import diff_settings
except ModuleNotFoundError:
fail("Unable to find diff_settings.py in the same directory.")
sys.path.pop(0)
# ==== CONFIG ====
# ==== COMMAND-LINE ====
try:
import argcomplete # type: ignore
except ModuleNotFoundError:
argcomplete = None
import argparse
parser = argparse.ArgumentParser(description="Diff MIPS assembly.")
parser.add_argument("start", help="Function name or address to start diffing from.")
start_argument = parser.add_argument("start", help="Function name or address to start diffing from.")
if argcomplete:
def complete_symbol(**kwargs):
prefix = kwargs["prefix"]
if prefix == "":
# skip reading the map file, which would
# result in a lot of useless completions
return []
parsed_args = kwargs["parsed_args"]
config = {}
diff_settings.apply(config, parsed_args)
mapfile = config.get("mapfile")
if not mapfile:
return []
completes = []
with open(mapfile) as f:
data = f.read()
# assume symbols are prefixed by a space character
search = f" {prefix}"
pos = data.find(search)
while pos != -1:
# skip the space character in the search string
pos += 1
# assume symbols are suffixed by either a space
# character or a (unix-style) line return
spacePos = data.find(" ", pos)
lineReturnPos = data.find("\n", pos)
if lineReturnPos == -1:
endPos = spacePos
elif spacePos == -1:
endPos = lineReturnPos
else:
endPos = min(spacePos, lineReturnPos)
if endPos == -1:
match = data[pos:]
pos = -1
else:
match = data[pos:endPos]
pos = data.find(search, endPos)
completes.append(match)
return completes
start_argument.completer = complete_symbol
parser.add_argument("end", nargs="?", help="Address to end diff at.")
parser.add_argument(
"-o",
@ -52,6 +75,7 @@ parser.add_argument(
)
parser.add_argument(
"-e",
"--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+.",
)
@ -132,6 +156,14 @@ parser.add_argument(
help="Automatically update when source/object files change. "
"Recommended in combination with -m.",
)
parser.add_argument(
"-3",
"--threeway",
dest="threeway",
action="store_true",
help="Show a three-way diff between target asm, current asm, and asm "
"prior to -w rebuild. Requires -w.",
)
parser.add_argument(
"--width",
dest="column_width",
@ -146,7 +178,6 @@ parser.add_argument(
choices=["levenshtein", "difflib"],
help="Diff algorithm to use.",
)
parser.add_argument(
"--max-size",
"--max-lines",
@ -158,12 +189,44 @@ parser.add_argument(
# Project-specific flags, e.g. different versions/make arguments.
if hasattr(diff_settings, "add_custom_arguments"):
diff_settings.add_custom_arguments(parser)
diff_settings.add_custom_arguments(parser) # type: ignore
if argcomplete:
argcomplete.autocomplete(parser)
# ==== IMPORTS ====
import re
import os
import ast
import subprocess
import difflib
import string
import itertools
import threading
import queue
import time
from typing import Any, Dict, List, NamedTuple, Optional, Set, Tuple, Union
MISSING_PREREQUISITES = (
"Missing prerequisite python module {}. "
"Run `python3 -m pip install --user colorama ansiwrap watchdog python-Levenshtein cxxfilt` to install prerequisites (cxxfilt only needed with --source)."
)
try:
from colorama import Fore, Style, Back # type: ignore
import ansiwrap # type: ignore
import watchdog # type: ignore
except ModuleNotFoundError as e:
fail(MISSING_PREREQUISITES.format(e.name))
# ==== CONFIG ====
args = parser.parse_args()
# Set imgs, map file and make flags in a project-specific manner.
config = {}
config: Dict[str, Any] = {}
diff_settings.apply(config, args)
arch = config.get("arch", "mips")
@ -199,13 +262,13 @@ FS_WATCH_EXTENSIONS = [".c", ".h"]
if args.algorithm == "levenshtein":
try:
import Levenshtein
import Levenshtein # type: ignore
except ModuleNotFoundError as e:
fail(MISSING_PREREQUISITES.format(e.name))
if args.source:
try:
import cxxfilt
import cxxfilt # type: ignore
except ModuleNotFoundError as e:
fail(MISSING_PREREQUISITES.format(e.name))
@ -538,22 +601,21 @@ def process_mips_reloc(row, prev):
return before + repl + after
def cleanup_whitespace(line):
return "".join(f"{o:<8s}" for o in line.strip().split("\t"))
def pad_mnemonic(line):
if "\t" not in line:
return line
mn, args = line.split("\t", 1)
return f"{mn:<7s} {args}"
Line = collections.namedtuple(
"Line",
[
"mnemonic",
"diff_row",
"original",
"line_num",
"branch_target",
"source_lines",
"comment",
],
)
class Line(NamedTuple):
mnemonic: str
diff_row: str
original: str
line_num: str
branch_target: Optional[str]
source_lines: List[str]
comment: Optional[str]
def process(lines):
@ -565,6 +627,7 @@ def process(lines):
lines.pop()
output = []
stop_after_delay_slot = False
for row in lines:
if args.diff_obj and (">:" in row or not row):
continue
@ -634,18 +697,15 @@ def process(lines):
source_lines = []
if args.stop_jrra and mnemonic == "jr" and row_parts[1].strip() == "ra":
stop_after_delay_slot = True
elif stop_after_delay_slot:
break
# Cleanup whitespace, after relocation fixups have happened
output = [
line._replace(original=cleanup_whitespace(line.original)) for line in output
]
return output
def format_single_line_diff(line1, line2, column_width):
return f"{ansi_ljust(line1,column_width)}{ansi_ljust(line2,column_width)}"
return f"{ansi_ljust(line1,column_width)}{line2}"
class SymbolColorer:
@ -743,11 +803,27 @@ def diff_sequences(seq1, seq2):
return Levenshtein.opcodes(seq1, seq2)
def do_diff(basedump, mydump):
output = []
class OutputLine:
base: Optional[str]
fmt2: str
key2: str
# TODO: status line?
# output.append(sha1sum(mydump))
def __init__(self, base: Optional[str], fmt2: str, key2: str) -> None:
self.base = base
self.fmt2 = fmt2
self.key2 = key2
def __eq__(self, other: object) -> bool:
if not isinstance(other, OutputLine):
return NotImplemented
return self.key2 == other.key2
def __hash__(self) -> int:
return hash(self.key2)
def do_diff(basedump: str, mydump: str) -> List[OutputLine]:
output: List[OutputLine] = []
lines1 = process(basedump.split("\n"))
lines2 = process(mydump.split("\n"))
@ -758,8 +834,8 @@ def do_diff(basedump, mydump):
sc4 = SymbolColorer(4)
sc5 = SymbolColorer(0)
sc6 = SymbolColorer(0)
bts1 = set()
bts2 = set()
bts1: Set[str] = set()
bts2: Set[str] = set()
if args.show_branches:
for (lines, btset, sc) in [
@ -856,40 +932,36 @@ def do_diff(basedump, mydump):
out2 = line2.original
elif line1:
line_prefix = "<"
line_color1 = line_color2 = sym_color = Fore.RED
line_color1 = sym_color = Fore.RED
out1 = line1.original
out2 = ""
elif line2:
line_prefix = ">"
line_color1 = line_color2 = sym_color = Fore.GREEN
line_color2 = sym_color = Fore.GREEN
out1 = ""
out2 = line2.original
in_arrow1 = " "
in_arrow2 = " "
out_arrow1 = ""
out_arrow2 = ""
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 ""
def format_part(out: str, line: Optional[Line], line_color: str, btset: Set[str], sc: SymbolColorer) -> Optional[str]:
if line is None:
return None
in_arrow = " "
out_arrow = ""
if args.show_branches:
if line.line_num in btset:
in_arrow = sc.color_symbol(line.line_num, "~>") + line_color
if line.branch_target is not None:
out_arrow = " " + sc.color_symbol(line.branch_target + ":", "~>")
out = pad_mnemonic(out)
return f"{line_color}{line.line_num} {in_arrow} {out}{Style.RESET_ALL}{out_arrow}"
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} "
part1 = format_part(out1, line1, line_color1, bts1, sc5)
part2 = format_part(out2, line2, line_color2, bts2, sc6)
key2 = line2.original if line2 else ""
mid = f"{sym_color}{line_prefix}"
if line2:
for source_line in line2.source_lines:
@ -907,22 +979,82 @@ def do_diff(basedump, mydump):
)
except:
pass
output.append(
format_single_line_diff(
"",
f" {color}{source_line}{Style.RESET_ALL}",
args.column_width,
)
)
output.append(OutputLine(None, f" {color}{source_line}{Style.RESET_ALL}", source_line))
output.append(format_single_line_diff(out1, mid + out2, args.column_width))
fmt2 = mid + " " + (part2 or "")
output.append(OutputLine(part1, fmt2, key2))
return output[args.skip_lines :]
return output
def chunk_diff(diff: List[OutputLine]) -> List[Union[List[OutputLine], OutputLine]]:
cur_right: List[OutputLine] = []
chunks: List[Union[List[OutputLine], OutputLine]] = []
for output_line in diff:
if output_line.base is not None:
chunks.append(cur_right)
chunks.append(output_line)
cur_right = []
else:
cur_right.append(output_line)
chunks.append(cur_right)
return chunks
def format_diff(old_diff: List[OutputLine], new_diff: List[OutputLine]) -> Tuple[str, List[str]]:
old_chunks = chunk_diff(old_diff)
new_chunks = chunk_diff(new_diff)
output: List[Tuple[str, OutputLine, OutputLine]] = []
assert len(old_chunks) == len(new_chunks), "same target"
empty = OutputLine("", "", "")
for old_chunk, new_chunk in zip(old_chunks, new_chunks):
if isinstance(old_chunk, list):
assert isinstance(new_chunk, list)
if not old_chunk and not new_chunk:
# Most of the time lines sync up without insertions/deletions,
# and there's no interdiffing to be done.
continue
differ = difflib.SequenceMatcher(a=old_chunk, b=new_chunk, autojunk=False)
for (tag, i1, i2, j1, j2) in differ.get_opcodes():
if tag in ["equal", "replace"]:
for i, j in zip(range(i1, i2), range(j1, j2)):
output.append(("", old_chunk[i], new_chunk[j]))
elif tag == "insert":
for j in range(j1, j2):
output.append(("", empty, new_chunk[j]))
else:
for i in range(i1, i2):
output.append(("", old_chunk[i], empty))
else:
assert isinstance(new_chunk, OutputLine)
# old_chunk.base and new_chunk.base have the same text since
# both diffs are based on the same target, but they might
# differ in color. Use the new version.
output.append((new_chunk.base or "", old_chunk, new_chunk))
# TODO: status line, with e.g. approximate permuter score?
width = args.column_width
if args.threeway:
header_line = "TARGET".ljust(width) + " CURRENT".ljust(width) + " PREVIOUS"
diff_lines = [
ansi_ljust(base, width)
+ ansi_ljust(new.fmt2, width)
+ (old.fmt2 or "-" if old != new else "")
for (base, old, new) in output
]
else:
header_line = ""
diff_lines = [
ansi_ljust(base, width) + new.fmt2
for (base, old, new) in output
if base or new.key2
]
return header_line, diff_lines
def debounced_fs_watch(targets, outq, debounce_delay):
import watchdog.events
import watchdog.observers
import watchdog.events # type: ignore
import watchdog.observers # type: ignore
class WatchEventHandler(watchdog.events.FileSystemEventHandler):
def __init__(self, queue, file_targets):
@ -993,12 +1125,18 @@ class Display:
self.basedump = basedump
self.mydump = mydump
self.emsg = None
self.last_diff_output = None
def run_less(self):
if self.emsg is not None:
output = self.emsg
else:
output = "\n".join(do_diff(self.basedump, self.mydump))
diff_output = do_diff(self.basedump, self.mydump)
last_diff_output = self.last_diff_output or diff_output
self.last_diff_output = diff_output
header, diff_lines = format_diff(last_diff_output, diff_output)
header_lines = [header] if header else []
output = "\n".join(header_lines + diff_lines[args.skip_lines :])
# Pipe the output through 'tail' and only then to less, to ensure the
# write call doesn't block. ('tail' has to buffer all its input before

View File

@ -1429,4 +1429,33 @@ typedef struct EncounterStatus {
/* 0x98 */ s32 unk_98;
} EncounterStatus; // size = 0x9C
typedef struct SaveData {
/* 0x0000 */ char magicString[16]; /* "Mario Story 006" string */
/* 0x0010 */ s8 pad[32]; /* always zero */
/* 0x0030 */ s32 crc1;
/* 0x0034 */ s32 crc2;
/* 0x0038 */ s32 saveSlot;
/* 0x003C */ s32 saveCount;
/* 0x0040 */ struct PlayerData player;
/* 0x0380 */ char unk_380[0xE0];
/* 0x0460 */ s32 starPoints;
/* 0x0464 */ char unk_464[4];
/* 0x0468 */ s16 areaID;
/* 0x046A */ s16 mapID;
/* 0x046C */ s16 entryID;
/* 0x046E */ char unk_46E[2];
/* 0x0470 */ s32 enemyDefeatFlags[720];
/* 0x0FB0 */ s8 globalFlags[256];
/* 0x10B0 */ s8 globalBytes[512];
/* 0x12B0 */ s32 areaFlags[8];
/* 0x12D0 */ s8 areaBytes[16];
/* 0x12E0 */ char unk_12E0[6];
/* 0x12E6 */ s16 savePos[3];
/* 0x12EC */ s32 unk_12EC;
/* 0x12F0 */ s8 unk_12F0[12]; /* player name starts at 4th char */
/* 0x12FC */ s32 unk_12FC;
/* 0x1300 */ s32 unk_1300;
/* 0x1304 */ char unk_1304[0x7C];
} SaveData; // size = 0x1380
#endif

View File

@ -10,8 +10,14 @@ void osCleanupThread(void);
s32 heap_malloc(s32 size);
HeapNode* _heap_create(void* addr, s32 size);
s8 get_global_byte(s32 index);
s32 get_global_flag(s32 index);
s8 get_area_byte(s32 index);
s32 get_area_flag(s32 index);
void clone_model(u16 srcModelID, u16 newModelID);
Model* get_model_from_list_index(s32 listIndex);
void get_model_center_and_size(s32 modelID, f32* centerX, f32* centerY, f32* centerZ, f32* sizeX, f32* sizeY, f32* sizeZ);
void update_collider_transform(s16 colliderID);
void get_collider_center(s32 colliderID, f32* x, f32* y, f32* z);

View File

@ -92,4 +92,9 @@ extern UNK_TYPE D_80108558;
extern UNK_TYPE D_8010F250; // play_sound state struct?
extern s8 D_8010EBB0;
extern SaveData gCurrentSaveFile;
extern u32* gMapFlags;
extern u32* gMapVars;
#endif

View File

@ -191,7 +191,7 @@ INCLUDE_ASM("code_a5dd0_len_114e0", get_model_list_index_from_tree_index);
INCLUDE_ASM("code_a5dd0_len_114e0", func_8011B090);
INCLUDE_ASM("code_a5dd0_len_114e0", get_model_center_and_size);
void INCLUDE_ASM("code_a5dd0_len_114e0", get_model_center_and_size, s32 modelID, f32* centerX, f32* centerY, f32* centerZ, f32* sizeX, f32* sizeY, f32* sizeZ);
INCLUDE_ASM("code_a5dd0_len_114e0", func_8011B1C0);

View File

@ -7,19 +7,104 @@ INCLUDE_ASM("code_dba20_len_350", clear_area_flags);
INCLUDE_ASM("code_dba20_len_350", clear_global_flag);
INCLUDE_ASM("code_dba20_len_350", set_global_flag);
/*s32 set_global_flag(s32 index) {
//SaveData* saveFile = &gCurrentSaveFile;
s32 flag;
INCLUDE_ASM("code_dba20_len_350", get_global_flag);
if (index <= -120000000) {
index += 130000000;
}
INCLUDE_ASM("code_dba20_len_350", set_global_byte);
flag = gCurrentSaveFile->globalFlags[index / 32] & (1 << (index % 32));
INCLUDE_ASM("code_dba20_len_350", get_global_byte);
if (flag) {
flag = 1;
}
gCurrentSaveFile->globalFlags[index / 32] |= (1 << (index % 32));
return flag;
}*/
s32 INCLUDE_ASM("code_dba20_len_350", get_global_flag, s32 index);
/*s32 get_global_flag(s32 index) {
s32 bitIdx;
s32 wordIdx;
s32 bit;
s32 phi_return;
if (index <= -120000000) {
index += 130000000;
}
wordIdx = index / 32;
bitIdx = index % 32;
bit = gCurrentSaveFile->globalFlags[wordIdx] & (1 << bitIdx);
if (bit != 0) {
bit = 1;
}
return bit;
//return (bit != 0) ? 1 : bit; // ??? surely this is `bit != 0`
}*/
s8 set_global_byte(s32 index, s8 value) {
SaveData* saveFile = &gCurrentSaveFile;
s32 ret = saveFile->globalBytes[index];
saveFile->globalBytes[index] = value;
return ret;
}
s8 get_global_byte(s32 index) {
return gCurrentSaveFile.globalBytes[index];
}
INCLUDE_ASM("code_dba20_len_350", clear_area_flag);
INCLUDE_ASM("code_dba20_len_350", set_area_flag);
/*s32 set_area_flag(s32 index) {
SaveData* saveFile = &gCurrentSaveFile;
s32 flag;
s32 flagIdx;
s32 flagShift;
INCLUDE_ASM("code_dba20_len_350", get_area_flag);
flagIdx = index / 32;
flagShift = index % 32;
INCLUDE_ASM("code_dba20_len_350", set_area_byte);
flag = saveFile->areaFlags[flagIdx] & (1 << flagShift);
INCLUDE_ASM("code_dba20_len_350", get_area_byte);
if (flag != 0) {
flag = 1;
}
saveFile->areaFlags[flagIdx] |= (1 << flagShift);
return flag;
}*/
s32 get_area_flag(s32 index) {
s32 flag;
s32 flagIdx;
s32 flagShift;
flagIdx = index / 32;
flagShift = index % 32;
flag = gCurrentSaveFile.areaFlags[flagIdx] & (1 << flagShift);
if (flag != 0) {
flag = 1;
}
return flag;
}
s8 set_area_byte(s32 index, s8 value) {
SaveData* saveFile = &gCurrentSaveFile;
s32 ret = saveFile->areaBytes[index];
saveFile->areaBytes[index] = value;
return ret;
}
s8 get_area_byte(s32 index) {
return gCurrentSaveFile.areaBytes[index];
}

View File

@ -719,6 +719,57 @@ s32 func_802C73B8(ScriptInstance* script) {
INCLUDE_ASM("code_e92d0_len_5da0", si_execute_next_command);
s32 INCLUDE_ASM("code_e92d0_len_5da0", get_variable, ScriptInstance* script, Bytecode var);
// TODO: consider renaming to si_get_variable
/*s32 get_variable(ScriptInstance* script, Bytecode var) {
s32 abs_value;
s32 word_index;
s32 bit_index;
if (var <= -270000000) {
return var;
} else if (var <= -250000000) {
return var;
} else if (var <= -220000000) {
return (s32) fixed_var_to_float(var);
} else if (var <= -200000000) {
var += 210000000;
word_index = var / 32;
bit_index = var % 32;
return (script->flagArray[word_index] & (1 << bit_index)) != 0;
} else if (var <= -180000000) {
var += 190000000;
var = script->array[var];
return (var > -270000000 && var < -220000000) ? (s32) fixed_var_to_float(var) : var;
} else if (var <= -160000000) {
return get_global_byte(var + 170000000);
} else if (var <= -140000000) {
return get_area_byte(var + 150000000);
} else if (var <= -120000000) {
return get_global_flag(var + 130000000);
} else if (var <= -100000000) {
return get_area_flag(var + 110000000);
} else if (var <= -80000000) {
s32 avar = var + 90000000;
word_index = avar / 32;
bit_index = avar % 32;
return (gMapFlags[word_index] & (1 << bit_index)) != 0;
} else if (var <= -60000000) {
var += 70000000;
word_index = var / 32;
bit_index = var % 32;
return (script->varFlags[word_index] & (1 << bit_index)) != 0;
} else if (var <= -40000000) {
var += 50000000;
var = gMapVars[var];
return (var > -270000000 && var < -220000000) ? (s32) fixed_var_to_float(var) : var;
} else if (var <= -20000000) {
var += 30000000;
var = script->varTable[var];
return (var > -270000000 && var < -220000000) ? (s32) fixed_var_to_float(var) : var;
} else {
return var;
}
}*/
INCLUDE_ASM("code_e92d0_len_5da0", get_variable_index);
@ -848,7 +899,21 @@ ApiStatus CloneModel(ScriptInstance* script, s32 isInitialCall) {
return ApiStatus_DONE2;
}
INCLUDE_API_ASM("code_e92d0_len_5da0", GetModelCenter);
ApiStatus GetModelCenter(ScriptInstance* script, s32 isInitialCall) {
Bytecode* thisPos = script->ptrReadPos;
f32 centerX;
f32 centerY;
f32 centerZ;
f32 sizeX;
f32 sizeY;
f32 sizeZ;
get_model_center_and_size(get_variable(script, *thisPos++) & 0xFFFF, &centerX, &centerY, &centerZ, &sizeX, &sizeY, &sizeZ);
script->varTable[0] = centerX;
script->varTable[1] = centerY;
script->varTable[2] = centerZ;
return ApiStatus_DONE2;
}
INCLUDE_API_ASM("code_e92d0_len_5da0", SetTexPanner);
@ -856,7 +921,20 @@ INCLUDE_API_ASM("code_e92d0_len_5da0", SetModelFlag10);
INCLUDE_API_ASM("code_e92d0_len_5da0", EnableTexPanning);
INCLUDE_API_ASM("code_e92d0_len_5da0", EnableModel);
ApiStatus EnableModel(ScriptInstance* script, s32 isInitialCall) {
Bytecode* thisPos = script->ptrReadPos;
Bytecode treeIndex = get_variable(script, *thisPos++);
s32 listIndex = get_model_list_index_from_tree_index(treeIndex);
Bytecode flag = get_variable(script, *thisPos++);
Model* model = get_model_from_list_index(listIndex);
if (flag != 0) {
model->flags &= ~0x2;
} else {
model->flags |= 0x2;
}
return ApiStatus_DONE2;
}
ApiStatus SetGroupEnabled(ScriptInstance* script, s32 isInitialCall) {
Bytecode* thisPos = script->ptrReadPos;

View File

@ -112,6 +112,11 @@ gScriptIdList = 0x802D1898;
gScriptIndexList = 0x802DAA98;
gScriptListCount = 0x802DAC98;
gCurrentSaveFile = 0x800DACC0;
gMapFlags = 0x802DA480;
gMapVars = 0x802DA484;
func_802A91F8 = 0x802A91F8;
func_802A9208 = 0x802A9208;
func_802A9228 = 0x802A9228;