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 = §or[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 = §or[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 = §or[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 = §or[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,§or[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,§or[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 = §or[sectnum];
2945 nsec = §or[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 = §or[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 = §or[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 = §or[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 = §or[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 = §or[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 = §or[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 = §or[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 = §or[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 = §or[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=§or[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 = §or[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 = §or[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 = §or[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