blob: b3b807d7062407d39b154ff1780507be4fb80cdb [file] [log] [blame]
Franklin Weia855d622017-01-21 15:18:31 -05001/*
2 * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
3 * Ken Silverman's official web site: "http://www.advsys.net/ken"
4 * See the included license file "BUILDLIC.TXT" for license info.
5 * This file has been modified from Ken Silverman's original release
6 */
7
8/* SUPERBUILD define is in engine.h ... */
9
10#define ENGINE
11
12#include "platform.h"
13
14#include "build.h"
15
16#include "engine.h"
17#include "tiles.h"
18
19int32_t stereowidth = 23040, stereopixelwidth = 28, ostereopixelwidth = -1;
20int32_t stereomode = 0, visualpage, activepage, whiteband, blackband;
21uint8_t oa1, o3c2, ortca, ortcb, overtbits, laststereoint;
22
23#include "display.h"
24
25#define MAXCLIPNUM 512
26#define MAXPERMS 512
27#define MAXTILEFILES 256
28#define MAXYSAVES ((MAXXDIM*MAXSPRITES)>>7)
29#define MAXNODESPERLINE 42 /* Warning: This depends on MAXYSAVES & MAXYDIM! */
30#define MAXWALLSB 2048
31#define MAXCLIPDIST 1024
32
33/* used to be static. --ryan. */
34uint8_t moustat = 0;
35
36int32_t transarea = 0, beforedrawrooms = 1;
37
38/* used to be static. --ryan. */
39int32_t oxdimen = -1, oviewingrange = -1, oxyaspect = -1;
40
41/* used to be static. --ryan. */
42int32_t curbrightness = 0;
43
44/* Textured Map variables */
45static uint8_t globalpolytype;
46static short *dotp1[MAXYDIM], *dotp2[MAXYDIM];
47
48static char tempbuf[MAXWALLS];
49
50int32_t ebpbak, espbak;
51int32_t slopalookup[16384];
52
53/*
54 * !!! used to be static. If we ever put the original setgamemode() back, this
55 * !!! can be made static again. --ryan.
56 */
57uint8_t permanentlock = 255;
58int32_t mapversion;
59
60uint8_t picsiz[MAXTILES], tilefilenum[MAXTILES];
61int32_t lastageclock;
62int32_t tilefileoffs[MAXTILES];
63
64int32_t artsize = 0, cachesize = 0;
65
66static short radarang[1280], radarang2[MAXXDIM+1];
67static uint16_t sqrtable[4096], shlookup[4096+256];
68uint8_t pow2char[8] = {1,2,4,8,16,32,64,-128};
69int32_t pow2long[32] =
70{
71 1L,2L,4L,8L,
72 16L,32L,64L,128L,
73 256L,512L,1024L,2048L,
74 4096L,8192L,16384L,32768L,
75 65536L,131072L,262144L,524288L,
76 1048576L,2097152L,4194304L,8388608L,
77 16777216L,33554432L,67108864L,134217728L,
78 268435456L,536870912L,1073741824L,2147483647L,
79};
80int32_t reciptable[2048], fpuasm;
81
82char kensmessage[128];
83
84uint8_t britable[16][64];
85uint8_t textfont[1024], smalltextfont[1024];
86
87
88
89
90
91
92
93
94
95enum vector_index_e {VEC_X=0,VEC_Y=1};
96enum screenSpaceCoo_index_e {VEC_COL=0,VEC_DIST=1};
97typedef int32_t vector_t[2];
98typedef int32_t coo2D_t[2];
99// This is the structure emitted for each wall that is potentially visible.
100// A stack of those is populated when the sectors are scanned.
101typedef struct pvWall_s{
102 vector_t cameraSpaceCoo[2]; //Camera space coordinates of the wall endpoints. Access with vector_index_e.
103 int16_t sectorId; //The index of the sector this wall belongs to in the map database.
104 int16_t worldWallId; //The index of the wall in the map database.
105 coo2D_t screenSpaceCoo[2]; //Screen space coordinate of the wall endpoints. Access with screenSpaceCoo_index_e.
106} pvWall_t;
107
108// Potentially Visible walls are stored in this stack.
109pvWall_t pvWalls[MAXWALLSB];
110
111
112
113
114//xb1 and xb2 seems to be storing the column of the wall endpoint
115//yb1 and yb2 store the Y distance from the camera.
116
117//static int32_t xb1[MAXWALLSB], yb1[MAXWALLSB], xb2[MAXWALLSB], yb2[MAXWALLSB];
118
119/*
120//rx1,rx2,ry1,ry2 stores the cameraspace wall endpoints coordinates.
121static int32_t rx1[MAXWALLSB], ry1[MAXWALLSB], rx2[MAXWALLSB], ry2[MAXWALLSB];
122static short thesector[MAXWALLSB], thewall[MAXWALLSB];
123*/
124
125// bunchWallsList contains the list of walls in a bunch.
126static short bunchWallsList[MAXWALLSB];
127
128static short bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB];
129
130
131
132
133
134
135
136static short smost[MAXYSAVES], smostcnt;
137static short smoststart[MAXWALLSB];
138static uint8_t smostwalltype[MAXWALLSB];
139static int32_t smostwall[MAXWALLSB], smostwallcnt = -1L;
140
141static short maskwall[MAXWALLSB], maskwallcnt;
142static int32_t spritesx[MAXSPRITESONSCREEN];
143static int32_t spritesy[MAXSPRITESONSCREEN+1];
144static int32_t spritesz[MAXSPRITESONSCREEN];
145static spritetype *tspriteptr[MAXSPRITESONSCREEN];
146
147//FCS: (up-most pixel on column x that can still be drawn to)
148short umost[MAXXDIM+1];
149
150//FCS: (down-most pixel +1 on column x that can still be drawn to)
151short dmost[MAXXDIM+1];
152
153int16_t bakumost[MAXXDIM+1], bakdmost[MAXXDIM+1];
154short uplc[MAXXDIM+1], dplc[MAXXDIM+1];
155static int16_t uwall[MAXXDIM+1], dwall[MAXXDIM+1];
156static int32_t swplc[MAXXDIM+1], lplc[MAXXDIM+1];
157static int32_t swall[MAXXDIM+1], lwall[MAXXDIM+4];
158int32_t xdimen = -1, xdimenrecip, halfxdimen, xdimenscale, xdimscale;
159int32_t wx1, wy1, wx2, wy2, ydimen;
160int32_t viewoffset;
161
162static int32_t rxi[8], ryi[8], rzi[8], rxi2[8], ryi2[8], rzi2[8];
163static int32_t xsi[8], ysi[8];
164
165/* used to be static. --ryan. */
166int32_t *horizlookup=0, *horizlookup2=0, horizycent;
167
168int32_t globalposx, globalposy, globalposz, globalhoriz;
169int16_t globalang, globalcursectnum;
170int32_t globalpal, cosglobalang, singlobalang;
171int32_t cosviewingrangeglobalang, sinviewingrangeglobalang;
172uint8_t *globalpalwritten;
173int32_t globaluclip, globaldclip, globvis = 0;
174int32_t globalvisibility, globalhisibility, globalpisibility, globalcisibility;
175uint8_t globparaceilclip, globparaflorclip;
176
177int32_t xyaspect, viewingrangerecip;
178
179int32_t asm1, asm4;
180intptr_t asm2, asm3;
181
182
183int32_t vplce[4], vince[4];
184intptr_t bufplce[4];
185
186uint8_t* palookupoffse[4];
187
188uint8_t globalxshift, globalyshift;
189int32_t globalxpanning, globalypanning, globalshade;
190int16_t globalpicnum, globalshiftval;
191int32_t globalzd, globalyscale, globalorientation;
192uint8_t* globalbufplc;
193int32_t globalx1, globaly1, globalx2, globaly2, globalx3, globaly3, globalzx;
194int32_t globalx, globaly, globalz;
195
196//FCS:
197// Those two variables are using during portal flooding:
198// sectorBorder is the stack and sectorbordercnt is the stack counter.
199// There is no really point to have this on the heap. That would have been better on the stack.
200
201//static short sectorborder[256], sectorbordercnt;
202//FCS: Moved this on the stack
203
204static uint8_t tablesloaded = 0;
205int32_t pageoffset, ydim16, qsetmode = 0;
206int32_t startposx, startposy, startposz;
207int16_t startang, startsectnum;
208int16_t pointhighlight, linehighlight, highlightcnt;
209static int32_t lastx[MAXYDIM];
210uint8_t paletteloaded = 0;
211
212#define FASTPALGRIDSIZ 8
213static int32_t rdist[129], gdist[129], bdist[129];
214static uint8_t colhere[((FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2))>>3];
215static uint8_t colhead[(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)];
216static int32_t colnext[256];
217static uint8_t coldist[8] = {0,1,2,3,4,3,2,1};
218static int32_t colscan[27];
219
220static int16_t clipnum, hitwalls[4];
221int32_t hitscangoalx = (1<<29)-1, hitscangoaly = (1<<29)-1;
222
223typedef struct {
224 int32_t x1, y1, x2, y2;
225} linetype;
226static linetype clipit[MAXCLIPNUM];
227static short clipsectorlist[MAXCLIPNUM], clipsectnum;
228static short clipobjectval[MAXCLIPNUM];
229
230typedef struct
231{
232 int32_t sx, sy, z;
233 short a, picnum;
234 int8_t dashade;
235 uint8_t dapalnum, dastat, pagesleft;
236 int32_t cx1, cy1, cx2, cy2;
237} permfifotype;
238static permfifotype permfifo[MAXPERMS];
239static int32_t permhead = 0, permtail = 0;
240
241//FCS: Num walls to potentially render.
242short numscans ;
243
244short numbunches;
245
246//FCS: Number of colums to draw. ALWAYS set to the screen dimension width.
247short numhits;
248
249short editstatus = 0;
250short searchit;
251int32_t searchx = -1, searchy; /* search input */
252short searchsector, searchwall, searchstat; /* search output */
253
254int32_t numtilefiles, artfil = -1, artfilnum, artfilplc;
255
256static uint8_t inpreparemirror = 0;
257static int32_t mirrorsx1, mirrorsy1, mirrorsx2, mirrorsy2;
258
259int32_t totalclocklock;
260
261uint16_t mapCRC;
262
263#include "draw.h"
264
265static __inline int32_t nsqrtasm(uint32_t param)
266{
267 uint16_t *shlookup_a = (uint16_t*)shlookup;
268 uint16_t *sqrtable_a = (uint16_t*)sqrtable;
269 uint16_t cx;
270
271 if (param & 0xff000000)
272 cx = shlookup_a[(param>>24)+4096];
273 else
274 cx = shlookup_a[param>>12];
275
276 param = param >> (cx&0xff);
277 param = ((param&0xffff0000)|sqrtable_a[param]);
278 param = param >> ((cx&0xff00)>>8);
279
280 return param;
281}
282
283static __inline int32_t krecipasm(int32_t i)
284{ // Ken did this
285 float f = (float)i;
286 i = *(int32_t *)&f;
287 return((reciptable[(i>>12)&2047]>>(((i-0x3f800000)>>23)&31))^(i>>31));
288}
289
290
291
292static __inline int32_t getclipmask(int32_t a, int32_t b, int32_t c, int32_t d)
293{ // Ken did this
294 d = ((a<0)*8) + ((b<0)*4) + ((c<0)*2) + (d<0);
295 return(((d<<4)^0xf0)|d);
296}
297
298//
299// krecip
300//
301int32_t krecip(int32_t num)
302{
303 return(krecipasm(num));
304}
305
306uint16_t _swap16(uint16_t D)
307{
308 return((D<<8)|(D>>8));
309}
310
311unsigned int _swap32(unsigned int D)
312{
313 return((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24));
314}
315
316/*
317 FCS:
318 Scan through sectors using portals (a portal is wall with a nextsector attribute >= 0).
319 Flood is prevented if a portal does not face the POV.
320 */
321static void scansector (short sectnum)
322{
323 walltype *wal, *wal2;
324 spritetype *spr;
325 int32_t xs, ys, x1, y1, x2, y2, xp1, yp1, xp2=0, yp2=0, tempint;
326 short z, zz, startwall, endwall, numscansbefore, scanfirst, bunchfrst;
327 short nextsectnum;
328
329 //The stack storing sectors to visit.
330 short sectorsToVisit[256], numSectorsToVisit;
331
332
333 if (sectnum < 0)
334 return;
335
336 if (automapping)
337 show2dsector[sectnum>>3] |= pow2char[sectnum&7];
338
339 sectorsToVisit[0] = sectnum;
340 numSectorsToVisit = 1;
341 do
342 {
343 sectnum = sectorsToVisit[--numSectorsToVisit];
344
345 //Add every script in the current sector as potentially visible.
346 for(z=headspritesect[sectnum]; z>=0; z=nextspritesect[z])
347 {
348 spr = &sprite[z];
349 if ((((spr->cstat&0x8000) == 0) || (showinvisibility)) &&
350 (spr->xrepeat > 0) && (spr->yrepeat > 0) &&
351 (spritesortcnt < MAXSPRITESONSCREEN))
352 {
353 xs = spr->x-globalposx;
354 ys = spr->y-globalposy;
355 if ((spr->cstat&48) || (xs*cosglobalang+ys*singlobalang > 0))
356 {
357 copybufbyte(spr,&tsprite[spritesortcnt],sizeof(spritetype));
358 tsprite[spritesortcnt++].owner = z;
359 }
360 }
361 }
362
363 //Mark the current sector bit as "visited" in the bitvector
364 visitedSectors[sectnum>>3] |= pow2char[sectnum&7];
365
366 bunchfrst = numbunches;
367 numscansbefore = numscans;
368
369 startwall = sector[sectnum].wallptr;
370 endwall = startwall + sector[sectnum].wallnum;
371 scanfirst = numscans;
372 for(z=startwall,wal=&wall[z]; z<endwall; z++,wal++)
373 {
374 nextsectnum = wal->nextsector;
375
376 wal2 = &wall[wal->point2];
377
378 // In camera space the center is the player.
379 // Tranform the 2 Wall endpoints (x,y) from worldspace to camera space.
380 // After that we have two vectors starting from the camera and going to the endpoints (x1,y1) and (x2,y2).
381 x1 = wal->x-globalposx;
382 y1 = wal->y-globalposy;
383
384 x2 = wal2->x-globalposx;
385 y2 = wal2->y-globalposy;
386
387 // If this is a portal...
388 if ((nextsectnum >= 0) && ((wal->cstat&32) == 0))
389 //If this portal has not been visited yet.
390 if ((visitedSectors[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0)
391 {
392 //Cross product -> Z component
393 tempint = x1*y2-x2*y1;
394
395 // Using cross product, determine if the portal is facing us or not.
396 // If it is: Add it to the stack and bump the stack counter.
397 // This line is equivalent to tempint < 0x40000
398 if (((uint32_t)tempint+262144) < 524288) // ??? What is this test ?? How acute the angle is ?
399 {
400 //(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1) is the squared length of the wall
401 // ??? What is this test ?? How acute the angle is ?
402 if (mulscale5(tempint,tempint) <= (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
403 sectorsToVisit[numSectorsToVisit++] = nextsectnum;
404 }
405 }
406
407 // Rotate the wall endpoints vectors according to the player orientation.
408 // This is a regular rotation matrix using [29.3] fixed point.
409 if ((z == startwall) || (wall[z-1].point2 != z))
410 {
411 //If this is the first endpoint of the bunch, rotate: This is a standard cos sin 2D rotation matrix projection
412 xp1 = dmulscale6(y1,cosglobalang,-x1,singlobalang);
413 yp1 = dmulscale6(x1,cosviewingrangeglobalang,y1,sinviewingrangeglobalang);
414 }
415 else
416 {
417 //If this is NOT the first endpoint, Save the coordinate for next loop.
418 xp1 = xp2;
419 yp1 = yp2;
420 }
421
422 // Rotate: This is a standard cos sin 2D rotation matrix projection
423 xp2 = dmulscale6(y2,cosglobalang,-x2,singlobalang);
424 yp2 = dmulscale6(x2,cosviewingrangeglobalang,y2,sinviewingrangeglobalang);
425
426
427
428 // Equivalent of a near plane clipping ?
429 if ((yp1 < 256) && (yp2 < 256)) goto skipitaddwall;
430
431 /* If wall's NOT facing you */
432 if (dmulscale32(xp1,yp2,-xp2,yp1) >= 0) goto skipitaddwall;
433
434 // The wall is still not eligible for rendition: Let's do some more Frustrum culling !!
435 if (xp1 >= -yp1){
436
437 if ((xp1 > yp1) || (yp1 == 0))
438 goto skipitaddwall;
439
440 //Project the point onto screen and see in which column it belongs.
441 pvWalls[numscans].screenSpaceCoo[0][VEC_COL] = halfxdimen + scale(xp1,halfxdimen,yp1);
442 if (xp1 >= 0)
443 pvWalls[numscans].screenSpaceCoo[0][VEC_COL]++; /* Fix for SIGNED divide */
444
445 if (pvWalls[numscans].screenSpaceCoo[0][VEC_COL] >= xdimen)
446 pvWalls[numscans].screenSpaceCoo[0][VEC_COL] = xdimen-1;
447
448 pvWalls[numscans].screenSpaceCoo[0][VEC_DIST] = yp1;
449 }
450 else{
451
452 if (xp2 < -yp2)
453 goto skipitaddwall;
454
455 pvWalls[numscans].screenSpaceCoo[0][VEC_COL] = 0;
456 tempint = yp1-yp2+xp1-xp2;
457
458 if (tempint == 0)
459 goto skipitaddwall;
460
461 pvWalls[numscans].screenSpaceCoo[0][VEC_DIST] = yp1 + scale(yp2-yp1,xp1+yp1,tempint);
462 }
463
464 if (pvWalls[numscans].screenSpaceCoo[0][VEC_DIST] < 256)
465 goto skipitaddwall;
466
467 if (xp2 <= yp2){
468
469 if ((xp2 < -yp2) || (yp2 == 0)) goto skipitaddwall;
470 pvWalls[numscans].screenSpaceCoo[1][VEC_COL] = halfxdimen + scale(xp2,halfxdimen,yp2) - 1;
471 if (xp2 >= 0) pvWalls[numscans].screenSpaceCoo[1][VEC_COL]++; /* Fix for SIGNED divide */
472 if (pvWalls[numscans].screenSpaceCoo[1][VEC_COL] >= xdimen) pvWalls[numscans].screenSpaceCoo[1][VEC_COL] = xdimen-1;
473 pvWalls[numscans].screenSpaceCoo[1][VEC_DIST] = yp2;
474 }
475 else{
476
477 if (xp1 > yp1) goto skipitaddwall;
478 pvWalls[numscans].screenSpaceCoo[1][VEC_COL] = xdimen-1;
479 tempint = xp2-xp1+yp1-yp2;
480 if (tempint == 0) goto skipitaddwall;
481 pvWalls[numscans].screenSpaceCoo[1][VEC_DIST] = yp1 + scale(yp2-yp1,yp1-xp1,tempint);
482 }
483 if ((pvWalls[numscans].screenSpaceCoo[1][VEC_DIST] < 256) || (pvWalls[numscans].screenSpaceCoo[0][VEC_COL] > pvWalls[numscans].screenSpaceCoo[1][VEC_COL])) goto skipitaddwall;
484
485 // Made it all the way!
486 // Time to add this wall information to the stack of wall potentially visible.
487 pvWalls[numscans].sectorId = sectnum;
488 pvWalls[numscans].worldWallId = z;
489
490 //Save the camera space wall endpoints coordinate (camera origin at player location + rotated according to player orientation).
491 pvWalls[numscans].cameraSpaceCoo[0][VEC_X] = xp1;
492 pvWalls[numscans].cameraSpaceCoo[0][VEC_Y] = yp1;
493 pvWalls[numscans].cameraSpaceCoo[1][VEC_X] = xp2;
494 pvWalls[numscans].cameraSpaceCoo[1][VEC_Y] = yp2;
495
496
497 bunchWallsList[numscans] = numscans+1;
498 numscans++;
499
500skipitaddwall:
501
502 if ((wall[z].point2 < z) && (scanfirst < numscans))
503 {
504 bunchWallsList[numscans-1] = scanfirst;
505 scanfirst = numscans;
506 }
507 }
508
509 //FCS: TODO rename this p2[] to bunchList[] or something like that. This name is an abomination
510 // DONE, p2 is now called "bunchWallsList".
511
512 //Break down the list of walls for this sector into bunchs. Since a bunch is a
513 // continuously visible list of wall: A sector can generate many bunches.
514 for(z=numscansbefore; z<numscans; z++)
515 {
516 if ((wall[pvWalls[z].worldWallId].point2 !=
517 pvWalls[bunchWallsList[z]].worldWallId) || (pvWalls[z].screenSpaceCoo[1][VEC_COL] >= pvWalls[bunchWallsList[z]].screenSpaceCoo[0][VEC_COL]))
518 {
519 // Create an entry in the bunch list
520 bunchfirst[numbunches++] = bunchWallsList[z];
521
522 //Mark the end of the bunch wall list.
523 bunchWallsList[z] = -1;
524 }
525 }
526
527 //For each bunch, find the last wall and cache it in bunchlast.
528 for(z=bunchfrst; z<numbunches; z++)
529 {
530 for(zz=bunchfirst[z]; bunchWallsList[zz]>=0; zz=bunchWallsList[zz]);
531 bunchlast[z] = zz;
532 }
533
534 } while (numSectorsToVisit > 0);
535 // do this until the stack of sectors to visit if empty.
536}
537
538/*
539 FCS:
540
541 Goal : ????
542 param 1: Z is the wallID in the list of potentially visible walls.
543 param 2: Only used to lookup the xrepeat attribute of the wall.
544
545*/
546static void prepwall(int32_t z, walltype *wal)
547{
548 int32_t i, l=0, ol=0, splc, sinc, x, topinc, top, botinc, bot, walxrepeat;
549 vector_t* wallCoo = pvWalls[z].cameraSpaceCoo;
550
551 walxrepeat = (wal->xrepeat<<3);
552
553 /* lwall calculation */
554 i = pvWalls[z].screenSpaceCoo[0][VEC_COL]-halfxdimen;
555
556 //Let's use some of the camera space wall coordinate now.
557 topinc = -(wallCoo[0][VEC_Y]>>2);
558 botinc = ((wallCoo[1][VEC_Y]-wallCoo[0][VEC_Y])>>8);
559
560 top = mulscale5(wallCoo[0][VEC_X],xdimen)+mulscale2(topinc,i);
561 bot = mulscale11(wallCoo[0][VEC_X]-wallCoo[1][VEC_X],xdimen)+mulscale2(botinc,i);
562
563 splc = mulscale19(wallCoo[0][VEC_Y],xdimscale);
564 sinc = mulscale16(wallCoo[1][VEC_Y]-wallCoo[0][VEC_Y],xdimscale);
565
566 //X screenspce column of point Z.
567 x = pvWalls[z].screenSpaceCoo[0][VEC_COL];
568
569 if (bot != 0)
570 {
571 l = divscale12(top,bot);
572 swall[x] = mulscale21(l,sinc)+splc;
573 l *= walxrepeat;
574 lwall[x] = (l>>18);
575 }
576
577 //If the wall is less than 4 column wide.
578 while (x+4 <= pvWalls[z].screenSpaceCoo[1][VEC_COL])
579 {
580 top += topinc;
581 bot += botinc;
582 if (bot != 0)
583 {
584 ol = l;
585 l = divscale12(top,bot);
586 swall[x+4] = mulscale21(l,sinc)+splc;
587 l *= walxrepeat;
588 lwall[x+4] = (l>>18);
589 }
590 i = ((ol+l)>>1);
591 lwall[x+2] = (i>>18);
592 lwall[x+1] = ((ol+i)>>19);
593 lwall[x+3] = ((l+i)>>19);
594 swall[x+2] = ((swall[x]+swall[x+4])>>1);
595 swall[x+1] = ((swall[x]+swall[x+2])>>1);
596 swall[x+3] = ((swall[x+4]+swall[x+2])>>1);
597 x += 4;
598 }
599
600 //If the wall is less than 2 columns wide.
601 if (x+2 <= pvWalls[z].screenSpaceCoo[1][VEC_COL])
602 {
603 top += (topinc>>1);
604 bot += (botinc>>1);
605 if (bot != 0)
606 {
607 ol = l;
608 l = divscale12(top,bot);
609 swall[x+2] = mulscale21(l,sinc)+splc;
610 l *= walxrepeat;
611 lwall[x+2] = (l>>18);
612 }
613 lwall[x+1] = ((l+ol)>>19);
614 swall[x+1] = ((swall[x]+swall[x+2])>>1);
615 x += 2;
616 }
617
618 //The wall is 1 column wide.
619 if (x+1 <= pvWalls[z].screenSpaceCoo[1][VEC_COL])
620 {
621 bot += (botinc>>2);
622 if (bot != 0)
623 {
624 l = divscale12(top+(topinc>>2),bot);
625 swall[x+1] = mulscale21(l,sinc)+splc;
626 lwall[x+1] = mulscale18(l,walxrepeat);
627 }
628 }
629
630 if (lwall[pvWalls[z].screenSpaceCoo[0][VEC_COL]] < 0)
631 lwall[pvWalls[z].screenSpaceCoo[0][VEC_COL]] = 0;
632
633 if ((lwall[pvWalls[z].screenSpaceCoo[1][VEC_COL]] >= walxrepeat) && (walxrepeat))
634 lwall[pvWalls[z].screenSpaceCoo[1][VEC_COL]] = walxrepeat-1;
635
636 if (wal->cstat&8)
637 {
638 walxrepeat--;
639 for(x=pvWalls[z].screenSpaceCoo[0][VEC_COL]; x<=pvWalls[z].screenSpaceCoo[1][VEC_COL]; x++)
640 lwall[x] = walxrepeat-lwall[x];
641 }
642}
643
644
645static int32_t getpalookup(int32_t davis, int32_t dashade)
646{
647 return(min(max(dashade+(davis>>8),0),numpalookups-1));
648}
649
650
651static void hline (int32_t xr, int32_t yp)
652{
653 int32_t xl, r, s;
654
655 xl = lastx[yp];
656
657 if (xl > xr)
658 return;
659
660 r = horizlookup2[yp-globalhoriz+horizycent];
661 asm1 = globalx1*r;
662 asm2 = globaly2*r;
663 s = (getpalookup(mulscale16(r,globvis),globalshade)<<8);
664
665 hlineasm4(xr-xl,s,globalx2*r+globalypanning,globaly1*r+globalxpanning,ylookup[yp]+xr+frameoffset);
666}
667
668
669static void slowhline (int32_t xr, int32_t yp)
670{
671 int32_t xl, r;
672
673 xl = lastx[yp];
674 if (xl > xr) return;
675 r = horizlookup2[yp-globalhoriz+horizycent];
676 asm1 = globalx1*r;
677 asm2 = globaly2*r;
678
679 asm3 = (int32_t)globalpalwritten + (getpalookup(mulscale16(r,globvis),globalshade)<<8);
680 if (!(globalorientation&256))
681 {
682 mhline(globalbufplc,globaly1*r+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,
683 globalx2*r+globalypanning-asm2*(xr-xl),ylookup[yp]+xl+frameoffset);
684 return;
685 }
686 thline(globalbufplc,globaly1*r+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,globalx2*r+globalypanning-asm2*(xr-xl),ylookup[yp]+xl+frameoffset);
687 transarea += (xr-xl);
688}
689
690
691
692
693
694/* renders non-parallaxed ceilings. --ryan. */
695static void ceilscan (int32_t x1, int32_t x2, int32_t sectnum)
696{
697 int32_t i, j, ox, oy, x, y1, y2, twall, bwall;
698 sectortype *sec;
699
700 sec = &sector[sectnum];
701
702 if (palookup[sec->ceilingpal] != globalpalwritten)
703 globalpalwritten = palookup[sec->ceilingpal];
704
705
706 globalzd = sec->ceilingz-globalposz;
707
708
709 if (globalzd > 0)
710 return;
711
712
713 globalpicnum = sec->ceilingpicnum;
714
715 if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES)
716 globalpicnum = 0;
717
718 setgotpic(globalpicnum);
719
720 //Check the tile dimension are valid.
721 if ((tiles[globalpicnum].dim.width <= 0) ||
722 (tiles[globalpicnum].dim.height <= 0))
723 return;
724
725 if (tiles[globalpicnum].animFlags&192)
726 globalpicnum += animateoffs(globalpicnum);
727
728 TILE_MakeAvailable(globalpicnum);
729
730 globalbufplc = tiles[globalpicnum].data;
731
732 globalshade = (int32_t)sec->ceilingshade;
733 globvis = globalcisibility;
734 if (sec->visibility != 0)
735 globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
736
737 globalorientation = (int32_t)sec->ceilingstat;
738
739
740 if ((globalorientation&64) == 0){
741 globalx1 = singlobalang;
742 globalx2 = singlobalang;
743 globaly1 = cosglobalang;
744 globaly2 = cosglobalang;
745 globalxpanning = (globalposx<<20);
746 globalypanning = -(globalposy<<20);
747 }
748 else{
749 j = sec->wallptr;
750 ox = wall[wall[j].point2].x - wall[j].x;
751 oy = wall[wall[j].point2].y - wall[j].y;
752 i = nsqrtasm(ox*ox+oy*oy);
753
754 if (i == 0)
755 i = 1024;
756 else
757 i = 1048576/i;
758
759 globalx1 = mulscale10(dmulscale10(ox,singlobalang,-oy,cosglobalang),i);
760 globaly1 = mulscale10(dmulscale10(ox,cosglobalang,oy,singlobalang),i);
761 globalx2 = -globalx1;
762 globaly2 = -globaly1;
763
764 ox = ((wall[j].x-globalposx)<<6);
765 oy = ((wall[j].y-globalposy)<<6);
766 i = dmulscale14(oy,cosglobalang,-ox,singlobalang);
767 j = dmulscale14(ox,cosglobalang,oy,singlobalang);
768 ox = i;
769 oy = j;
770 globalxpanning = globalx1*ox - globaly1*oy;
771 globalypanning = globaly2*ox + globalx2*oy;
772 }
773
774 globalx2 = mulscale16(globalx2,viewingrangerecip);
775 globaly1 = mulscale16(globaly1,viewingrangerecip);
776 globalxshift = (8-(picsiz[globalpicnum]&15));
777 globalyshift = (8-(picsiz[globalpicnum]>>4));
778 if (globalorientation&8) {
779 globalxshift++;
780 globalyshift++;
781 }
782
783 if ((globalorientation&0x4) > 0){
784 i = globalxpanning;
785 globalxpanning = globalypanning;
786 globalypanning = i;
787 i = globalx2;
788 globalx2 = -globaly1;
789 globaly1 = -i;
790 i = globalx1;
791 globalx1 = globaly2;
792 globaly2 = i;
793 }
794 if ((globalorientation&0x10) > 0){
795 globalx1 = -globalx1;
796 globaly1 = -globaly1;
797 globalxpanning = -globalxpanning;
798 }
799 if ((globalorientation&0x20) > 0){
800 globalx2 = -globalx2;
801 globaly2 = -globaly2;
802 globalypanning = -globalypanning;
803 }
804
805 globalx1 <<= globalxshift;
806 globaly1 <<= globalxshift;
807 globalx2 <<= globalyshift;
808 globaly2 <<= globalyshift;
809 globalxpanning <<= globalxshift;
810 globalypanning <<= globalyshift;
811 globalxpanning += (((int32_t)sec->ceilingxpanning)<<24);
812 globalypanning += (((int32_t)sec->ceilingypanning)<<24);
813 globaly1 = (-globalx1-globaly1)*halfxdimen;
814 globalx2 = (globalx2-globaly2)*halfxdimen;
815
816 sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
817
818 globalx2 += globaly2*(x1-1);
819 globaly1 += globalx1*(x1-1);
820 globalx1 = mulscale16(globalx1,globalzd);
821 globalx2 = mulscale16(globalx2,globalzd);
822 globaly1 = mulscale16(globaly1,globalzd);
823 globaly2 = mulscale16(globaly2,globalzd);
824 globvis = klabs(mulscale10(globvis,globalzd));
825
826 if (!(globalorientation&0x180))
827 {
828 y1 = umost[x1];
829 y2 = y1;
830 for(x=x1; x<=x2; x++)
831 {
832 twall = umost[x]-1;
833 bwall = min(uplc[x],dmost[x]);
834 if (twall < bwall-1)
835 {
836 if (twall >= y2)
837 {
838 while (y1 < y2-1) hline(x-1,++y1);
839 y1 = twall;
840 }
841 else
842 {
843 while (y1 < twall)
844 hline(x-1,++y1);
845 while (y1 > twall)
846 lastx[y1--] = x;
847 }
848 while (y2 > bwall)
849 hline(x-1,--y2);
850 while (y2 < bwall)
851 lastx[y2++] = x;
852 }
853 else
854 {
855 while (y1 < y2-1)
856 hline(x-1,++y1);
857 if (x == x2) {
858 globalx2 += globaly2;
859 globaly1 += globalx1;
860 break;
861 }
862 y1 = umost[x+1];
863 y2 = y1;
864 }
865 globalx2 += globaly2;
866 globaly1 += globalx1;
867 }
868 while (y1 < y2-1) hline(x2,++y1);
869 faketimerhandler();
870 return;
871 }
872
873 switch(globalorientation&0x180)
874 {
875 case 128:
876 msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
877 break;
878 case 256:
879 settrans(TRANS_NORMAL);
880 tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
881 break;
882 case 384:
883 settrans(TRANS_REVERSE);
884 tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
885 break;
886 }
887
888 y1 = umost[x1];
889 y2 = y1;
890 for(x=x1; x<=x2; x++)
891 {
892 twall = umost[x]-1;
893 bwall = min(uplc[x],dmost[x]);
894 if (twall < bwall-1)
895 {
896 if (twall >= y2)
897 {
898 while (y1 < y2-1) slowhline(x-1,++y1);
899 y1 = twall;
900 }
901 else
902 {
903 while (y1 < twall) slowhline(x-1,++y1);
904 while (y1 > twall) lastx[y1--] = x;
905 }
906 while (y2 > bwall) slowhline(x-1,--y2);
907 while (y2 < bwall) lastx[y2++] = x;
908 }
909 else
910 {
911 while (y1 < y2-1) slowhline(x-1,++y1);
912 if (x == x2) {
913 globalx2 += globaly2;
914 globaly1 += globalx1;
915 break;
916 }
917 y1 = umost[x+1];
918 y2 = y1;
919 }
920 globalx2 += globaly2;
921 globaly1 += globalx1;
922 }
923 while (y1 < y2-1) slowhline(x2,++y1);
924 faketimerhandler();
925}
926
927
928/* renders non-parallaxed floors. --ryan. */
929static void florscan (int32_t x1, int32_t x2, int32_t sectnum)
930{
931 int32_t i, j, ox, oy, x, y1, y2, twall, bwall;
932 sectortype *sec;
933
934 //Retrieve the sector object
935 sec = &sector[sectnum];
936
937 //Retrieve the floor palette.
938 if (palookup[sec->floorpal] != globalpalwritten)
939 globalpalwritten = palookup[sec->floorpal];
940
941 globalzd = globalposz-sec->floorz;
942
943 //We are UNDER the floor: Do NOT render anything.
944 if (globalzd > 0)
945 return;
946
947 //Retrive the floor texture.
948 globalpicnum = sec->floorpicnum;
949 if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES)
950 globalpicnum = 0;
951
952 //Lock the floor texture
953 setgotpic(globalpicnum);
954
955
956 //This tile has unvalid dimensions ( negative)
957 if ((tiles[globalpicnum].dim.width <= 0) ||
958 (tiles[globalpicnum].dim.height <= 0))
959 return;
960
961 //If this is an animated texture: Animate it.
962 if (tiles[globalpicnum].animFlags&192)
963 globalpicnum += animateoffs(globalpicnum);
964
965 //If the texture is not in RAM: Load it !!
966 TILE_MakeAvailable(globalpicnum);
967
968 //Check where is the texture in RAM
969 globalbufplc = tiles[globalpicnum].data;
970
971 //Retrieve the shade of the sector (illumination level).
972 globalshade = (int32_t)sec->floorshade;
973
974 globvis = globalcisibility;
975 if (sec->visibility != 0)
976 globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16)));
977
978
979 globalorientation = (int32_t)sec->floorstat;
980
981
982 if ((globalorientation&64) == 0)
983 {
984 globalx1 = singlobalang;
985 globalx2 = singlobalang;
986 globaly1 = cosglobalang;
987 globaly2 = cosglobalang;
988 globalxpanning = (globalposx<<20);
989 globalypanning = -(globalposy<<20);
990 }
991 else
992 {
993 j = sec->wallptr;
994 ox = wall[wall[j].point2].x - wall[j].x;
995 oy = wall[wall[j].point2].y - wall[j].y;
996 i = nsqrtasm(ox*ox+oy*oy);
997 if (i == 0)
998 i = 1024;
999 else
1000 i = 1048576/i;
1001 globalx1 = mulscale10(dmulscale10(ox,singlobalang,-oy,cosglobalang),i);
1002 globaly1 = mulscale10(dmulscale10(ox,cosglobalang,oy,singlobalang),i);
1003 globalx2 = -globalx1;
1004 globaly2 = -globaly1;
1005
1006 ox = ((wall[j].x-globalposx)<<6);
1007 oy = ((wall[j].y-globalposy)<<6);
1008 i = dmulscale14(oy,cosglobalang,-ox,singlobalang);
1009 j = dmulscale14(ox,cosglobalang,oy,singlobalang);
1010 ox = i;
1011 oy = j;
1012 globalxpanning = globalx1*ox - globaly1*oy;
1013 globalypanning = globaly2*ox + globalx2*oy;
1014 }
1015
1016
1017 globalx2 = mulscale16(globalx2,viewingrangerecip);
1018 globaly1 = mulscale16(globaly1,viewingrangerecip);
1019 globalxshift = (8-(picsiz[globalpicnum]&15));
1020 globalyshift = (8-(picsiz[globalpicnum]>>4));
1021 if (globalorientation&8) {
1022 globalxshift++;
1023 globalyshift++;
1024 }
1025
1026 if ((globalorientation&0x4) > 0)
1027 {
1028 i = globalxpanning;
1029 globalxpanning = globalypanning;
1030 globalypanning = i;
1031 i = globalx2;
1032 globalx2 = -globaly1;
1033 globaly1 = -i;
1034 i = globalx1;
1035 globalx1 = globaly2;
1036 globaly2 = i;
1037 }
1038
1039
1040 if ((globalorientation&0x10) > 0){
1041 globalx1 = -globalx1;
1042 globaly1 = -globaly1;
1043 globalxpanning = -globalxpanning;
1044 }
1045
1046 if ((globalorientation&0x20) > 0){
1047 globalx2 = -globalx2;
1048 globaly2 = -globaly2;
1049 globalypanning = -globalypanning;
1050 }
1051
1052
1053 globalx1 <<= globalxshift;
1054 globaly1 <<= globalxshift;
1055 globalx2 <<= globalyshift;
1056 globaly2 <<= globalyshift;
1057 globalxpanning <<= globalxshift;
1058 globalypanning <<= globalyshift;
1059 globalxpanning += (((int32_t)sec->floorxpanning)<<24);
1060 globalypanning += (((int32_t)sec->floorypanning)<<24);
1061 globaly1 = (-globalx1-globaly1)*halfxdimen;
1062 globalx2 = (globalx2-globaly2)*halfxdimen;
1063
1064 //Setup the drawing routine paramters
1065 sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
1066
1067 globalx2 += globaly2*(x1-1);
1068 globaly1 += globalx1*(x1-1);
1069 globalx1 = mulscale16(globalx1,globalzd);
1070 globalx2 = mulscale16(globalx2,globalzd);
1071 globaly1 = mulscale16(globaly1,globalzd);
1072 globaly2 = mulscale16(globaly2,globalzd);
1073 globvis = klabs(mulscale10(globvis,globalzd));
1074
1075 if (!(globalorientation&0x180))
1076 {
1077 y1 = max(dplc[x1],umost[x1]);
1078 y2 = y1;
1079 for(x=x1; x<=x2; x++)
1080 {
1081 twall = max(dplc[x],umost[x])-1;
1082 bwall = dmost[x];
1083 if (twall < bwall-1)
1084 {
1085 if (twall >= y2)
1086 {
1087 while (y1 < y2-1)
1088 hline(x-1,++y1);
1089 y1 = twall;
1090 }
1091 else
1092 {
1093 while (y1 < twall)
1094 hline(x-1,++y1);
1095 while (y1 > twall)
1096 lastx[y1--] = x;
1097 }
1098 while (y2 > bwall)
1099 hline(x-1,--y2);
1100 while (y2 < bwall)
1101 lastx[y2++] = x;
1102 }
1103 else
1104 {
1105 while (y1 < y2-1) hline(x-1,++y1);
1106 if (x == x2) {
1107 globalx2 += globaly2;
1108 globaly1 += globalx1;
1109 break;
1110 }
1111 y1 = max(dplc[x+1],umost[x+1]);
1112 y2 = y1;
1113 }
1114 globalx2 += globaly2;
1115 globaly1 += globalx1;
1116 }
1117 while (y1 < y2-1)
1118 hline(x2,++y1);
1119
1120 faketimerhandler();
1121 return;
1122 }
1123
1124 switch(globalorientation&0x180)
1125 {
1126 case 128:
1127 msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1128 break;
1129 case 256:
1130 settrans(TRANS_NORMAL);
1131 tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1132 break;
1133 case 384:
1134 settrans(TRANS_REVERSE);
1135 tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
1136 break;
1137 }
1138
1139 y1 = max(dplc[x1],umost[x1]);
1140 y2 = y1;
1141 for(x=x1; x<=x2; x++)
1142 {
1143 twall = max(dplc[x],umost[x])-1;
1144 bwall = dmost[x];
1145 if (twall < bwall-1)
1146 {
1147 if (twall >= y2)
1148 {
1149 while (y1 < y2-1) slowhline(x-1,++y1);
1150 y1 = twall;
1151 }
1152 else
1153 {
1154 while (y1 < twall)
1155 slowhline(x-1,++y1);
1156 while (y1 > twall)
1157 lastx[y1--] = x;
1158 }
1159 while (y2 > bwall)
1160 slowhline(x-1,--y2);
1161 while (y2 < bwall)
1162 lastx[y2++] = x;
1163 }
1164 else
1165 {
1166 while (y1 < y2-1)
1167 slowhline(x-1,++y1);
1168 if (x == x2) {
1169 globalx2 += globaly2;
1170 globaly1 += globalx1;
1171 break;
1172 }
1173 y1 = max(dplc[x+1],umost[x+1]);
1174 y2 = y1;
1175 }
1176 globalx2 += globaly2;
1177 globaly1 += globalx1;
1178 }
1179 while (y1 < y2-1)
1180 slowhline(x2,++y1);
1181
1182 faketimerhandler();
1183}
1184
1185
1186/*
1187 * renders walls and parallaxed skies/floors. Look at parascan() for the
1188 * higher level of parallaxing.
1189 *
1190 * x1 == offset of leftmost pixel of wall. 0 is left of surface.
1191 * x2 == offset of rightmost pixel of wall. 0 is left of surface.
1192 *
1193 * apparently, walls are always vertical; there are sloping functions
1194 * (!!!) er...elsewhere. Only the sides need be vertical, as the top and
1195 * bottom of the polygon will need to be angled as the camera perspective
1196 * shifts (user spins in a circle, etc.)
1197 *
1198 * uwal is an array of the upper most pixels, and dwal are the lower most.
1199 * This must be a list, as the top and bottom of the polygon are not
1200 * necessarily horizontal lines.
1201 *
1202 * So, the screen coordinate of the top left of a wall is specified by
1203 * uwal[x1], the bottom left by dwal[x1], the top right by uwal[x2], and
1204 * the bottom right by dwal[x2]. Every physical point on the edge of the
1205 * wall in between is specified by traversing those arrays, one pixel per
1206 * element.
1207 *
1208 * --ryan.
1209 */
1210static void wallscan(int32_t x1, int32_t x2,
1211 int16_t *uwal, int16_t *dwal,
1212 int32_t *swal, int32_t *lwal)
1213{
1214 int32_t x, xnice, ynice;
1215 intptr_t i;
1216 uint8_t* fpalookup;
1217 int32_t y1ve[4], y2ve[4], u4, d4, z, tileWidth, tsizy;
1218 uint8_t bad;
1219
1220 tileWidth = tiles[globalpicnum].dim.width;
1221 tsizy = tiles[globalpicnum].dim.height;
1222
1223 setgotpic(globalpicnum);
1224
1225 if ((tileWidth <= 0) || (tsizy <= 0))
1226 return;
1227
1228 if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen))
1229 return;
1230
1231 if ((dwal[x1] < 0) && (dwal[x2] < 0))
1232 return;
1233
1234 TILE_MakeAvailable(globalpicnum);
1235
1236 xnice = (pow2long[picsiz[globalpicnum]&15] == tileWidth);
1237 if (xnice)
1238 tileWidth--;
1239
1240 ynice = (pow2long[picsiz[globalpicnum]>>4] == tsizy);
1241 if (ynice)
1242 tsizy = (picsiz[globalpicnum]>>4);
1243
1244 fpalookup = palookup[globalpal];
1245
1246 setupvlineasm(globalshiftval);
1247
1248 //Starting on the left column of the wall, check the occlusion arrays.
1249 x = x1;
1250 while ((umost[x] > dmost[x]) && (x <= x2))
1251 x++;
1252
1253 for(; (x<=x2)&&((x+frameoffset-(uint8_t*)NULL)&3); x++)
1254 {
1255 y1ve[0] = max(uwal[x],umost[x]);
1256 y2ve[0] = min(dwal[x],dmost[x]);
1257 if (y2ve[0] <= y1ve[0])
1258 continue;
1259
1260 palookupoffse[0] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x],globvis),globalshade)<<8);
1261
1262 bufplce[0] = lwal[x] + globalxpanning;
1263
1264 if (bufplce[0] >= tileWidth)
1265 {
1266 if (xnice == 0)
1267 bufplce[0] %= tileWidth;
1268 else
1269 bufplce[0] &= tileWidth;
1270 }
1271
1272 if (ynice == 0)
1273 bufplce[0] *= tsizy;
1274 else
1275 bufplce[0] <<= tsizy;
1276
1277 vince[0] = swal[x]*globalyscale;
1278 vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
1279
1280 vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+tiles[globalpicnum].data,x+frameoffset+ylookup[y1ve[0]]);
1281 }
1282
1283 for(; x<=x2-3; x+=4)
1284 {
1285 bad = 0;
1286 for(z=3; z>=0; z--)
1287 {
1288 y1ve[z] = max(uwal[x+z],umost[x+z]);
1289 y2ve[z] = min(dwal[x+z],dmost[x+z])-1;
1290
1291 if (y2ve[z] < y1ve[z])
1292 {
1293 bad += pow2char[z];
1294 continue;
1295 }
1296
1297 i = lwal[x+z] + globalxpanning;
1298 if (i >= tileWidth) {
1299 if (xnice == 0) i %= tileWidth;
1300 else i &= tileWidth;
1301 }
1302 if (ynice == 0)
1303 i *= tsizy;
1304 else
1305 i <<= tsizy;
1306 bufplce[z] = tiles[globalpicnum].data+i;
1307
1308 vince[z] = swal[x+z]*globalyscale;
1309 vplce[z] = globalzd + vince[z]*(y1ve[z]-globalhoriz+1);
1310 }
1311
1312 if (bad == 15)
1313 continue;
1314
1315 palookupoffse[0] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x],globvis),globalshade)<<8);
1316 palookupoffse[3] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x+3],globvis),globalshade)<<8);
1317
1318 if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
1319 {
1320 palookupoffse[1] = palookupoffse[0];
1321 palookupoffse[2] = palookupoffse[0];
1322 }
1323 else
1324 {
1325 palookupoffse[1] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x+1],globvis),globalshade)<<8);
1326 palookupoffse[2] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x+2],globvis),globalshade)<<8);
1327 }
1328
1329 u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
1330 d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
1331
1332 if ((bad != 0) || (u4 >= d4))
1333 {
1334 if (!(bad&1))
1335 prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+x+frameoffset+0);
1336 if (!(bad&2))
1337 prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+x+frameoffset+1);
1338 if (!(bad&4))
1339 prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+x+frameoffset+2);
1340 if (!(bad&8))
1341 prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+x+frameoffset+3);
1342 continue;
1343 }
1344
1345 if (u4 > y1ve[0])
1346 vplce[0] =prevlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+x+frameoffset+0);
1347 if (u4 > y1ve[1])
1348 vplce[1] = prevlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+x+frameoffset+1);
1349 if (u4 > y1ve[2])
1350 vplce[2] = prevlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+x+frameoffset+2);
1351 if (u4 > y1ve[3])
1352 vplce[3] = prevlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+x+frameoffset+3);
1353
1354 if (d4 >= u4)
1355 vlineasm4(d4-u4+1,ylookup[u4]+x+frameoffset);
1356
1357 i = x+frameoffset+ylookup[d4+1];
1358
1359 if (y2ve[0] > d4)
1360 prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
1361 if (y2ve[1] > d4)
1362 prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
1363 if (y2ve[2] > d4)
1364 prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
1365 if (y2ve[3] > d4)
1366 prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
1367 }
1368 for(; x<=x2; x++)
1369 {
1370 y1ve[0] = max(uwal[x],umost[x]);
1371 y2ve[0] = min(dwal[x],dmost[x]);
1372 if (y2ve[0] <= y1ve[0])
1373 continue;
1374
1375 palookupoffse[0] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x],globvis),globalshade)<<8);
1376
1377 bufplce[0] = lwal[x] + globalxpanning;
1378 if (bufplce[0] >= tileWidth) {
1379 if (xnice == 0)
1380 bufplce[0] %= tileWidth;
1381 else
1382 bufplce[0] &= tileWidth;
1383 }
1384
1385 if (ynice == 0) bufplce[0]
1386 *= tsizy;
1387 else
1388 bufplce[0] <<= tsizy;
1389
1390 vince[0] = swal[x]*globalyscale;
1391 vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
1392
1393 vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+tiles[globalpicnum].data,x+frameoffset+ylookup[y1ve[0]]);
1394 }
1395 faketimerhandler();
1396}
1397
1398
1399/* this renders masking sprites. See wallscan(). --ryan. */
1400static void maskwallscan(int32_t x1, int32_t x2,
1401 short *uwal, short *dwal,
1402 int32_t *swal, int32_t *lwal)
1403{
1404 int32_t x, startx, xnice, ynice;
1405 intptr_t i;
1406 uint8_t* fpalookup;
1407 int32_t y1ve[4], y2ve[4], u4, d4, dax, z, tileWidth, tileHeight;
1408 uint8_t* p;
1409 uint8_t bad;
1410
1411 tileWidth = tiles[globalpicnum].dim.width;
1412 tileHeight = tiles[globalpicnum].dim.height;
1413 setgotpic(globalpicnum);
1414
1415 if ((tileWidth <= 0) || (tileHeight <= 0))
1416 return;
1417 if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen))
1418 return;
1419 if ((dwal[x1] < 0) && (dwal[x2] < 0))
1420 return;
1421
1422 TILE_MakeAvailable(globalpicnum);
1423
1424 startx = x1;
1425
1426 xnice = (pow2long[picsiz[globalpicnum]&15] == tileWidth);
1427 if (xnice)
1428 tileWidth = (tileWidth-1);
1429
1430 ynice = (pow2long[picsiz[globalpicnum]>>4] == tileHeight);
1431 if (ynice)
1432 tileHeight = (picsiz[globalpicnum]>>4);
1433
1434 fpalookup = palookup[globalpal];
1435
1436 setupmvlineasm(globalshiftval);
1437
1438 x = startx;
1439 while ((startumost[x+windowx1] > startdmost[x+windowx1]) && (x <= x2)) x++;
1440
1441 p = x+frameoffset;
1442
1443 for(; (x<=x2)&&((p-(uint8_t*)NULL)&3); x++,p++)
1444 {
1445 y1ve[0] = max(uwal[x],startumost[x+windowx1]-windowy1);
1446 y2ve[0] = min(dwal[x],startdmost[x+windowx1]-windowy1);
1447 if (y2ve[0] <= y1ve[0]) continue;
1448
1449 palookupoffse[0] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x],globvis),globalshade)<<8);
1450
1451 bufplce[0] = lwal[x] + globalxpanning;
1452 if (bufplce[0] >= tileWidth) {
1453 if (xnice == 0) bufplce[0] %= tileWidth;
1454 else bufplce[0] &= tileWidth;
1455 }
1456 if (ynice == 0)
1457 bufplce[0] *= tileHeight;
1458 else
1459 bufplce[0] <<= tileHeight;
1460
1461 vince[0] = swal[x]*globalyscale;
1462 vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
1463
1464 mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+tiles[globalpicnum].data,p+ylookup[y1ve[0]]);
1465 }
1466 for(; x<=x2-3; x+=4,p+=4)
1467 {
1468 bad = 0;
1469 for(z=3,dax=x+3; z>=0; z--,dax--)
1470 {
1471 y1ve[z] = max(uwal[dax],startumost[dax+windowx1]-windowy1);
1472 y2ve[z] = min(dwal[dax],startdmost[dax+windowx1]-windowy1)-1;
1473 if (y2ve[z] < y1ve[z]) {
1474 bad += pow2char[z];
1475 continue;
1476 }
1477
1478 i = lwal[dax] + globalxpanning;
1479 if (i >= tileWidth) {
1480 if (xnice == 0) i %= tileWidth;
1481 else i &= tileWidth;
1482 }
1483
1484 if (ynice == 0)
1485 i *= tileHeight;
1486 else
1487 i <<= tileHeight;
1488
1489 bufplce[z] = tiles[globalpicnum].data+i;
1490
1491 vince[z] = swal[dax]*globalyscale;
1492 vplce[z] = globalzd + vince[z]*(y1ve[z]-globalhoriz+1);
1493 }
1494 if (bad == 15) continue;
1495
1496 palookupoffse[0] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x],globvis),globalshade)<<8);
1497 palookupoffse[3] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x+3],globvis),globalshade)<<8);
1498
1499 if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
1500 {
1501 palookupoffse[1] = palookupoffse[0];
1502 palookupoffse[2] = palookupoffse[0];
1503 }
1504 else
1505 {
1506 palookupoffse[1] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x+1],globvis),globalshade)<<8);
1507 palookupoffse[2] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x+2],globvis),globalshade)<<8);
1508 }
1509
1510 u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
1511 d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
1512
1513 if ((bad > 0) || (u4 >= d4))
1514 {
1515 if (!(bad&1)) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
1516 if (!(bad&2)) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
1517 if (!(bad&4)) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
1518 if (!(bad&8)) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
1519 continue;
1520 }
1521
1522 if (u4 > y1ve[0]) vplce[0] = mvlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
1523 if (u4 > y1ve[1]) vplce[1] = mvlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
1524 if (u4 > y1ve[2]) vplce[2] = mvlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
1525 if (u4 > y1ve[3]) vplce[3] = mvlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
1526
1527 if (d4 >= u4) mvlineasm4(d4-u4+1,ylookup[u4]+p);
1528
1529 i = p+ylookup[d4+1];
1530 if (y2ve[0] > d4) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
1531 if (y2ve[1] > d4) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
1532 if (y2ve[2] > d4) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
1533 if (y2ve[3] > d4) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
1534 }
1535 for(; x<=x2; x++,p++)
1536 {
1537 y1ve[0] = max(uwal[x],startumost[x+windowx1]-windowy1);
1538 y2ve[0] = min(dwal[x],startdmost[x+windowx1]-windowy1);
1539 if (y2ve[0] <= y1ve[0]) continue;
1540
1541 palookupoffse[0] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x],globvis),globalshade)<<8);
1542
1543 bufplce[0] = lwal[x] + globalxpanning;
1544 if (bufplce[0] >= tileWidth) {
1545 if (xnice == 0) bufplce[0] %= tileWidth;
1546 else bufplce[0] &= tileWidth;
1547 }
1548 if (ynice == 0)
1549 bufplce[0] *= tileHeight;
1550 else
1551 bufplce[0] <<= tileHeight;
1552
1553 vince[0] = swal[x]*globalyscale;
1554 vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
1555
1556 mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+tiles[globalpicnum].data,p+ylookup[y1ve[0]]);
1557 }
1558 faketimerhandler();
1559}
1560
1561/* renders parallaxed skies/floors --ryan. */
1562static void parascan(int32_t dax1, int32_t dax2, int32_t sectnum,uint8_t dastat, int32_t bunch)
1563{
1564 sectortype *sec;
1565 int32_t j, k, l, m, n, x, z, wallnum, nextsectnum, globalhorizbak;
1566 short *topptr, *botptr;
1567
1568 sectnum = pvWalls[bunchfirst[bunch]].sectorId;
1569 sec = &sector[sectnum];
1570
1571 globalhorizbak = globalhoriz;
1572 if (parallaxyscale != 65536)
1573 globalhoriz = mulscale16(globalhoriz-(ydimen>>1),parallaxyscale) + (ydimen>>1);
1574 globvis = globalpisibility;
1575 /* globalorientation = 0L; */
1576 if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
1577
1578 if (dastat == 0)
1579 {
1580 globalpal = sec->ceilingpal;
1581 globalpicnum = sec->ceilingpicnum;
1582 globalshade = (int32_t)sec->ceilingshade;
1583 globalxpanning = (int32_t)sec->ceilingxpanning;
1584 globalypanning = (int32_t)sec->ceilingypanning;
1585 topptr = umost;
1586 botptr = uplc;
1587 }
1588 else
1589 {
1590 globalpal = sec->floorpal;
1591 globalpicnum = sec->floorpicnum;
1592 globalshade = (int32_t)sec->floorshade;
1593 globalxpanning = (int32_t)sec->floorxpanning;
1594 globalypanning = (int32_t)sec->floorypanning;
1595 topptr = dplc;
1596 botptr = dmost;
1597 }
1598
1599 if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
1600
1601 if (tiles[globalpicnum].animFlags&192)
1602 globalpicnum += animateoffs(globalpicnum);
1603
1604 globalshiftval = (picsiz[globalpicnum]>>4);
1605
1606 if (pow2long[globalshiftval] != tiles[globalpicnum].dim.height)
1607 globalshiftval++;
1608 globalshiftval = 32-globalshiftval;
1609 globalzd = (((tiles[globalpicnum].dim.height>>1)+parallaxyoffs)<<globalshiftval)+(globalypanning<<24);
1610 globalyscale = (8<<(globalshiftval-19));
1611 /*if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;*/
1612
1613 k = 11 - (picsiz[globalpicnum]&15) - pskybits;
1614 x = -1;
1615
1616 for(z=bunchfirst[bunch]; z>=0; z=bunchWallsList[z])
1617 {
1618 wallnum = pvWalls[z].worldWallId;
1619 nextsectnum = wall[wallnum].nextsector;
1620
1621 if (dastat == 0) j = sector[nextsectnum].ceilingstat;
1622 else j = sector[nextsectnum].floorstat;
1623
1624 if ((nextsectnum < 0) || (wall[wallnum].cstat&32) || ((j&1) == 0))
1625 {
1626 if (x == -1) x = pvWalls[z].screenSpaceCoo[0][VEC_COL];
1627
1628 if (parallaxtype == 0)
1629 {
1630 n = mulscale16(xdimenrecip,viewingrange);
1631 for(j=pvWalls[z].screenSpaceCoo[0][VEC_COL]; j<=pvWalls[z].screenSpaceCoo[1][VEC_COL]; j++)
1632 lplc[j] = (((mulscale23(j-halfxdimen,n)+globalang)&2047)>>k);
1633 }
1634 else
1635 {
1636 for(j=pvWalls[z].screenSpaceCoo[0][VEC_COL]; j<=pvWalls[z].screenSpaceCoo[1][VEC_COL]; j++)
1637 lplc[j] = ((((int32_t)radarang2[j]+globalang)&2047)>>k);
1638 }
1639 if (parallaxtype == 2)
1640 {
1641 n = mulscale16(xdimscale,viewingrange);
1642 for(j=pvWalls[z].screenSpaceCoo[0][VEC_COL]; j<=pvWalls[z].screenSpaceCoo[1][VEC_COL]; j++)
1643 swplc[j] = mulscale14(sintable[((int32_t)radarang2[j]+512)&2047],n);
1644 }
1645 else
1646 clearbuf(&swplc[pvWalls[z].screenSpaceCoo[0][VEC_COL]],pvWalls[z].screenSpaceCoo[1][VEC_COL]-pvWalls[z].screenSpaceCoo[0][VEC_COL]+1,mulscale16(xdimscale,viewingrange));
1647 }
1648 else if (x >= 0)
1649 {
1650 l = globalpicnum;
1651 m = (picsiz[globalpicnum]&15);
1652 globalpicnum = l+pskyoff[lplc[x]>>m];
1653
1654 if (((lplc[x]^lplc[pvWalls[z].screenSpaceCoo[0][VEC_COL]-1])>>m) == 0)
1655 wallscan(x,pvWalls[z].screenSpaceCoo[0][VEC_COL]-1,topptr,botptr,swplc,lplc);
1656 else
1657 {
1658 j = x;
1659 while (x < pvWalls[z].screenSpaceCoo[0][VEC_COL])
1660 {
1661 n = l+pskyoff[lplc[x]>>m];
1662 if (n != globalpicnum)
1663 {
1664 wallscan(j,x-1,topptr,botptr,swplc,lplc);
1665 j = x;
1666 globalpicnum = n;
1667 }
1668 x++;
1669 }
1670 if (j < x)
1671 wallscan(j,x-1,topptr,botptr,swplc,lplc);
1672 }
1673
1674 globalpicnum = l;
1675 x = -1;
1676 }
1677 }
1678
1679 if (x >= 0)
1680 {
1681 l = globalpicnum;
1682 m = (picsiz[globalpicnum]&15);
1683 globalpicnum = l+pskyoff[lplc[x]>>m];
1684
1685 if (((lplc[x]^lplc[pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL]])>>m) == 0)
1686 wallscan(x,pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],topptr,botptr,swplc,lplc);
1687 else
1688 {
1689 j = x;
1690 while (x <= pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL])
1691 {
1692 n = l+pskyoff[lplc[x]>>m];
1693 if (n != globalpicnum)
1694 {
1695 wallscan(j,x-1,topptr,botptr,swplc,lplc);
1696 j = x;
1697 globalpicnum = n;
1698 }
1699 x++;
1700 }
1701 if (j <= x)
1702 wallscan(j,x,topptr,botptr,swplc,lplc);
1703 }
1704 globalpicnum = l;
1705 }
1706 globalhoriz = globalhorizbak;
1707}
1708
1709
1710#define BITSOFPRECISION 3 /* Don't forget to change this in A.ASM also! */
1711static void grouscan (int32_t dax1, int32_t dax2, int32_t sectnum, uint8_t dastat)
1712{
1713 int32_t i, j, l, x, y, dx, dy, wx, wy, y1, y2, daz;
1714 int32_t daslope, dasqr;
1715 int32_t shoffs, shinc, m1, m2, *mptr1, *mptr2, *nptr1, *nptr2;
1716 walltype *wal;
1717 sectortype *sec;
1718
1719 sec = &sector[sectnum];
1720
1721 if (dastat == 0)
1722 {
1723 if (globalposz <= getceilzofslope((short) sectnum,globalposx,globalposy))
1724 return; /* Back-face culling */
1725 globalorientation = sec->ceilingstat;
1726 globalpicnum = sec->ceilingpicnum;
1727 globalshade = sec->ceilingshade;
1728 globalpal = sec->ceilingpal;
1729 daslope = sec->ceilingheinum;
1730 daz = sec->ceilingz;
1731 }
1732 else
1733 {
1734 if (globalposz >= getflorzofslope((short) sectnum,globalposx,globalposy))
1735 return; /* Back-face culling */
1736 globalorientation = sec->floorstat;
1737 globalpicnum = sec->floorpicnum;
1738 globalshade = sec->floorshade;
1739 globalpal = sec->floorpal;
1740 daslope = sec->floorheinum;
1741 daz = sec->floorz;
1742 }
1743
1744 if ((tiles[globalpicnum].animFlags&192) != 0)
1745 globalpicnum += animateoffs(globalpicnum);
1746
1747 setgotpic(globalpicnum);
1748
1749 if ((tiles[globalpicnum].dim.width <= 0) ||
1750 (tiles[globalpicnum].dim.height <= 0))
1751 return;
1752
1753 TILE_MakeAvailable(globalpicnum);
1754
1755 wal = &wall[sec->wallptr];
1756 wx = wall[wal->point2].x - wal->x;
1757 wy = wall[wal->point2].y - wal->y;
1758 dasqr = krecipasm(nsqrtasm(wx*wx+wy*wy));
1759 i = mulscale21(daslope,dasqr);
1760 wx *= i;
1761 wy *= i;
1762
1763 globalx = -mulscale19(singlobalang,xdimenrecip);
1764 globaly = mulscale19(cosglobalang,xdimenrecip);
1765 globalx1 = (globalposx<<8);
1766 globaly1 = -(globalposy<<8);
1767 i = (dax1-halfxdimen)*xdimenrecip;
1768 globalx2 = mulscale16(cosglobalang<<4,viewingrangerecip) - mulscale27(singlobalang,i);
1769 globaly2 = mulscale16(singlobalang<<4,viewingrangerecip) + mulscale27(cosglobalang,i);
1770 globalzd = (xdimscale<<9);
1771 globalzx = -dmulscale17(wx,globaly2,-wy,globalx2) + mulscale10(1-globalhoriz,globalzd);
1772 globalz = -dmulscale25(wx,globaly,-wy,globalx);
1773
1774 if (globalorientation&64) /* Relative alignment */
1775 {
1776 dx = mulscale14(wall[wal->point2].x-wal->x,dasqr);
1777 dy = mulscale14(wall[wal->point2].y-wal->y,dasqr);
1778
1779 i = nsqrtasm(daslope*daslope+16777216);
1780
1781 x = globalx;
1782 y = globaly;
1783 globalx = dmulscale16(x,dx,y,dy);
1784 globaly = mulscale12(dmulscale16(-y,dx,x,dy),i);
1785
1786 x = ((wal->x-globalposx)<<8);
1787 y = ((wal->y-globalposy)<<8);
1788 globalx1 = dmulscale16(-x,dx,-y,dy);
1789 globaly1 = mulscale12(dmulscale16(-y,dx,x,dy),i);
1790
1791 x = globalx2;
1792 y = globaly2;
1793 globalx2 = dmulscale16(x,dx,y,dy);
1794 globaly2 = mulscale12(dmulscale16(-y,dx,x,dy),i);
1795 }
1796 if (globalorientation&0x4)
1797 {
1798 i = globalx;
1799 globalx = -globaly;
1800 globaly = -i;
1801 i = globalx1;
1802 globalx1 = globaly1;
1803 globaly1 = i;
1804 i = globalx2;
1805 globalx2 = -globaly2;
1806 globaly2 = -i;
1807 }
1808 if (globalorientation&0x10) {
1809 globalx1 = -globalx1, globalx2 = -globalx2, globalx = -globalx;
1810 }
1811 if (globalorientation&0x20) {
1812 globaly1 = -globaly1, globaly2 = -globaly2, globaly = -globaly;
1813 }
1814
1815 daz = dmulscale9(wx,globalposy-wal->y,-wy,globalposx-wal->x) + ((daz-globalposz)<<8);
1816 globalx2 = mulscale20(globalx2,daz);
1817 globalx = mulscale28(globalx,daz);
1818 globaly2 = mulscale20(globaly2,-daz);
1819 globaly = mulscale28(globaly,-daz);
1820
1821 i = 8-(picsiz[globalpicnum]&15);
1822 j = 8-(picsiz[globalpicnum]>>4);
1823 if (globalorientation&8) {
1824 i++;
1825 j++;
1826 }
1827 globalx1 <<= (i+12);
1828 globalx2 <<= i;
1829 globalx <<= i;
1830 globaly1 <<= (j+12);
1831 globaly2 <<= j;
1832 globaly <<= j;
1833
1834 if (dastat == 0)
1835 {
1836 globalx1 += (((int32_t)sec->ceilingxpanning)<<24);
1837 globaly1 += (((int32_t)sec->ceilingypanning)<<24);
1838 }
1839 else
1840 {
1841 globalx1 += (((int32_t)sec->floorxpanning)<<24);
1842 globaly1 += (((int32_t)sec->floorypanning)<<24);
1843 }
1844
1845 asm1 = -(globalzd>>(16-BITSOFPRECISION));
1846
1847 globvis = globalvisibility;
1848 if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
1849 globvis = mulscale13(globvis,daz);
1850 globvis = mulscale16(globvis,xdimscale);
1851 j =(int32_t) FP_OFF(palookup[globalpal]);
1852
1853 setupslopevlin(((int32_t)(picsiz[globalpicnum]&15))+(((int32_t)(picsiz[globalpicnum]>>4))<<8),tiles[globalpicnum].data,-ylookup[1]);
1854
1855 l = (globalzd>>16);
1856
1857 shinc = mulscale16(globalz,xdimenscale);
1858 if (shinc > 0)
1859 shoffs = (4<<15);
1860 else
1861 shoffs = ((16380-ydimen)<<15); // JBF: was 2044 16380
1862 if (dastat == 0) y1 = umost[dax1];
1863 else y1 = max(umost[dax1],dplc[dax1]);
1864 m1 = mulscale16(y1,globalzd) + (globalzx>>6);
1865 /* Avoid visibility overflow by crossing horizon */
1866 if (globalzd > 0) m1 += (globalzd>>16);
1867 else m1 -= (globalzd>>16);
1868 m2 = m1+l;
1869 mptr1 = (int32_t *)&slopalookup[y1+(shoffs>>15)];
1870 mptr2 = mptr1+1;
1871
1872 for(x=dax1; x<=dax2; x++)
1873 {
1874 if (dastat == 0) {
1875 y1 = umost[x];
1876 y2 = min(dmost[x],uplc[x])-1;
1877 }
1878 else {
1879 y1 = max(umost[x],dplc[x]);
1880 y2 = dmost[x]-1;
1881 }
1882 if (y1 <= y2)
1883 {
1884 nptr1 = (int32_t *)&slopalookup[y1+(shoffs>>15)];
1885 nptr2 = (int32_t *)&slopalookup[y2+(shoffs>>15)];
1886 while (nptr1 <= mptr1)
1887 {
1888 *mptr1-- = j + (getpalookup((int32_t)mulscale24(krecipasm(m1),globvis),globalshade)<<8);
1889 m1 -= l;
1890 }
1891 while (nptr2 >= mptr2)
1892 {
1893 *mptr2++ = j + (getpalookup((int32_t)mulscale24(krecipasm(m2),globvis),globalshade)<<8);
1894 m2 += l;
1895 }
1896
1897 globalx3 = (globalx2>>10);
1898 globaly3 = (globaly2>>10);
1899 asm3 = mulscale16(y2,globalzd) + (globalzx>>6);
1900 slopevlin(ylookup[y2]+x+frameoffset,krecipasm(asm3>>3),(int32_t)nptr2,y2-y1+1,globalx1,globaly1);
1901
1902 if ((x&15) == 0) faketimerhandler();
1903 }
1904 globalx2 += globalx;
1905 globaly2 += globaly;
1906 globalzx += globalz;
1907 shoffs += shinc;
1908 }
1909}
1910
1911
1912static int owallmost(short *mostbuf, int32_t w, int32_t z)
1913{
1914 int32_t bad, inty, xcross, y, yinc;
1915 int32_t s1, s2, s3, s4, ix1, ix2, iy1, iy2, t;
1916
1917 z <<= 7;
1918 s1 = mulscale20(globaluclip,pvWalls[w].screenSpaceCoo[0][VEC_DIST]);
1919 s2 = mulscale20(globaluclip,pvWalls[w].screenSpaceCoo[1][VEC_DIST]);
1920 s3 = mulscale20(globaldclip,pvWalls[w].screenSpaceCoo[0][VEC_DIST]);
1921 s4 = mulscale20(globaldclip,pvWalls[w].screenSpaceCoo[1][VEC_DIST]);
1922 bad = (z<s1)+((z<s2)<<1)+((z>s3)<<2)+((z>s4)<<3);
1923
1924 ix1 = pvWalls[w].screenSpaceCoo[0][VEC_COL];
1925 iy1 = pvWalls[w].screenSpaceCoo[0][VEC_DIST];
1926 ix2 = pvWalls[w].screenSpaceCoo[1][VEC_COL];
1927 iy2 = pvWalls[w].screenSpaceCoo[1][VEC_DIST];
1928
1929 if ((bad&3) == 3)
1930 {
1931 clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),0L);
1932 return(bad);
1933 }
1934
1935 if ((bad&12) == 12)
1936 {
1937 clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
1938 return(bad);
1939 }
1940
1941 if (bad&3)
1942 {
1943 t = divscale30(z-s1,s2-s1);
1944 inty = pvWalls[w].screenSpaceCoo[0][VEC_DIST] + mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST]-pvWalls[w].screenSpaceCoo[0][VEC_DIST],t);
1945 xcross = pvWalls[w].screenSpaceCoo[0][VEC_COL] + scale(mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST],t),pvWalls[w].screenSpaceCoo[1][VEC_COL]-pvWalls[w].screenSpaceCoo[0][VEC_COL],inty);
1946
1947 if ((bad&3) == 2)
1948 {
1949 if (pvWalls[w].screenSpaceCoo[0][VEC_COL] <= xcross) {
1950 iy2 = inty;
1951 ix2 = xcross;
1952 }
1953 clearbufbyte(&mostbuf[xcross+1],(pvWalls[w].screenSpaceCoo[1][VEC_COL]-xcross)*sizeof(mostbuf[0]),0L);
1954 }
1955 else
1956 {
1957 if (xcross <= pvWalls[w].screenSpaceCoo[1][VEC_COL]) {
1958 iy1 = inty;
1959 ix1 = xcross;
1960 }
1961 clearbufbyte(&mostbuf[pvWalls[w].screenSpaceCoo[0][VEC_COL]],(xcross-pvWalls[w].screenSpaceCoo[0][VEC_COL]+1)*sizeof(mostbuf[0]),0L);
1962 }
1963 }
1964
1965 if (bad&12)
1966 {
1967 t = divscale30(z-s3,s4-s3);
1968 inty = pvWalls[w].screenSpaceCoo[0][VEC_DIST] + mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST]-pvWalls[w].screenSpaceCoo[0][VEC_DIST],t);
1969 xcross = pvWalls[w].screenSpaceCoo[0][VEC_COL] + scale(mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST],t),pvWalls[w].screenSpaceCoo[1][VEC_COL]-pvWalls[w].screenSpaceCoo[0][VEC_COL],inty);
1970
1971 if ((bad&12) == 8)
1972 {
1973 if (pvWalls[w].screenSpaceCoo[0][VEC_COL] <= xcross) {
1974 iy2 = inty;
1975 ix2 = xcross;
1976 }
1977 clearbufbyte(&mostbuf[xcross+1],(pvWalls[w].screenSpaceCoo[1][VEC_COL]-xcross)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
1978 }
1979 else
1980 {
1981 if (xcross <= pvWalls[w].screenSpaceCoo[1][VEC_COL]) {
1982 iy1 = inty;
1983 ix1 = xcross;
1984 }
1985 clearbufbyte(&mostbuf[pvWalls[w].screenSpaceCoo[0][VEC_COL]],(xcross-pvWalls[w].screenSpaceCoo[0][VEC_COL]+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
1986 }
1987 }
1988
1989 y = (scale(z,xdimenscale,iy1)<<4);
1990 yinc = ((scale(z,xdimenscale,iy2)<<4)-y) / (ix2-ix1+1);
1991 qinterpolatedown16short((int32_t *)&mostbuf[ix1],ix2-ix1+1,y+(globalhoriz<<16),yinc);
1992
1993 if (mostbuf[ix1] < 0) mostbuf[ix1] = 0;
1994 if (mostbuf[ix1] > ydimen) mostbuf[ix1] = ydimen;
1995 if (mostbuf[ix2] < 0) mostbuf[ix2] = 0;
1996 if (mostbuf[ix2] > ydimen) mostbuf[ix2] = ydimen;
1997
1998 return(bad);
1999}
2000
2001
2002static int wallmost(short *mostbuf, int32_t w, int32_t sectnum, uint8_t dastat)
2003{
2004 int32_t bad, i, j, t, y, z, inty, intz, xcross, yinc, fw;
2005 int32_t x1, y1, z1, x2, y2, z2, xv, yv, dx, dy, dasqr, oz1, oz2;
2006 int32_t s1, s2, s3, s4, ix1, ix2, iy1, iy2;
2007
2008 if (dastat == 0){
2009 z = sector[sectnum].ceilingz-globalposz;
2010 if ((sector[sectnum].ceilingstat&2) == 0)
2011 return(owallmost(mostbuf,w,z));
2012 }
2013 else{
2014 z = sector[sectnum].floorz-globalposz;
2015 if ((sector[sectnum].floorstat&2) == 0)
2016 return(owallmost(mostbuf,w,z));
2017 }
2018
2019 i = pvWalls[w].worldWallId;
2020 if (i == sector[sectnum].wallptr)
2021 return(owallmost(mostbuf,w,z));
2022
2023 x1 = wall[i].x;
2024 x2 = wall[wall[i].point2].x-x1;
2025 y1 = wall[i].y;
2026 y2 = wall[wall[i].point2].y-y1;
2027
2028 fw = sector[sectnum].wallptr;
2029 i = wall[fw].point2;
2030 dx = wall[i].x-wall[fw].x;
2031 dy = wall[i].y-wall[fw].y;
2032 dasqr = krecipasm(nsqrtasm(dx*dx+dy*dy));
2033
2034 if (pvWalls[w].screenSpaceCoo[0][VEC_COL] == 0){
2035 xv = cosglobalang+sinviewingrangeglobalang;
2036 yv = singlobalang-cosviewingrangeglobalang;
2037 }
2038 else{
2039 xv = x1-globalposx;
2040 yv = y1-globalposy;
2041 }
2042 i = xv*(y1-globalposy)-yv*(x1-globalposx);
2043 j = yv*x2-xv*y2;
2044
2045 if (klabs(j) > klabs(i>>3))
2046 i = divscale28(i,j);
2047
2048 if (dastat == 0){
2049 t = mulscale15(sector[sectnum].ceilingheinum,dasqr);
2050 z1 = sector[sectnum].ceilingz;
2051 }
2052 else{
2053 t = mulscale15(sector[sectnum].floorheinum,dasqr);
2054 z1 = sector[sectnum].floorz;
2055 }
2056
2057 z1 = dmulscale24(dx*t,mulscale20(y2,i)+((y1-wall[fw].y)<<8),-dy*t,mulscale20(x2,i)+((x1-wall[fw].x)<<8))+((z1-globalposz)<<7);
2058
2059
2060 if (pvWalls[w].screenSpaceCoo[1][VEC_COL] == xdimen-1){
2061 xv = cosglobalang-sinviewingrangeglobalang;
2062 yv = singlobalang+cosviewingrangeglobalang;
2063 }
2064 else{
2065 xv = (x2+x1)-globalposx;
2066 yv = (y2+y1)-globalposy;
2067 }
2068
2069 i = xv*(y1-globalposy)-yv*(x1-globalposx);
2070 j = yv*x2-xv*y2;
2071
2072 if (klabs(j) > klabs(i>>3))
2073 i = divscale28(i,j);
2074
2075 if (dastat == 0){
2076 t = mulscale15(sector[sectnum].ceilingheinum,dasqr);
2077 z2 = sector[sectnum].ceilingz;
2078 }
2079 else{
2080 t = mulscale15(sector[sectnum].floorheinum,dasqr);
2081 z2 = sector[sectnum].floorz;
2082 }
2083
2084 z2 = dmulscale24(dx*t,mulscale20(y2,i)+((y1-wall[fw].y)<<8),-dy*t,mulscale20(x2,i)+((x1-wall[fw].x)<<8))+((z2-globalposz)<<7);
2085
2086
2087 s1 = mulscale20(globaluclip,pvWalls[w].screenSpaceCoo[0][VEC_DIST]);
2088 s2 = mulscale20(globaluclip,pvWalls[w].screenSpaceCoo[1][VEC_DIST]);
2089 s3 = mulscale20(globaldclip,pvWalls[w].screenSpaceCoo[0][VEC_DIST]);
2090 s4 = mulscale20(globaldclip,pvWalls[w].screenSpaceCoo[1][VEC_DIST]);
2091 bad = (z1<s1)+((z2<s2)<<1)+((z1>s3)<<2)+((z2>s4)<<3);
2092
2093 ix1 = pvWalls[w].screenSpaceCoo[0][VEC_COL];
2094 ix2 = pvWalls[w].screenSpaceCoo[1][VEC_COL];
2095 iy1 = pvWalls[w].screenSpaceCoo[0][VEC_DIST];
2096 iy2 = pvWalls[w].screenSpaceCoo[1][VEC_DIST];
2097 oz1 = z1;
2098 oz2 = z2;
2099
2100 if ((bad&3) == 3){
2101 clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),0L);
2102 return(bad);
2103 }
2104
2105 if ((bad&12) == 12){
2106 clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
2107 return(bad);
2108 }
2109
2110 if (bad&3){
2111 /* inty = intz / (globaluclip>>16) */
2112 t = divscale30(oz1-s1,s2-s1+oz1-oz2);
2113 inty = pvWalls[w].screenSpaceCoo[0][VEC_DIST] + mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST]-pvWalls[w].screenSpaceCoo[0][VEC_DIST],t);
2114 intz = oz1 + mulscale30(oz2-oz1,t);
2115 xcross = pvWalls[w].screenSpaceCoo[0][VEC_COL] + scale(mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST],t),pvWalls[w].screenSpaceCoo[1][VEC_COL]-pvWalls[w].screenSpaceCoo[0][VEC_COL],inty);
2116
2117 if ((bad&3) == 2){
2118 if (pvWalls[w].screenSpaceCoo[0][VEC_COL] <= xcross){
2119 z2 = intz;
2120 iy2 = inty;
2121 ix2 = xcross;
2122 }
2123 clearbufbyte(&mostbuf[xcross+1],(pvWalls[w].screenSpaceCoo[1][VEC_COL]-xcross)*sizeof(mostbuf[0]),0L);
2124 }
2125 else{
2126 if (xcross <= pvWalls[w].screenSpaceCoo[1][VEC_COL]) {
2127 z1 = intz;
2128 iy1 = inty;
2129 ix1 = xcross;
2130 }
2131 clearbufbyte(&mostbuf[pvWalls[w].screenSpaceCoo[0][VEC_COL]],(xcross-pvWalls[w].screenSpaceCoo[0][VEC_COL]+1)*sizeof(mostbuf[0]),0L);
2132 }
2133 }
2134
2135 if (bad&12){
2136 /* inty = intz / (globaldclip>>16) */
2137 t = divscale30(oz1-s3,s4-s3+oz1-oz2);
2138 inty = pvWalls[w].screenSpaceCoo[0][VEC_DIST] + mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST]-pvWalls[w].screenSpaceCoo[0][VEC_DIST],t);
2139 intz = oz1 + mulscale30(oz2-oz1,t);
2140 xcross = pvWalls[w].screenSpaceCoo[0][VEC_COL] + scale(mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST],t),pvWalls[w].screenSpaceCoo[1][VEC_COL]-pvWalls[w].screenSpaceCoo[0][VEC_COL],inty);
2141
2142 if ((bad&12) == 8){
2143 if (pvWalls[w].screenSpaceCoo[0][VEC_COL] <= xcross) {
2144 z2 = intz;
2145 iy2 = inty;
2146 ix2 = xcross;
2147 }
2148 clearbufbyte(&mostbuf[xcross+1],(pvWalls[w].screenSpaceCoo[1][VEC_COL]-xcross)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
2149 }
2150 else{
2151 if (xcross <= pvWalls[w].screenSpaceCoo[1][VEC_COL]) {
2152 z1 = intz;
2153 iy1 = inty;
2154 ix1 = xcross;
2155 }
2156 clearbufbyte(&mostbuf[pvWalls[w].screenSpaceCoo[0][VEC_COL]],(xcross-pvWalls[w].screenSpaceCoo[0][VEC_COL]+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
2157 }
2158 }
2159
2160 y = (scale(z1,xdimenscale,iy1)<<4);
2161 yinc = ((scale(z2,xdimenscale,iy2)<<4)-y) / (ix2-ix1+1);
2162 qinterpolatedown16short((int32_t *)&mostbuf[ix1],ix2-ix1+1,y+(globalhoriz<<16),yinc);
2163
2164 if (mostbuf[ix1] < 0)
2165 mostbuf[ix1] = 0;
2166 if (mostbuf[ix1] > ydimen)
2167 mostbuf[ix1] = ydimen;
2168 if (mostbuf[ix2] < 0)
2169 mostbuf[ix2] = 0;
2170 if (mostbuf[ix2] > ydimen)
2171 mostbuf[ix2] = ydimen;
2172
2173 return(bad);
2174}
2175
2176
2177static void drawalls(int32_t bunch)
2178{
2179 sectortype *sec, *nextsec;
2180 walltype *wal;
2181 int32_t i, x, x1, x2, cz[5], fz[5];
2182 int32_t z, wallnum, sectnum, nextsectnum;
2183 int32_t startsmostwallcnt, startsmostcnt, gotswall;
2184 uint8_t andwstat1, andwstat2;
2185
2186 z = bunchfirst[bunch];
2187 sectnum = pvWalls[z].sectorId;
2188 sec = &sector[sectnum];
2189
2190 andwstat1 = 0xff;
2191 andwstat2 = 0xff;
2192 for(; z>=0; z=bunchWallsList[z]){ /* uplc/dplc calculation */
2193
2194 andwstat1 &= wallmost(uplc,z,sectnum,(uint8_t )0);
2195 andwstat2 &= wallmost(dplc,z,sectnum,(uint8_t )1);
2196 }
2197
2198 /* draw ceilings */
2199 if ((andwstat1&3) != 3){
2200 if ((sec->ceilingstat&3) == 2)
2201 grouscan(pvWalls[bunchfirst[bunch]].screenSpaceCoo[0][VEC_COL],pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],sectnum,0);
2202 else if ((sec->ceilingstat&1) == 0)
2203 ceilscan(pvWalls[bunchfirst[bunch]].screenSpaceCoo[0][VEC_COL],pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],sectnum);
2204 else
2205 parascan(pvWalls[bunchfirst[bunch]].screenSpaceCoo[0][VEC_COL],pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],sectnum,0,bunch);
2206 }
2207
2208 /* draw floors */
2209 if ((andwstat2&12) != 12){
2210 if ((sec->floorstat&3) == 2)
2211 grouscan(pvWalls[bunchfirst[bunch]].screenSpaceCoo[0][VEC_COL],pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],sectnum,1);
2212 else if ((sec->floorstat&1) == 0)
2213 florscan(pvWalls[bunchfirst[bunch]].screenSpaceCoo[0][VEC_COL],pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],sectnum);
2214 else
2215 parascan(pvWalls[bunchfirst[bunch]].screenSpaceCoo[0][VEC_COL],pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],sectnum,1,bunch);
2216 }
2217
2218 /* DRAW WALLS SECTION! */
2219 for(z=bunchfirst[bunch]; z>=0; z=bunchWallsList[z]){
2220
2221 x1 = pvWalls[z].screenSpaceCoo[0][VEC_COL];
2222 x2 = pvWalls[z].screenSpaceCoo[1][VEC_COL];
2223 if (umost[x2] >= dmost[x2])
2224 {
2225
2226 for(x=x1; x<x2; x++)
2227 if (umost[x] < dmost[x])
2228 break;
2229
2230 if (x >= x2)
2231 {
2232 smostwall[smostwallcnt] = z;
2233 smostwalltype[smostwallcnt] = 0;
2234 smostwallcnt++;
2235 continue;
2236 }
2237 }
2238
2239 wallnum = pvWalls[z].worldWallId;
2240 wal = &wall[wallnum];
2241 nextsectnum = wal->nextsector;
2242 nextsec = &sector[nextsectnum];
2243
2244 gotswall = 0;
2245
2246 startsmostwallcnt = smostwallcnt;
2247 startsmostcnt = smostcnt;
2248
2249 if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
2250 {
2251 if (searchy <= uplc[searchx]){ /* ceiling */
2252 searchsector = sectnum;
2253 searchwall = wallnum;
2254 searchstat = 1;
2255 searchit = 1;
2256 }
2257 else if (searchy >= dplc[searchx]){ /* floor */
2258 searchsector = sectnum;
2259 searchwall = wallnum;
2260 searchstat = 2;
2261 searchit = 1;
2262 }
2263 }
2264
2265 if (nextsectnum >= 0){
2266 getzsofslope((short)sectnum,wal->x,wal->y,&cz[0],&fz[0]);
2267 getzsofslope((short)sectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[1],&fz[1]);
2268 getzsofslope((short)nextsectnum,wal->x,wal->y,&cz[2],&fz[2]);
2269 getzsofslope((short)nextsectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[3],&fz[3]);
2270 getzsofslope((short)nextsectnum,globalposx,globalposy,&cz[4],&fz[4]);
2271
2272 if ((wal->cstat&48) == 16)
2273 maskwall[maskwallcnt++] = z;
2274
2275 if (((sec->ceilingstat&1) == 0) || ((nextsec->ceilingstat&1) == 0)){
2276 if ((cz[2] <= cz[0]) && (cz[3] <= cz[1])){
2277 if (globparaceilclip)
2278 for(x=x1; x<=x2; x++)
2279 if (uplc[x] > umost[x])
2280 if (umost[x] <= dmost[x]){
2281 umost[x] = uplc[x];
2282 if (umost[x] > dmost[x]) numhits--;
2283 }
2284 }
2285 else{
2286 wallmost(dwall,z,nextsectnum,(uint8_t )0);
2287 if ((cz[2] > fz[0]) || (cz[3] > fz[1]))
2288 for(i=x1; i<=x2; i++) if (dwall[i] > dplc[i]) dwall[i] = dplc[i];
2289
2290 if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
2291 if (searchy <= dwall[searchx]) /* wall */{
2292 searchsector = sectnum;
2293 searchwall = wallnum;
2294 searchstat = 0;
2295 searchit = 1;
2296 }
2297
2298 globalorientation = (int32_t)wal->cstat;
2299 globalpicnum = wal->picnum;
2300 if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
2301 globalxpanning = (int32_t)wal->xpanning;
2302 globalypanning = (int32_t)wal->ypanning;
2303 globalshiftval = (picsiz[globalpicnum]>>4);
2304 if (pow2long[globalshiftval] != tiles[globalpicnum].dim.height) globalshiftval++;
2305 globalshiftval = 32-globalshiftval;
2306
2307 //Animated
2308 if (tiles[globalpicnum].animFlags&192)
2309 globalpicnum += animateoffs(globalpicnum);
2310
2311 globalshade = (int32_t)wal->shade;
2312 globvis = globalvisibility;
2313 if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
2314 globalpal = (int32_t)wal->pal;
2315 globalyscale = (wal->yrepeat<<(globalshiftval-19));
2316 if ((globalorientation&4) == 0)
2317 globalzd = (((globalposz-nextsec->ceilingz)*globalyscale)<<8);
2318 else
2319 globalzd = (((globalposz-sec->ceilingz)*globalyscale)<<8);
2320 globalzd += (globalypanning<<24);
2321 if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
2322
2323 if (gotswall == 0) {
2324 gotswall = 1;
2325 prepwall(z,wal);
2326 }
2327 wallscan(x1,x2,uplc,dwall,swall,lwall);
2328
2329 if ((cz[2] >= cz[0]) && (cz[3] >= cz[1])){
2330 for(x=x1; x<=x2; x++)
2331 if (dwall[x] > umost[x])
2332 if (umost[x] <= dmost[x]){
2333 umost[x] = dwall[x];
2334 if (umost[x] > dmost[x]) numhits--;
2335 }
2336 }
2337 else
2338 {
2339 for(x=x1; x<=x2; x++)
2340 if (umost[x] <= dmost[x]){
2341 i = max(uplc[x],dwall[x]);
2342 if (i > umost[x]){
2343 umost[x] = i;
2344 if (umost[x] > dmost[x]) numhits--;
2345 }
2346 }
2347 }
2348 }
2349 if ((cz[2] < cz[0]) || (cz[3] < cz[1]) || (globalposz < cz[4])){
2350 i = x2-x1+1;
2351 if (smostcnt+i < MAXYSAVES){
2352 smoststart[smostwallcnt] = smostcnt;
2353 smostwall[smostwallcnt] = z;
2354 smostwalltype[smostwallcnt] = 1; /* 1 for umost */
2355 smostwallcnt++;
2356 copybufbyte((int32_t *)&umost[x1],(int32_t *)&smost[smostcnt],i*sizeof(smost[0]));
2357 smostcnt += i;
2358 }
2359 }
2360 }
2361 if (((sec->floorstat&1) == 0) || ((nextsec->floorstat&1) == 0)){
2362 if ((fz[2] >= fz[