]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Partial MacroSystem DraCo emulation
authorToni Wilen <twilen@winuae.net>
Mon, 1 Jan 2024 16:45:49 +0000 (18:45 +0200)
committerToni Wilen <twilen@winuae.net>
Mon, 1 Jan 2024 16:45:49 +0000 (18:45 +0200)
22 files changed:
casablanca.cpp [deleted file]
cfgfile.cpp
custom.cpp
devices.cpp
draco.cpp [new file with mode: 0644]
expansion.cpp
gfxboard.cpp
include/casablanca.h [deleted file]
include/cpuboard.h
include/draco.h [new file with mode: 0644]
include/gfxboard.h
include/ncr_scsi.h
include/rommgr.h
include/x86.h
memory.cpp
ncr_scsi.cpp
od-win32/sysconfig.h
od-win32/winuae_msvc15/winuae_msvc.vcxproj
od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters
pcem/serial.cpp
rommgr.cpp
x86.cpp

diff --git a/casablanca.cpp b/casablanca.cpp
deleted file mode 100644 (file)
index f73cb9c..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-#include "sysconfig.h"
-#include "sysdeps.h"
-
-#include "options.h"
-#include "uae.h"
-#include "memory.h"
-#include "newcpu.h"
-#include "casablanca.h"
-
-/*
-
-       53C710 (SCSI)
-       Base: 0x04000000
-       IRQ: 4
-       INTREQ: 7 (AUD0)
-
-       DracoMotion
-       Base: 0x20000000
-       IRQ: 3
-       INTREQ: 4 (COPER)
-       Size: 128k
-       Autoconfig: 83 17 30 00 47 54 00 00 00 00 00 00 00 00 00 00 (18260/23)
-
-       Mouse
-       Base: 0x02400BE3
-       IRQ: 4
-       INTREQ: 9 (AUD2)
-
-       Serial
-       Base: 0x02400FE3
-       IRQ: 4
-       INTREQ: 10 (AUD3)
-
-       Floppy:
-       Base: 0x02400003
-       IRQ: 5
-       INTREQ: 11 (RBF)
-*/
-
-static uae_u32 REGPARAM2 casa_lget(uaecptr addr)
-{
-       static int max = 100;
-       if (max < 0) {
-               write_log(_T("casa_lget %08x %08x\n"), addr, M68K_GETPC);
-               max--;
-       }
-
-       return 0;
-}
-static uae_u32 REGPARAM2 casa_wget(uaecptr addr)
-{
-       static int max = 100;
-       if (max >= 0) {
-               write_log(_T("casa_wget %08x %08x\n"), addr, M68K_GETPC);
-               max--;
-       }
-
-       return 0;
-}
-
-static uae_u32 REGPARAM2 casa_bget(uaecptr addr)
-{
-       uae_u8 v = 0;
-
-       static int max = 100;
-       if (max >= 0) {
-               write_log(_T("casa_bget %08x %08x\n"), addr, M68K_GETPC);
-               max--;
-       }
-
-
-       // casa
-       if (addr == 0x020007c3)
-               v = 4;
-
-       // draco
-       if (addr == 0x02000009)
-               v = 4;
-
-       return v;
-}
-
-static void REGPARAM2 casa_lput(uaecptr addr, uae_u32 l)
-{
-       static int max = 100;
-       if (max < 0)
-               return;
-       max--;
-
-       write_log(_T("casa_lput %08x %08x %08x\n"), addr, l, M68K_GETPC);
-}
-static void REGPARAM2 casa_wput(uaecptr addr, uae_u32 w)
-{
-       static int max = 100;
-       if (max < 0)
-               return;
-       max--;
-
-       write_log(_T("casa_wput %08x %04x %08x\n"), addr, w & 0xffff, M68K_GETPC);
-}
-
-static void REGPARAM2 casa_bput(uaecptr addr, uae_u32 b)
-{
-       static int max = 100;
-       if (max < 0)
-               return;
-       max--;
-
-       write_log(_T("casa_bput %08x %02x %08x\n"), addr, b & 0xff, M68K_GETPC);
-}
-
-static addrbank casa_ram_bank = {
-       casa_lget, casa_wget, casa_bget,
-       casa_lput, casa_wput, casa_bput,
-       default_xlate, default_check, NULL, NULL, _T("Casablanca IO"),
-       dummy_lgeti, dummy_wgeti, ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE,
-};
-
-
-void casablanca_map_overlay(void)
-{
-       // Casablanca has ROM at address zero, no chip ram, no overlay.
-       map_banks(&kickmem_bank, 524288 >> 16, 524288 >> 16, 0);
-       map_banks(&extendedkickmem_bank, 0 >> 16, 524288 >> 16, 0);
-       map_banks(&casa_ram_bank, 0x02000000 >> 16, 0x01000000 >> 16, 0);
-       // at least draco has rom here
-       map_banks(&kickmem_bank, 0x02c00000 >> 16, 524288 >> 16, 0);
-}
index 40df0b421cc6abc70da796a9931b4bfc4d9d191d..537220dc7cd810ee918e1be26cbe5201a5f79b04 100644 (file)
@@ -9457,7 +9457,7 @@ static int bip_casablanca(struct uae_prefs *p, int config, int compa, int romche
        case 2:
                p->cpu_model = 68060;
                p->fpu_model = 68060;
-               p->mmu_model = 68040;
+               p->mmu_model = 68060;
                break;
        }
        p->chipset_mask = CSMASK_AGA | CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE;
@@ -9472,6 +9472,30 @@ static int bip_casablanca(struct uae_prefs *p, int config, int compa, int romche
        return configure_rom(p, roms, romcheck);
 }
 
+static int bip_draco(struct uae_prefs *p, int config, int compa, int romcheck)
+{
+       int roms[8];
+
+       roms[0] = 16;
+       roms[1] = -1;
+
+       p->bogomem.size = 0;
+       p->chipmem.size = 0x200000;
+       p->cpu_model = 68060;
+       p->fpu_model = 68060;
+       p->mmu_model = 68060;
+       p->chipset_mask = CSMASK_AGA | CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE;
+       p->cpu_compatible = p->address_space_24 = 0;
+       p->m68k_speed = -1;
+       p->immediate_blits = 0;
+       p->produce_sound = 2;
+       p->floppyslots[0].dfxtype = DRV_NONE;
+       p->floppyslots[1].dfxtype = DRV_NONE;
+       p->cs_compatible = CP_DRACO;
+       built_in_chipset_prefs(p);
+       return configure_rom(p, roms, romcheck);
+}
+
 int built_in_prefs (struct uae_prefs *p, int model, int config, int compa, int romcheck)
 {
        int v = 0;
@@ -9521,6 +9545,9 @@ int built_in_prefs (struct uae_prefs *p, int model, int config, int compa, int r
        case 13:
                v = bip_super (p, config, compa, romcheck);
                break;
+       case 14:
+               v = bip_draco(p, config, compa, romcheck);
+               break;
        }
        if ((p->cpu_model >= 68020 || !p->cpu_memory_cycle_exact) && !p->immediate_blits)
                p->waiting_blits = 1;
index 04d0385571775fac1ae3b9df9be67f5e2cf07558..cd1b401acda3faf57f1459abc6b7115ea3a69bf1 100644 (file)
@@ -14551,6 +14551,11 @@ void custom_reset(bool hardreset, bool keyboardreset)
                maxhpos = ntsc ? MAXHPOS_NTSC : MAXHPOS_PAL;
                maxhpos_short = maxhpos;
                updateextblk();
+
+               if (currprefs.cs_compatible == CP_DRACO) {
+                       // fake draco interrupts
+                       INTENA(0x8000 | 0x4000 | 0x1000 | 0x2000 | 0x0080 | 0x0010 | 0x0008 | 0x0001);
+               }
        }
 
        specialmonitor_reset();
index 5c111794df34d200c5b15b14eda40f476f0169b6..aaf8444de1845de763e8d25d2bdba08a607d32b8 100644 (file)
@@ -63,6 +63,7 @@
 #ifdef RETROPLATFORM
 #include "rp.h"
 #endif
+#include "draco.h"
 #include "dsp3210/dsp_glue.h"
 
 #define MAX_DEVICE_ITEMS 64
@@ -351,7 +352,9 @@ void virtualdevice_free(void)
 #endif
        ethernet_enumerate_free();
        rtarea_free();
-
+#ifdef WITH_DRACO
+       draco_reset();
+#endif
        execute_device_items(device_leaves, device_leave_cnt);
 }
 
@@ -410,6 +413,9 @@ void virtualdevice_init (void)
 #ifdef WITH_TABLETLIBRARY
        tabletlib_install ();
 #endif
+#ifdef WITH_DRACO
+       draco_init();
+#endif
 }
 
 void devices_restore_start(void)
