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
8
9 #define ENGINE
10
11 #include "build.h"
12 #include "pragmas.h"
13 #include "cache1d.h"
14 #include "a.h"
15 #include "osd.h"
16 #include "crc32.h"
17
18 #include "baselayer.h"
19
20 #include "engine_priv.h"
21 #if USE_POLYMOST
22 # include "polymost_priv.h"
23 # if USE_OPENGL
24 # include "hightile_priv.h"
25 # include "polymosttex_priv.h"
26 # include "polymosttexcache.h"
27 # include "mdsprite_priv.h"
28 # endif
29 # ifdef _WIN32
30 # define WIN32_LEAN_AND_MEAN
31 # include <windows.h>
32 # endif
33 #endif
34
35 #include <math.h>
36 #include <assert.h>
37
kmalloc(bsize_t size)38 void *kmalloc(bsize_t size) { return(Bmalloc(size)); }
kfree(void * buffer)39 void kfree(void *buffer) { Bfree(buffer); }
40
loadvoxel(int voxindex)41 void loadvoxel(int voxindex) { voxindex=0; }
42 int tiletovox[MAXTILES];
43 int usevoxels = 1;
44 #define kloadvoxel loadvoxel
45
46 int novoxmips = 0;
47
48 //These variables need to be copied into BUILD
49 #define MAXXSIZ 256
50 #define MAXYSIZ 256
51 #define MAXZSIZ 255
52 #define MAXVOXMIPS 5
53 intptr_t voxoff[MAXVOXELS][MAXVOXMIPS];
54 unsigned char voxlock[MAXVOXELS][MAXVOXMIPS];
55 int voxscale[MAXVOXELS];
56
57 static int ggxinc[MAXXSIZ+1], ggyinc[MAXXSIZ+1];
58 static int lowrecip[1024], nytooclose, nytoofar;
59 static unsigned int distrecip[65536];
60
61 static int *lookups = NULL;
62 int dommxoverlay = 1, beforedrawrooms = 1;
63
64 static int oxdimen = -1, oviewingrange = -1, oxyaspect = -1;
65
66 int curbrightness = 0, gammabrightness = 0;
67 float curgamma = 1.0;
68
69 //Textured Map variables
70 static unsigned char globalpolytype;
71 static short *dotp1[MAXYDIM], *dotp2[MAXYDIM];
72
73 static unsigned char tempbuf[MAXWALLS];
74
75 int ebpbak, espbak;
76 #define SLOPALOOKUPSIZ (MAXXDIM<<1)
77 intptr_t slopalookup[SLOPALOOKUPSIZ];
78 #if USE_POLYMOST && USE_OPENGL
79 palette_t palookupfog[MAXPALOOKUPS];
80 #endif
81
82 int artversion, mapversion=7L; // JBF 20040211: default mapversion to 7
83 void *pic = NULL;
84 unsigned char picsiz[MAXTILES], tilefilenum[MAXTILES];
85 int lastageclock;
86 int tilefileoffs[MAXTILES];
87
88 int artsize = 0, cachesize = 0;
89 int editorgridextent = 131072;
90
91 static short radarang[1280], radarang2[MAXXDIM];
92 static unsigned short sqrtable[4096], shlookup[4096+256];
93 unsigned char pow2char[8] = {1,2,4,8,16,32,64,128};
94 int pow2long[32] =
95 {
96 1L,2L,4L,8L,
97 16L,32L,64L,128L,
98 256L,512L,1024L,2048L,
99 4096L,8192L,16384L,32768L,
100 65536L,131072L,262144L,524288L,
101 1048576L,2097152L,4194304L,8388608L,
102 16777216L,33554432L,67108864L,134217728L,
103 268435456L,536870912L,1073741824L,2147483647L
104 };
105 int reciptable[2048], fpuasm;
106
107 unsigned char britable[16][256];
108 extern unsigned char textfont[2048], smalltextfont[2048];
109
110 static char kensmessage[128];
111 char *engineerrstr = NULL;
112 static BFILE *logfile=NULL; // log filehandle
113
114
115 //unsigned int ratelimitlast[32], ratelimitn = 0, ratelimit = 60;
116
117 #if defined(__WATCOMC__) && USE_ASM
118
119 //
120 // Watcom Inline Assembly Routines
121 //
122
123 #pragma aux nsqrtasm =\
124 "test eax, 0xff000000",\
125 "mov ebx, eax",\
126 "jnz short over24",\
127 "shr ebx, 12",\
128 "mov cx, word ptr shlookup[ebx*2]",\
129 "jmp short under24",\
130 "over24: shr ebx, 24",\
131 "mov cx, word ptr shlookup[ebx*2+8192]",\
132 "under24: shr eax, cl",\
133 "mov cl, ch",\
134 "mov ax, word ptr sqrtable[eax*2]",\
135 "shr eax, cl",\
136 parm nomemory [eax]\
137 modify exact [eax ebx ecx]
138 unsigned int nsqrtasm(unsigned int);
139
140 #pragma aux msqrtasm =\
141 "mov eax, 0x40000000",\
142 "mov ebx, 0x20000000",\
143 "begit: cmp ecx, eax",\
144 "jl skip",\
145 "sub ecx, eax",\
146 "lea eax, [eax+ebx*4]",\
147 "skip: sub eax, ebx",\
148 "shr eax, 1",\
149 "shr ebx, 2",\
150 "jnz begit",\
151 "cmp ecx, eax",\
152 "sbb eax, -1",\
153 "shr eax, 1",\
154 parm nomemory [ecx]\
155 modify exact [eax ebx ecx]
156 int msqrtasm(unsigned int);
157
158 //0x007ff000 is (11<<13), 0x3f800000 is (127<<23)
159 #pragma aux krecipasm =\
160 "mov fpuasm, eax",\
161 "fild dword ptr fpuasm",\
162 "add eax, eax",\
163 "fstp dword ptr fpuasm",\
164 "sbb ebx, ebx",\
165 "mov eax, fpuasm",\
166 "mov ecx, eax",\
167 "and eax, 0x007ff000",\
168 "shr eax, 10",\
169 "sub ecx, 0x3f800000",\
170 "shr ecx, 23",\
171 "mov eax, dword ptr reciptable[eax]",\
172 "sar eax, cl",\
173 "xor eax, ebx",\
174 parm [eax]\
175 modify exact [eax ebx ecx]
176 int krecipasm(int);
177
178 #pragma aux getclipmask =\
179 "sar eax, 31",\
180 "add ebx, ebx",\
181 "adc eax, eax",\
182 "add ecx, ecx",\
183 "adc eax, eax",\
184 "add edx, edx",\
185 "adc eax, eax",\
186 "mov ebx, eax",\
187 "shl ebx, 4",\
188 "or al, 0xf0",\
189 "xor eax, ebx",\
190 parm [eax][ebx][ecx][edx]\
191 modify exact [eax ebx ecx edx]
192 int getclipmask(int,int,int,int);
193
194 #elif defined(_MSC_VER) && defined(_M_IX86) && USE_ASM // __WATCOMC__
195
196 //
197 // Microsoft C Inline Assembly Routines
198 //
199
nsqrtasm(int a)200 static inline int nsqrtasm(int a)
201 {
202 _asm {
203 push ebx
204 mov eax, a
205 test eax, 0xff000000
206 mov ebx, eax
207 jnz short over24
208 shr ebx, 12
209 mov cx, word ptr shlookup[ebx*2]
210 jmp short under24
211 over24:
212 shr ebx, 24
213 mov cx, word ptr shlookup[ebx*2+8192]
214 under24:
215 shr eax, cl
216 mov cl, ch
217 mov ax, word ptr sqrtable[eax*2]
218 shr eax, cl
219 pop ebx
220 }
221 }
222
msqrtasm(int c)223 static inline int msqrtasm(int c)
224 {
225 _asm {
226 push ebx
227 mov ecx, c
228 mov eax, 0x40000000
229 mov ebx, 0x20000000
230 begit:
231 cmp ecx, eax
232 jl skip
233 sub ecx, eax
234 lea eax, [eax+ebx*4]
235 skip:
236 sub eax, ebx
237 shr eax, 1
238 shr ebx, 2
239 jnz begit
240 cmp ecx, eax
241 sbb eax, -1
242 shr eax, 1
243 pop ebx
244 }
245 }
246
247 //0x007ff000 is (11<<13), 0x3f800000 is (127<<23)
krecipasm(int a)248 static inline int krecipasm(int a)
249 {
250 _asm {
251 push ebx
252 mov eax, a
253 mov fpuasm, eax
254 fild dword ptr fpuasm
255 add eax, eax
256 fstp dword ptr fpuasm
257 sbb ebx, ebx
258 mov eax, fpuasm
259 mov ecx, eax
260 and eax, 0x007ff000
261 shr eax, 10
262 sub ecx, 0x3f800000
263 shr ecx, 23
264 mov eax, dword ptr reciptable[eax]
265 sar eax, cl
266 xor eax, ebx
267 pop ebx
268 }
269 }
270
getclipmask(int a,int b,int c,int d)271 static inline int getclipmask(int a, int b, int c, int d)
272 {
273 _asm {
274 push ebx
275 mov eax, a
276 mov ebx, b
277 mov ecx, c
278 mov edx, d
279 sar eax, 31
280 add ebx, ebx
281 adc eax, eax
282 add ecx, ecx
283 adc eax, eax
284 add edx, edx
285 adc eax, eax
286 mov ebx, eax
287 shl ebx, 4
288 or al, 0xf0
289 xor eax, ebx
290 pop ebx
291 }
292 }
293
294 #elif defined(__GNUC__) && defined(__i386__) && USE_ASM // _MSC_VER
295
296 //
297 // GCC "Inline" Assembly Routines
298 //
299
300 #define nsqrtasm(a) \
301 ({ int __r, __a=(a); \
302 __asm__ __volatile__ ( \
303 "testl $0xff000000, %%eax\n\t" \
304 "movl %%eax, %%ebx\n\t" \
305 "jnz 0f\n\t" \
306 "shrl $12, %%ebx\n\t" \
307 "movw %[shlookup](,%%ebx,2), %%cx\n\t" \
308 "jmp 1f\n\t" \
309 "0:\n\t" \
310 "shrl $24, %%ebx\n\t" \
311 "movw (%[shlookup]+8192)(,%%ebx,2), %%cx\n\t" \
312 "1:\n\t" \
313 "shrl %%cl, %%eax\n\t" \
314 "movb %%ch, %%cl\n\t" \
315 "movw %[sqrtable](,%%eax,2), %%ax\n\t" \
316 "shrl %%cl, %%eax" \
317 : "=a" (__r) \
318 : "a" (__a), [shlookup] "m" (shlookup[0]), [sqrtable] "m" (sqrtable[0]) \
319 : "ebx", "ecx", "cc"); \
320 __r; })
321
322 // edx is blown by this code somehow?!
323 #define msqrtasm(c) \
324 ({ int __r, __c=(c); \
325 __asm__ __volatile__ ( \
326 "movl $0x40000000, %%eax\n\t" \
327 "movl $0x20000000, %%ebx\n\t" \
328 "0:\n\t" \
329 "cmpl %%eax, %%ecx\n\t" \
330 "jl 1f\n\t" \
331 "subl %%eax, %%ecx\n\t" \
332 "leal (%%eax,%%ebx,4), %%eax\n\t" \
333 "1:\n\t" \
334 "subl %%ebx, %%eax\n\t" \
335 "shrl $1, %%eax\n\t" \
336 "shrl $2, %%ebx\n\t" \
337 "jnz 0b\n\t" \
338 "cmpl %%eax, %%ecx\n\t" \
339 "sbbl $-1, %%eax\n\t" \
340 "shrl $1, %%eax" \
341 : "=a" (__r) : "c" (__c) : "edx","ebx", "cc"); \
342 __r; })
343
344 #define krecipasm(a) \
345 ({ int __a=(a); \
346 __asm__ __volatile__ ( \
347 "movl %%eax, (%[fpuasm]); fildl (%[fpuasm]); " \
348 "addl %%eax, %%eax; fstps (%[fpuasm]); sbbl %%ebx, %%ebx; " \
349 "movl (%[fpuasm]), %%eax; movl %%eax, %%ecx; " \
350 "andl $0x007ff000, %%eax; shrl $10, %%eax; subl $0x3f800000, %%ecx; " \
351 "shrl $23, %%ecx; movl %[reciptable](%%eax), %%eax; " \
352 "sarl %%cl, %%eax; xorl %%ebx, %%eax" \
353 : "=a" (__a) \
354 : "a" (__a), [fpuasm] "m" (fpuasm), [reciptable] "m" (reciptable[0]) \
355 : "ebx", "ecx", "memory", "cc"); \
356 __a; })
357
358 #define getclipmask(a,b,c,d) \
359 ({ int __a=(a), __b=(b), __c=(c), __d=(d); \
360 __asm__ __volatile__ ("sarl $31, %%eax; addl %%ebx, %%ebx; adcl %%eax, %%eax; " \
361 "addl %%ecx, %%ecx; adcl %%eax, %%eax; addl %%edx, %%edx; " \
362 "adcl %%eax, %%eax; movl %%eax, %%ebx; shl $4, %%ebx; " \
363 "orb $0xf0, %%al; xorl %%ebx, %%eax" \
364 : "=a" (__a), "=b" (__b), "=c" (__c), "=d" (__d) \
365 : "a" (__a), "b" (__b), "c" (__c), "d" (__d) : "cc"); \
366 __a; })
367
368 #else // __GNUC__ && __i386__
369
nsqrtasm(unsigned int a)370 static inline unsigned int nsqrtasm(unsigned int a)
371 { // JBF 20030901: This was a damn lot simpler to reverse engineer than
372 // msqrtasm was. Really, it was just like simplifying an algebra equation.
373 unsigned short c;
374
375 if (a & 0xff000000) { // test eax, 0xff000000 / jnz short over24
376 c = shlookup[(a >> 24) + 4096]; // mov ebx, eax
377 // over24: shr ebx, 24
378 // mov cx, word ptr shlookup[ebx*2+8192]
379 } else {
380 c = shlookup[a >> 12]; // mov ebx, eax
381 // shr ebx, 12
382 // mov cx, word ptr shlookup[ebx*2]
383 // jmp short under24
384 }
385 a >>= c&0xff; // under24: shr eax, cl
386 a = (a&0xffff0000)|(sqrtable[a]); // mov ax, word ptr sqrtable[eax*2]
387 a >>= ((c&0xff00) >> 8); // mov cl, ch
388 // shr eax, cl
389 return a;
390 }
391
msqrtasm(unsigned int c)392 static inline int msqrtasm(unsigned int c)
393 {
394 unsigned int a,b;
395
396 a = 0x40000000l; // mov eax, 0x40000000
397 b = 0x20000000l; // mov ebx, 0x20000000
398 do { // begit:
399 if (c >= a) { // cmp ecx, eax / jl skip
400 c -= a; // sub ecx, eax
401 a += b*4; // lea eax, [eax+ebx*4]
402 } // skip:
403 a -= b; // sub eax, ebx
404 a >>= 1; // shr eax, 1
405 b >>= 2; // shr ebx, 2
406 } while (b); // jnz begit
407 if (c >= a) // cmp ecx, eax
408 a++; // sbb eax, -1
409 a >>= 1; // shr eax, 1
410 return a;
411 }
412
krecipasm(int i)413 static inline int krecipasm(int i)
414 { // Ken did this
415 float f = (float)i; i = *(int *)&f;
416 return((reciptable[(i>>12)&2047]>>(((i-0x3f800000)>>23)&31))^(i>>31));
417 }
418
419
getclipmask(int a,int b,int c,int d)420 static inline int getclipmask(int a, int b, int c, int d)
421 { // Ken did this
422 d = ((a<0)*8) + ((b<0)*4) + ((c<0)*2) + (d<0);
423 return(((d<<4)^0xf0)|d);
424 }
425
426 #endif
427
428
429 int xb1[MAXWALLSB];
430 static int yb1[MAXWALLSB], xb2[MAXWALLSB], yb2[MAXWALLSB];
431 int rx1[MAXWALLSB], ry1[MAXWALLSB];
432 static int rx2[MAXWALLSB], ry2[MAXWALLSB];
433 short p2[MAXWALLSB];
434 short thesector[MAXWALLSB], thewall[MAXWALLSB];
435
436 short bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB];
437
438 static short smost[MAXYSAVES], smostcnt;
439 static short smoststart[MAXWALLSB];
440 static unsigned char smostwalltype[MAXWALLSB];
441 static int smostwall[MAXWALLSB], smostwallcnt = -1L;
442
443 short maskwall[MAXWALLSB], maskwallcnt;
444 static int spritesx[MAXSPRITESONSCREEN];
445 static int spritesy[MAXSPRITESONSCREEN+1];
446 static int spritesz[MAXSPRITESONSCREEN];
447 spritetype *tspriteptr[MAXSPRITESONSCREEN];
448
449 short umost[MAXXDIM], dmost[MAXXDIM];
450 static short bakumost[MAXXDIM], bakdmost[MAXXDIM];
451 short uplc[MAXXDIM], dplc[MAXXDIM];
452 static short uwall[MAXXDIM], dwall[MAXXDIM];
453 static int swplc[MAXXDIM], lplc[MAXXDIM];
454 static int swall[MAXXDIM], lwall[MAXXDIM+4];
455 int xdimen = -1, xdimenrecip, halfxdimen, xdimenscale, xdimscale;
456 int wx1, wy1, wx2, wy2, ydimen, ydimenscale;
457 intptr_t frameoffset;
458
459 static int nrx1[8], nry1[8], nrx2[8], nry2[8]; // JBF 20031206: Thanks Ken
460
461 static int rxi[8], ryi[8], rzi[8], rxi2[8], ryi2[8], rzi2[8];
462 static int xsi[8], ysi[8], *horizlookup=0, *horizlookup2=0, horizycent;
463
464 int globalposx, globalposy, globalposz, globalhoriz;
465 short globalang, globalcursectnum;
466 int globalpal, cosglobalang, singlobalang;
467 int cosviewingrangeglobalang, sinviewingrangeglobalang;
468 unsigned char *globalpalwritten;
469 int globaluclip, globaldclip, globvis;
470 int globalvisibility, globalhisibility, globalpisibility, globalcisibility;
471 unsigned char globparaceilclip, globparaflorclip;
472
473 int viewingrangerecip;
474
475 int asm1, asm2, asm4;
476 intptr_t asm3;
477 int vplce[4], vince[4];
478 intptr_t palookupoffse[4], bufplce[4];
479 unsigned char globalxshift, globalyshift;
480 int globalxpanning, globalypanning, globalshade;
481 short globalpicnum, globalshiftval;
482 int globalzd, globalyscale, globalorientation;
483 intptr_t globalbufplc;
484 int globalx1, globaly1, globalx2, globaly2, globalx3, globaly3, globalzx;
485 int globalx, globaly, globalz;
486
487 short sectorborder[256], sectorbordercnt;
488 int pageoffset, ydim16, qsetmode = 0;
489 int startposx, startposy, startposz;
490 short startang, startsectnum;
491 short pointhighlight, linehighlight, highlightcnt;
492 int lastx[MAXYDIM];
493 unsigned char *transluc = NULL;
494
495 int halfxdim16, midydim16;
496
497 #define FASTPALGRIDSIZ 8
498 static int rdist[129], gdist[129], bdist[129];
499 static unsigned char colhere[((FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2))>>3];
500 static unsigned char colhead[(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)];
501 static int colnext[256];
502 static unsigned char coldist[8] = {0,1,2,3,4,3,2,1};
503 static int colscan[27];
504
505 static short clipnum, hitwalls[4];
506 int hitscangoalx = (1<<29)-1, hitscangoaly = (1<<29)-1;
507 #if USE_POLYMOST
508 int hitallsprites = 0;
509 #endif
510
511 typedef struct { int x1, y1, x2, y2; } linetype;
512 static linetype clipit[MAXCLIPNUM];
513 static short clipsectorlist[MAXCLIPNUM], clipsectnum;
514 static short clipobjectval[MAXCLIPNUM];
515
516 typedef struct
517 {
518 int sx, sy, z;
519 short a, picnum;
520 signed char dashade;
521 unsigned char dapalnum, dastat, pagesleft;
522 int cx1, cy1, cx2, cy2;
523 int uniqid; //JF extension
524 } permfifotype;
525 static permfifotype permfifo[MAXPERMS];
526 static int permhead = 0, permtail = 0;
527
528 short numscans, numhits, numbunches;
529
530 static short capturecount = 0;
531 static char capturename[20], captureatnextpage = 0;
532 static int screencapture_pcx(char *filename, char inverseit);
533 static int screencapture_tga(char *filename, char inverseit);
534
535 unsigned char vgapal16[4*256] =
536 {
537 00,00,00,00, 42,00,00,00, 00,42,00,00, 42,42,00,00, 00,00,42,00,
538 42,00,42,00, 00,21,42,00, 42,42,42,00, 21,21,21,00, 63,21,21,00,
539 21,63,21,00, 63,63,21,00, 21,21,63,00, 63,21,63,00, 21,63,63,00,
540 63,63,63,00
541 };
542
543 short editstatus = 0;
544 short searchit;
545 int searchx = -1, searchy; //search input
546 short searchsector, searchwall, searchstat; //search output
547 double msens = 1.0;
548
549 static char artfilename[20];
550 static int numtilefiles, artfil = -1, artfilnum, artfilplc;
551
552 char inpreparemirror = 0;
553 static int mirrorsx1, mirrorsy1, mirrorsx2, mirrorsy2;
554
555 static int setviewcnt = 0; // interface layers use this now
556 static intptr_t bakframeplace[4];
557 static int bakxsiz[4], bakysiz[4];
558 static int bakwindowx1[4], bakwindowy1[4];
559 static int bakwindowx2[4], bakwindowy2[4];
560 #if USE_POLYMOST
561 static int bakrendmode,baktile;
562 #endif
563
564 int totalclocklock;
565
566 palette_t curpalette[256]; // the current palette, unadjusted for brightness or tint
567 palette_t curpalettefaded[256]; // the current palette, adjusted for brightness and tint (ie. what gets sent to the card)
568 palette_t palfadergb = { 0,0,0,0 };
569 unsigned char palfadedelta = 0;
570
571
572
573 //
574 // Internal Engine Functions
575 //
576 //int cacheresets = 0,cacheinvalidates = 0;
577
578 //
579 // getpalookup (internal)
580 //
getpalookup(int davis,int dashade)581 static inline int getpalookup(int davis, int dashade)
582 {
583 return(min(max(dashade+(davis>>8),0),numpalookups-1));
584 }
585
586
587 //
588 // scansector (internal)
589 //
scansector(short sectnum)590 static void scansector(short sectnum)
591 {
592 walltype *wal, *wal2;
593 spritetype *spr;
594 int xs, ys, x1, y1, x2, y2, xp1, yp1, xp2=0, yp2=0, templong;
595 short z, zz, startwall, endwall, numscansbefore, scanfirst, bunchfrst;
596 short nextsectnum;
597
598 if (sectnum < 0) return;
599
600 if (automapping) show2dsector[sectnum>>3] |= pow2char[sectnum&7];
601
602 sectorborder[0] = sectnum, sectorbordercnt = 1;
603 do
604 {
605 sectnum = sectorborder[--sectorbordercnt];
606
607 for(z=headspritesect[sectnum];z>=0;z=nextspritesect[z])
608 {
609 spr = &sprite[z];
610 if ((((spr->cstat&0x8000) == 0) || (showinvisibility)) &&
611 (spr->xrepeat > 0) && (spr->yrepeat > 0) &&
612 (spritesortcnt < MAXSPRITESONSCREEN))
613 {
614 xs = spr->x-globalposx; ys = spr->y-globalposy;
615 if ((spr->cstat&48) || (xs*cosglobalang+ys*singlobalang > 0))
616 {
617 copybufbyte(spr,&tsprite[spritesortcnt],sizeof(spritetype));
618 tsprite[spritesortcnt++].owner = z;
619 }
620 }
621 }
622
623 gotsector[sectnum>>3] |= pow2char[sectnum&7];
624
625 bunchfrst = numbunches;
626 numscansbefore = numscans;
627
628 startwall = sector[sectnum].wallptr;
629 endwall = startwall + sector[sectnum].wallnum;
630 scanfirst = numscans;
631 for(z=startwall,wal=&wall[z];z<endwall;z++,wal++)
632 {
633 nextsectnum = wal->nextsector;
634
635 wal2 = &wall[wal->point2];
636 x1 = wal->x-globalposx; y1 = wal->y-globalposy;
637 x2 = wal2->x-globalposx; y2 = wal2->y-globalposy;
638
639 if ((nextsectnum >= 0) && ((wal->cstat&32) == 0))
640 if ((gotsector[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0)
641 {
642 templong = x1*y2-x2*y1;
643 if (((unsigned)templong+262144) < 524288)
644 if (mulscale5(templong,templong) <= (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
645 sectorborder[sectorbordercnt++] = nextsectnum;
646 }
647
648 if ((z == startwall) || (wall[z-1].point2 != z))
649 {
650 xp1 = dmulscale6(y1,cosglobalang,-x1,singlobalang);
651 yp1 = dmulscale6(x1,cosviewingrangeglobalang,y1,sinviewingrangeglobalang);
652 }
653 else
654 {
655 xp1 = xp2;
656 yp1 = yp2;
657 }
658 xp2 = dmulscale6(y2,cosglobalang,-x2,singlobalang);
659 yp2 = dmulscale6(x2,cosviewingrangeglobalang,y2,sinviewingrangeglobalang);
660 if ((yp1 < 256) && (yp2 < 256)) goto skipitaddwall;
661
662 //If wall's NOT facing you
663 if (dmulscale32(xp1,yp2,-xp2,yp1) >= 0) goto skipitaddwall;
664
665 if (xp1 >= -yp1)
666 {
667 if ((xp1 > yp1) || (yp1 == 0)) goto skipitaddwall;
668 xb1[numscans] = halfxdimen + scale(xp1,halfxdimen,yp1);
669 if (xp1 >= 0) xb1[numscans]++; //Fix for SIGNED divide
670 if (xb1[numscans] >= xdimen) xb1[numscans] = xdimen-1;
671 yb1[numscans] = yp1;
672 }
673 else
674 {
675 if (xp2 < -yp2) goto skipitaddwall;
676 xb1[numscans] = 0;
677 templong = yp1-yp2+xp1-xp2;
678 if (templong == 0) goto skipitaddwall;
679 yb1[numscans] = yp1 + scale(yp2-yp1,xp1+yp1,templong);
680 }
681 if (yb1[numscans] < 256) goto skipitaddwall;
682
683 if (xp2 <= yp2)
684 {
685 if ((xp2 < -yp2) || (yp2 == 0)) goto skipitaddwall;
686 xb2[numscans] = halfxdimen + scale(xp2,halfxdimen,yp2) - 1;
687 if (xp2 >= 0) xb2[numscans]++; //Fix for SIGNED divide
688 if (xb2[numscans] >= xdimen) xb2[numscans] = xdimen-1;
689 yb2[numscans] = yp2;
690 }
691 else
692 {
693 if (xp1 > yp1) goto skipitaddwall;
694 xb2[numscans] = xdimen-1;
695 templong = xp2-xp1+yp1-yp2;
696 if (templong == 0) goto skipitaddwall;
697 yb2[numscans] = yp1 + scale(yp2-yp1,yp1-xp1,templong);
698 }
699 if ((yb2[numscans] < 256) || (xb1[numscans] > xb2[numscans])) goto skipitaddwall;
700
701 //Made it all the way!
702 thesector[numscans] = sectnum; thewall[numscans] = z;
703 rx1[numscans] = xp1; ry1[numscans] = yp1;
704 rx2[numscans] = xp2; ry2[numscans] = yp2;
705 p2[numscans] = numscans+1;
706 numscans++;
707 skipitaddwall:
708
709 if ((wall[z].point2 < z) && (scanfirst < numscans))
710 p2[numscans-1] = scanfirst, scanfirst = numscans;
711 }
712
713 for(z=numscansbefore;z<numscans;z++)
714 if ((wall[thewall[z]].point2 != thewall[p2[z]]) || (xb2[z] >= xb1[p2[z]]))
715 bunchfirst[numbunches++] = p2[z], p2[z] = -1;
716
717 for(z=bunchfrst;z<numbunches;z++)
718 {
719 for(zz=bunchfirst[z];p2[zz]>=0;zz=p2[zz]);
720 bunchlast[z] = zz;
721 }
722 } while (sectorbordercnt > 0);
723 }
724
725
726 //
727 // maskwallscan (internal)
728 //
maskwallscan(int x1,int x2,short * uwal,short * dwal,int * swal,int * lwal)729 static void maskwallscan(int x1, int x2, short *uwal, short *dwal, int *swal, int *lwal)
730 {
731 int x, startx, xnice, ynice;
732 intptr_t i, fpalookup, p;
733 int y1ve[4], y2ve[4], u4, d4, dax, z, tsizx, tsizy;
734 char bad;
735
736 tsizx = tilesizx[globalpicnum];
737 tsizy = tilesizy[globalpicnum];
738 setgotpic(globalpicnum);
739 if ((tsizx <= 0) || (tsizy <= 0)) return;
740 if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen)) return;
741 if ((dwal[x1] < 0) && (dwal[x2] < 0)) return;
742
743 if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
744
745 startx = x1;
746
747 xnice = (pow2long[picsiz[globalpicnum]&15] == tsizx);
748 if (xnice) tsizx = (tsizx-1);
749 ynice = (pow2long[picsiz[globalpicnum]>>4] == tsizy);
750 if (ynice) tsizy = (picsiz[globalpicnum]>>4);
751
752 fpalookup = (intptr_t)palookup[globalpal];
753
754 setupmvlineasm(globalshiftval);
755
756 #ifndef ENGINE_USING_A_C
757
758 x = startx;
759 while ((startumost[x+windowx1] > startdmost[x+windowx1]) && (x <= x2)) x++;
760
761 p = x+frameoffset;
762
763 for(;(x<=x2)&&(p&3);x++,p++)
764 {
765 y1ve[0] = max(uwal[x],startumost[x+windowx1]-windowy1);
766 y2ve[0] = min(dwal[x],startdmost[x+windowx1]-windowy1);
767 if (y2ve[0] <= y1ve[0]) continue;
768
769 palookupoffse[0] = fpalookup+(getpalookup((int)mulscale16(swal[x],globvis),globalshade)<<8);
770
771 bufplce[0] = lwal[x] + globalxpanning;
772 if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
773 if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
774
775 vince[0] = swal[x]*globalyscale;
776 vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
777
778 mvlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],(void *)(bufplce[0]+waloff[globalpicnum]),(void *)(p+ylookup[y1ve[0]]));
779 }
780 for(;x<=x2-3;x+=4,p+=4)
781 {
782 bad = 0;
783 for(z=3,dax=x+3;z>=0;z--,dax--)
784 {
785 y1ve[z] = max(uwal[dax],startumost[dax+windowx1]-windowy1);
786 y2ve[z] = min(dwal[dax],startdmost[dax+windowx1]-windowy1)-1;
787 if (y2ve[z] < y1ve[z]) { bad += pow2char[z]; continue; }
788
789 i = lwal[dax] + globalxpanning;
790 if (i >= tsizx) { if (xnice == 0) i %= tsizx; else i &= tsizx; }
791 if (ynice == 0) i *= tsizy; else i <<= tsizy;
792 bufplce[z] = waloff[globalpicnum]+i;
793
794 vince[z] = swal[dax]*globalyscale;
795 vplce[z] = globalzd + vince[z]*(y1ve[z]-globalhoriz+1);
796 }
797 if (bad == 15) continue;
798
799 palookupoffse[0] = fpalookup+(getpalookup((int)mulscale16(swal[x],globvis),globalshade)<<8);
800 palookupoffse[3] = fpalookup+(getpalookup((int)mulscale16(swal[x+3],globvis),globalshade)<<8);
801
802 if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
803 {
804 palookupoffse[1] = palookupoffse[0];
805 palookupoffse[2] = palookupoffse[0];
806 }
807 else
808 {
809 palookupoffse[1] = fpalookup+(getpalookup((int)mulscale16(swal[x+1],globvis),globalshade)<<8);
810 palookupoffse[2] = fpalookup+(getpalookup((int)mulscale16(swal[x+2],globvis),globalshade)<<8);
811 }
812
813 u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
814 d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
815
816 if ((bad > 0) || (u4 >= d4))
817 {
818 if (!(bad&1)) mvlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],(void *)bufplce[0],(void *)(ylookup[y1ve[0]]+p+0));
819 if (!(bad&2)) mvlineasm1(vince[1],(void *)palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],(void *)bufplce[1],(void *)(ylookup[y1ve[1]]+p+1));
820 if (!(bad&4)) mvlineasm1(vince[2],(void *)palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],(void *)bufplce[2],(void *)(ylookup[y1ve[2]]+p+2));
821 if (!(bad&8)) mvlineasm1(vince[3],(void *)palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],(void *)bufplce[3],(void *)(ylookup[y1ve[3]]+p+3));
822 continue;
823 }
824
825 if (u4 > y1ve[0]) vplce[0] = mvlineasm1(vince[0],(void *)palookupoffse[0],u4-y1ve[0]-1,vplce[0],(void *)bufplce[0],(void *)(ylookup[y1ve[0]]+p+0));
826 if (u4 > y1ve[1]) vplce[1] = mvlineasm1(vince[1],(void *)palookupoffse[1],u4-y1ve[1]-1,vplce[1],(void *)bufplce[1],(void *)(ylookup[y1ve[1]]+p+1));
827 if (u4 > y1ve[2]) vplce[2] = mvlineasm1(vince[2],(void *)palookupoffse[2],u4-y1ve[2]-1,vplce[2],(void *)bufplce[2],(void *)(ylookup[y1ve[2]]+p+2));
828 if (u4 > y1ve[3]) vplce[3] = mvlineasm1(vince[3],(void *)palookupoffse[3],u4-y1ve[3]-1,vplce[3],(void *)bufplce[3],(void *)(ylookup[y1ve[3]]+p+3));
829
830 if (d4 >= u4) mvlineasm4(d4-u4+1,(void *)(ylookup[u4]+p));
831
832 i = p+ylookup[d4+1];
833 if (y2ve[0] > d4) mvlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-d4-1,vplce[0],(void *)bufplce[0],(void *)(i+0));
834 if (y2ve[1] > d4) mvlineasm1(vince[1],(void *)palookupoffse[1],y2ve[1]-d4-1,vplce[1],(void *)bufplce[1],(void *)(i+1));
835 if (y2ve[2] > d4) mvlineasm1(vince[2],(void *)palookupoffse[2],y2ve[2]-d4-1,vplce[2],(void *)bufplce[2],(void *)(i+2));
836 if (y2ve[3] > d4) mvlineasm1(vince[3],(void *)palookupoffse[3],y2ve[3]-d4-1,vplce[3],(void *)bufplce[3],(void *)(i+3));
837 }
838 for(;x<=x2;x++,p++)
839 {
840 y1ve[0] = max(uwal[x],startumost[x+windowx1]-windowy1);
841 y2ve[0] = min(dwal[x],startdmost[x+windowx1]-windowy1);
842 if (y2ve[0] <= y1ve[0]) continue;
843
844 palookupoffse[0] = fpalookup+(getpalookup((int)mulscale16(swal[x],globvis),globalshade)<<8);
845
846 bufplce[0] = lwal[x] + globalxpanning;
847 if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
848 if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
849
850 vince[0] = swal[x]*globalyscale;
851 vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
852
853 mvlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],(void *)(bufplce[0]+waloff[globalpicnum]),(void *)(p+ylookup[y1ve[0]]));
854 }
855
856 #else // ENGINE_USING_A_C
857
858 p = startx+frameoffset;
859 for(x=startx;x<=x2;x++,p++)
860 {
861 y1ve[0] = max(uwal[x],startumost[x+windowx1]-windowy1);
862 y2ve[0] = min(dwal[x],startdmost[x+windowx1]-windowy1);
863 if (y2ve[0] <= y1ve[0]) continue;
864
865 palookupoffse[0] = fpalookup+(getpalookup((int)mulscale16(swal[x],globvis),globalshade)<<8);
866
867 bufplce[0] = lwal[x] + globalxpanning;
868 if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
869 if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
870
871 vince[0] = swal[x]*globalyscale;
872 vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
873
874 mvlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],(void *)(bufplce[0]+waloff[globalpicnum]),(void *)(p+ylookup[y1ve[0]]));
875 }
876
877 #endif
878
879 faketimerhandler();
880 }
881
882
883 //
884 // wallfront (internal)
885 //
wallfront(int l1,int l2)886 int wallfront(int l1, int l2)
887 {
888 walltype *wal;
889 int x11, y11, x21, y21, x12, y12, x22, y22, dx, dy, t1, t2;
890
891 wal = &wall[thewall[l1]]; x11 = wal->x; y11 = wal->y;
892 wal = &wall[wal->point2]; x21 = wal->x; y21 = wal->y;
893 wal = &wall[thewall[l2]]; x12 = wal->x; y12 = wal->y;
894 wal = &wall[wal->point2]; x22 = wal->x; y22 = wal->y;
895
896 dx = x21-x11; dy = y21-y11;
897 t1 = dmulscale2(x12-x11,dy,-dx,y12-y11); //p1(l2) vs. l1
898 t2 = dmulscale2(x22-x11,dy,-dx,y22-y11); //p2(l2) vs. l1
899 if (t1 == 0) { t1 = t2; if (t1 == 0) return(-1); }
900 if (t2 == 0) t2 = t1;
901 if ((t1^t2) >= 0)
902 {
903 t2 = dmulscale2(globalposx-x11,dy,-dx,globalposy-y11); //pos vs. l1
904 return((t2^t1) >= 0);
905 }
906
907 dx = x22-x12; dy = y22-y12;
908 t1 = dmulscale2(x11-x12,dy,-dx,y11-y12); //p1(l1) vs. l2
909 t2 = dmulscale2(x21-x12,dy,-dx,y21-y12); //p2(l1) vs. l2
910 if (t1 == 0) { t1 = t2; if (t1 == 0) return(-1); }
911 if (t2 == 0) t2 = t1;
912 if ((t1^t2) >= 0)
913 {
914 t2 = dmulscale2(globalposx-x12,dy,-dx,globalposy-y12); //pos vs. l2
915 return((t2^t1) < 0);
916 }
917 return(-2);
918 }
919
920
921 //
922 // spritewallfront (internal)
923 //
spritewallfront(spritetype * s,int w)924 static int spritewallfront(spritetype *s, int w)
925 {
926 walltype *wal;
927 int x1, y1;
928
929 wal = &wall[w]; x1 = wal->x; y1 = wal->y;
930 wal = &wall[wal->point2];
931 return (dmulscale32(wal->x-x1,s->y-y1,-(s->x-x1),wal->y-y1) >= 0);
932 }
933
934
935 //
936 // bunchfront (internal)
937 //
bunchfront(int b1,int b2)938 static int bunchfront(int b1, int b2)
939 {
940 int x1b1, x2b1, x1b2, x2b2, b1f, b2f, i;
941
942 b1f = bunchfirst[b1]; x1b1 = xb1[b1f]; x2b2 = xb2[bunchlast[b2]]+1;
943 if (x1b1 >= x2b2) return(-1);
944 b2f = bunchfirst[b2]; x1b2 = xb1[b2f]; x2b1 = xb2[bunchlast[b1]]+1;
945 if (x1b2 >= x2b1) return(-1);
946
947 if (x1b1 >= x1b2)
948 {
949 for(i=b2f;xb2[i]<x1b1;i=p2[i]);
950 return(wallfront(b1f,i));
951 }
952 for(i=b1f;xb2[i]<x1b2;i=p2[i]);
953 return(wallfront(i,b2f));
954 }
955
956
957 //
958 // hline (internal)
959 //
hline(int xr,int yp)960 static void hline(int xr, int yp)
961 {
962 int xl, r, s;
963
964 xl = lastx[yp]; if (xl > xr) return;
965 r = horizlookup2[yp-globalhoriz+horizycent];
966 asm1 = globalx1*r;
967 asm2 = globaly2*r;
968 s = ((int)getpalookup((int)mulscale16(r,globvis),globalshade)<<8);
969
970 hlineasm4(xr-xl,0L,s,globalx2*r+globalypanning,globaly1*r+globalxpanning,
971 (void *)(ylookup[yp]+xr+frameoffset));
972 }
973
974
975 //
976 // slowhline (internal)
977 //
slowhline(int xr,int yp)978 static void slowhline(int xr, int yp)
979 {
980 int xl, r;
981
982 xl = lastx[yp]; if (xl > xr) return;
983 r = horizlookup2[yp-globalhoriz+horizycent];
984 asm1 = globalx1*r;
985 asm2 = globaly2*r;
986
987 asm3 = (intptr_t)globalpalwritten + ((int)getpalookup((int)mulscale16(r,globvis),globalshade)<<8);
988 if (!(globalorientation&256))
989 {
990 mhline((void *)globalbufplc,globaly1*r+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,
991 globalx2*r+globalypanning-asm2*(xr-xl),(void *)(ylookup[yp]+xl+frameoffset));
992 return;
993 }
994 thline((void *)globalbufplc,globaly1*r+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,
995 globalx2*r+globalypanning-asm2*(xr-xl),(void *)(ylookup[yp]+xl+frameoffset));
996 }
997
998
999 //
1000 // prepwall (internal)
1001 //
prepwall(int z,walltype * wal)1002 static void prepwall(int z, walltype *wal)
1003 {
1004 int i, l=0, ol=0, splc, sinc, x, topinc, top, botinc, bot, walxrepeat;
1005
1006 walxrepeat = (wal->xrepeat<<3);
1007
1008 //lwall calculation
1009 i = xb1[z]-halfxdimen;
1010 topinc = -(ry1[z]>>2);
1011 botinc = ((ry2[z]-ry1[z])>>8);
1012 top = mulscale5(rx1[z],xdimen)+mulscale2(topinc,i);
1013 bot = mulscale11(rx1[z]-rx2[z],xdimen)+mulscale2(botinc,i);
1014
1015 splc = mulscale19(ry1[z],xdimscale);
1016 sinc = mulscale16(ry2[z]-ry1[z],xdimscale);
1017
1018 x = xb1[z];
1019 if (bot != 0)
1020 {
1021 l = divscale12(top,bot);
1022 swall[x] = mulscale21(l,sinc)+splc;
1023 l *= walxrepeat;
1024 lwall[x] = (l>>18);
1025 }
1026 while (x+4 <= xb2[z])
1027 {
1028 top += topinc; bot += botinc;
1029 if (bot != 0)
1030 {
1031 ol = l; l = divscale12(top,bot);
1032 swall[x+4] = mulscale21(l,sinc)+splc;
1033 l *= walxrepeat;
1034 lwall[x+4] = (l>>18);
1035 }
1036 i = ((ol+l)>>1);
1037 lwall[x+2] = (i>>18);
1038 lwall[x+1] = ((ol+i)>>19);
1039 lwall[x+3] = ((l+i)>>19);
1040 swall[x+2] = ((swall[x]+swall[x+4])>>1);
1041 swall[x+1] = ((swall[x]+swall[x+2])>>1);
1042 swall[x+3] = ((swall[x+4]+swall[x+2])>>1);
1043 x += 4;
1044 }
1045 if (x+2 <= xb2[z])
1046 {
1047 top += (topinc>>1); bot += (botinc>>1);
1048 if (bot != 0)
1049 {
1050 ol = l; l = divscale12(top,bot);
1051 swall[x+2] = mulscale21(l,sinc)+splc;
1052 l *= walxrepeat;
1053 lwall[x+2] = (l>>18);
1054 }
1055 lwall[x+1] = ((l+ol)>>19);
1056 swall[x+1] = ((swall[x]+swall[x+2])>>1);
1057 x += 2;
1058 }
1059 if (x+1 <= xb2[z])
1060 {
1061 bot += (botinc>>2);
1062 if (bot != 0)
1063 {
1064 l = divscale12(top+(topinc>>2),bot);
1065 swall[x+1] = mulscale21(l,sinc)+splc;
1066 lwall[x+1] = mulscale18(l,walxrepeat);
1067 }
1068 }
1069
1070 if (lwall[xb1[z]] < 0) lwall[xb1[z]] = 0;
1071 if ((lwall[xb2[z]] >= walxrepeat) && (walxrepeat)) lwall[xb2[z]] = walxrepeat-1;
1072 if (wal->cstat&8)
1073 {
1074 walxrepeat--;
1075 for(x=xb1[z];x<=xb2[z];x++) lwall[x] = walxrepeat-lwall[x];
1076 }
1077 }
1078
1079
1080 //
1081 // animateoffs (internal)
1082 //
animateoffs(short tilenum,short fakevar)1083 int animateoffs(short tilenum, short fakevar)
1084 {
1085 int i, k, offs;
1086
1087 offs = 0;
1088 i = (totalclocklock>>((picanm[tilenum]>>24)&15));
1089 if ((picanm[tilenum]&63) > 0)
1090 {
1091 switch(picanm[tilenum]&192)
1092 {
1093 case 64:
1094 k = (i%((picanm[tilenum]&63)<<1));
1095 if (k < (picanm[tilenum]&63))
1096 offs = k;
1097 else
1098 offs = (((picanm[tilenum]&63)<<1)-k);
1099 break;
1100 case 128:
1101 offs = (i%((picanm[tilenum]&63)+1));
1102 break;
1103 case 192:
1104 offs = -(i%((picanm[tilenum]&63)+1));
1105 }
1106 }
1107 return(offs);
1108 }
1109
1110
1111 //
1112 // owallmost (internal)
1113 //
owallmost(short * mostbuf,int w,int z)1114 static int owallmost(short *mostbuf, int w, int z)
1115 {
1116 int bad, inty, xcross, y, yinc;
1117 int s1, s2, s3, s4, ix1, ix2, iy1, iy2, t;
1118 int i;
1119
1120 z <<= 7;
1121 s1 = mulscale20(globaluclip,yb1[w]); s2 = mulscale20(globaluclip,yb2[w]);
1122 s3 = mulscale20(globaldclip,yb1[w]); s4 = mulscale20(globaldclip,yb2[w]);
1123 bad = (z<s1)+((z<s2)<<1)+((z>s3)<<2)+((z>s4)<<3);
1124
1125 ix1 = xb1[w]; iy1 = yb1[w];
1126 ix2 = xb2[w]; iy2 = yb2[w];
1127
1128 if ((bad&3) == 3)
1129 {
1130 //clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),0L);
1131 for (i=ix1; i<=ix2; i++) mostbuf[i] = 0;
1132 return(bad);
1133 }
1134
1135 if ((bad&12) == 12)
1136 {
1137 //clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
1138 for (i=ix1; i<=ix2; i++) mostbuf[i] = ydimen;
1139 return(bad);
1140 }
1141
1142 if (bad&3)
1143 {
1144 t = divscale30(z-s1,s2-s1);
1145 inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
1146 xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty);
1147
1148 if ((bad&3) == 2)
1149 {
1150 if (xb1[w] <= xcross) { iy2 = inty; ix2 = xcross; }
1151 //clearbufbyte(&mostbuf[xcross+1],(xb2[w]-xcross)*sizeof(mostbuf[0]),0L);
1152 for (i=xcross+1; i<=xb2[w]; i++) mostbuf[i] = 0;
1153 }
1154 else
1155 {
1156 if (xcross <= xb2[w]) { iy1 = inty; ix1 = xcross; }
1157 //clearbufbyte(&mostbuf[xb1[w]],(xcross-xb1[w]+1)*sizeof(mostbuf[0]),0L);
1158 for (i=xb1[w]; i<=xcross; i++) mostbuf[i] = 0;
1159 }
1160 }
1161
1162 if (bad&12)
1163 {
1164 t = divscale30(z-s3,s4-s3);
1165 inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
1166 xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty);
1167
1168 if ((bad&12) == 8)
1169 {
1170 if (xb1[w] <= xcross) { iy2 = inty; ix2 = xcross; }
1171 //clearbufbyte(&mostbuf[xcross+1],(xb2[w]-xcross)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
1172 for (i=xcross+1; i<=xb2[w]; i++) mostbuf[i] = ydimen;
1173 }
1174 else
1175 {
1176 if (xcross <= xb2[w]) { iy1 = inty; ix1 = xcross; }
1177 //clearbufbyte(&mostbuf[xb1[w]],(xcross-xb1[w]+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
1178 for (i=xb1[w]; i<=xcross; i++) mostbuf[i] = ydimen;
1179 }
1180 }
1181
1182 y = (scale(z,xdimenscale,iy1)<<4);
1183 yinc = ((scale(z,xdimenscale,iy2)<<4)-y) / (ix2-ix1+1);
1184 qinterpolatedown16short(&mostbuf[ix1],ix2-ix1+1,y+(globalhoriz<<16),yinc);
1185
1186 if (mostbuf[ix1] < 0) mostbuf[ix1] = 0;
1187 if (mostbuf[ix1] > ydimen) mostbuf[ix1] = ydimen;
1188 if (mostbuf[ix2] < 0) mostbuf[ix2] = 0;
1189 if (mostbuf[ix2] > ydimen) mostbuf[ix2] = ydimen;
1190
1191 return(bad);
1192 }
1193
1194
1195 //
1196 // wallmost (internal)
1197 //
wallmost(short * mostbuf,int w,int sectnum,unsigned char dastat)1198 int wallmost(short *mostbuf, int w, int sectnum, unsigned char dastat)
1199 {
1200 int bad, i, j, t, y, z, inty, intz, xcross, yinc, fw;
1201 int x1, y1, z1, x2, y2, z2, xv, yv, dx, dy, dasqr, oz1, oz2;
1202 int s1, s2, s3, s4, ix1, ix2, iy1, iy2;
1203
1204 if (dastat == 0)
1205 {
1206 z = sector[sectnum].ceilingz-globalposz;
1207 if ((sector[sectnum].ceilingstat&2) == 0) return(owallmost(mostbuf,w,z));
1208 }
1209 else
1210 {
1211 z = sector[sectnum].floorz-globalposz;
1212 if ((sector[sectnum].floorstat&2) == 0) return(owallmost(mostbuf,w,z));
1213 }
1214
1215 i = thewall[w];
1216 if (i == sector[sectnum].wallptr) return(owallmost(mostbuf,w,z));
1217
1218 x1 = wall[i].x; x2 = wall[wall[i].point2].x-x1;
1219 y1 = wall[i].y; y2 = wall[wall[i].point2].y-y1;
1220
1221 fw = sector[sectnum].wallptr; i = wall[fw].point2;
1222 dx = wall[i].x-wall[fw].x; dy = wall[i].y-wall[fw].y;
1223 dasqr = krecipasm(nsqrtasm(dx*dx+dy*dy));
1224
1225 if (xb1[w] == 0)
1226 { xv = cosglobalang+sinviewingrangeglobalang; yv = singlobalang-cosviewingrangeglobalang; }
1227 else
1228 { xv = x1-globalposx; yv = y1-globalposy; }
1229 i = xv*(y1-globalposy)-yv*(x1-globalposx); j = yv*x2-xv*y2;
1230 if (klabs(j) > klabs(i>>3)) i = divscale28(i,j);
1231 if (dastat == 0)
1232 {
1233 t = mulscale15(sector[sectnum].ceilingheinum,dasqr);
1234 z1 = sector[sectnum].ceilingz;
1235 }
1236 else
1237 {
1238 t = mulscale15(sector[sectnum].floorheinum,dasqr);
1239 z1 = sector[sectnum].floorz;
1240 }
1241 z1 = dmulscale24(dx*t,mulscale20(y2,i)+((y1-wall[fw].y)<<8),
1242 -dy*t,mulscale20(x2,i)+((x1-wall[fw].x)<<8))+((z1-globalposz)<<7);
1243
1244
1245 if (xb2[w] == xdimen-1)
1246 { xv = cosglobalang-sinviewingrangeglobalang; yv = singlobalang+cosviewingrangeglobalang; }
1247 else
1248 { xv = (x2+x1)-globalposx; yv = (y2+y1)-globalposy; }
1249 i = xv*(y1-globalposy)-yv*(x1-globalposx); j = yv*x2-xv*y2;
1250 if (klabs(j) > klabs(i>>3)) i = divscale28(i,j);
1251 if (dastat == 0)
1252 {
1253 t = mulscale15(sector[sectnum].ceilingheinum,dasqr);
1254 z2 = sector[sectnum].ceilingz;
1255 }
1256 else
1257 {
1258 t = mulscale15(sector[sectnum].floorheinum,dasqr);
1259 z2 = sector[sectnum].floorz;
1260 }
1261 z2 = dmulscale24(dx*t,mulscale20(y2,i)+((y1-wall[fw].y)<<8),
1262 -dy*t,mulscale20(x2,i)+((x1-wall[fw].x)<<8))+((z2-globalposz)<<7);
1263
1264
1265 s1 = mulscale20(globaluclip,yb1[w]); s2 = mulscale20(globaluclip,yb2[w]);
1266 s3 = mulscale20(globaldclip,yb1[w]); s4 = mulscale20(globaldclip,yb2[w]);
1267 bad = (z1<s1)+((z2<s2)<<1)+((z1>s3)<<2)+((z2>s4)<<3);
1268
1269 ix1 = xb1[w]; ix2 = xb2[w];
1270 iy1 = yb1[w]; iy2 = yb2[w];
1271 oz1 = z1; oz2 = z2;
1272
1273 if ((bad&3) == 3)
1274 {
1275 //clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),0L);
1276 for (i=ix1; i<=ix2; i++) mostbuf[i] = 0;
1277 return(bad);
1278 }
1279
1280 if ((bad&12) == 12)
1281 {
1282 //clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
1283 for (i=ix1; i<=ix2; i++) mostbuf[i] = ydimen;
1284 return(bad);
1285 }
1286
1287 if (bad&3)
1288 {
1289 //inty = intz / (globaluclip>>16)
1290 t = divscale30(oz1-s1,s2-s1+oz1-oz2);
1291 inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
1292 intz = oz1 + mulscale30(oz2-oz1,t);
1293 xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty);
1294
1295 //t = divscale30((x1<<4)-xcross*yb1[w],xcross*(yb2[w]-yb1[w])-((x2-x1)<<4));
1296 //inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
1297 //intz = z1 + mulscale30(z2-z1,t);
1298
1299 if ((bad&3) == 2)
1300 {
1301 if (xb1[w] <= xcross) { z2 = intz; iy2 = inty; ix2 = xcross; }
1302 //clearbufbyte(&mostbuf[xcross+1],(xb2[w]-xcross)*sizeof(mostbuf[0]),0L);
1303 for (i=xcross+1; i<=xb2[w]; i++) mostbuf[i] = 0;
1304 }
1305 else
1306 {
1307 if (xcross <= xb2[w]) { z1 = intz; iy1 = inty; ix1 = xcross; }
1308 //clearbufbyte(&mostbuf[xb1[w]],(xcross-xb1[w]+1)*sizeof(mostbuf[0]),0L);
1309 for (i=xb1[w]; i<=xcross; i++) mostbuf[i] = 0;
1310 }
1311 }
1312
1313 if (bad&12)
1314 {
1315 //inty = intz / (globaldclip>>16)
1316 t = divscale30(oz1-s3,s4-s3+oz1-oz2);
1317 inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
1318 intz = oz1 + mulscale30(oz2-oz1,t);
1319 xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty);
1320
1321 //t = divscale30((x1<<4)-xcross*yb1[w],xcross*(yb2[w]-yb1[w])-((x2-x1)<<4));
1322 //inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
1323 //intz = z1 + mulscale30(z2-z1,t);
1324
1325 if ((bad&12) == 8)
1326 {
1327 if (xb1[w] <= xcross) { z2 = intz; iy2 = inty; ix2 = xcross; }
1328 //clearbufbyte(&mostbuf[xcross+1],(xb2[w]-xcross)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
1329 for (i=xcross+1; i<=xb2[w]; i++) mostbuf[i] = ydimen;
1330 }
1331 else
1332 {
1333 if (xcross <= xb2[w]) { z1 = intz; iy1 = inty; ix1 = xcross; }
1334 //clearbufbyte(&mostbuf[xb1[w]],(xcross-xb1[w]+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
1335 for (i=xb1[w]; i<=xcross; i++) mostbuf[i] = ydimen;
1336 }
1337 }
1338
1339 y = (scale(z1,xdimenscale,iy1)<<4);
1340 yinc = ((scale(z2,xdimenscale,iy2)<<4)-y) / (ix2-ix1+1);
1341 qinterpolatedown16short(&mostbuf[ix1],ix2-ix1+1,y+(globalhoriz<<16),yinc);
1342
1343 if (mostbuf[ix1] < 0) mostbuf[ix1] = 0;
1344 if (mostbuf[ix1] > ydimen) mostbuf[ix1] = ydimen;
1345 if (mostbuf[ix2] < 0) mostbuf[ix2] = 0;
1346 if (mostbuf[ix2] > ydimen) mostbuf[ix2] = ydimen;
1347
1348 return(bad);
1349 }
1350
1351
1352 //
1353 // ceilscan (internal)
1354 //
ceilscan(int x1,int x2,int sectnum)1355 static void ceilscan(int x1, int x2, int sectnum)
1356 {
1357 int i, j, ox, oy, x, y1, y2, twall, bwall;
1358 sectortype *sec;
1359
1360 sec = §or[sectnum];
1361 if (palookup[sec->ceilingpal] != globalpalwritten)
1362 {
1363 globalpalwritten = palookup[sec->ceilingpal];
1364 if (!globalpalwritten) globalpalwritten = palookup[globalpal]; // JBF: fixes null-pointer crash
1365 setpalookupaddress(globalpalwritten);
1366 }
1367
1368 globalzd = sec->ceilingz-globalposz;
1369 if (globalzd > 0) return;
1370 globalpicnum = sec->ceilingpicnum;
1371 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
1372 setgotpic(globalpicnum);
1373 if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) return;
1374 if (picanm[globalpicnum]&192) globalpicnum += animateoffs((short)globalpicnum,(short)sectnum);
1375
1376 if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
1377 globalbufplc = waloff[globalpicnum];
1378
1379 globalshade = (int)sec->ceilingshade;
1380 globvis = globalcisibility;
1381 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
1382 globalorientation = (int)sec->ceilingstat;
1383
1384
1385 if ((globalorientation&64) == 0)
1386 {
1387 globalx1 = singlobalang; globalx2 = singlobalang;
1388 globaly1 = cosglobalang; globaly2 = cosglobalang;
1389 globalxpanning = (globalposx<<20);
1390 globalypanning = -(globalposy<<20);
1391 }
1392 else
1393 {
1394 j = sec->wallptr;
1395 ox = wall[wall[j].point2].x - wall[j].x;
1396 oy = wall[wall[j].point2].y - wall[j].y;
1397 i = nsqrtasm(ox*ox+oy*oy); if (i == 0) i = 1024; else i = 1048576/i;
1398 globalx1 = mulscale10(dmulscale10(ox,singlobalang,-oy,cosglobalang),i);
1399 globaly1 = mulscale10(dmulscale10(ox,cosglobalang,oy,singlobalang),i);
1400 globalx2 = -globalx1;
1401 globaly2 = -globaly1;
1402
1403 ox = ((wall[j].x-globalposx)<<6); oy = ((wall[j].y-globalposy)<<6);
1404 i = dmulscale14(oy,cosglobalang,-ox,singlobalang);
1405 j = dmulscale14(ox,cosglobalang,oy,singlobalang);
1406 ox = i; oy = j;
1407 globalxpanning = globalx1*ox - globaly1*oy;
1408 globalypanning = globaly2*ox + globalx2*oy;
1409 }
1410 globalx2 = mulscale16(globalx2,viewingrangerecip);
1411 globaly1 = mulscale16(globaly1,viewingrangerecip);
1412 globalxshift = (8-(picsiz[globalpicnum]&15));
1413 globalyshift = (8-(picsiz[globalpicnum]>>4));
1414 if (globalorientation&8) { globalxshift++; globalyshift++; }
1415
1416 if ((globalorientation&0x4) > 0)
1417 {
1418 i = globalxpanning; globalxpanning = globalypanning; globalypanning = i;
1419 i = globalx2; globalx2 = -globaly1; globaly1 = -i;
1420 i = globalx1; globalx1 = globaly2; globaly2 = i;
1421 }
1422 if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalxpanning = -globalxpanning;
1423 if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalypanning = -globalypanning;
1424 globalx1 <<= globalxshift; globaly1 <<= globalxshift;
1425 globalx2 <<= globalyshift; globaly2 <<= globalyshift;
1426 globalxpanning <<= globalxshift; globalypanning <<= globalyshift;
1427 globalxpanning += (((int)sec->ceilingxpanning)<<24);
1428 globalypanning += (((int)sec->ceilingypanning)<<24);
1429 globaly1 = (-globalx1-globaly1)*halfxdimen;
1430 globalx2 = (globalx2-globaly2)*halfxdimen;
1431
1432 sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,(void *)globalbufplc);
1433
1434 globalx2 += globaly2*(x1-1);
1435 globaly1 += globalx1*(x1-1);
1436 globalx1 = mulscale16(globalx1,globalzd);
1437 globalx2 = mulscale16(globalx2,globalzd);
1438 globaly1 = mulscale16(globaly1,globalzd);
1439 globaly2 = mulscale16(globaly2,globalzd);
1440 globvis = klabs(mulscale10(globvis,globalzd));
1441
1442 if (!(globalorientation&0x180))
1443 {
1444 y1 = umost[x1]; y2 = y1;
1445 for(x=x1;x<=x2;x++)
1446 {
1447 twall = umost[x]-1; bwall = min(uplc[x],dmost[x]);
1448 if (twall < bwall-1)
1449 {
1450 if (twall >= y2)
1451 {
1452 while (y1 < y2-1) hline(x-1,++y1);
1453 y1 = twall;
1454 }
1455 else
1456 {
1457 while (y1 < twall) hline(x-1,++y1);
1458 while (y1 > twall) lastx[y1--] = x;
1459 }
1460 while (y2 > bwall) hline(x-1,--y2);
1461 while (y2 < bwall) lastx[y2++] = x;
1462 }
1463 else
1464 {
1465 while (y1 < y2-1) hline(x-1,++y1);
1466 if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
1467 y1 = umost[x+1]; y2 = y1;
1468 }
1469 globalx2 += globaly2; globaly1 += globalx1;
1470 }
1471 while (y1 < y2-1) hline(x2,++y1);
1472 faketimerhandler();
1473 return;
1474 }
1475
1476 switch(globalorientation&0x180)
1477 {
1478 case 128:
1479 msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1480 break;
1481 case 256:
1482 settransnormal();
1483 tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1484 break;
1485 case 384:
1486 settransreverse();
1487 tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1488 break;
1489 }
1490
1491 y1 = umost[x1]; y2 = y1;
1492 for(x=x1;x<=x2;x++)
1493 {
1494 twall = umost[x]-1; bwall = min(uplc[x],dmost[x]);
1495 if (twall < bwall-1)
1496 {
1497 if (twall >= y2)
1498 {
1499 while (y1 < y2-1) slowhline(x-1,++y1);
1500 y1 = twall;
1501 }
1502 else
1503 {
1504 while (y1 < twall) slowhline(x-1,++y1);
1505 while (y1 > twall) lastx[y1--] = x;
1506 }
1507 while (y2 > bwall) slowhline(x-1,--y2);
1508 while (y2 < bwall) lastx[y2++] = x;
1509 }
1510 else
1511 {
1512 while (y1 < y2-1) slowhline(x-1,++y1);
1513 if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
1514 y1 = umost[x+1]; y2 = y1;
1515 }
1516 globalx2 += globaly2; globaly1 += globalx1;
1517 }
1518 while (y1 < y2-1) slowhline(x2,++y1);
1519 faketimerhandler();
1520 }
1521
1522
1523 //
1524 // florscan (internal)
1525 //
florscan(int x1,int x2,int sectnum)1526 static void florscan(int x1, int x2, int sectnum)
1527 {
1528 int i, j, ox, oy, x, y1, y2, twall, bwall;
1529 sectortype *sec;
1530
1531 sec = §or[sectnum];
1532 if (palookup[sec->floorpal] != globalpalwritten)
1533 {
1534 globalpalwritten = palookup[sec->floorpal];
1535 if (!globalpalwritten) globalpalwritten = palookup[globalpal]; // JBF: fixes null-pointer crash
1536 setpalookupaddress(globalpalwritten);
1537 }
1538
1539 globalzd = globalposz-sec->floorz;
1540 if (globalzd > 0) return;
1541 globalpicnum = sec->floorpicnum;
1542 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
1543 setgotpic(globalpicnum);
1544 if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) return;
1545 if (picanm[globalpicnum]&192) globalpicnum += animateoffs((short)globalpicnum,(short)sectnum);
1546
1547 if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
1548 globalbufplc = waloff[globalpicnum];
1549
1550 globalshade = (int)sec->floorshade;
1551 globvis = globalcisibility;
1552 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
1553 globalorientation = (int)sec->floorstat;
1554
1555
1556 if ((globalorientation&64) == 0)
1557 {
1558 globalx1 = singlobalang; globalx2 = singlobalang;
1559 globaly1 = cosglobalang; globaly2 = cosglobalang;
1560 globalxpanning = (globalposx<<20);
1561 globalypanning = -(globalposy<<20);
1562 }
1563 else
1564 {
1565 j = sec->wallptr;
1566 ox = wall[wall[j].point2].x - wall[j].x;
1567 oy = wall[wall[j].point2].y - wall[j].y;
1568 i = nsqrtasm(ox*ox+oy*oy); if (i == 0) i = 1024; else i = 1048576/i;
1569 globalx1 = mulscale10(dmulscale10(ox,singlobalang,-oy,cosglobalang),i);
1570 globaly1 = mulscale10(dmulscale10(ox,cosglobalang,oy,singlobalang),i);
1571 globalx2 = -globalx1;
1572 globaly2 = -globaly1;
1573
1574 ox = ((wall[j].x-globalposx)<<6); oy = ((wall[j].y-globalposy)<<6);
1575 i = dmulscale14(oy,cosglobalang,-ox,singlobalang);
1576 j = dmulscale14(ox,cosglobalang,oy,singlobalang);
1577 ox = i; oy = j;
1578 globalxpanning = globalx1*ox - globaly1*oy;
1579 globalypanning = globaly2*ox + globalx2*oy;
1580 }
1581 globalx2 = mulscale16(globalx2,viewingrangerecip);
1582 globaly1 = mulscale16(globaly1,viewingrangerecip);
1583 globalxshift = (8-(picsiz[globalpicnum]&15));
1584 globalyshift = (8-(picsiz[globalpicnum]>>4));
1585 if (globalorientation&8) { globalxshift++; globalyshift++; }
1586
1587 if ((globalorientation&0x4) > 0)
1588 {
1589 i = globalxpanning; globalxpanning = globalypanning; globalypanning = i;
1590 i = globalx2; globalx2 = -globaly1; globaly1 = -i;
1591 i = globalx1; globalx1 = globaly2; globaly2 = i;
1592 }
1593 if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalxpanning = -globalxpanning;
1594 if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalypanning = -globalypanning;
1595 globalx1 <<= globalxshift; globaly1 <<= globalxshift;
1596 globalx2 <<= globalyshift; globaly2 <<= globalyshift;
1597 globalxpanning <<= globalxshift; globalypanning <<= globalyshift;
1598 globalxpanning += (((int)sec->floorxpanning)<<24);
1599 globalypanning += (((int)sec->floorypanning)<<24);
1600 globaly1 = (-globalx1-globaly1)*halfxdimen;
1601 globalx2 = (globalx2-globaly2)*halfxdimen;
1602
1603 sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,(void *)globalbufplc);
1604
1605 globalx2 += globaly2*(x1-1);
1606 globaly1 += globalx1*(x1-1);
1607 globalx1 = mulscale16(globalx1,globalzd);
1608 globalx2 = mulscale16(globalx2,globalzd);
1609 globaly1 = mulscale16(globaly1,globalzd);
1610 globaly2 = mulscale16(globaly2,globalzd);
1611 globvis = klabs(mulscale10(globvis,globalzd));
1612
1613 if (!(globalorientation&0x180))
1614 {
1615 y1 = max(dplc[x1],umost[x1]); y2 = y1;
1616 for(x=x1;x<=x2;x++)
1617 {
1618 twall = max(dplc[x],umost[x])-1; bwall = dmost[x];
1619 if (twall < bwall-1)
1620 {
1621 if (twall >= y2)
1622 {
1623 while (y1 < y2-1) hline(x-1,++y1);
1624 y1 = twall;
1625 }
1626 else
1627 {
1628 while (y1 < twall) hline(x-1,++y1);
1629 while (y1 > twall) lastx[y1--] = x;
1630 }
1631 while (y2 > bwall) hline(x-1,--y2);
1632 while (y2 < bwall) lastx[y2++] = x;
1633 }
1634 else
1635 {
1636 while (y1 < y2-1) hline(x-1,++y1);
1637 if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
1638 y1 = max(dplc[x+1],umost[x+1]); y2 = y1;
1639 }
1640 globalx2 += globaly2; globaly1 += globalx1;
1641 }
1642 while (y1 < y2-1) hline(x2,++y1);
1643 faketimerhandler();
1644 return;
1645 }
1646
1647 switch(globalorientation&0x180)
1648 {
1649 case 128:
1650 msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1651 break;
1652 case 256:
1653 settransnormal();
1654 tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1655 break;
1656 case 384:
1657 settransreverse();
1658 tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1659 break;
1660 }
1661
1662 y1 = max(dplc[x1],umost[x1]); y2 = y1;
1663 for(x=x1;x<=x2;x++)
1664 {
1665 twall = max(dplc[x],umost[x])-1; bwall = dmost[x];
1666 if (twall < bwall-1)
1667 {
1668 if (twall >= y2)
1669 {
1670 while (y1 < y2-1) slowhline(x-1,++y1);
1671 y1 = twall;
1672 }
1673 else
1674 {
1675 while (y1 < twall) slowhline(x-1,++y1);
1676 while (y1 > twall) lastx[y1--] = x;
1677 }
1678 while (y2 > bwall) slowhline(x-1,--y2);
1679 while (y2 < bwall) lastx[y2++] = x;
1680 }
1681 else
1682 {
1683 while (y1 < y2-1) slowhline(x-1,++y1);
1684 if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
1685 y1 = max(dplc[x+1],umost[x+1]); y2 = y1;
1686 }
1687 globalx2 += globaly2; globaly1 += globalx1;
1688 }
1689 while (y1 < y2-1) slowhline(x2,++y1);
1690 faketimerhandler();
1691 }
1692
1693
1694 //
1695 // wallscan (internal)
1696 //
wallscan(int x1,int x2,short * uwal,short * dwal,int * swal,int * lwal)1697 static void wallscan(int x1, int x2, short *uwal, short *dwal, int *swal, int *lwal)
1698 {
1699 int x, xnice, ynice;
1700 intptr_t i, fpalookup;
1701 int y1ve[4], y2ve[4], u4, d4, z, tsizx, tsizy;
1702 char bad;
1703
1704 if (x2 >= xdim) x2 = xdim-1;
1705
1706 tsizx = tilesizx[globalpicnum];
1707 tsizy = tilesizy[globalpicnum];
1708 setgotpic(globalpicnum);
1709 if ((tsizx <= 0) || (tsizy <= 0)) return;
1710 if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen)) return;
1711 if ((dwal[x1] < 0) && (dwal[x2] < 0)) return;
1712
1713 if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
1714
1715 xnice = (pow2long[picsiz[globalpicnum]&15] == tsizx);
1716 if (xnice) tsizx--;
1717 ynice = (pow2long[picsiz[globalpicnum]>>4] == tsizy);
1718 if (ynice) tsizy = (picsiz[globalpicnum]>>4);
1719
1720 fpalookup = (intptr_t)palookup[globalpal];
1721
1722 setupvlineasm(globalshiftval);
1723
1724 #ifndef ENGINE_USING_A_C
1725
1726 x = x1;
1727 while ((umost[x] > dmost[x]) && (x <= x2)) x++;
1728
1729 for(;(x<=x2)&&((x+frameoffset)&3);x++)
1730 {
1731 y1ve[0] = max(uwal[x],umost[x]);
1732 y2ve[0] = min(dwal[x],dmost[x]);
1733 if (y2ve[0] <= y1ve[0]) continue;
1734
1735 palookupoffse[0] = fpalookup+(getpalookup((int)mulscale16(swal[x],globvis),globalshade)<<8);
1736
1737 bufplce[0] = lwal[x] + globalxpanning;
1738 if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
1739 if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
1740
1741 vince[0] = swal[x]*globalyscale;
1742 vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
1743
1744 vlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],(void *)(bufplce[0]+waloff[globalpicnum]),(void *)(x+frameoffset+ylookup[y1ve[0]]));
1745 }
1746 for(;x<=x2-3;x+=4)
1747 {
1748 bad = 0;
1749 for(z=3;z>=0;z--)
1750 {
1751 y1ve[z] = max(uwal[x+z],umost[x+z]);
1752 y2ve[z] = min(dwal[x+z],dmost[x+z])-1;
1753 if (y2ve[z] < y1ve[z]) { bad += pow2char[z]; continue; }
1754
1755 i = lwal[x+z] + globalxpanning;
1756 if (i >= tsizx) { if (xnice == 0) i %= tsizx; else i &= tsizx; }
1757 if (ynice == 0) i *= tsizy; else i <<= tsizy;
1758 bufplce[z] = waloff[globalpicnum]+i;
1759
1760 vince[z] = swal[x+z]*globalyscale;
1761 vplce[z] = globalzd + vince[z]*(y1ve[z]-globalhoriz+1);
1762 }
1763 if (bad == 15) continue;
1764
1765 palookupoffse[0] = fpalookup+(getpalookup((int)mulscale16(swal[x],globvis),globalshade)<<8);
1766 palookupoffse[3] = fpalookup+(getpalookup((int)mulscale16(swal[x+3],globvis),globalshade)<<8);
1767
1768 if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
1769 {
1770 palookupoffse[1] = palookupoffse[0];
1771 palookupoffse[2] = palookupoffse[0];
1772 }
1773 else
1774 {
1775 palookupoffse[1] = fpalookup+(getpalookup((int)mulscale16(swal[x+1],globvis),globalshade)<<8);
1776 palookupoffse[2] = fpalookup+(getpalookup((int)mulscale16(swal[x+2],globvis),globalshade)<<8);
1777 }
1778
1779 u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
1780 d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
1781
1782 if ((bad != 0) || (u4 >= d4))
1783 {
1784 if (!(bad&1)) prevlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],(void *)bufplce[0],(void *)(ylookup[y1ve[0]]+x+frameoffset+0));
1785 if (!(bad&2)) prevlineasm1(vince[1],(void *)palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],(void *)bufplce[1],(void *)(ylookup[y1ve[1]]+x+frameoffset+1));
1786 if (!(bad&4)) prevlineasm1(vince[2],(void *)palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],(void *)bufplce[2],(void *)(ylookup[y1ve[2]]+x+frameoffset+2));
1787 if (!(bad&8)) prevlineasm1(vince[3],(void *)palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],(void *)bufplce[3],(void *)(ylookup[y1ve[3]]+x+frameoffset+3));
1788 continue;
1789 }
1790
1791 if (u4 > y1ve[0]) vplce[0] = prevlineasm1(vince[0],(void *)palookupoffse[0],u4-y1ve[0]-1,vplce[0],(void *)bufplce[0],(void *)(ylookup[y1ve[0]]+x+frameoffset+0));
1792 if (u4 > y1ve[1]) vplce[1] = prevlineasm1(vince[1],(void *)palookupoffse[1],u4-y1ve[1]-1,vplce[1],(void *)bufplce[1],(void *)(ylookup[y1ve[1]]+x+frameoffset+1));
1793 if (u4 > y1ve[2]) vplce[2] = prevlineasm1(vince[2],(void *)palookupoffse[2],u4-y1ve[2]-1,vplce[2],(void *)bufplce[2],(void *)(ylookup[y1ve[2]]+x+frameoffset+2));
1794 if (u4 > y1ve[3]) vplce[3] = prevlineasm1(vince[3],(void *)palookupoffse[3],u4-y1ve[3]-1,vplce[3],(void *)bufplce[3],(void *)(ylookup[y1ve[3]]+x+frameoffset+3));
1795
1796 if (d4 >= u4) vlineasm4(d4-u4+1,(void *)(ylookup[u4]+x+frameoffset));
1797
1798 i = x+frameoffset+ylookup[d4+1];
1799 if (y2ve[0] > d4) prevlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-d4-1,vplce[0],(void *)bufplce[0],(void *)(i+0));
1800 if (y2ve[1] > d4) prevlineasm1(vince[1],(void *)palookupoffse[1],y2ve[1]-d4-1,vplce[1],(void *)bufplce[1],(void *)(i+1));
1801 if (y2ve[2] > d4) prevlineasm1(vince[2],(void *)palookupoffse[2],y2ve[2]-d4-1,vplce[2],(void *)bufplce[2],(void *)(i+2));
1802 if (y2ve[3] > d4) prevlineasm1(vince[3],(void *)palookupoffse[3],y2ve[3]-d4-1,vplce[3],(void *)bufplce[3],(void *)(i+3));
1803 }
1804 for(;x<=x2;x++)
1805 {
1806 y1ve[0] = max(uwal[x],umost[x]);
1807 y2ve[0] = min(dwal[x],dmost[x]);
1808 if (y2ve[0] <= y1ve[0]) continue;
1809
1810 palookupoffse[0] = fpalookup+(getpalookup((int)mulscale16(swal[x],globvis),globalshade)<<8);
1811
1812 bufplce[0] = lwal[x] + globalxpanning;
1813 if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
1814 if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
1815
1816 vince[0] = swal[x]*globalyscale;
1817 vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
1818
1819 vlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],(void *)(bufplce[0]+waloff[globalpicnum]),(void *)(x+frameoffset+ylookup[y1ve[0]]));
1820 }
1821
1822 #else // ENGINE_USING_A_C
1823
1824 for(x=x1;x<=x2;x++)
1825 {
1826 y1ve[0] = max(uwal[x],umost[x]);
1827 y2ve[0] = min(dwal[x],dmost[x]);
1828 if (y2ve[0] <= y1ve[0]) continue;
1829
1830 palookupoffse[0] = fpalookup+(getpalookup((int)mulscale16(swal[x],globvis),globalshade)<<8);
1831
1832 bufplce[0] = lwal[x] + globalxpanning;
1833 if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
1834 if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
1835
1836 vince[0] = swal[x]*globalyscale;
1837 vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
1838
1839 vlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],(void *)(bufplce[0]+waloff[globalpicnum]),(void *)(x+frameoffset+ylookup[y1ve[0]]));
1840 }
1841
1842 #endif
1843
1844 faketimerhandler();
1845 }
1846
1847
1848 //
1849 // transmaskvline (internal)
1850 //
transmaskvline(int x)1851 static void transmaskvline(int x)
1852 {
1853 int vplc, vinc, i;
1854 intptr_t p, palookupoffs, bufplc;
1855 short y1v, y2v;
1856
1857 if ((x < 0) || (x >= xdimen)) return;
1858
1859 y1v = max(uwall[x],startumost[x+windowx1]-windowy1);
1860 y2v = min(dwall[x],startdmost[x+windowx1]-windowy1);
1861 y2v--;
1862 if (y2v < y1v) return;
1863
1864 palookupoffs = (intptr_t)palookup[globalpal] + (getpalookup((int)mulscale16(swall[x],globvis),globalshade)<<8);
1865
1866 vinc = swall[x]*globalyscale;
1867 vplc = globalzd + vinc*(y1v-globalhoriz+1);
1868
1869 i = lwall[x]+globalxpanning;
1870 if (i >= tilesizx[globalpicnum]) i %= tilesizx[globalpicnum];
1871 bufplc = waloff[globalpicnum]+i*tilesizy[globalpicnum];
1872
1873 p = ylookup[y1v]+x+frameoffset;
1874
1875 tvlineasm1(vinc,(void *)palookupoffs,y2v-y1v,vplc,(void *)bufplc,(void *)p);
1876 }
1877
1878
1879 //
1880 // transmaskvline2 (internal)
1881 //
1882 #ifndef ENGINE_USING_A_C
transmaskvline2(int x)1883 static void transmaskvline2(int x)
1884 {
1885 intptr_t i;
1886 int y1, y2, x2;
1887 short y1ve[2], y2ve[2];
1888
1889 if ((x < 0) || (x >= xdimen)) return;
1890 if (x == xdimen-1) { transmaskvline(x); return; }
1891
1892 x2 = x+1;
1893
1894 y1ve[0] = max(uwall[x],startumost[x+windowx1]-windowy1);
1895 y2ve[0] = min(dwall[x],startdmost[x+windowx1]-windowy1)-1;
1896 if (y2ve[0] < y1ve[0]) { transmaskvline(x2); return; }
1897 y1ve[1] = max(uwall[x2],startumost[x2+windowx1]-windowy1);
1898 y2ve[1] = min(dwall[x2],startdmost[x2+windowx1]-windowy1)-1;
1899 if (y2ve[1] < y1ve[1]) { transmaskvline(x); return; }
1900
1901 palookupoffse[0] = (intptr_t)palookup[globalpal] + (getpalookup((int)mulscale16(swall[x],globvis),globalshade)<<8);
1902 palookupoffse[1] = (intptr_t)palookup[globalpal] + (getpalookup((int)mulscale16(swall[x2],globvis),globalshade)<<8);
1903
1904 setuptvlineasm2(globalshiftval,(void *)palookupoffse[0],(void *)palookupoffse[1]);
1905
1906 vince[0] = swall[x]*globalyscale;
1907 vince[1] = swall[x2]*globalyscale;
1908 vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
1909 vplce[1] = globalzd + vince[1]*(y1ve[1]-globalhoriz+1);
1910
1911 i = lwall[x] + globalxpanning;
1912 if (i >= tilesizx[globalpicnum]) i %= tilesizx[globalpicnum];
1913 bufplce[0] = waloff[globalpicnum]+i*tilesizy[globalpicnum];
1914
1915 i = lwall[x2] + globalxpanning;
1916 if (i >= tilesizx[globalpicnum]) i %= tilesizx[globalpicnum];
1917 bufplce[1] = waloff[globalpicnum]+i*tilesizy[globalpicnum];
1918
1919 y1 = max(y1ve[0],y1ve[1]);
1920 y2 = min(y2ve[0],y2ve[1]);
1921
1922 i = x+frameoffset;
1923
1924 if (y1ve[0] != y1ve[1])
1925 {
1926 if (y1ve[0] < y1)
1927 vplce[0] = tvlineasm1(vince[0],(void *)palookupoffse[0],y1-y1ve[0]-1,vplce[0],(void *)bufplce[0],(void *)(ylookup[y1ve[0]]+i));
1928 else
1929 vplce[1] = tvlineasm1(vince[1],(void *)palookupoffse[1],y1-y1ve[1]-1,vplce[1],(void *)bufplce[1],(void *)(ylookup[y1ve[1]]+i+1));
1930 }
1931
1932 if (y2 > y1)
1933 {
1934 asm1 = vince[1];
1935 asm2 = ylookup[y2]+i+1;
1936 tvlineasm2(vplce[1],vince[0],(void *)bufplce[0],(void *)bufplce[1],vplce[0],(void *)(ylookup[y1]+i));
1937 }
1938 else
1939 {
1940 asm1 = vplce[0];
1941 asm2 = vplce[1];
1942 }
1943
1944 if (y2ve[0] > y2ve[1])
1945 tvlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-y2-1,asm1,(void *)bufplce[0],(void *)(ylookup[y2+1]+i));
1946 else if (y2ve[0] < y2ve[1])
1947 tvlineasm1(vince[1],(void *)palookupoffse[1],y2ve[1]-y2-1,asm2,(void *)bufplce[1],(void *)(ylookup[y2+1]+i+1));
1948
1949 faketimerhandler();
1950 }
1951 #endif
1952
1953 //
1954 // transmaskwallscan (internal)
1955 //
transmaskwallscan(int x1,int x2)1956 static void transmaskwallscan(int x1, int x2)
1957 {
1958 int x;
1959
1960 setgotpic(globalpicnum);
1961 if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) return;
1962
1963 if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
1964
1965 setuptvlineasm(globalshiftval);
1966
1967 x = x1;
1968 while ((startumost[x+windowx1] > startdmost[x+windowx1]) && (x <= x2)) x++;
1969 #ifndef ENGINE_USING_A_C
1970 if ((x <= x2) && (x&1)) transmaskvline(x), x++;
1971 while (x < x2) transmaskvline2(x), x += 2;
1972 #endif
1973 while (x <= x2) transmaskvline(x), x++;
1974 faketimerhandler();
1975 }
1976
1977
1978 //
1979 // ceilspritehline (internal)
1980 //
ceilspritehline(int x2,int y)1981 static void ceilspritehline(int x2, int y)
1982 {
1983 int x1, v, bx, by;
1984
1985 //x = x1 + (x2-x1)t + (y1-y2)u ~ x = 160v
1986 //y = y1 + (y2-y1)t + (x2-x1)u ~ y = (scrx-160)v
1987 //z = z1 = z2 ~ z = posz + (scry-horiz)v
1988
1989 x1 = lastx[y]; if (x2 < x1) return;
1990
1991 v = mulscale20(globalzd,horizlookup[y-globalhoriz+horizycent]);
1992 bx = mulscale14(globalx2*x1+globalx1,v) + globalxpanning;
1993 by = mulscale14(globaly2*x1+globaly1,v) + globalypanning;
1994 asm1 = mulscale14(globalx2,v);
1995 asm2 = mulscale14(globaly2,v);
1996
1997 asm3 = (intptr_t)palookup[globalpal] + (getpalookup((int)mulscale28(klabs(v),globvis),globalshade)<<8);
1998
1999 if ((globalorientation&2) == 0)
2000 mhline((void *)globalbufplc,bx,(x2-x1)<<16,0L,by,(void *)(ylookup[y]+x1+frameoffset));
2001 else
2002 {
2003 thline((void *)globalbufplc,bx,(x2-x1)<<16,0L,by,(void *)(ylookup[y]+x1+frameoffset));
2004 }
2005 }
2006
2007
2008 //
2009 // ceilspritescan (internal)
2010 //
ceilspritescan(int x1,int x2)2011 static void ceilspritescan(int x1, int x2)
2012 {
2013 int x, y1, y2, twall, bwall;
2014
2015 y1 = uwall[x1]; y2 = y1;
2016 for(x=x1;x<=x2;x++)
2017 {
2018 twall = uwall[x]-1; bwall = dwall[x];
2019 if (twall < bwall-1)
2020 {
2021 if (twall >= y2)
2022 {
2023 while (y1 < y2-1) ceilspritehline(x-1,++y1);
2024 y1 = twall;
2025 }
2026 else
2027 {
2028 while (y1 < twall) ceilspritehline(x-1,++y1);
2029 while (y1 > twall) lastx[y1--] = x;
2030 }
2031 while (y2 > bwall) ceilspritehline(x-1,--y2);
2032 while (y2 < bwall) lastx[y2++] = x;
2033 }
2034 else
2035 {
2036 while (y1 < y2-1) ceilspritehline(x-1,++y1);
2037 if (x == x2) break;
2038 y1 = uwall[x+1]; y2 = y1;
2039 }
2040 }
2041 while (y1 < y2-1) ceilspritehline(x2,++y1);
2042 faketimerhandler();
2043 }
2044
2045
2046 //
2047 // grouscan (internal)
2048 //
2049 #define BITSOFPRECISION 3 //Don't forget to change this in A.ASM also!
grouscan(int dax1,int dax2,int sectnum,unsigned char dastat)2050 static void grouscan(int dax1, int dax2, int sectnum, unsigned char dastat)
2051 {
2052 int i, j, l, x, y, dx, dy, wx, wy, y1, y2, daz;
2053 int daslope, dasqr;
2054 int shoffs, shinc, m1, m2;
2055 intptr_t *mptr1, *mptr2, *nptr1, *nptr2;
2056 walltype *wal;
2057 sectortype *sec;
2058
2059 sec = §or[sectnum];
2060
2061 if (dastat == 0)
2062 {
2063 if (globalposz <= getceilzofslope(sectnum,globalposx,globalposy))
2064 return; //Back-face culling
2065 globalorientation = sec->ceilingstat;
2066 globalpicnum = sec->ceilingpicnum;
2067 globalshade = sec->ceilingshade;
2068 globalpal = sec->ceilingpal;
2069 daslope = sec->ceilingheinum;
2070 daz = sec->ceilingz;
2071 }
2072 else
2073 {
2074 if (globalposz >= getflorzofslope(sectnum,globalposx,globalposy))
2075 return; //Back-face culling
2076 globalorientation = sec->floorstat;
2077 globalpicnum = sec->floorpicnum;
2078 globalshade = sec->floorshade;
2079 globalpal = sec->floorpal;
2080 daslope = sec->floorheinum;
2081 daz = sec->floorz;
2082 }
2083
2084 if (palookup[globalpal] == 0) globalpal = 0;
2085 if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs(globalpicnum,sectnum);
2086 setgotpic(globalpicnum);
2087 if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) return;
2088 if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
2089
2090 wal = &wall[sec->wallptr];
2091 wx = wall[wal->point2].x - wal->x;
2092 wy = wall[wal->point2].y - wal->y;
2093 dasqr = krecipasm(nsqrtasm(wx*wx+wy*wy));
2094 i = mulscale21(daslope,dasqr);
2095 wx *= i; wy *= i;
2096
2097 globalx = -mulscale19(singlobalang,xdimenrecip);
2098 globaly = mulscale19(cosglobalang,xdimenrecip);
2099 globalx1 = (globalposx<<8);
2100 globaly1 = -(globalposy<<8);
2101 i = (dax1-halfxdimen)*xdimenrecip;
2102 globalx2 = mulscale16(cosglobalang<<4,viewingrangerecip) - mulscale27(singlobalang,i);
2103 globaly2 = mulscale16(singlobalang<<4,viewingrangerecip) + mulscale27(cosglobalang,i);
2104 globalzd = (xdimscale<<9);
2105 globalzx = -dmulscale17(wx,globaly2,-wy,globalx2) + mulscale10(1-globalhoriz,globalzd);
2106 globalz = -dmulscale25(wx,globaly,-wy,globalx);
2107
2108 if (globalorientation&64) //Relative alignment
2109 {
2110 dx = mulscale14(wall[wal->point2].x-wal->x,dasqr);
2111 dy = mulscale14(wall[wal->point2].y-wal->y,dasqr);
2112
2113 i = nsqrtasm(daslope*daslope+16777216);
2114
2115 x = globalx; y = globaly;
2116 globalx = dmulscale16(x,dx,y,dy);
2117 globaly = mulscale12(dmulscale16(-y,dx,x,dy),i);
2118
2119 x = ((wal->x-globalposx)<<8); y = ((wal->y-globalposy)<<8);
2120 globalx1 = dmulscale16(-x,dx,-y,dy);
2121 globaly1 = mulscale12(dmulscale16(-y,dx,x,dy),i);
2122
2123 x = globalx2; y = globaly2;
2124 globalx2 = dmulscale16(x,dx,y,dy);
2125 globaly2 = mulscale12(dmulscale16(-y,dx,x,dy),i);
2126 }
2127 if (globalorientation&0x4)
2128 {
2129 i = globalx; globalx = -globaly; globaly = -i;
2130 i = globalx1; globalx1 = globaly1; globaly1 = i;
2131 i = globalx2; globalx2 = -globaly2; globaly2 = -i;
2132 }
2133 if (globalorientation&0x10) { globalx1 = -globalx1, globalx2 = -globalx2, globalx = -globalx; }
2134 if (globalorientation&0x20) { globaly1 = -globaly1, globaly2 = -globaly2, globaly = -globaly; }
2135
2136 daz = dmulscale9(wx,globalposy-wal->y,-wy,globalposx-wal->x) + ((daz-globalposz)<<8);
2137 globalx2 = mulscale20(globalx2,daz); globalx = mulscale28(globalx,daz);
2138 globaly2 = mulscale20(globaly2,-daz); globaly = mulscale28(globaly,-daz);
2139
2140 i = 8-(picsiz[globalpicnum]&15); j = 8-(picsiz[globalpicnum]>>4);
2141 if (globalorientation&8) { i++; j++; }
2142 globalx1 <<= (i+12); globalx2 <<= i; globalx <<= i;
2143 globaly1 <<= (j+12); globaly2 <<= j; globaly <<= j;
2144
2145 if (dastat == 0)
2146 {
2147 globalx1 += (((int)sec->ceilingxpanning)<<24);
2148 globaly1 += (((int)sec->ceilingypanning)<<24);
2149 }
2150 else
2151 {
2152 globalx1 += (((int)sec->floorxpanning)<<24);
2153 globaly1 += (((int)sec->floorypanning)<<24);
2154 }
2155
2156 asm1 = -(globalzd>>(16-BITSOFPRECISION));
2157
2158 globvis = globalvisibility;
2159 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
2160 globvis = mulscale13(globvis,daz);
2161 globvis = mulscale16(globvis,xdimscale);
2162
2163 setupslopevlin(((int)(picsiz[globalpicnum]&15))+(((int)(picsiz[globalpicnum]>>4))<<8),(void *)waloff[globalpicnum],-ylookup[1]);
2164
2165 l = (globalzd>>16);
2166
2167 assert(SLOPALOOKUPSIZ - 4 - ydimen > 0);
2168
2169 shinc = mulscale16(globalz,xdimenscale);
2170 if (shinc > 0) shoffs = (4<<15); else shoffs = ((SLOPALOOKUPSIZ-4-ydimen)<<15);
2171 if (dastat == 0) y1 = umost[dax1]; else y1 = max(umost[dax1],dplc[dax1]);
2172 m1 = mulscale16(y1,globalzd) + (globalzx>>6);
2173 //Avoid visibility overflow by crossing horizon
2174 if (globalzd > 0) m1 += (globalzd>>16); else m1 -= (globalzd>>16);
2175 m2 = m1+l;
2176 mptr1 = &slopalookup[y1+(shoffs>>15)]; mptr2 = mptr1+1;
2177
2178 assert(y1+(shoffs>>15) >= 0);
2179 assert(y1+(shoffs>>15) <= SLOPALOOKUPSIZ-2);
2180
2181 for(x=dax1;x<=dax2;x++)
2182 {
2183 if (dastat == 0) { y1 = umost[x]; y2 = min(dmost[x],uplc[x])-1; }
2184 else { y1 = max(umost[x],dplc[x]); y2 = dmost[x]-1; }
2185 if (y1 <= y2)
2186 {
2187 assert(y1+(shoffs>>15) >= 0);
2188 assert(y1+(shoffs>>15) <= SLOPALOOKUPSIZ-1);
2189 assert(y2+(shoffs>>15) >= 0);
2190 assert(y2+(shoffs>>15) <= SLOPALOOKUPSIZ-1);
2191
2192 nptr1 = &slopalookup[y1+(shoffs>>15)];
2193 nptr2 = &slopalookup[y2+(shoffs>>15)];
2194 while (nptr1 <= mptr1)
2195 {
2196 *mptr1-- = (intptr_t)palookup[globalpal] + (getpalookup((int)mulscale24(krecipasm(m1),globvis),globalshade)<<8);
2197 m1 -= l;
2198 }
2199 while (nptr2 >= mptr2)
2200 {
2201 *mptr2++ = (intptr_t)palookup[globalpal] + (getpalookup((int)mulscale24(krecipasm(m2),globvis),globalshade)<<8);
2202 m2 += l;
2203 }
2204
2205 globalx3 = (globalx2>>10);
2206 globaly3 = (globaly2>>10);
2207 asm3 = mulscale16(y2,globalzd) + (globalzx>>6);
2208 slopevlin((void *)(ylookup[y2]+x+frameoffset),krecipasm(asm3>>3),nptr2,y2-y1+1,globalx1,globaly1);
2209
2210 if ((x&15) == 0) faketimerhandler();
2211 }
2212 globalx2 += globalx;
2213 globaly2 += globaly;
2214 globalzx += globalz;
2215 shoffs += shinc;
2216 }
2217 }
2218
2219
2220 //
2221 // parascan (internal)
2222 //
parascan(int dax1,int dax2,int sectnum,unsigned char dastat,int bunch)2223 static void parascan(int dax1, int dax2, int sectnum, unsigned char dastat, int bunch)
2224 {
2225 sectortype *sec;
2226 int j, k, l, m, n, x, z, wallnum, nextsectnum, globalhorizbak;
2227 short *topptr, *botptr;
2228
2229 sectnum = thesector[bunchfirst[bunch]]; sec = §or[sectnum];
2230
2231 globalhorizbak = globalhoriz;
2232 if (parallaxyscale != 65536)
2233 globalhoriz = mulscale16(globalhoriz-(ydimen>>1),parallaxyscale) + (ydimen>>1);
2234 globvis = globalpisibility;
2235 //globalorientation = 0L;
2236 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
2237
2238 if (dastat == 0)
2239 {
2240 globalpal = sec->ceilingpal;
2241 globalpicnum = sec->ceilingpicnum;
2242 globalshade = (int)sec->ceilingshade;
2243 globalxpanning = (int)sec->ceilingxpanning;
2244 globalypanning = (int)sec->ceilingypanning;
2245 topptr = umost;
2246 botptr = uplc;
2247 }
2248 else
2249 {
2250 globalpal = sec->floorpal;
2251 globalpicnum = sec->floorpicnum;
2252 globalshade = (int)sec->floorshade;
2253 globalxpanning = (int)sec->floorxpanning;
2254 globalypanning = (int)sec->floorypanning;
2255 topptr = dplc;
2256 botptr = dmost;
2257 }
2258
2259 if (palookup[globalpal] == 0) globalpal = 0;
2260 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
2261 if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)sectnum);
2262 globalshiftval = (picsiz[globalpicnum]>>4);
2263 if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
2264 globalshiftval = 32-globalshiftval;
2265 globalzd = (((tilesizy[globalpicnum]>>1)+parallaxyoffs)<<globalshiftval)+(globalypanning<<24);
2266 globalyscale = (8<<(globalshiftval-19));
2267 //if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
2268
2269 k = 11 - (picsiz[globalpicnum]&15) - pskybits;
2270 x = -1;
2271
2272 for(z=bunchfirst[bunch];z>=0;z=p2[z])
2273 {
2274 wallnum = thewall[z]; nextsectnum = wall[wallnum].nextsector;
2275
2276 if (dastat == 0) j = sector[nextsectnum].ceilingstat;
2277 else j = sector[nextsectnum].floorstat;
2278
2279 if ((nextsectnum < 0) || (wall[wallnum].cstat&32) || ((j&1) == 0))
2280 {
2281 if (x == -1) x = xb1[z];
2282
2283 if (parallaxtype == 0)
2284 {
2285 n = mulscale16(xdimenrecip,viewingrange);
2286 for(j=xb1[z];j<=xb2[z];j++)
2287 lplc[j] = (((mulscale23(j-halfxdimen,n)+globalang)&2047)>>k);
2288 }
2289 else
2290 {
2291 for(j=xb1[z];j<=xb2[z];j++)
2292 lplc[j] = ((((int)radarang2[j]+globalang)&2047)>>k);
2293 }
2294 if (parallaxtype == 2)
2295 {
2296 n = mulscale16(xdimscale,viewingrange);
2297 for(j=xb1[z];j<=xb2[z];j++)
2298 swplc[j] = mulscale14(sintable[((int)radarang2[j]+512)&2047],n);
2299 }
2300 else
2301 clearbuf(&swplc[xb1[z]],xb2[z]-xb1[z]+1,mulscale16(xdimscale,viewingrange));
2302 }
2303 else if (x >= 0)
2304 {
2305 l = globalpicnum; m = (picsiz[globalpicnum]&15);
2306 globalpicnum = l+pskyoff[lplc[x]>>m];
2307
2308 if (((lplc[x]^lplc[xb1[z]-1])>>m) == 0)
2309 wallscan(x,xb1[z]-1,topptr,botptr,swplc,lplc);
2310 else
2311 {
2312 j = x;
2313 while (x < xb1[z])
2314 {
2315 n = l+pskyoff[lplc[x]>>m];
2316 if (n != globalpicnum)
2317 {
2318 wallscan(j,x-1,topptr,botptr,swplc,lplc);
2319 j = x;
2320 globalpicnum = n;
2321 }
2322 x++;
2323 }
2324 if (j < x)
2325 wallscan(j,x-1,topptr,botptr,swplc,lplc);
2326 }
2327
2328 globalpicnum = l;
2329 x = -1;
2330 }
2331 }
2332
2333 if (x >= 0)
2334 {
2335 l = globalpicnum; m = (picsiz[globalpicnum]&15);
2336 globalpicnum = l+pskyoff[lplc[x]>>m];
2337
2338 if (((lplc[x]^lplc[xb2[bunchlast[bunch]]])>>m) == 0)
2339 wallscan(x,xb2[bunchlast[bunch]],topptr,botptr,swplc,lplc);
2340 else
2341 {
2342 j = x;
2343 while (x <= xb2[bunchlast[bunch]])
2344 {
2345 n = l+pskyoff[lplc[x]>>m];
2346 if (n != globalpicnum)
2347 {
2348 wallscan(j,x-1,topptr,botptr,swplc,lplc);
2349 j = x;
2350 globalpicnum = n;
2351 }
2352 x++;
2353 }
2354 if (j <= x)
2355 wallscan(j,x,topptr,botptr,swplc,lplc);
2356 }
2357 globalpicnum = l;
2358 }
2359 globalhoriz = globalhorizbak;
2360 }
2361
2362
2363 //
2364 // drawalls (internal)
2365 //
drawalls(int bunch)2366 static void drawalls(int bunch)
2367 {
2368 sectortype *sec, *nextsec;
2369 walltype *wal;
2370 int i, x, x1, x2, cz[5], fz[5];
2371 int z, wallnum, sectnum, nextsectnum;
2372 int startsmostwallcnt, startsmostcnt, gotswall;
2373 unsigned char andwstat1, andwstat2;
2374
2375 z = bunchfirst[bunch];
2376 sectnum = thesector[z]; sec = §or[sectnum];
2377
2378 andwstat1 = 0xff; andwstat2 = 0xff;
2379 for(;z>=0;z=p2[z]) //uplc/dplc calculation
2380 {
2381 andwstat1 &= wallmost(uplc,z,sectnum,(char)0);
2382 andwstat2 &= wallmost(dplc,z,sectnum,(char)1);
2383 }
2384
2385 if ((andwstat1&3) != 3) //draw ceilings
2386 {
2387 if ((sec->ceilingstat&3) == 2)
2388 grouscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,0);
2389 else if ((sec->ceilingstat&1) == 0)
2390 ceilscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum);
2391 else
2392 parascan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,0,bunch);
2393 }
2394 if ((andwstat2&12) != 12) //draw floors
2395 {
2396 if ((sec->floorstat&3) == 2)
2397 grouscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,1);
2398 else if ((sec->floorstat&1) == 0)
2399 florscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum);
2400 else
2401 parascan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,1,bunch);
2402 }
2403
2404 //DRAW WALLS SECTION!
2405 for(z=bunchfirst[bunch];z>=0;z=p2[z])
2406 {
2407 x1 = xb1[z]; x2 = xb2[z];
2408 if (umost[x2] >= dmost[x2])
2409 {
2410 for(x=x1;x<x2;x++)
2411 if (umost[x] < dmost[x]) break;
2412 if (x >= x2)
2413 {
2414 smostwall[smostwallcnt] = z;
2415 smostwalltype[smostwallcnt] = 0;
2416 smostwallcnt++;
2417 continue;
2418 }
2419 }
2420
2421 wallnum = thewall[z]; wal = &wall[wallnum];
2422 nextsectnum = wal->nextsector; nextsec = §or[nextsectnum];
2423
2424 gotswall = 0;
2425
2426 startsmostwallcnt = smostwallcnt;
2427 startsmostcnt = smostcnt;
2428
2429 if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
2430 {
2431 if (searchy <= uplc[searchx]) //ceiling
2432 {
2433 searchsector = sectnum; searchwall = wallnum;
2434 searchstat = 1; searchit = 1;
2435 }
2436 else if (searchy >= dplc[searchx]) //floor
2437 {
2438 searchsector = sectnum; searchwall = wallnum;
2439 searchstat = 2; searchit = 1;
2440 }
2441 }
2442
2443 if (nextsectnum >= 0)
2444 {
2445 getzsofslope((short)sectnum,wal->x,wal->y,&cz[0],&fz[0]);
2446 getzsofslope((short)sectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[1],&fz[1]);
2447 getzsofslope((short)nextsectnum,wal->x,wal->y,&cz[2],&fz[2]);
2448 getzsofslope((short)nextsectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[3],&fz[3]);
2449 getzsofslope((short)nextsectnum,globalposx,globalposy,&cz[4],&fz[4]);
2450
2451 if ((wal->cstat&48) == 16) maskwall[maskwallcnt++] = z;
2452
2453 if (((sec->ceilingstat&1) == 0) || ((nextsec->ceilingstat&1) == 0))
2454 {
2455 if ((cz[2] <= cz[0]) && (cz[3] <= cz[1]))
2456 {
2457 if (globparaceilclip)
2458 for(x=x1;x<=x2;x++)
2459 if (uplc[x] > umost[x])
2460 if (umost[x] <= dmost[x])
2461 {
2462 umost[x] = uplc[x];
2463 if (umost[x] > dmost[x]) numhits--;
2464 }
2465 }
2466 else
2467 {
2468 wallmost(dwall,z,nextsectnum,(char)0);
2469 if ((cz[2] > fz[0]) || (cz[3] > fz[1]))
2470 for(i=x1;i<=x2;i++) if (dwall[i] > dplc[i]) dwall[i] = dplc[i];
2471
2472 if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
2473 if (searchy <= dwall[searchx]) //wall
2474 {
2475 searchsector = sectnum; searchwall = wallnum;
2476 searchstat = 0; searchit = 1;
2477 }
2478
2479 globalorientation = (int)wal->cstat;
2480 globalpicnum = wal->picnum;
2481 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
2482 globalxpanning = (int)wal->xpanning;
2483 globalypanning = (int)wal->ypanning;
2484 globalshiftval = (picsiz[globalpicnum]>>4);
2485 if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
2486 globalshiftval = 32-globalshiftval;
2487 if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
2488 globalshade = (int)wal->shade;
2489 globvis = globalvisibility;
2490 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
2491 globalpal = (int)wal->pal;
2492 if (palookup[globalpal] == 0) globalpal = 0; // JBF: fixes crash
2493 globalyscale = (wal->yrepeat<<(globalshiftval-19));
2494 if ((globalorientation&4) == 0)
2495 globalzd = (((globalposz-nextsec->ceilingz)*globalyscale)<<8);
2496 else
2497 globalzd = (((globalposz-sec->ceilingz)*globalyscale)<<8);
2498 globalzd += (globalypanning<<24);
2499 if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
2500
2501 if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
2502 wallscan(x1,x2,uplc,dwall,swall,lwall);
2503
2504 if ((cz[2] >= cz[0]) && (cz[3] >= cz[1]))
2505 {
2506 for(x=x1;x<=x2;x++)
2507 if (dwall[x] > umost[x])
2508 if (umost[x] <= dmost[x])
2509 {
2510 umost[x] = dwall[x];
2511 if (umost[x] > dmost[x]) numhits--;
2512 }
2513 }
2514 else
2515 {
2516 for(x=x1;x<=x2;x++)
2517 if (umost[x] <= dmost[x])
2518 {
2519 i = max(uplc[x],dwall[x]);
2520 if (i > umost[x])
2521 {
2522 umost[x] = i;
2523 if (umost[x] > dmost[x]) numhits--;
2524 }
2525 }
2526 }
2527 }
2528 if ((cz[2] < cz[0]) || (cz[3] < cz[1]) || (globalposz < cz[4]))
2529 {
2530 i = x2-x1+1;
2531 if (smostcnt+i < MAXYSAVES)
2532 {
2533 smoststart[smostwallcnt] = smostcnt;
2534 smostwall[smostwallcnt] = z;
2535 smostwalltype[smostwallcnt] = 1; //1 for umost
2536 smostwallcnt++;
2537 copybufbyte(&umost[x1],&smost[smostcnt],i*sizeof(smost[0]));
2538 smostcnt += i;
2539 }
2540 }
2541 }
2542 if (((sec->floorstat&1) == 0) || ((nextsec->floorstat&1) == 0))
2543 {
2544 if ((fz[2] >= fz[0]) && (fz[3] >= fz[1]))
2545 {
2546 if (globparaflorclip)
2547 for(x=x1;x<=x2;x++)
2548 if (dplc[x] < dmost[x])
2549 if (umost[x] <= dmost[x])
2550 {
2551 dmost[x] = dplc[x];
2552 if (umost[x] > dmost[x]) numhits--;
2553 }
2554 }
2555 else
2556 {
2557 wallmost(uwall,z,nextsectnum,(char)1);
2558 if ((fz[2] < cz[0]) || (fz[3] < cz[1]))
2559 for(i=x1;i<=x2;i++) if (uwall[i] < uplc[i]) uwall[i] = uplc[i];
2560
2561 if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
2562 if (searchy >= uwall[searchx]) //wall
2563 {
2564 searchsector = sectnum; searchwall = wallnum;
2565 if ((wal->cstat&2) > 0) searchwall = wal->nextwall;
2566 searchstat = 0; searchit = 1;
2567 }
2568
2569 if ((wal->cstat&2) > 0)
2570 {
2571 wallnum = wal->nextwall; wal = &wall[wallnum];
2572 globalorientation = (int)wal->cstat;
2573 globalpicnum = wal->picnum;
2574 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
2575 globalxpanning = (int)wal->xpanning;
2576 globalypanning = (int)wal->ypanning;
2577 if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
2578 globalshade = (int)wal->shade;
2579 globalpal = (int)wal->pal;
2580 wallnum = thewall[z]; wal = &wall[wallnum];
2581 }
2582 else
2583 {
2584 globalorientation = (int)wal->cstat;
2585 globalpicnum = wal->picnum;
2586 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
2587 globalxpanning = (int)wal->xpanning;
2588 globalypanning = (int)wal->ypanning;
2589 if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
2590 globalshade = (int)wal->shade;
2591 globalpal = (int)wal->pal;
2592 }
2593 if (palookup[globalpal] == 0) globalpal = 0; // JBF: fixes crash
2594 globvis = globalvisibility;
2595 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
2596 globalshiftval = (picsiz[globalpicnum]>>4);
2597 if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
2598 globalshiftval = 32-globalshiftval;
2599 globalyscale = (wal->yrepeat<<(globalshiftval-19));
2600 if ((globalorientation&4) == 0)
2601 globalzd = (((globalposz-nextsec->floorz)*globalyscale)<<8);
2602 else
2603 globalzd = (((globalposz-sec->ceilingz)*globalyscale)<<8);
2604 globalzd += (globalypanning<<24);
2605 if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
2606
2607 if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
2608 wallscan(x1,x2,uwall,dplc,swall,lwall);
2609
2610 if ((fz[2] <= fz[0]) && (fz[3] <= fz[1]))
2611 {
2612 for(x=x1;x<=x2;x++)
2613 if (uwall[x] < dmost[x])
2614 if (umost[x] <= dmost[x])
2615 {
2616 dmost[x] = uwall[x];
2617 if (umost[x] > dmost[x]) numhits--;
2618 }
2619 }
2620 else
2621 {
2622 for(x=x1;x<=x2;x++)
2623 if (umost[x] <= dmost[x])
2624 {
2625 i = min(dplc[x],uwall[x]);
2626 if (i < dmost[x])
2627 {
2628 dmost[x] = i;
2629 if (umost[x] > dmost[x]) numhits--;
2630 }
2631 }
2632 }
2633 }
2634 if ((fz[2] > fz[0]) || (fz[3] > fz[1]) || (globalposz > fz[4]))
2635 {
2636 i = x2-x1+1;
2637 if (smostcnt+i < MAXYSAVES)
2638 {
2639 smoststart[smostwallcnt] = smostcnt;
2640 smostwall[smostwallcnt] = z;
2641 smostwalltype[smostwallcnt] = 2; //2 for dmost
2642 smostwallcnt++;
2643 copybufbyte(&dmost[x1],&smost[smostcnt],i*sizeof(smost[0]));
2644 smostcnt += i;
2645 }
2646 }
2647 }
2648 if (numhits < 0) return;
2649 if ((!(wal->cstat&32)) && ((gotsector[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0))
2650 {
2651 if (umost[x2] < dmost[x2])
2652 scansector(nextsectnum);
2653 else
2654 {
2655 for(x=x1;x<x2;x++)
2656 if (umost[x] < dmost[x])
2657 { scansector(nextsectnum); break; }
2658
2659 //If can't see sector beyond, then cancel smost array and just
2660 //store wall!
2661 if (x == x2)
2662 {
2663 smostwallcnt = startsmostwallcnt;
2664 smostcnt = startsmostcnt;
2665 smostwall[smostwallcnt] = z;
2666 smostwalltype[smostwallcnt] = 0;
2667 smostwallcnt++;
2668 }
2669 }
2670 }
2671 }
2672 if ((nextsectnum < 0) || (wal->cstat&32)) //White/1-way wall
2673 {
2674 globalorientation = (int)wal->cstat;
2675 if (nextsectnum < 0) globalpicnum = wal->picnum;
2676 else globalpicnum = wal->overpicnum;
2677 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
2678 globalxpanning = (int)wal->xpanning;
2679 globalypanning = (int)wal->ypanning;
2680 if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
2681 globalshade = (int)wal->shade;
2682 globvis = globalvisibility;
2683 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
2684 globalpal = (int)wal->pal;
2685 if (palookup[globalpal] == 0) globalpal = 0; // JBF: fixes crash
2686 globalshiftval = (picsiz[globalpicnum]>>4);
2687 if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
2688 globalshiftval = 32-globalshiftval;
2689 globalyscale = (wal->yrepeat<<(globalshiftval-19));
2690 if (nextsectnum >= 0)
2691 {
2692 if ((globalorientation&4) == 0) globalzd = globalposz-nextsec->ceilingz;
2693 else globalzd = globalposz-sec->ceilingz;
2694 }
2695 else
2696 {
2697 if ((globalorientation&4) == 0) globalzd = globalposz-sec->ceilingz;
2698 else globalzd = globalposz-sec->floorz;
2699 }
2700 globalzd = ((globalzd*globalyscale)<<8) + (globalypanning<<24);
2701 if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
2702
2703 if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
2704 wallscan(x1,x2,uplc,dplc,swall,lwall);
2705
2706 for(x=x1;x<=x2;x++)
2707 if (umost[x] <= dmost[x])
2708 { umost[x] = 1; dmost[x] = 0; numhits--; }
2709 smostwall[smostwallcnt] = z;
2710 smostwalltype[smostwallcnt] = 0;
2711 smostwallcnt++;
2712
2713 if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
2714 {
2715 searchit = 1; searchsector = sectnum; searchwall = wallnum;
2716 if (nextsectnum < 0) searchstat = 0; else searchstat = 4;
2717 }
2718 }
2719 }
2720 }
2721
2722
2723 //
2724 // drawvox
2725 //
drawvox(int dasprx,int daspry,int dasprz,int dasprang,int daxscale,int dayscale,unsigned char daindex,signed char dashade,unsigned char dapal,int * daumost,int * dadmost)2726 static void drawvox(int dasprx, int daspry, int dasprz, int dasprang,
2727 int daxscale, int dayscale, unsigned char daindex,
2728 signed char dashade, unsigned char dapal, int *daumost, int *dadmost)
2729 {
2730 int i, j, k, x, y, syoff, ggxstart, ggystart, nxoff;
2731 int cosang, sinang, sprcosang, sprsinang, backx, backy, gxinc, gyinc;
2732 int daxsiz, daysiz, dazsiz, daxpivot, daypivot, dazpivot;
2733 int daxscalerecip, dayscalerecip, cnt, gxstart, gystart, odayscale;
2734 int l1, l2, xyvoxoffs, *longptr;
2735 intptr_t slabxoffs;
2736 int lx, rx, nx, ny, x1=0, y1=0, z1, x2=0, y2=0, z2, yplc, yinc=0;
2737 int yoff, xs=0, ys=0, xe, ye, xi=0, yi=0, cbackx, cbacky, dagxinc, dagyinc;
2738 short *shortptr;
2739 unsigned char *voxptr, *voxend, *davoxptr, oand, oand16, oand32;
2740
2741 cosang = sintable[(globalang+512)&2047];
2742 sinang = sintable[globalang&2047];
2743 sprcosang = sintable[(dasprang+512)&2047];
2744 sprsinang = sintable[dasprang&2047];
2745
2746 i = klabs(dmulscale6(dasprx-globalposx,cosang,daspry-globalposy,sinang));
2747 j = (int)(getpalookup((int)mulscale21(globvis,i),(int)dashade)<<8);
2748 setupdrawslab(ylookup[1], palookup[dapal]+j);
2749 j = 1310720;
2750 j *= min(daxscale,dayscale); j >>= 6; //New hacks (for sized-down voxels)
2751 for(k=0;k<MAXVOXMIPS;k++)
2752 {
2753 if (i < j) { i = k; break; }
2754 j <<= 1;
2755 }
2756 if (k >= MAXVOXMIPS) i = MAXVOXMIPS-1;
2757
2758 if (novoxmips) i = 0;
2759 davoxptr = (unsigned char *)voxoff[daindex][i];
2760 if (!davoxptr && i > 0) { davoxptr = (unsigned char *)voxoff[daindex][0]; i = 0; }
2761 if (!davoxptr) return;
2762
2763 if (voxscale[daindex] == 65536)
2764 { daxscale <<= (i+8); dayscale <<= (i+8); }
2765 else
2766 {
2767 daxscale = mulscale8(daxscale<<i,voxscale[daindex]);
2768 dayscale = mulscale8(dayscale<<i,voxscale[daindex]);
2769 }
2770
2771 odayscale = dayscale;
2772 daxscale = mulscale16(daxscale,xyaspect);
2773 daxscale = scale(daxscale,xdimenscale,xdimen<<8);
2774 dayscale = scale(dayscale,mulscale16(xdimenscale,viewingrangerecip),xdimen<<8);
2775
2776 daxscalerecip = (1<<30)/daxscale;
2777 dayscalerecip = (1<<30)/dayscale;
2778
2779 longptr = (int *)davoxptr;
2780 daxsiz = B_LITTLE32(longptr[0]); daysiz = B_LITTLE32(longptr[1]); dazsiz = B_LITTLE32(longptr[2]);
2781 daxpivot = B_LITTLE32(longptr[3]); daypivot = B_LITTLE32(longptr[4]); dazpivot = B_LITTLE32(longptr[5]);
2782 davoxptr += (6<<2);
2783
2784 x = mulscale16(globalposx-dasprx,daxscalerecip);
2785 y = mulscale16(globalposy-daspry,daxscalerecip);
2786 backx = ((dmulscale10(x,sprcosang,y,sprsinang)+daxpivot)>>8);
2787 backy = ((dmulscale10(y,sprcosang,x,-sprsinang)+daypivot)>>8);
2788 cbackx = min(max(backx,0),daxsiz-1);
2789 cbacky = min(max(backy,0),daysiz-1);
2790
2791 sprcosang = mulscale14(daxscale,sprcosang);
2792 sprsinang = mulscale14(daxscale,sprsinang);
2793
2794 x = (dasprx-globalposx) - dmulscale18(daxpivot,sprcosang,daypivot,-sprsinang);
2795 y = (daspry-globalposy) - dmulscale18(daypivot,sprcosang,daxpivot,sprsinang);
2796
2797 cosang = mulscale16(cosang,dayscalerecip);
2798 sinang = mulscale16(sinang,dayscalerecip);
2799
2800 gxstart = y*cosang - x*sinang;
2801 gystart = x*cosang + y*sinang;
2802 gxinc = dmulscale10(sprsinang,cosang,sprcosang,-sinang);
2803 gyinc = dmulscale10(sprcosang,cosang,sprsinang,sinang);
2804
2805 x = 0; y = 0; j = max(daxsiz,daysiz);
2806 for(i=0;i<=j;i++)
2807 {
2808 ggxinc[i] = x; x += gxinc;
2809 ggyinc[i] = y; y += gyinc;
2810 }
2811
2812 if ((klabs(globalposz-dasprz)>>10) >= klabs(odayscale)) return;
2813 syoff = divscale21(globalposz-dasprz,odayscale) + (dazpivot<<7);
2814 yoff = ((klabs(gxinc)+klabs(gyinc))>>1);
2815 longptr = (int *)davoxptr;
2816 xyvoxoffs = ((daxsiz+1)<<2);
2817
2818 begindrawing(); //{{{
2819
2820 for(cnt=0;cnt<8;cnt++)
2821 {
2822 switch(cnt)
2823 {
2824 case 0: xs = 0; ys = 0; xi = 1; yi = 1; break;
2825 case 1: xs = daxsiz-1; ys = 0; xi = -1; yi = 1; break;
2826 case 2: xs = 0; ys = daysiz-1; xi = 1; yi = -1; break;
2827 case 3: xs = daxsiz-1; ys = daysiz-1; xi = -1; yi = -1; break;
2828 case 4: xs = 0; ys = cbacky; xi = 1; yi = 2; break;
2829 case 5: xs = daxsiz-1; ys = cbacky; xi = -1; yi = 2; break;
2830 case 6: xs = cbackx; ys = 0; xi = 2; yi = 1; break;
2831 case 7: xs = cbackx; ys = daysiz-1; xi = 2; yi = -1; break;
2832 }
2833 xe = cbackx; ye = cbacky;
2834 if (cnt < 4)
2835 {
2836 if ((xi < 0) && (xe >= xs)) continue;
2837 if ((xi > 0) && (xe <= xs)) continue;
2838 if ((yi < 0) && (ye >= ys)) continue;
2839 if ((yi > 0) && (ye <= ys)) continue;
2840 }
2841 else
2842 {
2843 if ((xi < 0) && (xe > xs)) continue;
2844 if ((xi > 0) && (xe < xs)) continue;
2845 if ((yi < 0) && (ye > ys)) continue;
2846 if ((yi > 0) && (ye < ys)) continue;
2847 xe += xi; ye += yi;
2848 }
2849
2850 i = ksgn(ys-backy)+ksgn(xs-backx)*3+4;
2851 switch(i)
2852 {
2853 case 6: case 7: x1 = 0; y1 = 0; break;
2854 case 8: case 5: x1 = gxinc; y1 = gyinc; break;
2855 case 0: case 3: x1 = gyinc; y1 = -gxinc; break;
2856 case 2: case 1: x1 = gxinc+gyinc; y1 = gyinc-gxinc; break;
2857 }
2858 switch(i)
2859 {
2860 case 2: case 5: x2 = 0; y2 = 0; break;
2861 case 0: case 1: x2 = gxinc; y2 = gyinc; break;
2862 case 8: case 7: x2 = gyinc; y2 = -gxinc; break;
2863 case 6: case 3: x2 = gxinc+gyinc; y2 = gyinc-gxinc; break;
2864 }
2865 oand = pow2char[(xs<backx)+0]+pow2char[(ys<backy)+2];
2866 oand16 = oand+16;
2867 oand32 = oand+32;
2868
2869 if (yi > 0) { dagxinc = gxinc; dagyinc = mulscale16(gyinc,viewingrangerecip); }
2870 else { dagxinc = -gxinc; dagyinc = -mulscale16(gyinc,viewingrangerecip); }
2871
2872 //Fix for non 90 degree viewing ranges
2873 nxoff = mulscale16(x2-x1,viewingrangerecip);
2874 x1 = mulscale16(x1,viewingrangerecip);
2875
2876 ggxstart = gxstart+ggyinc[ys];
2877 ggystart = gystart-ggxinc[ys];
2878
2879 for(x=xs;x!=xe;x+=xi)
2880 {
2881 slabxoffs = (intptr_t)&davoxptr[B_LITTLE32(longptr[x])];
2882 shortptr = (short *)&davoxptr[((x*(daysiz+1))<<1)+xyvoxoffs];
2883
2884 nx = mulscale16(ggxstart+ggxinc[x],viewingrangerecip)+x1;
2885 ny = ggystart+ggyinc[x];
2886 for(y=ys;y!=ye;y+=yi,nx+=dagyinc,ny-=dagxinc)
2887 {
2888 if ((ny <= nytooclose) || (ny >= nytoofar)) continue;
2889 voxptr = (unsigned char *)(B_LITTLE16(shortptr[y])+slabxoffs);
2890 voxend = (unsigned char *)(B_LITTLE16(shortptr[y+1])+slabxoffs);
2891 if (voxptr == voxend) continue;
2892
2893 lx = mulscale32(nx>>3,distrecip[(ny+y1)>>14])+halfxdimen;
2894 if (lx < 0) lx = 0;
2895 rx = mulscale32((nx+nxoff)>>3,distrecip[(ny+y2)>>14])+halfxdimen;
2896 if (rx > xdimen) rx = xdimen;
2897 if (rx <= lx) continue;
2898 rx -= lx;
2899
2900 l1 = distrecip[(ny-yoff)>>14];
2901 l2 = distrecip[(ny+yoff)>>14];
2902 for(;voxptr<voxend;voxptr+=voxptr[1]+3)
2903 {
2904 j = (voxptr[0]<<15)-syoff;
2905 if (j < 0)
2906 {
2907 k = j+(voxptr[1]<<15);
2908 if (k < 0)
2909 {
2910 if ((voxptr[2]&oand32) == 0) continue;
2911 z2 = mulscale32(l2,k) + globalhoriz; //Below slab
2912 }
2913 else
2914 {
2915 if ((voxptr[2]&oand) == 0) continue; //Middle of slab
2916 z2 = mulscale32(l1,k) + globalhoriz;
2917 }
2918 z1 = mulscale32(l1,j) + globalhoriz;
2919 }
2920 else
2921 {
2922 if ((voxptr[2]&oand16) == 0) continue;
2923 z1 = mulscale32(l2,j) + globalhoriz; //Above slab
2924 z2 = mulscale32(l1,j+(voxptr[1]<<15)) + globalhoriz;
2925 }
2926
2927 if (voxptr[1] == 1)
2928 {
2929 yplc = 0; yinc = 0;
2930 if (z1 < daumost[lx]) z1 = daumost[lx];
2931 }
2932 else
2933 {
2934 if (z2-z1 >= 1024) yinc = divscale16(voxptr[1],z2-z1);
2935 else if (z2 > z1) yinc = (lowrecip[z2-z1]*voxptr[1]>>8);
2936 if (z1 < daumost[lx]) { yplc = yinc*(daumost[lx]-z1); z1 = daumost[lx]; } else yplc = 0;
2937 }
2938 if (z2 > dadmost[lx]) z2 = dadmost[lx];
2939 z2 -= z1; if (z2 <= 0) continue;
2940
2941 drawslab(rx,yplc,z2,yinc,&voxptr[3],(void *)(ylookup[z1]+lx+frameoffset));
2942 }
2943 }
2944 }
2945 }
2946
2947 enddrawing(); //}}}
2948 }
2949
2950
2951 //
2952 // drawsprite (internal)
2953 //
drawsprite(int snum)2954 static void drawsprite(int snum)
2955 {
2956 spritetype *tspr;
2957 sectortype *sec;
2958 int startum, startdm, sectnum, xb, yp, cstat;
2959 int siz, xsiz, ysiz, xoff, yoff, xspan, yspan;
2960 int x1, y1, x2, y2, lx, rx, dalx2, darx2, i, j, k, x, linum, linuminc;
2961 int yinc, z, z1, z2, xp1, yp1, xp2, yp2;
2962 int xv, yv, top, topinc, bot, botinc, hplc, hinc;
2963 int cosang, sinang, dax, day, lpoint, lmax, rpoint, rmax, dax1, dax2, y;
2964 int npoints, npoints2, zz, t, zsgn, zzsgn, *longptr;
2965 int tilenum, vtilenum = 0, spritenum;
2966 unsigned char swapped, daclip;
2967
2968 //============================================================================= //POLYMOST BEGINS
2969 #if USE_POLYMOST
2970 if (rendmode) { polymost_drawsprite(snum); return; }
2971 #endif
2972 //============================================================================= //POLYMOST ENDS
2973
2974 tspr = tspriteptr[snum];
2975
2976 xb = spritesx[snum];
2977 yp = spritesy[snum];
2978 tilenum = tspr->picnum;
2979 spritenum = tspr->owner;
2980 cstat = tspr->cstat;
2981
2982 if ((cstat&48)==48) vtilenum = tilenum; // if the game wants voxels, it gets voxels
2983 else if ((cstat&48)!=48 && (usevoxels) && (tiletovox[tilenum] != -1)
2984 #if USE_POLYMOST && USE_OPENGL
2985 && (!(spriteext[tspr->owner].flags&SPREXT_NOTMD))
2986 #endif
2987 ) {
2988 vtilenum = tiletovox[tilenum];
2989 cstat |= 48;
2990 }
2991
2992 if ((cstat&48) != 48)
2993 {
2994 if (picanm[tilenum]&192) tilenum += animateoffs(tilenum,spritenum+32768);
2995 if ((tilesizx[tilenum] <= 0) || (tilesizy[tilenum] <= 0) || (spritenum < 0))
2996 return;
2997 }
2998 if ((tspr->xrepeat <= 0) || (tspr->yrepeat <= 0)) return;
2999
3000 sectnum = tspr->sectnum; sec = §or[sectnum];
3001 globalpal = tspr->pal;
3002 if (palookup[globalpal] == 0) globalpal = 0; // JBF: fixes null-pointer crash
3003 globalshade = tspr->shade;
3004 if (cstat&2)
3005 {
3006 if (cstat&512) settransreverse(); else settransnormal();
3007 }
3008
3009 xoff = (int)((signed char)((picanm[tilenum]>>8)&255))+((int)tspr->xoffset);
3010 yoff = (int)((signed char)((picanm[tilenum]>>16)&255))+((int)tspr->yoffset);
3011
3012 if ((cstat&48) == 0)
3013 {
3014 if (yp <= (4<<8)) return;
3015
3016 siz = divscale19(xdimenscale,yp);
3017
3018 xv = mulscale16(((int)tspr->xrepeat)<<16,xyaspect);
3019
3020 xspan = tilesizx[tilenum];
3021 yspan = tilesizy[tilenum];
3022 xsiz = mulscale30(siz,xv*xspan);
3023 ysiz = mulscale14(siz,tspr->yrepeat*yspan);
3024
3025 if (((tilesizx[tilenum]>>11) >= xsiz) || (yspan >= (ysiz>>1)))
3026 return; //Watch out for divscale overflow
3027
3028 x1 = xb-(xsiz>>1);
3029 if (xspan&1) x1 += mulscale31(siz,xv); //Odd xspans
3030 i = mulscale30(siz,xv*xoff);
3031 if ((cstat&4) == 0) x1 -= i; else x1 += i;
3032
3033 y1 = mulscale16(tspr->z-globalposz,siz);
3034 y1 -= mulscale14(siz,tspr->yrepeat*yoff);
3035 y1 += (globalhoriz<<8)-ysiz;
3036 if (cstat&128)
3037 {
3038 y1 += (ysiz>>1);
3039 if (yspan&1) y1 += mulscale15(siz,tspr->yrepeat); //Odd yspans
3040 }
3041
3042 x2 = x1+xsiz-1;
3043 y2 = y1+ysiz-1;
3044 if ((y1|255) >= (y2|255)) return;
3045
3046 lx = (x1>>8)+1; if (lx < 0) lx = 0;
3047 rx = (x2>>8); if (rx >= xdimen) rx = xdimen-1;
3048 if (lx > rx) return;
3049
3050 yinc = divscale32(yspan,ysiz);
3051
3052 if ((sec->ceilingstat&3) == 0)
3053 startum = globalhoriz+mulscale24(siz,sec->ceilingz-globalposz)-1;
3054 else
3055 startum = 0;
3056 if ((sec->floorstat&3) == 0)
3057 startdm = globalhoriz+mulscale24(siz,sec->floorz-globalposz)+1;
3058 else
3059 startdm = 0x7fffffff;
3060 if ((y1>>8) > startum) startum = (y1>>8);
3061 if ((y2>>8) < startdm) startdm = (y2>>8);
3062
3063 if (startum < -32768) startum = -32768;
3064 if (startdm > 32767) startdm = 32767;
3065 if (startum >= startdm) return;
3066
3067 if ((cstat&4) == 0)
3068 {
3069 linuminc = divscale24(xspan,xsiz);
3070 linum = mulscale8((lx<<8)-x1,linuminc);
3071 }
3072 else
3073 {
3074 linuminc = -divscale24(xspan,xsiz);
3075 linum = mulscale8((lx<<8)-x2,linuminc);
3076 }
3077 if ((cstat&8) > 0)
3078 {
3079 yinc = -yinc;
3080 i = y1; y1 = y2; y2 = i;
3081 }
3082
3083 for(x=lx;x<=rx;x++)
3084 {
3085 uwall[x] = max(startumost[x+windowx1]-windowy1,(short)startum);
3086 dwall[x] = min(startdmost[x+windowx1]-windowy1,(short)startdm);
3087 }
3088 daclip = 0;
3089 for(i=smostwallcnt-1;i>=0;i--)
3090 {
3091 if (smostwalltype[i]&daclip) continue;
3092 j = smostwall[i];
3093 if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
3094 if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
3095 if (spritewallfront(tspr,(int)thewall[j]) && ((yp <= yb1[j]) || (yp <= yb2[j]))) continue;
3096
3097 dalx2 = max(xb1[j],lx); darx2 = min(xb2[j],rx);
3098
3099 switch(smostwalltype[i])
3100 {
3101 case 0:
3102 if (dalx2 <= darx2)
3103 {
3104 if ((dalx2 == lx) && (darx2 == rx)) return;
3105 //clearbufbyte(&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
3106 for (k=dalx2; k<=darx2; k++) dwall[k] = 0;
3107 }
3108 break;
3109 case 1:
3110 k = smoststart[i] - xb1[j];
3111 for(x=dalx2;x<=darx2;x++)
3112 if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
3113 if ((dalx2 == lx) && (darx2 == rx)) daclip |= 1;
3114 break;
3115 case 2:
3116 k = smoststart[i] - xb1[j];
3117 for(x=dalx2;x<=darx2;x++)
3118 if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
3119 if ((dalx2 == lx) && (darx2 == rx)) daclip |= 2;
3120 break;
3121 }
3122 }
3123
3124 if (uwall[rx] >= dwall[rx])
3125 {
3126 for(x=lx;x<rx;x++)
3127 if (uwall[x] < dwall[x]) break;
3128 if (x == rx) return;
3129 }
3130
3131 //sprite
3132 if ((searchit >= 1) && (searchx >= lx) && (searchx <= rx))
3133 if ((searchy >= uwall[searchx]) && (searchy < dwall[searchx]))
3134 {
3135 searchsector = sectnum; searchwall = spritenum;
3136 searchstat = 3; searchit = 1;
3137 }
3138
3139 z2 = tspr->z - ((yoff*tspr->yrepeat)<<2);
3140 if (cstat&128)
3141 {
3142 z2 += ((yspan*tspr->yrepeat)<<1);
3143 if (yspan&1) z2 += (tspr->yrepeat<<1); //Odd yspans
3144 }
3145 z1 = z2 - ((yspan*tspr->yrepeat)<<2);
3146
3147 globalorientation = 0;
3148 globalpicnum = tilenum;
3149 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
3150 globalxpanning = 0L;
3151 globalypanning = 0L;
3152 globvis = globalvisibility;
3153 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
3154 globalshiftval = (picsiz[globalpicnum]>>4);
3155 if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
3156 globalshiftval = 32-globalshiftval;
3157 globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
3158 globalzd = (((globalposz-z1)*globalyscale)<<8);
3159 if ((cstat&8) > 0)
3160 {
3161 globalyscale = -globalyscale;
3162 globalzd = (((globalposz-z2)*globalyscale)<<8);
3163 }
3164
3165 qinterpolatedown16(&lwall[lx],rx-lx+1,linum,linuminc);
3166 clearbuf(&swall[lx],rx-lx+1,mulscale19(yp,xdimscale));
3167
3168 if ((cstat&2) == 0)
3169 maskwallscan(lx,rx,uwall,dwall,swall,lwall);
3170 else
3171 transmaskwallscan(lx,rx);
3172 }
3173 else if ((cstat&48) == 16)
3174 {
3175 if ((cstat&4) > 0) xoff = -xoff;
3176 if ((cstat&8) > 0) yoff = -yoff;
3177
3178 xspan = tilesizx[tilenum]; yspan = tilesizy[tilenum];
3179 xv = tspr->xrepeat*sintable[(tspr->ang+2560+1536)&2047];
3180 yv = tspr->xrepeat*sintable[(tspr->ang+2048+1536)&2047];
3181 i = (xspan>>1)+xoff;
3182 x1 = tspr->x-globalposx-mulscale16(xv,i); x2 = x1+mulscale16(xv,xspan);
3183 y1 = tspr->y-globalposy-mulscale16(yv,i); y2 = y1+mulscale16(yv,xspan);
3184
3185 yp1 = dmulscale6(x1,cosviewingrangeglobalang,y1,sinviewingrangeglobalang);
3186 yp2 = dmulscale6(x2,cosviewingrangeglobalang,y2,sinviewingrangeglobalang);
3187 if ((yp1 <= 0) && (yp2 <= 0)) return;
3188 xp1 = dmulscale6(y1,cosglobalang,-x1,singlobalang);
3189 xp2 = dmulscale6(y2,cosglobalang,-x2,singlobalang);
3190
3191 x1 += globalposx; y1 += globalposy;
3192 x2 += globalposx; y2 += globalposy;
3193
3194 swapped = 0;
3195 if (dmulscale32(xp1,yp2,-xp2,yp1) >= 0) //If wall's NOT facing you
3196 {
3197 if ((cstat&64) != 0) return;
3198 i = xp1, xp1 = xp2, xp2 = i;
3199 i = yp1, yp1 = yp2, yp2 = i;
3200 i = x1, x1 = x2, x2 = i;
3201 i = y1, y1 = y2, y2 = i;
3202 swapped = 1;
3203 }
3204
3205 if (xp1 >= -yp1)
3206 {
3207 if (xp1 > yp1) return;
3208
3209 if (yp1 == 0) return;
3210 xb1[MAXWALLSB-1] = halfxdimen + scale(xp1,halfxdimen,yp1);
3211 if (xp1 >= 0) xb1[MAXWALLSB-1]++; //Fix for SIGNED divide
3212 if (xb1[MAXWALLSB-1] >= xdimen) xb1[MAXWALLSB-1] = xdimen-1;
3213 yb1[MAXWALLSB-1] = yp1;
3214 }
3215 else
3216 {
3217 if (xp2 < -yp2) return;
3218 xb1[MAXWALLSB-1] = 0;
3219 i = yp1-yp2+xp1-xp2;
3220 if (i == 0) return;
3221 yb1[MAXWALLSB-1] = yp1 + scale(yp2-yp1,xp1+yp1,i);
3222 }
3223 if (xp2 <= yp2)
3224 {
3225 if (xp2 < -yp2) return;
3226
3227 if (yp2 == 0) return;
3228 xb2[MAXWALLSB-1] = halfxdimen + scale(xp2,halfxdimen,yp2) - 1;
3229 if (xp2 >= 0) xb2[MAXWALLSB-1]++; //Fix for SIGNED divide
3230 if (xb2[MAXWALLSB-1] >= xdimen) xb2[MAXWALLSB-1] = xdimen-1;
3231 yb2[MAXWALLSB-1] = yp2;
3232 }
3233 else
3234 {
3235 if (xp1 > yp1) return;
3236
3237 xb2[MAXWALLSB-1] = xdimen-1;
3238 i = xp2-xp1+yp1-yp2;
3239 if (i == 0) return;
3240 yb2[MAXWALLSB-1] = yp1 + scale(yp2-yp1,yp1-xp1,i);
3241 }
3242
3243 if ((yb1[MAXWALLSB-1] < 256) || (yb2[MAXWALLSB-1] < 256) || (xb1[MAXWALLSB-1] > xb2[MAXWALLSB-1]))
3244 return;
3245
3246 topinc = -mulscale10(yp1,xspan);
3247 top = (((mulscale10(xp1,xdimen) - mulscale9(xb1[MAXWALLSB-1]-halfxdimen,yp1))*xspan)>>3);
3248 botinc = ((yp2-yp1)>>8);
3249 bot = mulscale11(xp1-xp2,xdimen) + mulscale2(xb1[MAXWALLSB-1]-halfxdimen,botinc);
3250
3251 j = xb2[MAXWALLSB-1]+3;
3252 z = mulscale20(top,krecipasm(bot));
3253 lwall[xb1[MAXWALLSB-1]] = (z>>8);
3254 for(x=xb1[MAXWALLSB-1]+4;x<=j;x+=4)
3255 {
3256 top += topinc; bot += botinc;
3257 zz = z; z = mulscale20(top,krecipasm(bot));
3258 lwall[x] = (z>>8);
3259 i = ((z+zz)>>1);
3260 lwall[x-2] = (i>>8);
3261 lwall[x-3] = ((i+zz)>>9);
3262 lwall[x-1] = ((i+z)>>9);
3263 }
3264
3265 if (lwall[xb1[MAXWALLSB-1]] < 0) lwall[xb1[MAXWALLSB-1]] = 0;
3266 if (lwall[xb2[MAXWALLSB-1]] >= xspan) lwall[xb2[MAXWALLSB-1]] = xspan-1;
3267
3268 if ((swapped^((cstat&4)>0)) > 0)
3269 {
3270 j = xspan-1;
3271 for(x=xb1[MAXWALLSB-1];x<=xb2[MAXWALLSB-1];x++)
3272 lwall[x] = j-lwall[x];
3273 }
3274
3275 rx1[MAXWALLSB-1] = xp1; ry1[MAXWALLSB-1] = yp1;
3276 rx2[MAXWALLSB-1] = xp2; ry2[MAXWALLSB-1] = yp2;
3277
3278 hplc = divscale19(xdimenscale,yb1[MAXWALLSB-1]);
3279 hinc = divscale19(xdimenscale,yb2[MAXWALLSB-1]);
3280 hinc = (hinc-hplc)/(xb2[MAXWALLSB-1]-xb1[MAXWALLSB-1]+1);
3281
3282 z2 = tspr->z - ((yoff*tspr->yrepeat)<<2);
3283 if (cstat&128)
3284 {
3285 z2 += ((yspan*tspr->yrepeat)<<1);
3286 if (yspan&1) z2 += (tspr->yrepeat<<1); //Odd yspans
3287 }
3288 z1 = z2 - ((yspan*tspr->yrepeat)<<2);
3289
3290 globalorientation = 0;
3291 globalpicnum = tilenum;
3292 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
3293 globalxpanning = 0L;
3294 globalypanning = 0L;
3295 globvis = globalvisibility;
3296 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
3297 globalshiftval = (picsiz[globalpicnum]>>4);
3298 if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
3299 globalshiftval = 32-globalshiftval;
3300 globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
3301 globalzd = (((globalposz-z1)*globalyscale)<<8);
3302 if ((cstat&8) > 0)
3303 {
3304 globalyscale = -globalyscale;
3305 globalzd = (((globalposz-z2)*globalyscale)<<8);
3306 }
3307
3308 if (((sec->ceilingstat&1) == 0) && (z1 < sec->ceilingz))
3309 z1 = sec->ceilingz;
3310 if (((sec->floorstat&1) == 0) && (z2 > sec->floorz))
3311 z2 = sec->floorz;
3312
3313 owallmost(uwall,(int)(MAXWALLSB-1),z1-globalposz);
3314 owallmost(dwall,(int)(MAXWALLSB-1),z2-globalposz);
3315 for(i=xb1[MAXWALLSB-1];i<=xb2[MAXWALLSB-1];i++)
3316 { swall[i] = (krecipasm(hplc)<<2); hplc += hinc; }
3317
3318 for(i=smostwallcnt-1;i>=0;i--)
3319 {
3320 j = smostwall[i];
3321
3322 if ((xb1[j] > xb2[MAXWALLSB-1]) || (xb2[j] < xb1[MAXWALLSB-1])) continue;
3323
3324 dalx2 = xb1[j]; darx2 = xb2[j];
3325 if (max(yb1[MAXWALLSB-1],yb2[MAXWALLSB-1]) > min(yb1[j],yb2[j]))
3326 {
3327 if (min(yb1[MAXWALLSB-1],yb2[MAXWALLSB-1]) > max(yb1[j],yb2[j]))
3328 {
3329 x = 0x80000000;
3330 }
3331 else
3332 {
3333 x = thewall[j]; xp1 = wall[x].x; yp1 = wall[x].y;
3334 x = wall[x].point2; xp2 = wall[x].x; yp2 = wall[x].y;
3335
3336 z1 = (xp2-xp1)*(y1-yp1) - (yp2-yp1)*(x1-xp1);
3337 z2 = (xp2-xp1)*(y2-yp1) - (yp2-yp1)*(x2-xp1);
3338 if ((z1^z2) >= 0)
3339 x = (z1+z2);
3340 else
3341 {
3342 z1 = (x2-x1)*(yp1-y1) - (y2-y1)*(xp1-x1);
3343 z2 = (x2-x1)*(yp2-y1) - (y2-y1)*(xp2-x1);
3344
3345 if ((z1^z2) >= 0)
3346 x = -(z1+z2);
3347 else
3348 {
3349 if ((xp2-xp1)*(tspr->y-yp1) == (tspr->x-xp1)*(yp2-yp1))
3350 {
3351 if (wall[thewall[j]].nextsector == tspr->sectnum)
3352 x = 0x80000000;
3353 else
3354 x = 0x7fffffff;
3355 }
3356 else
3357 { //INTERSECTION!
3358 x = (xp1-globalposx) + scale(xp2-xp1,z1,z1-z2);
3359 y = (yp1-globalposy) + scale(yp2-yp1,z1,z1-z2);
3360
3361 yp1 = dmulscale14(x,cosglobalang,y,singlobalang);
3362 if (yp1 > 0)
3363 {
3364 xp1 = dmulscale14(y,cosglobalang,-x,singlobalang);
3365
3366 x = halfxdimen + scale(xp1,halfxdimen,yp1);
3367 if (xp1 >= 0) x++; //Fix for SIGNED divide
3368
3369 if (z1 < 0)
3370 { if (dalx2 < x) dalx2 = x; }
3371 else
3372 { if (darx2 > x) darx2 = x; }
3373 x = 0x80000001;
3374 }
3375 else
3376 x = 0x7fffffff;
3377 }
3378 }
3379 }
3380 }
3381 if (x < 0)
3382 {
3383 if (dalx2 < xb1[MAXWALLSB-1]) dalx2 = xb1[MAXWALLSB-1];
3384 if (darx2 > xb2[MAXWALLSB-1]) darx2 = xb2[MAXWALLSB-1];
3385 switch(smostwalltype[i])
3386 {
3387 case 0:
3388 if (dalx2 <= darx2)
3389 {
3390 if ((dalx2 == xb1[MAXWALLSB-1]) && (darx2 == xb2[MAXWALLSB-1])) return;
3391 //clearbufbyte(&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
3392 for (k=dalx2; k<=darx2; k++) dwall[k] = 0;
3393 }
3394 break;
3395 case 1:
3396 k = smoststart[i] - xb1[j];
3397 for(x=dalx2;x<=darx2;x++)
3398 if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
3399 break;
3400 case 2:
3401 k = smoststart[i] - xb1[j];
3402 for(x=dalx2;x<=darx2;x++)
3403 if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
3404 break;
3405 }
3406 }
3407 }
3408 }
3409
3410 //sprite
3411 if ((searchit >= 1) && (searchx >= xb1[MAXWALLSB-1]) && (searchx <= xb2[MAXWALLSB-1]))
3412 if ((searchy >= uwall[searchx]) && (searchy <= dwall[searchx]))
3413 {
3414 searchsector = sectnum; searchwall = spritenum;
3415 searchstat = 3; searchit = 1;
3416 }
3417
3418 if ((cstat&2) == 0) {
3419 maskwallscan(xb1[MAXWALLSB-1],xb2[MAXWALLSB-1],uwall,dwall,swall,lwall);
3420 } else {
3421 transmaskwallscan(xb1[MAXWALLSB-1],xb2[MAXWALLSB-1]);
3422 }
3423 }
3424 else if ((cstat&48) == 32)
3425 {
3426 if ((cstat&64) != 0)
3427 if ((globalposz > tspr->z) == ((cstat&8)==0))
3428 return;
3429
3430 if ((cstat&4) > 0) xoff = -xoff;
3431 if ((cstat&8) > 0) yoff = -yoff;
3432 xspan = tilesizx[tilenum];
3433 yspan = tilesizy[tilenum];
3434
3435 //Rotate center point
3436 dax = tspr->x-globalposx;
3437 day = tspr->y-globalposy;
3438 rzi[0] = dmulscale10(cosglobalang,dax,singlobalang,day);
3439 rxi[0] = dmulscale10(cosglobalang,day,-singlobalang,dax);
3440
3441 //Get top-left corner
3442 i = ((tspr->ang+2048-globalang)&2047);
3443 cosang = sintable[(i+512)&2047]; sinang = sintable[i];
3444 dax = ((xspan>>1)+xoff)*tspr->xrepeat;
3445 day = ((yspan>>1)+yoff)*tspr->yrepeat;
3446 rzi[0] += dmulscale12(sinang,dax,cosang,day);
3447 rxi[0] += dmulscale12(sinang,day,-cosang,dax);
3448
3449 //Get other 3 corners
3450 dax = xspan*tspr->xrepeat;
3451 day = yspan*tspr->yrepeat;
3452 rzi[1] = rzi[0]-mulscale12(sinang,dax);
3453 rxi[1] = rxi[0]+mulscale12(cosang,dax);
3454 dax = -mulscale12(cosang,day);
3455 day = -mulscale12(sinang,day);
3456 rzi[2] = rzi[1]+dax; rxi[2] = rxi[1]+day;
3457 rzi[3] = rzi[0]+dax; rxi[3] = rxi[0]+day;
3458
3459 //Put all points on same z
3460 ryi[0] = scale((tspr->z-globalposz),yxaspect,320<<8);
3461 if (ryi[0] == 0) return;
3462 ryi[1] = ryi[2] = ryi[3] = ryi[0];
3463
3464 if ((cstat&4) == 0)
3465 { z = 0; z1 = 1; z2 = 3; }
3466 else
3467 { z = 1; z1 = 0; z2 = 2; }
3468
3469 dax = rzi[z1]-rzi[z]; day = rxi[z1]-rxi[z];
3470 bot = dmulscale8(dax,dax,day,day);
3471 if (((klabs(dax)>>13) >= bot) || ((klabs(day)>>13) >= bot)) return;
3472 globalx1 = divscale18(dax,bot);
3473 globalx2 = divscale18(day,bot);
3474
3475 dax = rzi[z2]-rzi[z]; day = rxi[z2]-rxi[z];
3476 bot = dmulscale8(dax,dax,day,day);
3477 if (((klabs(dax)>>13) >= bot) || ((klabs(day)>>13) >= bot)) return;
3478 globaly1 = divscale18(dax,bot);
3479 globaly2 = divscale18(day,bot);
3480
3481 //Calculate globals for hline texture mapping function
3482 globalxpanning = (rxi[z]<<12);
3483 globalypanning = (rzi[z]<<12);
3484 globalzd = (ryi[z]<<12);
3485
3486 rzi[0] = mulscale16(rzi[0],viewingrange);
3487 rzi[1] = mulscale16(rzi[1],viewingrange);
3488 rzi[2] = mulscale16(rzi[2],viewingrange);
3489 rzi[3] = mulscale16(rzi[3],viewingrange);
3490
3491 if (ryi[0] < 0) //If ceilsprite is above you, reverse order of points
3492 {
3493 i = rxi[1]; rxi[1] = rxi[3]; rxi[3] = i;
3494 i = rzi[1]; rzi[1] = rzi[3]; rzi[3] = i;
3495 }
3496
3497
3498 //Clip polygon in 3-space
3499 npoints = 4;
3500
3501 //Clip edge 1
3502 npoints2 = 0;
3503 zzsgn = rxi[0]+rzi[0];
3504 for(z=0;z<npoints;z++)
3505 {
3506 zz = z+1; if (zz == npoints) zz = 0;
3507 zsgn = zzsgn; zzsgn = rxi[zz]+rzi[zz];
3508 if (zsgn >= 0)
3509 {
3510 rxi2[npoints2] = rxi[z]; ryi2[npoints2] = ryi[z]; rzi2[npoints2] = rzi[z];
3511 npoints2++;
3512 }
3513 if ((zsgn^zzsgn) < 0)
3514 {
3515 t = divscale30(zsgn,zsgn-zzsgn);
3516 rxi2[npoints2] = rxi[z] + mulscale30(t,rxi[zz]-rxi[z]);
3517 ryi2[npoints2] = ryi[z] + mulscale30(t,ryi[zz]-ryi[z]);
3518 rzi2[npoints2] = rzi[z] + mulscale30(t,rzi[zz]-rzi[z]);
3519 npoints2++;
3520 }
3521 }
3522 if (npoints2 <= 2) return;
3523
3524 //Clip edge 2
3525 npoints = 0;
3526 zzsgn = rxi2[0]-rzi2[0];
3527 for(z=0;z<npoints2;z++)
3528 {
3529 zz = z+1; if (zz == npoints2) zz = 0;
3530 zsgn = zzsgn; zzsgn = rxi2[zz]-rzi2[zz];
3531 if (zsgn <= 0)
3532 {
3533 rxi[npoints] = rxi2[z]; ryi[npoints] = ryi2[z]; rzi[npoints] = rzi2[z];
3534 npoints++;
3535 }
3536 if ((zsgn^zzsgn) < 0)
3537 {
3538 t = divscale30(zsgn,zsgn-zzsgn);
3539 rxi[npoints] = rxi2[z] + mulscale30(t,rxi2[zz]-rxi2[z]);
3540 ryi[npoints] = ryi2[z] + mulscale30(t,ryi2[zz]-ryi2[z]);
3541 rzi[npoints] = rzi2[z] + mulscale30(t,rzi2[zz]-rzi2[z]);
3542 npoints++;
3543 }
3544 }
3545 if (npoints <= 2) return;
3546
3547 //Clip edge 3
3548 npoints2 = 0;
3549 zzsgn = ryi[0]*halfxdimen + (rzi[0]*(globalhoriz-0));
3550 for(z=0;z<npoints;z++)
3551 {
3552 zz = z+1; if (zz == npoints) zz = 0;
3553 zsgn = zzsgn; zzsgn = ryi[zz]*halfxdimen + (rzi[zz]*(globalhoriz-0));
3554 if (zsgn >= 0)
3555 {
3556 rxi2[npoints2] = rxi[z];
3557 ryi2[npoints2] = ryi[z];
3558 rzi2[npoints2] = rzi[z];
3559 npoints2++;
3560 }
3561 if ((zsgn^zzsgn) < 0)
3562 {
3563 t = divscale30(zsgn,zsgn-zzsgn);
3564 rxi2[npoints2] = rxi[z] + mulscale30(t,rxi[zz]-rxi[z]);
3565 ryi2[npoints2] = ryi[z] + mulscale30(t,ryi[zz]-ryi[z]);
3566 rzi2[npoints2] = rzi[z] + mulscale30(t,rzi[zz]-rzi[z]);
3567 npoints2++;
3568 }
3569 }
3570 if (npoints2 <= 2) return;
3571
3572 //Clip edge 4
3573 npoints = 0;
3574 zzsgn = ryi2[0]*halfxdimen + (rzi2[0]*(globalhoriz-ydimen));
3575 for(z=0;z<npoints2;z++)
3576 {
3577 zz = z+1; if (zz == npoints2) zz = 0;
3578 zsgn = zzsgn; zzsgn = ryi2[zz]*halfxdimen + (rzi2[zz]*(globalhoriz-ydimen));
3579 if (zsgn <= 0)
3580 {
3581 rxi[npoints] = rxi2[z];
3582 ryi[npoints] = ryi2[z];
3583 rzi[npoints] = rzi2[z];
3584 npoints++;
3585 }
3586 if ((zsgn^zzsgn) < 0)
3587 {
3588 t = divscale30(zsgn,zsgn-zzsgn);
3589 rxi[npoints] = rxi2[z] + mulscale30(t,rxi2[zz]-rxi2[z]);
3590 ryi[npoints] = ryi2[z] + mulscale30(t,ryi2[zz]-ryi2[z]);
3591 rzi[npoints] = rzi2[z] + mulscale30(t,rzi2[zz]-rzi2[z]);
3592 npoints++;
3593 }
3594 }
3595 if (npoints <= 2) return;
3596
3597 //Project onto screen
3598 lpoint = -1; lmax = 0x7fffffff;
3599 rpoint = -1; rmax = 0x80000000;
3600 for(z=0;z<npoints;z++)
3601 {
3602 xsi[z] = scale(rxi[z],xdimen<<15,rzi[z]) + (xdimen<<15);
3603 ysi[z] = scale(ryi[z],xdimen<<15,rzi[z]) + (globalhoriz<<16);
3604 if (xsi[z] < 0) xsi[z] = 0;
3605 if (xsi[z] > (xdimen<<16)) xsi[z] = (xdimen<<16);
3606 if (ysi[z] < ((int)0<<16)) ysi[z] = ((int)0<<16);
3607 if (ysi[z] > ((int)ydimen<<16)) ysi[z] = ((int)ydimen<<16);
3608 if (xsi[z] < lmax) lmax = xsi[z], lpoint = z;
3609 if (xsi[z] > rmax) rmax = xsi[z], rpoint = z;
3610 }
3611
3612 //Get uwall arrays
3613 for(z=lpoint;z!=rpoint;z=zz)
3614 {
3615 zz = z+1; if (zz == npoints) zz = 0;
3616
3617 dax1 = ((xsi[z]+65535)>>16);
3618 dax2 = ((xsi[zz]+65535)>>16);
3619 if (dax2 > dax1)
3620 {
3621 yinc = divscale16(ysi[zz]-ysi[z],xsi[zz]-xsi[z]);
3622 y = ysi[z] + mulscale16((dax1<<16)-xsi[z],yinc);
3623 qinterpolatedown16short(&uwall[dax1],dax2-dax1,y,yinc);
3624 }
3625 }
3626
3627 //Get dwall arrays
3628 for(;z!=lpoint;z=zz)
3629 {
3630 zz = z+1; if (zz == npoints) zz = 0;
3631
3632 dax1 = ((xsi[zz]+65535)>>16);
3633 dax2 = ((xsi[z]+65535)>>16);
3634 if (dax2 > dax1)
3635 {
3636 yinc = divscale16(ysi[zz]-ysi[z],xsi[zz]-xsi[z]);
3637 y = ysi[zz] + mulscale16((dax1<<16)-xsi[zz],yinc);
3638 qinterpolatedown16short(&dwall[dax1],dax2-dax1,y,yinc);
3639 }
3640 }
3641
3642
3643 lx = ((lmax+65535)>>16);
3644 rx = ((rmax+65535)>>16);
3645 for(x=lx;x<=rx;x++)
3646 {
3647 uwall[x] = max(uwall[x],startumost[x+windowx1]-windowy1);
3648 dwall[x] = min(dwall[x],startdmost[x+windowx1]-windowy1);
3649 }
3650
3651 //Additional uwall/dwall clipping goes here
3652 for(i=smostwallcnt-1;i>=0;i--)
3653 {
3654 j = smostwall[i];
3655 if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
3656 if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
3657
3658 //if (spritewallfront(tspr,thewall[j]) == 0)
3659 x = thewall[j]; xp1 = wall[x].x; yp1 = wall[x].y;
3660 x = wall[x].point2; xp2 = wall[x].x; yp2 = wall[x].y;
3661 x = (xp2-xp1)*(tspr->y-yp1)-(tspr->x-xp1)*(yp2-yp1);
3662 if ((yp > yb1[j]) && (yp > yb2[j])) x = -1;
3663 if ((x >= 0) && ((x != 0) || (wall[thewall[j]].nextsector != tspr->sectnum))) continue;
3664
3665 dalx2 = max(xb1[j],lx); darx2 = min(xb2[j],rx);
3666
3667 switch(smostwalltype[i])
3668 {
3669 case 0:
3670 if (dalx2 <= darx2)
3671 {
3672 if ((dalx2 == lx) && (darx2 == rx)) return;
3673 //clearbufbyte(&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
3674 for (x=dalx2; x<=darx2; x++) dwall[x] = 0;
3675 }
3676 break;
3677 case 1:
3678 k = smoststart[i] - xb1[j];
3679 for(x=dalx2;x<=darx2;x++)
3680 if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
3681 break;
3682 case 2:
3683 k = smoststart[i] - xb1[j];
3684 for(x=dalx2;x<=darx2;x++)
3685 if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
3686 break;
3687 }
3688 }
3689
3690 //sprite
3691 if ((searchit >= 1) && (searchx >= lx) && (searchx <= rx))
3692 if ((searchy >= uwall[searchx]) && (searchy <= dwall[searchx]))
3693 {
3694 searchsector = sectnum; searchwall = spritenum;
3695 searchstat = 3; searchit = 1;
3696 }
3697
3698 globalorientation = cstat;
3699 globalpicnum = tilenum;
3700 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
3701 //if (picanm[globalpicnum]&192) globalpicnum += animateoffs((short)globalpicnum,spritenum+32768);
3702
3703 if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
3704 setgotpic(globalpicnum);
3705 globalbufplc = waloff[globalpicnum];
3706
3707 globvis = mulscale16(globalhisibility,viewingrange);
3708 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
3709
3710 x = picsiz[globalpicnum]; y = ((x>>4)&15); x &= 15;
3711 if (pow2long[x] != xspan)
3712 {
3713 x++;
3714 globalx1 = mulscale(globalx1,xspan,x);
3715 globalx2 = mulscale(globalx2,xspan,x);
3716 }
3717
3718 dax = globalxpanning; day = globalypanning;
3719 globalxpanning = -dmulscale6(globalx1,day,globalx2,dax);
3720 globalypanning = -dmulscale6(globaly1,day,globaly2,dax);
3721
3722 globalx2 = mulscale16(globalx2,viewingrange);
3723 globaly2 = mulscale16(globaly2,viewingrange);
3724 globalzd = mulscale16(globalzd,viewingrangerecip);
3725
3726 globalx1 = (globalx1-globalx2)*halfxdimen;
3727 globaly1 = (globaly1-globaly2)*halfxdimen;
3728
3729 if ((cstat&2) == 0)
3730 msethlineshift(x,y);
3731 else
3732 tsethlineshift(x,y);
3733
3734 //Draw it!
3735 ceilspritescan(lx,rx-1);
3736 }
3737 else if ((cstat&48) == 48)
3738 {
3739 int nxrepeat, nyrepeat;
3740
3741 lx = 0; rx = xdim-1;
3742 for(x=lx;x<=rx;x++)
3743 {
3744 lwall[x] = (int)startumost[x+windowx1]-windowy1;
3745 swall[x] = (int)startdmost[x+windowx1]-windowy1;
3746 }
3747 for(i=smostwallcnt-1;i>=0;i--)
3748 {
3749 j = smostwall[i];
3750 if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
3751 if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
3752 if (spritewallfront(tspr,(int)thewall[j]) && ((yp <= yb1[j]) || (yp <= yb2[j]))) continue;
3753
3754 dalx2 = max(xb1[j],lx); darx2 = min(xb2[j],rx);
3755
3756 switch(smostwalltype[i])
3757 {
3758 case 0:
3759 if (dalx2 <= darx2)
3760 {
3761 if ((dalx2 == lx) && (darx2 == rx)) return;
3762 //clearbufbyte(&swall[dalx2],(darx2-dalx2+1)*sizeof(swall[0]),0L);
3763 for (x=dalx2; x<=darx2; x++) swall[x] = 0;
3764 }
3765 break;
3766 case 1:
3767 k = smoststart[i] - xb1[j];
3768 for(x=dalx2;x<=darx2;x++)
3769 if (smost[k+x] > lwall[x]) lwall[x] = smost[k+x];
3770 break;
3771 case 2:
3772 k = smoststart[i] - xb1[j];
3773 for(x=dalx2;x<=darx2;x++)
3774 if (smost[k+x] < swall[x]) swall[x] = smost[k+x];
3775 break;
3776 }
3777 }
3778
3779 if (lwall[rx] >= swall[rx])
3780 {
3781 for(x=lx;x<rx;x++)
3782 if (lwall[x] < swall[x]) break;
3783 if (x == rx) return;
3784 }
3785
3786 for(i=0;i<MAXVOXMIPS;i++)
3787 if (!voxoff[vtilenum][i])
3788 {
3789 kloadvoxel(vtilenum);
3790 break;
3791 }
3792
3793 longptr = (int *)voxoff[vtilenum][0];
3794
3795 if (voxscale[vtilenum] == 65536)
3796 {
3797 nxrepeat = (((int)tspr->xrepeat)<<16);
3798 nyrepeat = (((int)tspr->yrepeat)<<16);
3799 }
3800 else
3801 {
3802 nxrepeat = ((int)tspr->xrepeat)*voxscale[vtilenum];
3803 nyrepeat = ((int)tspr->yrepeat)*voxscale[vtilenum];
3804 }
3805
3806 if (!(cstat&128)) tspr->z -= mulscale22(B_LITTLE32(longptr[5]),nyrepeat);
3807 yoff = (int)((signed char)((picanm[sprite[tspr->owner].picnum]>>16)&255))+((int)tspr->yoffset);
3808 tspr->z -= mulscale14(yoff,nyrepeat);
3809
3810 globvis = globalvisibility;
3811 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
3812
3813 if ((searchit >= 1) && (yp > (4<<8)) && (searchy >= lwall[searchx]) && (searchy < swall[searchx]))
3814 {
3815 siz = divscale19(xdimenscale,yp);
3816
3817 xv = mulscale16(nxrepeat,xyaspect);
3818
3819 xspan = ((B_LITTLE32(longptr[0])+B_LITTLE32(longptr[1]))>>1);
3820 yspan = B_LITTLE32(longptr[2]);
3821 xsiz = mulscale30(siz,xv*xspan);
3822 ysiz = mulscale30(siz,nyrepeat*yspan);
3823
3824 //Watch out for divscale overflow
3825 if (((xspan>>11) < xsiz) && (yspan < (ysiz>>1)))
3826 {
3827 x1 = xb-(xsiz>>1);
3828 if (xspan&1) x1 += mulscale31(siz,xv); //Odd xspans
3829 i = mulscale30(siz,xv*xoff);
3830 if ((cstat&4) == 0) x1 -= i; else x1 += i;
3831
3832 y1 = mulscale16(tspr->z-globalposz,siz);
3833 //y1 -= mulscale30(siz,nyrepeat*yoff);
3834 y1 += (globalhoriz<<8)-ysiz;
3835 //if (cstat&128) //Already fixed up above
3836 y1 += (ysiz>>1);
3837
3838 x2 = x1+xsiz-1;
3839 y2 = y1+ysiz-1;
3840 if (((y1|255) < (y2|255)) && (searchx >= (x1>>8)+1) && (searchx <= (x2>>8)))
3841 {
3842 if ((sec->ceilingstat&3) == 0)
3843 startum = globalhoriz+mulscale24(siz,sec->ceilingz-globalposz)-1;
3844 else
3845 startum = 0;
3846 if ((sec->floorstat&3) == 0)
3847 startdm = globalhoriz+mulscale24(siz,sec->floorz-globalposz)+1;
3848 else
3849 startdm = 0x7fffffff;
3850
3851 //sprite
3852 if ((searchy >= max(startum,(y1>>8))) && (searchy < min(startdm,(y2>>8))))
3853 {
3854 searchsector = sectnum; searchwall = spritenum;
3855 searchstat = 3; searchit = 1;
3856 }
3857 }
3858 }
3859 }
3860
3861 i = (int)tspr->ang+1536;
3862 #if USE_POLYMOST && USE_OPENGL
3863 i += spriteext[tspr->owner].angoff;
3864 #endif
3865 drawvox(tspr->x,tspr->y,tspr->z,i,(int)tspr->xrepeat,(int)tspr->yrepeat,vtilenum,tspr->shade,tspr->pal,lwall,swall);
3866 }
3867
3868 if (automapping == 1) show2dsprite[spritenum>>3] |= pow2char[spritenum&7];
3869 }
3870
3871
3872 //
3873 // drawmaskwall (internal)
3874 //
drawmaskwall(short damaskwallcnt)3875 static void drawmaskwall(short damaskwallcnt)
3876 {
3877 int i, j, k, x, z, sectnum, z1, z2, lx, rx;
3878 sectortype *sec, *nsec;
3879 walltype *wal;
3880
3881 //============================================================================= //POLYMOST BEGINS
3882 #if USE_POLYMOST
3883 if (rendmode) { polymost_drawmaskwall(damaskwallcnt); return; }
3884 #endif
3885 //============================================================================= //POLYMOST ENDS
3886
3887 z = maskwall[damaskwallcnt];
3888 wal = &wall[thewall[z]];
3889 sectnum = thesector[z]; sec = §or[sectnum];
3890 nsec = §or[wal->nextsector];
3891 z1 = max(nsec->ceilingz,sec->ceilingz);
3892 z2 = min(nsec->floorz,sec->floorz);
3893
3894 wallmost(uwall,z,sectnum,(char)0);
3895 wallmost(uplc,z,(int)wal->nextsector,(char)0);
3896 for(x=xb1[z];x<=xb2[z];x++) if (uplc[x] > uwall[x]) uwall[x] = uplc[x];
3897 wallmost(dwall,z,sectnum,(char)1);
3898 wallmost(dplc,z,(int)wal->nextsector,(char)1);
3899 for(x=xb1[z];x<=xb2[z];x++) if (dplc[x] < dwall[x]) dwall[x] = dplc[x];
3900 prepwall(z,wal);
3901
3902 globalorientation = (int)wal->cstat;
3903 globalpicnum = wal->overpicnum;
3904 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
3905 globalxpanning = (int)wal->xpanning;
3906 globalypanning = (int)wal->ypanning;
3907 if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)thewall[z]+16384);
3908 globalshade = (int)wal->shade;
3909 globvis = globalvisibility;
3910 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
3911 globalpal = (int)wal->pal;
3912 if (palookup[globalpal] == 0) globalpal = 0;
3913 globalshiftval = (picsiz[globalpicnum]>>4);
3914 if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
3915 globalshiftval = 32-globalshiftval;
3916 globalyscale = (wal->yrepeat<<(globalshiftval-19));
3917 if ((globalorientation&4) == 0)
3918 globalzd = (((globalposz-z1)*globalyscale)<<8);
3919 else
3920 globalzd = (((globalposz-z2)*globalyscale)<<8);
3921 globalzd += (globalypanning<<24);
3922 if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
3923
3924 for(i=smostwallcnt-1;i>=0;i--)
3925 {
3926 j = smostwall[i];
3927 if ((xb1[j] > xb2[z]) || (xb2[j] < xb1[z])) continue;
3928 if (wallfront(j,z)) continue;
3929
3930 lx = max(xb1[j],xb1[z]); rx = min(xb2[j],xb2[z]);
3931
3932 switch(smostwalltype[i])
3933 {
3934 case 0:
3935 if (lx <= rx)
3936 {
3937 if ((lx == xb1[z]) && (rx == xb2[z])) return;
3938 //clearbufbyte(&dwall[lx],(rx-lx+1)*sizeof(dwall[0]),0L);
3939 for (x=lx; x<=rx; x++) dwall[x] = 0;
3940 }
3941 break;
3942 case 1:
3943 k = smoststart[i] - xb1[j];
3944 for(x=lx;x<=rx;x++)
3945 if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
3946 break;
3947 case 2:
3948 k = smoststart[i] - xb1[j];
3949 for(x=lx;x<=rx;x++)
3950 if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
3951 break;
3952 }
3953 }
3954
3955 //maskwall
3956 if ((searchit >= 1) && (searchx >= xb1[z]) && (searchx <= xb2[z]))
3957 if ((searchy >= uwall[searchx]) && (searchy <= dwall[searchx]))
3958 {
3959 searchsector = sectnum; searchwall = thewall[z];
3960 searchstat = 4; searchit = 1;
3961 }
3962
3963 if ((globalorientation&128) == 0)
3964 maskwallscan(xb1[z],xb2[z],uwall,dwall,swall,lwall);
3965 else
3966 {
3967 if (globalorientation&128)
3968 {
3969 if (globalorientation&512) settransreverse(); else settransnormal();
3970 }
3971 transmaskwallscan(xb1[z],xb2[z]);
3972 }
3973 }
3974
3975
3976 //
3977 // fillpolygon (internal)
3978 //
fillpolygon(int npoints)3979 static void fillpolygon(int npoints)
3980 {
3981 int z, zz, x1, y1, x2, y2, miny, maxy, y, xinc, cnt;
3982 int ox, oy, bx, by, day1, day2;
3983 intptr_t p;
3984 short *ptr, *ptr2;
3985
3986 #if USE_POLYMOST && USE_OPENGL
3987 if (rendmode == 3) { polymost_fillpolygon(npoints); return; }
3988 #endif
3989
3990 miny = 0x7fffffff; maxy = 0x80000000;
3991 for(z=npoints-1;z>=0;z--)
3992 { y = ry1[z]; miny = min(miny,y); maxy = max(maxy,y); }
3993 miny = (miny>>12); maxy = (maxy>>12);
3994 if (miny < 0) miny = 0;
3995 if (maxy >= ydim) maxy = ydim-1;
3996 ptr = smost; //They're pointers! - watch how you optimize this thing
3997 for(y=miny;y<=maxy;y++)
3998 {
3999 dotp1[y] = ptr; dotp2[y] = ptr+(MAXNODESPERLINE>>1);
4000 ptr += MAXNODESPERLINE;
4001 }
4002
4003 for(z=npoints-1;z>=0;z--)
4004 {
4005 zz = xb1[z];
4006 y1 = ry1[z]; day1 = (y1>>12);
4007 y2 = ry1[zz]; day2 = (y2>>12);
4008 if (day1 != day2)
4009 {
4010 x1 = rx1[z]; x2 = rx1[zz];
4011 xinc = divscale12(x2-x1,y2-y1);
4012 if (day2 > day1)
4013 {
4014 x1 += mulscale12((day1<<12)+4095-y1,xinc);
4015 for(y=day1;y<day2;y++) { *dotp2[y]++ = (x1>>12); x1 += xinc; }
4016 }
4017 else
4018 {
4019 x2 += mulscale12((day2<<12)+4095-y2,xinc);
4020 for(y=day2;y<day1;y++) { *dotp1[y]++ = (x2>>12); x2 += xinc; }
4021 }
4022 }
4023 }
4024
4025 globalx1 = mulscale16(globalx1,xyaspect);
4026 globaly2 = mulscale16(globaly2,xyaspect);
4027
4028 oy = miny+1-(ydim>>1);
4029 globalposx += oy*globalx1;
4030 globalposy += oy*globaly2;
4031
4032 setuphlineasm4(asm1,asm2);
4033
4034 ptr = smost;
4035 for(y=miny;y<=maxy;y++)
4036 {
4037 cnt = dotp1[y]-ptr; ptr2 = ptr+(MAXNODESPERLINE>>1);
4038 for(z=cnt-1;z>=0;z--)
4039 {
4040 day1 = 0; day2 = 0;
4041 for(zz=z;zz>0;zz--)
4042 {
4043 if (ptr[zz] < ptr[day1]) day1 = zz;
4044 if (ptr2[zz] < ptr2[day2]) day2 = zz;
4045 }
4046 x1 = ptr[day1]; ptr[day1] = ptr[z];
4047 x2 = ptr2[day2]-1; ptr2[day2] = ptr2[z];
4048 if (x1 > x2) continue;
4049
4050 if (globalpolytype < 1)
4051 {
4052 //maphline
4053 ox = x2+1-(xdim>>1);
4054 bx = ox*asm1 + globalposx;
4055 by = ox*asm2 - globalposy;
4056
4057 p = ylookup[y]+x2+frameplace;
4058 hlineasm4(x2-x1,-1L,globalshade<<8,by,bx,(void *)p);
4059 }
4060 else
4061 {
4062 //maphline
4063 ox = x1+1-(xdim>>1);
4064 bx = ox*asm1 + globalposx;
4065 by = ox*asm2 - globalposy;
4066
4067 p = ylookup[y]+x1+frameplace;
4068 if (globalpolytype == 1)
4069 mhline((void *)globalbufplc,bx,(x2-x1)<<16,0L,by,(void *)p);
4070 else
4071 {
4072 thline((void *)globalbufplc,bx,(x2-x1)<<16,0L,by,(void *)p);
4073 }
4074 }
4075 }
4076 globalposx += globalx1;
4077 globalposy += globaly2;
4078 ptr += MAXNODESPERLINE;
4079 }
4080 faketimerhandler();
4081 }
4082
4083
4084 //
4085 // clippoly (internal)
4086 //
clippoly(int npoints,int clipstat)4087 static int clippoly(int npoints, int clipstat)
4088 {
4089 int z, zz, s1, s2, t, npoints2, start2, z1, z2, z3, z4, splitcnt;
4090 int cx1, cy1, cx2, cy2;
4091
4092 cx1 = windowx1;
4093 cy1 = windowy1;
4094 cx2 = windowx2+1;
4095 cy2 = windowy2+1;
4096 cx1 <<= 12; cy1 <<= 12; cx2 <<= 12; cy2 <<= 12;
4097
4098 if (clipstat&0xa) //Need to clip top or left
4099 {
4100 npoints2 = 0; start2 = 0; z = 0; splitcnt = 0;
4101 do
4102 {
4103 s2 = cx1-rx1[z];
4104 do
4105 {
4106 zz = xb1[z]; xb1[z] = -1;
4107 s1 = s2; s2 = cx1-rx1[zz];
4108 if (s1 < 0)
4109 {
4110 rx2[npoints2] = rx1[z]; ry2[npoints2] = ry1[z];
4111 xb2[npoints2] = npoints2+1; npoints2++;
4112 }
4113 if ((s1^s2) < 0)
4114 {
4115 rx2[npoints2] = rx1[z]+scale(rx1[zz]-rx1[z],s1,s1-s2);
4116 ry2[npoints2] = ry1[z]+scale(ry1[zz]-ry1[z],s1,s1-s2);
4117 if (s1 < 0) p2[splitcnt++] = npoints2;
4118 xb2[npoints2] = npoints2+1;
4119 npoints2++;
4120 }
4121 z = zz;
4122 } while (xb1[z] >= 0);
4123
4124 if (npoints2 >= start2+3)
4125 xb2[npoints2-1] = start2, start2 = npoints2;
4126 else
4127 npoints2 = start2;
4128
4129 z = 1;
4130 while ((z < npoints) && (xb1[z] < 0)) z++;
4131 } while (z < npoints);
4132 if (npoints2 <= 2) return(0);
4133
4134 for(z=1;z<splitcnt;z++)
4135 for(zz=0;zz<z;zz++)
4136 {
4137 z1 = p2[z]; z2 = xb2[z1]; z3 = p2[zz]; z4 = xb2[z3];
4138 s1 = klabs(rx2[z1]-rx2[z2])+klabs(ry2[z1]-ry2[z2]);
4139 s1 += klabs(rx2[z3]-rx2[z4])+klabs(ry2[z3]-ry2[z4]);
4140 s2 = klabs(rx2[z1]-rx2[z4])+klabs(ry2[z1]-ry2[z4]);
4141 s2 += klabs(rx2[z3]-rx2[z2])+klabs(ry2[z3]-ry2[z2]);
4142 if (s2 < s1)
4143 { t = xb2[p2[z]]; xb2[p2[z]] = xb2[p2[zz]]; xb2[p2[zz]] = t; }
4144 }
4145
4146
4147 npoints = 0; start2 = 0; z = 0; splitcnt = 0;
4148 do
4149 {
4150 s2 = cy1-ry2[z];
4151 do
4152 {
4153 zz = xb2[z]; xb2[z] = -1;
4154 s1 = s2; s2 = cy1-ry2[zz];
4155 if (s1 < 0)
4156 {
4157 rx1[npoints] = rx2[z]; ry1[npoints] = ry2[z];
4158 xb1[npoints] = npoints+1; npoints++;
4159 }
4160 if ((s1^s2) < 0)
4161 {
4162 rx1[npoints] = rx2[z]+scale(rx2[zz]-rx2[z],s1,s1-s2);
4163 ry1[npoints] = ry2[z]+scale(ry2[zz]-ry2[z],s1,s1-s2);
4164 if (s1 < 0) p2[splitcnt++] = npoints;
4165 xb1[npoints] = npoints+1;
4166 npoints++;
4167 }
4168 z = zz;
4169 } while (xb2[z] >= 0);
4170
4171 if (npoints >= start2+3)
4172 xb1[npoints-1] = start2, start2 = npoints;
4173 else
4174 npoints = start2;
4175
4176 z = 1;
4177 while ((z < npoints2) && (xb2[z] < 0)) z++;
4178 } while (z < npoints2);
4179 if (npoints <= 2) return(0);
4180
4181 for(z=1;z<splitcnt;z++)
4182 for(zz=0;zz<z;zz++)
4183 {
4184 z1 = p2[z]; z2 = xb1[z1]; z3 = p2[zz]; z4 = xb1[z3];
4185 s1 = klabs(rx1[z1]-rx1[z2])+klabs(ry1[z1]-ry1[z2]);
4186 s1 += klabs(rx1[z3]-rx1[z4])+klabs(ry1[z3]-ry1[z4]);
4187 s2 = klabs(rx1[z1]-rx1[z4])+klabs(ry1[z1]-ry1[z4]);
4188 s2 += klabs(rx1[z3]-rx1[z2])+klabs(ry1[z3]-ry1[z2]);
4189 if (s2 < s1)
4190 { t = xb1[p2[z]]; xb1[p2[z]] = xb1[p2[zz]]; xb1[p2[zz]] = t; }
4191 }
4192 }
4193 if (clipstat&0x5) //Need to clip bottom or right
4194 {
4195 npoints2 = 0; start2 = 0; z = 0; splitcnt = 0;
4196 do
4197 {
4198 s2 = rx1[z]-cx2;
4199 do
4200 {
4201 zz = xb1[z]; xb1[z] = -1;
4202 s1 = s2; s2 = rx1[zz]-cx2;
4203 if (s1 < 0)
4204 {
4205 rx2[npoints2] = rx1[z]; ry2[npoints2] = ry1[z];
4206 xb2[npoints2] = npoints2+1; npoints2++;
4207 }
4208 if ((s1^s2) < 0)
4209 {
4210 rx2[npoints2] = rx1[z]+scale(rx1[zz]-rx1[z],s1,s1-s2);
4211 ry2[npoints2] = ry1[z]+scale(ry1[zz]-ry1[z],s1,s1-s2);
4212 if (s1 < 0) p2[splitcnt++] = npoints2;
4213 xb2[npoints2] = npoints2+1;
4214 npoints2++;
4215 }
4216 z = zz;
4217 } while (xb1[z] >= 0);
4218
4219 if (npoints2 >= start2+3)
4220 xb2[npoints2-1] = start2, start2 = npoints2;
4221 else
4222 npoints2 = start2;
4223
4224 z = 1;
4225 while ((z < npoints) && (xb1[z] < 0)) z++;
4226 } while (z < npoints);
4227 if (npoints2 <= 2) return(0);
4228
4229 for(z=1;z<splitcnt;z++)
4230 for(zz=0;zz<z;zz++)
4231 {
4232 z1 = p2[z]; z2 = xb2[z1]; z3 = p2[zz]; z4 = xb2[z3];
4233 s1 = klabs(rx2[z1]-rx2[z2])+klabs(ry2[z1]-ry2[z2]);
4234 s1 += klabs(rx2[z3]-rx2[z4])+klabs(ry2[z3]-ry2[z4]);
4235 s2 = klabs(rx2[z1]-rx2[z4])+klabs(ry2[z1]-ry2[z4]);
4236 s2 += klabs(rx2[z3]-rx2[z2])+klabs(ry2[z3]-ry2[z2]);
4237 if (s2 < s1)
4238 { t = xb2[p2[z]]; xb2[p2[z]] = xb2[p2[zz]]; xb2[p2[zz]] = t; }
4239 }
4240
4241
4242 npoints = 0; start2 = 0; z = 0; splitcnt = 0;
4243 do
4244 {
4245 s2 = ry2[z]-cy2;
4246 do
4247 {
4248 zz = xb2[z]; xb2[z] = -1;
4249 s1 = s2; s2 = ry2[zz]-cy2;
4250 if (s1 < 0)
4251 {
4252 rx1[npoints] = rx2[z]; ry1[npoints] = ry2[z];
4253 xb1[npoints] = npoints+1; npoints++;
4254 }
4255 if ((s1^s2) < 0)
4256 {
4257 rx1[npoints] = rx2[z]+scale(rx2[zz]-rx2[z],s1,s1-s2);
4258 ry1[npoints] = ry2[z]+scale(ry2[zz]-ry2[z],s1,s1-s2);
4259 if (s1 < 0) p2[splitcnt++] = npoints;
4260 xb1[npoints] = npoints+1;
4261 npoints++;
4262 }
4263 z = zz;
4264 } while (xb2[z] >= 0);
4265
4266 if (npoints >= start2+3)
4267 xb1[npoints-1] = start2, start2 = npoints;
4268 else
4269 npoints = start2;
4270
4271 z = 1;
4272 while ((z < npoints2) && (xb2[z] < 0)) z++;
4273 } while (z < npoints2);
4274 if (npoints <= 2) return(0);
4275
4276 for(z=1;z<splitcnt;z++)
4277 for(zz=0;zz<z;zz++)
4278 {
4279 z1 = p2[z]; z2 = xb1[z1]; z3 = p2[zz]; z4 = xb1[z3];
4280 s1 = klabs(rx1[z1]-rx1[z2])+klabs(ry1[z1]-ry1[z2]);
4281 s1 += klabs(rx1[z3]-rx1[z4])+klabs(ry1[z3]-ry1[z4]);
4282 s2 = klabs(rx1[z1]-rx1[z4])+klabs(ry1[z1]-ry1[z4]);
4283 s2 += klabs(rx1[z3]-rx1[z2])+klabs(ry1[z3]-ry1[z2]);
4284 if (s2 < s1)
4285 { t = xb1[p2[z]]; xb1[p2[z]] = xb1[p2[zz]]; xb1[p2[zz]] = t; }
4286 }
4287 }
4288 return(npoints);
4289 }
4290
4291
4292 //
4293 // clippoly4 (internal)
4294 //
4295 //Assume npoints=4 with polygon on &nrx1,&nry1
4296 //JBF 20031206: Thanks to Ken's hunting, s/(rx1|ry1|rx2|ry2)/n\1/ in this function
clippoly4(int cx1,int cy1,int cx2,int cy2)4297 static int clippoly4(int cx1, int cy1, int cx2, int cy2)
4298 {
4299 int n, nn, z, zz, x, x1, x2, y, y1, y2, t;
4300
4301 nn = 0; z = 0;
4302 do
4303 {
4304 zz = ((z+1)&3);
4305 x1 = nrx1[z]; x2 = nrx1[zz]-x1;
4306
4307 if ((cx1 <= x1) && (x1 <= cx2))
4308 nrx2[nn] = x1, nry2[nn] = nry1[z], nn++;
4309
4310 if (x2 <= 0) x = cx2; else x = cx1;
4311 t = x-x1;
4312 if (((t-x2)^t) < 0)
4313 nrx2[nn] = x, nry2[nn] = nry1[z]+scale(t,nry1[zz]-nry1[z],x2), nn++;
4314
4315 if (x2 <= 0) x = cx1; else x = cx2;
4316 t = x-x1;
4317 if (((t-x2)^t) < 0)
4318 nrx2[nn] = x, nry2[nn] = nry1[z]+scale(t,nry1[zz]-nry1[z],x2), nn++;
4319
4320 z = zz;
4321 } while (z != 0);
4322 if (nn < 3) return(0);
4323
4324 n = 0; z = 0;
4325 do
4326 {
4327 zz = z+1; if (zz == nn) zz = 0;
4328 y1 = nry2[z]; y2 = nry2[zz]-y1;
4329
4330 if ((cy1 <= y1) && (y1 <= cy2))
4331 nry1[n] = y1, nrx1[n] = nrx2[z], n++;
4332
4333 if (y2 <= 0) y = cy2; else y = cy1;
4334 t = y-y1;
4335 if (((t-y2)^t) < 0)
4336 nry1[n] = y, nrx1[n] = nrx2[z]+scale(t,nrx2[zz]-nrx2[z],y2), n++;
4337
4338 if (y2 <= 0) y = cy1; else y = cy2;
4339 t = y-y1;
4340 if (((t-y2)^t) < 0)
4341 nry1[n] = y, nrx1[n] = nrx2[z]+scale(t,nrx2[zz]-nrx2[z],y2), n++;
4342
4343 z = zz;
4344 } while (z != 0);
4345 return(n);
4346 }
4347
4348
4349 //
4350 // dorotatesprite (internal)
4351 //
4352 //JBF 20031206: Thanks to Ken's hunting, s/(rx1|ry1|rx2|ry2)/n\1/ in this function
dorotatesprite(int sx,int sy,int z,short a,short picnum,signed char dashade,unsigned char dapalnum,unsigned char dastat,int cx1,int cy1,int cx2,int cy2,int uniqid)4353 static void dorotatesprite(int sx, int sy, int z, short a, short picnum, signed char dashade,
4354 unsigned char dapalnum, unsigned char dastat, int cx1, int cy1, int cx2, int cy2, int uniqid)
4355 {
4356 int cosang, sinang, v, nextv, dax1, dax2, oy, bx, by, ny1, ny2;
4357 int x, y, x1, y1, x2, y2, gx1, gy1;
4358 intptr_t i, p, bufplc, palookupoffs;
4359 int xsiz, ysiz, xoff, yoff, npoints, yplc, yinc, lx, rx, xx, xend;
4360 int xv, yv, xv2, yv2, obuffermode, qlinemode=0, y1ve[4], y2ve[4], u4, d4;
4361 char bad;
4362
4363 //============================================================================= //POLYMOST BEGINS
4364 #if USE_POLYMOST
4365 if (rendmode) { polymost_dorotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,cx1,cy1,cx2,cy2,uniqid); return; }
4366 #endif
4367 //============================================================================= //POLYMOST ENDS
4368
4369 if (cx1 < 0) cx1 = 0;
4370 if (cy1 < 0) cy1 = 0;
4371 if (cx2 > xres-1) cx2 = xres-1;
4372 if (cy2 > yres-1) cy2 = yres-1;
4373
4374 xsiz = tilesizx[picnum]; ysiz = tilesizy[picnum];
4375 if (dastat&16) { xoff = 0; yoff = 0; }
4376 else
4377 {
4378 xoff = (int)((signed char)((picanm[picnum]>>8)&255))+(xsiz>>1);
4379 yoff = (int)((signed char)((picanm[picnum]>>16)&255))+(ysiz>>1);
4380 }
4381
4382 if (dastat&4) yoff = ysiz-yoff;
4383
4384 cosang = sintable[(a+512)&2047]; sinang = sintable[a&2047];
4385
4386 if ((dastat&2) != 0) //Auto window size scaling
4387 {
4388 if ((dastat&8) == 0)
4389 {
4390 if (widescreen) {
4391 x = ydimenscale; //= scale(xdimen,yxaspect,320);
4392 sx = ((cx1+cx2+2)<<15)+scale(sx-(320<<15),ydimen<<16,200*pixelaspect);
4393 } else {
4394 x = xdimenscale; //= scale(xdimen,yxaspect,320);
4395 sx = ((cx1+cx2+2)<<15)+scale(sx-(320<<15),xdimen,320);
4396 }
4397 sy = ((cy1+cy2+2)<<15)+mulscale16(sy-(200<<15),x);
4398 }
4399 else
4400 {
4401 //If not clipping to startmosts, & auto-scaling on, as a
4402 //hard-coded bonus, scale to full screen instead
4403 if (widescreen) {
4404 x = scale(ydim<<16,yxaspect,200*pixelaspect);
4405 sx = (xdim<<15)+32768+scale(sx-(320<<15),ydim<<16,200*pixelaspect);
4406 } else {
4407 x = scale(xdim,yxaspect,320);
4408 sx = (xdim<<15)+32768+scale(sx-(320<<15),xdim,320);
4409 }
4410 sy = (ydim<<15)+32768+mulscale16(sy-(200<<15),x);
4411 }
4412 z = mulscale16(z,x);
4413 }
4414
4415 xv = mulscale14(cosang,z);
4416 yv = mulscale14(sinang,z);
4417 if (((dastat&2) != 0) || ((dastat&8) == 0)) //Don't aspect unscaled perms
4418 {
4419 xv2 = mulscale16(xv,xyaspect);
4420 yv2 = mulscale16(yv,xyaspect);
4421 }
4422 else
4423 {
4424 xv2 = xv;
4425 yv2 = yv;
4426 }
4427
4428 nry1[0] = sy - (yv*xoff + xv*yoff);
4429 nry1[1] = nry1[0] + yv*xsiz;
4430 nry1[3] = nry1[0] + xv*ysiz;
4431 nry1[2] = nry1[1]+nry1[3]-nry1[0];
4432 i = (cy1<<16); if ((nry1[0]<i) && (nry1[1]<i) && (nry1[2]<i) && (nry1[3]<i)) return;
4433 i = (cy2<<16); if ((nry1[0]>i) && (nry1[1]>i) && (nry1[2]>i) && (nry1[3]>i)) return;
4434
4435 nrx1[0] = sx - (xv2*xoff - yv2*yoff);
4436 nrx1[1] = nrx1[0] + xv2*xsiz;
4437 nrx1[3] = nrx1[0] - yv2*ysiz;
4438 nrx1[2] = nrx1[1]+nrx1[3]-nrx1[0];
4439 i = (cx1<<16); if ((nrx1[0]<i) && (nrx1[1]<i) && (nrx1[2]<i) && (nrx1[3]<i)) return;
4440 i = (cx2<<16); if ((nrx1[0]>i) && (nrx1[1]>i) && (nrx1[2]>i) && (nrx1[3]>i)) return;
4441
4442 gx1 = nrx1[0]; gy1 = nry1[0]; //back up these before clipping
4443
4444 if ((npoints = clippoly4(cx1<<16,cy1<<16,(cx2+1)<<16,(cy2+1)<<16)) < 3) return;
4445
4446 lx = nrx1[0]; rx = nrx1[0];
4447
4448 nextv = 0;
4449 for(v=npoints-1;v>=0;v--)
4450 {
4451 x1 = nrx1[v]; x2 = nrx1[nextv];
4452 dax1 = (x1>>16); if (x1 < lx) lx = x1;
4453 dax2 = (x2>>16); if (x1 > rx) rx = x1;
4454 if (dax1 != dax2)
4455 {
4456 y1 = nry1[v]; y2 = nry1[nextv];
4457 yinc = divscale16(y2-y1,x2-x1);
4458 if (dax2 > dax1)
4459 {
4460 yplc = y1 + mulscale16((dax1<<16)+65535-x1,yinc);
4461 qinterpolatedown16short(&uplc[dax1],dax2-dax1,yplc,yinc);
4462 }
4463 else
4464 {
4465 yplc = y2 + mulscale16((dax2<<16)+65535-x2,yinc);
4466 qinterpolatedown16short(&dplc[dax2],dax1-dax2,yplc,yinc);
4467 }
4468 }
4469 nextv = v;
4470 }
4471
4472 if (waloff[picnum] == 0) loadtile(picnum);
4473 setgotpic(picnum);
4474 bufplc = waloff[picnum];
4475
4476 palookupoffs = (intptr_t)palookup[dapalnum] + (getpalookup(0L,(int)dashade)<<8);
4477
4478 i = divscale32(1L,z);
4479 xv = mulscale14(sinang,i);
4480 yv = mulscale14(cosang,i);
4481 if (((dastat&2) != 0) || ((dastat&8) == 0)) //Don't aspect unscaled perms
4482 {
4483 yv2 = mulscale16(-xv,yxaspect);
4484 xv2 = mulscale16(yv,yxaspect);
4485 }
4486 else
4487 {
4488 yv2 = -xv;
4489 xv2 = yv;
4490 }
4491
4492 x1 = (lx>>16); x2 = (rx>>16);
4493
4494 oy = 0;
4495 x = (x1<<16)-1-gx1; y = (oy<<16)+65535-gy1;
4496 bx = dmulscale16(x,xv2,y,xv);
4497 by = dmulscale16(x,yv2,y,yv);
4498 if (dastat&4) { yv = -yv; yv2 = -yv2; by = (ysiz<<16)-1-by; }
4499
4500 /* if (origbuffermode == 0)
4501 {
4502 if (dastat&128)
4503 {
4504 obuffermode = buffermode;
4505 buffermode = 0;
4506 setactivepage(activepage);
4507 }
4508 }
4509 else if (dastat&8)
4510 permanentupdate = 1; */
4511
4512 #ifndef ENGINE_USING_A_C
4513
4514 if ((dastat&1) == 0)
4515 {
4516 if (((a&1023) == 0) && (ysiz <= 256)) //vlineasm4 has 256 high limit!
4517 {
4518 if (dastat&64) setupvlineasm(24L); else setupmvlineasm(24L);
4519 by <<= 8; yv <<= 8; yv2 <<= 8;
4520
4521 palookupoffse[0] = palookupoffse[1] = palookupoffse[2] = palookupoffse[3] = palookupoffs;
4522 vince[0] = vince[1] = vince[2] = vince[3] = yv;
4523
4524 for(x=x1;x<x2;x+=4)
4525 {
4526 bad = 15; xend = min(x2-x,4);
4527 for(xx=0;xx<xend;xx++)
4528 {
4529 bx += xv2;
4530
4531 y1 = uplc[x+xx]; y2 = dplc[x+xx];
4532 if ((dastat&8) == 0)
4533 {
4534 if (startumost[x+xx] > y1) y1 = startumost[x+xx];
4535 if (startdmost[x+xx] < y2) y2 = startdmost[x+xx];
4536 }
4537 if (y2 <= y1) continue;
4538
4539 by += yv*(y1-oy); oy = y1;
4540
4541 bufplce[xx] = (bx>>16)*ysiz+bufplc;
4542 vplce[xx] = by;
4543 y1ve[xx] = y1;
4544 y2ve[xx] = y2-1;
4545 bad &= ~pow2char[xx];
4546 }
4547
4548 p = x+frameplace;
4549
4550 u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
4551 d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
4552
4553 if (dastat&64)
4554 {
4555 if ((bad != 0) || (u4 >= d4))
4556 {
4557 if (!(bad&1)) prevlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],(void *)bufplce[0],(void *)(ylookup[y1ve[0]]+p+0));
4558 if (!(bad&2)) prevlineasm1(vince[1],(void *)palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],(void *)bufplce[1],(void *)(ylookup[y1ve[1]]+p+1));
4559 if (!(bad&4)) prevlineasm1(vince[2],(void *)palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],(void *)bufplce[2],(void *)(ylookup[y1ve[2]]+p+2));
4560 if (!(bad&8)) prevlineasm1(vince[3],(void *)palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],(void *)bufplce[3],(void *)(ylookup[y1ve[3]]+p+3));
4561 continue;
4562 }
4563
4564 if (u4 > y1ve[0]) vplce[0] = prevlineasm1(vince[0],(void *)palookupoffse[0],u4-y1ve[0]-1,vplce[0],(void *)bufplce[0],(void *)(ylookup[y1ve[0]]+p+0));
4565 if (u4 > y1ve[1]) vplce[1] = prevlineasm1(vince[1],(void *)palookupoffse[1],u4-y1ve[1]-1,vplce[1],(void *)bufplce[1],(void *)(ylookup[y1ve[1]]+p+1));
4566 if (u4 > y1ve[2]) vplce[2] = prevlineasm1(vince[2],(void *)palookupoffse[2],u4-y1ve[2]-1,vplce[2],(void *)bufplce[2],(void *)(ylookup[y1ve[2]]+p+2));
4567 if (u4 > y1ve[3]) vplce[3] = prevlineasm1(vince[3],(void *)palookupoffse[3],u4-y1ve[3]-1,vplce[3],(void *)bufplce[3],(void *)(ylookup[y1ve[3]]+p+3));
4568
4569 if (d4 >= u4) vlineasm4(d4-u4+1,(void *)(ylookup[u4]+p));
4570
4571 i = p+ylookup[d4+1];
4572 if (y2ve[0] > d4) prevlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-d4-1,vplce[0],(void *)bufplce[0],(void *)(i+0));
4573 if (y2ve[1] > d4) prevlineasm1(vince[1],(void *)palookupoffse[1],y2ve[1]-d4-1,vplce[1],(void *)bufplce[1],(void *)(i+1));
4574 if (y2ve[2] > d4) prevlineasm1(vince[2],(void *)palookupoffse[2],y2ve[2]-d4-1,vplce[2],(void *)bufplce[2],(void *)(i+2));
4575 if (y2ve[3] > d4) prevlineasm1(vince[3],(void *)palookupoffse[3],y2ve[3]-d4-1,vplce[3],(void *)bufplce[3],(void *)(i+3));
4576 }
4577 else
4578 {
4579 if ((bad != 0) || (u4 >= d4))
4580 {
4581 if (!(bad&1)) mvlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],(void *)bufplce[0],(void *)(ylookup[y1ve[0]]+p+0));
4582 if (!(bad&2)) mvlineasm1(vince[1],(void *)palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],(void *)bufplce[1],(void *)(ylookup[y1ve[1]]+p+1));
4583 if (!(bad&4)) mvlineasm1(vince[2],(void *)palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],(void *)bufplce[2],(void *)(ylookup[y1ve[2]]+p+2));
4584 if (!(bad&8)) mvlineasm1(vince[3],(void *)palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],(void *)bufplce[3],(void *)(ylookup[y1ve[3]]+p+3));
4585 continue;
4586 }
4587
4588 if (u4 > y1ve[0]) vplce[0] = mvlineasm1(vince[0],(void *)palookupoffse[0],u4-y1ve[0]-1,vplce[0],(void *)bufplce[0],(void *)(ylookup[y1ve[0]]+p+0));
4589 if (u4 > y1ve[1]) vplce[1] = mvlineasm1(vince[1],(void *)palookupoffse[1],u4-y1ve[1]-1,vplce[1],(void *)bufplce[1],(void *)(ylookup[y1ve[1]]+p+1));
4590 if (u4 > y1ve[2]) vplce[2] = mvlineasm1(vince[2],(void *)palookupoffse[2],u4-y1ve[2]-1,vplce[2],(void *)bufplce[2],(void *)(ylookup[y1ve[2]]+p+2));
4591 if (u4 > y1ve[3]) vplce[3] = mvlineasm1(vince[3],(void *)palookupoffse[3],u4-y1ve[3]-1,vplce[3],(void *)bufplce[3],(void *)(ylookup[y1ve[3]]+p+3));
4592
4593 if (d4 >= u4) mvlineasm4(d4-u4+1,(void *)(ylookup[u4]+p));
4594
4595 i = p+ylookup[d4+1];
4596 if (y2ve[0] > d4) mvlineasm1(vince[0],(void *)palookupoffse[0],y2ve[0]-d4-1,vplce[0],(void *)bufplce[0],(void *)(i+0));
4597 if (y2ve[1] > d4) mvlineasm1(vince[1],(void *)palookupoffse[1],y2ve[1]-d4-1,vplce[1],(void *)bufplce[1],(void *)(i+1));
4598 if (y2ve[2] > d4) mvlineasm1(vince[2],(void *)palookupoffse[2],y2ve[2]-d4-1,vplce[2],(void *)bufplce[2],(void *)(i+2));
4599 if (y2ve[3] > d4) mvlineasm1(vince[3],(void *)palookupoffse[3],y2ve[3]-d4-1,vplce[3],(void *)bufplce[3],(void *)(i+3));
4600 }
4601
4602 faketimerhandler();
4603 }
4604 }
4605 else
4606 {
4607 if (dastat&64)
4608 {
4609 if ((xv2&0x0000ffff) == 0)
4610 {
4611 qlinemode = 1;
4612 setupqrhlineasm4(0L,yv2<<16,(xv2>>16)*ysiz+(yv2>>16),(void *)palookupoffs,0L,0L);
4613 }
4614 else
4615 {
4616 qlinemode = 0;
4617 setuprhlineasm4(xv2<<16,yv2<<16,(xv2>>16)*ysiz+(yv2>>16),(void *)palookupoffs,ysiz,0L);
4618 }
4619 }
4620 else
4621 setuprmhlineasm4(xv2<<16,yv2<<16,(xv2>>16)*ysiz+(yv2>>16),(void *)palookupoffs,ysiz,0L);
4622
4623 y1 = uplc[x1];
4624 if (((dastat&8) == 0) && (startumost[x1] > y1)) y1 = startumost[x1];
4625 y2 = y1;
4626 for(x=x1;x<x2;x++)
4627 {
4628 ny1 = uplc[x]-1; ny2 = dplc[x];
4629 if ((dastat&8) == 0)
4630 {
4631 if (startumost[x]-1 > ny1) ny1 = startumost[x]-1;
4632 if (startdmost[x] < ny2) ny2 = startdmost[x];
4633 }
4634
4635 if (ny1 < ny2-1)
4636 {
4637 if (ny1 >= y2)
4638 {
4639 while (y1 < y2-1)
4640 {
4641 y1++; if ((y1&31) == 0) faketimerhandler();
4642
4643 //x,y1
4644 bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1;
4645 if (dastat&64) {
4646 if (qlinemode) qrhlineasm4(x-lastx[y1],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,0L ,by<<16,(void *)(ylookup[y1]+x+frameplace));
4647 else rhlineasm4(x-lastx[y1],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,bx<<16,by<<16,(void *)(ylookup[y1]+x+frameplace));
4648 } else rmhlineasm4(x-lastx[y1],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,bx<<16,by<<16,(void *)(ylookup[y1]+x+frameplace));
4649 }
4650 y1 = ny1;
4651 }
4652 else
4653 {
4654 while (y1 < ny1)
4655 {
4656 y1++; if ((y1&31) == 0) faketimerhandler();
4657
4658 //x,y1
4659 bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1;
4660 if (dastat&64) {
4661 if (qlinemode) qrhlineasm4(x-lastx[y1],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,0L ,by<<16,(void *)(ylookup[y1]+x+frameplace));
4662 else rhlineasm4(x-lastx[y1],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,bx<<16,by<<16,(void *)(ylookup[y1]+x+frameplace));
4663 } else rmhlineasm4(x-lastx[y1],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,bx<<16,by<<16,(void *)(ylookup[y1]+x+frameplace));
4664 }
4665 while (y1 > ny1) lastx[y1--] = x;
4666 }
4667 while (y2 > ny2)
4668 {
4669 y2--; if ((y2&31) == 0) faketimerhandler();
4670
4671 //x,y2
4672 bx += xv*(y2-oy); by += yv*(y2-oy); oy = y2;
4673 if (dastat&64) {
4674 if (qlinemode) qrhlineasm4(x-lastx[y2],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,0L ,by<<16,(void *)(ylookup[y2]+x+frameplace));
4675 else rhlineasm4(x-lastx[y2],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,bx<<16,by<<16,(void *)(ylookup[y2]+x+frameplace));
4676 } else rmhlineasm4(x-lastx[y2],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,bx<<16,by<<16,(void *)(ylookup[y2]+x+frameplace));
4677 }
4678 while (y2 < ny2) lastx[y2++] = x;
4679 }
4680 else
4681 {
4682 while (y1 < y2-1)
4683 {
4684 y1++; if ((y1&31) == 0) faketimerhandler();
4685
4686 //x,y1
4687 bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1;
4688 if (dastat&64) {
4689 if (qlinemode) qrhlineasm4(x-lastx[y1],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,0L ,by<<16,(void *)(ylookup[y1]+x+frameplace));
4690 else rhlineasm4(x-lastx[y1],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,bx<<16,by<<16,(void *)(ylookup[y1]+x+frameplace));
4691 } else rmhlineasm4(x-lastx[y1],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,bx<<16,by<<16,(void *)(ylookup[y1]+x+frameplace));
4692 }
4693 if (x == x2-1) { bx += xv2; by += yv2; break; }
4694 y1 = uplc[x+1];
4695 if (((dastat&8) == 0) && (startumost[x+1] > y1)) y1 = startumost[x+1];
4696 y2 = y1;
4697 }
4698 bx += xv2; by += yv2;
4699 }
4700 while (y1 < y2-1)
4701 {
4702 y1++; if ((y1&31) == 0) faketimerhandler();
4703
4704 //x2,y1
4705 bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1;
4706 if (dastat&64) {
4707 if (qlinemode) qrhlineasm4(x2-lastx[y1],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,0L,by<<16,(void *)(ylookup[y1]+x2+frameplace));
4708 else rhlineasm4(x2-lastx[y1],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,bx<<16,by<<16,(void *)(ylookup[y1]+x2+frameplace));
4709 } else rmhlineasm4(x2-lastx[y1],(void *)((bx>>16)*ysiz+(by>>16)+bufplc),0L,bx<<16,by<<16,(void *)(ylookup[y1]+x2+frameplace));
4710 }
4711 }
4712 }
4713 else
4714 {
4715 if ((dastat&1) == 0)
4716 {
4717 if (dastat&64)
4718 setupspritevline((void *)palookupoffs,(xv>>16)*ysiz,xv<<16,ysiz,yv,0L);
4719 else
4720 msetupspritevline((void *)palookupoffs,(xv>>16)*ysiz,xv<<16,ysiz,yv,0L);
4721 }
4722 else
4723 {
4724 tsetupspritevline((void *)palookupoffs,(xv>>16)*ysiz,xv<<16,ysiz,yv,0L);
4725 if (dastat&32) settransreverse(); else settransnormal();
4726 }
4727 for(x=x1;x<x2;x++)
4728 {
4729 bx += xv2; by += yv2;
4730
4731 y1 = uplc[x]; y2 = dplc[x];
4732 if ((dastat&8) == 0)
4733 {
4734 if (startumost[x] > y1) y1 = startumost[x];
4735 if (startdmost[x] < y2) y2 = startdmost[x];
4736 }
4737 if (y2 <= y1) continue;
4738
4739 switch(y1-oy)
4740 {
4741 case -1: bx -= xv; by -= yv; oy = y1; break;
4742 case 0: break;
4743 case 1: bx += xv; by += yv; oy = y1; break;
4744 default: bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1; break;
4745 }
4746
4747 p = ylookup[y1]+x+frameplace;
4748
4749 if ((dastat&1) == 0)
4750 {
4751 if (dastat&64)
4752 spritevline(0L,by<<16,y2-y1+1,bx<<16,(void *)((bx>>16)*ysiz+(by>>16)+bufplc),(void *)p);
4753 else
4754 mspritevline(0L,by<<16,y2-y1+1,bx<<16,(void *)((bx>>16)*ysiz+(by>>16)+bufplc),(void *)p);
4755 }
4756 else
4757 {
4758 tspritevline(0L,by<<16,y2-y1+1,bx<<16,(void *)((bx>>16)*ysiz+(by>>16)+bufplc),(void *)p);
4759 }
4760 faketimerhandler();
4761 }
4762 }
4763
4764 #else // ENGINE_USING_A_C
4765
4766 if ((dastat&1) == 0)
4767 {
4768 if (dastat&64)
4769 setupspritevline((void *)palookupoffs,xv,yv,ysiz);
4770 else
4771 msetupspritevline((void *)palookupoffs,xv,yv,ysiz);
4772 }
4773 else
4774 {
4775 tsetupspritevline((void *)palookupoffs,xv,yv,ysiz);
4776 if (dastat&32) settransreverse(); else settransnormal();
4777 }
4778 for(x=x1;x<x2;x++)
4779 {
4780 bx += xv2; by += yv2;
4781
4782 y1 = uplc[x]; y2 = dplc[x];
4783 if ((dastat&8) == 0)
4784 {
4785 if (startumost[x] > y1) y1 = startumost[x];
4786 if (startdmost[x] < y2) y2 = startdmost[x];
4787 }
4788 if (y2 <= y1) continue;
4789
4790 switch(y1-oy)
4791 {
4792 case -1: bx -= xv; by -= yv; oy = y1; break;
4793 case 0: break;
4794 case 1: bx += xv; by += yv; oy = y1; break;
4795 default: bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1; break;
4796 }
4797
4798 p = ylookup[y1]+x+frameplace;
4799
4800 if ((dastat&1) == 0)
4801 {
4802 if (dastat&64)
4803 spritevline(bx&65535,by&65535,y2-y1+1,(void *)((bx>>16)*ysiz+(by>>16)+bufplc),(void *)p);
4804 else
4805 mspritevline(bx&65535,by&65535,y2-y1+1,(void *)((bx>>16)*ysiz+(by>>16)+bufplc),(void *)p);
4806 }
4807 else
4808 {
4809 tspritevline(bx&65535,by&65535,y2-y1+1,(void *)((bx>>16)*ysiz+(by>>16)+bufplc),(void *)p);
4810 //transarea += (y2-y1);
4811 }
4812 faketimerhandler();
4813 }
4814
4815 #endif
4816
4817 /* if ((dastat&128) && (origbuffermode == 0))
4818 {
4819 buffermode = obuffermode;
4820 setactivepage(activepage);
4821 }*/
4822 }
4823
4824
4825 //
4826 // initksqrt (internal)
4827 //
initksqrt(void)4828 static void initksqrt(void)
4829 {
4830 int i, j, k;
4831
4832 j = 1; k = 0;
4833 for(i=0;i<4096;i++)
4834 {
4835 if (i >= j) { j <<= 2; k++; }
4836 sqrtable[i] = (unsigned short)(msqrtasm((i<<18)+131072)<<1);
4837 shlookup[i] = (k<<1)+((10-k)<<8);
4838 if (i < 256) shlookup[i+4096] = ((k+6)<<1)+((10-(k+6))<<8);
4839 }
4840 }
4841
4842
4843 //
4844 // dosetaspect
4845 //
dosetaspect(void)4846 static void dosetaspect(void)
4847 {
4848 int i, j, k, x, xinc,a;
4849
4850 if (xyaspect != oxyaspect)
4851 {
4852 oxyaspect = xyaspect;
4853 j = xyaspect*320;
4854 horizlookup2[horizycent-1] = divscale26(131072,j);
4855 for(i=ydim*4-1;i>=0;i--)
4856 if (i != (horizycent-1))
4857 {
4858 horizlookup[i] = divscale28(1,i-(horizycent-1));
4859 horizlookup2[i] = divscale14(klabs(horizlookup[i]),j);
4860 }
4861 }
4862 if ((xdimen != oxdimen) || (viewingrange != oviewingrange))
4863 {
4864 oxdimen = xdimen;
4865 oviewingrange = viewingrange;
4866 xinc = mulscale32(viewingrange*320,xdimenrecip);
4867 x = (640<<16)-mulscale1(xinc,xdimen);
4868 for(i=0;i<xdimen;i++)
4869 {
4870 j = (x&65535); k = (x>>16); x += xinc;
4871 if (j != 0) j = mulscale16((int)radarang[k+1]-(int)radarang[k],j);
4872 radarang2[i] = (short)(((int)radarang[k]+j)>>6);
4873 }
4874 for(i=1;i<65536;i++) distrecip[i] = divscale20(xdimen,i);
4875 nytooclose = xdimen*2100;
4876 nytoofar = 65536*16384-1048576;
4877 }
4878 }
4879
4880
4881 //
4882 // loadtables (internal)
4883 //
calcbritable(void)4884 static void calcbritable(void)
4885 {
4886 int i,j;
4887 double a,b;
4888 for(i=0;i<16;i++) {
4889 a = (double)8 / ((double)i+8);
4890 b = (double)255 / pow((double)255,a);
4891 for(j=0;j<256;j++) // JBF 20040207: full 8bit precision
4892 britable[i][j] = (unsigned char)(pow((double)j,a)*b);
4893 }
4894 }
4895
loadtables(void)4896 static int loadtables(void)
4897 {
4898 int i;
4899
4900 initksqrt();
4901 for(i=0;i<2048;i++) {
4902 sintable[i] = (short)(16384*sin((double)i*3.14159265358979/1024));
4903 reciptable[i] = divscale30(2048L,i+2048);
4904 }
4905 for(i=0;i<640;i++) {
4906 radarang[i] = (short)(atan(((double)i-639.5)/160)*64*1024/3.14159265358979);
4907 radarang[1279-i] = -radarang[i];
4908 }
4909 calcbritable();
4910
4911 if (crc32once((unsigned char *)sintable, sizeof(sintable)) != 0xee1e7aba) {
4912 engineerrstr = "Calculation of sintable yielded unexpected results.";
4913 return 1;
4914 }
4915 if (crc32once((unsigned char *)radarang, sizeof(radarang)/2) != 0xee893d92) {
4916 engineerrstr = "Calculation of radarang yielded unexpected results.";
4917 return 1;
4918 }
4919
4920 return 0;
4921 }
4922
4923
4924 //
4925 // initfastcolorlookup (internal)
4926 //
initfastcolorlookup(int rscale,int gscale,int bscale)4927 static void initfastcolorlookup(int rscale, int gscale, int bscale)
4928 {
4929 int i, j, x, y, z;
4930 unsigned char *pal1;
4931
4932 j = 0;
4933 for(i=64;i>=0;i--)
4934 {
4935 //j = (i-64)*(i-64);
4936 rdist[i] = rdist[128-i] = j*rscale;
4937 gdist[i] = gdist[128-i] = j*gscale;
4938 bdist[i] = bdist[128-i] = j*bscale;
4939 j += 129-(i<<1);
4940 }
4941
4942 //clearbufbyte(colhere,sizeof(colhere),0L);
4943 //clearbufbyte(colhead,sizeof(colhead),0L);
4944 Bmemset(colhere,0,sizeof(colhere));
4945 Bmemset(colhead,0,sizeof(colhead));
4946
4947 pal1 = &palette[768-3];
4948 for(i=255;i>=0;i--,pal1-=3)
4949 {
4950 j = (pal1[0]>>3)*FASTPALGRIDSIZ*FASTPALGRIDSIZ+(pal1[1]>>3)*FASTPALGRIDSIZ+(pal1[2]>>3)+FASTPALGRIDSIZ*FASTPALGRIDSIZ+FASTPALGRIDSIZ+1;
4951 if (colhere[j>>3]&pow2char[j&7]) colnext[i] = colhead[j]; else colnext[i] = -1;
4952 colhead[j] = i;
4953 colhere[j>>3] |= pow2char[j&7];
4954 }
4955
4956 i = 0;
4957 for(x=-FASTPALGRIDSIZ*FASTPALGRIDSIZ;x<=FASTPALGRIDSIZ*FASTPALGRIDSIZ;x+=FASTPALGRIDSIZ*FASTPALGRIDSIZ)
4958 for(y=-FASTPALGRIDSIZ;y<=FASTPALGRIDSIZ;y+=FASTPALGRIDSIZ)
4959 for(z=-1;z<=1;z++)
4960 colscan[i++] = x+y+z;
4961 i = colscan[13]; colscan[13] = colscan[26]; colscan[26] = i;
4962 }
4963
4964
4965 //
4966 // loadpalette (internal)
4967 //
loadpalette(void)4968 static int loadpalette(void)
4969 {
4970 int fil = -1, flen, i;
4971
4972 if ((fil = kopen4load("palette.dat",0)) < 0) goto badpalette;
4973 flen = kfilelength(fil);
4974
4975 if (kread(fil,palette,768) != 768) {
4976 buildputs("loadpalette: truncated palette\n");
4977 goto badpalette;
4978 }
4979
4980 if ((flen - 65536 - 2 - 768) % 256 == 0) {
4981 // Map format 7+ palette.
4982 if (kread(fil,&numpalookups,2) != 2) {
4983 buildputs("loadpalette: read error\n");
4984 goto badpalette;
4985 }
4986 numpalookups = B_LITTLE16(numpalookups);
4987 } else if ((flen - 32640 - 768) % 256 == 0) {
4988 // Old format palette.
4989 numpalookups = (flen - 32640 - 768) >> 8;
4990 buildprintf("loadpalette: old format palette (%d shades)\n",
4991 numpalookups);
4992 goto badpalette;
4993 } else {
4994 buildprintf("loadpalette: damaged palette\n");
4995 goto badpalette;
4996 }
4997
4998 if ((palookup[0] = kmalloc(numpalookups<<8)) == NULL) {
4999 engineerrstr = "Failed to allocate palette memory";
5000 kclose(fil);
5001 return 1;
5002 }
5003 if ((transluc = kmalloc(65536L)) == NULL) {
5004 engineerrstr = "Failed to allocate translucency memory";
5005 kclose(fil);
5006 return 1;
5007 }
5008
5009 globalpalwritten = palookup[0]; globalpal = 0;
5010 setpalookupaddress(globalpalwritten);
5011
5012 fixtransluscence(transluc);
5013
5014 kread(fil,palookup[globalpal],numpalookups<<8);
5015 kread(fil,transluc,65536);
5016 kclose(fil);
5017
5018 initfastcolorlookup(30L,59L,11L);
5019
5020 return 0;
5021
5022 badpalette:
5023 engineerrstr = "Failed to load PALETTE.DAT!";
5024 if (fil >= 0) kclose(fil);
5025 return 1;
5026 }
5027
5028
5029 //
5030 // getclosestcol
5031 //
getclosestcol(int r,int g,int b)5032 int getclosestcol(int r, int g, int b)
5033 {
5034 int i, j, k, dist, mindist, retcol;
5035 unsigned char *pal1;
5036
5037 j = (r>>3)*FASTPALGRIDSIZ*FASTPALGRIDSIZ+(g>>3)*FASTPALGRIDSIZ+(b>>3)+FASTPALGRIDSIZ*FASTPALGRIDSIZ+FASTPALGRIDSIZ+1;
5038 mindist = min(rdist[coldist[r&7]+64+8],gdist[coldist[g&7]+64+8]);
5039 mindist = min(mindist,bdist[coldist[b&7]+64+8]);
5040 mindist++;
5041
5042 r = 64-r; g = 64-g; b = 64-b;
5043
5044 retcol = -1;
5045 for(k=26;k>=0;k--)
5046 {
5047 i = colscan[k]+j; if ((colhere[i>>3]&pow2char[i&7]) == 0) continue;
5048 i = colhead[i];
5049 do
5050 {
5051 pal1 = &palette[i*3];
5052 dist = gdist[pal1[1]+g];
5053 if (dist < mindist)
5054 {
5055 dist += rdist[pal1[0]+r];
5056 if (dist < mindist)
5057 {
5058 dist += bdist[pal1[2]+b];
5059 if (dist < mindist) { mindist = dist; retcol = i; }
5060 }
5061 }
5062 i = colnext[i];
5063 } while (i >= 0);
5064 }
5065 if (retcol >= 0) return(retcol);
5066
5067 mindist = 0x7fffffff;
5068 pal1 = &palette[768-3];
5069 for(i=255;i>=0;i--,pal1-=3)
5070 {
5071 dist = gdist[pal1[1]+g]; if (dist >= mindist) continue;
5072 dist += rdist[pal1[0]+r]; if (dist >= mindist) continue;
5073 dist += bdist[pal1[2]+b]; if (dist >= mindist) continue;
5074 mindist = dist; retcol = i;
5075 }
5076 return(retcol);
5077 }
5078
5079
5080 //
5081 // insertspritesect (internal)
5082 //
insertspritesect(short sectnum)5083 static int insertspritesect(short sectnum)
5084 {
5085 short blanktouse;
5086
5087 if ((sectnum >= MAXSECTORS) || (headspritesect[MAXSECTORS] == -1))
5088 return(-1); //list full
5089
5090 blanktouse = headspritesect[MAXSECTORS];
5091
5092 headspritesect[MAXSECTORS] = nextspritesect[blanktouse];
5093 if (headspritesect[MAXSECTORS] >= 0)
5094 prevspritesect[headspritesect[MAXSECTORS]] = -1;
5095
5096 prevspritesect[blanktouse] = -1;
5097 nextspritesect[blanktouse] = headspritesect[sectnum];
5098 if (headspritesect[sectnum] >= 0)
5099 prevspritesect[headspritesect[sectnum]] = blanktouse;
5100 headspritesect[sectnum] = blanktouse;
5101
5102 sprite[blanktouse].sectnum = sectnum;
5103
5104 return(blanktouse);
5105 }
5106
5107
5108 //
5109 // insertspritestat (internal)
5110 //
insertspritestat(short statnum)5111 static int insertspritestat(short statnum)
5112 {
5113 short blanktouse;
5114
5115 if ((statnum >= MAXSTATUS) || (headspritestat[MAXSTATUS] == -1))
5116 return(-1); //list full
5117
5118 blanktouse = headspritestat[MAXSTATUS];
5119
5120 headspritestat[MAXSTATUS] = nextspritestat[blanktouse];
5121 if (headspritestat[MAXSTATUS] >= 0)
5122 prevspritestat[headspritestat[MAXSTATUS]] = -1;
5123
5124 prevspritestat[blanktouse] = -1;
5125 nextspritestat[blanktouse] = headspritestat[statnum];
5126 if (headspritestat[statnum] >= 0)
5127 prevspritestat[headspritestat[statnum]] = blanktouse;
5128 headspritestat[statnum] = blanktouse;
5129
5130 sprite[blanktouse].statnum = statnum;
5131
5132 return(blanktouse);
5133 }
5134
5135
5136 //
5137 // deletespritesect (internal)
5138 //
deletespritesect(short deleteme)5139 static int deletespritesect(short deleteme)
5140 {
5141 if (sprite[deleteme].sectnum == MAXSECTORS)
5142 return(-1);
5143
5144 if (headspritesect[sprite[deleteme].sectnum] == deleteme)
5145 headspritesect[sprite[deleteme].sectnum] = nextspritesect[deleteme];
5146
5147 if (prevspritesect[deleteme] >= 0) nextspritesect[prevspritesect[deleteme]] = nextspritesect[deleteme];
5148 if (nextspritesect[deleteme] >= 0) prevspritesect[nextspritesect[deleteme]] = prevspritesect[deleteme];
5149
5150 if (headspritesect[MAXSECTORS] >= 0) prevspritesect[headspritesect[MAXSECTORS]] = deleteme;
5151 prevspritesect[deleteme] = -1;
5152 nextspritesect[deleteme] = headspritesect[MAXSECTORS];
5153 headspritesect[MAXSECTORS] = deleteme;
5154
5155 sprite[deleteme].sectnum = MAXSECTORS;
5156 return(0);
5157 }
5158
5159
5160 //
5161 // deletespritestat (internal)
5162 //
deletespritestat(short deleteme)5163 static int deletespritestat(short deleteme)
5164 {
5165 if (sprite[deleteme].statnum == MAXSTATUS)
5166 return(-1);
5167
5168 if (headspritestat[sprite[deleteme].statnum] == deleteme)
5169 headspritestat[sprite[deleteme].statnum] = nextspritestat[deleteme];
5170
5171 if (prevspritestat[deleteme] >= 0) nextspritestat[prevspritestat[deleteme]] = nextspritestat[deleteme];
5172 if (nextspritestat[deleteme] >= 0) prevspritestat[nextspritestat[deleteme]] = prevspritestat[deleteme];
5173
5174 if (headspritestat[MAXSTATUS] >= 0) prevspritestat[headspritestat[MAXSTATUS]] = deleteme;
5175 prevspritestat[deleteme] = -1;
5176 nextspritestat[deleteme] = headspritestat[MAXSTATUS];
5177 headspritestat[MAXSTATUS] = deleteme;
5178
5179 sprite[deleteme].statnum = MAXSTATUS;
5180 return(0);
5181 }
5182
5183
5184 //
5185 // lintersect (internal)
5186 //
lintersect(int x1,int y1,int z1,int x2,int y2,int z2,int x3,int y3,int x4,int y4,int * intx,int * inty,int * intz)5187 static int lintersect(int x1, int y1, int z1, int x2, int y2, int z2, int x3,
5188 int y3, int x4, int y4, int *intx, int *inty, int *intz)
5189 { //p1 to p2 is a line segment
5190 int x21, y21, x34, y34, x31, y31, bot, topt, topu, t;
5191
5192 x21 = x2-x1; x34 = x3-x4;
5193 y21 = y2-y1; y34 = y3-y4;
5194 bot = x21*y34 - y21*x34;
5195 if (bot >= 0)
5196 {
5197 if (bot == 0) return(0);
5198 x31 = x3-x1; y31 = y3-y1;
5199 topt = x31*y34 - y31*x34; if ((topt < 0) || (topt >= bot)) return(0);
5200 topu = x21*y31 - y21*x31; if ((topu < 0) || (topu >= bot)) return(0);
5201 }
5202 else
5203 {
5204 x31 = x3-x1; y31 = y3-y1;
5205 topt = x31*y34 - y31*x34; if ((topt > 0) || (topt <= bot)) return(0);
5206 topu = x21*y31 - y21*x31; if ((topu > 0) || (topu <= bot)) return(0);
5207 }
5208 t = divscale24(topt,bot);
5209 *intx = x1 + mulscale24(x21,t);
5210 *inty = y1 + mulscale24(y21,t);
5211 *intz = z1 + mulscale24(z2-z1,t);
5212 return(1);
5213 }
5214
5215
5216 //
5217 // rintersect (internal)
5218 //
rintersect(int x1,int y1,int z1,int vx,int vy,int vz,int x3,int y3,int x4,int y4,int * intx,int * inty,int * intz)5219 static int rintersect(int x1, int y1, int z1, int vx, int vy, int vz, int x3,
5220 int y3, int x4, int y4, int *intx, int *inty, int *intz)
5221 { //p1 towards p2 is a ray
5222 int x34, y34, x31, y31, bot, topt, topu, t;
5223
5224 x34 = x3-x4; y34 = y3-y4;
5225 bot = vx*y34 - vy*x34;
5226 if (bot >= 0)
5227 {
5228 if (bot == 0) return(0);
5229 x31 = x3-x1; y31 = y3-y1;
5230 topt = x31*y34 - y31*x34; if (topt < 0) return(0);
5231 topu = vx*y31 - vy*x31; if ((topu < 0) || (topu >= bot)) return(0);
5232 }
5233 else
5234 {
5235 x31 = x3-x1; y31 = y3-y1;
5236 topt = x31*y34 - y31*x34; if (topt > 0) return(0);
5237 topu = vx*y31 - vy*x31; if ((topu > 0) || (topu <= bot)) return(0);
5238 }
5239 t = divscale16(topt,bot);
5240 *intx = x1 + mulscale16(vx,t);
5241 *inty = y1 + mulscale16(vy,t);
5242 *intz = z1 + mulscale16(vz,t);
5243 return(1);
5244 }
5245
5246
5247 //
5248 // keepaway (internal)
5249 //
keepaway(int * x,int * y,int w)5250 static void keepaway (int *x, int *y, int w)
5251 {
5252 int dx, dy, ox, oy, x1, y1;
5253 char first;
5254
5255 x1 = clipit[w].x1; dx = clipit[w].x2-x1;
5256 y1 = clipit[w].y1; dy = clipit[w].y2-y1;
5257 ox = ksgn(-dy); oy = ksgn(dx);
5258 first = (klabs(dx) <= klabs(dy));
5259 while (1)
5260 {
5261 if (dx*(*y-y1) > (*x-x1)*dy) return;
5262 if (first == 0) *x += ox; else *y += oy;
5263 first ^= 1;
5264 }
5265 }
5266
5267
5268 //
5269 // raytrace (internal)
5270 //
raytrace(int x3,int y3,int * x4,int * y4)5271 static int raytrace(int x3, int y3, int *x4, int *y4)
5272 {
5273 int x1, y1, x2, y2, bot, topu, nintx, ninty, cnt, z, hitwall;
5274 int x21, y21, x43, y43;
5275
5276 hitwall = -1;
5277 for(z=clipnum-1;z>=0;z--)
5278 {
5279 x1 = clipit[z].x1; x2 = clipit[z].x2; x21 = x2-x1;
5280 y1 = clipit[z].y1; y2 = clipit[z].y2; y21 = y2-y1;
5281
5282 topu = x21*(y3-y1) - (x3-x1)*y21; if (topu <= 0) continue;
5283 if (x21*(*y4-y1) > (*x4-x1)*y21) continue;
5284 x43 = *x4-x3; y43 = *y4-y3;
5285 if (x43*(y1-y3) > (x1-x3)*y43) continue;
5286 if (x43*(y2-y3) <= (x2-x3)*y43) continue;
5287 bot = x43*y21 - x21*y43; if (bot == 0) continue;
5288
5289 cnt = 256;
5290 do
5291 {
5292 cnt--; if (cnt < 0) { *x4 = x3; *y4 = y3; return(z); }
5293 nintx = x3 + scale(x43,topu,bot);
5294 ninty = y3 + scale(y43,topu,bot);
5295 topu--;
5296 } while (x21*(ninty-y1) <= (nintx-x1)*y21);
5297
5298 if (klabs(x3-nintx)+klabs(y3-ninty) < klabs(x3-*x4)+klabs(y3-*y4))
5299 { *x4 = nintx; *y4 = ninty; hitwall = z; }
5300 }
5301 return(hitwall);
5302 }
5303
5304
5305
5306 //
5307 // Exported Engine Functions
5308 //
5309
5310 #if !defined _WIN32 && defined DEBUGGINGAIDS
5311 #include <signal.h>
sighandler(int sig,siginfo_t * info,void * ctx)5312 static void sighandler(int sig, siginfo_t *info, void *ctx)
5313 {
5314 const char *s;
5315 switch (sig) {
5316 case SIGFPE:
5317 switch (info->si_code) {
5318 case FPE_INTDIV: s = "FPE_INTDIV (integer divide by zero)"; break;
5319 case FPE_INTOVF: s = "FPE_INTOVF (integer overflow)"; break;
5320 case FPE_FLTDIV: s = "FPE_FLTDIV (floating-point divide by zero)"; break;
5321 case FPE_FLTOVF: s = "FPE_FLTOVF (floating-point overflow)"; break;
5322 case FPE_FLTUND: s = "FPE_FLTUND (floating-point underflow)"; break;
5323 case FPE_FLTRES: s = "FPE_FLTRES (floating-point inexact result)"; break;
5324 case FPE_FLTINV: s = "FPE_FLTINV (floating-point invalid operation)"; break;
5325 case FPE_FLTSUB: s = "FPE_FLTSUB (floating-point subscript out of range)"; break;
5326 default: s = "?! (unknown)"; break;
5327 }
5328 fprintf(stderr, "Caught SIGFPE at address %p, code %s. Aborting.\n", info->si_addr, s);
5329 break;
5330 default: break;
5331 }
5332 abort();
5333 }
5334 #endif
5335
5336 //
5337 // preinitengine
5338 //
5339 static int preinitcalled = 0;
preinitengine(void)5340 int preinitengine(void)
5341 {
5342 char *e;
5343 char compiler[30] = "an unidentified compiler";
5344
5345 #if defined(_MSC_VER)
5346 sprintf(compiler, "MS Visual C++ %d.%02d", _MSC_VER/100, _MSC_VER%100);
5347 #elif defined(__clang__)
5348 sprintf(compiler, "Clang %d.%d", __clang_major__, __clang_minor__);
5349 #elif defined(__GNUC__)
5350 sprintf(compiler, "GCC %d.%d", __GNUC__, __GNUC_MINOR__);
5351 #endif
5352
5353 buildprintf("\nBUILD engine by Ken Silverman (http://www.advsys.net/ken)\n"
5354 "Additional improvements by Jonathon Fowler (http://www.jonof.id.au)\n"
5355 "and other contributors. See BUILDLIC.TXT for terms.\n\n"
5356 "Version %s.\nBuilt %s %s using %s.\n%d-bit word size.\n\n",
5357 build_version, build_date, build_time, compiler, (int)(sizeof(intptr_t)<<3));
5358
5359 // Detect anomalous structure packing.
5360 assert(sizeof(sectortype) == 40);
5361 assert((intptr_t)§or[1] - (intptr_t)§or[0] == sizeof(sectortype));
5362 assert(sizeof(walltype) == 32);
5363 assert((intptr_t)&wall[1] - (intptr_t)&wall[0] == sizeof(walltype));
5364 assert(sizeof(spritetype) == 44);
5365 assert((intptr_t)&sprite[1] - (intptr_t)&sprite[0] == sizeof(spritetype));
5366 assert(sizeof(spriteexttype) == 12);
5367 assert((intptr_t)&spriteext[1] - (intptr_t)&spriteext[0] == sizeof(spriteexttype));
5368
5369 if (initsystem()) exit(1);
5370
5371 makeasmwriteable();
5372
5373 if ((e = Bgetenv("BUILD_NOP6")) != NULL)
5374 if (!Bstrcasecmp(e, "TRUE")) {
5375 buildprintf("Disabling P6 optimizations.\n");
5376 dommxoverlay = 0;
5377 }
5378 if (dommxoverlay) mmxoverlay();
5379
5380 validmodecnt = 0;
5381 getvalidmodes();
5382
5383 initcrc32table();
5384
5385 preinitcalled = 1;
5386 return 0;
5387 }
5388
5389
5390 //
5391 // initengine
5392 //
initengine(void)5393 int initengine(void)
5394 {
5395 int i, j;
5396
5397 #if !defined _WIN32 && defined DEBUGGINGAIDS
5398 struct sigaction sigact, oldact;
5399 memset(&sigact, 0, sizeof(sigact));
5400 sigact.sa_sigaction = sighandler;
5401 sigact.sa_flags = SA_SIGINFO;
5402 sigaction(SIGFPE, &sigact, &oldact);
5403 #endif
5404 if (!preinitcalled) {
5405 i = preinitengine();
5406 if (i) return i;
5407 }
5408
5409 xyaspect = -1;
5410
5411 pskyoff[0] = 0; pskybits = 0;
5412
5413 parallaxtype = 2; parallaxyoffs = 0L; parallaxyscale = 65536;
5414 showinvisibility = 0;
5415
5416 for(i=1;i<1024;i++) lowrecip[i] = ((1<<24)-1)/i;
5417 for(i=0;i<MAXVOXELS;i++)
5418 for(j=0;j<MAXVOXMIPS;j++)
5419 {
5420 voxoff[i][j] = 0L;
5421 voxlock[i][j] = 200;
5422 }
5423 for(i=0;i<MAXTILES;i++)
5424 tiletovox[i] = -1;
5425 clearbuf(&voxscale[0],sizeof(voxscale)>>2,65536L);
5426
5427 #if USE_POLYMOST
5428 polymost_initosdfuncs();
5429 #endif
5430
5431 searchit = 0; searchstat = -1;
5432
5433 for(i=0;i<MAXPALOOKUPS;i++) palookup[i] = NULL;
5434
5435 clearbuf(&waloff[0],(int)MAXTILES,0L);
5436
5437 clearbuf(&show2dsector[0],(int)((MAXSECTORS+3)>>5),0L);
5438 clearbuf(&show2dsprite[0],(int)((MAXSPRITES+3)>>5),0L);
5439 clearbuf(&show2dwall[0],(int)((MAXWALLS+3)>>5),0L);
5440 automapping = 0;
5441
5442 pointhighlight = -1;
5443 linehighlight = -1;
5444 highlightcnt = 0;
5445
5446 totalclock = 0;
5447 visibility = 512;
5448 parallaxvisibility = 512;
5449
5450 captureformat = 0;
5451
5452 if (loadtables()) return 1;
5453 if (loadpalette()) return 1;
5454
5455 #if USE_POLYMOST && USE_OPENGL
5456 if (!hicfirstinit) hicinit();
5457 if (!mdinited) mdinit();
5458 PTCacheLoadIndex();
5459 #endif
5460
5461 return 0;
5462 }
5463
5464
5465 //
5466 // uninitengine
5467 //
uninitengine(void)5468 void uninitengine(void)
5469 {
5470 int i;
5471
5472 //buildprintf("cacheresets = %d, cacheinvalidates = %d\n", cacheresets, cacheinvalidates);
5473
5474 #if USE_POLYMOST && USE_OPENGL
5475 polymost_glreset();
5476 PTClear();
5477 PTCacheUnloadIndex();
5478 hicinit();
5479 freeallmodels();
5480 #endif
5481
5482 uninitsystem();
5483
5484 if (logfile) Bfclose(logfile);
5485 logfile = NULL;
5486
5487 if (artfil != -1) kclose(artfil);
5488
5489 if (transluc != NULL) { kfree(transluc); transluc = NULL; }
5490 if (pic != NULL) { kfree(pic); pic = NULL; }
5491 if (lookups != NULL) { kfree(lookups); lookups = NULL; }
5492 for(i=0;i<MAXPALOOKUPS;i++)
5493 if (palookup[i] != NULL) { kfree(palookup[i]); palookup[i] = NULL; }
5494 }
5495
5496
5497 //
5498 // initspritelists
5499 //
initspritelists(void)5500 void initspritelists(void)
5501 {
5502 int i;
5503
5504 for (i=0;i<MAXSECTORS;i++) //Init doubly-linked sprite sector lists
5505 headspritesect[i] = -1;
5506 headspritesect[MAXSECTORS] = 0;
5507 for(i=0;i<MAXSPRITES;i++)
5508 {
5509 prevspritesect[i] = i-1;
5510 nextspritesect[i] = i+1;
5511 sprite[i].sectnum = MAXSECTORS;
5512 }
5513 prevspritesect[0] = -1;
5514 nextspritesect[MAXSPRITES-1] = -1;
5515
5516
5517 for(i=0;i<MAXSTATUS;i++) //Init doubly-linked sprite status lists
5518 headspritestat[i] = -1;
5519 headspritestat[MAXSTATUS] = 0;
5520 for(i=0;i<MAXSPRITES;i++)
5521 {
5522 prevspritestat[i] = i-1;
5523 nextspritestat[i] = i+1;
5524 sprite[i].statnum = MAXSTATUS;
5525 }
5526 prevspritestat[0] = -1;
5527 nextspritestat[MAXSPRITES-1] = -1;
5528 }
5529
5530
5531 //
5532 // drawrooms
5533 //
drawrooms(int daposx,int daposy,int daposz,short daang,int dahoriz,short dacursectnum)5534 void drawrooms(int daposx, int daposy, int daposz,
5535 short daang, int dahoriz, short dacursectnum)
5536 {
5537 int i, j, z, cz, fz, closest;
5538 short *shortptr1, *shortptr2;
5539
5540 beforedrawrooms = 0;
5541
5542 globalposx = daposx; globalposy = daposy; globalposz = daposz;
5543 globalang = (daang&2047);
5544
5545 globalhoriz = mulscale16(dahoriz-100,xdimenscale)+(ydimen>>1);
5546 globaluclip = (0-globalhoriz)*xdimscale;
5547 globaldclip = (ydimen-globalhoriz)*xdimscale;
5548
5549 i = mulscale16(xdimenscale,viewingrangerecip);
5550 globalpisibility = mulscale16(parallaxvisibility,i);
5551 globalvisibility = mulscale16(visibility,i);
5552 globalhisibility = mulscale16(globalvisibility,xyaspect);
5553 globalcisibility = mulscale8(globalhisibility,320);
5554
5555 globalcursectnum = dacursectnum;
5556 totalclocklock = totalclock;
5557
5558 cosglobalang = sintable[(globalang+512)&2047];
5559 singlobalang = sintable[globalang&2047];
5560 cosviewingrangeglobalang = mulscale16(cosglobalang,viewingrange);
5561 sinviewingrangeglobalang = mulscale16(singlobalang,viewingrange);
5562
5563 if ((xyaspect != oxyaspect) || (xdimen != oxdimen) || (viewingrange != oviewingrange))
5564 dosetaspect();
5565
5566 //clearbufbyte(&gotsector[0],(int)((numsectors+7)>>3),0L);
5567 Bmemset(&gotsector[0],0,(int)((numsectors+7)>>3));
5568
5569 shortptr1 = (short *)&startumost[windowx1];
5570 shortptr2 = (short *)&startdmost[windowx1];
5571 i = xdimen-1;
5572 do
5573 {
5574 umost[i] = shortptr1[i]-windowy1;
5575 dmost[i] = shortptr2[i]-windowy1;
5576 i--;
5577 } while (i != 0);
5578 umost[0] = shortptr1[0]-windowy1;
5579 dmost[0] = shortptr2[0]-windowy1;
5580
5581 //============================================================================= //POLYMOST BEGINS
5582 #if USE_POLYMOST
5583 polymost_drawrooms(); if (rendmode) { return; }
5584 #endif
5585 //============================================================================= //POLYMOST ENDS
5586
5587 begindrawing(); //{{{
5588
5589 frameoffset = frameplace + windowy1*bytesperline + windowx1;
5590
5591 numhits = xdimen; numscans = 0; numbunches = 0;
5592 maskwallcnt = 0; smostwallcnt = 0; smostcnt = 0; spritesortcnt = 0;
5593
5594 if (globalcursectnum >= MAXSECTORS)
5595 globalcursectnum -= MAXSECTORS;
5596 else
5597 {
5598 i = globalcursectnum;
5599 updatesector(globalposx,globalposy,&globalcursectnum);
5600 if (globalcursectnum < 0) globalcursectnum = i;
5601 }
5602
5603 globparaceilclip = 1;
5604 globparaflorclip = 1;
5605 getzsofslope(globalcursectnum,globalposx,globalposy,&cz,&fz);
5606 if (globalposz < cz) globparaceilclip = 0;
5607 if (globalposz > fz) globparaflorclip = 0;
5608
5609 scansector(globalcursectnum);
5610
5611 if (inpreparemirror)
5612 {
5613 inpreparemirror = 0;
5614 mirrorsx1 = xdimen-1; mirrorsx2 = 0;
5615 for(i=numscans-1;i>=0;i--)
5616 {
5617 if (wall[thewall[i]].nextsector < 0) continue;
5618 if (xb1[i] < mirrorsx1) mirrorsx1 = xb1[i];
5619 if (xb2[i] > mirrorsx2) mirrorsx2 = xb2[i];
5620 }
5621
5622 for(i=0;i<mirrorsx1;i++)
5623 if (umost[i] <= dmost[i])
5624 { umost[i] = 1; dmost[i] = 0; numhits--; }
5625 for(i=mirrorsx2+1;i<xdimen;i++)
5626 if (umost[i] <= dmost[i])
5627 { umost[i] = 1; dmost[i] = 0; numhits--; }
5628
5629 drawalls(0L);
5630 numbunches--;
5631 bunchfirst[0] = bunchfirst[numbunches];
5632 bunchlast[0] = bunchlast[numbunches];
5633
5634 mirrorsy1 = min(umost[mirrorsx1],umost[mirrorsx2]);
5635 mirrorsy2 = max(dmost[mirrorsx1],dmost[mirrorsx2]);
5636 }
5637
5638 while ((numbunches > 0) && (numhits > 0))
5639 {
5640 clearbuf(&tempbuf[0],(int)((numbunches+3)>>2),0L);
5641 tempbuf[0] = 1;
5642
5643 closest = 0; //Almost works, but not quite :(
5644 for(i=1;i<numbunches;i++)
5645 {
5646 if ((j = bunchfront(i,closest)) < 0) continue;
5647 tempbuf[i] = 1;
5648 if (j == 0) tempbuf[closest] = 1, closest = i;
5649 }
5650 for(i=0;i<numbunches;i++) //Double-check
5651 {
5652 if (tempbuf[i]) continue;
5653 if ((j = bunchfront(i,closest)) < 0) continue;
5654 tempbuf[i] = 1;
5655 if (j == 0) tempbuf[closest] = 1, closest = i, i = 0;
5656 }
5657
5658 drawalls(closest);
5659
5660 if (automapping)
5661 {
5662 for(z=bunchfirst[closest];z>=0;z=p2[z])
5663 show2dwall[thewall[z]>>3] |= pow2char[thewall[z]&7];
5664 }
5665
5666 numbunches--;
5667 bunchfirst[closest] = bunchfirst[numbunches];
5668 bunchlast[closest] = bunchlast[numbunches];
5669 }
5670
5671 enddrawing(); //}}}
5672 }
5673
5674
5675 //
5676 // drawmasks
5677 //
drawmasks(void)5678 void drawmasks(void)
5679 {
5680 int i, j, k, l, gap, xs, ys, xp, yp, yoff, yspan;
5681
5682 for(i=spritesortcnt-1;i>=0;i--) tspriteptr[i] = &tsprite[i];
5683 for(i=spritesortcnt-1;i>=0;i--)
5684 {
5685 xs = tspriteptr[i]->x-globalposx; ys = tspriteptr[i]->y-globalposy;
5686 yp = dmulscale6(xs,cosviewingrangeglobalang,ys,sinviewingrangeglobalang);
5687 if (yp > (4<<8))
5688 {
5689 xp = dmulscale6(ys,cosglobalang,-xs,singlobalang);
5690 if (mulscale24(labs(xp+yp),xdimen) >= yp) goto killsprite;
5691 spritesx[i] = scale(xp+yp,xdimen<<7,yp);
5692 }
5693 else if ((tspriteptr[i]->cstat&48) == 0)
5694 {
5695 killsprite:
5696 spritesortcnt--; //Delete face sprite if on wrong side!
5697 if (i != spritesortcnt)
5698 {
5699 tspriteptr[i] = tspriteptr[spritesortcnt];
5700 spritesx[i] = spritesx[spritesortcnt];
5701 spritesy[i] = spritesy[spritesortcnt];
5702 }
5703 continue;
5704 }
5705 spritesy[i] = yp;
5706 }
5707
5708 gap = 1; while (gap < spritesortcnt) gap = (gap<<1)+1;
5709 for(gap>>=1;gap>0;gap>>=1) //Sort sprite list
5710 for(i=0;i<spritesortcnt-gap;i++)
5711 for(l=i;l>=0;l-=gap)
5712 {
5713 if (spritesy[l] <= spritesy[l+gap]) break;
5714 swaplong(&tspriteptr[l],&tspriteptr[l+gap]);
5715 swaplong(&spritesx[l],&spritesx[l+gap]);
5716 swaplong(&spritesy[l],&spritesy[l+gap]);
5717 }
5718
5719 if (spritesortcnt > 0)
5720 spritesy[spritesortcnt] = (spritesy[spritesortcnt-1]^1);
5721
5722 ys = spritesy[0]; i = 0;
5723 for(j=1;j<=spritesortcnt;j++)
5724 {
5725 if (spritesy[j] == ys) continue;
5726 ys = spritesy[j];
5727 if (j > i+1)
5728 {
5729 for(k=i;k<j;k++)
5730 {
5731 spritesz[k] = tspriteptr[k]->z;
5732 if ((tspriteptr[k]->cstat&48) != 32)
5733 {
5734 yoff = (int)((signed char)((picanm[tspriteptr[k]->picnum]>>16)&255))+((int)tspriteptr[k]->yoffset);
5735 spritesz[k] -= ((yoff*tspriteptr[k]->yrepeat)<<2);
5736 yspan = (tilesizy[tspriteptr[k]->picnum]*tspriteptr[k]->yrepeat<<2);
5737 if (!(tspriteptr[k]->cstat&128)) spritesz[k] -= (yspan>>1);
5738 if (klabs(spritesz[k]-globalposz) < (yspan>>1)) spritesz[k] = globalposz;
5739 }
5740 }
5741 for(k=i+1;k<j;k++)
5742 for(l=i;l<k;l++)
5743 if (klabs(spritesz[k]-globalposz) < klabs(spritesz[l]-globalposz))
5744 {
5745 swaplong(&tspriteptr[k],&tspriteptr[l]);
5746 swaplong(&spritesx[k],&spritesx[l]);
5747 swaplong(&spritesy[k],&spritesy[l]);
5748 swaplong(&spritesz[k],&spritesz[l]);
5749 }
5750 for(k=i+1;k<j;k++)
5751 for(l=i;l<k;l++)
5752 if (tspriteptr[k]->statnum < tspriteptr[l]->statnum)
5753 {
5754 swaplong(&tspriteptr[k],&tspriteptr[l]);
5755 swaplong(&spritesx[k],&spritesx[l]);
5756 swaplong(&spritesy[k],&spritesy[l]);
5757 }
5758 }
5759 i = j;
5760 }
5761
5762 begindrawing(); //{{{
5763
5764 /*for(i=spritesortcnt-1;i>=0;i--)
5765 {
5766 xs = tspriteptr[i].x-globalposx;
5767 ys = tspriteptr[i].y-globalposy;
5768 zs = tspriteptr[i].z-globalposz;
5769
5770 xp = ys*cosglobalang-xs*singlobalang;
5771 yp = (zs<<1);
5772 zp = xs*cosglobalang+ys*singlobalang;
5773
5774 xs = scale(xp,halfxdimen<<12,zp)+((halfxdimen+windowx1)<<12);
5775 ys = scale(yp,xdimenscale<<12,zp)+((globalhoriz+windowy1)<<12);
5776
5777 drawline256(xs-65536,ys-65536,xs+65536,ys+65536,31);
5778 drawline256(xs+65536,ys-65536,xs-65536,ys+65536,31);
5779 }*/
5780
5781
5782 #if USE_POLYMOST
5783 //Hack to make it draw all opaque quads first. This should reduce the chances of
5784 //bad sorting causing transparent quads knocking out opaque quads behind it.
5785 //
5786 //Need to store alpha flag with all textures before this works right!
5787 if (rendmode > 0)
5788 {
5789 for(i=spritesortcnt-1;i>=0;i--)
5790 if ((!(tspriteptr[i]->cstat&2))
5791 #if USE_OPENGL
5792 && (!polymost_texmayhavealpha(tspriteptr[i]->picnum,tspriteptr[i]->pal))
5793 #endif
5794 )
5795 { drawsprite(i); tspriteptr[i] = 0; } //draw only if it is fully opaque
5796 for(i=j=0;i<spritesortcnt;i++)
5797 {
5798 if (!tspriteptr[i]) continue;
5799 tspriteptr[j] = tspriteptr[i];
5800 spritesx[j] = spritesx[i];
5801 spritesy[j] = spritesy[i]; j++;
5802 }
5803 spritesortcnt = j;
5804
5805
5806 for(i=maskwallcnt-1;i>=0;i--)
5807 {
5808 k = thewall[maskwall[i]];
5809 if ((!(wall[k].cstat&128))
5810 #if USE_OPENGL
5811 && (!polymost_texmayhavealpha(wall[k].overpicnum,wall[k].pal))
5812 #endif
5813 )
5814 { drawmaskwall(i); maskwall[i] = -1; } //draw only if it is fully opaque
5815 }
5816 for(i=j=0;i<maskwallcnt;i++)
5817 {
5818 if (maskwall[i] < 0) continue;
5819 maskwall[j++] = maskwall[i];
5820 }
5821 maskwallcnt = j;
5822 }
5823 #endif
5824
5825 while ((spritesortcnt > 0) && (maskwallcnt > 0)) //While BOTH > 0
5826 {
5827 j = maskwall[maskwallcnt-1];
5828 if (spritewallfront(tspriteptr[spritesortcnt-1],(int)thewall[j]) == 0)
5829 drawsprite(--spritesortcnt);
5830 else
5831 {
5832 //Check to see if any sprites behind the masked wall...
5833 k = -1;
5834 gap = 0;
5835 for(i=spritesortcnt-2;i>=0;i--)
5836 {
5837 #if USE_POLYMOST
5838 if (rendmode > 0)
5839 l = dxb1[j] <= (double)spritesx[i]/256.0 && (double)spritesx[i]/256.0 <= dxb2[j];
5840 else
5841 #endif
5842 l = xb1[j] <= (spritesx[i]>>8) && (spritesx[i]>>8) <= xb2[j];
5843 if (l && spritewallfront(tspriteptr[i],(int)thewall[j]) == 0)
5844 {
5845 drawsprite(i);
5846 tspriteptr[i]->owner = -1;
5847 k = i;
5848 gap++;
5849 }
5850 }
5851 if (k >= 0) //remove holes in sprite list
5852 {
5853 for(i=k;i<spritesortcnt;i++)
5854 if (tspriteptr[i]->owner >= 0)
5855 {
5856 if (i > k)
5857 {
5858 tspriteptr[k] = tspriteptr[i];
5859 spritesx[k] = spritesx[i];
5860 spritesy[k] = spritesy[i];
5861 }
5862 k++;
5863 }
5864 spritesortcnt -= gap;
5865 }
5866
5867 //finally safe to draw the masked wall
5868 drawmaskwall(--maskwallcnt);
5869 }
5870 }
5871 while (spritesortcnt > 0) drawsprite(--spritesortcnt);
5872 while (maskwallcnt > 0) drawmaskwall(--maskwallcnt);
5873
5874 enddrawing(); //}}}
5875 }
5876
5877
5878 //
5879 // drawmapview
5880 //
drawmapview(int dax,int day,int zoome,short ang)5881 void drawmapview(int dax, int day, int zoome, short ang)
5882 {
5883 walltype *wal;
5884 sectortype *sec;
5885 spritetype *spr;
5886 int tilenum, xoff, yoff, i, j, k, l, cosang, sinang, xspan, yspan;
5887 int xrepeat, yrepeat, x, y, x1, y1, x2, y2, x3, y3, x4, y4, bakx1, baky1;
5888 int s, w, ox, oy, startwall, cx1, cy1, cx2, cy2;
5889 int bakgxvect, bakgyvect, sortnum, gap, npoints;
5890 int xvect, yvect, xvect2, yvect2, daslope;
5891
5892 beforedrawrooms = 0;
5893
5894 clearbuf(&gotsector[0],(int)((numsectors+31)>>5),0L);
5895
5896 cx1 = (windowx1<<12); cy1 = (windowy1<<12);
5897 cx2 = ((windowx2+1)<<12)-1; cy2 = ((windowy2+1)<<12)-1;
5898 zoome <<= 8;
5899 bakgxvect = divscale28(sintable[(1536-ang)&2047],zoome);
5900 bakgyvect = divscale28(sintable[(2048-ang)&2047],zoome);
5901 xvect = mulscale8(sintable[(2048-ang)&2047],zoome);
5902 yvect = mulscale8(sintable[(1536-ang)&2047],zoome);
5903 xvect2 = mulscale16(xvect,yxaspect);
5904 yvect2 = mulscale16(yvect,yxaspect);
5905
5906 sortnum = 0;
5907
5908 begindrawing(); //{{{
5909
5910 for(s=0,sec=§or[s];s<numsectors;s++,sec++)
5911 if (show2dsector[s>>3]&pow2char[s&7])
5912 {
5913 npoints = 0; i = 0;
5914 startwall = sec->wallptr;
5915 #if 0
5916 for(w=sec->wallnum,wal=&wall[startwall];w>0;w--,wal++)
5917 {
5918 ox = wal->x - dax; oy = wal->y - day;
5919 x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11);
5920 y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11);
5921 i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
5922 rx1[npoints] = x;
5923 ry1[npoints] = y;
5924 xb1[npoints] = wal->point2 - startwall;
5925 npoints++;
5926 }
5927 #else
5928 j = startwall; l = 0;
5929 for(w=sec->wallnum,wal=&wall[startwall];w>0;w--,wal++,j++)
5930 {
5931 k = lastwall(j);
5932 if ((k > j) && (npoints > 0)) { xb1[npoints-1] = l; l = npoints; } //overwrite point2
5933 //wall[k].x wal->x wall[wal->point2].x
5934 //wall[k].y wal->y wall[wal->point2].y
5935 if (!dmulscale1(wal->x-wall[k].x,wall[wal->point2].y-wal->y,-(wal->y-wall[k].y),wall[wal->point2].x-wal->x)) continue;
5936 ox = wal->x - dax; oy = wal->y - day;
5937 x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11);
5938 y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11);
5939 i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
5940 rx1[npoints] = x;
5941 ry1[npoints] = y;
5942 xb1[npoints] = npoints+1;
5943 npoints++;
5944 }
5945 if (npoints > 0) xb1[npoints-1] = l; //overwrite point2
5946 #endif
5947 if ((i&0xf0) != 0xf0) continue;
5948 bakx1 = rx1[0]; baky1 = mulscale16(ry1[0]-(ydim<<11),xyaspect)+(ydim<<11);
5949 if (i&0x0f)
5950 {
5951 npoints = clippoly(npoints,i);
5952 if (npoints < 3) continue;
5953 }
5954
5955 //Collect floor sprites to draw
5956 for(i=headspritesect[s];i>=0;i=nextspritesect[i])
5957 if ((sprite[i].cstat&48) == 32)
5958 {
5959 if ((sprite[i].cstat&(64+8)) == (64+8)) continue;
5960 tsprite[sortnum++].owner = i;
5961 }
5962
5963 gotsector[s>>3] |= pow2char[s&7];
5964
5965 globalorientation = (int)sec->floorstat;
5966 if ((globalorientation&1) != 0) continue;
5967
5968 globalpal = sec->floorpal;
5969 if (palookup[sec->floorpal] != globalpalwritten)
5970 {
5971 globalpalwritten = palookup[sec->floorpal];
5972 if (!globalpalwritten) globalpalwritten = palookup[0]; // JBF: fixes null-pointer crash
5973 setpalookupaddress(globalpalwritten);
5974 }
5975 globalpicnum = sec->floorpicnum;
5976 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
5977 setgotpic(globalpicnum);
5978 if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) continue;
5979 if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs((short)globalpicnum,s);
5980 if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
5981 globalbufplc = waloff[globalpicnum];
5982 globalshade = max(min(sec->floorshade,numpalookups-1),0);
5983 globvis = globalhisibility;
5984 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
5985 globalpolytype = 0;
5986 if ((globalorientation&64) == 0)
5987 {
5988 globalposx = dax; globalx1 = bakgxvect; globaly1 = bakgyvect;
5989 globalposy = day; globalx2 = bakgxvect; globaly2 = bakgyvect;
5990 }
5991 else
5992 {
5993 ox = wall[wall[startwall].point2].x - wall[startwall].x;
5994 oy = wall[wall[startwall].point2].y - wall[startwall].y;
5995 i = nsqrtasm(ox*ox+oy*oy); if (i == 0) continue;
5996 i = 1048576/i;
5997 globalx1 = mulscale10(dmulscale10(ox,bakgxvect,oy,bakgyvect),i);
5998 globaly1 = mulscale10(dmulscale10(ox,bakgyvect,-oy,bakgxvect),i);
5999 ox = (bakx1>>4)-(xdim<<7); oy = (baky1>>4)-(ydim<<7);
6000 globalposx = dmulscale28(-oy,globalx1,-ox,globaly1);
6001 globalposy = dmulscale28(-ox,globalx1,oy,globaly1);
6002 globalx2 = -globalx1;
6003 globaly2 = -globaly1;
6004
6005 daslope = sector[s].floorheinum;
6006 i = nsqrtasm(daslope*daslope+16777216);
6007 globalposy = mulscale12(globalposy,i);
6008 globalx2 = mulscale12(globalx2,i);
6009 globaly2 = mulscale12(globaly2,i);
6010 }
6011 globalxshift = (8-(picsiz[globalpicnum]&15));
6012 globalyshift = (8-(picsiz[globalpicnum]>>4));
6013 if (globalorientation&8) {globalxshift++; globalyshift++; }
6014
6015 sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,(void *)globalbufplc);
6016
6017 if ((globalorientation&0x4) > 0)
6018 {
6019 i = globalposx; globalposx = -globalposy; globalposy = -i;
6020 i = globalx2; globalx2 = globaly1; globaly1 = i;
6021 i = globalx1; globalx1 = -globaly2; globaly2 = -i;
6022 }
6023 if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalposx = -globalposx;
6024 if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalposy = -globalposy;
6025 asm1 = (globaly1<<globalxshift);
6026 asm2 = (globalx2<<globalyshift);
6027 globalx1 <<= globalxshift;
6028 globaly2 <<= globalyshift;
6029 globalposx = (globalposx<<(20+globalxshift))+(((int)sec->floorxpanning)<<24);
6030 globalposy = (globalposy<<(20+globalyshift))-(((int)sec->floorypanning)<<24);
6031
6032 fillpolygon(npoints);
6033 }
6034
6035 //Sort sprite list
6036 gap = 1; while (gap < sortnum) gap = (gap<<1)+1;
6037 for(gap>>=1;gap>0;gap>>=1)
6038 for(i=0;i<sortnum-gap;i++)
6039 for(j=i;j>=0;j-=gap)
6040 {
6041 if (sprite[tsprite[j].owner].z <= sprite[tsprite[j+gap].owner].z) break;
6042 swapshort(&tsprite[j].owner,&tsprite[j+gap].owner);
6043 }
6044
6045 for(s=sortnum-1;s>=0;s--)
6046 {
6047 spr = &sprite[tsprite[s].owner];
6048 if ((spr->cstat&48) == 32)
6049 {
6050 npoints = 0;
6051
6052 tilenum = spr->picnum;
6053 xoff = (int)((signed char)((picanm[tilenum]>>8)&255))+((int)spr->xoffset);
6054 yoff = (int)((signed char)((picanm[tilenum]>>16)&255))+((int)spr->yoffset);
6055 if ((spr->cstat&4) > 0) xoff = -xoff;
6056 if ((spr->cstat&8) > 0) yoff = -yoff;
6057
6058 k = spr->ang;
6059 cosang = sintable[(k+512)&2047]; sinang = sintable[k];
6060 xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat;
6061 yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat;
6062
6063 ox = ((xspan>>1)+xoff)*xrepeat; oy = ((yspan>>1)+yoff)*yrepeat;
6064 x1 = spr->x + mulscale(sinang,ox,16) + mulscale(cosang,oy,16);
6065 y1 = spr->y + mulscale(sinang,oy,16) - mulscale(cosang,ox,16);
6066 l = xspan*xrepeat;
6067 x2 = x1 - mulscale(sinang,l,16);
6068 y2 = y1 + mulscale(cosang,l,16);
6069 l = yspan*yrepeat;
6070 k = -mulscale(cosang,l,16); x3 = x2+k; x4 = x1+k;
6071 k = -mulscale(sinang,l,16); y3 = y2+k; y4 = y1+k;
6072
6073 xb1[0] = 1; xb1[1] = 2; xb1[2] = 3; xb1[3] = 0;
6074 npoints = 4;
6075
6076 i = 0;
6077
6078 ox = x1 - dax; oy = y1 - day;
6079 x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11);
6080 y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11);
6081 i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
6082 rx1[0] = x; ry1[0] = y;
6083
6084 ox = x2 - dax; oy = y2 - day;
6085 x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11);
6086 y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11);
6087 i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
6088 rx1[1] = x; ry1[1] = y;
6089
6090 ox = x3 - dax; oy = y3 - day;
6091 x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11);
6092 y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11);
6093 i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
6094 rx1[2] = x; ry1[2] = y;
6095
6096 x = rx1[0]+rx1[2]-rx1[1];
6097 y = ry1[0]+ry1[2]-ry1[1];
6098 i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
6099 rx1[3] = x; ry1[3] = y;
6100
6101 if ((i&0xf0) != 0xf0) continue;
6102 bakx1 = rx1[0]; baky1 = mulscale16(ry1[0]-(ydim<<11),xyaspect)+(ydim<<11);
6103 if (i&0x0f)
6104 {
6105 npoints = clippoly(npoints,i);
6106 if (npoints < 3) continue;
6107 }
6108
6109 globalpicnum = spr->picnum;
6110 if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
6111 setgotpic(globalpicnum);
6112 if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) continue;
6113 if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs((short)globalpicnum,s);
6114 if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
6115 globalbufplc = waloff[globalpicnum];
6116 if ((sector[spr->sectnum].ceilingstat&1) > 0)
6117 globalshade = ((int)sector[spr->sectnum].ceilingshade);
6118 else
6119 globalshade = ((int)sector[spr->sectnum].floorshade);
6120 globalshade = max(min(globalshade+spr->shade+6,numpalookups-1),0);
6121 asm3 = (intptr_t)palookup[spr->pal]+(globalshade<<8);
6122 globvis = globalhisibility;
6123 if (sec->visibility != 0) globvis = mulscale4(globvis,(int)((unsigned char)(sec->visibility+16)));
6124 globalpolytype = ((spr->cstat&2)>>1)+1;
6125
6126 //relative alignment stuff
6127 ox = x2-x1; oy = y2-y1;
6128 i = ox*ox+oy*oy; if (i == 0) continue; i = (65536*16384)/i;
6129 globalx1 = mulscale10(dmulscale10(ox,bakgxvect,oy,bakgyvect),i);
6130 globaly1 = mulscale10(dmulscale10(ox,bakgyvect,-oy,bakgxvect),i);
6131 ox = y1-y4; oy = x4-x1;
6132 i = ox*ox+oy*oy; if (i == 0) continue; i = (65536*16384)/i;
6133 globalx2 = mulscale10(dmulscale10(ox,bakgxvect,oy,bakgyvect),i);
6134 globaly2 = mulscale10(dmulscale10(ox,bakgyvect,-oy,bakgxvect),i);
6135
6136 ox = picsiz[globalpicnum]; oy = ((ox>>4)&15); ox &= 15;
6137 if (pow2long[ox] != xspan)
6138 {
6139 ox++;
6140 globalx1 = mulscale(globalx1,xspan,ox);
6141 globaly1 = mulscale(globaly1,xspan,ox);
6142 }
6143
6144 bakx1 = (bakx1>>4)-(xdim<<7); baky1 = (baky1>>4)-(ydim<<7);
6145 globalposx = dmulscale28(-baky1,globalx1,-bakx1,globaly1);
6146 globalposy = dmulscale28(bakx1,globalx2,-baky1,globaly2);
6147
6148 if ((spr->cstat&2) == 0)
6149 msethlineshift(ox,oy);
6150 else {
6151 if (spr->cstat&512) settransreverse(); else settransnormal();
6152 tsethlineshift(ox,oy);
6153 }
6154
6155 if ((spr->cstat&0x4) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalposx = -globalposx;
6156 asm1 = (globaly1<<2); globalx1 <<= 2; globalposx <<= (20+2);
6157 asm2 = (globalx2<<2); globaly2 <<= 2; globalposy <<= (20+2);
6158
6159 globalorientation = ((spr->cstat&2)<<7) | ((spr->cstat&512)>>2); // so polymost can get the translucency. ignored in software mode.
6160 fillpolygon(npoints);
6161 }
6162 }
6163
6164 enddrawing(); //}}}
6165 }
6166
6167
6168 //
6169 // loadboard
6170 //
loadboard(char * filename,char fromwhere,int * daposx,int * daposy,int * daposz,short * daang,short * dacursectnum)6171 int loadboard(char *filename, char fromwhere, int *daposx, int *daposy, int *daposz,
6172 short *daang, short *dacursectnum)
6173 {
6174 short fil, i, numsprites;
6175
6176 i = strlen(filename)-1;
6177 if ((unsigned char)filename[i] == 255) { filename[i] = 0; fromwhere = 1; } // JBF 20040119: "compatibility"
6178 if ((fil = kopen4load(filename,fromwhere)) == -1)
6179 { mapversion = 7L; return(-1); }
6180
6181 kread(fil,&mapversion,4); mapversion = B_LITTLE32(mapversion);
6182 if (mapversion != 7L && mapversion != 8L) { kclose(fil); return(-2); }
6183
6184 /*
6185 // Enable this for doing map checksum tests
6186 clearbufbyte(&wall, sizeof(wall), 0);
6187 clearbufbyte(§or, sizeof(sector), 0);
6188 clearbufbyte(&sprite, sizeof(sprite), 0);
6189 */
6190
6191 initspritelists();
6192
6193 #define MYMAXSECTORS (mapversion==7l?MAXSECTORSV7:MAXSECTORSV8)
6194 #define MYMAXWALLS (mapversion==7l?MAXWALLSV7:MAXWALLSV8)
6195 #define MYMAXSPRITES (mapversion==7l?MAXSPRITESV7:MAXSPRITESV8)
6196
6197 clearbuf(&show2dsector[0],(int)((MAXSECTORS+3)>>5),0L);
6198 clearbuf(&show2dsprite[0],(int)((MAXSPRITES+3)>>5),0L);
6199 clearbuf(&show2dwall[0],(int)((MAXWALLS+3)>>5),0L);
6200
6201 kread(fil,daposx,4); *daposx = B_LITTLE32(*daposx);
6202 kread(fil,daposy,4); *daposy = B_LITTLE32(*daposy);
6203 kread(fil,daposz,4); *daposz = B_LITTLE32(*daposz);
6204 kread(fil,daang,2); *daang = B_LITTLE16(*daang);
6205 kread(fil,dacursectnum,2); *dacursectnum = B_LITTLE16(*dacursectnum);
6206
6207 kread(fil,&numsectors,2); numsectors = B_LITTLE16(numsectors);
6208 if (numsectors > MYMAXSECTORS) { kclose(fil); return(-1); }
6209 kread(fil,§or[0],sizeof(sectortype)*numsectors);
6210 for (i=numsectors-1; i>=0; i--) {
6211 sector[i].wallptr = B_LITTLE16(sector[i].wallptr);
6212 sector[i].wallnum = B_LITTLE16(sector[i].wallnum);
6213 sector[i].ceilingz = B_LITTLE32(sector[i].ceilingz);
6214 sector[i].floorz = B_LITTLE32(sector[i].floorz);
6215 sector[i].ceilingstat = B_LITTLE16(sector[i].ceilingstat);
6216 sector[i].floorstat = B_LITTLE16(sector[i].floorstat);
6217 sector[i].ceilingpicnum = B_LITTLE16(sector[i].ceilingpicnum);
6218 sector[i].ceilingheinum = B_LITTLE16(sector[i].ceilingheinum);
6219 sector[i].floorpicnum = B_LITTLE16(sector[i].floorpicnum);
6220 sector[i].floorheinum = B_LITTLE16(sector[i].floorheinum);
6221 sector[i].lotag = B_LITTLE16(sector[i].lotag);
6222 sector[i].hitag = B_LITTLE16(sector[i].hitag);
6223 sector[i].extra = B_LITTLE16(sector[i].extra);
6224 }
6225
6226 kread(fil,&numwalls,2); numwalls = B_LITTLE16(numwalls);
6227 if (numwalls > MYMAXWALLS) { kclose(fil); return(-1); }
6228 kread(fil,&wall[0],sizeof(walltype)*numwalls);
6229 for (i=numwalls-1; i>=0; i--) {
6230 wall[i].x = B_LITTLE32(wall[i].x);
6231 wall[i].y = B_LITTLE32(wall[i].y);
6232 wall[i].point2 = B_LITTLE16(wall[i].point2);
6233 wall[i].nextwall = B_LITTLE16(wall[i].nextwall);
6234 wall[i].nextsector = B_LITTLE16(wall[i].nextsector);
6235 wall[i].cstat = B_LITTLE16(wall[i].cstat);
6236 wall[i].picnum = B_LITTLE16(wall[i].picnum);
6237 wall[i].overpicnum = B_LITTLE16(wall[i].overpicnum);
6238 wall[i].lotag = B_LITTLE16(wall[i].lotag);
6239 wall[i].hitag = B_LITTLE16(wall[i].hitag);
6240 wall[i].extra = B_LITTLE16(wall[i].extra);
6241 }
6242
6243 kread(fil,&numsprites,2); numsprites = B_LITTLE16(numsprites);
6244 if (numsprites > MYMAXSPRITES) { kclose(fil); return(-1); }
6245 kread(fil,&sprite[0],sizeof(spritetype)*numsprites);
6246 for (i=numsprites-1; i>=0; i--) {
6247 sprite[i].x = B_LITTLE32(sprite[i].x);
6248 sprite[i].y = B_LITTLE32(sprite[i].y);
6249 sprite[i].z = B_LITTLE32(sprite[i].z);
6250 sprite[i].cstat = B_LITTLE16(sprite[i].cstat);
6251 sprite[i].picnum = B_LITTLE16(sprite[i].picnum);
6252 sprite[i].sectnum = B_LITTLE16(sprite[i].sectnum);
6253 sprite[i].statnum = B_LITTLE16(sprite[i].statnum);
6254 sprite[i].ang = B_LITTLE16(sprite[i].ang);
6255 sprite[i].owner = B_LITTLE16(sprite[i].owner);
6256 sprite[i].xvel = B_LITTLE16(sprite[i].xvel);
6257 sprite[i].yvel = B_LITTLE16(sprite[i].yvel);
6258 sprite[i].zvel = B_LITTLE16(sprite[i].zvel);
6259 sprite[i].lotag = B_LITTLE16(sprite[i].lotag);
6260 sprite[i].hitag = B_LITTLE16(sprite[i].hitag);
6261 sprite[i].extra = B_LITTLE16(sprite[i].extra);
6262 }
6263
6264 for(i=0;i<numsprites;i++) {
6265 if ((sprite[i].cstat & 48) == 48) sprite[i].cstat &= ~48;
6266 insertsprite(sprite[i].sectnum,sprite[i].statnum);
6267 }
6268
6269 //Must be after loading sectors, etc!
6270 updatesector(*daposx,*daposy,dacursectnum);
6271
6272 kclose(fil);
6273
6274 #if USE_POLYMOST && USE_OPENGL
6275 memset(spriteext, 0, sizeof(spriteext));
6276 #endif
6277 guniqhudid = 0;
6278
6279 return(0);
6280 }
6281
6282
6283 //
6284 // loadboardv5/6
6285 //
6286 struct sectortypev5
6287 {
6288 unsigned short wallptr, wallnum;
6289 short ceilingpicnum, floorpicnum;
6290 short ceilingheinum, floorheinum;
6291 int ceilingz, floorz;
6292 signed char ceilingshade, floorshade;
6293 unsigned char ceilingxpanning, floorxpanning;
6294 unsigned char ceilingypanning, floorypanning;
6295 unsigned char ceilingstat, floorstat;
6296 unsigned char ceilingpal, floorpal;
6297 unsigned char visibility;
6298 short lotag, hitag;
6299 short extra;
6300 };
6301 struct walltypev5
6302 {
6303 int x, y;
6304 short point2;
6305 short picnum, overpicnum;
6306 signed char shade;
6307 short cstat;
6308 unsigned char xrepeat, yrepeat, xpanning, ypanning;
6309 short nextsector1, nextwall1;
6310 short nextsector2, nextwall2;
6311 short lotag, hitag;
6312 short extra;
6313 };
6314 struct spritetypev5
6315 {
6316 int x, y, z;
6317 unsigned char cstat;
6318 signed char shade;
6319 unsigned char xrepeat, yrepeat;
6320 short picnum, ang, xvel, yvel, zvel, owner;
6321 short sectnum, statnum;
6322 short lotag, hitag;
6323 short extra;
6324 };
6325 struct sectortypev6
6326 {
6327 unsigned short wallptr, wallnum;
6328 short ceilingpicnum, floorpicnum;
6329 short ceilingheinum, floorheinum;
6330 int ceilingz, floorz;
6331 signed char ceilingshade, floorshade;
6332 unsigned char ceilingxpanning, floorxpanning;
6333 unsigned char ceilingypanning, floorypanning;
6334 unsigned char ceilingstat, floorstat;
6335 unsigned char ceilingpal, floorpal;
6336 unsigned char visibility;
6337 short lotag, hitag, extra;
6338 };
6339 struct walltypev6
6340 {
6341 int x, y;
6342 short point2, nextsector, nextwall;
6343 short picnum, overpicnum;
6344 signed char shade;
6345 unsigned char pal;
6346 short cstat;
6347 unsigned char xrepeat, yrepeat, xpanning, ypanning;
6348 short lotag, hitag, extra;
6349 };
6350 struct spritetypev6
6351 {
6352 int x, y, z;
6353 short cstat;
6354 signed char shade;
6355 unsigned char pal, clipdist;
6356 unsigned char xrepeat, yrepeat;
6357 signed char xoffset, yoffset;
6358 short picnum, ang, xvel, yvel, zvel, owner;
6359 short sectnum, statnum;
6360 short lotag, hitag, extra;
6361 };
6362
sectorofwallv5(short theline)6363 static short sectorofwallv5(short theline)
6364 {
6365 short i, startwall, endwall, sucksect;
6366
6367 sucksect = -1;
6368 for(i=0;i<numsectors;i++)
6369 {
6370 startwall = sector[i].wallptr;
6371 endwall = startwall + sector[i].wallnum - 1;
6372 if ((theline >= startwall) && (theline <= endwall))
6373 {
6374 sucksect = i;
6375 break;
6376 }
6377 }
6378 return(sucksect);
6379 }
6380
readv5sect(int fil,struct sectortypev5 * sect)6381 static int readv5sect(int fil, struct sectortypev5 *sect)
6382 {
6383 if (kread(fil, §->wallptr, 2) != 2) return -1;
6384 if (kread(fil, §->wallnum, 2) != 2) return -1;
6385 if (kread(fil, §->ceilingpicnum, 2) != 2) return -1;
6386 if (kread(fil, §->floorpicnum, 2) != 2) return -1;
6387 if (kread(fil, §->ceilingheinum, 2) != 2) return -1;
6388 if (kread(fil, §->floorheinum, 2) != 2) return -1;
6389 if (kread(fil, §->ceilingz, 4) != 4) return -1;
6390 if (kread(fil, §->floorz, 4) != 4) return -1;
6391 if (kread(fil, §->ceilingshade, 1) != 1) return -1;
6392 if (kread(fil, §->floorshade, 1) != 1) return -1;
6393 if (kread(fil, §->ceilingxpanning, 1) != 1) return -1;
6394 if (kread(fil, §->floorxpanning, 1) != 1) return -1;
6395 if (kread(fil, §->ceilingypanning, 1) != 1) return -1;
6396 if (kread(fil, §->floorypanning, 1) != 1) return -1;
6397 if (kread(fil, §->ceilingstat, 1) != 1) return -1;
6398 if (kread(fil, §->floorstat, 1) != 1) return -1;
6399 if (kread(fil, §->ceilingpal, 1) != 1) return -1;
6400 if (kread(fil, §->floorpal, 1) != 1) return -1;
6401 if (kread(fil, §->visibility, 1) != 1) return -1;
6402 if (kread(fil, §->lotag, 2) != 2) return -1;
6403 if (kread(fil, §->hitag, 2) != 2) return -1;
6404 if (kread(fil, §->extra, 2) != 2) return -1;
6405
6406 sect->wallptr = B_LITTLE16(sect->wallptr);
6407 sect->wallnum = B_LITTLE16(sect->wallnum);
6408 sect->ceilingpicnum = B_LITTLE16(sect->ceilingpicnum);
6409 sect->floorpicnum = B_LITTLE16(sect->floorpicnum);
6410 sect->ceilingheinum = B_LITTLE16(sect->ceilingheinum);
6411 sect->floorheinum = B_LITTLE16(sect->floorheinum);
6412 sect->ceilingz = B_LITTLE32(sect->ceilingz);
6413 sect->floorz = B_LITTLE32(sect->floorz);
6414 sect->lotag = B_LITTLE16(sect->lotag);
6415 sect->hitag = B_LITTLE16(sect->hitag);
6416 sect->extra = B_LITTLE16(sect->extra);
6417
6418 return 0;
6419 }
6420
writev5sect(int fil,struct sectortypev5 * sect)6421 static int writev5sect(int fil, struct sectortypev5 *sect)
6422 {
6423 uint32_t tl;
6424 uint16_t ts;
6425
6426 ts = B_LITTLE16(sect->wallptr); if (Bwrite(fil, &ts, 2) != 2) return -1;
6427 ts = B_LITTLE16(sect->wallnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6428 ts = B_LITTLE16(sect->ceilingpicnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6429 ts = B_LITTLE16(sect->floorpicnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6430 ts = B_LITTLE16(sect->ceilingheinum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6431 ts = B_LITTLE16(sect->floorheinum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6432 tl = B_LITTLE32(sect->ceilingz); if (Bwrite(fil, &tl, 4) != 4) return -1;
6433 tl = B_LITTLE32(sect->floorz); if (Bwrite(fil, &tl, 4) != 4) return -1;
6434 if (Bwrite(fil, §->ceilingshade, 1) != 1) return -1;
6435 if (Bwrite(fil, §->floorshade, 1) != 1) return -1;
6436 if (Bwrite(fil, §->ceilingxpanning, 1) != 1) return -1;
6437 if (Bwrite(fil, §->floorxpanning, 1) != 1) return -1;
6438 if (Bwrite(fil, §->ceilingypanning, 1) != 1) return -1;
6439 if (Bwrite(fil, §->floorypanning, 1) != 1) return -1;
6440 if (Bwrite(fil, §->ceilingstat, 1) != 1) return -1;
6441 if (Bwrite(fil, §->floorstat, 1) != 1) return -1;
6442 if (Bwrite(fil, §->ceilingpal, 1) != 1) return -1;
6443 if (Bwrite(fil, §->floorpal, 1) != 1) return -1;
6444 if (Bwrite(fil, §->visibility, 1) != 1) return -1;
6445 ts = B_LITTLE16(sect->lotag); if (Bwrite(fil, &ts, 2) != 2) return -1;
6446 ts = B_LITTLE16(sect->hitag); if (Bwrite(fil, &ts, 2) != 2) return -1;
6447 ts = B_LITTLE16(sect->extra); if (Bwrite(fil, &ts, 2) != 2) return -1;
6448
6449 return 0;
6450 }
6451
convertv5sectv6(struct sectortypev5 * from,struct sectortypev6 * to)6452 static void convertv5sectv6(struct sectortypev5 *from, struct sectortypev6 *to)
6453 {
6454 to->wallptr = from->wallptr;
6455 to->wallnum = from->wallnum;
6456 to->ceilingpicnum = from->ceilingpicnum;
6457 to->floorpicnum = from->floorpicnum;
6458 to->ceilingheinum = from->ceilingheinum;
6459 to->floorheinum = from->floorheinum;
6460 to->ceilingz = from->ceilingz;
6461 to->floorz = from->floorz;
6462 to->ceilingshade = from->ceilingshade;
6463 to->floorshade = from->floorshade;
6464 to->ceilingxpanning = from->ceilingxpanning;
6465 to->floorxpanning = from->floorxpanning;
6466 to->ceilingypanning = from->ceilingypanning;
6467 to->floorypanning = from->floorypanning;
6468 to->ceilingstat = from->ceilingstat;
6469 to->floorstat = from->floorstat;
6470 to->ceilingpal = from->ceilingpal;
6471 to->floorpal = from->floorpal;
6472 to->visibility = from->visibility;
6473 to->lotag = from->lotag;
6474 to->hitag = from->hitag;
6475 to->extra = from->extra;
6476 }
6477
convertv6sectv5(struct sectortypev6 * from,struct sectortypev5 * to)6478 static void convertv6sectv5(struct sectortypev6 *from, struct sectortypev5 *to)
6479 {
6480 to->wallptr = from->wallptr;
6481 to->wallnum = from->wallnum;
6482 to->ceilingpicnum = from->ceilingpicnum;
6483 to->floorpicnum = from->floorpicnum;
6484 to->ceilingheinum = from->ceilingheinum;
6485 to->floorheinum = from->floorheinum;
6486 to->ceilingz = from->ceilingz;
6487 to->floorz = from->floorz;
6488 to->ceilingshade = from->ceilingshade;
6489 to->floorshade = from->floorshade;
6490 to->ceilingxpanning = from->ceilingxpanning;
6491 to->floorxpanning = from->floorxpanning;
6492 to->ceilingypanning = from->ceilingypanning;
6493 to->floorypanning = from->floorypanning;
6494 to->ceilingstat = from->ceilingstat;
6495 to->floorstat = from->floorstat;
6496 to->ceilingpal = from->ceilingpal;
6497 to->floorpal = from->floorpal;
6498 to->visibility = from->visibility;
6499 to->lotag = from->lotag;
6500 to->hitag = from->hitag;
6501 to->extra = from->extra;
6502 }
6503
readv5wall(int fil,struct walltypev5 * wall)6504 static int readv5wall(int fil, struct walltypev5 *wall)
6505 {
6506 if (kread(fil, &wall->x, 4) != 4) return -1;
6507 if (kread(fil, &wall->y, 4) != 4) return -1;
6508 if (kread(fil, &wall->point2, 2) != 2) return -1;
6509 if (kread(fil, &wall->picnum, 2) != 2) return -1;
6510 if (kread(fil, &wall->overpicnum, 2) != 2) return -1;
6511 if (kread(fil, &wall->shade, 1) != 1) return -1;
6512 if (kread(fil, &wall->cstat, 2) != 2) return -1;
6513 if (kread(fil, &wall->xrepeat, 1) != 1) return -1;
6514 if (kread(fil, &wall->yrepeat, 1) != 1) return -1;
6515 if (kread(fil, &wall->xpanning, 1) != 1) return -1;
6516 if (kread(fil, &wall->ypanning, 1) != 1) return -1;
6517 if (kread(fil, &wall->nextsector1, 2) != 2) return -1;
6518 if (kread(fil, &wall->nextwall1, 2) != 2) return -1;
6519 if (kread(fil, &wall->nextsector2, 2) != 2) return -1;
6520 if (kread(fil, &wall->nextwall2, 2) != 2) return -1;
6521 if (kread(fil, &wall->lotag, 2) != 2) return -1;
6522 if (kread(fil, &wall->hitag, 2) != 2) return -1;
6523 if (kread(fil, &wall->extra, 2) != 2) return -1;
6524
6525 wall->x = B_LITTLE32(wall->x);
6526 wall->y = B_LITTLE32(wall->y);
6527 wall->point2 = B_LITTLE16(wall->point2);
6528 wall->picnum = B_LITTLE16(wall->picnum);
6529 wall->overpicnum = B_LITTLE16(wall->overpicnum);
6530 wall->cstat = B_LITTLE16(wall->cstat);
6531 wall->nextsector1 = B_LITTLE16(wall->nextsector1);
6532 wall->nextwall1 = B_LITTLE16(wall->nextwall1);
6533 wall->nextsector2 = B_LITTLE16(wall->nextsector2);
6534 wall->nextwall2 = B_LITTLE16(wall->nextwall2);
6535 wall->lotag = B_LITTLE16(wall->lotag);
6536 wall->hitag = B_LITTLE16(wall->hitag);
6537 wall->extra = B_LITTLE16(wall->extra);
6538
6539 return 0;
6540 }
6541
writev5wall(int fil,struct walltypev5 * wall)6542 static int writev5wall(int fil, struct walltypev5 *wall)
6543 {
6544 uint32_t tl;
6545 uint16_t ts;
6546
6547 tl = B_LITTLE32(wall->x); if (Bwrite(fil, &tl, 4) != 4) return -1;
6548 tl = B_LITTLE32(wall->y); if (Bwrite(fil, &tl, 4) != 4) return -1;
6549 ts = B_LITTLE16(wall->point2); if (Bwrite(fil, &ts, 2) != 2) return -1;
6550 ts = B_LITTLE16(wall->picnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6551 ts = B_LITTLE16(wall->overpicnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6552 if (Bwrite(fil, &wall->shade, 1) != 1) return -1;
6553 ts = B_LITTLE16(wall->cstat); if (Bwrite(fil, &ts, 2) != 2) return -1;
6554 if (Bwrite(fil, &wall->xrepeat, 1) != 1) return -1;
6555 if (Bwrite(fil, &wall->yrepeat, 1) != 1) return -1;
6556 if (Bwrite(fil, &wall->xpanning, 1) != 1) return -1;
6557 if (Bwrite(fil, &wall->ypanning, 1) != 1) return -1;
6558 ts = B_LITTLE16(wall->nextsector1); if (Bwrite(fil, &ts, 2) != 2) return -1;
6559 ts = B_LITTLE16(wall->nextwall1); if (Bwrite(fil, &ts, 2) != 2) return -1;
6560 ts = B_LITTLE16(wall->nextsector2); if (Bwrite(fil, &ts, 2) != 2) return -1;
6561 ts = B_LITTLE16(wall->nextwall2); if (Bwrite(fil, &ts, 2) != 2) return -1;
6562 ts = B_LITTLE16(wall->lotag); if (Bwrite(fil, &ts, 2) != 2) return -1;
6563 ts = B_LITTLE16(wall->hitag); if (Bwrite(fil, &ts, 2) != 2) return -1;
6564 ts = B_LITTLE16(wall->extra); if (Bwrite(fil, &ts, 2) != 2) return -1;
6565
6566 return 0;
6567 }
6568
convertv5wallv6(struct walltypev5 * from,struct walltypev6 * to,int i)6569 static void convertv5wallv6(struct walltypev5 *from, struct walltypev6 *to, int i)
6570 {
6571 to->x = from->x;
6572 to->y = from->y;
6573 to->point2 = from->point2;
6574 to->nextsector = from->nextsector1;
6575 to->nextwall = from->nextwall1;
6576 to->picnum = from->picnum;
6577 to->overpicnum = from->overpicnum;
6578 to->shade = from->shade;
6579 to->pal = sector[sectorofwallv5((short)i)].floorpal;
6580 to->cstat = from->cstat;
6581 to->xrepeat = from->xrepeat;
6582 to->yrepeat = from->yrepeat;
6583 to->xpanning = from->xpanning;
6584 to->ypanning = from->ypanning;
6585 to->lotag = from->lotag;
6586 to->hitag = from->hitag;
6587 to->extra = from->extra;
6588 }
6589
convertv6wallv5(struct walltypev6 * from,struct walltypev5 * to)6590 static void convertv6wallv5(struct walltypev6 *from, struct walltypev5 *to)
6591 {
6592 to->x = from->x;
6593 to->y = from->y;
6594 to->point2 = from->point2;
6595 to->nextsector1 = from->nextsector;
6596 to->nextwall1 = from->nextwall;
6597 to->nextsector2 = -1;
6598 to->nextwall2 = -1;
6599 to->picnum = from->picnum;
6600 to->overpicnum = from->overpicnum;
6601 to->shade = from->shade;
6602 to->cstat = from->cstat;
6603 to->xrepeat = from->xrepeat;
6604 to->yrepeat = from->yrepeat;
6605 to->xpanning = from->xpanning;
6606 to->ypanning = from->ypanning;
6607 to->lotag = from->lotag;
6608 to->hitag = from->hitag;
6609 to->extra = from->extra;
6610 }
6611
readv5sprite(int fil,struct spritetypev5 * spr)6612 static int readv5sprite(int fil, struct spritetypev5 *spr)
6613 {
6614 if (kread(fil, &spr->x, 4) != 4) return -1;
6615 if (kread(fil, &spr->y, 4) != 4) return -1;
6616 if (kread(fil, &spr->z, 4) != 4) return -1;
6617 if (kread(fil, &spr->cstat, 1) != 1) return -1;
6618 if (kread(fil, &spr->shade, 1) != 1) return -1;
6619 if (kread(fil, &spr->xrepeat, 1) != 1) return -1;
6620 if (kread(fil, &spr->yrepeat, 1) != 1) return -1;
6621 if (kread(fil, &spr->picnum, 2) != 2) return -1;
6622 if (kread(fil, &spr->ang, 2) != 2) return -1;
6623 if (kread(fil, &spr->xvel, 2) != 2) return -1;
6624 if (kread(fil, &spr->yvel, 2) != 2) return -1;
6625 if (kread(fil, &spr->zvel, 2) != 2) return -1;
6626 if (kread(fil, &spr->owner, 2) != 2) return -1;
6627 if (kread(fil, &spr->sectnum, 2) != 2) return -1;
6628 if (kread(fil, &spr->statnum, 2) != 2) return -1;
6629 if (kread(fil, &spr->lotag, 2) != 2) return -1;
6630 if (kread(fil, &spr->hitag, 2) != 2) return -1;
6631 if (kread(fil, &spr->extra, 2) != 2) return -1;
6632
6633 spr->x = B_LITTLE32(spr->x);
6634 spr->y = B_LITTLE32(spr->y);
6635 spr->z = B_LITTLE32(spr->z);
6636 spr->picnum = B_LITTLE16(spr->picnum);
6637 spr->ang = B_LITTLE16(spr->ang);
6638 spr->xvel = B_LITTLE16(spr->xvel);
6639 spr->yvel = B_LITTLE16(spr->yvel);
6640 spr->zvel = B_LITTLE16(spr->zvel);
6641 spr->owner = B_LITTLE16(spr->owner);
6642 spr->sectnum = B_LITTLE16(spr->sectnum);
6643 spr->statnum = B_LITTLE16(spr->statnum);
6644 spr->lotag = B_LITTLE16(spr->lotag);
6645 spr->hitag = B_LITTLE16(spr->hitag);
6646 spr->extra = B_LITTLE16(spr->extra);
6647
6648 return 0;
6649 }
6650
writev5sprite(int fil,struct spritetypev5 * spr)6651 static int writev5sprite(int fil, struct spritetypev5 *spr)
6652 {
6653 uint32_t tl;
6654 uint16_t ts;
6655
6656 tl = B_LITTLE32(spr->x); if (Bwrite(fil, &tl, 4) != 4) return -1;
6657 tl = B_LITTLE32(spr->y); if (Bwrite(fil, &tl, 4) != 4) return -1;
6658 tl = B_LITTLE32(spr->z); if (Bwrite(fil, &tl, 4) != 4) return -1;
6659 if (Bwrite(fil, &spr->cstat, 1) != 1) return -1;
6660 if (Bwrite(fil, &spr->shade, 1) != 1) return -1;
6661 if (Bwrite(fil, &spr->xrepeat, 1) != 1) return -1;
6662 if (Bwrite(fil, &spr->yrepeat, 1) != 1) return -1;
6663 ts = B_LITTLE16(spr->picnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6664 ts = B_LITTLE16(spr->ang); if (Bwrite(fil, &ts, 2) != 2) return -1;
6665 ts = B_LITTLE16(spr->xvel); if (Bwrite(fil, &ts, 2) != 2) return -1;
6666 ts = B_LITTLE16(spr->yvel); if (Bwrite(fil, &ts, 2) != 2) return -1;
6667 ts = B_LITTLE16(spr->zvel); if (Bwrite(fil, &ts, 2) != 2) return -1;
6668 ts = B_LITTLE16(spr->owner); if (Bwrite(fil, &ts, 2) != 2) return -1;
6669 ts = B_LITTLE16(spr->sectnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6670 ts = B_LITTLE16(spr->statnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6671 ts = B_LITTLE16(spr->lotag); if (Bwrite(fil, &ts, 2) != 2) return -1;
6672 ts = B_LITTLE16(spr->hitag); if (Bwrite(fil, &ts, 2) != 2) return -1;
6673 ts = B_LITTLE16(spr->extra); if (Bwrite(fil, &ts, 2) != 2) return -1;
6674
6675 return 0;
6676 }
6677
convertv5sprv6(struct spritetypev5 * from,struct spritetypev6 * to)6678 static void convertv5sprv6(struct spritetypev5 *from, struct spritetypev6 *to)
6679 {
6680 short j;
6681 to->x = from->x;
6682 to->y = from->y;
6683 to->z = from->z;
6684 to->cstat = from->cstat;
6685 to->shade = from->shade;
6686
6687 j = from->sectnum;
6688 if ((sector[j].ceilingstat&1) > 0)
6689 to->pal = sector[j].ceilingpal;
6690 else
6691 to->pal = sector[j].floorpal;
6692
6693 to->clipdist = 32;
6694 to->xrepeat = from->xrepeat;
6695 to->yrepeat = from->yrepeat;
6696 to->xoffset = 0;
6697 to->yoffset = 0;
6698 to->picnum = from->picnum;
6699 to->ang = from->ang;
6700 to->xvel = from->xvel;
6701 to->yvel = from->yvel;
6702 to->zvel = from->zvel;
6703 to->owner = from->owner;
6704 to->sectnum = from->sectnum;
6705 to->statnum = from->statnum;
6706 to->lotag = from->lotag;
6707 to->hitag = from->hitag;
6708 to->extra = from->extra;
6709 }
6710
convertv6sprv5(struct spritetypev6 * from,struct spritetypev5 * to)6711 static void convertv6sprv5(struct spritetypev6 *from, struct spritetypev5 *to)
6712 {
6713 to->x = from->x;
6714 to->y = from->y;
6715 to->z = from->z;
6716 to->cstat = (unsigned char)from->cstat;
6717 to->shade = from->shade;
6718 to->xrepeat = from->xrepeat;
6719 to->yrepeat = from->yrepeat;
6720 to->picnum = from->picnum;
6721 to->ang = from->ang;
6722 to->xvel = from->xvel;
6723 to->yvel = from->yvel;
6724 to->zvel = from->zvel;
6725 to->owner = from->owner;
6726 to->sectnum = from->sectnum;
6727 to->statnum = from->statnum;
6728 to->lotag = from->lotag;
6729 to->hitag = from->hitag;
6730 to->extra = from->extra;
6731 }
6732
readv6sect(int fil,struct sectortypev6 * sect)6733 static int readv6sect(int fil, struct sectortypev6 *sect)
6734 {
6735 if (kread(fil, §->wallptr, 2) != 2) return -1;
6736 if (kread(fil, §->wallnum, 2) != 2) return -1;
6737 if (kread(fil, §->ceilingpicnum, 2) != 2) return -1;
6738 if (kread(fil, §->floorpicnum, 2) != 2) return -1;
6739 if (kread(fil, §->ceilingheinum, 2) != 2) return -1;
6740 if (kread(fil, §->floorheinum, 2) != 2) return -1;
6741 if (kread(fil, §->ceilingz, 4) != 4) return -1;
6742 if (kread(fil, §->floorz, 4) != 4) return -1;
6743 if (kread(fil, §->ceilingshade, 1) != 1) return -1;
6744 if (kread(fil, §->floorshade, 1) != 1) return -1;
6745 if (kread(fil, §->ceilingxpanning, 1) != 1) return -1;
6746 if (kread(fil, §->floorxpanning, 1) != 1) return -1;
6747 if (kread(fil, §->ceilingypanning, 1) != 1) return -1;
6748 if (kread(fil, §->floorypanning, 1) != 1) return -1;
6749 if (kread(fil, §->ceilingstat, 1) != 1) return -1;
6750 if (kread(fil, §->floorstat, 1) != 1) return -1;
6751 if (kread(fil, §->ceilingpal, 1) != 1) return -1;
6752 if (kread(fil, §->floorpal, 1) != 1) return -1;
6753 if (kread(fil, §->visibility, 1) != 1) return -1;
6754 if (kread(fil, §->lotag, 2) != 2) return -1;
6755 if (kread(fil, §->hitag, 2) != 2) return -1;
6756 if (kread(fil, §->extra, 2) != 2) return -1;
6757
6758 sect->wallptr = B_LITTLE16(sect->wallptr);
6759 sect->wallnum = B_LITTLE16(sect->wallnum);
6760 sect->ceilingpicnum = B_LITTLE16(sect->ceilingpicnum);
6761 sect->floorpicnum = B_LITTLE16(sect->floorpicnum);
6762 sect->ceilingheinum = B_LITTLE16(sect->ceilingheinum);
6763 sect->floorheinum = B_LITTLE16(sect->floorheinum);
6764 sect->ceilingz = B_LITTLE32(sect->ceilingz);
6765 sect->floorz = B_LITTLE32(sect->floorz);
6766 sect->lotag = B_LITTLE16(sect->lotag);
6767 sect->hitag = B_LITTLE16(sect->hitag);
6768 sect->extra = B_LITTLE16(sect->extra);
6769
6770 return 0;
6771 }
6772
writev6sect(int fil,struct sectortypev6 * sect)6773 static int writev6sect(int fil, struct sectortypev6 *sect)
6774 {
6775 uint32_t tl;
6776 uint16_t ts;
6777
6778 ts = B_LITTLE16(sect->wallptr); if (Bwrite(fil, &ts, 2) != 2) return -1;
6779 ts = B_LITTLE16(sect->wallnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6780 ts = B_LITTLE16(sect->ceilingpicnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6781 ts = B_LITTLE16(sect->floorpicnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6782 ts = B_LITTLE16(sect->ceilingheinum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6783 ts = B_LITTLE16(sect->floorheinum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6784 tl = B_LITTLE32(sect->ceilingz); if (Bwrite(fil, &tl, 4) != 4) return -1;
6785 tl = B_LITTLE32(sect->floorz); if (Bwrite(fil, &tl, 4) != 4) return -1;
6786 if (Bwrite(fil, §->ceilingshade, 1) != 1) return -1;
6787 if (Bwrite(fil, §->floorshade, 1) != 1) return -1;
6788 if (Bwrite(fil, §->ceilingxpanning, 1) != 1) return -1;
6789 if (Bwrite(fil, §->floorxpanning, 1) != 1) return -1;
6790 if (Bwrite(fil, §->ceilingypanning, 1) != 1) return -1;
6791 if (Bwrite(fil, §->floorypanning, 1) != 1) return -1;
6792 if (Bwrite(fil, §->ceilingstat, 1) != 1) return -1;
6793 if (Bwrite(fil, §->floorstat, 1) != 1) return -1;
6794 if (Bwrite(fil, §->ceilingpal, 1) != 1) return -1;
6795 if (Bwrite(fil, §->floorpal, 1) != 1) return -1;
6796 if (Bwrite(fil, §->visibility, 1) != 1) return -1;
6797 ts = B_LITTLE16(sect->lotag); if (Bwrite(fil, &ts, 2) != 2) return -1;
6798 ts = B_LITTLE16(sect->hitag); if (Bwrite(fil, &ts, 2) != 2) return -1;
6799 ts = B_LITTLE16(sect->extra); if (Bwrite(fil, &ts, 2) != 2) return -1;
6800
6801 return 0;
6802 }
6803
convertv6sectv7(struct sectortypev6 * from,sectortype * to)6804 static void convertv6sectv7(struct sectortypev6 *from, sectortype *to)
6805 {
6806 to->ceilingz = from->ceilingz;
6807 to->floorz = from->floorz;
6808 to->wallptr = from->wallptr;
6809 to->wallnum = from->wallnum;
6810 to->ceilingpicnum = from->ceilingpicnum;
6811 to->ceilingheinum = max(min(((int)from->ceilingheinum)<<5,32767),-32768);
6812 if ((from->ceilingstat&2) == 0) to->ceilingheinum = 0;
6813 to->ceilingshade = from->ceilingshade;
6814 to->ceilingpal = from->ceilingpal;
6815 to->ceilingxpanning = from->ceilingxpanning;
6816 to->ceilingypanning = from->ceilingypanning;
6817 to->floorpicnum = from->floorpicnum;
6818 to->floorheinum = max(min(((int)from->floorheinum)<<5,32767),-32768);
6819 if ((from->floorstat&2) == 0) to->floorheinum = 0;
6820 to->floorshade = from->floorshade;
6821 to->floorpal = from->floorpal;
6822 to->floorxpanning = from->floorxpanning;
6823 to->floorypanning = from->floorypanning;
6824 to->ceilingstat = from->ceilingstat;
6825 to->floorstat = from->floorstat;
6826 to->visibility = from->visibility;
6827 to->filler = 0;
6828 to->lotag = from->lotag;
6829 to->hitag = from->hitag;
6830 to->extra = from->extra;
6831 }
6832
convertv7sectv6(sectortype * from,struct sectortypev6 * to)6833 static void convertv7sectv6(sectortype *from, struct sectortypev6 *to)
6834 {
6835 to->ceilingz = from->ceilingz;
6836 to->floorz = from->floorz;
6837 to->wallptr = from->wallptr;
6838 to->wallnum = from->wallnum;
6839 to->ceilingpicnum = from->ceilingpicnum;
6840 to->ceilingheinum = (((int)from->ceilingheinum)>>5);
6841 to->ceilingshade = from->ceilingshade;
6842 to->ceilingpal = from->ceilingpal;
6843 to->ceilingxpanning = from->ceilingxpanning;
6844 to->ceilingypanning = from->ceilingypanning;
6845 to->floorpicnum = from->floorpicnum;
6846 to->floorheinum = (((int)from->floorheinum)>>5);
6847 to->floorshade = from->floorshade;
6848 to->floorpal = from->floorpal;
6849 to->floorxpanning = from->floorxpanning;
6850 to->floorypanning = from->floorypanning;
6851 to->ceilingstat = from->ceilingstat;
6852 if (to->ceilingheinum == 0) to->ceilingstat &= ~2;
6853 to->floorstat = from->floorstat;
6854 if (to->floorheinum == 0) to->floorstat &= ~2;
6855 to->visibility = from->visibility;
6856 to->lotag = from->lotag;
6857 to->hitag = from->hitag;
6858 to->extra = from->extra;
6859 }
6860
readv6wall(int fil,struct walltypev6 * wall)6861 static int readv6wall(int fil, struct walltypev6 *wall)
6862 {
6863 if (kread(fil, &wall->x, 4) != 4) return -1;
6864 if (kread(fil, &wall->y, 4) != 4) return -1;
6865 if (kread(fil, &wall->point2, 2) != 2) return -1;
6866 if (kread(fil, &wall->nextsector, 2) != 2) return -1;
6867 if (kread(fil, &wall->nextwall, 2) != 2) return -1;
6868 if (kread(fil, &wall->picnum, 2) != 2) return -1;
6869 if (kread(fil, &wall->overpicnum, 2) != 2) return -1;
6870 if (kread(fil, &wall->shade, 1) != 1) return -1;
6871 if (kread(fil, &wall->pal, 1) != 1) return -1;
6872 if (kread(fil, &wall->cstat, 2) != 2) return -1;
6873 if (kread(fil, &wall->xrepeat, 1) != 1) return -1;
6874 if (kread(fil, &wall->yrepeat, 1) != 1) return -1;
6875 if (kread(fil, &wall->xpanning, 1) != 1) return -1;
6876 if (kread(fil, &wall->ypanning, 1) != 1) return -1;
6877 if (kread(fil, &wall->lotag, 2) != 2) return -1;
6878 if (kread(fil, &wall->hitag, 2) != 2) return -1;
6879 if (kread(fil, &wall->extra, 2) != 2) return -1;
6880
6881 wall->x = B_LITTLE32(wall->x);
6882 wall->y = B_LITTLE32(wall->y);
6883 wall->point2 = B_LITTLE16(wall->point2);
6884 wall->nextsector = B_LITTLE16(wall->nextsector);
6885 wall->nextwall = B_LITTLE16(wall->nextwall);
6886 wall->picnum = B_LITTLE16(wall->picnum);
6887 wall->overpicnum = B_LITTLE16(wall->overpicnum);
6888 wall->cstat = B_LITTLE16(wall->cstat);
6889 wall->lotag = B_LITTLE16(wall->lotag);
6890 wall->hitag = B_LITTLE16(wall->hitag);
6891 wall->extra = B_LITTLE16(wall->extra);
6892
6893 return 0;
6894 }
6895
writev6wall(int fil,struct walltypev6 * wall)6896 static int writev6wall(int fil, struct walltypev6 *wall)
6897 {
6898 uint32_t tl;
6899 uint16_t ts;
6900
6901 tl = B_LITTLE32(wall->x); if (Bwrite(fil, &tl, 4) != 4) return -1;
6902 tl = B_LITTLE32(wall->y); if (Bwrite(fil, &tl, 4) != 4) return -1;
6903 ts = B_LITTLE16(wall->point2); if (Bwrite(fil, &ts, 2) != 2) return -1;
6904 ts = B_LITTLE16(wall->nextsector); if (Bwrite(fil, &ts, 2) != 2) return -1;
6905 ts = B_LITTLE16(wall->nextwall); if (Bwrite(fil, &ts, 2) != 2) return -1;
6906 ts = B_LITTLE16(wall->picnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6907 ts = B_LITTLE16(wall->overpicnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
6908 if (Bwrite(fil, &wall->shade, 1) != 1) return -1;
6909 if (Bwrite(fil, &wall->pal, 1) != 1) return -1;
6910 ts = B_LITTLE16(wall->cstat); if (Bwrite(fil, &ts, 2) != 2) return -1;
6911 if (Bwrite(fil, &wall->xrepeat, 1) != 1) return -1;
6912 if (Bwrite(fil, &wall->yrepeat, 1) != 1) return -1;
6913 if (Bwrite(fil, &wall->xpanning, 1) != 1) return -1;
6914 if (Bwrite(fil, &wall->ypanning, 1) != 1) return -1;
6915 ts = B_LITTLE16(wall->lotag); if (Bwrite(fil, &ts, 2) != 2) return -1;
6916 ts = B_LITTLE16(wall->hitag); if (Bwrite(fil, &ts, 2) != 2) return -1;
6917 ts = B_LITTLE16(wall->extra); if (Bwrite(fil, &ts, 2) != 2) return -1;
6918
6919 return 0;
6920 }
6921
convertv6wallv7(struct walltypev6 * from,walltype * to)6922 static void convertv6wallv7(struct walltypev6 *from, walltype *to)
6923 {
6924 to->x = from->x;
6925 to->y = from->y;
6926 to->point2 = from->point2;
6927 to->nextwall = from->nextwall;
6928 to->nextsector = from->nextsector;
6929 to->cstat = from->cstat;
6930 to->picnum = from->picnum;
6931 to->overpicnum = from->overpicnum;
6932 to->shade = from->shade;
6933 to->pal = from->pal;
6934 to->xrepeat = from->xrepeat;
6935 to->yrepeat = from->yrepeat;
6936 to->xpanning = from->xpanning;
6937 to->ypanning = from->ypanning;
6938 to->lotag = from->lotag;
6939 to->hitag = from->hitag;
6940 to->extra = from->extra;
6941 }
6942
convertv7wallv6(walltype * from,struct walltypev6 * to)6943 static void convertv7wallv6(walltype *from, struct walltypev6 *to)
6944 {
6945 to->x = from->x;
6946 to->y = from->y;
6947 to->point2 = from->point2;
6948 to->nextwall = from->nextwall;
6949 to->nextsector = from->nextsector;
6950 to->cstat = from->cstat;
6951 to->picnum = from->picnum;
6952 to->overpicnum = from->overpicnum;
6953 to->shade = from->shade;
6954 to->pal = from->pal;
6955 to->xrepeat = from->xrepeat;
6956 to->yrepeat = from->yrepeat;
6957 to->xpanning = from->xpanning;
6958 to->ypanning = from->ypanning;
6959 to->lotag = from->lotag;
6960 to->hitag = from->hitag;
6961 to->extra = from->extra;
6962 }
6963
readv6sprite(int fil,struct spritetypev6 * spr)6964 static int readv6sprite(int fil, struct spritetypev6 *spr)
6965 {
6966 if (kread(fil, &spr->x, 4) != 4) return -1;
6967 if (kread(fil, &spr->y, 4) != 4) return -1;
6968 if (kread(fil, &spr->z, 4) != 4) return -1;
6969 if (kread(fil, &spr->cstat, 2) != 2) return -1;
6970 if (kread(fil, &spr->shade, 1) != 1) return -1;
6971 if (kread(fil, &spr->pal, 1) != 1) return -1;
6972 if (kread(fil, &spr->clipdist, 1) != 1) return -1;
6973 if (kread(fil, &spr->xrepeat, 1) != 1) return -1;
6974 if (kread(fil, &spr->yrepeat, 1) != 1) return -1;
6975 if (kread(fil, &spr->xoffset, 1) != 1) return -1;
6976 if (kread(fil, &spr->yoffset, 1) != 1) return -1;
6977 if (kread(fil, &spr->picnum, 2) != 2) return -1;
6978 if (kread(fil, &spr->ang, 2) != 2) return -1;
6979 if (kread(fil, &spr->xvel, 2) != 2) return -1;
6980 if (kread(fil, &spr->yvel, 2) != 2) return -1;
6981 if (kread(fil, &spr->zvel, 2) != 2) return -1;
6982 if (kread(fil, &spr->owner, 2) != 2) return -1;
6983 if (kread(fil, &spr->sectnum, 2) != 2) return -1;
6984 if (kread(fil, &spr->statnum, 2) != 2) return -1;
6985 if (kread(fil, &spr->lotag, 2) != 2) return -1;
6986 if (kread(fil, &spr->hitag, 2) != 2) return -1;
6987 if (kread(fil, &spr->extra, 2) != 2) return -1;
6988
6989 spr->x = B_LITTLE32(spr->x);
6990 spr->y = B_LITTLE32(spr->y);
6991 spr->z = B_LITTLE32(spr->z);
6992 spr->cstat = B_LITTLE16(spr->cstat);
6993 spr->picnum = B_LITTLE16(spr->picnum);
6994 spr->ang = B_LITTLE16(spr->ang);
6995 spr->xvel = B_LITTLE16(spr->xvel);
6996 spr->yvel = B_LITTLE16(spr->yvel);
6997 spr->zvel = B_LITTLE16(spr->zvel);
6998 spr->owner = B_LITTLE16(spr->owner);
6999 spr->sectnum = B_LITTLE16(spr->sectnum);
7000 spr->statnum = B_LITTLE16(spr->statnum);
7001 spr->lotag = B_LITTLE16(spr->lotag);
7002 spr->hitag = B_LITTLE16(spr->hitag);
7003 spr->extra = B_LITTLE16(spr->extra);
7004
7005 return 0;
7006 }
7007
writev6sprite(int fil,struct spritetypev6 * spr)7008 static int writev6sprite(int fil, struct spritetypev6 *spr)
7009 {
7010 uint32_t tl;
7011 uint16_t ts;
7012
7013 tl = B_LITTLE32(spr->x); if (Bwrite(fil, &tl, 4) != 4) return -1;
7014 tl = B_LITTLE32(spr->y); if (Bwrite(fil, &tl, 4) != 4) return -1;
7015 tl = B_LITTLE32(spr->z); if (Bwrite(fil, &tl, 4) != 4) return -1;
7016 ts = B_LITTLE16(spr->cstat); if (Bwrite(fil, &ts, 2) != 2) return -1;
7017 if (Bwrite(fil, &spr->shade, 1) != 1) return -1;
7018 if (Bwrite(fil, &spr->pal, 1) != 1) return -1;
7019 if (Bwrite(fil, &spr->clipdist, 1) != 1) return -1;
7020 if (Bwrite(fil, &spr->xrepeat, 1) != 1) return -1;
7021 if (Bwrite(fil, &spr->yrepeat, 1) != 1) return -1;
7022 if (Bwrite(fil, &spr->xoffset, 1) != 1) return -1;
7023 if (Bwrite(fil, &spr->yoffset, 1) != 1) return -1;
7024 ts = B_LITTLE16(spr->picnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
7025 ts = B_LITTLE16(spr->ang); if (Bwrite(fil, &ts, 2) != 2) return -1;
7026 ts = B_LITTLE16(spr->xvel); if (Bwrite(fil, &ts, 2) != 2) return -1;
7027 ts = B_LITTLE16(spr->yvel); if (Bwrite(fil, &ts, 2) != 2) return -1;
7028 ts = B_LITTLE16(spr->zvel); if (Bwrite(fil, &ts, 2) != 2) return -1;
7029 ts = B_LITTLE16(spr->owner); if (Bwrite(fil, &ts, 2) != 2) return -1;
7030 ts = B_LITTLE16(spr->sectnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
7031 ts = B_LITTLE16(spr->statnum); if (Bwrite(fil, &ts, 2) != 2) return -1;
7032 ts = B_LITTLE16(spr->lotag); if (Bwrite(fil, &ts, 2) != 2) return -1;
7033 ts = B_LITTLE16(spr->hitag); if (Bwrite(fil, &ts, 2) != 2) return -1;
7034 ts = B_LITTLE16(spr->extra); if (Bwrite(fil, &ts, 2) != 2) return -1;
7035
7036 return 0;
7037 }
7038
convertv6sprv7(struct spritetypev6 * from,spritetype * to)7039 static void convertv6sprv7(struct spritetypev6 *from, spritetype *to)
7040 {
7041 to->x = from->x;
7042 to->y = from->y;
7043 to->z = from->z;
7044 to->cstat = from->cstat;
7045 to->picnum = from->picnum;
7046 to->shade = from->shade;
7047 to->pal = from->pal;
7048 to->clipdist = from->clipdist;
7049 to->filler = 0;
7050 to->xrepeat = from->xrepeat;
7051 to->yrepeat = from->yrepeat;
7052 to->xoffset = from->xoffset;
7053 to->yoffset = from->yoffset;
7054 to->sectnum = from->sectnum;
7055 to->statnum = from->statnum;
7056 to->ang = from->ang;
7057 to->owner = from->owner;
7058 to->xvel = from->xvel;
7059 to->yvel = from->yvel;
7060 to->zvel = from->zvel;
7061 to->lotag = from->lotag;
7062 to->hitag = from->hitag;
7063 to->extra = from->extra;
7064 }
7065
convertv7sprv6(spritetype * from,struct spritetypev6 * to)7066 static void convertv7sprv6(spritetype *from, struct spritetypev6 *to)
7067 {
7068 to->x = from->x;
7069 to->y = from->y;
7070 to->z = from->z;
7071 to->cstat = from->cstat;
7072 to->picnum = from->picnum;
7073 to->shade = from->shade;
7074 to->pal = from->pal;
7075 to->clipdist = from->clipdist;
7076 to->xrepeat = from->xrepeat;
7077 to->yrepeat = from->yrepeat;
7078 to->xoffset = from->xoffset;
7079 to->yoffset = from->yoffset;
7080 to->sectnum = from->sectnum;
7081 to->statnum = from->statnum;
7082 to->ang = from->ang;
7083 to->owner = from->owner;
7084 to->xvel = from->xvel;
7085 to->yvel = from->yvel;
7086 to->zvel = from->zvel;
7087 to->lotag = from->lotag;
7088 to->hitag = from->hitag;
7089 to->extra = from->extra;
7090 }
7091
7092 // Powerslave uses v6
7093 // Witchaven 1 and TekWar use v5
loadoldboard(char * filename,char fromwhere,int * daposx,int * daposy,int * daposz,short * daang,short * dacursectnum)7094 int loadoldboard(char *filename, char fromwhere, int *daposx, int *daposy, int *daposz,
7095 short *daang, short *dacursectnum)
7096 {
7097 short fil, i, numsprites;
7098 struct sectortypev5 v5sect;
7099 struct walltypev5 v5wall;
7100 struct spritetypev5 v5spr;
7101 struct sectortypev6 v6sect;
7102 struct walltypev6 v6wall;
7103 struct spritetypev6 v6spr;
7104
7105 i = strlen(filename)-1;
7106 if ((unsigned char)filename[i] == 255) { filename[i] = 0; fromwhere = 1; } // JBF 20040119: "compatibility"
7107 if ((fil = kopen4load(filename,fromwhere)) == -1)
7108 { mapversion = 5L; return(-1); }
7109
7110 if (kread(fil,&mapversion,4) != 4) goto readerror;
7111 mapversion = B_LITTLE32(mapversion);
7112 if (mapversion != 5L && mapversion != 6L) {
7113 kclose(fil);
7114 return(-2);
7115 }
7116
7117 initspritelists();
7118
7119 clearbuf(&show2dsector[0],(int)((MAXSECTORS+3)>>5),0L);
7120 clearbuf(&show2dsprite[0],(int)((MAXSPRITES+3)>>5),0L);
7121 clearbuf(&show2dwall[0],(int)((MAXWALLS+3)>>5),0L);
7122
7123 if (kread(fil,daposx,4) != 4) goto readerror;
7124 if (kread(fil,daposy,4) != 4) goto readerror;
7125 if (kread(fil,daposz,4) != 4) goto readerror;
7126 if (kread(fil,daang,2) != 2) goto readerror;
7127 if (kread(fil,dacursectnum,2) != 2) goto readerror;
7128 *daposx = B_LITTLE32(*daposx);
7129 *daposy = B_LITTLE32(*daposy);
7130 *daposz = B_LITTLE32(*daposz);
7131 *daang = B_LITTLE16(*daang);
7132 *dacursectnum = B_LITTLE16(*dacursectnum);
7133
7134 if (kread(fil,&numsectors,2) != 2) goto readerror;
7135 numsectors = B_LITTLE16(numsectors);
7136 if (numsectors > MAXSECTORS) {
7137 kclose(fil);
7138 return(-1);
7139 }
7140
7141 for (i=0; i<numsectors; i++) {
7142 switch (mapversion) {
7143 case 5:
7144 if (readv5sect(fil,&v5sect)) goto readerror;
7145 convertv5sectv6(&v5sect,&v6sect);
7146 convertv6sectv7(&v6sect,§or[i]);
7147 break;
7148 case 6:
7149 if (readv6sect(fil,&v6sect)) goto readerror;
7150 convertv6sectv7(&v6sect,§or[i]);
7151 break;
7152 }
7153 }
7154
7155 if (kread(fil,&numwalls,2) != 2) goto readerror;
7156 numwalls = B_LITTLE16(numwalls);
7157 if (numwalls > MAXWALLS) {
7158 kclose(fil);
7159 return(-1);
7160 }
7161
7162 for (i=0; i<numwalls; i++) {
7163 switch (mapversion) {
7164 case 5:
7165 if (readv5wall(fil,&v5wall)) goto readerror;
7166 convertv5wallv6(&v5wall,&v6wall,i);
7167 convertv6wallv7(&v6wall,&wall[i]);
7168 break;
7169 case 6:
7170 if (readv6wall(fil,&v6wall)) goto readerror;
7171 convertv6wallv7(&v6wall,&wall[i]);
7172 break;
7173 }
7174 }
7175
7176 if (kread(fil,&numsprites,2) != 2) goto readerror;
7177 numsprites = B_LITTLE16(numsprites);
7178 if (numsprites > MAXSPRITES) {
7179 kclose(fil);
7180 return(-1);
7181 }
7182
7183 for (i=0; i<numsprites; i++) {
7184 switch (mapversion) {
7185 case 5:
7186 if (readv5sprite(fil,&v5spr)) goto readerror;
7187 convertv5sprv6(&v5spr,&v6spr);
7188 convertv6sprv7(&v6spr,&sprite[i]);
7189 break;
7190 case 6:
7191 if (readv6sprite(fil,&v6spr)) goto readerror;
7192 convertv6sprv7(&v6spr,&sprite[i]);
7193 break;
7194 }
7195 }
7196
7197 for(i=0;i<numsprites;i++) {
7198 if ((sprite[i].cstat & 48) == 48) sprite[i].cstat &= ~48;
7199 insertsprite(sprite[i].sectnum,sprite[i].statnum);
7200 }
7201
7202 //Must be after loading sectors, etc!
7203 updatesector(*daposx,*daposy,dacursectnum);
7204
7205 kclose(fil);
7206
7207 #if USE_POLYMOST && USE_OPENGL
7208 memset(spriteext, 0, sizeof(spriteext));
7209 #endif
7210 guniqhudid = 0;
7211
7212 return(0);
7213
7214 readerror:
7215 kclose(fil);
7216 return -3;
7217 }
7218
7219
7220 //
7221 // loadmaphack
7222 //
7223 #include "scriptfile.h"
loadmaphack(char * filename)7224 int loadmaphack(char *filename)
7225 {
7226 #if USE_POLYMOST && USE_OPENGL
7227 static struct { char *text; int tokenid; } legaltokens[] = {
7228 { "sprite", 0 },
7229 { "angleoff", 1 },
7230 { "angoff", 1 },
7231 { "notmd2", 2 },
7232 { "notmd3", 2 },
7233 { "notmd", 2 },
7234 { "nomd2anim", 3 },
7235 { "nomd3anim", 3 },
7236 { "nomdanim", 3 },
7237 { NULL, -1 }
7238 };
7239
7240 scriptfile *script;
7241 char *tok, *cmdtokptr;
7242 int i;
7243 int whichsprite = -1;
7244
7245 script = scriptfile_fromfile(filename);
7246 if (!script) return -1;
7247
7248 memset(spriteext, 0, sizeof(spriteext));
7249
7250 while (1) {
7251 tok = scriptfile_gettoken(script);
7252 if (!tok) break;
7253 for (i=0;legaltokens[i].text;i++) if (!Bstrcasecmp(tok,legaltokens[i].text)) break;
7254 cmdtokptr = script->ltextptr;
7255 switch (legaltokens[i].tokenid) {
7256 case 0: // sprite <xx>
7257 if (scriptfile_getnumber(script, &whichsprite)) break;
7258
7259 if ((unsigned)whichsprite >= (unsigned)MAXSPRITES) {
7260 // sprite number out of range
7261 buildprintf("Sprite number out of range 0-%d on line %s:%d\n",
7262 MAXSPRITES-1,script->filename, scriptfile_getlinum(script,cmdtokptr));
7263 whichsprite = -1;
7264 break;
7265 }
7266
7267 break;
7268 case 1: // angoff <xx>
7269 {
7270 int ang;
7271 if (scriptfile_getnumber(script, &ang)) break;
7272
7273 if (whichsprite < 0) {
7274 // no sprite directive preceeding
7275 buildprintf("Ignoring angle offset directive because of absent/invalid sprite number on line %s:%d\n",
7276 script->filename, scriptfile_getlinum(script,cmdtokptr));
7277 break;
7278 }
7279 spriteext[whichsprite].angoff = (short)ang;
7280 }
7281 break;
7282 case 2: // notmd
7283 if (whichsprite < 0) {
7284 // no sprite directive preceeding
7285 buildprintf("Ignoring not-MD2/MD3 directive because of absent/invalid sprite number on line %s:%d\n",
7286 script->filename, scriptfile_getlinum(script,cmdtokptr));
7287 break;
7288 }
7289 spriteext[whichsprite].flags |= SPREXT_NOTMD;
7290 break;
7291 case 3: // nomdanim
7292 if (whichsprite < 0) {
7293 // no sprite directive preceeding
7294 buildprintf("Ignoring no-MD2/MD3-anim directive because of absent/invalid sprite number on line %s:%d\n",
7295 script->filename, scriptfile_getlinum(script,cmdtokptr));
7296 break;
7297 }
7298 spriteext[whichsprite].flags |= SPREXT_NOMDANIM;
7299 break;
7300 default:
7301 // unrecognised token
7302 break;
7303 }
7304 }
7305
7306 scriptfile_close(script);
7307 #endif //USE_POLYMOST && USE_OPENGL
7308
7309 return 0;
7310 }
7311
7312
7313 //
7314 // saveboard
7315 //
saveboard(char * filename,int * daposx,int * daposy,int * daposz,short * daang,short * dacursectnum)7316 int saveboard(char *filename, int *daposx, int *daposy, int *daposz,
7317 short *daang, short *dacursectnum)
7318 {
7319 short fil, i, j, numsprites, ts;
7320 int tl;
7321 sectortype tsect;
7322 walltype twall;
7323 spritetype tspri;
7324
7325 if ((fil = Bopen(filename,BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY,BS_IREAD|BS_IWRITE)) == -1)
7326 return(-1);
7327
7328 numsprites = 0;
7329 for(j=0;j<MAXSTATUS;j++)
7330 {
7331 i = headspritestat[j];
7332 while (i != -1)
7333 {
7334 numsprites++;
7335 i = nextspritestat[i];
7336 }
7337 }
7338
7339 if (numsectors > MAXSECTORSV7 || numwalls > MAXWALLSV7 || numsprites > MAXSPRITESV7)
7340 mapversion = 8;
7341 else
7342 mapversion = 7;
7343 tl = B_LITTLE32(mapversion); Bwrite(fil,&tl,4);
7344
7345 tl = B_LITTLE32(*daposx); Bwrite(fil,&tl,4);
7346 tl = B_LITTLE32(*daposy); Bwrite(fil,&tl,4);
7347 tl = B_LITTLE32(*daposz); Bwrite(fil,&tl,4);
7348 ts = B_LITTLE16(*daang); Bwrite(fil,&ts,2);
7349 ts = B_LITTLE16(*dacursectnum); Bwrite(fil,&ts,2);
7350
7351 ts = B_LITTLE16(numsectors); Bwrite(fil,&ts,2);
7352 for (i=0; i<numsectors; i++) {
7353 tsect = sector[i];
7354 tsect.wallptr = B_LITTLE16(tsect.wallptr);
7355 tsect.wallnum = B_LITTLE16(tsect.wallnum);
7356 tsect.ceilingz = B_LITTLE32(tsect.ceilingz);
7357 tsect.floorz = B_LITTLE32(tsect.floorz);
7358 tsect.ceilingstat = B_LITTLE16(tsect.ceilingstat);
7359 tsect.floorstat = B_LITTLE16(tsect.floorstat);
7360 tsect.ceilingpicnum = B_LITTLE16(tsect.ceilingpicnum);
7361 tsect.ceilingheinum = B_LITTLE16(tsect.ceilingheinum);
7362 tsect.floorpicnum = B_LITTLE16(tsect.floorpicnum);
7363 tsect.floorheinum = B_LITTLE16(tsect.floorheinum);
7364 tsect.lotag = B_LITTLE16(tsect.lotag);
7365 tsect.hitag = B_LITTLE16(tsect.hitag);
7366 tsect.extra = B_LITTLE16(tsect.extra);
7367 Bwrite(fil,&tsect,sizeof(sectortype));
7368 }
7369
7370 ts = B_LITTLE16(numwalls); Bwrite(fil,&ts,2);
7371 for (i=0; i<numwalls; i++) {
7372 twall = wall[i];
7373 twall.x = B_LITTLE32(twall.x);
7374 twall.y = B_LITTLE32(twall.y);
7375 twall.point2 = B_LITTLE16(twall.point2);
7376 twall.nextwall = B_LITTLE16(twall.nextwall);
7377 twall.nextsector = B_LITTLE16(twall.nextsector);
7378 twall.cstat = B_LITTLE16(twall.cstat);
7379 twall.picnum = B_LITTLE16(twall.picnum);
7380 twall.overpicnum = B_LITTLE16(twall.overpicnum);
7381 twall.lotag = B_LITTLE16(twall.lotag);
7382 twall.hitag = B_LITTLE16(twall.hitag);
7383 twall.extra = B_LITTLE16(twall.extra);
7384 Bwrite(fil,&twall,sizeof(walltype));
7385 }
7386
7387 ts = B_LITTLE16(numsprites); Bwrite(fil,&ts,2);
7388
7389 for(j=0;j<MAXSTATUS;j++)
7390 {
7391 i = headspritestat[j];
7392 while (i != -1)
7393 {
7394 tspri = sprite[i];
7395 tspri.x = B_LITTLE32(tspri.x);
7396 tspri.y = B_LITTLE32(tspri.y);
7397 tspri.z = B_LITTLE32(tspri.z);
7398 tspri.cstat = B_LITTLE16(tspri.cstat);
7399 tspri.picnum = B_LITTLE16(tspri.picnum);
7400 tspri.sectnum = B_LITTLE16(tspri.sectnum);
7401 tspri.statnum = B_LITTLE16(tspri.statnum);
7402 tspri.ang = B_LITTLE16(tspri.ang);
7403 tspri.owner = B_LITTLE16(tspri.owner);
7404 tspri.xvel = B_LITTLE16(tspri.xvel);
7405 tspri.yvel = B_LITTLE16(tspri.yvel);
7406 tspri.zvel = B_LITTLE16(tspri.zvel);
7407 tspri.lotag = B_LITTLE16(tspri.lotag);
7408 tspri.hitag = B_LITTLE16(tspri.hitag);
7409 tspri.extra = B_LITTLE16(tspri.extra);
7410 Bwrite(fil,&tspri,sizeof(spritetype));
7411 i = nextspritestat[i];
7412 }
7413 }
7414
7415 Bclose(fil);
7416 return(0);
7417 }
7418
7419
saveoldboard(char * filename,int * daposx,int * daposy,int * daposz,short * daang,short * dacursectnum)7420 int saveoldboard(char *filename, int *daposx, int *daposy, int *daposz,
7421 short *daang, short *dacursectnum)
7422 {
7423 short fil, i, j, numsprites, ts;
7424 int tl;
7425 struct sectortypev5 v5sect;
7426 struct walltypev5 v5wall;
7427 struct spritetypev5 v5spr;
7428 struct sectortypev6 v6sect;
7429 struct walltypev6 v6wall;
7430 struct spritetypev6 v6spr;
7431
7432 if (mapversion != 5 && mapversion != 6) {
7433 buildputs("saveoldboard: map version not 5 or 6\n");
7434 return -2;
7435 }
7436
7437 numsprites = 0;
7438 for(j=0;j<MAXSTATUS;j++)
7439 {
7440 i = headspritestat[j];
7441 while (i != -1)
7442 {
7443 numsprites++;
7444 i = nextspritestat[i];
7445 }
7446 }
7447
7448 switch (mapversion) {
7449 case 5:
7450 if (numsectors > MAXSECTORSV5 || numwalls > MAXWALLSV5 || numsprites > MAXSPRITESV5) {
7451 buildprintf("saveoldboard: too many sectors/walls/sprites for map version 5 (%d/%d, %d/%d, %d/%d)\n",
7452 numsectors, MAXSECTORSV5, numwalls, MAXWALLSV5, numsprites, MAXSPRITESV5);
7453 return -2;
7454 }
7455 break;
7456 case 6:
7457 if (numsectors > MAXSECTORSV6 || numwalls > MAXWALLSV6 || numsprites > MAXSPRITESV6) {
7458 buildprintf("saveoldboard: too many sectors/walls/sprites for map version 6 (%d/%d, %d/%d, %d/%d)\n",
7459 numsectors, MAXSECTORSV6, numwalls, MAXWALLSV6, numsprites, MAXSPRITESV6);
7460 return -2;
7461 }
7462 break;
7463 }
7464
7465 if ((fil = Bopen(filename,BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY,BS_IREAD|BS_IWRITE)) == -1)
7466 return(-1);
7467
7468 tl = B_LITTLE32(mapversion);
7469 if (Bwrite(fil,&tl,4) != 4) goto writeerror;
7470
7471 tl = B_LITTLE32(*daposx);
7472 if (Bwrite(fil,&tl,4) != 4) goto writeerror;
7473 tl = B_LITTLE32(*daposy);
7474 if (Bwrite(fil,&tl,4) != 4) goto writeerror;
7475 tl = B_LITTLE32(*daposz);
7476 if (Bwrite(fil,&tl,4) != 4) goto writeerror;
7477 ts = B_LITTLE16(*daang);
7478 if (Bwrite(fil,&ts,2) != 2) goto writeerror;
7479 ts = B_LITTLE16(*dacursectnum);
7480 if (Bwrite(fil,&ts,2) != 2) goto writeerror;
7481
7482 ts = B_LITTLE16(numsectors);
7483 if (Bwrite(fil,&ts,2) != 2) goto writeerror;
7484 for (i=0; i<numsectors; i++) {
7485 switch (mapversion) {
7486 case 6:
7487 convertv7sectv6(§or[i], &v6sect);
7488 if (writev6sect(fil, &v6sect)) goto writeerror;
7489 break;
7490 case 5:
7491 convertv7sectv6(§or[i], &v6sect);
7492 convertv6sectv5(&v6sect, &v5sect);
7493 if (writev5sect(fil, &v5sect)) goto writeerror;
7494 break;
7495 }
7496 }
7497
7498 ts = B_LITTLE16(numwalls);
7499 if (Bwrite(fil,&ts,2) != 2) goto writeerror;
7500 for (i=0; i<numwalls; i++) {
7501 switch (mapversion) {
7502 case 6:
7503 convertv7wallv6(&wall[i], &v6wall);
7504 if (writev6wall(fil, &v6wall)) goto writeerror;
7505 break;
7506 case 5:
7507 convertv7wallv6(&wall[i], &v6wall);
7508 convertv6wallv5(&v6wall, &v5wall);
7509 if (writev5wall(fil, &v5wall)) goto writeerror;
7510 break;
7511 }
7512 }
7513
7514 ts = B_LITTLE16(numsprites);
7515 if (Bwrite(fil,&ts,2) != 2) goto writeerror;
7516 for(j=0;j<MAXSTATUS;j++)
7517 {
7518 i = headspritestat[j];
7519 while (i != -1)
7520 {
7521 switch (mapversion) {
7522 case 6:
7523 convertv7sprv6(&sprite[i], &v6spr);
7524 if (writev6sprite(fil, &v6spr)) goto writeerror;
7525 break;
7526 case 5:
7527 convertv7sprv6(&sprite[i], &v6spr);
7528 convertv6sprv5(&v6spr, &v5spr);
7529 if (writev5sprite(fil, &v5spr)) goto writeerror;
7530 break;
7531 }
7532 i = nextspritestat[i];
7533 }
7534 }
7535
7536 Bclose(fil);
7537 return(0);
7538
7539 writeerror:
7540 Bclose(fil);
7541 return -1;
7542 }
7543
7544
7545 //
7546 // setgamemode
7547 //
7548 // JBF: davidoption now functions as a windowed-mode flag (0 == windowed, 1 == fullscreen)
7549 extern char videomodereset;
setgamemode(char davidoption,int daxdim,int daydim,int dabpp)7550 int setgamemode(char davidoption, int daxdim, int daydim, int dabpp)
7551 {
7552 int i, j, oldbpp;
7553
7554 if ((qsetmode == 200) && (videomodereset == 0) &&
7555 (davidoption == fullscreen) && (xdim == daxdim) && (ydim == daydim) && (bpp == dabpp))
7556 return(0);
7557
7558 strcpy(kensmessage,"!!!! BUILD engine&tools programmed by Ken Silverman of E.G. RI. (c) Copyright 1995 Ken Silverman. Summary: BUILD = Ken. !!!!");
7559
7560 //if (checkvideomode(&daxdim, &daydim, dabpp, davidoption)<0) return (-1);
7561
7562 //bytesperline is set in this function
7563 oldbpp = bpp;
7564 if (setvideomode(daxdim,daydim,dabpp,davidoption) < 0) return(-1);
7565 daxdim = xres; daydim = yres; // The mode set might not be a perfect match to what we asked for.
7566
7567 // it's possible the previous call protected our code sections again
7568 makeasmwriteable();
7569
7570 #if USE_POLYMOST && USE_OPENGL
7571 if (dabpp > 8) rendmode = 3; // GL renderer
7572 else if (dabpp == 8 && oldbpp != 8) rendmode = 0; // going from GL to software activates classic
7573 #endif
7574
7575 xdim = daxdim; ydim = daydim;
7576
7577 // determine the corrective factor for pixel-squareness. Build
7578 // is built around the non-square pixels of Mode 13h, so to get
7579 // things back square on VGA screens, things need to be "compressed"
7580 // vertically a little.
7581 widescreen = 0;
7582 tallscreen = 0;
7583 if ((xdim == 320 && ydim == 200) || (xdim == 640 && ydim == 400)) {
7584 pixelaspect = 65536;
7585 } else {
7586 int ratio = divscale16(ydim*320, xdim*240);
7587 pixelaspect = divscale16(240*320L,320*200L);
7588
7589 if (ratio < 65536) {
7590 widescreen = 1;
7591 } else if (ratio > 65536) {
7592 tallscreen = 1;
7593
7594 // let tall screens (eg. 1280x1024) stretch the 2D elements
7595 // vertically a little until something better is thought of
7596 pixelaspect = divscale16(ydim*320L,xdim*200L);
7597 }
7598 }
7599
7600 j = ydim*4*sizeof(int); //Leave room for horizlookup&horizlookup2
7601
7602 if (lookups != NULL) { kfree((void *)lookups); lookups = NULL; }
7603 if ((lookups = kmalloc(j<<1)) == NULL) {
7604 engineerrstr = "Failed to allocate lookups memory";
7605 return -1;
7606 }
7607
7608 horizlookup = (int *)(lookups);
7609 horizlookup2 = (int *)((intptr_t)lookups+j);
7610 horizycent = ((ydim*4)>>1);
7611
7612 //Force drawrooms to call dosetaspect & recalculate stuff
7613 oxyaspect = oxdimen = oviewingrange = -1;
7614
7615 setvlinebpl(bytesperline);
7616 j = 0;
7617 for(i=0;i<=ydim;i++) ylookup[i] = j, j += bytesperline;
7618
7619 setview(0L,0L,xdim-1,ydim-1);
7620
7621 #if USE_POLYMOST && USE_OPENGL
7622 if (rendmode == 3) {
7623 polymost_glreset();
7624 polymost_glinit();
7625 }
7626 #endif
7627
7628 setbrightness(curbrightness,&palette[0],0);
7629 clearallviews(0L);
7630
7631 if (searchx < 0) { searchx = halfxdimen; searchy = (ydimen>>1); }
7632
7633 qsetmode = 200;
7634
7635 //memset(ratelimitlast,0,sizeof(ratelimitlast));
7636 //ratelimitn = 0;
7637
7638 return(0);
7639 }
7640
7641
7642 //
7643 // nextpage
7644 //
nextpage(void)7645 void nextpage(void)
7646 {
7647 int i;
7648 permfifotype *per;
7649
7650 //char snotbuf[32];
7651 //j = 0; k = 0;
7652 //for(i=0;i<4096;i++)
7653 // if (waloff[i] != 0)
7654 // {
7655 // sprintf(snotbuf,"%ld-%ld",i,tilesizx[i]*tilesizy[i]);
7656 // printext256((j>>5)*40+32,(j&31)*6,walock[i]>>3,-1,snotbuf,1);
7657 // k += tilesizx[i]*tilesizy[i];
7658 // j++;
7659 // }
7660 //sprintf(snotbuf,"Total: %ld",k);
7661 //printext256((j>>5)*40+32,(j&31)*6,31,-1,snotbuf,1);
7662
7663 switch(qsetmode)
7664 {
7665 case 200:
7666 begindrawing(); //{{{
7667 for(i=permtail;i!=permhead;i=((i+1)&(MAXPERMS-1)))
7668 {
7669 per = &permfifo[i];
7670 if ((per->pagesleft > 0) && (per->pagesleft <= numpages))
7671 dorotatesprite(per->sx,per->sy,per->z,per->a,per->picnum,
7672 per->dashade,per->dapalnum,per->dastat,
7673 per->cx1,per->cy1,per->cx2,per->cy2,per->uniqid);
7674 }
7675 enddrawing(); //}}}
7676
7677 OSD_Draw();
7678 #if USE_POLYMOST
7679 polymost_nextpage();
7680 #endif
7681
7682 if (captureatnextpage) {
7683 if (captureformat == 0) screencapture_tga(capturename,captureatnextpage&1);
7684 else screencapture_pcx(capturename,captureatnextpage&1);
7685 captureatnextpage = 0;
7686 }
7687
7688 showframe();
7689 #if USE_POLYMOST && USE_OPENGL
7690 polymost_aftershowframe();
7691 #endif
7692
7693 /*
7694 if (ratelimit > 0) {
7695 int delaytime;
7696 unsigned int thisticks, thist;
7697
7698 ratelimitlast[ ratelimitn++ & 31 ] = thist = getusecticks();
7699 delaytime = 0;
7700 if (ratelimitn >= 32) {
7701 for (i=1;i<32;i++) delaytime += ratelimitlast[i] - ratelimitlast[i-1];
7702 delaytime = (1000000/ratelimit) - (delaytime/31);
7703 }
7704 #ifdef _WIN32
7705 while (delaytime > 0) {
7706 Sleep(1);
7707 thisticks = getusecticks();
7708 delaytime -= (thisticks - thist);
7709 thist = thisticks;
7710 }
7711 #endif
7712 }
7713 */
7714
7715 begindrawing(); //{{{
7716 for(i=permtail;i!=permhead;i=((i+1)&(MAXPERMS-1)))
7717 {
7718 per = &permfifo[i];
7719 if (per->pagesleft >= 130)
7720 dorotatesprite(per->sx,per->sy,per->z,per->a,per->picnum,
7721 per->dashade,per->dapalnum,per->dastat,
7722 per->cx1,per->cy1,per->cx2,per->cy2,per->uniqid);
7723
7724 if ((per->pagesleft&127) && (numpages < 127)) per->pagesleft--;
7725 if (((per->pagesleft&127) == 0) && (i == permtail))
7726 permtail = ((permtail+1)&(MAXPERMS-1));
7727 }
7728 enddrawing(); //}}}
7729 break;
7730
7731 case 350:
7732 case 480:
7733 break;
7734 }
7735 faketimerhandler();
7736
7737 if ((totalclock >= lastageclock+8) || (totalclock < lastageclock))
7738 { lastageclock = totalclock; agecache(); }
7739
7740 #if USE_POLYMOST && USE_OPENGL
7741 omdtims = mdtims; mdtims = getticks();
7742 if (((unsigned int)(mdtims-omdtims)) > 10000) omdtims = mdtims;
7743 #endif
7744
7745 beforedrawrooms = 1;
7746 numframes++;
7747 }
7748
7749
7750 //
7751 // loadpics
7752 //
loadpics(char * filename,int askedsize)7753 int loadpics(char *filename, int askedsize)
7754 {
7755 int offscount, localtilestart, localtileend, dasiz;
7756 short fil, i, j, k;
7757
7758 Bstrcpy(artfilename,filename);
7759
7760 for(i=0;i<MAXTILES;i++)
7761 {
7762 tilesizx[i] = 0;
7763 tilesizy[i] = 0;
7764 picanm[i] = 0L;
7765 }
7766
7767 artsize = 0L;
7768
7769 numtilefiles = 0;
7770 do
7771 {
7772 k = numtilefiles;
7773
7774 artfilename[7] = (k%10)+48;
7775 artfilename[6] = ((k/10)%10)+48;
7776 artfilename[5] = ((k/100)%10)+48;
7777 if ((fil = kopen4load(artfilename,0)) != -1)
7778 {
7779 kread(fil,&artversion,4); artversion = B_LITTLE32(artversion);
7780 if (artversion != 1) {
7781 buildprintf("loadpics(): Invalid art file version in %s\n", artfilename);
7782 return(-1);
7783 }
7784 kread(fil,&numtiles,4); numtiles = B_LITTLE32(numtiles);
7785 kread(fil,&localtilestart,4); localtilestart = B_LITTLE32(localtilestart);
7786 kread(fil,&localtileend,4); localtileend = B_LITTLE32(localtileend);
7787 kread(fil,&tilesizx[localtilestart],(localtileend-localtilestart+1)<<1);
7788 kread(fil,&tilesizy[localtilestart],(localtileend-localtilestart+1)<<1);
7789 kread(fil,&picanm[localtilestart],(localtileend-localtilestart+1)<<2);
7790 for (i=localtilestart; i<=localtileend; i++) {
7791 tilesizx[i] = B_LITTLE16(tilesizx[i]);
7792 tilesizy[i] = B_LITTLE16(tilesizy[i]);
7793 picanm[i] = B_LITTLE32(picanm[i]);
7794 }
7795
7796 offscount = 4+4+4+4+((localtileend-localtilestart+1)<<3);
7797 for(i=localtilestart;i<=localtileend;i++)
7798 {
7799 tilefilenum[i] = k;
7800 tilefileoffs[i] = offscount;
7801 dasiz = (int)(tilesizx[i]*tilesizy[i]);
7802 offscount += dasiz;
7803 artsize += ((dasiz+15)&0xfffffff0);
7804 }
7805 kclose(fil);
7806
7807 numtilefiles++;
7808 }
7809 }
7810 while (k != numtilefiles);
7811
7812 clearbuf(&gotpic[0],(int)((MAXTILES+31)>>5),0L);
7813
7814 //try dpmi_DETERMINEMAXREALALLOC!
7815
7816 //cachesize = min((int)((Bgetsysmemsize()/100)*60),max(artsize,askedsize));
7817 if (Bgetsysmemsize() <= (unsigned int)askedsize)
7818 cachesize = (Bgetsysmemsize()/100)*60;
7819 else
7820 cachesize = askedsize;
7821 while ((pic = kmalloc(cachesize)) == NULL)
7822 {
7823 cachesize -= 65536L;
7824 if (cachesize < 65536) return(-1);
7825 }
7826 initcache(pic, cachesize);
7827
7828 for(i=0;i<MAXTILES;i++)
7829 {
7830 j = 15;
7831 while ((j > 1) && (pow2long[j] > tilesizx[i])) j--;
7832 picsiz[i] = ((unsigned char)j);
7833 j = 15;
7834 while ((j > 1) && (pow2long[j] > tilesizy[i])) j--;
7835 picsiz[i] += ((unsigned char)(j<<4));
7836 }
7837
7838 artfil = -1;
7839 artfilnum = -1;
7840 artfilplc = 0L;
7841
7842 return(0);
7843 }
7844
7845
7846 //
7847 // loadtile
7848 //
7849 char cachedebug = 0;
loadtile(short tilenume)7850 void loadtile(short tilenume)
7851 {
7852 char *ptr;
7853 int i, dasiz;
7854
7855 if ((unsigned)tilenume >= (unsigned)MAXTILES) return;
7856 dasiz = tilesizx[tilenume]*tilesizy[tilenume];
7857 if (dasiz <= 0) return;
7858
7859 i = tilefilenum[tilenume];
7860 if (i != artfilnum)
7861 {
7862 if (artfil != -1) kclose(artfil);
7863 artfilnum = i;
7864 artfilplc = 0L;
7865
7866 artfilename[7] = (i%10)+48;
7867 artfilename[6] = ((i/10)%10)+48;
7868 artfilename[5] = ((i/100)%10)+48;
7869 artfil = kopen4load(artfilename,0);
7870 faketimerhandler();
7871 }
7872
7873 if (cachedebug) buildprintf("Tile:%d\n",tilenume);
7874
7875 if (waloff[tilenume] == 0)
7876 {
7877 walock[tilenume] = 199;
7878 allocache((void **)&waloff[tilenume],dasiz,&walock[tilenume]);
7879 }
7880
7881 if (artfilplc != tilefileoffs[tilenume])
7882 {
7883 klseek(artfil,tilefileoffs[tilenume]-artfilplc,BSEEK_CUR);
7884 faketimerhandler();
7885 }
7886 ptr = (char *)waloff[tilenume];
7887 kread(artfil,ptr,dasiz);
7888 faketimerhandler();
7889 artfilplc = tilefileoffs[tilenume]+dasiz;
7890 }
7891
7892
7893 //
7894 // allocatepermanenttile
7895 //
allocatepermanenttile(short tilenume,int xsiz,int ysiz)7896 int allocatepermanenttile(short tilenume, int xsiz, int ysiz)
7897 {
7898 int j, dasiz;
7899
7900 if ((xsiz <= 0) || (ysiz <= 0) || ((unsigned)tilenume >= (unsigned)MAXTILES))
7901 return(0);
7902
7903 dasiz = xsiz*ysiz;
7904
7905 walock[tilenume] = 255;
7906 allocache((void **)&waloff[tilenume],dasiz,&walock[tilenume]);
7907
7908 tilesizx[tilenume] = xsiz;
7909 tilesizy[tilenume] = ysiz;
7910 picanm[tilenume] = 0;
7911
7912 j = 15; while ((j > 1) && (pow2long[j] > xsiz)) j--;
7913 picsiz[tilenume] = ((unsigned char)j);
7914 j = 15; while ((j > 1) && (pow2long[j] > ysiz)) j--;
7915 picsiz[tilenume] += ((unsigned char)(j<<4));
7916
7917 return(waloff[tilenume]);
7918 }
7919
7920
7921 //
7922 // copytilepiece
7923 //
copytilepiece(int tilenume1,int sx1,int sy1,int xsiz,int ysiz,int tilenume2,int sx2,int sy2)7924 void copytilepiece(int tilenume1, int sx1, int sy1, int xsiz, int ysiz,
7925 int tilenume2, int sx2, int sy2)
7926 {
7927 unsigned char *ptr1, *ptr2, dat;
7928 int xsiz1, ysiz1, xsiz2, ysiz2, i, j, x1, y1, x2, y2;
7929
7930 xsiz1 = tilesizx[tilenume1]; ysiz1 = tilesizy[tilenume1];
7931 xsiz2 = tilesizx[tilenume2]; ysiz2 = tilesizy[tilenume2];
7932 if ((xsiz1 > 0) && (ysiz1 > 0) && (xsiz2 > 0) && (ysiz2 > 0))
7933 {
7934 if (waloff[tilenume1] == 0) loadtile(tilenume1);
7935 if (waloff[tilenume2] == 0) loadtile(tilenume2);
7936
7937 x1 = sx1;
7938 for(i=0;i<xsiz;i++)
7939 {
7940 y1 = sy1;
7941 for(j=0;j<ysiz;j++)
7942 {
7943 x2 = sx2+i;
7944 y2 = sy2+j;
7945 if ((x2 >= 0) && (y2 >= 0) && (x2 < xsiz2) && (y2 < ysiz2))
7946 {
7947 ptr1 = (unsigned char *)(waloff[tilenume1] + x1*ysiz1 + y1);
7948 ptr2 = (unsigned char *)(waloff[tilenume2] + x2*ysiz2 + y2);
7949 dat = *ptr1;
7950 if (dat != 255)
7951 *ptr2 = *ptr1;
7952 }
7953
7954 y1++; if (y1 >= ysiz1) y1 = 0;
7955 }
7956 x1++; if (x1 >= xsiz1) x1 = 0;
7957 }
7958 }
7959 }
7960
7961
7962 //
7963 // qloadkvx
7964 //
qloadkvx(int voxindex,char * filename)7965 int qloadkvx(int voxindex, char *filename)
7966 {
7967 int i, fil, dasiz, lengcnt, lengtot;
7968 unsigned char *ptr;
7969
7970 if ((fil = kopen4load(filename,0)) == -1) return -1;
7971
7972 lengcnt = 0;
7973 lengtot = kfilelength(fil);
7974
7975 for(i=0;i<MAXVOXMIPS;i++)
7976 {
7977 kread(fil,&dasiz,4); dasiz = B_LITTLE32(dasiz);
7978 //Must store filenames to use cacheing system :(
7979 voxlock[voxindex][i] = 200;
7980 allocache((void **)&voxoff[voxindex][i],dasiz,&voxlock[voxindex][i]);
7981 ptr = (unsigned char *)voxoff[voxindex][i];
7982 kread(fil,ptr,dasiz);
7983
7984 lengcnt += dasiz+4;
7985 if (lengcnt >= lengtot-768) break;
7986 }
7987 kclose(fil);
7988
7989 #if USE_POLYMOST && USE_OPENGL
7990 if (voxmodels[voxindex]) {
7991 voxfree(voxmodels[voxindex]);
7992 voxmodels[voxindex] = NULL;
7993 }
7994 voxmodels[voxindex] = voxload(filename);
7995 #endif
7996 return 0;
7997 }
7998
7999
8000 //
8001 // clipinsidebox
8002 //
clipinsidebox(int x,int y,short wallnum,int walldist)8003 int clipinsidebox(int x, int y, short wallnum, int walldist)
8004 {
8005 walltype *wal;
8006 int x1, y1, x2, y2, r;
8007
8008 r = (walldist<<1);
8009 wal = &wall[wallnum]; x1 = wal->x+walldist-x; y1 = wal->y+walldist-y;
8010 wal = &wall[wal->point2]; x2 = wal->x+walldist-x; y2 = wal->y+walldist-y;
8011
8012 if ((x1 < 0) && (x2 < 0)) return(0);
8013 if ((y1 < 0) && (y2 < 0)) return(0);
8014 if ((x1 >= r) && (x2 >= r)) return(0);
8015 if ((y1 >= r) && (y2 >= r)) return(0);
8016
8017 x2 -= x1; y2 -= y1;
8018 if (x2*(walldist-y1) >= y2*(walldist-x1)) //Front
8019 {
8020 if (x2 > 0) x2 *= (0-y1); else x2 *= (r-y1);
8021 if (y2 > 0) y2 *= (r-x1); else y2 *= (0-x1);
8022 return(x2 < y2);
8023 }
8024 if (x2 > 0) x2 *= (r-y1); else x2 *= (0-y1);
8025 if (y2 > 0) y2 *= (0-x1); else y2 *= (r-x1);
8026 return((x2 >= y2)<<1);
8027 }
8028
8029
8030 //
8031 // clipinsideboxline
8032 //
clipinsideboxline(int x,int y,int x1,int y1,int x2,int y2,int walldist)8033 int clipinsideboxline(int x, int y, int x1, int y1, int x2, int y2, int walldist)
8034 {
8035 int r;
8036
8037 r = (walldist<<1);
8038
8039 x1 += walldist-x; x2 += walldist-x;
8040 if ((x1 < 0) && (x2 < 0)) return(0);
8041 if ((x1 >= r) && (x2 >= r)) return(0);
8042
8043 y1 += walldist-y; y2 += walldist-y;
8044 if ((y1 < 0) && (y2 < 0)) return(0);
8045 if ((y1 >= r) && (y2 >= r)) return(0);
8046
8047 x2 -= x1; y2 -= y1;
8048 if (x2*(walldist-y1) >= y2*(walldist-x1)) //Front
8049 {
8050 if (x2 > 0) x2 *= (0-y1); else x2 *= (r-y1);
8051 if (y2 > 0) y2 *= (r-x1); else y2 *= (0-x1);
8052 return(x2 < y2);
8053 }
8054 if (x2 > 0) x2 *= (r-y1); else x2 *= (0-y1);
8055 if (y2 > 0) y2 *= (0-x1); else y2 *= (r-x1);
8056 return((x2 >= y2)<<1);
8057 }
8058
8059
8060 //
8061 // inside
8062 //
inside(int x,int y,short sectnum)8063 int inside(int x, int y, short sectnum)
8064 {
8065 walltype *wal;
8066 int i, x1, y1, x2, y2;
8067 unsigned int cnt;
8068
8069 if ((sectnum < 0) || (sectnum >= numsectors)) return(-1);
8070
8071 cnt = 0;
8072 wal = &wall[sector[sectnum].wallptr];
8073 i = sector[sectnum].wallnum;
8074 do
8075 {
8076 y1 = wal->y-y; y2 = wall[wal->point2].y-y;
8077 if ((y1^y2) < 0)
8078 {
8079 x1 = wal->x-x; x2 = wall[wal->point2].x-x;
8080 if ((x1^x2) >= 0) cnt ^= x1; else cnt ^= (x1*y2-x2*y1)^y2;
8081 }
8082 wal++; i--;
8083 } while (i);
8084 return(cnt>>31);
8085 }
8086
8087
8088 //
8089 // getangle
8090 //
getangle(int xvect,int yvect)8091 int getangle(int xvect, int yvect)
8092 {
8093 if ((xvect|yvect) == 0) return(0);
8094 if (xvect == 0) return(512+((yvect<0)<<10));
8095 if (yvect == 0) return(((xvect<0)<<10));
8096 if (xvect == yvect) return(256+((xvect<0)<<10));
8097 if (xvect == -yvect) return(768+((xvect>0)<<10));
8098 if (klabs(xvect) > klabs(yvect))
8099 return(((radarang[640+scale(160,yvect,xvect)]>>6)+((xvect<0)<<10))&2047);
8100 return(((radarang[640-scale(160,xvect,yvect)]>>6)+512+((yvect<0)<<10))&2047);
8101 }
8102
8103
8104 //
8105 // ksqrt
8106 //
ksqrt(int num)8107 int ksqrt(int num)
8108 {
8109 return(nsqrtasm(num));
8110 }
8111
8112
8113 //
8114 // krecip
8115 //
krecip(int num)8116 int krecip(int num)
8117 {
8118 return(krecipasm(num));
8119 }
8120
8121
8122 //
8123 // setsprite
8124 //
setsprite(short spritenum,int newx,int newy,int newz)8125 int setsprite(short spritenum, int newx, int newy, int newz)
8126 {
8127 short tempsectnum;
8128
8129 sprite[spritenum].x = newx;
8130 sprite[spritenum].y = newy;
8131 sprite[spritenum].z = newz;
8132
8133 tempsectnum = sprite[spritenum].sectnum;
8134 updatesector(newx,newy,&tempsectnum);
8135 if (tempsectnum < 0)
8136 return(-1);
8137 if (tempsectnum != sprite[spritenum].sectnum)
8138 changespritesect(spritenum,tempsectnum);
8139
8140 return(0);
8141 }
8142
8143 //
8144 // setspritez
8145 //
setspritez(short spritenum,int newx,int newy,int newz)8146 int setspritez(short spritenum, int newx, int newy, int newz)
8147 {
8148 short tempsectnum;
8149
8150 sprite[spritenum].x = newx;
8151 sprite[spritenum].y = newy;
8152 sprite[spritenum].z = newz;
8153
8154 tempsectnum = sprite[spritenum].sectnum;
8155 updatesectorz(newx,newy,newz,&tempsectnum);
8156 if (tempsectnum < 0)
8157 return(-1);
8158 if (tempsectnum != sprite[spritenum].sectnum)
8159 changespritesect(spritenum,tempsectnum);
8160
8161 return(0);
8162 }
8163
8164
8165 //
8166 // insertsprite
8167 //
insertsprite(short sectnum,short statnum)8168 int insertsprite(short sectnum, short statnum)
8169 {
8170 insertspritestat(statnum);
8171 return(insertspritesect(sectnum));
8172 }
8173
8174
8175 //
8176 // deletesprite
8177 //
deletesprite(short spritenum)8178 int deletesprite(short spritenum)
8179 {
8180 deletespritestat(spritenum);
8181 return(deletespritesect(spritenum));
8182 }
8183
8184
8185 //
8186 // changespritesect
8187 //
changespritesect(short spritenum,short newsectnum)8188 int changespritesect(short spritenum, short newsectnum)
8189 {
8190 if ((newsectnum < 0) || (newsectnum > MAXSECTORS)) return(-1);
8191 if (sprite[spritenum].sectnum == newsectnum) return(0);
8192 if (sprite[spritenum].sectnum == MAXSECTORS) return(-1);
8193 if (deletespritesect(spritenum) < 0) return(-1);
8194 insertspritesect(newsectnum);
8195 return(0);
8196 }
8197
8198
8199 //
8200 // changespritestat
8201 //
changespritestat(short spritenum,short newstatnum)8202 int changespritestat(short spritenum, short newstatnum)
8203 {
8204 if ((newstatnum < 0) || (newstatnum > MAXSTATUS)) return(-1);
8205 if (sprite[spritenum].statnum == newstatnum) return(0);
8206 if (sprite[spritenum].statnum == MAXSTATUS) return(-1);
8207 if (deletespritestat(spritenum) < 0) return(-1);
8208 insertspritestat(newstatnum);
8209 return(0);
8210 }
8211
8212
8213 //
8214 // nextsectorneighborz
8215 //
nextsectorneighborz(short sectnum,int thez,short topbottom,short direction)8216 int nextsectorneighborz(short sectnum, int thez, short topbottom, short direction)
8217 {
8218 walltype *wal;
8219 int i, testz, nextz;
8220 short sectortouse;
8221
8222 if (direction == 1) nextz = 0x7fffffff; else nextz = 0x80000000;
8223
8224 sectortouse = -1;
8225
8226 wal = &wall[sector[sectnum].wallptr];
8227 i = sector[sectnum].wallnum;
8228 do
8229 {
8230 if (wal->nextsector >= 0)
8231 {
8232 if (topbottom == 1)
8233 {
8234 testz = sector[wal->nextsector].floorz;
8235 if (direction == 1)
8236 {
8237 if ((testz > thez) && (testz < nextz))
8238 {
8239 nextz = testz;
8240 sectortouse = wal->nextsector;
8241 }
8242 }
8243 else
8244 {
8245 if ((testz < thez) && (testz > nextz))
8246 {
8247 nextz = testz;
8248 sectortouse = wal->nextsector;
8249 }
8250 }
8251 }
8252 else
8253 {
8254 testz = sector[wal->nextsector].ceilingz;
8255 if (direction == 1)
8256 {
8257 if ((testz > thez) && (testz < nextz))
8258 {
8259 nextz = testz;
8260 sectortouse = wal->nextsector;
8261 }
8262 }
8263 else
8264 {
8265 if ((testz < thez) && (testz > nextz))
8266 {
8267 nextz = testz;
8268 sectortouse = wal->nextsector;
8269 }
8270 }
8271 }
8272 }
8273 wal++;
8274 i--;
8275 } while (i != 0);
8276
8277 return(sectortouse);
8278 }
8279
8280
8281 //
8282 // cansee
8283 //
cansee(int x1,int y1,int z1,short sect1,int x2,int y2,int z2,short sect2)8284 int cansee(int x1, int y1, int z1, short sect1, int x2, int y2, int z2, short sect2)
8285 {
8286 sectortype *sec;
8287 walltype *wal, *wal2;
8288 int i, cnt, nexts, x, y, z, cz, fz, dasectnum, dacnt, danum;
8289 int x21, y21, z21, x31, y31, x34, y34, bot, t;
8290
8291 if ((x1 == x2) && (y1 == y2)) return(sect1 == sect2);
8292
8293 x21 = x2-x1; y21 = y2-y1; z21 = z2-z1;
8294
8295 clipsectorlist[0] = sect1; danum = 1;
8296 for(dacnt=0;dacnt<danum;dacnt++)
8297 {
8298 dasectnum = clipsectorlist[dacnt]; sec = §or[dasectnum];
8299 for(cnt=sec->wallnum,wal=&wall[sec->wallptr];cnt>0;cnt--,wal++)
8300 {
8301 wal2 = &wall[wal->point2];
8302 x31 = wal->x-x1; x34 = wal->x-wal2->x;
8303 y31 = wal->y-y1; y34 = wal->y-wal2->y;
8304
8305 bot = y21*x34-x21*y34; if (bot <= 0) continue;
8306 t = y21*x31-x21*y31; if ((unsigned)t >= (unsigned)bot) continue;
8307 t = y31*x34-x31*y34; if ((unsigned)t >= (unsigned)bot) continue;
8308
8309 nexts = wal->nextsector;
8310 if ((nexts < 0) || (wal->cstat&32)) return(0);
8311
8312 t = divscale24(t,bot);
8313 x = x1 + mulscale24(x21,t);
8314 y = y1 + mulscale24(y21,t);
8315 z = z1 + mulscale24(z21,t);
8316
8317 getzsofslope((short)dasectnum,x,y,&cz,&fz);
8318 if ((z <= cz) || (z >= fz)) return(0);
8319 getzsofslope((short)nexts,x,y,&cz,&fz);
8320 if ((z <= cz) || (z >= fz)) return(0);
8321
8322 for(i=danum-1;i>=0;i--) if (clipsectorlist[i] == nexts) break;
8323 if (i < 0) clipsectorlist[danum++] = nexts;
8324 }
8325 }
8326 for(i=danum-1;i>=0;i--) if (clipsectorlist[i] == sect2) return(1);
8327 return(0);
8328 }
8329
8330
8331 //
8332 // hitscan
8333 //
hitscan(int xs,int ys,int zs,short sectnum,int vx,int vy,int vz,short * hitsect,short * hitwall,short * hitsprite,int * hitx,int * hity,int * hitz,unsigned int cliptype)8334 int hitscan(int xs, int ys, int zs, short sectnum, int vx, int vy, int vz,
8335 short *hitsect, short *hitwall, short *hitsprite,
8336 int *hitx, int *hity, int *hitz, unsigned int cliptype)
8337 {
8338 sectortype *sec;
8339 walltype *wal, *wal2;
8340 spritetype *spr;
8341 int z, zz, x1, y1=0, z1=0, x2, y2, x3, y3, x4, y4, intx, inty, intz;
8342 int topt, topu, bot, dist, offx, offy, cstat;
8343 int i, j, k, l, tilenum, xoff, yoff, dax, day, daz, daz2;
8344 int ang, cosang, sinang, xspan, yspan, xrepeat, yrepeat;
8345 int dawalclipmask, dasprclipmask;
8346 short tempshortcnt, tempshortnum, dasector, startwall, endwall;
8347 short nextsector;
8348 unsigned char clipyou;
8349
8350 *hitsect = -1; *hitwall = -1; *hitsprite = -1;
8351 if (sectnum < 0) return(-1);
8352
8353 *hitx = hitscangoalx; *hity = hitscangoaly;
8354
8355 dawalclipmask = (cliptype&65535);
8356 dasprclipmask = (cliptype>>16);
8357
8358 clipsectorlist[0] = sectnum;
8359 tempshortcnt = 0; tempshortnum = 1;
8360 do
8361 {
8362 dasector = clipsectorlist[tempshortcnt]; sec = §or[dasector];
8363
8364 x1 = 0x7fffffff;
8365 if (sec->ceilingstat&2)
8366 {
8367 wal = &wall[sec->wallptr]; wal2 = &wall[wal->point2];
8368 dax = wal2->x-wal->x; day = wal2->y-wal->y;
8369 i = nsqrtasm(dax*dax+day*day); if (i == 0) continue;
8370 i = divscale15(sec->ceilingheinum,i);
8371 dax *= i; day *= i;
8372
8373 j = (vz<<8)-dmulscale15(dax,vy,-day,vx);
8374 if (j != 0)
8375 {
8376 i = ((sec->ceilingz-zs)<<8)+dmulscale15(dax,ys-wal->y,-day,xs-wal->x);
8377 if (((i^j) >= 0) && ((klabs(i)>>1) < klabs(j)))
8378 {
8379 i = divscale30(i,j);
8380 x1 = xs + mulscale30(vx,i);
8381 y1 = ys + mulscale30(vy,i);
8382 z1 = zs + mulscale30(vz,i);
8383 }
8384 }
8385 }
8386 else if ((vz < 0) && (zs >= sec->ceilingz))
8387 {
8388 z1 = sec->ceilingz; i = z1-zs;
8389 if ((klabs(i)>>1) < -vz)
8390 {
8391 i = divscale30(i,vz);
8392 x1 = xs + mulscale30(vx,i);
8393 y1 = ys + mulscale30(vy,i);
8394 }
8395 }
8396 if ((x1 != 0x7fffffff) && (klabs(x1-xs)+klabs(y1-ys) < klabs((*hitx)-xs)+klabs((*hity)-ys)))
8397 if (inside(x1,y1,dasector) != 0)
8398 {
8399 *hitsect = dasector; *hitwall = -1; *hitsprite = -1;
8400 *hitx = x1; *hity = y1; *hitz = z1;
8401 }
8402
8403 x1 = 0x7fffffff;
8404 if (sec->floorstat&2)
8405 {
8406 wal = &wall[sec->wallptr]; wal2 = &wall[wal->point2];
8407 dax = wal2->x-wal->x; day = wal2->y-wal->y;
8408 i = nsqrtasm(dax*dax+day*day); if (i == 0) continue;
8409 i = divscale15(sec->floorheinum,i);
8410 dax *= i; day *= i;
8411
8412 j = (vz<<8)-dmulscale15(dax,vy,-day,vx);
8413 if (j != 0)
8414 {
8415 i = ((sec->floorz-zs)<<8)+dmulscale15(dax,ys-wal->y,-day,xs-wal->x);
8416 if (((i^j) >= 0) && ((klabs(i)>>1) < klabs(j)))
8417 {
8418 i = divscale30(i,j);
8419 x1 = xs + mulscale30(vx,i);
8420 y1 = ys + mulscale30(vy,i);
8421 z1 = zs + mulscale30(vz,i);
8422 }
8423 }
8424 }
8425 else if ((vz > 0) && (zs <= sec->floorz))
8426 {
8427 z1 = sec->floorz; i = z1-zs;
8428 if ((klabs(i)>>1) < vz)
8429 {
8430 i = divscale30(i,vz);
8431 x1 = xs + mulscale30(vx,i);
8432 y1 = ys + mulscale30(vy,i);
8433 }
8434 }
8435 if ((x1 != 0x7fffffff) && (klabs(x1-xs)+klabs(y1-ys) < klabs((*hitx)-xs)+klabs((*hity)-ys)))
8436 if (inside(x1,y1,dasector) != 0)
8437 {
8438 *hitsect = dasector; *hitwall = -1; *hitsprite = -1;
8439 *hitx = x1; *hity = y1; *hitz = z1;
8440 }
8441
8442 startwall = sec->wallptr; endwall = startwall + sec->wallnum;
8443 for(z=startwall,wal=&wall[startwall];z<endwall;z++,wal++)
8444 {
8445 wal2 = &wall[wal->point2];
8446 x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y;
8447
8448 if ((x1-xs)*(y2-ys) < (x2-xs)*(y1-ys)) continue;
8449 if (rintersect(xs,ys,zs,vx,vy,vz,x1,y1,x2,y2,&intx,&inty,&intz) == 0) continue;
8450
8451 if (klabs(intx-xs)+klabs(inty-ys) >= klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
8452
8453 nextsector = wal->nextsector;
8454 if ((nextsector < 0) || (wal->cstat&dawalclipmask))
8455 {
8456 *hitsect = dasector; *hitwall = z; *hitsprite = -1;
8457 *hitx = intx; *hity = inty; *hitz = intz;
8458 continue;
8459 }
8460 getzsofslope(nextsector,intx,inty,&daz,&daz2);
8461 if ((intz <= daz) || (intz >= daz2))
8462 {
8463 *hitsect = dasector; *hitwall = z; *hitsprite = -1;
8464 *hitx = intx; *hity = inty; *hitz = intz;
8465 continue;
8466 }
8467
8468 for(zz=tempshortnum-1;zz>=0;zz--)
8469 if (clipsectorlist[zz] == nextsector) break;
8470 if (zz < 0) clipsectorlist[tempshortnum++] = nextsector;
8471 }
8472
8473 for(z=headspritesect[dasector];z>=0;z=nextspritesect[z])
8474 {
8475 spr = &sprite[z];
8476 cstat = spr->cstat;
8477 #if USE_POLYMOST
8478 if (!hitallsprites)
8479 #endif
8480 if ((cstat&dasprclipmask) == 0) continue;
8481
8482 x1 = spr->x; y1 = spr->y; z1 = spr->z;
8483 switch(cstat&48)
8484 {
8485 case 0:
8486 topt = vx*(x1-xs) + vy*(y1-ys); if (topt <= 0) continue;
8487 bot = vx*vx + vy*vy; if (bot == 0) continue;
8488
8489 intz = zs+scale(vz,topt,bot);
8490
8491 i = (tilesizy[spr->picnum]*spr->yrepeat<<2);
8492 if (cstat&128) z1 += (i>>1);
8493 if (picanm[spr->picnum]&0x00ff0000) z1 -= ((int)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
8494 if ((intz > z1) || (intz < z1-i)) continue;
8495 topu = vx*(y1-ys) - vy*(x1-xs);
8496
8497 offx = scale(vx,topu,bot);
8498 offy = scale(vy,topu,bot);
8499 dist = offx*offx + offy*offy;
8500 i = tilesizx[spr->picnum]*spr->xrepeat; i *= i;
8501 if (dist > (i>>7)) continue;
8502 intx = xs + scale(vx,topt,bot);
8503 inty = ys + scale(vy,topt,bot);
8504
8505 if (klabs(intx-xs)+klabs(inty-ys) > klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
8506
8507 *hitsect = dasector; *hitwall = -1; *hitsprite = z;
8508 *hitx = intx; *hity = inty; *hitz = intz;
8509 break;
8510 case 16:
8511 //These lines get the 2 points of the rotated sprite
8512 //Given: (x1, y1) starts out as the center point
8513 tilenum = spr->picnum;
8514 xoff = (int)((signed char)((picanm[tilenum]>>8)&255))+((int)spr->xoffset);
8515 if ((cstat&4) > 0) xoff = -xoff;
8516 k = spr->ang; l = spr->xrepeat;
8517 dax = sintable[k&2047]*l; day = sintable[(k+1536)&2047]*l;
8518 l = tilesizx[tilenum]; k = (l>>1)+xoff;
8519 x1 -= mulscale16(dax,k); x2 = x1+mulscale16(dax,l);
8520 y1 -= mulscale16(day,k); y2 = y1+mulscale16(day,l);
8521
8522 if ((cstat&64) != 0) //back side of 1-way sprite
8523 if ((x1-xs)*(y2-ys) < (x2-xs)*(y1-ys)) continue;
8524
8525 if (rintersect(xs,ys,zs,vx,vy,vz,x1,y1,x2,y2,&intx,&inty,&intz) == 0) continue;
8526
8527 if (klabs(intx-xs)+klabs(inty-ys) > klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
8528
8529 k = ((tilesizy[spr->picnum]*spr->yrepeat)<<2);
8530 if (cstat&128) daz = spr->z+(k>>1); else daz = spr->z;
8531 if (picanm[spr->picnum]&0x00ff0000) daz -= ((int)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
8532 if ((intz < daz) && (intz > daz-k))
8533 {
8534 *hitsect = dasector; *hitwall = -1; *hitsprite = z;
8535 *hitx = intx; *hity = inty; *hitz = intz;
8536 }
8537 break;
8538 case 32:
8539 if (vz == 0) continue;
8540 intz = z1;
8541 if (((intz-zs)^vz) < 0) continue;
8542 if ((cstat&64) != 0)
8543 if ((zs > intz) == ((cstat&8)==0)) continue;
8544
8545 intx = xs+scale(intz-zs,vx,vz);
8546 inty = ys+scale(intz-zs,vy,vz);
8547
8548 if (klabs(intx-xs)+klabs(inty-ys) > klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
8549
8550 tilenum = spr->picnum;
8551 xoff = (int)((signed char)((picanm[tilenum]>>8)&255))+((int)spr->xoffset);
8552 yoff = (int)((signed char)((picanm[tilenum]>>16)&255))+((int)spr->yoffset);
8553 if ((cstat&4) > 0) xoff = -xoff;
8554 if ((cstat&8) > 0) yoff = -yoff;
8555
8556 ang = spr->ang;
8557 cosang = sintable[(ang+512)&2047]; sinang = sintable[ang];
8558 xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat;
8559 yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat;
8560
8561 dax = ((xspan>>1)+xoff)*xrepeat; day = ((yspan>>1)+yoff)*yrepeat;
8562 x1 += dmulscale16(sinang,dax,cosang,day)-intx;
8563 y1 += dmulscale16(sinang,day,-cosang,dax)-inty;
8564 l = xspan*xrepeat;
8565 x2 = x1 - mulscale16(sinang,l);
8566 y2 = y1 + mulscale16(cosang,l);
8567 l = yspan*yrepeat;
8568 k = -mulscale16(cosang,l); x3 = x2+k; x4 = x1+k;
8569 k = -mulscale16(sinang,l); y3 = y2+k; y4 = y1+k;
8570
8571 clipyou = 0;
8572 if ((y1^y2) < 0)
8573 {
8574 if ((x1^x2) < 0) clipyou ^= (x1*y2<x2*y1)^(y1<y2);
8575 else if (x1 >= 0) clipyou ^= 1;
8576 }
8577 if ((y2^y3) < 0)
8578 {
8579 if ((x2^x3) < 0) clipyou ^= (x2*y3<x3*y2)^(y2<y3);
8580 else if (x2 >= 0) clipyou ^= 1;
8581 }
8582 if ((y3^y4) < 0)
8583 {
8584 if ((x3^x4) < 0) clipyou ^= (x3*y4<x4*y3)^(y3<y4);
8585 else if (x3 >= 0) clipyou ^= 1;
8586 }
8587 if ((y4^y1) < 0)
8588 {
8589 if ((x4^x1) < 0) clipyou ^= (x4*y1<x1*y4)^(y4<y1);
8590 else if (x4 >= 0) clipyou ^= 1;
8591 }
8592
8593 if (clipyou != 0)
8594 {
8595 *hitsect = dasector; *hitwall = -1; *hitsprite = z;
8596 *hitx = intx; *hity = inty; *hitz = intz;
8597 }
8598 break;
8599 }
8600 }
8601 tempshortcnt++;
8602 } while (tempshortcnt < tempshortnum);
8603 return(0);
8604 }
8605
8606
8607 //
8608 // neartag
8609 //
neartag(int xs,int ys,int zs,short sectnum,short ange,short * neartagsector,short * neartagwall,short * neartagsprite,int * neartaghitdist,int neartagrange,unsigned char tagsearch)8610 int neartag(int xs, int ys, int zs, short sectnum, short ange, short *neartagsector, short *neartagwall,
8611 short *neartagsprite, int *neartaghitdist, int neartagrange, unsigned char tagsearch)
8612 {
8613 walltype *wal, *wal2;
8614 spritetype *spr;
8615 int i, z, zz, xe, ye, ze, x1, y1, z1, x2, y2, intx, inty, intz;
8616 int topt, topu, bot, dist, offx, offy, vx, vy, vz;
8617 short tempshortcnt, tempshortnum, dasector, startwall, endwall;
8618 short nextsector, good;
8619
8620 *neartagsector = -1; *neartagwall = -1; *neartagsprite = -1;
8621 *neartaghitdist = 0;
8622
8623 if (sectnum < 0) return(0);
8624 if ((tagsearch < 1) || (tagsearch > 3)) return(0);
8625
8626 vx = mulscale14(sintable[(ange+2560)&2047],neartagrange); xe = xs+vx;
8627 vy = mulscale14(sintable[(ange+2048)&2047],neartagrange); ye = ys+vy;
8628 vz = 0; ze = 0;
8629
8630 clipsectorlist[0] = sectnum;
8631 tempshortcnt = 0; tempshortnum = 1;
8632
8633 do
8634 {
8635 dasector = clipsectorlist[tempshortcnt];
8636
8637 startwall = sector[dasector].wallptr;
8638 endwall = startwall + sector[dasector].wallnum - 1;
8639 for(z=startwall,wal=&wall[startwall];z<=endwall;z++,wal++)
8640 {
8641 wal2 = &wall[wal->point2];
8642 x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y;
8643
8644 nextsector = wal->nextsector;
8645
8646 good = 0;
8647 if (nextsector >= 0)
8648 {
8649 if ((tagsearch&1) && sector[nextsector].lotag) good |= 1;
8650 if ((tagsearch&2) && sector[nextsector].hitag) good |= 1;
8651 }
8652 if ((tagsearch&1) && wal->lotag) good |= 2;
8653 if ((tagsearch&2) && wal->hitag) good |= 2;
8654
8655 if ((good == 0) && (nextsector < 0)) continue;
8656 if ((x1-xs)*(y2-ys) < (x2-xs)*(y1-ys)) continue;
8657
8658 if (lintersect(xs,ys,zs,xe,ye,ze,x1,y1,x2,y2,&intx,&inty,&intz) == 1)
8659 {
8660 if (good != 0)
8661 {
8662 if (good&1) *neartagsector = nextsector;
8663 if (good&2) *neartagwall = z;
8664 *neartaghitdist = dmulscale14(intx-xs,sintable[(ange+2560)&2047],inty-ys,sintable[(ange+2048)&2047]);
8665 xe = intx; ye = inty; ze = intz;
8666 }
8667 if (nextsector >= 0)
8668 {
8669 for(zz=tempshortnum-1;zz>=0;zz--)
8670 if (clipsectorlist[zz] == nextsector) break;
8671 if (zz < 0) clipsectorlist[tempshortnum++] = nextsector;
8672 }
8673 }
8674 }
8675
8676 for(z=headspritesect[dasector];z>=0;z=nextspritesect[z])
8677 {
8678 spr = &sprite[z];
8679
8680 good = 0;
8681 if ((tagsearch&1) && spr->lotag) good |= 1;
8682 if ((tagsearch&2) && spr->hitag) good |= 1;
8683 if (good != 0)
8684 {
8685 x1 = spr->x; y1 = spr->y; z1 = spr->z;
8686
8687 topt = vx*(x1-xs) + vy*(y1-ys);
8688 if (topt > 0)
8689 {
8690 bot = vx*vx + vy*vy;
8691 if (bot != 0)
8692 {
8693 intz = zs+scale(vz,topt,bot);
8694 i = tilesizy[spr->picnum]*spr->yrepeat;
8695 if (spr->cstat&128) z1 += (i<<1);
8696 if (picanm[spr->picnum]&0x00ff0000) z1 -= ((int)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
8697 if ((intz <= z1) && (intz >= z1-(i<<2)))
8698 {
8699 topu = vx*(y1-ys) - vy*(x1-xs);
8700
8701 offx = scale(vx,topu,bot);
8702 offy = scale(vy,topu,bot);
8703 dist = offx*offx + offy*offy;
8704 i = (tilesizx[spr->picnum]*spr->xrepeat); i *= i;
8705 if (dist <= (i>>7))
8706 {
8707 intx = xs + scale(vx,topt,bot);
8708 inty = ys + scale(vy,topt,bot);
8709 if (klabs(intx-xs)+klabs(inty-ys) < klabs(xe-xs)+klabs(ye-ys))
8710 {
8711 *neartagsprite = z;
8712 *neartaghitdist = dmulscale14(intx-xs,sintable[(ange+2560)&2047],inty-ys,sintable[(ange+2048)&2047]);
8713 xe = intx;
8714 ye = inty;
8715 ze = intz;
8716 }
8717 }
8718 }
8719 }
8720 }
8721 }
8722 }
8723
8724 tempshortcnt++;
8725 } while (tempshortcnt < tempshortnum);
8726 return(0);
8727 }
8728
8729
8730 //
8731 // dragpoint
8732 //
dragpoint(short pointhighlight,int dax,int day)8733 void dragpoint(short pointhighlight, int dax, int day)
8734 {
8735 short cnt, tempshort;
8736
8737 wall[pointhighlight].x = dax;
8738 wall[pointhighlight].y = day;
8739
8740 cnt = MAXWALLS;
8741 tempshort = pointhighlight; //search points CCW
8742 do
8743 {
8744 if (wall[tempshort].nextwall >= 0)
8745 {
8746 tempshort = wall[wall[tempshort].nextwall].point2;
8747 wall[tempshort].x = dax;
8748 wall[tempshort].y = day;
8749 }
8750 else
8751 {
8752 tempshort = pointhighlight; //search points CW if not searched all the way around
8753 do
8754 {
8755 if (wall[lastwall(tempshort)].nextwall >= 0)
8756 {
8757 tempshort = wall[lastwall(tempshort)].nextwall;
8758 wall[tempshort].x = dax;
8759 wall[tempshort].y = day;
8760 }
8761 else
8762 {
8763 break;
8764 }
8765 cnt--;
8766 }
8767 while ((tempshort != pointhighlight) && (cnt > 0));
8768 break;
8769 }
8770 cnt--;
8771 }
8772 while ((tempshort != pointhighlight) && (cnt > 0));
8773 }
8774
8775
8776 //
8777 // lastwall
8778 //
lastwall(short point)8779 int lastwall(short point)
8780 {
8781 int i, j, cnt;
8782
8783 if ((point > 0) && (wall[point-1].point2 == point)) return(point-1);
8784 i = point;
8785 cnt = MAXWALLS;
8786 do
8787 {
8788 j = wall[i].point2;
8789 if (j == point) return(i);
8790 i = j;
8791 cnt--;
8792 } while (cnt > 0);
8793 return(point);
8794 }
8795
8796
8797
8798 #define addclipline(dax1, day1, dax2, day2, daoval) \
8799 { \
8800 if (clipnum < MAXCLIPNUM) { \
8801 clipit[clipnum].x1 = dax1; clipit[clipnum].y1 = day1; \
8802 clipit[clipnum].x2 = dax2; clipit[clipnum].y2 = day2; \
8803 clipobjectval[clipnum] = daoval; \
8804 clipnum++; \
8805 } \
8806 } \
8807
8808 int clipmoveboxtracenum = 3;
8809
8810 //
8811 // clipmove
8812 //
clipmove(int * x,int * y,int * z,short * sectnum,int xvect,int yvect,int walldist,int ceildist,int flordist,unsigned int cliptype)8813 int clipmove (int *x, int *y, int *z, short *sectnum,
8814 int xvect, int yvect,
8815 int walldist, int ceildist, int flordist, unsigned int cliptype)
8816 {
8817 walltype *wal, *wal2;
8818 spritetype *spr;
8819 sectortype *sec, *sec2;
8820 int i, j, templong1, templong2;
8821 int oxvect, oyvect, goalx, goaly, intx, inty, lx, ly, retval;
8822 int k, l, clipsectcnt, startwall, endwall, cstat, dasect;
8823 int x1, y1, x2, y2, cx, cy, rad, xmin, ymin, xmax, ymax, daz, daz2;
8824 int bsz, dax, day, xoff, yoff, xspan, yspan, cosang, sinang, tilenum;
8825 int xrepeat, yrepeat, gx, gy, dx, dy, dasprclipmask, dawalclipmask;
8826 int hitwall, cnt, clipyou;
8827
8828 if (((xvect|yvect) == 0) || (*sectnum < 0)) return(0);
8829 retval = 0;
8830
8831 oxvect = xvect;
8832 oyvect = yvect;
8833
8834 goalx = (*x) + (xvect>>14);
8835 goaly = (*y) + (yvect>>14);
8836
8837
8838 clipnum = 0;
8839
8840 cx = (((*x)+goalx)>>1);
8841 cy = (((*y)+goaly)>>1);
8842 //Extra walldist for sprites on sector lines
8843 gx = goalx-(*x); gy = goaly-(*y);
8844 rad = nsqrtasm(gx*gx + gy*gy) + MAXCLIPDIST+walldist + 8;
8845 xmin = cx-rad; ymin = cy-rad;
8846 xmax = cx+rad; ymax = cy+rad;
8847
8848 dawalclipmask = (cliptype&65535); //CLIPMASK0 = 0x00010001
8849 dasprclipmask = (cliptype>>16); //CLIPMASK1 = 0x01000040
8850
8851 clipsectorlist[0] = (*sectnum);
8852 clipsectcnt = 0; clipsectnum = 1;
8853 do
8854 {
8855 dasect = clipsectorlist[clipsectcnt++];
8856 sec = §or[dasect];
8857 startwall = sec->wallptr; endwall = startwall + sec->wallnum;
8858 for(j=startwall,wal=&wall[startwall];j<endwall;j++,wal++)
8859 {
8860 wal2 = &wall[wal->point2];
8861 if ((wal->x < xmin) && (wal2->x < xmin)) continue;
8862 if ((wal->x > xmax) && (wal2->x > xmax)) continue;
8863 if ((wal->y < ymin) && (wal2->y < ymin)) continue;
8864 if ((wal->y > ymax) && (wal2->y > ymax)) continue;
8865
8866 x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y;
8867
8868 dx = x2-x1; dy = y2-y1;
8869 if (dx*((*y)-y1) < ((*x)-x1)*dy) continue; //If wall's not facing you
8870
8871 if (dx > 0) dax = dx*(ymin-y1); else dax = dx*(ymax-y1);
8872 if (dy > 0) day = dy*(xmax-x1); else day = dy*(xmin-x1);
8873 if (dax >= day) continue;
8874
8875 clipyou = 0;
8876 if ((wal->nextsector < 0) || (wal->cstat&dawalclipmask)) clipyou = 1;
8877 else if (editstatus == 0)
8878 {
8879 if (rintersect(*x,*y,0,gx,gy,0,x1,y1,x2,y2,&dax,&day,&daz) == 0)
8880 dax = *x, day = *y;
8881 daz = getflorzofslope((short)dasect,dax,day);
8882 daz2 = getflorzofslope(wal->nextsector,dax,day);
8883
8884 sec2 = §or[wal->nextsector];
8885 if (daz2 < daz-(1<<8))
8886 if ((sec2->floorstat&1) == 0)
8887 if ((*z) >= daz2-(flordist-1)) clipyou = 1;
8888 if (clipyou == 0)
8889 {
8890 daz = getceilzofslope((short)dasect,dax,day);
8891 daz2 = getceilzofslope(wal->nextsector,dax,day);
8892 if (daz2 > daz+(1<<8))
8893 if ((sec2->ceilingstat&1) == 0)
8894 if ((*z) <= daz2+(ceildist-1)) clipyou = 1;
8895 }
8896 }
8897
8898 if (clipyou)
8899 {
8900 //Add 2 boxes at endpoints
8901 bsz = walldist; if (gx < 0) bsz = -bsz;
8902 addclipline(x1-bsz,y1-bsz,x1-bsz,y1+bsz,(short)j+32768);
8903 addclipline(x2-bsz,y2-bsz,x2-bsz,y2+bsz,(short)j+32768);
8904 bsz = walldist; if (gy < 0) bsz = -bsz;
8905 addclipline(x1+bsz,y1-bsz,x1-bsz,y1-bsz,(short)j+32768);
8906 addclipline(x2+bsz,y2-bsz,x2-bsz,y2-bsz,(short)j+32768);
8907
8908 dax = walldist; if (dy > 0) dax = -dax;
8909 day = walldist; if (dx < 0) day = -day;
8910 addclipline(x1+dax,y1+day,x2+dax,y2+day,(short)j+32768);
8911 }
8912 else
8913 {
8914 for(i=clipsectnum-1;i>=0;i--)
8915 if (wal->nextsector == clipsectorlist[i]) break;
8916 if (i < 0) clipsectorlist[clipsectnum++] = wal->nextsector;
8917 }
8918 }
8919
8920 for(j=headspritesect[dasect];j>=0;j=nextspritesect[j])
8921 {
8922 spr = &sprite[j];
8923 cstat = spr->cstat;
8924 if ((cstat&dasprclipmask) == 0) continue;
8925 x1 = spr->x; y1 = spr->y;
8926 switch(cstat&48)
8927 {
8928 case 0:
8929 if ((x1 >= xmin) && (x1 <= xmax) && (y1 >= ymin) && (y1 <= ymax))
8930 {
8931 k = ((tilesizy[spr->picnum]*spr->yrepeat)<<2);
8932 if (cstat&128) daz = spr->z+(k>>1); else daz = spr->z;
8933 if (picanm[spr->picnum]&0x00ff0000) daz -= ((int)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
8934 if (((*z) < daz+ceildist) && ((*z) > daz-k-flordist))
8935 {
8936 bsz = (spr->clipdist<<2)+walldist; if (gx < 0) bsz = -bsz;
8937 addclipline(x1-bsz,y1-bsz,x1-bsz,y1+bsz,(short)j+49152);
8938 bsz = (spr->clipdist<<2)+walldist; if (gy < 0) bsz = -bsz;
8939 addclipline(x1+bsz,y1-bsz,x1-bsz,y1-bsz,(short)j+49152);
8940 }
8941 }
8942 break;
8943 case 16:
8944 k = ((tilesizy[spr->picnum]*spr->yrepeat)<<2);
8945 if (cstat&128) daz = spr->z+(k>>1); else daz = spr->z;
8946 if (picanm[spr->picnum]&0x00ff0000) daz -= ((int)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
8947 daz2 = daz-k;
8948 daz += ceildist; daz2 -= flordist;
8949 if (((*z) < daz) && ((*z) > daz2))
8950 {
8951 //These lines get the 2 points of the rotated sprite
8952 //Given: (x1, y1) starts out as the center point
8953 tilenum = spr->picnum;
8954 xoff = (int)((signed char)((picanm[tilenum]>>8)&255))+((int)spr->xoffset);
8955 if ((cstat&4) > 0) xoff = -xoff;
8956 k = spr->ang; l = spr->xrepeat;
8957 dax = sintable[k&2047]*l; day = sintable[(k+1536)&2047]*l;
8958 l = tilesizx[tilenum]; k = (l>>1)+xoff;
8959 x1 -= mulscale16(dax,k); x2 = x1+mulscale16(dax,l);
8960 y1 -= mulscale16(day,k); y2 = y1+mulscale16(day,l);
8961 if (clipinsideboxline(cx,cy,x1,y1,x2,y2,rad) != 0)
8962 {
8963 dax = mulscale14(sintable[(spr->ang+256+512)&2047],walldist);
8964 day = mulscale14(sintable[(spr->ang+256)&2047],walldist);
8965
8966 if ((x1-(*x))*(y2-(*y)) >= (x2-(*x))*(y1-(*y))) //Front
8967 {
8968 addclipline(x1+dax,y1+day,x2+day,y2-dax,(short)j+49152);
8969 }
8970 else
8971 {
8972 if ((cstat&64) != 0) continue;
8973 addclipline(x2-dax,y2-day,x1-day,y1+dax,(short)j+49152);
8974 }
8975
8976 //Side blocker
8977 if ((x2-x1)*((*x)-x1) + (y2-y1)*((*y)-y1) < 0)
8978 { addclipline(x1-day,y1+dax,x1+dax,y1+day,(short)j+49152); }
8979 else if ((x1-x2)*((*x)-x2) + (y1-y2)*((*y)-y2) < 0)
8980 { addclipline(x2+day,y2-dax,x2-dax,y2-day,(short)j+49152); }
8981 }
8982 }
8983 break;
8984 case 32:
8985 daz = spr->z+ceildist;
8986 daz2 = spr->z-flordist;
8987 if (((*z) < daz) && ((*z) > daz2))
8988 {
8989 if ((cstat&64) != 0)
8990 if (((*z) > spr->z) == ((cstat&8)==0)) continue;
8991
8992 tilenum = spr->picnum;
8993 xoff = (int)((signed char)((picanm[tilenum]>>8)&255))+((int)spr->xoffset);
8994 yoff = (int)((signed char)((picanm[tilenum]>>16)&255))+((int)spr->yoffset);
8995 if ((cstat&4) > 0) xoff = -xoff;
8996 if ((cstat&8) > 0) yoff = -yoff;
8997
8998 k = spr->ang;
8999 cosang = sintable[(k+512)&2047]; sinang = sintable[k];
9000 xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat;
9001 yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat;
9002
9003 dax = ((xspan>>1)+xoff)*xrepeat; day = ((yspan>>1)+yoff)*yrepeat;
9004 rxi[0] = x1 + dmulscale16(sinang,dax,cosang,day);
9005 ryi[0] = y1 + dmulscale16(sinang,day,-cosang,dax);
9006 l = xspan*xrepeat;
9007 rxi[1] = rxi[0] - mulscale16(sinang,l);
9008 ryi[1] = ryi[0] + mulscale16(cosang,l);
9009 l = yspan*yrepeat;
9010 k = -mulscale16(cosang,l); rxi[2] = rxi[1]+k; rxi[3] = rxi[0]+k;
9011 k = -mulscale16(sinang,l); ryi[2] = ryi[1]+k; ryi[3] = ryi[0]+k;
9012
9013 dax = mulscale14(sintable[(spr->ang-256+512)&2047],walldist);
9014 day = mulscale14(sintable[(spr->ang-256)&2047],walldist);
9015
9016 if ((rxi[0]-(*x))*(ryi[1]-(*y)) < (rxi[1]-(*x))*(ryi[0]-(*y)))
9017 {
9018 if (clipinsideboxline(cx,cy,rxi[1],ryi[1],rxi[0],ryi[0],rad) != 0)
9019 addclipline(rxi[1]-day,ryi[1]+dax,rxi[0]+dax,ryi[0]+day,(short)j+49152);
9020 }
9021 else if ((rxi[2]-(*x))*(ryi[3]-(*y)) < (rxi[3]-(*x))*(ryi[2]-(*y)))
9022 {
9023 if (clipinsideboxline(cx,cy,rxi[3],ryi[3],rxi[2],ryi[2],rad) != 0)
9024 addclipline(rxi[3]+day,ryi[3]-dax,rxi[2]-dax,ryi[2]-day,(short)j+49152);
9025 }
9026
9027 if ((rxi[1]-(*x))*(ryi[2]-(*y)) < (rxi[2]-(*x))*(ryi[1]-(*y)))
9028 {
9029 if (clipinsideboxline(cx,cy,rxi[2],ryi[2],rxi[1],ryi[1],rad) != 0)
9030 addclipline(rxi[2]-dax,ryi[2]-day,rxi[1]-day,ryi[1]+dax,(short)j+49152);
9031 }
9032 else if ((rxi[3]-(*x))*(ryi[0]-(*y)) < (rxi[0]-(*x))*(ryi[3]-(*y)))
9033 {
9034 if (clipinsideboxline(cx,cy,rxi[0],ryi[0],rxi[3],ryi[3],rad) != 0)
9035 addclipline(rxi[0]+dax,ryi[0]+day,rxi[3]+day,ryi[3]-dax,(short)j+49152);
9036 }
9037 }
9038 break;
9039 }
9040 }
9041 } while (clipsectcnt < clipsectnum);
9042
9043
9044 hitwall = 0;
9045 cnt = clipmoveboxtracenum;
9046 do
9047 {
9048 intx = goalx; inty = goaly;
9049 if ((hitwall = raytrace(*x, *y, &intx, &inty)) >= 0)
9050 {
9051 lx = clipit[hitwall].x2-clipit[hitwall].x1;
9052 ly = clipit[hitwall].y2-clipit[hitwall].y1;
9053 templong2 = lx*lx + ly*ly;
9054 if (templong2 > 0)
9055 {
9056 templong1 = (goalx-intx)*lx + (goaly-inty)*ly;
9057
9058 if ((klabs(templong1)>>11) < templong2)
9059 i = divscale20(templong1,templong2);
9060 else
9061 i = 0;
9062 goalx = mulscale20(lx,i)+intx;
9063 goaly = mulscale20(ly,i)+inty;
9064 }
9065
9066 templong1 = dmulscale6(lx,oxvect,ly,oyvect);
9067 for(i=cnt+1;i<=clipmoveboxtracenum;i++)
9068 {
9069 j = hitwalls[i];
9070 templong2 = dmulscale6(clipit[j].x2-clipit[j].x1,oxvect,clipit[j].y2-clipit[j].y1,oyvect);
9071 if ((templong1^templong2) < 0)
9072 {
9073 updatesector(*x,*y,sectnum);
9074 return(retval);
9075 }
9076 }
9077
9078 keepaway(&goalx, &goaly, hitwall);
9079 xvect = ((goalx-intx)<<14);
9080 yvect = ((goaly-inty)<<14);
9081
9082 if (cnt == clipmoveboxtracenum) retval = clipobjectval[hitwall];
9083 hitwalls[cnt] = hitwall;
9084 }
9085 cnt--;
9086
9087 *x = intx;
9088 *y = inty;
9089 } while (((xvect|yvect) != 0) && (hitwall >= 0) && (cnt > 0));
9090
9091 for(j=0;j<clipsectnum;j++)
9092 if (inside(*x,*y,clipsectorlist[j]) == 1)
9093 {
9094 *sectnum = clipsectorlist[j];
9095 return(retval);
9096 }
9097
9098 *sectnum = -1; templong1 = 0x7fffffff;
9099 for(j=numsectors-1;j>=0;j--)
9100 if (inside(*x,*y,j) == 1)
9101 {
9102 if (sector[j].ceilingstat&2)
9103 templong2 = (getceilzofslope((short)j,*x,*y)-(*z));
9104 else
9105 templong2 = (sector[j].ceilingz-(*z));
9106
9107 if (templong2 > 0)
9108 {
9109 if (templong2 < templong1)
9110 { *sectnum = j; templong1 = templong2; }
9111 }
9112 else
9113 {
9114 if (sector[j].floorstat&2)
9115 templong2 = ((*z)-getflorzofslope((short)j,*x,*y));
9116 else
9117 templong2 = ((*z)-sector[j].floorz);
9118
9119 if (templong2 <= 0)
9120 {
9121 *sectnum = j;
9122 return(retval);
9123 }
9124 if (templong2 < templong1)
9125 { *sectnum = j; templong1 = templong2; }
9126 }
9127 }
9128
9129 return(retval);
9130 }
9131
9132
9133 //
9134 // pushmove
9135 //
pushmove(int * x,int * y,int * z,short * sectnum,int walldist,int ceildist,int flordist,unsigned int cliptype)9136 int pushmove (int *x, int *y, int *z, short *sectnum,
9137 int walldist, int ceildist, int flordist, unsigned int cliptype)
9138 {
9139 sectortype *sec, *sec2;
9140 walltype *wal, *wal2;
9141 spritetype *spr;
9142 int i, j, k, t, dx, dy, dax, day, daz, daz2, bad, dir;
9143 int dasprclipmask, dawalclipmask;
9144 short startwall, endwall, clipsectcnt;
9145 char bad2;
9146
9147 if ((*sectnum) < 0) return(-1);
9148
9149 dawalclipmask = (cliptype&65535);
9150 dasprclipmask = (cliptype>>16);
9151
9152 k = 32;
9153 dir = 1;
9154 do
9155 {
9156 bad = 0;
9157
9158 clipsectorlist[0] = *sectnum;
9159 clipsectcnt = 0; clipsectnum = 1;
9160 do
9161 {
9162 /*Push FACE sprites
9163 for(i=headspritesect[clipsectorlist[clipsectcnt]];i>=0;i=nextspritesect[i])
9164 {
9165 spr = &sprite[i];
9166 if (((spr->cstat&48) != 0) && ((spr->cstat&48) != 48)) continue;
9167 if ((spr->cstat&dasprclipmask) == 0) continue;
9168
9169 dax = (*x)-spr->x; day = (*y)-spr->y;
9170 t = (spr->clipdist<<2)+walldist;
9171 if ((klabs(dax) < t) && (klabs(day) < t))
9172 {
9173 t = ((tilesizy[spr->picnum]*spr->yrepeat)<<2);
9174 if (spr->cstat&128) daz = spr->z+(t>>1); else daz = spr->z;
9175 if (picanm[spr->picnum]&0x00ff0000) daz -= ((int)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
9176 if (((*z) < daz+ceildist) && ((*z) > daz-t-flordist))
9177 {
9178 t = (spr->clipdist<<2)+walldist;
9179
9180 j = getangle(dax,day);
9181 dx = (sintable[(j+512)&2047]>>11);
9182 dy = (sintable[(j)&2047]>>11);
9183 bad2 = 16;
9184 do
9185 {
9186 *x = (*x) + dx; *y = (*y) + dy;
9187 bad2--; if (bad2 == 0) break;
9188 } while ((klabs((*x)-spr->x) < t) && (klabs((*y)-spr->y) < t));
9189 bad = -1;
9190 k--; if (k <= 0) return(bad);
9191 updatesector(*x,*y,sectnum);
9192 }
9193 }
9194 }*/
9195
9196 sec = §or[clipsectorlist[clipsectcnt]];
9197 if (dir > 0)
9198 startwall = sec->wallptr, endwall = startwall + sec->wallnum;
9199 else
9200 endwall = sec->wallptr, startwall = endwall + sec->wallnum;
9201
9202 for(i=startwall,wal=&wall[startwall];i!=endwall;i+=dir,wal+=dir)
9203 if (clipinsidebox(*x,*y,i,walldist-4) == 1)
9204 {
9205 j = 0;
9206 if (wal->nextsector < 0) j = 1;
9207 if (wal->cstat&dawalclipmask) j = 1;
9208 if (j == 0)
9209 {
9210 sec2 = §or[wal->nextsector];
9211
9212
9213 //Find closest point on wall (dax, day) to (*x, *y)
9214 dax = wall[wal->point2].x-wal->x;
9215 day = wall[wal->point2].y-wal->y;
9216 daz = dax*((*x)-wal->x) + day*((*y)-wal->y);
9217 if (daz <= 0)
9218 t = 0;
9219 else
9220 {
9221 daz2 = dax*dax+day*day;
9222 if (daz >= daz2) t = (1<<30); else t = divscale30(daz,daz2);
9223 }
9224 dax = wal->x + mulscale30(dax,t);
9225 day = wal->y + mulscale30(day,t);
9226
9227
9228 daz = getflorzofslope(clipsectorlist[clipsectcnt],dax,day);
9229 daz2 = getflorzofslope(wal->nextsector,dax,day);
9230 if ((daz2 < daz-(1<<8)) && ((sec2->floorstat&1) == 0))
9231 if (*z >= daz2-(flordist-1)) j = 1;
9232
9233 daz = getceilzofslope(clipsectorlist[clipsectcnt],dax,day);
9234 daz2 = getceilzofslope(wal->nextsector,dax,day);
9235 if ((daz2 > daz+(1<<8)) && ((sec2->ceilingstat&1) == 0))
9236 if (*z <= daz2+(ceildist-1)) j = 1;
9237 }
9238 if (j != 0)
9239 {
9240 j = getangle(wall[wal->point2].x-wal->x,wall[wal->point2].y-wal->y);
9241 dx = (sintable[(j+1024)&2047]>>11);
9242 dy = (sintable[(j+512)&2047]>>11);
9243 bad2 = 16;
9244 do
9245 {
9246 *x = (*x) + dx; *y = (*y) + dy;
9247 bad2--; if (bad2 == 0) break;
9248 } while (clipinsidebox(*x,*y,i,walldist-4) != 0);
9249 bad = -1;
9250 k--; if (k <= 0) return(bad);
9251 updatesector(*x,*y,sectnum);
9252 }
9253 else
9254 {
9255 for(j=clipsectnum-1;j>=0;j--)
9256 if (wal->nextsector == clipsectorlist[j]) break;
9257 if (j < 0) clipsectorlist[clipsectnum++] = wal->nextsector;
9258 }
9259 }
9260
9261 clipsectcnt++;
9262 } while (clipsectcnt < clipsectnum);
9263 dir = -dir;
9264 } while (bad != 0);
9265
9266 return(bad);
9267 }
9268
9269
9270 //
9271 // updatesector[z]
9272 //
updatesector(int x,int y,short * sectnum)9273 void updatesector(int x, int y, short *sectnum)
9274 {
9275 walltype *wal;
9276 int i, j;
9277
9278 if (inside(x,y,*sectnum) == 1) return;
9279
9280 if ((*sectnum >= 0) && (*sectnum < numsectors))
9281 {
9282 wal = &wall[sector[*sectnum].wallptr];
9283 j = sector[*sectnum].wallnum;
9284 do
9285 {
9286 i = wal->nextsector;
9287 if (i >= 0)
9288 if (inside(x,y,(short)i) == 1)
9289 {
9290 *sectnum = i;
9291 return;
9292 }
9293 wal++;
9294 j--;
9295 } while (j != 0);
9296 }
9297
9298 for(i=numsectors-1;i>=0;i--)
9299 if (inside(x,y,(short)i) == 1)
9300 {
9301 *sectnum = i;
9302 return;
9303 }
9304
9305 *sectnum = -1;
9306 }
9307
updatesectorz(int x,int y,int z,short * sectnum)9308 void updatesectorz(int x, int y, int z, short *sectnum)
9309 {
9310 walltype *wal;
9311 int i, j, cz, fz;
9312
9313 getzsofslope(*sectnum, x, y, &cz, &fz);
9314 if ((z >= cz) && (z <= fz))
9315 if (inside(x,y,*sectnum) != 0) return;
9316
9317 if ((*sectnum >= 0) && (*sectnum < numsectors))
9318 {
9319 wal = &wall[sector[*sectnum].wallptr];
9320 j = sector[*sectnum].wallnum;
9321 do
9322 {
9323 i = wal->nextsector;
9324 if (i >= 0)
9325 {
9326 getzsofslope(i, x, y, &cz, &fz);
9327 if ((z >= cz) && (z <= fz))
9328 if (inside(x,y,(short)i) == 1)
9329 { *sectnum = i; return; }
9330 }
9331 wal++; j--;
9332 } while (j != 0);
9333 }
9334
9335 for (i=numsectors-1;i>=0;i--)
9336 {
9337 getzsofslope(i, x, y, &cz, &fz);
9338 if ((z >= cz) && (z <= fz))
9339 if (inside(x,y,(short)i) == 1)
9340 { *sectnum = i; return; }
9341 }
9342
9343 *sectnum = -1;
9344 }
9345
9346
9347 //
9348 // rotatepoint
9349 //
rotatepoint(int xpivot,int ypivot,int x,int y,short daang,int * x2,int * y2)9350 void rotatepoint(int xpivot, int ypivot, int x, int y, short daang, int *x2, int *y2)
9351 {
9352 int dacos, dasin;
9353
9354 dacos = sintable[(daang+2560)&2047];
9355 dasin = sintable[(daang+2048)&2047];
9356 x -= xpivot;
9357 y -= ypivot;
9358 *x2 = dmulscale14(x,dacos,-y,dasin) + xpivot;
9359 *y2 = dmulscale14(y,dacos,x,dasin) + ypivot;
9360 }
9361
9362
9363 //
9364 // getmousevalues
9365 //
getmousevalues(int * mousx,int * mousy,int * bstatus)9366 void getmousevalues(int *mousx, int *mousy, int *bstatus)
9367 {
9368 readmousexy(mousx,mousy);
9369 readmousebstatus(bstatus);
9370 }
9371
9372
9373 //
9374 // krand
9375 //
krand(void)9376 int krand(void)
9377 {
9378 randomseed = (randomseed*27584621)+1;
9379 return(((unsigned int)randomseed)>>16);
9380 }
9381
9382
9383 //
9384 // getzrange
9385 //
getzrange(int x,int y,int z,short sectnum,int * ceilz,int * ceilhit,int * florz,int * florhit,int walldist,unsigned int cliptype)9386 void getzrange(int x, int y, int z, short sectnum,
9387 int *ceilz, int *ceilhit, int *florz, int *florhit,
9388 int walldist, unsigned int cliptype)
9389 {
9390 sectortype *sec;
9391 walltype *wal, *wal2;
9392 spritetype *spr;
9393 int clipsectcnt, startwall, endwall, tilenum, xoff, yoff, dax, day;
9394 int xmin, ymin, xmax, ymax, i, j, k, l, daz, daz2, dx, dy;
9395 int x1, y1, x2, y2, x3, y3, x4, y4, ang, cosang, sinang;
9396 int xspan, yspan, xrepeat, yrepeat, dasprclipmask, dawalclipmask;
9397 short cstat;
9398 unsigned char clipyou;
9399
9400 if (sectnum < 0)
9401 {
9402 *ceilz = 0x80000000; *ceilhit = -1;
9403 *florz = 0x7fffffff; *florhit = -1;
9404 return;
9405 }
9406
9407 //Extra walldist for sprites on sector lines
9408 i = walldist+MAXCLIPDIST+1;
9409 xmin = x-i; ymin = y-i;
9410 xmax = x+i; ymax = y+i;
9411
9412 getzsofslope(sectnum,x,y,ceilz,florz);
9413 *ceilhit = sectnum+16384; *florhit = sectnum+16384;
9414
9415 dawalclipmask = (cliptype&65535);
9416 dasprclipmask = (cliptype>>16);
9417
9418 clipsectorlist[0] = sectnum;
9419 clipsectcnt = 0; clipsectnum = 1;
9420
9421 do //Collect sectors inside your square first
9422 {
9423 sec = §or[clipsectorlist[clipsectcnt]];
9424 startwall = sec->wallptr; endwall = startwall + sec->wallnum;
9425 for(j=startwall,wal=&wall[startwall];j<endwall;j++,wal++)
9426 {
9427 k = wal->nextsector;
9428 if (k >= 0)
9429 {
9430 wal2 = &wall[wal->point2];
9431 x1 = wal->x; x2 = wal2->x;
9432 if ((x1 < xmin) && (x2 < xmin)) continue;
9433 if ((x1 > xmax) && (x2 > xmax)) continue;
9434 y1 = wal->y; y2 = wal2->y;
9435 if ((y1 < ymin) && (y2 < ymin)) continue;
9436 if ((y1 > ymax) && (y2 > ymax)) continue;
9437
9438 dx = x2-x1; dy = y2-y1;
9439 if (dx*(y-y1) < (x-x1)*dy) continue; //back
9440 if (dx > 0) dax = dx*(ymin-y1); else dax = dx*(ymax-y1);
9441 if (dy > 0) day = dy*(xmax-x1); else day = dy*(xmin-x1);
9442 if (dax >= day) continue;
9443
9444 if (wal->cstat&dawalclipmask) continue;
9445 sec = §or[k];
9446 if (editstatus == 0)
9447 {
9448 if (((sec->ceilingstat&1) == 0) && (z <= sec->ceilingz+(3<<8))) continue;
9449 if (((sec->floorstat&1) == 0) && (z >= sec->floorz-(3<<8))) continue;
9450 }
9451
9452 for(i=clipsectnum-1;i>=0;i--) if (clipsectorlist[i] == k) break;
9453 if (i < 0) clipsectorlist[clipsectnum++] = k;
9454
9455 if ((x1 < xmin+MAXCLIPDIST) && (x2 < xmin+MAXCLIPDIST)) continue;
9456 if ((x1 > xmax-MAXCLIPDIST) && (x2 > xmax-MAXCLIPDIST)) continue;
9457 if ((y1 < ymin+MAXCLIPDIST) && (y2 < ymin+MAXCLIPDIST)) continue;
9458 if ((y1 > ymax-MAXCLIPDIST) && (y2 > ymax-MAXCLIPDIST)) continue;
9459 if (dx > 0) dax += dx*MAXCLIPDIST; else dax -= dx*MAXCLIPDIST;
9460 if (dy > 0) day -= dy*MAXCLIPDIST; else day += dy*MAXCLIPDIST;
9461 if (dax >= day) continue;
9462
9463 //It actually got here, through all the continue's!!!
9464 getzsofslope((short)k,x,y,&daz,&daz2);
9465 if (daz > *ceilz) { *ceilz = daz; *ceilhit = k+16384; }
9466 if (daz2 < *florz) { *florz = daz2; *florhit = k+16384; }
9467 }
9468 }
9469 clipsectcnt++;
9470 } while (clipsectcnt < clipsectnum);
9471
9472 for(i=0;i<clipsectnum;i++)
9473 {
9474 for(j=headspritesect[clipsectorlist[i]];j>=0;j=nextspritesect[j])
9475 {
9476 spr = &sprite[j];
9477 cstat = spr->cstat;
9478 if (cstat&dasprclipmask)
9479 {
9480 x1 = spr->x; y1 = spr->y;
9481
9482 clipyou = 0;
9483 switch(cstat&48)
9484 {
9485 case 0:
9486 k = walldist+(spr->clipdist<<2)+1;
9487 if ((klabs(x1-x) <= k) && (klabs(y1-y) <= k))
9488 {
9489 daz = spr->z;
9490 k = ((tilesizy[spr->picnum]*spr->yrepeat)<<1);
9491 if (cstat&128) daz += k;
9492 if (picanm[spr->picnum]&0x00ff0000) daz -= ((int)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
9493 daz2 = daz - (k<<1);
9494 clipyou = 1;
9495 }
9496 break;
9497 case 16:
9498 tilenum = spr->picnum;
9499 xoff = (int)((signed char)((picanm[tilenum]>>8)&255))+((int)spr->xoffset);
9500 if ((cstat&4) > 0) xoff = -xoff;
9501 k = spr->ang; l = spr->xrepeat;
9502 dax = sintable[k&2047]*l; day = sintable[(k+1536)&2047]*l;
9503 l = tilesizx[tilenum]; k = (l>>1)+xoff;
9504 x1 -= mulscale16(dax,k); x2 = x1+mulscale16(dax,l);
9505 y1 -= mulscale16(day,k); y2 = y1+mulscale16(day,l);
9506 if (clipinsideboxline(x,y,x1,y1,x2,y2,walldist+1) != 0)
9507 {
9508 daz = spr->z; k = ((tilesizy[spr->picnum]*spr->yrepeat)<<1);
9509 if (cstat&128) daz += k;
9510 if (picanm[spr->picnum]&0x00ff0000) daz -= ((int)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
9511 daz2 = daz-(k<<1);
9512 clipyou = 1;
9513 }
9514 break;
9515 case 32:
9516 daz = spr->z; daz2 = daz;
9517
9518 if ((cstat&64) != 0)
9519 if ((z > daz) == ((cstat&8)==0)) continue;
9520
9521 tilenum = spr->picnum;
9522 xoff = (int)((signed char)((picanm[tilenum]>>8)&255))+((int)spr->xoffset);
9523 yoff = (int)((signed char)((picanm[tilenum]>>16)&255))+((int)spr->yoffset);
9524 if ((cstat&4) > 0) xoff = -xoff;
9525 if ((cstat&8) > 0) yoff = -yoff;
9526
9527 ang = spr->ang;
9528 cosang = sintable[(ang+512)&2047]; sinang = sintable[ang];
9529 xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat;
9530 yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat;
9531
9532 dax = ((xspan>>1)+xoff)*xrepeat; day = ((yspan>>1)+yoff)*yrepeat;
9533 x1 += dmulscale16(sinang,dax,cosang,day)-x;
9534 y1 += dmulscale16(sinang,day,-cosang,dax)-y;
9535 l = xspan*xrepeat;
9536 x2 = x1 - mulscale16(sinang,l);
9537 y2 = y1 + mulscale16(cosang,l);
9538 l = yspan*yrepeat;
9539 k = -mulscale16(cosang,l); x3 = x2+k; x4 = x1+k;
9540 k = -mulscale16(sinang,l); y3 = y2+k; y4 = y1+k;
9541
9542 dax = mulscale14(sintable[(spr->ang-256+512)&2047],walldist+4);
9543 day = mulscale14(sintable[(spr->ang-256)&2047],walldist+4);
9544 x1 += dax; x2 -= day; x3 -= dax; x4 += day;
9545 y1 += day; y2 += dax; y3 -= day; y4 -= dax;
9546
9547 if ((y1^y2) < 0)
9548 {
9549 if ((x1^x2) < 0) clipyou ^= (x1*y2<x2*y1)^(y1<y2);
9550 else if (x1 >= 0) clipyou ^= 1;
9551 }
9552 if ((y2^y3) < 0)
9553 {
9554 if ((x2^x3) < 0) clipyou ^= (x2*y3<x3*y2)^(y2<y3);
9555 else if (x2 >= 0) clipyou ^= 1;
9556 }
9557 if ((y3^y4) < 0)
9558 {
9559 if ((x3^x4) < 0) clipyou ^= (x3*y4<x4*y3)^(y3<y4);
9560 else if (x3 >= 0) clipyou ^= 1;
9561 }
9562 if ((y4^y1) < 0)
9563 {
9564 if ((x4^x1) < 0) clipyou ^= (x4*y1<x1*y4)^(y4<y1);
9565 else if (x4 >= 0) clipyou ^= 1;
9566 }
9567 break;
9568 }
9569
9570 if (clipyou != 0)
9571 {
9572 if ((z > daz) && (daz > *ceilz)) { *ceilz = daz; *ceilhit = j+49152; }
9573 if ((z < daz2) && (daz2 < *florz)) { *florz = daz2; *florhit = j+49152; }
9574 }
9575 }
9576 }
9577 }
9578 }
9579
9580
9581 //
9582 // setview
9583 //
setview(int x1,int y1,int x2,int y2)9584 void setview(int x1, int y1, int x2, int y2)
9585 {
9586 int i;
9587 float xfov;
9588
9589 xfov = ((float)xdim / (float)ydim) / (4.f / 3.f);
9590
9591 windowx1 = x1; wx1 = (x1<<12);
9592 windowy1 = y1; wy1 = (y1<<12);
9593 windowx2 = x2; wx2 = ((x2+1)<<12);
9594 windowy2 = y2; wy2 = ((y2+1)<<12);
9595
9596 xdimen = (x2-x1)+1; halfxdimen = (xdimen>>1);
9597 xdimenrecip = divscale32(1L,xdimen);
9598 ydimen = (y2-y1)+1;
9599
9600 setaspect((int)(65536.f * xfov), pixelaspect);
9601
9602 for(i=0;i<windowx1;i++) { startumost[i] = 1, startdmost[i] = 0; }
9603 for(i=windowx1;i<=windowx2;i++)
9604 { startumost[i] = windowy1, startdmost[i] = windowy2+1; }
9605 for(i=windowx2+1;i<xdim;i++) { startumost[i] = 1, startdmost[i] = 0; }
9606
9607 #if USE_POLYMOST && USE_OPENGL
9608 polymost_setview();
9609 #endif
9610 }
9611
9612
9613 //
9614 // setaspect
9615 //
setaspect(int daxrange,int daaspect)9616 void setaspect(int daxrange, int daaspect)
9617 {
9618 int ys = mulscale16(200, pixelaspect);
9619
9620 viewingrange = daxrange;
9621 viewingrangerecip = divscale32(1L,daxrange);
9622
9623 yxaspect = daaspect;
9624 xyaspect = divscale32(1,yxaspect);
9625 xdimenscale = scale(xdimen,yxaspect,320);
9626 xdimscale = scale(320,xyaspect,xdimen);
9627
9628 ydimenscale = scale(ydimen, yxaspect, ys);
9629 }
9630
9631
9632 //
9633 // flushperms
9634 //
flushperms(void)9635 void flushperms(void)
9636 {
9637 permhead = permtail = 0;
9638 }
9639
9640
9641 //
9642 // rotatesprite
9643 //
rotatesprite(int sx,int sy,int z,short a,short picnum,signed char dashade,unsigned char dapalnum,unsigned char dastat,int cx1,int cy1,int cx2,int cy2)9644 void rotatesprite(int sx, int sy, int z, short a, short picnum, signed char dashade,
9645 unsigned char dapalnum, unsigned char dastat, int cx1, int cy1, int cx2, int cy2)
9646 {
9647 int i, gap = -1;
9648 permfifotype *per, *per2;
9649
9650 if ((cx1 > cx2) || (cy1 > cy2)) return;
9651 if (z <= 16) return;
9652 if (picanm[picnum]&192) picnum += animateoffs(picnum,(short)0xc000);
9653 if ((tilesizx[picnum] <= 0) || (tilesizy[picnum] <= 0)) return;
9654
9655 if (((dastat&128) == 0) || (numpages < 2) || (beforedrawrooms != 0)) {
9656 begindrawing(); //{{{
9657 dorotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,cx1,cy1,cx2,cy2,guniqhudid);
9658 enddrawing(); //}}}
9659 }
9660
9661 if ((dastat&64) && (cx1 <= 0) && (cy1 <= 0) && (cx2 >= xdim-1) && (cy2 >= ydim-1) &&
9662 (sx == (160<<16)) && (sy == (100<<16)) && (z == 65536L) && (a == 0) && ((dastat&1) == 0))
9663 permhead = permtail = 0;
9664
9665 if ((dastat&128) == 0) return;
9666 if (numpages >= 2)
9667 {
9668 if (((permhead+1)&(MAXPERMS-1)) == permtail)
9669 {
9670 for(i=permtail;i!=permhead;i=((i+1)&(MAXPERMS-1)))
9671 {
9672 if ((permfifo[i].pagesleft&127) == 0)
9673 { if (gap < 0) gap = i; }
9674 else if (gap >= 0)
9675 {
9676 copybufbyte(&permfifo[i], &permfifo[gap], sizeof(permfifotype));
9677 permfifo[i].pagesleft = 0;
9678 for (;gap!=i;gap=((gap+1)&(MAXPERMS-1)))
9679 if ((permfifo[gap].pagesleft&127) == 0)
9680 break;
9681 if (gap==i) gap = -1;
9682 }
9683 }
9684 if (gap >= 0) permhead = gap;
9685 else permtail = ((permtail+1)&(MAXPERMS-1));
9686 }
9687 per = &permfifo[permhead];
9688 per->sx = sx; per->sy = sy; per->z = z; per->a = a;
9689 per->picnum = picnum;
9690 per->dashade = dashade; per->dapalnum = dapalnum;
9691 per->dastat = dastat;
9692 per->pagesleft = numpages+((beforedrawrooms&1)<<7);
9693 per->cx1 = cx1; per->cy1 = cy1; per->cx2 = cx2; per->cy2 = cy2;
9694 per->uniqid = guniqhudid; //JF extension
9695
9696 //Would be better to optimize out true bounding boxes
9697 if (dastat&64) //If non-masking write, checking for overlapping cases
9698 {
9699 for(i=permtail;i!=permhead;i=((i+1)&(MAXPERMS-1)))
9700 {
9701 per2 = &permfifo[i];
9702 if ((per2->pagesleft&127) == 0) continue;
9703 if (per2->sx != per->sx) continue;
9704 if (per2->sy != per->sy) continue;
9705 if (per2->z != per->z) continue;
9706 if (per2->a != per->a) continue;
9707 if (tilesizx[per2->picnum] > tilesizx[per->picnum]) continue;
9708 if (tilesizy[per2->picnum] > tilesizy[per->picnum]) continue;
9709 if (per2->cx1 < per->cx1) continue;
9710 if (per2->cy1 < per->cy1) continue;
9711 if (per2->cx2 > per->cx2) continue;
9712 if (per2->cy2 > per->cy2) continue;
9713 per2->pagesleft = 0;
9714 }
9715 if (per->a == 0)
9716 for(i=permtail;i!=permhead;i=((i+1)&(MAXPERMS-1)))
9717 {
9718 per2 = &permfifo[i];
9719 if ((per2->pagesleft&127) == 0) continue;
9720 if (per2->z != per->z) continue;
9721 if (per2->a != 0) continue;
9722 if (per2->cx1 < per->cx1) continue;
9723 if (per2->cy1 < per->cy1) continue;
9724 if (per2->cx2 > per->cx2) continue;
9725 if (per2->cy2 > per->cy2) continue;
9726 if ((per2->sx>>16) < (per->sx>>16)) continue;
9727 if ((per2->sy>>16) < (per->sy>>16)) continue;
9728 if (per2->sx+(tilesizx[per2->picnum]*per2->z) > per->sx+(tilesizx[per->picnum]*per->z)) continue;
9729 if (per2->sy+(tilesizy[per2->picnum]*per2->z) > per->sy+(tilesizy[per->picnum]*per->z)) continue;
9730 per2->pagesleft = 0;
9731 }
9732 }
9733
9734 permhead = ((permhead+1)&(MAXPERMS-1));
9735 }
9736 }
9737
9738
9739 //
9740 // makepalookup
9741 //
makepalookup(int palnum,unsigned char * remapbuf,signed char r,signed char g,signed char b,unsigned char dastat)9742 int makepalookup(int palnum, unsigned char *remapbuf, signed char r, signed char g, signed char b, unsigned char dastat)
9743 {
9744 int i, j, palscale;
9745 unsigned char *ptr, *ptr2;
9746
9747 if (palookup[palnum] == NULL)
9748 {
9749 //Allocate palookup buffer
9750 if ((palookup[palnum] = kmalloc(numpalookups<<8)) == NULL) {
9751 engineerrstr = "Failed to allocate palette lookup memory";
9752 return 1;
9753 }
9754 }
9755
9756 if (dastat == 0) return 0;
9757 if ((r|g|b|63) != 63) return 0;
9758
9759 if ((r|g|b) == 0)
9760 {
9761 for(i=0;i<256;i++)
9762 {
9763 ptr = (unsigned char *)((intptr_t)palookup[0]+remapbuf[i]);
9764 ptr2 = (unsigned char *)((intptr_t)palookup[palnum]+i);
9765 for(j=0;j<numpalookups;j++)
9766 { *ptr2 = *ptr; ptr += 256; ptr2 += 256; }
9767 }
9768 #if USE_POLYMOST && USE_OPENGL
9769 palookupfog[palnum].r = 0;
9770 palookupfog[palnum].g = 0;
9771 palookupfog[palnum].b = 0;
9772 #endif
9773 }
9774 else
9775 {
9776 ptr2 = palookup[palnum];
9777 for(i=0;i<numpalookups;i++)
9778 {
9779 palscale = divscale16(i,numpalookups);
9780 for(j=0;j<256;j++)
9781 {
9782 ptr = &palette[remapbuf[j]*3];
9783 *ptr2++ = getclosestcol((int)ptr[0]+mulscale16(r-ptr[0],palscale),
9784 (int)ptr[1]+mulscale16(g-ptr[1],palscale),
9785 (int)ptr[2]+mulscale16(b-ptr[2],palscale));
9786 }
9787 }
9788 #if USE_POLYMOST && USE_OPENGL
9789 palookupfog[palnum].r = r;
9790 palookupfog[palnum].g = g;
9791 palookupfog[palnum].b = b;
9792 #endif
9793 }
9794
9795 return 0;
9796 }
9797
9798
setvgapalette(void)9799 void setvgapalette(void)
9800 {
9801 int i;
9802
9803 for (i=0;i<256;i++) {
9804 curpalettefaded[i].b = curpalette[i].b = vgapal16[4*i] << 2;
9805 curpalettefaded[i].g = curpalette[i].g = vgapal16[4*i+1] << 2;
9806 curpalettefaded[i].r = curpalette[i].r = vgapal16[4*i+2] << 2;
9807 }
9808 setpalette(0,256,vgapal16);
9809 }
9810
9811 //
9812 // setbrightness
9813 //
9814 static unsigned int lastpalettesum = 0;
setbrightness(int dabrightness,unsigned char * dapal,char noapply)9815 void setbrightness(int dabrightness, unsigned char *dapal, char noapply)
9816 {
9817 int i, k, j;
9818 float f;
9819 unsigned int newpalettesum, lastbright;
9820
9821 lastbright = curbrightness;
9822 if (!(noapply&4))
9823 curbrightness = min(max((int)dabrightness,0),15);
9824
9825 curgamma = 1.0 + ((float)curbrightness / 10.0);
9826 if (setgamma(curgamma)) j = curbrightness; else j = 0;
9827
9828 for(k=i=0;i<256;i++)
9829 {
9830 // save palette without any brightness adjustment
9831 curpalette[i].r = dapal[i*3+0] << 2;
9832 curpalette[i].g = dapal[i*3+1] << 2;
9833 curpalette[i].b = dapal[i*3+2] << 2;
9834 curpalette[i].f = 0;
9835
9836 // brightness adjust the palette
9837 curpalettefaded[i].b = (tempbuf[k++] = britable[j][ curpalette[i].b ]);
9838 curpalettefaded[i].g = (tempbuf[k++] = britable[j][ curpalette[i].g ]);
9839 curpalettefaded[i].r = (tempbuf[k++] = britable[j][ curpalette[i].r ]);
9840 curpalettefaded[i].f = tempbuf[k++] = 0;
9841 }
9842
9843 if ((noapply&1) == 0) setpalette(0,256,(unsigned char*)tempbuf);
9844
9845 #if USE_POLYMOST && USE_OPENGL
9846 if (rendmode == 3) {
9847 newpalettesum = crc32once((unsigned char *)curpalettefaded, sizeof(curpalettefaded));
9848
9849 // only reset the textures if the preserve flag (bit 1 of noapply) is clear and
9850 // either (a) the new palette is different to the last, or (b) the brightness
9851 // changed and we couldn't set it using hardware gamma
9852 if (!(noapply&2) && (newpalettesum != lastpalettesum))
9853 polymost_texinvalidateall();
9854
9855 lastpalettesum = newpalettesum;
9856 }
9857 #endif
9858
9859 palfadergb.r = palfadergb.g = palfadergb.b = 0;
9860 palfadedelta = 0;
9861 }
9862
9863
9864 //
9865 // setpalettefade
9866 //
setpalettefade(unsigned char r,unsigned char g,unsigned char b,unsigned char offset)9867 void setpalettefade(unsigned char r, unsigned char g, unsigned char b, unsigned char offset)
9868 {
9869 int i,k;
9870 palette_t p;
9871
9872 palfadergb.r = min(63,r) << 2;
9873 palfadergb.g = min(63,g) << 2;
9874 palfadergb.b = min(63,b) << 2;
9875 palfadedelta = min(63,offset) << 2;
9876
9877 k = 0;
9878 for (i=0;i<256;i++) {
9879 if (gammabrightness) p = curpalette[i];
9880 else {
9881 p.b = britable[curbrightness][ curpalette[i].b ];
9882 p.g = britable[curbrightness][ curpalette[i].g ];
9883 p.r = britable[curbrightness][ curpalette[i].r ];
9884 }
9885
9886 tempbuf[k++] =
9887 (curpalettefaded[i].b =
9888 p.b + ( ( ( (int)palfadergb.b - (int)p.b ) * (int)offset ) >> 6 ) ) >> 2;
9889 tempbuf[k++] =
9890 (curpalettefaded[i].g =
9891 p.g + ( ( ( (int)palfadergb.g - (int)p.g ) * (int)offset ) >> 6 ) ) >> 2;
9892 tempbuf[k++] =
9893 (curpalettefaded[i].r =
9894 p.r + ( ( ( (int)palfadergb.r - (int)p.r ) * (int)offset ) >> 6 ) ) >> 2;
9895 tempbuf[k++] = curpalettefaded[i].f = 0;
9896 }
9897
9898 setpalette(0,256,(unsigned char*)tempbuf);
9899 }
9900
9901
9902 //
9903 // clearview
9904 //
clearview(int dacol)9905 void clearview(int dacol)
9906 {
9907 int y, dx;
9908 intptr_t p;
9909
9910 if (qsetmode != 200) return;
9911
9912 #if USE_POLYMOST && USE_OPENGL
9913 if (rendmode == 3) {
9914 palette_t p;
9915 if (gammabrightness) p = curpalette[dacol];
9916 else {
9917 p.r = britable[curbrightness][ curpalette[dacol].r ];
9918 p.g = britable[curbrightness][ curpalette[dacol].g ];
9919 p.b = britable[curbrightness][ curpalette[dacol].b ];
9920 }
9921 glfunc.glClearColor(((float)p.r)/255.0,
9922 ((float)p.g)/255.0,
9923 ((float)p.b)/255.0,
9924 0);
9925 glfunc.glScissor(windowx1,yres-(windowy2+1),windowx2-windowx1+1,windowy2-windowy1+1);
9926 glfunc.glEnable(GL_SCISSOR_TEST);
9927 glfunc.glClear(GL_COLOR_BUFFER_BIT);
9928 glfunc.glDisable(GL_SCISSOR_TEST);
9929 return;
9930 }
9931 #endif
9932
9933 begindrawing(); //{{{
9934 dx = windowx2-windowx1+1;
9935 //dacol += (dacol<<8); dacol += (dacol<<16);
9936 p = frameplace+ylookup[windowy1]+windowx1;
9937 for(y=windowy1;y<=windowy2;y++) {
9938 //clearbufbyte((void*)p,dx,dacol);
9939 Bmemset((void*)p,dacol,dx);
9940 p += ylookup[1];
9941 }
9942 enddrawing(); //}}}
9943
9944 faketimerhandler();
9945 }
9946
9947
9948 //
9949 // clearallviews
9950 //
clearallviews(int dacol)9951 void clearallviews(int dacol)
9952 {
9953 if (qsetmode != 200) return;
9954 //dacol += (dacol<<8); dacol += (dacol<<16);
9955
9956 #if USE_POLYMOST && USE_OPENGL
9957 if (rendmode == 3) {
9958 palette_t p;
9959 if (gammabrightness) p = curpalette[dacol];
9960 else {
9961 p.r = britable[curbrightness][ curpalette[dacol].r ];
9962 p.g = britable[curbrightness][ curpalette[dacol].g ];
9963 p.b = britable[curbrightness][ curpalette[dacol].b ];
9964 }
9965 glfunc.glViewport(0,0,xdim,ydim); glox1 = -1;
9966 glfunc.glClearColor(((float)p.r)/255.0,
9967 ((float)p.g)/255.0,
9968 ((float)p.b)/255.0,
9969 0);
9970 glfunc.glClear(GL_COLOR_BUFFER_BIT);
9971 return;
9972 }
9973 #endif
9974
9975 begindrawing(); //{{{
9976 //clearbufbyte((void*)frameplace,imageSize,0L);
9977 Bmemset((void*)frameplace,dacol,imageSize);
9978 enddrawing(); //}}}
9979 //nextpage();
9980
9981 faketimerhandler();
9982 }
9983
9984
9985 //
9986 // plotpixel
9987 //
plotpixel(int x,int y,unsigned char col)9988 void plotpixel(int x, int y, unsigned char col)
9989 {
9990 #if USE_POLYMOST && USE_OPENGL
9991 if (!polymost_plotpixel(x,y,col)) return;
9992 #endif
9993
9994 begindrawing(); //{{{
9995 drawpixel((void*)(ylookup[y]+x+frameplace),(int)col);
9996 enddrawing(); //}}}
9997 }
9998
9999
10000 //
10001 // getpixel
10002 //
getpixel(int x,int y)10003 unsigned char getpixel(int x, int y)
10004 {
10005 unsigned char r;
10006
10007 #if USE_POLYMOST && USE_OPENGL
10008 if (rendmode == 3 && qsetmode == 200) return 0;
10009 #endif
10010
10011 begindrawing(); //{{{
10012 r = readpixel((void*)(ylookup[y]+x+frameplace));
10013 enddrawing(); //}}}
10014 return(r);
10015 }
10016
10017
10018 //MUST USE RESTOREFORDRAWROOMS AFTER DRAWING
10019
10020 //
10021 // setviewtotile
10022 //
setviewtotile(short tilenume,int xsiz,int ysiz)10023 void setviewtotile(short tilenume, int xsiz, int ysiz)
10024 {
10025 int i, j;
10026
10027 //DRAWROOMS TO TILE BACKUP&SET CODE
10028 tilesizx[tilenume] = xsiz; tilesizy[tilenume] = ysiz;
10029 bakxsiz[setviewcnt] = xsiz; bakysiz[setviewcnt] = ysiz;
10030 bakframeplace[setviewcnt] = frameplace; frameplace = waloff[tilenume];
10031 bakwindowx1[setviewcnt] = windowx1; bakwindowy1[setviewcnt] = windowy1;
10032 bakwindowx2[setviewcnt] = windowx2; bakwindowy2[setviewcnt] = windowy2;
10033 #if USE_POLYMOST
10034 if (setviewcnt == 0) {
10035 bakrendmode = rendmode;
10036 baktile = tilenume;
10037 }
10038 rendmode = 0;//2;
10039 #endif
10040 copybufbyte(&startumost[windowx1],&bakumost[windowx1],(windowx2-windowx1+1)*sizeof(bakumost[0]));
10041 copybufbyte(&startdmost[windowx1],&bakdmost[windowx1],(windowx2-windowx1+1)*sizeof(bakdmost[0]));
10042 setviewcnt++;
10043
10044 offscreenrendering = 1;
10045 setview(0,0,ysiz-1,xsiz-1);
10046 setaspect(65536,65536);
10047 j = 0; for(i=0;i<=xsiz;i++) { ylookup[i] = j, j += ysiz; }
10048 setvlinebpl(ysiz);
10049 }
10050
10051
10052 //
10053 // setviewback
10054 //
10055 extern char modechange;
setviewback(void)10056 void setviewback(void)
10057 {
10058 int i, j, k;
10059
10060 if (setviewcnt <= 0) return;
10061 setviewcnt--;
10062
10063 offscreenrendering = (setviewcnt>0);
10064 #if USE_POLYMOST
10065 if (setviewcnt == 0) {
10066 rendmode = bakrendmode;
10067 #if USE_OPENGL
10068 invalidatetile(baktile,-1,-1);
10069 #endif
10070 }
10071 #endif
10072
10073 setview(bakwindowx1[setviewcnt],bakwindowy1[setviewcnt],
10074 bakwindowx2[setviewcnt],bakwindowy2[setviewcnt]);
10075 copybufbyte(&bakumost[windowx1],&startumost[windowx1],(windowx2-windowx1+1)*sizeof(startumost[0]));
10076 copybufbyte(&bakdmost[windowx1],&startdmost[windowx1],(windowx2-windowx1+1)*sizeof(startdmost[0]));
10077 frameplace = bakframeplace[setviewcnt];
10078 if (setviewcnt == 0)
10079 k = bakxsiz[0];
10080 else
10081 k = max(bakxsiz[setviewcnt-1],bakxsiz[setviewcnt]);
10082 j = 0; for(i=0;i<=k;i++) ylookup[i] = j, j += bytesperline;
10083 setvlinebpl(bytesperline);
10084 modechange=1;
10085 }
10086
10087
10088 //
10089 // squarerotatetile
10090 //
squarerotatetile(short tilenume)10091 void squarerotatetile(short tilenume)
10092 {
10093 int i, j, k, xsiz, ysiz;
10094 unsigned char *ptr1, *ptr2;
10095
10096 xsiz = tilesizx[tilenume]; ysiz = tilesizy[tilenume];
10097
10098 //supports square tiles only for rotation part
10099 if (xsiz == ysiz)
10100 {
10101 k = (xsiz<<1);
10102 for(i=xsiz-1;i>=0;i--)
10103 {
10104 ptr1 = (unsigned char *)(waloff[tilenume]+i*(xsiz+1)); ptr2 = ptr1;
10105 if ((i&1) != 0) { ptr1--; ptr2 -= xsiz; swapchar(ptr1,ptr2); }
10106 for(j=(i>>1)-1;j>=0;j--)
10107 { ptr1 -= 2; ptr2 -= k; swapchar2(ptr1,ptr2,xsiz); }
10108 }
10109 }
10110 }
10111
10112
10113 //
10114 // preparemirror
10115 //
preparemirror(int dax,int day,int daz,short daang,int dahoriz,short dawall,short dasector,int * tposx,int * tposy,short * tang)10116 void preparemirror(int dax, int day, int daz, short daang, int dahoriz, short dawall, short dasector, int *tposx, int *tposy, short *tang)
10117 {
10118 int i, j, x, y, dx, dy;
10119
10120 x = wall[dawall].x; dx = wall[wall[dawall].point2].x-x;
10121 y = wall[dawall].y; dy = wall[wall[dawall].point2].y-y;
10122 j = dx*dx + dy*dy; if (j == 0) return;
10123 i = (((dax-x)*dx + (day-y)*dy)<<1);
10124 *tposx = (x<<1) + scale(dx,i,j) - dax;
10125 *tposy = (y<<1) + scale(dy,i,j) - day;
10126 *tang = (((getangle(dx,dy)<<1)-daang)&2047);
10127
10128 inpreparemirror = 1;
10129 }
10130
10131
10132 //
10133 // completemirror
10134 //
completemirror(void)10135 void completemirror(void)
10136 {
10137 int i, dy;
10138 intptr_t p;
10139
10140 #if USE_POLYMOST
10141 if (rendmode) return;
10142 #endif
10143
10144 //Can't reverse with uninitialized data
10145 if (inpreparemirror) { inpreparemirror = 0; return; }
10146 if (mirrorsx1 > 0) mirrorsx1--;
10147 if (mirrorsx2 < windowx2-windowx1-1) mirrorsx2++;
10148 if (mirrorsx2 < mirrorsx1) return;
10149
10150 begindrawing();
10151 p = frameplace+ylookup[windowy1+mirrorsy1]+windowx1+mirrorsx1;
10152 i = windowx2-windowx1-mirrorsx2-mirrorsx1; mirrorsx2 -= mirrorsx1;
10153 for(dy=mirrorsy2-mirrorsy1-1;dy>=0;dy--)
10154 {
10155 copybufbyte((void*)(p+1),tempbuf,mirrorsx2+1);
10156 tempbuf[mirrorsx2] = tempbuf[mirrorsx2-1];
10157 copybufreverse(&tempbuf[mirrorsx2],(void*)(p+i),mirrorsx2+1);
10158 p += ylookup[1];
10159 faketimerhandler();
10160 }
10161 enddrawing();
10162 }
10163
10164
10165 //
10166 // sectorofwall
10167 //
sectorofwall(short theline)10168 int sectorofwall(short theline)
10169 {
10170 int i, gap;
10171
10172 if ((theline < 0) || (theline >= numwalls)) return(-1);
10173 i = wall[theline].nextwall; if (i >= 0) return(wall[i].nextsector);
10174
10175 gap = (numsectors>>1); i = gap;
10176 while (gap > 1)
10177 {
10178 gap >>= 1;
10179 if (sector[i].wallptr < theline) i += gap; else i -= gap;
10180 }
10181 while (sector[i].wallptr > theline) i--;
10182 while (sector[i].wallptr+sector[i].wallnum <= theline) i++;
10183 return(i);
10184 }
10185
10186
10187 //
10188 // getceilzofslope
10189 //
getceilzofslope(short sectnum,int dax,int day)10190 int getceilzofslope(short sectnum, int dax, int day)
10191 {
10192 int dx, dy, i, j;
10193 walltype *wal;
10194
10195 if (!(sector[sectnum].ceilingstat&2)) return(sector[sectnum].ceilingz);
10196 wal = &wall[sector[sectnum].wallptr];
10197 dx = wall[wal->point2].x-wal->x; dy = wall[wal->point2].y-wal->y;
10198 i = (nsqrtasm(dx*dx+dy*dy)<<5); if (i == 0) return(sector[sectnum].ceilingz);
10199 j = dmulscale3(dx,day-wal->y,-dy,dax-wal->x);
10200 return(sector[sectnum].ceilingz+scale(sector[sectnum].ceilingheinum,j,i));
10201 }
10202
10203
10204 //
10205 // getflorzofslope
10206 //
getflorzofslope(short sectnum,int dax,int day)10207 int getflorzofslope(short sectnum, int dax, int day)
10208 {
10209 int dx, dy, i, j;
10210 walltype *wal;
10211
10212 if (!(sector[sectnum].floorstat&2)) return(sector[sectnum].floorz);
10213 wal = &wall[sector[sectnum].wallptr];
10214 dx = wall[wal->point2].x-wal->x; dy = wall[wal->point2].y-wal->y;
10215 i = (nsqrtasm(dx*dx+dy*dy)<<5); if (i == 0) return(sector[sectnum].floorz);
10216 j = dmulscale3(dx,day-wal->y,-dy,dax-wal->x);
10217 return(sector[sectnum].floorz+scale(sector[sectnum].floorheinum,j,i));
10218 }
10219
10220
10221 //
10222 // getzsofslope
10223 //
getzsofslope(short sectnum,int dax,int day,int * ceilz,int * florz)10224 void getzsofslope(short sectnum, int dax, int day, int *ceilz, int *florz)
10225 {
10226 int dx, dy, i, j;
10227 walltype *wal, *wal2;
10228 sectortype *sec;
10229
10230 sec = §or[sectnum];
10231 *ceilz = sec->ceilingz; *florz = sec->floorz;
10232 if ((sec->ceilingstat|sec->floorstat)&2)
10233 {
10234 wal = &wall[sec->wallptr]; wal2 = &wall[wal->point2];
10235 dx = wal2->x-wal->x; dy = wal2->y-wal->y;
10236 i = (nsqrtasm(dx*dx+dy*dy)<<5); if (i == 0) return;
10237 j = dmulscale3(dx,day-wal->y,-dy,dax-wal->x);
10238 if (sec->ceilingstat&2) *ceilz = (*ceilz)+scale(sec->ceilingheinum,j,i);
10239 if (sec->floorstat&2) *florz = (*florz)+scale(sec->floorheinum,j,i);
10240 }
10241 }
10242
10243
10244 //
10245 // alignceilslope
10246 //
alignceilslope(short dasect,int x,int y,int z)10247 void alignceilslope(short dasect, int x, int y, int z)
10248 {
10249 int i, dax, day;
10250 walltype *wal;
10251
10252 wal = &wall[sector[dasect].wallptr];
10253 dax = wall[wal->point2].x-wal->x;
10254 day = wall[wal->point2].y-wal->y;
10255
10256 i = (y-wal->y)*dax - (x-wal->x)*day; if (i == 0) return;
10257 sector[dasect].ceilingheinum = scale((z-sector[dasect].ceilingz)<<8,
10258 nsqrtasm(dax*dax+day*day),i);
10259
10260 if (sector[dasect].ceilingheinum == 0) sector[dasect].ceilingstat &= ~2;
10261 else sector[dasect].ceilingstat |= 2;
10262 }
10263
10264
10265 //
10266 // alignflorslope
10267 //
alignflorslope(short dasect,int x,int y,int z)10268 void alignflorslope(short dasect, int x, int y, int z)
10269 {
10270 int i, dax, day;
10271 walltype *wal;
10272
10273 wal = &wall[sector[dasect].wallptr];
10274 dax = wall[wal->point2].x-wal->x;
10275 day = wall[wal->point2].y-wal->y;
10276
10277 i = (y-wal->y)*dax - (x-wal->x)*day; if (i == 0) return;
10278 sector[dasect].floorheinum = scale((z-sector[dasect].floorz)<<8,
10279 nsqrtasm(dax*dax+day*day),i);
10280
10281 if (sector[dasect].floorheinum == 0) sector[dasect].floorstat &= ~2;
10282 else sector[dasect].floorstat |= 2;
10283 }
10284
10285
10286 //
10287 // loopnumofsector
10288 //
loopnumofsector(short sectnum,short wallnum)10289 int loopnumofsector(short sectnum, short wallnum)
10290 {
10291 int i, numloops, startwall, endwall;
10292
10293 numloops = 0;
10294 startwall = sector[sectnum].wallptr;
10295 endwall = startwall + sector[sectnum].wallnum;
10296 for(i=startwall;i<endwall;i++)
10297 {
10298 if (i == wallnum) return(numloops);
10299 if (wall[i].point2 < i) numloops++;
10300 }
10301 return(-1);
10302 }
10303
10304
10305 //
10306 // setfirstwall
10307 //
setfirstwall(short sectnum,short newfirstwall)10308 void setfirstwall(short sectnum, short newfirstwall)
10309 {
10310 int i, j, k, numwallsofloop;
10311 int startwall, endwall, danumwalls, dagoalloop;
10312
10313 startwall = sector[sectnum].wallptr;
10314 danumwalls = sector[sectnum].wallnum;
10315 endwall = startwall+danumwalls;
10316 if ((newfirstwall < startwall) || (newfirstwall >= startwall+danumwalls)) return;
10317 for(i=0;i<danumwalls;i++)
10318 Bmemcpy(&wall[i+numwalls],&wall[i+startwall],sizeof(walltype));
10319
10320 numwallsofloop = 0;
10321 i = newfirstwall;
10322 do
10323 {
10324 numwallsofloop++;
10325 i = wall[i].point2;
10326 } while (i != newfirstwall);
10327
10328 //Put correct loop at beginning
10329 dagoalloop = loopnumofsector(sectnum,newfirstwall);
10330 if (dagoalloop > 0)
10331 {
10332 j = 0;
10333 while (loopnumofsector(sectnum,j+startwall) != dagoalloop) j++;
10334 for(i=0;i<danumwalls;i++)
10335 {
10336 k = i+j; if (k >= danumwalls) k -= danumwalls;
10337 Bmemcpy(&wall[startwall+i],&wall[numwalls+k],sizeof(walltype));
10338
10339 wall[startwall+i].point2 += danumwalls-startwall-j;
10340 if (wall[startwall+i].point2 >= danumwalls)
10341 wall[startwall+i].point2 -= danumwalls;
10342 wall[startwall+i].point2 += startwall;
10343 }
10344 newfirstwall += danumwalls-j;
10345 if (newfirstwall >= startwall+danumwalls) newfirstwall -= danumwalls;
10346 }
10347
10348 for(i=0;i<numwallsofloop;i++)
10349 Bmemcpy(&wall[i+numwalls],&wall[i+startwall],sizeof(walltype));
10350 for(i=0;i<numwallsofloop;i++)
10351 {
10352 k = i+newfirstwall-startwall;
10353 if (k >= numwallsofloop) k -= numwallsofloop;
10354 Bmemcpy(&wall[startwall+i],&wall[numwalls+k],sizeof(walltype));
10355
10356 wall[startwall+i].point2 += numwallsofloop-newfirstwall;
10357 if (wall[startwall+i].point2 >= numwallsofloop)
10358 wall[startwall+i].point2 -= numwallsofloop;
10359 wall[startwall+i].point2 += startwall;
10360 }
10361
10362 for(i=startwall;i<endwall;i++)
10363 if (wall[i].nextwall >= 0) wall[wall[i].nextwall].nextwall = i;
10364 }
10365
10366
10367 //
10368 // drawline256
10369 //
drawline256(int x1,int y1,int x2,int y2,unsigned char col)10370 void drawline256(int x1, int y1, int x2, int y2, unsigned char col)
10371 {
10372 int dx, dy, i, j, inc, daend;
10373 intptr_t p, plc;
10374
10375 col = palookup[0][col];
10376
10377 dx = x2-x1; dy = y2-y1;
10378 if (dx >= 0)
10379 {
10380 if ((x1 >= wx2) || (x2 < wx1)) return;
10381 if (x1 < wx1) y1 += scale(wx1-x1,dy,dx), x1 = wx1;
10382 if (x2 > wx2) y2 += scale(wx2-x2,dy,dx), x2 = wx2;
10383 }
10384 else
10385 {
10386 if ((x2 >= wx2) || (x1 < wx1)) return;
10387 if (x2 < wx1) y2 += scale(wx1-x2,dy,dx), x2 = wx1;
10388 if (x1 > wx2) y1 += scale(wx2-x1,dy,dx), x1 = wx2;
10389 }
10390 if (dy >= 0)
10391 {
10392 if ((y1 >= wy2) || (y2 < wy1)) return;
10393 if (y1 < wy1) x1 += scale(wy1-y1,dx,dy), y1 = wy1;
10394 if (y2 > wy2) x2 += scale(wy2-y2,dx,dy), y2 = wy2;
10395 }
10396 else
10397 {
10398 if ((y2 >= wy2) || (y1 < wy1)) return;
10399 if (y2 < wy1) x2 += scale(wy1-y2,dx,dy), y2 = wy1;
10400 if (y1 > wy2) x1 += scale(wy2-y1,dx,dy), y1 = wy2;
10401 }
10402
10403 #if USE_POLYMOST && USE_OPENGL
10404 if (!polymost_drawline256(x1,y1,x2,y2,col)) return;
10405 #endif
10406
10407 if (klabs(dx) >= klabs(dy))
10408 {
10409 if (dx == 0) return;
10410 if (dx < 0)
10411 {
10412 i = x1; x1 = x2; x2 = i;
10413 i = y1; y1 = y2; y2 = i;
10414 x1+=4096; x2+=4096;
10415 }
10416
10417 inc = divscale12(dy,dx);
10418 plc = y1+mulscale12((2047-x1)&4095,inc);
10419 i = ((x1+2048)>>12); daend = ((x2+2048)>>12);
10420
10421 begindrawing(); //{{{
10422 for(;i<daend;i++)
10423 {
10424 j = (plc>>12);
10425 if ((j >= startumost[i]) && (j < startdmost[i]))
10426 drawpixel((void*)(frameplace+ylookup[j]+i),col);
10427 plc += inc;
10428 }
10429 enddrawing(); //}}}
10430 }
10431 else
10432 {
10433 if (dy < 0)
10434 {
10435 i = x1; x1 = x2; x2 = i;
10436 i = y1; y1 = y2; y2 = i;
10437 y1+=4096; y2+=4096;
10438 }
10439
10440 inc = divscale12(dx,dy);
10441 plc = x1+mulscale12((2047-y1)&4095,inc);
10442 i = ((y1+2048)>>12); daend = ((y2+2048)>>12);
10443
10444 begindrawing(); //{{{
10445 p = ylookup[i]+frameplace;
10446 for(;i<daend;i++)
10447 {
10448 j = (plc>>12);
10449 if ((i >= startumost[j]) && (i < startdmost[j]))
10450 drawpixel((void*)(j+p),col);
10451 plc += inc; p += ylookup[1];
10452 }
10453 enddrawing(); //}}}
10454 }
10455 }
10456
10457
10458 //
10459 // drawline16
10460 //
10461 // JBF: Had to add extra tests to make sure x-coordinates weren't winding up -'ve
10462 // after clipping or crashes would ensue
10463 unsigned int drawlinepat = 0xffffffff;
10464
drawline16(int x1,int y1,int x2,int y2,unsigned char col)10465 void drawline16(int x1, int y1, int x2, int y2, unsigned char col)
10466 {
10467 int i, dx, dy, pinc, d;
10468 intptr_t p;
10469 unsigned int patc=0;
10470
10471 dx = x2-x1; dy = y2-y1;
10472 if (dx >= 0)
10473 {
10474 if ((x1 >= xres) || (x2 < 0)) return;
10475 if (x1 < 0) { if (dy) y1 += scale(0-x1,dy,dx); x1 = 0; }
10476 if (x2 >= xres) { if (dy) y2 += scale(xres-1-x2,dy,dx); x2 = xres-1; }
10477 }
10478 else
10479 {
10480 if ((x2 >= xres) || (x1 < 0)) return;
10481 if (x2 < 0) { if (dy) y2 += scale(0-x2,dy,dx); x2 = 0; }
10482 if (x1 >= xres) { if (dy) y1 += scale(xres-1-x1,dy,dx); x1 = xres-1; }
10483 }
10484 if (dy >= 0)
10485 {
10486 if ((y1 >= ydim16) || (y2 < 0)) return;
10487 if (y1 < 0) { if (dx) x1 += scale(0-y1,dx,dy); y1 = 0; if (x1 < 0) x1 = 0; }
10488 if (y2 >= ydim16) { if (dx) x2 += scale(ydim16-1-y2,dx,dy); y2 = ydim16-1; if (x2 < 0) x2 = 0; }
10489 }
10490 else
10491 {
10492 if ((y2 >= ydim16) || (y1 < 0)) return;
10493 if (y2 < 0) { if (dx) x2 += scale(0-y2,dx,dy); y2 = 0; if (x2 < 0) x2 = 0; }
10494 if (y1 >= ydim16) { if (dx) x1 += scale(ydim16-1-y1,dx,dy); y1 = ydim16-1; if (x1 < 0) x1 = 0; }
10495 }
10496
10497 dx = klabs(x2-x1)+1; dy = klabs(y2-y1)+1;
10498 if (dx >= dy)
10499 {
10500 if (x2 < x1)
10501 {
10502 i = x1; x1 = x2; x2 = i;
10503 i = y1; y1 = y2; y2 = i;
10504 }
10505 d = 0;
10506 if (y2 > y1) pinc = bytesperline; else pinc = -bytesperline;
10507
10508 begindrawing(); //{{{
10509 p = (y1*bytesperline)+x1+frameplace;
10510 if (dy == 0 && drawlinepat == 0xffffffff) {
10511 i = ((int)col<<24)|((int)col<<16)|((int)col<<8)|col;
10512 clearbufbyte((void *)p, dx, i);
10513 } else
10514 for(i=dx;i>0;i--)
10515 {
10516 if (drawlinepat & pow2long[(patc++)&31])
10517 drawpixel((void *)p, col);
10518 d += dy;
10519 if (d >= dx) { d -= dx; p += pinc; }
10520 p++;
10521 }
10522 enddrawing(); //}}}
10523 return;
10524 }
10525
10526 if (y2 < y1)
10527 {
10528 i = x1; x1 = x2; x2 = i;
10529 i = y1; y1 = y2; y2 = i;
10530 }
10531 d = 0;
10532 if (x2 > x1) pinc = 1; else pinc = -1;
10533
10534 begindrawing(); //{{{
10535 p = (y1*bytesperline)+x1+frameplace;
10536 for(i=dy;i>0;i--)
10537 {
10538 if (drawlinepat & pow2long[(patc++)&31])
10539 drawpixel((void *)p, col);
10540 d += dx;
10541 if (d >= dy) { d -= dy; p += pinc; }
10542 p += bytesperline;
10543 }
10544 enddrawing(); //}}}
10545 }
10546
drawcircle16(int x1,int y1,int r,unsigned char col)10547 void drawcircle16(int x1, int y1, int r, unsigned char col)
10548 {
10549 #if 1
10550 int xp, yp, xpbpl, ypbpl, d, de, dse, patc=0;
10551 intptr_t p;
10552
10553 if (r < 0) r = -r;
10554 if (x1+r < 0 || x1-r >= xres) return;
10555 if (y1+r < 0 || y1-r >= ydim16) return;
10556
10557 /*
10558 * d
10559 * 6 | 7
10560 * \ | /
10561 * 5 \|/ 8
10562 * c----+----a
10563 * 4 /|\ 1
10564 * / | \
10565 * 3 | 2
10566 * b
10567 */
10568
10569 xp = 0;
10570 yp = r;
10571 d = 1 - r;
10572 de = 2;
10573 dse = 5 - (r << 1);
10574
10575 begindrawing();
10576 p = (y1*bytesperline)+x1+frameplace;
10577
10578 if (drawlinepat & pow2long[(patc++)&31]) {
10579 if ((unsigned int)y1 < (unsigned int)ydim16 && (unsigned int)(x1+r) < (unsigned int)xres )
10580 drawpixel((void *)(p+r), col); // a
10581 if ((unsigned int)x1 < (unsigned int)xres && (unsigned int)(y1+r) < (unsigned int)ydim16)
10582 drawpixel((void *)(p+(r*bytesperline)), col); // b
10583 if ((unsigned int)y1 < (unsigned int)ydim16 && (unsigned int)(x1-r) < (unsigned int)xres )
10584 drawpixel((void *)(p-r), col); // c
10585 if ((unsigned int)x1 < (unsigned int)xres && (unsigned int)(y1-r) < (unsigned int)ydim16)
10586 drawpixel((void *)(p-(r*bytesperline)), col); // d
10587 }
10588
10589 while (yp > xp) {
10590 if (d < 0) {
10591 d += de;
10592 de += 2;
10593 dse += 2;
10594 xp++;
10595 } else {
10596 d += dse;
10597 de += 2;
10598 dse += 4;
10599 xp++;
10600 yp--;
10601 }
10602
10603 ypbpl = yp*bytesperline;
10604 xpbpl = xp*bytesperline;
10605 if (drawlinepat & pow2long[(patc++)&31]) {
10606 if ((unsigned int)(x1+yp) < (unsigned int)xres && (unsigned int)(y1+xp) < (unsigned int)ydim16)
10607 drawpixel((void *)(p+yp+xpbpl), col); // 1
10608 if ((unsigned int)(x1+xp) < (unsigned int)xres && (unsigned int)(y1+yp) < (unsigned int)ydim16)
10609 drawpixel((void *)(p+xp+ypbpl), col); // 2
10610 if ((unsigned int)(x1-xp) < (unsigned int)xres && (unsigned int)(y1+yp) < (unsigned int)ydim16)
10611 drawpixel((void *)(p-xp+ypbpl), col); // 3
10612 if ((unsigned int)(x1-yp) < (unsigned int)xres && (unsigned int)(y1+xp) < (unsigned int)ydim16)
10613 drawpixel((void *)(p-yp+xpbpl), col); // 4
10614 if ((unsigned int)(x1-yp) < (unsigned int)xres && (unsigned int)(y1-xp) < (unsigned int)ydim16)
10615 drawpixel((void *)(p-yp-xpbpl), col); // 5
10616 if ((unsigned int)(x1-xp) < (unsigned int)xres && (unsigned int)(y1-yp) < (unsigned int)ydim16)
10617 drawpixel((void *)(p-xp-ypbpl), col); // 6
10618 if ((unsigned int)(x1+xp) < (unsigned int)xres && (unsigned int)(y1-yp) < (unsigned int)ydim16)
10619 drawpixel((void *)(p+xp-ypbpl), col); // 7
10620 if ((unsigned int)(x1+yp) < (unsigned int)xres && (unsigned int)(y1-xp) < (unsigned int)ydim16)
10621 drawpixel((void *)(p+yp-xpbpl), col); // 8
10622 }
10623 }
10624 enddrawing();
10625 #else
10626 // JonoF's rough approximation of a circle
10627 int l,spx,spy,lpx,lpy,px,py;
10628
10629 spx = lpx = x1+mulscale14(r,sintable[0]);
10630 spy = lpy = y1+mulscale14(r,sintable[512]);
10631
10632 for (l=64;l<2048;l+=64) {
10633 px = x1+mulscale14(r,sintable[l]);
10634 py = y1+mulscale14(r,sintable[(l+512)&2047]);
10635
10636 drawline16(lpx,lpy,px,py,col);
10637
10638 lpx = px;
10639 lpy = py;
10640 }
10641
10642 drawline16(lpx,lpy,spx,spy,col);
10643 #endif
10644 }
10645
10646
10647 //
10648 // qsetmode640350
10649 //
qsetmode640350(void)10650 void qsetmode640350(void)
10651 {
10652 if (qsetmode != 350)
10653 {
10654 if (setvideomode(640, 350, 8, fullscreen) < 0) {
10655 //fprintf(stderr, "Couldn't set 640x350 video mode for some reason.\n");
10656 return;
10657 }
10658
10659 xdim = xres;
10660 ydim = yres;
10661 pixelaspect = 65536;
10662
10663 setvgapalette();
10664
10665 ydim16 = 350;
10666 halfxdim16 = 320;
10667 midydim16 = 146;
10668
10669 begindrawing(); //{{{
10670 clearbuf((void *)frameplace, (bytesperline*350L) >> 2, 0);
10671 enddrawing(); //}}}
10672 }
10673
10674 qsetmode = 350;
10675 }
10676
10677
10678 //
10679 // qsetmode640480
10680 //
qsetmode640480(void)10681 void qsetmode640480(void)
10682 {
10683 if (qsetmode != 480)
10684 {
10685 if (setvideomode(640, 480, 8, fullscreen) < 0) {
10686 //fprintf(stderr, "Couldn't set 640x480 video mode for some reason.\n");
10687 return;
10688 }
10689
10690 xdim = xres;
10691 ydim = yres;
10692 pixelaspect = 65536;
10693
10694 setvgapalette();
10695
10696 ydim16 = 336;
10697 halfxdim16 = 320;
10698 midydim16 = 200;
10699
10700 begindrawing(); //{{{
10701 clearbuf((void *)(frameplace + (336l*bytesperline)), (bytesperline*144L) >> 2, 0x08080808l);
10702 clearbuf((void *)frameplace, (bytesperline*336L) >> 2, 0L);
10703 enddrawing(); //}}}
10704 }
10705
10706 qsetmode = 480;
10707 }
10708
10709
10710 //
10711 // qsetmodeany
10712 //
qsetmodeany(int daxdim,int daydim)10713 void qsetmodeany(int daxdim, int daydim)
10714 {
10715 if (daxdim < 640) daxdim = 640;
10716 if (daydim < 480) daydim = 480;
10717
10718 if (qsetmode != ((daxdim<<16)|(daydim&0xffff))) {
10719 if (setvideomode(daxdim, daydim, 8, fullscreen) < 0)
10720 return;
10721
10722 xdim = xres;
10723 ydim = yres;
10724 pixelaspect = 65536;
10725
10726 setvgapalette();
10727
10728 ydim16 = yres - STATUS2DSIZ;
10729 halfxdim16 = xres >> 1;
10730 midydim16 = scale(200,yres,480);
10731
10732 begindrawing(); //{{{
10733 clearbuf((void *)(frameplace + (ydim16*bytesperline)), (bytesperline*STATUS2DSIZ) >> 2, 0x08080808l);
10734 clearbuf((void *)frameplace, (ydim16*bytesperline) >> 2, 0L);
10735 enddrawing(); //}}}
10736 }
10737
10738 qsetmode = ((daxdim<<16)|(daydim&0xffff));
10739 }
10740
10741
10742 //
10743 // clear2dscreen
10744 //
clear2dscreen(void)10745 void clear2dscreen(void)
10746 {
10747 int clearsz;
10748
10749 begindrawing(); //{{{
10750 if (qsetmode == 350) clearsz = 350;
10751 else {
10752 if (ydim16 <= yres-STATUS2DSIZ) clearsz = yres - STATUS2DSIZ;
10753 else clearsz = yres;
10754 }
10755 clearbuf((void *)frameplace, (bytesperline*clearsz) >> 2, 0);
10756 enddrawing(); //}}}
10757 }
10758
10759
10760 //
10761 // draw2dgrid
10762 //
draw2dgrid(int posxe,int posye,short ange,int zoome,short gride)10763 void draw2dgrid(int posxe, int posye, short ange, int zoome, short gride)
10764 {
10765 int i, xp1, yp1, xp2=0, yp2, tempy;
10766
10767 if (gride > 0)
10768 {
10769 begindrawing(); //{{{
10770
10771 yp1 = midydim16-mulscale14(posye+editorgridextent,zoome);
10772 if (yp1 < 0) yp1 = 0;
10773 yp2 = midydim16-mulscale14(posye-editorgridextent,zoome);
10774 if (yp2 >= ydim16) yp2 = ydim16-1;
10775
10776 if ((yp1 < ydim16) && (yp2 >= 0) && (yp2 >= yp1))
10777 {
10778 xp1 = halfxdim16-mulscale14(posxe+editorgridextent,zoome);
10779
10780 for(i=-editorgridextent;i<=editorgridextent;i+=(2048>>gride))
10781 {
10782 xp2 = xp1;
10783 xp1 = halfxdim16-mulscale14(posxe-i,zoome);
10784
10785 if (xp1 >= xdim) break;
10786 if (xp1 >= 0)
10787 {
10788 if (xp1 != xp2)
10789 {
10790 drawline16(xp1,yp1,xp1,yp2,8);
10791 }
10792 }
10793 }
10794 if ((i >= editorgridextent) && (xp1 < xdim))
10795 xp2 = xp1;
10796 if ((xp2 >= 0) && (xp2 < xdim))
10797 {
10798 drawline16(xp2,yp1,xp2,yp2,8);
10799 }
10800 }
10801
10802 xp1 = mulscale14(posxe+editorgridextent,zoome);
10803 xp2 = mulscale14(posxe-editorgridextent,zoome);
10804 tempy = 0x80000000l;
10805 for(i=-editorgridextent;i<=editorgridextent;i+=(2048>>gride))
10806 {
10807 yp1 = (((posye-i)*zoome)>>14);
10808 if (yp1 != tempy)
10809 {
10810 if ((yp1 > midydim16-ydim16) && (yp1 <= midydim16))
10811 {
10812 drawline16(halfxdim16-xp1,midydim16-yp1,halfxdim16-xp2,midydim16-yp1,8);
10813 tempy = yp1;
10814 }
10815 }
10816 }
10817
10818 enddrawing(); //}}}
10819 }
10820 }
10821
10822
10823 //
10824 // draw2dscreen
10825 //
draw2dscreen(int posxe,int posye,short ange,int zoome,short gride)10826 void draw2dscreen(int posxe, int posye, short ange, int zoome, short gride)
10827 {
10828 walltype *wal;
10829 int i, j, k, xp1, yp1, xp2, yp2, tempy;
10830 intptr_t templong;
10831 unsigned char col, mask;
10832
10833 if (qsetmode == 200) return;
10834
10835 begindrawing(); //{{{
10836
10837 if (editstatus == 0)
10838 {
10839 faketimerhandler();
10840 clear2dscreen();
10841
10842 faketimerhandler();
10843 draw2dgrid(posxe,posye,ange,zoome,gride);
10844 }
10845
10846 faketimerhandler();
10847 for(i=numwalls-1,wal=&wall[i];i>=0;i--,wal--)
10848 {
10849 if (editstatus == 0)
10850 {
10851 if ((show2dwall[i>>3]&pow2char[i&7]) == 0) continue;
10852 j = wal->nextwall;
10853 if ((j >= 0) && (i > j))
10854 if ((show2dwall[j>>3]&pow2char[j&7]) > 0) continue;
10855 }
10856 else
10857 {
10858 j = wal->nextwall;
10859 if ((j >= 0) && (i > j)) continue;
10860 }
10861
10862 if (j < 0)
10863 {
10864 col = 7;
10865 if (i == linehighlight) if (totalclock & 8) col += (2<<2);
10866 }
10867 else
10868 {
10869 col = 4;
10870 if ((wal->cstat&1) != 0) col = 5;
10871 if ((i == linehighlight) || ((linehighlight >= 0) && (i == wall[linehighlight].nextwall)))
10872 if (totalclock & 8) col += (2<<2);
10873 }
10874
10875 xp1 = mulscale14(wal->x-posxe,zoome);
10876 yp1 = mulscale14(wal->y-posye,zoome);
10877 xp2 = mulscale14(wall[wal->point2].x-posxe,zoome);
10878 yp2 = mulscale14(wall[wal->point2].y-posye,zoome);
10879
10880 if ((wal->cstat&64) > 0)
10881 {
10882 if (klabs(xp2-xp1) >= klabs(yp2-yp1))
10883 {
10884 drawline16(halfxdim16+xp1,midydim16+yp1+1,halfxdim16+xp2,midydim16+yp2+1,col);
10885 drawline16(halfxdim16+xp1,midydim16+yp1-1,halfxdim16+xp2,midydim16+yp2-1,col);
10886 }
10887 else
10888 {
10889 drawline16(halfxdim16+xp1+1,midydim16+yp1,halfxdim16+xp2+1,midydim16+yp2,col);
10890 drawline16(halfxdim16+xp1-1,midydim16+yp1,halfxdim16+xp2-1,midydim16+yp2,col);
10891 }
10892 col += 8;
10893 }
10894 drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp2,midydim16+yp2,col);
10895
10896 if ((zoome >= 256) && (editstatus == 1))
10897 if (((halfxdim16+xp1) >= 2) && ((halfxdim16+xp1) <= xdim-3))
10898 if (((midydim16+yp1) >= 2) && ((midydim16+yp1) <= ydim16-3))
10899 {
10900 col = 2;
10901 if (i == pointhighlight) {
10902 if (totalclock & 8) col += (2<<2); // JBF 20040116: two braces is all this needed. man I'm a fool sometimes.
10903 }
10904 else if ((highlightcnt > 0) && (editstatus == 1))
10905 {
10906 if (show2dwall[i>>3]&pow2char[i&7])
10907 if (totalclock & 8) col += (2<<2);
10908 }
10909
10910 templong = ((midydim16+yp1)*bytesperline)+(halfxdim16+xp1)+frameplace;
10911 drawpixel((void *)(templong-2-(bytesperline<<1)), col);
10912 drawpixel((void *)(templong-1-(bytesperline<<1)), col);
10913 drawpixel((void *)(templong+0-(bytesperline<<1)), col);
10914 drawpixel((void *)(templong+1-(bytesperline<<1)), col);
10915 drawpixel((void *)(templong+2-(bytesperline<<1)), col);
10916
10917 drawpixel((void *)(templong-2+(bytesperline<<1)), col);
10918 drawpixel((void *)(templong-1+(bytesperline<<1)), col);
10919 drawpixel((void *)(templong+0+(bytesperline<<1)), col);
10920 drawpixel((void *)(templong+1+(bytesperline<<1)), col);
10921 drawpixel((void *)(templong+2+(bytesperline<<1)), col);
10922
10923 drawpixel((void *)(templong-2-bytesperline), col);
10924 drawpixel((void *)(templong-2+0), col);
10925 drawpixel((void *)(templong-2+bytesperline), col);
10926
10927 drawpixel((void *)(templong+2-bytesperline), col);
10928 drawpixel((void *)(templong+2+0), col);
10929 drawpixel((void *)(templong+2+bytesperline), col);
10930 }
10931 }
10932 faketimerhandler();
10933
10934 if ((zoome >= 256) || (editstatus == 0))
10935 for(i=0;i<numsectors;i++)
10936 for(j=headspritesect[i];j>=0;j=nextspritesect[j])
10937 if ((editstatus == 1) || (show2dsprite[j>>3]&pow2char[j&7]))
10938 {
10939 col = 3;
10940 if ((sprite[j].cstat&1) > 0) col = 5;
10941 if (editstatus == 1)
10942 {
10943 if (j+16384 == pointhighlight) {
10944 if (totalclock & 8) col += (2<<2);
10945 }
10946 else if ((highlightcnt > 0) && (editstatus == 1))
10947 {
10948 if (show2dsprite[j>>3]&pow2char[j&7])
10949 if (totalclock & 8) col += (2<<2);
10950 }
10951 }
10952
10953 xp1 = mulscale14(sprite[j].x-posxe,zoome);
10954 yp1 = mulscale14(sprite[j].y-posye,zoome);
10955 if (((halfxdim16+xp1) >= 2) && ((halfxdim16+xp1) <= xdim-3))
10956 if (((midydim16+yp1) >= 2) && ((midydim16+yp1) <= ydim16-3))
10957 {
10958 templong = ((midydim16+yp1)*bytesperline)+(halfxdim16+xp1)+frameplace;
10959 drawpixel((void *)(templong-1-(bytesperline<<1)), col);
10960 drawpixel((void *)(templong+0-(bytesperline<<1)), col);
10961 drawpixel((void *)(templong+1-(bytesperline<<1)), col);
10962
10963 drawpixel((void *)(templong-1+(bytesperline<<1)), col);
10964 drawpixel((void *)(templong+0+(bytesperline<<1)), col);
10965 drawpixel((void *)(templong+1+(bytesperline<<1)), col);
10966
10967 drawpixel((void *)(templong-2-bytesperline), col);
10968 drawpixel((void *)(templong-2+0), col);
10969 drawpixel((void *)(templong-2+bytesperline), col);
10970
10971 drawpixel((void *)(templong+2-bytesperline), col);
10972 drawpixel((void *)(templong+2+0), col);
10973 drawpixel((void *)(templong+2+bytesperline), col);
10974
10975 drawpixel((void *)(templong+1+bytesperline), col);
10976 drawpixel((void *)(templong-1+bytesperline), col);
10977 drawpixel((void *)(templong+1-bytesperline), col);
10978 drawpixel((void *)(templong-1-bytesperline), col);
10979
10980 /*
10981 * JBF 20050103: A little something intended for TerminX. It draws a box
10982 * indicating the extents of a floor-aligned sprite in the 2D view of the editor.
10983 *
10984 if ((sprite[j].cstat&32) > 0) {
10985 int fx = mulscale6(tilesizx[sprite[j].picnum], sprite[j].xrepeat);
10986 int fy = mulscale6(tilesizy[sprite[j].picnum], sprite[j].yrepeat);
10987 int co[4][2], ii;
10988 int sinang = sintable[(sprite[j].ang+512+1024)&2047];
10989 int cosang = sintable[(sprite[j].ang+1024)&2047];
10990 int r,s;
10991
10992 fx = mulscale10(fx,zoome) >> 1;
10993 fy = mulscale10(fy,zoome) >> 1;
10994
10995 co[0][0] = -fx;
10996 co[0][1] = -fy;
10997 co[1][0] = fx;
10998 co[1][1] = -fy;
10999 co[2][0] = fx;
11000 co[2][1] = fy;
11001 co[3][0] = -fx;
11002 co[3][1] = fy;
11003
11004 for (ii=0;ii<4;ii++) {
11005 r = mulscale14(cosang,co[ii][0]) - mulscale14(sinang,co[ii][1]);
11006 s = mulscale14(sinang,co[ii][0]) + mulscale14(cosang,co[ii][1]);
11007 co[ii][0] = r;
11008 co[ii][1] = s;
11009 }
11010
11011 drawlinepat = 0xcccccccc;
11012 for (ii=0;ii<4;ii++) {
11013 drawline16(halfxdim16 + xp1 + co[ii][0], midydim16 + yp1 - co[ii][1],
11014 halfxdim16 + xp1 + co[(ii+1)&3][0], midydim16 + yp1 - co[(ii+1)&3][1],
11015 col);
11016 }
11017 drawlinepat = 0xffffffff;
11018 }
11019 */
11020
11021 xp2 = mulscale11(sintable[(sprite[j].ang+2560)&2047],zoome) / 768;
11022 yp2 = mulscale11(sintable[(sprite[j].ang+2048)&2047],zoome) / 768;
11023
11024 if ((sprite[j].cstat&256) > 0)
11025 {
11026 if (((sprite[j].ang+256)&512) == 0)
11027 {
11028 drawline16(halfxdim16+xp1,midydim16+yp1-1,halfxdim16+xp1+xp2,midydim16+yp1+yp2-1,col);
11029 drawline16(halfxdim16+xp1,midydim16+yp1+1,halfxdim16+xp1+xp2,midydim16+yp1+yp2+1,col);
11030 }
11031 else
11032 {
11033 drawline16(halfxdim16+xp1-1,midydim16+yp1,halfxdim16+xp1+xp2-1,midydim16+yp1+yp2,col);
11034 drawline16(halfxdim16+xp1+1,midydim16+yp1,halfxdim16+xp1+xp2+1,midydim16+yp1+yp2,col);
11035 }
11036 col += 8;
11037 }
11038 drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1+xp2,midydim16+yp1+yp2,col);
11039 }
11040 }
11041
11042 faketimerhandler();
11043 xp1 = mulscale11(sintable[(ange+2560)&2047],zoome) / 768; //Draw white arrow
11044 yp1 = mulscale11(sintable[(ange+2048)&2047],zoome) / 768;
11045 drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16-xp1,midydim16-yp1,15);
11046 drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+yp1,midydim16-xp1,15);
11047 drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16-yp1,midydim16+xp1,15);
11048
11049 enddrawing(); //}}}
11050 }
11051
11052
11053 //
11054 // printext16
11055 //
printext16(int xpos,int ypos,short col,short backcol,const char * name,char fontsize)11056 void printext16(int xpos, int ypos, short col, short backcol, const char *name, char fontsize)
11057 {
11058 int stx, i, x, y, charxsiz;
11059 unsigned char *fontptr, *letptr, *ptr;
11060
11061 stx = xpos;
11062
11063 if (fontsize) { fontptr = smalltextfont; charxsiz = 4; }
11064 else { fontptr = textfont; charxsiz = 8; }
11065
11066 begindrawing(); //{{{
11067 for(i=0;name[i];i++)
11068 {
11069 letptr = &fontptr[((int)(unsigned char)name[i])<<3];
11070 ptr = (unsigned char *)(bytesperline*(ypos+7)+(stx-fontsize)+frameplace);
11071 for(y=7;y>=0;y--)
11072 {
11073 for(x=charxsiz-1;x>=0;x--)
11074 {
11075 if (letptr[y]&pow2char[7-fontsize-x])
11076 ptr[x] = (unsigned char)col;
11077 else if (backcol >= 0)
11078 ptr[x] = (unsigned char)backcol;
11079 }
11080 ptr -= bytesperline;
11081 }
11082 stx += charxsiz;
11083 }
11084 enddrawing(); //}}}
11085 }
11086
11087
11088 //
11089 // printext256
11090 //
printext256(int xpos,int ypos,short col,short backcol,const char * name,char fontsize)11091 void printext256(int xpos, int ypos, short col, short backcol, const char *name, char fontsize)
11092 {
11093 int stx, i, x, y, charxsiz;
11094 unsigned char *fontptr, *letptr, *ptr;
11095
11096 stx = xpos;
11097
11098 if (fontsize) { fontptr = smalltextfont; charxsiz = 4; }
11099 else { fontptr = textfont; charxsiz = 8; }
11100
11101 #if USE_POLYMOST && USE_OPENGL
11102 if (!polymost_printext256(xpos,ypos,col,backcol,name,fontsize)) return;
11103 #endif
11104
11105 begindrawing(); //{{{
11106 for(i=0;name[i];i++)
11107 {
11108 letptr = &fontptr[name[i]<<3];
11109 ptr = (unsigned char *)(ylookup[ypos+7]+(stx-fontsize)+frameplace);
11110 for(y=7;y>=0;y--)
11111 {
11112 for(x=charxsiz-1;x>=0;x--)
11113 {
11114 if (letptr[y]&pow2char[7-fontsize-x])
11115 ptr[x] = (unsigned char)col;
11116 else if (backcol >= 0)
11117 ptr[x] = (unsigned char)backcol;
11118 }
11119 ptr -= ylookup[1];
11120 }
11121 stx += charxsiz;
11122 }
11123 enddrawing(); //}}}
11124 }
11125
11126
11127 //
11128 // screencapture
11129 //
screencapture_tga(char * filename,char inverseit)11130 static int screencapture_tga(char *filename, char inverseit)
11131 {
11132 int i,j;
11133 unsigned char *ptr, head[18] = { 0,1,1,0,0,0,1,24,0,0,0,0,0/*wlo*/,0/*whi*/,0/*hlo*/,0/*hhi*/,8,0 };
11134 //char palette[4*256];
11135 char *fn = Bstrdup(filename), *inversebuf, c;
11136 BFILE *fil;
11137
11138 do { // JBF 2004022: So we don't overwrite existing screenshots
11139 if (capturecount > 9999) {
11140 Bfree(fn);
11141 return -1;
11142 }
11143
11144 i = Bstrrchr(fn,'.')-fn-4;
11145 fn[i++] = ((capturecount/1000)%10)+48;
11146 fn[i++] = ((capturecount/100)%10)+48;
11147 fn[i++] = ((capturecount/10)%10)+48;
11148 fn[i++] = (capturecount%10)+48;
11149 i++;
11150 fn[i++] = 't';
11151 fn[i++] = 'g';
11152 fn[i++] = 'a';
11153
11154 if ((fil = Bfopen(fn,"rb")) == NULL) break;
11155 Bfclose(fil);
11156 capturecount++;
11157 } while (1);
11158 fil = Bfopen(fn,"wb");
11159 if (fil == NULL) {
11160 Bfree(fn);
11161 return -1;
11162 }
11163
11164 #if USE_POLYMOST && USE_OPENGL
11165 if (rendmode >= 3 && qsetmode == 200) {
11166 head[1] = 0; // no colourmap
11167 head[2] = 2; // uncompressed truecolour
11168 head[3] = 0; // (low) first colourmap index
11169 head[4] = 0; // (high) first colourmap index
11170 head[5] = 0; // (low) number colourmap entries
11171 head[6] = 0; // (high) number colourmap entries
11172 head[7] = 0; // colourmap entry size
11173 head[16] = 24; // 24 bits per pixel
11174 }
11175 #endif
11176
11177 head[12] = xdim & 0xff;
11178 head[13] = (xdim >> 8) & 0xff;
11179 head[14] = ydim & 0xff;
11180 head[15] = (ydim >> 8) & 0xff;
11181
11182 Bfwrite(head, 18, 1, fil);
11183
11184 begindrawing(); //{{{
11185 ptr = (unsigned char *)frameplace;
11186
11187 // palette first
11188 #if USE_POLYMOST && USE_OPENGL
11189 if (rendmode < 3 || (rendmode == 3 && qsetmode != 200)) {
11190 #endif
11191 //getpalette(0,256,palette);
11192 for (i=0; i<256; i++) {
11193 Bfputc(curpalettefaded[i].b, fil); // b
11194 Bfputc(curpalettefaded[i].g, fil); // g
11195 Bfputc(curpalettefaded[i].r, fil); // r
11196 }
11197 #if USE_POLYMOST && USE_OPENGL
11198 }
11199 #endif
11200
11201 // targa renders bottom to top, from left to right
11202 if (inverseit && qsetmode != 200) {
11203 inversebuf = kmalloc(bytesperline);
11204 if (inversebuf) {
11205 for (i=ydim-1; i>=0; i--) {
11206 copybuf(ptr+i*bytesperline, inversebuf, xdim >> 2);
11207 for (j=0; j < (bytesperline>>2); j++) ((int *)inversebuf)[j] ^= 0x0f0f0f0fL;
11208 Bfwrite(inversebuf, xdim, 1, fil);
11209 }
11210 kfree(inversebuf);
11211 }
11212 } else {
11213 #if USE_POLYMOST && USE_OPENGL
11214 if (rendmode >= 3 && qsetmode == 200) {
11215 // 24bit
11216 inversebuf = kmalloc(xdim*ydim*3);
11217 if (inversebuf) {
11218 glfunc.glReadPixels(0,0,xdim,ydim,GL_RGB,GL_UNSIGNED_BYTE,inversebuf);
11219 j = xdim*ydim*3;
11220 for (i=0; i<j; i+=3) {
11221 c = inversebuf[i];
11222 inversebuf[i] = inversebuf[i+2];
11223 inversebuf[i+2] = c;
11224 }
11225 Bfwrite(inversebuf, xdim*ydim, 3, fil);
11226 kfree(inversebuf);
11227 }
11228 } else {
11229 #endif
11230 for (i=ydim-1; i>=0; i--)
11231 Bfwrite(ptr+i*bytesperline, xdim, 1, fil);
11232 #if USE_POLYMOST && USE_OPENGL
11233 }
11234 #endif
11235 }
11236
11237 enddrawing(); //}}}
11238
11239 Bfclose(fil);
11240 buildprintf("Saved screenshot to %s\n", fn);
11241 Bfree(fn);
11242 capturecount++;
11243 return(0);
11244 }
11245
11246 // PCX is nasty, which is why I've lifted these functions from the PCX spec by ZSoft
writepcxbyte(unsigned char colour,unsigned char count,BFILE * fp)11247 static int writepcxbyte(unsigned char colour, unsigned char count, BFILE *fp)
11248 {
11249 if (!count) return 0;
11250 if (count == 1 && (colour & 0xc0) != 0xc0) {
11251 Bfputc(colour, fp);
11252 return 1;
11253 } else {
11254 Bfputc(0xc0 | count, fp);
11255 Bfputc(colour, fp);
11256 return 2;
11257 }
11258 }
11259
writepcxline(unsigned char * buf,int bytes,int step,BFILE * fp)11260 static void writepcxline(unsigned char *buf, int bytes, int step, BFILE *fp)
11261 {
11262 unsigned char ths, last;
11263 int srcIndex, i;
11264 unsigned char runCount;
11265
11266 runCount = 1;
11267 last = *buf;
11268
11269 for (srcIndex=1; srcIndex<bytes; srcIndex++) {
11270 buf += step;
11271 ths = *buf;
11272 if (ths == last) {
11273 runCount++;
11274 if (runCount == 63) {
11275 writepcxbyte(last, runCount, fp);
11276 runCount = 0;
11277 }
11278 } else {
11279 if (runCount)
11280 writepcxbyte(last, runCount, fp);
11281
11282 last = ths;
11283 runCount = 1;
11284 }
11285 }
11286
11287 if (runCount) writepcxbyte(last, runCount, fp);
11288 if (bytes&1) writepcxbyte(0, 1, fp);
11289 }
11290
screencapture_pcx(char * filename,char inverseit)11291 static int screencapture_pcx(char *filename, char inverseit)
11292 {
11293 int i,j,bpl;
11294 unsigned char *ptr, head[128], *inversebuf;
11295 char *fn = Bstrdup(filename);
11296 BFILE *fil;
11297
11298 do { // JBF 2004022: So we don't overwrite existing screenshots
11299 if (capturecount > 9999) {
11300 Bfree(fn);
11301 return -1;
11302 }
11303
11304 i = Bstrrchr(fn,'.')-fn-4;
11305 fn[i++] = ((capturecount/1000)%10)+48;
11306 fn[i++] = ((capturecount/100)%10)+48;
11307 fn[i++] = ((capturecount/10)%10)+48;
11308 fn[i++] = (capturecount%10)+48;
11309 i++;
11310 fn[i++] = 'p';
11311 fn[i++] = 'c';
11312 fn[i++] = 'x';
11313
11314 if ((fil = Bfopen(fn,"rb")) == NULL) break;
11315 Bfclose(fil);
11316 capturecount++;
11317 } while (1);
11318 fil = Bfopen(fn,"wb");
11319 if (fil == NULL) {
11320 Bfree(fn);
11321 return -1;
11322 }
11323
11324 memset(head,0,128);
11325 head[0] = 10;
11326 head[1] = 5;
11327 head[2] = 1;
11328 head[3] = 8;
11329 head[12] = 72; head[13] = 0;
11330 head[14] = 72; head[15] = 0;
11331 head[65] = 1; // 8-bit
11332 head[68] = 1;
11333
11334 #if USE_POLYMOST && USE_OPENGL
11335 if (rendmode >= 3 && qsetmode == 200) {
11336 head[65] = 3; // 24-bit
11337 }
11338 #endif
11339
11340 head[8] = (xdim-1) & 0xff;
11341 head[9] = ((xdim-1) >> 8) & 0xff;
11342 head[10] = (ydim-1) & 0xff;
11343 head[11] = ((ydim-1) >> 8) & 0xff;
11344
11345 bpl = xdim + (xdim&1);
11346
11347 head[66] = bpl & 0xff;
11348 head[67] = (bpl >> 8) & 0xff;
11349
11350 Bfwrite(head, 128, 1, fil);
11351
11352 begindrawing(); //{{{
11353 ptr = (unsigned char *)frameplace;
11354
11355 // targa renders bottom to top, from left to right
11356 if (inverseit && qsetmode != 200) {
11357 inversebuf = kmalloc(bytesperline);
11358 if (inversebuf) {
11359 for (i=0; i<ydim; i++) {
11360 copybuf(ptr+i*bytesperline, inversebuf, xdim >> 2);
11361 for (j=0; j < (bytesperline>>2); j++) ((int *)inversebuf)[j] ^= 0x0f0f0f0fL;
11362 writepcxline(inversebuf, xdim, 1, fil);
11363 }
11364 kfree(inversebuf);
11365 }
11366 } else {
11367 #if USE_POLYMOST && USE_OPENGL
11368 if (rendmode >= 3 && qsetmode == 200) {
11369 // 24bit
11370 inversebuf = kmalloc(xdim*ydim*3);
11371 if (inversebuf) {
11372 glfunc.glReadPixels(0,0,xdim,ydim,GL_RGB,GL_UNSIGNED_BYTE,inversebuf);
11373 for (i=ydim-1; i>=0; i--) {
11374 writepcxline(inversebuf+i*xdim*3, xdim, 3, fil);
11375 writepcxline(inversebuf+i*xdim*3+1, xdim, 3, fil);
11376 writepcxline(inversebuf+i*xdim*3+2, xdim, 3, fil);
11377 }
11378 kfree(inversebuf);
11379 }
11380 } else {
11381 #endif
11382 for (i=0; i<ydim; i++)
11383 writepcxline(ptr+i*bytesperline, xdim, 1, fil);
11384 #if USE_POLYMOST && USE_OPENGL
11385 }
11386 #endif
11387 }
11388
11389 enddrawing(); //}}}
11390
11391 // palette last
11392 #if USE_POLYMOST && USE_OPENGL
11393 if (rendmode < 3 || (rendmode == 3 && qsetmode != 200)) {
11394 #endif
11395 //getpalette(0,256,palette);
11396 Bfputc(12,fil);
11397 for (i=0; i<256; i++) {
11398 Bfputc(curpalettefaded[i].r, fil); // b
11399 Bfputc(curpalettefaded[i].g, fil); // g
11400 Bfputc(curpalettefaded[i].b, fil); // r
11401 }
11402 #if USE_POLYMOST && USE_OPENGL
11403 }
11404 #endif
11405
11406 Bfclose(fil);
11407 buildprintf("Saved screenshot to %s\n", fn);
11408 Bfree(fn);
11409 capturecount++;
11410 return(0);
11411 }
11412
screencapture(char * filename,char mode)11413 int screencapture(char *filename, char mode)
11414 {
11415 if (qsetmode == 200 && (mode & 2)) {
11416 captureatnextpage = mode;
11417 strcpy(capturename, filename);
11418 return 0;
11419 }
11420 if (captureformat == 0) return screencapture_tga(filename,mode&1);
11421 else return screencapture_pcx(filename,mode&1);
11422 }
11423
11424
11425 #if USE_POLYMOST
11426
11427 //
11428 // setrendermode
11429 //
setrendermode(int renderer)11430 int setrendermode(int renderer)
11431 {
11432 int method;
11433
11434 if (bpp == 8) {
11435 if (renderer < 0) renderer = 0;
11436 else if (renderer > 2) renderer = 2;
11437 } else {
11438 renderer = 3;
11439 }
11440
11441 rendmode = renderer;
11442
11443 return 0;
11444 }
11445
11446 //
11447 // getrendermode
11448 //
getrendermode(void)11449 int getrendermode(void)
11450 {
11451 return rendmode;
11452 }
11453
11454
11455 //
11456 // setrollangle
11457 //
setrollangle(int rolla)11458 void setrollangle(int rolla)
11459 {
11460 if (rolla == 0) gtang = 0.0;
11461 else gtang = PI * (double)rolla / 1024.0;
11462 }
11463
11464 #endif //USE_POLYMOST
11465
11466 #if USE_POLYMOST && USE_OPENGL
11467
11468 //
11469 // invalidatetile
11470 // pal: pass -1 to invalidate all palettes for the tile, or >=0 for a particular palette
11471 // how: pass -1 to invalidate all instances of the tile in texture memory, or a bitfield
11472 // bit 0: opaque or masked (non-translucent) texture, using repeating
11473 // bit 1: ignored
11474 // bit 2: ignored (33% translucence, using repeating)
11475 // bit 3: ignored (67% translucence, using repeating)
11476 // bit 4: opaque or masked (non-translucent) texture, using clamping
11477 // bit 5: ignored
11478 // bit 6: ignored (33% translucence, using clamping)
11479 // bit 7: ignored (67% translucence, using clamping)
11480 // clamping is for sprites, repeating is for walls
11481 //
invalidatetile(short tilenume,int pal,int how)11482 void invalidatetile(short tilenume, int pal, int how)
11483 {
11484 int numpal, firstpal, np;
11485 int hp;
11486
11487 if (rendmode < 3) return;
11488
11489 if (pal < 0) {
11490 numpal = MAXPALOOKUPS;
11491 firstpal = 0;
11492 } else {
11493 numpal = 1;
11494 firstpal = pal % MAXPALOOKUPS;
11495 }
11496
11497 for (hp = 0; hp < 8; hp+=4) {
11498 if (!(how & pow2long[hp])) continue;
11499
11500 for (np = firstpal; np < firstpal+numpal; np++) {
11501 polymost_texinvalidate(tilenume, np, hp);
11502 }
11503 }
11504 }
11505
11506
11507 //
11508 // setpolymost2dview
11509 // Sets OpenGL for 2D drawing
11510 //
setpolymost2dview(void)11511 void setpolymost2dview(void)
11512 {
11513 if (rendmode < 3) return;
11514
11515 if (gloy1 != -1) {
11516 glfunc.glViewport(0,0,xres,yres);
11517 }
11518
11519 gloy1 = -1;
11520
11521 glfunc.glDisable(GL_DEPTH_TEST);
11522 glfunc.glDisable(GL_BLEND);
11523 }
11524
11525 #endif //USE_POLYMOST && USE_OPENGL
11526
11527
buildprintf(const char * fmt,...)11528 void buildprintf(const char *fmt, ...)
11529 {
11530 char tmpstr[1024];
11531 va_list va, vac;
11532
11533 va_start(va, fmt);
11534
11535 va_copy(vac, va);
11536 vfprintf(stdout, fmt, vac);
11537 va_end(vac);
11538
11539 if (logfile) {
11540 va_copy(vac, va);
11541 vfprintf(logfile, fmt, vac);
11542 va_end(vac);
11543 }
11544
11545 va_copy(vac, va);
11546 Bvsnprintf(tmpstr, sizeof(tmpstr)-1, fmt, vac);
11547 tmpstr[sizeof(tmpstr)-1] = 0;
11548 va_end(vac);
11549
11550 initputs(tmpstr);
11551 OSD_Puts(tmpstr);
11552
11553 va_end(va);
11554 }
11555
buildputs(const char * str)11556 void buildputs(const char *str)
11557 {
11558 fputs(str, stdout);
11559 if (logfile) fputs(str, logfile);
11560 initputs(str); // the startup window
11561 OSD_Puts(str); // the onscreen-display
11562 }
11563
buildsetlogfile(const char * fn)11564 void buildsetlogfile(const char *fn)
11565 {
11566 if (logfile) Bfclose(logfile);
11567 logfile = NULL;
11568 if (fn) logfile = Bfopen(fn,"w");
11569 if (logfile) setvbuf(logfile, (char*)NULL, _IONBF, 0);
11570 }
11571
11572
11573 /*
11574 * vim:ts=8:
11575 */
11576
11577