From fcd850c4952a5311f07f2f2c5650c39c8921dcb4 Mon Sep 17 00:00:00 2001 From: Paulo Duarte Date: Sun, 27 Jun 2021 04:24:38 +0100 Subject: [PATCH 1/4] Amiga emulated IRQ implementation --- Makefile | 1 + emulator.c | 13 +++++- platforms/amiga/amiga-interrupts.c | 63 ++++++++++++++++++++++++++++++ platforms/amiga/amiga-interrupts.h | 30 ++++++++++++++ platforms/amiga/amiga-platform.c | 3 ++ 5 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 platforms/amiga/amiga-interrupts.c create mode 100644 platforms/amiga/amiga-interrupts.h diff --git a/Makefile b/Makefile index ed7fbf6..797ba6d 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ MAINFILES = emulator.c \ platforms/amiga/amiga-autoconf.c \ platforms/amiga/amiga-platform.c \ platforms/amiga/amiga-registers.c \ + platforms/amiga/amiga-interrupts.c \ platforms/mac68k/mac68k-platform.c \ platforms/dummy/dummy-platform.c \ platforms/dummy/dummy-registers.c \ diff --git a/emulator.c b/emulator.c index 43d86e7..7a059c8 100644 --- a/emulator.c +++ b/emulator.c @@ -8,6 +8,7 @@ #include "platforms/amiga/Gayle.h" #include "platforms/amiga/amiga-registers.h" +#include "platforms/amiga/amiga-interrupts.h" #include "platforms/amiga/rtg/rtg.h" #include "platforms/amiga/hunk-reloc.h" #include "platforms/amiga/piscsi/piscsi.h" @@ -121,7 +122,7 @@ void *ipl_task(void *args) { if (value & (1 << PIN_TXN_IN_PROGRESS)) goto noppers; - if (!(value & (1 << PIN_IPL_ZERO))) { + if (!(value & (1 << PIN_IPL_ZERO)) || ipl_enabled[amiga_emulated_ipl()]) { old_irq = irq_delay; //NOP if (!irq) { @@ -231,6 +232,10 @@ cpu_loop: while (irq) { last_irq = ((inline_read_status_reg() & 0xe000) >> 13); + uint8_t amiga_irq = amiga_emulated_ipl(); + if (amiga_irq >= last_irq) { + last_irq = amiga_irq; + } if (last_irq != 0 && last_irq != last_last_irq) { last_last_irq = last_irq; M68K_SET_IRQ(last_irq); @@ -850,6 +855,9 @@ static inline int32_t platform_read_check(uint8_t type, uint32_t addr, uint32_t switch (cfg->platform->id) { case PLATFORM_AMIGA: switch (addr) { + case INTREQR: + return amiga_handle_intrqr_read(res); + break; case CIAAPRA: if (mouse_hook_enabled && (mouse_buttons & 0x01)) { rres = (uint32_t)ps_read(type, addr); @@ -1040,6 +1048,9 @@ static inline int32_t platform_write_check(uint8_t type, uint32_t addr, uint32_t break; case PLATFORM_AMIGA: switch (addr) { + case INTREQ: + return amiga_handle_intrq_write(val); + break; case CIAAPRA: if (ovl != (val & (1 << 0))) { ovl = (val & (1 << 0)); diff --git a/platforms/amiga/amiga-interrupts.c b/platforms/amiga/amiga-interrupts.c new file mode 100644 index 0000000..d292eda --- /dev/null +++ b/platforms/amiga/amiga-interrupts.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT + +#include +#include "config_file/config_file.h" +#include "amiga-registers.h" +#include "amiga-interrupts.h" +#include "gpio/ps_protocol.h" + +static const uint8_t IPL[14] = {1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6 }; + +uint16_t emulated_irqs = 0x0000; +uint8_t emulated_ipl; + +void amiga_emulate_irq(AMIGA_IRQ irq) { + emulated_irqs |= 1 << irq; + uint8_t ipl = IPL[irq]; + + if (emulated_ipl < ipl) { + emulated_ipl = ipl; + } +} + +inline uint8_t amiga_emulated_ipl() { + return emulated_ipl; +} + +inline int amiga_emulating_irq(AMIGA_IRQ irq) { + return emulated_irqs & (1 << irq); +} + +void amiga_clear_emulating_irq() { + emulated_irqs = 0; + emulated_ipl = 0; +} + +inline int amiga_handle_intrqr_read(uint32_t *res) { + if (emulated_irqs) { + *res = ps_read_16(INTREQR) | emulated_irqs; + return 1; + } + return 0; +} + +int amiga_handle_intrq_write(uint32_t val) { + if (emulated_irqs && !(val & 0x8000)) { + uint16_t previous_emulated_irqs = emulated_irqs; + uint16_t hardware_irqs_to_clear = val & ~emulated_irqs; + emulated_irqs &= ~val; + if (previous_emulated_irqs != emulated_irqs) { + emulated_ipl = 0; + for (int irq = 13; irq >= 0; irq--) { + if (emulated_irqs & (1 << irq)) { + emulated_ipl = IPL[irq]; + } + } + } + if (hardware_irqs_to_clear) { + ps_write_16(INTREQ, hardware_irqs_to_clear); + } + return 1; + } + return 0; +} diff --git a/platforms/amiga/amiga-interrupts.h b/platforms/amiga/amiga-interrupts.h new file mode 100644 index 0000000..cbcca45 --- /dev/null +++ b/platforms/amiga/amiga-interrupts.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT + +#ifndef PISTORM_AMIGA_INTERRUPTS_H +#define PISTORM_AMIGA_INTERRUPTS_H + +typedef enum { + TBE, //Serial port transmit buffer empty + DSKBLK, //Disk block finished + SOFT, //Reserved for software initiated interrupt + PORTS, //I/O Ports and timers + COPER, //Coprocessor + VERTB, //Start of vertical blank + BLIT, //Blitter has finished + AUD0, //Audio channel 0 block finished + AUD1, //Audio channel 1 block finished + AUD2, //Audio channel 2 block finished + AUD3, //Audio channel 3 block finished + RBF, //Serial port receive buffer full + DSKSYN, //Disk sync register (DSKSYNC) matches disk + EXTER, //External interrupt +} AMIGA_IRQ; + +void amiga_emulate_irq(AMIGA_IRQ irq); +uint8_t amiga_emulated_ipl(); +int amiga_emulating_irq(AMIGA_IRQ irq); +void amiga_clear_emulating_irq(); +int amiga_handle_intrqr_read(uint32_t *res); +int amiga_handle_intrq_write(uint32_t val); + +#endif //PISTORM_AMIGA_INTERRUPTS_H diff --git a/platforms/amiga/amiga-platform.c b/platforms/amiga/amiga-platform.c index f12c28d..bb50259 100644 --- a/platforms/amiga/amiga-platform.c +++ b/platforms/amiga/amiga-platform.c @@ -6,6 +6,7 @@ #include #include "amiga-autoconf.h" #include "amiga-registers.h" +#include "amiga-interrupts.h" #include "hunk-reloc.h" #include "net/pi-net-enums.h" #include "net/pi-net.h" @@ -536,6 +537,8 @@ void handle_reset_amiga(struct emulator_config *cfg) { if (piscsi_enabled) piscsi_refresh_drives(); + amiga_clear_emulating_irq(); + adjust_ranges_amiga(cfg); } From 5b74c77b1a858f7efa52841180425aa716fe7817 Mon Sep 17 00:00:00 2001 From: Paulo Duarte Date: Sun, 27 Jun 2021 04:25:11 +0100 Subject: [PATCH 2/4] Keyboard using emulated IRQ --- emulator.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/emulator.c b/emulator.c index 7a059c8..ac94024 100644 --- a/emulator.c +++ b/emulator.c @@ -317,6 +317,9 @@ key_loop: // 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)) { + if (cfg->platform->id == PLATFORM_AMIGA && last_irq != 2 && get_num_kb_queued()) { + amiga_emulate_irq(PORTS); + } goto key_loop; } @@ -337,9 +340,10 @@ key_loop: 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); + if (queue_keypress(c_code, c_type, cfg->platform->id)) { + if (cfg->platform->id == PLATFORM_AMIGA && last_irq != 2) { + amiga_emulate_irq(PORTS); + } } } } @@ -675,7 +679,6 @@ int cpu_irq_ack(int level) { } static unsigned int target = 0; -static uint8_t send_keypress = 0; static uint32_t platform_res, rres; uint8_t cdtv_dmac_reg_idx_read(); @@ -867,29 +870,18 @@ static inline int32_t platform_read_check(uint8_t type, uint32_t addr, uint32_t return 0; break; case CIAAICR: - if (kb_hook_enabled) { - rres = (uint32_t)ps_read(type, addr); - if (get_num_kb_queued() && (!send_keypress || send_keypress == 1)) { - rres |= 0x08; - if (!send_keypress) - send_keypress = 1; - } - if (send_keypress == 2) { - send_keypress = 0; - } - *res = rres; + if (kb_hook_enabled && get_num_kb_queued() && amiga_emulating_irq(PORTS)) { + *res = 0x88; return 1; } return 0; break; case CIAADAT: - if (kb_hook_enabled) { - rres = (uint32_t)ps_read(type, addr); + if (kb_hook_enabled && amiga_emulating_irq(PORTS)) { uint8_t c = 0, t = 0; pop_queued_key(&c, &t); t ^= 0x01; rres = ((c << 1) | t) ^ 0xFF; - send_keypress = 2; *res = rres; return 1; } From 6aef6ea4b66c68c63fad001e45a0172d15c75b5f Mon Sep 17 00:00:00 2001 From: Paulo Duarte Date: Sun, 27 Jun 2021 04:40:44 +0100 Subject: [PATCH 3/4] Fixed lowercase v on char_from_input_event --- input/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input/input.c b/input/input.c index 735744b..547c17c 100644 --- a/input/input.c +++ b/input/input.c @@ -101,7 +101,7 @@ char char_from_input_event(struct input_event *ev) { KEYCASE(KEY_S, 's', 'S'); KEYCASE(KEY_T, 't', 'T'); KEYCASE(KEY_U, 'u', 'U'); - KEYCASE(KEY_V, 'c', 'V'); + KEYCASE(KEY_V, 'v', 'V'); KEYCASE(KEY_W, 'w', 'W'); KEYCASE(KEY_X, 'x', 'X'); KEYCASE(KEY_Y, 'y', 'Y'); From 441b0709b45498812417db922ca0f260e92208f4 Mon Sep 17 00:00:00 2001 From: Paulo Duarte Date: Sun, 27 Jun 2021 04:40:59 +0100 Subject: [PATCH 4/4] Fixed Caps Lock behaviour --- input/input.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/input/input.c b/input/input.c index 547c17c..2f5e68f 100644 --- a/input/input.c +++ b/input/input.c @@ -14,7 +14,7 @@ #define NONE 0x80 -static int lshift = 0, rshift = 0,/* lctrl = 0, rctrl = 0,*/ lalt = 0, altgr = 0; +static int lshift = 0, rshift = 0,/* lctrl = 0, rctrl = 0,*/ lalt = 0, altgr = 0, capslk = 0; extern int mouse_fd; extern int keyboard_fd; @@ -24,7 +24,7 @@ char keymap_amiga[256] = { /*00*/ 0x80, 0x45, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x41, 0x42, /*10*/ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x44, 0x63, 0x20, 0x21, /*20*/ 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x00, 0x60, 0x2B, 0x31, 0x32, 0x33, 0x34, -/*30*/ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x61, 0x5D, 0x64, 0x40, NONE, 0x50, 0x51, 0x52, 0x53, 0x54, +/*30*/ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x61, 0x5D, 0x64, 0x40, 0x62, 0x50, 0x51, 0x52, 0x53, 0x54, /*40*/ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5B, NONE, 0x3D, 0x3E, 0x3F, 0x4A, 0x2D, 0x2E, 0x2F, 0x5E, 0x1D, /*50*/ 0x1E, 0x1F, 0x0F, 0x3C, NONE, NONE, 0x30, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, /*60*/ 0x43, NONE, 0x5C, NONE, 0x65, NONE, 0x5F, 0x4C, 0x5A, 0x4F, 0x4E, NONE, 0x4D, NONE, 0x0D, 0x46, @@ -64,13 +64,15 @@ int handle_modifier(struct input_event *ev) { } *target_modifier = (ev->value == KEYPRESS_RELEASE) ? 0 : 1; return 1; - } - else { + } else if (ev->value == KEYPRESS_PRESS && ev->code == KEY_CAPSLOCK) { + capslk = !capslk; + return 1; + } else { return 0; } } -#define KEYCASE(a, b, c)case a: return (lshift || rshift) ? c : b; +#define KEYCASE(a, b, c)case a: return (((lshift || rshift) && !capslk) || (!(lshift || rshift) && capslk)) ? (c) : (b); /** * translates keycodes back into a simpler enumerable value for handling emulator command events @@ -187,6 +189,12 @@ int queue_keypress(uint8_t keycode, uint8_t event_type, uint8_t platform) { if (keymap[keycode] != NONE) { if (queued_keypresses < 255) { // printf("Keypress queued, matched %.2X to host key code %.2X\n", keycode, keymap[keycode]); + if (keycode == KEY_CAPSLOCK) { + if (event_type == KEYPRESS_RELEASE) { + return 0; + } + event_type = capslk; + } queued_keys[queue_output_pos] = keymap[keycode]; queued_events[queue_output_pos] = event_type; queue_output_pos++;