diff --git a/draco.cpp b/draco.cpp
new file mode 100644 (file)
index 0000000..395f376
--- /dev/null
+++ b/draco.cpp
@@ -0,0 +1,992 @@
+
+/* MacroSystem DraCo
+ *
+ * Toni Wilen 2023-2024
+ */
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "options.h"
+#include "uae.h"
+#include "memory.h"
+#include "newcpu.h"
+#include "devices.h"
+#include "custom.h"
+#include "debug.h"
+#include "x86.h"
+#include "ncr_scsi.h"
+#include "draco.h"
+#include "zfile.h"
+
+static int maxcnt = 100;
+
+
+/*
+       .asciz  "kbd/soft"      | 1: native keyboard, soft ints
+       .asciz  "cia/zbus"      | 2: cia, PORTS
+       .asciz  "lclbus"        | 3: local bus, e.g. Altais vbl
+       .asciz  "drscsi"        | 4: mainboard scsi
+       .asciz  "superio"       | 5: superio chip
+       .asciz  "lcl/zbus"      | 6: lcl/zorro lev6
+       .asciz  "buserr"        | 7: nmi: bus timeout
+*/
+
+// INTENA  : 0x01000001
+// INTPEN  : 0x01400001
+// INTFRC  : 0x01800001
+// ?       : 0x01c00001
+// IO      : 0x02000000 (Misc control, 1-wire RTC)
+// SuperIO : 0x02400000 (PC-style serial, parallel, WD floppy) PC IO = Amiga address >> 2
+// CIA     : 0x02800000 (only in pre-4 revisions)
+// KS ROM  : 0x02c00000 (A3000 KS 3.1)
+// Z2      : 0x03e80000
+// SCSI    : 0x04000000 (53C710)
+// SVGA    : 0x20000000 (NCR 77C32BLT)
+
+// Interrupt
+
+// Bit 0: Master enable / INT1
+// Bit 1: INT4 (SCSI)
+// Bit 2: INT2 (Timer)
+// Bit 3: INT6
+
+// SVGA vblank: INT3
+// SuperIO: INT5
+
+
+// IO:
+
+// IO_control   : 01
+#define DRCNTRL_FDCINTENA 1
+#define DRCNTRL_KBDDATOUT 2
+#define DRCNTRL_KBDCLKOUT 4
+#define DRCNTRL_WDOGDIS 8
+#define DRCNTRL_WDOGDAT 16
+#define DRCNTRL_KBDINTENA 32
+#define DRCNTRL_KBDKBDACK 64
+#define DRCNTRL_SCSITERM 128
+
+// IO_status    : 03
+#define DRSTAT_CLKDAT 1 // (1-wire data)
+#define DRSTAT_KBDDATIN 2
+#define DRSTAT_KBDCLKIN 4
+#define DRSTAT_KBDRECV 8
+#define DRSTAT_CLKBUSY 16 // (1-wire, busy)
+#define DRSTAT_BUSTIMO 32
+#define DRSTAT_SCSILED 64
+
+// IO_KBD_data  : 05
+
+// IO_status2   : 07
+#define DRSTAT2_KBDBUSY 1
+#define DRSTAT2_PARIRQPEN 4
+#define DRSTAT2_PARIRQENA 8
+#define DRSTAT2_TMRINTENA 16
+#define DRSTAT2_TMRIRQPEN 32
+
+// Revision     : 09 (write=timer reset)
+// IO_TimerHI   : 0B
+// IO_TimerLO   : 0D
+// unused       : 0F
+// IO_clockw0   : 11 (1-wire, write 1)
+// IO_clockw1   : 13 (1-wire, write 0)
+// IO_clockrst  : 15 (1-wire, reset)
+// IO_KBD_Reset : 17
+// IO_bustimeout: 19 
+// IO_scsiledres: 1b
+// IO_fdcread   : 1d
+// IO_parrst    : 1f
+
+
+/*
+
+       53C710 (SCSI)
+       Base: 0x04000000
+       IRQ: 4
+       INTREQ: 7 (AUD0)
+
+       DracoMotion
+       Base: 0x20000000
+       IRQ: 3
+       INTREQ: 4 (COPER)
+       Size: 128k
+       Autoconfig: 83 17 30 00 47 54 00 00 00 00 00 00 00 00 00 00 (18260/23)
+
+       Mouse
+       Base: 0x02400BE3
+       IRQ: 4
+       INTREQ: 9 (AUD2)
+
+       Serial
+       Base: 0x02400FE3
+       IRQ: 4
+       INTREQ: 10 (AUD3)
+
+       Floppy:
+       Base: 0x02400003
+       IRQ: 5
+       INTREQ: 11 (RBF)
+*/
+
+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);
+
+static void *draco_serial[2];
+
+static uae_u8 draco_intena, draco_intpen, draco_svga_irq_state;
+static uae_u16 draco_timer, draco_timer_latch;
+static bool draco_timer_latched;
+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 void draco_irq(void)
+{
+       uae_u16 irq = 0;
+       if (draco_intena & 1) {
+               uae_u16 mask = draco_intena & draco_intpen;
+               if (mask) {
+                       if (mask & 1) { // INT1
+                               irq |= 1;
+                       }
+                       if (mask & 2) { // INT4
+                               irq |= 0x80;
+                       }
+                       if (mask & 4) { // INT2
+                               irq |= 8;
+                       }
+                       if (mask & 8) { // INT6
+                               irq |= 0x2000;
+                       }
+               }
+               if (draco_svga_irq_state) {
+                       irq |= 0x0010; // INT3
+               }
+               if (draco_fdc_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)) {
+                       irq |= 1;
+               }
+       }
+       INTREQ_f(0x7fff);
+       if (irq) {
+               INTREQ_f(0x8000 | irq);
+               doint();
+       }
+
+}
+
+void draco_svga_irq(bool state)
+{
+       draco_svga_irq_state = state;
+       draco_irq();
+}
+
+static uae_u8 draco_kbd_state, draco_kbd_state2;
+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_u8 draco_keyboard_read(uae_u8 v)
+{
+       if (draco_kbd_state2) {
+               draco_reg[3] &= ~DRSTAT_KBDCLKIN;
+
+               draco_kbd_poll++;
+               if (draco_kbd_state2 > 0 && draco_kbd_poll >= 4) {
+                       draco_reg[3] |= DRSTAT_KBDCLKIN;
+                       draco_kbd_code >>= 1;
+                       draco_kbd_code |= (draco_reg[1] & DRCNTRL_KBDDATOUT) ? 0x8000 : 0;
+                       draco_kbd_state2++;
+                       draco_kbd_poll = 0;
+               }
+       }
+       return v;
+}
+static void draco_keyboard_write(uae_u8 v)
+{
+       v &= DRCNTRL_KBDDATOUT | DRCNTRL_KBDCLKOUT;
+       if (v == draco_kbd_state) {
+               return;
+       }
+
+       // start receive
+       if ((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_state = v;
+}
+
+static void draco_keyboard_done(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;
+               }
+       }
+       draco_reg[3] &= ~DRSTAT_KBDCLKIN;
+       draco_reg[3] &= ~DRSTAT_KBDRECV;
+       draco_kbd_state2 = 0;
+       draco_kbd_poll = 0;
+}
+
+static void draco_keyboard_send(void)
+{
+       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();
+       }
+}
+
+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;
+static uae_s16 draco_1wire_sram_offset, draco_1wire_sram_offset_copy;
+static uae_s8 draco_1wire_rom_offset, draco_1wire_cnt, draco_1wire_busycnt;
+static bool draco_1wire_bit;
+
+#define DS_ROM_MATCH            0x55
+#define DS_ROM_SEARCH           0xf0
+#define DS_ROM_SKIP             0xcc
+#define DS_ROM_READ             0x33
+#define DS_WRITE_SCRATCHPAD     0x0f
+#define DS_READ_SCRATCHPAD      0xaa
+#define DS_COPY_SCRATCHPAD      0x55
+
+static void draco_1wire_rtc_count(void)
+{
+       uae_u8 *rtc = draco_1wire_sram + 512;
+       rtc[2]++;
+       if (rtc[2] == 0) {
+               rtc[3]++;
+               if (rtc[3] == 0) {
+                       rtc[4]++;
+                       if (rtc[4] == 0) {
+                               rtc[5]++;
+                       }
+               }
+       }
+}
+
+static void draco_1wire_rtc_validate(void)
+{
+       uae_u8 *rtc = draco_1wire_sram + 512;
+       rtc[0] &= ~7;
+       draco_1wire_rtc_count();
+}
+
+static void draco_1wire_set_bit(void)
+{
+       uae_u8 *dptr = NULL;
+       int maxlen = 0;
+       if (draco_1wire_cmd == DS_ROM_SEARCH) {
+               dptr = draco_1wire_sram;
+               maxlen = sizeof(draco_1wire_sram);
+       } else if (draco_1wire_cmd == DS_READ_SCRATCHPAD) {
+               dptr = draco_1wire_scratchpad;
+               maxlen = sizeof(draco_1wire_scratchpad);
+       }
+       if (dptr && draco_1wire_sram_offset >= 0 && draco_1wire_dir) {
+               if (draco_1wire_rom_offset >= 0) {
+                       draco_1wire_dat = draco_1wire_rom[draco_1wire_rom_offset];
+                       uae_u8 bit = (draco_1wire_rom[draco_1wire_rom_offset] >> draco_1wire_cnt) & 1;
+                       draco_1wire_bit = bit != 0;
+               } else {
+                       if (draco_1wire_sram_offset >= maxlen) {
+                               draco_1wire_dat = 0xff;
+                               draco_1wire_bit = true;
+                       } else {
+                               if (draco_1wire_sram_offset >= 0) {
+                                       draco_1wire_dat = dptr[draco_1wire_sram_offset];
+                                       uae_u8 bit = (dptr[draco_1wire_sram_offset] >> draco_1wire_cnt) & 1;
+                                       draco_1wire_bit = bit != 0;
+                               }
+                       }
+               }
+       }
+}
+
+static uae_u8 draco_1wire_read(uae_u8 v)
+{
+       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)) {
+               write_log("draco read 1-wire SRAM byte %02x, %02x\n", draco_1wire_dat, draco_1wire_bytes);
+               draco_1wire_cnt = 0;
+               draco_1wire_bytes++;
+               if (draco_1wire_rom_offset >= 0) {
+                       if (draco_1wire_rom_offset == sizeof(draco_1wire_rom)) {
+                               draco_1wire_rom_offset = -1;
+                       }
+               } else if (draco_1wire_cmd == DS_READ_SCRATCHPAD) {
+                       if (draco_1wire_sram_offset == 2) {
+                               draco_1wire_sram_offset = (draco_1wire_sram_offset_copy & 31) + 3;
+                       } else if (draco_1wire_sram_offset < 2) {
+                               draco_1wire_sram_offset++;
+                       } else {
+                               draco_1wire_sram_offset++;
+                               draco_1wire_sram_offset -= 3;
+                               draco_1wire_sram_offset &= 31;
+                               draco_1wire_sram_offset += 3;
+                       }
+               } else {
+                       draco_1wire_sram_offset++;
+               }
+       }
+       
+       if (draco_reg[3] & DRSTAT_CLKBUSY) {
+               draco_1wire_busycnt--;
+               if (draco_1wire_busycnt < 0) {
+                       draco_reg[3] &= ~DRSTAT_CLKBUSY;
+               }
+       }
+
+       return v;
+}
+
+static void draco_1wire_busy(void)
+{
+       draco_reg[3] |= DRSTAT_CLKBUSY;
+       draco_1wire_busycnt = 3;
+}
+
+
+static void draco_1wire_send(int bit)
+{
+       if (draco_1wire_dir) {
+               draco_1wire_set_bit();
+               draco_1wire_cnt++;
+               draco_1wire_busy();
+       }
+
+       if (!draco_1wire_dir) {
+               draco_1wire_data[0] >>= 1;
+               draco_1wire_data[0] |= bit ? 0x80 : 0;
+               draco_1wire_cnt++;
+               draco_1wire_busy();
+       }
+       if (draco_1wire_cnt == 8 && !draco_1wire_dir) {
+               bool gotcmd = false;
+               if (!draco_1wire_state) {
+                       draco_1wire_cmd = draco_1wire_data[0];
+                       if (draco_1wire_cmd != DS_ROM_SKIP) {
+                               draco_1wire_state = 1;
+                               gotcmd = true;
+                       } else {
+                               draco_1wire_rom_offset = -1;
+                       }
+               }
+               for (int i = sizeof(draco_1wire_data) - 1; i >= 1; i--) {
+                       draco_1wire_data[i] = draco_1wire_data[i - 1];
+               }
+               write_log("draco received 1-wire byte %02x, cnt %02x\n", draco_1wire_data[0], draco_1wire_bytes);
+               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) {
+                       draco_1wire_sram_offset = (draco_1wire_data[1] << 8) | draco_1wire_data[2];
+                       draco_1wire_dir = 1;
+                       draco_1wire_bytes = 0;
+                       write_log("draco received 1-wire SRAM read command, offset %04x\n", draco_1wire_sram_offset);
+               }
+               // 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));
+                       write_log("draco received 1-wire SRAM scratchpad write command, offset %04x\n", draco_1wire_sram_offset);
+               }
+               // read scratchpad
+               if (draco_1wire_cmd == DS_READ_SCRATCHPAD) {
+                       draco_1wire_sram_offset = 0;
+                       draco_1wire_dir = 1;
+                       draco_1wire_bytes = 0;
+                       draco_1wire_set_bit();
+                       write_log("draco received 1-wire SRAM scratchpad read command\n");
+               }
+               // copy scratchpad
+               if (draco_1wire_cmd == DS_COPY_SCRATCHPAD && draco_1wire_data[4] == DS_COPY_SCRATCHPAD) {
+                       draco_1wire_sram_offset = 0;
+                       uae_u8 status = draco_1wire_data[1];
+                       if (status == draco_1wire_scratchpad[2] &&
+                               draco_1wire_data[2] == draco_1wire_scratchpad[1] &&
+                               draco_1wire_data[3] == draco_1wire_scratchpad[0]) {
+                               int start = draco_1wire_sram_offset_copy & 31;
+                               int offset = draco_1wire_sram_offset_copy & ~31;
+                               write_log("draco received 1-wire SRAM scratchpad copy command, accepted\n");
+                               for (int i = 0; i < 32; i++) {
+                                       draco_1wire_sram[offset + start] = draco_1wire_scratchpad[start + 3];
+                                       write_log("draco 1-wire SRAM scratchpad copy %02x -> %04x\n", draco_1wire_sram[offset + start], offset + start);
+                                       if (start == (draco_1wire_scratchpad[2] & 31)) {
+                                               break;
+                                       }
+                                       start++;
+                                       start &= 31;
+                               }
+                               draco_1wire_scratchpad[0] |= 0x80;
+                               draco_1wire_rtc_validate();
+                               draco_1wire_busy();
+                               draco_1wire_bit = 0;
+                       } else {
+                               write_log("draco received 1-wire SRAM scratchpad copy command, rejected\n");
+                               draco_1wire_busy();
+                       }
+               }
+       }
+}
+static void draco_1wire_reset(void)
+{
+       if (draco_1wire_state) {
+               // write scratchpad
+               if (draco_1wire_cmd == DS_WRITE_SCRATCHPAD) {
+                       int len = draco_1wire_bytes - 4;
+                       int start = draco_1wire_sram_offset_copy;
+                       for (int i = 0; i < len; i++) {
+                               draco_1wire_scratchpad[(start & 31) + 3] = draco_1wire_data[len - i];
+                               start++;
+                               start &= 31;
+                       }
+                       draco_1wire_scratchpad[0] = draco_1wire_sram_offset_copy >> 0;
+                       draco_1wire_scratchpad[1] = draco_1wire_sram_offset_copy >> 8;
+                       draco_1wire_scratchpad[2] = (start - 1) & 31;
+                       if (len > 32) {
+                               draco_1wire_scratchpad[2] |= 0x40;
+                       } else if (len < 32) {
+                               draco_1wire_scratchpad[2] |= 0x20;
+                       }
+                       write_log("draco received 1-wire SRAM scratchpad write, %d bytes received\n", len);
+               }
+       }
+
+       memset(draco_1wire_data, 0, sizeof(draco_1wire_data));
+       draco_1wire_cnt = 0;
+       draco_1wire_state = 0;
+       draco_1wire_dir = 0;
+       draco_1wire_bytes = 0;
+       draco_1wire_sram_offset = -1;
+       draco_1wire_rom_offset = 0;
+       write_log("draco 1-wire reset\n");
+}
+
+static uae_u32 REGPARAM2 draco_lget(uaecptr addr)
+{
+       uae_u32 l = 0;
+
+       if ((addr & 0x07c00000) == 0x04000000) {
+
+               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;
+       } else {
+               write_log(_T("draco_lget %08x %08x\n"), addr, M68K_GETPC);
+       }
+
+       return l;
+}
+static uae_u32 REGPARAM2 draco_wget(uaecptr addr)
+{
+       write_log(_T("draco_wget %08x %08x\n"), addr, M68K_GETPC);
+
+       return 0;
+}
+
+static uae_u32 REGPARAM2 draco_bget(uaecptr addr)
+{
+       uae_u8 v = 0;
+
+       if (maxcnt >= 0) {
+               write_log(_T("draco_bget %08x %08x\n"), addr, M68K_GETPC);
+               maxcnt--;
+       }
+
+       if (addr >= 0x20000000) {
+               write_log("draco bus timeout %08x\n", addr);
+               draco_reg[3] |= DRSTAT_BUSTIMO;
+               return 0;
+       }
+
+       if ((addr & 0x07c00000) == 0x04000000) {
+
+               int reg = addr & 0xffff;
+               v = cpuboard_ncr710_io_bget(reg);
+               write_log("draco scsi read %08x\n", addr);
+
+       } else if ((addr & 0x07c00000) == 0x02400000) {
+
+               // super io
+
+               int reg = (addr & 0x7fff) >> 2;
+               switch(reg)
+               {
+                       case 0x3f0:
+                               if (draco_superio_idx >= 0) {
+                                       v = draco_superio_idx;
+                               } else {
+                                       v = x86_infloppy(reg);
+                               }
+                               break;
+                       case 0x3f1:
+                               if (draco_superio_idx >= 0 && draco_superio_idx < 16) {
+                                       v = draco_superio_cfg[draco_superio_idx];
+                               } else {
+                                       v = x86_infloppy(reg);
+                               }
+                               break;
+
+                       case 0x3f2:
+                       case 0x3f3:
+                       case 0x3f4:
+                       case 0x3f5:
+                       case 0x3f7:
+                               v = x86_infloppy(reg);
+                               break;
+
+                       case 0x3f8:
+                       case 0x3f9:
+                       case 0x3fa:
+                       case 0x3fb:
+                       case 0x3fc:
+                       case 0x3fd:
+                       case 0x3fe:
+                       case 0x3ff:
+                               v = serial_read(reg, draco_serial[0]);
+                               break;
+
+                       case 0x2f8:
+                       case 0x2f9:
+                       case 0x2fa:
+                       case 0x2fb:
+                       case 0x2fc:
+                       case 0x2fd:
+                       case 0x2fe:
+                       case 0x2ff:
+                               v = serial_read(reg, draco_serial[1]);
+                               break;
+
+                       default:
+                               write_log("draco superio read %04x = %02x\n", (addr >> 2) & 0xfff, v);
+                               break;
+               }
+
+
+       } 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);
+                       break;
+               case 9:
+                       v = 4;
+                       draco_timer_latched = true;
+                       break;
+               case 0xb:
+                       v = (draco_timer_latched ? draco_timer_latch : draco_timer) >> 8;
+                       break;
+               case 0xd:
+                       v = (draco_timer_latched ? draco_timer_latch : draco_timer) >> 0;
+                       draco_timer_latched = false;
+                       break;
+               }
+
+       } else if ((addr & 0x07c00000) == 0x02800000) {
+
+               // CIA (no CIAs if rev4+)
+
+       } else if ((addr & 0x07000000) == 0x01000000) {
+
+               // interrupt control
+               int reg = (addr & 0x0c00001);
+               switch(reg)
+               {
+                       case 0x000001:
+                               v = draco_intena;
+                               break;
+                       case 0x400001:
+                               v = draco_intpen;
+                               break;
+                       case 0x800001:
+                               v = 0;
+                               break;
+                       case 0xc0001:
+                               v = 0;
+                               break;
+               }
+       } else {
+
+               write_log("draco unknown bank read %08x\n", addr);
+       }
+
+       return v;
+}
+
+static void REGPARAM2 draco_lput(uaecptr addr, uae_u32 l)
+{
+       if ((addr & 0x07c00000) == 0x04000000) {
+
+               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 + 1, l >> 16);
+               cpuboard_ncr710_io_bput(reg + 2, l >>  8);
+               cpuboard_ncr710_io_bput(reg + 3, l >>  0);
+
+       } else {
+
+               write_log(_T("draco_lput %08x %08x %08x\n"), addr, l, M68K_GETPC);
+       }
+}
+static void REGPARAM2 draco_wput(uaecptr addr, uae_u32 w)
+{
+       write_log(_T("draco_wput %08x %04x %08x\n"), addr, w & 0xffff, M68K_GETPC);
+}
+
+static void REGPARAM2 draco_bput(uaecptr addr, uae_u32 b)
+{
+       if (maxcnt >= 0) {
+               maxcnt--;
+               write_log(_T("draco_bput %08x %02x %08x\n"), addr, b & 0xff, M68K_GETPC);
+       }
+
+       if (addr >= 0x20000000) {
+               draco_reg[3] |= DRSTAT_BUSTIMO;
+               return;
+       }
+
+       if ((addr & 0x07c00000) == 0x04000000) {
+
+               write_log("draco scsi put %08x\n", addr);
+               int reg = addr & 0xffff;
+               cpuboard_ncr710_io_bput(reg, b);
+
+       } else if ((addr & 0x07c00000) == 0x02400000) {
+
+               // super io
+               int reg = (addr & 0x7fff) >> 2;
+               switch (reg)
+               {
+                       case 0x3f0:
+                               if (b == 0x55 && draco_superio_idx < 0) {
+                                       draco_superio_idx++;
+                               } else if (b == 0xaa && draco_superio_idx >= 0) {
+                                       draco_superio_idx = -2;
+                               } else if (draco_superio_idx >= 0) {
+                                       draco_superio_idx = b;
+                               } else {
+                                       x86_outfloppy(reg, b);
+                               }
+                               break;
+                       case 0x3f1:
+                               if (draco_superio_idx >= 0 && draco_superio_idx < 16) {
+                                       draco_superio_cfg[draco_superio_idx] = b;
+                               } else {
+                                       x86_outfloppy(reg, b);
+                               }
+                               break;
+
+                       case 0x3f2:
+                       case 0x3f3:
+                       case 0x3f4:
+                       case 0x3f5:
+                       case 0x3f7:
+                               x86_outfloppy(reg, b);
+                               draco_superio_idx = -2;
+                               break;
+
+                       case 0x3f8:
+                       case 0x3f9:
+                       case 0x3fa:
+                       case 0x3fb:
+                       case 0x3fc:
+                       case 0x3fd:
+                       case 0x3fe:
+                       case 0x3ff:
+                               serial_write(reg, b, draco_serial[0]);
+                               break;
+
+                       case 0x2f8:
+                       case 0x2f9:
+                       case 0x2fa:
+                       case 0x2fb:
+                       case 0x2fc:
+                       case 0x2fd:
+                       case 0x2fe:
+                       case 0x2ff:
+                               serial_write(reg, b, draco_serial[1]);
+                               break;
+                       default:
+                               write_log("draco superio write %04x = %02x\n", (addr >> 2) & 0xfff, b);
+                               break;
+               }
+
+       } else if ((addr & 0x07c00000) == 0x02800000) {
+
+               // CIA (no CIAs if rev4+)
+
+       } else if ((addr & 0x07c00000) == 0x02000000) {
+
+               // IO
+
+               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:
+                               draco_irq();
+                               draco_keyboard_write(b);
+                               break;
+                       case 3: // RO
+                               draco_reg[reg] = oldval;
+                               break;
+                       case 7:
+                               draco_irq();
+                               break;
+                       case 9:
+                               draco_reg[7] &= ~DRSTAT2_TMRIRQPEN;
+                               break;
+                       case 0x0b:
+                               draco_timer &= 0x00ff;
+                               draco_timer |= b << 8;
+                               break;
+                       case 0x0d:
+                               draco_timer &= 0xff00;
+                               draco_timer |= b;
+                               break;
+                       case 0x11:
+                               draco_1wire_send(0);
+                               break;
+                       case 0x13:
+                               draco_1wire_send(1);
+                               break;
+                       case 0x15:
+                               draco_1wire_reset();
+                               break;
+                       case 0x17:
+                               draco_keyboard_done();
+                               break;
+                       case 0x19:
+                               draco_reg[3] &= ~DRSTAT_BUSTIMO;
+                               break;
+               }
+       } else if ((addr & 0x07000000) == 0x01000000) {
+
+               // interrupt control
+               int reg = (addr & 0x0c00001);
+               switch (reg)
+               {
+                       case 0x000001:
+                               draco_intena = b & 15;
+                               draco_irq();
+                               break;
+                       case 0x400001:
+                               draco_intpen = b & 15;
+                               if (b)
+                                       write_log("draco interrupt 0x400001 write %02x\n", b);
+                               draco_irq();
+                               break;
+                       case 0x800001:
+                               if (b)
+                                       write_log("draco interrupt 0x800001 write %02x\n", b);
+                               draco_intpen |= b & 15;
+                               draco_irq();
+                               break;
+                       case 0xc00001:
+                               if (b)
+                                       write_log("draco interrupt 0xc00001 write %02x\n", b);
+                               draco_irq();
+                               break;
+               }
+
+       } else {
+       
+               write_log("draco unknown bank write %08x\n", addr);
+
+       }
+}
+
+static addrbank draco_bank = {
+       draco_lget, draco_wget, draco_bget,
+       draco_lput, draco_wput, draco_bput,
+       default_xlate, default_check, NULL, NULL, _T("DraCo mainboard"),
+       dummy_lgeti, dummy_wgeti, ABFLAG_IO, S_READ, S_WRITE
+};
+
+
+void casablanca_map_overlay(void)
+{
+       // Casablanca has ROM at address zero, no chip ram, no overlay.
+       map_banks(&kickmem_bank, 524288 >> 16, 524288 >> 16, 0);
+       map_banks(&extendedkickmem_bank, 0 >> 16, 524288 >> 16, 0);
+       map_banks(&draco_bank, 0x02000000 >> 16, 0x01000000 >> 16, 0);
+       // KS ROM is here
+       map_banks(&kickmem_bank, 0x02c00000 >> 16, 524288 >> 16, 0);
+       map_banks(&draco_bank, 0x03000000 >> 16, 0x01000000 >> 16, 0);
+}
+
+static void draco_hsync(void)
+{
+       uae_u16 tm = 1, ot;
+       static int hcnt;
+
+       ot = draco_timer;
+       draco_timer -= tm;
+       if ((draco_timer > 0xf000 && ot < 0x1000) || (draco_timer < 0x1000 && ot > 0xf000)) {
+               draco_reg[7] |= DRSTAT2_TMRIRQPEN;
+               if (draco_reg[7] & DRSTAT2_TMRINTENA) {
+                       draco_irq();
+               }
+       }
+       x86_floppy_run();
+
+       if (draco_kbd_buffer_len > 0) {
+               draco_keyboard_send();
+       }
+       hcnt++;
+       if (hcnt >= 60) {
+               draco_1wire_rtc_count();
+               hcnt = 0;
+       }
+}
+
+void draco_set_scsi_irq(int id, int level)
+{
+       if (level) {
+               draco_intpen |= 2;
+       } else {
+               draco_intpen &= ~2;
+       }
+       draco_irq();
+}
+
+
+static void x86_irq(int irq, bool state)
+{
+       draco_fdc_intpen = state;
+       draco_irq();
+}
+
+void draco_reset(void)
+{
+       TCHAR path[MAX_DPATH];
+       cfgfile_resolve_path_out_load(currprefs.flashfile, path, MAX_DPATH, PATH_ROM);
+       struct zfile *draco_flashfile = zfile_fopen(path, _T("wb"), ZFD_NORMAL);
+       if (draco_flashfile) {
+               uae_u8 zeros[8] = { 0 };
+               zfile_fwrite(draco_1wire_rom, sizeof(draco_1wire_rom), 1, draco_flashfile);
+               zfile_fwrite(zeros, sizeof(zeros), 1, draco_flashfile);
+               zfile_fwrite(draco_1wire_sram, sizeof(draco_1wire_sram), 1, draco_flashfile);
+               zfile_fclose(draco_flashfile);
+       }
+}
+
+void draco_init(void)
+{
+       if (currprefs.cs_compatible != CP_DRACO) {
+               return;
+       }
+
+       draco_intena = 0;
+       draco_intpen = 0;
+       draco_timer = 0;
+       draco_timer_latched = 0;
+       draco_timer_latched = false;
+       draco_svga_irq_state = 0;
+       draco_fdc_intpen = false;
+       draco_superio_idx = -2;
+       draco_kbd_buffer_len = 0;
+       draco_kbd_state2 = 0;
+       memset(draco_superio_cfg, 0, sizeof(draco_superio_cfg));
+       draco_superio_cfg[0] = 0x3b;
+       draco_superio_cfg[1] = 0x9f;
+       draco_superio_cfg[2] = 0xdc;
+       draco_superio_cfg[3] = 0x78;
+       draco_superio_cfg[6] = 0xff;
+       draco_superio_cfg[13] = 0x65;
+       draco_superio_cfg[14] = 1;
+       memset(draco_reg, 0, sizeof(draco_reg));
+
+       draco_1wire_rtc_validate();
+       draco_1wire_rom[0] = 0x04;
+       draco_1wire_rom[1] = 1;
+       draco_1wire_rom[2] = 2;
+       draco_1wire_rom[3] = 3;
+       draco_1wire_rom[4] = 4;
+       draco_1wire_rom[5] = 5;
+       draco_1wire_rom[6] = 6;
+       draco_1wire_rom[7] = 0xaa;
+
+       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);
+       if (draco_flashfile) {
+               zfile_fread(draco_1wire_rom, sizeof(draco_1wire_rom), 1, draco_flashfile);
+               zfile_fseek(draco_flashfile, 8, SEEK_CUR);
+               zfile_fread(draco_1wire_sram, sizeof(draco_1wire_sram), 1, draco_flashfile);
+               zfile_fclose(draco_flashfile);
+       }
+
+       x86_initfloppy(x86_irq);
+       draco_serial_init(&draco_serial[0], &draco_serial[1]);
+
+       device_add_rethink(draco_irq);
+       device_add_hsync(draco_hsync);
+}
+
+void draco_map_overlay(void)
+{
+       // hide custom registers
+       map_banks(&dummy_bank, 0xd00000 >> 16, 0x200000 >> 16, 0);
+       // hide cias
+       map_banks(&dummy_bank, 0xa00000 >> 16, 0x200000 >> 16, 0);
+
+       map_banks(&extendedkickmem_bank, 0 >> 16, 524288 >> 16, 0);
+       map_banks(&draco_bank, 0x01000000 >> 16, 0x01c00000 >> 16, 0);
+       map_banks(&kickmem_bank, 0x02c00000 >> 16, 524288 >> 16, 0);
+       map_banks(&draco_bank, 0x04000000 >> 16, 0x01000000 >> 16, 0);
+       map_banks(&draco_bank, 0x21000000 >> 16, 0x1f000000 >> 16, 0);
+}
index b338293bfa94415d6227e0f1623cbd8dc004fad0..229de3939a8f4cc208115fb3df64333e425ae75a 100644 (file)
@@ -3614,6 +3614,17 @@ static void expansion_add_autoconfig(struct uae_prefs *p)
                cards_set[cardno++].map = NULL;
        }
 
