devilutionX/Source/render.cpp
Anders Jenbo f8c16a1dcb Only use safe blitting and set gpBufEnd to the correct relative values
This again allows us to only selectivly render the UI panel
This also eliminates the need for the BORDER_BOTTOM 10k memory saved!
2019-10-20 15:59:47 +02:00

292 lines
6.5 KiB
C++

#include "diablo.h"
DEVILUTION_BEGIN_NAMESPACE
#define NO_OVERDRAW
typedef enum {
RT_SQUARE,
RT_TRANSPARENT,
RT_LTRIANGLE,
RT_RTRIANGLE,
RT_LTRAPEZOID,
RT_RTRAPEZOID
};
static DWORD RightMask[32] = {
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
};
static DWORD LeftMask[32] = {
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
};
static DWORD WallMask[32] = {
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
};
static DWORD SolidMask[32] = {
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
};
inline static void RenderLine(BYTE **dst, BYTE **src, int n, BYTE *tbl, DWORD mask)
{
int i;
#ifdef NO_OVERDRAW
if (zoomflag) {
if ((*dst) < &gpBuffer[(0 + 160) * BUFFER_WIDTH]
|| (*dst) > &gpBuffer[(VIEWPORT_HEIGHT + 160) * BUFFER_WIDTH]) {
(*src) += n;
(*dst) += n;
return;
}
} else {
if ((*dst) < &gpBuffer[(-17 + 160) * BUFFER_WIDTH]
|| (*dst) > &gpBuffer[(160 + 160) * BUFFER_WIDTH]) {
(*src) += n;
(*dst) += n;
return;
}
}
#endif
if (mask == 0xFFFFFFFF) {
if (light_table_index == lightmax) {
(*src) += n;
for (i = 0; i < n; i++, (*dst)++) {
(*dst)[0] = 0;
}
} else if (light_table_index == 0) {
for (i = n & 3; i != 0; i--, (*src)++, (*dst)++) {
(*dst)[0] = (*src)[0];
}
n = (n >> 2) << 2;
memcpy(*dst, *src, n);
(*src) += n;
(*dst) += n;
} else {
for (i = 0; i < n; i++, (*src)++, (*dst)++) {
(*dst)[0] = tbl[(*src)[0]];
}
}
} else {
if (light_table_index == lightmax) {
(*src) += n;
for (i = 0; i < n; i++, (*dst)++, mask <<= 1) {
if (mask & 0x80000000) {
(*dst)[0] = 0;
}
}
} else if (light_table_index == 0) {
for (i = 0; i < n; i++, (*src)++, (*dst)++, mask <<= 1) {
if (mask & 0x80000000) {
(*dst)[0] = (*src)[0];
}
}
} else {
for (i = 0; i < n; i++, (*src)++, (*dst)++, mask <<= 1) {
if (mask & 0x80000000) {
(*dst)[0] = tbl[(*src)[0]];
}
}
}
}
}
#if defined(__clang__) || defined(__GNUC__)
__attribute__((no_sanitize("shift-base")))
#endif
void RenderTile(BYTE *pBuff)
{
int i, j;
char c, v, tile;
BYTE *src, *dst, *tbl;
DWORD m, *mask, *pFrameTable;
dst = pBuff;
pFrameTable = (DWORD *)pDungeonCels;
src = &pDungeonCels[SDL_SwapLE32(pFrameTable[level_cel_block & 0xFFF])];
tile = (level_cel_block & 0x7000) >> 12;
tbl = &pLightTbl[256 * light_table_index];
mask = &SolidMask[31];
if (cel_transparency_active) {
if (arch_draw_type == 0) {
mask = &WallMask[31];
}
if (arch_draw_type == 1 && tile != RT_LTRIANGLE) {
c = block_lvid[level_piece_id];
if (c == 1 || c == 3) {
mask = &LeftMask[31];
}
}
if (arch_draw_type == 2 && tile != RT_RTRIANGLE) {
c = block_lvid[level_piece_id];
if (c == 2 || c == 3) {
mask = &RightMask[31];
}
}
}
#ifdef _DEBUG
if (GetAsyncKeyState(VK_MENU) & 0x8000) {
mask = &SolidMask[31];
}
#endif
switch (tile) {
case RT_SQUARE:
for (i = 32; i != 0; i--, dst -= BUFFER_WIDTH + 32, mask--) {
RenderLine(&dst, &src, 32, tbl, *mask);
}
break;
case RT_TRANSPARENT:
for (i = 32; i != 0; i--, dst -= BUFFER_WIDTH + 32, mask--) {
m = *mask;
for (j = 32; j != 0; j -= v, m <<= v) {
v = *src++;
if (v >= 0) {
RenderLine(&dst, &src, v, tbl, m);
} else {
v = -v;
dst += v;
}
}
}
break;
case RT_LTRIANGLE:
for (i = 30; i >= 0; i -= 2, dst -= BUFFER_WIDTH + 32, mask--) {
src += i & 2;
dst += i;
RenderLine(&dst, &src, 32 - i, tbl, *mask);
}
for (i = 2; i != 32; i += 2, dst -= BUFFER_WIDTH + 32, mask--) {
src += i & 2;
dst += i;
RenderLine(&dst, &src, 32 - i, tbl, *mask);
}
break;
case RT_RTRIANGLE:
for (i = 30; i >= 0; i -= 2, dst -= BUFFER_WIDTH + 32, mask--) {
RenderLine(&dst, &src, 32 - i, tbl, *mask);
src += i & 2;
dst += i;
}
for (i = 2; i != 32; i += 2, dst -= BUFFER_WIDTH + 32, mask--) {
RenderLine(&dst, &src, 32 - i, tbl, *mask);
src += i & 2;
dst += i;
}
break;
case RT_LTRAPEZOID:
for (i = 30; i >= 0; i -= 2, dst -= BUFFER_WIDTH + 32, mask--) {
src += i & 2;
dst += i;
RenderLine(&dst, &src, 32 - i, tbl, *mask);
}
for (i = 16; i != 0; i--, dst -= BUFFER_WIDTH + 32, mask--) {
RenderLine(&dst, &src, 32, tbl, *mask);
}
break;
case RT_RTRAPEZOID:
for (i = 30; i >= 0; i -= 2, dst -= BUFFER_WIDTH + 32, mask--) {
RenderLine(&dst, &src, 32 - i, tbl, *mask);
src += i & 2;
dst += i;
}
for (i = 16; i != 0; i--, dst -= BUFFER_WIDTH + 32, mask--) {
RenderLine(&dst, &src, 32, tbl, *mask);
}
break;
}
}
void world_draw_black_tile(BYTE *pBuff)
{
int i, j, k;
BYTE *dst;
dst = pBuff;
for (i = 30, j = 1; i >= 0; i -= 2, j++, dst -= BUFFER_WIDTH + 64) {
dst += i;
if (dst < gpBufEnd) {
for (k = 0; k < 4 * j; k++)
*dst++ = 0;
}
dst += i;
}
for (i = 2, j = 15; i != 32; i += 2, j--, dst -= BUFFER_WIDTH + 64) {
dst += i;
if (dst < gpBufEnd) {
for (k = 0; k < 4 * j; k++)
*dst++ = 0;
}
dst += i;
}
}
DEVILUTION_END_NAMESPACE