Devilution
Diablo devolved - magic behind the 1996 computer game
render.cpp
Go to the documentation of this file.
1 #include "all.h"
2 
4 
5 #define NO_OVERDRAW
6 
7 enum {
14 };
15 
16 static DWORD RightMask[32] = {
17  0xEAAAAAAA, 0xF5555555,
18  0xFEAAAAAA, 0xFF555555,
19  0xFFEAAAAA, 0xFFF55555,
20  0xFFFEAAAA, 0xFFFF5555,
21  0xFFFFEAAA, 0xFFFFF555,
22  0xFFFFFEAA, 0xFFFFFF55,
23  0xFFFFFFEA, 0xFFFFFFF5,
24  0xFFFFFFFE, 0xFFFFFFFF,
25  0xFFFFFFFF, 0xFFFFFFFF,
26  0xFFFFFFFF, 0xFFFFFFFF,
27  0xFFFFFFFF, 0xFFFFFFFF,
28  0xFFFFFFFF, 0xFFFFFFFF,
29  0xFFFFFFFF, 0xFFFFFFFF,
30  0xFFFFFFFF, 0xFFFFFFFF,
31  0xFFFFFFFF, 0xFFFFFFFF,
32  0xFFFFFFFF, 0xFFFFFFFF
33 };
34 
35 static DWORD LeftMask[32] = {
36  0xAAAAAAAB, 0x5555555F,
37  0xAAAAAABF, 0x555555FF,
38  0xAAAAABFF, 0x55555FFF,
39  0xAAAABFFF, 0x5555FFFF,
40  0xAAABFFFF, 0x555FFFFF,
41  0xAABFFFFF, 0x55FFFFFF,
42  0xABFFFFFF, 0x5FFFFFFF,
43  0xBFFFFFFF, 0xFFFFFFFF,
44  0xFFFFFFFF, 0xFFFFFFFF,
45  0xFFFFFFFF, 0xFFFFFFFF,
46  0xFFFFFFFF, 0xFFFFFFFF,
47  0xFFFFFFFF, 0xFFFFFFFF,
48  0xFFFFFFFF, 0xFFFFFFFF,
49  0xFFFFFFFF, 0xFFFFFFFF,
50  0xFFFFFFFF, 0xFFFFFFFF,
51  0xFFFFFFFF, 0xFFFFFFFF
52 };
53 
54 static DWORD WallMask[32] = {
55  0xAAAAAAAA, 0x55555555,
56  0xAAAAAAAA, 0x55555555,
57  0xAAAAAAAA, 0x55555555,
58  0xAAAAAAAA, 0x55555555,
59  0xAAAAAAAA, 0x55555555,
60  0xAAAAAAAA, 0x55555555,
61  0xAAAAAAAA, 0x55555555,
62  0xAAAAAAAA, 0x55555555,
63  0xAAAAAAAA, 0x55555555,
64  0xAAAAAAAA, 0x55555555,
65  0xAAAAAAAA, 0x55555555,
66  0xAAAAAAAA, 0x55555555,
67  0xAAAAAAAA, 0x55555555,
68  0xAAAAAAAA, 0x55555555,
69  0xAAAAAAAA, 0x55555555,
70  0xAAAAAAAA, 0x55555555
71 };
72 
73 static DWORD SolidMask[32] = {
74  0xFFFFFFFF, 0xFFFFFFFF,
75  0xFFFFFFFF, 0xFFFFFFFF,
76  0xFFFFFFFF, 0xFFFFFFFF,
77  0xFFFFFFFF, 0xFFFFFFFF,
78  0xFFFFFFFF, 0xFFFFFFFF,
79  0xFFFFFFFF, 0xFFFFFFFF,
80  0xFFFFFFFF, 0xFFFFFFFF,
81  0xFFFFFFFF, 0xFFFFFFFF,
82  0xFFFFFFFF, 0xFFFFFFFF,
83  0xFFFFFFFF, 0xFFFFFFFF,
84  0xFFFFFFFF, 0xFFFFFFFF,
85  0xFFFFFFFF, 0xFFFFFFFF,
86  0xFFFFFFFF, 0xFFFFFFFF,
87  0xFFFFFFFF, 0xFFFFFFFF,
88  0xFFFFFFFF, 0xFFFFFFFF,
89  0xFFFFFFFF, 0xFFFFFFFF
90 };
91 
92 static DWORD RightFoliageMask[32] = {
93  0xFFFFFFFF, 0x3FFFFFFF,
94  0x0FFFFFFF, 0x03FFFFFF,
95  0x00FFFFFF, 0x003FFFFF,
96  0x000FFFFF, 0x0003FFFF,
97  0x0000FFFF, 0x00003FFF,
98  0x00000FFF, 0x000003FF,
99  0x000000FF, 0x0000003F,
100  0x0000000F, 0x00000003,
101  0x00000000, 0x00000003,
102  0x0000000F, 0x0000003F,
103  0x000000FF, 0x000003FF,
104  0x00000FFF, 0x00003FFF,
105  0x0000FFFF, 0x0003FFFF,
106  0x000FFFFF, 0x003FFFFF,
107  0x00FFFFFF, 0x03FFFFFF,
108  0x0FFFFFFF, 0x3FFFFFFF,
109 };
110 
111 static DWORD LeftFoliageMask[32] = {
112  0xFFFFFFFF, 0xFFFFFFFC,
113  0xFFFFFFF0, 0xFFFFFFC0,
114  0xFFFFFF00, 0xFFFFFC00,
115  0xFFFFF000, 0xFFFFC000,
116  0xFFFF0000, 0xFFFC0000,
117  0xFFF00000, 0xFFC00000,
118  0xFF000000, 0xFC000000,
119  0xF0000000, 0xC0000000,
120  0x00000000, 0xC0000000,
121  0xF0000000, 0xFC000000,
122  0xFF000000, 0xFFC00000,
123  0xFFF00000, 0xFFFC0000,
124  0xFFFF0000, 0xFFFFC000,
125  0xFFFFF000, 0xFFFFFC00,
126  0xFFFFFF00, 0xFFFFFFC0,
127  0xFFFFFFF0, 0xFFFFFFFC,
128 };
129 
130 inline static void RenderLine(BYTE **dst, BYTE **src, int n, BYTE *tbl, DWORD mask)
131 {
132  int i;
133 
134 #ifdef NO_OVERDRAW
135  if (*dst < gpBufStart || *dst > gpBufEnd) {
136  *src += n;
137  *dst += n;
138  return;
139  }
140 #endif
141 
142  if (mask == 0xFFFFFFFF) {
143  if (light_table_index == lightmax) {
144  memset(*dst, 0, n);
145  (*src) += n;
146  (*dst) += n;
147  } else if (light_table_index == 0) {
148  memcpy(*dst, *src, n);
149  (*src) += n;
150  (*dst) += n;
151  } else {
152  for (i = 0; i < n; i++, (*src)++, (*dst)++) {
153  (*dst)[0] = tbl[(*src)[0]];
154  }
155  }
156  } else {
157  if (light_table_index == lightmax) {
158  (*src) += n;
159  for (i = 0; i < n; i++, (*dst)++, mask <<= 1) {
160  if (mask & 0x80000000) {
161  (*dst)[0] = 0;
162  }
163  }
164  } else if (light_table_index == 0) {
165  for (i = 0; i < n; i++, (*src)++, (*dst)++, mask <<= 1) {
166  if (mask & 0x80000000) {
167  (*dst)[0] = (*src)[0];
168  }
169  }
170  } else {
171  for (i = 0; i < n; i++, (*src)++, (*dst)++, mask <<= 1) {
172  if (mask & 0x80000000) {
173  (*dst)[0] = tbl[(*src)[0]];
174  }
175  }
176  }
177  }
178 }
179 
180 #if defined(__clang__) || defined(__GNUC__)
181 __attribute__((no_sanitize("shift-base")))
182 #endif
183 
187 void RenderTile(BYTE *pBuff)
188 {
189  int i, j;
190  char c, v, tile;
191  BYTE *src, *dst, *tbl;
192  DWORD m, *mask, *pFrameTable;
193 
194  dst = pBuff;
195  pFrameTable = (DWORD *)pDungeonCels;
196 
197  src = &pDungeonCels[SDL_SwapLE32(pFrameTable[level_cel_block & 0xFFF])];
198  tile = (level_cel_block & 0x7000) >> 12;
199  tbl = &pLightTbl[256 * light_table_index];
200 
201  mask = &SolidMask[31];
202 
204  if (arch_draw_type == 0) {
205  mask = &WallMask[31];
206  }
207  if (arch_draw_type == 1 && tile != RT_LTRIANGLE) {
209  if (c == 1 || c == 3) {
210  mask = &LeftMask[31];
211  }
212  }
213  if (arch_draw_type == 2 && tile != RT_RTRIANGLE) {
215  if (c == 2 || c == 3) {
216  mask = &RightMask[31];
217  }
218  }
219  } else if (arch_draw_type && cel_foliage_active) {
220  if (tile != RT_TRANSPARENT) {
221  return;
222  }
223  if (arch_draw_type == 1) {
224  mask = &LeftFoliageMask[31];
225  }
226  if (arch_draw_type == 2) {
227  mask = &RightFoliageMask[31];
228  }
229  }
230 
231 #ifdef _DEBUG
232  if (GetAsyncKeyState(VK_MENU) & 0x8000) {
233  mask = &SolidMask[31];
234  }
235 #endif
236 
237  switch (tile) {
238  case RT_SQUARE:
239  for (i = 32; i != 0; i--, dst -= BUFFER_WIDTH + 32, mask--) {
240  RenderLine(&dst, &src, 32, tbl, *mask);
241  }
242  break;
243  case RT_TRANSPARENT:
244  for (i = 32; i != 0; i--, dst -= BUFFER_WIDTH + 32, mask--) {
245  m = *mask;
246  for (j = 32; j != 0; j -= v, v == 32 ? m = 0 : m <<= v) {
247  v = *src++;
248  if (v >= 0) {
249  RenderLine(&dst, &src, v, tbl, m);
250  } else {
251  v = -v;
252  dst += v;
253  }
254  }
255  }
256  break;
257  case RT_LTRIANGLE:
258  for (i = 30; i >= 0; i -= 2, dst -= BUFFER_WIDTH + 32, mask--) {
259  src += i & 2;
260  dst += i;
261  RenderLine(&dst, &src, 32 - i, tbl, *mask);
262  }
263  for (i = 2; i != 32; i += 2, dst -= BUFFER_WIDTH + 32, mask--) {
264  src += i & 2;
265  dst += i;
266  RenderLine(&dst, &src, 32 - i, tbl, *mask);
267  }
268  break;
269  case RT_RTRIANGLE:
270  for (i = 30; i >= 0; i -= 2, dst -= BUFFER_WIDTH + 32, mask--) {
271  RenderLine(&dst, &src, 32 - i, tbl, *mask);
272  src += i & 2;
273  dst += i;
274  }
275  for (i = 2; i != 32; i += 2, dst -= BUFFER_WIDTH + 32, mask--) {
276  RenderLine(&dst, &src, 32 - i, tbl, *mask);
277  src += i & 2;
278  dst += i;
279  }
280  break;
281  case RT_LTRAPEZOID:
282  for (i = 30; i >= 0; i -= 2, dst -= BUFFER_WIDTH + 32, mask--) {
283  src += i & 2;
284  dst += i;
285  RenderLine(&dst, &src, 32 - i, tbl, *mask);
286  }
287  for (i = 16; i != 0; i--, dst -= BUFFER_WIDTH + 32, mask--) {
288  RenderLine(&dst, &src, 32, tbl, *mask);
289  }
290  break;
291  case RT_RTRAPEZOID:
292  for (i = 30; i >= 0; i -= 2, dst -= BUFFER_WIDTH + 32, mask--) {
293  RenderLine(&dst, &src, 32 - i, tbl, *mask);
294  src += i & 2;
295  dst += i;
296  }
297  for (i = 16; i != 0; i--, dst -= BUFFER_WIDTH + 32, mask--) {
298  RenderLine(&dst, &src, 32, tbl, *mask);
299  }
300  break;
301  }
302 }
303 
309 void world_draw_black_tile(int sx, int sy)
310 {
311  int i, j, k;
312  BYTE *dst;
313 
314  if (sx >= SCREEN_X + SCREEN_WIDTH || sy >= SCREEN_Y + VIEWPORT_HEIGHT + 32)
315  return;
316 
317  if (sx < SCREEN_X - 60 || sy < SCREEN_Y)
318  return;
319 
320  dst = &gpBuffer[sx + BUFFER_WIDTH * sy] + 30;
321 
322  for (i = 30, j = 1; i >= 0; i -= 2, j++, dst -= BUFFER_WIDTH + 2) {
323  if (dst < gpBufEnd)
324  memset(dst, 0, 4 * j);
325  }
326  dst += 4;
327  for (i = 2, j = 15; i != 32; i += 2, j--, dst -= BUFFER_WIDTH - 2) {
328  if (dst < gpBufEnd)
329  memset(dst, 0, 4 * j);
330  }
331 }
332 
342 void trans_rect(int sx, int sy, int width, int height)
343 {
344  int row, col;
345  BYTE *pix = &gpBuffer[SCREENXY(sx, sy)];
346  for (row = 0; row < height; row++) {
347  for (col = 0; col < width; col++) {
348  if ((row & 1 && col & 1) || (!(row & 1) && !(col & 1)))
349  *pix = 0;
350  pix++;
351  }
352  pix += BUFFER_WIDTH - width;
353  }
354 }
355 
trans_rect
void trans_rect(int sx, int sy, int width, int height)
Draws a half-transparent rectangle by blacking out odd pixels on odd lines, even pixels on even lines...
Definition: render.cpp:342
gpBuffer
BYTE * gpBuffer
SCREENXY
#define SCREENXY(x, y)
Definition: defs.h:155
SolidMask
static DWORD SolidMask[32]
Definition: render.cpp:73
RenderLine
static void RenderLine(BYTE **dst, BYTE **src, int n, BYTE *tbl, DWORD mask)
Definition: render.cpp:130
SCREEN_Y
#define SCREEN_Y
Definition: defs.h:126
pLightTbl
BYTE * pLightTbl
Definition: lighting.cpp:21
level_cel_block
DWORD level_cel_block
Specifies the current MIN block of the level CEL file, as used during rendering of the level tiles.
Definition: scrollrt.cpp:28
cel_transparency_active
int cel_transparency_active
Specifies whether transparency is active for the current CEL file being decoded.
Definition: scrollrt.cpp:38
LeftMask
static DWORD LeftMask[32]
Definition: render.cpp:35
pDungeonCels
BYTE * pDungeonCels
Definition: gendung.cpp:47
RightMask
static DWORD RightMask[32]
Definition: render.cpp:16
RT_RTRAPEZOID
@ RT_RTRAPEZOID
Definition: render.cpp:13
VIEWPORT_HEIGHT
#define VIEWPORT_HEIGHT
Definition: defs.h:149
RenderTile
void RenderTile(BYTE *pBuff)
Blit current world CEL to the given buffer.
Definition: render.cpp:187
all.h
RT_LTRIANGLE
@ RT_LTRIANGLE
Definition: render.cpp:10
level_piece_id
int level_piece_id
Specifies the current dungeon piece ID of the level, as used during rendering of the level tiles.
Definition: scrollrt.cpp:46
SCREEN_WIDTH
#define SCREEN_WIDTH
Definition: defs.h:105
RT_TRANSPARENT
@ RT_TRANSPARENT
Definition: render.cpp:9
DEVILUTION_END_NAMESPACE
#define DEVILUTION_END_NAMESPACE
Definition: types.h:10
light_table_index
DEVILUTION_BEGIN_NAMESPACE int light_table_index
Specifies the current light entry.
Definition: scrollrt.cpp:8
cel_foliage_active
int cel_foliage_active
Specifies whether foliage (tile has extra content that overlaps previous tile) being rendered.
Definition: scrollrt.cpp:42
RightFoliageMask
static DWORD RightFoliageMask[32]
Definition: render.cpp:92
WallMask
static DWORD WallMask[32]
Definition: render.cpp:54
gpBufEnd
BYTE * gpBufEnd
Lower bound of back buffer.
Definition: scrollrt.cpp:19
arch_draw_type
char arch_draw_type
Specifies the type of arches to render.
Definition: scrollrt.cpp:34
RT_RTRIANGLE
@ RT_RTRIANGLE
Definition: render.cpp:11
block_lvid
char block_lvid[2049]
List of transparancy masks to use for dPieces.
Definition: gendung.cpp:35
BUFFER_WIDTH
#define BUFFER_WIDTH
Definition: defs.h:128
world_draw_black_tile
void world_draw_black_tile(int sx, int sy)
Render a black tile.
Definition: render.cpp:309
DEVILUTION_BEGIN_NAMESPACE
Definition: sha.cpp:10
RT_SQUARE
@ RT_SQUARE
Definition: render.cpp:8
SCREEN_X
#define SCREEN_X
Definition: defs.h:125
LeftFoliageMask
static DWORD LeftFoliageMask[32]
Definition: render.cpp:111
RT_LTRAPEZOID
@ RT_LTRAPEZOID
Definition: render.cpp:12
lightmax
char lightmax
Definition: lighting.cpp:17