+       for (int i = 0; i < MAX_RTG_BOARDS; i++) {
+               struct rtgboardconfig *rbc = &p->rtgboards[i];
+               int type = gfxboard_get_configtype(rbc);
+               if (rbc->rtgmem_size && rbc->rtgmem_type >= GFXBOARD_HARDWARE && type == BOARD_NONAUTOCONFIG_BEFORE) {
+                       cards_set[cardno].flags = 4 | (i << 16);
+                       cards_set[cardno].name = _T("MainBoardRTG");
+                       cards_set[cardno].zorro = BOARD_NONAUTOCONFIG_BEFORE;
+                       cards_set[cardno++].initnum = gfxboard_init_memory;
+               }
+       }
+
        // add possible non-autoconfig boards
        add_cpu_expansions(p, BOARD_NONAUTOCONFIG_BEFORE, NULL);
        add_expansions(p, BOARD_NONAUTOCONFIG_BEFORE, NULL, 0);
@@ -3677,7 +3688,8 @@ static void expansion_add_autoconfig(struct uae_prefs *p)
 #ifdef GFXBOARD
        for (int i = 0; i < MAX_RTG_BOARDS; i++) {
                struct rtgboardconfig *rbc = &p->rtgboards[i];
-               if (rbc->rtgmem_size && rbc->rtgmem_type >= GFXBOARD_HARDWARE && gfxboard_get_configtype(rbc) <= 2) {
+               int type = gfxboard_get_configtype(rbc);
+               if (rbc->rtgmem_size && rbc->rtgmem_type >= GFXBOARD_HARDWARE && type <= 2) {
                        cards_set[cardno].flags = 4 | (i << 16);
                        if (gfxboard_get_func(rbc)) {
                                cards_set[cardno].name = _T("Z2RTG");
@@ -6869,6 +6881,22 @@ static const struct cpuboardsubtype harms_sub[] = {
        }
 };
 
+static const struct cpuboardsubtype draco_sub[] = {
+       {
+               _T("DraCo"),
+               _T("draco"),
+               ROMTYPE_CB_DRACO | ROMTYPE_NONE, 0, 4,
+               draco_add_scsi_unit, EXPANSIONTYPE_SCSI,
+               BOARD_MEMORY_HIGHMEM,
+               128 * 1024 * 1024,
+               0,
+               ncr710_draco_init, NULL, BOARD_NONAUTOCONFIG_BEFORE, 1,
+       },
+       {
+               NULL
+       }
+};
+
 static const struct cpuboardsubtype dummy_sub[] = {
        { NULL }
 };
@@ -6959,6 +6987,11 @@ const struct cpuboardtype cpuboards[] = {
                _T("Harms"),
                harms_sub, 0
        },
+       {
+               BOARD_DRACO,
+               _T("Draco"),
+               draco_sub, 0
+       },
        {
                NULL
        }
index b5b63901e5073300f35b37b67d65de53562304a6..f2cd6b0e447c34ecec262561941582877ca0fafc 100644 (file)
@@ -125,7 +125,7 @@ struct gfxboard
        struct gfxboard_func *func;
        device_t *pcemdev;
        uae_u8 er_flags;
-       bool pci;
+       int bustype;
 };
 
 #define ISP4() (gb->rbc->rtgmem_type == GFXBOARD_ID_PICASSO4_Z2 || gb->rbc->rtgmem_type == GFXBOARD_ID_PICASSO4_Z3)
@@ -249,6 +249,13 @@ static const struct gfxboard boards[] =
                0x00000000, 0x00100000, 0x00400000, 0x00400000, 0, 3, 2, false, false,
                0, 0, NULL, &ncr_retina_z3_device
        },
+       {
+               GFXBOARD_ID_ALTAIS_Z3,
+               _T("Altais [DracoBus]"), _T("MacroSystem"), _T("Altais"),
+               18260, 19, 0, 0,
+               0x00000000, 0x00400000, 0x00400000, 0x00400000, 0, 4, 3, false, false,
+               0, 0, NULL, &ncr_retina_z3_device, 0, GFXBOARD_BUSTYPE_DRACO
+       },
        {
                GFXBOARD_ID_HARLEQUIN,
                _T("Harlequin [Zorro II]"), _T("ACS"), _T("Harlequin_PAL"),
@@ -270,14 +277,14 @@ static const struct gfxboard boards[] =
                0, 0, 0, 0,
                0x00000000, 0x01000000, 0x01000000, 0x01000000, 0, 0, -1, false, false,
                ROMTYPE_VOODOO3,
-               0, NULL, &voodoo_3_3000_device, 0, true
+               0, NULL, &voodoo_3_3000_device, 0, GFXBOARD_BUSTYPE_PCI
        },
        {
                GFXBOARD_ID_S3VIRGE_PCI,
                _T("Virge [PCI]"), _T("S3"), _T("S3VIRGE_PCI"),
                0, 0, 0, 0,
                0x00000000, 0x00400000, 0x00400000, 0x10000000, 0, 0, -1, false, false,
-               0, 0, NULL, &s3_virge_device, 0, true
+               0, 0, NULL, &s3_virge_device, 0, GFXBOARD_BUSTYPE_PCI
        },
        {
                GFXBOARD_ID_VGA,
@@ -784,9 +791,12 @@ static void gfxboard_rethink(void)
 {
        for (int i = 0; i < MAX_RTG_BOARDS; i++) {
                struct rtggfxboard *gb = &rtggfxboards[i];
-               if (gb->pcemdev && gb->pcemobject && gb->gfxboard_intreq && gb->gfxboard_intena) {
+               if (gb->pcemdev && gb->pcemobject) {
                        int irq = 0;
-                       if (gb->board->irq > 0) {
+                       if (gb->board->bustype == GFXBOARD_BUSTYPE_DRACO) {
+                               void draco_svga_irq(bool state);
+                               draco_svga_irq(gb->gfxboard_intreq);
+                       } else if (gb->gfxboard_intreq &&gb->gfxboard_intena) {
                                if (gb->board->irq == 2 && gb->gfxboard_intena != 6)
                                        irq = 2;
                                else
@@ -892,7 +902,7 @@ static void init_board (struct rtggfxboard *gb)
                gb->gfxmem_bank->flags |= ABFLAG_ALLOCINDIRECT | ABFLAG_PPCIOSPACE;
                gb->gfxmem_bank->label = _T("*");
                mapped_malloc(gb->gfxmem_bank);
-       } else if (gb->board->pci) {
+       } else if (gb->board->bustype == GFXBOARD_BUSTYPE_PCI) {
                // We don't know VRAM address until PCI bridge and
                // PCI display card's BARs have been initialized
                ;
@@ -915,7 +925,7 @@ static void init_board (struct rtggfxboard *gb)
        //gb->gfxmem_bank->baseaddr = gb->vram;
        // restore original value because this is checked against
        // configured size in expansion.cpp
-       if (!gb->board->pci) {
+       if (!gb->board->bustype) {
                gb->gfxmem_bank->allocated_size = rbc->rtgmem_size;
                gb->gfxmem_bank->reserved_size = rbc->rtgmem_size;
        }
@@ -3628,7 +3638,7 @@ void gfxboard_voodoo_lfb_endianswap(int m)
 {
        for (int i = 0; i < MAX_RTG_BOARDS; i++) {
                struct rtggfxboard *gb = &rtggfxboards[i];
-               if (gb->active && gb->board->pci) {
+               if (gb->active && gb->board->bustype == GFXBOARD_BUSTYPE_PCI) {
                        if (gb->lfbbyteswapmode != m) {
                                gb->lfbbyteswapmode = m;
                                if (gb->original_pci_bank) {
@@ -3943,7 +3953,7 @@ void gfxboard_s3virge_lfb_endianswap(int m)
 {
        for (int i = 0; i < MAX_RTG_BOARDS; i++) {
                struct rtggfxboard *gb = &rtggfxboards[i];
-               if (gb->active && gb->board->pci) {
+               if (gb->active && gb->board->bustype == GFXBOARD_BUSTYPE_PCI) {
                        gb->lfbbyteswapmode = m;
                }
        }
@@ -3952,7 +3962,7 @@ void gfxboard_s3virge_lfb_endianswap2(int m)
 {
        for (int i = 0; i < MAX_RTG_BOARDS; i++) {
                struct rtggfxboard *gb = &rtggfxboards[i];
-               if (gb->active && gb->board->pci) {
+               if (gb->active && gb->board->bustype == GFXBOARD_BUSTYPE_PCI) {
                        gb->mmiobyteswapmode = m;
                }
        }
@@ -4473,7 +4483,7 @@ bool gfxboard_init_memory (struct autoconfig_info *aci)
                        gb->monswitch_keep_trying = true;
                }
        }
-       if (gb->board->pci) {
+       if (gb->board->bustype > 0) {
                aci->zorro = -1;
        }
        aci->parent = aci;
@@ -4481,7 +4491,7 @@ bool gfxboard_init_memory (struct autoconfig_info *aci)
                if (gb->rbc->rtgmem_type == GFXBOARD_ID_VGA) {
                        static const int parent[] = { ROMTYPE_A1060, ROMTYPE_A2088, ROMTYPE_A2088T, ROMTYPE_A2286, ROMTYPE_A2386, 0 };
                        aci->parent_romtype = parent;
-               } else if (gb->board->pci) {
+               } else if (gb->board->bustype == GFXBOARD_BUSTYPE_PCI) {
                        static const int parent[] = { ROMTYPE_GREX, ROMTYPE_MEDIATOR, ROMTYPE_PROMETHEUS, 0 };
                        aci->parent_romtype = parent;
                } else {
@@ -4548,7 +4558,7 @@ bool gfxboard_init_memory (struct autoconfig_info *aci)
 
        gb->active = true;
 
-       if (gb->board->pci) {
+       if (gb->board->bustype == GFXBOARD_BUSTYPE_PCI) {
 
                TCHAR path[MAX_DPATH];
                fetch_rompath(path, sizeof path / sizeof(TCHAR));
@@ -4583,6 +4593,28 @@ bool gfxboard_init_memory (struct autoconfig_info *aci)
                gb->gfxboard_intena = 1;
                return true;
        }
+       if (gb->board->bustype == GFXBOARD_BUSTYPE_DRACO) {
+               gb->gfxboard_bank_memory.bget = gfxboard_bget_mem;
+               gb->gfxboard_bank_memory.bput = gfxboard_bput_mem;
+               gb->gfxboard_bank_memory.wput = gfxboard_wput_mem;
+               uaecptr start = 0x20000000;
+               gb->gfxboardmem_start = start + 0xc00000;
+               init_board(gb);
+               copyvrambank(&gb->gfxboard_bank_memory, gb->gfxmem_bank, true);
+               copyvrambank(&gb->gfxboard_bank_vram_pcem, gb->gfxmem_bank, true);
+               map_banks(&gb->gfxboard_bank_vram_pcem, gb->gfxboardmem_start >> 16, gb->gfxboard_bank_vram_pcem.allocated_size >> 16, 0);
+               map_banks(&gb->gfxboard_bank_mmio_wbs_pcem, (start + 0xb00000) >> 16, 1, 0);
+               map_banks(&gb->gfxboard_bank_special_pcem, (start + 0x000000) >> 16, 1, 0);
+               gb->pcem_vram_offset = 0x800000;
+               gb->pcem_vram_mask = 0x3fffff;
+               gb->pcem_io_mask = 0x3fff;
+               gb->pcem_mmio_offset = 0x00300000;
+               gb->pcem_mmio_mask = 0xff;
+               gb->configured_regs = gb->gfxmem_bank->start >> 16;
+               gb->gfxboard_intena = 1;
+               gb->configured_mem = 1;
+               gb->configured_regs = 1;
+       }
 
        if (gb->rbc->rtgmem_type == GFXBOARD_ID_VGA) {
                init_board(gb);
@@ -5513,7 +5545,14 @@ static void special_pcem_put(uaecptr addr, uae_u32 v, int size)
                write_log(_T("PCEM SPECIAL PUT %08x %08x %d PC=%08x\n"), addr, v, size, M68K_GETPC);
 #endif
 
-       if (boardnum == GFXBOARD_ID_RETINA_Z2) {
+       if (boardnum == GFXBOARD_ID_ALTAIS_Z3) {
+
+               addr &= 0xffff;
+               if (addr >= 0x40) {
+                       gfxboard_bput_io_swap_pcem(addr, v);
+               }
+
+       } else if (boardnum == GFXBOARD_ID_RETINA_Z2) {
        
                addr &= 0x1ffff;
                if (addr & 0x10000) {
@@ -5859,7 +5898,32 @@ static uae_u32 special_pcem_get(uaecptr addr, int size)
        write_log(_T("PCEM SPECIAL GET %08x %d PC=%08x\n"), addr, size, M68K_GETPC);
 #endif
 
-       if (boardnum == GFXBOARD_ID_RETINA_Z2) {
+       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;
+
+
+                       }
+               }
+
+       } else if (boardnum == GFXBOARD_ID_RETINA_Z2) {
 
                addr &= 0x1ffff;
                if (addr & 0x10000) {
diff --git a/include/casablanca.h b/include/casablanca.h
deleted file mode 100644 (file)
index b1b15b1..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-
-void casablanca_map_overlay(void);
index 9f26ea7e4b8ffc96d2baef766e4e366169e46323..2a95a1281aabfe4e231311e9f49dfab5b3518008 100644 (file)
@@ -116,4 +116,7 @@ void cpuboard_gvpmaprom(int);
 #define BOARD_HARMS 16
 #define BOARD_HARMS_SUB_3KPRO 0
 
+#define BOARD_DRACO 17
+#define BOARD_DRACO_SUB_DRACO 0
+
 #endif /* UAE_CPUBOARD_H */
diff --git a/include/draco.h b/include/draco.h
new file mode 100644 (file)
index 0000000..d98e7f7
--- /dev/null
@@ -0,0 +1,6 @@
+
+void casablanca_map_overlay(void);
+void draco_map_overlay(void);
+void draco_init(void);
+void draco_reset(void);
+
index 0f8c42afd67cd0da3bc694701943311134125bd2..985c77a17d18ac9c2c65027961c74d08428cbab1 100644 (file)
@@ -83,7 +83,12 @@ int pcem_getvramsize(void);
 #define GFXBOARD_ID_PIXEL64 20
 #define GFXBOARD_ID_RETINA_Z2 21
 #define GFXBOARD_ID_RETINA_Z3 22
-#define GFXBOARD_ID_VOODOO5_PCI 23
+#define GFXBOARD_ID_ALTAIS_Z3 23
+#define GFXBOARD_ID_VOODOO5_PCI 24
+
+#define GFXBOARD_BUSTYPE_Z 0
+#define GFXBOARD_BUSTYPE_PCI 1
+#define GFXBOARD_BUSTYPE_DRACO 2
 
 struct gfxboard_mode
 {
@@ -115,5 +120,4 @@ struct gfxboard_func
        GFXBOARD_CONFIGURED configured;
 };
 
-
 #endif /* UAE_GFXBOARD_H */
index 324d38de55b844299a8aba9e5155fd53c1fa2f3a..e61f147cd73457407524366d01f9805f676d98da 100644 (file)
@@ -19,6 +19,7 @@ extern bool ncr710_a4091_autoconfig_init(struct autoconfig_info *aci);
 extern bool ncr710_warpengine_autoconfig_init(struct autoconfig_info *aci);
 extern bool ncr710_zeus040_autoconfig_init(struct autoconfig_info *aci);
 extern bool ncr710_magnum40_autoconfig_init(struct autoconfig_info *aci);
+extern bool ncr710_draco_init(struct autoconfig_info *aci);
 
 void cpuboard_ncr710_io_bput(uaecptr addr, uae_u32 v);
 uae_u32 cpuboard_ncr710_io_bget(uaecptr addr);
@@ -38,5 +39,6 @@ extern void a4091_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct ro
 extern void wildfire_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
 extern void zeus040_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
 extern void magnum40_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+extern void draco_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
 
 #endif /* UAE_NCR_SCSI_H */
index 52c39857f549a1d21bed2279d63a5191810011b1..f166632b38c181983e5b209136a18aaf133af7c9 100644 (file)
@@ -54,6 +54,7 @@ extern int decode_cloanto_rom_do(uae_u8 *mem, int size, int real_size);
 #define ROMTYPE_CB_12GAUGE     0x0004001f
 #define ROMTYPE_CB_HARMS3KP    0x00040020
 #define ROMTYPE_CB_A1230S1     0x00040021
+#define ROMTYPE_CB_DRACO       0x00040022
 
 #define ROMTYPE_FREEZER                0x00080000
 #define ROMTYPE_AR                     0x00080001
@@ -207,6 +208,7 @@ extern int decode_cloanto_rom_do(uae_u8 *mem, int size, int real_size);
 #define ROMTYPE_CSMK1SCSI      0x0010008d
 #define ROMTYPE_GVPA1208       0x0010008e
 #define ROMTYPE_DSP3210                0x0010008f
+#define ROMTYPE_ALTAIS         0x00100090
 
 #define ROMTYPE_NOT                    0x00800000
 #define ROMTYPE_QUAD           0x01000000
index 208388f1d641f3c066742d74d8fe506be2205b3f..ee2ba110353f680409f55549199b52f81b0af186 100644 (file)
@@ -17,4 +17,11 @@ void x86_mouse(int port, int x, int y, int z, int b);
 
 int is_x86_cpu(struct uae_prefs*);
 
+typedef void (*X86_INTERRUPT_CALLBACK)(int,bool);
+
+uae_u8 x86_infloppy(int portnum);
+void x86_outfloppy(int portnum, uae_u8 v);
+void x86_initfloppy(X86_INTERRUPT_CALLBACK);
+void x86_floppy_run(void);
+
 #endif /* UAE_X86_H */
index 951f4ad63fc3d49b2da3c765225c86f35fdeb3ce..0416e652c011e0e0a4df350feb019910fe49f48e 100644 (file)
@@ -41,7 +41,7 @@
 #include "uae/ppc.h"
 #include "devices.h"
 #include "inputdevice.h"
-#include "casablanca.h"
+#include "draco.h"
 
 bool canbang;
 uaecptr highest_ram;
@@ -2536,7 +2536,11 @@ static void allocate_memory (void)
 
                a3000hmem_bank.reserved_size = currprefs.mbresmem_high.size;
                a3000hmem_bank.mask = a3000hmem_bank.reserved_size - 1;
-               a3000hmem_bank.start = 0x08000000;
+               if (currprefs.cs_compatible == CP_DRACO) {
+                       a3000hmem_bank.start = 0x40000000;
+               } else {
+                       a3000hmem_bank.start = 0x08000000;
+               }
                if (a3000hmem_bank.reserved_size) {
                        if (!mapped_malloc (&a3000hmem_bank)) {
                                write_log (_T("Out of memory for a3000highmem.\n"));
@@ -2688,6 +2692,10 @@ void map_overlay (int chip)
                casablanca_map_overlay();
                return;
        }
+       if (currprefs.cs_compatible == CP_DRACO) {
+               draco_map_overlay();
+               return;
+       }
 
        size = chipmem_bank.allocated_size >= 0x180000 ? (chipmem_bank.allocated_size >> 16) : 32;
        if (bogomem_aliasing)
@@ -3550,11 +3558,23 @@ void restore_banks(void)
        }
 }
 
+static void map_banks_draco(addrbank *bank, int start, int size, int realsize)
+{
+       // draco has Z2 space mapped at 0x03e80000-0x03fffff
+       if (start >= 0xe8 && start < 0xf0) {
+               map_banks(bank, 0x0300 + start, size, realsize);
+       }
+}
+
 void map_banks (addrbank *bank, int start, int size, int realsize)
 {
        if (start == 0xffffffff)
                return;
 
+       if (currprefs.cs_compatible == CP_DRACO) {
+               map_banks_draco(bank, start, size, realsize);
+       }
+
 #ifdef JIT
        if ((bank->jit_read_flag | bank->jit_write_flag) & S_N_ADDR) {
                jit_n_addr_unsafe = 1;
index d84c1ceb6b47a5ab50da0828eaa1fb97b94a52e4..f6835134f9321c72186e0ac2f1b9482c802dfda4 100644 (file)
@@ -1074,6 +1074,29 @@ bool ncr710_magnum40_autoconfig_init(struct autoconfig_info *aci)
        return true;
 }
 
+bool ncr710_draco_init(struct autoconfig_info *aci)
+{
+       device_add_reset(ncr_reset);
+       if (!aci->doinit) {
+               return true;
+       }
+
+       struct ncr_state *ncr = getscsi(aci->rc);
+       if (!ncr)
+               return false;
+
+       ncr->enabled = true;
+       ncr->io_start = 0;
+       ncr->io_end = 0xffff;
+       ncr->io_mask = 0x7f;
+
+       ncr_reset_board(ncr);
+
+       aci->addrbank = &ncr_bank_generic;
+       return true;
+}
+
+
 static void allocscsidevice(struct ncr_state *ncr, int ch, struct scsi_data *handle, int uae_unitnum)
 {
        handle->privdata = ncr;
@@ -1223,4 +1246,14 @@ void magnum40_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romcon
        ncr_magnum40->z2 = true;
 }
 
+extern void draco_set_scsi_irq(int, int);
+
+void draco_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+       ncr_add_scsi_unit(&ncr_cpuboard, ch, ci, rc, false);
+       ncr_cpuboard->irq_func = draco_set_scsi_irq;
+       ncr_cpuboard->irqlevel = true;
+       ncr_cpuboard->bank = &ncr_bank_generic;
+}
+
 #endif
index 62499a03bc907566811c9620dd6d7c7bc2fadd66..3bbf51cf4297cb51c45843620a198a9a7aaeea65 100644 (file)
 #define FLOPPYBRIDGE
 #define WITH_MIDIEMU
 #define WITH_DSP
+#define WITH_DRACO
 
 
 #else
index 4d4fcd2aa807cbe2d17d4dbb744677626ca11233..5782f1816fb51520b3ae7352e7a5ddf23905e517 100644 (file)
     <ClCompile Include="..\..\archivers\zip\zip.cpp" />
     <ClCompile Include="..\..\aros.rom.cpp" />
     <ClCompile Include="..\..\calc.cpp" />
-    <ClCompile Include="..\..\casablanca.cpp" />
+    <ClCompile Include="..\..\draco.cpp" />
     <ClCompile Include="..\..\cd32_fmv_genlock.cpp" />
     <ClCompile Include="..\..\cdtvcr.cpp" />
     <ClCompile Include="..\..\cfgfile.cpp" />
index 5e358ac85cfdd78aed063f927a298c14e30d5d30..50433bf1ff113678e67b30ab527f5924178115e6 100644 (file)
     <ClCompile Include="..\..\debugmem.cpp">
       <Filter>common</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\casablanca.cpp">
+    <ClCompile Include="..\..\draco.cpp">
       <Filter>common</Filter>
     </ClCompile>
     <ClCompile Include="..\fpp_native_msvc_80bit.cpp">
index 570da45fa0cd38a576a4a95c089a8aa75587c521..30dc5f563ccbf8c1e2b4e00862eb46564122d90b 100644 (file)
@@ -299,3 +299,13 @@ void serial2_remove()
 {
         io_removehandler(serial2.addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
 }
+
+void draco_serial_init(void **s1, void **s2)
+{
+    serial_reset();
+    serial1.has_fifo = 1;
+    serial2.has_fifo = 1;
+    *s1 = &serial1;
+    *s2 = &serial2;
+}
+
index 1045e5d3fc479653adece781167c58b06cd0feae..910356ad79992dc85ffe0a56d70e747f9410d71c 100644 (file)
@@ -97,7 +97,7 @@ struct romdata *getromdatabypath (const TCHAR *path)
        return NULL;
 }
 
-#define NEXT_ROM_ID 311
+#define NEXT_ROM_ID 312
 
 #if NEXT_ROM_ID >= MAX_ROMMGR_ROMS
 #error Increase MAX_ROMMGR_ROMS!
@@ -299,6 +299,8 @@ static struct romdata roms[] = {
        ALTROMPN(231, 1, 2, 524288, ROMTYPE_ODD , _T("74095 00 717 02 02 U5"), 0x6ccb0431, 0xa2a43444,0xbeda38be,0x1fa5cabe,0x75fc4def,0x063bcd7a)
        { _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 },
 
        { _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 6093e10730d3705fd96dc943c4ddc39ab36f7c42..074feef58d746c293bc048b5f336080dad9145e5 100644 (file)
--- a/x86.cpp
+++ b/x86.cpp
@@ -19,7 +19,7 @@
 #define X86_DEBUG_BRIDGE_IRQ 0
 #define X86_IO_PORT_DEBUG 0
 #define X86_DEBUG_SPECIAL_IO 0
-#define FLOPPY_DEBUG 0
+#define FLOPPY_DEBUG 1
 #define EMS_DEBUG 0
 
 #define DEBUG_DMA 0
@@ -199,6 +199,8 @@ struct x86_bridge
        bool vlsi_config;
        int a2386flipper;
        bool a2386_amigapcdrive;
+
+       X86_INTERRUPT_CALLBACK irq_callback;
 };
 static int x86_found;
 
@@ -528,15 +530,21 @@ void x86_ack_keyboard(void)
 void x86_clearirq(uint8_t irqnum)
 {
        struct x86_bridge *xb = bridges[0];
-
-       picintc(1 << irqnum);
+       if (xb->irq_callback) {
+               xb->irq_callback(irqnum, false);
+       } else {
+               picintc(1 << irqnum);
+       }
 }
 
 void x86_doirq(uint8_t irqnum)
 {
        struct x86_bridge *xb = bridges[0];
-
-       picint(1 << irqnum);
+       if (xb->irq_callback) {
+               xb->irq_callback(irqnum, true);
+       } else {
+               picint(1 << irqnum);
+       }
 }
 
 struct pc_floppy
@@ -1049,10 +1057,16 @@ static void floppy_do_cmd(struct x86_bridge *xb)
                }
                break;
 
+               case 16:
+               floppy_status[0] = 0x90;
+               floppy_cmd_len = 1;
+               break;
+
                default:
                floppy_status[0] = 0x80;
                floppy_cmd_len = 1;
                break;
+
        }
 
 end:
@@ -1072,6 +1086,8 @@ end:
        }
 }
 
+static int draco_force_irq;
+
 static void outfloppy(struct x86_bridge *xb, int portnum, uae_u8 v)
 {
        switch (portnum)
@@ -1096,6 +1112,9 @@ static void outfloppy(struct x86_bridge *xb, int portnum, uae_u8 v)
                }
 #endif
                floppy_dpc = v;
+               if (xb->type < 0 && 1) {
+                       floppy_dpc |= 8;
+               }
                floppy_num = v & 3;
                for (int i = 0; i < 2; i++) {
                        disk_reserved_setinfo(0, floppy_pc[i].cyl, floppy_pc[i].head, floppy_selected() == i);
@@ -1104,6 +1123,7 @@ static void outfloppy(struct x86_bridge *xb, int portnum, uae_u8 v)
                case 0x3f5: // data reg
                floppy_cmd[floppy_idx] = v;
                if (floppy_idx == 0) {
+                       floppy_cmd_len = -1;
                        switch(v & 31)
                        {
                                case 3: // specify
@@ -1127,16 +1147,31 @@ static void outfloppy(struct x86_bridge *xb, int portnum, uae_u8 v)
                                case 10: // read id
                                floppy_cmd_len = 2;
                                break;
+                               case 12: // perpendiculaor mode
+                               if (xb->type < 0) {
+                                       floppy_cmd_len = 2;
+                               }
+                               break;
                                case 13: // format track
                                floppy_cmd_len = 6;
                                break;
                                case 15: // seek
                                floppy_cmd_len = 3;
                                break;
-                               default:
+                               case 16: // get versionm
+                               if (xb->type < 0) {
+                                       floppy_cmd_len = 1;
+                               }
+                               break;
+                               case 19: // configure
+                               if (xb->type < 0) {
+                                       floppy_cmd_len = 4;
+                               }
+                               break;
+                       }
+                       if (floppy_cmd_len < 0) {
                                write_log(_T("Floppy unimplemented command %02x\n"), v);
                                floppy_cmd_len = 1;
-                               break;
                        }
                }
                floppy_idx++;
@@ -1168,6 +1203,30 @@ static uae_u8 infloppy(struct x86_bridge *xb, int portnum)
        uae_u8 v = 0;
        switch (portnum)
        {
+               case 0x3f0: // PS/2 status A (draco)
+               if (xb->type < 0) {
+                       struct floppy_reserved fr = { 0 };
+                       bool valid_floppy = disk_reserved_getinfo(floppy_num, &fr);
+                       v |= floppy_irq ? 0x80 : 0x00;
+                       v |= 0x40;
+                       v |= fr.wrprot ? 0 : 2;
+                       v |= fr.cyl == 0 ? 0 : 16;
+               }
+               break;
+               case 0x3f1: // PS/2 status B (draco)
+               if (xb->type < 0) {
+                       v |= 0x80 | 0x40;
+                       if (floppy_dpc & 1)
+                               v |= 0x20;
+                       if ((floppy_dpc >> 4) & 1)
+                               v |= 0x01;
+                       if ((floppy_dpc >> 4) & 2)
+                               v |= 0x02;
+               }
+               break;
+               case 0x3f2:
+                       v = floppy_dpc;
+                       break;
                case 0x3f4: // main status
                v = 0;
                if (!floppy_delay_hsync && (floppy_dpc & 4))
@@ -4037,3 +4096,29 @@ bool isa_expansion_init(struct autoconfig_info *aci)
        aci->zorro = 0;
        return true;
 }
+
+void x86_outfloppy(int portnum, uae_u8 v)
+{
+       struct x86_bridge *b = bridges[0];
+       outfloppy(b, portnum, v);
+}
+uae_u8 x86_infloppy(int portnum)
+{
+       struct x86_bridge *b = bridges[0];
+       return infloppy(b, portnum);
+}
+void x86_floppy_run(void)
+{
+       check_floppy_delay();
+}
+void x86_initfloppy(X86_INTERRUPT_CALLBACK irq_callback)
+{
+       struct x86_bridge *xb = bridges[0];
+       if (!xb) {
+               xb = x86_bridge_alloc();
+               bridges[0] = xb;
+       }
+       xb->type = -1;
+       xb->irq_callback = irq_callback;
+       floppy_hardreset();
+}