# HG changeset patch # User Michael Pavone # Date 1459668834 25200 # Node ID c677507682e3bd61d3339840189691a9d73a2f02 # Parent 351a0d0cce3b4b94701a11ff102e545c26178525 Untested controller implementation diff -r 351a0d0cce3b -r c677507682e3 Makefile --- a/Makefile Fri Apr 01 21:51:46 2016 -0700 +++ b/Makefile Sun Apr 03 00:33:54 2016 -0700 @@ -18,7 +18,7 @@ $(TARGETDIR) : mkdir $(TARGETDIR) -$(TARGETDIR)/s16 : $(TARGETDIR)/main.o $(TARGETDIR)/cpu.o $(TARGETDIR)/vdp.o $(TARGETDIR)/audio.o $(TARGETDIR)/timer.o $(TARGETDIR)/system_sdl.o +$(TARGETDIR)/s16 : $(TARGETDIR)/main.o $(TARGETDIR)/cpu.o $(TARGETDIR)/vdp.o $(TARGETDIR)/audio.o $(TARGETDIR)/timer.o $(TARGETDIR)/controller.o $(TARGETDIR)/system_sdl.o $(CC) -o $@ $^ $(LDFLAGS) $(TARGETDIR)/asm : $(TARGETDIR)/asm.o $(TARGETDIR)/mnemonics.o diff -r 351a0d0cce3b -r c677507682e3 src/main.c --- a/src/main.c Fri Apr 01 21:51:46 2016 -0700 +++ b/src/main.c Sun Apr 03 00:33:54 2016 -0700 @@ -6,6 +6,7 @@ #include "vdp.h" #include "audio.h" #include "timer.h" +#include "controller.h" #include "system.h" #define CYCLES_PER_FRAME (832*262) @@ -17,8 +18,8 @@ enum { PORT_CONTROLLER_1, PORT_CONTROLLER_2, - PORT_CONTROLLER_3, - PORT_CONTROLLER_4, + RESERVED_1, + RESERVED_2, PORT_FREQUENCY_A, PORT_FREQUENCY_B, PORT_FREQUENCY_C, @@ -34,10 +35,11 @@ }; typedef struct { - cpu *proc; - audio *audio; - timer timer; - vdp video; + cpu *proc; + audio *audio; + timer timer; + controllers pads; + vdp video; } console; void debug_port_write(cpu *context, uint8_t port, uint16_t value) @@ -124,6 +126,14 @@ } } +uint16_t controller_port_read(cpu *context, uint8_t port) +{ + //process events so controller state is as fresh as possible + system_poll_events(); + console *system = context->system; + return controller_read(&system->pads, port - PORT_CONTROLLER_1); +} + uint32_t next_interrupt_cycle(cpu *context, uint8_t mask) { console *system = context->system; @@ -210,6 +220,8 @@ context.proc->system = &context; vdp_init(&context.video, 2); timer_init(&context.timer, 16); + context.proc->port_handlers[PORT_CONTROLLER_1].read = controller_port_read; + context.proc->port_handlers[PORT_CONTROLLER_2].read = controller_port_read; context.proc->port_handlers[PORT_FREQUENCY_A].write = frequency_port_write; context.proc->port_handlers[PORT_FREQUENCY_B].write = frequency_port_write; context.proc->port_handlers[PORT_FREQUENCY_C].write = frequency_port_write; diff -r 351a0d0cce3b -r c677507682e3 src/system_sdl.c --- a/src/system_sdl.c Fri Apr 01 21:51:46 2016 -0700 +++ b/src/system_sdl.c Sun Apr 03 00:33:54 2016 -0700 @@ -1,6 +1,7 @@ #include #include #include +#include "controller.h" static SDL_Window *window; @@ -69,9 +70,12 @@ return buffer_size; } +static int num_controllers; +static SDL_GameController **game_controllers; + int system_init(int width, int height, int desired_sample_rate) { - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER) < 0) { fprintf(stderr, "Failed to init SDL: %s\n", SDL_GetError()); return 0; } @@ -116,6 +120,18 @@ atexit(close_audio); SDL_PauseAudio(0); + num_controllers = SDL_NumJoysticks(); + game_controllers = calloc(num_controllers, sizeof(*game_controllers)); + + for (int i = 0; i < num_controllers; i++) + { + if (!SDL_IsGameController(i)) { + printf("Joystick %d: %s is not recognized as a controller by SDL2\n", i, SDL_JoystickNameForIndex(i)); + continue; + } + game_controllers[i] = SDL_GameControllerOpen(i); + } + return 1; error: @@ -142,6 +158,36 @@ SDL_RenderPresent(renderer); } +//SDL2 provides this, but only in 2.0.4+ +SDL_GameController *controller_by_id(SDL_JoystickID which) +{ + for (int i = 0; i < num_controllers; i++) + { + if (!game_controllers[i]) { + continue; + } + if (SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(game_controllers[i])) == which) { + return game_controllers[i]; + } + } + return NULL; +} + +const uint16_t mapping[SDL_CONTROLLER_BUTTON_MAX] = { + [SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = 0x001, + [SDL_CONTROLLER_BUTTON_Y] = 0x002, + [SDL_CONTROLLER_BUTTON_X] = 0x004, + [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = 0x008, + [SDL_CONTROLLER_BUTTON_B] = 0x010, + [SDL_CONTROLLER_BUTTON_A] = 0x020, + [SDL_CONTROLLER_BUTTON_BACK] = 0x040, + [SDL_CONTROLLER_BUTTON_START] = 0x080, + [SDL_CONTROLLER_BUTTON_DPAD_RIGHT] = 0x100, + [SDL_CONTROLLER_BUTTON_DPAD_LEFT] = 0x200, + [SDL_CONTROLLER_BUTTON_DPAD_DOWN] = 0x400, + [SDL_CONTROLLER_BUTTON_DPAD_UP] = 0x800, +}; + void system_poll_events() { SDL_Event event; @@ -152,6 +198,14 @@ case SDL_QUIT: exit(0); break; + case SDL_CONTROLLERBUTTONDOWN: + controller_pressed(event.cbutton.which, mapping[event.cbutton.button]); + break; + case SDL_CONTROLLERBUTTONUP: + controller_released(event.cbutton.which, mapping[event.cbutton.button]); + break; + //TODO: Keyboard input + //TODO: Controller hotplug } } }