From d07815a94f78fa5a3bfc9f02a16ba62c9854d439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net> Date: Sun, 3 Nov 2024 00:12:56 -0400 Subject: [PATCH] Implement double-height. This is so gross... outputting any character depends on every character above it, so it must be checked every time. If the state was ste up differently, this could be avoided, but it's not, so it can't. For v2, I'm going to want to store some per-line data in a separate struct so I can track this. --- src/conio/bitmap_con.c | 86 +++++++++++++++++++++++++++++++++++++++++- src/conio/cterm.c | 58 ++++++++++++++++++++++++---- 2 files changed, 135 insertions(+), 9 deletions(-) diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c index 5ff88585df..4538d9b650 100644 --- a/src/conio/bitmap_con.c +++ b/src/conio/bitmap_con.c @@ -541,6 +541,9 @@ static int bitmap_draw_one_char(struct vmem_cell *vc, unsigned int xpos, unsigne WORD sch; BOOL draw_fg = TRUE; size_t rsz; + bool double_height = false; + bool bottom = false; + bool top = false; if(!bitmap_initialized) { return(-1); @@ -596,6 +599,58 @@ static int bitmap_draw_one_char(struct vmem_cell *vc, unsigned int xpos, unsigne pixeloffset = PIXEL_OFFSET(screena, xoffset, yoffset); rsz = screena.screenwidth - vstat.charwidth; + // PRESTEL! + if (vstat.mode == PRESTEL_40X24) { + struct vstat_vmem *vmem_ptr = get_vmem(&vstat); + + if (ypos > 1) { + for (y = 0; y < ypos; y++) { + if (top) { + bottom = true; + top = false; + } + else { + if (bottom) + bottom = false; + else { + if (y == ypos - 1) + break; + for (x = 0; x < vstat.cols; x++) { + if (vmem_ptr->vmem[y * vstat.cols + x].bg & 0x01000000) { + top = true; + break; + } + } + } + } + } + } + if (bottom) { + if (vmem_ptr->vmem[(ypos - 2) * vstat.cols + (xpos - 1)].bg & 0x01000000) { + double_height = true; + } + fg = vmem_ptr->vmem[(ypos - 2) * vstat.cols + (xpos - 1)].fg; + bg = vmem_ptr->vmem[(ypos - 2) * vstat.cols + (xpos - 1)].bg; + } + else { + if (ypos != vstat.rows) { + if (vmem_ptr->vmem[(ypos - 1) * vstat.cols + (xpos - 1)].bg & 0x01000000) { + top = true; + double_height = true; + } + } + } + // Draw as space if not double-bottom + if (bottom) { + if (double_height) { + pixeloffset -= vstat.charheight * vstat.scrnwidth; + fontoffset=(vmem_ptr->vmem[(ypos - 2) * vstat.cols + (xpos - 1)].ch) * (vstat.charheight * ((fdw + 7) / 8)); + } + else + fontoffset=(32) * (vstat.charheight * ((fdw + 7) / 8)); + } + release_vmem(vmem_ptr); + } for (y = 0; y < vstat.charheight; y++) { for(x = 0; x < vstat.charwidth; x++) { fdx = x; @@ -624,12 +679,24 @@ static int bitmap_draw_one_char(struct vmem_cell *vc, unsigned int xpos, unsigne screena.update_pixels = 1; screena.rect->data[pixeloffset] = fg; } + if (double_height) { + if (screena.rect->data[pixeloffset+screena.screenwidth] != fg) { + screena.update_pixels = 1; + screena.rect->data[pixeloffset+screena.screenwidth] = fg; + } + } } else { if (screena.rect->data[pixeloffset] != bg) { screena.update_pixels = 1; screena.rect->data[pixeloffset] = bg; } + if (double_height) { + if (screena.rect->data[pixeloffset+screena.screenwidth] != bg) { + screena.update_pixels = 1; + screena.rect->data[pixeloffset+screena.screenwidth] = bg; + } + } } if(fbb) { @@ -637,18 +704,35 @@ static int bitmap_draw_one_char(struct vmem_cell *vc, unsigned int xpos, unsigne screenb.update_pixels = 1; screenb.rect->data[pixeloffset] = fg; } + if (double_height) { + if (screenb.rect->data[pixeloffset+screena.screenwidth] != fg) { + screenb.update_pixels = 1; + screenb.rect->data[pixeloffset+screena.screenwidth] = fg; + } + } } else { if (screenb.rect->data[pixeloffset] != bg) { screenb.update_pixels = 1; screenb.rect->data[pixeloffset] = bg; } + if (double_height) { + if (screenb.rect->data[pixeloffset+screena.screenwidth] != bg) { + screenb.update_pixels = 1; + screenb.rect->data[pixeloffset+screena.screenwidth] = bg; + } + } } pixeloffset++; } - if (x & 0x07) + if (x & 0x07) { fontoffset++; + if (double_height && ((y & 1) == 0)) + fontoffset--; + } pixeloffset += rsz; + if (double_height) + pixeloffset += screena.screenwidth; } pthread_mutex_unlock(&screenlock); diff --git a/src/conio/cterm.c b/src/conio/cterm.c index 9c58a68ea1..f955a484c7 100644 --- a/src/conio/cterm.c +++ b/src/conio/cterm.c @@ -796,6 +796,10 @@ set_attr(struct cterminal *cterm, unsigned char colour, bool bg) cterm->attr |= (colour & 0x07); } attr2palette(cterm->attr, bg ? NULL : &cterm->fg_color, bg ? &cterm->bg_color : NULL); + if (cterm->emulation == CTERM_EMULATION_PRESTEL) { + if (cterm->extattr & CTERM_EXTATTR_PRESTEL_DOUBLE_HEIGHT) + cterm->bg_color |= 0x01000000; + } if (bg) FREE_AND_NULL(cterm->bg_tc_str); else @@ -832,9 +836,12 @@ prestel_apply_ctrl_before(struct cterminal *cterm, uint8_t ch) case 73: // Steady cterm->attr &= 0x7f; attr2palette(cterm->attr, &cterm->fg_color, &cterm->bg_color); + if (CTERM_EXTATTR_PRESTEL_DOUBLE_HEIGHT) + cterm->bg_color |= 0x01000000; break; case 76: // Normal Height cterm->extattr &= ~(CTERM_EXTATTR_PRESTEL_DOUBLE_HEIGHT); + cterm->bg_color &= ~0x01000000; cterm->prestel_last_mosaic = 32; break; case 88: // Conceal Display @@ -908,9 +915,12 @@ prestel_apply_ctrl_after(struct cterminal *cterm, uint8_t ch) case 72: // Flash cterm->attr |= 0x80; attr2palette(cterm->attr, &cterm->fg_color, &cterm->bg_color); + if (cterm->extattr & CTERM_EXTATTR_PRESTEL_DOUBLE_HEIGHT) + cterm->bg_color |= 0x01000000; break; case 77: // Double Height cterm->extattr |= CTERM_EXTATTR_PRESTEL_DOUBLE_HEIGHT; + cterm->bg_color |= 0x01000000; cterm->prestel_last_mosaic = 32; break; case 80: // Mosaic Black @@ -4948,7 +4958,7 @@ void cterm_start(struct cterminal *cterm) * - Format effector added or removed * - Hold mosaic character changed */ -static void prestel_fix_line(struct cterminal *cterm, int x, int y) +static void prestel_fix_line(struct cterminal *cterm, int x, int y, bool restore, bool force) { int sy = y; int sx = 1; @@ -4960,6 +4970,7 @@ static void prestel_fix_line(struct cterminal *cterm, int x, int y) unsigned char attr = cterm->attr; uint8_t prestel_last_mosaic = cterm->prestel_last_mosaic; bool fixed = false; + bool fixedheight = false; coord_conv_xy(cterm, CTERM_COORD_TERM, CTERM_COORD_SCREEN, &sy, &sx); ex = sx + TERM_MAXX - 1; @@ -4973,6 +4984,18 @@ static void prestel_fix_line(struct cterminal *cterm, int x, int y) // This is a control character ch = (line[i].fg & 0x7F000000) >> 24; prestel_apply_ctrl_before(cterm, ch); + if ((cterm->extattr & CTERM_EXTATTR_PRESTEL_DOUBLE_HEIGHT) && ((line[i].bg & 0x01000000) == 0)) { + // Should be double-high + line[i].bg |= 0x01000000; + fixed = true; + fixedheight = true; + } + if (((cterm->extattr & CTERM_EXTATTR_PRESTEL_DOUBLE_HEIGHT) == 0) && (line[i].bg & 0x01000000)) { + // Should not be double-high + line[i].bg &= ~0x01000000; + fixed = true; + fixedheight = true; + } if (line[i].fg != (cterm->fg_color | (ch << 24)) || line[i].bg != cterm->bg_color || line[i].legacy_attr != cterm->attr) { @@ -5009,6 +5032,18 @@ static void prestel_fix_line(struct cterminal *cterm, int x, int y) prestel_last_mosaic = cterm->prestel_last_mosaic; } // This is displayable + if ((cterm->extattr & CTERM_EXTATTR_PRESTEL_DOUBLE_HEIGHT) && ((line[i].bg & 0x01000000) == 0)) { + // Should be double-high + line[i].bg |= 0x01000000; + fixed = true; + fixedheight = true; + } + if (((cterm->extattr & CTERM_EXTATTR_PRESTEL_DOUBLE_HEIGHT) == 0) && (line[i].bg & 0x01000000)) { + // Should not be double-high + line[i].bg &= ~0x01000000; + fixed = true; + fixedheight = true; + } if (line[i].fg != cterm->fg_color || line[i].bg != cterm->bg_color || line[i].legacy_attr != cterm->attr) { @@ -5052,14 +5087,19 @@ static void prestel_fix_line(struct cterminal *cterm, int x, int y) } } } - if (fixed) + if (force || fixed) vmem_puttext(sx, sy, ex, sy, line); free(line); - cterm->extattr = extattr; - cterm->fg_color = fg_color; - cterm->bg_color = bg_color; - cterm->attr = attr; - cterm->prestel_last_mosaic = prestel_last_mosaic; + if (restore) { + cterm->extattr = extattr; + cterm->fg_color = fg_color; + cterm->bg_color = bg_color; + cterm->attr = attr; + cterm->prestel_last_mosaic = prestel_last_mosaic; + } + if (fixedheight) { + prestel_fix_line(cterm, x, y+1, false, true); + } } static void @@ -5070,7 +5110,7 @@ advance_char(struct cterminal *cterm, int *x, int *y, int move) int bm = cterm->bottom_margin; if (cterm->emulation == CTERM_EMULATION_PRESTEL) { - prestel_fix_line(cterm, *x, *y); + prestel_fix_line(cterm, *x, *y, true, false); TEXTATTR(cterm->attr); setcolour(cterm->fg_color, cterm->bg_color); } @@ -5199,6 +5239,8 @@ ctputs(struct cterminal *cterm, char *buf) } } CPUTS(outp); + if (cterm->emulation == CTERM_EMULATION_PRESTEL) + prestel_fix_line(cterm, cx, cy, true, false); *cterm->_wscroll=oldscroll; } -- GitLab