Fixes #74 Implement Paddle/Joystick Support (#85)

This commit is contained in:
Stefan Arentz 2016-12-19 22:30:33 -05:00 committed by GitHub
parent 5596fc4555
commit 2557b2b1d0
5 changed files with 84 additions and 48 deletions

View File

@ -170,6 +170,8 @@ static int cpu_execute_instruction(struct cpu_t *cpu) {
pc, bytes, trace_instruction, trace_state, trace_stack); pc, bytes, trace_instruction, trace_state, trace_stack);
} }
cpu->counter += i->cycles;
return i->cycles; return i->cycles;
} }
@ -408,21 +410,6 @@ int cpu_nmi(struct cpu_t *cpu) {
return 0; return 0;
} }
int cpu_run(struct cpu_t *cpu) {
uint64_t instruction_count = 0;
int err = 0;
while ((err = cpu_execute_instruction(cpu)) == 0) {
/* TODO: Tick? */
instruction_count++;
}
return err;
}
int cpu_boot(struct cpu_t *cpu) {
cpu_reset(cpu);
return cpu_run(cpu);
}
int cpu_step(struct cpu_t *cpu) { int cpu_step(struct cpu_t *cpu) {
return cpu_execute_instruction(cpu); return cpu_execute_instruction(cpu);
} }

View File

@ -53,6 +53,7 @@ struct cpu_t {
bool strict; bool strict;
struct mem_t *mem; struct mem_t *mem;
struct cpu_instruction_t *instructions; struct cpu_instruction_t *instructions;
uint64_t counter;
}; };
#define MEM_FLAGS_READ 0x01 #define MEM_FLAGS_READ 0x01
@ -105,8 +106,6 @@ void cpu_reset(struct cpu_t *cpu);
int cpu_irq(struct cpu_t *cpu); int cpu_irq(struct cpu_t *cpu);
int cpu_nmi(struct cpu_t *cpu); int cpu_nmi(struct cpu_t *cpu);
int cpu_run(struct cpu_t *cpu);
int cpu_boot(struct cpu_t *cpu);
int cpu_step(struct cpu_t *cpu); int cpu_step(struct cpu_t *cpu);
uint16_t cpu_memory_get_word(struct cpu_t *cpu, uint16_t addr); uint16_t cpu_memory_get_word(struct cpu_t *cpu, uint16_t addr);

View File

