Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bfont format #220

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 | ✗ | ✗ | Missing | Missing |
| BCWAV | ✗ | ✗ | Missing | Missing |
| BFGRP | Missing | Missing | ✗ | ✗ |
| BFONT | ✗ | ✗ | ✗ | ✗ |
| BFONT | ✓ | ✓ | ✓ | ✓ |
| BFSAR | Missing | Missing | ✗ | ✗ |
| BFSTM | Missing | Missing | ✗ | ✗ |
| BGSNDS | Missing | Missing | ✓ | ✓ |
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])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a , after the last argument so it ends up multi-line


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)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

construct.len_(construct.this.glyph_data) instead of the lambda

"_data_start" / Rebuild(Int32ul, lambda ctx: calc_padding(0x10, 0x28 + len(ctx.atlas_path))),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's gotta be a way to have this be calculated automatically somehow......

"_buct_name_offset" / Rebuild(Int32ul, lambda ctx: calc_padding(0x4, ctx._data_start + ctx.glyph_count * 14)),
"atlas_path" / StrId,
AlignTo(0x10),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does just adding construct.Aligned work here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. Aligned adds bytes until the subcon length is a multiple of the modulus, while this should be aligned to the file.

"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)