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