From: Ray Chason Date: Sat, 8 Oct 2022 23:41:22 +0000 (-0400) Subject: Support Unicode symbols in 16 color mode X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6400ce073aa2cfb88e4ee94a606853baf05b9cb0;p=nethack Support Unicode symbols in 16 color mode --- diff --git a/sys/msdos/vidvga.c b/sys/msdos/vidvga.c index 99c7f3cfc..062b6cff5 100644 --- a/sys/msdos/vidvga.c +++ b/sys/msdos/vidvga.c @@ -11,6 +11,7 @@ #include "pcvideo.h" #include "tile.h" #include "tileset.h" +#include "font.h" #include #include @@ -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