Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
theCapypara committed Jul 20, 2024
1 parent bd4cba0 commit a24d32e
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 22 deletions.
6 changes: 0 additions & 6 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ ignore_missing_imports = True
[mypy-skytemple_rust._st_bma_collision_rle_compression]
ignore_missing_imports = True

[mypy-explorerscript.*]
ignore_missing_imports = True

[mypy-pytest.*]
ignore_missing_imports = True

Expand All @@ -57,9 +54,6 @@ ignore_missing_imports = True
[mypy-dungeon_eos.*]
ignore_missing_imports = True

[mypy-igraph]
ignore_missing_imports = True

[mypy-desmume]
ignore_missing_imports = True

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ gql[aiohttp]==3.5.0
graphql-core>=3.2.0
aiohttp[speedups]
lru-dict==1.3.0
skytemple-3rdparty-typestubs
skytemple-3rdparty-typestubs==1.1.0
types-Pillow==10.2.0.20240324
types-PyYAML==6.0.12.20240311
types-setuptools
Expand Down
17 changes: 11 additions & 6 deletions skytemple_files/script/ssb/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from __future__ import annotations

import logging
from typing import MutableSequence, TYPE_CHECKING

from explorerscript.source_map import SourceMap
from explorerscript.ssb_converting.ssb_data_types import (
Expand Down Expand Up @@ -66,7 +67,9 @@


class SkyTempleSsbOperation(SsbOperation):
def __init__(self, offset: int, op_code: Pmd2ScriptOpCode, params: list[SsbOpParam]):
op_code: Pmd2ScriptOpCode

def __init__(self, offset: int, op_code: Pmd2ScriptOpCode, params: MutableSequence[SsbOpParam]):
super().__init__(offset, op_code, params)


Expand Down Expand Up @@ -228,7 +231,7 @@ def _read_single_op_code(self, data, cursor, len_header):
opcode_offset = int((cursor - len_header) / 2)
op_code = self._scriptdata.op_codes__by_id[read_u16(data, cursor)]
cursor += 2
arguments = []
arguments: MutableSequence[SsbOpParam] = []
cnt_params = op_code.params
if cnt_params == -1:
# Variable length opcode
Expand Down Expand Up @@ -278,9 +281,11 @@ def get_filled_routine_ops(self):
for rtn in self.routine_ops:
rtn_ops = []
for op in rtn:
new_params = []
new_params: MutableSequence[SsbOpParam] = []
skip_arguments = 0
for i, param in enumerate(op.params):
if TYPE_CHECKING:
assert isinstance(param, int)
if skip_arguments > 0:
skip_arguments -= 1
continue
Expand Down Expand Up @@ -308,9 +313,9 @@ def get_filled_routine_ops(self):
x_offset = y_offset = x_relative = y_relative = 0
try:
x_offset = param
y_offset = op.params[i + 1]
x_relative = op.params[i + 2]
y_relative = op.params[i + 3]
y_offset = op.params[i + 1] # type: ignore
x_relative = op.params[i + 2] # type: ignore
y_relative = op.params[i + 3] # type: ignore
except IndexError:
logger.warning("SSB had wrong number of arguments for building a position marker.")
new_params.append(
Expand Down
27 changes: 22 additions & 5 deletions skytemple_files/script/ssb/script_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from __future__ import annotations

import logging
from typing import Callable, Optional
from typing import Callable, Optional, MutableSequence, Sequence, TYPE_CHECKING

from explorerscript.error import ParseError, SsbCompilerError
from explorerscript.source_map import SourceMap
Expand Down Expand Up @@ -83,6 +83,13 @@ def compile_ssbscript(
if callback_after_parsing:
callback_after_parsing()

assert (
base_compiler.routine_infos is not None
and base_compiler.routine_ops is not None
and base_compiler.named_coroutines is not None
and base_compiler.source_map is not None
)

return self.compile_structured(
base_compiler.routine_infos,
base_compiler.routine_ops,
Expand Down Expand Up @@ -127,6 +134,13 @@ def compile_explorerscript(
if callback_after_parsing:
callback_after_parsing()

assert (
base_compiler.routine_infos is not None
and base_compiler.routine_ops is not None
and base_compiler.named_coroutines is not None
and base_compiler.source_map is not None
)

return self.compile_structured(
base_compiler.routine_infos,
base_compiler.routine_ops,
Expand Down Expand Up @@ -194,7 +208,7 @@ def compile_structured(

# Build Routine Infos
built_routine_info_with_offset: list[tuple[int, SsbRoutineInfo]] = []
built_routine_ops: list[list[SsbOperation]] = []
built_routine_ops: list[MutableSequence[SsbOperation]] = []
# A list of lists for ALL opcodes that maps all opcode indices to their memory address.
opcode_index_mem_offset_mapping: dict[int, int] = {}
bytes_written_last_rtn = 0
Expand All @@ -207,7 +221,7 @@ def compile_structured(

routine_start_cursor = opcode_cursor
# Build OPs
built_ops: list[SkyTempleSsbOperation] = []
built_ops: MutableSequence[SsbOperation] = []
if len(input_ops) == 0:
# ALIAS ROUTINE. This alias the PREVIOUS routine
routine_start_cursor = opcode_cursor - bytes_written_last_rtn
Expand Down Expand Up @@ -238,7 +252,7 @@ def compile_structured(
)
else:
op_code = op_codes[0]
new_params: list[int] = []
new_params: MutableSequence[SsbOpParam] = []
op_len = 2
if op_code.params == -1:
# Handle variable length opcode by inserting the number of opcodes as the first argument.
Expand Down Expand Up @@ -277,6 +291,7 @@ def compile_structured(

# Find out the target for this routine if it's specified by name
if input_info.linked_to == -1:
assert input_info.linked_to_name is not None
input_info.linked_to = SsbConstant(input_info.linked_to_name, self.rom_data.script_data).value.id

built_routine_info_with_offset.append((routine_start_cursor, input_info))
Expand All @@ -288,6 +303,8 @@ def compile_structured(
if op.op_code.name in OPS_WITH_JUMP_TO_MEM_OFFSET:
param_id = OPS_WITH_JUMP_TO_MEM_OFFSET[op.op_code.name]
index_to_jump_to = op.params[param_id]
if TYPE_CHECKING:
assert isinstance(index_to_jump_to, int)
op.params[param_id] = opcode_index_mem_offset_mapping[index_to_jump_to]
for i, param in enumerate(op.params):
if isinstance(param, StringIndexPlaceholder):
Expand Down Expand Up @@ -350,7 +367,7 @@ def _parse_param(
raise SsbCompilerError(f(_("Invalid parameter supplied for an operation: {param}")))

@staticmethod
def _correct_param_list_len(params: list[SsbOpParam]) -> int:
def _correct_param_list_len(params: Sequence[SsbOpParam]) -> int:
"""Returns the correct length of a parameter list (positon markers count as 4"""
len = 0
for p in params:
Expand Down
7 changes: 4 additions & 3 deletions skytemple_files/script/ssb/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,21 +111,22 @@ def write(self) -> bytes:
# Routine Info - The offsets used for the routine starts MUST already be correctly calculated!
for offset, routine_info in self.model.routine_info:
write_u16(data, u16(offset // 2), self.bytes_written)
write_u16(data, routine_info.type.value, self.bytes_written + 2)
write_u16(data, routine_info.linked_to, self.bytes_written + 4)
write_u16(data, u16_checked(routine_info.type.value), self.bytes_written + 2)
write_u16(data, u16_checked(routine_info.linked_to), self.bytes_written + 4)
self.bytes_written += 6

# Routines - The offsets used for the routine starts MUST already be correctly calculated!
op_codes = self.static_data.script_data.op_codes__by_id
for i, ops in enumerate(self.model.routine_ops):
for op in ops:
self.write_u16(data, op.op_code.id, self.bytes_written)
self.write_u16(data, u16_checked(op.op_code.id), self.bytes_written)
self.bytes_written += 2
if self.static_data.script_data.op_codes__by_id[op.op_code.id].params == -1:
# Dynamic argument handling: Write number of arguments next
self.write_u16(data, u16_checked(len(op.params)), self.bytes_written)
self.bytes_written += 2
for argidx, param in enumerate(op.params):
assert isinstance(param, int)
# If negative, store as 14-bit or 16-bit signed integer.
if param < 0:
# TODO: Support for repeating args
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def test_using_custom_ssb_decompile(self, path: str):

_exps, ssb, pmd2_data = _collect_for_path(path)

self._run_test(path, None, ssb, pmd2_data)
self._run_test(path, None, ssb, pmd2_data, expect_ssb_script="UTOPIA13_final2" in path)

def _run_test(
self,
Expand All @@ -113,13 +113,20 @@ def _run_test(
ssb_file: bytes,
pmd2_data: Pmd2Data,
*,
expect_ssb_script=False,
_skip_flow_check=False,
):
ssb_before = SsbHandler.deserialize(ssb_file, pmd2_data)
if not exps_before:
# Test the compiling and writing, by compiling the model, writing it to binary,
# and then loading it again, and checking the generated ssb script.
exps_before, _source_map_before = ssb_before.to_explorerscript()
if not expect_ssb_script:
self.assertNotIn(
"is-ssb-script", exps_before, "Was not expecting the decompiler to fall back to SsbScript"
)
else:
self.assertIn("is-ssb-script", exps_before, "Was expecting the decompiler to fall back to SsbScript")

compiler = ScriptCompiler(pmd2_data)

Expand Down

0 comments on commit a24d32e

Please sign in to comment.