X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=emulator.c;h=acf6a1f18d31db910e3e935fb6e1207744f464be;hb=3b91ccdbc93d5b503f2f958dd00439e25f00958b;hp=cdd21b18ed9daa26dc8fc793399442f9af59ddcf;hpb=cfff241e2359701d1735da9199a76e0429d5625b;p=pistorm diff --git a/emulator.c b/emulator.c index cdd21b1..acf6a1f 100644 --- a/emulator.c +++ b/emulator.c @@ -4,7 +4,6 @@ #include "input/input.h" #include "platforms/amiga/Gayle.h" -#include "platforms/amiga/gayle-ide/ide.h" #include "platforms/amiga/amiga-registers.h" #include "platforms/amiga/rtg/rtg.h" #include "platforms/amiga/hunk-reloc.h" @@ -18,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +31,7 @@ #include #include +#define KEY_POLL_INTERVAL_MSEC 5000 unsigned char read_ranges; unsigned int read_addr[8]; @@ -58,8 +59,7 @@ extern volatile uint16_t srdata; extern uint8_t realtime_graphics_debug; uint8_t realtime_disassembly, int2_enabled = 0; uint32_t do_disasm = 0, old_level; -uint32_t last_irq = 0, last_last_irq = 0; -char c = 0, c_code = 0, c_type = 0; // @todo temporary main/cpu_task scope workaround until input moved to a thread +uint32_t last_irq = 8, last_last_irq = 8; char disasm_buf[4096]; @@ -71,7 +71,7 @@ int mem_fd_gpclk; int irq; int gayleirq; -//#define MUSASHI_HAX +#define MUSASHI_HAX #ifdef MUSASHI_HAX #include "m68kcpu.h" @@ -107,6 +107,8 @@ char keyboard_file[256] = "/dev/input/event1"; uint64_t trig_irq = 0, serv_irq = 0; uint16_t irq_delay = 0; +unsigned int amiga_reset=0, amiga_reset_last=0; +unsigned int do_reset=0; void *ipl_task(void *args) { printf("IPL thread running\n"); @@ -119,8 +121,10 @@ void *ipl_task(void *args) { if (!(value & (1 << PIN_IPL_ZERO))) { irq = 1; old_irq = irq_delay; - NOP + //NOP M68K_END_TIMESLICE; + NOP + //usleep(0); } else { if (irq) { @@ -130,12 +134,31 @@ void *ipl_task(void *args) { else { irq = 0; } - NOP M68K_END_TIMESLICE; + NOP + //usleep(0); + } + } + if(do_reset==0) + { + amiga_reset=(value & (1 << PIN_RESET)); + if(amiga_reset!=amiga_reset_last) + { + amiga_reset_last=amiga_reset; + if(amiga_reset==0) + { + printf("Amiga Reset is down...\n"); + do_reset=1; + M68K_END_TIMESLICE; + } + else + { + printf("Amiga Reset is up...\n"); + } } } - if (gayle_ide_enabled) { + /*if (gayle_ide_enabled) { if (((gayle_int & 0x80) || gayle_a4k_int) && (get_ide(0)->drive[0].intrq || get_ide(0)->drive[1].intrq)) { //get_ide(0)->drive[0].intrq = 0; gayleirq = 1; @@ -143,11 +166,12 @@ void *ipl_task(void *args) { } else gayleirq = 0; - } + }*/ //usleep(0); + //NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP - NOP NOP NOP NOP NOP NOP NOP NOP - NOP NOP NOP NOP NOP NOP NOP NOP + //NOP NOP NOP NOP NOP NOP NOP NOP + //NOP NOP NOP NOP NOP NOP NOP NOP /*NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP*/ @@ -157,158 +181,200 @@ void *ipl_task(void *args) { void *cpu_task() { m68k_pulse_reset(); - while (42) { - if (mouse_hook_enabled) { - get_mouse_status(&mouse_dx, &mouse_dy, &mouse_buttons, &mouse_extra); - } - if (realtime_disassembly && (do_disasm || cpu_emulation_running)) { - m68k_disassemble(disasm_buf, m68k_get_reg(NULL, M68K_REG_PC), cpu_type); - printf("REGA: 0:$%.8X 1:$%.8X 2:$%.8X 3:$%.8X 4:$%.8X 5:$%.8X 6:$%.8X 7:$%.8X\n", m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1), m68k_get_reg(NULL, M68K_REG_A2), m68k_get_reg(NULL, M68K_REG_A3), \ - m68k_get_reg(NULL, M68K_REG_A4), m68k_get_reg(NULL, M68K_REG_A5), m68k_get_reg(NULL, M68K_REG_A6), m68k_get_reg(NULL, M68K_REG_A7)); - printf("REGD: 0:$%.8X 1:$%.8X 2:$%.8X 3:$%.8X 4:$%.8X 5:$%.8X 6:$%.8X 7:$%.8X\n", m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2), m68k_get_reg(NULL, M68K_REG_D3), \ - m68k_get_reg(NULL, M68K_REG_D4), m68k_get_reg(NULL, M68K_REG_D5), m68k_get_reg(NULL, M68K_REG_D6), m68k_get_reg(NULL, M68K_REG_D7)); - printf("%.8X (%.8X)]] %s\n", m68k_get_reg(NULL, M68K_REG_PC), (m68k_get_reg(NULL, M68K_REG_PC) & 0xFFFFFF), disasm_buf); - if (do_disasm) - do_disasm--; - m68k_execute(1); - } - else { - if (cpu_emulation_running) - m68k_execute(loop_cycles); - } +cpu_loop: + if (mouse_hook_enabled) { + get_mouse_status(&mouse_dx, &mouse_dy, &mouse_buttons, &mouse_extra); + } - if (irq) { - while (irq) { - last_irq = ((read_reg() & 0xe000) >> 13); - if (last_irq != last_last_irq) { - last_last_irq = last_irq; - M68K_SET_IRQ(last_irq); - } - m68k_execute(5); - } - if (gayleirq && int2_enabled) { - write16(0xdff09c, 0x8000 | (1 << 3) && last_irq != 2); + if (realtime_disassembly && (do_disasm || cpu_emulation_running)) { + m68k_disassemble(disasm_buf, m68k_get_reg(NULL, M68K_REG_PC), cpu_type); + printf("REGA: 0:$%.8X 1:$%.8X 2:$%.8X 3:$%.8X 4:$%.8X 5:$%.8X 6:$%.8X 7:$%.8X\n", m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1), m68k_get_reg(NULL, M68K_REG_A2), m68k_get_reg(NULL, M68K_REG_A3), \ + m68k_get_reg(NULL, M68K_REG_A4), m68k_get_reg(NULL, M68K_REG_A5), m68k_get_reg(NULL, M68K_REG_A6), m68k_get_reg(NULL, M68K_REG_A7)); + printf("REGD: 0:$%.8X 1:$%.8X 2:$%.8X 3:$%.8X 4:$%.8X 5:$%.8X 6:$%.8X 7:$%.8X\n", m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2), m68k_get_reg(NULL, M68K_REG_D3), \ + m68k_get_reg(NULL, M68K_REG_D4), m68k_get_reg(NULL, M68K_REG_D5), m68k_get_reg(NULL, M68K_REG_D6), m68k_get_reg(NULL, M68K_REG_D7)); + printf("%.8X (%.8X)]] %s\n", m68k_get_reg(NULL, M68K_REG_PC), (m68k_get_reg(NULL, M68K_REG_PC) & 0xFFFFFF), disasm_buf); + if (do_disasm) + do_disasm--; + m68k_execute(1); + } + else { + if (cpu_emulation_running) + m68k_execute(loop_cycles); + } + + if (irq) { + while (irq) { + last_irq = ((read_reg() & 0xe000) >> 13); + if (last_irq != last_last_irq) { last_last_irq = last_irq; - last_irq = 2; - M68K_SET_IRQ(2); + M68K_SET_IRQ(last_irq); } + m68k_execute(5); + } + if (gayleirq && int2_enabled) { + write16(0xdff09c, 0x8000 | (1 << 3) && last_irq != 2); + last_last_irq = last_irq; + last_irq = 2; + M68K_SET_IRQ(2); + } + M68K_SET_IRQ(0); + last_last_irq = 0; + m68k_execute(5); + } + /*else { + if (last_irq != 0) { M68K_SET_IRQ(0); - last_last_irq = 0; + last_last_irq = last_irq; + last_irq = 0; } - /*else { - if (last_irq != 0) { - M68K_SET_IRQ(0); - last_last_irq = last_irq; - last_irq = 0; - } - }*/ + }*/ + if (do_reset) { + cpu_pulse_reset(); + m68k_pulse_reset(); + do_reset=0; + usleep(1000000); // 1sec +// while(amiga_reset==0); +// printf("CPU emulation reset.\n"); + } + + + if (mouse_hook_enabled && (mouse_extra != 0x00)) { + // mouse wheel events have occurred; unlike l/m/r buttons, these are queued as keypresses, so add to end of buffer + switch (mouse_extra) { + case 0xff: + // wheel up + queue_keypress(0xfe, KEYPRESS_PRESS, PLATFORM_AMIGA); + break; + case 0x01: + // wheel down + queue_keypress(0xff, KEYPRESS_PRESS, PLATFORM_AMIGA); + break; + } + + // dampen the scroll wheel until next while loop iteration + mouse_extra = 0x00; + } + goto cpu_loop; + +//stop_cpu_emulation: + printf("[CPU] End of CPU thread\n"); +} - while (get_key_char(&c, &c_code, &c_type)) { - if (c && c == cfg->keyboard_toggle_key && !kb_hook_enabled) { - kb_hook_enabled = 1; - printf("Keyboard hook enabled.\n"); +void *keyboard_task() { + struct pollfd kbdpoll[1]; + int kpollrc; + char c = 0, c_code = 0, c_type = 0; + char grab_message[] = "[KBD] Grabbing keyboard from input layer\n", + ungrab_message[] = "[KBD] Ungrabbing keyboard\n"; + + printf("[KBD] Keyboard thread started\n"); + + // because we permit the keyboard to be grabbed on startup, quickly check if we need to grab it + if (kb_hook_enabled && cfg->keyboard_grab) { + printf(grab_message); + grab_device(keyboard_fd); + } + + kbdpoll[0].fd = keyboard_fd; + kbdpoll[0].events = POLLIN; + +key_loop: + kpollrc = poll(kbdpoll, 1, KEY_POLL_INTERVAL_MSEC); + if ((kpollrc > 0) && (kbdpoll[0].revents & POLLHUP)) { + // in the event that a keyboard is unplugged, keyboard_task will whiz up to 100% utilisation + // this is undesired, so if the keyboard HUPs, end the thread without ending the emulation + printf("[KBD] Keyboard node returned HUP (unplugged?)\n"); + goto key_end; + } + + // if kpollrc > 0 then it contains number of events to pull, also check if POLLIN is set in revents + if ((kpollrc <= 0) || !(kbdpoll[0].revents & POLLIN)) { + goto key_loop; + } + + while (get_key_char(&c, &c_code, &c_type)) { + if (c && c == cfg->keyboard_toggle_key && !kb_hook_enabled) { + kb_hook_enabled = 1; + printf("[KBD] Keyboard hook enabled.\n"); + if (cfg->keyboard_grab) { + grab_device(keyboard_fd); + printf(grab_message); } - else if (kb_hook_enabled) { - if (c == 0x1B && c_type) { - kb_hook_enabled = 0; - printf("Keyboard hook disabled.\n"); + } else if (kb_hook_enabled) { + if (c == 0x1B && c_type) { + kb_hook_enabled = 0; + printf("[KBD] Keyboard hook disabled.\n"); + if (cfg->keyboard_grab) { + release_device(keyboard_fd); + printf(ungrab_message); } - else { - /*printf("Key code: %.2X - ", c_code); - switch (c_type) { - case 0: - printf("released.\n"); - break; - case 1: - printf("pressed.\n"); - break; - case 2: - printf("repeat.\n"); - break; - default: - printf("unknown.\n"); - break; - }*/ - if (queue_keypress(c_code, c_type, cfg->platform->id) && int2_enabled && last_irq != 2) { - //last_irq = 0; - //M68K_SET_IRQ(2); - } + } else { + if (queue_keypress(c_code, c_type, cfg->platform->id) && int2_enabled && last_irq != 2) { + //last_irq = 0; + //M68K_SET_IRQ(2); } } + } - // pause pressed; trigger nmi (int level 7) - if (c == 0x01 && c_type) { - printf("[INT] Sending NMI\n"); - M68K_SET_IRQ(7); - } + // pause pressed; trigger nmi (int level 7) + if (c == 0x01 && c_type) { + printf("[INT] Sending NMI\n"); + M68K_SET_IRQ(7); + } - if (!kb_hook_enabled && c_type) { - if (c && c == cfg->mouse_toggle_key) { - mouse_hook_enabled ^= 1; - printf("Mouse hook %s.\n", mouse_hook_enabled ? "enabled" : "disabled"); - mouse_dx = mouse_dy = mouse_buttons = mouse_extra = 0; - } - if (c == 'r') { - cpu_emulation_running ^= 1; - printf("CPU emulation is now %s\n", cpu_emulation_running ? "running" : "stopped"); - } - if (c == 'g') { - realtime_graphics_debug ^= 1; - printf("Real time graphics debug is now %s\n", realtime_graphics_debug ? "on" : "off"); - } - if (c == 'R') { - cpu_pulse_reset(); - //m68k_pulse_reset(); - printf("CPU emulation reset.\n"); - } - if (c == 'q') { - printf("Quitting and exiting emulator.\n"); - goto stop_cpu_emulation; - } - if (c == 'd') { - realtime_disassembly ^= 1; - do_disasm = 1; - printf("Real time disassembly is now %s\n", realtime_disassembly ? "on" : "off"); - } - if (c == 'D') { - int r = get_mapped_item_by_address(cfg, 0x08000000); - if (r != -1) { - printf("Dumping first 16MB of mapped range %d.\n", r); - FILE *dmp = fopen("./memdmp.bin", "wb+"); - fwrite(cfg->map_data[r], 16 * SIZE_MEGA, 1, dmp); - fclose(dmp); - } - } - if (c == 's' && realtime_disassembly) { - do_disasm = 1; - } - if (c == 'S' && realtime_disassembly) { - do_disasm = 128; + if (!kb_hook_enabled && c_type) { + if (c && c == cfg->mouse_toggle_key) { + mouse_hook_enabled ^= 1; + printf("Mouse hook %s.\n", mouse_hook_enabled ? "enabled" : "disabled"); + mouse_dx = mouse_dy = mouse_buttons = mouse_extra = 0; + } + if (c == 'r') { + cpu_emulation_running ^= 1; + printf("CPU emulation is now %s\n", cpu_emulation_running ? "running" : "stopped"); + } + if (c == 'g') { + realtime_graphics_debug ^= 1; + printf("Real time graphics debug is now %s\n", realtime_graphics_debug ? "on" : "off"); + } + if (c == 'R') { + cpu_pulse_reset(); + //m68k_pulse_reset(); + printf("CPU emulation reset.\n"); + } + // @todo work out how to signal the main process that we want to quit + // if (c == 'q') { + // printf("Quitting and exiting emulator.\n"); + // goto stop_cpu_emulation; + // } + if (c == 'd') { + realtime_disassembly ^= 1; + do_disasm = 1; + printf("Real time disassembly is now %s\n", realtime_disassembly ? "on" : "off"); + } + if (c == 'D') { + int r = get_mapped_item_by_address(cfg, 0x08000000); + if (r != -1) { + printf("Dumping first 16MB of mapped range %d.\n", r); + FILE *dmp = fopen("./memdmp.bin", "wb+"); + fwrite(cfg->map_data[r], 16 * SIZE_MEGA, 1, dmp); + fclose(dmp); } } - } - - if (mouse_hook_enabled && (mouse_extra != 0x00)) { - // mouse wheel events have occurred; unlike l/m/r buttons, these are queued as keypresses, so add to end of buffer - switch (mouse_extra) { - case 0xff: - // wheel up - queue_keypress(0xfe, KEYPRESS_PRESS, PLATFORM_AMIGA); - break; - case 0x01: - // wheel down - queue_keypress(0xff, KEYPRESS_PRESS, PLATFORM_AMIGA); - break; + if (c == 's' && realtime_disassembly) { + do_disasm = 1; + } + if (c == 'S' && realtime_disassembly) { + do_disasm = 128; } - - // dampen the scroll wheel until next while loop iteration - mouse_extra = 0x00; } } -stop_cpu_emulation: - printf("[CPU] End of CPU thread\n"); + goto key_loop; + +key_end: + printf("[KBD] Keyboard thread ending\n"); + return (void*)NULL; } void stop_cpu_emulation(uint8_t disasm_cur) { @@ -435,7 +501,11 @@ int main(int argc, char *argv[]) { } } - keyboard_fd = open(keyboard_file, O_RDONLY | O_NONBLOCK); + if (cfg->keyboard_file) + keyboard_fd = open(cfg->keyboard_file, O_RDONLY | O_NONBLOCK); + else + keyboard_fd = open(keyboard_file, O_RDONLY | O_NONBLOCK); + if (keyboard_fd == -1) { printf("Failed to open keyboard event source.\n"); } @@ -485,7 +555,7 @@ int main(int argc, char *argv[]) { m68k_set_cpu_type(cpu_type); cpu_pulse_reset(); - pthread_t ipl_tid, cpu_tid; + pthread_t ipl_tid, cpu_tid, kbd_tid; int err; err = pthread_create(&ipl_tid, NULL, &ipl_task, NULL); if (err != 0) @@ -493,16 +563,25 @@ int main(int argc, char *argv[]) { else { pthread_setname_np(ipl_tid, "pistorm: ipl"); printf("IPL thread created successfully\n"); - } + } + + // create keyboard task + err = pthread_create(&kbd_tid, NULL, &keyboard_task, NULL); + if (err != 0) + printf("[ERROR] Cannot create keyboard thread: [%s]", strerror(err)); + else { + pthread_setname_np(kbd_tid, "pistorm: kbd"); + printf("[MAIN] Keyboard thread created successfully\n"); + } // create cpu task err = pthread_create(&cpu_tid, NULL, &cpu_task, NULL); if (err != 0) printf("[ERROR] Cannot create CPU thread: [%s]", strerror(err)); - else { + else { pthread_setname_np(cpu_tid, "pistorm: cpu"); - printf("CPU thread created successfully\n"); - } + printf("[MAIN] CPU thread created successfully\n"); + } // wait for cpu task to end before closing up and finishing pthread_join(cpu_tid, NULL); @@ -526,8 +605,7 @@ void cpu_pulse_reset(void) { if (cfg->platform->handle_reset) cfg->platform->handle_reset(cfg); - - m68k_write_memory_16(INTENA, 0x7FFF); + //m68k_write_memory_16(INTENA, 0x7FFF); ovl = 1; m68k_write_memory_8(0xbfe201, 0x0001); // AMIGA OVL m68k_write_memory_8(0xbfe001, 0x0001); // AMIGA OVL high (ROM@0x0)