Merge branch 'msdos-tile-processing' of https://github.com/chasonr/NetHack into NetHack-5.0

This commit is contained in:
nhmall
2026-07-06 07:53:06 -04:00
3 changed files with 143 additions and 60 deletions
+59 -24
View File
@@ -60,6 +60,8 @@ static unsigned long vesa_DoublePixels(unsigned long);
static unsigned long vesa_TriplePixels(unsigned long); static unsigned long vesa_TriplePixels(unsigned long);
static void vesa_WriteStr(const char *, int, int, int, int); static void vesa_WriteStr(const char *, int, int, int, int);
static unsigned char __far *vesa_FontPtrs(void); static unsigned char __far *vesa_FontPtrs(void);
static unsigned char *vesa_tile(unsigned);
static unsigned char *vesa_oview_tile(unsigned);
/* static void vesa_process_tile(struct TileImage *tile); */ /* static void vesa_process_tile(struct TileImage *tile); */
#ifdef POSITIONBAR #ifdef POSITIONBAR
@@ -849,7 +851,7 @@ vesa_redrawmap(void)
for (cy = 0; cy < ROWNO; ++cy) { for (cy = 0; cy < ROWNO; ++cy) {
for (py = 0; py < vesa_oview_height; ++py) { for (py = 0; py < vesa_oview_height; ++py) {
for (cx = 0; cx < COLNO; ++cx) { for (cx = 0; cx < COLNO; ++cx) {
tile = vesa_oview_tiles[map[cy][cx].tileidx]; tile = vesa_oview_tile(map[cy][cx].tileidx);
vesa_WritePixelRow(offset + p_row_width * cx, tile + p_row_width * py, p_row_width); vesa_WritePixelRow(offset + p_row_width * cx, tile + p_row_width * py, p_row_width);
} }
x = COLNO * vesa_oview_width; x = COLNO * vesa_oview_width;
@@ -869,7 +871,7 @@ vesa_redrawmap(void)
for (cy = clipy; cy <= (unsigned) clipymax && cy < ROWNO; ++cy) { for (cy = clipy; cy <= (unsigned) clipymax && cy < ROWNO; ++cy) {
for (py = 0; py < (unsigned) iflags.wc_tile_height; ++py) { for (py = 0; py < (unsigned) iflags.wc_tile_height; ++py) {
for (cx = clipx; cx <= (unsigned) clipxmax && cx < COLNO; ++cx) { for (cx = clipx; cx <= (unsigned) clipxmax && cx < COLNO; ++cx) {
tile = vesa_tiles[map[cy][cx].tileidx]; tile = vesa_tile(map[cy][cx].tileidx);
vesa_WritePixelRow(offset + p_row_width * (cx - clipx), tile + p_row_width * py, p_row_width); vesa_WritePixelRow(offset + p_row_width * (cx - clipx), tile + p_row_width * py, p_row_width);
} }
x = (cx - clipx) * iflags.wc_tile_width; x = (cx - clipx) * iflags.wc_tile_width;
@@ -1053,8 +1055,6 @@ vesa_Init(void)
{ {
static boolean inited = FALSE; static boolean inited = FALSE;
const struct Pixel *paletteptr; const struct Pixel *paletteptr;
unsigned i;
unsigned num_pixels, num_oview_pixels;
const char *tile_file; const char *tile_file;
const char *font_name; const char *font_name;
int tilefailure = 0; int tilefailure = 0;
@@ -1186,31 +1186,33 @@ vesa_Init(void)
/* Process tiles for the current video mode */ /* Process tiles for the current video mode */
vesa_tiles = (unsigned char **) alloc(total_tiles_used * sizeof(void *)); vesa_tiles = (unsigned char **) alloc(total_tiles_used * sizeof(void *));
memset(vesa_tiles, 0, total_tiles_used * sizeof(void *));
vesa_oview_tiles = (unsigned char **) alloc(total_tiles_used * sizeof(void *)); vesa_oview_tiles = (unsigned char **) alloc(total_tiles_used * sizeof(void *));
num_pixels = iflags.wc_tile_width * iflags.wc_tile_height; memset(vesa_oview_tiles, 0, total_tiles_used * sizeof(void *));
num_oview_pixels = vesa_oview_width * vesa_oview_height;
set_tile_type(vesa_pixel_size > 8); set_tile_type(vesa_pixel_size > 8);
for (i = 0; i < (unsigned) total_tiles_used; ++i) { }
const struct TileImage *tile = get_tile(i);
struct TileImage *ov_tile = stretch_tile(tile, vesa_oview_width, vesa_oview_height); RESTORE_WARNING_FORMAT_NONLITERAL
/* Return processed pixels for a normal tile */
static unsigned char *
vesa_tile(unsigned index)
{
if (vesa_tiles[index] == NULL) {
unsigned num_pixels = iflags.wc_tile_width * iflags.wc_tile_height;
const struct TileImage *tile = get_tile(index);
unsigned j; unsigned j;
unsigned char *t_img = (unsigned char *) alloc(num_pixels * vesa_pixel_bytes); unsigned char *t_img = (unsigned char *) alloc(num_pixels * vesa_pixel_bytes);
unsigned char *ot_img = (unsigned char *) alloc(num_oview_pixels * vesa_pixel_bytes); vesa_tiles[index] = t_img;
vesa_tiles[i] = t_img;
vesa_oview_tiles[i] = ot_img;
switch (vesa_pixel_bytes) { switch (vesa_pixel_bytes) {
case 1: case 1:
memcpy(t_img, tile->indexes, num_pixels); memcpy(t_img, tile->indexes, num_pixels);
memcpy(ot_img, ov_tile->indexes, num_oview_pixels);
break; break;
case 2: case 2:
for (j = 0; j < num_pixels; ++j) { for (j = 0; j < num_pixels; ++j) {
((uint16_t *)t_img)[j] = vesa_MakeColor(tile->pixels[j]); ((uint16_t *)t_img)[j] = vesa_MakeColor(tile->pixels[j]);
} }
for (j = 0; j < num_oview_pixels; ++j) {
((uint16_t *)ot_img)[j] = vesa_MakeColor(ov_tile->pixels[j]);
}
break; break;
case 3: case 3:
@@ -1220,6 +1222,42 @@ vesa_Init(void)
t_img[3*j + 1] = (color >> 8) & 0xFF; t_img[3*j + 1] = (color >> 8) & 0xFF;
t_img[3*j + 2] = (color >> 16) & 0xFF; t_img[3*j + 2] = (color >> 16) & 0xFF;
} }
break;
case 4:
for (j = 0; j < num_pixels; ++j) {
((uint32_t *)t_img)[j] = vesa_MakeColor(tile->pixels[j]);
}
break;
}
}
return vesa_tiles[index];
}
/* Return processed pixels for an overview tile */
static unsigned char *
vesa_oview_tile(unsigned index)
{
if (vesa_oview_tiles[index] == NULL) {
unsigned num_oview_pixels = vesa_oview_width * vesa_oview_height;
const struct TileImage *tile = get_tile(index);
struct TileImage *ov_tile = stretch_tile(tile, vesa_oview_width, vesa_oview_height);
unsigned j;
unsigned char *ot_img = (unsigned char *) alloc(num_oview_pixels * vesa_pixel_bytes);
vesa_oview_tiles[index] = ot_img;
switch (vesa_pixel_bytes) {
case 1:
memcpy(ot_img, ov_tile->indexes, num_oview_pixels);
break;
case 2:
for (j = 0; j < num_oview_pixels; ++j) {
((uint16_t *)ot_img)[j] = vesa_MakeColor(ov_tile->pixels[j]);
}
break;
case 3:
for (j = 0; j < num_oview_pixels; ++j) { for (j = 0; j < num_oview_pixels; ++j) {
unsigned long color = vesa_MakeColor(ov_tile->pixels[j]); unsigned long color = vesa_MakeColor(ov_tile->pixels[j]);
ot_img[3*j + 0] = color & 0xFF; ot_img[3*j + 0] = color & 0xFF;
@@ -1229,9 +1267,6 @@ vesa_Init(void)
break; break;
case 4: case 4:
for (j = 0; j < num_pixels; ++j) {
((uint32_t *)t_img)[j] = vesa_MakeColor(tile->pixels[j]);
}
for (j = 0; j < num_oview_pixels; ++j) { for (j = 0; j < num_oview_pixels; ++j) {
((uint32_t *)ot_img)[j] = vesa_MakeColor(ov_tile->pixels[j]); ((uint32_t *)ot_img)[j] = vesa_MakeColor(ov_tile->pixels[j]);
} }
@@ -1239,10 +1274,9 @@ vesa_Init(void)
} }
free_tile(ov_tile); free_tile(ov_tile);
} }
free_tiles();
}
RESTORE_WARNING_FORMAT_NONLITERAL return vesa_oview_tiles[index];
}
/* Set the size of the map viewport */ /* Set the size of the map viewport */
static void static void
@@ -1314,6 +1348,7 @@ vesa_Finish(void)
} }
free(vesa_tiles); free(vesa_tiles);
free(vesa_oview_tiles); free(vesa_oview_tiles);
free_tiles();
vesa_SwitchMode(MODETEXT); vesa_SwitchMode(MODETEXT);
windowprocs.win_cliparound = tty_cliparound; windowprocs.win_cliparound = tty_cliparound;
g_attribute = attrib_text_normal; g_attribute = attrib_text_normal;
@@ -1873,11 +1908,11 @@ vesa_DisplayCell(int tilenum, int col, int row)
unsigned p_row_width; unsigned p_row_width;
if (iflags.over_view) { if (iflags.over_view) {
tile = vesa_oview_tiles[tilenum]; tile = vesa_oview_tile(tilenum);
t_width = vesa_oview_width; t_width = vesa_oview_width;
t_height = vesa_oview_height; t_height = vesa_oview_height;
} else { } else {
tile = vesa_tiles[tilenum]; tile = vesa_tile(tilenum);
t_width = iflags.wc_tile_width; t_width = iflags.wc_tile_width;
t_height = iflags.wc_tile_height; t_height = iflags.wc_tile_height;
} }
+71 -25
View File
@@ -213,8 +213,8 @@ int vp[SCREENPLANES] = { 8, 4, 2, 1 };
#endif #endif
int vp2[SCREENPLANES] = { 1, 2, 4, 8 }; int vp2[SCREENPLANES] = { 1, 2, 4, 8 };
static struct planar_cell_struct planecell; static struct planar_cell_struct **cell_cache;
static struct overview_planar_cell_struct planecell_O; static struct overview_planar_cell_struct **cell_cache_O;
/* static int g_attribute; */ /* Current attribute to use */ /* static int g_attribute; */ /* Current attribute to use */
@@ -410,6 +410,7 @@ vga_xputg(const glyph_info *glyphinfo,
vga_WriteChar(ch, col, row, attr); vga_WriteChar(ch, col, row, attr);
} else if (!iflags.over_view) { } else if (!iflags.over_view) {
if ((col >= clipx) && (col <= clipxmax)) { if ((col >= clipx) && (col <= clipxmax)) {
struct planar_cell_struct planecell;
read_planar_tile(glyphnum, &planecell); read_planar_tile(glyphnum, &planecell);
if (map[ry][col].special) if (map[ry][col].special)
decal_planar(&planecell, special); decal_planar(&planecell, special);
@@ -426,6 +427,7 @@ vga_xputg(const glyph_info *glyphinfo,
} }
} }
} else { } else {
struct overview_planar_cell_struct planecell_O;
read_planar_tile_O(glyphnum, &planecell_O); read_planar_tile_O(glyphnum, &planecell_O);
vga_DisplayCell_O(&planecell_O, col, row); vga_DisplayCell_O(&planecell_O, col, row);
} }
@@ -512,11 +514,13 @@ vga_redrawmap(boolean clearfirst)
} else { } else {
t = map[y][x].glyph; t = map[y][x].glyph;
if (!iflags.over_view) { if (!iflags.over_view) {
struct planar_cell_struct planecell;
read_planar_tile(t, &planecell); read_planar_tile(t, &planecell);
if (map[y][x].special) if (map[y][x].special)
decal_planar(&planecell, map[y][x].special); decal_planar(&planecell, map[y][x].special);
vga_DisplayCell(&planecell, x - clipx, y + TOP_MAP_ROW); vga_DisplayCell(&planecell, x - clipx, y + TOP_MAP_ROW);
} else { } else {
struct overview_planar_cell_struct planecell_O;
read_planar_tile_O(t, &planecell_O); read_planar_tile_O(t, &planecell_O);
vga_DisplayCell_O(&planecell_O, x, y + TOP_MAP_ROW); vga_DisplayCell_O(&planecell_O, x, y + TOP_MAP_ROW);
} }
@@ -643,6 +647,7 @@ boolean left;
} }
for (y = 0; y < ROWNO; ++y) { for (y = 0; y < ROWNO; ++y) {
for (x = i; x < j; x += 2) { for (x = i; x < j; x += 2) {
struct planar_cell_struct planecell;
t = map[y][x].glyph; t = map[y][x].glyph;
read_planar_tile(t, &planecell); read_planar_tile(t, &planecell);
if (map[y][x].special) if (map[y][x].special)
@@ -656,47 +661,69 @@ boolean left;
static void static void
read_planar_tile(unsigned glyph, struct planar_cell_struct *cell) read_planar_tile(unsigned glyph, struct planar_cell_struct *cell)
{ {
struct planar_cell_struct *pcell;
unsigned char indexes[TILE_Y][TILE_X]; unsigned char indexes[TILE_Y][TILE_X];
unsigned plane, y, byte, bit; unsigned plane, y, byte, bit;
int tilenum = glyphmap[glyph].tileidx;
read_tile_indexes(glyph, indexes); /* Get the processed tile from the cache if we can */
/* cell->plane[0..3].image[0..15][0..1] */ pcell = cell_cache[tilenum];
for (plane = 0; plane < SCREENPLANES; ++plane) { if (pcell == NULL) {
for (y = 0; y < TILE_Y; ++y) { /* Process the tile */
for (byte = 0; byte < MAX_BYTES_PER_CELL; ++byte) { pcell = (struct planar_cell_struct *) alloc(sizeof(*pcell));
unsigned char b = 0; cell_cache[tilenum] = pcell;
for (bit = 0; bit < 8; ++bit) { read_tile_indexes(glyph, indexes);
unsigned char x = byte * 8 + bit; /* pcell->plane[0..3].image[0..15][0..1] */
unsigned char i = indexes[y][x]; for (plane = 0; plane < SCREENPLANES; ++plane) {
b <<= 1; for (y = 0; y < TILE_Y; ++y) {
if (i & (0x8 >> plane)) b |= 1; for (byte = 0; byte < MAX_BYTES_PER_CELL; ++byte) {
unsigned char b = 0;
for (bit = 0; bit < 8; ++bit) {
unsigned char x = byte * 8 + bit;
unsigned char i = indexes[y][x];
b <<= 1;
if (i & (0x8 >> plane)) b |= 1;
}
pcell->plane[plane].image[y][byte] = b;
} }
cell->plane[plane].image[y][byte] = b;
} }
} }
} }
*cell = *pcell;
} }
static void static void
read_planar_tile_O(unsigned glyph, struct overview_planar_cell_struct *cell) read_planar_tile_O(unsigned glyph, struct overview_planar_cell_struct *cell)
{ {
struct overview_planar_cell_struct *pcell;
unsigned char indexes[TILE_Y][TILE_X]; unsigned char indexes[TILE_Y][TILE_X];
unsigned plane, y, bit; unsigned plane, y, bit;
int tilenum = glyphmap[glyph].tileidx;
read_tile_indexes(glyph, indexes); /* Get the processed tile from the cache if we can */
/* cell->plane[0..3].image[0..15][0..0] */ pcell = cell_cache_O[tilenum];
for (plane = 0; plane < SCREENPLANES; ++plane) { if (pcell == NULL) {
for (y = 0; y < TILE_Y; ++y) { /* Process the tile */
unsigned char b = 0; pcell = (struct overview_planar_cell_struct *) alloc(sizeof(*pcell));
for (bit = 0; bit < 8; ++bit) { cell_cache_O[tilenum] = pcell;
unsigned char x = bit * 2; read_tile_indexes(glyph, indexes);
unsigned char i = indexes[y][x]; /* pcell->plane[0..3].image[0..15][0..0] */
b <<= 1; for (plane = 0; plane < SCREENPLANES; ++plane) {
if (i & (0x8 >> plane)) b |= 1; for (y = 0; y < TILE_Y; ++y) {
unsigned char b = 0;
for (bit = 0; bit < 8; ++bit) {
unsigned char x = bit * 2;
unsigned char i = indexes[y][x];
b <<= 1;
if (i & (0x8 >> plane)) b |= 1;
}
pcell->plane[plane].image[y][0] = b;
} }
cell->plane[plane].image[y][0] = b;
} }
} }
*cell = *pcell;
} }
static void static void
@@ -782,6 +809,15 @@ vga_Init(void)
/* term_clear_screen() */ /* not vga_clear_screen() */ /* term_clear_screen() */ /* not vga_clear_screen() */
return; return;
} }
if (cell_cache == NULL) {
cell_cache = (struct planar_cell_struct **) alloc(
total_tiles_used * sizeof(cell_cache[0]));
memset(cell_cache, 0, total_tiles_used * sizeof(cell_cache[0]));
cell_cache_O = (struct overview_planar_cell_struct **) alloc(
total_tiles_used * sizeof(cell_cache_O[0]));
memset(cell_cache_O, 0, total_tiles_used * sizeof(cell_cache_O[0]));
}
#endif #endif
if (iflags.usevga) { if (iflags.usevga) {
@@ -860,7 +896,17 @@ vga_SwitchMode(unsigned int mode)
void void
vga_Finish(void) vga_Finish(void)
{ {
int i;
free_tiles(); free_tiles();
for (i = 0; i < total_tiles_used; ++i) {
free(cell_cache[i]);
free(cell_cache_O[i]);
}
free(cell_cache);
cell_cache = NULL;
free(cell_cache_O);
cell_cache_O = NULL;
vga_SwitchMode(MODETEXT); vga_SwitchMode(MODETEXT);
windowprocs.win_cliparound = tty_cliparound; windowprocs.win_cliparound = tty_cliparound;
g_attribute = attrib_text_normal; g_attribute = attrib_text_normal;
+13 -11
View File
@@ -30,6 +30,9 @@ read_tiles(const char *filename, boolean true_color)
char header[16]; char header[16];
boolean ok; boolean ok;
if (tiles != NULL)
return TRUE;
/* Fill the image structure with known values */ /* Fill the image structure with known values */
image.width = 0; image.width = 0;
image.height = 0; image.height = 0;
@@ -283,7 +286,7 @@ split_tiles(const struct TileSetImage *image)
{ {
unsigned tile_rows, tile_cols; unsigned tile_rows, tile_cols;
size_t tile_size, i, j; size_t tile_size, i, j;
unsigned x1, y1, x2, y2; unsigned x1, y1, y2;
/* Get the number of tiles */ /* Get the number of tiles */
tile_rows = image->height / iflags.wc_tile_height; tile_rows = image->height / iflags.wc_tile_height;
@@ -308,16 +311,15 @@ split_tiles(const struct TileSetImage *image)
tile->indexes = (unsigned char *) alloc(tile_size); tile->indexes = (unsigned char *) alloc(tile_size);
} }
for (y2 = 0; y2 < (unsigned) iflags.wc_tile_height; ++y2) { for (y2 = 0; y2 < (unsigned) iflags.wc_tile_height; ++y2) {
for (x2 = 0; x2 < (unsigned) iflags.wc_tile_width; ++x2) { unsigned y = y1 * iflags.wc_tile_height + y2;
unsigned x = x1 * iflags.wc_tile_width + x2; unsigned x = x1 * iflags.wc_tile_width;
unsigned y = y1 * iflags.wc_tile_height + y2; i = y * image->width;
j = y2 * tile->width;
i = y * image->width + x; memcpy(tile->pixels + j, image->pixels + i + x,
j = y2 * tile->width + x2; sizeof(tile->pixels[0]) * iflags.wc_tile_width);
tile->pixels[j] = image->pixels[i]; if (image->indexes != NULL) {
if (image->indexes != NULL) { memcpy(tile->indexes + j, image->indexes + i + x,
tile->indexes[j] = image->indexes[i]; iflags.wc_tile_width);
}
} }
} }
} }