-char keyboard_file[256] = "/dev/input/event0";
-
-// I/O access
-volatile unsigned int *gpio;
-volatile unsigned int *gpclk;
-volatile unsigned int gpfsel0;
-volatile unsigned int gpfsel1;
-volatile unsigned int gpfsel2;
-volatile unsigned int gpfsel0_o;
-volatile unsigned int gpfsel1_o;
-volatile unsigned int gpfsel2_o;
-
-// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or
-// SET_GPIO_ALT(x,y)
-#define INP_GPIO(g) *(gpio + ((g) / 10)) &= ~(7 << (((g) % 10) * 3))
-#define OUT_GPIO(g) *(gpio + ((g) / 10)) |= (1 << (((g) % 10) * 3))
-#define SET_GPIO_ALT(g, a) \
- *(gpio + (((g) / 10))) |= \
- (((a) <= 3 ? (a) + 4 : (a) == 4 ? 3 : 2) << (((g) % 10) * 3))
-
-#define GPIO_SET \
- *(gpio + 7) // sets bits which are 1 ignores bits which are 0
-#define GPIO_CLR \
- *(gpio + 10) // clears bits which are 1 ignores bits which are 0
-
-#define GET_GPIO(g) (*(gpio + 13) & (1 << g)) // 0 if LOW, (1<<g) if HIGH
-
-#define GPIO_PULL *(gpio + 37) // Pull up/pull down
-#define GPIO_PULLCLK0 *(gpio + 38) // Pull up/pull down clock
-
-void setup_io();
-
-uint32_t read8(uint32_t address);
-void write8(uint32_t address, uint32_t data);
-
-uint32_t read16(uint32_t address);
-void write16(uint32_t address, uint32_t data);
-
-void write32(uint32_t address, uint32_t data);
-uint32_t read32(uint32_t address);
-
-uint16_t read_reg(void);
-void write_reg(unsigned int value);
-
-volatile uint16_t srdata;
-volatile uint32_t srdata2;
-volatile uint32_t srdata2_old;
-
-//unsigned char g_kick[524288];
-//unsigned char g_ram[FASTSIZE + 1]; /* RAM */
-unsigned char toggle;
-int ovl;
+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");
+ uint16_t old_irq = 0;
+ uint32_t value;
+
+ while (1) {
+ value = *(gpio + 13);
+
+ if (!(value & (1 << PIN_IPL_ZERO))) {
+ irq = 1;
+ old_irq = irq_delay;
+ //NOP
+ M68K_END_TIMESLICE;
+ NOP
+ //usleep(0);
+ }
+ else {
+ if (irq) {
+ if (old_irq) {
+ old_irq--;
+ }
+ else {
+ irq = 0;
+ }
+ 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_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;
+ M68K_END_TIMESLICE;
+ }
+ 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*/
+ }
+ return args;
+}
+
+void *cpu_task() {
+ m68k_pulse_reset();
+
+cpu_loop:
+ 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);
+ }
+
+ 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);
+ 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 = last_irq;
+ last_irq = 0;
+ }
+ }*/
+ if (do_reset) {
+ cpu_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) {
+ 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;
+ }
+
+ 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:
+ printf("[CPU] End of CPU thread\n");
+ return (void *)NULL;
+}
+
+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("[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);
+ }
+ }
+ }
+
+ // 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");
+ end_signal = 1;
+ goto key_end;
+ }
+ 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;
+ }
+ }
+ }
+
+ goto key_loop;
+
+key_end:
+ printf("[KBD] Keyboard thread ending\n");
+ if (cfg->keyboard_grab) {
+ printf(ungrab_message);
+ release_device(keyboard_fd);
+ }
+ return (void*)NULL;
+}
+
+void stop_cpu_emulation(uint8_t disasm_cur) {
+ M68K_END_TIMESLICE;
+ if (disasm_cur) {
+ 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);
+ realtime_disassembly = 1;
+ }
+
+ cpu_emulation_running = 0;
+ do_disasm = 0;
+}
+
+unsigned int ovl;