1 // "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
2 // Ken Silverman's official web site: "http://www.advsys.net/ken"
3 // See the included license file "BUILDLIC.TXT" for license info.
4 //
5 // This file has been modified from Ken Silverman's original release
6 // by Jonathon Fowler (jf@jonof.id.au)
7 // by the EDuke32 team (development@voidpoint.com)
8
9 #pragma once
10
11 #ifndef build_h_
12 #define build_h_
13
14 #if !defined __cplusplus || (__cplusplus < 201103L && !defined _MSC_VER)
15 # error C++11 or greater is required.
16 #endif
17
18 #if defined _MSC_VER && _MSC_VER < 1800
19 # error Visual Studio 2013 is the minimum supported version.
20 #endif
21
22 #include "collections.h"
23 #include "compat.h"
24 #include "glad/glad.h"
25 #include "glbuild.h"
26 #include "palette.h"
27 #include "pragmas.h"
28
29 #include "vfs.h"
30 #include "cache1d.h"
31
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35
36 enum rendmode_t {
37 REND_CLASSIC,
38 REND_POLYMOST = 3,
39 REND_POLYMER
40 };
41
42 #define PI 3.14159265358979323846
43 #define fPI 3.14159265358979323846f
44
45 #define BANG2RAD (fPI * (1.f/1024.f))
46
47 #define MAXSECTORSV8 4096
48 #define MAXWALLSV8 16384
49 #define MAXSPRITESV8 16384
50
51 #define MAXSECTORSV7 1024
52 #define MAXWALLSV7 8192
53 #define MAXSPRITESV7 4096
54
55 #define MAXVOXMIPS 5
56
57 #if !defined GEKKO && !defined __OPENDINGUX__
58 # define MAXSECTORS MAXSECTORSV8
59 # define MAXWALLS MAXWALLSV8
60 # define MAXSPRITES MAXSPRITESV8
61
62 # define MAXXDIM 7680
63 # define MAXYDIM 3200
64 # define MINXDIM 640
65 # define MINYDIM 480
66
67 // additional space beyond wall, in walltypes:
68 # define M32_FIXME_WALLS 512
69 # define M32_FIXME_SECTORS 2
70 #else
71 # define MAXSECTORS MAXSECTORSV7
72 # define MAXWALLS MAXWALLSV7
73 # define MAXSPRITES MAXSPRITESV7
74
75 #ifdef GEKKO
76 # define MAXXDIM 860
77 # define MAXYDIM 490
78 # else
79 # define MAXXDIM 320
80 # define MAXYDIM 200
81 # endif
82
83 # define MINXDIM MAXXDIM
84 # define MINYDIM MAXYDIM
85 # define M32_FIXME_WALLS 0
86 # define M32_FIXME_SECTORS 0
87 #endif
88
89 //define NEW_MAP_FORMAT
90
91 #define MAXWALLSB ((MAXWALLS>>2)+(MAXWALLS>>3))
92
93 #define MAXTILES 30720
94 #define MAXUSERTILES (MAXTILES-16) // reserve 16 tiles at the end
95
96 #define MAXVOXELS 1024
97 #define MAXSTATUS 1024
98 #define MAXPLAYERS 16
99 // Maximum number of component tiles in a multi-psky:
100 #define MAXPSKYTILES 16
101 #define MAXSPRITESONSCREEN 2560
102 #define MAXUNIQHUDID 256 //Extra slots so HUD models can store animation state without messing game sprites
103
104 #define TSPR_TEMP 99
105
106 #define PR_LIGHT_PRIO_MAX 0
107 #define PR_LIGHT_PRIO_MAX_GAME 1
108 #define PR_LIGHT_PRIO_HIGH 2
109 #define PR_LIGHT_PRIO_HIGH_GAME 3
110 #define PR_LIGHT_PRIO_LOW 4
111 #define PR_LIGHT_PRIO_LOW_GAME 5
112
113 #define CLOCKTICKSPERSECOND 120
114
115 // Convenient sprite iterators, must not be used if any sprites inside the loop
116 // are potentially deleted or their sector changed...
117 #define SPRITES_OF(Statnum, Iter) Iter=headspritestat[Statnum]; Iter>=0; Iter=nextspritestat[Iter]
118 #define SPRITES_OF_SECT(Sectnum, Iter) Iter=headspritesect[Sectnum]; Iter>=0; Iter=nextspritesect[Iter]
119 // ... in which case this iterator may be used:
120 #define SPRITES_OF_SECT_SAFE(Sectnum, Iter, Next) Iter=headspritesect[Sectnum]; \
121 Iter>=0 && (Next=nextspritesect[Iter], 1); Iter=Next
122 #define SPRITES_OF_STAT_SAFE(Statnum, Iter, Next) Iter=headspritestat[Statnum]; \
123 Iter>=0 && (Next=nextspritestat[Iter], 1); Iter=Next
124
125 #define CLEARLINES2D(Startline, Numlines, Color) \
126 clearbuf((char *)(frameplace + ((Startline)*bytesperline)), (bytesperline*(Numlines))>>2, (Color))
127
128
129 ////////// True Room over Room (YAX == rot -17 of "PRO") //////////
130 #define YAX_ENABLE
131 //#define YAX_DEBUG
132 //#define ENGINE_SCREENSHOT_DEBUG
133
134 #ifdef YAX_ENABLE
135 # if !defined NEW_MAP_FORMAT
136 # define YAX_ENABLE__COMPAT
137 # endif
138 #endif
139
140 ////////// yax defs //////////
141 #define SECTORFLD(Sect,Fld, Cf) (*((Cf) ? (§or[Sect].floor##Fld) : (§or[Sect].ceiling##Fld)))
142
143 #define YAX_CEILING 0 // don't change!
144 #define YAX_FLOOR 1 // don't change!
145
146 # ifdef NEW_MAP_FORMAT
147 # define YAX_MAXBUNCHES 512
148 # define YAX_BIT__COMPAT 1024
149 # define YAX_NEXTWALLBIT__COMPAT(Cf) (1<<(10+Cf))
150 # define YAX_NEXTWALLBITS__COMPAT (YAX_NEXTWALLBIT__COMPAT(0)|YAX_NEXTWALLBIT__COMPAT(1))
151 # else
152 # define YAX_MAXBUNCHES 256
153 # define YAX_BIT 1024
154 // "has next wall when constrained"-bit (1<<10: ceiling, 1<<11: floor)
155 # define YAX_NEXTWALLBIT(Cf) (1<<(10+Cf))
156 # define YAX_NEXTWALLBITS (YAX_NEXTWALLBIT(0)|YAX_NEXTWALLBIT(1))
157 # endif
158
159 int32_t get_alwaysshowgray(void); // editor only
160 void yax_updategrays(int32_t posze);
161
162 #ifdef YAX_ENABLE
163 # ifdef NEW_MAP_FORMAT
164 // New map format -- no hijacking of otherwise used members.
165 # define YAX_PTRNEXTWALL(Ptr, Wall, Cf) (*(&Ptr[Wall].upwall + Cf))
166 # define YAX_NEXTWALLDEFAULT(Cf) (-1)
167 # else
168 // More user tag hijacking: lotag/extra. :/
169 # define YAX_PTRNEXTWALL(Ptr, Wall, Cf) (*(int16_t *)(&Ptr[Wall].lotag + (bloodhack ? 1 : 2)*Cf))
170 # define YAX_NEXTWALLDEFAULT(Cf) (bloodhack ? 0 : ((Cf)==YAX_CEILING) ? 0 : -1)
171 extern int16_t yax_bunchnum[MAXSECTORS][2];
172 extern int16_t yax_nextwall[MAXWALLS][2];
173 # endif
174
175 # define YAX_NEXTWALL(Wall, Cf) YAX_PTRNEXTWALL(wall, Wall, Cf)
176
177 # define YAX_ITER_WALLS(Wal, Itervar, Cfvar) Cfvar=0, Itervar=(Wal); Itervar!=-1; \
178 Itervar=yax_getnextwall(Itervar, Cfvar), \
179 (void)(Itervar==-1 && Cfvar==0 && (Cfvar=1) && (Itervar=yax_getnextwall((Wal), Cfvar)))
180
181 # define SECTORS_OF_BUNCH(Bunchnum, Cf, Itervar) Itervar = headsectbunch[Cf][Bunchnum]; \
182 Itervar != -1; Itervar = nextsectbunch[Cf][Itervar]
183
184 extern int32_t r_tror_nomaskpass;
185
186 # ifdef NEW_MAP_FORMAT
187 // Moved below declarations of sector, wall, sprite.
188 # else
189 int16_t yax_getbunch(int16_t i, int16_t cf);
yax_getbunches(int16_t i,int16_t * cb,int16_t * fb)190 static FORCE_INLINE void yax_getbunches(int16_t i, int16_t *cb, int16_t *fb)
191 {
192 *cb = yax_getbunch(i, YAX_CEILING);
193 *fb = yax_getbunch(i, YAX_FLOOR);
194 }
195 int16_t yax_getnextwall(int16_t wal, int16_t cf);
196 void yax_setnextwall(int16_t wal, int16_t cf, int16_t thenextwall);
197 # endif
198
199 void yax_setbunch(int16_t i, int16_t cf, int16_t bunchnum);
200 void yax_setbunches(int16_t i, int16_t cb, int16_t fb);
201 int16_t yax_vnextsec(int16_t line, int16_t cf);
202 void yax_update(int32_t resetstat);
203 int32_t yax_getneighborsect(int32_t x, int32_t y, int32_t sectnum, int32_t cf);
204
yax_waltosecmask(int32_t const walclipmask)205 static FORCE_INLINE CONSTEXPR int32_t yax_waltosecmask(int32_t const walclipmask)
206 {
207 // blocking: walstat&1 --> secstat&512
208 // hitscan: walstat&64 --> secstat&2048
209 return ((walclipmask&1)<<9) | ((walclipmask&64)<<5);
210 }
211 void yax_preparedrawrooms(void);
212 void yax_drawrooms(void (*SpriteAnimFunc)(int32_t,int32_t,int32_t,int32_t,int32_t),
213 int16_t sectnum, int32_t didmirror, int32_t smoothr);
214 # define YAX_SKIPSECTOR(i) if (graysectbitmap[(i)>>3]&pow2char[(i)&7]) continue
215 # define YAX_SKIPWALL(i) if (graywallbitmap[(i)>>3]&pow2char[(i)&7]) continue
216 #else
217 # define yax_preparedrawrooms()
218 # define yax_drawrooms(SpriteAnimFunc, sectnum, didmirror, smoothr)
219 # define YAX_SKIPSECTOR(i) (i)=(i)
220 # define YAX_SKIPWALL(i) (i)=(i)
221 #endif
222
223 #define CLIPMASK0 (((1L)<<16)+1L)
224 #define CLIPMASK1 (((256L)<<16)+64L)
225
226 #define NEXTWALL(i) (wall[wall[i].nextwall])
227 #define POINT2(i) (wall[wall[i].point2])
228
229 // max x/y val (= max editorgridextent in Mapster32)
230 #define BXY_MAX 524288
231
232 // rotatesprite 'orientation' (actually much more) bits
233 enum {
234 RS_TRANS1 = 1,
235 RS_AUTO = 2,
236 RS_YFLIP = 4,
237 RS_NOCLIP = 8,
238 RS_TOPLEFT = 16,
239 RS_TRANS2 = 32,
240 RS_NOMASK = 64,
241 RS_PERM = 128,
242
243 RS_ALIGN_L = 256,
244 RS_ALIGN_R = 512,
245 RS_ALIGN_MASK = 768,
246 RS_STRETCH = 1024,
247
248 ROTATESPRITE_FULL16 = 2048,
249 // ROTATESPRITE_MAX-1 is the mask of all externally available orientation bits
250 ROTATESPRITE_MAX = 4096,
251
252 RS_CENTERORIGIN = (1<<30),
253 };
254
255 //Make all variables in BUILD.H defined in the ENGINE,
256 //and externed in GAME
257 #ifdef engine_c_
258 # define EXTERN
259 #else
260 # define EXTERN extern
261 #endif
262
263 #ifdef __cplusplus
264 }
265 #endif
266
267 #if defined __cplusplus && (defined USE_OPENGL || defined POLYMER)
268 # define USE_STRUCT_TRACKERS
269 #endif
270
271 #ifdef USE_STRUCT_TRACKERS
272
273 extern "C" {
274 static FORCE_INLINE void sector_tracker_hook__(intptr_t address);
275 static FORCE_INLINE void wall_tracker_hook__(intptr_t address);
276 static FORCE_INLINE void sprite_tracker_hook__(intptr_t address);
277 }
278
279 #define TRACKER_NAME__ SectorTracker
280 #define TRACKER_HOOK_ sector_tracker_hook__
281 #include "tracker.hpp"
282 #undef TRACKER_NAME__
283 #undef TRACKER_HOOK_
284
285 #define TRACKER_NAME__ WallTracker
286 #define TRACKER_HOOK_ wall_tracker_hook__
287 #include "tracker.hpp"
288 #undef TRACKER_NAME__
289 #undef TRACKER_HOOK_
290
291 #define TRACKER_NAME__ SpriteTracker
292 #define TRACKER_HOOK_ sprite_tracker_hook__
293 #include "tracker.hpp"
294 #undef TRACKER_NAME__
295 #undef TRACKER_HOOK_
296
297 #define Tracker(Container, Type) Container##Tracker<Type>
298 #define TrackerCast(x) x.cast()
299
300 #else
301
302 #define Tracker(Container, Type) Type
303 #define TrackerCast(x) x
304
305 #endif // __cplusplus
306
307 // Links to various ABIs specifying (or documenting non-normatively) the
308 // alignment requirements of aggregates:
309 //
310 // System V AMD64: http://www.x86-64.org/documentation/abi-0.99.pdf
311 // (x86-64.org down as of 2013-02-02?)
312 // "An array uses the same alignment as its elements, except that a local or global
313 // array variable of length at least 16 bytes or a C99 variable-length array variable
314 // always has alignment of at least 16 bytes."
315 // (Not reproducible with GCC or LuaJIT on Ubuntu)
316 //
317 // Win64: http://msdn.microsoft.com/en-us/library/9dbwhz68.aspx
318 //
319 // x86: http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86
320
321 enum {
322 SPR_XFLIP = 4,
323 SPR_YFLIP = 8,
324
325 SPR_WALL = 16,
326 SPR_FLOOR = 32,
327 SPR_ALIGN_MASK = 32+16,
328 };
329
330 #define UNTRACKED_STRUCTS__
331 #include "buildtypes.h"
332 #undef UNTRACKED_STRUCTS__
333 #undef buildtypes_h__
334 #include "buildtypes.h"
335
336 #if !defined NEW_MAP_FORMAT
337 using sectortype = sectortypev7;
338 using usectortype = usectortypev7;
339
340 using walltype = walltypev7;
341 using uwalltype = uwalltypev7;
342 #else
343 using sectortype = sectortypevx;
344 using usectortype = usectortypevx;
345
346 using walltype = walltypevx;
347 using uwalltype = uwalltypevx;
348 #endif
349
350 using spritetype = spritetypev7;
351 using uspritetype = uspritetypev7;
352
353 using uspriteptr_t = uspritetype const *;
354 using uwallptr_t = uwalltype const *;
355 using usectorptr_t = usectortype const *;
356 using tspriteptr_t = tspritetype *;
357
358 // this is probably never going to be necessary
359 EDUKE32_STATIC_ASSERT(sizeof(sectortype) == sizeof(usectortype));
360 EDUKE32_STATIC_ASSERT(sizeof(walltype) == sizeof(uwalltype));
361 EDUKE32_STATIC_ASSERT(sizeof(spritetype) == sizeof(uspritetype));
362
363 #ifdef NEW_MAP_FORMAT
364
365 # define SECTORVX_SZ1 offsetof(sectortypevx, ceilingpicnum)
366 # define SECTORVX_SZ4 sizeof(sectortypevx)-offsetof(sectortypevx, visibility)
367
copy_v7_from_vx_sector(usectortypev7 * v7sec,const sectortypevx * vxsec)368 static inline void copy_v7_from_vx_sector(usectortypev7 *v7sec, const sectortypevx *vxsec)
369 {
370 /* [wallptr..wallnum] */
371 Bmemcpy(v7sec, vxsec, SECTORVX_SZ1);
372
373 /* ceiling* */
374 v7sec->ceilingpicnum = vxsec->ceilingpicnum;
375 v7sec->ceilingheinum = vxsec->ceilingheinum;
376 v7sec->ceilingstat = vxsec->ceilingstat;
377 v7sec->ceilingz = vxsec->ceilingz;
378 v7sec->ceilingshade = vxsec->ceilingshade;
379 v7sec->ceilingpal = vxsec->ceilingpal;
380 v7sec->ceilingxpanning = vxsec->ceilingxpanning;
381 v7sec->ceilingypanning = vxsec->ceilingypanning;
382
383 /* floor* */
384 v7sec->floorpicnum = vxsec->floorpicnum;
385 v7sec->floorheinum = vxsec->floorheinum;
386 v7sec->floorstat = vxsec->floorstat;
387 v7sec->floorz = vxsec->floorz;
388 v7sec->floorshade = vxsec->floorshade;
389 v7sec->floorpal = vxsec->floorpal;
390 v7sec->floorxpanning = vxsec->floorxpanning;
391 v7sec->floorypanning = vxsec->floorypanning;
392
393 /* [visibility..extra] */
394 Bmemcpy(&v7sec->visibility, &vxsec->visibility, SECTORVX_SZ4);
395
396 /* Clear YAX_BIT of ceiling and floor. (New-map format build saves TROR
397 * maps as map-text.) */
398 v7sec->ceilingstat &= ~YAX_BIT__COMPAT;
399 v7sec->floorstat &= ~YAX_BIT__COMPAT;
400 }
401
inplace_vx_from_v7_sector(sectortypevx * vxsec)402 static inline void inplace_vx_from_v7_sector(sectortypevx *vxsec)
403 {
404 const sectortypev7 *v7sec = (sectortypev7 *)vxsec;
405 usectortypev7 bakv7sec;
406
407 // Can't do this in-place since the members were rearranged.
408 Bmemcpy(&bakv7sec, v7sec, sizeof(sectortypev7));
409
410 /* [wallptr..wallnum] is already at the right place */
411
412 /* ceiling* */
413 vxsec->ceilingpicnum = bakv7sec.ceilingpicnum;
414 vxsec->ceilingheinum = bakv7sec.ceilingheinum;
415 vxsec->ceilingstat = bakv7sec.ceilingstat;
416 vxsec->ceilingz = bakv7sec.ceilingz;
417 vxsec->ceilingshade = bakv7sec.ceilingshade;
418 vxsec->ceilingpal = bakv7sec.ceilingpal;
419 vxsec->ceilingxpanning = bakv7sec.ceilingxpanning;
420 vxsec->ceilingypanning = bakv7sec.ceilingypanning;
421
422 /* floor* */
423 vxsec->floorpicnum = bakv7sec.floorpicnum;
424 vxsec->floorheinum = bakv7sec.floorheinum;
425 vxsec->floorstat = bakv7sec.floorstat;
426 vxsec->floorz = bakv7sec.floorz;
427 vxsec->floorshade = bakv7sec.floorshade;
428 vxsec->floorpal = bakv7sec.floorpal;
429 vxsec->floorxpanning = bakv7sec.floorxpanning;
430 vxsec->floorypanning = bakv7sec.floorypanning;
431
432 /* [visibility..extra] */
433 Bmemmove(&vxsec->visibility, &bakv7sec.visibility, SECTORVX_SZ4);
434 }
435
inplace_vx_tweak_sector(sectortypevx * vxsec,int32_t yaxp)436 static inline void inplace_vx_tweak_sector(sectortypevx *vxsec, int32_t yaxp)
437 {
438 if (yaxp)
439 {
440 int32_t cisext = (vxsec->ceilingstat&YAX_BIT__COMPAT);
441 int32_t fisext = (vxsec->floorstat&YAX_BIT__COMPAT);
442
443 vxsec->ceilingbunch = cisext ? vxsec->ceilingxpanning : -1;
444 vxsec->floorbunch = fisext ? vxsec->floorxpanning : -1;
445
446 if (cisext)
447 vxsec->ceilingxpanning = 0;
448 if (fisext)
449 vxsec->floorxpanning = 0;
450 }
451 else
452 {
453 vxsec->ceilingbunch = vxsec->floorbunch = -1;
454 }
455
456 /* Clear YAX_BIT of ceiling and floor (map-int VX doesn't use it). */
457 vxsec->ceilingstat &= ~YAX_BIT__COMPAT;
458 vxsec->floorstat &= ~YAX_BIT__COMPAT;
459 }
460
461 # undef SECTORVX_SZ1
462 # undef SECTORVX_SZ4
463
464 # define WALLVX_SZ2 offsetof(walltypevx, blend)-offsetof(walltypevx, cstat)
465
copy_v7_from_vx_wall(uwalltypev7 * v7wal,const walltypevx * vxwal)466 static inline void copy_v7_from_vx_wall(uwalltypev7 *v7wal, const walltypevx *vxwal)
467 {
468 /* [x..nextsector] */
469 Bmemcpy(v7wal, vxwal, offsetof(walltypevx, upwall));
470 /* [cstat..extra] */
471 Bmemcpy(&v7wal->cstat, &vxwal->cstat, WALLVX_SZ2);
472 /* Clear YAX_NEXTWALLBITS. */
473 v7wal->cstat &= ~YAX_NEXTWALLBITS__COMPAT;
474 }
475
inplace_vx_from_v7_wall(walltypevx * vxwal)476 static inline void inplace_vx_from_v7_wall(walltypevx *vxwal)
477 {
478 const walltypev7 *v7wal = (walltypev7 *)vxwal;
479
480 /* [cstat..extra] */
481 Bmemmove(&vxwal->cstat, &v7wal->cstat, WALLVX_SZ2);
482
483 vxwal->blend = vxwal->filler_ = 0;
484 }
485
inplace_vx_tweak_wall(walltypevx * vxwal,int32_t yaxp)486 static inline void inplace_vx_tweak_wall(walltypevx *vxwal, int32_t yaxp)
487 {
488 if (yaxp)
489 {
490 int32_t haveupwall = (vxwal->cstat & YAX_NEXTWALLBIT__COMPAT(YAX_CEILING));
491 int32_t havednwall = (vxwal->cstat & YAX_NEXTWALLBIT__COMPAT(YAX_FLOOR));
492
493 vxwal->upwall = haveupwall ? vxwal->lotag : -1;
494 vxwal->dnwall = havednwall ? vxwal->extra : -1;
495
496 if (haveupwall)
497 vxwal->lotag = 0;
498 if (havednwall)
499 vxwal->extra = -1;
500 }
501 else
502 {
503 vxwal->upwall = vxwal->dnwall = -1;
504 }
505
506 /* Clear YAX_NEXTWALLBITS (map-int VX doesn't use it). */
507 vxwal->cstat &= ~YAX_NEXTWALLBITS__COMPAT;
508 }
509
510 # undef WALLVX_SZ2
511
512 #endif
513
514 #include "clip.h"
515
516 int32_t getwalldist(vec2_t const in, int const wallnum);
517 int32_t getwalldist(vec2_t const in, int const wallnum, vec2_t * const out);
518
519 #ifdef __cplusplus
520 extern "C" {
521 #endif
522
523 #pragma pack(push,1)
524 typedef struct {
525 union
526 {
527 tspriteptr_t tspr;
528 #if !defined UINTPTR_MAX
529 # error Need UINTPTR_MAX define to select between 32- and 64-bit structs
530 #endif
531 #if UINTPTR_MAX != UINT64_MAX
532 /* On a 32-bit build, pad the struct so it has the same size everywhere. */
533 uint64_t ptrfill;
534 #endif
535 };
536
537 float alpha;
538 uint16_t flags;
539
540 // this is organized so that most of the bytes that will usually be zero are adjacent
541 int16_t mdanimcur;
542 uint32_t mdanimtims;
543 int16_t mdangoff;
544 uint8_t xpanning, ypanning;
545 int16_t mdpitch, mdroll;
546 vec3_t mdpivot_offset, mdposition_offset;
547
548 // since this goes into savegames, pad to 64 bytes for future usage
549 uint8_t filler[12];
550 } spriteext_t;
551
552 EDUKE32_STATIC_ASSERT(offsetof(spriteext_t, flags) % 4 == 0);
553 EDUKE32_STATIC_ASSERT(offsetof(spriteext_t, mdangoff) % 4 == 0);
554 EDUKE32_STATIC_ASSERT(offsetof(spriteext_t, mdanimtims) % 4 == 0);
555 EDUKE32_STATIC_ASSERT(offsetof(spriteext_t, mdposition_offset) % 4 == 0);
556 EDUKE32_STATIC_ASSERT(sizeof(spriteext_t) == 64);
557
558 typedef struct {
559 float smoothduration;
560 int16_t mdcurframe, mdoldframe;
561 int16_t mdsmooth;
562 } spritesmooth_t;
563
564 #ifndef NEW_MAP_FORMAT
565 typedef struct {
566 uint8_t blend;
567 } wallext_t;
568 #endif
569 #pragma pack(pop)
570
571 #define SPREXT_NOTMD 1
572 #define SPREXT_NOMDANIM 2
573 #define SPREXT_AWAY1 4
574 #define SPREXT_AWAY2 8
575 #define SPREXT_TSPRACCESS 16
576 #define SPREXT_TEMPINVISIBLE 32
577
578 #define NEG_ALPHA_TO_BLEND(alpha, blend, orientation) do { \
579 if ((alpha) < 0) { (blend) = -(alpha); (alpha) = 0; (orientation) |= RS_TRANS1; } \
580 } while (0)
581
582 // using the clipdist field
583 enum
584 {
585 TSPR_FLAGS_MDHACK = 1u<<0u,
586 TSPR_FLAGS_DRAW_LAST = 1u<<1u,
587 TSPR_FLAGS_NO_SHADOW = 1u<<2u,
588 TSPR_FLAGS_INVISIBLE_WITH_SHADOW = 1u<<3u,
589 TSPR_FLAGS_SLOPE_SPRITE = 1u<<4u,
590 };
591
592 EXTERN int32_t guniqhudid;
593 EXTERN int32_t spritesortcnt;
594 extern int32_t g_loadedMapVersion;
595
596 typedef struct {
597 char *mhkfile;
598 char *title;
599 uint8_t md4[16];
600 } usermaphack_t;
601
602 extern usermaphack_t g_loadedMapHack;
603 extern int compare_usermaphacks(const void *, const void *);
604 extern usermaphack_t *usermaphacks;
605 extern int32_t num_usermaphacks;
606
607 #if !defined DEBUG_MAIN_ARRAYS
608 EXTERN spriteext_t *spriteext;
609 EXTERN spritesmooth_t *spritesmooth;
610 # ifndef NEW_MAP_FORMAT
611 EXTERN wallext_t *wallext;
612 # endif
613
614 EXTERN sectortype *sector;
615 EXTERN walltype *wall;
616 EXTERN spritetype *sprite;
617 EXTERN tspriteptr_t tsprite;
618 #else
619 EXTERN spriteext_t spriteext[MAXSPRITES+MAXUNIQHUDID];
620 EXTERN spritesmooth_t spritesmooth[MAXSPRITES+MAXUNIQHUDID];
621 # ifndef NEW_MAP_FORMAT
622 EXTERN wallext_t wallext[MAXWALLS];
623 # endif
624
625 EXTERN sectortype sector[MAXSECTORS + M32_FIXME_SECTORS];
626 EXTERN walltype wall[MAXWALLS + M32_FIXME_WALLS];
627 EXTERN spritetype sprite[MAXSPRITES];
628 EXTERN uspritetype tsprite[MAXSPRITESONSCREEN];
629 #endif
630
631 #ifdef USE_STRUCT_TRACKERS
632 EXTERN uint32_t sectorchanged[MAXSECTORS + M32_FIXME_SECTORS];
633 EXTERN uint32_t wallchanged[MAXWALLS + M32_FIXME_WALLS];
634 EXTERN uint32_t spritechanged[MAXSPRITES];
635 #endif
636
637 #ifdef NEW_MAP_FORMAT
yax_getbunch(int16_t i,int16_t cf)638 static FORCE_INLINE int16_t yax_getbunch(int16_t i, int16_t cf)
639 {
640 return cf ? sector[i].floorbunch : sector[i].ceilingbunch;
641 }
642
yax_getbunches(int16_t i,int16_t * cb,int16_t * fb)643 static FORCE_INLINE void yax_getbunches(int16_t i, int16_t *cb, int16_t *fb)
644 {
645 *cb = yax_getbunch(i, YAX_CEILING);
646 *fb = yax_getbunch(i, YAX_FLOOR);
647 }
648
yax_getnextwall(int16_t wal,int16_t cf)649 static FORCE_INLINE int16_t yax_getnextwall(int16_t wal, int16_t cf)
650 {
651 return cf ? wall[wal].dnwall : wall[wal].upwall;
652 }
653
yax_setnextwall(int16_t wal,int16_t cf,int16_t thenextwall)654 static FORCE_INLINE void yax_setnextwall(int16_t wal, int16_t cf, int16_t thenextwall)
655 {
656 YAX_NEXTWALL(wal, cf) = thenextwall;
657 }
658 #endif
659
660 #ifdef USE_STRUCT_TRACKERS
sector_tracker_hook__(intptr_t const address)661 static FORCE_INLINE void sector_tracker_hook__(intptr_t const address)
662 {
663 intptr_t const sectnum = (address - (intptr_t)sector) / sizeof(sectortype);
664
665 #if DEBUGGINGAIDS>=2
666 Bassert((unsigned)sectnum < ((MAXSECTORS + M32_FIXME_SECTORS)));
667 #endif
668
669 ++sectorchanged[sectnum];
670 }
671
wall_tracker_hook__(intptr_t const address)672 static FORCE_INLINE void wall_tracker_hook__(intptr_t const address)
673 {
674 intptr_t const wallnum = (address - (intptr_t)wall) / sizeof(walltype);
675
676 #if DEBUGGINGAIDS>=2
677 Bassert((unsigned)wallnum < ((MAXWALLS + M32_FIXME_WALLS)));
678 #endif
679
680 ++wallchanged[wallnum];
681 }
682
sprite_tracker_hook__(intptr_t const address)683 static FORCE_INLINE void sprite_tracker_hook__(intptr_t const address)
684 {
685 intptr_t const spritenum = (address - (intptr_t)sprite) / sizeof(spritetype);
686
687 #if DEBUGGINGAIDS>=2
688 Bassert((unsigned)spritenum < MAXSPRITES);
689 #endif
690
691 ++spritechanged[spritenum];
692 }
693 #endif
694
renderMakeTSpriteFromSprite(tspriteptr_t const tspr,uint16_t const spritenum)695 static inline tspriteptr_t renderMakeTSpriteFromSprite(tspriteptr_t const tspr, uint16_t const spritenum)
696 {
697 auto const spr = (uspriteptr_t)&sprite[spritenum];
698
699 tspr->pos = spr->pos;
700 tspr->cstat = spr->cstat;
701 tspr->picnum = spr->picnum;
702 tspr->shade = spr->shade;
703 tspr->pal = spr->pal;
704 tspr->blend = spr->blend;
705 tspr->xrepeat = spr->xrepeat;
706 tspr->yrepeat = spr->yrepeat;
707 tspr->xoffset = spr->xoffset;
708 tspr->yoffset = spr->yoffset;
709 tspr->sectnum = spr->sectnum;
710 tspr->statnum = spr->statnum;
711 tspr->ang = spr->ang;
712 tspr->vel = spr->vel;
713 tspr->lotag = spr->lotag;
714 tspr->hitag = spr->hitag;
715 tspr->extra = spr->extra;
716
717 tspr->clipdist = 0;
718 tspr->owner = spritenum;
719
720 if ((tspr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) == CSTAT_SPRITE_ALIGNMENT_SLOPE)
721 {
722 tspr->cstat &= ~CSTAT_SPRITE_ALIGNMENT_MASK;
723 tspr->cstat |= CSTAT_SPRITE_ALIGNMENT_FLOOR;
724 tspr->clipdist |= TSPR_FLAGS_SLOPE_SPRITE;
725 }
726
727 return tspr;
728 }
729
renderAddTSpriteFromSprite(uint16_t const spritenum)730 static inline tspriteptr_t renderAddTSpriteFromSprite(uint16_t const spritenum)
731 {
732 return renderMakeTSpriteFromSprite(&tsprite[spritesortcnt++], spritenum);
733 }
734
spriteSetSlope(uint16_t const spritenum,int16_t const heinum)735 static inline void spriteSetSlope(uint16_t const spritenum, int16_t const heinum)
736 {
737 auto const spr = &sprite[spritenum];
738 uint16_t const cstat = spr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK;
739 if (cstat != CSTAT_SPRITE_ALIGNMENT_FLOOR && cstat != CSTAT_SPRITE_ALIGNMENT_SLOPE)
740 return;
741
742 spr->xoffset = heinum & 255;
743 spr->yoffset = (heinum >> 8) & 255;
744 spr->cstat &= ~CSTAT_SPRITE_ALIGNMENT_MASK;
745 spr->cstat |= heinum != 0 ? CSTAT_SPRITE_ALIGNMENT_SLOPE : CSTAT_SPRITE_ALIGNMENT_FLOOR;
746 }
747
spriteGetSlope(uint16_t const spritenum)748 static inline int16_t spriteGetSlope(uint16_t const spritenum)
749 {
750 auto const spr = &sprite[spritenum];
751 uint16_t const cstat = spr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK;
752 if (cstat != CSTAT_SPRITE_ALIGNMENT_SLOPE)
753 return 0;
754 return uint8_t(spr->xoffset) + (uint8_t(spr->yoffset) << 8);
755 }
756
757 extern int32_t animateoffs(int const tilenum, int fakevar);
758
759 EXTERN int16_t maskwall[MAXWALLSB], maskwallcnt;
760 EXTERN int16_t thewall[MAXWALLSB];
761 EXTERN tspriteptr_t tspriteptr[MAXSPRITESONSCREEN + 1];
762
763 EXTERN int32_t wx1, wy1, wx2, wy2;
764 EXTERN int32_t xdim, ydim, numpages, upscalefactor;
765 EXTERN int32_t yxaspect, viewingrange;
766 EXTERN intptr_t *ylookup;
767
768 EXTERN int32_t rotatesprite_y_offset;
769 EXTERN int32_t rotatesprite_yxaspect;
770
771 #ifndef GEKKO
772 #define MAXVALIDMODES 256
773 #else
774 #define MAXVALIDMODES 16
775 #endif
776 EXTERN int32_t validmodecnt;
777 struct validmode_t {
778 int32_t xdim,ydim;
779 char bpp;
780 char fs; // bit 0 = fullscreen flag
781 char filler[2];
782 int32_t extra; // internal use
783 };
784 EXTERN struct validmode_t validmode[MAXVALIDMODES];
785
786 EXTERN int32_t numyaxbunches;
787 #ifdef YAX_ENABLE
788 // Singly-linked list of sectnums grouped by bunches and ceiling (0)/floor (1)
789 // Usage e.g.:
790 // int16_t bunchnum = yax_getbunch(somesector, YAX_CEILING);
791 // Iteration over all sectors whose floor bunchnum equals 'bunchnum' (i.e. "all
792 // floors of the other side"):
793 // for (i=headsectbunch[1][bunchnum]; i!=-1; i=nextsectbunch[1][i])
794 // <do stuff with sector i...>
795
796 EXTERN int16_t headsectbunch[2][YAX_MAXBUNCHES], nextsectbunch[2][MAXSECTORS];
797 #endif
798
799 EXTERN int32_t Numsprites;
800 EXTERN int16_t numsectors, numwalls;
801 EXTERN int32_t display_mirror;
802 // totalclocklock: the totalclock value that is backed up once on each
803 // drawrooms() and is used for animateoffs().
804 EXTERN ClockTicks totalclock, totalclocklock;
BGetTime(void)805 static inline int32_t BGetTime(void) { return (int32_t) totalclock; }
806
807 EXTERN int32_t numframes, randomseed;
808 EXTERN int16_t sintable[2048];
809
810 EXTERN uint8_t palette[768];
811 EXTERN int16_t numshades;
812 EXTERN char *palookup[MAXPALOOKUPS];
813 extern uint8_t *basepaltable[MAXBASEPALS];
814 EXTERN uint8_t paletteloaded;
815 EXTERN char *blendtable[MAXBLENDTABS];
816 EXTERN uint8_t whitecol, redcol, blackcol;
817
818 EXTERN int32_t maxspritesonscreen;
819
820 enum {
821 PALETTE_MAIN = 1<<0,
822 PALETTE_SHADE = 1<<1,
823 PALETTE_TRANSLUC = 1<<2,
824 };
825
826 EXTERN char showinvisibility;
827 EXTERN int32_t g_visibility, parallaxvisibility;
828 EXTERN int32_t g_rotatespriteNoWidescreen;
829
830 // blendtable[1] to blendtable[numalphatabs] are considered to be
831 // alpha-blending tables:
832 EXTERN uint8_t numalphatabs;
833
834 EXTERN vec2_t windowxy1, windowxy2;
835 EXTERN int16_t *startumost, *startdmost;
836
837 // The maximum tile offset ever used in any tiled parallaxed multi-sky.
838 #define PSKYOFF_MAX 16
839 #define DEFAULTPSKY -1
840
841 typedef struct {
842 // The proportion at which looking up/down affects the apparent 'horiz' of
843 // a parallaxed sky, scaled by 65536 (so, a value of 65536 makes it align
844 // with the drawn surrounding scene):
845 int32_t horizfrac;
846
847 // The texel index offset in the y direction of a parallaxed sky:
848 // XXX: currently always 0.
849 int32_t yoffs;
850
851 int8_t lognumtiles; // 1<<lognumtiles: number of tiles in multi-sky
852 int8_t tileofs[MAXPSKYTILES]; // for 0 <= j < (1<<lognumtiles): tile offset relative to basetile
853
854 int32_t yscale;
855 } psky_t;
856
857 // Index of map-global (legacy) multi-sky:
858 EXTERN int32_t g_pskyidx;
859 // New multi-psky
860 EXTERN int32_t pskynummultis;
861 EXTERN psky_t * multipsky;
862 // Mapping of multi-sky index to base sky tile number:
863 EXTERN int32_t * multipskytile;
864
getpskyidx(int32_t picnum)865 static FORCE_INLINE int32_t getpskyidx(int32_t picnum)
866 {
867 int32_t j;
868
869 for (j=pskynummultis-1; j>0; j--) // NOTE: j==0 on non-early loop end
870 if (picnum == multipskytile[j])
871 break; // Have a match.
872
873 return j;
874 }
875
876 EXTERN psky_t * tileSetupSky(int32_t tilenum);
877
878 EXTERN char parallaxtype;
879 EXTERN int32_t parallaxyoffs_override, parallaxyscale_override;
880 extern int16_t pskybits_override;
881
882 // last sprite in the freelist, that is the spritenum for which
883 // .statnum==MAXSTATUS && nextspritestat[spritenum]==-1
884 // (or -1 if freelist is empty):
885 EXTERN int16_t tailspritefree;
886
887 EXTERN int16_t headspritesect[MAXSECTORS+1], headspritestat[MAXSTATUS+1];
888 EXTERN int16_t prevspritesect[MAXSPRITES], prevspritestat[MAXSPRITES];
889 EXTERN int16_t nextspritesect[MAXSPRITES], nextspritestat[MAXSPRITES];
890
891 EXTERN vec2_16_t tilesiz[MAXTILES];
892
893 EXTERN char picsiz[MAXTILES];
894 EXTERN char walock[MAXTILES];
895
896 extern const char pow2char_[];
897 static CONSTEXPR const int32_t pow2long[32] =
898 {
899 1, 2, 4, 8,
900 16, 32, 64, 128,
901 256, 512, 1024, 2048,
902 4096, 8192, 16384, 32768,
903 65536, 131072, 262144, 524288,
904 1048576, 2097152, 4194304, 8388608,
905 16777216, 33554432, 67108864, 134217728,
906 268435456, 536870912, 1073741824, 2147483647
907 };
908
909 // picanm[].sf:
910 // |bit(1<<7)
911 // |animtype|animtype|texhitscan|nofullbright|speed|speed|speed|speed|
912 enum {
913 PICANM_ANIMTYPE_NONE = 0,
914 PICANM_ANIMTYPE_OSC = (1<<6),
915 PICANM_ANIMTYPE_FWD = (2<<6),
916 PICANM_ANIMTYPE_BACK = (3<<6),
917
918 PICANM_ANIMTYPE_SHIFT = 6,
919 PICANM_ANIMTYPE_MASK = (3<<6), // must be 192
920 PICANM_MISC_MASK = (3<<4),
921 PICANM_TEXHITSCAN_BIT = (2<<4),
922 PICANM_NOFULLBRIGHT_BIT = (1<<4),
923 PICANM_ANIMSPEED_MASK = 15, // must be 15
924 };
925
926 enum {
927 TILEFLAGS_NONE = 0,
928 TILEFLAGS_TRUENPOT = (1<<1),
929 };
930
931 // NOTE: If the layout of this struct is changed, loadpics() must be modified
932 // accordingly.
933 typedef struct {
934 uint8_t num; // animate number
935 int8_t xofs, yofs;
936 uint8_t sf; // anim. speed and flags
937 uint8_t tileflags; // tile-specific flags, such as true non-power-of-2 drawing.
938 uint8_t extra;
939 } picanm_t;
940 EXTERN picanm_t picanm[MAXTILES];
941 typedef struct { int16_t newtile; int16_t owner; } rottile_t;
942 EXTERN rottile_t rottile[MAXTILES];
943 EXTERN intptr_t waloff[MAXTILES]; // stores pointers to cache -- SA
944
945 EXTERN int32_t windowpos, windowx, windowy;
946
947 //These variables are for auto-mapping with the draw2dscreen function.
948 //When you load a new board, these bits are all set to 0 - since
949 //you haven't mapped out anything yet. Note that these arrays are
950 //bit-mapped.
951 //If you want draw2dscreen() to show sprite #54 then you say:
952 // spritenum = 54;
953 // show2dsprite[spritenum>>3] |= (1<<(spritenum&7));
954 //And if you want draw2dscreen() to not show sprite #54 then you say:
955 // spritenum = 54;
956 // show2dsprite[spritenum>>3] &= ~(1<<(spritenum&7));
957
958 EXTERN int automapping;
959 EXTERN char show2dsector[(MAXSECTORS+7)>>3];
960 EXTERN char show2dwall[(MAXWALLS+7)>>3];
961 EXTERN char show2dsprite[(MAXSPRITES+7)>>3];
962
963 // In the editor, gotpic is only referenced from inline assembly;
964 // the compiler needs that hint or building with LTO will discard it.
965 #if !defined __clang__ && !defined NOASM
966 # define GOTPIC_USED ATTRIBUTE((used))
967 #else
968 # define GOTPIC_USED
969 #endif
970
971 EXTERN char GOTPIC_USED gotpic[(MAXTILES+7)>>3];
972 EXTERN char gotsector[(MAXSECTORS+7)>>3];
973
974 EXTERN char editorcolors[256];
975 EXTERN char editorcolorsdef[256];
976
977 EXTERN char faketile[(MAXTILES+7)>>3];
978 EXTERN char *faketiledata[MAXTILES];
979 EXTERN int faketilesize[MAXTILES];
980
981 EXTERN char spritecol2d[MAXTILES][2];
982 EXTERN uint8_t tilecols[MAXTILES];
983
984 EXTERN char editwall[(MAXWALLS+7)>>3];
985
986 extern uint8_t vgapal16[4*256];
987
988 extern uint32_t drawlinepat;
989
990 extern void faketimerhandler(void);
991
992 extern char apptitle[256];
993
994 extern int32_t novoxmips;
995
996 #ifdef DEBUGGINGAIDS
997 extern float debug1, debug2;
998 #endif
999
1000 extern int16_t tiletovox[MAXTILES];
1001 extern int32_t usevoxels, voxscale[MAXVOXELS];
1002 extern char g_haveVoxels;
1003
1004 #ifdef USE_OPENGL
1005 extern int32_t usemodels, usehightile;
1006 extern int32_t rendmode;
1007 #endif
1008 extern uint8_t globalr, globalg, globalb;
1009 EXTERN uint16_t h_xsize[MAXTILES], h_ysize[MAXTILES];
1010 EXTERN int8_t h_xoffs[MAXTILES], h_yoffs[MAXTILES];
1011
1012 EXTERN char *globalpalwritten;
1013
1014 enum {
1015 GLOBAL_NO_GL_TILESHADES = 1<<0,
1016 GLOBAL_NO_GL_FULLBRIGHT = 1<<1,
1017 GLOBAL_NO_GL_FOGSHADE = 1<<2,
1018 };
1019
1020 extern int32_t globalflags;
1021
1022 extern const char *engineerrstr;
1023
1024 EXTERN int32_t editorzrange[2];
1025
videoGetRenderMode(void)1026 static FORCE_INLINE int32_t videoGetRenderMode(void)
1027 {
1028 #ifndef USE_OPENGL
1029 return REND_CLASSIC;
1030 #else
1031 return rendmode;
1032 #endif
1033 }
1034
1035 extern int32_t bloodhack;
1036 enum
1037 {
1038 ENGINE_19950829 = 19950829, // Powerslave/Exhumed
1039 ENGINE_19960925 = 19960925, // Blood v1.21
1040 ENGINE_19961112 = 19961112, // Duke 3D v1.5, Redneck Rampage
1041 ENGINE_EDUKE32 = INT_MAX,
1042 };
1043
1044 #ifndef EDUKE32_STANDALONE
1045 extern int32_t enginecompatibilitymode;
1046 #else
1047 static CONSTEXPR int32_t const enginecompatibilitymode = ENGINE_EDUKE32;
1048 #endif
1049
1050 EXTERN int32_t duke64;
1051 extern bool (*rt_tileload_callback)(int16_t tileNum);
1052
1053 /*************************************************************************
1054 POSITION VARIABLES:
1055
1056 POSX is your x - position ranging from 0 to 65535
1057 POSY is your y - position ranging from 0 to 65535
1058 (the length of a side of the grid in EDITBORD would be 1024)
1059 POSZ is your z - position (height) ranging from 0 to 65535, 0 highest.
1060 ANG is your angle ranging from 0 to 2047. Instead of 360 degrees, or
1061 2 * PI radians, I use 2048 different angles, so 90 degrees would
1062 be 512 in my system.
1063
1064 SPRITE VARIABLES:
1065
1066 EXTERN short headspritesect[MAXSECTORS+1], headspritestat[MAXSTATUS+1];
1067 EXTERN short prevspritesect[MAXSPRITES], prevspritestat[MAXSPRITES];
1068 EXTERN short nextspritesect[MAXSPRITES], nextspritestat[MAXSPRITES];
1069
1070 Example: if the linked lists look like the following:
1071 ????????????????
1072 Sector lists: Status lists:
1073 ????????????????J
1074 Sector0: 4, 5, 8 Status0: 2, 0, 8
1075 Sector1: 16, 2, 0, 7 Status1: 4, 5, 16, 7, 3, 9
1076 Sector2: 3, 9
1077 ????????????????
1078 Notice that each number listed above is shown exactly once on both the
1079 left and right side. This is because any sprite that exists must
1080 be in some sector, and must have some kind of status that you define.
1081
1082
1083 Coding example #1:
1084 To go through all the sprites in sector 1, the code can look like this:
1085
1086 sectnum = 1;
1087 i = headspritesect[sectnum];
1088 while (i != -1)
1089 {
1090 nexti = nextspritesect[i];
1091
1092 //your code goes here
1093 //ex: printf("Sprite %d is in sector %d\n",i,sectnum);
1094
1095 i = nexti;
1096 }
1097
1098 Coding example #2:
1099 To go through all sprites with status = 1, the code can look like this:
1100
1101 statnum = 1; //status 1
1102 i = headspritestat[statnum];
1103 while (i != -1)
1104 {
1105 nexti = nextspritestat[i];
1106
1107 //your code goes here
1108 //ex: printf("Sprite %d has a status of 1 (active)\n",i,statnum);
1109
1110 i = nexti;
1111 }
1112
1113 insertsprite(short sectnum, short statnum);
1114 deletesprite(short spritenum);
1115 changespritesect(short spritenum, short newsectnum);
1116 changespritestat(short spritenum, short newstatnum);
1117
1118 TILE VARIABLES:
1119 NUMTILES - the number of tiles found TILES.DAT.
1120 TILESIZX[MAXTILES] - simply the x-dimension of the tile number.
1121 TILESIZY[MAXTILES] - simply the y-dimension of the tile number.
1122 WALOFF[MAXTILES] - the actual address pointing to the top-left
1123 corner of the tile.
1124 PICANM[MAXTILES] - flags for animating the tile.
1125
1126 TIMING VARIABLES:
1127 TOTALCLOCK - When the engine is initialized, TOTALCLOCK is set to zero.
1128 From then on, it is incremented 120 times a second by 1. That
1129 means that the number of seconds elapsed is totalclock / 120.
1130 NUMFRAMES - The number of times the draw3dscreen function was called
1131 since the engine was initialized. This helps to determine frame
1132 rate. (Frame rate = numframes * 120 / totalclock.)
1133
1134 OTHER VARIABLES:
1135
1136 STARTUMOST[320] is an array of the highest y-coordinates on each column
1137 that my engine is allowed to write to. You need to set it only
1138 once.
1139 STARTDMOST[320] is an array of the lowest y-coordinates on each column
1140 that my engine is allowed to write to. You need to set it only
1141 once.
1142 SINTABLE[2048] is a sin table with 2048 angles rather than the
1143 normal 360 angles for higher precision. Also since SINTABLE is in
1144 all integers, the range is multiplied by 16383, so instead of the
1145 normal -1<sin(x)<1, the range of sintable is -16383<sintable[]<16383
1146 If you use this sintable, you can possibly speed up your code as
1147 well as save space in memory. If you plan to use sintable, 2
1148 identities you may want to keep in mind are:
1149 sintable[ang&2047] = sin(ang * (3.141592/1024)) * 16383
1150 sintable[(ang+512)&2047] = cos(ang * (3.141592/1024)) * 16383
1151 NUMSECTORS - the total number of existing sectors. Modified every time
1152 you call the loadboard function.
1153 ***************************************************************************/
1154
1155 typedef struct {
1156 vec3_t pos;
1157 int16_t sprite, wall, sect;
1158 } hitdata_t;
1159
1160 typedef struct artheader_t {
1161 int32_t tilestart, tileend, numtiles;
1162 } artheader_t;
1163 #define ARTv1_UNITOFFSET ((signed)(4*sizeof(int32_t) + 2*sizeof(int16_t) + sizeof(picanm_t)))
1164
1165 int32_t enginePreInit(void); // a partial setup of the engine used for launch windows
1166 int32_t engineInit(void);
1167 int32_t enginePostInit(void);
1168 void engineUnInit(void);
1169 void initspritelists(void);
1170 int32_t engineFatalError(char const * msg);
1171
1172 int32_t engineLoadBoard(const char *filename, char flags, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum);
1173 int32_t engineLoadMHK(const char *filename);
1174 void engineClearLightsFromMHK();
1175 #ifdef HAVE_CLIPSHAPE_FEATURE
1176 int32_t engineLoadClipMaps(void);
1177 #endif
1178 int32_t saveboard(const char *filename, const vec3_t *dapos, int16_t daang, int16_t dacursectnum);
1179
1180 void tileSetupDummy(int32_t tile);
1181 void tileSetData(int32_t tile, int32_t tsiz, char const *buffer);
1182 void tileDelete(int32_t tile);
1183 void tileSetSize(int32_t picnum, int16_t dasizx, int16_t dasizy);
1184 int32_t artReadHeader(buildvfs_kfd fil, char const *fn, artheader_t *local);
1185 int32_t artReadHeaderFromBuffer(uint8_t const *buf, artheader_t *local);
1186 int32_t artCheckUnitFileHeader(uint8_t const *buf, int32_t length);
1187 void tileConvertAnimFormat(int32_t picnum, uint32_t const picanmdisk);
1188 void artReadManifest(buildvfs_kfd fil, artheader_t const *local);
1189 void artPreloadFile(buildvfs_kfd fil, artheader_t const *local);
1190 int32_t artLoadFiles(const char *filename, int32_t askedsize);
1191 void artClearMapArt(void);
1192 void artSetupMapArt(const char *filename);
1193 bool tileLoad(int16_t tilenume);
1194 void tileLoadData(int16_t tilenume, int32_t dasiz, char *buffer);
1195 int32_t tileGetCRC32(int16_t tileNum);
1196 vec2_16_t tileGetSize(int16_t tileNum);
1197 void artConvertRGB(palette_t *pic, uint8_t const *buf, int32_t bufsizx, int32_t sizx, int32_t sizy);
1198 void tileUpdatePicSiz(int32_t picnum);
1199
1200 int32_t qloadkvx(int32_t voxindex, const char *filename);
1201 void vox_undefine(int32_t const);
1202 intptr_t tileCreate(int16_t tilenume, int32_t xsiz, int32_t ysiz);
1203 void tileCopySection(int32_t tilenume1, int32_t sx1, int32_t sy1, int32_t xsiz, int32_t ysiz, int32_t tilenume2, int32_t sx2, int32_t sy2);
1204 void squarerotatetile(int16_t tilenume);
1205
1206 int32_t videoSetGameMode(char davidoption, int32_t daupscaledxdim, int32_t daupscaledydim, int32_t dabpp, int32_t daupscalefactor);
1207 void videoNextPage(void);
1208 void videoSetCorrectedAspect();
1209 void videoSetViewableArea(int32_t x1, int32_t y1, int32_t x2, int32_t y2);
1210 void renderSetAspect(int32_t daxrange, int32_t daaspect);
1211 void renderFlushPerms(void);
1212
1213 void plotlines2d(const int32_t *xx, const int32_t *yy, int32_t numpoints, int col) ATTRIBUTE((nonnull(1,2)));
1214
1215 void plotpixel(int32_t x, int32_t y, char col);
1216 void renderSetTarget(int16_t tilenume, int32_t xsiz, int32_t ysiz);
1217 void renderRestoreTarget(void);
1218 void renderPrepareMirror(int32_t dax, int32_t day, int32_t daz, fix16_t daang, fix16_t dahoriz, int16_t dawall,
1219 int32_t *tposx, int32_t *tposy, fix16_t *tang);
1220 void renderCompleteMirror(void);
1221
1222 int32_t renderDrawRoomsQ16(int32_t daposx, int32_t daposy, int32_t daposz, fix16_t daang, fix16_t dahoriz, int16_t dacursectnum);
1223
drawrooms(int32_t daposx,int32_t daposy,int32_t daposz,int16_t daang,int16_t dahoriz,int16_t dacursectnum)1224 static FORCE_INLINE int32_t drawrooms(int32_t daposx, int32_t daposy, int32_t daposz, int16_t daang, int16_t dahoriz, int16_t dacursectnum)
1225 {
1226 return renderDrawRoomsQ16(daposx, daposy, daposz, fix16_from_int(daang), fix16_from_int(dahoriz), dacursectnum);
1227 }
1228
1229 void renderDrawMasks(void);
1230 void videoClearViewableArea(int32_t dacol);
1231 void videoClearScreen(int32_t dacol);
1232 void renderDrawMapView(int32_t dax, int32_t day, int32_t zoome, int16_t ang);
1233 void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
1234 int8_t dashade, char dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
1235 int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2);
1236 void renderDrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, char col);
1237 void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, palette_t p);
1238 int32_t printext16(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol,
1239 const char *name, char fontsize) ATTRIBUTE((nonnull(5)));
1240 void printext256(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol,
1241 const char *name, char fontsize) ATTRIBUTE((nonnull(5)));
1242 void Buninitart(void);
1243
1244 ////////// specialized rotatesprite wrappers for (very) often used cases //////////
rotatesprite(int32_t sx,int32_t sy,int32_t z,int16_t a,int16_t picnum,int8_t dashade,char dapalnum,int32_t dastat,int32_t cx1,int32_t cy1,int32_t cx2,int32_t cy2)1245 static FORCE_INLINE void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
1246 int8_t dashade, char dapalnum, int32_t dastat,
1247 int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2)
1248 {
1249 rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, cx1, cy1, cx2, cy2);
1250 }
1251 // Don't clip at all, i.e. the whole screen real estate is available:
rotatesprite_fs(int32_t sx,int32_t sy,int32_t z,int16_t a,int16_t picnum,int8_t dashade,char dapalnum,int32_t dastat)1252 static FORCE_INLINE void rotatesprite_fs(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
1253 int8_t dashade, char dapalnum, int32_t dastat)
1254 {
1255 rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, 0,0,xdim-1,ydim-1);
1256 }
1257
rotatesprite_fs_alpha(int32_t sx,int32_t sy,int32_t z,int16_t a,int16_t picnum,int8_t dashade,char dapalnum,int32_t dastat,uint8_t alpha)1258 static FORCE_INLINE void rotatesprite_fs_alpha(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
1259 int8_t dashade, char dapalnum, int32_t dastat, uint8_t alpha)
1260 {
1261 rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, alpha, 0, 0, 0, xdim-1, ydim-1);
1262 }
1263
rotatesprite_win(int32_t sx,int32_t sy,int32_t z,int16_t a,int16_t picnum,int8_t dashade,char dapalnum,int32_t dastat)1264 static FORCE_INLINE void rotatesprite_win(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
1265 int8_t dashade, char dapalnum, int32_t dastat)
1266 {
1267 rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, windowxy1.x,windowxy1.y,windowxy2.x,windowxy2.y);
1268 }
1269
1270 void getzrange(const vec3_t *pos, int16_t sectnum, int32_t *ceilz, int32_t *ceilhit, int32_t *florz,
1271 int32_t *florhit, int32_t walldist, uint32_t cliptype) ATTRIBUTE((nonnull(1,3,4,5,6)));
1272 extern vec2_t hitscangoal;
1273 int32_t hitscan(const vec3_t *sv, int16_t sectnum, int32_t vx, int32_t vy, int32_t vz,
1274 hitdata_t *hitinfo, uint32_t cliptype) ATTRIBUTE((nonnull(1,6)));
1275 void neartag(int32_t xs, int32_t ys, int32_t zs, int16_t sectnum, int16_t ange,
1276 int16_t *neartagsector, int16_t *neartagwall, int16_t *neartagsprite,
1277 int32_t *neartaghitdist, int32_t neartagrange, uint8_t tagsearch,
1278 int32_t (*blacklist_sprite_func)(int32_t)) ATTRIBUTE((nonnull(6,7,8)));
1279 int32_t cansee(int32_t x1, int32_t y1, int32_t z1, int16_t sect1,
1280 int32_t x2, int32_t y2, int32_t z2, int16_t sect2);
1281 int32_t inside(int32_t x, int32_t y, int16_t sectnum);
1282 void dragpoint(int16_t pointhighlight, int32_t dax, int32_t day, uint8_t flags);
1283 void setfirstwall(int16_t sectnum, int16_t newfirstwall);
1284 int32_t try_facespr_intersect(uspriteptr_t const spr, vec3_t const in,
1285 int32_t vx, int32_t vy, int32_t vz,
1286 vec3_t * const intp, int32_t strictly_smaller_than_p);
1287
1288 #define MAXUPDATESECTORDIST 1536
1289 #define INITIALUPDATESECTORDIST 256
1290 void updatesector(int32_t const x, int32_t const y, int16_t * const sectnum) ATTRIBUTE((nonnull(3)));
1291 void updatesectorexclude(int32_t const x, int32_t const y, int16_t * const sectnum,
1292 const uint8_t * const excludesectbitmap) ATTRIBUTE((nonnull(3,4)));
1293 void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum) ATTRIBUTE((nonnull(4)));
1294 void updatesectorneighbor(int32_t const x, int32_t const y, int16_t * const sectnum, int32_t initialMaxDistance = INITIALUPDATESECTORDIST, int32_t maxDistance = MAXUPDATESECTORDIST) ATTRIBUTE((nonnull(3)));
1295 void updatesectorneighborz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum, int32_t initialMaxDistance = INITIALUPDATESECTORDIST, int32_t maxDistance = MAXUPDATESECTORDIST) ATTRIBUTE((nonnull(4)));
1296
1297 int findwallbetweensectors(int sect1, int sect2);
sectoradjacent(int sect1,int sect2)1298 static FORCE_INLINE int sectoradjacent(int sect1, int sect2) { return findwallbetweensectors(sect1, sect2) != -1; }
1299 int32_t getsectordist(vec2_t const in, int const sectnum, vec2_t * const out = nullptr);
1300 extern const int16_t *chsecptr_onextwall;
1301 int32_t checksectorpointer(int16_t i, int16_t sectnum);
1302
1303 void mouseGetValues(int32_t *mousx, int32_t *mousy, int32_t *bstatus) ATTRIBUTE((nonnull(1,2,3)));
1304
1305 #if !KRANDDEBUG
krand(void)1306 static FORCE_INLINE int32_t krand(void)
1307 {
1308 randomseed = (randomseed * 1664525ul) + 221297ul;
1309 return ((uint32_t) randomseed)>>16;
1310 }
1311 #else
1312 int32_t krand(void);
1313 #endif
1314
1315 int32_t ksqrt(uint32_t num);
1316 int32_t __fastcall getangle(int32_t xvect, int32_t yvect);
1317 fix16_t __fastcall gethiq16angle(int32_t xvect, int32_t yvect);
1318
getq16angle(int32_t xvect,int32_t yvect)1319 static FORCE_INLINE fix16_t __fastcall getq16angle(int32_t xvect, int32_t yvect)
1320 {
1321 return fix16_from_int(getangle(xvect, yvect));
1322 }
1323
uhypsq(int32_t const dx,int32_t const dy)1324 static FORCE_INLINE CONSTEXPR uint32_t uhypsq(int32_t const dx, int32_t const dy)
1325 {
1326 return (uint32_t)dx*dx + (uint32_t)dy*dy;
1327 }
1328
logapproach(int32_t const val,int32_t const targetval)1329 static FORCE_INLINE int32_t logapproach(int32_t const val, int32_t const targetval)
1330 {
1331 int32_t const dif = targetval - val;
1332 return (dif>>1) ? val + (dif>>1) : targetval;
1333 }
1334
1335 void rotatepoint(vec2_t const pivot, vec2_t p, int16_t const daang, vec2_t * const p2) ATTRIBUTE((nonnull(4)));
1336
rotatevec(vec2_t p,int16_t const daang,vec2_t * const p2)1337 static inline void rotatevec(vec2_t p, int16_t const daang, vec2_t * const p2)
1338 {
1339 int const dacos = sintable[(daang+2560)&2047];
1340 int const dasin = sintable[(daang+2048)&2047];
1341 *p2 = { dmulscale14(p.x, dacos, -p.y, dasin), dmulscale14(p.y, dacos, p.x, dasin) };
1342 }
1343
1344
1345 int32_t lastwall(int16_t point);
1346 int32_t nextsectorneighborz(int16_t sectnum, int32_t refz, int16_t topbottom, int16_t direction);
1347
1348 int32_t getceilzofslopeptr(usectorptr_t sec, int32_t dax, int32_t day) ATTRIBUTE((nonnull(1)));
1349 int32_t getflorzofslopeptr(usectorptr_t sec, int32_t dax, int32_t day) ATTRIBUTE((nonnull(1)));
1350 void getzsofslopeptr(usectorptr_t sec, int32_t dax, int32_t day,
1351 int32_t *ceilz, int32_t *florz) ATTRIBUTE((nonnull(1,4,5)));
1352 void yax_getzsofslope(int sectNum, int playerX, int playerY, int32_t* pCeilZ, int32_t* pFloorZ);
1353
1354 int32_t yax_getceilzofslope(int const sectnum, vec2_t const vect);
1355 int32_t yax_getflorzofslope(int const sectnum, vec2_t const vect);
1356
getceilzofslope(int16_t sectnum,int32_t dax,int32_t day)1357 static FORCE_INLINE int32_t getceilzofslope(int16_t sectnum, int32_t dax, int32_t day)
1358 {
1359 return getceilzofslopeptr((usectorptr_t)§or[sectnum], dax, day);
1360 }
1361
getflorzofslope(int16_t sectnum,int32_t dax,int32_t day)1362 static FORCE_INLINE int32_t getflorzofslope(int16_t sectnum, int32_t dax, int32_t day)
1363 {
1364 return getflorzofslopeptr((usectorptr_t)§or[sectnum], dax, day);
1365 }
1366
getzsofslope(int16_t sectnum,int32_t dax,int32_t day,int32_t * ceilz,int32_t * florz)1367 static FORCE_INLINE void getzsofslope(int16_t sectnum, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz)
1368 {
1369 getzsofslopeptr((usectorptr_t)§or[sectnum], dax, day, ceilz, florz);
1370 }
1371
getcorrectzsofslope(int16_t sectnum,int32_t dax,int32_t day,int32_t * ceilz,int32_t * florz)1372 static FORCE_INLINE void getcorrectzsofslope(int16_t sectnum, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz)
1373 {
1374 vec2_t closest = { dax, day };
1375 getsectordist(closest, sectnum, &closest);
1376 getzsofslopeptr((usectorptr_t)§or[sectnum], closest.x, closest.y, ceilz, florz);
1377 }
1378
getcorrectceilzofslope(int16_t sectnum,int32_t dax,int32_t day)1379 static FORCE_INLINE int32_t getcorrectceilzofslope(int16_t sectnum, int32_t dax, int32_t day)
1380 {
1381 vec2_t closest = { dax, day };
1382 getsectordist(closest, sectnum, &closest);
1383 return getceilzofslopeptr((usectorptr_t)§or[sectnum], closest.x, closest.y);
1384 }
1385
getcorrectflorzofslope(int16_t sectnum,int32_t dax,int32_t day)1386 static FORCE_INLINE int32_t getcorrectflorzofslope(int16_t sectnum, int32_t dax, int32_t day)
1387 {
1388 vec2_t closest = { dax, day };
1389 getsectordist(closest, sectnum, &closest);
1390 return getflorzofslopeptr((usectorptr_t)§or[sectnum], closest.x, closest.y);
1391 }
1392
1393 // Is <wal> a red wall in a safe fashion, i.e. only if consistency invariant
1394 // ".nextsector >= 0 iff .nextwall >= 0" holds.
redwallp(uwallptr_t wal)1395 static FORCE_INLINE CONSTEXPR int32_t redwallp(uwallptr_t wal)
1396 {
1397 return (wal->nextwall >= 0 && wal->nextsector >= 0);
1398 }
1399
E_SpriteIsValid(const int32_t i)1400 static FORCE_INLINE CONSTEXPR int32_t E_SpriteIsValid(const int32_t i)
1401 {
1402 return ((unsigned)i < MAXSPRITES && sprite[i].statnum != MAXSTATUS);
1403 }
1404
1405 int clipshape_idx_for_sprite(uspriteptr_t curspr, int curidx);
1406
1407 void alignceilslope(int16_t dasect, int32_t x, int32_t y, int32_t z);
1408 void alignflorslope(int16_t dasect, int32_t x, int32_t y, int32_t z);
1409 int32_t sectorofwall(int16_t wallNum);
1410 int32_t sectorofwall_noquick(int16_t wallNum);
1411 int32_t loopnumofsector(int16_t sectnum, int16_t wallnum);
1412 void setslope(int32_t sectnum, int32_t cf, int16_t slope);
1413
1414 int32_t lintersect(int32_t originX, int32_t originY, int32_t originZ,
1415 int32_t destX, int32_t destY, int32_t destZ,
1416 int32_t lineStartX, int32_t lineStartY, int32_t lineEndX, int32_t lineEndY,
1417 int32_t *intersectionX, int32_t *intersectionY, int32_t *intersectionZ);
1418
1419 int32_t rayintersect(int32_t x1, int32_t y1, int32_t z1, int32_t vx, int32_t vy, int32_t vz, int32_t x3,
1420 int32_t y3, int32_t x4, int32_t y4, int32_t *intx, int32_t *inty, int32_t *intz);
1421 #if !defined NETCODE_DISABLE
1422 void do_insertsprite_at_headofstat(int16_t spritenum, int16_t statnum);
1423 int32_t insertspritestat(int16_t statnum);
1424 void do_deletespritestat(int16_t deleteme);
1425 void do_insertsprite_at_headofsect(int16_t spritenum, int16_t sectnum);
1426 void do_deletespritesect(int16_t deleteme);
1427 #endif
1428 int32_t insertsprite(int16_t sectnum, int16_t statnum);
1429 int32_t deletesprite(int16_t spritenum);
1430
1431 int32_t changespritesect(int16_t spritenum, int16_t newsectnum);
1432 int32_t changespritestat(int16_t spritenum, int16_t newstatnum);
1433 int32_t setsprite(int16_t spritenum, const vec3_t *) ATTRIBUTE((nonnull(2)));
1434 int32_t setspritez(int16_t spritenum, const vec3_t *) ATTRIBUTE((nonnull(2)));
1435
1436 int32_t spriteheightofsptr(uspriteptr_t spr, int32_t *height, int32_t alsotileyofs);
spriteheightofs(int16_t i,int32_t * height,int32_t alsotileyofs)1437 static FORCE_INLINE int32_t spriteheightofs(int16_t i, int32_t *height, int32_t alsotileyofs)
1438 {
1439 return spriteheightofsptr((uspriteptr_t)&sprite[i], height, alsotileyofs);
1440 }
1441
1442 int videoCaptureScreen(const char *filename, char inverseit) ATTRIBUTE((nonnull(1)));
1443 int videoCaptureScreenTGA(const char *filename, char inverseit) ATTRIBUTE((nonnull(1)));
1444
1445 struct OutputFileCounter {
1446 uint16_t count = 0;
1447 buildvfs_FILE opennextfile(char *, char *);
1448 buildvfs_FILE opennextfile_withext(char *, const char *);
1449 };
1450
1451 // PLAG: line utility functions
1452 typedef struct s_equation
1453 {
1454 float a, b, c;
1455 } _equation;
1456
1457 int32_t wallvisible(int32_t const x, int32_t const y, int16_t const wallnum);
1458
1459 #define STATUS2DSIZ 144
1460 #define STATUS2DSIZ2 26
1461
1462 //void qsetmode640350(void);
1463 //void qsetmode640480(void);
1464 void videoSet2dMode(int32_t,int32_t);
1465 void clear2dscreen(void);
1466 void editorDraw2dGrid(int32_t posxe, int32_t posye, int32_t posze, int16_t cursectnum,
1467 int16_t ange, int32_t zoome, int16_t gride);
1468 void editorDraw2dScreen(const vec3_t *pos, int16_t cursectnum,
1469 int16_t ange, int32_t zoome, int16_t gride) ATTRIBUTE((nonnull(1)));
1470 int32_t editorDraw2dLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int col);
1471 void editorDraw2dCircle(int32_t x1, int32_t y1, int32_t r, int32_t eccen, char col);
1472
1473 int32_t videoSetRenderMode(int32_t renderer);
1474
1475 #ifdef USE_OPENGL
1476 void renderSetRollAngle(int32_t rolla);
1477 #endif
1478
1479 // pal: pass -1 to invalidate all palettes for the tile, or >=0 for a particular palette
1480 // how: pass -1 to invalidate all instances of the tile in texture memory, or a bitfield
1481 // bit 0: opaque or masked (non-translucent) texture, using repeating
1482 // bit 1: ignored
1483 // bit 2: 33% translucence, using repeating
1484 // bit 3: 67% translucence, using repeating
1485 // bit 4: opaque or masked (non-translucent) texture, using clamping
1486 // bit 5: ignored
1487 // bit 6: 33% translucence, using clamping
1488 // bit 7: 67% translucence, using clamping
1489 // clamping is for sprites, repeating is for walls
1490 void tileInvalidate(int16_t tilenume, int32_t pal, int32_t how);
1491
1492 void polymostSet2dView(void); // sets up GL for 2D drawing
1493
1494 int32_t polymost_drawtilescreen(int32_t tilex, int32_t tiley, int32_t wallnum, int32_t dimen, int32_t tilezoom,
1495 int32_t usehitile, uint8_t *loadedhitile);
1496 void polymost_glreset(void);
1497 void polymost_precache(int32_t dapicnum, int32_t dapalnum, int32_t datype);
1498
1499 typedef uint16_t polytintflags_t;
1500
1501 enum cutsceneflags {
1502 CUTSCENE_FORCEFILTER = 1,
1503 CUTSCENE_FORCENOFILTER = 2,
1504 CUTSCENE_TEXTUREFILTER = 4,
1505 };
1506
1507 extern int32_t benchmarkScreenshot;
1508
1509 #ifdef USE_OPENGL
1510 extern int32_t glanisotropy;
1511 extern int32_t glusetexcompr;
1512 extern int32_t gltexfiltermode;
1513 extern int32_t r_useindexedcolortextures;
1514
1515 enum {
1516 TEXFILTER_OFF = 0, // GL_NEAREST
1517 TEXFILTER_ON = 5, // GL_LINEAR_MIPMAP_LINEAR
1518 };
1519
1520 extern int32_t glusetexcache, glusememcache;
1521 extern int32_t glprojectionhacks;
1522 extern int32_t gltexmaxsize;
1523 void gltexapplyprops (void);
1524 void texcache_invalidate(void);
1525
1526 # ifdef USE_GLEXT
1527 extern int32_t r_detailmapping;
1528 extern int32_t r_glowmapping;
1529 # endif
1530
1531 extern int32_t r_vertexarrays;
1532 # ifdef USE_GLEXT
1533 extern int32_t r_vbos;
1534 extern int32_t r_vbocount;
1535 # endif
1536 extern int32_t r_animsmoothing;
1537 extern int32_t r_parallaxskyclamping;
1538 extern int32_t r_parallaxskypanning;
1539 extern int32_t r_fullbrights;
1540 extern int32_t r_downsize;
1541 extern int32_t r_downsizevar;
1542 extern int32_t mdtims, omdtims;
1543 extern int32_t glrendmode;
1544
1545 extern int32_t r_rortexture;
1546 extern int32_t r_rortexturerange;
1547 extern int32_t r_rorphase;
1548 #endif
1549
1550 void hicinit(void);
1551 void hicsetpalettetint(int32_t palnum, char r, char g, char b, char sr, char sg, char sb, polytintflags_t effect);
1552 // flags bitset: 1 = don't compress
1553 int32_t hicsetsubsttex(int32_t picnum, int32_t palnum, const char *filen, float alphacut,
1554 float xscale, float yscale, float specpower, float specfactor, char flags);
1555 int32_t hicsetskybox(int32_t picnum, int32_t palnum, char *faces[6], int32_t flags);
1556 int32_t hicclearsubst(int32_t picnum, int32_t palnum);
1557
1558 int32_t Ptile2tile(int32_t tile, int32_t palette) ATTRIBUTE((pure));
1559 int32_t md_loadmodel(const char *fn);
1560 int32_t md_setmisc(int32_t modelid, float scale, int32_t shadeoff, float zadd, float yoffset, int32_t flags);
1561 // int32_t md_tilehasmodel(int32_t tilenume, int32_t pal);
1562
1563 extern const char *G_DefaultDefFile(void);
1564 extern const char *G_DefFile(void);
1565 extern char *g_defNamePtr;
1566
1567 extern GrowArray<char *> g_defModules;
1568
1569 #ifdef HAVE_CLIPSHAPE_FEATURE
1570 extern GrowArray<char *> g_clipMapFiles;
1571 #endif
1572
1573 EXTERN int32_t nextvoxid;
1574 EXTERN intptr_t voxoff[MAXVOXELS][MAXVOXMIPS]; // used in KenBuild
1575 EXTERN int8_t voxreserve[(MAXVOXELS+7)>>3];
1576 EXTERN int8_t voxrotate[(MAXVOXELS+7)>>3];
1577
1578 #ifdef USE_OPENGL
1579 // TODO: dynamically allocate this
1580
1581 typedef struct { vec3f_t add; int16_t angadd, flags, fov; } hudtyp;
1582
1583 typedef struct
1584 {
1585 // maps build tiles to particular animation frames of a model
1586 int16_t modelid;
1587 int16_t framenum; // calculate the number from the name when declaring
1588 int16_t nexttile;
1589 uint16_t smoothduration;
1590 hudtyp *hudmem[2];
1591 int8_t skinnum;
1592 char pal;
1593 } tile2model_t;
1594
1595 # define EXTRATILES (MAXTILES/8)
1596
1597 EXTERN int32_t mdinited;
1598 EXTERN tile2model_t tile2model[MAXTILES+EXTRATILES];
1599
md_tilehasmodel(int32_t const tilenume,int32_t const pal)1600 static FORCE_INLINE int32_t md_tilehasmodel(int32_t const tilenume, int32_t const pal)
1601 {
1602 return mdinited ? tile2model[Ptile2tile(tilenume,pal)].modelid : -1;
1603 }
1604 #endif // defined USE_OPENGL
1605
tilehasmodelorvoxel(int const tilenume,int pal)1606 static FORCE_INLINE int tilehasmodelorvoxel(int const tilenume, int pal)
1607 {
1608 UNREFERENCED_PARAMETER(pal);
1609 return
1610 #ifdef USE_OPENGL
1611 (videoGetRenderMode() >= REND_POLYMOST && mdinited && usemodels && tile2model[Ptile2tile(tilenume, pal)].modelid != -1) ||
1612 #endif
1613 (videoGetRenderMode() <= REND_POLYMOST && usevoxels && tiletovox[tilenume] != -1);
1614 }
1615
1616 int32_t md_defineframe(int32_t modelid, const char *framename, int32_t tilenume,
1617 int32_t skinnum, float smoothduration, int32_t pal);
1618 int32_t md_defineanimation(int32_t modelid, const char *framestart, const char *frameend,
1619 int32_t fps, int32_t flags);
1620 int32_t md_defineskin(int32_t modelid, const char *skinfn, int32_t palnum, int32_t skinnum,
1621 int32_t surfnum, float param, float specpower, float specfactor, int32_t flags);
1622 int32_t md_definehud (int32_t modelid, int32_t tilex, vec3f_t add,
1623 int32_t angadd, int32_t flags, int32_t fov);
1624 int32_t md_undefinetile(int32_t tile);
1625 int32_t md_undefinemodel(int32_t modelid);
1626
1627 int32_t loaddefinitionsfile(const char *fn);
1628
1629 // if loadboard() fails with -2 return, try loadoldboard(). if it fails with
1630 // -2, board is dodgy
1631 int32_t engineLoadBoardV5V6(const char *filename, char fromwhere, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum);
1632
1633 #ifdef __cplusplus
1634 }
1635 #endif
1636
1637 #include "hash.h"
1638
1639 #ifdef POLYMER
1640 # include "polymer.h"
1641 #endif
1642 #ifdef USE_OPENGL
1643 # include "polymost.h"
1644 #endif
1645
1646 #ifdef __cplusplus
1647 extern "C" {
1648 #endif
1649
renderDisableFog(void)1650 static FORCE_INLINE void renderDisableFog(void)
1651 {
1652 #ifdef USE_OPENGL
1653 if (videoGetRenderMode() >= REND_POLYMOST)
1654 {
1655 polymost_setFogEnabled(false);
1656 }
1657 #endif
1658 }
1659
renderEnableFog(void)1660 static FORCE_INLINE void renderEnableFog(void)
1661 {
1662 #ifdef USE_OPENGL
1663 if (videoGetRenderMode() >= REND_POLYMOST && !nofog)
1664 polymost_setFogEnabled(true);
1665 #endif
1666 }
1667
inside_p(int32_t const x,int32_t const y,int const sectnum)1668 static FORCE_INLINE CONSTEXPR int inside_p(int32_t const x, int32_t const y, int const sectnum) { return (sectnum >= 0 && inside(x, y, sectnum) == 1); }
1669
1670 #define SET_AND_RETURN(Lval, Rval) \
1671 do \
1672 { \
1673 (Lval) = (Rval); \
1674 return; \
1675 } while (0)
1676
compat_maybe_truncate_to_int32(int64_t val)1677 static FORCE_INLINE int64_t compat_maybe_truncate_to_int32(int64_t val)
1678 {
1679 return enginecompatibilitymode != ENGINE_EDUKE32 ? (int32_t)val : val;
1680 }
1681
1682 static inline int32_t clipmove_old(int32_t *x, int32_t *y, int32_t *z, int16_t *sectnum, int32_t xvect, int32_t yvect, int32_t walldist,
1683 int32_t ceildist, int32_t flordist, uint32_t cliptype) ATTRIBUTE((nonnull(1,2,3,4)));
1684
clipmove_old(int32_t * x,int32_t * y,int32_t * z,int16_t * sectnum,int32_t xvect,int32_t yvect,int32_t walldist,int32_t ceildist,int32_t flordist,uint32_t cliptype)1685 static inline int32_t clipmove_old(int32_t *x, int32_t *y, int32_t *z, int16_t *sectnum, int32_t xvect, int32_t yvect, int32_t walldist,
1686 int32_t ceildist, int32_t flordist, uint32_t cliptype)
1687 {
1688 vec3_t vector = { *x, *y, *z };
1689
1690 int32_t result = clipmove(&vector, sectnum, xvect, yvect, walldist, ceildist, flordist, cliptype);
1691
1692 *x = vector.x;
1693 *y = vector.y;
1694 *z = vector.z;
1695
1696 return result;
1697 }
1698
1699 static inline int32_t pushmove_old(int32_t *x, int32_t *y, int32_t *z, int16_t *sectnum, int32_t walldist,
1700 int32_t ceildist, int32_t flordist, uint32_t cliptype) ATTRIBUTE((nonnull(1,2,3,4)));
1701
pushmove_old(int32_t * x,int32_t * y,int32_t * z,int16_t * sectnum,int32_t walldist,int32_t ceildist,int32_t flordist,uint32_t cliptype)1702 static inline int32_t pushmove_old(int32_t *x, int32_t *y, int32_t *z, int16_t *sectnum, int32_t walldist,
1703 int32_t ceildist, int32_t flordist, uint32_t cliptype)
1704 {
1705 vec3_t vector = { *x, *y, *z };
1706
1707 int32_t result = pushmove(&vector, sectnum, walldist, ceildist, flordist, cliptype);
1708
1709 *x = vector.x;
1710 *y = vector.y;
1711 *z = vector.z;
1712
1713 return result;
1714 }
1715
1716 static inline void getzrange_old(int32_t x, int32_t y, int32_t z, int16_t sectnum, int32_t *ceilz, int32_t *ceilhit, int32_t *florz,
1717 int32_t *florhit, int32_t walldist, uint32_t cliptype) ATTRIBUTE((nonnull(5,6,7,8)));
1718
getzrange_old(int32_t x,int32_t y,int32_t z,int16_t sectnum,int32_t * ceilz,int32_t * ceilhit,int32_t * florz,int32_t * florhit,int32_t walldist,uint32_t cliptype)1719 static inline void getzrange_old(int32_t x, int32_t y, int32_t z, int16_t sectnum, int32_t *ceilz, int32_t *ceilhit, int32_t *florz,
1720 int32_t *florhit, int32_t walldist, uint32_t cliptype)
1721 {
1722 const vec3_t vector = { x, y, z };
1723 getzrange(&vector, sectnum, ceilz, ceilhit, florz, florhit, walldist, cliptype);
1724 }
1725
setspritez_old(int16_t spritenum,int32_t x,int32_t y,int32_t z)1726 static inline int32_t setspritez_old(int16_t spritenum, int32_t x, int32_t y, int32_t z)
1727 {
1728 const vec3_t vector = { x, y, z };
1729 return setspritez(spritenum, &vector);
1730 }
1731
1732 extern int32_t rintersect(int32_t x1, int32_t y1, int32_t z1,
1733 int32_t vx_, int32_t vy_, int32_t vz,
1734 int32_t x3, int32_t y3, int32_t x4, int32_t y4,
1735 int32_t *intx, int32_t *inty, int32_t *intz);
1736
1737 extern int32_t(*animateoffs_replace)(int const tilenum, int fakevar);
1738 extern void(*paletteLoadFromDisk_replace)(void);
1739 extern int32_t(*getpalookup_replace)(int32_t davis, int32_t dashade);
1740 extern void(*initspritelists_replace)(void);
1741 extern int32_t(*insertsprite_replace)(int16_t sectnum, int16_t statnum);
1742 extern int32_t(*deletesprite_replace)(int16_t spritenum);
1743 extern int32_t(*changespritesect_replace)(int16_t spritenum, int16_t newsectnum);
1744 extern int32_t(*changespritestat_replace)(int16_t spritenum, int16_t newstatnum);
1745 extern void(*loadvoxel_replace)(int32_t voxel);
1746 extern int32_t(*loadboard_replace)(const char *filename, char flags, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum);
1747 extern int32_t(*saveboard_replace)(const char *filename, const vec3_t *dapos, int16_t daang, int16_t dacursectnum);
1748 #ifdef USE_OPENGL
1749 extern void(*PolymostProcessVoxels_Callback)(void);
1750 #endif
1751
tspriteGetSlope(tspriteptr_t const tspr)1752 static inline int16_t tspriteGetSlope(tspriteptr_t const tspr)
1753 {
1754 if (!(tspr->clipdist & TSPR_FLAGS_SLOPE_SPRITE))
1755 return 0;
1756 return uint8_t(tspr->xoffset) + (uint8_t(tspr->yoffset) << 8);
1757 }
1758
spriteGetZOfSlope(uint16_t const spritenum,int32_t dax,int32_t day)1759 static inline int32_t spriteGetZOfSlope(uint16_t const spritenum, int32_t dax, int32_t day)
1760 {
1761 auto const spr = &sprite[spritenum];
1762 int16_t const heinum = spriteGetSlope(spritenum);
1763 if (heinum == 0)
1764 return spr->z;
1765
1766 int const j = dmulscale4(sintable[(spr->ang+1024)&2047], day-spr->y,
1767 -sintable[(spr->ang+512)&2047], dax-spr->x);
1768 return spr->z + mulscale18(heinum,j);
1769 }
1770
tspriteGetZOfSlope(tspriteptr_t const tspr,int32_t dax,int32_t day)1771 static inline int32_t tspriteGetZOfSlope(tspriteptr_t const tspr, int32_t dax, int32_t day)
1772 {
1773 int16_t const heinum = tspriteGetSlope(tspr);
1774 if (heinum == 0)
1775 return tspr->z;
1776
1777 int const j = dmulscale4(sintable[(tspr->ang+1024)&2047], day-tspr->y,
1778 -sintable[(tspr->ang+512)&2047], dax-tspr->x);
1779 return tspr->z + mulscale18(heinum,j);
1780 }
1781
tspriteGetZOfSlopeFloat(tspriteptr_t const tspr,float dax,float day)1782 static inline float tspriteGetZOfSlopeFloat(tspriteptr_t const tspr, float dax, float day)
1783 {
1784 int16_t const heinum = tspriteGetSlope(tspr);
1785 if (heinum == 0)
1786 return float(tspr->z);
1787
1788 float const f = sintable[(tspr->ang+1024)&2047] * (day-tspr->y) - sintable[(tspr->ang+512)&2047] * (dax-tspr->x);
1789 return float(tspr->z) + heinum * f * (1.f/4194304.f);
1790 }
1791
1792 #ifdef __cplusplus
1793 }
1794 #endif
1795
1796 #endif // build_h_
1797