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 = &sector[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 = &sector[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 = &sector[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 = &sector[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 = &sector[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 = &sector[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 = &sector[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 = &sector[sectnum];
3890 	nsec = &sector[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)&sector[1] - (intptr_t)&sector[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=&sector[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(&sector, 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,&sector[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, &sect->wallptr, 2) != 2) return -1;
6384 	if (kread(fil, &sect->wallnum, 2) != 2) return -1;
6385 	if (kread(fil, &sect->ceilingpicnum, 2) != 2) return -1;
6386 	if (kread(fil, &sect->floorpicnum, 2) != 2) return -1;
6387 	if (kread(fil, &sect->ceilingheinum, 2) != 2) return -1;
6388 	if (kread(fil, &sect->floorheinum, 2) != 2) return -1;
6389 	if (kread(fil, &sect->ceilingz, 4) != 4) return -1;
6390 	if (kread(fil, &sect->floorz, 4) != 4) return -1;
6391 	if (kread(fil, &sect->ceilingshade, 1) != 1) return -1;
6392 	if (kread(fil, &sect->floorshade, 1) != 1) return -1;
6393 	if (kread(fil, &sect->ceilingxpanning, 1) != 1) return -1;
6394 	if (kread(fil, &sect->floorxpanning, 1) != 1) return -1;
6395 	if (kread(fil, &sect->ceilingypanning, 1) != 1) return -1;
6396 	if (kread(fil, &sect->floorypanning, 1) != 1) return -1;
6397 	if (kread(fil, &sect->ceilingstat, 1) != 1) return -1;
6398 	if (kread(fil, &sect->floorstat, 1) != 1) return -1;
6399 	if (kread(fil, &sect->ceilingpal, 1) != 1) return -1;
6400 	if (kread(fil, &sect->floorpal, 1) != 1) return -1;
6401 	if (kread(fil, &sect->visibility, 1) != 1) return -1;
6402 	if (kread(fil, &sect->lotag, 2) != 2) return -1;
6403 	if (kread(fil, &sect->hitag, 2) != 2) return -1;
6404 	if (kread(fil, &sect->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, &sect->ceilingshade, 1) != 1) return -1;
6435 	if (Bwrite(fil, &sect->floorshade, 1) != 1) return -1;
6436 	if (Bwrite(fil, &sect->ceilingxpanning, 1) != 1) return -1;
6437 	if (Bwrite(fil, &sect->floorxpanning, 1) != 1) return -1;
6438 	if (Bwrite(fil, &sect->ceilingypanning, 1) != 1) return -1;
6439 	if (Bwrite(fil, &sect->floorypanning, 1) != 1) return -1;
6440 	if (Bwrite(fil, &sect->ceilingstat, 1) != 1) return -1;
6441 	if (Bwrite(fil, &sect->floorstat, 1) != 1) return -1;
6442 	if (Bwrite(fil, &sect->ceilingpal, 1) != 1) return -1;
6443 	if (Bwrite(fil, &sect->floorpal, 1) != 1) return -1;
6444 	if (Bwrite(fil, &sect->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, &sect->wallptr, 2) != 2) return -1;
6736 	if (kread(fil, &sect->wallnum, 2) != 2) return -1;
6737 	if (kread(fil, &sect->ceilingpicnum, 2) != 2) return -1;
6738 	if (kread(fil, &sect->floorpicnum, 2) != 2) return -1;
6739 	if (kread(fil, &sect->ceilingheinum, 2) != 2) return -1;
6740 	if (kread(fil, &sect->floorheinum, 2) != 2) return -1;
6741 	if (kread(fil, &sect->ceilingz, 4) != 4) return -1;
6742 	if (kread(fil, &sect->floorz, 4) != 4) return -1;
6743 	if (kread(fil, &sect->ceilingshade, 1) != 1) return -1;
6744 	if (kread(fil, &sect->floorshade, 1) != 1) return -1;
6745 	if (kread(fil, &sect->ceilingxpanning, 1) != 1) return -1;
6746 	if (kread(fil, &sect->floorxpanning, 1) != 1) return -1;
6747 	if (kread(fil, &sect->ceilingypanning, 1) != 1) return -1;
6748 	if (kread(fil, &sect->floorypanning, 1) != 1) return -1;
6749 	if (kread(fil, &sect->ceilingstat, 1) != 1) return -1;
6750 	if (kread(fil, &sect->floorstat, 1) != 1) return -1;
6751 	if (kread(fil, &sect->ceilingpal, 1) != 1) return -1;
6752 	if (kread(fil, &sect->floorpal, 1) != 1) return -1;
6753 	if (kread(fil, &sect->visibility, 1) != 1) return -1;
6754 	if (kread(fil, &sect->lotag, 2) != 2) return -1;
6755 	if (kread(fil, &sect->hitag, 2) != 2) return -1;
6756 	if (kread(fil, &sect->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, &sect->ceilingshade, 1) != 1) return -1;
6787 	if (Bwrite(fil, &sect->floorshade, 1) != 1) return -1;
6788 	if (Bwrite(fil, &sect->ceilingxpanning, 1) != 1) return -1;
6789 	if (Bwrite(fil, &sect->floorxpanning, 1) != 1) return -1;
6790 	if (Bwrite(fil, &sect->ceilingypanning, 1) != 1) return -1;
6791 	if (Bwrite(fil, &sect->floorypanning, 1) != 1) return -1;
6792 	if (Bwrite(fil, &sect->ceilingstat, 1) != 1) return -1;
6793 	if (Bwrite(fil, &sect->floorstat, 1) != 1) return -1;
6794 	if (Bwrite(fil, &sect->ceilingpal, 1) != 1) return -1;
6795 	if (Bwrite(fil, &sect->floorpal, 1) != 1) return -1;
6796 	if (Bwrite(fil, &sect->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,&sector[i]);
7147 				break;
7148 			case 6:
7149 				if (readv6sect(fil,&v6sect)) goto readerror;
7150 				convertv6sectv7(&v6sect,&sector[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(&sector[i], &v6sect);
7488 				if (writev6sect(fil, &v6sect)) goto writeerror;
7489 				break;
7490 			case 5:
7491 				convertv7sectv6(&sector[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 = &sector[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 = &sector[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 = &sector[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 = &sector[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 = &sector[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 = &sector[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 = &sector[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 = &sector[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 = &sector[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