From 02463089661ed583364982723b80be8ec497483e Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Sun, 26 Jun 2022 19:19:33 +1000 Subject: [PATCH] In /emu_65c02 implement SDL2 joystick and Apple game port emulation --- emu_65c02/emu_65c02.c | 127 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 121 insertions(+), 6 deletions(-) diff --git a/emu_65c02/emu_65c02.c b/emu_65c02/emu_65c02.c index 0f8a1ff..707a1e9 100644 --- a/emu_65c02/emu_65c02.c +++ b/emu_65c02/emu_65c02.c @@ -81,10 +81,14 @@ #define HW_CLRAN2 0xc05d // RW annunciator 2 on #define HW_SETAN3 0xc05e // RW annunciator 2 off #define HW_CLRAN3 0xc05f // RW annunciator 3 on +#define HW_TAPEIN 0xc060 // R #define HW_PB0 0xc061 // R switch input 0 / open-apple (orig: BUTN0) #define HW_PB1 0xc062 // R switch input 1 / closed-apple (orig: BUTN1) -#define HW_PADDL0 0xc064 -#define HW_PADDL1 0xc065 +#define HW_PB2 0xc063 // R +#define HW_PADDL0 0xc064 // R +#define HW_PADDL1 0xc065 // R +#define HW_PADDL2 0xc066 // R +#define HW_PADDL3 0xc067 // R #define HW_PTRIG 0xc070 #define HW_LC_BANK2_RAM_WP 0xc080 // RW #define HW_LC_BANK2_ROM_WE 0xc081 // RWx2 @@ -234,6 +238,26 @@ uint8_t c0x0_soft_switches_buf[C0X0_SOFT_SWITCHES_BUF_SIZE]; #define C05X_SOFT_SWITCH_NOTAN3 0x80 uint8_t c05x_soft_switches = C05X_SOFT_SWITCH_TEXT; +#define C06X_INPUT_TAPEIN 1 +#define C06X_INPUT_PB0 2 +#define C06X_INPUT_PB1 4 +#define C06X_INPUT_PB2 8 +#define C06X_INPUT_PADDL0 0x10 +#define C06X_INPUT_PADDL1 0x20 +#define C06X_INPUT_PADDL2 0x40 +#define C06X_INPUT_PADDL3 0x80 +#define C06X_INPUT_PADDLX 0xf0 +uint8_t c06x_inputs; + +#define JOYSTICK_COUNT 0x900 // 9 cycles per loop of ROM_PREAD +int joystick_count = JOYSTICK_COUNT; +int joystick_axes[4] = { + JOYSTICK_COUNT, + JOYSTICK_COUNT, + JOYSTICK_COUNT, + JOYSTICK_COUNT +}; + #define LC_BANK 4 #define LC_BANK2 0 #define LC_BANK1 4 @@ -516,6 +540,19 @@ void dos(char *line) { } uint8_t mem_read(uint16_t addr0, bool isDbg) { + // for joystick, for now count memory accesses as proxy for cycles + if (joystick_count < JOYSTICK_COUNT) { + ++joystick_count; + if (joystick_axes[0] < joystick_count) + c06x_inputs &= ~C06X_INPUT_PADDL0; + if (joystick_axes[1] < joystick_count) + c06x_inputs &= ~C06X_INPUT_PADDL1; + if (joystick_axes[2] < joystick_count) + c06x_inputs &= ~C06X_INPUT_PADDL2; + if (joystick_axes[3] < joystick_count) + c06x_inputs &= ~C06X_INPUT_PADDL3; + } + int addr = addr0; if ((addr & 0xff00) != IO_PAGE) { #if APPLE_IIE @@ -829,9 +866,19 @@ uint8_t mem_read(uint16_t addr0, bool isDbg) { case HW_CLRAN3 : // 0xc05f c05x_soft_switches |= 1 << ((addr >> 1) & 7); break; - case HW_PB0: - case HW_PB1: - return 0; // needed for proper boot with IIe ROM + case HW_TAPEIN: // 0xc060 + case HW_PB0: // 0xc061 + case HW_PB1: // 0xc062 + case HW_PB2: // 0xc063 + case HW_PADDL0: // 0xc064 + case HW_PADDL1: // 0xc065 + case HW_PADDL2: // 0xc066 + case HW_PADDL3: // 0xc067 + return ((c06x_inputs & (1 << (addr & 7))) != 0) << 7; + case HW_PTRIG: + joystick_count = 0; + c06x_inputs |= C06X_INPUT_PADDLX; + break; case HW_LC_BANK2_RAM_WP: // 0xc080 case HW_LC_BANK2_ROM_WE: // 0xc081 case HW_LC_BANK2_ROM_WP: // 0xc082 @@ -892,6 +939,19 @@ uint8_t mem_read(uint16_t addr0, bool isDbg) { } void mem_write(uint16_t addr0, uint8_t val) { + // for joystick, for now count memory accesses as proxy for cycles + if (joystick_count < JOYSTICK_COUNT) { + ++joystick_count; + if (joystick_axes[0] < joystick_count) + c06x_inputs &= ~C06X_INPUT_PADDL0; + if (joystick_axes[1] < joystick_count) + c06x_inputs &= ~C06X_INPUT_PADDL1; + if (joystick_axes[2] < joystick_count) + c06x_inputs &= ~C06X_INPUT_PADDL2; + if (joystick_axes[3] < joystick_count) + c06x_inputs &= ~C06X_INPUT_PADDL3; + } + int addr = addr0; #if 0 // vectors if (addr >= 4 && addr < 0x80) { @@ -1408,7 +1468,7 @@ int main(int argc, char **argv) { } } - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) { fprintf(stderr, "SDL_Init(): %s\n\n", SDL_GetError()); exit(EXIT_FAILURE); } @@ -1479,6 +1539,25 @@ int main(int argc, char **argv) { //); SDL_PauseAudioDevice(audio_device_id, 0); + SDL_Joystick *joystick = NULL; + if (SDL_NumJoysticks()) { + joystick = SDL_JoystickOpen(0); + if (joystick == NULL) { + fprintf(stderr, "SDL_JoystickOpen(): %s\n", SDL_GetError()); + exit(EXIT_FAILURE); + } + + if (SDL_JoystickEventState(SDL_ENABLE) != 1) { + fprintf(stderr, "SDL_JoystickEventState(): %s\n", SDL_GetError()); + exit(EXIT_FAILURE); + } + + // we should get the current position to use until first event, + // for now just centre it (no joystick is fully to right and down) + for (int i = 0; i < 4; ++i) + joystick_axes[i] = JOYSTICK_COUNT >> 1; + } + cpu = vrEmu6502New(CPU_65C02, mem_read, mem_write); if (cpu == NULL) { perror("malloc()"); @@ -1585,6 +1664,40 @@ int main(int argc, char **argv) { } } break; + case SDL_JOYBUTTONUP: + { + SDL_JoyButtonEvent *e = (SDL_JoyButtonEvent *)&event; + if ( + joystick && + e->which == SDL_JoystickInstanceID(joystick) && + e->button < 3 + ) + c06x_inputs &= ~(C06X_INPUT_PB0 << e->button); + } + break; + case SDL_JOYBUTTONDOWN: + { + SDL_JoyButtonEvent *e = (SDL_JoyButtonEvent *)&event; + if ( + joystick && + e->which == SDL_JoystickInstanceID(joystick) && + e->button < 3 + ) + c06x_inputs |= C06X_INPUT_PB0 << e->button; + } + break; + case SDL_JOYAXISMOTION: + { + SDL_JoyAxisEvent *e = (SDL_JoyAxisEvent *)&event; + if ( + joystick && + e->which == SDL_JoystickInstanceID(joystick) && + e->axis < 4 + ) + joystick_axes[e->axis] = + ((e->value + 0x8000) * JOYSTICK_COUNT) >> 16; + } + break; } // video update @@ -1947,6 +2060,8 @@ jam: quit: vrEmu6502Destroy(cpu); + if (joystick) + SDL_JoystickClose(joystick); SDL_CloseAudioDevice(audio_device_id); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); -- 2.34.1