23 std::uint32_t raw = 0;
24 for (
const Field &field : schema.fields()) {
25 const std::uint32_t value = field.packs_layer_type() ?
static_cast<std::uint32_t
>(attribute.
layer_type())
26 : attribute.fields().contains(field.
name()) ? attribute.field(field.
name())
27 : field.default_value();
28 raw |= (value << field.offset()) & field.mask();
44 for (
const Field &field : schema.value_fields()) {
45 attribute.
field(field.name(), (raw & field.mask()) >> field.offset());
63 std::ifstream metatiles_bin{path, std::ios::binary};
68 const std::vector<unsigned char> data_buf{std::istreambuf_iterator(metatiles_bin), {}};
70 if (data_buf.size() % 2 != 0) {
71 return FormattableError{
"Size of metatiles.bin is not a multiple of 2 bytes, possibly corrupted."};
74 std::vector<TilemapEntry> entries;
75 entries.reserve(data_buf.size() / 2);
77 for (std::size_t byte_index = 0; byte_index < data_buf.size(); byte_index += 2) {
79 const std::uint16_t lower_byte = data_buf.at(byte_index);
80 const std::uint16_t upper_byte = data_buf.at(byte_index + 1);
81 const std::uint16_t entry_bits = (upper_byte << 8) | lower_byte;
100 entry.h_flip((entry_bits >> 10) & 0x0001);
101 entry.v_flip((entry_bits >> 11) & 0x0001);
102 entry.palette_index((entry_bits >> 12) & 0x000F);
104 entries.push_back(std::move(entry));
113 std::ifstream metatile_attribute_bin{path, std::ios::binary};
114 if (!metatile_attribute_bin) {
119 const std::vector<unsigned char> data_buf{std::istreambuf_iterator(metatile_attribute_bin), {}};
122 if (data_buf.size() % attribute_bytes != 0) {
124 "Size of metatile_attributes.bin is not a multiple of {} bytes, possibly corrupted.",
128 std::vector<MetatileAttribute> attributes;
129 const std::size_t metatile_count = data_buf.size() / attribute_bytes;
130 attributes.reserve(metatile_count);
132 for (std::size_t metatile_index = 0; metatile_index < metatile_count; metatile_index++) {
133 const std::size_t base = metatile_index * attribute_bytes;
134 std::uint32_t raw = 0;
135 for (std::size_t byte_index = 0; byte_index < attribute_bytes; byte_index++) {
136 raw |=
static_cast<std::uint32_t
>(data_buf.at(base + byte_index)) << (byte_index * 8);
139 auto attribute_result = unpack_metatile_attribute(raw, schema);
140 if (!attribute_result.has_value()) {
145 attributes.push_back(std::move(attribute_result).value());
152 const std::vector<MetatileAttribute> &attributes,
const std::filesystem::path &path,
const Schema &schema)
154 std::ofstream out{path, std::ios::binary};
161 for (
const auto &attribute : attributes) {
162 const std::uint32_t raw = pack_metatile_attribute(attribute, schema);
163 for (std::size_t byte_index = 0; byte_index < attribute_bytes; byte_index++) {
164 out << static_cast<std::uint8_t>(raw >> (byte_index * 8));
175 if (!image_result.has_value()) {
180 return std::move(image_result.value());
186 auto palette_result = loader.
load(path);
187 if (!palette_result.has_value()) {
192 return palette_result.value();
#define PT_TRY_ASSIGN_PASS_ERR(var, expr, return_type)
Unwraps a ChainableResult, passing through the error chain with an empty FormattableError when types ...
A result type that maintains a chainable sequence of errors for debugging and error reporting.
One named bit-field within a metatile attribute layout.
A service interface that loads a fixed-length Palette from a given file.
virtual ChainableResult< Palette< Rgba32, palette::max_size > > load(const std::filesystem::path &path) const =0
An image loader that reads PNG files to create an Image with an index pixel type.
ChainableResult< std::unique_ptr< Image< IndexPixel > > > load_from_file(const std::filesystem::path &path) const
A validated metatile attribute layout: an ordered set of non-overlapping fields.
const Field * layer_type_field() const
Returns the field carrying the layer_type role, or nullptr when the layer type is disabled.
std::size_t attribute_bytes() const
static const Style bold
Bold text formatting.
Represents a tilemap entry referencing a tile with palette and flip attributes.
std::size_t tile_index() const
ChainableResult< void > save_metatile_attributes_bin(const std::vector< MetatileAttribute > &attributes, const std::filesystem::path &path, const Schema &schema)
Writes metatile attributes to a metatile_attributes.bin file according to a schema.
ChainableResult< LayerType > layer_type_from_int(unsigned int i)
Converts an integer to LayerType.
ChainableResult< Palette< Rgba32, palette::max_size > > load_porymap_palette(const std::filesystem::path &path, const FilePaletteLoader &loader)
Loads a Porymap palette file (e.g., 00.pal).
ChainableResult< std::vector< TilemapEntry > > parse_metatiles_bin(const std::filesystem::path &path)
Parses a metatiles.bin file into TilemapEntry objects.
ChainableResult< std::vector< MetatileAttribute > > parse_metatile_attributes(const std::filesystem::path &path, const Schema &schema)
Parses a metatile_attributes.bin file according to a metatile attribute schema.
ChainableResult< std::unique_ptr< Image< IndexPixel > > > load_indexed_png(const std::filesystem::path &path, const PngIndexedImageLoader &loader)
Loads an indexed PNG file (e.g., tiles.png).