From: Toni Wilen Date: Mon, 1 Jan 2024 16:45:49 +0000 (+0200) Subject: Partial MacroSystem DraCo emulation X-Git-Tag: 5200~106 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=5f51bec6637f191cfe79167c1b799881b8ca2a83;p=francis%2Fwinuae.git Partial MacroSystem DraCo emulation --- diff --git a/casablanca.cpp b/casablanca.cpp deleted file mode 100644 index f73cb9ce..00000000 --- a/casablanca.cpp +++ /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); -} diff --git a/cfgfile.cpp b/cfgfile.cpp index 40df0b42..537220dc 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -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; diff --git a/custom.cpp b/custom.cpp index 04d03855..cd1b401a 100644 --- a/custom.cpp +++ b/custom.cpp @@ -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(); diff --git a/devices.cpp b/devices.cpp index 5c111794..aaf8444d 100644 --- a/devices.cpp +++ b/devices.cpp @@ -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 index 00000000..395f3760 --- /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); +} diff --git a/expansion.cpp b/expansion.cpp index b338293b..229de393 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -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 } diff --git a/gfxboard.cpp b/gfxboard.cpp index b5b63901..f2cd6b0e 100644 --- a/gfxboard.cpp +++ b/gfxboard.cpp @@ -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 index b1b15b17..00000000 --- a/include/casablanca.h +++ /dev/null @@ -1,2 +0,0 @@ - -void casablanca_map_overlay(void); diff --git a/include/cpuboard.h b/include/cpuboard.h index 9f26ea7e..2a95a128 100644 --- a/include/cpuboard.h +++ b/include/cpuboard.h @@ -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 index 00000000..d98e7f77 --- /dev/null +++ b/include/draco.h @@ -0,0 +1,6 @@ + +void casablanca_map_overlay(void); +void draco_map_overlay(void); +void draco_init(void); +void draco_reset(void); + diff --git a/include/gfxboard.h b/include/gfxboard.h index 0f8c42af..985c77a1 100644 --- a/include/gfxboard.h +++ b/include/gfxboard.h @@ -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 */ diff --git a/include/ncr_scsi.h b/include/ncr_scsi.h index 324d38de..e61f147c 100644 --- a/include/ncr_scsi.h +++ b/include/ncr_scsi.h @@ -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 */ diff --git a/include/rommgr.h b/include/rommgr.h index 52c39857..f166632b 100644 --- a/include/rommgr.h +++ b/include/rommgr.h @@ -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 diff --git a/include/x86.h b/include/x86.h index 208388f1..ee2ba110 100644 --- a/include/x86.h +++ b/include/x86.h @@ -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 */ diff --git a/memory.cpp b/memory.cpp index 951f4ad6..0416e652 100644 --- a/memory.cpp +++ b/memory.cpp @@ -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; diff --git a/ncr_scsi.cpp b/ncr_scsi.cpp index d84c1ceb..f6835134 100644 --- a/ncr_scsi.cpp +++ b/ncr_scsi.cpp @@ -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 diff --git a/od-win32/sysconfig.h b/od-win32/sysconfig.h index 62499a03..3bbf51cf 100644 --- a/od-win32/sysconfig.h +++ b/od-win32/sysconfig.h @@ -118,6 +118,7 @@ #define FLOPPYBRIDGE #define WITH_MIDIEMU #define WITH_DSP +#define WITH_DRACO #else diff --git a/od-win32/winuae_msvc15/winuae_msvc.vcxproj b/od-win32/winuae_msvc15/winuae_msvc.vcxproj index 4d4fcd2a..5782f181 100644 --- a/od-win32/winuae_msvc15/winuae_msvc.vcxproj +++ b/od-win32/winuae_msvc15/winuae_msvc.vcxproj @@ -1305,7 +1305,7 @@ - + diff --git a/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters b/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters index 5e358ac8..50433bf1 100644 --- a/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters +++ b/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters @@ -820,7 +820,7 @@ common - + common diff --git a/pcem/serial.cpp b/pcem/serial.cpp index 570da45f..30dc5f56 100644 --- a/pcem/serial.cpp +++ b/pcem/serial.cpp @@ -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; +} + diff --git a/rommgr.cpp b/rommgr.cpp index 1045e5d3..910356ad 100644 --- a/rommgr.cpp +++ b/rommgr.cpp @@ -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 6093e107..074feef5 100644 --- 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(); +}