From 0e732d77555583fd73d37613d1349ddb5e190de4 Mon Sep 17 00:00:00 2001 From: qufb <93520295+qufb@users.noreply.github.com> Date: Mon, 27 Jun 2022 22:54:43 +0100 Subject: [PATCH] Add support for Pico Keyboard --- pico/pico.h | 31 +++++ pico/pico/memory.c | 207 ++++++++++++++++++++++++++++++++- platform/common/emu.c | 82 +++++++++---- platform/common/input_pico.h | 97 ++++++++++++++- platform/common/inputmap_kbd.c | 94 +++++++++++++++ platform/common/menu_pico.c | 1 + platform/common/plat_sdl.c | 1 + platform/common/plat_sdl.h | 1 + platform/libpicofe | 2 +- 9 files changed, 490 insertions(+), 26 deletions(-) diff --git a/pico/pico.h b/pico/pico.h index 32522c5c..25cf8776 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -132,6 +132,8 @@ typedef struct PicoInterface void (*mcdTrayOpen)(void); void (*mcdTrayClose)(void); + + unsigned int ps2; // PS/2 peripherals, e.g. Pico Keyboard } PicoInterface; extern PicoInterface PicoIn; @@ -151,6 +153,32 @@ struct PicoEState; // pico.c #define XPCM_BUFFER_SIZE 64 +enum { + KEY_RELEASED = 0, + KEY_DOWN, + KEY_UP, +}; +enum { + SHIFT_RELEASED = 0, + SHIFT_DOWN, + SHIFT_UP_HELD_DOWN, + SHIFT_RELEASED_HELD_DOWN, + SHIFT_UP +}; +typedef struct +{ + uint8_t i; + uint8_t mode; + uint8_t neg; + uint8_t has_read; + uint8_t caps_lock; + uint8_t has_caps_lock; + uint32_t mem; + uint64_t start_time_keydown; + uint64_t time_keydown; + uint8_t key_state; + uint8_t shift_state; +} picohw_kb; typedef struct { int pen_pos[2]; @@ -160,6 +188,9 @@ typedef struct unsigned int reserved[3]; unsigned char xpcm_buffer[XPCM_BUFFER_SIZE+4]; unsigned char *xpcm_ptr; + int is_kb_active; + int inp_mode; + picohw_kb kb; } picohw_state; extern picohw_state PicoPicohw; diff --git a/pico/pico/memory.c b/pico/pico/memory.c index f294b037..c2e09046 100644 --- a/pico/pico/memory.c +++ b/pico/pico/memory.c @@ -8,6 +8,8 @@ */ #include "../pico_int.h" #include "../memory.h" +#include +#include /* void dump(u16 w) @@ -25,6 +27,20 @@ void dump(u16 w) } */ +u64 get_ticks(void) +{ + struct timeval tv; + u64 ret; + + gettimeofday(&tv, NULL); + + ret = (unsigned)tv.tv_sec * 1000; + /* approximate /= 1000 */ + ret += ((unsigned)tv.tv_usec * 4195) >> 22; + + return ret; +} + static u32 PicoRead16_pico(u32 a) { u32 d = 0; @@ -40,7 +56,15 @@ static u32 PicoRead16_pico(u32 a) case 0x06: d = PicoPicohw.pen_pos[0] & 0xff; break; case 0x08: d = (PicoPicohw.pen_pos[1] >> 8); break; case 0x0a: d = PicoPicohw.pen_pos[1] & 0xff; break; - case 0x0c: d = (1 << (PicoPicohw.page & 7)) - 1; break; + case 0x0c: d = (1 << (PicoPicohw.page & 7)) - 1; + if (PicoPicohw.is_kb_active) { + // Apply 1 of 2 bitmasks, depending on which one preserves the highest set bit. + if (PicoPicohw.page % 2 == 0) + d &= 0x2a; // 0b00101010 + else + d &= 0x15; // 0b00010101 + } + break; case 0x10: d = (PicoPicohw.fifo_bytes > 0x3f) ? 0 : (0x3f - PicoPicohw.fifo_bytes); break; case 0x12: d = (PicoPicohw.fifo_bytes | !PicoPicoPCMBusyN()) ? 0 : 0x8000; d |= PicoPicohw.r12 & 0x7fff; @@ -111,6 +135,178 @@ static void PicoWrite16_pico(u32 a, u32 d) elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); } +static u32 PicoRead8_pico_kb(u32 a) +{ + u32 d = 0; + if (PicoPicohw.is_kb_active == 0) { + elprintf(EL_PICOHW, "kb: r @%06X %04X = %04X\n", SekPc, a, d); + return d; + } + + PicoPicohw.kb.has_read = 1; + + u32 key_shift = (PicoIn.ps2 & 0xff00) >> 8; + u32 key = (PicoIn.ps2 & 0x00ff); + + // The Shift key requires 2 key up events to be registered: + // SHIFT_UP_HELD_DOWN to allow the game to register the key down event + // for the next held down key(s), and SHIFT_UP when the Shift key + // is no longer held down. + // + // For the second key up event, we need to + // override the parsed key code with PEVB_PICO_PS2_LSHIFT, + // otherwise it will be zero and the game won't clear its Shift key state. + u32 key_code = (key_shift + && !key + && PicoPicohw.kb.key_state != KEY_UP + && PicoPicohw.kb.shift_state != SHIFT_UP_HELD_DOWN) + ? key_shift + : PicoPicohw.kb.shift_state == SHIFT_UP ? PEVB_PICO_PS2_LSHIFT : key; + u32 key_code_7654 = (key_code & 0xf0) >> 4; + u32 key_code_3210 = (key_code & 0x0f); + switch(PicoPicohw.kb.i) { + case 0x0: d = 1; // m5id + break; + case 0x1: d = 3; // m6id + break; + case 0x2: d = 4; // data size + break; + case 0x3: d = 0; // pad1 rldu + break; + case 0x4: d = 0; // pad2 sacb + break; + case 0x5: d = 0; // pad3 rxyz + break; + case 0x6: d = 0; // l&kbtype + break; + case 0x7: // cap/num/scr + if (PicoPicohw.inp_mode == 3) { + if (key == PEVB_PICO_PS2_CAPSLOCK && PicoPicohw.kb.has_caps_lock == 1) { + PicoPicohw.kb.caps_lock = PicoPicohw.kb.caps_lock == 4 ? 0 : 4; + PicoPicohw.kb.has_caps_lock = 0; + } + d = PicoPicohw.kb.caps_lock; + } + break; + case 0x8: + d = 6; + if (PicoPicohw.inp_mode == 3) { + if (key) { + PicoPicohw.kb.key_state = KEY_DOWN; + } + if (!key) { + PicoPicohw.kb.key_state = !PicoPicohw.kb.key_state ? 0 : (PicoPicohw.kb.key_state + 1) % (KEY_UP + 1); + PicoPicohw.kb.start_time_keydown = 0; + } + if (key_shift && !key) { + if (PicoPicohw.kb.shift_state < SHIFT_RELEASED_HELD_DOWN) { + PicoPicohw.kb.shift_state++; + } + PicoPicohw.kb.start_time_keydown = 0; + } + if (!key_shift) { + PicoPicohw.kb.shift_state = !PicoPicohw.kb.shift_state ? 0 : (PicoPicohw.kb.shift_state + 1) % (SHIFT_UP + 1); + } + + if (PicoPicohw.kb.key_state == KEY_DOWN || PicoPicohw.kb.shift_state == SHIFT_DOWN) { + if (PicoPicohw.kb.start_time_keydown == 0) { + d |= 8; // Send key down a.k.a. make + PicoPicohw.kb.time_keydown = 0; + PicoPicohw.kb.start_time_keydown = get_ticks(); + if (PicoPicohw.kb.key_state == KEY_DOWN) + elprintf(EL_PICOHW, "PicoPicohw.kb.key_state: KEY DOWN\n"); + else + elprintf(EL_PICOHW, "PicoPicohw.kb.key_state: SHIFT DOWN\n"); + } + // Simulate key repeat while held down a.k.a. typematic + PicoPicohw.kb.time_keydown = get_ticks() - PicoPicohw.kb.start_time_keydown; + if (PicoPicohw.kb.time_keydown > 350 + // Modifier keys don't have typematic + && key_code != PEVB_PICO_PS2_CAPSLOCK + && key_code != PEVB_PICO_PS2_LSHIFT) { + d |= 8; // Send key down a.k.a. make + if (PicoPicohw.kb.key_state == KEY_DOWN) + elprintf(EL_PICOHW, "PicoPicohw.kb.key_state: KEY DOWN\n"); + else + elprintf(EL_PICOHW, "PicoPicohw.kb.key_state: SHIFT DOWN\n"); + } + } + if (PicoPicohw.kb.key_state == KEY_UP + || PicoPicohw.kb.shift_state == SHIFT_UP_HELD_DOWN + || PicoPicohw.kb.shift_state == SHIFT_UP) { + d |= 1; // Send key up a.k.a. break + PicoPicohw.kb.start_time_keydown = 0; + if (PicoPicohw.kb.key_state == KEY_UP) + elprintf(EL_PICOHW, "PicoPicohw.kb.key_state: KEY UP\n"); + else + elprintf(EL_PICOHW, "PicoPicohw.kb.key_state: SHIFT UP\n"); + } + } + break; + case 0x9: d = key_code_7654; // data 7654 + break; + case 0xa: d = key_code_3210; // data 3210 + break; + case 0xb: d = 0; // ? + break; + case 0xc: d = 0; // ? + break; + default: + d = 0; + break; + } + + if (PicoPicohw.kb.neg) { + d |= 0xfffffff0; + } + + elprintf(EL_PICOHW, "kb: r @%06X %04X = %04X\n", SekPc, a, d); + return d; +} + +static u32 PicoRead16_pico_kb(u32 a) +{ + u32 d = PicoPicohw.kb.mem; + + elprintf(EL_PICOHW, "kb: r16 @%06X %04X = %04X\n", SekPc, a, d); + return d; +} + +static void PicoWrite8_pico_kb(u32 a, u32 d) +{ + elprintf(EL_PICOHW, "kb: w @%06X %04X = %04X\n", SekPc, a, d); + + switch(d) { + case 0x0: + PicoPicohw.kb.neg = 0; + PicoPicohw.kb.i++; + break; + case 0x20: + PicoPicohw.kb.neg = 1; + if (PicoPicohw.kb.has_read == 1) { + PicoPicohw.kb.i++; + } + break; + case 0x40: + break; + case 0x60: + PicoPicohw.kb.mode = !PicoPicohw.kb.mode; + PicoPicohw.kb.i = 0; + PicoPicohw.kb.has_read = 0; + break; + default: + break; + } + + PicoPicohw.kb.mem = (PicoPicohw.kb.mem & 0xff00) | d; +} + +static void PicoWrite16_pico_kb(u32 a, u32 d) +{ + elprintf(EL_PICOHW, "kb: w16 @%06X %04X = %04X\n", SekPc, a, d); + + PicoPicohw.kb.mem = d; +} PICO_INTERNAL void PicoMemSetupPico(void) { @@ -124,5 +320,12 @@ PICO_INTERNAL void PicoMemSetupPico(void) cpu68k_map_set(m68k_read16_map, 0x800000, 0x80ffff, PicoRead16_pico, 1); cpu68k_map_set(m68k_write8_map, 0x800000, 0x80ffff, PicoWrite8_pico, 1); cpu68k_map_set(m68k_write16_map, 0x800000, 0x80ffff, PicoWrite16_pico, 1); -} + m68k_map_unmap(0x200000, 0x20ffff); + + // map Pico PS/2 Peripheral I/O + cpu68k_map_set(m68k_read8_map, 0x200000, 0x20ffff, PicoRead8_pico_kb, 1); + cpu68k_map_set(m68k_read16_map, 0x200000, 0x20ffff, PicoRead16_pico_kb, 1); + cpu68k_map_set(m68k_write8_map, 0x200000, 0x20ffff, PicoWrite8_pico_kb, 1); + cpu68k_map_set(m68k_write16_map, 0x200000, 0x20ffff, PicoWrite16_pico_kb, 1); +} diff --git a/platform/common/emu.c b/platform/common/emu.c index e2b540b2..9ca71a20 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1142,6 +1142,9 @@ void run_events_pico(unsigned int events) } if (events & PEV_PICO_PAD) { if (pico_inp_mode == 2) { + pico_inp_mode = (PicoPicohw.is_kb_active ? 3 : 0); + emu_status_msg("Input: %s", pico_inp_mode ? "Keyboard" : "D-Pad"); + } else if (pico_inp_mode == 3) { pico_inp_mode = 0; emu_status_msg("Input: D-Pad"); } else { @@ -1160,7 +1163,15 @@ void run_events_pico(unsigned int events) pico_inp_mode = 0; emu_status_msg("Input: D-Pad"); } - if (pico_inp_mode == 0) + if (events & PEV_PICO_SWPS2) { + PicoPicohw.is_kb_active = !PicoPicohw.is_kb_active; + if (pico_inp_mode == 3) pico_inp_mode = 0; + emu_status_msg("Keyboard %sconnected", PicoPicohw.is_kb_active ? "" : "dis"); + } + + PicoPicohw.inp_mode = pico_inp_mode; + + if (pico_inp_mode == 0 || pico_inp_mode == 3) return; /* handle other input modes */ @@ -1282,42 +1293,71 @@ void emu_update_input(void) { static int prev_events = 0; int actions[IN_BINDTYPE_COUNT] = { 0, }; + int actions_pico_ps2[IN_BIND_LAST] = { 0, }; int pl_actions[4]; int events; in_update(actions); + in_update_pico_ps2(actions_pico_ps2); + PicoIn.ps2 = 0; + for (int i = 0; i < IN_BIND_LAST; i++) { + if (actions_pico_ps2[i]) { + unsigned int action = actions_pico_ps2[i]; + if ((action & 0xff) == PEVB_PICO_PS2_LSHIFT) { + PicoIn.ps2 = (PicoIn.ps2 & 0x00ff) | (action << 8); + } else { + PicoIn.ps2 = (PicoIn.ps2 & 0xff00) | action; + } + } + } pl_actions[0] = actions[IN_BINDTYPE_PLAYER12]; pl_actions[1] = actions[IN_BINDTYPE_PLAYER12] >> 16; pl_actions[2] = actions[IN_BINDTYPE_PLAYER34]; pl_actions[3] = actions[IN_BINDTYPE_PLAYER34] >> 16; - PicoIn.pad[0] = pl_actions[0] & 0xfff; - PicoIn.pad[1] = pl_actions[1] & 0xfff; - PicoIn.pad[2] = pl_actions[2] & 0xfff; - PicoIn.pad[3] = pl_actions[3] & 0xfff; - - if (pl_actions[0] & 0x7000) - do_turbo(&PicoIn.pad[0], pl_actions[0]); - if (pl_actions[1] & 0x7000) - do_turbo(&PicoIn.pad[1], pl_actions[1]); - if (pl_actions[2] & 0x7000) - do_turbo(&PicoIn.pad[2], pl_actions[2]); - if (pl_actions[3] & 0x7000) - do_turbo(&PicoIn.pad[3], pl_actions[3]); - events = actions[IN_BINDTYPE_EMU] & PEV_MASK; + if (pico_inp_mode == 3) { + // FIXME: Only passthrough joystick input to avoid collisions + // with PS/2 bindings. Ideally we should check if the device this + // input originated from is the same as the device used for + // PS/2 input, and passthrough if they are different devices. + PicoIn.pad[0] = pl_actions[0] & 0xf; + PicoIn.pad[1] = pl_actions[1] & 0xf; + PicoIn.pad[2] = pl_actions[2] & 0xf; + PicoIn.pad[3] = pl_actions[3] & 0xf; + + // Ignore events mapped to bindings that collide with PS/2 peripherals. + // Note that calls to emu_set_fastforward() should be avoided as well, + // since fast-forward activates even with parameter set_on = 0. + events &= ~PEV_MENU; + } else { + PicoIn.pad[0] = pl_actions[0] & 0xfff; + PicoIn.pad[1] = pl_actions[1] & 0xfff; + PicoIn.pad[2] = pl_actions[2] & 0xfff; + PicoIn.pad[3] = pl_actions[3] & 0xfff; + + if (pl_actions[0] & 0x7000) + do_turbo(&PicoIn.pad[0], pl_actions[0]); + if (pl_actions[1] & 0x7000) + do_turbo(&PicoIn.pad[1], pl_actions[1]); + if (pl_actions[2] & 0x7000) + do_turbo(&PicoIn.pad[2], pl_actions[2]); + if (pl_actions[3] & 0x7000) + do_turbo(&PicoIn.pad[3], pl_actions[3]); + + if ((events ^ prev_events) & PEV_FF) { + emu_set_fastforward(events & PEV_FF); + plat_update_volume(0, 0); + reset_timing = 1; + } + } + // volume is treated in special way and triggered every frame if (events & (PEV_VOL_DOWN|PEV_VOL_UP)) plat_update_volume(1, events & PEV_VOL_UP); - if ((events ^ prev_events) & PEV_FF) { - emu_set_fastforward(events & PEV_FF); - plat_update_volume(0, 0); - reset_timing = 1; - } - events &= ~prev_events; if (PicoIn.AHW == PAHW_PICO) diff --git a/platform/common/input_pico.h b/platform/common/input_pico.h index 2f3de418..47d9554d 100644 --- a/platform/common/input_pico.h +++ b/platform/common/input_pico.h @@ -30,7 +30,8 @@ #define PEVB_PICO_STORY 19 #define PEVB_PICO_PAD 18 #define PEVB_PICO_PENST 17 -#define PEVB_RESET 16 +#define PEVB_PICO_SWPS2 16 +#define PEVB_RESET 15 #define PEV_VOL_DOWN (1 << PEVB_VOL_DOWN) #define PEV_VOL_UP (1 << PEVB_VOL_UP) @@ -46,8 +47,100 @@ #define PEV_PICO_STORY (1 << PEVB_PICO_STORY) #define PEV_PICO_PAD (1 << PEVB_PICO_PAD) #define PEV_PICO_PENST (1 << PEVB_PICO_PENST) +#define PEV_PICO_SWPS2 (1 << PEVB_PICO_SWPS2) #define PEV_RESET (1 << PEVB_RESET) -#define PEV_MASK 0x7fff0000 +#define PEV_MASK 0x7fff8000 + +/* Keyboard Pico */ + +// Blue buttons +#define PEVB_PICO_PS2_SPACE 0x29 +#define PEVB_PICO_PS2_EXCLAIM 0 +#define PEVB_PICO_PS2_QUOTEDBL 0 +#define PEVB_PICO_PS2_HASH 0 +#define PEVB_PICO_PS2_DOLLAR 0 +#define PEVB_PICO_PS2_AMPERSAND 0 +#define PEVB_PICO_PS2_LEFTPAREN 0 +#define PEVB_PICO_PS2_RIGHTPAREN 0 +#define PEVB_PICO_PS2_ASTERISK 0x7c +#define PEVB_PICO_PS2_PLUS 0x79 +#define PEVB_PICO_PS2_MINUS 0x4e +#define PEVB_PICO_PS2_COMMA 0x41 +#define PEVB_PICO_PS2_PERIOD 0x49 +#define PEVB_PICO_PS2_SLASH 0x4a +#define PEVB_PICO_PS2_1 0x16 +#define PEVB_PICO_PS2_2 0x1e +#define PEVB_PICO_PS2_3 0x26 +#define PEVB_PICO_PS2_4 0x25 +#define PEVB_PICO_PS2_5 0x2e +#define PEVB_PICO_PS2_6 0x36 +#define PEVB_PICO_PS2_7 0x3d +#define PEVB_PICO_PS2_8 0x3e +#define PEVB_PICO_PS2_9 0x46 +#define PEVB_PICO_PS2_0 0x45 +#define PEVB_PICO_PS2_COLON 0x52 +#define PEVB_PICO_PS2_SEMICOLON 0x4c +#define PEVB_PICO_PS2_LESS 0 +#define PEVB_PICO_PS2_EQUALS 0x55 +#define PEVB_PICO_PS2_GREATER 0 +#define PEVB_PICO_PS2_QUESTION 0 +#define PEVB_PICO_PS2_AT 0 +#define PEVB_PICO_PS2_DAKUTEN 0x54 // ゛ +#define PEVB_PICO_PS2_LEFTBRACKET 0x5b +#define PEVB_PICO_PS2_RIGHTBRACKET 0x5d +#define PEVB_PICO_PS2_CARET 0 +#define PEVB_PICO_PS2_UNDERSCORE 0 +#define PEVB_PICO_PS2_YEN 0x6a // ¥ +#define PEVB_PICO_PS2_RO 0x51 // ろ +#define PEVB_PICO_PS2_KE 0x52 // け + +#define PEVB_PICO_PS2_a 0x1c +#define PEVB_PICO_PS2_b 0x32 +#define PEVB_PICO_PS2_c 0x21 +#define PEVB_PICO_PS2_d 0x23 +#define PEVB_PICO_PS2_e 0x24 +#define PEVB_PICO_PS2_f 0x2b +#define PEVB_PICO_PS2_g 0x34 +#define PEVB_PICO_PS2_h 0x33 +#define PEVB_PICO_PS2_i 0x43 +#define PEVB_PICO_PS2_j 0x3b +#define PEVB_PICO_PS2_k 0x42 +#define PEVB_PICO_PS2_l 0x4b +#define PEVB_PICO_PS2_m 0x3a +#define PEVB_PICO_PS2_n 0x31 +#define PEVB_PICO_PS2_o 0x44 +#define PEVB_PICO_PS2_p 0x4d +#define PEVB_PICO_PS2_q 0x15 +#define PEVB_PICO_PS2_r 0x2d +#define PEVB_PICO_PS2_s 0x1b +#define PEVB_PICO_PS2_t 0x2c +#define PEVB_PICO_PS2_u 0x3c +#define PEVB_PICO_PS2_v 0x2a +#define PEVB_PICO_PS2_w 0x1d +#define PEVB_PICO_PS2_x 0x22 +#define PEVB_PICO_PS2_y 0x35 +#define PEVB_PICO_PS2_z 0x1a + +// Green button on top-left +#define PEVB_PICO_PS2_ESCAPE 0x76 + +// Orange buttons on left +#define PEVB_PICO_PS2_CAPSLOCK 0x58 +#define PEVB_PICO_PS2_LSHIFT 0x12 + +// Green buttons on right +#define PEVB_PICO_PS2_BACKSPACE 0x66 +#define PEVB_PICO_PS2_INSERT 0x81 +#define PEVB_PICO_PS2_DELETE 0x85 + +// Red button on bottom-right +#define PEVB_PICO_PS2_RETURN 0x5a + +// Orange buttons on bottom +#define PEVB_PICO_PS2_SOUND 0x67 +#define PEVB_PICO_PS2_HOME 0x64 +#define PEVB_PICO_PS2_CJK 0x13 +#define PEVB_PICO_PS2_ROMAJI 0x17 #endif /* INCLUDE_c48097f3ff2a6a9af1cce8fd7a9b3f0c */ diff --git a/platform/common/inputmap_kbd.c b/platform/common/inputmap_kbd.c index 8fbb29f8..022638d5 100644 --- a/platform/common/inputmap_kbd.c +++ b/platform/common/inputmap_kbd.c @@ -32,7 +32,101 @@ const struct in_default_bind _in_sdl_defbinds[] = { { SDLK_F8, IN_BINDTYPE_EMU, PEVB_PICO_STORY }, { SDLK_F9, IN_BINDTYPE_EMU, PEVB_PICO_PAD }, { SDLK_F10, IN_BINDTYPE_EMU, PEVB_PICO_PENST }, + { SDLK_F12, IN_BINDTYPE_EMU, PEVB_PICO_SWPS2 }, { SDLK_BACKSPACE, IN_BINDTYPE_EMU, PEVB_FF }, + + { 0, 0, 0 } +}; + +const struct in_default_bind in_sdl_pico_ps2_map[] = { + // Blue buttons + { SDLK_SPACE, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_SPACE }, + { SDLK_EXCLAIM, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_EXCLAIM }, + { SDLK_QUOTEDBL, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_QUOTEDBL }, + { SDLK_HASH, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_HASH }, + { SDLK_DOLLAR, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_DOLLAR }, + { SDLK_AMPERSAND, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_AMPERSAND }, + { SDLK_LEFTPAREN, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_LEFTPAREN }, + { SDLK_RIGHTPAREN, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_RIGHTPAREN }, + { SDLK_ASTERISK, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_ASTERISK }, + { SDLK_PLUS, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_PLUS }, + { SDLK_COMMA, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_COMMA }, + { SDLK_MINUS, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_MINUS }, + { SDLK_PERIOD, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_PERIOD }, + { SDLK_SLASH, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_SLASH }, + { SDLK_0, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_0 }, + { SDLK_1, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_1 }, + { SDLK_2, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_2 }, + { SDLK_3, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_3 }, + { SDLK_4, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_4 }, + { SDLK_5, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_5 }, + { SDLK_6, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_6 }, + { SDLK_7, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_7 }, + { SDLK_8, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_8 }, + { SDLK_9, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_9 }, + { SDLK_COLON, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_COLON }, + { SDLK_SEMICOLON, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_SEMICOLON }, + { SDLK_LESS, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_LESS }, + { SDLK_EQUALS, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_EQUALS }, + { SDLK_GREATER, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_GREATER }, + { SDLK_QUESTION, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_QUESTION }, + { SDLK_AT, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_AT }, + { SDLK_BACKSLASH, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_DAKUTEN }, + { SDLK_LEFTBRACKET, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_LEFTBRACKET }, + { SDLK_RIGHTBRACKET, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_RIGHTBRACKET }, + { SDLK_CARET, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_CARET }, + { SDLK_UNDERSCORE, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_UNDERSCORE }, + { SDLK_BACKQUOTE, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_YEN }, + { SDLK_a, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_a }, + { SDLK_b, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_b }, + { SDLK_c, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_c }, + { SDLK_d, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_d }, + { SDLK_e, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_e }, + { SDLK_f, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_f }, + { SDLK_g, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_g }, + { SDLK_h, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_h }, + { SDLK_i, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_i }, + { SDLK_j, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_j }, + { SDLK_k, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_k }, + { SDLK_l, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_l }, + { SDLK_m, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_m }, + { SDLK_n, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_n }, + { SDLK_o, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_o }, + { SDLK_p, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_p }, + { SDLK_q, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_q }, + { SDLK_r, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_r }, + { SDLK_s, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_s }, + { SDLK_t, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_t }, + { SDLK_u, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_u }, + { SDLK_v, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_v }, + { SDLK_w, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_w }, + { SDLK_x, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_x }, + { SDLK_y, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_y }, + { SDLK_z, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_z }, + { SDLK_QUOTE, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_KE }, + { SDLK_RSHIFT, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_RO }, + + // Green button on top-left + { SDLK_ESCAPE, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_ESCAPE }, + + // Orange buttons on left + { SDLK_LCTRL, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_CAPSLOCK }, // Also switches english input + { SDLK_LSHIFT, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_LSHIFT }, + + // Green buttons on right + { SDLK_BACKSPACE, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_BACKSPACE }, + { SDLK_INSERT, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_INSERT }, + { SDLK_DELETE, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_DELETE }, + + // Red button on bottom-right + { SDLK_RETURN, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_RETURN }, + + // Orange buttons on bottom + { SDLK_END, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_SOUND }, + { SDLK_HOME, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_HOME }, + { SDLK_PAGEUP, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_CJK }, // CJK Scripts: Hiragana / Katakana / Kanji (Keyboard Pico); Hangul (Kibodeu Piko) + { SDLK_PAGEDOWN, IN_BINDTYPE_PICO_PS2, PEVB_PICO_PS2_ROMAJI }, // English Script + { 0, 0, 0 } }; const struct in_default_bind *in_sdl_defbinds = _in_sdl_defbinds; diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 70e18b45..78342c09 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -375,6 +375,7 @@ me_bind_action emuctrl_actions[] = { "Pico Storyware ", PEV_PICO_STORY }, { "Pico Pad ", PEV_PICO_PAD }, { "Pico Pen state ", PEV_PICO_PENST }, + { "Pico Keyboard ", PEV_PICO_SWPS2 }, { NULL, 0 } }; diff --git a/platform/common/plat_sdl.c b/platform/common/plat_sdl.c index 8ba3a8c9..7a9d6b92 100644 --- a/platform/common/plat_sdl.c +++ b/platform/common/plat_sdl.c @@ -511,6 +511,7 @@ void plat_init(void) in_sdl_platform_data.jmap_size = in_sdl_joy_map_sz, in_sdl_platform_data.joy_map = in_sdl_joy_map, in_sdl_platform_data.key_names = in_sdl_key_names, + in_sdl_platform_data.pico_ps2_map = in_sdl_pico_ps2_map, in_sdl_init(&in_sdl_platform_data, plat_sdl_event_handler); in_probe(); diff --git a/platform/common/plat_sdl.h b/platform/common/plat_sdl.h index cecdb2b3..13f7d0c4 100644 --- a/platform/common/plat_sdl.h +++ b/platform/common/plat_sdl.h @@ -6,5 +6,6 @@ extern const struct menu_keymap *in_sdl_joy_map; extern const int in_sdl_joy_map_sz; extern const char * const *in_sdl_key_names; extern const char *plat_device; +extern const struct in_default_bind in_sdl_pico_ps2_map[]; void linux_menu_init(void); diff --git a/platform/libpicofe b/platform/libpicofe index 86a086ed..b047d2e2 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit 86a086ed64aadc1e87fc58a90703a07d91c9cdbe +Subproject commit b047d2e2e6375b5fad2f1b716616a536f7b56dc2 -- 2.39.5