From 172d6f683359d2c07a07cbe051794710f3060918 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net>
Date: Sat, 15 May 2021 00:49:38 -0400
Subject: [PATCH] Add support for VGA 80x25 mode.

This uses the 720x400 with 9x16 character cell that always made
BBSs look so terrible.
---
 src/conio/bitmap_con.c  | 40 +++++++++++++++++++++++++++++++++-------
 src/conio/ciolib.h      | 15 ++++++++++-----
 src/conio/scale.c       | 10 ++++------
 src/conio/vidmodes.c    | 10 ++++++++++
 src/conio/vidmodes.h    |  6 ++++--
 src/syncterm/bbslist.c  |  4 ++--
 src/syncterm/bbslist.h  |  1 +
 src/syncterm/syncterm.c |  2 ++
 8 files changed, 66 insertions(+), 22 deletions(-)

diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c
index 7f5615ddff..3809287461 100644
--- a/src/conio/bitmap_con.c
+++ b/src/conio/bitmap_con.c
@@ -127,6 +127,7 @@ static int bitmap_loadfont_locked(char *filename)
 {
 	static char current_filename[MAX_PATH];
 	unsigned int fontsize;
+	int fdw;
 	int fw;
 	int fh;
 	int i;
@@ -159,7 +160,8 @@ static int bitmap_loadfont_locked(char *filename)
 	}
 
 	fh=vstat.charheight;
-	fw=vstat.charwidth/8+(vstat.charwidth%8?1:0);
+	fdw = vstat.charwidth - (vstat.flags & VIDMODES_FLAG_EXPAND) ? 1 : 0;
+	fw = fdw / 8 + (fdw % 8 ? 1 : 0);
 
 	fontsize=fw*fh*256*sizeof(unsigned char);
 
