diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index def3f0f2b..d834a6f42 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -41,6 +41,8 @@ typedef union { typedef struct ibm8514_t { rom_t bios_rom; + rom_t bios_rom2; + rom_t bios_rom3; hwcursor8514_t hwcursor; hwcursor8514_t hwcursor_latch; uint8_t pos_regs[8]; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index fef9b2122..18b7b672a 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -171,9 +171,11 @@ typedef struct svga_t { pc_timer_t timer; pc_timer_t timer8514; + pc_timer_t timer_xga; double clock; double clock8514; + double clock_xga; double multiplier; @@ -319,9 +321,13 @@ extern void ati8514_pos_write(uint16_t port, uint8_t val, void *priv); extern void ati8514_init(svga_t *svga, void *ext8514, void *dev8514); #endif -extern void xga_poll(void *priv, svga_t *svga); +extern void xga_write_test(uint32_t addr, uint8_t val, void *priv); +extern uint8_t xga_read_test(uint32_t addr, void *priv); +extern void xga_poll(void *priv); extern void xga_recalctimings(svga_t *svga); +extern uint32_t svga_decode_addr(svga_t *svga, uint32_t addr, int write); + extern int svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, void (*recalctimings_ex)(struct svga_t *svga), uint8_t (*video_in)(uint16_t addr, void *priv), diff --git a/src/include/86box/vid_vga.h b/src/include/86box/vid_vga.h index bc552b285..0ffbeb4cd 100644 --- a/src/include/86box/vid_vga.h +++ b/src/include/86box/vid_vga.h @@ -28,9 +28,7 @@ typedef struct vga_t { rom_t bios_rom; } vga_t; -static video_timings_t timing_vga = { VIDEO_ISA, 8, 16, 32, 8, 16, 32 }; - -void vga_out(uint16_t addr, uint8_t val, void *priv); -uint8_t vga_in(uint16_t addr, void *priv); +extern void vga_out(uint16_t addr, uint8_t val, void *priv); +extern uint8_t vga_in(uint16_t addr, void *priv); #endif /*VIDEO_VGA_H*/ diff --git a/src/include/86box/vid_xga.h b/src/include/86box/vid_xga.h index 0686972ca..90a3c69aa 100644 --- a/src/include/86box/vid_xga.h +++ b/src/include/86box/vid_xga.h @@ -31,10 +31,12 @@ typedef struct xga_hwcursor_t { } xga_hwcursor_t; typedef struct xga_t { + mem_mapping_t membios_mapping; mem_mapping_t memio_mapping; mem_mapping_t linear_mapping; mem_mapping_t video_mapping; rom_t bios_rom; + rom_t membios_rom; rom_t vga_bios_rom; xga_hwcursor_t hwcursor; xga_hwcursor_t hwcursor_latch; @@ -47,8 +49,8 @@ typedef struct xga_t { uint8_t pos_regs[8]; uint8_t disp_addr; - uint8_t dac_mask; - uint8_t dac_status; + uint8_t dac_mask; + uint8_t dac_status; uint8_t cfg_reg; uint8_t instance; uint8_t op_mode; @@ -87,6 +89,8 @@ typedef struct xga_t { uint8_t instance_isa; uint8_t instance_num; uint8_t ext_mem_addr; + uint8_t vga_post; + uint8_t addr_test; uint8_t *vram; uint8_t *changedvram; @@ -167,6 +171,9 @@ typedef struct xga_t { uint32_t write_bank; uint32_t px_map_base; uint32_t pallook[512]; + uint32_t bios_diag; + + PALETTE xgapal; uint64_t dispontime; uint64_t dispofftime; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index e8ae527b5..944a14a88 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -44,8 +44,6 @@ #ifdef ATI_8514_ULTRA #define BIOS_MACH8_ROM_PATH "roms/video/mach8/11301113140.BIN" - -static video_timings_t timing_8514ultra_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; #endif static void ibm8514_accel_outb(uint16_t port, uint8_t val, void *priv); @@ -2407,9 +2405,9 @@ rect_fill_pix: dev->accel.sx += (dev->accel.cur_x & 3); } - if (dev->accel.cmd & 0x20) { + if (dev->accel.cmd & 0x20) dev->accel.cx -= (dev->accel.sx) + 1; - } else + else dev->accel.cx += (dev->accel.sx) + 1; if (dev->accel.cmd & 2) { @@ -3006,9 +3004,7 @@ rect_fill: else dev->accel.oldcy = dev->accel.cy - 1; - dev->accel.oldcx = 0; - - ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cur_x_nolimit, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, dev->accel.clip_left, clip_r, dev->accel.clip_top, clip_b, compare_mode, dev->accel.multifunc[0x0a]); + ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cx, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, dev->accel.multifunc[2], dev->accel.multifunc[4], dev->accel.clip_top, clip_b, dev->accel.multifunc[0x0a]); if (ibm8514_cpu_src(svga)) { dev->data_available = 0; @@ -3122,10 +3118,8 @@ rect_fill: } } else { while (count-- && (dev->accel.sy >= 0)) { - if (dev->accel.cx < 0) - dev->accel.cx = 0; - if (dev->accel.cy < 0) - dev->accel.cy = 0; + if (dev->accel.cx < dev->accel.clip_left) + dev->accel.cx = dev->accel.clip_left; if (dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { @@ -3155,12 +3149,8 @@ rect_fill: if ((dev->accel.cmd & 0x14) == 0x14) { if (dev->accel.sy) { - if (dev->accel.cmd & 0x40) { + if (dev->accel.oldcy != dev->accel.cy) { WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - } else { - if (dev->accel.oldcy != dev->accel.cy) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - } } } } @@ -3178,6 +3168,7 @@ rect_fill: break; if (dev->accel.cmd & 0x40) { + dev->accel.oldcy = dev->accel.cy; if (dev->accel.cmd & 0x80) dev->accel.cy++; else @@ -4159,12 +4150,12 @@ ibm8514_poll(void *priv) if (dev->on[0] || dev->on[1]) { ibm8514_log("ON!\n"); if (!dev->linepos) { - if ((dev->displine == dev->hwcursor_latch.y) && dev->hwcursor_latch.ena) { + if ((dev->displine == ((dev->hwcursor_latch.y < 0) ? 0 : dev->hwcursor_latch.y)) && dev->hwcursor_latch.ena) { dev->hwcursor_on = dev->hwcursor_latch.cur_ysize - dev->hwcursor_latch.yoff; dev->hwcursor_oddeven = 0; } - if ((dev->displine == (dev->hwcursor_latch.y + 1)) && dev->hwcursor_latch.ena && dev->interlace) { + if ((dev->displine == (((dev->hwcursor_latch.y < 0) ? 0 : dev->hwcursor_latch.y) + 1)) && dev->hwcursor_latch.ena && dev->interlace) { dev->hwcursor_on = dev->hwcursor_latch.cur_ysize - (dev->hwcursor_latch.yoff + 1); dev->hwcursor_oddeven = 1; } @@ -4195,7 +4186,7 @@ ibm8514_poll(void *priv) if (dev->hwcursor_on) { if (svga->hwcursor_draw) - svga->hwcursor_draw(svga, dev->displine + svga->y_add); + svga->hwcursor_draw(svga, (dev->displine + svga->y_add + ((dev->hwcursor_latch.y >= 0) ? 0 : dev->hwcursor_latch.y)) & 2047); dev->hwcursor_on--; if (dev->hwcursor_on && dev->interlace) dev->hwcursor_on--; @@ -4333,15 +4324,15 @@ ibm8514_recalctimings(svga_t *svga) else svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - if (dev->interlace) - dev->dispend >>= 1; - if (dev->dispend == 766) dev->dispend += 2; if (dev->dispend == 478) dev->dispend += 2; + if (dev->interlace) + dev->dispend >>= 1; + dev->pitch = 1024; dev->rowoffset = 0x80; svga->map8 = dev->pallook; @@ -4405,6 +4396,10 @@ ibm8514_mca_reset(void *priv) static void * ibm8514_init(const device_t *info) { +#ifdef ATI_8514_ULTRA + uint32_t bios_addr = 0; +#endif + if (svga_get_pri() == NULL) return NULL; @@ -4426,6 +4421,7 @@ ibm8514_init(const device_t *info) #ifdef ATI_8514_ULTRA dev->extensions = device_get_config_int("extensions"); + bios_addr = device_get_config_hex20("bios_addr"); switch (dev->extensions) { case 1: @@ -4446,10 +4442,14 @@ ibm8514_init(const device_t *info) } else { rom_init(&dev->bios_rom, BIOS_MACH8_ROM_PATH, - 0xd0000, 0x2000, 0x1fff, + bios_addr, 0x1000, 0xfff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&dev->bios_rom2, + BIOS_MACH8_ROM_PATH, + bios_addr + 0x1000, 0x800, 0x7ff, + 0x1000, MEM_MAPPING_EXTERNAL); ati_eeprom_load(&mach->eeprom, "ati8514.nvr", 0); - dev->bios_addr = dev->bios_rom.mapping.base; + mach->accel.scratch0 = (((bios_addr >> 7) - 0x1000) >> 4); } ati8514_init(svga, svga->ext8514, svga->dev8514); break; @@ -4538,6 +4538,30 @@ static const device_config_t ext8514_config[] = { } } }, + { + .name = "bios_addr", + .description = "BIOS address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xc8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "C800h", .value = 0xc8000 }, + { .description = "CA00h", .value = 0xca000 }, + { .description = "CC00h", .value = 0xcc000 }, + { .description = "CE00h", .value = 0xce000 }, + { .description = "D000h", .value = 0xd0000 }, + { .description = "D200h", .value = 0xd2000 }, + { .description = "D400h", .value = 0xd4000 }, + { .description = "D600h", .value = 0xd6000 }, + { .description = "D800h", .value = 0xd8000 }, + { .description = "DA00h", .value = 0xda000 }, + { .description = "DC00h", .value = 0xdc000 }, + { .description = "DE00h", .value = 0xde000 }, + { .description = "" } + }, + }, { .type = CONFIG_END } diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 46d884adf..d41f65ed9 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -37,6 +37,7 @@ #include <86box/i2c.h> #include <86box/vid_ddc.h> #include <86box/vid_8514a.h> +#include <86box/vid_xga.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> #include <86box/vid_ati_eeprom.h> @@ -2478,11 +2479,13 @@ ati8514_recalctimings(svga_t *svga) dev->dispend = dev->vdisp; } - if (dev->accel.advfunc_cntl & 0x04) { + if (dev->accel.advfunc_cntl & 0x04) svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; - } else { + else svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - } + + if (dev->interlace) + dev->dispend >>= 1; if (dev->dispend == 766) dev->dispend += 2; @@ -3456,7 +3459,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u static void mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8514_t *dev) { - if (port != 0x7aee && port != 0x7aef && port != 0x42e8 && port != 0x42e9 && port != 0x46e8 && port != 0x46e9) + if (port != 0x7aee && port != 0x7aef && port != 0x42e8 && port != 0x42e9) mach_log("[%04X:%08X]: Port CALL OUT=%04x, val=%02x.\n", CS, cpu_state.pc, port, val); switch (port) { @@ -4290,26 +4293,6 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 0x52ee: case 0x52ef: READ8(port, mach->accel.scratch0); -#ifdef ATI_8514_ULTRA - if (mach->mca_bus) { - if (!(port & 1)) { - if (svga->ext8514 != NULL) - temp = dev->pos_regs[4]; - } else { - if (svga->ext8514 != NULL) - temp = dev->pos_regs[5]; - } - } else { - if (svga->ext8514 != NULL) { - temp = ((dev->bios_addr >> 7) - 0x1000) >> 4; - if (port & 1) { - temp &= ~0x80; - temp |= 0x01; - } - } else - temp = 0x00; - } -#endif break; case 0x56ee: @@ -4368,7 +4351,7 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) default: break; } - if (port != 0x62ee && port != 0x62ef && port != 0x42e8 && port != 0x42e9) + if (port != 0x62ee && port != 0x62ef && port != 0x42e8 && port != 0x42e9 && port != 0x02e8 && port != 0x02e9) mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); return temp; @@ -4641,6 +4624,7 @@ mach32_write_common(uint32_t addr, uint8_t val, int linear, mach_t *mach, svga_t dev->vram[addr] = val; return; } else { + xga_write_test(addr, val, svga); addr = mach32_decode_addr(svga, addr, 1); if (addr == 0xffffffff) return; @@ -4858,6 +4842,7 @@ mach32_read_common(uint32_t addr, int linear, mach_t *mach, svga_t *svga) if (linear) { return dev->vram[addr & dev->vram_mask]; } else { + (void) xga_read_test(addr, svga); addr = mach32_decode_addr(svga, addr, 0); if (addr == 0xffffffff) return 0xff; diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index bf27a700a..01210a9d9 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -37,6 +37,7 @@ #include <86box/video.h> #include <86box/i2c.h> #include <86box/vid_ddc.h> +#include <86box/vid_xga.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> #include <86box/plat_fallthrough.h> @@ -2195,6 +2196,8 @@ gd54xx_write(uint32_t addr, uint8_t val, void *priv) return; } + xga_write_test(addr, val, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; svga_write_linear(addr, val, svga); @@ -2212,6 +2215,9 @@ gd54xx_writew(uint32_t addr, uint16_t val, void *priv) return; } + xga_write_test(addr, val, svga); + xga_write_test(addr + 1, val >> 8, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; @@ -2237,6 +2243,11 @@ gd54xx_writel(uint32_t addr, uint32_t val, void *priv) return; } + xga_write_test(addr, val, svga); + xga_write_test(addr + 1, val >> 8, svga); + xga_write_test(addr + 2, val >> 16, svga); + xga_write_test(addr + 3, val >> 24, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; @@ -2762,6 +2773,8 @@ gd54xx_read(uint32_t addr, void *priv) if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) return gd54xx_mem_sys_dest_read(gd54xx, 0); + (void) xga_read_test(addr, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_read_linear(addr, svga); @@ -2780,6 +2793,9 @@ gd54xx_readw(uint32_t addr, void *priv) return ret; } + (void) xga_read_test(addr, svga); + (void) xga_read_test(addr + 1, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_readw_linear(addr, svga); @@ -2800,6 +2816,11 @@ gd54xx_readl(uint32_t addr, void *priv) return ret; } + (void) xga_read_test(addr, svga); + (void) xga_read_test(addr + 1, svga); + (void) xga_read_test(addr + 2, svga); + (void) xga_read_test(addr + 3, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_readl_linear(addr, svga); @@ -3826,6 +3847,16 @@ cl_pci_read(UNUSED(int func), int addr, void *priv) ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? ((gd54xx->vgablt_base >> 24) & 0xff) : 0x00; break; + case 0x2c: + ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? gd54xx->bios_rom.rom[0x7ffc] : 0x00; + break; + case 0x2d: + ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? gd54xx->bios_rom.rom[0x7ffd] : 0x00; + break; + case 0x2e: + ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? gd54xx->bios_rom.rom[0x7ffe] : 0x00; + break; + case 0x30: ret = (gd54xx->pci_regs[0x30] & 0x01); /*BIOS ROM address*/ break; diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index c223d37ba..0ac7050f4 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -125,15 +125,6 @@ et4000_in(uint16_t addr, void *priv) addr ^= 0x60; switch (addr) { - case 0x3c2: - if (dev->type == ET4000_TYPE_MCA) { - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) - return 0; - else - return 0x10; - } - break; - case 0x3c5: if ((svga->seqaddr & 0xf) == 7) return svga->seqregs[svga->seqaddr & 0xf] | 4; @@ -770,12 +761,16 @@ et4000_mca_write(int port, uint8_t val, void *priv) /* Save the MCA register value. */ et4000->pos_regs[port & 7] = val; + mem_mapping_disable(&et4000->bios_rom.mapping); + if (et4000->pos_regs[2] & 1) + mem_mapping_enable(&et4000->bios_rom.mapping); } static uint8_t et4000_mca_feedb(UNUSED(void *priv)) { - return 1; + et4000_t *et4000 = (et4000_t *) priv; + return et4000->pos_regs[2] & 1; } static void * @@ -889,7 +884,10 @@ et4000_init(const device_t *info) dev->vram_mask = dev->vram_size - 1; rom_init(&dev->bios_rom, fn, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + if (dev->type == ET4000_TYPE_MCA) + mem_mapping_disable(&dev->bios_rom.mapping); dev->svga.translate_address = get_et4000_addr; diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index 213cf9ed4..7d868a63b 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -33,6 +33,7 @@ #include <86box/rom.h> #include <86box/device.h> #include <86box/video.h> +#include <86box/vid_xga.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> #include <86box/plat_fallthrough.h> @@ -1217,6 +1218,8 @@ ht216_write(uint32_t addr, uint8_t val, void *priv) svga_t *svga = &ht216->svga; uint32_t prev_addr = addr; + xga_write_test(addr, val, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; @@ -1238,6 +1241,9 @@ ht216_writew(uint32_t addr, uint16_t val, void *priv) svga_t *svga = &ht216->svga; uint32_t prev_addr = addr; + xga_write_test(addr, val, svga); + xga_write_test(addr + 1, val >> 8, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; @@ -1261,6 +1267,11 @@ ht216_writel(uint32_t addr, uint32_t val, void *priv) svga_t *svga = &ht216->svga; uint32_t prev_addr = addr; + xga_write_test(addr, val, svga); + xga_write_test(addr + 1, val >> 8, svga); + xga_write_test(addr + 2, val >> 16, svga); + xga_write_test(addr + 3, val >> 24, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; @@ -1422,9 +1433,11 @@ static uint8_t ht216_read(uint32_t addr, void *priv) { ht216_t *ht216 = (ht216_t *) priv; - const svga_t *svga = &ht216->svga; + svga_t *svga = &ht216->svga; uint32_t prev_addr = addr; + (void) xga_read_test(addr, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->read_banks[(addr >> 15) & 1]; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index bd31abd23..cecdcf840 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -559,11 +559,12 @@ svga_set_ramdac_type(svga_t *svga, int type) } if (xga_active && xga) { if (svga->ramdac_type == RAMDAC_8BIT) - xga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); - else - xga->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, - (svga->vgapal[c].g & 0x3f) * 4, - (svga->vgapal[c].b & 0x3f) * 4); + xga->pallook[c] = makecol32(xga->xgapal[c].r, xga->xgapal[c].g, xga->xgapal[c].b); + else { + xga->pallook[c] = makecol32((xga->xgapal[c].r & 0x3f) * 4, + (xga->xgapal[c].g & 0x3f) * 4, + (xga->xgapal[c].b & 0x3f) * 4); + } } if (svga->ramdac_type == RAMDAC_8BIT) svga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); @@ -669,11 +670,11 @@ svga_recalctimings(svga_t *svga) } if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) { /*40 column*/ + if (svga->seqregs[1] & 8) { /*40 column*/ svga->render = svga_render_text_40; - } else { + } else svga->render = svga_render_text_80; - } + svga->hdisp_old = svga->hdisp; } else { svga->hdisp_old = svga->hdisp; @@ -1036,7 +1037,7 @@ svga_poll(void *priv) if (!svga->override) { if (xga_active && xga && xga->on) { if ((xga->disp_cntl_2 & 7) >= 2) { - xga_poll(xga, svga); + xga_poll(svga); return; } } @@ -1407,7 +1408,7 @@ svga_close(svga_t *svga) svga_pri = NULL; } -static uint32_t +uint32_t svga_decode_addr(svga_t *svga, uint32_t addr, int write) { int memory_map_mode = (svga->gdcreg[6] >> 2) & 3; @@ -1448,7 +1449,6 @@ static __inline void svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; int writemask2 = svga->writemask; int reset_wm = 0; latch_t vall; @@ -1462,40 +1462,7 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *priv) cycles -= svga->monitor->mon_video_timing_write_b; if (!linear) { - if (xga_active && xga) { - if (((xga->op_mode & 7) >= 4) && (xga->aperture_cntl >= 1)) { - if (val == 0xa5) { /*Memory size test of XGA*/ - xga->test = val; - if (addr == 0xa0001) - xga->a5_test = 1; - else if (addr == 0xafffe) - xga->a5_test = 2; - - xga->on = 0; - vga_on = 1; - xga->disp_cntl_2 = 0; - svga_log("XGA test1 addr = %05x.\n", addr); - return; - } else if (val == 0x5a) { - xga->test = val; - xga->on = 0; - vga_on = 1; - xga->disp_cntl_2 = 0; - svga_log("XGA test2 addr = %05x.\n", addr); - return; - } else if ((addr == 0xa0000) || (addr == 0xa0010)) { - addr += xga->write_bank; - xga->vram[addr & xga->vram_mask] = val; - svga_log("XGA Linear endian reverse write, val = %02x, addr = %05x, banked mask = %04x.\n", val, addr, svga->banked_mask); - if (!xga->a5_test) - xga->linear_endian_reverse = 1; - return; - } - } else { - xga->on = 0; - vga_on = 1; - } - } + xga_write_test(addr, val, svga); addr = svga_decode_addr(svga, addr, 1); if (addr == 0xffffffff) @@ -1670,12 +1637,11 @@ static __inline uint8_t svga_read_common(uint32_t addr, uint8_t linear, void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; uint32_t latch_addr = 0; int readplane = svga->readplane; uint8_t count; uint8_t temp; - uint8_t ret; + uint8_t ret = 0x00; if (svga->adv_flags & FLAG_ADDR_BY8) readplane = svga->gdcreg[4] & 7; @@ -1683,39 +1649,7 @@ svga_read_common(uint32_t addr, uint8_t linear, void *priv) cycles -= svga->monitor->mon_video_timing_read_b; if (!linear) { - if (xga_active && xga) { - if (((xga->op_mode & 7) >= 4) && (xga->aperture_cntl >= 1)) { - if (xga->test == 0xa5) { /*Memory size test of XGA*/ - if (addr == 0xa0001) { - ret = xga->test; - xga->on = 1; - vga_on = 0; - } else if ((addr == 0xa0000) && (xga->a5_test == 1)) { /*This is required by XGAKIT to pass the memory test*/ - svga_log("A5 test bank = %x.\n", addr); - addr += xga->read_bank; - ret = xga->vram[addr & xga->vram_mask]; - } else { - ret = xga->test; - xga->on = 1; - vga_on = 0; - } - svga_log("A5 read: XGA ON = %d, addr = %05x, ret = %02x, test1 = %x.\n", xga->on, addr, ret, xga->a5_test); - return ret; - } else if (xga->test == 0x5a) { - ret = xga->test; - xga->on = 1; - vga_on = 0; - svga_log("5A read: XGA ON = %d.\n", xga->on); - return ret; - } else if ((addr == 0xa0000) || (addr == 0xa0010)) { - addr += xga->read_bank; - return xga->vram[addr & xga->vram_mask]; - } - } else { - xga->on = 0; - vga_on = 1; - } - } + (void) xga_read_test(addr, svga); addr = svga_decode_addr(svga, addr, 0); if (addr == 0xffffffff) diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 8b2e761a3..881a3c6fd 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -31,6 +31,7 @@ #include <86box/vid_svga.h> #include <86box/vid_vga.h> +static video_timings_t timing_vga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; static video_timings_t timing_ps1_svga_isa = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; static video_timings_t timing_ps1_svga_mca = { .type = VIDEO_MCA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; @@ -207,7 +208,7 @@ const device_t ps1vga_device = { .init = ps1vga_init, .close = vga_close, .reset = NULL, - { .available = vga_available }, + { .available = NULL }, .speed_changed = vga_speed_changed, .force_redraw = vga_force_redraw, .config = NULL @@ -221,7 +222,7 @@ const device_t ps1vga_mca_device = { .init = ps1vga_init, .close = vga_close, .reset = NULL, - { .available = vga_available }, + { .available = NULL }, .speed_changed = vga_speed_changed, .force_redraw = vga_force_redraw, .config = NULL diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 8946d7122..ff82a834a 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -157,6 +157,14 @@ xga_updatemapping(svga_t *svga) break; case 1: xga_log("XGA: VGA mode address decode enabled.\n"); + if (xga->base_addr_1mb) { + mem_mapping_set_addr(&xga->linear_mapping, xga->base_addr_1mb, 0x100000); + mem_mapping_enable(&xga->linear_mapping); + } else if (xga->linear_base) { + mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000); + mem_mapping_enable(&xga->linear_mapping); + } else + mem_mapping_disable(&xga->linear_mapping); break; case 2: xga_log("XGA: 132-Column mode address decode disabled.\n"); @@ -203,8 +211,8 @@ void xga_recalctimings(svga_t *svga) { xga_t *xga = (xga_t *) svga->xga; - if (xga->on) { + xga->h_total = xga->htotal + 1; xga->v_total = xga->vtotal + 1; xga->dispend = xga->vdispend + 1; xga->v_syncstart = xga->vsyncstart + 1; @@ -213,7 +221,7 @@ xga_recalctimings(svga_t *svga) xga->h_disp = (xga->hdisp + 1) << 3; - xga->rowoffset = xga->hdisp + 1; + xga->rowoffset = xga->pix_map_width; xga->interlace = !!(xga->disp_cntl_1 & 0x08); xga->rowcount = (xga->disp_cntl_2 & 0xc0) >> 6; @@ -228,11 +236,6 @@ xga_recalctimings(svga_t *svga) xga->ma_latch = xga->disp_start_addr; - if ((xga->disp_cntl_2 & 7) == 2) - xga->rowoffset >>= 1; - else if ((xga->disp_cntl_2 & 7) == 4) - xga->rowoffset <<= 1; - xga_log("XGA ClkSel1 = %d, ClkSel2 = %02x.\n", (xga->clk_sel_1 >> 2) & 3, xga->clk_sel_2 & 0x80); switch ((xga->clk_sel_1 >> 2) & 3) { case 0: @@ -373,12 +376,15 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) case 0x40: xga->disp_start_addr = (xga->disp_start_addr & 0x7ff00) | val; + xga_log("DISPSTARTADDR0=%x.\n", xga->disp_start_addr); break; case 0x41: xga->disp_start_addr = (xga->disp_start_addr & 0x700ff) | (val << 8); + xga_log("DISPSTARTADDR8=%x.\n", xga->disp_start_addr); break; case 0x42: xga->disp_start_addr = (xga->disp_start_addr & 0x0ffff) | ((val & 0x07) << 16); + xga_log("DISPSTARTADDR16=%x.\n", xga->disp_start_addr); svga_recalctimings(svga); break; @@ -387,10 +393,11 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) break; case 0x44: xga->pix_map_width = (xga->pix_map_width & 0xff) | ((val & 0x07) << 8); + svga_recalctimings(svga); break; case 0x50: - xga_log("Reg50 write = %02x.\n", val); + xga_log("Reg50 write=%02x.\n", val); xga->disp_cntl_1 = val; svga_recalctimings(svga); break; @@ -430,18 +437,9 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) xga->cursor_data_on, xga->sprite_pal_addr_idx, xga->aperture_cntl); break; - case 0x62: - xga->sprite_pal_addr_idx_prefetch = (xga->sprite_pal_addr_idx_prefetch & 0x3f00) | val; - xga->dac_pos = 0; - xga->dac_addr = val & 0xff; - break; - case 0x63: - xga->sprite_pal_addr_idx_prefetch = (xga->sprite_pal_addr_idx_prefetch & 0xff) | ((val & 0x3f) << 8); - xga->sprite_pos_prefetch = xga->sprite_pal_addr_idx_prefetch & 0x1ff; - break; - case 0x64: xga->dac_mask = val; + xga_log("DAC mask=%02x.\n", val); break; case 0x65: @@ -458,10 +456,11 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) case 2: xga->pal_b = val; index = xga->dac_addr & 0xff; - svga->vgapal[index].r = xga->dac_r; - svga->vgapal[index].g = xga->dac_g; - svga->vgapal[index].b = xga->pal_b; - xga->pallook[index] = makecol32(svga->vgapal[index].r, svga->vgapal[index].g, svga->vgapal[index].b); + xga->xgapal[index].r = xga->dac_r; + xga->xgapal[index].g = xga->dac_g; + xga->xgapal[index].b = xga->pal_b; + xga->pallook[index] = makecol32(xga->xgapal[index].r, xga->xgapal[index].g, xga->xgapal[index].b); + xga_log("XGA Pallook=%06x, idx=%d.\n", xga->pallook[index], index); xga->dac_pos = 0; xga->dac_addr = (xga->dac_addr + 1) & 0xff; break; @@ -472,19 +471,10 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) break; case 0x66: + xga_log("Palette Sequence=%02x.\n", val); xga->pal_seq = val; break; - case 0x67: - xga->dac_r = val; - break; - case 0x68: - xga->pal_b = val; - break; - case 0x69: - xga->dac_g = val; - break; - case 0x6a: xga->sprite_data[xga->sprite_pos] = val; xga->sprite_pos = (xga->sprite_pos + 1) & 0x3ff; @@ -592,6 +582,9 @@ xga_ext_inb(uint16_t addr, void *priv) case 0x0e: case 0x0f: switch (xga->regs_idx) { + case 0: + ret = (xga->bus & DEVICE_MCA) ? 0x02 : 0x01; + break; case 4: if (xga->bus & DEVICE_MCA) ret = 0x01; /*32-bit MCA*/ @@ -724,13 +717,6 @@ xga_ext_inb(uint16_t addr, void *priv) ret = xga->sprite_pal_addr_idx >> 8; break; - case 0x62: - ret = xga->sprite_pal_addr_idx_prefetch & 0xff; - break; - case 0x63: - ret = xga->sprite_pal_addr_idx_prefetch >> 8; - break; - case 0x64: ret = xga->dac_mask; break; @@ -740,16 +726,16 @@ xga_ext_inb(uint16_t addr, void *priv) switch (xga->dac_pos) { case 0: xga->dac_pos++; - ret = svga->vgapal[index].r; + ret = xga->xgapal[index].r; break; case 1: xga->dac_pos++; - ret = svga->vgapal[index].g; + ret = xga->xgapal[index].g; break; case 2: xga->dac_pos = 0; xga->dac_addr = (xga->dac_addr + 1) & 0xff; - ret = svga->vgapal[index].b; + ret = xga->xgapal[index].b; break; default: @@ -761,21 +747,10 @@ xga_ext_inb(uint16_t addr, void *priv) ret = xga->pal_seq; break; - case 0x67: - ret = xga->dac_r; - break; - case 0x68: - ret = xga->pal_b; - break; - case 0x69: - ret = xga->dac_g; - break; - case 0x6a: - xga_log("Sprite POS Read = %d, addr idx = %04x\n", xga->sprite_pos, - xga->sprite_pal_addr_idx_prefetch); - ret = xga->sprite_data[xga->sprite_pos_prefetch]; - xga->sprite_pos_prefetch = (xga->sprite_pos_prefetch + 1) & 0x3ff; + xga_log("Sprite POS Read=%d.\n", xga->sprite_pos); + ret = xga->sprite_data[xga->sprite_pos]; + xga->sprite_pos = (xga->sprite_pos + 1) & 0x3ff; break; case 0x70: @@ -914,7 +889,7 @@ xga_accel_read_pattern_map_pixel(svga_t *svga, int x, int y, int map, uint32_t b uint8_t px; int skip = 0; - if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) + if ((addr < xga->linear_base) || (addr > (xga->linear_base + 0xfffff))) skip = 1; addr += (y * (width >> 3)); @@ -953,7 +928,7 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int uint8_t px; int skip = 0; - if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) + if ((addr < xga->linear_base) || (addr > (xga->linear_base + 0xfffff))) skip = 1; switch (xga->accel.px_map_format[map] & 7) { @@ -1025,7 +1000,7 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui uint8_t mask; int skip = 0; - if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) + if ((addr < xga->linear_base) || (addr > (xga->linear_base + 0xfffff))) skip = 1; switch (xga->accel.px_map_format[map] & 7) { @@ -1743,9 +1718,12 @@ xga_bitblt(svga_t *svga) static void xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) { + uint32_t min_addr = (0x1c00 + (xga->instance << 7)); + uint32_t max_addr = (0x1c00 + (xga->instance << 7)) + 0x7f; + addr &= 0x1fff; - if (addr >= 0x1800) { + if ((addr >= min_addr) && (addr <= max_addr)) { switch (addr & 0x7f) { case 0x11: xga->accel.control = val; @@ -2255,7 +2233,7 @@ xga_memio_writeb(uint32_t addr, uint8_t val, void *priv) xga_mem_write(addr, val, xga, svga, 1); - xga_log("Write MEMIOB = %04x, val = %02x\n", addr & 0x7f, val); + xga_log("[%04X:%08X]: Write MEMIOB = %04x, val = %02x\n", CS, cpu_state.pc, addr, val); } static void @@ -2266,7 +2244,7 @@ xga_memio_writew(uint32_t addr, uint16_t val, void *priv) xga_mem_write(addr, val, xga, svga, 2); - xga_log("Write MEMIOW = %04x, val = %04x\n", addr & 0x7f, val); + xga_log("[%04X:%08X]: Write MEMIOW = %04x, val = %04x\n", CS, cpu_state.pc, addr, val); } static void @@ -2277,21 +2255,25 @@ xga_memio_writel(uint32_t addr, uint32_t val, void *priv) xga_mem_write(addr, val, xga, svga, 4); - xga_log("Write MEMIOL = %04x, val = %08x\n", addr & 0x7f, val); + xga_log("[%04X:%08X]: Write MEMIOL = %04x, val = %08x\n", CS, cpu_state.pc, addr, val); } static uint8_t xga_mem_read(uint32_t addr, xga_t *xga, UNUSED(svga_t *svga)) { + uint32_t min_addr = (0x1c00 + (xga->instance << 7)); + uint32_t max_addr = (0x1c00 + (xga->instance << 7)) + 0x7f; uint8_t temp = 0; addr &= 0x1fff; - if (addr < 0x1800) { + if (addr < 0x1c00) { if (xga_standalone_enabled) temp = xga->bios_rom.rom[addr]; else temp = xga->vga_bios_rom.rom[addr]; - } else { + } else if ((addr >= 0x1c00) && (addr <= 0x1c7f) && xga->instance) { + temp = 0xff; + } else if ((addr >= min_addr) && (addr <= max_addr)) { switch (addr & 0x7f) { case 0x11: temp = xga->accel.control; @@ -2360,7 +2342,6 @@ xga_mem_read(uint32_t addr, xga_t *xga, UNUSED(svga_t *svga)) break; } } - return temp; } @@ -2479,7 +2460,7 @@ xga_render_overscan_left(xga_t *xga, svga_t *svga) if (svga->scrblank || (xga->h_disp == 0)) return; - uint32_t *line_ptr = svga->monitor->target_buffer->line[xga->displine + svga->y_add]; + uint32_t *line_ptr = buffer32->line[xga->displine + svga->y_add]; for (int i = 0; i < svga->x_add; i++) *line_ptr++ = svga->overscan_color; } @@ -2495,7 +2476,7 @@ xga_render_overscan_right(xga_t *xga, svga_t *svga) if (svga->scrblank || (xga->h_disp == 0)) return; - uint32_t *line_ptr = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add + xga->h_disp]; + uint32_t *line_ptr = &buffer32->line[xga->displine + svga->y_add][svga->x_add + xga->h_disp]; right = (overscan_x >> 1); for (int i = 0; i < right; i++) *line_ptr++ = svga->overscan_color; @@ -2512,10 +2493,11 @@ xga_render_4bpp(svga_t *svga) return; if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { - p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; + p = &buffer32->line[xga->displine + svga->y_add][svga->x_add]; if (xga->firstline_draw == 2000) xga->firstline_draw = xga->displine; + xga->lastline_draw = xga->displine; for (int x = 0; x <= xga->h_disp; x += 16) { @@ -2557,7 +2539,7 @@ xga_render_8bpp(svga_t *svga) return; if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { - p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; + p = &buffer32->line[xga->displine + svga->y_add][svga->x_add]; if (xga->firstline_draw == 2000) xga->firstline_draw = xga->displine; @@ -2595,7 +2577,7 @@ xga_render_16bpp(svga_t *svga) return; if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { - p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; + p = &buffer32->line[xga->displine + svga->y_add][svga->x_add]; if (xga->firstline_draw == 2000) xga->firstline_draw = xga->displine; @@ -2623,17 +2605,51 @@ xga_render_16bpp(svga_t *svga) } } +void +xga_write_test(uint32_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + if (xga_active && xga) { + if (((xga->op_mode & 7) >= 1) && (xga->aperture_cntl >= 1)) { + if (val == 0xa5) { /*Memory size test of XGA*/ + xga->test = val; + if (addr == 0xa0001) + xga->a5_test = 1; + else if (addr == 0xafffe) + xga->a5_test = 2; + + xga->on = 0; + vga_on = 1; + xga->disp_cntl_2 = 0; + xga_log("XGA test1 addr=%05x, test=%02x.\n", addr, xga->a5_test); + } else if (val == 0x5a) { + xga->test = val; + xga->on = 0; + vga_on = 1; + xga->disp_cntl_2 = 0; + xga_log("XGA test2 addr = %05x.\n", addr); + } else if ((addr == 0xa0000) || (addr == 0xa0010)) { + addr += xga->write_bank; + xga->vram[addr & xga->vram_mask] = val; + xga_log("XGA Linear endian reverse write, val = %02x, addr = %05x, banked mask = %04x, a5test=%d.\n", val, addr, svga->banked_mask, xga->a5_test); + if (!xga->a5_test) + xga->linear_endian_reverse = 1; + } + } else { + xga->on = 0; + vga_on = 1; + } + } +} + static void xga_write(uint32_t addr, uint8_t val, void *priv) { svga_t *svga = (svga_t *) priv; xga_t *xga = (xga_t *) svga->xga; - if (!xga->on) { - svga_write(addr, val, svga); - return; - } - addr &= xga->banked_mask; addr += xga->write_bank; @@ -2655,12 +2671,6 @@ static void xga_writew(uint32_t addr, uint16_t val, void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; - - if (!xga->on) { - svga_writew(addr, val, svga); - return; - } xga_write(addr, val & 0xff, svga); xga_write(addr + 1, val >> 8, svga); @@ -2670,12 +2680,6 @@ static void xga_writel(uint32_t addr, uint32_t val, void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; - - if (!xga->on) { - svga_writel(addr, val, svga); - return; - } xga_write(addr, val & 0xff, svga); xga_write(addr + 1, (val >> 8) & 0xff, svga); @@ -2683,6 +2687,49 @@ xga_writel(uint32_t addr, uint32_t val, void *priv) xga_write(addr + 3, (val >> 24) & 0xff, svga); } +uint8_t +xga_read_test(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + uint8_t ret = 0x00; + + if (xga_active && xga) { + if (((xga->op_mode & 7) >= 1) && (xga->aperture_cntl >= 1)) { + if (xga->test == 0xa5) { /*Memory size test of XGA*/ + if (addr == 0xa0001) { + ret = xga->test; + xga->on = 1; + vga_on = 0; + } else if ((addr == 0xa0000) && (xga->a5_test == 1)) { /*This is required by XGAKIT to pass the memory test*/ + xga_log("A5 test bank = %x.\n", addr); + addr += xga->read_bank; + ret = xga->vram[addr & xga->vram_mask]; + } else { + ret = xga->test; + xga->on = 1; + vga_on = 0; + } + xga_log("A5 read: XGA ON = %d, addr = %05x, ret = %02x, test1 = %x.\n", xga->on, addr, ret, xga->a5_test); + return ret; + } else if (xga->test == 0x5a) { + ret = xga->test; + xga->on = 1; + vga_on = 0; + xga_log("5A read: XGA ON = %d.\n", xga->on); + return ret; + } else if ((addr == 0xa0000) || (addr == 0xa0010)) { + addr += xga->read_bank; + return xga->vram[addr & xga->vram_mask]; + } + } else { + xga->on = 0; + vga_on = 1; + } + } + return ret; +} + static uint8_t xga_read(uint32_t addr, void *priv) { @@ -2690,11 +2737,6 @@ xga_read(uint32_t addr, void *priv) xga_t *xga = (xga_t *) svga->xga; uint8_t ret = 0xff; - if (!xga->on) { - ret = svga_read(addr, svga); - return ret; - } - addr &= xga->banked_mask; addr += xga->read_bank; @@ -2717,14 +2759,8 @@ static uint16_t xga_readw(uint32_t addr, void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; uint16_t ret = 0xffff; - if (!xga->on) { - ret = svga_readw(addr, svga); - return ret; - } - ret = xga_read(addr, svga); ret |= (xga_read(addr + 1, svga) << 8); @@ -2735,14 +2771,8 @@ static uint32_t xga_readl(uint32_t addr, void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; uint32_t ret = 0xffffffff; - if (!xga->on) { - ret = svga_readl(addr, svga); - return ret; - } - ret = xga_read(addr, svga); ret |= (xga_read(addr + 1, svga) << 8); ret |= (xga_read(addr + 2, svga) << 16); @@ -2883,43 +2913,11 @@ xga_readl_linear(uint32_t addr, void *priv) return ret; } -static void -xga_do_render(svga_t *svga) -{ - xga_t *xga = (xga_t *) svga->xga; - - xga_log("DISPCNTL = %d, vga = %d.\n", xga->disp_cntl_2 & 7, vga_on); - switch (xga->disp_cntl_2 & 7) { - case 2: - xga_render_4bpp(svga); - break; - case 3: - xga_render_8bpp(svga); - break; - case 4: - xga_render_16bpp(svga); - break; - default: - break; - } - - svga->x_add = (overscan_x >> 1); - xga_render_overscan_left(xga, svga); - xga_render_overscan_right(xga, svga); - svga->x_add = (overscan_x >> 1); - - if (xga->hwcursor_on) { - xga_hwcursor_draw(svga, xga->displine + svga->y_add); - xga->hwcursor_on--; - if (xga->hwcursor_on && xga->interlace) - xga->hwcursor_on--; - } -} - void -xga_poll(void *priv, svga_t *svga) +xga_poll(void *priv) { - xga_t *xga = (xga_t *) priv; + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; uint32_t x; int wx; int wy; @@ -2936,6 +2934,7 @@ xga_poll(void *priv, svga_t *svga) } timer_advance_u64(&svga->timer, svga->dispofftime); + svga->cgastat |= 1; xga->linepos = 1; if (xga->dispon) { @@ -2951,7 +2950,32 @@ xga_poll(void *priv, svga_t *svga) if (xga->hwcursor_on) xga->changedvram[xga->ma >> 12] = xga->changedvram[(xga->ma >> 12) + 1] = xga->interlace ? 3 : 2; - xga_do_render(svga); + xga_log("DISPCNTL = %d, vga = %d.\n", xga->disp_cntl_2 & 7, vga_on); + switch (xga->disp_cntl_2 & 7) { + case 2: + xga_render_4bpp(svga); + break; + case 3: + xga_render_8bpp(svga); + break; + case 4: + xga_render_16bpp(svga); + break; + default: + break; + } + + svga->x_add = (overscan_x >> 1); + xga_render_overscan_left(xga, svga); + xga_render_overscan_right(xga, svga); + svga->x_add = (overscan_x >> 1); + + if (xga->hwcursor_on) { + xga_hwcursor_draw(svga, xga->displine + svga->y_add); + xga->hwcursor_on--; + if (xga->hwcursor_on && xga->interlace) + xga->hwcursor_on--; + } if (xga->lastline < xga->displine) xga->lastline = xga->displine; @@ -2960,10 +2984,15 @@ xga_poll(void *priv, svga_t *svga) xga->displine++; if (xga->interlace) xga->displine++; + if ((svga->cgastat & 8) && ((xga->displine & 0x0f) == (svga->crtc[0x11] & 0x0f)) && svga->vslines) + svga->cgastat &= ~8; if (xga->displine > 1500) xga->displine = 0; } else { timer_advance_u64(&svga->timer, svga->dispontime); + if (xga->dispon) + svga->cgastat &= ~1; + xga->h_disp_on = 0; xga->linepos = 0; @@ -2971,6 +3000,7 @@ xga_poll(void *priv, svga_t *svga) if (xga->sc == xga->rowcount) { xga->sc = 0; + xga_log("MA=%08x, MALATCH=%x.\n", xga->ma, xga->ma_latch); xga->maback += (xga->rowoffset << 3); if (xga->interlace) xga->maback += (xga->rowoffset << 3); @@ -3010,6 +3040,7 @@ xga_poll(void *priv, svga_t *svga) } if (xga->vc == xga->v_syncstart) { xga->dispon = 0; + svga->cgastat |= 8; x = xga->h_disp; if (xga->interlace && !xga->oddeven) @@ -3057,13 +3088,10 @@ xga_poll(void *priv, svga_t *svga) static uint8_t xga_mca_read(int port, void *priv) { - const svga_t *svga = (svga_t *) priv; - const xga_t *xga = (xga_t *) svga->xga; + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; uint8_t ret = xga->pos_regs[port & 7]; - if (((port & 7) == 3) && !(ret & 1)) /*Always enable the mapping.*/ - ret |= 1; - xga_log("[%04X:%08X]: POS Read Port = %x, val = %02x\n", CS, cpu_state.pc, port & 7, xga->pos_regs[port & 7]); @@ -3081,7 +3109,6 @@ xga_mca_write(int port, uint8_t val, void *priv) return; io_removehandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); - mem_mapping_disable(&xga->bios_rom.mapping); mem_mapping_disable(&xga->memio_mapping); xga->on = 0; vga_on = 1; @@ -3090,8 +3117,6 @@ xga_mca_write(int port, uint8_t val, void *priv) /* Save the MCA register value. */ xga->pos_regs[port & 7] = val; - if (!(xga->pos_regs[4] & 1) && (mem_size >= 16384)) /*MCA 4MB addressing on systems with more than 16MB of memory*/ - xga->pos_regs[4] |= 1; if (xga->pos_regs[2] & 1) { xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; @@ -3101,10 +3126,10 @@ xga_mca_write(int port, uint8_t val, void *priv) io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); - if (xga->pos_regs[3] & 1) - mem_mapping_set_addr(&xga->bios_rom.mapping, xga->rom_addr, 0x2000); - else - mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr + 0x1c00 + (xga->instance * 0x80), 0x80); + if (xga->rom_addr) { + mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr, 0x2000); + xga_log("ROM address=%05x.\n", xga->rom_addr); + } } xga_log("[%04X:%08X]: POS Write Port = %x, val = %02x, linear base = %08x, instance = %d, " @@ -3118,6 +3143,7 @@ xga_mca_feedb(void *priv) const svga_t *svga = (svga_t *) priv; const xga_t *xga = (xga_t *) svga->xga; + xga_log("FeedB.\n"); return xga->pos_regs[2] & 1; } @@ -3127,10 +3153,10 @@ xga_mca_reset(void *priv) svga_t *svga = (svga_t *) priv; xga_t *xga = (xga_t *) svga->xga; - mem_mapping_disable(&xga->bios_rom.mapping); mem_mapping_disable(&xga->memio_mapping); xga->on = 0; vga_on = 1; + xga_log("MCA Reset.\n"); xga_mca_write(0x102, 0, svga); xga->linear_endian_reverse = 0; xga->a5_test = 0; @@ -3142,7 +3168,10 @@ xga_reset(void *priv) svga_t *svga = (svga_t *) priv; xga_t *xga = (xga_t *) svga->xga; - mem_mapping_disable(&xga->bios_rom.mapping); + if (!(xga->bus & DEVICE_MCA) && !xga_standalone_enabled) + mem_mapping_disable(&xga->bios_rom.mapping); + + xga_log("Normal Reset.\n"); mem_mapping_disable(&xga->memio_mapping); xga->on = 0; vga_on = 1; @@ -3155,32 +3184,31 @@ xga_pos_in(uint16_t addr, void *priv) { svga_t *svga = (svga_t *) priv; xga_t *xga = (xga_t *) svga->xga; - uint8_t ret = 0xff; + uint8_t ret = 0x00; if (!xga_standalone_enabled) { switch (addr) { case 0x0100: case 0x0101: - if (xga->instance_isa == xga->instance_num) + if (xga->instance == xga->instance_num) ret = xga->pos_regs[addr & 7]; else ret = 0xff; + + xga_log("%03xRead=%02x.\n", addr, ret); break; case 0x0102: + ret = xga->pos_regs[2]; + break; case 0x0105: - ret = xga->pos_regs[addr & 7]; - break; - case 0x0106: - ret = xga->pos_idx >> 8; - break; - case 0x0107: - ret = xga->pos_idx & 0xff; + ret = xga->pos_regs[5]; + xga_log("POS IDX Read 010%x ret = %02x.\n", addr & 7, ret); break; case 0x0103: - if (!(xga->pos_idx & 3)) + if ((xga->pos_idx & 3) == 0) { ret = xga->pos_regs[3]; - else - ret = 0; + ret |= (xga->dma_channel << 3); + } xga_log("POS IDX for 0103 = %d, ret = %02x.\n", xga->pos_idx & 3, ret); break; @@ -3195,31 +3223,25 @@ xga_pos_in(uint16_t addr, void *priv) case 2: ret = xga->pos_regs[1]; break; - case 3: - ret = 0; - break; default: break; } - xga_log("POS IDX for 0104 = %d, ret = %02x.\n", xga->pos_idx & 3, ret); break; - case 0x0108: - case 0x0109: - case 0x010a: - case 0x010b: - case 0x010c: - case 0x010d: - case 0x010e: - case 0x010f: - xga->instance_num = addr & 7; - if (xga->instance_isa == xga->instance_num) - ret = xga->instance_isa; - else - ret = 0; + case 0x0106: + ret = xga->pos_idx >> 8; + break; + case 0x0107: + ret = xga->pos_idx & 0xff; + break; + case 0x0108 ... 0x010f: + xga->instance_num = addr & 0x07; + if (xga->instance == xga->instance_num) + ret = xga->instance; ret |= xga->isa_pos_enable; + xga_log("%03xRead=%02x.\n", addr, ret); break; default: @@ -3227,12 +3249,15 @@ xga_pos_in(uint16_t addr, void *priv) } } else { switch (addr) { + case 0x0096: + ret = xga->vga_post; + break; case 0x0100: case 0x0101: ret = xga->pos_regs[addr & 7]; break; case 0x0103: - ret = xga->pos_regs[3] | 7; + ret = xga->pos_regs[3] | 0x06; ret |= (xga->dma_channel << 3); break; case 0x0102: @@ -3242,26 +3267,11 @@ xga_pos_in(uint16_t addr, void *priv) case 0x0107: ret = (xga_mca_read(addr, svga)); break; - case 0x0108: - case 0x0109: - case 0x010a: - case 0x010b: - case 0x010c: - case 0x010d: - case 0x010e: - case 0x010f: - xga->instance_num = addr & 7; - if (xga->instance_isa == xga->instance_num) - ret = xga->instance_isa; - else - ret = 0; - - ret |= xga->isa_pos_enable; - break; default: break; } + xga_log("XGA Standalone ISA Read Port=%04x, Ret=%02x.\n", addr, ret); } return ret; } @@ -3274,6 +3284,44 @@ xga_pos_out(uint16_t addr, uint8_t val, void *priv) if (!xga_standalone_enabled) { switch (addr) { + case 0x0096: + xga->vga_post = val; + xga_log("096Write=%02x.\n", val); + break; + case 0x0102: + xga->pos_regs[2] = (val & 0x01); + xga->pos_regs[2] |= ((xga->instance_isa << 1) | xga->ext_mem_addr); + io_removehandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); + mem_mapping_disable(&xga->memio_mapping); + if (xga->pos_regs[2] & 0x01) { + xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000); + xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; + xga->linear_base = ((xga->pos_regs[4] & 0xfe) * 0x1000000) + (xga->instance << 22); + xga->base_addr_1mb = (xga->pos_regs[5] & 0x0f) << 20; + io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); + xga_log("XGA ISA ROM address=%05x, instance=%d.\n", xga->rom_addr, xga->instance); + if (xga->rom_addr >= 0xc8000) + mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr, 0x2000); + else + mem_mapping_disable(&xga->memio_mapping); + } + xga_log("102Write=%02x.\n", val); + break; + case 0x0103: + if ((xga->pos_idx & 3) == 0) + xga->pos_regs[3] = val; + + xga_log("[%04X:%08X]: 103Write=%02x.\n", CS, cpu_state.pc, val); + break; + case 0x0104: + xga_log("104Write=%02x.\n", val); + if ((xga->pos_idx & 3) == 0) + xga->pos_regs[4] = val; + break; + case 0x0105: + xga_log("105Write=%02x.\n", val); + xga->pos_regs[5] = val; + break; case 0x0106: xga->pos_idx = (xga->pos_idx & 0x00ff) | (val << 8); break; @@ -3281,15 +3329,9 @@ xga_pos_out(uint16_t addr, uint8_t val, void *priv) xga->pos_idx = (xga->pos_idx & 0xff00) | val; xga_log("POS IDX Write = %04x.\n", xga->pos_idx); break; - case 0x0108: - case 0x0109: - case 0x010a: - case 0x010b: - case 0x010c: - case 0x010d: - case 0x010e: - case 0x010f: - xga->instance_num = addr & 7; + case 0x0108 ... 0x010f: + xga_log("%03xWrite=%02x.\n", addr, val); + xga->instance_num = addr & 0x07; xga->isa_pos_enable = val & 0x08; break; @@ -3297,17 +3339,10 @@ xga_pos_out(uint16_t addr, uint8_t val, void *priv) break; } } else { + xga_log("XGA Standalone ISA Write Port=%04x, Val=%02x.\n", addr, val); switch (addr) { - case 0x0108: - case 0x0109: - case 0x010a: - case 0x010b: - case 0x010c: - case 0x010d: - case 0x010e: - case 0x010f: - xga->instance_num = addr & 7; - xga->isa_pos_enable = val & 0x08; + case 0x0096: + xga->vga_post = val; break; default: @@ -3324,8 +3359,6 @@ xga_init(const device_t *info) svga_t *svga = svga_get_pri(); xga_t *xga = (xga_t *) calloc(1, sizeof(xga_t)); - FILE *fp; - uint8_t *rom = NULL; svga->xga = xga; @@ -3346,21 +3379,6 @@ xga_init(const device_t *info) xga->linear_endian_reverse = 0; xga->a5_test = 0; - fp = rom_fopen(xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, "rb"); - (void) fseek(fp, 0L, SEEK_END); - (void) fseek(fp, 0L, SEEK_SET); - - rom = malloc(xga->bios_rom.sz); - memset(rom, 0xff, xga->bios_rom.sz); - (void) !fread(rom, xga->bios_rom.sz, 1, fp); - (void) fclose(fp); - - xga->bios_rom.rom = rom; - xga->bios_rom.mask = xga->bios_rom.sz - 1; - if (fp != NULL) { - free(rom); - } - if (info->flags & DEVICE_MCA) { video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_xga_mca); xga->base_addr_1mb = 0; @@ -3368,29 +3386,30 @@ xga_init(const device_t *info) xga->instance = 0; xga->rom_addr = 0; rom_init(&xga->bios_rom, xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, 0xc0000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&xga->bios_rom.mapping); } else { - if (!xga_standalone_enabled) + xga->pos_regs[4] = 0x02; + if (!xga_standalone_enabled) { rom_init(&xga->vga_bios_rom, INMOS_XGA_BIOS_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_xga_isa); - - xga->pos_regs[2] = 1 | (xga->instance_isa << 1) | xga->ext_mem_addr; - xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; - xga->pos_regs[4] = 2; - if (mem_size >= 16384) { - xga->pos_regs[4] |= 1; - xga->pos_regs[5] = 0; } else { - xga->pos_regs[5] = ((mem_size * 64) >> 0x10) + 1; - if (xga->pos_regs[5] == 0x10) { + xga->pos_regs[2] = (xga->instance_isa << 1) | xga->ext_mem_addr; + xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000); + xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; + xga->pos_regs[2] |= 0x01; + if (mem_size >= 16384) { + xga->pos_regs[4] |= 0x01; xga->pos_regs[5] = 0; - xga->pos_regs[4] |= 1; + } else { + xga->pos_regs[5] = ((mem_size * 64) >> 0x10) + 1; + if (xga->pos_regs[5] == 0x10) { + xga->pos_regs[5] = 0x00; + xga->pos_regs[4] |= 0x01; + } } + xga->base_addr_1mb = (xga->pos_regs[5] & 0x0f) << 20; + xga->linear_base = ((xga->pos_regs[4] & 0xfe) * 0x1000000) + (xga->instance << 22); + rom_init(&xga->bios_rom, xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, xga->rom_addr, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); } - - xga->base_addr_1mb = (xga->pos_regs[5] & 0x0f) << 20; - xga->linear_base = ((xga->pos_regs[4] & 0xfe) * 0x1000000) + (xga->instance << 22); - xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000); } mem_mapping_add(&xga->video_mapping, 0, 0, xga_read, xga_readw, xga_readl, @@ -3399,9 +3418,14 @@ xga_init(const device_t *info) mem_mapping_add(&xga->linear_mapping, 0, 0, xga_read_linear, xga_readw_linear, xga_readl_linear, xga_write_linear, xga_writew_linear, xga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga); - mem_mapping_add(&xga->memio_mapping, 0, 0, xga_memio_readb, xga_memio_readw, xga_memio_readl, + if (xga_standalone_enabled) + mem_mapping_add(&xga->memio_mapping, 0, 0, xga_memio_readb, xga_memio_readw, xga_memio_readl, xga_memio_writeb, xga_memio_writew, xga_memio_writel, - !xga_standalone_enabled ? xga->vga_bios_rom.rom : xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga); + xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga); + else + mem_mapping_add(&xga->memio_mapping, 0, 0, xga_memio_readb, xga_memio_readw, xga_memio_readl, + xga_memio_writeb, xga_memio_writew, xga_memio_writel, + xga->vga_bios_rom.rom, MEM_MAPPING_EXTERNAL, svga); mem_mapping_disable(&xga->linear_mapping); mem_mapping_disable(&xga->memio_mapping); @@ -3412,13 +3436,12 @@ xga_init(const device_t *info) if (xga->bus & DEVICE_MCA) { mca_add(xga_mca_read, xga_mca_write, xga_mca_feedb, xga_mca_reset, svga); } else { - io_sethandler(0x0100, 0x0008, xga_pos_in, NULL, NULL, NULL, NULL, NULL, svga); - if (!xga_standalone_enabled) - io_sethandler(0x0106, 0x0002, NULL, NULL, NULL, xga_pos_out, NULL, NULL, svga); - - io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); - io_sethandler(0x0108, 0x0008, xga_pos_in, NULL, NULL, xga_pos_out, NULL, NULL, svga); - mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr + 0x1c00 + (xga->instance * 0x80), 0x80); + io_sethandler(0x0096, 0x0001, xga_pos_in, NULL, NULL, xga_pos_out, NULL, NULL, svga); + io_sethandler(0x0100, 0x0010, xga_pos_in, NULL, NULL, xga_pos_out, NULL, NULL, svga); + if (xga_standalone_enabled) { + io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); + mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr, 0x2000); + } } return svga; } @@ -3598,6 +3621,83 @@ static const device_config_t xga_isa_configuration[] = { // clang-format on }; +static const device_config_t xga_inmos_isa_configuration[] = { + // clang-format off + { + .name = "type", + .description = "XGA type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "XGA-1", + .value = 0 + }, + { + .description = "XGA-2", + .value = 1 + }, + { .description = "" } + } + }, + { + .name = "instance", + .description = "Instance", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 6, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0 (2100h-210Fh)", .value = 0 }, + { .description = "1 (2110h-211Fh)", .value = 1 }, + { .description = "2 (2120h-212Fh)", .value = 2 }, + { .description = "3 (2130h-213Fh)", .value = 3 }, + { .description = "4 (2140h-214Fh)", .value = 4 }, + { .description = "5 (2150h-215Fh)", .value = 5 }, + { .description = "6 (2160h-216Fh)", .value = 6 }, + { .description = "7 (2170h-217Fh)", .value = 7 }, + { .description = "" } + }, + }, + { + .name = "ext_mem_addr", + .description = "MMIO address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0040, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "C800h", .value = 0x0040 }, + { .description = "CA00h", .value = 0x0050 }, + { .description = "CC00h", .value = 0x0060 }, + { .description = "CE00h", .value = 0x0070 }, + { .description = "" } + }, + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "DMA 6", .value = 6 }, + { .description = "DMA 7", .value = 7 }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + const device_t xga_device = { .name = "XGA (MCA)", .internal_name = "xga_mca", @@ -3637,7 +3737,7 @@ const device_t inmos_isa_device = { { .available = inmos_xga_available }, .speed_changed = xga_speed_changed, .force_redraw = xga_force_redraw, - .config = xga_isa_configuration + .config = xga_inmos_isa_configuration }; void