]> granicus.if.org Git - nethack/commitdiff
Support Unicode symbols in 16 color mode
authorRay Chason <Ray Chason>
Sat, 8 Oct 2022 23:41:22 +0000 (19:41 -0400)
committerRay Chason <Ray Chason>
Sat, 8 Oct 2022 23:41:22 +0000 (19:41 -0400)
sys/msdos/vidvga.c

index 99c7f3cfc987da1b7e05935bdbab5020871141e0..062b6cff575cac40ba7c7f1fcc178fa690d4b2a3 100644 (file)
@@ -11,6 +11,7 @@
 #include "pcvideo.h"
 #include "tile.h"
 #include "tileset.h"
+#include "font.h"
 
 #include <dos.h>
 #include <ctype.h>
@@ -123,7 +124,8 @@ static void vga_DisplayCell_O(struct overview_planar_cell_struct *, int,
                               int);
 static void vga_SwitchMode(unsigned int);
 static void vga_SetPalette(const struct Pixel *);
-static void vga_WriteChar(int, int, int, int);
+static void vga_WriteChar(uint32, int, int, int);
+static void vga_GetBitmap(uint32, unsigned char *);
 static void vga_WriteStr(char *, int, int, int, int);
 
 static void read_planar_tile(unsigned, struct planar_cell_struct *);
@@ -149,13 +151,14 @@ extern glyph_map glyphmap[MAX_GLYPH];
  * Global Variables
  */
 
