mirror of
https://github.com/pmret/papermario.git
synced 2024-11-08 12:02:30 +01:00
new dsl syntax
This commit is contained in:
parent
91f3517b86
commit
21ab7fed6c
4
Makefile
4
Makefile
@ -135,7 +135,7 @@ $(BUILD_DIR)/%.c.o: %.c $(MDEPS)
|
||||
$(CPP) $(CPPFLAGS) -o - $< $(CPPMFLAGS) | $(CC) $(CFLAGS) -o - | $(OLD_AS) $(OLDASFLAGS) -o $@ -
|
||||
|
||||
# Compile C files (with DSL macros)
|
||||
$(foreach cfile, $(DSL_C_FILES), $(BUILD_DIR)/$(cfile).o): $(BUILD_DIR)/%.c.o: %.c $(MDEPS)
|
||||
$(foreach cfile, $(DSL_C_FILES), $(BUILD_DIR)/$(cfile).o): $(BUILD_DIR)/%.c.o: %.c $(MDEPS) tools/compile_dsl_macros.py
|
||||
@mkdir -p $(shell dirname $@)
|
||||
$(CPP) $(CPPFLAGS) -o - $< $(CPPMFLAGS) | tools/compile_dsl_macros.py | $(CC) $(CFLAGS) -o - | $(OLD_AS) $(OLDASFLAGS) -o $@ -
|
||||
|
||||
@ -151,7 +151,7 @@ $(BUILD_DIR)/bin/assets/%: bin/assets/%.bin
|
||||
@mkdir -p $(shell dirname $@)
|
||||
@cp $< $@
|
||||
|
||||
$(ASSETS_BIN): $(ASSET_FILES) $(YAY0_ASSET_FILES)
|
||||
$(ASSETS_BIN): $(ASSET_FILES) $(YAY0_ASSET_FILES) sources.mk
|
||||
@mkdir -p $(shell dirname $@)
|
||||
@echo "building $@"
|
||||
@$(PYTHON) tools/build_assets_bin.py $@ $(ASSET_FILES)
|
||||
|
@ -29,17 +29,18 @@ script_parser = Lark(r"""
|
||||
block: "{" NEWLINE* (stmt STMT_SEP)* NEWLINE* "}"
|
||||
|
||||
?stmt: call
|
||||
| label ":" -> label_decl
|
||||
| label ":" [stmt] -> label_decl
|
||||
| "goto" label -> label_goto
|
||||
| if_stmt
|
||||
| "return" -> return_stmt
|
||||
| "break" -> break_stmt
|
||||
| "sleep" expr -> sleep_stmt
|
||||
| "sleep" expr "secs" -> sleep_secs_stmt
|
||||
| "spawn" expr -> spawn_stmt
|
||||
| "await" expr -> await_stmt
|
||||
| lhs "=" "spawn" expr -> spawn_set_stmt
|
||||
| lhs set_op expr -> set_stmt
|
||||
| lhs ":=" expr -> set_const_stmt
|
||||
| "const" lhs set_op expr -> set_const_stmt
|
||||
| bind_stmt
|
||||
| bind_set_stmt
|
||||
| "unbind" -> unbind_stmt
|
||||
@ -49,12 +50,19 @@ script_parser = Lark(r"""
|
||||
| kill_stmt
|
||||
| loop_stmt
|
||||
| loop_until_stmt
|
||||
| ["await"] block -> block_stmt
|
||||
| "spawn" block -> spawn_block_stmt
|
||||
| "parallel" block -> parallel_block_stmt
|
||||
|
||||
call: CNAME "(" [expr ("," expr)* [","]] ")"
|
||||
|
||||
if_stmt: "if" expr if_op expr block ["else" block]
|
||||
?if_op: "==" -> if_op_eq
|
||||
| "!=" -> if_op_ne
|
||||
| ">" -> if_op_gt
|
||||
| "<" -> if_op_lt
|
||||
| ">=" -> if_op_ge
|
||||
| "<=" -> if_op_le
|
||||
|
||||
suspend_stmt: "suspend" control_type expr ("," control_type expr)* [","]
|
||||
resume_stmt: "resume" control_type expr ("," control_type expr)* [","]
|
||||
@ -84,6 +92,11 @@ script_parser = Lark(r"""
|
||||
| "*=" -> set_op_mul
|
||||
| "/=" -> set_op_div
|
||||
| "%=" -> set_op_mod
|
||||
| "&=" -> set_op_and
|
||||
| "|=" -> set_op_or
|
||||
| ":=" -> set_op_eq_const
|
||||
| ":&=" -> set_op_and_const
|
||||
| ":|=" -> set_op_or_const
|
||||
|
||||
c_const_expr: c_const_expr_internal
|
||||
c_const_expr_internal: "(" (c_const_expr_internal | NOT_PARENS)+ ")"
|
||||
@ -175,6 +188,22 @@ class LoopUntilCtx(CmdCtx):
|
||||
def break_opcode(self, meta):
|
||||
raise CompileError("breaking out of a loop..until is not supported (hint: use a label)", meta)
|
||||
|
||||
class LabelCtx(CmdCtx):
|
||||
def __init__(self, label):
|
||||
super().__init__()
|
||||
self.label = label
|
||||
|
||||
# TODO: implement break_opcode so you can do lbl: loop { break lbl }
|
||||
|
||||
class BlockCtx(CmdCtx):
|
||||
pass
|
||||
|
||||
class SpawnCtx(CmdCtx):
|
||||
pass
|
||||
|
||||
class ParallelCtx(CmdCtx):
|
||||
pass
|
||||
|
||||
class CompileError(Exception):
|
||||
def __init__(self, message, meta):
|
||||
super().__init__(message)
|
||||
@ -255,6 +284,10 @@ class Compile(Transformer):
|
||||
return [ Cmd(op, a, b, meta=tree.meta), *block, Cmd(0x13) ]
|
||||
def if_op_eq(self, tree): return 0x0A
|
||||
def if_op_ne(self, tree): return 0x0B
|
||||
def if_op_lt(self, tree): return 0x0C
|
||||
def if_op_gt(self, tree): return 0x0D
|
||||
def if_op_le(self, tree): return 0x0E
|
||||
def if_op_ge(self, tree): return 0x0F
|
||||
|
||||
def loop_stmt(self, tree):
|
||||
expr = tree.children.pop(0) if len(tree.children) > 1 else 0
|
||||
@ -336,6 +369,8 @@ class Compile(Transformer):
|
||||
|
||||
def sleep_stmt(self, tree):
|
||||
return Cmd(0x08, tree.children[0], meta=tree.meta)
|
||||
def sleep_secs_stmt(self, tree):
|
||||
return Cmd(0x09, tree.children[0], meta=tree.meta)
|
||||
|
||||
def bind_stmt(self, tree):
|
||||
script, trigger, target = tree.children
|
||||
@ -366,12 +401,16 @@ class Compile(Transformer):
|
||||
raise CompileError(f"operation `{opcodes['__op__']}' not supported for ints", tree.meta)
|
||||
return Cmd(opcode, lhs, rhs)
|
||||
def set_const_stmt(self, tree):
|
||||
lhs, rhs = tree.children
|
||||
return Cmd(0x25, lhs, rhs)
|
||||
lhs, opcodes, rhs = tree.children
|
||||
opcode = opcodes.get("const", None)
|
||||
if not opcode:
|
||||
raise CompileError(f"operation `{opcodes['__op__']}' not supported for consts", tree.meta)
|
||||
return Cmd(opcode, lhs, rhs)
|
||||
def set_op_eq(self, tree):
|
||||
return {
|
||||
"__op__": "=",
|
||||
"int": 0x24,
|
||||
"const": 0x25,
|
||||
"float": 0x26,
|
||||
}
|
||||
def set_op_add(self, tree):
|
||||
@ -403,10 +442,37 @@ class Compile(Transformer):
|
||||
"__op__": "%",
|
||||
"int": 0x2B,
|
||||
}
|
||||
def set_op_and(self, tree):
|
||||
return {
|
||||
"__op__": "&",
|
||||
"int": 0x3F,
|
||||
"const": 0x41,
|
||||
}
|
||||
def set_op_or(self, tree):
|
||||
return {
|
||||
"__op__": "|",
|
||||
"int": 0x40,
|
||||
"const": 0x42,
|
||||
}
|
||||
|
||||
def label_decl(self, tree):
|
||||
label = tree.children[0]
|
||||
return Cmd(0x03, label, meta=tree.meta)
|
||||
if len(tree.children) == 0:
|
||||
label = tree.children[0]
|
||||
return Cmd(0x03, label, meta=tree.meta)
|
||||
else:
|
||||
label, cmd_or_block = tree.children
|
||||
|
||||
if type(cmd_or_block) is not list:
|
||||
cmd_or_block = [cmd_or_block]
|
||||
|
||||
for cmd in cmd_or_block:
|
||||
if isinstance(cmd, BaseCmd):
|
||||
cmd.add_context(LabelCtx(label))
|
||||
|
||||
return [
|
||||
Cmd(0x03, label, meta=tree.meta),
|
||||
*cmd_or_block
|
||||
]
|
||||
def label_goto(self, tree):
|
||||
label = tree.children[0]
|
||||
return Cmd(0x04, label, meta=tree.meta)
|
||||
@ -416,6 +482,25 @@ class Compile(Transformer):
|
||||
return self.alloc.labels.index(name)
|
||||
raise CompileError(f"label `{name}' is undeclared", tree.meta)
|
||||
|
||||
def block_stmt(self, tree):
|
||||
block, = tree.children
|
||||
for cmd in block:
|
||||
if isinstance(cmd, BaseCmd):
|
||||
cmd.add_context(BlockCtx())
|
||||
return block
|
||||
def spawn_block_stmt(self, tree):
|
||||
block, = tree.children
|
||||
for cmd in block:
|
||||
if isinstance(cmd, BaseCmd):
|
||||
cmd.add_context(SpawnCtx())
|
||||
return [ Cmd(0x56, meta=tree.meta), *block, Cmd(0x57) ]
|
||||
def parallel_block_stmt(self, tree):
|
||||
block, = tree.children
|
||||
for cmd in block:
|
||||
if isinstance(cmd, BaseCmd):
|
||||
cmd.add_context(ParallelCtx())
|
||||
return [ Cmd(0x58, meta=tree.meta), *block, Cmd(0x59) ]
|
||||
|
||||
def compile_script(s):
|
||||
tree = script_parser.parse(s)
|
||||
|
||||
|
@ -6,7 +6,7 @@ import yaml
|
||||
import json
|
||||
from struct import unpack
|
||||
|
||||
from disasm_script import disassemble as disassemble_script
|
||||
import disasm_script
|
||||
|
||||
def disassemble(bytes, offset, midx, symbol_map = {}, map_name = "map"):
|
||||
out = ""
|
||||
@ -15,6 +15,9 @@ def disassemble(bytes, offset, midx, symbol_map = {}, map_name = "map"):
|
||||
while len(midx) > 0:
|
||||
struct = midx.pop(0)
|
||||
name = struct["name"]
|
||||
|
||||
print(name)
|
||||
|
||||
if name == "Script_Main": name = f"M(Main)"
|
||||
|
||||
#print(f"{offset:X} ({name}, start = {struct['start']:X}, len = {struct['length']:X})")
|
||||
@ -28,7 +31,12 @@ def disassemble(bytes, offset, midx, symbol_map = {}, map_name = "map"):
|
||||
|
||||
# format struct
|
||||
if struct["type"].startswith("Script"):
|
||||
out += disassemble_script(bytes, f"M({name})", symbol_map)
|
||||
pos = bytes.tell()
|
||||
try:
|
||||
out += disasm_script.ScriptDSLDisassembler(bytes, f"M({name})", symbol_map).disassemble()
|
||||
except disasm_script.UnsupportedScript as e:
|
||||
bytes.seek(pos)
|
||||
out += disasm_script.ScriptDisassembler(bytes, f"M({name})", symbol_map).disassemble()
|
||||
elif struct["type"] == "Padding":
|
||||
# nops at end of file
|
||||
bytes.seek(offset % 4, 1)
|
||||
@ -56,7 +64,7 @@ def disassemble(bytes, offset, midx, symbol_map = {}, map_name = "map"):
|
||||
out += f" .background = &gBackgroundImage,\n"
|
||||
elif bg != 0:
|
||||
raise Exception(f"unknown MapConfig background {bg:X}")
|
||||
out += f" .tattle = {tattle:X},\n"
|
||||
out += f" .tattle = 0x{tattle:X},\n"
|
||||
|
||||
out += f"}};\n"
|
||||
elif struct["type"] == "ASCII":
|
||||
@ -218,4 +226,5 @@ if __name__ == "__main__":
|
||||
|
||||
if len(disasm.strip()) > 0:
|
||||
with open(f"{src_dir}/{rom_addr:X}.bin.c", "w") as f:
|
||||
f.write(disasm)
|
||||
f.write(f'#include "{map_name}.h"\n\n')
|
||||
f.write(disasm.rstrip() + "\n")
|
||||
|
@ -2,17 +2,19 @@
|
||||
|
||||
import sys
|
||||
|
||||
_star_rod_lib = None
|
||||
def star_rod_lib():
|
||||
global _star_rod_lib
|
||||
_script_lib = None
|
||||
def script_lib():
|
||||
global _script_lib
|
||||
|
||||
if not _star_rod_lib:
|
||||
_star_rod_lib = {}
|
||||
if not _script_lib:
|
||||
_script_lib = {}
|
||||
|
||||
from pathlib import Path
|
||||
from os import path
|
||||
import re
|
||||
|
||||
# star rod database
|
||||
"""
|
||||
LIB_LINE_RE = re.compile(r"\s+:\s+")
|
||||
NAME_RE = re.compile(r"({[^}]*})?\s*([a-zA-Z0-9_]+)")
|
||||
|
||||
@ -28,46 +30,71 @@ def star_rod_lib():
|
||||
if name := NAME_RE.match(parts[2]):
|
||||
name = name.group(2)
|
||||
|
||||
_star_rod_lib[vaddr] = name
|
||||
|
||||
"""
|
||||
if "map" in str(filename):
|
||||
if kind == "api":
|
||||
print(f"ApiStatus {name}(ScriptInstance* script, s32 isInitialCall);")
|
||||
elif kind == "scr":
|
||||
print(f"extern Script {name};")
|
||||
"""
|
||||
_script_lib[vaddr] = name
|
||||
except:
|
||||
pass
|
||||
"""
|
||||
|
||||
return _star_rod_lib
|
||||
# symbol_addrs.txt
|
||||
with open(Path(path.dirname(__file__), "symbol_addrs.txt"), "r") as file:
|
||||
for line in file.readlines():
|
||||
s = line.split(";")
|
||||
name = s[0]
|
||||
addr = s[1]
|
||||
_script_lib[int(addr, 16)] = name
|
||||
|
||||
def disassemble(bytes, script_name = "script", symbol_map = {}):
|
||||
out = ""
|
||||
prefix = ""
|
||||
return _script_lib
|
||||
|
||||
indent = 1
|
||||
indent_used = False
|
||||
class ScriptDisassembler:
|
||||
def __init__(self, bytes, script_name = "script", symbol_map = {}):
|
||||
self.bytes = bytes
|
||||
self.script_name = script_name
|
||||
self.symbol_map = symbol_map
|
||||
|
||||
def write_line(line):
|
||||
nonlocal out, indent, indent_used
|
||||
if indent < 0: indent = 0
|
||||
if indent > 1: indent_used = True
|
||||
out += " " * indent
|
||||
out += line
|
||||
out += "\n"
|
||||
def prefix_line(line):
|
||||
nonlocal prefix
|
||||
prefix += line
|
||||
prefix += "\n"
|
||||
self.out = ""
|
||||
self.prefix = ""
|
||||
|
||||
def var(arg):
|
||||
if arg in symbol_map:
|
||||
return symbol_map[arg]
|
||||
self.indent = 1
|
||||
self.indent_used = False
|
||||
|
||||
self.done = False
|
||||
|
||||
def disassemble(self):
|
||||
while True:
|
||||
opcode = self.read_word()
|
||||
argc = self.read_word()
|
||||
|
||||
if opcode > 0xFF or argc > 0xFF:
|
||||
raise Exception(f"script '{script_name}' is malformed")
|
||||
|
||||
argv = []
|
||||
for i in range(0, argc):
|
||||
argv.append(self.read_word())
|
||||
|
||||
self.disassemble_command(opcode, argc, argv)
|
||||
|
||||
if self.done:
|
||||
return self.prefix + self.out
|
||||
|
||||
def write_line(self, line):
|
||||
if self.indent < 0: self.indent = 0
|
||||
if self.indent > 1: self.indent_used = True
|
||||
|
||||
self.out += " " * self.indent
|
||||
self.out += line
|
||||
self.out += "\n"
|
||||
|
||||
def prefix_line(self, line):
|
||||
self.prefix += line
|
||||
self.prefix += "\n"
|
||||
|
||||
def var(self, arg):
|
||||
if arg in self.symbol_map:
|
||||
return self.symbol_map[arg]
|
||||
|
||||
v = arg - 2**32 # convert to s32
|
||||
if v > -250000000:
|
||||
if v <= -220000000: return f"SI_FIXED({(v + 230000000) / 1024}f)"
|
||||
if v <= -220000000: return f"SI_FIXED({(v + 230000000) / 1024})"
|
||||
elif v <= -200000000: return f"SI_ARRAY_FLAG({v + 210000000})"
|
||||
elif v <= -180000000: return f"SI_ARRAY({v + 190000000})"
|
||||
elif v <= -160000000: return f"SI_SAVE_VAR({v + 170000000})"
|
||||
@ -86,12 +113,12 @@ def disassemble(bytes, script_name = "script", symbol_map = {}):
|
||||
else:
|
||||
return f"{arg}"
|
||||
|
||||
def addr_ref(addr):
|
||||
if addr in symbol_map:
|
||||
return symbol_map[addr]
|
||||
return star_rod_lib().get(addr, f"0x{addr:08X}")
|
||||
def addr_ref(self, addr):
|
||||
if addr in self.symbol_map:
|
||||
return self.symbol_map[addr]
|
||||
return script_lib().get(addr, f"0x{addr:08X}")
|
||||
|
||||
def trigger(trigger):
|
||||
def trigger(self, trigger):
|
||||
if trigger == 0x00000080: trigger = "TriggerFlag_FLOOR_TOUCH"
|
||||
if trigger == 0x00800000: trigger = "TriggerFlag_FLOOR_ABOVE"
|
||||
if trigger == 0x00000800: trigger = "TriggerFlag_FLOOR_INTERACT"
|
||||
@ -106,206 +133,391 @@ def disassemble(bytes, script_name = "script", symbol_map = {}):
|
||||
if trigger == 0x00100000: trigger = "TriggerFlag_BOMB"
|
||||
return trigger
|
||||
|
||||
def read_word():
|
||||
return int.from_bytes(bytes.read(4), byteorder="big")
|
||||
|
||||
while True:
|
||||
opcode = read_word()
|
||||
argc = read_word()
|
||||
|
||||
if opcode > 0xFF or argc > 0xFF:
|
||||
return f"/* malformed script: {script_name} */\n"
|
||||
|
||||
argv = []
|
||||
for i in range(0, argc):
|
||||
argv.append(read_word())
|
||||
def read_word(self):
|
||||
return int.from_bytes(self.bytes.read(4), byteorder="big")
|
||||
|
||||
def disassemble_command(self, opcode, argc, argv):
|
||||
if opcode == 0x01:
|
||||
write_line("SI_END(),")
|
||||
indent -= 1
|
||||
self.write_line("SI_END(),")
|
||||
self.indent -= 1
|
||||
|
||||
if indent_used:
|
||||
prefix_line("// *INDENT-OFF*")
|
||||
prefix_line(f"Script {script_name} = {{")
|
||||
write_line("};")
|
||||
write_line("// *INDENT-ON*")
|
||||
if self.indent_used:
|
||||
self.prefix_line("// *INDENT-OFF*")
|
||||
self.prefix_line(f"Script {self.script_name} = {{")
|
||||
self.write_line("};")
|
||||
self.write_line("// *INDENT-ON*")
|
||||
else:
|
||||
prefix_line(f"Script {script_name} = {{")
|
||||
write_line("};")
|
||||
self.prefix_line(f"Script {self.script_name} = {{")
|
||||
self.write_line("};")
|
||||
|
||||
return prefix + out
|
||||
elif opcode == 0x02: write_line(f"SI_RETURN(),")
|
||||
elif opcode == 0x03: write_line(f"SI_LABEL({var(argv[0])}),")
|
||||
elif opcode == 0x04: write_line(f"SI_GOTO({var(argv[0])}),")
|
||||
self.done = True
|
||||
elif opcode == 0x02: self.write_line(f"SI_RETURN(),")
|
||||
elif opcode == 0x03: self.write_line(f"SI_LABEL({self.var(argv[0])}),")
|
||||
elif opcode == 0x04: self.write_line(f"SI_GOTO({self.var(argv[0])}),")
|
||||
elif opcode == 0x05:
|
||||
write_line(f"SI_LOOP({var(argv[0])}),")
|
||||
indent += 1
|
||||
self.write_line(f"SI_LOOP({self.var(argv[0])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x06:
|
||||
indent -= 1
|
||||
write_line("SI_END_LOOP(),")
|
||||
elif opcode == 0x07: write_line(f"SI_BREAK_LOOP(),")
|
||||
elif opcode == 0x08: write_line(f"SI_WAIT_FRAMES({var(argv[0])}),")
|
||||
elif opcode == 0x09: write_line(f"SI_WAIT_SECS({var(argv[0])}),")
|
||||
self.indent -= 1
|
||||
self.write_line("SI_END_LOOP(),")
|
||||
elif opcode == 0x07: self.write_line(f"SI_BREAK_LOOP(),")
|
||||
elif opcode == 0x08: self.write_line(f"SI_WAIT_FRAMES({self.var(argv[0])}),")
|
||||
elif opcode == 0x09: self.write_line(f"SI_WAIT_SECS({self.var(argv[0])}),")
|
||||
elif opcode == 0x0A:
|
||||
write_line(f"SI_IF_EQ({var(argv[0])}, {var(argv[1])}),")
|
||||
indent += 1
|
||||
self.write_line(f"SI_IF_EQ({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x0B:
|
||||
write_line(f"SI_IF_NE({var(argv[0])}, {var(argv[1])}),")
|
||||
indent += 1
|
||||
self.write_line(f"SI_IF_NE({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x0C:
|
||||
write_line(f"SI_IF_LT({var(argv[0])}, {var(argv[1])}),")
|
||||
indent += 1
|
||||
self.write_line(f"SI_IF_LT({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x0D:
|
||||
write_line(f"SI_IF_GT({var(argv[0])}, {var(argv[1])}),")
|
||||
indent += 1
|
||||
self.write_line(f"SI_IF_GT({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x0E:
|
||||
write_line(f"SI_IF_LE({var(argv[0])}, {var(argv[1])}),")
|
||||
indent += 1
|
||||
self.write_line(f"SI_IF_LE({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x0F:
|
||||
write_line(f"SI_IF_GE({var(argv[0])}, {var(argv[1])}),")
|
||||
indent += 1
|
||||
self.write_line(f"SI_IF_GE({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x10:
|
||||
write_line(f"SI_IF_BITS_ON({var(argv[0])}, {var(argv[1])}),")
|
||||
indent += 1
|
||||
self.write_line(f"SI_IF_BITS_ON({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x11:
|
||||
write_line(f"SI_IF_BITS_OFF({var(argv[0])}, {var(argv[1])}),")
|
||||
indent += 1
|
||||
elif opcode == 0x12: write_line(f"SI_ELSE(),")
|
||||
self.write_line(f"SI_IF_BITS_OFF({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x12:
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_ELSE(),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x13:
|
||||
indent -= 1
|
||||
write_line(f"SI_END_IF(),")
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_END_IF(),")
|
||||
elif opcode == 0x14:
|
||||
write_line(f"SI_SWITCH({var(argv[0])}),")
|
||||
indent += 2
|
||||
self.write_line(f"SI_SWITCH({self.var(argv[0])}),")
|
||||
self.indent += 2
|
||||
elif opcode == 0x15:
|
||||
write_line(f"SI_SWITCH_CONST(0x{argv[0]:X}),")
|
||||
indent += 2
|
||||
self.write_line(f"SI_SWITCH_CONST(0x{argv[0]:X}),")
|
||||
self.indent += 2
|
||||
elif opcode == 0x16:
|
||||
indent -= 1
|
||||
write_line(f"SI_CASE_EQ({var(argv[0])}),")
|
||||
indent += 1
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_CASE_EQ({self.var(argv[0])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x17:
|
||||
indent -= 1
|
||||
write_line(f"SI_CASE_NE({var(argv[0])}),")
|
||||
indent += 1
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_CASE_NE({self.var(argv[0])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x18:
|
||||
indent -= 1
|
||||
write_line(f"SI_CASE_LT({var(argv[0])}),")
|
||||
indent += 1
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_CASE_LT({self.var(argv[0])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x19:
|
||||
indent -= 1
|
||||
write_line(f"SI_CASE_GT({var(argv[0])}),")
|
||||
indent += 1
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_CASE_GT({self.var(argv[0])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x1A:
|
||||
indent -= 1
|
||||
write_line(f"SI_CASE_LE({var(argv[0])}),")
|
||||
indent += 1
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_CASE_LE({self.var(argv[0])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x1B:
|
||||
indent -= 1
|
||||
write_line(f"SI_CASE_GE({var(argv[0])}),")
|
||||
indent += 1
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_CASE_GE({self.var(argv[0])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x1C:
|
||||
indent -= 1
|
||||
write_line(f"SI_CASE_DEFAULT(),")
|
||||
indent += 1
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_CASE_DEFAULT(),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x1D:
|
||||
indent -= 1
|
||||
write_line(f"SI_CASE_OR_EQ({var(argv[0])}),")
|
||||
indent += 1
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_CASE_OR_EQ({self.var(argv[0])}),")
|
||||
self.indent += 1
|
||||
# opcode 0x1E?
|
||||
elif opcode == 0x1F:
|
||||
indent -= 1
|
||||
write_line(f"SI_CASE_BITS_ON({var(argv[0])}),")
|
||||
indent += 1
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_CASE_BITS_ON({self.var(argv[0])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x20:
|
||||
indent -= 1
|
||||
write_line(f"SI_END_MULTI_CASE(),")
|
||||
indent += 1
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_END_MULTI_CASE(),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x21:
|
||||
indent -= 1
|
||||
write_line(f"SI_CASE_RANGE({var(argv[0])}, {var(argv[1])}),")
|
||||
indent += 1
|
||||
elif opcode == 0x22: write_line(f"SI_BREAK_CASE(),")
|
||||
self.indent -= 1
|
||||
self.write_line(f"SI_CASE_RANGE({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x22: self.write_line(f"SI_BREAK_CASE(),")
|
||||
elif opcode == 0x23:
|
||||
indent -= 2
|
||||
write_line(f"SI_END_SWITCH(),")
|
||||
elif opcode == 0x24: write_line(f"SI_SET({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x25: write_line(f"SI_SET_CONST({var(argv[0])}, 0x{argv[1]:X}),")
|
||||
elif opcode == 0x26: write_line(f"SI_SET_F({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x27: write_line(f"SI_ADD({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x28: write_line(f"SI_SUB({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x29: write_line(f"SI_MUL({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x2A: write_line(f"SI_DIV({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x2B: write_line(f"SI_MOD({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x2C: write_line(f"SI_ADD_F({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x2D: write_line(f"SI_SUB_F({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x2E: write_line(f"SI_MUL_F({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x2F: write_line(f"SI_DIV_F({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x30: write_line(f"SI_USE_BUFFER({var(argv[0])}),")
|
||||
self.indent -= 2
|
||||
self.write_line(f"SI_END_SWITCH(),")
|
||||
elif opcode == 0x24: self.write_line(f"SI_SET({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x25: self.write_line(f"SI_SET_CONST({self.var(argv[0])}, 0x{argv[1]:X}),")
|
||||
elif opcode == 0x26: self.write_line(f"SI_SET_F({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x27: self.write_line(f"SI_ADD({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x28: self.write_line(f"SI_SUB({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x29: self.write_line(f"SI_MUL({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x2A: self.write_line(f"SI_DIV({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x2B: self.write_line(f"SI_MOD({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x2C: self.write_line(f"SI_ADD_F({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x2D: self.write_line(f"SI_SUB_F({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x2E: self.write_line(f"SI_MUL_F({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x2F: self.write_line(f"SI_DIV_F({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x30: self.write_line(f"SI_USE_BUFFER({self.var(argv[0])}),")
|
||||
# TODO: SI_BUF commands
|
||||
elif opcode == 0x3C: write_line(f"SI_USE_ARRAY({var(argv[0])}),")
|
||||
elif opcode == 0x3D: write_line(f"SI_NEW_ARRAY({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x3E: write_line(f"SI_USE_FLAGS({var(argv[0])}),")
|
||||
elif opcode == 0x3F: write_line(f"SI_AND({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x40: write_line(f"SI_OR({var(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x41: write_line(f"SI_AND_CONST({var(argv[0])}, 0x{argv[1]:X})")
|
||||
elif opcode == 0x42: write_line(f"SI_OR_CONST({var(argv[0])}, 0x{argv[1]:X})")
|
||||
elif opcode == 0x3C: self.write_line(f"SI_USE_ARRAY({self.var(argv[0])}),")
|
||||
elif opcode == 0x3D: self.write_line(f"SI_NEW_ARRAY({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x3E: self.write_line(f"SI_USE_FLAGS({self.var(argv[0])}),")
|
||||
elif opcode == 0x3F: self.write_line(f"SI_AND({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x40: self.write_line(f"SI_OR({self.var(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x41: self.write_line(f"SI_AND_CONST({self.var(argv[0])}, 0x{argv[1]:X})")
|
||||
elif opcode == 0x42: self.write_line(f"SI_OR_CONST({self.var(argv[0])}, 0x{argv[1]:X})")
|
||||
elif opcode == 0x43:
|
||||
argv_str = ""
|
||||
for arg in argv[1:]:
|
||||
argv_str += ", "
|
||||
argv_str += var(arg)
|
||||
argv_str += self.var(arg)
|
||||
|
||||
write_line(f"SI_CALL({addr_ref(argv[0])}{argv_str}),")
|
||||
elif opcode == 0x44: write_line(f"SI_EXEC({addr_ref(argv[0])}),")
|
||||
elif opcode == 0x45: write_line(f"SI_EXEC_GET_ID({addr_ref(argv[0])}, {var(argv[1])}),")
|
||||
elif opcode == 0x46: write_line(f"SI_EXEC_WAIT({addr_ref(argv[0])}),")
|
||||
self.write_line(f"SI_CALL({self.addr_ref(argv[0])}{argv_str}),")
|
||||
elif opcode == 0x44: self.write_line(f"SI_EXEC({self.addr_ref(argv[0])}),")
|
||||
elif opcode == 0x45: self.write_line(f"SI_EXEC_GET_ID({self.addr_ref(argv[0])}, {self.var(argv[1])}),")
|
||||
elif opcode == 0x46: self.write_line(f"SI_EXEC_WAIT({self.addr_ref(argv[0])}),")
|
||||
elif opcode == 0x47:
|
||||
if argv[3] != 1:
|
||||
raise "BIND argv[3] != 1"
|
||||
|
||||
write_line(f"SI_BIND({addr_ref(argv[0])}, {trigger(argv[1])}, {var(argv[2])}, {'NULL' if argv[4] == 0 else var(argv[4])}),")
|
||||
elif opcode == 0x48: write_line(f"SI_UNBIND_ME(),")
|
||||
elif opcode == 0x49: write_line(f"SI_KILL({var(argv[0])}),")
|
||||
elif opcode == 0x4A: write_line(f"SI_JUMP({var(argv[0])}),")
|
||||
elif opcode == 0x4B: write_line(f"SI_PRIORITY({var(argv[0])}),")
|
||||
elif opcode == 0x4C: write_line(f"SI_TIMESCALE({var(argv[0])}),")
|
||||
elif opcode == 0x4D: write_line(f"SI_GROUP({var(argv[0])}),")
|
||||
assert argv[3] == 1
|
||||
self.write_line(f"SI_BIND({self.addr_ref(argv[0])}, {self.trigger(argv[1])}, {self.var(argv[2])}, {'NULL' if argv[4] == 0 else self.var(argv[4])}),")
|
||||
elif opcode == 0x48: self.write_line(f"SI_UNBIND_ME(),")
|
||||
elif opcode == 0x49: self.write_line(f"SI_KILL({self.var(argv[0])}),")
|
||||
elif opcode == 0x4A: self.write_line(f"SI_JUMP({self.var(argv[0])}),")
|
||||
elif opcode == 0x4B: self.write_line(f"SI_PRIORITY({self.var(argv[0])}),")
|
||||
elif opcode == 0x4C: self.write_line(f"SI_TIMESCALE({self.var(argv[0])}),")
|
||||
elif opcode == 0x4D: self.write_line(f"SI_GROUP({self.var(argv[0])}),")
|
||||
elif opcode == 0x4E:
|
||||
if argv[4] != 0:
|
||||
raise "BIND_PADLOCK argv[4] != NULL"
|
||||
if argv[5] != 1:
|
||||
raise "BIND_PADLOCK argv[5] != 1"
|
||||
|
||||
write_line(f"SI_BIND_PADLOCK({addr_ref(argv[0])}, {trigger(argv[1])}, {var(argv[2])}, {var(argv[3])}),")
|
||||
elif opcode == 0x4F: write_line(f"SI_SUSPEND_GROUP({var(argv[0])}),")
|
||||
elif opcode == 0x50: write_line(f"SI_RESUME_GROUP({var(argv[0])}),")
|
||||
elif opcode == 0x51: write_line(f"SI_SUSPEND_GROUP_NOT_ME({var(argv[0])}),")
|
||||
elif opcode == 0x52: write_line(f"SI_RESUME_GROUP_NOT_ME({var(argv[0])}),")
|
||||
elif opcode == 0x53: write_line(f"SI_SUSPEND({var(argv[0])}),")
|
||||
elif opcode == 0x54: write_line(f"SI_RESUME({var(argv[0])}),")
|
||||
elif opcode == 0x55: write_line(f"SI_EXISTS({var(argv[0])}),")
|
||||
assert argv[4] == 0
|
||||
assert argv[5] == 1
|
||||
self.write_line(f"SI_BIND_PADLOCK({self.addr_ref(argv[0])}, {self.trigger(argv[1])}, {self.var(argv[2])}, {self.var(argv[3])}),")
|
||||
elif opcode == 0x4F: self.write_line(f"SI_SUSPEND_GROUP({self.var(argv[0])}),")
|
||||
elif opcode == 0x50: self.write_line(f"SI_RESUME_GROUP({self.var(argv[0])}),")
|
||||
elif opcode == 0x51: self.write_line(f"SI_SUSPEND_GROUP_NOT_ME({self.var(argv[0])}),")
|
||||
elif opcode == 0x52: self.write_line(f"SI_RESUME_GROUP_NOT_ME({self.var(argv[0])}),")
|
||||
elif opcode == 0x53: self.write_line(f"SI_SUSPEND({self.var(argv[0])}),")
|
||||
elif opcode == 0x54: self.write_line(f"SI_RESUME({self.var(argv[0])}),")
|
||||
elif opcode == 0x55: self.write_line(f"SI_EXISTS({self.var(argv[0])}),")
|
||||
elif opcode == 0x56:
|
||||
write_line("SI_THREAD(),")
|
||||
indent += 1
|
||||
self.write_line("SI_THREAD(),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x57:
|
||||
indent -= 1
|
||||
write_line("SI_END_THREAD(),")
|
||||
self.indent -= 1
|
||||
self.write_line("SI_END_THREAD(),")
|
||||
elif opcode == 0x58:
|
||||
write_line("SI_CHILD_THREAD(),")
|
||||
indent += 1
|
||||
self.write_line("SI_CHILD_THREAD(),")
|
||||
self.indent += 1
|
||||
elif opcode == 0x59:
|
||||
indent -= 1
|
||||
write_line("SI_END_CHILD_THREAD(),")
|
||||
self.indent -= 1
|
||||
self.write_line("SI_END_CHILD_THREAD(),")
|
||||
else:
|
||||
# unknown opcode
|
||||
argv_str = ""
|
||||
for arg in argv:
|
||||
argv_str += ", "
|
||||
argv_str += f"0x{arg:X}"
|
||||
write_line(f"SI_CMD(0x{opcode:02X}{argv_str}),")
|
||||
self.write_line(f"SI_CMD(0x{opcode:02X}{argv_str}),")
|
||||
|
||||
raise "Reached end of data before END command"
|
||||
class UnsupportedScript(Exception):
|
||||
pass
|
||||
|
||||
class ScriptDSLDisassembler(ScriptDisassembler):
|
||||
def var(self, arg):
|
||||
if arg in self.symbol_map:
|
||||
return self.symbol_map[arg]
|
||||
|
||||
v = arg - 2**32 # convert to s32
|
||||
if v > -250000000:
|
||||
if v <= -220000000: return str((v + 230000000) / 1024)
|
||||
elif v <= -200000000: return f"SI_ARRAY_FLAG({v + 210000000})"
|
||||
elif v <= -180000000: return f"SI_ARRAY({v + 190000000})"
|
||||
elif v <= -160000000: return f"SI_SAVE_VAR({v + 170000000})"
|
||||
elif v <= -140000000: return f"SI_AREA_VAR({v + 150000000})"
|
||||
elif v <= -120000000: return f"SI_SAVE_FLAG({v + 130000000})"
|
||||
elif v <= -100000000: return f"SI_AREA_FLAG({v + 110000000})"
|
||||
elif v <= -80000000: return f"SI_MAP_FLAG({v + 90000000})"
|
||||
elif v <= -60000000: return f"SI_FLAG({v + 70000000})"
|
||||
elif v <= -40000000: return f"SI_MAP_VAR({v + 50000000})"
|
||||
elif v <= -20000000: return f"SI_VAR({v + 30000000})"
|
||||
|
||||
if arg == 0xFFFFFFFF:
|
||||
return "-1"
|
||||
elif ((arg & 0xFF000000) == 0x80000000) or arg > 10000:
|
||||
return f"0x{arg:X}"
|
||||
else:
|
||||
return f"{arg}"
|
||||
|
||||
def verify_float(self, var):
|
||||
try:
|
||||
float(var)
|
||||
except Exception:
|
||||
# not a float!
|
||||
raise UnsupportedScript("non-float used in float command")
|
||||
|
||||
return var
|
||||
|
||||
def disassemble_command(self, opcode, argc, argv):
|
||||
if opcode == 0x01:
|
||||
if self.out.endswith("return\n"):
|
||||
# implicit return; break
|
||||
self.out = self.out[:-7].rstrip() + "\n"
|
||||
else:
|
||||
self.write_line("break")
|
||||
|
||||
self.indent -= 1
|
||||
|
||||
self.prefix_line(f"Script {self.script_name} = SCRIPT({{")
|
||||
self.write_line("});")
|
||||
|
||||
self.done = True
|
||||
elif opcode == 0x02: self.write_line(f"return")
|
||||
elif opcode == 0x03: self.write_line(f"lbl{self.var(argv[0])}:")
|
||||
elif opcode == 0x04: self.write_line(f"goto lbl{self.var(argv[0])}")
|
||||
elif opcode == 0x05:
|
||||
if argv[0] == 0:
|
||||
self.write_line("loop {")
|
||||
else:
|
||||
self.write_line(f"loop {self.var(argv[0])} {{")
|
||||
self.indent += 1
|
||||
elif opcode == 0x06:
|
||||
self.indent -= 1
|
||||
self.write_line("}")
|
||||
elif opcode == 0x07: self.write_line(f"break")
|
||||
elif opcode == 0x08: self.write_line(f"sleep {self.var(argv[0])}")
|
||||
elif opcode == 0x09: self.write_line(f"sleep {self.var(argv[0])} secs")
|
||||
elif opcode == 0x0A:
|
||||
self.write_line(f"if {self.var(argv[0])} == {self.var(argv[1])} {{")
|
||||
self.indent += 1
|
||||
elif opcode == 0x0B:
|
||||
self.write_line(f"if {self.var(argv[0])} != {self.var(argv[1])} {{")
|
||||
self.indent += 1
|
||||
elif opcode == 0x0C:
|
||||
self.write_line(f"if {self.var(argv[0])} < {self.var(argv[1])} {{")
|
||||
self.indent += 1
|
||||
elif opcode == 0x0D:
|
||||
self.write_line(f"if {self.var(argv[0])} > {self.var(argv[1])} {{")
|
||||
self.indent += 1
|
||||
elif opcode == 0x0E:
|
||||
self.write_line(f"if {self.var(argv[0])} <= {self.var(argv[1])} {{")
|
||||
self.indent += 1
|
||||
elif opcode == 0x0F:
|
||||
self.write_line(f"if {self.var(argv[0])} >= {self.var(argv[1])} {{")
|
||||
self.indent += 1
|
||||
elif opcode == 0x12:
|
||||
self.indent -= 1
|
||||
self.write_line("} else {")
|
||||
self.indent += 1
|
||||
elif opcode == 0x13:
|
||||
self.indent -= 1
|
||||
self.write_line("}")
|
||||
# elif opcode == 0x14:
|
||||
# self.write_line(f"SI_SWITCH({self.var(argv[0])}),")
|
||||
# self.indent += 2
|
||||
# elif opcode == 0x15:
|
||||
# self.write_line(f"SI_SWITCH_CONST(0x{argv[0]:X}),")
|
||||
# self.indent += 2
|
||||
# elif opcode == 0x16:
|
||||
# self.indent -= 1
|
||||
# self.write_line(f"SI_CASE_EQ({self.var(argv[0])}),")
|
||||
# self.indent += 1
|
||||
# elif opcode == 0x17:
|
||||
# self.indent -= 1
|
||||
# self.write_line(f"SI_CASE_NE({self.var(argv[0])}),")
|
||||
# self.indent += 1
|
||||
# elif opcode == 0x18:
|
||||
# self.indent -= 1
|
||||
# self.write_line(f"SI_CASE_LT({self.var(argv[0])}),")
|
||||
# self.indent += 1
|
||||
# elif opcode == 0x19:
|
||||
# self.indent -= 1
|
||||
# self.write_line(f"SI_CASE_GT({self.var(argv[0])}),")
|
||||
# self.indent += 1
|
||||
# elif opcode == 0x1A:
|
||||
# self.indent -= 1
|
||||
# self.write_line(f"SI_CASE_LE({self.var(argv[0])}),")
|
||||
# self.indent += 1
|
||||
# elif opcode == 0x1B:
|
||||
# self.indent -= 1
|
||||
# self.write_line(f"SI_CASE_GE({self.var(argv[0])}),")
|
||||
# self.indent += 1
|
||||
# elif opcode == 0x1C:
|
||||
# self.indent -= 1
|
||||
# self.write_line(f"SI_CASE_DEFAULT(),")
|
||||
# self.indent += 1
|
||||
# elif opcode == 0x1D:
|
||||
# self.indent -= 1
|
||||
# self.write_line(f"SI_CASE_OR_EQ({self.var(argv[0])}),")
|
||||
# self.indent += 1
|
||||
# # opcode 0x1E?
|
||||
# elif opcode == 0x1F:
|
||||
# self.indent -= 1
|
||||
# self.write_line(f"SI_CASE_BITS_ON({self.var(argv[0])}),")
|
||||
# self.indent += 1
|
||||
# elif opcode == 0x20:
|
||||
# self.indent -= 1
|
||||
# self.write_line(f"SI_END_MULTI_CASE(),")
|
||||
# self.indent += 1
|
||||
# elif opcode == 0x21:
|
||||
# self.indent -= 1
|
||||
# self.write_line(f"case {self.var(argv[0])}..{self.var(argv[1])}:")
|
||||
# self.indent += 1
|
||||
# elif opcode == 0x22: self.write_line("break")
|
||||
# elif opcode == 0x23:
|
||||
# self.indent -= 2
|
||||
# self.write_line("}")
|
||||
elif opcode == 0x24: self.write_line(f"{self.var(argv[0])} = {self.var(argv[1])}")
|
||||
elif opcode == 0x25: self.write_line(f"const {self.var(argv[0])} = 0x{argv[1]:X}")
|
||||
elif opcode == 0x26: self.write_line(f"{self.var(argv[0])} = {self.verify_float(self.var(argv[1]))}")
|
||||
elif opcode == 0x27: self.write_line(f"{self.var(argv[0])} += {self.var(argv[1])}")
|
||||
elif opcode == 0x28: self.write_line(f"{self.var(argv[0])} -= {self.var(argv[1])}")
|
||||
elif opcode == 0x29: self.write_line(f"{self.var(argv[0])} *= {self.var(argv[1])}")
|
||||
elif opcode == 0x2A: self.write_line(f"{self.var(argv[0])} /= {self.var(argv[1])}")
|
||||
elif opcode == 0x2B: self.write_line(f"{self.var(argv[0])} %= {self.var(argv[1])}")
|
||||
elif opcode == 0x2C: self.write_line(f"{self.var(argv[0])} += {self.verify_float(self.var(argv[1]))}")
|
||||
elif opcode == 0x2D: self.write_line(f"{self.var(argv[0])} -= {self.verify_float(self.var(argv[1]))}")
|
||||
elif opcode == 0x2E: self.write_line(f"{self.var(argv[0])} *= {self.verify_float(self.var(argv[1]))}")
|
||||
elif opcode == 0x2F: self.write_line(f"{self.var(argv[0])} /= {self.verify_float(self.var(argv[1]))}")
|
||||
elif opcode == 0x3F: self.write_line(f"{self.var(argv[0])} &= {self.var(argv[1])}")
|
||||
elif opcode == 0x40: self.write_line(f"{self.var(argv[0])} |= {self.var(argv[1])}")
|
||||
elif opcode == 0x41: self.write_line(f"const {self.var(argv[0])} &= {argv[1]:X})")
|
||||
elif opcode == 0x42: self.write_line(f"const {self.var(argv[0])} |= {argv[1]:X})")
|
||||
elif opcode == 0x43:
|
||||
argv_str = ", ".join(self.var(arg) for arg in argv[1:])
|
||||
self.write_line(f"{self.addr_ref(argv[0])}({argv_str})")
|
||||
elif opcode == 0x44: self.write_line(f"spawn {self.addr_ref(argv[0])}")
|
||||
elif opcode == 0x45: self.write_line(f"{self.var(argv[1])} = spawn ({self.addr_ref(argv[0])}")
|
||||
elif opcode == 0x46: self.write_line(f"await {self.addr_ref(argv[0])}")
|
||||
elif opcode == 0x47:
|
||||
assert argv[3] == 1
|
||||
if argv[4] != 0:
|
||||
self.write_line(f"{self.var(argv[4])} = bind {self.addr_ref(argv[0])} to {self.trigger(argv[1])} {self.var(argv[2])}")
|
||||
else:
|
||||
self.write_line(f"bind {self.addr_ref(argv[0])} to {self.trigger(argv[1])} {self.var(argv[2])}")
|
||||
elif opcode == 0x48: self.write_line(f"unbind")
|
||||
elif opcode == 0x49: self.write_line(f"kill {self.var(argv[0])}")
|
||||
elif opcode == 0x4D: self.write_line(f"group {self.var(argv[0])}")
|
||||
elif opcode == 0x4F: self.write_line(f"suspend group {self.var(argv[0])}")
|
||||
elif opcode == 0x50: self.write_line(f"resume group {self.var(argv[0])}")
|
||||
elif opcode == 0x51: self.write_line(f"suspend others {self.var(argv[0])}")
|
||||
elif opcode == 0x52: self.write_line(f"resume others {self.var(argv[0])}")
|
||||
elif opcode == 0x53: self.write_line(f"suspend {self.var(argv[0])}")
|
||||
elif opcode == 0x54: self.write_line(f"resume {self.var(argv[0])}")
|
||||
elif opcode == 0x56:
|
||||
self.write_line("spawn {")
|
||||
self.indent += 1
|
||||
elif opcode == 0x57:
|
||||
self.indent -= 1
|
||||
self.write_line("}")
|
||||
elif opcode == 0x58:
|
||||
self.write_line("parallel {")
|
||||
self.indent += 1
|
||||
elif opcode == 0x59:
|
||||
self.indent -= 1
|
||||
self.write_line("}")
|
||||
else:
|
||||
raise UnsupportedScript(f"DSL does not support script opcode {opcode:X}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) <= 1:
|
||||
@ -317,4 +529,8 @@ if __name__ == "__main__":
|
||||
|
||||
with open(file, "rb") as f:
|
||||
f.seek(offset)
|
||||
print(disassemble(f), end="")
|
||||
|
||||
try:
|
||||
print(ScriptDSLDisassembler(f).disassemble(), end="")
|
||||
except UnsupportedScript:
|
||||
print(ScriptDisassembler(f).disassemble(), end="")
|
||||
|
Loading…
Reference in New Issue
Block a user