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 // This file has been modified from Ken Silverman's original release
5 
6 #define SUPERBUILD
7 
8 #define ENGINE
9 #include <string.h>
10 #include <malloc.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <dos.h>
14 #include <fcntl.h>
15 #include <io.h>
16 #include <sys\types.h>
17 #include <sys\stat.h>
18 #include <conio.h>
19 #include <i86.h>
20 #include "build.h"
21 #include "pragmas.h"
22 
23 #include "ves2.h"
24 
25 #pragma intrinsic(min);
26 #pragma intrinsic(max);
27 
28 #define MAXCLIPNUM 512
29 #define MAXPERMS 512
30 #define MAXTILEFILES 256
31 #define MAXYSAVES ((MAXXDIM*MAXSPRITES)>>7)
32 #define MAXNODESPERLINE 42   //Warning: This depends on MAXYSAVES & MAXYDIM!
33 #define MAXWALLSB 2048
34 #define MAXCLIPDIST 1024
35 
36 	//MUST CALL MALLOC THIS WAY TO FORCE CALLS TO KMALLOC!
kmalloc(size_t size)37 void *kmalloc(size_t size) { return(malloc(size)); }
38 void *kkmalloc(size_t size);
39 #pragma aux kkmalloc =\
40 	"call kmalloc",\
41 	parm [eax]\
42 
43 	//MUST CALL FREE THIS WAY TO FORCE CALLS TO KFREE!
kfree(void * buffer)44 void kfree(void *buffer) { free(buffer); }
45 void kkfree(void *buffer);
46 #pragma aux kkfree =\
47 	"call kfree",\
48 	parm [eax]\
49 
50 #ifdef SUPERBUILD
51 	//MUST CALL LOADVOXEL THIS WAY BECAUSE WATCOM STINKS!
loadvoxel(long voxindex)52 void loadvoxel(long voxindex) { }
53 void kloadvoxel(long voxindex);
54 #pragma aux kloadvoxel =\
55 	"call loadvoxel",\
56 	parm [eax]\
57 
58 	//These variables need to be copied into BUILD
59 #define MAXXSIZ 128
60 #define MAXYSIZ 128
61 #define MAXZSIZ 200
62 #define MAXVOXELS 512
63 #define MAXVOXMIPS 5
64 long voxoff[MAXVOXELS][MAXVOXMIPS], voxlock[MAXVOXELS][MAXVOXMIPS];
65 static long ggxinc[MAXXSIZ+1], ggyinc[MAXXSIZ+1];
66 static long lowrecip[1024], nytooclose, nytoofar;
67 static unsigned long distrecip[16384];
68 #endif
69 
70 static char moustat = 0;
71 
72 long transarea = 0, totalarea = 0, beforedrawrooms = 1;
73 
74 static long oxdimen = -1, oviewingrange = -1, oxyaspect = -1;
75 
76 long stereowidth = 23040, stereopixelwidth = 28, ostereopixelwidth = -1;
77 volatile long stereomode = 0, visualpage, activepage, whiteband, blackband;
78 volatile char oa1, o3c2, ortca, ortcb, overtbits, laststereoint;
79 (interrupt *oldstereohandler)();
80 
81 static long curbrightness = 0;
82 
83 	//Textured Map variables
84 static char globalpolytype;
85 static short *dotp1[MAXYDIM], *dotp2[MAXYDIM];
86 
87 static unsigned char tempbuf[MAXWALLS];
88 
89 long ebpbak, espbak;
90 long slopalookup[2048];
91 
92 static char permanentlock = 255;
93 long artversion, mapversion;
94 char *pic = NULL;
95 char picsiz[MAXTILES], tilefilenum[MAXTILES];
96 long lastageclock;
97 long tilefileoffs[MAXTILES];
98 
99 long artsize = 0, cachesize = 0;
100 
101 static short radarang[1280], radarang2[MAXXDIM];
102 static unsigned short sqrtable[4096], shlookup[4096+256];
103 char pow2char[8] = {1,2,4,8,16,32,64,128};
104 long pow2long[32] =
105 {
106 	1L,2L,4L,8L,
107 	16L,32L,64L,128L,
108 	256L,512L,1024L,2048L,
109 	4096L,8192L,16384L,32768L,
110 	65536L,131072L,262144L,524288L,
111 	1048576L,2097152L,4194304L,8388608L,
112 	16777216L,33554432L,67108864L,134217728L,
113 	268435456L,536870912L,1073741824L,2147483647L,
114 };
115 long reciptable[2048], fpuasm;
116 
117 char britable[16][64];
118 char textfont[1024], smalltextfont[1024];
119 
120 static char kensmessage[128];
121 #pragma aux getkensmessagecrc =\
122 	"xor eax, eax",\
123 	"mov ecx, 32",\
124 	"beg: mov edx, dword ptr [ebx+ecx*4-4]",\
125 	"ror edx, cl",\
126 	"adc eax, edx",\
127 	"bswap eax",\
128 	"loop short beg",\
129 	parm [ebx]\
130 	modify exact [eax ebx ecx edx]\
131 
132 static long xb1[MAXWALLSB], yb1[MAXWALLSB], xb2[MAXWALLSB], yb2[MAXWALLSB];
133 static long rx1[MAXWALLSB], ry1[MAXWALLSB], rx2[MAXWALLSB], ry2[MAXWALLSB];
134 static short p2[MAXWALLSB], thesector[MAXWALLSB], thewall[MAXWALLSB];
135 
136 static short bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB];
137 
138 static short smost[MAXYSAVES], smostcnt;
139 static short smoststart[MAXWALLSB];
140 static char smostwalltype[MAXWALLSB];
141 static long smostwall[MAXWALLSB], smostwallcnt = -1L;
142 
143 static short maskwall[MAXWALLSB], maskwallcnt;
144 static long spritesx[MAXSPRITESONSCREEN];
145 static long spritesy[MAXSPRITESONSCREEN+1];
146 static long spritesz[MAXSPRITESONSCREEN];
147 static spritetype *tspriteptr[MAXSPRITESONSCREEN];
148 
149 short umost[MAXXDIM], dmost[MAXXDIM];
150 static short bakumost[MAXXDIM], bakdmost[MAXXDIM];
151 short uplc[MAXXDIM], dplc[MAXXDIM];
152 static short uwall[MAXXDIM], dwall[MAXXDIM];
153 static long swplc[MAXXDIM], lplc[MAXXDIM];
154 static long swall[MAXXDIM], lwall[MAXXDIM+4];
155 long xdimen = -1, xdimenrecip, halfxdimen, xdimenscale, xdimscale;
156 long wx1, wy1, wx2, wy2, ydimen;
157 long viewoffset, frameoffset;
158 
159 static long rxi[8], ryi[8], rzi[8], rxi2[8], ryi2[8], rzi2[8];
160 static long xsi[8], ysi[8], *horizlookup, *horizlookup2, horizycent;
161 
162 long globalposx, globalposy, globalposz, globalhoriz;
163 short globalang, globalcursectnum;
164 long globalpal, cosglobalang, singlobalang;
165 long cosviewingrangeglobalang, sinviewingrangeglobalang;
166 char *globalpalwritten;
167 long globaluclip, globaldclip, globvis;
168 long globalvisibility, globalhisibility, globalpisibility, globalcisibility;
169 char globparaceilclip, globparaflorclip;
170 
171 long xyaspect, viewingrangerecip;
172 
173 long asm1, asm2, asm3, asm4;
174 long vplce[4], vince[4], palookupoffse[4], bufplce[4];
175 char globalxshift, globalyshift;
176 long globalxpanning, globalypanning, globalshade;
177 short globalpicnum, globalshiftval;
178 long globalzd, globalbufplc, globalyscale, globalorientation;
179 long globalx1, globaly1, globalx2, globaly2, globalx3, globaly3, globalzx;
180 long globalx, globaly, globalz;
181 
182 static short sectorborder[256], sectorbordercnt;
183 static char tablesloaded = 0;
184 long pageoffset, ydim16, qsetmode = 0;
185 long startposx, startposy, startposz;
186 short startang, startsectnum;
187 short pointhighlight, linehighlight, highlightcnt;
188 static long lastx[MAXYDIM];
189 char *transluc = NULL, paletteloaded = 0;
190 
191 #define FASTPALGRIDSIZ 8
192 static long rdist[129], gdist[129], bdist[129];
193 static char colhere[((FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2))>>3];
194 static char colhead[(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)];
195 static long colnext[256];
196 static char coldist[8] = {0,1,2,3,4,3,2,1};
197 static long colscan[27];
198 
199 static short clipnum, hitwalls[4];
200 long hitscangoalx = (1<<29)-1, hitscangoaly = (1<<29)-1;
201 
202 typedef struct { long x1, y1, x2, y2; } linetype;
203 static linetype clipit[MAXCLIPNUM];
204 static short clipsectorlist[MAXCLIPNUM], clipsectnum;
205 static short clipobjectval[MAXCLIPNUM];
206 
207 typedef struct
208 {
209 	long sx, sy, z;
210 	short a, picnum;
211 	signed char dashade;
212 	char dapalnum, dastat, pagesleft;
213 	long cx1, cy1, cx2, cy2;
214 } permfifotype;
215 static permfifotype permfifo[MAXPERMS];
216 static long permhead = 0, permtail = 0;
217 
218 short numscans, numhits, numbunches;
219 static short posfil, capturecount = 0, hitcnt;
220 
221 static char pcxheader[128] =
222 {
223 	0xa,0x5,0x1,0x8,0x0,0x0,0x0,0x0,0x3f,0x1,0xc7,0x0,
224 	0x40,0x1,0xc8,0x0,0x0,0x0,0x0,0x8,0x8,0x8,0x10,0x10,
225 	0x10,0x18,0x18,0x18,0x20,0x20,0x20,0x28,0x28,0x28,0x30,0x30,
226 	0x30,0x38,0x38,0x38,0x40,0x40,0x40,0x48,0x48,0x48,0x50,0x50,
227 	0x50,0x58,0x58,0x58,0x60,0x60,0x60,0x68,0x68,0x68,0x70,0x70,
228 	0x70,0x78,0x78,0x78,0x0,0x1,0x40,0x1,0x0,0x0,0x0,0x0,
229 	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
230 	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
231 	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
232 	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
233 	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
234 };
235 static char vgapal16[48] =
236 {
237 	00,00,00,00,00,42,00,42,00,00,42,42,42,00,00,42,00,42,42,21,00,42,42,42,
238 	21,21,21,21,21,63,21,63,21,21,63,63,63,21,21,63,21,63,63,63,21,63,63,63,
239 };
240 
241 short editstatus = 0;
242 short searchit;
243 long searchx = -1, searchy;                          //search input
244 short searchsector, searchwall, searchstat;     //search output
245 
246 static char artfilename[20];
247 static long numtilefiles, artfil = -1, artfilnum, artfilplc;
248 
249 long totalclocklock;
250 
251 extern long sethlinesizes(long,long,long);
252 #pragma aux sethlinesizes parm [eax][ebx][ecx];
253 extern long setpalookupaddress(char *);
254 #pragma aux setpalookupaddress parm [eax];
255 extern long setuphlineasm4(long,long);
256 #pragma aux setuphlineasm4 parm [eax][ebx];
257 extern long hlineasm4(long,long,long,long,long,long);
258 #pragma aux hlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
259 extern long setuprhlineasm4(long,long,long,long,long,long);
260 #pragma aux setuprhlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
261 extern long rhlineasm4(long,long,long,long,long,long);
262 #pragma aux rhlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
263 extern long setuprmhlineasm4(long,long,long,long,long,long);
264 #pragma aux setuprmhlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
265 extern long rmhlineasm4(long,long,long,long,long,long);
266 #pragma aux rmhlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
267 extern long setupqrhlineasm4(long,long,long,long,long,long);
268 #pragma aux setupqrhlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
269 extern long qrhlineasm4(long,long,long,long,long,long);
270 #pragma aux qrhlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
271 extern long setvlinebpl(long);
272 #pragma aux setvlinebpl parm [eax];
273 extern long fixtransluscence(long);
274 #pragma aux fixtransluscence parm [eax];
275 extern long prevlineasm1(long,long,long,long,long,long);
276 #pragma aux prevlineasm1 parm [eax][ebx][ecx][edx][esi][edi];
277 extern long vlineasm1(long,long,long,long,long,long);
278 #pragma aux vlineasm1 parm [eax][ebx][ecx][edx][esi][edi];
279 extern long setuptvlineasm(long);
280 #pragma aux setuptvlineasm parm [eax];
281 extern long tvlineasm1(long,long,long,long,long,long);
282 #pragma aux tvlineasm1 parm [eax][ebx][ecx][edx][esi][edi];
283 extern long setuptvlineasm2(long,long,long);
284 #pragma aux setuptvlineasm2 parm [eax][ebx][ecx];
285 extern long tvlineasm2(long,long,long,long,long,long);
286 #pragma aux tvlineasm2 parm [eax][ebx][ecx][edx][esi][edi];
287 extern long mvlineasm1(long,long,long,long,long,long);
288 #pragma aux mvlineasm1 parm [eax][ebx][ecx][edx][esi][edi];
289 extern long setupvlineasm(long);
290 #pragma aux setupvlineasm parm [eax];
291 extern long vlineasm4(long,long);
292 #pragma aux vlineasm4 parm [ecx][edi] modify [eax ebx ecx edx esi edi];
293 extern long setupmvlineasm(long);
294 #pragma aux setupmvlineasm parm [eax];
295 extern long mvlineasm4(long,long);
296 #pragma aux mvlineasm4 parm [ecx][edi] modify [eax ebx ecx edx esi edi];
297 extern void setupspritevline(long,long,long,long,long,long);
298 #pragma aux setupspritevline parm [eax][ebx][ecx][edx][esi][edi];
299 extern void spritevline(long,long,long,long,long,long);
300 #pragma aux spritevline parm [eax][ebx][ecx][edx][esi][edi];
301 extern void msetupspritevline(long,long,long,long,long,long);
302 #pragma aux msetupspritevline parm [eax][ebx][ecx][edx][esi][edi];
303 extern void mspritevline(long,long,long,long,long,long);
304 #pragma aux mspritevline parm [eax][ebx][ecx][edx][esi][edi];
305 extern void tsetupspritevline(long,long,long,long,long,long);
306 #pragma aux tsetupspritevline parm [eax][ebx][ecx][edx][esi][edi];
307 extern void tspritevline(long,long,long,long,long,long);
308 #pragma aux tspritevline parm [eax][ebx][ecx][edx][esi][edi];
309 extern long mhline(long,long,long,long,long,long);
310 #pragma aux mhline parm [eax][ebx][ecx][edx][esi][edi];
311 extern long mhlineskipmodify(long,long,long,long,long,long);
312 #pragma aux mhlineskipmodify parm [eax][ebx][ecx][edx][esi][edi];
313 extern long msethlineshift(long,long);
314 #pragma aux msethlineshift parm [eax][ebx];
315 extern long thline(long,long,long,long,long,long);
316 #pragma aux thline parm [eax][ebx][ecx][edx][esi][edi];
317 extern long thlineskipmodify(long,long,long,long,long,long);
318 #pragma aux thlineskipmodify parm [eax][ebx][ecx][edx][esi][edi];
319 extern long tsethlineshift(long,long);
320 #pragma aux tsethlineshift parm [eax][ebx];
321 extern long setupslopevlin(long,long,long);
322 #pragma aux setupslopevlin parm [eax][ebx][ecx] modify [edx];
323 extern long slopevlin(long,long,long,long,long,long);
324 #pragma aux slopevlin parm [eax][ebx][ecx][edx][esi][edi];
325 extern long settransnormal();
326 #pragma aux settransnormal parm;
327 extern long settransreverse();
328 #pragma aux settransreverse parm;
329 extern long setupdrawslab(long,long);
330 #pragma aux setupdrawslab parm [eax][ebx];
331 extern long drawslab(long,long,long,long,long,long);
332 #pragma aux drawslab parm [eax][ebx][ecx][edx][esi][edi];
333 
334 #pragma aux nsqrtasm =\
335 	"test eax, 0xff000000",\
336 	"mov ebx, eax",\
337 	"jnz short over24",\
338 	"shr ebx, 12",\
339 	"mov cx, word ptr shlookup[ebx*2]",\
340 	"jmp short under24",\
341 	"over24: shr ebx, 24",\
342 	"mov cx, word ptr shlookup[ebx*2+8192]",\
343 	"under24: shr eax, cl",\
344 	"mov cl, ch",\
345 	"mov ax, word ptr sqrtable[eax*2]",\
346 	"shr eax, cl",\
347 	parm nomemory [eax]\
348 	modify exact [eax ebx ecx]\
349 
350 #pragma aux msqrtasm =\
351 	"mov eax, 0x40000000",\
352 	"mov ebx, 0x20000000",\
353 	"begit: cmp ecx, eax",\
354 	"jl skip",\
355 	"sub ecx, eax",\
356 	"lea eax, [eax+ebx*4]",\
357 	"skip: sub eax, ebx",\
358 	"shr eax, 1",\
359 	"shr ebx, 2",\
360 	"jnz begit",\
361 	"cmp ecx, eax",\
362 	"sbb eax, -1",\
363 	"shr eax, 1",\
364 	parm nomemory [ecx]\
365 	modify exact [eax ebx ecx]\
366 
367 	//0x007ff000 is (11<<13), 0x3f800000 is (127<<23)
368 #pragma aux krecipasm =\
369 	"mov fpuasm, eax",\
370 	"fild dword ptr fpuasm",\
371 	"add eax, eax",\
372 	"fstp dword ptr fpuasm",\
373 	"sbb ebx, ebx",\
374 	"mov eax, fpuasm",\
375 	"mov ecx, eax",\
376 	"and eax, 0x007ff000",\
377 	"shr eax, 10",\
378 	"sub ecx, 0x3f800000",\
379 	"shr ecx, 23",\
380 	"mov eax, dword ptr reciptable[eax]",\
381 	"sar eax, cl",\
382 	"xor eax, ebx",\
383 	parm [eax]\
384 	modify exact [eax ebx ecx]\
385 
386 #pragma aux setgotpic =\
387 	"mov ebx, eax",\
388 	"cmp byte ptr walock[eax], 200",\
389 	"jae skipit",\
390 	"mov byte ptr walock[eax], 199",\
391 	"skipit: shr eax, 3",\
392 	"and ebx, 7",\
393 	"mov dl, byte ptr gotpic[eax]",\
394 	"mov bl, byte ptr pow2char[ebx]",\
395 	"or dl, bl",\
396 	"mov byte ptr gotpic[eax], dl",\
397 	parm [eax]\
398 	modify exact [eax ebx ecx edx]\
399 
400 #pragma aux getclipmask =\
401 	"sar eax, 31",\
402 	"add ebx, ebx",\
403 	"adc eax, eax",\
404 	"add ecx, ecx",\
405 	"adc eax, eax",\
406 	"add edx, edx",\
407 	"adc eax, eax",\
408 	"mov ebx, eax",\
409 	"shl ebx, 4",\
410 	"or al, 0xf0",\
411 	"xor eax, ebx",\
412 	parm [eax][ebx][ecx][edx]\
413 	modify exact [eax ebx ecx edx]\
414 
drawrooms(long daposx,long daposy,long daposz,short daang,long dahoriz,short dacursectnum)415 drawrooms(long daposx, long daposy, long daposz,
416 			 short daang, long dahoriz, short dacursectnum)
417 {
418 	long i, j, z, cz, fz, closest;
419 	short *shortptr1, *shortptr2;
420 
421 	beforedrawrooms = 0;
422 	totalarea += (windowx2+1-windowx1)*(windowy2+1-windowy1);
423 
424 	globalposx = daposx; globalposy = daposy; globalposz = daposz;
425 	globalang = (daang&2047);
426 
427 	globalhoriz = mulscale16(dahoriz-100,xdimenscale)+(ydimen>>1);
428 	globaluclip = (0-globalhoriz)*xdimscale;
429 	globaldclip = (ydimen-globalhoriz)*xdimscale;
430 
431 	i = mulscale16(xdimenscale,viewingrangerecip);
432 	globalpisibility = mulscale16(parallaxvisibility,i);
433 	globalvisibility = mulscale16(visibility,i);
434 	globalhisibility = mulscale16(globalvisibility,xyaspect);
435 	globalcisibility = mulscale8(globalhisibility,320);
436 
437 	globalcursectnum = dacursectnum;
438 	totalclocklock = totalclock;
439 
440 	cosglobalang = sintable[(globalang+512)&2047];
441 	singlobalang = sintable[globalang&2047];
442 	cosviewingrangeglobalang = mulscale16(cosglobalang,viewingrange);
443 	sinviewingrangeglobalang = mulscale16(singlobalang,viewingrange);
444 
445 	if ((stereomode != 0) || (vidoption == 6))
446 	{
447 		if (stereopixelwidth != ostereopixelwidth)
448 		{
449 			ostereopixelwidth = stereopixelwidth;
450 			xdimen = (windowx2-windowx1+1)+(stereopixelwidth<<1); halfxdimen = (xdimen>>1);
451 			xdimenrecip = divscale32(1L,xdimen);
452 			setaspect((long)divscale16(xdimen,windowx2-windowx1+1),yxaspect);
453 		}
454 
455 		if (!(activepage&1))
456 		{
457 			for(i=windowx1;i<windowx1+(stereopixelwidth<<1);i++) { startumost[i] = 1, startdmost[i] = 0; }
458 			for(;i<windowx2+1+(stereopixelwidth<<1);i++) { startumost[i] = windowy1, startdmost[i] = windowy2+1; }
459 			viewoffset = windowy1*bytesperline+windowx1-(stereopixelwidth<<1);
460 			i = stereowidth;
461 		}
462 		else
463 		{
464 			for(i=windowx1;i<windowx2+1;i++) { startumost[i] = windowy1, startdmost[i] = windowy2+1; }
465 			for(;i<windowx2+1+(stereopixelwidth<<1);i++) { startumost[i] = 1, startdmost[i] = 0; }
466 			viewoffset = windowy1*bytesperline+windowx1;
467 			i = -stereowidth;
468 		}
469 		globalposx += mulscale24(singlobalang,i);
470 		globalposy -= mulscale24(cosglobalang,i);
471 		if (vidoption == 6) frameplace = FP_OFF(screen)+(activepage&1)*65536;
472 	}
473 
474 	if ((xyaspect != oxyaspect) || (xdimen != oxdimen) || (viewingrange != oviewingrange))
475 		dosetaspect();
476 
477 	frameoffset = frameplace+viewoffset;
478 
479 	clearbufbyte((long)(&gotsector[0]),(long)((numsectors+7)>>3),0L);
480 
481 	shortptr1 = (short *)&startumost[windowx1];
482 	shortptr2 = (short *)&startdmost[windowx1];
483 	i = xdimen-1;
484 	do
485 	{
486 		umost[i] = shortptr1[i]-windowy1;
487 		dmost[i] = shortptr2[i]-windowy1;
488 		i--;
489 	} while (i != 0);
490 	umost[0] = shortptr1[0]-windowy1;
491 	dmost[0] = shortptr2[0]-windowy1;
492 
493 	if (smostwallcnt < 0)
494 		if (getkensmessagecrc(FP_OFF(kensmessage)) != 0x56c764d4)
495 			{ setvmode(0x3); printf("Nice try.\n"); exit(0); }
496 
497 	numhits = xdimen; numscans = 0; numbunches = 0;
498 	maskwallcnt = 0; smostwallcnt = 0; smostcnt = 0; spritesortcnt = 0;
499 
500 	if (globalcursectnum >= MAXSECTORS)
501 		globalcursectnum -= MAXSECTORS;
502 	else
503 	{
504 		i = globalcursectnum;
505 		updatesector(globalposx,globalposy,&globalcursectnum);
506 		if (globalcursectnum < 0) globalcursectnum = i;
507 	}
508 
509 	globparaceilclip = 1;
510 	globparaflorclip = 1;
511 	getzsofslope(globalcursectnum,globalposx,globalposy,&cz,&fz);
512 	if (globalposz < cz) globparaceilclip = 0;
513 	if (globalposz > fz) globparaflorclip = 0;
514 
515 	scansector(globalcursectnum);
516 
517 	while ((numbunches > 0) && (numhits > 0))
518 	{
519 		clearbuf((long)(&tempbuf[0]),(long)((numbunches+3)>>2),0L);
520 		tempbuf[0] = 1;
521 
522 		closest = 0;              //Almost works, but not quite :(
523 		for(i=1;i<numbunches;i++)
524 		{
525 			if ((j = bunchfront(i,closest)) < 0) continue;
526 			tempbuf[i] = 1;
527 			if (j == 0) tempbuf[closest] = 1, closest = i;
528 		}
529 		for(i=0;i<numbunches;i++) //Double-check
530 		{
531 			if (tempbuf[i]) continue;
532 			if ((j = bunchfront(i,closest)) < 0) continue;
533 			tempbuf[i] = 1;
534 			if (j == 0) tempbuf[closest] = 1, closest = i, i = 0;
535 		}
536 
537 		drawalls(closest);
538 
539 		if (automapping)
540 		{
541 			for(z=bunchfirst[closest];z>=0;z=p2[z])
542 				show2dwall[thewall[z]>>3] |= pow2char[thewall[z]&7];
543 		}
544 
545 		numbunches--;
546 		bunchfirst[closest] = bunchfirst[numbunches];
547 		bunchlast[closest] = bunchlast[numbunches];
548 	}
549 }
550 
scansector(short sectnum)551 scansector (short sectnum)
552 {
553 	walltype *wal, *wal2;
554 	spritetype *spr;
555 	long i, xs, ys, xp, yp, x1, y1, x2, y2, xp1, yp1, xp2, yp2, templong;
556 	short z, zz, startwall, endwall, numscansbefore, scanfirst, bunchfrst;
557 	short nextsectnum;
558 
559 	if (sectnum < 0) return;
560 
561 	if (automapping) show2dsector[sectnum>>3] |= pow2char[sectnum&7];
562 
563 	sectorborder[0] = sectnum, sectorbordercnt = 1;
564 	do
565 	{
566 		sectnum = sectorborder[--sectorbordercnt];
567 
568 		for(z=headspritesect[sectnum];z>=0;z=nextspritesect[z])
569 		{
570 			spr = &sprite[z];
571 			if ((((spr->cstat&0x8000) == 0) || (showinvisibility)) &&
572 				  (spr->xrepeat > 0) && (spr->yrepeat > 0) &&
573 				  (spritesortcnt < MAXSPRITESONSCREEN))
574 			{
575 				xs = spr->x-globalposx; ys = spr->y-globalposy;
576 				if ((spr->cstat&48) || (xs*cosglobalang+ys*singlobalang > 0))
577 				{
578 					copybufbyte(spr,&tsprite[spritesortcnt],sizeof(spritetype));
579 					tsprite[spritesortcnt++].owner = z;
580 				}
581 			}
582 		}
583 
584 		gotsector[sectnum>>3] |= pow2char[sectnum&7];
585 
586 		bunchfrst = numbunches;
587 		numscansbefore = numscans;
588 
589 		startwall = sector[sectnum].wallptr;
590 		endwall = startwall + sector[sectnum].wallnum;
591 		scanfirst = numscans;
592 		for(z=startwall,wal=&wall[z];z<endwall;z++,wal++)
593 		{
594 			nextsectnum = wal->nextsector;
595 
596 			wal2 = &wall[wal->point2];
597 			x1 = wal->x-globalposx; y1 = wal->y-globalposy;
598 			x2 = wal2->x-globalposx; y2 = wal2->y-globalposy;
599 
600 			if ((nextsectnum >= 0) && ((wal->cstat&32) == 0))
601 				if ((gotsector[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0)
602 				{
603 					templong = x1*y2-x2*y1;
604 					if (((unsigned)templong+262144) < 524288)
605 						if (mulscale5(templong,templong) <= (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
606 							sectorborder[sectorbordercnt++] = nextsectnum;
607 				}
608 
609 			if ((z == startwall) || (wall[z-1].point2 != z))
610 			{
611 				xp1 = dmulscale6(y1,cosglobalang,-x1,singlobalang);
612 				yp1 = dmulscale6(x1,cosviewingrangeglobalang,y1,sinviewingrangeglobalang);
613 			}
614 			else
615 			{
616 				xp1 = xp2;
617 				yp1 = yp2;
618 			}
619 			xp2 = dmulscale6(y2,cosglobalang,-x2,singlobalang);
620 			yp2 = dmulscale6(x2,cosviewingrangeglobalang,y2,sinviewingrangeglobalang);
621 			if ((yp1 < 256) && (yp2 < 256)) goto skipitaddwall;
622 
623 				//If wall's NOT facing you
624 			if (dmulscale32(xp1,yp2,-xp2,yp1) >= 0) goto skipitaddwall;
625 
626 			if (xp1 >= -yp1)
627 			{
628 				if ((xp1 > yp1) || (yp1 == 0)) goto skipitaddwall;
629 				xb1[numscans] = halfxdimen + scale(xp1,halfxdimen,yp1);
630 				if (xp1 >= 0) xb1[numscans]++;   //Fix for SIGNED divide
631 				if (xb1[numscans] >= xdimen) xb1[numscans] = xdimen-1;
632 				yb1[numscans] = yp1;
633 			}
634 			else
635 			{
636 				if (xp2 < -yp2) goto skipitaddwall;
637 				xb1[numscans] = 0;
638 				templong = yp1-yp2+xp1-xp2;
639 				if (templong == 0) goto skipitaddwall;
640 				yb1[numscans] = yp1 + scale(yp2-yp1,xp1+yp1,templong);
641 			}
642 			if (yb1[numscans] < 256) goto skipitaddwall;
643 
644 			if (xp2 <= yp2)
645 			{
646 				if ((xp2 < -yp2) || (yp2 == 0)) goto skipitaddwall;
647 				xb2[numscans] = halfxdimen + scale(xp2,halfxdimen,yp2) - 1;
648 				if (xp2 >= 0) xb2[numscans]++;   //Fix for SIGNED divide
649 				if (xb2[numscans] >= xdimen) xb2[numscans] = xdimen-1;
650 				yb2[numscans] = yp2;
651 			}
652 			else
653 			{
654 				if (xp1 > yp1) goto skipitaddwall;
655 				xb2[numscans] = xdimen-1;
656 				templong = xp2-xp1+yp1-yp2;
657 				if (templong == 0) goto skipitaddwall;
658 				yb2[numscans] = yp1 + scale(yp2-yp1,yp1-xp1,templong);
659 			}
660 			if ((yb2[numscans] < 256) || (xb1[numscans] > xb2[numscans])) goto skipitaddwall;
661 
662 				//Made it all the way!
663 			thesector[numscans] = sectnum; thewall[numscans] = z;
664 			rx1[numscans] = xp1; ry1[numscans] = yp1;
665 			rx2[numscans] = xp2; ry2[numscans] = yp2;
666 			p2[numscans] = numscans+1;
667 			numscans++;
668 skipitaddwall:
669 
670 			if ((wall[z].point2 < z) && (scanfirst < numscans))
671 				p2[numscans-1] = scanfirst, scanfirst = numscans;
672 		}
673 
674 		for(z=numscansbefore;z<numscans;z++)
675 			if ((wall[thewall[z]].point2 != thewall[p2[z]]) || (xb2[z] >= xb1[p2[z]]))
676 				bunchfirst[numbunches++] = p2[z], p2[z] = -1;
677 
678 		for(z=bunchfrst;z<numbunches;z++)
679 		{
680 			for(zz=bunchfirst[z];p2[zz]>=0;zz=p2[zz]);
681 			bunchlast[z] = zz;
682 		}
683 	} while (sectorbordercnt > 0);
684 }
685 
wallfront(long l1,long l2)686 wallfront (long l1, long l2)
687 {
688 	walltype *wal;
689 	long x11, y11, x21, y21, x12, y12, x22, y22, dx, dy, t1, t2;
690 
691 	wal = &wall[thewall[l1]]; x11 = wal->x; y11 = wal->y;
692 	wal = &wall[wal->point2]; x21 = wal->x; y21 = wal->y;
693 	wal = &wall[thewall[l2]]; x12 = wal->x; y12 = wal->y;
694 	wal = &wall[wal->point2]; x22 = wal->x; y22 = wal->y;
695 
696 	dx = x21-x11; dy = y21-y11;
697 	t1 = dmulscale2(x12-x11,dy,-dx,y12-y11); //p1(l2) vs. l1
698 	t2 = dmulscale2(x22-x11,dy,-dx,y22-y11); //p2(l2) vs. l1
699 	if (t1 == 0) { t1 = t2; if (t1 == 0) return(-1); }
700 	if (t2 == 0) t2 = t1;
701 	if ((t1^t2) >= 0)
702 	{
703 		t2 = dmulscale2(globalposx-x11,dy,-dx,globalposy-y11); //pos vs. l1
704 		return((t2^t1) >= 0);
705 	}
706 
707 	dx = x22-x12; dy = y22-y12;
708 	t1 = dmulscale2(x11-x12,dy,-dx,y11-y12); //p1(l1) vs. l2
709 	t2 = dmulscale2(x21-x12,dy,-dx,y21-y12); //p2(l1) vs. l2
710 	if (t1 == 0) { t1 = t2; if (t1 == 0) return(-1); }
711 	if (t2 == 0) t2 = t1;
712 	if ((t1^t2) >= 0)
713 	{
714 		t2 = dmulscale2(globalposx-x12,dy,-dx,globalposy-y12); //pos vs. l2
715 		return((t2^t1) < 0);
716 	}
717 	return(-2);
718 }
719 
spritewallfront(spritetype * s,long w)720 spritewallfront (spritetype *s, long w)
721 {
722 	walltype *wal;
723 	long x1, y1;
724 
725 	wal = &wall[w]; x1 = wal->x; y1 = wal->y;
726 	wal = &wall[wal->point2];
727 	return (dmulscale32(wal->x-x1,s->y-y1,-(s->x-x1),wal->y-y1) >= 0);
728 }
729 
bunchfront(long b1,long b2)730 bunchfront (long b1, long b2)
731 {
732 	long x1b1, x2b1, x1b2, x2b2, b1f, b2f, i;
733 
734 	b1f = bunchfirst[b1]; x1b1 = xb1[b1f]; x2b2 = xb2[bunchlast[b2]]+1;
735 	if (x1b1 >= x2b2) return(-1);
736 	b2f = bunchfirst[b2]; x1b2 = xb1[b2f]; x2b1 = xb2[bunchlast[b1]]+1;
737 	if (x1b2 >= x2b1) return(-1);
738 
739 	if (x1b1 >= x1b2)
740 	{
741 		for(i=b2f;xb2[i]<x1b1;i=p2[i]);
742 		return(wallfront(b1f,i));
743 	}
744 	for(i=b1f;xb2[i]<x1b2;i=p2[i]);
745 	return(wallfront(i,b2f));
746 }
747 
drawalls(long bunch)748 drawalls (long bunch)
749 {
750 	sectortype *sec, *nextsec;
751 	walltype *wal;
752 	long i, j, k, l, m, n, x, y, x1, x2, cz[5], fz[5];
753 	long z, wallnum, sectnum, nextsectnum, globalhorizbak;
754 	long startsmostwallcnt, startsmostcnt, gotswall;
755 	char andwstat1, andwstat2;
756 
757 	z = bunchfirst[bunch];
758 	sectnum = thesector[z]; sec = &sector[sectnum];
759 
760 	andwstat1 = 0xff; andwstat2 = 0xff;
761 	for(;z>=0;z=p2[z])  //uplc/dplc calculation
762 	{
763 		andwstat1 &= wallmost(uplc,z,sectnum,(char)0);
764 		andwstat2 &= wallmost(dplc,z,sectnum,(char)1);
765 	}
766 
767 	if ((andwstat1&3) != 3)     //draw ceilings
768 	{
769 		if ((sec->ceilingstat&3) == 2)
770 			grouscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,0);
771 		else if ((sec->ceilingstat&1) == 0)
772 			ceilscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum);
773 		else
774 			parascan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,0,bunch);
775 	}
776 	if ((andwstat2&12) != 12)   //draw floors
777 	{
778 		if ((sec->floorstat&3) == 2)
779 			grouscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,1);
780 		else if ((sec->floorstat&1) == 0)
781 			florscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum);
782 		else
783 			parascan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,1,bunch);
784 	}
785 
786 		//DRAW WALLS SECTION!
787 	for(z=bunchfirst[bunch];z>=0;z=p2[z])
788 	{
789 		x1 = xb1[z]; x2 = xb2[z];
790 		if (umost[x2] >= dmost[x2])
791 		{
792 			for(x=x1;x<x2;x++)
793 				if (umost[x] < dmost[x]) break;
794 			if (x >= x2)
795 			{
796 				smostwall[smostwallcnt] = z;
797 				smostwalltype[smostwallcnt] = 0;
798 				smostwallcnt++;
799 				continue;
800 			}
801 		}
802 
803 		wallnum = thewall[z]; wal = &wall[wallnum];
804 		nextsectnum = wal->nextsector; nextsec = &sector[nextsectnum];
805 
806 		gotswall = 0;
807 
808 		startsmostwallcnt = smostwallcnt;
809 		startsmostcnt = smostcnt;
810 
811 		if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
812 		{
813 			if (searchy <= uplc[searchx]) //ceiling
814 			{
815 				searchsector = sectnum; searchwall = wallnum;
816 				searchstat = 1; searchit = 1;
817 			}
818 			else if (searchy >= dplc[searchx]) //floor
819 			{
820 				searchsector = sectnum; searchwall = wallnum;
821 				searchstat = 2; searchit = 1;
822 			}
823 		}
824 
825 		if (nextsectnum >= 0)
826 		{
827 			getzsofslope((short)sectnum,wal->x,wal->y,&cz[0],&fz[0]);
828 			getzsofslope((short)sectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[1],&fz[1]);
829 			getzsofslope((short)nextsectnum,wal->x,wal->y,&cz[2],&fz[2]);
830 			getzsofslope((short)nextsectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[3],&fz[3]);
831 			getzsofslope((short)nextsectnum,globalposx,globalposy,&cz[4],&fz[4]);
832 
833 			if ((wal->cstat&48) == 16) maskwall[maskwallcnt++] = z;
834 
835 			if (((sec->ceilingstat&1) == 0) || ((nextsec->ceilingstat&1) == 0))
836 			{
837 				if ((cz[2] <= cz[0]) && (cz[3] <= cz[1]))
838 				{
839 					if (globparaceilclip)
840 						for(x=x1;x<=x2;x++)
841 							if (uplc[x] > umost[x])
842 								if (umost[x] <= dmost[x])
843 								{
844 									umost[x] = uplc[x];
845 									if (umost[x] > dmost[x]) numhits--;
846 								}
847 				}
848 				else
849 				{
850 					wallmost(dwall,z,nextsectnum,(char)0);
851 					if ((cz[2] > fz[0]) || (cz[3] > fz[1]))
852 						for(i=x1;i<=x2;i++) if (dwall[i] > dplc[i]) dwall[i] = dplc[i];
853 
854 					if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
855 						if (searchy <= dwall[searchx]) //wall
856 						{
857 							searchsector = sectnum; searchwall = wallnum;
858 							searchstat = 0; searchit = 1;
859 						}
860 
861 					globalorientation = (long)wal->cstat;
862 					globalpicnum = wal->picnum;
863 					if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
864 					globalxpanning = (long)wal->xpanning;
865 					globalypanning = (long)wal->ypanning;
866 					globalshiftval = (picsiz[globalpicnum]>>4);
867 					if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
868 					globalshiftval = 32-globalshiftval;
869 					if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
870 					globalshade = (long)wal->shade;
871 					globvis = globalvisibility;
872 					if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
873 					globalpal = (long)wal->pal;
874 					globalyscale = (wal->yrepeat<<(globalshiftval-19));
875 					if ((globalorientation&4) == 0)
876 						globalzd = (((globalposz-nextsec->ceilingz)*globalyscale)<<8);
877 					else
878 						globalzd = (((globalposz-sec->ceilingz)*globalyscale)<<8);
879 					globalzd += (globalypanning<<24);
880 					if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
881 
882 					if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
883 					wallscan(x1,x2,uplc,dwall,swall,lwall);
884 
885 					if ((cz[2] >= cz[0]) && (cz[3] >= cz[1]))
886 					{
887 						for(x=x1;x<=x2;x++)
888 							if (dwall[x] > umost[x])
889 								if (umost[x] <= dmost[x])
890 								{
891 									umost[x] = dwall[x];
892 									if (umost[x] > dmost[x]) numhits--;
893 								}
894 					}
895 					else
896 					{
897 						for(x=x1;x<=x2;x++)
898 							if (umost[x] <= dmost[x])
899 							{
900 								i = max(uplc[x],dwall[x]);
901 								if (i > umost[x])
902 								{
903 									umost[x] = i;
904 									if (umost[x] > dmost[x]) numhits--;
905 								}
906 							}
907 					}
908 				}
909 				if ((cz[2] < cz[0]) || (cz[3] < cz[1]) || (globalposz < cz[4]))
910 				{
911 					i = x2-x1+1;
912 					if (smostcnt+i < MAXYSAVES)
913 					{
914 						smoststart[smostwallcnt] = smostcnt;
915 						smostwall[smostwallcnt] = z;
916 						smostwalltype[smostwallcnt] = 1;   //1 for umost
917 						smostwallcnt++;
918 						copybufbyte((long)&umost[x1],(long)&smost[smostcnt],i*sizeof(smost[0]));
919 						smostcnt += i;
920 					}
921 				}
922 			}
923 			if (((sec->floorstat&1) == 0) || ((nextsec->floorstat&1) == 0))
924 			{
925 				if ((fz[2] >= fz[0]) && (fz[3] >= fz[1]))
926 				{
927 					if (globparaflorclip)
928 						for(x=x1;x<=x2;x++)
929 							if (dplc[x] < dmost[x])
930 								if (umost[x] <= dmost[x])
931 								{
932 									dmost[x] = dplc[x];
933 									if (umost[x] > dmost[x]) numhits--;
934 								}
935 				}
936 				else
937 				{
938 					wallmost(uwall,z,nextsectnum,(char)1);
939 					if ((fz[2] < cz[0]) || (fz[3] < cz[1]))
940 						for(i=x1;i<=x2;i++) if (uwall[i] < uplc[i]) uwall[i] = uplc[i];
941 
942 					if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
943 						if (searchy >= uwall[searchx]) //wall
944 						{
945 							searchsector = sectnum; searchwall = wallnum;
946 							if ((wal->cstat&2) > 0) searchwall = wal->nextwall;
947 							searchstat = 0; searchit = 1;
948 						}
949 
950 					if ((wal->cstat&2) > 0)
951 					{
952 						wallnum = wal->nextwall; wal = &wall[wallnum];
953 						globalorientation = (long)wal->cstat;
954 						globalpicnum = wal->picnum;
955 						if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
956 						globalxpanning = (long)wal->xpanning;
957 						globalypanning = (long)wal->ypanning;
958 						if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
959 						globalshade = (long)wal->shade;
960 						globalpal = (long)wal->pal;
961 						wallnum = thewall[z]; wal = &wall[wallnum];
962 					}
963 					else
964 					{
965 						globalorientation = (long)wal->cstat;
966 						globalpicnum = wal->picnum;
967 						if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
968 						globalxpanning = (long)wal->xpanning;
969 						globalypanning = (long)wal->ypanning;
970 						if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
971 						globalshade = (long)wal->shade;
972 						globalpal = (long)wal->pal;
973 					}
974 					globvis = globalvisibility;
975 					if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
976 					globalshiftval = (picsiz[globalpicnum]>>4);
977 					if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
978 					globalshiftval = 32-globalshiftval;
979 					globalyscale = (wal->yrepeat<<(globalshiftval-19));
980 					if ((globalorientation&4) == 0)
981 						globalzd = (((globalposz-nextsec->floorz)*globalyscale)<<8);
982 					else
983 						globalzd = (((globalposz-sec->ceilingz)*globalyscale)<<8);
984 					globalzd += (globalypanning<<24);
985 					if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
986 
987 					if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
988 					wallscan(x1,x2,uwall,dplc,swall,lwall);
989 
990 					if ((fz[2] <= fz[0]) && (fz[3] <= fz[1]))
991 					{
992 						for(x=x1;x<=x2;x++)
993 							if (uwall[x] < dmost[x])
994 								if (umost[x] <= dmost[x])
995 								{
996 									dmost[x] = uwall[x];
997 									if (umost[x] > dmost[x]) numhits--;
998 								}
999 					}
1000 					else
1001 					{
1002 						for(x=x1;x<=x2;x++)
1003 							if (umost[x] <= dmost[x])
1004 							{
1005 								i = min(dplc[x],uwall[x]);
1006 								if (i < dmost[x])
1007 								{
1008 									dmost[x] = i;
1009 									if (umost[x] > dmost[x]) numhits--;
1010 								}
1011 							}
1012 					}
1013 				}
1014 				if ((fz[2] > fz[0]) || (fz[3] > fz[1]) || (globalposz > fz[4]))
1015 				{
1016 					i = x2-x1+1;
1017 					if (smostcnt+i < MAXYSAVES)
1018 					{
1019 						smoststart[smostwallcnt] = smostcnt;
1020 						smostwall[smostwallcnt] = z;
1021 						smostwalltype[smostwallcnt] = 2;   //2 for dmost
1022 						smostwallcnt++;
1023 						copybufbyte((long)&dmost[x1],(long)&smost[smostcnt],i*sizeof(smost[0]));
1024 						smostcnt += i;
1025 					}
1026 				}
1027 			}
1028 			if (numhits < 0) return;
1029 			if ((!(wal->cstat&32)) && ((gotsector[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0))
1030 			{
1031 				if (umost[x2] < dmost[x2])
1032 					scansector(nextsectnum);
1033 				else
1034 				{
1035 					for(x=x1;x<x2;x++)
1036 						if (umost[x] < dmost[x])
1037 							{ scansector(nextsectnum); break; }
1038 
1039 						//If can't see sector beyond, then cancel smost array and just
1040 						//store wall!
1041 					if (x == x2)
1042 					{
1043 						smostwallcnt = startsmostwallcnt;
1044 						smostcnt = startsmostcnt;
1045 						smostwall[smostwallcnt] = z;
1046 						smostwalltype[smostwallcnt] = 0;
1047 						smostwallcnt++;
1048 					}
1049 				}
1050 			}
1051 		}
1052 		if ((nextsectnum < 0) || (wal->cstat&32))   //White/1-way wall
1053 		{
1054 			globalorientation = (long)wal->cstat;
1055 			if (nextsectnum < 0) globalpicnum = wal->picnum;
1056 								  else globalpicnum = wal->overpicnum;
1057 			if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
1058 			globalxpanning = (long)wal->xpanning;
1059 			globalypanning = (long)wal->ypanning;
1060 			if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
1061 			globalshade = (long)wal->shade;
1062 			globvis = globalvisibility;
1063 			if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
1064 			globalpal = (long)wal->pal;
1065 			globalshiftval = (picsiz[globalpicnum]>>4);
1066 			if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
1067 			globalshiftval = 32-globalshiftval;
1068 			globalyscale = (wal->yrepeat<<(globalshiftval-19));
1069 			if (nextsectnum >= 0)
1070 			{
1071 				if ((globalorientation&4) == 0) globalzd = globalposz-nextsec->ceilingz;
1072 													else globalzd = globalposz-sec->ceilingz;
1073 			}
1074 			else
1075 			{
1076 				if ((globalorientation&4) == 0) globalzd = globalposz-sec->ceilingz;
1077 													else globalzd = globalposz-sec->floorz;
1078 			}
1079 			globalzd = ((globalzd*globalyscale)<<8) + (globalypanning<<24);
1080 			if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
1081 
1082 			if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
1083 			wallscan(x1,x2,uplc,dplc,swall,lwall);
1084 
1085 			for(x=x1;x<=x2;x++)
1086 				if (umost[x] <= dmost[x])
1087 					{ umost[x] = 1; dmost[x] = 0; numhits--; }
1088 			smostwall[smostwallcnt] = z;
1089 			smostwalltype[smostwallcnt] = 0;
1090 			smostwallcnt++;
1091 
1092 			if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
1093 			{
1094 				searchit = 1; searchsector = sectnum; searchwall = wallnum;
1095 				if (nextsectnum < 0) searchstat = 0; else searchstat = 4;
1096 			}
1097 		}
1098 	}
1099 }
1100 
prepwall(long z,walltype * wal)1101 prepwall(long z, walltype *wal)
1102 {
1103 	long i, l, ol, splc, sinc, x, topinc, top, botinc, bot, hplc, walxrepeat;
1104 
1105 	walxrepeat = (wal->xrepeat<<3);
1106 
1107 		//lwall calculation
1108 	i = xb1[z]-halfxdimen;
1109 	topinc = -(ry1[z]>>2);
1110 	botinc = ((ry2[z]-ry1[z])>>8);
1111 	top = mulscale5(rx1[z],xdimen)+mulscale2(topinc,i);
1112 	bot = mulscale11(rx1[z]-rx2[z],xdimen)+mulscale2(botinc,i);
1113 
1114 	splc = mulscale19(ry1[z],xdimscale);
1115 	sinc = mulscale16(ry2[z]-ry1[z],xdimscale);
1116 
1117 	x = xb1[z];
1118 	if (bot != 0)
1119 	{
1120 		l = divscale12(top,bot);
1121 		swall[x] = mulscale21(l,sinc)+splc;
1122 		l *= walxrepeat;
1123 		lwall[x] = (l>>18);
1124 	}
1125 	while (x+4 <= xb2[z])
1126 	{
1127 		top += topinc; bot += botinc;
1128 		if (bot != 0)
1129 		{
1130 			ol = l; l = divscale12(top,bot);
1131 			swall[x+4] = mulscale21(l,sinc)+splc;
1132 			l *= walxrepeat;
1133 			lwall[x+4] = (l>>18);
1134 		}
1135 		i = ((ol+l)>>1);
1136 		lwall[x+2] = (i>>18);
1137 		lwall[x+1] = ((ol+i)>>19);
1138 		lwall[x+3] = ((l+i)>>19);
1139 		swall[x+2] = ((swall[x]+swall[x+4])>>1);
1140 		swall[x+1] = ((swall[x]+swall[x+2])>>1);
1141 		swall[x+3] = ((swall[x+4]+swall[x+2])>>1);
1142 		x += 4;
1143 	}
1144 	if (x+2 <= xb2[z])
1145 	{
1146 		top += (topinc>>1); bot += (botinc>>1);
1147 		if (bot != 0)
1148 		{
1149 			ol = l; l = divscale12(top,bot);
1150 			swall[x+2] = mulscale21(l,sinc)+splc;
1151 			l *= walxrepeat;
1152 			lwall[x+2] = (l>>18);
1153 		}
1154 		lwall[x+1] = ((l+ol)>>19);
1155 		swall[x+1] = ((swall[x]+swall[x+2])>>1);
1156 		x += 2;
1157 	}
1158 	if (x+1 <= xb2[z])
1159 	{
1160 		bot += (botinc>>2);
1161 		if (bot != 0)
1162 		{
1163 			l = divscale12(top+(topinc>>2),bot);
1164 			swall[x+1] = mulscale21(l,sinc)+splc;
1165 			lwall[x+1] = mulscale18(l,walxrepeat);
1166 		}
1167 	}
1168 
1169 	if (lwall[xb1[z]] < 0) lwall[xb1[z]] = 0;
1170 	if ((lwall[xb2[z]] >= walxrepeat) && (walxrepeat)) lwall[xb2[z]] = walxrepeat-1;
1171 	if (wal->cstat&8)
1172 	{
1173 		walxrepeat--;
1174 		for(x=xb1[z];x<=xb2[z];x++) lwall[x] = walxrepeat-lwall[x];
1175 	}
1176 }
1177 
ceilscan(long x1,long x2,long sectnum)1178 ceilscan (long x1, long x2, long sectnum)
1179 {
1180 	long i, j, ox, oy, x, y1, y2, twall, bwall;
1181 	sectortype *sec;
1182 
1183 	sec = &sector[sectnum];
1184 	if (palookup[sec->ceilingpal] != globalpalwritten)
1185 	{
1186 		globalpalwritten = palookup[sec->ceilingpal];
1187 		setpalookupaddress(globalpalwritten);
1188 	}
1189 
1190 	globalzd = sec->ceilingz-globalposz;
1191 	if (globalzd > 0) return;
1192 	globalpicnum = sec->ceilingpicnum;
1193 	if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
1194 	setgotpic(globalpicnum);
1195 	if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) return;
1196 	if (picanm[globalpicnum]&192) globalpicnum += animateoffs((short)globalpicnum,(short)sectnum);
1197 
1198 	if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
1199 	globalbufplc = waloff[globalpicnum];
1200 
1201 	globalshade = (long)sec->ceilingshade;
1202 	globvis = globalcisibility;
1203 	if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
1204 	globalorientation = (long)sec->ceilingstat;
1205 
1206 
1207 	if ((globalorientation&64) == 0)
1208 	{
1209 		globalx1 = singlobalang; globalx2 = singlobalang;
1210 		globaly1 = cosglobalang; globaly2 = cosglobalang;
1211 		globalxpanning = (globalposx<<20);
1212 		globalypanning = -(globalposy<<20);
1213 	}
1214 	else
1215 	{
1216 		j = sec->wallptr;
1217 		ox = wall[wall[j].point2].x - wall[j].x;
1218 		oy = wall[wall[j].point2].y - wall[j].y;
1219 		i = nsqrtasm(ox*ox+oy*oy); if (i == 0) i = 1024; else i = 1048576/i;
1220 		globalx1 = mulscale10(dmulscale10(ox,singlobalang,-oy,cosglobalang),i);
1221 		globaly1 = mulscale10(dmulscale10(ox,cosglobalang,oy,singlobalang),i);
1222 		globalx2 = -globalx1;
1223 		globaly2 = -globaly1;
1224 
1225 		ox = ((wall[j].x-globalposx)<<6); oy = ((wall[j].y-globalposy)<<6);
1226 		i = dmulscale14(oy,cosglobalang,-ox,singlobalang);
1227 		j = dmulscale14(ox,cosglobalang,oy,singlobalang);
1228 		ox = i; oy = j;
1229 		globalxpanning = globalx1*ox - globaly1*oy;
1230 		globalypanning = globaly2*ox + globalx2*oy;
1231 	}
1232 	globalx2 = mulscale16(globalx2,viewingrangerecip);
1233 	globaly1 = mulscale16(globaly1,viewingrangerecip);
1234 	globalxshift = (8-(picsiz[globalpicnum]&15));
1235 	globalyshift = (8-(picsiz[globalpicnum]>>4));
1236 	if (globalorientation&8) { globalxshift++; globalyshift++; }
1237 
1238 	if ((globalorientation&0x4) > 0)
1239 	{
1240 		i = globalxpanning; globalxpanning = globalypanning; globalypanning = i;
1241 		i = globalx2; globalx2 = -globaly1; globaly1 = -i;
1242 		i = globalx1; globalx1 = globaly2; globaly2 = i;
1243 	}
1244 	if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalxpanning = -globalxpanning;
1245 	if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalypanning = -globalypanning;
1246 	globalx1 <<= globalxshift; globaly1 <<= globalxshift;
1247 	globalx2 <<= globalyshift;  globaly2 <<= globalyshift;
1248 	globalxpanning <<= globalxshift; globalypanning <<= globalyshift;
1249 	globalxpanning += (((long)sec->ceilingxpanning)<<24);
1250 	globalypanning += (((long)sec->ceilingypanning)<<24);
1251 	globaly1 = (-globalx1-globaly1)*halfxdimen;
1252 	globalx2 = (globalx2-globaly2)*halfxdimen;
1253 
1254 	sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
1255 
1256 	globalx2 += globaly2*(x1-1);
1257 	globaly1 += globalx1*(x1-1);
1258 	globalx1 = mulscale16(globalx1,globalzd);
1259 	globalx2 = mulscale16(globalx2,globalzd);
1260 	globaly1 = mulscale16(globaly1,globalzd);
1261 	globaly2 = mulscale16(globaly2,globalzd);
1262 	globvis = klabs(mulscale10(globvis,globalzd));
1263 
1264 	if (!(globalorientation&0x180))
1265 	{
1266 		y1 = umost[x1]; y2 = y1;
1267 		for(x=x1;x<=x2;x++)
1268 		{
1269 			twall = umost[x]-1; bwall = min(uplc[x],dmost[x]);
1270 			if (twall < bwall-1)
1271 			{
1272 				if (twall >= y2)
1273 				{
1274 					while (y1 < y2-1) hline(x-1,++y1);
1275 					y1 = twall;
1276 				}
1277 				else
1278 				{
1279 					while (y1 < twall) hline(x-1,++y1);
1280 					while (y1 > twall) lastx[y1--] = x;
1281 				}
1282 				while (y2 > bwall) hline(x-1,--y2);
1283 				while (y2 < bwall) lastx[y2++] = x;
1284 			}
1285 			else
1286 			{
1287 				while (y1 < y2-1) hline(x-1,++y1);
1288 				if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
1289 				y1 = umost[x+1]; y2 = y1;
1290 			}
1291 			globalx2 += globaly2; globaly1 += globalx1;
1292 		}
1293 		while (y1 < y2-1) hline(x2,++y1);
1294 		faketimerhandler();
1295 		return;
1296 	}
1297 
1298 	switch(globalorientation&0x180)
1299 	{
1300 		case 128:
1301 			msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1302 			break;
1303 		case 256:
1304 			settransnormal();
1305 			tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1306 			break;
1307 		case 384:
1308 			settransreverse();
1309 			tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1310 			break;
1311 	}
1312 
1313 	y1 = umost[x1]; y2 = y1;
1314 	for(x=x1;x<=x2;x++)
1315 	{
1316 		twall = umost[x]-1; bwall = min(uplc[x],dmost[x]);
1317 		if (twall < bwall-1)
1318 		{
1319 			if (twall >= y2)
1320 			{
1321 				while (y1 < y2-1) slowhline(x-1,++y1);
1322 				y1 = twall;
1323 			}
1324 			else
1325 			{
1326 				while (y1 < twall) slowhline(x-1,++y1);
1327 				while (y1 > twall) lastx[y1--] = x;
1328 			}
1329 			while (y2 > bwall) slowhline(x-1,--y2);
1330 			while (y2 < bwall) lastx[y2++] = x;
1331 		}
1332 		else
1333 		{
1334 			while (y1 < y2-1) slowhline(x-1,++y1);
1335 			if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
1336 			y1 = umost[x+1]; y2 = y1;
1337 		}
1338 		globalx2 += globaly2; globaly1 += globalx1;
1339 	}
1340 	while (y1 < y2-1) slowhline(x2,++y1);
1341 	faketimerhandler();
1342 }
1343 
florscan(long x1,long x2,long sectnum)1344 florscan (long x1, long x2, long sectnum)
1345 {
1346 	long i, j, ox, oy, x, y1, y2, twall, bwall;
1347 	sectortype *sec;
1348 
1349 	sec = &sector[sectnum];
1350 	if (palookup[sec->floorpal] != globalpalwritten)
1351 	{
1352 		globalpalwritten = palookup[sec->floorpal];
1353 		setpalookupaddress(globalpalwritten);
1354 	}
1355 
1356 	globalzd = globalposz-sec->floorz;
1357 	if (globalzd > 0) return;
1358 	globalpicnum = sec->floorpicnum;
1359 	if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
1360 	setgotpic(globalpicnum);
1361 	if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) return;
1362 	if (picanm[globalpicnum]&192) globalpicnum += animateoffs((short)globalpicnum,(short)sectnum);
1363 
1364 	if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
1365 	globalbufplc = waloff[globalpicnum];
1366 
1367 	globalshade = (long)sec->floorshade;
1368 	globvis = globalcisibility;
1369 	if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
1370 	globalorientation = (long)sec->floorstat;
1371 
1372 
1373 	if ((globalorientation&64) == 0)
1374 	{
1375 		globalx1 = singlobalang; globalx2 = singlobalang;
1376 		globaly1 = cosglobalang; globaly2 = cosglobalang;
1377 		globalxpanning = (globalposx<<20);
1378 		globalypanning = -(globalposy<<20);
1379 	}
1380 	else
1381 	{
1382 		j = sec->wallptr;
1383 		ox = wall[wall[j].point2].x - wall[j].x;
1384 		oy = wall[wall[j].point2].y - wall[j].y;
1385 		i = nsqrtasm(ox*ox+oy*oy); if (i == 0) i = 1024; else i = 1048576/i;
1386 		globalx1 = mulscale10(dmulscale10(ox,singlobalang,-oy,cosglobalang),i);
1387 		globaly1 = mulscale10(dmulscale10(ox,cosglobalang,oy,singlobalang),i);
1388 		globalx2 = -globalx1;
1389 		globaly2 = -globaly1;
1390 
1391 		ox = ((wall[j].x-globalposx)<<6); oy = ((wall[j].y-globalposy)<<6);
1392 		i = dmulscale14(oy,cosglobalang,-ox,singlobalang);
1393 		j = dmulscale14(ox,cosglobalang,oy,singlobalang);
1394 		ox = i; oy = j;
1395 		globalxpanning = globalx1*ox - globaly1*oy;
1396 		globalypanning = globaly2*ox + globalx2*oy;
1397 	}
1398 	globalx2 = mulscale16(globalx2,viewingrangerecip);
1399 	globaly1 = mulscale16(globaly1,viewingrangerecip);
1400 	globalxshift = (8-(picsiz[globalpicnum]&15));
1401 	globalyshift = (8-(picsiz[globalpicnum]>>4));
1402 	if (globalorientation&8) { globalxshift++; globalyshift++; }
1403 
1404 	if ((globalorientation&0x4) > 0)
1405 	{
1406 		i = globalxpanning; globalxpanning = globalypanning; globalypanning = i;
1407 		i = globalx2; globalx2 = -globaly1; globaly1 = -i;
1408 		i = globalx1; globalx1 = globaly2; globaly2 = i;
1409 	}
1410 	if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalxpanning = -globalxpanning;
1411 	if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalypanning = -globalypanning;
1412 	globalx1 <<= globalxshift; globaly1 <<= globalxshift;
1413 	globalx2 <<= globalyshift;  globaly2 <<= globalyshift;
1414 	globalxpanning <<= globalxshift; globalypanning <<= globalyshift;
1415 	globalxpanning += (((long)sec->floorxpanning)<<24);
1416 	globalypanning += (((long)sec->floorypanning)<<24);
1417 	globaly1 = (-globalx1-globaly1)*halfxdimen;
1418 	globalx2 = (globalx2-globaly2)*halfxdimen;
1419 
1420 	sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
1421 
1422 	globalx2 += globaly2*(x1-1);
1423 	globaly1 += globalx1*(x1-1);
1424 	globalx1 = mulscale16(globalx1,globalzd);
1425 	globalx2 = mulscale16(globalx2,globalzd);
1426 	globaly1 = mulscale16(globaly1,globalzd);
1427 	globaly2 = mulscale16(globaly2,globalzd);
1428 	globvis = klabs(mulscale10(globvis,globalzd));
1429 
1430 	if (!(globalorientation&0x180))
1431 	{
1432 		y1 = max(dplc[x1],umost[x1]); y2 = y1;
1433 		for(x=x1;x<=x2;x++)
1434 		{
1435 			twall = max(dplc[x],umost[x])-1; bwall = dmost[x];
1436 			if (twall < bwall-1)
1437 			{
1438 				if (twall >= y2)
1439 				{
1440 					while (y1 < y2-1) hline(x-1,++y1);
1441 					y1 = twall;
1442 				}
1443 				else
1444 				{
1445 					while (y1 < twall) hline(x-1,++y1);
1446 					while (y1 > twall) lastx[y1--] = x;
1447 				}
1448 				while (y2 > bwall) hline(x-1,--y2);
1449 				while (y2 < bwall) lastx[y2++] = x;
1450 			}
1451 			else
1452 			{
1453 				while (y1 < y2-1) hline(x-1,++y1);
1454 				if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
1455 				y1 = max(dplc[x+1],umost[x+1]); y2 = y1;
1456 			}
1457 			globalx2 += globaly2; globaly1 += globalx1;
1458 		}
1459 		while (y1 < y2-1) hline(x2,++y1);
1460 		faketimerhandler();
1461 		return;
1462 	}
1463 
1464 	switch(globalorientation&0x180)
1465 	{
1466 		case 128:
1467 			msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1468 			break;
1469 		case 256:
1470 			settransnormal();
1471 			tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1472 			break;
1473 		case 384:
1474 			settransreverse();
1475 			tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1476 			break;
1477 	}
1478 
1479 	y1 = max(dplc[x1],umost[x1]); y2 = y1;
1480 	for(x=x1;x<=x2;x++)
1481 	{
1482 		twall = max(dplc[x],umost[x])-1; bwall = dmost[x];
1483 		if (twall < bwall-1)
1484 		{
1485 			if (twall >= y2)
1486 			{
1487 				while (y1 < y2-1) slowhline(x-1,++y1);
1488 				y1 = twall;
1489 			}
1490 			else
1491 			{
1492 				while (y1 < twall) slowhline(x-1,++y1);
1493 				while (y1 > twall) lastx[y1--] = x;
1494 			}
1495 			while (y2 > bwall) slowhline(x-1,--y2);
1496 			while (y2 < bwall) lastx[y2++] = x;
1497 		}
1498 		else
1499 		{
1500 			while (y1 < y2-1) slowhline(x-1,++y1);
1501 			if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
1502 			y1 = max(dplc[x+1],umost[x+1]); y2 = y1;
1503 		}
1504 		globalx2 += globaly2; globaly1 += globalx1;
1505 	}
1506 	while (y1 < y2-1) slowhline(x2,++y1);
1507 	faketimerhandler();
1508 }
1509 
wallscan(long x1,long x2,short * uwal,short * dwal,long * swal,long * lwal)1510 wallscan(long x1, long x2, short *uwal, short *dwal, long *swal, long *lwal)
1511 {
1512 	long i, x, xnice, ynice, fpalookup, shade;
1513 	long y1ve[4], y2ve[4], u4, d4, dax, z, tsizx, tsizy;
1514 	char bad;
1515 
1516 	tsizx = tilesizx[globalpicnum];
1517 	tsizy = tilesizy[globalpicnum];
1518 	setgotpic(globalpicnum);
1519 	if ((tsizx <= 0) || (tsizy <= 0)) return;
1520 	if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen)) return;
1521 	if ((dwal[x1] < 0) && (dwal[x2] < 0)) return;
1522 
1523 	if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
1524 
1525 	xnice = (pow2long[picsiz[globalpicnum]&15] == tsizx);
1526 	if (xnice) tsizx--;
1527 	ynice = (pow2long[picsiz[globalpicnum]>>4] == tsizy);
1528 	if (ynice) tsizy = (picsiz[globalpicnum]>>4);
1529 
1530 	fpalookup = FP_OFF(palookup[globalpal]);
1531 
1532 	setupvlineasm(globalshiftval);
1533 
1534 	x = x1;
1535 	while ((umost[x] > dmost[x]) && (x <= x2)) x++;
1536 
1537 	for(;(x<=x2)&&((x+frameoffset)&3);x++)
1538 	{
1539 		y1ve[0] = max(uwal[x],umost[x]);
1540 		y2ve[0] = min(dwal[x],dmost[x]);
1541 		if (y2ve[0] <= y1ve[0]) continue;
1542 
1543 		palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
1544 
1545 		bufplce[0] = lwal[x] + globalxpanning;
1546 		if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
1547 		if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
1548 
1549 		vince[0] = swal[x]*globalyscale;
1550 		vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
1551 
1552 		vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],x+frameoffset+ylookup[y1ve[0]]);
1553 	}
1554 	for(;x<=x2-3;x+=4)
1555 	{
1556 		bad = 0;
1557 		for(z=3;z>=0;z--)
1558 		{
1559 			y1ve[z] = max(uwal[x+z],umost[x+z]);
1560 			y2ve[z] = min(dwal[x+z],dmost[x+z])-1;
1561 			if (y2ve[z] < y1ve[z]) { bad += pow2char[z]; continue; }
1562 
1563 			i = lwal[x+z] + globalxpanning;
1564 			if (i >= tsizx) { if (xnice == 0) i %= tsizx; else i &= tsizx; }
1565 			if (ynice == 0) i *= tsizy; else i <<= tsizy;
1566 			bufplce[z] = waloff[globalpicnum]+i;
1567 
1568 			vince[z] = swal[x+z]*globalyscale;
1569 			vplce[z] = globalzd + vince[z]*(y1ve[z]-globalhoriz+1);
1570 		}
1571 		if (bad == 15) continue;
1572 
1573 		palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
1574 		palookupoffse[3] = fpalookup+(getpalookup((long)mulscale16(swal[x+3],globvis),globalshade)<<8);
1575 
1576 		if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
1577 		{
1578 			palookupoffse[1] = palookupoffse[0];
1579 			palookupoffse[2] = palookupoffse[0];
1580 		}
1581 		else
1582 		{
1583 			palookupoffse[1] = fpalookup+(getpalookup((long)mulscale16(swal[x+1],globvis),globalshade)<<8);
1584 			palookupoffse[2] = fpalookup+(getpalookup((long)mulscale16(swal[x+2],globvis),globalshade)<<8);
1585 		}
1586 
1587 		u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
1588 		d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
1589 
1590 		if ((bad != 0) || (u4 >= d4))
1591 		{
1592 			if (!(bad&1)) prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+x+frameoffset+0);
1593 			if (!(bad&2)) prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+x+frameoffset+1);
1594 			if (!(bad&4)) prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+x+frameoffset+2);
1595 			if (!(bad&8)) prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+x+frameoffset+3);
1596 			continue;
1597 		}
1598 
1599 		if (u4 > y1ve[0]) vplce[0] = prevlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+x+frameoffset+0);
1600 		if (u4 > y1ve[1]) vplce[1] = prevlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+x+frameoffset+1);
1601 		if (u4 > y1ve[2]) vplce[2] = prevlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+x+frameoffset+2);
1602 		if (u4 > y1ve[3]) vplce[3] = prevlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+x+frameoffset+3);
1603 
1604 		if (d4 >= u4) vlineasm4(d4-u4+1,ylookup[u4]+x+frameoffset);
1605 
1606 		i = x+frameoffset+ylookup[d4+1];
1607 		if (y2ve[0] > d4) prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
1608 		if (y2ve[1] > d4) prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
1609 		if (y2ve[2] > d4) prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
1610 		if (y2ve[3] > d4) prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
1611 	}
1612 	for(;x<=x2;x++)
1613 	{
1614 		y1ve[0] = max(uwal[x],umost[x]);
1615 		y2ve[0] = min(dwal[x],dmost[x]);
1616 		if (y2ve[0] <= y1ve[0]) continue;
1617 
1618 		palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
1619 
1620 		bufplce[0] = lwal[x] + globalxpanning;
1621 		if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
1622 		if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
1623 
1624 		vince[0] = swal[x]*globalyscale;
1625 		vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
1626 
1627 		vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],x+frameoffset+ylookup[y1ve[0]]);
1628 	}
1629 	faketimerhandler();
1630 }
1631 
maskwallscan(long x1,long x2,short * uwal,short * dwal,long * swal,long * lwal)1632 maskwallscan(long x1, long x2, short *uwal, short *dwal, long *swal, long *lwal)
1633 {
1634 	long i, x, startx, xnice, ynice, fpalookup, shade;
1635 	long y1ve[4], y2ve[4], u4, d4, dax, z, p, tsizx, tsizy;
1636 	char bad;
1637 
1638 	tsizx = tilesizx[globalpicnum];
1639 	tsizy = tilesizy[globalpicnum];
1640 	setgotpic(globalpicnum);
1641 	if ((tsizx <= 0) || (tsizy <= 0)) return;
1642 	if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen)) return;
1643 	if ((dwal[x1] < 0) && (dwal[x2] < 0)) return;
1644 
1645 	if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
1646 
1647 	startx = x1;
1648 
1649 	xnice = (pow2long[picsiz[globalpicnum]&15] == tsizx);
1650 	if (xnice) tsizx = (tsizx-1);
1651 	ynice = (pow2long[picsiz[globalpicnum]>>4] == tsizy);
1652 	if (ynice) tsizy = (picsiz[globalpicnum]>>4);
1653 
1654 	fpalookup = FP_OFF(palookup[globalpal]);
1655 
1656 	setupmvlineasm(globalshiftval);
1657 
1658 	x = startx;
1659 	while ((startumost[x+windowx1] > startdmost[x+windowx1]) && (x <= x2)) x++;
1660 
1661 	p = x+frameoffset;
1662 
1663 	for(;(x<=x2)&&(p&3);x++,p++)
1664 	{
1665 		y1ve[0] = max(uwal[x],startumost[x+windowx1]-windowy1);
1666 		y2ve[0] = min(dwal[x],startdmost[x+windowx1]-windowy1);
1667 		if (y2ve[0] <= y1ve[0]) continue;
1668 
1669 		palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
1670 
1671 		bufplce[0] = lwal[x] + globalxpanning;
1672 		if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
1673 		if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
1674 
1675 		vince[0] = swal[x]*globalyscale;
1676 		vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
1677 
1678 		mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],p+ylookup[y1ve[0]]);
1679 	}
1680 	for(;x<=x2-3;x+=4,p+=4)
1681 	{
1682 		bad = 0;
1683 		for(z=3,dax=x+3;z>=0;z--,dax--)
1684 		{
1685 			y1ve[z] = max(uwal[dax],startumost[dax+windowx1]-windowy1);
1686 			y2ve[z] = min(dwal[dax],startdmost[dax+windowx1]-windowy1)-1;
1687 			if (y2ve[z] < y1ve[z]) { bad += pow2char[z]; continue; }
1688 
1689 			i = lwal[dax] + globalxpanning;
1690 			if (i >= tsizx) { if (xnice == 0) i %= tsizx; else i &= tsizx; }
1691 			if (ynice == 0) i *= tsizy; else i <<= tsizy;
1692 			bufplce[z] = waloff[globalpicnum]+i;
1693 
1694 			vince[z] = swal[dax]*globalyscale;
1695 			vplce[z] = globalzd + vince[z]*(y1ve[z]-globalhoriz+1);
1696 		}
1697 		if (bad == 15) continue;
1698 
1699 		palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
1700 		palookupoffse[3] = fpalookup+(getpalookup((long)mulscale16(swal[x+3],globvis),globalshade)<<8);
1701 
1702 		if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
1703 		{
1704 			palookupoffse[1] = palookupoffse[0];
1705 			palookupoffse[2] = palookupoffse[0];
1706 		}
1707 		else
1708 		{
1709 			palookupoffse[1] = fpalookup+(getpalookup((long)mulscale16(swal[x+1],globvis),globalshade)<<8);
1710 			palookupoffse[2] = fpalookup+(getpalookup((long)mulscale16(swal[x+2],globvis),globalshade)<<8);
1711 		}
1712 
1713 		u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
1714 		d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
1715 
1716 		if ((bad > 0) || (u4 >= d4))
1717 		{
1718 			if (!(bad&1)) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
1719 			if (!(bad&2)) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
1720 			if (!(bad&4)) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
1721 			if (!(bad&8)) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
1722 			continue;
1723 		}
1724 
1725 		if (u4 > y1ve[0]) vplce[0] = mvlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
1726 		if (u4 > y1ve[1]) vplce[1] = mvlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
1727 		if (u4 > y1ve[2]) vplce[2] = mvlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
1728 		if (u4 > y1ve[3]) vplce[3] = mvlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
1729 
1730 		if (d4 >= u4) mvlineasm4(d4-u4+1,ylookup[u4]+p);
1731 
1732 		i = p+ylookup[d4+1];
1733 		if (y2ve[0] > d4) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
1734 		if (y2ve[1] > d4) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
1735 		if (y2ve[2] > d4) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
1736 		if (y2ve[3] > d4) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
1737 	}
1738 	for(;x<=x2;x++,p++)
1739 	{
1740 		y1ve[0] = max(uwal[x],startumost[x+windowx1]-windowy1);
1741 		y2ve[0] = min(dwal[x],startdmost[x+windowx1]-windowy1);
1742 		if (y2ve[0] <= y1ve[0]) continue;
1743 
1744 		palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
1745 
1746 		bufplce[0] = lwal[x] + globalxpanning;
1747 		if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
1748 		if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
1749 
1750 		vince[0] = swal[x]*globalyscale;
1751 		vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
1752 
1753 		mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],p+ylookup[y1ve[0]]);
1754 	}
1755 	faketimerhandler();
1756 }
1757 
transmaskwallscan(long x1,long x2)1758 transmaskwallscan(long x1, long x2)
1759 {
1760 	long x, startx;
1761 
1762 	setgotpic(globalpicnum);
1763 	if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) return;
1764 
1765 	if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
1766 
1767 	setuptvlineasm(globalshiftval);
1768 
1769 	x = x1;
1770 	while ((startumost[x+windowx1] > startdmost[x+windowx1]) && (x <= x2)) x++;
1771 	if ((x <= x2) && (x&1)) transmaskvline(x), x++;
1772 	while (x < x2) transmaskvline2(x), x += 2;
1773 	while (x <= x2) transmaskvline(x), x++;
1774 	faketimerhandler();
1775 }
1776 
loadboard(char * filename,long * daposx,long * daposy,long * daposz,short * daang,short * dacursectnum)1777 loadboard(char *filename, long *daposx, long *daposy, long *daposz,
1778 			 short *daang, short *dacursectnum)
1779 {
1780 	short fil, i, numsprites;
1781 
1782 	i = strlen(filename)-1;
1783 	if (filename[i] == 255) { filename[i] = 0; i = 1; } else i = 0;
1784 	if ((fil = kopen4load(filename,i)) == -1)
1785 		{ mapversion = 7L; return(-1); }
1786 
1787 	kread(fil,&mapversion,4);
1788 	if (mapversion != 7L) return(-1);
1789 
1790 	initspritelists();
1791 
1792 	clearbuf((long)(&show2dsector[0]),(long)((MAXSECTORS+3)>>5),0L);
1793 	clearbuf((long)(&show2dsprite[0]),(long)((MAXSPRITES+3)>>5),0L);
1794 	clearbuf((long)(&show2dwall[0]),(long)((MAXWALLS+3)>>5),0L);
1795 
1796 	kread(fil,daposx,4);
1797 	kread(fil,daposy,4);
1798 	kread(fil,daposz,4);
1799 	kread(fil,daang,2);
1800 	kread(fil,dacursectnum,2);
1801 
1802 	kread(fil,&numsectors,2);
1803 	kread(fil,&sector[0],sizeof(sectortype)*numsectors);
1804 
1805 	kread(fil,&numwalls,2);
1806 	kread(fil,&wall[0],sizeof(walltype)*numwalls);
1807 
1808 	kread(fil,&numsprites,2);
1809 	kread(fil,&sprite[0],sizeof(spritetype)*numsprites);
1810 
1811 	for(i=0;i<numsprites;i++)
1812 		insertsprite(sprite[i].sectnum,sprite[i].statnum);
1813 
1814 		//Must be after loading sectors, etc!
1815 	updatesector(*daposx,*daposy,dacursectnum);
1816 
1817 	kclose(fil);
1818 	return(0);
1819 }
1820 
saveboard(char * filename,long * daposx,long * daposy,long * daposz,short * daang,short * dacursectnum)1821 saveboard(char *filename, long *daposx, long *daposy, long *daposz,
1822 			 short *daang, short *dacursectnum)
1823 {
1824 	short fil, i, j, numsprites;
1825 
1826 	if ((fil = open(filename,O_BINARY|O_TRUNC|O_CREAT|O_WRONLY,S_IWRITE)) == -1)
1827 		return(-1);
1828 	write(fil,&mapversion,4);
1829 
1830 	write(fil,daposx,4);
1831 	write(fil,daposy,4);
1832 	write(fil,daposz,4);
1833 	write(fil,daang,2);
1834 	write(fil,dacursectnum,2);
1835 
1836 	write(fil,&numsectors,2);
1837 	write(fil,&sector[0],sizeof(sectortype)*numsectors);
1838 
1839 	write(fil,&numwalls,2);
1840 	write(fil,&wall[0],sizeof(walltype)*numwalls);
1841 
1842 	numsprites = 0;
1843 	for(j=0;j<MAXSTATUS;j++)
1844 	{
1845 		i = headspritestat[j];
1846 		while (i != -1)
1847 		{
1848 			numsprites++;
1849 			i = nextspritestat[i];
1850 		}
1851 	}
1852 	write(fil,&numsprites,2);
1853 
1854 	for(j=0;j<MAXSTATUS;j++)
1855 	{
1856 		i = headspritestat[j];
1857 		while (i != -1)
1858 		{
1859 			write(fil,&sprite[i],sizeof(spritetype));
1860 			i = nextspritestat[i];
1861 		}
1862 	}
1863 
1864 	close(fil);
1865 	return(0);
1866 }
1867 
loadtables()1868 loadtables()
1869 {
1870 	long i, fil;
1871 
1872 	if (tablesloaded == 0)
1873 	{
1874 		initksqrt();
1875 
1876 		for(i=0;i<2048;i++) reciptable[i] = divscale30(2048L,i+2048);
1877 
1878 		if ((fil = kopen4load("tables.dat",0)) != -1)
1879 		{
1880 			kread(fil,sintable,2048*2);
1881 			kread(fil,radarang,640*2);
1882 			for(i=0;i<640;i++) radarang[1279-i] = -radarang[i];
1883 			kread(fil,textfont,1024);
1884 			kread(fil,smalltextfont,1024);
1885 			kread(fil,britable,1024);
1886 			kclose(fil);
1887 		}
1888 		tablesloaded = 1;
1889 	}
1890 }
1891 
loadpalette()1892 loadpalette()
1893 {
1894 	long i, j, k, dist, fil;
1895 	char *ptr;
1896 
1897 	if (paletteloaded != 0) return;
1898 	if ((fil = kopen4load("palette.dat",0)) == -1) return;
1899 
1900 	kread(fil,palette,768);
1901 	kread(fil,&numpalookups,2);
1902 
1903 	if ((palookup[0] = (char *)kkmalloc(numpalookups<<8)) == NULL)
1904 		allocache(&palookup[0],numpalookups<<8,&permanentlock);
1905 	if ((transluc = (char *)kkmalloc(65536L)) == NULL)
1906 		allocache(&transluc,65536,&permanentlock);
1907 
1908 	globalpalwritten = palookup[0]; globalpal = 0;
1909 	setpalookupaddress(globalpalwritten);
1910 
1911 	fixtransluscence(FP_OFF(transluc));
1912 
1913 	kread(fil,palookup[globalpal],numpalookups<<8);
1914 	kread(fil,transluc,65536);
1915 	kclose(fil);
1916 
1917 	initfastcolorlookup(30L,59L,11L);
1918 
1919 	paletteloaded = 1;
1920 
1921 	if (vidoption == 6)
1922 	{
1923 		for(k=0;k<MAXPALOOKUPS;k++)
1924 			if (palookup[k] != NULL)
1925 				for(i=0;i<256;i++)
1926 				{
1927 					dist = palette[i*3]*3+palette[i*3+1]*5+palette[i*3+2]*2;
1928 					ptr = (char *)(FP_OFF(palookup[k])+i);
1929 					for(j=0;j<32;j++)
1930 						ptr[j<<8] = (char)min(max(mulscale10(dist,32-j),0),15);
1931 				}
1932 
1933 		if (transluc != NULL)
1934 		{
1935 			for(i=0;i<16;i++)
1936 				for(j=0;j<16;j++)
1937 					transluc[(i<<8)+j] = ((i+j+1)>>1);
1938 		}
1939 	}
1940 }
1941 
1942 static char screenalloctype = 255;
setgamemode(char davidoption,long daxdim,long daydim)1943 setgamemode(char davidoption, long daxdim, long daydim)
1944 {
1945 	long i, j, k, ostereomode;
1946 
1947 	if ((qsetmode == 200) && (vidoption == davidoption) && (xdim == daxdim) && (ydim == daydim))
1948 		return(0);
1949 	vidoption = davidoption; xdim = daxdim; ydim = daydim;
1950 
1951 	strcpy(kensmessage,"!!!! BUILD engine&tools programmed by Ken Silverman of E.G. RI.  (c) Copyright 1995 Ken Silverman.  Summary:  BUILD = Ken. !!!!");
1952 	if (getkensmessagecrc(FP_OFF(kensmessage)) != 0x56c764d4)
1953 		{ setvmode(0x3); printf("Nice try.\n"); exit(0); }
1954 
1955 	ostereomode = stereomode; if (stereomode) uninitstereo();
1956 
1957 	activepage = visualpage = 0;
1958 	switch(vidoption)
1959 	{
1960 		case 1: i = xdim*ydim; break;
1961 		case 2: xdim = 320; ydim = 200; i = xdim*ydim; break;
1962 		case 6: xdim = 320; ydim = 200; i = 131072; break;
1963 		default: return(-1);
1964 	}
1965 	j = ydim*4*sizeof(long);  //Leave room for horizlookup&horizlookup2
1966 
1967 	if (screen != NULL)
1968 	{
1969 		if (screenalloctype == 0) kkfree((void *)screen);
1970 		if (screenalloctype == 1) suckcache((long *)screen);
1971 		screen = NULL;
1972 	}
1973 	screenalloctype = 0;
1974 	if ((screen = (char *)kkmalloc(i+(j<<1))) == NULL)
1975 	{
1976 		 allocache((long *)&screen,i+(j<<1),&permanentlock);
1977 		 screenalloctype = 1;
1978 	}
1979 
1980 	frameplace = FP_OFF(screen);
1981 	horizlookup = (long *)(frameplace+i);
1982 	horizlookup2 = (long *)(frameplace+i+j);
1983 	horizycent = ((ydim*4)>>1);
1984 
1985 	switch(vidoption)
1986 	{
1987 		case 1:
1988 				//bytesperline is set in this function
1989 			if (setvesa(xdim,ydim) < 0) return(-1);
1990 			break;
1991 		case 2:
1992 			horizycent = ((ydim*4)>>1);  //HACK for switching to this mode
1993 		case 6:
1994 			bytesperline = xdim;
1995 			setvmode(0x13);
1996 			break;
1997 		default: return(-1);
1998 	}
1999 
2000 		//Force drawrooms to call dosetaspect & recalculate stuff
2001 	oxyaspect = oxdimen = oviewingrange = -1;
2002 
2003 	setvlinebpl(bytesperline);
2004 	j = 0;
2005 	for(i=0;i<=ydim;i++) ylookup[i] = j, j += bytesperline;
2006 
2007 	numpages = 1;
2008 	if (vidoption == 1) numpages = min(maxpages,8);
2009 
2010 	setview(0L,0L,xdim-1,ydim-1);
2011 	clearallviews(0L);
2012 	setbrightness((char)curbrightness,(char *)&palette[0]);
2013 
2014 	if (searchx < 0) { searchx = halfxdimen; searchy = (ydimen>>1); }
2015 
2016 	if (ostereomode) initstereo();
2017 
2018 	qsetmode = 200;
2019 	return(0);
2020 }
2021 
2022 
hline(long xr,long yp)2023 hline (long xr, long yp)
2024 {
2025 	long xl, r;
2026 
2027 	xl = lastx[yp]; if (xl > xr) return;
2028 	r = horizlookup2[yp-globalhoriz+horizycent];
2029 	asm1 = globalx1*r;
2030 	asm2 = globaly2*r;
2031 	hlineasm4(xr-xl,0L,((long)getpalookup((long)mulscale16(r,globvis),globalshade)<<8),
2032 		globalx2*r+globalypanning,globaly1*r+globalxpanning,
2033 		ylookup[yp]+xr+frameoffset);
2034 }
2035 
slowhline(long xr,long yp)2036 slowhline (long xr, long yp)
2037 {
2038 	long xl, x, y, ox, oy, r, p, shade;
2039 
2040 	xl = lastx[yp]; if (xl > xr) return;
2041 	r = horizlookup2[yp-globalhoriz+horizycent];
2042 	asm1 = globalx1*r;
2043 	asm2 = globaly2*r;
2044 
2045 	asm3 = (long)globalpalwritten + ((long)getpalookup((long)mulscale16(r,globvis),globalshade)<<8);
2046 	if (!(globalorientation&256))
2047 	{
2048 		mhline(globalbufplc,globaly1*r+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,
2049 			globalx2*r+globalypanning-asm2*(xr-xl),ylookup[yp]+xl+frameoffset);
2050 		return;
2051 	}
2052 	thline(globalbufplc,globaly1*r+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,
2053 		globalx2*r+globalypanning-asm2*(xr-xl),ylookup[yp]+xl+frameoffset);
2054 	transarea += (xr-xl);
2055 }
2056 
transmaskvline(long x)2057 transmaskvline (long x)
2058 {
2059 	long vplc, vinc, p, i, palookupoffs, shade, bufplc;
2060 	short y1v, y2v;
2061 
2062 	if ((x < 0) || (x >= xdimen)) return;
2063 
2064 	y1v = max(uwall[x],startumost[x+windowx1]-windowy1);
2065 	y2v = min(dwall[x],startdmost[x+windowx1]-windowy1);
2066 	y2v--;
2067 	if (y2v < y1v) return;
2068 
2069 	palookupoffs = FP_OFF(palookup[globalpal]) + (getpalookup((long)mulscale16(swall[x],globvis),globalshade)<<8);
2070 
2071 	vinc = swall[x]*globalyscale;
2072 	vplc = globalzd + vinc*(y1v-globalhoriz+1);
2073 
2074 	i = lwall[x]+globalxpanning;
2075 	if (i >= tilesizx[globalpicnum]) i %= tilesizx[globalpicnum];
2076 	bufplc = waloff[globalpicnum]+i*tilesizy[globalpicnum];
2077 
2078 	p = ylookup[y1v]+x+frameoffset;
2079 
2080 	tvlineasm1(vinc,palookupoffs,y2v-y1v,vplc,bufplc,p);
2081 
2082 	transarea += y2v-y1v;
2083 }
2084 
transmaskvline2(long x)2085 transmaskvline2 (long x)
2086 {
2087 	long i, y1, y2, x2;
2088 	short y1ve[2], y2ve[2];
2089 
2090 	if ((x < 0) || (x >= xdimen)) return;
2091 	if (x == xdimen-1) { transmaskvline(x); return; }
2092 
2093 	x2 = x+1;
2094 
2095 	y1ve[0] = max(uwall[x],startumost[x+windowx1]-windowy1);
2096 	y2ve[0] = min(dwall[x],startdmost[x+windowx1]-windowy1)-1;
2097 	if (y2ve[0] < y1ve[0]) { transmaskvline(x2); return; }
2098 	y1ve[1] = max(uwall[x2],startumost[x2+windowx1]-windowy1);
2099 	y2ve[1] = min(dwall[x2],startdmost[x2+windowx1]-windowy1)-1;
2100 	if (y2ve[1] < y1ve[1]) { transmaskvline(x); return; }
2101 
2102 	palookupoffse[0] = FP_OFF(palookup[globalpal]) + (getpalookup((long)mulscale16(swall[x],globvis),globalshade)<<8);
2103 	palookupoffse[1] = FP_OFF(palookup[globalpal]) + (getpalookup((long)mulscale16(swall[x2],globvis),globalshade)<<8);
2104 
2105 	setuptvlineasm2(globalshiftval,palookupoffse[0],palookupoffse[1]);
2106 
2107 	vince[0] = swall[x]*globalyscale;
2108 	vince[1] = swall[x2]*globalyscale;
2109 	vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
2110 	vplce[1] = globalzd + vince[1]*(y1ve[1]-globalhoriz+1);
2111 
2112 	i = lwall[x] + globalxpanning;
2113 	if (i >= tilesizx[globalpicnum]) i %= tilesizx[globalpicnum];
2114 	bufplce[0] = waloff[globalpicnum]+i*tilesizy[globalpicnum];
2115 
2116 	i = lwall[x2] + globalxpanning;
2117 	if (i >= tilesizx[globalpicnum]) i %= tilesizx[globalpicnum];
2118 	bufplce[1] = waloff[globalpicnum]+i*tilesizy[globalpicnum];
2119 
2120 	y1 = max(y1ve[0],y1ve[1]);
2121 	y2 = min(y2ve[0],y2ve[1]);
2122 
2123 	i = x+frameoffset;
2124 
2125 	if (y1ve[0] != y1ve[1])
2126 	{
2127 		if (y1ve[0] < y1)
2128 			vplce[0] = tvlineasm1(vince[0],palookupoffse[0],y1-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+i);
2129 		else
2130 			vplce[1] = tvlineasm1(vince[1],palookupoffse[1],y1-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+i+1);
2131 	}
2132 
2133 	if (y2 > y1)
2134 	{
2135 		asm1 = vince[1];
2136 		asm2 = ylookup[y2]+i+1;
2137 		tvlineasm2(vplce[1],vince[0],bufplce[0],bufplce[1],vplce[0],ylookup[y1]+i);
2138 		transarea += ((y2-y1)<<1);
2139 	}
2140 	else
2141 	{
2142 		asm1 = vplce[0];
2143 		asm2 = vplce[1];
2144 	}
2145 
2146 	if (y2ve[0] > y2ve[1])
2147 		tvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y2-1,asm1,bufplce[0],ylookup[y2+1]+i);
2148 	else if (y2ve[0] < y2ve[1])
2149 		tvlineasm1(vince[1],palookupoffse[1],y2ve[1]-y2-1,asm2,bufplce[1],ylookup[y2+1]+i+1);
2150 
2151 	faketimerhandler();
2152 }
2153 
initengine()2154 initengine()
2155 {
2156 	long i, j;
2157 
2158 	loadtables();
2159 
2160 	xyaspect = -1;
2161 
2162 	pskyoff[0] = 0; pskybits = 0;
2163 
2164 	parallaxtype = 2; parallaxyoffs = 0L; parallaxyscale = 65536;
2165 	showinvisibility = 0;
2166 
2167 #ifdef SUPERBUILD
2168 	for(i=1;i<1024;i++) lowrecip[i] = ((1<<24)-1)/i;
2169 	for(i=0;i<MAXVOXELS;i++)
2170 		for(j=0;j<MAXVOXMIPS;j++)
2171 		{
2172 			voxoff[i][j] = 0L;
2173 			voxlock[i][j] = 200;
2174 		}
2175 #endif
2176 
2177 	paletteloaded = 0;
2178 
2179 	searchit = 0; searchstat = -1;
2180 
2181 	for(i=0;i<MAXPALOOKUPS;i++) palookup[i] = NULL;
2182 
2183 	clearbuf((long)(&waloff[0]),(long)MAXTILES,0L);
2184 
2185 	clearbuf((long)(&show2dsector[0]),(long)((MAXSECTORS+3)>>5),0L);
2186 	clearbuf((long)(&show2dsprite[0]),(long)((MAXSPRITES+3)>>5),0L);
2187 	clearbuf((long)(&show2dwall[0]),(long)((MAXWALLS+3)>>5),0L);
2188 	automapping = 0;
2189 
2190 	validmodecnt = 0;
2191 
2192 	pointhighlight = -1;
2193 	linehighlight = -1;
2194 	highlightcnt = 0;
2195 
2196 	totalclock = 0;
2197 	visibility = 512;
2198 	parallaxvisibility = 512;
2199 
2200 	loadpalette();
2201 }
2202 
uninitengine()2203 uninitengine()
2204 {
2205 	long i;
2206 
2207 	if (vidoption == 1) uninitvesa();
2208 	if (artfil != -1) kclose(artfil);
2209 
2210 	if (transluc != NULL) { kkfree(transluc); transluc = NULL; }
2211 	if (pic != NULL) { kkfree(pic); pic = NULL; }
2212 	if (screen != NULL)
2213 	{
2214 		if (screenalloctype == 0) kkfree((void *)screen);
2215 		//if (screenalloctype == 1) suckcache(screen);  //Cache already gone
2216 		screen = NULL;
2217 	}
2218 	for(i=0;i<MAXPALOOKUPS;i++)
2219 		if (palookup[i] != NULL) { kkfree(palookup[i]); palookup[i] = NULL; }
2220 }
2221 
nextpage()2222 nextpage()
2223 {
2224 	long totbytes, i, j, k;
2225 	permfifotype *per;
2226 
2227 	//char snotbuf[32];
2228 	//j = 0; k = 0;
2229 	//for(i=0;i<4096;i++)
2230 	//   if (waloff[i] != 0)
2231 	//   {
2232 	//      sprintf(snotbuf,"%ld-%ld",i,tilesizx[i]*tilesizy[i]);
2233 	//      printext256((j>>5)*40+32,(j&31)*6,walock[i]>>3,-1,snotbuf,1);
2234 	//      k += tilesizx[i]*tilesizy[i];
2235 	//      j++;
2236 	//   }
2237 	//sprintf(snotbuf,"Total: %ld",k);
2238 	//printext256((j>>5)*40+32,(j&31)*6,31,-1,snotbuf,1);
2239 
2240 	switch(qsetmode)
2241 	{
2242 		case 200:
2243 			for(i=permtail;i!=permhead;i=((i+1)&(MAXPERMS-1)))
2244 			{
2245 				per = &permfifo[i];
2246 				if ((per->pagesleft > 0) && (per->pagesleft <= numpages))
2247 					dorotatesprite(per->sx,per->sy,per->z,per->a,per->picnum,
2248 										per->dashade,per->dapalnum,per->dastat,
2249 										per->cx1,per->cy1,per->cx2,per->cy2);
2250 			}
2251 
2252 			switch(vidoption)
2253 			{
2254 				case 1:
2255 					if (stereomode)
2256 					{
2257 						stereonextpage();
2258 						if (!origbuffermode)
2259 						{
2260 							buffermode = 0;
2261 							transarea = 0;
2262 							totalarea = 0;
2263 						}
2264 					}
2265 					else
2266 					{
2267 						visualpage = activepage;
2268 						setvisualpage(visualpage);
2269 						if (!origbuffermode)
2270 						{
2271 							buffermode = ((transarea<<3) > totalarea);
2272 							transarea = 0;
2273 							totalarea = 0;
2274 						}
2275 						activepage++; if (activepage >= numpages) activepage = 0;
2276 						setactivepage(activepage);
2277 					}
2278 					break;
2279 				case 2:
2280 					copybuf(frameplace,0xa0000,64000>>2);
2281 					break;
2282 				case 6:
2283 					if (!activepage) redblueblit(screen,&screen[65536],64000L);
2284 					activepage ^= 1;
2285 					break;
2286 			}
2287 
2288 
2289 			for(i=permtail;i!=permhead;i=((i+1)&(MAXPERMS-1)))
2290 			{
2291 				per = &permfifo[i];
2292 				if (per->pagesleft >= 130)
2293 					dorotatesprite(per->sx,per->sy,per->z,per->a,per->picnum,
2294 										per->dashade,per->dapalnum,per->dastat,
2295 										per->cx1,per->cy1,per->cx2,per->cy2);
2296 
2297 				if (per->pagesleft&127) per->pagesleft--;
2298 				if (((per->pagesleft&127) == 0) && (i == permtail))
2299 					permtail = ((permtail+1)&(MAXPERMS-1));
2300 			}
2301 			break;
2302 
2303 		case 350:
2304 			koutpw(0x3d4,0xc+((pageoffset>>11)<<8));
2305 			limitrate();
2306 			pageoffset = 225280-pageoffset; //225280 is 352(multiple of 16)*640
2307 			break;
2308 
2309 		case 480:
2310 			koutpw(0x3d4,0xc+((pageoffset>>11)<<8));
2311 			limitrate();
2312 			pageoffset = 399360-pageoffset;
2313 			break;
2314 	}
2315 	faketimerhandler();
2316 
2317 	if ((totalclock >= lastageclock+8) || (totalclock < lastageclock))
2318 		{ lastageclock = totalclock; agecache(); }
2319 
2320 	beforedrawrooms = 1;
2321 	numframes++;
2322 }
2323 
2324 char cachedebug = 0;
loadtile(short tilenume)2325 loadtile (short tilenume)
2326 {
2327 	char *ptr;
2328 	long i, dasiz;
2329 
2330 	if ((unsigned)tilenume >= (unsigned)MAXTILES) return;
2331 	dasiz = tilesizx[tilenume]*tilesizy[tilenume];
2332 	if (dasiz <= 0) return;
2333 
2334 	i = tilefilenum[tilenume];
2335 	if (i != artfilnum)
2336 	{
2337 		if (artfil != -1) kclose(artfil);
2338 		artfilnum = i;
2339 		artfilplc = 0L;
2340 
2341 		artfilename[7] = (i%10)+48;
2342 		artfilename[6] = ((i/10)%10)+48;
2343 		artfilename[5] = ((i/100)%10)+48;
2344 		artfil = kopen4load(artfilename,0);
2345 		faketimerhandler();
2346 	}
2347 
2348 	if (cachedebug) printf("Tile:%ld\n",tilenume);
2349 
2350 	if (waloff[tilenume] == 0)
2351 	{
2352 		walock[tilenume] = 199;
2353 		allocache(&waloff[tilenume],dasiz,&walock[tilenume]);
2354 	}
2355 
2356 	if (artfilplc != tilefileoffs[tilenume])
2357 	{
2358 		klseek(artfil,tilefileoffs[tilenume]-artfilplc,SEEK_CUR);
2359 		faketimerhandler();
2360 	}
2361 	ptr = (char *)waloff[tilenume];
2362 	kread(artfil,ptr,dasiz);
2363 	faketimerhandler();
2364 	artfilplc = tilefileoffs[tilenume]+dasiz;
2365 }
2366 
allocatepermanenttile(short tilenume,long xsiz,long ysiz)2367 allocatepermanenttile(short tilenume, long xsiz, long ysiz)
2368 {
2369 	long i, j, x, y, dasiz;
2370 
2371 	if ((xsiz <= 0) || (ysiz <= 0) || ((unsigned)tilenume >= (unsigned)MAXTILES))
2372 		return(0);
2373 
2374 	dasiz = xsiz*ysiz;
2375 
2376 	walock[tilenume] = 255;
2377 	allocache(&waloff[tilenume],dasiz,&walock[tilenume]);
2378 
2379 	tilesizx[tilenume] = xsiz;
2380 	tilesizy[tilenume] = ysiz;
2381 	picanm[tilenume] = 0;
2382 
2383 	j = 15; while ((j > 1) && (pow2long[j] > xsiz)) j--;
2384 	picsiz[tilenume] = ((char)j);
2385 	j = 15; while ((j > 1) && (pow2long[j] > ysiz)) j--;
2386 	picsiz[tilenume] += ((char)(j<<4));
2387 
2388 	return(waloff[tilenume]);
2389 }
2390 
loadpics(char * filename)2391 loadpics(char *filename)
2392 {
2393 	long offscount, siz, localtilestart, localtileend, dasiz;
2394 	short fil, i, j, k;
2395 
2396 	strcpy(artfilename,filename);
2397 
2398 	for(i=0;i<MAXTILES;i++)
2399 	{
2400 		tilesizx[i] = 0;
2401 		tilesizy[i] = 0;
2402 		picanm[i] = 0L;
2403 	}
2404 
2405 	artsize = 0L;
2406 
2407 	numtilefiles = 0;
2408 	do
2409 	{
2410 		k = numtilefiles;
2411 
2412 		artfilename[7] = (k%10)+48;
2413 		artfilename[6] = ((k/10)%10)+48;
2414 		artfilename[5] = ((k/100)%10)+48;
2415 		if ((fil = kopen4load(artfilename,0)) != -1)
2416 		{
2417 			kread(fil,&artversion,4);
2418 			if (artversion != 1) return(-1);
2419 			kread(fil,&numtiles,4);
2420 			kread(fil,&localtilestart,4);
2421 			kread(fil,&localtileend,4);
2422 			kread(fil,&tilesizx[localtilestart],(localtileend-localtilestart+1)<<1);
2423 			kread(fil,&tilesizy[localtilestart],(localtileend-localtilestart+1)<<1);
2424 			kread(fil,&picanm[localtilestart],(localtileend-localtilestart+1)<<2);
2425 
2426 			offscount = 4+4+4+4+((localtileend-localtilestart+1)<<3);
2427 			for(i=localtilestart;i<=localtileend;i++)
2428 			{
2429 				tilefilenum[i] = k;
2430 				tilefileoffs[i] = offscount;
2431 				dasiz = (long)(tilesizx[i]*tilesizy[i]);
2432 				offscount += dasiz;
2433 				artsize += ((dasiz+15)&0xfffffff0);
2434 			}
2435 			kclose(fil);
2436 
2437 			numtilefiles++;
2438 		}
2439 	}
2440 	while (k != numtilefiles);
2441 
2442 	clearbuf((long)(&gotpic[0]),(long)((MAXTILES+31)>>5),0L);
2443 
2444 	//try dpmi_DETERMINEMAXREALALLOC!
2445 
2446 	cachesize = max(artsize,1048576);
2447 	while ((pic = (char *)kkmalloc(cachesize)) == NULL)
2448 	{
2449 		cachesize -= 65536L;
2450 		if (cachesize < 65536) return(-1);
2451 	}
2452 	initcache((FP_OFF(pic)+15)&0xfffffff0,(cachesize-((-FP_OFF(pic))&15))&0xfffffff0);
2453 
2454 	for(i=0;i<MAXTILES;i++)
2455 	{
2456 		j = 15;
2457 		while ((j > 1) && (pow2long[j] > tilesizx[i])) j--;
2458 		picsiz[i] = ((char)j);
2459 		j = 15;
2460 		while ((j > 1) && (pow2long[j] > tilesizy[i])) j--;
2461 		picsiz[i] += ((char)(j<<4));
2462 	}
2463 
2464 	artfil = -1;
2465 	artfilnum = -1;
2466 	artfilplc = 0L;
2467 
2468 	return(0);
2469 }
2470 
2471 #ifdef SUPERBUILD
qloadkvx(long voxindex,char * filename)2472 qloadkvx(long voxindex, char *filename)
2473 {
2474 	long i, fil, dasiz, lengcnt, lengtot;
2475 	char *ptr;
2476 
2477 	if ((fil = kopen4load(filename,0)) == -1) return;
2478 
2479 	lengcnt = 0;
2480 	lengtot = kfilelength(fil);
2481 
2482 	for(i=0;i<MAXVOXMIPS;i++)
2483 	{
2484 		kread(fil,&dasiz,4);
2485 			//Must store filenames to use cacheing system :(
2486 		voxlock[voxindex][i] = 200;
2487 		allocache(&voxoff[voxindex][i],dasiz,&voxlock[voxindex][i]);
2488 		ptr = (char *)voxoff[voxindex][i];
2489 		kread(fil,ptr,dasiz);
2490 
2491 		lengcnt += dasiz+4;
2492 		if (lengcnt >= lengtot-768) break;
2493 	}
2494 	kclose(fil);
2495 }
2496 #endif
2497 
clipinsidebox(long x,long y,short wallnum,long walldist)2498 clipinsidebox(long x, long y, short wallnum, long walldist)
2499 {
2500 	walltype *wal;
2501 	long x1, y1, x2, y2, r;
2502 
2503 	r = (walldist<<1);
2504 	wal = &wall[wallnum];     x1 = wal->x+walldist-x; y1 = wal->y+walldist-y;
2505 	wal = &wall[wal->point2]; x2 = wal->x+walldist-x; y2 = wal->y+walldist-y;
2506 
2507 	if ((x1 < 0) && (x2 < 0)) return(0);
2508 	if ((y1 < 0) && (y2 < 0)) return(0);
2509 	if ((x1 >= r) && (x2 >= r)) return(0);
2510 	if ((y1 >= r) && (y2 >= r)) return(0);
2511 
2512 	x2 -= x1; y2 -= y1;
2513 	if (x2*(walldist-y1) >= y2*(walldist-x1))  //Front
2514 	{
2515 		if (x2 > 0) x2 *= (0-y1); else x2 *= (r-y1);
2516 		if (y2 > 0) y2 *= (r-x1); else y2 *= (0-x1);
2517 		return(x2 < y2);
2518 	}
2519 	if (x2 > 0) x2 *= (r-y1); else x2 *= (0-y1);
2520 	if (y2 > 0) y2 *= (0-x1); else y2 *= (r-x1);
2521 	return((x2 >= y2)<<1);
2522 }
2523 
clipinsideboxline(long x,long y,long x1,long y1,long x2,long y2,long walldist)2524 clipinsideboxline(long x, long y, long x1, long y1, long x2, long y2, long walldist)
2525 {
2526 	long r;
2527 
2528 	r = (walldist<<1);
2529 
2530 	x1 += walldist-x; x2 += walldist-x;
2531 	if ((x1 < 0) && (x2 < 0)) return(0);
2532 	if ((x1 >= r) && (x2 >= r)) return(0);
2533 
2534 	y1 += walldist-y; y2 += walldist-y;
2535 	if ((y1 < 0) && (y2 < 0)) return(0);
2536 	if ((y1 >= r) && (y2 >= r)) return(0);
2537 
2538 	x2 -= x1; y2 -= y1;
2539 	if (x2*(walldist-y1) >= y2*(walldist-x1))  //Front
2540 	{
2541 		if (x2 > 0) x2 *= (0-y1); else x2 *= (r-y1);
2542 		if (y2 > 0) y2 *= (r-x1); else y2 *= (0-x1);
2543 		return(x2 < y2);
2544 	}
2545 	if (x2 > 0) x2 *= (r-y1); else x2 *= (0-y1);
2546 	if (y2 > 0) y2 *= (0-x1); else y2 *= (r-x1);
2547 	return((x2 >= y2)<<1);
2548 }
2549 
readpixel16(long p)2550 readpixel16(long p)
2551 {
2552 	long mask, dat;
2553 
2554 	mask = pow2long[p&7^7];
2555 
2556 	if ((qsetmode == 480) && (ydim16 <= 336) && (p >= 640*336))
2557 		p -= 640*336;
2558 	else
2559 		p += pageoffset;
2560 
2561 	p >>= 3;
2562 
2563 	koutp(0x3ce,0x4);
2564 	koutp(0x3cf,0); dat = ((readpixel(p+0xa0000)&mask)>0);
2565 	koutp(0x3cf,1); dat += (((readpixel(p+0xa0000)&mask)>0)<<1);
2566 	koutp(0x3cf,2); dat += (((readpixel(p+0xa0000)&mask)>0)<<2);
2567 	koutp(0x3cf,3); dat += (((readpixel(p+0xa0000)&mask)>0)<<3);
2568 	return(dat);
2569 }
2570 
screencapture(char * filename,char inverseit)2571 screencapture(char *filename, char inverseit)
2572 {
2573 	char *ptr;
2574 	long fil, i, bufplc, p, col, ncol, leng, numbytes, xres;
2575 
2576 	filename[4] = ((capturecount/1000)%10)+48;
2577 	filename[5] = ((capturecount/100)%10)+48;
2578 	filename[6] = ((capturecount/10)%10)+48;
2579 	filename[7] = (capturecount%10)+48;
2580 	if ((fil=open(filename,O_BINARY|O_CREAT|O_TRUNC|O_WRONLY,S_IWRITE))==-1)
2581 		return(-1);
2582 
2583 	if (qsetmode == 200)
2584 	{
2585 		pcxheader[8] = ((xdim-1)&255); pcxheader[9] = (((xdim-1)>>8)&255);
2586 		pcxheader[10] = ((ydim-1)&255); pcxheader[11] = (((ydim-1)>>8)&255);
2587 		pcxheader[12] = (xdim&255); pcxheader[13] = ((xdim>>8)&255);
2588 		pcxheader[14] = (ydim&255); pcxheader[15] = ((ydim>>8)&255);
2589 		pcxheader[66] = (xdim&255); pcxheader[67] = ((xdim>>8)&255);
2590 	}
2591 	else
2592 	{
2593 		pcxheader[8] = ((640-1)&255); pcxheader[9] = (((640-1)>>8)&255);
2594 		pcxheader[10] = ((qsetmode-1)&255); pcxheader[11] = (((qsetmode-1)>>8)&255);
2595 		pcxheader[12] = (640&255); pcxheader[13] = ((640>>8)&255);
2596 		pcxheader[14] = (qsetmode&255); pcxheader[15] = ((qsetmode>>8)&255);
2597 		pcxheader[66] = (640&255); pcxheader[67] = ((640>>8)&255);
2598 	}
2599 
2600 	write(fil,&pcxheader[0],128);
2601 
2602 	if (qsetmode == 200)
2603 	{
2604 		ptr = (char *)frameplace;
2605 		numbytes = xdim*ydim;
2606 		xres = xdim;
2607 	}
2608 	else
2609 	{
2610 		numbytes = (mul5(qsetmode)<<7);
2611 		xres = 640;
2612 	}
2613 
2614 	bufplc = 0; p = 0;
2615 	while (p < numbytes)
2616 	{
2617 		koutp(97,kinp(97)|3);
2618 
2619 		if (qsetmode == 200) { col = *ptr; p++; ptr++; }
2620 		else
2621 		{
2622 			col = readpixel16(p);
2623 			p++;
2624 			if ((inverseit == 1) && (((col&7) == 0) || ((col&7) == 7))) col ^= 15;
2625 		}
2626 
2627 		leng = 1;
2628 
2629 		if (qsetmode == 200) ncol = *ptr;
2630 		else
2631 		{
2632 			ncol = readpixel16(p);
2633 			if ((inverseit == 1) && (((ncol&7) == 0) || ((ncol&7) == 7))) ncol ^= 15;
2634 		}
2635 
2636 		while ((ncol == col) && (p < numbytes) && (leng < 63) && ((p%xres) != 0))
2637 		{
2638 			leng++;
2639 
2640 			if (qsetmode == 200) { p++; ptr++; ncol = *ptr; }
2641 			else
2642 			{
2643 				p++;
2644 				ncol = readpixel16(p);
2645 				if ((inverseit == 1) && (((ncol&7) == 0) || ((ncol&7) == 7))) ncol ^= 15;
2646 			}
2647 		}
2648 
2649 		koutp(97,kinp(97)&252);
2650 
2651 		if ((leng > 1) || (col >= 0xc0))
2652 		{
2653 			tempbuf[bufplc++] = (leng|0xc0);
2654 			if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
2655 		}
2656 		tempbuf[bufplc++] = col;
2657 		if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
2658 	}
2659 
2660 	tempbuf[bufplc++] = 0xc;
2661 	if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
2662 
2663 	if (qsetmode == 200)
2664 	{
2665 		VBE_getPalette(0,256,&tempbuf[4096]);
2666 		for(i=0;i<256;i++)
2667 		{
2668 			tempbuf[bufplc++] = (tempbuf[(i<<2)+4096+2]<<2);
2669 			if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
2670 			tempbuf[bufplc++] = (tempbuf[(i<<2)+4096+1]<<2);
2671 			if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
2672 			tempbuf[bufplc++] = (tempbuf[(i<<2)+4096+0]<<2);
2673 			if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
2674 		}
2675 	}
2676 	else
2677 	{
2678 		for(i=0;i<768;i++)
2679 		{
2680 			if (i < 48)
2681 				tempbuf[bufplc++] = (vgapal16[i]<<2);
2682 			else
2683 				tempbuf[bufplc++] = 0;
2684 			if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
2685 		}
2686 
2687 	}
2688 
2689 	if (bufplc > 0)
2690 		if (write(fil,&tempbuf[0],bufplc) < bufplc) { close(fil); return(-1); }
2691 
2692 	close(fil);
2693 	capturecount++;
2694 	return(0);
2695 }
2696 
inside(long x,long y,short sectnum)2697 inside (long x, long y, short sectnum)
2698 {
2699 	walltype *wal;
2700 	long i, x1, y1, x2, y2;
2701 	unsigned long cnt;
2702 
2703 	if ((sectnum < 0) || (sectnum >= numsectors)) return(-1);
2704 
2705 	cnt = 0;
2706 	wal = &wall[sector[sectnum].wallptr];
2707 	i = sector[sectnum].wallnum;
2708 	do
2709 	{
2710 		y1 = wal->y-y; y2 = wall[wal->point2].y-y;
2711 		if ((y1^y2) < 0)
2712 		{
2713 			x1 = wal->x-x; x2 = wall[wal->point2].x-x;
2714 			if ((x1^x2) >= 0) cnt ^= x1; else cnt ^= (x1*y2-x2*y1)^y2;
2715 		}
2716 		wal++; i--;
2717 	} while (i);
2718 	return(cnt>>31);
2719 }
2720 
getangle(long xvect,long yvect)2721 getangle(long xvect, long yvect)
2722 {
2723 	if ((xvect|yvect) == 0) return(0);
2724 	if (xvect == 0) return(512+((yvect<0)<<10));
2725 	if (yvect == 0) return(((xvect<0)<<10));
2726 	if (xvect == yvect) return(256+((xvect<0)<<10));
2727 	if (xvect == -yvect) return(768+((xvect>0)<<10));
2728 	if (klabs(xvect) > klabs(yvect))
2729 		return(((radarang[640+scale(160,yvect,xvect)]>>6)+((xvect<0)<<10))&2047);
2730 	return(((radarang[640-scale(160,xvect,yvect)]>>6)+512+((yvect<0)<<10))&2047);
2731 }
2732 
ksqrt(long num)2733 ksqrt(long num)
2734 {
2735 	return(nsqrtasm(num));
2736 }
2737 
krecip(long num)2738 krecip(long num)
2739 {
2740 	return(krecipasm(num));
2741 }
2742 
initksqrt()2743 initksqrt()
2744 {
2745 	long i, j, k;
2746 
2747 	j = 1; k = 0;
2748 	for(i=0;i<4096;i++)
2749 	{
2750 		if (i >= j) { j <<= 2; k++; }
2751 		sqrtable[i] = (unsigned short)(msqrtasm((i<<18)+131072)<<1);
2752 		shlookup[i] = (k<<1)+((10-k)<<8);
2753 		if (i < 256) shlookup[i+4096] = ((k+6)<<1)+((10-(k+6))<<8);
2754 	}
2755 }
2756 
copytilepiece(long tilenume1,long sx1,long sy1,long xsiz,long ysiz,long tilenume2,long sx2,long sy2)2757 copytilepiece(long tilenume1, long sx1, long sy1, long xsiz, long ysiz,
2758 				  long tilenume2, long sx2, long sy2)
2759 {
2760 	char *ptr1, *ptr2, dat;
2761 	long xsiz1, ysiz1, xsiz2, ysiz2, i, j, x1, y1, x2, y2;
2762 
2763 	xsiz1 = tilesizx[tilenume1]; ysiz1 = tilesizy[tilenume1];
2764 	xsiz2 = tilesizx[tilenume2]; ysiz2 = tilesizy[tilenume2];
2765 	if ((xsiz1 > 0) && (ysiz1 > 0) && (xsiz2 > 0) && (ysiz2 > 0))
2766 	{
2767 		if (waloff[tilenume1] == 0) loadtile(tilenume1);
2768 		if (waloff[tilenume2] == 0) loadtile(tilenume2);
2769 
2770 		x1 = sx1;
2771 		for(i=0;i<xsiz;i++)
2772 		{
2773 			y1 = sy1;
2774 			for(j=0;j<ysiz;j++)
2775 			{
2776 				x2 = sx2+i;
2777 				y2 = sy2+j;
2778 				if ((x2 >= 0) && (y2 >= 0) && (x2 < xsiz2) && (y2 < ysiz2))
2779 				{
2780 					ptr1 = (char *)(waloff[tilenume1] + x1*ysiz1 + y1);
2781 					ptr2 = (char *)(waloff[tilenume2] + x2*ysiz2 + y2);
2782 					dat = *ptr1;
2783 					if (dat != 255)
2784 						*ptr2 = *ptr1;
2785 				}
2786 
2787 				y1++; if (y1 >= ysiz1) y1 = 0;
2788 			}
2789 			x1++; if (x1 >= xsiz1) x1 = 0;
2790 		}
2791 	}
2792 }
2793 
drawmasks()2794 drawmasks()
2795 {
2796 	long i, j, k, l, gap, xs, ys, zs, xp, yp, zp, z1, z2, yoff, yspan;
2797 
2798 	for(i=spritesortcnt-1;i>=0;i--) tspriteptr[i] = &tsprite[i];
2799 	for(i=spritesortcnt-1;i>=0;i--)
2800 	{
2801 		xs = tspriteptr[i]->x-globalposx; ys = tspriteptr[i]->y-globalposy;
2802 		yp = dmulscale6(xs,cosviewingrangeglobalang,ys,sinviewingrangeglobalang);
2803 		if (yp > (4<<8))
2804 		{
2805 			xp = dmulscale6(ys,cosglobalang,-xs,singlobalang);
2806 			spritesx[i] = scale(xp+yp,xdimen<<7,yp);
2807 		}
2808 		else if ((tspriteptr[i]->cstat&48) == 0)
2809 		{
2810 			spritesortcnt--;  //Delete face sprite if on wrong side!
2811 			if (i != spritesortcnt)
2812 			{
2813 				tspriteptr[i] = tspriteptr[spritesortcnt];
2814 				spritesx[i] = spritesx[spritesortcnt];
2815 				spritesy[i] = spritesy[spritesortcnt];
2816 			}
2817 			continue;
2818 		}
2819 		spritesy[i] = yp;
2820 	}
2821 
2822 	gap = 1; while (gap < spritesortcnt) gap = (gap<<1)+1;
2823 	for(gap>>=1;gap>0;gap>>=1)      //Sort sprite list
2824 		for(i=0;i<spritesortcnt-gap;i++)
2825 			for(l=i;l>=0;l-=gap)
2826 			{
2827 				if (spritesy[l] <= spritesy[l+gap]) break;
2828 				swaplong(&tspriteptr[l],&tspriteptr[l+gap]);
2829 				swaplong(&spritesx[l],&spritesx[l+gap]);
2830 				swaplong(&spritesy[l],&spritesy[l+gap]);
2831 			}
2832 
2833 	if (spritesortcnt > 0)
2834 		spritesy[spritesortcnt] = (spritesy[spritesortcnt-1]^1);
2835 
2836 	ys = spritesy[0]; i = 0;
2837 	for(j=1;j<=spritesortcnt;j++)
2838 	{
2839 		if (spritesy[j] == ys) continue;
2840 		ys = spritesy[j];
2841 		if (j > i+1)
2842 		{
2843 			for(k=i;k<j;k++)
2844 			{
2845 				spritesz[k] = tspriteptr[k]->z;
2846 				if ((tspriteptr[k]->cstat&48) != 32)
2847 				{
2848 					yoff = (long)((signed char)((picanm[tspriteptr[k]->picnum]>>16)&255))+((long)tspriteptr[k]->yoffset);
2849 					spritesz[k] -= ((yoff*tspriteptr[k]->yrepeat)<<2);
2850 					yspan = (tilesizy[tspriteptr[k]->picnum]*tspriteptr[k]->yrepeat<<2);
2851 					if (!(tspriteptr[k]->cstat&128)) spritesz[k] -= (yspan>>1);
2852 					if (klabs(spritesz[k]-globalposz) < (yspan>>1)) spritesz[k] = globalposz;
2853 				}
2854 			}
2855 			for(k=i+1;k<j;k++)
2856 				for(l=i;l<k;l++)
2857 					if (klabs(spritesz[k]-globalposz) < klabs(spritesz[l]-globalposz))
2858 					{
2859 						swaplong(&tspriteptr[k],&tspriteptr[l]);
2860 						swaplong(&spritesx[k],&spritesx[l]);
2861 						swaplong(&spritesy[k],&spritesy[l]);
2862 						swaplong(&spritesz[k],&spritesz[l]);
2863 					}
2864 			for(k=i+1;k<j;k++)
2865 				for(l=i;l<k;l++)
2866 					if (tspriteptr[k]->statnum < tspriteptr[l]->statnum)
2867 					{
2868 						swaplong(&tspriteptr[k],&tspriteptr[l]);
2869 						swaplong(&spritesx[k],&spritesx[l]);
2870 						swaplong(&spritesy[k],&spritesy[l]);
2871 					}
2872 		}
2873 		i = j;
2874 	}
2875 
2876 	/*for(i=spritesortcnt-1;i>=0;i--)
2877 	{
2878 		xs = tspriteptr[i].x-globalposx;
2879 		ys = tspriteptr[i].y-globalposy;
2880 		zs = tspriteptr[i].z-globalposz;
2881 
2882 		xp = ys*cosglobalang-xs*singlobalang;
2883 		yp = (zs<<1);
2884 		zp = xs*cosglobalang+ys*singlobalang;
2885 
2886 		xs = scale(xp,halfxdimen<<12,zp)+((halfxdimen+windowx1)<<12);
2887 		ys = scale(yp,xdimenscale<<12,zp)+((globalhoriz+windowy1)<<12);
2888 
2889 		drawline256(xs-65536,ys-65536,xs+65536,ys+65536,31);
2890 		drawline256(xs+65536,ys-65536,xs-65536,ys+65536,31);
2891 	}*/
2892 
2893 	while ((spritesortcnt > 0) && (maskwallcnt > 0))  //While BOTH > 0
2894 	{
2895 		j = maskwall[maskwallcnt-1];
2896 		if (spritewallfront(tspriteptr[spritesortcnt-1],(long)thewall[j]) == 0)
2897 			drawsprite(--spritesortcnt);
2898 		else
2899 		{
2900 				//Check to see if any sprites behind the masked wall...
2901 			k = -1;
2902 			gap = 0;
2903 			for(i=spritesortcnt-2;i>=0;i--)
2904 				if ((xb1[j] <= (spritesx[i]>>8)) && ((spritesx[i]>>8) <= xb2[j]))
2905 					if (spritewallfront(tspriteptr[i],(long)thewall[j]) == 0)
2906 					{
2907 						drawsprite(i);
2908 						tspriteptr[i]->owner = -1;
2909 						k = i;
2910 						gap++;
2911 					}
2912 			if (k >= 0)       //remove holes in sprite list
2913 			{
2914 				for(i=k;i<spritesortcnt;i++)
2915 					if (tspriteptr[i]->owner >= 0)
2916 					{
2917 						if (i > k)
2918 						{
2919 							tspriteptr[k] = tspriteptr[i];
2920 							spritesx[k] = spritesx[i];
2921 							spritesy[k] = spritesy[i];
2922 						}
2923 						k++;
2924 					}
2925 				spritesortcnt -= gap;
2926 			}
2927 
2928 				//finally safe to draw the masked wall
2929 			drawmaskwall(--maskwallcnt);
2930 		}
2931 	}
2932 	while (spritesortcnt > 0) drawsprite(--spritesortcnt);
2933 	while (maskwallcnt > 0) drawmaskwall(--maskwallcnt);
2934 }
2935 
drawmaskwall(short damaskwallcnt)2936 drawmaskwall(short damaskwallcnt)
2937 {
2938 	long i, j, k, x, z, sectnum, z1, z2, lx, rx;
2939 	sectortype *sec, *nsec;
2940 	walltype *wal;
2941 
2942 	z = maskwall[damaskwallcnt];
2943 	wal = &wall[thewall[z]];
2944 	sectnum = thesector[z]; sec = &sector[sectnum];
2945 	nsec = &sector[wal->nextsector];
2946 	z1 = max(nsec->ceilingz,sec->ceilingz);
2947 	z2 = min(nsec->floorz,sec->floorz);
2948 
2949 	wallmost(uwall,z,sectnum,(char)0);
2950 	wallmost(uplc,z,(long)wal->nextsector,(char)0);
2951 	for(x=xb1[z];x<=xb2[z];x++) if (uplc[x] > uwall[x]) uwall[x] = uplc[x];
2952 	wallmost(dwall,z,sectnum,(char)1);
2953 	wallmost(dplc,z,(long)wal->nextsector,(char)1);
2954 	for(x=xb1[z];x<=xb2[z];x++) if (dplc[x] < dwall[x]) dwall[x] = dplc[x];
2955 	prepwall(z,wal);
2956 
2957 	globalorientation = (long)wal->cstat;
2958 	globalpicnum = wal->overpicnum;
2959 	if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
2960 	globalxpanning = (long)wal->xpanning;
2961 	globalypanning = (long)wal->ypanning;
2962 	if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)thewall[z]+16384);
2963 	globalshade = (long)wal->shade;
2964 	globvis = globalvisibility;
2965 	if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
2966 	globalpal = (long)wal->pal;
2967 	globalshiftval = (picsiz[globalpicnum]>>4);
2968 	if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
2969 	globalshiftval = 32-globalshiftval;
2970 	globalyscale = (wal->yrepeat<<(globalshiftval-19));
2971 	if ((globalorientation&4) == 0)
2972 		globalzd = (((globalposz-z1)*globalyscale)<<8);
2973 	else
2974 		globalzd = (((globalposz-z2)*globalyscale)<<8);
2975 	globalzd += (globalypanning<<24);
2976 	if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
2977 
2978 	for(i=smostwallcnt-1;i>=0;i--)
2979 	{
2980 		j = smostwall[i];
2981 		if ((xb1[j] > xb2[z]) || (xb2[j] < xb1[z])) continue;
2982 		if (wallfront(j,z)) continue;
2983 
2984 		lx = max(xb1[j],xb1[z]); rx = min(xb2[j],xb2[z]);
2985 
2986 		switch(smostwalltype[i])
2987 		{
2988 			case 0:
2989 				if (lx <= rx)
2990 				{
2991 					if ((lx == xb1[z]) && (rx == xb2[z])) return;
2992 					clearbufbyte((long)&dwall[lx],(rx-lx+1)*sizeof(dwall[0]),0L);
2993 				}
2994 				break;
2995 			case 1:
2996 				k = smoststart[i] - xb1[j];
2997 				for(x=lx;x<=rx;x++)
2998 					if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
2999 				break;
3000 			case 2:
3001 				k = smoststart[i] - xb1[j];
3002 				for(x=lx;x<=rx;x++)
3003 					if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
3004 				break;
3005 		}
3006 	}
3007 
3008 		//maskwall
3009 	if ((searchit >= 1) && (searchx >= xb1[z]) && (searchx <= xb2[z]))
3010 		if ((searchy >= uwall[searchx]) && (searchy <= dwall[searchx]))
3011 		{
3012 			searchsector = sectnum; searchwall = thewall[z];
3013 			searchstat = 4; searchit = 1;
3014 		}
3015 
3016 	if ((globalorientation&128) == 0)
3017 		maskwallscan(xb1[z],xb2[z],uwall,dwall,swall,lwall);
3018 	else
3019 	{
3020 		if (globalorientation&128)
3021 		{
3022 			if (globalorientation&512) settransreverse(); else settransnormal();
3023 		}
3024 		transmaskwallscan(xb1[z],xb2[z]);
3025 	}
3026 }
3027 
drawsprite(long snum)3028 drawsprite (long snum)
3029 {
3030 	spritetype *tspr;
3031 	sectortype *sec;
3032 	long startum, startdm, sectnum, xb, yp, cstat;
3033 	long siz, xsiz, ysiz, xoff, yoff, xspan, yspan;
3034 	long x1, y1, x2, y2, lx, rx, dalx2, darx2, i, j, k, x, linum, linuminc;
3035 	long yplc, yinc, z, z1, z2, xp1, yp1, xp2, yp2;
3036 	long xs, ys, xpos, ypos, xv, yv, top, topinc, bot, botinc, hplc, hinc;
3037 	long cosang, sinang, dax, day, lpoint, lmax, rpoint, rmax, dax1, dax2, y;
3038 	long npoints, npoints2, zz, t, zsgn, zzsgn, *longptr;
3039 	signed short shade;
3040 	short tilenum, spritenum;
3041 	char swapped, daclip;
3042 
3043 	tspr = tspriteptr[snum];
3044 
3045 	xb = spritesx[snum];
3046 	yp = spritesy[snum];
3047 	tilenum = tspr->picnum;
3048 	spritenum = tspr->owner;
3049 	cstat = tspr->cstat;
3050 
3051 	if ((cstat&48) != 48)
3052 	{
3053 		if (picanm[tilenum]&192) tilenum += animateoffs(tilenum,spritenum+32768);
3054 		if ((tilesizx[tilenum] <= 0) || (tilesizy[tilenum] <= 0) || (spritenum < 0))
3055 			return;
3056 	}
3057 	if ((tspr->xrepeat <= 0) || (tspr->yrepeat <= 0)) return;
3058 
3059 	sectnum = tspr->sectnum; sec = &sector[sectnum];
3060 	globalpal = tspr->pal;
3061 	globalshade = tspr->shade;
3062 	if (cstat&2)
3063 	{
3064 		if (cstat&512) settransreverse(); else settransnormal();
3065 	}
3066 
3067 	xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)tspr->xoffset);
3068 	yoff = (long)((signed char)((picanm[tilenum]>>16)&255))+((long)tspr->yoffset);
3069 
3070 	if ((cstat&48) == 0)
3071 	{
3072 		if (yp <= (4<<8)) return;
3073 
3074 		siz = divscale19(xdimenscale,yp);
3075 
3076 		xv = mulscale16(((long)tspr->xrepeat)<<16,xyaspect);
3077 
3078 		xspan = tilesizx[tilenum];
3079 		yspan = tilesizy[tilenum];
3080 		xsiz = mulscale30(siz,xv*xspan);
3081 		ysiz = mulscale14(siz,tspr->yrepeat*yspan);
3082 
3083 		if (((tilesizx[tilenum]>>11) >= xsiz) || (yspan >= (ysiz>>1)))
3084 			return;  //Watch out for divscale overflow
3085 
3086 		x1 = xb-(xsiz>>1);
3087 		if (xspan&1) x1 += mulscale31(siz,xv);  //Odd xspans
3088 		i = mulscale30(siz,xv*xoff);
3089 		if ((cstat&4) == 0) x1 -= i; else x1 += i;
3090 
3091 		y1 = mulscale16(tspr->z-globalposz,siz);
3092 		y1 -= mulscale14(siz,tspr->yrepeat*yoff);
3093 		y1 += (globalhoriz<<8)-ysiz;
3094 		if (cstat&128)
3095 		{
3096 			y1 += (ysiz>>1);
3097 			if (yspan&1) y1 += mulscale15(siz,tspr->yrepeat);  //Odd yspans
3098 		}
3099 
3100 		x2 = x1+xsiz-1;
3101 		y2 = y1+ysiz-1;
3102 		if ((y1|255) >= (y2|255)) return;
3103 
3104 		lx = (x1>>8)+1; if (lx < 0) lx = 0;
3105 		rx = (x2>>8); if (rx >= xdimen) rx = xdimen-1;
3106 		if (lx > rx) return;
3107 
3108 		yinc = divscale32(yspan,ysiz);
3109 
3110 		if ((sec->ceilingstat&3) == 0)
3111 			startum = globalhoriz+mulscale24(siz,sec->ceilingz-globalposz)-1;
3112 		else
3113 			startum = 0;
3114 		if ((sec->floorstat&3) == 0)
3115 			startdm = globalhoriz+mulscale24(siz,sec->floorz-globalposz)+1;
3116 		else
3117 			startdm = 0x7fffffff;
3118 		if ((y1>>8) > startum) startum = (y1>>8);
3119 		if ((y2>>8) < startdm) startdm = (y2>>8);
3120 
3121 		if (startum < -32768) startum = -32768;
3122 		if (startdm > 32767) startdm = 32767;
3123 		if (startum >= startdm) return;
3124 
3125 		if ((cstat&4) == 0)
3126 		{
3127 			linuminc = divscale24(xspan,xsiz);
3128 			linum = mulscale8((lx<<8)-x1,linuminc);
3129 		}
3130 		else
3131 		{
3132 			linuminc = -divscale24(xspan,xsiz);
3133 			linum = mulscale8((lx<<8)-x2,linuminc);
3134 		}
3135 		if ((cstat&8) > 0)
3136 		{
3137 			yinc = -yinc;
3138 			i = y1; y1 = y2; y2 = i;
3139 		}
3140 
3141 		for(x=lx;x<=rx;x++)
3142 		{
3143 			uwall[x] = max(startumost[x+windowx1]-windowy1,(short)startum);
3144 			dwall[x] = min(startdmost[x+windowx1]-windowy1,(short)startdm);
3145 		}
3146 		daclip = 0;
3147 		for(i=smostwallcnt-1;i>=0;i--)
3148 		{
3149 			if (smostwalltype[i]&daclip) continue;
3150 			j = smostwall[i];
3151 			if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
3152 			if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
3153 			if (spritewallfront(tspr,(long)thewall[j]) && ((yp <= yb1[j]) || (yp <= yb2[j]))) continue;
3154 
3155 			dalx2 = max(xb1[j],lx); darx2 = min(xb2[j],rx);
3156 
3157 			switch(smostwalltype[i])
3158 			{
3159 				case 0:
3160 					if (dalx2 <= darx2)
3161 					{
3162 						if ((dalx2 == lx) && (darx2 == rx)) return;
3163 						clearbufbyte((long)&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
3164 					}
3165 					break;
3166 				case 1:
3167 					k = smoststart[i] - xb1[j];
3168 					for(x=dalx2;x<=darx2;x++)
3169 						if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
3170 					if ((dalx2 == lx) && (darx2 == rx)) daclip |= 1;
3171 					break;
3172 				case 2:
3173 					k = smoststart[i] - xb1[j];
3174 					for(x=dalx2;x<=darx2;x++)
3175 						if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
3176 					if ((dalx2 == lx) && (darx2 == rx)) daclip |= 2;
3177 					break;
3178 			}
3179 		}
3180 
3181 		if (uwall[rx] >= dwall[rx])
3182 		{
3183 			for(x=lx;x<rx;x++)
3184 				if (uwall[x] < dwall[x]) break;
3185 			if (x == rx) return;
3186 		}
3187 
3188 			//sprite
3189 		if ((searchit >= 1) && (searchx >= lx) && (searchx <= rx))
3190 			if ((searchy >= uwall[searchx]) && (searchy < dwall[searchx]))
3191 			{
3192 				searchsector = sectnum; searchwall = spritenum;
3193 				searchstat = 3; searchit = 1;
3194 			}
3195 
3196 		z2 = tspr->z - ((yoff*tspr->yrepeat)<<2);
3197 		if (cstat&128)
3198 		{
3199 			z2 += ((yspan*tspr->yrepeat)<<1);
3200 			if (yspan&1) z2 += (tspr->yrepeat<<1);        //Odd yspans
3201 		}
3202 		z1 = z2 - ((yspan*tspr->yrepeat)<<2);
3203 
3204 		globalorientation = 0;
3205 		globalpicnum = tilenum;
3206 		if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
3207 		globalxpanning = 0L;
3208 		globalypanning = 0L;
3209 		globvis = globalvisibility;
3210 		if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
3211 		globalshiftval = (picsiz[globalpicnum]>>4);
3212 		if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
3213 		globalshiftval = 32-globalshiftval;
3214 		globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
3215 		globalzd = (((globalposz-z1)*globalyscale)<<8);
3216 		if ((cstat&8) > 0)
3217 		{
3218 			globalyscale = -globalyscale;
3219 			globalzd = (((globalposz-z2)*globalyscale)<<8);
3220 		}
3221 
3222 		qinterpolatedown16((long)&lwall[lx],rx-lx+1,linum,linuminc);
3223 		clearbuf((long)&swall[lx],rx-lx+1,mulscale19(yp,xdimscale));
3224 
3225 		if ((cstat&2) == 0)
3226 			maskwallscan(lx,rx,uwall,dwall,swall,lwall);
3227 		else
3228 			transmaskwallscan(lx,rx);
3229 	}
3230 	else if ((cstat&48) == 16)
3231 	{
3232 		if ((cstat&4) > 0) xoff = -xoff;
3233 		if ((cstat&8) > 0) yoff = -yoff;
3234 
3235 		xspan = tilesizx[tilenum]; yspan = tilesizy[tilenum];
3236 		xv = tspr->xrepeat*sintable[(tspr->ang+2560+1536)&2047];
3237 		yv = tspr->xrepeat*sintable[(tspr->ang+2048+1536)&2047];
3238 		i = (xspan>>1)+xoff;
3239 		x1 = tspr->x-globalposx-mulscale16(xv,i); x2 = x1+mulscale16(xv,xspan);
3240 		y1 = tspr->y-globalposy-mulscale16(yv,i); y2 = y1+mulscale16(yv,xspan);
3241 
3242 		yp1 = dmulscale6(x1,cosviewingrangeglobalang,y1,sinviewingrangeglobalang);
3243 		yp2 = dmulscale6(x2,cosviewingrangeglobalang,y2,sinviewingrangeglobalang);
3244 		if ((yp1 <= 0) && (yp2 <= 0)) return;
3245 		xp1 = dmulscale6(y1,cosglobalang,-x1,singlobalang);
3246 		xp2 = dmulscale6(y2,cosglobalang,-x2,singlobalang);
3247 
3248 		x1 += globalposx; y1 += globalposy;
3249 		x2 += globalposx; y2 += globalposy;
3250 
3251 		swapped = 0;
3252 		if (dmulscale32(xp1,yp2,-xp2,yp1) >= 0)  //If wall's NOT facing you
3253 		{
3254 			if ((cstat&64) != 0) return;
3255 			i = xp1, xp1 = xp2, xp2 = i;
3256 			i = yp1, yp1 = yp2, yp2 = i;
3257 			i = x1, x1 = x2, x2 = i;
3258 			i = y1, y1 = y2, y2 = i;
3259 			swapped = 1;
3260 		}
3261 
3262 		if (xp1 >= -yp1)
3263 		{
3264 			if (xp1 > yp1) return;
3265 
3266 			if (yp1 == 0) return;
3267 			xb1[MAXWALLSB-1] = halfxdimen + scale(xp1,halfxdimen,yp1);
3268 			if (xp1 >= 0) xb1[MAXWALLSB-1]++;   //Fix for SIGNED divide
3269 			if (xb1[MAXWALLSB-1] >= xdimen) xb1[MAXWALLSB-1] = xdimen-1;
3270 			yb1[MAXWALLSB-1] = yp1;
3271 		}
3272 		else
3273 		{
3274 			if (xp2 < -yp2) return;
3275 			xb1[MAXWALLSB-1] = 0;
3276 			i = yp1-yp2+xp1-xp2;
3277 			if (i == 0) return;
3278 			yb1[MAXWALLSB-1] = yp1 + scale(yp2-yp1,xp1+yp1,i);
3279 		}
3280 		if (xp2 <= yp2)
3281 		{
3282 			if (xp2 < -yp2) return;
3283 
3284 			if (yp2 == 0) return;
3285 			xb2[MAXWALLSB-1] = halfxdimen + scale(xp2,halfxdimen,yp2) - 1;
3286 			if (xp2 >= 0) xb2[MAXWALLSB-1]++;   //Fix for SIGNED divide
3287 			if (xb2[MAXWALLSB-1] >= xdimen) xb2[MAXWALLSB-1] = xdimen-1;
3288 			yb2[MAXWALLSB-1] = yp2;
3289 		}
3290 		else
3291 		{
3292 			if (xp1 > yp1) return;
3293 
3294 			xb2[MAXWALLSB-1] = xdimen-1;
3295 			i = xp2-xp1+yp1-yp2;
3296 			if (i == 0) return;
3297 			yb2[MAXWALLSB-1] = yp1 + scale(yp2-yp1,yp1-xp1,i);
3298 		}
3299 
3300 		if ((yb1[MAXWALLSB-1] < 256) || (yb2[MAXWALLSB-1] < 256) || (xb1[MAXWALLSB-1] > xb2[MAXWALLSB-1]))
3301 			return;
3302 
3303 		topinc = -mulscale10(yp1,xspan);
3304 		top = (((mulscale10(xp1,xdimen) - mulscale9(xb1[MAXWALLSB-1]-halfxdimen,yp1))*xspan)>>3);
3305 		botinc = ((yp2-yp1)>>8);
3306 		bot = mulscale11(xp1-xp2,xdimen) + mulscale2(xb1[MAXWALLSB-1]-halfxdimen,botinc);
3307 
3308 		j = xb2[MAXWALLSB-1]+3;
3309 		z = mulscale20(top,krecipasm(bot));
3310 		lwall[xb1[MAXWALLSB-1]] = (z>>8);
3311 		for(x=xb1[MAXWALLSB-1]+4;x<=j;x+=4)
3312 		{
3313 			top += topinc; bot += botinc;
3314 			zz = z; z = mulscale20(top,krecipasm(bot));
3315 			lwall[x] = (z>>8);
3316 			i = ((z+zz)>>1);
3317 			lwall[x-2] = (i>>8);
3318 			lwall[x-3] = ((i+zz)>>9);
3319 			lwall[x-1] = ((i+z)>>9);
3320 		}
3321 
3322 		if (lwall[xb1[MAXWALLSB-1]] < 0) lwall[xb1[MAXWALLSB-1]] = 0;
3323 		if (lwall[xb2[MAXWALLSB-1]] >= xspan) lwall[xb2[MAXWALLSB-1]] = xspan-1;
3324 
3325 		if ((swapped^((cstat&4)>0)) > 0)
3326 		{
3327 			j = xspan-1;
3328 			for(x=xb1[MAXWALLSB-1];x<=xb2[MAXWALLSB-1];x++)
3329 				lwall[x] = j-lwall[x];
3330 		}
3331 
3332 		rx1[MAXWALLSB-1] = xp1; ry1[MAXWALLSB-1] = yp1;
3333 		rx2[MAXWALLSB-1] = xp2; ry2[MAXWALLSB-1] = yp2;
3334 
3335 		hplc = divscale19(xdimenscale,yb1[MAXWALLSB-1]);
3336 		hinc = divscale19(xdimenscale,yb2[MAXWALLSB-1]);
3337 		hinc = (hinc-hplc)/(xb2[MAXWALLSB-1]-xb1[MAXWALLSB-1]+1);
3338 
3339 		z2 = tspr->z - ((yoff*tspr->yrepeat)<<2);
3340 		if (cstat&128)
3341 		{
3342 			z2 += ((yspan*tspr->yrepeat)<<1);
3343 			if (yspan&1) z2 += (tspr->yrepeat<<1);        //Odd yspans
3344 		}
3345 		z1 = z2 - ((yspan*tspr->yrepeat)<<2);
3346 
3347 		globalorientation = 0;
3348 		globalpicnum = tilenum;
3349 		if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
3350 		globalxpanning = 0L;
3351 		globalypanning = 0L;
3352 		globvis = globalvisibility;
3353 		if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
3354 		globalshiftval = (picsiz[globalpicnum]>>4);
3355 		if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
3356 		globalshiftval = 32-globalshiftval;
3357 		globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
3358 		globalzd = (((globalposz-z1)*globalyscale)<<8);
3359 		if ((cstat&8) > 0)
3360 		{
3361 			globalyscale = -globalyscale;
3362 			globalzd = (((globalposz-z2)*globalyscale)<<8);
3363 		}
3364 
3365 		if (((sec->ceilingstat&1) == 0) && (z1 < sec->ceilingz))
3366 			z1 = sec->ceilingz;
3367 		if (((sec->floorstat&1) == 0) && (z2 > sec->floorz))
3368 			z2 = sec->floorz;
3369 
3370 		owallmost(uwall,(long)(MAXWALLSB-1),z1-globalposz);
3371 		owallmost(dwall,(long)(MAXWALLSB-1),z2-globalposz);
3372 		for(i=xb1[MAXWALLSB-1];i<=xb2[MAXWALLSB-1];i++)
3373 			{ swall[i] = (krecipasm(hplc)<<2); hplc += hinc; }
3374 
3375 		for(i=smostwallcnt-1;i>=0;i--)
3376 		{
3377 			j = smostwall[i];
3378 
3379 			if ((xb1[j] > xb2[MAXWALLSB-1]) || (xb2[j] < xb1[MAXWALLSB-1])) continue;
3380 
3381 			dalx2 = xb1[j]; darx2 = xb2[j];
3382 			if (max(yb1[MAXWALLSB-1],yb2[MAXWALLSB-1]) > min(yb1[j],yb2[j]))
3383 			{
3384 				if (min(yb1[MAXWALLSB-1],yb2[MAXWALLSB-1]) > max(yb1[j],yb2[j]))
3385 				{
3386 					x = 0x80000000;
3387 				}
3388 				else
3389 				{
3390 					x = thewall[j]; xp1 = wall[x].x; yp1 = wall[x].y;
3391 					x = wall[x].point2; xp2 = wall[x].x; yp2 = wall[x].y;
3392 
3393 					z1 = (xp2-xp1)*(y1-yp1) - (yp2-yp1)*(x1-xp1);
3394 					z2 = (xp2-xp1)*(y2-yp1) - (yp2-yp1)*(x2-xp1);
3395 					if ((z1^z2) >= 0)
3396 						x = (z1+z2);
3397 					else
3398 					{
3399 						z1 = (x2-x1)*(yp1-y1) - (y2-y1)*(xp1-x1);
3400 						z2 = (x2-x1)*(yp2-y1) - (y2-y1)*(xp2-x1);
3401 
3402 						if ((z1^z2) >= 0)
3403 							x = -(z1+z2);
3404 						else
3405 						{
3406 							if ((xp2-xp1)*(tspr->y-yp1) == (tspr->x-xp1)*(yp2-yp1))
3407 							{
3408 								if (wall[thewall[j]].nextsector == tspr->sectnum)
3409 									x = 0x80000000;
3410 								else
3411 									x = 0x7fffffff;
3412 							}
3413 							else
3414 							{     //INTERSECTION!
3415 								x = (xp1-globalposx) + scale(xp2-xp1,z1,z1-z2);
3416 								y = (yp1-globalposy) + scale(yp2-yp1,z1,z1-z2);
3417 
3418 								yp1 = dmulscale14(x,cosglobalang,y,singlobalang);
3419 								if (yp1 > 0)
3420 								{
3421 									xp1 = dmulscale14(y,cosglobalang,-x,singlobalang);
3422 
3423 									x = halfxdimen + scale(xp1,halfxdimen,yp1);
3424 									if (xp1 >= 0) x++;   //Fix for SIGNED divide
3425 
3426 									if (z1 < 0)
3427 										{ if (dalx2 < x) dalx2 = x; }
3428 									else
3429 										{ if (darx2 > x) darx2 = x; }
3430 									x = 0x80000001;
3431 								}
3432 								else
3433 									x = 0x7fffffff;
3434 							}
3435 						}
3436 					}
3437 				}
3438 				if (x < 0)
3439 				{
3440 					if (dalx2 < xb1[MAXWALLSB-1]) dalx2 = xb1[MAXWALLSB-1];
3441 					if (darx2 > xb2[MAXWALLSB-1]) darx2 = xb2[MAXWALLSB-1];
3442 					switch(smostwalltype[i])
3443 					{
3444 						case 0:
3445 							if (dalx2 <= darx2)
3446 							{
3447 								if ((dalx2 == xb1[MAXWALLSB-1]) && (darx2 == xb2[MAXWALLSB-1])) return;
3448 								clearbufbyte((long)&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
3449 							}
3450 							break;
3451 						case 1:
3452 							k = smoststart[i] - xb1[j];
3453 							for(x=dalx2;x<=darx2;x++)
3454 								if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
3455 							break;
3456 						case 2:
3457 							k = smoststart[i] - xb1[j];
3458 							for(x=dalx2;x<=darx2;x++)
3459 								if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
3460 							break;
3461 					}
3462 				}
3463 			}
3464 		}
3465 
3466 			//sprite
3467 		if ((searchit >= 1) && (searchx >= xb1[MAXWALLSB-1]) && (searchx <= xb2[MAXWALLSB-1]))
3468 			if ((searchy >= uwall[searchx]) && (searchy <= dwall[searchx]))
3469 			{
3470 				searchsector = sectnum; searchwall = spritenum;
3471 				searchstat = 3; searchit = 1;
3472 			}
3473 
3474 		if ((cstat&2) == 0)
3475 			maskwallscan(xb1[MAXWALLSB-1],xb2[MAXWALLSB-1],uwall,dwall,swall,lwall);
3476 		else
3477 			transmaskwallscan(xb1[MAXWALLSB-1],xb2[MAXWALLSB-1]);
3478 	}
3479 	else if ((cstat&48) == 32)
3480 	{
3481 		if ((cstat&64) != 0)
3482 			if ((globalposz > tspr->z) == ((cstat&8)==0))
3483 				return;
3484 
3485 		if ((cstat&4) > 0) xoff = -xoff;
3486 		if ((cstat&8) > 0) yoff = -yoff;
3487 		xspan = tilesizx[tilenum];
3488 		yspan = tilesizy[tilenum];
3489 
3490 			//Rotate center point
3491 		dax = tspr->x-globalposx;
3492 		day = tspr->y-globalposy;
3493 		rzi[0] = dmulscale10(cosglobalang,dax,singlobalang,day);
3494 		rxi[0] = dmulscale10(cosglobalang,day,-singlobalang,dax);
3495 
3496 			//Get top-left corner
3497 		i = ((tspr->ang+2048-globalang)&2047);
3498 		cosang = sintable[(i+512)&2047]; sinang = sintable[i];
3499 		dax = ((xspan>>1)+xoff)*tspr->xrepeat;
3500 		day = ((yspan>>1)+yoff)*tspr->yrepeat;
3501 		rzi[0] += dmulscale12(sinang,dax,cosang,day);
3502 		rxi[0] += dmulscale12(sinang,day,-cosang,dax);
3503 
3504 			//Get other 3 corners
3505 		dax = xspan*tspr->xrepeat;
3506 		day = yspan*tspr->yrepeat;
3507 		rzi[1] = rzi[0]-mulscale12(sinang,dax);
3508 		rxi[1] = rxi[0]+mulscale12(cosang,dax);
3509 		dax = -mulscale12(cosang,day);
3510 		day = -mulscale12(sinang,day);
3511 		rzi[2] = rzi[1]+dax; rxi[2] = rxi[1]+day;
3512 		rzi[3] = rzi[0]+dax; rxi[3] = rxi[0]+day;
3513 
3514 			//Put all points on same z
3515 		ryi[0] = scale((tspr->z-globalposz),yxaspect,320<<8);
3516 		if (ryi[0] == 0) return;
3517 		ryi[1] = ryi[2] = ryi[3] = ryi[0];
3518 
3519 		if ((cstat&4) == 0)
3520 			{ z = 0; z1 = 1; z2 = 3; }
3521 		else
3522 			{ z = 1; z1 = 0; z2 = 2; }
3523 
3524 		dax = rzi[z1]-rzi[z]; day = rxi[z1]-rxi[z];
3525 		bot = dmulscale8(dax,dax,day,day);
3526 		if (((klabs(dax)>>13) >= bot) || ((klabs(day)>>13) >= bot)) return;
3527 		globalx1 = divscale18(dax,bot);
3528 		globalx2 = divscale18(day,bot);
3529 
3530 		dax = rzi[z2]-rzi[z]; day = rxi[z2]-rxi[z];
3531 		bot = dmulscale8(dax,dax,day,day);
3532 		if (((klabs(dax)>>13) >= bot) || ((klabs(day)>>13) >= bot)) return;
3533 		globaly1 = divscale18(dax,bot);
3534 		globaly2 = divscale18(day,bot);
3535 
3536 			//Calculate globals for hline texture mapping function
3537 		globalxpanning = (rxi[z]<<12);
3538 		globalypanning = (rzi[z]<<12);
3539 		globalzd = (ryi[z]<<12);
3540 
3541 		rzi[0] = mulscale16(rzi[0],viewingrange);
3542 		rzi[1] = mulscale16(rzi[1],viewingrange);
3543 		rzi[2] = mulscale16(rzi[2],viewingrange);
3544 		rzi[3] = mulscale16(rzi[3],viewingrange);
3545 
3546 		if (ryi[0] < 0)   //If ceilsprite is above you, reverse order of points
3547 		{
3548 			i = rxi[1]; rxi[1] = rxi[3]; rxi[3] = i;
3549 			i = rzi[1]; rzi[1] = rzi[3]; rzi[3] = i;
3550 		}
3551 
3552 
3553 			//Clip polygon in 3-space
3554 		npoints = 4;
3555 
3556 			//Clip edge 1
3557 		npoints2 = 0;
3558 		zzsgn = rxi[0]+rzi[0];
3559 		for(z=0;z<npoints;z++)
3560 		{
3561 			zz = z+1; if (zz == npoints) zz = 0;
3562 			zsgn = zzsgn; zzsgn = rxi[zz]+rzi[zz];
3563 			if (zsgn >= 0)
3564 			{
3565 				rxi2[npoints2] = rxi[z]; ryi2[npoints2] = ryi[z]; rzi2[npoints2] = rzi[z];
3566 				npoints2++;
3567 			}
3568 			if ((zsgn^zzsgn) < 0)
3569 			{
3570 				t = divscale30(zsgn,zsgn-zzsgn);
3571 				rxi2[npoints2] = rxi[z] + mulscale30(t,rxi[zz]-rxi[z]);
3572 				ryi2[npoints2] = ryi[z] + mulscale30(t,ryi[zz]-ryi[z]);
3573 				rzi2[npoints2] = rzi[z] + mulscale30(t,rzi[zz]-rzi[z]);
3574 				npoints2++;
3575 			}
3576 		}
3577 		if (npoints2 <= 2) return;
3578 
3579 			//Clip edge 2
3580 		npoints = 0;
3581 		zzsgn = rxi2[0]-rzi2[0];
3582 		for(z=0;z<npoints2;z++)
3583 		{
3584 			zz = z+1; if (zz == npoints2) zz = 0;
3585 			zsgn = zzsgn; zzsgn = rxi2[zz]-rzi2[zz];
3586 			if (zsgn <= 0)
3587 			{
3588 				rxi[npoints] = rxi2[z]; ryi[npoints] = ryi2[z]; rzi[npoints] = rzi2[z];
3589 				npoints++;
3590 			}
3591 			if ((zsgn^zzsgn) < 0)
3592 			{
3593 				t = divscale30(zsgn,zsgn-zzsgn);
3594 				rxi[npoints] = rxi2[z] + mulscale30(t,rxi2[zz]-rxi2[z]);
3595 				ryi[npoints] = ryi2[z] + mulscale30(t,ryi2[zz]-ryi2[z]);
3596 				rzi[npoints] = rzi2[z] + mulscale30(t,rzi2[zz]-rzi2[z]);
3597 				npoints++;
3598 			}
3599 		}
3600 		if (npoints <= 2) return;
3601 
3602 			//Clip edge 3
3603 		npoints2 = 0;
3604 		zzsgn = ryi[0]*halfxdimen + (rzi[0]*(globalhoriz-0));
3605 		for(z=0;z<npoints;z++)
3606 		{
3607 			zz = z+1; if (zz == npoints) zz = 0;
3608 			zsgn = zzsgn; zzsgn = ryi[zz]*halfxdimen + (rzi[zz]*(globalhoriz-0));
3609 			if (zsgn >= 0)
3610 			{
3611 				rxi2[npoints2] = rxi[z];
3612 				ryi2[npoints2] = ryi[z];
3613 				rzi2[npoints2] = rzi[z];
3614 				npoints2++;
3615 			}
3616 			if ((zsgn^zzsgn) < 0)
3617 			{
3618 				t = divscale30(zsgn,zsgn-zzsgn);
3619 				rxi2[npoints2] = rxi[z] + mulscale30(t,rxi[zz]-rxi[z]);
3620 				ryi2[npoints2] = ryi[z] + mulscale30(t,ryi[zz]-ryi[z]);
3621 				rzi2[npoints2] = rzi[z] + mulscale30(t,rzi[zz]-rzi[z]);
3622 				npoints2++;
3623 			}
3624 		}
3625 		if (npoints2 <= 2) return;
3626 
3627 			//Clip edge 4
3628 		npoints = 0;
3629 		zzsgn = ryi2[0]*halfxdimen + (rzi2[0]*(globalhoriz-ydimen));
3630 		for(z=0;z<npoints2;z++)
3631 		{
3632 			zz = z+1; if (zz == npoints2) zz = 0;
3633 			zsgn = zzsgn; zzsgn = ryi2[zz]*halfxdimen + (rzi2[zz]*(globalhoriz-ydimen));
3634 			if (zsgn <= 0)
3635 			{
3636 				rxi[npoints] = rxi2[z];
3637 				ryi[npoints] = ryi2[z];
3638 				rzi[npoints] = rzi2[z];
3639 				npoints++;
3640 			}
3641 			if ((zsgn^zzsgn) < 0)
3642 			{
3643 				t = divscale30(zsgn,zsgn-zzsgn);
3644 				rxi[npoints] = rxi2[z] + mulscale30(t,rxi2[zz]-rxi2[z]);
3645 				ryi[npoints] = ryi2[z] + mulscale30(t,ryi2[zz]-ryi2[z]);
3646 				rzi[npoints] = rzi2[z] + mulscale30(t,rzi2[zz]-rzi2[z]);
3647 				npoints++;
3648 			}
3649 		}
3650 		if (npoints <= 2) return;
3651 
3652 			//Project onto screen
3653 		lpoint = -1; lmax = 0x7fffffff;
3654 		rpoint = -1; rmax = 0x80000000;
3655 		for(z=0;z<npoints;z++)
3656 		{
3657 			xsi[z] = scale(rxi[z],xdimen<<15,rzi[z]) + (xdimen<<15);
3658 			ysi[z] = scale(ryi[z],xdimen<<15,rzi[z]) + (globalhoriz<<16);
3659 			if (xsi[z] < 0) xsi[z] = 0;
3660 			if (xsi[z] > (xdimen<<16)) xsi[z] = (xdimen<<16);
3661 			if (ysi[z] < ((long)0<<16)) ysi[z] = ((long)0<<16);
3662 			if (ysi[z] > ((long)ydimen<<16)) ysi[z] = ((long)ydimen<<16);
3663 			if (xsi[z] < lmax) lmax = xsi[z], lpoint = z;
3664 			if (xsi[z] > rmax) rmax = xsi[z], rpoint = z;
3665 		}
3666 
3667 			//Get uwall arrays
3668 		for(z=lpoint;z!=rpoint;z=zz)
3669 		{
3670 			zz = z+1; if (zz == npoints) zz = 0;
3671 
3672 			dax1 = ((xsi[z]+65535)>>16);
3673 			dax2 = ((xsi[zz]+65535)>>16);
3674 			if (dax2 > dax1)
3675 			{
3676 				yinc = divscale16(ysi[zz]-ysi[z],xsi[zz]-xsi[z]);
3677 				y = ysi[z] + mulscale16((dax1<<16)-xsi[z],yinc);
3678 				qinterpolatedown16short((long)(&uwall[dax1]),dax2-dax1,y,yinc);
3679 			}
3680 		}
3681 
3682 			//Get dwall arrays
3683 		for(;z!=lpoint;z=zz)
3684 		{
3685 			zz = z+1; if (zz == npoints) zz = 0;
3686 
3687 			dax1 = ((xsi[zz]+65535)>>16);
3688 			dax2 = ((xsi[z]+65535)>>16);
3689 			if (dax2 > dax1)
3690 			{
3691 				yinc = divscale16(ysi[zz]-ysi[z],xsi[zz]-xsi[z]);
3692 				y = ysi[zz] + mulscale16((dax1<<16)-xsi[zz],yinc);
3693 				qinterpolatedown16short((long)(&dwall[dax1]),dax2-dax1,y,yinc);
3694 			}
3695 		}
3696 
3697 
3698 		lx = ((lmax+65535)>>16);
3699 		rx = ((rmax+65535)>>16);
3700 		for(x=lx;x<=rx;x++)
3701 		{
3702 			uwall[x] = max(uwall[x],startumost[x+windowx1]-windowy1);
3703 			dwall[x] = min(dwall[x],startdmost[x+windowx1]-windowy1);
3704 		}
3705 
3706 			//Additional uwall/dwall clipping goes here
3707 		for(i=smostwallcnt-1;i>=0;i--)
3708 		{
3709 			j = smostwall[i];
3710 			if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
3711 			if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
3712 
3713 				//if (spritewallfront(tspr,thewall[j]) == 0)
3714 			x = thewall[j]; xp1 = wall[x].x; yp1 = wall[x].y;
3715 			x = wall[x].point2; xp2 = wall[x].x; yp2 = wall[x].y;
3716 			x = (xp2-xp1)*(tspr->y-yp1)-(tspr->x-xp1)*(yp2-yp1);
3717 			if ((yp > yb1[j]) && (yp > yb2[j])) x = -1;
3718 			if ((x >= 0) && ((x != 0) || (wall[thewall[j]].nextsector != tspr->sectnum))) continue;
3719 
3720 			dalx2 = max(xb1[j],lx); darx2 = min(xb2[j],rx);
3721 
3722 			switch(smostwalltype[i])
3723 			{
3724 				case 0:
3725 					if (dalx2 <= darx2)
3726 					{
3727 						if ((dalx2 == lx) && (darx2 == rx)) return;
3728 						clearbufbyte((long)&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
3729 					}
3730 					break;
3731 				case 1:
3732 					k = smoststart[i] - xb1[j];
3733 					for(x=dalx2;x<=darx2;x++)
3734 						if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
3735 					break;
3736 				case 2:
3737 					k = smoststart[i] - xb1[j];
3738 					for(x=dalx2;x<=darx2;x++)
3739 						if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
3740 					break;
3741 			}
3742 		}
3743 
3744 			//sprite
3745 		if ((searchit >= 1) && (searchx >= lx) && (searchx <= rx))
3746 			if ((searchy >= uwall[searchx]) && (searchy <= dwall[searchx]))
3747 			{
3748 				searchsector = sectnum; searchwall = spritenum;
3749 				searchstat = 3; searchit = 1;
3750 			}
3751 
3752 		globalorientation = cstat;
3753 		globalpicnum = tilenum;
3754 		if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
3755 		//if (picanm[globalpicnum]&192) globalpicnum += animateoffs((short)globalpicnum,spritenum+32768);
3756 
3757 		if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
3758 		setgotpic(globalpicnum);
3759 		globalbufplc = waloff[globalpicnum];
3760 
3761 		globvis = mulscale16(globalhisibility,viewingrange);
3762 		if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
3763 
3764 		x = picsiz[globalpicnum]; y = ((x>>4)&15); x &= 15;
3765 		if (pow2long[x] != xspan)
3766 		{
3767 			x++;
3768 			globalx1 = mulscale(globalx1,xspan,x);
3769 			globalx2 = mulscale(globalx2,xspan,x);
3770 		}
3771 
3772 		dax = globalxpanning; day = globalypanning;
3773 		globalxpanning = -dmulscale6(globalx1,day,globalx2,dax);
3774 		globalypanning = -dmulscale6(globaly1,day,globaly2,dax);
3775 
3776 		globalx2 = mulscale16(globalx2,viewingrange);
3777 		globaly2 = mulscale16(globaly2,viewingrange);
3778 		globalzd = mulscale16(globalzd,viewingrangerecip);
3779 
3780 		globalx1 = (globalx1-globalx2)*halfxdimen;
3781 		globaly1 = (globaly1-globaly2)*halfxdimen;
3782 
3783 		if ((cstat&2) == 0)
3784 			msethlineshift(x,y);
3785 		else
3786 			tsethlineshift(x,y);
3787 
3788 			//Draw it!
3789 		ceilspritescan(lx,rx-1);
3790 	}
3791 #ifdef SUPERBUILD
3792 	else if ((cstat&48) == 48)
3793 	{
3794 		lx = 0; rx = xdim-1;
3795 		for(x=lx;x<=rx;x++)
3796 		{
3797 			lwall[x] = (long)startumost[x+windowx1]-windowy1;
3798 			swall[x] = (long)startdmost[x+windowx1]-windowy1;
3799 		}
3800 		for(i=smostwallcnt-1;i>=0;i--)
3801 		{
3802 			j = smostwall[i];
3803 			if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
3804 			if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
3805 			if (spritewallfront(tspr,(long)thewall[j]) && ((yp <= yb1[j]) || (yp <= yb2[j]))) continue;
3806 
3807 			dalx2 = max(xb1[j],lx); darx2 = min(xb2[j],rx);
3808 
3809 			switch(smostwalltype[i])
3810 			{
3811 				case 0:
3812 					if (dalx2 <= darx2)
3813 					{
3814 						if ((dalx2 == lx) && (darx2 == rx)) return;
3815 							clearbufbyte((long)&swall[dalx2],(darx2-dalx2+1)*sizeof(swall[0]),0L);
3816 					}
3817 					break;
3818 				case 1:
3819 					k = smoststart[i] - xb1[j];
3820 					for(x=dalx2;x<=darx2;x++)
3821 						if (smost[k+x] > lwall[x]) lwall[x] = smost[k+x];
3822 					break;
3823 				case 2:
3824 					k = smoststart[i] - xb1[j];
3825 					for(x=dalx2;x<=darx2;x++)
3826 						if (smost[k+x] < swall[x]) swall[x] = smost[k+x];
3827 					break;
3828 			}
3829 		}
3830 
3831 		if (lwall[rx] >= swall[rx])
3832 		{
3833 			for(x=lx;x<rx;x++)
3834 				if (lwall[x] < swall[x]) break;
3835 			if (x == rx) return;
3836 		}
3837 
3838 		for(i=0;i<MAXVOXMIPS;i++)
3839 			if (!voxoff[tilenum][i])
3840 			{
3841 				kloadvoxel(tilenum);
3842 				break;
3843 			}
3844 
3845 		longptr = (long *)voxoff[tilenum][0];
3846 		if (!(cstat&128)) tspr->z -= mulscale6(longptr[5],(long)tspr->yrepeat);
3847 		yoff = (long)((signed char)((picanm[sprite[tspr->owner].picnum]>>16)&255))+((long)tspr->yoffset);
3848 		tspr->z -= ((yoff*tspr->yrepeat)<<2);
3849 
3850 		globvis = globalvisibility;
3851 		if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
3852 
3853 		if ((searchit >= 1) && (yp > (4<<8)) && (searchy >= lwall[searchx]) && (searchy < swall[searchx]))
3854 		{
3855 			siz = divscale19(xdimenscale,yp);
3856 
3857 			xv = mulscale16(((long)tspr->xrepeat)<<16,xyaspect);
3858 
3859 			xspan = ((longptr[0]+longptr[1])>>1);
3860 			yspan = longptr[2];
3861 			xsiz = mulscale30(siz,xv*xspan);
3862 			ysiz = mulscale14(siz,tspr->yrepeat*yspan);
3863 
3864 				//Watch out for divscale overflow
3865 			if (((xspan>>11) < xsiz) && (yspan < (ysiz>>1)))
3866 			{
3867 				x1 = xb-(xsiz>>1);
3868 				if (xspan&1) x1 += mulscale31(siz,xv);  //Odd xspans
3869 				i = mulscale30(siz,xv*xoff);
3870 				if ((cstat&4) == 0) x1 -= i; else x1 += i;
3871 
3872 				y1 = mulscale16(tspr->z-globalposz,siz);
3873 				//y1 -= mulscale14(siz,tspr->yrepeat*yoff);
3874 				y1 += (globalhoriz<<8)-ysiz;
3875 				//if (cstat&128)  //Already fixed up above
3876 				y1 += (ysiz>>1);
3877 
3878 				x2 = x1+xsiz-1;
3879 				y2 = y1+ysiz-1;
3880 				if (((y1|255) < (y2|255)) && (searchx >= (x1>>8)+1) && (searchx <= (x2>>8)))
3881 				{
3882 					if ((sec->ceilingstat&3) == 0)
3883 						startum = globalhoriz+mulscale24(siz,sec->ceilingz-globalposz)-1;
3884 					else
3885 						startum = 0;
3886 					if ((sec->floorstat&3) == 0)
3887 						startdm = globalhoriz+mulscale24(siz,sec->floorz-globalposz)+1;
3888 					else
3889 						startdm = 0x7fffffff;
3890 
3891 						//sprite
3892 					if ((searchy >= max(startum,(y1>>8))) && (searchy < min(startdm,(y2>>8))))
3893 					{
3894 						searchsector = sectnum; searchwall = spritenum;
3895 						searchstat = 3; searchit = 1;
3896 					}
3897 				}
3898 			}
3899 		}
3900 
3901 		drawvox(tspr->x,tspr->y,tspr->z,(long)tspr->ang+1536,(long)tspr->xrepeat,(long)tspr->yrepeat,tilenum,tspr->shade,tspr->pal,lwall,swall);
3902 	}
3903 #endif
3904 	if (automapping == 1) show2dsprite[spritenum>>3] |= pow2char[spritenum&7];
3905 }
3906 
3907 #ifdef SUPERBUILD
drawvox(long dasprx,long daspry,long dasprz,long dasprang,long daxscale,long dayscale,char daindex,signed char dashade,char dapal,long * daumost,long * dadmost)3908 drawvox(long dasprx, long daspry, long dasprz, long dasprang,
3909 		  long daxscale, long dayscale, char daindex,
3910 		  signed char dashade, char dapal, long *daumost, long *dadmost)
3911 {
3912 	long i, j, k, x, y, z, syoff, ggxstart, ggystart, nxoff;
3913 	long cosang, sinang, sprcosang, sprsinang, backx, backy, gxinc, gyinc;
3914 	long daxsiz, daysiz, dazsiz, daxpivot, daypivot, dazpivot;
3915 	long daxscalerecip, dayscalerecip, cnt, gxstart, gystart, odayscale;
3916 	long l1, l2, p, pend, slabxoffs, xyvoxoffs, *longptr;
3917 	long lx, rx, nx, ny, zx, zy, x1, y1, z1, x2, y2, z2, yplc, yinc, bufplc;
3918 	long yoff, xs, ys, xe, ye, xi, yi, cbackx, cbacky, dagxinc, dagyinc;
3919 	short *shortptr;
3920 	char *voxptr, *voxend, *davoxptr, oand, oand16, oand32;
3921 
3922 	cosang = sintable[(globalang+512)&2047];
3923 	sinang = sintable[globalang&2047];
3924 	sprcosang = sintable[(dasprang+512)&2047];
3925 	sprsinang = sintable[dasprang&2047];
3926 
3927 	i = klabs(dmulscale6(dasprx-globalposx,cosang,daspry-globalposy,sinang));
3928 	setupdrawslab(ylookup[1],FP_OFF(palookup[dapal]) + (long)(getpalookup(mulscale21(globvis,i),(long)dashade)<<8));
3929 	j = 1310720;
3930 	for(k=0;k<MAXVOXMIPS;k++)
3931 	{
3932 		if (i < j) { i = k; break; }
3933 		j <<= 1;
3934 	}
3935 	if (k >= MAXVOXMIPS) i = MAXVOXMIPS-1;
3936 
3937 	davoxptr = (char *)voxoff[daindex][i]; if (!davoxptr) return;
3938 
3939 	daxscale <<= (i+8); dayscale <<= (i+8);
3940 	odayscale = dayscale;
3941 	daxscale = mulscale16(daxscale,xyaspect);
3942 	daxscale = scale(daxscale,xdimenscale,xdimen<<8);
3943 	dayscale = scale(dayscale,mulscale16(xdimenscale,viewingrangerecip),xdimen<<8);
3944 
3945 	daxscalerecip = (1<<30)/daxscale;
3946 	dayscalerecip = (1<<30)/dayscale;
3947 
3948 	longptr = (long *)davoxptr;
3949 	daxsiz = longptr[0]; daysiz = longptr[1]; dazsiz = longptr[2];
3950 	daxpivot = longptr[3]; daypivot = longptr[4]; dazpivot = longptr[5];
3951 	davoxptr += (6<<2);
3952 
3953 	x = mulscale16(globalposx-dasprx,daxscalerecip);
3954 	y = mulscale16(globalposy-daspry,daxscalerecip);
3955 	backx = ((dmulscale10(x,sprcosang,y,sprsinang)+daxpivot)>>8);
3956 	backy = ((dmulscale10(y,sprcosang,x,-sprsinang)+daypivot)>>8);
3957 	cbackx = min(max(backx,0),daxsiz-1);
3958 	cbacky = min(max(backy,0),daysiz-1);
3959 
3960 	sprcosang = mulscale14(daxscale,sprcosang);
3961 	sprsinang = mulscale14(daxscale,sprsinang);
3962 
3963 	x = (dasprx-globalposx) - dmulscale18(daxpivot,sprcosang,daypivot,-sprsinang);
3964 	y = (daspry-globalposy) - dmulscale18(daypivot,sprcosang,daxpivot,sprsinang);
3965 
3966 	cosang = mulscale16(cosang,dayscalerecip);
3967 	sinang = mulscale16(sinang,dayscalerecip);
3968 
3969 	gxstart = y*cosang - x*sinang;
3970 	gystart = x*cosang + y*sinang;
3971 	gxinc = dmulscale10(sprsinang,cosang,sprcosang,-sinang);
3972 	gyinc = dmulscale10(sprcosang,cosang,sprsinang,sinang);
3973 
3974 	x = 0; y = 0; j = max(daxsiz,daysiz);
3975 	for(i=0;i<=j;i++)
3976 	{
3977 		ggxinc[i] = x; x += gxinc;
3978 		ggyinc[i] = y; y += gyinc;
3979 	}
3980 
3981 	if ((klabs(globalposz-dasprz)>>10) >= klabs(odayscale)) return;
3982 	syoff = divscale21(globalposz-dasprz,odayscale) + (dazpivot<<7);
3983 	yoff = ((klabs(gxinc)+klabs(gyinc))>>1);
3984 	longptr = (long *)davoxptr;
3985 	xyvoxoffs = ((daxsiz+1)<<2);
3986 
3987 	for(cnt=0;cnt<8;cnt++)
3988 	{
3989 		switch(cnt)
3990 		{
3991 			case 0: xs = 0;        ys = 0;        xi = 1;  yi = 1;  break;
3992 			case 1: xs = daxsiz-1; ys = 0;        xi = -1; yi = 1;  break;
3993 			case 2: xs = 0;        ys = daysiz-1; xi = 1;  yi = -1; break;
3994 			case 3: xs = daxsiz-1; ys = daysiz-1; xi = -1; yi = -1; break;
3995 			case 4: xs = 0;        ys = cbacky;   xi = 1;  yi = 2;  break;
3996 			case 5: xs = daxsiz-1; ys = cbacky;   xi = -1; yi = 2;  break;
3997 			case 6: xs = cbackx;   ys = 0;        xi = 2;  yi = 1;  break;
3998 			case 7: xs = cbackx;   ys = daysiz-1; xi = 2;  yi = -1; break;
3999 		}
4000 		xe = cbackx; ye = cbacky;
4001 		if (cnt < 4)
4002 		{
4003 			if ((xi < 0) && (xe >= xs)) continue;
4004 			if ((xi > 0) && (xe <= xs)) continue;
4005 			if ((yi < 0) && (ye >= ys)) continue;
4006 			if ((yi > 0) && (ye <= ys)) continue;
4007 		}
4008 		else
4009 		{
4010 			if ((xi < 0) && (xe > xs)) continue;
4011 			if ((xi > 0) && (xe < xs)) continue;
4012 			if ((yi < 0) && (ye > ys)) continue;
4013 			if ((yi > 0) && (ye < ys)) continue;
4014 			xe += xi; ye += yi;
4015 		}
4016 
4017 		i = ksgn(ys-backy)+ksgn(xs-backx)*3+4;
4018 		switch(i)
4019 		{
4020 			case 6: case 7: x1 = 0; y1 = 0; break;
4021 			case 8: case 5: x1 = gxinc; y1 = gyinc; break;
4022 			case 0: case 3: x1 = gyinc; y1 = -gxinc; break;
4023 			case 2: case 1: x1 = gxinc+gyinc; y1 = gyinc-gxinc; break;
4024 		}
4025 		switch(i)
4026 		{
4027 			case 2: case 5: x2 = 0; y2 = 0; break;
4028 			case 0: case 1: x2 = gxinc; y2 = gyinc; break;
4029 			case 8: case 7: x2 = gyinc; y2 = -gxinc; break;
4030 			case 6: case 3: x2 = gxinc+gyinc; y2 = gyinc-gxinc; break;
4031 		}
4032 		oand = pow2char[(xs<backx)+0]+pow2char[(ys<backy)+2];
4033 		oand16 = oand+16;
4034 		oand32 = oand+32;
4035 
4036 		if (yi > 0) { dagxinc = gxinc; dagyinc = mulscale16(gyinc,viewingrangerecip); }
4037 				 else { dagxinc = -gxinc; dagyinc = -mulscale16(gyinc,viewingrangerecip); }
4038 
4039 			//Fix for non 90 degree viewing ranges
4040 		nxoff = mulscale16(x2-x1,viewingrangerecip);
4041 		x1 = mulscale16(x1,viewingrangerecip);
4042 
4043 		ggxstart = gxstart+ggyinc[ys];
4044 		ggystart = gystart-ggxinc[ys];
4045 
4046 		for(x=xs;x!=xe;x+=xi)
4047 		{
4048 			slabxoffs = (long)&davoxptr[longptr[x]];
4049 			shortptr = (short *)&davoxptr[((x*(daysiz+1))<<1)+xyvoxoffs];
4050 
4051 			nx = mulscale16(ggxstart+ggxinc[x],viewingrangerecip)+x1;
4052 			ny = ggystart+ggyinc[x];
4053 			for(y=ys;y!=ye;y+=yi,nx+=dagyinc,ny-=dagxinc)
4054 			{
4055 				if ((ny <= nytooclose) || (ny >= nytoofar)) continue;
4056 				voxptr = (char *)(shortptr[y]+slabxoffs);
4057 				voxend = (char *)(shortptr[y+1]+slabxoffs);
4058 				if (voxptr == voxend) continue;
4059 
4060 				lx = mulscale32(nx>>3,distrecip[(ny+y1)>>14])+halfxdimen;
4061 				if (lx < 0) lx = 0;
4062 				rx = mulscale32((nx+nxoff)>>3,distrecip[(ny+y2)>>14])+halfxdimen;
4063 				if (rx > xdimen) rx = xdimen;
4064 				if (rx <= lx) continue;
4065 				rx -= lx;
4066 
4067 				l1 = distrecip[(ny-yoff)>>14];
4068 				l2 = distrecip[(ny+yoff)>>14];
4069 				for(;voxptr<voxend;voxptr+=voxptr[1]+3)
4070 				{
4071 					j = (voxptr[0]<<15)-syoff;
4072 					if (j < 0)
4073 					{
4074 						k = j+(voxptr[1]<<15);
4075 						if (k < 0)
4076 						{
4077 							if ((voxptr[2]&oand32) == 0) continue;
4078 							z2 = mulscale32(l2,k) + globalhoriz;     //Below slab
4079 						}
4080 						else
4081 						{
4082 							if ((voxptr[2]&oand) == 0) continue;    //Middle of slab
4083 							z2 = mulscale32(l1,k) + globalhoriz;
4084 						}
4085 						z1 = mulscale32(l1,j) + globalhoriz;
4086 					}
4087 					else
4088 					{
4089 						if ((voxptr[2]&oand16) == 0) continue;
4090 						z1 = mulscale32(l2,j) + globalhoriz;        //Above slab
4091 						z2 = mulscale32(l1,j+(voxptr[1]<<15)) + globalhoriz;
4092 					}
4093 
4094 					if (voxptr[1] == 1)
4095 					{
4096 						yplc = 0; yinc = 0;
4097 						if (z1 < daumost[lx]) z1 = daumost[lx];
4098 					}
4099 					else
4100 					{
4101 						if (z2-z1 >= 1024) yinc = divscale16(voxptr[1],z2-z1);
4102 						else if (z2 > z1) yinc = (lowrecip[z2-z1]*voxptr[1]>>8);
4103 						if (z1 < daumost[lx]) { yplc = yinc*(daumost[lx]-z1); z1 = daumost[lx]; } else yplc = 0;
4104 					}
4105 					if (z2 > dadmost[lx]) z2 = dadmost[lx];
4106 					z2 -= z1; if (z2 <= 0) continue;
4107 
4108 					drawslab(rx,yplc,z2,yinc,(long)&voxptr[3],ylookup[z1]+lx+frameoffset);
4109 				}
4110 			}
4111 		}
4112 	}
4113 }
4114 #endif
4115 
ceilspritescan(long x1,long x2)4116 ceilspritescan (long x1, long x2)
4117 {
4118 	long x, y1, y2, twall, bwall;
4119 
4120 	y1 = uwall[x1]; y2 = y1;
4121 	for(x=x1;x<=x2;x++)
4122 	{
4123 		twall = uwall[x]-1; bwall = dwall[x];
4124 		if (twall < bwall-1)
4125 		{
4126 			if (twall >= y2)
4127 			{
4128 				while (y1 < y2-1) ceilspritehline(x-1,++y1);
4129 				y1 = twall;
4130 			}
4131 			else
4132 			{
4133 				while (y1 < twall) ceilspritehline(x-1,++y1);
4134 				while (y1 > twall) lastx[y1--] = x;
4135 			}
4136 			while (y2 > bwall) ceilspritehline(x-1,--y2);
4137 			while (y2 < bwall) lastx[y2++] = x;
4138 		}
4139 		else
4140 		{
4141 			while (y1 < y2-1) ceilspritehline(x-1,++y1);
4142 			if (x == x2) break;
4143 			y1 = uwall[x+1]; y2 = y1;
4144 		}
4145 	}
4146 	while (y1 < y2-1) ceilspritehline(x2,++y1);
4147 	faketimerhandler();
4148 }
4149 
ceilspritehline(long x2,long y)4150 ceilspritehline (long x2, long y)
4151 {
4152 	long x1, v, bx, by;
4153 
4154 	//x = x1 + (x2-x1)t + (y1-y2)u  �  x = 160v
4155 	//y = y1 + (y2-y1)t + (x2-x1)u  �  y = (scrx-160)v
4156 	//z = z1 = z2                   �  z = posz + (scry-horiz)v
4157 
4158 	x1 = lastx[y]; if (x2 < x1) return;
4159 
4160 	v = mulscale20(globalzd,horizlookup[y-globalhoriz+horizycent]);
4161 	bx = mulscale14(globalx2*x1+globalx1,v) + globalxpanning;
4162 	by = mulscale14(globaly2*x1+globaly1,v) + globalypanning;
4163 	asm1 = mulscale14(globalx2,v);
4164 	asm2 = mulscale14(globaly2,v);
4165 
4166 	asm3 = FP_OFF(palookup[globalpal]) + (getpalookup((long)mulscale28(klabs(v),globvis),globalshade)<<8);
4167 
4168 	if ((globalorientation&2) == 0)
4169 		mhline(globalbufplc,bx,(x2-x1)<<16,0L,by,ylookup[y]+x1+frameoffset);
4170 	else
4171 	{
4172 		thline(globalbufplc,bx,(x2-x1)<<16,0L,by,ylookup[y]+x1+frameoffset);
4173 		transarea += (x2-x1);
4174 	}
4175 }
4176 
setsprite(short spritenum,long newx,long newy,long newz)4177 setsprite(short spritenum, long newx, long newy, long newz)
4178 {
4179 	short bad, j, tempsectnum;
4180 
4181 	sprite[spritenum].x = newx;
4182 	sprite[spritenum].y = newy;
4183 	sprite[spritenum].z = newz;
4184 
4185 	tempsectnum = sprite[spritenum].sectnum;
4186 	updatesector(newx,newy,&tempsectnum);
4187 	if (tempsectnum < 0)
4188 		return(-1);
4189 	if (tempsectnum != sprite[spritenum].sectnum)
4190 		changespritesect(spritenum,tempsectnum);
4191 
4192 	return(0);
4193 }
4194 
animateoffs(short tilenum,short fakevar)4195 animateoffs(short tilenum, short fakevar)
4196 {
4197 	long i, k, offs;
4198 
4199 	offs = 0;
4200 	i = (totalclocklock>>((picanm[tilenum]>>24)&15));
4201 	if ((picanm[tilenum]&63) > 0)
4202 	{
4203 		switch(picanm[tilenum]&192)
4204 		{
4205 			case 64:
4206 				k = (i%((picanm[tilenum]&63)<<1));
4207 				if (k < (picanm[tilenum]&63))
4208 					offs = k;
4209 				else
4210 					offs = (((picanm[tilenum]&63)<<1)-k);
4211 				break;
4212 			case 128:
4213 				offs = (i%((picanm[tilenum]&63)+1));
4214 					break;
4215 			case 192:
4216 				offs = -(i%((picanm[tilenum]&63)+1));
4217 		}
4218 	}
4219 	return(offs);
4220 }
4221 
initspritelists()4222 initspritelists()
4223 {
4224 	long i;
4225 
4226 	for (i=0;i<MAXSECTORS;i++)     //Init doubly-linked sprite sector lists
4227 		headspritesect[i] = -1;
4228 	headspritesect[MAXSECTORS] = 0;
4229 	for(i=0;i<MAXSPRITES;i++)
4230 	{
4231 		prevspritesect[i] = i-1;
4232 		nextspritesect[i] = i+1;
4233 		sprite[i].sectnum = MAXSECTORS;
4234 	}
4235 	prevspritesect[0] = -1;
4236 	nextspritesect[MAXSPRITES-1] = -1;
4237 
4238 
4239 	for(i=0;i<MAXSTATUS;i++)      //Init doubly-linked sprite status lists
4240 		headspritestat[i] = -1;
4241 	headspritestat[MAXSTATUS] = 0;
4242 	for(i=0;i<MAXSPRITES;i++)
4243 	{
4244 		prevspritestat[i] = i-1;
4245 		nextspritestat[i] = i+1;
4246 		sprite[i].statnum = MAXSTATUS;
4247 	}
4248 	prevspritestat[0] = -1;
4249 	nextspritestat[MAXSPRITES-1] = -1;
4250 }
4251 
insertsprite(short sectnum,short statnum)4252 insertsprite(short sectnum, short statnum)
4253 {
4254 	insertspritestat(statnum);
4255 	return(insertspritesect(sectnum));
4256 }
4257 
insertspritesect(short sectnum)4258 insertspritesect(short sectnum)
4259 {
4260 	short blanktouse;
4261 
4262 	if ((sectnum >= MAXSECTORS) || (headspritesect[MAXSECTORS] == -1))
4263 		return(-1);  //list full
4264 
4265 	blanktouse = headspritesect[MAXSECTORS];
4266 
4267 	headspritesect[MAXSECTORS] = nextspritesect[blanktouse];
4268 	if (headspritesect[MAXSECTORS] >= 0)
4269 		prevspritesect[headspritesect[MAXSECTORS]] = -1;
4270 
4271 	prevspritesect[blanktouse] = -1;
4272 	nextspritesect[blanktouse] = headspritesect[sectnum];
4273 	if (headspritesect[sectnum] >= 0)
4274 		prevspritesect[headspritesect[sectnum]] = blanktouse;
4275 	headspritesect[sectnum] = blanktouse;
4276 
4277 	sprite[blanktouse].sectnum = sectnum;
4278 
4279 	return(blanktouse);
4280 }
4281 
insertspritestat(short statnum)4282 insertspritestat(short statnum)
4283 {
4284 	short blanktouse;
4285 
4286 	if ((statnum >= MAXSTATUS) || (headspritestat[MAXSTATUS] == -1))
4287 		return(-1);  //list full
4288 
4289 	blanktouse = headspritestat[MAXSTATUS];
4290 
4291 	headspritestat[MAXSTATUS] = nextspritestat[blanktouse];
4292 	if (headspritestat[MAXSTATUS] >= 0)
4293 		prevspritestat[headspritestat[MAXSTATUS]] = -1;
4294 
4295 	prevspritestat[blanktouse] = -1;
4296 	nextspritestat[blanktouse] = headspritestat[statnum];
4297 	if (headspritestat[statnum] >= 0)
4298 		prevspritestat[headspritestat[statnum]] = blanktouse;
4299 	headspritestat[statnum] = blanktouse;
4300 
4301 	sprite[blanktouse].statnum = statnum;
4302 
4303 	return(blanktouse);
4304 }
4305 
deletesprite(short spritenum)4306 deletesprite(short spritenum)
4307 {
4308 	deletespritestat(spritenum);
4309 	return(deletespritesect(spritenum));
4310 }
4311 
deletespritesect(short deleteme)4312 deletespritesect(short deleteme)
4313 {
4314 	if (sprite[deleteme].sectnum == MAXSECTORS)
4315 		return(-1);
4316 
4317 	if (headspritesect[sprite[deleteme].sectnum] == deleteme)
4318 		headspritesect[sprite[deleteme].sectnum] = nextspritesect[deleteme];
4319 
4320 	if (prevspritesect[deleteme] >= 0) nextspritesect[prevspritesect[deleteme]] = nextspritesect[deleteme];
4321 	if (nextspritesect[deleteme] >= 0) prevspritesect[nextspritesect[deleteme]] = prevspritesect[deleteme];
4322 
4323 	if (headspritesect[MAXSECTORS] >= 0) prevspritesect[headspritesect[MAXSECTORS]] = deleteme;
4324 	prevspritesect[deleteme] = -1;
4325 	nextspritesect[deleteme] = headspritesect[MAXSECTORS];
4326 	headspritesect[MAXSECTORS] = deleteme;
4327 
4328 	sprite[deleteme].sectnum = MAXSECTORS;
4329 	return(0);
4330 }
4331 
deletespritestat(short deleteme)4332 deletespritestat (short deleteme)
4333 {
4334 	if (sprite[deleteme].statnum == MAXSTATUS)
4335 		return(-1);
4336 
4337 	if (headspritestat[sprite[deleteme].statnum] == deleteme)
4338 		headspritestat[sprite[deleteme].statnum] = nextspritestat[deleteme];
4339 
4340 	if (prevspritestat[deleteme] >= 0) nextspritestat[prevspritestat[deleteme]] = nextspritestat[deleteme];
4341 	if (nextspritestat[deleteme] >= 0) prevspritestat[nextspritestat[deleteme]] = prevspritestat[deleteme];
4342 
4343 	if (headspritestat[MAXSTATUS] >= 0) prevspritestat[headspritestat[MAXSTATUS]] = deleteme;
4344 	prevspritestat[deleteme] = -1;
4345 	nextspritestat[deleteme] = headspritestat[MAXSTATUS];
4346 	headspritestat[MAXSTATUS] = deleteme;
4347 
4348 	sprite[deleteme].statnum = MAXSTATUS;
4349 	return(0);
4350 }
4351 
changespritesect(short spritenum,short newsectnum)4352 changespritesect(short spritenum, short newsectnum)
4353 {
4354 	if ((newsectnum < 0) || (newsectnum > MAXSECTORS)) return(-1);
4355 	if (sprite[spritenum].sectnum == newsectnum) return(0);
4356 	if (sprite[spritenum].sectnum == MAXSECTORS) return(-1);
4357 	if (deletespritesect(spritenum) < 0) return(-1);
4358 	insertspritesect(newsectnum);
4359 	return(0);
4360 }
4361 
changespritestat(short spritenum,short newstatnum)4362 changespritestat(short spritenum, short newstatnum)
4363 {
4364 	if ((newstatnum < 0) || (newstatnum > MAXSTATUS)) return(-1);
4365 	if (sprite[spritenum].statnum == newstatnum) return(0);
4366 	if (sprite[spritenum].statnum == MAXSTATUS) return(-1);
4367 	if (deletespritestat(spritenum) < 0) return(-1);
4368 	insertspritestat(newstatnum);
4369 	return(0);
4370 }
4371 
nextsectorneighborz(short sectnum,long thez,short topbottom,short direction)4372 nextsectorneighborz(short sectnum, long thez, short topbottom, short direction)
4373 {
4374 	walltype *wal;
4375 	long i, testz, nextz;
4376 	short sectortouse;
4377 
4378 	if (direction == 1) nextz = 0x7fffffff; else nextz = 0x80000000;
4379 
4380 	sectortouse = -1;
4381 
4382 	wal = &wall[sector[sectnum].wallptr];
4383 	i = sector[sectnum].wallnum;
4384 	do
4385 	{
4386 		if (wal->nextsector >= 0)
4387 		{
4388 			if (topbottom == 1)
4389 			{
4390 				testz = sector[wal->nextsector].floorz;
4391 				if (direction == 1)
4392 				{
4393 					if ((testz > thez) && (testz < nextz))
4394 					{
4395 						nextz = testz;
4396 						sectortouse = wal->nextsector;
4397 					}
4398 				}
4399 				else
4400 				{
4401 					if ((testz < thez) && (testz > nextz))
4402 					{
4403 						nextz = testz;
4404 						sectortouse = wal->nextsector;
4405 					}
4406 				}
4407 			}
4408 			else
4409 			{
4410 				testz = sector[wal->nextsector].ceilingz;
4411 				if (direction == 1)
4412 				{
4413 					if ((testz > thez) && (testz < nextz))
4414 					{
4415 						nextz = testz;
4416 						sectortouse = wal->nextsector;
4417 					}
4418 				}
4419 				else
4420 				{
4421 					if ((testz < thez) && (testz > nextz))
4422 					{
4423 						nextz = testz;
4424 						sectortouse = wal->nextsector;
4425 					}
4426 				}
4427 			}
4428 		}
4429 		wal++;
4430 		i--;
4431 	} while (i != 0);
4432 
4433 	return(sectortouse);
4434 }
4435 
cansee(long x1,long y1,long z1,short sect1,long x2,long y2,long z2,short sect2)4436 cansee(long x1, long y1, long z1, short sect1, long x2, long y2, long z2, short sect2)
4437 {
4438 	sectortype *sec;
4439 	walltype *wal, *wal2;
4440 	long i, cnt, nexts, x, y, z, cz, fz, dasectnum, dacnt, danum;
4441 	long x21, y21, z21, x31, y31, x34, y34, bot, t;
4442 
4443 	if ((x1 == x2) && (y1 == y2)) return(sect1 == sect2);
4444 
4445 	x21 = x2-x1; y21 = y2-y1; z21 = z2-z1;
4446 
4447 	clipsectorlist[0] = sect1; danum = 1;
4448 	for(dacnt=0;dacnt<danum;dacnt++)
4449 	{
4450 		dasectnum = clipsectorlist[dacnt]; sec = &sector[dasectnum];
4451 		for(cnt=sec->wallnum,wal=&wall[sec->wallptr];cnt>0;cnt--,wal++)
4452 		{
4453 			wal2 = &wall[wal->point2];
4454 			x31 = wal->x-x1; x34 = wal->x-wal2->x;
4455 			y31 = wal->y-y1; y34 = wal->y-wal2->y;
4456 
4457 			bot = y21*x34-x21*y34; if (bot <= 0) continue;
4458 			t = y21*x31-x21*y31; if (t < 0 || t >= bot) continue;
4459 			t = y31*x34-x31*y34; if (t < 0 || t >= bot) continue;
4460 
4461 			nexts = wal->nextsector;
4462 			if ((nexts < 0) || (wal->cstat&32)) return(0);
4463 
4464 			t = divscale24(t,bot);
4465 			x = x1 + mulscale24(x21,t);
4466 			y = y1 + mulscale24(y21,t);
4467 			z = z1 + mulscale24(z21,t);
4468 
4469 			getzsofslope((short)dasectnum,x,y,&cz,&fz);
4470 			if ((z <= cz) || (z >= fz)) return(0);
4471 			getzsofslope((short)nexts,x,y,&cz,&fz);
4472 			if ((z <= cz) || (z >= fz)) return(0);
4473 
4474 			for(i=danum-1;i>=0;i--) if (clipsectorlist[i] == nexts) break;
4475 			if (i < 0) clipsectorlist[danum++] = nexts;
4476 		}
4477 	}
4478 	for(i=danum-1;i>=0;i--) if (clipsectorlist[i] == sect2) return(1);
4479 	return(0);
4480 }
4481 
hitscan(long xs,long ys,long zs,short sectnum,long vx,long vy,long vz,short * hitsect,short * hitwall,short * hitsprite,long * hitx,long * hity,long * hitz,unsigned long cliptype)4482 hitscan(long xs, long ys, long zs, short sectnum, long vx, long vy, long vz,
4483 	short *hitsect, short *hitwall, short *hitsprite,
4484 	long *hitx, long *hity, long *hitz, unsigned long cliptype)
4485 {
4486 	sectortype *sec;
4487 	walltype *wal, *wal2;
4488 	spritetype *spr;
4489 	long z, zz, x1, y1, z1, x2, y2, z2, x3, y3, x4, y4, intx, inty, intz;
4490 	long topt, topu, bot, dist, offx, offy, cstat;
4491 	long i, j, k, l, tilenum, xoff, yoff, dax, day, daz, daz2;
4492 	long ang, cosang, sinang, xspan, yspan, xrepeat, yrepeat;
4493 	long dawalclipmask, dasprclipmask;
4494 	short tempshortcnt, tempshortnum, dasector, startwall, endwall;
4495 	short nextsector;
4496 	char clipyou;
4497 
4498 	*hitsect = -1; *hitwall = -1; *hitsprite = -1;
4499 	if (sectnum < 0) return(-1);
4500 
4501 	*hitx = hitscangoalx; *hity = hitscangoaly;
4502 
4503 	dawalclipmask = (cliptype&65535);
4504 	dasprclipmask = (cliptype>>16);
4505 
4506 	clipsectorlist[0] = sectnum;
4507 	tempshortcnt = 0; tempshortnum = 1;
4508 	do
4509 	{
4510 		dasector = clipsectorlist[tempshortcnt]; sec = &sector[dasector];
4511 
4512 		x1 = 0x7fffffff;
4513 		if (sec->ceilingstat&2)
4514 		{
4515 			wal = &wall[sec->wallptr]; wal2 = &wall[wal->point2];
4516 			dax = wal2->x-wal->x; day = wal2->y-wal->y;
4517 			i = nsqrtasm(dax*dax+day*day); if (i == 0) continue;
4518 			i = divscale15(sec->ceilingheinum,i);
4519 			dax *= i; day *= i;
4520 
4521 			j = (vz<<8)-dmulscale15(dax,vy,-day,vx);
4522 			if (j != 0)
4523 			{
4524 				i = ((sec->ceilingz-zs)<<8)+dmulscale15(dax,ys-wal->y,-day,xs-wal->x);
4525 				if (((i^j) >= 0) && ((klabs(i)>>1) < klabs(j)))
4526 				{
4527 					i = divscale30(i,j);
4528 					x1 = xs + mulscale30(vx,i);
4529 					y1 = ys + mulscale30(vy,i);
4530 					z1 = zs + mulscale30(vz,i);
4531 				}
4532 			}
4533 		}
4534 		else if ((vz < 0) && (zs >= sec->ceilingz))
4535 		{
4536 			z1 = sec->ceilingz; i = z1-zs;
4537 			if ((klabs(i)>>1) < -vz)
4538 			{
4539 				i = divscale30(i,vz);
4540 				x1 = xs + mulscale30(vx,i);
4541 				y1 = ys + mulscale30(vy,i);
4542 			}
4543 		}
4544 		if ((x1 != 0x7fffffff) && (klabs(x1-xs)+klabs(y1-ys) < klabs((*hitx)-xs)+klabs((*hity)-ys)))
4545 			if (inside(x1,y1,dasector) != 0)
4546 			{
4547 				*hitsect = dasector; *hitwall = -1; *hitsprite = -1;
4548 				*hitx = x1; *hity = y1; *hitz = z1;
4549 			}
4550 
4551 		x1 = 0x7fffffff;
4552 		if (sec->floorstat&2)
4553 		{
4554 			wal = &wall[sec->wallptr]; wal2 = &wall[wal->point2];
4555 			dax = wal2->x-wal->x; day = wal2->y-wal->y;
4556 			i = nsqrtasm(dax*dax+day*day); if (i == 0) continue;
4557 			i = divscale15(sec->floorheinum,i);
4558 			dax *= i; day *= i;
4559 
4560 			j = (vz<<8)-dmulscale15(dax,vy,-day,vx);
4561 			if (j != 0)
4562 			{
4563 				i = ((sec->floorz-zs)<<8)+dmulscale15(dax,ys-wal->y,-day,xs-wal->x);
4564 				if (((i^j) >= 0) && ((klabs(i)>>1) < klabs(j)))
4565 				{
4566 					i = divscale30(i,j);
4567 					x1 = xs + mulscale30(vx,i);
4568 					y1 = ys + mulscale30(vy,i);
4569 					z1 = zs + mulscale30(vz,i);
4570 				}
4571 			}
4572 		}
4573 		else if ((vz > 0) && (zs <= sec->floorz))
4574 		{
4575 			z1 = sec->floorz; i = z1-zs;
4576 			if ((klabs(i)>>1) < vz)
4577 			{
4578 				i = divscale30(i,vz);
4579 				x1 = xs + mulscale30(vx,i);
4580 				y1 = ys + mulscale30(vy,i);
4581 			}
4582 		}
4583 		if ((x1 != 0x7fffffff) && (klabs(x1-xs)+klabs(y1-ys) < klabs((*hitx)-xs)+klabs((*hity)-ys)))
4584 			if (inside(x1,y1,dasector) != 0)
4585 			{
4586 				*hitsect = dasector; *hitwall = -1; *hitsprite = -1;
4587 				*hitx = x1; *hity = y1; *hitz = z1;
4588 			}
4589 
4590 		startwall = sec->wallptr; endwall = startwall + sec->wallnum;
4591 		for(z=startwall,wal=&wall[startwall];z<endwall;z++,wal++)
4592 		{
4593 			wal2 = &wall[wal->point2];
4594 			x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y;
4595 
4596 			if ((x1-xs)*(y2-ys) < (x2-xs)*(y1-ys)) continue;
4597 			if (rintersect(xs,ys,zs,vx,vy,vz,x1,y1,x2,y2,&intx,&inty,&intz) == 0) continue;
4598 
4599 			if (klabs(intx-xs)+klabs(inty-ys) >= klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
4600 
4601 			nextsector = wal->nextsector;
4602 			if ((nextsector < 0) || (wal->cstat&dawalclipmask))
4603 			{
4604 				*hitsect = dasector; *hitwall = z; *hitsprite = -1;
4605 				*hitx = intx; *hity = inty; *hitz = intz;
4606 				continue;
4607 			}
4608 			getzsofslope(nextsector,intx,inty,&daz,&daz2);
4609 			if ((intz <= daz) || (intz >= daz2))
4610 			{
4611 				*hitsect = dasector; *hitwall = z; *hitsprite = -1;
4612 				*hitx = intx; *hity = inty; *hitz = intz;
4613 				continue;
4614 			}
4615 
4616 			for(zz=tempshortnum-1;zz>=0;zz--)
4617 				if (clipsectorlist[zz] == nextsector) break;
4618 			if (zz < 0) clipsectorlist[tempshortnum++] = nextsector;
4619 		}
4620 
4621 		for(z=headspritesect[dasector];z>=0;z=nextspritesect[z])
4622 		{
4623 			spr = &sprite[z];
4624 			cstat = spr->cstat;
4625 			if ((cstat&dasprclipmask) == 0) continue;
4626 
4627 			x1 = spr->x; y1 = spr->y; z1 = spr->z;
4628 			switch(cstat&48)
4629 			{
4630 				case 0:
4631 					topt = vx*(x1-xs) + vy*(y1-ys); if (topt <= 0) continue;
4632 					bot = vx*vx + vy*vy; if (bot == 0) continue;
4633 
4634 					intz = zs+scale(vz,topt,bot);
4635 
4636 					i = (tilesizy[spr->picnum]*spr->yrepeat<<2);
4637 					if (cstat&128) z1 += (i>>1);
4638 					if (picanm[spr->picnum]&0x00ff0000) z1 -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
4639 					if ((intz > z1) || (intz < z1-i)) continue;
4640 					topu = vx*(y1-ys) - vy*(x1-xs);
4641 
4642 					offx = scale(vx,topu,bot);
4643 					offy = scale(vy,topu,bot);
4644 					dist = offx*offx + offy*offy;
4645 					i = tilesizx[spr->picnum]*spr->xrepeat; i *= i;
4646 					if (dist > (i>>7)) continue;
4647 					intx = xs + scale(vx,topt,bot);
4648 					inty = ys + scale(vy,topt,bot);
4649 
4650 					if (klabs(intx-xs)+klabs(inty-ys) > klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
4651 
4652 					*hitsect = dasector; *hitwall = -1; *hitsprite = z;
4653 					*hitx = intx; *hity = inty; *hitz = intz;
4654 					break;
4655 				case 16:
4656 						//These lines get the 2 points of the rotated sprite
4657 						//Given: (x1, y1) starts out as the center point
4658 					tilenum = spr->picnum;
4659 					xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
4660 					if ((cstat&4) > 0) xoff = -xoff;
4661 					k = spr->ang; l = spr->xrepeat;
4662 					dax = sintable[k&2047]*l; day = sintable[(k+1536)&2047]*l;
4663 					l = tilesizx[tilenum]; k = (l>>1)+xoff;
4664 					x1 -= mulscale16(dax,k); x2 = x1+mulscale16(dax,l);
4665 					y1 -= mulscale16(day,k); y2 = y1+mulscale16(day,l);
4666 
4667 					if ((cstat&64) != 0)   //back side of 1-way sprite
4668 						if ((x1-xs)*(y2-ys) < (x2-xs)*(y1-ys)) continue;
4669 
4670 					if (rintersect(xs,ys,zs,vx,vy,vz,x1,y1,x2,y2,&intx,&inty,&intz) == 0) continue;
4671 
4672 					if (klabs(intx-xs)+klabs(inty-ys) > klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
4673 
4674 					k = ((tilesizy[spr->picnum]*spr->yrepeat)<<2);
4675 					if (cstat&128) daz = spr->z+(k>>1); else daz = spr->z;
4676 					if (picanm[spr->picnum]&0x00ff0000) daz -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
4677 					if ((intz < daz) && (intz > daz-k))
4678 					{
4679 						*hitsect = dasector; *hitwall = -1; *hitsprite = z;
4680 						*hitx = intx; *hity = inty; *hitz = intz;
4681 					}
4682 					break;
4683 				case 32:
4684 					if (vz == 0) continue;
4685 					intz = z1;
4686 					if (((intz-zs)^vz) < 0) continue;
4687 					if ((cstat&64) != 0)
4688 						if ((zs > intz) == ((cstat&8)==0)) continue;
4689 
4690 					intx = xs+scale(intz-zs,vx,vz);
4691 					inty = ys+scale(intz-zs,vy,vz);
4692 
4693 					if (klabs(intx-xs)+klabs(inty-ys) > klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
4694 
4695 					tilenum = spr->picnum;
4696 					xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
4697 					yoff = (long)((signed char)((picanm[tilenum]>>16)&255))+((long)spr->yoffset);
4698 					if ((cstat&4) > 0) xoff = -xoff;
4699 					if ((cstat&8) > 0) yoff = -yoff;
4700 
4701 					ang = spr->ang;
4702 					cosang = sintable[(ang+512)&2047]; sinang = sintable[ang];
4703 					xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat;
4704 					yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat;
4705 
4706 					dax = ((xspan>>1)+xoff)*xrepeat; day = ((yspan>>1)+yoff)*yrepeat;
4707 					x1 += dmulscale16(sinang,dax,cosang,day)-intx;
4708 					y1 += dmulscale16(sinang,day,-cosang,dax)-inty;
4709 					l = xspan*xrepeat;
4710 					x2 = x1 - mulscale16(sinang,l);
4711 					y2 = y1 + mulscale16(cosang,l);
4712 					l = yspan*yrepeat;
4713 					k = -mulscale16(cosang,l); x3 = x2+k; x4 = x1+k;
4714 					k = -mulscale16(sinang,l); y3 = y2+k; y4 = y1+k;
4715 
4716 					clipyou = 0;
4717 					if ((y1^y2) < 0)
4718 					{
4719 						if ((x1^x2) < 0) clipyou ^= (x1*y2<x2*y1)^(y1<y2);
4720 						else if (x1 >= 0) clipyou ^= 1;
4721 					}
4722 					if ((y2^y3) < 0)
4723 					{
4724 						if ((x2^x3) < 0) clipyou ^= (x2*y3<x3*y2)^(y2<y3);
4725 						else if (x2 >= 0) clipyou ^= 1;
4726 					}
4727 					if ((y3^y4) < 0)
4728 					{
4729 						if ((x3^x4) < 0) clipyou ^= (x3*y4<x4*y3)^(y3<y4);
4730 						else if (x3 >= 0) clipyou ^= 1;
4731 					}
4732 					if ((y4^y1) < 0)
4733 					{
4734 						if ((x4^x1) < 0) clipyou ^= (x4*y1<x1*y4)^(y4<y1);
4735 						else if (x4 >= 0) clipyou ^= 1;
4736 					}
4737 
4738 					if (clipyou != 0)
4739 					{
4740 						*hitsect = dasector; *hitwall = -1; *hitsprite = z;
4741 						*hitx = intx; *hity = inty; *hitz = intz;
4742 					}
4743 					break;
4744 			}
4745 		}
4746 		tempshortcnt++;
4747 	} while (tempshortcnt < tempshortnum);
4748 	return(0);
4749 }
4750 
neartag(long xs,long ys,long zs,short sectnum,short ange,short * neartagsector,short * neartagwall,short * neartagsprite,long * neartaghitdist,long neartagrange,char tagsearch)4751 neartag (long xs, long ys, long zs, short sectnum, short ange, short *neartagsector, short *neartagwall, short *neartagsprite, long *neartaghitdist, long neartagrange, char tagsearch)
4752 {
4753 	walltype *wal, *wal2;
4754 	spritetype *spr;
4755 	long i, z, zz, xe, ye, ze, x1, y1, z1, x2, y2, z2, intx, inty, intz;
4756 	long topt, topu, bot, dist, offx, offy, vx, vy, vz;
4757 	short tempshortcnt, tempshortnum, dasector, startwall, endwall;
4758 	short nextsector, good;
4759 
4760 	*neartagsector = -1; *neartagwall = -1; *neartagsprite = -1;
4761 	*neartaghitdist = 0;
4762 
4763 	if (sectnum < 0) return(0);
4764 	if ((tagsearch < 1) || (tagsearch > 3)) return(0);
4765 
4766 	vx = mulscale14(sintable[(ange+2560)&2047],neartagrange); xe = xs+vx;
4767 	vy = mulscale14(sintable[(ange+2048)&2047],neartagrange); ye = ys+vy;
4768 	vz = 0; ze = 0;
4769 
4770 	clipsectorlist[0] = sectnum;
4771 	tempshortcnt = 0; tempshortnum = 1;
4772 
4773 	do
4774 	{
4775 		dasector = clipsectorlist[tempshortcnt];
4776 
4777 		startwall = sector[dasector].wallptr;
4778 		endwall = startwall + sector[dasector].wallnum - 1;
4779 		for(z=startwall,wal=&wall[startwall];z<=endwall;z++,wal++)
4780 		{
4781 			wal2 = &wall[wal->point2];
4782 			x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y;
4783 
4784 			nextsector = wal->nextsector;
4785 
4786 			good = 0;
4787 			if (nextsector >= 0)
4788 			{
4789 				if ((tagsearch&1) && sector[nextsector].lotag) good |= 1;
4790 				if ((tagsearch&2) && sector[nextsector].hitag) good |= 1;
4791 			}
4792 			if ((tagsearch&1) && wal->lotag) good |= 2;
4793 			if ((tagsearch&2) && wal->hitag) good |= 2;
4794 
4795 			if ((good == 0) && (nextsector < 0)) continue;
4796 			if ((x1-xs)*(y2-ys) < (x2-xs)*(y1-ys)) continue;
4797 
4798 			if (lintersect(xs,ys,zs,xe,ye,ze,x1,y1,x2,y2,&intx,&inty,&intz) == 1)
4799 			{
4800 				if (good != 0)
4801 				{
4802 					if (good&1) *neartagsector = nextsector;
4803 					if (good&2) *neartagwall = z;
4804 					*neartaghitdist = dmulscale14(intx-xs,sintable[(ange+2560)&2047],inty-ys,sintable[(ange+2048)&2047]);
4805 					xe = intx; ye = inty; ze = intz;
4806 				}
4807 				if (nextsector >= 0)
4808 				{
4809 					for(zz=tempshortnum-1;zz>=0;zz--)
4810 						if (clipsectorlist[zz] == nextsector) break;
4811 					if (zz < 0) clipsectorlist[tempshortnum++] = nextsector;
4812 				}
4813 			}
4814 		}
4815 
4816 		for(z=headspritesect[dasector];z>=0;z=nextspritesect[z])
4817 		{
4818 			spr = &sprite[z];
4819 
4820 			good = 0;
4821 			if ((tagsearch&1) && spr->lotag) good |= 1;
4822 			if ((tagsearch&2) && spr->hitag) good |= 1;
4823 			if (good != 0)
4824 			{
4825 				x1 = spr->x; y1 = spr->y; z1 = spr->z;
4826 
4827 				topt = vx*(x1-xs) + vy*(y1-ys);
4828 				if (topt > 0)
4829 				{
4830 					bot = vx*vx + vy*vy;
4831 					if (bot != 0)
4832 					{
4833 						intz = zs+scale(vz,topt,bot);
4834 						i = tilesizy[spr->picnum]*spr->yrepeat;
4835 						if (spr->cstat&128) z1 += (i<<1);
4836 						if (picanm[spr->picnum]&0x00ff0000) z1 -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
4837 						if ((intz <= z1) && (intz >= z1-(i<<2)))
4838 						{
4839 							topu = vx*(y1-ys) - vy*(x1-xs);
4840 
4841 							offx = scale(vx,topu,bot);
4842 							offy = scale(vy,topu,bot);
4843 							dist = offx*offx + offy*offy;
4844 							i = (tilesizx[spr->picnum]*spr->xrepeat); i *= i;
4845 							if (dist <= (i>>7))
4846 							{
4847 								intx = xs + scale(vx,topt,bot);
4848 								inty = ys + scale(vy,topt,bot);
4849 								if (klabs(intx-xs)+klabs(inty-ys) < klabs(xe-xs)+klabs(ye-ys))
4850 								{
4851 									*neartagsprite = z;
4852 									*neartaghitdist = dmulscale14(intx-xs,sintable[(ange+2560)&2047],inty-ys,sintable[(ange+2048)&2047]);
4853 									xe = intx;
4854 									ye = inty;
4855 									ze = intz;
4856 								}
4857 							}
4858 						}
4859 					}
4860 				}
4861 			}
4862 		}
4863 
4864 		tempshortcnt++;
4865 	} while (tempshortcnt < tempshortnum);
4866 	return(0);
4867 }
4868 
lintersect(long x1,long y1,long z1,long x2,long y2,long z2,long x3,long y3,long x4,long y4,long * intx,long * inty,long * intz)4869 lintersect(long x1, long y1, long z1, long x2, long y2, long z2, long x3,
4870 			  long y3, long x4, long y4, long *intx, long *inty, long *intz)
4871 {     //p1 to p2 is a line segment
4872 	long x21, y21, x34, y34, x31, y31, bot, topt, topu, t;
4873 
4874 	x21 = x2-x1; x34 = x3-x4;
4875 	y21 = y2-y1; y34 = y3-y4;
4876 	bot = x21*y34 - y21*x34;
4877 	if (bot >= 0)
4878 	{
4879 		if (bot == 0) return(0);
4880 		x31 = x3-x1; y31 = y3-y1;
4881 		topt = x31*y34 - y31*x34; if ((topt < 0) || (topt >= bot)) return(0);
4882 		topu = x21*y31 - y21*x31; if ((topu < 0) || (topu >= bot)) return(0);
4883 	}
4884 	else
4885 	{
4886 		x31 = x3-x1; y31 = y3-y1;
4887 		topt = x31*y34 - y31*x34; if ((topt > 0) || (topt <= bot)) return(0);
4888 		topu = x21*y31 - y21*x31; if ((topu > 0) || (topu <= bot)) return(0);
4889 	}
4890 	t = divscale24(topt,bot);
4891 	*intx = x1 + mulscale24(x21,t);
4892 	*inty = y1 + mulscale24(y21,t);
4893 	*intz = z1 + mulscale24(z2-z1,t);
4894 	return(1);
4895 }
4896 
rintersect(long x1,long y1,long z1,long vx,long vy,long vz,long x3,long y3,long x4,long y4,long * intx,long * inty,long * intz)4897 rintersect(long x1, long y1, long z1, long vx, long vy, long vz, long x3,
4898 			  long y3, long x4, long y4, long *intx, long *inty, long *intz)
4899 {     //p1 towards p2 is a ray
4900 	long x34, y34, x31, y31, bot, topt, topu, t;
4901 
4902 	x34 = x3-x4; y34 = y3-y4;
4903 	bot = vx*y34 - vy*x34;
4904 	if (bot >= 0)
4905 	{
4906 		if (bot == 0) return(0);
4907 		x31 = x3-x1; y31 = y3-y1;
4908 		topt = x31*y34 - y31*x34; if (topt < 0) return(0);
4909 		topu = vx*y31 - vy*x31; if ((topu < 0) || (topu >= bot)) return(0);
4910 	}
4911 	else
4912 	{
4913 		x31 = x3-x1; y31 = y3-y1;
4914 		topt = x31*y34 - y31*x34; if (topt > 0) return(0);
4915 		topu = vx*y31 - vy*x31; if ((topu > 0) || (topu <= bot)) return(0);
4916 	}
4917 	t = divscale16(topt,bot);
4918 	*intx = x1 + mulscale16(vx,t);
4919 	*inty = y1 + mulscale16(vy,t);
4920 	*intz = z1 + mulscale16(vz,t);
4921 	return(1);
4922 }
4923 
dragpoint(short pointhighlight,long dax,long day)4924 dragpoint(short pointhighlight, long dax, long day)
4925 {
4926 	short cnt, tempshort;
4927 
4928 	wall[pointhighlight].x = dax;
4929 	wall[pointhighlight].y = day;
4930 
4931 	cnt = MAXWALLS;
4932 	tempshort = pointhighlight;    //search points CCW
4933 	do
4934 	{
4935 		if (wall[tempshort].nextwall >= 0)
4936 		{
4937 			tempshort = wall[wall[tempshort].nextwall].point2;
4938 			wall[tempshort].x = dax;
4939 			wall[tempshort].y = day;
4940 		}
4941 		else
4942 		{
4943 			tempshort = pointhighlight;    //search points CW if not searched all the way around
4944 			do
4945 			{
4946 				if (wall[lastwall(tempshort)].nextwall >= 0)
4947 				{
4948 					tempshort = wall[lastwall(tempshort)].nextwall;
4949 					wall[tempshort].x = dax;
4950 					wall[tempshort].y = day;
4951 				}
4952 				else
4953 				{
4954 					break;
4955 				}
4956 				cnt--;
4957 			}
4958 			while ((tempshort != pointhighlight) && (cnt > 0));
4959 			break;
4960 		}
4961 		cnt--;
4962 	}
4963 	while ((tempshort != pointhighlight) && (cnt > 0));
4964 }
4965 
lastwall(short point)4966 lastwall(short point)
4967 {
4968 	long i, j, cnt;
4969 
4970 	if ((point > 0) && (wall[point-1].point2 == point)) return(point-1);
4971 	i = point;
4972 	cnt = MAXWALLS;
4973 	do
4974 	{
4975 		j = wall[i].point2;
4976 		if (j == point) return(i);
4977 		i = j;
4978 		cnt--;
4979 	} while (cnt > 0);
4980 	return(point);
4981 }
4982 
4983 #define addclipline(dax1, day1, dax2, day2, daoval)      \
4984 {                                                        \
4985 	clipit[clipnum].x1 = dax1; clipit[clipnum].y1 = day1; \
4986 	clipit[clipnum].x2 = dax2; clipit[clipnum].y2 = day2; \
4987 	clipobjectval[clipnum] = daoval;                      \
4988 	clipnum++;                                            \
4989 }                                                        \
4990 
4991 long clipmoveboxtracenum = 3;
clipmove(long * x,long * y,long * z,short * sectnum,long xvect,long yvect,long walldist,long ceildist,long flordist,unsigned long cliptype)4992 clipmove (long *x, long *y, long *z, short *sectnum,
4993 			 long xvect, long yvect,
4994 			 long walldist, long ceildist, long flordist, unsigned long cliptype)
4995 {
4996 	walltype *wal, *wal2;
4997 	spritetype *spr;
4998 	sectortype *sec, *sec2;
4999 	long i, j, templong1, templong2;
5000 	long oxvect, oyvect, goalx, goaly, intx, inty, lx, ly, retval;
5001 	long k, l, clipsectcnt, startwall, endwall, cstat, dasect;
5002 	long x1, y1, x2, y2, cx, cy, rad, xmin, ymin, xmax, ymax, daz, daz2;
5003 	long bsz, dax, day, xoff, yoff, xspan, yspan, cosang, sinang, tilenum;
5004 	long xrepeat, yrepeat, gx, gy, dx, dy, dasprclipmask, dawalclipmask;
5005 	long hitwall, cnt, clipyou;
5006 
5007 	if (((xvect|yvect) == 0) || (*sectnum < 0)) return(0);
5008 	retval = 0;
5009 
5010 	oxvect = xvect;
5011 	oyvect = yvect;
5012 
5013 	goalx = (*x) + (xvect>>14);
5014 	goaly = (*y) + (yvect>>14);
5015 
5016 
5017 	clipnum = 0;
5018 
5019 	cx = (((*x)+goalx)>>1);
5020 	cy = (((*y)+goaly)>>1);
5021 		//Extra walldist for sprites on sector lines
5022 	gx = goalx-(*x); gy = goaly-(*y);
5023 	rad = nsqrtasm(gx*gx + gy*gy) + MAXCLIPDIST+walldist + 8;
5024 	xmin = cx-rad; ymin = cy-rad;
5025 	xmax = cx+rad; ymax = cy+rad;
5026 
5027 	dawalclipmask = (cliptype&65535);        //CLIPMASK0 = 0x00010001
5028 	dasprclipmask = (cliptype>>16);          //CLIPMASK1 = 0x01000040
5029 
5030 	clipsectorlist[0] = (*sectnum);
5031 	clipsectcnt = 0; clipsectnum = 1;
5032 	do
5033 	{
5034 		dasect = clipsectorlist[clipsectcnt++];
5035 		sec = &sector[dasect];
5036 		startwall = sec->wallptr; endwall = startwall + sec->wallnum;
5037 		for(j=startwall,wal=&wall[startwall];j<endwall;j++,wal++)
5038 		{
5039 			wal2 = &wall[wal->point2];
5040 			if ((wal->x < xmin) && (wal2->x < xmin)) continue;
5041 			if ((wal->x > xmax) && (wal2->x > xmax)) continue;
5042 			if ((wal->y < ymin) && (wal2->y < ymin)) continue;
5043 			if ((wal->y > ymax) && (wal2->y > ymax)) continue;
5044 
5045 			x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y;
5046 
5047 			dx = x2-x1; dy = y2-y1;
5048 			if (dx*((*y)-y1) < ((*x)-x1)*dy) continue;  //If wall's not facing you
5049 
5050 			if (dx > 0) dax = dx*(ymin-y1); else dax = dx*(ymax-y1);
5051 			if (dy > 0) day = dy*(xmax-x1); else day = dy*(xmin-x1);
5052 			if (dax >= day) continue;
5053 
5054 			clipyou = 0;
5055 			if ((wal->nextsector < 0) || (wal->cstat&dawalclipmask)) clipyou = 1;
5056 			else if (editstatus == 0)
5057 			{
5058 				if (rintersect(*x,*y,0,gx,gy,0,x1,y1,x2,y2,&dax,&day,&daz) == 0)
5059 					dax = *x, day = *y;
5060 				daz = getflorzofslope((short)dasect,dax,day);
5061 				daz2 = getflorzofslope(wal->nextsector,dax,day);
5062 
5063 				sec2 = &sector[wal->nextsector];
5064 				if (daz2 < daz-(1<<8))
5065 					if ((sec2->floorstat&1) == 0)
5066 						if ((*z) >= daz2-(flordist-1)) clipyou = 1;
5067 				if (clipyou == 0)
5068 				{
5069 					daz = getceilzofslope((short)dasect,dax,day);
5070 					daz2 = getceilzofslope(wal->nextsector,dax,day);
5071 					if (daz2 > daz+(1<<8))
5072 						if ((sec2->ceilingstat&1) == 0)
5073 							if ((*z) <= daz2+(ceildist-1)) clipyou = 1;
5074 				}
5075 			}
5076 
5077 			if (clipyou)
5078 			{
5079 					//Add 2 boxes at endpoints
5080 				bsz = walldist; if (gx < 0) bsz = -bsz;
5081 				addclipline(x1-bsz,y1-bsz,x1-bsz,y1+bsz,(short)j+32768);
5082 				addclipline(x2-bsz,y2-bsz,x2-bsz,y2+bsz,(short)j+32768);
5083 				bsz = walldist; if (gy < 0) bsz = -bsz;
5084 				addclipline(x1+bsz,y1-bsz,x1-bsz,y1-bsz,(short)j+32768);
5085 				addclipline(x2+bsz,y2-bsz,x2-bsz,y2-bsz,(short)j+32768);
5086 
5087 				dax = walldist; if (dy > 0) dax = -dax;
5088 				day = walldist; if (dx < 0) day = -day;
5089 				addclipline(x1+dax,y1+day,x2+dax,y2+day,(short)j+32768);
5090 			}
5091 			else
5092 			{
5093 				for(i=clipsectnum-1;i>=0;i--)
5094 					if (wal->nextsector == clipsectorlist[i]) break;
5095 				if (i < 0) clipsectorlist[clipsectnum++] = wal->nextsector;
5096 			}
5097 		}
5098 
5099 		for(j=headspritesect[dasect];j>=0;j=nextspritesect[j])
5100 		{
5101 			spr = &sprite[j];
5102 			cstat = spr->cstat;
5103 			if ((cstat&dasprclipmask) == 0) continue;
5104 			x1 = spr->x; y1 = spr->y;
5105 			switch(cstat&48)
5106 			{
5107 				case 0:
5108 					if ((x1 >= xmin) && (x1 <= xmax) && (y1 >= ymin) && (y1 <= ymax))
5109 					{
5110 						k = ((tilesizy[spr->picnum]*spr->yrepeat)<<2);
5111 						if (cstat&128) daz = spr->z+(k>>1); else daz = spr->z;
5112 						if (picanm[spr->picnum]&0x00ff0000) daz -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
5113 						if (((*z) < daz+ceildist) && ((*z) > daz-k-flordist))
5114 						{
5115 							bsz = (spr->clipdist<<2)+walldist; if (gx < 0) bsz = -bsz;
5116 							addclipline(x1-bsz,y1-bsz,x1-bsz,y1+bsz,(short)j+49152);
5117 							bsz = (spr->clipdist<<2)+walldist; if (gy < 0) bsz = -bsz;
5118 							addclipline(x1+bsz,y1-bsz,x1-bsz,y1-bsz,(short)j+49152);
5119 						}
5120 					}
5121 					break;
5122 				case 16:
5123 					k = ((tilesizy[spr->picnum]*spr->yrepeat)<<2);
5124 					if (cstat&128) daz = spr->z+(k>>1); else daz = spr->z;
5125 					if (picanm[spr->picnum]&0x00ff0000) daz -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
5126 					daz2 = daz-k;
5127 					daz += ceildist; daz2 -= flordist;
5128 					if (((*z) < daz) && ((*z) > daz2))
5129 					{
5130 							//These lines get the 2 points of the rotated sprite
5131 							//Given: (x1, y1) starts out as the center point
5132 						tilenum = spr->picnum;
5133 						xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
5134 						if ((cstat&4) > 0) xoff = -xoff;
5135 						k = spr->ang; l = spr->xrepeat;
5136 						dax = sintable[k&2047]*l; day = sintable[(k+1536)&2047]*l;
5137 						l = tilesizx[tilenum]; k = (l>>1)+xoff;
5138 						x1 -= mulscale16(dax,k); x2 = x1+mulscale16(dax,l);
5139 						y1 -= mulscale16(day,k); y2 = y1+mulscale16(day,l);
5140 						if (clipinsideboxline(cx,cy,x1,y1,x2,y2,rad) != 0)
5141 						{
5142 							dax = mulscale14(sintable[(spr->ang+256+512)&2047],walldist);
5143 							day = mulscale14(sintable[(spr->ang+256)&2047],walldist);
5144 
5145 							if ((x1-(*x))*(y2-(*y)) >= (x2-(*x))*(y1-(*y)))   //Front
5146 							{
5147 								addclipline(x1+dax,y1+day,x2+day,y2-dax,(short)j+49152);
5148 							}
5149 							else
5150 							{
5151 								if ((cstat&64) != 0) continue;
5152 								addclipline(x2-dax,y2-day,x1-day,y1+dax,(short)j+49152);
5153 							}
5154 
5155 								//Side blocker
5156 							if ((x2-x1)*((*x)-x1) + (y2-y1)*((*y)-y1) < 0)
5157 								{ addclipline(x1-day,y1+dax,x1+dax,y1+day,(short)j+49152); }
5158 							else if ((x1-x2)*((*x)-x2) + (y1-y2)*((*y)-y2) < 0)
5159 								{ addclipline(x2+day,y2-dax,x2-dax,y2-day,(short)j+49152); }
5160 						}
5161 					}
5162 					break;
5163 				case 32:
5164 					daz = spr->z+ceildist;
5165 					daz2 = spr->z-flordist;
5166 					if (((*z) < daz) && ((*z) > daz2))
5167 					{
5168 						if ((cstat&64) != 0)
5169 							if (((*z) > spr->z) == ((cstat&8)==0)) continue;
5170 
5171 						tilenum = spr->picnum;
5172 						xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
5173 						yoff = (long)((signed char)((picanm[tilenum]>>16)&255))+((long)spr->yoffset);
5174 						if ((cstat&4) > 0) xoff = -xoff;
5175 						if ((cstat&8) > 0) yoff = -yoff;
5176 
5177 						k = spr->ang;
5178 						cosang = sintable[(k+512)&2047]; sinang = sintable[k];
5179 						xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat;
5180 						yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat;
5181 
5182 						dax = ((xspan>>1)+xoff)*xrepeat; day = ((yspan>>1)+yoff)*yrepeat;
5183 						rxi[0] = x1 + dmulscale16(sinang,dax,cosang,day);
5184 						ryi[0] = y1 + dmulscale16(sinang,day,-cosang,dax);
5185 						l = xspan*xrepeat;
5186 						rxi[1] = rxi[0] - mulscale16(sinang,l);
5187 						ryi[1] = ryi[0] + mulscale16(cosang,l);
5188 						l = yspan*yrepeat;
5189 						k = -mulscale16(cosang,l); rxi[2] = rxi[1]+k; rxi[3] = rxi[0]+k;
5190 						k = -mulscale16(sinang,l); ryi[2] = ryi[1]+k; ryi[3] = ryi[0]+k;
5191 
5192 						dax = mulscale14(sintable[(spr->ang-256+512)&2047],walldist);
5193 						day = mulscale14(sintable[(spr->ang-256)&2047],walldist);
5194 
5195 						if ((rxi[0]-(*x))*(ryi[1]-(*y)) < (rxi[1]-(*x))*(ryi[0]-(*y)))
5196 						{
5197 							if (clipinsideboxline(cx,cy,rxi[1],ryi[1],rxi[0],ryi[0],rad) != 0)
5198 								addclipline(rxi[1]-day,ryi[1]+dax,rxi[0]+dax,ryi[0]+day,(short)j+49152);
5199 						}
5200 						else if ((rxi[2]-(*x))*(ryi[3]-(*y)) < (rxi[3]-(*x))*(ryi[2]-(*y)))
5201 						{
5202 							if (clipinsideboxline(cx,cy,rxi[3],ryi[3],rxi[2],ryi[2],rad) != 0)
5203 								addclipline(rxi[3]+day,ryi[3]-dax,rxi[2]-dax,ryi[2]-day,(short)j+49152);
5204 						}
5205 
5206 						if ((rxi[1]-(*x))*(ryi[2]-(*y)) < (rxi[2]-(*x))*(ryi[1]-(*y)))
5207 						{
5208 							if (clipinsideboxline(cx,cy,rxi[2],ryi[2],rxi[1],ryi[1],rad) != 0)
5209 								addclipline(rxi[2]-dax,ryi[2]-day,rxi[1]-day,ryi[1]+dax,(short)j+49152);
5210 						}
5211 						else if ((rxi[3]-(*x))*(ryi[0]-(*y)) < (rxi[0]-(*x))*(ryi[3]-(*y)))
5212 						{
5213 							if (clipinsideboxline(cx,cy,rxi[0],ryi[0],rxi[3],ryi[3],rad) != 0)
5214 								addclipline(rxi[0]+dax,ryi[0]+day,rxi[3]+day,ryi[3]-dax,(short)j+49152);
5215 						}
5216 					}
5217 					break;
5218 			}
5219 		}
5220 	} while (clipsectcnt < clipsectnum);
5221 
5222 
5223 	hitwall = 0;
5224 	cnt = clipmoveboxtracenum;
5225 	do
5226 	{
5227 		intx = goalx; inty = goaly;
5228 		if ((hitwall = raytrace(*x, *y, &intx, &inty)) >= 0)
5229 		{
5230 			lx = clipit[hitwall].x2-clipit[hitwall].x1;
5231 			ly = clipit[hitwall].y2-clipit[hitwall].y1;
5232 			templong2 = lx*lx + ly*ly;
5233 			if (templong2 > 0)
5234 			{
5235 				templong1 = (goalx-intx)*lx + (goaly-inty)*ly;
5236 
5237 				if ((klabs(templong1)>>11) < templong2)
5238 					i = divscale20(templong1,templong2);
5239 				else
5240 					i = 0;
5241 				goalx = mulscale20(lx,i)+intx;
5242 				goaly = mulscale20(ly,i)+inty;
5243 			}
5244 
5245 			templong1 = dmulscale6(lx,oxvect,ly,oyvect);
5246 			for(i=cnt+1;i<=clipmoveboxtracenum;i++)
5247 			{
5248 				j = hitwalls[i];
5249 				templong2 = dmulscale6(clipit[j].x2-clipit[j].x1,oxvect,clipit[j].y2-clipit[j].y1,oyvect);
5250 				if ((templong1^templong2) < 0)
5251 				{
5252 					updatesector(*x,*y,sectnum);
5253 					return(retval);
5254 				}
5255 			}
5256 
5257 			keepaway(&goalx, &goaly, hitwall);
5258 			xvect = ((goalx-intx)<<14);
5259 			yvect = ((goaly-inty)<<14);
5260 
5261 			if (cnt == clipmoveboxtracenum) retval = clipobjectval[hitwall];
5262 			hitwalls[cnt] = hitwall;
5263 		}
5264 		cnt--;
5265 
5266 		*x = intx;
5267 		*y = inty;
5268 	} while (((xvect|yvect) != 0) && (hitwall >= 0) && (cnt > 0));
5269 
5270 	for(j=0;j<clipsectnum;j++)
5271 		if (inside(*x,*y,clipsectorlist[j]) == 1)
5272 		{
5273 			*sectnum = clipsectorlist[j];
5274 			return(retval);
5275 		}
5276 
5277 	*sectnum = -1; templong1 = 0x7fffffff;
5278 	for(j=numsectors-1;j>=0;j--)
5279 		if (inside(*x,*y,j) == 1)
5280 		{
5281 			if (sector[j].ceilingstat&2)
5282 				templong2 = (getceilzofslope((short)j,*x,*y)-(*z));
5283 			else
5284 				templong2 = (sector[j].ceilingz-(*z));
5285 
5286 			if (templong2 > 0)
5287 			{
5288 				if (templong2 < templong1)
5289 					{ *sectnum = j; templong1 = templong2; }
5290 			}
5291 			else
5292 			{
5293 				if (sector[j].floorstat&2)
5294 					templong2 = ((*z)-getflorzofslope((short)j,*x,*y));
5295 				else
5296 					templong2 = ((*z)-sector[j].floorz);
5297 
5298 				if (templong2 <= 0)
5299 				{
5300 					*sectnum = j;
5301 					return(retval);
5302 				}
5303 				if (templong2 < templong1)
5304 					{ *sectnum = j; templong1 = templong2; }
5305 			}
5306 		}
5307 
5308 	return(retval);
5309 }
5310 
keepaway(long * x,long * y,long w)5311 keepaway (long *x, long *y, long w)
5312 {
5313 	long dx, dy, ox, oy, x1, y1;
5314 	char first;
5315 
5316 	x1 = clipit[w].x1; dx = clipit[w].x2-x1;
5317 	y1 = clipit[w].y1; dy = clipit[w].y2-y1;
5318 	ox = ksgn(-dy); oy = ksgn(dx);
5319 	first = (klabs(dx) <= klabs(dy));
5320 	while (1)
5321 	{
5322 		if (dx*(*y-y1) > (*x-x1)*dy) return;
5323 		if (first == 0) *x += ox; else *y += oy;
5324 		first ^= 1;
5325 	}
5326 }
5327 
raytrace(long x3,long y3,long * x4,long * y4)5328 raytrace (long x3, long y3, long *x4, long *y4)
5329 {
5330 	long x1, y1, x2, y2, t, bot, topu, nintx, ninty, cnt, z, hitwall;
5331 	long x21, y21, x43, y43;
5332 
5333 	hitwall = -1;
5334 	for(z=clipnum-1;z>=0;z--)
5335 	{
5336 		x1 = clipit[z].x1; x2 = clipit[z].x2; x21 = x2-x1;
5337 		y1 = clipit[z].y1; y2 = clipit[z].y2; y21 = y2-y1;
5338 
5339 		topu = x21*(y3-y1) - (x3-x1)*y21; if (topu <= 0) continue;
5340 		if (x21*(*y4-y1) > (*x4-x1)*y21) continue;
5341 		x43 = *x4-x3; y43 = *y4-y3;
5342 		if (x43*(y1-y3) > (x1-x3)*y43) continue;
5343 		if (x43*(y2-y3) <= (x2-x3)*y43) continue;
5344 		bot = x43*y21 - x21*y43; if (bot == 0) continue;
5345 
5346 		cnt = 256;
5347 		do
5348 		{
5349 			cnt--; if (cnt < 0) { *x4 = x3; *y4 = y3; return(z); }
5350 			nintx = x3 + scale(x43,topu,bot);
5351 			ninty = y3 + scale(y43,topu,bot);
5352 			topu--;
5353 		} while (x21*(ninty-y1) <= (nintx-x1)*y21);
5354 
5355 		if (klabs(x3-nintx)+klabs(y3-ninty) < klabs(x3-*x4)+klabs(y3-*y4))
5356 			{ *x4 = nintx; *y4 = ninty; hitwall = z; }
5357 	}
5358 	return(hitwall);
5359 }
5360 
pushmove(long * x,long * y,long * z,short * sectnum,long walldist,long ceildist,long flordist,unsigned long cliptype)5361 pushmove (long *x, long *y, long *z, short *sectnum,
5362 			 long walldist, long ceildist, long flordist, unsigned long cliptype)
5363 {
5364 	sectortype *sec, *sec2;
5365 	walltype *wal, *wal2;
5366 	spritetype *spr;
5367 	long i, j, k, t, dx, dy, dax, day, daz, daz2, bad, dir;
5368 	long dasprclipmask, dawalclipmask;
5369 	short startwall, endwall, clipsectcnt;
5370 	char bad2;
5371 
5372 	if ((*sectnum) < 0) return(-1);
5373 
5374 	dawalclipmask = (cliptype&65535);
5375 	dasprclipmask = (cliptype>>16);
5376 
5377 	k = 32;
5378 	dir = 1;
5379 	do
5380 	{
5381 		bad = 0;
5382 
5383 		clipsectorlist[0] = *sectnum;
5384 		clipsectcnt = 0; clipsectnum = 1;
5385 		do
5386 		{
5387 			/*Push FACE sprites
5388 			for(i=headspritesect[clipsectorlist[clipsectcnt]];i>=0;i=nextspritesect[i])
5389 			{
5390 				spr = &sprite[i];
5391 				if (((spr->cstat&48) != 0) && ((spr->cstat&48) != 48)) continue;
5392 				if ((spr->cstat&dasprclipmask) == 0) continue;
5393 
5394 				dax = (*x)-spr->x; day = (*y)-spr->y;
5395 				t = (spr->clipdist<<2)+walldist;
5396 				if ((klabs(dax) < t) && (klabs(day) < t))
5397 				{
5398 					t = ((tilesizy[spr->picnum]*spr->yrepeat)<<2);
5399 					if (spr->cstat&128) daz = spr->z+(t>>1); else daz = spr->z;
5400 					if (picanm[spr->picnum]&0x00ff0000) daz -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
5401 					if (((*z) < daz+ceildist) && ((*z) > daz-t-flordist))
5402 					{
5403 						t = (spr->clipdist<<2)+walldist;
5404 
5405 						j = getangle(dax,day);
5406 						dx = (sintable[(j+512)&2047]>>11);
5407 						dy = (sintable[(j)&2047]>>11);
5408 						bad2 = 16;
5409 						do
5410 						{
5411 							*x = (*x) + dx; *y = (*y) + dy;
5412 							bad2--; if (bad2 == 0) break;
5413 						} while ((klabs((*x)-spr->x) < t) && (klabs((*y)-spr->y) < t));
5414 						bad = -1;
5415 						k--; if (k <= 0) return(bad);
5416 						updatesector(*x,*y,sectnum);
5417 					}
5418 				}
5419 			}*/
5420 
5421 			sec = &sector[clipsectorlist[clipsectcnt]];
5422 			if (dir > 0)
5423 				startwall = sec->wallptr, endwall = startwall + sec->wallnum;
5424 			else
5425 				endwall = sec->wallptr, startwall = endwall + sec->wallnum;
5426 
5427 			for(i=startwall,wal=&wall[startwall];i!=endwall;i+=dir,wal+=dir)
5428 				if (clipinsidebox(*x,*y,i,walldist-4) == 1)
5429 				{
5430 					j = 0;
5431 					if (wal->nextsector < 0) j = 1;
5432 					if (wal->cstat&dawalclipmask) j = 1;
5433 					if (j == 0)
5434 					{
5435 						sec2 = &sector[wal->nextsector];
5436 
5437 
5438 							//Find closest point on wall (dax, day) to (*x, *y)
5439 						dax = wall[wal->point2].x-wal->x;
5440 						day = wall[wal->point2].y-wal->y;
5441 						daz = dax*((*x)-wal->x) + day*((*y)-wal->y);
5442 						if (daz <= 0)
5443 							t = 0;
5444 						else
5445 						{
5446 							daz2 = dax*dax+day*day;
5447 							if (daz >= daz2) t = (1<<30); else t = divscale30(daz,daz2);
5448 						}
5449 						dax = wal->x + mulscale30(dax,t);
5450 						day = wal->y + mulscale30(day,t);
5451 
5452 
5453 						daz = getflorzofslope(clipsectorlist[clipsectcnt],dax,day);
5454 						daz2 = getflorzofslope(wal->nextsector,dax,day);
5455 						if ((daz2 < daz-(1<<8)) && ((sec2->floorstat&1) == 0))
5456 							if (*z >= daz2-(flordist-1)) j = 1;
5457 
5458 						daz = getceilzofslope(clipsectorlist[clipsectcnt],dax,day);
5459 						daz2 = getceilzofslope(wal->nextsector,dax,day);
5460 						if ((daz2 > daz+(1<<8)) && ((sec2->ceilingstat&1) == 0))
5461 							if (*z <= daz2+(ceildist-1)) j = 1;
5462 					}
5463 					if (j != 0)
5464 					{
5465 						j = getangle(wall[wal->point2].x-wal->x,wall[wal->point2].y-wal->y);
5466 						dx = (sintable[(j+1024)&2047]>>11);
5467 						dy = (sintable[(j+512)&2047]>>11);
5468 						bad2 = 16;
5469 						do
5470 						{
5471 							*x = (*x) + dx; *y = (*y) + dy;
5472 							bad2--; if (bad2 == 0) break;
5473 						} while (clipinsidebox(*x,*y,i,walldist-4) != 0);
5474 						bad = -1;
5475 						k--; if (k <= 0) return(bad);
5476 						updatesector(*x,*y,sectnum);
5477 					}
5478 					else
5479 					{
5480 						for(j=clipsectnum-1;j>=0;j--)
5481 							if (wal->nextsector == clipsectorlist[j]) break;
5482 						if (j < 0) clipsectorlist[clipsectnum++] = wal->nextsector;
5483 					}
5484 				}
5485 
5486 			clipsectcnt++;
5487 		} while (clipsectcnt < clipsectnum);
5488 		dir = -dir;
5489 	} while (bad != 0);
5490 
5491 	return(bad);
5492 }
5493 
updatesector(long x,long y,short * sectnum)5494 updatesector(long x, long y, short *sectnum)
5495 {
5496 	walltype *wal;
5497 	long i, j;
5498 
5499 	if (inside(x,y,*sectnum) == 1) return;
5500 
5501 	if ((*sectnum >= 0) && (*sectnum < numsectors))
5502 	{
5503 		wal = &wall[sector[*sectnum].wallptr];
5504 		j = sector[*sectnum].wallnum;
5505 		do
5506 		{
5507 			i = wal->nextsector;
5508 			if (i >= 0)
5509 				if (inside(x,y,(short)i) == 1)
5510 				{
5511 					*sectnum = i;
5512 					return;
5513 				}
5514 			wal++;
5515 			j--;
5516 		} while (j != 0);
5517 	}
5518 
5519 	for(i=numsectors-1;i>=0;i--)
5520 		if (inside(x,y,(short)i) == 1)
5521 		{
5522 			*sectnum = i;
5523 			return;
5524 		}
5525 
5526 	*sectnum = -1;
5527 }
5528 
rotatepoint(long xpivot,long ypivot,long x,long y,short daang,long * x2,long * y2)5529 rotatepoint(long xpivot, long ypivot, long x, long y, short daang, long *x2, long *y2)
5530 {
5531 	long dacos, dasin;
5532 
5533 	dacos = sintable[(daang+2560)&2047];
5534 	dasin = sintable[(daang+2048)&2047];
5535 	x -= xpivot;
5536 	y -= ypivot;
5537 	*x2 = dmulscale14(x,dacos,-y,dasin) + xpivot;
5538 	*y2 = dmulscale14(y,dacos,x,dasin) + ypivot;
5539 }
5540 
initmouse()5541 initmouse()
5542 {
5543 	return(moustat = setupmouse());
5544 }
5545 
getmousevalues(short * mousx,short * mousy,short * bstatus)5546 getmousevalues(short *mousx, short *mousy, short *bstatus)
5547 {
5548 	if (moustat == 0) { *mousx = 0; *mousy = 0; *bstatus = 0; return; }
5549 	readmousexy(mousx,mousy);
5550 	readmousebstatus(bstatus);
5551 }
5552 
printscreeninterrupt()5553 printscreeninterrupt()
5554 {
5555 	int5();
5556 }
5557 
drawline256(long x1,long y1,long x2,long y2,char col)5558 drawline256 (long x1, long y1, long x2, long y2, char col)
5559 {
5560 	long dx, dy, i, j, p, inc, plc, daend;
5561 
5562 	col = palookup[0][col];
5563 
5564 	dx = x2-x1; dy = y2-y1;
5565 	if (dx >= 0)
5566 	{
5567 		if ((x1 >= wx2) || (x2 < wx1)) return;
5568 		if (x1 < wx1) y1 += scale(wx1-x1,dy,dx), x1 = wx1;
5569 		if (x2 > wx2) y2 += scale(wx2-x2,dy,dx), x2 = wx2;
5570 	}
5571 	else
5572 	{
5573 		if ((x2 >= wx2) || (x1 < wx1)) return;
5574 		if (x2 < wx1) y2 += scale(wx1-x2,dy,dx), x2 = wx1;
5575 		if (x1 > wx2) y1 += scale(wx2-x1,dy,dx), x1 = wx2;
5576 	}
5577 	if (dy >= 0)
5578 	{
5579 		if ((y1 >= wy2) || (y2 < wy1)) return;
5580 		if (y1 < wy1) x1 += scale(wy1-y1,dx,dy), y1 = wy1;
5581 		if (y2 > wy2) x2 += scale(wy2-y2,dx,dy), y2 = wy2;
5582 	}
5583 	else
5584 	{
5585 		if ((y2 >= wy2) || (y1 < wy1)) return;
5586 		if (y2 < wy1) x2 += scale(wy1-y2,dx,dy), y2 = wy1;
5587 		if (y1 > wy2) x1 += scale(wy2-y1,dx,dy), y1 = wy2;
5588 	}
5589 
5590 	if (klabs(dx) >= klabs(dy))
5591 	{
5592 		if (dx == 0) return;
5593 		if (dx < 0)
5594 		{
5595 			i = x1; x1 = x2; x2 = i;
5596 			i = y1; y1 = y2; y2 = i;
5597 		}
5598 
5599 		inc = divscale12(dy,dx);
5600 		plc = y1+mulscale12((2047-x1)&4095,inc);
5601 		i = ((x1+2048)>>12); daend = ((x2+2048)>>12);
5602 		for(;i<daend;i++)
5603 		{
5604 			j = (plc>>12);
5605 			if ((j >= startumost[i]) && (j < startdmost[i]))
5606 				drawpixel(ylookup[j]+i+frameplace,col);
5607 			plc += inc;
5608 		}
5609 	}
5610 	else
5611 	{
5612 		if (dy < 0)
5613 		{
5614 			i = x1; x1 = x2; x2 = i;
5615 			i = y1; y1 = y2; y2 = i;
5616 		}
5617 
5618 		inc = divscale12(dx,dy);
5619 		plc = x1+mulscale12((2047-y1)&4095,inc);
5620 		i = ((y1+2048)>>12); daend = ((y2+2048)>>12);
5621 		p = ylookup[i]+frameplace;
5622 		for(;i<daend;i++)
5623 		{
5624 			j = (plc>>12);
5625 			if ((i >= startumost[j]) && (i < startdmost[j]))
5626 				drawpixel(j+p,col);
5627 			plc += inc; p += ylookup[1];
5628 		}
5629 	}
5630 }
5631 
drawline16(long x1,long y1,long x2,long y2,char col)5632 drawline16(long x1, long y1, long x2, long y2, char col)
5633 {
5634 	long i, dx, dy, p, pinc, d;
5635 	char lmask, rmask;
5636 
5637 	dx = x2-x1; dy = y2-y1;
5638 	if (dx >= 0)
5639 	{
5640 		if ((x1 > 639) || (x2 < 0)) return;
5641 		if (x1 < 0) { if (dy) y1 += scale(0-x1,dy,dx); x1 = 0; }
5642 		if (x2 > 639) { if (dy) y2 += scale(639-x2,dy,dx); x2 = 639; }
5643 	}
5644 	else
5645 	{
5646 		if ((x2 > 639) || (x1 < 0)) return;
5647 		if (x2 < 0) { if (dy) y2 += scale(0-x2,dy,dx); x2 = 0; }
5648 		if (x1 > 639) { if (dy) y1 += scale(639-x1,dy,dx); x1 = 639; }
5649 	}
5650 	if (dy >= 0)
5651 	{
5652 		if ((y1 >= ydim16) || (y2 < 0)) return;
5653 		if (y1 < 0) { if (dx) x1 += scale(0-y1,dx,dy); y1 = 0; }
5654 		if (y2 >= ydim16) { if (dx) x2 += scale(ydim16-1-y2,dx,dy); y2 = ydim16-1; }
5655 	}
5656 	else
5657 	{
5658 		if ((y2 >= ydim16) || (y1 < 0)) return;
5659 		if (y2 < 0) { if (dx) x2 += scale(0-y2,dx,dy); y2 = 0; }
5660 		if (y1 >= ydim16) { if (dx) x1 += scale(ydim16-1-y1,dx,dy); y1 = ydim16-1; }
5661 	}
5662 
5663 	setcolor16((long)col);
5664 	if (x1 == x2)
5665 	{
5666 		if (y2 < y1) i = y1, y1 = y2, y2 = i;
5667 		koutpw(0x3ce,0x8+(256<<(x1&7^7)));  //bit mask
5668 		vlin16((((mul5(y1)<<7)+x1+pageoffset)>>3)+0xa0000,y2-y1+1);
5669 		return;
5670 	}
5671 	if (y1 == y2)
5672 	{
5673 		if (x2 < x1) i = x1, x1 = x2, x2 = i;
5674 		lmask = (0x00ff>>(x1&7));
5675 		rmask = (0xff80>>(x2&7));
5676 
5677 		p = (((mul5(y1)<<7)+x1+pageoffset)>>3)+0xa0000;
5678 
5679 		dx = (x2>>3)-(x1>>3);
5680 		if (dx == 0)
5681 		{
5682 			koutpw(0x3ce,0x8+((lmask&rmask)<<8)); drawpixel(p,readpixel(p));
5683 			return;
5684 		}
5685 
5686 		dx--;
5687 
5688 		koutpw(0x3ce,0x8+(lmask<<8)); drawpixel(p,readpixel(p)); p++;
5689 		if (dx > 0) { koutp(0x3cf,0xff); clearbufbyte(p,dx,0L); p += dx; }
5690 		koutp(0x3cf,rmask); drawpixel(p,readpixel(p));
5691 		return;
5692 	}
5693 
5694 	dx = klabs(x2-x1)+1; dy = klabs(y2-y1)+1;
5695 	if (dx >= dy)
5696 	{
5697 		if (x2 < x1)
5698 		{
5699 			i = x1; x1 = x2; x2 = i;
5700 			i = y1; y1 = y2; y2 = i;
5701 		}
5702 		p = (mul5(y1)<<7)+x1+pageoffset;
5703 		d = 0;
5704 		if (y2 > y1) pinc = 640; else pinc = -640;
5705 		for(i=dx;i>0;i--)
5706 		{
5707 			drawpixel16(p);
5708 			d += dy;
5709 			if (d >= dx) { d -= dx; p += pinc; }
5710 			p++;
5711 		}
5712 		return;
5713 	}
5714 
5715 	if (y2 < y1)
5716 	{
5717 		i = x1; x1 = x2; x2 = i;
5718 		i = y1; y1 = y2; y2 = i;
5719 	}
5720 	p = (mul5(y1)<<7)+x1+pageoffset;
5721 	d = 0;
5722 	if (x2 > x1) pinc = 1; else pinc = -1;
5723 	for(i=dy;i>0;i--)
5724 	{
5725 		drawpixel16(p);
5726 		d += dx;
5727 		if (d >= dy) { d -= dy; p += pinc; }
5728 		p += 640;
5729 	}
5730 }
5731 
qsetmode640350()5732 qsetmode640350()
5733 {
5734 	if (qsetmode != 350)
5735 	{
5736 		stereomode = 0;
5737 
5738 		setvmode(0x10);
5739 
5740 		pageoffset = 0;
5741 		ydim16 = 350;
5742 		koutpw(0x3d4,0xc+((pageoffset>>11)<<8));
5743 
5744 		koutpw(0x3ce,0x0f00);  //set/reset
5745 		koutpw(0x3ce,0x0f01);  //enable set/reset
5746 		fillscreen16(0L,0L,640L*350L);
5747 	}
5748 	qsetmode = 350;
5749 }
5750 
qsetmode640480()5751 qsetmode640480()
5752 {
5753 	short i;
5754 
5755 	if (qsetmode != 480)
5756 	{
5757 		stereomode = 0;
5758 
5759 		setvmode(0x12);
5760 
5761 		i = 479-144;
5762 		koutpw(0x3d4,0x18+((i&255)<<8));             //line compare
5763 		koutp(0x3d4,0x7); koutp(0x3d5,(kinp(0x3d5)&239)|((i&256)>>4));
5764 		koutp(0x3d4,0x9); koutp(0x3d5,(kinp(0x3d5)&191)|((i&512)>>3));
5765 
5766 		pageoffset = 92160;
5767 		koutpw(0x3d4,0xc+((pageoffset>>11)<<8));
5768 
5769 		koutpw(0x3ce,0x0f00);  //set/reset
5770 		koutpw(0x3ce,0x0f01);  //enable set/reset
5771 		fillscreen16(0L,8L,640L*144L);
5772 		fillscreen16((640L*144L)>>3,0L,640L*336L);
5773 		pageoffset = 92160; ydim16 = 336;
5774 	}
5775 
5776 	qsetmode = 480;
5777 }
5778 
clear2dscreen()5779 clear2dscreen()
5780 {
5781 	if (qsetmode == 350)
5782 		fillscreen16(pageoffset>>3,0L,640L*350L);
5783 	else if (qsetmode == 480)
5784 	{
5785 		if (ydim16 <= 336) fillscreen16(pageoffset>>3,0L,640L*336L);
5786 						  else fillscreen16(pageoffset>>3,0L,640L*480L);
5787 	}
5788 }
5789 
draw2dgrid(long posxe,long posye,short ange,long zoome,short gride)5790 draw2dgrid(long posxe, long posye, short ange, long zoome, short gride)
5791 {
5792 	long i, xp1, yp1, xp2, yp2, tempy, templong;
5793 	char mask;
5794 
5795 	if (gride > 0)
5796 	{
5797 		yp1 = 200-mulscale14(posye+131072,zoome);
5798 		if (yp1 < 0) yp1 = 0;
5799 		yp2 = 200-mulscale14(posye-131072,zoome);
5800 		if (yp2 >= ydim16) yp2 = ydim16-1;
5801 
5802 		if ((yp1 < ydim16) && (yp2 >= 0) && (yp2 >= yp1))
5803 		{
5804 			setcolor16(8);
5805 			koutp(0x3ce,0x8);
5806 
5807 			templong = ((yp1*640+pageoffset)>>3)+0xa0000;
5808 			tempy = yp2-yp1+1;
5809 			mask = 0;
5810 			xp1 = 320-mulscale14(posxe+131072,zoome);
5811 
5812 			for(i=-131072;i<=131072;i+=(2048>>gride))
5813 			{
5814 				xp2 = xp1;
5815 				xp1 = 320-mulscale14(posxe-i,zoome);
5816 
5817 				if (xp1 >= 640) break;
5818 				if (xp1 >= 0)
5819 				{
5820 					if ((xp1|7) != (xp2|7))
5821 					{
5822 						koutp(0x3cf,mask);
5823 						if (((xp2>>3) >= 0) && ((xp2>>3) < 80))
5824 							vlin16first(templong+(xp2>>3),tempy);
5825 						mask = 0;
5826 					}
5827 					mask |= pow2char[xp1&7^7];
5828 				}
5829 			}
5830 			if ((i >= 131072) && (xp1 < 640))
5831 				xp2 = xp1;
5832 			if ((mask != 0) && ((xp2>>3) >= 0) && ((xp2>>3) < 80))
5833 			{
5834 				koutp(0x3cf,mask);
5835 				vlin16first(templong+(xp2>>3),tempy);
5836 			}
5837 		}
5838 
5839 		xp1 = mulscale14(posxe+131072,zoome);
5840 		xp2 = mulscale14(posxe-131072,zoome);
5841 		tempy = 0x80000000;
5842 		for(i=-131072;i<=131072;i+=(2048>>gride))
5843 		{
5844 			yp1 = (((posye-i)*zoome)>>14);
5845 			if (yp1 != tempy)
5846 			{
5847 				if ((yp1 > 200-ydim16) && (yp1 <= 200))
5848 				{
5849 					drawline16(320-xp1,200-yp1,320-xp2,200-yp1,8);
5850 					tempy = yp1;
5851 				}
5852 			}
5853 		}
5854 	}
5855 }
5856 
draw2dscreen(long posxe,long posye,short ange,long zoome,short gride)5857 draw2dscreen(long posxe, long posye, short ange, long zoome, short gride)
5858 {
5859 	walltype *wal;
5860 	long i, j, k, xp1, yp1, xp2, yp2, tempy, templong;
5861 	char col, mask;
5862 
5863 	if (qsetmode == 200) return;
5864 
5865 	if (editstatus == 0)
5866 	{
5867 		faketimerhandler();
5868 		clear2dscreen();
5869 
5870 		faketimerhandler();
5871 		draw2dgrid(posxe,posye,ange,zoome,gride);
5872 	}
5873 
5874 	faketimerhandler();
5875 	for(i=numwalls-1,wal=&wall[i];i>=0;i--,wal--)
5876 	{
5877 		if (editstatus == 0)
5878 		{
5879 			if ((show2dwall[i>>3]&pow2char[i&7]) == 0) continue;
5880 			j = wal->nextwall;
5881 			if ((j >= 0) && (i > j))
5882 				if ((show2dwall[j>>3]&pow2char[j&7]) > 0) continue;
5883 		}
5884 		else
5885 		{
5886 			j = wal->nextwall;
5887 			if ((j >= 0) && (i > j)) continue;
5888 		}
5889 
5890 		if (j < 0)
5891 		{
5892 			col = 7;
5893 			if (i == linehighlight) col += ((numframes&2)<<2);
5894 		}
5895 		else
5896 		{
5897 			col = 4;
5898 			if ((wal->cstat&1) != 0) col = 5;
5899 			if ((i == linehighlight) || ((linehighlight >= 0) && (i == wall[linehighlight].nextwall)))
5900 				col += ((numframes&2)<<2);
5901 		}
5902 
5903 		xp1 = mulscale14(wal->x-posxe,zoome);
5904 		yp1 = mulscale14(wal->y-posye,zoome);
5905 		xp2 = mulscale14(wall[wal->point2].x-posxe,zoome);
5906 		yp2 = mulscale14(wall[wal->point2].y-posye,zoome);
5907 
5908 		if ((wal->cstat&64) > 0)
5909 		{
5910 			if (klabs(xp2-xp1) >= klabs(yp2-yp1))
5911 			{
5912 				drawline16(320+xp1,200+yp1+1,320+xp2,200+yp2+1,col);
5913 				drawline16(320+xp1,200+yp1-1,320+xp2,200+yp2-1,col);
5914 			}
5915 			else
5916 			{
5917 				drawline16(320+xp1+1,200+yp1,320+xp2+1,200+yp2,col);
5918 				drawline16(320+xp1-1,200+yp1,320+xp2-1,200+yp2,col);
5919 			}
5920 			col += 8;
5921 		}
5922 		drawline16(320+xp1,200+yp1,320+xp2,200+yp2,col);
5923 
5924 		if ((zoome >= 256) && (editstatus == 1))
5925 			if (((320+xp1) >= 2) && ((320+xp1) <= 637))
5926 				if (((200+yp1) >= 2) && ((200+yp1) <= ydim16-3))
5927 				{
5928 					col = 2;
5929 					if (i == pointhighlight) col += ((numframes&2)<<2);
5930 					else if ((highlightcnt > 0) && (editstatus == 1))
5931 					{
5932 						if (show2dwall[i>>3]&pow2char[i&7])
5933 							col += ((numframes&2)<<2);
5934 					}
5935 
5936 					templong = (mul5(200+yp1)<<7)+(320+xp1)+pageoffset;
5937 					setcolor16((long)col);
5938 					drawpixel16(templong-2-1280);
5939 					drawpixel16(templong-1-1280);
5940 					drawpixel16(templong+0-1280);
5941 					drawpixel16(templong+1-1280);
5942 					drawpixel16(templong+2-1280);
5943 
5944 					drawpixel16(templong-2+1280);
5945 					drawpixel16(templong-1+1280);
5946 					drawpixel16(templong+0+1280);
5947 					drawpixel16(templong+1+1280);
5948 					drawpixel16(templong+2+1280);
5949 
5950 					drawpixel16(templong-2-640);
5951 					drawpixel16(templong-2+0);
5952 					drawpixel16(templong-2+640);
5953 
5954 					drawpixel16(templong+2-640);
5955 					drawpixel16(templong+2+0);
5956 					drawpixel16(templong+2+640);
5957 				}
5958 	}
5959 	faketimerhandler();
5960 
5961 	if ((zoome >= 256) || (editstatus == 0))
5962 		for(i=0;i<numsectors;i++)
5963 			for(j=headspritesect[i];j>=0;j=nextspritesect[j])
5964 				if ((editstatus == 1) || (show2dsprite[j>>3]&pow2char[j&7]))
5965 				{
5966 					col = 3;
5967 					if ((sprite[j].cstat&1) > 0) col = 5;
5968 					if (editstatus == 1)
5969 					{
5970 						if (j+16384 == pointhighlight)
5971 							col += ((numframes&2)<<2);
5972 						else if ((highlightcnt > 0) && (editstatus == 1))
5973 						{
5974 							if (show2dsprite[j>>3]&pow2char[j&7])
5975 								col += ((numframes&2)<<2);
5976 						}
5977 					}
5978 
5979 					xp1 = mulscale14(sprite[j].x-posxe,zoome);
5980 					yp1 = mulscale14(sprite[j].y-posye,zoome);
5981 					if (((320+xp1) >= 2) && ((320+xp1) <= 637))
5982 						if (((200+yp1) >= 2) && ((200+yp1) <= ydim16-3))
5983 						{
5984 							templong = (mul5(200+yp1)<<7)+(320+xp1)+pageoffset;
5985 							setcolor16((long)col);
5986 							drawpixel16(templong-1-1280);
5987 							drawpixel16(templong+0-1280);
5988 							drawpixel16(templong+1-1280);
5989 
5990 							drawpixel16(templong-1+1280);
5991 							drawpixel16(templong+0+1280);
5992 							drawpixel16(templong+1+1280);
5993 
5994 							drawpixel16(templong-2-640);
5995 							drawpixel16(templong-2+0);
5996 							drawpixel16(templong-2+640);
5997 
5998 							drawpixel16(templong+2-640);
5999 							drawpixel16(templong+2+0);
6000 							drawpixel16(templong+2+640);
6001 
6002 							drawpixel16(templong+1+640);
6003 							drawpixel16(templong-1+640);
6004 							drawpixel16(templong+1-640);
6005 							drawpixel16(templong-1-640);
6006 
6007 							xp2 = mulscale11(sintable[(sprite[j].ang+2560)&2047],zoome) / 768;
6008 							yp2 = mulscale11(sintable[(sprite[j].ang+2048)&2047],zoome) / 768;
6009 
6010 							if ((sprite[j].cstat&256) > 0)
6011 							{
6012 								if (((sprite[j].ang+256)&512) == 0)
6013 								{
6014 									drawline16(320+xp1,200+yp1-1,320+xp1+xp2,200+yp1+yp2-1,col);
6015 									drawline16(320+xp1,200+yp1+1,320+xp1+xp2,200+yp1+yp2+1,col);
6016 								}
6017 								else
6018 								{
6019 									drawline16(320+xp1-1,200+yp1,320+xp1+xp2-1,200+yp1+yp2,col);
6020 									drawline16(320+xp1+1,200+yp1,320+xp1+xp2+1,200+yp1+yp2,col);
6021 								}
6022 								col += 8;
6023 							}
6024 							drawline16(320+xp1,200+yp1,320+xp1+xp2,200+yp1+yp2,col);
6025 						}
6026 				}
6027 
6028 	faketimerhandler();
6029 	xp1 = mulscale11(sintable[(ange+2560)&2047],zoome) / 768; //Draw white arrow
6030 	yp1 = mulscale11(sintable[(ange+2048)&2047],zoome) / 768;
6031 	drawline16(320+xp1,200+yp1,320-xp1,200-yp1,15);
6032 	drawline16(320+xp1,200+yp1,320+yp1,200-xp1,15);
6033 	drawline16(320+xp1,200+yp1,320-yp1,200+xp1,15);
6034 }
6035 
printext16(long xpos,long ypos,short col,short backcol,char name[82],char fontsize)6036 printext16(long xpos, long ypos, short col, short backcol, char name[82], char fontsize)
6037 {
6038 	long p, z, zz, charxsiz, daxpos;
6039 	char ch, dat, mask, *fontptr;
6040 
6041 	daxpos = xpos;
6042 
6043 	koutp(0x3ce,0x5); koutp(0x3cf,(kinp(0x3cf)&(255-3))+2);
6044 	koutp(0x3ce,0x8);
6045 
6046 	if (fontsize == 1)
6047 	{
6048 		fontptr = smalltextfont;
6049 		charxsiz = 4;
6050 	}
6051 	else
6052 	{
6053 		fontptr = textfont;
6054 		charxsiz = 8;
6055 	}
6056 
6057 	z = 0;
6058 	while (name[z] != 0)
6059 	{
6060 		ch = name[z];
6061 		z++;
6062 
6063 		mask = pow2char[8-(daxpos&7)]-1;
6064 		p = ypos*80 + (daxpos>>3)+0xa0000;   //Do not make ylookup!
6065 
6066 		if ((daxpos&7) == 0)
6067 		{
6068 			for(zz=0;zz<8;zz++)
6069 			{
6070 				if (backcol >= 0)
6071 				{
6072 					koutp(0x3cf,0xff);
6073 					if (charxsiz == 4) koutp(0x3cf,0x7c);
6074 					readpixel(p), drawpixel(p,(long)backcol);
6075 				}
6076 				koutp(0x3cf,fontptr[(((long)ch)<<3)+zz]);
6077 				if (charxsiz == 4) koutp(0x3cf,0x7c&fontptr[(((long)ch)<<3)+zz]);
6078 				readpixel(p), drawpixel(p,col);
6079 				p += 80;
6080 			}
6081 		}
6082 		else
6083 		{
6084 			for(zz=0;zz<8;zz++)
6085 			{
6086 				if (backcol >= 0)
6087 				{
6088 					if (charxsiz == 8)
6089 					{
6090 						koutp(0x3cf,mask);
6091 						readpixel(p), drawpixel(p,backcol);
6092 						koutp(0x3cf,~mask);
6093 						readpixel(p+1), drawpixel(p+1,backcol);
6094 					}
6095 					else
6096 					{
6097 						koutp(0x3cf,0x7c>>(daxpos&7));
6098 						readpixel(p), drawpixel(p,backcol);
6099 						koutp(0x3cf,0x7c<<(8-(daxpos&7)));
6100 						readpixel(p+1), drawpixel(p+1,backcol);
6101 					}
6102 				}
6103 				dat = fontptr[(((long)ch)<<3)+zz];
6104 				if (charxsiz == 8)
6105 				{
6106 					koutp(0x3cf,mask&(dat>>(daxpos&7)));
6107 					readpixel(p), drawpixel(p,col);
6108 					koutp(0x3cf,(~mask)&(dat<<(8-(daxpos&7))));
6109 					readpixel(p+1), drawpixel(p+1,col);
6110 				}
6111 				else
6112 				{
6113 					koutp(0x3cf,(0x7c&dat)>>(daxpos&7));
6114 					readpixel(p), drawpixel(p,col);
6115 					koutp(0x3cf,(0x7c&dat)<<(8-(daxpos&7)));
6116 					readpixel(p+1), drawpixel(p+1,col);
6117 				}
6118 				p += 80;    //Do not make bytesperline!
6119 			}
6120 		}
6121 
6122 		daxpos += charxsiz;
6123 	}
6124 	koutp(0x3ce,0x5); koutp(0x3cf,(kinp(0x3cf)&(255-3))+0);
6125 }
6126 
printext256(long xpos,long ypos,short col,short backcol,char name[82],char fontsize)6127 printext256(long xpos, long ypos, short col, short backcol, char name[82], char fontsize)
6128 {
6129 	long stx, i, x, y, charxsiz;
6130 	char *fontptr, *letptr, *ptr;
6131 
6132 	stx = xpos;
6133 
6134 	if (fontsize) { fontptr = smalltextfont; charxsiz = 4; }
6135 				else { fontptr = textfont; charxsiz = 8; }
6136 
6137 	for(i=0;name[i];i++)
6138 	{
6139 		letptr = &fontptr[name[i]<<3];
6140 		ptr = (char *)(ylookup[ypos+7]+(stx-fontsize)+frameplace);
6141 		for(y=7;y>=0;y--)
6142 		{
6143 			for(x=charxsiz-1;x>=0;x--)
6144 			{
6145 				if (letptr[y]&pow2char[7-fontsize-x])
6146 					ptr[x] = (char)col;
6147 				else if (backcol >= 0)
6148 					ptr[x] = (char)backcol;
6149 			}
6150 			ptr -= ylookup[1];
6151 		}
6152 		stx += charxsiz;
6153 	}
6154 }
6155 
krand()6156 krand()
6157 {
6158 	randomseed = (randomseed*27584621)+1;
6159 	return(((unsigned long)randomseed)>>16);
6160 }
6161 
getzrange(long x,long y,long z,short sectnum,long * ceilz,long * ceilhit,long * florz,long * florhit,long walldist,unsigned long cliptype)6162 getzrange(long x, long y, long z, short sectnum,
6163 			 long *ceilz, long *ceilhit, long *florz, long *florhit,
6164 			 long walldist, unsigned long cliptype)
6165 {
6166 	sectortype *sec;
6167 	walltype *wal, *wal2;
6168 	spritetype *spr;
6169 	long clipsectcnt, startwall, endwall, tilenum, xoff, yoff, dax, day;
6170 	long xmin, ymin, xmax, ymax, i, j, k, l, daz, daz2, dx, dy;
6171 	long x1, y1, x2, y2, x3, y3, x4, y4, ang, cosang, sinang;
6172 	long xspan, yspan, xrepeat, yrepeat, dasprclipmask, dawalclipmask;
6173 	short cstat;
6174 	char bad, clipyou;
6175 
6176 	if (sectnum < 0)
6177 	{
6178 		*ceilz = 0x80000000; *ceilhit = -1;
6179 		*florz = 0x7fffffff; *florhit = -1;
6180 		return;
6181 	}
6182 
6183 		//Extra walldist for sprites on sector lines
6184 	i = walldist+MAXCLIPDIST+1;
6185 	xmin = x-i; ymin = y-i;
6186 	xmax = x+i; ymax = y+i;
6187 
6188 	getzsofslope(sectnum,x,y,ceilz,florz);
6189 	*ceilhit = sectnum+16384; *florhit = sectnum+16384;
6190 
6191 	dawalclipmask = (cliptype&65535);
6192 	dasprclipmask = (cliptype>>16);
6193 
6194 	clipsectorlist[0] = sectnum;
6195 	clipsectcnt = 0; clipsectnum = 1;
6196 
6197 	do  //Collect sectors inside your square first
6198 	{
6199 		sec = &sector[clipsectorlist[clipsectcnt]];
6200 		startwall = sec->wallptr; endwall = startwall + sec->wallnum;
6201 		for(j=startwall,wal=&wall[startwall];j<endwall;j++,wal++)
6202 		{
6203 			k = wal->nextsector;
6204 			if (k >= 0)
6205 			{
6206 				wal2 = &wall[wal->point2];
6207 				x1 = wal->x; x2 = wal2->x;
6208 				if ((x1 < xmin) && (x2 < xmin)) continue;
6209 				if ((x1 > xmax) && (x2 > xmax)) continue;
6210 				y1 = wal->y; y2 = wal2->y;
6211 				if ((y1 < ymin) && (y2 < ymin)) continue;
6212 				if ((y1 > ymax) && (y2 > ymax)) continue;
6213 
6214 				dx = x2-x1; dy = y2-y1;
6215 				if (dx*(y-y1) < (x-x1)*dy) continue; //back
6216 				if (dx > 0) dax = dx*(ymin-y1); else dax = dx*(ymax-y1);
6217 				if (dy > 0) day = dy*(xmax-x1); else day = dy*(xmin-x1);
6218 				if (dax >= day) continue;
6219 
6220 				if (wal->cstat&dawalclipmask) continue;
6221 				sec = &sector[k];
6222 				if (editstatus == 0)
6223 				{
6224 					if (((sec->ceilingstat&1) == 0) && (z <= sec->ceilingz+(3<<8))) continue;
6225 					if (((sec->floorstat&1) == 0) && (z >= sec->floorz-(3<<8))) continue;
6226 				}
6227 
6228 				for(i=clipsectnum-1;i>=0;i--) if (clipsectorlist[i] == k) break;
6229 				if (i < 0) clipsectorlist[clipsectnum++] = k;
6230 
6231 				if ((x1 < xmin+MAXCLIPDIST) && (x2 < xmin+MAXCLIPDIST)) continue;
6232 				if ((x1 > xmax-MAXCLIPDIST) && (x2 > xmax-MAXCLIPDIST)) continue;
6233 				if ((y1 < ymin+MAXCLIPDIST) && (y2 < ymin+MAXCLIPDIST)) continue;
6234 				if ((y1 > ymax-MAXCLIPDIST) && (y2 > ymax-MAXCLIPDIST)) continue;
6235 				if (dx > 0) dax += dx*MAXCLIPDIST; else dax -= dx*MAXCLIPDIST;
6236 				if (dy > 0) day -= dy*MAXCLIPDIST; else day += dy*MAXCLIPDIST;
6237 				if (dax >= day) continue;
6238 
6239 					//It actually got here, through all the continue's!!!
6240 				getzsofslope((short)k,x,y,&daz,&daz2);
6241 				if (daz > *ceilz) { *ceilz = daz; *ceilhit = k+16384; }
6242 				if (daz2 < *florz) { *florz = daz2; *florhit = k+16384; }
6243 			}
6244 		}
6245 		clipsectcnt++;
6246 	} while (clipsectcnt < clipsectnum);
6247 
6248 	for(i=0;i<clipsectnum;i++)
6249 	{
6250 		for(j=headspritesect[clipsectorlist[i]];j>=0;j=nextspritesect[j])
6251 		{
6252 			spr = &sprite[j];
6253 			cstat = spr->cstat;
6254 			if (cstat&dasprclipmask)
6255 			{
6256 				x1 = spr->x; y1 = spr->y;
6257 
6258 				clipyou = 0;
6259 				switch(cstat&48)
6260 				{
6261 					case 0:
6262 						k = walldist+(spr->clipdist<<2)+1;
6263 						if ((klabs(x1-x) <= k) && (klabs(y1-y) <= k))
6264 						{
6265 							daz = spr->z;
6266 							k = ((tilesizy[spr->picnum]*spr->yrepeat)<<1);
6267 							if (cstat&128) daz += k;
6268 							if (picanm[spr->picnum]&0x00ff0000) daz -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
6269 							daz2 = daz - (k<<1);
6270 							clipyou = 1;
6271 						}
6272 						break;
6273 					case 16:
6274 						tilenum = spr->picnum;
6275 						xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
6276 						if ((cstat&4) > 0) xoff = -xoff;
6277 						k = spr->ang; l = spr->xrepeat;
6278 						dax = sintable[k&2047]*l; day = sintable[(k+1536)&2047]*l;
6279 						l = tilesizx[tilenum]; k = (l>>1)+xoff;
6280 						x1 -= mulscale16(dax,k); x2 = x1+mulscale16(dax,l);
6281 						y1 -= mulscale16(day,k); y2 = y1+mulscale16(day,l);
6282 						if (clipinsideboxline(x,y,x1,y1,x2,y2,walldist+1) != 0)
6283 						{
6284 							daz = spr->z; k = ((tilesizy[spr->picnum]*spr->yrepeat)<<1);
6285 							if (cstat&128) daz += k;
6286 							if (picanm[spr->picnum]&0x00ff0000) daz -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
6287 							daz2 = daz-(k<<1);
6288 							clipyou = 1;
6289 						}
6290 						break;
6291 					case 32:
6292 						daz = spr->z; daz2 = daz;
6293 
6294 						if ((cstat&64) != 0)
6295 							if ((z > daz) == ((cstat&8)==0)) continue;
6296 
6297 						tilenum = spr->picnum;
6298 						xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
6299 						yoff = (long)((signed char)((picanm[tilenum]>>16)&255))+((long)spr->yoffset);
6300 						if ((cstat&4) > 0) xoff = -xoff;
6301 						if ((cstat&8) > 0) yoff = -yoff;
6302 
6303 						ang = spr->ang;
6304 						cosang = sintable[(ang+512)&2047]; sinang = sintable[ang];
6305 						xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat;
6306 						yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat;
6307 
6308 						dax = ((xspan>>1)+xoff)*xrepeat; day = ((yspan>>1)+yoff)*yrepeat;
6309 						x1 += dmulscale16(sinang,dax,cosang,day)-x;
6310 						y1 += dmulscale16(sinang,day,-cosang,dax)-y;
6311 						l = xspan*xrepeat;
6312 						x2 = x1 - mulscale16(sinang,l);
6313 						y2 = y1 + mulscale16(cosang,l);
6314 						l = yspan*yrepeat;
6315 						k = -mulscale16(cosang,l); x3 = x2+k; x4 = x1+k;
6316 						k = -mulscale16(sinang,l); y3 = y2+k; y4 = y1+k;
6317 
6318 						dax = mulscale14(sintable[(spr->ang-256+512)&2047],walldist+4);
6319 						day = mulscale14(sintable[(spr->ang-256)&2047],walldist+4);
6320 						x1 += dax; x2 -= day; x3 -= dax; x4 += day;
6321 						y1 += day; y2 += dax; y3 -= day; y4 -= dax;
6322 
6323 						if ((y1^y2) < 0)
6324 						{
6325 							if ((x1^x2) < 0) clipyou ^= (x1*y2<x2*y1)^(y1<y2);
6326 							else if (x1 >= 0) clipyou ^= 1;
6327 						}
6328 						if ((y2^y3) < 0)
6329 						{
6330 							if ((x2^x3) < 0) clipyou ^= (x2*y3<x3*y2)^(y2<y3);
6331 							else if (x2 >= 0) clipyou ^= 1;
6332 						}
6333 						if ((y3^y4) < 0)
6334 						{
6335 							if ((x3^x4) < 0) clipyou ^= (x3*y4<x4*y3)^(y3<y4);
6336 							else if (x3 >= 0) clipyou ^= 1;
6337 						}
6338 						if ((y4^y1) < 0)
6339 						{
6340 							if ((x4^x1) < 0) clipyou ^= (x4*y1<x1*y4)^(y4<y1);
6341 							else if (x4 >= 0) clipyou ^= 1;
6342 						}
6343 						break;
6344 				}
6345 
6346 				if (clipyou != 0)
6347 				{
6348 					if ((z > daz) && (daz > *ceilz)) { *ceilz = daz; *ceilhit = j+49152; }
6349 					if ((z < daz2) && (daz2 < *florz)) { *florz = daz2; *florhit = j+49152; }
6350 				}
6351 			}
6352 		}
6353 	}
6354 }
6355 
setview(long x1,long y1,long x2,long y2)6356 setview(long x1, long y1, long x2, long y2)
6357 {
6358 	long i, j;
6359 
6360 	windowx1 = x1; wx1 = (x1<<12);
6361 	windowy1 = y1; wy1 = (y1<<12);
6362 	windowx2 = x2; wx2 = ((x2+1)<<12);
6363 	windowy2 = y2; wy2 = ((y2+1)<<12);
6364 
6365 	xdimen = (x2-x1)+1; halfxdimen = (xdimen>>1);
6366 	xdimenrecip = divscale32(1L,xdimen);
6367 	ydimen = (y2-y1)+1;
6368 
6369 	setaspect(65536L,(long)divscale16(ydim*320L,xdim*200L));
6370 
6371 	for(i=0;i<windowx1;i++) { startumost[i] = 1, startdmost[i] = 0; }
6372 	for(i=windowx1;i<=windowx2;i++)
6373 		{ startumost[i] = windowy1, startdmost[i] = windowy2+1; }
6374 	for(i=windowx2+1;i<xdim;i++) { startumost[i] = 1, startdmost[i] = 0; }
6375 
6376 	viewoffset = windowy1*bytesperline + windowx1;
6377 
6378 	if ((stereomode) || (vidoption == 6))
6379 	{
6380 		ostereopixelwidth = stereopixelwidth;
6381 		xdimen = (windowx2-windowx1+1)+(stereopixelwidth<<1); halfxdimen = (xdimen>>1);
6382 		xdimenrecip = divscale32(1L,xdimen);
6383 		setaspect((long)divscale16(xdimen,windowx2-windowx1+1),yxaspect);
6384 	}
6385 }
6386 
setaspect(long daxrange,long daaspect)6387 setaspect(long daxrange, long daaspect)
6388 {
6389 	viewingrange = daxrange;
6390 	viewingrangerecip = divscale32(1L,daxrange);
6391 
6392 	yxaspect = daaspect;
6393 	xyaspect = divscale32(1,yxaspect);
6394 	xdimenscale = scale(xdimen,yxaspect,320);
6395 	xdimscale = scale(320,xyaspect,xdimen);
6396 }
6397 
dosetaspect()6398 dosetaspect()
6399 {
6400 	long i, j, k, x, y, xinc;
6401 
6402 	if (xyaspect != oxyaspect)
6403 	{
6404 		oxyaspect = xyaspect;
6405 		j = xyaspect*320;
6406 		horizlookup2[horizycent-1] = divscale26(131072,j);
6407 		for(i=ydim*4-1;i>=0;i--)
6408 			if (i != (horizycent-1))
6409 			{
6410 				horizlookup[i] = divscale28(1,i-(horizycent-1));
6411 				horizlookup2[i] = divscale14(klabs(horizlookup[i]),j);
6412 			}
6413 	}
6414 	if ((xdimen != oxdimen) || (viewingrange != oviewingrange))
6415 	{
6416 		oxdimen = xdimen;
6417 		oviewingrange = viewingrange;
6418 		xinc = mulscale32(viewingrange*320,xdimenrecip);
6419 		x = (640<<16)-mulscale1(xinc,xdimen);
6420 		for(i=0;i<xdimen;i++)
6421 		{
6422 			j = (x&65535); k = (x>>16); x += xinc;
6423 			if (j != 0) j = mulscale16((long)radarang[k+1]-(long)radarang[k],j);
6424 			radarang2[i] = (short)(((long)radarang[k]+j)>>6);
6425 		}
6426 #ifdef SUPERBUILD
6427 		for(i=1;i<16384;i++) distrecip[i] = divscale20(xdimen,i);
6428 		nytooclose = xdimen*2100;
6429 		nytoofar = 16384*16384-1048576;
6430 #endif
6431 	}
6432 }
6433 
flushperms()6434 flushperms()
6435 {
6436 	permhead = permtail = 0;
6437 }
6438 
rotatesprite(long sx,long sy,long z,short a,short picnum,signed char dashade,char dapalnum,char dastat,long cx1,long cy1,long cx2,long cy2)6439 rotatesprite (long sx, long sy, long z, short a, short picnum, signed char dashade, char dapalnum, char dastat, long cx1, long cy1, long cx2, long cy2)
6440 {
6441 	long i;
6442 	permfifotype *per, *per2;
6443 
6444 	if ((cx1 > cx2) || (cy1 > cy2)) return;
6445 	if (z <= 16) return;
6446 	if (picanm[picnum]&192) picnum += animateoffs(picnum,(short)0xc000);
6447 	if ((tilesizx[picnum] <= 0) || (tilesizy[picnum] <= 0)) return;
6448 
6449 	if (((dastat&128) == 0) || (numpages < 2) || (beforedrawrooms != 0))
6450 		dorotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,cx1,cy1,cx2,cy2);
6451 
6452 	if ((dastat&64) && (cx1 <= 0) && (cy1 <= 0) && (cx2 >= xdim-1) && (cy2 >= ydim-1) &&
6453 		 (sx == (160<<16)) && (sy == (100<<16)) && (z == 65536L) && (a == 0) && ((dastat&1) == 0))
6454 		permhead = permtail = 0;
6455 
6456 	if ((dastat&128) == 0) return;
6457 	if (numpages >= 2)
6458 	{
6459 		per = &permfifo[permhead];
6460 		per->sx = sx; per->sy = sy; per->z = z; per->a = a;
6461 		per->picnum = picnum;
6462 		per->dashade = dashade; per->dapalnum = dapalnum;
6463 		per->dastat = dastat;
6464 		per->pagesleft = numpages+((beforedrawrooms&1)<<7);
6465 		per->cx1 = cx1; per->cy1 = cy1; per->cx2 = cx2; per->cy2 = cy2;
6466 
6467 			//Would be better to optimize out true bounding boxes
6468 		if (dastat&64)  //If non-masking write, checking for overlapping cases
6469 		{
6470 			for(i=permtail;i!=permhead;i=((i+1)&(MAXPERMS-1)))
6471 			{
6472 				per2 = &permfifo[i];
6473 				if ((per2->pagesleft&127) == 0) continue;
6474 				if (per2->sx != per->sx) continue;
6475 				if (per2->sy != per->sy) continue;
6476 				if (per2->z != per->z) continue;
6477 				if (per2->a != per->a) continue;
6478 				if (tilesizx[per2->picnum] > tilesizx[per->picnum]) continue;
6479 				if (tilesizy[per2->picnum] > tilesizy[per->picnum]) continue;
6480 				if (per2->cx1 < per->cx1) continue;
6481 				if (per2->cy1 < per->cy1) continue;
6482 				if (per2->cx2 > per->cx2) continue;
6483 				if (per2->cy2 > per->cy2) continue;
6484 				per2->pagesleft = 0;
6485 			}
6486 			if ((per->z == 65536) && (per->a == 0))
6487 				for(i=permtail;i!=permhead;i=((i+1)&(MAXPERMS-1)))
6488 				{
6489 					per2 = &permfifo[i];
6490 					if ((per2->pagesleft&127) == 0) continue;
6491 					if (per2->z != 65536) continue;
6492 					if (per2->a != 0) continue;
6493 					if (per2->cx1 < per->cx1) continue;
6494 					if (per2->cy1 < per->cy1) continue;
6495 					if (per2->cx2 > per->cx2) continue;
6496 					if (per2->cy2 > per->cy2) continue;
6497 					if ((per2->sx>>16) < (per->sx>>16)) continue;
6498 					if ((per2->sy>>16) < (per->sy>>16)) continue;
6499 					if ((per2->sx>>16)+tilesizx[per2->picnum] > (per->sx>>16)+tilesizx[per->picnum]) continue;
6500 					if ((per2->sy>>16)+tilesizy[per2->picnum] > (per->sy>>16)+tilesizy[per->picnum]) continue;
6501 					per2->pagesleft = 0;
6502 				}
6503 		}
6504 
6505 		permhead = ((permhead+1)&(MAXPERMS-1));
6506 	}
6507 }
6508 
dorotatesprite(long sx,long sy,long z,short a,short picnum,signed char dashade,char dapalnum,char dastat,long cx1,long cy1,long cx2,long cy2)6509 dorotatesprite (long sx, long sy, long z, short a, short picnum, signed char dashade, char dapalnum, char dastat, long cx1, long cy1, long cx2, long cy2)
6510 {
6511 	long cosang, sinang, v, nextv, dax1, dax2, oy, bx, by, ny1, ny2;
6512 	long i, x, y, x1, y1, x2, y2, gx1, gy1, p, bufplc, palookupoffs;
6513 	long xsiz, ysiz, xoff, yoff, npoints, yplc, yinc, lx, rx, xx, xend;
6514 	long xv, yv, xv2, yv2, obuffermode, qlinemode, y1ve[4], y2ve[4], u4, d4;
6515 	char bad;
6516 
6517 	xsiz = tilesizx[picnum]; ysiz = tilesizy[picnum];
6518 	if (dastat&16) { xoff = 0; yoff = 0; }
6519 	else
6520 	{
6521 		xoff = (long)((signed char)((picanm[picnum]>>8)&255))+(xsiz>>1);
6522 		yoff = (long)((signed char)((picanm[picnum]>>16)&255))+(ysiz>>1);
6523 	}
6524 
6525 	if (dastat&4) yoff = ysiz-yoff;
6526 
6527 	cosang = sintable[(a+512)&2047]; sinang = sintable[a&2047];
6528 
6529 	if ((dastat&2) != 0)  //Auto window size scaling
6530 	{
6531 		if ((dastat&8) == 0)
6532 		{
6533 			x = xdimenscale;   //= scale(xdimen,yxaspect,320);
6534 			if (stereomode) x = scale(windowx2-windowx1+1,yxaspect,320);
6535 			sx = ((cx1+cx2+2)<<15)+scale(sx-(320<<15),xdimen,320);
6536 			sy = ((cy1+cy2+2)<<15)+mulscale16(sy-(200<<15),x);
6537 		}
6538 		else
6539 		{
6540 			  //If not clipping to startmosts, & auto-scaling on, as a
6541 			  //hard-coded bonus, scale to full screen instead
6542 			x = scale(xdim,yxaspect,320);
6543 			sx = (xdim<<15)+32768+scale(sx-(320<<15),xdim,320);
6544 			sy = (ydim<<15)+32768+mulscale16(sy-(200<<15),x);
6545 		}
6546 		z = mulscale16(z,x);
6547 	}
6548 
6549 	xv = mulscale14(cosang,z);
6550 	yv = mulscale14(sinang,z);
6551 	if (((dastat&2) != 0) || ((dastat&8) == 0)) //Don't aspect unscaled perms
6552 	{
6553 		xv2 = mulscale16(xv,xyaspect);
6554 		yv2 = mulscale16(yv,xyaspect);
6555 	}
6556 	else
6557 	{
6558 		xv2 = xv;
6559 		yv2 = yv;
6560 	}
6561 
6562 	ry1[0] = sy - (yv*xoff + xv*yoff);
6563 	ry1[1] = ry1[0] + yv*xsiz;
6564 	ry1[3] = ry1[0] + xv*ysiz;
6565 	ry1[2] = ry1[1]+ry1[3]-ry1[0];
6566 	i = (cy1<<16); if ((ry1[0]<i) && (ry1[1]<i) && (ry1[2]<i) && (ry1[3]<i)) return;
6567 	i = (cy2<<16); if ((ry1[0]>i) && (ry1[1]>i) && (ry1[2]>i) && (ry1[3]>i)) return;
6568 
6569 	rx1[0] = sx - (xv2*xoff - yv2*yoff);
6570 	rx1[1] = rx1[0] + xv2*xsiz;
6571 	rx1[3] = rx1[0] - yv2*ysiz;
6572 	rx1[2] = rx1[1]+rx1[3]-rx1[0];
6573 	i = (cx1<<16); if ((rx1[0]<i) && (rx1[1]<i) && (rx1[2]<i) && (rx1[3]<i)) return;
6574 	i = (cx2<<16); if ((rx1[0]>i) && (rx1[1]>i) && (rx1[2]>i) && (rx1[3]>i)) return;
6575 
6576 	gx1 = rx1[0]; gy1 = ry1[0];   //back up these before clipping
6577 
6578 	if ((npoints = clippoly4(cx1<<16,cy1<<16,(cx2+1)<<16,(cy2+1)<<16)) < 3) return;
6579 
6580 	lx = rx1[0]; rx = rx1[0];
6581 
6582 	nextv = 0;
6583 	for(v=npoints-1;v>=0;v--)
6584 	{
6585 		x1 = rx1[v]; x2 = rx1[nextv];
6586 		dax1 = (x1>>16); if (x1 < lx) lx = x1;
6587 		dax2 = (x2>>16); if (x1 > rx) rx = x1;
6588 		if (dax1 != dax2)
6589 		{
6590 			y1 = ry1[v]; y2 = ry1[nextv];
6591 			yinc = divscale16(y2-y1,x2-x1);
6592 			if (dax2 > dax1)
6593 			{
6594 				yplc = y1 + mulscale16((dax1<<16)+65535-x1,yinc);
6595 				qinterpolatedown16short((long)(&uplc[dax1]),dax2-dax1,yplc,yinc);
6596 			}
6597 			else
6598 			{
6599 				yplc = y2 + mulscale16((dax2<<16)+65535-x2,yinc);
6600 				qinterpolatedown16short((long)(&dplc[dax2]),dax1-dax2,yplc,yinc);
6601 			}
6602 		}
6603 		nextv = v;
6604 	}
6605 
6606 	if (waloff[picnum] == 0) loadtile(picnum);
6607 	setgotpic(picnum);
6608 	bufplc = waloff[picnum];
6609 
6610 	palookupoffs = FP_OFF(palookup[dapalnum]) + (getpalookup(0L,(long)dashade)<<8);
6611 
6612 	i = divscale32(1L,z);
6613 	xv = mulscale14(sinang,i);
6614 	yv = mulscale14(cosang,i);
6615 	if (((dastat&2) != 0) || ((dastat&8) == 0)) //Don't aspect unscaled perms
6616 	{
6617 		yv2 = mulscale16(-xv,yxaspect);
6618 		xv2 = mulscale16(yv,yxaspect);
6619 	}
6620 	else
6621 	{
6622 		yv2 = -xv;
6623 		xv2 = yv;
6624 	}
6625 
6626 	x1 = (lx>>16); x2 = (rx>>16);
6627 
6628 	oy = 0;
6629 	x = (x1<<16)-1-gx1; y = (oy<<16)+65535-gy1;
6630 	bx = dmulscale16(x,xv2,y,xv);
6631 	by = dmulscale16(x,yv2,y,yv);
6632 	if (dastat&4) { yv = -yv; yv2 = -yv2; by = (ysiz<<16)-1-by; }
6633 
6634 	if ((vidoption == 1) && (origbuffermode == 0))
6635 	{
6636 		if (dastat&128)
6637 		{
6638 			obuffermode = buffermode;
6639 			buffermode = 0;
6640 			setactivepage(activepage);
6641 		}
6642 	}
6643 	else if (dastat&8)
6644 		 permanentupdate = 1;
6645 
6646 	if ((dastat&1) == 0)
6647 	{
6648 		if (((a&1023) == 0) && (ysiz <= 256))  //vlineasm4 has 256 high limit!
6649 		{
6650 			if (dastat&64) setupvlineasm(24L); else setupmvlineasm(24L);
6651 			by <<= 8; yv <<= 8; yv2 <<= 8;
6652 
6653 			palookupoffse[0] = palookupoffse[1] = palookupoffse[2] = palookupoffse[3] = palookupoffs;
6654 			vince[0] = vince[1] = vince[2] = vince[3] = yv;
6655 
6656 			for(x=x1;x<x2;x+=4)
6657 			{
6658 				bad = 15; xend = min(x2-x,4);
6659 				for(xx=0;xx<xend;xx++)
6660 				{
6661 					bx += xv2;
6662 
6663 					y1 = uplc[x+xx]; y2 = dplc[x+xx];
6664 					if ((dastat&8) == 0)
6665 					{
6666 						if (startumost[x+xx] > y1) y1 = startumost[x+xx];
6667 						if (startdmost[x+xx] < y2) y2 = startdmost[x+xx];
6668 					}
6669 					if (y2 <= y1) continue;
6670 
6671 					by += yv*(y1-oy); oy = y1;
6672 
6673 					bufplce[xx] = (bx>>16)*ysiz+bufplc;
6674 					vplce[xx] = by;
6675 					y1ve[xx] = y1;
6676 					y2ve[xx] = y2-1;
6677 					bad &= ~pow2char[xx];
6678 				}
6679 
6680 				p = x+frameplace;
6681 
6682 				u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
6683 				d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
6684 
6685 				if (dastat&64)
6686 				{
6687 					if ((bad != 0) || (u4 >= d4))
6688 					{
6689 						if (!(bad&1)) prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
6690 						if (!(bad&2)) prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
6691 						if (!(bad&4)) prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
6692 						if (!(bad&8)) prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
6693 						continue;
6694 					}
6695 
6696 					if (u4 > y1ve[0]) vplce[0] = prevlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
6697 					if (u4 > y1ve[1]) vplce[1] = prevlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
6698 					if (u4 > y1ve[2]) vplce[2] = prevlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
6699 					if (u4 > y1ve[3]) vplce[3] = prevlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
6700 
6701 					if (d4 >= u4) vlineasm4(d4-u4+1,ylookup[u4]+p);
6702 
6703 					i = p+ylookup[d4+1];
6704 					if (y2ve[0] > d4) prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
6705 					if (y2ve[1] > d4) prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
6706 					if (y2ve[2] > d4) prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
6707 					if (y2ve[3] > d4) prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
6708 				}
6709 				else
6710 				{
6711 					if ((bad != 0) || (u4 >= d4))
6712 					{
6713 						if (!(bad&1)) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
6714 						if (!(bad&2)) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
6715 						if (!(bad&4)) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
6716 						if (!(bad&8)) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
6717 						continue;
6718 					}
6719 
6720 					if (u4 > y1ve[0]) vplce[0] = mvlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
6721 					if (u4 > y1ve[1]) vplce[1] = mvlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
6722 					if (u4 > y1ve[2]) vplce[2] = mvlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
6723 					if (u4 > y1ve[3]) vplce[3] = mvlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
6724 
6725 					if (d4 >= u4) mvlineasm4(d4-u4+1,ylookup[u4]+p);
6726 
6727 					i = p+ylookup[d4+1];
6728 					if (y2ve[0] > d4) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
6729 					if (y2ve[1] > d4) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
6730 					if (y2ve[2] > d4) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
6731 					if (y2ve[3] > d4) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
6732 				}
6733 
6734 				faketimerhandler();
6735 			}
6736 		}
6737 		else
6738 		{
6739 			if (dastat&64)
6740 			{
6741 				if ((xv2&0x0000ffff) == 0)
6742 				{
6743 					qlinemode = 1;
6744 					setupqrhlineasm4(0L,yv2<<16,(xv2>>16)*ysiz+(yv2>>16),palookupoffs,0L,0L);
6745 				}
6746 				else
6747 				{
6748 					qlinemode = 0;
6749 					setuprhlineasm4(xv2<<16,yv2<<16,(xv2>>16)*ysiz+(yv2>>16),palookupoffs,ysiz,0L);
6750 				}
6751 			}
6752 			else
6753 				setuprmhlineasm4(xv2<<16,yv2<<16,(xv2>>16)*ysiz+(yv2>>16),palookupoffs,ysiz,0L);
6754 
6755 			y1 = uplc[x1];
6756 			if (((dastat&8) == 0) && (startumost[x1] > y1)) y1 = startumost[x1];
6757 			y2 = y1;
6758 			for(x=x1;x<x2;x++)
6759 			{
6760 				ny1 = uplc[x]-1; ny2 = dplc[x];
6761 				if ((dastat&8) == 0)
6762 				{
6763 					if (startumost[x]-1 > ny1) ny1 = startumost[x]-1;
6764 					if (startdmost[x] < ny2) ny2 = startdmost[x];
6765 				}
6766 
6767 				if (ny1 < ny2-1)
6768 				{
6769 					if (ny1 >= y2)
6770 					{
6771 						while (y1 < y2-1)
6772 						{
6773 							y1++; if ((y1&31) == 0) faketimerhandler();
6774 
6775 								//x,y1
6776 							bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1;
6777 							if (dastat&64) {  if (qlinemode) qrhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,0L    ,by<<16,ylookup[y1]+x+frameplace);
6778 																  else rhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
6779 															  } else rmhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
6780 						}
6781 						y1 = ny1;
6782 					}
6783 					else
6784 					{
6785 						while (y1 < ny1)
6786 						{
6787 							y1++; if ((y1&31) == 0) faketimerhandler();
6788 
6789 								//x,y1
6790 							bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1;
6791 							if (dastat&64) {  if (qlinemode) qrhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,0L    ,by<<16,ylookup[y1]+x+frameplace);
6792 																  else rhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
6793 															  } else rmhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
6794 						}
6795 						while (y1 > ny1) lastx[y1--] = x;
6796 					}
6797 					while (y2 > ny2)
6798 					{
6799 						y2--; if ((y2&31) == 0) faketimerhandler();
6800 
6801 							//x,y2
6802 						bx += xv*(y2-oy); by += yv*(y2-oy); oy = y2;
6803 						if (dastat&64) {  if (qlinemode) qrhlineasm4(x-lastx[y2],(bx>>16)*ysiz+(by>>16)+bufplc,0L,0L    ,by<<16,ylookup[y2]+x+frameplace);
6804 															  else rhlineasm4(x-lastx[y2],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y2]+x+frameplace);
6805 														  } else rmhlineasm4(x-lastx[y2],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y2]+x+frameplace);
6806 					}
6807 					while (y2 < ny2) lastx[y2++] = x;
6808 				}
6809 				else
6810 				{
6811 					while (y1 < y2-1)
6812 					{
6813 						y1++; if ((y1&31) == 0) faketimerhandler();
6814 
6815 							//x,y1
6816 						bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1;
6817 						if (dastat&64) {  if (qlinemode) qrhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,0L    ,by<<16,ylookup[y1]+x+frameplace);
6818 															  else rhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
6819 														  } else rmhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
6820 					}
6821 					if (x == x2-1) { bx += xv2; by += yv2; break; }
6822 					y1 = uplc[x+1];
6823 					if (((dastat&8) == 0) && (startumost[x+1] > y1)) y1 = startumost[x+1];
6824 					y2 = y1;
6825 				}
6826 				bx += xv2; by += yv2;
6827 			}
6828 			while (y1 < y2-1)
6829 			{
6830 				y1++; if ((y1&31) == 0) faketimerhandler();
6831 
6832 					//x2,y1
6833 				bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1;
6834 				if (dastat&64) {  if (qlinemode) qrhlineasm4(x2-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,0L    ,by<<16,ylookup[y1]+x2+frameplace);
6835 													  else rhlineasm4(x2-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x2+frameplace);
6836 												  } else rmhlineasm4(x2-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x2+frameplace);
6837 			}
6838 		}
6839 	}
6840 	else
6841 	{
6842 		if ((dastat&1) == 0)
6843 		{
6844 			if (dastat&64)
6845 				setupspritevline(palookupoffs,(xv>>16)*ysiz,xv<<16,ysiz,yv,0L);
6846 			else
6847 				msetupspritevline(palookupoffs,(xv>>16)*ysiz,xv<<16,ysiz,yv,0L);
6848 		}
6849 		else
6850 		{
6851 			tsetupspritevline(palookupoffs,(xv>>16)*ysiz,xv<<16,ysiz,yv,0L);
6852 			if (dastat&32) settransreverse(); else settransnormal();
6853 		}
6854 		for(x=x1;x<x2;x++)
6855 		{
6856 			bx += xv2; by += yv2;
6857 
6858 			y1 = uplc[x]; y2 = dplc[x];
6859 			if ((dastat&8) == 0)
6860 			{
6861 				if (startumost[x] > y1) y1 = startumost[x];
6862 				if (startdmost[x] < y2) y2 = startdmost[x];
6863 			}
6864 			if (y2 <= y1) continue;
6865 
6866 			switch(y1-oy)
6867 			{
6868 				case -1: bx -= xv; by -= yv; oy = y1; break;
6869 				case 0: break;
6870 				case 1: bx += xv; by += yv; oy = y1; break;
6871 				default: bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1; break;
6872 			}
6873 
6874 			p = ylookup[y1]+x+frameplace;
6875 
6876 			if ((dastat&1) == 0)
6877 			{
6878 				if (dastat&64)
6879 					spritevline(0L,by<<16,y2-y1+1,bx<<16,(bx>>16)*ysiz+(by>>16)+bufplc,p);
6880 				else
6881 					mspritevline(0L,by<<16,y2-y1+1,bx<<16,(bx>>16)*ysiz+(by>>16)+bufplc,p);
6882 			}
6883 			else
6884 			{
6885 				tspritevline(0L,by<<16,y2-y1+1,bx<<16,(bx>>16)*ysiz+(by>>16)+bufplc,p);
6886 				transarea += (y2-y1);
6887 			}
6888 			faketimerhandler();
6889 		}
6890 	}
6891 
6892 	if ((vidoption == 1) && (dastat&128) && (origbuffermode == 0))
6893 	{
6894 		buffermode = obuffermode;
6895 		setactivepage(activepage);
6896 	}
6897 }
6898 
6899 	//Assume npoints=4 with polygon on &rx1,&ry1
clippoly4(long cx1,long cy1,long cx2,long cy2)6900 clippoly4(long cx1, long cy1, long cx2, long cy2)
6901 {
6902 	long n, nn, z, zz, x, x1, x2, y, y1, y2, t;
6903 
6904 	nn = 0; z = 0;
6905 	do
6906 	{
6907 		zz = ((z+1)&3);
6908 		x1 = rx1[z]; x2 = rx1[zz]-x1;
6909 
6910 		if ((cx1 <= x1) && (x1 <= cx2))
6911 			rx2[nn] = x1, ry2[nn] = ry1[z], nn++;
6912 
6913 		if (x2 <= 0) x = cx2; else x = cx1;
6914 		t = x-x1;
6915 		if (((t-x2)^t) < 0)
6916 			rx2[nn] = x, ry2[nn] = ry1[z]+scale(t,ry1[zz]-ry1[z],x2), nn++;
6917 
6918 		if (x2 <= 0) x = cx1; else x = cx2;
6919 		t = x-x1;
6920 		if (((t-x2)^t) < 0)
6921 			rx2[nn] = x, ry2[nn] = ry1[z]+scale(t,ry1[zz]-ry1[z],x2), nn++;
6922 
6923 		z = zz;
6924 	} while (z != 0);
6925 	if (nn < 3) return(0);
6926 
6927 	n = 0; z = 0;
6928 	do
6929 	{
6930 		zz = z+1; if (zz == nn) zz = 0;
6931 		y1 = ry2[z]; y2 = ry2[zz]-y1;
6932 
6933 		if ((cy1 <= y1) && (y1 <= cy2))
6934 			ry1[n] = y1, rx1[n] = rx2[z], n++;
6935 
6936 		if (y2 <= 0) y = cy2; else y = cy1;
6937 		t = y-y1;
6938 		if (((t-y2)^t) < 0)
6939 			ry1[n] = y, rx1[n] = rx2[z]+scale(t,rx2[zz]-rx2[z],y2), n++;
6940 
6941 		if (y2 <= 0) y = cy1; else y = cy2;
6942 		t = y-y1;
6943 		if (((t-y2)^t) < 0)
6944 			ry1[n] = y, rx1[n] = rx2[z]+scale(t,rx2[zz]-rx2[z],y2), n++;
6945 
6946 		z = zz;
6947 	} while (z != 0);
6948 	return(n);
6949 }
6950 
makepalookup(long palnum,char * remapbuf,signed char r,signed char g,signed char b,char dastat)6951 makepalookup(long palnum, char *remapbuf, signed char r, signed char g, signed char b, char dastat)
6952 {
6953 	long i, j, dist, palscale;
6954 	char *ptr, *ptr2;
6955 
6956 	if (paletteloaded == 0) return;
6957 
6958 	if (palookup[palnum] == NULL)
6959 	{
6960 			//Allocate palookup buffer
6961 		if ((palookup[palnum] = (char *)kkmalloc(numpalookups<<8)) == NULL)
6962 			allocache(&palookup[palnum],numpalookups<<8,&permanentlock);
6963 	}
6964 
6965 	if (dastat == 0) return;
6966 	if ((r|g|b|63) != 63) return;
6967 
6968 	if ((r|g|b) == 0)
6969 	{
6970 		for(i=0;i<256;i++)
6971 		{
6972 			ptr = (char *)(FP_OFF(palookup[0])+remapbuf[i]);
6973 			ptr2 = (char *)(FP_OFF(palookup[palnum])+i);
6974 			for(j=0;j<numpalookups;j++)
6975 				{ *ptr2 = *ptr; ptr += 256; ptr2 += 256; }
6976 		}
6977 	}
6978 	else
6979 	{
6980 		ptr2 = (char *)FP_OFF(palookup[palnum]);
6981 		for(i=0;i<numpalookups;i++)
6982 		{
6983 			palscale = divscale16(i,numpalookups);
6984 			for(j=0;j<256;j++)
6985 			{
6986 				ptr = (char *)&palette[remapbuf[j]*3];
6987 				*ptr2++ = getclosestcol((long)ptr[0]+mulscale16(r-ptr[0],palscale),
6988 												(long)ptr[1]+mulscale16(g-ptr[1],palscale),
6989 												(long)ptr[2]+mulscale16(b-ptr[2],palscale));
6990 			}
6991 		}
6992 	}
6993 
6994 	if ((vidoption == 6) && (qsetmode == 200))
6995 	{
6996 		for(i=0;i<256;i++)
6997 		{
6998 			dist = palette[i*3]*3+palette[i*3+1]*5+palette[i*3+2]*2;
6999 			ptr = (char *)(FP_OFF(palookup[palnum])+i);
7000 			for(j=0;j<32;j++)
7001 				ptr[j<<8] = (char)min(max(mulscale10(dist,32-j),0),15);
7002 		}
7003 	}
7004 }
7005 
initfastcolorlookup(long rscale,long gscale,long bscale)7006 initfastcolorlookup(long rscale, long gscale, long bscale)
7007 {
7008 	long i, j, x, y, z;
7009 	char *pal1;
7010 
7011 	j = 0;
7012 	for(i=64;i>=0;i--)
7013 	{
7014 		//j = (i-64)*(i-64);
7015 		rdist[i] = rdist[128-i] = j*rscale;
7016 		gdist[i] = gdist[128-i] = j*gscale;
7017 		bdist[i] = bdist[128-i] = j*bscale;
7018 		j += 129-(i<<1);
7019 	}
7020 
7021 	clearbufbyte(FP_OFF(colhere),sizeof(colhere),0L);
7022 	clearbufbyte(FP_OFF(colhead),sizeof(colhead),0L);
7023 
7024 	pal1 = (char *)&palette[768-3];
7025 	for(i=255;i>=0;i--,pal1-=3)
7026 	{
7027 		j = (pal1[0]>>3)*FASTPALGRIDSIZ*FASTPALGRIDSIZ+(pal1[1]>>3)*FASTPALGRIDSIZ+(pal1[2]>>3)+FASTPALGRIDSIZ*FASTPALGRIDSIZ+FASTPALGRIDSIZ+1;
7028 		if (colhere[j>>3]&pow2char[j&7]) colnext[i] = colhead[j]; else colnext[i] = -1;
7029 		colhead[j] = i;
7030 		colhere[j>>3] |= pow2char[j&7];
7031 	}
7032 
7033 	i = 0;
7034 	for(x=-FASTPALGRIDSIZ*FASTPALGRIDSIZ;x<=FASTPALGRIDSIZ*FASTPALGRIDSIZ;x+=FASTPALGRIDSIZ*FASTPALGRIDSIZ)
7035 		for(y=-FASTPALGRIDSIZ;y<=FASTPALGRIDSIZ;y+=FASTPALGRIDSIZ)
7036 			for(z=-1;z<=1;z++)
7037 				colscan[i++] = x+y+z;
7038 	i = colscan[13]; colscan[13] = colscan[26]; colscan[26] = i;
7039 }
7040 
getclosestcol(long r,long g,long b)7041 getclosestcol(long r, long g, long b)
7042 {
7043 	long x, y, z, i, j, k, dist, mindist, retcol;
7044 	char *pal1;
7045 
7046 	j = (r>>3)*FASTPALGRIDSIZ*FASTPALGRIDSIZ+(g>>3)*FASTPALGRIDSIZ+(b>>3)+FASTPALGRIDSIZ*FASTPALGRIDSIZ+FASTPALGRIDSIZ+1;
7047 	mindist = min(rdist[coldist[r&7]+64+8],gdist[coldist[g&7]+64+8]);
7048 	mindist = min(mindist,bdist[coldist[b&7]+64+8]);
7049 	mindist++;
7050 
7051 	r = 64-r; g = 64-g; b = 64-b;
7052 
7053 	retcol = -1;
7054 	for(k=26;k>=0;k--)
7055 	{
7056 		i = colscan[k]+j; if ((colhere[i>>3]&pow2char[i&7]) == 0) continue;
7057 		i = colhead[i];
7058 		do
7059 		{
7060 			pal1 = (char *)&palette[i*3];
7061 			dist = gdist[pal1[1]+g];
7062 			if (dist < mindist)
7063 			{
7064 				dist += rdist[pal1[0]+r];
7065 				if (dist < mindist)
7066 				{
7067 					dist += bdist[pal1[2]+b];
7068 					if (dist < mindist) { mindist = dist; retcol = i; }
7069 				}
7070 			}
7071 			i = colnext[i];
7072 		} while (i >= 0);
7073 	}
7074 	if (retcol >= 0) return(retcol);
7075 
7076 	mindist = 0x7fffffff;
7077 	pal1 = (char *)&palette[768-3];
7078 	for(i=255;i>=0;i--,pal1-=3)
7079 	{
7080 		dist = gdist[pal1[1]+g]; if (dist >= mindist) continue;
7081 		dist += rdist[pal1[0]+r]; if (dist >= mindist) continue;
7082 		dist += bdist[pal1[2]+b]; if (dist >= mindist) continue;
7083 		mindist = dist; retcol = i;
7084 	}
7085 	return(retcol);
7086 }
7087 
setbrightness(char dabrightness,char * dapal)7088 setbrightness(char dabrightness, char *dapal)
7089 {
7090 	char *ptr;
7091 	long i, j, k, dist, daval;
7092 
7093 	curbrightness = min(max((long)dabrightness,0),15);
7094 
7095 	k = 0;
7096 	if (vidoption == 6)
7097 	{
7098 		for(j=0;j<16;j++)
7099 			for(i=0;i<16;i++)
7100 			{
7101 				tempbuf[k++] = britable[curbrightness][j<<2];
7102 				tempbuf[k++] = 0;
7103 				tempbuf[k++] = britable[curbrightness][i<<2];
7104 				tempbuf[k++] = 0;
7105 			}
7106 	}
7107 	else
7108 	{
7109 		for(i=0;i<256;i++)
7110 		{
7111 			tempbuf[k++] = britable[curbrightness][dapal[i*3+2]];
7112 			tempbuf[k++] = britable[curbrightness][dapal[i*3+1]];
7113 			tempbuf[k++] = britable[curbrightness][dapal[i*3+0]];
7114 			tempbuf[k++] = 0;
7115 		}
7116 	}
7117 
7118 	VBE_setPalette(0,256,tempbuf);
7119 }
7120 
drawmapview(long dax,long day,long zoome,short ang)7121 drawmapview (long dax, long day, long zoome, short ang)
7122 {
7123 	walltype *wal;
7124 	sectortype *sec;
7125 	spritetype *spr;
7126 	long tilenum, xoff, yoff, i, j, k, l, cosang, sinang, xspan, yspan;
7127 	long xrepeat, yrepeat, x, y, x1, y1, x2, y2, x3, y3, x4, y4, bakx1, baky1;
7128 	long s, w, ox, oy, startwall, cx1, cy1, cx2, cy2;
7129 	long bakgxvect, bakgyvect, sortnum, gap, npoints;
7130 	long xvect, yvect, xvect2, yvect2, daslope;
7131 
7132 	beforedrawrooms = 0;
7133 	totalarea += (windowx2+1-windowx1)*(windowy2+1-windowy1);
7134 
7135 	clearbuf((long)(&gotsector[0]),(long)((numsectors+31)>>5),0L);
7136 
7137 	cx1 = (windowx1<<16); cy1 = (windowy1<<16);
7138 	cx2 = ((windowx2+1)<<16)-1; cy2 = ((windowy2+1)<<16)-1;
7139 	zoome <<= 8;
7140 	bakgxvect = divscale28(sintable[(1536-ang)&2047],zoome);
7141 	bakgyvect = divscale28(sintable[(2048-ang)&2047],zoome);
7142 	xvect = mulscale8(sintable[(2048-ang)&2047],zoome);
7143 	yvect = mulscale8(sintable[(1536-ang)&2047],zoome);
7144 	xvect2 = mulscale16(xvect,yxaspect);
7145 	yvect2 = mulscale16(yvect,yxaspect);
7146 
7147 	sortnum = 0;
7148 	for(s=0,sec=&sector[s];s<numsectors;s++,sec++)
7149 		if (show2dsector[s>>3]&pow2char[s&7])
7150 		{
7151 			npoints = 0; i = 0;
7152 			startwall = sec->wallptr;
7153 			for(w=sec->wallnum,wal=&wall[startwall];w>0;w--,wal++)
7154 			{
7155 				ox = wal->x - dax; oy = wal->y - day;
7156 				x = dmulscale12(ox,xvect,-oy,yvect) + (xdim<<15);
7157 				y = dmulscale12(oy,xvect2,ox,yvect2) + (ydim<<15);
7158 				i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
7159 				rx1[npoints] = x;
7160 				ry1[npoints] = y;
7161 				xb1[npoints] = wal->point2 - startwall;
7162 				npoints++;
7163 			}
7164 			if ((i&0xf0) != 0xf0) continue;
7165 			bakx1 = rx1[0]; baky1 = mulscale16(ry1[0]-(ydim<<15),xyaspect)+(ydim<<15);
7166 			if (i&0x0f)
7167 			{
7168 				npoints = clippoly(npoints,i);
7169 				if (npoints < 3) continue;
7170 			}
7171 
7172 				//Collect floor sprites to draw
7173 			for(i=headspritesect[s];i>=0;i=nextspritesect[i])
7174 				if ((sprite[i].cstat&48) == 32)
7175 				{
7176 					if ((sprite[i].cstat&(64+8)) == (64+8)) continue;
7177 					tsprite[sortnum++].owner = i;
7178 				}
7179 
7180 			gotsector[s>>3] |= pow2char[s&7];
7181 
7182 			globalorientation = (long)sec->floorstat;
7183 			if ((globalorientation&1) != 0) continue;
7184 
7185 			if (palookup[sec->floorpal] != globalpalwritten)
7186 			{
7187 				globalpalwritten = palookup[sec->floorpal];
7188 				setpalookupaddress(globalpalwritten);
7189 			}
7190 			globalpicnum = sec->floorpicnum;
7191 			if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
7192 			setgotpic(globalpicnum);
7193 			if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) continue;
7194 			if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs((short)globalpicnum,s);
7195 			if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
7196 			globalbufplc = waloff[globalpicnum];
7197 			globalshade = max(min(sec->floorshade,numpalookups-1),0);
7198 			globvis = globalhisibility;
7199 			if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
7200 			globalpolytype = 0;
7201 			if ((globalorientation&64) == 0)
7202 			{
7203 				globalposx = dax; globalx1 = bakgxvect; globaly1 = bakgyvect;
7204 				globalposy = day; globalx2 = bakgxvect; globaly2 = bakgyvect;
7205 			}
7206 			else
7207 			{
7208 				ox = wall[wall[startwall].point2].x - wall[startwall].x;
7209 				oy = wall[wall[startwall].point2].y - wall[startwall].y;
7210 				i = nsqrtasm(ox*ox+oy*oy); if (i == 0) continue;
7211 				i = 1048576/i;
7212 				globalx1 = mulscale10(dmulscale10(ox,bakgxvect,oy,bakgyvect),i);
7213 				globaly1 = mulscale10(dmulscale10(ox,bakgyvect,-oy,bakgxvect),i);
7214 				ox = (bakx1>>8)-(xdim<<7); oy = (baky1>>8)-(ydim<<7);
7215 				globalposx = dmulscale28(-oy,globalx1,-ox,globaly1);
7216 				globalposy = dmulscale28(-ox,globalx1,oy,globaly1);
7217 				globalx2 = -globalx1;
7218 				globaly2 = -globaly1;
7219 
7220 				daslope = sector[s].floorheinum;
7221 				i = nsqrtasm(daslope*daslope+16777216);
7222 				globalposy = mulscale12(globalposy,i);
7223 				globalx2 = mulscale12(globalx2,i);
7224 				globaly2 = mulscale12(globaly2,i);
7225 			}
7226 			globalxshift = (8-(picsiz[globalpicnum]&15));
7227 			globalyshift = (8-(picsiz[globalpicnum]>>4));
7228 			if (globalorientation&8) {globalxshift++; globalyshift++; }
7229 
7230 			sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
7231 
7232 			if ((globalorientation&0x4) > 0)
7233 			{
7234 				i = globalposx; globalposx = -globalposy; globalposy = -i;
7235 				i = globalx2; globalx2 = globaly1; globaly1 = i;
7236 				i = globalx1; globalx1 = -globaly2; globaly2 = -i;
7237 			}
7238 			if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalposx = -globalposx;
7239 			if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalposy = -globalposy;
7240 			asm1 = (globaly1<<globalxshift);
7241 			asm2 = (globalx2<<globalyshift);
7242 			globalx1 <<= globalxshift;
7243 			globaly2 <<= globalyshift;
7244 			globalposx = (globalposx<<(20+globalxshift))+(((long)sec->floorxpanning)<<24);
7245 			globalposy = (globalposy<<(20+globalyshift))-(((long)sec->floorypanning)<<24);
7246 
7247 			fillpolygon(npoints);
7248 		}
7249 
7250 		//Sort sprite list
7251 	gap = 1; while (gap < sortnum) gap = (gap<<1)+1;
7252 	for(gap>>=1;gap>0;gap>>=1)
7253 		for(i=0;i<sortnum-gap;i++)
7254 			for(j=i;j>=0;j-=gap)
7255 			{
7256 				if (sprite[tsprite[j].owner].z <= sprite[tsprite[j+gap].owner].z) break;
7257 				swapshort(&tsprite[j].owner,&tsprite[j+gap].owner);
7258 			}
7259 
7260 	for(s=sortnum-1;s>=0;s--)
7261 	{
7262 		spr = &sprite[tsprite[s].owner];
7263 		if ((spr->cstat&48) == 32)
7264 		{
7265 			npoints = 0;
7266 
7267 			tilenum = spr->picnum;
7268 			xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
7269 			yoff = (long)((signed char)((picanm[tilenum]>>16)&255))+((long)spr->yoffset);
7270 			if ((spr->cstat&4) > 0) xoff = -xoff;
7271 			if ((spr->cstat&8) > 0) yoff = -yoff;
7272 
7273 			k = spr->ang;
7274 			cosang = sintable[(k+512)&2047]; sinang = sintable[k];
7275 			xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat;
7276 			yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat;
7277 
7278 			ox = ((xspan>>1)+xoff)*xrepeat; oy = ((yspan>>1)+yoff)*yrepeat;
7279 			x1 = spr->x + mulscale(sinang,ox,16) + mulscale(cosang,oy,16);
7280 			y1 = spr->y + mulscale(sinang,oy,16) - mulscale(cosang,ox,16);
7281 			l = xspan*xrepeat;
7282 			x2 = x1 - mulscale(sinang,l,16);
7283 			y2 = y1 + mulscale(cosang,l,16);
7284 			l = yspan*yrepeat;
7285 			k = -mulscale(cosang,l,16); x3 = x2+k; x4 = x1+k;
7286 			k = -mulscale(sinang,l,16); y3 = y2+k; y4 = y1+k;
7287 
7288 			xb1[0] = 1; xb1[1] = 2; xb1[2] = 3; xb1[3] = 0;
7289 			npoints = 4;
7290 
7291 			i = 0;
7292 
7293 			ox = x1 - dax; oy = y1 - day;
7294 			x = dmulscale12(ox,xvect,-oy,yvect) + (xdim<<15);
7295 			y = dmulscale12(oy,xvect2,ox,yvect2) + (ydim<<15);
7296 			i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
7297 			rx1[0] = x; ry1[0] = y;
7298 
7299 			ox = x2 - dax; oy = y2 - day;
7300 			x = dmulscale12(ox,xvect,-oy,yvect) + (xdim<<15);
7301 			y = dmulscale12(oy,xvect2,ox,yvect2) + (ydim<<15);
7302 			i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
7303 			rx1[1] = x; ry1[1] = y;
7304 
7305 			ox = x3 - dax; oy = y3 - day;
7306 			x = dmulscale12(ox,xvect,-oy,yvect) + (xdim<<15);
7307 			y = dmulscale12(oy,xvect2,ox,yvect2) + (ydim<<15);
7308 			i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
7309 			rx1[2] = x; ry1[2] = y;
7310 
7311 			x = rx1[0]+rx1[2]-rx1[1];
7312 			y = ry1[0]+ry1[2]-ry1[1];
7313 			i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
7314 			rx1[3] = x; ry1[3] = y;
7315 
7316 			if ((i&0xf0) != 0xf0) continue;
7317 			bakx1 = rx1[0]; baky1 = mulscale16(ry1[0]-(ydim<<15),xyaspect)+(ydim<<15);
7318 			if (i&0x0f)
7319 			{
7320 				npoints = clippoly(npoints,i);
7321 				if (npoints < 3) continue;
7322 			}
7323 
7324 			globalpicnum = spr->picnum;
7325 			if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
7326 			setgotpic(globalpicnum);
7327 			if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) continue;
7328 			if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs((short)globalpicnum,s);
7329 			if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
7330 			globalbufplc = waloff[globalpicnum];
7331 			if ((sector[spr->sectnum].ceilingstat&1) > 0)
7332 				globalshade = ((long)sector[spr->sectnum].ceilingshade);
7333 			else
7334 				globalshade = ((long)sector[spr->sectnum].floorshade);
7335 			globalshade = max(min(globalshade+spr->shade+6,numpalookups-1),0);
7336 			asm3 = FP_OFF(palookup[spr->pal]+(globalshade<<8));
7337 			globvis = globalhisibility;
7338 			if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
7339 			globalpolytype = ((spr->cstat&2)>>1)+1;
7340 
7341 				//relative alignment stuff
7342 			ox = x2-x1; oy = y2-y1;
7343 			i = ox*ox+oy*oy; if (i == 0) continue; i = (65536*16384)/i;
7344 			globalx1 = mulscale10(dmulscale10(ox,bakgxvect,oy,bakgyvect),i);
7345 			globaly1 = mulscale10(dmulscale10(ox,bakgyvect,-oy,bakgxvect),i);
7346 			ox = y1-y4; oy = x4-x1;
7347 			i = ox*ox+oy*oy; if (i == 0) continue; i = (65536*16384)/i;
7348 			globalx2 = mulscale10(dmulscale10(ox,bakgxvect,oy,bakgyvect),i);
7349 			globaly2 = mulscale10(dmulscale10(ox,bakgyvect,-oy,bakgxvect),i);
7350 
7351 			ox = picsiz[globalpicnum]; oy = ((ox>>4)&15); ox &= 15;
7352 			if (pow2long[ox] != xspan)
7353 			{
7354 				ox++;
7355 				globalx1 = mulscale(globalx1,xspan,ox);
7356 				globaly1 = mulscale(globaly1,xspan,ox);
7357 			}
7358 
7359 			bakx1 = (bakx1>>8)-(xdim<<7); baky1 = (baky1>>8)-(ydim<<7);
7360 			globalposx = dmulscale28(-baky1,globalx1,-bakx1,globaly1);
7361 			globalposy = dmulscale28(bakx1,globalx2,-baky1,globaly2);
7362 
7363 			if ((spr->cstat&2) == 0)
7364 				msethlineshift(ox,oy);
7365 			else
7366 				tsethlineshift(ox,oy);
7367 
7368 			if ((spr->cstat&0x4) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalposx = -globalposx;
7369 			asm1 = (globaly1<<2); globalx1 <<= 2; globalposx <<= (20+2);
7370 			asm2 = (globalx2<<2); globaly2 <<= 2; globalposy <<= (20+2);
7371 
7372 			fillpolygon(npoints);
7373 		}
7374 	}
7375 }
7376 
clippoly(long npoints,long clipstat)7377 clippoly (long npoints, long clipstat)
7378 {
7379 	long z, zz, s1, s2, t, npoints2, start2, z1, z2, z3, z4, splitcnt;
7380 	long cx1, cy1, cx2, cy2;
7381 
7382 	cx1 = windowx1;
7383 	cy1 = windowy1;
7384 	cx2 = windowx2+1;
7385 	cy2 = windowy2+1;
7386 	cx1 <<= 16; cy1 <<= 16; cx2 <<= 16; cy2 <<= 16;
7387 
7388 	if (clipstat&0xa)   //Need to clip top or left
7389 	{
7390 		npoints2 = 0; start2 = 0; z = 0; splitcnt = 0;
7391 		do
7392 		{
7393 			s2 = cx1-rx1[z];
7394 			do
7395 			{
7396 				zz = xb1[z]; xb1[z] = -1;
7397 				s1 = s2; s2 = cx1-rx1[zz];
7398 				if (s1 < 0)
7399 				{
7400 					rx2[npoints2] = rx1[z]; ry2[npoints2] = ry1[z];
7401 					xb2[npoints2] = npoints2+1; npoints2++;
7402 				}
7403 				if ((s1^s2) < 0)
7404 				{
7405 					rx2[npoints2] = rx1[z]+scale(rx1[zz]-rx1[z],s1,s1-s2);
7406 					ry2[npoints2] = ry1[z]+scale(ry1[zz]-ry1[z],s1,s1-s2);
7407 					if (s1 < 0) p2[splitcnt++] = npoints2;
7408 					xb2[npoints2] = npoints2+1;
7409 					npoints2++;
7410 				}
7411 				z = zz;
7412 			} while (xb1[z] >= 0);
7413 
7414 			if (npoints2 >= start2+3)
7415 				xb2[npoints2-1] = start2, start2 = npoints2;
7416 			else
7417 				npoints2 = start2;
7418 
7419 			z = 1;
7420 			while ((z < npoints) && (xb1[z] < 0)) z++;
7421 		} while (z < npoints);
7422 		if (npoints2 <= 2) return(0);
7423 
7424 		for(z=1;z<splitcnt;z++)
7425 			for(zz=0;zz<z;zz++)
7426 			{
7427 				z1 = p2[z]; z2 = xb2[z1]; z3 = p2[zz]; z4 = xb2[z3];
7428 				s1  = klabs(rx2[z1]-rx2[z2])+klabs(ry2[z1]-ry2[z2]);
7429 				s1 += klabs(rx2[z3]-rx2[z4])+klabs(ry2[z3]-ry2[z4]);
7430 				s2  = klabs(rx2[z1]-rx2[z4])+klabs(ry2[z1]-ry2[z4]);
7431 				s2 += klabs(rx2[z3]-rx2[z2])+klabs(ry2[z3]-ry2[z2]);
7432 				if (s2 < s1)
7433 					{ t = xb2[p2[z]]; xb2[p2[z]] = xb2[p2[zz]]; xb2[p2[zz]] = t; }
7434 			}
7435 
7436 
7437 		npoints = 0; start2 = 0; z = 0; splitcnt = 0;
7438 		do
7439 		{
7440 			s2 = cy1-ry2[z];
7441 			do
7442 			{
7443 				zz = xb2[z]; xb2[z] = -1;
7444 				s1 = s2; s2 = cy1-ry2[zz];
7445 				if (s1 < 0)
7446 				{
7447 					rx1[npoints] = rx2[z]; ry1[npoints] = ry2[z];
7448 					xb1[npoints] = npoints+1; npoints++;
7449 				}
7450 				if ((s1^s2) < 0)
7451 				{
7452 					rx1[npoints] = rx2[z]+scale(rx2[zz]-rx2[z],s1,s1-s2);
7453 					ry1[npoints] = ry2[z]+scale(ry2[zz]-ry2[z],s1,s1-s2);
7454 					if (s1 < 0) p2[splitcnt++] = npoints;
7455 					xb1[npoints] = npoints+1;
7456 					npoints++;
7457 				}
7458 				z = zz;
7459 			} while (xb2[z] >= 0);
7460 
7461 			if (npoints >= start2+3)
7462 				xb1[npoints-1] = start2, start2 = npoints;
7463 			else
7464 				npoints = start2;
7465 
7466 			z = 1;
7467 			while ((z < npoints2) && (xb2[z] < 0)) z++;
7468 		} while (z < npoints2);
7469 		if (npoints <= 2) return(0);
7470 
7471 		for(z=1;z<splitcnt;z++)
7472 			for(zz=0;zz<z;zz++)
7473 			{
7474 				z1 = p2[z]; z2 = xb1[z1]; z3 = p2[zz]; z4 = xb1[z3];
7475 				s1  = klabs(rx1[z1]-rx1[z2])+klabs(ry1[z1]-ry1[z2]);
7476 				s1 += klabs(rx1[z3]-rx1[z4])+klabs(ry1[z3]-ry1[z4]);
7477 				s2  = klabs(rx1[z1]-rx1[z4])+klabs(ry1[z1]-ry1[z4]);
7478 				s2 += klabs(rx1[z3]-rx1[z2])+klabs(ry1[z3]-ry1[z2]);
7479 				if (s2 < s1)
7480 					{ t = xb1[p2[z]]; xb1[p2[z]] = xb1[p2[zz]]; xb1[p2[zz]] = t; }
7481 			}
7482 	}
7483 	if (clipstat&0x5)   //Need to clip bottom or right
7484 	{
7485 		npoints2 = 0; start2 = 0; z = 0; splitcnt = 0;
7486 		do
7487 		{
7488 			s2 = rx1[z]-cx2;
7489 			do
7490 			{
7491 				zz = xb1[z]; xb1[z] = -1;
7492 				s1 = s2; s2 = rx1[zz]-cx2;
7493 				if (s1 < 0)
7494 				{
7495 					rx2[npoints2] = rx1[z]; ry2[npoints2] = ry1[z];
7496 					xb2[npoints2] = npoints2+1; npoints2++;
7497 				}
7498 				if ((s1^s2) < 0)
7499 				{
7500 					rx2[npoints2] = rx1[z]+scale(rx1[zz]-rx1[z],s1,s1-s2);
7501 					ry2[npoints2] = ry1[z]+scale(ry1[zz]-ry1[z],s1,s1-s2);
7502 					if (s1 < 0) p2[splitcnt++] = npoints2;
7503 					xb2[npoints2] = npoints2+1;
7504 					npoints2++;
7505 				}
7506 				z = zz;
7507 			} while (xb1[z] >= 0);
7508 
7509 			if (npoints2 >= start2+3)
7510 				xb2[npoints2-1] = start2, start2 = npoints2;
7511 			else
7512 				npoints2 = start2;
7513 
7514 			z = 1;
7515 			while ((z < npoints) && (xb1[z] < 0)) z++;
7516 		} while (z < npoints);
7517 		if (npoints2 <= 2) return(0);
7518 
7519 		for(z=1;z<splitcnt;z++)
7520 			for(zz=0;zz<z;zz++)
7521 			{
7522 				z1 = p2[z]; z2 = xb2[z1]; z3 = p2[zz]; z4 = xb2[z3];
7523 				s1  = klabs(rx2[z1]-rx2[z2])+klabs(ry2[z1]-ry2[z2]);
7524 				s1 += klabs(rx2[z3]-rx2[z4])+klabs(ry2[z3]-ry2[z4]);
7525 				s2  = klabs(rx2[z1]-rx2[z4])+klabs(ry2[z1]-ry2[z4]);
7526 				s2 += klabs(rx2[z3]-rx2[z2])+klabs(ry2[z3]-ry2[z2]);
7527 				if (s2 < s1)
7528 					{ t = xb2[p2[z]]; xb2[p2[z]] = xb2[p2[zz]]; xb2[p2[zz]] = t; }
7529 			}
7530 
7531 
7532 		npoints = 0; start2 = 0; z = 0; splitcnt = 0;
7533 		do
7534 		{
7535 			s2 = ry2[z]-cy2;
7536 			do
7537 			{
7538 				zz = xb2[z]; xb2[z] = -1;
7539 				s1 = s2; s2 = ry2[zz]-cy2;
7540 				if (s1 < 0)
7541 				{
7542 					rx1[npoints] = rx2[z]; ry1[npoints] = ry2[z];
7543 					xb1[npoints] = npoints+1; npoints++;
7544 				}
7545 				if ((s1^s2) < 0)
7546 				{
7547 					rx1[npoints] = rx2[z]+scale(rx2[zz]-rx2[z],s1,s1-s2);
7548 					ry1[npoints] = ry2[z]+scale(ry2[zz]-ry2[z],s1,s1-s2);
7549 					if (s1 < 0) p2[splitcnt++] = npoints;
7550 					xb1[npoints] = npoints+1;
7551 					npoints++;
7552 				}
7553 				z = zz;
7554 			} while (xb2[z] >= 0);
7555 
7556 			if (npoints >= start2+3)
7557 				xb1[npoints-1] = start2, start2 = npoints;
7558 			else
7559 				npoints = start2;
7560 
7561 			z = 1;
7562 			while ((z < npoints2) && (xb2[z] < 0)) z++;
7563 		} while (z < npoints2);
7564 		if (npoints <= 2) return(0);
7565 
7566 		for(z=1;z<splitcnt;z++)
7567 			for(zz=0;zz<z;zz++)
7568 			{
7569 				z1 = p2[z]; z2 = xb1[z1]; z3 = p2[zz]; z4 = xb1[z3];
7570 				s1  = klabs(rx1[z1]-rx1[z2])+klabs(ry1[z1]-ry1[z2]);
7571 				s1 += klabs(rx1[z3]-rx1[z4])+klabs(ry1[z3]-ry1[z4]);
7572 				s2  = klabs(rx1[z1]-rx1[z4])+klabs(ry1[z1]-ry1[z4]);
7573 				s2 += klabs(rx1[z3]-rx1[z2])+klabs(ry1[z3]-ry1[z2]);
7574 				if (s2 < s1)
7575 					{ t = xb1[p2[z]]; xb1[p2[z]] = xb1[p2[zz]]; xb1[p2[zz]] = t; }
7576 			}
7577 	}
7578 	return(npoints);
7579 }
7580 
fillpolygon(long npoints)7581 fillpolygon(long npoints)
7582 {
7583 	long z, zz, zzz, x1, y1, x2, y2, miny, maxy, x, y, xinc, cnt;
7584 	long ox, oy, bx, by, bxinc, byinc, xend, p, r, day1, day2;
7585 	short *ptr, *ptr2;
7586 
7587 	miny = 0x7fffffff; maxy = 0x80000000;
7588 	for(z=npoints-1;z>=0;z--)
7589 		{ y = ry1[z]; miny = min(miny,y); maxy = max(maxy,y); }
7590 	miny = (miny>>16); maxy = (maxy>>16);
7591 	if (miny < 0) miny = 0;
7592 	if (maxy >= ydim) maxy = ydim-1;
7593 	ptr = smost;    //They're pointers! - watch how you optimize this thing
7594 	for(y=miny;y<=maxy;y++)
7595 	{
7596 		dotp1[y] = ptr; dotp2[y] = ptr+(MAXNODESPERLINE>>1);
7597 		ptr += MAXNODESPERLINE;
7598 	}
7599 
7600 	for(z=npoints-1;z>=0;z--)
7601 	{
7602 		zz = xb1[z];
7603 		y1 = ry1[z]; day1 = (y1>>16);
7604 		y2 = ry1[zz]; day2 = (y2>>16);
7605 		if (day1 != day2)
7606 		{
7607 			x1 = rx1[z]; x2 = rx1[zz];
7608 			xinc = divscale16(x2-x1,y2-y1);
7609 			if (day2 > day1)
7610 			{
7611 				x1 += mulscale16((day1<<16)+65535-y1,xinc);
7612 				for(y=day1;y<day2;y++) { *dotp2[y]++ = (x1>>16); x1 += xinc; }
7613 			}
7614 			else
7615 			{
7616 				x2 += mulscale16((day2<<16)+65535-y2,xinc);
7617 				for(y=day2;y<day1;y++) { *dotp1[y]++ = (x2>>16); x2 += xinc; }
7618 			}
7619 		}
7620 	}
7621 
7622 	globalx1 = mulscale16(globalx1,xyaspect);
7623 	globaly2 = mulscale16(globaly2,xyaspect);
7624 
7625 	oy = miny+1-(ydim>>1);
7626 	globalposx += oy*globalx1;
7627 	globalposy += oy*globaly2;
7628 
7629 	setuphlineasm4(asm1,asm2);
7630 
7631 	ptr = smost;
7632 	for(y=miny;y<=maxy;y++)
7633 	{
7634 		cnt = dotp1[y]-ptr; ptr2 = ptr+(MAXNODESPERLINE>>1);
7635 		for(z=cnt-1;z>=0;z--)
7636 		{
7637 			day1 = 0; day2 = 0;
7638 			for(zz=z;zz>0;zz--)
7639 			{
7640 				if (ptr[zz] < ptr[day1]) day1 = zz;
7641 				if (ptr2[zz] < ptr2[day2]) day2 = zz;
7642 			}
7643 			x1 = ptr[day1]; ptr[day1] = ptr[z];
7644 			x2 = ptr2[day2]-1; ptr2[day2] = ptr2[z];
7645 			if (x1 > x2) continue;
7646 
7647 			if (globalpolytype < 1)
7648 			{
7649 					//maphline
7650 				ox = x2+1-(xdim>>1);
7651 				bx = ox*asm1 + globalposx;
7652 				by = ox*asm2 - globalposy;
7653 
7654 				p = ylookup[y]+x2+frameplace;
7655 				hlineasm4(x2-x1,-1L,globalshade<<8,by,bx,p);
7656 			}
7657 			else
7658 			{
7659 					//maphline
7660 				ox = x1+1-(xdim>>1);
7661 				bx = ox*asm1 + globalposx;
7662 				by = ox*asm2 - globalposy;
7663 
7664 				p = ylookup[y]+x1+frameplace;
7665 				if (globalpolytype == 1)
7666 					mhline(globalbufplc,bx,(x2-x1)<<16,0L,by,p);
7667 				else
7668 				{
7669 					thline(globalbufplc,bx,(x2-x1)<<16,0L,by,p);
7670 					transarea += (x2-x1);
7671 				}
7672 			}
7673 		}
7674 		globalposx += globalx1;
7675 		globalposy += globaly2;
7676 		ptr += MAXNODESPERLINE;
7677 	}
7678 	faketimerhandler();
7679 }
7680 
clearview(long dacol)7681 clearview(long dacol)
7682 {
7683 	long i, p, y, x1, x2, dx;
7684 	char *ptr;
7685 
7686 	if (qsetmode != 200) return;
7687 
7688 	dx = windowx2-windowx1+1;
7689 	dacol += (dacol<<8); dacol += (dacol<<16);
7690 	if (vidoption == 6)
7691 	{
7692 		p = FP_OFF(screen)+ylookup[windowy1]+windowx1;
7693 		for(y=windowy1;y<=windowy2;y++)
7694 		{
7695 			clearbufbyte(p,dx,dacol);
7696 			clearbufbyte(p+65536,dx,dacol);
7697 			p += ylookup[1];
7698 		}
7699 		faketimerhandler();
7700 		return;
7701 	}
7702 	p = frameplace+ylookup[windowy1]+windowx1;
7703 	for(y=windowy1;y<=windowy2;y++)
7704 		{ clearbufbyte(p,dx,dacol); p += ylookup[1]; }
7705 	faketimerhandler();
7706 }
7707 
clearallviews(long dacol)7708 clearallviews(long dacol)
7709 {
7710 	long i;
7711 
7712 	if (qsetmode != 200) return;
7713 	dacol += (dacol<<8); dacol += (dacol<<16);
7714 
7715 	switch(vidoption)
7716 	{
7717 		case 1:
7718 			for(i=0;i<numpages;i++)
7719 			{
7720 				setactivepage(i);
7721 				clearbufbyte(frameplace,imageSize,0L);
7722 			}
7723 			setactivepage(activepage);
7724 		case 2:
7725 			clearbuf(frameplace,(xdim*ydim)>>2,0L);
7726 			break;
7727 		case 6:
7728 			clearbuf(screen,128000L>>2,dacol);
7729 			break;
7730 	}
7731 	faketimerhandler();
7732 }
7733 
plotpixel(long x,long y,char col)7734 plotpixel(long x, long y, char col)
7735 {
7736 	drawpixel(ylookup[y]+x+frameplace,(long)col);
7737 }
7738 
getpixel(long x,long y)7739 char getpixel(long x, long y)
7740 {
7741 	return(readpixel(ylookup[y]+x+frameplace));
7742 }
7743 
7744 	//MUST USE RESTOREFORDRAWROOMS AFTER DRAWING
7745 static long setviewcnt = 0;
7746 static long bakvidoption[4];
7747 static long bakframeplace[4], bakxsiz[4], bakysiz[4];
7748 static long bakwindowx1[4], bakwindowy1[4];
7749 static long bakwindowx2[4], bakwindowy2[4];
7750 
setviewtotile(short tilenume,long xsiz,long ysiz)7751 setviewtotile(short tilenume, long xsiz, long ysiz)
7752 {
7753 	long i, j;
7754 
7755 		//DRAWROOMS TO TILE BACKUP&SET CODE
7756 	tilesizx[tilenume] = xsiz; tilesizy[tilenume] = ysiz;
7757 	bakxsiz[setviewcnt] = xsiz; bakysiz[setviewcnt] = ysiz;
7758 	bakvidoption[setviewcnt] = vidoption; vidoption = 2;
7759 	bakframeplace[setviewcnt] = frameplace; frameplace = waloff[tilenume];
7760 	bakwindowx1[setviewcnt] = windowx1; bakwindowy1[setviewcnt] = windowy1;
7761 	bakwindowx2[setviewcnt] = windowx2; bakwindowy2[setviewcnt] = windowy2;
7762 	copybufbyte(&startumost[windowx1],&bakumost[windowx1],(windowx2-windowx1+1)*sizeof(bakumost[0]));
7763 	copybufbyte(&startdmost[windowx1],&bakdmost[windowx1],(windowx2-windowx1+1)*sizeof(bakdmost[0]));
7764 	setview(0,0,ysiz-1,xsiz-1);
7765 	setaspect(65536,65536);
7766 	j = 0; for(i=0;i<=xsiz;i++) { ylookup[i] = j, j += ysiz; }
7767 	setvlinebpl(ysiz);
7768 	setviewcnt++;
7769 }
7770 
setviewback()7771 setviewback()
7772 {
7773 	long i, j, k, xsiz, ysiz;
7774 
7775 	if (setviewcnt <= 0) return;
7776 	setviewcnt--;
7777 
7778 	setview(bakwindowx1[setviewcnt],bakwindowy1[setviewcnt],
7779 			  bakwindowx2[setviewcnt],bakwindowy2[setviewcnt]);
7780 	copybufbyte(&bakumost[windowx1],&startumost[windowx1],(windowx2-windowx1+1)*sizeof(startumost[0]));
7781 	copybufbyte(&bakdmost[windowx1],&startdmost[windowx1],(windowx2-windowx1+1)*sizeof(startdmost[0]));
7782 	vidoption = bakvidoption[setviewcnt];
7783 	frameplace = bakframeplace[setviewcnt];
7784 	if (setviewcnt == 0)
7785 		k = bakxsiz[0];
7786 	else
7787 		k = max(bakxsiz[setviewcnt-1],bakxsiz[setviewcnt]);
7788 	j = 0; for(i=0;i<=k;i++) ylookup[i] = j, j += bytesperline;
7789 	setvlinebpl(bytesperline);
7790 }
7791 
squarerotatetile(short tilenume)7792 squarerotatetile(short tilenume)
7793 {
7794 	long i, j, k, xsiz, ysiz;
7795 	char *ptr1, *ptr2;
7796 
7797 	xsiz = tilesizx[tilenume]; ysiz = tilesizy[tilenume];
7798 
7799 		//supports square tiles only for rotation part
7800 	if (xsiz == ysiz)
7801 	{
7802 		k = (xsiz<<1);
7803 		for(i=xsiz-1;i>=0;i--)
7804 		{
7805 			ptr1 = (char *)(waloff[tilenume]+i*(xsiz+1)); ptr2 = ptr1;
7806 			if ((i&1) != 0) { ptr1--; ptr2 -= xsiz; swapchar(ptr1,ptr2); }
7807 			for(j=(i>>1)-1;j>=0;j--)
7808 				{ ptr1 -= 2; ptr2 -= k; swapchar2(ptr1,ptr2,xsiz); }
7809 		}
7810 	}
7811 }
7812 
7813 static long mirthoriz, mirbakdaz;
7814 static short mirbakdasector;
preparemirror(long dax,long day,long daz,short daang,long dahoriz,short dawall,short dasector,long * tposx,long * tposy,short * tang)7815 preparemirror(long dax, long day, long daz, short daang, long dahoriz, short dawall, short dasector, long *tposx, long *tposy, short *tang)
7816 {
7817 	long i, j, x, y, dx, dy;
7818 
7819 	x = wall[dawall].x; dx = wall[wall[dawall].point2].x-x;
7820 	y = wall[dawall].y; dy = wall[wall[dawall].point2].y-y;
7821 	j = dx*dx + dy*dy; if (j == 0) return;
7822 	i = (((dax-x)*dx + (day-y)*dy)<<1);
7823 	*tposx = (x<<1) + scale(dx,i,j) - dax;
7824 	*tposy = (y<<1) + scale(dy,i,j) - day;
7825 	*tang = (((getangle(dx,dy)<<1)-daang)&2047);
7826 
7827 	mirbakdaz = daz; mirbakdasector = dasector;
7828 	if ((daz > sector[dasector].ceilingz) && (daz < sector[dasector].floorz))
7829 	{
7830 			//Draw pink pixels on horizon to get mirror l&r bounds.
7831 		mirthoriz = scale(dahoriz-100,windowx2-windowx1,320)+((windowy1+windowy2)>>1);
7832 		if ((daz<<1) > sector[dasector].ceilingz+sector[dasector].floorz)
7833 			mirthoriz--; else mirthoriz++;
7834 		mirthoriz = min(max(mirthoriz,windowy1),windowy2);
7835 		clearbufbyte(frameplace+ylookup[mirthoriz]+windowx1,windowx2-windowx1+1,0xffffffff);
7836 	}
7837 }
7838 
completemirror()7839 completemirror()
7840 {
7841 	long i, j, k, l, x1, y1, x2, y2, dy, templong;
7842 	char *ptr;
7843 
7844 		//Get pink pixels on horizon to get mirror l&r bounds.
7845 	x1 = 0; x2 = windowx2-windowx1;
7846 	if ((mirbakdaz > sector[mirbakdasector].ceilingz) && (mirbakdaz < sector[mirbakdasector].floorz))
7847 	{
7848 		ptr = (char *)frameplace+ylookup[mirthoriz]+windowx1;
7849 		while ((ptr[x1] == 255) && (x2 >= x1)) x1++;
7850 		while ((ptr[x2] == 255) && (x2 >= x1)) x2--;
7851 		if (x1 > 0) x1--;
7852 		if (x2 < windowx2-windowx1) x2++;
7853 		x2 |= 3;
7854 		if (x2 > windowx2-windowx1) x2 = windowx2-windowx1;
7855 	}
7856 
7857 	if (x2 >= x1)  //Flip window x-wise
7858 	{
7859 		transarea += (x2-x1)*(windowy2-windowy1);
7860 
7861 		ptr = (char *)frameplace+ylookup[windowy1]+windowx1;
7862 		y1 = windowx2-windowx1-x2; x2 -= x1; y2 = x2+1;
7863 		for(dy=windowy2-windowy1;dy>=0;dy--)
7864 		{
7865 			copybufbyte(&ptr[x1+1],&tempbuf[0],y2);
7866 			tempbuf[x2] = tempbuf[x2-1];
7867 			copybufreverse(&tempbuf[x2],&ptr[y1],y2);
7868 			ptr += ylookup[1];
7869 			faketimerhandler();
7870 		}
7871 	}
7872 }
7873 
sectorofwall(short theline)7874 sectorofwall(short theline)
7875 {
7876 	long i, j, gap;
7877 
7878 	if ((theline < 0) || (theline >= numwalls)) return(-1);
7879 	i = wall[theline].nextwall; if (i >= 0) return(wall[i].nextsector);
7880 
7881 	gap = (numsectors>>1); i = gap;
7882 	while (gap > 1)
7883 	{
7884 		gap >>= 1;
7885 		if (sector[i].wallptr < theline) i += gap; else i -= gap;
7886 	}
7887 	while (sector[i].wallptr > theline) i--;
7888 	while (sector[i].wallptr+sector[i].wallnum <= theline) i++;
7889 	return(i);
7890 }
7891 
getceilzofslope(short sectnum,long dax,long day)7892 getceilzofslope(short sectnum, long dax, long day)
7893 {
7894 	long dx, dy, i, j;
7895 	walltype *wal;
7896 
7897 	if (!(sector[sectnum].ceilingstat&2)) return(sector[sectnum].ceilingz);
7898 	wal = &wall[sector[sectnum].wallptr];
7899 	dx = wall[wal->point2].x-wal->x; dy = wall[wal->point2].y-wal->y;
7900 	i = (nsqrtasm(dx*dx+dy*dy)<<5); if (i == 0) return(sector[sectnum].ceilingz);
7901 	j = dmulscale3(dx,day-wal->y,-dy,dax-wal->x);
7902 	return(sector[sectnum].ceilingz+scale(sector[sectnum].ceilingheinum,j,i));
7903 }
7904 
getflorzofslope(short sectnum,long dax,long day)7905 getflorzofslope(short sectnum, long dax, long day)
7906 {
7907 	long dx, dy, i, j;
7908 	walltype *wal;
7909 
7910 	if (!(sector[sectnum].floorstat&2)) return(sector[sectnum].floorz);
7911 	wal = &wall[sector[sectnum].wallptr];
7912 	dx = wall[wal->point2].x-wal->x; dy = wall[wal->point2].y-wal->y;
7913 	i = (nsqrtasm(dx*dx+dy*dy)<<5); if (i == 0) return(sector[sectnum].floorz);
7914 	j = dmulscale3(dx,day-wal->y,-dy,dax-wal->x);
7915 	return(sector[sectnum].floorz+scale(sector[sectnum].floorheinum,j,i));
7916 }
7917 
getzsofslope(short sectnum,long dax,long day,long * ceilz,long * florz)7918 getzsofslope(short sectnum, long dax, long day, long *ceilz, long *florz)
7919 {
7920 	long dx, dy, i, j;
7921 	walltype *wal, *wal2;
7922 	sectortype *sec;
7923 
7924 	sec = &sector[sectnum];
7925 	*ceilz = sec->ceilingz; *florz = sec->floorz;
7926 	if ((sec->ceilingstat|sec->floorstat)&2)
7927 	{
7928 		wal = &wall[sec->wallptr]; wal2 = &wall[wal->point2];
7929 		dx = wal2->x-wal->x; dy = wal2->y-wal->y;
7930 		i = (nsqrtasm(dx*dx+dy*dy)<<5); if (i == 0) return;
7931 		j = dmulscale3(dx,day-wal->y,-dy,dax-wal->x);
7932 		if (sec->ceilingstat&2) *ceilz = (*ceilz)+scale(sec->ceilingheinum,j,i);
7933 		if (sec->floorstat&2) *florz = (*florz)+scale(sec->floorheinum,j,i);
7934 	}
7935 }
7936 
alignceilslope(short dasect,long x,long y,long z)7937 alignceilslope(short dasect, long x, long y, long z)
7938 {
7939 	long i, dax, day;
7940 	walltype *wal;
7941 
7942 	wal = &wall[sector[dasect].wallptr];
7943 	dax = wall[wal->point2].x-wal->x;
7944 	day = wall[wal->point2].y-wal->y;
7945 
7946 	i = (y-wal->y)*dax - (x-wal->x)*day; if (i == 0) return;
7947 	sector[dasect].ceilingheinum = scale((z-sector[dasect].ceilingz)<<8,
7948 													 nsqrtasm(dax*dax+day*day),i);
7949 
7950 	if (sector[dasect].ceilingheinum == 0) sector[dasect].ceilingstat &= ~2;
7951 												 else sector[dasect].ceilingstat |= 2;
7952 }
7953 
alignflorslope(short dasect,long x,long y,long z)7954 alignflorslope(short dasect, long x, long y, long z)
7955 {
7956 	long i, dax, day;
7957 	walltype *wal;
7958 
7959 	wal = &wall[sector[dasect].wallptr];
7960 	dax = wall[wal->point2].x-wal->x;
7961 	day = wall[wal->point2].y-wal->y;
7962 
7963 	i = (y-wal->y)*dax - (x-wal->x)*day; if (i == 0) return;
7964 	sector[dasect].floorheinum = scale((z-sector[dasect].floorz)<<8,
7965 												  nsqrtasm(dax*dax+day*day),i);
7966 
7967 	if (sector[dasect].floorheinum == 0) sector[dasect].floorstat &= ~2;
7968 											  else sector[dasect].floorstat |= 2;
7969 }
7970 
owallmost(short * mostbuf,long w,long z)7971 owallmost(short *mostbuf, long w, long z)
7972 {
7973 	long bad, x, intx, inty, xcross, y, yy, yinc;
7974 	long s1, s2, s3, s4, ix1, ix2, iy1, iy2, t, x1, x2;
7975 
7976 	z <<= 7;
7977 	s1 = mulscale20(globaluclip,yb1[w]); s2 = mulscale20(globaluclip,yb2[w]);
7978 	s3 = mulscale20(globaldclip,yb1[w]); s4 = mulscale20(globaldclip,yb2[w]);
7979 	bad = (z<s1)+((z<s2)<<1)+((z>s3)<<2)+((z>s4)<<3);
7980 
7981 	ix1 = xb1[w]; iy1 = yb1[w];
7982 	ix2 = xb2[w]; iy2 = yb2[w];
7983 
7984 	if ((bad&3) == 3)
7985 	{
7986 		clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),0L);
7987 		return(bad);
7988 	}
7989 
7990 	if ((bad&12) == 12)
7991 	{
7992 		clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
7993 		return(bad);
7994 	}
7995 
7996 	if (bad&3)
7997 	{
7998 		t = divscale30(z-s1,s2-s1);
7999 		inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
8000 		xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty);
8001 
8002 		if ((bad&3) == 2)
8003 		{
8004 			if (xb1[w] <= xcross) { iy2 = inty; ix2 = xcross; }
8005 			clearbufbyte(&mostbuf[xcross+1],(xb2[w]-xcross)*sizeof(mostbuf[0]),0L);
8006 		}
8007 		else
8008 		{
8009 			if (xcross <= xb2[w]) { iy1 = inty; ix1 = xcross; }
8010 			clearbufbyte(&mostbuf[xb1[w]],(xcross-xb1[w]+1)*sizeof(mostbuf[0]),0L);
8011 		}
8012 	}
8013 
8014 	if (bad&12)
8015 	{
8016 		t = divscale30(z-s3,s4-s3);
8017 		inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
8018 		xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty);
8019 
8020 		if ((bad&12) == 8)
8021 		{
8022 			if (xb1[w] <= xcross) { iy2 = inty; ix2 = xcross; }
8023 			clearbufbyte(&mostbuf[xcross+1],(xb2[w]-xcross)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
8024 		}
8025 		else
8026 		{
8027 			if (xcross <= xb2[w]) { iy1 = inty; ix1 = xcross; }
8028 			clearbufbyte(&mostbuf[xb1[w]],(xcross-xb1[w]+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
8029 		}
8030 	}
8031 
8032 	y = (scale(z,xdimenscale,iy1)<<4);
8033 	yinc = ((scale(z,xdimenscale,iy2)<<4)-y) / (ix2-ix1+1);
8034 	qinterpolatedown16short(&mostbuf[ix1],ix2-ix1+1,y+(globalhoriz<<16),yinc);
8035 
8036 	if (mostbuf[ix1] < 0) mostbuf[ix1] = 0;
8037 	if (mostbuf[ix1] > ydimen) mostbuf[ix1] = ydimen;
8038 	if (mostbuf[ix2] < 0) mostbuf[ix2] = 0;
8039 	if (mostbuf[ix2] > ydimen) mostbuf[ix2] = ydimen;
8040 
8041 	return(bad);
8042 }
8043 
wallmost(short * mostbuf,long w,long sectnum,char dastat)8044 wallmost(short *mostbuf, long w, long sectnum, char dastat)
8045 {
8046 	long bad, i, j, t, x, y, z, intx, inty, intz, xcross, yinc, fw;
8047 	long x1, y1, z1, x2, y2, z2, xv, yv, dx, dy, dasqr, oz1, oz2;
8048 	long s1, s2, s3, s4, ix1, ix2, iy1, iy2;
8049 	char datempbuf[256];
8050 
8051 	if (dastat == 0)
8052 	{
8053 		z = sector[sectnum].ceilingz-globalposz;
8054 		if ((sector[sectnum].ceilingstat&2) == 0) return(owallmost(mostbuf,w,z));
8055 	}
8056 	else
8057 	{
8058 		z = sector[sectnum].floorz-globalposz;
8059 		if ((sector[sectnum].floorstat&2) == 0) return(owallmost(mostbuf,w,z));
8060 	}
8061 
8062 	i = thewall[w];
8063 	if (i == sector[sectnum].wallptr) return(owallmost(mostbuf,w,z));
8064 
8065 	x1 = wall[i].x; x2 = wall[wall[i].point2].x-x1;
8066 	y1 = wall[i].y; y2 = wall[wall[i].point2].y-y1;
8067 
8068 	fw = sector[sectnum].wallptr; i = wall[fw].point2;
8069 	dx = wall[i].x-wall[fw].x; dy = wall[i].y-wall[fw].y;
8070 	dasqr = krecipasm(nsqrtasm(dx*dx+dy*dy));
8071 
8072 	if (xb1[w] == 0)
8073 		{ xv = cosglobalang+sinviewingrangeglobalang; yv = singlobalang-cosviewingrangeglobalang; }
8074 	else
8075 		{ xv = x1-globalposx; yv = y1-globalposy; }
8076 	i = xv*(y1-globalposy)-yv*(x1-globalposx); j = yv*x2-xv*y2;
8077 	if (klabs(j) > klabs(i>>3)) i = divscale28(i,j);
8078 	if (dastat == 0)
8079 	{
8080 		t = mulscale15(sector[sectnum].ceilingheinum,dasqr);
8081 		z1 = sector[sectnum].ceilingz;
8082 	}
8083 	else
8084 	{
8085 		t = mulscale15(sector[sectnum].floorheinum,dasqr);
8086 		z1 = sector[sectnum].floorz;
8087 	}
8088 	z1 = dmulscale24(dx*t,mulscale20(y2,i)+((y1-wall[fw].y)<<8),
8089 						 -dy*t,mulscale20(x2,i)+((x1-wall[fw].x)<<8))+((z1-globalposz)<<7);
8090 
8091 
8092 	if (xb2[w] == xdimen-1)
8093 		{ xv = cosglobalang-sinviewingrangeglobalang; yv = singlobalang+cosviewingrangeglobalang; }
8094 	else
8095 		{ xv = (x2+x1)-globalposx; yv = (y2+y1)-globalposy; }
8096 	i = xv*(y1-globalposy)-yv*(x1-globalposx); j = yv*x2-xv*y2;
8097 	if (klabs(j) > klabs(i>>3)) i = divscale28(i,j);
8098 	if (dastat == 0)
8099 	{
8100 		t = mulscale15(sector[sectnum].ceilingheinum,dasqr);
8101 		z2 = sector[sectnum].ceilingz;
8102 	}
8103 	else
8104 	{
8105 		t = mulscale15(sector[sectnum].floorheinum,dasqr);
8106 		z2 = sector[sectnum].floorz;
8107 	}
8108 	z2 = dmulscale24(dx*t,mulscale20(y2,i)+((y1-wall[fw].y)<<8),
8109 						 -dy*t,mulscale20(x2,i)+((x1-wall[fw].x)<<8))+((z2-globalposz)<<7);
8110 
8111 
8112 	s1 = mulscale20(globaluclip,yb1[w]); s2 = mulscale20(globaluclip,yb2[w]);
8113 	s3 = mulscale20(globaldclip,yb1[w]); s4 = mulscale20(globaldclip,yb2[w]);
8114 	bad = (z1<s1)+((z2<s2)<<1)+((z1>s3)<<2)+((z2>s4)<<3);
8115 
8116 	ix1 = xb1[w]; ix2 = xb2[w];
8117 	iy1 = yb1[w]; iy2 = yb2[w];
8118 	oz1 = z1; oz2 = z2;
8119 
8120 	if ((bad&3) == 3)
8121 	{
8122 		clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),0L);
8123 		return(bad);
8124 	}
8125 
8126 	if ((bad&12) == 12)
8127 	{
8128 		clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
8129 		return(bad);
8130 	}
8131 
8132 	if (bad&3)
8133 	{
8134 			//inty = intz / (globaluclip>>16)
8135 		t = divscale30(oz1-s1,s2-s1+oz1-oz2);
8136 		inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
8137 		intz = oz1 + mulscale30(oz2-oz1,t);
8138 		xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty);
8139 
8140 		//t = divscale30((x1<<4)-xcross*yb1[w],xcross*(yb2[w]-yb1[w])-((x2-x1)<<4));
8141 		//inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
8142 		//intz = z1 + mulscale30(z2-z1,t);
8143 
8144 		if ((bad&3) == 2)
8145 		{
8146 			if (xb1[w] <= xcross) { z2 = intz; iy2 = inty; ix2 = xcross; }
8147 			clearbufbyte(&mostbuf[xcross+1],(xb2[w]-xcross)*sizeof(mostbuf[0]),0L);
8148 		}
8149 		else
8150 		{
8151 			if (xcross <= xb2[w]) { z1 = intz; iy1 = inty; ix1 = xcross; }
8152 			clearbufbyte(&mostbuf[xb1[w]],(xcross-xb1[w]+1)*sizeof(mostbuf[0]),0L);
8153 		}
8154 	}
8155 
8156 	if (bad&12)
8157 	{
8158 			//inty = intz / (globaldclip>>16)
8159 		t = divscale30(oz1-s3,s4-s3+oz1-oz2);
8160 		inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
8161 		intz = oz1 + mulscale30(oz2-oz1,t);
8162 		xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty);
8163 
8164 		//t = divscale30((x1<<4)-xcross*yb1[w],xcross*(yb2[w]-yb1[w])-((x2-x1)<<4));
8165 		//inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
8166 		//intz = z1 + mulscale30(z2-z1,t);
8167 
8168 		if ((bad&12) == 8)
8169 		{
8170 			if (xb1[w] <= xcross) { z2 = intz; iy2 = inty; ix2 = xcross; }
8171 			clearbufbyte(&mostbuf[xcross+1],(xb2[w]-xcross)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
8172 		}
8173 		else
8174 		{
8175 			if (xcross <= xb2[w]) { z1 = intz; iy1 = inty; ix1 = xcross; }
8176 			clearbufbyte(&mostbuf[xb1[w]],(xcross-xb1[w]+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
8177 		}
8178 	}
8179 
8180 	y = (scale(z1,xdimenscale,iy1)<<4);
8181 	yinc = ((scale(z2,xdimenscale,iy2)<<4)-y) / (ix2-ix1+1);
8182 	qinterpolatedown16short((long)&mostbuf[ix1],ix2-ix1+1,y+(globalhoriz<<16),yinc);
8183 
8184 	if (mostbuf[ix1] < 0) mostbuf[ix1] = 0;
8185 	if (mostbuf[ix1] > ydimen) mostbuf[ix1] = ydimen;
8186 	if (mostbuf[ix2] < 0) mostbuf[ix2] = 0;
8187 	if (mostbuf[ix2] > ydimen) mostbuf[ix2] = ydimen;
8188 
8189 	return(bad);
8190 }
8191 
8192 #define BITSOFPRECISION 3  //Don't forget to change this in A.ASM also!
grouscan(long dax1,long dax2,long sectnum,char dastat)8193 grouscan (long dax1, long dax2, long sectnum, char dastat)
8194 {
8195 	long i, j, k, l, m, n, x, y, dx, dy, wx, wy, x1, y1, x2, y2, daz;
8196 	long daslope, dasqr;
8197 	long dashade, shoffs, shinc, m1, m2, *mptr1, *mptr2, *nptr1, *nptr2;
8198 	walltype *wal;
8199 	sectortype *sec;
8200 
8201 	sec = &sector[sectnum];
8202 
8203 	if (dastat == 0)
8204 	{
8205 		if (globalposz <= getceilzofslope(sectnum,globalposx,globalposy))
8206 			return;  //Back-face culling
8207 		globalorientation = sec->ceilingstat;
8208 		globalpicnum = sec->ceilingpicnum;
8209 		globalshade = sec->ceilingshade;
8210 		globalpal = sec->ceilingpal;
8211 		daslope = sec->ceilingheinum;
8212 		daz = sec->ceilingz;
8213 	}
8214 	else
8215 	{
8216 		if (globalposz >= getflorzofslope(sectnum,globalposx,globalposy))
8217 			return;  //Back-face culling
8218 		globalorientation = sec->floorstat;
8219 		globalpicnum = sec->floorpicnum;
8220 		globalshade = sec->floorshade;
8221 		globalpal = sec->floorpal;
8222 		daslope = sec->floorheinum;
8223 		daz = sec->floorz;
8224 	}
8225 
8226 	if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs(globalpicnum,sectnum);
8227 	setgotpic(globalpicnum);
8228 	if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) return;
8229 	if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
8230 
8231 	wal = &wall[sec->wallptr];
8232 	wx = wall[wal->point2].x - wal->x;
8233 	wy = wall[wal->point2].y - wal->y;
8234 	dasqr = krecipasm(nsqrtasm(wx*wx+wy*wy));
8235 	i = mulscale21(daslope,dasqr);
8236 	wx *= i; wy *= i;
8237 
8238 	globalx = -mulscale19(singlobalang,xdimenrecip);
8239 	globaly = mulscale19(cosglobalang,xdimenrecip);
8240 	globalx1 = (globalposx<<8);
8241 	globaly1 = -(globalposy<<8);
8242 	i = (dax1-halfxdimen)*xdimenrecip;
8243 	globalx2 = mulscale16(cosglobalang<<4,viewingrangerecip) - mulscale27(singlobalang,i);
8244 	globaly2 = mulscale16(singlobalang<<4,viewingrangerecip) + mulscale27(cosglobalang,i);
8245 	globalzd = (xdimscale<<9);
8246 	globalzx = -dmulscale17(wx,globaly2,-wy,globalx2) + mulscale10(1-globalhoriz,globalzd);
8247 	globalz = -dmulscale25(wx,globaly,-wy,globalx);
8248 
8249 	if (globalorientation&64)  //Relative alignment
8250 	{
8251 		dx = mulscale14(wall[wal->point2].x-wal->x,dasqr);
8252 		dy = mulscale14(wall[wal->point2].y-wal->y,dasqr);
8253 
8254 		i = nsqrtasm(daslope*daslope+16777216);
8255 
8256 		x = globalx; y = globaly;
8257 		globalx = dmulscale16(x,dx,y,dy);
8258 		globaly = mulscale12(dmulscale16(-y,dx,x,dy),i);
8259 
8260 		x = ((wal->x-globalposx)<<8); y = ((wal->y-globalposy)<<8);
8261 		globalx1 = dmulscale16(-x,dx,-y,dy);
8262 		globaly1 = mulscale12(dmulscale16(-y,dx,x,dy),i);
8263 
8264 		x = globalx2; y = globaly2;
8265 		globalx2 = dmulscale16(x,dx,y,dy);
8266 		globaly2 = mulscale12(dmulscale16(-y,dx,x,dy),i);
8267 	}
8268 	if (globalorientation&0x4)
8269 	{
8270 		i = globalx; globalx = -globaly; globaly = -i;
8271 		i = globalx1; globalx1 = globaly1; globaly1 = i;
8272 		i = globalx2; globalx2 = -globaly2; globaly2 = -i;
8273 	}
8274 	if (globalorientation&0x10) { globalx1 = -globalx1, globalx2 = -globalx2, globalx = -globalx; }
8275 	if (globalorientation&0x20) { globaly1 = -globaly1, globaly2 = -globaly2, globaly = -globaly; }
8276 
8277 	daz = dmulscale9(wx,globalposy-wal->y,-wy,globalposx-wal->x) + ((daz-globalposz)<<8);
8278 	globalx2 = mulscale20(globalx2,daz); globalx = mulscale28(globalx,daz);
8279 	globaly2 = mulscale20(globaly2,-daz); globaly = mulscale28(globaly,-daz);
8280 
8281 	i = 8-(picsiz[globalpicnum]&15); j = 8-(picsiz[globalpicnum]>>4);
8282 	if (globalorientation&8) { i++; j++; }
8283 	globalx1 <<= (i+12); globalx2 <<= i; globalx <<= i;
8284 	globaly1 <<= (j+12); globaly2 <<= j; globaly <<= j;
8285 
8286 	if (dastat == 0)
8287 	{
8288 		globalx1 += (((long)sec->ceilingxpanning)<<24);
8289 		globaly1 += (((long)sec->ceilingypanning)<<24);
8290 	}
8291 	else
8292 	{
8293 		globalx1 += (((long)sec->floorxpanning)<<24);
8294 		globaly1 += (((long)sec->floorypanning)<<24);
8295 	}
8296 
8297 	asm1 = -(globalzd>>(16-BITSOFPRECISION));
8298 
8299 	globvis = globalvisibility;
8300 	if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
8301 	globvis = mulscale13(globvis,daz);
8302 	globvis = mulscale16(globvis,xdimscale);
8303 	j = FP_OFF(palookup[globalpal]);
8304 
8305 	setupslopevlin(((long)(picsiz[globalpicnum]&15))+(((long)(picsiz[globalpicnum]>>4))<<8),waloff[globalpicnum],-ylookup[1]);
8306 
8307 	l = (globalzd>>16);
8308 
8309 	shinc = mulscale16(globalz,xdimenscale);
8310 	if (shinc > 0) shoffs = (4<<15); else shoffs = ((2044-ydimen)<<15);
8311 	if (dastat == 0) y1 = umost[dax1]; else y1 = max(umost[dax1],dplc[dax1]);
8312 	m1 = mulscale16(y1,globalzd) + (globalzx>>6);
8313 		//Avoid visibility overflow by crossing horizon
8314 	if (globalzd > 0) m1 += (globalzd>>16); else m1 -= (globalzd>>16);
8315 	m2 = m1+l;
8316 	mptr1 = (long *)&slopalookup[y1+(shoffs>>15)]; mptr2 = mptr1+1;
8317 
8318 	for(x=dax1;x<=dax2;x++)
8319 	{
8320 		if (dastat == 0) { y1 = umost[x]; y2 = min(dmost[x],uplc[x])-1; }
8321 						else { y1 = max(umost[x],dplc[x]); y2 = dmost[x]-1; }
8322 		if (y1 <= y2)
8323 		{
8324 			nptr1 = (long *)&slopalookup[y1+(shoffs>>15)];
8325 			nptr2 = (long *)&slopalookup[y2+(shoffs>>15)];
8326 			while (nptr1 <= mptr1)
8327 			{
8328 				*mptr1-- = j + (getpalookup((long)mulscale24(krecipasm(m1),globvis),globalshade)<<8);
8329 				m1 -= l;
8330 			}
8331 			while (nptr2 >= mptr2)
8332 			{
8333 				*mptr2++ = j + (getpalookup((long)mulscale24(krecipasm(m2),globvis),globalshade)<<8);
8334 				m2 += l;
8335 			}
8336 
8337 			globalx3 = (globalx2>>10);
8338 			globaly3 = (globaly2>>10);
8339 			asm3 = mulscale16(y2,globalzd) + (globalzx>>6);
8340 			slopevlin(ylookup[y2]+x+frameoffset,krecipasm(asm3>>3),(long)nptr2,y2-y1+1,globalx1,globaly1);
8341 
8342 			if ((x&15) == 0) faketimerhandler();
8343 		}
8344 		globalx2 += globalx;
8345 		globaly2 += globaly;
8346 		globalzx += globalz;
8347 		shoffs += shinc;
8348 	}
8349 }
8350 
getpalookup(long davis,long dashade)8351 getpalookup(long davis, long dashade)
8352 {
8353 	return(min(max(dashade+(davis>>8),0),numpalookups-1));
8354 }
8355 
parascan(long dax1,long dax2,long sectnum,char dastat,long bunch)8356 parascan (long dax1, long dax2, long sectnum, char dastat, long bunch)
8357 {
8358 	sectortype *sec;
8359 	long i, j, k, l, m, n, x, y, z, wallnum, nextsectnum, globalhorizbak;
8360 	short *topptr, *botptr;
8361 
8362 	sectnum = thesector[bunchfirst[bunch]]; sec = &sector[sectnum];
8363 
8364 	globalhorizbak = globalhoriz;
8365 	if (parallaxyscale != 65536)
8366 		globalhoriz = mulscale16(globalhoriz-(ydimen>>1),parallaxyscale) + (ydimen>>1);
8367 	globvis = globalpisibility;
8368 	//globalorientation = 0L;
8369 	if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
8370 
8371 	if (dastat == 0)
8372 	{
8373 		globalpal = sec->ceilingpal;
8374 		globalpicnum = sec->ceilingpicnum;
8375 		globalshade = (long)sec->ceilingshade;
8376 		globalxpanning = (long)sec->ceilingxpanning;
8377 		globalypanning = (long)sec->ceilingypanning;
8378 		topptr = umost;
8379 		botptr = uplc;
8380 	}
8381 	else
8382 	{
8383 		globalpal = sec->floorpal;
8384 		globalpicnum = sec->floorpicnum;
8385 		globalshade = (long)sec->floorshade;
8386 		globalxpanning = (long)sec->floorxpanning;
8387 		globalypanning = (long)sec->floorypanning;
8388 		topptr = dplc;
8389 		botptr = dmost;
8390 	}
8391 
8392 	if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
8393 	if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)sectnum);
8394 	globalshiftval = (picsiz[globalpicnum]>>4);
8395 	if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
8396 	globalshiftval = 32-globalshiftval;
8397 	globalzd = (((tilesizy[globalpicnum]>>1)+parallaxyoffs)<<globalshiftval)+(globalypanning<<24);
8398 	globalyscale = (8<<(globalshiftval-19));
8399 	//if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
8400 
8401 	k = 11 - (picsiz[globalpicnum]&15) - pskybits;
8402 	x = -1;
8403 
8404 	for(z=bunchfirst[bunch];z>=0;z=p2[z])
8405 	{
8406 		wallnum = thewall[z]; nextsectnum = wall[wallnum].nextsector;
8407 
8408 		if (dastat == 0) j = sector[nextsectnum].ceilingstat;
8409 						else j = sector[nextsectnum].floorstat;
8410 
8411 		if ((nextsectnum < 0) || (wall[wallnum].cstat&32) || ((j&1) == 0))
8412 		{
8413 			if (x == -1) x = xb1[z];
8414 
8415 			if (parallaxtype == 0)
8416 			{
8417 				n = mulscale16(xdimenrecip,viewingrange);
8418 				for(j=xb1[z];j<=xb2[z];j++)
8419 					lplc[j] = (((mulscale23(j-halfxdimen,n)+globalang)&2047)>>k);
8420 			}
8421 			else
8422 			{
8423 				for(j=xb1[z];j<=xb2[z];j++)
8424 					lplc[j] = ((((long)radarang2[j]+globalang)&2047)>>k);
8425 			}
8426 			if (parallaxtype == 2)
8427 			{
8428 				n = mulscale16(xdimscale,viewingrange);
8429 				for(j=xb1[z];j<=xb2[z];j++)
8430 					swplc[j] = mulscale14(sintable[((long)radarang2[j]+512)&2047],n);
8431 			}
8432 			else
8433 				clearbuf((long)(&swplc[xb1[z]]),xb2[z]-xb1[z]+1,mulscale16(xdimscale,viewingrange));
8434 		}
8435 		else if (x >= 0)
8436 		{
8437 			l = globalpicnum; m = (picsiz[globalpicnum]&15);
8438 			globalpicnum = l+pskyoff[lplc[x]>>m];
8439 
8440 			if (((lplc[x]^lplc[xb1[z]-1])>>m) == 0)
8441 				wallscan(x,xb1[z]-1,topptr,botptr,swplc,lplc);
8442 			else
8443 			{
8444 				j = x;
8445 				while (x < xb1[z])
8446 				{
8447 					n = l+pskyoff[lplc[x]>>m];
8448 					if (n != globalpicnum)
8449 					{
8450 						wallscan(j,x-1,topptr,botptr,swplc,lplc);
8451 						j = x;
8452 						globalpicnum = n;
8453 					}
8454 					x++;
8455 				}
8456 				if (j < x)
8457 					wallscan(j,x-1,topptr,botptr,swplc,lplc);
8458 			}
8459 
8460 			globalpicnum = l;
8461 			x = -1;
8462 		}
8463 	}
8464 
8465 	if (x >= 0)
8466 	{
8467 		l = globalpicnum; m = (picsiz[globalpicnum]&15);
8468 		globalpicnum = l+pskyoff[lplc[x]>>m];
8469 
8470 		if (((lplc[x]^lplc[xb2[bunchlast[bunch]]])>>m) == 0)
8471 			wallscan(x,xb2[bunchlast[bunch]],topptr,botptr,swplc,lplc);
8472 		else
8473 		{
8474 			j = x;
8475 			while (x <= xb2[bunchlast[bunch]])
8476 			{
8477 				n = l+pskyoff[lplc[x]>>m];
8478 				if (n != globalpicnum)
8479 				{
8480 					wallscan(j,x-1,topptr,botptr,swplc,lplc);
8481 					j = x;
8482 					globalpicnum = n;
8483 				}
8484 				x++;
8485 			}
8486 			if (j <= x)
8487 				wallscan(j,x,topptr,botptr,swplc,lplc);
8488 		}
8489 		globalpicnum = l;
8490 	}
8491 	globalhoriz = globalhorizbak;
8492 }
8493 
stereohandler()8494 interrupt stereohandler()
8495 {
8496 		//VR flag
8497 	if (kinp(0x3c2)&128)
8498 	{
8499 		koutpw(0x3d4,((long)overtbits<<8)+0x11);
8500 		koutp(0x3d5,overtbits+16);
8501 		laststereoint = 0;
8502 	}
8503 	if (laststereoint == 1)
8504 	{
8505 		visualpage ^= 1;
8506 		setvisualpage(visualpage|0x80000000);  //0x80000000 to ignore qlimitrate
8507 	}
8508 	laststereoint++;
8509 	koutp(0x70,0xc); kinp(0x71);
8510 	koutp(0xa0,0x20);
8511 	koutp(0x20,0x20);
8512 }
8513 
initstereo()8514 initstereo()
8515 {
8516 	long i, dist, blackdist, whitedist, t1, t2, numlines;
8517 	char c1, c2;
8518 
8519 	if ((vidoption != 1) || (numpages < 2)) return;
8520 
8521 	activepage = (visualpage & ~1)+2;
8522 	if (activepage >= numpages-1) activepage = 0;
8523 
8524 	blackdist = 0x7fffffff; whitedist = 0x80000000;
8525 	koutp(0x3c7,0);
8526 	for(i=0;i<256;i++)
8527 	{
8528 		dist = (kinp(0x3c9)&255)+(kinp(0x3c9)&255)+(kinp(0x3c9)&255);
8529 		if (dist < blackdist) { blackdist = dist; blackband = i; }
8530 		if (dist > whitedist) { whitedist = dist; whiteband = i; }
8531 	}
8532 	blackband += (blackband<<8); blackband += (blackband<<16);
8533 	whiteband += (whiteband<<8); whiteband += (whiteband<<16);
8534 
8535 	if ((xdim == 320) && (ydim == 200))
8536 	{
8537 			//80 hz
8538 		o3c2 = kinp(0x3cc);
8539 		koutp(0x3c2,(o3c2&0xf3)+4);
8540 	}
8541 
8542 		//Init RTC
8543 	_disable();
8544 	oldstereohandler = _dos_getvect(0x70); _dos_setvect(0x70,stereohandler);
8545 	koutp(0x70,0xa); ortca = kinp(0x71); koutp(0x71,0x28); //+8 = 256hz
8546 	koutp(0x70,0xb); ortcb = kinp(0x71); koutp(0x71,0x42);
8547 	oa1 = kinp(0xa1); koutp(0xa1,oa1&~1);
8548 	_enable();
8549 
8550 		//Init VR flag
8551 	koutp(0x3d4,0x11);
8552 	overtbits = kinp(0x3d5) & ~(16+32);
8553 	koutp(0x3d5,overtbits);
8554 	koutp(0x3d5,overtbits+16);
8555 
8556 	stereomode = 1;
8557 }
8558 
uninitstereo()8559 uninitstereo()
8560 {
8561 	long i;
8562 
8563 	if ((xdim == 320) && (ydim == 200))
8564 	{
8565 			//back to 70 hz
8566 		koutp(0x3c2,o3c2);
8567 	}
8568 
8569 		//Uninit VR flag
8570 	koutpw(0x3d4,(((long)overtbits+32)<<8)+0x11);
8571 
8572 		//Uninit RTC
8573 	_disable();
8574 	koutp(0xa1,(kinp(0xa1)&~1)|(oa1&1));
8575 	koutp(0x70,0xa); koutp(0x71,ortca);
8576 	koutp(0x70,0xb); koutp(0x71,ortcb);
8577 	_dos_setvect(0x70, oldstereohandler);
8578 	_enable();
8579 
8580 	stereomode = 0;
8581 	ostereopixelwidth = -1;
8582 	setview(windowx1,windowy1,windowx2,windowy2);
8583 	for(i=0;i<numpages;i++)
8584 	{
8585 		setactivepage(i);
8586 		clearbuf(ylookup[ydim-1]+frameplace,xdim>>2,blackband);
8587 	}
8588 	setactivepage(activepage);
8589 }
8590 
stereonextpage()8591 stereonextpage()
8592 {
8593 	koutpw(0x70,0x420b);
8594 	if ((activepage&1) == 0)
8595 	{
8596 		clearbuf(ylookup[ydim-1]+frameplace,xdim>>4,whiteband);
8597 		clearbuf(ylookup[ydim-1]+frameplace+(xdim>>2),(xdim>>2)-(xdim>>4),blackband);
8598 		activepage++;
8599 		setactivepage(activepage);
8600 		return;
8601 	}
8602 	clearbuf(ylookup[ydim-1]+frameplace,(xdim>>2)-(xdim>>4),whiteband);
8603 	clearbuf(ylookup[ydim-1]+frameplace+xdim-(xdim>>2),xdim>>4,blackband);
8604 	if (activepage < numpages-1) activepage++; else activepage = 0;
8605 	setactivepage(activepage);
8606 	if (visualpage < numpages-2) visualpage += 2;
8607 									else visualpage += 2-numpages;
8608 }
8609 
loopnumofsector(short sectnum,short wallnum)8610 loopnumofsector(short sectnum, short wallnum)
8611 {
8612 	long i, numloops, startwall, endwall;
8613 
8614 	numloops = 0;
8615 	startwall = sector[sectnum].wallptr;
8616 	endwall = startwall + sector[sectnum].wallnum;
8617 	for(i=startwall;i<endwall;i++)
8618 	{
8619 		if (i == wallnum) return(numloops);
8620 		if (wall[i].point2 < i) numloops++;
8621 	}
8622 	return(-1);
8623 }
8624 
setfirstwall(short sectnum,short newfirstwall)8625 setfirstwall(short sectnum, short newfirstwall)
8626 {
8627 	long i, j, k, numwallsofloop;
8628 	long startwall, endwall, danumwalls, dagoalloop;
8629 
8630 	startwall = sector[sectnum].wallptr;
8631 	danumwalls = sector[sectnum].wallnum;
8632 	endwall = startwall+danumwalls;
8633 	if ((newfirstwall < startwall) || (newfirstwall >= startwall+danumwalls)) return;
8634 	for(i=0;i<danumwalls;i++)
8635 		memcpy(&wall[i+numwalls],&wall[i+startwall],sizeof(walltype));
8636 
8637 	numwallsofloop = 0;
8638 	i = newfirstwall;
8639 	do
8640 	{
8641 		numwallsofloop++;
8642 		i = wall[i].point2;
8643 	} while (i != newfirstwall);
8644 
8645 		//Put correct loop at beginning
8646 	dagoalloop = loopnumofsector(sectnum,newfirstwall);
8647 	if (dagoalloop > 0)
8648 	{
8649 		j = 0;
8650 		while (loopnumofsector(sectnum,j+startwall) != dagoalloop) j++;
8651 		for(i=0;i<danumwalls;i++)
8652 		{
8653 			k = i+j; if (k >= danumwalls) k -= danumwalls;
8654 			memcpy(&wall[startwall+i],&wall[numwalls+k],sizeof(walltype));
8655 
8656 			wall[startwall+i].point2 += danumwalls-startwall-j;
8657 			if (wall[startwall+i].point2 >= danumwalls)
8658 				wall[startwall+i].point2 -= danumwalls;
8659 			wall[startwall+i].point2 += startwall;
8660 		}
8661 		newfirstwall += danumwalls-j;
8662 		if (newfirstwall >= startwall+danumwalls) newfirstwall -= danumwalls;
8663 	}
8664 
8665 	for(i=0;i<numwallsofloop;i++)
8666 		memcpy(&wall[i+numwalls],&wall[i+startwall],sizeof(walltype));
8667 	for(i=0;i<numwallsofloop;i++)
8668 	{
8669 		k = i+newfirstwall-startwall;
8670 		if (k >= numwallsofloop) k -= numwallsofloop;
8671 		memcpy(&wall[startwall+i],&wall[numwalls+k],sizeof(walltype));
8672 
8673 		wall[startwall+i].point2 += numwallsofloop-newfirstwall;
8674 		if (wall[startwall+i].point2 >= numwallsofloop)
8675 			wall[startwall+i].point2 -= numwallsofloop;
8676 		wall[startwall+i].point2 += startwall;
8677 	}
8678 
8679 	for(i=startwall;i<endwall;i++)
8680 		if (wall[i].nextwall >= 0) wall[wall[i].nextwall].nextwall = i;
8681 }
8682