-static unsigned char __far *font;
+static unsigned char __far *rom_font;
+static struct BitmapFont *psf_font;
 static char *screentable[SCREENHEIGHT];
 
 static const struct Pixel *paletteptr;
 static struct map_struct {
     int glyph;
-    int ch;
+    uint32 ch;
     int attr;
     unsigned special;
     short int tileidx;
@@ -363,12 +366,18 @@ void vga_xputc(char ch, int attr)
 void
 vga_xputg(const glyph_info *glyphinfo)
 {
-    int glyphnum = glyphinfo->glyph, ch = glyphinfo->ttychar;
+    int glyphnum = glyphinfo->glyph;
+    uint32 ch = glyphinfo->ttychar;
     unsigned special = glyphinfo->gm.glyphflags;
     int col, row;
     int attr;
     int ry;
 
+    if (psf_font != NULL && SYMHANDLING(H_UTF8) && glyphinfo->gm.u
+            && glyphinfo->gm.u->utf8str) {
+        ch = glyphinfo->gm.u->utf32ch;
+    }
+
     /* If statue glyph, map to the generic statue */
 #if 0
     if (GLYPH_STATUE_OFF <= glyphnum && glyphnum < GLYPH_STATUE_OFF + NUMMONS) {
@@ -389,7 +398,7 @@ vga_xputg(const glyph_info *glyphinfo)
     map[ry][col].attr = attr;
     map[ry][col].tileidx = glyphinfo->gm.tileidx;
     if (iflags.traditional_view) {
-        vga_WriteChar((unsigned char) ch, col, row, attr);
+        vga_WriteChar(ch, col, row, attr);
     } else if (!iflags.over_view) {
         if ((col >= clipx) && (col <= clipxmax)) {
             read_planar_tile(glyphnum, &planecell);
@@ -479,7 +488,7 @@ vga_redrawmap(boolean clearfirst)
 #endif
             if (iflags.traditional_view) {
                 if (!(clearfirst && map[y][x].ch == S_stone))
-                    vga_WriteChar((unsigned char) map[y][x].ch, x,
+                    vga_WriteChar(map[y][x].ch, x,
                                   y + TOP_MAP_ROW, map[y][x].attr);
             } else {
                 t = map[y][x].glyph;
@@ -723,6 +732,7 @@ void
 vga_Init(void)
 {
     int i;
+    const char *font_name;
 
 #ifdef USE_TILES
     const char *tile_file;
@@ -773,7 +783,21 @@ vga_Init(void)
 #endif
     vga_SetPalette(paletteptr);
     g_attribute = attrib_gr_normal;
-    font = (unsigned char __far *) vga_FontPtrs();
+    rom_font = (unsigned char __far *) vga_FontPtrs();
+
+    /* Load an external font if requested */
+    font_name = "ter-u16v.psf";
+    if (iflags.wc_font_map != NULL && iflags.wc_font_map[0] != '\0') {
+        font_name = iflags.wc_font_map;
+    }
+    free_font(psf_font);
+    psf_font = load_font(font_name);
+    if (psf_font->width != 8 || psf_font->height != 16) {
+        raw_printf("VGA mode only supports 8x16 fonts");
+        free_font(psf_font);
+        psf_font = NULL;
+    }
+
     clear_screen();
     clipx = 0;
     clipxmax = clipx + (viewport_size - 1);
@@ -910,22 +934,23 @@ vga_detect(void)
  *
  */
 static void
-vga_WriteChar(int chr, int col, int row, int colour)
+vga_WriteChar(uint32 chr, int col, int row, int colour)
 {
     int i;
     int x, pixy;
 
     char __far *cp;
-    unsigned char __far *fp = font;
     unsigned char fnt;
     int actual_colour = vgacmap[colour];
     int vplane;
+    unsigned char bitmap[ROWS_PER_CELL];
+
+    /* if (chr < ' ') chr = ' ';  */ /* assumes ASCII set */
+    vga_GetBitmap(chr, bitmap);
 
     x = min(col, (CO - 1));         /* min() used protection from callers */
     pixy = min(row, (LI - 1)) * 16; /* assumes 8 x 16 char set */
-    /* if (chr < ' ') chr = ' ';  */ /* assumes ASCII set */
 
-    chr = chr << 4;
     vplane = ~actual_colour & ~BACKGROUND_VGA_COLOR & 0xF;
     if (vplane != 0) {
         egawriteplane(vplane);
@@ -939,7 +964,7 @@ vga_WriteChar(int chr, int col, int row, int colour)
         egawriteplane(vplane);
         for (i = 0; i < MAX_ROWS_PER_CELL; ++i) {
             cp = screentable[pixy + i] + x;
-            fnt =  READ_ABSOLUTE((fp + chr + i));
+            fnt =  bitmap[i];
             WRITE_ABSOLUTE(cp, (char) fnt);
         }
     }
@@ -948,7 +973,7 @@ vga_WriteChar(int chr, int col, int row, int colour)
         egawriteplane(vplane);
         for (i = 0; i < MAX_ROWS_PER_CELL; ++i) {
             cp = screentable[pixy + i] + x;
-            fnt = ~READ_ABSOLUTE((fp + chr + i));
+            fnt = ~bitmap[i];
             WRITE_ABSOLUTE(cp, (char) fnt);
         }
     }
@@ -963,6 +988,28 @@ vga_WriteChar(int chr, int col, int row, int colour)
     egawriteplane(15);
 }
 
+/*
+ * Given the character, return the bitmap that displays that character
+ */
+static void
+vga_GetBitmap(uint32 chr, unsigned char *bitmap)
+{
+    unsigned i;
+
+    if (psf_font) {
+        unsigned char const *fp = get_font_glyph(psf_font, chr,
+                SYMHANDLING(H_UTF8));
+        for (i = 0; i < ROWS_PER_CELL; ++i) {
+            bitmap[i] = fp[i];
+        }
+    } else {
+        unsigned char const __far *fp = rom_font + chr * ROWS_PER_CELL;
+        for (i = 0; i < ROWS_PER_CELL; ++i) {
+            bitmap[i] = READ_ABSOLUTE((fp + i));
+        }
+    }
+}
+
 /*
  * This is the routine that displays a high-res "cell" pointed to by 'gp'
  * at the desired location (col,row).
@@ -1045,7 +1092,7 @@ vga_WriteStr(char *s, int len, int col, int row, int colour)
     i = 0;
     us = (unsigned char *) s;
     while ((*us != 0) && (i < len) && (col < (CO - 1))) {
-        vga_WriteChar(*us, col, row, colour);
+        vga_WriteChar((uchar) *us, col, row, colour);
         ++us;
         ++i;
         ++col;
@@ -1221,6 +1268,9 @@ vga_special(int chr, int col, int color)
     int vplane;
     char fnt;
     char bits[SCREENPLANES][ROWS_PER_CELL];
+    unsigned char bitmap[ROWS_PER_CELL];
+
+    vga_GetBitmap(chr, bitmap);
 
     pixy = PBAR_ROW * MAX_ROWS_PER_CELL;
     for (vplane = 0; vplane < SCREENPLANES; ++vplane) {
@@ -1229,7 +1279,7 @@ vga_special(int chr, int col, int color)
         for (i = 0; i < ROWS_PER_CELL; ++i) {
             tmp_d = screentable[y++] + col;
             bits[vplane][i] = READ_ABSOLUTE(tmp_d);
-            fnt = READ_ABSOLUTE((font + ((chr << 4) + i)));
+            fnt = READ_ABSOLUTE((rom_font + ((chr << 4) + i)));
             if (colorbits[vplane] & color)
                 bits[vplane][i] |= fnt;
             else