From 0524805a17a52ec481ea3e4ab24543d6d87e5409 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net>
Date: Tue, 21 Jan 2025 23:48:32 -0500
Subject: [PATCH] Fix up cursor and blinking rates, step 1...

For "PC" modes, cursor blinked at 1/16th of the VSYNC rate, so use
the CGA timings, where were generally the slowest of the bunch...
This means cursor blink at 3.745Hz, and character blink at 1.8725Hz.

For Prestel, character blink was 0.75Hz with a 3:1 On:Off ratio.
The cursor on the other hand was 1/32th the VSYNC and was generally
PAL, so 1.5625Hz.

I still need to dig into C64 and Atari modes, because they're likely
way off now (assuming either supports blinking).
---
 src/conio/bitmap_con.c | 77 +++++++++++++++++++++++++++++-------------
 1 file changed, 54 insertions(+), 23 deletions(-)

diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c
index 970ed7ea63..f8276344c0 100644
--- a/src/conio/bitmap_con.c
+++ b/src/conio/bitmap_con.c
@@ -402,6 +402,10 @@ static void	cb_drawrect(struct rectlist *data)
 	 * 5) When blinking, the cursor is shown when vstat.blink is true.
 	 */
 	assert_rwlock_rdlock(&vstatlock);
+	if (vstat.mode == PRESTEL_40X24)
+		cv = 0x80FFFFFF;
+	else
+		cv = color_value(ciolib_fg);
 	curs_start = vstat.curs_start;
 	curs_end = vstat.curs_end;
 	curs_row = vstat.curs_row;
@@ -410,7 +414,6 @@ static void	cb_drawrect(struct rectlist *data)
 	charwidth = vstat.charwidth;
 	if (cursor_visible_locked()) {
 		assert_rwlock_unlock(&vstatlock);
-		cv = color_value(ciolib_fg);
 		for (y = curs_start; y <= curs_end; y++) {
 			pixel = &data->data[((curs_row - 1) * charheight + y) * data->rect.width + (curs_col - 1) * charwidth];
 			for (x = 0; x < charwidth; x++) {
@@ -970,43 +973,71 @@ static int check_redraw(void)
 static void blinker_thread(void *data)
 {
 	void *rect;
-	int count=0;
+	uint64_t next_blink = 0;
+	uint64_t next_cursor = 0;
 	int curs_changed;
 	int blink_changed;
 	struct bitmap_screen *screen;
 	struct bitmap_screen *ncscreen;
 	int lfc;
 	int blink;
+	bool prestel;
 
 	SetThreadName("Blinker");
 	while(1) {
 		curs_changed = 0;
 		blink_changed = 0;
 		SLEEP(10);
-		count++;
+		uint64_t now = xp_timer64();
 
 		assert_rwlock_wrlock(&vstatlock);
-		if (count==25) {
-			curs_changed = cursor_visible_locked();
-			if(vstat.curs_blink)
-				vstat.curs_blink=FALSE;
-			else
-				vstat.curs_blink=TRUE;
-			curs_changed = (curs_changed != cursor_visible_locked());
+		prestel = vstat.mode == PRESTEL_40X24;
+		if (prestel) {
+			if (next_blink < now) {
+				if (vstat.blink) {
+					vstat.blink=FALSE;
+					next_blink = now + 1000;
+				}
+				else {
+					vstat.blink=TRUE;
+					next_blink = now + 333;
+				}
+				blink_changed = 1;
+			}
+			if (next_cursor < now) {
+				curs_changed = cursor_visible_locked();
+				if (vstat.curs_blink) {
+					vstat.curs_blink=FALSE;
+				}
+				else {
+					vstat.curs_blink=TRUE;
+				}
+				curs_changed = (curs_changed != cursor_visible_locked());
+				next_cursor = now + 320;
+			}
 		}
-		if(count==50) {
-			if(vstat.blink)
-				vstat.blink=FALSE;
-			else
-				vstat.blink=TRUE;
-			blink_changed = 1;
-			curs_changed = cursor_visible_locked();
-			if(vstat.curs_blink)
-				vstat.curs_blink=FALSE;
-			else
-				vstat.curs_blink=TRUE;
-			curs_changed = (curs_changed != cursor_visible_locked());
-			count=0;
+		else {
+			if (next_blink < now) {
+				if (vstat.blink) {
+					vstat.blink=FALSE;
+				}
+				else {
+					vstat.blink=TRUE;
+				}
+				next_blink = now + 266;
+				blink_changed = 1;
+			}
+			if (next_cursor < now) {
+				curs_changed = cursor_visible_locked();
+				if (vstat.curs_blink) {
+					vstat.curs_blink=FALSE;
+				}
+				else {
+					vstat.curs_blink=TRUE;
+				}
+				curs_changed = (curs_changed != cursor_visible_locked());
+				next_cursor = now + 133;
+			}
 		}
 		lfc = force_cursor;
 		force_cursor = 0;
-- 
GitLab