Browse Source

Implemented blended tranparency

pull/1021/head
FluffyQuack 5 years ago committed by Anders Jenbo
parent
commit
790c8e17e5
  1. 23
      Source/diablo.cpp
  2. 7
      Source/diablo.h
  3. 79
      Source/engine.cpp
  4. 1
      Source/engine.h
  5. 4
      Source/mainmenu.cpp
  6. 47
      Source/palette.cpp
  7. 1
      Source/palette.h
  8. 477
      Source/render.cpp
  9. 10
      Source/scrollrt.cpp

23
Source/diablo.cpp

@ -55,6 +55,8 @@ char sgbMouseDown;
int color_cycle_timer;
int ticks_per_sec = 20;
WORD tick_delay = 50;
/** Game options */
Options sgOptions;
/* rdata */
@ -408,6 +410,25 @@ BOOL StartGame(BOOL bNewGame, BOOL bSinglePlayer)
return gbRunGameResult;
}
/**
* @brief Save game configurations to ini file
*/
static void SaveOptions()
{
SRegSaveValue("devilutionx", "game speed", 0, sgOptions.ticksPerSecound);
SRegSaveValue("devilutionx", "blended transparency", 0, sgOptions.blendedTransparancy);
}
/**
* @brief Load game configurations from ini file
*/
static void LoadOptions()
{
sgOptions.ticksPerSecound = ticks_per_sec;
SRegLoadValue("devilutionx", "game speed", 0, &sgOptions.ticksPerSecound);
sgOptions.blendedTransparancy = getIniBool("devilutionx", "blended transparency", true);
}
static void diablo_init_screen()
{
MouseX = SCREEN_WIDTH / 2;
@ -498,9 +519,11 @@ void diablo_quit(int exitStatus)
int DiabloMain(int argc, char **argv)
{
diablo_parse_flags(argc, argv);
LoadOptions();
diablo_init();
diablo_splash();
mainmenu_loop();
SaveOptions();
diablo_deinit();
return 0;

7
Source/diablo.h

@ -12,6 +12,11 @@ DEVILUTION_BEGIN_NAMESPACE
extern "C" {
#endif
typedef struct Options {
bool blendedTransparancy; // Use blended transparency rather than stippled
int ticksPerSecound; // Game play ticks per secound
} Options;
extern SDL_Window *ghMainWnd;
extern DWORD glSeedTbl[NUMLEVELS];
extern int gnLevelTypeTbl[NUMLEVELS];
@ -46,6 +51,7 @@ extern BOOLEAN UseMultiTest;
extern char sgbMouseDown;
extern int ticks_per_sec;
extern WORD tick_delay;
extern Options sgOptions;
void FreeGameMem();
BOOL StartGame(BOOL bNewGame, BOOL bSinglePlayer);
@ -59,6 +65,7 @@ void GM_Game(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void LoadGameLevel(BOOL firstflag, int lvldir);
void game_loop(BOOL bStartup);
void diablo_color_cyc_logic();
void LoadOptions();
/* rdata */

79
Source/engine.cpp

@ -330,13 +330,13 @@ void CelBlitLightSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidt
}
/**
* @brief Same as CelBlitLightSafe, with transparancy applied
* @brief Same as CelBlitLightSafe, with stippled transparancy applied
* @param pDecodeTo The output buffer
* @param pRLEBytes CEL pixel stream (run-length encoded)
* @param nDataSize Size of CEL in bytes
* @param nWidth Width of sprite
*/
void CelBlitLightTransSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth)
static void CelBlitLightTransSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth)
{
int w;
BOOL shift;
@ -420,7 +420,71 @@ void CelBlitLightTransSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int
}
/**
* @brief Same as CelBlitLightTransSafe
* @brief Same as CelBlitLightSafe, with blended transparancy applied
* @param pDecodeTo The output buffer
* @param pRLEBytes CEL pixel stream (run-length encoded)
* @param nDataSize Size of CEL in bytes
* @param nWidth Width of sprite
* @param tbl Palette translation table
*/
static void CelBlitLightBlendedSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE *tbl)
{
int i, w;
BYTE width;
BYTE *src, *dst;
assert(pDecodeTo != NULL);
assert(pRLEBytes != NULL);
assert(gpBuffer);
src = pRLEBytes;
dst = pDecodeTo;
if (tbl == NULL)
tbl = &pLightTbl[light_table_index * 256];
w = nWidth;
for (; src != &pRLEBytes[nDataSize]; dst -= BUFFER_WIDTH + w) {
for (i = w; i;) {
width = *src++;
if (!(width & 0x80)) {
i -= width;
if (dst < gpBufEnd && dst > gpBufStart) {
if (width & 1) {
dst[0] = paletteTransparencyLookup[dst[0]][tbl[src[0]]];
src++;
dst++;
}
width >>= 1;
if (width & 1) {
dst[0] = paletteTransparencyLookup[dst[0]][tbl[src[0]]];
dst[1] = paletteTransparencyLookup[dst[1]][tbl[src[1]]];
src += 2;
dst += 2;
}
width >>= 1;
for (; width; width--) {
dst[0] = paletteTransparencyLookup[dst[0]][tbl[src[0]]];
dst[1] = paletteTransparencyLookup[dst[1]][tbl[src[1]]];
dst[2] = paletteTransparencyLookup[dst[2]][tbl[src[2]]];
dst[3] = paletteTransparencyLookup[dst[3]][tbl[src[3]]];
src += 4;
dst += 4;
}
} else {
src += width;
dst += width;
}
} else {
width = -(char)width;
dst += width;
i -= width;
}
}
}
}
/**
* @brief Same as CelBlitLightSafe, with stippled transparancy applied
* @param pBuff Target buffer
* @param pCelBuff Cel data
* @param nCel CEL frame number
@ -435,9 +499,12 @@ void CelClippedBlitLightTrans(BYTE *pBuff, BYTE *pCelBuff, int nCel, int nWidth)
pRLEBytes = CelGetFrameClipped(pCelBuff, nCel, &nDataSize);
if (cel_transparency_active)
CelBlitLightTransSafe(pBuff, pRLEBytes, nDataSize, nWidth);
else if (light_table_index)
if (cel_transparency_active) {
if (sgOptions.blendedTransparancy)
CelBlitLightBlendedSafe(pBuff, pRLEBytes, nDataSize, nWidth, NULL);
else
CelBlitLightTransSafe(pBuff, pRLEBytes, nDataSize, nWidth);
} else if (light_table_index)
CelBlitLightSafe(pBuff, pRLEBytes, nDataSize, nWidth, NULL);
else
CelBlitSafe(pBuff, pRLEBytes, nDataSize, nWidth);

1
Source/engine.h

@ -59,7 +59,6 @@ void CelDrawLightRed(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char
void CelBlitSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth);
void CelClippedDrawSafe(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth);
void CelBlitLightSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE *tbl);
void CelBlitLightTransSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth);
void CelDrawLightRedSafe(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light);
void CelBlitWidth(BYTE *pBuff, int x, int y, int wdt, BYTE *pCelBuff, int nCel, int nWidth);
void CelBlitOutline(char col, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth);

4
Source/mainmenu.cpp

@ -60,9 +60,7 @@ static BOOL mainmenu_single_player()
gbIsMultiplayer = false;
if (!SRegLoadValue("devilutionx", "game speed", 0, &ticks_per_sec)) {
SRegSaveValue("devilutionx", "game speed", 0, ticks_per_sec);
}
ticks_per_sec = sgOptions.ticksPerSecound;
return mainmenu_init_menu(SELHERO_NEW_DUNGEON);
}

47
Source/palette.cpp

@ -12,6 +12,7 @@ DEVILUTION_BEGIN_NAMESPACE
SDL_Color logical_palette[256];
SDL_Color system_palette[256];
SDL_Color orig_palette[256];
Uint8 paletteTransparencyLookup[256][256]; //Lookup table for transparency
/* data */
@ -79,6 +80,48 @@ void palette_init()
InitPalette();
}
/**
* Generate lookup table for transparency
*
* This is based of the same technique found in Quake2.
*
* To mimic 50% transparency we figure out what colours in the existing palette are the best match for the combination of any 2 colours.
* We save this into a lookup table for use during rendering.
*/
void GenerateBlendedLookupTable()
{
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 256; j++) {
if (i == j) { // No need to calculate transparency between 2 identical colours
paletteTransparencyLookup[i][j] = j;
continue;
}
if (i > j) { // Half the blends will be mirror identical ([i][j] is the same as [j][i]), so simply copy the existing combination.
paletteTransparencyLookup[i][j] = paletteTransparencyLookup[j][i];
continue;
}
Uint8 r = ((int)orig_palette[i].r + (int)orig_palette[j].r) / 2;
Uint8 g = ((int)orig_palette[i].g + (int)orig_palette[j].g) / 2;
Uint8 b = ((int)orig_palette[i].b + (int)orig_palette[j].b) / 2;
Uint8 best;
Uint32 bestDiff = SDL_MAX_UINT32;
for (int k = 0; k < 256; k++) {
int diffr = orig_palette[k].r - r;
int diffg = orig_palette[k].g - g;
int diffb = orig_palette[k].b - b;
int diff = diffr * diffr + diffg * diffg + diffb * diffb;
if (bestDiff > diff) {
best = k;
bestDiff = diff;
}
}
paletteTransparencyLookup[i][j] = best;
}
}
}
void LoadPalette(const char *pszFileName)
{
int i;
@ -99,6 +142,10 @@ void LoadPalette(const char *pszFileName)
orig_palette[i].a = SDL_ALPHA_OPAQUE;
#endif
}
if (sgOptions.blendedTransparancy) {
GenerateBlendedLookupTable();
}
}
void LoadRndLvlPal(int l)

