X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=emulator.c;h=ec2d0f172d20653153a9dde0cc68880678c7b24b;hb=6b48b5b3e0d7641b7bef4f6c85b6f5f11b836d93;hp=157cb64660d002059202752b61dda5f590bffd27;hpb=975ce97643fd0d74fa1befc8e51d6d7872c735e2;p=pistorm diff --git a/emulator.c b/emulator.c index 157cb64..ec2d0f1 100644 --- a/emulator.c +++ b/emulator.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include "m68k.h" #include "emulator.h" #include "platforms/platforms.h" @@ -11,6 +13,8 @@ #include "platforms/amiga/piscsi/piscsi-enums.h" #include "platforms/amiga/net/pi-net.h" #include "platforms/amiga/net/pi-net-enums.h" +#include "platforms/amiga/pistorm-dev/pistorm-dev.h" +#include "platforms/amiga/pistorm-dev/pistorm-dev-enums.h" #include "gpio/ps_protocol.h" #include @@ -56,12 +60,14 @@ extern uint8_t gayle_emulation_enabled; extern uint8_t gayle_a4k_int; extern volatile unsigned int *gpio; extern volatile uint16_t srdata; -extern uint8_t realtime_graphics_debug; +extern uint8_t realtime_graphics_debug, emulator_exiting; +extern uint8_t rtg_on; uint8_t realtime_disassembly, int2_enabled = 0; uint32_t do_disasm = 0, old_level; -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; +uint8_t end_signal = 0, load_new_config = 0; + char disasm_buf[4096]; #define KICKBASE 0xF80000 @@ -232,14 +238,13 @@ cpu_loop: }*/ if (do_reset) { cpu_pulse_reset(); - m68k_pulse_reset(); do_reset=0; usleep(1000000); // 1sec + rtg_on=0; // 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) { @@ -256,46 +261,71 @@ cpu_loop: // dampen the scroll wheel until next while loop iteration mouse_extra = 0x00; } + + if (load_new_config) { + printf("[CPU] Loading new config file.\n"); + goto stop_cpu_emulation; + } + + if (end_signal) + goto stop_cpu_emulation; + goto cpu_loop; -//stop_cpu_emulation: +stop_cpu_emulation: printf("[CPU] End of CPU thread\n"); + return (void *)NULL; } void *keyboard_task() { - struct pollfd kbdfd[1]; - int kpoll; + 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"); - kbdfd[0].fd = keyboard_fd; - kbdfd[0].events = POLLIN; + // 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: - kpoll = poll(kbdfd, 1, KEY_POLL_INTERVAL_MSEC); - if ((kpoll > 0) && (kbdfd[0].revents & POLLHUP)) { + 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 kpoll > 0 then it contains number of events to pull, also check if POLLIN is set in revents - if ((kpoll <= 0) || !(kbdfd[0].revents & POLLIN)) { + // 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("Keyboard hook enabled.\n"); - } - else if (kb_hook_enabled) { + 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 { + printf("[KBD] Keyboard hook disabled.\n"); + if (cfg->keyboard_grab) { + release_device(keyboard_fd); + printf(ungrab_message); + } + } else { if (queue_keypress(c_code, c_type, cfg->platform->id) && int2_enabled && last_irq != 2) { //last_irq = 0; //M68K_SET_IRQ(2); @@ -328,11 +358,11 @@ key_loop: //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 == 'q') { + printf("Quitting and exiting emulator.\n"); + end_signal = 1; + goto key_end; + } if (c == 'd') { realtime_disassembly ^= 1; do_disasm = 1; @@ -360,6 +390,10 @@ key_loop: key_end: printf("[KBD] Keyboard thread ending\n"); + if (cfg->keyboard_grab) { + printf(ungrab_message); + release_device(keyboard_fd); + } return (void*)NULL; } @@ -397,6 +431,11 @@ void sigint_handler(int sig_num) { cfg->platform->shutdown(cfg); } + while (!emulator_exiting) { + emulator_exiting = 1; + usleep(0); + } + printf("IRQs triggered: %lld\n", trig_irq); printf("IRQs serviced: %lld\n", serv_irq); @@ -407,11 +446,6 @@ int main(int argc, char *argv[]) { int g; //const struct sched_param priority = {99}; - if (argc > 1) { - irq_delay = atoi(argv[1]); - printf("Setting IRQ delay to %d loops (%s).\n", irq_delay, argv[1]); - } - // Some command line switch stuffles for (g = 1; g < argc; g++) { if (strcmp(argv[g], "--cpu_type") == 0 || strcmp(argv[g], "--cpu") == 0) { @@ -428,6 +462,9 @@ int main(int argc, char *argv[]) { } else { g++; cfg = load_config_file(argv[g]); + if (cfg) { + set_pistorm_devcfg_filename(argv[g]); + } } } else if (strcmp(argv[g], "--keyboard-file") == 0 || strcmp(argv[g], "--kbfile") == 0) { @@ -440,6 +477,33 @@ int main(int argc, char *argv[]) { } } +switch_config: + srand(clock()); + + if (load_new_config != 0) { + uint8_t config_action = load_new_config - 1; + load_new_config = 0; + free_config_file(cfg); + if (cfg) { + free(cfg); + cfg = NULL; + } + + /*for(int i = 0; i < 2 * SIZE_MEGA; i++) { + write8(i, 0); + }*/ + + switch(config_action) { + case PICFG_LOAD: + case PICFG_RELOAD: + cfg = load_config_file(get_pistorm_devcfg_filename()); + break; + case PICFG_DEFAULT: + cfg = load_config_file("default.cfg"); + break; + } + } + if (!cfg) { printf("No config file specified. Trying to load default.cfg...\n"); cfg = load_config_file("default.cfg"); @@ -496,6 +560,12 @@ int main(int argc, char *argv[]) { printf("Failed to open keyboard event source.\n"); } + if (cfg->mouse_autoconnect) + mouse_hook_enabled = 1; + + if (cfg->keyboard_autoconnect) + kb_hook_enabled = 1; + InitGayle(); signal(SIGINT, sigint_handler); @@ -541,14 +611,16 @@ int main(int argc, char *argv[]) { m68k_set_cpu_type(cpu_type); cpu_pulse_reset(); - pthread_t ipl_tid, cpu_tid, kbd_tid; + pthread_t ipl_tid = 0, cpu_tid, kbd_tid; int err; - err = pthread_create(&ipl_tid, NULL, &ipl_task, NULL); - if (err != 0) - printf("[ERROR] Cannot create IPL thread: [%s]", strerror(err)); - else { - pthread_setname_np(ipl_tid, "pistorm: ipl"); - printf("IPL thread created successfully\n"); + if (ipl_tid == 0) { + err = pthread_create(&ipl_tid, NULL, &ipl_task, NULL); + if (err != 0) + printf("[ERROR] Cannot create IPL thread: [%s]", strerror(err)); + else { + pthread_setname_np(ipl_tid, "pistorm: ipl"); + printf("IPL thread created successfully\n"); + } } // create keyboard task @@ -571,30 +643,39 @@ int main(int argc, char *argv[]) { // wait for cpu task to end before closing up and finishing pthread_join(cpu_tid, NULL); - printf("[MAIN] All threads appear to have concluded; ending process\n"); + + while (!emulator_exiting) { + emulator_exiting = 1; + usleep(0); + } + + if (load_new_config == 0) + printf("[MAIN] All threads appear to have concluded; ending process\n"); if (mouse_fd != -1) close(mouse_fd); if (mem_fd) close(mem_fd); + if (load_new_config != 0) + goto switch_config; + + if (cfg->platform->shutdown) { + cfg->platform->shutdown(cfg); + } + return 0; } void cpu_pulse_reset(void) { ps_pulse_reset(); - //write_reg(0x00); - // printf("Status Reg%x\n",read_reg()); - //usleep(100000); - //write_reg(0x02); - // printf("Status Reg%x\n",read_reg()); if (cfg->platform->handle_reset) cfg->platform->handle_reset(cfg); //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) + //m68k_write_memory_8(0xbfe201, 0x0001); // AMIGA OVL + //m68k_write_memory_8(0xbfe001, 0x0001); // AMIGA OVL high (ROM@0x0) m68k_pulse_reset(); } @@ -788,9 +869,11 @@ unsigned int m68k_read_memory_32(unsigned int address) { case PLATFORM_AMIGA: { \ if (address >= PISCSI_OFFSET && address < PISCSI_UPPER) { \ handle_piscsi_write(address, value, a); \ + return; \ } \ if (address >= PINET_OFFSET && address < PINET_UPPER) { \ handle_pinet_write(address, value, a); \ + return; \ } \ if (address >= PIGFX_RTG_BASE && address < PIGFX_UPPER) { \ rtg_write((address & 0x0FFFFFFF), value, a); \