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 },