SVGA hskew

This commit is contained in:
Jasmine Iwanek
2023-08-06 20:29:39 -04:00
parent cb24ee27cb
commit 01ffb60df8
7 changed files with 306 additions and 32 deletions

View File

@@ -202,7 +202,7 @@ svga_out(uint16_t addr, uint8_t val, void *priv)
break;
case 4:
svga->chain2_write = !(val & 4);
svga->chain4 = val & 8;
svga->chain4 = (svga->chain4 & ~8) | (val & 8);
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8);
break;
@@ -307,6 +307,9 @@ svga_out(uint16_t addr, uint8_t val, void *priv)
if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1))
svga_recalctimings(svga);
break;
case 0x3da:
svga->fcr = val;
break;
default:
break;
@@ -384,6 +387,9 @@ svga_in(uint16_t addr, void *priv)
if (svga->adv_flags & FLAG_RAMDAC_SHIFT)
ret >>= 2;
break;
case 0x3ca:
ret = svga->fcr;
break;
case 0x3cc:
ret = svga->miscout;
break;
@@ -420,6 +426,8 @@ svga_in(uint16_t addr, void *priv)
ret = svga->cgastat;
if ((svga->fcr & 0x08) && svga->dispon)
ret |= 0x08;
break;
default:
@@ -453,6 +461,14 @@ svga_recalctimings(svga_t *svga)
double _dispontime;
double _dispofftime;
double disptime;
#ifdef ENABLE_SVGA_LOG
int vsyncend;
int vblankend;
int hdispstart;
int hdispend;
int hsyncstart;
int hsyncend;
#endif
svga->vtotal = svga->crtc[6];
svga->dispend = svga->crtc[0x12];
@@ -490,7 +506,7 @@ svga_recalctimings(svga_t *svga)
svga->vblankstart |= 0x200;
svga->vblankstart++;
svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5);
svga->hdisp = svga->crtc[1] - ((svga->crtc[3] & 0x60) >> 5);
svga->hdisp++;
svga->htotal = svga->crtc[0];
@@ -513,20 +529,20 @@ svga_recalctimings(svga_t *svga)
svga->hdisp_time = svga->hdisp;
svga->render = svga_render_blank;
if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) {
/* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */
if (svga->seqregs[1] & 8)
svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18;
else
svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9;
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/
if (svga->seqregs[1] & 8) { /*40 column*/
svga->render = svga_render_text_40;
svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18;
/* Character clock is off by 1 now in 40-line modes, on all cards. */
svga->ma_latch--;
svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18;
} else {
svga->render = svga_render_text_80;
svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9;
}
svga->hdisp_old = svga->hdisp;
} else {
svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
svga->hdisp_old = svga->hdisp;
switch (svga->gdcreg[5] & 0x60) {
@@ -612,6 +628,26 @@ svga_recalctimings(svga_t *svga)
} else
svga->monitor->mon_overscan_x = 16;
svga->htotal = svga->crtc[0];
svga->hblankstart = svga->crtc[4] + 1;
svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00);
#if 0
pclog("htotal = %i, hblankstart = %i, hblank_end_val = %02X\n", svga->htotal, svga->hblankstart, svga->hblank_end_val);
#endif
svga->hblank_end_len = 0x00000040;
svga->hblank_overscan = 1;
if (!svga->scrblank && svga->attr_palette_enable) {
/* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */
if (svga->seqregs[1] & 8)
svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18);
else
svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9);
} else
svga->dots_per_clock = 1;
/* Do svga->recalctimings_ex() here so that the above five variables can be
updated by said function. */
if (vga_on) {
if (svga->recalctimings_ex) {
svga->recalctimings_ex(svga);
@@ -629,6 +665,20 @@ svga_recalctimings(svga_t *svga)
xga_recalctimings(svga);
}
svga->htotal += 6; /*+6 is required for Tyrian*/
svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val;
if (svga->hblankend <= svga->hblankstart)
svga->hblankend += svga->hblank_end_len;
svga->hblankend += svga->hblank_ext;
svga->hblank_sub = 0;
if (svga->hblankend > svga->htotal) {
svga->hblankend &= (svga->hblank_end_len - 1);
svga->hblank_sub = svga->hblankend + svga->hblank_overscan;
svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock);
}
if (svga->hdisp >= 2048)
svga->monitor->mon_overscan_x = 0;
@@ -640,6 +690,43 @@ svga_recalctimings(svga_t *svga)
crtcconst = svga->clock * svga->char_width;
#ifdef ENABLE_SVGA_LOG
vsyncend = (svga->vsyncstart & 0xfffffff0) | (svga->crtc[0x11] & 0x0f);
if (vsyncend <= svga->vsyncstart)
vsyncend += 0x00000010;
vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f);
if (vblankend <= svga->vblankstart)
vblankend += 0x00000080;
hdispstart = ((svga->crtc[3] >> 5) & 3);
hdispend = svga->crtc[1] + 1;
hsyncstart = svga->crtc[4] + ((svga->crtc[5] >> 5) & 3) + 1;
hsyncend = (hsyncstart & 0xffffffe0) | (svga->crtc[5] & 0x1f);
if (hsyncend <= hsyncstart)
hsyncend += 0x00000020;
#endif
svga_log("Last scanline in the vertical period: %i\n"
"First scanline after the last of active display: %i\n"
"First scanline with vertical retrace asserted: %i\n"
"First scanline after the last with vertical retrace asserted: %i\n"
"First scanline of blanking: %i\n"
"First scanline after the last of blanking: %i\n"
"\n"
"Last character in the horizontal period: %i\n"
"First character of active display: %i\n"
"First character after the last of active display: %i\n"
"First character with horizontal retrace asserted: %i\n"
"First character after the last with horizontal retrace asserted: %i\n"
"First character of blanking: %i\n"
"First character after the last of blanking: %i\n"
"\n"
"\n",
svga->vtotal, svga->dispend, svga->vsyncstart, vsyncend,
svga->vblankstart, vblankend,
svga->htotal, hdispstart, hdispend, hsyncstart, hsyncend,
svga->hblankstart, svga->hblankend);
if (ibm8514_on && !svga->dev8514.local) {
disptime = svga->dev8514.h_total;
_dispontime = svga->dev8514.h_disp;
@@ -878,9 +965,9 @@ svga_poll(void *priv)
if (ret) {
if (svga->interlace && svga->oddeven)
svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5);
svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub;
else
svga->ma = svga->maback = ((svga->crtc[5] & 0x60) >> 5);
svga->ma = svga->maback = ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub;
svga->ma = (svga->ma << 2);
svga->maback = (svga->maback << 2);
@@ -951,9 +1038,9 @@ svga_poll(void *priv)
if ((dev->local && vga_on) || !dev->local) {
if (svga->interlace && svga->oddeven)
svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5);
svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub;
else
svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5);
svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub;
} else if (dev->local && ibm8514_on) {
if (svga->interlace && svga->oddeven)
svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1);
@@ -968,6 +1055,9 @@ svga_poll(void *priv)
if (svga->vsync_callback)
svga->vsync_callback(svga);
}
#if 0
if (svga->vc == lines_num) {
#endif
if (svga->vc == svga->vtotal) {
svga->vc = 0;
svga->sc = 0;
@@ -1090,7 +1180,8 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize,
svga->ramdac_type = RAMDAC_6BIT;
svga->map8 = svga->pallook;
svga->map8 = svga->pallook;
svga->hblank_overscan = 1; /* Do at least 1 character of overscan after horizontal blanking. */
return 0;
}