From be37f274be067e92f9240112b7a047b8ef9e09b0 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 8 Jan 2024 15:32:13 +0100 Subject: Add input retriggering with configurable rate and offset --- src/gba/gba.h | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) (limited to 'src/gba/gba.h') diff --git a/src/gba/gba.h b/src/gba/gba.h index 8ba3de5..b5868f0 100644 --- a/src/gba/gba.h +++ b/src/gba/gba.h @@ -327,6 +327,117 @@ key_hold(u32 key) { return key_curr & key_prev & key; } +// Stores number of frames since a keay was pressed. +typedef struct Controller { + int key_up; + int key_down; + int key_left; + int key_right; + int key_select; + int key_start; + int key_b; + int key_a; + int key_l; + int key_r; +} Controller; + +static Controller ctrl = {0}; + +#define RETRIG_OFFSET 16 +#define RETRIG_FRAMES 3 + +static inline +bool +_key_retrig(int key, int offset, int frames) { + if (key_tap(key)) { + return true; + } + switch (key) { + case KEY_L: { + if (key_hold(key)) { + if (ctrl.key_l < offset) { return false; } + if (ctrl.key_l % frames == 0) { return true; } + } + } break; + case KEY_R: { + if (key_hold(key)) { + if (ctrl.key_r < offset) { return false; } + if (ctrl.key_r % frames == 0) { return true; } + } + } break; + case KEY_A: { + if (key_hold(key)) { + if (ctrl.key_a < offset) { return false; } + if (ctrl.key_a % frames == 0) { return true; } + } + } break; + case KEY_B: { + if (key_hold(key)) { + if (ctrl.key_b < offset) { return false; } + if (ctrl.key_b % frames == 0) { return true; } + } + } break; + case KEY_SELECT: { + if (key_hold(key)) { + if (ctrl.key_select < offset) { return false; } + if (ctrl.key_select % frames == 0) { return true; } + } + } break; + case KEY_START: { + if (key_hold(key)) { + if (ctrl.key_start < offset) { return false; } + if (ctrl.key_start % frames == 0) { return true; } + } + } break; + case KEY_UP: { + if (key_hold(key)) { + if (ctrl.key_up < offset) { return false; } + if (ctrl.key_up % frames == 0) { return true; } + } + } break; + case KEY_DOWN: { + if (key_hold(key)) { + if (ctrl.key_down < offset) { return false; } + if (ctrl.key_down % frames == 0) { return true; } + } + } break; + case KEY_LEFT: { + if (key_hold(key)) { + if (ctrl.key_left < offset) { return false; } + if (ctrl.key_left % frames == 0) { return true; } + } + } break; + case KEY_RIGHT: { + if (key_hold(key)) { + if (ctrl.key_right < offset) { return false; } + if (ctrl.key_right % frames == 0) { return true; } + } + } break; + } + return false; +} + +static inline +bool +key_retrig(int key) { + return _key_retrig(key, RETRIG_OFFSET, RETRIG_FRAMES); +} + +static inline +void +update_controller(void) { + if (key_pressed(KEY_UP)) { ctrl.key_up++; } else if (key_released(KEY_UP)) { ctrl.key_up = 0; } + if (key_pressed(KEY_DOWN)) { ctrl.key_down++; } else if (key_released(KEY_DOWN)) { ctrl.key_down = 0; } + if (key_pressed(KEY_LEFT)) { ctrl.key_left++; } else if (key_released(KEY_LEFT)) { ctrl.key_left = 0; } + if (key_pressed(KEY_RIGHT)) { ctrl.key_right++; } else if (key_released(KEY_RIGHT)) { ctrl.key_right = 0; } + if (key_pressed(KEY_L)) { ctrl.key_l++; } else if (key_released(KEY_L)) { ctrl.key_l = 0; } + if (key_pressed(KEY_R)) { ctrl.key_r++; } else if (key_released(KEY_R)) { ctrl.key_r = 0; } + if (key_pressed(KEY_A)) { ctrl.key_a++; } else if (key_released(KEY_A)) { ctrl.key_a = 0; } + if (key_pressed(KEY_B)) { ctrl.key_b++; } else if (key_released(KEY_B)) { ctrl.key_b = 0; } + if (key_pressed(KEY_SELECT)) { ctrl.key_select++; } else if (key_released(KEY_SELECT)) { ctrl.key_select = 0; } + if (key_pressed(KEY_START)) { ctrl.key_start++; } else if (key_released(KEY_START)) { ctrl.key_start = 0; } +} + // // Direct Memory Access (DMA) // -- cgit v1.2.1