Skip to content

Commit

Permalink
in the middle of binary import changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Lilaa3 committed Apr 21, 2024
1 parent 1991d81 commit 4310699
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 105 deletions.
25 changes: 14 additions & 11 deletions fast64_internal/sm64/animation/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def to_c(self, is_dma_structure: bool):

return text_data.getvalue()

def to_binary(self, start_address: int) -> bytearray:
def to_binary(self, start_address: int = 0) -> bytearray:
data: bytearray = bytearray()

value_table, indice_tables = create_tables([self])
Expand Down Expand Up @@ -300,12 +300,12 @@ def to_props(self, action, header, actor_name: str, use_custom_name: bool = True

header.action = action

header.custom_name = self.reference
if (
isinstance(self.reference, str)
and self.reference != header.get_anim_name(actor_name, action)
and use_custom_name
):
header.custom_name = self.reference
header.override_name = True

correct_frame_range = self.start_frame, self.loop_start, self.loop_end
Expand Down Expand Up @@ -336,7 +336,7 @@ class SM64_Anim:
headers: list[SM64_AnimHeader] = dataclasses.field(default_factory=list)
action_name: str = None

def to_binary(self, is_dma: bool, start_address: int) -> bytearray:
def to_binary(self, is_dma: bool = False, start_address: int = 0) -> bytearray:
data: bytearray = bytearray()
ptrs: list[int] = []

Expand Down Expand Up @@ -395,8 +395,10 @@ def to_props(self, action, actor_name: str, remove_name_footer: bool = True, use

main_header = self.headers[0]

if not self.action_name and main_header.reference and remove_name_footer:
self.action_name = main_header.reference.lstrip("anim_")
if not self.action_name and main_header.reference:
self.action_name = str(main_header.reference)
if remove_name_footer:
self.action_name = self.action_name.lstrip("anim_")
if self.action_name:
action.name = self.action_name

Expand Down Expand Up @@ -482,7 +484,7 @@ def get_sets(self) -> tuple[list[SM64_AnimHeader], list[SM64_AnimData]]:
headers_set.append(anim_header)
return headers_set, data_set

def to_binary(self, is_dma: bool, start_address: int):
def to_binary(self, is_dma: bool = False, start_address: int = 0):
# TODO: Handle dma exports
data: bytearray = bytearray()
ptrs: list[int] = []
Expand All @@ -491,7 +493,7 @@ def to_binary(self, is_dma: bool, start_address: int):

# Calculate offsets and generate tables
table_offset = start_address
table_length = len(self.elements) * 4
table_length = len(self.elements) * 4 + 4
headers_offset = table_offset + table_length
headers_length = len(headers_set) * HEADER_SIZE
if data_set:
Expand All @@ -505,29 +507,30 @@ def to_binary(self, is_dma: bool, start_address: int):
ptrs.append(len(data))
header_offset = headers_offset + (headers_set.index(anim_header) * HEADER_SIZE)
data.extend(header_offset.to_bytes(4, byteorder="big", signed=False))
data.extend(bytearray([0x00] * 4))

# Add all the headers
for anim_header in self.elements:
if anim_header.data:
indice_offset = sum(
ptrs.extend([start_address + len(data) + 12, start_address + len(data) + 16])
indice_offset = indice_tables_offset + sum(
[len(indice_table.data) for indice_table in indice_tables[: data_set.index(anim_header.data)]]
)
data.extend(
anim_header.to_binary(
indice_tables_offset + indice_offset,
indice_offset,
values_table_offset,
)
)
else:
ptrs.append(len(data))
data.extend(anim_header.to_binary())

if data_set:
for indice_table in indice_tables:
data.extend(indice_table.to_binary())
data.extend(value_table.to_binary())

return data
return data, ptrs

def to_c_dma(self) -> list[os.PathLike, str]:
files_data: dict[str, str] = {}
Expand Down
73 changes: 41 additions & 32 deletions fast64_internal/sm64/animation/importing.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,33 +275,23 @@ def import_binary_dma_animation(


def import_binary_table(
rom_data: bytes,
address: int,
segment_data: dict[int, tuple[int, int]],
table_reader: RomReading,
animations: dict[str, SM64_Anim],
read_entire_table: bool,
table_index: int,
ignore_null: bool,
table: SM64_AnimTable,
):
table_reader = RomReading(rom_data, address)
for i in range(255):
ptr = table_reader.read_value(4, signed=False)
ptr = table_reader.read_ptr()
if ptr == 0 and not ignore_null:
if not read_entire_table:
raise PluginError("Table Index not in table.")
raise PluginError("Table index not in table.")
break

is_correct_index = i == table_index
if read_entire_table or is_correct_index:
ptr_in_bytes: bytes = ptr.to_bytes(4, "big")
if ptr_in_bytes[0] not in segment_data:
raise PluginError(
f"Header at table index {i} located at {hex(table_reader.address)} does not belong to the current segment."
)
header_address = decodeSegmentedAddr(ptr_in_bytes, segment_data)

header = import_binary_header(rom_data, header_address, False, animations, segment_data)
header = import_binary_header(table_reader.data, ptr, False, animations, None)
table.elements.append(header)

if not read_entire_table and is_correct_index:
Expand All @@ -311,7 +301,7 @@ def import_binary_table(


def import_binary_animations(
rom_data: BufferedReader,
rom_data: RomReading,
import_type: str,
is_segmented_pointer: bool,
address: int,
Expand All @@ -327,7 +317,12 @@ def import_binary_animations(

if import_type == "Table":
import_binary_table(
rom_data, address, segment_data, animations, read_entire_table, table_index, ignore_null, table
rom_data=rom_data,
animations=animations,
table=table,
read_entire_table=read_entire_table,
table_index=table_index,
ignore_null=ignore_null,
)
elif import_type == "DMA":
import_binary_dma_animation(rom_data, address, animations, table, table_index if read_entire_table else None)
Expand All @@ -338,29 +333,43 @@ def import_binary_animations(


def import_insertable_binary_animations(
header_and_data: bytes,
insertable_data_reader: RomReading,
animations: dict[str, SM64_Anim],
segment_data: Optional[dict[int, tuple[int, int]]] = None,
read_entire_table: bool = False,
table_index: int = 0,
ignore_null: bool = False,
table: SM64_AnimTable = SM64_AnimTable(),
):
# TODO: Finish
header_reader = RomReading(header_and_data, 0)
data_type_num = header_reader.read_value(4, signed=False)

data_type_num = insertable_data_reader.read_value(4, signed=False)
if data_type_num not in insertableBinaryTypes.values():
raise PluginError(f"Unknown data type: {hex(data_type_num)}")
data_type = next(key for key, value in insertableBinaryTypes.items() if value == data_type_num)
if data_type not in {"Animation"}:
raise PluginError(f'Wrong data type "{data_type}".')

data_size = header_reader.read_value(4, signed=False)
start_address = header_reader.read_value(4, signed=False)
data_size = insertable_data_reader.read_value(4, signed=False)
start_address = insertable_data_reader.read_value(4, signed=False)

pointer_count = header_reader.read_value(4, signed=False)
pointer_count = insertable_data_reader.read_value(4, signed=False)
pointer_offsets = []
for _ in range(pointer_count):
pointer_offsets.append(header_reader.read_value(4, signed=False))
pointer_offsets.append(insertable_data_reader.read_value(4, signed=False))
insertable_data_reader.insertable_ptrs = pointer_offsets

actual_start = header_reader.address + start_address
data = header_and_data[actual_start : actual_start + data_size]
actual_start = insertable_data_reader.address + start_address
data_reader = insertable_data_reader.branch(
0,
insertable_data_reader.data[actual_start : actual_start + data_size],
)

import_binary_header(data, 0, False, animations)
data_type = next(key for key, value in insertableBinaryTypes.items() if value == data_type_num)
if data_type == "Animation":
import_binary_header(data_reader, 0, False, animations)
elif data_type == "Animation Table":
import_binary_table(
table_reader=data_reader,
animations=animations,
read_entire_table=read_entire_table,
table_index=table_index,
ignore_null=ignore_null,
table=table,
)
else:
raise PluginError(f'Wrong animation data type "{data_type}".')
90 changes: 58 additions & 32 deletions fast64_internal/sm64/animation/operators.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

import bpy
from bpy.utils import register_class, unregister_class
from bpy.types import Context, Object, Scene, Operator
Expand All @@ -14,19 +16,19 @@
PluginError,
applyBasicTweaks,
copyPropertyGroup,
path_checks,
filepath_checks,
toAlnum,
raisePluginError,
get_mode_set_from_context_mode,
applyRotation,
writeInsertableFile,
)
from ...utility_anim import stashActionInArmature
from ..sm64_utility import import_rom_checks
from ..sm64_level_parser import parseLevelAtPointer
from ..sm64_constants import level_pointers
from ..sm64_constants import level_pointers, insertableBinaryTypes

from .classes import DMATable, DMATableEntrie, SM64_Anim, SM64_AnimTable
from .classes import DMATable, DMATableEntrie, SM64_Anim, SM64_AnimTable, RomReading
from .importing import (
import_binary_animations,
import_binary_dma_animation,
Expand All @@ -48,6 +50,11 @@
)
from .constants import marioAnimationNames

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from ..settings.properties import SM64_Properties
from .properties import SM64_AnimExportProps, SM64_AnimImportProps, SM64_AnimTableProps

def emulate_no_loop(scene: Scene):
export_props = scene.fast64.sm64.anim_export
Expand Down Expand Up @@ -260,9 +267,9 @@ def execute_operator(self, context: Context):
animation_operator_checks(context)

scene = context.scene
sm64_props = scene.fast64.sm64
export_props = sm64_props.anim_export
table_props = export_props.table
sm64_props: SM64_Properties = scene.fast64.sm64
export_props: SM64_AnimExportProps = sm64_props.anim_export
table_props: SM64_AnimTableProps = export_props.table

actions = table_props.actions
armature_obj: Object = context.selected_objects[0]
Expand Down Expand Up @@ -343,6 +350,10 @@ def execute_operator(self, context: Context):
header_type,
True,
)
elif sm64_props.export_type == "Insertable Binary":
data, ptrs = table.to_binary(export_props.is_binary_dma, 0)
path = abspath(os.path.join(export_props.directory_path, table_props.insertable_file_name))
writeInsertableFile(path, insertableBinaryTypes["Animation Table"], ptrs, 0, data)
else:
raise PluginError(f"Unimplemented export type ({sm64_props.export_type})")

Expand Down Expand Up @@ -525,44 +536,59 @@ def execute_operator(self, context):
bpy.ops.object.mode_set(mode="OBJECT")
animation_operator_checks(context, False)

sm64_props = context.scene.fast64.sm64
export_props = sm64_props.anim_export
import_props = sm64_props.anim_import
scene = context.scene
sm64_props: SM64_Properties = scene.fast64.sm64
export_props: SM64_AnimExportProps = sm64_props.anim_export
import_props: SM64_AnimImportProps = sm64_props.anim_import
table_props: SM64_AnimTableProps = export_props.table

animations: dict[str, SM64_Anim] = {}
table = SM64_AnimTable()

if import_props.import_type == "Binary":
if import_props.import_type == "Binary" or (
import_props.import_type == "Insertable Binary" and import_props.insertable_read_from_rom
):
import_rom_path = abspath(sm64_props.import_rom)
import_rom_checks(import_rom_path)
with open(import_rom_path, "rb") as rom_data:
import_binary_animations(
rom_data.read(),
import_props.binary_import_type,
import_props.is_segmented_address,
eval_num_from_str(
import_props.dma_table_address
if import_props.binary_import_type == "DMA"
else import_props.address
),
parseLevelAtPointer(rom_data, level_pointers[import_props.level]).segmentData,
animations,
import_props.read_entire_table,
import_props.mario_or_table_index,
import_props.ignore_null,
table,
)
with open(import_rom_path, "rb") as rom_file:
rom_data = rom_file.read()
segment_data = parseLevelAtPointer(rom_file, level_pointers[import_props.level]).segmentData
else:
rom_data, segment_data = None, None

if import_props.import_type == "Binary":
import_binary_animations(
rom_data,
import_props.binary_import_type,
import_props.is_segmented_address,
eval_num_from_str(
import_props.dma_table_address if import_props.binary_import_type == "DMA" else import_props.address
),
segment_data,
animations,
import_props.read_entire_table,
import_props.mario_or_table_index,
import_props.ignore_null,
table,
)
elif import_props.import_type == "Insertable Binary":
insertable_path = abspath(import_props.insertable_path)
filepath_checks(insertable_path)
with open(insertable_path, "rb") as rom_data:

with open(insertable_path, "rb") as insertable_file:
import_insertable_binary_animations(
rom_data.read(),
animations,
table,
insertable_data_reader=RomReading(insertable_file.read(), 0, None, rom_data, segment_data),
animations=animations,
table=table,
segment_data=segment_data,
read_entire_table=import_props.read_entire_table,
table_index=import_props.mario_or_table_index,
ignore_null=import_props.ignore_null,
)
elif import_props.import_type == "C":
import_c_animations(abspath(import_props.c_path), animations, table)
c_path = abspath(import_props.c_path)
path_checks(c_path)
import_c_animations(c_path, animations, table)

for data in animations.values():
animation_data_to_blender(
Expand Down
Loading

0 comments on commit 4310699

Please sign in to comment.