#ifndef GBAEXP_SPRITES_H #define GBAEXP_SPRITES_H #include "common.h" u32 unpack_1bb(u8 hex) { const u32 conversion_u32[16] = { 0x00000000, 0x00000001, 0x00000010, 0x00000011, 0x00000100, 0x00000101, 0x00000110, 0x00000111, 0x00001000, 0x00001001, 0x00001010, 0x00001011, 0x00001100, 0x00001101, 0x00001110, 0x00001111, }; u8 low = hex & 0xF; u8 high = (hex >> 4) & 0xF; return (conversion_u32[high] << 16) | conversion_u32[low]; } typedef struct Sprite { // A unique sprite identifier. size_t id; // The number of tiles for a single sprite frame. size_t n_tiles; // The starting tile of this sprite. size_t tile_start; // The associated palette bank for this sprite. size_t pal_bank; } Sprite; #define NUM_SPRITES 128 Sprite sprites[NUM_SPRITES]; // Keeping track of unique sprites and current sprite memory pointer using // global singletons. size_t sprite_counter = 0; size_t sprite_tile_counter = 0; u32 *sprite_memory = NULL; // Loads the sprite data into video memory and initialize the Sprite structure. size_t load_sprite_data(u32 *sprite_data, size_t n_tiles, size_t n_frames) { memcpy(sprite_memory, sprite_data, 8 * n_tiles * n_frames * sizeof(u32)); sprite_memory += 8 * n_tiles * n_frames; Sprite sprite = { .id = sprite_counter, .n_tiles = n_tiles, .tile_start = sprite_tile_counter, }; sprite_tile_counter += n_tiles * n_frames; sprites[sprite_counter] = sprite; return sprite_counter++; } size_t load_packed_sprite_data(u32 *sprite_data, size_t n_tiles, size_t n_frames) { size_t counter = 0; for (size_t i = 0; i < 8 * n_tiles * n_frames / 4; ++i) { u32 hex = sprite_data[i]; sprite_memory[counter++] = unpack_1bb((hex >> 24) & 0xFF); sprite_memory[counter++] = unpack_1bb((hex >> 16) & 0xFF); sprite_memory[counter++] = unpack_1bb((hex >> 8) & 0xFF); sprite_memory[counter++] = unpack_1bb((hex) & 0xFF); } sprite_memory += 8 * n_tiles * n_frames; Sprite sprite = { .id = sprite_counter, .n_tiles = n_tiles, .tile_start = sprite_tile_counter, }; sprite_tile_counter += n_tiles * n_frames; sprites[sprite_counter] = sprite; return sprite_counter++; } void init_sprites(size_t starting_tile) { // Initialize all attributes by disabling rendering. If we don't do this, // glitches may appear. for (size_t i = 0; i < 128; ++i) { OBJ_ATTR_0(i) = (1 << 9); } sprite_counter = 0; // Prepare global sprite_memory address. sprite_memory = &TILE_MEM[4][starting_tile]; } void init_sprite_pal(size_t starting_index, Color col) { // Add colors to the sprite color palette. Tiles with color number 0 are // treated as transparent. for (size_t i = 0; i < 16; ++i) { PAL_BUFFER_SPRITES[i + starting_index] = col; } } #endif // GBAEXP_SPRITES_H