From ac0a1ee327de845bcfe193778c24780839310b7f Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 19 Nov 2019 19:18:44 +0100 Subject: [PATCH] Fixed EGA and (S)VGA pel panning, fixes games like Supaplex. --- src/video/vid_ega.c | 12 +++++++--- src/video/vid_ega_render.c | 16 ++++++------- src/video/vid_svga.c | 30 +++++++++++++++-------- src/video/vid_svga_render.c | 48 ++++++++++++++++++------------------- 4 files changed, 61 insertions(+), 45 deletions(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index fac75e163..acda3edde 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -9,7 +9,7 @@ * Emulation of the EGA and Chips & Technologies SuperEGA * graphics cards. * - * Version: @(#)vid_ega.c 1.0.22 2019/10/03 + * Version: @(#)vid_ega.c 1.0.23 2019/11/19 * * Authors: Sarah Walker, * Miran Grca, @@ -389,9 +389,13 @@ ega_poll(void *p) ega->displine <<= 1; ega->y_add <<= 1; - ega_render_overscan_left(ega); ega->render(ega); + + ega->x_add = (overscan_x >> 1); + ega_render_overscan_left(ega); ega_render_overscan_right(ega); + ega->x_add = (overscan_x >> 1) - ega->scrollcache; + ega->displine++; ega->ma = old_ma; @@ -454,8 +458,10 @@ ega_poll(void *p) if (ega->vc == ega->split) { ega->ma = ega->maback = 0; ega->sc = 0; - if (ega->attrregs[0x10] & 0x20) + if (ega->attrregs[0x10] & 0x20) { ega->scrollcache = 0; + ega->x_add = (overscan_x >> 1); + } } if (ega->vc == ega->dispend) { ega->dispon = 0; diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index e5bcc9fb0..cf5ec7d50 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -8,7 +8,7 @@ * * EGA renderers. * - * Version: @(#)vid_ega_render.c 1.0.6 2019/10/03 + * Version: @(#)vid_ega_render.c 1.0.7 2019/11/19 * * Author: Sarah Walker, * Miran Grca, @@ -53,7 +53,7 @@ ega_render_blank(ega_t *ega) if ((ega->displine + ega->y_add) < 0) return; - for (x = 0; x < ega->hdisp; x++) { + for (x = 0; x < (ega->hdisp + ega->scrollcache); x++) { switch (ega->seqregs[1] & 9) { case 0: for (xx = 0; xx < 9; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 9) + xx] = 0; @@ -120,7 +120,7 @@ ega_render_text_40(ega_t *ega) p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; xinc = (ega->seqregs[1] & 1) ? 16 : 18; - for (x = 0; x < ega->hdisp; x += xinc) { + for (x = 0; x < (ega->hdisp + ega->scrollcache); x += xinc) { drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron); chr = ega->vram[(ega->ma << 1) & ega->vrammask]; attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask]; @@ -183,7 +183,7 @@ ega_render_text_80(ega_t *ega) p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; xinc = (ega->seqregs[1] & 1) ? 8 : 9; - for (x = 0; x < ega->hdisp; x += xinc) { + for (x = 0; x < (ega->hdisp + ega->scrollcache); x += xinc) { drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron); chr = ega->vram[(ega->ma << 1) & ega->vrammask]; attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask]; @@ -240,7 +240,7 @@ ega_render_2bpp_lowres(ega_t *ega) ega->firstline_draw = ega->displine; ega->lastline_draw = ega->displine; - for (x = 0; x <= ega->hdisp; x += 16) { + for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 16) { addr = ega->ma; if (!(ega->crtc[0x17] & 0x40)) { @@ -299,7 +299,7 @@ ega_render_2bpp_highres(ega_t *ega) ega->firstline_draw = ega->displine; ega->lastline_draw = ega->displine; - for (x = 0; x <= ega->hdisp; x += 8) { + for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 8) { addr = ega->ma; if (!(ega->crtc[0x17] & 0x40)) { @@ -358,7 +358,7 @@ ega_render_4bpp_lowres(ega_t *ega) ega->firstline_draw = ega->displine; ega->lastline_draw = ega->displine; - for (x = 0; x <= ega->hdisp; x += 16) { + for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 16) { addr = ega->ma; oddeven = 0; @@ -431,7 +431,7 @@ ega_render_4bpp_highres(ega_t *ega) ega->firstline_draw = ega->displine; ega->lastline_draw = ega->displine; - for (x = 0; x <= ega->hdisp; x += 8) { + for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 8) { addr = ega->ma; oddeven = 0; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index c3c31ef59..d2f7e45a3 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -11,7 +11,7 @@ * This is intended to be used by another SVGA driver, * and not as a card in it's own right. * - * Version: @(#)vid_svga.c 1.0.37 2019/10/21 + * Version: @(#)vid_svga.c 1.0.38 2019/11/19 * * Authors: Sarah Walker, * Miran Grca, @@ -530,10 +530,13 @@ svga_recalctimings(svga_t *svga) overscan_y = 16; } - overscan_x = (svga->seqregs[1] & 1) ? 16 : 18; + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { + overscan_x = (svga->seqregs[1] & 1) ? 16 : 18; - if (svga->seqregs[1] & 8) - overscan_x <<= 1; + if (svga->seqregs[1] & 8) + overscan_x <<= 1; + } else + overscan_x = 16; if (svga->recalctimings_ex) svga->recalctimings_ex(svga); @@ -553,6 +556,7 @@ svga_recalctimings(svga_t *svga) disptime *= 2; _dispontime *= 2; } + _dispofftime = disptime - _dispontime; _dispontime *= crtcconst; _dispofftime *= crtcconst; @@ -572,6 +576,7 @@ svga_poll(void *p) svga_t *svga = (svga_t *)p; uint32_t x, blink_delay; int wx, wy; + int skip = (svga->crtc[8] >> 5) & 0x03; if (!svga->linepos) { if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { @@ -625,9 +630,12 @@ svga_poll(void *p) } if (!svga->override) { - svga_render_overscan_left(svga); svga->render(svga); + + svga->x_add = (overscan_x >> 1); + svga_render_overscan_left(svga); svga_render_overscan_right(svga); + svga->x_add = (overscan_x >> 1) - svga->scrollcache; } if (svga->overlay_on) { @@ -702,8 +710,10 @@ svga_poll(void *p) if (svga->vc == svga->split) { svga->ma = svga->maback = 0; svga->sc = 0; - if (svga->attrregs[0x10] & 0x20) + if (svga->attrregs[0x10] & 0x20) { svga->scrollcache = 0; + svga->x_add = (overscan_x >> 1); + } } if (svga->vc == svga->dispend) { if (svga->vblank_start) @@ -761,9 +771,9 @@ svga_poll(void *p) svga->ma = svga->maback = svga->ma_latch; svga->ca = (svga->crtc[0xe] << 8) | svga->crtc[0xf]; - svga->ma <<= 2; - svga->maback <<= 2; - svga->ca <<= 2; + svga->ma = (svga->ma << 2) + (skip << 2); + svga->maback = (svga->maback << 2) + (skip << 2); + svga->ca = (svga->ca << 2) + (skip << 2); } if (svga->vc == svga->vtotal) { svga->vc = 0; @@ -786,7 +796,7 @@ svga_poll(void *p) else svga->scrollcache = (svga->scrollcache & 0x06) >> 1; - if (svga->seqregs[1] & 8) + if ((svga->seqregs[1] & 8) || (svga->render == svga_render_8bpp_lowres)) svga->scrollcache <<= 1; svga->x_add = (overscan_x >> 1) - svga->scrollcache; diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index 04a1f7219..2448bd1fb 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -8,7 +8,7 @@ * * SVGA renderers. * - * Version: @(#)vid_svga_render.c 1.0.13 2019/03/08 + * Version: @(#)vid_svga_render.c 1.0.14 2019/11/19 * * Authors: Sarah Walker, * Miran Grca, @@ -40,7 +40,7 @@ svga_render_blank(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x < svga->hdisp; x++) { + for (x = 0; x < (svga->hdisp + svga->scrollcache); x++) { switch (svga->seqregs[1] & 9) { case 0: for (xx = 0; xx < 9; xx++) @@ -84,7 +84,7 @@ svga_render_overscan_right(svga_t *svga) if (svga->scrblank || (svga->hdisp == 0)) return; - right = (overscan_x >> 1) + svga->scrollcache; + right = (overscan_x >> 1); for (i = 0; i < right; i++) buffer32->line[svga->displine + svga->y_add][svga->x_add + svga->hdisp + i] = svga->overscan_color; } @@ -111,7 +111,7 @@ svga_render_text_40(svga_t *svga) p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; xinc = (svga->seqregs[1] & 1) ? 16 : 18; - for (x = 0; x < svga->hdisp; x += xinc) { + for (x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; @@ -174,7 +174,7 @@ svga_render_text_80(svga_t *svga) p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; xinc = (svga->seqregs[1] & 1) ? 8 : 9; - for (x = 0; x < svga->hdisp; x += xinc) { + for (x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; @@ -237,7 +237,7 @@ svga_render_text_80_ksc5601(svga_t *svga) xinc = (svga->seqregs[1] & 1) ? 8 : 9; - for (x = 0; x < svga->hdisp; x += xinc) { + for (x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) { drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; nextchr = svga->vram[((svga->ma + 4) << 1) & svga->vram_display_mask]; @@ -348,7 +348,7 @@ svga_render_2bpp_lowres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 16) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 16) { addr = svga->ma; if (!(svga->crtc[0x17] & 0x40)) { @@ -411,7 +411,7 @@ svga_render_2bpp_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 8) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { addr = svga->ma; if (!(svga->crtc[0x17] & 0x40)) { @@ -473,7 +473,7 @@ svga_render_4bpp_lowres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 16) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 16) { addr = svga->ma; oddeven = 0; @@ -547,7 +547,7 @@ svga_render_4bpp_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 8) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { addr = svga->ma; oddeven = 0; @@ -617,7 +617,7 @@ svga_render_8bpp_lowres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 8) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); p[0] = p[1] = svga->map8[dat & 0xff]; @@ -650,7 +650,7 @@ svga_render_8bpp_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 8) { + for (x = 0; x <= (svga->hdisp/* + svga->scrollcache*/); x += 8) { dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); p[0] = svga->map8[dat & 0xff]; p[1] = svga->map8[(dat >> 8) & 0xff]; @@ -688,7 +688,7 @@ svga_render_15bpp_lowres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 4) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); p[(x << 1)] = p[(x << 1) + 1] = video_15to32[dat & 0xffff]; @@ -724,7 +724,7 @@ svga_render_15bpp_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 8) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); p[x] = video_15to32[dat & 0xffff]; p[x + 1] = video_15to32[dat >> 16]; @@ -764,7 +764,7 @@ svga_render_15bpp_mix_lowres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 4) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); p[(x << 1)] = p[(x << 1) + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; @@ -800,7 +800,7 @@ svga_render_15bpp_mix_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 8) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); p[x] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff]; dat >>= 16; @@ -844,7 +844,7 @@ svga_render_16bpp_lowres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 4) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); p[(x << 1)] = p[(x << 1) + 1] = video_16to32[dat & 0xffff]; p[(x << 1) + 2] = p[(x << 1) + 3] = video_16to32[dat >> 16]; @@ -875,7 +875,7 @@ svga_render_16bpp_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 8) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); p[x] = video_16to32[dat & 0xffff]; p[x + 1] = video_16to32[dat >> 16]; @@ -912,7 +912,7 @@ svga_render_24bpp_lowres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x++) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); svga->ma += 3; svga->ma &= svga->vram_display_mask; @@ -940,7 +940,7 @@ svga_render_24bpp_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 4) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) { dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); p[x] = dat & 0xffffff; @@ -974,7 +974,7 @@ svga_render_32bpp_lowres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x++) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); svga->ma += 4; svga->ma &= svga->vram_display_mask; @@ -1002,7 +1002,7 @@ svga_render_32bpp_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x++) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); p[x] = dat & 0xffffff; } @@ -1029,7 +1029,7 @@ svga_render_ABGR8888_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x++) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); } @@ -1056,7 +1056,7 @@ svga_render_RGBA8888_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x++) { + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); p[x] = dat >> 8; }