Support pet and tile decals in 16 color mode
This commit is contained in:
+147
-26
@@ -121,6 +121,7 @@ static void vga_scrollmap(boolean);
|
||||
static void vga_redrawmap(boolean);
|
||||
static void vga_cliparound(int, int);
|
||||
static void decal_planar(struct planar_cell_struct *, unsigned);
|
||||
static void decal_oview_planar(struct overview_planar_cell_struct *, unsigned);
|
||||
#endif
|
||||
|
||||
#ifdef POSITIONBAR
|
||||
@@ -141,6 +142,7 @@ static void vga_WriteStr(char *, int, int, int, int);
|
||||
static char __far *vga_FontPtrs(void);
|
||||
|
||||
#ifdef TILES_IN_GLYPHMAP
|
||||
static int glyph_to_tilenum(unsigned);
|
||||
static void read_planar_tile(unsigned, struct planar_cell_struct *);
|
||||
static void read_planar_tile_O(unsigned,
|
||||
struct overview_planar_cell_struct *);
|
||||
@@ -243,6 +245,10 @@ static int vp[SCREENPLANES] = { 8, 4, 2, 1 };
|
||||
#ifdef TILES_IN_GLYPHMAP
|
||||
static struct planar_cell_struct **cell_cache;
|
||||
static struct overview_planar_cell_struct **cell_cache_O;
|
||||
|
||||
enum { delimdecal, petdecal, piledecal, NUMDECALS };
|
||||
static struct cellplane *decal_alpha[NUMDECALS] = { 0 };
|
||||
static struct overview_cellplane *decal_oview_alpha[NUMDECALS] = { 0 };
|
||||
#endif
|
||||
|
||||
/* static int g_attribute; */ /* Current attribute to use */
|
||||
@@ -442,8 +448,8 @@ vga_xputg(const glyph_info *glyphinfo,
|
||||
} 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)
|
||||
read_planar_tile(glyph_to_tilenum(glyphnum), &planecell);
|
||||
if (special)
|
||||
decal_planar(&planecell, special);
|
||||
vga_DisplayCell(&planecell, col - clipx, row);
|
||||
if (bkglyphinfo->framecolor != NO_COLOR) {
|
||||
@@ -459,7 +465,9 @@ vga_xputg(const glyph_info *glyphinfo,
|
||||
}
|
||||
} else {
|
||||
struct overview_planar_cell_struct planecell_O;
|
||||
read_planar_tile_O(glyphnum, &planecell_O);
|
||||
read_planar_tile_O(glyph_to_tilenum(glyphnum), &planecell_O);
|
||||
if (special)
|
||||
decal_oview_planar(&planecell_O, special);
|
||||
vga_DisplayCell_O(&planecell_O, col, row);
|
||||
}
|
||||
if (col < (CO - 1))
|
||||
@@ -546,13 +554,15 @@ vga_redrawmap(boolean clearfirst)
|
||||
t = map[y][x].glyph;
|
||||
if (!iflags.over_view) {
|
||||
struct planar_cell_struct planecell;
|
||||
read_planar_tile(t, &planecell);
|
||||
read_planar_tile(glyph_to_tilenum(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);
|
||||
read_planar_tile_O(glyph_to_tilenum(t), &planecell_O);
|
||||
if (map[y][x].special)
|
||||
decal_oview_planar(&planecell_O, map[y][x].special);
|
||||
vga_DisplayCell_O(&planecell_O, x, y + TOP_MAP_ROW);
|
||||
}
|
||||
}
|
||||
@@ -684,7 +694,7 @@ boolean left;
|
||||
for (x = i; x < j; x += 2) {
|
||||
struct planar_cell_struct planecell;
|
||||
t = map[y][x].glyph;
|
||||
read_planar_tile(t, &planecell);
|
||||
read_planar_tile(glyph_to_tilenum(t), &planecell);
|
||||
if (map[y][x].special)
|
||||
decal_planar(&planecell, map[y][x].special);
|
||||
vga_DisplayCell(&planecell, x - clipx, y + TOP_MAP_ROW);
|
||||
@@ -693,13 +703,23 @@ boolean left;
|
||||
}
|
||||
#endif /* SCROLLMAP */
|
||||
|
||||
static int
|
||||
glyph_to_tilenum(unsigned glyph)
|
||||
{
|
||||
/* We don't have enough colors to show the statues */
|
||||
if (glyph_is_statue(glyph)) {
|
||||
glyph = GLYPH_OBJ_OFF + STATUE;
|
||||
}
|
||||
|
||||
return glyphmap[glyph].tileidx;
|
||||
}
|
||||
|
||||
static void
|
||||
read_planar_tile(unsigned glyph, struct planar_cell_struct *cell)
|
||||
read_planar_tile(unsigned tilenum, 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;
|
||||
|
||||
/* Get the processed tile from the cache if we can */
|
||||
pcell = cell_cache[tilenum];
|
||||
@@ -707,7 +727,7 @@ read_planar_tile(unsigned glyph, struct planar_cell_struct *cell)
|
||||
/* Process the tile */
|
||||
pcell = (struct planar_cell_struct *) alloc(sizeof(*pcell));
|
||||
cell_cache[tilenum] = pcell;
|
||||
read_tile_indexes(glyph, indexes);
|
||||
read_tile_indexes(tilenum, indexes);
|
||||
/* pcell->plane[0..3].image[0..15][0..1] */
|
||||
for (plane = 0; plane < SCREENPLANES; ++plane) {
|
||||
for (y = 0; y < TILE_Y; ++y) {
|
||||
@@ -729,12 +749,11 @@ read_planar_tile(unsigned glyph, struct planar_cell_struct *cell)
|
||||
}
|
||||
|
||||
static void
|
||||
read_planar_tile_O(unsigned glyph, struct overview_planar_cell_struct *cell)
|
||||
read_planar_tile_O(unsigned tilenum, 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;
|
||||
|
||||
/* Get the processed tile from the cache if we can */
|
||||
pcell = cell_cache_O[tilenum];
|
||||
@@ -742,7 +761,7 @@ read_planar_tile_O(unsigned glyph, struct overview_planar_cell_struct *cell)
|
||||
/* Process the tile */
|
||||
pcell = (struct overview_planar_cell_struct *) alloc(sizeof(*pcell));
|
||||
cell_cache_O[tilenum] = pcell;
|
||||
read_tile_indexes(glyph, indexes);
|
||||
read_tile_indexes(tilenum, indexes);
|
||||
/* pcell->plane[0..3].image[0..15][0..0] */
|
||||
for (plane = 0; plane < SCREENPLANES; ++plane) {
|
||||
for (y = 0; y < TILE_Y; ++y) {
|
||||
@@ -762,19 +781,12 @@ read_planar_tile_O(unsigned glyph, struct overview_planar_cell_struct *cell)
|
||||
}
|
||||
|
||||
static void
|
||||
read_tile_indexes(unsigned glyph, unsigned char (*indexes)[TILE_X])
|
||||
read_tile_indexes(unsigned tilenum, unsigned char (*indexes)[TILE_X])
|
||||
{
|
||||
const struct TileImage *tile;
|
||||
unsigned x, y;
|
||||
int tilenum;
|
||||
|
||||
/* We don't have enough colors to show the statues */
|
||||
if (glyph_is_statue(glyph)) {
|
||||
glyph = GLYPH_OBJ_OFF + STATUE;
|
||||
}
|
||||
|
||||
/* Get the tile from the image */
|
||||
tilenum = glyphmap[glyph].tileidx;
|
||||
tile = get_tile(tilenum);
|
||||
|
||||
/* Map to a 16 bit palette; assume colors laid out as in default tileset */
|
||||
@@ -792,13 +804,122 @@ read_tile_indexes(unsigned glyph, unsigned char (*indexes)[TILE_X])
|
||||
}
|
||||
|
||||
static void
|
||||
decal_planar(struct planar_cell_struct *gpcs UNUSED, unsigned special)
|
||||
decal_planar(struct planar_cell_struct *gpcs, unsigned special)
|
||||
{
|
||||
if (special & MG_CORPSE) {
|
||||
} else if (special & MG_INVIS) {
|
||||
} else if (special & MG_DETECT) {
|
||||
} else if (special & MG_PET) {
|
||||
} else if (special & MG_RIDDEN) {
|
||||
int decalnum; /* indexes decal_alpha */
|
||||
int decal_tile; /* tile index of decal */
|
||||
|
||||
/* Which decal do we use? */
|
||||
if ((special & MG_PET) != 0 && iflags.hilite_pet) {
|
||||
decalnum = petdecal;
|
||||
decal_tile = Tile_petmark;
|
||||
} else if ((special & MG_OBJPILE) != 0 && iflags.hilite_pile) {
|
||||
decalnum = piledecal;
|
||||
decal_tile = Tile_pilemark;
|
||||
} else {
|
||||
/* No decal */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read the decal */
|
||||
struct planar_cell_struct decal;
|
||||
read_planar_tile(decal_tile, &decal);
|
||||
|
||||
/* Build the alpha channel for the decal */
|
||||
struct cellplane *alpha = decal_alpha[decalnum];
|
||||
|
||||
if (alpha == NULL) {
|
||||
/* Read the delimiter to get the background color */
|
||||
struct planar_cell_struct delim;
|
||||
read_planar_tile(Tile_delimiter, &delim);
|
||||
|
||||
/* Allocate space for the alpha channel */
|
||||
alpha = (struct cellplane *) alloc(sizeof(*alpha));
|
||||
decal_alpha[decalnum] = alpha;
|
||||
memset(alpha, 0x00, sizeof(*alpha));
|
||||
|
||||
/* Alpha channel is 0 where all planes of the decal match the
|
||||
background, and 1 otherwise */
|
||||
for (unsigned i = 0; i < SCREENPLANES; ++i) {
|
||||
uint8_t background = (delim.plane[i].image[0][0] & 0x80) ? 0xFF : 0x00;
|
||||
for (unsigned j = 0; j < MAX_ROWS_PER_CELL; ++j) {
|
||||
for (unsigned k = 0; k < MAX_BYTES_PER_CELL; ++k) {
|
||||
/* Set alpha to 1 wherever the decal doesn't match the
|
||||
background */
|
||||
alpha->image[j][k] |= decal.plane[i].image[j][k] ^ background;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply the decal to the tile */
|
||||
for (unsigned i = 0; i < SCREENPLANES; ++i) {
|
||||
for (unsigned j = 0; j < MAX_ROWS_PER_CELL; ++j) {
|
||||
for (unsigned k = 0; k < MAX_BYTES_PER_CELL; ++k) {
|
||||
uint8_t b1 = gpcs->plane[i].image[j][k];
|
||||
uint8_t b2 = decal.plane[i].image[j][k];
|
||||
uint8_t a = alpha->image[j][k];
|
||||
gpcs->plane[i].image[j][k] = (b1 & ~a) | (b2 & a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
decal_oview_planar(struct overview_planar_cell_struct *gpcs, unsigned special)
|
||||
{
|
||||
int decalnum; /* indexes decal_alpha */
|
||||
int decal_tile; /* tile index of decal */
|
||||
|
||||
/* Which decal do we use? */
|
||||
if ((special & MG_PET) != 0 && iflags.hilite_pet) {
|
||||
decalnum = petdecal;
|
||||
decal_tile = Tile_petmark;
|
||||
} else if ((special & MG_OBJPILE) != 0 && iflags.hilite_pile) {
|
||||
decalnum = piledecal;
|
||||
decal_tile = Tile_pilemark;
|
||||
} else {
|
||||
/* No decal */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read the decal */
|
||||
struct overview_planar_cell_struct decal;
|
||||
read_planar_tile_O(decal_tile, &decal);
|
||||
|
||||
/* Build the alpha channel for the decal */
|
||||
struct overview_cellplane *alpha = decal_oview_alpha[decalnum];
|
||||
|
||||
if (alpha == NULL) {
|
||||
/* Read the delimiter to get the background color */
|
||||
struct planar_cell_struct delim; /* not overview_planar_cell_struct */
|
||||
read_planar_tile(Tile_delimiter, &delim);
|
||||
|
||||
/* Allocate space for the alpha channel */
|
||||
alpha = (struct overview_cellplane *) alloc(sizeof(*alpha));
|
||||
decal_oview_alpha[decalnum] = alpha;
|
||||
memset(alpha, 0x00, sizeof(*alpha));
|
||||
|
||||
/* Alpha channel is 0 where all planes of the decal match the
|
||||
background, and 1 otherwise */
|
||||
for (unsigned i = 0; i < SCREENPLANES; ++i) {
|
||||
uint8_t background = (delim.plane[i].image[0][0] & 0x80) ? 0xFF : 0x00;
|
||||
for (unsigned j = 0; j < MAX_ROWS_PER_CELL; ++j) {
|
||||
/* Set alpha to 1 wherever the decal doesn't match the
|
||||
background */
|
||||
alpha->image[j][0] |= decal.plane[i].image[j][0] ^ background;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply the decal to the tile */
|
||||
for (unsigned i = 0; i < SCREENPLANES; ++i) {
|
||||
for (unsigned j = 0; j < MAX_ROWS_PER_CELL; ++j) {
|
||||
uint8_t b1 = gpcs->plane[i].image[j][0];
|
||||
uint8_t b2 = decal.plane[i].image[j][0];
|
||||
uint8_t a = alpha->image[j][0];
|
||||
gpcs->plane[i].image[j][0] = (b1 & ~a) | (b2 & a);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* TILES_IN_GLYPHMAP */
|
||||
|
||||
Reference in New Issue
Block a user