Merge branch 'dos-tty-unicode' of https://github.com/chasonr/NetHack into pr899

This commit is contained in:
nhmall
2022-10-09 09:26:08 -04:00
8 changed files with 519 additions and 81 deletions

View File

@@ -202,7 +202,7 @@ U = $(UTIL)/
# Utility Objects.
#==========================================
VGAOBJ = $(O)vidvga.o $(O)vidvesa.o
VGAOBJ = $(O)vidvga.o $(O)vidvesa.o $(O)font.o
MAKESRC = makedefs.c
@@ -601,9 +601,7 @@ ifdef CWSDPMI
else
@$(subst /,\,echo Could not find a copy of CWSDPMI.EXE to put into $(GAMEDIR))
endif
ifdef WANT_DOSVGA
@$(subst /,\,copy $(MSYS)/fonts/*.psf $(GAMEDIR))
endif
@$(subst /,\,echo install done > $@)
#==========================================
@@ -925,7 +923,6 @@ $(O)luac.o: $(LUASRC)/luac.c
# Fonts for Unicode support
#==========================================
ifdef WANT_DOSVGA
$(O)fonts.tag: lua.exe $(MSYS)/fonts/makefont.lua
lua $(MSYS)/fonts/makefont.lua $(FONTTOP)/ter-u16b.bdf $(MSYS)/fonts/ter-u16b.psf
lua $(MSYS)/fonts/makefont.lua $(FONTTOP)/ter-u16v.bdf $(MSYS)/fonts/ter-u16v.psf
@@ -936,10 +933,6 @@ $(O)fonts.tag: lua.exe $(MSYS)/fonts/makefont.lua
lua $(MSYS)/fonts/makefont.lua $(FONTTOP)/ter-u28b.bdf $(MSYS)/fonts/ter-u28b.psf
lua $(MSYS)/fonts/makefont.lua $(FONTTOP)/ter-u32b.bdf $(MSYS)/fonts/ter-u32b.psf
@echo Fonts done >$(O)fonts.tag
else
$(O)fonts.tag:
@echo Fonts not needed >$(O)fonts.tag
endif
#==========================================
# Housekeeping.
@@ -1052,6 +1045,9 @@ $(O)vidvesa.o : $(HACK_H) $(MSYS)/pcvideo.h $(MSYS)/portio.h $(TILE_H) $(MSYS)/
$(O)vidtxt.o : $(HACK_H) $(MSYS)/pcvideo.h $(MSYS)/portio.h $(TILE_H) $(MSYS)/vidtxt.c
# $(CC) $(cflags) -o$@ -I$(MSYS) $(MSYS)/vidtxt.c
$(O)font.o : $(HACK_H) $(MSYS)/font.h $(MSYS)/font.c
$(CC) $(cflags) -I$(MSYS) -I$(WSHR) -o$@ $(MSYS)/font.c
$(O)stubvid.o : $(HACK_H) $(MSYS)/pcvideo.h $(MSYS)/video.c
$(CC) $(cflags) -I$(MSYS) -DSTUBVIDEO -o$@ $(MSYS)/video.c

276
sys/msdos/font.c Executable file
View File

@@ -0,0 +1,276 @@
/* Maintain a data structure describing a monospaced bitmap font */
#include "hack.h"
#include "integer.h"
#include "font.h"
static uint32 read_u32(const unsigned char *);
static void add_unicode_index(
struct BitmapFont *font,
uint32 ch,
unsigned index);
static uint32 *uni_8to32(const char *);
struct BitmapFont *
load_font(const char *filename)
{
FILE *fp;
struct BitmapFont *font = NULL;
unsigned char header[32];
size_t size;
uint32 magic;
uint32 version;
uint32 headersize;
uint32 flags;
uint32 length;
uint32 charsize;
uint32 height;
uint32 width;
uint32 bwidth, memsize;
uint32 i;
fp = fopen(filename, "rb");
if (fp == NULL) goto error;
/* Read the PSF header */
size = fread(header, 1, sizeof(header), fp);
if (size != sizeof(header)) goto error;
/* Convert from little endian order */
magic = read_u32(header + 0);
if (magic != 0x864AB572) goto error;
version = read_u32(header + 4);
if (version != 0) goto error;
headersize = read_u32(header + 8);
if (headersize < sizeof(header)) goto error;
flags = read_u32(header + 12);
length = read_u32(header + 16);
charsize = read_u32(header + 20);
height = read_u32(header + 24);
width = read_u32(header + 28);
/* Check that the declared character size can hold the declared width
and height */
bwidth = (width + 7) / 8;
memsize = bwidth * height;
if (memsize > charsize) goto error;
/* Allocate a font structure */
font = (struct BitmapFont *) alloc(sizeof(struct BitmapFont));
memset(font, 0, sizeof(struct BitmapFont));
/* Dimensions of the font */
font->width = width;
font->height = height;
font->num_glyphs = length;
/* The glyph array */
font->glyphs = (unsigned char **) alloc(length * sizeof(unsigned char *));
memset(font->glyphs, 0, length * sizeof(unsigned char *));
/* Read the glyphs */
fseek(fp, headersize, SEEK_SET);
for (i = 0; i < length; ++i) {
font->glyphs[i] = (unsigned char *) alloc(memsize);
size = fread(font->glyphs[i], 1, memsize, fp);
if (size != memsize) goto error;
fseek(fp, charsize - memsize, SEEK_CUR);
}
if (flags & 0x01) {
/* Read the Unicode table */
char buf[128], buf2[128+1];
unsigned bufsize, strsize;
char *p;
uint32 *codepoints;
bufsize = 0;
i = 0;
while (i < length) {
unsigned j;
size = fread(buf + bufsize, 1, sizeof(buf) - bufsize, fp);
if (ferror(fp)) goto error;
bufsize += size;
if (bufsize == 0) goto error; /* unexpected EOF */
p = memchr(buf, 0xFF, bufsize);
if (p != NULL) { /* end marker found */
strsize = p - buf;
memcpy(buf2, buf, strsize);
buf2[strsize] = '\0';
bufsize -= strsize + 1;
memmove(buf, buf + strsize + 1, bufsize);
} else { /* partial string */
strsize = bufsize - 1;
/* Roll back to character boundary in case of partial character */
while (strsize != 0 && (buf[strsize] & 0xC0) == 0x80)
--strsize;
if (strsize == 0) /* avoid infinite loop */
strsize = (bufsize < 4) ? bufsize : 4;
memcpy(buf2, buf, strsize);
buf2[strsize] = '\0';
bufsize -= strsize;
memmove(buf, buf + strsize, bufsize);
}
codepoints = uni_8to32(buf2);
for (j = 0; codepoints[j] != 0; ++j) {
add_unicode_index(font, codepoints[j], i);
}
free(codepoints);
if (p != NULL)
++i;
}
} else {
/* Fake a Unicode table, assuming that ASCII glyphs are in the
expected places */
for (i = 0x20; i <= 0x7E; ++i) {
add_unicode_index(font, i, i);
}
}
fclose(fp);
return font;
error:
if (fp != NULL) fclose(fp);
free_font(font);
return NULL;
}
void
free_font(struct BitmapFont *font)
{
unsigned i, j;
if (font == NULL) return;
if (font->glyphs != NULL) {
for (i = 0; i < font->num_glyphs; ++i)
free(font->glyphs[i]);
free(font->glyphs);
}
for (i = 0; i < SIZE(font->unicode); ++i) {
if (font->unicode[i] == NULL) continue;
for (j = 0; j < 256; ++j)
free(font->unicode[i][j]);
free(font->unicode[i]);
}
free(font);
}
const unsigned char *
get_font_glyph(struct BitmapFont *font, uint32 ch, boolean unicode)
{
unsigned index;
if (unicode) {
index = 0;
if (ch <= 0x10FFFF && (ch & 0xFFFFD800) != 0xD800) {
unsigned i, j, k;
i = (unsigned) (ch >> 16);
j = (unsigned) ((ch >> 8) & 0xFF);
k = (unsigned) (ch & 0xFF);
if (font->unicode[i] != NULL
&& font->unicode[i][j] != NULL) {
index = font->unicode[i][j][k];
}
}
} else {
index = ch;
}
if (index >= font->num_glyphs)
index = 0;
return font->glyphs[index];
}
static void
add_unicode_index(struct BitmapFont *font, uint32 ch, unsigned index)
{
unsigned i, j, k;
i = (unsigned) (ch >> 16);
j = (unsigned) ((ch >> 8) & 0xFF);
k = (unsigned) (ch & 0xFF);
if (font->unicode[i] == NULL) {
/* Create the second level node */
font->unicode[i] = (unsigned **) alloc(256 * sizeof(unsigned *));
memset(font->unicode[i], 0, 256 * sizeof(unsigned *));
}
if (font->unicode[i][j] == NULL) {
/* Create the third level node */
font->unicode[i][j] = (unsigned *) alloc(256 * sizeof(unsigned));
memset(font->unicode[i][j], 0, 256 * sizeof(unsigned));
}
font->unicode[i][j][k] = index;
}
static uint32
read_u32(const unsigned char *buf)
{
return ((uint32) buf[0] << 0)
| ((uint32) buf[1] << 8)
| ((uint32) buf[2] << 16)
| ((uint32) buf[3] << 24);
}
static uint32 *
uni_8to32(const char *inp)
{
size_t i, j;
uint32 *out;
/* Output string */
out = (uint32 *) alloc((strlen(inp) + 1) * sizeof(out[0]));
i = 0;
j = 0;
while (inp[i] != 0) {
unsigned char byte = inp[i++];
uint32 ch32;
uint32 min = 0;
unsigned count = 0;
if (byte < 0x80) {
ch32 = byte;
} else if (byte < 0xC0) {
ch32 = 0xFFFD;
} else if (byte < 0xE0) {
ch32 = byte & 0x1F;
min = 0x80;
count = 1;
} else if (byte < 0xF0) {
ch32 = byte & 0x0F;
min = 0x800;
count = 2;
} else if (byte < 0xF5) {
ch32 = byte & 0x07;
min = 0x10000;
count = 3;
} else {
ch32 = 0xFFFD;
}
for (; count != 0; --count) {
byte = inp[i];
if ((byte & 0xC0) != 0x80) {
break;
}
++i;
ch32 = (ch32 << 6) | (byte & 0x3F);
}
if (count != 0 || ch32 < min || ((ch32 & 0xFFFFF800) == 0xD800)) {
ch32 = 0xFFFD;
}
out[j++] = ch32;
}
out[j] = 0;
return out;
}

53
sys/msdos/font.h Executable file
View File

@@ -0,0 +1,53 @@
/* Maintain a data structure describing a monospaced bitmap font */
#ifndef FONT_H
#define FONT_H
#include "integer.h"
/*
* The file format is Linux PSF, version 2. Version 1 is not supported.
* Actual Linux fonts are restricted to 256 or 512 glyphs; for NetHack, the
* font can have any number of glyphs. The Unicode map is expected to be
* present, but combining sequences are not supported.
* The fonts supplied for use with this data structure have the first 256
* glyphs arranged according to IBM code page 437, for simpler support of
* the IBM handling mode for the map.
*/
/* For Unicode lookup, a three level tree provides constant-time access to
the glyphs without using an excessive amount of memory.
The root has seventeen entries, one for each plane of Unicode. Most fonts
will populate only plane 0, and Unicode defines only planes 0, 1, 2, 3, 15
and 16.
The second level has 256 entries, each pointing to a third level node with
256 entries. Each third level entry has type unsigned, and gives the index
of the glyph.
Given the Unicode code point, we can use bits 20 through 16 to index the
root, bits 15 through 8 for the second level and bits 7 through 0 for the
third level. */
struct BitmapFont {
/* Dimensions of a single glyph */
unsigned width;
unsigned height;
/* The glyphs, in the order that they appear in the font */
/* IBM handling will index the glyphs this way */
/* glyph points to an allocated array, each element of which points to
another allocated array */
unsigned num_glyphs;
unsigned char **glyphs;
/* The root node of the Unicode tree */
unsigned **unicode[17];
};
extern struct BitmapFont *load_font(const char *filename);
extern void free_font(struct BitmapFont *font);
extern const unsigned char *get_font_glyph(
struct BitmapFont *font,
uint32 ch,
boolean unicode);
#endif

View File

@@ -476,6 +476,7 @@ tty_start_screen(void)
void
gr_init(void)
{
windowprocs.wincap2 &= ~WC2_U_24BITCOLOR;
#ifdef SCREEN_VGA
if (iflags.usevga) {
vga_Init();

View File

@@ -16,13 +16,14 @@
#include "vesa.h"
#include "wintty.h"
#include "tileset.h"
#include "font.h"
#define FIRST_TEXT_COLOR 240
extern int total_tiles_used, Tile_corr, Tile_unexplored; /* from tile.c */
struct VesaCharacter {
int colour;
int chr;
uint32 colour;
uint32 chr;
};
static unsigned long vesa_SetWindow(int window, unsigned long offset);
@@ -47,13 +48,13 @@ static boolean vesa_SetHardPalette(const struct Pixel *);
static boolean vesa_SetSoftPalette(const struct Pixel *);
static void vesa_DisplayCell(int, int, int);
static unsigned vesa_FindMode(unsigned long mode_addr, unsigned bits);
static void vesa_WriteChar(int, int, int, int);
static void vesa_WriteCharXY(int, int, int, int);
static void vesa_WriteChar(uint32, int, int, uint32);
static void vesa_WriteCharXY(uint32, int, int, uint32);
static void vesa_WriteCharTransparent(int, int, int, int);
static void vesa_WriteTextRow(int pixx, int pixy,
struct VesaCharacter const *t_row, unsigned t_row_width);
static boolean vesa_GetCharPixel(int, unsigned, unsigned);
static unsigned char vesa_GetCharPixelRow(int, unsigned, unsigned);
static unsigned char vesa_GetCharPixelRow(uint32, unsigned, unsigned);
static unsigned long vesa_DoublePixels(unsigned long);
static unsigned long vesa_TriplePixels(unsigned long);
static void vesa_WriteStr(const char *, int, int, int, int);
@@ -81,8 +82,8 @@ static unsigned char __far *font;
static struct map_struct {
int glyph;
int ch;
int attr;
uint32 ch;
uint32 attr;
unsigned special;
short int tileidx;
} map[ROWNO][COLNO]; /* track the glyphs */
@@ -151,6 +152,7 @@ static unsigned vesa_char_width = 8, vesa_char_height = 16;
static unsigned vesa_oview_width, vesa_oview_height;
static unsigned char **vesa_tiles;
static unsigned char **vesa_oview_tiles;
static struct BitmapFont *vesa_font;
#ifdef SIMULATE_CURSOR
static unsigned long *undercursor;
@@ -670,12 +672,24 @@ vesa_xputc(char ch, int attr)
void
vesa_xputg(const glyph_info *glyphinfo)
{
int glyphnum = glyphinfo->glyph, ch = glyphinfo->ttychar;
int glyphnum = glyphinfo->glyph;
uint32 ch = (uchar) glyphinfo->ttychar;
unsigned special = glyphinfo->gm.glyphflags;
int col, row;
int attr;
uint32_t attr = (g_attribute == 0) ? attrib_gr_normal : g_attribute;
int ry;
#ifdef ENHANCED_SYMBOLS
if (SYMHANDLING(H_UTF8) && glyphinfo->gm.u && glyphinfo->gm.u->utf8str) {
ch = glyphinfo->gm.u->utf32ch;
if (vesa_pixel_size > 8 && glyphinfo->gm.u->ucolor != 0) {
/* FIXME: won't display black (0,0,0) correctly, but the background
is usually black anyway */
attr = glyphinfo->gm.u->ucolor | 0x80000000;
}
}
#endif
row = currow;
col = curcol;
if ((col < 0 || col >= COLNO)
@@ -686,10 +700,9 @@ vesa_xputg(const glyph_info *glyphinfo)
map[ry][col].ch = ch;
map[ry][col].special = special;
map[ry][col].tileidx = glyphinfo->gm.tileidx;
attr = (g_attribute == 0) ? attrib_gr_normal : g_attribute;
map[ry][col].attr = attr;
if (iflags.traditional_view) {
vesa_WriteChar((unsigned char) ch, col, row, attr);
vesa_WriteChar(ch, col, row, attr);
} else {
if ((col >= clipx) && (col <= clipxmax)
&& (ry >= clipy) && (ry <= clipymax)) {
@@ -1011,6 +1024,7 @@ vesa_Init(void)
unsigned i;
unsigned num_pixels, num_oview_pixels;
const char *tile_file;
const char *font_name;
int tilefailure = 0;
if (inited) return;
@@ -1063,6 +1077,11 @@ vesa_Init(void)
vesa_SwitchMode(vesa_mode);
vesa_SetViewPort();
windowprocs.win_cliparound = vesa_cliparound;
#ifdef ENHANCED_SYMBOLS
if (vesa_pixel_size > 8) {
windowprocs.wincap2 |= WC2_U_24BITCOLOR;
}
#endif
#ifdef USE_TILES
paletteptr = get_palette();
iflags.tile_view = TRUE;
@@ -1090,22 +1109,48 @@ vesa_Init(void)
vesa_oview_height = (unsigned) iflags.wc_tile_height;
}
/* Use the map font size to set the font size */
/* Supported sizes are 8x16, 16x32, 24x48 and 32x64 */
vesa_char_height = iflags.wc_fontsiz_map;
if (vesa_char_height <= 0 || vesa_char_height > vesa_y_res / 30) {
vesa_char_height = vesa_y_res / 30;
}
if (vesa_char_height < 32) {
vesa_char_height = 16;
} else if (vesa_char_height < 48) {
vesa_char_height = 32;
} else if (vesa_char_height < 64) {
vesa_char_height = 48;
/* Load a font of size appropriate to the screen size */
if (vesa_x_res >= 1280 && vesa_y_res >= 960)
font_name = "ter-u32b.psf";
else if (vesa_x_res >= 1120 && vesa_y_res >= 840)
font_name = "ter-u28b.psf";
else if (vesa_x_res >= 960 && vesa_y_res >= 720)
font_name = "ter-u24b.psf";
else if (vesa_x_res >= 880 && vesa_y_res >= 660)
font_name = "ter-u22b.psf";
else if (vesa_x_res >= 800 && vesa_y_res >= 600)
font_name = "ter-u20b.psf";
else if (vesa_x_res >= 720 && vesa_y_res >= 540)
font_name = "ter-u18b.psf";
else
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(vesa_font);
vesa_font = load_font(font_name);
/* if load_font fails, vesa_font is NULL and we'll fall back to the font
defined in ROM */
if (vesa_font != NULL) {
vesa_char_width = vesa_font->width;
vesa_char_height = vesa_font->height;
} else {
vesa_char_height = 64;
/* Use the map font size to set the font size */
/* Supported sizes are 8x16, 16x32, 24x48 and 32x64 */
vesa_char_height = iflags.wc_fontsiz_map;
if (vesa_char_height <= 0 || vesa_char_height > vesa_y_res / 30) {
vesa_char_height = vesa_y_res / 30;
}
if (vesa_char_height < 32) {
vesa_char_height = 16;
} else if (vesa_char_height < 48) {
vesa_char_height = 32;
} else if (vesa_char_height < 64) {
vesa_char_height = 48;
} else {
vesa_char_height = 64;
}
vesa_char_width = vesa_char_height / 2;
}
vesa_char_width = vesa_char_height / 2;
/* Process tiles for the current video mode */
vesa_tiles = (unsigned char **) alloc(total_tiles_used * sizeof(void *));
@@ -1333,8 +1378,12 @@ vesa_detect(void)
}
/* Scan the mode list for an acceptable mode */
/* Choose the widest bit-width, even if the tile set can handle 8 bits,
so that Unicode symbols can display in their colors */
#ifndef ENHANCED_SYMBOLS
if (get_palette() != NULL && vesa_mode == 0xFFFF)
vesa_mode = vesa_FindMode(mode_addr, 8);
#endif
if (vesa_mode == 0xFFFF)
vesa_mode = vesa_FindMode(mode_addr, 32);
if (vesa_mode == 0xFFFF)
@@ -1508,7 +1557,7 @@ vesa_FindMode(unsigned long mode_addr, unsigned bits)
*
*/
static void
vesa_WriteChar(int chr, int col, int row, int colour)
vesa_WriteChar(uint32 chr, int col, int row, uint32 colour)
{
int pixx, pixy;
@@ -1527,7 +1576,7 @@ vesa_WriteChar(int chr, int col, int row, int colour)
* transparency
*/
static void
vesa_WriteCharXY(int chr, int pixx, int pixy, int colour)
vesa_WriteCharXY(uint32 chr, int pixx, int pixy, uint32 colour)
{
/* Flush if cache is full or if not contiguous to the last character */
if (chr_cache_size >= SIZE(chr_cache)) {
@@ -1604,13 +1653,18 @@ vesa_WriteTextRow(int pixx, int pixy, struct VesaCharacter const *t_row,
/* Second loop: draw one raster line of one character */
x = 0;
for (i = 0; i < t_row_width; ++i) {
int chr = t_row[i].chr;
int colour = t_row[i].colour + FIRST_TEXT_COLOR;
uint32 chr = t_row[i].chr;
uint32 colour = t_row[i].colour;
/* Preprocess the foreground color */
if (vesa_pixel_bytes == 1) {
fg[0] = colour;
if (colour & 0x80000000) {
fg[0] = colour & 0xFF;
fg[1] = (colour >> 8) & 0xFF;
fg[2] = (colour >> 16) & 0xFF;
fg[3] = 0;
} else if (vesa_pixel_bytes == 1) {
fg[0] = colour + FIRST_TEXT_COLOR;
} else {
unsigned long pix = vesa_palette[colour];
unsigned long pix = vesa_palette[colour + FIRST_TEXT_COLOR];
fg[0] = pix & 0xFF;
fg[1] = (pix >> 8) & 0xFF;
fg[2] = (pix >> 16) & 0xFF;
@@ -1655,8 +1709,9 @@ vesa_GetCharPixel(int ch, unsigned x, unsigned y)
}
static unsigned char
vesa_GetCharPixelRow(int ch, unsigned x, unsigned y)
vesa_GetCharPixelRow(uint32 ch, unsigned x, unsigned y)
{
unsigned fnt_width;
unsigned x1;
unsigned char fnt;
size_t offset;
@@ -1664,30 +1719,38 @@ vesa_GetCharPixelRow(int ch, unsigned x, unsigned y)
if (x >= vesa_char_width) return 0;
if (y >= vesa_char_height) return 0;
fnt_width = (vesa_char_width + 7) / 8;
x1 = x / 8;
const unsigned char __far *fp;
if (vesa_font != NULL) {
const unsigned char *fp;
if (ch < 0 || 255 < ch) return FALSE;
offset = ch * 16 + (y * 16 / vesa_char_height);
fp = font;
fnt = READ_ABSOLUTE((fp + offset));
offset = y * fnt_width + x1;
fp = get_font_glyph(vesa_font, ch, SYMHANDLING(H_UTF8));
fnt = fp[offset];
} else {
const unsigned char __far *fp;
if (vesa_char_width != 8) {
unsigned long fnt2 = fnt;
unsigned width = vesa_char_width;
if (width % 3 == 0) {
fnt2 = vesa_TriplePixels(fnt2);
width /= 3;
if (255 < ch) return 0;
offset = (ch * vesa_char_height + y) * fnt_width + x1;
fp = font;
fnt = READ_ABSOLUTE((fp + offset));
if (vesa_char_width != 8) {
unsigned long fnt2 = fnt;
unsigned width = vesa_char_width;
if (width % 3 == 0) {
fnt2 = vesa_TriplePixels(fnt2);
width /= 3;
}
while (width > 8) {
fnt2 = vesa_DoublePixels(fnt2);
width /= 2;
}
fnt2 <<= 32 - vesa_char_width;
fnt = (unsigned char)(fnt2 >> (24 - 8 * x1));
}
while (width > 8) {
fnt2 = vesa_DoublePixels(fnt2);
width /= 2;
}
fnt2 <<= 32 - vesa_char_width;
fnt = (unsigned char)(fnt2 >> (24 - 8 * x1));
}
return fnt;
}

View 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,20 @@ 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;
#ifdef ENHANCED_SYMBOLS
if (psf_font != NULL && SYMHANDLING(H_UTF8) && glyphinfo->gm.u
&& glyphinfo->gm.u->utf8str) {
ch = glyphinfo->gm.u->utf32ch;
}
#endif
/* If statue glyph, map to the generic statue */
#if 0
if (GLYPH_STATUE_OFF <= glyphnum && glyphnum < GLYPH_STATUE_OFF + NUMMONS) {
@@ -389,7 +400,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 +490,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 +734,7 @@ void
vga_Init(void)
{
int i;
const char *font_name;
#ifdef USE_TILES
const char *tile_file;
@@ -773,7 +785,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 +936,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 +966,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 +975,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 +990,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 +1094,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 +1270,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 +1281,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

View File

@@ -6,6 +6,7 @@
ifdef CROSS_TO_MSDOS
#
$(TARGETPFX)msdos.o : ../sys/msdos/msdos.c $(HACK_H)
$(TARGETPFX)font.o : ../sys/msdos/font.c ../sys/msdos/font.h $(HACK_H)
$(TARGETPFX)pckeys.o : ../sys/msdos/pckeys.c $(HACK_H)
$(TARGETPFX)pctiles.o : ../sys/msdos/pctiles.c ../sys/msdos/portio.h $(HACK_H)
$(TARGETPFX)video.o : ../sys/msdos/video.c ../sys/msdos/portio.h $(HACK_H)
@@ -14,7 +15,7 @@ $(TARGETPFX)vidtxt.o : ../sys/msdos/vidtxt.c ../sys/msdos/portio.h \
$(TARGETPFX)vidvga.o : ../sys/msdos/vidvga.c ../sys/msdos/portio.h \
../win/share/tile.h ../include/tileset.h $(HACK_H)
$(TARGETPFX)vidvesa.o : ../sys/msdos/vidvesa.c ../sys/msdos/portio.h \
../win/share/tile.h ../include/tileset.h $(HACK_H)
../win/share/tile.h ../include/tileset.h ../sys/msdos/font.h $(HACK_H)
$(TARGETPFX)vidstub.o : ../sys/msdos/vidvesa.c ../sys/msdos/portio.h \
$(HACK_H)
$(TARGETPFX)tile.o : tile.c
@@ -42,11 +43,7 @@ $(FONTDIR)/ter-u32b.psf: $(FONTTOP)/ter-u32b.bdf $(FONTDIR)/makefont.lua $(LUABI
$(LUABIN) $(FONTDIR)/makefont.lua $(FONTTOP)/ter-u32b.bdf $@
#
.PHONY: dodata dospkg dosfonts
ifdef WANT_DOSVGA
dosfonts: $(FONTTARGETS)
else
dosfonts:
endif
dospkg: dodata dosfonts $(GAMEBIN) $(TARGETPFX)recover.exe ../dat/nhtiles.bmp
$(TARGET_STUBEDIT) $(GAMEBIN) minstack=2048K
mkdir -p $(TARGETPFX)pkg
@@ -59,7 +56,6 @@ dospkg: dodata dosfonts $(GAMEBIN) $(TARGETPFX)recover.exe ../dat/nhtiles.bmp
cp ../sys/share/NetHack.cnf $(TARGETPFX)pkg/NETHACK.CNF
cp ../sys/msdos/sysconf $(TARGETPFX)pkg/SYSCONF
cp ../doc/nethack.txt $(TARGETPFX)pkg/NETHACK.TXT
ifdef WANT_DOSVGA
cp ../sys/msdos/fonts/ter-u16b.psf $(TARGETPFX)pkg/TER-U16B.PSF
cp ../sys/msdos/fonts/ter-u16v.psf $(TARGETPFX)pkg/TER-U16V.PSF
cp ../sys/msdos/fonts/ter-u18b.psf $(TARGETPFX)pkg/TER-U18B.PSF
@@ -68,7 +64,6 @@ ifdef WANT_DOSVGA
cp ../sys/msdos/fonts/ter-u24b.psf $(TARGETPFX)pkg/TER-U24B.PSF
cp ../sys/msdos/fonts/ter-u28b.psf $(TARGETPFX)pkg/TER-U28B.PSF
cp ../sys/msdos/fonts/ter-u32b.psf $(TARGETPFX)pkg/TER-U32B.PSF
endif
cp ../lib/djgpp/cwsdpmi/bin/CWSDPMI.EXE $(TARGETPFX)pkg/CWSDPMI.EXE
-touch $(TARGETPFX)pkg/RECORD
cd $(TARGETPFX)pkg ; zip -9 ../NH370DOS.ZIP * ; cd ../../..

View File

@@ -185,6 +185,7 @@ override SYSSRC = ../sys/share/pcmain.c ../sys/msdos/msdos.c \
../sys/share/pcunix.c ../sys/msdos/video.c \
../sys/msdos/vidtxt.c ../sys/msdos/pckeys.c \
../sys/msdos/vidvga.c ../sys/msdos/vidvesa.c \
../sys/msdos/font.c \
../win/share/bmptiles.c ../win/share/giftiles.c \
../win/share/tileset.c
override SYSOBJ= $(TARGETPFX)pcmain.o $(TARGETPFX)msdos.o \
@@ -192,6 +193,7 @@ override SYSOBJ= $(TARGETPFX)pcmain.o $(TARGETPFX)msdos.o \
$(TARGETPFX)pcunix.o $(TARGETPFX)video.o \
$(TARGETPFX)vidtxt.o $(TARGETPFX)pckeys.o \
$(TARGETPFX)vidvga.o $(TARGETPFX)vidvesa.o \
$(TARGETPFX)font.o \
$(TARGETPFX)bmptiles.o $(TARGETPFX)giftiles.o \
$(TARGETPFX)tileset.o $(TARGETPFX)tile.o
override WINLIB=