]> git.sesse.net Git - pistorm/blobdiff - emulator.c
Merge pull request #12 from beeanyew/wip-crap
[pistorm] / emulator.c
index a54485b86c84db8b28deec6ebf8a33f2c3cbd78a..fec99a82e3c4248b74f230e0252eb2bfd04d4df9 100644 (file)
@@ -18,6 +18,7 @@
 #include <dirent.h>
 #include <endian.h>
 #include <fcntl.h>
+#include <poll.h>
 #include <pthread.h>
 #include <sched.h>
 #include <signal.h>
@@ -31,6 +32,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#define KEY_POLL_INTERVAL_MSEC 5000
 
 unsigned char read_ranges;
 unsigned int read_addr[8];
@@ -58,8 +60,8 @@ 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 +73,7 @@ int mem_fd_gpclk;
 int irq;
 int gayleirq;
 
-//#define MUSASHI_HAX
+#define MUSASHI_HAX
 
 #ifdef MUSASHI_HAX
 #include "m68kcpu.h"
@@ -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,13 @@ void *ipl_task(void *args) {
         else {
           irq = 0;
         }
-        NOP
         M68K_END_TIMESLICE;
+        NOP
+        //usleep(0);
       }
     }
 
-    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 +148,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*/
@@ -196,6 +202,7 @@ cpu_loop:
     }
     M68K_SET_IRQ(0);
     last_last_irq = 0;
+    m68k_execute(5);
   }
   /*else {
     if (last_irq != 0) {
@@ -205,6 +212,51 @@ cpu_loop:
     }
   }*/
 
+  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");
+}
+
+void *keyboard_task() {
+  struct pollfd kbdfd[1];
+  int kpoll;
+
+  printf("[KBD] Keyboard thread started\n");
+
+  kbdfd[0].fd = keyboard_fd;
+  kbdfd[0].events = POLLIN;
+
+key_loop:
+  kpoll = poll(kbdfd, 1, KEY_POLL_INTERVAL_MSEC);
+  if ((kpoll > 0) && (kbdfd[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)) {
+    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;
@@ -216,21 +268,6 @@ cpu_loop:
         printf("Keyboard hook disabled.\n");
       }
       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);
@@ -263,10 +300,11 @@ cpu_loop:
         //m68k_pulse_reset();
         printf("CPU emulation reset.\n");
       }
-      if (c == 'q') {
-        printf("Quitting and exiting emulator.\n");
-        goto stop_cpu_emulation;
-      }
+      // @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;
@@ -290,26 +328,10 @@ cpu_loop:
     }
   }
 
-  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;
+  goto key_loop;
 
-stop_cpu_emulation:
-  printf("[CPU] End of CPU thread\n");
+key_end:
+  printf("[KBD] Keyboard thread ending\n");
 }
 
 void stop_cpu_emulation(uint8_t disasm_cur) {
@@ -486,7 +508,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)
@@ -496,13 +518,22 @@ int main(int argc, char *argv[]) {
     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 {
     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
@@ -527,7 +558,6 @@ void cpu_pulse_reset(void) {
   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