@@ -190,7 +192,7 @@ static int bitmap_loadfont_locked(char *filename)
 	for (i=0; i<sizeof(font)/sizeof(font[0]); i++) {
 		if (current_font[i] < 0)
 			continue;
-		switch(vstat.charwidth) {
+		switch(fdw) {
 			case 8:
 				switch(vstat.charheight) {
 					case 8:
@@ -476,9 +478,12 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
 {
 	uint32_t fg;
 	uint32_t bg;
+	int fdw;
 	int		xoffset=(xpos-1)*vstat.charwidth;
 	int		yoffset=(ypos-1)*vstat.charheight;
 	int		x;
+	int		fdx;
+	uint8_t fb = 0;
 	int		y;
 	int		fontoffset;
 	unsigned char *this_font;
@@ -542,12 +547,33 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
 	}
 	if (this_font == NULL)
 		this_font = font[0];
-	fontoffset=(sch & 0xff) * (vstat.charheight * ((vstat.charwidth + 7) / 8));
+	fdw = vstat.charwidth - (vstat.flags & VIDMODES_FLAG_EXPAND) ? 1 : 0;
+	fontoffset=(sch & 0xff) * (vstat.charheight * ((fdw + 7) / 8));
 
 	draw_fg = ((!(sch & 0x8000)) || vstat.no_blink);
 	for(y=0; y<vstat.charheight; y++) {
 		for(x=0; x<vstat.charwidth; x++) {
-			if(this_font[fontoffset] & (0x80 >> (x & 7)) && draw_fg) {
+			fdx = x;
+			fb = this_font[fontoffset];
+			if ((x & 0x07) == 7)
+				fontoffset++;
+			if (vstat.flags & VIDMODES_FLAG_EXPAND) {
+				if (x == vstat.charwidth - 1) {
+					fontoffset--;
+					fdx--;
+					if (!(vstat.flags & VIDMODES_FLAG_LINE_GRAPHICS_EXPAND)) {
+						fb = 0;
+					}
+					else if ((sch & 0xff) >= 0xC0 && (sch & 0xff) <= 0xDF) {
+						fb = this_font[fontoffset];
+					}
+					else
+						fb = 0;
+					
+				}
+			}
+
+			if(fb & (0x80 >> (fdx & 7)) && draw_fg) {
 				if (screena.screen[PIXEL_OFFSET(screena, xoffset + x, yoffset + y)] != fg) {
 					screena.update_pixels = 1;
 					screena.screen[PIXEL_OFFSET(screena, xoffset + x, yoffset + y)] = fg;
@@ -559,7 +585,8 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
 					screena.screen[PIXEL_OFFSET(screena, xoffset + x, yoffset + y)] = bg;
 				}
 			}
-			if(this_font[fontoffset] & (0x80 >> (x & 7))) {
+
+			if(fb & (0x80 >> (fdx & 7))) {
 				if (screenb.screen[PIXEL_OFFSET(screenb, xoffset + x, yoffset + y)]!=fg) {
 					screenb.update_pixels = 1;
 					screenb.screen[PIXEL_OFFSET(screenb, xoffset + x, yoffset + y)]=fg;
@@ -571,8 +598,7 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
 					screenb.screen[PIXEL_OFFSET(screenb, xoffset+x, yoffset+y)]=bg;
 				}
 			}
-			if ((x & 0x07) == 7)
-				fontoffset++;
+
 		}
 		if (x & 0x07)
 			fontoffset++;
diff --git a/src/conio/ciolib.h b/src/conio/ciolib.h
index e355d3cba6..c1fdcf631c 100644
--- a/src/conio/ciolib.h
+++ b/src/conio/ciolib.h
@@ -118,11 +118,13 @@ enum {
 #define BLINK 128
 #endif
 
-#define CIOLIB_VIDEO_ALTCHARS		(1<<0)	// Attribute bit 3 selects alternate char set
-#define CIOLIB_VIDEO_NOBRIGHT		(1<<1)	// Attribute bit 3 does not increase intensity
-#define CIOLIB_VIDEO_BGBRIGHT		(1<<2)	// Attribute bit 7 selects high intensity background, not blink
-#define CIOLIB_VIDEO_BLINKALTCHARS	(1<<3)	// Attribute bit 7 selects alternate char set
-#define CIOLIB_VIDEO_NOBLINK		(1<<4)	// Attribute bit 7 has no effect
+#define CIOLIB_VIDEO_ALTCHARS             (1<<0)	// Attribute bit 3 selects alternate char set
+#define CIOLIB_VIDEO_NOBRIGHT             (1<<1)	// Attribute bit 3 does not increase intensity
+#define CIOLIB_VIDEO_BGBRIGHT             (1<<2)	// Attribute bit 7 selects high intensity background, not blink
+#define CIOLIB_VIDEO_BLINKALTCHARS        (1<<3)	// Attribute bit 7 selects alternate char set
+#define CIOLIB_VIDEO_NOBLINK              (1<<4)	// Attribute bit 7 has no effect
+#define CIOLIB_VIDEO_EXPAND               (1<<5)	// Use an extra blank column between characters from the font
+#define CIOLIB_VIDEO_LINE_GRAPHICS_EXPAND (1<<6)	// Per VGA, when using CIOLIB_VIDEO_EXPAND, repeat the last column for chars 0xC0 - 0xDF inclusive
 
 enum text_modes
 {
@@ -182,6 +184,9 @@ enum text_modes
 	ST132X37_16_9,
 	ST132X52_5_4,
 
+	/* New modes we've added 'cause they're stupid */
+	VGA80X25,
+
 	/* Cruft... */
 
 	C4350    = C80X50,	/* this is actually "64" in the "real" conio */
diff --git a/src/conio/scale.c b/src/conio/scale.c
index 87c7cdfb14..05d356b413 100644
--- a/src/conio/scale.c
+++ b/src/conio/scale.c
@@ -186,14 +186,12 @@ do_scale(struct rectlist* rect, int xscale, int yscale, double ratio)
 	}
 
 	// Calculate the scaled height from ratio...
-	if (ratio < 1)
-		fheight = lround((double)(rect->rect.height * (yscale)) / ratio);
-	else
+	fheight = lround((double)(rect->rect.height * (yscale)) / ratio);
+	if (fheight < rect->rect.height * yscale)
 		fheight = rect->rect.height * yscale;
 
-	if (ratio > 1)
-		fwidth = lround((double)(rect->rect.width * (xscale)) / ratio);
-	else
+	fwidth = lround((double)(rect->rect.width * (xscale)) * ratio);
+	if (fwidth < rect->rect.width * xscale)
 		fwidth = rect->rect.width * xscale;
 
 	// Now make sure target is big enough...
diff --git a/src/conio/vidmodes.c b/src/conio/vidmodes.c
index 463fd00711..8ef2690594 100644
--- a/src/conio/vidmodes.c
+++ b/src/conio/vidmodes.c
@@ -115,6 +115,8 @@ struct video_params vparams[] = {
 	/* Awesome modes */
 	{ST132X37_16_9, COLOUR_PALETTE,      132, 37, 14, 15, 16, 8, 1, 7, 0,   1,    1, 1056, 600},
 	{ST132X52_5_4, COLOUR_PALETTE,       132, 52, 14, 15, 16, 8, 1, 7, 0,   1,    1, 1056, 823},
+	/* Stupid modes */
+	{VGA80X25, COLOUR_PALETTE,            80, 25, 14, 15, 16, 9, 1, 7, CIOLIB_VIDEO_EXPAND | CIOLIB_VIDEO_LINE_GRAPHICS_EXPAND, 740, 1000, 720, 400},
 	/* Custom mode */
 	{CIOLIB_MODE_CUSTOM, COLOUR_PALETTE, 80,  25, 14, 15, 16, 8, 1, 7, 0,   1,    1,   -1,  -1},
 };
@@ -318,6 +320,14 @@ int load_vmode(struct video_stats *vs, int mode)
 	vs->bright_altcharset=vparams[i].flags & CIOLIB_VIDEO_ALTCHARS;
 	vs->no_blink=vparams[i].flags & CIOLIB_VIDEO_NOBLINK;
 	vs->blink_altcharset=vparams[i].flags & CIOLIB_VIDEO_BLINKALTCHARS;
+	if (vparams[i].flags & CIOLIB_VIDEO_EXPAND)
+		vs->flags |= VIDMODES_FLAG_EXPAND;
+	else
+		vs->flags &= ~VIDMODES_FLAG_EXPAND;
+	if (vparams[i].flags & CIOLIB_VIDEO_LINE_GRAPHICS_EXPAND)
+		vs->flags |= VIDMODES_FLAG_LINE_GRAPHICS_EXPAND;
+	else
+		vs->flags &= ~VIDMODES_FLAG_LINE_GRAPHICS_EXPAND;
 	if(vs->curs_row < 0)
 		vs->curs_row=0;
 	if(vs->curs_row >= vparams[i].rows)
diff --git a/src/conio/vidmodes.h b/src/conio/vidmodes.h
index e80df43ada..c9695ddfc7 100644
--- a/src/conio/vidmodes.h
+++ b/src/conio/vidmodes.h
@@ -106,7 +106,9 @@ struct video_stats {
 	int scale_numerator;
 	int scale_denominator;
 	uint32_t flags;
-#define VIDMODES_FLAG_PALETTE_VMEM	1
+#define VIDMODES_FLAG_PALETTE_VMEM         1
+#define VIDMODES_FLAG_EXPAND               2
+#define VIDMODES_FLAG_LINE_GRAPHICS_EXPAND 4
 	uint32_t palette[16];
 	struct vstat_vmem *vmem;
 	uint8_t *forced_font;
@@ -120,7 +122,7 @@ enum {
 	,ATARI_PALETTE
 };
 
-extern struct video_params vparams[54];
+extern struct video_params vparams[55];
 #define NUMMODES      (sizeof(vparams) / sizeof(struct video_params))
 extern uint32_t palettes[5][16];
 extern struct dac_colors dac_default[TOTAL_DAC_SIZE];
diff --git a/src/syncterm/bbslist.c b/src/syncterm/bbslist.c
index 5f586da90f..61d38e372a 100644
--- a/src/syncterm/bbslist.c
+++ b/src/syncterm/bbslist.c
@@ -188,8 +188,8 @@ static struct sort_order_info sort_order[] = {
 
 int sortorder[sizeof(sort_order)/sizeof(struct sort_order_info)];
 
-char *screen_modes[]={     "Current", "80x25", "80x28", "80x30", "80x43", "80x50", "80x60", "132x37 (16:9)", "132x52 (5:4)", "132x25", "132x28", "132x30", "132x34", "132x43", "132x50", "132x60", "C64", "C128 (40col)", "C128 (80col)", "Atari", "Atari XEP80", "Custom", "EGA 80x25", NULL};
-static char *screen_modes_enum[]={"Current", "80x25", "80x28", "80x30", "80x43", "80x50", "80x60", "132x37",        "132x52",       "132x25", "132x28", "132x30", "132x34", "132x43", "132x50", "132x60", "C64", "C128-40col",   "C128-80col",   "Atari", "Atari-XEP80", "Custom", "EGA80x25", NULL};
+char *screen_modes[]={     "Current", "80x25", "80x28", "80x30", "80x43", "80x50", "80x60", "132x37 (16:9)", "132x52 (5:4)", "132x25", "132x28", "132x30", "132x34", "132x43", "132x50", "132x60", "C64", "C128 (40col)", "C128 (80col)", "Atari", "Atari XEP80", "Custom", "EGA 80x25", "VGA 80x25", NULL};
+static char *screen_modes_enum[]={"Current", "80x25", "80x28", "80x30", "80x43", "80x50", "80x60", "132x37",        "132x52",       "132x25", "132x28", "132x30", "132x34", "132x43", "132x50", "132x60", "C64", "C128-40col",   "C128-80col",   "Atari", "Atari-XEP80", "Custom", "EGA80x25", "VGA80x25", NULL};
 
 char *log_levels[]={"Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Info", "Debug", NULL};
 static char *log_level_desc[]={"None", "Alerts", "Critical Errors", "Errors", "Warnings", "Notices", "Normal", "All (Debug)", NULL};
diff --git a/src/syncterm/bbslist.h b/src/syncterm/bbslist.h
index bc9f413bc6..77b3ab310a 100644
--- a/src/syncterm/bbslist.h
+++ b/src/syncterm/bbslist.h
@@ -57,6 +57,7 @@ enum {
     ,SCREEN_MODE_ATARI_XEP80
     ,SCREEN_MODE_CUSTOM
     ,SCREEN_MODE_EGA_80X25
+    ,SCREEN_MODE_VGA_80X25
     ,SCREEN_MODE_TERMINATOR
 };
 
diff --git a/src/syncterm/syncterm.c b/src/syncterm/syncterm.c
index 53aa4135af..f5328f3b86 100644
--- a/src/syncterm/syncterm.c
+++ b/src/syncterm/syncterm.c
@@ -1948,6 +1948,8 @@ int screen_to_ciolib(int screen)
 			return(CIOLIB_MODE_CUSTOM);
 		case SCREEN_MODE_EGA_80X25:
 			return(EGA80X25);
+		case SCREEN_MODE_VGA_80X25:
+			return(VGA80X25);
 	}
 	gettextinfo(&ti);
 	return(ti.currmode);
-- 
GitLab