From 6cefdd40dd62f098874bd706720db731341bc957 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Mon, 14 Jul 2025 08:52:15 -0700 Subject: Move file format defs to separate header --- include/isogfx/asset.h | 132 +++++++++++++++++++++++++++++++++++++++++++++++++ src/isogfx.c | 129 ++++------------------------------------------- 2 files changed, 142 insertions(+), 119 deletions(-) create mode 100644 include/isogfx/asset.h diff --git a/include/isogfx/asset.h b/include/isogfx/asset.h new file mode 100644 index 0000000..298c469 --- /dev/null +++ b/include/isogfx/asset.h @@ -0,0 +1,132 @@ +/* + * File format definitions for isogfx assets. + * + * All formats are defined so that they can be simply read into memory and used + * by the engine. Likewise, a tool that generates these formats can generate + * the structures in memory and then write them as is to a file. + */ +#pragma once + +#include +#include + +// Maximum length of path strings in .TS and .TM files. +#define ISOGFX_MAX_PATH_LENGTH 128 + +// ----------------------------------------------------------------------------- +// Tile set (TS) file format. +// ----------------------------------------------------------------------------- + +typedef struct Ts_Tile { + uint16_t width; // Tile width in pixels. + uint16_t height; // Tile height in pixels. + Pixel pixels[1]; // Count: width * height. +} Ts_Tile; + +typedef struct Ts_TileSet { + uint16_t num_tiles; + uint16_t max_tile_width; // Maximum tile width in pixels. + uint16_t max_tile_height; // Maximum tile height in pixels. + Ts_Tile tiles[1]; // Count: num_tiles. +} Ts_TileSet; + +// ----------------------------------------------------------------------------- +// Tile map (TM) file format. +// ----------------------------------------------------------------------------- + +typedef struct Tm_Layer { + union { + char tileset_path[ISOGFX_MAX_PATH_LENGTH]; // Relative to the Tm_Map file. + }; + Tile tiles[1]; // Count: world_width * world_height. +} Tm_Layer; + +typedef struct Tm_Map { + uint16_t world_width; // World width in number of tiles. + uint16_t world_height; // World height in number of tiles. + uint16_t base_tile_width; + uint16_t base_tile_height; + uint16_t num_layers; + Tm_Layer layers[1]; // Count: num_layers. +} Tm_Map; + +// ----------------------------------------------------------------------------- +// Sprite sheet file format. +// ----------------------------------------------------------------------------- + +/// A row of sprites in a sprite sheet. +/// +/// Each row in a sprite sheet can have a different number of columns. +/// +/// The pixels of the row follow a "sprite-major" order. It contains the +/// 'sprite_width * sprite_height' pixels for the first column/sprite, then the +/// second column/sprite, etc. +/// +/// Pixels are 8-bit indices into the sprite sheet's colour palette. +typedef struct Ss_Row { + uint16_t num_cols; /// Number of columns in this row. + uint8_t pixels[1]; /// Count: num_cols * sprite_width * sprite_height. +} Ss_Row; + +typedef struct Ss_Palette { + uint16_t num_colours; + Pixel colours[1]; /// Count: num_colors. +} Ss_Palette; + +/// Sprite sheet top-level data definition. +/// +/// Sprite width and height are assumed constant throughout the sprite sheet. +typedef struct Ss_SpriteSheet { + uint16_t sprite_width; /// Sprite width in pixels. + uint16_t sprite_height; /// Sprite height in pixels. + uint16_t num_rows; + Ss_Palette palette; /// Variable size. + Ss_Row rows[1]; /// Count: num_rows. Variable offset. +} Ss_SpriteSheet; + +// ----------------------------------------------------------------------------- +// Data accessors. +// ----------------------------------------------------------------------------- + +/// Return the next tile in the tile set. +static inline const Ts_Tile* ts_tileset_get_next_tile( + const Ts_TileSet* tileset, const Ts_Tile* tile) { + assert(tileset); + assert(tile); + return (const Ts_Tile*)((const uint8_t*)tile + sizeof(Ts_Tile) + + ((tile->width * tile->height - 1) * sizeof(Pixel))); +} + +/// Return the next layer in the tile map. +static inline const Tm_Layer* tm_map_get_next_layer( + const Tm_Map* map, const Tm_Layer* layer) { + assert(map); + assert(layer); + return (const Tm_Layer*)((const uint8_t*)layer + sizeof(Tm_Layer) + + ((map->world_width * map->world_height - 1) * + sizeof(Tile))); +} + +/// Return the ith row in the sprite sheet. +static inline const Ss_Row* get_sprite_sheet_row( + const Ss_SpriteSheet* sheet, int row) { + assert(sheet); + assert(row >= 0); + assert(row < sheet->num_rows); + // Skip over the palette. + const Ss_Row* rows = + (const Ss_Row*)(&sheet->palette.colours[0] + sheet->palette.num_colours); + return &rows[row]; +} + +/// Return the ith sprite in the row. +static inline const uint8_t* get_sprite_sheet_sprite( + const Ss_SpriteSheet* sheet, const Ss_Row* row, int col) { + assert(sheet); + assert(row); + assert(col >= 0); + assert(col < row->num_cols); + const int sprite_offset = col * sheet->sprite_width * sheet->sprite_height; + const uint8_t* sprite = &row->pixels[sprite_offset]; + return sprite; +} diff --git a/src/isogfx.c b/src/isogfx.c index 52c4ae2..baf422f 100644 --- a/src/isogfx.c +++ b/src/isogfx.c @@ -1,5 +1,7 @@ #include +#include + #include #include #include @@ -37,115 +39,6 @@ typedef struct vec2 { double x, y; } vec2; -// ----------------------------------------------------------------------------- -// Tile set (TS) and tile map (TM) file formats. -// ----------------------------------------------------------------------------- - -/// Maximum length of path strings in .TS and .TM files. -#define MAX_PATH_LENGTH 128 - -typedef struct Ts_Tile { - uint16_t width; /// Tile width in pixels. - uint16_t height; /// Tile height in pixels. - Pixel pixels[1]; /// Count: width * height. -} Ts_Tile; - -typedef struct Ts_TileSet { - uint16_t num_tiles; - uint16_t max_tile_width; /// Maximum tile width in pixels. - uint16_t max_tile_height; /// Maximum tile height in pixels. - Ts_Tile tiles[1]; /// Count: num_tiles. -} Ts_TileSet; - -typedef struct Tm_Layer { - union { - char tileset_path[MAX_PATH_LENGTH]; // Relative to the Tm_Map file. - }; - Tile tiles[1]; /// Count: world_width * world_height. -} Tm_Layer; - -typedef struct Tm_Map { - uint16_t world_width; /// World width in number of tiles. - uint16_t world_height; /// World height in number of tiles. - uint16_t base_tile_width; - uint16_t base_tile_height; - uint16_t num_layers; - Tm_Layer layers[1]; // Count: num_layers. -} Tm_Map; - -static inline const Tm_Layer* tm_map_get_next_layer( - const Tm_Map* map, const Tm_Layer* layer) { - assert(map); - assert(layer); - return (const Tm_Layer*)((const uint8_t*)layer + sizeof(Tm_Layer) + - ((map->world_width * map->world_height - 1) * - sizeof(Tile))); -} - -static inline const Ts_Tile* ts_tileset_get_next_tile( - const Ts_TileSet* tileset, const Ts_Tile* tile) { - assert(tileset); - assert(tile); - return (const Ts_Tile*)((const uint8_t*)tile + sizeof(Ts_Tile) + - ((tile->width * tile->height - 1) * sizeof(Pixel))); -} - -// ----------------------------------------------------------------------------- -// Sprite sheet file format. -// ----------------------------------------------------------------------------- - -/// A row of sprites in a sprite sheet. -/// -/// Each row in a sprite sheet can have a different number of columns. -/// -/// The pixels of the row follow a "sprite-major" order. It contains the -/// 'sprite_width * sprite_height' pixels for the first column/sprite, then the -/// second column/sprite, etc. -/// -/// Pixels are 8-bit indices into the sprite sheet's colour palette. -typedef struct Ss_Row { - uint16_t num_cols; /// Number of columns in this row. - uint8_t pixels[1]; /// Count: num_cols * sprite_width * sprite_height. -} Ss_Row; - -typedef struct Ss_Palette { - uint16_t num_colours; - Pixel colours[1]; /// Count: num_colors. -} Ss_Palette; - -/// Sprite sheet top-level data definition. -/// -/// Sprite width and height are assumed constant throughout the sprite sheet. -typedef struct Ss_SpriteSheet { - uint16_t sprite_width; /// Sprite width in pixels. - uint16_t sprite_height; /// Sprite height in pixels. - uint16_t num_rows; - Ss_Palette palette; /// Variable size. - Ss_Row rows[1]; /// Count: num_rows. Variable offset. -} Ss_SpriteSheet; - -static inline const Ss_Row* get_sprite_sheet_row( - const Ss_SpriteSheet* sheet, int row) { - assert(sheet); - assert(row >= 0); - assert(row < sheet->num_rows); - // Skip over the palette. - const Ss_Row* rows = - (const Ss_Row*)(&sheet->palette.colours[0] + sheet->palette.num_colours); - return &rows[row]; -} - -static inline const uint8_t* get_sprite_sheet_sprite( - const Ss_SpriteSheet* sheet, const Ss_Row* row, int col) { - assert(sheet); - assert(row); - assert(col >= 0); - assert(col < row->num_cols); - const int sprite_offset = col * sheet->sprite_width * sheet->sprite_height; - const uint8_t* sprite = &row->pixels[sprite_offset]; - return sprite; -} - // ----------------------------------------------------------------------------- // Renderer state. // ----------------------------------------------------------------------------- @@ -204,8 +97,8 @@ static inline ivec2 ivec2_scale(ivec2 a, int s) { } static inline ivec2 iso2cart(ivec2 iso, int s, int t, int w) { - return (ivec2){ - .x = (iso.x - iso.y) * (s / 2) + (w / 2), .y = (iso.x + iso.y) * (t / 2)}; + return (ivec2){.x = (iso.x - iso.y) * (s / 2) + (w / 2), + .y = (iso.x + iso.y) * (t / 2)}; } // Method 1. @@ -221,9 +114,8 @@ static inline vec2 cart2iso(vec2 cart, int s, int t, int w) { const double one_over_s = 1. / (double)s; const double one_over_t = 1. / (double)t; const double x = cart.x - (double)(w / 2); - return (vec2){ - .x = (one_over_s * x + one_over_t * cart.y), - .y = (-one_over_s * x + one_over_t * cart.y)}; + return (vec2){.x = (one_over_s * x + one_over_t * cart.y), + .y = (-one_over_s * x + one_over_t * cart.y)}; } static const Pixel* tile_xy_const_ref( @@ -752,11 +644,10 @@ static Pixel alpha_blend(Pixel src, Pixel dst) { (double)((uint16_t)s * (uint16_t)src.a + \ (uint16_t)d * one_minus_alpha) / \ 255.0) - return (Pixel){ - .r = blend(src.r, dst.r), - .g = blend(src.g, dst.g), - .b = blend(src.b, dst.b), - .a = src.a}; + return (Pixel){.r = blend(src.r, dst.r), + .g = blend(src.g, dst.g), + .b = blend(src.b, dst.b), + .a = src.a}; } /// Draw a rectangle (tile or sprite). -- cgit v1.2.3