More decal support for VESA

* Support decals in overview mode
* Draw decals when redrawing the map
This commit is contained in:
Ray Chason
2026-08-04 09:38:38 -04:00
parent 85bb8c1fbc
commit 9d5184562e
+155 -101
View File
@@ -47,7 +47,9 @@ static unsigned long vesa_ReadPixel32(unsigned x, unsigned y);
static void vesa_WritePixel32(unsigned x, unsigned y, unsigned long color);
static void vesa_WritePixel(unsigned x, unsigned y, unsigned color);
static void vesa_WritePixelRow(unsigned long offset,
unsigned char const *p_row, unsigned p_row_size);
unsigned char const *p_row,
unsigned char const *p_decal_row,
unsigned p_row_size);
static unsigned long vesa_MakeColor(struct Pixel);
static void vesa_FillRect(unsigned left, unsigned top, unsigned width,
unsigned height, unsigned color);
@@ -66,7 +68,7 @@ static boolean vesa_SetHardPalette(const struct Pixel *);
static boolean vesa_SetSoftPalette(const struct Pixel *);
#ifdef TILES_IN_GLYPHMAP
static void vesa_DisplayCell(int, int, int, uint8_t);
static unsigned char const *tile_with_decal(unsigned char const *, unsigned char const *);
static uint8_t *add_transparent_row(uint8_t const *, uint8_t const *, unsigned, uint32_t);
#endif
static unsigned vesa_FindMode(unsigned long mode_addr, unsigned bits);
static void vesa_WriteChar(uint32, int, int, uint32);
@@ -112,13 +114,15 @@ static struct map_struct {
uint32 ch;
uint32 attr;
unsigned special;
short int tileidx;
uint16_t tileidx;
uint16_t decalnum;
int framecolor;
int inverse;
} map[ROWNO][COLNO]; /* track the glyphs */
enum { delimdecal, petdecal, piledecal, NUMDECALS };
static unsigned char *vesa_decals[NUMDECALS] = { 0 };
static unsigned char *vesa_oview_decals[NUMDECALS] = { 0 };
static unsigned char *tmptilebuf;
static uint32_t tilebackground;
@@ -133,6 +137,7 @@ static uint32_t tilebackground;
map[y][x].attr = 0; \
map[y][x].special = 0; \
map[y][x].tileidx = Tile_unexplored; \
map[y][x].decalnum = 0; \
map[y][x].inverse = 0; \
} \
}
@@ -496,8 +501,22 @@ vesa_WritePixel(unsigned x, unsigned y, unsigned color)
static void
vesa_WritePixelRow(unsigned long offset,
unsigned char const *p_row, unsigned p_row_size)
unsigned char const *p_row,
unsigned char const *p_decal_row,
unsigned p_row_size)
{
#ifdef TILES_IN_GLYPHMAP
uint8_t *p_combined_row = NULL; /* custodial */
if (p_decal_row != NULL) {
p_combined_row = add_transparent_row(
p_row, p_decal_row, p_row_size, tilebackground);
p_row = p_combined_row;
}
#else
nhUse(p_decal_row);
#endif
if (vesa_segment != 0) {
/* Linear frame buffer in use */
movedata(_go32_my_ds(), (unsigned)p_row, vesa_segment, offset, p_row_size);
@@ -516,6 +535,10 @@ vesa_WritePixelRow(unsigned long offset,
}
dosmemput(p_row + i, p_row_size - i, addr);
}
#ifdef TILES_IN_GLYPHMAP
free(p_combined_row);
#endif
}
static unsigned long
@@ -566,7 +589,7 @@ vesa_FillRect(unsigned left, unsigned top, unsigned width,
}
for (y = 0; y < height; ++y) {
vesa_WritePixelRow(offset, p_row, p_row_size);
vesa_WritePixelRow(offset, p_row, NULL, p_row_size);
offset += vesa_scan_line;
}
@@ -745,7 +768,18 @@ vesa_xputg(const glyph_info *glyphinfo, const glyph_info *bkglyphinfo UNUSED)
if (!vesa_decals[piledecal])
vesa_decals[piledecal] = vesa_tile(Tile_pilemark);
if (!vesa_oview_decals[petdecal])
vesa_oview_decals[petdecal] = vesa_oview_tile(Tile_petmark);
if (!vesa_oview_decals[piledecal])
vesa_oview_decals[piledecal] = vesa_oview_tile(Tile_pilemark);
}
unsigned decalnum = ((special & MG_PET) && iflags.hilite_pet)
? petdecal
: ((special & MG_OBJPILE) && iflags.hilite_pile)
? piledecal : 0;
#ifdef ENHANCED_SYMBOLS
if (SYMHANDLING(H_UTF8) && glyphinfo->gm.u && glyphinfo->gm.u->utf8str) {
@@ -775,6 +809,7 @@ vesa_xputg(const glyph_info *glyphinfo, const glyph_info *bkglyphinfo UNUSED)
map[ry][col].ch = ch;
map[ry][col].special = special;
map[ry][col].tileidx = glyphinfo->gm.tileidx;
map[ry][col].decalnum = decalnum;
map[ry][col].attr = attr;
map[ry][col].inverse = inversed;
@@ -791,11 +826,7 @@ vesa_xputg(const glyph_info *glyphinfo, const glyph_info *bkglyphinfo UNUSED)
if (!iflags.over_view && map[ry][col].special)
decal_packed(packcell, special);
#endif
vesa_DisplayCell(glyphinfo->gm.tileidx, col - clipx, ry - clipy,
((special & MG_PET) && iflags.hilite_pet)
? petdecal
: ((special & MG_OBJPILE) && iflags.hilite_pile)
? piledecal : 0);
vesa_DisplayCell(glyphinfo->gm.tileidx, col - clipx, ry - clipy, decalnum);
if (bkglyphinfo->framecolor != NO_COLOR) {
int curtypbak = cursor_type;
int cclr = cursor_color;
@@ -908,15 +939,20 @@ vesa_redrawmap(void)
}
} else if (iflags.over_view) {
/* Overview mode */
const unsigned char *tile;
p_row_width = vesa_oview_width * vesa_pixel_bytes;
y = y_top;
for (cy = 0; cy < ROWNO; ++cy) {
for (py = 0; py < vesa_oview_height; ++py) {
for (cx = 0; cx < COLNO; ++cx) {
tile = vesa_oview_tile(map[cy][cx].tileidx);
vesa_WritePixelRow(offset + p_row_width * cx, tile + p_row_width * py, p_row_width);
const uint8_t *tile = vesa_oview_tile(map[cy][cx].tileidx);
const uint8_t *decal = NULL;
unsigned decalnum = map[cy][cx].decalnum;
if (decalnum != 0 && decalnum < NUMDECALS) {
decal = vesa_oview_decals[decalnum];
decal += p_row_width * py;
}
vesa_WritePixelRow(offset + p_row_width * cx, tile + p_row_width * py, decal, p_row_width);
}
x = COLNO * vesa_oview_width;
if (x < vesa_x_res) {
@@ -928,15 +964,20 @@ vesa_redrawmap(void)
}
} else {
/* Normal tiled mode */
const unsigned char *tile;
p_row_width = iflags.wc_tile_width * vesa_pixel_bytes;
y = y_top;
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_tile(map[cy][cx].tileidx);
vesa_WritePixelRow(offset + p_row_width * (cx - clipx), tile + p_row_width * py, p_row_width);
const uint8_t *tile = vesa_tile(map[cy][cx].tileidx);
const uint8_t *decal = NULL;
unsigned decalnum = map[cy][cx].decalnum;
if (decalnum != 0 && decalnum < NUMDECALS) {
decal = vesa_decals[decalnum];
decal += p_row_width * py;
}
vesa_WritePixelRow(offset + p_row_width * (cx - clipx), tile + p_row_width * py, decal, p_row_width);
}
x = (cx - clipx) * iflags.wc_tile_width;
if (x < vesa_x_res) {
@@ -1867,7 +1908,7 @@ vesa_WriteTextRow(int pixx, int pixy, struct VesaCharacter const *t_row,
}
}
}
vesa_WritePixelRow(offset, p_row, p_row_width);
vesa_WritePixelRow(offset, p_row, NULL, p_row_width);
offset += vesa_scan_line;
}
free(p_row);
@@ -2011,101 +2052,114 @@ vesa_DisplayCell(int tilenum, int col, int row, uint8_t decalnum)
pixx += vesa_x_center;
pixy += vesa_y_center;
offset = pixy * (unsigned long)vesa_scan_line + pixx * vesa_pixel_bytes;
decal = (decalnum == petdecal)
? vesa_decals[petdecal]
: (decalnum == piledecal)
? vesa_decals[piledecal]
: NULL;
tptr = (decal == NULL) ? tile : tile_with_decal(tile, decal);
if (decalnum != 0 && decalnum < NUMDECALS) {
if (iflags.over_view) {
decal = vesa_oview_decals[decalnum];
} else {
decal = vesa_decals[decalnum];
}
} else {
decal = NULL;
}
tptr = tile;
for (py = 0; py < (int) t_height; ++py) {
vesa_WritePixelRow(offset, tptr, p_row_width);
vesa_WritePixelRow(offset, tptr, decal, p_row_width);
offset += vesa_scan_line;
tptr += p_row_width;
if (decal != NULL) {
decal += p_row_width;
}
}
}
unsigned char const *
tile_with_decal(unsigned char const *tile, unsigned char const *decal)
/* Overlay a transparent row onto the given pixel row */
/* Return an allocated buffer containing the overlaid row */
/* The caller is responsible for freeing the returned row */
static uint8_t *
add_transparent_row(
uint8_t const *p_row,
uint8_t const *p_overlay,
unsigned p_row_size,
uint32_t transparent_pixel)
{
int tr, tc;
unsigned char const *tptr, *declptr;
unsigned char *dst;
/*
* ignore the "background" pixels in decal,
* which is identified by the delim tile in the stock
* tile set which is 100% background.
*/
uint8_t *p_combined_row = (uint8_t *) alloc(p_row_size);
switch(vesa_pixel_bytes) {
case 1: {
uint8_t *t1 = (uint8_t *) p_row,
*t2 = (uint8_t *) p_overlay,
*t3 = (uint8_t *) p_combined_row;
if (!tmptilebuf)
tmptilebuf = (unsigned char *)
alloc(iflags.wc_tile_width * vesa_pixel_bytes * iflags.wc_tile_height);
tptr = tile;
declptr = decal;
dst = tmptilebuf;
for (tr = 0; tr < iflags.wc_tile_height; ++tr) {
for (tc = 0; tc < iflags.wc_tile_width; ++tc) {
/*
* ignore the "background" pixels in decal,
* which is identified by the delim tile in the stock
* tile set which is 100% background.
*/
switch(vesa_pixel_bytes) {
case 1: {
uint8_t *t1 = (uint8_t *) tptr,
*t2 = (uint8_t *) declptr,
*t3 = (uint8_t *) dst;
*t3 = (*t2 != tilebackground) ? *t2 : *t1;
}
break;
case 2: {
uint16_t *t1 = (uint16_t *) tptr,
*t2 = (uint16_t *) declptr,
*t3 = (uint16_t *) dst;
*t3 = (*t2 != tilebackground) ? *t2 : *t1;
}
break;
case 3: {
uint8_t *t1 = (uint8_t *) tptr,
*t2 = (uint8_t *) declptr,
*t3 = (uint8_t *) dst;
uint32_t pix = ((uint32_t) t2[2] << 16)
| ((uint32_t) t2[1] << 8)
| ((uint32_t) t2[0] << 0);
if (pix != tilebackground) {
t3[0] = t2[0];
t3[1] = t2[1];
t3[2] = t2[2];
} else {
t3[0] = t1[0];
t3[1] = t1[1];
t3[2] = t1[2];
}
}
break;
case 4: {
uint32_t *t1 = (uint32_t *) tptr,
*t2 = (uint32_t *) declptr,
*t3 = (uint32_t *) dst;
*t3 = ((*t2 & 0x00FFFFFF) != tilebackground) ? *t2 : *t1;
}
break;
default: {
unsigned char const *t1 = tptr;
unsigned char *t3 = dst;
for (int i = 0; i < vesa_pixel_bytes; ++i) {
*t3 = *t1;
}
}
break;
for (unsigned i = 0; i < p_row_size; i += vesa_pixel_bytes) {
*t3 = (*t2 != transparent_pixel) ? *t2 : *t1;
++t1;
++t2;
++t3;
}
}
tptr += vesa_pixel_bytes;
dst += vesa_pixel_bytes;
declptr += vesa_pixel_bytes;
}
break;
case 2: {
uint16_t *t1 = (uint16_t *) p_row,
*t2 = (uint16_t *) p_overlay,
*t3 = (uint16_t *) p_combined_row;
for (unsigned i = 0; i < p_row_size; i += vesa_pixel_bytes) {
*t3 = (*t2 != transparent_pixel) ? *t2 : *t1;
++t1;
++t2;
++t3;
}
}
break;
case 3: {
uint8_t *t1 = (uint8_t *) p_row,
*t2 = (uint8_t *) p_overlay,
*t3 = (uint8_t *) p_combined_row;
for (unsigned i = 0; i < p_row_size; i += vesa_pixel_bytes) {
uint32_t pix = ((uint32_t) t2[2] << 16)
| ((uint32_t) t2[1] << 8)
| ((uint32_t) t2[0] << 0);
if (pix != transparent_pixel) {
t3[0] = t2[0];
t3[1] = t2[1];
t3[2] = t2[2];
} else {
t3[0] = t1[0];
t3[1] = t1[1];
t3[2] = t1[2];
}
t1 += 3;
t2 += 3;
t3 += 3;
}
}
break;
case 4: {
uint32_t *t1 = (uint32_t *) p_row,
*t2 = (uint32_t *) p_overlay,
*t3 = (uint32_t *) p_combined_row;
for (unsigned i = 0; i < p_row_size; i += vesa_pixel_bytes) {
*t3 = ((*t2 & 0x00FFFFFF) != transparent_pixel) ? *t2 : *t1;
++t1;
++t2;
++t3;
}
}
break;
default:
/* This isn't supposed to happen */
memcpy(p_combined_row, p_row, p_row_size);
break;
}
return tmptilebuf;
return p_combined_row;
}
#endif /* TILES_IN_GLYPHMAP */