Permalink
Find file
05ba48e Jan 23, 2013
executable file 8830 lines (7682 sloc) 257 KB
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// Ken Silverman's official web site: "http://www.advsys.net/ken"
// See the included license file "BUILDLIC.TXT" for license info.
#define SUPERBUILD
#define ENGINE
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <fcntl.h>
#include <io.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <conio.h>
#include <i86.h>
#include "build.h"
#include "pragmas.h"
long stereowidth = 23040, stereopixelwidth = 28, ostereopixelwidth = -1;
volatile long stereomode = 0, visualpage, activepage, whiteband, blackband;
volatile char oa1, o3c2, ortca, ortcb, overtbits, laststereoint;
#include "ves2.h"
#pragma intrinsic(min);
#pragma intrinsic(max);
#define MAXCLIPNUM 512
#define MAXPERMS 512
#define MAXTILEFILES 256
#define MAXYSAVES ((MAXXDIM*MAXSPRITES)>>7)
#define MAXNODESPERLINE 42 //Warning: This depends on MAXYSAVES & MAXYDIM!
#define MAXWALLSB 2048
#define MAXCLIPDIST 1024
//MUST CALL MALLOC THIS WAY TO FORCE CALLS TO KMALLOC!
void *kmalloc(size_t size) { return(malloc(size)); }
void *kkmalloc(size_t size);
#pragma aux kkmalloc =\
"call kmalloc",\
parm [eax]\
//MUST CALL FREE THIS WAY TO FORCE CALLS TO KFREE!
void kfree(void *buffer) { free(buffer); }
void kkfree(void *buffer);
#pragma aux kkfree =\
"call kfree",\
parm [eax]\
#ifdef SUPERBUILD
//MUST CALL LOADVOXEL THIS WAY BECAUSE WATCOM STINKS!
void loadvoxel(long voxindex) { }
void kloadvoxel(long voxindex);
#pragma aux kloadvoxel =\
"call loadvoxel",\
parm [eax]\
//These variables need to be copied into BUILD
#define MAXXSIZ 128
#define MAXYSIZ 128
#define MAXZSIZ 200
#define MAXVOXELS 512
#define MAXVOXMIPS 5
long voxoff[MAXVOXELS][MAXVOXMIPS], voxlock[MAXVOXELS][MAXVOXMIPS];
static long ggxinc[MAXXSIZ+1], ggyinc[MAXXSIZ+1];
static long lowrecip[1024], nytooclose, nytoofar;
static unsigned long distrecip[16384];
#endif
static char moustat = 0;
long transarea = 0, totalarea = 0, beforedrawrooms = 1;
static long oxdimen = -1, oviewingrange = -1, oxyaspect = -1;
static long curbrightness = 0;
//Textured Map variables
static char globalpolytype;
static short *dotp1[MAXYDIM], *dotp2[MAXYDIM];
static unsigned char tempbuf[MAXWALLS];
long ebpbak, espbak;
long slopalookup[2048];
static char permanentlock = 255;
long artversion, mapversion;
char *pic = NULL;
char picsiz[MAXTILES], tilefilenum[MAXTILES];
long lastageclock;
long tilefileoffs[MAXTILES];
long artsize = 0, cachesize = 0;
static short radarang[1280], radarang2[MAXXDIM];
static unsigned short sqrtable[4096], shlookup[4096+256];
char pow2char[8] = {1,2,4,8,16,32,64,128};
long pow2long[32] =
{
1L,2L,4L,8L,
16L,32L,64L,128L,
256L,512L,1024L,2048L,
4096L,8192L,16384L,32768L,
65536L,131072L,262144L,524288L,
1048576L,2097152L,4194304L,8388608L,
16777216L,33554432L,67108864L,134217728L,
268435456L,536870912L,1073741824L,2147483647L,
};
long reciptable[2048], fpuasm;
char britable[16][64];
char textfont[1024], smalltextfont[1024];
static char kensmessage[128];
#pragma aux getkensmessagecrc =\
"xor eax, eax",\
"mov ecx, 32",\
"beg: mov edx, dword ptr [ebx+ecx*4-4]",\
"ror edx, cl",\
"adc eax, edx",\
"bswap eax",\
"loop short beg",\
parm [ebx]\
modify exact [eax ebx ecx edx]\
static long xb1[MAXWALLSB], yb1[MAXWALLSB], xb2[MAXWALLSB], yb2[MAXWALLSB];
static long rx1[MAXWALLSB], ry1[MAXWALLSB], rx2[MAXWALLSB], ry2[MAXWALLSB];
static short p2[MAXWALLSB], thesector[MAXWALLSB], thewall[MAXWALLSB];
static short bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB];
static short smost[MAXYSAVES], smostcnt;
static short smoststart[MAXWALLSB];
static char smostwalltype[MAXWALLSB];
static long smostwall[MAXWALLSB], smostwallcnt = -1L;
static short maskwall[MAXWALLSB], maskwallcnt;
static long spritesx[MAXSPRITESONSCREEN];
static long spritesy[MAXSPRITESONSCREEN+1];
static long spritesz[MAXSPRITESONSCREEN];
static spritetype *tspriteptr[MAXSPRITESONSCREEN];
short umost[MAXXDIM], dmost[MAXXDIM];
static short bakumost[MAXXDIM], bakdmost[MAXXDIM];
short uplc[MAXXDIM], dplc[MAXXDIM];
static short uwall[MAXXDIM], dwall[MAXXDIM];
static long swplc[MAXXDIM], lplc[MAXXDIM];
static long swall[MAXXDIM], lwall[MAXXDIM+4];
long xdimen = -1, xdimenrecip, halfxdimen, xdimenscale, xdimscale;
long wx1, wy1, wx2, wy2, ydimen;
long viewoffset, frameoffset;
static long rxi[8], ryi[8], rzi[8], rxi2[8], ryi2[8], rzi2[8];
static long xsi[8], ysi[8], *horizlookup, *horizlookup2, horizycent;
long globalposx, globalposy, globalposz, globalhoriz;
short globalang, globalcursectnum;
long globalpal, cosglobalang, singlobalang;
long cosviewingrangeglobalang, sinviewingrangeglobalang;
char *globalpalwritten;
long globaluclip, globaldclip, globvis;
long globalvisibility, globalhisibility, globalpisibility, globalcisibility;
char globparaceilclip, globparaflorclip;
long xyaspect, viewingrangerecip;
long asm1, asm2, asm3, asm4;
long vplce[4], vince[4], palookupoffse[4], bufplce[4];
char globalxshift, globalyshift;
long globalxpanning, globalypanning, globalshade;
short globalpicnum, globalshiftval;
long globalzd, globalbufplc, globalyscale, globalorientation;
long globalx1, globaly1, globalx2, globaly2, globalx3, globaly3, globalzx;
long globalx, globaly, globalz;
static short sectorborder[256], sectorbordercnt;
static char tablesloaded = 0;
long pageoffset, ydim16, qsetmode = 0;
long startposx, startposy, startposz;
short startang, startsectnum;
short pointhighlight, linehighlight, highlightcnt;
static long lastx[MAXYDIM];
char *transluc = NULL, paletteloaded = 0;
#define FASTPALGRIDSIZ 8
static long rdist[129], gdist[129], bdist[129];
static char colhere[((FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2))>>3];
static char colhead[(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)];
static long colnext[256];
static char coldist[8] = {0,1,2,3,4,3,2,1};
static long colscan[27];
static short clipnum, hitwalls[4];
long hitscangoalx = (1<<29)-1, hitscangoaly = (1<<29)-1;
typedef struct { long x1, y1, x2, y2; } linetype;
static linetype clipit[MAXCLIPNUM];
static short clipsectorlist[MAXCLIPNUM], clipsectnum;
static short clipobjectval[MAXCLIPNUM];
typedef struct
{
long sx, sy, z;
short a, picnum;
signed char dashade;
char dapalnum, dastat, pagesleft;
long cx1, cy1, cx2, cy2;
} permfifotype;
static permfifotype permfifo[MAXPERMS];
static long permhead = 0, permtail = 0;
short numscans, numhits, numbunches;
static short posfil, capturecount = 0, hitcnt;
static char pcxheader[128] =
{
0xa,0x5,0x1,0x8,0x0,0x0,0x0,0x0,0x3f,0x1,0xc7,0x0,
0x40,0x1,0xc8,0x0,0x0,0x0,0x0,0x8,0x8,0x8,0x10,0x10,
0x10,0x18,0x18,0x18,0x20,0x20,0x20,0x28,0x28,0x28,0x30,0x30,
0x30,0x38,0x38,0x38,0x40,0x40,0x40,0x48,0x48,0x48,0x50,0x50,
0x50,0x58,0x58,0x58,0x60,0x60,0x60,0x68,0x68,0x68,0x70,0x70,
0x70,0x78,0x78,0x78,0x0,0x1,0x40,0x1,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
};
static char vgapal16[48] =
{
00,00,00,00,00,42,00,42,00,00,42,42,42,00,00,42,00,42,42,21,00,42,42,42,
21,21,21,21,21,63,21,63,21,21,63,63,63,21,21,63,21,63,63,63,21,63,63,63,
};
short editstatus = 0;
short searchit;
long searchx = -1, searchy; //search input
short searchsector, searchwall, searchstat; //search output
static char artfilename[20];
static long numtilefiles, artfil = -1, artfilnum, artfilplc;
static char inpreparemirror = 0;
static long mirrorsx1, mirrorsy1, mirrorsx2, mirrorsy2;
long totalclocklock;
extern long mmxoverlay();
#pragma aux mmxoverlay modify [eax ebx ecx edx];
extern long sethlinesizes(long,long,long);
#pragma aux sethlinesizes parm [eax][ebx][ecx];
extern long setpalookupaddress(char *);
#pragma aux setpalookupaddress parm [eax];
extern long setuphlineasm4(long,long);
#pragma aux setuphlineasm4 parm [eax][ebx];
extern long hlineasm4(long,long,long,long,long,long);
#pragma aux hlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
extern long setuprhlineasm4(long,long,long,long,long,long);
#pragma aux setuprhlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
extern long rhlineasm4(long,long,long,long,long,long);
#pragma aux rhlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
extern long setuprmhlineasm4(long,long,long,long,long,long);
#pragma aux setuprmhlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
extern long rmhlineasm4(long,long,long,long,long,long);
#pragma aux rmhlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
extern long setupqrhlineasm4(long,long,long,long,long,long);
#pragma aux setupqrhlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
extern long qrhlineasm4(long,long,long,long,long,long);
#pragma aux qrhlineasm4 parm [eax][ebx][ecx][edx][esi][edi];
extern long setvlinebpl(long);
#pragma aux setvlinebpl parm [eax];
extern long fixtransluscence(long);
#pragma aux fixtransluscence parm [eax];
extern long prevlineasm1(long,long,long,long,long,long);
#pragma aux prevlineasm1 parm [eax][ebx][ecx][edx][esi][edi];
extern long vlineasm1(long,long,long,long,long,long);
#pragma aux vlineasm1 parm [eax][ebx][ecx][edx][esi][edi];
extern long setuptvlineasm(long);
#pragma aux setuptvlineasm parm [eax];
extern long tvlineasm1(long,long,long,long,long,long);
#pragma aux tvlineasm1 parm [eax][ebx][ecx][edx][esi][edi];
extern long setuptvlineasm2(long,long,long);
#pragma aux setuptvlineasm2 parm [eax][ebx][ecx];
extern long tvlineasm2(long,long,long,long,long,long);
#pragma aux tvlineasm2 parm [eax][ebx][ecx][edx][esi][edi];
extern long mvlineasm1(long,long,long,long,long,long);
#pragma aux mvlineasm1 parm [eax][ebx][ecx][edx][esi][edi];
extern long setupvlineasm(long);
#pragma aux setupvlineasm parm [eax];
extern long vlineasm4(long,long);
#pragma aux vlineasm4 parm [ecx][edi] modify [eax ebx ecx edx esi edi];
extern long setupmvlineasm(long);
#pragma aux setupmvlineasm parm [eax];
extern long mvlineasm4(long,long);
#pragma aux mvlineasm4 parm [ecx][edi] modify [eax ebx ecx edx esi edi];
extern void setupspritevline(long,long,long,long,long,long);
#pragma aux setupspritevline parm [eax][ebx][ecx][edx][esi][edi];
extern void spritevline(long,long,long,long,long,long);
#pragma aux spritevline parm [eax][ebx][ecx][edx][esi][edi];
extern void msetupspritevline(long,long,long,long,long,long);
#pragma aux msetupspritevline parm [eax][ebx][ecx][edx][esi][edi];
extern void mspritevline(long,long,long,long,long,long);
#pragma aux mspritevline parm [eax][ebx][ecx][edx][esi][edi];
extern void tsetupspritevline(long,long,long,long,long,long);
#pragma aux tsetupspritevline parm [eax][ebx][ecx][edx][esi][edi];
extern void tspritevline(long,long,long,long,long,long);
#pragma aux tspritevline parm [eax][ebx][ecx][edx][esi][edi];
extern long mhline(long,long,long,long,long,long);
#pragma aux mhline parm [eax][ebx][ecx][edx][esi][edi];
extern long mhlineskipmodify(long,long,long,long,long,long);
#pragma aux mhlineskipmodify parm [eax][ebx][ecx][edx][esi][edi];
extern long msethlineshift(long,long);
#pragma aux msethlineshift parm [eax][ebx];
extern long thline(long,long,long,long,long,long);
#pragma aux thline parm [eax][ebx][ecx][edx][esi][edi];
extern long thlineskipmodify(long,long,long,long,long,long);
#pragma aux thlineskipmodify parm [eax][ebx][ecx][edx][esi][edi];
extern long tsethlineshift(long,long);
#pragma aux tsethlineshift parm [eax][ebx];
extern long setupslopevlin(long,long,long);
#pragma aux setupslopevlin parm [eax][ebx][ecx] modify [edx];
extern long slopevlin(long,long,long,long,long,long);
#pragma aux slopevlin parm [eax][ebx][ecx][edx][esi][edi];
extern long settransnormal();
#pragma aux settransnormal parm;
extern long settransreverse();
#pragma aux settransreverse parm;
extern long setupdrawslab(long,long);
#pragma aux setupdrawslab parm [eax][ebx];
extern long drawslab(long,long,long,long,long,long);
#pragma aux drawslab parm [eax][ebx][ecx][edx][esi][edi];
#pragma aux nsqrtasm =\
"test eax, 0xff000000",\
"mov ebx, eax",\
"jnz short over24",\
"shr ebx, 12",\
"mov cx, word ptr shlookup[ebx*2]",\
"jmp short under24",\
"over24: shr ebx, 24",\
"mov cx, word ptr shlookup[ebx*2+8192]",\
"under24: shr eax, cl",\
"mov cl, ch",\
"mov ax, word ptr sqrtable[eax*2]",\
"shr eax, cl",\
parm nomemory [eax]\
modify exact [eax ebx ecx]\
#pragma aux msqrtasm =\
"mov eax, 0x40000000",\
"mov ebx, 0x20000000",\
"begit: cmp ecx, eax",\
"jl skip",\
"sub ecx, eax",\
"lea eax, [eax+ebx*4]",\
"skip: sub eax, ebx",\
"shr eax, 1",\
"shr ebx, 2",\
"jnz begit",\
"cmp ecx, eax",\
"sbb eax, -1",\
"shr eax, 1",\
parm nomemory [ecx]\
modify exact [eax ebx ecx]\
//0x007ff000 is (11<<13), 0x3f800000 is (127<<23)
#pragma aux krecipasm =\
"mov fpuasm, eax",\
"fild dword ptr fpuasm",\
"add eax, eax",\
"fstp dword ptr fpuasm",\
"sbb ebx, ebx",\
"mov eax, fpuasm",\
"mov ecx, eax",\
"and eax, 0x007ff000",\
"shr eax, 10",\
"sub ecx, 0x3f800000",\
"shr ecx, 23",\
"mov eax, dword ptr reciptable[eax]",\
"sar eax, cl",\
"xor eax, ebx",\
parm [eax]\
modify exact [eax ebx ecx]\
#pragma aux setgotpic =\
"mov ebx, eax",\
"cmp byte ptr walock[eax], 200",\
"jae skipit",\
"mov byte ptr walock[eax], 199",\
"skipit: shr eax, 3",\
"and ebx, 7",\
"mov dl, byte ptr gotpic[eax]",\
"mov bl, byte ptr pow2char[ebx]",\
"or dl, bl",\
"mov byte ptr gotpic[eax], dl",\
parm [eax]\
modify exact [eax ebx ecx edx]\
#pragma aux getclipmask =\
"sar eax, 31",\
"add ebx, ebx",\
"adc eax, eax",\
"add ecx, ecx",\
"adc eax, eax",\
"add edx, edx",\
"adc eax, eax",\
"mov ebx, eax",\
"shl ebx, 4",\
"or al, 0xf0",\
"xor eax, ebx",\
parm [eax][ebx][ecx][edx]\
modify exact [eax ebx ecx edx]\
drawrooms(long daposx, long daposy, long daposz,
short daang, long dahoriz, short dacursectnum)
{
long i, j, z, cz, fz, closest;
short *shortptr1, *shortptr2;
beforedrawrooms = 0;
totalarea += (windowx2+1-windowx1)*(windowy2+1-windowy1);
globalposx = daposx; globalposy = daposy; globalposz = daposz;
globalang = (daang&2047);
globalhoriz = mulscale16(dahoriz-100,xdimenscale)+(ydimen>>1);
globaluclip = (0-globalhoriz)*xdimscale;
globaldclip = (ydimen-globalhoriz)*xdimscale;
i = mulscale16(xdimenscale,viewingrangerecip);
globalpisibility = mulscale16(parallaxvisibility,i);
globalvisibility = mulscale16(visibility,i);
globalhisibility = mulscale16(globalvisibility,xyaspect);
globalcisibility = mulscale8(globalhisibility,320);
globalcursectnum = dacursectnum;
totalclocklock = totalclock;
cosglobalang = sintable[(globalang+512)&2047];
singlobalang = sintable[globalang&2047];
cosviewingrangeglobalang = mulscale16(cosglobalang,viewingrange);
sinviewingrangeglobalang = mulscale16(singlobalang,viewingrange);
if ((stereomode != 0) || (vidoption == 6))
{
if (stereopixelwidth != ostereopixelwidth)
{
ostereopixelwidth = stereopixelwidth;
xdimen = (windowx2-windowx1+1)+(stereopixelwidth<<1); halfxdimen = (xdimen>>1);
xdimenrecip = divscale32(1L,xdimen);
setaspect((long)divscale16(xdimen,windowx2-windowx1+1),yxaspect);
}
if ((!(activepage&1)) ^ inpreparemirror)
{
for(i=windowx1;i<windowx1+(stereopixelwidth<<1);i++) { startumost[i] = 1, startdmost[i] = 0; }
for(;i<windowx2+1+(stereopixelwidth<<1);i++) { startumost[i] = windowy1, startdmost[i] = windowy2+1; }
viewoffset = windowy1*bytesperline+windowx1-(stereopixelwidth<<1);
i = stereowidth;
}
else
{
for(i=windowx1;i<windowx2+1;i++) { startumost[i] = windowy1, startdmost[i] = windowy2+1; }
for(;i<windowx2+1+(stereopixelwidth<<1);i++) { startumost[i] = 1, startdmost[i] = 0; }
viewoffset = windowy1*bytesperline+windowx1;
i = -stereowidth;
}
globalposx += mulscale24(singlobalang,i);
globalposy -= mulscale24(cosglobalang,i);
if (vidoption == 6) frameplace = FP_OFF(screen)+(activepage&1)*65536;
}
if ((xyaspect != oxyaspect) || (xdimen != oxdimen) || (viewingrange != oviewingrange))
dosetaspect();
frameoffset = frameplace+viewoffset;
clearbufbyte((long)(&gotsector[0]),(long)((numsectors+7)>>3),0L);
shortptr1 = (short *)&startumost[windowx1];
shortptr2 = (short *)&startdmost[windowx1];
i = xdimen-1;
do
{
umost[i] = shortptr1[i]-windowy1;
dmost[i] = shortptr2[i]-windowy1;
i--;
} while (i != 0);
umost[0] = shortptr1[0]-windowy1;
dmost[0] = shortptr2[0]-windowy1;
if (smostwallcnt < 0)
if (getkensmessagecrc(FP_OFF(kensmessage)) != 0x56c764d4)
{ setvmode(0x3); printf("Nice try.\n"); exit(0); }
numhits = xdimen; numscans = 0; numbunches = 0;
maskwallcnt = 0; smostwallcnt = 0; smostcnt = 0; spritesortcnt = 0;
if (globalcursectnum >= MAXSECTORS)
globalcursectnum -= MAXSECTORS;
else
{
i = globalcursectnum;
updatesector(globalposx,globalposy,&globalcursectnum);
if (globalcursectnum < 0) globalcursectnum = i;
}
globparaceilclip = 1;
globparaflorclip = 1;
getzsofslope(globalcursectnum,globalposx,globalposy,&cz,&fz);
if (globalposz < cz) globparaceilclip = 0;
if (globalposz > fz) globparaflorclip = 0;
scansector(globalcursectnum);
if (inpreparemirror)
{
inpreparemirror = 0;
mirrorsx1 = xdimen-1; mirrorsx2 = 0;
for(i=numscans-1;i>=0;i--)
{
if (wall[thewall[i]].nextsector < 0) continue;
if (xb1[i] < mirrorsx1) mirrorsx1 = xb1[i];
if (xb2[i] > mirrorsx2) mirrorsx2 = xb2[i];
}
if (stereomode)
{
mirrorsx1 += (stereopixelwidth<<1);
mirrorsx2 += (stereopixelwidth<<1);
}
for(i=0;i<mirrorsx1;i++)
if (umost[i] <= dmost[i])
{ umost[i] = 1; dmost[i] = 0; numhits--; }
for(i=mirrorsx2+1;i<xdimen;i++)
if (umost[i] <= dmost[i])
{ umost[i] = 1; dmost[i] = 0; numhits--; }
drawalls(0L);
numbunches--;
bunchfirst[0] = bunchfirst[numbunches];
bunchlast[0] = bunchlast[numbunches];
mirrorsy1 = min(umost[mirrorsx1],umost[mirrorsx2]);
mirrorsy2 = max(dmost[mirrorsx1],dmost[mirrorsx2]);
}
while ((numbunches > 0) && (numhits > 0))
{
clearbuf((long)(&tempbuf[0]),(long)((numbunches+3)>>2),0L);
tempbuf[0] = 1;
closest = 0; //Almost works, but not quite :(
for(i=1;i<numbunches;i++)
{
if ((j = bunchfront(i,closest)) < 0) continue;
tempbuf[i] = 1;
if (j == 0) tempbuf[closest] = 1, closest = i;
}
for(i=0;i<numbunches;i++) //Double-check
{
if (tempbuf[i]) continue;
if ((j = bunchfront(i,closest)) < 0) continue;
tempbuf[i] = 1;
if (j == 0) tempbuf[closest] = 1, closest = i, i = 0;
}
drawalls(closest);
if (automapping)
{
for(z=bunchfirst[closest];z>=0;z=p2[z])
show2dwall[thewall[z]>>3] |= pow2char[thewall[z]&7];
}
numbunches--;
bunchfirst[closest] = bunchfirst[numbunches];
bunchlast[closest] = bunchlast[numbunches];
}
}
scansector (short sectnum)
{
walltype *wal, *wal2;
spritetype *spr;
long i, xs, ys, xp, yp, x1, y1, x2, y2, xp1, yp1, xp2, yp2, templong;
short z, zz, startwall, endwall, numscansbefore, scanfirst, bunchfrst;
short nextsectnum;
if (sectnum < 0) return;
if (automapping) show2dsector[sectnum>>3] |= pow2char[sectnum&7];
sectorborder[0] = sectnum, sectorbordercnt = 1;
do
{
sectnum = sectorborder[--sectorbordercnt];
for(z=headspritesect[sectnum];z>=0;z=nextspritesect[z])
{
spr = &sprite[z];
if ((((spr->cstat&0x8000) == 0) || (showinvisibility)) &&
(spr->xrepeat > 0) && (spr->yrepeat > 0) &&
(spritesortcnt < MAXSPRITESONSCREEN))
{
xs = spr->x-globalposx; ys = spr->y-globalposy;
if ((spr->cstat&48) || (xs*cosglobalang+ys*singlobalang > 0))
{
copybufbyte(spr,&tsprite[spritesortcnt],sizeof(spritetype));
tsprite[spritesortcnt++].owner = z;
}
}
}
gotsector[sectnum>>3] |= pow2char[sectnum&7];
bunchfrst = numbunches;
numscansbefore = numscans;
startwall = sector[sectnum].wallptr;
endwall = startwall + sector[sectnum].wallnum;
scanfirst = numscans;
for(z=startwall,wal=&wall[z];z<endwall;z++,wal++)
{
nextsectnum = wal->nextsector;
wal2 = &wall[wal->point2];
x1 = wal->x-globalposx; y1 = wal->y-globalposy;
x2 = wal2->x-globalposx; y2 = wal2->y-globalposy;
if ((nextsectnum >= 0) && ((wal->cstat&32) == 0))
if ((gotsector[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0)
{
templong = x1*y2-x2*y1;
if (((unsigned)templong+262144) < 524288)
if (mulscale5(templong,templong) <= (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
sectorborder[sectorbordercnt++] = nextsectnum;
}
if ((z == startwall) || (wall[z-1].point2 != z))
{
xp1 = dmulscale6(y1,cosglobalang,-x1,singlobalang);
yp1 = dmulscale6(x1,cosviewingrangeglobalang,y1,sinviewingrangeglobalang);
}
else
{
xp1 = xp2;
yp1 = yp2;
}
xp2 = dmulscale6(y2,cosglobalang,-x2,singlobalang);
yp2 = dmulscale6(x2,cosviewingrangeglobalang,y2,sinviewingrangeglobalang);
if ((yp1 < 256) && (yp2 < 256)) goto skipitaddwall;
//If wall's NOT facing you
if (dmulscale32(xp1,yp2,-xp2,yp1) >= 0) goto skipitaddwall;
if (xp1 >= -yp1)
{
if ((xp1 > yp1) || (yp1 == 0)) goto skipitaddwall;
xb1[numscans] = halfxdimen + scale(xp1,halfxdimen,yp1);
if (xp1 >= 0) xb1[numscans]++; //Fix for SIGNED divide
if (xb1[numscans] >= xdimen) xb1[numscans] = xdimen-1;
yb1[numscans] = yp1;
}
else
{
if (xp2 < -yp2) goto skipitaddwall;
xb1[numscans] = 0;
templong = yp1-yp2+xp1-xp2;
if (templong == 0) goto skipitaddwall;
yb1[numscans] = yp1 + scale(yp2-yp1,xp1+yp1,templong);
}
if (yb1[numscans] < 256) goto skipitaddwall;
if (xp2 <= yp2)
{
if ((xp2 < -yp2) || (yp2 == 0)) goto skipitaddwall;
xb2[numscans] = halfxdimen + scale(xp2,halfxdimen,yp2) - 1;
if (xp2 >= 0) xb2[numscans]++; //Fix for SIGNED divide
if (xb2[numscans] >= xdimen) xb2[numscans] = xdimen-1;
yb2[numscans] = yp2;
}
else
{
if (xp1 > yp1) goto skipitaddwall;
xb2[numscans] = xdimen-1;
templong = xp2-xp1+yp1-yp2;
if (templong == 0) goto skipitaddwall;
yb2[numscans] = yp1 + scale(yp2-yp1,yp1-xp1,templong);
}
if ((yb2[numscans] < 256) || (xb1[numscans] > xb2[numscans])) goto skipitaddwall;
//Made it all the way!
thesector[numscans] = sectnum; thewall[numscans] = z;
rx1[numscans] = xp1; ry1[numscans] = yp1;
rx2[numscans] = xp2; ry2[numscans] = yp2;
p2[numscans] = numscans+1;
numscans++;
skipitaddwall:
if ((wall[z].point2 < z) && (scanfirst < numscans))
p2[numscans-1] = scanfirst, scanfirst = numscans;
}
for(z=numscansbefore;z<numscans;z++)
if ((wall[thewall[z]].point2 != thewall[p2[z]]) || (xb2[z] >= xb1[p2[z]]))
bunchfirst[numbunches++] = p2[z], p2[z] = -1;
for(z=bunchfrst;z<numbunches;z++)
{
for(zz=bunchfirst[z];p2[zz]>=0;zz=p2[zz]);
bunchlast[z] = zz;
}
} while (sectorbordercnt > 0);
}
wallfront (long l1, long l2)
{
walltype *wal;
long x11, y11, x21, y21, x12, y12, x22, y22, dx, dy, t1, t2;
wal = &wall[thewall[l1]]; x11 = wal->x; y11 = wal->y;
wal = &wall[wal->point2]; x21 = wal->x; y21 = wal->y;
wal = &wall[thewall[l2]]; x12 = wal->x; y12 = wal->y;
wal = &wall[wal->point2]; x22 = wal->x; y22 = wal->y;
dx = x21-x11; dy = y21-y11;
t1 = dmulscale2(x12-x11,dy,-dx,y12-y11); //p1(l2) vs. l1
t2 = dmulscale2(x22-x11,dy,-dx,y22-y11); //p2(l2) vs. l1
if (t1 == 0) { t1 = t2; if (t1 == 0) return(-1); }
if (t2 == 0) t2 = t1;
if ((t1^t2) >= 0)
{
t2 = dmulscale2(globalposx-x11,dy,-dx,globalposy-y11); //pos vs. l1
return((t2^t1) >= 0);
}
dx = x22-x12; dy = y22-y12;
t1 = dmulscale2(x11-x12,dy,-dx,y11-y12); //p1(l1) vs. l2
t2 = dmulscale2(x21-x12,dy,-dx,y21-y12); //p2(l1) vs. l2
if (t1 == 0) { t1 = t2; if (t1 == 0) return(-1); }
if (t2 == 0) t2 = t1;
if ((t1^t2) >= 0)
{
t2 = dmulscale2(globalposx-x12,dy,-dx,globalposy-y12); //pos vs. l2
return((t2^t1) < 0);
}
return(-2);
}
spritewallfront (spritetype *s, long w)
{
walltype *wal;
long x1, y1;
wal = &wall[w]; x1 = wal->x; y1 = wal->y;
wal = &wall[wal->point2];
return (dmulscale32(wal->x-x1,s->y-y1,-(s->x-x1),wal->y-y1) >= 0);
}
bunchfront (long b1, long b2)
{
long x1b1, x2b1, x1b2, x2b2, b1f, b2f, i;
b1f = bunchfirst[b1]; x1b1 = xb1[b1f]; x2b2 = xb2[bunchlast[b2]]+1;
if (x1b1 >= x2b2) return(-1);
b2f = bunchfirst[b2]; x1b2 = xb1[b2f]; x2b1 = xb2[bunchlast[b1]]+1;
if (x1b2 >= x2b1) return(-1);
if (x1b1 >= x1b2)
{
for(i=b2f;xb2[i]<x1b1;i=p2[i]);
return(wallfront(b1f,i));
}
for(i=b1f;xb2[i]<x1b2;i=p2[i]);
return(wallfront(i,b2f));
}
drawalls (long bunch)
{
sectortype *sec, *nextsec;
walltype *wal;
long i, j, k, l, m, n, x, y, x1, x2, cz[5], fz[5];
long z, wallnum, sectnum, nextsectnum, globalhorizbak;
long startsmostwallcnt, startsmostcnt, gotswall;
char andwstat1, andwstat2;
z = bunchfirst[bunch];
sectnum = thesector[z]; sec = &sector[sectnum];
andwstat1 = 0xff; andwstat2 = 0xff;
for(;z>=0;z=p2[z]) //uplc/dplc calculation
{
andwstat1 &= wallmost(uplc,z,sectnum,(char)0);
andwstat2 &= wallmost(dplc,z,sectnum,(char)1);
}
if ((andwstat1&3) != 3) //draw ceilings
{
if ((sec->ceilingstat&3) == 2)
grouscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,0);
else if ((sec->ceilingstat&1) == 0)
ceilscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum);
else
parascan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,0,bunch);
}
if ((andwstat2&12) != 12) //draw floors
{
if ((sec->floorstat&3) == 2)
grouscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,1);
else if ((sec->floorstat&1) == 0)
florscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum);
else
parascan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,1,bunch);
}
//DRAW WALLS SECTION!
for(z=bunchfirst[bunch];z>=0;z=p2[z])
{
x1 = xb1[z]; x2 = xb2[z];
if (umost[x2] >= dmost[x2])
{
for(x=x1;x<x2;x++)
if (umost[x] < dmost[x]) break;
if (x >= x2)
{
smostwall[smostwallcnt] = z;
smostwalltype[smostwallcnt] = 0;
smostwallcnt++;
continue;
}
}
wallnum = thewall[z]; wal = &wall[wallnum];
nextsectnum = wal->nextsector; nextsec = &sector[nextsectnum];
gotswall = 0;
startsmostwallcnt = smostwallcnt;
startsmostcnt = smostcnt;
if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
{
if (searchy <= uplc[searchx]) //ceiling
{
searchsector = sectnum; searchwall = wallnum;
searchstat = 1; searchit = 1;
}
else if (searchy >= dplc[searchx]) //floor
{
searchsector = sectnum; searchwall = wallnum;
searchstat = 2; searchit = 1;
}
}
if (nextsectnum >= 0)
{
getzsofslope((short)sectnum,wal->x,wal->y,&cz[0],&fz[0]);
getzsofslope((short)sectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[1],&fz[1]);
getzsofslope((short)nextsectnum,wal->x,wal->y,&cz[2],&fz[2]);
getzsofslope((short)nextsectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[3],&fz[3]);
getzsofslope((short)nextsectnum,globalposx,globalposy,&cz[4],&fz[4]);
if ((wal->cstat&48) == 16) maskwall[maskwallcnt++] = z;
if (((sec->ceilingstat&1) == 0) || ((nextsec->ceilingstat&1) == 0))
{
if ((cz[2] <= cz[0]) && (cz[3] <= cz[1]))
{
if (globparaceilclip)
for(x=x1;x<=x2;x++)
if (uplc[x] > umost[x])
if (umost[x] <= dmost[x])
{
umost[x] = uplc[x];
if (umost[x] > dmost[x]) numhits--;
}
}
else
{
wallmost(dwall,z,nextsectnum,(char)0);
if ((cz[2] > fz[0]) || (cz[3] > fz[1]))
for(i=x1;i<=x2;i++) if (dwall[i] > dplc[i]) dwall[i] = dplc[i];
if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
if (searchy <= dwall[searchx]) //wall
{
searchsector = sectnum; searchwall = wallnum;
searchstat = 0; searchit = 1;
}
globalorientation = (long)wal->cstat;
globalpicnum = wal->picnum;
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
globalxpanning = (long)wal->xpanning;
globalypanning = (long)wal->ypanning;
globalshiftval = (picsiz[globalpicnum]>>4);
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
globalshiftval = 32-globalshiftval;
if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
globalshade = (long)wal->shade;
globvis = globalvisibility;
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
globalpal = (long)wal->pal;
globalyscale = (wal->yrepeat<<(globalshiftval-19));
if ((globalorientation&4) == 0)
globalzd = (((globalposz-nextsec->ceilingz)*globalyscale)<<8);
else
globalzd = (((globalposz-sec->ceilingz)*globalyscale)<<8);
globalzd += (globalypanning<<24);
if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
wallscan(x1,x2,uplc,dwall,swall,lwall);
if ((cz[2] >= cz[0]) && (cz[3] >= cz[1]))
{
for(x=x1;x<=x2;x++)
if (dwall[x] > umost[x])
if (umost[x] <= dmost[x])
{
umost[x] = dwall[x];
if (umost[x] > dmost[x]) numhits--;
}
}
else
{
for(x=x1;x<=x2;x++)
if (umost[x] <= dmost[x])
{
i = max(uplc[x],dwall[x]);
if (i > umost[x])
{
umost[x] = i;
if (umost[x] > dmost[x]) numhits--;
}
}
}
}
if ((cz[2] < cz[0]) || (cz[3] < cz[1]) || (globalposz < cz[4]))
{
i = x2-x1+1;
if (smostcnt+i < MAXYSAVES)
{
smoststart[smostwallcnt] = smostcnt;
smostwall[smostwallcnt] = z;
smostwalltype[smostwallcnt] = 1; //1 for umost
smostwallcnt++;
copybufbyte((long)&umost[x1],(long)&smost[smostcnt],i*sizeof(smost[0]));
smostcnt += i;
}
}
}
if (((sec->floorstat&1) == 0) || ((nextsec->floorstat&1) == 0))
{
if ((fz[2] >= fz[0]) && (fz[3] >= fz[1]))
{
if (globparaflorclip)
for(x=x1;x<=x2;x++)
if (dplc[x] < dmost[x])
if (umost[x] <= dmost[x])
{
dmost[x] = dplc[x];
if (umost[x] > dmost[x]) numhits--;
}
}
else
{
wallmost(uwall,z,nextsectnum,(char)1);
if ((fz[2] < cz[0]) || (fz[3] < cz[1]))
for(i=x1;i<=x2;i++) if (uwall[i] < uplc[i]) uwall[i] = uplc[i];
if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
if (searchy >= uwall[searchx]) //wall
{
searchsector = sectnum; searchwall = wallnum;
if ((wal->cstat&2) > 0) searchwall = wal->nextwall;
searchstat = 0; searchit = 1;
}
if ((wal->cstat&2) > 0)
{
wallnum = wal->nextwall; wal = &wall[wallnum];
globalorientation = (long)wal->cstat;
globalpicnum = wal->picnum;
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
globalxpanning = (long)wal->xpanning;
globalypanning = (long)wal->ypanning;
if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
globalshade = (long)wal->shade;
globalpal = (long)wal->pal;
wallnum = thewall[z]; wal = &wall[wallnum];
}
else
{
globalorientation = (long)wal->cstat;
globalpicnum = wal->picnum;
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
globalxpanning = (long)wal->xpanning;
globalypanning = (long)wal->ypanning;
if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
globalshade = (long)wal->shade;
globalpal = (long)wal->pal;
}
globvis = globalvisibility;
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
globalshiftval = (picsiz[globalpicnum]>>4);
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
globalshiftval = 32-globalshiftval;
globalyscale = (wal->yrepeat<<(globalshiftval-19));
if ((globalorientation&4) == 0)
globalzd = (((globalposz-nextsec->floorz)*globalyscale)<<8);
else
globalzd = (((globalposz-sec->ceilingz)*globalyscale)<<8);
globalzd += (globalypanning<<24);
if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
wallscan(x1,x2,uwall,dplc,swall,lwall);
if ((fz[2] <= fz[0]) && (fz[3] <= fz[1]))
{
for(x=x1;x<=x2;x++)
if (uwall[x] < dmost[x])
if (umost[x] <= dmost[x])
{
dmost[x] = uwall[x];
if (umost[x] > dmost[x]) numhits--;
}
}
else
{
for(x=x1;x<=x2;x++)
if (umost[x] <= dmost[x])
{
i = min(dplc[x],uwall[x]);
if (i < dmost[x])
{
dmost[x] = i;
if (umost[x] > dmost[x]) numhits--;
}
}
}
}
if ((fz[2] > fz[0]) || (fz[3] > fz[1]) || (globalposz > fz[4]))
{
i = x2-x1+1;
if (smostcnt+i < MAXYSAVES)
{
smoststart[smostwallcnt] = smostcnt;
smostwall[smostwallcnt] = z;
smostwalltype[smostwallcnt] = 2; //2 for dmost
smostwallcnt++;
copybufbyte((long)&dmost[x1],(long)&smost[smostcnt],i*sizeof(smost[0]));
smostcnt += i;
}
}
}
if (numhits < 0) return;
if ((!(wal->cstat&32)) && ((gotsector[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0))
{
if (umost[x2] < dmost[x2])
scansector(nextsectnum);
else
{
for(x=x1;x<x2;x++)
if (umost[x] < dmost[x])
{ scansector(nextsectnum); break; }
//If can't see sector beyond, then cancel smost array and just
//store wall!
if (x == x2)
{
smostwallcnt = startsmostwallcnt;
smostcnt = startsmostcnt;
smostwall[smostwallcnt] = z;
smostwalltype[smostwallcnt] = 0;
smostwallcnt++;
}
}
}
}
if ((nextsectnum < 0) || (wal->cstat&32)) //White/1-way wall
{
globalorientation = (long)wal->cstat;
if (nextsectnum < 0) globalpicnum = wal->picnum;
else globalpicnum = wal->overpicnum;
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
globalxpanning = (long)wal->xpanning;
globalypanning = (long)wal->ypanning;
if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
globalshade = (long)wal->shade;
globvis = globalvisibility;
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
globalpal = (long)wal->pal;
globalshiftval = (picsiz[globalpicnum]>>4);
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
globalshiftval = 32-globalshiftval;
globalyscale = (wal->yrepeat<<(globalshiftval-19));
if (nextsectnum >= 0)
{
if ((globalorientation&4) == 0) globalzd = globalposz-nextsec->ceilingz;
else globalzd = globalposz-sec->ceilingz;
}
else
{
if ((globalorientation&4) == 0) globalzd = globalposz-sec->ceilingz;
else globalzd = globalposz-sec->floorz;
}
globalzd = ((globalzd*globalyscale)<<8) + (globalypanning<<24);
if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
wallscan(x1,x2,uplc,dplc,swall,lwall);
for(x=x1;x<=x2;x++)
if (umost[x] <= dmost[x])
{ umost[x] = 1; dmost[x] = 0; numhits--; }
smostwall[smostwallcnt] = z;
smostwalltype[smostwallcnt] = 0;
smostwallcnt++;
if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
{
searchit = 1; searchsector = sectnum; searchwall = wallnum;
if (nextsectnum < 0) searchstat = 0; else searchstat = 4;
}
}
}
}
prepwall(long z, walltype *wal)
{
long i, l, ol, splc, sinc, x, topinc, top, botinc, bot, hplc, walxrepeat;
walxrepeat = (wal->xrepeat<<3);
//lwall calculation
i = xb1[z]-halfxdimen;
topinc = -(ry1[z]>>2);
botinc = ((ry2[z]-ry1[z])>>8);
top = mulscale5(rx1[z],xdimen)+mulscale2(topinc,i);
bot = mulscale11(rx1[z]-rx2[z],xdimen)+mulscale2(botinc,i);
splc = mulscale19(ry1[z],xdimscale);
sinc = mulscale16(ry2[z]-ry1[z],xdimscale);
x = xb1[z];
if (bot != 0)
{
l = divscale12(top,bot);
swall[x] = mulscale21(l,sinc)+splc;
l *= walxrepeat;
lwall[x] = (l>>18);
}
while (x+4 <= xb2[z])
{
top += topinc; bot += botinc;
if (bot != 0)
{
ol = l; l = divscale12(top,bot);
swall[x+4] = mulscale21(l,sinc)+splc;
l *= walxrepeat;
lwall[x+4] = (l>>18);
}
i = ((ol+l)>>1);
lwall[x+2] = (i>>18);
lwall[x+1] = ((ol+i)>>19);
lwall[x+3] = ((l+i)>>19);
swall[x+2] = ((swall[x]+swall[x+4])>>1);
swall[x+1] = ((swall[x]+swall[x+2])>>1);
swall[x+3] = ((swall[x+4]+swall[x+2])>>1);
x += 4;
}
if (x+2 <= xb2[z])
{
top += (topinc>>1); bot += (botinc>>1);
if (bot != 0)
{
ol = l; l = divscale12(top,bot);
swall[x+2] = mulscale21(l,sinc)+splc;
l *= walxrepeat;
lwall[x+2] = (l>>18);
}
lwall[x+1] = ((l+ol)>>19);
swall[x+1] = ((swall[x]+swall[x+2])>>1);
x += 2;
}
if (x+1 <= xb2[z])
{
bot += (botinc>>2);
if (bot != 0)
{
l = divscale12(top+(topinc>>2),bot);
swall[x+1] = mulscale21(l,sinc)+splc;
lwall[x+1] = mulscale18(l,walxrepeat);
}
}
if (lwall[xb1[z]] < 0) lwall[xb1[z]] = 0;
if ((lwall[xb2[z]] >= walxrepeat) && (walxrepeat)) lwall[xb2[z]] = walxrepeat-1;
if (wal->cstat&8)
{
walxrepeat--;
for(x=xb1[z];x<=xb2[z];x++) lwall[x] = walxrepeat-lwall[x];
}
}
ceilscan (long x1, long x2, long sectnum)
{
long i, j, ox, oy, x, y1, y2, twall, bwall;
sectortype *sec;
sec = &sector[sectnum];
if (palookup[sec->ceilingpal] != globalpalwritten)
{
globalpalwritten = palookup[sec->ceilingpal];
setpalookupaddress(globalpalwritten);
}
globalzd = sec->ceilingz-globalposz;
if (globalzd > 0) return;
globalpicnum = sec->ceilingpicnum;
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
setgotpic(globalpicnum);
if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) return;
if (picanm[globalpicnum]&192) globalpicnum += animateoffs((short)globalpicnum,(short)sectnum);
if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
globalbufplc = waloff[globalpicnum];
globalshade = (long)sec->ceilingshade;
globvis = globalcisibility;
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
globalorientation = (long)sec->ceilingstat;
if ((globalorientation&64) == 0)
{
globalx1 = singlobalang; globalx2 = singlobalang;
globaly1 = cosglobalang; globaly2 = cosglobalang;
globalxpanning = (globalposx<<20);
globalypanning = -(globalposy<<20);
}
else
{
j = sec->wallptr;
ox = wall[wall[j].point2].x - wall[j].x;
oy = wall[wall[j].point2].y - wall[j].y;
i = nsqrtasm(ox*ox+oy*oy); if (i == 0) i = 1024; else i = 1048576/i;
globalx1 = mulscale10(dmulscale10(ox,singlobalang,-oy,cosglobalang),i);
globaly1 = mulscale10(dmulscale10(ox,cosglobalang,oy,singlobalang),i);
globalx2 = -globalx1;
globaly2 = -globaly1;
ox = ((wall[j].x-globalposx)<<6); oy = ((wall[j].y-globalposy)<<6);
i = dmulscale14(oy,cosglobalang,-ox,singlobalang);
j = dmulscale14(ox,cosglobalang,oy,singlobalang);
ox = i; oy = j;
globalxpanning = globalx1*ox - globaly1*oy;
globalypanning = globaly2*ox + globalx2*oy;
}
globalx2 = mulscale16(globalx2,viewingrangerecip);
globaly1 = mulscale16(globaly1,viewingrangerecip);
globalxshift = (8-(picsiz[globalpicnum]&15));
globalyshift = (8-(picsiz[globalpicnum]>>4));
if (globalorientation&8) { globalxshift++; globalyshift++; }
if ((globalorientation&0x4) > 0)
{
i = globalxpanning; globalxpanning = globalypanning; globalypanning = i;
i = globalx2; globalx2 = -globaly1; globaly1 = -i;
i = globalx1; globalx1 = globaly2; globaly2 = i;
}
if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalxpanning = -globalxpanning;
if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalypanning = -globalypanning;
globalx1 <<= globalxshift; globaly1 <<= globalxshift;
globalx2 <<= globalyshift; globaly2 <<= globalyshift;
globalxpanning <<= globalxshift; globalypanning <<= globalyshift;
globalxpanning += (((long)sec->ceilingxpanning)<<24);
globalypanning += (((long)sec->ceilingypanning)<<24);
globaly1 = (-globalx1-globaly1)*halfxdimen;
globalx2 = (globalx2-globaly2)*halfxdimen;
sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
globalx2 += globaly2*(x1-1);
globaly1 += globalx1*(x1-1);
globalx1 = mulscale16(globalx1,globalzd);
globalx2 = mulscale16(globalx2,globalzd);
globaly1 = mulscale16(globaly1,globalzd);
globaly2 = mulscale16(globaly2,globalzd);
globvis = klabs(mulscale10(globvis,globalzd));
if (!(globalorientation&0x180))
{
y1 = umost[x1]; y2 = y1;
for(x=x1;x<=x2;x++)
{
twall = umost[x]-1; bwall = min(uplc[x],dmost[x]);
if (twall < bwall-1)
{
if (twall >= y2)
{
while (y1 < y2-1) hline(x-1,++y1);
y1 = twall;
}
else
{
while (y1 < twall) hline(x-1,++y1);
while (y1 > twall) lastx[y1--] = x;
}
while (y2 > bwall) hline(x-1,--y2);
while (y2 < bwall) lastx[y2++] = x;
}
else
{
while (y1 < y2-1) hline(x-1,++y1);
if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
y1 = umost[x+1]; y2 = y1;
}
globalx2 += globaly2; globaly1 += globalx1;
}
while (y1 < y2-1) hline(x2,++y1);
faketimerhandler();
return;
}
switch(globalorientation&0x180)
{
case 128:
msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
break;
case 256:
settransnormal();
tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
break;
case 384:
settransreverse();
tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
break;
}
y1 = umost[x1]; y2 = y1;
for(x=x1;x<=x2;x++)
{
twall = umost[x]-1; bwall = min(uplc[x],dmost[x]);
if (twall < bwall-1)
{
if (twall >= y2)
{
while (y1 < y2-1) slowhline(x-1,++y1);
y1 = twall;
}
else
{
while (y1 < twall) slowhline(x-1,++y1);
while (y1 > twall) lastx[y1--] = x;
}
while (y2 > bwall) slowhline(x-1,--y2);
while (y2 < bwall) lastx[y2++] = x;
}
else
{
while (y1 < y2-1) slowhline(x-1,++y1);
if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
y1 = umost[x+1]; y2 = y1;
}
globalx2 += globaly2; globaly1 += globalx1;
}
while (y1 < y2-1) slowhline(x2,++y1);
faketimerhandler();
}
florscan (long x1, long x2, long sectnum)
{
long i, j, ox, oy, x, y1, y2, twall, bwall;
sectortype *sec;
sec = &sector[sectnum];
if (palookup[sec->floorpal] != globalpalwritten)
{
globalpalwritten = palookup[sec->floorpal];
setpalookupaddress(globalpalwritten);
}
globalzd = globalposz-sec->floorz;
if (globalzd > 0) return;
globalpicnum = sec->floorpicnum;
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
setgotpic(globalpicnum);
if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) return;
if (picanm[globalpicnum]&192) globalpicnum += animateoffs((short)globalpicnum,(short)sectnum);
if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
globalbufplc = waloff[globalpicnum];
globalshade = (long)sec->floorshade;
globvis = globalcisibility;
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
globalorientation = (long)sec->floorstat;
if ((globalorientation&64) == 0)
{
globalx1 = singlobalang; globalx2 = singlobalang;
globaly1 = cosglobalang; globaly2 = cosglobalang;
globalxpanning = (globalposx<<20);
globalypanning = -(globalposy<<20);
}
else
{
j = sec->wallptr;
ox = wall[wall[j].point2].x - wall[j].x;
oy = wall[wall[j].point2].y - wall[j].y;
i = nsqrtasm(ox*ox+oy*oy); if (i == 0) i = 1024; else i = 1048576/i;
globalx1 = mulscale10(dmulscale10(ox,singlobalang,-oy,cosglobalang),i);
globaly1 = mulscale10(dmulscale10(ox,cosglobalang,oy,singlobalang),i);
globalx2 = -globalx1;
globaly2 = -globaly1;
ox = ((wall[j].x-globalposx)<<6); oy = ((wall[j].y-globalposy)<<6);
i = dmulscale14(oy,cosglobalang,-ox,singlobalang);
j = dmulscale14(ox,cosglobalang,oy,singlobalang);
ox = i; oy = j;
globalxpanning = globalx1*ox - globaly1*oy;
globalypanning = globaly2*ox + globalx2*oy;
}
globalx2 = mulscale16(globalx2,viewingrangerecip);
globaly1 = mulscale16(globaly1,viewingrangerecip);
globalxshift = (8-(picsiz[globalpicnum]&15));
globalyshift = (8-(picsiz[globalpicnum]>>4));
if (globalorientation&8) { globalxshift++; globalyshift++; }
if ((globalorientation&0x4) > 0)
{
i = globalxpanning; globalxpanning = globalypanning; globalypanning = i;
i = globalx2; globalx2 = -globaly1; globaly1 = -i;
i = globalx1; globalx1 = globaly2; globaly2 = i;
}
if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalxpanning = -globalxpanning;
if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalypanning = -globalypanning;
globalx1 <<= globalxshift; globaly1 <<= globalxshift;
globalx2 <<= globalyshift; globaly2 <<= globalyshift;
globalxpanning <<= globalxshift; globalypanning <<= globalyshift;
globalxpanning += (((long)sec->floorxpanning)<<24);
globalypanning += (((long)sec->floorypanning)<<24);
globaly1 = (-globalx1-globaly1)*halfxdimen;
globalx2 = (globalx2-globaly2)*halfxdimen;
sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
globalx2 += globaly2*(x1-1);
globaly1 += globalx1*(x1-1);
globalx1 = mulscale16(globalx1,globalzd);
globalx2 = mulscale16(globalx2,globalzd);
globaly1 = mulscale16(globaly1,globalzd);
globaly2 = mulscale16(globaly2,globalzd);
globvis = klabs(mulscale10(globvis,globalzd));
if (!(globalorientation&0x180))
{
y1 = max(dplc[x1],umost[x1]); y2 = y1;
for(x=x1;x<=x2;x++)
{
twall = max(dplc[x],umost[x])-1; bwall = dmost[x];
if (twall < bwall-1)
{
if (twall >= y2)
{
while (y1 < y2-1) hline(x-1,++y1);
y1 = twall;
}
else
{
while (y1 < twall) hline(x-1,++y1);
while (y1 > twall) lastx[y1--] = x;
}
while (y2 > bwall) hline(x-1,--y2);
while (y2 < bwall) lastx[y2++] = x;
}
else
{
while (y1 < y2-1) hline(x-1,++y1);
if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
y1 = max(dplc[x+1],umost[x+1]); y2 = y1;
}
globalx2 += globaly2; globaly1 += globalx1;
}
while (y1 < y2-1) hline(x2,++y1);
faketimerhandler();
return;
}
switch(globalorientation&0x180)
{
case 128:
msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
break;
case 256:
settransnormal();
tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
break;
case 384:
settransreverse();
tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
break;
}
y1 = max(dplc[x1],umost[x1]); y2 = y1;
for(x=x1;x<=x2;x++)
{
twall = max(dplc[x],umost[x])-1; bwall = dmost[x];
if (twall < bwall-1)
{
if (twall >= y2)
{
while (y1 < y2-1) slowhline(x-1,++y1);
y1 = twall;
}
else
{
while (y1 < twall) slowhline(x-1,++y1);
while (y1 > twall) lastx[y1--] = x;
}
while (y2 > bwall) slowhline(x-1,--y2);
while (y2 < bwall) lastx[y2++] = x;
}
else
{
while (y1 < y2-1) slowhline(x-1,++y1);
if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
y1 = max(dplc[x+1],umost[x+1]); y2 = y1;
}
globalx2 += globaly2; globaly1 += globalx1;
}
while (y1 < y2-1) slowhline(x2,++y1);
faketimerhandler();
}
wallscan(long x1, long x2, short *uwal, short *dwal, long *swal, long *lwal)
{
long i, x, xnice, ynice, fpalookup, shade;
long y1ve[4], y2ve[4], u4, d4, dax, z, tsizx, tsizy;
char bad;
tsizx = tilesizx[globalpicnum];
tsizy = tilesizy[globalpicnum];
setgotpic(globalpicnum);
if ((tsizx <= 0) || (tsizy <= 0)) return;
if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen)) return;
if ((dwal[x1] < 0) && (dwal[x2] < 0)) return;
if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
xnice = (pow2long[picsiz[globalpicnum]&15] == tsizx);
if (xnice) tsizx--;
ynice = (pow2long[picsiz[globalpicnum]>>4] == tsizy);
if (ynice) tsizy = (picsiz[globalpicnum]>>4);
fpalookup = FP_OFF(palookup[globalpal]);
setupvlineasm(globalshiftval);
x = x1;
while ((umost[x] > dmost[x]) && (x <= x2)) x++;
for(;(x<=x2)&&((x+frameoffset)&3);x++)
{
y1ve[0] = max(uwal[x],umost[x]);
y2ve[0] = min(dwal[x],dmost[x]);
if (y2ve[0] <= y1ve[0]) continue;
palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
bufplce[0] = lwal[x] + globalxpanning;
if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
vince[0] = swal[x]*globalyscale;
vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],x+frameoffset+ylookup[y1ve[0]]);
}
for(;x<=x2-3;x+=4)
{
bad = 0;
for(z=3;z>=0;z--)
{
y1ve[z] = max(uwal[x+z],umost[x+z]);
y2ve[z] = min(dwal[x+z],dmost[x+z])-1;
if (y2ve[z] < y1ve[z]) { bad += pow2char[z]; continue; }
i = lwal[x+z] + globalxpanning;
if (i >= tsizx) { if (xnice == 0) i %= tsizx; else i &= tsizx; }
if (ynice == 0) i *= tsizy; else i <<= tsizy;
bufplce[z] = waloff[globalpicnum]+i;
vince[z] = swal[x+z]*globalyscale;
vplce[z] = globalzd + vince[z]*(y1ve[z]-globalhoriz+1);
}
if (bad == 15) continue;
palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
palookupoffse[3] = fpalookup+(getpalookup((long)mulscale16(swal[x+3],globvis),globalshade)<<8);
if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
{
palookupoffse[1] = palookupoffse[0];
palookupoffse[2] = palookupoffse[0];
}
else
{
palookupoffse[1] = fpalookup+(getpalookup((long)mulscale16(swal[x+1],globvis),globalshade)<<8);
palookupoffse[2] = fpalookup+(getpalookup((long)mulscale16(swal[x+2],globvis),globalshade)<<8);
}
u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
if ((bad != 0) || (u4 >= d4))
{
if (!(bad&1)) prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+x+frameoffset+0);
if (!(bad&2)) prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+x+frameoffset+1);
if (!(bad&4)) prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+x+frameoffset+2);
if (!(bad&8)) prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+x+frameoffset+3);
continue;
}
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);
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);
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);
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);
if (d4 >= u4) vlineasm4(d4-u4+1,ylookup[u4]+x+frameoffset);
i = x+frameoffset+ylookup[d4+1];
if (y2ve[0] > d4) prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
if (y2ve[1] > d4) prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
if (y2ve[2] > d4) prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
if (y2ve[3] > d4) prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
}
for(;x<=x2;x++)
{
y1ve[0] = max(uwal[x],umost[x]);
y2ve[0] = min(dwal[x],dmost[x]);
if (y2ve[0] <= y1ve[0]) continue;
palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
bufplce[0] = lwal[x] + globalxpanning;
if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
vince[0] = swal[x]*globalyscale;
vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],x+frameoffset+ylookup[y1ve[0]]);
}
faketimerhandler();
}
maskwallscan(long x1, long x2, short *uwal, short *dwal, long *swal, long *lwal)
{
long i, x, startx, xnice, ynice, fpalookup, shade;
long y1ve[4], y2ve[4], u4, d4, dax, z, p, tsizx, tsizy;
char bad;
tsizx = tilesizx[globalpicnum];
tsizy = tilesizy[globalpicnum];
setgotpic(globalpicnum);
if ((tsizx <= 0) || (tsizy <= 0)) return;
if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen)) return;
if ((dwal[x1] < 0) && (dwal[x2] < 0)) return;
if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
startx = x1;
xnice = (pow2long[picsiz[globalpicnum]&15] == tsizx);
if (xnice) tsizx = (tsizx-1);
ynice = (pow2long[picsiz[globalpicnum]>>4] == tsizy);
if (ynice) tsizy = (picsiz[globalpicnum]>>4);
fpalookup = FP_OFF(palookup[globalpal]);
setupmvlineasm(globalshiftval);
x = startx;
while ((startumost[x+windowx1] > startdmost[x+windowx1]) && (x <= x2)) x++;
p = x+frameoffset;
for(;(x<=x2)&&(p&3);x++,p++)
{
y1ve[0] = max(uwal[x],startumost[x+windowx1]-windowy1);
y2ve[0] = min(dwal[x],startdmost[x+windowx1]-windowy1);
if (y2ve[0] <= y1ve[0]) continue;
palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
bufplce[0] = lwal[x] + globalxpanning;
if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
vince[0] = swal[x]*globalyscale;
vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],p+ylookup[y1ve[0]]);
}
for(;x<=x2-3;x+=4,p+=4)
{
bad = 0;
for(z=3,dax=x+3;z>=0;z--,dax--)
{
y1ve[z] = max(uwal[dax],startumost[dax+windowx1]-windowy1);
y2ve[z] = min(dwal[dax],startdmost[dax+windowx1]-windowy1)-1;
if (y2ve[z] < y1ve[z]) { bad += pow2char[z]; continue; }
i = lwal[dax] + globalxpanning;
if (i >= tsizx) { if (xnice == 0) i %= tsizx; else i &= tsizx; }
if (ynice == 0) i *= tsizy; else i <<= tsizy;
bufplce[z] = waloff[globalpicnum]+i;
vince[z] = swal[dax]*globalyscale;
vplce[z] = globalzd + vince[z]*(y1ve[z]-globalhoriz+1);
}
if (bad == 15) continue;
palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
palookupoffse[3] = fpalookup+(getpalookup((long)mulscale16(swal[x+3],globvis),globalshade)<<8);
if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
{
palookupoffse[1] = palookupoffse[0];
palookupoffse[2] = palookupoffse[0];
}
else
{
palookupoffse[1] = fpalookup+(getpalookup((long)mulscale16(swal[x+1],globvis),globalshade)<<8);
palookupoffse[2] = fpalookup+(getpalookup((long)mulscale16(swal[x+2],globvis),globalshade)<<8);
}
u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
if ((bad > 0) || (u4 >= d4))
{
if (!(bad&1)) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
if (!(bad&2)) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
if (!(bad&4)) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
if (!(bad&8)) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
continue;
}
if (u4 > y1ve[0]) vplce[0] = mvlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
if (u4 > y1ve[1]) vplce[1] = mvlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
if (u4 > y1ve[2]) vplce[2] = mvlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
if (u4 > y1ve[3]) vplce[3] = mvlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
if (d4 >= u4) mvlineasm4(d4-u4+1,ylookup[u4]+p);
i = p+ylookup[d4+1];
if (y2ve[0] > d4) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
if (y2ve[1] > d4) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
if (y2ve[2] > d4) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
if (y2ve[3] > d4) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
}
for(;x<=x2;x++,p++)
{
y1ve[0] = max(uwal[x],startumost[x+windowx1]-windowy1);
y2ve[0] = min(dwal[x],startdmost[x+windowx1]-windowy1);
if (y2ve[0] <= y1ve[0]) continue;
palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
bufplce[0] = lwal[x] + globalxpanning;
if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
vince[0] = swal[x]*globalyscale;
vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],p+ylookup[y1ve[0]]);
}
faketimerhandler();
}
transmaskvline (long x)
{
long vplc, vinc, p, i, palookupoffs, shade, bufplc;
short y1v, y2v;
if ((x < 0) || (x >= xdimen)) return;
y1v = max(uwall[x],startumost[x+windowx1]-windowy1);
y2v = min(dwall[x],startdmost[x+windowx1]-windowy1);
y2v--;
if (y2v < y1v) return;
palookupoffs = FP_OFF(palookup[globalpal]) + (getpalookup((long)mulscale16(swall[x],globvis),globalshade)<<8);
vinc = swall[x]*globalyscale;
vplc = globalzd + vinc*(y1v-globalhoriz+1);
i = lwall[x]+globalxpanning;
if (i >= tilesizx[globalpicnum]) i %= tilesizx[globalpicnum];
bufplc = waloff[globalpicnum]+i*tilesizy[globalpicnum];
p = ylookup[y1v]+x+frameoffset;
tvlineasm1(vinc,palookupoffs,y2v-y1v,vplc,bufplc,p);
transarea += y2v-y1v;
}
transmaskvline2 (long x)
{
long i, y1, y2, x2;
short y1ve[2], y2ve[2];
if ((x < 0) || (x >= xdimen)) return;
if (x == xdimen-1) { transmaskvline(x); return; }
x2 = x+1;
y1ve[0] = max(uwall[x],startumost[x+windowx1]-windowy1);
y2ve[0] = min(dwall[x],startdmost[x+windowx1]-windowy1)-1;
if (y2ve[0] < y1ve[0]) { transmaskvline(x2); return; }
y1ve[1] = max(uwall[x2],startumost[x2+windowx1]-windowy1);
y2ve[1] = min(dwall[x2],startdmost[x2+windowx1]-windowy1)-1;
if (y2ve[1] < y1ve[1]) { transmaskvline(x); return; }
palookupoffse[0] = FP_OFF(palookup[globalpal]) + (getpalookup((long)mulscale16(swall[x],globvis),globalshade)<<8);
palookupoffse[1] = FP_OFF(palookup[globalpal]) + (getpalookup((long)mulscale16(swall[x2],globvis),globalshade)<<8);
setuptvlineasm2(globalshiftval,palookupoffse[0],palookupoffse[1]);
vince[0] = swall[x]*globalyscale;
vince[1] = swall[x2]*globalyscale;
vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
vplce[1] = globalzd + vince[1]*(y1ve[1]-globalhoriz+1);
i = lwall[x] + globalxpanning;
if (i >= tilesizx[globalpicnum]) i %= tilesizx[globalpicnum];
bufplce[0] = waloff[globalpicnum]+i*tilesizy[globalpicnum];
i = lwall[x2] + globalxpanning;
if (i >= tilesizx[globalpicnum]) i %= tilesizx[globalpicnum];
bufplce[1] = waloff[globalpicnum]+i*tilesizy[globalpicnum];
y1 = max(y1ve[0],y1ve[1]);
y2 = min(y2ve[0],y2ve[1]);
i = x+frameoffset;
if (y1ve[0] != y1ve[1])
{
if (y1ve[0] < y1)
vplce[0] = tvlineasm1(vince[0],palookupoffse[0],y1-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+i);
else
vplce[1] = tvlineasm1(vince[1],palookupoffse[1],y1-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+i+1);
}
if (y2 > y1)
{
asm1 = vince[1];
asm2 = ylookup[y2]+i+1;
tvlineasm2(vplce[1],vince[0],bufplce[0],bufplce[1],vplce[0],ylookup[y1]+i);
transarea += ((y2-y1)<<1);
}
else
{
asm1 = vplce[0];
asm2 = vplce[1];
}
if (y2ve[0] > y2ve[1])
tvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y2-1,asm1,bufplce[0],ylookup[y2+1]+i);
else if (y2ve[0] < y2ve[1])
tvlineasm1(vince[1],palookupoffse[1],y2ve[1]-y2-1,asm2,bufplce[1],ylookup[y2+1]+i+1);
faketimerhandler();
}
transmaskwallscan(long x1, long x2)
{
long x, startx;
setgotpic(globalpicnum);
if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) return;
if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
setuptvlineasm(globalshiftval);
x = x1;
while ((startumost[x+windowx1] > startdmost[x+windowx1]) && (x <= x2)) x++;
if ((x <= x2) && (x&1)) transmaskvline(x), x++;
while (x < x2) transmaskvline2(x), x += 2;
while (x <= x2) transmaskvline(x), x++;
faketimerhandler();
}
loadboard(char *filename, long *daposx, long *daposy, long *daposz,
short *daang, short *dacursectnum)
{
short fil, i, numsprites;
i = strlen(filename)-1;
if (filename[i] == 255) { filename[i] = 0; i = 1; } else i = 0;
if ((fil = kopen4load(filename,i)) == -1)
{ mapversion = 7L; return(-1); }
kread(fil,&mapversion,4);
if (mapversion != 7L) return(-1);
initspritelists();
clearbuf((long)(&show2dsector[0]),(long)((MAXSECTORS+3)>>5),0L);
clearbuf((long)(&show2dsprite[0]),(long)((MAXSPRITES+3)>>5),0L);
clearbuf((long)(&show2dwall[0]),(long)((MAXWALLS+3)>>5),0L);
kread(fil,daposx,4);
kread(fil,daposy,4);
kread(fil,daposz,4);
kread(fil,daang,2);
kread(fil,dacursectnum,2);
kread(fil,&numsectors,2);
kread(fil,&sector[0],sizeof(sectortype)*numsectors);
kread(fil,&numwalls,2);
kread(fil,&wall[0],sizeof(walltype)*numwalls);
kread(fil,&numsprites,2);
kread(fil,&sprite[0],sizeof(spritetype)*numsprites);
for(i=0;i<numsprites;i++)
insertsprite(sprite[i].sectnum,sprite[i].statnum);
//Must be after loading sectors, etc!
updatesector(*daposx,*daposy,dacursectnum);
kclose(fil);
return(0);
}
saveboard(char *filename, long *daposx, long *daposy, long *daposz,
short *daang, short *dacursectnum)
{
short fil, i, j, numsprites;
if ((fil = open(filename,O_BINARY|O_TRUNC|O_CREAT|O_WRONLY,S_IWRITE)) == -1)
return(-1);
write(fil,&mapversion,4);
write(fil,daposx,4);
write(fil,daposy,4);
write(fil,daposz,4);
write(fil,daang,2);
write(fil,dacursectnum,2);
write(fil,&numsectors,2);
write(fil,&sector[0],sizeof(sectortype)*numsectors);
write(fil,&numwalls,2);
write(fil,&wall[0],sizeof(walltype)*numwalls);
numsprites = 0;
for(j=0;j<MAXSTATUS;j++)
{
i = headspritestat[j];
while (i != -1)
{
numsprites++;
i = nextspritestat[i];
}
}
write(fil,&numsprites,2);
for(j=0;j<MAXSTATUS;j++)
{
i = headspritestat[j];
while (i != -1)
{
write(fil,&sprite[i],sizeof(spritetype));
i = nextspritestat[i];
}
}
close(fil);
return(0);
}
loadtables()
{
long i, fil;
if (tablesloaded == 0)
{
initksqrt();
for(i=0;i<2048;i++) reciptable[i] = divscale30(2048L,i+2048);
if ((fil = kopen4load("tables.dat",0)) != -1)
{
kread(fil,sintable,2048*2);
kread(fil,radarang,640*2);
for(i=0;i<640;i++) radarang[1279-i] = -radarang[i];
kread(fil,textfont,1024);
kread(fil,smalltextfont,1024);
kread(fil,britable,1024);
kclose(fil);
}
tablesloaded = 1;
}
}
loadpalette()
{
long i, j, k, dist, fil;
char *ptr;
if (paletteloaded != 0) return;
if ((fil = kopen4load("palette.dat",0)) == -1) return;
kread(fil,palette,768);
kread(fil,&numpalookups,2);
if ((palookup[0] = (char *)kkmalloc(numpalookups<<8)) == NULL)
allocache(&palookup[0],numpalookups<<8,&permanentlock);
if ((transluc = (char *)kkmalloc(65536L)) == NULL)
allocache(&transluc,65536,&permanentlock);
globalpalwritten = palookup[0]; globalpal = 0;
setpalookupaddress(globalpalwritten);
fixtransluscence(FP_OFF(transluc));
kread(fil,palookup[globalpal],numpalookups<<8);
kread(fil,transluc,65536);
kclose(fil);
initfastcolorlookup(30L,59L,11L);
paletteloaded = 1;
if (vidoption == 6)
{
for(k=0;k<MAXPALOOKUPS;k++)
if (palookup[k] != NULL)
for(i=0;i<256;i++)
{
dist = palette[i*3]*3+palette[i*3+1]*5+palette[i*3+2]*2;
ptr = (char *)(FP_OFF(palookup[k])+i);
for(j=0;j<32;j++)
ptr[j<<8] = (char)min(max(mulscale10(dist,32-j),0),15);
}
if (transluc != NULL)
{
for(i=0;i<16;i++)
for(j=0;j<16;j++)
transluc[(i<<8)+j] = ((i+j+1)>>1);
}
}
}
static char screenalloctype = 255;
setgamemode(char davidoption, long daxdim, long daydim)
{
long i, j, k, ostereomode;
if ((qsetmode == 200) && (vidoption == davidoption) && (xdim == daxdim) && (ydim == daydim))
return(0);
vidoption = davidoption; xdim = daxdim; ydim = daydim;
strcpy(kensmessage,"!!!! BUILD engine&tools programmed by Ken Silverman of E.G. RI. (c) Copyright 1995 Ken Silverman. Summary: BUILD = Ken. !!!!");
if (getkensmessagecrc(FP_OFF(kensmessage)) != 0x56c764d4)
{ setvmode(0x3); printf("Nice try.\n"); exit(0); }
ostereomode = stereomode; if (stereomode) setstereo(0L);
activepage = visualpage = 0;
switch(vidoption)
{
case 1: i = xdim*ydim; break;
case 2: xdim = 320; ydim = 200; i = xdim*ydim; break;
case 6: xdim = 320; ydim = 200; i = 131072; break;
default: return(-1);
}
j = ydim*4*sizeof(long); //Leave room for horizlookup&horizlookup2
if (screen != NULL)
{
if (screenalloctype == 0) kkfree((void *)screen);
if (screenalloctype == 1) suckcache((long *)screen);
screen = NULL;
}
screenalloctype = 0;
if ((screen = (char *)kkmalloc(i+(j<<1))) == NULL)
{
allocache((long *)&screen,i+(j<<1),&permanentlock);
screenalloctype = 1;
}
frameplace = FP_OFF(screen);
horizlookup = (long *)(frameplace+i);
horizlookup2 = (long *)(frameplace+i+j);
horizycent = ((ydim*4)>>1);
switch(vidoption)
{
case 1:
//bytesperline is set in this function
if (setvesa(xdim,ydim) < 0) return(-1);
break;
case 2:
horizycent = ((ydim*4)>>1); //HACK for switching to this mode
case 6:
bytesperline = xdim;
setvmode(0x13);
break;
default: return(-1);
}
//Force drawrooms to call dosetaspect & recalculate stuff
oxyaspect = oxdimen = oviewingrange = -1;
setvlinebpl(bytesperline);
j = 0;
for(i=0;i<=ydim;i++) ylookup[i] = j, j += bytesperline;
numpages = 1;
if (vidoption == 1) numpages = min(maxpages,8);
setview(0L,0L,xdim-1,ydim-1);
clearallviews(0L);
setbrightness((char)curbrightness,(char *)&palette[0]);
if (searchx < 0) { searchx = halfxdimen; searchy = (ydimen>>1); }
if (ostereomode) setstereo(ostereomode);
qsetmode = 200;
return(0);
}
hline (long xr, long yp)
{
long xl, r, s;
xl = lastx[yp]; if (xl > xr) return;
r = horizlookup2[yp-globalhoriz+horizycent];
asm1 = globalx1*r;
asm2 = globaly2*r;
s = ((long)getpalookup((long)mulscale16(r,globvis),globalshade)<<8);
hlineasm4(xr-xl,0L,s,globalx2*r+globalypanning,globaly1*r+globalxpanning,
ylookup[yp]+xr+frameoffset);
}
slowhline (long xr, long yp)
{
long xl, x, y, ox, oy, r, p, shade;
xl = lastx[yp]; if (xl > xr) return;
r = horizlookup2[yp-globalhoriz+horizycent];
asm1 = globalx1*r;
asm2 = globaly2*r;
asm3 = (long)globalpalwritten + ((long)getpalookup((long)mulscale16(r,globvis),globalshade)<<8);
if (!(globalorientation&256))
{
mhline(globalbufplc,globaly1*r+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,
globalx2*r+globalypanning-asm2*(xr-xl),ylookup[yp]+xl+frameoffset);
return;
}
thline(globalbufplc,globaly1*r+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,
globalx2*r+globalypanning-asm2*(xr-xl),ylookup[yp]+xl+frameoffset);
transarea += (xr-xl);
}
long dommxoverlay = 1;
initengine()
{
long i, j;
if (dommxoverlay) mmxoverlay();
loadtables();
xyaspect = -1;
pskyoff[0] = 0; pskybits = 0;
parallaxtype = 2; parallaxyoffs = 0L; parallaxyscale = 65536;
showinvisibility = 0;
#ifdef SUPERBUILD
for(i=1;i<1024;i++) lowrecip[i] = ((1<<24)-1)/i;
for(i=0;i<MAXVOXELS;i++)
for(j=0;j<MAXVOXMIPS;j++)
{
voxoff[i][j] = 0L;
voxlock[i][j] = 200;
}
#endif
paletteloaded = 0;
searchit = 0; searchstat = -1;
for(i=0;i<MAXPALOOKUPS;i++) palookup[i] = NULL;
clearbuf((long)(&waloff[0]),(long)MAXTILES,0L);
clearbuf((long)(&show2dsector[0]),(long)((MAXSECTORS+3)>>5),0L);
clearbuf((long)(&show2dsprite[0]),(long)((MAXSPRITES+3)>>5),0L);
clearbuf((long)(&show2dwall[0]),(long)((MAXWALLS+3)>>5),0L);
automapping = 0;
validmodecnt = 0;
pointhighlight = -1;
linehighlight = -1;
highlightcnt = 0;
totalclock = 0;
visibility = 512;
parallaxvisibility = 512;
loadpalette();
}
uninitengine()
{
long i;
if (vidoption == 1) uninitvesa();
if (artfil != -1) kclose(artfil);
if (stereomode) setstereo(0L);
if (transluc != NULL) { kkfree(transluc); transluc = NULL; }
if (pic != NULL) { kkfree(pic); pic = NULL; }
if (screen != NULL)
{
if (screenalloctype == 0) kkfree((void *)screen);
//if (screenalloctype == 1) suckcache(screen); //Cache already gone
screen = NULL;
}
for(i=0;i<MAXPALOOKUPS;i++)
if (palookup[i] != NULL) { kkfree(palookup[i]); palookup[i] = NULL; }
}
nextpage()
{
long totbytes, i, j, k;
permfifotype *per;
//char snotbuf[32];
//j = 0; k = 0;
//for(i=0;i<4096;i++)
// if (waloff[i] != 0)
// {
// sprintf(snotbuf,"%ld-%ld",i,tilesizx[i]*tilesizy[i]);
// printext256((j>>5)*40+32,(j&31)*6,walock[i]>>3,-1,snotbuf,1);
// k += tilesizx[i]*tilesizy[i];
// j++;
// }
//sprintf(snotbuf,"Total: %ld",k);
//printext256((j>>5)*40+32,(j&31)*6,31,-1,snotbuf,1);
switch(qsetmode)
{
case 200:
for(i=permtail;i!=permhead;i=((i+1)&(MAXPERMS-1)))
{
per = &permfifo[i];
if ((per->pagesleft > 0) && (per->pagesleft <= numpages))
dorotatesprite(per->sx,per->sy,per->z,per->a,per->picnum,
per->dashade,per->dapalnum,per->dastat,
per->cx1,per->cy1,per->cx2,per->cy2);
}
switch(vidoption)
{
case 1:
if (stereomode)
{
stereonextpage();
if (!origbuffermode) buffermode = transarea = totalarea = 0;
}
else
{
visualpage = activepage;
setvisualpage(visualpage);
if (!origbuffermode)
{
buffermode = ((transarea<<3) > totalarea);
transarea = totalarea = 0;
}
activepage++; if (activepage >= numpages) activepage = 0;
setactivepage(activepage);
}
break;
case 2:
copybuf(frameplace,0xa0000,64000>>2);
break;
case 6:
if (!activepage) redblueblit(screen,&screen[65536],64000L);
activepage ^= 1;
break;
}
for(i=permtail;i!=permhead;i=((i+1)&(MAXPERMS-1)))
{
per = &permfifo[i];
if (per->pagesleft >= 130)
dorotatesprite(per->sx,per->sy,per->z,per->a,per->picnum,
per->dashade,per->dapalnum,per->dastat,
per->cx1,per->cy1,per->cx2,per->cy2);
if (per->pagesleft&127) per->pagesleft--;
if (((per->pagesleft&127) == 0) && (i == permtail))
permtail = ((permtail+1)&(MAXPERMS-1));
}
break;
case 350:
koutpw(0x3d4,0xc+((pageoffset>>11)<<8));
limitrate();
pageoffset = 225280-pageoffset; //225280 is 352(multiple of 16)*640
break;
case 480:
koutpw(0x3d4,0xc+((pageoffset>>11)<<8));
limitrate();
pageoffset = 399360-pageoffset;
break;
}
faketimerhandler();
if ((totalclock >= lastageclock+8) || (totalclock < lastageclock))
{ lastageclock = totalclock; agecache(); }
beforedrawrooms = 1;
numframes++;
}
char cachedebug = 0;
loadtile (short tilenume)
{
char *ptr;
long i, dasiz;
if ((unsigned)tilenume >= (unsigned)MAXTILES) return;
dasiz = tilesizx[tilenume]*tilesizy[tilenume];
if (dasiz <= 0) return;
i = tilefilenum[tilenume];
if (i != artfilnum)
{
if (artfil != -1) kclose(artfil);
artfilnum = i;
artfilplc = 0L;
artfilename[7] = (i%10)+48;
artfilename[6] = ((i/10)%10)+48;
artfilename[5] = ((i/100)%10)+48;
artfil = kopen4load(artfilename,0);
faketimerhandler();
}
if (cachedebug) printf("Tile:%ld\n",tilenume);
if (waloff[tilenume] == 0)
{
walock[tilenume] = 199;
allocache(&waloff[tilenume],dasiz,&walock[tilenume]);
}
if (artfilplc != tilefileoffs[tilenume])
{
klseek(artfil,tilefileoffs[tilenume]-artfilplc,SEEK_CUR);
faketimerhandler();
}
ptr = (char *)waloff[tilenume];
kread(artfil,ptr,dasiz);
faketimerhandler();
artfilplc = tilefileoffs[tilenume]+dasiz;
}
allocatepermanenttile(short tilenume, long xsiz, long ysiz)
{
long i, j, x, y, dasiz;
if ((xsiz <= 0) || (ysiz <= 0) || ((unsigned)tilenume >= (unsigned)MAXTILES))
return(0);
dasiz = xsiz*ysiz;
walock[tilenume] = 255;
allocache(&waloff[tilenume],dasiz,&walock[tilenume]);
tilesizx[tilenume] = xsiz;
tilesizy[tilenume] = ysiz;
picanm[tilenume] = 0;
j = 15; while ((j > 1) && (pow2long[j] > xsiz)) j--;
picsiz[tilenume] = ((char)j);
j = 15; while ((j > 1) && (pow2long[j] > ysiz)) j--;
picsiz[tilenume] += ((char)(j<<4));
return(waloff[tilenume]);
}
loadpics(char *filename)
{
long offscount, siz, localtilestart, localtileend, dasiz;
short fil, i, j, k;
strcpy(artfilename,filename);
for(i=0;i<MAXTILES;i++)
{
tilesizx[i] = 0;
tilesizy[i] = 0;
picanm[i] = 0L;
}
artsize = 0L;
numtilefiles = 0;
do
{
k = numtilefiles;
artfilename[7] = (k%10)+48;
artfilename[6] = ((k/10)%10)+48;
artfilename[5] = ((k/100)%10)+48;
if ((fil = kopen4load(artfilename,0)) != -1)
{
kread(fil,&artversion,4);
if (artversion != 1) return(-1);
kread(fil,&numtiles,4);
kread(fil,&localtilestart,4);
kread(fil,&localtileend,4);
kread(fil,&tilesizx[localtilestart],(localtileend-localtilestart+1)<<1);
kread(fil,&tilesizy[localtilestart],(localtileend-localtilestart+1)<<1);
kread(fil,&picanm[localtilestart],(localtileend-localtilestart+1)<<2);
offscount = 4+4+4+4+((localtileend-localtilestart+1)<<3);
for(i=localtilestart;i<=localtileend;i++)
{
tilefilenum[i] = k;
tilefileoffs[i] = offscount;
dasiz = (long)(tilesizx[i]*tilesizy[i]);
offscount += dasiz;
artsize += ((dasiz+15)&0xfffffff0);
}
kclose(fil);
numtilefiles++;
}
}
while (k != numtilefiles);
clearbuf((long)(&gotpic[0]),(long)((MAXTILES+31)>>5),0L);
//try dpmi_DETERMINEMAXREALALLOC!
cachesize = max(artsize,1048576);
while ((pic = (char *)kkmalloc(cachesize)) == NULL)
{
cachesize -= 65536L;
if (cachesize < 65536) return(-1);
}
initcache((FP_OFF(pic)+15)&0xfffffff0,(cachesize-((-FP_OFF(pic))&15))&0xfffffff0);
for(i=0;i<MAXTILES;i++)
{
j = 15;
while ((j > 1) && (pow2long[j] > tilesizx[i])) j--;
picsiz[i] = ((char)j);
j = 15;
while ((j > 1) && (pow2long[j] > tilesizy[i])) j--;
picsiz[i] += ((char)(j<<4));
}
artfil = -1;
artfilnum = -1;
artfilplc = 0L;
return(0);
}
#ifdef SUPERBUILD
qloadkvx(long voxindex, char *filename)
{
long i, fil, dasiz, lengcnt, lengtot;
char *ptr;
if ((fil = kopen4load(filename,0)) == -1) return;
lengcnt = 0;
lengtot = kfilelength(fil);
for(i=0;i<MAXVOXMIPS;i++)
{
kread(fil,&dasiz,4);
//Must store filenames to use cacheing system :(
voxlock[voxindex][i] = 200;
allocache(&voxoff[voxindex][i],dasiz,&voxlock[voxindex][i]);
ptr = (char *)voxoff[voxindex][i];
kread(fil,ptr,dasiz);
lengcnt += dasiz+4;
if (lengcnt >= lengtot-768) break;
}
kclose(fil);
}
#endif
clipinsidebox(long x, long y, short wallnum, long walldist)
{
walltype *wal;
long x1, y1, x2, y2, r;
r = (walldist<<1);
wal = &wall[wallnum]; x1 = wal->x+walldist-x; y1 = wal->y+walldist-y;
wal = &wall[wal->point2]; x2 = wal->x+walldist-x; y2 = wal->y+walldist-y;
if ((x1 < 0) && (x2 < 0)) return(0);
if ((y1 < 0) && (y2 < 0)) return(0);
if ((x1 >= r) && (x2 >= r)) return(0);
if ((y1 >= r) && (y2 >= r)) return(0);
x2 -= x1; y2 -= y1;
if (x2*(walldist-y1) >= y2*(walldist-x1)) //Front
{
if (x2 > 0) x2 *= (0-y1); else x2 *= (r-y1);
if (y2 > 0) y2 *= (r-x1); else y2 *= (0-x1);
return(x2 < y2);
}
if (x2 > 0) x2 *= (r-y1); else x2 *= (0-y1);
if (y2 > 0) y2 *= (0-x1); else y2 *= (r-x1);
return((x2 >= y2)<<1);
}
clipinsideboxline(long x, long y, long x1, long y1, long x2, long y2, long walldist)
{
long r;
r = (walldist<<1);
x1 += walldist-x; x2 += walldist-x;
if ((x1 < 0) && (x2 < 0)) return(0);
if ((x1 >= r) && (x2 >= r)) return(0);
y1 += walldist-y; y2 += walldist-y;
if ((y1 < 0) && (y2 < 0)) return(0);
if ((y1 >= r) && (y2 >= r)) return(0);
x2 -= x1; y2 -= y1;
if (x2*(walldist-y1) >= y2*(walldist-x1)) //Front
{
if (x2 > 0) x2 *= (0-y1); else x2 *= (r-y1);
if (y2 > 0) y2 *= (r-x1); else y2 *= (0-x1);
return(x2 < y2);
}
if (x2 > 0) x2 *= (r-y1); else x2 *= (0-y1);
if (y2 > 0) y2 *= (0-x1); else y2 *= (r-x1);
return((x2 >= y2)<<1);
}
readpixel16(long p)
{
long mask, dat;
mask = pow2long[p&7^7];
if ((qsetmode == 480) && (ydim16 <= 336) && (p >= 640*336))
p -= 640*336;
else
p += pageoffset;
p >>= 3;
koutp(0x3ce,0x4);
koutp(0x3cf,0); dat = ((readpixel(p+0xa0000)&mask)>0);
koutp(0x3cf,1); dat += (((readpixel(p+0xa0000)&mask)>0)<<1);
koutp(0x3cf,2); dat += (((readpixel(p+0xa0000)&mask)>0)<<2);
koutp(0x3cf,3); dat += (((readpixel(p+0xa0000)&mask)>0)<<3);
return(dat);
}
screencapture(char *filename, char inverseit)
{
char *ptr;
long fil, i, bufplc, p, col, ncol, leng, numbytes, xres;
filename[4] = ((capturecount/1000)%10)+48;
filename[5] = ((capturecount/100)%10)+48;
filename[6] = ((capturecount/10)%10)+48;
filename[7] = (capturecount%10)+48;
if ((fil=open(filename,O_BINARY|O_CREAT|O_TRUNC|O_WRONLY,S_IWRITE))==-1)
return(-1);
if (qsetmode == 200)
{
pcxheader[8] = ((xdim-1)&255); pcxheader[9] = (((xdim-1)>>8)&255);
pcxheader[10] = ((ydim-1)&255); pcxheader[11] = (((ydim-1)>>8)&255);
pcxheader[12] = (xdim&255); pcxheader[13] = ((xdim>>8)&255);
pcxheader[14] = (ydim&255); pcxheader[15] = ((ydim>>8)&255);
pcxheader[66] = (xdim&255); pcxheader[67] = ((xdim>>8)&255);
}
else
{
pcxheader[8] = ((640-1)&255); pcxheader[9] = (((640-1)>>8)&255);
pcxheader[10] = ((qsetmode-1)&255); pcxheader[11] = (((qsetmode-1)>>8)&255);
pcxheader[12] = (640&255); pcxheader[13] = ((640>>8)&255);
pcxheader[14] = (qsetmode&255); pcxheader[15] = ((qsetmode>>8)&255);
pcxheader[66] = (640&255); pcxheader[67] = ((640>>8)&255);
}
write(fil,&pcxheader[0],128);
if (qsetmode == 200)
{
ptr = (char *)frameplace;
numbytes = xdim*ydim;
xres = xdim;
}
else
{
numbytes = (mul5(qsetmode)<<7);
xres = 640;
}
bufplc = 0; p = 0;
while (p < numbytes)
{
koutp(97,kinp(97)|3);
if (qsetmode == 200) { col = *ptr; p++; ptr++; }
else
{
col = readpixel16(p);
p++;
if ((inverseit == 1) && (((col&7) == 0) || ((col&7) == 7))) col ^= 15;
}
leng = 1;
if (qsetmode == 200) ncol = *ptr;
else
{
ncol = readpixel16(p);
if ((inverseit == 1) && (((ncol&7) == 0) || ((ncol&7) == 7))) ncol ^= 15;
}
while ((ncol == col) && (p < numbytes) && (leng < 63) && ((p%xres) != 0))
{
leng++;
if (qsetmode == 200) { p++; ptr++; ncol = *ptr; }
else
{
p++;
ncol = readpixel16(p);
if ((inverseit == 1) && (((ncol&7) == 0) || ((ncol&7) == 7))) ncol ^= 15;
}
}
koutp(97,kinp(97)&252);
if ((leng > 1) || (col >= 0xc0))
{
tempbuf[bufplc++] = (leng|0xc0);
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
}
tempbuf[bufplc++] = col;
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
}
tempbuf[bufplc++] = 0xc;
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
if (qsetmode == 200)
{
VBE_getPalette(0,256,&tempbuf[4096]);
for(i=0;i<256;i++)
{
tempbuf[bufplc++] = (tempbuf[(i<<2)+4096+2]<<2);
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
tempbuf[bufplc++] = (tempbuf[(i<<2)+4096+1]<<2);
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
tempbuf[bufplc++] = (tempbuf[(i<<2)+4096+0]<<2);
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
}
}
else
{
for(i=0;i<768;i++)
{
if (i < 48)
tempbuf[bufplc++] = (vgapal16[i]<<2);
else
tempbuf[bufplc++] = 0;
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
}
}
if (bufplc > 0)
if (write(fil,&tempbuf[0],bufplc) < bufplc) { close(fil); return(-1); }
close(fil);
capturecount++;
return(0);
}
inside (long x, long y, short sectnum)
{
walltype *wal;
long i, x1, y1, x2, y2;
unsigned long cnt;
if ((sectnum < 0) || (sectnum >= numsectors)) return(-1);
cnt = 0;
wal = &wall[sector[sectnum].wallptr];
i = sector[sectnum].wallnum;
do
{
y1 = wal->y-y; y2 = wall[wal->point2].y-y;
if ((y1^y2) < 0)
{
x1 = wal->x-x; x2 = wall[wal->point2].x-x;
if ((x1^x2) >= 0) cnt ^= x1; else cnt ^= (x1*y2-x2*y1)^y2;
}
wal++; i--;
} while (i);
return(cnt>>31);
}
getangle(long xvect, long yvect)
{
if ((xvect|yvect) == 0) return(0);
if (xvect == 0) return(512+((yvect<0)<<10));
if (yvect == 0) return(((xvect<0)<<10));
if (xvect == yvect) return(256+((xvect<0)<<10));
if (xvect == -yvect) return(768+((xvect>0)<<10));
if (klabs(xvect) > klabs(yvect))
return(((radarang[640+scale(160,yvect,xvect)]>>6)+((xvect<0)<<10))&2047);
return(((radarang[640-scale(160,xvect,yvect)]>>6)+512+((yvect<0)<<10))&2047);
}
ksqrt(long num)
{
return(nsqrtasm(num));
}
krecip(long num)
{
return(krecipasm(num));
}
initksqrt()
{
long i, j, k;
j = 1; k = 0;
for(i=0;i<4096;i++)
{
if (i >= j) { j <<= 2; k++; }
sqrtable[i] = (unsigned short)(msqrtasm((i<<18)+131072)<<1);
shlookup[i] = (k<<1)+((10-k)<<8);
if (i < 256) shlookup[i+4096] = ((k+6)<<1)+((10-(k+6))<<8);
}
}
copytilepiece(long tilenume1, long sx1, long sy1, long xsiz, long ysiz,
long tilenume2, long sx2, long sy2)
{
char *ptr1, *ptr2, dat;
long xsiz1, ysiz1, xsiz2, ysiz2, i, j, x1, y1, x2, y2;
xsiz1 = tilesizx[tilenume1]; ysiz1 = tilesizy[tilenume1];
xsiz2 = tilesizx[tilenume2]; ysiz2 = tilesizy[tilenume2];
if ((xsiz1 > 0) && (ysiz1 > 0) && (xsiz2 > 0) && (ysiz2 > 0))
{
if (waloff[tilenume1] == 0) loadtile(tilenume1);
if (waloff[tilenume2] == 0) loadtile(tilenume2);
x1 = sx1;
for(i=0;i<xsiz;i++)
{
y1 = sy1;
for(j=0;j<ysiz;j++)
{
x2 = sx2+i;
y2 = sy2+j;
if ((x2 >= 0) && (y2 >= 0) && (x2 < xsiz2) && (y2 < ysiz2))
{
ptr1 = (char *)(waloff[tilenume1] + x1*ysiz1 + y1);
ptr2 = (char *)(waloff[tilenume2] + x2*ysiz2 + y2);
dat = *ptr1;
if (dat != 255)
*ptr2 = *ptr1;
}
y1++; if (y1 >= ysiz1) y1 = 0;
}
x1++; if (x1 >= xsiz1) x1 = 0;
}
}
}
drawmasks()
{
long i, j, k, l, gap, xs, ys, zs, xp, yp, zp, z1, z2, yoff, yspan;
for(i=spritesortcnt-1;i>=0;i--) tspriteptr[i] = &tsprite[i];
for(i=spritesortcnt-1;i>=0;i--)
{
xs = tspriteptr[i]->x-globalposx; ys = tspriteptr[i]->y-globalposy;
yp = dmulscale6(xs,cosviewingrangeglobalang,ys,sinviewingrangeglobalang);
if (yp > (4<<8))
{
xp = dmulscale6(ys,cosglobalang,-xs,singlobalang);
spritesx[i] = scale(xp+yp,xdimen<<7,yp);
}
else if ((tspriteptr[i]->cstat&48) == 0)
{
spritesortcnt--; //Delete face sprite if on wrong side!
if (i != spritesortcnt)
{
tspriteptr[i] = tspriteptr[spritesortcnt];
spritesx[i] = spritesx[spritesortcnt];
spritesy[i] = spritesy[spritesortcnt];
}
continue;
}
spritesy[i] = yp;
}
gap = 1; while (gap < spritesortcnt) gap = (gap<<1)+1;
for(gap>>=1;gap>0;gap>>=1) //Sort sprite list
for(i=0;i<spritesortcnt-gap;i++)
for(l=i;l>=0;l-=gap)
{
if (spritesy[l] <= spritesy[l+gap]) break;
swaplong(&tspriteptr[l],&tspriteptr[l+gap]);
swaplong(&spritesx[l],&spritesx[l+gap]);
swaplong(&spritesy[l],&spritesy[l+gap]);
}
if (spritesortcnt > 0)
spritesy[spritesortcnt] = (spritesy[spritesortcnt-1]^1);
ys = spritesy[0]; i = 0;
for(j=1;j<=spritesortcnt;j++)
{
if (spritesy[j] == ys) continue;
ys = spritesy[j];
if (j > i+1)
{
for(k=i;k<j;k++)
{
spritesz[k] = tspriteptr[k]->z;
if ((tspriteptr[k]->cstat&48) != 32)
{
yoff = (long)((signed char)((picanm[tspriteptr[k]->picnum]>>16)&255))+((long)tspriteptr[k]->yoffset);
spritesz[k] -= ((yoff*tspriteptr[k]->yrepeat)<<2);
yspan = (tilesizy[tspriteptr[k]->picnum]*tspriteptr[k]->yrepeat<<2);
if (!(tspriteptr[k]->cstat&128)) spritesz[k] -= (yspan>>1);
if (klabs(spritesz[k]-globalposz) < (yspan>>1)) spritesz[k] = globalposz;
}
}
for(k=i+1;k<j;k++)
for(l=i;l<k;l++)
if (klabs(spritesz[k]-globalposz) < klabs(spritesz[l]-globalposz))
{
swaplong(&tspriteptr[k],&tspriteptr[l]);
swaplong(&spritesx[k],&spritesx[l]);
swaplong(&spritesy[k],&spritesy[l]);
swaplong(&spritesz[k],&spritesz[l]);
}
for(k=i+1;k<j;k++)
for(l=i;l<k;l++)
if (tspriteptr[k]->statnum < tspriteptr[l]->statnum)
{
swaplong(&tspriteptr[k],&tspriteptr[l]);
swaplong(&spritesx[k],&spritesx[l]);
swaplong(&spritesy[k],&spritesy[l]);
}
}
i = j;
}
/*for(i=spritesortcnt-1;i>=0;i--)
{
xs = tspriteptr[i].x-globalposx;
ys = tspriteptr[i].y-globalposy;
zs = tspriteptr[i].z-globalposz;
xp = ys*cosglobalang-xs*singlobalang;
yp = (zs<<1);
zp = xs*cosglobalang+ys*singlobalang;
xs = scale(xp,halfxdimen<<12,zp)+((halfxdimen+windowx1)<<12);
ys = scale(yp,xdimenscale<<12,zp)+((globalhoriz+windowy1)<<12);
drawline256(xs-65536,ys-65536,xs+65536,ys+65536,31);
drawline256(xs+65536,ys-65536,xs-65536,ys+65536,31);
}*/
while ((spritesortcnt > 0) && (maskwallcnt > 0)) //While BOTH > 0
{
j = maskwall[maskwallcnt-1];
if (spritewallfront(tspriteptr[spritesortcnt-1],(long)thewall[j]) == 0)
drawsprite(--spritesortcnt);
else
{
//Check to see if any sprites behind the masked wall...
k = -1;
gap = 0;
for(i=spritesortcnt-2;i>=0;i--)
if ((xb1[j] <= (spritesx[i]>>8)) && ((spritesx[i]>>8) <= xb2[j]))
if (spritewallfront(tspriteptr[i],(long)thewall[j]) == 0)
{
drawsprite(i);
tspriteptr[i]->owner = -1;
k = i;
gap++;
}
if (k >= 0) //remove holes in sprite list
{
for(i=k;i<spritesortcnt;i++)
if (tspriteptr[i]->owner >= 0)
{
if (i > k)
{
tspriteptr[k] = tspriteptr[i];
spritesx[k] = spritesx[i];
spritesy[k] = spritesy[i];
}
k++;
}
spritesortcnt -= gap;
}
//finally safe to draw the masked wall
drawmaskwall(--maskwallcnt);
}
}
while (spritesortcnt > 0) drawsprite(--spritesortcnt);
while (maskwallcnt > 0) drawmaskwall(--maskwallcnt);
}
drawmaskwall(short damaskwallcnt)
{
long i, j, k, x, z, sectnum, z1, z2, lx, rx;
sectortype *sec, *nsec;
walltype *wal;
z = maskwall[damaskwallcnt];
wal = &wall[thewall[z]];
sectnum = thesector[z]; sec = &sector[sectnum];
nsec = &sector[wal->nextsector];
z1 = max(nsec->ceilingz,sec->ceilingz);
z2 = min(nsec->floorz,sec->floorz);
wallmost(uwall,z,sectnum,(char)0);
wallmost(uplc,z,(long)wal->nextsector,(char)0);
for(x=xb1[z];x<=xb2[z];x++) if (uplc[x] > uwall[x]) uwall[x] = uplc[x];
wallmost(dwall,z,sectnum,(char)1);
wallmost(dplc,z,(long)wal->nextsector,(char)1);
for(x=xb1[z];x<=xb2[z];x++) if (dplc[x] < dwall[x]) dwall[x] = dplc[x];
prepwall(z,wal);
globalorientation = (long)wal->cstat;
globalpicnum = wal->overpicnum;
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
globalxpanning = (long)wal->xpanning;
globalypanning = (long)wal->ypanning;
if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)thewall[z]+16384);
globalshade = (long)wal->shade;
globvis = globalvisibility;
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
globalpal = (long)wal->pal;
globalshiftval = (picsiz[globalpicnum]>>4);
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
globalshiftval = 32-globalshiftval;
globalyscale = (wal->yrepeat<<(globalshiftval-19));
if ((globalorientation&4) == 0)
globalzd = (((globalposz-z1)*globalyscale)<<8);
else
globalzd = (((globalposz-z2)*globalyscale)<<8);
globalzd += (globalypanning<<24);
if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
for(i=smostwallcnt-1;i>=0;i--)
{
j = smostwall[i];
if ((xb1[j] > xb2[z]) || (xb2[j] < xb1[z])) continue;
if (wallfront(j,z)) continue;
lx = max(xb1[j],xb1[z]); rx = min(xb2[j],xb2[z]);
switch(smostwalltype[i])
{
case 0:
if (lx <= rx)
{
if ((lx == xb1[z]) && (rx == xb2[z])) return;
clearbufbyte((long)&dwall[lx],(rx-lx+1)*sizeof(dwall[0]),0L);
}
break;
case 1:
k = smoststart[i] - xb1[j];
for(x=lx;x<=rx;x++)
if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
break;
case 2:
k = smoststart[i] - xb1[j];
for(x=lx;x<=rx;x++)
if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
break;
}
}
//maskwall
if ((searchit >= 1) && (searchx >= xb1[z]) && (searchx <= xb2[z]))
if ((searchy >= uwall[searchx]) && (searchy <= dwall[searchx]))
{
searchsector = sectnum; searchwall = thewall[z];
searchstat = 4; searchit = 1;
}
if ((globalorientation&128) == 0)
maskwallscan(xb1[z],xb2[z],uwall,dwall,swall,lwall);
else
{
if (globalorientation&128)
{
if (globalorientation&512) settransreverse(); else settransnormal();
}
transmaskwallscan(xb1[z],xb2[z]);
}
}
drawsprite (long snum)
{
spritetype *tspr;
sectortype *sec;
long startum, startdm, sectnum, xb, yp, cstat;
long siz, xsiz, ysiz, xoff, yoff, xspan, yspan;
long x1, y1, x2, y2, lx, rx, dalx2, darx2, i, j, k, x, linum, linuminc;
long yplc, yinc, z, z1, z2, xp1, yp1, xp2, yp2;
long xs, ys, xpos, ypos, xv, yv, top, topinc, bot, botinc, hplc, hinc;
long cosang, sinang, dax, day, lpoint, lmax, rpoint, rmax, dax1, dax2, y;
long npoints, npoints2, zz, t, zsgn, zzsgn, *longptr;
signed short shade;
short tilenum, spritenum;
char swapped, daclip;
tspr = tspriteptr[snum];
xb = spritesx[snum];
yp = spritesy[snum];
tilenum = tspr->picnum;
spritenum = tspr->owner;
cstat = tspr->cstat;
if ((cstat&48) != 48)
{
if (picanm[tilenum]&192) tilenum += animateoffs(tilenum,spritenum+32768);
if ((tilesizx[tilenum] <= 0) || (tilesizy[tilenum] <= 0) || (spritenum < 0))
return;
}
if ((tspr->xrepeat <= 0) || (tspr->yrepeat <= 0)) return;
sectnum = tspr->sectnum; sec = &sector[sectnum];
globalpal = tspr->pal;
globalshade = tspr->shade;
if (cstat&2)
{
if (cstat&512) settransreverse(); else settransnormal();
}
xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)tspr->xoffset);
yoff = (long)((signed char)((picanm[tilenum]>>16)&255))+((long)tspr->yoffset);
if ((cstat&48) == 0)
{
if (yp <= (4<<8)) return;
siz = divscale19(xdimenscale,yp);
xv = mulscale16(((long)tspr->xrepeat)<<16,xyaspect);
xspan = tilesizx[tilenum];
yspan = tilesizy[tilenum];
xsiz = mulscale30(siz,xv*xspan);
ysiz = mulscale14(siz,tspr->yrepeat*yspan);
if (((tilesizx[tilenum]>>11) >= xsiz) || (yspan >= (ysiz>>1)))
return; //Watch out for divscale overflow
x1 = xb-(xsiz>>1);
if (xspan&1) x1 += mulscale31(siz,xv); //Odd xspans
i = mulscale30(siz,xv*xoff);
if ((cstat&4) == 0) x1 -= i; else x1 += i;
y1 = mulscale16(tspr->z-globalposz,siz);
y1 -= mulscale14(siz,tspr->yrepeat*yoff);
y1 += (globalhoriz<<8)-ysiz;
if (cstat&128)
{
y1 += (ysiz>>1);
if (yspan&1) y1 += mulscale15(siz,tspr->yrepeat); //Odd yspans
}
x2 = x1+xsiz-1;
y2 = y1+ysiz-1;
if ((y1|255) >= (y2|255)) return;
lx = (x1>>8)+1; if (lx < 0) lx = 0;
rx = (x2>>8); if (rx >= xdimen) rx = xdimen-1;
if (lx > rx) return;
yinc = divscale32(yspan,ysiz);
if ((sec->ceilingstat&3) == 0)
startum = globalhoriz+mulscale24(siz,sec->ceilingz-globalposz)-1;
else
startum = 0;
if ((sec->floorstat&3) == 0)
startdm = globalhoriz+mulscale24(siz,sec->floorz-globalposz)+1;
else
startdm = 0x7fffffff;
if ((y1>>8) > startum) startum = (y1>>8);
if ((y2>>8) < startdm) startdm = (y2>>8);
if (startum < -32768) startum = -32768;
if (startdm > 32767) startdm = 32767;
if (startum >= startdm) return;
if ((cstat&4) == 0)
{
linuminc = divscale24(xspan,xsiz);
linum = mulscale8((lx<<8)-x1,linuminc);
}
else
{
linuminc = -divscale24(xspan,xsiz);
linum = mulscale8((lx<<8)-x2,linuminc);
}
if ((cstat&8) > 0)
{
yinc = -yinc;
i = y1; y1 = y2; y2 = i;
}
for(x=lx;x<=rx;x++)
{
uwall[x] = max(startumost[x+windowx1]-windowy1,(short)startum);
dwall[x] = min(startdmost[x+windowx1]-windowy1,(short)startdm);
}
daclip = 0;
for(i=smostwallcnt-1;i>=0;i--)
{
if (smostwalltype[i]&daclip) continue;
j = smostwall[i];
if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
if (spritewallfront(tspr,(long)thewall[j]) && ((yp <= yb1[j]) || (yp <= yb2[j]))) continue;
dalx2 = max(xb1[j],lx); darx2 = min(xb2[j],rx);
switch(smostwalltype[i])
{
case 0:
if (dalx2 <= darx2)
{
if ((dalx2 == lx) && (darx2 == rx)) return;
clearbufbyte((long)&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
}
break;
case 1:
k = smoststart[i] - xb1[j];
for(x=dalx2;x<=darx2;x++)
if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
if ((dalx2 == lx) && (darx2 == rx)) daclip |= 1;
break;
case 2:
k = smoststart[i] - xb1[j];
for(x=dalx2;x<=darx2;x++)
if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
if ((dalx2 == lx) && (darx2 == rx)) daclip |= 2;
break;
}
}
if (uwall[rx] >= dwall[rx])
{
for(x=lx;x<rx;x++)
if (uwall[x] < dwall[x]) break;
if (x == rx) return;
}
//sprite
if ((searchit >= 1) && (searchx >= lx) && (searchx <= rx))
if ((searchy >= uwall[searchx]) && (searchy < dwall[searchx]))
{
searchsector = sectnum; searchwall = spritenum;
searchstat = 3; searchit = 1;
}
z2 = tspr->z - ((yoff*tspr->yrepeat)<<2);
if (cstat&128)
{
z2 += ((yspan*tspr->yrepeat)<<1);
if (yspan&1) z2 += (tspr->yrepeat<<1); //Odd yspans
}
z1 = z2 - ((yspan*tspr->yrepeat)<<2);
globalorientation = 0;
globalpicnum = tilenum;
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
globalxpanning = 0L;
globalypanning = 0L;
globvis = globalvisibility;
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
globalshiftval = (picsiz[globalpicnum]>>4);
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
globalshiftval = 32-globalshiftval;
globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
globalzd = (((globalposz-z1)*globalyscale)<<8);
if ((cstat&8) > 0)
{
globalyscale = -globalyscale;
globalzd = (((globalposz-z2)*globalyscale)<<8);
}
qinterpolatedown16((long)&lwall[lx],rx-lx+1,linum,linuminc);
clearbuf((long)&swall[lx],rx-lx+1,mulscale19(yp,xdimscale));
if ((cstat&2) == 0)
maskwallscan(lx,rx,uwall,dwall,swall,lwall);
else
transmaskwallscan(lx,rx);
}
else if ((cstat&48) == 16)
{
if ((cstat&4) > 0) xoff = -xoff;
if ((cstat&8) > 0) yoff = -yoff;
xspan = tilesizx[tilenum]; yspan = tilesizy[tilenum];
xv = tspr->xrepeat*sintable[(tspr->ang+2560+1536)&2047];
yv = tspr->xrepeat*sintable[(tspr->ang+2048+1536)&2047];
i = (xspan>>1)+xoff;
x1 = tspr->x-globalposx-mulscale16(xv,i); x2 = x1+mulscale16(xv,xspan);
y1 = tspr->y-globalposy-mulscale16(yv,i); y2 = y1+mulscale16(yv,xspan);
yp1 = dmulscale6(x1,cosviewingrangeglobalang,y1,sinviewingrangeglobalang);
yp2 = dmulscale6(x2,cosviewingrangeglobalang,y2,sinviewingrangeglobalang);
if ((yp1 <= 0) && (yp2 <= 0)) return;
xp1 = dmulscale6(y1,cosglobalang,-x1,singlobalang);
xp2 = dmulscale6(y2,cosglobalang,-x2,singlobalang);
x1 += globalposx; y1 += globalposy;
x2 += globalposx; y2 += globalposy;
swapped = 0;
if (dmulscale32(xp1,yp2,-xp2,yp1) >= 0) //If wall's NOT facing you
{
if ((cstat&64) != 0) return;
i = xp1, xp1 = xp2, xp2 = i;
i = yp1, yp1 = yp2, yp2 = i;
i = x1, x1 = x2, x2 = i;
i = y1, y1 = y2, y2 = i;
swapped = 1;
}
if (xp1 >= -yp1)
{
if (xp1 > yp1) return;
if (yp1 == 0) return;
xb1[MAXWALLSB-1] = halfxdimen + scale(xp1,halfxdimen,yp1);
if (xp1 >= 0) xb1[MAXWALLSB-1]++; //Fix for SIGNED divide
if (xb1[MAXWALLSB-1] >= xdimen) xb1[MAXWALLSB-1] = xdimen-1;
yb1[MAXWALLSB-1] = yp1;
}
else
{
if (xp2 < -yp2) return;
xb1[MAXWALLSB-1] = 0;
i = yp1-yp2+xp1-xp2;
if (i == 0) return;
yb1[MAXWALLSB-1] = yp1 + scale(yp2-yp1,xp1+yp1,i);
}
if (xp2 <= yp2)
{
if (xp2 < -yp2) return;
if (yp2 == 0) return;
xb2[MAXWALLSB-1] = halfxdimen + scale(xp2,halfxdimen,yp2) - 1;
if (xp2 >= 0) xb2[MAXWALLSB-1]++; //Fix for SIGNED divide
if (xb2[MAXWALLSB-1] >= xdimen) xb2[MAXWALLSB-1] = xdimen-1;
yb2[MAXWALLSB-1] = yp2;
}
else
{
if (xp1 > yp1) return;
xb2[MAXWALLSB-1] = xdimen-1;
i = xp2-xp1+yp1-yp2;
if (i == 0) return;
yb2[MAXWALLSB-1] = yp1 + scale(yp2-yp1,yp1-xp1,i);
}
if ((yb1[MAXWALLSB-1] < 256) || (yb2[MAXWALLSB-1] < 256) || (xb1[MAXWALLSB-1] > xb2[MAXWALLSB-1]))
return;
topinc = -mulscale10(yp1,xspan);
top = (((mulscale10(xp1,xdimen) - mulscale9(xb1[MAXWALLSB-1]-halfxdimen,yp1))*xspan)>>3);
botinc = ((yp2-yp1)>>8);
bot = mulscale11(xp1-xp2,xdimen) + mulscale2(xb1[MAXWALLSB-1]-halfxdimen,botinc);
j = xb2[MAXWALLSB-1]+3;
z = mulscale20(top,krecipasm(bot));
lwall[xb1[MAXWALLSB-1]] = (z>>8);
for(x=xb1[MAXWALLSB-1]+4;x<=j;x+=4)
{
top += topinc; bot += botinc;
zz = z; z = mulscale20(top,krecipasm(bot));
lwall[x] = (z>>8);
i = ((z+zz)>>1);
lwall[x-2] = (i>>8);
lwall[x-3] = ((i+zz)>>9);
lwall[x-1] = ((i+z)>>9);
}
if (lwall[xb1[MAXWALLSB-1]] < 0) lwall[xb1[MAXWALLSB-1]] = 0;
if (lwall[xb2[MAXWALLSB-1]] >= xspan) lwall[xb2[MAXWALLSB-1]] = xspan-1;
if ((swapped^((cstat&4)>0)) > 0)
{
j = xspan-1;
for(x=xb1[MAXWALLSB-1];x<=xb2[MAXWALLSB-1];x++)
lwall[x] = j-lwall[x];
}
rx1[MAXWALLSB-1] = xp1; ry1[MAXWALLSB-1] = yp1;
rx2[MAXWALLSB-1] = xp2; ry2[MAXWALLSB-1] = yp2;
hplc = divscale19(xdimenscale,yb1[MAXWALLSB-1]);
hinc = divscale19(xdimenscale,yb2[MAXWALLSB-1]);
hinc = (hinc-hplc)/(xb2[MAXWALLSB-1]-xb1[MAXWALLSB-1]+1);
z2 = tspr->z - ((yoff*tspr->yrepeat)<<2);
if (cstat&128)
{
z2 += ((yspan*tspr->yrepeat)<<1);
if (yspan&1) z2 += (tspr->yrepeat<<1); //Odd yspans
}
z1 = z2 - ((yspan*tspr->yrepeat)<<2);
globalorientation = 0;
globalpicnum = tilenum;
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
globalxpanning = 0L;
globalypanning = 0L;
globvis = globalvisibility;
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
globalshiftval = (picsiz[globalpicnum]>>4);
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
globalshiftval = 32-globalshiftval;
globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
globalzd = (((globalposz-z1)*globalyscale)<<8);
if ((cstat&8) > 0)
{
globalyscale = -globalyscale;
globalzd = (((globalposz-z2)*globalyscale)<<8);
}
if (((sec->ceilingstat&1) == 0) && (z1 < sec->ceilingz))
z1 = sec->ceilingz;
if (((sec->floorstat&1) == 0) && (z2 > sec->floorz))
z2 = sec->floorz;
owallmost(uwall,(long)(MAXWALLSB-1),z1-globalposz);
owallmost(dwall,(long)(MAXWALLSB-1),z2-globalposz);
for(i=xb1[MAXWALLSB-1];i<=xb2[MAXWALLSB-1];i++)
{ swall[i] = (krecipasm(hplc)<<2); hplc += hinc; }
for(i=smostwallcnt-1;i>=0;i--)
{
j = smostwall[i];
if ((xb1[j] > xb2[MAXWALLSB-1]) || (xb2[j] < xb1[MAXWALLSB-1])) continue;
dalx2 = xb1[j]; darx2 = xb2[j];
if (max(yb1[MAXWALLSB-1],yb2[MAXWALLSB-1]) > min(yb1[j],yb2[j]))
{
if (min(yb1[MAXWALLSB-1],yb2[MAXWALLSB-1]) > max(yb1[j],yb2[j]))
{
x = 0x80000000;
}
else
{
x = thewall[j]; xp1 = wall[x].x; yp1 = wall[x].y;
x = wall[x].point2; xp2 = wall[x].x; yp2 = wall[x].y;
z1 = (xp2-xp1)*(y1-yp1) - (yp2-yp1)*(x1-xp1);
z2 = (xp2-xp1)*(y2-yp1) - (yp2-yp1)*(x2-xp1);
if ((z1^z2) >= 0)
x = (z1+z2);
else
{
z1 = (x2-x1)*(yp1-y1) - (y2-y1)*(xp1-x1);
z2 = (x2-x1)*(yp2-y1) - (y2-y1)*(xp2-x1);
if ((z1^z2) >= 0)
x = -(z1+z2);
else
{
if ((xp2-xp1)*(tspr->y-yp1) == (tspr->x-xp1)*(yp2-yp1))
{
if (wall[thewall[j]].nextsector == tspr->sectnum)
x = 0x80000000;
else
x = 0x7fffffff;
}
else
{ //INTERSECTION!
x = (xp1-globalposx) + scale(xp2-xp1,z1,z1-z2);
y = (yp1-globalposy) + scale(yp2-yp1,z1,z1-z2);
yp1 = dmulscale14(x,cosglobalang,y,singlobalang);
if (yp1 > 0)
{
xp1 = dmulscale14(y,cosglobalang,-x,singlobalang);
x = halfxdimen + scale(xp1,halfxdimen,yp1);
if (xp1 >= 0) x++; //Fix for SIGNED divide
if (z1 < 0)
{ if (dalx2 < x) dalx2 = x; }
else
{ if (darx2 > x) darx2 = x; }
x = 0x80000001;
}
else
x = 0x7fffffff;
}
}
}
}
if (x < 0)
{
if (dalx2 < xb1[MAXWALLSB-1]) dalx2 = xb1[MAXWALLSB-1];
if (darx2 > xb2[MAXWALLSB-1]) darx2 = xb2[MAXWALLSB-1];
switch(smostwalltype[i])
{
case 0:
if (dalx2 <= darx2)
{
if ((dalx2 == xb1[MAXWALLSB-1]) && (darx2 == xb2[MAXWALLSB-1])) return;
clearbufbyte((long)&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
}
break;
case 1:
k = smoststart[i] - xb1[j];
for(x=dalx2;x<=darx2;x++)
if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
break;
case 2:
k = smoststart[i] - xb1[j];
for(x=dalx2;x<=darx2;x++)
if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
break;
}
}
}
}
//sprite
if ((searchit >= 1) && (searchx >= xb1[MAXWALLSB-1]) && (searchx <= xb2[MAXWALLSB-1]))
if ((searchy >= uwall[searchx]) && (searchy <= dwall[searchx]))
{
searchsector = sectnum; searchwall = spritenum;
searchstat = 3; searchit = 1;
}
if ((cstat&2) == 0)
maskwallscan(xb1[MAXWALLSB-1],xb2[MAXWALLSB-1],uwall,dwall,swall,lwall);
else
transmaskwallscan(xb1[MAXWALLSB-1],xb2[MAXWALLSB-1]);
}
else if ((cstat&48) == 32)
{
if ((cstat&64) != 0)
if ((globalposz > tspr->z) == ((cstat&8)==0))
return;
if ((cstat&4) > 0) xoff = -xoff;
if ((cstat&8) > 0) yoff = -yoff;
xspan = tilesizx[tilenum];
yspan = tilesizy[tilenum];
//Rotate center point
dax = tspr->x-globalposx;
day = tspr->y-globalposy;
rzi[0] = dmulscale10(cosglobalang,dax,singlobalang,day);
rxi[0] = dmulscale10(cosglobalang,day,-singlobalang,dax);
//Get top-left corner
i = ((tspr->ang+2048-globalang)&2047);
cosang = sintable[(i+512)&2047]; sinang = sintable[i];
dax = ((xspan>>1)+xoff)*tspr->xrepeat;
day = ((yspan>>1)+yoff)*tspr->yrepeat;
rzi[0] += dmulscale12(sinang,dax,cosang,day);
rxi[0] += dmulscale12(sinang,day,-cosang,dax);
//Get other 3 corners
dax = xspan*tspr->xrepeat;
day = yspan*tspr->yrepeat;
rzi[1] = rzi[0]-mulscale12(sinang,dax);
rxi[1] = rxi[0]+mulscale12(cosang,dax);
dax = -mulscale12(cosang,day);
day = -mulscale12(sinang,day);
rzi[2] = rzi[1]+dax; rxi[2] = rxi[1]+day;
rzi[3] = rzi[0]+dax; rxi[3] = rxi[0]+day;
//Put all points on same z
ryi[0] = scale((tspr->z-globalposz),yxaspect,320<<8);
if (ryi[0] == 0) return;
ryi[1] = ryi[2] = ryi[3] = ryi[0];
if ((cstat&4) == 0)
{ z = 0; z1 = 1; z2 = 3; }
else
{ z = 1; z1 = 0; z2 = 2; }
dax = rzi[z1]-rzi[z]; day = rxi[z1]-rxi[z];
bot = dmulscale8(dax,dax,day,day);
if (((klabs(dax)>>13) >= bot) || ((klabs(day)>>13) >= bot)) return;
globalx1 = divscale18(dax,bot);
globalx2 = divscale18(day,bot);
dax = rzi[z2]-rzi[z]; day = rxi[z2]-rxi[z];
bot = dmulscale8(dax,dax,day,day);
if (((klabs(dax)>>13) >= bot) || ((klabs(day)>>13) >= bot)) return;
globaly1 = divscale18(dax,bot);
globaly2 = divscale18(day,bot);
//Calculate globals for hline texture mapping function
globalxpanning = (rxi[z]<<12);
globalypanning = (rzi[z]<<12);
globalzd = (ryi[z]<<12);
rzi[0] = mulscale16(rzi[0],viewingrange);
rzi[1] = mulscale16(rzi[1],viewingrange);
rzi[2] = mulscale16(rzi[2],viewingrange);
rzi[3] = mulscale16(rzi[3],viewingrange);
if (ryi[0] < 0) //If ceilsprite is above you, reverse order of points
{
i = rxi[1]; rxi[1] = rxi[3]; rxi[3] = i;
i = rzi[1]; rzi[1] = rzi[3]; rzi[3] = i;
}
//Clip polygon in 3-space
npoints = 4;
//Clip edge 1
npoints2 = 0;
zzsgn = rxi[0]+rzi[0];
for(z=0;z<npoints;z++)
{
zz = z+1; if (zz == npoints) zz = 0;
zsgn = zzsgn; zzsgn = rxi[zz]+rzi[zz];
if (zsgn >= 0)
{
rxi2[npoints2] = rxi[z]; ryi2[npoints2] = ryi[z]; rzi2[npoints2] = rzi[z];
npoints2++;
}
if ((zsgn^zzsgn) < 0)
{
t = divscale30(zsgn,zsgn-zzsgn);
rxi2[npoints2] = rxi[z] + mulscale30(t,rxi[zz]-rxi[z]);
ryi2[npoints2] = ryi[z] + mulscale30(t,ryi[zz]-ryi[z]);
rzi2[npoints2] = rzi[z] + mulscale30(t,rzi[zz]-rzi[z]);
npoints2++;
}
}
if (npoints2 <= 2) return;
//Clip edge 2
npoints = 0;
zzsgn = rxi2[0]-rzi2[0];
for(z=0;z<npoints2;z++)
{
zz = z+1; if (zz == npoints2) zz = 0;
zsgn = zzsgn; zzsgn = rxi2[zz]-rzi2[zz];
if (zsgn <= 0)
{
rxi[npoints] = rxi2[z]; ryi[npoints] = ryi2[z]; rzi[npoints] = rzi2[z];
npoints++;
}
if ((zsgn^zzsgn) < 0)
{
t = divscale30(zsgn,zsgn-zzsgn);
rxi[npoints] = rxi2[z] + mulscale30(t,rxi2[zz]-rxi2[z]);
ryi[npoints] = ryi2[z] + mulscale30(t,ryi2[zz]-ryi2[z]);
rzi[npoints] = rzi2[z] + mulscale30(t,rzi2[zz]-rzi2[z]);
npoints++;
}
}
if (npoints <= 2) return;
//Clip edge 3
npoints2 = 0;
zzsgn = ryi[0]*halfxdimen + (rzi[0]*(globalhoriz-0));
for(z=0;z<npoints;z++)
{
zz = z+1; if (zz == npoints) zz = 0;
zsgn = zzsgn; zzsgn = ryi[zz]*halfxdimen + (rzi[zz]*(globalhoriz-0));
if (zsgn >= 0)
{
rxi2[npoints2] = rxi[z];
ryi2[npoints2] = ryi[z];
rzi2[npoints2] = rzi[z];
npoints2++;
}
if ((zsgn^zzsgn) < 0)
{
t = divscale30(zsgn,zsgn-zzsgn);
rxi2[npoints2] = rxi[z] + mulscale30(t,rxi[zz]-rxi[z]);
ryi2[npoints2] = ryi[z] + mulscale30(t,ryi[zz]-ryi[z]);
rzi2[npoints2] = rzi[z] + mulscale30(t,rzi[zz]-rzi[z]);
npoints2++;
}
}
if (npoints2 <= 2) return;
//Clip edge 4
npoints = 0;
zzsgn = ryi2[0]*halfxdimen + (rzi2[0]*(globalhoriz-ydimen));
for(z=0;z<npoints2;z++)
{
zz = z+1; if (zz == npoints2) zz = 0;
zsgn = zzsgn; zzsgn = ryi2[zz]*halfxdimen + (rzi2[zz]*(globalhoriz-ydimen));
if (zsgn <= 0)
{
rxi[npoints] = rxi2[z];
ryi[npoints] = ryi2[z];
rzi[npoints] = rzi2[z];
npoints++;
}
if ((zsgn^zzsgn) < 0)
{
t = divscale30(zsgn,zsgn-zzsgn);
rxi[npoints] = rxi2[z] + mulscale30(t,rxi2[zz]-rxi2[z]);
ryi[npoints] = ryi2[z] + mulscale30(t,ryi2[zz]-ryi2[z]);
rzi[npoints] = rzi2[z] + mulscale30(t,rzi2[zz]-rzi2[z]);
npoints++;
}
}
if (npoints <= 2) return;
//Project onto screen
lpoint = -1; lmax = 0x7fffffff;
rpoint = -1; rmax = 0x80000000;
for(z=0;z<npoints;z++)
{
xsi[z] = scale(rxi[z],xdimen<<15,rzi[z]) + (xdimen<<15);
ysi[z] = scale(ryi[z],xdimen<<15,rzi[z]) + (globalhoriz<<16);
if (xsi[z] < 0) xsi[z] = 0;
if (xsi[z] > (xdimen<<16)) xsi[z] = (xdimen<<16);
if (ysi[z] < ((long)0<<16)) ysi[z] = ((long)0<<16);
if (ysi[z] > ((long)ydimen<<16)) ysi[z] = ((long)ydimen<<16);
if (xsi[z] < lmax) lmax = xsi[z], lpoint = z;
if (xsi[z] > rmax) rmax = xsi[z], rpoint = z;
}
//Get uwall arrays
for(z=lpoint;z!=rpoint;z=zz)
{
zz = z+1; if (zz == npoints) zz = 0;
dax1 = ((xsi[z]+65535)>>16);
dax2 = ((xsi[zz]+65535)>>16);
if (dax2 > dax1)
{
yinc = divscale16(ysi[zz]-ysi[z],xsi[zz]-xsi[z]);
y = ysi[z] + mulscale16((dax1<<16)-xsi[z],yinc);
qinterpolatedown16short((long)(&uwall[dax1]),dax2-dax1,y,yinc);
}
}
//Get dwall arrays
for(;z!=lpoint;z=zz)
{
zz = z+1; if (zz == npoints) zz = 0;
dax1 = ((xsi[zz]+65535)>>16);
dax2 = ((xsi[z]+65535)>>16);
if (dax2 > dax1)
{
yinc = divscale16(ysi[zz]-ysi[z],xsi[zz]-xsi[z]);
y = ysi[zz] + mulscale16((dax1<<16)-xsi[zz],yinc);
qinterpolatedown16short((long)(&dwall[dax1]),dax2-dax1,y,yinc);
}
}
lx = ((lmax+65535)>>16);
rx = ((rmax+65535)>>16);
for(x=lx;x<=rx;x++)
{
uwall[x] = max(uwall[x],startumost[x+windowx1]-windowy1);
dwall[x] = min(dwall[x],startdmost[x+windowx1]-windowy1);
}
//Additional uwall/dwall clipping goes here
for(i=smostwallcnt-1;i>=0;i--)
{
j = smostwall[i];
if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
//if (spritewallfront(tspr,thewall[j]) == 0)
x = thewall[j]; xp1 = wall[x].x; yp1 = wall[x].y;
x = wall[x].point2; xp2 = wall[x].x; yp2 = wall[x].y;
x = (xp2-xp1)*(tspr->y-yp1)-(tspr->x-xp1)*(yp2-yp1);
if ((yp > yb1[j]) && (yp > yb2[j])) x = -1;
if ((x >= 0) && ((x != 0) || (wall[thewall[j]].nextsector != tspr->sectnum))) continue;
dalx2 = max(xb1[j],lx); darx2 = min(xb2[j],rx);
switch(smostwalltype[i])
{
case 0:
if (dalx2 <= darx2)
{
if ((dalx2 == lx) && (darx2 == rx)) return;
clearbufbyte((long)&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
}
break;
case 1:
k = smoststart[i] - xb1[j];
for(x=dalx2;x<=darx2;x++)
if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
break;
case 2:
k = smoststart[i] - xb1[j];
for(x=dalx2;x<=darx2;x++)
if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
break;
}
}
//sprite
if ((searchit >= 1) && (searchx >= lx) && (searchx <= rx))
if ((searchy >= uwall[searchx]) && (searchy <= dwall[searchx]))
{
searchsector = sectnum; searchwall = spritenum;
searchstat = 3; searchit = 1;
}
globalorientation = cstat;
globalpicnum = tilenum;
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
//if (picanm[globalpicnum]&192) globalpicnum += animateoffs((short)globalpicnum,spritenum+32768);
if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
setgotpic(globalpicnum);
globalbufplc = waloff[globalpicnum];
globvis = mulscale16(globalhisibility,viewingrange);
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
x = picsiz[globalpicnum]; y = ((x>>4)&15); x &= 15;
if (pow2long[x] != xspan)
{
x++;
globalx1 = mulscale(globalx1,xspan,x);
globalx2 = mulscale(globalx2,xspan,x);
}
dax = globalxpanning; day = globalypanning;
globalxpanning = -dmulscale6(globalx1,day,globalx2,dax);
globalypanning = -dmulscale6(globaly1,day,globaly2,dax);
globalx2 = mulscale16(globalx2,viewingrange);
globaly2 = mulscale16(globaly2,viewingrange);
globalzd = mulscale16(globalzd,viewingrangerecip);
globalx1 = (globalx1-globalx2)*halfxdimen;
globaly1 = (globaly1-globaly2)*halfxdimen;
if ((cstat&2) == 0)
msethlineshift(x,y);
else
tsethlineshift(x,y);
//Draw it!
ceilspritescan(lx,rx-1);
}
#ifdef SUPERBUILD
else if ((cstat&48) == 48)
{
lx = 0; rx = xdim-1;
for(x=lx;x<=rx;x++)
{
lwall[x] = (long)startumost[x+windowx1]-windowy1;
swall[x] = (long)startdmost[x+windowx1]-windowy1;
}
for(i=smostwallcnt-1;i>=0;i--)
{
j = smostwall[i];
if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
if (spritewallfront(tspr,(long)thewall[j]) && ((yp <= yb1[j]) || (yp <= yb2[j]))) continue;
dalx2 = max(xb1[j],lx); darx2 = min(xb2[j],rx);
switch(smostwalltype[i])
{
case 0:
if (dalx2 <= darx2)
{
if ((dalx2 == lx) && (darx2 == rx)) return;
clearbufbyte((long)&swall[dalx2],(darx2-dalx2+1)*sizeof(swall[0]),0L);
}
break;
case 1:
k = smoststart[i] - xb1[j];
for(x=dalx2;x<=darx2;x++)
if (smost[k+x] > lwall[x]) lwall[x] = smost[k+x];
break;
case 2:
k = smoststart[i] - xb1[j];
for(x=dalx2;x<=darx2;x++)
if (smost[k+x] < swall[x]) swall[x] = smost[k+x];
break;
}
}
if (lwall[rx] >= swall[rx])
{
for(x=lx;x<rx;x++)
if (lwall[x] < swall[x]) break;
if (x == rx) return;
}
for(i=0;i<MAXVOXMIPS;i++)
if (!voxoff[tilenum][i])
{
kloadvoxel(tilenum);
break;
}
longptr = (long *)voxoff[tilenum][0];
if (!(cstat&128)) tspr->z -= mulscale6(longptr[5],(long)tspr->yrepeat);
yoff = (long)((signed char)((picanm[sprite[tspr->owner].picnum]>>16)&255))+((long)tspr->yoffset);
tspr->z -= ((yoff*tspr->yrepeat)<<2);
globvis = globalvisibility;
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
if ((searchit >= 1) && (yp > (4<<8)) && (searchy >= lwall[searchx]) && (searchy < swall[searchx]))
{
siz = divscale19(xdimenscale,yp);
xv = mulscale16(((long)tspr->xrepeat)<<16,xyaspect);
xspan = ((longptr[0]+longptr[1])>>1);
yspan = longptr[2];
xsiz = mulscale30(siz,xv*xspan);
ysiz = mulscale14(siz,tspr->yrepeat*yspan);
//Watch out for divscale overflow
if (((xspan>>11) < xsiz) && (yspan < (ysiz>>1)))
{
x1 = xb-(xsiz>>1);
if (xspan&1) x1 += mulscale31(siz,xv); //Odd xspans
i = mulscale30(siz,xv*xoff);
if ((cstat&4) == 0) x1 -= i; else x1 += i;
y1 = mulscale16(tspr->z-globalposz,siz);
//y1 -= mulscale14(siz,tspr->yrepeat*yoff);
y1 += (globalhoriz<<8)-ysiz;
//if (cstat&128) //Already fixed up above
y1 += (ysiz>>1);
x2 = x1+xsiz-1;
y2 = y1+ysiz-1;
if (((y1|255) < (y2|255)) && (searchx >= (x1>>8)+1) && (searchx <= (x2>>8)))
{
if ((sec->ceilingstat&3) == 0)
startum = globalhoriz+mulscale24(siz,sec->ceilingz-globalposz)-1;
else
startum = 0;
if ((sec->floorstat&3) == 0)
startdm = globalhoriz+mulscale24(siz,sec->floorz-globalposz)+1;
else
startdm = 0x7fffffff;
//sprite
if ((searchy >= max(startum,(y1>>8))) && (searchy < min(startdm,(y2>>8))))
{
searchsector = sectnum; searchwall = spritenum;
searchstat = 3; searchit = 1;
}
}
}
}
drawvox(tspr->x,tspr->y,tspr->z,(long)tspr->ang+1536,(long)tspr->xrepeat,(long)tspr->yrepeat,tilenum,tspr->shade,tspr->pal,lwall,swall);
}
#endif
if (automapping == 1) show2dsprite[spritenum>>3] |= pow2char[spritenum&7];
}
#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)
{
long i, j, k, x, y, z, syoff, ggxstart, ggystart, nxoff;
long cosang, sinang, sprcosang, sprsinang, backx, backy, gxinc, gyinc;
long daxsiz, daysiz, dazsiz, daxpivot, daypivot, dazpivot;
long daxscalerecip, dayscalerecip, cnt, gxstart, gystart, odayscale;
long l1, l2, p, pend, slabxoffs, xyvoxoffs, *longptr;
long lx, rx, nx, ny, zx, zy, x1, y1, z1, x2, y2, z2, yplc, yinc, bufplc;
long yoff, xs, ys, xe, ye, xi, yi, cbackx, cbacky, dagxinc, dagyinc;
short *shortptr;
char *voxptr, *voxend, *davoxptr, oand, oand16, oand32;
cosang = sintable[(globalang+512)&2047];
sinang = sintable[globalang&2047];
sprcosang = sintable[(dasprang+512)&2047];
sprsinang = sintable[dasprang&2047];
i = klabs(dmulscale6(dasprx-globalposx,cosang,daspry-globalposy,sinang));
j = (long)(getpalookup((long)mulscale21(globvis,i),(long)dashade)<<8);
setupdrawslab(ylookup[1],FP_OFF(palookup[dapal])+j);
j = 1310720;
j *= min(daxscale,dayscale); j >>= 6; //New hacks (for sized-down voxels)
for(k=0;k<MAXVOXMIPS;k++)
{
if (i < j) { i = k; break; }
j <<= 1;
}
if (k >= MAXVOXMIPS) i = MAXVOXMIPS-1;
davoxptr = (char *)voxoff[daindex][i]; if (!davoxptr) return;
daxscale <<= (i+8); dayscale <<= (i+8);
odayscale = dayscale;
daxscale = mulscale16(daxscale,xyaspect);
daxscale = scale(daxscale,xdimenscale,xdimen<<8);
dayscale = scale(dayscale,mulscale16(xdimenscale,viewingrangerecip),xdimen<<8);
daxscalerecip = (1<<30)/daxscale;
dayscalerecip = (1<<30)/dayscale;
longptr = (long *)davoxptr;
daxsiz = longptr[0]; daysiz = longptr[1]; dazsiz = longptr[2];
daxpivot = longptr[3]; daypivot = longptr[4]; dazpivot = longptr[5];
davoxptr += (6<<2);
x = mulscale16(globalposx-dasprx,daxscalerecip);
y = mulscale16(globalposy-daspry,daxscalerecip);
backx = ((dmulscale10(x,sprcosang,y,sprsinang)+daxpivot)>>8);
backy = ((dmulscale10(y,sprcosang,x,-sprsinang)+daypivot)>>8);
cbackx = min(max(backx,0),daxsiz-1);
cbacky = min(max(backy,0),daysiz-1);
sprcosang = mulscale14(daxscale,sprcosang);
sprsinang = mulscale14(daxscale,sprsinang);
x = (dasprx-globalposx) - dmulscale18(daxpivot,sprcosang,daypivot,-sprsinang);
y = (daspry-globalposy) - dmulscale18(daypivot,sprcosang,daxpivot,sprsinang);
cosang = mulscale16(cosang,dayscalerecip);
sinang = mulscale16(sinang,dayscalerecip);
gxstart = y*cosang - x*sinang;
gystart