Skip to content

Commit

Permalink
bfont format
Browse files Browse the repository at this point in the history
- matches the sprite alias to the buct file?
- two unks that i couldn't track down
- i think the <region>_32.bfont are the only ones used. others have
  different dimensions to their atlases.
  • Loading branch information
steven11sjf committed Sep 6, 2024
1 parent dce704e commit 4275cfc
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Construct type definitions for Mercury Engine
| BCUT | &cross; | &cross; | Missing | Missing |
| BCWAV | &cross; | &cross; | Missing | Missing |
| BFGRP | Missing | Missing | &cross; | &cross; |
| BFONT | &cross; | &cross; | &cross; | &cross; |
| BFONT | &check; | &check; | &check; | &check; |
| BFSAR | Missing | Missing | &cross; | &cross; |
| BFSTM | Missing | Missing | &cross; | &cross; |
| BGSNDS | Missing | Missing | &check; | &check; |
Expand Down
2 changes: 2 additions & 0 deletions src/mercury_engine_data_structures/formats/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from mercury_engine_data_structures.formats.bcmdl import Bcmdl
from mercury_engine_data_structures.formats.bcskla import Bcskla
from mercury_engine_data_structures.formats.bctex import Bctex
from mercury_engine_data_structures.formats.bfont import Bfont
from mercury_engine_data_structures.formats.bgsnds import Bgsnds
from mercury_engine_data_structures.formats.bldef import Bldef
from mercury_engine_data_structures.formats.blsnd import Blsnd
Expand Down Expand Up @@ -55,6 +56,7 @@
"BCMDL": Bcmdl,
"BCSKLA": Bcskla,
"BCTEX": Bctex,
"BFONT": Bfont,
"BGSNDS": Bgsnds,
"BLDEF": Bldef,
"BLSND": Blsnd,
Expand Down
72 changes: 72 additions & 0 deletions src/mercury_engine_data_structures/formats/bfont.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import math

import construct
from construct import Construct
from construct.core import (
Const,
Int16sl,
Int16ul,
Int32ul,
Int64ul,
Rebuild,
Struct,
Terminated,
)

from mercury_engine_data_structures.common_types import StrId, VersionAdapter
from mercury_engine_data_structures.construct_extensions.alignment import AlignTo
from mercury_engine_data_structures.formats.base_resource import BaseResource
from mercury_engine_data_structures.game_check import Game, GameSpecificStruct


# helper func to calculate padding for rebuild
def calc_padding(pad_to, offset):
return math.ceil(offset / pad_to) * pad_to


Sprite = Struct("pos" / Int16sl[2], "width" / Int16sl, "height" / Int16sl, "unk1" / Int16sl, "unk2" / Int16sl[2])

BFONT_MSR = Struct(
"magic" / Const(b"MFNT"),
"version" / VersionAdapter("1.9.0"),
Const(0x28, Int32ul), # pointer to name
"width" / Int32ul,
"height" / Int32ul,
"unk1" / Int32ul,
"unk2" / Int32ul,
"glyph_count" / Rebuild(Int32ul, lambda ctx: len(ctx.glyph_data)),
"_data_start" / Rebuild(Int32ul, lambda ctx: calc_padding(0x10, 0x28 + len(ctx.atlas_path))),
"_buct_name_offset" / Rebuild(Int32ul, lambda ctx: calc_padding(0x4, ctx._data_start + ctx.glyph_count * 14)),
"atlas_path" / StrId,
AlignTo(0x10),
"glyph_data" / Sprite[construct.this.glyph_count],
AlignTo(0x4),
"buct_path" / StrId,
Terminated,
)

BFONT_DREAD = Struct(
"magic" / Const(b"MFNT"),
"version" / VersionAdapter("1.10.0"),
Const(0x38, Int64ul), # pointer to name
"width" / Int32ul,
"height" / Int32ul,
"unk1" / Int16ul,
Const(b"\xff\xff"),
"unk2" / Int32ul,
"glyph_count" / Rebuild(Int32ul, lambda ctx: len(ctx.glyph_data)),
Const(b"\xff\xff\xff\xff"),
"_data_start" / Rebuild(Int64ul, lambda ctx: calc_padding(0x10, 0x38 + len(ctx.atlas_path))),
"_buct_name_offset" / Rebuild(Int64ul, lambda ctx: ctx._data_start + ctx.glyph_count * 14),
"atlas_path" / StrId,
AlignTo(0x10, pattern=b"\xff"),
"glyph_data" / Sprite[construct.this.glyph_count],
"buct_path" / StrId,
Terminated,
)


class Bfont(BaseResource):
@classmethod
def construct_class(cls, target_game: Game) -> Construct:
return GameSpecificStruct({Game.SAMUS_RETURNS: BFONT_MSR, Game.DREAD: BFONT_DREAD}[target_game], target_game)
15 changes: 15 additions & 0 deletions tests/formats/test_bfont.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
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.bfont import Bfont


@pytest.mark.parametrize("bfont_path", dread_data.all_files_ending_with(".bfont"))
def test_buct_dread(dread_file_tree, bfont_path):
parse_build_compare_editor(Bfont, dread_file_tree, bfont_path)


@pytest.mark.parametrize("bfont_path", samus_returns_data.all_files_ending_with(".bfont"))
def test_buct_sr(samus_returns_tree, bfont_path):
parse_build_compare_editor(Bfont, samus_returns_tree, bfont_path)

0 comments on commit 4275cfc

Please sign in to comment.