]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
DraCo updates
authorToni Wilen <twilen@winuae.net>
Thu, 4 Jan 2024 19:12:20 +0000 (21:12 +0200)
committerToni Wilen <twilen@winuae.net>
Thu, 4 Jan 2024 19:12:20 +0000 (21:12 +0200)
16 files changed:
cia.cpp
devices.cpp
draco.cpp
gfxboard.cpp
include/draco.h
include/x86.h
inputdevice.cpp
keybuf.cpp
newcpu.cpp
od-win32/winuae_msvc15/keyboard_at_draco.cpp [new file with mode: 0644]
od-win32/winuae_msvc15/winuae_msvc.vcxproj
od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters
pcem/mouse_serial.cpp
pcem/serial.cpp
rommgr.cpp
x86.cpp

diff --git a/cia.cpp b/cia.cpp
index 9ea46f522993a306b997ecee71d52e8a61fa3891..23d0a6d593f313aa11d66acdcb388d2bc389a28f 100644 (file)
--- a/cia.cpp
+++ b/cia.cpp
@@ -1161,7 +1161,7 @@ void keyboard_connected(bool connect)
 
 static void check_keyboard(void)
 {
-       if (currprefs.keyboard_connected) {
+       if (currprefs.keyboard_connected && currprefs.cs_compatible != CP_DRACO) {
                if ((keys_available() || kbstate < 3) && !kblostsynccnt ) {
                        switch (kbstate)
                        {
index aaf8444de1845de763e8d25d2bdba08a607d32b8..74635b16128115cb78a8701f014c71b2304007bd 100644 (file)
@@ -353,7 +353,7 @@ void virtualdevice_free(void)
        ethernet_enumerate_free();
        rtarea_free();
 #ifdef WITH_DRACO
-       draco_reset();
+       draco_free();
 #endif
        execute_device_items(device_leaves, device_leave_cnt);
 }
index 395f37602f08da7755bdd39076dfa5d7a622f0df..cdb2b661449e786ca969c29ecbc756346b3583b7 100644 (file)
--- a/draco.cpp
+++ b/draco.cpp
 #include "ncr_scsi.h"
 #include "draco.h"
 #include "zfile.h"
+#include "keybuf.h"
 
 static int maxcnt = 100;
 
+#define ONEWIRE_DEBUG 1
+#define KBD_DEBUG 1
 
 /*
        .asciz  "kbd/soft"      | 1: native keyboard, soft ints
@@ -133,8 +136,17 @@ void serial_reset();
 void serial_write(uint16_t addr, uint8_t val, void *p);
 uint8_t serial_read(uint16_t addr, void *p);
 void draco_serial_init(void **s1, void **s2);
+void mouse_serial_poll(int x, int y, int z, int b, void *p);
+void *mouse_serial_init_draco();
+
+void keyboard_at_write(uint8_t val, void *priv);
+uint8_t keyboard_at_read(uint16_t port, void *priv);
+void *draco_keyboard_init(void);
+void draco_key_process(uint16_t scan, int down);
+int draco_kbc_translate(uint8_t val);
 
 static void *draco_serial[2];
+static void *draco_mouse_base, *draco_keyboard;
 
 static uae_u8 draco_intena, draco_intpen, draco_svga_irq_state;
 static uae_u16 draco_timer, draco_timer_latch;
@@ -143,10 +155,17 @@ static bool draco_fdc_intpen;
 static uae_u8 draco_superio_cfg[16];
 static uae_s8 draco_superio_idx;
 static uae_u8 draco_reg[0x20];
+static int draco_watchdog;
+static int draco_scsi_intpen, draco_serial_intpen;
 
 static void draco_irq(void)
 {
        uae_u16 irq = 0;
+       if (draco_scsi_intpen) {
+               draco_intpen |= 2;
+       } else {
+               draco_intpen &= ~2;
+       }
        if (draco_intena & 1) {
                uae_u16 mask = draco_intena & draco_intpen;
                if (mask) {
@@ -166,13 +185,13 @@ static void draco_irq(void)
                if (draco_svga_irq_state) {
                        irq |= 0x0010; // INT3
                }
-               if (draco_fdc_intpen && (draco_reg[1] & DRCNTRL_FDCINTENA)) {
+               if ((draco_fdc_intpen || draco_serial_intpen) && (draco_reg[1] & DRCNTRL_FDCINTENA)) {
                        irq = 0x1000; // INT5
                }
                if ((draco_reg[7] & DRSTAT2_TMRINTENA) && (draco_reg[7] & DRSTAT2_TMRIRQPEN)) {
                        irq |= 1;
                }
-               if ((draco_reg[3] & DRSTAT_KBDRECV) && (draco_reg[1] & DRCNTRL_KBDINTENA)) {
+               if (draco_reg[3] & DRSTAT_KBDRECV) {
                        irq |= 1;
                }
        }
@@ -190,79 +209,136 @@ void draco_svga_irq(bool state)
        draco_irq();
 }
 
-static uae_u8 draco_kbd_state, draco_kbd_state2;
+static uae_u8 draco_kbd_state;
+static uae_s8 draco_kbd_state2, draco_kbd_poll;
 static uae_u16 draco_kbd_code;
-static int draco_kbd_poll;
 static uae_u8 draco_kbd_buffer[10];
 static uae_u8 draco_kbd_buffer_len;
+static uae_s8 draco_kdb_params;
+static uae_u16 draco_kbd_in_buffer[16];
+static int draco_kbd_in_buffer_len;
+
+static void draco_keyboard_reset(void)
+{
+       draco_kbd_buffer_len = 0;
+       draco_kbd_in_buffer_len = 0;
+       draco_kbd_state = 0;
+       draco_kbd_poll = 0;
+       draco_kbd_code = 0;
+       draco_kdb_params = 0;
+       draco_kbd_state2 = -1;
+}
 
-static uae_u8 draco_keyboard_read(uae_u8 v)
+static void draco_keyboard_read(void)
 {
-       if (draco_kbd_state2) {
-               draco_reg[3] &= ~DRSTAT_KBDCLKIN;
+       uae_u8 v = draco_reg[3];
+
+       if (draco_kbd_poll > 0) {
+               draco_kbd_poll--;
+               if (draco_kbd_poll == 0) {
+                       draco_reg[3] &= ~DRSTAT_KBDCLKIN;
+                       v &= ~DRSTAT_KBDCLKIN;
+                       draco_kbd_poll = -4;
+               }
+               draco_reg[3] = v;
+               return;
+       }
 
+       if (draco_kbd_poll < 0) {
                draco_kbd_poll++;
-               if (draco_kbd_state2 > 0 && draco_kbd_poll >= 4) {
-                       draco_reg[3] |= DRSTAT_KBDCLKIN;
+               if (draco_kbd_poll == 0) {
+                       draco_kbd_poll = 4;
+                       v |= DRSTAT_KBDCLKIN;
+                       uae_u16 bit = (draco_reg[1] & DRCNTRL_KBDDATOUT) ? 0x8000 : 0;
+#if KBD_DEBUG > 1
+                       write_log("draco keyboard got bit %d: %d\n", draco_kbd_state2, bit ? 1 : 0);
+#endif
                        draco_kbd_code >>= 1;
-                       draco_kbd_code |= (draco_reg[1] & DRCNTRL_KBDDATOUT) ? 0x8000 : 0;
+                       draco_kbd_code |= bit;
                        draco_kbd_state2++;
-                       draco_kbd_poll = 0;
+
+                       if (draco_kbd_state2 == 11) {
+                               draco_kbd_code >>= 5;
+                               draco_kbd_code &= 0xff;
+#if KBD_DEBUG
+                               write_log("draco->keyboard code %02x\n", draco_kbd_code);
+#endif
+                               draco_reg[3] = v;
+                               keyboard_at_write((uae_u8)draco_kbd_code, draco_keyboard);
+                               v = draco_reg[3];
+                       }
                }
        }
-       return v;
+
+       draco_reg[3] = v;
 }
+
+
 static void draco_keyboard_write(uae_u8 v)
 {
        v &= DRCNTRL_KBDDATOUT | DRCNTRL_KBDCLKOUT;
        if (v == draco_kbd_state) {
                return;
        }
+       if ((v & DRCNTRL_KBDDATOUT) != (draco_kbd_state & DRCNTRL_KBDDATOUT)) {
+#if KBD_DEBUG > 1
+               write_log("DRCNTRL_KBDDATOUT %d -> %d\n", (draco_kbd_state & DRCNTRL_KBDDATOUT) ? 1 : 0, (v & DRCNTRL_KBDDATOUT) ? 1 : 0);
+#endif
+       }
+       if ((v & DRCNTRL_KBDCLKOUT) != (draco_kbd_state & DRCNTRL_KBDCLKOUT)) {
+#if KBD_DEBUG > 1
+               write_log("DRCNTRL_KBDCLKOUT %d -> %d\n", (draco_kbd_state & DRCNTRL_KBDCLKOUT) ? 1 : 0, (v & DRCNTRL_KBDCLKOUT) ? 1 : 0);
+#endif
+       }
 
        // start receive
-       if ((v & DRCNTRL_KBDCLKOUT) && !(draco_kbd_state & DRCNTRL_KBDCLKOUT)) {
+       if (draco_kbd_state2 < 0 && (v & DRCNTRL_KBDCLKOUT) && !(draco_kbd_state & DRCNTRL_KBDCLKOUT)) {
                draco_reg[3] |= DRSTAT_KBDCLKIN;
                draco_kbd_code = 0;
-               draco_kbd_state2 = 1;
-               draco_kbd_poll = 0;
+               draco_kbd_state2 = 0;
+               draco_kbd_poll = 4;
        }
 
        draco_kbd_state = v;
 }
 
-static void draco_keyboard_done(void)
+static void draco_keyboard_send(void)
 {
-
-       if (draco_kbd_state2 == 12) {
-               draco_kbd_code >>= 5;
-               draco_kbd_code &= 0xff;
-               write_log("draco received keyboard data %04x\n", draco_kbd_code);
-               if (draco_kbd_code == 0xf2) {
-                       draco_kbd_buffer[0] = 0xab;
-                       draco_kbd_buffer[1] = 0x83;
-                       draco_kbd_buffer_len = 2;
+       if (draco_kbd_buffer_len > 0 && !(draco_reg[3] & DRSTAT_KBDRECV)) {
+               uae_u8 code = draco_kbd_buffer[0];
+               for (int i = 1; i < draco_kbd_buffer_len; i++) {
+                       draco_kbd_buffer[i - i] = draco_kbd_buffer[i];
                }
+               draco_kbd_buffer_len--;
+               draco_reg[5] = code;
+               draco_reg[3] |= DRSTAT_KBDRECV;
+#if KBD_DEBUG
+               write_log("keyboard->draco code %02x\n", code);
+#endif
+               draco_irq();
        }
+}
+
+static void draco_keyboard_done(void)
+{
+#if KBD_DEBUG > 1
+       write_log("draco keyboard interface reset\n");
+#endif
        draco_reg[3] &= ~DRSTAT_KBDCLKIN;
        draco_reg[3] &= ~DRSTAT_KBDRECV;
-       draco_kbd_state2 = 0;
+       draco_reg[1] &= ~DRCNTRL_KBDDATOUT;
+       draco_reg[1] &= ~DRCNTRL_KBDCLKOUT;
+       draco_kbd_state2 = -1;
        draco_kbd_poll = 0;
+       draco_keyboard_send();
 }
 
-static void draco_keyboard_send(void)
+void draco_kdb_queue_add(void *d, uint8_t val, int state)
 {
-       if (draco_kbd_buffer_len <= 0) {
-               return;
-       }
-       if (!(draco_reg[3] & DRSTAT_KBDRECV)) {
-               draco_kbd_buffer_len--;
-               uae_u8 code = draco_kbd_buffer[draco_kbd_buffer_len];
-               draco_reg[5] = code;
-               draco_reg[3] |= DRSTAT_KBDRECV;
-               draco_irq();
-       }
+       draco_kbd_buffer[draco_kbd_buffer_len++] = val;
 }
 
+
 static uae_u8 draco_1wire_data[40], draco_1wire_state, draco_1wire_dir;
 static uae_u8 draco_1wire_sram[512 + 32], draco_1wire_scratchpad[32 + 3], draco_1wire_rom[8];
 static uae_u8 draco_1wire_cmd, draco_1wire_bytes, draco_1wire_dat;
@@ -274,6 +350,8 @@ static bool draco_1wire_bit;
 #define DS_ROM_SEARCH           0xf0
 #define DS_ROM_SKIP             0xcc
 #define DS_ROM_READ             0x33
+
+#define DS_READ_MEMORY          0xf0
 #define DS_WRITE_SCRATCHPAD     0x0f
 #define DS_READ_SCRATCHPAD      0xaa
 #define DS_COPY_SCRATCHPAD      0x55
@@ -331,18 +409,20 @@ static void draco_1wire_set_bit(void)
        }
 }
 
-static uae_u8 draco_1wire_read(uae_u8 v)
+static void draco_1wire_read(void)
 {
+       uae_u8 v = draco_reg[3];
+
        if (draco_1wire_bit) {
-               draco_reg[3] |= DRSTAT_CLKDAT;
                v |= DRSTAT_CLKDAT;
        } else {
-               draco_reg[3] &= ~DRSTAT_CLKDAT;
                v &= ~DRSTAT_CLKDAT;
        }
 
-       if (draco_1wire_cnt == 8 && !(draco_reg[3] & DRSTAT_CLKBUSY)) {
+       if (draco_1wire_cnt == 8 && !(v & DRSTAT_CLKBUSY)) {
+#if ONEWIRE_DEBUG > 1
                write_log("draco read 1-wire SRAM byte %02x, %02x\n", draco_1wire_dat, draco_1wire_bytes);
+#endif
                draco_1wire_cnt = 0;
                draco_1wire_bytes++;
                if (draco_1wire_rom_offset >= 0) {
@@ -365,14 +445,14 @@ static uae_u8 draco_1wire_read(uae_u8 v)
                }
        }
        
-       if (draco_reg[3] & DRSTAT_CLKBUSY) {
+       if (v & DRSTAT_CLKBUSY) {
                draco_1wire_busycnt--;
                if (draco_1wire_busycnt < 0) {
-                       draco_reg[3] &= ~DRSTAT_CLKBUSY;
+                       v &= ~DRSTAT_CLKBUSY;
                }
        }
 
-       return v;
+       draco_reg[3] = v;
 }
 
 static void draco_1wire_busy(void)
@@ -410,22 +490,28 @@ static void draco_1wire_send(int bit)
                for (int i = sizeof(draco_1wire_data) - 1; i >= 1; i--) {
                        draco_1wire_data[i] = draco_1wire_data[i - 1];
                }
+#if ONEWIRE_DEBUG > 1
                write_log("draco received 1-wire byte %02x, cnt %02x\n", draco_1wire_data[0], draco_1wire_bytes);
+#endif
                draco_1wire_cnt = 0;
                draco_1wire_bytes++;
-               // read data command + 2 address bytes?
-               if (draco_1wire_cmd == DS_ROM_SEARCH && draco_1wire_data[3] == DS_ROM_SEARCH) {
+               // read data command + 2 address bytes
+               if (draco_1wire_cmd == DS_READ_MEMORY && draco_1wire_data[3] == DS_READ_MEMORY) {
                        draco_1wire_sram_offset = (draco_1wire_data[1] << 8) | draco_1wire_data[2];
                        draco_1wire_dir = 1;
                        draco_1wire_bytes = 0;
+#if ONEWIRE_DEBUG
                        write_log("draco received 1-wire SRAM read command, offset %04x\n", draco_1wire_sram_offset);
+#endif
                }
-               // write scratchpad + 2 address bytes?
+               // write scratchpad + 2 address bytes
                if (draco_1wire_cmd == DS_WRITE_SCRATCHPAD && draco_1wire_data[3] == DS_WRITE_SCRATCHPAD) {
                        draco_1wire_sram_offset = (draco_1wire_data[1] << 8) | draco_1wire_data[2];
                        draco_1wire_sram_offset_copy = draco_1wire_sram_offset;
                        memset(draco_1wire_scratchpad, 0, sizeof(draco_1wire_scratchpad));
+#if ONEWIRE_DEBUG
                        write_log("draco received 1-wire SRAM scratchpad write command, offset %04x\n", draco_1wire_sram_offset);
+#endif
                }
                // read scratchpad
                if (draco_1wire_cmd == DS_READ_SCRATCHPAD) {
@@ -433,7 +519,9 @@ static void draco_1wire_send(int bit)
                        draco_1wire_dir = 1;
                        draco_1wire_bytes = 0;
                        draco_1wire_set_bit();
+#if ONEWIRE_DEBUG
                        write_log("draco received 1-wire SRAM scratchpad read command\n");
+#endif
                }
                // copy scratchpad
                if (draco_1wire_cmd == DS_COPY_SCRATCHPAD && draco_1wire_data[4] == DS_COPY_SCRATCHPAD) {
@@ -444,10 +532,14 @@ static void draco_1wire_send(int bit)
                                draco_1wire_data[3] == draco_1wire_scratchpad[0]) {
                                int start = draco_1wire_sram_offset_copy & 31;
                                int offset = draco_1wire_sram_offset_copy & ~31;
+#if ONEWIRE_DEBUG
                                write_log("draco received 1-wire SRAM scratchpad copy command, accepted\n");
+#endif
                                for (int i = 0; i < 32; i++) {
                                        draco_1wire_sram[offset + start] = draco_1wire_scratchpad[start + 3];
+#if ONEWIRE_DEBUG > 1
                                        write_log("draco 1-wire SRAM scratchpad copy %02x -> %04x\n", draco_1wire_sram[offset + start], offset + start);
+#endif
                                        if (start == (draco_1wire_scratchpad[2] & 31)) {
                                                break;
                                        }
@@ -459,7 +551,9 @@ static void draco_1wire_send(int bit)
                                draco_1wire_busy();
                                draco_1wire_bit = 0;
                        } else {
+#if ONEWIRE_DEBUG
                                write_log("draco received 1-wire SRAM scratchpad copy command, rejected\n");
+#endif
                                draco_1wire_busy();
                        }
                }
@@ -485,7 +579,9 @@ static void draco_1wire_reset(void)
                        } else if (len < 32) {
                                draco_1wire_scratchpad[2] |= 0x20;
                        }
+#if ONEWIRE_DEBUG
                        write_log("draco received 1-wire SRAM scratchpad write, %d bytes received\n", len);
+#endif
                }
        }
 
@@ -496,7 +592,9 @@ static void draco_1wire_reset(void)
        draco_1wire_bytes = 0;
        draco_1wire_sram_offset = -1;
        draco_1wire_rom_offset = 0;
+#if ONEWIRE_DEBUG
        write_log("draco 1-wire reset\n");
+#endif
 }
 
 static uae_u32 REGPARAM2 draco_lget(uaecptr addr)
@@ -505,12 +603,13 @@ static uae_u32 REGPARAM2 draco_lget(uaecptr addr)
 
        if ((addr & 0x07c00000) == 0x04000000) {
 
-               write_log("draco scsi lput %08x %08x\n", addr, l);
+               //write_log("draco scsi lput %08x %08x\n", addr, l);
                int reg = addr & 0xffff;
-               l = cpuboard_ncr710_io_bget(reg + 0) << 24;
-               l |= cpuboard_ncr710_io_bget(reg + 1) << 16;
-               l |= cpuboard_ncr710_io_bget(reg + 2) << 8;
                l |= cpuboard_ncr710_io_bget(reg + 3) << 0;
+               l |= cpuboard_ncr710_io_bget(reg + 2) << 8;
+               l |= cpuboard_ncr710_io_bget(reg + 1) << 16;
+               l |= cpuboard_ncr710_io_bget(reg + 0) << 24;
+
        } else {
                write_log(_T("draco_lget %08x %08x\n"), addr, M68K_GETPC);
        }
@@ -524,6 +623,12 @@ static uae_u32 REGPARAM2 draco_wget(uaecptr addr)
        return 0;
 }
 
+void draco_bustimeout(uaecptr addr)
+{
+       write_log("draco bus timeout %08x\n", addr);
+       draco_reg[3] |= DRSTAT_BUSTIMO;
+}
+
 static uae_u32 REGPARAM2 draco_bget(uaecptr addr)
 {
        uae_u8 v = 0;
@@ -534,8 +639,7 @@ static uae_u32 REGPARAM2 draco_bget(uaecptr addr)
        }
 
        if (addr >= 0x20000000) {
-               write_log("draco bus timeout %08x\n", addr);
-               draco_reg[3] |= DRSTAT_BUSTIMO;
+               draco_bustimeout(addr);
                return 0;
        }
 
@@ -543,7 +647,7 @@ static uae_u32 REGPARAM2 draco_bget(uaecptr addr)
 
                int reg = addr & 0xffff;
                v = cpuboard_ncr710_io_bget(reg);
-               write_log("draco scsi read %08x\n", addr);
+//             write_log("draco scsi read %08x\n", addr);
 
        } else if ((addr & 0x07c00000) == 0x02400000) {
 
@@ -597,6 +701,10 @@ static uae_u32 REGPARAM2 draco_bget(uaecptr addr)
                                v = serial_read(reg, draco_serial[1]);
                                break;
 
+                       case 0x278:
+                               // parallel
+                               break;
+
                        default:
                                write_log("draco superio read %04x = %02x\n", (addr >> 2) & 0xfff, v);
                                break;
@@ -606,16 +714,19 @@ static uae_u32 REGPARAM2 draco_bget(uaecptr addr)
        } else if ((addr & 0x07c00000) == 0x02000000) {
 
                // io
-               if ((addr & 0xffffff) > 0x1f)
-                       write_log("x");
-
                int reg = addr & 0x1f;
                v = draco_reg[reg];
                switch(reg)
                {
                case 3:
-                       v = draco_keyboard_read(v);
-                       v = draco_1wire_read(v);
+                       draco_keyboard_read();
+                       draco_1wire_read();
+                       v = draco_reg[reg];
+                       break;
+               case 5:
+#if KBD_DEBUG > 1
+                       write_log("draco keyboard scan code read %02x\n", v);
+#endif
                        break;
                case 9:
                        v = 4;
@@ -665,12 +776,12 @@ static void REGPARAM2 draco_lput(uaecptr addr, uae_u32 l)
 {
        if ((addr & 0x07c00000) == 0x04000000) {
 
-               write_log("draco scsi lput %08x %08x\n", addr, l);
+               //write_log("draco scsi lput %08x %08x\n", addr, l);
                int reg = addr & 0xffff;
-               cpuboard_ncr710_io_bput(reg + 0, l >> 24);
+               cpuboard_ncr710_io_bput(reg + 3, l >> 0);
+               cpuboard_ncr710_io_bput(reg + 2, l >> 8);
                cpuboard_ncr710_io_bput(reg + 1, l >> 16);
-               cpuboard_ncr710_io_bput(reg + 2, l >>  8);
-               cpuboard_ncr710_io_bput(reg + 3, l >>  0);
+               cpuboard_ncr710_io_bput(reg + 0, l >> 24);
 
        } else {
 
@@ -696,7 +807,7 @@ static void REGPARAM2 draco_bput(uaecptr addr, uae_u32 b)
 
        if ((addr & 0x07c00000) == 0x04000000) {
 
-               write_log("draco scsi put %08x\n", addr);
+//             write_log("draco scsi put %08x\n", addr);
                int reg = addr & 0xffff;
                cpuboard_ncr710_io_bput(reg, b);
 
@@ -755,6 +866,11 @@ static void REGPARAM2 draco_bput(uaecptr addr, uae_u32 b)
                        case 0x2ff:
                                serial_write(reg, b, draco_serial[1]);
                                break;
+
+                       case 0x278:
+                               // parallel
+                               break;
+
                        default:
                                write_log("draco superio write %04x = %02x\n", (addr >> 2) & 0xfff, b);
                                break;
@@ -771,12 +887,14 @@ static void REGPARAM2 draco_bput(uaecptr addr, uae_u32 b)
                int reg = addr & 0x1f;
                uae_u8 oldval = draco_reg[reg];
                draco_reg[reg] = b;
-               //draco_reg[1] |= DRCNTRL_FDCINTENA;
 
                //write_log(_T("draco_bput %08x %02x %08x\n"), addr, b & 0xff, M68K_GETPC);
                switch(reg)
                {
                        case 1:
+                               if (b & DRCNTRL_WDOGDAT) {
+                                       draco_watchdog = 0;
+                               }
                                draco_irq();
                                draco_keyboard_write(b);
                                break;
@@ -868,9 +986,29 @@ void casablanca_map_overlay(void)
        map_banks(&draco_bank, 0x03000000 >> 16, 0x01000000 >> 16, 0);
 }
 
+void draco_ext_interrupt(bool i6)
+{
+       if (i6) {
+               draco_intpen |= 8;
+       } else {
+               draco_intpen |= 4;
+       }
+       draco_irq();
+}
+
+void draco_keycode(uae_u8 scancode, uae_u8 state)
+{
+       if (currprefs.cs_compatible == CP_DRACO) {
+               draco_kbd_in_buffer[draco_kbd_in_buffer_len++] = scancode | (state ? 0x8000 : 0x00);
+               if (draco_kbd_buffer_len == 0 && !(draco_reg[3] & DRSTAT_KBDRECV)) {
+                       draco_key_process(scancode, state);
+               }
+       }
+}
+
 static void draco_hsync(void)
 {
-       uae_u16 tm = 1, ot;
+       uae_u16 tm = 5, ot;
        static int hcnt;
 
        ot = draco_timer;
@@ -886,31 +1024,49 @@ static void draco_hsync(void)
        if (draco_kbd_buffer_len > 0) {
                draco_keyboard_send();
        }
+
+       if (draco_kbd_buffer_len == 0 && draco_kbd_in_buffer_len  > 0 && !(draco_reg[3] & DRSTAT_KBDRECV)) {
+               uae_u8 code = (uae_u8)draco_kbd_in_buffer[0];
+               uae_u8 state = (draco_kbd_in_buffer[0] & 0x8000) ? 1 : 0;
+               for (int i = 1; i < draco_kbd_in_buffer_len; i++) {
+                       draco_kbd_in_buffer[i - i] = draco_kbd_in_buffer[i];
+               }
+               draco_kbd_in_buffer_len--;
+               draco_key_process(code, state);
+       }
+
        hcnt++;
        if (hcnt >= 60) {
                draco_1wire_rtc_count();
                hcnt = 0;
        }
+
+       draco_watchdog++;
+       if (0 && draco_watchdog > 312 * 50) {
+               IRQ_forced(7, -1);
+               activate_debugger();
+               draco_watchdog = 0;
+       }
 }
 
 void draco_set_scsi_irq(int id, int level)
 {
-       if (level) {
-               draco_intpen |= 2;
-       } else {
-               draco_intpen &= ~2;
-       }
+       draco_scsi_intpen = level;
        draco_irq();
 }
 
 
 static void x86_irq(int irq, bool state)
 {
-       draco_fdc_intpen = state;
+       if (irq == 4) {
+               draco_serial_intpen = state;
+       } else {
+               draco_fdc_intpen = state;
+       }
        draco_irq();
 }
 
-void draco_reset(void)
+void draco_free(void)
 {
        TCHAR path[MAX_DPATH];
        cfgfile_resolve_path_out_load(currprefs.flashfile, path, MAX_DPATH, PATH_ROM);
@@ -922,13 +1078,17 @@ void draco_reset(void)
                zfile_fwrite(draco_1wire_sram, sizeof(draco_1wire_sram), 1, draco_flashfile);
                zfile_fclose(draco_flashfile);
        }
+       xfree(draco_mouse_base);
+       draco_mouse_base = NULL;
 }
 
-void draco_init(void)
+void draco_reset(int hardreset)
 {
-       if (currprefs.cs_compatible != CP_DRACO) {
-               return;
-       }
+
+       x86_initfloppy(x86_irq);
+       draco_serial_init(&draco_serial[0], &draco_serial[1]);
+       draco_mouse_base = mouse_serial_init_draco();
+       draco_keyboard = draco_keyboard_init();
 
        draco_intena = 0;
        draco_intpen = 0;
@@ -938,8 +1098,9 @@ void draco_init(void)
        draco_svga_irq_state = 0;
        draco_fdc_intpen = false;
        draco_superio_idx = -2;
-       draco_kbd_buffer_len = 0;
-       draco_kbd_state2 = 0;
+       draco_watchdog = 0;
+       draco_scsi_intpen = 0;
+       draco_serial_intpen = 0;
        memset(draco_superio_cfg, 0, sizeof(draco_superio_cfg));
        draco_superio_cfg[0] = 0x3b;
        draco_superio_cfg[1] = 0x9f;
@@ -949,7 +1110,9 @@ void draco_init(void)
        draco_superio_cfg[13] = 0x65;
        draco_superio_cfg[14] = 1;
        memset(draco_reg, 0, sizeof(draco_reg));
+       draco_reg[1] = DRCNTRL_FDCINTENA | DRCNTRL_KBDINTENA;
 
+       draco_keyboard_reset();
        draco_1wire_rtc_validate();
        draco_1wire_rom[0] = 0x04;
        draco_1wire_rom[1] = 1;
@@ -960,6 +1123,14 @@ void draco_init(void)
        draco_1wire_rom[6] = 6;
        draco_1wire_rom[7] = 0xaa;
 
+}
+
+void draco_init(void)
+{
+       if (currprefs.cs_compatible != CP_DRACO) {
+               return;
+       }
+
        TCHAR path[MAX_DPATH];
        cfgfile_resolve_path_out_load(currprefs.flashfile, path, MAX_DPATH, PATH_ROM);
        struct zfile *draco_flashfile = zfile_fopen(path, _T("rb"), ZFD_NORMAL);
@@ -970,11 +1141,22 @@ void draco_init(void)
                zfile_fclose(draco_flashfile);
        }
 
-       x86_initfloppy(x86_irq);
-       draco_serial_init(&draco_serial[0], &draco_serial[1]);
+       draco_reset(1);
 
        device_add_rethink(draco_irq);
        device_add_hsync(draco_hsync);
+       device_add_reset(draco_reset);
+}
+
+bool draco_mouse(int port, int x, int y, int z, int b)
+{
+       if (currprefs.cs_compatible == CP_DRACO) {
+               if (b < 0)
+                       return true;
+               mouse_serial_poll(x, y, z, b, draco_mouse_base);
+               return true;
+       }
+       return false;
 }
 
 void draco_map_overlay(void)
index f2cd6b0e447c34ecec262561941582877ca0fafc..ff2353c8ee0731caefcaa59b3eecd75348ebca1d 100644 (file)
@@ -57,6 +57,7 @@ static bool memlogw = true;
 #include "pcem/pcemglue.h"
 #include "qemuvga/qemuuaeglue.h"
 #include "qemuvga/vga.h"
+#include "draco.h"
 
 extern void put_io_pcem(uaecptr, uae_u32, int);
 extern uae_u32 get_io_pcem(uaecptr, int);
@@ -5547,10 +5548,12 @@ static void special_pcem_put(uaecptr addr, uae_u32 v, int size)
 
        if (boardnum == GFXBOARD_ID_ALTAIS_Z3) {
 
-               addr &= 0xffff;
-               if (addr >= 0x40) {
-                       gfxboard_bput_io_swap_pcem(addr, v);
+               if ((addr & 0xffff) < 0x100) {
+                       draco_bustimeout(addr);
+                       return;
                }
+               addr &= 0xffff;
+               gfxboard_bput_io_swap_pcem(addr, v);
 
        } else if (boardnum == GFXBOARD_ID_RETINA_Z2) {
        
@@ -5900,28 +5903,12 @@ static uae_u32 special_pcem_get(uaecptr addr, int size)
 
        if (boardnum == GFXBOARD_ID_ALTAIS_Z3) {
 
-               addr &= 0xffff;
-               if (addr >= 0x40) {
-                       v = gfxboard_bget_io_swap_pcem(addr);
-               } else {
-                       switch(addr)
-                       {
-                               case 3:
-                                       v = 2 + 4 + 8;
-                                       break;
-                               case 7:
-                                       v = 19;
-                                       break;
-                               case 11:
-                                       v = 0x47;
-                                       break;
-                               case 15:
-                                       v = 0x54;
-                                       break;
-
-
-                       }
+               if ((addr & 0xffff) < 0x100) {
+                       draco_bustimeout(addr);
+                       return v;
                }
+               addr &= 0xffff;
+               v = gfxboard_bget_io_swap_pcem(addr);
 
        } else if (boardnum == GFXBOARD_ID_RETINA_Z2) {
 
index d98e7f7763e30eb4b03cd414fddc8eb42c33cfa6..ce98ffa005025c2fa1f48feb973122e64c26a1cc 100644 (file)
@@ -2,5 +2,8 @@
 void casablanca_map_overlay(void);
 void draco_map_overlay(void);
 void draco_init(void);
-void draco_reset(void);
-
+void draco_free(void);
+bool draco_mouse(int port, int x, int y, int z, int b);
+void draco_bustimeout(uaecptr addr);
+void draco_ext_interrupt(bool);
+void draco_keycode(uae_u8 scancode, uae_u8 state);
index ee2ba110353f680409f55549199b52f81b0af186..d153e22811fabdacc605c7a1a4d5b99ebf352ec6 100644 (file)
@@ -9,7 +9,7 @@ bool a2386_init(struct autoconfig_info *aci);
 bool isa_expansion_init(struct autoconfig_info *aci);
 void x86_bridge_sync_change(void);
 void x86_update_sound(float);
-void x86_mouse(int port, int x, int y, int z, int b);
+bool x86_mouse(int port, int x, int y, int z, int b);
 
 #define X86_STATE_INACTIVE 0
 #define X86_STATE_STOP 1
index ec30ab1ae20eec7adc7f93dc37dfa622e3d45e52..0012dfe11620a30074f912eedfc8a3f9eaf06278 100644 (file)
@@ -50,6 +50,7 @@
 #include "cia.h"
 #include "autoconf.h"
 #include "x86.h"
+#include "draco.h"
 #ifdef RETROPLATFORM
 #include "rp.h"
 #endif
@@ -3393,9 +3394,17 @@ static int getvelocity (int num, int subnum, int pct)
 static void mouseupdate (int pct, bool vsync)
 {
        int max = 120;
+       bool pcmouse = false;
        static int mxd, myd;
 
        if (vsync) {
+
+               if (x86_mouse(0, 0, 0, 0, -1) || draco_mouse(0, 0, 0, 0, -1)) {
+                       pcmouse = true;
+                       pct = 1000;
+               }
+
+
                if (mxd < 0) {
                        if (mouseedge_x > 0)
                                mouseedge_x = 0;
@@ -3473,19 +3482,24 @@ static void mouseupdate (int pct, bool vsync)
                        if (!mouse_deltanoreset[i][2])
                                mouse_delta[i][2] = 0;
 
-                       if (getbuttonstate(i, JOYBUTTON_1))
-                               pc_mouse_buttons[i] |= 1;
-                       else
-                               pc_mouse_buttons[i] &= ~1;
-                       if (getbuttonstate(i, JOYBUTTON_2))
-                               pc_mouse_buttons[i] |= 2;
-                       else
-                               pc_mouse_buttons[i] &= ~2;
-                       if (getbuttonstate(i, JOYBUTTON_3))
-                               pc_mouse_buttons[i] |= 4;
-                       else
-                               pc_mouse_buttons[i] &= ~4;
-                       x86_mouse(i, v1, v2, v3, pc_mouse_buttons[i]);
+                       if (pcmouse) {
+                               if (getbuttonstate(i, JOYBUTTON_1))
+                                       pc_mouse_buttons[i] |= 1;
+                               else
+                                       pc_mouse_buttons[i] &= ~1;
+                               if (getbuttonstate(i, JOYBUTTON_2))
+                                       pc_mouse_buttons[i] |= 2;
+                               else
+                                       pc_mouse_buttons[i] &= ~2;
+                               if (getbuttonstate(i, JOYBUTTON_3))
+                                       pc_mouse_buttons[i] |= 4;
+                               else
+                                       pc_mouse_buttons[i] &= ~4;
+
+                               x86_mouse(0, v1, v2, v3, pc_mouse_buttons[i]);
+                               draco_mouse(0, v1, v2, v3, pc_mouse_buttons[i]);
+                       }
+
 
 #if OUTPUTDEBUG
                        if (v1 || v2) {
index 9f6725bcad88612637e27e6accefad4628e65ce8..b98bb0878b5dc8429db57a30ed6b1069b2383a72 100644 (file)
@@ -295,6 +295,11 @@ int record_key_direct(int kc, bool direct)
        int kpb_next = kpb_first + 1;
        int kcd = (kc << 7) | (kc >> 1);
 
+       if (currprefs.cs_compatible == CP_DRACO) {
+               inputdevice_draco_key(kc);
+               return 1;
+       }
+
        if (!direct) {
                if (key_swap_hack2) {
                        // $0D <> $0C
index c1b5685ff226f1ddc57024317f9d68473f25a43b..dde2bbfaf0d4c979846cb230594452335c8bff0f 100644 (file)
@@ -52,6 +52,7 @@
 #include "x86.h"
 #include "bsdsocket.h"
 #include "devices.h"
+#include "draco.h"
 #ifdef JIT
 #include "jit/compemu.h"
 #include <signal.h>
@@ -4274,12 +4275,16 @@ void safe_interrupt_set(int num, int id, bool i6)
                atomic_or(p, 1 << id);
                atomic_or(&uae_interrupt, 1);
        } else {
-               int inum = i6 ? 13 : 3;
-               uae_u16 v = 1 << inum;
-               if (currprefs.cpu_cycle_exact || currprefs.cpu_compatible) {
-                       INTREQ_INT(inum, 0);
-               } else if (!(intreq & v)) {
-                       INTREQ_0(0x8000 | v);
+               if (currprefs.cs_compatible == CP_DRACO) {
+                       draco_ext_interrupt(i6);
+               } else {
+                       int inum = i6 ? 13 : 3;
+                       uae_u16 v = 1 << inum;
+                       if (currprefs.cpu_cycle_exact || currprefs.cpu_compatible) {
+                               INTREQ_INT(inum, 0);
+                       } else if (!(intreq & v)) {
+                               INTREQ_0(0x8000 | v);
+                       }
                }
        }
 }
diff --git a/od-win32/winuae_msvc15/keyboard_at_draco.cpp b/od-win32/winuae_msvc15/keyboard_at_draco.cpp
new file mode 100644 (file)
index 0000000..176ef76
--- /dev/null
@@ -0,0 +1,1160 @@
+/*
+ * x86box at keyboard and other stuff mixed and patched here for quick DraCo keyboard emulation..
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <wchar.h>
+#define HAVE_STDARG_H
+
+#define STATE_SHIFT_MASK 0x22
+#define STATE_RSHIFT     0x20
+#define STATE_LSHIFT     0x02
+
+#define FAKE_LSHIFT_ON   0x100
+#define FAKE_LSHIFT_OFF  0x101
+#define LSHIFT_ON        0x102
+#define LSHIFT_OFF       0x103
+#define RSHIFT_ON        0x104
+#define RSHIFT_OFF       0x105
+
+ /* Global keyboard mode:
+    Bits 0 - 1 = scan code set. */
+uint8_t keyboard_mode = 0x02;
+
+void draco_kdb_queue_add(void *d, uint8_t val, int state);
+
+void kbc_at_dev_reset(void *d, int r)
+{
+}
+void keyboard_at_log(const char *txt, ...)
+{
+}
+void fatalx(const char *txt, ...)
+{
+}
+
+enum {
+    DEV_STATE_MAIN_1 = 0,
+    DEV_STATE_MAIN_OUT = 1,
+    DEV_STATE_MAIN_2 = 2,
+    DEV_STATE_MAIN_CMD = 3,
+    DEV_STATE_MAIN_WANT_IN = 4,
+    DEV_STATE_MAIN_IN = 5,
+    DEV_STATE_EXECUTE_BAT = 6,
+    DEV_STATE_MAIN_WANT_EXECUTE_BAT = 7
+};
+
+#define FLAG_PS2       0x08  /* dev is AT or PS/2 */
+#define FLAG_AT        0x00  /* dev is AT or PS/2 */
+#define FLAG_TYPE_MASK 0x07  /* mask for type     */
+
+#define FIFO_SIZE      16
+
+enum {
+    KBD_84_KEY = 0,
+    KBD_101_KEY,
+    KBD_102_KEY,
+    KBD_JIS,
+    KBD_KOREAN
+};
+
+#define FLAG_ENABLED 0x10  /* dev is enabled for use */
+#define FLAG_CTRLDAT 0x08  /* ctrl or data mode */
+
+static int keyboard_scan;
+
+typedef struct atkbc_dev_t {
+    const char *name; /* name of this device */
+
+    uint8_t type;
+    uint8_t command;
+    uint8_t last_scan_code;
+    uint8_t state;
+    uint8_t resolution;
+    uint8_t rate;
+    uint8_t cmd_queue_start;
+    uint8_t cmd_queue_end;
+    uint8_t queue_start;
+    uint8_t queue_end;
+
+    uint16_t flags;
+
+    /* Internal FIFO, not present on real devices, needed for commands that
+       output multiple bytes. */
+    uint8_t cmd_queue[16];
+
+    uint8_t queue[64];
+
+    int     fifo_mask;
+    int     mode;
+    int     x;
+    int     y;
+    int     z;
+    int     b;
+
+    int *scan;
+
+    void    (*process_cmd)(void *priv);
+    void    (*execute_bat)(void *priv);
+
+    void *port;
+
+} atkbc_dev_t;
+
+static atkbc_dev_t draco_kbd;
+static atkbc_dev_t *SavedKbd = &draco_kbd;
+
+typedef struct scancode {
+    const uint8_t mk[4];
+    const uint8_t brk[4];
+} scancode;
+
+static scancode *scan_table; /* scancode table for keyboard */
+
+static uint8_t caps_lock = 0;
+static uint8_t num_lock = 0;
+static uint8_t scroll_lock = 0;
+static uint8_t shift = 0;
+
+
+/* Non - translated to translated scan codes. */
+static const uint8_t nont_to_t[256] = {
+    0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
+    0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
+    0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
+    0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
+    0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
+    0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
+    0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
+    0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
+    0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
+    0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
+    0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
+    0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
+    0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
+    0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
+    0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
+    0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
+    0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static int dev_sc_or;
+
+int draco_kbc_translate(uint8_t val)
+{
+    int      translate = 1;
+    int      ret = -1;
+
+    /* Allow for scan code translation. */
+    if (translate && (val == 0xf0)) {
+        dev_sc_or = 0x80;
+        return ret;
+    }
+
+    /* Skip break code if translated make code has bit 7 set. */
+    if (translate && (dev_sc_or == 0x80) && (nont_to_t[val] & 0x80)) {
+        dev_sc_or = 0;
+        return ret;
+    }
+
+    ret = translate ? (nont_to_t[val] | dev_sc_or) : val;
+
+    if (dev_sc_or == 0x80)
+        dev_sc_or = 0;
+
+    return ret;
+}
+
+static void kbc_at_dev_queue_add(void *d, uint8_t val, int state)
+{
+    if (keyboard_mode == 3) {
+        //val = draco_kbc_translate(val);
+    }
+    draco_kdb_queue_add(d, val, state);
+}
+
+
+void
+keyboard_set_table(const scancode *ptr)
+{
+    scan_table = (scancode *)ptr;
+}
+
+
+const uint8_t id_bytes[16][4] = { { 0x00, 0x00, 0x00, 0x00 },    /* AT 84-key */
+                                  { 0x00, 0x00, 0x00, 0x00 },    /* AT 101/102/106-key */
+                                  { 0x00, 0x00, 0x00, 0x00 },
+                                  { 0x00, 0x00, 0x00, 0x00 },
+                                  { 0x00, 0x00, 0x00, 0x00 },    /* AT Korean */
+                                  { 0x00, 0x00, 0x00, 0x00 },
+                                  { 0x00, 0x00, 0x00, 0x00 },
+                                  { 0x00, 0x00, 0x00, 0x00 },
+                                  { 0x00, 0x00, 0x00, 0x00 },
+                                  { 0x83, 0xab, 0x00, 0x00 },    /* PS/2 101-key */
+                                  { 0x83, 0xab, 0x00, 0x00 },    /* PS/2 102-key */
+                                  { 0xab, 0x90, 0x00, 0x00 },    /* PS/2 106-key JIS */
+    /* Japanese keyboard ID - TODO: Find the actual Korean one. */
+    { 0xab, 0x90, 0x00, 0x00 },    /* PS/2 Korean */
+    { 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00 } };
+
+/* Global keyboard flags for scan code set 3:
+   bit 0 = repeat, bit 1 = makes break code? */
+uint8_t keyboard_set3_flags[512];
+uint8_t keyboard_set3_all_repeat;
+uint8_t keyboard_set3_all_break;
+
+static uint8_t     inv_cmd_response = 0xfa;
+
+static const scancode scancode_set1[512] = {
+    // clang-format off
+      { {          0},{               0} }, { {     0x01,0},{          0x81,0} }, { {     0x02,0},{          0x82,0} }, { {     0x03,0},{          0x83,0} },        /*000*/
+      { {     0x04,0},{          0x84,0} }, { {     0x05,0},{          0x85,0} }, { {     0x06,0},{          0x86,0} }, { {     0x07,0},{          0x87,0} },        /*004*/
+      { {     0x08,0},{          0x88,0} }, { {     0x09,0},{          0x89,0} }, { {     0x0a,0},{          0x8a,0} }, { {     0x0b,0},{          0x8b,0} },        /*008*/
+      { {     0x0c,0},{          0x8c,0} }, { {     0x0d,0},{          0x8d,0} }, { {     0x0e,0},{          0x8e,0} }, { {     0x0f,0},{          0x8f,0} },        /*00c*/
+      { {     0x10,0},{          0x90,0} }, { {     0x11,0},{          0x91,0} }, { {     0x12,0},{          0x92,0} }, { {     0x13,0},{          0x93,0} },        /*010*/
+      { {     0x14,0},{          0x94,0} }, { {     0x15,0},{          0x95,0} }, { {     0x16,0},{          0x96,0} }, { {     0x17,0},{          0x97,0} },        /*014*/
+      { {     0x18,0},{          0x98,0} }, { {     0x19,0},{          0x99,0} }, { {     0x1a,0},{          0x9a,0} }, { {     0x1b,0},{          0x9b,0} },        /*018*/
+      { {     0x1c,0},{          0x9c,0} }, { {     0x1d,0},{          0x9d,0} }, { {     0x1e,0},{          0x9e,0} }, { {     0x1f,0},{          0x9f,0} },        /*01c*/
+      { {     0x20,0},{          0xa0,0} }, { {     0x21,0},{          0xa1,0} }, { {     0x22,0},{          0xa2,0} }, { {     0x23,0},{          0xa3,0} },        /*020*/
+      { {     0x24,0},{          0xa4,0} }, { {     0x25,0},{          0xa5,0} }, { {     0x26,0},{          0xa6,0} }, { {     0x27,0},{          0xa7,0} },        /*024*/
+      { {     0x28,0},{          0xa8,0} }, { {     0x29,0},{          0xa9,0} }, { {     0x2a,0},{          0xaa,0} }, { {     0x2b,0},{          0xab,0} },        /*028*/
+      { {     0x2c,0},{          0xac,0} }, { {     0x2d,0},{          0xad,0} }, { {     0x2e,0},{          0xae,0} }, { {     0x2f,0},{          0xaf,0} },        /*02c*/
+      { {     0x30,0},{          0xb0,0} }, { {     0x31,0},{          0xb1,0} }, { {     0x32,0},{          0xb2,0} }, { {     0x33,0},{          0xb3,0} },        /*030*/
+      { {     0x34,0},{          0xb4,0} }, { {     0x35,0},{          0xb5,0} }, { {     0x36,0},{          0xb6,0} }, { {     0x37,0},{          0xb7,0} },        /*034*/
+      { {     0x38,0},{          0xb8,0} }, { {     0x39,0},{          0xb9,0} }, { {     0x3a,0},{          0xba,0} }, { {     0x3b,0},{          0xbb,0} },        /*038*/
+      { {     0x3c,0},{          0xbc,0} }, { {     0x3d,0},{          0xbd,0} }, { {     0x3e,0},{          0xbe,0} }, { {     0x3f,0},{          0xbf,0} },        /*03c*/
+      { {     0x40,0},{          0xc0,0} }, { {     0x41,0},{          0xc1,0} }, { {     0x42,0},{          0xc2,0} }, { {     0x43,0},{          0xc3,0} },        /*040*/
+      { {     0x44,0},{          0xc4,0} }, { {     0x45,0},{          0xc5,0} }, { {     0x46,0},{          0xc6,0} }, { {     0x47,0},{          0xc7,0} },        /*044*/
+      { {     0x48,0},{          0xc8,0} }, { {     0x49,0},{          0xc9,0} }, { {     0x4a,0},{          0xca,0} }, { {     0x4b,0},{          0xcb,0} },        /*048*/
+      { {     0x4c,0},{          0xcc,0} }, { {     0x4d,0},{          0xcd,0} }, { {     0x4e,0},{          0xce,0} }, { {     0x4f,0},{          0xcf,0} },        /*04c*/
+      { {     0x50,0},{          0xd0,0} }, { {     0x51,0},{          0xd1,0} }, { {     0x52,0},{          0xd2,0} }, { {     0x53,0},{          0xd3,0} },        /*050*/
+      { {     0x54,0},{          0xd4,0} }, { {     0x55,0},{          0xd5,0} }, { {     0x56,0},{          0xd6,0} }, { {     0x57,0},{          0xd7,0} },        /*054*/
+      { {     0x58,0},{          0xd8,0} }, { {     0x59,0},{          0xd9,0} }, { {     0x5a,0},{          0xda,0} }, { {     0x5b,0},{          0xdb,0} },        /*058*/
+      { {     0x5c,0},{          0xdc,0} }, { {     0x5d,0},{          0xdd,0} }, { {     0x5e,0},{          0xde,0} }, { {     0x5f,0},{          0xdf,0} },        /*05c*/
+      { {     0x60,0},{          0xe0,0} }, { {     0x61,0},{          0xe1,0} }, { {     0x62,0},{          0xe2,0} }, { {     0x63,0},{          0xe3,0} },        /*060*/
+      { {     0x64,0},{          0xe4,0} }, { {     0x65,0},{          0xe5,0} }, { {     0x66,0},{          0xe6,0} }, { {     0x67,0},{          0xe7,0} },        /*064*/
+      { {     0x68,0},{          0xe8,0} }, { {     0x69,0},{          0xe9,0} }, { {     0x6a,0},{          0xea,0} }, { {     0x6b,0},{          0xeb,0} },        /*068*/
+      { {     0x6c,0},{          0xec,0} }, { {     0x6d,0},{          0xed,0} }, { {     0x6e,0},{          0xee,0} }, { {     0x6f,0},{          0xef,0} },        /*06c*/
+      { {     0x70,0},{          0xf0,0} }, { {     0x71,0},{          0xf1,0} }, { {     0x72,0},{          0xf2,0} }, { {     0x73,0},{          0xf3,0} },        /*070*/
+      { {     0x74,0},{          0xf4,0} }, { {     0x75,0},{          0xf5,0} }, { {     0x76,0},{          0xf6,0} }, { {     0x77,0},{          0xf7,0} },        /*074*/
+      { {     0x78,0},{          0xf8,0} }, { {     0x79,0},{          0xf9,0} }, { {     0x7a,0},{          0xfa,0} }, { {     0x7b,0},{          0xfb,0} },        /*078*/
+      { {     0x7c,0},{          0xfc,0} }, { {     0x7d,0},{          0xfd,0} }, { {     0x7e,0},{          0xfe,0} }, { {     0x7f,0},{          0xff,0} },        /*07c*/
+
+      { {     0x80,0},{               0} }, { {     0x81,0},{               0} }, { {     0x82,0},{               0} }, { {          0},{               0} },        /*080*/
+      { {          0},{               0} }, { {     0x85,0},{               0} }, { {     0x86,0},{               0} }, { {     0x87,0},{               0} },        /*084*/
+      { {     0x88,0},{               0} }, { {     0x89,0},{               0} }, { {     0x8a,0},{               0} }, { {     0x8b,0},{               0} },        /*088*/
+      { {     0x8c,0},{               0} }, { {     0x8d,0},{               0} }, { {     0x8e,0},{               0} }, { {     0x8f,0},{               0} },        /*08c*/
+      { {     0x90,0},{               0} }, { {     0x91,0},{               0} }, { {     0x92,0},{               0} }, { {     0x93,0},{               0} },        /*090*/
+      { {     0x94,0},{               0} }, { {     0x95,0},{               0} }, { {     0x96,0},{               0} }, { {     0x97,0},{               0} },        /*094*/
+      { {     0x98,0},{               0} }, { {     0x99,0},{               0} }, { {     0x9a,0},{               0} }, { {     0x9b,0},{               0} },        /*098*/
+      { {     0x9c,0},{               0} }, { {     0x9d,0},{               0} }, { {     0x9e,0},{               0} }, { {     0x9f,0},{               0} },        /*09c*/
+      { {     0xa0,0},{               0} }, { {     0xa1,0},{               0} }, { {     0xa2,0},{               0} }, { {     0xa3,0},{               0} },        /*0a0*/
+      { {     0xa4,0},{               0} }, { {     0xa5,0},{               0} }, { {     0xa6,0},{               0} }, { {     0xa7,0},{               0} },        /*0a4*/
+      { {     0xa8,0},{               0} }, { {     0xa9,0},{               0} }, { {     0xaa,0},{               0} }, { {     0xab,0},{               0} },        /*0a8*/
+      { {     0xac,0},{               0} }, { {     0xad,0},{               0} }, { {     0xae,0},{               0} }, { {     0xaf,0},{               0} },        /*0ac*/
+      { {     0xb0,0},{               0} }, { {     0xb1,0},{               0} }, { {     0xb2,0},{               0} }, { {     0xb3,0},{               0} },        /*0b0*/
+      { {     0xb4,0},{               0} }, { {     0xb5,0},{               0} }, { {     0xb6,0},{               0} }, { {     0xb7,0},{               0} },        /*0b4*/
+      { {     0xb8,0},{               0} }, { {     0xb9,0},{               0} }, { {     0xba,0},{               0} }, { {     0xbb,0},{               0} },        /*0b8*/
+      { {     0xbc,0},{               0} }, { {     0xbd,0},{               0} }, { {     0xbe,0},{               0} }, { {     0xbf,0},{               0} },        /*0bc*/
+      { {     0xc0,0},{               0} }, { {     0xc1,0},{               0} }, { {     0xc2,0},{               0} }, { {     0xc3,0},{               0} },        /*0c0*/
+      { {     0xc4,0},{               0} }, { {     0xc5,0},{               0} }, { {     0xc6,0},{               0} }, { {     0xc7,0},{               0} },        /*0c4*/
+      { {     0xc8,0},{               0} }, { {     0xc9,0},{               0} }, { {     0xca,0},{               0} }, { {     0xcb,0},{               0} },        /*0c8*/
+      { {     0xcc,0},{               0} }, { {     0xcd,0},{               0} }, { {     0xce,0},{               0} }, { {     0xcf,0},{               0} },        /*0cc*/
+      { {     0xd0,0},{               0} }, { {     0xd1,0},{               0} }, { {     0xd2,0},{               0} }, { {     0xd3,0},{               0} },        /*0d0*/
+      { {     0xd4,0},{               0} }, { {     0xd5,0},{               0} }, { {     0xd6,0},{               0} }, { {     0xd7,0},{               0} },        /*0d4*/
+      { {     0xd8,0},{               0} }, { {     0xd9,0},{               0} }, { {     0xda,0},{               0} }, { {     0xdb,0},{               0} },        /*0d8*/
+      { {     0xdc,0},{               0} }, { {     0xdd,0},{               0} }, { {     0xde,0},{               0} }, { {     0xdf,0},{               0} },        /*0dc*/
+      { {     0xe0,0},{               0} }, { {     0xe1,0},{               0} }, { {     0xe2,0},{               0} }, { {     0xe3,0},{               0} },        /*0e0*/
+      { {     0xe4,0},{               0} }, { {     0xe5,0},{               0} }, { {     0xe6,0},{               0} }, { {     0xe7,0},{               0} },        /*0e4*/
+      { {     0xe8,0},{               0} }, { {     0xe9,0},{               0} }, { {     0xea,0},{               0} }, { {     0xeb,0},{               0} },        /*0e8*/
+      { {     0xec,0},{               0} }, { {     0xed,0},{               0} }, { {     0xee,0},{               0} }, { {     0xef,0},{               0} },        /*0ec*/
+      { {          0},{               0} }, { {     0xf1,0},{               0} }, { {     0xf2,0},{               0} }, { {     0xf3,0},{               0} },        /*0f0*/
+      { {     0xf4,0},{               0} }, { {     0xf5,0},{               0} }, { {     0xf6,0},{               0} }, { {     0xf7,0},{               0} },        /*0f4*/
+      { {     0xf8,0},{               0} }, { {     0xf9,0},{               0} }, { {     0xfa,0},{               0} }, { {     0xfb,0},{               0} },        /*0f8*/
+      { {     0xfc,0},{               0} }, { {     0xfd,0},{               0} }, { {     0xfe,0},{               0} }, { {     0xff,0},{               0} },        /*0fc*/
+
+      { {0xe1,0x1d,0},{0xe1,     0x9d,0} }, { {0xe0,0x01,0},{0xe0,     0x81,0} }, { {0xe0,0x02,0},{0xe0,     0x82,0} }, { {0xe0,0x03,0},{0xe0,     0x83,0} },        /*100*/
+      { {0xe0,0x04,0},{0xe0,     0x84,0} }, { {0xe0,0x05,0},{0xe0,     0x85,0} }, { {0xe0,0x06,0},{0xe0,     0x86,0} }, { {0xe0,0x07,0},{0xe0,     0x87,0} },        /*104*/
+      { {0xe0,0x08,0},{0xe0,     0x88,0} }, { {0xe0,0x09,0},{0xe0,     0x89,0} }, { {0xe0,0x0a,0},{0xe0,     0x8a,0} }, { {0xe0,0x0b,0},{0xe0,     0x8b,0} },        /*108*/
+      { {0xe0,0x0c,0},{0xe0,     0x8c,0} }, { {          0},{               0} }, { {0xe0,0x0e,0},{0xe0,     0x8e,0} }, { {0xe0,0x0f,0},{0xe0,     0x8f,0} },        /*10c*/
+      { {0xe0,0x10,0},{0xe0,     0x90,0} }, { {0xe0,0x11,0},{0xe0,     0x91,0} }, { {0xe0,0x12,0},{0xe0,     0x92,0} }, { {0xe0,0x13,0},{0xe0,     0x93,0} },        /*110*/
+      { {0xe0,0x14,0},{0xe0,     0x94,0} }, { {0xe0,0x15,0},{0xe0,     0x95,0} }, { {0xe0,0x16,0},{0xe0,     0x96,0} }, { {0xe0,0x17,0},{0xe0,     0x97,0} },        /*114*/
+      { {0xe0,0x18,0},{0xe0,     0x98,0} }, { {0xe0,0x19,0},{0xe0,     0x99,0} }, { {0xe0,0x1a,0},{0xe0,     0x9a,0} }, { {0xe0,0x1b,0},{0xe0,     0x9b,0} },        /*118*/
+      { {0xe0,0x1c,0},{0xe0,     0x9c,0} }, { {0xe0,0x1d,0},{0xe0,     0x9d,0} }, { {0xe0,0x1e,0},{0xe0,     0x9e,0} }, { {0xe0,0x1f,0},{0xe0,     0x9f,0} },        /*11c*/
+      { {0xe0,0x20,0},{0xe0,     0xa0,0} }, { {0xe0,0x21,0},{0xe0,     0xa1,0} }, { {0xe0,0x22,0},{0xe0,     0xa2,0} }, { {0xe0,0x23,0},{0xe0,     0xa3,0} },        /*120*/
+      { {0xe0,0x24,0},{0xe0,     0xa4,0} }, { {0xe0,0x25,0},{0xe0,     0xa5,0} }, { {0xe0,0x26,0},{0xe0,     0xa6,0} }, { {          0},{               0} },        /*124*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*128*/
+      { {0xe0,0x2c,0},{0xe0,     0xac,0} }, { {0xe0,0x2d,0},{0xe0,     0xad,0} }, { {0xe0,0x2e,0},{0xe0,     0xae,0} }, { {0xe0,0x2f,0},{0xe0,     0xaf,0} },        /*12c*/
+      { {0xe0,0x30,0},{0xe0,     0xb0,0} }, { {0xe0,0x31,0},{0xe0,     0xb1,0} }, { {0xe0,0x32,0},{0xe0,     0xb2,0} }, { {          0},{               0} },        /*130*/
+      { {0xe0,0x34,0},{0xe0,     0xb4,0} }, { {0xe0,0x35,0},{0xe0,     0xb5,0} }, { {          0},{               0} }, { {0xe0,0x37,0},{0xe0,     0xb7,0} },        /*134*/
+      { {0xe0,0x38,0},{0xe0,     0xb8,0} }, { {          0},{               0} }, { {0xe0,0x3a,0},{0xe0,     0xba,0} }, { {0xe0,0x3b,0},{0xe0,     0xbb,0} },        /*138*/
+      { {0xe0,0x3c,0},{0xe0,     0xbc,0} }, { {0xe0,0x3d,0},{0xe0,     0xbd,0} }, { {0xe0,0x3e,0},{0xe0,     0xbe,0} }, { {0xe0,0x3f,0},{0xe0,     0xbf,0} },        /*13c*/
+      { {0xe0,0x40,0},{0xe0,     0xc0,0} }, { {0xe0,0x41,0},{0xe0,     0xc1,0} }, { {0xe0,0x42,0},{0xe0,     0xc2,0} }, { {0xe0,0x43,0},{0xe0,     0xc3,0} },        /*140*/
+      { {0xe0,0x44,0},{0xe0,     0xc4,0} }, { {          0},{               0} }, { {0xe0,0x46,0},{0xe0,     0xc6,0} }, { {0xe0,0x47,0},{0xe0,     0xc7,0} },        /*144*/
+      { {0xe0,0x48,0},{0xe0,     0xc8,0} }, { {0xe0,0x49,0},{0xe0,     0xc9,0} }, { {          0},{               0} }, { {0xe0,0x4b,0},{0xe0,     0xcb,0} },        /*148*/
+      { {0xe0,0x4c,0},{0xe0,     0xcc,0} }, { {0xe0,0x4d,0},{0xe0,     0xcd,0} }, { {0xe0,0x4e,0},{0xe0,     0xce,0} }, { {0xe0,0x4f,0},{0xe0,     0xcf,0} },        /*14c*/
+      { {0xe0,0x50,0},{0xe0,     0xd0,0} }, { {0xe0,0x51,0},{0xe0,     0xd1,0} }, { {0xe0,0x52,0},{0xe0,     0xd2,0} }, { {0xe0,0x53,0},{0xe0,     0xd3,0} },        /*150*/
+      { {          0},{               0} }, { {0xe0,0x55,0},{0xe0,     0xd5,0} }, { {          0},{               0} }, { {0xe0,0x57,0},{0xe0,     0xd7,0} },        /*154*/
+      { {0xe0,0x58,0},{0xe0,     0xd8,0} }, { {0xe0,0x59,0},{0xe0,     0xd9,0} }, { {0xe0,0x5a,0},{0xe0,     0xaa,0} }, { {0xe0,0x5b,0},{0xe0,     0xdb,0} },        /*158*/
+      { {0xe0,0x5c,0},{0xe0,     0xdc,0} }, { {0xe0,0x5d,0},{0xe0,     0xdd,0} }, { {0xe0,0x5e,0},{0xe0,     0xee,0} }, { {0xe0,0x5f,0},{0xe0,     0xdf,0} },        /*15c*/
+      { {          0},{               0} }, { {0xe0,0x61,0},{0xe0,     0xe1,0} }, { {0xe0,0x62,0},{0xe0,     0xe2,0} }, { {0xe0,0x63,0},{0xe0,     0xe3,0} },        /*160*/
+      { {0xe0,0x64,0},{0xe0,     0xe4,0} }, { {0xe0,0x65,0},{0xe0,     0xe5,0} }, { {0xe0,0x66,0},{0xe0,     0xe6,0} }, { {0xe0,0x67,0},{0xe0,     0xe7,0} },        /*164*/
+      { {0xe0,0x68,0},{0xe0,     0xe8,0} }, { {0xe0,0x69,0},{0xe0,     0xe9,0} }, { {0xe0,0x6a,0},{0xe0,     0xea,0} }, { {0xe0,0x6b,0},{0xe0,     0xeb,0} },        /*168*/
+      { {0xe0,0x6c,0},{0xe0,     0xec,0} }, { {0xe0,0x6d,0},{0xe0,     0xed,0} }, { {0xe0,0x6e,0},{0xe0,     0xee,0} }, { {          0},{               0} },        /*16c*/
+      { {0xe0,0x70,0},{0xe0,     0xf0,0} }, { {0xe0,0x71,0},{0xe0,     0xf1,0} }, { {0xe0,0x72,0},{0xe0,     0xf2,0} }, { {0xe0,0x73,0},{0xe0,     0xf3,0} },        /*170*/
+      { {0xe0,0x74,0},{0xe0,     0xf4,0} }, { {0xe0,0x75,0},{0xe0,     0xf5,0} }, { {          0},{               0} }, { {0xe0,0x77,0},{0xe0,     0xf7,0} },        /*174*/
+      { {0xe0,0x78,0},{0xe0,     0xf8,0} }, { {0xe0,0x79,0},{0xe0,     0xf9,0} }, { {0xe0,0x7a,0},{0xe0,     0xfa,0} }, { {0xe0,0x7b,0},{0xe0,     0xfb,0} },        /*178*/
+      { {0xe0,0x7c,0},{0xe0,     0xfc,0} }, { {0xe0,0x7d,0},{0xe0,     0xfd,0} }, { {0xe0,0x7e,0},{0xe0,     0xfe,0} }, { {0xe0,0x7f,0},{0xe0,     0xff,0} },        /*17c*/
+
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*180*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*184*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*188*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*18c*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*190*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*194*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*198*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*19c*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1ac*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1cc*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1dc*/
+      { {          0},{               0} }, { {0xe0,0xe1,0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {0xe0,0xee,0},{               0} }, { {          0},{               0} },        /*1ec*/
+      { {          0},{               0} }, { {0xe0,0xf1,0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {0xe0,0xfe,0},{               0} }, { {0xe0,0xff,0},{               0} }         /*1fc*/
+      // clang-format on
+};
+
+static const scancode scancode_set2[512] = {
+    // clang-format off
+      { {          0},{               0} }, { {     0x76,0},{     0xF0,0x76,0} }, { {     0x16,0},{     0xF0,0x16,0} }, { {     0x1E,0},{     0xF0,0x1E,0} },        /*000*/
+      { {     0x26,0},{     0xF0,0x26,0} }, { {     0x25,0},{     0xF0,0x25,0} }, { {     0x2E,0},{     0xF0,0x2E,0} }, { {     0x36,0},{     0xF0,0x36,0} },        /*004*/
+      { {     0x3D,0},{     0xF0,0x3D,0} }, { {     0x3E,0},{     0xF0,0x3E,0} }, { {     0x46,0},{     0xF0,0x46,0} }, { {     0x45,0},{     0xF0,0x45,0} },        /*008*/
+      { {     0x4E,0},{     0xF0,0x4E,0} }, { {     0x55,0},{     0xF0,0x55,0} }, { {     0x66,0},{     0xF0,0x66,0} }, { {     0x0D,0},{     0xF0,0x0D,0} },        /*00c*/
+      { {     0x15,0},{     0xF0,0x15,0} }, { {     0x1D,0},{     0xF0,0x1D,0} }, { {     0x24,0},{     0xF0,0x24,0} }, { {     0x2D,0},{     0xF0,0x2D,0} },        /*010*/
+      { {     0x2C,0},{     0xF0,0x2C,0} }, { {     0x35,0},{     0xF0,0x35,0} }, { {     0x3C,0},{     0xF0,0x3C,0} }, { {     0x43,0},{     0xF0,0x43,0} },        /*014*/
+      { {     0x44,0},{     0xF0,0x44,0} }, { {     0x4D,0},{     0xF0,0x4D,0} }, { {     0x54,0},{     0xF0,0x54,0} }, { {     0x5B,0},{     0xF0,0x5B,0} },        /*018*/
+      { {     0x5A,0},{     0xF0,0x5A,0} }, { {     0x14,0},{     0xF0,0x14,0} }, { {     0x1C,0},{     0xF0,0x1C,0} }, { {     0x1B,0},{     0xF0,0x1B,0} },        /*01c*/
+      { {     0x23,0},{     0xF0,0x23,0} }, { {     0x2B,0},{     0xF0,0x2B,0} }, { {     0x34,0},{     0xF0,0x34,0} }, { {     0x33,0},{     0xF0,0x33,0} },        /*020*/
+      { {     0x3B,0},{     0xF0,0x3B,0} }, { {     0x42,0},{     0xF0,0x42,0} }, { {     0x4B,0},{     0xF0,0x4B,0} }, { {     0x4C,0},{     0xF0,0x4C,0} },        /*024*/
+      { {     0x52,0},{     0xF0,0x52,0} }, { {     0x0E,0},{     0xF0,0x0E,0} }, { {     0x12,0},{     0xF0,0x12,0} }, { {     0x5D,0},{     0xF0,0x5D,0} },        /*028*/
+      { {     0x1A,0},{     0xF0,0x1A,0} }, { {     0x22,0},{     0xF0,0x22,0} }, { {     0x21,0},{     0xF0,0x21,0} }, { {     0x2A,0},{     0xF0,0x2A,0} },        /*02c*/
+      { {     0x32,0},{     0xF0,0x32,0} }, { {     0x31,0},{     0xF0,0x31,0} }, { {     0x3A,0},{     0xF0,0x3A,0} }, { {     0x41,0},{     0xF0,0x41,0} },        /*030*/
+      { {     0x49,0},{     0xF0,0x49,0} }, { {     0x4A,0},{     0xF0,0x4A,0} }, { {     0x59,0},{     0xF0,0x59,0} }, { {     0x7C,0},{     0xF0,0x7C,0} },        /*034*/
+      { {     0x11,0},{     0xF0,0x11,0} }, { {     0x29,0},{     0xF0,0x29,0} }, { {     0x58,0},{     0xF0,0x58,0} }, { {     0x05,0},{     0xF0,0x05,0} },        /*038*/
+      { {     0x06,0},{     0xF0,0x06,0} }, { {     0x04,0},{     0xF0,0x04,0} }, { {     0x0C,0},{     0xF0,0x0C,0} }, { {     0x03,0},{     0xF0,0x03,0} },        /*03c*/
+      { {     0x0B,0},{     0xF0,0x0B,0} }, { {     0x83,0},{     0xF0,0x83,0} }, { {     0x0A,0},{     0xF0,0x0A,0} }, { {     0x01,0},{     0xF0,0x01,0} },        /*040*/
+      { {     0x09,0},{     0xF0,0x09,0} }, { {     0x77,0},{     0xF0,0x77,0} }, { {     0x7E,0},{     0xF0,0x7E,0} }, { {     0x6C,0},{     0xF0,0x6C,0} },        /*044*/
+      { {     0x75,0},{     0xF0,0x75,0} }, { {     0x7D,0},{     0xF0,0x7D,0} }, { {     0x7B,0},{     0xF0,0x7B,0} }, { {     0x6B,0},{     0xF0,0x6B,0} },        /*048*/
+      { {     0x73,0},{     0xF0,0x73,0} }, { {     0x74,0},{     0xF0,0x74,0} }, { {     0x79,0},{     0xF0,0x79,0} }, { {     0x69,0},{     0xF0,0x69,0} },        /*04c*/
+      { {     0x72,0},{     0xF0,0x72,0} }, { {     0x7A,0},{     0xF0,0x7A,0} }, { {     0x70,0},{     0xF0,0x70,0} }, { {     0x71,0},{     0xF0,0x71,0} },        /*050*/
+      { {     0x84,0},{     0xF0,0x84,0} }, { {     0x60,0},{     0xF0,0x60,0} }, { {     0x61,0},{     0xF0,0x61,0} }, { {     0x78,0},{     0xF0,0x78,0} },        /*054*/
+      { {     0x07,0},{     0xF0,0x07,0} }, { {     0x0F,0},{     0xF0,0x0F,0} }, { {     0x17,0},{     0xF0,0x17,0} }, { {     0x1F,0},{     0xF0,0x1F,0} },        /*058*/
+      { {     0x27,0},{     0xF0,0x27,0} }, { {     0x2F,0},{     0xF0,0x2F,0} }, { {     0x37,0},{     0xF0,0x37,0} }, { {     0x3F,0},{     0xF0,0x3F,0} },        /*05c*/
+      { {     0x47,0},{     0xF0,0x47,0} }, { {     0x4F,0},{     0xF0,0x4F,0} }, { {     0x56,0},{     0xF0,0x56,0} }, { {     0x5E,0},{     0xF0,0x5E,0} },        /*060*/
+      { {     0x08,0},{     0xF0,0x08,0} }, { {     0x10,0},{     0xF0,0x10,0} }, { {     0x18,0},{     0xF0,0x18,0} }, { {     0x20,0},{     0xF0,0x20,0} },        /*064*/
+      { {     0x28,0},{     0xF0,0x28,0} }, { {     0x30,0},{     0xF0,0x30,0} }, { {     0x38,0},{     0xF0,0x38,0} }, { {     0x40,0},{     0xF0,0x40,0} },        /*068*/
+      { {     0x48,0},{     0xF0,0x48,0} }, { {     0x50,0},{     0xF0,0x50,0} }, { {     0x57,0},{     0xF0,0x57,0} }, { {     0x6F,0},{     0xF0,0x6F,0} },        /*06c*/
+      { {     0x13,0},{     0xF0,0x13,0} }, { {     0x19,0},{     0xF0,0x19,0} }, { {     0x39,0},{     0xF0,0x39,0} }, { {     0x51,0},{     0xF0,0x51,0} },        /*070*/
+      { {     0x53,0},{     0xF0,0x53,0} }, { {     0x5C,0},{     0xF0,0x5C,0} }, { {     0x5F,0},{     0xF0,0x5F,0} }, { {     0x62,0},{     0xF0,0x62,0} },        /*074*/
+      { {     0x63,0},{     0xF0,0x63,0} }, { {     0x64,0},{     0xF0,0x64,0} }, { {     0x65,0},{     0xF0,0x65,0} }, { {     0x67,0},{     0xF0,0x67,0} },        /*078*/
+      { {     0x68,0},{     0xF0,0x68,0} }, { {     0x6A,0},{     0xF0,0x6A,0} }, { {     0x6D,0},{     0xF0,0x6D,0} }, { {     0x6E,0},{     0xF0,0x6E,0} },        /*07c*/
+
+      { {     0x80,0},{     0xf0,0x80,0} }, { {     0x81,0},{     0xf0,0x81,0} }, { {     0x82,0},{     0xf0,0x82,0} }, { {          0},{               0} },        /*080*/
+      { {          0},{               0} }, { {     0x85,0},{     0xf0,0x54,0} }, { {     0x86,0},{     0xf0,0x86,0} }, { {     0x87,0},{     0xf0,0x87,0} },        /*084*/
+      { {     0x88,0},{     0xf0,0x88,0} }, { {     0x89,0},{     0xf0,0x89,0} }, { {     0x8a,0},{     0xf0,0x8a,0} }, { {     0x8b,0},{     0xf0,0x8b,0} },        /*088*/
+      { {     0x8c,0},{     0xf0,0x8c,0} }, { {     0x8d,0},{     0xf0,0x8d,0} }, { {     0x8e,0},{     0xf0,0x8e,0} }, { {     0x8f,0},{     0xf0,0x8f,0} },        /*08c*/
+      { {     0x90,0},{     0xf0,0x90,0} }, { {     0x91,0},{     0xf0,0x91,0} }, { {     0x92,0},{     0xf0,0x92,0} }, { {     0x93,0},{     0xf0,0x93,0} },        /*090*/
+      { {     0x94,0},{     0xf0,0x94,0} }, { {     0x95,0},{     0xf0,0x95,0} }, { {     0x96,0},{     0xf0,0x96,0} }, { {     0x97,0},{     0xf0,0x97,0} },        /*094*/
+      { {     0x98,0},{     0xf0,0x98,0} }, { {     0x99,0},{     0xf0,0x99,0} }, { {     0x9a,0},{     0xf0,0x9a,0} }, { {     0x9b,0},{     0xf0,0x9b,0} },        /*098*/
+      { {     0x9c,0},{     0xf0,0x9c,0} }, { {     0x9d,0},{     0xf0,0x9d,0} }, { {     0x9e,0},{     0xf0,0x9e,0} }, { {     0x9f,0},{     0xf0,0x9f,0} },        /*09c*/
+      { {     0xa0,0},{     0xf0,0xa0,0} }, { {     0xa1,0},{     0xf0,0xa1,0} }, { {     0xa2,0},{     0xf0,0xa2,0} }, { {     0xa3,0},{     0xf0,0xa3,0} },        /*0a0*/
+      { {     0xa4,0},{     0xf0,0xa4,0} }, { {     0xa5,0},{     0xf0,0xa5,0} }, { {     0xa6,0},{     0xf0,0xa6,0} }, { {     0xa7,0},{     0xf0,0xa7,0} },        /*0a4*/
+      { {     0xa8,0},{     0xf0,0xa8,0} }, { {     0xa9,0},{     0xf0,0xa9,0} }, { {     0xaa,0},{     0xf0,0xaa,0} }, { {     0xab,0},{     0xf0,0xab,0} },        /*0a8*/
+      { {     0xac,0},{     0xf0,0xac,0} }, { {     0xad,0},{     0xf0,0xad,0} }, { {     0xae,0},{     0xf0,0xae,0} }, { {     0xaf,0},{     0xf0,0xaf,0} },        /*0ac*/
+      { {     0xb0,0},{     0xf0,0xb0,0} }, { {     0xb1,0},{     0xf0,0xb1,0} }, { {     0xb2,0},{     0xf0,0xb2,0} }, { {     0xb3,0},{     0xf0,0xb3,0} },        /*0b0*/
+      { {     0xb4,0},{     0xf0,0xb4,0} }, { {     0xb5,0},{     0xf0,0xb5,0} }, { {     0xb6,0},{     0xf0,0xb6,0} }, { {     0xb7,0},{     0xf0,0xb7,0} },        /*0b4*/
+      { {     0xb8,0},{     0xf0,0xb8,0} }, { {     0xb9,0},{     0xf0,0xb9,0} }, { {     0xba,0},{     0xf0,0xba,0} }, { {     0xbb,0},{     0xf0,0xbb,0} },        /*0b8*/
+      { {     0xbc,0},{     0xf0,0xbc,0} }, { {     0xbd,0},{     0xf0,0xbd,0} }, { {     0xbe,0},{     0xf0,0xbe,0} }, { {     0xbf,0},{     0xf0,0xbf,0} },        /*0bc*/
+      { {     0xc0,0},{     0xf0,0xc0,0} }, { {     0xc1,0},{     0xf0,0xc1,0} }, { {     0xc2,0},{     0xf0,0xc2,0} }, { {     0xc3,0},{     0xf0,0xc3,0} },        /*0c0*/
+      { {     0xc4,0},{     0xf0,0xc4,0} }, { {     0xc5,0},{     0xf0,0xc5,0} }, { {     0xc6,0},{     0xf0,0xc6,0} }, { {     0xc7,0},{     0xf0,0xc7,0} },        /*0c4*/
+      { {     0xc8,0},{     0xf0,0xc8,0} }, { {     0xc9,0},{     0xf0,0xc9,0} }, { {     0xca,0},{     0xf0,0xca,0} }, { {     0xcb,0},{     0xf0,0xcb,0} },        /*0c8*/
+      { {     0xcc,0},{     0xf0,0xcc,0} }, { {     0xcd,0},{     0xf0,0xcd,0} }, { {     0xce,0},{     0xf0,0xce,0} }, { {     0xcf,0},{     0xf0,0xcf,0} },        /*0cc*/
+      { {     0xd0,0},{     0xf0,0xd0,0} }, { {     0xd1,0},{     0xf0,0xd0,0} }, { {     0xd2,0},{     0xf0,0xd2,0} }, { {     0xd3,0},{     0xf0,0xd3,0} },        /*0d0*/
+      { {     0xd4,0},{     0xf0,0xd4,0} }, { {     0xd5,0},{     0xf0,0xd5,0} }, { {     0xd6,0},{     0xf0,0xd6,0} }, { {     0xd7,0},{     0xf0,0xd7,0} },        /*0d4*/
+      { {     0xd8,0},{     0xf0,0xd8,0} }, { {     0xd9,0},{     0xf0,0xd9,0} }, { {     0xda,0},{     0xf0,0xda,0} }, { {     0xdb,0},{     0xf0,0xdb,0} },        /*0d8*/
+      { {     0xdc,0},{     0xf0,0xdc,0} }, { {     0xdd,0},{     0xf0,0xdd,0} }, { {     0xde,0},{     0xf0,0xde,0} }, { {     0xdf,0},{     0xf0,0xdf,0} },        /*0dc*/
+      { {     0xe0,0},{     0xf0,0xe0,0} }, { {     0xe1,0},{     0xf0,0xe1,0} }, { {     0xe2,0},{     0xf0,0xe2,0} }, { {     0xe3,0},{     0xf0,0xe3,0} },        /*0e0*/
+      { {     0xe4,0},{     0xf0,0xe4,0} }, { {     0xe5,0},{     0xf0,0xe5,0} }, { {     0xe6,0},{     0xf0,0xe6,0} }, { {     0xe7,0},{     0xf0,0xe7,0} },        /*0e4*/
+      { {     0xe8,0},{     0xf0,0xe8,0} }, { {     0xe9,0},{     0xf0,0xe9,0} }, { {     0xea,0},{     0xf0,0xea,0} }, { {     0xeb,0},{     0xf0,0xeb,0} },        /*0e8*/
+      { {     0xec,0},{     0xf0,0xec,0} }, { {     0xed,0},{     0xf0,0xed,0} }, { {     0xee,0},{     0xf0,0xee,0} }, { {     0xef,0},{     0xf0,0xef,0} },        /*0ec*/
+      { {          0},{               0} }, { {     0xf1,0},{     0xf0,0xf1,0} }, { {     0xf2,0},{     0xf0,0xf2,0} }, { {     0xf3,0},{     0xf0,0xf3,0} },        /*0f0*/
+      { {     0xf4,0},{     0xf0,0xf4,0} }, { {     0xf5,0},{     0xf0,0xf5,0} }, { {     0xf6,0},{     0xf0,0xf6,0} }, { {     0xf7,0},{     0xf0,0xf7,0} },        /*0f4*/
+      { {     0xf8,0},{     0xf0,0xf8,0} }, { {     0xf9,0},{     0xf0,0xf9,0} }, { {     0xfa,0},{     0xf0,0xfa,0} }, { {     0xfb,0},{     0xf0,0xfb,0} },        /*0f8*/
+      { {     0xfc,0},{     0xf0,0xfc,0} }, { {     0xfd,0},{     0xf0,0xfd,0} }, { {     0xfe,0},{     0xf0,0xfe,0} }, { {     0xff,0},{     0xf0,0xff,0} },        /*0fc*/
+
+      { {0xe1,0x14,0},{0xe1,0xf0,0x14,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} },        /*100*/
+      { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} },        /*104*/
+      { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} },        /*108*/
+      { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { {          0},{               0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} },        /*10c*/
+      { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} },        /*110*/
+      { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} },        /*114*/
+      { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} },        /*118*/
+      { {0xe0,0x5A,0},{0xe0,0xF0,0x5A,0} }, { {0xe0,0x14,0},{0xe0,0xF0,0x14,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} },        /*11c*/
+      { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} },        /*120*/
+      { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { {          0},{               0} },        /*124*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*128*/
+      { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} },        /*12c*/
+      { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { {          0},{               0} },        /*130*/
+      { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { {0xe0,0x4A,0},{0xe0,0xF0,0x4A,0} }, { {          0},{               0} }, { {0xe0,0x7C,0},{0xe0,0xF0,0x7C,0} },        /*134*/
+      { {0xe0,0x11,0},{0xe0,0xF0,0x11,0} }, { {          0},{               0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} },        /*138*/
+      { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} },        /*13c*/
+      { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} },        /*140*/
+      { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { {          0},{               0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { {0xe0,0x6C,0},{0xe0,0xF0,0x6C,0} },        /*144*/
+      { {0xe0,0x75,0},{0xe0,0xF0,0x75,0} }, { {0xe0,0x7D,0},{0xe0,0xF0,0x7D,0} }, { {          0},{               0} }, { {0xe0,0x6B,0},{0xe0,0xF0,0x6B,0} },        /*148*/
+      { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { {0xe0,0x74,0},{0xe0,0xF0,0x74,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { {0xe0,0x69,0},{0xe0,0xF0,0x69,0} },        /*14c*/
+      { {0xe0,0x72,0},{0xe0,0xF0,0x72,0} }, { {0xe0,0x7A,0},{0xe0,0xF0,0x7A,0} }, { {0xe0,0x70,0},{0xe0,0xF0,0x70,0} }, { {0xe0,0x71,0},{0xe0,0xF0,0x71,0} },        /*150*/
+      { {          0},{               0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { {          0},{               0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} },        /*154*/
+      { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { {0xe0,0x1F,0},{0xe0,0xF0,0x1F,0} },        /*158*/
+      { {0xe0,0x27,0},{0xe0,0xF0,0x27,0} }, { {0xe0,0x2F,0},{0xe0,0xF0,0x2F,0} }, { {0xe0,0x37,0},{0xe0,0xF0,0x37,0} }, { {0xe0,0x3F,0},{0xe0,0xF0,0x3F,0} },        /*15c*/
+      { {          0},{               0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { {0xe0,0x5E,0},{0xe0,0xF0,0x5E,0} },        /*160*/
+      { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} },        /*164*/
+      { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} },        /*168*/
+      { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { {          0},{               0} },        /*16c*/
+      { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} },        /*170*/
+      { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { {          0},{               0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} },        /*174*/
+      { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} },        /*178*/
+      { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} },        /*17c*/
+
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*180*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*184*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*188*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*18c*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*190*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*194*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*198*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*19c*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1ac*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1cc*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1dc*/
+      { {          0},{               0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { {          0},{               0} },        /*1ec*/
+      { {          0},{               0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} }         /*1fc*/
+      // clang-format on
+};
+
+static const scancode scancode_set3[512] = {
+    // clang-format off
+      { {          0},{               0} }, { {     0x08,0},{     0xf0,0x08,0} }, { {     0x16,0},{     0xf0,0x16,0} }, { {     0x1E,0},{     0xf0,0x1E,0} },        /*000*/
+      { {     0x26,0},{     0xf0,0x26,0} }, { {     0x25,0},{     0xf0,0x25,0} }, { {     0x2E,0},{     0xf0,0x2E,0} }, { {     0x36,0},{     0xf0,0x36,0} },        /*004*/
+      { {     0x3D,0},{     0xf0,0x3D,0} }, { {     0x3E,0},{     0xf0,0x3E,0} }, { {     0x46,0},{     0xf0,0x46,0} }, { {     0x45,0},{     0xf0,0x45,0} },        /*008*/
+      { {     0x4E,0},{     0xf0,0x4E,0} }, { {     0x55,0},{     0xf0,0x55,0} }, { {     0x66,0},{     0xf0,0x66,0} }, { {     0x0D,0},{     0xf0,0x0D,0} },        /*00c*/
+      { {     0x15,0},{     0xf0,0x15,0} }, { {     0x1D,0},{     0xf0,0x1D,0} }, { {     0x24,0},{     0xf0,0x24,0} }, { {     0x2D,0},{     0xf0,0x2D,0} },        /*010*/
+      { {     0x2C,0},{     0xf0,0x2C,0} }, { {     0x35,0},{     0xf0,0x35,0} }, { {     0x3C,0},{     0xf0,0x3C,0} }, { {     0x43,0},{     0xf0,0x43,0} },        /*014*/
+      { {     0x44,0},{     0xf0,0x44,0} }, { {     0x4D,0},{     0xf0,0x4D,0} }, { {     0x54,0},{     0xf0,0x54,0} }, { {     0x5B,0},{     0xf0,0x5B,0} },        /*018*/
+      { {     0x5A,0},{     0xf0,0x5A,0} }, { {     0x11,0},{     0xf0,0x11,0} }, { {     0x1C,0},{     0xf0,0x1C,0} }, { {     0x1B,0},{     0xf0,0x1B,0} },        /*01c*/
+      { {     0x23,0},{     0xf0,0x23,0} }, { {     0x2B,0},{     0xf0,0x2B,0} }, { {     0x34,0},{     0xf0,0x34,0} }, { {     0x33,0},{     0xf0,0x33,0} },        /*020*/
+      { {     0x3B,0},{     0xf0,0x3B,0} }, { {     0x42,0},{     0xf0,0x42,0} }, { {     0x4B,0},{     0xf0,0x4B,0} }, { {     0x4C,0},{     0xf0,0x4C,0} },        /*024*/
+      { {     0x52,0},{     0xf0,0x52,0} }, { {     0x0E,0},{     0xf0,0x0E,0} }, { {     0x12,0},{     0xf0,0x12,0} }, { {     0x5C,0},{     0xf0,0x5C,0} },        /*028*/
+      { {     0x1A,0},{     0xf0,0x1A,0} }, { {     0x22,0},{     0xf0,0x22,0} }, { {     0x21,0},{     0xf0,0x21,0} }, { {     0x2A,0},{     0xf0,0x2A,0} },        /*02c*/
+      { {     0x32,0},{     0xf0,0x32,0} }, { {     0x31,0},{     0xf0,0x31,0} }, { {     0x3A,0},{     0xf0,0x3A,0} }, { {     0x41,0},{     0xf0,0x41,0} },        /*030*/
+      { {     0x49,0},{     0xf0,0x49,0} }, { {     0x4A,0},{     0xf0,0x4A,0} }, { {     0x59,0},{     0xf0,0x59,0} }, { {     0x7E,0},{     0xf0,0x7E,0} },        /*034*/
+      { {     0x19,0},{     0xf0,0x19,0} }, { {     0x29,0},{     0xf0,0x29,0} }, { {     0x14,0},{     0xf0,0x14,0} }, { {     0x07,0},{     0xf0,0x07,0} },        /*038*/
+      { {     0x0F,0},{     0xf0,0x0F,0} }, { {     0x17,0},{     0xf0,0x17,0} }, { {     0x1F,0},{     0xf0,0x1F,0} }, { {     0x27,0},{     0xf0,0x27,0} },        /*03c*/
+      { {     0x2F,0},{     0xf0,0x2F,0} }, { {     0x37,0},{     0xf0,0x37,0} }, { {     0x3F,0},{     0xf0,0x3F,0} }, { {     0x47,0},{     0xf0,0x47,0} },        /*040*/
+      { {     0x4F,0},{     0xf0,0x4F,0} }, { {     0x76,0},{     0xf0,0x76,0} }, { {     0x5F,0},{     0xf0,0x5F,0} }, { {     0x6C,0},{     0xf0,0x6C,0} },        /*044*/
+      { {     0x75,0},{     0xf0,0x75,0} }, { {     0x7D,0},{     0xf0,0x7D,0} }, { {     0x84,0},{     0xf0,0x84,0} }, { {     0x6B,0},{     0xf0,0x6B,0} },        /*048*/
+      { {     0x73,0},{     0xf0,0x73,0} }, { {     0x74,0},{     0xf0,0x74,0} }, { {     0x7C,0},{     0xf0,0x7C,0} }, { {     0x69,0},{     0xf0,0x69,0} },        /*04c*/
+      { {     0x72,0},{     0xf0,0x72,0} }, { {     0x7A,0},{     0xf0,0x7A,0} }, { {     0x70,0},{     0xf0,0x70,0} }, { {     0x71,0},{     0xf0,0x71,0} },        /*050*/
+      { {     0x57,0},{     0xf0,0x57,0} }, { {     0x60,0},{     0xf0,0x60,0} }, { {          0},{               0} }, { {     0x56,0},{     0xf0,0x56,0} },        /*054*/
+      { {     0x5E,0},{     0xf0,0x5E,0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*058*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*05c*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*060*/
+      { {          0},{               0} }, { {     0x10,0},{     0xf0,0x10,0} }, { {     0x18,0},{     0xf0,0x18,0} }, { {     0x20,0},{     0xf0,0x20,0} },        /*064*/
+      { {     0x28,0},{     0xf0,0x28,0} }, { {     0x30,0},{     0xf0,0x30,0} }, { {     0x38,0},{     0xf0,0x38,0} }, { {     0x40,0},{     0xf0,0x40,0} },        /*068*/
+      { {     0x48,0},{     0xf0,0x48,0} }, { {     0x50,0},{     0xf0,0x50,0} }, { {          0},{               0} }, { {          0},{               0} },        /*06c*/
+      { {     0x87,0},{     0xf0,0x87,0} }, { {          0},{               0} }, { {          0},{               0} }, { {     0x51,0},{     0xf0,0x51,0} },        /*070*/
+      { {     0x53,0},{     0xf0,0x53,0} }, { {     0x5C,0},{     0xf0,0x5C,0} }, { {          0},{               0} }, { {     0x62,0},{     0xf0,0x62,0} },        /*074*/
+      { {     0x63,0},{     0xf0,0x63,0} }, { {     0x86,0},{     0xf0,0x86,0} }, { {          0},{               0} }, { {     0x85,0},{     0xf0,0x85,0} },        /*078*/
+      { {     0x68,0},{     0xf0,0x68,0} }, { {     0x13,0},{     0xf0,0x13,0} }, { {          0},{               0} }, { {          0},{               0} },        /*07c*/
+
+      { {     0x80,0},{     0xf0,0x80,0} }, { {     0x81,0},{     0xf0,0x81,0} }, { {     0x82,0},{     0xf0,0x82,0} }, { {          0},{               0} },        /*080*/
+      { {          0},{               0} }, { {     0x85,0},{     0xf0,0x54,0} }, { {     0x86,0},{     0xf0,0x86,0} }, { {     0x87,0},{     0xf0,0x87,0} },        /*084*/
+      { {     0x88,0},{     0xf0,0x88,0} }, { {     0x89,0},{     0xf0,0x89,0} }, { {     0x8a,0},{     0xf0,0x8a,0} }, { {     0x8b,0},{     0xf0,0x8b,0} },        /*088*/
+      { {          0},{               0} }, { {          0},{               0} }, { {     0x8e,0},{     0xf0,0x8e,0} }, { {     0x8f,0},{     0xf0,0x8f,0} },        /*08c*/
+      { {     0x90,0},{     0xf0,0x90,0} }, { {     0x91,0},{     0xf0,0x91,0} }, { {     0x92,0},{     0xf0,0x92,0} }, { {     0x93,0},{     0xf0,0x93,0} },        /*090*/
+      { {     0x94,0},{     0xf0,0x94,0} }, { {     0x95,0},{     0xf0,0x95,0} }, { {     0x96,0},{     0xf0,0x96,0} }, { {     0x97,0},{     0xf0,0x97,0} },        /*094*/
+      { {     0x98,0},{     0xf0,0x98,0} }, { {     0x99,0},{     0xf0,0x99,0} }, { {     0x9a,0},{     0xf0,0x9a,0} }, { {     0x9b,0},{     0xf0,0x9b,0} },        /*098*/
+      { {     0x9c,0},{     0xf0,0x9c,0} }, { {     0x9d,0},{     0xf0,0x9d,0} }, { {     0x9e,0},{     0xf0,0x9e,0} }, { {     0x9f,0},{     0xf0,0x9f,0} },        /*09c*/
+      { {     0xa0,0},{     0xf0,0xa0,0} }, { {     0xa1,0},{     0xf0,0xa1,0} }, { {     0xa2,0},{     0xf0,0xa2,0} }, { {     0xa3,0},{     0xf0,0xa3,0} },        /*0a0*/
+      { {     0xa4,0},{     0xf0,0xa4,0} }, { {     0xa5,0},{     0xf0,0xa5,0} }, { {     0xa6,0},{     0xf0,0xa6,0} }, { {     0xa7,0},{     0xf0,0xa7,0} },        /*0a4*/
+      { {     0xa8,0},{     0xf0,0xa8,0} }, { {     0xa9,0},{     0xf0,0xa9,0} }, { {     0xaa,0},{     0xf0,0xaa,0} }, { {     0xab,0},{     0xf0,0xab,0} },        /*0a8*/
+      { {     0xac,0},{     0xf0,0xac,0} }, { {     0xad,0},{     0xf0,0xad,0} }, { {     0xae,0},{     0xf0,0xae,0} }, { {     0xaf,0},{     0xf0,0xaf,0} },        /*0ac*/
+      { {     0xb0,0},{     0xf0,0xb0,0} }, { {     0xb1,0},{     0xf0,0xb1,0} }, { {     0xb2,0},{     0xf0,0xb2,0} }, { {     0xb3,0},{     0xf0,0xb3,0} },        /*0b0*/
+      { {     0xb4,0},{     0xf0,0xb4,0} }, { {     0xb5,0},{     0xf0,0xb5,0} }, { {     0xb6,0},{     0xf0,0xb6,0} }, { {     0xb7,0},{     0xf0,0xb7,0} },        /*0b4*/
+      { {     0xb8,0},{     0xf0,0xb8,0} }, { {     0xb9,0},{     0xf0,0xb9,0} }, { {     0xba,0},{     0xf0,0xba,0} }, { {     0xbb,0},{     0xf0,0xbb,0} },        /*0b8*/
+      { {     0xbc,0},{     0xf0,0xbc,0} }, { {     0xbd,0},{     0xf0,0xbd,0} }, { {     0xbe,0},{     0xf0,0xbe,0} }, { {     0xbf,0},{     0xf0,0xbf,0} },        /*0bc*/
+      { {     0xc0,0},{     0xf0,0xc0,0} }, { {     0xc1,0},{     0xf0,0xc1,0} }, { {     0xc2,0},{     0xf0,0xc2,0} }, { {     0xc3,0},{     0xf0,0xc3,0} },        /*0c0*/
+      { {     0xc4,0},{     0xf0,0xc4,0} }, { {     0xc5,0},{     0xf0,0xc5,0} }, { {     0xc6,0},{     0xf0,0xc6,0} }, { {     0xc7,0},{     0xf0,0xc7,0} },        /*0c4*/
+      { {     0xc8,0},{     0xf0,0xc8,0} }, { {     0xc9,0},{     0xf0,0xc9,0} }, { {     0xca,0},{     0xf0,0xca,0} }, { {     0xcb,0},{     0xf0,0xcb,0} },        /*0c8*/
+      { {     0xcc,0},{     0xf0,0xcc,0} }, { {     0xcd,0},{     0xf0,0xcd,0} }, { {     0xce,0},{     0xf0,0xce,0} }, { {     0xcf,0},{     0xf0,0xcf,0} },        /*0cc*/
+      { {     0xd0,0},{     0xf0,0xd0,0} }, { {     0xd1,0},{     0xf0,0xd0,0} }, { {     0xd2,0},{     0xf0,0xd2,0} }, { {     0xd3,0},{     0xf0,0xd3,0} },        /*0d0*/
+      { {     0xd4,0},{     0xf0,0xd4,0} }, { {     0xd5,0},{     0xf0,0xd5,0} }, { {     0xd6,0},{     0xf0,0xd6,0} }, { {     0xd7,0},{     0xf0,0xd7,0} },        /*0d4*/
+      { {     0xd8,0},{     0xf0,0xd8,0} }, { {     0xd9,0},{     0xf0,0xd9,0} }, { {     0xda,0},{     0xf0,0xda,0} }, { {     0xdb,0},{     0xf0,0xdb,0} },        /*0d8*/
+      { {     0xdc,0},{     0xf0,0xdc,0} }, { {     0xdd,0},{     0xf0,0xdd,0} }, { {     0xde,0},{     0xf0,0xde,0} }, { {     0xdf,0},{     0xf0,0xdf,0} },        /*0dc*/
+      { {     0xe0,0},{     0xf0,0xe0,0} }, { {     0xe1,0},{     0xf0,0xe1,0} }, { {     0xe2,0},{     0xf0,0xe2,0} }, { {     0xe3,0},{     0xf0,0xe3,0} },        /*0e0*/
+      { {     0xe4,0},{     0xf0,0xe4,0} }, { {     0xe5,0},{     0xf0,0xe5,0} }, { {     0xe6,0},{     0xf0,0xe6,0} }, { {     0xe7,0},{     0xf0,0xe7,0} },        /*0e4*/
+      { {     0xe8,0},{     0xf0,0xe8,0} }, { {     0xe9,0},{     0xf0,0xe9,0} }, { {     0xea,0},{     0xf0,0xea,0} }, { {     0xeb,0},{     0xf0,0xeb,0} },        /*0e8*/
+      { {     0xec,0},{     0xf0,0xec,0} }, { {     0xed,0},{     0xf0,0xed,0} }, { {     0xee,0},{     0xf0,0xee,0} }, { {     0xef,0},{     0xf0,0xef,0} },        /*0ec*/
+      { {          0},{               0} }, { {     0xf1,0},{     0xf0,0xf1,0} }, { {     0xf2,0},{     0xf0,0xf2,0} }, { {     0xf3,0},{     0xf0,0xf3,0} },        /*0f0*/
+      { {     0xf4,0},{     0xf0,0xf4,0} }, { {     0xf5,0},{     0xf0,0xf5,0} }, { {     0xf6,0},{     0xf0,0xf6,0} }, { {     0xf7,0},{     0xf0,0xf7,0} },        /*0f4*/
+      { {     0xf8,0},{     0xf0,0xf8,0} }, { {     0xf9,0},{     0xf0,0xf9,0} }, { {     0xfa,0},{     0xf0,0xfa,0} }, { {     0xfb,0},{     0xf0,0xfb,0} },        /*0f8*/
+      { {     0xfc,0},{     0xf0,0xfc,0} }, { {     0xfd,0},{     0xf0,0xfd,0} }, { {     0xfe,0},{     0xf0,0xfe,0} }, { {     0xff,0},{     0xf0,0xff,0} },        /*0fc*/
+
+      { {     0x62,0},{     0xF0,0x62,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} },        /*100*/
+      { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} },        /*104*/
+      { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} },        /*108*/
+      { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { {          0},{               0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} },        /*10c*/
+      { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} },        /*110*/
+      { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} },        /*114*/
+      { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} },        /*118*/
+      { {     0x79,0},{     0xf0,0x79,0} }, { {     0x58,0},{     0xf0,0x58,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} },        /*11c*/
+      { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} },        /*120*/
+      { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { {          0},{               0} },        /*124*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*128*/
+      { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} },        /*12c*/
+      { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { {          0},{               0} },        /*130*/
+      { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { {     0x77,0},{     0xf0,0x77,0} }, { {          0},{               0} }, { {     0x57,0},{     0xf0,0x57,0} },        /*134*/
+      { {     0x39,0},{     0xf0,0x39,0} }, { {          0},{               0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} },        /*138*/
+      { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} },        /*13c*/
+      { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} },        /*140*/
+      { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { {          0},{               0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { {     0x6E,0},{     0xf0,0x6E,0} },        /*144*/
+      { {     0x63,0},{     0xf0,0x63,0} }, { {     0x6F,0},{     0xf0,0x6F,0} }, { {          0},{               0} }, { {     0x61,0},{     0xf0,0x61,0} },        /*148*/
+      { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { {     0x6A,0},{     0xf0,0x6A,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { {     0x65,0},{     0xf0,0x65,0} },        /*14c*/
+      { {     0x60,0},{     0xf0,0x60,0} }, { {     0x6D,0},{     0xf0,0x6D,0} }, { {     0x67,0},{     0xf0,0x67,0} }, { {     0x64,0},{     0xf0,0x64,0} },        /*150*/
+      { {     0xd4,0},{     0xf0,0xD4,0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { {          0},{               0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} },        /*154*/
+      { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { {     0x8B,0},{     0xf0,0x8B,0} },        /*158*/
+      { {     0x8C,0},{     0xf0,0x8C,0} }, { {     0x8D,0},{     0xf0,0x8D,0} }, { {          0},{               0} }, { {     0x7F,0},{     0xf0,0x7F,0} },        /*15c*/
+      { {          0},{               0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { {          0},{               0} },        /*160*/
+      { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} },        /*164*/
+      { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} },        /*168*/
+      { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { {          0},{               0} },        /*16c*/
+      { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} },        /*170*/
+      { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { {          0},{               0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} },        /*174*/
+      { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} },        /*178*/
+      { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} },        /*17c*/
+
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*180*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*184*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*188*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*18c*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*190*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*194*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*198*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*19c*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1ac*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1cc*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1dc*/
+      { {          0},{               0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { {          0},{               0} },        /*1ec*/
+      { {          0},{               0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f0*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f4*/
+      { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f8*/
+      { {          0},{               0} }, { {          0},{               0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} }         /*1fc*/
+      // clang-format on
+};
+
+static void
+keyboard_at_set_scancode_set(void)
+{
+    switch (keyboard_mode) {
+        default:
+        case 0x01:
+            keyboard_set_table(scancode_set1);
+            break;
+
+        case 0x02:
+            keyboard_set_table(scancode_set2);
+            break;
+
+        case 0x03:
+            keyboard_set_table(scancode_set3);
+            break;
+    }
+}
+
+static void
+add_data_vals(atkbc_dev_t *dev, uint8_t *val, uint8_t len)
+{
+    for (uint8_t i = 0; i < len; i++)
+        kbc_at_dev_queue_add(dev, val[i], 1);
+}
+
+static void
+add_data_kbd(uint16_t val)
+{
+    atkbc_dev_t *dev = SavedKbd;
+    uint8_t  fake_shift[4];
+    uint8_t  num_lock = 0;
+    uint8_t  shift_states = 0;
+
+    //keyboard_get_states(NULL, &num_lock, NULL);
+    shift_states = 0; // keyboard_get_shift() &STATE_SHIFT_MASK;
+
+    switch (val) {
+        case FAKE_LSHIFT_ON:
+            keyboard_at_log("%s: Fake left shift on, scan code: ", dev->name);
+            if (num_lock) {
+                if (shift_states) {
+                    keyboard_at_log("N/A (one or both shifts on)\n");
+                    break;
+                } else {
+                    /* Num lock on and no shifts are pressed, send non-inverted fake shift. */
+                    switch (keyboard_mode & 0x02) {
+                        case 1:
+                            fake_shift[0] = 0xe0;
+                            fake_shift[1] = 0x2a;
+                            add_data_vals(dev, fake_shift, 2);
+                            break;
+
+                        case 2:
+                            fake_shift[0] = 0xe0;
+                            fake_shift[1] = 0x12;
+                            add_data_vals(dev, fake_shift, 2);
+                            break;
+
+                        default:
+                            keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
+                            break;
+                    }
+                }
+            } else {
+                if (shift_states & STATE_LSHIFT) {
+                    /* Num lock off and left shift pressed. */
+                    switch (keyboard_mode & 0x02) {
+                        case 1:
+                            fake_shift[0] = 0xe0;
+                            fake_shift[1] = 0xaa;
+                            add_data_vals(dev, fake_shift, 2);
+                            break;
+
+                        case 2:
+                            fake_shift[0] = 0xe0;
+                            fake_shift[1] = 0xf0;
+                            fake_shift[2] = 0x12;
+                            add_data_vals(dev, fake_shift, 3);
+                            break;
+
+                        default:
+                            keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
+                            break;
+                    }
+                }
+                if (shift_states & STATE_RSHIFT) {
+                    /* Num lock off and right shift pressed. */
+                    switch (keyboard_mode & 0x02) {
+                        case 1:
+                            fake_shift[0] = 0xe0;
+                            fake_shift[1] = 0xb6;
+                            add_data_vals(dev, fake_shift, 2);
+                            break;
+
+                        case 2:
+                            fake_shift[0] = 0xe0;
+                            fake_shift[1] = 0xf0;
+                            fake_shift[2] = 0x59;
+                            add_data_vals(dev, fake_shift, 3);
+                            break;
+
+                        default:
+                            keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
+                            break;
+                    }
+                }
+                keyboard_at_log(shift_states ? "" : "N/A (both shifts off)\n");
+            }
+            break;
+
+        case FAKE_LSHIFT_OFF:
+            keyboard_at_log("%s: Fake left shift on, scan code: ", dev->name);
+            if (num_lock) {
+                if (shift_states) {
+                    keyboard_at_log("N/A (one or both shifts on)\n");
+                    break;
+                } else {
+                    /* Num lock on and no shifts are pressed, send non-inverted fake shift. */
+                    switch (keyboard_mode & 0x02) {
+                        case 1:
+                            fake_shift[0] = 0xe0;
+                            fake_shift[1] = 0xaa;
+                            add_data_vals(dev, fake_shift, 2);
+                            break;
+
+                        case 2:
+                            fake_shift[0] = 0xe0;
+                            fake_shift[1] = 0xf0;
+                            fake_shift[2] = 0x12;
+                            add_data_vals(dev, fake_shift, 3);
+                            break;
+
+                        default:
+                            keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
+                            break;
+                    }
+                }
+            } else {
+                if (shift_states & STATE_LSHIFT) {
+                    /* Num lock off and left shift pressed. */
+                    switch (keyboard_mode & 0x02) {
+                        case 1:
+                            fake_shift[0] = 0xe0;
+                            fake_shift[1] = 0x2a;
+                            add_data_vals(dev, fake_shift, 2);
+                            break;
+
+                        case 2:
+                            fake_shift[0] = 0xe0;
+                            fake_shift[1] = 0x12;
+                            add_data_vals(dev, fake_shift, 2);
+                            break;
+
+                        default:
+                            keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
+                            break;
+                    }
+                }
+                if (shift_states & STATE_RSHIFT) {
+                    /* Num lock off and right shift pressed. */
+                    switch (keyboard_mode & 0x02) {
+                        case 1:
+                            fake_shift[0] = 0xe0;
+                            fake_shift[1] = 0x36;
+                            add_data_vals(dev, fake_shift, 2);
+                            break;
+
+                        case 2:
+                            fake_shift[0] = 0xe0;
+                            fake_shift[1] = 0x59;
+                            add_data_vals(dev, fake_shift, 2);
+                            break;
+
+                        default:
+                            keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
+                            break;
+                    }
+                }
+                keyboard_at_log(shift_states ? "" : "N/A (both shifts off)\n");
+            }
+            break;
+
+        default:
+            kbc_at_dev_queue_add(dev, (uint8_t)val, 1);
+            break;
+    }
+}
+
+void
+keyboard_at_clear_data(void *priv)
+{
+    atkbc_dev_t *dev = (atkbc_dev_t *)priv;
+
+    dev->flags &= ~FLAG_CTRLDAT;
+}
+
+static void
+keyboard_at_set_defaults(atkbc_dev_t *dev)
+{
+    dev->rate = 1;
+
+    keyboard_set3_all_break = 0;
+    keyboard_set3_all_repeat = 0;
+    memset(keyboard_set3_flags, 0, 512);
+
+    keyboard_mode = 0x02;
+    keyboard_at_set_scancode_set();
+}
+
+static void
+keyboard_at_bat(void *priv)
+{
+    atkbc_dev_t *dev = (atkbc_dev_t *)priv;
+
+    keyboard_at_set_defaults(dev);
+
+    keyboard_scan = 1;
+
+    kbc_at_dev_queue_add(dev, 0xaa, 0);
+}
+
+static void
+keyboard_at_invalid_cmd(atkbc_dev_t *dev)
+{
+    keyboard_at_log("%s: Invalid command\n", dev->name);
+    kbc_at_dev_queue_add(dev, inv_cmd_response, 0);
+}
+
+
+void keyboard_at_write(uint8_t val, void *priv)
+{
+    atkbc_dev_t *dev = (atkbc_dev_t *)priv;
+    //uint8_t val;
+
+    //if (dev->port == NULL)
+    //    return;
+
+    //val = dev->port->dat;
+
+    dev->state = DEV_STATE_MAIN_OUT;
+
+    if ((val < 0xed) && (dev->flags & FLAG_CTRLDAT)) {
+        dev->flags &= ~FLAG_CTRLDAT;
+
+        switch (dev->command) {
+
+            case 0xfb:
+            case 0xfc:
+            case 0xfd:
+                // not implemented, ignore value, return ack to keep DraCo happy */
+                kbc_at_dev_queue_add(dev, 0xfa, 0);
+                break;
+
+            case 0xed: /* Set/reset LEDs */
+                kbc_at_dev_queue_add(dev, 0xfa, 0);
+                keyboard_at_log("%s: Set/reset LEDs [%02X]\n", dev->name, val);
+                break;
+
+            case 0xf0: /* Get/set scancode set */
+                kbc_at_dev_queue_add(dev, (val > 3) ? 0xfe : 0xfa, 0);
+                switch (val) {
+                    case 0x00:
+                        keyboard_at_log("%s: Get scan code set [%02X]\n", dev->name, keyboard_mode);
+                        kbc_at_dev_queue_add(dev, keyboard_mode, 0);
+                        break;
+                    case 0x01:
+                    case 0x02:
+                    case 0x03:
+                        keyboard_mode = val;
+                        keyboard_at_log("%s: Set scan code set [%02X]\n", dev->name, keyboard_mode);
+                        keyboard_at_set_scancode_set();
+                        break;
+                    default:
+                        /* Fatal so any instance of anything attempting to set scan code > 3 can be reported to us. */
+                        fatalx("%s: Scan code set [%02X] invalid, resend\n", dev->name, val);
+                        dev->flags |= FLAG_CTRLDAT;
+                        dev->state = DEV_STATE_MAIN_WANT_IN;
+                        break;
+                }
+                break;
+
+            case 0xf3: /* set typematic rate/delay */
+                if (val & 0x80) {
+                    keyboard_at_log("%s: Set typematic rate/delay [%02X] has bit 7 set - invalid\n", dev->name, val);
+                    dev->flags |= FLAG_CTRLDAT;      /* Resend = keep waiting for parameter. */
+                    kbc_at_dev_queue_add(dev, 0xfe, 0); /* Command response */
+                    dev->state = DEV_STATE_MAIN_WANT_IN;
+                } else {
+                    dev->rate = val;
+                    kbc_at_dev_queue_add(dev, 0xfa, 0); /* Command response */
+                    keyboard_at_log("%s: Set typematic rate/delay [%02X]\n", dev->name, val);
+                }
+                break;
+
+            default:
+                fatalx("%s: Parameter [%02X] for invalid command [%02X] - possibly memory corruption!\n", dev->name, val, dev->command);
+                kbc_at_dev_queue_add(dev, 0xfe, 0);
+        }
+    } else {
+        if (dev->flags & FLAG_CTRLDAT) {
+            /* Special case - another command during another command that wants input - proceed
+               as normal but do not cancel the command (so keep waiting for input), unless the
+               command in progress is ED (Set/reset LEDs). */
+            if (val == 0xed) {
+                keyboard_scan = 1;
+                dev->flags &= ~FLAG_CTRLDAT;
+            } else
+                dev->state = DEV_STATE_MAIN_WANT_IN;
+        }
+
+        switch (val) {
+            case 0xed: /* set/reset LEDs */
+                dev->command = val;
+                keyboard_at_log("%s: set/reset LEDs\n", dev->name);
+                dev->flags |= FLAG_CTRLDAT;
+                kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
+                dev->state = DEV_STATE_MAIN_WANT_IN;
+                break;
+
+            case 0xee: /* diagnostic echo */
+                keyboard_at_log("%s: ECHO\n", dev->name);
+                kbc_at_dev_queue_add(dev, 0xee, 0);
+                break;
+
+            case 0xef: /* Invalid command */
+            case 0xf1: /* Invalid command */
+                keyboard_at_log("%s: Invalid command\n", dev->name);
+                kbc_at_dev_queue_add(dev, inv_cmd_response, 0);
+                break;
+
+            case 0xf0: /* get/set scan code set */
+                if (dev->type & FLAG_PS2) {
+                    dev->command = val;
+                    keyboard_at_log("%s: scan code set\n", dev->name);
+                    dev->flags |= FLAG_CTRLDAT;
+                    kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
+                    dev->state = DEV_STATE_MAIN_WANT_IN;
+                } else
+                    keyboard_at_invalid_cmd(dev);
+                break;
+
+            case 0xf2: /* read ID */
+                keyboard_at_log("%s: read keyboard id\n", dev->name);
+                /* TODO: After keyboard type selection is implemented, make this
+                         return the correct keyboard ID for the selected type. */
+                kbc_at_dev_queue_add(dev, 0xfa, 0);
+                for (uint8_t i = 0; i < 4; i++) {
+                    if (id_bytes[dev->type][i] == 0)
+                        break;
+
+                    kbc_at_dev_queue_add(dev, id_bytes[dev->type][i], 0);
+                }
+                break;
+
+            case 0xf3: /* set command mode */
+                dev->command = val;
+                keyboard_at_log("%s: set typematic rate/delay\n", dev->name);
+                dev->flags |= FLAG_CTRLDAT;
+                kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
+                dev->state = DEV_STATE_MAIN_WANT_IN;
+                break;
+
+            case 0xf4: /* enable */
+                keyboard_at_log("%s: enable keyboard\n", dev->name);
+                keyboard_scan = 1;
+                kbc_at_dev_queue_add(dev, 0xfa, 0);
+                break;
+
+            case 0xf5: /* set defaults and disable keyboard */
+            case 0xf6: /* set defaults */
+                keyboard_at_log("%s: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard");
+                keyboard_scan = !(val & 0x01);
+                keyboard_at_log("%s: val = %02X, keyboard_scan = %i\n",
+                    dev->name, val, keyboard_scan);
+                kbc_at_dev_queue_add(dev, 0xfa, 0);
+
+                keyboard_set3_all_break = 0;
+                keyboard_set3_all_repeat = 0;
+                memset(keyboard_set3_flags, 0, 512);
+
+                keyboard_mode = 0x02;
+                keyboard_at_set_scancode_set();
+                break;
+
+            case 0xf7: /* set all keys to repeat */
+                if (dev->type & FLAG_PS2) {
+                    keyboard_at_log("%s: set all keys to repeat\n", dev->name);
+                    kbc_at_dev_queue_add(dev, 0xfa, 0);
+                    keyboard_set3_all_break = 1;
+                } else
+                    keyboard_at_invalid_cmd(dev);
+                break;
+
+            case 0xf8: /* set all keys to give make/break codes */
+                if (dev->type & FLAG_PS2) {
+                    keyboard_at_log("%s: set all keys to give make/break codes\n", dev->name);
+                    kbc_at_dev_queue_add(dev, 0xfa, 0);
+                    keyboard_set3_all_break = 1;
+                } else
+                    keyboard_at_invalid_cmd(dev);
+                break;
+
+            case 0xf9: /* set all keys to give make codes only */
+                if (dev->type & FLAG_PS2) {
+                    keyboard_at_log("%s: set all keys to give make codes only\n", dev->name);
+                    kbc_at_dev_queue_add(dev, 0xfa, 0);
+                    keyboard_set3_all_break = 0;
+                } else
+                    keyboard_at_invalid_cmd(dev);
+                break;
+
+            case 0xfa: /* set all keys to repeat and give make/break codes */
+                if (dev->type & FLAG_PS2) {
+                    keyboard_at_log("%s: set all keys to repeat and give make/break codes\n", dev->name);
+                    kbc_at_dev_queue_add(dev, 0xfa, 0);
+                    keyboard_set3_all_repeat = 1;
+                    keyboard_set3_all_break = 1;
+                } else
+                    keyboard_at_invalid_cmd(dev);
+                break;
+
+                /* TODO: Actually implement these commands. */
+            case 0xfb: /* set some keys to repeat */
+                keyboard_at_log("%s: set some keys to repeat\n", dev->name);
+                dev->flags |= FLAG_CTRLDAT;
+                kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
+                dev->state = DEV_STATE_MAIN_WANT_IN;
+                dev->command = val;
+                break;
+
+            case 0xfc: /* set some keys to give make/break codes */
+                keyboard_at_log("%s: set some keys to give make/break codes\n", dev->name);
+                dev->flags |= FLAG_CTRLDAT;
+                kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
+                dev->state = DEV_STATE_MAIN_WANT_IN;
+                dev->command = val;
+                break;
+
+            case 0xfd: /* set some keys to give make codes only */
+                keyboard_at_log("%s: set some keys to give make codes only\n", dev->name);
+                dev->flags |= FLAG_CTRLDAT;
+                kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
+                dev->state = DEV_STATE_MAIN_WANT_IN;
+                dev->command = val;
+                break;
+
+                /* TODO: This is supposed to resend multiple bytes after some commands. */
+            case 0xfe: /* resend last scan code */
+                keyboard_at_log("%s: resend last scan code\n", dev->name);
+                kbc_at_dev_queue_add(dev, 0xfa, 0);
+                kbc_at_dev_queue_add(dev, dev->last_scan_code, 0);
+                break;
+
+            case 0xff: /* reset */
+                kbc_at_dev_reset(dev, 1);
+                break;
+
+            default:
+                kbc_at_dev_queue_add(dev, 0xfe, 0);
+        }
+    }
+}
+
+
+static int oldkey[512];
+
+static uint8_t
+fake_shift_needed(uint16_t scan)
+{
+    switch (scan) {
+        case 0x137:    /* Yes, Print Screen requires the fake shifts. */
+        case 0x147:
+        case 0x148:
+        case 0x149:
+        case 0x14a:
+        case 0x14b:
+        case 0x14d:
+        case 0x14f:
+        case 0x150:
+        case 0x151:
+        case 0x152:
+        case 0x153:
+            return 1;
+        default:
+            return 0;
+    }
+}
+
+void
+draco_key_process(uint16_t scan, int down)
+{
+    const scancode *codes = scan_table;
+    int             c;
+
+    if (!codes)
+        return;
+
+    if (!keyboard_scan)
+        return;
+
+    oldkey[scan] = down;
+
+    if (down && (codes[scan].mk[0] == 0))
+        return;
+
+    if (!down && (codes[scan].brk[0] == 0))
+        return;
+
+    /* TODO: The keyboard controller needs to report the AT flag to us here. */
+    if (((keyboard_mode & 3) == 3)) {
+        if (!keyboard_set3_all_break && !down && !(keyboard_set3_flags[codes[scan].mk[0]] & 2))
+            return;
+    }
+
+    c = 0;
+    if (down) {
+        /* Send the special code indicating an opening fake shift might be needed. */
+        if (fake_shift_needed(scan))
+            add_data_kbd(0x100);
+        while (codes[scan].mk[c] != 0)
+            add_data_kbd(codes[scan].mk[c++]);
+    } else {
+        while (codes[scan].brk[c] != 0)
+            add_data_kbd(codes[scan].brk[c++]);
+        /* Send the special code indicating a closing fake shift might be needed. */
+        if (fake_shift_needed(scan))
+            add_data_kbd(0x101);
+    }
+}
+void *draco_keyboard_init(void)
+{
+    draco_kbd.type = 10;
+    memset(oldkey, 0, sizeof(oldkey));
+    return &draco_kbd;
+}
index 5782f1816fb51520b3ae7352e7a5ddf23905e517..02048453e6155683c71320707b23b521a19a73da 100644 (file)
     <ClCompile Include="..\..\jit\compemu_support.cpp" />
     <ClCompile Include="..\..\jit\compstbl.cpp" />
     <ClCompile Include="..\..\moduleripper.cpp" />
+    <ClCompile Include="keyboard_at_draco.cpp" />
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\fpux64_80.asm">
index 50433bf1ff113678e67b30ab527f5924178115e6..c1b68ddfca31e54454ad19a0caad9e1b6ab6ebf2 100644 (file)
     <ClCompile Include="..\..\pcem\vid_ncr.cpp">
       <Filter>pcem</Filter>
     </ClCompile>
+    <ClCompile Include="keyboard_at_draco.cpp">
+      <Filter>pcem</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\resources\35floppy.ico">
index 2d81dea4bc540abcae7ed0d302a0b66627889940..635d843f4cc92d2df23c4bac3132c843f41d95d7 100644 (file)
@@ -21,7 +21,7 @@ void mouse_serial_poll(int x, int y, int z, int b, void *p)
 
         if (!(serial->ier & 1))
                 return;
-        if (!x && !y && b == mouse->oldb)
+        if (!x && !y && b == mouse->oldb && !b)
                 return;
 
         mouse->oldb = b;
@@ -48,25 +48,26 @@ void mouse_serial_poll(int x, int y, int z, int b, void *p)
         }
 }
 
+void mousecallback(void *p)
+{
+    mouse_serial_t *mouse = (mouse_serial_t *)p;
+
+    if (mouse->mousepos == -1)
+    {
+        mouse->mousepos = 0;
+        serial_write_fifo(mouse->serial, 'M');
+    }
+}
+
 void mouse_serial_rcr(struct SERIAL *serial, void *p)
 {
         mouse_serial_t *mouse = (mouse_serial_t *)p;
         
         mouse->mousepos = -1;
-        timer_set_delay_u64(&mouse->mousedelay_timer, TIMER_USEC * 5000);
+        mousecallback(p);
+//        timer_set_delay_u64(&mouse->mousedelay_timer, TIMER_USEC * 5000);
 }
         
-void mousecallback(void *p)
-{
-        mouse_serial_t *mouse = (mouse_serial_t *)p;
-
-        if (mouse->mousepos == -1)
-        {
-                mouse->mousepos = 0;
-                serial_write_fifo(mouse->serial, 'M');
-        }
-}
-
 void *mouse_serial_init()
 {
         mouse_serial_t *mouse = (mouse_serial_t *)malloc(sizeof(mouse_serial_t));
@@ -80,6 +81,19 @@ void *mouse_serial_init()
         return mouse;
 }
 
+void *mouse_serial_init_draco()
+{
+    mouse_serial_t *mouse = (mouse_serial_t *)malloc(sizeof(mouse_serial_t));
+    memset(mouse, 0, sizeof(mouse_serial_t));
+
+    mouse->serial = &serial2;
+    serial2.rcr_callback = mouse_serial_rcr;
+    serial2.rcr_callback_p = mouse;
+
+    return mouse;
+}
+
+
 void mouse_serial_close(void *p)
 {
         mouse_serial_t *mouse = (mouse_serial_t *)p;
index 30dc5f563ccbf8c1e2b4e00862eb46564122d90b..c2b004c12a2539df7733ee8ac8c3daa3600c7730 100644 (file)
@@ -15,6 +15,9 @@ enum
 
 SERIAL serial1, serial2;
 
+static bool draco_serial;
+void x86_clearirq(uint8_t irqnum);
+void x86_doirq(uint8_t irqnum);
 
 void serial_reset()
 {
@@ -22,6 +25,8 @@ void serial_reset()
         serial2.iir = serial2.ier = serial2.lcr = 0;
         serial1.fifo_read = serial1.fifo_write = 0;
         serial2.fifo_read = serial2.fifo_write = 0;
+        serial1.iir = 1;
+        serial2.iir = 1;
 }
 
 void serial_update_ints(SERIAL *serial)
@@ -51,10 +56,31 @@ void serial_update_ints(SERIAL *serial)
                 serial->iir = 0;
         }
 
-        if (stat && ((serial->mctrl & 8) || PCJR))
-                picintlevel(1 << serial->irq);               
-        else
+        if (stat && ((serial->mctrl & 8) || PCJR)) {
+            if (draco_serial) {
+                x86_doirq(serial->irq);
+            } else {
+                picintlevel(1 << serial->irq);
+            }
+        } else {
+            if (draco_serial) {
+                x86_clearirq(serial->irq);
+            } else {
                 picintc(1 << serial->irq);
+            }
+        }
+}
+
+void serial_receive_callback(void *p)
+{
+    SERIAL *serial = (SERIAL *)p;
+
+    if (serial->fifo_read != serial->fifo_write)
+    {
+        serial->lsr |= 1;
+        serial->int_status |= SERIAL_INT_RECEIVE;
+        serial_update_ints(serial);
+    }
 }
 
 void serial_write_fifo(SERIAL *serial, uint8_t dat)
@@ -185,8 +211,13 @@ uint8_t serial_read(uint16_t addr, void *p)
                 serial->int_status &= ~SERIAL_INT_RECEIVE;
                 serial_update_ints(serial);
                 temp = serial_read_fifo(serial);
-                if (serial->fifo_read != serial->fifo_write)
+                if (serial->fifo_read != serial->fifo_write) {
+                    if (draco_serial) {
+                        serial_receive_callback(p);
+                    } else {
                         timer_set_delay_u64(&serial->receive_timer, 1000 * TIMER_USEC);
+                    }
+                }
                 break;
                 case 1:
                 if (serial->lcr & 0x80)
@@ -235,18 +266,6 @@ uint8_t serial_read(uint16_t addr, void *p)
         return temp;
 }
 
-void serial_receive_callback(void *p)
-{
-        SERIAL *serial = (SERIAL *)p;
-        
-        if (serial->fifo_read != serial->fifo_write)
-        {
-                serial->lsr |= 1;
-                serial->int_status |= SERIAL_INT_RECEIVE;
-                serial_update_ints(serial);
-        }
-}
-
 /*Tandy might need COM1 at 2f8*/
 void serial1_init(uint16_t addr, int irq, int has_fifo)
 {
@@ -257,6 +276,7 @@ void serial1_init(uint16_t addr, int irq, int has_fifo)
         serial1.rcr_callback = NULL;
         timer_add(&serial1.receive_timer, serial_receive_callback, &serial1, 0);
         serial1.has_fifo = has_fifo;
+        draco_serial = false;
 }
 void serial1_set(uint16_t addr, int irq)
 {
@@ -305,7 +325,10 @@ void draco_serial_init(void **s1, void **s2)
     serial_reset();
     serial1.has_fifo = 1;
     serial2.has_fifo = 1;
+    serial1.irq = 4;
+    serial2.irq = 4;
     *s1 = &serial1;
     *s2 = &serial2;
+    draco_serial = true;
 }
 
index 910356ad79992dc85ffe0a56d70e747f9410d71c..0dc0ffe35fa56dfd58c703d6bdd86e67431f7b34 100644 (file)
@@ -300,7 +300,7 @@ static struct romdata roms[] = {
        { _T("DraCo Boot ROM v1.3"), 1, 3, 1, 3, _T("DRACO\0"), 131072, 234, 2 | 4, 0, ROMTYPE_EXTCDTV, 0, 0, NULL,
        0x0e9c5899,0x82151324,0x01207554,0x60c8a068,0x4793ec18,0x3f744d74, NULL, NULL, 4 },
        { _T("DraCo Boot ROM v1.5"), 1, 5, 1, 5, _T("DRACO\0"), 131072, 311, 2 | 4, 0, ROMTYPE_EXTCDTV, 0, 0, NULL,
-       0x0f2959d5,0xe8fd5d15,0x08797693,0x99f1df97,0x2fe792fd,0x8146cf1d, NULL, NULL, 4 },
+       0x7b4cdd4a,0x4d383adb,0x85c681a3,0xb625dcda,0x7a229a17,0x6af4d161, NULL, NULL, 4 },
 
        { _T("CD32 KS ROM v3.1"), 3, 1, 40, 60, _T("CD32\0"), 524288, 18, 1, 0, ROMTYPE_KICKCD32, 0, 0, NULL,
        0x1e62d4a5, 0x3525BE88,0x87F79B59,0x29E017B4,0x2380A79E,0xDFEE542D, NULL, NULL, 1 },
diff --git a/x86.cpp b/x86.cpp
index 074feef58d746c293bc048b5f336080dad9145e5..a25232be33d2b66d2978e5d823bc782cc78fdef2 100644 (file)
--- a/x86.cpp
+++ b/x86.cpp
@@ -3303,6 +3303,8 @@ int is_x86_cpu(struct uae_prefs *p)
        }
        if (!xb || xb->x86_reset)
                return X86_STATE_STOP;
+       if (xb && xb->type < 0)
+               return X86_STATE_INACTIVE;
        return X86_STATE_ACTIVE;
 }
 
@@ -3575,22 +3577,27 @@ static void set_vga(struct x86_bridge *xb)
 void mouse_serial_poll(int x, int y, int z, int b, void *p);
 void mouse_ps2_poll(int x, int y, int z, int b, void *p);
 
-void x86_mouse(int port, int x, int y, int z, int b)
+bool x86_mouse(int port, int x, int y, int z, int b)
 {
        struct x86_bridge *xb = bridges[0];
        if (!xb || !xb->mouse_port || !xb->mouse_base || xb->mouse_port != port + 1)
-               return;
+               return false;
        switch (xb->mouse_type)
        {
                case 0:
                default:
+               if (b < 0)
+                       return true;
                mouse_serial_poll(x, y, z, b, xb->mouse_base);
-               break;
+               return true;
                case 1:
                case 2:
+               if (b < 0)
+                       return true;
                mouse_ps2_poll(x, y, z, b, xb->mouse_base);
-               break;
+               return true;
        }
+       return false;
 }
 
 void *mouse_serial_init();