Skip to content
Merged
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
15 changes: 15 additions & 0 deletions src/tests/test_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ def test_icns_file():
temp_icns = tempfile.NamedTemporaryFile('rb+', suffix='.icns')
return temp_icns

@pytest.fixture
def test_bi_source_file():
temp_src = tempfile.NamedTemporaryFile('rb+', suffix='.cpp')
return temp_src

@pytest.fixture
def test_binary_file():
Expand Down Expand Up @@ -78,6 +82,17 @@ def test_metadata_dump(test_resources):
'--file', str(test_resources / 'doom-fire.blit')
])

def test_metadata_pico_bi(test_resources, test_binary_file, test_bi_source_file):
from ttblit import main

with pytest.raises(SystemExit):
main([
'metadata',
'--config', str(test_resources / 'metadata-basic.yml'),
'--pico-bi', test_bi_source_file.name,
'--force'
])

def test_metadata_invalid_bin(test_resources, test_invalid_binary_file):
from ttblit import main

Expand Down
6 changes: 6 additions & 0 deletions src/ttblit/core/struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,9 @@ def _encode(self, obj, context, path):
'data_length' / Rebuild(Int32ub, len_(this.data) + 8),
'data' / Bytes(this.data_length - 8)
)

struct_blit_image_bi = Struct(
'type' / Const(1, Int16ul), # raw data
'tag' / Const(b'3B'), # 32blit tag
'data' / struct_blit_image
)
76 changes: 60 additions & 16 deletions src/ttblit/tool/metadata.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import io
import logging
import pathlib
import textwrap
from datetime import datetime

import click
from construct.core import StreamError
from PIL import Image

from ..asset.builder import AssetBuilder
from ..asset.formatters.c import c_initializer
from ..core.struct import (blit_game, blit_game_with_meta,
blit_game_with_meta_and_relo, blit_icns,
struct_blit_image, struct_blit_pixel)
struct_blit_image, struct_blit_image_bi, struct_blit_pixel)
from ..core.yamlloader import YamlLoader


Expand Down Expand Up @@ -88,7 +90,40 @@ def dump_game_metadata(self, file, game, dump_images):
print('Metadata: No')
print('')

def run(self, config, icns, file, force, dump_images):
def write_pico_bi_source(self, pico_bi_file, metadata):

title = metadata['title'].replace('"', r'\"')
author = metadata['author'].replace('"', r'\"')
description = metadata['description'].replace('"', r'\"')

icon = struct_blit_image_bi.build({'data': metadata['icon']})
splash = struct_blit_image_bi.build({'data': metadata['splash']})

open(pico_bi_file, "w").write(textwrap.dedent(
'''
#include "pico/binary_info.h"

#include "binary_info.hpp"

bi_decl(bi_program_name("{title}"))
bi_decl(bi_program_description("{description}"))
bi_decl(bi_program_version_string("{version}"))
bi_decl(bi_program_url("{url}"))

bi_decl(bi_string(BINARY_INFO_TAG_32BLIT, BINARY_INFO_ID_32BLIT_AUTHOR, "{author}"))
bi_decl(bi_string(BINARY_INFO_TAG_32BLIT, BINARY_INFO_ID_32BLIT_CATEGORY, "{category}"))

static const uint8_t metadata_icon[]{icon};
static const uint8_t metadata_splash[]{splash};

__bi_decl(bi_metadata_icon, &((binary_info_raw_data_t *)metadata_icon)->core, ".binary_info.keep.", __used);
__bi_decl(bi_metadata_splash, &((binary_info_raw_data_t *)metadata_splash)->core, ".binary_info.keep.", __used);
''').format(title=title, description=description, version=metadata['version'], url=metadata['url'],
author=author, category=metadata['category'], icon=c_initializer(icon), splash=c_initializer(splash)))

logging.info(f'Wrote pico-sdk binary info to {pico_bi_file}')

def run(self, config, icns, pico_bi, file, force, dump_images):
if file is None and config is None:
raise click.UsageError('the following arguments are required: --config and/or --file')

Expand Down Expand Up @@ -178,6 +213,25 @@ def run(self, config, icns, file, force, dump_images):
if len(filetype) > 4:
raise ValueError('Filetype should be a maximum of 4 characters! (Hint, don\'t include the .)')


metadata = {
'date': datetime.now().strftime("%Y%m%dT%H%M%S"),
'title': title,
'description': description,
'version': version,
'author': author,
'category': category,
'filetypes': filetypes,
'url': url,
'icon': icon,
'splash': splash
}

if pico_bi is not None:
if not pico_bi.is_file() or force:
self.write_pico_bi_source(pico_bi, metadata)

# Add to the game file
if not game:
return

Expand All @@ -187,18 +241,7 @@ def run(self, config, icns, file, force, dump_images):
return 1

game.meta = {
'data': {
'date': datetime.now().strftime("%Y%m%dT%H%M%S"),
'title': title,
'description': description,
'version': version,
'author': author,
'category': category,
'filetypes': filetypes,
'url': url,
'icon': icon,
'splash': splash
}
'data': metadata
}

# Force through a non-optional builder if relo symbols exist
Expand All @@ -218,8 +261,9 @@ def run(self, config, icns, file, force, dump_images):
@click.command('metadata', help='Tag a 32Blit .blit file with metadata')
@click.option('--config', type=pathlib.Path, help='Metadata config file')
@click.option('--icns', type=pathlib.Path, help='macOS icon output file')
@click.option('--pico-bi', type=pathlib.Path, help='pico-sdk binary info source file output')
@click.option('--file', type=pathlib.Path, help='Input file')
@click.option('--force', is_flag=True, help='Force file overwrite')
@click.option('--dump-images', is_flag=True, help='Dump images from metadata')
def metadata_cli(config, icns, file, force, dump_images):
Metadata().run(config, icns, file, force, dump_images)
def metadata_cli(config, icns, pico_bi, file, force, dump_images):
Metadata().run(config, icns, pico_bi, file, force, dump_images)