From 69c18755a4df0a51c1017a184d6460c844c5b45e Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Thu, 23 Mar 2023 15:28:25 +1300 Subject: [PATCH] vid_ega: Extend 4bpp renderer to handle CGA 2bpp chunky graphics; Remove 2bpp renderer This also lets planes 2 and 3 be used. --- src/include/86box/vid_ega.h | 6 +-- src/video/vid_ega.c | 27 +++++----- src/video/vid_ega_render.c | 103 +++++------------------------------- 3 files changed, 30 insertions(+), 106 deletions(-) diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 63d3afaea..c308f7edc 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -113,6 +113,7 @@ extern int con, cursoron, cgablink; extern int scrollcache; extern uint8_t edatlookup[4][4]; +extern uint8_t egaremap2bpp[256]; #if defined(EMU_MEM_H) && defined(EMU_ROM_H) void ega_render_blank(ega_t *ega); @@ -123,10 +124,7 @@ void ega_render_overscan_right(ega_t *ega); void ega_render_text_40(ega_t *ega); void ega_render_text_80(ega_t *ega); -void ega_render_2bpp_lowres(ega_t *ega); -void ega_render_2bpp_highres(ega_t *ega); - -void ega_render_4bpp(ega_t *ega); +void ega_render_graphics(ega_t *ega); #endif #endif /*VIDEO_EGA_H*/ diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index b78667d54..91166cf00 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -57,7 +57,7 @@ static uint8_t ega_rotate[8][256]; static uint32_t pallook16[256], pallook64[256]; static int ega_type = 0, old_overscan_color = 0; -extern uint8_t edatlookup[4][4]; +uint8_t egaremap2bpp[256]; /* 3C2 controls default mode on EGA. On VGA, it determines monitor type (mono or colour): 7=CGA mode (200 lines), 9=EGA mode (350 lines), 8=EGA mode (200 lines). */ @@ -419,19 +419,8 @@ ega_recalctimings(ega_t *ega) ega->hdisp_old = ega->hdisp; } else { ega->hdisp *= (ega->seqregs[1] & 8) ? 16 : 8; + ega->render = ega_render_graphics; ega->hdisp_old = ega->hdisp; - - switch (ega->gdcreg[5] & 0x20) { - case 0x00: - ega->render = ega_render_4bpp; - break; - case 0x20: - if (ega->seqregs[1] & 8) - ega->render = ega_render_2bpp_lowres; - else - ega->render = ega_render_2bpp_highres; - break; - } } } @@ -1060,6 +1049,18 @@ ega_init(ega_t *ega, int monitor_type, int is_mono) } } + for (c = 0; c < 256; c++) { + egaremap2bpp[c] = 0; + if (c & 0x01) + egaremap2bpp[c] |= 0x01; + if (c & 0x04) + egaremap2bpp[c] |= 0x02; + if (c & 0x10) + egaremap2bpp[c] |= 0x04; + if (c & 0x40) + egaremap2bpp[c] |= 0x08; + } + if (is_mono) { for (c = 0; c < 256; c++) { if (((c >> 3) & 3) == 0) diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index fc77f6c3b..9543c9761 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -247,95 +247,7 @@ ega_render_text_80(ega_t *ega) } void -ega_render_2bpp_lowres(ega_t *ega) -{ - int x; - uint8_t dat[2]; - uint32_t addr, *p; - - if ((ega->displine + ega->y_add) < 0) - return; - - p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; - - if (ega->firstline_draw == 2000) - ega->firstline_draw = ega->displine; - ega->lastline_draw = ega->displine; - - for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 16) { - addr = ega->remap_func(ega, ega->ma); - - dat[0] = ega->vram[addr]; - dat[1] = ega->vram[addr | 0x1]; - if (ega->seqregs[1] & 4) - ega->ma += 2; - else - ega->ma += 4; - - ega->ma &= ega->vrammask; - - if (ega->crtc[0x17] & 0x80) { - p[0] = p[1] = ega->pallook[ega->egapal[(dat[0] >> 6) & 3]]; - p[2] = p[3] = ega->pallook[ega->egapal[(dat[0] >> 4) & 3]]; - p[4] = p[5] = ega->pallook[ega->egapal[(dat[0] >> 2) & 3]]; - p[6] = p[7] = ega->pallook[ega->egapal[dat[0] & 3]]; - p[8] = p[9] = ega->pallook[ega->egapal[(dat[1] >> 6) & 3]]; - p[10] = p[11] = ega->pallook[ega->egapal[(dat[1] >> 4) & 3]]; - p[12] = p[13] = ega->pallook[ega->egapal[(dat[1] >> 2) & 3]]; - p[14] = p[15] = ega->pallook[ega->egapal[dat[1] & 3]]; - } else - memset(p, 0x00, 16 * sizeof(uint32_t)); - - p += 16; - } -} - -void -ega_render_2bpp_highres(ega_t *ega) -{ - int x; - uint8_t dat[2]; - uint32_t addr, *p; - - if ((ega->displine + ega->y_add) < 0) - return; - - p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; - - if (ega->firstline_draw == 2000) - ega->firstline_draw = ega->displine; - ega->lastline_draw = ega->displine; - - for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 8) { - addr = ega->remap_func(ega, ega->ma); - - dat[0] = ega->vram[addr]; - dat[1] = ega->vram[addr | 0x1]; - if (ega->seqregs[1] & 4) - ega->ma += 2; - else - ega->ma += 4; - - ega->ma &= ega->vrammask; - - if (ega->crtc[0x17] & 0x80) { - p[0] = ega->pallook[ega->egapal[(dat[0] >> 6) & 3]]; - p[1] = ega->pallook[ega->egapal[(dat[0] >> 4) & 3]]; - p[2] = ega->pallook[ega->egapal[(dat[0] >> 2) & 3]]; - p[3] = ega->pallook[ega->egapal[dat[0] & 3]]; - p[4] = ega->pallook[ega->egapal[(dat[1] >> 6) & 3]]; - p[5] = ega->pallook[ega->egapal[(dat[1] >> 4) & 3]]; - p[6] = ega->pallook[ega->egapal[(dat[1] >> 2) & 3]]; - p[7] = ega->pallook[ega->egapal[dat[1] & 3]]; - } else - memset(p, 0x00, 8 * sizeof(uint32_t)); - - p += 8; - } -} - -void -ega_render_4bpp(ega_t *ega) +ega_render_graphics(ega_t *ega) { if ((ega->displine + ega->y_add) < 0) return; @@ -347,6 +259,7 @@ ega_render_4bpp(ega_t *ega) ega->lastline_draw = ega->displine; const bool doublewidth = ((ega->seqregs[1] & 8) != 0); + const bool cga2bpp = ((ega->gdcreg[5] & 0x20) != 0); const int dotwidth = (doublewidth ? 2 : 1); const int charwidth = dotwidth*8; int secondcclk = 0; @@ -369,6 +282,18 @@ ega_render_4bpp(ega_t *ega) } ega->ma &= 0x3ffff; + if (cga2bpp) { + // Remap CGA 2bpp-chunky data into fully planar data + uint8_t dat0 = egaremap2bpp[edat[1] ] | (egaremap2bpp[edat[0] ] << 4); + uint8_t dat1 = egaremap2bpp[edat[1]>>1] | (egaremap2bpp[edat[0]>>1] << 4); + uint8_t dat2 = egaremap2bpp[edat[3] ] | (egaremap2bpp[edat[2] ] << 4); + uint8_t dat3 = egaremap2bpp[edat[3]>>1] | (egaremap2bpp[edat[2]>>1] << 4); + edat[0] = dat0; + edat[1] = dat1; + edat[2] = dat2; + edat[3] = dat3; + } + if (ega->crtc[0x17] & 0x80) { for (int i = 0; i < 4; i++) { const int outoffs = i*(dotwidth<<1);