1
Source/palette.h

@ -15,6 +15,7 @@ extern "C" {
extern SDL_Color logical_palette[256];
extern SDL_Color system_palette[256];
extern SDL_Color orig_palette[256];
extern Uint8 paletteTransparencyLookup[256][256];
void palette_update();
void SaveGamma();

477
Source/render.cpp

@ -18,119 +18,320 @@ enum {
RT_RTRAPEZOID
};
/** Fully transparent variant of WallMask. */
static DWORD WallMask_FullyTrasparent[TILE_HEIGHT] = {
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000
};
/** Transparent variant of RightMask. */
static DWORD RightMask_Transparent[TILE_HEIGHT] = {
0xE0000000,
0xF0000000,
0xFE000000,
0xFF000000,
0xFFE00000,
0xFFF00000,
0xFFFE0000,
0xFFFF0000,
0xFFFFE000,
0xFFFFF000,
0xFFFFFE00,
0xFFFFFF00,
0xFFFFFFE0,
0xFFFFFFF0,
0xFFFFFFFE,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF
};
/** Transparent variant of LeftMask. */
static DWORD LeftMask_Transparent[TILE_HEIGHT] = {
0x00000003,
0x0000000F,
0x0000003F,
0x000000FF,
0x000003FF,
0x00000FFF,
0x00003FFF,
0x0000FFFF,
0x0003FFFF,
0x000FFFFF,
0x003FFFFF,
0x00FFFFFF,
0x03FFFFFF,
0x0FFFFFFF,
0x3FFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF
};
/** Specifies the draw masks used to render transparency of the right side of tiles. */
static DWORD RightMask[TILE_HEIGHT] = {
0xEAAAAAAA, 0xF5555555,
0xFEAAAAAA, 0xFF555555,
0xFFEAAAAA, 0xFFF55555,
0xFFFEAAAA, 0xFFFF5555,
0xFFFFEAAA, 0xFFFFF555,
0xFFFFFEAA, 0xFFFFFF55,
0xFFFFFFEA, 0xFFFFFFF5,
0xFFFFFFFE, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF
0xEAAAAAAA,
0xF5555555,
0xFEAAAAAA,
0xFF555555,
0xFFEAAAAA,
0xFFF55555,
0xFFFEAAAA,
0xFFFF5555,
0xFFFFEAAA,
0xFFFFF555,
0xFFFFFEAA,
0xFFFFFF55,
0xFFFFFFEA,
0xFFFFFFF5,
0xFFFFFFFE,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF
};
/** Specifies the draw masks used to render transparency of the left side of tiles. */
static DWORD LeftMask[TILE_HEIGHT] = {
0xAAAAAAAB, 0x5555555F,
0xAAAAAABF, 0x555555FF,
0xAAAAABFF, 0x55555FFF,
0xAAAABFFF, 0x5555FFFF,
0xAAABFFFF, 0x555FFFFF,
0xAABFFFFF, 0x55FFFFFF,
0xABFFFFFF, 0x5FFFFFFF,
0xBFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF
0xAAAAAAAB,
0x5555555F,
0xAAAAAABF,
0x555555FF,
0xAAAAABFF,
0x55555FFF,
0xAAAABFFF,
0x5555FFFF,
0xAAABFFFF,
0x555FFFFF,
0xAABFFFFF,
0x55FFFFFF,
0xABFFFFFF,
0x5FFFFFFF,
0xBFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF
};
/** Specifies the draw masks used to render transparency of wall tiles. */
static DWORD WallMask[TILE_HEIGHT] = {
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555,
0xAAAAAAAA, 0x55555555
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555,
0xAAAAAAAA,
0x55555555
};
/** Fully opaque mask */
static DWORD SolidMask[TILE_HEIGHT] = {
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF
};
/** Used to mask out the left half of the tile diamond and only render additional content */
static DWORD RightFoliageMask[TILE_HEIGHT] = {
0xFFFFFFFF, 0x3FFFFFFF,
0x0FFFFFFF, 0x03FFFFFF,
0x00FFFFFF, 0x003FFFFF,
0x000FFFFF, 0x0003FFFF,
0x0000FFFF, 0x00003FFF,
0x00000FFF, 0x000003FF,
0x000000FF, 0x0000003F,
0x0000000F, 0x00000003,
0x00000000, 0x00000003,
0x0000000F, 0x0000003F,
0x000000FF, 0x000003FF,
0x00000FFF, 0x00003FFF,
0x0000FFFF, 0x0003FFFF,
0x000FFFFF, 0x003FFFFF,
0x00FFFFFF, 0x03FFFFFF,
0x0FFFFFFF, 0x3FFFFFFF,
0xFFFFFFFF,
0x3FFFFFFF,
0x0FFFFFFF,
0x03FFFFFF,
0x00FFFFFF,
0x003FFFFF,
0x000FFFFF,
0x0003FFFF,
0x0000FFFF,
0x00003FFF,
0x00000FFF,
0x000003FF,
0x000000FF,
0x0000003F,
0x0000000F,
0x00000003,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
};
/** Used to mask out the left half of the tile diamond and only render additional content */
static DWORD LeftFoliageMask[TILE_HEIGHT] = {
0xFFFFFFFF, 0xFFFFFFFC,
0xFFFFFFF0, 0xFFFFFFC0,
0xFFFFFF00, 0xFFFFFC00,
0xFFFFF000, 0xFFFFC000,
0xFFFF0000, 0xFFFC0000,
0xFFF00000, 0xFFC00000,
0xFF000000, 0xFC000000,
0xF0000000, 0xC0000000,
0x00000000, 0xC0000000,
0xF0000000, 0xFC000000,
0xFF000000, 0xFFC00000,
0xFFF00000, 0xFFFC0000,
0xFFFF0000, 0xFFFFC000,
0xFFFFF000, 0xFFFFFC00,
0xFFFFFF00, 0xFFFFFFC0,
0xFFFFFFF0, 0xFFFFFFFC,
0xFFFFFFFF,
0xFFFFFFFC,
0xFFFFFFF0,
0xFFFFFFC0,
0xFFFFFF00,
0xFFFFFC00,
0xFFFFF000,
0xFFFFC000,
0xFFFF0000,
0xFFFC0000,
0xFFF00000,
0xFFC00000,
0xFF000000,
0xFC000000,
0xF0000000,
0xC0000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
};
inline static int count_leading_zeros(DWORD mask)
@ -179,12 +380,12 @@ inline static void RenderLine(BYTE **dst, BYTE **src, int n, BYTE *tbl, DWORD ma
}
#endif
if (mask == 0xFFFFFFFF) {
if (light_table_index == lightmax) {
if (mask == 0xFFFFFFFF) { // Opaque line
if (light_table_index == lightmax) { // Complete darkness
memset(*dst, 0, n);
} else if (light_table_index == 0) {
} else if (light_table_index == 0) { // Fully lit
memcpy(*dst, *src, n);
} else {
} else { // Partially lit
for (int i = 0; i < n; i++) {
(*dst)[i] = tbl[(*src)[i]];
}
@ -197,12 +398,37 @@ inline static void RenderLine(BYTE **dst, BYTE **src, int n, BYTE *tbl, DWORD ma
assert(n != 0 && n <= sizeof(DWORD) * CHAR_BIT);
mask &= DWORD(-1) << ((sizeof(DWORD) * CHAR_BIT) - n);
if (light_table_index == lightmax) {
foreach_set_bit(mask, [=](int i) { (*dst)[i] = 0; });
} else if (light_table_index == 0) {
foreach_set_bit(mask, [=](int i) { (*dst)[i] = (*src)[i]; });
} else {
foreach_set_bit(mask, [=](int i) { (*dst)[i] = tbl[(*src)[i]]; });
if (sgOptions.blendedTransparancy && !cel_foliage_active) { // Blended transparancy
if (light_table_index == lightmax) { // Complete darkness
for (int i = 0; i < n; i++, mask <<= 1) {
if (mask & 0x80000000)
(*dst)[i] = 0;
else
(*dst)[i] = paletteTransparencyLookup[0][(*dst)[i]];
}
} else if (light_table_index == 0) { // Fully lit
for (int i = 0; i < n; i++, mask <<= 1) {
if (mask & 0x80000000)
(*dst)[i] = (*src)[i];
else
(*dst)[i] = paletteTransparencyLookup[(*dst)[i]][(*src)[i]];
}
} else { // Partially lit
for (int i = 0; i < n; i++, mask <<= 1) {
if (mask & 0x80000000)
(*dst)[i] = tbl[(*src)[i]];
else
(*dst)[i] = paletteTransparencyLookup[(*dst)[i]][tbl[(*src)[i]]];
}
}
} else { // Stippled transparancy
if (light_table_index == lightmax) { // Complete darkness
foreach_set_bit(mask, [=](int i) { (*dst)[i] = 0; });
} else if (light_table_index == 0) { // Fully lit
foreach_set_bit(mask, [=](int i) { (*dst)[i] = (*src)[i]; });
} else { // Partially lit
foreach_set_bit(mask, [=](int i) { (*dst)[i] = tbl[(*src)[i]]; });
}
}
}
@ -218,7 +444,8 @@ __attribute__((no_sanitize("shift-base")))
* @brief Blit current world CEL to the given buffer
* @param pBuff Output buffer
*/
void RenderTile(BYTE *pBuff)
void
RenderTile(BYTE *pBuff)
{
int i, j;
char c, v, tile;
@ -232,22 +459,32 @@ void RenderTile(BYTE *pBuff)
tile = (level_cel_block & 0x7000) >> 12;
tbl = &pLightTbl[256 * light_table_index];
// The mask defines what parts of the tile is opaque
mask = &SolidMask[TILE_HEIGHT - 1];
if (cel_transparency_active) {
if (arch_draw_type == 0) {
mask = &WallMask[TILE_HEIGHT - 1];
if (sgOptions.blendedTransparancy) // Use a fully transparent mask
mask = &WallMask_FullyTrasparent[TILE_HEIGHT - 1];
else
mask = &WallMask[TILE_HEIGHT - 1];
}
if (arch_draw_type == 1 && tile != RT_LTRIANGLE) {
c = block_lvid[level_piece_id];
if (c == 1 || c == 3) {
mask = &LeftMask[TILE_HEIGHT - 1];
if (sgOptions.blendedTransparancy) // Use a fully transparent mask
mask = &LeftMask_Transparent[TILE_HEIGHT - 1];
else
mask = &LeftMask[TILE_HEIGHT - 1];
}
}
if (arch_draw_type == 2 && tile != RT_RTRIANGLE) {
c = block_lvid[level_piece_id];
if (c == 2 || c == 3) {
mask = &RightMask[TILE_HEIGHT - 1];
if (sgOptions.blendedTransparancy) // Use a fully transparent mask
mask = &RightMask_Transparent[TILE_HEIGHT - 1];
else
mask = &RightMask[TILE_HEIGHT - 1];
}
}
} else if (arch_draw_type && cel_foliage_active) {
@ -377,9 +614,21 @@ void trans_rect(int sx, int sy, int width, int height)
{
int row, col;
BYTE *pix = &gpBuffer[SCREENXY(sx, sy)];
if (sgOptions.blendedTransparancy) { // Blended
for (row = 0; row < height; row++) {
for (col = 0; col < width; col++) {
*pix = paletteTransparencyLookup[0][*pix];
pix++;
}
pix += BUFFER_WIDTH - width;
}
return;
}
for (row = 0; row < height; row++) {
for (col = 0; col < width; col++) {
if ((row & 1 && col & 1) || (!(row & 1) && !(col & 1)))
if ((row & 1 && col & 1) || (!(row & 1) && !(col & 1))) // Stippled
*pix = 0;
pix++;
}

10
Source/scrollrt.cpp

@ -742,7 +742,17 @@ static void scrollrt_draw_dungeon(int sx, int sy, int dx, int dy)
bArch = dSpecial[sx][sy];
if (bArch != 0) {
cel_transparency_active = TransList[bMap];
#ifdef _DEBUG
if (GetAsyncKeyState(DVL_VK_MENU) & 0x8000) {
cel_transparency_active = 0; // Turn transparency off here for debugging
}
#endif
CelClippedBlitLightTrans(&gpBuffer[dx + BUFFER_WIDTH * dy], pSpecialCels, bArch, 64);
#ifdef _DEBUG
if (GetAsyncKeyState(DVL_VK_MENU) & 0x8000) {
cel_transparency_active = TransList[bMap]; // Turn transparency back to its normal state
}
#endif
}
} else {
// Tree leaves should always cover player when entering or leaving the tile,

Loading…
Cancel
Save