From dfd848713b39d1d62fa99b835a4ed3433b4168ac Mon Sep 17 00:00:00 2001 From: David Kuder Date: Tue, 25 Apr 2023 01:55:14 -0400 Subject: [PATCH] Color Artifact Changes This changeset improves the horizontal resolution of the color DHGR rendering and fixes double-lores rendering. HGR rendering has been rewritten to match the new DHGR rendering. DHGR, HGR and DGR modes now have a horizontal stippling effect applied. The DHGR & HGR changes can be reverted at runtime with bit 3 of the $C0n1 register. --- common/buffers.h | 1 + vga/businterface.c | 5 ++ vga/hires_dot_patterns.h | 67 +++++++++++++++++++ vga/render.h | 2 + vga/render_dgr.c | 125 ++++++++++++++++++++++++++-------- vga/render_dhgr.c | 111 +++++++++++++++++++------------ vga/render_hires.c | 140 +++++++++++++++++++++++++++------------ 7 files changed, 337 insertions(+), 114 deletions(-) diff --git a/common/buffers.h b/common/buffers.h index 8ffdfe5..627fc67 100644 --- a/common/buffers.h +++ b/common/buffers.h @@ -105,6 +105,7 @@ extern volatile uint32_t internal_flags; #define SOFTSW_SHADOW_IO 0x04000000 // V2 Analog specific softswitches +#define IFLAGS_OLDCOLOR 0x08000000 #define SOFTSW_TERMINAL 0x10000000 #define IFLAGS_TEST 0x20000000 #define IFLAGS_IIE_REGS 0x40000000 diff --git a/vga/businterface.c b/vga/businterface.c index 0ad160f..eca0378 100644 --- a/vga/businterface.c +++ b/vga/businterface.c @@ -213,6 +213,11 @@ void __time_critical_func(vga_businterface)(uint32_t address, uint32_t value) { switch(address & 0x0F) { case 0x01: mono_palette = (value >> 4) & 0xF; + if(value & 0x8) { + internal_flags |= IFLAGS_OLDCOLOR; + } else { + internal_flags &= ~IFLAGS_OLDCOLOR; + } apple_memory[address] = value; break; case 0x02: diff --git a/vga/hires_dot_patterns.h b/vga/hires_dot_patterns.h index 5ec8e7b..0366683 100644 --- a/vga/hires_dot_patterns.h +++ b/vga/hires_dot_patterns.h @@ -39,3 +39,70 @@ static uint16_t DELAYED_COPY_DATA(hires_dot_patterns)[256] = { 0x001f,0x181f,0x061f,0x1e1f,0x019f,0x199f,0x079f,0x1f9f, 0x007f,0x187f,0x067f,0x1e7f,0x01ff,0x19ff,0x07ff,0x1fff, }; + +static uint16_t DELAYED_COPY_DATA(hires_dot_patterns2)[512] = { + 0b0000000000000000,0b0000000000000011,0b0000000000001100,0b0000000000001111,0b0000000000110000,0b0000000000110011,0b0000000000111100,0b0000000000111111, + 0b0000000011000000,0b0000000011000011,0b0000000011001100,0b0000000011001111,0b0000000011110000,0b0000000011110011,0b0000000011111100,0b0000000011111111, + 0b0000001100000000,0b0000001100000011,0b0000001100001100,0b0000001100001111,0b0000001100110000,0b0000001100110011,0b0000001100111100,0b0000001100111111, + 0b0000001111000000,0b0000001111000011,0b0000001111001100,0b0000001111001111,0b0000001111110000,0b0000001111110011,0b0000001111111100,0b0000001111111111, + 0b0000110000000000,0b0000110000000011,0b0000110000001100,0b0000110000001111,0b0000110000110000,0b0000110000110011,0b0000110000111100,0b0000110000111111, + 0b0000110011000000,0b0000110011000011,0b0000110011001100,0b0000110011001111,0b0000110011110000,0b0000110011110011,0b0000110011111100,0b0000110011111111, + 0b0000111100000000,0b0000111100000011,0b0000111100001100,0b0000111100001111,0b0000111100110000,0b0000111100110011,0b0000111100111100,0b0000111100111111, + 0b0000111111000000,0b0000111111000011,0b0000111111001100,0b0000111111001111,0b0000111111110000,0b0000111111110011,0b0000111111111100,0b0000111111111111, + 0b0011000000000000,0b0011000000000011,0b0011000000001100,0b0011000000001111,0b0011000000110000,0b0011000000110011,0b0011000000111100,0b0011000000111111, + 0b0011000011000000,0b0011000011000011,0b0011000011001100,0b0011000011001111,0b0011000011110000,0b0011000011110011,0b0011000011111100,0b0011000011111111, + 0b0011001100000000,0b0011001100000011,0b0011001100001100,0b0011001100001111,0b0011001100110000,0b0011001100110011,0b0011001100111100,0b0011001100111111, + 0b0011001111000000,0b0011001111000011,0b0011001111001100,0b0011001111001111,0b0011001111110000,0b0011001111110011,0b0011001111111100,0b0011001111111111, + 0b0011110000000000,0b0011110000000011,0b0011110000001100,0b0011110000001111,0b0011110000110000,0b0011110000110011,0b0011110000111100,0b0011110000111111, + 0b0011110011000000,0b0011110011000011,0b0011110011001100,0b0011110011001111,0b0011110011110000,0b0011110011110011,0b0011110011111100,0b0011110011111111, + 0b0011111100000000,0b0011111100000011,0b0011111100001100,0b0011111100001111,0b0011111100110000,0b0011111100110011,0b0011111100111100,0b0011111100111111, + 0b0011111111000000,0b0011111111000011,0b0011111111001100,0b0011111111001111,0b0011111111110000,0b0011111111110011,0b0011111111111100,0b0011111111111111, + 0b0000000000000000,0b0000000000000110,0b0000000000011000,0b0000000000011110,0b0000000001100000,0b0000000001100110,0b0000000001111000,0b0000000001111110, + 0b0000000110000000,0b0000000110000110,0b0000000110011000,0b0000000110011110,0b0000000111100000,0b0000000111100110,0b0000000111111000,0b0000000111111110, + 0b0000011000000000,0b0000011000000110,0b0000011000011000,0b0000011000011110,0b0000011001100000,0b0000011001100110,0b0000011001111000,0b0000011001111110, + 0b0000011110000000,0b0000011110000110,0b0000011110011000,0b0000011110011110,0b0000011111100000,0b0000011111100110,0b0000011111111000,0b0000011111111110, + 0b0001100000000000,0b0001100000000110,0b0001100000011000,0b0001100000011110,0b0001100001100000,0b0001100001100110,0b0001100001111000,0b0001100001111110, + 0b0001100110000000,0b0001100110000110,0b0001100110011000,0b0001100110011110,0b0001100111100000,0b0001100111100110,0b0001100111111000,0b0001100111111110, + 0b0001111000000000,0b0001111000000110,0b0001111000011000,0b0001111000011110,0b0001111001100000,0b0001111001100110,0b0001111001111000,0b0001111001111110, + 0b0001111110000000,0b0001111110000110,0b0001111110011000,0b0001111110011110,0b0001111111100000,0b0001111111100110,0b0001111111111000,0b0001111111111110, + 0b0110000000000000,0b0110000000000110,0b0110000000011000,0b0110000000011110,0b0110000001100000,0b0110000001100110,0b0110000001111000,0b0110000001111110, + 0b0110000110000000,0b0110000110000110,0b0110000110011000,0b0110000110011110,0b0110000111100000,0b0110000111100110,0b0110000111111000,0b0110000111111110, + 0b0110011000000000,0b0110011000000110,0b0110011000011000,0b0110011000011110,0b0110011001100000,0b0110011001100110,0b0110011001111000,0b0110011001111110, + 0b0110011110000000,0b0110011110000110,0b0110011110011000,0b0110011110011110,0b0110011111100000,0b0110011111100110,0b0110011111111000,0b0110011111111110, + 0b0111100000000000,0b0111100000000110,0b0111100000011000,0b0111100000011110,0b0111100001100000,0b0111100001100110,0b0111100001111000,0b0111100001111110, + 0b0111100110000000,0b0111100110000110,0b0111100110011000,0b0111100110011110,0b0111100111100000,0b0111100111100110,0b0111100111111000,0b0111100111111110, + 0b0111111000000000,0b0111111000000110,0b0111111000011000,0b0111111000011110,0b0111111001100000,0b0111111001100110,0b0111111001111000,0b0111111001111110, + 0b0111111110000000,0b0111111110000110,0b0111111110011000,0b0111111110011110,0b0111111111100000,0b0111111111100110,0b0111111111111000,0b0111111111111110, + 0b0000000000000000,0b0000000000000011,0b0000000000001100,0b0000000000001111,0b0000000000110000,0b0000000000110011,0b0000000000111100,0b0000000000111111, + 0b0000000011000000,0b0000000011000011,0b0000000011001100,0b0000000011001111,0b0000000011110000,0b0000000011110011,0b0000000011111100,0b0000000011111111, + 0b0000001100000000,0b0000001100000011,0b0000001100001100,0b0000001100001111,0b0000001100110000,0b0000001100110011,0b0000001100111100,0b0000001100111111, + 0b0000001111000000,0b0000001111000011,0b0000001111001100,0b0000001111001111,0b0000001111110000,0b0000001111110011,0b0000001111111100,0b0000001111111111, + 0b0000110000000000,0b0000110000000011,0b0000110000001100,0b0000110000001111,0b0000110000110000,0b0000110000110011,0b0000110000111100,0b0000110000111111, + 0b0000110011000000,0b0000110011000011,0b0000110011001100,0b0000110011001111,0b0000110011110000,0b0000110011110011,0b0000110011111100,0b0000110011111111, + 0b0000111100000000,0b0000111100000011,0b0000111100001100,0b0000111100001111,0b0000111100110000,0b0000111100110011,0b0000111100111100,0b0000111100111111, + 0b0000111111000000,0b0000111111000011,0b0000111111001100,0b0000111111001111,0b0000111111110000,0b0000111111110011,0b0000111111111100,0b0000111111111111, + 0b0011000000000000,0b0011000000000011,0b0011000000001100,0b0011000000001111,0b0011000000110000,0b0011000000110011,0b0011000000111100,0b0011000000111111, + 0b0011000011000000,0b0011000011000011,0b0011000011001100,0b0011000011001111,0b0011000011110000,0b0011000011110011,0b0011000011111100,0b0011000011111111, + 0b0011001100000000,0b0011001100000011,0b0011001100001100,0b0011001100001111,0b0011001100110000,0b0011001100110011,0b0011001100111100,0b0011001100111111, + 0b0011001111000000,0b0011001111000011,0b0011001111001100,0b0011001111001111,0b0011001111110000,0b0011001111110011,0b0011001111111100,0b0011001111111111, + 0b0011110000000000,0b0011110000000011,0b0011110000001100,0b0011110000001111,0b0011110000110000,0b0011110000110011,0b0011110000111100,0b0011110000111111, + 0b0011110011000000,0b0011110011000011,0b0011110011001100,0b0011110011001111,0b0011110011110000,0b0011110011110011,0b0011110011111100,0b0011110011111111, + 0b0011111100000000,0b0011111100000011,0b0011111100001100,0b0011111100001111,0b0011111100110000,0b0011111100110011,0b0011111100111100,0b0011111100111111, + 0b0011111111000000,0b0011111111000011,0b0011111111001100,0b0011111111001111,0b0011111111110000,0b0011111111110011,0b0011111111111100,0b0011111111111111, + 0b0000000000000001,0b0000000000000111,0b0000000000011001,0b0000000000011111,0b0000000001100001,0b0000000001100111,0b0000000001111001,0b0000000001111111, + 0b0000000110000001,0b0000000110000111,0b0000000110011001,0b0000000110011111,0b0000000111100001,0b0000000111100111,0b0000000111111001,0b0000000111111111, + 0b0000011000000001,0b0000011000000111,0b0000011000011001,0b0000011000011111,0b0000011001100001,0b0000011001100111,0b0000011001111001,0b0000011001111111, + 0b0000011110000001,0b0000011110000111,0b0000011110011001,0b0000011110011111,0b0000011111100001,0b0000011111100111,0b0000011111111001,0b0000011111111111, + 0b0001100000000001,0b0001100000000111,0b0001100000011001,0b0001100000011111,0b0001100001100001,0b0001100001100111,0b0001100001111001,0b0001100001111111, + 0b0001100110000001,0b0001100110000111,0b0001100110011001,0b0001100110011111,0b0001100111100001,0b0001100111100111,0b0001100111111001,0b0001100111111111, + 0b0001111000000001,0b0001111000000111,0b0001111000011001,0b0001111000011111,0b0001111001100001,0b0001111001100111,0b0001111001111001,0b0001111001111111, + 0b0001111110000001,0b0001111110000111,0b0001111110011001,0b0001111110011111,0b0001111111100001,0b0001111111100111,0b0001111111111001,0b0001111111111111, + 0b0110000000000001,0b0110000000000111,0b0110000000011001,0b0110000000011111,0b0110000001100001,0b0110000001100111,0b0110000001111001,0b0110000001111111, + 0b0110000110000001,0b0110000110000111,0b0110000110011001,0b0110000110011111,0b0110000111100001,0b0110000111100111,0b0110000111111001,0b0110000111111111, + 0b0110011000000001,0b0110011000000111,0b0110011000011001,0b0110011000011111,0b0110011001100001,0b0110011001100111,0b0110011001111001,0b0110011001111111, + 0b0110011110000001,0b0110011110000111,0b0110011110011001,0b0110011110011111,0b0110011111100001,0b0110011111100111,0b0110011111111001,0b0110011111111111, + 0b0111100000000001,0b0111100000000111,0b0111100000011001,0b0111100000011111,0b0111100001100001,0b0111100001100111,0b0111100001111001,0b0111100001111111, + 0b0111100110000001,0b0111100110000111,0b0111100110011001,0b0111100110011111,0b0111100111100001,0b0111100111100111,0b0111100111111001,0b0111100111111111, + 0b0111111000000001,0b0111111000000111,0b0111111000011001,0b0111111000011111,0b0111111001100001,0b0111111001100111,0b0111111001111001,0b0111111001111111, + 0b0111111110000001,0b0111111110000111,0b0111111110011001,0b0111111110011111,0b0111111111100001,0b0111111111100111,0b0111111111111001,0b0111111111111111, +}; diff --git a/vga/render.h b/vga/render.h index e10143a..b5f45ac 100644 --- a/vga/render.h +++ b/vga/render.h @@ -57,12 +57,14 @@ extern void vga_deinit(); (((((uint)(g) * 256 / 18) + 256) / 256) << 4) | \ ((((uint)(b) * 256 / 18) + 256) / 256) \ ) +#define _RGBHALF 0x777 #else #define _RGB(r, g, b) ( \ (((((uint)(r) * 256 / 36) + 128) / 256) << 6) | \ (((((uint)(g) * 256 / 36) + 128) / 256) << 3) | \ ((((uint)(b) * 256 / 36) + 128) / 256) \ ) +#define _RGBHALF 0x0DB #endif #define RGB_BLACK _RGB(0x00,0x00,0x00) diff --git a/vga/render_dgr.c b/vga/render_dgr.c index 3aac52e..ea58d30 100644 --- a/vga/render_dgr.c +++ b/vga/render_dgr.c @@ -7,8 +7,14 @@ //#define PAGE2SEL (!(soft_switches & SOFTSW_80STORE) && (soft_switches & SOFTSW_PAGE_2)) #define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2) -extern uint16_t lores_palette[16]; -extern uint16_t lores_dot_pattern[16]; +extern uint16_t dhgr_palette[16]; + +uint8_t DELAYED_COPY_DATA(dgr_dot_pattern)[32] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x08, 0x19, 0x2A, 0x3B, 0x4C, 0x5D, 0x6E, 0x7F, + 0x00, 0x44, 0x08, 0x4C, 0x11, 0x55, 0x19, 0x5D, + 0x22, 0x66, 0x2A, 0x6E, 0x33, 0x77, 0x3B, 0x7F, +}; static void render_dgr_line(bool p2, uint line); @@ -40,7 +46,9 @@ static void DELAYED_COPY_CODE(render_dgr_line)(bool p2, uint line) { struct vga_scanline *sl2 = vga_prepare_scanline(); uint sl_pos = 0; uint i, j; - uint32_t color1, color2, color3, color4; + uint32_t color1, color2; + uint_fast8_t dotc = 0; + uint32_t pixeldata; const uint8_t *line_bufa = (const uint8_t *)((p2 ? text_p2 : text_p1) + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40)); const uint8_t *line_bufb = (const uint8_t *)((p2 ? text_p4 : text_p3) + ((line & 0x7) << 7) + (((line >> 3) & 0x3) * 40)); @@ -56,42 +64,105 @@ static void DELAYED_COPY_CODE(render_dgr_line)(bool p2, uint line) { sl2->data[sl_pos] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 8 pixels per word sl_pos++; - + i = 0; if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) { - for(i = 0; i < 40; i++) { - color1 = lores_dot_pattern[line_bufb[i] & 0xf] << 21; - color2 = lores_dot_pattern[(line_bufb[i] >> 4) & 0xf] << 21; - color1 |= lores_dot_pattern[line_bufa[i] & 0xf] << 7; - color2 |= lores_dot_pattern[(line_bufa[i] >> 4) & 0xf] << 7; + while(i < 40) { + while((dotc <= 18) && (i < 40)) { + color1 |= dgr_dot_pattern[((i & 1) << 4) | (line_bufb[i] & 0xf)] << dotc; + color2 |= dgr_dot_pattern[((i & 1) << 4) | ((line_bufb[i] >> 4) & 0xf)] << dotc; + dotc += 7; + color1 |= dgr_dot_pattern[((i & 1) << 4) | (line_bufa[i] & 0xf)] << dotc; + color2 |= dgr_dot_pattern[((i & 1) << 4) | ((line_bufa[i] >> 4) & 0xf)] << dotc; + dotc += 7; + i++; + } - for(j = 0; j < 7; j++) { - uint32_t pixeldata; - - pixeldata = (color1 & 0x8000000) ? (text_fore) : (text_back); - pixeldata |= (color1 & 0x4000000) ? ((text_fore) << 16) : ((text_back) << 16); - color1 <<= 2; + // Consume pixels + while(dotc >= 2) { + pixeldata = ((color1 & 1) ? (text_fore) : (text_back)); + pixeldata |= (((color1 & 2) ? (text_fore) : (text_back))) << 16; sl1->data[sl_pos] = pixeldata; - pixeldata = (color2 & 0x8000000) ? (text_fore) : (text_back); - pixeldata |= (color2 & 0x4000000) ? ((text_fore) << 16) : ((text_back) << 16); + pixeldata = ((color2 & 1) ? (text_fore) : (text_back)); + pixeldata |= (((color2 & 2) ? (text_fore) : (text_back))) << 16; sl2->data[sl_pos] = pixeldata; - color2 <<= 2; + color1 >>= 2; + color2 >>= 2; sl_pos++; + dotc -= 2; } } } else { - for(i=0; i < 40; i++) { - color1 = lores_palette[line_bufb[i] & 0xf]; - color2 = lores_palette[(line_bufb[i] >> 4) & 0xf]; - color3 = lores_palette[line_bufa[i] & 0xf]; - color4 = lores_palette[(line_bufa[i] >> 4) & 0xf]; + // Preload the first 14 subpixels + color1 = dgr_dot_pattern[line_bufb[i] & 0xf] << dotc; + color2 = dgr_dot_pattern[(line_bufb[i] >> 4) & 0xf] << dotc; + dotc += 7; + color1 |= dgr_dot_pattern[(line_bufa[i] & 0xf)] << dotc; + color2 |= dgr_dot_pattern[((line_bufa[i] >> 4) & 0xf)] << dotc; + dotc += 7; + i++; - // Each double lores pixel is 7 double hires pixels, or 7 VGA pixels wide - sl1->data[sl_pos] = (color1|THEN_EXTEND_6) | ((color3|THEN_EXTEND_6) << 16); - sl2->data[sl_pos] = (color2|THEN_EXTEND_6) | ((color4|THEN_EXTEND_6) << 16); - sl_pos++; + // First two pixels + pixeldata = dhgr_palette[0]; + pixeldata |= ((dhgr_palette[color1 & 0xf] >> 1) & _RGBHALF) << 16; + sl1->data[sl_pos] = pixeldata; + + pixeldata = dhgr_palette[0]; + pixeldata |= ((dhgr_palette[color1 & 0xf] >> 1) & _RGBHALF) << 16; + sl2->data[sl_pos] = pixeldata; + sl_pos++; + + while(i < 40) { + // Load in as many subpixels as possible + while((dotc <= 18) && (i < 40)) { + color1 |= dgr_dot_pattern[((i & 1) << 4) | (line_bufb[i] & 0xf)] << dotc; + color2 |= dgr_dot_pattern[((i & 1) << 4) | ((line_bufb[i] >> 4) & 0xf)] << dotc; + dotc += 7; + color1 |= dgr_dot_pattern[((i & 1) << 4) | (line_bufa[i] & 0xf)] << dotc; + color2 |= dgr_dot_pattern[((i & 1) << 4) | ((line_bufa[i] >> 4) & 0xf)] << dotc; + dotc += 7; + i++; + } + + // Consume pixels + while(dotc >= 8) { + pixeldata = (dhgr_palette[color1 & 0xf]); + pixeldata |= ((dhgr_palette[color1 & 0xf] >> 1) & _RGBHALF) << 16; + sl1->data[sl_pos] = pixeldata; + + pixeldata = (dhgr_palette[color2 & 0xf]); + pixeldata |= ((dhgr_palette[color2 & 0xf] >> 1) & _RGBHALF) << 16; + sl2->data[sl_pos] = pixeldata; + + sl_pos++; + + pixeldata = (dhgr_palette[(color1 & 0xc) | ((color1 & 0x30) >> 4)]); + pixeldata |= ((dhgr_palette[(color1 & 0xf0) >> 4] >> 1) & _RGBHALF) << 16; + sl1->data[sl_pos] = pixeldata; + + pixeldata = (dhgr_palette[(color2 & 0xc) | ((color2 & 0x30) >> 4)]); + pixeldata |= ((dhgr_palette[(color2 & 0xf0) >> 4] >> 1) & _RGBHALF) << 16; + sl2->data[sl_pos] = pixeldata; + + sl_pos++; + + color1 >>= 4; + color2 >>= 4; + dotc -= 4; + } } + + // Last two pixels + pixeldata = (dhgr_palette[color1 & 0xf]); + pixeldata |= ((dhgr_palette[color1 & 0xf] >> 1) & _RGBHALF) << 16; + sl1->data[sl_pos] = pixeldata; + + pixeldata = (dhgr_palette[color2 & 0xf]); + pixeldata |= ((dhgr_palette[color2 & 0xf] >> 1) & _RGBHALF) << 16; + sl2->data[sl_pos] = pixeldata; + + sl_pos++; } // Pad 40 pixels on the right to center horizontally diff --git a/vga/render_dhgr.c b/vga/render_dhgr.c index ed5d67d..cdc3e70 100644 --- a/vga/render_dhgr.c +++ b/vga/render_dhgr.c @@ -61,67 +61,92 @@ static void DELAYED_COPY_CODE(render_dhgr_line)(bool p2, uint line) { // DHGR is weird. Nuff said. uint32_t dots = 0; + uint_fast8_t dotc = 0; uint32_t pixeldata; - int j; i = 0; - while(i < 40) { - // Load in the next 28 subpixels - dots = (line_memb[i] & 0x7f) << 0; - dots |= (line_mema[i] & 0x7f) << 7; - i++; - dots |= (line_memb[i] & 0x7f) << 14; - dots |= (line_mema[i] & 0x7f) << 21; - i++; + if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) { + while(i < 40) { + // Load in as many subpixels as possible + while((dotc < 28) && (i < 40)) { + dots |= (line_memb[i] & 0x7f) << dotc; + dotc += 7; + dots |= (line_mema[i] & 0x7f) << dotc; + dotc += 7; + i++; + } - if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) { - // Consume 6 pixels (24 subpixel bits) - for(j = 0; j < 12; j++) { + // Consume pixels + while(dotc) { pixeldata = ((dots & 1) ? (text_fore) : (text_back)); dots >>= 1; pixeldata |= (((dots & 1) ? (text_fore) : (text_back))) << 16; dots >>= 1; sl->data[sl_pos++] = pixeldata; + dotc -= 2; } - } else { - // Consume 6 pixels (24 subpixel bits) - for(j = 0; j < 3; j++) { + } + } else if(internal_flags & IFLAGS_OLDCOLOR) { + while(i < 40) { + // Load in as many subpixels as possible + while((dotc <= 18) && (i < 40)) { + dots |= (line_memb[i] & 0x7f) << dotc; + dotc += 7; + dots |= (line_mema[i] & 0x7f) << dotc; + dotc += 7; + i++; + } + + // Consume pixels + while(dotc >= 8) { pixeldata = (dhgr_palette[dots & 0xf] | THEN_EXTEND_3); dots >>= 4; pixeldata |= (dhgr_palette[dots & 0xf] | THEN_EXTEND_3) << 16; dots >>= 4; sl->data[sl_pos++] = pixeldata; + dotc -= 8; + } + } + } else { + // Preload the first 14 subpixels + dots |= (line_memb[i] & 0x7f) << dotc; + dotc += 7; + dots |= (line_mema[i] & 0x7f) << dotc; + dotc += 7; + i++; + + // First two pixels + pixeldata = dhgr_palette[0]; + pixeldata |= ((dhgr_palette[dots & 0xf] >> 1) & _RGBHALF) << 16; + sl->data[sl_pos++] = pixeldata; + + while(i < 40) { + // Load in as many subpixels as possible + while((dotc <= 18) && (i < 40)) { + dots |= (line_memb[i] & 0x7f) << dotc; + dotc += 7; + dots |= (line_mema[i] & 0x7f) << dotc; + dotc += 7; + i++; + } + + // Consume pixels + while(dotc >= 8) { + pixeldata = (dhgr_palette[dots & 0xf]); + pixeldata |= ((dhgr_palette[dots & 0xf] >> 1) & _RGBHALF) << 16; + sl->data[sl_pos++] = pixeldata; + pixeldata = (dhgr_palette[(dots & 0xc) | ((dots & 0x30) >> 4)]); + pixeldata |= ((dhgr_palette[(dots & 0xf0) >> 4] >> 1) & _RGBHALF) << 16; + sl->data[sl_pos++] = pixeldata; + dots >>= 4; + dotc -= 4; } } - // 4 subpixels roll over to the next block - // Load in the next 28 subpixels - dots |= (line_memb[i] & 0x7f) << 4; - dots |= (line_mema[i] & 0x7f) << 11; - i++; - dots |= (line_memb[i] & 0x7f) << 18; - dots |= (line_mema[i] & 0x7f) << 25; - i++; - - if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) { - // Consume 8 pixels (32 subpixel bits) - for(j = 0; j < 16; j++) { - pixeldata = ((dots & 1) ? (text_fore) : (text_back)); - dots >>= 1; - pixeldata |= (((dots & 1) ? (text_fore) : (text_back))) << 16; - dots >>= 1; - sl->data[sl_pos++] = pixeldata; - } - } else { - // Consume 8 pixels (32 subpixel bits) - for(j = 0; j < 4; j++) { - pixeldata = (dhgr_palette[dots & 0xf] | THEN_EXTEND_3); - dots >>= 4; - pixeldata |= (dhgr_palette[dots & 0xf] | THEN_EXTEND_3) << 16; - dots >>= 4; - sl->data[sl_pos++] = pixeldata; - } - } + // Last two pixels + pixeldata = (dhgr_palette[dots & 0xf]); + pixeldata |= ((dhgr_palette[dots & 0xf] >> 1) & _RGBHALF) << 16; + sl->data[sl_pos++] = pixeldata; } // Pad 40 pixels on the right to center horizontally diff --git a/vga/render_hires.c b/vga/render_hires.c index 987fd7e..8dac829 100644 --- a/vga/render_hires.c +++ b/vga/render_hires.c @@ -10,6 +10,7 @@ #define PAGE2SEL ((soft_switches & (SOFTSW_80STORE | SOFTSW_PAGE_2)) == SOFTSW_PAGE_2) static void render_hires_line(bool p2, uint line); +extern uint16_t dhgr_palette[16]; static inline uint hires_line_to_mem_offset(uint line) { return ((line & 0x07) << 10) | ((line & 0x38) << 4) | (((line & 0xc0) >> 6) * 40); @@ -37,7 +38,6 @@ void DELAYED_COPY_CODE(render_mixed_hires)() { } } - static void DELAYED_COPY_CODE(render_hires_line)(bool p2, uint line) { struct vga_scanline *sl = vga_prepare_scanline(); uint sl_pos = 0; @@ -49,52 +49,66 @@ static void DELAYED_COPY_CODE(render_hires_line)(bool p2, uint line) { sl->data[sl_pos++] = (text_border|THEN_EXTEND_7) | ((text_border|THEN_EXTEND_7) << 16); // 16 pixels per word sl->data[sl_pos++] = (text_border|THEN_EXTEND_3) | ((text_border|THEN_EXTEND_3) << 16); // 16 pixels per word - // Each hires byte contains 7 pixels which may be shifted right 1/2 a pixel. That is - // represented here by 14 'dots' to precisely describe the half-pixel positioning. - // - // For each pixel, inspect a window of 8 dots around the pixel to determine the - // precise dot locations and colors. - // - // Dots would be scanned out to the CRT from MSB to LSB (left to right here): - // - // previous | next - // dots | dots - // +-------------------+--------------------------------------------------+ - // dots: | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | ... | 14 | 13 | 12 | ... - // | | | | - // \______________|_________|______________/ - // | | - // \_________/ - // current - // pixel + uint32_t lastmsb = 0; uint32_t dots = 0; - uint oddness = 0; - uint i, j; + uint_fast8_t dotc = 0; + uint32_t pixeldata; + uint i; - // Load in the first 14 dots - dots |= (uint32_t)hires_dot_patterns[line_mem[0]] << 15; - - for(i=1; i < 41; i++) { - // Load in the next 14 dots - uint b = (i < 40) ? line_mem[i] : 0; - if(b & 0x80) { - // Extend the last bit from the previous byte - dots |= (dots & (1u << 15)) >> 1; - } - dots |= (uint32_t)hires_dot_patterns[b] << 1; - - if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) { - // Consume 14 dots - for(j = 0; j < 7; j++) { - uint32_t pixeldata = (dots & 0x40000000) ? (text_fore) : (text_back); - pixeldata |= (dots & 0x20000000) ? - ((text_fore) << 16) : - ((text_back) << 16); - dots <<= 2; - sl->data[sl_pos] = pixeldata; - sl_pos++; + if((soft_switches & SOFTSW_MONOCHROME) || (mono_palette & 0x8)) { + while(i < 40) { + // Load in as many subpixels as possible + while((dotc < 18) && (i < 40)) { + dots |= (hires_dot_patterns2[lastmsb | line_mem[i]]) << dotc; + lastmsb = (dotc>0) ? ((line_mem[i] & 0x40)<<2) : 0; + i++; + dotc += 14; } - } else { + + // Consume pixels + while(dotc) { + pixeldata = ((dots & 1) ? (text_fore) : (text_back)); + dots >>= 1; + pixeldata |= (((dots & 1) ? (text_fore) : (text_back))) << 16; + dots >>= 1; + sl->data[sl_pos++] = pixeldata; + dotc -= 2; + } + } + } else if(internal_flags & IFLAGS_OLDCOLOR) { + // Each hires byte contains 7 pixels which may be shifted right 1/2 a pixel. That is + // represented here by 14 'dots' to precisely describe the half-pixel positioning. + // + // For each pixel, inspect a window of 8 dots around the pixel to determine the + // precise dot locations and colors. + // + // Dots would be scanned out to the CRT from MSB to LSB (left to right here): + // + // previous | next + // dots | dots + // +-------------------+--------------------------------------------------+ + // dots: | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | ... | 14 | 13 | 12 | ... + // | | | | + // \______________|_________|______________/ + // | | + // \_________/ + // current + // pixel + uint oddness = 0; + uint j; + + // Load in the first 14 dots + dots |= (uint32_t)hires_dot_patterns[line_mem[0]] << 15; + + for(i=1; i < 41; i++) { + // Load in the next 14 dots + uint b = (i < 40) ? line_mem[i] : 0; + if(b & 0x80) { + // Extend the last bit from the previous byte + dots |= (dots & (1u << 15)) >> 1; + } + dots |= (uint32_t)hires_dot_patterns[b] << 1; + // Consume 14 dots for(uint j=0; j < 7; j++) { uint dot_pattern = oddness | ((dots >> 24) & 0xff); @@ -104,6 +118,44 @@ static void DELAYED_COPY_CODE(render_hires_line)(bool p2, uint line) { oddness ^= 0x100; } } + } else { + // Preload the first 14 subpixels + dots = (hires_dot_patterns2[line_mem[i]]); + lastmsb = (dotc>0) ? ((line_mem[i] & 0x40)<<2) : 0; + i++; + dotc = 14; + + // First two pixels + pixeldata = lores_palette[0]; + pixeldata |= ((lores_palette[dots & 0xf] >> 1) & _RGBHALF) << 16; + sl->data[sl_pos++] = pixeldata; + + while(i < 40) { + // Load in as many subpixels as possible + if((dotc < 18) && (i < 40)) { + dots |= (hires_dot_patterns2[lastmsb | line_mem[i]]) << dotc; + lastmsb = (dotc>0) ? ((line_mem[i] & 0x40)<<2) : 0; + i++; + dotc += 14; + } + + // Consume pixels + while(dotc >= 8) { + pixeldata = (lores_palette[dots & 0xf]); + pixeldata |= ((lores_palette[dots & 0xf] >> 1) & _RGBHALF) << 16; + sl->data[sl_pos++] = pixeldata; + pixeldata = (lores_palette[(dots & 0xc) | ((dots & 0x30) >> 4)]); + pixeldata |= ((lores_palette[(dots & 0xf0) >> 4] >> 1) & _RGBHALF) << 16; + sl->data[sl_pos++] = pixeldata; + dots >>= 4; + dotc -= 4; + } + } + + // Last two pixels + pixeldata = (lores_palette[dots & 0xf]); + pixeldata |= ((lores_palette[dots & 0xf] >> 1) & _RGBHALF) << 16; + sl->data[sl_pos++] = pixeldata; } // Pad 40 pixels on the right to center horizontally