Merge pull request #6463 from 86Box/TC1995

Refresh rate and acceleration fixes and cleanups for displays.
This commit is contained in:
Miran Grča
2025-11-11 00:24:49 +01:00
committed by GitHub
3 changed files with 279 additions and 172 deletions

View File

@@ -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;
}
}
}
}

View File

@@ -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

View File

@@ -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)) {