@ -116,7 +116,7 @@ int main() {
// Setup the CPU, Apple ][+ and it's screen. // Setup the CPU, Apple ][+ and it's screen.
struct ewm_two_t *two = ewm_two_create(EWM_TWO_TYPE_APPLE2PLUS, renderer); struct ewm_two_t *two = ewm_two_create(EWM_TWO_TYPE_APPLE2PLUS, renderer, NULL);
test(two->scr, "txt_full_refresh", txt_full_refresh_setup, txt_full_refresh_test); test(two->scr, "txt_full_refresh", txt_full_refresh_setup, txt_full_refresh_test);
test(two->scr, "lgr_full_refresh", lgr_full_refresh_setup, lgr_full_refresh_test); test(two->scr, "lgr_full_refresh", lgr_full_refresh_setup, lgr_full_refresh_test);

View File

@ -62,6 +62,13 @@
#define EWM_A2P_SS_PB2 0xC063 #define EWM_A2P_SS_PB2 0xC063
#define EWM_A2P_SS_PB3 0xC060 // TODO On the gs only? #define EWM_A2P_SS_PB3 0xC060 // TODO On the gs only?
#define EWM_TWO_SS_PTRIG 0xc070
#define EWM_TWO_SS_PADL0 0xc064
#define EWM_TWO_SS_PADL1 0xc065
#define EWM_TWO_SS_PADL3 0xc066
#define EWM_TWO_SS_PADL4 0xc067
static uint8_t ewm_two_iom_read(struct cpu_t *cpu, struct mem_t *mem, uint16_t addr) { static uint8_t ewm_two_iom_read(struct cpu_t *cpu, struct mem_t *mem, uint16_t addr) {
struct ewm_two_t *two = (struct ewm_two_t*) mem->obj; struct ewm_two_t *two = (struct ewm_two_t*) mem->obj;
switch (addr) { switch (addr) {
@ -138,6 +145,31 @@ static uint8_t ewm_two_iom_read(struct cpu_t *cpu, struct mem_t *mem, uint16_t a
case EWM_A2P_SS_CLRAN3: case EWM_A2P_SS_CLRAN3:
break; break;
case EWM_TWO_SS_PTRIG: {
if (two->joystick != NULL) {
int x = 128 + (SDL_JoystickGetAxis(two->joystick, 0) / 256);
two->padl0_time = two->cpu->counter + (x * (2820 / 255)); // TODO Remove magic values
two->padl0_value = 0xff;
int y = 128 + (SDL_JoystickGetAxis(two->joystick, 1) / 256);
two->padl1_time = two->cpu->counter + (y * (2820 / 255)); // TODO Remove magic values
two->padl1_value = 0xff;
}
break;
}
case EWM_TWO_SS_PADL0: {
if (two->padl0_time != 0 && two->cpu->counter >= two->padl0_time) {
two->padl0_time = 0;
two->padl0_value = 0;
}
return two->padl0_value;
}
case EWM_TWO_SS_PADL1: {
if (two->padl1_time != 0 && two->cpu->counter >= two->padl1_time) {
two->padl1_value = 0;
}
return two->padl1_value;
}
default: default:
printf("[A2P] Unexpected read at $%.4X\n", addr); printf("[A2P] Unexpected read at $%.4X\n", addr);
break; break;
@ -239,7 +271,7 @@ static void ewm_two_screen_hgr_write(struct cpu_t *cpu, struct mem_t *mem, uint1
two->screen_dirty = true; two->screen_dirty = true;
} }
static int ewm_two_init(struct ewm_two_t *two, int type, SDL_Renderer *renderer) { static int ewm_two_init(struct ewm_two_t *two, int type, SDL_Renderer *renderer, SDL_Joystick *joystick) {
memset(two, 0, sizeof(struct ewm_two_t)); memset(two, 0, sizeof(struct ewm_two_t));
two->type = type; two->type = type;
@ -297,12 +329,14 @@ static int ewm_two_init(struct ewm_two_t *two, int type, SDL_Renderer *renderer)
two->screen_hgr_data = malloc(16 * 1024); two->screen_hgr_data = malloc(16 * 1024);
two->screen_hgr_iom = cpu_add_iom(two->cpu, 0x2000, 0x5fff, two, ewm_two_screen_hgr_read, ewm_two_screen_hgr_write); two->screen_hgr_iom = cpu_add_iom(two->cpu, 0x2000, 0x5fff, two, ewm_two_screen_hgr_read, ewm_two_screen_hgr_write);
two->joystick = joystick;
return 0; return 0;
} }
struct ewm_two_t *ewm_two_create(int type, SDL_Renderer *renderer) { struct ewm_two_t *ewm_two_create(int type, SDL_Renderer *renderer, SDL_Joystick *joystick) {
struct ewm_two_t *two = malloc(sizeof(struct ewm_two_t)); struct ewm_two_t *two = malloc(sizeof(struct ewm_two_t));
if (ewm_two_init(two, type, renderer) != 0) { if (ewm_two_init(two, type, renderer, joystick) != 0) {
free(two); free(two);
two = NULL; two = NULL;
} }
@ -330,34 +364,28 @@ static bool ewm_two_poll_event(struct ewm_two_t *two, SDL_Window *window) { // T
two->screen_dirty = true; two->screen_dirty = true;
break; break;
case SDL_JOYBUTTONDOWN: case SDL_CONTROLLERBUTTONDOWN:
if (event.jbutton.button < EWM_A2P_BUTTON_COUNT) { case SDL_CONTROLLERBUTTONUP:
two->buttons[event.jbutton.button] = 1; switch (event.cbutton.button) {
} case SDL_CONTROLLER_BUTTON_A:
break; case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
case SDL_JOYBUTTONUP: two->buttons[0] = event.cbutton.state == SDL_PRESSED ? 0x80 : 0x00;
if (event.jbutton.button < EWM_A2P_BUTTON_COUNT) { break;
two->buttons[event.jbutton.button] = 0; case SDL_CONTROLLER_BUTTON_B:
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
two->buttons[1] = event.cbutton.state == SDL_PRESSED ? 0x80 : 0x00;
break;
case SDL_CONTROLLER_BUTTON_X:
two->buttons[2] = event.cbutton.state == SDL_PRESSED ? 0x80 : 0x00;
break;
case SDL_CONTROLLER_BUTTON_Y:
two->buttons[3] = event.cbutton.state == SDL_PRESSED ? 0x80 : 0x00;
break;
} }
break; break;
case SDL_KEYDOWN: case SDL_KEYDOWN:
if (event.key.keysym.mod & KMOD_ALT) { if (event.key.keysym.mod & KMOD_CTRL) {
switch (event.key.keysym.sym) {
case SDLK_1:
two->buttons[0] = 1;
break;
case SDLK_2:
two->buttons[1] = 1;
break;
case SDLK_3:
two->buttons[2] = 1;
break;
case SDLK_4:
two->buttons[3] = 1;
break;
}
} else if (event.key.keysym.mod & KMOD_CTRL) {
if (event.key.keysym.sym >= SDLK_a && event.key.keysym.sym <= SDLK_z) { if (event.key.keysym.sym >= SDLK_a && event.key.keysym.sym <= SDLK_z) {
two->key = (event.key.keysym.sym - SDLK_a) | 0x80; two->key = (event.key.keysym.sym - SDLK_a) | 0x80;
} else { } else {
@ -497,7 +525,7 @@ int ewm_two_main(int argc, char **argv) {
// Initialize SDL // Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS) < 0) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER) < 0) {
fprintf(stderr, "Failed to initialize SDL: %s\n", SDL_GetError()); fprintf(stderr, "Failed to initialize SDL: %s\n", SDL_GetError());
exit(1); exit(1);
} }
@ -516,9 +544,20 @@ int ewm_two_main(int argc, char **argv) {
SDL_RenderSetLogicalSize(renderer, 280*3, 192*3); SDL_RenderSetLogicalSize(renderer, 280*3, 192*3);
// If we have a joystick, open it
SDL_GameController *controller = NULL;
SDL_Joystick *joystick = NULL;
if (SDL_NumJoysticks() != 0) {
controller = SDL_GameControllerOpen(0);
SDL_GameControllerEventState(SDL_ENABLE);
joystick = SDL_GameControllerGetJoystick(controller);
}
// Create and configure the Apple II // Create and configure the Apple II
struct ewm_two_t *two = ewm_two_create(EWM_TWO_TYPE_APPLE2PLUS, renderer); struct ewm_two_t *two = ewm_two_create(EWM_TWO_TYPE_APPLE2PLUS, renderer, joystick);
if (color) { if (color) {
ewm_scr_set_color_scheme(two->scr, EWM_SCR_COLOR_SCHEME_COLOR); ewm_scr_set_color_scheme(two->scr, EWM_SCR_COLOR_SCHEME_COLOR);

View File

@ -80,9 +80,20 @@ struct ewm_two_t {
uint8_t key; uint8_t key;
uint8_t buttons[EWM_A2P_BUTTON_COUNT]; uint8_t buttons[EWM_A2P_BUTTON_COUNT];
uint64_t padl0_time;
uint8_t padl0_value;
uint64_t padl1_time;
uint8_t padl1_value;
uint64_t padl2_time; // Are 2 and 3 actually used? Not sure what to map them to.
uint8_t padl2_value;
uint64_t padl3_time;
uint8_t padl3_value;
SDL_Joystick *joystick;
}; };
struct ewm_two_t *ewm_two_create(int type, SDL_Renderer *renderer); struct ewm_two_t *ewm_two_create(int type, SDL_Renderer *renderer, SDL_Joystick *joystick);
void ewm_two_destroy(struct ewm_two_t *two); void ewm_two_destroy(struct ewm_two_t *two);
int ewm_two_load_disk(struct ewm_two_t *two, int drive, char *path); int ewm_two_load_disk(struct ewm_two_t *two, int drive, char *path);