Fix disasm script (#243)

* Enum all the things

* Fix disasm script
This commit is contained in:
Maide 2021-03-30 04:39:17 +01:00 committed by GitHub
parent 21917eb3dc
commit 986f594d00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 105 additions and 84 deletions

View File

@ -111,8 +111,8 @@ typedef enum ScriptOpcode {
#define SI_ARRAY_FLAG(v) ((v - 210000000))
#define SI_FIXED(v) (((v * 1024.0f) + -230000000)) // See float_to_fixed_var
#define STORY_PROGRESS SI_SAVE_VAR(0x000)
#define WORLD_LOCATION SI_SAVE_VAR(0x1A9)
#define STORY_PROGRESS SI_SAVE_VAR(0)
#define WORLD_LOCATION SI_SAVE_VAR(425)
/* Return type of si_execute_next_command */
#define SI_CONTINUE 0 /* Continue to next command */

View File

@ -3,7 +3,7 @@
void fio_serialize_state(void);
s32 get_spirits_rescued(void) {
s32 storyProgress = get_variable(NULL, SI_SAVE_VAR(0));
s32 storyProgress = get_variable(NULL, STORY_PROGRESS);
s32 ret = 7;
if (storyProgress < get_variable(NULL, -0x4D)) {

View File

@ -65,7 +65,7 @@ void check_input_status_menu(void) {
PlayerStatus* playerStatus = &gPlayerStatus;
s32 pressedButtons;
if (get_variable(NULL, SI_SAVE_VAR(0)) < STORY_EPILOGUE) {
if (get_variable(NULL, STORY_PROGRESS) < STORY_EPILOGUE) {
if (playerStatus->actionState != ACTION_STATE_RIDE) {
pressedButtons = playerStatus->pressedButtons;
} else {

View File

@ -12,7 +12,7 @@ void load_map_bg(char* optAssetName) {
u32 assetSize;
char* assetName = optAssetName;
if (get_variable(0, SI_SAVE_VAR(0)) >= STORY_CH6_DESTROYED_PUFF_PUFF_MACHINE) {
if (get_variable(0, STORY_PROGRESS) >= STORY_CH6_DESTROYED_PUFF_PUFF_MACHINE) {
// Use sunny Flower Fields bg rather than cloudy
if (!strcmp(assetName, gCloudyFlowerFieldsBg)) {
assetName = gSunnyFlowerFieldsBg;

View File

@ -11,7 +11,7 @@ Script N(BindExits) = SCRIPT({
});
Script N(Main) = SCRIPT({
SI_SAVE_VAR(425) = 34;
WORLD_LOCATION = LOCATION_GUSTY_GULCH;
SetSpriteShading(-1);
SetCamPerspective(0, 3, 25, 16, 4096);
SetCamBGColor(0, 0, 0, 0);

View File

@ -15,7 +15,7 @@ MapConfig N(config) = {
};
Script N(PlayMusic) = SCRIPT({
match SI_SAVE_VAR(0) {
match STORY_PROGRESS {
< STORY_CH3_TUBBA_WOKE_UP {
SetMusicTrack(0, SONG_GUSTY_GULCH, 0, 8);
}

View File

@ -25,7 +25,7 @@ Script N(Script_802407A8) = SCRIPT({
});
Script N(Main) = SCRIPT({
SI_SAVE_VAR(425) = 30;
WORLD_LOCATION = LOCATION_GOOMBA_VILLAGE;
SetSpriteShading(-1);
SetCamPerspective(0, 3, 25, 16, 4096);
SetCamBGColor(0, 0, 0, 0);
@ -87,7 +87,7 @@ Script N(Script_8024097C) = SCRIPT({
Script N(NpcAI_80240B50) = SCRIPT({
1:
match SI_SAVE_VAR(0) {
match STORY_PROGRESS {
== STORY_CH0_FELL_OFF_CLIFF {
89:
N(UnkPositionFunc)(0xFFFFFF8A, 86, 0xFFFFFFBA, 0xFFFFFFF1);
@ -127,7 +127,7 @@ Script N(NpcAI_80240B50) = SCRIPT({
sleep 30;
SpeakToPlayer(0, 0x9D0008, 0x9D0001, 0, 0xB00A8);
func_80240000_8C7F90(0, 5);
SI_SAVE_VAR(0) = STORY_CH0_GOOMPA_JOINED_PARTY;
STORY_PROGRESS = STORY_CH0_GOOMPA_JOINED_PARTY;
UseSettingsFrom(0, 0xFFFFFF24, 20, 0xFFFFFFB8);
GetPlayerPos(SI_VAR(0), SI_VAR(1), SI_VAR(2));
SetPanTarget(0, SI_VAR(0), SI_VAR(1), SI_VAR(2));
@ -186,7 +186,7 @@ Script N(Init_802411A8) = SCRIPT({
BindNpcIdle(-1, N(NpcAI_80240B50));
BindNpcAux(-1, N(Script_8024097C));
BindNpcHit(-1, N(Hit_80240F64));
match SI_SAVE_VAR(0) {
match STORY_PROGRESS {
>= 0xFFFFFF87 {
SetNpcFlagBits(-1, 512, 0);
SetNpcFlagBits(-1, 8, 1);
@ -222,7 +222,7 @@ s32 N(padding2)[] = {0, 0};
Script N(Script_80241470) = SCRIPT({
ModifyColliderFlags(0, 9, 0x7FFFFE00);
SI_SAVE_VAR(0) = STORY_CH0_LEFT_THE_PLAYGROUND;
STORY_PROGRESS = STORY_CH0_LEFT_THE_PLAYGROUND;
});
Script N(Script_802414A8) = SCRIPT({
@ -238,7 +238,7 @@ Script N(Script_802414C8) = SCRIPT({
});
Script N(MakeEntities) = SCRIPT({
if (SI_SAVE_VAR(0) < STORY_CH0_LEFT_THE_PLAYGROUND) {
if (STORY_PROGRESS < STORY_CH0_LEFT_THE_PLAYGROUND) {
MakeEntity(0x802EA10C, 45, 0, 70, 15, 0x80000000);
AssignScript(N(Script_80241470));
} else {

View File

@ -6,7 +6,7 @@ Script N(Script_80242340) = SCRIPT({
SetCamDistance(0, 700.0);
SetCamSpeed(0, 90.0);
PanToTarget(0, 0, 1);
if (SI_SAVE_VAR(0) >= STORY_CH0_FOUND_HAMMER) {
if (STORY_PROGRESS >= STORY_CH0_FOUND_HAMMER) {
SetPlayerPos(0, 0xFFFFFC18, 0);
DisablePlayerInput(1);
SetPlayerPos(0xFFFFFF20, 20, 0xFFFFFFB0);

View File

@ -11,7 +11,7 @@ Script N(BindExits) = SCRIPT({
});
Script N(Main) = SCRIPT({
WORLD_LOCATION = 31;
WORLD_LOCATION = LOCATION_GOOMBA_ROAD;
SetSpriteShading(-1);
SetCamPerspective(0, 3, 25, 16, 4096);
SetCamBGColor(0, 0, 0, 0);

View File

@ -42,9 +42,9 @@ Script N(Script_80240198) = SCRIPT({
});
Script N(Main) = SCRIPT({
SI_SAVE_VAR(425) = 10;
WORLD_LOCATION = LOCATION_DRY_DRY_DESERT;
SetSpriteShading(-1);
if (SI_SAVE_VAR(0) == STORY_CH2_GOT_PULSE_STONE) {
if (STORY_PROGRESS == STORY_CH2_GOT_PULSE_STONE) {
DisablePulseStone(0);
}
SetCamPerspective(0, 3, 25, 16, 4096);

View File

@ -51,9 +51,9 @@ Script N(Script_802401F4) = SCRIPT({
});
Script N(Main) = SCRIPT({
SI_SAVE_VAR(425) = 10;
WORLD_LOCATION = LOCATION_DRY_DRY_DESERT;
SetSpriteShading(-1);
if (SI_SAVE_VAR(0) == STORY_CH2_GOT_PULSE_STONE) {
if (STORY_PROGRESS == STORY_CH2_GOT_PULSE_STONE) {
DisablePulseStone(0);
}
SetCamPerspective(0, 3, 25, 16, 4096);

View File

@ -67,20 +67,23 @@ def script_lib(offset):
_script_lib[k] = sorted(_script_lib[k], key=lambda x: x[0])
return _script_lib
# Grab constants from the include/ folder to save manual work
constants = {}
# Grab CONSTANTS from the include/ folder to save manual work
CONSTANTS = {}
SAVE_VARS = set()
def get_constants():
global constants
valid_defines = { "ItemId", "PlayerAnim", "ActorID", "Event", "SoundId", "Song" }
valid_enums = { "StoryProgress" }
for enum in valid_defines:
constants[enum] = {}
global CONSTANTS
global VALID_SAVE_VARS
valid_enums = { "StoryProgress", "ItemIDs", "PlayerAnims", "ActorIDs", "Events", "SoundIDs", "SongIDs", "Locations" }
for enum in valid_enums:
constants[enum] = {}
CONSTANTS[enum] = {}
[SAVE_VARS.add(x) for x in ["WORLD_LOCATION", "STORY_PROGRESS"]]
include_path = Path(Path(__file__).resolve().parent.parent / "include")
enums = Path(include_path / "enums.h").read_text().splitlines()
'''
# define stuff
for line in enums:
this_enum = ""
@ -94,14 +97,15 @@ def get_constants():
id_ = line.split("0x", 1)[1]
if " " in id_:
id_ = id_.split(" ",1)[0]
constants[this_enum][int(id_, 16)] = name
CONSTANTS[this_enum][int(id_, 16)] = name
'''
# enums
for i,line in enumerate(enums):
if line.startswith("enum "):
enum_name = line.split(" ",1)[1].split(" {",1)[0]
if enum_name in valid_enums:
constants[enum_name] = {}
CONSTANTS[enum_name] = {}
last_num = 0
i += 1
while "}" not in enums[i]:
@ -112,19 +116,21 @@ def get_constants():
name = enums[i].strip()
val = last_num+1
if "=" in name:
name, _, val = name.split(" ")
name, val = name.split(" = ")
val = int(val[:-1], 0)
else:
name = name[:-1]
name = name.strip()
#print("\"" + name + "\"", "===", val)
constants[enum_name][val] = name
CONSTANTS[enum_name][val] = name.strip()
i += 1
last_num = val
return
def fix_args(args, info):
global constants
global CONSTANTS
new_args = []
for i,arg in enumerate(args.split(", ")):
@ -134,11 +140,11 @@ def fix_args(args, info):
else:
argNum = int(arg, 10)
if argNum in constants[info[i]]:
new_args.append(f"{constants[info[i]][argNum]}")
if argNum in CONSTANTS[info[i]]:
new_args.append(f"{CONSTANTS[info[i]][argNum]}")
else:
print(f"{argNum:X} was not found within {info[i]} constants, add it.")
if info[i] == "SoundId":
print(f"{argNum:X} was not found within {info[i]} CONSTANTS, add it.")
if info[i] == "SoundIDs":
# Ethan wanted sound IDs in hex instead, so convert it back
if "0x" not in arg:
argNum = int(arg, 10)
@ -149,41 +155,42 @@ def fix_args(args, info):
return ", ".join(new_args)
replace_funcs = {
"DispatchDamagePlayerEvent" :{1:"Event"},
"DispatchEvent" :{0:"ActorID"},
"DispatchDamagePlayerEvent" :{1:"Events"},
"DispatchEvent" :{0:"ActorIDs"},
"ForceHomePos" :{0:"ActorID"},
"ForceHomePos" :{0:"ActorIDs"},
"GetActorPos" :{0:"ActorID"},
"GetGoalPos" :{0:"ActorID"},
"GetItemPower" :{0:"ItemId"},
"GetActorPos" :{0:"ActorIDs"},
"GetGoalPos" :{0:"ActorIDs"},
"GetItemPower" :{0:"ItemIDs"},
"JumpToGoal" :{0:"ActorID"},
"JumpToGoal" :{0:"ActorIDs"},
"MakeEntity" :{5:"ItemId"},
"MakeItemEntity" :{0:"ItemId"},
"MakeEntity" :{5:"ItemIDs"},
"MakeItemEntity" :{0:"ItemIDs"},
"PlaySound" :{0:"SoundId"},
"PlaySoundAtActor" :{0:"ActorID", 1:"SoundId"},
"PlaySound" :{0:"SoundIDs"},
"PlaySoundAtActor" :{0:"ActorIDs", 1:"SoundIDs"},
"SetActorJumpGravity" :{0:"ActorID"},
"SetActorSpeed" :{0:"ActorID"},
"SetActorScale" :{0:"ActorID"},
"SetActorYaw" :{0:"ActorID"},
"SetAnimation" :{0:"ActorID", 2:"PlayerAnim"},
"SetGoalPos" :{0:"ActorID"},
"SetGoalToHome" :{0:"ActorID"},
"SetGoalToTarget" :{0:"ActorID"},
"SetJumpAnimations" :{0:"ActorID", 2:"PlayerAnim", 3:"PlayerAnim", 4:"PlayerAnim"},
"SetMusicTrack" :{1:"Song"},
"SetTargetActor" :{0:"ActorID"},
"SetActorJumpGravity" :{0:"ActorIDs"},
"SetActorSpeed" :{0:"ActorIDs"},
"SetActorScale" :{0:"ActorIDs"},
"SetActorYaw" :{0:"ActorIDs"},
"SetAnimation" :{0:"ActorIDs", 2:"PlayerAnims"},
"SetGoalPos" :{0:"ActorIDs"},
"SetGoalToHome" :{0:"ActorIDs"},
"SetGoalToTarget" :{0:"ActorIDs"},
"SetJumpAnimations" :{0:"ActorIDs", 2:"PlayerAnims", 3:"PlayerAnims", 4:"PlayerAnims"},
"SetMusicTrack" :{1:"SongIDs"},
"SetTargetActor" :{0:"ActorIDs"},
"UseIdleAnimation" :{0:"ActorID"},
"UseIdleAnimation" :{0:"ActorIDs"},
}
def replace_constants(func, args):
global replace_funcs
if func in replace_funcs:
return fix_args(args, replace_funcs[func])
elif func == "PlayEffect":
@ -538,7 +545,12 @@ class ScriptDSLDisassembler(ScriptDisassembler):
elif v <= -200000000: return f"SI_ARRAY_FLAG({v + 210000000})"
elif v <= -180000000: return f"SI_ARRAY({v + 190000000})"
elif v <= -160000000:
self.save_variable = f"SI_SAVE_VAR({v + 170000000})"
if v + 170000000 == 0:
self.save_variable = "STORY_PROGRESS"
elif v + 170000000 == 425:
self.save_variable = "WORLD_LOCATION"
else:
self.save_variable = f"SI_SAVE_VAR({v + 170000000})"
return self.save_variable
elif v <= -140000000: return f"SI_AREA_VAR({v + 150000000})"
elif v <= -120000000: return f"SI_SAVE_FLAG({v + 130000000})"
@ -575,12 +587,15 @@ class ScriptDSLDisassembler(ScriptDisassembler):
if var > 0x10000000:
var -= 0x100000000
if ((case and self.case_variable == "SI_SAVE_VAR(0)") or
(not case and self.save_variable == "SI_SAVE_VAR(0)")):
if var in constants["StoryProgress"]:
return constants["StoryProgress"][var]
# put cases for replacing vars here
if (( case and self.case_variable == "STORY_PROGRESS") or
(not case and self.save_variable == "STORY_PROGRESS")):
if var in CONSTANTS["StoryProgress"]:
return CONSTANTS["StoryProgress"][var]
elif (( case and self.case_variable == "WORLD_LOCATION") or
(not case and self.save_variable == "WORLD_LOCATION")):
if var in CONSTANTS["Locations"]:
return CONSTANTS["Locations"][var]
return varO
@ -613,7 +628,9 @@ class ScriptDSLDisassembler(ScriptDisassembler):
self.write_line("}")
#print(f"Op 0x{opcode:2X} saved_var \"{self.save_variable}\" case_var \"{self.case_variable}\"")
if self.in_case and 0x16 <= opcode <= 0x1B and self.case_variable == "SI_SAVE_VAR(0)":
# case variables need to be saved ahead of time, since they span many instructions
if ((self.in_case and 0x16 <= opcode <= 0x1B and self.case_variable == "STORY_PROGRESS") or
(self.in_case and 0x16 <= opcode <= 0x1B and self.case_variable == "WORLD_LOCATION")):
argv[0] = self.replace_enum(argv[0], case=True)
if opcode == 0x01:
@ -650,50 +667,44 @@ class ScriptDSLDisassembler(ScriptDisassembler):
elif opcode == 0x0A:
varA = self.replace_enum(argv[0])
varB = self.replace_enum(argv[1])
if varB == "SI_SAVE_VAR(0)":
if varB in SAVE_VARS:
varA = self.replace_enum(argv[0])
self.write_line(f"if ({varA} == {varB}) {{")
self.save_variable = ""
self.indent += 1
elif opcode == 0x0B:
varA = self.replace_enum(argv[0])
varB = self.replace_enum(argv[1])
if varB == "SI_SAVE_VAR(0)":
if varB in SAVE_VARS:
varA = self.replace_enum(argv[0])
self.write_line(f"if ({varA} != {varB}) {{")
self.save_variable = ""
self.indent += 1
elif opcode == 0x0C:
varA = self.replace_enum(argv[0])
varB = self.replace_enum(argv[1])
if varB == "SI_SAVE_VAR(0)":
if varB in SAVE_VARS:
varA = self.replace_enum(argv[0])
self.write_line(f"if ({varA} < {varB}) {{")
self.save_variable = ""
self.indent += 1
elif opcode == 0x0D:
varA = self.replace_enum(argv[0])
varB = self.replace_enum(argv[1])
if varB == "SI_SAVE_VAR(0)":
if varB in SAVE_VARS:
varA = self.replace_enum(argv[0])
self.write_line(f"if ({varA} > {varB}) {{")
self.save_variable = ""
self.indent += 1
elif opcode == 0x0E:
varA = self.replace_enum(argv[0])
varB = self.replace_enum(argv[1])
if varB == "SI_SAVE_VAR(0)":
if varB in SAVE_VARS:
varA = self.replace_enum(argv[0])
self.write_line(f"if ({varA} <= {varB}) {{")
self.save_variable = ""
self.indent += 1
elif opcode == 0x0F:
varA = self.replace_enum(argv[0])
varB = self.replace_enum(argv[1])
if varB == "SI_SAVE_VAR(0)":
if varB in SAVE_VARS:
varA = self.replace_enum(argv[0])
self.write_line(f"if ({varA} >= {varB}) {{")
self.save_variable = ""
self.indent += 1
elif opcode == 0x10:
self.write_line(f"if ({self.var(argv[0])} & {self.var(argv[1])}) {{")
@ -778,7 +789,6 @@ class ScriptDSLDisassembler(ScriptDisassembler):
elif opcode == 0x24:
varA = self.replace_enum(argv[0])
varB = self.replace_enum(argv[1])
self.save_variable = ""
self.write_line(f"{varA} = {varB};")
elif opcode == 0x25: self.write_line(f"{self.var(argv[0])} =c 0x{argv[1]:X};")
elif opcode == 0x26:
@ -866,19 +876,24 @@ class ScriptDSLDisassembler(ScriptDisassembler):
else:
raise UnsupportedScript(f"DSL does not support script opcode 0x{opcode:X}")
# reset this at the end of each instruction
self.save_variable = ""
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("file", type=str, help="File to dissassemble from")
parser.add_argument("--o", "-o", type=lambda x: int(x, 0), default=0, dest="offset", required=False, help="Offset to start dissassembling from")
parser.add_argument("--e", "-e", type=lambda x: int(x, 0), default=0, dest="end", required=False, help="End offset to stop dissassembling from.\nOnly used as a way to find valid scripts.")
parser.add_argument("offset", type=lambda x: int(x, 16), default=0, help="Offset to start dissassembling from")
parser.add_argument("-end", "-e", "--e", type=lambda x: int(x, 16), default=0, dest="end", required=False, help="End offset to stop dissassembling from.\nOnly used as a way to find valid scripts.")
args = parser.parse_args()
get_constants()
if args.end > args.offset:
# Search the given memory range and report scripts
with open(args.file, "rb") as f:
while args.offset < args.end:
f.seek(args.offset)
@ -886,8 +901,14 @@ if __name__ == "__main__":
script = ScriptDSLDisassembler(f)
try:
script_text = script.disassemble()
if script.instructions > 1:
print(f"Valid script found at 0x{args.offset:X}")
if script.instructions > 1 and "SI_CMD" not in script_text and "break;" not in script_text:
print(f"Script read from 0x{script.start_pos:X} to 0x{script.end_pos:X} "
f"(0x{script.end_pos - script.start_pos:X} bytes, {script.instructions} instructions)")
print()
print(script_text, end="")
print()
#print(f"Valid script found at 0x{args.offset:X}")
args.offset = script.end_pos
else:
args.offset += 4