1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#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
|