From 61273f5c1ff7460b0f12b036053562fb379461a5 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 24 Oct 2021 19:06:05 +0200 Subject: [PATCH 1/4] Video changes: Improved the banking of the ATI 28800-5 cards (VGA Charger and VGA Wonder XL). Improved the skew and horizontal display of some of the ET4000W32P cards as well as the cursor. Made the Oak OTI 077 and PVGA WD90c30 cards use the Sierra 11487 (actually a clone is used in the real cards). For the WD90c30, changed the way the hack is involved. Reverted some changes of the S3 Vision/Trio that originally made glitches, now the glitches are gone and the accelerator renders fine. Re-organized the Sierra 1148x RAMDAC's and added the 11486 (Mark 1). MCA SVGA cards use the full 32-bit mapping. --- src/include/86box/vid_svga.h | 2 +- src/video/vid_ati28800.c | 205 +++++++++++-------- src/video/vid_et4000w32.c | 134 +++++++----- src/video/vid_oak_oti.c | 25 +++ src/video/vid_paradise.c | 45 +++- src/video/vid_s3.c | 363 +++++++++++++++++++-------------- src/video/vid_sc1148x_ramdac.c | 84 +++++--- src/video/vid_svga.c | 2 +- src/video/vid_table.c | 8 +- 9 files changed, 551 insertions(+), 317 deletions(-) diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 90282a578..30d30254c 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -290,7 +290,7 @@ extern const device_t icd2061_device; extern const device_t ics9161_device; extern const device_t sc11483_ramdac_device; extern const device_t sc11487_ramdac_device; -extern const device_t sc11484_ramdac_device; +extern const device_t sc11486_ramdac_device; extern const device_t sc11484_nors2_ramdac_device; extern const device_t sc1502x_ramdac_device; extern const device_t sdac_ramdac_device; diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index d6630ccf8..565418e84 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -59,6 +59,7 @@ #endif #define BIOS_ROM_PATH "roms/video/ati28800/bios.bin" +#define BIOS_VGAXL_ROM_PATH "roms/video/ati28800/ATI_VGAWonder_XL.bin" typedef struct ati28800_t @@ -82,6 +83,8 @@ typedef struct ati28800_t int get_korean_font_index; uint16_t get_korean_font_base; int ksc5601_mode_enabled; + + int type, type_korean; } ati28800_t; @@ -111,7 +114,6 @@ ati28800_log(const char *fmt, ...) static void ati28800_recalctimings(svga_t *svga); - static void ati28800_out(uint16_t addr, uint8_t val, void *p) { @@ -134,37 +136,36 @@ ati28800_out(uint16_t addr, uint8_t val, void *p) ati28800_log("ATI 28800 write reg=0x%02X, val=0x%02X\n", ati28800->index, val); switch (ati28800->index) { case 0xa3: - ati28800->regs[0xa3] = val & 0x1f; - svga_recalctimings(svga); + if ((old ^ val) & 0x10) + svga_recalctimings(svga); break; - case 0xa6: - ati28800->regs[0xa6] = val & 0xc9; - break; - case 0xab: - ati28800->regs[0xab] = val & 0xdf; + case 0xa7: + if ((old ^ val) & 0x80) + svga_recalctimings(svga); break; case 0xb0: - ati28800->regs[0xb0] = val & 0x7d; - svga_recalctimings(svga); - break; - case 0xb1: - ati28800->regs[0xb0] = val & 0x7f; + if ((old ^ val) & 0x60) + svga_recalctimings(svga); break; case 0xb2: + case 0xbe: if (ati28800->regs[0xbe] & 0x08) { /* Read/write bank mode */ - svga->read_bank = (((val & 0x01) << 3) | ((val & 0xe0) >> 5)) * 0x10000; - svga->write_bank = ((val & 0x1e) >> 1) * 0x10000; + svga->read_bank = (((ati28800->regs[0xb2] & 0x01) << 3) | ((ati28800->regs[0xb2] & 0xe0) >> 5)) * 0x10000; + svga->write_bank = ((ati28800->regs[0xb2] & 0x1e) >> 1) * 0x10000; } else { /* Single bank mode */ - svga->read_bank = ((val & 0x1e) >> 1) * 0x10000; - svga->write_bank = ((val & 0x1e) >> 1) * 0x10000; + svga->read_bank = ((ati28800->regs[0xb2] & 0x1e) >> 1) * 0x10000; + svga->write_bank = ((ati28800->regs[0xb2] & 0x1e) >> 1) * 0x10000; + } + if (ati28800->index == 0xbe) { + if ((old ^ val) & 0x10) + svga_recalctimings(svga); } break; case 0xb3: - ati28800->regs[0xb3] = val & 0xef; ati_eeprom_write(&ati28800->eeprom, val & 8, val & 2, val & 1); break; case 0xb6: - if ((old ^ val) & 0x10) + if ((old ^ val) & 0x11) svga_recalctimings(svga); break; case 0xb8: @@ -179,7 +180,10 @@ ati28800_out(uint16_t addr, uint8_t val, void *p) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - sc1502x_ramdac_out(addr, val, svga->ramdac, svga); + if (ati28800->type == 1) + sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); + else + svga_out(addr, val, svga); return; case 0x3D4: @@ -190,12 +194,6 @@ ati28800_out(uint16_t addr, uint8_t val, void *p) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) val = (svga->crtc[7] & ~0x10) | (val & 0x10); - if ((ati28800->regs[0xb4] & 0x10) && ((svga->crtcreg == 0x0a) || (svga->crtcreg == 0x0b))) - return; - if ((ati28800->regs[0xb4] & 0x20) && ((svga->crtc[0x08] & 0x7f) && (svga->crtc[0x14] & 0x1f))) - return; - if ((ati28800->regs[0xb4] & 0x40) && ((svga->crtcreg <= 0x06) && (svga->crtc[0x07] & 0x10) != 0x10)) - return; old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; @@ -299,22 +297,23 @@ ati28800_in(uint16_t addr, void *p) break; case 0x1cf: switch (ati28800->index) { - case 0xa0: - temp = 0x10; - break; case 0xaa: temp = ati28800->id; break; case 0xb0: - if (ati28800->memory == 1024) - temp = 0x08; - else if (ati28800->memory == 512) - temp = 0x10; - else - temp = 0x00; + temp = ati28800->regs[0xb0] | 0x80; + if (ati28800->memory == 1024) { + temp &= ~0x10; + temp |= 0x08; + } else if (ati28800->memory == 512) { + temp |= 0x10; + temp &= ~0x08; + } else { + temp &= ~0x18; + } break; case 0xb7: - temp = ati28800->regs[ati28800->index] & ~8; + temp = ati28800->regs[0xb7] & ~8; if (ati_eeprom_read(&ati28800->eeprom)) temp |= 8; break; @@ -333,7 +332,9 @@ ati28800_in(uint16_t addr, void *p) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - return sc1502x_ramdac_in(addr, svga->ramdac, svga); + if (ati28800->type == 1) + return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); + return svga_in(addr, svga); case 0x3D4: temp = svga->crtcreg; @@ -401,8 +402,14 @@ ati28800_recalctimings(svga_t *svga) { ati28800_t *ati28800 = (ati28800_t *)svga->p; - switch (((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1) | - ((svga->miscout & 0x0C) >> 2)) { + if (ati28800->regs[0xa3] & 0x10) + svga->ma_latch |= 0x10000; + + if (ati28800->regs[0xb0] & 0x40) + svga->ma_latch |= 0x20000; + + switch (((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1) | + ((svga->miscout & 0x0C) >> 2)) { case 0x00: svga->clock = (cpuclock * (double)(1ull << 32)) / 42954000.0; break; case 0x01: svga->clock = (cpuclock * (double)(1ull << 32)) / 48771000.0; break; case 0x02: ati28800_log ("clock 2\n"); break; @@ -420,38 +427,69 @@ ati28800_recalctimings(svga_t *svga) case 0x0E: svga->clock = (cpuclock * (double)(1ull << 32)) / 75000000.0; break; case 0x0F: svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; break; default: break; - } + } - if (ati28800->regs[0xb8] & 0x40) + if (ati28800->regs[0xb8] & 0x40) svga->clock *= 2; - if (ati28800->regs[0xa3] & 0x10) - svga->ma |= 0x10000; + if (ati28800->regs[0xa7] & 0x80) + svga->clock *= 3; - if (ati28800->regs[0xb0] & 0x40) - svga->ma |= 0x20000; - - if (ati28800->regs[0xb6] & 0x10) { + if (ati28800->regs[0xb6] & 0x10) { svga->hdisp <<= 1; svga->htotal <<= 1; svga->rowoffset <<= 1; - } - - if (!svga->scrblank && (ati28800->regs[0xb0] & 0x20)) { /* Extended 256 colour modes */ - switch (svga->bpp) { - case 8: - svga->render = svga_render_8bpp_highres; - svga->rowoffset <<= 1; - svga->ma <<= 1; - break; - case 15: - svga->render = svga_render_15bpp_highres; - svga->hdisp >>= 1; - svga->rowoffset <<= 1; - svga->ma <<= 1; - break; + svga->gdcreg[5] &= ~0x40; } - } + + if (ati28800->regs[0xb0] & 0x20) { + svga->gdcreg[5] |= 0x40; + } + + if (!svga->scrblank && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_4bpp_lowres; + else + svga->render = svga_render_4bpp_highres; + break; + case 0x20: /*4 colours*/ + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_2bpp_lowres; + else + svga->render = svga_render_2bpp_highres; + break; + case 0x40: case 0x60: /*256+ colours*/ + switch (svga->bpp) { + case 8: + svga->map8 = svga->pallook; + if (svga->lowres) + svga->render = svga_render_8bpp_lowres; + else { + svga->render = svga_render_8bpp_highres; + svga->rowoffset <<= 1; + svga->ma_latch <<= 1; + } + break; + case 15: + if (svga->lowres) + svga->render = svga_render_15bpp_lowres; + else { + svga->render = svga_render_15bpp_highres; + svga->hdisp >>= 1; + svga->rowoffset <<= 1; + svga->ma_latch <<= 1; + } + break; + } + break; + } + } + } + + svga->vram_display_mask = (ati28800->regs[0xb6] & 1) ? ((ati28800->memory << 10) - 1) : 0x3ffff; } @@ -466,14 +504,15 @@ ati28800k_recalctimings(svga_t *svga) svga->render = svga_render_text_80_ksc5601; } - void * ati28800k_init(const device_t *info) { ati28800_t *ati28800 = (ati28800_t *) malloc(sizeof(ati28800_t)); memset(ati28800, 0, sizeof(ati28800_t)); - if (info->local == 0) { + ati28800->type_korean = info->local; + + if (ati28800->type_korean == 0) { ati28800->memory = device_get_config_int("memory"); video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati28800); } else { @@ -489,7 +528,7 @@ ati28800k_init(const device_t *info) ati28800->in_get_korean_font_kind_set = 0; ati28800->ksc5601_mode_enabled = 0; - switch(info->local) { + switch(ati28800->type_korean) { case 0: default: rom_init(&ati28800->bios_rom, BIOS_ATIKOR_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -512,12 +551,12 @@ ati28800k_init(const device_t *info) NULL, NULL); - ati28800->svga.ramdac = device_add(&sc1502x_ramdac_device); - io_sethandler(0x01ce, 0x0002, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800); io_sethandler(0x03c0, 0x0020, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800); ati28800->svga.miscout = 1; + ati28800->svga.bpp = 8; + ati28800->svga.packed_chain4 = 1; ati28800->svga.ksc5601_sbyte_mask = 0; ati28800->svga.ksc5601_udc_area_msb[0] = 0xC9; ati28800->svga.ksc5601_udc_area_msb[1] = 0xFE; @@ -541,14 +580,16 @@ ati28800_init(const device_t *info) ati28800->memory = device_get_config_int("memory"); - switch(info->local) { + ati28800->type = info->local; + + switch(ati28800->type) { case VGAWONDERXL: - ati28800->id = 6; - rom_init_interleaved(&ati28800->bios_rom, - BIOS_VGAXL_EVEN_PATH, - BIOS_VGAXL_ODD_PATH, - 0xc0000, 0x10000, 0xffff, - 0, MEM_MAPPING_EXTERNAL); + ati28800->id = 5; + rom_init(&ati28800->bios_rom, + BIOS_VGAXL_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + ati28800->svga.ramdac = device_add(&sc11486_ramdac_device); break; #if defined(DEV_BRANCH) && defined(USE_XL24) @@ -576,8 +617,6 @@ ati28800_init(const device_t *info) ati28800_in, ati28800_out, NULL, NULL); - - ati28800->svga.ramdac = device_add(&sc1502x_ramdac_device); io_sethandler(0x01ce, 2, ati28800_in, NULL, NULL, @@ -587,8 +626,10 @@ ati28800_init(const device_t *info) ati28800_out, NULL, NULL, ati28800); ati28800->svga.miscout = 1; + ati28800->svga.bpp = 8; + ati28800->svga.packed_chain4 = 1; - switch (info->local) { + switch (ati28800->type) { case VGAWONDERXL: ati_eeprom_load(&ati28800->eeprom, "ati28800xl.nvr", 0); break; @@ -616,7 +657,7 @@ ati28800_available(void) static int -ati28800k_available() +ati28800k_available(void) { return ((rom_present(BIOS_ATIKOR_PATH) && rom_present(FONT_ATIKOR_PATH))); } @@ -625,7 +666,7 @@ ati28800k_available() static int compaq_ati28800_available(void) { - return((rom_present(BIOS_VGAXL_EVEN_PATH) && rom_present(BIOS_VGAXL_ODD_PATH))); + return((rom_present(BIOS_VGAXL_ROM_PATH))); } @@ -719,7 +760,7 @@ static const device_config_t ati28800_wonderxl_config[] = const device_t ati28800_device = { - "ATI-28800", + "ATI 28800-5 (ATI VGA Charger)", DEVICE_ISA, 0, ati28800_init, ati28800_close, NULL, @@ -765,7 +806,7 @@ const device_t ati28800k_spc6033p_device = const device_t compaq_ati28800_device = { - "Compaq ATI-28800", + "ATI 28800-5 (ATI VGA Wonder XL)", DEVICE_ISA, VGAWONDERXL, ati28800_init, ati28800_close, NULL, diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 36f8b67fb..233783439 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -97,11 +97,12 @@ typedef struct et4000w32p_t uint32_t pattern_addr, source_addr, dest_addr, mix_addr; } queued, internal; + uint8_t osr; uint8_t status; int pattern_x, source_x, pattern_x_back, source_x_back, pattern_y, source_y, cpu_dat_pos, pix_pos, - cpu_input_num; + cpu_input_num, queue; uint32_t pattern_addr, source_addr, dest_addr, mix_addr, pattern_back, source_back, dest_back, mix_back, @@ -119,9 +120,9 @@ typedef struct et4000w32p_t static int et4000w32_vbus[4] = {1, 2, 4, 4}; -static int et4000w32_max_x[8] = {0, 0, 4, 8, 16, 32, 64, 0x70000000}; -static int et4000w32_wrap_x[8] = {0, 0, 3, 7, 15, 31, 63, 0xffffffff}; -static int et4000w32_wrap_y[8] = {1, 2, 4, 8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}; +static int et4000w32_max_x[8] = {0,0,4,8,0x10,0x20,0x40,0x70000000}; +static int et4000w32_wrap_x[8] = {0,0,3,7,0x0F,0x1F,0x3F,~0}; +static int et4000w32_wrap_y[8] = {1,2,4,8,~0,~0,~0,~0}; static video_timings_t timing_et4000w32_vlb = {VIDEO_BUS, 4, 4, 4, 10, 10, 10}; static video_timings_t timing_et4000w32_pci = {VIDEO_PCI, 4, 4, 4, 10, 10, 10}; @@ -271,14 +272,24 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *p) switch (svga->bpp) { case 8: svga->hwcursor.xoff += 32; - break; + break; } } if (svga->hwcursor.xsize == 128) { svga->hwcursor.xoff &= 0x7f; svga->hwcursor.yoff &= 0x7f; + if (et4000->type > ET4000W32P_REVC) { + if (svga->bpp == 24) { + et4000->adjust_cursor = 2; + } + } } else { + if (et4000->type > ET4000W32P_REVC) { + if (svga->bpp == 24 && et4000->adjust_cursor) { + et4000->adjust_cursor = 0; + } + } svga->hwcursor.xoff &= 0x3f; svga->hwcursor.yoff &= 0x3f; } @@ -331,10 +342,15 @@ et4000w32p_in(uint16_t addr, void *p) case 0x214B: case 0x215B: case 0x216B: case 0x217B: if (et4000->index == 0xec) return (et4000->regs[0xec] & 0xf) | (et4000->rev << 4); - if (et4000->index == 0xee) { /* Preliminary implementation */ - if (svga->bpp == 8) - return 3; - else if (svga->bpp == 16) + if (et4000->index == 0xee) { + if (svga->bpp == 8) { + if ((svga->gdcreg[5] & 0x60) >= 0x40) + return 3; + else if ((svga->gdcreg[5] & 0x60) == 0x20) + return 1; + else + return 2; + } else if (svga->bpp == 15 || svga->bpp == 16) return 4; else break; @@ -409,13 +425,21 @@ et4000w32p_recalctimings(svga_t *svga) switch (svga->bpp) { case 15: case 16: svga->hdisp >>= 1; - if (et4000->type <= ET4000W32P_REVC) - et4000->adjust_cursor = 1; + if (et4000->type <= ET4000W32P_REVC) { + if (et4000->type == ET4000W32P_REVC) { + if (svga->hdisp != 1024) + et4000->adjust_cursor = 1; + } else + et4000->adjust_cursor = 1; + } break; case 24: svga->hdisp /= 3; if (et4000->type <= ET4000W32P_REVC) et4000->adjust_cursor = 2; + if (et4000->type == ET4000W32P_DIAMOND && (svga->hdisp == 640/2 || svga->hdisp == 1232)) { + svga->hdisp = 640; + } break; } @@ -569,45 +593,51 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) case 0x7f80: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFFFFFF00) | val; break; case 0x7f81: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFFFF00FF) | (val << 8); break; case 0x7f82: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0xFF00FFFF) | (val << 16); break; - case 0x7f83: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x00FFFFFF) | (val << 24); break; + case 0x7f83: et4000->acl.queued.pattern_addr = (et4000->acl.queued.pattern_addr & 0x00FFFFFF) | (val << 24); et4000->acl.queue++; break; case 0x7f84: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFFFFFF00) | val; break; case 0x7f85: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFFFF00FF) | (val << 8); break; case 0x7f86: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0xFF00FFFF) | (val << 16); break; - case 0x7f87: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x00FFFFFF) | (val << 24); break; + case 0x7f87: et4000->acl.queued.source_addr = (et4000->acl.queued.source_addr & 0x00FFFFFF) | (val << 24); et4000->acl.queue++; break; case 0x7f88: et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0xFF00) | val; break; - case 0x7f89: et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0x00FF) | (val << 8); break; + case 0x7f89: et4000->acl.queued.pattern_off = (et4000->acl.queued.pattern_off & 0x00FF) | (val << 8); et4000->acl.queue++; break; case 0x7f8a: et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0xFF00) | val; break; - case 0x7f8b: et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0x00FF) | (val << 8); break; + case 0x7f8b: et4000->acl.queued.source_off = (et4000->acl.queued.source_off & 0x00FF) | (val << 8); et4000->acl.queue++;break; case 0x7f8c: et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0xFF00) | val; break; - case 0x7f8d: et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00FF) | (val << 8); break; + case 0x7f8d: et4000->acl.queued.dest_off = (et4000->acl.queued.dest_off & 0x00FF) | (val << 8); et4000->acl.queue++; break; case 0x7f8e: + et4000->acl.queue++; if (et4000->type >= ET4000W32P_REVC) et4000->acl.queued.pixel_depth = val; else et4000->acl.queued.vbus = val; break; - case 0x7f8f: et4000->acl.queued.xy_dir = val; break; - case 0x7f90: et4000->acl.queued.pattern_wrap = val; break; - case 0x7f92: et4000->acl.queued.source_wrap = val; break; + case 0x7f8f: et4000->acl.queued.xy_dir = val; et4000->acl.queue++; break; + case 0x7f90: et4000->acl.queued.pattern_wrap = val; et4000->acl.queue++; break; + case 0x7f92: et4000->acl.queued.source_wrap = val; et4000->acl.queue++; break; case 0x7f98: et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0xFF00) | val; break; - case 0x7f99: et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0x00FF) | (val << 8); break; + case 0x7f99: et4000->acl.queued.count_x = (et4000->acl.queued.count_x & 0x00FF) | (val << 8); et4000->acl.queue++; break; case 0x7f9a: et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0xFF00) | val; break; - case 0x7f9b: et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00FF) | (val << 8); break; - case 0x7f9c: et4000->acl.queued.ctrl_routing = val; break; - case 0x7f9d: et4000->acl.queued.ctrl_reload = val; break; - case 0x7f9e: et4000->acl.queued.rop_bg = val; break; - case 0x7f9f: et4000->acl.queued.rop_fg = val; break; + case 0x7f9b: et4000->acl.queued.count_y = (et4000->acl.queued.count_y & 0x00FF) | (val << 8); et4000->acl.queue++; break; + case 0x7f9c: et4000->acl.queued.ctrl_routing = val; et4000->acl.queue++; break; + case 0x7f9d: et4000->acl.queued.ctrl_reload = val; et4000->acl.queue++; break; + case 0x7f9e: et4000->acl.queued.rop_bg = val; et4000->acl.queue++; break; + case 0x7f9f: et4000->acl.queued.rop_fg = val; et4000->acl.queue++; break; case 0x7fa0: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFFFFFF00) | val; break; case 0x7fa1: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFFFF00FF) | (val << 8); break; case 0x7fa2: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0xFF00FFFF) | (val << 16); break; case 0x7fa3: et4000->acl.queued.dest_addr = (et4000->acl.queued.dest_addr & 0x00FFFFFF) | (val << 24); + et4000->acl.queue++; et4000->acl.internal = et4000->acl.queued; if (et4000->type >= ET4000W32P_REVC) { - et4000w32p_blit_start(et4000); - if (!(et4000->acl.queued.ctrl_routing & 0x43)) - et4000w32p_blit(0xffffff, ~0, 0, 0, et4000); - if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3)) - et4000w32p_blit(4, ~0, 0, 0, et4000); + if (et4000->acl.osr & 0x10) { + et4000w32p_blit_start(et4000); + if (!(et4000->acl.queued.ctrl_routing & 0x43)) { + et4000w32p_blit(0xffffff, ~0, 0, 0, et4000); + } + if ((et4000->acl.queued.ctrl_routing & 0x40) && !(et4000->acl.internal.ctrl_routing & 3)) { + et4000w32p_blit(4, ~0, 0, 0, et4000); + } + } } else { et4000w32_blit_start(et4000); et4000->acl.cpu_input_num = 0; @@ -618,15 +648,15 @@ et4000w32p_accel_write_fifo(et4000w32p_t *et4000, uint32_t addr, uint8_t val) case 0x7fa4: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFFFF00) | val; break; case 0x7fa5: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFFFF00FF) | (val << 8); break; case 0x7fa6: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0xFF00FFFF) | (val << 16); break; - case 0x7fa7: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0x00FFFFFF) | (val << 24); break; + case 0x7fa7: et4000->acl.queued.mix_addr = (et4000->acl.queued.mix_addr & 0x00FFFFFF) | (val << 24); et4000->acl.queue++; break; case 0x7fa8: et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0xFF00) | val; break; - case 0x7fa9: et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0x00FF) | (val << 8); break; + case 0x7fa9: et4000->acl.queued.mix_off = (et4000->acl.queued.mix_off & 0x00FF) | (val << 8); et4000->acl.queue++; break; case 0x7faa: et4000->acl.queued.error = (et4000->acl.queued.error & 0xFF00) | val; break; - case 0x7fab: et4000->acl.queued.error = (et4000->acl.queued.error & 0x00FF) | (val << 8); break; + case 0x7fab: et4000->acl.queued.error = (et4000->acl.queued.error & 0x00FF) | (val << 8); et4000->acl.queue++; break; case 0x7fac: et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0xFF00) | val; break; - case 0x7fad: et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0x00FF) | (val << 8); break; + case 0x7fad: et4000->acl.queued.dmin = (et4000->acl.queued.dmin & 0x00FF) | (val << 8); et4000->acl.queue++; break; case 0x7fae: et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0xFF00) | val; break; - case 0x7faf: et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0x00FF) | (val << 8); break; + case 0x7faf: et4000->acl.queued.dmaj = (et4000->acl.queued.dmaj & 0x00FF) | (val << 8); et4000->acl.queue++; break; } } @@ -638,17 +668,17 @@ et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val) if (!(et4000->acl.status & ACL_XYST)) return; if (et4000->acl.internal.ctrl_routing & 3) { + et4000->acl.queue++; if ((et4000->acl.internal.ctrl_routing & 3) == 2) { - if (et4000->acl.mix_addr & 7) - et4000w32p_blit(8 - (et4000->acl.mix_addr & 7), val >> (et4000->acl.mix_addr & 7), 0, 1, et4000); - else - et4000w32p_blit(8, val, 0, 1, et4000); + et4000w32p_blit(8 - (et4000->acl.mix_addr & 7), val >> (et4000->acl.mix_addr & 7), 0, 1, et4000); } - else if ((et4000->acl.internal.ctrl_routing & 3) == 1) + else if ((et4000->acl.internal.ctrl_routing & 3) == 1) { et4000w32p_blit(1, ~0, val, 2, et4000); + } } } else { if (!(et4000->acl.status & ACL_XYST)) { + et4000->acl.queue++; et4000->acl.queued.dest_addr = (addr & 0x1FFF) + et4000->mmu.base[et4000->bank]; et4000->acl.internal = et4000->acl.queued; et4000w32_blit_start(et4000); @@ -658,6 +688,7 @@ et4000w32p_accel_write_mmu(et4000w32p_t *et4000, uint32_t addr, uint8_t val) } if (et4000->acl.internal.ctrl_routing & 7) { + et4000->acl.queue++; et4000->acl.cpu_input = (et4000->acl.cpu_input &~ (0xFF << (et4000->acl.cpu_input_num << 3))) | (val << (et4000->acl.cpu_input_num << 3)); et4000->acl.cpu_input_num++; @@ -716,6 +747,7 @@ et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) case 0x7f0a: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0xFF00FFFF) | (val << 16); break; case 0x7f0b: et4000->mmu.base[2] = (et4000->mmu.base[2] & 0x00FFFFFF) | (val << 24); break; case 0x7f13: et4000->mmu.ctrl = val; break; + case 0x7f31: et4000->acl.osr = val; break; } break; } @@ -771,13 +803,23 @@ et4000w32p_mmu_read(uint32_t addr, void *p) case 0x7f13: return et4000->mmu.ctrl; case 0x7f36: - if (et4000->type >= ET4000W32P_REVC) { + if (et4000->type >= ET4000W32P_REVC) { + if (et4000->acl.queue) { + et4000->acl.status |= ACL_RDST; + et4000->acl.queue = 0; + } else + et4000->acl.status &= ~ACL_RDST; + temp = et4000->acl.status; - temp &= ~(ACL_RDST | ACL_WRST); - if (temp == ACL_XYST && (et4000->acl.internal.ctrl_routing == 1 || et4000->acl.internal.ctrl_routing == 2)) - temp |= ACL_RDST; } else { et4000->acl.status &= ~(ACL_XYST | ACL_SSO); + + if (et4000->acl.queue) { + et4000->acl.status |= ACL_RDST; + et4000->acl.queue = 0; + } else + et4000->acl.status &= ~ACL_RDST; + temp = et4000->acl.status; } return temp; @@ -883,7 +925,7 @@ et4000w32p_blit_start(et4000w32p_t *et4000) et4000->acl.status |= ACL_XYST; et4000w32_log("ACL status XYST set\n"); if ((!(et4000->acl.internal.ctrl_routing & 7) || (et4000->acl.internal.ctrl_routing & 4)) && !(et4000->acl.internal.ctrl_routing & 0x40)) - et4000->acl.status |= ACL_SSO; + et4000->acl.status |= ACL_SSO; if (et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]) { et4000->acl.pattern_x = et4000->acl.pattern_addr & et4000w32_wrap_x[et4000->acl.internal.pattern_wrap & 7]; @@ -997,7 +1039,7 @@ et4000w32p_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32 if (!(et4000->acl.status & ACL_XYST) && (et4000->type >= ET4000W32P_REVC)) return; - if (et4000->acl.internal.xy_dir & 0x80){ /* Line draw */ + if (et4000->acl.internal.xy_dir & 0x80) { /* Line draw */ while (count--) { et4000w32_log("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & et4000->vram_mask]; diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index 892967837..941359987 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -28,6 +28,7 @@ #include <86box/device.h> #include <86box/video.h> #include <86box/vid_svga.h> +#include <86box/vid_svga_render.h> #define BIOS_037C_PATH "roms/video/oti/bios.bin" #define BIOS_067_AMA932J_PATH "roms/machines/ama932j/oti067.bin" @@ -85,6 +86,14 @@ oti_out(uint16_t addr, uint8_t val, void *p) return; } else break; + break; + + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: + if (oti->chip_id == OTI_077) + sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); + else + svga_out(addr, val, svga); + return; case 0x3D4: if (oti->chip_id) @@ -216,6 +225,11 @@ oti_in(uint16_t addr, void *p) temp = oti->enable_register; break; + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: + if (oti->chip_id == OTI_077) + return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); + return svga_in(addr, svga); + case 0x3CF: return svga->gdcreg[svga->gdcaddr & 0xf]; @@ -343,6 +357,14 @@ oti_recalctimings(svga_t *svga) if ((oti->regs[0x0d] & 0x0c) && !(oti->regs[0x0d] & 0x10)) svga->rowoffset <<= 1; svga->interlace = oti->regs[0x14] & 0x80; + + if (svga->bpp == 16) { + svga->render = svga_render_16bpp_highres; + svga->hdisp >>= 1; + } else if (svga->bpp == 15) { + svga->render = svga_render_15bpp_highres; + svga->hdisp >>= 1; + } } @@ -406,6 +428,9 @@ oti_init(const device_t *info) svga_init(info, &oti->svga, oti, oti->vram_size << 10, oti_recalctimings, oti_in, oti_out, NULL, NULL); + if (oti->chip_id == OTI_077) + oti->svga.ramdac = device_add(&sc11487_ramdac_device); /*Actually a 82c487, probably a clone.*/ + io_sethandler(0x03c0, 32, oti_in, NULL, NULL, oti_out, NULL, NULL, oti); diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index edb732032..5fd0aada0 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -54,6 +54,7 @@ typedef struct paradise_t uint32_t read_bank[4], write_bank[4]; int interlace; + int check; struct { uint8_t reg_block_ptr; @@ -105,6 +106,13 @@ void paradise_out(uint16_t addr, uint8_t val, void *p) } break; + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: + if (paradise->type == WD90C30) + sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); + else + svga_out(addr, val, svga); + return; + case 0x3cf: if (svga->gdcaddr >= 9 && svga->gdcaddr <= 0x0e) { if ((paradise->pr5 & 7) != 5) @@ -215,7 +223,12 @@ uint8_t paradise_in(uint16_t addr, void *p) return svga->seqregs[svga->seqaddr & 0x1f]; } break; - + + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: + if (paradise->type == WD90C30) + return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); + return svga_in(addr, svga); + case 0x3cf: if (svga->gdcaddr >= 9 && svga->gdcaddr <= 0x0e) { if ((paradise->pr5 & 7) != 5) @@ -232,8 +245,11 @@ uint8_t paradise_in(uint16_t addr, void *p) paradise->pr1 &= ~0x40; } else if (paradise->vram_mask == (1024 << 10) - 1) { paradise->pr1 |= 0xc0; - if (svga->bpp >= 8 && !svga->lowres) /*Horrible tweak, but needed to get around black corruption in 1M mode*/ + /*The following is a horrible tweak, but needed to get around black corruption in 1M mode*/ + if (svga->bpp >= 8 && (svga->gdcreg[0x0e] & 0x01) && paradise->check) paradise->pr1 &= ~0x40; + else if (!(svga->gdcreg[0x0e] & 0x01) && !(svga->crtc[0x14] & 0x40) && paradise->check) + paradise->check = 0; } return paradise->pr1; case 6: @@ -336,9 +352,25 @@ void paradise_recalctimings(svga_t *svga) svga->interlace = 1; } } - - if (svga->bpp >= 8 && !svga->lowres) - svga->render = svga_render_8bpp_highres; + + if (paradise->type < WD90C30) { + if (svga->bpp >= 8 && !svga->lowres) + svga->render = svga_render_8bpp_highres; + } else { + if (svga->bpp >= 8 && !svga->lowres) { + if (svga->bpp == 16) { + svga->render = svga_render_16bpp_highres; + svga->hdisp >>= 1; + } else if (svga->bpp == 15) { + svga->render = svga_render_15bpp_highres; + svga->hdisp >>= 1; + } else { + if ((svga->crtc[0x17] == 0xc2) && (svga->crtc[0x14] & 0x40)) + paradise->check = 1; + svga->render = svga_render_8bpp_highres; + } + } + } } static void paradise_write(uint32_t addr, uint8_t val, void *p) @@ -348,7 +380,7 @@ static void paradise_write(uint32_t addr, uint8_t val, void *p) addr &= svga->banked_mask; addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; - + svga_write_linear(addr, val, svga); } static void paradise_writew(uint32_t addr, uint16_t val, void *p) @@ -421,6 +453,7 @@ void *paradise_init(const device_t *info, uint32_t memsize) NULL); paradise->vram_mask = memsize - 1; svga->decode_mask = memsize - 1; + svga->ramdac = device_add(&sc11487_ramdac_device); /*Actually a Winbond W82c487-80, probably a clone.*/ break; } diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 84f49425a..7385c068a 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -238,7 +238,7 @@ typedef struct s3_t uint16_t multifunc[16]; uint8_t pix_trans[4]; int ssv_state; - + int cx, cy; int px, py; int sx, sy; @@ -347,6 +347,7 @@ typedef struct s3_t int translate; int enable_8514; + int color_16bit; volatile int busy, force_busy; uint8_t thread_run, serialport; @@ -453,7 +454,7 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; \ #define READ_PIXTRANS_WORD \ - if (s3->bpp == 0) { \ + if (s3->bpp == 0 && !s3->color_16bit) { \ temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; \ temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 1)) & s3->vram_mask] << 8); \ } else { \ @@ -461,7 +462,7 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); } #define READ_PIXTRANS_LONG \ - if (s3->bpp == 0) { \ + if (s3->bpp == 0 && !s3->color_16bit) { \ temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; \ temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 1)) & s3->vram_mask] << 8); \ temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 2)) & s3->vram_mask] << 16); \ @@ -520,7 +521,7 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) { svga_t *svga = &s3->svga; - if (s3_cpu_src(s3)) { + if (s3->accel.cmd & 0x100) { switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -530,8 +531,12 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) s3_accel_start(8, 1, val | (val << 16), 0, s3); } else s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); - } else - s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + } else { + if (s3->color_16bit) + s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + } break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -586,7 +591,7 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) static void s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) { - if (s3_cpu_src(s3)) { + if (s3->accel.cmd & 0x100) { switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -700,12 +705,14 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xff) | ((val & 0x0f) << 8); s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; break; - + + case 0xcae8: case 0x8948: case 0x8ae8: s3->accel.draw_fifo_slot++; s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val; s3->accel.point_1_updated = 1; break; + case 0xcae9: case 0x8949: case 0x8ae9: s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8); if (val & 0x20) @@ -805,7 +812,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; break; case 0x9d49: case 0x9ee9: - s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); + s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); s3->accel.ssv_state = 1; s3->accel.cx = s3->accel.cur_x; @@ -1015,7 +1022,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.setup_fifo_slot++; s3->accel.frgd_mix = val; break; - + case 0xbd48: case 0xbee8: s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff00) | val; break; @@ -1138,8 +1145,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - } else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } else { + if (s3->color_16bit) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } } } break; @@ -1156,8 +1167,9 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } else + } else { s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } break; case 0x200: /*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9) in the 86c928*/ @@ -1313,6 +1325,7 @@ s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) } else { s3->accel.b2e8_pix = 0; } + s3_accel_out_pixtrans_l(s3, val); } @@ -1467,8 +1480,26 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) if (addr & 0x8000) { s3_accel_out_fifo(s3, addr & 0xffff, val); } else { - s3_accel_out_fifo(s3, 0xe2e8 + (addr & 3), val); - } + if (s3->accel.cmd & 0x100) { + if ((s3->accel.cmd & 0x600) == 0x200) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } else + s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } else { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } + } + } } } @@ -2199,11 +2230,13 @@ s3_io_remove(s3_t *s3) io_removehandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xcae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xe2e8, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); io_removehandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xfee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); s3_io_remove_alt(s3); } @@ -2316,13 +2349,15 @@ s3_io_set(s3_t *s3) io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xcae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xe2e8, 0x0004, s3_accel_in, s3_accel_in_w, s3_accel_in_l, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { io_sethandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - } + } + io_sethandler(0xfee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); s3_io_set_alt(s3); } @@ -2360,13 +2395,10 @@ s3_out(uint16_t addr, uint8_t val, void *p) } if (svga->seqaddr == 4) /*Chain-4 - update banking*/ { - svga->chain4 = !!(val & 8); - if (svga->crtc[0x31] & 1) { - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - } + if (val & 0x08) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; } else if (svga->seqaddr == 9) { svga->seqregs[svga->seqaddr] = val & 0x80; s3_io_set(s3); @@ -2430,7 +2462,9 @@ s3_out(uint16_t addr, uint8_t val, void *p) return; if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5)) return; - if ((s3->chip == S3_TRIO64V2) && svga->crtcreg >= 0x80) + if ((s3->chip == S3_TRIO64V2) && (svga->crtcreg >= 0x80)) + return; + if ((s3->chip <= S3_86C924) && (svga->crtcreg >= 0x50)) return; old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; @@ -2486,12 +2520,10 @@ s3_out(uint16_t addr, uint8_t val, void *p) case 0x35: s3->bank = (s3->bank & 0x70) | (val & 0xf); - if (svga->crtc[0x31] & 1) { - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - } + if (svga->chain4) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; break; case 0x51: @@ -2502,23 +2534,19 @@ s3_out(uint16_t addr, uint8_t val, void *p) s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2); s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); } - if (svga->crtc[0x31] & 1) { - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - } + if (svga->chain4) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; break; case 0x6a: if (s3->chip >= S3_VISION964) { s3->bank = val; - if (svga->crtc[0x31] & 1) { - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - } + if (svga->chain4) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; } break; @@ -2771,6 +2799,7 @@ static void s3_recalctimings(svga_t *svga) } } } + svga->ma_latch |= (s3->ma_ext << 16); if (s3->chip >= S3_86C928) { svga->hdisp = svga->hdisp_old; @@ -2830,8 +2859,18 @@ static void s3_recalctimings(svga_t *svga) } } - if ((svga->crtc[0x43] & 0x08) && (s3->bpp == 0)) + if ((svga->crtc[0x43] & 0x08) && (s3->color_16bit == 0) && (s3->chip <= S3_86C805)) { + s3->color_16bit = 1; s3->width = 1024; + } else if (!(svga->crtc[0x43] & 0x08) && (s3->color_16bit == 1) && (s3->chip <= S3_86C805)) { + s3->color_16bit = 0; + if (s3->chip <= S3_86C924) { + if (s3->accel.advfunc_cntl & 4) + s3->width = 1024; + else + s3->width = 640; + } + } if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { svga->fb_only = 1; @@ -3002,35 +3041,17 @@ static void s3_recalctimings(svga_t *svga) } } else { svga->fb_only = 0; - if (!svga->scrblank && svga->attr_palette_enable) { - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) /*40 column*/ { - svga->render = svga_render_text_40; - } else { - svga->render = svga_render_text_80; - } - } else { - if ((svga->crtc[0x31] & 0x08) && ((svga->gdcreg[5] & 0x60) == 0x00)) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if ((svga->crtc[0x31] & 0x08) && ((svga->gdcreg[5] & 0x60) == 0x00)) { + if (svga->bpp == 8) { svga->render = svga_render_8bpp_highres; /*Enhanced 4bpp mode, just like the 8bpp mode per spec.*/ if (svga->hdisp <= 1024) s3->width = 1024; - } else { - switch (svga->gdcreg[5] & 0x60) { - case 0x00: - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_4bpp_lowres; - else - svga->render = svga_render_4bpp_highres; - break; - case 0x20: /*4 colours*/ - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_2bpp_lowres; - else - svga->render = svga_render_2bpp_highres; - break; - } } } + } else { + if (s3->chip <= S3_86C924) + s3->width = 1024; } } } @@ -3069,7 +3090,9 @@ static void s3_trio64v_recalctimings(svga_t *svga) if (!svga->rowoffset) svga->rowoffset = 256; svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { + svga->fb_only = 1; switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -3090,10 +3113,13 @@ static void s3_trio64v_recalctimings(svga_t *svga) svga->render = svga_render_32bpp_highres; break; } - } + } else + svga->fb_only = 0; } else /*Streams mode*/ { + svga->fb_only = 1; + if (s3->streams.buffer_ctrl & 1) svga->ma_latch = s3->streams.pri_fb1 >> 2; else @@ -3179,7 +3205,7 @@ s3_updatemapping(s3_t *s3) svga->banked_mask = 0x7fff; break; } - + if (s3->chip >= S3_86C928) { s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); @@ -3236,12 +3262,8 @@ s3_updatemapping(s3_t *s3) mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); } - if (s3->chip >= S3_TRIO64V) - svga->fb_only = 1; } else { mem_mapping_disable(&s3->linear_mapping); - if (s3->chip >= S3_TRIO64V) - svga->fb_only = 0; } /* Memory mapped I/O. */ @@ -3255,9 +3277,10 @@ s3_updatemapping(s3_t *s3) } else { mem_mapping_enable(&s3->mmio_mapping); } - } else + } else { mem_mapping_disable(&s3->mmio_mapping); - + } + /* New MMIO. */ if (svga->crtc[0x53] & 0x08) mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); @@ -3288,12 +3311,12 @@ s3_accel_out(uint16_t port, uint8_t val, void *p) s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; - if (!s3->enable_8514) - return; + if (port >= 0x8000) { + if (!s3->enable_8514) + return; - if (port >= 0x8000) s3_accel_out_fifo(s3, port, val); - else { + } else { switch (port) { case 0x4148: case 0x42e8: @@ -3313,8 +3336,12 @@ s3_accel_out(uint16_t port, uint8_t val, void *p) s3->width = (val & 4) ? 1600 : 800; svga->fullchange = changeframecount; svga_recalctimings(svga); + } else if (s3->chip <= S3_86C805) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); } - s3_updatemapping(s3); + if (s3->chip > S3_86C924) + s3_updatemapping(s3); break; } } @@ -3778,21 +3805,28 @@ s3_accel_in_w(uint16_t port, void *p) if (s3->accel.cmd & 0x1000) temp = (temp >> 8) | (temp << 8); s3_accel_start(8, 1, temp | (temp << 16), 0, s3); - } else + } else { s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); - } else - s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + } + } else { + if (s3->color_16bit) { + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + } + } break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { if (s3->accel.cmd & 0x1000) - temp = (temp >> 8) | (temp << 8); + temp = (temp >> 8) | (temp << 8); s3_accel_start(16, 1, temp | (temp << 16), 0, s3); } else s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); - } else + } else { s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + } break; } } @@ -3941,7 +3975,28 @@ s3_accel_read(uint32_t addr, void *p) if (addr & 0x8000) { temp = s3_accel_in(addr & 0xffff, p); } else if (s3_cpu_dest(s3)) { - temp = s3_accel_in(0xe2e8 + (addr & 3), p); + READ_PIXTRANS_BYTE_MM + + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); + break; + } } } @@ -4216,8 +4271,8 @@ polygon_setup(s3_t *s3) } } -#define READ(addr, dat) if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \ - else if (s3->bpp == 1 || (svga->crtc[0x43] & 0x08)) dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \ +#define READ(addr, dat) if (s3->bpp == 0 && !s3->color_16bit) dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \ + else if (s3->bpp == 1 || s3->color_16bit) dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \ else if (s3->bpp == 2) dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \ else dat = vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)]; @@ -4522,12 +4577,12 @@ polygon_setup(s3_t *s3) } -#define WRITE(addr, dat) if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) \ +#define WRITE(addr, dat) if (s3->bpp == 0 && !s3->color_16bit) \ { \ - svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \ + svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \ svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = changeframecount; \ } \ - else if (s3->bpp == 1 || (svga->crtc[0x43] & 0x08)) \ + else if (s3->bpp == 1 || s3->color_16bit) \ { \ vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)] = dat; \ svga->changedvram[(dword_remap_w(svga, addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ @@ -5038,33 +5093,33 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ cmd |= 8; } - // SRC-BASE/DST-BASE - if ((s3->accel.multifunc[0xd] >> 4) & 7) { - srcbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 4) & 3); - } else { - srcbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 2) & 3); - } - if ((s3->accel.multifunc[0xd] >> 0) & 7) { - dstbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 0) & 3); - } else { - dstbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 0) & 3); - } - if (s3->bpp == 1 || (svga->crtc[0x43] & 0x08)) { - srcbase >>= 1; - dstbase >>= 1; - } else if (s3->bpp == 3) { - srcbase >>= 2; - dstbase >>= 2; - } + // SRC-BASE/DST-BASE + if ((s3->accel.multifunc[0xd] >> 4) & 7) { + srcbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 4) & 3); + } else { + srcbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 2) & 3); + } + if ((s3->accel.multifunc[0xd] >> 0) & 7) { + dstbase = 0x100000 * ((s3->accel.multifunc[0xd] >> 0) & 3); + } else { + dstbase = 0x100000 * ((s3->accel.multifunc[0xe] >> 0) & 3); + } + if (s3->bpp == 1) { + srcbase >>= 1; + dstbase >>= 1; + } else if (s3->bpp == 3) { + srcbase >>= 2; + dstbase >>= 2; + } - if ((s3->accel.cmd & 0x100) && ((s3_cpu_src(s3) || (s3_cpu_dest(s3))) && !cpu_input)) { + if ((s3->accel.cmd & 0x100) && ((s3_cpu_src(s3) || (s3_cpu_dest(s3)))) && (!cpu_input || (s3_enable_fifo(s3) == 0))) { s3->force_busy = 1; } if (!cpu_input) s3->accel.dat_count = 0; - if (cpu_input && (count <= 4)) { + if (cpu_input && (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 2)))) { if ((s3->bpp == 3) && count == 2) { if (s3->accel.dat_count) { cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf; @@ -5075,19 +5130,19 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dat_count = 1; } } - if (s3->bpp == 1 || (svga->crtc[0x43] & 0x08)) + if (s3->bpp == 1 || s3->color_16bit) count >>= 1; if (s3->bpp == 3) count >>= 2; } - if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) + if (s3->bpp == 0 && !s3->color_16bit) rd_mask &= 0xff; - else if (s3->bpp == 1 || (svga->crtc[0x43] & 0x08)) + else if (s3->bpp == 1 || s3->color_16bit) rd_mask &= 0xffff; - if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) compare &= 0xff; - if (s3->bpp == 1 || (svga->crtc[0x43] & 0x08)) compare &= 0xffff; + if (s3->bpp == 0 && !s3->color_16bit) compare &= 0xff; + if (s3->bpp == 1 || s3->color_16bit) compare &= 0xffff; switch (s3->accel.cmd & 0x600) { @@ -5100,6 +5155,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ + switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ @@ -5140,7 +5196,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat <<= 1; mix_dat |= 1; - if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) cpu_dat >>= 8; + if (s3->bpp == 0) cpu_dat >>= 8; else cpu_dat >>= 16; if (!s3->accel.ssv_len) break; @@ -5173,14 +5229,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; s3->accel.sy = s3->accel.maj_axis_pcnt; - + s3_fifo_slots(s3); - + if (s3_cpu_src(s3)) { return; /*Wait for data from CPU*/ } } - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; @@ -5199,24 +5254,26 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 3: src_dat = 0; break; } - if (((compare_mode == 2 && src_dat != compare) || + if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2)) + compare_mode < 2) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - + MIX - if (s3->accel.cmd & 0x10) { - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - } + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } mix_dat <<= 1; mix_dat |= 1; - if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) cpu_dat >>= 8; - else cpu_dat >>= 16; + if (s3->bpp == 0 && !s3->color_16bit) + cpu_dat >>= 8; + else { + cpu_dat >>= 16; + } + if (!s3->accel.sy) { break; } @@ -5232,7 +5289,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0xc0: s3->accel.cy++; break; case 0xe0: s3->accel.cx++; s3->accel.cy++; break; } - s3->accel.sy--; } s3->accel.cur_x = s3->accel.cx; @@ -5263,17 +5319,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 3: src_dat = 0; break; } - if (((compare_mode == 2 && src_dat != compare) || + if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || - compare_mode < 2)) + compare_mode < 2) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX - if (s3->accel.cmd & 0x10) { - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - } + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } @@ -5287,13 +5341,16 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat <<= 1; mix_dat |= 1; } - if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) cpu_dat >>= 8; - else cpu_dat >>= 16; + if (s3->bpp == 0 && !s3->color_16bit) + cpu_dat >>= 8; + else { + cpu_dat >>= 16; + } if (!s3->accel.sy) { break; } - + if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) { s3->accel.err_term += s3->accel.destx_distp; /*Step minor axis*/ @@ -5324,7 +5381,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0xc0: s3->accel.cy++; break; case 0xe0: s3->accel.cy++; break; } - s3->accel.sy--; } s3->accel.cur_x = s3->accel.cx; @@ -5432,10 +5488,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat |= 1; } - if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) + if (s3->bpp == 0 && !s3->color_16bit) cpu_dat >>= 8; - else + else { cpu_dat >>= 16; + } if (s3->accel.cmd & 0x20) s3->accel.cx++; @@ -5462,7 +5519,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (cpu_input) { if (s3->accel.b2e8_pix) { s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; + s3->accel.cur_y = s3->accel.cy; } return; } @@ -5694,8 +5751,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat <<= 1; mix_dat |= 1; - if (s3->bpp == 0 && !(svga->crtc[0x43] & 0x08)) cpu_dat >>= 8; - else cpu_dat >>= 16; + if (s3->bpp == 0 && !s3->color_16bit) + cpu_dat >>= 8; + else { + cpu_dat >>= 16; + } if (s3->accel.cmd & 0x20) { @@ -6384,7 +6444,6 @@ static int vram_sizes[] = 3 /*8 MB*/ }; - static void s3_reset(void *priv) { s3_t *s3 = (s3_t *) priv; @@ -6403,14 +6462,14 @@ static void s3_reset(void *priv) svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); else svga->crtc[0x36] = 3 | (1 << 4); - + if (s3->chip >= S3_86C928) svga->crtc[0x36] |= (vram_sizes[s3->vram] << 5); else svga->crtc[0x36] |= ((s3->vram == 1) ? 0x00 : 0x20) | 0x80; - + svga->crtc[0x37] = 1 | (7 << 5); - + if (s3->chip >= S3_86C928) svga->crtc[0x37] |= 0x04; @@ -6440,11 +6499,11 @@ static void s3_reset(void *priv) case S3_PHOENIX_86C805: svga->crtc[0x5a] = 0x0a; break; - + case S3_METHEUS_86C928: svga->crtc[0x5a] = 0x0a; break; - + case S3_PARADISE_BAHAMAS64: case S3_PHOENIX_VISION864: case S3_MIROCRYSTAL20SD_864: @@ -6857,8 +6916,10 @@ static void *s3_init(const device_t *info) if (chip >= S3_86C928) svga->crtc[0x36] |= (vram_sizes[vram] << 5); - else - svga->crtc[0x36] |= ((vram == 1) ? 0x00 : 0x20) | 0x80; + else { + svga->crtc[0x36] |= ((vram == 1) ? 0x00 : 0x20) | 0x98; + svga->crtc[0x41] = (vram == 1) ? 0x10 : 0x00; + } svga->crtc[0x37] = 1 | (7 << 5); diff --git a/src/video/vid_sc1148x_ramdac.c b/src/video/vid_sc1148x_ramdac.c index 046624bf4..d23d00efa 100644 --- a/src/video/vid_sc1148x_ramdac.c +++ b/src/video/vid_sc1148x_ramdac.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * Emulation of Sierra SC11483 and SC11487 RAMDACs. + * Emulation of Sierra SC1148x RAMDACs and clones (e.g.: Winbond). * * Used by the S3 911 and 924 chips. * @@ -43,24 +43,45 @@ sc1148x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) { sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) p; uint8_t rs = (addr & 0x03); - rs |= ((!!rs2) << 2); + rs |= ((!!rs2) << 2); + int oldbpp = 0; switch (addr) { case 0x3c6: - if (ramdac->state == 4) { - ramdac->state = 0; - ramdac->ctrl = val; - if (ramdac->ctrl & 0xa0) { - if ((ramdac->ctrl & 0x40) && (ramdac->type == 1)) - svga->bpp = 16; - else - svga->bpp = 15; - } else - svga->bpp = 8; - svga_recalctimings(svga); - return; + switch (ramdac->state) { + case 4: + ramdac->state = 0; + if (val == 0xff) + break; + ramdac->ctrl = val; + ramdac->ctrl = (ramdac->ctrl & ~1) | ((((val >> 2) ^ val) & (val & 0x20)) >> 5); + oldbpp = svga->bpp; + switch (ramdac->type) { + case 0: /* Sierra Mark 2 (11483)*/ + case 2: /* Sierra Mark 2 (11484)*/ + case 3: /* Sierra Mark 1 (11486)*/ + if (val & 0xa0) { + svga->bpp = 15; + } else if (val == 0x00) + svga->bpp = 8; + break; + case 1: /* Sierra Mark 3 (11487)*/ + if (val & 0xa0) { + if (val & 0x40) + svga->bpp = 16; + else + svga->bpp = 15; + } else if (val == 0x00) + svga->bpp = 8; + break; + } + if (oldbpp != svga->bpp) + svga_recalctimings(svga); + return; + default: + svga_out(addr, val, svga); + break; } - ramdac->state = 0; break; case 0x3c7: case 0x3c8: @@ -82,18 +103,21 @@ sc1148x_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) switch (addr) { case 0x3c6: - if (ramdac->state == 4) { - ramdac->state = 0; - ret = ramdac->ctrl; - if (ramdac->type == 1) { - if (((ramdac->ctrl >> 5) == 1) || ((ramdac->ctrl >> 5) == 3)) - ret |= 1; - else - ret &= ~1; - } - return ret; + switch (ramdac->state) { + case 1: + case 2: case 3: + ret = 0x00; + ramdac->state++; + break; + case 4: + ret = ramdac->ctrl; + ret = (ret & ~0x18) | (svga->dac_mask & 0x18); + break; + default: + ret = svga_in(addr, svga); + ramdac->state++; + break; } - ramdac->state++; break; case 0x3c7: case 0x3c8: @@ -150,4 +174,12 @@ const device_t sc11484_nors2_ramdac_device = 0, 2, sc1148x_ramdac_init, sc1148x_ramdac_close, NULL, { NULL }, NULL, NULL +}; + +const device_t sc11486_ramdac_device = +{ + "Sierra SC11486 RAMDAC", + 0, 3, + sc1148x_ramdac_init, sc1148x_ramdac_close, + NULL, { NULL }, NULL, NULL }; \ No newline at end of file diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 2544fd361..b1d446829 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -953,7 +953,7 @@ svga_init(const device_t *info, svga_t *svga, void *p, int memsize, svga->translate_address = NULL; svga->ksc5601_english_font_type = 0; - if ((info->flags & DEVICE_PCI) || (info->flags & DEVICE_VLB)) { + if ((info->flags & DEVICE_PCI) || (info->flags & DEVICE_VLB) || (info->flags & DEVICE_MCA)) { mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 72ca625d4..9b457326e 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -58,12 +58,13 @@ video_cards[] = { { "ati28800k", &ati28800k_device }, { "ati18800v", &ati18800_vga88_device }, { "ati28800", &ati28800_device }, + { "compaq_ati28800", &compaq_ati28800_device }, +#if defined(DEV_BRANCH) && defined(USE_XL24) + { "ati28800w", &ati28800_wonderxl24_device }, +#endif { "ati18800", &ati18800_device }, #if defined(DEV_BRANCH) && defined(USE_VGAWONDER) { "ati18800w", &ati18800_wonder_device }, -#endif -#if defined(DEV_BRANCH) && defined(USE_XL24) - { "ati28800w", &ati28800_wonderxl24_device }, #endif { "cga", &cga_device }, { "superega", &sega_device }, @@ -74,7 +75,6 @@ video_cards[] = { { "cl_gd5428_isa", &gd5428_isa_device }, { "cl_gd5429_isa", &gd5429_isa_device }, { "cl_gd5434_isa", &gd5434_isa_device }, - { "compaq_ati28800", &compaq_ati28800_device }, { "compaq_cga", &compaq_cga_device }, { "compaq_cga_2", &compaq_cga_2_device }, { "compaq_ega", &cpqega_device }, From 666becd27afda4d280ea80bffe9e50f79deaa7b8 Mon Sep 17 00:00:00 2001 From: Ompronce <88358700+Ompronce@users.noreply.github.com> Date: Mon, 25 Oct 2021 16:18:24 -0400 Subject: [PATCH 2/4] Prevent the selection of certain sound cards on machines without ISA or ISA16 --- src/win/win_settings.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 4b538f31b..9d729342c 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -1380,13 +1380,15 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) settings_set_check(hdlg, IDC_CHECK_MPU401, temp_mpu401); settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); + settings_enable_window(hdlg, IDC_CHECK_CMS, (machines[temp_machine].flags & MACHINE_BUS_ISA)); settings_set_check(hdlg, IDC_CHECK_CMS, temp_GAMEBLASTER); - settings_enable_window(hdlg, IDC_CONFIGURE_CMS, temp_GAMEBLASTER); + settings_enable_window(hdlg, IDC_CONFIGURE_CMS, (machines[temp_machine].flags & MACHINE_BUS_ISA) && temp_GAMEBLASTER); + settings_enable_window(hdlg, IDC_CHECK_GUS, (machines[temp_machine].flags & MACHINE_BUS_ISA16)); settings_set_check(hdlg, IDC_CHECK_GUS, temp_GUS); - settings_enable_window(hdlg, IDC_CONFIGURE_GUS, temp_GUS); + settings_enable_window(hdlg, IDC_CONFIGURE_GUS, (machines[temp_machine].flags & MACHINE_BUS_ISA16) && temp_GUS); + settings_enable_window(hdlg, IDC_CHECK_SSI, (machines[temp_machine].flags & MACHINE_BUS_ISA)); settings_set_check(hdlg, IDC_CHECK_SSI, temp_SSI2001); - settings_enable_window(hdlg, IDC_CONFIGURE_SSI, temp_SSI2001); - settings_set_check(hdlg, IDC_CHECK_FLOAT, temp_float); + settings_enable_window(hdlg, IDC_CONFIGURE_SSI, (machines[temp_machine].flags & MACHINE_BUS_ISA) && temp_SSI2001); free(lptsTemp); From ce4814c2a0111807787bb119a72dcedafc3311c0 Mon Sep 17 00:00:00 2001 From: Ompronce <88358700+Ompronce@users.noreply.github.com> Date: Mon, 25 Oct 2021 16:19:31 -0400 Subject: [PATCH 3/4] Prevent the selection of certain sound cards on machines without ISA or ISA16 --- src/sound/snd_cms.c | 2 +- src/sound/snd_gus.c | 2 +- src/sound/snd_ssi2001.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index 631e00c6a..15a065776 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -207,7 +207,7 @@ static const device_config_t cms_config[] = const device_t cms_device = { "Creative Music System / Game Blaster", - 0, 0, + DEVICE_ISA, 0, cms_init, cms_close, NULL, { NULL }, NULL, NULL, cms_config diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index fe94ebf2f..003b93b58 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -1315,7 +1315,7 @@ static const device_config_t gus_config[] = { const device_t gus_device = { "Gravis UltraSound", - DEVICE_ISA, + DEVICE_ISA | DEVICE_AT, 0, gus_init, gus_close, NULL, { NULL }, diff --git a/src/sound/snd_ssi2001.c b/src/sound/snd_ssi2001.c index 55740fac9..400700131 100644 --- a/src/sound/snd_ssi2001.c +++ b/src/sound/snd_ssi2001.c @@ -118,7 +118,7 @@ static const device_config_t ssi2001_config[] = const device_t ssi2001_device = { "Innovation SSI-2001", - 0, 0, + DEVICE_ISA, 0, ssi2001_init, ssi2001_close, NULL, { NULL }, NULL, NULL, ssi2001_config From 6b9802f0d9a0a9e83138251b379bd201e19fe1b1 Mon Sep 17 00:00:00 2001 From: Ompronce <88358700+Ompronce@users.noreply.github.com> Date: Mon, 25 Oct 2021 16:26:26 -0400 Subject: [PATCH 4/4] Corrected accidental removal of "IDC_CHECK_FLOAT" --- src/win/win_settings.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 9d729342c..668487d00 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -1389,6 +1389,7 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) settings_enable_window(hdlg, IDC_CHECK_SSI, (machines[temp_machine].flags & MACHINE_BUS_ISA)); settings_set_check(hdlg, IDC_CHECK_SSI, temp_SSI2001); settings_enable_window(hdlg, IDC_CONFIGURE_SSI, (machines[temp_machine].flags & MACHINE_BUS_ISA) && temp_SSI2001); + settings_set_check(hdlg, IDC_CHECK_FLOAT, temp_float); free(lptsTemp);