From 24887f28c3eb6d67a7c1a0803520b3fb728ee4f3 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 26 Apr 2021 11:11:36 +0200 Subject: Move code to relevant files for organization --- src/gba-buttons.c | 602 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 597 insertions(+), 5 deletions(-) (limited to 'src/gba-buttons.c') diff --git a/src/gba-buttons.c b/src/gba-buttons.c index 951b4dc..dd06351 100644 --- a/src/gba-buttons.c +++ b/src/gba-buttons.c @@ -1,3 +1,6 @@ +#include "common.h" +#include "sprites.h" + // 1bpp packed u32 gba_btn_a_data[] = { 0xc0300804, 0x844242c2, 0x030c1020, 0x21424243, @@ -133,11 +136,6 @@ u32 gba_btn_fx_startselect[] = { 0x01800000, 0x00000000, 0x00000000, 0x00000004, }; -typedef struct SpriteAnimation { - size_t *tile_offsets; - size_t n_frames; -} SpriteAnimation; - typedef enum {BTN_STATE_IDLE, BTN_STATE_PRESSED, BTN_STATE_RELEASED, BTN_STATE_HOLD} BtnState; typedef struct AnimationEntry { @@ -262,3 +260,597 @@ AnimationEntry *btn_animation_startselect[] = { {0, 0, 12, 1}, }, }; + +typedef struct ButtonSprite { + ObjState *sprites; + AnimationEntry **animations; + size_t frame; + size_t n_obj; + size_t n_frames; + BtnState state; +} ButtonSprite; + +void +init_button_sprite(ButtonSprite *btn) { + for (size_t i = 0; i < btn->n_obj; ++i) { + btn->sprites[i].id = load_packed_sprite_data( + btn->sprites[i].data, + btn->sprites[i].n_tiles, + btn->sprites[i].frames); + btn->sprites[i].base_tile = sprites[btn->sprites[i].id].tile_start; + } +} + +void +button_tick(ButtonSprite *btn) { + // Nothing to do here. + if (btn->state == BTN_STATE_IDLE) { + return; + } + + // Reset animation state. + if (btn->state == BTN_STATE_PRESSED && btn->frame != 0) { + btn->frame = 0; + } + + // Continue the animation. + if (btn->state == BTN_STATE_HOLD || btn->state == BTN_STATE_PRESSED ) { + if(btn->frame < btn->n_frames - 1) { + btn->frame++; + } + } + + // Finish the animation and return to idle. + if (btn->state == BTN_STATE_RELEASED) { + if (btn->frame > 0 && btn->frame < btn->n_frames - 1) { + btn->frame++; + } else { + btn->frame = 0; + btn->state = BTN_STATE_IDLE; + } + } + for (size_t i = 0; i < btn->n_obj; ++i) { + AnimationEntry anim_frame = btn->animations[i][btn->frame]; + int x = btn->sprites[i].x + anim_frame.x_offset; + int y = btn->sprites[i].y + anim_frame.y_offset; + int base_tile = btn->sprites[i].base_tile + anim_frame.tile_offset; + + // Clear the previous x/y coordinate and base tiles. + btn->sprites[i].obj_attr_0 &= ~0xFF; + btn->sprites[i].obj_attr_1 &= ~0x1FF; + btn->sprites[i].obj_attr_2 &= ~0x3FF; + + // Update x/y/tile and hidden state from the animations. + btn->sprites[i].obj_attr_0 |= OBJ_Y_COORD(y); + btn->sprites[i].obj_attr_1 |= OBJ_X_COORD(x); + btn->sprites[i].obj_attr_2 |= base_tile; + if (anim_frame.hidden) { + btn->sprites[i].obj_attr_0 |= OBJ_HIDDEN; + } else { + btn->sprites[i].obj_attr_0 &= ~OBJ_HIDDEN; + } + + // Update OBJ attributes. + OBJ_ATTR_0(btn->sprites[i].id) = btn->sprites[i].obj_attr_0; + OBJ_ATTR_1(btn->sprites[i].id) = btn->sprites[i].obj_attr_1; + OBJ_ATTR_2(btn->sprites[i].id) = btn->sprites[i].obj_attr_2; + } +} + +ButtonSprite buttons[] = { + // DOWN. + { + .frame = 0, + .n_obj = 3, + .n_frames = 8, + .state = BTN_STATE_RELEASED, + .animations = &btn_animation, + .sprites = &(ObjState[]){ + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 16, + .y = SCREEN_HEIGHT / 2 + 29, + .data = &gba_btn_updown_data, + .n_tiles = 4, + .frames = 1, + .obj_attr_0 = 0, + .obj_attr_1 = OBJ_V_FLIP | OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 16, + .y = SCREEN_HEIGHT / 2 + 29 + 11, + .data = &gba_btn_down_shadow_data, + .n_tiles = 2, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_SMALL, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 16 - 8, + .y = SCREEN_HEIGHT / 2 + 29 + 17, + .data = &gba_btn_fx_downup, + .n_tiles = 4, + .frames = 4, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + }, + }, + // UP. + { + .frame = 0, + .n_obj = 3, + .n_frames = 8, + .state = BTN_STATE_RELEASED, + .animations = &btn_animation, + .sprites = &(ObjState[]){ + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 16, + .y = SCREEN_HEIGHT / 2 + 32 - 18, + .data = &gba_btn_updown_data, + .n_tiles = 4, + .frames = 1, + .obj_attr_0 = 0, + .obj_attr_1 = OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 16, + .y = SCREEN_HEIGHT / 2 + 32 - 18 + 7, + .data = &gba_btn_up_shadow_data, + .n_tiles = 2, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_SMALL, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 16 - 8, + .y = SCREEN_HEIGHT / 2 + 32 - 18 - 7, + .data = &gba_btn_fx_downup, + .n_tiles = 4, + .frames = 4, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_V_FLIP | OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + }, + }, + // LEFT + { + .frame = 0, + .n_obj = 3, + .n_frames = 8, + .state = BTN_STATE_RELEASED, + .animations = &btn_animation, + .sprites = &(ObjState[]){ + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 16 - 10, + .y = SCREEN_HEIGHT / 2 + 32 - 10, + .data = &gba_btn_leftright_data, + .n_tiles = 4, + .frames = 1, + .obj_attr_0 = 0, + .obj_attr_1 = OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 16 - 10, + .y = SCREEN_HEIGHT / 2 + 32 - 10 + 6, + .data = &gba_btn_leftright_shadow_data, + .n_tiles = 2, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_SMALL, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 16 - 10 - 6, + .y = SCREEN_HEIGHT / 2 + 32 - 10 - 8, + .data = &gba_btn_fx_leftright, + .n_tiles = 4, + .frames = 4, + .obj_attr_0 = OBJ_SHAPE_TALL, + .obj_attr_1 = OBJ_H_FLIP | OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + }, + }, + // RIGHT. + { + .frame = 0, + .n_obj = 3, + .n_frames = 8, + .state = BTN_STATE_RELEASED, + .animations = &btn_animation, + .sprites = &(ObjState[]){ + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 16 + 11, + .y = SCREEN_HEIGHT / 2 + 32 - 10, + .data = &gba_btn_leftright_data, + .n_tiles = 4, + .frames = 1, + .obj_attr_0 = 0, + .obj_attr_1 = OBJ_H_FLIP | OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 16 + 11, + .y = SCREEN_HEIGHT / 2 + 32 - 10 + 6, + .data = &gba_btn_leftright_shadow_data, + .n_tiles = 2, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_H_FLIP | OBJ_SIZE_SMALL, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 16 + 11 + 14, + .y = SCREEN_HEIGHT / 2 + 32 - 10 - 8, + .data = &gba_btn_fx_leftright, + .n_tiles = 4, + .frames = 4, + .obj_attr_0 = OBJ_SHAPE_TALL, + .obj_attr_1 = OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + }, + }, + // L. + { + .frame = 0, + .n_obj = 3, + .n_frames = 8, + .state = BTN_STATE_RELEASED, + .animations = &btn_animation, + .sprites = &(ObjState[]){ + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 28, + .y = SCREEN_HEIGHT / 2 - 32 - 20, + .data = &gba_btn_l_data, + .n_tiles = 2, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_SMALL, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 28, + .y = SCREEN_HEIGHT / 2 - 32 - 20 + 2, + .data = &gba_btn_lr_shadow_data, + .n_tiles = 2, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_SMALL, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 64 - 28 - 12, + .y = SCREEN_HEIGHT / 2 - 32 - 20 - 12, + .data = &gba_btn_fx_lr, + .n_tiles = 4, + .frames = 4, + .obj_attr_0 = OBJ_SHAPE_SQUARE, + .obj_attr_1 = OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + }, + }, + // R. + { + .frame = 0, + .n_obj = 3, + .n_frames = 8, + .state = BTN_STATE_RELEASED, + .animations = &btn_animation, + .sprites = &(ObjState[]){ + { + .id = 0, + .x = SCREEN_WIDTH / 2 + 32 + 20 + 24, + .y = SCREEN_HEIGHT / 2 - 32 - 20, + .data = &gba_btn_r_data, + .n_tiles = 2, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_SMALL, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 + 32 + 20 + 24, + .y = SCREEN_HEIGHT / 2 - 32 - 20 + 2, + .data = &gba_btn_lr_shadow_data, + .n_tiles = 2, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_SMALL, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 + 32 + 20 + 12 + 24, + .y = SCREEN_HEIGHT / 2 - 32 - 20 - 12, + .data = &gba_btn_fx_lr, + .n_tiles = 4, + .frames = 4, + .obj_attr_0 = OBJ_SHAPE_SQUARE, + .obj_attr_1 = OBJ_H_FLIP | OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + }, + }, + // A. + { + .frame = 0, + .n_obj = 3, + .n_frames = 8, + .state = BTN_STATE_RELEASED, + .animations = &btn_animation_ab, + .sprites = &(ObjState[]){ + { + .id = 0, + .x = SCREEN_WIDTH / 2 + 32 + 20 + 20, + .y = SCREEN_HEIGHT / 2 + 32 - 16, + .data = &gba_btn_a_data, + .n_tiles = 4, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_SQUARE, + .obj_attr_1 = OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 + 32 + 20 + 20, + .y = SCREEN_HEIGHT / 2 + 32 - 16 + 8, + .data = &gba_btn_ab_shadow_data, + .n_tiles = 2, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_SMALL, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 + 32 + 19 - 7 + 20, + .y = SCREEN_HEIGHT / 2 + 32 - 23, + .data = &gba_btn_fx_ab, + .n_tiles = 16, + .frames = 3, + .obj_attr_0 = OBJ_SHAPE_SQUARE, + .obj_attr_1 = OBJ_SIZE_BIG, + .obj_attr_2 = 0 + }, + }, + }, + // B. + { + .frame = 0, + .n_obj = 3, + .n_frames = 8, + .state = BTN_STATE_RELEASED, + .animations = &btn_animation_ab, + .sprites = &(ObjState[]){ + { + .id = 0, + .x = SCREEN_WIDTH / 2 + 32 + 20, + .y = SCREEN_HEIGHT / 2 + 32, + .data = &gba_btn_b_data, + .n_tiles = 4, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_SQUARE, + .obj_attr_1 = OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 + 32 + 20, + .y = SCREEN_HEIGHT / 2 + 32 + 8, + .data = &gba_btn_ab_shadow_data, + .n_tiles = 2, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_SMALL, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 + 32 - 8 + 20, + .y = SCREEN_HEIGHT / 2 + 33 + 8 - 16, + .data = &gba_btn_fx_ab, + .n_tiles = 16, + .frames = 3, + .obj_attr_0 = OBJ_SHAPE_SQUARE, + .obj_attr_1 = OBJ_SIZE_BIG, + .obj_attr_2 = 0 + }, + }, + }, + // START. + { + .frame = 0, + .n_obj = 3, + .n_frames = 8, + .state = BTN_STATE_RELEASED, + .animations = &btn_animation_startselect, + .sprites = &(ObjState[]){ + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 10 + 26 - 14, + .y = SCREEN_HEIGHT / 2 + 40 + 10, + .data = &gba_btn_startselect_data, + .n_tiles = 2, + .frames = 2, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_SMALL, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 18 + 26 - 14, + .y = SCREEN_HEIGHT / 2 + 46 + 10, + .data = &gba_btn_start_text, + .n_tiles = 4, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 19 + 26 - 14, + .y = SCREEN_HEIGHT / 2 + 37 + 10, + .data = &gba_btn_fx_startselect, + .n_tiles = 4, + .frames = 4, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + }, + }, + // SELECT. + { + .frame = 0, + .n_obj = 3, + .n_frames = 8, + .state = BTN_STATE_RELEASED, + .animations = &btn_animation_startselect, + .sprites = &(ObjState[]){ + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 10 - 14, + .y = SCREEN_HEIGHT / 2 + 40 + 10, + .data = &gba_btn_startselect_data, + .n_tiles = 2, + .frames = 2, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_SMALL, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 18 - 14, + .y = SCREEN_HEIGHT / 2 + 46 + 10, + .data = &gba_btn_select_text, + .n_tiles = 4, + .frames = 1, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + { + .id = 0, + .x = SCREEN_WIDTH / 2 - 19 - 14, + .y = SCREEN_HEIGHT / 2 + 37 + 10, + .data = &gba_btn_fx_startselect, + .n_tiles = 4, + .frames = 4, + .obj_attr_0 = OBJ_SHAPE_WIDE, + .obj_attr_1 = OBJ_SIZE_MID, + .obj_attr_2 = 0 + }, + }, + }, +}; + +static inline void +init_button_sprites(void) { + for (size_t i = 0; i < sizeof(buttons) / sizeof(ButtonSprite); ++i) { + init_button_sprite(&buttons[i]); + } +} + +static inline void +update_button_sprites(void) { + if (key_pressed(KEY_DOWN)) { + buttons[0].state = BTN_STATE_PRESSED; + } else if (key_hold(KEY_DOWN)) { + buttons[0].state = BTN_STATE_HOLD; + } else { + buttons[0].state = BTN_STATE_RELEASED; + } + if (key_pressed(KEY_UP)) { + buttons[1].state = BTN_STATE_PRESSED; + } else if (key_hold(KEY_UP)) { + buttons[1].state = BTN_STATE_HOLD; + } else { + buttons[1].state = BTN_STATE_RELEASED; + } + if (key_pressed(KEY_LEFT)) { + buttons[2].state = BTN_STATE_PRESSED; + } else if (key_hold(KEY_LEFT)) { + buttons[2].state = BTN_STATE_HOLD; + } else { + buttons[2].state = BTN_STATE_RELEASED; + } + if (key_pressed(KEY_RIGHT)) { + buttons[3].state = BTN_STATE_PRESSED; + } else if (key_hold(KEY_RIGHT)) { + buttons[3].state = BTN_STATE_HOLD; + } else { + buttons[3].state = BTN_STATE_RELEASED; + } + if (key_pressed(KEY_L)) { + buttons[4].state = BTN_STATE_PRESSED; + } else if (key_hold(KEY_L)) { + buttons[4].state = BTN_STATE_HOLD; + } else { + buttons[4].state = BTN_STATE_RELEASED; + } + if (key_pressed(KEY_R)) { + buttons[5].state = BTN_STATE_PRESSED; + } else if (key_hold(KEY_R)) { + buttons[5].state = BTN_STATE_HOLD; + } else { + buttons[5].state = BTN_STATE_RELEASED; + } + if (key_pressed(KEY_A)) { + buttons[6].state = BTN_STATE_PRESSED; + } else if (key_hold(KEY_A)) { + buttons[6].state = BTN_STATE_HOLD; + } else { + buttons[6].state = BTN_STATE_RELEASED; + } + if (key_pressed(KEY_B)) { + buttons[7].state = BTN_STATE_PRESSED; + } else if (key_hold(KEY_B)) { + buttons[7].state = BTN_STATE_HOLD; + } else { + buttons[7].state = BTN_STATE_RELEASED; + } + if (key_pressed(KEY_START)) { + buttons[8].state = BTN_STATE_PRESSED; + } else if (key_hold(KEY_START)) { + buttons[8].state = BTN_STATE_HOLD; + } else { + buttons[8].state = BTN_STATE_RELEASED; + } + if (key_pressed(KEY_SELECT)) { + buttons[9].state = BTN_STATE_PRESSED; + } else if (key_hold(KEY_SELECT)) { + buttons[9].state = BTN_STATE_HOLD; + } else { + buttons[9].state = BTN_STATE_RELEASED; + } + + for (size_t i = 0; i < sizeof(buttons) / sizeof(ButtonSprite); ++i) { + button_tick(&buttons[i]); + } +} -- cgit v1.2.1