From 22fed0fea18af5ce3b58f8c0f448851017293639 Mon Sep 17 00:00:00 2001 From: condret Date: Fri, 18 Oct 2024 05:09:58 +0200 Subject: [PATCH] Joypad support --- include/gb.h | 14 ++++++++-- io/joypad.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 82 insertions(+), 6 deletions(-) diff --git a/include/gb.h b/include/gb.h index 39922d1..0e63cc4 100644 --- a/include/gb.h +++ b/include/gb.h @@ -21,17 +21,27 @@ typedef struct gb_timers_t { } GBTimers; GBTimers *gb_timers_open(RIO *io); -void gb_timers_close(RIO *io, GBTimers *timers); void gb_timers_update(GBTimers *timers, ut32 cycles); +void gb_timers_close(RIO *io, GBTimers *timers); typedef struct gb_joypad_t { ut8 *keys; int fd; + ut16 up; + ut16 down; + ut16 left; + ut16 right; + ut16 a; + ut16 b; + ut16 start; + ut16 select; ut8 data; ut8 odata; } GBJoypad; -GBJoypad *gb_joypad_open(RIO *io) +GBJoypad *gb_joypad_open(RIO *io); +void gb_joypad_update(GBJoypad *joypad); +void gb_joypad_close(RIO *io, GBJoypad *joypad); //int gb_mbc1_open(RIO *io, char *path); diff --git a/io/joypad.c b/io/joypad.c index e4c3c95..477df13 100644 --- a/io/joypad.c +++ b/io/joypad.c @@ -19,22 +19,41 @@ static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { return desc; } +static ut64 __lseek(RIO* io, RIODesc *desc, ut64 offset, int whence) { + GBJoypad *joypad = (GBTimers *)desc->data; + ut64 seek = (joypad->odata & 0x40) >> 6; + switch (whence) { + case R_IO_SEEK_SET: + seek = R_MIN (1, offset); + break; + case R_IO_SEEK_CUR: + seek = R_MIN (1, seek + offset); + break; + case R_IO_SEEK_END: + seek = 1; + break; + } + joypad->odata = (joypad->odata & 0x3f) | + return seek; +} + static int __read(RIO *io, RIODesc *desc, ut8 *buf, int len) { GBJoypad *joypad = (GBJoypad *)desc->data; - if (!len || (joypad->odata & 0x10)) { + if (!len || (joypad->odata & 0x40)) { return 0; } joypad->data = buf[0] & 0xf; - joypad->odata |= 0x10; + joypad->odata |= 0x40; return 1; } static int __write(RIO *io, RIODesc *desc, const ut8 *buf, int len) { GBJoypad *joypad = (GBJoypad *)desc->data; - if (!len || (joypad->odata & 0x10)) { + if (!len || (joypad->odata & 0x40)) { return 0; } - joypad->odata |= 0x10; + joypad->odata |= 0x40; + joypad->data = (buf[0] & 0x30) | (joypad->data & 0xf); return 1; } @@ -73,5 +92,52 @@ GBJoypad *gb_joypad_open (RIO *io) { } joypad->fd = desc->fd; joypad->keys = SDL_GetKeyboardState (NULL); + joypad->up = SDL_SCANCODE_W; + joypad->down = SDL_SCANCODE_S; + joypad->left = SDL_SCANCODE_A; + joypad->right = SDL_SCANCODE_D; + joypad->a = SDL_SCANCODE_L; + joypad->b = SDL_SCANCODE_K; + joypad->start = SDL_SCANCODE_SPACE; + joypad->select = SDL_SCANCODE_KP_ENTER; return joypad; } + +void gb_joypad_update(GBJoypad *joypad) { + joypad->odata &= 0xc0; + joypad->odata |= joypad->data & 0x3f; + SDL_PumpEvents (); + ut8 ndata = 0; + if (!(joypad->data & 0x8)) { //d-pad + const ut8 data = (~joypad->data) & 0xf; + ndata = !!joypad->keys[joypad->right]; + ndata |= (!!joypad->keys[joypad->left]) << 1; + ndata |= (!!joypad->keys[joypad->up]) << 2; + ndata |= (!!joypad->keys[joypad->down]) << 3; + // on a real gameboy you cannot press up and down, or left and right at the same time + if ((ndata & 0x3) == 0x3) { + ndata = (ndata & 0xc) | (data & 0x3); + } + if ((ndata & 0xc) == 0xc) { + ndata = (ndata & 0x3) | (data & 0xc); + } + } + if (!(joypad->data & 0x10)) { + ndata |= !!joypad->keys[joypad->a]; + ndata |= (!!joypad->keys[joypad->b]) << 1; + ndata |= (!!joypad->keys[joypad->select]) << 2; + ndata |= (!!joypad->keys[joypad->start]) << 3; + } + joypad->data = (joypad->data & 0x30) | (ndata ^ 0xf); + if (joypad->odata & ndata) { + //TODO: request interrupt + } +} + +void gb_joypad_close (RIO *io, GBJoypad *joypad) { + if (!io || !joypad) { + return; + } + r_io_fd_close (io, joypad->fd); + free (joypad); +}