ase layer refactor

This commit is contained in:
jacob 2025-07-30 16:44:49 -05:00
parent a29c728b92
commit c1c0ca5464
3 changed files with 517 additions and 350 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,157 @@
Struct(Ase_Error) { ////////////////////////////////
//~ Inflator types
#define Ase_HuffBitCount 16
Struct(Ase_Bitbuff)
{
u8 *data;
u64 cur_bit;
};
typedef i32 Ase_BlockType; enum
{
Ase_BlockType_Uncompressed = 0,
Ase_BlockType_CompressedFixed = 1,
Ase_BlockType_CompressedDynamic = 2,
Ase_BlockType_Reserved = 3
};
Struct(Ase_HuffEntry)
{
u16 symbol;
u16 bits_used;
};
Struct(Ase_HuffDict)
{
u32 max_code_bits;
u32 entries_count;
Ase_HuffEntry *entries;
};
////////////////////////////////
//~ Header types
Packed(Struct(Ase_Header)
{
u32 file_size;
u16 magic;
u16 frames;
u16 width;
u16 height;
u16 color_depth;
u32 flags;
u16 speed;
u32 _1;
u32 _2;
u8 palette_entry;
u8 _3[3];
u16 num_colors;
u8 pixel_width;
u8 pixel_height;
i16 grid_x;
i16 grid_y;
u16 grid_width;
u16 grid_height;
u8 _4[84];
});
Packed(Struct(Ase_FrameHeader)
{
u32 bytes;
u16 magic;
u16 chunks_old;
u16 frame_duration_ms;
u8 _[2];
u32 chunks_new;
});
////////////////////////////////
//~ Image decoder types
typedef i32 Ase_ChunkKind; enum
{
Ase_ChunkKind_OldPalette1 = 0x0004,
Ase_ChunkKind_OldPalette2 = 0x0011,
Ase_ChunkKind_Layer = 0x2004,
Ase_ChunkKind_Cel = 0x2005,
Ase_ChunkKind_CelExtra = 0x2006,
Ase_ChunkKind_ColorProfile = 0x2007,
Ase_ChunkKind_ExternalFiles = 0x2008,
Ase_ChunkKind_Mask = 0x2016,
Ase_ChunkKind_Path = 0x2017,
Ase_ChunkKind_Tags = 0x2018,
Ase_ChunkKind_Palette = 0x2019,
Ase_ChunkKind_Userdata = 0x2020,
Ase_ChunkKind_Slice = 0x2022,
Ase_ChunkKind_Tileset = 0x2023
};
typedef i32 Ase_CelKind; enum
{
Ase_CelKind_RawImage = 0,
Ase_CelKind_Linked = 1,
Ase_CelKind_CompressedImage = 2,
Ase_CelKind_CompressedTilemap = 3
};
Struct(Ase_Layer)
{
u16 flags;
u16 type;
u16 child_level;
u16 blend_mode;
u8 opacity;
String name;
u32 tileset_index;
u32 index;
Ase_Layer *next;
};
Struct(Ace_Cel)
{
u16 layer_index;
i16 x_pos;
i16 y_pos;
u8 opacity;
Ase_CelKind type;
i16 z_index;
/* Linked cel */
u16 frame_pos;
/* Compressed image */
u32 width;
u32 height;
u32 *pixels;
u16 frame_index;
Ace_Cel *next;
};
////////////////////////////////
//~ Error types
Struct(Ase_Error)
{
String msg; String msg;
Ase_Error *next; Ase_Error *next;
}; };
Struct(Ase_ErrorList) { Struct(Ase_ErrorList)
{
u64 count; u64 count;
Ase_Error *first; Ase_Error *first;
Ase_Error *last; Ase_Error *last;
}; };
Struct(Ase_Slice) { ////////////////////////////////
//~ Sheet types
Struct(Ase_Slice)
{
u32 start; u32 start;
i32 x1; i32 x1;
i32 y1; i32 y1;
@ -18,21 +160,24 @@ Struct(Ase_Slice) {
Ase_Slice *next; Ase_Slice *next;
}; };
Struct(Ase_SliceKey) { Struct(Ase_SliceKey)
{
String name; String name;
u32 num_slices; u32 num_slices;
Ase_Slice *slice_head; Ase_Slice *slice_head;
Ase_SliceKey *next; Ase_SliceKey *next;
}; };
Struct(Ase_Span) { Struct(Ase_Span)
{
String name; String name;
u32 start; u32 start;
u32 end; u32 end;
Ase_Span *next; Ase_Span *next;
}; };
Struct(Ase_Frame) { Struct(Ase_Frame)
{
u32 index; u32 index;
u32 x1; u32 x1;
u32 y1; u32 y1;
@ -42,7 +187,11 @@ Struct(Ase_Frame) {
Ase_Frame *next; Ase_Frame *next;
}; };
Struct(Ase_DecodedImage) { ////////////////////////////////
//~ Decoder result types
Struct(Ase_DecodedImage)
{
u32 width; u32 width;
u32 height; u32 height;
u32 *pixels; /* Array of [width * height] pixels */ u32 *pixels; /* Array of [width * height] pixels */
@ -50,7 +199,8 @@ Struct(Ase_DecodedImage) {
b32 success; b32 success;
}; };
Struct(Ase_DecodedSheet) { Struct(Ase_DecodedSheet)
{
Vec2 image_size; Vec2 image_size;
Vec2 frame_size; Vec2 frame_size;
u32 num_frames; u32 num_frames;
@ -63,5 +213,36 @@ Struct(Ase_DecodedSheet) {
b32 success; b32 success;
}; };
Ase_DecodedImage ase_decode_image(Arena *arena, String encoded); ////////////////////////////////
Ase_DecodedSheet ase_decode_sheet(Arena *arena, String encoded); //~ Ase bitbuff operations
u32 Ase_PeekBits(Ase_Bitbuff *bb, u32 nbits);
u32 Ase_ConsumeBits(Ase_Bitbuff *bb, u32 nbits);
void Ase_SkipBits(Ase_Bitbuff *bb, u32 nbits);
////////////////////////////////
//~ Inflate operations
u32 Ase_ReverseBits(u32 v, u32 bit_count);
Ase_HuffDict Ase_InitHuffDict(Arena *arena, u32 max_code_bits, u32 *bl_counts, u32 bl_counts_count);
u16 Ase_DecodeHuffDict(Ase_HuffDict *huffman, Ase_Bitbuff *bb);
void Ase_Inflate(u8 *dst, u8 *encoded);
////////////////////////////////
//~ Error handling operations
void Ase_PushError(Arena *arena, Ase_ErrorList *list, String msg_src);
////////////////////////////////
//~ Decoder operations
//- Helpers
u32 Ase_BlendMulU8(u32 a, u32 b);
u32 Ase_Blend(u32 src, u32 dst, u8 opacity);
void Ase_MakeDimensionsSquareish(Ase_Header *header, u32 *frames_x, u32 *frames_y, u64 *image_width, u64 *image_height);
//- Decode image
Ase_DecodedImage Ase_DecodeImage(Arena *arena, String encoded);
//- Decode sheet
Ase_DecodedSheet Ase_DecodeSheet(Arena *arena, String encoded);

View File

@ -339,7 +339,7 @@ internal void cache_entry_load_texture(struct cache_ref ref, S_Tag tag)
{ {
R_Resource texture_rs = resource_open(path); R_Resource texture_rs = resource_open(path);
if (resource_exists(&texture_rs)) { if (resource_exists(&texture_rs)) {
decoded = ase_decode_image(scratch.arena, resource_get_data(&texture_rs)); decoded = Ase_DecodeImage(scratch.arena, resource_get_data(&texture_rs));
} else { } else {
P_LogErrorF("Sprite texture for \"%F\" not found", FmtString(path)); P_LogErrorF("Sprite texture for \"%F\" not found", FmtString(path));
} }
@ -659,7 +659,7 @@ internal void cache_entry_load_sheet(struct cache_ref ref, S_Tag tag)
{ {
R_Resource sheet_rs = resource_open(path); R_Resource sheet_rs = resource_open(path);
if (resource_exists(&sheet_rs)) { if (resource_exists(&sheet_rs)) {
decoded = ase_decode_sheet(scratch.arena, resource_get_data(&sheet_rs)); decoded = Ase_DecodeSheet(scratch.arena, resource_get_data(&sheet_rs));
} else { } else {
P_LogErrorF("Sprite sheet for \"%F\" not found", FmtString(path)); P_LogErrorF("Sprite sheet for \"%F\" not found", FmtString(path));
} }
@ -668,7 +668,7 @@ internal void cache_entry_load_sheet(struct cache_ref ref, S_Tag tag)
if (decoded.success) { if (decoded.success) {
R_Resource sheet_rs = resource_open(path); R_Resource sheet_rs = resource_open(path);
decoded = ase_decode_sheet(scratch.arena, resource_get_data(&sheet_rs)); decoded = Ase_DecodeSheet(scratch.arena, resource_get_data(&sheet_rs));
resource_close(&sheet_rs); resource_close(&sheet_rs);
/* Initialize */ /* Initialize */