power_play/src/ase/ase.h
2025-09-04 00:57:28 -05:00

249 lines
4.6 KiB
C

////////////////////////////////
//~ Sheet types
Struct(ASE_Slice)
{
u32 start;
i32 x1;
i32 y1;
i32 x2;
i32 y2;
ASE_Slice *next;
};
Struct(ASE_Span)
{
String name;
u32 start;
u32 end;
ASE_Span *next;
};
Struct(ASE_Frame)
{
u32 index;
u32 x1;
u32 y1;
u32 x2;
u32 y2;
f64 duration;
ASE_Frame *next;
};
Struct(ASE_SliceKey)
{
String name;
u32 num_slices;
ASE_Slice *slice_head;
ASE_SliceKey *next;
};
////////////////////////////////
//~ Decoder result types
Struct(ASE_Error)
{
String msg;
ASE_Error *next;
};
Struct(ASE_ErrorList)
{
u64 count;
ASE_Error *first;
ASE_Error *last;
};
Struct(ASE_DecodedImage)
{
u32 width;
u32 height;
u32 *pixels; /* Array of [width * height] pixels */
ASE_ErrorList errors;
b32 success;
};
Struct(ASE_DecodedSheet)
{
Vec2 image_size;
Vec2 frame_size;
u32 num_frames;
u32 num_spans;
u32 num_slice_keys;
ASE_Frame *frame_head;
ASE_Span *span_head;
ASE_SliceKey *slice_key_head;
ASE_ErrorList errors;
b32 success;
};
////////////////////////////////
//~ Inflator types
#define ASE_HuffBitCount 16
Struct(ASE_Bitbuff)
{
u8 *data;
u64 cur_bit;
};
Enum(ASE_BlockType)
{
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
Enum(ASE_ChunkKind)
{
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
};
Enum(ASE_CelKind)
{
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;
};
////////////////////////////////
//~ 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 helpers
void ASE_PushError(Arena *arena, ASE_ErrorList *list, String msg_src);
////////////////////////////////
//~ Decode 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);