/* * 86Box A hypervisor and IBM PC system emulator that specializes in * running old operating systems and software designed for IBM * PC systems and compatibles from 1981 through fairly recent * system designs based on the PCI bus. * * This file is part of the 86Box distribution. * * EGA renderers. * * Version: @(#)vid_ega_render.c 1.0.1 2017/06/05 * * Author: Sarah Walker, * Miran Grca, * Copyright 2008-2017 Sarah Walker. * Copyright 2016-2017 Miran Grca. */ #include #include "../ibm.h" #include "../device.h" #include "../mem.h" #include "../rom.h" #include "video.h" #include "vid_ega.h" #include "vid_ega_render.h" int ega_display_line(ega_t *ega) { int y_add = (enable_overscan) ? (overscan_y >> 1) : 0; unsigned int dl = ega->displine; if (ega->crtc[9] & 0x1f) { dl -= (ega->crtc[8] & 0x1f); } dl += y_add; dl &= 0x7ff; return dl; } void ega_render_blank(ega_t *ega) { int x_add = (enable_overscan) ? 8 : 0; int dl = ega_display_line(ega); int x, xx; for (x = 0; x < ega->hdisp; x++) { switch (ega->seqregs[1] & 9) { case 0: for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[dl])[(x * 9) + xx + 32 + x_add] = 0; break; case 1: for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[dl])[(x * 8) + xx + 32 + x_add] = 0; break; case 8: for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[dl])[(x * 18) + xx + 32 + x_add] = 0; break; case 9: for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[dl])[(x * 16) + xx + 32 + x_add] = 0; break; } } } void ega_render_text_standard(ega_t *ega, int drawcursor) { int x, xx; int x_add = (enable_overscan) ? 8 : 0; int dl = ega_display_line(ega); for (x = 0; x < ega->hdisp; x++) { int drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron); uint8_t chr = ega->vram[(ega->ma << 1) & ega->vrammask]; uint8_t attr = ega->vram[((ega->ma << 1) + 1) & ega->vrammask]; uint8_t dat; uint32_t fg, bg; uint32_t charaddr; if (attr & 8) charaddr = ega->charsetb + (chr * 128); else charaddr = ega->charseta + (chr * 128); if (drawcursor) { bg = ega->pallook[ega->egapal[attr & 15]]; fg = ega->pallook[ega->egapal[attr >> 4]]; } else { fg = ega->pallook[ega->egapal[attr & 15]]; bg = ega->pallook[ega->egapal[attr >> 4]]; if (attr & 0x80 && ega->attrregs[0x10] & 8) { bg = ega->pallook[ega->egapal[(attr >> 4) & 7]]; if (ega->blink & 16) fg = bg; } } dat = ega->vram[charaddr + (ega->sc << 2)]; if (ega->seqregs[1] & 8) { if (ega->seqregs[1] & 1) { for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[dl])[((x << 4) + 32 + (xx << 1) + x_add) & 2047] = ((uint32_t *)buffer32->line[dl])[((x << 4) + 33 + (xx << 1) + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg; } else { for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + (xx << 1) + x_add) & 2047] = ((uint32_t *)buffer32->line[dl])[((x * 18) + 33 + (xx << 1) + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg; if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4)) ((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + 16 + x_add) & 2047] = ((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + 17 + x_add) & 2047] = bg; else ((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + 16 + x_add) & 2047] = ((uint32_t *)buffer32->line[dl])[((x * 18) + 32 + 17 + x_add) & 2047] = (dat & 1) ? fg : bg; } } else { if (ega->seqregs[1] & 1) { for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[dl])[((x << 3) + 32 + xx + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg; } else { for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[dl])[((x * 9) + 32 + xx + x_add) & 2047] = (dat & (0x80 >> xx)) ? fg : bg; if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4)) ((uint32_t *)buffer32->line[dl])[((x * 9) + 32 + 8 + x_add) & 2047] = bg; else ((uint32_t *)buffer32->line[dl])[((x * 9) + 32 + 8 + x_add) & 2047] = (dat & 1) ? fg : bg; } } ega->ma += 4; ega->ma &= ega->vrammask; } } #ifdef JEGA static __inline int is_kanji1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } static __inline int is_kanji2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } void ega_jega_render_blit_text(ega_t *ega, int x, int dl, int start, int width, uint16_t dat, int cw, uint32_t fg, uint32_t bg) { int x_add = (enable_overscan) ? 8 : 0; int xx = 0; int xxx = 0; if (ega->seqregs[1] & 8) { for (xx = start; xx < (start + width); xx++) for (xxx = 0; xxx < cw; xxx++) ((uint32_t *)buffer32->line[dl])[(((x * width) + 32 + (xxx << 1) + ((xx << 1) * cw)) & 2047) + x_add] = ((uint32_t *)buffer32->line[dl])[(((x * width) + 33 + (xxx << 1) + ((xx << 1) * cw)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg; } else { for (xx = start; xx < (start + width); xx++) ((uint32_t *)buffer32->line[dl])[(((x * width) + 32 + xxx + (xx * cw)) & 2047) + x_add] = (dat & (0x80 >> xx)) ? fg : bg; } } void ega_render_text_jega(ega_t *ega, int drawcursor) { int dl = ega_display_line(ega); uint8_t chr, attr; uint16_t dat = 0, dat2; int x; uint32_t fg = 0, bg = 0; /* Temporary for DBCS. */ unsigned int chr_left = 0; unsigned int bsattr = 0; int chr_wide = 0; uint32_t bg_ex = 0; uint32_t fg_ex = 0; int blocks = ega->hdisp; int fline; unsigned int pad_y, exattr; if (fullchange) { for (x = 0; x < ega->hdisp; x++) { 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]; if (chr_wide == 0) { if (ega->RMOD2 & 0x80) { fg_ex = ega->pallook[ega->egapal[attr & 15]]; if (attr & 0x80 && ega->attrregs[0x10] & 8) { bg_ex = ega->pallook[ega->egapal[(attr >> 4) & 7]]; } else { bg_ex = ega->pallook[ega->egapal[attr >> 4]]; } } else { if (attr & 0x40) { /* Reversed in JEGA mode */ bg_ex = ega->pallook[ega->egapal[attr & 15]]; fg_ex = ega->pallook[0]; } else { /* Reversed in JEGA mode */ fg_ex = ega->pallook[ega->egapal[attr & 15]]; bg_ex = ega->pallook[0]; } } if (drawcursor) { bg = fg_ex; fg = bg_ex; } else { fg = fg_ex; bg = bg_ex; } if (attr & 0x80 && ega->attrregs[0x10] & 8) { if (ega->blink & 16) fg = bg; } /* Stay drawing if the char code is DBCS and not at last column. */ if (is_kanji1(dat) && (blocks > 1)) { /* Set the present char/attr code to the next loop. */ chr_left = chr; chr_wide = 1; } else { /* The char code is ANK (8 dots width). */ dat = jfont_sbcs_19[chr*19+(ega->sc)]; /* w8xh19 font */ ega_jega_render_blit_text(ega, x, dl, 0, 8, dat, 1, fg, bg); if (bsattr & 0x20) { /* Vertical line. */ dat = 0x18; ega_jega_render_blit_text(ega, x, fline, 0, 8, dat, 1, fg, bg); } if (ega->sc == 18 && bsattr & 0x10) { /* Underline. */ dat = 0xff; ega_jega_render_blit_text(ega, x, fline, 0, 8, dat, 1, fg, bg); } chr_wide = 0; blocks--; } } else { /* The char code may be in DBCS. */ pad_y = ega->RPSSC; exattr = 0; /* Note: The second column should be applied its basic attribute. */ if (ega->RMOD2 & 0x40) { /* If JEGA Extended Attribute is enabled. */ exattr = attr; if ((exattr & 0x30) == 0x30) pad_y = ega->RPSSL; /* Set top padding of lower 2x character. */ else if (exattr & 0x30) pad_y = ega->RPSSU; /* Set top padding of upper 2x character. */ } if (ega->sc >= pad_y && ega->sc < 16 + pad_y) { /* Check the char code is in Wide charset of Shift-JIS. */ if (is_kanji2(chr)) { fline = ega->sc - pad_y; chr_left <<= 8; /* Fix vertical position. */ chr |= chr_left; /* Horizontal wide font (Extended Attribute). */ if (exattr & 0x20) { if (exattr & 0x10) fline = (fline >> 1) + 8; else fline = fline >> 1; } /* Vertical wide font (Extended Attribute). */ if (exattr & 0x40) { dat = jfont_dbcs_16[chr * 32 + fline * 2]; if (!(exattr & 0x08)) dat = jfont_dbcs_16[chr * 32 + fline * 2 + 1]; /* Draw 8 dots. */ ega_jega_render_blit_text(ega, x, dl, 0, 8, dat, 2, fg, bg); } else { /* Get the font pattern. */ dat = jfont_dbcs_16[chr * 32 + fline * 2]; dat <<= 8; dat |= jfont_dbcs_16[chr * 32 + fline * 2 + 1]; /* Bold (Extended Attribute). */ if (exattr &= 0x80) { dat2 = dat; dat2 >>= 1; dat |= dat2; /* Original JEGA colours the last row with the next column's attribute. */ } /* Draw 16 dots */ ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg); } } else { /* Ignore wide char mode, put blank. */ dat = 0; ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg); } } else if (ega->sc == (17 + pad_y) && (bsattr & 0x10)) { /* Underline. */ dat = 0xffff; ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg); } else { /* Draw blank */ dat = 0; ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg); } if (bsattr & 0x20) { /* Vertical line draw at last. */ dat = 0x0180; ega_jega_render_blit_text(ega, x, dl, 0, 16, dat, 1, fg, bg); } chr_wide = 0; blocks -= 2; /* Move by 2 columns. */ } ega->ma += 4; ega->ma &= ega->vrammask; } } } #endif void ega_render_2bpp_lowres(ega_t *ega) { int x_add = (enable_overscan) ? 8 : 0; int dl = ega_display_line(ega); int x; int offset = ((8 - ega->scrollcache) << 1) + 16; for (x = 0; x <= ega->hdisp; x++) { uint8_t edat[2]; uint32_t addr = ega->ma; if (!(ega->crtc[0x17] & 0x40)) { addr = (addr << 1) & ega->vrammask; addr &= ~7; if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000)) addr |= 4; if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000)) addr |= 4; } if (!(ega->crtc[0x17] & 0x01)) addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0); if (!(ega->crtc[0x17] & 0x02)) addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0); edat[0] = ega->vram[addr]; edat[1] = ega->vram[addr | 0x1]; if (ega->seqregs[1] & 4) ega->ma += 2; else ega->ma += 4; ega->ma &= ega->vrammask; ((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset + x_add]= ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[edat[1] & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 10 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 11 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 8 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 9 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]]; } } void ega_render_2bpp_highres(ega_t *ega) { int x_add = (enable_overscan) ? 8 : 0; int dl = ega_display_line(ega); int x; int offset = ((8 - ega->scrollcache) << 1) + 16; for (x = 0; x <= ega->hdisp; x++) { uint8_t edat[2]; uint32_t addr = ega->ma; if (!(ega->crtc[0x17] & 0x40)) { addr = (addr << 1) & ega->vrammask; addr &= ~7; if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000)) addr |= 4; if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000)) addr |= 4; } if (!(ega->crtc[0x17] & 0x01)) addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0); if (!(ega->crtc[0x17] & 0x02)) addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0); edat[0] = ega->vram[addr]; edat[1] = ega->vram[addr | 0x1]; if (ega->seqregs[1] & 4) ega->ma += 2; else ega->ma += 4; ega->ma &= ega->vrammask; ((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[edat[1] & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 2) & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 4) & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ega->pallook[ega->egapal[(edat[1] >> 6) & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 0) & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 2) & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 4) & 3]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ega->pallook[ega->egapal[(edat[0] >> 6) & 3]]; } } void ega_render_4bpp_lowres(ega_t *ega) { int x_add = (enable_overscan) ? 8 : 0; int dl = ega_display_line(ega); int x; int offset = ((8 - ega->scrollcache) << 1) + 16; for (x = 0; x <= ega->hdisp; x++) { uint8_t edat[4]; uint8_t dat; uint32_t addr = ega->ma; int oddeven = 0; if (!(ega->crtc[0x17] & 0x40)) { addr = (addr << 1) & ega->vrammask; if (ega->seqregs[1] & 4) oddeven = (addr & 4) ? 1 : 0; addr &= ~7; if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000)) addr |= 4; if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000)) addr |= 4; } if (!(ega->crtc[0x17] & 0x01)) addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0); if (!(ega->crtc[0x17] & 0x02)) addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0); if (ega->seqregs[1] & 4) { edat[0] = ega->vram[addr | oddeven]; edat[2] = ega->vram[addr | oddeven | 0x2]; edat[1] = edat[3] = 0; ega->ma += 2; } else { edat[0] = ega->vram[addr]; edat[1] = ega->vram[addr | 0x1]; edat[2] = ega->vram[addr | 0x2]; edat[3] = ega->vram[addr | 0x3]; ega->ma += 4; } ega->ma &= ega->vrammask; dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); ((uint32_t *)buffer32->line[dl])[(x << 4) + 14 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 15 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 12 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 13 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); ((uint32_t *)buffer32->line[dl])[(x << 4) + 10 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 11 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 8 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 9 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); ((uint32_t *)buffer32->line[dl])[(x << 4) + 6 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + 4 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); ((uint32_t *)buffer32->line[dl])[(x << 4) + 2 + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; ((uint32_t *)buffer32->line[dl])[(x << 4) + offset + x_add] = ((uint32_t *)buffer32->line[dl])[(x << 4) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; } } void ega_render_4bpp_highres(ega_t *ega) { int x_add = (enable_overscan) ? 8 : 0; int dl = ega_display_line(ega); int x; int offset = (8 - ega->scrollcache) + 24; for (x = 0; x <= ega->hdisp; x++) { uint8_t edat[4]; uint8_t dat; uint32_t addr = ega->ma; int oddeven = 0; if (!(ega->crtc[0x17] & 0x40)) { addr = (addr << 1) & ega->vrammask; if (ega->seqregs[1] & 4) oddeven = (addr & 4) ? 1 : 0; addr &= ~7; if ((ega->crtc[0x17] & 0x20) && (ega->ma & 0x20000)) addr |= 4; if (!(ega->crtc[0x17] & 0x20) && (ega->ma & 0x8000)) addr |= 4; } if (!(ega->crtc[0x17] & 0x01)) addr = (addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0); if (!(ega->crtc[0x17] & 0x02)) addr = (addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0); if (ega->seqregs[1] & 4) { edat[0] = ega->vram[addr | oddeven]; edat[2] = ega->vram[addr | oddeven | 0x2]; edat[1] = edat[3] = 0; ega->ma += 2; } else { edat[0] = ega->vram[addr]; edat[1] = ega->vram[addr | 0x1]; edat[2] = ega->vram[addr | 0x2]; edat[3] = ega->vram[addr | 0x3]; ega->ma += 4; } ega->ma &= ega->vrammask; dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); ((uint32_t *)buffer32->line[dl])[(x << 3) + 7 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; ((uint32_t *)buffer32->line[dl])[(x << 3) + 6 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); ((uint32_t *)buffer32->line[dl])[(x << 3) + 5 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; ((uint32_t *)buffer32->line[dl])[(x << 3) + 4 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); ((uint32_t *)buffer32->line[dl])[(x << 3) + 3 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; ((uint32_t *)buffer32->line[dl])[(x << 3) + 2 + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); ((uint32_t *)buffer32->line[dl])[(x << 3) + 1 + offset + x_add] = ega->pallook[ega->egapal[(dat & 0xf) & ega->attrregs[0x12]]]; ((uint32_t *)buffer32->line[dl])[(x << 3) + offset + x_add] = ega->pallook[ega->egapal[(dat >> 4) & ega->attrregs[0x12]]]; } }