diff --git a/src/api.c b/src/api.c index f1e8245..f989301 100644 --- a/src/api.c +++ b/src/api.c @@ -39,7 +39,8 @@ uint32_t pico8_frame_start = 0; uint32_t pico8_frame_ms = 0; // Touch button state (when SDL_HINT_MOUSE_TOUCH_EVENTS is used). -uint8_t touch_button_state = 0; +uint8_t touch_button_state_player_0 = 0; +uint8_t touch_button_state_player_1 = 0; // Input state: tracks how many consecutive frames each button has been held. // Index [player][button], players 0-1, buttons 0-5. @@ -1501,7 +1502,7 @@ static int pico8_btn(lua_State* L) if (argc == 0) { - lua_pushunsigned(L, fix32_value(pico8_ram[0x5f4c], 0)); + lua_pushunsigned(L, fix32_value(pico8_ram[0x5f4c] | (pico8_ram[0x5f4d] << 8), 0)); return 1; } @@ -1542,13 +1543,16 @@ static int pico8_btnp(lua_State* L) if (argc == 0) { - uint8_t result = 0; - for (int b = 0; b < 6; b++) + uint16_t result = 0; + for (int p = 0; p < 2; p++) { - uint8_t f = btn_held_frames[0][b]; - if (f == 1 || (f > 15 && ((f - 15) % 4 == 0))) + for (int b = 0; b < 6; b++) { - result |= (1 << b); + uint8_t f = btn_held_frames[p][b]; + if (f == 1 || (f > 15 && ((f - 15) % 4 == 0))) + { + result |= (1 << (b + p * 8)); + } } } lua_pushunsigned(L, fix32_value(result, 0)); @@ -2727,16 +2731,48 @@ void update_input(SDL_Renderer* renderer) state |= (1 << 5); } #else - if (keys[SDL_SCANCODE_Z] || keys[SDL_SCANCODE_Y] || keys[SDL_SCANCODE_C]) + if (keys[SDL_SCANCODE_Z] || keys[SDL_SCANCODE_Y] || keys[SDL_SCANCODE_C] || + keys[SDL_SCANCODE_N] || keys[SDL_SCANCODE_KP_MULTIPLY]) { state |= (1 << 4); } - if (keys[SDL_SCANCODE_X] || keys[SDL_SCANCODE_V]) + if (keys[SDL_SCANCODE_X] || keys[SDL_SCANCODE_V] || keys[SDL_SCANCODE_M] || + keys[SDL_SCANCODE_8]) { state |= (1 << 5); } #endif } + else + { + int num_keys = 0; + const bool* keys = SDL_GetKeyboardState(&num_keys); + + if (keys[SDL_SCANCODE_S]) + { + state |= (1 << 0); + } + if (keys[SDL_SCANCODE_F]) + { + state |= (1 << 1); + } + if (keys[SDL_SCANCODE_E]) + { + state |= (1 << 2); + } + if (keys[SDL_SCANCODE_D]) + { + state |= (1 << 3); + } + if (keys[SDL_SCANCODE_LSHIFT] || keys[SDL_SCANCODE_TAB]) + { + state |= (1 << 4); + } + if (keys[SDL_SCANCODE_A] || keys[SDL_SCANCODE_Q]) + { + state |= (1 << 5); + } + } // Gamepad input: first connected gamepad -> player 0, second -> player 1. SDL_Gamepad* gp = SDL_GetGamepadFromPlayerIndex(p); @@ -2768,11 +2804,14 @@ void update_input(SDL_Renderer* renderer) } } - // Touch button state (when SDL_HINT_MOUSE_TOUCH_EVENTS is used) - // Only applied to player 0. + // Touch button state (when SDL_HINT_MOUSE_TOUCH_EVENTS is used). if (p == 0) { - state |= touch_button_state; + state |= touch_button_state_player_0; + } + else + { + state |= touch_button_state_player_1; } pico8_ram[0x5f4c + p] = state; diff --git a/src/core.c b/src/core.c index 66388e7..53ad8cb 100644 --- a/src/core.c +++ b/src/core.c @@ -128,7 +128,7 @@ static void update_touch_input(SDL_Renderer* renderer) } // Reset button state and accumulate from all active fingers. - touch_button_state = 0; + touch_button_state_player_0 = 0; // Get touch regions for button detection. int touch_count = 0; @@ -165,7 +165,7 @@ static void update_touch_input(SDL_Renderer* renderer) { if (point_in_touch_region(region_x, region_y, ®ions[r])) { - touch_button_state |= (1 << regions[r].bit); + touch_button_state_player_0 |= (1 << regions[r].bit); } } } @@ -1182,7 +1182,7 @@ bool handle_events(SDL_Renderer* renderer, SDL_Event* event) { if (point_in_touch_region(region_x, region_y, ®ions[i])) { - touch_button_state |= (1 << regions[i].bit); + touch_button_state_player_0 |= (1 << regions[i].bit); uint8_t bit = regions[i].bit; if (bit == 99) @@ -1236,7 +1236,7 @@ bool handle_events(SDL_Renderer* renderer, SDL_Event* event) { if (point_in_touch_region(region_x, region_y, ®ions[i])) { - touch_button_state &= ~(1 << regions[i].bit); + touch_button_state_player_0 &= ~(1 << regions[i].bit); } } } @@ -1335,7 +1335,7 @@ bool handle_events(SDL_Renderer* renderer, SDL_Event* event) { if (point_in_touch_region(region_x, region_y, ®ions[i])) { - touch_button_state |= (1 << regions[i].bit); + touch_button_state_player_0 |= (1 << regions[i].bit); uint8_t bit = regions[i].bit; if (bit == 99) @@ -1355,7 +1355,7 @@ bool handle_events(SDL_Renderer* renderer, SDL_Event* event) // Clear touch button state when touch is released. if (event->button.button == SDL_BUTTON_LEFT && state == STATE_EMULATOR) { - touch_button_state = 0; + touch_button_state_player_0 = 0; } break; } diff --git a/src/core.h b/src/core.h index 5019749..5fd8729 100644 --- a/src/core.h +++ b/src/core.h @@ -27,8 +27,9 @@ typedef enum state } state_t; -// Touch button state (when SDL_HINT_MOUSE_TOUCH_EVENTS is used) -extern uint8_t touch_button_state; +// Touch button state (when SDL_HINT_MOUSE_TOUCH_EVENTS is used). +extern uint8_t touch_button_state_player_0; +extern uint8_t touch_button_state_player_1; void handle_resize(SDL_Renderer* renderer); diff --git a/tests/tests.lua b/tests/tests.lua index a4e331d..c008be7 100644 --- a/tests/tests.lua +++ b/tests/tests.lua @@ -1306,6 +1306,7 @@ end function test_btn() -- No buttons pressed: btn() bitfield == 0. poke(0x5f4c, 0x00) + poke(0x5f4d, 0x00) assert_equal(btn(), 0, "btn() no buttons") -- Single button: btn(b) returns true when bit b is set. @@ -1334,6 +1335,11 @@ function test_btn() assert_true(btn(0, 1) == true, "btn(0,1) p1 pressed") assert_true(btn(0, 0) == false, "btn(0,0) p0 not pressed") + -- No-argument btn() includes player 1 in bits 8-13. + poke(0x5f4c, 0x3f) + poke(0x5f4d, 0x3f) + assert_equal(btn(), 0x3f3f, "btn() both players") + -- Clean up. poke(0x5f4c, 0x00) poke(0x5f4d, 0x00) @@ -1379,11 +1385,19 @@ function test_btnp() assert_true(btnp(6) == false, "btnp(6) out of range") assert_true(btnp(-1) == false, "btnp(-1) out of range") + for b = 0, 5 do + set_btnp_frames(b, 0) + end + -- Player 1: set frame count for p1 button 3. set_btnp_frames(3, 1, 1) assert_true(btnp(3, 1) == true, "btnp(3,1) p1 first press") assert_true(btnp(3, 0) == false, "btnp(3,0) p0 not pressed") + -- No-argument btnp() includes player 1 in bits 8-13. + set_btnp_frames(3, 19, 1) + assert_equal(btnp(), 0x0800, "btnp() p1 mask") + -- Clean up. for b = 0, 5 do set_btnp_frames(b, 0)