diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index b0642c0de..e57675bb5 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -3322,29 +3322,28 @@ mach_recalctimings(svga_t *svga) if (!svga->scrblank && svga->attr_palette_enable) { mach_log("GDCREG5=%02x, ATTR10=%02x, ATI B0 bit 5=%02x, ON=%d.\n", svga->gdcreg[5] & 0x60, svga->attrregs[0x10] & 0x40, mach->regs[0xb0] & 0x20, dev->on); - if (ATI_MACH32) - svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); - else - svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel ^ 0x08, svga->clock_gen); - - switch ((mach->regs[0xb8] >> 6) & 3) { - case 0: - default: - break; - case 1: - svga->clock *= 2.0; - break; - case 2: - svga->clock *= 3.0; - break; - case 3: - svga->clock *= 4.0; - break; - } mach_log("VGA clock sel=%02x, divide reg=%02x, miscout bits2-3=%x, machregbe bit4=%02x, machregb9 bit1=%02x, charwidth=%d, htotal=%02x, hdisptime=%02x, seqregs1 bit 3=%02x.\n", clock_sel, (mach->regs[0xb8] >> 6) & 3, svga->miscout & 0x0c, mach->regs[0xbe] & 0x10, mach->regs[0xb9] & 0x02, svga->char_width, svga->htotal, svga->hdisp_time, svga->seqregs[1] & 8); if ((svga->gdcreg[6] & 0x01) || (svga->attrregs[0x10] & 0x01)) { if ((svga->gdcreg[5] & 0x40) || (svga->attrregs[0x10] & 0x40) || (mach->regs[0xb0] & 0x20)) { + if (ATI_MACH32) + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); + else + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel ^ 0x08, svga->clock_gen); + + switch ((mach->regs[0xb8] >> 6) & 3) { + case 1: + svga->clock *= 2.0; + break; + case 2: + svga->clock *= 3.0; + break; + case 3: + svga->clock *= 4.0; + break; + default: + break; + } svga->map8 = svga->pallook; mach_log("Lowres=%x, seqreg[1]bit3=%x.\n", svga->lowres, svga->seqregs[1] & 8); if (svga->lowres) @@ -3357,6 +3356,26 @@ mach_recalctimings(svga_t *svga) } } } + } else { + if (ATI_MACH32) + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); + else + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel ^ 0x08, svga->clock_gen); + + switch ((mach->regs[0xb8] >> 6) & 3) { + case 0: + default: + break; + case 1: + svga->clock *= 2.0; + break; + case 2: + svga->clock *= 3.0; + break; + case 3: + svga->clock *= 4.0; + break; + } } } } diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index c0d802fe4..e7538d6a7 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -93,6 +93,7 @@ typedef struct et4000w32p_t { int index, vlb, pci, interleaved, bank; + int onboard_vid; int vram_size; uint32_t linearbase; uint32_t vram_mask; @@ -513,7 +514,8 @@ et4000w32p_recalctimings(svga_t *svga) svga->memaddr_latch |= (svga->crtc[0x33] & 0x7) << 16; - svga->hblankstart = (((svga->crtc[0x3f] & 0x4) >> 2) << 8) + svga->crtc[2]; + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) + svga->hblankstart = (((svga->crtc[0x3f] & 0x4) >> 2) << 8) + svga->crtc[2]; if (svga->crtc[0x35] & 0x01) svga->vblankstart |= 0x400; @@ -527,7 +529,7 @@ et4000w32p_recalctimings(svga_t *svga) svga->split |= 0x400; if (svga->crtc[0x3F] & 0x80) svga->rowoffset |= 0x100; - if (svga->crtc[0x3F] & 0x01) + if ((svga->crtc[0x3F] & 0x01) && ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1))) svga->htotal |= 0x100; if (svga->attrregs[0x16] & 0x20) { svga->hdisp <<= 1; @@ -539,30 +541,38 @@ et4000w32p_recalctimings(svga_t *svga) svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clk_sel, svga->clock_gen); if (svga->getclock == ics2494_getclock) { - if (et4000->card_type == HERCULES_DYNAMITE_PRO_VLB) { - if (clk_sel < 2) - svga->clock *= 2.0; - } + if (clk_sel < 2) + svga->clock *= 2.0; } if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { - if (et4000->card_type != HERCULES_DYNAMITE_PRO_VLB) { + et4000w32_log("Graphics Mode clk_sel=%d, cr35 bit7=%02x, seq7=%02x, clksel=%d, htotal=%03x.\n", clk_sel, svga->crtc[0x35] & 0x80, svga->seqregs[7] & 0x41, clk_sel, svga->htotal); + if (svga->getclock != ics2494_getclock) { if (!(svga->crtc[0x35] & 0x80)) { if (clk_sel >= 2) { if (svga->seqregs[7] & 0x01) svga->clock *= 4.0; else if (svga->seqregs[7] & 0x40) svga->clock *= 2.0; + } else { + if (svga->getclock == sdac_getclock) { + if ((svga->gdcreg[5] & 0x60) >= 0x40) + svga->clock /= 2.0; + } } } } - if (svga->gdcreg[5] & 0x40) { + if ((svga->gdcreg[5] & 0x60) >= 0x40) { if (et4000->rev == ET4000W32) { switch (svga->bpp) { case 8: if ((svga->hdisp == 640) || (svga->hdisp == 800) || (svga->hdisp == 1024)) break; svga->hdisp -= 24; + if (svga->hdisp == 632) + svga->hdisp += 8; + else if (svga->hdisp == 1256) + svga->hdisp += 24; break; default: @@ -572,6 +582,7 @@ et4000w32p_recalctimings(svga_t *svga) switch (svga->bpp) { case 15: case 16: + et4000w32_log("ClkSel=%d, bpp=%d, seq7=%02x, cr35=%02x.\n", clk_sel, svga->bpp, svga->seqregs[7] & 0x41, svga->crtc[0x35] & 0x80); svga->hdisp >>= 1; svga->dots_per_clock >>= 1; if (et4000->rev <= ET4000W32P_REVC) { @@ -604,81 +615,56 @@ et4000w32p_recalctimings(svga_t *svga) default: break; } - //pclog("ClkSel=%d, crtc34 bits 0-1=%02x, crtc31 bits 6-7=%02x, seq7=%02x, interlace=%02x.\n", clk_sel, svga->crtc[0x34] & 0x03, svga->crtc[0x31] & 0xc0, svga->seqregs[7], svga->crtc[0x35] & 0x80); + et4000w32_log("ClkSel=%d, crtc34 bits 0-1=%02x, crtc31 bits 6-7=%02x, seq7=%02x, interlace=%02x.\n", clk_sel, svga->crtc[0x34] & 0x03, svga->crtc[0x31] & 0xc0, svga->seqregs[7], svga->crtc[0x35] & 0x80); } - }//else - // pclog("CLOCK translate=%02x, EGA VGA=%02x, clk=%d.\n", svga->crtc[0x34], svga->seqregs[7] & 0x80, clk_sel); + } else + et4000w32_log("CLOCK text clk=%d, htotal=%03x.\n", clk_sel, svga->htotal); - svga->render = svga_render_blank; 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 { - 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 */ - //pclog("BPP=%d.\n", svga->bpp); - 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; - break; - case 15: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_15bpp_lowres; - else - svga->render = svga_render_15bpp_highres; - break; - case 16: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_16bpp_lowres; - else - svga->render = svga_render_16bpp_highres; - break; - case 17: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_15bpp_mix_lowres; - else - svga->render = svga_render_15bpp_mix_highres; - break; - case 24: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_24bpp_lowres; - else - svga->render = svga_render_24bpp_highres; - break; - case 32: - if (svga->lowres || (svga->seqregs[1] & 8)) - svga->render = svga_render_32bpp_lowres; - else - svga->render = svga_render_32bpp_highres; - break; + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (svga->gdcreg[5] & 0x40) { + 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; + break; + case 15: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_15bpp_lowres; + else + svga->render = svga_render_15bpp_highres; + break; + case 16: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; + break; + case 17: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_15bpp_mix_lowres; + else + svga->render = svga_render_15bpp_mix_highres; + break; + case 24: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_24bpp_lowres; + else + svga->render = svga_render_24bpp_highres; + break; + case 32: + if (svga->lowres || (svga->seqregs[1] & 8)) + svga->render = svga_render_32bpp_lowres; + else + svga->render = svga_render_32bpp_highres; + break; - default: - break; - } - break; - - default: - break; + default: + break; + } } } } @@ -2680,11 +2666,6 @@ et4000w32p_pci_read(UNUSED(int func), int addr, void *priv) { const et4000w32p_t *et4000 = (et4000w32p_t *) priv; - if (func > 0) - return 0xff; - - addr &= 0xff; - switch (addr) { case 0x00: return 0x0c; /* Tseng Labs */ @@ -2722,13 +2703,13 @@ et4000w32p_pci_read(UNUSED(int func), int addr, void *priv) return (et4000->linearbase >> 24); case 0x30: - return et4000->pci_regs[0x30] & 0x01; /* BIOS ROM address */ + return et4000->onboard_vid ? 0x00 : (et4000->pci_regs[0x30] & 0x01); /* BIOS ROM address */ case 0x31: return 0x00; case 0x32: - return et4000->pci_regs[0x32]; + return et4000->onboard_vid ? 0x00 : et4000->pci_regs[0x32]; case 0x33: - return et4000->pci_regs[0x33]; + return et4000->onboard_vid ? 0x00 : et4000->pci_regs[0x33]; default: break; @@ -2743,11 +2724,6 @@ et4000w32p_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) et4000w32p_t *et4000 = (et4000w32p_t *) priv; svga_t *svga = &et4000->svga; - if (func > 0) - return; - - addr &= 0xff; - switch (addr) { case PCI_REG_COMMAND: et4000->pci_regs[PCI_REG_COMMAND] = (val & 0x23) | 0x80; @@ -2770,6 +2746,9 @@ et4000w32p_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) case 0x30: case 0x32: case 0x33: + if (et4000->onboard_vid) + return; + et4000->pci_regs[addr] = val; if (et4000->pci_regs[0x30] & 0x01) { uint32_t biosaddr = (et4000->pci_regs[0x32] << 16) | (et4000->pci_regs[0x33] << 24); @@ -2795,6 +2774,9 @@ et4000w32p_init(const device_t *info) et4000->pci = (info->flags & DEVICE_PCI) ? 0x80 : 0x00; et4000->vlb = (info->flags & DEVICE_VLB) ? 0x40 : 0x00; + et4000->card_type = info->local & 0xff; + et4000->onboard_vid = (info->local >> 8) & 0xff; + et4000->vram_size = device_get_config_int("memory"); if (info->flags & DEVICE_PCI) @@ -2813,7 +2795,6 @@ et4000w32p_init(const device_t *info) et4000->vram_mask = (et4000->vram_size << 20) - 1; et4000->svga.decode_mask = (et4000->vram_size << 20) - 1; - et4000->card_type = info->local & 0xff; et4000->ramdac_type = BUILT_IN; et4000->svga.crtc[0x31] = 0x40; et4000->svga.miscout = 0x01; @@ -2823,17 +2804,23 @@ et4000w32p_init(const device_t *info) case MACHSPEED_VGA_GUI_2400S: /* ET4000/W32 */ et4000->rev = ET4000W32; - et4000->ramdac_type = ET4K_SDAC; + if (et4000->onboard_vid) { + et4000->ramdac_type = ATT49X; + et4000->svga.ramdac = device_add(&att490_ramdac_device); + et4000->svga.clock_gen = device_add(&ics2494an_324_device); + et4000->svga.getclock = ics2494_getclock; + } else { + et4000->ramdac_type = ET4K_SDAC; - if (!(info->local & 0x100)) rom_init(&et4000->bios_rom, BIOS_ROM_PATH_W32_MACHSPEED_VGA_GUI_2400S, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device); - et4000->svga.clock_gen = et4000->svga.ramdac; - et4000->svga.getclock = sdac_getclock; - sdac_set_ref_clock(et4000->svga.ramdac, 14318184.0f); - svga_recalctimings(&et4000->svga); + et4000->svga.ramdac = device_add(&tseng_ics5301_ramdac_device); + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = sdac_getclock; + sdac_set_ref_clock(et4000->svga.ramdac, 14318184.0f); + svga_recalctimings(&et4000->svga); + } break; case AXIS_MICRODEVICE_ET4W32_5: @@ -2940,16 +2927,17 @@ et4000w32p_init(const device_t *info) /*The interleaved VRAM was introduced by the ET4000/W32i*/ et4000->interleaved = ((et4000->vram_size == 2) && (et4000->rev != ET4000W32)) ? 1 : 0; - if (info->flags & DEVICE_PCI) - mem_mapping_disable(&et4000->bios_rom.mapping); - + if (info->flags & DEVICE_PCI) { + if (!et4000->onboard_vid) + mem_mapping_disable(&et4000->bios_rom.mapping); + } mem_mapping_add(&et4000->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &et4000->svga); mem_mapping_add(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, et4000); et4000w32p_io_set(et4000); if (info->flags & DEVICE_PCI) - pci_add_card(PCI_ADD_NORMAL, et4000w32p_pci_read, et4000w32p_pci_write, et4000, &et4000->pci_slot); + pci_add_card(et4000->onboard_vid ? PCI_ADD_VIDEO : PCI_ADD_NORMAL, et4000w32p_pci_read, et4000w32p_pci_write, et4000, &et4000->pci_slot); /* Hardwired bits: 00000000 1xx0x0xx */ /* R/W bits: xx xxxx */ @@ -2967,7 +2955,7 @@ et4000w32p_init(const device_t *info) et4000->pci_regs[0x33] = 0xf0; et4000->svga.packed_chain4 = 1; - et4000->svga.adv_flags |= FLAG_PANNING_ATI; + et4000->svga.adv_flags |= FLAG_PANNING_ATI; return et4000; } @@ -3103,7 +3091,7 @@ const device_t et4000w32_onboard_device = { .init = et4000w32p_init, .close = et4000w32p_close, .reset = NULL, - .available = et4000w32_machspeed_vga_gui_2400s_available, + .available = NULL, .speed_changed = et4000w32p_speed_changed, .force_redraw = et4000w32p_force_redraw, .config = et4000w32p_config diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index e03ef71ba..1ffed47cd 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -251,6 +251,7 @@ typedef struct s3_t { uint32_t vram_mask; uint8_t data_available; + uint16_t port_82ec; int card_type; @@ -283,10 +284,13 @@ typedef struct s3_t { uint8_t frgd_mix; uint16_t multifunc_cntl; uint16_t multifunc[16]; + uint16_t height; uint8_t pix_trans[4]; uint8_t pix_trans_val[2048][2048]; int pix_trans_inc; int ssv_state; + int read_sel_reg; + int multifunc_phase; int16_t cx, cy; int16_t px, py; @@ -321,12 +325,6 @@ typedef struct s3_t { int start; int mix_dat_upper; int overflow; - - /*For non-threaded FIFO*/ - int setup_fifo_slot; - int draw_fifo_slot; - int setup_fifo, setup_fifo2; - int draw_fifo, draw_fifo2; } accel; struct { @@ -595,10 +593,11 @@ 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 + 1)) & s3->vram_mask] << 8); \ temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 2)) & s3->vram_mask] << 16); \ temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 3)) & s3->vram_mask] << 24); \ - } else { \ + } else if ((s3->bpp == 1) || s3->color_16bit) { \ temp = vram_w[dword_remap_w(svga, (s3->accel.dest + s3->accel.cx)) & (s3->vram_mask >> 1)]; \ temp |= (vram_w[dword_remap_w(svga, (s3->accel.dest + s3->accel.cx + 2)) & (s3->vram_mask >> 1)] << 16); \ - } + } else \ + temp = vram_l[dword_remap_w(svga, (s3->accel.dest + s3->accel.cx)) & (s3->vram_mask >> 2)]; static int s3_cpu_src(s3_t *s3) @@ -834,7 +833,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) { svga_t *svga = &s3->svga; - s3_log("OUTB FIFO=%04x, val=%02x.\n", port, val); switch (port) { case 0x8148: case 0x82e8: @@ -1358,7 +1356,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xb148: case 0xb2e8: s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x, CMD=%04x, C(%d,%d).\n", CS, cpu_state.pc, port, val, s3->accel.cmd, s3->accel.cur_x, s3->accel.cur_y); - if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_VISION964)) { + if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_86C928)) { s3->accel.b2e8_pix = 0; if (s3->bpp == 3) { if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { @@ -1400,7 +1398,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xb149: case 0xb2e9: s3_log("[%04X:%08X] OUT PORTB=%04x, val=%02x, CMD=%04x, C(%d,%d).\n", CS, cpu_state.pc, port, val, s3->accel.cmd, s3->accel.cur_x, s3->accel.cur_y); - if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_VISION964)) { + if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_86C928)) { s3->accel.b2e8_pix = 0; if (s3->bpp == 3) { if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { @@ -1554,14 +1552,28 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xbd48: case 0xbee8: + if ((s3->accel.multifunc_cntl >> 12) == 0x00) { + s3->accel.multifunc_phase = 1; + s3->accel.height = s3->accel.multifunc[0]; + } s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff00) | val; break; case 0xbd49: case 0xbee9: - s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8); - s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; - if ((s3->accel.multifunc_cntl >> 12) == 5) - s3_log("S3 multifunc_cntl = %d, val = %03x.\n", s3->accel.multifunc_cntl >> 12, s3->accel.multifunc_cntl & 0xfff); + s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8); + if ((val >> 4) == 0x0f) { + s3->accel.read_sel_reg = s3->accel.multifunc_cntl & 0xfff; + s3_log("[%04X:%08X] OUT PORTB=%04x, val=%x, multifunc idx=%x, multifunc_val=%03x.\n", CS, cpu_state.pc, port - 1, val >> 4, s3->accel.multifunc_cntl >> 12, s3->accel.multifunc_cntl & 0xfff); + } else { + s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; + if (s3->accel.multifunc_phase == 2) { + if (s3->accel.height != s3->accel.multifunc[0]) + s3->accel.multifunc[0] = s3->accel.height; + + s3->accel.multifunc_phase = 0; + } + s3_log("[%04X:%08X] OUT PORTB=%04x, val=%x, multifunc idx=%x, multifunc_val=%03x.\n", CS, cpu_state.pc, port - 1, val >> 4, s3->accel.multifunc_cntl >> 12, s3->accel.multifunc_cntl & 0xfff); + } break; case 0xd148: @@ -1708,7 +1720,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) if (s3->accel.cmd & 0x100) { switch (s3->accel.cmd & 0x600) { case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 0x02)) { if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) s3->accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); else @@ -2869,6 +2881,7 @@ static void s3_io_remove(s3_t *s3) { io_removehandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); + io_removehandler(0x82ec, 0x0002, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); io_removehandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2911,12 +2924,11 @@ s3_io_set_alt(s3_t *s3) if (!s3->translate) return; - if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 0x80)) { + if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 0x80)) return; - } io_sethandler(0x4148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x4548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { io_sethandler(0x8148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2971,6 +2983,7 @@ s3_io_set(s3_t *s3) return; } + io_sethandler(0x82ec, 0x0002, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -3030,6 +3043,8 @@ s3_out(uint16_t addr, uint8_t val, void *priv) if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; + s3_log("%04X:%08X: %03X: s3_out: val=%02x.\n", CS, cpu_state.pc, addr, val); + switch (addr) { case 0x3c2: if (svga->getclock == icd2061_getclock) { @@ -3164,6 +3179,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv) case 0x40: s3->enable_8514 = val & 0x01; + s3_log("Enable 8514/A functions=%02x.\n", val & 0x01); break; case 0x50: @@ -3338,6 +3354,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv) s3_io_remove_alt(s3); s3->translate = !!(val & 0x10); + s3_log("Translate=%02x.\n", s3->translate); s3_io_set_alt(s3); } break; @@ -3387,6 +3404,12 @@ s3_out(uint16_t addr, uint8_t val, void *priv) } break; + case 0x82ec: + s3->port_82ec = (s3->port_82ec & 0xff00) | val; + break; + case 0x82ed: + s3->port_82ec = (s3->port_82ec & 0xff) | (val << 8); + break; default: break; } @@ -3401,10 +3424,13 @@ s3_in(uint16_t addr, void *priv) int rs2; int rs3; uint8_t temp; + uint8_t temp2; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; + s3_log("%04X:%08X: %03X: s3_in.\n", CS, cpu_state.pc, addr); + switch (addr) { case 0x3c1: if (svga->attraddr > 0x14) @@ -3414,7 +3440,8 @@ s3_in(uint16_t addr, void *priv) case 0x3c2: if (s3->elsa_eeprom) { temp = nmc93cxx_eeprom_read(s3->eeprom) ? 0x10 : 0x00; - return (svga_in(addr, svga) & 0xef) | temp; + temp2 = (svga_in(addr, svga) & 0xef) | temp; + return temp2; } if (s3->chip <= S3_86C924) return svga_in(addr, svga) | 0x10; @@ -3484,6 +3511,7 @@ s3_in(uint16_t addr, void *priv) case 0x3d4: return svga->crtcreg; case 0x3d5: + s3_log("%04X:%08X: s3_in: crtc=%02x.\n", CS, cpu_state.pc, svga->crtcreg); switch (svga->crtcreg) { case 0x2d: return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; /*Extended chip ID*/ @@ -3553,6 +3581,11 @@ s3_in(uint16_t addr, void *priv) } return svga->crtc[svga->crtcreg]; + case 0x82ec: + return s3->port_82ec & 0xff; + case 0x82ed: + return s3->port_82ec >> 8; + default: break; } @@ -3865,9 +3898,9 @@ s3_recalctimings(svga_t *svga) if (enhanced_8bpp_modes) { s3_log("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, " - "attr=%02x, hdisp=%d, dotsperclock=%x, clksel=%x, clockmultiplier=%d, multiplexingrate=%d, xadd=%d, overscanx=%d.\n", svga->bpp, s3->width, svga->crtc[0x50], + "attr=%02x, hdisp=%d, dotsperclock=%x, clksel=%x, clockmultiplier=%d, multiplexingrate=%d, mapenable=%x.\n", svga->bpp, s3->width, svga->crtc[0x50], svga->crtc[0x31] & 0x02, s3->color_16bit, s3->accel.advfunc_cntl & 0x04, - svga->attrregs[0x10] & 0x40, svga->hdisp, svga->dots_per_clock, clk_sel, svga->clock_multiplier, svga->multiplexing_rate, svga->x_add, svga->monitor->mon_overscan_x); + svga->attrregs[0x10] & 0x40, svga->hdisp, svga->dots_per_clock, clk_sel, svga->clock_multiplier, svga->multiplexing_rate, svga->mapping.enable); switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -3883,14 +3916,21 @@ s3_recalctimings(svga_t *svga) if (svga->clock_multiplier == 1) { svga->hdisp <<= 2; svga->dots_per_clock <<= 2; + svga->clock *= 2.0; + } else { + if (clk_sel > 2) { + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; + svga->clock *= 4.0; + } } } else { if (!svga->clock_multiplier) { svga->hdisp <<= 1; svga->dots_per_clock <<= 1; + svga->clock *= 2.0; } } - svga->clock *= 2.0; } else { if (svga->multiplexing_rate == 0) { svga->hdisp <<= 1; @@ -4899,7 +4939,7 @@ s3_updatemapping(s3_t *s3) /*Banked framebuffer*/ if (svga->crtc[0x31] & 0x08) /*Enhanced mode mappings*/ { - s3_log("Enhanced Mode Mapping.\n"); + s3_log("Enhanced Mode Mapping, gdc6=%02x.\n", svga->gdcreg[6] & 0xc); /* Enhanced mode forces 64kb at 0xa0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; @@ -4937,6 +4977,7 @@ s3_updatemapping(s3_t *s3) if (s3->chip >= S3_86C928) { s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); + s3_log("Initial linear base=%08x, crtc58=%02x, crtc53=%02x.\n", s3->linear_base, svga->crtc[0x58], svga->crtc[0x53]); if (s3->chip <= S3_86C805I) { if (s3->vlb) s3->linear_base &= 0x03ffffff; @@ -4977,11 +5018,13 @@ s3_updatemapping(s3_t *s3) break; } s3->linear_base &= ~(s3->linear_size - 1); + s3_log("First LinearBase update=%x, size=%x, mmio1=%02x, mmio2=%02x, mapenable=%x.\n", s3->linear_base, s3->linear_size, svga->crtc[0x53] & 0x10, s3->accel.advfunc_cntl & 0x20, svga->mapping.enable); if ((s3->linear_base == 0xa0000) || (s3->linear_size == 0x10000)) { mem_mapping_disable(&s3->linear_mapping); if (!(svga->crtc[0x53] & 0x10)) { mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; + s3_log("Actually enable banked mapping=%d.\n", svga->mapping.enable); } } else { if (s3->chip >= S3_TRIO64V) @@ -4989,7 +5032,7 @@ s3_updatemapping(s3_t *s3) else if ((s3->chip == S3_VISION968) || (s3->chip == S3_VISION868)) s3->linear_base &= 0xfe000000; - s3_log("LinearBase update=%x, size=%x.\n", s3->linear_base, s3->linear_size); + s3_log("Update LinearBase update=%x, size=%x.\n", s3->linear_base, s3->linear_size); if (s3->linear_base) mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); else @@ -5055,6 +5098,8 @@ s3_accel_out(uint16_t port, uint8_t val, void *priv) s3_t *s3 = (s3_t *) priv; svga_t *svga = &s3->svga; + s3_log("%04X:%08X: OUTB FIFO=%04x, val=%02x.\n", CS, cpu_state.pc, port, val); + if (port >= 0x8000) { if (!s3->enable_8514) return; @@ -5076,9 +5121,11 @@ s3_accel_out(uint16_t port, uint8_t val, void *priv) s3->accel.subsys_cntl = (s3->accel.subsys_cntl & 0xff) | (val << 8); s3_update_irqs(s3); break; - case 0x4548: case 0x46e8: - s3->accel.setup_md = val; + s3->accel.setup_md = (s3->accel.setup_md & 0xff00) | val; + break; + case 0x46e9: + s3->accel.setup_md = (s3->accel.setup_md & 0xff) | (val << 8); break; case 0x4948: case 0x4ae8: @@ -5104,6 +5151,8 @@ s3_accel_out_w(uint16_t port, uint16_t val, void *priv) { s3_t *s3 = (s3_t *) priv; + s3_log("%04X:%08X: OUTW FIFO=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); + if (!s3->enable_8514) return; @@ -5118,6 +5167,8 @@ s3_accel_out_l(uint16_t port, uint32_t val, void *priv) { s3_t *s3 = (s3_t *) priv; + s3_log("%04X:%08X: OUTL FIFO=%04x, val=%08x.\n", CS, cpu_state.pc, port, val); + if (!s3->enable_8514) return; @@ -5135,6 +5186,8 @@ s3_accel_in(uint16_t port, void *priv) int temp; uint8_t temp2 = 0x00; + s3_log("%04X:%08X: INB=%04x.\n", CS, cpu_state.pc, port); + if (!s3->enable_8514) return 0xff; @@ -5146,6 +5199,13 @@ s3_accel_in(uint16_t port, void *priv) case 0x42e9: return s3->accel.subsys_cntl >> 8; + case 0x4948: + case 0x4ae8: + return s3->accel.advfunc_cntl; + case 0x4949: + case 0x4ae9: + return 0x00; + case 0x8148: case 0x82e8: if (s3_enable_fifo(s3)) @@ -5686,9 +5746,20 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.color_cmp >> 16; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.color_cmp >> 16; + else + temp2 = s3->accel.color_cmp & 0xff; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.color_cmp >> 16; + else + temp2 = s3->accel.color_cmp & 0xff; + } + } else temp2 = s3->accel.color_cmp & 0xff; return temp2; @@ -5699,13 +5770,34 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.color_cmp >> 24; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.color_cmp >> 24; + else + temp2 = s3->accel.color_cmp >> 8; + + s3->accel.multifunc[0xe] ^= 0x10; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.color_cmp >> 24; + else + temp2 = s3->accel.color_cmp >> 8; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { temp2 = s3->accel.color_cmp >> 8; - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if (s3->chip < S3_VISION964) + s3->accel.multifunc[0xe] ^= 0x10; + else { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } return temp2; } break; @@ -5756,7 +5848,11 @@ s3_accel_in(uint16_t port, void *priv) if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); if (s3->chip >= S3_VISION964) { - temp = s3->accel.multifunc[0xf] & 0xf; + temp = s3->accel.read_sel_reg & 0xf; + s3_log("964 and up: ReadSelReg=%x.\n", temp); + if (s3->accel.multifunc_phase == 1) + s3->accel.multifunc_phase = 2; + switch (temp) { case 0x0: return s3->accel.multifunc[0x0] & 0xff; @@ -5785,7 +5881,7 @@ s3_accel_in(uint16_t port, void *priv) break; } } else { - temp = s3->accel.multifunc[0xf] & 7; + temp = s3->accel.read_sel_reg & 7; switch (temp) { case 0x0: return s3->accel.multifunc[0x0] & 0xff; @@ -5817,8 +5913,8 @@ s3_accel_in(uint16_t port, void *priv) if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); if (s3->chip >= S3_VISION964) { - temp = s3->accel.multifunc[0xf] & 0xf; - s3->accel.multifunc[0xf] = (s3->accel.multifunc[0xf] + 1) & 0xf; + temp = s3->accel.read_sel_reg & 0xf; + s3->accel.read_sel_reg = (s3->accel.read_sel_reg + 1) & 0xf; switch (temp) { case 0x0: return s3->accel.multifunc[0x0] >> 8; @@ -5835,11 +5931,11 @@ s3_accel_in(uint16_t port, void *priv) case 0x6: return s3->accel.multifunc[0xe] >> 8; case 0x7: - return s3->accel.cmd >> 8; + return (s3->accel.cmd >> 8) & ~0xf0; case 0x8: - return (s3->accel.subsys_cntl >> 8) & ~0xe000; + return (s3->accel.subsys_cntl >> 8) & ~0xe0; case 0x9: - return (s3->accel.setup_md >> 8) & ~0xf000; + return s3->accel.setup_md >> 8; case 0xa: return s3->accel.multifunc[0xd] >> 8; @@ -5847,8 +5943,8 @@ s3_accel_in(uint16_t port, void *priv) break; } } else { - temp = s3->accel.multifunc[0xf] & 7; - s3->accel.multifunc[0xf] = (s3->accel.multifunc[0xf] + 1) & 7; + temp = s3->accel.read_sel_reg & 7; + s3->accel.read_sel_reg = (s3->accel.read_sel_reg + 1) & 7; switch (temp) { case 0x0: return s3->accel.multifunc[0x0] >> 8; @@ -5865,7 +5961,7 @@ s3_accel_in(uint16_t port, void *priv) case 0x6: return s3->accel.multifunc[0xe] >> 8; case 0x7: - return s3->accel.cmd >> 8; + return (s3->accel.cmd >> 8) & ~0xf0; default: break; @@ -6207,6 +6303,7 @@ s3_accel_in_w(uint16_t port, void *priv) if (s3_cpu_dest(s3)) { READ_PIXTRANS_WORD + s3_log("PIXTRANS WORD READ=%04x.\n", s3->accel.cmd); switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 0x02)) { @@ -6286,6 +6383,7 @@ s3_accel_in_l(UNUSED(uint16_t port), void *priv) svga_t *svga = &s3->svga; uint32_t temp = 0x00000000; const uint16_t *vram_w = (uint16_t *) svga->vram; + const uint32_t *vram_l = (uint32_t *) svga->vram; if (!s3->enable_8514) return 0xffffffff; @@ -6293,6 +6391,7 @@ s3_accel_in_l(UNUSED(uint16_t port), void *priv) if (s3_cpu_dest(s3)) { READ_PIXTRANS_LONG + s3_log("PIXTRANS LONG READ=%04x.\n", s3->accel.cmd); switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -6707,6 +6806,7 @@ s3_accel_read_l(uint32_t addr, void *priv) svga_t *svga = &s3->svga; uint32_t temp = 0x00000000; const uint16_t *vram_w = (uint16_t *) svga->vram; + const uint32_t *vram_l = (uint32_t *) svga->vram; if (!s3->enable_8514) return 0xffffffff; @@ -8291,7 +8391,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi /*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)*/ - s3_log("CMD=%d, full=%04x, cnt=%d, s3bpp=%x, clr=%d, clb=%d, sourcedisplay=%02x, mmio=%02x, srcbase=%08x, dstbase=%08x, cpu=%08x, mix=%08x, count=%d, rd_mask=%08x, wrt_mask=%08x, width=%d, s=%d,%d, c=%d,%d, d=%d,%d, 16bitcolor=%x, frgdcolor=%08x, bkgdcolor=%08x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, curx=%d, cury=%d, cll=%d, b2e8pix=%x.\n", cmd, s3->accel.cmd, count, s3->bpp, clip_r, clip_b, s3->accel.multifunc[0x0a] & 0xc4, svga->crtc[0x53] & 0x18, srcbase, dstbase, cpu_dat & 0xffffffff, mix_dat & 0xffffffff, count, rd_mask, wrt_mask, s3->width, s3->accel.sx, s3->accel.sy, s3->accel.cx, s3->accel.cy, s3->accel.destx_distp, s3->accel.desty_axstp, s3->color_16bit, frgd_color, bkgd_color, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.cur_x, s3->accel.cur_y, clip_l, s3->accel.b2e8_pix); + s3_log("CMD=%d, full=%04x, cnt=%d, s3bpp=%x, clr=%d, clb=%d, sourcedisplay=%02x, mmio=%02x, srcbase=%08x, dstbase=%08x, cpu=%08x, mix=%08x, count=%d, rd_mask=%08x, wrt_mask=%08x, width=%d, s=%d,%d, c=%d,%d, d=%d,%d, 16bitcolor=%x, frgdcolor=%08x, bkgdcolor=%08x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, curx=%d, cury=%d, cll=%d, b2e8pix=%x, multifuncE=%03x.\n", cmd, s3->accel.cmd, count, s3->bpp, clip_r, clip_b, s3->accel.multifunc[0x0a] & 0xc4, svga->crtc[0x53] & 0x18, srcbase, dstbase, cpu_dat & 0xffffffff, mix_dat & 0xffffffff, count, rd_mask, wrt_mask, s3->width, s3->accel.sx, s3->accel.sy, s3->accel.cx, s3->accel.cy, s3->accel.destx_distp, s3->accel.desty_axstp, s3->color_16bit, frgd_color, bkgd_color, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.cur_x, s3->accel.cur_y, clip_l, s3->accel.b2e8_pix, s3->accel.multifunc[0xe]); switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ @@ -9225,7 +9325,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } } - break; + return; } while (count-- && (s3->accel.sy >= 0)) {