From 3061afa4b181b9723b1945aba3765a35bd714546 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net>
Date: Sun, 19 Jan 2025 17:08:37 -0500
Subject: [PATCH] Fix Prestel double-height bottom clearing issue

Any change to any double-height bit anywhere on the screen can
potentially change the display of every character after it on the
screen.  If the bit changes, force a full redraw from vmem
(Luckily there's no graphics in Prestel mode).

Fixes ticket 181
Ugh.
---
 src/conio/bitmap_con.c | 48 +++++++++++++++++++++++++++++++++---------
 1 file changed, 38 insertions(+), 10 deletions(-)

diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c
index 627eded961..2993e6b05c 100644
--- a/src/conio/bitmap_con.c
+++ b/src/conio/bitmap_con.c
@@ -278,6 +278,7 @@ bitmap_vmem_puttext_locked(int sx, int sy, int ex, int ey, struct vmem_cell *fil
 	int x,y;
 	struct vmem_cell *vc;
 	struct vmem_cell *fi = fill;
+	bool fullredraw = false;
 
 	if(!bitmap_initialized)
 		return(0);
@@ -297,16 +298,27 @@ bitmap_vmem_puttext_locked(int sx, int sy, int ex, int ey, struct vmem_cell *fil
 	for(y=sy-1;y<ey;y++) {
 		vc = vmem_cell_ptr(vstat.vmem, sx - 1, y);
 		for(x=sx-1;x<ex;x++) {
+			if (vstat.mode == PRESTEL_40X24 && ((vc->bg & 0x02000000) || (fi->bg & 0x02000000))) {
+				if ((vc->bg & 0x01000000) != (fi->bg & 0x01000000)) {
+					// *ANY* change to double-height potentially changes
+					// *EVERY* character on the screen
+					fullredraw = true;
+				}
+			}
 			*vc = *(fi++);
-			if (vstat.mode == PRESTEL_40X24 && (vc->bg & 0x02000000) && (vc->legacy_attr & 0x08)) {
-				if (cio_api.options & CONIO_OPT_PRESTEL_REVEAL)
-					vc->fg |= 0x01000000;
-				else
-					vc->fg &= ~0x01000000;
+			if (vstat.mode == PRESTEL_40X24 && (vc->bg & 0x02000000)) {
+				if (vc->legacy_attr & 0x08) {
+					if (cio_api.options & CONIO_OPT_PRESTEL_REVEAL)
+						vc->fg |= 0x01000000;
+					else
+						vc->fg &= ~0x01000000;
+				}
 			}
 			vc = vmem_next_ptr(vstat.vmem, vc);
 		}
 	}
+	if (fullredraw)
+		request_redraw_locked();
 	return(1);
 }
 
@@ -334,11 +346,26 @@ set_vmem_cell(size_t x, size_t y, uint16_t cell, uint32_t fg, uint32_t bg)
 	vc->legacy_attr = cell >> 8;
 	vc->ch = cell & 0xff;
 	vc->fg = fg;
-	if (vstat.mode == PRESTEL_40X24 && (vc->bg & 0x02000000) && (vc->legacy_attr & 0x08)) {
-		if (cio_api.options & CONIO_OPT_PRESTEL_REVEAL)
-			vc->fg |= 0x01000000;
-		else
-			vc->fg &= ~0x01000000;
+	if (vstat.mode == PRESTEL_40X24 && ((vc->bg & 0x02000000) || (bg & 0x02000000))) {
+		if (vc->legacy_attr & 0x08) {
+			if (cio_api.options & CONIO_OPT_PRESTEL_REVEAL)
+				vc->fg |= 0x01000000;
+			else
+				vc->fg &= ~0x01000000;
+		}
+		if ((vc->bg & 0x01000000) != (bg & 0x01000000)) {
+			// *ANY* change to double-height potentially changes
+			// *EVERY* character on the screen
+			request_redraw_locked();
+		}
+	}
+	if (vstat.mode == PRESTEL_40X24 && (vc->bg & 0x02000000)) {
+		if (vc->legacy_attr & 0x08) {
+			if (cio_api.options & CONIO_OPT_PRESTEL_REVEAL)
+				vc->fg |= 0x01000000;
+			else
+				vc->fg &= ~0x01000000;
+		}
 	}
 	vc->bg = bg;
 	vc->font = font;
@@ -1080,6 +1107,7 @@ same_cell(struct vmem_cell *bitmap_cell, struct vmem_cell *c2)
 		return false;
 	if (bitmap_cell->bg != c2->bg)
 		return false;
+	// Handles reveal/unreveal updates, modifies vmem
 	if (vstat.mode == PRESTEL_40X24 && (c2->bg & 0x02000000)) {
 		if (c2->legacy_attr & 0x08) {
 			if (cio_api.options & CONIO_OPT_PRESTEL_REVEAL)
-- 
GitLab