This commit is contained in:
OBattler
2025-08-14 00:26:09 +02:00
6 changed files with 82 additions and 23 deletions

View File

@@ -253,6 +253,7 @@ typedef struct ibm8514_t {
int vdisp; int vdisp;
int vdisp2; int vdisp2;
int disp_cntl; int disp_cntl;
int disp_cntl_2;
int interlace; int interlace;
uint16_t subsys_cntl; uint16_t subsys_cntl;
uint8_t subsys_stat; uint8_t subsys_stat;

View File

@@ -109,6 +109,7 @@ typedef struct mach_t {
uint16_t src_y; uint16_t src_y;
int16_t bres_count; int16_t bres_count;
uint16_t clock_sel; uint16_t clock_sel;
uint16_t clock_sel_mode;
uint16_t crt_pitch; uint16_t crt_pitch;
uint16_t ge_pitch; uint16_t ge_pitch;
uint16_t src_pitch; uint16_t src_pitch;

View File

@@ -140,6 +140,7 @@ typedef struct svga_t {
int vblankend; int vblankend;
int render_line_offset; int render_line_offset;
int start_retrace_latch; int start_retrace_latch;
int vga_mode;
/*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 :
0MB-1MB - VRAM 0MB-1MB - VRAM

View File

@@ -2725,8 +2725,10 @@ mach_set_resolution(mach_t *mach, svga_t *svga)
if (dev->v_syncstart == 1) if (dev->v_syncstart == 1)
dev->v_syncstart = 0x0601; dev->v_syncstart = 0x0601;
mach->accel.clock_sel_mode = 0;
mach_log("ATI Mode: set=%02x, dispcntl=%02x, h_total=%d, hdisp=%d, vdisp=%d, v_total=%04x, v_syncstart=%04x, hsync_start=%d, hsync_width=%d, clocksel=%02x, advancedcntl=%02x.\n", mach->shadow_set & 0x03, dev->disp_cntl, dev->h_total, dev->hdisp, dev->vdisp, dev->v_total, dev->v_syncstart, dev->hsync_start, dev->hsync_width, mach->accel.clock_sel & 0xff, dev->accel.advfunc_cntl & 0x05); mach_log("ATI Mode: set=%02x, dispcntl=%02x, h_total=%d, hdisp=%d, vdisp=%d, v_total=%04x, v_syncstart=%04x, hsync_start=%d, hsync_width=%d, clocksel=%02x, advancedcntl=%02x.\n", mach->shadow_set & 0x03, dev->disp_cntl, dev->h_total, dev->hdisp, dev->vdisp, dev->v_total, dev->v_syncstart, dev->hsync_start, dev->hsync_width, mach->accel.clock_sel & 0xff, dev->accel.advfunc_cntl & 0x05);
if ((dev->disp_cntl >> 5) == 1) { /*Enable the 8514/A subsystem and set modes according to the shadow sets if needed.*/ if ((dev->disp_cntl_2 >> 5) == 1) { /*Enable the 8514/A subsystem and set modes according to the shadow sets if needed.*/
switch (mach->shadow_set & 0x03) { switch (mach->shadow_set & 0x03) {
case 0x01: case 0x01:
if (!(dev->accel.advfunc_cntl & 0x04)) { if (!(dev->accel.advfunc_cntl & 0x04)) {
@@ -2735,6 +2737,7 @@ mach_set_resolution(mach_t *mach, svga_t *svga)
dev->vdisp = 480; dev->vdisp = 480;
dev->v_total = 0x0419; dev->v_total = 0x0419;
dev->v_syncstart = 0x03d7; dev->v_syncstart = 0x03d7;
mach->accel.clock_sel_mode = 0x50;
} }
break; break;
case 0x02: case 0x02:
@@ -2744,6 +2747,7 @@ mach_set_resolution(mach_t *mach, svga_t *svga)
dev->vdisp = 768; dev->vdisp = 768;
dev->v_total = 0x0669; dev->v_total = 0x0669;
dev->v_syncstart = 0x0601; dev->v_syncstart = 0x0601;
mach->accel.clock_sel_mode = 0x1c;
} }
break; break;
@@ -2751,7 +2755,7 @@ mach_set_resolution(mach_t *mach, svga_t *svga)
break; break;
} }
svga_recalctimings(svga); svga_recalctimings(svga);
} else if ((dev->disp_cntl >> 5) == 2) { /*Reset 8514/A to defaults if needed.*/ } else if ((dev->disp_cntl_2 >> 5) == 2) { /*Reset 8514/A to defaults if needed.*/
if (dev->accel.advfunc_cntl & 0x04) { if (dev->accel.advfunc_cntl & 0x04) {
if (dev->hdisp == 640) { if (dev->hdisp == 640) {
dev->h_total = 0x9e; dev->h_total = 0x9e;
@@ -2759,6 +2763,7 @@ mach_set_resolution(mach_t *mach, svga_t *svga)
dev->vdisp = 768; dev->vdisp = 768;
dev->v_total = 0x0669; dev->v_total = 0x0669;
dev->v_syncstart = 0x0601; dev->v_syncstart = 0x0601;
mach->accel.clock_sel_mode = 0x1c;
svga_recalctimings(svga); svga_recalctimings(svga);
} }
} else { } else {
@@ -2768,6 +2773,7 @@ mach_set_resolution(mach_t *mach, svga_t *svga)
dev->vdisp = 480; dev->vdisp = 480;
dev->v_total = 0x0419; dev->v_total = 0x0419;
dev->v_syncstart = 0x03d7; dev->v_syncstart = 0x03d7;
mach->accel.clock_sel_mode = 0x50;
svga_recalctimings(svga); svga_recalctimings(svga);
} }
} }
@@ -2780,6 +2786,7 @@ ati8514_recalctimings(svga_t *svga)
{ {
mach_t *mach = (mach_t *) svga->ext8514; mach_t *mach = (mach_t *) svga->ext8514;
ibm8514_t *dev = (ibm8514_t *) svga->dev8514; ibm8514_t *dev = (ibm8514_t *) svga->dev8514;
int _8514_modes = 0;
mach_log("ON=%d, vgahdisp=%d.\n", dev->on, svga->hdisp); mach_log("ON=%d, vgahdisp=%d.\n", dev->on, svga->hdisp);
if (dev->on) { if (dev->on) {
@@ -2790,6 +2797,14 @@ ati8514_recalctimings(svga_t *svga)
dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)) << 2; dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)) << 2;
mach->accel.crt_offset = (mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2; mach->accel.crt_offset = (mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2;
if (mach->accel.clock_sel_mode == 0x1c) {
dev->interlace = 1;
_8514_modes = 1;
} else if (mach->accel.clock_sel_mode == 0x50) {
dev->interlace = 0;
_8514_modes = 2;
}
dev->accel.ge_offset -= mach->accel.crt_offset; dev->accel.ge_offset -= mach->accel.crt_offset;
mach_log("HDISP=%d, VDISP=%d, shadowset=%x, 8514/A mode=%x, clocksel=%02x.\n", mach_log("HDISP=%d, VDISP=%d, shadowset=%x, 8514/A mode=%x, clocksel=%02x.\n",
@@ -2811,13 +2826,22 @@ ati8514_recalctimings(svga_t *svga)
else if (dev->h_disp == 640) else if (dev->h_disp == 640)
dev->dispend = 480; dev->dispend = 480;
if (dev->accel.advfunc_cntl & 0x04) dev->h_disp_time = dev->hdisp >> 3;
svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0;
else
svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0;
if (dev->interlace) if (_8514_modes) {
svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock8514((mach->accel.clock_sel_mode >> 2) & 0x0f, svga->clock_gen8514) / 2;
if (mach->accel.clock_sel_mode & 0x40)
svga->clock_8514 *= 2;
} else {
svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock8514((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen8514) / 2;
if (mach->accel.clock_sel & 0x40)
svga->clock_8514 *= 2;
}
if (dev->interlace) {
dev->dispend >>= 1; dev->dispend >>= 1;
svga->clock_8514 /= 2;
}
mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d.\n", mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d.\n",
dev->accel.advfunc_cntl & 0x04, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, dev->accel.advfunc_cntl & 0x04, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset,
@@ -2841,6 +2865,7 @@ mach_recalctimings(svga_t *svga)
mach_t *mach = (mach_t *) svga->priv; mach_t *mach = (mach_t *) svga->priv;
ibm8514_t *dev = (ibm8514_t *) svga->dev8514; ibm8514_t *dev = (ibm8514_t *) svga->dev8514;
int clock_sel; int clock_sel;
int _8514_modes = 0;
if (mach->regs[0xad] & 0x08) if (mach->regs[0xad] & 0x08)
svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[2]; svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[2];
@@ -2886,6 +2911,10 @@ mach_recalctimings(svga_t *svga)
svga->ati_4color = 0; svga->ati_4color = 0;
} }
svga->interlace = !!(mach->regs[0xbe] & 0x02);
if (svga->interlace)
svga->dispend >>= 1;
mach_log("ON=%d, override=%d, gelo=%04x, gehi=%04x, crtlo=%04x, crthi=%04x, vgahdisp=%d.\n", dev->on, svga->override, mach->accel.ge_offset_lo, mach->accel.ge_offset_hi, mach->accel.crt_offset_lo, mach->accel.crt_offset_hi, svga->hdisp); mach_log("ON=%d, override=%d, gelo=%04x, gehi=%04x, crtlo=%04x, crthi=%04x, vgahdisp=%d.\n", dev->on, svga->override, mach->accel.ge_offset_lo, mach->accel.ge_offset_hi, mach->accel.crt_offset_lo, mach->accel.crt_offset_hi, svga->hdisp);
if (dev->on) { if (dev->on) {
dev->memaddr_latch = 0; /*(mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2;*/ dev->memaddr_latch = 0; /*(mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2;*/
@@ -2896,6 +2925,14 @@ mach_recalctimings(svga_t *svga)
dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16));
mach->accel.crt_offset = (mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)); mach->accel.crt_offset = (mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16));
if (mach->accel.clock_sel_mode == 0x1c) {
dev->interlace = 1;
_8514_modes = 1;
} else if (mach->accel.clock_sel_mode == 0x50) {
dev->interlace = 0;
_8514_modes = 2;
}
if (dev->bpp) { if (dev->bpp) {
dev->accel.ge_offset <<= 1; dev->accel.ge_offset <<= 1;
mach->accel.crt_offset <<= 1; mach->accel.crt_offset <<= 1;
@@ -2928,14 +2965,22 @@ mach_recalctimings(svga_t *svga)
dev->h_disp_time = dev->hdisp >> 3; dev->h_disp_time = dev->hdisp >> 3;
svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen) / 2; if (_8514_modes) {
if (mach->accel.clock_sel & 0x40) svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel_mode >> 2) & 0x0f, svga->clock_gen) / 2;
svga->clock_8514 *= 2; if (mach->accel.clock_sel_mode & 0x40)
svga->clock_8514 *= 2;
} else {
svga->clock_8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen) / 2;
if (mach->accel.clock_sel & 0x40)
svga->clock_8514 *= 2;
}
mach_log("8514/A clock sel=%x, divide reg ibm=%02x, divide reg vga=%02x.\n", clock_sel, mach->accel.clock_sel & 0x40, mach->regs[0xb8] & 0xc0); mach_log("8514/A clock sel=%x, divide reg ibm=%02x, divide reg vga=%02x, vgainterlace=%x, interlace=%x.\n", clock_sel, mach->accel.clock_sel & 0x40, mach->regs[0xb8] & 0xc0, svga->interlace, dev->interlace);
if (dev->interlace) if (dev->interlace) {
dev->dispend >>= 1; dev->dispend >>= 1;
svga->clock_8514 /= 2;
}
if (ATI_MACH32) { if (ATI_MACH32) {
switch ((mach->shadow_set >> 8) & 0x03) { switch ((mach->shadow_set >> 8) & 0x03) {
@@ -3064,6 +3109,9 @@ mach_recalctimings(svga_t *svga)
svga->gdcreg[5] & 0x60, svga->attrregs[0x10] & 0x40, mach->regs[0xb0] & 0x20, dev->on); svga->gdcreg[5] & 0x60, svga->attrregs[0x10] & 0x40, mach->regs[0xb0] & 0x20, dev->on);
svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen);
mach_log("VGA clock sel=%x, divide reg=%02x.\n", clock_sel, mach->regs[0xb8] & 0xc0); mach_log("VGA clock sel=%x, divide reg=%02x.\n", clock_sel, mach->regs[0xb8] & 0xc0);
if (svga->interlace)
svga->clock /= 2;
if (ATI_MACH32) { if (ATI_MACH32) {
if (mach->regs[0xb8] & 0x40) if (mach->regs[0xb8] & 0x40)
svga->clock *= 2; svga->clock *= 2;
@@ -3122,6 +3170,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u
switch (port) { switch (port) {
case 0x2e8: case 0x2e8:
mach_log("HTOTAL=%04x, len=%d, set=%x, ATI mode bit=%x.\n", val, len, mach->shadow_set & 0x03, mach->accel.clock_sel & 0x01);
if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/
if (!(mach->shadow_cntl & 0x04)) if (!(mach->shadow_cntl & 0x04))
dev->htotal = val; dev->htotal = val;
@@ -3151,7 +3200,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u
if (len == 2) { if (len == 2) {
mach_log("HDISP and HTOTAL=%04x, len=%d, set=%x, ATI mode bit=%x.\n", val, len, mach->shadow_set & 0x03, mach->accel.clock_sel & 0x01); mach_log("HDISP and HTOTAL=%04x, len=%d, set=%x, ATI mode bit=%x.\n", val, len, mach->shadow_set & 0x03, mach->accel.clock_sel & 0x01);
if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/
if (!(mach->shadow_cntl & 0x04)) if ((!(mach->shadow_cntl & 0x04)) && ((val >> 8) & 0xff))
dev->htotal = (val >> 8) & 0xff; dev->htotal = (val >> 8) & 0xff;
if (!(mach->shadow_cntl & 0x08)) { if (!(mach->shadow_cntl & 0x08)) {
@@ -3179,7 +3228,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u
if (len == 1) { if (len == 1) {
mach_log("HDISP and HTOTAL+1=%02x, len=%d, set=%x, ATI mode bit=%x.\n", val, len, mach->shadow_set & 0x03, mach->accel.clock_sel & 0x01); mach_log("HDISP and HTOTAL+1=%02x, len=%d, set=%x, ATI mode bit=%x.\n", val, len, mach->shadow_set & 0x03, mach->accel.clock_sel & 0x01);
if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/
if (!(mach->shadow_cntl & 0x04)) { if (!(mach->shadow_cntl & 0x04) && val) {
dev->htotal = val; dev->htotal = val;
} }
} }
@@ -3294,11 +3343,16 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u
break; break;
case 0x22e8: case 0x22e8:
if ((mach->shadow_cntl & 0x03) == 0x00) if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) {
dev->disp_cntl = val; if ((mach->shadow_cntl & 0x03) == 0x00)
dev->disp_cntl = val;
}
mach_log("ATI 8514/A: DISP_CNTL write %04x=%02x, written=%02x, interlace=%d.\n", if (((mach->shadow_cntl & 0x03) == 0x00) || !dev->local)
port, val & 0x70, dev->disp_cntl & 0x70, dev->interlace); dev->disp_cntl_2 = val;
mach_log("ATI 8514/A: DISP_CNTL write %04x=%02x, written=%02x, interlace=%02x, shadowset=%02x, shadowcntl=%02x.\n",
port, val & 0x70, dev->disp_cntl & 0x70, dev->disp_cntl & 0x10, mach->shadow_set & 0x03, mach->shadow_cntl & 0x03);
svga_recalctimings(svga); svga_recalctimings(svga);
break; break;
@@ -7287,6 +7341,8 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514)
dev->accel_out_fifo = ati8514_accel_out_fifo; dev->accel_out_fifo = ati8514_accel_out_fifo;
dev->vblank_start = ati8514_vblank_start; dev->vblank_start = ati8514_vblank_start;
svga->clock_gen8514 = device_add(&ati18811_0_device);
svga->getclock8514 = ics2494_getclock;
} }
static int static int

View File

@@ -1102,10 +1102,8 @@ chips_69000_recalctimings(svga_t *svga)
svga->rowoffset |= (svga->crtc[0x41] & 0xF) << 8; svga->rowoffset |= (svga->crtc[0x41] & 0xF) << 8;
svga->interlace = !!(svga->crtc[0x70] & 0x80); svga->interlace = !!(svga->crtc[0x70] & 0x80);
if (svga->interlace)
if (svga->hdisp == 1280 && svga->dispend == 1024) { svga->dispend >>= 1;
svga->interlace = 0;
}
switch (chips->ext_regs[0x81] & 0xF) { switch (chips->ext_regs[0x81] & 0xF) {
default: default:
@@ -1146,6 +1144,8 @@ chips_69000_recalctimings(svga_t *svga)
if (svga->dispend > (((chips->flat_panel_regs[0x30] | ((chips->flat_panel_regs[0x35] & 0xF) << 8)) + 1))) { if (svga->dispend > (((chips->flat_panel_regs[0x30] | ((chips->flat_panel_regs[0x35] & 0xF) << 8)) + 1))) {
svga->dispend = svga->vsyncstart = svga->vblankstart = ((chips->flat_panel_regs[0x30] | ((chips->flat_panel_regs[0x35] & 0xF) << 8)) + 1); svga->dispend = svga->vsyncstart = svga->vblankstart = ((chips->flat_panel_regs[0x30] | ((chips->flat_panel_regs[0x35] & 0xF) << 8)) + 1);
if (svga->interlace)
svga->dispend >>= 1;
} }
//svga->hdisp = ((chips->flat_panel_regs[0x20] | ((chips->flat_panel_regs[0x25] & 0xF) << 8)) + 1) << 3; //svga->hdisp = ((chips->flat_panel_regs[0x20] | ((chips->flat_panel_regs[0x25] & 0xF) << 8)) + 1) << 3;
//svga->htotal = ((chips->flat_panel_regs[0x23] | ((chips->flat_panel_regs[0x26] & 0xF) << 8)) + 5) << 3; //svga->htotal = ((chips->flat_panel_regs[0x23] | ((chips->flat_panel_regs[0x26] & 0xF) << 8)) + 5) << 3;

View File

@@ -1050,7 +1050,7 @@ svga_recalctimings(svga_t *svga)
} }
if (xga_active && (svga->xga != NULL)) { if (xga_active && (svga->xga != NULL)) {
if (xga->on) if (xga->on)
crtcconst_xga = svga->clock_xga * svga->char_width; crtcconst_xga = svga->clock_xga * 8;
} }
#ifdef ENABLE_SVGA_LOG #ifdef ENABLE_SVGA_LOG