diff --git a/README.md b/README.md index 56ffc54b..9902db24 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Construct type definitions for Mercury Engine | BSHDAT | ✗ | ✗ | ✗ | ✗ | | BSMAT | Missing | Missing | ✓ | ✓ | | BTUNDA | Missing | Missing | ✓ | ✓ | -| BUCT | ✗ | ✗ | ✗ | ✗ | +| BUCT | ✓ | ✓ | ✓ | ✓ | | INI | Missing | Missing | ✓ | ✓ | | LC | ✓ | ✓ | ✓ | ✓ | | PKG | ✓ | ✓ | ✓ | ✓ | diff --git a/src/mercury_engine_data_structures/formats/__init__.py b/src/mercury_engine_data_structures/formats/__init__.py index c4287b45..0a1ff339 100644 --- a/src/mercury_engine_data_structures/formats/__init__.py +++ b/src/mercury_engine_data_structures/formats/__init__.py @@ -40,6 +40,7 @@ from mercury_engine_data_structures.formats.brsa import Brsa from mercury_engine_data_structures.formats.brspd import Brspd from mercury_engine_data_structures.formats.bsmat import Bsmat +from mercury_engine_data_structures.formats.buct import Buct from mercury_engine_data_structures.formats.gui_files import Bmscp, Bmssh, Bmssk, Bmsss from mercury_engine_data_structures.formats.ini import Ini from mercury_engine_data_structures.formats.lua import Lua @@ -94,6 +95,7 @@ "BRES": Bres, "BREV": Brev, "BSMAT": Bsmat, + "BUCT": Buct, "TOC": Toc, "TXT": Txt, "INI": Ini, diff --git a/src/mercury_engine_data_structures/formats/buct.py b/src/mercury_engine_data_structures/formats/buct.py new file mode 100644 index 00000000..5b7ebeb9 --- /dev/null +++ b/src/mercury_engine_data_structures/formats/buct.py @@ -0,0 +1,45 @@ +import construct +from construct.core import ( + Array, + Const, + Construct, + If, + Int16ul, + Int32ul, + Int64ul, + Rebuild, + Struct, + Terminated, +) + +from mercury_engine_data_structures import game_check +from mercury_engine_data_structures.common_types import VersionAdapter +from mercury_engine_data_structures.formats.base_resource import BaseResource + +BUCT = Struct( + _magic = Const(b"MUCT"), + version = game_check.is_sr_or_else( + VersionAdapter("1.3.0"), + VersionAdapter("1.4.0") + ), + size = Rebuild(Int32ul, construct.len_(construct.this.data)), + _padding = If(game_check.current_game_at_least(game_check.Game.DREAD), Const(0xFFFFFFFF, Int32ul)), + _data_start = game_check.is_sr_or_else( + Const(0x10, Int32ul), + Const(0x18, Int64ul) + ), + data=Array(construct.this.size, Struct( + char_maybe = Int16ul, # I think this could be utf8 chars? + _padding = game_check.is_sr_or_else( + Const(0x0000, Int16ul), + Const(0xFFFF, Int16ul), + ), + index = Int32ul + )), + _eof=Terminated +) + +class Buct(BaseResource): + @classmethod + def construct_class(cls, target_game: game_check.Game) -> Construct: + return BUCT diff --git a/tests/formats/test_buct.py b/tests/formats/test_buct.py new file mode 100644 index 00000000..9088f244 --- /dev/null +++ b/tests/formats/test_buct.py @@ -0,0 +1,14 @@ +import pytest +from tests.test_lib import parse_build_compare_editor + +from mercury_engine_data_structures import dread_data, samus_returns_data +from mercury_engine_data_structures.formats.buct import Buct + + +@pytest.mark.parametrize("buct_path", dread_data.all_files_ending_with(".buct")) +def test_buct_dread(dread_file_tree, buct_path): + parse_build_compare_editor(Buct, dread_file_tree, buct_path) + +@pytest.mark.parametrize("buct_path", samus_returns_data.all_files_ending_with(".buct")) +def test_buct_sr(samus_returns_tree, buct_path): + parse_build_compare_editor(Buct, samus_returns_tree, buct_path)