// "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. // // This file has been modified from Ken Silverman's original release // by Jonathon Fowler (jonof@edgenetwk.com) //#define POLYMOST //#define SUPERBUILD #define ENGINE #include "compat.h" #include "build.h" #include "pragmas.h" #include "cache1d.h" #include "a.h" #include "osd.h" #include "crc32.h" #include "quicklz.h" #include "baselayer.h" #include "scriptfile.h" #ifdef POLYMOST # ifdef USE_OPENGL # include "glbuild.h" # include "mdsprite.h" # ifdef POLYMER # include "polymer.h" # endif # endif # include "hightile.h" # include "polymost.h" # ifdef _WIN32 # define WIN32_LEAN_AND_MEAN # include # endif #endif #include #include "engine_priv.h" #define CACHEAGETIME 16 float debug1, debug2; static void drawpixel_safe(void *s, char a) { #if defined __GNUC__ if (__builtin_expect((intptr_t)s >= frameplace && (intptr_t)s < frameplace+bytesperline*ydim, 1)) #else if ((intptr_t)s >= frameplace && (intptr_t)s < frameplace+bytesperline*ydim) #endif drawpixel(s, a); #ifdef DEBUGGINGAIDS else { static const char *const c = &editorcolors[15]; drawpixel((intptr_t *)frameplace, *c); drawpixel((intptr_t *)frameplace+1, *c); drawpixel((intptr_t *)frameplace+2, *c); drawpixel((intptr_t *)frameplace+bytesperline, *c); drawpixel((intptr_t *)frameplace+bytesperline+1, *c); drawpixel((intptr_t *)frameplace+bytesperline+2, *c); drawpixel((intptr_t *)frameplace+2*bytesperline, *c); drawpixel((intptr_t *)frameplace+2*bytesperline+1, *c); drawpixel((intptr_t *)frameplace+2*bytesperline+2, *c); } #endif } #ifdef SUPERBUILD void loadvoxel(int32_t voxindex) { voxindex=0; } int32_t tiletovox[MAXTILES]; int32_t usevoxels = 1; #define kloadvoxel loadvoxel int32_t novoxmips = 0; int32_t editorgridextent = 131072; //These variables need to be copied into BUILD #define MAXXSIZ 256 #define MAXYSIZ 256 #define MAXZSIZ 255 #define MAXVOXMIPS 5 intptr_t voxoff[MAXVOXELS][MAXVOXMIPS]; char voxlock[MAXVOXELS][MAXVOXMIPS]; int32_t voxscale[MAXVOXELS]; static int32_t ggxinc[MAXXSIZ+1], ggyinc[MAXXSIZ+1]; static int32_t lowrecip[1024], nytooclose, nytoofar; static uint32_t distrecip[65536]; #endif static intptr_t *lookups = NULL; static char lookupsalloctype = 255; int32_t dommxoverlay = 1, beforedrawrooms = 1, indrawroomsandmasks = 0; static int32_t oxdimen = -1, oviewingrange = -1, oxyaspect = -1; // r_usenewaspect is the cvar, newaspect_enable to trigger the new behaviour in the code int32_t r_usenewaspect = 0, newaspect_enable=0; uint32_t r_screenxy = 403; // 4:3 aspect ratio int32_t curbrightness = 0, gammabrightness = 0; double vid_gamma = DEFAULT_GAMMA; double vid_contrast = DEFAULT_CONTRAST; double vid_brightness = DEFAULT_BRIGHTNESS; //Textured Map variables static char globalpolytype; static int16_t *dotp1[MAXYDIM], *dotp2[MAXYDIM]; static int8_t tempbuf[MAXWALLS]; int32_t ebpbak, espbak; intptr_t slopalookup[16384]; // was 2048 #if defined(USE_OPENGL) palette_t palookupfog[MAXPALOOKUPS]; #endif static char permanentlock = 255; int32_t artversion, mapversion=7L; // JBF 20040211: default mapversion to 7 void *pic = NULL; char picsiz[MAXTILES], tilefilenum[MAXTILES]; int32_t lastageclock; int32_t tilefileoffs[MAXTILES]; int32_t artsize = 0, cachesize = 0; // unlikely to occur, but .art files with less than 256 tiles are certainly possible // this would be 60 (MAXTILES/256) if we just assumed there were 256 tiles per .art as in Duke char *artptrs[256]; static int16_t radarang2[MAXXDIM]; static uint16_t sqrtable[4096], shlookup[4096+256]; char pow2char[8] = {1,2,4,8,16,32,64,128}; int32_t 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 }; int32_t reciptable[2048], fpuasm; char britable[16][256]; // JBF 20040207: full 8bit precision extern char textfont[2048], smalltextfont[2048]; static char kensmessage[128]; char *engineerrstr = "No error"; int32_t showfirstwall=0; int32_t showheightindicators=2; int32_t circlewall=-1; char cachedebug = 0; qlz_state_compress *state_compress = NULL; qlz_state_decompress *state_decompress = NULL; int32_t whitecol; #ifdef POLYMER static int16_t maphacklightcnt=0; static int16_t maphacklight[PR_MAXLIGHTS]; #endif ////////// editor side view ////////// int32_t m32_sideview = 0; int32_t m32_sideelev = 256; // elevation in BUILD degrees, 0..512 int16_t m32_sideang = 200; // azimuth, 0..2047 int32_t m32_sidecos, m32_sidesin; int32_t m32_swcnt; int16_t *m32_wallsprite; // [MAXSWALLS+MAXSPRITES] static int32_t *m32_sidedist; // [MAXSWALLS+MAXSPRITES] static vec3_t m32_viewplane; ////// sector-like clipping for sprites ////// typedef struct { int16_t numsectors, numwalls; sectortype *sector; walltype *wall; } mapinfo_t; static void mapinfo_set(mapinfo_t *bak, mapinfo_t *new) { if (bak) { bak->numsectors = numsectors; bak->numwalls = numwalls; bak->sector = sector; bak->wall = wall; } if (new) { numsectors = new->numsectors; numwalls = new->numwalls; sector = new->sector; wall = new->wall; } } static mapinfo_t origmapinfo, clipmapinfo; static int32_t quickloadboard=0; #define CM_MAX 256 // must be a power of 2 typedef struct { int16_t qbeg, qend; // indices into sectq int16_t picnum, next; int32_t maxdist; } clipinfo_t; static int32_t numclipmaps; static clipinfo_t clipinfo[CM_MAX]; static int32_t numclipsects; // number in sectq[] static int16_t *sectoidx, *sectq; // [numsectors] static int16_t pictoidx[MAXTILES]; // maps tile num to clipinfo[] index static int16_t *tempictoidx; static sectortype *loadsector; static walltype *loadwall, *loadwallinv; static spritetype *loadsprite; // sectoidx bits #define CM_NONE (CM_MAX<<1) #define CM_SOME (CM_NONE-1) #define CM_OUTER (CM_MAX) // sector surrounds clipping sector // sprite -> sector tag mappings #define CM_XREPEAT floorpal #define CM_YREPEAT floorxpanning #define CM_XOFFSET ceilingshade #define CM_YOFFSET floorshade #define CM_CSTAT hitag #define CM_ANG extra #define CM_FLOORZ(Sec) (*(int32_t *)§or[Sec].ceilingxpanning) // ceilingxpanning,ceilingypanning,floorpicnum #define CM_CEILINGZ(Sec) (*(int32_t *)§or[Sec].visibility) // visibility,filler,lotag // backup of original normalized coordinates #define CM_WALL_X(Wal) (*(int32_t *)&wall[Wal].picnum) #define CM_WALL_Y(Wal) (*(int32_t *)&wall[Wal].lotag) // don't rotate when applying clipping, for models with rotational symmetry #define CM_NOROT(Spri) (sprite[Spri].cstat&2) #define CM_NOROTS(Sect) (sector[Sect].CM_CSTAT&2) static void clipmapinfo_init() { int32_t i; numclipmaps = 0; numclipsects = 0; if (sectq) { Bfree(sectq); sectq=NULL; } if (sectoidx) { Bfree(sectoidx); sectoidx=NULL; } if (tempictoidx) { Bfree(tempictoidx); tempictoidx=NULL; } for (i=0; iMAXSECTORS || ournumwalls+numwalls>MAXWALLS || ournumsprites+numsprites>MAXSPRITES) { initprintf("clip map: warning: exceeded limits when loading %s, aborting.\n", fn); break; } Bmemcpy(loadsector+ournumsectors, sector, numsectors*sizeof(sectortype)); Bmemcpy(loadwall+ournumwalls, wall, numwalls*sizeof(walltype)); Bmemcpy(loadsprite+ournumsprites, sprite, numsprites*sizeof(spritetype)); for (i=ournumsectors; i=0) loadwall[i].point2 += ournumwalls; if (loadwall[i].nextwall>=0) { loadwall[i].nextwall += ournumwalls; loadwall[i].nextsector += ournumsectors; } } for (i=ournumsprites; i=0) loadsprite[i].sectnum += ournumsectors; ournumsectors += numsectors; ournumwalls += numwalls; ournumsprites += numsprites; if (lwcp != loadedwhich) { *lwcp++ = ','; *lwcp++ = ' '; } *lwcp++ = fi; *lwcp = 0; } quickloadboard = 0; if (ournumsectors==0 || ournumwalls==0 || ournumsprites==0) // nothing loaded { clipmapinfo_init(); return -1; } // shrink loadsector = Brealloc(loadsector, ournumsectors*sizeof(sectortype)); loadwall = Brealloc(loadwall, ournumwalls*sizeof(walltype)); Bmemcpy(sector, loadsector, ournumsectors*sizeof(sectortype)); Bmemcpy(wall, loadwall, ournumwalls*sizeof(walltype)); Bmemcpy(sprite, loadsprite, ournumsprites*sizeof(spritetype)); numsectors = ournumsectors; numwalls = ournumwalls; // vvvv don't use headsprite[sect,stat]! vvvv sectoidx = Bmalloc(numsectors*sizeof(sectoidx[0])); if (!sectoidx || !sector || !wall) { clipmapinfo_init(); return 1; } for (i=0; i=0 && sectoidx[wall[w].nextsector]==CM_OUTER) { wall[k].nextwall = wall[k].nextsector = -1; wall[w].nextwall = wall[w].nextsector = -1; } } } { int16_t ns, outersect; int32_t pn,scnt, x,y,z, maxdist; sectq = Bmalloc(numsectors*sizeof(sectq[0])); tempictoidx = Bmalloc(MAXTILES*sizeof(tempictoidx[0])); if (!sectq || !tempictoidx) { clipmapinfo_init(); return 1; } for (i=0; i=MAXTILES || k<0 || k>=numsectors || (sectoidx[k]&CM_OUTER)) continue; // chain if (pictoidx[pn]>=0) { if (sectoidx[k]&CM_SOME) { for (fi=0; fi<9; fi++) if (k>=fisec[fi]) break; initprintf("clip map %d: error: tried to chain picnum %d (sprite %d) in sector %d which" " already belongs to picnum %d.\n", fi, pn, i-fispr[fi], k-fisec[fi], clipinfo[sectoidx[k]].picnum); clipmapinfo_init(); return 2; } // new one is front clipinfo[numclipmaps].next = pictoidx[pn]; pictoidx[pn] = numclipmaps; } else { clipinfo[numclipmaps].next = -1; pictoidx[pn] = numclipmaps; } if (!CM_NOROT(i)) { if (sprite[i].ang!=1536 && sprite[i].ang!=512) { for (fi=0; fi<9; fi++) if (i>=fispr[fi]) break; initprintf("clip map %d: warning: sprite %d pointing neither northward nor southward. %s will be wrong.\n", fi, i-fispr[fi], (sprite[i].cstat&48)==32 ? "Scaling and flipping" : "X-flipping"); } } clipinfo[numclipmaps].picnum = pn; // collect sectors scnt = numclipsects; sectq[numclipsects++] = k; sectoidx[k] = numclipmaps; clipinfo[numclipmaps].qbeg = scnt; outersect = -1; do { k = sectq[scnt]; for (w=sector[k].wallptr; w=0) { if (sectoidx[ns]==CM_NONE) { sectoidx[ns] = numclipmaps; sectq[numclipsects++] = ns; } else if (sectoidx[ns]&CM_OUTER) { if (outersect>=0 && ns!=outersect) { for (fi=0; fi<9; fi++) if (ns>=fisec[fi]) break; initprintf("clip map %d: error: encountered more than one outer sector (%d and %d)" " for sprite %d.\n", fi, outersect-fisec[fi], ns-fisec[fi], i-fispr[fi]); clipmapinfo_init(); return 3; } outersect = ns; sectoidx[outersect] |= numclipmaps; } else if (sectoidx[ns]!=numclipmaps) { for (fi=0; fi<9; fi++) if (ns>=fisec[fi]) break; initprintf("clip map %d: error: encountered sector %d belonging to index %d" " while collecting sectors for sprite %d (index %d).\n", fi, ns-fisec[fi], sectoidx[ns], i-fispr[fi], numclipmaps); clipmapinfo_init(); return 4; } } } } while (++scnt < numclipsects); if (outersect==-1) { initprintf("clip map: INTERNAL ERROR: outersect==-1!\n"); clipmapinfo_init(); return 5; } sectq[numclipsects++] = outersect; // last is outer clipinfo[numclipmaps].qend = numclipsects-1; // normalize maxdist = 0; for (scnt=clipinfo[numclipmaps].qbeg; scnt<=clipinfo[numclipmaps].qend; scnt++) { k = sectq[scnt]; x = sprite[i].x; y = sprite[i].y; z = sprite[i].z; sector[k].floorz -= z; sector[k].ceilingz -= z; if (scnt==clipinfo[numclipmaps].qbeg) { // backup sprite tags since we'll discard sprites later sector[k].CM_XREPEAT = sprite[i].xrepeat; sector[k].CM_YREPEAT = sprite[i].yrepeat; sector[k].CM_XOFFSET = sprite[i].xoffset; sector[k].CM_YOFFSET = sprite[i].yoffset; sector[k].CM_CSTAT = sprite[i].cstat; sector[k].CM_ANG = sprite[i].ang; } // backup floor and ceiling z CM_FLOORZ(k) = sector[k].floorz; CM_CEILINGZ(k) = sector[k].ceilingz; for (w=sector[k].wallptr; w maxdist) maxdist = klabs(wall[w].x); if (klabs(wall[w].y) > maxdist) maxdist = klabs(wall[w].y); } else { int32_t tmp = ksqrt(wall[w].x*wall[w].x + wall[w].y*wall[w].y); if (tmp > maxdist) maxdist = tmp; } } // aliasing if (wall[w].lotag>0 || wall[w].hitag>0) { int32_t ii; if (wall[w].lotag>0 && wall[w].hitag>0) { if (wall[w].lotag > wall[w].hitag) swapshort(&wall[w].lotag, &wall[w].hitag); for (ii=wall[w].lotag; ii0) { if (wall[w].lotag=0) pictoidx[i]=tempictoidx[i]; } Bfree(loadsprite); loadsprite=NULL; Bfree(tempictoidx); tempictoidx=NULL; // don't let other code be distracted by the temporary map we constructed numsectors = 0; numwalls = 0; initspritelists(); initprintf("Loaded clip map%s %s.\n", lwcp==loadedwhich+1?"":"s", loadedwhich); return 0; } ////// ////// int32_t checksectorpointer(int16_t i, int16_t sectnum) { int32_t j, k, startwall, endwall, x1, y1, x2, y2, numnewwalls=0; #if 0 if (checksectorpointer_warn && (i<0 || i>=max(numwalls,newnumwalls))) { char buf[128]; Bsprintf(buf, "WARN: checksectorpointer called with i=%d but (new)numwalls=%d", i, max(numwalls,newnumwalls)); OSD_Printf("%s\n", buf); printmessage16("%s", buf); return 0; } #endif x1 = wall[i].x; y1 = wall[i].y; x2 = (wall[wall[i].point2]).x; y2 = (wall[wall[i].point2]).y; if (wall[i].nextwall >= 0) //Check for early exit { k = wall[i].nextwall; if (wall[k].x == x2 && wall[k].y == y2) if ((wall[wall[k].point2]).x == x1 && (wall[wall[k].point2]).y == y1) return(0); } wall[i].nextsector = -1; wall[i].nextwall = -1; for (j=0; j> 24) + 4096]; // mov ebx, eax // over24: shr ebx, 24 // mov cx, word ptr shlookup[ebx*2+8192] } else { c = shlookup[a >> 12]; // mov ebx, eax // shr ebx, 12 // mov cx, word ptr shlookup[ebx*2] // jmp short under24 } a >>= c&0xff; // under24: shr eax, cl a = (a&0xffff0000)|(sqrtable[a]); // mov ax, word ptr sqrtable[eax*2] a >>= ((c&0xff00) >> 8); // mov cl, ch // shr eax, cl return a; } static inline int32_t msqrtasm(uint32_t c) { uint32_t a,b; a = 0x40000000l; // mov eax, 0x40000000 b = 0x20000000l; // mov ebx, 0x20000000 do // begit: { if (c >= a) // cmp ecx, eax / jl skip { c -= a; // sub ecx, eax a += b*4; // lea eax, [eax+ebx*4] } // skip: a -= b; // sub eax, ebx a >>= 1; // shr eax, 1 b >>= 2; // shr ebx, 2 } while (b); // jnz begit if (c >= a) // cmp ecx, eax a++; // sbb eax, -1 a >>= 1; // shr eax, 1 return a; } static inline int32_t krecipasm(int32_t i) { // Ken did this float f = (float)i; i = *(int32_t *)&f; return((reciptable[(i>>12)&2047]>>(((i-0x3f800000)>>23)&31))^(i>>31)); } static inline int32_t getclipmask(int32_t a, int32_t b, int32_t c, int32_t d) { // Ken did this d = ((a<0)*8) + ((b<0)*4) + ((c<0)*2) + (d<0); return(((d<<4)^0xf0)|d); } inline int32_t getkensmessagecrc(int32_t b) { return 0x56c764d4l; b=b; } #endif int32_t xb1[MAXWALLSB], yb1[MAXWALLSB], xb2[MAXWALLSB], yb2[MAXWALLSB]; int32_t rx1[MAXWALLSB], ry1[MAXWALLSB], rx2[MAXWALLSB], ry2[MAXWALLSB]; int16_t p2[MAXWALLSB], thesector[MAXWALLSB]; int16_t thewall[MAXWALLSB]; int16_t bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB]; static int16_t smost[MAXYSAVES], smostcnt; static int16_t smoststart[MAXWALLSB]; static char smostwalltype[MAXWALLSB]; static int32_t smostwall[MAXWALLSB], smostwallcnt = -1L; int16_t maskwall[MAXWALLSB], maskwallcnt; static int32_t spritesx[MAXSPRITESONSCREEN]; static int32_t spritesy[MAXSPRITESONSCREEN+1]; static int32_t spritesz[MAXSPRITESONSCREEN]; spritetype *tspriteptr[MAXSPRITESONSCREEN + 1]; int16_t umost[MAXXDIM], dmost[MAXXDIM]; static int16_t bakumost[MAXXDIM], bakdmost[MAXXDIM]; int16_t uplc[MAXXDIM], dplc[MAXXDIM]; static int16_t uwall[MAXXDIM], dwall[MAXXDIM]; static int32_t swplc[MAXXDIM], lplc[MAXXDIM]; static int32_t swall[MAXXDIM], lwall[MAXXDIM+4]; int32_t xdimen = -1, xdimenrecip, halfxdimen, xdimenscale, xdimscale; int32_t wx1, wy1, wx2, wy2, ydimen; intptr_t /*viewoffset,*/ frameoffset; static int32_t nrx1[8], nry1[8], nrx2[8], nry2[8]; // JBF 20031206: Thanks Ken static int32_t rxi[8], ryi[8], rzi[8], rxi2[8], ryi2[8], rzi2[8]; static int32_t xsi[8], ysi[8], horizycent; static intptr_t *horizlookup=0, *horizlookup2=0; int32_t globalposx, globalposy, globalposz, globalhoriz; int16_t globalang, globalcursectnum; int32_t globalpal, cosglobalang, singlobalang; int32_t cosviewingrangeglobalang, sinviewingrangeglobalang; char *globalpalwritten; int32_t globaluclip, globaldclip, globvis; int32_t globalvisibility, globalhisibility, globalpisibility, globalcisibility; char globparaceilclip, globparaflorclip; int32_t xyaspect, viewingrangerecip; intptr_t asm1, asm2, asm3, asm4,palookupoffse[4]; int32_t vplce[4], vince[4], bufplce[4]; char globalxshift, globalyshift; int32_t globalxpanning, globalypanning, globalshade; int16_t globalpicnum, globalshiftval; int32_t globalzd, globalyscale, globalorientation; intptr_t globalbufplc; int32_t globalx1, globaly1, globalx2, globaly2, globalx3, globaly3, globalzx; int32_t globalx, globaly, globalz; int16_t sectorborder[256], sectorbordercnt; static char tablesloaded = 0; int32_t pageoffset, ydim16, qsetmode = 0; int32_t startposx, startposy, startposz; int16_t startang, startsectnum; int16_t pointhighlight, linehighlight, highlightcnt; int32_t lastx[MAXYDIM]; char *transluc = NULL, paletteloaded = 0; int32_t halfxdim16, midydim16; #define FASTPALGRIDSIZ 8 static int32_t 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 int32_t colnext[256]; static char coldist[8] = {0,1,2,3,4,3,2,1}; static int32_t colscan[27]; static int16_t clipnum, hitwalls[4]; const int32_t hitscangoalx = (1<<29)-1, hitscangoaly = (1<<29)-1; #ifdef POLYMOST int32_t hitallsprites = 0; #endif typedef struct { int32_t x1, y1, x2, y2; } linetype; static linetype clipit[MAXCLIPNUM]; static int16_t clipsectorlist[MAXCLIPNUM], clipsectnum, origclipsectorlist[MAXCLIPNUM], origclipsectnum; static int16_t clipspritelist[MAXCLIPNUM], clipspritenum; // sector-like sprite clipping static int16_t clipobjectval[MAXCLIPNUM]; typedef struct { int32_t sx, sy, z; int16_t a, picnum; int8_t dashade; char dapalnum, dastat, pagesleft; int32_t cx1, cy1, cx2, cy2; int32_t uniqid; //JF extension } permfifotype; static permfifotype permfifo[MAXPERMS]; static int32_t permhead = 0, permtail = 0; int16_t numscans, numhits, numbunches; int16_t capturecount = 0; char vgapal16[4*256] = { 00,00,00,00, 42,00,00,00, 00,42,00,00, 42,42,00,00, 00,00,42,00, 42,00,42,00, 00,21,42,00, 42,42,42,00, 21,21,21,00, 63,21,21,00, 21,63,21,00, 63,63,21,00, 21,21,63,00, 63,21,63,00, 21,63,63,00, 63,63,63,00 }; int16_t editstatus = 0; int16_t searchit; int32_t searchx = -1, searchy; //search input int16_t searchsector, searchwall, searchstat; //search output // if searchstat==0 (wall), searchbottomwall is ==.nextwall if aiming at // bottom of a wall with swapped walls (.cstat&2), else it's ==searchwall int16_t searchbottomwall; double msens = 1.0; static char artfilename[20]; static int32_t numtilefiles, artfil = -1, artfilnum, artfilplc; char inpreparemirror = 0; static int32_t mirrorsx1, mirrorsy1, mirrorsx2, mirrorsy2; static int32_t setviewcnt = 0; // interface layers use this now static int32_t bakframeplace[4], bakxsiz[4], bakysiz[4]; static int32_t bakwindowx1[4], bakwindowy1[4]; static int32_t bakwindowx2[4], bakwindowy2[4]; #ifdef POLYMOST static int32_t bakrendmode,baktile; #endif int32_t totalclocklock; char apptitle[256] = "Build Engine"; uint8_t **basepaltableptr; uint8_t basepalcount; uint8_t curbasepal; palette_t curpalette[256]; // the current palette, unadjusted for brightness or tint palette_t curpalettefaded[256]; // the current palette, adjusted for brightness and tint (ie. what gets sent to the card) palette_t palfadergb = { 0,0,0,0 }; char palfadedelta = 0; // // Internal Engine Functions // //int32_t cacheresets = 0,cacheinvalidates = 0; // // getpalookup (internal) // static inline int32_t getpalookup(int32_t davis, int32_t dashade) { return(min(max(dashade+(davis>>8),0),numpalookups-1)); } // // scansector (internal) // static void scansector(int16_t sectnum) { walltype *wal, *wal2; spritetype *spr; int32_t xs, ys, x1, y1, x2, y2, xp1, yp1, xp2=0, yp2=0, tempint; int16_t z, zz, startwall, endwall, numscansbefore, scanfirst, bunchfrst; int16_t 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)); spriteext[z].tspr = (spritetype *)&tsprite[spritesortcnt]; 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]; znextsector; 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) { tempint = x1*y2-x2*y1; if (((unsigned)tempint+262144) < 524288) if (mulscale5(tempint,tempint) <= (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; tempint = yp1-yp2+xp1-xp2; if (tempint == 0) goto skipitaddwall; yb1[numscans] = yp1 + scale(yp2-yp1,xp1+yp1,tempint); } 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; tempint = xp2-xp1+yp1-yp2; if (tempint == 0) goto skipitaddwall; yb2[numscans] = yp1 + scale(yp2-yp1,yp1-xp1,tempint); } 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= xb1[p2[z]])) bunchfirst[numbunches++] = p2[z], p2[z] = -1; for (z=bunchfrst; z=0; zz=p2[zz]); bunchlast[z] = zz; } } while (sectorbordercnt > 0); } // // maskwallscan (internal) // static void maskwallscan(int32_t x1, int32_t x2, int16_t *uwal, int16_t *dwal, int32_t *swal, int32_t *lwal) { int32_t x,/* startx,*/ xnice, ynice; intptr_t startx, p, fpalookup; int32_t y1ve[4], y2ve[4], /* p,*/ tsizx, tsizy; #ifndef ENGINE_USING_A_C char bad; int32_t i, u4, d4, dax, z; #endif 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); if (palookup[globalpal] == NULL) globalpal = 0; fpalookup = FP_OFF(palookup[globalpal]); setupmvlineasm(globalshiftval); #ifndef ENGINE_USING_A_C 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((int32_t)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((int32_t)mulscale16(swal[x],globvis),globalshade)<<8); palookupoffse[3] = fpalookup+(getpalookup((int32_t)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((int32_t)mulscale16(swal[x+1],globvis),globalshade)<<8); palookupoffse[2] = fpalookup+(getpalookup((int32_t)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((int32_t)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]]); } #else // ENGINE_USING_A_C p = startx+frameoffset; for (x=startx; 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((int32_t)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]]); } #endif faketimerhandler(); } // // wallfront (internal) // int32_t wallfront(int32_t l1, int32_t l2) { walltype *wal; int32_t 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 (internal) // static inline int32_t spritewallfront(spritetype *s, int32_t w) { walltype *wal; int32_t 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); } // // spritebehindwall(internal) // #if 0 static int32_t spriteobstructswall(spritetype *s, int32_t w) { walltype *wal; int32_t x, y; int32_t x1, y1; int32_t x2, y2; double a1, b1, c1; double a2, b2, c2; double d1, d2; // wall line equation wal = &wall[w]; x1 = wal->x - globalposx; y1 = wal->y - globalposy; wal = &wall[wal->point2]; x2 = wal->x - globalposx; y2 = wal->y - globalposy; if ((x2 - x1) != 0) a1 = (float)(y2 - y1)/(x2 - x1); else a1 = 1e+37; // not infinite, but almost ;) b1 = -1; c1 = (y1 - (a1 * x1)); // player to sprite line equation if ((s->x - globalposx) != 0) a2 = (float)(s->y - globalposy)/(s->x - globalposx); else a2 = 1e+37; b2 = -1; c2 = 0; // intersection point d1 = (float)(1) / (a1*b2 - a2*b1); x = ((b1*c2 - b2*c1) * d1); y = ((a2*c1 - a1*c2) * d1); // distance between the sprite and the player a1 = s->x - globalposx; b1 = s->y - globalposy; d1 = (a1 * a1 + b1 * b1); // distance between the intersection point and the player d2 = (x * x + y * y); // check if the sprite obstructs the wall if ((d1 < d2) && (min(x1, x2) <= x) && (x <= max(x1, x2)) && (min(y1, y2) <= y) && (y <= max(y1, y2))) return (1); else return (0); } #endif // // bunchfront (internal) // static inline int32_t bunchfront(int32_t b1, int32_t b2) { int32_t 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] xr) return; r = horizlookup2[yp-globalhoriz+horizycent]; asm1 = globalx1*r; asm2 = globaly2*r; s = ((int32_t)getpalookup((int32_t)mulscale16(r,globvis),globalshade)<<8); hlineasm4(xr-xl,0,s,globalx2*r+globalypanning,globaly1*r+globalxpanning, ylookup[yp]+xr+frameoffset); } // // slowhline (internal) // static inline void slowhline(int32_t xr, int32_t yp) { int32_t xl, r; xl = lastx[yp]; if (xl > xr) return; r = horizlookup2[yp-globalhoriz+horizycent]; asm1 = globalx1*r; asm2 = globaly2*r; asm3 = (intptr_t)globalpalwritten + ((intptr_t)getpalookup((int32_t)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); } // // prepwall (internal) // static void prepwall(int32_t z, walltype *wal) { int32_t i, l=0, ol=0, splc, sinc, x, topinc, top, botinc, bot, 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]; } } // // animateoffs (internal) // inline int32_t animateoffs(int16_t tilenum, int16_t fakevar) { int32_t i, k, offs; UNREFERENCED_PARAMETER(fakevar); offs = 0; i = (totalclocklock>>((picanm[tilenum]>>24)&15)); if ((picanm[tilenum]&63) > 0) { switch (picanm[tilenum]&192) { case 64: k = (i%((picanm[tilenum]&63)<<1)); if (k < (picanm[tilenum]&63)) offs = k; else offs = (((picanm[tilenum]&63)<<1)-k); break; case 128: offs = (i%((picanm[tilenum]&63)+1)); break; case 192: offs = -(i%((picanm[tilenum]&63)+1)); } } return(offs); } // // owallmost (internal) // static int32_t owallmost(int16_t *mostbuf, int32_t w, int32_t z) { int32_t bad, inty, xcross, y, yinc; int32_t s1, s2, s3, s4, ix1, ix2, iy1, iy2, t; int32_t i; z <<= 7; s1 = mulscale20(globaluclip,yb1[w]); s2 = mulscale20(globaluclip,yb2[w]); s3 = mulscale20(globaldclip,yb1[w]); s4 = mulscale20(globaldclip,yb2[w]); bad = (zs3)<<2)+((z>s4)<<3); ix1 = xb1[w]; iy1 = yb1[w]; ix2 = xb2[w]; iy2 = yb2[w]; if ((bad&3) == 3) { //clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),0L); for (i=ix1; i<=ix2; i++) mostbuf[i] = 0; return(bad); } if ((bad&12) == 12) { //clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16)); for (i=ix1; i<=ix2; i++) mostbuf[i] = ydimen; return(bad); } if (bad&3) { t = divscale30(z-s1,s2-s1); inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t); xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty); if ((bad&3) == 2) { if (xb1[w] <= xcross) { iy2 = inty; ix2 = xcross; } //clearbufbyte(&mostbuf[xcross+1],(xb2[w]-xcross)*sizeof(mostbuf[0]),0L); for (i=xcross+1; i<=xb2[w]; i++) mostbuf[i] = 0; } else { if (xcross <= xb2[w]) { iy1 = inty; ix1 = xcross; } //clearbufbyte(&mostbuf[xb1[w]],(xcross-xb1[w]+1)*sizeof(mostbuf[0]),0L); for (i=xb1[w]; i<=xcross; i++) mostbuf[i] = 0; } } if (bad&12) { t = divscale30(z-s3,s4-s3); inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t); xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty); if ((bad&12) == 8) { if (xb1[w] <= xcross) { iy2 = inty; ix2 = xcross; } //clearbufbyte(&mostbuf[xcross+1],(xb2[w]-xcross)*sizeof(mostbuf[0]),ydimen+(ydimen<<16)); for (i=xcross+1; i<=xb2[w]; i++) mostbuf[i] = ydimen; } else { if (xcross <= xb2[w]) { iy1 = inty; ix1 = xcross; } //clearbufbyte(&mostbuf[xb1[w]],(xcross-xb1[w]+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16)); for (i=xb1[w]; i<=xcross; i++) mostbuf[i] = ydimen; } } y = (scale(z,xdimenscale,iy1)<<4); yinc = ((scale(z,xdimenscale,iy2)<<4)-y) / (ix2-ix1+1); qinterpolatedown16short((intptr_t)&mostbuf[ix1],ix2-ix1+1,y+(globalhoriz<<16),yinc); if (mostbuf[ix1] < 0) mostbuf[ix1] = 0; if (mostbuf[ix1] > ydimen) mostbuf[ix1] = ydimen; if (mostbuf[ix2] < 0) mostbuf[ix2] = 0; if (mostbuf[ix2] > ydimen) mostbuf[ix2] = ydimen; return(bad); } // // wallmost (internal) // static int32_t wallmost(int16_t *mostbuf, int32_t w, int32_t sectnum, char dastat) { int32_t bad, i, j, t, y, z, inty, intz, xcross, yinc, fw; int32_t x1, y1, z1, x2, y2, z2, xv, yv, dx, dy, dasqr, oz1, oz2; int32_t s1, s2, s3, s4, ix1, ix2, iy1, iy2; //char datempbuf[256]; if (dastat == 0) { z = sector[sectnum].ceilingz-globalposz; if ((sector[sectnum].ceilingstat&2) == 0) return(owallmost(mostbuf,w,z)); } else { z = sector[sectnum].floorz-globalposz; if ((sector[sectnum].floorstat&2) == 0) return(owallmost(mostbuf,w,z)); } i = thewall[w]; if (i == sector[sectnum].wallptr) return(owallmost(mostbuf,w,z)); x1 = wall[i].x; x2 = wall[wall[i].point2].x-x1; y1 = wall[i].y; y2 = wall[wall[i].point2].y-y1; fw = sector[sectnum].wallptr; i = wall[fw].point2; dx = wall[i].x-wall[fw].x; dy = wall[i].y-wall[fw].y; dasqr = krecipasm(nsqrtasm(dx*dx+dy*dy)); if (xb1[w] == 0) { xv = cosglobalang+sinviewingrangeglobalang; yv = singlobalang-cosviewingrangeglobalang; } else { xv = x1-globalposx; yv = y1-globalposy; } i = xv*(y1-globalposy)-yv*(x1-globalposx); j = yv*x2-xv*y2; if (klabs(j) > klabs(i>>3)) i = divscale28(i,j); if (dastat == 0) { t = mulscale15(sector[sectnum].ceilingheinum,dasqr); z1 = sector[sectnum].ceilingz; } else { t = mulscale15(sector[sectnum].floorheinum,dasqr); z1 = sector[sectnum].floorz; } z1 = dmulscale24(dx*t,mulscale20(y2,i)+((y1-wall[fw].y)<<8), -dy*t,mulscale20(x2,i)+((x1-wall[fw].x)<<8))+((z1-globalposz)<<7); if (xb2[w] == xdimen-1) { xv = cosglobalang-sinviewingrangeglobalang; yv = singlobalang+cosviewingrangeglobalang; } else { xv = (x2+x1)-globalposx; yv = (y2+y1)-globalposy; } i = xv*(y1-globalposy)-yv*(x1-globalposx); j = yv*x2-xv*y2; if (klabs(j) > klabs(i>>3)) i = divscale28(i,j); if (dastat == 0) { t = mulscale15(sector[sectnum].ceilingheinum,dasqr); z2 = sector[sectnum].ceilingz; } else { t = mulscale15(sector[sectnum].floorheinum,dasqr); z2 = sector[sectnum].floorz; } z2 = dmulscale24(dx*t,mulscale20(y2,i)+((y1-wall[fw].y)<<8), -dy*t,mulscale20(x2,i)+((x1-wall[fw].x)<<8))+((z2-globalposz)<<7); s1 = mulscale20(globaluclip,yb1[w]); s2 = mulscale20(globaluclip,yb2[w]); s3 = mulscale20(globaldclip,yb1[w]); s4 = mulscale20(globaldclip,yb2[w]); bad = (z1s3)<<2)+((z2>s4)<<3); ix1 = xb1[w]; ix2 = xb2[w]; iy1 = yb1[w]; iy2 = yb2[w]; oz1 = z1; oz2 = z2; if ((bad&3) == 3) { //clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),0L); for (i=ix1; i<=ix2; i++) mostbuf[i] = 0; return(bad); } if ((bad&12) == 12) { //clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16)); for (i=ix1; i<=ix2; i++) mostbuf[i] = ydimen; return(bad); } if (bad&3) { //inty = intz / (globaluclip>>16) t = divscale30(oz1-s1,s2-s1+oz1-oz2); inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t); intz = oz1 + mulscale30(oz2-oz1,t); xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty); //t = divscale30((x1<<4)-xcross*yb1[w],xcross*(yb2[w]-yb1[w])-((x2-x1)<<4)); //inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t); //intz = z1 + mulscale30(z2-z1,t); if ((bad&3) == 2) { if (xb1[w] <= xcross) { z2 = intz; iy2 = inty; ix2 = xcross; } //clearbufbyte(&mostbuf[xcross+1],(xb2[w]-xcross)*sizeof(mostbuf[0]),0L); for (i=xcross+1; i<=xb2[w]; i++) mostbuf[i] = 0; } else { if (xcross <= xb2[w]) { z1 = intz; iy1 = inty; ix1 = xcross; } //clearbufbyte(&mostbuf[xb1[w]],(xcross-xb1[w]+1)*sizeof(mostbuf[0]),0L); for (i=xb1[w]; i<=xcross; i++) mostbuf[i] = 0; } } if (bad&12) { //inty = intz / (globaldclip>>16) t = divscale30(oz1-s3,s4-s3+oz1-oz2); inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t); intz = oz1 + mulscale30(oz2-oz1,t); xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty); //t = divscale30((x1<<4)-xcross*yb1[w],xcross*(yb2[w]-yb1[w])-((x2-x1)<<4)); //inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t); //intz = z1 + mulscale30(z2-z1,t); if ((bad&12) == 8) { if (xb1[w] <= xcross) { z2 = intz; iy2 = inty; ix2 = xcross; } //clearbufbyte(&mostbuf[xcross+1],(xb2[w]-xcross)*sizeof(mostbuf[0]),ydimen+(ydimen<<16)); for (i=xcross+1; i<=xb2[w]; i++) mostbuf[i] = ydimen; } else { if (xcross <= xb2[w]) { z1 = intz; iy1 = inty; ix1 = xcross; } //clearbufbyte(&mostbuf[xb1[w]],(xcross-xb1[w]+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16)); for (i=xb1[w]; i<=xcross; i++) mostbuf[i] = ydimen; } } y = (scale(z1,xdimenscale,iy1)<<4); yinc = ((scale(z2,xdimenscale,iy2)<<4)-y) / (ix2-ix1+1); qinterpolatedown16short((intptr_t)&mostbuf[ix1],ix2-ix1+1,y+(globalhoriz<<16),yinc); if (mostbuf[ix1] < 0) mostbuf[ix1] = 0; if (mostbuf[ix1] > ydimen) mostbuf[ix1] = ydimen; if (mostbuf[ix2] < 0) mostbuf[ix2] = 0; if (mostbuf[ix2] > ydimen) mostbuf[ix2] = ydimen; return(bad); } // // ceilscan (internal) // static void ceilscan(int32_t x1, int32_t x2, int32_t sectnum) { int32_t i, j, ox, oy, x, y1, y2, twall, bwall; sectortype *sec; sec = §or[sectnum]; if (palookup[sec->ceilingpal] != globalpalwritten) { globalpalwritten = palookup[sec->ceilingpal]; if (!globalpalwritten) globalpalwritten = palookup[globalpal]; // JBF: fixes null-pointer crash 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((int16_t)globalpicnum,(int16_t)sectnum); if (waloff[globalpicnum] == 0) loadtile(globalpicnum); globalbufplc = waloff[globalpicnum]; globalshade = (int32_t)sec->ceilingshade; globvis = globalcisibility; if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16))); globalorientation = (int32_t)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 += (((int32_t)sec->ceilingxpanning)<<24); globalypanning += (((int32_t)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 (internal) // static void florscan(int32_t x1, int32_t x2, int32_t sectnum) { int32_t i, j, ox, oy, x, y1, y2, twall, bwall; sectortype *sec; sec = §or[sectnum]; if (palookup[sec->floorpal] != globalpalwritten) { globalpalwritten = palookup[sec->floorpal]; if (!globalpalwritten) globalpalwritten = palookup[globalpal]; // JBF: fixes null-pointer crash 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((int16_t)globalpicnum,(int16_t)sectnum); if (waloff[globalpicnum] == 0) loadtile(globalpicnum); globalbufplc = waloff[globalpicnum]; globalshade = (int32_t)sec->floorshade; globvis = globalcisibility; if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16))); globalorientation = (int32_t)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 += (((int32_t)sec->floorxpanning)<<24); globalypanning += (((int32_t)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 (internal) // static void wallscan(int32_t x1, int32_t x2, int16_t *uwal, int16_t *dwal, int32_t *swal, int32_t *lwal) { int32_t x, xnice, ynice; intptr_t fpalookup; int32_t y1ve[4], y2ve[4], tsizx, tsizy; #ifndef ENGINE_USING_A_C char bad; int32_t i, u4, d4, z; #endif if (x2 >= xdim) x2 = xdim-1; 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); #ifndef ENGINE_USING_A_C 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((int32_t)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((int32_t)mulscale16(swal[x],globvis),globalshade)<<8); palookupoffse[3] = fpalookup+(getpalookup((int32_t)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((int32_t)mulscale16(swal[x+1],globvis),globalshade)<<8); palookupoffse[2] = fpalookup+(getpalookup((int32_t)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((int32_t)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]]); } #else // ENGINE_USING_A_C for (x=x1; 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((int32_t)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]]); } #endif faketimerhandler(); } // // transmaskvline (internal) // static void transmaskvline(int32_t x) { int32_t vplc, vinc, i; intptr_t palookupoffs; intptr_t bufplc,p; int16_t 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((int32_t)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); } // // transmaskvline2 (internal) // #ifndef ENGINE_USING_A_C static void transmaskvline2(int32_t x) { int32_t i, y1, y2, x2; int16_t 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((int32_t)mulscale16(swall[x],globvis),globalshade)<<8); palookupoffse[1] = FP_OFF(palookup[globalpal]) + (getpalookup((int32_t)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); } 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(); } #endif // // transmaskwallscan (internal) // static inline void transmaskwallscan(int32_t x1, int32_t x2) { int32_t x; 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++; #ifndef ENGINE_USING_A_C if ((x <= x2) && (x&1)) transmaskvline(x), x++; while (x < x2) transmaskvline2(x), x += 2; #endif while (x <= x2) transmaskvline(x), x++; faketimerhandler(); } // // ceilspritehline (internal) // static inline void ceilspritehline(int32_t x2, int32_t y) { int32_t x1, v, bx, by; //x = x1 + (x2-x1)t + (y1-y2)u ~ x = 160v //y = y1 + (y2-y1)t + (x2-x1)u ~ y = (scrx-160)v //z = z1 = z2 ~ z = posz + (scry-horiz)v x1 = lastx[y]; if (x2 < x1) return; v = mulscale20(globalzd,horizlookup[y-globalhoriz+horizycent]); bx = mulscale14(globalx2*x1+globalx1,v) + globalxpanning; by = mulscale14(globaly2*x1+globaly1,v) + globalypanning; asm1 = mulscale14(globalx2,v); asm2 = mulscale14(globaly2,v); asm3 = FP_OFF(palookup[globalpal]) + (getpalookup((int32_t)mulscale28(klabs(v),globvis),globalshade)<<8); if ((globalorientation&2) == 0) mhline(globalbufplc,bx,(x2-x1)<<16,0L,by,ylookup[y]+x1+frameoffset); else { thline(globalbufplc,bx,(x2-x1)<<16,0L,by,ylookup[y]+x1+frameoffset); } } // // ceilspritescan (internal) // static inline void ceilspritescan(int32_t x1, int32_t x2) { int32_t x, y1, y2, twall, bwall; y1 = uwall[x1]; y2 = y1; for (x=x1; x<=x2; x++) { twall = uwall[x]-1; bwall = dwall[x]; if (twall < bwall-1) { if (twall >= y2) { while (y1 < y2-1) ceilspritehline(x-1,++y1); y1 = twall; } else { while (y1 < twall) ceilspritehline(x-1,++y1); while (y1 > twall) lastx[y1--] = x; } while (y2 > bwall) ceilspritehline(x-1,--y2); while (y2 < bwall) lastx[y2++] = x; } else { while (y1 < y2-1) ceilspritehline(x-1,++y1); if (x == x2) break; y1 = uwall[x+1]; y2 = y1; } } while (y1 < y2-1) ceilspritehline(x2,++y1); faketimerhandler(); } // // grouscan (internal) // #define BITSOFPRECISION 3 //Don't forget to change this in A.ASM also! static void grouscan(int32_t dax1, int32_t dax2, int32_t sectnum, char dastat) { int32_t i, l, x, y, dx, dy, wx, wy, y1, y2, daz; int32_t daslope, dasqr; int32_t shoffs, shinc, m1, m2; intptr_t *mptr1, *mptr2, *nptr1, *nptr2,j; walltype *wal; sectortype *sec; sec = §or[sectnum]; if (dastat == 0) { if (globalposz <= getceilzofslope(sectnum,globalposx,globalposy)) return; //Back-face culling globalorientation = sec->ceilingstat; globalpicnum = sec->ceilingpicnum; globalshade = sec->ceilingshade; globalpal = sec->ceilingpal; daslope = sec->ceilingheinum; daz = sec->ceilingz; } else { if (globalposz >= getflorzofslope(sectnum,globalposx,globalposy)) return; //Back-face culling globalorientation = sec->floorstat; globalpicnum = sec->floorpicnum; globalshade = sec->floorshade; globalpal = sec->floorpal; daslope = sec->floorheinum; daz = sec->floorz; } if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs(globalpicnum,sectnum); setgotpic(globalpicnum); if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) return; if (waloff[globalpicnum] == 0) loadtile(globalpicnum); wal = &wall[sec->wallptr]; wx = wall[wal->point2].x - wal->x; wy = wall[wal->point2].y - wal->y; dasqr = krecipasm(nsqrtasm(wx*wx+wy*wy)); i = mulscale21(daslope,dasqr); wx *= i; wy *= i; globalx = -mulscale19(singlobalang,xdimenrecip); globaly = mulscale19(cosglobalang,xdimenrecip); globalx1 = (globalposx<<8); globaly1 = -(globalposy<<8); i = (dax1-halfxdimen)*xdimenrecip; globalx2 = mulscale16(cosglobalang<<4,viewingrangerecip) - mulscale27(singlobalang,i); globaly2 = mulscale16(singlobalang<<4,viewingrangerecip) + mulscale27(cosglobalang,i); globalzd = (xdimscale<<9); globalzx = -dmulscale17(wx,globaly2,-wy,globalx2) + mulscale10(1-globalhoriz,globalzd); globalz = -dmulscale25(wx,globaly,-wy,globalx); if (globalorientation&64) //Relative alignment { dx = mulscale14(wall[wal->point2].x-wal->x,dasqr); dy = mulscale14(wall[wal->point2].y-wal->y,dasqr); i = nsqrtasm(daslope*daslope+16777216); x = globalx; y = globaly; globalx = dmulscale16(x,dx,y,dy); globaly = mulscale12(dmulscale16(-y,dx,x,dy),i); x = ((wal->x-globalposx)<<8); y = ((wal->y-globalposy)<<8); globalx1 = dmulscale16(-x,dx,-y,dy); globaly1 = mulscale12(dmulscale16(-y,dx,x,dy),i); x = globalx2; y = globaly2; globalx2 = dmulscale16(x,dx,y,dy); globaly2 = mulscale12(dmulscale16(-y,dx,x,dy),i); } if (globalorientation&0x4) { i = globalx; globalx = -globaly; globaly = -i; i = globalx1; globalx1 = globaly1; globaly1 = i; i = globalx2; globalx2 = -globaly2; globaly2 = -i; } if (globalorientation&0x10) { globalx1 = -globalx1, globalx2 = -globalx2, globalx = -globalx; } if (globalorientation&0x20) { globaly1 = -globaly1, globaly2 = -globaly2, globaly = -globaly; } daz = dmulscale9(wx,globalposy-wal->y,-wy,globalposx-wal->x) + ((daz-globalposz)<<8); globalx2 = mulscale20(globalx2,daz); globalx = mulscale28(globalx,daz); globaly2 = mulscale20(globaly2,-daz); globaly = mulscale28(globaly,-daz); i = 8-(picsiz[globalpicnum]&15); j = 8-(picsiz[globalpicnum]>>4); if (globalorientation&8) { i++; j++; } globalx1 <<= (i+12); globalx2 <<= i; globalx <<= i; globaly1 <<= (j+12); globaly2 <<= j; globaly <<= j; if (dastat == 0) { globalx1 += (((int32_t)sec->ceilingxpanning)<<24); globaly1 += (((int32_t)sec->ceilingypanning)<<24); } else { globalx1 += (((int32_t)sec->floorxpanning)<<24); globaly1 += (((int32_t)sec->floorypanning)<<24); } asm1 = -(globalzd>>(16-BITSOFPRECISION)); globvis = globalvisibility; if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16))); globvis = mulscale13(globvis,daz); globvis = mulscale16(globvis,xdimscale); j = FP_OFF(palookup[globalpal]); setupslopevlin(((int32_t)(picsiz[globalpicnum]&15))+(((int32_t)(picsiz[globalpicnum]>>4))<<8),waloff[globalpicnum],-ylookup[1]); l = (globalzd>>16); shinc = mulscale16(globalz,xdimenscale); if (shinc > 0) shoffs = (4<<15); else shoffs = ((16380-ydimen)<<15); // JBF: was 2044 if (dastat == 0) y1 = umost[dax1]; else y1 = max(umost[dax1],dplc[dax1]); m1 = mulscale16(y1,globalzd) + (globalzx>>6); //Avoid visibility overflow by crossing horizon if (globalzd > 0) m1 += (globalzd>>16); else m1 -= (globalzd>>16); m2 = m1+l; mptr1 = (intptr_t *)&slopalookup[y1+(shoffs>>15)]; mptr2 = mptr1+1; for (x=dax1; x<=dax2; x++) { if (dastat == 0) { y1 = umost[x]; y2 = min(dmost[x],uplc[x])-1; } else { y1 = max(umost[x],dplc[x]); y2 = dmost[x]-1; } if (y1 <= y2) { nptr1 = (intptr_t *)&slopalookup[y1+(shoffs>>15)]; nptr2 = (intptr_t *)&slopalookup[y2+(shoffs>>15)]; while (nptr1 <= mptr1) { *mptr1-- = j + (getpalookup((int32_t)mulscale24(krecipasm(m1),globvis),globalshade)<<8); m1 -= l; } while (nptr2 >= mptr2) { *mptr2++ = j + (getpalookup((int32_t)mulscale24(krecipasm(m2),globvis),globalshade)<<8); m2 += l; } globalx3 = (globalx2>>10); globaly3 = (globaly2>>10); asm3 = mulscale16(y2,globalzd) + (globalzx>>6); slopevlin(ylookup[y2]+x+frameoffset,krecipasm(asm3>>3),(intptr_t)nptr2,y2-y1+1,globalx1,globaly1); if ((x&15) == 0) faketimerhandler(); } globalx2 += globalx; globaly2 += globaly; globalzx += globalz; shoffs += shinc; } } // // parascan (internal) // static void parascan(int32_t dax1, int32_t dax2, int32_t sectnum, char dastat, int32_t bunch) { sectortype *sec; int32_t j, k, l, m, n, x, z, wallnum, nextsectnum, globalhorizbak; int16_t *topptr, *botptr; UNREFERENCED_PARAMETER(dax1); UNREFERENCED_PARAMETER(dax2); sectnum = thesector[bunchfirst[bunch]]; sec = §or[sectnum]; globalhorizbak = globalhoriz; if (parallaxyscale != 65536) globalhoriz = mulscale16(globalhoriz-(ydimen>>1),parallaxyscale) + (ydimen>>1); globvis = globalpisibility; //globalorientation = 0L; if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16))); if (dastat == 0) { globalpal = sec->ceilingpal; globalpicnum = sec->ceilingpicnum; globalshade = (int32_t)sec->ceilingshade; globalxpanning = (int32_t)sec->ceilingxpanning; globalypanning = (int32_t)sec->ceilingypanning; topptr = umost; botptr = uplc; } else { globalpal = sec->floorpal; globalpicnum = sec->floorpicnum; globalshade = (int32_t)sec->floorshade; globalxpanning = (int32_t)sec->floorxpanning; globalypanning = (int32_t)sec->floorypanning; topptr = dplc; botptr = dmost; } if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0; if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(int16_t)sectnum); globalshiftval = (picsiz[globalpicnum]>>4); if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++; globalshiftval = 32-globalshiftval; globalzd = (((tilesizy[globalpicnum]>>1)+parallaxyoffs)<=0; z=p2[z]) { wallnum = thewall[z]; nextsectnum = wall[wallnum].nextsector; if (nextsectnum >= 0) //else negative array access { if (dastat == 0) j = sector[nextsectnum].ceilingstat; else j = sector[nextsectnum].floorstat; } if ((nextsectnum < 0) || (wall[wallnum].cstat&32) || ((j&1) == 0)) { if (x == -1) x = xb1[z]; if (parallaxtype == 0) { n = mulscale16(xdimenrecip,viewingrange); for (j=xb1[z]; j<=xb2[z]; j++) lplc[j] = (((mulscale23(j-halfxdimen,n)+globalang)&2047)>>k); } else { for (j=xb1[z]; j<=xb2[z]; j++) lplc[j] = ((((int32_t)radarang2[j]+globalang)&2047)>>k); } if (parallaxtype == 2) { n = mulscale16(xdimscale,viewingrange); for (j=xb1[z]; j<=xb2[z]; j++) swplc[j] = mulscale14(sintable[((int32_t)radarang2[j]+512)&2047],n); } else clearbuf(&swplc[xb1[z]],xb2[z]-xb1[z]+1,mulscale16(xdimscale,viewingrange)); } else if (x >= 0) { l = globalpicnum; m = (picsiz[globalpicnum]&15); globalpicnum = l+pskyoff[lplc[x]>>m]; if (((lplc[x]^lplc[xb1[z]-1])>>m) == 0) wallscan(x,xb1[z]-1,topptr,botptr,swplc,lplc); else { j = x; while (x < xb1[z]) { n = l+pskyoff[lplc[x]>>m]; if (n != globalpicnum) { wallscan(j,x-1,topptr,botptr,swplc,lplc); j = x; globalpicnum = n; } x++; } if (j < x) wallscan(j,x-1,topptr,botptr,swplc,lplc); } globalpicnum = l; x = -1; } } if (x >= 0) { l = globalpicnum; m = (picsiz[globalpicnum]&15); globalpicnum = l+pskyoff[lplc[x]>>m]; if (((lplc[x]^lplc[xb2[bunchlast[bunch]]])>>m) == 0) wallscan(x,xb2[bunchlast[bunch]],topptr,botptr,swplc,lplc); else { j = x; while (x <= xb2[bunchlast[bunch]]) { n = l+pskyoff[lplc[x]>>m]; if (n != globalpicnum) { wallscan(j,x-1,topptr,botptr,swplc,lplc); j = x; globalpicnum = n; } x++; } if (j <= x) wallscan(j,x-1,topptr,botptr,swplc,lplc); } globalpicnum = l; } globalhoriz = globalhorizbak; } // // drawalls (internal) // static void drawalls(int32_t bunch) { sectortype *sec, *nextsec; walltype *wal; int32_t i, x, x1, x2, cz[5], fz[5]; int32_t z, wallnum, sectnum, nextsectnum; int32_t startsmostwallcnt, startsmostcnt, gotswall; char andwstat1, andwstat2; z = bunchfirst[bunch]; sectnum = thesector[z]; sec = §or[sectnum]; andwstat1 = 0xff; andwstat2 = 0xff; for (; z>=0; z=p2[z]) //uplc/dplc calculation { andwstat1 &= wallmost(uplc,z,sectnum,(uint8_t)0); andwstat2 &= wallmost(dplc,z,sectnum,(uint8_t)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) { smostwall[smostwallcnt] = z; smostwalltype[smostwallcnt] = 0; smostwallcnt++; continue; } } wallnum = thewall[z]; wal = &wall[wallnum]; nextsectnum = wal->nextsector; nextsec = nextsectnum>=0 ? §or[nextsectnum] : NULL; 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((int16_t)sectnum,wal->x,wal->y,&cz[0],&fz[0]); getzsofslope((int16_t)sectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[1],&fz[1]); getzsofslope((int16_t)nextsectnum,wal->x,wal->y,&cz[2],&fz[2]); getzsofslope((int16_t)nextsectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[3],&fz[3]); getzsofslope((int16_t)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,(uint8_t)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; searchbottomwall = searchwall = wallnum; searchstat = 0; searchit = 1; } globalorientation = (int32_t)wal->cstat; globalpicnum = wal->picnum; if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0; globalxpanning = (int32_t)wal->xpanning; globalypanning = (int32_t)wal->ypanning; globalshiftval = (picsiz[globalpicnum]>>4); if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++; globalshiftval = 32-globalshiftval; if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(int16_t)wallnum+16384); globalshade = (int32_t)wal->shade; globvis = globalvisibility; if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16))); globalpal = (int32_t)wal->pal; if (palookup[globalpal] == NULL) globalpal = 0; // JBF: fixes crash 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(&umost[x1],&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,(uint8_t)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; searchbottomwall = searchwall = wallnum; if ((wal->cstat&2) > 0) searchbottomwall = wal->nextwall; searchstat = 0; searchit = 1; } if ((wal->cstat&2) > 0) { wallnum = wal->nextwall; wal = &wall[wallnum]; globalorientation = (int32_t)wal->cstat; globalpicnum = wal->picnum; if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0; globalxpanning = (int32_t)wal->xpanning; globalypanning = (int32_t)wal->ypanning; if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(int16_t)wallnum+16384); globalshade = (int32_t)wal->shade; globalpal = (int32_t)wal->pal; wallnum = thewall[z]; wal = &wall[wallnum]; } else { globalorientation = (int32_t)wal->cstat; globalpicnum = wal->picnum; if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0; globalxpanning = (int32_t)wal->xpanning; globalypanning = (int32_t)wal->ypanning; if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(int16_t)wallnum+16384); globalshade = (int32_t)wal->shade; globalpal = (int32_t)wal->pal; } if (palookup[globalpal] == NULL) globalpal = 0; // JBF: fixes crash globvis = globalvisibility; if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t)(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(&dmost[x1],&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; xcstat&32)) //White/1-way wall { globalorientation = (int32_t)wal->cstat; if (nextsectnum < 0) globalpicnum = wal->picnum; else globalpicnum = wal->overpicnum; if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0; globalxpanning = (int32_t)wal->xpanning; globalypanning = (int32_t)wal->ypanning; if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(int16_t)wallnum+16384); globalshade = (int32_t)wal->shade; globvis = globalvisibility; if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16))); globalpal = (int32_t)wal->pal; if (palookup[globalpal] == NULL) globalpal = 0; // JBF: fixes crash 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; searchbottomwall = searchwall = wallnum; if (nextsectnum < 0) searchstat = 0; else searchstat = 4; } } } } // // drawvox // #ifdef SUPERBUILD static void drawvox(int32_t dasprx, int32_t daspry, int32_t dasprz, int32_t dasprang, int32_t daxscale, int32_t dayscale, char daindex, int8_t dashade, char dapal, int32_t *daumost, int32_t *dadmost) { int32_t i, j, k, x, y, syoff, ggxstart, ggystart, nxoff; int32_t cosang, sinang, sprcosang, sprsinang, backx, backy, gxinc, gyinc; int32_t daxsiz, daysiz, dazsiz, daxpivot, daypivot, dazpivot; int32_t daxscalerecip, dayscalerecip, cnt, gxstart, gystart, odayscale; int32_t l1, l2, /*slabxoffs,*/ xyvoxoffs, *longptr; intptr_t slabxoffs; int32_t lx, rx, nx, ny, x1=0, y1=0, z1, x2=0, y2=0, z2, yplc, yinc=0; int32_t yoff, xs=0, ys=0, xe, ye, xi=0, yi=0, cbackx, cbacky, dagxinc, dagyinc; int16_t *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 = (int32_t)(getpalookup((int32_t)mulscale21(globvis,i),(int32_t)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) i = MAXVOXMIPS-1; if (novoxmips) i = 0; davoxptr = (char *)voxoff[daindex][i]; if (!davoxptr && i > 0) { davoxptr = (char *)voxoff[daindex][0]; i = 0; } if (!davoxptr) return; if (voxscale[daindex] == 65536) { daxscale <<= (i+8); dayscale <<= (i+8); } else { daxscale = mulscale8(daxscale<>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 = x*cosang + y*sinang; gxinc = dmulscale10(sprsinang,cosang,sprcosang,-sinang); gyinc = dmulscale10(sprcosang,cosang,sprsinang,sinang); x = 0; y = 0; j = max(daxsiz,daysiz); for (i=0; i<=j; i++) { ggxinc[i] = x; x += gxinc; ggyinc[i] = y; y += gyinc; } if ((klabs(globalposz-dasprz)>>10) >= klabs(odayscale)) return; syoff = divscale21(globalposz-dasprz,odayscale) + (dazpivot<<7); yoff = ((klabs(gxinc)+klabs(gyinc))>>1); longptr = (int32_t *)davoxptr; xyvoxoffs = ((daxsiz+1)<<2); begindrawing(); //{{{ for (cnt=0; cnt<8; cnt++) { switch (cnt) { case 0: xs = 0; ys = 0; xi = 1; yi = 1; break; case 1: xs = daxsiz-1; ys = 0; xi = -1; yi = 1; break; case 2: xs = 0; ys = daysiz-1; xi = 1; yi = -1; break; case 3: xs = daxsiz-1; ys = daysiz-1; xi = -1; yi = -1; break; case 4: xs = 0; ys = cbacky; xi = 1; yi = 2; break; case 5: xs = daxsiz-1; ys = cbacky; xi = -1; yi = 2; break; case 6: xs = cbackx; ys = 0; xi = 2; yi = 1; break; case 7: xs = cbackx; ys = daysiz-1; xi = 2; yi = -1; break; } xe = cbackx; ye = cbacky; if (cnt < 4) { if ((xi < 0) && (xe >= xs)) continue; if ((xi > 0) && (xe <= xs)) continue; if ((yi < 0) && (ye >= ys)) continue; if ((yi > 0) && (ye <= ys)) continue; } else { if ((xi < 0) && (xe > xs)) continue; if ((xi > 0) && (xe < xs)) continue; if ((yi < 0) && (ye > ys)) continue; if ((yi > 0) && (ye < ys)) continue; xe += xi; ye += yi; } i = ksgn(ys-backy)+ksgn(xs-backx)*3+4; switch (i) { case 6: case 7: x1 = 0; y1 = 0; break; case 8: case 5: x1 = gxinc; y1 = gyinc; break; case 0: case 3: x1 = gyinc; y1 = -gxinc; break; case 2: case 1: x1 = gxinc+gyinc; y1 = gyinc-gxinc; break; } switch (i) { case 2: case 5: x2 = 0; y2 = 0; break; case 0: case 1: x2 = gxinc; y2 = gyinc; break; case 8: case 7: x2 = gyinc; y2 = -gxinc; break; case 6: case 3: x2 = gxinc+gyinc; y2 = gyinc-gxinc; break; } oand = pow2char[(xs 0) { dagxinc = gxinc; dagyinc = mulscale16(gyinc,viewingrangerecip); } else { dagxinc = -gxinc; dagyinc = -mulscale16(gyinc,viewingrangerecip); } //Fix for non 90 degree viewing ranges nxoff = mulscale16(x2-x1,viewingrangerecip); x1 = mulscale16(x1,viewingrangerecip); ggxstart = gxstart+ggyinc[ys]; ggystart = gystart-ggxinc[ys]; for (x=xs; x!=xe; x+=xi) { slabxoffs = (intptr_t)&davoxptr[B_LITTLE32(longptr[x])]; shortptr = (int16_t *)&davoxptr[((x*(daysiz+1))<<1)+xyvoxoffs]; nx = mulscale16(ggxstart+ggxinc[x],viewingrangerecip)+x1; ny = ggystart+ggyinc[x]; for (y=ys; y!=ye; y+=yi,nx+=dagyinc,ny-=dagxinc) { if ((ny <= nytooclose) || (ny >= nytoofar)) continue; voxptr = (char *)(B_LITTLE16(shortptr[y])+slabxoffs); voxend = (char *)(B_LITTLE16(shortptr[y+1])+slabxoffs); if (voxptr == voxend) continue; lx = mulscale32(nx>>3,distrecip[(ny+y1)>>14])+halfxdimen; if (lx < 0) lx = 0; rx = mulscale32((nx+nxoff)>>3,distrecip[(ny+y2)>>14])+halfxdimen; if (rx > xdimen) rx = xdimen; if (rx <= lx) continue; rx -= lx; l1 = distrecip[(ny-yoff)>>14]; l2 = distrecip[(ny+yoff)>>14]; for (; voxptr= 1024) yinc = divscale16(voxptr[1],z2-z1); else if (z2 > z1) yinc = (lowrecip[z2-z1]*voxptr[1]>>8); if (z1 < daumost[lx]) { yplc = yinc*(daumost[lx]-z1); z1 = daumost[lx]; } else yplc = 0; } if (z2 > dadmost[lx]) z2 = dadmost[lx]; z2 -= z1; if (z2 <= 0) continue; drawslab(rx,yplc,z2,yinc,(intptr_t)&voxptr[3],ylookup[z1]+lx+frameoffset); } } } } enddrawing(); //}}} } #endif // // drawsprite (internal) // static void drawsprite(int32_t snum) { spritetype *tspr; sectortype *sec; int32_t startum, startdm, sectnum, xb, yp, cstat; int32_t siz, xsiz, ysiz, xoff, yoff, xspan, yspan; int32_t x1, y1, x2, y2, lx, rx, dalx2, darx2, i, j, k, x, linum, linuminc; int32_t yinc, z, z1, z2, xp1, yp1, xp2, yp2; int32_t xv, yv, top, topinc, bot, botinc, hplc, hinc; int32_t cosang, sinang, dax, day, lpoint, lmax, rpoint, rmax, dax1, dax2, y; int32_t npoints, npoints2, zz, t, zsgn, zzsgn, *longptr; int32_t tilenum, vtilenum = 0, spritenum; char swapped, daclip; //============================================================================= //POLYMOST BEGINS #ifdef POLYMOST if (rendmode == 3) { polymost_drawsprite(snum); # ifdef USE_OPENGL bglDisable(GL_POLYGON_OFFSET_FILL); # endif return; } # ifdef POLYMER if (rendmode == 4) { bglEnable(GL_ALPHA_TEST); bglEnable(GL_BLEND); polymer_drawsprite(snum); bglDisable(GL_BLEND); bglDisable(GL_ALPHA_TEST); return; } # endif #endif //============================================================================= //POLYMOST ENDS tspr = tspriteptr[snum]; xb = spritesx[snum]; yp = spritesy[snum]; tilenum = tspr->picnum; spritenum = tspr->owner; cstat = tspr->cstat; if (tilenum < 0 || tilenum >= MAXSPRITES) return; #ifdef SUPERBUILD if ((cstat&48)==48) vtilenum = tilenum; // if the game wants voxels, it gets voxels else if ((cstat&48)!=48 && (usevoxels) && (tiletovox[tilenum] != -1) #if defined(POLYMOST) && defined(USE_OPENGL) && (!(spriteext[tspr->owner].flags&SPREXT_NOTMD)) #endif ) { vtilenum = tiletovox[tilenum]; cstat |= 48; } #endif 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 = §or[sectnum]; globalpal = tspr->pal; if (palookup[globalpal] == NULL) globalpal = 0; // JBF: fixes null-pointer crash globalshade = tspr->shade; if (cstat&2) { if (cstat&512) settransreverse(); else settransnormal(); } xoff = (int32_t)((int8_t)((picanm[tilenum]>>8)&255))+((int32_t)tspr->xoffset); yoff = (int32_t)((int8_t)((picanm[tilenum]>>16)&255))+((int32_t)tspr->yoffset); if ((cstat&48) == 0) { if (yp <= (4<<8)) return; siz = divscale19(xdimenscale,yp); xv = mulscale16(((int32_t)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,(int16_t)startum); dwall[x] = min(startdmost[x+windowx1]-windowy1,(int16_t)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,(int32_t)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(&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L); for (k=dalx2; k<=darx2; k++) dwall[k] = 0; } 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= 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,(int32_t)((uint8_t)(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((intptr_t)&lwall[lx],rx-lx+1,linum,linuminc); clearbuf(&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,(int32_t)((uint8_t)(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,(int32_t)(MAXWALLSB-1),z1-globalposz); owallmost(dwall,(int32_t)(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(&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L); for (k=dalx2; k<=darx2; k++) dwall[k] = 0; } 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= 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= 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 (xdimen<<16)) xsi[z] = (xdimen<<16); if (ysi[z] < ((int32_t)0<<16)) ysi[z] = ((int32_t)0<<16); if (ysi[z] > ((int32_t)ydimen<<16)) ysi[z] = ((int32_t)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((intptr_t)(&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((intptr_t)(&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(&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L); for (x=dalx2; x<=darx2; x++) dwall[x] = 0; } 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,(int32_t)((uint8_t)(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) { int32_t nxrepeat, nyrepeat; lx = 0; rx = xdim-1; for (x=lx; x<=rx; x++) { lwall[x] = (int32_t)startumost[x+windowx1]-windowy1; swall[x] = (int32_t)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,(int32_t)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(&swall[dalx2],(darx2-dalx2+1)*sizeof(swall[0]),0L); for (x=dalx2; x<=darx2; x++) swall[x] = 0; } 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; xxrepeat)<<16); nyrepeat = (((int32_t)tspr->yrepeat)<<16); } else { nxrepeat = ((int32_t)tspr->xrepeat)*voxscale[vtilenum]; nyrepeat = ((int32_t)tspr->yrepeat)*voxscale[vtilenum]; } if (!(cstat&128)) tspr->z -= mulscale22(B_LITTLE32(longptr[5]),nyrepeat); yoff = (int32_t)((int8_t)((picanm[sprite[tspr->owner].picnum]>>16)&255))+((int32_t)tspr->yoffset); tspr->z -= mulscale14(yoff,nyrepeat); globvis = globalvisibility; if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16))); if ((searchit >= 1) && (yp > (4<<8)) && (searchy >= lwall[searchx]) && (searchy < swall[searchx])) { siz = divscale19(xdimenscale,yp); xv = mulscale16(nxrepeat,xyaspect); xspan = ((B_LITTLE32(longptr[0])+B_LITTLE32(longptr[1]))>>1); yspan = B_LITTLE32(longptr[2]); xsiz = mulscale30(siz,xv*xspan); ysiz = mulscale30(siz,nyrepeat*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 -= mulscale30(siz,nyrepeat*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; } } } } i = (int32_t)tspr->ang+1536; #if defined(POLYMOST) && defined(USE_OPENGL) i += spriteext[tspr->owner].angoff; #endif drawvox(tspr->x,tspr->y,tspr->z,i,(int32_t)tspr->xrepeat,(int32_t)tspr->yrepeat,vtilenum,tspr->shade,tspr->pal,lwall,swall); } #endif if (automapping == 1) show2dsprite[spritenum>>3] |= pow2char[spritenum&7]; } // // drawmaskwall (internal) // static void drawmaskwall(int16_t damaskwallcnt) { int32_t i, j, k, x, z, sectnum, z1, z2, lx, rx; sectortype *sec, *nsec; walltype *wal; //============================================================================= //POLYMOST BEGINS #ifdef POLYMOST if (rendmode == 3) { polymost_drawmaskwall(damaskwallcnt); return; } # ifdef POLYMER if (rendmode == 4) { bglEnable(GL_ALPHA_TEST); bglEnable(GL_BLEND); polymer_drawmaskwall(damaskwallcnt); bglDisable(GL_BLEND); bglDisable(GL_ALPHA_TEST); return; } #endif #endif //============================================================================= //POLYMOST ENDS z = maskwall[damaskwallcnt]; wal = &wall[thewall[z]]; sectnum = thesector[z]; sec = §or[sectnum]; nsec = §or[wal->nextsector]; z1 = max(nsec->ceilingz,sec->ceilingz); z2 = min(nsec->floorz,sec->floorz); wallmost(uwall,z,sectnum,(uint8_t)0); wallmost(uplc,z,(int32_t)wal->nextsector,(uint8_t)0); for (x=xb1[z]; x<=xb2[z]; x++) if (uplc[x] > uwall[x]) uwall[x] = uplc[x]; wallmost(dwall,z,sectnum,(uint8_t)1); wallmost(dplc,z,(int32_t)wal->nextsector,(uint8_t)1); for (x=xb1[z]; x<=xb2[z]; x++) if (dplc[x] < dwall[x]) dwall[x] = dplc[x]; prepwall(z,wal); globalorientation = (int32_t)wal->cstat; globalpicnum = wal->overpicnum; if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0; globalxpanning = (int32_t)wal->xpanning; globalypanning = (int32_t)wal->ypanning; if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(int16_t)thewall[z]+16384); globalshade = (int32_t)wal->shade; globvis = globalvisibility; if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16))); globalpal = (int32_t)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(&dwall[lx],(rx-lx+1)*sizeof(dwall[0]),0L); for (x=lx; x<=rx; x++) dwall[x] = 0; } 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]); } } // // fillpolygon (internal) // static void fillpolygon(int32_t npoints) { int32_t z, zz, x1, y1, x2, y2, miny, maxy, y, xinc, cnt; int32_t ox, oy, bx, by, day1, day2; int16_t *ptr, *ptr2; intptr_t p; #if defined POLYMOST && defined USE_OPENGL if (rendmode >= 3 && qsetmode == 200) { polymost_fillpolygon(npoints); return; } #endif miny = 0x7fffffff; maxy = 0x80000000; for (z=npoints-1; z>=0; z--) { y = ry1[z]; miny = min(miny,y); maxy = max(maxy,y); } miny = (miny>>12); maxy = (maxy>>12); if (miny < 0) miny = 0; if (maxy >= ydim) maxy = ydim-1; ptr = smost; //They're pointers! - watch how you optimize this thing for (y=miny; y<=maxy; y++) { dotp1[y] = ptr; dotp2[y] = ptr+(MAXNODESPERLINE>>1); ptr += MAXNODESPERLINE; } for (z=npoints-1; z>=0; z--) { zz = xb1[z]; y1 = ry1[z]; day1 = (y1>>12); y2 = ry1[zz]; day2 = (y2>>12); if (day1 != day2) { x1 = rx1[z]; x2 = rx1[zz]; xinc = divscale12(x2-x1,y2-y1); if (day2 > day1) { x1 += mulscale12((day1<<12)+4095-y1,xinc); for (y=day1; y>12); x1 += xinc; } } else { x2 += mulscale12((day2<<12)+4095-y2,xinc); for (y=day2; y>12); x2 += xinc; } } } } globalx1 = mulscale16(globalx1,xyaspect); globaly2 = mulscale16(globaly2,xyaspect); oy = miny+1-(ydim>>1); globalposx += oy*globalx1; globalposy += oy*globaly2; setuphlineasm4(asm1,asm2); ptr = smost; for (y=miny; y<=maxy; y++) { cnt = dotp1[y]-ptr; ptr2 = ptr+(MAXNODESPERLINE>>1); for (z=cnt-1; z>=0; z--) { day1 = 0; day2 = 0; for (zz=z; zz>0; zz--) { if (ptr[zz] < ptr[day1]) day1 = zz; if (ptr2[zz] < ptr2[day2]) day2 = zz; } x1 = ptr[day1]; ptr[day1] = ptr[z]; x2 = ptr2[day2]-1; ptr2[day2] = ptr2[z]; if (x1 > x2) continue; if (globalpolytype < 1) { //maphline ox = x2+1-(xdim>>1); bx = ox*asm1 + globalposx; by = ox*asm2 - globalposy; p = ylookup[y]+x2+frameplace; hlineasm4(x2-x1,-1L,globalshade<<8,by,bx,p); } else { //maphline ox = x1+1-(xdim>>1); bx = ox*asm1 + globalposx; by = ox*asm2 - globalposy; p = ylookup[y]+x1+frameplace; if (globalpolytype == 1) mhline(globalbufplc,bx,(x2-x1)<<16,0L,by,p); else { thline(globalbufplc,bx,(x2-x1)<<16,0L,by,p); } } } globalposx += globalx1; globalposy += globaly2; ptr += MAXNODESPERLINE; } faketimerhandler(); } // // clippoly (internal) // static int32_t clippoly(int32_t npoints, int32_t clipstat) { int32_t z, zz, s1, s2, t, npoints2, start2, z1, z2, z3, z4, splitcnt; int32_t cx1, cy1, cx2, cy2; cx1 = windowx1; cy1 = windowy1; cx2 = windowx2+1; cy2 = windowy2+1; cx1 <<= 12; cy1 <<= 12; cx2 <<= 12; cy2 <<= 12; if (clipstat&0xa) //Need to clip top or left { npoints2 = 0; start2 = 0; z = 0; splitcnt = 0; do { s2 = cx1-rx1[z]; do { zz = xb1[z]; xb1[z] = -1; s1 = s2; s2 = cx1-rx1[zz]; if (s1 < 0) { rx2[npoints2] = rx1[z]; ry2[npoints2] = ry1[z]; xb2[npoints2] = npoints2+1; npoints2++; } if ((s1^s2) < 0) { rx2[npoints2] = rx1[z]+scale(rx1[zz]-rx1[z],s1,s1-s2); ry2[npoints2] = ry1[z]+scale(ry1[zz]-ry1[z],s1,s1-s2); if (s1 < 0) p2[splitcnt++] = npoints2; xb2[npoints2] = npoints2+1; npoints2++; } z = zz; } while (xb1[z] >= 0); if (npoints2 >= start2+3) xb2[npoints2-1] = start2, start2 = npoints2; else npoints2 = start2; z = 1; while ((z < npoints) && (xb1[z] < 0)) z++; } while (z < npoints); if (npoints2 <= 2) return(0); for (z=1; z= 0); if (npoints >= start2+3) xb1[npoints-1] = start2, start2 = npoints; else npoints = start2; z = 1; while ((z < npoints2) && (xb2[z] < 0)) z++; } while (z < npoints2); if (npoints <= 2) return(0); for (z=1; z= 0); if (npoints2 >= start2+3) xb2[npoints2-1] = start2, start2 = npoints2; else npoints2 = start2; z = 1; while ((z < npoints) && (xb1[z] < 0)) z++; } while (z < npoints); if (npoints2 <= 2) return(0); for (z=1; z= 0); if (npoints >= start2+3) xb1[npoints-1] = start2, start2 = npoints; else npoints = start2; z = 1; while ((z < npoints2) && (xb2[z] < 0)) z++; } while (z < npoints2); if (npoints <= 2) return(0); for (z=1; z= 3 && qsetmode == 200) { polymost_dorotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,cx1,cy1,cx2,cy2,uniqid); return; } # ifdef POLYMER if (rendmode == 4 && qsetmode == 200) { polymer_rotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,cx1,cy1,cx2,cy2); return; } #endif #endif //============================================================================= //POLYMOST ENDS if (cx1 < 0) cx1 = 0; if (cy1 < 0) cy1 = 0; if (cx2 > xres-1) cx2 = xres-1; if (cy2 > yres-1) cy2 = yres-1; xsiz = tilesizx[picnum]; ysiz = tilesizy[picnum]; if (dastat&16) { xoff = 0; yoff = 0; } else { xoff = (int32_t)((int8_t)((picanm[picnum]>>8)&255))+(xsiz>>1); yoff = (int32_t)((int8_t)((picanm[picnum]>>16)&255))+(ysiz>>1); } if (dastat&4) yoff = ysiz-yoff; cosang = sintable[(a+512)&2047]; sinang = sintable[a&2047]; if ((dastat&2) != 0) //Auto window size scaling { if ((dastat&8) == 0) { x = xdimenscale; //= scale(xdimen,yxaspect,320); sx = ((cx1+cx2+2)<<15)+scale(sx-(320<<15),xdimen,320); sy = ((cy1+cy2+2)<<15)+mulscale16(sy-(200<<15),x); } else { //If not clipping to startmosts, & auto-scaling on, as a //hard-coded bonus, scale to full screen instead x = scale(xdim,yxaspect,320); sx = (xdim<<15)+32768+scale(sx-(320<<15),xdim,320); sy = (ydim<<15)+32768+mulscale16(sy-(200<<15),x); } z = mulscale16(z,x); } xv = mulscale14(cosang,z); yv = mulscale14(sinang,z); if (((dastat&2) != 0) || ((dastat&8) == 0)) //Don't aspect unscaled perms { xv2 = mulscale16(xv,xyaspect); yv2 = mulscale16(yv,xyaspect); } else { xv2 = xv; yv2 = yv; } nry1[0] = sy - (yv*xoff + xv*yoff); nry1[1] = nry1[0] + yv*xsiz; nry1[3] = nry1[0] + xv*ysiz; nry1[2] = nry1[1]+nry1[3]-nry1[0]; i = (cy1<<16); if ((nry1[0]i) && (nry1[1]>i) && (nry1[2]>i) && (nry1[3]>i)) return; nrx1[0] = sx - (xv2*xoff - yv2*yoff); nrx1[1] = nrx1[0] + xv2*xsiz; nrx1[3] = nrx1[0] - yv2*ysiz; nrx1[2] = nrx1[1]+nrx1[3]-nrx1[0]; i = (cx1<<16); if ((nrx1[0]i) && (nrx1[1]>i) && (nrx1[2]>i) && (nrx1[3]>i)) return; gx1 = nrx1[0]; gy1 = nry1[0]; //back up these before clipping if ((npoints = clippoly4(cx1<<16,cy1<<16,(cx2+1)<<16,(cy2+1)<<16)) < 3) return; lx = nrx1[0]; rx = nrx1[0]; nextv = 0; for (v=npoints-1; v>=0; v--) { x1 = nrx1[v]; x2 = nrx1[nextv]; dax1 = (x1>>16); if (x1 < lx) lx = x1; dax2 = (x2>>16); if (x1 > rx) rx = x1; if (dax1 != dax2) { y1 = nry1[v]; y2 = nry1[nextv]; yinc = divscale16(y2-y1,x2-x1); if (dax2 > dax1) { yplc = y1 + mulscale16((dax1<<16)+65535-x1,yinc); qinterpolatedown16short((intptr_t)(&uplc[dax1]),dax2-dax1,yplc,yinc); } else { yplc = y2 + mulscale16((dax2<<16)+65535-x2,yinc); qinterpolatedown16short((intptr_t)(&dplc[dax2]),dax1-dax2,yplc,yinc); } } nextv = v; } if (waloff[picnum] == 0) loadtile(picnum); setgotpic(picnum); bufplc = waloff[picnum]; if (palookup[dapalnum] == NULL) dapalnum = 0; palookupoffs = FP_OFF(palookup[dapalnum]) + (getpalookup(0L,(int32_t)dashade)<<8); i = divscale32(1L,z); xv = mulscale14(sinang,i); yv = mulscale14(cosang,i); if (((dastat&2) != 0) || ((dastat&8) == 0)) //Don't aspect unscaled perms { yv2 = mulscale16(-xv,yxaspect); xv2 = mulscale16(yv,yxaspect); } else { yv2 = -xv; xv2 = yv; } x1 = (lx>>16); x2 = (rx>>16); oy = 0; x = (x1<<16)-1-gx1; y = (oy<<16)+65535-gy1; bx = dmulscale16(x,xv2,y,xv); by = dmulscale16(x,yv2,y,yv); if (dastat&4) { yv = -yv; yv2 = -yv2; by = (ysiz<<16)-1-by; } /* if (origbuffermode == 0) { if (dastat&128) { obuffermode = buffermode; buffermode = 0; setactivepage(activepage); } } else if (dastat&8) permanentupdate = 1; */ #ifndef ENGINE_USING_A_C if ((dastat&1) == 0) { if (((a&1023) == 0) && (ysiz <= 256)) //vlineasm4 has 256 high limit! { if (dastat&64) setupvlineasm(24L); else setupmvlineasm(24L); by <<= 8; yv <<= 8; yv2 <<= 8; palookupoffse[0] = palookupoffse[1] = palookupoffse[2] = palookupoffse[3] = palookupoffs; vince[0] = vince[1] = vince[2] = vince[3] = yv; for (x=x1; x y1) y1 = startumost[x+xx]; if (startdmost[x+xx] < y2) y2 = startdmost[x+xx]; } if (y2 <= y1) continue; by += yv*(y1-oy); oy = y1; bufplce[xx] = (bx>>16)*ysiz+bufplc; vplce[xx] = by; y1ve[xx] = y1; y2ve[xx] = y2-1; bad &= ~pow2char[xx]; } p = x+frameplace; 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 (dastat&64) { if ((bad != 0) || (u4 >= d4)) { if (!(bad&1)) prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0); if (!(bad&2)) prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1); if (!(bad&4)) prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2); if (!(bad&8)) prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3); continue; } if (u4 > y1ve[0]) vplce[0] = prevlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0); if (u4 > y1ve[1]) vplce[1] = prevlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1); if (u4 > y1ve[2]) vplce[2] = prevlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2); if (u4 > y1ve[3]) vplce[3] = prevlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3); if (d4 >= u4) vlineasm4(d4-u4+1,ylookup[u4]+p); i = p+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); } else { 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); } faketimerhandler(); } } else { if (dastat&64) { if ((xv2&0x0000ffff) == 0) { qlinemode = 1; setupqrhlineasm4(0L,yv2<<16,(xv2>>16)*ysiz+(yv2>>16),palookupoffs,0L,0L); } else { qlinemode = 0; setuprhlineasm4(xv2<<16,yv2<<16,(xv2>>16)*ysiz+(yv2>>16),palookupoffs,ysiz,0L); } } else setuprmhlineasm4(xv2<<16,yv2<<16,(xv2>>16)*ysiz+(yv2>>16),palookupoffs,ysiz,0L); y1 = uplc[x1]; if (((dastat&8) == 0) && (startumost[x1] > y1)) y1 = startumost[x1]; y2 = y1; for (x=x1; x ny1) ny1 = startumost[x]-1; if (startdmost[x] < ny2) ny2 = startdmost[x]; } if (ny1 < ny2-1) { if (ny1 >= y2) { while (y1 < y2-1) { y1++; if ((y1&31) == 0) faketimerhandler(); //x,y1 bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1; if (dastat&64) { if (qlinemode) qrhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,0L ,by<<16,ylookup[y1]+x+frameplace); else rhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace); } else rmhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace); } y1 = ny1; } else { while (y1 < ny1) { y1++; if ((y1&31) == 0) faketimerhandler(); //x,y1 bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1; if (dastat&64) { if (qlinemode) qrhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,0L ,by<<16,ylookup[y1]+x+frameplace); else rhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace); } else rmhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace); } while (y1 > ny1) lastx[y1--] = x; } while (y2 > ny2) { y2--; if ((y2&31) == 0) faketimerhandler(); //x,y2 bx += xv*(y2-oy); by += yv*(y2-oy); oy = y2; if (dastat&64) { if (qlinemode) qrhlineasm4(x-lastx[y2],(bx>>16)*ysiz+(by>>16)+bufplc,0L,0L ,by<<16,ylookup[y2]+x+frameplace); else rhlineasm4(x-lastx[y2],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y2]+x+frameplace); } else rmhlineasm4(x-lastx[y2],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y2]+x+frameplace); } while (y2 < ny2) lastx[y2++] = x; } else { while (y1 < y2-1) { y1++; if ((y1&31) == 0) faketimerhandler(); //x,y1 bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1; if (dastat&64) { if (qlinemode) qrhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,0L ,by<<16,ylookup[y1]+x+frameplace); else rhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace); } else rmhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace); } if (x == x2-1) { bx += xv2; by += yv2; break; } y1 = uplc[x+1]; if (((dastat&8) == 0) && (startumost[x+1] > y1)) y1 = startumost[x+1]; y2 = y1; } bx += xv2; by += yv2; } while (y1 < y2-1) { y1++; if ((y1&31) == 0) faketimerhandler(); //x2,y1 bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1; if (dastat&64) { if (qlinemode) qrhlineasm4(x2-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,0L,by<<16,ylookup[y1]+x2+frameplace); else rhlineasm4(x2-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x2+frameplace); } else rmhlineasm4(x2-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x2+frameplace); } } } else { if ((dastat&1) == 0) { if (dastat&64) setupspritevline(palookupoffs,(xv>>16)*ysiz,xv<<16,ysiz,yv,0L); else msetupspritevline(palookupoffs,(xv>>16)*ysiz,xv<<16,ysiz,yv,0L); } else { tsetupspritevline(palookupoffs,(xv>>16)*ysiz,xv<<16,ysiz,yv,0L); if (dastat&32) settransreverse(); else settransnormal(); } for (x=x1; x y1) y1 = startumost[x]; if (startdmost[x] < y2) y2 = startdmost[x]; } if (y2 <= y1) continue; switch (y1-oy) { case -1: bx -= xv; by -= yv; oy = y1; break; case 0: break; case 1: bx += xv; by += yv; oy = y1; break; default: bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1; break; } p = ylookup[y1]+x+frameplace; if ((dastat&1) == 0) { if (dastat&64) spritevline(0L,by<<16,y2-y1+1,bx<<16,(bx>>16)*ysiz+(by>>16)+bufplc,p); else mspritevline(0L,by<<16,y2-y1+1,bx<<16,(bx>>16)*ysiz+(by>>16)+bufplc,p); } else { tspritevline(0L,by<<16,y2-y1+1,bx<<16,(bx>>16)*ysiz+(by>>16)+bufplc,p); } faketimerhandler(); } } #else // ENGINE_USING_A_C if ((dastat&1) == 0) { if (dastat&64) setupspritevline(palookupoffs,xv,yv,ysiz); else msetupspritevline(palookupoffs,xv,yv,ysiz); } else { tsetupspritevline(palookupoffs,xv,yv,ysiz); if (dastat&32) settransreverse(); else settransnormal(); } for (x=x1; x y1) y1 = startumost[x]; if (startdmost[x] < y2) y2 = startdmost[x]; } if (y2 <= y1) continue; switch (y1-oy) { case -1: bx -= xv; by -= yv; oy = y1; break; case 0: break; case 1: bx += xv; by += yv; oy = y1; break; default: bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1; break; } p = ylookup[y1]+x+frameplace; if ((dastat&1) == 0) { if (dastat&64) spritevline(bx&65535,by&65535,y2-y1+1,(bx>>16)*ysiz+(by>>16)+bufplc,p); else mspritevline(bx&65535,by&65535,y2-y1+1,(bx>>16)*ysiz+(by>>16)+bufplc,p); } else { tspritevline(bx&65535,by&65535,y2-y1+1,(bx>>16)*ysiz+(by>>16)+bufplc,p); //transarea += (y2-y1); } faketimerhandler(); } #endif /* if ((dastat&128) && (origbuffermode == 0)) { buffermode = obuffermode; setactivepage(activepage); }*/ } // // initksqrt (internal) // static inline void initksqrt(void) { int32_t i, j, k; j = 1; k = 0; for (i=0; i<4096; i++) { if (i >= j) { j <<= 2; k++; } sqrtable[i] = (uint16_t)(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); } } // // dosetaspect // static void dosetaspect(void) { int32_t i, j, k, x, xinc; if (xyaspect != oxyaspect) { oxyaspect = xyaspect; j = xyaspect*320; horizlookup2[horizycent-1] = divscale26(131072,j); for (i=ydim*4-1; i>=0; i--) if (i != (horizycent-1)) { horizlookup[i] = divscale28(1,i-(horizycent-1)); horizlookup2[i] = divscale14(klabs(horizlookup[i]),j); } } if ((xdimen != oxdimen) || (viewingrange != oviewingrange)) { oxdimen = xdimen; oviewingrange = viewingrange; xinc = mulscale32(viewingrange*320,xdimenrecip); x = (640<<16)-mulscale1(xinc,xdimen); for (i=0; i>16); x += xinc; if (j != 0) j = mulscale16((int32_t)radarang[k+1]-(int32_t)radarang[k],j); radarang2[i] = (int16_t)(((int32_t)radarang[k]+j)>>6); } #ifdef SUPERBUILD for (i=1; i<65536; i++) distrecip[i] = divscale20(xdimen,i); nytooclose = xdimen*2100; nytoofar = 65536*16384-1048576; #endif } } // // loadtables (internal) // static inline void calcbritable(void) { int32_t i,j; double a,b; for (i=0; i<16; i++) { a = (double)8 / ((double)i+8); b = (double)255 / pow((double)255,a); for (j=0; j<256; j++) // JBF 20040207: full 8bit precision britable[i][j] = (uint8_t)(pow((double)j,a)*b); } } static int32_t loadtables(void) { int32_t 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); for (i=2048-1; i>=0; i--) sintable[i] = B_LITTLE16(sintable[i]); kread(fil,radarang,640*2); for (i=640-1; i>=0; i--) radarang[i] = B_LITTLE16(radarang[i]); for (i=0; i<640; i++) radarang[1279-i] = -radarang[i]; //kread(fil,textfont,1024); //kread(fil,smalltextfont,1024); //kread(fil,britable,1024); calcbritable(); kclose(fil); } else { engineerrstr = "Failed to load TABLES.DAT!"; initprintf("ERROR: %s\n", engineerrstr); return 1; } tablesloaded = 1; } return 0; } // // initfastcolorlookup (internal) // static void initfastcolorlookup(int32_t rscale, int32_t gscale, int32_t bscale) { int32_t i, j, x, y, z; char *pal1; j = 0; for (i=64; i>=0; i--) { //j = (i-64)*(i-64); rdist[i] = rdist[128-i] = j*rscale; gdist[i] = gdist[128-i] = j*gscale; bdist[i] = bdist[128-i] = j*bscale; j += 129-(i<<1); } //clearbufbyte(colhere,sizeof(colhere),0L); //clearbufbyte(colhead,sizeof(colhead),0L); Bmemset(colhere,0,sizeof(colhere)); Bmemset(colhead,0,sizeof(colhead)); pal1 = (char *)&palette[768-3]; for (i=255; i>=0; i--,pal1-=3) { j = (pal1[0]>>3)*FASTPALGRIDSIZ*FASTPALGRIDSIZ+(pal1[1]>>3)*FASTPALGRIDSIZ+(pal1[2]>>3)+FASTPALGRIDSIZ*FASTPALGRIDSIZ+FASTPALGRIDSIZ+1; if (colhere[j>>3]&pow2char[j&7]) colnext[i] = colhead[j]; else colnext[i] = -1; colhead[j] = i; colhere[j>>3] |= pow2char[j&7]; } i = 0; for (x=-FASTPALGRIDSIZ*FASTPALGRIDSIZ; x<=FASTPALGRIDSIZ*FASTPALGRIDSIZ; x+=FASTPALGRIDSIZ*FASTPALGRIDSIZ) for (y=-FASTPALGRIDSIZ; y<=FASTPALGRIDSIZ; y+=FASTPALGRIDSIZ) for (z=-1; z<=1; z++) colscan[i++] = x+y+z; i = colscan[13]; colscan[13] = colscan[26]; colscan[26] = i; } // // loadpalette (internal) // static void loadpalette(void) { int32_t fil; if (paletteloaded != 0) return; if ((fil = kopen4load("palette.dat",0)) == -1) return; kread(fil,palette,768); kread(fil,&numpalookups,2); numpalookups = B_LITTLE16(numpalookups); if ((palookup[0] = (char *)Bmalloc(numpalookups<<8)) == NULL) allocache((intptr_t *)&palookup[0],numpalookups<<8,&permanentlock); if ((transluc = (char *)Bmalloc(65536L)) == NULL) allocache((intptr_t *)&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); { int32_t i, j, k = 0; for (i=0; i<256; i++) { j = ((int32_t)palette[i*3])+((int32_t)palette[i*3+1])+((int32_t)palette[i*3+2]); if (j > k) { k = j; whitecol = i; } } } paletteloaded = 1; } // // getclosestcol // int32_t getclosestcol(int32_t r, int32_t g, int32_t b) { int32_t i, j, k, dist, mindist, retcol; char *pal1; j = (r>>3)*FASTPALGRIDSIZ*FASTPALGRIDSIZ+(g>>3)*FASTPALGRIDSIZ+(b>>3)+FASTPALGRIDSIZ*FASTPALGRIDSIZ+FASTPALGRIDSIZ+1; mindist = min(rdist[coldist[r&7]+64+8],gdist[coldist[g&7]+64+8]); mindist = min(mindist,bdist[coldist[b&7]+64+8]); mindist++; r = 64-r; g = 64-g; b = 64-b; retcol = -1; for (k=26; k>=0; k--) { i = colscan[k]+j; if ((colhere[i>>3]&pow2char[i&7]) == 0) continue; i = colhead[i]; do { pal1 = (char *)&palette[i*3]; dist = gdist[pal1[1]+g]; if (dist < mindist) { dist += rdist[pal1[0]+r]; if (dist < mindist) { dist += bdist[pal1[2]+b]; if (dist < mindist) { mindist = dist; retcol = i; } } } i = colnext[i]; } while (i >= 0); } if (retcol >= 0) return(retcol); mindist = 0x7fffffff; pal1 = (char *)&palette[768-3]; for (i=255; i>=0; i--,pal1-=3) { dist = gdist[pal1[1]+g]; if (dist >= mindist) continue; dist += rdist[pal1[0]+r]; if (dist >= mindist) continue; dist += bdist[pal1[2]+b]; if (dist >= mindist) continue; mindist = dist; retcol = i; } return(retcol); } // // insertspritesect (internal) // int32_t insertspritesect(int16_t sectnum) { int16_t blanktouse; if ((sectnum >= MAXSECTORS) || (headspritesect[MAXSECTORS] == -1)) return(-1); //list full blanktouse = headspritesect[MAXSECTORS]; headspritesect[MAXSECTORS] = nextspritesect[blanktouse]; if (headspritesect[MAXSECTORS] >= 0) prevspritesect[headspritesect[MAXSECTORS]] = -1; prevspritesect[blanktouse] = -1; nextspritesect[blanktouse] = headspritesect[sectnum]; if (headspritesect[sectnum] >= 0) prevspritesect[headspritesect[sectnum]] = blanktouse; headspritesect[sectnum] = blanktouse; sprite[blanktouse].sectnum = sectnum; return(blanktouse); } // // insertspritestat (internal) // int32_t insertspritestat(int16_t statnum) { int16_t blanktouse; if ((statnum >= MAXSTATUS) || (headspritestat[MAXSTATUS] == -1)) return(-1); //list full blanktouse = headspritestat[MAXSTATUS]; headspritestat[MAXSTATUS] = nextspritestat[blanktouse]; if (headspritestat[MAXSTATUS] >= 0) prevspritestat[headspritestat[MAXSTATUS]] = -1; prevspritestat[blanktouse] = -1; nextspritestat[blanktouse] = headspritestat[statnum]; if (headspritestat[statnum] >= 0) prevspritestat[headspritestat[statnum]] = blanktouse; headspritestat[statnum] = blanktouse; sprite[blanktouse].statnum = statnum; return(blanktouse); } // // deletespritesect (internal) // int32_t deletespritesect(int16_t deleteme) { if (sprite[deleteme].sectnum == MAXSECTORS) return(-1); if (headspritesect[sprite[deleteme].sectnum] == deleteme) headspritesect[sprite[deleteme].sectnum] = nextspritesect[deleteme]; if (prevspritesect[deleteme] >= 0) nextspritesect[prevspritesect[deleteme]] = nextspritesect[deleteme]; if (nextspritesect[deleteme] >= 0) prevspritesect[nextspritesect[deleteme]] = prevspritesect[deleteme]; if (headspritesect[MAXSECTORS] >= 0) prevspritesect[headspritesect[MAXSECTORS]] = deleteme; prevspritesect[deleteme] = -1; nextspritesect[deleteme] = headspritesect[MAXSECTORS]; headspritesect[MAXSECTORS] = deleteme; sprite[deleteme].sectnum = MAXSECTORS; return(0); } // // deletespritestat (internal) // int32_t deletespritestat(int16_t deleteme) { if (sprite[deleteme].statnum == MAXSTATUS) return(-1); if (headspritestat[sprite[deleteme].statnum] == deleteme) headspritestat[sprite[deleteme].statnum] = nextspritestat[deleteme]; if (prevspritestat[deleteme] >= 0) nextspritestat[prevspritestat[deleteme]] = nextspritestat[deleteme]; if (nextspritestat[deleteme] >= 0) prevspritestat[nextspritestat[deleteme]] = prevspritestat[deleteme]; if (headspritestat[MAXSTATUS] >= 0) prevspritestat[headspritestat[MAXSTATUS]] = deleteme; prevspritestat[deleteme] = -1; nextspritestat[deleteme] = headspritestat[MAXSTATUS]; headspritestat[MAXSTATUS] = deleteme; sprite[deleteme].statnum = MAXSTATUS; return(0); } // // lintersect (internal) // static inline int32_t lintersect(int32_t x1, int32_t y1, int32_t z1, int32_t x2, int32_t y2, int32_t z2, int32_t x3, int32_t y3, int32_t x4, int32_t y4, int32_t *intx, int32_t *inty, int32_t *intz) { //p1 to p2 is a line segment int32_t x21, y21, x34, y34, x31, y31, bot, topt, topu, t; x21 = x2-x1; x34 = x3-x4; y21 = y2-y1; y34 = y3-y4; bot = x21*y34 - y21*x34; if (bot >= 0) { if (bot == 0) return(0); x31 = x3-x1; y31 = y3-y1; topt = x31*y34 - y31*x34; if ((topt < 0) || (topt >= bot)) return(0); topu = x21*y31 - y21*x31; if ((topu < 0) || (topu >= bot)) return(0); } else { x31 = x3-x1; y31 = y3-y1; topt = x31*y34 - y31*x34; if ((topt > 0) || (topt <= bot)) return(0); topu = x21*y31 - y21*x31; if ((topu > 0) || (topu <= bot)) return(0); } t = divscale24(topt,bot); *intx = x1 + mulscale24(x21,t); *inty = y1 + mulscale24(y21,t); *intz = z1 + mulscale24(z2-z1,t); return(1); } int32_t lineintersect(int32_t x1, int32_t y1, int32_t z1, int32_t x2, int32_t y2, int32_t z2, int32_t x3, int32_t y3, int32_t x4, int32_t y4, int32_t *intx, int32_t *inty, int32_t *intz) { return lintersect(x1, y1, z1, x2, y2, z2, x3, y3, x4, y4, intx, inty, intz); } // // rintersect (internal) // static inline int32_t rintersect(int32_t x1, int32_t y1, int32_t z1, int32_t vx, int32_t vy, int32_t vz, int32_t x3, int32_t y3, int32_t x4, int32_t y4, int32_t *intx, int32_t *inty, int32_t *intz) { //p1 towards p2 is a ray int32_t x34, y34, x31, y31, bot, topt, topu, t; x34 = x3-x4; y34 = y3-y4; bot = vx*y34 - vy*x34; if (bot >= 0) { if (bot == 0) return(0); x31 = x3-x1; y31 = y3-y1; topt = x31*y34 - y31*x34; if (topt < 0) return(0); topu = vx*y31 - vy*x31; if ((topu < 0) || (topu >= bot)) return(0); } else { x31 = x3-x1; y31 = y3-y1; topt = x31*y34 - y31*x34; if (topt > 0) return(0); topu = vx*y31 - vy*x31; if ((topu > 0) || (topu <= bot)) return(0); } t = divscale16(topt,bot); *intx = x1 + mulscale16(vx,t); *inty = y1 + mulscale16(vy,t); *intz = z1 + mulscale16(vz,t); return(1); } int32_t rayintersect(int32_t x1, int32_t y1, int32_t z1, int32_t vx, int32_t vy, int32_t vz, int32_t x3, int32_t y3, int32_t x4, int32_t y4, int32_t *intx, int32_t *inty, int32_t *intz) { return rintersect(x1, y1, z1, vx, vy, vz, x3, y3, x4, y4, intx, inty, intz); } // // keepaway (internal) // static inline void keepaway(int32_t *x, int32_t *y, int32_t w) { int32_t dx, dy, ox, oy, x1, y1; char first; x1 = clipit[w].x1; dx = clipit[w].x2-x1; y1 = clipit[w].y1; dy = clipit[w].y2-y1; ox = ksgn(-dy); oy = ksgn(dx); first = (klabs(dx) <= klabs(dy)); while (1) { if (dx*(*y-y1) > (*x-x1)*dy) return; if (first == 0) *x += ox; else *y += oy; first ^= 1; } } // // raytrace (internal) // static inline int32_t raytrace(int32_t x3, int32_t y3, int32_t *x4, int32_t *y4) { int32_t x1, y1, x2, y2, bot, topu, nintx, ninty, cnt, z, hitwall; int32_t x21, y21, x43, y43; hitwall = -1; for (z=clipnum-1; z>=0; z--) { x1 = clipit[z].x1; x2 = clipit[z].x2; x21 = x2-x1; y1 = clipit[z].y1; y2 = clipit[z].y2; y21 = y2-y1; topu = x21*(y3-y1) - (x3-x1)*y21; if (topu <= 0) continue; if (x21*(*y4-y1) > (*x4-x1)*y21) continue; x43 = *x4-x3; y43 = *y4-y3; if (x43*(y1-y3) > (x1-x3)*y43) continue; if (x43*(y2-y3) <= (x2-x3)*y43) continue; bot = x43*y21 - x21*y43; if (bot == 0) continue; cnt = 256; do { cnt--; if (cnt < 0) { *x4 = x3; *y4 = y3; return(z); } nintx = x3 + scale(x43,topu,bot); ninty = y3 + scale(y43,topu,bot); topu--; } while (x21*(ninty-y1) <= (nintx-x1)*y21); if (klabs(x3-nintx)+klabs(y3-ninty) < klabs(x3-*x4)+klabs(y3-*y4)) { *x4 = nintx; *y4 = ninty; hitwall = z; } } return(hitwall); } // // Exported Engine Functions // #if !defined _WIN32 && defined DEBUGGINGAIDS #include static void sighandler(int32_t sig, const siginfo_t *info, void *ctx) { const char *s; UNREFERENCED_PARAMETER(ctx); switch (sig) { case SIGFPE: switch (info->si_code) { case FPE_INTDIV: s = "FPE_INTDIV (integer divide by zero)"; break; case FPE_INTOVF: s = "FPE_INTOVF (integer overflow)"; break; case FPE_FLTDIV: s = "FPE_FLTDIV (floating-point divide by zero)"; break; case FPE_FLTOVF: s = "FPE_FLTOVF (floating-point overflow)"; break; case FPE_FLTUND: s = "FPE_FLTUND (floating-point underflow)"; break; case FPE_FLTRES: s = "FPE_FLTRES (floating-point inexact result)"; break; case FPE_FLTINV: s = "FPE_FLTINV (floating-point invalid operation)"; break; case FPE_FLTSUB: s = "FPE_FLTSUB (floating-point subscript out of range)"; break; default: s = "?! (unknown)"; break; } fprintf(stderr, "Caught SIGFPE at address %p, code %s. Aborting.\n", info->si_addr, s); break; default: break; } abort(); } #endif // // preinitengine // static int32_t preinitcalled = 0; #define DYNALLOC_ARRAYS #ifndef DYNALLOC_ARRAYS static spriteext_t spriteext_s[MAXSPRITES+MAXUNIQHUDID]; static spritesmooth_t spritesmooth_s[MAXSPRITES+MAXUNIQHUDID]; static sectortype sector_s[MAXSECTORS]; static walltype wall_s[MAXWALLS]; static spritetype sprite_s[MAXSPRITES]; static spritetype tsprite_s[MAXSPRITESONSCREEN]; #else void *blockptr = NULL; #endif int32_t preinitengine(void) { char *e; if (initsystem()) exit(9); makeasmwriteable(); #ifdef DYNALLOC_ARRAYS { size_t i, size = 0; // allocate everything at once... why not? entries can just be added to this table // to allocate future arrays without further intervention struct { void **ptr; size_t size; } dynarray[] = { { (void **) §or, sizeof(sectortype) *MAXSECTORS }, { (void **) &wall, sizeof(walltype) *(MAXWALLS+4) }, // +4: editor quirks { (void **) &sprite, sizeof(spritetype) *MAXSPRITES }, { (void **) &tsprite, sizeof(spritetype) *MAXSPRITESONSCREEN }, { (void **) &spriteext, sizeof(spriteext_t) *(MAXSPRITES+MAXUNIQHUDID) }, { (void **) &spritesmooth, sizeof(spritesmooth_t) *(MAXSPRITES+MAXUNIQHUDID) }, { (void **) &state_compress, sizeof(qlz_state_compress) }, { (void **) &state_decompress, sizeof(qlz_state_decompress) } }; for (i=0; i<(signed)(sizeof(dynarray)/sizeof(dynarray[0])); i++) size += dynarray[i].size; if ((blockptr = Bcalloc(1, size)) == NULL) return 1; size = 0; for (i=0; i<(signed)(sizeof(dynarray)/sizeof(dynarray[0])); i++) { *dynarray[i].ptr = (int8_t *)blockptr + size; size += dynarray[i].size; } } #else sector = sector_s; wall = wall_s; sprite = sprite_s; tsprite = tsprite_s; spriteext = spriteext_s; spritesmooth = spritesmooth_s; state_compress = (qlz_state_compress *) Bmalloc(sizeof(qlz_state_compress) + sizeof(qlz_state_decompress)); state_decompress = (qlz_state_decompress *)((int8_t *)(state_compress) + sizeof(qlz_state_compress)); #endif if ((e = Bgetenv("BUILD_NOP6")) != NULL) if (!Bstrcasecmp(e, "TRUE")) { Bprintf("Disabling P6 optimizations.\n"); dommxoverlay = 0; } if (dommxoverlay) mmxoverlay(); validmodecnt = 0; getvalidmodes(); initcrc32table(); clipmapinfo_init(); preinitcalled = 1; return 0; } // // initengine // int32_t initengine(void) { int32_t i, j; #if !defined _WIN32 && defined DEBUGGINGAIDS struct sigaction sigact, oldact; memset(&sigact, 0, sizeof(sigact)); sigact.sa_sigaction = (void *)sighandler; sigact.sa_flags = SA_SIGINFO; sigaction(SIGFPE, &sigact, &oldact); #endif if (!preinitcalled) { i = preinitengine(); if (i) return i; } if (loadtables()) return 1; 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>2,65536L); #endif paletteloaded = 0; searchit = 0; searchstat = -1; for (i=0; i>5),0L); clearbuf(&show2dsprite[0],(int32_t)((MAXSPRITES+3)>>5),0L); clearbuf(&show2dwall[0],(int32_t)((MAXWALLS+3)>>5),0L); automapping = 0; pointhighlight = -1; linehighlight = -1; highlightcnt = 0; totalclock = 0; visibility = 512; parallaxvisibility = 512; captureformat = 0; loadpalette(); #if defined(POLYMOST) && defined(USE_OPENGL) if (!hicfirstinit) hicinit(); if (!mdinited) mdinit(); #endif return 0; } // // uninitengine // void uninitengine(void) { int32_t i; //OSD_Printf("cacheresets = %d, cacheinvalidates = %d\n", cacheresets, cacheinvalidates); #if defined(POLYMOST) && defined(USE_OPENGL) polymost_glreset(); hicinit(); freeallmodels(); #ifdef POLYMER polymer_uninit(); #endif /* if (cachefilehandle > -1) Bclose(cachefilehandle); if (cacheindexptr != NULL) Bfclose(cacheindexptr); */ #endif if (artfil != -1) kclose(artfil); i=(sizeof(artptrs)/sizeof(intptr_t))-1; // this leaves a bunch of invalid pointers in waloff... fixme? for (; i>=0; i--) { if (artptrs[i]) { Bfree(artptrs[i]); artptrs[i] = NULL; } } if (transluc != NULL) { Bfree(transluc); transluc = NULL; } if (pic != NULL) { Bfree(pic); pic = NULL; } if (lookups != NULL) { if (lookupsalloctype == 0) Bfree((void *)lookups); //if (lookupsalloctype == 1) suckcache(lookups); //Cache already gone lookups = NULL; } for (i=0; i>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 ((xyaspect != oxyaspect) || (xdimen != oxdimen) || (viewingrange != oviewingrange)) dosetaspect(); //clearbufbyte(&gotsector[0],(int32_t)((numsectors+7)>>3),0L); Bmemset(&gotsector[0],0,(int32_t)((numsectors+7)>>3)); shortptr1 = (int16_t *)&startumost[windowx1]; shortptr2 = (int16_t *)&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; #ifdef POLYMOST # ifdef POLYMER if (rendmode == 4) { polymer_glinit(); polymer_drawrooms(daposx, daposy, daposz, daang, dahoriz, dacursectnum); bglDisable(GL_CULL_FACE); gloy1 = 0; return; } # endif //============================================================================= //POLYMOST BEGINS polymost_drawrooms(); if (rendmode) return; #endif //============================================================================= //POLYMOST ENDS begindrawing(); //{{{ //frameoffset = frameplace + viewoffset; frameoffset = frameplace + windowy1*bytesperline + windowx1; //if (smostwallcnt < 0) // if (getkensmessagecrc(FP_OFF(kensmessage)) != 0x56c764d4) // { /* setvmode(0x3);*/ OSD_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; // PK 20110123: I'm not sure what the line above is supposed to do, but 'i' // *can* be negative, so let's just quit here in that case... if (globalcursectnum<0) { enddrawing(); return; } } 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]; } for (i=0; i 0) && (numhits > 0)) { clearbuf(&tempbuf[0],(int32_t)((numbunches+3)>>2),0L); tempbuf[0] = 1; closest = 0; //Almost works, but not quite :( for (i=1; i=0; z=p2[z]) show2dwall[thewall[z]>>3] |= pow2char[thewall[z]&7]; } numbunches--; bunchfirst[closest] = bunchfirst[numbunches]; bunchlast[closest] = bunchlast[numbunches]; } enddrawing(); //}}} } // UTILITY TYPES AND FUNCTIONS FOR DRAWMASKS OCCLUSION TREE // typedef struct s_maskleaf // { // int32_t index; // _point2d p1, p2; // _equation maskeq, p1eq, p2eq; // struct s_maskleaf* branch[MAXWALLSB]; // int32_t drawing; // } _maskleaf; // // _maskleaf maskleaves[MAXWALLSB]; // returns equation of a line given two points static inline _equation equation(float x1, float y1, float x2, float y2) { _equation ret; if ((x2 - x1) != 0) { ret.a = (float)(y2 - y1)/(float)(x2 - x1); ret.b = -1; ret.c = (y1 - (ret.a * x1)); } else // vertical { ret.a = 1; ret.b = 0; ret.c = -x1; } return (ret); } int32_t wallvisible(int32_t x, int32_t y, int16_t wallnum) { // 1 if wall is in front of player 0 otherwise int32_t a1, a2; walltype *w1, *w2; w1 = &wall[wallnum]; w2 = &wall[w1->point2]; a1 = getangle(w1->x - x, w1->y - y); a2 = getangle(w2->x - x, w2->y - y); //if ((wallnum == 23) || (wallnum == 9)) // OSD_Printf("Wall %d : %d - sector %d - x %d - y %d.\n", wallnum, (a2 + (2048 - a1)) & 2047, globalcursectnum, globalposx, globalposy); if (((a2 + (2048 - a1)) & 2047) <= 1024) return (1); return (0); } /* // returns the intersection point between two lines _point2d intersection(_equation eq1, _equation eq2) { _point2d ret; float det; det = (float)(1) / (eq1.a*eq2.b - eq2.a*eq1.b); ret.x = ((eq1.b*eq2.c - eq2.b*eq1.c) * det); ret.y = ((eq2.a*eq1.c - eq1.a*eq2.c) * det); return (ret); } // check if a point that's on the line is within the segment boundaries int32_t pointonmask(_point2d point, _maskleaf* wall) { if ((min(wall->p1.x, wall->p2.x) <= point.x) && (point.x <= max(wall->p1.x, wall->p2.x)) && (min(wall->p1.y, wall->p2.y) <= point.y) && (point.y <= max(wall->p1.y, wall->p2.y))) return (1); return (0); } // returns 1 if wall2 is hidden by wall1 int32_t wallobstructswall(_maskleaf* wall1, _maskleaf* wall2) { _point2d cross; cross = intersection(wall2->p1eq, wall1->maskeq); if (pointonmask(cross, wall1)) return (1); cross = intersection(wall2->p2eq, wall1->maskeq); if (pointonmask(cross, wall1)) return (1); cross = intersection(wall1->p1eq, wall2->maskeq); if (pointonmask(cross, wall2)) return (1); cross = intersection(wall1->p2eq, wall2->maskeq); if (pointonmask(cross, wall2)) return (1); return (0); } // recursive mask drawing function static inline void drawmaskleaf(_maskleaf* wall) { int32_t i; wall->drawing = 1; i = 0; while (wall->branch[i] != NULL) { if (wall->branch[i]->drawing == 0) { //OSD_Printf("Drawing parent of %i : mask %i\n", wall->index, wall->branch[i]->index); drawmaskleaf(wall->branch[i]); } i++; } //OSD_Printf("Drawing mask %i\n", wall->index); drawmaskwall(wall->index); } */ static inline int32_t sameside(_equation *eq, _point2d *p1, _point2d *p2) { float sign1, sign2; sign1 = eq->a * p1->x + eq->b * p1->y + eq->c; sign2 = eq->a * p2->x + eq->b * p2->y + eq->c; sign1 = sign1 * sign2; if (sign1 > 0) { //OSD_Printf("SAME SIDE !\n"); return (1); } //OSD_Printf("OPPOSITE SIDE !\n"); return (0); } // // drawmasks // void drawmasks(void) { int32_t i, j, k, l, gap, xs, ys, xp, yp, yoff, yspan; // PLAG: sorting stuff _equation maskeq, p1eq, p2eq; _point2d dot, dot2, middle, pos, spr; #ifdef POLYMER if ((rendmode == 4) && 0) { polymer_drawmasks(); return; } #endif 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); if (mulscale24(labs(xp+yp),xdimen) >= yp) goto killsprite; spritesx[i] = scale(xp+yp,xdimen<<7,yp); } else if ((tspriteptr[i]->cstat&48) == 0) { killsprite: spritesortcnt--; //Delete face sprite if on wrong side! if (i == spritesortcnt) continue; 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=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; kz; if ((tspriteptr[k]->cstat&48) != 32) { yoff = (int32_t)((int8_t)((picanm[tspriteptr[k]->picnum]>>16)&255))+((int32_t)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; kstatnum < tspriteptr[l]->statnum) { swaplong(&tspriteptr[k],&tspriteptr[l]); swaplong(&spritesx[k],&spritesx[l]); swaplong(&spritesy[k],&spritesy[l]); } } i = j; } } begindrawing(); //{{{ /*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); }*/ { #if defined(USE_OPENGL) && defined(POLYMOST) curpolygonoffset = 0; cullcheckcnt = 0; #endif pos.x = (float)globalposx; pos.y = (float)globalposy; while (maskwallcnt) { maskwallcnt--; #if defined(USE_OPENGL) && defined(POLYMER) if (rendmode == 4) { dot.x = (float)wall[maskwall[maskwallcnt]].x; dot.y = (float)wall[maskwall[maskwallcnt]].y; dot2.x = (float)wall[wall[maskwall[maskwallcnt]].point2].x; dot2.y = (float)wall[wall[maskwall[maskwallcnt]].point2].y; } else #endif { dot.x = (float)wall[thewall[maskwall[maskwallcnt]]].x; dot.y = (float)wall[thewall[maskwall[maskwallcnt]]].y; dot2.x = (float)wall[wall[thewall[maskwall[maskwallcnt]]].point2].x; dot2.y = (float)wall[wall[thewall[maskwall[maskwallcnt]]].point2].y; } maskeq = equation(dot.x, dot.y, dot2.x, dot2.y); p1eq = equation(pos.x, pos.y, dot.x, dot.y); p2eq = equation(pos.x, pos.y, dot2.x, dot2.y); middle.x = (dot.x + dot2.x) / 2; middle.y = (dot.y + dot2.y) / 2; i = spritesortcnt; while (i) { i--; if (tspriteptr[i] != NULL) { spr.x = (float)tspriteptr[i]->x; spr.y = (float)tspriteptr[i]->y; if ((sameside(&maskeq, &spr, &pos) == 0) && sameside(&p1eq, &middle, &spr) && sameside(&p2eq, &middle, &spr)) { drawsprite(i); tspriteptr[i] = NULL; } } } drawmaskwall(maskwallcnt); } while (spritesortcnt) { spritesortcnt--; if (tspriteptr[spritesortcnt] != NULL) drawsprite(spritesortcnt); } #if defined(USE_OPENGL) && defined(POLYMOST) if (totalclock < lastcullcheck - CULL_DELAY) lastcullcheck = totalclock; if (totalclock >= lastcullcheck + CULL_DELAY) lastcullcheck = (totalclock + CULL_DELAY); #endif } indrawroomsandmasks = 0; enddrawing(); //}}} } // // drawmapview // void drawmapview(int32_t dax, int32_t day, int32_t zoome, int16_t ang) { walltype *wal; sectortype *sec; spritetype *spr; int32_t tilenum, xoff, yoff, i, j, k, l, cosang, sinang, xspan, yspan; int32_t xrepeat, yrepeat, x, y, x1, y1, x2, y2, x3, y3, x4, y4, bakx1, baky1; int32_t s, w, ox, oy, startwall, cx1, cy1, cx2, cy2; int32_t bakgxvect, bakgyvect, sortnum, gap, npoints; int32_t xvect, yvect, xvect2, yvect2, daslope; int32_t oydim=ydim; int32_t oyxaspect=yxaspect, oviewingrange=viewingrange; ydim = (int32_t)((double)xdim * 0.625f); setaspect(65536L,(int32_t)divscale16(ydim*320L,xdim*200L)); ydim = oydim; beforedrawrooms = 0; clearbuf(&gotsector[0],(int32_t)((numsectors+31)>>5),0L); cx1 = (windowx1<<12); cy1 = (windowy1<<12); cx2 = ((windowx2+1)<<12)-1; cy2 = ((windowy2+1)<<12)-1; zoome <<= 8; bakgxvect = divscale28(sintable[(1536-ang)&2047],zoome); bakgyvect = divscale28(sintable[(2048-ang)&2047],zoome); xvect = mulscale8(sintable[(2048-ang)&2047],zoome); yvect = mulscale8(sintable[(1536-ang)&2047],zoome); xvect2 = mulscale16(xvect,yxaspect); yvect2 = mulscale16(yvect,yxaspect); sortnum = 0; begindrawing(); //{{{ for (s=0,sec=§or[s]; s>3]&pow2char[s&7]) { npoints = 0; i = 0; startwall = sec->wallptr; #if 0 for (w=sec->wallnum,wal=&wall[startwall]; w>0; w--,wal++) { ox = wal->x - dax; oy = wal->y - day; x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11); y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11); i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y); rx1[npoints] = x; ry1[npoints] = y; xb1[npoints] = wal->point2 - startwall; npoints++; } #else j = startwall; l = 0; for (w=sec->wallnum,wal=&wall[startwall]; w>0; w--,wal++,j++) { k = lastwall(j); if ((k > j) && (npoints > 0)) { xb1[npoints-1] = l; l = npoints; } //overwrite point2 //wall[k].x wal->x wall[wal->point2].x //wall[k].y wal->y wall[wal->point2].y if (!dmulscale1(wal->x-wall[k].x,wall[wal->point2].y-wal->y,-(wal->y-wall[k].y),wall[wal->point2].x-wal->x)) continue; ox = wal->x - dax; oy = wal->y - day; x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11); y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11); i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y); rx1[npoints] = x; ry1[npoints] = y; xb1[npoints] = npoints+1; npoints++; } if (npoints > 0) xb1[npoints-1] = l; //overwrite point2 #endif if ((i&0xf0) != 0xf0) continue; bakx1 = rx1[0]; baky1 = mulscale16(ry1[0]-(ydim<<11),xyaspect)+(ydim<<11); if (i&0x0f) { npoints = clippoly(npoints,i); if (npoints < 3) continue; } //Collect floor sprites to draw for (i=headspritesect[s]; i>=0; i=nextspritesect[i]) if ((sprite[i].cstat&48) == 32) { if ((sprite[i].cstat&(64+8)) == (64+8)) continue; tsprite[sortnum++].owner = i; } gotsector[s>>3] |= pow2char[s&7]; globalorientation = (int32_t)sec->floorstat; if ((globalorientation&1) != 0) continue; globalpal = sec->floorpal; if (palookup[sec->floorpal] != globalpalwritten) { globalpalwritten = palookup[sec->floorpal]; if (!globalpalwritten) globalpalwritten = palookup[0]; // JBF: fixes null-pointer crash setpalookupaddress(globalpalwritten); } globalpicnum = sec->floorpicnum; if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0; setgotpic(globalpicnum); if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) continue; if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs((int16_t)globalpicnum,s); if (waloff[globalpicnum] == 0) loadtile(globalpicnum); globalbufplc = waloff[globalpicnum]; globalshade = max(min(sec->floorshade,numpalookups-1),0); globvis = globalhisibility; if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16))); globalpolytype = 0; if ((globalorientation&64) == 0) { globalposx = dax; globalx1 = bakgxvect; globaly1 = bakgyvect; globalposy = day; globalx2 = bakgxvect; globaly2 = bakgyvect; } else { ox = wall[wall[startwall].point2].x - wall[startwall].x; oy = wall[wall[startwall].point2].y - wall[startwall].y; i = nsqrtasm(ox*ox+oy*oy); if (i == 0) continue; i = 1048576/i; globalx1 = mulscale10(dmulscale10(ox,bakgxvect,oy,bakgyvect),i); globaly1 = mulscale10(dmulscale10(ox,bakgyvect,-oy,bakgxvect),i); ox = (bakx1>>4)-(xdim<<7); oy = (baky1>>4)-(ydim<<7); globalposx = dmulscale28(-oy,globalx1,-ox,globaly1); globalposy = dmulscale28(-ox,globalx1,oy,globaly1); globalx2 = -globalx1; globaly2 = -globaly1; daslope = sector[s].floorheinum; i = nsqrtasm(daslope*daslope+16777216); globalposy = mulscale12(globalposy,i); globalx2 = mulscale12(globalx2,i); globaly2 = mulscale12(globaly2,i); } globalxshift = (8-(picsiz[globalpicnum]&15)); globalyshift = (8-(picsiz[globalpicnum]>>4)); if (globalorientation&8) {globalxshift++; globalyshift++; } sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc); if ((globalorientation&0x4) > 0) { i = globalposx; globalposx = -globalposy; globalposy = -i; i = globalx2; globalx2 = globaly1; globaly1 = i; i = globalx1; globalx1 = -globaly2; globaly2 = -i; } if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalposx = -globalposx; if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalposy = -globalposy; asm1 = (globaly1<floorxpanning)<<24); globalposy = (globalposy<<(20+globalyshift))-(((int32_t)sec->floorypanning)<<24); fillpolygon(npoints); } //Sort sprite list gap = 1; while (gap < sortnum) gap = (gap<<1)+1; for (gap>>=1; gap>0; gap>>=1) for (i=0; i=0; j-=gap) { if (sprite[tsprite[j].owner].z <= sprite[tsprite[j+gap].owner].z) break; swapshort(&tsprite[j].owner,&tsprite[j+gap].owner); } for (s=sortnum-1; s>=0; s--) { spr = &sprite[tsprite[s].owner]; if ((spr->cstat&48) == 32) { npoints = 0; tilenum = spr->picnum; xoff = (int32_t)((int8_t)((picanm[tilenum]>>8)&255))+((int32_t)spr->xoffset); yoff = (int32_t)((int8_t)((picanm[tilenum]>>16)&255))+((int32_t)spr->yoffset); if ((spr->cstat&4) > 0) xoff = -xoff; if ((spr->cstat&8) > 0) yoff = -yoff; k = spr->ang; cosang = sintable[(k+512)&2047]; sinang = sintable[k]; xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat; yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat; ox = ((xspan>>1)+xoff)*xrepeat; oy = ((yspan>>1)+yoff)*yrepeat; x1 = spr->x + mulscale(sinang,ox,16) + mulscale(cosang,oy,16); y1 = spr->y + mulscale(sinang,oy,16) - mulscale(cosang,ox,16); l = xspan*xrepeat; x2 = x1 - mulscale(sinang,l,16); y2 = y1 + mulscale(cosang,l,16); l = yspan*yrepeat; k = -mulscale(cosang,l,16); x3 = x2+k; x4 = x1+k; k = -mulscale(sinang,l,16); y3 = y2+k; y4 = y1+k; xb1[0] = 1; xb1[1] = 2; xb1[2] = 3; xb1[3] = 0; npoints = 4; i = 0; ox = x1 - dax; oy = y1 - day; x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11); y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11); i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y); rx1[0] = x; ry1[0] = y; ox = x2 - dax; oy = y2 - day; x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11); y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11); i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y); rx1[1] = x; ry1[1] = y; ox = x3 - dax; oy = y3 - day; x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11); y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11); i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y); rx1[2] = x; ry1[2] = y; x = rx1[0]+rx1[2]-rx1[1]; y = ry1[0]+ry1[2]-ry1[1]; i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y); rx1[3] = x; ry1[3] = y; if ((i&0xf0) != 0xf0) continue; bakx1 = rx1[0]; baky1 = mulscale16(ry1[0]-(ydim<<11),xyaspect)+(ydim<<11); if (i&0x0f) { npoints = clippoly(npoints,i); if (npoints < 3) continue; } globalpicnum = spr->picnum; globalpal = spr->pal; // GL needs this, software doesn't if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0; setgotpic(globalpicnum); if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) continue; if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs((int16_t)globalpicnum,s); if (waloff[globalpicnum] == 0) loadtile(globalpicnum); globalbufplc = waloff[globalpicnum]; if ((sector[spr->sectnum].ceilingstat&1) > 0) globalshade = ((int32_t)sector[spr->sectnum].ceilingshade); else globalshade = ((int32_t)sector[spr->sectnum].floorshade); globalshade = max(min(globalshade+spr->shade+6,numpalookups-1),0); asm3 = FP_OFF(palookup[spr->pal]+(globalshade<<8)); globvis = globalhisibility; if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16))); globalpolytype = ((spr->cstat&2)>>1)+1; //relative alignment stuff ox = x2-x1; oy = y2-y1; i = ox*ox+oy*oy; if (i == 0) continue; i = (65536*16384)/i; globalx1 = mulscale10(dmulscale10(ox,bakgxvect,oy,bakgyvect),i); globaly1 = mulscale10(dmulscale10(ox,bakgyvect,-oy,bakgxvect),i); ox = y1-y4; oy = x4-x1; i = ox*ox+oy*oy; if (i == 0) continue; i = (65536*16384)/i; globalx2 = mulscale10(dmulscale10(ox,bakgxvect,oy,bakgyvect),i); globaly2 = mulscale10(dmulscale10(ox,bakgyvect,-oy,bakgxvect),i); ox = picsiz[globalpicnum]; oy = ((ox>>4)&15); ox &= 15; if (pow2long[ox] != xspan) { ox++; globalx1 = mulscale(globalx1,xspan,ox); globaly1 = mulscale(globaly1,xspan,ox); } bakx1 = (bakx1>>4)-(xdim<<7); baky1 = (baky1>>4)-(ydim<<7); globalposx = dmulscale28(-baky1,globalx1,-bakx1,globaly1); globalposy = dmulscale28(bakx1,globalx2,-baky1,globaly2); if ((spr->cstat&2) == 0) msethlineshift(ox,oy); else { if (spr->cstat&512) settransreverse(); else settransnormal(); tsethlineshift(ox,oy); } if ((spr->cstat&0x4) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalposx = -globalposx; asm1 = (globaly1<<2); globalx1 <<= 2; globalposx <<= (20+2); asm2 = (globalx2<<2); globaly2 <<= 2; globalposy <<= (20+2); globalorientation = ((spr->cstat&2)<<7) | ((spr->cstat&512)>>2); // so polymost can get the translucency. ignored in software mode. fillpolygon(npoints); } } enddrawing(); //}}} if (r_usenewaspect) setaspect(oviewingrange, oyxaspect); else setaspect(65536L,(int32_t)divscale16(ydim*320L,xdim*200L)); } // // loadboard // // flags: 1, 2: former parameter "fromwhere" // 4: don't call polymer_loadboard int32_t loadboard(char *filename, char flags, int32_t *daposx, int32_t *daposy, int32_t *daposz, int16_t *daang, int16_t *dacursectnum) { int16_t fil, i, numsprites, dq[MAXSPRITES], dnum = 0; char myflags = flags&(~3); flags &= 3; i = strlen(filename)-1; if (filename[i] == 255) { filename[i] = 0; flags = 1; } // JBF 20040119: "compatibility" if ((fil = kopen4load(filename,flags)) == -1) { mapversion = 7L; return(-1); } kread(fil,&mapversion,4); mapversion = B_LITTLE32(mapversion); if (mapversion != 7L && mapversion != 8L) { kclose(fil); return(-2); } /* // Enable this for doing map checksum tests clearbufbyte(&wall, sizeof(wall), 0); clearbufbyte(§or, sizeof(sector), 0); clearbufbyte(&sprite, sizeof(sprite), 0); */ #ifdef NEDMALLOC nedtrimthreadcache(0, 0); #endif initspritelists(); #define MYMAXSECTORS (mapversion==7l?MAXSECTORSV7:MAXSECTORSV8) #define MYMAXWALLS (mapversion==7l?MAXWALLSV7:MAXWALLSV8) #define MYMAXSPRITES (mapversion==7l?MAXSPRITESV7:MAXSPRITESV8) clearbuf(&show2dsector[0],(int32_t)((MAXSECTORS+3)>>5),0L); clearbuf(&show2dsprite[0],(int32_t)((MAXSPRITES+3)>>5),0L); clearbuf(&show2dwall[0],(int32_t)((MAXWALLS+3)>>5),0L); kread(fil,daposx,4); *daposx = B_LITTLE32(*daposx); kread(fil,daposy,4); *daposy = B_LITTLE32(*daposy); kread(fil,daposz,4); *daposz = B_LITTLE32(*daposz); kread(fil,daang,2); *daang = B_LITTLE16(*daang); kread(fil,dacursectnum,2); *dacursectnum = B_LITTLE16(*dacursectnum); kread(fil,&numsectors,2); numsectors = B_LITTLE16(numsectors); if (numsectors > MYMAXSECTORS) { kclose(fil); return(-1); } kread(fil,§or[0],sizeof(sectortype)*numsectors); for (i=numsectors-1; i>=0; i--) { sector[i].wallptr = B_LITTLE16(sector[i].wallptr); sector[i].wallnum = B_LITTLE16(sector[i].wallnum); sector[i].ceilingz = B_LITTLE32(sector[i].ceilingz); sector[i].floorz = B_LITTLE32(sector[i].floorz); sector[i].ceilingstat = B_LITTLE16(sector[i].ceilingstat); sector[i].floorstat = B_LITTLE16(sector[i].floorstat); sector[i].ceilingpicnum = B_LITTLE16(sector[i].ceilingpicnum); sector[i].ceilingheinum = B_LITTLE16(sector[i].ceilingheinum); sector[i].floorpicnum = B_LITTLE16(sector[i].floorpicnum); sector[i].floorheinum = B_LITTLE16(sector[i].floorheinum); sector[i].lotag = B_LITTLE16(sector[i].lotag); sector[i].hitag = B_LITTLE16(sector[i].hitag); sector[i].extra = B_LITTLE16(sector[i].extra); } kread(fil,&numwalls,2); numwalls = B_LITTLE16(numwalls); if (numwalls > MYMAXWALLS) { kclose(fil); return(-1); } kread(fil,&wall[0],sizeof(walltype)*numwalls); for (i=numwalls-1; i>=0; i--) { wall[i].x = B_LITTLE32(wall[i].x); wall[i].y = B_LITTLE32(wall[i].y); wall[i].point2 = B_LITTLE16(wall[i].point2); wall[i].nextwall = B_LITTLE16(wall[i].nextwall); wall[i].nextsector = B_LITTLE16(wall[i].nextsector); wall[i].cstat = B_LITTLE16(wall[i].cstat); wall[i].picnum = B_LITTLE16(wall[i].picnum); wall[i].overpicnum = B_LITTLE16(wall[i].overpicnum); wall[i].lotag = B_LITTLE16(wall[i].lotag); wall[i].hitag = B_LITTLE16(wall[i].hitag); wall[i].extra = B_LITTLE16(wall[i].extra); } kread(fil,&numsprites,2); numsprites = B_LITTLE16(numsprites); if (numsprites > MYMAXSPRITES) { kclose(fil); return(-1); } kread(fil,&sprite[0],sizeof(spritetype)*numsprites); for (i=numsprites-1; i>=0; i--) { sprite[i].x = B_LITTLE32(sprite[i].x); sprite[i].y = B_LITTLE32(sprite[i].y); sprite[i].z = B_LITTLE32(sprite[i].z); sprite[i].cstat = B_LITTLE16(sprite[i].cstat); sprite[i].picnum = B_LITTLE16(sprite[i].picnum); sprite[i].sectnum = B_LITTLE16(sprite[i].sectnum); sprite[i].statnum = B_LITTLE16(sprite[i].statnum); sprite[i].ang = B_LITTLE16(sprite[i].ang); sprite[i].owner = B_LITTLE16(sprite[i].owner); sprite[i].xvel = B_LITTLE16(sprite[i].xvel); sprite[i].yvel = B_LITTLE16(sprite[i].yvel); sprite[i].zvel = B_LITTLE16(sprite[i].zvel); sprite[i].lotag = B_LITTLE16(sprite[i].lotag); sprite[i].hitag = B_LITTLE16(sprite[i].hitag); sprite[i].extra = B_LITTLE16(sprite[i].extra); if (sprite[i].sectnum<0||sprite[i].sectnum>=MYMAXSECTORS) { initprintf(OSD_ERROR "Map error: sprite #%d(%d,%d) with illegal sector(%d). Map is corrupt!\n",i,sprite[i].x,sprite[i].y,sprite[i].sectnum); updatesector(sprite[i].x, sprite[i].y, &sprite[i].sectnum); } if (sprite[i].picnum<0||sprite[i].picnum>=MAXTILES) { initprintf(OSD_ERROR "Map error: sprite #%d(%d,%d) with illegal picnum(%d). Map is corrupt!\n",i,sprite[i].x,sprite[i].y,sprite[i].picnum); dq[dnum++] = i; sprite[i].picnum = 0; } } for (i=0; i= 0; ii--) { for (jj=32; jj >= 0; jj--) { updatesector(sprite[k].x+ii-16, sprite[k].y+jj-16, §); if (sect != -1) break; } if (sect != -1) break; } / * fuck it, the sprite is clearly not legitimately in any sector at this point so let's queue it up for deletion * / if (sect == -1) dq[dnum++] = k; } */ } /* while (dnum--) { initprintf(OSD_ERROR "Map error: removing sprite #%d(%d,%d) in null space. Map is corrupt!\n",dq[dnum],sprite[dq[dnum]].x,sprite[dq[dnum]].y); deletesprite(dq[dnum]); } */ //Must be after loading sectors, etc! updatesector(*daposx,*daposy,dacursectnum); kclose(fil); if (!quickloadboard) { Bmemset(spriteext, 0, sizeof(spriteext_t) * MAXSPRITES); #if defined(POLYMOST) && defined(USE_OPENGL) Bmemset(spritesmooth, 0, sizeof(spritesmooth_t) *(MAXSPRITES+MAXUNIQHUDID)); // polymost_cachesync(); # ifdef POLYMER if (rendmode == 4) { if ((myflags&4)==0) polymer_loadboard(); } #endif #endif } guniqhudid = 0; startposx = *daposx; startposy = *daposy; startposz = *daposz; startang = *daang; startsectnum = *dacursectnum; return(0); } // // loadboardv5/6 // #pragma pack(push,1) struct sectortypev5 { uint16_t wallptr, wallnum; int16_t ceilingpicnum, floorpicnum; int16_t ceilingheinum, floorheinum; int32_t ceilingz, floorz; int8_t ceilingshade, floorshade; char ceilingxpanning, floorxpanning; char ceilingypanning, floorypanning; char ceilingstat, floorstat; char ceilingpal, floorpal; char visibility; int16_t lotag, hitag; int16_t extra; }; struct walltypev5 { int32_t x, y; int16_t point2; int16_t picnum, overpicnum; int8_t shade; int16_t cstat; char xrepeat, yrepeat, xpanning, ypanning; int16_t nextsector1, nextwall1; int16_t nextsector2, nextwall2; int16_t lotag, hitag; int16_t extra; }; struct spritetypev5 { int32_t x, y, z; char cstat; int8_t shade; char xrepeat, yrepeat; int16_t picnum, ang, xvel, yvel, zvel, owner; int16_t sectnum, statnum; int16_t lotag, hitag; int16_t extra; }; struct sectortypev6 { uint16_t wallptr, wallnum; int16_t ceilingpicnum, floorpicnum; int16_t ceilingheinum, floorheinum; int32_t ceilingz, floorz; int8_t ceilingshade, floorshade; char ceilingxpanning, floorxpanning; char ceilingypanning, floorypanning; char ceilingstat, floorstat; char ceilingpal, floorpal; char visibility; int16_t lotag, hitag, extra; }; struct walltypev6 { int32_t x, y; int16_t point2, nextsector, nextwall; int16_t picnum, overpicnum; int8_t shade; char pal; int16_t cstat; char xrepeat, yrepeat, xpanning, ypanning; int16_t lotag, hitag, extra; }; struct spritetypev6 { int32_t x, y, z; int16_t cstat; int8_t shade; char pal, clipdist; char xrepeat, yrepeat; int8_t xoffset, yoffset; int16_t picnum, ang, xvel, yvel, zvel, owner; int16_t sectnum, statnum; int16_t lotag, hitag, extra; }; #pragma pack(pop) static int16_t sectorofwallv5(int16_t theline) { int16_t i, startwall, endwall, sucksect; sucksect = -1; for (i=0; i= startwall) && (theline <= endwall)) { sucksect = i; break; } } return(sucksect); } static void convertv5sectv6(struct sectortypev5 *from, struct sectortypev6 *to) { to->wallptr = from->wallptr; to->wallnum = from->wallnum; to->ceilingpicnum = from->ceilingpicnum; to->floorpicnum = from->floorpicnum; to->ceilingheinum = from->ceilingheinum; to->floorheinum = from->floorheinum; to->ceilingz = from->ceilingz; to->floorz = from->floorz; to->ceilingshade = from->ceilingshade; to->floorshade = from->floorshade; to->ceilingxpanning = from->ceilingxpanning; to->floorxpanning = from->floorxpanning; to->ceilingypanning = from->ceilingypanning; to->floorypanning = from->floorypanning; to->ceilingstat = from->ceilingstat; to->floorstat = from->floorstat; to->ceilingpal = from->ceilingpal; to->floorpal = from->floorpal; to->visibility = from->visibility; to->lotag = from->lotag; to->hitag = from->hitag; to->extra = from->extra; } static void convertv5wallv6(struct walltypev5 *from, struct walltypev6 *to, int32_t i) { to->x = from->x; to->y = from->y; to->point2 = from->point2; to->nextsector = from->nextsector1; to->nextwall = from->nextwall1; to->picnum = from->picnum; to->overpicnum = from->overpicnum; to->shade = from->shade; to->pal = sector[sectorofwallv5((int16_t)i)].floorpal; to->cstat = from->cstat; to->xrepeat = from->xrepeat; to->yrepeat = from->yrepeat; to->xpanning = from->xpanning; to->ypanning = from->ypanning; to->lotag = from->lotag; to->hitag = from->hitag; to->extra = from->extra; } static void convertv5sprv6(struct spritetypev5 *from, struct spritetypev6 *to) { int16_t j; to->x = from->x; to->y = from->y; to->z = from->z; to->cstat = from->cstat; to->shade = from->shade; j = from->sectnum; if ((sector[j].ceilingstat&1) > 0) to->pal = sector[j].ceilingpal; else to->pal = sector[j].floorpal; to->clipdist = 32; to->xrepeat = from->xrepeat; to->yrepeat = from->yrepeat; to->xoffset = 0; to->yoffset = 0; to->picnum = from->picnum; to->ang = from->ang; to->xvel = from->xvel; to->yvel = from->yvel; to->zvel = from->zvel; to->owner = from->owner; to->sectnum = from->sectnum; to->statnum = from->statnum; to->lotag = from->lotag; to->hitag = from->hitag; to->extra = from->extra; } static void convertv6sectv7(struct sectortypev6 *from, sectortype *to) { to->ceilingz = from->ceilingz; to->floorz = from->floorz; to->wallptr = from->wallptr; to->wallnum = from->wallnum; to->ceilingpicnum = from->ceilingpicnum; to->ceilingheinum = max(min(((int32_t)from->ceilingheinum)<<5,32767),-32768); if ((from->ceilingstat&2) == 0) to->ceilingheinum = 0; to->ceilingshade = from->ceilingshade; to->ceilingpal = from->ceilingpal; to->ceilingxpanning = from->ceilingxpanning; to->ceilingypanning = from->ceilingypanning; to->floorpicnum = from->floorpicnum; to->floorheinum = max(min(((int32_t)from->floorheinum)<<5,32767),-32768); if ((from->floorstat&2) == 0) to->floorheinum = 0; to->floorshade = from->floorshade; to->floorpal = from->floorpal; to->floorxpanning = from->floorxpanning; to->floorypanning = from->floorypanning; to->ceilingstat = from->ceilingstat; to->floorstat = from->floorstat; to->visibility = from->visibility; to->filler = 0; to->lotag = from->lotag; to->hitag = from->hitag; to->extra = from->extra; } static void convertv6wallv7(struct walltypev6 *from, walltype *to) { to->x = from->x; to->y = from->y; to->point2 = from->point2; to->nextwall = from->nextwall; to->nextsector = from->nextsector; to->cstat = from->cstat; to->picnum = from->picnum; to->overpicnum = from->overpicnum; to->shade = from->shade; to->pal = from->pal; to->xrepeat = from->xrepeat; to->yrepeat = from->yrepeat; to->xpanning = from->xpanning; to->ypanning = from->ypanning; to->lotag = from->lotag; to->hitag = from->hitag; to->extra = from->extra; } static void convertv6sprv7(struct spritetypev6 *from, spritetype *to) { to->x = from->x; to->y = from->y; to->z = from->z; to->cstat = from->cstat; to->picnum = from->picnum; to->shade = from->shade; to->pal = from->pal; to->clipdist = from->clipdist; to->filler = 0; to->xrepeat = from->xrepeat; to->yrepeat = from->yrepeat; to->xoffset = from->xoffset; to->yoffset = from->yoffset; to->sectnum = from->sectnum; to->statnum = from->statnum; to->ang = from->ang; to->owner = from->owner; to->xvel = from->xvel; to->yvel = from->yvel; to->zvel = from->zvel; to->lotag = from->lotag; to->hitag = from->hitag; to->extra = from->extra; } // Powerslave uses v6 // Witchaven 1 and TekWar and LameDuke use v5 int32_t loadoldboard(char *filename, char fromwhere, int32_t *daposx, int32_t *daposy, int32_t *daposz, int16_t *daang, int16_t *dacursectnum) { int16_t fil, i, numsprites; struct sectortypev5 v5sect; struct walltypev5 v5wall; struct spritetypev5 v5spr; struct sectortypev6 v6sect; struct walltypev6 v6wall; struct spritetypev6 v6spr; i = strlen(filename)-1; if (filename[i] == 255) { filename[i] = 0; fromwhere = 1; } // JBF 20040119: "compatibility" if ((fil = kopen4load(filename,fromwhere)) == -1) { mapversion = 5L; return(-1); } kread(fil,&mapversion,4); mapversion = B_LITTLE32(mapversion); if (mapversion != 5L && mapversion != 6L) { kclose(fil); return(-2); } initspritelists(); clearbuf(&show2dsector[0],(int32_t)((MAXSECTORS+3)>>5),0L); clearbuf(&show2dsprite[0],(int32_t)((MAXSPRITES+3)>>5),0L); clearbuf(&show2dwall[0],(int32_t)((MAXWALLS+3)>>5),0L); kread(fil,daposx,4); *daposx = B_LITTLE32(*daposx); kread(fil,daposy,4); *daposy = B_LITTLE32(*daposy); kread(fil,daposz,4); *daposz = B_LITTLE32(*daposz); kread(fil,daang,2); *daang = B_LITTLE16(*daang); kread(fil,dacursectnum,2); *dacursectnum = B_LITTLE16(*dacursectnum); kread(fil,&numsectors,2); numsectors = B_LITTLE16(numsectors); if (numsectors > MAXSECTORS) { kclose(fil); return(-1); } for (i=0; i MAXWALLS) { kclose(fil); return(-1); } for (i=0; i MAXSPRITES) { kclose(fil); return(-1); } for (i=0; iltextptr; if (!filename && legaltokens[i].tokenid != T_LIGHT) continue; switch (legaltokens[i].tokenid) { case T_SPRITE: // sprite if (scriptfile_getnumber(script, &whichsprite)) break; if ((unsigned)whichsprite >= (unsigned)MAXSPRITES) { // sprite number out of range initprintf("Sprite number out of range 0-%d on line %s:%d\n", MAXSPRITES-1,script->filename, scriptfile_getlinum(script,cmdtokptr)); whichsprite = -1; break; } break; case T_ANGOFF: // angoff { int32_t ang; if (scriptfile_getnumber(script, &ang)) break; if (whichsprite < 0) { // no sprite directive preceeding initprintf("Ignoring angle offset directive because of absent/invalid sprite number on line %s:%d\n", script->filename, scriptfile_getlinum(script,cmdtokptr)); break; } spriteext[whichsprite].angoff = (int16_t)ang; } break; case T_NOMODEL: // notmd if (whichsprite < 0) { // no sprite directive preceeding initprintf("Ignoring not-MD2/MD3 directive because of absent/invalid sprite number on line %s:%d\n", script->filename, scriptfile_getlinum(script,cmdtokptr)); break; } spriteext[whichsprite].flags |= SPREXT_NOTMD; break; case T_NOANIM: // nomdanim if (whichsprite < 0) { // no sprite directive preceeding initprintf("Ignoring no-MD2/MD3-anim directive because of absent/invalid sprite number on line %s:%d\n", script->filename, scriptfile_getlinum(script,cmdtokptr)); break; } spriteext[whichsprite].flags |= SPREXT_NOMDANIM; break; case T_PITCH: // pitch { int32_t pitch; if (scriptfile_getnumber(script, &pitch)) break; if (whichsprite < 0) { // no sprite directive preceeding initprintf("Ignoring pitch directive because of absent/invalid sprite number on line %s:%d\n", script->filename, scriptfile_getlinum(script,cmdtokptr)); break; } spriteext[whichsprite].pitch = (int16_t)pitch; } break; case T_ROLL: // roll { int32_t roll; if (scriptfile_getnumber(script, &roll)) break; if (whichsprite < 0) { // no sprite directive preceeding initprintf("Ignoring roll directive because of absent/invalid sprite number on line %s:%d\n", script->filename, scriptfile_getlinum(script,cmdtokptr)); break; } spriteext[whichsprite].roll = (int16_t)roll; } break; case T_MDXOFF: // mdxoff { int32_t i; if (scriptfile_getnumber(script, &i)) break; if (whichsprite < 0) { // no sprite directive preceeding initprintf("Ignoring mdxoff directive because of absent/invalid sprite number on line %s:%d\n", script->filename, scriptfile_getlinum(script,cmdtokptr)); break; } spriteext[whichsprite].xoff = i; } break; case T_MDYOFF: // mdyoff { int32_t i; if (scriptfile_getnumber(script, &i)) break; if (whichsprite < 0) { // no sprite directive preceeding initprintf("Ignoring mdyoff directive because of absent/invalid sprite number on line %s:%d\n", script->filename, scriptfile_getlinum(script,cmdtokptr)); break; } spriteext[whichsprite].yoff = i; } break; case T_MDZOFF: // mdzoff { int32_t i; if (scriptfile_getnumber(script, &i)) break; if (whichsprite < 0) { // no sprite directive preceeding initprintf("Ignoring mdzoff directive because of absent/invalid sprite number on line %s:%d\n", script->filename, scriptfile_getlinum(script,cmdtokptr)); break; } spriteext[whichsprite].zoff = i; } break; case T_AWAY1: // away1 if (whichsprite < 0) { // no sprite directive preceeding initprintf("Ignoring moving away directive because of absent/invalid sprite number on line %s:%d\n", script->filename, scriptfile_getlinum(script,cmdtokptr)); break; } spriteext[whichsprite].flags |= SPREXT_AWAY1; break; case T_AWAY2: // away2 if (whichsprite < 0) { // no sprite directive preceeding initprintf("Ignoring moving away directive because of absent/invalid sprite number on line %s:%d\n", script->filename, scriptfile_getlinum(script,cmdtokptr)); break; } spriteext[whichsprite].flags |= SPREXT_AWAY2; break; #ifdef POLYMER case T_LIGHT: // light sector x y z range r g b radius faderadius angle horiz minshade maxshade priority tilenum { int32_t value; int16_t lightid; #pragma pack(push,1) _prlight light; #pragma pack(pop) scriptfile_getnumber(script, &value); light.sector = value; scriptfile_getnumber(script, &value); light.x = value; scriptfile_getnumber(script, &value); light.y = value; scriptfile_getnumber(script, &value); light.z = value; scriptfile_getnumber(script, &value); light.range = value; scriptfile_getnumber(script, &value); light.color[0] = value; scriptfile_getnumber(script, &value); light.color[1] = value; scriptfile_getnumber(script, &value); light.color[2] = value; scriptfile_getnumber(script, &value); light.radius = value; scriptfile_getnumber(script, &value); light.faderadius = value; scriptfile_getnumber(script, &value); light.angle = value; scriptfile_getnumber(script, &value); light.horiz = value; scriptfile_getnumber(script, &value); light.minshade = value; scriptfile_getnumber(script, &value); light.maxshade = value; scriptfile_getnumber(script, &value); light.priority = value; scriptfile_getnumber(script, &value); light.tilenum = value; if (rendmode == 4) { lightid = polymer_addlight(&light); if (lightid>=0) maphacklight[maphacklightcnt++] = lightid; } break; } #endif // POLYMER default: // unrecognised token break; } } scriptfile_close(script); return 0; } #else int32_t loadmaphack(char *filename) { UNREFERENCED_PARAMETER(filename); return -1; } #endif // // saveboard // int32_t saveboard(const char *filename, int32_t *daposx, int32_t *daposy, int32_t *daposz, int16_t *daang, int16_t *dacursectnum) { int16_t fil, i, j, numsprites, ts; int32_t tl; sectortype *tsect = NULL; walltype *twall = NULL; spritetype *tspri = NULL; sectortype *sec; walltype *wal; spritetype *spri; if ((fil = Bopen(filename,BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY,BS_IREAD|BS_IWRITE)) == -1) { initprintf("Couldn't open \"%s\" for writing: %s\n", filename, strerror(errno)); return(-1); } for (j=0; jMAXSTATUS) { initprintf("Map error: sprite #%d(%d,%d) with an illegal statnum(%d)\n",j,sprite[j].x,sprite[j].y,sprite[j].statnum); changespritestat(j,0); } numsprites = 0; #if 0 for (j=0; j MAXSECTORSV7 || numwalls > MAXWALLSV7 || numsprites > MAXSPRITESV7) mapversion = 8; else mapversion = 7; tl = B_LITTLE32(mapversion); Bwrite(fil,&tl,4); tl = B_LITTLE32(*daposx); Bwrite(fil,&tl,4); tl = B_LITTLE32(*daposy); Bwrite(fil,&tl,4); tl = B_LITTLE32(*daposz); Bwrite(fil,&tl,4); ts = B_LITTLE16(*daang); Bwrite(fil,&ts,2); ts = B_LITTLE16(*dacursectnum); Bwrite(fil,&ts,2); ts = B_LITTLE16(numsectors); Bwrite(fil,&ts,2); while (1) { tsect = (sectortype *)Bmalloc(sizeof(sectortype) * numsectors); if (tsect == NULL) break; Bmemcpy(&tsect[0], §or[0], sizeof(sectortype) * numsectors); for (i=0; iwallptr = B_LITTLE16(sec->wallptr); sec->wallnum = B_LITTLE16(sec->wallnum); sec->ceilingz = B_LITTLE32(sec->ceilingz); sec->floorz = B_LITTLE32(sec->floorz); sec->ceilingstat = B_LITTLE16(sec->ceilingstat); sec->floorstat = B_LITTLE16(sec->floorstat); sec->ceilingpicnum = B_LITTLE16(sec->ceilingpicnum); sec->ceilingheinum = B_LITTLE16(sec->ceilingheinum); sec->floorpicnum = B_LITTLE16(sec->floorpicnum); sec->floorheinum = B_LITTLE16(sec->floorheinum); sec->lotag = B_LITTLE16(sec->lotag); sec->hitag = B_LITTLE16(sec->hitag); sec->extra = B_LITTLE16(sec->extra); } Bwrite(fil,&tsect[0],sizeof(sectortype) * numsectors); Bfree(tsect); ts = B_LITTLE16(numwalls); Bwrite(fil,&ts,2); twall = (walltype *)Bmalloc(sizeof(walltype) * numwalls); if (twall == NULL) break; Bmemcpy(&twall[0], &wall[0], sizeof(walltype) * numwalls); for (i=0; ix = B_LITTLE32(wal->x); wal->y = B_LITTLE32(wal->y); wal->point2 = B_LITTLE16(wal->point2); wal->nextwall = B_LITTLE16(wal->nextwall); wal->nextsector = B_LITTLE16(wal->nextsector); wal->cstat = B_LITTLE16(wal->cstat); wal->picnum = B_LITTLE16(wal->picnum); wal->overpicnum = B_LITTLE16(wal->overpicnum); wal->lotag = B_LITTLE16(wal->lotag); wal->hitag = B_LITTLE16(wal->hitag); wal->extra = B_LITTLE16(wal->extra); } Bwrite(fil,&twall[0],sizeof(walltype) * numwalls); Bfree(twall); ts = B_LITTLE16(numsprites); Bwrite(fil,&ts,2); tspri = (spritetype *)Bmalloc(sizeof(spritetype) * numsprites); if (tspri == NULL) break; spri=tspri; for (j=0; jx = B_LITTLE32(spri->x); spri->y = B_LITTLE32(spri->y); spri->z = B_LITTLE32(spri->z); spri->cstat = B_LITTLE16(spri->cstat); spri->picnum = B_LITTLE16(spri->picnum); spri->sectnum = B_LITTLE16(spri->sectnum); spri->statnum = B_LITTLE16(spri->statnum); spri->ang = B_LITTLE16(spri->ang); spri->owner = B_LITTLE16(spri->owner); spri->xvel = B_LITTLE16(spri->xvel); spri->yvel = B_LITTLE16(spri->yvel); spri->zvel = B_LITTLE16(spri->zvel); spri->lotag = B_LITTLE16(spri->lotag); spri->hitag = B_LITTLE16(spri->hitag); spri->extra = B_LITTLE16(spri->extra); spri++; } } Bwrite(fil,&tspri[0],sizeof(spritetype) * numsprites); Bfree(tspri); Bclose(fil); return(0); } Bclose(fil); if (tsect != NULL) Bfree(tsect); if (twall != NULL) Bfree(twall); if (tspri != NULL) Bfree(tspri); return(-1); } // // setgamemode // // JBF: davidoption now functions as a windowed-mode flag (0 == windowed, 1 == fullscreen) extern char videomodereset; int32_t setgamemode(char davidoption, int32_t daxdim, int32_t daydim, int32_t dabpp) { int32_t i, j; #if defined(USE_OPENGL) && defined(POLYMOST) extern char nogl; if (nogl) dabpp = 8; #endif if ((qsetmode == 200) && (videomodereset == 0) && (davidoption == fullscreen) && (xdim == daxdim) && (ydim == daydim) && (bpp == dabpp) /* #ifdef POLYMER && glrendmode != 4 #endif // POLYMER */ ) return(0); 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) // { OSD_Printf("Nice try.\n"); exit(0); } //if (checkvideomode(&daxdim, &daydim, dabpp, davidoption)<0) return (-1); //bytesperline is set in this function j = bpp; if (setvideomode(daxdim,daydim,dabpp,davidoption) < 0) return(-1); // Workaround possible bugs in the GL driver makeasmwriteable(); #if defined(POLYMOST) && defined(USE_OPENGL) if (dabpp > 8) rendmode = glrendmode; // GL renderer else if (dabpp == 8 && j > 8) rendmode = 0; // going from GL to software activates softpolymost #endif xdim = daxdim; ydim = daydim; j = ydim*4*sizeof(intptr_t); //Leave room for horizlookup&horizlookup2 if (lookups != NULL) { if (lookupsalloctype == 0) Bfree((void *)lookups); if (lookupsalloctype == 1) suckcache(lookups); lookups = NULL; } lookupsalloctype = 0; if ((lookups = (intptr_t *)Bmalloc(j<<1)) == NULL) { allocache((intptr_t *)&lookups,j<<1,&permanentlock); lookupsalloctype = 1; } horizlookup = lookups; horizlookup2 = (intptr_t *)((intptr_t)lookups+j); // FIXME_SA horizycent = ((ydim*4)>>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; setview(0L,0L,xdim-1,ydim-1); clearallviews(0L); setbrightness(curbrightness,0,0); if (searchx < 0) { searchx = halfxdimen; searchy = (ydimen>>1); } #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode >= 3) { polymost_glreset(); polymost_glinit(); } # ifdef POLYMER if (rendmode == 4) { if (!polymer_init()) rendmode = 3; } #endif #endif qsetmode = 200; return(0); } // // nextpage // void nextpage(void) { int32_t i; permfifotype *per; //char snotbuf[32]; //j = 0; k = 0; //for(i=0;i<4096;i++) // if (waloff[i] != 0) // { // sprintf(snotbuf,"%d-%d",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: %d",k); //printext256((j>>5)*40+32,(j&31)*6,31,-1,snotbuf,1); switch (qsetmode) { case 200: begindrawing(); //{{{ 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,per->uniqid); } enddrawing(); //}}} OSD_Draw(); showframe(0); begindrawing(); //{{{ 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,per->uniqid); if (per->pagesleft&127) per->pagesleft--; if (((per->pagesleft&127) == 0) && (i == permtail)) permtail = ((permtail+1)&(MAXPERMS-1)); } enddrawing(); //}}} break; case 350: case 480: break; } faketimerhandler(); if ((totalclock >= lastageclock+CACHEAGETIME) || (totalclock < lastageclock)) { lastageclock = totalclock; agecache(); } #ifdef USE_OPENGL omdtims = mdtims; mdtims = getticks(); { int32_t i; for (i=0; i>5),0L); //cachesize = min((int32_t)((Bgetsysmemsize()/100)*60),max(artsize,askedsize)); if (Bgetsysmemsize() <= (uint32_t)askedsize) cachesize = (Bgetsysmemsize()/100)*60; else cachesize = askedsize; while ((pic = Bmalloc(cachesize)) == NULL) { cachesize -= 65536L; if (cachesize < 65536) return(-1); } initcache((intptr_t) pic, cachesize); for (i=0; i 1) && (pow2long[j] > tilesizx[i])) j--; picsiz[i] = ((uint8_t)j); j = 15; while ((j > 1) && (pow2long[j] > tilesizy[i])) j--; picsiz[i] += ((uint8_t)(j<<4)); } artfil = -1; artfilnum = -1; artfilplc = 0L; return(0); } // // loadtile // void loadtile(int16_t tilenume) { int32_t i, dasiz; if ((unsigned)tilenume >= (unsigned)MAXTILES) return; if ((dasiz = tilesizx[tilenume]*tilesizy[tilenume]) <= 0) return; #ifdef WITHKPLIB if (artptrs[(i = tilefilenum[tilenume])]) // from zip { waloff[tilenume] = (intptr_t)(artptrs[i]) + tilefileoffs[tilenume]; faketimerhandler(); // OSD_Printf("loaded tile %d from zip\n", tilenume); return; } #endif 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) OSD_Printf("Tile:%d\n",tilenume); // dummy tiles for highres replacements and tilefromtexture definitions if (faketilesiz[tilenume]) { if (faketilesiz[tilenume] == -1) { walock[tilenume] = 255; // permanent tile allocache(&waloff[tilenume], dasiz, &walock[tilenume]); Bmemset((char *)waloff[tilenume],0,dasiz); } else if (faketiledata[tilenume] != NULL) { walock[tilenume] = 255; allocache(&waloff[tilenume], dasiz, &walock[tilenume]); qlz_decompress(faketiledata[tilenume], (char *)waloff[tilenume], state_decompress); Bfree(faketiledata[tilenume]); faketiledata[tilenume] = NULL; } faketimerhandler(); return; } if (waloff[tilenume] == 0) { walock[tilenume] = 199; allocache(&waloff[tilenume],dasiz,&walock[tilenume]); } if (artfilplc != tilefileoffs[tilenume]) { klseek(artfil,tilefileoffs[tilenume]-artfilplc,BSEEK_CUR); faketimerhandler(); } kread(artfil, (char *)waloff[tilenume], dasiz); faketimerhandler(); artfilplc = tilefileoffs[tilenume]+dasiz; } // // allocatepermanenttile // int32_t allocatepermanenttile(int16_t tilenume, int32_t xsiz, int32_t ysiz) { int32_t j, 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] = ((uint8_t)j); j = 15; while ((j > 1) && (pow2long[j] > ysiz)) j--; picsiz[tilenume] += ((uint8_t)(j<<4)); return(waloff[tilenume]); } // // copytilepiece // void copytilepiece(int32_t tilenume1, int32_t sx1, int32_t sy1, int32_t xsiz, int32_t ysiz, int32_t tilenume2, int32_t sx2, int32_t sy2) { char *ptr1, *ptr2, dat; int32_t 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= 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; } } } // // qloadkvx // #ifdef SUPERBUILD int32_t qloadkvx(int32_t voxindex, const char *filename) { int32_t i, fil, dasiz, lengcnt, lengtot; char *ptr; if ((fil = kopen4load(filename,0)) == -1) return -1; lengcnt = 0; lengtot = kfilelength(fil); for (i=0; i= lengtot-768) break; } kclose(fil); #if defined POLYMOST && defined USE_OPENGL if (voxmodels[voxindex]) { voxfree(voxmodels[voxindex]); voxmodels[voxindex] = NULL; } voxmodels[voxindex] = voxload(filename); #endif return 0; } #endif // // clipinsidebox // int32_t clipinsidebox(int32_t x, int32_t y, int16_t wallnum, int32_t walldist) { walltype *wal; int32_t 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 // int32_t clipinsideboxline(int32_t x, int32_t y, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t walldist) { int32_t 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); } // // inside // int32_t inside(int32_t x, int32_t y, int16_t sectnum) { walltype *wal; int32_t i, x1, y1, x2, y2; uint32_t 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); } // // ksqrt // int32_t ksqrt(int32_t num) { return(nsqrtasm(num)); } // // krecip // int32_t krecip(int32_t num) { return(krecipasm(num)); } // // setsprite // int32_t setsprite(int16_t spritenum, const vec3_t *new) { int16_t tempsectnum = sprite[spritenum].sectnum; if ((void *)new != (void *)&sprite[spritenum]) Bmemcpy(&sprite[spritenum], new, sizeof(vec3_t)); updatesector(new->x,new->y,&tempsectnum); if (tempsectnum < 0) return(-1); if (tempsectnum != sprite[spritenum].sectnum) changespritesect(spritenum,tempsectnum); return(0); } int32_t setspritez(int16_t spritenum, const vec3_t *new) { int16_t tempsectnum = sprite[spritenum].sectnum; if ((void *)new != (void *)&sprite[spritenum]) Bmemcpy(&sprite[spritenum], new, sizeof(vec3_t)); updatesectorz(new->x,new->y,new->z,&tempsectnum); if (tempsectnum < 0) return(-1); if (tempsectnum != sprite[spritenum].sectnum) changespritesect(spritenum,tempsectnum); return(0); } // // changespritesect // int32_t changespritesect(int16_t spritenum, int16_t newsectnum) { if ((newsectnum < 0) || (newsectnum > MAXSECTORS)) return(-1); if (sprite[spritenum].sectnum == newsectnum) return(0); if (sprite[spritenum].sectnum == MAXSECTORS) return(-1); if (deletespritesect(spritenum) < 0) return(-1); insertspritesect(newsectnum); return(0); } // // changespritestat // int32_t changespritestat(int16_t spritenum, int16_t newstatnum) { if ((newstatnum < 0) || (newstatnum > MAXSTATUS)) return(-1); if (sprite[spritenum].statnum == newstatnum) return(0); if (sprite[spritenum].statnum == MAXSTATUS) return(-1); if (deletespritestat(spritenum) < 0) return(-1); insertspritestat(newstatnum); return(0); } // // nextsectorneighborz // int32_t nextsectorneighborz(int16_t sectnum, int32_t thez, int16_t topbottom, int16_t direction) { walltype *wal; int32_t i, testz, nextz; int16_t sectortouse; if (direction == 1) nextz = 0x7fffffff; else nextz = 0x80000000; sectortouse = -1; wal = &wall[sector[sectnum].wallptr]; i = sector[sectnum].wallnum; do { if (wal->nextsector >= 0) { if (topbottom == 1) { testz = sector[wal->nextsector].floorz; if (direction == 1) { if ((testz > thez) && (testz < nextz)) { nextz = testz; sectortouse = wal->nextsector; } } else { if ((testz < thez) && (testz > nextz)) { nextz = testz; sectortouse = wal->nextsector; } } } else { testz = sector[wal->nextsector].ceilingz; if (direction == 1) { if ((testz > thez) && (testz < nextz)) { nextz = testz; sectortouse = wal->nextsector; } } else { if ((testz < thez) && (testz > nextz)) { nextz = testz; sectortouse = wal->nextsector; } } } } wal++; i--; } while (i != 0); return(sectortouse); } // // cansee // int32_t cansee(int32_t x1, int32_t y1, int32_t z1, int16_t sect1, int32_t x2, int32_t y2, int32_t z2, int16_t sect2) { sectortype *sec; walltype *wal, *wal2; int32_t i, cnt, nexts, x, y, z, cz, fz, dasectnum, dacnt, danum; int32_t x21, y21, z21, x31, y31, x34, y34, bot, t; if ((x1 == x2) && (y1 == y2)) return(sect1 == sect2); x21 = x2-x1; y21 = y2-y1; z21 = z2-z1; clipsectorlist[0] = sect1; danum = 1; for (dacnt=0; dacntwallnum,wal=&wall[sec->wallptr]; cnt>0; cnt--,wal++) { wal2 = &wall[wal->point2]; x31 = wal->x-x1; x34 = wal->x-wal2->x; y31 = wal->y-y1; y34 = wal->y-wal2->y; bot = y21*x34-x21*y34; if (bot <= 0) continue; t = y21*x31-x21*y31; if ((unsigned)t >= (unsigned)bot) continue; t = y31*x34-x31*y34; if ((unsigned)t >= (unsigned)bot) continue; nexts = wal->nextsector; if ((nexts < 0) || (wal->cstat&32)) return(0); t = divscale24(t,bot); x = x1 + mulscale24(x21,t); y = y1 + mulscale24(y21,t); z = z1 + mulscale24(z21,t); getzsofslope((int16_t)dasectnum,x,y,&cz,&fz); if ((z <= cz) || (z >= fz)) return(0); getzsofslope((int16_t)nexts,x,y,&cz,&fz); if ((z <= cz) || (z >= fz)) return(0); for (i=danum-1; i>=0; i--) if (clipsectorlist[i] == nexts) break; if (i < 0) clipsectorlist[danum++] = nexts; } } for (i=danum-1; i>=0; i--) if (clipsectorlist[i] == sect2) return(1); return(0); } // stat, heinum, z: either ceiling- or floor- // how: -1: behave like ceiling, 1: behave like floor static int32_t hitscan_trysector(const vec3_t *sv, const sectortype *sec, hitdata_t *hitinfo, int32_t vx, int32_t vy, int32_t vz, int16_t stat, int16_t heinum, int32_t z, int32_t how, const intptr_t *tmp) { int32_t x1 = 0x7fffffff, y1, z1; int32_t dax, day, i, j; walltype *wal, *wal2; if (stat&2) { wal = &wall[sec->wallptr]; wal2 = &wall[wal->point2]; dax = wal2->x-wal->x; day = wal2->y-wal->y; i = nsqrtasm(dax*dax+day*day); if (i == 0) return 1; //continue; i = divscale15(heinum,i); dax *= i; day *= i; j = (vz<<8)-dmulscale15(dax,vy,-day,vx); if (j != 0) { i = ((z - sv->z)<<8)+dmulscale15(dax,sv->y-wal->y,-day,sv->x-wal->x); if (((i^j) >= 0) && ((klabs(i)>>1) < klabs(j))) { i = divscale30(i,j); x1 = sv->x + mulscale30(vx,i); y1 = sv->y + mulscale30(vy,i); z1 = sv->z + mulscale30(vz,i); } } } else if ((how*vz > 0) && (how *sv->z <= how*z)) { z1 = z; i = z1-sv->z; if ((klabs(i)>>1) < vz*how) { i = divscale30(i,vz); x1 = sv->x + mulscale30(vx,i); y1 = sv->y + mulscale30(vy,i); } } if ((x1 != 0x7fffffff) && (klabs(x1-sv->x)+klabs(y1-sv->y) < klabs((hitinfo->pos.x)-sv->x)+klabs((hitinfo->pos.y)-sv->y))) { if (tmp==NULL) { if (inside(x1,y1,sec-sector) != 0) { hitinfo->hitsect = sec-sector; hitinfo->hitwall = -1; hitinfo->hitsprite = -1; hitinfo->pos.x = x1; hitinfo->pos.y = y1; hitinfo->pos.z = z1; } } else { int32_t curidx=(int32_t)tmp[0]; spritetype *curspr=(spritetype *)tmp[1]; int32_t thislastsec = tmp[2]; if (!thislastsec) { if (inside(x1,y1,sec-sector) != 0) { hitinfo->hitsect = curspr->sectnum; hitinfo->hitwall = -1; hitinfo->hitsprite = curspr-sprite; hitinfo->pos.x = x1; hitinfo->pos.y = y1; hitinfo->pos.z = z1; } } else { for (i=clipinfo[curidx].qbeg; ihitsect = curspr->sectnum; hitinfo->hitwall = -1; hitinfo->hitsprite = curspr-sprite; hitinfo->pos.x = x1; hitinfo->pos.y = y1; hitinfo->pos.z = z1; break; } } } } } return 0; } // // hitscan // static int32_t clipsprite_initindex(int32_t curidx, spritetype *curspr, int32_t *clipsectcnt, const vec3_t *vect); int32_t hitscan(const vec3_t *sv, int16_t sectnum, int32_t vx, int32_t vy, int32_t vz, hitdata_t *hitinfo, uint32_t cliptype) { sectortype *sec; walltype *wal, *wal2; spritetype *spr; int32_t z, zz, x1, y1=0, z1=0, x2, y2, x3, y3, x4, y4, intx, inty, intz; int32_t topt, topu, bot, dist, offx, offy, cstat; int32_t i, k, l, tilenum, xoff, yoff, dax, day, daz, daz2; int32_t ang, cosang, sinang, xspan, yspan, xrepeat, yrepeat; int32_t dawalclipmask, dasprclipmask; int16_t tempshortcnt, tempshortnum, dasector, startwall, endwall; int16_t nextsector; char clipyou; spritetype *curspr = NULL; int32_t clipspritecnt, curidx=-1; // tmp: { (int32_t)curidx, (spritetype *)curspr, (!=0 if outer sector) } intptr_t tmp[3], *tmpptr=NULL; hitinfo->hitsect = -1; hitinfo->hitwall = -1; hitinfo->hitsprite = -1; if (sectnum < 0) return(-1); hitinfo->pos.x = hitscangoalx; hitinfo->pos.y = hitscangoaly; dawalclipmask = (cliptype&65535); dasprclipmask = (cliptype>>16); clipsectorlist[0] = sectnum; tempshortcnt = 0; tempshortnum = 1; clipspritecnt = clipspritenum = 0; do { if (tempshortcnt >= tempshortnum) { // one bunch of sectors completed, prepare the next if (!curspr) mapinfo_set(&origmapinfo, &clipmapinfo); // replace sector and wall with clip map curspr = &sprite[clipspritelist[clipspritecnt]]; if (curidx < 0) // per-sprite init curidx = pictoidx[curspr->picnum]; else curidx = clipinfo[curidx].next; while (curidx>=0 && (curspr->cstat&32) != (sector[sectq[clipinfo[curidx].qbeg]].CM_CSTAT&32)) curidx = clipinfo[curidx].next; if (curidx < 0) { clipspritecnt++; continue; } tmp[0] = (intptr_t)curidx; tmp[1] = (intptr_t)curspr; tmpptr = tmp; clipsprite_initindex(curidx, curspr, &i, sv); // &i is dummy tempshortnum = (int16_t)clipsectnum; tempshortcnt = 0; } dasector = clipsectorlist[tempshortcnt]; sec = §or[dasector]; i = 1; if (curspr) { if (dasector == sectq[clipinfo[curidx].qend]) { i = -1; tmp[2] = 1; } else tmp[2] = 0; } if (hitscan_trysector(sv, sec, hitinfo, vx,vy,vz, sec->ceilingstat, sec->ceilingheinum, sec->ceilingz, -i, tmpptr)) continue; if (hitscan_trysector(sv, sec, hitinfo, vx,vy,vz, sec->floorstat, sec->floorheinum, sec->floorz, i, tmpptr)) continue; startwall = sec->wallptr; endwall = startwall + sec->wallnum; for (z=startwall,wal=&wall[startwall]; znextsector<0) continue; wal2 = &wall[wal->point2]; x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y; if ((x1-sv->x)*(y2-sv->y) < (x2-sv->x)*(y1-sv->y)) continue; if (rintersect(sv->x,sv->y,sv->z, vx,vy,vz, x1,y1, x2,y2, &intx,&inty,&intz) == 0) continue; if (klabs(intx-sv->x)+klabs(inty-sv->y) >= klabs((hitinfo->pos.x)-sv->x)+klabs((hitinfo->pos.y)-sv->y)) continue; nextsector = wal->nextsector; if (!curspr) { if ((nextsector < 0) || (wal->cstat&dawalclipmask)) { hitinfo->hitsect = dasector; hitinfo->hitwall = z; hitinfo->hitsprite = -1; hitinfo->pos.x = intx; hitinfo->pos.y = inty; hitinfo->pos.z = intz; continue; } getzsofslope(nextsector,intx,inty,&daz,&daz2); if ((intz <= daz) || (intz >= daz2)) { hitinfo->hitsect = dasector; hitinfo->hitwall = z; hitinfo->hitsprite = -1; hitinfo->pos.x = intx; hitinfo->pos.y = inty; hitinfo->pos.z = intz; continue; } } else { int32_t cz,fz; if (wal->cstat&dawalclipmask) { hitinfo->hitsect = curspr->sectnum; hitinfo->hitwall = -1; hitinfo->hitsprite = curspr-sprite; hitinfo->pos.x = intx; hitinfo->pos.y = inty; hitinfo->pos.z = intz; continue; } getzsofslope(nextsector,intx,inty,&daz,&daz2); getzsofslope(sectq[clipinfo[curidx].qend],intx,inty,&cz,&fz); // ceil cz daz daz2 fz floor if ((cz <= intz && intz <= daz) || (daz2 <= intz && intz <= fz)) { hitinfo->hitsect = curspr->sectnum; hitinfo->hitwall = -1; hitinfo->hitsprite = curspr-sprite; hitinfo->pos.x = intx; hitinfo->pos.y = inty; hitinfo->pos.z = intz; continue; } } for (zz=tempshortnum-1; zz>=0; zz--) if (clipsectorlist[zz] == nextsector) break; if (zz < 0) clipsectorlist[tempshortnum++] = nextsector; } if (curspr) continue; for (z=headspritesect[dasector]; z>=0; z=nextspritesect[z]) { spr = &sprite[z]; cstat = spr->cstat; #ifdef POLYMOST if (!hitallsprites) #endif if ((cstat&dasprclipmask) == 0) continue; // try and see whether this sprite's picnum has sector-like clipping data i = pictoidx[spr->picnum]; // handle sector-like floor sprites separately while (i>=0 && (spr->cstat&32) != (clipmapinfo.sector[sectq[clipinfo[i].qbeg]].CM_CSTAT&32)) i = clipinfo[i].next; if (i>=0 && clipspritenumx; y1 = spr->y; z1 = spr->z; switch (cstat&48) { case 0: topt = vx*(x1-sv->x) + vy*(y1-sv->y); if (topt <= 0) continue; bot = vx*vx + vy*vy; if (bot == 0) continue; intz = sv->z+scale(vz,topt,bot); i = (tilesizy[spr->picnum]*spr->yrepeat<<2); if (cstat&128) z1 += (i>>1); if (picanm[spr->picnum]&0x00ff0000) z1 -= ((int32_t)((int8_t)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2); if ((intz > z1) || (intz < z1-i)) continue; topu = vx*(y1-sv->y) - vy*(x1-sv->x); offx = scale(vx,topu,bot); offy = scale(vy,topu,bot); dist = offx*offx + offy*offy; i = tilesizx[spr->picnum]*spr->xrepeat; i *= i; if (dist > (i>>7)) continue; intx = sv->x + scale(vx,topt,bot); inty = sv->y + scale(vy,topt,bot); if (klabs(intx-sv->x)+klabs(inty-sv->y) > klabs((hitinfo->pos.x)-sv->x)+klabs((hitinfo->pos.y)-sv->y)) continue; hitinfo->hitsect = dasector; hitinfo->hitwall = -1; hitinfo->hitsprite = z; hitinfo->pos.x = intx; hitinfo->pos.y = inty; hitinfo->pos.z = intz; break; case 16: //These lines get the 2 points of the rotated sprite //Given: (x1, y1) starts out as the center point tilenum = spr->picnum; xoff = (int32_t)((int8_t)((picanm[tilenum]>>8)&255))+((int32_t)spr->xoffset); if ((cstat&4) > 0) xoff = -xoff; k = spr->ang; l = spr->xrepeat; dax = sintable[k&2047]*l; day = sintable[(k+1536)&2047]*l; l = tilesizx[tilenum]; k = (l>>1)+xoff; x1 -= mulscale16(dax,k); x2 = x1+mulscale16(dax,l); y1 -= mulscale16(day,k); y2 = y1+mulscale16(day,l); if ((cstat&64) != 0) //back side of 1-way sprite if ((x1-sv->x)*(y2-sv->y) < (x2-sv->x)*(y1-sv->y)) continue; if (rintersect(sv->x,sv->y,sv->z,vx,vy,vz,x1,y1,x2,y2,&intx,&inty,&intz) == 0) continue; if (klabs(intx-sv->x)+klabs(inty-sv->y) > klabs((hitinfo->pos.x)-sv->x)+klabs((hitinfo->pos.y)-sv->y)) continue; k = ((tilesizy[spr->picnum]*spr->yrepeat)<<2); if (cstat&128) daz = spr->z+(k>>1); else daz = spr->z; if (picanm[spr->picnum]&0x00ff0000) daz -= ((int32_t)((int8_t)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2); if ((intz < daz) && (intz > daz-k)) { hitinfo->hitsect = dasector; hitinfo->hitwall = -1; hitinfo->hitsprite = z; hitinfo->pos.x = intx; hitinfo->pos.y = inty; hitinfo->pos.z = intz; } break; case 32: if (vz == 0) continue; intz = z1; if (((intz-sv->z)^vz) < 0) continue; if ((cstat&64) != 0) if ((sv->z > intz) == ((cstat&8)==0)) continue; #if 1 // Abyss crash prevention code ((intz-sv->z)*zx overflowing a 8-bit word) zz=(int32_t)((intz-sv->z)*vx); intx = sv->x+scale(zz,1,vz); zz=(int32_t)((intz-sv->z)*vy); inty = sv->y+scale(zz,1,vz); #else intx = sv->x+scale(intz-sv->z,vx,vz); inty = sv->y+scale(intz-sv->z,vy,vz); #endif if (klabs(intx-sv->x)+klabs(inty-sv->y) > klabs((hitinfo->pos.x)-sv->x)+klabs((hitinfo->pos.y)-sv->y)) continue; tilenum = spr->picnum; xoff = (int32_t)((int8_t)((picanm[tilenum]>>8)&255))+((int32_t)spr->xoffset); yoff = (int32_t)((int8_t)((picanm[tilenum]>>16)&255))+((int32_t)spr->yoffset); if ((cstat&4) > 0) xoff = -xoff; if ((cstat&8) > 0) yoff = -yoff; ang = spr->ang; cosang = sintable[(ang+512)&2047]; sinang = sintable[ang]; xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat; yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat; dax = ((xspan>>1)+xoff)*xrepeat; day = ((yspan>>1)+yoff)*yrepeat; x1 += dmulscale16(sinang,dax,cosang,day)-intx; y1 += dmulscale16(sinang,day,-cosang,dax)-inty; l = xspan*xrepeat; x2 = x1 - mulscale16(sinang,l); y2 = y1 + mulscale16(cosang,l); l = yspan*yrepeat; k = -mulscale16(cosang,l); x3 = x2+k; x4 = x1+k; k = -mulscale16(sinang,l); y3 = y2+k; y4 = y1+k; clipyou = 0; if ((y1^y2) < 0) { if ((x1^x2) < 0) clipyou ^= (x1*y2= 0) clipyou ^= 1; } if ((y2^y3) < 0) { if ((x2^x3) < 0) clipyou ^= (x2*y3= 0) clipyou ^= 1; } if ((y3^y4) < 0) { if ((x3^x4) < 0) clipyou ^= (x3*y4= 0) clipyou ^= 1; } if ((y4^y1) < 0) { if ((x4^x1) < 0) clipyou ^= (x4*y1= 0) clipyou ^= 1; } if (clipyou != 0) { hitinfo->hitsect = dasector; hitinfo->hitwall = -1; hitinfo->hitsprite = z; hitinfo->pos.x = intx; hitinfo->pos.y = inty; hitinfo->pos.z = intz; } break; } } } while (++tempshortcnt < tempshortnum || clipspritecnt < clipspritenum); if (curspr) mapinfo_set(NULL, &origmapinfo); return(0); } // // neartag // int32_t neartag(int32_t xs, int32_t ys, int32_t zs, int16_t sectnum, int16_t ange, int16_t *neartagsector, int16_t *neartagwall, int16_t *neartagsprite, int32_t *neartaghitdist, int32_t neartagrange, char tagsearch) { walltype *wal, *wal2; spritetype *spr; int32_t i, z, zz, xe, ye, ze, x1, y1, z1, x2, y2, intx, inty, intz; int32_t topt, topu, bot, dist, offx, offy, vx, vy, vz; int16_t tempshortcnt, tempshortnum, dasector, startwall, endwall; int16_t nextsector, good; *neartagsector = -1; *neartagwall = -1; *neartagsprite = -1; *neartaghitdist = 0; if (sectnum < 0) return(0); if ((tagsearch < 1) || (tagsearch > 3)) return(0); vx = mulscale14(sintable[(ange+2560)&2047],neartagrange); xe = xs+vx; vy = mulscale14(sintable[(ange+2048)&2047],neartagrange); ye = ys+vy; vz = 0; ze = 0; clipsectorlist[0] = sectnum; tempshortcnt = 0; tempshortnum = 1; do { dasector = clipsectorlist[tempshortcnt]; startwall = sector[dasector].wallptr; endwall = startwall + sector[dasector].wallnum - 1; for (z=startwall,wal=&wall[startwall]; z<=endwall; z++,wal++) { wal2 = &wall[wal->point2]; x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y; nextsector = wal->nextsector; good = 0; if (nextsector >= 0) { if ((tagsearch&1) && sector[nextsector].lotag) good |= 1; if ((tagsearch&2) && sector[nextsector].hitag) good |= 1; } if ((tagsearch&1) && wal->lotag) good |= 2; if ((tagsearch&2) && wal->hitag) good |= 2; if ((good == 0) && (nextsector < 0)) continue; if ((x1-xs)*(y2-ys) < (x2-xs)*(y1-ys)) continue; if (lintersect(xs,ys,zs,xe,ye,ze,x1,y1,x2,y2,&intx,&inty,&intz) == 1) { if (good != 0) { if (good&1) *neartagsector = nextsector; if (good&2) *neartagwall = z; *neartaghitdist = dmulscale14(intx-xs,sintable[(ange+2560)&2047],inty-ys,sintable[(ange+2048)&2047]); xe = intx; ye = inty; ze = intz; } if (nextsector >= 0) { for (zz=tempshortnum-1; zz>=0; zz--) if (clipsectorlist[zz] == nextsector) break; if (zz < 0) clipsectorlist[tempshortnum++] = nextsector; } } } for (z=headspritesect[dasector]; z>=0; z=nextspritesect[z]) { spr = &sprite[z]; good = 0; if ((tagsearch&1) && spr->lotag) good |= 1; if ((tagsearch&2) && spr->hitag) good |= 1; if (good != 0) { x1 = spr->x; y1 = spr->y; z1 = spr->z; topt = vx*(x1-xs) + vy*(y1-ys); if (topt > 0) { bot = vx*vx + vy*vy; if (bot != 0) { intz = zs+scale(vz,topt,bot); i = tilesizy[spr->picnum]*spr->yrepeat; if (spr->cstat&128) z1 += (i<<1); if (picanm[spr->picnum]&0x00ff0000) z1 -= ((int32_t)((int8_t)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2); if ((intz <= z1) && (intz >= z1-(i<<2))) { topu = vx*(y1-ys) - vy*(x1-xs); offx = scale(vx,topu,bot); offy = scale(vy,topu,bot); dist = offx*offx + offy*offy; i = (tilesizx[spr->picnum]*spr->xrepeat); i *= i; if (dist <= (i>>7)) { intx = xs + scale(vx,topt,bot); inty = ys + scale(vy,topt,bot); if (klabs(intx-xs)+klabs(inty-ys) < klabs(xe-xs)+klabs(ye-ys)) { *neartagsprite = z; *neartaghitdist = dmulscale14(intx-xs,sintable[(ange+2560)&2047],inty-ys,sintable[(ange+2048)&2047]); xe = intx; ye = inty; ze = intz; } } } } } } } tempshortcnt++; } while (tempshortcnt < tempshortnum); return(0); } // // dragpoint // void dragpoint(int16_t pointhighlight, int32_t dax, int32_t day) { int16_t cnt, tempshort; wall[pointhighlight].x = dax; wall[pointhighlight].y = day; wall[pointhighlight].cstat |= (1<<14); if (linehighlight >= 0 && linehighlight < MAXWALLS) wall[linehighlight].cstat |= (1<<14); wall[lastwall(pointhighlight)].cstat |= (1<<14); cnt = MAXWALLS; tempshort = pointhighlight; //search points CCW do { if (wall[tempshort].nextwall >= 0) { tempshort = wall[wall[tempshort].nextwall].point2; wall[tempshort].x = dax; wall[tempshort].y = day; wall[tempshort].cstat |= (1<<14); } else { tempshort = pointhighlight; //search points CW if not searched all the way around do { if (wall[lastwall(tempshort)].nextwall >= 0) { tempshort = wall[lastwall(tempshort)].nextwall; wall[tempshort].x = dax; wall[tempshort].y = day; wall[tempshort].cstat |= (1<<14); } else { break; } cnt--; } while ((tempshort != pointhighlight) && (cnt > 0)); break; } cnt--; } while ((tempshort != pointhighlight) && (cnt > 0)); } // // lastwall // int32_t lastwall(int16_t point) { int32_t i, j, cnt; if ((point > 0) && (wall[point-1].point2 == point)) return(point-1); i = point; cnt = MAXWALLS; do { j = wall[i].point2; if (j == point) return(i); i = j; cnt--; } while (cnt > 0); return(point); } ////////// static int32_t clipsprite_try(const spritetype *spr, int32_t xmin, int32_t ymin, int32_t xmax, int32_t ymax) { int32_t i,k,tempint1,tempint2; // try and see whether this sprite's picnum has sector-like clipping data i = pictoidx[spr->picnum]; // handle sector-like floor sprites separately while (i>=0 && (spr->cstat&32) != (clipmapinfo.sector[sectq[clipinfo[i].qbeg]].CM_CSTAT&32)) i = clipinfo[i].next; if (i>=0) { int32_t maxcorrection = clipinfo[i].maxdist; k = sectq[clipinfo[i].qbeg]; if ((spr->cstat&48)!=32) // face/wall sprite { tempint1 = clipmapinfo.sector[k].CM_XREPEAT; maxcorrection = (maxcorrection * (int32_t)spr->xrepeat)/tempint1; } else // floor sprite { tempint1 = clipmapinfo.sector[k].CM_XREPEAT; tempint2 = clipmapinfo.sector[k].CM_YREPEAT; maxcorrection = max((maxcorrection * (int32_t)spr->xrepeat)/tempint1, (maxcorrection * (int32_t)spr->yrepeat)/tempint2); } maxcorrection -= MAXCLIPDIST; if (spr->x < xmin - maxcorrection) return 1; if (spr->y < ymin - maxcorrection) return 1; if (spr->x > xmax + maxcorrection) return 1; if (spr->y > ymax + maxcorrection) return 1; if (clipspritenum < MAXCLIPNUM) clipspritelist[clipspritenum++] = spr-sprite; //initprintf("%d: clip sprite[%d]\n",clipspritenum,j); return 1; } return 0; } // return: -1 if curspr has x-flip xor y-flip (in the horizontal map plane!), 1 else static int32_t clipsprite_initindex(int32_t curidx, spritetype *curspr, int32_t *clipsectcnt, const vec3_t *vect) { int32_t j,k,w,tempint1,tempint2,daz = curspr->z; int32_t scalex,scaley,scalez,flipx,flipy,rotang, dorot; int32_t startwall, endwall, flipmul=1; sectortype *sec; walltype *wal; j = sectq[clipinfo[curidx].qbeg]; tempint1 = sector[j].CM_XREPEAT; tempint2 = sector[j].CM_YREPEAT; if ((curspr->cstat&48)!=32) // face/wall sprite { scalex = scaley = divscale22(curspr->xrepeat, tempint1); scalez = divscale22(curspr->yrepeat, tempint2); flipx = 1-((curspr->cstat&4)>>1); flipy = 1; } else { scalex = divscale22(curspr->xrepeat, tempint1); scaley = divscale22(curspr->yrepeat, tempint2); scalez = scalex; flipx = 1-((curspr->cstat&4)>>1); flipy = 1-((curspr->cstat&8)>>2); } rotang = (curspr->ang - sector[j].CM_ANG)&2047; dorot = !CM_NOROTS(j); if (dorot) { flipmul = flipx*flipy; if (flipmul==-1) wall = loadwallinv; } if ((curspr->cstat&128) != (sector[j].CM_CSTAT&128)) daz += (((curspr->cstat&128)>>6)-1)*(((int32_t)tilesizy[curspr->picnum]*(int32_t)curspr->yrepeat)<<1); *clipsectcnt = clipsectnum = 0; // init sectors for this index for (k=clipinfo[curidx].qbeg; k<=clipinfo[curidx].qend; k++) { j = sectq[k]; sec = §or[j]; sec->floorz = daz + mulscale22(scalez, CM_FLOORZ(j)); sec->ceilingz = daz + mulscale22(scalez, CM_CEILINGZ(j)); //initprintf("sec %d: f=%d, c=%d\n", j, sec->floorz, sec->ceilingz); startwall=sec->wallptr; endwall=startwall+sec->wallnum; for (w=startwall,wal=&wall[startwall]; wx = mulscale22(scalex, CM_WALL_X(w)); wal->y = mulscale22(scaley, CM_WALL_Y(w)); if (dorot) { wal->x *= flipx; wal->y *= flipy; rotatepoint(0,0, wal->x,wal->y, rotang, &wal->x,&wal->y); } wal->x += curspr->x; wal->y += curspr->y; } if (inside(vect->x, vect->y, j)==1) clipsectorlist[clipsectnum++] = j; } if (clipsectnum==0) clipsectorlist[clipsectnum++] = sectq[k-1]; return flipmul; } #define addclipline(dax1, day1, dax2, day2, daoval) \ { \ if (clipnum < MAXCLIPNUM) { \ clipit[clipnum].x1 = dax1; clipit[clipnum].y1 = day1; \ clipit[clipnum].x2 = dax2; clipit[clipnum].y2 = day2; \ clipobjectval[clipnum] = daoval; \ clipnum++; \ } else if (!warned) { initprintf("!!clipnum\n"); warned=1; } \ } \ int32_t clipmoveboxtracenum = 3; // // clipmove // int32_t clipmove(vec3_t *vect, int16_t *sectnum, int32_t xvect, int32_t yvect, int32_t walldist, int32_t ceildist, int32_t flordist, uint32_t cliptype) { walltype *wal, *wal2; spritetype *spr; sectortype *sec, *sec2; int32_t i, j, tempint1, tempint2; int32_t oxvect, oyvect, goalx, goaly, intx, inty, lx, ly, retval; int32_t k, l, clipsectcnt, startwall, endwall, cstat, dasect; int32_t x1, y1, x2, y2, cx, cy, rad, xmin, ymin, xmax, ymax, daz, daz2; int32_t bsz, dax, day, xoff, yoff, xspan, yspan, cosang, sinang, tilenum; int32_t xrepeat, yrepeat, gx, gy, dx, dy, dasprclipmask, dawalclipmask; int32_t hitwall, cnt, clipyou; spritetype *curspr=NULL; // non-NULL when handling sprite with sector-like clipping int32_t curidx=-1, warned=0, clipspritecnt; if (((xvect|yvect) == 0) || (*sectnum < 0)) return(0); retval = 0; oxvect = xvect; oyvect = yvect; goalx = (vect->x) + (xvect>>14); goaly = (vect->y) + (yvect>>14); clipnum = 0; cx = (((vect->x)+goalx)>>1); cy = (((vect->y)+goaly)>>1); //Extra walldist for sprites on sector lines gx = goalx-(vect->x); gy = goaly-(vect->y); rad = nsqrtasm(gx*gx + gy*gy) + MAXCLIPDIST+walldist + 8; xmin = cx-rad; ymin = cy-rad; xmax = cx+rad; ymax = cy+rad; dawalclipmask = (cliptype&65535); //CLIPMASK0 = 0x00010001 dasprclipmask = (cliptype>>16); //CLIPMASK1 = 0x01000040 clipsectorlist[0] = (*sectnum); clipsectcnt = 0; clipsectnum = 1; clipspritecnt = 0; clipspritenum = 0; do { if (clipsectcnt>=clipsectnum) { // one bunch of sectors completed (either the very first // one or a sector-like sprite one), prepare the next //initprintf("init sprite %d\n", clipspritecnt); if (!curspr) { // init sector-like sprites for clipping origclipsectnum = clipsectnum; Bmemcpy(origclipsectorlist, clipsectorlist, clipsectnum*sizeof(clipsectorlist[0])); // replace sector and wall with clip map mapinfo_set(&origmapinfo, &clipmapinfo); } curspr = &sprite[clipspritelist[clipspritecnt]]; if (curidx < 0) // per-sprite init curidx = pictoidx[curspr->picnum]; else curidx = clipinfo[curidx].next; while (curidx>=0 && (curspr->cstat&32) != (sector[sectq[clipinfo[curidx].qbeg]].CM_CSTAT&32)) curidx = clipinfo[curidx].next; if (curidx < 0) { clipspritecnt++; continue; } clipsprite_initindex(curidx, curspr, &clipsectcnt, vect); } dasect = clipsectorlist[clipsectcnt++]; //if (curspr) // initprintf("sprite %d/%d: sect %d/%d (%d)\n", clipspritecnt,clipspritenum, clipsectcnt,clipsectnum,dasect); sec = §or[dasect]; startwall = sec->wallptr; endwall = startwall + sec->wallnum; for (j=startwall,wal=&wall[startwall]; jpoint2]; if ((wal->x < xmin) && (wal2->x < xmin)) continue; if ((wal->x > xmax) && (wal2->x > xmax)) continue; if ((wal->y < ymin) && (wal2->y < ymin)) continue; if ((wal->y > ymax) && (wal2->y > ymax)) continue; x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y; dx = x2-x1; dy = y2-y1; if (dx*((vect->y)-y1) < ((vect->x)-x1)*dy) continue; //If wall's not facing you if (dx > 0) dax = dx*(ymin-y1); else dax = dx*(ymax-y1); if (dy > 0) day = dy*(xmax-x1); else day = dy*(xmin-x1); if (dax >= day) continue; clipyou = 0; if (curspr) { if (wal->nextsector>=0) { int32_t basez; if (rintersect(vect->x,vect->y,0, gx,gy,0, x1,y1, x2,y2, &dax,&day,&daz) == 0) dax = vect->x, day = vect->y; daz = getflorzofslope((int16_t)dasect,dax,day); daz2 = getflorzofslope(wal->nextsector,dax,day); basez = getflorzofslope(sectq[clipinfo[curidx].qend],dax,day); sec2 = §or[wal->nextsector]; if ((sec2->floorstat&1) == 0) // if (dasect==sectq[clipinfo[curidx].qend] || daz2 < daz-(1<<8)) if (daz2-(flordist-1) <= vect->z && vect->z <= basez+(flordist-1)) clipyou = 1; if (clipyou == 0) { daz = getceilzofslope((int16_t)dasect,dax,day); daz2 = getceilzofslope(wal->nextsector,dax,day); basez = getceilzofslope(sectq[clipinfo[curidx].qend],dax,day); if ((sec2->ceilingstat&1) == 0) // if (dasect==sectq[clipinfo[curidx].qend] || daz2 > daz+(1<<8)) if (basez-(ceildist-1) <= vect->z && vect->z <= daz2+(ceildist-1)) clipyou = 1; } } } else if ((wal->nextsector < 0) || (wal->cstat&dawalclipmask)) clipyou = 1; else if (editstatus == 0) { if (rintersect(vect->x,vect->y,0,gx,gy,0,x1,y1,x2,y2,&dax,&day,&daz) == 0) dax = vect->x, day = vect->y; daz = getflorzofslope((int16_t)dasect,dax,day); daz2 = getflorzofslope(wal->nextsector,dax,day); sec2 = §or[wal->nextsector]; if (daz2 < daz-(1<<8)) if ((sec2->floorstat&1) == 0) if ((vect->z) >= daz2-(flordist-1)) clipyou = 1; if (clipyou == 0) { daz = getceilzofslope((int16_t)dasect,dax,day); daz2 = getceilzofslope(wal->nextsector,dax,day); if (daz2 > daz+(1<<8)) if ((sec2->ceilingstat&1) == 0) if ((vect->z) <= daz2+(ceildist-1)) clipyou = 1; } } if (clipyou) { int16_t objtype; if (!curspr) objtype = (int16_t)j+32768; else objtype = (int16_t)(curspr-sprite)+49152; //Add 2 boxes at endpoints bsz = walldist; if (gx < 0) bsz = -bsz; addclipline(x1-bsz,y1-bsz,x1-bsz,y1+bsz,objtype); addclipline(x2-bsz,y2-bsz,x2-bsz,y2+bsz,objtype); bsz = walldist; if (gy < 0) bsz = -bsz; addclipline(x1+bsz,y1-bsz,x1-bsz,y1-bsz,objtype); addclipline(x2+bsz,y2-bsz,x2-bsz,y2-bsz,objtype); dax = walldist; if (dy > 0) dax = -dax; day = walldist; if (dx < 0) day = -day; addclipline(x1+dax,y1+day,x2+dax,y2+day,objtype); } else if (wal->nextsector>=0) { for (i=clipsectnum-1; i>=0; i--) if (wal->nextsector == clipsectorlist[i]) break; if (i < 0) clipsectorlist[clipsectnum++] = wal->nextsector; } } if (curspr) continue; // next sector of this index for (j=headspritesect[dasect]; j>=0; j=nextspritesect[j]) { spr = &sprite[j]; cstat = spr->cstat; if ((cstat&dasprclipmask) == 0) continue; if (clipsprite_try(spr, xmin,ymin, xmax,ymax)) continue; x1 = spr->x; y1 = spr->y; switch (cstat&48) { case 0: if ((x1 >= xmin) && (x1 <= xmax) && (y1 >= ymin) && (y1 <= ymax)) { k = ((tilesizy[spr->picnum]*spr->yrepeat)<<2); if (cstat&128) daz = spr->z+(k>>1); else daz = spr->z; if (picanm[spr->picnum]&0x00ff0000) daz -= ((int32_t)((int8_t)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2); if (((vect->z) < daz+ceildist) && ((vect->z) > daz-k-flordist)) { bsz = (spr->clipdist<<2)+walldist; if (gx < 0) bsz = -bsz; addclipline(x1-bsz,y1-bsz,x1-bsz,y1+bsz,(int16_t)j+49152); bsz = (spr->clipdist<<2)+walldist; if (gy < 0) bsz = -bsz; addclipline(x1+bsz,y1-bsz,x1-bsz,y1-bsz,(int16_t)j+49152); } } break; case 16: k = ((tilesizy[spr->picnum]*spr->yrepeat)<<2); if (cstat&128) daz = spr->z+(k>>1); else daz = spr->z; if (picanm[spr->picnum]&0x00ff0000) daz -= ((int32_t)((int8_t)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2); daz2 = daz-k; daz += ceildist; daz2 -= flordist; if (((vect->z) < daz) && ((vect->z) > daz2)) { //These lines get the 2 points of the rotated sprite //Given: (x1, y1) starts out as the center point tilenum = spr->picnum; xoff = (int32_t)((int8_t)((picanm[tilenum]>>8)&255))+((int32_t)spr->xoffset); if ((cstat&4) > 0) xoff = -xoff; k = spr->ang; l = spr->xrepeat; dax = sintable[k&2047]*l; day = sintable[(k+1536)&2047]*l; l = tilesizx[tilenum]; k = (l>>1)+xoff; x1 -= mulscale16(dax,k); x2 = x1+mulscale16(dax,l); y1 -= mulscale16(day,k); y2 = y1+mulscale16(day,l); if (clipinsideboxline(cx,cy,x1,y1,x2,y2,rad) != 0) { dax = mulscale14(sintable[(spr->ang+256+512)&2047],walldist); day = mulscale14(sintable[(spr->ang+256)&2047],walldist); if ((x1-(vect->x))*(y2-(vect->y)) >= (x2-(vect->x))*(y1-(vect->y))) //Front { addclipline(x1+dax,y1+day,x2+day,y2-dax,(int16_t)j+49152); } else { if ((cstat&64) != 0) continue; addclipline(x2-dax,y2-day,x1-day,y1+dax,(int16_t)j+49152); } //Side blocker if ((x2-x1)*((vect->x)-x1) + (y2-y1)*((vect->y)-y1) < 0) { addclipline(x1-day,y1+dax,x1+dax,y1+day,(int16_t)j+49152); } else if ((x1-x2)*((vect->x)-x2) + (y1-y2)*((vect->y)-y2) < 0) { addclipline(x2+day,y2-dax,x2-dax,y2-day,(int16_t)j+49152); } } } break; case 32: daz = spr->z+ceildist; daz2 = spr->z-flordist; if (((vect->z) < daz) && ((vect->z) > daz2)) { if ((cstat&64) != 0) if (((vect->z) > spr->z) == ((cstat&8)==0)) continue; tilenum = spr->picnum; xoff = (int32_t)((int8_t)((picanm[tilenum]>>8)&255))+((int32_t)spr->xoffset); yoff = (int32_t)((int8_t)((picanm[tilenum]>>16)&255))+((int32_t)spr->yoffset); if ((cstat&4) > 0) xoff = -xoff; if ((cstat&8) > 0) yoff = -yoff; k = spr->ang; cosang = sintable[(k+512)&2047]; sinang = sintable[k]; xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat; yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat; dax = ((xspan>>1)+xoff)*xrepeat; day = ((yspan>>1)+yoff)*yrepeat; rxi[0] = x1 + dmulscale16(sinang,dax,cosang,day); ryi[0] = y1 + dmulscale16(sinang,day,-cosang,dax); l = xspan*xrepeat; rxi[1] = rxi[0] - mulscale16(sinang,l); ryi[1] = ryi[0] + mulscale16(cosang,l); l = yspan*yrepeat; k = -mulscale16(cosang,l); rxi[2] = rxi[1]+k; rxi[3] = rxi[0]+k; k = -mulscale16(sinang,l); ryi[2] = ryi[1]+k; ryi[3] = ryi[0]+k; dax = mulscale14(sintable[(spr->ang-256+512)&2047],walldist); day = mulscale14(sintable[(spr->ang-256)&2047],walldist); if ((rxi[0]-(vect->x))*(ryi[1]-(vect->y)) < (rxi[1]-(vect->x))*(ryi[0]-(vect->y))) { if (clipinsideboxline(cx,cy,rxi[1],ryi[1],rxi[0],ryi[0],rad) != 0) addclipline(rxi[1]-day,ryi[1]+dax,rxi[0]+dax,ryi[0]+day,(int16_t)j+49152); } else if ((rxi[2]-(vect->x))*(ryi[3]-(vect->y)) < (rxi[3]-(vect->x))*(ryi[2]-(vect->y))) { if (clipinsideboxline(cx,cy,rxi[3],ryi[3],rxi[2],ryi[2],rad) != 0) addclipline(rxi[3]+day,ryi[3]-dax,rxi[2]-dax,ryi[2]-day,(int16_t)j+49152); } if ((rxi[1]-(vect->x))*(ryi[2]-(vect->y)) < (rxi[2]-(vect->x))*(ryi[1]-(vect->y))) { if (clipinsideboxline(cx,cy,rxi[2],ryi[2],rxi[1],ryi[1],rad) != 0) addclipline(rxi[2]-dax,ryi[2]-day,rxi[1]-day,ryi[1]+dax,(int16_t)j+49152); } else if ((rxi[3]-(vect->x))*(ryi[0]-(vect->y)) < (rxi[0]-(vect->x))*(ryi[3]-(vect->y))) { if (clipinsideboxline(cx,cy,rxi[0],ryi[0],rxi[3],ryi[3],rad) != 0) addclipline(rxi[0]+dax,ryi[0]+day,rxi[3]+day,ryi[3]-dax,(int16_t)j+49152); } } break; } } } while (clipsectcnt < clipsectnum || clipspritecnt < clipspritenum); if (curspr) { // restore original map mapinfo_set(NULL, &origmapinfo); clipsectnum = origclipsectnum; Bmemcpy(clipsectorlist, origclipsectorlist, clipsectnum*sizeof(clipsectorlist[0])); } hitwall = 0; cnt = clipmoveboxtracenum; do { intx = goalx; inty = goaly; hitwall = raytrace(vect->x, vect->y, &intx, &inty); if (hitwall >= 0) { lx = clipit[hitwall].x2-clipit[hitwall].x1; ly = clipit[hitwall].y2-clipit[hitwall].y1; tempint2 = lx*lx + ly*ly; if (tempint2 > 0) { tempint1 = (goalx-intx)*lx + (goaly-inty)*ly; if ((klabs(tempint1)>>11) < tempint2) i = divscale20(tempint1,tempint2); else i = 0; goalx = mulscale20(lx,i)+intx; goaly = mulscale20(ly,i)+inty; } tempint1 = dmulscale6(lx,oxvect,ly,oyvect); for (i=cnt+1; i<=clipmoveboxtracenum; i++) { j = hitwalls[i]; tempint2 = dmulscale6(clipit[j].x2-clipit[j].x1,oxvect,clipit[j].y2-clipit[j].y1,oyvect); if ((tempint1^tempint2) < 0) { updatesector(vect->x,vect->y,sectnum); return(retval); } } keepaway(&goalx, &goaly, hitwall); xvect = ((goalx-intx)<<14); yvect = ((goaly-inty)<<14); if (cnt == clipmoveboxtracenum) retval = clipobjectval[hitwall]; hitwalls[cnt] = hitwall; } cnt--; vect->x = intx; vect->y = inty; } while (((xvect|yvect) != 0) && (hitwall >= 0) && (cnt > 0)); for (j=0; jx,vect->y,clipsectorlist[j]) == 1) { *sectnum = clipsectorlist[j]; return(retval); } *sectnum = -1; tempint1 = 0x7fffffff; for (j=numsectors-1; j>=0; j--) if (inside(vect->x,vect->y,j) == 1) { if (sector[j].ceilingstat&2) tempint2 = (getceilzofslope((int16_t)j,vect->x,vect->y)-(vect->z)); else tempint2 = (sector[j].ceilingz-(vect->z)); if (tempint2 > 0) { if (tempint2 < tempint1) { *sectnum = j; tempint1 = tempint2; } } else { if (sector[j].floorstat&2) tempint2 = ((vect->z)-getflorzofslope((int16_t)j,vect->x,vect->y)); else tempint2 = ((vect->z)-sector[j].floorz); if (tempint2 <= 0) { *sectnum = j; return(retval); } if (tempint2 < tempint1) { *sectnum = j; tempint1 = tempint2; } } } return(retval); } // // pushmove // int32_t pushmove(vec3_t *vect, int16_t *sectnum, int32_t walldist, int32_t ceildist, int32_t flordist, uint32_t cliptype) { sectortype *sec, *sec2; walltype *wal; int32_t i, j, k, t, dx, dy, dax, day, daz, daz2, bad, dir; int32_t dasprclipmask, dawalclipmask; int16_t startwall, endwall, clipsectcnt; char bad2; if ((*sectnum) < 0) return(-1); dawalclipmask = (cliptype&65535); dasprclipmask = (cliptype>>16); k = 32; dir = 1; do { bad = 0; clipsectorlist[0] = *sectnum; clipsectcnt = 0; clipsectnum = 1; do { /*Push FACE sprites for(i=headspritesect[clipsectorlist[clipsectcnt]];i>=0;i=nextspritesect[i]) { spr = &sprite[i]; if (((spr->cstat&48) != 0) && ((spr->cstat&48) != 48)) continue; if ((spr->cstat&dasprclipmask) == 0) continue; dax = (vect->x)-spr->x; day = (vect->y)-spr->y; t = (spr->clipdist<<2)+walldist; if ((klabs(dax) < t) && (klabs(day) < t)) { t = ((tilesizy[spr->picnum]*spr->yrepeat)<<2); if (spr->cstat&128) daz = spr->z+(t>>1); else daz = spr->z; if (picanm[spr->picnum]&0x00ff0000) daz -= ((int32_t)((int8_t)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2); if (((vect->z) < daz+ceildist) && ((vect->z) > daz-t-flordist)) { t = (spr->clipdist<<2)+walldist; j = getangle(dax,day); dx = (sintable[(j+512)&2047]>>11); dy = (sintable[(j)&2047]>>11); bad2 = 16; do { vect->x = (vect->x) + dx; vect->y = (vect->y) + dy; bad2--; if (bad2 == 0) break; } while ((klabs((vect->x)-spr->x) < t) && (klabs((vect->y)-spr->y) < t)); bad = -1; k--; if (k <= 0) return(bad); updatesector(vect->x,vect->y,sectnum); } } }*/ sec = §or[clipsectorlist[clipsectcnt]]; if (dir > 0) startwall = sec->wallptr, endwall = startwall + sec->wallnum; else endwall = sec->wallptr, startwall = endwall + sec->wallnum; for (i=startwall,wal=&wall[startwall]; i!=endwall; i+=dir,wal+=dir) if (clipinsidebox(vect->x,vect->y,i,walldist-4) == 1) { j = 0; if (wal->nextsector < 0) j = 1; if (wal->cstat&dawalclipmask) j = 1; if (j == 0) { sec2 = §or[wal->nextsector]; //Find closest point on wall (dax, day) to (vect->x, vect->y) dax = wall[wal->point2].x-wal->x; day = wall[wal->point2].y-wal->y; daz = dax*((vect->x)-wal->x) + day*((vect->y)-wal->y); if (daz <= 0) t = 0; else { daz2 = dax*dax+day*day; if (daz >= daz2) t = (1<<30); else t = divscale30(daz,daz2); } dax = wal->x + mulscale30(dax,t); day = wal->y + mulscale30(day,t); daz = getflorzofslope(clipsectorlist[clipsectcnt],dax,day); daz2 = getflorzofslope(wal->nextsector,dax,day); if ((daz2 < daz-(1<<8)) && ((sec2->floorstat&1) == 0)) if (vect->z >= daz2-(flordist-1)) j = 1; daz = getceilzofslope(clipsectorlist[clipsectcnt],dax,day); daz2 = getceilzofslope(wal->nextsector,dax,day); if ((daz2 > daz+(1<<8)) && ((sec2->ceilingstat&1) == 0)) if (vect->z <= daz2+(ceildist-1)) j = 1; } if (j != 0) { j = getangle(wall[wal->point2].x-wal->x,wall[wal->point2].y-wal->y); dx = (sintable[(j+1024)&2047]>>11); dy = (sintable[(j+512)&2047]>>11); bad2 = 16; do { vect->x = (vect->x) + dx; vect->y = (vect->y) + dy; bad2--; if (bad2 == 0) break; } while (clipinsidebox(vect->x,vect->y,i,walldist-4) != 0); bad = -1; k--; if (k <= 0) return(bad); updatesector(vect->x,vect->y,sectnum); if (*sectnum < 0) return -1; } else { for (j=clipsectnum-1; j>=0; j--) if (wal->nextsector == clipsectorlist[j]) break; if (j < 0) clipsectorlist[clipsectnum++] = wal->nextsector; } } clipsectcnt++; } while (clipsectcnt < clipsectnum); dir = -dir; } while (bad != 0); return(bad); } // // updatesector[z] // void updatesector(int32_t x, int32_t y, int16_t *sectnum) { walltype *wal; int32_t i, j; if (inside(x,y,*sectnum) == 1) return; if ((*sectnum >= 0) && (*sectnum < numsectors)) { wal = &wall[sector[*sectnum].wallptr]; j = sector[*sectnum].wallnum; do { i = wal->nextsector; if (i >= 0) if (inside(x,y,(int16_t)i) == 1) { *sectnum = i; return; } wal++; j--; } while (j != 0); } for (i=numsectors-1; i>=0; i--) if (inside(x,y,(int16_t)i) == 1) { *sectnum = i; return; } *sectnum = -1; } void updatesectorexclude(int32_t x, int32_t y, int16_t *sectnum, const uint8_t *excludesectbitmap) { walltype *wal; int32_t i, j; if (!(excludesectbitmap[*sectnum>>3]&(1<<(*sectnum&7))) && inside(x,y,*sectnum) == 1) return; if ((*sectnum >= 0) && (*sectnum < numsectors)) { wal = &wall[sector[*sectnum].wallptr]; j = sector[*sectnum].wallnum; do { i = wal->nextsector; if (i >= 0) if (!(excludesectbitmap[i>>3]&(1<<(i&7))) && inside(x,y,(int16_t)i) == 1) { *sectnum = i; return; } wal++; j--; } while (j != 0); } for (i=numsectors-1; i>=0; i--) if (!(excludesectbitmap[i>>3]&(1<<(i&7))) && inside(x,y,(int16_t)i) == 1) { *sectnum = i; return; } *sectnum = -1; } void updatesectorz(int32_t x, int32_t y, int32_t z, int16_t *sectnum) { walltype *wal; int32_t i, j, cz, fz; if ((*sectnum >= 0) && (*sectnum < numsectors)) { // this block used to be outside the "if" and caused crashes in Polymost Mapster32 getzsofslope(*sectnum, x, y, &cz, &fz); if ((z >= cz) && (z <= fz)) if (inside(x,y,*sectnum) != 0) return; wal = &wall[sector[*sectnum].wallptr]; j = sector[*sectnum].wallnum; do { i = wal->nextsector; if (i >= 0) { getzsofslope(i, x, y, &cz, &fz); if ((z >= cz) && (z <= fz)) if (inside(x,y,(int16_t)i) == 1) { *sectnum = i; return; } } wal++; j--; } while (j != 0); } for (i=numsectors-1; i>=0; i--) { getzsofslope(i, x, y, &cz, &fz); if ((z >= cz) && (z <= fz)) if (inside(x,y,(int16_t)i) == 1) { *sectnum = i; return; } } *sectnum = -1; } // // rotatepoint // void rotatepoint(int32_t xpivot, int32_t ypivot, int32_t x, int32_t y, int16_t daang, int32_t *x2, int32_t *y2) { int32_t dacos, dasin; dacos = sintable[(daang+2560)&2047]; dasin = sintable[(daang+2048)&2047]; x -= xpivot; y -= ypivot; *x2 = dmulscale14(x,dacos,-y,dasin) + xpivot; *y2 = dmulscale14(y,dacos,x,dasin) + ypivot; } // // getmousevalues // void getmousevalues(int32_t *mousx, int32_t *mousy, int32_t *bstatus) { readmousexy(mousx,mousy); readmousebstatus(bstatus); } #if KRANDDEBUG # include # define KRD_MAXCALLS 262144 # define KRD_DEPTH 8 static int32_t krd_numcalls=0; static void *krd_fromwhere[KRD_MAXCALLS][KRD_DEPTH]; static int32_t krd_enabled=0; void krd_enable(int which) // 0: disable, 1: rec, 2: play { krd_enabled = which; if (which) Bmemset(krd_fromwhere, 0, sizeof(krd_fromwhere)); } int32_t krd_print(const char *filename) { FILE *fp; int32_t i, j; if (!krd_enabled) return 1; krd_enabled = 0; fp = fopen(filename, "wb"); if (!fp) { OSD_Printf("krd_print (2): fopen"); return 1; } for (i=0; i=KRD_DEPTH || krd_fromwhere[i][j]==NULL) { fprintf(fp, "\n"); break; } fprintf(fp, " [%p]", krd_fromwhere[i][j]); } } krd_numcalls = 0; fclose(fp); return 0; } #endif // KRANDDEBUG // // krand // int32_t krand(void) { // randomseed = (randomseed*27584621)+1; randomseed = (randomseed * 1664525ul) + 221297ul; #if KRANDDEBUG if (krd_enabled) if (krd_numcalls < KRD_MAXCALLS) { backtrace(krd_fromwhere[krd_numcalls], KRD_DEPTH); krd_numcalls++; } #endif return(((uint32_t)randomseed)>>16); } // // getzrange // void getzrange(const vec3_t *vect, int16_t sectnum, int32_t *ceilz, int32_t *ceilhit, int32_t *florz, int32_t *florhit, int32_t walldist, uint32_t cliptype) { sectortype *sec; walltype *wal, *wal2; spritetype *spr; int32_t clipsectcnt, startwall, endwall, tilenum, xoff, yoff, dax, day; int32_t xmin, ymin, xmax, ymax, i, j, k, l, daz, daz2, dx, dy; int32_t x1, y1, x2, y2, x3, y3, x4, y4, ang, cosang, sinang; int32_t xspan, yspan, xrepeat, yrepeat, dasprclipmask, dawalclipmask; int16_t cstat; char clipyou; spritetype *curspr=NULL; // non-NULL when handling sprite with sector-like clipping int32_t curidx=-1, clipspritecnt; if (sectnum < 0) { *ceilz = 0x80000000; *ceilhit = -1; *florz = 0x7fffffff; *florhit = -1; return; } //Extra walldist for sprites on sector lines i = walldist+MAXCLIPDIST+1; xmin = vect->x-i; ymin = vect->y-i; xmax = vect->x+i; ymax = vect->y+i; getzsofslope(sectnum,vect->x,vect->y,ceilz,florz); *ceilhit = sectnum+16384; *florhit = sectnum+16384; dawalclipmask = (cliptype&65535); dasprclipmask = (cliptype>>16); clipsectorlist[0] = sectnum; clipsectcnt = 0; clipsectnum = 1; clipspritecnt = clipspritenum = 0; if (0) { beginagain: // replace sector and wall with clip map mapinfo_set(&origmapinfo, &clipmapinfo); clipsectcnt = clipsectnum; // should be a nop, "safety"... } do //Collect sectors inside your square first { if (clipsectcnt>=clipsectnum) { // one bunch of sectors completed, prepare the next curspr = &sprite[clipspritelist[clipspritecnt]]; if (curidx < 0) // per-sprite init curidx = pictoidx[curspr->picnum]; else curidx = clipinfo[curidx].next; while (curidx>=0 && (curspr->cstat&32) != (sector[sectq[clipinfo[curidx].qbeg]].CM_CSTAT&32)) curidx = clipinfo[curidx].next; if (curidx < 0) { clipspritecnt++; continue; } clipsprite_initindex(curidx, curspr, &clipsectcnt, vect); for (i=0; ix,vect->y,&daz,&daz2); getzsofslope(sectq[clipinfo[curidx].qend],vect->x,vect->y,&cz,&fz); if ((sector[k].ceilingstat&1)==0) { if (vect->z < cz && cz < *florz) { *florz = cz; *florhit = (curspr-sprite)+49152; } if (vect->z > daz && daz > *ceilz) { *ceilz = daz; *ceilhit = (curspr-sprite)+49152; } } if ((sector[k].floorstat&1)==0) { if (vect->z < daz2 && daz2 < *florz) { *florz = daz2; *florhit = (curspr-sprite)+49152; } if (vect->z > fz && fz > *ceilz) { *ceilz = fz; *ceilhit = (curspr-sprite)+49152; } } } } sec = §or[clipsectorlist[clipsectcnt]]; startwall = sec->wallptr; endwall = startwall + sec->wallnum; for (j=startwall,wal=&wall[startwall]; jnextsector; if (k >= 0) { wal2 = &wall[wal->point2]; x1 = wal->x; x2 = wal2->x; if ((x1 < xmin) && (x2 < xmin)) continue; if ((x1 > xmax) && (x2 > xmax)) continue; y1 = wal->y; y2 = wal2->y; if ((y1 < ymin) && (y2 < ymin)) continue; if ((y1 > ymax) && (y2 > ymax)) continue; dx = x2-x1; dy = y2-y1; if (dx*(vect->y-y1) < (vect->x-x1)*dy) continue; //back if (dx > 0) dax = dx*(ymin-y1); else dax = dx*(ymax-y1); if (dy > 0) day = dy*(xmax-x1); else day = dy*(xmin-x1); if (dax >= day) continue; if (wal->cstat&dawalclipmask) continue; sec = §or[k]; if (curspr) { if (k==sectq[clipinfo[curidx].qend]) continue; if ((sec->ceilingstat&1) && (sec->floorstat&1)) continue; } else if (editstatus == 0) { if (((sec->ceilingstat&1) == 0) && (vect->z <= sec->ceilingz+(3<<8))) continue; if (((sec->floorstat&1) == 0) && (vect->z >= sec->floorz-(3<<8))) continue; } for (i=clipsectnum-1; i>=0; i--) if (clipsectorlist[i] == k) break; if (i < 0) clipsectorlist[clipsectnum++] = k; if ((x1 < xmin+MAXCLIPDIST) && (x2 < xmin+MAXCLIPDIST)) continue; if ((x1 > xmax-MAXCLIPDIST) && (x2 > xmax-MAXCLIPDIST)) continue; if ((y1 < ymin+MAXCLIPDIST) && (y2 < ymin+MAXCLIPDIST)) continue; if ((y1 > ymax-MAXCLIPDIST) && (y2 > ymax-MAXCLIPDIST)) continue; if (dx > 0) dax += dx*MAXCLIPDIST; else dax -= dx*MAXCLIPDIST; if (dy > 0) day -= dy*MAXCLIPDIST; else day += dy*MAXCLIPDIST; if (dax >= day) continue; //It actually got here, through all the continue's!!! getzsofslope((int16_t)k,vect->x,vect->y,&daz,&daz2); if (curspr) { int32_t fz,cz; getzsofslope(sectq[clipinfo[curidx].qend],vect->x,vect->y,&cz,&fz); if ((sec->ceilingstat&1)==0) { if (vect->z < cz && cz < *florz) { *florz = cz; *florhit = (curspr-sprite)+49152; } if (vect->z > daz && daz > *ceilz) { *ceilz = daz; *ceilhit = (curspr-sprite)+49152; } } if ((sec->floorstat&1)==0) { if (vect->z < daz2 && daz2 < *florz) { *florz = daz2; *florhit = (curspr-sprite)+49152; } if (vect->z > fz && fz > *ceilz) { *ceilz = fz; *ceilhit = (curspr-sprite)+49152; } } } else { if (daz > *ceilz) { *ceilz = daz; *ceilhit = k+16384; } if (daz2 < *florz) { *florz = daz2; *florhit = k+16384; } } } } clipsectcnt++; } while (clipsectcnt < clipsectnum || clipspritecnt < clipspritenum); if (curspr) { mapinfo_set(NULL, &origmapinfo); // restore original map return; } for (i=0; i=0; j=nextspritesect[j]) { spr = &sprite[j]; cstat = spr->cstat; if (cstat&dasprclipmask) { if (clipsprite_try(spr, xmin,ymin, xmax,ymax)) continue; x1 = spr->x; y1 = spr->y; clipyou = 0; switch (cstat&48) { case 0: k = walldist+(spr->clipdist<<2)+1; if ((klabs(x1-vect->x) <= k) && (klabs(y1-vect->y) <= k)) { daz = spr->z; k = ((tilesizy[spr->picnum]*spr->yrepeat)<<1); if (cstat&128) daz += k; if (picanm[spr->picnum]&0x00ff0000) daz -= ((int32_t)((int8_t)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2); daz2 = daz - (k<<1); clipyou = 1; } break; case 16: tilenum = spr->picnum; xoff = (int32_t)((int8_t)((picanm[tilenum]>>8)&255))+((int32_t)spr->xoffset); if ((cstat&4) > 0) xoff = -xoff; k = spr->ang; l = spr->xrepeat; dax = sintable[k&2047]*l; day = sintable[(k+1536)&2047]*l; l = tilesizx[tilenum]; k = (l>>1)+xoff; x1 -= mulscale16(dax,k); x2 = x1+mulscale16(dax,l); y1 -= mulscale16(day,k); y2 = y1+mulscale16(day,l); if (clipinsideboxline(vect->x,vect->y,x1,y1,x2,y2,walldist+1) != 0) { daz = spr->z; k = ((tilesizy[spr->picnum]*spr->yrepeat)<<1); if (cstat&128) daz += k; if (picanm[spr->picnum]&0x00ff0000) daz -= ((int32_t)((int8_t)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2); daz2 = daz-(k<<1); clipyou = 1; } break; case 32: daz = spr->z; daz2 = daz; if ((cstat&64) != 0) if ((vect->z > daz) == ((cstat&8)==0)) continue; tilenum = spr->picnum; xoff = (int32_t)((int8_t)((picanm[tilenum]>>8)&255))+((int32_t)spr->xoffset); yoff = (int32_t)((int8_t)((picanm[tilenum]>>16)&255))+((int32_t)spr->yoffset); if ((cstat&4) > 0) xoff = -xoff; if ((cstat&8) > 0) yoff = -yoff; ang = spr->ang; cosang = sintable[(ang+512)&2047]; sinang = sintable[ang]; xspan = tilesizx[tilenum]; xrepeat = spr->xrepeat; yspan = tilesizy[tilenum]; yrepeat = spr->yrepeat; dax = ((xspan>>1)+xoff)*xrepeat; day = ((yspan>>1)+yoff)*yrepeat; x1 += dmulscale16(sinang,dax,cosang,day)-vect->x; y1 += dmulscale16(sinang,day,-cosang,dax)-vect->y; l = xspan*xrepeat; x2 = x1 - mulscale16(sinang,l); y2 = y1 + mulscale16(cosang,l); l = yspan*yrepeat; k = -mulscale16(cosang,l); x3 = x2+k; x4 = x1+k; k = -mulscale16(sinang,l); y3 = y2+k; y4 = y1+k; dax = mulscale14(sintable[(spr->ang-256+512)&2047],walldist+4); day = mulscale14(sintable[(spr->ang-256)&2047],walldist+4); x1 += dax; x2 -= day; x3 -= dax; x4 += day; y1 += day; y2 += dax; y3 -= day; y4 -= dax; if ((y1^y2) < 0) { if ((x1^x2) < 0) clipyou ^= (x1*y2= 0) clipyou ^= 1; } if ((y2^y3) < 0) { if ((x2^x3) < 0) clipyou ^= (x2*y3= 0) clipyou ^= 1; } if ((y3^y4) < 0) { if ((x3^x4) < 0) clipyou ^= (x3*y4= 0) clipyou ^= 1; } if ((y4^y1) < 0) { if ((x4^x1) < 0) clipyou ^= (x4*y1= 0) clipyou ^= 1; } break; } if (clipyou != 0) { if ((vect->z > daz) && (daz > *ceilz)) { *ceilz = daz; *ceilhit = j+49152; } if ((vect->z < daz2) && (daz2 < *florz)) { *florz = daz2; *florhit = j+49152; } } } } } if (clipspritenum>0) goto beginagain; } void setaspect_new() { if (r_usenewaspect && newaspect_enable) { // the correction factor 100/107 has been found // out experimentally. squares ftw! int32_t vr, yx=(65536*4*100)/(3*107); int32_t y, x; if (fullscreen) { x=r_screenxy/100; y=r_screenxy%100; if (y==0 || x==0) { x=4; y=3; } } else { x = xdim; y = ydim; } vr = (65536*x*3)/(y*4); setaspect(vr, yx); } else setaspect(65536L,(int32_t)divscale16(ydim*320L,xdim*200L)); } // // setview // void setview(int32_t x1, int32_t y1, int32_t x2, int32_t y2) { int32_t i; windowx1 = x1; wx1 = (x1<<12); windowy1 = y1; wy1 = (y1<<12); windowx2 = x2; wx2 = ((x2+1)<<12); windowy2 = y2; wy2 = ((y2+1)<<12); xdimen = (x2-x1)+1; halfxdimen = (xdimen>>1); xdimenrecip = divscale32(1L,xdimen); ydimen = (y2-y1)+1; setaspect_new(); for (i=0; i cx2) || (cy1 > cy2)) return; if (z <= 16) return; if (picanm[picnum]&192) picnum += animateoffs(picnum,(int16_t)0xc000); if ((tilesizx[picnum] <= 0) || (tilesizy[picnum] <= 0)) return; if (((dastat&128) == 0) || (numpages < 2) || (beforedrawrooms != 0)) { begindrawing(); //{{{ dorotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,cx1,cy1,cx2,cy2,guniqhudid); enddrawing(); //}}} } if ((dastat&64) && (cx1 <= 0) && (cy1 <= 0) && (cx2 >= xdim-1) && (cy2 >= ydim-1) && (sx == (160<<16)) && (sy == (100<<16)) && (z == 65536L) && (a == 0) && ((dastat&1) == 0)) permhead = permtail = 0; if ((dastat&128) == 0) return; if (numpages >= 2) { per = &permfifo[permhead]; per->sx = sx; per->sy = sy; per->z = z; per->a = a; per->picnum = picnum; per->dashade = dashade; per->dapalnum = dapalnum; per->dastat = dastat; per->pagesleft = numpages+((beforedrawrooms&1)<<7); per->cx1 = cx1; per->cy1 = cy1; per->cx2 = cx2; per->cy2 = cy2; per->uniqid = guniqhudid; //JF extension //Would be better to optimize out true bounding boxes if (dastat&64) //If non-masking write, checking for overlapping cases { for (i=permtail; i!=permhead; i=((i+1)&(MAXPERMS-1))) { per2 = &permfifo[i]; if ((per2->pagesleft&127) == 0) continue; if (per2->sx != per->sx) continue; if (per2->sy != per->sy) continue; if (per2->z != per->z) continue; if (per2->a != per->a) continue; if (tilesizx[per2->picnum] > tilesizx[per->picnum]) continue; if (tilesizy[per2->picnum] > tilesizy[per->picnum]) continue; if (per2->cx1 < per->cx1) continue; if (per2->cy1 < per->cy1) continue; if (per2->cx2 > per->cx2) continue; if (per2->cy2 > per->cy2) continue; per2->pagesleft = 0; } if ((per->z == 65536) && (per->a == 0)) for (i=permtail; i!=permhead; i=((i+1)&(MAXPERMS-1))) { per2 = &permfifo[i]; if ((per2->pagesleft&127) == 0) continue; if (per2->z != 65536) continue; if (per2->a != 0) continue; if (per2->cx1 < per->cx1) continue; if (per2->cy1 < per->cy1) continue; if (per2->cx2 > per->cx2) continue; if (per2->cy2 > per->cy2) continue; if ((per2->sx>>16) < (per->sx>>16)) continue; if ((per2->sy>>16) < (per->sy>>16)) continue; if ((per2->sx>>16)+tilesizx[per2->picnum] > (per->sx>>16)+tilesizx[per->picnum]) continue; if ((per2->sy>>16)+tilesizy[per2->picnum] > (per->sy>>16)+tilesizy[per->picnum]) continue; per2->pagesleft = 0; } } permhead = ((permhead+1)&(MAXPERMS-1)); } } // // makepalookup // void makepalookup(int32_t palnum, char *remapbuf, int8_t r, int8_t g, int8_t b, char dastat) { int32_t i, j, palscale; char *ptr, *ptr2; if (paletteloaded == 0) return; if (palookup[palnum] == NULL) { //Allocate palookup buffer if ((palookup[palnum] = (char *)Bmalloc(numpalookups<<8)) == NULL) allocache((intptr_t *)&palookup[palnum],numpalookups<<8,&permanentlock); } if (dastat == 0) return; if ((r|g|b|63) != 63) return; if ((r|g|b) == 0) { for (i=0; i<256; i++) { ptr = (char *)(FP_OFF(palookup[0])+remapbuf[i]); ptr2 = (char *)(FP_OFF(palookup[palnum])+i); for (j=0; j= MAXBASEPALS) thebasepalcount = MAXBASEPALS - 1; basepaltableptr = thebasepaltable; basepalcount = thebasepalcount; } // // setbrightness // void setbrightness(char dabrightness, uint8_t dapalid, char noapply) { int32_t i, k, j; uint8_t *dapal; // uint32_t lastbright = curbrightness; if (dapalid >= basepalcount) dapalid = 0; curbasepal = dapalid; dapal = basepaltableptr[dapalid]; if (!(noapply&4)) { curbrightness = min(max((int32_t)dabrightness,0),15); // if (lastbright != (unsigned)curbrightness) // vid_gamma = 1.0 + ((float)curbrightness / 10.0); } if (setgamma()) j = curbrightness; else j = 0; for (k=i=0; i<256; i++) { // save palette without any brightness adjustment curpalette[i].r = dapal[i*3+0] << 2; curpalette[i].g = dapal[i*3+1] << 2; curpalette[i].b = dapal[i*3+2] << 2; curpalette[i].f = 0; // brightness adjust the palette curpalettefaded[i].b = britable[j][ curpalette[i].b ]; curpalettefaded[i].g = britable[j][ curpalette[i].g ]; curpalettefaded[i].r = britable[j][ curpalette[i].r ]; curpalettefaded[i].f = 0; } if ((noapply&1) == 0) setpalette(0,256); #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode >= 3) { static uint32_t lastpalettesum = 0; uint32_t newpalettesum = crc32once((uint8_t *)curpalettefaded, sizeof(curpalettefaded)); // only reset the textures if the preserve flag (bit 1 of noapply) is clear and // either (a) the new palette is different to the last, or (b) the brightness // changed and we couldn't set it using hardware gamma if (!(noapply&2) && (newpalettesum != lastpalettesum)) gltexinvalidateall(); if (!(noapply&8) && (newpalettesum != lastpalettesum)) gltexinvalidate8(); #ifdef POLYMER if ((rendmode == 4) && (newpalettesum != lastpalettesum)) polymer_texinvalidate(); #endif lastpalettesum = newpalettesum; } #endif palfadergb.r = palfadergb.g = palfadergb.b = 0; palfadedelta = 0; } static inline palette_t getpal(int32_t col) { if (gammabrightness) return curpalette[col]; else { palette_t p; p.b = britable[curbrightness][ curpalette[col].b ]; p.g = britable[curbrightness][ curpalette[col].g ]; p.r = britable[curbrightness][ curpalette[col].r ]; return p; } } // // setpalettefade // void setpalettefade(char r, char g, char b, char offset) { int32_t i; palette_t p; palfadergb.r = min(63,r) << 2; palfadergb.g = min(63,g) << 2; palfadergb.b = min(63,b) << 2; palfadedelta = min(63,offset) << 2; for (i=0; i<256; i++) { p = getpal(i); curpalettefaded[i].b = p.b + (((palfadergb.b - p.b) * offset) >> 6); curpalettefaded[i].g = p.g + (((palfadergb.g - p.g) * offset) >> 6); curpalettefaded[i].r = p.r + (((palfadergb.r - p.r) * offset) >> 6); curpalettefaded[i].f = 0; } setpalette(0,256); } // // clearview // void clearview(int32_t dacol) { intptr_t p; int32_t y, dx; if (qsetmode != 200) return; #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode >= 3) { palette_t p = getpal(dacol); bglClearColor(((float)p.r)/255.0, ((float)p.g)/255.0, ((float)p.b)/255.0, 0); bglClear(GL_COLOR_BUFFER_BIT); return; } #endif begindrawing(); //{{{ dx = windowx2-windowx1+1; //dacol += (dacol<<8); dacol += (dacol<<16); p = frameplace+ylookup[windowy1]+windowx1; for (y=windowy1; y<=windowy2; y++) { //clearbufbyte((void*)p,dx,dacol); Bmemset((void *)p,dacol,dx); p += ylookup[1]; } enddrawing(); //}}} faketimerhandler(); } // // clearallviews // void clearallviews(int32_t dacol) { if (qsetmode != 200) return; //dacol += (dacol<<8); dacol += (dacol<<16); #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode >= 3) { palette_t p = getpal(dacol); bglViewport(0,0,xdim,ydim); glox1 = -1; bglClearColor(((float)p.r)/255.0, ((float)p.g)/255.0, ((float)p.b)/255.0, 0); bglClear(GL_COLOR_BUFFER_BIT); return; } #endif begindrawing(); //{{{ //clearbufbyte((void*)frameplace,imageSize,0L); Bmemset((void *)frameplace,dacol,imageSize); enddrawing(); //}}} //nextpage(); faketimerhandler(); } // // plotpixel // void plotpixel(int32_t x, int32_t y, char col) { #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode >= 3 && qsetmode == 200) { palette_t p = getpal(col); setpolymost2dview(); // JBF 20040205: more efficient setup // bglBegin(GL_POINTS); // bglColor4ub(p.r,p.g,p.b,255); // bglVertex2i(x,y); // bglEnd(); bglRasterPos4i(x, y, 0, 1); bglDrawPixels(1, 1, GL_RGB, GL_UNSIGNED_BYTE, &p); bglRasterPos4i(0, 0, 0, 1); return; } #endif begindrawing(); //{{{ drawpixel_safe((void *)(ylookup[y]+x+frameplace),(int32_t)col); enddrawing(); //}}} } void plotlines2d(int32_t *xx, int32_t *yy, int32_t numpoints, char col) { int32_t i; #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode >= 3 && qsetmode == 200) { palette_t p = getpal(col); bglBegin(GL_LINE_STRIP); bglColor4ub(p.r, p.g, p.b, 1); for (i=0; i= 3 && qsetmode == 200) return 0; #endif begindrawing(); //{{{ r = readpixel((void *)(ylookup[y]+x+frameplace)); enddrawing(); //}}} return(r); } //MUST USE RESTOREFORDRAWROOMS AFTER DRAWING // // setviewtotile // void setviewtotile(int16_t tilenume, int32_t xsiz, int32_t ysiz) { int32_t i, j; //DRAWROOMS TO TILE BACKUP&SET CODE tilesizx[tilenume] = xsiz; tilesizy[tilenume] = ysiz; bakxsiz[setviewcnt] = xsiz; bakysiz[setviewcnt] = ysiz; bakframeplace[setviewcnt] = frameplace; frameplace = waloff[tilenume]; bakwindowx1[setviewcnt] = windowx1; bakwindowy1[setviewcnt] = windowy1; bakwindowx2[setviewcnt] = windowx2; bakwindowy2[setviewcnt] = windowy2; #ifdef POLYMOST if (setviewcnt == 0) { bakrendmode = rendmode; baktile = tilenume; } rendmode = 0;//2; #endif copybufbyte(&startumost[windowx1],&bakumost[windowx1],(windowx2-windowx1+1)*sizeof(bakumost[0])); copybufbyte(&startdmost[windowx1],&bakdmost[windowx1],(windowx2-windowx1+1)*sizeof(bakdmost[0])); setviewcnt++; offscreenrendering = 1; setview(0,0,ysiz-1,xsiz-1); setaspect(65536,65536); j = 0; for (i=0; i<=xsiz; i++) { ylookup[i] = j, j += ysiz; } setvlinebpl(ysiz); } // // setviewback // extern char modechange; void setviewback(void) { int32_t i, j, k; if (setviewcnt <= 0) return; setviewcnt--; offscreenrendering = (setviewcnt>0); #ifdef POLYMOST if (setviewcnt == 0) { rendmode = bakrendmode; invalidatetile(baktile,-1,-1); } #endif setview(bakwindowx1[setviewcnt],bakwindowy1[setviewcnt], bakwindowx2[setviewcnt],bakwindowy2[setviewcnt]); copybufbyte(&bakumost[windowx1],&startumost[windowx1],(windowx2-windowx1+1)*sizeof(startumost[0])); copybufbyte(&bakdmost[windowx1],&startdmost[windowx1],(windowx2-windowx1+1)*sizeof(startdmost[0])); frameplace = bakframeplace[setviewcnt]; if (setviewcnt == 0) k = bakxsiz[0]; else k = max(bakxsiz[setviewcnt-1],bakxsiz[setviewcnt]); j = 0; for (i=0; i<=k; i++) ylookup[i] = j, j += bytesperline; setvlinebpl(bytesperline); modechange=1; } // // squarerotatetile // void squarerotatetile(int16_t tilenume) { int32_t siz; //supports square tiles only for rotation part if ((siz = tilesizx[tilenume]) == tilesizy[tilenume]) { int32_t i = siz-1; for (; i>=0; i--) { int32_t j=(i>>1)-1; char *ptr1 = (char *)(waloff[tilenume]+i*(siz+1)), *ptr2 = ptr1; if (i&1) swapchar(--ptr1, (ptr2 -= siz)); for (; j>=0; j--) swapchar2((ptr1 -= 2), (ptr2 -= (siz<<1)), siz); } } } // // preparemirror // void preparemirror(int32_t dax, int32_t day, int32_t daz, int16_t daang, int32_t dahoriz, int16_t dawall, int16_t dasector, int32_t *tposx, int32_t *tposy, int16_t *tang) { int32_t i, j, x, y, dx, dy; UNREFERENCED_PARAMETER(daz); UNREFERENCED_PARAMETER(dahoriz); UNREFERENCED_PARAMETER(dasector); x = wall[dawall].x; dx = wall[wall[dawall].point2].x-x; y = wall[dawall].y; dy = wall[wall[dawall].point2].y-y; j = dx*dx + dy*dy; if (j == 0) return; i = (((dax-x)*dx + (day-y)*dy)<<1); *tposx = (x<<1) + scale(dx,i,j) - dax; *tposy = (y<<1) + scale(dy,i,j) - day; *tang = (((getangle(dx,dy)<<1)-daang)&2047); inpreparemirror = 1; } // // completemirror // void completemirror(void) { int32_t i, dy; intptr_t p; #ifdef POLYMOST if (rendmode) return; #endif //Can't reverse with uninitialized data if (inpreparemirror) { inpreparemirror = 0; return; } if (mirrorsx1 > 0) mirrorsx1--; if (mirrorsx2 < windowx2-windowx1-1) mirrorsx2++; if (mirrorsx2 < mirrorsx1) return; begindrawing(); p = frameplace+ylookup[windowy1+mirrorsy1]+windowx1+mirrorsx1; i = windowx2-windowx1-mirrorsx2-mirrorsx1; mirrorsx2 -= mirrorsx1; for (dy=mirrorsy2-mirrorsy1-1; dy>=0; dy--) { copybufbyte((void *)(p+1),tempbuf,mirrorsx2+1); tempbuf[mirrorsx2] = tempbuf[mirrorsx2-1]; copybufreverse(&tempbuf[mirrorsx2],(void *)(p+i),mirrorsx2+1); p += ylookup[1]; faketimerhandler(); } enddrawing(); } // // sectorofwall // int32_t sectorofwall(int16_t theline) { int32_t i, gap; if ((theline < 0) || (theline >= numwalls)) return(-1); i = wall[theline].nextwall; if (i >= 0 && i < MAXWALLS) return(wall[i].nextsector); gap = (numsectors>>1); i = gap; while (gap > 1) { gap >>= 1; if (sector[i].wallptr < theline) i += gap; else i -= gap; } while (sector[i].wallptr > theline) i--; while (sector[i].wallptr+sector[i].wallnum <= theline) i++; return(i); } // // getceilzofslope // int32_t getceilzofslope(int16_t sectnum, int32_t dax, int32_t day) { if (!(sector[sectnum].ceilingstat&2)) return(sector[sectnum].ceilingz); { int32_t dx, dy, i, j; walltype *wal; wal = &wall[sector[sectnum].wallptr]; dx = wall[wal->point2].x-wal->x; dy = wall[wal->point2].y-wal->y; i = (nsqrtasm(dx*dx+dy*dy)<<5); if (i == 0) return(sector[sectnum].ceilingz); j = dmulscale3(dx,day-wal->y,-dy,dax-wal->x); return(sector[sectnum].ceilingz+(scale(sector[sectnum].ceilingheinum,j>>1,i)<<1)); } } // // getflorzofslope // int32_t getflorzofslope(int16_t sectnum, int32_t dax, int32_t day) { if (!(sector[sectnum].floorstat&2)) return(sector[sectnum].floorz); { int32_t dx, dy, i, j; walltype *wal; wal = &wall[sector[sectnum].wallptr]; dx = wall[wal->point2].x-wal->x; dy = wall[wal->point2].y-wal->y; i = (nsqrtasm(dx*dx+dy*dy)<<5); if (i == 0) return(sector[sectnum].floorz); j = dmulscale3(dx,day-wal->y,-dy,dax-wal->x); return(sector[sectnum].floorz+(scale(sector[sectnum].floorheinum,j>>1,i)<<1)); } } // // getzsofslope // void getzsofslope(int16_t sectnum, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz) { int32_t dx, dy, i, j; walltype *wal, *wal2; sectortype *sec; sec = §or[sectnum]; *ceilz = sec->ceilingz; *florz = sec->floorz; if ((sec->ceilingstat|sec->floorstat)&2) { wal = &wall[sec->wallptr]; wal2 = &wall[wal->point2]; dx = wal2->x-wal->x; dy = wal2->y-wal->y; i = (nsqrtasm(dx*dx+dy*dy)<<5); if (i == 0) return; j = dmulscale3(dx,day-wal->y,-dy,dax-wal->x); if (sec->ceilingstat&2) *ceilz = (*ceilz)+(scale(sec->ceilingheinum,j>>1,i)<<1); if (sec->floorstat&2) *florz = (*florz)+(scale(sec->floorheinum,j>>1,i)<<1); } } // // alignceilslope // void alignceilslope(int16_t dasect, int32_t x, int32_t y, int32_t z) { int32_t i, dax, day; walltype *wal; wal = &wall[sector[dasect].wallptr]; dax = wall[wal->point2].x-wal->x; day = wall[wal->point2].y-wal->y; i = (y-wal->y)*dax - (x-wal->x)*day; if (i == 0) return; sector[dasect].ceilingheinum = scale((z-sector[dasect].ceilingz)<<8, nsqrtasm(dax*dax+day*day),i); if (sector[dasect].ceilingheinum == 0) sector[dasect].ceilingstat &= ~2; else sector[dasect].ceilingstat |= 2; } // // alignflorslope // void alignflorslope(int16_t dasect, int32_t x, int32_t y, int32_t z) { int32_t i, dax, day; walltype *wal; wal = &wall[sector[dasect].wallptr]; dax = wall[wal->point2].x-wal->x; day = wall[wal->point2].y-wal->y; i = (y-wal->y)*dax - (x-wal->x)*day; if (i == 0) return; sector[dasect].floorheinum = scale((z-sector[dasect].floorz)<<8, nsqrtasm(dax*dax+day*day),i); if (sector[dasect].floorheinum == 0) sector[dasect].floorstat &= ~2; else sector[dasect].floorstat |= 2; } // // loopnumofsector // int32_t loopnumofsector(int16_t sectnum, int16_t wallnum) { int32_t i, numloops, startwall, endwall; numloops = 0; startwall = sector[sectnum].wallptr; endwall = startwall + sector[sectnum].wallnum; for (i=startwall; i= startwall+danumwalls)) return; tmpwall = Bmalloc(danumwalls * sizeof(walltype)); if (!tmpwall) { initprintf("setfirstwall: OUT OF MEMORY!\n"); return; } Bmemcpy(tmpwall, &wall[startwall], danumwalls*sizeof(walltype)); // for (i=0; i 0) { j = 0; while (loopnumofsector(sectnum,j+startwall) != dagoalloop) j++; for (i=0; i= danumwalls) k -= danumwalls; Bmemcpy(&wall[startwall+i], &tmpwall[k], sizeof(walltype)); wall[startwall+i].point2 += danumwalls-startwall-j; if (wall[startwall+i].point2 >= danumwalls) wall[startwall+i].point2 -= danumwalls; wall[startwall+i].point2 += startwall; } newfirstwall += danumwalls-j; if (newfirstwall >= startwall+danumwalls) newfirstwall -= danumwalls; } for (i=0; i= numwallsofloop) k -= numwallsofloop; Bmemcpy(&wall[startwall+i], &tmpwall[k], sizeof(walltype)); wall[startwall+i].point2 += numwallsofloop-newfirstwall; if (wall[startwall+i].point2 >= numwallsofloop) wall[startwall+i].point2 -= numwallsofloop; wall[startwall+i].point2 += startwall; } for (i=startwall; i= 0) wall[wall[i].nextwall].nextwall = i; Bfree(tmpwall); } // // drawline256 // void drawline256(int32_t x1, int32_t y1, int32_t x2, int32_t y2, char col) { int32_t dx, dy, i, j, inc, plc, daend; intptr_t p; col = palookup[0][col]; #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode >= 3) { palette_t p; if (gammabrightness) p = curpalette[col]; else { p.r = britable[curbrightness][ curpalette[col].r ]; p.g = britable[curbrightness][ curpalette[col].g ]; p.b = britable[curbrightness][ curpalette[col].b ]; } setpolymost2dview(); // JBF 20040205: more efficient setup //bglEnable(GL_BLEND); // When using line antialiasing, this is needed bglBegin(GL_LINES); bglColor4ub(p.r,p.g,p.b,255); bglVertex2f((float)x1/4096.0,(float)y1/4096.0); bglVertex2f((float)x2/4096.0,(float)y2/4096.0); bglEnd(); //bglDisable(GL_BLEND); return; } #endif dx = x2-x1; dy = y2-y1; if (dx >= 0) { if ((x1 >= wx2) || (x2 < wx1)) return; if (x1 < wx1) y1 += scale(wx1-x1,dy,dx), x1 = wx1; if (x2 > wx2) y2 += scale(wx2-x2,dy,dx), x2 = wx2; } else { if ((x2 >= wx2) || (x1 < wx1)) return; if (x2 < wx1) y2 += scale(wx1-x2,dy,dx), x2 = wx1; if (x1 > wx2) y1 += scale(wx2-x1,dy,dx), x1 = wx2; } if (dy >= 0) { if ((y1 >= wy2) || (y2 < wy1)) return; if (y1 < wy1) x1 += scale(wy1-y1,dx,dy), y1 = wy1; if (y2 > wy2) x2 += scale(wy2-y2,dx,dy), y2 = wy2; } else { if ((y2 >= wy2) || (y1 < wy1)) return; if (y2 < wy1) x2 += scale(wy1-y2,dx,dy), y2 = wy1; if (y1 > wy2) x1 += scale(wy2-y1,dx,dy), y1 = wy2; } if (klabs(dx) >= klabs(dy)) { if (dx == 0) return; if (dx < 0) { i = x1; x1 = x2; x2 = i; i = y1; y1 = y2; y2 = i; } inc = divscale12(dy,dx); plc = y1+mulscale12((2047-x1)&4095,inc); i = ((x1+2048)>>12); daend = ((x2+2048)>>12); begindrawing(); //{{{ for (; i>12); if ((j >= startumost[i]) && (j < startdmost[i])) drawpixel_safe((void *)(frameplace+ylookup[j]+i),col); plc += inc; } enddrawing(); //}}} } else { if (dy < 0) { i = x1; x1 = x2; x2 = i; i = y1; y1 = y2; y2 = i; } inc = divscale12(dx,dy); plc = x1+mulscale12((2047-y1)&4095,inc); i = ((y1+2048)>>12); daend = ((y2+2048)>>12); begindrawing(); //{{{ p = ylookup[i]+frameplace; for (; i>12); if ((i >= startumost[j]) && (i < startdmost[j])) drawpixel_safe((void *)(j+p),col); plc += inc; p += ylookup[1]; } enddrawing(); //}}} } } //static void attach_here() {} // // drawline16 // // JBF: Had to add extra tests to make sure x-coordinates weren't winding up -'ve // after clipping or crashes would ensue uint32_t drawlinepat = 0xffffffff; int32_t drawline16(int32_t x1, int32_t y1, int32_t x2, int32_t y2, char col) { int32_t i, dx, dy, pinc, d; uint32_t patc=0; intptr_t p; //int32_t odx,ody; //int32_t ox1=x1,oy1=y1, ox2=x2,oy2=y2; dx = x2-x1; dy = y2-y1; //odx=dx; //ody=dy; if (dx >= 0) { if (x1 >= xres || x2 < 0) return 0; if (x1 < 0) { if (dy) y1 += scale(0-x1,dy,dx); x1 = 0; } if (x2 >= xres) { if (dy) y2 += scale(xres-1-x2,dy,dx); x2 = xres-1; } } else { if (x2 >= xres || x1 < 0) return 0; if (x2 < 0) { if (dy) y2 += scale(0-x2,dy,dx); x2 = 0; } if (x1 >= xres) { if (dy) y1 += scale(xres-1-x1,dy,dx); x1 = xres-1; } } if (dy >= 0) { if (y1 >= ydim16 || y2 < 0) return 0; if (y1 < 0) { if (dx) x1 += scale(0-y1,dx,dy); y1 = 0; x1 = clamp(x1, 0, xres-1); } if (y2 >= ydim16) { if (dx) x2 += scale(ydim16-1-y2,dx,dy); y2 = ydim16-1; x2 = clamp(x2, 0, xres-1); } } else { if (y2 >= ydim16 || y1 < 0) return 0; if (y2 < 0) { if (dx) x2 += scale(0-y2,dx,dy); y2 = 0; x2 = clamp(x2, 0, xres-1); } if (y1 >= ydim16) { if (dx) x1 += scale(ydim16-1-y1,dx,dy); y1 = ydim16-1; x1 = clamp(x1, 0, xres-1); } } //if (ox1||ox2||oy1||oy2) // if (x1<0||x1>=xres || y2<0||y2>=yres) // attach_here(); dx = klabs(x2-x1)+1; dy = klabs(y2-y1)+1; if (dx >= dy) { if (x2 < x1) { i = x1; x1 = x2; x2 = i; i = y1; y1 = y2; y2 = i; } d = 0; if (y2 > y1) pinc = bytesperline; else pinc = -bytesperline; begindrawing(); //{{{ p = (y1*bytesperline)+x1+frameplace; if (dy == 0 && drawlinepat == 0xffffffff) { i = ((int32_t)col<<24)|((int32_t)col<<16)|((int32_t)col<<8)|col; clearbufbyte((void *)p, dx, i); } else for (i=dx; i>0; i--) { if (drawlinepat & pow2long[(patc++)&31]) drawpixel((char *)p, col); d += dy; if (d >= dx) { d -= dx; p += pinc; } p++; } enddrawing(); //}}} return 1; } if (y2 < y1) { i = x1; x1 = x2; x2 = i; i = y1; y1 = y2; y2 = i; } d = 0; if (x2 > x1) pinc = 1; else pinc = -1; begindrawing(); //{{{ p = (y1*bytesperline)+x1+frameplace; for (i=dy; i>0; i--) { if (drawlinepat & pow2long[(patc++)&31]) drawpixel((char *)p, col); d += dx; if (d >= dy) { d -= dy; p += pinc; } p += bytesperline; } enddrawing(); //}}} return 1; } static void drawline16mid(int32_t x1, int32_t y1, int32_t x2, int32_t y2, char col) { drawline16(halfxdim16+x1,midydim16+y1, halfxdim16+x2,midydim16+y2, col); } // eccen: eccentricity of the ellipse, // 16384: circle // <16384: shrink in y // >16384: grow in y void drawcircle16(int32_t x1, int32_t y1, int32_t r, int32_t eccen, char col) { if (eccen==16384) { intptr_t p; int32_t xp, yp, xpbpl, ypbpl, d, de, dse, patc=0; if (r < 0) r = -r; if (x1+r < 0 || x1-r >= xres) return; if (y1+r < 0 || y1-r >= ydim16) return; /* * d * 6 | 7 * \ | / * 5 \|/ 8 * c----+----a * 4 /|\ 1 * / | \ * 3 | 2 * b */ xp = 0; yp = r; d = 1 - r; de = 2; dse = 5 - (r << 1); begindrawing(); p = (y1*bytesperline)+x1+frameplace; if (drawlinepat & pow2long[(patc++)&31]) { if ((uint32_t)y1 < (uint32_t)ydim16 && (uint32_t)(x1+r) < (uint32_t)xres) drawpixel_safe((char *)(p+r), col); // a if ((uint32_t)x1 < (uint32_t)xres && (uint32_t)(y1+r) < (uint32_t)ydim16) drawpixel_safe((char *)(p+(r*bytesperline)), col); // b if ((uint32_t)y1 < (uint32_t)ydim16 && (uint32_t)(x1-r) < (uint32_t)xres) drawpixel_safe((char *)(p-r), col); // c if ((uint32_t)x1 < (uint32_t)xres && (uint32_t)(y1-r) < (uint32_t)ydim16) drawpixel_safe((char *)(p-(r*bytesperline)), col); // d } do { if (d < 0) { d += de; de += 2; dse += 2; xp++; } else { d += dse; de += 2; dse += 4; xp++; yp--; } ypbpl = yp*bytesperline; xpbpl = xp*bytesperline; if (drawlinepat & pow2long[(patc++)&31]) { if ((uint32_t)(x1+yp) < (uint32_t)xres && (uint32_t)(y1+xp) < (uint32_t)ydim16) drawpixel_safe((char *)(p+yp+xpbpl), col); // 1 if ((uint32_t)(x1+xp) < (uint32_t)xres && (uint32_t)(y1+yp) < (uint32_t)ydim16) drawpixel_safe((char *)(p+xp+ypbpl), col); // 2 if ((uint32_t)(x1-xp) < (uint32_t)xres && (uint32_t)(y1+yp) < (uint32_t)ydim16) drawpixel_safe((char *)(p-xp+ypbpl), col); // 3 if ((uint32_t)(x1-yp) < (uint32_t)xres && (uint32_t)(y1+xp) < (uint32_t)ydim16) drawpixel_safe((char *)(p-yp+xpbpl), col); // 4 if ((uint32_t)(x1-yp) < (uint32_t)xres && (uint32_t)(y1-xp) < (uint32_t)ydim16) drawpixel_safe((char *)(p-yp-xpbpl), col); // 5 if ((uint32_t)(x1-xp) < (uint32_t)xres && (uint32_t)(y1-yp) < (uint32_t)ydim16) drawpixel_safe((char *)(p-xp-ypbpl), col); // 6 if ((uint32_t)(x1+xp) < (uint32_t)xres && (uint32_t)(y1-yp) < (uint32_t)ydim16) drawpixel_safe((char *)(p+xp-ypbpl), col); // 7 if ((uint32_t)(x1+yp) < (uint32_t)xres && (uint32_t)(y1-xp) < (uint32_t)ydim16) drawpixel_safe((char *)(p+yp-xpbpl), col); // 8 } } while (yp > xp); enddrawing(); } else { // JonoF's rough approximation of a circle int32_t l,spx,spy,lpx,lpy,px,py; spx = lpx = x1 + mulscale14(r,sintable[0]); spy = lpy = y1 + mulscale14(eccen, mulscale14(r,sintable[512])); for (l=64; l<2048; l+=64) { px = x1 + mulscale14(r,sintable[l]); py = y1 + mulscale14(eccen, mulscale14(r,sintable[(l+512)&2047])); drawline16(lpx,lpy,px,py,col); lpx = px; lpy = py; } drawline16(lpx,lpy,spx,spy,col); } } // // qsetmode640350 // void qsetmode640350(void) { if (qsetmode != 350) { if (setvideomode(640, 350, 8, fullscreen) < 0) { //fprintf(stderr, "Couldn't set 640x350 video mode for some reason.\n"); return; } xdim = xres; ydim = yres; // setvgapalette(); ydim16 = 350; halfxdim16 = 320; midydim16 = 146; begindrawing(); //{{{ clearbuf((char *)frameplace, (bytesperline*350L) >> 2, 0); enddrawing(); //}}} } qsetmode = 350; } // // qsetmode640480 // void qsetmode640480(void) { if (qsetmode != 480) { if (setvideomode(640, 480, 8, fullscreen) < 0) { //fprintf(stderr, "Couldn't set 640x480 video mode for some reason.\n"); return; } xdim = xres; ydim = yres; // setvgapalette(); ydim16 = 336; halfxdim16 = 320; midydim16 = 200; begindrawing(); //{{{ clearbuf((char *)(frameplace + (336l*bytesperline)), (bytesperline*144L) >> 2, 0x08080808l); clearbuf((char *)frameplace, (bytesperline*336L) >> 2, 0L); enddrawing(); //}}} } qsetmode = 480; } // // qsetmodeany // void qsetmodeany(int32_t daxdim, int32_t daydim) { if (daxdim < 640) daxdim = 640; if (daydim < 480) daydim = 480; if (qsetmode != ((daxdim<<16)|(daydim&0xffff))) { if (setvideomode(daxdim, daydim, 8, fullscreen) < 0) return; xdim = xres; ydim = yres; // setvgapalette(); ydim16 = yres - STATUS2DSIZ2; halfxdim16 = xres >> 1; midydim16 = ydim16 >> 1; // scale(200,yres,480); begindrawing(); //{{{ clearbuf((char *)(frameplace + (ydim16*bytesperline)), (bytesperline*STATUS2DSIZ2) >> 2, 0x08080808l); clearbuf((char *)frameplace, (ydim16*bytesperline) >> 2, 0L); enddrawing(); //}}} } qsetmode = ((daxdim<<16)|(daydim&0xffff)); } // // clear2dscreen // void clear2dscreen(void) { int32_t clearsz; begindrawing(); //{{{ if (qsetmode == 350) clearsz = 350; else { if (ydim16 <= yres-STATUS2DSIZ2) clearsz = yres - STATUS2DSIZ2; else clearsz = yres; } clearbuf((char *)frameplace, (bytesperline*clearsz) >> 2, 0); enddrawing(); //}}} } ////////// editor side view ////////// inline int32_t scalescreeny(int32_t sy) { if (m32_sideview) return mulscale14(sy, m32_sidesin); else return sy; } // return screen coordinates for BUILD coords x and y (relative to current position) void screencoords(int32_t *xres, int32_t *yres, int32_t x, int32_t y, int32_t zoome) { if (m32_sideview) rotatepoint(0,0, x,y, m32_sideang, &x,&y); *xres = mulscale14(x,zoome); *yres = scalescreeny(mulscale14(y,zoome)); } #if 0 void invscreencoords(int32_t *dx, int32_t *dy, int32_t sx, int32_t sy, int32_t zoome) { if (m32_sidesin==0 || zoome==0) { *dx=0; *dy=0; return; } sy = divscale14(divscale14(sy, m32_sidesin), zoome); sx = divscale14(sx, zoome); rotatepoint(0,0, sx,sy, -m32_sideang, dx,dy); } #endif // invscreencoords with sx==0 and sy==getscreenvdisp(dz, zoom) int32_t getinvdisplacement(int32_t *dx, int32_t *dy, int32_t dz) { if (m32_sidesin==0) return 1; dz = (((int64_t)dz * (int64_t)m32_sidecos)/(int64_t)m32_sidesin)>>4; rotatepoint(0,0, 0,dz, -m32_sideang, dx,dy); return 0; } // return vertical screen coordinate displacement for BUILD z coord inline int32_t getscreenvdisp(int32_t bz, int32_t zoome) { return mulscale32(bz,zoome*m32_sidecos); } void setup_sideview_sincos() { if (m32_sideview) { m32_viewplane.x = 0; m32_viewplane.y = -512; m32_sidesin = sintable[m32_sideelev&2047]; m32_sidecos = sintable[(m32_sideelev+512)&2047]; rotatepoint(0,0, m32_viewplane.x,m32_viewplane.y, -m32_sideang, &m32_viewplane.x,&m32_viewplane.y); m32_viewplane.x = mulscale14(m32_viewplane.x, m32_sidecos); m32_viewplane.y = mulscale14(m32_viewplane.y, m32_sidecos); m32_viewplane.z = m32_sidesin>>5; } } static void sideview_getdist(int16_t sw, int16_t sect) { vec3_t *p; vec3_t v; if (sw>1; v.y = (wall[sw].y + wall[wall[sw].point2].y)>>1; v.z = getflorzofslope(sect, v.x, v.y); p = &v; } else p = (vec3_t *)&sprite[sw-MAXWALLS]; m32_sidedist[sw] = p->x*m32_viewplane.x + p->y*m32_viewplane.y + (p->z>>4)*m32_viewplane.z; } static int sideview_cmppoints(const int16_t *sw1, const int16_t *sw2) { int32_t dist1 = m32_sidedist[*sw1]; int32_t dist2 = m32_sidedist[*sw2]; if (dist2>dist1) return 1; else if (dist1>dist2) return -1; // if (*sw1=0) - (wall[*sw1].nextwall>=0); return 0; } // // draw2dgrid // void draw2dgrid(int32_t posxe, int32_t posye, int32_t posze, int16_t cursectnum, int16_t ange, int32_t zoome, int16_t gride) { int64_t i, xp1, yp1, xp2=0, yp2, tempy; UNREFERENCED_PARAMETER(ange); if (gride <= 0) return; begindrawing(); //{{{ if (m32_sideview) { int32_t sx1,sy1, sx2,sy2, dx=0,dy=0; int32_t xinc=0, yinc=2048>>gride, yofs; // yofs = getscreenvdisp((yinc-posze)&((yinc<<4)-1), zoome); if (cursectnum<0 || cursectnum>=numsectors) yofs = getscreenvdisp(-posze, zoome); else yofs = getscreenvdisp(getflorzofslope(cursectnum, posxe,posye)-posze, zoome); while (scalescreeny(mulscale14(yinc, zoome))==0 && gride>2) { gride--; yinc = 2048>>gride; } xp2 = xp1 = ((posxe+(1024>>gride))&(((int64_t)(-1))<<(11-gride))); yp2 = yp1 = ((posye+(1024>>gride))&(((int64_t)(-1))<<(11-gride))); do { if (xinc==0) { screencoords(&sx1,&sy1, -editorgridextent-posxe,yp2-posye, zoome); if (yp2 == yp1) { screencoords(&sx2,&sy2, editorgridextent-posxe,yp2-posye, zoome); dx = sx2-sx1; dy = sy2-sy1; } yp2 += yinc; } else // if (yinc==0) { screencoords(&sx1,&sy1, xp2-posxe, -editorgridextent-posye, zoome); if (xp2 == xp1) { screencoords(&sx2,&sy2, xp2-posxe, editorgridextent-posye, zoome); dx = sx2-sx1; dy = sy2-sy1; } xp2 += xinc; } i = drawline16(halfxdim16+sx1,midydim16+sy1+yofs, halfxdim16+sx1+dx,midydim16+sy1+dy+yofs, whitecol-25); if (i==0 || (xp2<-editorgridextent || xp2>editorgridextent || yp2<-editorgridextent || yp2>editorgridextent)) { xp2 = xp1; yp2 = yp1; i = 1; if (yinc>0) yinc *= -1; else if (yinc<0) { xinc = -yinc; yinc = 0; } else if (xinc>0) xinc *= -1; else // if (xinc<0) i = 0; } } while (i); } else { // vertical lines yp1 = midydim16-mulscale14(posye+editorgridextent,zoome); if (yp1 < 0) yp1 = 0; yp2 = midydim16-mulscale14(posye-editorgridextent,zoome); if (yp2 >= ydim16) yp2 = ydim16-1; if ((yp1 < ydim16) && (yp2 >= 0) && (yp2 >= yp1)) { xp1 = halfxdim16-mulscale14(posxe+editorgridextent,zoome); for (i=-editorgridextent; i<=editorgridextent; i+=(2048>>gride)) { xp2 = xp1; xp1 = halfxdim16-mulscale14(posxe-i,zoome); if (xp1 >= xdim) break; if (xp1 >= 0) { if (xp1 != xp2) drawline16(xp1,yp1,xp1,yp2,whitecol-25); } } if (i >= editorgridextent && xp1 < xdim) xp2 = xp1; if (xp2 >= 0 && xp2 < xdim) drawline16(xp2,yp1, xp2,yp2, whitecol-25); } // horizontal lines xp1 = mulscale14(posxe+editorgridextent,zoome); xp2 = mulscale14(posxe-editorgridextent,zoome); tempy = 0x80000000l; for (i=-editorgridextent; i<=editorgridextent; i+=(2048>>gride)) { yp1 = ((posye-i)*zoome)>>14; if (yp1 != tempy) { if ((yp1 > midydim16-ydim16) && (yp1 <= midydim16)) { drawline16mid(-xp1,-yp1, -xp2,-yp1, whitecol-25); tempy = yp1; } } } } enddrawing(); //}}} } static void drawscreen_drawwall(int32_t i, int32_t posxe, int32_t posye, int32_t posze, int32_t zoome) { const walltype *wal = &wall[i]; int32_t j, x1, y1, x2, y2, dz = 0, dz2 = 0; // intptr_t tempint; char col; int64_t dist,dx,dy; if (editstatus == 0) { if ((show2dwall[i>>3]&pow2char[i&7]) == 0) return; j = wal->nextwall; if ((j >= 0) && (i > j)) if ((show2dwall[j>>3]&pow2char[j&7]) > 0) return; } else { j = wal->nextwall; if (!m32_sideview && (j >= 0) && (i > j)) return; } if (j < 0) { col = 15; if (i == linehighlight) col = (totalclock & 16) ? 15 : 7; } else { col = 33; if ((wal->cstat&1) != 0) col = 5; if (wal->nextwall >= 0 && ((wal->cstat^wall[wal->nextwall].cstat)&1)) col = 2; if ((i == linehighlight) || ((linehighlight >= 0) && (i == wall[linehighlight].nextwall))) if (totalclock & 16) col += (2<<2); } screencoords(&x1,&y1, wal->x-posxe,wal->y-posye, zoome); screencoords(&x2,&y2, wall[wal->point2].x-posxe,wall[wal->point2].y-posye, zoome); dx = wal->x-wall[wal->point2].x; dy = wal->y-wall[wal->point2].y; dist = dx*dx+dy*dy; if (dist > 0xffffffff) { col=9; if (i == linehighlight || ((linehighlight >= 0) && (i == wall[linehighlight].nextwall))) if (totalclock & 16) col -= (2<<2); } else if (showfirstwall && searchsector>=0 && (sector[searchsector].wallptr == i || sector[searchsector].wallptr == wall[i].nextwall)) { col = 14; if (i == linehighlight) if (totalclock & 16) col -= (2<<2); } else if (circlewall >= 0 && (i == circlewall || wal->nextwall == circlewall)) col = 14; if (m32_sideview) { // draw vertical line to neighboring wall int32_t fz, fz2, fzn; int32_t sect=sectorofwall(i); fz = getflorzofslope(sect, wal->x,wal->y); fz2 = getflorzofslope(sect, wall[wal->point2].x,wall[wal->point2].y); dz = getscreenvdisp(fz-posze,zoome); dz2 = getscreenvdisp(fz2-posze,zoome); y1 += dz; y2 += dz2; if (wal->nextwall>=0) { fzn = getflorzofslope(wal->nextsector, wal->x,wal->y)-fz; drawline16mid(x1,y1, x1,y1+getscreenvdisp(fzn,zoome), editorcolors[col]); } } if ((wal->cstat&64) > 0) // if hitscan bit set { int32_t one=(klabs(x2-x1) >= klabs(y2-y1)), no=!one; drawline16mid(x1+no,y1+one, x2+no,y2+one, editorcolors[col]); drawline16mid(x1-no,y1-one, x2-no,y2-one, editorcolors[col]); col += 8; } drawline16mid(x1,y1, x2,y2, editorcolors[col]); if (showheightindicators && !m32_sideview) { int32_t dax,day, k=getangle(x1-x2, y1-y2); //+angofs; screencoords(&dax,&day, ((wal->x+wall[wal->point2].x)>>1)-posxe,((wal->y+wall[wal->point2].y)>>1)-posye, zoome); if (m32_sideview) day += (dz2+dz)>>1; if (wal->nextsector >= 0) { int32_t ii = sector[sectorofwall(i)].floorz; int32_t jj = sector[wal->nextsector].floorz; if (jj == ii && showheightindicators > 1) { int32_t dax3 = mulscale11(sintable[(k+1024)&2047],zoome) / 2560; int32_t day3 = mulscale11(sintable[(k+512)&2047],zoome) / 2560; int32_t dax2 = mulscale11(sintable[(k+2048)&2047],zoome) / 2560; int32_t day2 = mulscale11(sintable[(k+1536)&2047],zoome) / 2560; day2 = scalescreeny(day2); day3 = scalescreeny(day3); drawline16mid(dax+dax3,day+day3, dax+dax2,day+day2, editorcolors[col]); } else if (jj > ii) { int32_t dax2 = mulscale11(sintable[(k+1024)&2047],zoome) / 2560; int32_t day2 = mulscale11(sintable[(k+512)&2047],zoome) / 2560; day2 = scalescreeny(day2); drawline16mid(dax,day, dax+dax2,day+day2, editorcolors[col]); } else if (jj < ii) { int32_t dax2 = mulscale11(sintable[(k+2048)&2047],zoome) / 2560; int32_t day2 = mulscale11(sintable[(k+1536)&2047],zoome) / 2560; day2 = scalescreeny(day2); drawline16mid(dax,day, dax+dax2,day+day2, editorcolors[col]); } } else if (showheightindicators > 1) { int32_t dax2 = mulscale11(sintable[(k+2048)&2047],zoome) / 2560; int32_t day2 = mulscale11(sintable[(k+1536)&2047],zoome) / 2560; day2 = scalescreeny(day2); drawline16mid(dax,day, dax+dax2,day+day2, editorcolors[col]); } } if (zoome >= 256 && editstatus == 1) if ((halfxdim16+x1 >= 2) && (halfxdim16+x1 <= xdim-3) && (midydim16+y1 >= 2) && (midydim16+y1 <= ydim16-3)) { int32_t pointsize = 2; if (i == pointhighlight || ((pointhighlight < MAXWALLS) && (pointhighlight >= 0) && (wall[i].x == wall[pointhighlight].x) && (wall[i].y == wall[pointhighlight].y))) { if (totalclock & 16) pointsize++; } else //if (highlightcnt > 0) { if (show2dwall[i>>3]&pow2char[i&7]) { if (totalclock & 16) pointsize++; } } col = 15; if (m32_sideview) { int16_t nw = wall[i].nextwall; if (nw>=0) { int32_t fz = getflorzofslope(sectorofwall(i), wall[i].x, wall[i].y); int32_t fz2 = getflorzofslope(wall[i].nextsector, wall[i].x, wall[i].y); if (fz < fz2) col = 7; else if (fz==fz2) col = 4; } } // tempint = ((midydim16+y1)*bytesperline)+(halfxdim16+x1)+frameplace; do drawcircle16(halfxdim16+x1, midydim16+y1, pointsize--, 16384, editorcolors[col]); while (pointsize); } } static void drawscreen_drawsprite(int32_t j, int32_t posxe, int32_t posye, int32_t posze, int32_t zoome) { int32_t x1, y1, x2, y2; char col; int16_t hitblocking=(sprite[j].cstat&256), flooraligned=(sprite[j].cstat&32), wallaligned=(sprite[j].cstat&16); int16_t angofs = m32_sideview ? m32_sideang : 0; if (sprite[j].sectnum<0) col = 4; // red else { col = 3; if (spritecol2d[sprite[j].picnum][0]) col = spritecol2d[sprite[j].picnum][0]; else if ((sprite[j].cstat&1) > 0) { col = 5; if (spritecol2d[sprite[j].picnum][1]) col = spritecol2d[sprite[j].picnum][1]; } } if (editstatus == 1) { if ((pointhighlight) >= 16384 && (j+16384 == pointhighlight || (!m32_sideview && ((sprite[j].x == sprite[pointhighlight-16384].x) && (sprite[j].y == sprite[pointhighlight-16384].y))))) { if (totalclock & 32) col += 8; } else // if (highlightcnt > 0) { if (show2dsprite[j>>3]&pow2char[j&7]) if (totalclock & 32) col += 8; } } screencoords(&x1,&y1, sprite[j].x-posxe,sprite[j].y-posye, zoome); // tempint = ((midydim16+y1)*bytesperline)+(halfxdim16+x1)+frameplace; if (m32_sideview) y1 += getscreenvdisp(sprite[j].z-posze,zoome); if ((halfxdim16+x1 >= 0) && (halfxdim16+x1 < xdim) && (midydim16+y1 >= 0) && (midydim16+y1 < ydim16)) { drawcircle16(halfxdim16+x1, midydim16+y1, 4, 16384, editorcolors[col]); x2 = mulscale11(sintable[(sprite[j].ang+angofs+2560)&2047],zoome) / 768; y2 = mulscale11(sintable[(sprite[j].ang+angofs+2048)&2047],zoome) / 768; y2 = scalescreeny(y2); drawline16mid(x1,y1, x1+x2,y1+y2, editorcolors[col]); if (hitblocking) { drawline16mid(x1,y1+1, x1+x2,y1+y2+1, editorcolors[col]); drawline16mid(x1,y1-1, x1+x2,y1+y2-1, editorcolors[col]); drawline16mid(x1-1,y1, x1+x2-1,y1+y2, editorcolors[col]); drawline16mid(x1+1,y1, x1+x2+1,y1+y2, editorcolors[col]); } if (flooraligned) { int32_t fx = mulscale10(mulscale6(tilesizx[sprite[j].picnum], sprite[j].xrepeat),zoome) >> 1; int32_t fy = mulscale10(mulscale6(tilesizy[sprite[j].picnum], sprite[j].yrepeat),zoome) >> 1; int32_t co[4][2], ii, in; int32_t sinang = sintable[(sprite[j].ang+angofs+1536)&2047]; int32_t cosang = sintable[(sprite[j].ang+angofs+1024)&2047]; int32_t r,s; co[0][0] = co[3][0] = -fx; co[0][1] = co[1][1] = -fy; co[1][0] = co[2][0] = fx; co[2][1] = co[3][1] = fy; for (ii=3; ii>=0; ii--) { r = mulscale14(cosang,co[ii][0]) - mulscale14(sinang,co[ii][1]); s = mulscale14(sinang,co[ii][0]) + mulscale14(cosang,co[ii][1]); s = scalescreeny(s); co[ii][0] = r; co[ii][1] = s; } drawlinepat = 0xcfcfcfcf; for (ii=3; ii>=0; ii--) { in = (ii+1)&3; drawline16mid(x1+co[ii][0], y1-co[ii][1], x1+co[in][0], y1-co[in][1], editorcolors[col]); if (hitblocking) { drawline16mid(x1+co[ii][0], y1-co[ii][1]+1, x1+co[in][0], y1-co[in][1]+1, editorcolors[col]); drawline16mid(x1+co[ii][0], y1-co[ii][1]-1, x1+co[in][0], y1-co[in][1]-1, editorcolors[col]); drawline16mid(x1+co[ii][0]+1, y1-co[ii][1], x1+co[in][0]+1, y1-co[in][1], editorcolors[col]); drawline16mid(x1+co[ii][0]-1, y1-co[ii][1], x1+co[in][0]-1, y1-co[in][1], editorcolors[col]); } drawline16mid(x1, y1, x1 + co[in][0], y1 - co[in][1], editorcolors[col]); } drawlinepat = 0xffffffff; } else if (wallaligned) { int32_t fx = mulscale6(tilesizx[sprite[j].picnum], sprite[j].xrepeat); int32_t one=(((sprite[j].ang+angofs+256)&512) == 0), no=!one; x2 = mulscale11(sintable[(sprite[j].ang+angofs+2560)&2047],zoome) / 6144; y2 = mulscale11(sintable[(sprite[j].ang+angofs+2048)&2047],zoome) / 6144; y2 = scalescreeny(y2); drawline16mid(x1,y1, x1+x2,y1+y2, editorcolors[col]); if (!(sprite[j].cstat&64)) // not 1-sided { drawline16mid(x1,y1, x1-x2,y1-y2, editorcolors[col]); if (hitblocking) { drawline16mid(x1-no,y1-one, x1-x2-no,y1-y2-one, editorcolors[col]); drawline16mid(x1+no,y1+one, x1-x2+no,y1-y2+one, editorcolors[col]); } } if (hitblocking) { drawline16mid(x1-no,y1-one, x1+x2-no,y1+y2-one, editorcolors[col]); drawline16mid(x1+no,y1+one, x1+x2+no,y1+y2+one, editorcolors[col]); } x2 = mulscale13(sintable[(sprite[j].ang+angofs+1024)&2047],zoome) * fx / 4096; y2 = mulscale13(sintable[(sprite[j].ang+angofs+512)&2047],zoome) * fx / 4096; y2 = scalescreeny(y2); drawline16mid(x1,y1, x1-x2,y1-y2, editorcolors[col]); drawline16mid(x1,y1, x1+x2,y1+y2, editorcolors[col]); if (hitblocking) { drawline16mid(x1+1,y1, x1+x2+1,y1+y2, editorcolors[col]); drawline16mid(x1-1,y1, x1-x2-1,y1-y2, editorcolors[col]); drawline16mid(x1-1,y1, x1+x2-1,y1+y2, editorcolors[col]); drawline16mid(x1+1,y1, x1-x2+1,y1-y2, editorcolors[col]); drawline16mid(x1,y1-1, x1+x2,y1+y2-1, editorcolors[col]); drawline16mid(x1,y1+1, x1-x2,y1-y2+1, editorcolors[col]); drawline16mid(x1,y1+1, x1+x2,y1+y2+1, editorcolors[col]); drawline16mid(x1,y1-1, x1-x2,y1-y2-1, editorcolors[col]); } } } } // // draw2dscreen // void draw2dscreen(const vec3_t *pos, int16_t cursectnum, int16_t ange, int32_t zoome, int16_t gride) { int32_t i, j, x1, y1; int16_t angofs = m32_sideview ? m32_sideang : 0; int32_t posxe=pos->x, posye=pos->y, posze=pos->z; if (qsetmode == 200) return; setup_sideview_sincos(); if (m32_sideview && !m32_wallsprite) { m32_wallsprite = Bmalloc((MAXWALLS+MAXSPRITES)*sizeof(int16_t)); m32_sidedist = Bmalloc((MAXWALLS+MAXSPRITES)*sizeof(m32_sidedist[0])); if (!m32_wallsprite || !m32_sidedist) { if (m32_wallsprite) Bfree(m32_wallsprite); if (m32_sidedist) { Bfree(m32_sidedist); m32_sidedist=NULL; } initprintf("out of memory!"); m32_sideview = 0; } } begindrawing(); //{{{ if (editstatus == 0) { // faketimerhandler(); clear2dscreen(); // faketimerhandler(); draw2dgrid(posxe,posye,posze,cursectnum,ange,zoome,gride); } faketimerhandler(); m32_swcnt = 0; if (!m32_sideview) for (i=numwalls-1; i>=0; i--) drawscreen_drawwall(i,posxe,posye,posze,zoome); else { for (i=0; i= 256 || editstatus == 0) for (j=0; j>3]&pow2char[j&7]))) { if (!m32_sideview) drawscreen_drawsprite(j,posxe,posye,posze,zoome); else { m32_wallsprite[m32_swcnt++] = MAXWALLS+j; sideview_getdist(MAXWALLS+j, -1); } } faketimerhandler(); if (m32_sideview) { qsort(m32_wallsprite, m32_swcnt, sizeof(int16_t), (int( *)(const void *, const void *))&sideview_cmppoints); for (i=0; i7) return 0; } else if (ypos+7 >= ydim) { ymax = ydim-ypos-1; if (ymax<0) return 0; } if (fontsize & 2) printext16(xpos+1, ypos+1, 0, -1, name, (fontsize & ~2) | 4); if (fontsize & 1) { fontptr = smalltextfont; charxsiz = 4; } else { fontptr = textfont; charxsiz = 8; } begindrawing(); //{{{ for (i=0; name[i]; i++) { if (name[i] == '^') { i++; if (name[i] == 'O') // ^O resets formatting { if (fontsize & 4) continue; col = ocol; backcol = obackcol; continue; } if (isdigit(name[i])) { if (isdigit(name[i+1])) { if (isdigit(name[i+2])) { Bmemcpy(&smallbuf[0],&name[i],3); i += 2; smallbuf[3] = '\0'; } else { Bmemcpy(&smallbuf[0],&name[i],2); i++; smallbuf[2] = '\0'; } } else { smallbuf[0] = name[i]; smallbuf[1] = '\0'; } if (!(fontsize & 4)) col = editorcolors[atol(smallbuf)]; if (name[i+1] == ',' && isdigit(name[i+2])) { i+=2; if (isdigit(name[i+1])) { if (isdigit(name[i+2])) { Bmemcpy(&smallbuf[0],&name[i],3); i += 2; smallbuf[3] = '\0'; } else { Bmemcpy(&smallbuf[0],&name[i],2); i++; smallbuf[2] = '\0'; } } else { smallbuf[0] = name[i]; smallbuf[1] = '\0'; } if (!(fontsize & 4)) backcol = editorcolors[atol(smallbuf)]; } continue; } } if (stx<0) { stx += charxsiz; continue; } letptr = &fontptr[name[i]<<3]; ptr = (char *)(bytesperline*ypos + (stx-(fontsize&1)) + frameplace); for (y=ymin; y<=ymax; y++) { for (x=0; x= xdim) break; if (letptr[y]&pow2char[7-(fontsize&1)-x]) ptr[x] = (uint8_t)col; else if (backcol >= 0) ptr[x] = (uint8_t)backcol; } ptr += bytesperline; } stx += charxsiz; if (stx >= xdim) break; } enddrawing(); //}}} return stx; } // // printext256 // void printext256(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol, const char *name, char fontsize) { int32_t stx, i, x, y, charxsiz; char *fontptr, *letptr, *ptr; stx = xpos; if (fontsize) { fontptr = smalltextfont; charxsiz = 4; } else { fontptr = textfont; charxsiz = 8; } #if defined(POLYMOST) && defined(USE_OPENGL) if (!polymost_printext256(xpos,ypos,col,backcol,name,fontsize)) return; if (rendmode >= 3 && qsetmode == 200) { int32_t xx, yy; int32_t lc=-1; palette_t p=getpal(col), b=getpal(backcol); setpolymost2dview(); bglDisable(GL_ALPHA_TEST); bglDepthMask(GL_FALSE); // disable writing to the z-buffer bglBegin(GL_POINTS); for (i=0; name[i]; i++) { if (name[i] == '^' && isdigit(name[i+1])) { char smallbuf[8]; int32_t bi=0; while (isdigit(name[i+1]) && bi<8) { smallbuf[bi++]=name[i+1]; i++; } smallbuf[bi++]=0; if (col) col = atol(smallbuf); p = getpal(col); continue; } letptr = &fontptr[name[i]<<3]; xx = stx-fontsize; yy = ypos+7 + 2; //+1 is hack! for (y=7; y>=0; y--) { for (x=charxsiz-1; x>=0; x--) { if (letptr[y]&pow2char[7-fontsize-x]) { if (lc!=col) bglColor4ub(p.r,p.g,p.b,255); lc = col; bglVertex2i(xx+x,yy); } else if (backcol >= 0) { if (lc!=backcol) bglColor4ub(b.r,b.g,b.b,255); lc = backcol; bglVertex2i(xx+x,yy); } } yy--; } stx += charxsiz; } bglEnd(); bglDepthMask(GL_TRUE); // re-enable writing to the z-buffer return; } #endif begindrawing(); //{{{ for (i=0; name[i]; i++) { if (name[i] == '^' && isdigit(name[i+1])) { char smallbuf[8]; int32_t bi=0; while (isdigit(name[i+1]) && bi<8) { smallbuf[bi++]=name[i+1]; i++; } smallbuf[bi++]=0; if (col)col = atol(smallbuf); continue; } letptr = &fontptr[name[i]<<3]; ptr = (char *)(ylookup[ypos+7]+(stx-fontsize)+frameplace); for (y=7; y>=0; y--) { for (x=charxsiz-1; x>=0; x--) { if (letptr[y]&pow2char[7-fontsize-x]) ptr[x] = (uint8_t)col; else if (backcol >= 0) ptr[x] = (uint8_t)backcol; } ptr -= ylookup[1]; } stx += charxsiz; } enddrawing(); //}}} } // // screencapture // int32_t screencapture_tga(const char *filename, char inverseit) { int32_t i,j; char *ptr, head[18] = { 0,1,1,0,0,0,1,24,0,0,0,0,0/*wlo*/,0/*whi*/,0/*hlo*/,0/*hhi*/,8,0 }; //char palette[4*256]; char *fn = Bstrdup(filename), *inversebuf; BFILE *fil; do // JBF 2004022: So we don't overwrite existing screenshots { if (capturecount > 9999) return -1; i = Bstrrchr(fn,'.')-fn-4; fn[i++] = ((capturecount/1000)%10)+48; fn[i++] = ((capturecount/100)%10)+48; fn[i++] = ((capturecount/10)%10)+48; fn[i++] = (capturecount%10)+48; i++; fn[i++] = 't'; fn[i++] = 'g'; fn[i++] = 'a'; if ((fil = Bfopen(fn,"rb")) == NULL) break; Bfclose(fil); capturecount++; } while (1); fil = Bfopen(fn,"wb"); if (fil == NULL) { Bfree(fn); return -1; } #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode >= 3 && qsetmode == 200) { head[1] = 0; // no colourmap head[2] = 2; // uncompressed truecolour head[3] = 0; // (low) first colourmap index head[4] = 0; // (high) first colourmap index head[5] = 0; // (low) number colourmap entries head[6] = 0; // (high) number colourmap entries head[7] = 0; // colourmap entry size head[16] = 24; // 24 bits per pixel } #endif head[12] = xdim & 0xff; head[13] = (xdim >> 8) & 0xff; head[14] = ydim & 0xff; head[15] = (ydim >> 8) & 0xff; Bfwrite(head, 18, 1, fil); begindrawing(); //{{{ ptr = (char *)frameplace; // palette first #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode < 3 || (rendmode >= 3 && qsetmode != 200)) { #endif //getpalette(0,256,palette); for (i=0; i<256; i++) { Bfputc(curpalettefaded[i].b, fil); // b Bfputc(curpalettefaded[i].g, fil); // g Bfputc(curpalettefaded[i].r, fil); // r } #if defined(POLYMOST) && defined(USE_OPENGL) } #endif // targa renders bottom to top, from left to right if (inverseit && qsetmode != 200) { inversebuf = (char *)Bmalloc(bytesperline); if (inversebuf) { for (i=ydim-1; i>=0; i--) { copybuf(ptr+i*bytesperline, inversebuf, xdim >> 2); for (j=0; j < (bytesperline>>2); j++)((int32_t *)inversebuf)[j] ^= 0x0f0f0f0fL; Bfwrite(inversebuf, xdim, 1, fil); } Bfree(inversebuf); } } else { #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode >= 3 && qsetmode == 200) { char c; // 24bit inversebuf = (char *)Bmalloc(xdim*ydim*3); if (inversebuf) { bglReadPixels(0,0,xdim,ydim,GL_RGB,GL_UNSIGNED_BYTE,inversebuf); j = xdim*ydim*3; for (i=0; i=0; i--) Bfwrite(ptr+i*bytesperline, xdim, 1, fil); #if defined(POLYMOST) && defined(USE_OPENGL) } #endif } enddrawing(); //}}} Bfclose(fil); OSD_Printf("Saved screenshot to %s\n", fn); Bfree(fn); capturecount++; return(0); } // PCX is nasty, which is why I've lifted these functions from the PCX spec by ZSoft static int32_t writepcxbyte(char colour, char count, BFILE *fp) { if (!count) return 0; if (count == 1 && (colour & 0xc0) != 0xc0) { Bfputc(colour, fp); return 1; } else { Bfputc(0xc0 | count, fp); Bfputc(colour, fp); return 2; } } static void writepcxline(char *buf, int32_t bytes, int32_t step, BFILE *fp) { char ths, last; int32_t srcIndex; char runCount; runCount = 1; last = *buf; for (srcIndex=1; srcIndex 9999) return -1; i = Bstrrchr(fn,'.')-fn-4; fn[i++] = ((capturecount/1000)%10)+48; fn[i++] = ((capturecount/100)%10)+48; fn[i++] = ((capturecount/10)%10)+48; fn[i++] = (capturecount%10)+48; i++; fn[i++] = 'p'; fn[i++] = 'c'; fn[i++] = 'x'; if ((fil = Bfopen(fn,"rb")) == NULL) break; Bfclose(fil); capturecount++; } while (1); fil = Bfopen(fn,"wb"); if (fil == NULL) { Bfree(fn); return -1; } memset(head,0,128); head[0] = 10; head[1] = 5; head[2] = 1; head[3] = 8; head[12] = 72; head[13] = 0; head[14] = 72; head[15] = 0; head[65] = 1; // 8-bit head[68] = 1; #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode >= 3 && qsetmode == 200) { head[65] = 3; // 24-bit } #endif head[8] = (xdim-1) & 0xff; head[9] = ((xdim-1) >> 8) & 0xff; head[10] = (ydim-1) & 0xff; head[11] = ((ydim-1) >> 8) & 0xff; bpl = xdim + (xdim&1); head[66] = bpl & 0xff; head[67] = (bpl >> 8) & 0xff; Bfwrite(head, 128, 1, fil); begindrawing(); //{{{ ptr = (char *)frameplace; // targa renders bottom to top, from left to right if (inverseit && qsetmode != 200) { inversebuf = (char *)Bmalloc(bytesperline); if (inversebuf) { for (i=0; i> 2); for (j=0; j < (bytesperline>>2); j++)((int32_t *)inversebuf)[j] ^= 0x0f0f0f0fL; writepcxline(inversebuf, xdim, 1, fil); } Bfree(inversebuf); } } else { #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode >= 3 && qsetmode == 200) { // 24bit inversebuf = (char *)Bmalloc(xdim*ydim*3); if (inversebuf) { bglReadPixels(0,0,xdim,ydim,GL_RGB,GL_UNSIGNED_BYTE,inversebuf); for (i=ydim-1; i>=0; i--) { writepcxline(inversebuf+i*xdim*3, xdim, 3, fil); writepcxline(inversebuf+i*xdim*3+1, xdim, 3, fil); writepcxline(inversebuf+i*xdim*3+2, xdim, 3, fil); } Bfree(inversebuf); } } else { #endif for (i=0; i= 3 && qsetmode != 200)) { #endif //getpalette(0,256,palette); Bfputc(12,fil); for (i=0; i<256; i++) { Bfputc(curpalettefaded[i].r, fil); // b Bfputc(curpalettefaded[i].g, fil); // g Bfputc(curpalettefaded[i].b, fil); // r } #if defined(POLYMOST) && defined(USE_OPENGL) } #endif Bfclose(fil); OSD_Printf("Saved screenshot to %s\n", fn); Bfree(fn); capturecount++; return(0); } int32_t screencapture(const char *filename, char inverseit) { if (captureformat == 0) return screencapture_tga(filename,inverseit); else return screencapture_pcx(filename,inverseit); } // // setrendermode // int32_t setrendermode(int32_t renderer) { UNREFERENCED_PARAMETER(renderer); #if defined(POLYMOST) && defined(USE_OPENGL) if (bpp == 8) renderer = 0; # ifdef POLYMER else renderer = min(4,max(3,renderer)); if (renderer == 4) { int32_t i; // potentially deferred MD3 postprocessing for (i=0; imdnum==3 && ((md3model_t *)models[i])->head.surfs[0].geometry == NULL) { static int32_t warned=0; if (!warned) { OSD_Printf("Post-processing MD3 models for Polymer. This can take a while...\n"); nextpage(); warned = 1; } if (!md3postload_polymer((md3model_t *)models[i])) OSD_Printf("INTERNAL ERROR: mdmodel %d failed postprocessing!\n", i); if (((md3model_t *)models[i])->head.surfs[0].geometry == NULL) OSD_Printf("INTERNAL ERROR: wtf?\n"); } // else // OSD_Printf("mdmodel %d already postprocessed.\n", i); } if (!polymer_init()) renderer = 3; } # else else renderer = 3; # endif rendmode = renderer; if (rendmode >= 3) glrendmode = rendmode; #endif return 0; } // // setrollangle // #ifdef POLYMOST void setrollangle(int32_t rolla) { UNREFERENCED_PARAMETER(rolla); if (rolla == 0) gtang = 0.0; else gtang = PI * (double)rolla / 1024.0; } #endif // // invalidatetile // pal: pass -1 to invalidate all palettes for the tile, or >=0 for a particular palette // how: pass -1 to invalidate all instances of the tile in texture memory, or a bitfield // bit 0: opaque or masked (non-translucent) texture, using repeating // bit 1: ignored // bit 2: ignored (33% translucence, using repeating) // bit 3: ignored (67% translucence, using repeating) // bit 4: opaque or masked (non-translucent) texture, using clamping // bit 5: ignored // bit 6: ignored (33% translucence, using clamping) // bit 7: ignored (67% translucence, using clamping) // clamping is for sprites, repeating is for walls // void invalidatetile(int16_t tilenume, int32_t pal, int32_t how) { #if defined(POLYMOST) && defined(USE_OPENGL) int32_t numpal, firstpal, np; int32_t hp; if (rendmode < 3) return; if (pal < 0) { numpal = MAXPALOOKUPS; firstpal = 0; } else { numpal = 1; firstpal = pal % MAXPALOOKUPS; } for (hp = 0; hp < 8; hp+=4) { if (!(how & pow2long[hp])) continue; for (np = firstpal; np < firstpal+numpal; np++) { gltexinvalidate(tilenume, np, hp); } } #endif UNREFERENCED_PARAMETER(tilenume); UNREFERENCED_PARAMETER(pal); UNREFERENCED_PARAMETER(how); } // // setpolymost2dview // Sets OpenGL for 2D drawing // void setpolymost2dview(void) { #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode < 3) return; if (gloy1 != -1) { bglViewport(0,0,xres,yres); bglMatrixMode(GL_PROJECTION); bglLoadIdentity(); bglOrtho(0,xres,yres,0,-1,1); bglMatrixMode(GL_MODELVIEW); bglLoadIdentity(); } gloy1 = -1; bglDisable(GL_DEPTH_TEST); bglDisable(GL_TEXTURE_2D); bglDisable(GL_BLEND); #endif } void hash_init(hashtable_t *t) { hash_free(t); t->items=Bcalloc(1, t->size * sizeof(hashitem_t)); } void hash_free(hashtable_t *t) { hashitem_t *cur, *tmp; int32_t i; int32_t num; if (t->items == NULL) return; // initprintf("*free, num:%d\n",t->size); i= t->size-1; do { cur = t->items[i]; num = 0; while (cur) { tmp = cur; cur = cur->next; // initprintf("Free %4d '%s'\n",tmp->key,(tmp->string)?tmp->string:"."); if (tmp->string) { Bfree(tmp->string); tmp->string = NULL; } Bfree(tmp); num++; } // initprintf("#%4d: %3d\t",i,num); } while (--i > -1); Bfree(t->items); t->items = 0; } // djb3 algorithm static inline uint32_t hash_getcode(const char *s) { uint32_t h = 5381; int32_t ch; while ((ch = *s++) != '\0') h = ((h << 5) + h) ^ ch; return h; } void hash_add(hashtable_t *t, const char *s, int32_t key, int32_t replace) { hashitem_t *cur, *prev=NULL; int32_t code; if (t->items == NULL) { initprintf("hash_replace(): table not initialized!\n"); return; } code = hash_getcode(s) % t->size; cur = t->items[code]; if (!cur) { cur = (hashitem_t *)Bcalloc(1,sizeof(hashitem_t)); cur->string = Bstrdup(s); cur->key = key; cur->next = NULL; t->items[code] = cur; return; } do { if (Bstrcmp(s,cur->string) == 0) { if (replace) cur->key = key; return; } prev = cur; } while ((cur = cur->next)); cur = (hashitem_t *)Bcalloc(1,sizeof(hashitem_t)); cur->string = Bstrdup(s); cur->key = key; cur->next = NULL; prev->next = cur; } int32_t hash_find(hashtable_t *t, const char *s) { hashitem_t *cur; if (t->items == NULL) { initprintf("hash_find(): table not initialized!\n"); return -1; } if ((cur = t->items[hash_getcode(s) % t->size]) == NULL) return -1; do if (Bstrcmp(s,cur->string) == 0) return cur->key; while ((cur = cur->next)); return -1; } int32_t hash_findcase(hashtable_t *t, const char *s) { hashitem_t *cur; if (t->items == NULL) { initprintf("hash_findcase(): table not initialized!\n"); return -1; } if ((cur=t->items[hash_getcode(s)%t->size]) == NULL) return -1; do if (Bstrcasecmp(s,cur->string) == 0) return cur->key; while ((cur=cur->next)); return -1; } /* * vim:ts=8: */