mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-16 09:21:36 +00:00
11512 lines
378 KiB
C
11512 lines
378 KiB
C
// "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 "baselayer.h"
|
|
|
|
#ifdef POLYMOST
|
|
# ifdef _WIN32
|
|
# define WIN32_LEAN_AND_MEAN
|
|
# include <windows.h>
|
|
# endif
|
|
# ifdef USE_OPENGL
|
|
# include "glbuild.h"
|
|
# include "polymer.h"
|
|
# endif
|
|
#endif
|
|
|
|
#include <math.h>
|
|
|
|
#define MAXCLIPNUM 1024
|
|
#define MAXPERMS 512
|
|
#define MAXTILEFILES 256
|
|
#define MAXYSAVES ((MAXXDIM*MAXSPRITES)>>7)
|
|
#define MAXNODESPERLINE 42 //Warning: This depends on MAXYSAVES & MAXYDIM!
|
|
#define MAXWALLSB 2048
|
|
#define MAXCLIPDIST 1024
|
|
|
|
|
|
void *kmalloc(bsize_t size) { return(Bmalloc(size)); }
|
|
#define kkmalloc kmalloc
|
|
|
|
void kfree(void *buffer) { Bfree(buffer); }
|
|
#define kkfree kfree
|
|
|
|
#ifdef SUPERBUILD
|
|
void loadvoxel(long voxindex) { voxindex=0; }
|
|
long tiletovox[MAXTILES];
|
|
long usevoxels = 1;
|
|
#define kloadvoxel loadvoxel
|
|
|
|
long novoxmips = 0;
|
|
long editorgridextent = 131072;
|
|
|
|
//These variables need to be copied into BUILD
|
|
#define MAXXSIZ 256
|
|
#define MAXYSIZ 256
|
|
#define MAXZSIZ 255
|
|
#define MAXVOXMIPS 5
|
|
long voxoff[MAXVOXELS][MAXVOXMIPS]; char voxlock[MAXVOXELS][MAXVOXMIPS];
|
|
long voxscale[MAXVOXELS];
|
|
|
|
static long ggxinc[MAXXSIZ+1], ggyinc[MAXXSIZ+1];
|
|
static long lowrecip[1024], nytooclose, nytoofar;
|
|
static unsigned long distrecip[65536];
|
|
#endif
|
|
|
|
static long *lookups = NULL;
|
|
static char lookupsalloctype = 255;
|
|
long dommxoverlay = 1, beforedrawrooms = 1, indrawroomsandmasks = 0;
|
|
|
|
static long oxdimen = -1, oviewingrange = -1, oxyaspect = -1;
|
|
|
|
long curbrightness = 0, gammabrightness = 0;
|
|
|
|
//Textured Map variables
|
|
static char globalpolytype;
|
|
static short *dotp1[MAXYDIM], *dotp2[MAXYDIM];
|
|
|
|
static unsigned char tempbuf[MAXWALLS];
|
|
|
|
long ebpbak, espbak;
|
|
long slopalookup[16384]; // was 2048
|
|
#if defined(USE_OPENGL)
|
|
static palette_t palookupfog[MAXPALOOKUPS];
|
|
#endif
|
|
|
|
static char permanentlock = 255;
|
|
long artversion, mapversion=7L; // JBF 20040211: default mapversion to 7
|
|
void *pic = NULL;
|
|
char picsiz[MAXTILES], tilefilenum[MAXTILES];
|
|
long lastageclock;
|
|
long tilefileoffs[MAXTILES];
|
|
|
|
long artsize = 0, cachesize = 0;
|
|
|
|
static short radarang[1280], radarang2[MAXXDIM];
|
|
static unsigned short sqrtable[4096], shlookup[4096+256];
|
|
char pow2char[8] = {1,2,4,8,16,32,64,128};
|
|
long pow2long[32] =
|
|
{
|
|
1L,2L,4L,8L,
|
|
16L,32L,64L,128L,
|
|
256L,512L,1024L,2048L,
|
|
4096L,8192L,16384L,32768L,
|
|
65536L,131072L,262144L,524288L,
|
|
1048576L,2097152L,4194304L,8388608L,
|
|
16777216L,33554432L,67108864L,134217728L,
|
|
268435456L,536870912L,1073741824L,2147483647L
|
|
};
|
|
long reciptable[2048], fpuasm;
|
|
|
|
char britable[16][256]; // JBF 20040207: full 8bit precision
|
|
//char textfont[1024], smalltextfont[1024];
|
|
#include "textfont.c"
|
|
#include "smalltextfont.c"
|
|
|
|
static char kensmessage[128];
|
|
char *engineerrstr = "No error";
|
|
|
|
|
|
#if defined(__WATCOMC__) && !defined(NOASM)
|
|
|
|
//
|
|
// Watcom Inline Assembly Routines
|
|
//
|
|
|
|
#pragma aux nsqrtasm =\
|
|
"test eax, 0xff000000",\
|
|
"mov ebx, eax",\
|
|
"jnz short over24",\
|
|
"shr ebx, 12",\
|
|
"mov cx, word ptr shlookup[ebx*2]",\
|
|
"jmp short under24",\
|
|
"over24: shr ebx, 24",\
|
|
"mov cx, word ptr shlookup[ebx*2+8192]",\
|
|
"under24: shr eax, cl",\
|
|
"mov cl, ch",\
|
|
"mov ax, word ptr sqrtable[eax*2]",\
|
|
"shr eax, cl",\
|
|
parm nomemory [eax]\
|
|
modify exact [eax ebx ecx]
|
|
unsigned long nsqrtasm(unsigned long);
|
|
|
|
#pragma aux msqrtasm =\
|
|
"mov eax, 0x40000000",\
|
|
"mov ebx, 0x20000000",\
|
|
"begit: cmp ecx, eax",\
|
|
"jl skip",\
|
|
"sub ecx, eax",\
|
|
"lea eax, [eax+ebx*4]",\
|
|
"skip: sub eax, ebx",\
|
|
"shr eax, 1",\
|
|
"shr ebx, 2",\
|
|
"jnz begit",\
|
|
"cmp ecx, eax",\
|
|
"sbb eax, -1",\
|
|
"shr eax, 1",\
|
|
parm nomemory [ecx]\
|
|
modify exact [eax ebx ecx]
|
|
long msqrtasm(unsigned long);
|
|
|
|
//0x007ff000 is (11<<13), 0x3f800000 is (127<<23)
|
|
#pragma aux krecipasm =\
|
|
"mov fpuasm, eax",\
|
|
"fild dword ptr fpuasm",\
|
|
"add eax, eax",\
|
|
"fstp dword ptr fpuasm",\
|
|
"sbb ebx, ebx",\
|
|
"mov eax, fpuasm",\
|
|
"mov ecx, eax",\
|
|
"and eax, 0x007ff000",\
|
|
"shr eax, 10",\
|
|
"sub ecx, 0x3f800000",\
|
|
"shr ecx, 23",\
|
|
"mov eax, dword ptr reciptable[eax]",\
|
|
"sar eax, cl",\
|
|
"xor eax, ebx",\
|
|
parm [eax]\
|
|
modify exact [eax ebx ecx]
|
|
long krecipasm(long);
|
|
|
|
#pragma aux setgotpic =\
|
|
"mov ebx, eax",\
|
|
"cmp byte ptr walock[eax], 200",\
|
|
"jae skipit",\
|
|
"mov byte ptr walock[eax], 199",\
|
|
"skipit: shr eax, 3",\
|
|
"and ebx, 7",\
|
|
"mov dl, byte ptr gotpic[eax]",\
|
|
"mov bl, byte ptr pow2char[ebx]",\
|
|
"or dl, bl",\
|
|
"mov byte ptr gotpic[eax], dl",\
|
|
parm [eax]\
|
|
modify exact [eax ebx ecx edx]
|
|
void setgotpic(long);
|
|
|
|
#pragma aux getclipmask =\
|
|
"sar eax, 31",\
|
|
"add ebx, ebx",\
|
|
"adc eax, eax",\
|
|
"add ecx, ecx",\
|
|
"adc eax, eax",\
|
|
"add edx, edx",\
|
|
"adc eax, eax",\
|
|
"mov ebx, eax",\
|
|
"shl ebx, 4",\
|
|
"or al, 0xf0",\
|
|
"xor eax, ebx",\
|
|
parm [eax][ebx][ecx][edx]\
|
|
modify exact [eax ebx ecx edx]
|
|
long getclipmask(long,long,long,long);
|
|
|
|
#pragma aux getkensmessagecrc =\
|
|
"xor eax, eax",\
|
|
"mov ecx, 32",\
|
|
"beg: mov edx, dword ptr [ebx+ecx*4-4]",\
|
|
"ror edx, cl",\
|
|
"adc eax, edx",\
|
|
"bswap eax",\
|
|
"loop short beg",\
|
|
parm [ebx]\
|
|
modify exact [eax ebx ecx edx]
|
|
long getkensmessagecrc(long);
|
|
|
|
#elif defined(_MSC_VER) && !defined(NOASM) // __WATCOMC__
|
|
|
|
//
|
|
// Microsoft C Inline Assembly Routines
|
|
//
|
|
|
|
static inline long nsqrtasm(long a)
|
|
{
|
|
_asm {
|
|
push ebx
|
|
mov eax, a
|
|
test eax, 0xff000000
|
|
mov ebx, eax
|
|
jnz short over24
|
|
shr ebx, 12
|
|
mov cx, word ptr shlookup[ebx*2]
|
|
jmp short under24
|
|
over24:
|
|
shr ebx, 24
|
|
mov cx, word ptr shlookup[ebx*2+8192]
|
|
under24:
|
|
shr eax, cl
|
|
mov cl, ch
|
|
mov ax, word ptr sqrtable[eax*2]
|
|
shr eax, cl
|
|
pop ebx
|
|
}
|
|
}
|
|
|
|
static inline long msqrtasm(long c)
|
|
{
|
|
_asm {
|
|
push ebx
|
|
mov ecx, c
|
|
mov eax, 0x40000000
|
|
mov ebx, 0x20000000
|
|
begit:
|
|
cmp ecx, eax
|
|
jl skip
|
|
sub ecx, eax
|
|
lea eax, [eax+ebx*4]
|
|
skip:
|
|
sub eax, ebx
|
|
shr eax, 1
|
|
shr ebx, 2
|
|
jnz begit
|
|
cmp ecx, eax
|
|
sbb eax, -1
|
|
shr eax, 1
|
|
pop ebx
|
|
}
|
|
}
|
|
|
|
//0x007ff000 is (11<<13), 0x3f800000 is (127<<23)
|
|
static inline long krecipasm(long a)
|
|
{
|
|
_asm {
|
|
push ebx
|
|
mov eax, a
|
|
mov fpuasm, eax
|
|
fild dword ptr fpuasm
|
|
add eax, eax
|
|
fstp dword ptr fpuasm
|
|
sbb ebx, ebx
|
|
mov eax, fpuasm
|
|
mov ecx, eax
|
|
and eax, 0x007ff000
|
|
shr eax, 10
|
|
sub ecx, 0x3f800000
|
|
shr ecx, 23
|
|
mov eax, dword ptr reciptable[eax]
|
|
sar eax, cl
|
|
xor eax, ebx
|
|
pop ebx
|
|
}
|
|
}
|
|
|
|
static inline void setgotpic(long a)
|
|
{
|
|
_asm {
|
|
push ebx
|
|
mov eax, a
|
|
mov ebx, eax
|
|
cmp byte ptr walock[eax], 200
|
|
jae skipit
|
|
mov byte ptr walock[eax], 199
|
|
skipit:
|
|
shr eax, 3
|
|
and ebx, 7
|
|
mov dl, byte ptr gotpic[eax]
|
|
mov bl, byte ptr pow2char[ebx]
|
|
or dl, bl
|
|
mov byte ptr gotpic[eax], dl
|
|
pop ebx
|
|
}
|
|
}
|
|
|
|
static inline long getclipmask(long a, long b, long c, long d)
|
|
{
|
|
_asm {
|
|
push ebx
|
|
mov eax, a
|
|
mov ebx, b
|
|
mov ecx, c
|
|
mov edx, d
|
|
sar eax, 31
|
|
add ebx, ebx
|
|
adc eax, eax
|
|
add ecx, ecx
|
|
adc eax, eax
|
|
add edx, edx
|
|
adc eax, eax
|
|
mov ebx, eax
|
|
shl ebx, 4
|
|
or al, 0xf0
|
|
xor eax, ebx
|
|
pop ebx
|
|
}
|
|
}
|
|
|
|
static inline long getkensmessagecrc(void *b)
|
|
{
|
|
_asm {
|
|
push ebx
|
|
mov ebx, b
|
|
xor eax, eax
|
|
mov ecx, 32
|
|
beg:
|
|
mov edx, dword ptr [ebx+ecx*4-4]
|
|
ror edx, cl
|
|
adc eax, edx
|
|
bswap eax
|
|
loop short beg
|
|
pop ebx
|
|
}
|
|
}
|
|
|
|
#elif defined(__GNUC__) && defined(__i386__) && !defined(NOASM) // _MSC_VER
|
|
|
|
//
|
|
// GCC "Inline" Assembly Routines
|
|
//
|
|
|
|
#define nsqrtasm(a) \
|
|
({ long __r, __a=(a); \
|
|
__asm__ __volatile__ ( \
|
|
"testl $0xff000000, %%eax\n\t" \
|
|
"movl %%eax, %%ebx\n\t" \
|
|
"jnz 0f\n\t" \
|
|
"shrl $12, %%ebx\n\t" \
|
|
"movw "ASMSYM("shlookup")"(,%%ebx,2), %%cx\n\t" \
|
|
"jmp 1f\n\t" \
|
|
"0:\n\t" \
|
|
"shrl $24, %%ebx\n\t" \
|
|
"movw ("ASMSYM("shlookup")"+8192)(,%%ebx,2), %%cx\n\t" \
|
|
"1:\n\t" \
|
|
"shrl %%cl, %%eax\n\t" \
|
|
"movb %%ch, %%cl\n\t" \
|
|
"movw "ASMSYM("sqrtable")"(,%%eax,2), %%ax\n\t" \
|
|
"shrl %%cl, %%eax" \
|
|
: "=a" (__r) : "a" (__a) : "ebx", "ecx", "cc"); \
|
|
__r; })
|
|
|
|
// edx is blown by this code somehow?!
|
|
#define msqrtasm(c) \
|
|
({ long __r, __c=(c); \
|
|
__asm__ __volatile__ ( \
|
|
"movl $0x40000000, %%eax\n\t" \
|
|
"movl $0x20000000, %%ebx\n\t" \
|
|
"0:\n\t" \
|
|
"cmpl %%eax, %%ecx\n\t" \
|
|
"jl 1f\n\t" \
|
|
"subl %%eax, %%ecx\n\t" \
|
|
"leal (%%eax,%%ebx,4), %%eax\n\t" \
|
|
"1:\n\t" \
|
|
"subl %%ebx, %%eax\n\t" \
|
|
"shrl $1, %%eax\n\t" \
|
|
"shrl $2, %%ebx\n\t" \
|
|
"jnz 0b\n\t" \
|
|
"cmpl %%eax, %%ecx\n\t" \
|
|
"sbbl $-1, %%eax\n\t" \
|
|
"shrl $1, %%eax" \
|
|
: "=a" (__r) : "c" (__c) : "edx","ebx", "cc"); \
|
|
__r; })
|
|
|
|
#define setgotpic(a) \
|
|
({ long __a=(a); \
|
|
__asm__ __volatile__ ( \
|
|
"movl %%eax, %%ebx\n\t" \
|
|
"cmpb $200, "ASMSYM("walock")"(%%eax)\n\t" \
|
|
"jae 0f\n\t" \
|
|
"movb $199, "ASMSYM("walock")"(%%eax)\n\t" \
|
|
"0:\n\t" \
|
|
"shrl $3, %%eax\n\t" \
|
|
"andl $7, %%ebx\n\t" \
|
|
"movb "ASMSYM("gotpic")"(%%eax), %%dl\n\t" \
|
|
"movb "ASMSYM("pow2char")"(%%ebx), %%bl\n\t" \
|
|
"orb %%bl, %%dl\n\t" \
|
|
"movb %%dl, "ASMSYM("gotpic")"(%%eax)" \
|
|
: "=a" (__a) : "a" (__a) \
|
|
: "ebx", "edx", "memory", "cc"); \
|
|
__a; })
|
|
|
|
#define krecipasm(a) \
|
|
({ long __a=(a); \
|
|
__asm__ __volatile__ ( \
|
|
"movl %%eax, ("ASMSYM("fpuasm")"); fildl ("ASMSYM("fpuasm")"); " \
|
|
"addl %%eax, %%eax; fstps ("ASMSYM("fpuasm")"); sbbl %%ebx, %%ebx; " \
|
|
"movl ("ASMSYM("fpuasm")"), %%eax; movl %%eax, %%ecx; " \
|
|
"andl $0x007ff000, %%eax; shrl $10, %%eax; subl $0x3f800000, %%ecx; " \
|
|
"shrl $23, %%ecx; movl "ASMSYM("reciptable")"(%%eax), %%eax; " \
|
|
"sarl %%cl, %%eax; xorl %%ebx, %%eax" \
|
|
: "=a" (__a) : "a" (__a) : "ebx", "ecx", "memory", "cc"); \
|
|
__a; })
|
|
|
|
#define getclipmask(a,b,c,d) \
|
|
({ long __a=(a), __b=(b), __c=(c), __d=(d); \
|
|
__asm__ __volatile__ ("sarl $31, %%eax; addl %%ebx, %%ebx; adcl %%eax, %%eax; " \
|
|
"addl %%ecx, %%ecx; adcl %%eax, %%eax; addl %%edx, %%edx; " \
|
|
"adcl %%eax, %%eax; movl %%eax, %%ebx; shl $4, %%ebx; " \
|
|
"orb $0xf0, %%al; xorl %%ebx, %%eax" \
|
|
: "=a" (__a), "=b" (__b), "=c" (__c), "=d" (__d) \
|
|
: "a" (__a), "b" (__b), "c" (__c), "d" (__d) : "cc"); \
|
|
__a; })
|
|
|
|
|
|
#define getkensmessagecrc(b) \
|
|
({ long __a, __b=(b); \
|
|
__asm__ __volatile__ ( \
|
|
"xorl %%eax, %%eax\n\t" \
|
|
"movl $32, %%ecx\n\t" \
|
|
"0:\n\t" \
|
|
"movl -4(%%ebx,%%ecx,4), %%edx\n\t" \
|
|
"rorl %%cl, %%edx\n\t" \
|
|
"adcl %%edx, %%eax\n\t" \
|
|
"bswapl %%eax\n\t" \
|
|
"loop 0b" \
|
|
: "=a" (__a) : "b" (__b) : "ecx", "edx" \
|
|
__a; })
|
|
|
|
#else // __GNUC__ && __i386__
|
|
|
|
static inline unsigned long nsqrtasm(unsigned long a)
|
|
{ // JBF 20030901: This was a damn lot simpler to reverse engineer than
|
|
// msqrtasm was. Really, it was just like simplifying an algebra equation.
|
|
unsigned short c;
|
|
|
|
if (a & 0xff000000) { // test eax, 0xff000000 / jnz short over24
|
|
c = shlookup[(a >> 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 long msqrtasm(unsigned long c)
|
|
{
|
|
unsigned long 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 void setgotpic(long tilenume)
|
|
{
|
|
if (walock[tilenume] < 200) walock[tilenume] = 199;
|
|
gotpic[tilenume>>3] |= pow2char[tilenume&7];
|
|
}
|
|
|
|
static inline long krecipasm(long i)
|
|
{ // Ken did this
|
|
float f = (float)i; i = *(long *)&f;
|
|
return((reciptable[(i>>12)&2047]>>(((i-0x3f800000)>>23)&31))^(i>>31));
|
|
}
|
|
|
|
|
|
static inline long getclipmask(long a, long b, long c, long d)
|
|
{ // Ken did this
|
|
d = ((a<0)*8) + ((b<0)*4) + ((c<0)*2) + (d<0);
|
|
return(((d<<4)^0xf0)|d);
|
|
}
|
|
|
|
inline long getkensmessagecrc(long b)
|
|
{
|
|
return 0x56c764d4l;
|
|
b=b;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
static long xb1[MAXWALLSB], yb1[MAXWALLSB], xb2[MAXWALLSB], yb2[MAXWALLSB];
|
|
static long rx1[MAXWALLSB], ry1[MAXWALLSB], rx2[MAXWALLSB], ry2[MAXWALLSB];
|
|
static short p2[MAXWALLSB], thesector[MAXWALLSB], thewall[MAXWALLSB];
|
|
|
|
static short bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB];
|
|
|
|
static short smost[MAXYSAVES], smostcnt;
|
|
static short smoststart[MAXWALLSB];
|
|
static char smostwalltype[MAXWALLSB];
|
|
static long smostwall[MAXWALLSB], smostwallcnt = -1L;
|
|
|
|
static short maskwall[MAXWALLSB], maskwallcnt;
|
|
static long spritesx[MAXSPRITESONSCREEN];
|
|
static long spritesy[MAXSPRITESONSCREEN+1];
|
|
static long spritesz[MAXSPRITESONSCREEN];
|
|
static spritetype *tspriteptr[MAXSPRITESONSCREEN];
|
|
|
|
short umost[MAXXDIM], dmost[MAXXDIM];
|
|
static short bakumost[MAXXDIM], bakdmost[MAXXDIM];
|
|
short uplc[MAXXDIM], dplc[MAXXDIM];
|
|
static short uwall[MAXXDIM], dwall[MAXXDIM];
|
|
static long swplc[MAXXDIM], lplc[MAXXDIM];
|
|
static long swall[MAXXDIM], lwall[MAXXDIM+4];
|
|
long xdimen = -1, xdimenrecip, halfxdimen, xdimenscale, xdimscale;
|
|
long wx1, wy1, wx2, wy2, ydimen;
|
|
long /*viewoffset,*/ frameoffset;
|
|
|
|
static long nrx1[8], nry1[8], nrx2[8], nry2[8]; // JBF 20031206: Thanks Ken
|
|
|
|
static long rxi[8], ryi[8], rzi[8], rxi2[8], ryi2[8], rzi2[8];
|
|
static long xsi[8], ysi[8], *horizlookup=0, *horizlookup2=0, horizycent;
|
|
|
|
long globalposx, globalposy, globalposz, globalhoriz;
|
|
short globalang, globalcursectnum;
|
|
long globalpal, cosglobalang, singlobalang;
|
|
long cosviewingrangeglobalang, sinviewingrangeglobalang;
|
|
char *globalpalwritten;
|
|
long globaluclip, globaldclip, globvis;
|
|
long globalvisibility, globalhisibility, globalpisibility, globalcisibility;
|
|
char globparaceilclip, globparaflorclip;
|
|
|
|
long xyaspect, viewingrangerecip;
|
|
|
|
long asm1, asm2, asm3, asm4;
|
|
long vplce[4], vince[4], palookupoffse[4], bufplce[4];
|
|
char globalxshift, globalyshift;
|
|
long globalxpanning, globalypanning, globalshade;
|
|
short globalpicnum, globalshiftval;
|
|
long globalzd, globalbufplc, globalyscale, globalorientation;
|
|
long globalx1, globaly1, globalx2, globaly2, globalx3, globaly3, globalzx;
|
|
long globalx, globaly, globalz;
|
|
|
|
static short sectorborder[256], sectorbordercnt;
|
|
static char tablesloaded = 0;
|
|
long pageoffset, ydim16, qsetmode = 0;
|
|
long startposx, startposy, startposz;
|
|
short startang, startsectnum;
|
|
short pointhighlight, linehighlight, highlightcnt;
|
|
static long lastx[MAXYDIM];
|
|
char *transluc = NULL, paletteloaded = 0;
|
|
|
|
long halfxdim16, midydim16;
|
|
|
|
#define FASTPALGRIDSIZ 8
|
|
static long rdist[129], gdist[129], bdist[129];
|
|
static char colhere[((FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2))>>3];
|
|
static char colhead[(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)];
|
|
static long colnext[256];
|
|
static char coldist[8] = {0,1,2,3,4,3,2,1};
|
|
static long colscan[27];
|
|
|
|
static short clipnum, hitwalls[4];
|
|
long hitscangoalx = (1<<29)-1, hitscangoaly = (1<<29)-1;
|
|
#ifdef POLYMOST
|
|
static long hitallsprites = 0;
|
|
#endif
|
|
|
|
typedef struct { long x1, y1, x2, y2; } linetype;
|
|
static linetype clipit[MAXCLIPNUM];
|
|
static short clipsectorlist[MAXCLIPNUM], clipsectnum;
|
|
static short clipobjectval[MAXCLIPNUM];
|
|
|
|
typedef struct
|
|
{
|
|
long sx, sy, z;
|
|
short a, picnum;
|
|
signed char dashade;
|
|
char dapalnum, dastat, pagesleft;
|
|
long cx1, cy1, cx2, cy2;
|
|
long uniqid; //JF extension
|
|
} permfifotype;
|
|
static permfifotype permfifo[MAXPERMS];
|
|
static long permhead = 0, permtail = 0;
|
|
|
|
short numscans, numhits, numbunches;
|
|
static short posfil, capturecount = 0, hitcnt;
|
|
|
|
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
|
|
};
|
|
|
|
short editstatus = 0;
|
|
short searchit;
|
|
long searchx = -1, searchy; //search input
|
|
short searchsector, searchwall, searchstat; //search output
|
|
double msens = 1.0;
|
|
|
|
static char artfilename[20];
|
|
static long numtilefiles, artfil = -1, artfilnum, artfilplc;
|
|
|
|
static char inpreparemirror = 0;
|
|
static long mirrorsx1, mirrorsy1, mirrorsx2, mirrorsy2;
|
|
|
|
static long setviewcnt = 0; // interface layers use this now
|
|
static long bakframeplace[4], bakxsiz[4], bakysiz[4];
|
|
static long bakwindowx1[4], bakwindowy1[4];
|
|
static long bakwindowx2[4], bakwindowy2[4];
|
|
#ifdef POLYMOST
|
|
static long bakrendmode,baktile;
|
|
#endif
|
|
|
|
long totalclocklock;
|
|
|
|
char apptitle[256] = "Build Engine";
|
|
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
|
|
//
|
|
//long cacheresets = 0,cacheinvalidates = 0;
|
|
|
|
|
|
//============================================================================= //POLYMOST BEGINS
|
|
#ifdef POLYMOST
|
|
static void scansector(short sectnum);
|
|
#include "polymost.h"
|
|
#include "hightile.c"
|
|
#include "polymost.c"
|
|
#else
|
|
void hicsetpalettetint(long palnum, unsigned char r, unsigned char g, unsigned char b, unsigned char effect) { }
|
|
int hicsetsubsttex(long picnum, long palnum, char *filen, float alphacut, float xscale, float yscale, char flags) { return 0; }
|
|
int hicsetskybox(long picnum, long palnum, char *faces[6]) { return 0; }
|
|
int hicclearsubst(long picnum, long palnum) { return 0; }
|
|
long polymost_drawtilescreen (long tilex, long tiley, long wallnum, long dimen, int tilezoom) { return -1; }
|
|
#endif
|
|
//============================================================================= //POLYMOST ENDS
|
|
|
|
//
|
|
// getpalookup (internal)
|
|
//
|
|
static inline long getpalookup(long davis, long dashade)
|
|
{
|
|
return(min(max(dashade+(davis>>8),0),numpalookups-1));
|
|
}
|
|
|
|
|
|
//
|
|
// scansector (internal)
|
|
//
|
|
static void scansector(short sectnum)
|
|
{
|
|
walltype *wal, *wal2;
|
|
spritetype *spr;
|
|
long xs, ys, x1, y1, x2, y2, xp1, yp1, xp2=0, yp2=0, templong;
|
|
short z, zz, startwall, endwall, numscansbefore, scanfirst, bunchfrst;
|
|
short nextsectnum;
|
|
|
|
if (sectnum < 0) return;
|
|
|
|
if (automapping) show2dsector[sectnum>>3] |= pow2char[sectnum&7];
|
|
|
|
sectorborder[0] = sectnum, sectorbordercnt = 1;
|
|
do
|
|
{
|
|
sectnum = sectorborder[--sectorbordercnt];
|
|
|
|
for (z=headspritesect[sectnum];z>=0;z=nextspritesect[z])
|
|
{
|
|
spr = &sprite[z];
|
|
if ((((spr->cstat&0x8000) == 0) || (showinvisibility)) &&
|
|
(spr->xrepeat > 0) && (spr->yrepeat > 0) &&
|
|
(spritesortcnt < MAXSPRITESONSCREEN))
|
|
{
|
|
xs = spr->x-globalposx; ys = spr->y-globalposy;
|
|
if ((spr->cstat&48) || (xs*cosglobalang+ys*singlobalang > 0))
|
|
{
|
|
copybufbyte(spr,&tsprite[spritesortcnt],sizeof(spritetype));
|
|
tsprite[spritesortcnt++].owner = z;
|
|
}
|
|
}
|
|
}
|
|
|
|
gotsector[sectnum>>3] |= pow2char[sectnum&7];
|
|
|
|
bunchfrst = numbunches;
|
|
numscansbefore = numscans;
|
|
|
|
startwall = sector[sectnum].wallptr;
|
|
endwall = startwall + sector[sectnum].wallnum;
|
|
scanfirst = numscans;
|
|
for (z=startwall,wal=&wall[z];z<endwall;z++,wal++)
|
|
{
|
|
nextsectnum = wal->nextsector;
|
|
|
|
wal2 = &wall[wal->point2];
|
|
x1 = wal->x-globalposx; y1 = wal->y-globalposy;
|
|
x2 = wal2->x-globalposx; y2 = wal2->y-globalposy;
|
|
|
|
if ((nextsectnum >= 0) && ((wal->cstat&32) == 0))
|
|
if ((gotsector[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0)
|
|
{
|
|
templong = x1*y2-x2*y1;
|
|
if (((unsigned)templong+262144) < 524288)
|
|
if (mulscale5(templong,templong) <= (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
|
|
sectorborder[sectorbordercnt++] = nextsectnum;
|
|
}
|
|
|
|
if ((z == startwall) || (wall[z-1].point2 != z))
|
|
{
|
|
xp1 = dmulscale6(y1,cosglobalang,-x1,singlobalang);
|
|
yp1 = dmulscale6(x1,cosviewingrangeglobalang,y1,sinviewingrangeglobalang);
|
|
}
|
|
else
|
|
{
|
|
xp1 = xp2;
|
|
yp1 = yp2;
|
|
}
|
|
xp2 = dmulscale6(y2,cosglobalang,-x2,singlobalang);
|
|
yp2 = dmulscale6(x2,cosviewingrangeglobalang,y2,sinviewingrangeglobalang);
|
|
if ((yp1 < 256) && (yp2 < 256)) goto skipitaddwall;
|
|
|
|
//If wall's NOT facing you
|
|
if (dmulscale32(xp1,yp2,-xp2,yp1) >= 0) goto skipitaddwall;
|
|
|
|
if (xp1 >= -yp1)
|
|
{
|
|
if ((xp1 > yp1) || (yp1 == 0)) goto skipitaddwall;
|
|
xb1[numscans] = halfxdimen + scale(xp1,halfxdimen,yp1);
|
|
if (xp1 >= 0) xb1[numscans]++; //Fix for SIGNED divide
|
|
if (xb1[numscans] >= xdimen) xb1[numscans] = xdimen-1;
|
|
yb1[numscans] = yp1;
|
|
}
|
|
else
|
|
{
|
|
if (xp2 < -yp2) goto skipitaddwall;
|
|
xb1[numscans] = 0;
|
|
templong = yp1-yp2+xp1-xp2;
|
|
if (templong == 0) goto skipitaddwall;
|
|
yb1[numscans] = yp1 + scale(yp2-yp1,xp1+yp1,templong);
|
|
}
|
|
if (yb1[numscans] < 256) goto skipitaddwall;
|
|
|
|
if (xp2 <= yp2)
|
|
{
|
|
if ((xp2 < -yp2) || (yp2 == 0)) goto skipitaddwall;
|
|
xb2[numscans] = halfxdimen + scale(xp2,halfxdimen,yp2) - 1;
|
|
if (xp2 >= 0) xb2[numscans]++; //Fix for SIGNED divide
|
|
if (xb2[numscans] >= xdimen) xb2[numscans] = xdimen-1;
|
|
yb2[numscans] = yp2;
|
|
}
|
|
else
|
|
{
|
|
if (xp1 > yp1) goto skipitaddwall;
|
|
xb2[numscans] = xdimen-1;
|
|
templong = xp2-xp1+yp1-yp2;
|
|
if (templong == 0) goto skipitaddwall;
|
|
yb2[numscans] = yp1 + scale(yp2-yp1,yp1-xp1,templong);
|
|
}
|
|
if ((yb2[numscans] < 256) || (xb1[numscans] > xb2[numscans])) goto skipitaddwall;
|
|
|
|
//Made it all the way!
|
|
thesector[numscans] = sectnum; thewall[numscans] = z;
|
|
rx1[numscans] = xp1; ry1[numscans] = yp1;
|
|
rx2[numscans] = xp2; ry2[numscans] = yp2;
|
|
p2[numscans] = numscans+1;
|
|
numscans++;
|
|
skipitaddwall:
|
|
|
|
if ((wall[z].point2 < z) && (scanfirst < numscans))
|
|
p2[numscans-1] = scanfirst, scanfirst = numscans;
|
|
}
|
|
|
|
for (z=numscansbefore;z<numscans;z++)
|
|
if ((wall[thewall[z]].point2 != thewall[p2[z]]) || (xb2[z] >= xb1[p2[z]]))
|
|
bunchfirst[numbunches++] = p2[z], p2[z] = -1;
|
|
|
|
for (z=bunchfrst;z<numbunches;z++)
|
|
{
|
|
for (zz=bunchfirst[z];p2[zz]>=0;zz=p2[zz]);
|
|
bunchlast[z] = zz;
|
|
}
|
|
} while (sectorbordercnt > 0);
|
|
}
|
|
|
|
|
|
//
|
|
// maskwallscan (internal)
|
|
//
|
|
static void maskwallscan(long x1, long x2, short *uwal, short *dwal, long *swal, long *lwal)
|
|
{
|
|
long i, x, startx, xnice, ynice, fpalookup;
|
|
long y1ve[4], y2ve[4], u4, d4, dax, z, p, tsizx, tsizy;
|
|
char bad;
|
|
|
|
tsizx = tilesizx[globalpicnum];
|
|
tsizy = tilesizy[globalpicnum];
|
|
setgotpic(globalpicnum);
|
|
if ((tsizx <= 0) || (tsizy <= 0)) return;
|
|
if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen)) return;
|
|
if ((dwal[x1] < 0) && (dwal[x2] < 0)) return;
|
|
|
|
if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
|
|
|
|
startx = x1;
|
|
|
|
xnice = (pow2long[picsiz[globalpicnum]&15] == tsizx);
|
|
if (xnice) tsizx = (tsizx-1);
|
|
ynice = (pow2long[picsiz[globalpicnum]>>4] == tsizy);
|
|
if (ynice) tsizy = (picsiz[globalpicnum]>>4);
|
|
|
|
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((long)mulscale16(swal[x],globvis),globalshade)<<8);
|
|
|
|
bufplce[0] = lwal[x] + globalxpanning;
|
|
if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
|
|
if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
|
|
|
|
vince[0] = swal[x]*globalyscale;
|
|
vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
|
|
|
|
mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],p+ylookup[y1ve[0]]);
|
|
}
|
|
for (;x<=x2-3;x+=4,p+=4)
|
|
{
|
|
bad = 0;
|
|
for (z=3,dax=x+3;z>=0;z--,dax--)
|
|
{
|
|
y1ve[z] = max(uwal[dax],startumost[dax+windowx1]-windowy1);
|
|
y2ve[z] = min(dwal[dax],startdmost[dax+windowx1]-windowy1)-1;
|
|
if (y2ve[z] < y1ve[z]) { bad += pow2char[z]; continue; }
|
|
|
|
i = lwal[dax] + globalxpanning;
|
|
if (i >= tsizx) { if (xnice == 0) i %= tsizx; else i &= tsizx; }
|
|
if (ynice == 0) i *= tsizy; else i <<= tsizy;
|
|
bufplce[z] = waloff[globalpicnum]+i;
|
|
|
|
vince[z] = swal[dax]*globalyscale;
|
|
vplce[z] = globalzd + vince[z]*(y1ve[z]-globalhoriz+1);
|
|
}
|
|
if (bad == 15) continue;
|
|
|
|
palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
|
|
palookupoffse[3] = fpalookup+(getpalookup((long)mulscale16(swal[x+3],globvis),globalshade)<<8);
|
|
|
|
if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
|
|
{
|
|
palookupoffse[1] = palookupoffse[0];
|
|
palookupoffse[2] = palookupoffse[0];
|
|
}
|
|
else
|
|
{
|
|
palookupoffse[1] = fpalookup+(getpalookup((long)mulscale16(swal[x+1],globvis),globalshade)<<8);
|
|
palookupoffse[2] = fpalookup+(getpalookup((long)mulscale16(swal[x+2],globvis),globalshade)<<8);
|
|
}
|
|
|
|
u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
|
|
d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
|
|
|
|
if ((bad > 0) || (u4 >= d4))
|
|
{
|
|
if (!(bad&1)) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
|
|
if (!(bad&2)) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
|
|
if (!(bad&4)) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
|
|
if (!(bad&8)) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
|
|
continue;
|
|
}
|
|
|
|
if (u4 > y1ve[0]) vplce[0] = mvlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
|
|
if (u4 > y1ve[1]) vplce[1] = mvlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
|
|
if (u4 > y1ve[2]) vplce[2] = mvlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
|
|
if (u4 > y1ve[3]) vplce[3] = mvlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
|
|
|
|
if (d4 >= u4) mvlineasm4(d4-u4+1,ylookup[u4]+p);
|
|
|
|
i = p+ylookup[d4+1];
|
|
if (y2ve[0] > d4) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
|
|
if (y2ve[1] > d4) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
|
|
if (y2ve[2] > d4) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
|
|
if (y2ve[3] > d4) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
|
|
}
|
|
for (;x<=x2;x++,p++)
|
|
{
|
|
y1ve[0] = max(uwal[x],startumost[x+windowx1]-windowy1);
|
|
y2ve[0] = min(dwal[x],startdmost[x+windowx1]-windowy1);
|
|
if (y2ve[0] <= y1ve[0]) continue;
|
|
|
|
palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
|
|
|
|
bufplce[0] = lwal[x] + globalxpanning;
|
|
if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
|
|
if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
|
|
|
|
vince[0] = swal[x]*globalyscale;
|
|
vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
|
|
|
|
mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],p+ylookup[y1ve[0]]);
|
|
}
|
|
|
|
#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((long)mulscale16(swal[x],globvis),globalshade)<<8);
|
|
|
|
bufplce[0] = lwal[x] + globalxpanning;
|
|
if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
|
|
if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
|
|
|
|
vince[0] = swal[x]*globalyscale;
|
|
vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
|
|
|
|
mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],p+ylookup[y1ve[0]]);
|
|
}
|
|
|
|
#endif
|
|
|
|
faketimerhandler();
|
|
}
|
|
|
|
|
|
//
|
|
// wallfront (internal)
|
|
//
|
|
static long wallfront(long l1, long l2)
|
|
{
|
|
walltype *wal;
|
|
long x11, y11, x21, y21, x12, y12, x22, y22, dx, dy, t1, t2;
|
|
|
|
wal = &wall[thewall[l1]]; x11 = wal->x; y11 = wal->y;
|
|
wal = &wall[wal->point2]; x21 = wal->x; y21 = wal->y;
|
|
wal = &wall[thewall[l2]]; x12 = wal->x; y12 = wal->y;
|
|
wal = &wall[wal->point2]; x22 = wal->x; y22 = wal->y;
|
|
|
|
dx = x21-x11; dy = y21-y11;
|
|
t1 = dmulscale2(x12-x11,dy,-dx,y12-y11); //p1(l2) vs. l1
|
|
t2 = dmulscale2(x22-x11,dy,-dx,y22-y11); //p2(l2) vs. l1
|
|
if (t1 == 0) { t1 = t2; if (t1 == 0) return(-1); }
|
|
if (t2 == 0) t2 = t1;
|
|
if ((t1^t2) >= 0)
|
|
{
|
|
t2 = dmulscale2(globalposx-x11,dy,-dx,globalposy-y11); //pos vs. l1
|
|
return((t2^t1) >= 0);
|
|
}
|
|
|
|
dx = x22-x12; dy = y22-y12;
|
|
t1 = dmulscale2(x11-x12,dy,-dx,y11-y12); //p1(l1) vs. l2
|
|
t2 = dmulscale2(x21-x12,dy,-dx,y21-y12); //p2(l1) vs. l2
|
|
if (t1 == 0) { t1 = t2; if (t1 == 0) return(-1); }
|
|
if (t2 == 0) t2 = t1;
|
|
if ((t1^t2) >= 0)
|
|
{
|
|
t2 = dmulscale2(globalposx-x12,dy,-dx,globalposy-y12); //pos vs. l2
|
|
return((t2^t1) < 0);
|
|
}
|
|
return(-2);
|
|
}
|
|
|
|
|
|
//
|
|
// spritewallfront (internal)
|
|
//
|
|
static long spritewallfront(spritetype *s, long w)
|
|
{
|
|
walltype *wal;
|
|
long x1, y1;
|
|
|
|
wal = &wall[w]; x1 = wal->x; y1 = wal->y;
|
|
wal = &wall[wal->point2];
|
|
return (dmulscale32(wal->x-x1,s->y-y1,-(s->x-x1),wal->y-y1) >= 0);
|
|
}
|
|
|
|
//
|
|
// spritebehindwall(internal)
|
|
//
|
|
static long spriteobstructswall(spritetype *s, long w)
|
|
{
|
|
walltype *wal;
|
|
long x, y;
|
|
long x1, y1;
|
|
long 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);
|
|
}
|
|
|
|
//
|
|
// bunchfront (internal)
|
|
//
|
|
static long bunchfront(long b1, long b2)
|
|
{
|
|
long x1b1, x2b1, x1b2, x2b2, b1f, b2f, i;
|
|
|
|
b1f = bunchfirst[b1]; x1b1 = xb1[b1f]; x2b2 = xb2[bunchlast[b2]]+1;
|
|
if (x1b1 >= x2b2) return(-1);
|
|
b2f = bunchfirst[b2]; x1b2 = xb1[b2f]; x2b1 = xb2[bunchlast[b1]]+1;
|
|
if (x1b2 >= x2b1) return(-1);
|
|
|
|
if (x1b1 >= x1b2)
|
|
{
|
|
for (i=b2f;xb2[i]<x1b1;i=p2[i]);
|
|
return(wallfront(b1f,i));
|
|
}
|
|
for (i=b1f;xb2[i]<x1b2;i=p2[i]);
|
|
return(wallfront(i,b2f));
|
|
}
|
|
|
|
|
|
//
|
|
// hline (internal)
|
|
//
|
|
static void hline(long xr, long yp)
|
|
{
|
|
long xl, r, s;
|
|
|
|
xl = lastx[yp]; if (xl > xr) return;
|
|
r = horizlookup2[yp-globalhoriz+horizycent];
|
|
asm1 = globalx1*r;
|
|
asm2 = globaly2*r;
|
|
s = ((long)getpalookup((long)mulscale16(r,globvis),globalshade)<<8);
|
|
|
|
hlineasm4(xr-xl,0L,s,globalx2*r+globalypanning,globaly1*r+globalxpanning,
|
|
ylookup[yp]+xr+frameoffset);
|
|
}
|
|
|
|
|
|
//
|
|
// slowhline (internal)
|
|
//
|
|
static void slowhline(long xr, long yp)
|
|
{
|
|
long xl, r;
|
|
|
|
xl = lastx[yp]; if (xl > xr) return;
|
|
r = horizlookup2[yp-globalhoriz+horizycent];
|
|
asm1 = globalx1*r;
|
|
asm2 = globaly2*r;
|
|
|
|
asm3 = (long)globalpalwritten + ((long)getpalookup((long)mulscale16(r,globvis),globalshade)<<8);
|
|
if (!(globalorientation&256))
|
|
{
|
|
mhline(globalbufplc,globaly1*r+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,
|
|
globalx2*r+globalypanning-asm2*(xr-xl),ylookup[yp]+xl+frameoffset);
|
|
return;
|
|
}
|
|
thline(globalbufplc,globaly1*r+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,
|
|
globalx2*r+globalypanning-asm2*(xr-xl),ylookup[yp]+xl+frameoffset);
|
|
}
|
|
|
|
|
|
//
|
|
// prepwall (internal)
|
|
//
|
|
static void prepwall(long z, walltype *wal)
|
|
{
|
|
long 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)
|
|
//
|
|
long animateoffs(short tilenum, short fakevar)
|
|
{
|
|
long i, k, offs;
|
|
|
|
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 long owallmost(short *mostbuf, long w, long z)
|
|
{
|
|
long bad, inty, xcross, y, yinc;
|
|
long s1, s2, s3, s4, ix1, ix2, iy1, iy2, t;
|
|
long i;
|
|
|
|
z <<= 7;
|
|
s1 = mulscale20(globaluclip,yb1[w]); s2 = mulscale20(globaluclip,yb2[w]);
|
|
s3 = mulscale20(globaldclip,yb1[w]); s4 = mulscale20(globaldclip,yb2[w]);
|
|
bad = (z<s1)+((z<s2)<<1)+((z>s3)<<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((long)&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 long wallmost(short *mostbuf, long w, long sectnum, char dastat)
|
|
{
|
|
long bad, i, j, t, y, z, inty, intz, xcross, yinc, fw;
|
|
long x1, y1, z1, x2, y2, z2, xv, yv, dx, dy, dasqr, oz1, oz2;
|
|
long 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 = (z1<s1)+((z2<s2)<<1)+((z1>s3)<<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((long)&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(long x1, long x2, long sectnum)
|
|
{
|
|
long 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((short)globalpicnum,(short)sectnum);
|
|
|
|
if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
|
|
globalbufplc = waloff[globalpicnum];
|
|
|
|
globalshade = (long)sec->ceilingshade;
|
|
globvis = globalcisibility;
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
|
|
globalorientation = (long)sec->ceilingstat;
|
|
|
|
|
|
if ((globalorientation&64) == 0)
|
|
{
|
|
globalx1 = singlobalang; globalx2 = singlobalang;
|
|
globaly1 = cosglobalang; globaly2 = cosglobalang;
|
|
globalxpanning = (globalposx<<20);
|
|
globalypanning = -(globalposy<<20);
|
|
}
|
|
else
|
|
{
|
|
j = sec->wallptr;
|
|
ox = wall[wall[j].point2].x - wall[j].x;
|
|
oy = wall[wall[j].point2].y - wall[j].y;
|
|
i = nsqrtasm(ox*ox+oy*oy); if (i == 0) i = 1024; else i = 1048576/i;
|
|
globalx1 = mulscale10(dmulscale10(ox,singlobalang,-oy,cosglobalang),i);
|
|
globaly1 = mulscale10(dmulscale10(ox,cosglobalang,oy,singlobalang),i);
|
|
globalx2 = -globalx1;
|
|
globaly2 = -globaly1;
|
|
|
|
ox = ((wall[j].x-globalposx)<<6); oy = ((wall[j].y-globalposy)<<6);
|
|
i = dmulscale14(oy,cosglobalang,-ox,singlobalang);
|
|
j = dmulscale14(ox,cosglobalang,oy,singlobalang);
|
|
ox = i; oy = j;
|
|
globalxpanning = globalx1*ox - globaly1*oy;
|
|
globalypanning = globaly2*ox + globalx2*oy;
|
|
}
|
|
globalx2 = mulscale16(globalx2,viewingrangerecip);
|
|
globaly1 = mulscale16(globaly1,viewingrangerecip);
|
|
globalxshift = (8-(picsiz[globalpicnum]&15));
|
|
globalyshift = (8-(picsiz[globalpicnum]>>4));
|
|
if (globalorientation&8) { globalxshift++; globalyshift++; }
|
|
|
|
if ((globalorientation&0x4) > 0)
|
|
{
|
|
i = globalxpanning; globalxpanning = globalypanning; globalypanning = i;
|
|
i = globalx2; globalx2 = -globaly1; globaly1 = -i;
|
|
i = globalx1; globalx1 = globaly2; globaly2 = i;
|
|
}
|
|
if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalxpanning = -globalxpanning;
|
|
if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalypanning = -globalypanning;
|
|
globalx1 <<= globalxshift; globaly1 <<= globalxshift;
|
|
globalx2 <<= globalyshift; globaly2 <<= globalyshift;
|
|
globalxpanning <<= globalxshift; globalypanning <<= globalyshift;
|
|
globalxpanning += (((long)sec->ceilingxpanning)<<24);
|
|
globalypanning += (((long)sec->ceilingypanning)<<24);
|
|
globaly1 = (-globalx1-globaly1)*halfxdimen;
|
|
globalx2 = (globalx2-globaly2)*halfxdimen;
|
|
|
|
sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
|
|
|
|
globalx2 += globaly2*(x1-1);
|
|
globaly1 += globalx1*(x1-1);
|
|
globalx1 = mulscale16(globalx1,globalzd);
|
|
globalx2 = mulscale16(globalx2,globalzd);
|
|
globaly1 = mulscale16(globaly1,globalzd);
|
|
globaly2 = mulscale16(globaly2,globalzd);
|
|
globvis = klabs(mulscale10(globvis,globalzd));
|
|
|
|
if (!(globalorientation&0x180))
|
|
{
|
|
y1 = umost[x1]; y2 = y1;
|
|
for (x=x1;x<=x2;x++)
|
|
{
|
|
twall = umost[x]-1; bwall = min(uplc[x],dmost[x]);
|
|
if (twall < bwall-1)
|
|
{
|
|
if (twall >= y2)
|
|
{
|
|
while (y1 < y2-1) hline(x-1,++y1);
|
|
y1 = twall;
|
|
}
|
|
else
|
|
{
|
|
while (y1 < twall) hline(x-1,++y1);
|
|
while (y1 > twall) lastx[y1--] = x;
|
|
}
|
|
while (y2 > bwall) hline(x-1,--y2);
|
|
while (y2 < bwall) lastx[y2++] = x;
|
|
}
|
|
else
|
|
{
|
|
while (y1 < y2-1) hline(x-1,++y1);
|
|
if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
|
|
y1 = umost[x+1]; y2 = y1;
|
|
}
|
|
globalx2 += globaly2; globaly1 += globalx1;
|
|
}
|
|
while (y1 < y2-1) hline(x2,++y1);
|
|
faketimerhandler();
|
|
return;
|
|
}
|
|
|
|
switch (globalorientation&0x180)
|
|
{
|
|
case 128:
|
|
msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
|
|
break;
|
|
case 256:
|
|
settransnormal();
|
|
tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
|
|
break;
|
|
case 384:
|
|
settransreverse();
|
|
tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
|
|
break;
|
|
}
|
|
|
|
y1 = umost[x1]; y2 = y1;
|
|
for (x=x1;x<=x2;x++)
|
|
{
|
|
twall = umost[x]-1; bwall = min(uplc[x],dmost[x]);
|
|
if (twall < bwall-1)
|
|
{
|
|
if (twall >= y2)
|
|
{
|
|
while (y1 < y2-1) slowhline(x-1,++y1);
|
|
y1 = twall;
|
|
}
|
|
else
|
|
{
|
|
while (y1 < twall) slowhline(x-1,++y1);
|
|
while (y1 > twall) lastx[y1--] = x;
|
|
}
|
|
while (y2 > bwall) slowhline(x-1,--y2);
|
|
while (y2 < bwall) lastx[y2++] = x;
|
|
}
|
|
else
|
|
{
|
|
while (y1 < y2-1) slowhline(x-1,++y1);
|
|
if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
|
|
y1 = umost[x+1]; y2 = y1;
|
|
}
|
|
globalx2 += globaly2; globaly1 += globalx1;
|
|
}
|
|
while (y1 < y2-1) slowhline(x2,++y1);
|
|
faketimerhandler();
|
|
}
|
|
|
|
|
|
//
|
|
// florscan (internal)
|
|
//
|
|
static void florscan(long x1, long x2, long sectnum)
|
|
{
|
|
long 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((short)globalpicnum,(short)sectnum);
|
|
|
|
if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
|
|
globalbufplc = waloff[globalpicnum];
|
|
|
|
globalshade = (long)sec->floorshade;
|
|
globvis = globalcisibility;
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
|
|
globalorientation = (long)sec->floorstat;
|
|
|
|
|
|
if ((globalorientation&64) == 0)
|
|
{
|
|
globalx1 = singlobalang; globalx2 = singlobalang;
|
|
globaly1 = cosglobalang; globaly2 = cosglobalang;
|
|
globalxpanning = (globalposx<<20);
|
|
globalypanning = -(globalposy<<20);
|
|
}
|
|
else
|
|
{
|
|
j = sec->wallptr;
|
|
ox = wall[wall[j].point2].x - wall[j].x;
|
|
oy = wall[wall[j].point2].y - wall[j].y;
|
|
i = nsqrtasm(ox*ox+oy*oy); if (i == 0) i = 1024; else i = 1048576/i;
|
|
globalx1 = mulscale10(dmulscale10(ox,singlobalang,-oy,cosglobalang),i);
|
|
globaly1 = mulscale10(dmulscale10(ox,cosglobalang,oy,singlobalang),i);
|
|
globalx2 = -globalx1;
|
|
globaly2 = -globaly1;
|
|
|
|
ox = ((wall[j].x-globalposx)<<6); oy = ((wall[j].y-globalposy)<<6);
|
|
i = dmulscale14(oy,cosglobalang,-ox,singlobalang);
|
|
j = dmulscale14(ox,cosglobalang,oy,singlobalang);
|
|
ox = i; oy = j;
|
|
globalxpanning = globalx1*ox - globaly1*oy;
|
|
globalypanning = globaly2*ox + globalx2*oy;
|
|
}
|
|
globalx2 = mulscale16(globalx2,viewingrangerecip);
|
|
globaly1 = mulscale16(globaly1,viewingrangerecip);
|
|
globalxshift = (8-(picsiz[globalpicnum]&15));
|
|
globalyshift = (8-(picsiz[globalpicnum]>>4));
|
|
if (globalorientation&8) { globalxshift++; globalyshift++; }
|
|
|
|
if ((globalorientation&0x4) > 0)
|
|
{
|
|
i = globalxpanning; globalxpanning = globalypanning; globalypanning = i;
|
|
i = globalx2; globalx2 = -globaly1; globaly1 = -i;
|
|
i = globalx1; globalx1 = globaly2; globaly2 = i;
|
|
}
|
|
if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalxpanning = -globalxpanning;
|
|
if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalypanning = -globalypanning;
|
|
globalx1 <<= globalxshift; globaly1 <<= globalxshift;
|
|
globalx2 <<= globalyshift; globaly2 <<= globalyshift;
|
|
globalxpanning <<= globalxshift; globalypanning <<= globalyshift;
|
|
globalxpanning += (((long)sec->floorxpanning)<<24);
|
|
globalypanning += (((long)sec->floorypanning)<<24);
|
|
globaly1 = (-globalx1-globaly1)*halfxdimen;
|
|
globalx2 = (globalx2-globaly2)*halfxdimen;
|
|
|
|
sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
|
|
|
|
globalx2 += globaly2*(x1-1);
|
|
globaly1 += globalx1*(x1-1);
|
|
globalx1 = mulscale16(globalx1,globalzd);
|
|
globalx2 = mulscale16(globalx2,globalzd);
|
|
globaly1 = mulscale16(globaly1,globalzd);
|
|
globaly2 = mulscale16(globaly2,globalzd);
|
|
globvis = klabs(mulscale10(globvis,globalzd));
|
|
|
|
if (!(globalorientation&0x180))
|
|
{
|
|
y1 = max(dplc[x1],umost[x1]); y2 = y1;
|
|
for (x=x1;x<=x2;x++)
|
|
{
|
|
twall = max(dplc[x],umost[x])-1; bwall = dmost[x];
|
|
if (twall < bwall-1)
|
|
{
|
|
if (twall >= y2)
|
|
{
|
|
while (y1 < y2-1) hline(x-1,++y1);
|
|
y1 = twall;
|
|
}
|
|
else
|
|
{
|
|
while (y1 < twall) hline(x-1,++y1);
|
|
while (y1 > twall) lastx[y1--] = x;
|
|
}
|
|
while (y2 > bwall) hline(x-1,--y2);
|
|
while (y2 < bwall) lastx[y2++] = x;
|
|
}
|
|
else
|
|
{
|
|
while (y1 < y2-1) hline(x-1,++y1);
|
|
if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
|
|
y1 = max(dplc[x+1],umost[x+1]); y2 = y1;
|
|
}
|
|
globalx2 += globaly2; globaly1 += globalx1;
|
|
}
|
|
while (y1 < y2-1) hline(x2,++y1);
|
|
faketimerhandler();
|
|
return;
|
|
}
|
|
|
|
switch (globalorientation&0x180)
|
|
{
|
|
case 128:
|
|
msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
|
|
break;
|
|
case 256:
|
|
settransnormal();
|
|
tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
|
|
break;
|
|
case 384:
|
|
settransreverse();
|
|
tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
|
|
break;
|
|
}
|
|
|
|
y1 = max(dplc[x1],umost[x1]); y2 = y1;
|
|
for (x=x1;x<=x2;x++)
|
|
{
|
|
twall = max(dplc[x],umost[x])-1; bwall = dmost[x];
|
|
if (twall < bwall-1)
|
|
{
|
|
if (twall >= y2)
|
|
{
|
|
while (y1 < y2-1) slowhline(x-1,++y1);
|
|
y1 = twall;
|
|
}
|
|
else
|
|
{
|
|
while (y1 < twall) slowhline(x-1,++y1);
|
|
while (y1 > twall) lastx[y1--] = x;
|
|
}
|
|
while (y2 > bwall) slowhline(x-1,--y2);
|
|
while (y2 < bwall) lastx[y2++] = x;
|
|
}
|
|
else
|
|
{
|
|
while (y1 < y2-1) slowhline(x-1,++y1);
|
|
if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
|
|
y1 = max(dplc[x+1],umost[x+1]); y2 = y1;
|
|
}
|
|
globalx2 += globaly2; globaly1 += globalx1;
|
|
}
|
|
while (y1 < y2-1) slowhline(x2,++y1);
|
|
faketimerhandler();
|
|
}
|
|
|
|
|
|
//
|
|
// wallscan (internal)
|
|
//
|
|
static void wallscan(long x1, long x2, short *uwal, short *dwal, long *swal, long *lwal)
|
|
{
|
|
long i, x, xnice, ynice, fpalookup;
|
|
long y1ve[4], y2ve[4], u4, d4, z, tsizx, tsizy;
|
|
char bad;
|
|
|
|
tsizx = tilesizx[globalpicnum];
|
|
tsizy = tilesizy[globalpicnum];
|
|
setgotpic(globalpicnum);
|
|
if ((tsizx <= 0) || (tsizy <= 0)) return;
|
|
if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen)) return;
|
|
if ((dwal[x1] < 0) && (dwal[x2] < 0)) return;
|
|
|
|
if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
|
|
|
|
xnice = (pow2long[picsiz[globalpicnum]&15] == tsizx);
|
|
if (xnice) tsizx--;
|
|
ynice = (pow2long[picsiz[globalpicnum]>>4] == tsizy);
|
|
if (ynice) tsizy = (picsiz[globalpicnum]>>4);
|
|
|
|
fpalookup = FP_OFF(palookup[globalpal]);
|
|
|
|
setupvlineasm(globalshiftval);
|
|
|
|
#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((long)mulscale16(swal[x],globvis),globalshade)<<8);
|
|
|
|
bufplce[0] = lwal[x] + globalxpanning;
|
|
if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
|
|
if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
|
|
|
|
vince[0] = swal[x]*globalyscale;
|
|
vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
|
|
|
|
vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],x+frameoffset+ylookup[y1ve[0]]);
|
|
}
|
|
for (;x<=x2-3;x+=4)
|
|
{
|
|
bad = 0;
|
|
for (z=3;z>=0;z--)
|
|
{
|
|
y1ve[z] = max(uwal[x+z],umost[x+z]);
|
|
y2ve[z] = min(dwal[x+z],dmost[x+z])-1;
|
|
if (y2ve[z] < y1ve[z]) { bad += pow2char[z]; continue; }
|
|
|
|
i = lwal[x+z] + globalxpanning;
|
|
if (i >= tsizx) { if (xnice == 0) i %= tsizx; else i &= tsizx; }
|
|
if (ynice == 0) i *= tsizy; else i <<= tsizy;
|
|
bufplce[z] = waloff[globalpicnum]+i;
|
|
|
|
vince[z] = swal[x+z]*globalyscale;
|
|
vplce[z] = globalzd + vince[z]*(y1ve[z]-globalhoriz+1);
|
|
}
|
|
if (bad == 15) continue;
|
|
|
|
palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
|
|
palookupoffse[3] = fpalookup+(getpalookup((long)mulscale16(swal[x+3],globvis),globalshade)<<8);
|
|
|
|
if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
|
|
{
|
|
palookupoffse[1] = palookupoffse[0];
|
|
palookupoffse[2] = palookupoffse[0];
|
|
}
|
|
else
|
|
{
|
|
palookupoffse[1] = fpalookup+(getpalookup((long)mulscale16(swal[x+1],globvis),globalshade)<<8);
|
|
palookupoffse[2] = fpalookup+(getpalookup((long)mulscale16(swal[x+2],globvis),globalshade)<<8);
|
|
}
|
|
|
|
u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
|
|
d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
|
|
|
|
if ((bad != 0) || (u4 >= d4))
|
|
{
|
|
if (!(bad&1)) prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+x+frameoffset+0);
|
|
if (!(bad&2)) prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+x+frameoffset+1);
|
|
if (!(bad&4)) prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+x+frameoffset+2);
|
|
if (!(bad&8)) prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+x+frameoffset+3);
|
|
continue;
|
|
}
|
|
|
|
if (u4 > y1ve[0]) vplce[0] = prevlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+x+frameoffset+0);
|
|
if (u4 > y1ve[1]) vplce[1] = prevlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+x+frameoffset+1);
|
|
if (u4 > y1ve[2]) vplce[2] = prevlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+x+frameoffset+2);
|
|
if (u4 > y1ve[3]) vplce[3] = prevlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+x+frameoffset+3);
|
|
|
|
if (d4 >= u4) vlineasm4(d4-u4+1,ylookup[u4]+x+frameoffset);
|
|
|
|
i = x+frameoffset+ylookup[d4+1];
|
|
if (y2ve[0] > d4) prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
|
|
if (y2ve[1] > d4) prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
|
|
if (y2ve[2] > d4) prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
|
|
if (y2ve[3] > d4) prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
|
|
}
|
|
for (;x<=x2;x++)
|
|
{
|
|
y1ve[0] = max(uwal[x],umost[x]);
|
|
y2ve[0] = min(dwal[x],dmost[x]);
|
|
if (y2ve[0] <= y1ve[0]) continue;
|
|
|
|
palookupoffse[0] = fpalookup+(getpalookup((long)mulscale16(swal[x],globvis),globalshade)<<8);
|
|
|
|
bufplce[0] = lwal[x] + globalxpanning;
|
|
if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
|
|
if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
|
|
|
|
vince[0] = swal[x]*globalyscale;
|
|
vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
|
|
|
|
vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],x+frameoffset+ylookup[y1ve[0]]);
|
|
}
|
|
|
|
#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((long)mulscale16(swal[x],globvis),globalshade)<<8);
|
|
|
|
bufplce[0] = lwal[x] + globalxpanning;
|
|
if (bufplce[0] >= tsizx) { if (xnice == 0) bufplce[0] %= tsizx; else bufplce[0] &= tsizx; }
|
|
if (ynice == 0) bufplce[0] *= tsizy; else bufplce[0] <<= tsizy;
|
|
|
|
vince[0] = swal[x]*globalyscale;
|
|
vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
|
|
|
|
vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+waloff[globalpicnum],x+frameoffset+ylookup[y1ve[0]]);
|
|
}
|
|
|
|
#endif
|
|
|
|
faketimerhandler();
|
|
}
|
|
|
|
|
|
//
|
|
// transmaskvline (internal)
|
|
//
|
|
static void transmaskvline(long x)
|
|
{
|
|
long vplc, vinc, p, i, palookupoffs, bufplc;
|
|
short y1v, y2v;
|
|
|
|
if ((x < 0) || (x >= xdimen)) return;
|
|
|
|
y1v = max(uwall[x],startumost[x+windowx1]-windowy1);
|
|
y2v = min(dwall[x],startdmost[x+windowx1]-windowy1);
|
|
y2v--;
|
|
if (y2v < y1v) return;
|
|
|
|
palookupoffs = FP_OFF(palookup[globalpal]) + (getpalookup((long)mulscale16(swall[x],globvis),globalshade)<<8);
|
|
|
|
vinc = swall[x]*globalyscale;
|
|
vplc = globalzd + vinc*(y1v-globalhoriz+1);
|
|
|
|
i = lwall[x]+globalxpanning;
|
|
if (i >= tilesizx[globalpicnum]) i %= tilesizx[globalpicnum];
|
|
bufplc = waloff[globalpicnum]+i*tilesizy[globalpicnum];
|
|
|
|
p = ylookup[y1v]+x+frameoffset;
|
|
|
|
tvlineasm1(vinc,palookupoffs,y2v-y1v,vplc,bufplc,p);
|
|
}
|
|
|
|
|
|
//
|
|
// transmaskvline2 (internal)
|
|
//
|
|
#ifndef ENGINE_USING_A_C
|
|
static void transmaskvline2(long x)
|
|
{
|
|
long i, y1, y2, x2;
|
|
short y1ve[2], y2ve[2];
|
|
|
|
if ((x < 0) || (x >= xdimen)) return;
|
|
if (x == xdimen-1) { transmaskvline(x); return; }
|
|
|
|
x2 = x+1;
|
|
|
|
y1ve[0] = max(uwall[x],startumost[x+windowx1]-windowy1);
|
|
y2ve[0] = min(dwall[x],startdmost[x+windowx1]-windowy1)-1;
|
|
if (y2ve[0] < y1ve[0]) { transmaskvline(x2); return; }
|
|
y1ve[1] = max(uwall[x2],startumost[x2+windowx1]-windowy1);
|
|
y2ve[1] = min(dwall[x2],startdmost[x2+windowx1]-windowy1)-1;
|
|
if (y2ve[1] < y1ve[1]) { transmaskvline(x); return; }
|
|
|
|
palookupoffse[0] = FP_OFF(palookup[globalpal]) + (getpalookup((long)mulscale16(swall[x],globvis),globalshade)<<8);
|
|
palookupoffse[1] = FP_OFF(palookup[globalpal]) + (getpalookup((long)mulscale16(swall[x2],globvis),globalshade)<<8);
|
|
|
|
setuptvlineasm2(globalshiftval,palookupoffse[0],palookupoffse[1]);
|
|
|
|
vince[0] = swall[x]*globalyscale;
|
|
vince[1] = swall[x2]*globalyscale;
|
|
vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
|
|
vplce[1] = globalzd + vince[1]*(y1ve[1]-globalhoriz+1);
|
|
|
|
i = lwall[x] + globalxpanning;
|
|
if (i >= tilesizx[globalpicnum]) i %= tilesizx[globalpicnum];
|
|
bufplce[0] = waloff[globalpicnum]+i*tilesizy[globalpicnum];
|
|
|
|
i = lwall[x2] + globalxpanning;
|
|
if (i >= tilesizx[globalpicnum]) i %= tilesizx[globalpicnum];
|
|
bufplce[1] = waloff[globalpicnum]+i*tilesizy[globalpicnum];
|
|
|
|
y1 = max(y1ve[0],y1ve[1]);
|
|
y2 = min(y2ve[0],y2ve[1]);
|
|
|
|
i = x+frameoffset;
|
|
|
|
if (y1ve[0] != y1ve[1])
|
|
{
|
|
if (y1ve[0] < y1)
|
|
vplce[0] = tvlineasm1(vince[0],palookupoffse[0],y1-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+i);
|
|
else
|
|
vplce[1] = tvlineasm1(vince[1],palookupoffse[1],y1-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+i+1);
|
|
}
|
|
|
|
if (y2 > y1)
|
|
{
|
|
asm1 = vince[1];
|
|
asm2 = ylookup[y2]+i+1;
|
|
tvlineasm2(vplce[1],vince[0],bufplce[0],bufplce[1],vplce[0],ylookup[y1]+i);
|
|
}
|
|
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 void transmaskwallscan(long x1, long x2)
|
|
{
|
|
long 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 void ceilspritehline(long x2, long y)
|
|
{
|
|
long 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((long)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 void ceilspritescan(long x1, long x2)
|
|
{
|
|
long 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(long dax1, long dax2, long sectnum, char dastat)
|
|
{
|
|
long i, j, l, x, y, dx, dy, wx, wy, y1, y2, daz;
|
|
long daslope, dasqr;
|
|
long shoffs, shinc, m1, m2, *mptr1, *mptr2, *nptr1, *nptr2;
|
|
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 += (((long)sec->ceilingxpanning)<<24);
|
|
globaly1 += (((long)sec->ceilingypanning)<<24);
|
|
}
|
|
else
|
|
{
|
|
globalx1 += (((long)sec->floorxpanning)<<24);
|
|
globaly1 += (((long)sec->floorypanning)<<24);
|
|
}
|
|
|
|
asm1 = -(globalzd>>(16-BITSOFPRECISION));
|
|
|
|
globvis = globalvisibility;
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
|
|
globvis = mulscale13(globvis,daz);
|
|
globvis = mulscale16(globvis,xdimscale);
|
|
j = FP_OFF(palookup[globalpal]);
|
|
|
|
setupslopevlin(((long)(picsiz[globalpicnum]&15))+(((long)(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 = (long *)&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 = (long *)&slopalookup[y1+(shoffs>>15)];
|
|
nptr2 = (long *)&slopalookup[y2+(shoffs>>15)];
|
|
while (nptr1 <= mptr1)
|
|
{
|
|
*mptr1-- = j + (getpalookup((long)mulscale24(krecipasm(m1),globvis),globalshade)<<8);
|
|
m1 -= l;
|
|
}
|
|
while (nptr2 >= mptr2)
|
|
{
|
|
*mptr2++ = j + (getpalookup((long)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),(long)nptr2,y2-y1+1,globalx1,globaly1);
|
|
|
|
if ((x&15) == 0) faketimerhandler();
|
|
}
|
|
globalx2 += globalx;
|
|
globaly2 += globaly;
|
|
globalzx += globalz;
|
|
shoffs += shinc;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// parascan (internal)
|
|
//
|
|
static void parascan(long dax1, long dax2, long sectnum, char dastat, long bunch)
|
|
{
|
|
sectortype *sec;
|
|
long j, k, l, m, n, x, z, wallnum, nextsectnum, globalhorizbak;
|
|
short *topptr, *botptr;
|
|
|
|
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,(long)((unsigned char)(sec->visibility+16)));
|
|
|
|
if (dastat == 0)
|
|
{
|
|
globalpal = sec->ceilingpal;
|
|
globalpicnum = sec->ceilingpicnum;
|
|
globalshade = (long)sec->ceilingshade;
|
|
globalxpanning = (long)sec->ceilingxpanning;
|
|
globalypanning = (long)sec->ceilingypanning;
|
|
topptr = umost;
|
|
botptr = uplc;
|
|
}
|
|
else
|
|
{
|
|
globalpal = sec->floorpal;
|
|
globalpicnum = sec->floorpicnum;
|
|
globalshade = (long)sec->floorshade;
|
|
globalxpanning = (long)sec->floorxpanning;
|
|
globalypanning = (long)sec->floorypanning;
|
|
topptr = dplc;
|
|
botptr = dmost;
|
|
}
|
|
|
|
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
|
|
if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)sectnum);
|
|
globalshiftval = (picsiz[globalpicnum]>>4);
|
|
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
|
|
globalshiftval = 32-globalshiftval;
|
|
globalzd = (((tilesizy[globalpicnum]>>1)+parallaxyoffs)<<globalshiftval)+(globalypanning<<24);
|
|
globalyscale = (8<<(globalshiftval-19));
|
|
//if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
|
|
|
|
k = 11 - (picsiz[globalpicnum]&15) - pskybits;
|
|
x = -1;
|
|
|
|
for (z=bunchfirst[bunch];z>=0;z=p2[z])
|
|
{
|
|
wallnum = thewall[z]; nextsectnum = wall[wallnum].nextsector;
|
|
|
|
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] = ((((long)radarang2[j]+globalang)&2047)>>k);
|
|
}
|
|
if (parallaxtype == 2)
|
|
{
|
|
n = mulscale16(xdimscale,viewingrange);
|
|
for (j=xb1[z];j<=xb2[z];j++)
|
|
swplc[j] = mulscale14(sintable[((long)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(long bunch)
|
|
{
|
|
sectortype *sec, *nextsec;
|
|
walltype *wal;
|
|
long i, x, x1, x2, cz[5], fz[5];
|
|
long z, wallnum, sectnum, nextsectnum;
|
|
long 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,(char)0);
|
|
andwstat2 &= wallmost(dplc,z,sectnum,(char)1);
|
|
}
|
|
|
|
if ((andwstat1&3) != 3) //draw ceilings
|
|
{
|
|
if ((sec->ceilingstat&3) == 2)
|
|
grouscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,0);
|
|
else if ((sec->ceilingstat&1) == 0)
|
|
ceilscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum);
|
|
else
|
|
parascan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,0,bunch);
|
|
}
|
|
if ((andwstat2&12) != 12) //draw floors
|
|
{
|
|
if ((sec->floorstat&3) == 2)
|
|
grouscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,1);
|
|
else if ((sec->floorstat&1) == 0)
|
|
florscan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum);
|
|
else
|
|
parascan(xb1[bunchfirst[bunch]],xb2[bunchlast[bunch]],sectnum,1,bunch);
|
|
}
|
|
|
|
//DRAW WALLS SECTION!
|
|
for (z=bunchfirst[bunch];z>=0;z=p2[z])
|
|
{
|
|
x1 = xb1[z]; x2 = xb2[z];
|
|
if (umost[x2] >= dmost[x2])
|
|
{
|
|
for (x=x1;x<x2;x++)
|
|
if (umost[x] < dmost[x]) break;
|
|
if (x >= x2)
|
|
{
|
|
smostwall[smostwallcnt] = z;
|
|
smostwalltype[smostwallcnt] = 0;
|
|
smostwallcnt++;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
wallnum = thewall[z]; wal = &wall[wallnum];
|
|
nextsectnum = wal->nextsector; nextsec = §or[nextsectnum];
|
|
|
|
gotswall = 0;
|
|
|
|
startsmostwallcnt = smostwallcnt;
|
|
startsmostcnt = smostcnt;
|
|
|
|
if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
|
|
{
|
|
if (searchy <= uplc[searchx]) //ceiling
|
|
{
|
|
searchsector = sectnum; searchwall = wallnum;
|
|
searchstat = 1; searchit = 1;
|
|
}
|
|
else if (searchy >= dplc[searchx]) //floor
|
|
{
|
|
searchsector = sectnum; searchwall = wallnum;
|
|
searchstat = 2; searchit = 1;
|
|
}
|
|
}
|
|
|
|
if (nextsectnum >= 0)
|
|
{
|
|
getzsofslope((short)sectnum,wal->x,wal->y,&cz[0],&fz[0]);
|
|
getzsofslope((short)sectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[1],&fz[1]);
|
|
getzsofslope((short)nextsectnum,wal->x,wal->y,&cz[2],&fz[2]);
|
|
getzsofslope((short)nextsectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[3],&fz[3]);
|
|
getzsofslope((short)nextsectnum,globalposx,globalposy,&cz[4],&fz[4]);
|
|
|
|
if ((wal->cstat&48) == 16) maskwall[maskwallcnt++] = z;
|
|
|
|
if (((sec->ceilingstat&1) == 0) || ((nextsec->ceilingstat&1) == 0))
|
|
{
|
|
if ((cz[2] <= cz[0]) && (cz[3] <= cz[1]))
|
|
{
|
|
if (globparaceilclip)
|
|
for (x=x1;x<=x2;x++)
|
|
if (uplc[x] > umost[x])
|
|
if (umost[x] <= dmost[x])
|
|
{
|
|
umost[x] = uplc[x];
|
|
if (umost[x] > dmost[x]) numhits--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wallmost(dwall,z,nextsectnum,(char)0);
|
|
if ((cz[2] > fz[0]) || (cz[3] > fz[1]))
|
|
for (i=x1;i<=x2;i++) if (dwall[i] > dplc[i]) dwall[i] = dplc[i];
|
|
|
|
if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
|
|
if (searchy <= dwall[searchx]) //wall
|
|
{
|
|
searchsector = sectnum; searchwall = wallnum;
|
|
searchstat = 0; searchit = 1;
|
|
}
|
|
|
|
globalorientation = (long)wal->cstat;
|
|
globalpicnum = wal->picnum;
|
|
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
|
|
globalxpanning = (long)wal->xpanning;
|
|
globalypanning = (long)wal->ypanning;
|
|
globalshiftval = (picsiz[globalpicnum]>>4);
|
|
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
|
|
globalshiftval = 32-globalshiftval;
|
|
if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
|
|
globalshade = (long)wal->shade;
|
|
globvis = globalvisibility;
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
|
|
globalpal = (long)wal->pal;
|
|
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,(char)1);
|
|
if ((fz[2] < cz[0]) || (fz[3] < cz[1]))
|
|
for (i=x1;i<=x2;i++) if (uwall[i] < uplc[i]) uwall[i] = uplc[i];
|
|
|
|
if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
|
|
if (searchy >= uwall[searchx]) //wall
|
|
{
|
|
searchsector = sectnum; searchwall = wallnum;
|
|
if ((wal->cstat&2) > 0) searchwall = wal->nextwall;
|
|
searchstat = 0; searchit = 1;
|
|
}
|
|
|
|
if ((wal->cstat&2) > 0)
|
|
{
|
|
wallnum = wal->nextwall; wal = &wall[wallnum];
|
|
globalorientation = (long)wal->cstat;
|
|
globalpicnum = wal->picnum;
|
|
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
|
|
globalxpanning = (long)wal->xpanning;
|
|
globalypanning = (long)wal->ypanning;
|
|
if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
|
|
globalshade = (long)wal->shade;
|
|
globalpal = (long)wal->pal;
|
|
wallnum = thewall[z]; wal = &wall[wallnum];
|
|
}
|
|
else
|
|
{
|
|
globalorientation = (long)wal->cstat;
|
|
globalpicnum = wal->picnum;
|
|
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
|
|
globalxpanning = (long)wal->xpanning;
|
|
globalypanning = (long)wal->ypanning;
|
|
if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
|
|
globalshade = (long)wal->shade;
|
|
globalpal = (long)wal->pal;
|
|
}
|
|
if (palookup[globalpal] == NULL) globalpal = 0; // JBF: fixes crash
|
|
globvis = globalvisibility;
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
|
|
globalshiftval = (picsiz[globalpicnum]>>4);
|
|
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
|
|
globalshiftval = 32-globalshiftval;
|
|
globalyscale = (wal->yrepeat<<(globalshiftval-19));
|
|
if ((globalorientation&4) == 0)
|
|
globalzd = (((globalposz-nextsec->floorz)*globalyscale)<<8);
|
|
else
|
|
globalzd = (((globalposz-sec->ceilingz)*globalyscale)<<8);
|
|
globalzd += (globalypanning<<24);
|
|
if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
|
|
|
|
if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
|
|
wallscan(x1,x2,uwall,dplc,swall,lwall);
|
|
|
|
if ((fz[2] <= fz[0]) && (fz[3] <= fz[1]))
|
|
{
|
|
for (x=x1;x<=x2;x++)
|
|
if (uwall[x] < dmost[x])
|
|
if (umost[x] <= dmost[x])
|
|
{
|
|
dmost[x] = uwall[x];
|
|
if (umost[x] > dmost[x]) numhits--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (x=x1;x<=x2;x++)
|
|
if (umost[x] <= dmost[x])
|
|
{
|
|
i = min(dplc[x],uwall[x]);
|
|
if (i < dmost[x])
|
|
{
|
|
dmost[x] = i;
|
|
if (umost[x] > dmost[x]) numhits--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((fz[2] > fz[0]) || (fz[3] > fz[1]) || (globalposz > fz[4]))
|
|
{
|
|
i = x2-x1+1;
|
|
if (smostcnt+i < MAXYSAVES)
|
|
{
|
|
smoststart[smostwallcnt] = smostcnt;
|
|
smostwall[smostwallcnt] = z;
|
|
smostwalltype[smostwallcnt] = 2; //2 for dmost
|
|
smostwallcnt++;
|
|
copybufbyte(&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;x<x2;x++)
|
|
if (umost[x] < dmost[x])
|
|
{ scansector(nextsectnum); break; }
|
|
|
|
//If can't see sector beyond, then cancel smost array and just
|
|
//store wall!
|
|
if (x == x2)
|
|
{
|
|
smostwallcnt = startsmostwallcnt;
|
|
smostcnt = startsmostcnt;
|
|
smostwall[smostwallcnt] = z;
|
|
smostwalltype[smostwallcnt] = 0;
|
|
smostwallcnt++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((nextsectnum < 0) || (wal->cstat&32)) //White/1-way wall
|
|
{
|
|
globalorientation = (long)wal->cstat;
|
|
if (nextsectnum < 0) globalpicnum = wal->picnum;
|
|
else globalpicnum = wal->overpicnum;
|
|
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
|
|
globalxpanning = (long)wal->xpanning;
|
|
globalypanning = (long)wal->ypanning;
|
|
if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)wallnum+16384);
|
|
globalshade = (long)wal->shade;
|
|
globvis = globalvisibility;
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
|
|
globalpal = (long)wal->pal;
|
|
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; searchwall = wallnum;
|
|
if (nextsectnum < 0) searchstat = 0; else searchstat = 4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// drawvox
|
|
//
|
|
#ifdef SUPERBUILD
|
|
static void drawvox(long dasprx, long daspry, long dasprz, long dasprang,
|
|
long daxscale, long dayscale, char daindex,
|
|
signed char dashade, char dapal, long *daumost, long *dadmost)
|
|
{
|
|
long i, j, k, x, y, syoff, ggxstart, ggystart, nxoff;
|
|
long cosang, sinang, sprcosang, sprsinang, backx, backy, gxinc, gyinc;
|
|
long daxsiz, daysiz, dazsiz, daxpivot, daypivot, dazpivot;
|
|
long daxscalerecip, dayscalerecip, cnt, gxstart, gystart, odayscale;
|
|
long l1, l2, slabxoffs, xyvoxoffs, *longptr;
|
|
long lx, rx, nx, ny, x1=0, y1=0, z1, x2=0, y2=0, z2, yplc, yinc=0;
|
|
long yoff, xs=0, ys=0, xe, ye, xi=0, yi=0, cbackx, cbacky, dagxinc, dagyinc;
|
|
short *shortptr;
|
|
char *voxptr, *voxend, *davoxptr, oand, oand16, oand32;
|
|
|
|
cosang = sintable[(globalang+512)&2047];
|
|
sinang = sintable[globalang&2047];
|
|
sprcosang = sintable[(dasprang+512)&2047];
|
|
sprsinang = sintable[dasprang&2047];
|
|
|
|
i = klabs(dmulscale6(dasprx-globalposx,cosang,daspry-globalposy,sinang));
|
|
j = (long)(getpalookup((long)mulscale21(globvis,i),(long)dashade)<<8);
|
|
setupdrawslab(ylookup[1],FP_OFF(palookup[dapal])+j);
|
|
j = 1310720;
|
|
j *= min(daxscale,dayscale); j >>= 6; //New hacks (for sized-down voxels)
|
|
for (k=0;k<MAXVOXMIPS;k++)
|
|
{
|
|
if (i < j) { i = k; break; }
|
|
j <<= 1;
|
|
}
|
|
if (k >= MAXVOXMIPS) i = MAXVOXMIPS-1;
|
|
|
|
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<<i,voxscale[daindex]);
|
|
dayscale = mulscale8(dayscale<<i,voxscale[daindex]);
|
|
}
|
|
|
|
odayscale = dayscale;
|
|
daxscale = mulscale16(daxscale,xyaspect);
|
|
daxscale = scale(daxscale,xdimenscale,xdimen<<8);
|
|
dayscale = scale(dayscale,mulscale16(xdimenscale,viewingrangerecip),xdimen<<8);
|
|
|
|
daxscalerecip = (1<<30)/daxscale;
|
|
dayscalerecip = (1<<30)/dayscale;
|
|
|
|
longptr = (long *)davoxptr;
|
|
daxsiz = B_LITTLE32(longptr[0]); daysiz = B_LITTLE32(longptr[1]); dazsiz = B_LITTLE32(longptr[2]);
|
|
daxpivot = B_LITTLE32(longptr[3]); daypivot = B_LITTLE32(longptr[4]); dazpivot = B_LITTLE32(longptr[5]);
|
|
davoxptr += (6<<2);
|
|
|
|
x = mulscale16(globalposx-dasprx,daxscalerecip);
|
|
y = mulscale16(globalposy-daspry,daxscalerecip);
|
|
backx = ((dmulscale10(x,sprcosang,y,sprsinang)+daxpivot)>>8);
|
|
backy = ((dmulscale10(y,sprcosang,x,-sprsinang)+daypivot)>>8);
|
|
cbackx = min(max(backx,0),daxsiz-1);
|
|
cbacky = min(max(backy,0),daysiz-1);
|
|
|
|
sprcosang = mulscale14(daxscale,sprcosang);
|
|
sprsinang = mulscale14(daxscale,sprsinang);
|
|
|
|
x = (dasprx-globalposx) - dmulscale18(daxpivot,sprcosang,daypivot,-sprsinang);
|
|
y = (daspry-globalposy) - dmulscale18(daypivot,sprcosang,daxpivot,sprsinang);
|
|
|
|
cosang = mulscale16(cosang,dayscalerecip);
|
|
sinang = mulscale16(sinang,dayscalerecip);
|
|
|
|
gxstart = y*cosang - x*sinang;
|
|
gystart = 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 = (long *)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<backx)+0]+pow2char[(ys<backy)+2];
|
|
oand16 = oand+16;
|
|
oand32 = oand+32;
|
|
|
|
if (yi > 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 = (long)&davoxptr[B_LITTLE32(longptr[x])];
|
|
shortptr = (short *)&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<voxend;voxptr+=voxptr[1]+3)
|
|
{
|
|
j = (voxptr[0]<<15)-syoff;
|
|
if (j < 0)
|
|
{
|
|
k = j+(voxptr[1]<<15);
|
|
if (k < 0)
|
|
{
|
|
if ((voxptr[2]&oand32) == 0) continue;
|
|
z2 = mulscale32(l2,k) + globalhoriz; //Below slab
|
|
}
|
|
else
|
|
{
|
|
if ((voxptr[2]&oand) == 0) continue; //Middle of slab
|
|
z2 = mulscale32(l1,k) + globalhoriz;
|
|
}
|
|
z1 = mulscale32(l1,j) + globalhoriz;
|
|
}
|
|
else
|
|
{
|
|
if ((voxptr[2]&oand16) == 0) continue;
|
|
z1 = mulscale32(l2,j) + globalhoriz; //Above slab
|
|
z2 = mulscale32(l1,j+(voxptr[1]<<15)) + globalhoriz;
|
|
}
|
|
|
|
if (voxptr[1] == 1)
|
|
{
|
|
yplc = 0; yinc = 0;
|
|
if (z1 < daumost[lx]) z1 = daumost[lx];
|
|
}
|
|
else
|
|
{
|
|
if (z2-z1 >= 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,(long)&voxptr[3],ylookup[z1]+lx+frameoffset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
enddrawing(); //}}}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// drawsprite (internal)
|
|
//
|
|
static void drawsprite(long snum)
|
|
{
|
|
spritetype *tspr;
|
|
sectortype *sec;
|
|
long startum, startdm, sectnum, xb, yp, cstat;
|
|
long siz, xsiz, ysiz, xoff, yoff, xspan, yspan;
|
|
long x1, y1, x2, y2, lx, rx, dalx2, darx2, i, j, k, x, linum, linuminc;
|
|
long yinc, z, z1, z2, xp1, yp1, xp2, yp2;
|
|
long xv, yv, top, topinc, bot, botinc, hplc, hinc;
|
|
long cosang, sinang, dax, day, lpoint, lmax, rpoint, rmax, dax1, dax2, y;
|
|
long npoints, npoints2, zz, t, zsgn, zzsgn, *longptr;
|
|
long 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;
|
|
}
|
|
if (rendmode == 4) { polymer_drawsprite(snum); return; }
|
|
#endif
|
|
//============================================================================= //POLYMOST ENDS
|
|
|
|
tspr = tspriteptr[snum];
|
|
|
|
xb = spritesx[snum];
|
|
yp = spritesy[snum];
|
|
tilenum = tspr->picnum;
|
|
spritenum = tspr->owner;
|
|
cstat = tspr->cstat;
|
|
|
|
#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 = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)tspr->xoffset);
|
|
yoff = (long)((signed char)((picanm[tilenum]>>16)&255))+((long)tspr->yoffset);
|
|
|
|
if ((cstat&48) == 0)
|
|
{
|
|
if (yp <= (4<<8)) return;
|
|
|
|
siz = divscale19(xdimenscale,yp);
|
|
|
|
xv = mulscale16(((long)tspr->xrepeat)<<16,xyaspect);
|
|
|
|
xspan = tilesizx[tilenum];
|
|
yspan = tilesizy[tilenum];
|
|
xsiz = mulscale30(siz,xv*xspan);
|
|
ysiz = mulscale14(siz,tspr->yrepeat*yspan);
|
|
|
|
if (((tilesizx[tilenum]>>11) >= xsiz) || (yspan >= (ysiz>>1)))
|
|
return; //Watch out for divscale overflow
|
|
|
|
x1 = xb-(xsiz>>1);
|
|
if (xspan&1) x1 += mulscale31(siz,xv); //Odd xspans
|
|
i = mulscale30(siz,xv*xoff);
|
|
if ((cstat&4) == 0) x1 -= i; else x1 += i;
|
|
|
|
y1 = mulscale16(tspr->z-globalposz,siz);
|
|
y1 -= mulscale14(siz,tspr->yrepeat*yoff);
|
|
y1 += (globalhoriz<<8)-ysiz;
|
|
if (cstat&128)
|
|
{
|
|
y1 += (ysiz>>1);
|
|
if (yspan&1) y1 += mulscale15(siz,tspr->yrepeat); //Odd yspans
|
|
}
|
|
|
|
x2 = x1+xsiz-1;
|
|
y2 = y1+ysiz-1;
|
|
if ((y1|255) >= (y2|255)) return;
|
|
|
|
lx = (x1>>8)+1; if (lx < 0) lx = 0;
|
|
rx = (x2>>8); if (rx >= xdimen) rx = xdimen-1;
|
|
if (lx > rx) return;
|
|
|
|
yinc = divscale32(yspan,ysiz);
|
|
|
|
if ((sec->ceilingstat&3) == 0)
|
|
startum = globalhoriz+mulscale24(siz,sec->ceilingz-globalposz)-1;
|
|
else
|
|
startum = 0;
|
|
if ((sec->floorstat&3) == 0)
|
|
startdm = globalhoriz+mulscale24(siz,sec->floorz-globalposz)+1;
|
|
else
|
|
startdm = 0x7fffffff;
|
|
if ((y1>>8) > startum) startum = (y1>>8);
|
|
if ((y2>>8) < startdm) startdm = (y2>>8);
|
|
|
|
if (startum < -32768) startum = -32768;
|
|
if (startdm > 32767) startdm = 32767;
|
|
if (startum >= startdm) return;
|
|
|
|
if ((cstat&4) == 0)
|
|
{
|
|
linuminc = divscale24(xspan,xsiz);
|
|
linum = mulscale8((lx<<8)-x1,linuminc);
|
|
}
|
|
else
|
|
{
|
|
linuminc = -divscale24(xspan,xsiz);
|
|
linum = mulscale8((lx<<8)-x2,linuminc);
|
|
}
|
|
if ((cstat&8) > 0)
|
|
{
|
|
yinc = -yinc;
|
|
i = y1; y1 = y2; y2 = i;
|
|
}
|
|
|
|
for (x=lx;x<=rx;x++)
|
|
{
|
|
uwall[x] = max(startumost[x+windowx1]-windowy1,(short)startum);
|
|
dwall[x] = min(startdmost[x+windowx1]-windowy1,(short)startdm);
|
|
}
|
|
daclip = 0;
|
|
for (i=smostwallcnt-1;i>=0;i--)
|
|
{
|
|
if (smostwalltype[i]&daclip) continue;
|
|
j = smostwall[i];
|
|
if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
|
|
if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
|
|
if (spritewallfront(tspr,(long)thewall[j]) && ((yp <= yb1[j]) || (yp <= yb2[j]))) continue;
|
|
|
|
dalx2 = max(xb1[j],lx); darx2 = min(xb2[j],rx);
|
|
|
|
switch (smostwalltype[i])
|
|
{
|
|
case 0:
|
|
if (dalx2 <= darx2)
|
|
{
|
|
if ((dalx2 == lx) && (darx2 == rx)) return;
|
|
//clearbufbyte(&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<rx;x++)
|
|
if (uwall[x] < dwall[x]) break;
|
|
if (x == rx) return;
|
|
}
|
|
|
|
//sprite
|
|
if ((searchit >= 1) && (searchx >= lx) && (searchx <= rx))
|
|
if ((searchy >= uwall[searchx]) && (searchy < dwall[searchx]))
|
|
{
|
|
searchsector = sectnum; searchwall = spritenum;
|
|
searchstat = 3; searchit = 1;
|
|
}
|
|
|
|
z2 = tspr->z - ((yoff*tspr->yrepeat)<<2);
|
|
if (cstat&128)
|
|
{
|
|
z2 += ((yspan*tspr->yrepeat)<<1);
|
|
if (yspan&1) z2 += (tspr->yrepeat<<1); //Odd yspans
|
|
}
|
|
z1 = z2 - ((yspan*tspr->yrepeat)<<2);
|
|
|
|
globalorientation = 0;
|
|
globalpicnum = tilenum;
|
|
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
|
|
globalxpanning = 0L;
|
|
globalypanning = 0L;
|
|
globvis = globalvisibility;
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
|
|
globalshiftval = (picsiz[globalpicnum]>>4);
|
|
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
|
|
globalshiftval = 32-globalshiftval;
|
|
globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
|
|
globalzd = (((globalposz-z1)*globalyscale)<<8);
|
|
if ((cstat&8) > 0)
|
|
{
|
|
globalyscale = -globalyscale;
|
|
globalzd = (((globalposz-z2)*globalyscale)<<8);
|
|
}
|
|
|
|
qinterpolatedown16((long)&lwall[lx],rx-lx+1,linum,linuminc);
|
|
clearbuf(&swall[lx],rx-lx+1,mulscale19(yp,xdimscale));
|
|
|
|
if ((cstat&2) == 0)
|
|
maskwallscan(lx,rx,uwall,dwall,swall,lwall);
|
|
else
|
|
transmaskwallscan(lx,rx);
|
|
}
|
|
else if ((cstat&48) == 16)
|
|
{
|
|
if ((cstat&4) > 0) xoff = -xoff;
|
|
if ((cstat&8) > 0) yoff = -yoff;
|
|
|
|
xspan = tilesizx[tilenum]; yspan = tilesizy[tilenum];
|
|
xv = tspr->xrepeat*sintable[(tspr->ang+2560+1536)&2047];
|
|
yv = tspr->xrepeat*sintable[(tspr->ang+2048+1536)&2047];
|
|
i = (xspan>>1)+xoff;
|
|
x1 = tspr->x-globalposx-mulscale16(xv,i); x2 = x1+mulscale16(xv,xspan);
|
|
y1 = tspr->y-globalposy-mulscale16(yv,i); y2 = y1+mulscale16(yv,xspan);
|
|
|
|
yp1 = dmulscale6(x1,cosviewingrangeglobalang,y1,sinviewingrangeglobalang);
|
|
yp2 = dmulscale6(x2,cosviewingrangeglobalang,y2,sinviewingrangeglobalang);
|
|
if ((yp1 <= 0) && (yp2 <= 0)) return;
|
|
xp1 = dmulscale6(y1,cosglobalang,-x1,singlobalang);
|
|
xp2 = dmulscale6(y2,cosglobalang,-x2,singlobalang);
|
|
|
|
x1 += globalposx; y1 += globalposy;
|
|
x2 += globalposx; y2 += globalposy;
|
|
|
|
swapped = 0;
|
|
if (dmulscale32(xp1,yp2,-xp2,yp1) >= 0) //If wall's NOT facing you
|
|
{
|
|
if ((cstat&64) != 0) return;
|
|
i = xp1, xp1 = xp2, xp2 = i;
|
|
i = yp1, yp1 = yp2, yp2 = i;
|
|
i = x1, x1 = x2, x2 = i;
|
|
i = y1, y1 = y2, y2 = i;
|
|
swapped = 1;
|
|
}
|
|
|
|
if (xp1 >= -yp1)
|
|
{
|
|
if (xp1 > yp1) return;
|
|
|
|
if (yp1 == 0) return;
|
|
xb1[MAXWALLSB-1] = halfxdimen + scale(xp1,halfxdimen,yp1);
|
|
if (xp1 >= 0) xb1[MAXWALLSB-1]++; //Fix for SIGNED divide
|
|
if (xb1[MAXWALLSB-1] >= xdimen) xb1[MAXWALLSB-1] = xdimen-1;
|
|
yb1[MAXWALLSB-1] = yp1;
|
|
}
|
|
else
|
|
{
|
|
if (xp2 < -yp2) return;
|
|
xb1[MAXWALLSB-1] = 0;
|
|
i = yp1-yp2+xp1-xp2;
|
|
if (i == 0) return;
|
|
yb1[MAXWALLSB-1] = yp1 + scale(yp2-yp1,xp1+yp1,i);
|
|
}
|
|
if (xp2 <= yp2)
|
|
{
|
|
if (xp2 < -yp2) return;
|
|
|
|
if (yp2 == 0) return;
|
|
xb2[MAXWALLSB-1] = halfxdimen + scale(xp2,halfxdimen,yp2) - 1;
|
|
if (xp2 >= 0) xb2[MAXWALLSB-1]++; //Fix for SIGNED divide
|
|
if (xb2[MAXWALLSB-1] >= xdimen) xb2[MAXWALLSB-1] = xdimen-1;
|
|
yb2[MAXWALLSB-1] = yp2;
|
|
}
|
|
else
|
|
{
|
|
if (xp1 > yp1) return;
|
|
|
|
xb2[MAXWALLSB-1] = xdimen-1;
|
|
i = xp2-xp1+yp1-yp2;
|
|
if (i == 0) return;
|
|
yb2[MAXWALLSB-1] = yp1 + scale(yp2-yp1,yp1-xp1,i);
|
|
}
|
|
|
|
if ((yb1[MAXWALLSB-1] < 256) || (yb2[MAXWALLSB-1] < 256) || (xb1[MAXWALLSB-1] > xb2[MAXWALLSB-1]))
|
|
return;
|
|
|
|
topinc = -mulscale10(yp1,xspan);
|
|
top = (((mulscale10(xp1,xdimen) - mulscale9(xb1[MAXWALLSB-1]-halfxdimen,yp1))*xspan)>>3);
|
|
botinc = ((yp2-yp1)>>8);
|
|
bot = mulscale11(xp1-xp2,xdimen) + mulscale2(xb1[MAXWALLSB-1]-halfxdimen,botinc);
|
|
|
|
j = xb2[MAXWALLSB-1]+3;
|
|
z = mulscale20(top,krecipasm(bot));
|
|
lwall[xb1[MAXWALLSB-1]] = (z>>8);
|
|
for (x=xb1[MAXWALLSB-1]+4;x<=j;x+=4)
|
|
{
|
|
top += topinc; bot += botinc;
|
|
zz = z; z = mulscale20(top,krecipasm(bot));
|
|
lwall[x] = (z>>8);
|
|
i = ((z+zz)>>1);
|
|
lwall[x-2] = (i>>8);
|
|
lwall[x-3] = ((i+zz)>>9);
|
|
lwall[x-1] = ((i+z)>>9);
|
|
}
|
|
|
|
if (lwall[xb1[MAXWALLSB-1]] < 0) lwall[xb1[MAXWALLSB-1]] = 0;
|
|
if (lwall[xb2[MAXWALLSB-1]] >= xspan) lwall[xb2[MAXWALLSB-1]] = xspan-1;
|
|
|
|
if ((swapped^((cstat&4)>0)) > 0)
|
|
{
|
|
j = xspan-1;
|
|
for (x=xb1[MAXWALLSB-1];x<=xb2[MAXWALLSB-1];x++)
|
|
lwall[x] = j-lwall[x];
|
|
}
|
|
|
|
rx1[MAXWALLSB-1] = xp1; ry1[MAXWALLSB-1] = yp1;
|
|
rx2[MAXWALLSB-1] = xp2; ry2[MAXWALLSB-1] = yp2;
|
|
|
|
hplc = divscale19(xdimenscale,yb1[MAXWALLSB-1]);
|
|
hinc = divscale19(xdimenscale,yb2[MAXWALLSB-1]);
|
|
hinc = (hinc-hplc)/(xb2[MAXWALLSB-1]-xb1[MAXWALLSB-1]+1);
|
|
|
|
z2 = tspr->z - ((yoff*tspr->yrepeat)<<2);
|
|
if (cstat&128)
|
|
{
|
|
z2 += ((yspan*tspr->yrepeat)<<1);
|
|
if (yspan&1) z2 += (tspr->yrepeat<<1); //Odd yspans
|
|
}
|
|
z1 = z2 - ((yspan*tspr->yrepeat)<<2);
|
|
|
|
globalorientation = 0;
|
|
globalpicnum = tilenum;
|
|
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
|
|
globalxpanning = 0L;
|
|
globalypanning = 0L;
|
|
globvis = globalvisibility;
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
|
|
globalshiftval = (picsiz[globalpicnum]>>4);
|
|
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
|
|
globalshiftval = 32-globalshiftval;
|
|
globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
|
|
globalzd = (((globalposz-z1)*globalyscale)<<8);
|
|
if ((cstat&8) > 0)
|
|
{
|
|
globalyscale = -globalyscale;
|
|
globalzd = (((globalposz-z2)*globalyscale)<<8);
|
|
}
|
|
|
|
if (((sec->ceilingstat&1) == 0) && (z1 < sec->ceilingz))
|
|
z1 = sec->ceilingz;
|
|
if (((sec->floorstat&1) == 0) && (z2 > sec->floorz))
|
|
z2 = sec->floorz;
|
|
|
|
owallmost(uwall,(long)(MAXWALLSB-1),z1-globalposz);
|
|
owallmost(dwall,(long)(MAXWALLSB-1),z2-globalposz);
|
|
for (i=xb1[MAXWALLSB-1];i<=xb2[MAXWALLSB-1];i++)
|
|
{ swall[i] = (krecipasm(hplc)<<2); hplc += hinc; }
|
|
|
|
for (i=smostwallcnt-1;i>=0;i--)
|
|
{
|
|
j = smostwall[i];
|
|
|
|
if ((xb1[j] > xb2[MAXWALLSB-1]) || (xb2[j] < xb1[MAXWALLSB-1])) continue;
|
|
|
|
dalx2 = xb1[j]; darx2 = xb2[j];
|
|
if (max(yb1[MAXWALLSB-1],yb2[MAXWALLSB-1]) > min(yb1[j],yb2[j]))
|
|
{
|
|
if (min(yb1[MAXWALLSB-1],yb2[MAXWALLSB-1]) > max(yb1[j],yb2[j]))
|
|
{
|
|
x = 0x80000000;
|
|
}
|
|
else
|
|
{
|
|
x = thewall[j]; xp1 = wall[x].x; yp1 = wall[x].y;
|
|
x = wall[x].point2; xp2 = wall[x].x; yp2 = wall[x].y;
|
|
|
|
z1 = (xp2-xp1)*(y1-yp1) - (yp2-yp1)*(x1-xp1);
|
|
z2 = (xp2-xp1)*(y2-yp1) - (yp2-yp1)*(x2-xp1);
|
|
if ((z1^z2) >= 0)
|
|
x = (z1+z2);
|
|
else
|
|
{
|
|
z1 = (x2-x1)*(yp1-y1) - (y2-y1)*(xp1-x1);
|
|
z2 = (x2-x1)*(yp2-y1) - (y2-y1)*(xp2-x1);
|
|
|
|
if ((z1^z2) >= 0)
|
|
x = -(z1+z2);
|
|
else
|
|
{
|
|
if ((xp2-xp1)*(tspr->y-yp1) == (tspr->x-xp1)*(yp2-yp1))
|
|
{
|
|
if (wall[thewall[j]].nextsector == tspr->sectnum)
|
|
x = 0x80000000;
|
|
else
|
|
x = 0x7fffffff;
|
|
}
|
|
else
|
|
{ //INTERSECTION!
|
|
x = (xp1-globalposx) + scale(xp2-xp1,z1,z1-z2);
|
|
y = (yp1-globalposy) + scale(yp2-yp1,z1,z1-z2);
|
|
|
|
yp1 = dmulscale14(x,cosglobalang,y,singlobalang);
|
|
if (yp1 > 0)
|
|
{
|
|
xp1 = dmulscale14(y,cosglobalang,-x,singlobalang);
|
|
|
|
x = halfxdimen + scale(xp1,halfxdimen,yp1);
|
|
if (xp1 >= 0) x++; //Fix for SIGNED divide
|
|
|
|
if (z1 < 0)
|
|
{ if (dalx2 < x) dalx2 = x; }
|
|
else
|
|
{ if (darx2 > x) darx2 = x; }
|
|
x = 0x80000001;
|
|
}
|
|
else
|
|
x = 0x7fffffff;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (x < 0)
|
|
{
|
|
if (dalx2 < xb1[MAXWALLSB-1]) dalx2 = xb1[MAXWALLSB-1];
|
|
if (darx2 > xb2[MAXWALLSB-1]) darx2 = xb2[MAXWALLSB-1];
|
|
switch (smostwalltype[i])
|
|
{
|
|
case 0:
|
|
if (dalx2 <= darx2)
|
|
{
|
|
if ((dalx2 == xb1[MAXWALLSB-1]) && (darx2 == xb2[MAXWALLSB-1])) return;
|
|
//clearbufbyte(&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<npoints;z++)
|
|
{
|
|
zz = z+1; if (zz == npoints) zz = 0;
|
|
zsgn = zzsgn; zzsgn = rxi[zz]+rzi[zz];
|
|
if (zsgn >= 0)
|
|
{
|
|
rxi2[npoints2] = rxi[z]; ryi2[npoints2] = ryi[z]; rzi2[npoints2] = rzi[z];
|
|
npoints2++;
|
|
}
|
|
if ((zsgn^zzsgn) < 0)
|
|
{
|
|
t = divscale30(zsgn,zsgn-zzsgn);
|
|
rxi2[npoints2] = rxi[z] + mulscale30(t,rxi[zz]-rxi[z]);
|
|
ryi2[npoints2] = ryi[z] + mulscale30(t,ryi[zz]-ryi[z]);
|
|
rzi2[npoints2] = rzi[z] + mulscale30(t,rzi[zz]-rzi[z]);
|
|
npoints2++;
|
|
}
|
|
}
|
|
if (npoints2 <= 2) return;
|
|
|
|
//Clip edge 2
|
|
npoints = 0;
|
|
zzsgn = rxi2[0]-rzi2[0];
|
|
for (z=0;z<npoints2;z++)
|
|
{
|
|
zz = z+1; if (zz == npoints2) zz = 0;
|
|
zsgn = zzsgn; zzsgn = rxi2[zz]-rzi2[zz];
|
|
if (zsgn <= 0)
|
|
{
|
|
rxi[npoints] = rxi2[z]; ryi[npoints] = ryi2[z]; rzi[npoints] = rzi2[z];
|
|
npoints++;
|
|
}
|
|
if ((zsgn^zzsgn) < 0)
|
|
{
|
|
t = divscale30(zsgn,zsgn-zzsgn);
|
|
rxi[npoints] = rxi2[z] + mulscale30(t,rxi2[zz]-rxi2[z]);
|
|
ryi[npoints] = ryi2[z] + mulscale30(t,ryi2[zz]-ryi2[z]);
|
|
rzi[npoints] = rzi2[z] + mulscale30(t,rzi2[zz]-rzi2[z]);
|
|
npoints++;
|
|
}
|
|
}
|
|
if (npoints <= 2) return;
|
|
|
|
//Clip edge 3
|
|
npoints2 = 0;
|
|
zzsgn = ryi[0]*halfxdimen + (rzi[0]*(globalhoriz-0));
|
|
for (z=0;z<npoints;z++)
|
|
{
|
|
zz = z+1; if (zz == npoints) zz = 0;
|
|
zsgn = zzsgn; zzsgn = ryi[zz]*halfxdimen + (rzi[zz]*(globalhoriz-0));
|
|
if (zsgn >= 0)
|
|
{
|
|
rxi2[npoints2] = rxi[z];
|
|
ryi2[npoints2] = ryi[z];
|
|
rzi2[npoints2] = rzi[z];
|
|
npoints2++;
|
|
}
|
|
if ((zsgn^zzsgn) < 0)
|
|
{
|
|
t = divscale30(zsgn,zsgn-zzsgn);
|
|
rxi2[npoints2] = rxi[z] + mulscale30(t,rxi[zz]-rxi[z]);
|
|
ryi2[npoints2] = ryi[z] + mulscale30(t,ryi[zz]-ryi[z]);
|
|
rzi2[npoints2] = rzi[z] + mulscale30(t,rzi[zz]-rzi[z]);
|
|
npoints2++;
|
|
}
|
|
}
|
|
if (npoints2 <= 2) return;
|
|
|
|
//Clip edge 4
|
|
npoints = 0;
|
|
zzsgn = ryi2[0]*halfxdimen + (rzi2[0]*(globalhoriz-ydimen));
|
|
for (z=0;z<npoints2;z++)
|
|
{
|
|
zz = z+1; if (zz == npoints2) zz = 0;
|
|
zsgn = zzsgn; zzsgn = ryi2[zz]*halfxdimen + (rzi2[zz]*(globalhoriz-ydimen));
|
|
if (zsgn <= 0)
|
|
{
|
|
rxi[npoints] = rxi2[z];
|
|
ryi[npoints] = ryi2[z];
|
|
rzi[npoints] = rzi2[z];
|
|
npoints++;
|
|
}
|
|
if ((zsgn^zzsgn) < 0)
|
|
{
|
|
t = divscale30(zsgn,zsgn-zzsgn);
|
|
rxi[npoints] = rxi2[z] + mulscale30(t,rxi2[zz]-rxi2[z]);
|
|
ryi[npoints] = ryi2[z] + mulscale30(t,ryi2[zz]-ryi2[z]);
|
|
rzi[npoints] = rzi2[z] + mulscale30(t,rzi2[zz]-rzi2[z]);
|
|
npoints++;
|
|
}
|
|
}
|
|
if (npoints <= 2) return;
|
|
|
|
//Project onto screen
|
|
lpoint = -1; lmax = 0x7fffffff;
|
|
rpoint = -1; rmax = 0x80000000;
|
|
for (z=0;z<npoints;z++)
|
|
{
|
|
xsi[z] = scale(rxi[z],xdimen<<15,rzi[z]) + (xdimen<<15);
|
|
ysi[z] = scale(ryi[z],xdimen<<15,rzi[z]) + (globalhoriz<<16);
|
|
if (xsi[z] < 0) xsi[z] = 0;
|
|
if (xsi[z] > (xdimen<<16)) xsi[z] = (xdimen<<16);
|
|
if (ysi[z] < ((long)0<<16)) ysi[z] = ((long)0<<16);
|
|
if (ysi[z] > ((long)ydimen<<16)) ysi[z] = ((long)ydimen<<16);
|
|
if (xsi[z] < lmax) lmax = xsi[z], lpoint = z;
|
|
if (xsi[z] > rmax) rmax = xsi[z], rpoint = z;
|
|
}
|
|
|
|
//Get uwall arrays
|
|
for (z=lpoint;z!=rpoint;z=zz)
|
|
{
|
|
zz = z+1; if (zz == npoints) zz = 0;
|
|
|
|
dax1 = ((xsi[z]+65535)>>16);
|
|
dax2 = ((xsi[zz]+65535)>>16);
|
|
if (dax2 > dax1)
|
|
{
|
|
yinc = divscale16(ysi[zz]-ysi[z],xsi[zz]-xsi[z]);
|
|
y = ysi[z] + mulscale16((dax1<<16)-xsi[z],yinc);
|
|
qinterpolatedown16short((long)(&uwall[dax1]),dax2-dax1,y,yinc);
|
|
}
|
|
}
|
|
|
|
//Get dwall arrays
|
|
for (;z!=lpoint;z=zz)
|
|
{
|
|
zz = z+1; if (zz == npoints) zz = 0;
|
|
|
|
dax1 = ((xsi[zz]+65535)>>16);
|
|
dax2 = ((xsi[z]+65535)>>16);
|
|
if (dax2 > dax1)
|
|
{
|
|
yinc = divscale16(ysi[zz]-ysi[z],xsi[zz]-xsi[z]);
|
|
y = ysi[zz] + mulscale16((dax1<<16)-xsi[zz],yinc);
|
|
qinterpolatedown16short((long)(&dwall[dax1]),dax2-dax1,y,yinc);
|
|
}
|
|
}
|
|
|
|
|
|
lx = ((lmax+65535)>>16);
|
|
rx = ((rmax+65535)>>16);
|
|
for (x=lx;x<=rx;x++)
|
|
{
|
|
uwall[x] = max(uwall[x],startumost[x+windowx1]-windowy1);
|
|
dwall[x] = min(dwall[x],startdmost[x+windowx1]-windowy1);
|
|
}
|
|
|
|
//Additional uwall/dwall clipping goes here
|
|
for (i=smostwallcnt-1;i>=0;i--)
|
|
{
|
|
j = smostwall[i];
|
|
if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
|
|
if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
|
|
|
|
//if (spritewallfront(tspr,thewall[j]) == 0)
|
|
x = thewall[j]; xp1 = wall[x].x; yp1 = wall[x].y;
|
|
x = wall[x].point2; xp2 = wall[x].x; yp2 = wall[x].y;
|
|
x = (xp2-xp1)*(tspr->y-yp1)-(tspr->x-xp1)*(yp2-yp1);
|
|
if ((yp > yb1[j]) && (yp > yb2[j])) x = -1;
|
|
if ((x >= 0) && ((x != 0) || (wall[thewall[j]].nextsector != tspr->sectnum))) continue;
|
|
|
|
dalx2 = max(xb1[j],lx); darx2 = min(xb2[j],rx);
|
|
|
|
switch (smostwalltype[i])
|
|
{
|
|
case 0:
|
|
if (dalx2 <= darx2)
|
|
{
|
|
if ((dalx2 == lx) && (darx2 == rx)) return;
|
|
//clearbufbyte(&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,(long)((unsigned char)(sec->visibility+16)));
|
|
|
|
x = picsiz[globalpicnum]; y = ((x>>4)&15); x &= 15;
|
|
if (pow2long[x] != xspan)
|
|
{
|
|
x++;
|
|
globalx1 = mulscale(globalx1,xspan,x);
|
|
globalx2 = mulscale(globalx2,xspan,x);
|
|
}
|
|
|
|
dax = globalxpanning; day = globalypanning;
|
|
globalxpanning = -dmulscale6(globalx1,day,globalx2,dax);
|
|
globalypanning = -dmulscale6(globaly1,day,globaly2,dax);
|
|
|
|
globalx2 = mulscale16(globalx2,viewingrange);
|
|
globaly2 = mulscale16(globaly2,viewingrange);
|
|
globalzd = mulscale16(globalzd,viewingrangerecip);
|
|
|
|
globalx1 = (globalx1-globalx2)*halfxdimen;
|
|
globaly1 = (globaly1-globaly2)*halfxdimen;
|
|
|
|
if ((cstat&2) == 0)
|
|
msethlineshift(x,y);
|
|
else
|
|
tsethlineshift(x,y);
|
|
|
|
//Draw it!
|
|
ceilspritescan(lx,rx-1);
|
|
}
|
|
#ifdef SUPERBUILD
|
|
else if ((cstat&48) == 48)
|
|
{
|
|
long nxrepeat, nyrepeat;
|
|
|
|
lx = 0; rx = xdim-1;
|
|
for (x=lx;x<=rx;x++)
|
|
{
|
|
lwall[x] = (long)startumost[x+windowx1]-windowy1;
|
|
swall[x] = (long)startdmost[x+windowx1]-windowy1;
|
|
}
|
|
for (i=smostwallcnt-1;i>=0;i--)
|
|
{
|
|
j = smostwall[i];
|
|
if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
|
|
if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
|
|
if (spritewallfront(tspr,(long)thewall[j]) && ((yp <= yb1[j]) || (yp <= yb2[j]))) continue;
|
|
|
|
dalx2 = max(xb1[j],lx); darx2 = min(xb2[j],rx);
|
|
|
|
switch (smostwalltype[i])
|
|
{
|
|
case 0:
|
|
if (dalx2 <= darx2)
|
|
{
|
|
if ((dalx2 == lx) && (darx2 == rx)) return;
|
|
//clearbufbyte(&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;x<rx;x++)
|
|
if (lwall[x] < swall[x]) break;
|
|
if (x == rx) return;
|
|
}
|
|
|
|
for (i=0;i<MAXVOXMIPS;i++)
|
|
if (!voxoff[vtilenum][i])
|
|
{
|
|
kloadvoxel(vtilenum);
|
|
break;
|
|
}
|
|
|
|
longptr = (long *)voxoff[vtilenum][0];
|
|
|
|
if (voxscale[vtilenum] == 65536)
|
|
{
|
|
nxrepeat = (((long)tspr->xrepeat)<<16);
|
|
nyrepeat = (((long)tspr->yrepeat)<<16);
|
|
}
|
|
else
|
|
{
|
|
nxrepeat = ((long)tspr->xrepeat)*voxscale[vtilenum];
|
|
nyrepeat = ((long)tspr->yrepeat)*voxscale[vtilenum];
|
|
}
|
|
|
|
if (!(cstat&128)) tspr->z -= mulscale22(B_LITTLE32(longptr[5]),nyrepeat);
|
|
yoff = (long)((signed char)((picanm[sprite[tspr->owner].picnum]>>16)&255))+((long)tspr->yoffset);
|
|
tspr->z -= mulscale14(yoff,nyrepeat);
|
|
|
|
globvis = globalvisibility;
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
|
|
|
|
if ((searchit >= 1) && (yp > (4<<8)) && (searchy >= lwall[searchx]) && (searchy < swall[searchx]))
|
|
{
|
|
siz = divscale19(xdimenscale,yp);
|
|
|
|
xv = mulscale16(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 = (long)tspr->ang+1536;
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
i += spriteext[tspr->owner].angoff;
|
|
#endif
|
|
drawvox(tspr->x,tspr->y,tspr->z,i,(long)tspr->xrepeat,(long)tspr->yrepeat,vtilenum,tspr->shade,tspr->pal,lwall,swall);
|
|
}
|
|
#endif
|
|
if (automapping == 1) show2dsprite[spritenum>>3] |= pow2char[spritenum&7];
|
|
}
|
|
|
|
|
|
//
|
|
// drawmaskwall (internal)
|
|
//
|
|
static void drawmaskwall(short damaskwallcnt)
|
|
{
|
|
long 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; }
|
|
if (rendmode == 4) { polymer_drawmaskwall(damaskwallcnt); return; }
|
|
#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,(char)0);
|
|
wallmost(uplc,z,(long)wal->nextsector,(char)0);
|
|
for (x=xb1[z];x<=xb2[z];x++) if (uplc[x] > uwall[x]) uwall[x] = uplc[x];
|
|
wallmost(dwall,z,sectnum,(char)1);
|
|
wallmost(dplc,z,(long)wal->nextsector,(char)1);
|
|
for (x=xb1[z];x<=xb2[z];x++) if (dplc[x] < dwall[x]) dwall[x] = dplc[x];
|
|
prepwall(z,wal);
|
|
|
|
globalorientation = (long)wal->cstat;
|
|
globalpicnum = wal->overpicnum;
|
|
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
|
|
globalxpanning = (long)wal->xpanning;
|
|
globalypanning = (long)wal->ypanning;
|
|
if (picanm[globalpicnum]&192) globalpicnum += animateoffs(globalpicnum,(short)thewall[z]+16384);
|
|
globalshade = (long)wal->shade;
|
|
globvis = globalvisibility;
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis,(long)((unsigned char)(sec->visibility+16)));
|
|
globalpal = (long)wal->pal;
|
|
globalshiftval = (picsiz[globalpicnum]>>4);
|
|
if (pow2long[globalshiftval] != tilesizy[globalpicnum]) globalshiftval++;
|
|
globalshiftval = 32-globalshiftval;
|
|
globalyscale = (wal->yrepeat<<(globalshiftval-19));
|
|
if ((globalorientation&4) == 0)
|
|
globalzd = (((globalposz-z1)*globalyscale)<<8);
|
|
else
|
|
globalzd = (((globalposz-z2)*globalyscale)<<8);
|
|
globalzd += (globalypanning<<24);
|
|
if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
|
|
|
|
for (i=smostwallcnt-1;i>=0;i--)
|
|
{
|
|
j = smostwall[i];
|
|
if ((xb1[j] > xb2[z]) || (xb2[j] < xb1[z])) continue;
|
|
if (wallfront(j,z)) continue;
|
|
|
|
lx = max(xb1[j],xb1[z]); rx = min(xb2[j],xb2[z]);
|
|
|
|
switch (smostwalltype[i])
|
|
{
|
|
case 0:
|
|
if (lx <= rx)
|
|
{
|
|
if ((lx == xb1[z]) && (rx == xb2[z])) return;
|
|
//clearbufbyte(&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(long npoints)
|
|
{
|
|
long z, zz, x1, y1, x2, y2, miny, maxy, y, xinc, cnt;
|
|
long ox, oy, bx, by, p, day1, day2;
|
|
short *ptr, *ptr2;
|
|
|
|
#if defined POLYMOST && defined USE_OPENGL
|
|
if (rendmode >= 3) { 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<day2;y++) { *dotp2[y]++ = (x1>>12); x1 += xinc; }
|
|
}
|
|
else
|
|
{
|
|
x2 += mulscale12((day2<<12)+4095-y2,xinc);
|
|
for (y=day2;y<day1;y++) { *dotp1[y]++ = (x2>>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 long clippoly(long npoints, long clipstat)
|
|
{
|
|
long z, zz, s1, s2, t, npoints2, start2, z1, z2, z3, z4, splitcnt;
|
|
long 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<splitcnt;z++)
|
|
for (zz=0;zz<z;zz++)
|
|
{
|
|
z1 = p2[z]; z2 = xb2[z1]; z3 = p2[zz]; z4 = xb2[z3];
|
|
s1 = klabs(rx2[z1]-rx2[z2])+klabs(ry2[z1]-ry2[z2]);
|
|
s1 += klabs(rx2[z3]-rx2[z4])+klabs(ry2[z3]-ry2[z4]);
|
|
s2 = klabs(rx2[z1]-rx2[z4])+klabs(ry2[z1]-ry2[z4]);
|
|
s2 += klabs(rx2[z3]-rx2[z2])+klabs(ry2[z3]-ry2[z2]);
|
|
if (s2 < s1)
|
|
{ t = xb2[p2[z]]; xb2[p2[z]] = xb2[p2[zz]]; xb2[p2[zz]] = t; }
|
|
}
|
|
|
|
|
|
npoints = 0; start2 = 0; z = 0; splitcnt = 0;
|
|
do
|
|
{
|
|
s2 = cy1-ry2[z];
|
|
do
|
|
{
|
|
zz = xb2[z]; xb2[z] = -1;
|
|
s1 = s2; s2 = cy1-ry2[zz];
|
|
if (s1 < 0)
|
|
{
|
|
rx1[npoints] = rx2[z]; ry1[npoints] = ry2[z];
|
|
xb1[npoints] = npoints+1; npoints++;
|
|
}
|
|
if ((s1^s2) < 0)
|
|
{
|
|
rx1[npoints] = rx2[z]+scale(rx2[zz]-rx2[z],s1,s1-s2);
|
|
ry1[npoints] = ry2[z]+scale(ry2[zz]-ry2[z],s1,s1-s2);
|
|
if (s1 < 0) p2[splitcnt++] = npoints;
|
|
xb1[npoints] = npoints+1;
|
|
npoints++;
|
|
}
|
|
z = zz;
|
|
} while (xb2[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<splitcnt;z++)
|
|
for (zz=0;zz<z;zz++)
|
|
{
|
|
z1 = p2[z]; z2 = xb1[z1]; z3 = p2[zz]; z4 = xb1[z3];
|
|
s1 = klabs(rx1[z1]-rx1[z2])+klabs(ry1[z1]-ry1[z2]);
|
|
s1 += klabs(rx1[z3]-rx1[z4])+klabs(ry1[z3]-ry1[z4]);
|
|
s2 = klabs(rx1[z1]-rx1[z4])+klabs(ry1[z1]-ry1[z4]);
|
|
s2 += klabs(rx1[z3]-rx1[z2])+klabs(ry1[z3]-ry1[z2]);
|
|
if (s2 < s1)
|
|
{ t = xb1[p2[z]]; xb1[p2[z]] = xb1[p2[zz]]; xb1[p2[zz]] = t; }
|
|
}
|
|
}
|
|
if (clipstat&0x5) //Need to clip bottom or right
|
|
{
|
|
npoints2 = 0; start2 = 0; z = 0; splitcnt = 0;
|
|
do
|
|
{
|
|
s2 = rx1[z]-cx2;
|
|
do
|
|
{
|
|
zz = xb1[z]; xb1[z] = -1;
|
|
s1 = s2; s2 = rx1[zz]-cx2;
|
|
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<splitcnt;z++)
|
|
for (zz=0;zz<z;zz++)
|
|
{
|
|
z1 = p2[z]; z2 = xb2[z1]; z3 = p2[zz]; z4 = xb2[z3];
|
|
s1 = klabs(rx2[z1]-rx2[z2])+klabs(ry2[z1]-ry2[z2]);
|
|
s1 += klabs(rx2[z3]-rx2[z4])+klabs(ry2[z3]-ry2[z4]);
|
|
s2 = klabs(rx2[z1]-rx2[z4])+klabs(ry2[z1]-ry2[z4]);
|
|
s2 += klabs(rx2[z3]-rx2[z2])+klabs(ry2[z3]-ry2[z2]);
|
|
if (s2 < s1)
|
|
{ t = xb2[p2[z]]; xb2[p2[z]] = xb2[p2[zz]]; xb2[p2[zz]] = t; }
|
|
}
|
|
|
|
|
|
npoints = 0; start2 = 0; z = 0; splitcnt = 0;
|
|
do
|
|
{
|
|
s2 = ry2[z]-cy2;
|
|
do
|
|
{
|
|
zz = xb2[z]; xb2[z] = -1;
|
|
s1 = s2; s2 = ry2[zz]-cy2;
|
|
if (s1 < 0)
|
|
{
|
|
rx1[npoints] = rx2[z]; ry1[npoints] = ry2[z];
|
|
xb1[npoints] = npoints+1; npoints++;
|
|
}
|
|
if ((s1^s2) < 0)
|
|
{
|
|
rx1[npoints] = rx2[z]+scale(rx2[zz]-rx2[z],s1,s1-s2);
|
|
ry1[npoints] = ry2[z]+scale(ry2[zz]-ry2[z],s1,s1-s2);
|
|
if (s1 < 0) p2[splitcnt++] = npoints;
|
|
xb1[npoints] = npoints+1;
|
|
npoints++;
|
|
}
|
|
z = zz;
|
|
} while (xb2[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<splitcnt;z++)
|
|
for (zz=0;zz<z;zz++)
|
|
{
|
|
z1 = p2[z]; z2 = xb1[z1]; z3 = p2[zz]; z4 = xb1[z3];
|
|
s1 = klabs(rx1[z1]-rx1[z2])+klabs(ry1[z1]-ry1[z2]);
|
|
s1 += klabs(rx1[z3]-rx1[z4])+klabs(ry1[z3]-ry1[z4]);
|
|
s2 = klabs(rx1[z1]-rx1[z4])+klabs(ry1[z1]-ry1[z4]);
|
|
s2 += klabs(rx1[z3]-rx1[z2])+klabs(ry1[z3]-ry1[z2]);
|
|
if (s2 < s1)
|
|
{ t = xb1[p2[z]]; xb1[p2[z]] = xb1[p2[zz]]; xb1[p2[zz]] = t; }
|
|
}
|
|
}
|
|
return(npoints);
|
|
}
|
|
|
|
|
|
//
|
|
// clippoly4 (internal)
|
|
//
|
|
//Assume npoints=4 with polygon on &nrx1,&nry1
|
|
//JBF 20031206: Thanks to Ken's hunting, s/(rx1|ry1|rx2|ry2)/n\1/ in this function
|
|
static long clippoly4(long cx1, long cy1, long cx2, long cy2)
|
|
{
|
|
long n, nn, z, zz, x, x1, x2, y, y1, y2, t;
|
|
|
|
nn = 0; z = 0;
|
|
do
|
|
{
|
|
zz = ((z+1)&3);
|
|
x1 = nrx1[z]; x2 = nrx1[zz]-x1;
|
|
|
|
if ((cx1 <= x1) && (x1 <= cx2))
|
|
nrx2[nn] = x1, nry2[nn] = nry1[z], nn++;
|
|
|
|
if (x2 <= 0) x = cx2; else x = cx1;
|
|
t = x-x1;
|
|
if (((t-x2)^t) < 0)
|
|
nrx2[nn] = x, nry2[nn] = nry1[z]+scale(t,nry1[zz]-nry1[z],x2), nn++;
|
|
|
|
if (x2 <= 0) x = cx1; else x = cx2;
|
|
t = x-x1;
|
|
if (((t-x2)^t) < 0)
|
|
nrx2[nn] = x, nry2[nn] = nry1[z]+scale(t,nry1[zz]-nry1[z],x2), nn++;
|
|
|
|
z = zz;
|
|
} while (z != 0);
|
|
if (nn < 3) return(0);
|
|
|
|
n = 0; z = 0;
|
|
do
|
|
{
|
|
zz = z+1; if (zz == nn) zz = 0;
|
|
y1 = nry2[z]; y2 = nry2[zz]-y1;
|
|
|
|
if ((cy1 <= y1) && (y1 <= cy2))
|
|
nry1[n] = y1, nrx1[n] = nrx2[z], n++;
|
|
|
|
if (y2 <= 0) y = cy2; else y = cy1;
|
|
t = y-y1;
|
|
if (((t-y2)^t) < 0)
|
|
nry1[n] = y, nrx1[n] = nrx2[z]+scale(t,nrx2[zz]-nrx2[z],y2), n++;
|
|
|
|
if (y2 <= 0) y = cy1; else y = cy2;
|
|
t = y-y1;
|
|
if (((t-y2)^t) < 0)
|
|
nry1[n] = y, nrx1[n] = nrx2[z]+scale(t,nrx2[zz]-nrx2[z],y2), n++;
|
|
|
|
z = zz;
|
|
} while (z != 0);
|
|
return(n);
|
|
}
|
|
|
|
|
|
//
|
|
// dorotatesprite (internal)
|
|
//
|
|
//JBF 20031206: Thanks to Ken's hunting, s/(rx1|ry1|rx2|ry2)/n\1/ in this function
|
|
static void dorotatesprite(long sx, long sy, long z, short a, short picnum, signed char dashade, char dapalnum, char dastat, long cx1, long cy1, long cx2, long cy2, long uniqid)
|
|
{
|
|
long cosang, sinang, v, nextv, dax1, dax2, oy, bx, by, ny1, ny2;
|
|
long i, x, y, x1, y1, x2, y2, gx1, gy1, p, bufplc, palookupoffs;
|
|
long xsiz, ysiz, xoff, yoff, npoints, yplc, yinc, lx, rx, xx, xend;
|
|
long xv, yv, xv2, yv2, obuffermode, qlinemode=0, y1ve[4], y2ve[4], u4, d4;
|
|
char bad;
|
|
|
|
//============================================================================= //POLYMOST BEGINS
|
|
#ifdef POLYMOST
|
|
if (rendmode >= 3) { polymost_dorotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,cx1,cy1,cx2,cy2,uniqid); return; }
|
|
if (rendmode == 4) { polymer_rotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,cx1,cy1,cx2,cy2); return; }
|
|
#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 = (long)((signed char)((picanm[picnum]>>8)&255))+(xsiz>>1);
|
|
yoff = (long)((signed char)((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;
|
|
i = (cy2<<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;
|
|
i = (cx2<<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((long)(&uplc[dax1]),dax2-dax1,yplc,yinc);
|
|
}
|
|
else
|
|
{
|
|
yplc = y2 + mulscale16((dax2<<16)+65535-x2,yinc);
|
|
qinterpolatedown16short((long)(&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,(long)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<x2;x+=4)
|
|
{
|
|
bad = 15; xend = min(x2-x,4);
|
|
for (xx=0;xx<xend;xx++)
|
|
{
|
|
bx += xv2;
|
|
|
|
y1 = uplc[x+xx]; y2 = dplc[x+xx];
|
|
if ((dastat&8) == 0)
|
|
{
|
|
if (startumost[x+xx] > 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<x2;x++)
|
|
{
|
|
ny1 = uplc[x]-1; ny2 = dplc[x];
|
|
if ((dastat&8) == 0)
|
|
{
|
|
if (startumost[x]-1 > 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<x2;x++)
|
|
{
|
|
bx += xv2; by += yv2;
|
|
|
|
y1 = uplc[x]; y2 = dplc[x];
|
|
if ((dastat&8) == 0)
|
|
{
|
|
if (startumost[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<x2;x++)
|
|
{
|
|
bx += xv2; by += yv2;
|
|
|
|
y1 = uplc[x]; y2 = dplc[x];
|
|
if ((dastat&8) == 0)
|
|
{
|
|
if (startumost[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 void initksqrt(void)
|
|
{
|
|
long i, j, k;
|
|
|
|
j = 1; k = 0;
|
|
for (i=0;i<4096;i++)
|
|
{
|
|
if (i >= j) { j <<= 2; k++; }
|
|
sqrtable[i] = (unsigned short)(msqrtasm((i<<18)+131072)<<1);
|
|
shlookup[i] = (k<<1)+((10-k)<<8);
|
|
if (i < 256) shlookup[i+4096] = ((k+6)<<1)+((10-(k+6))<<8);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// dosetaspect
|
|
//
|
|
static void dosetaspect(void)
|
|
{
|
|
long i, j, k, x, xinc,a;
|
|
|
|
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<xdimen;i++)
|
|
{
|
|
j = (x&65535); k = (x>>16); x += xinc;
|
|
if (j != 0) j = mulscale16((long)radarang[k+1]-(long)radarang[k],j);
|
|
radarang2[i] = (short)(((long)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 void calcbritable(void)
|
|
{
|
|
int 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] = (char)(pow((double)j,a)*b);
|
|
}
|
|
}
|
|
|
|
static int loadtables(void)
|
|
{
|
|
long i, fil;
|
|
|
|
if (tablesloaded == 0)
|
|
{
|
|
initksqrt();
|
|
|
|
for (i=0;i<2048;i++) reciptable[i] = divscale30(2048L,i+2048);
|
|
|
|
if ((fil = kopen4load("tables.dat",0)) != -1)
|
|
{
|
|
kread(fil,sintable,2048*2); 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(long rscale, long gscale, long bscale)
|
|
{
|
|
long 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)
|
|
{
|
|
long fil,i;
|
|
|
|
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 *)kkmalloc(numpalookups<<8)) == NULL)
|
|
allocache((long*)&palookup[0],numpalookups<<8,&permanentlock);
|
|
if ((transluc = (char *)kkmalloc(65536L)) == NULL)
|
|
allocache((long*)&transluc,65536,&permanentlock);
|
|
|
|
globalpalwritten = palookup[0]; globalpal = 0;
|
|
setpalookupaddress(globalpalwritten);
|
|
|
|
fixtransluscence(FP_OFF(transluc));
|
|
|
|
kread(fil,palookup[globalpal],numpalookups<<8);
|
|
kread(fil,transluc,65536);
|
|
kclose(fil);
|
|
|
|
initfastcolorlookup(30L,59L,11L);
|
|
|
|
paletteloaded = 1;
|
|
}
|
|
|
|
|
|
//
|
|
// getclosestcol (internal)
|
|
//
|
|
static long getclosestcol(long r, long g, long b)
|
|
{
|
|
long 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)
|
|
//
|
|
static long insertspritesect(short sectnum)
|
|
{
|
|
short 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)
|
|
//
|
|
static long insertspritestat(short statnum)
|
|
{
|
|
short 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)
|
|
//
|
|
static long deletespritesect(short 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)
|
|
//
|
|
static long deletespritestat(short 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 long lintersect(long x1, long y1, long z1, long x2, long y2, long z2, long x3,
|
|
long y3, long x4, long y4, long *intx, long *inty, long *intz)
|
|
{ //p1 to p2 is a line segment
|
|
long 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);
|
|
}
|
|
|
|
|
|
//
|
|
// rintersect (internal)
|
|
//
|
|
static long rintersect(long x1, long y1, long z1, long vx, long vy, long vz, long x3,
|
|
long y3, long x4, long y4, long *intx, long *inty, long *intz)
|
|
{ //p1 towards p2 is a ray
|
|
long 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);
|
|
}
|
|
|
|
|
|
//
|
|
// keepaway (internal)
|
|
//
|
|
static void keepaway (long *x, long *y, long w)
|
|
{
|
|
long 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 long raytrace(long x3, long y3, long *x4, long *y4)
|
|
{
|
|
long x1, y1, x2, y2, bot, topu, nintx, ninty, cnt, z, hitwall;
|
|
long 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 <signal.h>
|
|
static void sighandler(int sig, const siginfo_t *info, void *ctx)
|
|
{
|
|
const char *s;
|
|
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 int preinitcalled = 0;
|
|
int preinitengine(void)
|
|
{
|
|
char *e;
|
|
if (initsystem()) exit(1);
|
|
|
|
if ((e = Bgetenv("BUILD_NOP6")) != NULL)
|
|
if (!Bstrcasecmp(e, "TRUE")) {
|
|
Bprintf("Disabling P6 optimizations.\n");
|
|
dommxoverlay = 0;
|
|
}
|
|
if (dommxoverlay) mmxoverlay();
|
|
|
|
validmodecnt = 0;
|
|
getvalidmodes();
|
|
|
|
initcrc32table();
|
|
|
|
preinitcalled = 1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// initengine
|
|
//
|
|
int initengine(void)
|
|
{
|
|
long 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<MAXVOXELS;i++)
|
|
for (j=0;j<MAXVOXMIPS;j++)
|
|
{
|
|
voxoff[i][j] = 0L;
|
|
voxlock[i][j] = 200;
|
|
}
|
|
for (i=0;i<MAXTILES;i++)
|
|
tiletovox[i] = -1;
|
|
clearbuf(&voxscale[0],sizeof(voxscale)>>2,65536L);
|
|
#endif
|
|
|
|
#ifdef POLYMOST
|
|
polymost_initosdfuncs();
|
|
#endif
|
|
|
|
paletteloaded = 0;
|
|
|
|
searchit = 0; searchstat = -1;
|
|
|
|
for (i=0;i<MAXPALOOKUPS;i++) palookup[i] = NULL;
|
|
|
|
clearbuf(&waloff[0],(long)MAXTILES,0L);
|
|
|
|
clearbuf(&show2dsector[0],(long)((MAXSECTORS+3)>>5),0L);
|
|
clearbuf(&show2dsprite[0],(long)((MAXSPRITES+3)>>5),0L);
|
|
clearbuf(&show2dwall[0],(long)((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)
|
|
{
|
|
long i;
|
|
|
|
//OSD_Printf("cacheresets = %d, cacheinvalidates = %d\n", cacheresets, cacheinvalidates);
|
|
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
polymost_glreset();
|
|
hicinit();
|
|
freeallmodels();
|
|
#endif
|
|
|
|
uninitsystem();
|
|
if (artfil != -1) kclose(artfil);
|
|
|
|
if (transluc != NULL) { kkfree(transluc); transluc = NULL; }
|
|
if (pic != NULL) { kkfree(pic); pic = NULL; }
|
|
if (lookups != NULL)
|
|
{
|
|
if (lookupsalloctype == 0) kkfree((void *)lookups);
|
|
//if (lookupsalloctype == 1) suckcache(lookups); //Cache already gone
|
|
lookups = NULL;
|
|
}
|
|
for (i=0;i<MAXPALOOKUPS;i++)
|
|
if (palookup[i] != NULL) { kkfree(palookup[i]); palookup[i] = NULL; }
|
|
}
|
|
|
|
|
|
//
|
|
// initspritelists
|
|
//
|
|
void initspritelists(void)
|
|
{
|
|
long i;
|
|
|
|
for (i=0;i<MAXSECTORS;i++) //Init doubly-linked sprite sector lists
|
|
headspritesect[i] = -1;
|
|
headspritesect[MAXSECTORS] = 0;
|
|
for (i=0;i<MAXSPRITES;i++)
|
|
{
|
|
prevspritesect[i] = i-1;
|
|
nextspritesect[i] = i+1;
|
|
sprite[i].sectnum = MAXSECTORS;
|
|
}
|
|
prevspritesect[0] = -1;
|
|
nextspritesect[MAXSPRITES-1] = -1;
|
|
|
|
|
|
for (i=0;i<MAXSTATUS;i++) //Init doubly-linked sprite status lists
|
|
headspritestat[i] = -1;
|
|
headspritestat[MAXSTATUS] = 0;
|
|
for (i=0;i<MAXSPRITES;i++)
|
|
{
|
|
prevspritestat[i] = i-1;
|
|
nextspritestat[i] = i+1;
|
|
sprite[i].statnum = MAXSTATUS;
|
|
}
|
|
prevspritestat[0] = -1;
|
|
nextspritestat[MAXSPRITES-1] = -1;
|
|
}
|
|
|
|
|
|
//
|
|
// drawrooms
|
|
//
|
|
void drawrooms(long daposx, long daposy, long daposz,
|
|
short daang, long dahoriz, short dacursectnum)
|
|
{
|
|
long i, j, z, cz, fz, closest;
|
|
short *shortptr1, *shortptr2;
|
|
|
|
beforedrawrooms = 0;
|
|
indrawroomsandmasks = 1;
|
|
|
|
globalposx = daposx; globalposy = daposy; globalposz = daposz;
|
|
globalang = (daang&2047);
|
|
|
|
globalhoriz = mulscale16(dahoriz-100,xdimenscale)+(ydimen>>1);
|
|
|
|
globaluclip = (0-globalhoriz)*xdimscale;
|
|
globaldclip = (ydimen-globalhoriz)*xdimscale;
|
|
|
|
i = mulscale16(xdimenscale,viewingrangerecip);
|
|
globalpisibility = mulscale16(parallaxvisibility,i);
|
|
globalvisibility = mulscale16(visibility,i);
|
|
globalhisibility = mulscale16(globalvisibility,xyaspect);
|
|
globalcisibility = mulscale8(globalhisibility,320);
|
|
|
|
globalcursectnum = dacursectnum;
|
|
totalclocklock = totalclock;
|
|
|
|
cosglobalang = sintable[(globalang+512)&2047];
|
|
singlobalang = sintable[globalang&2047];
|
|
cosviewingrangeglobalang = mulscale16(cosglobalang,viewingrange);
|
|
sinviewingrangeglobalang = mulscale16(singlobalang,viewingrange);
|
|
|
|
if ((xyaspect != oxyaspect) || (xdimen != oxdimen) || (viewingrange != oviewingrange))
|
|
dosetaspect();
|
|
|
|
//clearbufbyte(&gotsector[0],(long)((numsectors+7)>>3),0L);
|
|
Bmemset(&gotsector[0],0,(long)((numsectors+7)>>3));
|
|
|
|
shortptr1 = (short *)&startumost[windowx1];
|
|
shortptr2 = (short *)&startdmost[windowx1];
|
|
i = xdimen-1;
|
|
do
|
|
{
|
|
umost[i] = shortptr1[i]-windowy1;
|
|
dmost[i] = shortptr2[i]-windowy1;
|
|
i--;
|
|
} while (i != 0);
|
|
umost[0] = shortptr1[0]-windowy1;
|
|
dmost[0] = shortptr2[0]-windowy1;
|
|
|
|
#ifdef POLYMOST
|
|
if (rendmode == 4)
|
|
{
|
|
polymer_glinit();
|
|
polymer_drawrooms(daposx, daposy, daposz, daang, dahoriz, dacursectnum, 1);
|
|
bglDisable(GL_CULL_FACE);
|
|
return;
|
|
}
|
|
|
|
//============================================================================= //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);*/ printOSD("Nice try.\n"); exit(0); }
|
|
|
|
numhits = xdimen; numscans = 0; numbunches = 0;
|
|
maskwallcnt = 0; smostwallcnt = 0; smostcnt = 0; spritesortcnt = 0;
|
|
|
|
if (globalcursectnum >= MAXSECTORS)
|
|
globalcursectnum -= MAXSECTORS;
|
|
else
|
|
{
|
|
i = globalcursectnum;
|
|
updatesector(globalposx,globalposy,&globalcursectnum);
|
|
if (globalcursectnum < 0) globalcursectnum = i;
|
|
}
|
|
|
|
globparaceilclip = 1;
|
|
globparaflorclip = 1;
|
|
getzsofslope(globalcursectnum,globalposx,globalposy,&cz,&fz);
|
|
if (globalposz < cz) globparaceilclip = 0;
|
|
if (globalposz > fz) globparaflorclip = 0;
|
|
|
|
scansector(globalcursectnum);
|
|
|
|
if (inpreparemirror)
|
|
{
|
|
inpreparemirror = 0;
|
|
mirrorsx1 = xdimen-1; mirrorsx2 = 0;
|
|
for (i=numscans-1;i>=0;i--)
|
|
{
|
|
if (wall[thewall[i]].nextsector < 0) continue;
|
|
if (xb1[i] < mirrorsx1) mirrorsx1 = xb1[i];
|
|
if (xb2[i] > mirrorsx2) mirrorsx2 = xb2[i];
|
|
}
|
|
|
|
for (i=0;i<mirrorsx1;i++)
|
|
if (umost[i] <= dmost[i])
|
|
{ umost[i] = 1; dmost[i] = 0; numhits--; }
|
|
for (i=mirrorsx2+1;i<xdimen;i++)
|
|
if (umost[i] <= dmost[i])
|
|
{ umost[i] = 1; dmost[i] = 0; numhits--; }
|
|
|
|
drawalls(0L);
|
|
numbunches--;
|
|
bunchfirst[0] = bunchfirst[numbunches];
|
|
bunchlast[0] = bunchlast[numbunches];
|
|
|
|
mirrorsy1 = min(umost[mirrorsx1],umost[mirrorsx2]);
|
|
mirrorsy2 = max(dmost[mirrorsx1],dmost[mirrorsx2]);
|
|
}
|
|
|
|
while ((numbunches > 0) && (numhits > 0))
|
|
{
|
|
clearbuf(&tempbuf[0],(long)((numbunches+3)>>2),0L);
|
|
tempbuf[0] = 1;
|
|
|
|
closest = 0; //Almost works, but not quite :(
|
|
for (i=1;i<numbunches;i++)
|
|
{
|
|
if ((j = bunchfront(i,closest)) < 0) continue;
|
|
tempbuf[i] = 1;
|
|
if (j == 0) tempbuf[closest] = 1, closest = i;
|
|
}
|
|
for (i=0;i<numbunches;i++) //Double-check
|
|
{
|
|
if (tempbuf[i]) continue;
|
|
if ((j = bunchfront(i,closest)) < 0) continue;
|
|
tempbuf[i] = 1;
|
|
if (j == 0) tempbuf[closest] = 1, closest = i, i = 0;
|
|
}
|
|
|
|
drawalls(closest);
|
|
|
|
if (automapping)
|
|
{
|
|
for (z=bunchfirst[closest];z>=0;z=p2[z])
|
|
show2dwall[thewall[z]>>3] |= pow2char[thewall[z]&7];
|
|
}
|
|
|
|
numbunches--;
|
|
bunchfirst[closest] = bunchfirst[numbunches];
|
|
bunchlast[closest] = bunchlast[numbunches];
|
|
}
|
|
|
|
enddrawing(); //}}}
|
|
}
|
|
|
|
// UTILITY TYPES AND FUNCTIONS FOR DRAWMASKS OCCLUSION TREE
|
|
typedef struct s_maskleaf {
|
|
long index;
|
|
_point2d p1, p2;
|
|
_equation maskeq, p1eq, p2eq;
|
|
struct s_maskleaf* branch[MAXWALLSB];
|
|
int drawing;
|
|
} _maskleaf;
|
|
|
|
_maskleaf maskleaves[MAXWALLSB];
|
|
|
|
// returns equation of a line given two points
|
|
_equation equation(long x1, long y1, long x2, long 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);
|
|
}
|
|
|
|
// 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
|
|
int 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
|
|
int 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
|
|
void drawmaskleaf(_maskleaf* wall)
|
|
{
|
|
int 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);
|
|
}
|
|
|
|
int 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);
|
|
}
|
|
|
|
#ifdef USE_OPENGL
|
|
void drawpeel(int peel)
|
|
{
|
|
bglBindTexture(GL_TEXTURE_RECTANGLE, peels[peel]);
|
|
bglBegin(GL_QUADS);
|
|
bglTexCoord2f(0.0f, 0.0f);
|
|
bglVertex2f(-1.0f, -1.0f);
|
|
bglTexCoord2f(xdim, 0.0f);
|
|
bglVertex2f(1.0f, -1.0f);
|
|
bglTexCoord2f(xdim, ydim);
|
|
bglVertex2f(1.0f, 1.0f);
|
|
bglTexCoord2f(0.0f, ydim);
|
|
bglVertex2f(-1.0f, 1.0f);
|
|
bglEnd();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// drawmasks
|
|
//
|
|
void drawmasks(void)
|
|
{
|
|
long i, j, k, l, m, gap, xs, ys, xp, yp, yoff, yspan;
|
|
// PLAG: sorting stuff
|
|
_equation maskeq, p1eq, p2eq;
|
|
_point2d dot, dot2, middle, pos, spr;
|
|
|
|
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)
|
|
{
|
|
tspriteptr[i] = tspriteptr[spritesortcnt];
|
|
spritesx[i] = spritesx[spritesortcnt];
|
|
spritesy[i] = spritesy[spritesortcnt];
|
|
}
|
|
continue;
|
|
}
|
|
spritesy[i] = yp;
|
|
}
|
|
|
|
#ifdef USE_OPENGL
|
|
if ((!r_depthpeeling) || (rendmode < 3))
|
|
#endif
|
|
{
|
|
|
|
gap = 1; while (gap < spritesortcnt) gap = (gap<<1)+1;
|
|
for (gap>>=1;gap>0;gap>>=1) //Sort sprite list
|
|
for (i=0;i<spritesortcnt-gap;i++)
|
|
for (l=i;l>=0;l-=gap)
|
|
{
|
|
if (spritesy[l] <= spritesy[l+gap]) break;
|
|
swaplong(&tspriteptr[l],&tspriteptr[l+gap]);
|
|
swaplong(&spritesx[l],&spritesx[l+gap]);
|
|
swaplong(&spritesy[l],&spritesy[l+gap]);
|
|
}
|
|
|
|
if (spritesortcnt > 0)
|
|
spritesy[spritesortcnt] = (spritesy[spritesortcnt-1]^1);
|
|
|
|
ys = spritesy[0]; i = 0;
|
|
for (j=1;j<=spritesortcnt;j++)
|
|
{
|
|
if (spritesy[j] == ys) continue;
|
|
ys = spritesy[j];
|
|
if (j > i+1)
|
|
{
|
|
for (k=i;k<j;k++)
|
|
{
|
|
spritesz[k] = tspriteptr[k]->z;
|
|
if ((tspriteptr[k]->cstat&48) != 32)
|
|
{
|
|
yoff = (long)((signed char)((picanm[tspriteptr[k]->picnum]>>16)&255))+((long)tspriteptr[k]->yoffset);
|
|
spritesz[k] -= ((yoff*tspriteptr[k]->yrepeat)<<2);
|
|
yspan = (tilesizy[tspriteptr[k]->picnum]*tspriteptr[k]->yrepeat<<2);
|
|
if (!(tspriteptr[k]->cstat&128)) spritesz[k] -= (yspan>>1);
|
|
if (klabs(spritesz[k]-globalposz) < (yspan>>1)) spritesz[k] = globalposz;
|
|
}
|
|
}
|
|
for (k=i+1;k<j;k++)
|
|
for (l=i;l<k;l++)
|
|
if (klabs(spritesz[k]-globalposz) < klabs(spritesz[l]-globalposz))
|
|
{
|
|
swaplong(&tspriteptr[k],&tspriteptr[l]);
|
|
swaplong(&spritesx[k],&spritesx[l]);
|
|
swaplong(&spritesy[k],&spritesy[l]);
|
|
swaplong(&spritesz[k],&spritesz[l]);
|
|
}
|
|
for (k=i+1;k<j;k++)
|
|
for (l=i;l<k;l++)
|
|
if (tspriteptr[k]->statnum < tspriteptr[l]->statnum)
|
|
{
|
|
swaplong(&tspriteptr[k],&tspriteptr[l]);
|
|
swaplong(&spritesx[k],&spritesx[l]);
|
|
swaplong(&spritesy[k],&spritesy[l]);
|
|
}
|
|
}
|
|
i = j;
|
|
}
|
|
}
|
|
|
|
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)
|
|
if ((!r_depthpeeling) || (rendmode < 3))
|
|
#endif
|
|
{
|
|
#if defined(USE_OPENGL) && defined(POLYMOST)
|
|
curpolygonoffset = 0;
|
|
#endif
|
|
pos.x = globalposx;
|
|
pos.y = globalposy;
|
|
|
|
while (maskwallcnt)
|
|
{
|
|
maskwallcnt--;
|
|
|
|
dot.x = wall[thewall[maskwall[maskwallcnt]]].x;
|
|
dot.y = wall[thewall[maskwall[maskwallcnt]]].y;
|
|
dot2.x = wall[wall[thewall[maskwall[maskwallcnt]]].point2].x;
|
|
dot2.y = 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 = tspriteptr[i]->x;
|
|
spr.y = 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);
|
|
}
|
|
|
|
} /* depthpeeling */
|
|
#if defined(USE_OPENGL) && defined(POLYMOST)
|
|
else
|
|
{
|
|
curpolygonoffset = 0;
|
|
j = spritesortcnt;
|
|
k = maskwallcnt;
|
|
|
|
while (j > 0) drawsprite(--j);
|
|
while (k > 0) drawmaskwall(--k);
|
|
}
|
|
#endif
|
|
|
|
#if defined(USE_OPENGL) && defined(POLYMOST)
|
|
if ((r_depthpeeling) && (rendmode >= 3))
|
|
{
|
|
bglPopAttrib();
|
|
bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
|
|
bglNewList(1, GL_COMPILE);
|
|
|
|
peelcompiling = 1;
|
|
curpolygonoffset = 0;
|
|
|
|
while (spritesortcnt > 0) drawsprite(--spritesortcnt);
|
|
while (maskwallcnt > 0) drawmaskwall(--maskwallcnt);
|
|
|
|
peelcompiling = 0;
|
|
|
|
bglEndList();
|
|
|
|
bglDisable(GL_BLEND);
|
|
bglEnable(GL_ALPHA_TEST);
|
|
bglAlphaFunc(GL_GREATER, 0.0f);
|
|
bglEnable(GL_FRAGMENT_PROGRAM_ARB);
|
|
|
|
i = 0;
|
|
while (i < r_peelscount)
|
|
{
|
|
|
|
if (i > 0)
|
|
{
|
|
bglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, peelprogram[1]);
|
|
bglActiveTextureARB(GL_TEXTURE1_ARB);
|
|
bglBindTexture(GL_TEXTURE_RECTANGLE, ztexture[(i - 1) % 2]);
|
|
bglActiveTextureARB(GL_TEXTURE2_ARB);
|
|
bglBindTexture(GL_TEXTURE_RECTANGLE, ztexture[2]);
|
|
bglActiveTextureARB(GL_TEXTURE0_ARB);
|
|
}
|
|
else
|
|
{
|
|
bglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, peelprogram[0]);
|
|
bglActiveTextureARB(GL_TEXTURE1_ARB);
|
|
bglBindTexture(GL_TEXTURE_RECTANGLE, ztexture[2]);
|
|
bglActiveTextureARB(GL_TEXTURE0_ARB);
|
|
}
|
|
|
|
if (i == (r_peelscount - 1))
|
|
bglEnable(GL_BLEND);
|
|
|
|
bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, peelfbos[i]);
|
|
bglPushAttrib(GL_VIEWPORT_BIT);
|
|
bglViewport(0, 0, xdim, ydim);
|
|
|
|
bglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
bglCallList(1);
|
|
|
|
bglPopAttrib();
|
|
bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
|
|
i++;
|
|
}
|
|
|
|
bglDisable(GL_FRAGMENT_PROGRAM_ARB);
|
|
bglEnable(GL_BLEND);
|
|
bglDisable(GL_DEPTH_TEST);
|
|
|
|
bglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
// identity for screen aligned quads
|
|
bglMatrixMode(GL_PROJECTION);
|
|
bglPushMatrix();
|
|
bglLoadIdentity();
|
|
bglMatrixMode(GL_MODELVIEW);
|
|
bglPushMatrix();
|
|
bglLoadIdentity();
|
|
|
|
bglEnable(GL_TEXTURE_RECTANGLE);
|
|
|
|
// backbuffer
|
|
drawpeel(r_peelscount);
|
|
|
|
if (r_curpeel == -1)
|
|
{
|
|
i = r_peelscount - 1;
|
|
while (i >= 0)
|
|
drawpeel(i--);
|
|
}
|
|
else
|
|
drawpeel(r_curpeel);
|
|
|
|
bglDisable(GL_TEXTURE_RECTANGLE);
|
|
bglEnable(GL_TEXTURE_2D);
|
|
|
|
// restore the polymost projection
|
|
bglMatrixMode(GL_PROJECTION);
|
|
bglPopMatrix();
|
|
bglMatrixMode(GL_MODELVIEW);
|
|
bglPopMatrix();
|
|
|
|
bglEnable(GL_DEPTH_TEST);
|
|
|
|
bglDeleteLists(1, 1);
|
|
}
|
|
#endif
|
|
|
|
indrawroomsandmasks = 0;
|
|
enddrawing(); //}}}
|
|
}
|
|
|
|
//
|
|
// drawmapview
|
|
//
|
|
void drawmapview(long dax, long day, long zoome, short ang)
|
|
{
|
|
walltype *wal;
|
|
sectortype *sec;
|
|
spritetype *spr;
|
|
long tilenum, xoff, yoff, i, j, k, l, cosang, sinang, xspan, yspan;
|
|
long xrepeat, yrepeat, x, y, x1, y1, x2, y2, x3, y3, x4, y4, bakx1, baky1;
|
|
long s, w, ox, oy, startwall, cx1, cy1, cx2, cy2;
|
|
long bakgxvect, bakgyvect, sortnum, gap, npoints;
|
|
long xvect, yvect, xvect2, yvect2, daslope;
|
|
|
|
beforedrawrooms = 0;
|
|
|
|
clearbuf(&gotsector[0],(long)((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<numsectors;s++,sec++)
|
|
if (show2dsector[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 = (long)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((short)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,(long)((unsigned char)(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<<globalxshift);
|
|
asm2 = (globalx2<<globalyshift);
|
|
globalx1 <<= globalxshift;
|
|
globaly2 <<= globalyshift;
|
|
globalposx = (globalposx<<(20+globalxshift))+(((long)sec->floorxpanning)<<24);
|
|
globalposy = (globalposy<<(20+globalyshift))-(((long)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<sortnum-gap;i++)
|
|
for (j=i;j>=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 = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
|
|
yoff = (long)((signed char)((picanm[tilenum]>>16)&255))+((long)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;
|
|
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
|
|
setgotpic(globalpicnum);
|
|
if ((tilesizx[globalpicnum] <= 0) || (tilesizy[globalpicnum] <= 0)) continue;
|
|
if ((picanm[globalpicnum]&192) != 0) globalpicnum += animateoffs((short)globalpicnum,s);
|
|
if (waloff[globalpicnum] == 0) loadtile(globalpicnum);
|
|
globalbufplc = waloff[globalpicnum];
|
|
if ((sector[spr->sectnum].ceilingstat&1) > 0)
|
|
globalshade = ((long)sector[spr->sectnum].ceilingshade);
|
|
else
|
|
globalshade = ((long)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,(long)((unsigned char)(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(); //}}}
|
|
}
|
|
|
|
|
|
//
|
|
// loadboard
|
|
//
|
|
long loadboard(char *filename, char fromwhere, long *daposx, long *daposy, long *daposz,
|
|
short *daang, short *dacursectnum)
|
|
{
|
|
short fil, i, numsprites;
|
|
|
|
i = strlen(filename)-1;
|
|
if (filename[i] == 255) { filename[i] = 0; fromwhere = 1; } // JBF 20040119: "compatibility"
|
|
if ((fil = kopen4load(filename,fromwhere)) == -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);
|
|
*/
|
|
|
|
initspritelists();
|
|
|
|
#define MYMAXSECTORS (mapversion==7l?MAXSECTORSV7:MAXSECTORSV8)
|
|
#define MYMAXWALLS (mapversion==7l?MAXWALLSV7:MAXWALLSV8)
|
|
#define MYMAXSPRITES (mapversion==7l?MAXSPRITESV7:MAXSPRITESV8)
|
|
|
|
clearbuf(&show2dsector[0],(long)((MYMAXSECTORS+3)>>5),0L);
|
|
clearbuf(&show2dsprite[0],(long)((MYMAXSPRITES+3)>>5),0L);
|
|
clearbuf(&show2dwall[0],(long)((MYMAXWALLS+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);
|
|
}
|
|
|
|
for (i=0;i<numsprites;i++) {
|
|
if ((sprite[i].cstat & 48) == 48) sprite[i].cstat &= ~48;
|
|
insertsprite(sprite[i].sectnum,sprite[i].statnum);
|
|
}
|
|
|
|
//Must be after loading sectors, etc!
|
|
updatesector(*daposx,*daposy,dacursectnum);
|
|
|
|
kclose(fil);
|
|
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
memset(spriteext, 0, sizeof(spriteext));
|
|
memset(spritesmooth, 0, sizeof(spritesmooth));
|
|
|
|
if (rendmode == 4)
|
|
polymer_loadboard();
|
|
#endif
|
|
guniqhudid = 0;
|
|
|
|
startposx = *daposx;
|
|
startposy = *daposy;
|
|
startposz = *daposz;
|
|
startang = *daang;
|
|
startsectnum = *dacursectnum;
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
//
|
|
// loadboardv5/6
|
|
//
|
|
#ifdef __GNUC__
|
|
#define BPACK __attribute__ ((packed))
|
|
#else
|
|
#define BPACK
|
|
#endif
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma pack(1)
|
|
#endif
|
|
|
|
#ifdef __WATCOMC__
|
|
#pragma pack(push,1);
|
|
#endif
|
|
struct BPACK sectortypev5
|
|
{
|
|
short unsigned int wallptr, wallnum;
|
|
short ceilingpicnum, floorpicnum;
|
|
short ceilingheinum, floorheinum;
|
|
long ceilingz, floorz;
|
|
signed char ceilingshade, floorshade;
|
|
char ceilingxpanning, floorxpanning;
|
|
char ceilingypanning, floorypanning;
|
|
char ceilingstat, floorstat;
|
|
char ceilingpal, floorpal;
|
|
char visibility;
|
|
short lotag, hitag;
|
|
short extra;
|
|
};
|
|
struct BPACK walltypev5
|
|
{
|
|
long x, y;
|
|
short point2;
|
|
short picnum, overpicnum;
|
|
signed char shade;
|
|
short cstat;
|
|
unsigned char xrepeat, yrepeat, xpanning, ypanning;
|
|
short nextsector1, nextwall1;
|
|
short nextsector2, nextwall2;
|
|
short lotag, hitag;
|
|
short extra;
|
|
};
|
|
struct BPACK spritetypev5
|
|
{
|
|
long x, y, z;
|
|
char cstat;
|
|
signed char shade;
|
|
unsigned char xrepeat, yrepeat;
|
|
short picnum, ang, xvel, yvel, zvel, owner;
|
|
short sectnum, statnum;
|
|
short lotag, hitag;
|
|
short extra;
|
|
};
|
|
struct BPACK sectortypev6
|
|
{
|
|
unsigned short wallptr, wallnum;
|
|
short ceilingpicnum, floorpicnum;
|
|
short ceilingheinum, floorheinum;
|
|
long ceilingz, floorz;
|
|
signed char ceilingshade, floorshade;
|
|
char ceilingxpanning, floorxpanning;
|
|
char ceilingypanning, floorypanning;
|
|
char ceilingstat, floorstat;
|
|
char ceilingpal, floorpal;
|
|
char visibility;
|
|
short lotag, hitag, extra;
|
|
};
|
|
struct BPACK walltypev6
|
|
{
|
|
long x, y;
|
|
short point2, nextsector, nextwall;
|
|
short picnum, overpicnum;
|
|
signed char shade;
|
|
char pal;
|
|
short cstat;
|
|
unsigned char xrepeat, yrepeat, xpanning, ypanning;
|
|
short lotag, hitag, extra;
|
|
};
|
|
struct BPACK spritetypev6
|
|
{
|
|
long x, y, z;
|
|
short cstat;
|
|
signed char shade;
|
|
char pal, clipdist;
|
|
unsigned char xrepeat, yrepeat;
|
|
signed char xoffset, yoffset;
|
|
short picnum, ang, xvel, yvel, zvel, owner;
|
|
short sectnum, statnum;
|
|
short lotag, hitag, extra;
|
|
};
|
|
#ifdef _MSC_VER
|
|
#pragma pack()
|
|
#endif
|
|
|
|
#ifdef __WATCOMC__
|
|
#pragma pack(pop)
|
|
#endif
|
|
|
|
#undef BPACK
|
|
|
|
static short sectorofwallv5(short theline)
|
|
{
|
|
short i, startwall, endwall, sucksect;
|
|
|
|
sucksect = -1;
|
|
for (i=0;i<numsectors;i++)
|
|
{
|
|
startwall = sector[i].wallptr;
|
|
endwall = startwall + sector[i].wallnum - 1;
|
|
if ((theline >= 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, long 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((short)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)
|
|
{
|
|
short 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(((long)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(((long)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 use v5
|
|
long loadoldboard(char *filename, char fromwhere, long *daposx, long *daposy, long *daposz,
|
|
short *daang, short *dacursectnum)
|
|
{
|
|
short 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],(long)((MAXSECTORS+3)>>5),0L);
|
|
clearbuf(&show2dsprite[0],(long)((MAXSPRITES+3)>>5),0L);
|
|
clearbuf(&show2dwall[0],(long)((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<numsectors; i++) {
|
|
switch (mapversion) {
|
|
case 5:
|
|
kread(fil,&v5sect,sizeof(struct sectortypev5));
|
|
v5sect.wallptr = B_LITTLE16(v5sect.wallptr);
|
|
v5sect.wallnum = B_LITTLE16(v5sect.wallnum);
|
|
v5sect.ceilingpicnum = B_LITTLE16(v5sect.ceilingpicnum);
|
|
v5sect.floorpicnum = B_LITTLE16(v5sect.floorpicnum);
|
|
v5sect.ceilingheinum = B_LITTLE16(v5sect.ceilingheinum);
|
|
v5sect.floorheinum = B_LITTLE16(v5sect.floorheinum);
|
|
v5sect.ceilingz = B_LITTLE32(v5sect.ceilingz);
|
|
v5sect.floorz = B_LITTLE32(v5sect.floorz);
|
|
v5sect.lotag = B_LITTLE16(v5sect.lotag);
|
|
v5sect.hitag = B_LITTLE16(v5sect.hitag);
|
|
v5sect.extra = B_LITTLE16(v5sect.extra);
|
|
break;
|
|
case 6:
|
|
kread(fil,&v6sect,sizeof(struct sectortypev6));
|
|
v6sect.wallptr = B_LITTLE16(v6sect.wallptr);
|
|
v6sect.wallnum = B_LITTLE16(v6sect.wallnum);
|
|
v6sect.ceilingpicnum = B_LITTLE16(v6sect.ceilingpicnum);
|
|
v6sect.floorpicnum = B_LITTLE16(v6sect.floorpicnum);
|
|
v6sect.ceilingheinum = B_LITTLE16(v6sect.ceilingheinum);
|
|
v6sect.floorheinum = B_LITTLE16(v6sect.floorheinum);
|
|
v6sect.ceilingz = B_LITTLE32(v6sect.ceilingz);
|
|
v6sect.floorz = B_LITTLE32(v6sect.floorz);
|
|
v6sect.lotag = B_LITTLE16(v6sect.lotag);
|
|
v6sect.hitag = B_LITTLE16(v6sect.hitag);
|
|
v6sect.extra = B_LITTLE16(v6sect.extra);
|
|
break;
|
|
}
|
|
switch (mapversion) {
|
|
case 5:
|
|
convertv5sectv6(&v5sect,&v6sect);
|
|
case 6:
|
|
convertv6sectv7(&v6sect,§or[i]);
|
|
}
|
|
}
|
|
|
|
kread(fil,&numwalls,2); numwalls = B_LITTLE16(numwalls);
|
|
if (numwalls > MAXWALLS) { kclose(fil); return(-1); }
|
|
for (i=0; i<numwalls; i++) {
|
|
switch (mapversion) {
|
|
case 5:
|
|
kread(fil,&v5wall,sizeof(struct walltypev5));
|
|
v5wall.x = B_LITTLE32(v5wall.x);
|
|
v5wall.y = B_LITTLE32(v5wall.y);
|
|
v5wall.point2 = B_LITTLE16(v5wall.point2);
|
|
v5wall.picnum = B_LITTLE16(v5wall.picnum);
|
|
v5wall.overpicnum = B_LITTLE16(v5wall.overpicnum);
|
|
v5wall.cstat = B_LITTLE16(v5wall.cstat);
|
|
v5wall.nextsector1 = B_LITTLE16(v5wall.nextsector1);
|
|
v5wall.nextwall1 = B_LITTLE16(v5wall.nextwall1);
|
|
v5wall.nextsector2 = B_LITTLE16(v5wall.nextsector2);
|
|
v5wall.nextwall2 = B_LITTLE16(v5wall.nextwall2);
|
|
v5wall.lotag = B_LITTLE16(v5wall.lotag);
|
|
v5wall.hitag = B_LITTLE16(v5wall.hitag);
|
|
v5wall.extra = B_LITTLE16(v5wall.extra);
|
|
break;
|
|
case 6:
|
|
kread(fil,&v6wall,sizeof(struct walltypev6));
|
|
v6wall.x = B_LITTLE32(v6wall.x);
|
|
v6wall.y = B_LITTLE32(v6wall.y);
|
|
v6wall.point2 = B_LITTLE16(v6wall.point2);
|
|
v6wall.nextsector = B_LITTLE16(v6wall.nextsector);
|
|
v6wall.nextwall = B_LITTLE16(v6wall.nextwall);
|
|
v6wall.picnum = B_LITTLE16(v6wall.picnum);
|
|
v6wall.overpicnum = B_LITTLE16(v6wall.overpicnum);
|
|
v6wall.cstat = B_LITTLE16(v6wall.cstat);
|
|
v6wall.lotag = B_LITTLE16(v6wall.lotag);
|
|
v6wall.hitag = B_LITTLE16(v6wall.hitag);
|
|
v6wall.extra = B_LITTLE16(v6wall.extra);
|
|
break;
|
|
}
|
|
switch (mapversion) {
|
|
case 5:
|
|
convertv5wallv6(&v5wall,&v6wall,i);
|
|
case 6:
|
|
convertv6wallv7(&v6wall,&wall[i]);
|
|
}
|
|
}
|
|
|
|
kread(fil,&numsprites,2); numsprites = B_LITTLE16(numsprites);
|
|
if (numsprites > MAXSPRITES) { kclose(fil); return(-1); }
|
|
for (i=0; i<numsprites; i++) {
|
|
switch (mapversion) {
|
|
case 5:
|
|
kread(fil,&v5spr,sizeof(struct spritetypev5));
|
|
v5spr.x = B_LITTLE32(v5spr.x);
|
|
v5spr.y = B_LITTLE32(v5spr.y);
|
|
v5spr.z = B_LITTLE32(v5spr.z);
|
|
v5spr.picnum = B_LITTLE16(v5spr.picnum);
|
|
v5spr.ang = B_LITTLE16(v5spr.ang);
|
|
v5spr.xvel = B_LITTLE16(v5spr.xvel);
|
|
v5spr.yvel = B_LITTLE16(v5spr.yvel);
|
|
v5spr.zvel = B_LITTLE16(v5spr.zvel);
|
|
v5spr.owner = B_LITTLE16(v5spr.owner);
|
|
v5spr.sectnum = B_LITTLE16(v5spr.sectnum);
|
|
v5spr.statnum = B_LITTLE16(v5spr.statnum);
|
|
v5spr.lotag = B_LITTLE16(v5spr.lotag);
|
|
v5spr.hitag = B_LITTLE16(v5spr.hitag);
|
|
v5spr.extra = B_LITTLE16(v5spr.extra);
|
|
break;
|
|
case 6:
|
|
kread(fil,&v6spr,sizeof(struct spritetypev6));
|
|
v6spr.x = B_LITTLE32(v6spr.x);
|
|
v6spr.y = B_LITTLE32(v6spr.y);
|
|
v6spr.z = B_LITTLE32(v6spr.z);
|
|
v6spr.cstat = B_LITTLE16(v6spr.cstat);
|
|
v6spr.picnum = B_LITTLE16(v6spr.picnum);
|
|
v6spr.ang = B_LITTLE16(v6spr.ang);
|
|
v6spr.xvel = B_LITTLE16(v6spr.xvel);
|
|
v6spr.yvel = B_LITTLE16(v6spr.yvel);
|
|
v6spr.zvel = B_LITTLE16(v6spr.zvel);
|
|
v6spr.owner = B_LITTLE16(v6spr.owner);
|
|
v6spr.sectnum = B_LITTLE16(v6spr.sectnum);
|
|
v6spr.statnum = B_LITTLE16(v6spr.statnum);
|
|
v6spr.lotag = B_LITTLE16(v6spr.lotag);
|
|
v6spr.hitag = B_LITTLE16(v6spr.hitag);
|
|
v6spr.extra = B_LITTLE16(v6spr.extra);
|
|
break;
|
|
}
|
|
switch (mapversion) {
|
|
case 5:
|
|
convertv5sprv6(&v5spr,&v6spr);
|
|
case 6:
|
|
convertv6sprv7(&v6spr,&sprite[i]);
|
|
}
|
|
}
|
|
|
|
for (i=0;i<numsprites;i++) {
|
|
if ((sprite[i].cstat & 48) == 48) sprite[i].cstat &= ~48;
|
|
insertsprite(sprite[i].sectnum,sprite[i].statnum);
|
|
}
|
|
|
|
//Must be after loading sectors, etc!
|
|
updatesector(*daposx,*daposy,dacursectnum);
|
|
|
|
kclose(fil);
|
|
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
memset(spriteext, 0, sizeof(spriteext));
|
|
memset(spritesmooth, 0, sizeof(spritesmooth));
|
|
#endif
|
|
guniqhudid = 0;
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
//
|
|
// loadmaphack
|
|
//
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
#include "scriptfile.h"
|
|
long loadmaphack(char *filename)
|
|
{
|
|
enum
|
|
{
|
|
T_EOF = -2,
|
|
T_ERROR = -1,
|
|
T_SPRITE = 0,
|
|
T_ANGOFF,
|
|
T_NOMODEL,
|
|
T_NOANIM,
|
|
T_PITCH,
|
|
T_ROLL
|
|
};
|
|
|
|
static struct { char *text; int tokenid; } legaltokens[] = {
|
|
{ "sprite", T_SPRITE },
|
|
{ "angleoff", T_ANGOFF },
|
|
{ "angoff", T_ANGOFF },
|
|
{ "notmd2", T_NOMODEL },
|
|
{ "notmd3", T_NOMODEL },
|
|
{ "notmd", T_NOMODEL },
|
|
{ "nomd2anim", T_NOANIM },
|
|
{ "nomd3anim", T_NOANIM },
|
|
{ "nomdanim", T_NOANIM },
|
|
{ "pitch", T_PITCH },
|
|
{ "roll", T_ROLL },
|
|
{ NULL, -1 }
|
|
};
|
|
|
|
scriptfile *script;
|
|
char *tok, *cmdtokptr;
|
|
int i;
|
|
int whichsprite = -1;
|
|
|
|
script = scriptfile_fromfile(filename);
|
|
if (!script) return -1;
|
|
|
|
memset(spriteext, 0, sizeof(spriteext));
|
|
memset(spritesmooth, 0, sizeof(spritesmooth));
|
|
|
|
while (1) {
|
|
tok = scriptfile_gettoken(script);
|
|
if (!tok) break;
|
|
for (i=0;legaltokens[i].text;i++) if (!Bstrcasecmp(tok,legaltokens[i].text)) break;
|
|
cmdtokptr = script->ltextptr;
|
|
switch (legaltokens[i].tokenid) {
|
|
case T_SPRITE: // sprite <xx>
|
|
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 <xx>
|
|
{
|
|
int 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 = (short)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 <xx>
|
|
{
|
|
int 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 = (short)pitch;
|
|
}
|
|
case T_ROLL: // roll <xx>
|
|
{
|
|
int 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 = (short)roll;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// unrecognised token
|
|
break;
|
|
}
|
|
}
|
|
|
|
scriptfile_close(script);
|
|
return 0;
|
|
}
|
|
#else
|
|
long loadmaphack(char *filename) { return -1; }
|
|
#endif
|
|
|
|
|
|
//
|
|
// saveboard
|
|
//
|
|
long saveboard(char *filename, long *daposx, long *daposy, long *daposz,
|
|
short *daang, short *dacursectnum)
|
|
{
|
|
short fil, i, j, numsprites, ts;
|
|
long tl;
|
|
sectortype tsect;
|
|
walltype twall;
|
|
spritetype tspri;
|
|
|
|
if ((fil = Bopen(filename,BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY,BS_IREAD|BS_IWRITE)) == -1)
|
|
return(-1);
|
|
|
|
numsprites = 0;
|
|
for (j=0;j<MAXSTATUS;j++)
|
|
{
|
|
i = headspritestat[j];
|
|
while (i != -1)
|
|
{
|
|
numsprites++;
|
|
i = nextspritestat[i];
|
|
}
|
|
}
|
|
|
|
if (numsectors > 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);
|
|
for (i=0; i<numsectors; i++) {
|
|
tsect = sector[i];
|
|
tsect.wallptr = B_LITTLE16(tsect.wallptr);
|
|
tsect.wallnum = B_LITTLE16(tsect.wallnum);
|
|
tsect.ceilingz = B_LITTLE32(tsect.ceilingz);
|
|
tsect.floorz = B_LITTLE32(tsect.floorz);
|
|
tsect.ceilingstat = B_LITTLE16(tsect.ceilingstat);
|
|
tsect.floorstat = B_LITTLE16(tsect.floorstat);
|
|
tsect.ceilingpicnum = B_LITTLE16(tsect.ceilingpicnum);
|
|
tsect.ceilingheinum = B_LITTLE16(tsect.ceilingheinum);
|
|
tsect.floorpicnum = B_LITTLE16(tsect.floorpicnum);
|
|
tsect.floorheinum = B_LITTLE16(tsect.floorheinum);
|
|
tsect.lotag = B_LITTLE16(tsect.lotag);
|
|
tsect.hitag = B_LITTLE16(tsect.hitag);
|
|
tsect.extra = B_LITTLE16(tsect.extra);
|
|
Bwrite(fil,&tsect,sizeof(sectortype));
|
|
}
|
|
|
|
ts = B_LITTLE16(numwalls); Bwrite(fil,&ts,2);
|
|
for (i=0; i<numwalls; i++) {
|
|
twall = wall[i];
|
|
twall.x = B_LITTLE32(twall.x);
|
|
twall.y = B_LITTLE32(twall.y);
|
|
twall.point2 = B_LITTLE16(twall.point2);
|
|
twall.nextwall = B_LITTLE16(twall.nextwall);
|
|
twall.nextsector = B_LITTLE16(twall.nextsector);
|
|
twall.cstat = B_LITTLE16(twall.cstat);
|
|
twall.picnum = B_LITTLE16(twall.picnum);
|
|
twall.overpicnum = B_LITTLE16(twall.overpicnum);
|
|
twall.lotag = B_LITTLE16(twall.lotag);
|
|
twall.hitag = B_LITTLE16(twall.hitag);
|
|
twall.extra = B_LITTLE16(twall.extra);
|
|
Bwrite(fil,&twall,sizeof(walltype));
|
|
}
|
|
|
|
ts = B_LITTLE16(numsprites); Bwrite(fil,&ts,2);
|
|
|
|
for (j=0;j<MAXSTATUS;j++)
|
|
{
|
|
i = headspritestat[j];
|
|
while (i != -1)
|
|
{
|
|
tspri = sprite[i];
|
|
tspri.x = B_LITTLE32(tspri.x);
|
|
tspri.y = B_LITTLE32(tspri.y);
|
|
tspri.z = B_LITTLE32(tspri.z);
|
|
tspri.cstat = B_LITTLE16(tspri.cstat);
|
|
tspri.picnum = B_LITTLE16(tspri.picnum);
|
|
tspri.sectnum = B_LITTLE16(tspri.sectnum);
|
|
tspri.statnum = B_LITTLE16(tspri.statnum);
|
|
tspri.ang = B_LITTLE16(tspri.ang);
|
|
tspri.owner = B_LITTLE16(tspri.owner);
|
|
tspri.xvel = B_LITTLE16(tspri.xvel);
|
|
tspri.yvel = B_LITTLE16(tspri.yvel);
|
|
tspri.zvel = B_LITTLE16(tspri.zvel);
|
|
tspri.lotag = B_LITTLE16(tspri.lotag);
|
|
tspri.hitag = B_LITTLE16(tspri.hitag);
|
|
tspri.extra = B_LITTLE16(tspri.extra);
|
|
Bwrite(fil,&tspri,sizeof(spritetype));
|
|
i = nextspritestat[i];
|
|
}
|
|
}
|
|
|
|
Bclose(fil);
|
|
return(0);
|
|
}
|
|
|
|
|
|
//
|
|
// setgamemode
|
|
//
|
|
// JBF: davidoption now functions as a windowed-mode flag (0 == windowed, 1 == fullscreen)
|
|
extern char videomodereset;
|
|
long setgamemode(char davidoption, long daxdim, long daydim, long dabpp)
|
|
{
|
|
long i, j;
|
|
|
|
if ((qsetmode == 200) && (videomodereset == 0) &&
|
|
(davidoption == fullscreen) && (xdim == daxdim) && (ydim == daydim) && (bpp == dabpp))
|
|
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)
|
|
// { printOSD("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);
|
|
|
|
#ifdef POLYMOST
|
|
if (dabpp > 8) rendmode = 3; // 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(long); //Leave room for horizlookup&horizlookup2
|
|
|
|
if (lookups != NULL)
|
|
{
|
|
if (lookupsalloctype == 0) kkfree((void *)lookups);
|
|
if (lookupsalloctype == 1) suckcache((long *)lookups);
|
|
lookups = NULL;
|
|
}
|
|
lookupsalloctype = 0;
|
|
if ((lookups = (long *)kkmalloc(j<<1)) == NULL)
|
|
{
|
|
allocache((long *)&lookups,j<<1,&permanentlock);
|
|
lookupsalloctype = 1;
|
|
}
|
|
|
|
horizlookup = (long *)(lookups);
|
|
horizlookup2 = (long *)(FP_OFF(lookups)+j);
|
|
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,&palette[0],0);
|
|
|
|
if (searchx < 0) { searchx = halfxdimen; searchy = (ydimen>>1); }
|
|
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
if (rendmode == 3)
|
|
{
|
|
polymost_glreset();
|
|
polymost_glinit();
|
|
}
|
|
if (rendmode == 4)
|
|
polymer_glinit();
|
|
#endif
|
|
qsetmode = 200;
|
|
return(0);
|
|
}
|
|
|
|
|
|
//
|
|
// nextpage
|
|
//
|
|
void nextpage(void)
|
|
{
|
|
long i;
|
|
permfifotype *per;
|
|
|
|
//char snotbuf[32];
|
|
//j = 0; k = 0;
|
|
//for(i=0;i<4096;i++)
|
|
// if (waloff[i] != 0)
|
|
// {
|
|
// sprintf(snotbuf,"%ld-%ld",i,tilesizx[i]*tilesizy[i]);
|
|
// printext256((j>>5)*40+32,(j&31)*6,walock[i]>>3,-1,snotbuf,1);
|
|
// k += tilesizx[i]*tilesizy[i];
|
|
// j++;
|
|
// }
|
|
//sprintf(snotbuf,"Total: %ld",k);
|
|
//printext256((j>>5)*40+32,(j&31)*6,31,-1,snotbuf,1);
|
|
|
|
switch (qsetmode)
|
|
{
|
|
case 200:
|
|
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+8) || (totalclock < lastageclock))
|
|
{ lastageclock = totalclock; agecache(); }
|
|
|
|
#ifdef USE_OPENGL
|
|
omdtims = mdtims; mdtims = getticks();
|
|
if (((unsigned long)(mdtims-omdtims)) > 10000) omdtims = mdtims;
|
|
#endif
|
|
|
|
beforedrawrooms = 1;
|
|
numframes++;
|
|
}
|
|
|
|
|
|
//
|
|
// loadpics
|
|
//
|
|
long loadpics(char *filename, long askedsize)
|
|
{
|
|
long offscount, localtilestart, localtileend, dasiz;
|
|
short fil, i, j, k;
|
|
|
|
Bstrcpy(artfilename,filename);
|
|
|
|
for (i=0;i<MAXTILES;i++)
|
|
{
|
|
tilesizx[i] = 0;
|
|
tilesizy[i] = 0;
|
|
picanm[i] = 0L;
|
|
}
|
|
|
|
artsize = 0L;
|
|
|
|
numtilefiles = 0;
|
|
do
|
|
{
|
|
k = numtilefiles;
|
|
|
|
artfilename[7] = (k%10)+48;
|
|
artfilename[6] = ((k/10)%10)+48;
|
|
artfilename[5] = ((k/100)%10)+48;
|
|
if ((fil = kopen4load(artfilename,0)) != -1)
|
|
{
|
|
kread(fil,&artversion,4); artversion = B_LITTLE32(artversion);
|
|
if (artversion != 1) {
|
|
Bprintf("loadpics(): Invalid art file version in %s\n", artfilename);
|
|
return(-1);
|
|
}
|
|
kread(fil,&numtiles,4); numtiles = B_LITTLE32(numtiles);
|
|
kread(fil,&localtilestart,4); localtilestart = B_LITTLE32(localtilestart);
|
|
kread(fil,&localtileend,4); localtileend = B_LITTLE32(localtileend);
|
|
kread(fil,&tilesizx[localtilestart],(localtileend-localtilestart+1)<<1);
|
|
kread(fil,&tilesizy[localtilestart],(localtileend-localtilestart+1)<<1);
|
|
kread(fil,&picanm[localtilestart],(localtileend-localtilestart+1)<<2);
|
|
for (i=localtilestart; i<=localtileend; i++) {
|
|
tilesizx[i] = B_LITTLE16(tilesizx[i]);
|
|
tilesizy[i] = B_LITTLE16(tilesizy[i]);
|
|
picanm[i] = B_LITTLE32(picanm[i]);
|
|
}
|
|
|
|
offscount = 4+4+4+4+((localtileend-localtilestart+1)<<3);
|
|
for (i=localtilestart;i<=localtileend;i++)
|
|
{
|
|
tilefilenum[i] = k;
|
|
tilefileoffs[i] = offscount;
|
|
dasiz = (long)(tilesizx[i]*tilesizy[i]);
|
|
offscount += dasiz;
|
|
artsize += ((dasiz+15)&0xfffffff0);
|
|
}
|
|
kclose(fil);
|
|
|
|
numtilefiles++;
|
|
}
|
|
}
|
|
while (k != numtilefiles);
|
|
|
|
clearbuf(&gotpic[0],(long)((MAXTILES+31)>>5),0L);
|
|
|
|
//try dpmi_DETERMINEMAXREALALLOC!
|
|
|
|
//cachesize = min((long)((Bgetsysmemsize()/100)*60),max(artsize,askedsize));
|
|
if (Bgetsysmemsize() <= (unsigned long)askedsize)
|
|
cachesize = (Bgetsysmemsize()/100)*60;
|
|
else
|
|
cachesize = askedsize;
|
|
while ((pic = kkmalloc(cachesize)) == NULL)
|
|
{
|
|
cachesize -= 65536L;
|
|
if (cachesize < 65536) return(-1);
|
|
}
|
|
initcache((FP_OFF(pic)+15)&0xfffffff0,(cachesize-((-FP_OFF(pic))&15))&0xfffffff0);
|
|
|
|
for (i=0;i<MAXTILES;i++)
|
|
{
|
|
j = 15;
|
|
while ((j > 1) && (pow2long[j] > tilesizx[i])) j--;
|
|
picsiz[i] = ((char)j);
|
|
j = 15;
|
|
while ((j > 1) && (pow2long[j] > tilesizy[i])) j--;
|
|
picsiz[i] += ((char)(j<<4));
|
|
}
|
|
|
|
artfil = -1;
|
|
artfilnum = -1;
|
|
artfilplc = 0L;
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
//
|
|
// loadtile
|
|
//
|
|
char cachedebug = 0;
|
|
char faketile[MAXTILES];
|
|
|
|
void loadtile(short tilenume)
|
|
{
|
|
char *ptr;
|
|
long i, dasiz;
|
|
|
|
if ((unsigned)tilenume >= (unsigned)MAXTILES) return;
|
|
dasiz = tilesizx[tilenume]*tilesizy[tilenume];
|
|
if (dasiz <= 0) return;
|
|
|
|
i = tilefilenum[tilenume];
|
|
if (i != artfilnum)
|
|
{
|
|
if (artfil != -1) kclose(artfil);
|
|
artfilnum = i;
|
|
artfilplc = 0L;
|
|
|
|
artfilename[7] = (i%10)+48;
|
|
artfilename[6] = ((i/10)%10)+48;
|
|
artfilename[5] = ((i/100)%10)+48;
|
|
artfil = kopen4load(artfilename,0);
|
|
faketimerhandler();
|
|
}
|
|
|
|
if (cachedebug) printOSD("Tile:%d\n",tilenume);
|
|
|
|
if (waloff[tilenume] == 0)
|
|
{
|
|
walock[tilenume] = 199;
|
|
allocache(&waloff[tilenume],dasiz,&walock[tilenume]);
|
|
}
|
|
|
|
if (!faketile[tilenume])
|
|
{
|
|
if (artfilplc != tilefileoffs[tilenume])
|
|
{
|
|
klseek(artfil,tilefileoffs[tilenume]-artfilplc,BSEEK_CUR);
|
|
faketimerhandler();
|
|
}
|
|
ptr = (char *)waloff[tilenume];
|
|
kread(artfil,ptr,dasiz);
|
|
faketimerhandler();
|
|
artfilplc = tilefileoffs[tilenume]+dasiz;
|
|
} else { Bmemset((char *)waloff[tilenume],0,dasiz); faketimerhandler(); }
|
|
}
|
|
|
|
void checktile(short tilenume)
|
|
{
|
|
if (!waloff[tilenume])
|
|
loadtile(tilenume);
|
|
}
|
|
|
|
//
|
|
// allocatepermanenttile
|
|
//
|
|
long allocatepermanenttile(short tilenume, long xsiz, long ysiz)
|
|
{
|
|
long 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] = ((char)j);
|
|
j = 15; while ((j > 1) && (pow2long[j] > ysiz)) j--;
|
|
picsiz[tilenume] += ((char)(j<<4));
|
|
|
|
return(waloff[tilenume]);
|
|
}
|
|
|
|
|
|
//
|
|
// copytilepiece
|
|
//
|
|
void copytilepiece(long tilenume1, long sx1, long sy1, long xsiz, long ysiz,
|
|
long tilenume2, long sx2, long sy2)
|
|
{
|
|
char *ptr1, *ptr2, dat;
|
|
long xsiz1, ysiz1, xsiz2, ysiz2, i, j, x1, y1, x2, y2;
|
|
|
|
xsiz1 = tilesizx[tilenume1]; ysiz1 = tilesizy[tilenume1];
|
|
xsiz2 = tilesizx[tilenume2]; ysiz2 = tilesizy[tilenume2];
|
|
if ((xsiz1 > 0) && (ysiz1 > 0) && (xsiz2 > 0) && (ysiz2 > 0))
|
|
{
|
|
if (waloff[tilenume1] == 0) loadtile(tilenume1);
|
|
if (waloff[tilenume2] == 0) loadtile(tilenume2);
|
|
|
|
x1 = sx1;
|
|
for (i=0;i<xsiz;i++)
|
|
{
|
|
y1 = sy1;
|
|
for (j=0;j<ysiz;j++)
|
|
{
|
|
x2 = sx2+i;
|
|
y2 = sy2+j;
|
|
if ((x2 >= 0) && (y2 >= 0) && (x2 < xsiz2) && (y2 < ysiz2))
|
|
{
|
|
ptr1 = (char *)(waloff[tilenume1] + x1*ysiz1 + y1);
|
|
ptr2 = (char *)(waloff[tilenume2] + x2*ysiz2 + y2);
|
|
dat = *ptr1;
|
|
if (dat != 255)
|
|
*ptr2 = *ptr1;
|
|
}
|
|
|
|
y1++; if (y1 >= ysiz1) y1 = 0;
|
|
}
|
|
x1++; if (x1 >= xsiz1) x1 = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// qloadkvx
|
|
//
|
|
#ifdef SUPERBUILD
|
|
long qloadkvx(long voxindex, char *filename)
|
|
{
|
|
long i, fil, dasiz, lengcnt, lengtot;
|
|
char *ptr;
|
|
|
|
if ((fil = kopen4load(filename,0)) == -1) return -1;
|
|
|
|
lengcnt = 0;
|
|
lengtot = kfilelength(fil);
|
|
|
|
for (i=0;i<MAXVOXMIPS;i++)
|
|
{
|
|
kread(fil,&dasiz,4); dasiz = B_LITTLE32(dasiz);
|
|
//Must store filenames to use cacheing system :(
|
|
voxlock[voxindex][i] = 200;
|
|
allocache(&voxoff[voxindex][i],dasiz,&voxlock[voxindex][i]);
|
|
ptr = (char *)voxoff[voxindex][i];
|
|
kread(fil,ptr,dasiz);
|
|
|
|
lengcnt += dasiz+4;
|
|
if (lengcnt >= lengtot-768) break;
|
|
}
|
|
kclose(fil);
|
|
|
|
#if defined POLYMOST && defined USE_OPENGL
|
|
if (voxmodels[voxindex]) {
|
|
voxfree(voxmodels[voxindex]);
|
|
voxmodels[voxindex] = NULL;
|
|
}
|
|
voxmodels[voxindex] = voxload(filename);
|
|
#endif
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
// clipinsidebox
|
|
//
|
|
long clipinsidebox(long x, long y, short wallnum, long walldist)
|
|
{
|
|
walltype *wal;
|
|
long x1, y1, x2, y2, r;
|
|
|
|
r = (walldist<<1);
|
|
wal = &wall[wallnum]; x1 = wal->x+walldist-x; y1 = wal->y+walldist-y;
|
|
wal = &wall[wal->point2]; x2 = wal->x+walldist-x; y2 = wal->y+walldist-y;
|
|
|
|
if ((x1 < 0) && (x2 < 0)) return(0);
|
|
if ((y1 < 0) && (y2 < 0)) return(0);
|
|
if ((x1 >= r) && (x2 >= r)) return(0);
|
|
if ((y1 >= r) && (y2 >= r)) return(0);
|
|
|
|
x2 -= x1; y2 -= y1;
|
|
if (x2*(walldist-y1) >= y2*(walldist-x1)) //Front
|
|
{
|
|
if (x2 > 0) x2 *= (0-y1); else x2 *= (r-y1);
|
|
if (y2 > 0) y2 *= (r-x1); else y2 *= (0-x1);
|
|
return(x2 < y2);
|
|
}
|
|
if (x2 > 0) x2 *= (r-y1); else x2 *= (0-y1);
|
|
if (y2 > 0) y2 *= (0-x1); else y2 *= (r-x1);
|
|
return((x2 >= y2)<<1);
|
|
}
|
|
|
|
|
|
//
|
|
// clipinsideboxline
|
|
//
|
|
long clipinsideboxline(long x, long y, long x1, long y1, long x2, long y2, long walldist)
|
|
{
|
|
long r;
|
|
|
|
r = (walldist<<1);
|
|
|
|
x1 += walldist-x; x2 += walldist-x;
|
|
if ((x1 < 0) && (x2 < 0)) return(0);
|
|
if ((x1 >= r) && (x2 >= r)) return(0);
|
|
|
|
y1 += walldist-y; y2 += walldist-y;
|
|
if ((y1 < 0) && (y2 < 0)) return(0);
|
|
if ((y1 >= r) && (y2 >= r)) return(0);
|
|
|
|
x2 -= x1; y2 -= y1;
|
|
if (x2*(walldist-y1) >= y2*(walldist-x1)) //Front
|
|
{
|
|
if (x2 > 0) x2 *= (0-y1); else x2 *= (r-y1);
|
|
if (y2 > 0) y2 *= (r-x1); else y2 *= (0-x1);
|
|
return(x2 < y2);
|
|
}
|
|
if (x2 > 0) x2 *= (r-y1); else x2 *= (0-y1);
|
|
if (y2 > 0) y2 *= (0-x1); else y2 *= (r-x1);
|
|
return((x2 >= y2)<<1);
|
|
}
|
|
|
|
|
|
//
|
|
// inside
|
|
//
|
|
long inside(long x, long y, short sectnum)
|
|
{
|
|
walltype *wal;
|
|
long i, x1, y1, x2, y2;
|
|
unsigned long cnt;
|
|
|
|
if ((sectnum < 0) || (sectnum >= numsectors)) return(-1);
|
|
|
|
cnt = 0;
|
|
wal = &wall[sector[sectnum].wallptr];
|
|
i = sector[sectnum].wallnum;
|
|
do
|
|
{
|
|
y1 = wal->y-y; y2 = wall[wal->point2].y-y;
|
|
if ((y1^y2) < 0)
|
|
{
|
|
x1 = wal->x-x; x2 = wall[wal->point2].x-x;
|
|
if ((x1^x2) >= 0) cnt ^= x1; else cnt ^= (x1*y2-x2*y1)^y2;
|
|
}
|
|
wal++; i--;
|
|
} while (i);
|
|
return(cnt>>31);
|
|
}
|
|
|
|
|
|
//
|
|
// getangle
|
|
//
|
|
long getangle(long xvect, long yvect)
|
|
{
|
|
if ((xvect|yvect) == 0) return(0);
|
|
if (xvect == 0) return(512+((yvect<0)<<10));
|
|
if (yvect == 0) return(((xvect<0)<<10));
|
|
if (xvect == yvect) return(256+((xvect<0)<<10));
|
|
if (xvect == -yvect) return(768+((xvect>0)<<10));
|
|
if (klabs(xvect) > klabs(yvect))
|
|
return(((radarang[640+scale(160,yvect,xvect)]>>6)+((xvect<0)<<10))&2047);
|
|
return(((radarang[640-scale(160,xvect,yvect)]>>6)+512+((yvect<0)<<10))&2047);
|
|
}
|
|
|
|
|
|
//
|
|
// ksqrt
|
|
//
|
|
long ksqrt(long num)
|
|
{
|
|
return(nsqrtasm(num));
|
|
}
|
|
|
|
|
|
//
|
|
// krecip
|
|
//
|
|
long krecip(long num)
|
|
{
|
|
return(krecipasm(num));
|
|
}
|
|
|
|
//
|
|
// setsprite
|
|
//
|
|
long setsprite(short spritenum, long newx, long newy, long newz)
|
|
{
|
|
short tempsectnum;
|
|
|
|
sprite[spritenum].x = newx;
|
|
sprite[spritenum].y = newy;
|
|
sprite[spritenum].z = newz;
|
|
|
|
tempsectnum = sprite[spritenum].sectnum;
|
|
#ifdef SETSPRITEZ
|
|
updatesectorz(newx,newy,newz,&tempsectnum);
|
|
#else
|
|
updatesector(newx,newy,&tempsectnum);
|
|
#endif
|
|
if (tempsectnum < 0)
|
|
return(-1);
|
|
if (tempsectnum != sprite[spritenum].sectnum)
|
|
changespritesect(spritenum,tempsectnum);
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
//
|
|
// insertsprite
|
|
//
|
|
long insertsprite(short sectnum, short statnum)
|
|
{
|
|
insertspritestat(statnum);
|
|
return(insertspritesect(sectnum));
|
|
}
|
|
|
|
|
|
//
|
|
// deletesprite
|
|
//
|
|
long deletesprite(short spritenum)
|
|
{
|
|
deletespritestat(spritenum);
|
|
return(deletespritesect(spritenum));
|
|
}
|
|
|
|
|
|
//
|
|
// changespritesect
|
|
//
|
|
long changespritesect(short spritenum, short 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
|
|
//
|
|
long changespritestat(short spritenum, short 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
|
|
//
|
|
long nextsectorneighborz(short sectnum, long thez, short topbottom, short direction)
|
|
{
|
|
walltype *wal;
|
|
long i, testz, nextz;
|
|
short 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
|
|
//
|
|
long cansee(long x1, long y1, long z1, short sect1, long x2, long y2, long z2, short sect2)
|
|
{
|
|
sectortype *sec;
|
|
walltype *wal, *wal2;
|
|
long i, cnt, nexts, x, y, z, cz, fz, dasectnum, dacnt, danum;
|
|
long 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;dacnt<danum;dacnt++)
|
|
{
|
|
dasectnum = clipsectorlist[dacnt]; sec = §or[dasectnum];
|
|
for (cnt=sec->wallnum,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((short)dasectnum,x,y,&cz,&fz);
|
|
if ((z <= cz) || (z >= fz)) return(0);
|
|
getzsofslope((short)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);
|
|
}
|
|
|
|
|
|
//
|
|
// hitscan
|
|
//
|
|
long hitscan(long xs, long ys, long zs, short sectnum, long vx, long vy, long vz,
|
|
short *hitsect, short *hitwall, short *hitsprite,
|
|
long *hitx, long *hity, long *hitz, unsigned long cliptype)
|
|
{
|
|
sectortype *sec;
|
|
walltype *wal, *wal2;
|
|
spritetype *spr;
|
|
long z, zz, x1, y1=0, z1=0, x2, y2, x3, y3, x4, y4, intx, inty, intz;
|
|
long topt, topu, bot, dist, offx, offy, cstat;
|
|
long i, j, k, l, tilenum, xoff, yoff, dax, day, daz, daz2;
|
|
long ang, cosang, sinang, xspan, yspan, xrepeat, yrepeat;
|
|
long dawalclipmask, dasprclipmask;
|
|
short tempshortcnt, tempshortnum, dasector, startwall, endwall;
|
|
short nextsector;
|
|
char clipyou;
|
|
|
|
*hitsect = -1; *hitwall = -1; *hitsprite = -1;
|
|
if (sectnum < 0) return(-1);
|
|
|
|
*hitx = hitscangoalx; *hity = hitscangoaly;
|
|
|
|
dawalclipmask = (cliptype&65535);
|
|
dasprclipmask = (cliptype>>16);
|
|
|
|
clipsectorlist[0] = sectnum;
|
|
tempshortcnt = 0; tempshortnum = 1;
|
|
do
|
|
{
|
|
dasector = clipsectorlist[tempshortcnt]; sec = §or[dasector];
|
|
|
|
x1 = 0x7fffffff;
|
|
if (sec->ceilingstat&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) continue;
|
|
i = divscale15(sec->ceilingheinum,i);
|
|
dax *= i; day *= i;
|
|
|
|
j = (vz<<8)-dmulscale15(dax,vy,-day,vx);
|
|
if (j != 0)
|
|
{
|
|
i = ((sec->ceilingz-zs)<<8)+dmulscale15(dax,ys-wal->y,-day,xs-wal->x);
|
|
if (((i^j) >= 0) && ((klabs(i)>>1) < klabs(j)))
|
|
{
|
|
i = divscale30(i,j);
|
|
x1 = xs + mulscale30(vx,i);
|
|
y1 = ys + mulscale30(vy,i);
|
|
z1 = zs + mulscale30(vz,i);
|
|
}
|
|
}
|
|
}
|
|
else if ((vz < 0) && (zs >= sec->ceilingz))
|
|
{
|
|
z1 = sec->ceilingz; i = z1-zs;
|
|
if ((klabs(i)>>1) < -vz)
|
|
{
|
|
i = divscale30(i,vz);
|
|
x1 = xs + mulscale30(vx,i);
|
|
y1 = ys + mulscale30(vy,i);
|
|
}
|
|
}
|
|
if ((x1 != 0x7fffffff) && (klabs(x1-xs)+klabs(y1-ys) < klabs((*hitx)-xs)+klabs((*hity)-ys)))
|
|
if (inside(x1,y1,dasector) != 0)
|
|
{
|
|
*hitsect = dasector; *hitwall = -1; *hitsprite = -1;
|
|
*hitx = x1; *hity = y1; *hitz = z1;
|
|
}
|
|
|
|
x1 = 0x7fffffff;
|
|
if (sec->floorstat&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) continue;
|
|
i = divscale15(sec->floorheinum,i);
|
|
dax *= i; day *= i;
|
|
|
|
j = (vz<<8)-dmulscale15(dax,vy,-day,vx);
|
|
if (j != 0)
|
|
{
|
|
i = ((sec->floorz-zs)<<8)+dmulscale15(dax,ys-wal->y,-day,xs-wal->x);
|
|
if (((i^j) >= 0) && ((klabs(i)>>1) < klabs(j)))
|
|
{
|
|
i = divscale30(i,j);
|
|
x1 = xs + mulscale30(vx,i);
|
|
y1 = ys + mulscale30(vy,i);
|
|
z1 = zs + mulscale30(vz,i);
|
|
}
|
|
}
|
|
}
|
|
else if ((vz > 0) && (zs <= sec->floorz))
|
|
{
|
|
z1 = sec->floorz; i = z1-zs;
|
|
if ((klabs(i)>>1) < vz)
|
|
{
|
|
i = divscale30(i,vz);
|
|
x1 = xs + mulscale30(vx,i);
|
|
y1 = ys + mulscale30(vy,i);
|
|
}
|
|
}
|
|
if ((x1 != 0x7fffffff) && (klabs(x1-xs)+klabs(y1-ys) < klabs((*hitx)-xs)+klabs((*hity)-ys)))
|
|
if (inside(x1,y1,dasector) != 0)
|
|
{
|
|
*hitsect = dasector; *hitwall = -1; *hitsprite = -1;
|
|
*hitx = x1; *hity = y1; *hitz = z1;
|
|
}
|
|
|
|
startwall = sec->wallptr; endwall = startwall + sec->wallnum;
|
|
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;
|
|
|
|
if ((x1-xs)*(y2-ys) < (x2-xs)*(y1-ys)) continue;
|
|
if (rintersect(xs,ys,zs,vx,vy,vz,x1,y1,x2,y2,&intx,&inty,&intz) == 0) continue;
|
|
|
|
if (klabs(intx-xs)+klabs(inty-ys) >= klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
|
|
|
|
nextsector = wal->nextsector;
|
|
if ((nextsector < 0) || (wal->cstat&dawalclipmask))
|
|
{
|
|
*hitsect = dasector; *hitwall = z; *hitsprite = -1;
|
|
*hitx = intx; *hity = inty; *hitz = intz;
|
|
continue;
|
|
}
|
|
getzsofslope(nextsector,intx,inty,&daz,&daz2);
|
|
if ((intz <= daz) || (intz >= daz2))
|
|
{
|
|
*hitsect = dasector; *hitwall = z; *hitsprite = -1;
|
|
*hitx = intx; *hity = inty; *hitz = intz;
|
|
continue;
|
|
}
|
|
|
|
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];
|
|
cstat = spr->cstat;
|
|
#ifdef POLYMOST
|
|
if (!hitallsprites)
|
|
#endif
|
|
if ((cstat&dasprclipmask) == 0) continue;
|
|
|
|
x1 = spr->x; y1 = spr->y; z1 = spr->z;
|
|
switch (cstat&48)
|
|
{
|
|
case 0:
|
|
topt = vx*(x1-xs) + vy*(y1-ys); if (topt <= 0) continue;
|
|
bot = vx*vx + vy*vy; if (bot == 0) continue;
|
|
|
|
intz = zs+scale(vz,topt,bot);
|
|
|
|
i = (tilesizy[spr->picnum]*spr->yrepeat<<2);
|
|
if (cstat&128) z1 += (i>>1);
|
|
if (picanm[spr->picnum]&0x00ff0000) z1 -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
|
|
if ((intz > z1) || (intz < z1-i)) continue;
|
|
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)) continue;
|
|
intx = xs + scale(vx,topt,bot);
|
|
inty = ys + scale(vy,topt,bot);
|
|
|
|
if (klabs(intx-xs)+klabs(inty-ys) > klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
|
|
|
|
*hitsect = dasector; *hitwall = -1; *hitsprite = z;
|
|
*hitx = intx; *hity = inty; *hitz = 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 = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)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-xs)*(y2-ys) < (x2-xs)*(y1-ys)) continue;
|
|
|
|
if (rintersect(xs,ys,zs,vx,vy,vz,x1,y1,x2,y2,&intx,&inty,&intz) == 0) continue;
|
|
|
|
if (klabs(intx-xs)+klabs(inty-ys) > klabs((*hitx)-xs)+klabs((*hity)-ys)) 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 -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
|
|
if ((intz < daz) && (intz > daz-k))
|
|
{
|
|
*hitsect = dasector; *hitwall = -1; *hitsprite = z;
|
|
*hitx = intx; *hity = inty; *hitz = intz;
|
|
}
|
|
break;
|
|
case 32:
|
|
if (vz == 0) continue;
|
|
intz = z1;
|
|
if (((intz-zs)^vz) < 0) continue;
|
|
if ((cstat&64) != 0)
|
|
if ((zs > intz) == ((cstat&8)==0)) continue;
|
|
|
|
#if 1 // Abyss crash prevention code ((intz-zs)*zx overflowing a 8-bit word)
|
|
zz=(long)((intz-zs)*vx);
|
|
intx = xs+scale(zz,1,vz);
|
|
zz=(long)((intz-zs)*vy);
|
|
inty = ys+scale(zz,1,vz);
|
|
#else
|
|
intx = xs+scale(intz-zs,vx,vz);
|
|
inty = ys+scale(intz-zs,vy,vz);
|
|
#endif
|
|
|
|
if (klabs(intx-xs)+klabs(inty-ys) > klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
|
|
|
|
tilenum = spr->picnum;
|
|
xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
|
|
yoff = (long)((signed char)((picanm[tilenum]>>16)&255))+((long)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<x2*y1)^(y1<y2);
|
|
else if (x1 >= 0) clipyou ^= 1;
|
|
}
|
|
if ((y2^y3) < 0)
|
|
{
|
|
if ((x2^x3) < 0) clipyou ^= (x2*y3<x3*y2)^(y2<y3);
|
|
else if (x2 >= 0) clipyou ^= 1;
|
|
}
|
|
if ((y3^y4) < 0)
|
|
{
|
|
if ((x3^x4) < 0) clipyou ^= (x3*y4<x4*y3)^(y3<y4);
|
|
else if (x3 >= 0) clipyou ^= 1;
|
|
}
|
|
if ((y4^y1) < 0)
|
|
{
|
|
if ((x4^x1) < 0) clipyou ^= (x4*y1<x1*y4)^(y4<y1);
|
|
else if (x4 >= 0) clipyou ^= 1;
|
|
}
|
|
|
|
if (clipyou != 0)
|
|
{
|
|
*hitsect = dasector; *hitwall = -1; *hitsprite = z;
|
|
*hitx = intx; *hity = inty; *hitz = intz;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
tempshortcnt++;
|
|
} while (tempshortcnt < tempshortnum);
|
|
return(0);
|
|
}
|
|
|
|
|
|
//
|
|
// neartag
|
|
//
|
|
long neartag(long xs, long ys, long zs, short sectnum, short ange, short *neartagsector, short *neartagwall, short *neartagsprite, long *neartaghitdist, long neartagrange, char tagsearch)
|
|
{
|
|
walltype *wal, *wal2;
|
|
spritetype *spr;
|
|
long i, z, zz, xe, ye, ze, x1, y1, z1, x2, y2, intx, inty, intz;
|
|
long topt, topu, bot, dist, offx, offy, vx, vy, vz;
|
|
short tempshortcnt, tempshortnum, dasector, startwall, endwall;
|
|
short 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 -= ((long)((signed char)((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(short pointhighlight, long dax, long day)
|
|
{
|
|
short cnt, tempshort;
|
|
|
|
wall[pointhighlight].x = dax;
|
|
wall[pointhighlight].y = day;
|
|
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
cnt--;
|
|
}
|
|
while ((tempshort != pointhighlight) && (cnt > 0));
|
|
break;
|
|
}
|
|
cnt--;
|
|
}
|
|
while ((tempshort != pointhighlight) && (cnt > 0));
|
|
}
|
|
|
|
|
|
//
|
|
// lastwall
|
|
//
|
|
long lastwall(short point)
|
|
{
|
|
long 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);
|
|
}
|
|
|
|
|
|
|
|
#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++; \
|
|
} \
|
|
} \
|
|
|
|
long clipmoveboxtracenum = 3;
|
|
|
|
//
|
|
// clipmove
|
|
//
|
|
long clipmove (long *x, long *y, long *z, short *sectnum,
|
|
long xvect, long yvect,
|
|
long walldist, long ceildist, long flordist, unsigned long cliptype)
|
|
{
|
|
walltype *wal, *wal2;
|
|
spritetype *spr;
|
|
sectortype *sec, *sec2;
|
|
long i, j, templong1, templong2;
|
|
long oxvect, oyvect, goalx, goaly, intx, inty, lx, ly, retval;
|
|
long k, l, clipsectcnt, startwall, endwall, cstat, dasect;
|
|
long x1, y1, x2, y2, cx, cy, rad, xmin, ymin, xmax, ymax, daz, daz2;
|
|
long bsz, dax, day, xoff, yoff, xspan, yspan, cosang, sinang, tilenum;
|
|
long xrepeat, yrepeat, gx, gy, dx, dy, dasprclipmask, dawalclipmask;
|
|
long hitwall, cnt, clipyou;
|
|
|
|
if (((xvect|yvect) == 0) || (*sectnum < 0)) return(0);
|
|
retval = 0;
|
|
|
|
oxvect = xvect;
|
|
oyvect = yvect;
|
|
|
|
goalx = (*x) + (xvect>>14);
|
|
goaly = (*y) + (yvect>>14);
|
|
|
|
|
|
clipnum = 0;
|
|
|
|
cx = (((*x)+goalx)>>1);
|
|
cy = (((*y)+goaly)>>1);
|
|
//Extra walldist for sprites on sector lines
|
|
gx = goalx-(*x); gy = goaly-(*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;
|
|
do
|
|
{
|
|
dasect = clipsectorlist[clipsectcnt++];
|
|
sec = §or[dasect];
|
|
startwall = sec->wallptr; endwall = startwall + sec->wallnum;
|
|
for (j=startwall,wal=&wall[startwall];j<endwall;j++,wal++)
|
|
{
|
|
wal2 = &wall[wal->point2];
|
|
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*((*y)-y1) < ((*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 ((wal->nextsector < 0) || (wal->cstat&dawalclipmask)) clipyou = 1;
|
|
else if (editstatus == 0)
|
|
{
|
|
if (rintersect(*x,*y,0,gx,gy,0,x1,y1,x2,y2,&dax,&day,&daz) == 0)
|
|
dax = *x, day = *y;
|
|
daz = getflorzofslope((short)dasect,dax,day);
|
|
daz2 = getflorzofslope(wal->nextsector,dax,day);
|
|
|
|
sec2 = §or[wal->nextsector];
|
|
if (daz2 < daz-(1<<8))
|
|
if ((sec2->floorstat&1) == 0)
|
|
if ((*z) >= daz2-(flordist-1)) clipyou = 1;
|
|
if (clipyou == 0)
|
|
{
|
|
daz = getceilzofslope((short)dasect,dax,day);
|
|
daz2 = getceilzofslope(wal->nextsector,dax,day);
|
|
if (daz2 > daz+(1<<8))
|
|
if ((sec2->ceilingstat&1) == 0)
|
|
if ((*z) <= daz2+(ceildist-1)) clipyou = 1;
|
|
}
|
|
}
|
|
|
|
if (clipyou)
|
|
{
|
|
//Add 2 boxes at endpoints
|
|
bsz = walldist; if (gx < 0) bsz = -bsz;
|
|
addclipline(x1-bsz,y1-bsz,x1-bsz,y1+bsz,(short)j+32768);
|
|
addclipline(x2-bsz,y2-bsz,x2-bsz,y2+bsz,(short)j+32768);
|
|
bsz = walldist; if (gy < 0) bsz = -bsz;
|
|
addclipline(x1+bsz,y1-bsz,x1-bsz,y1-bsz,(short)j+32768);
|
|
addclipline(x2+bsz,y2-bsz,x2-bsz,y2-bsz,(short)j+32768);
|
|
|
|
dax = walldist; if (dy > 0) dax = -dax;
|
|
day = walldist; if (dx < 0) day = -day;
|
|
addclipline(x1+dax,y1+day,x2+dax,y2+day,(short)j+32768);
|
|
}
|
|
else
|
|
{
|
|
for (i=clipsectnum-1;i>=0;i--)
|
|
if (wal->nextsector == clipsectorlist[i]) break;
|
|
if (i < 0) clipsectorlist[clipsectnum++] = wal->nextsector;
|
|
}
|
|
}
|
|
|
|
for (j=headspritesect[dasect];j>=0;j=nextspritesect[j])
|
|
{
|
|
spr = &sprite[j];
|
|
cstat = spr->cstat;
|
|
if ((cstat&dasprclipmask) == 0) 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 -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
|
|
if (((*z) < daz+ceildist) && ((*z) > daz-k-flordist))
|
|
{
|
|
bsz = (spr->clipdist<<2)+walldist; if (gx < 0) bsz = -bsz;
|
|
addclipline(x1-bsz,y1-bsz,x1-bsz,y1+bsz,(short)j+49152);
|
|
bsz = (spr->clipdist<<2)+walldist; if (gy < 0) bsz = -bsz;
|
|
addclipline(x1+bsz,y1-bsz,x1-bsz,y1-bsz,(short)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 -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
|
|
daz2 = daz-k;
|
|
daz += ceildist; daz2 -= flordist;
|
|
if (((*z) < daz) && ((*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 = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)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-(*x))*(y2-(*y)) >= (x2-(*x))*(y1-(*y))) //Front
|
|
{
|
|
addclipline(x1+dax,y1+day,x2+day,y2-dax,(short)j+49152);
|
|
}
|
|
else
|
|
{
|
|
if ((cstat&64) != 0) continue;
|
|
addclipline(x2-dax,y2-day,x1-day,y1+dax,(short)j+49152);
|
|
}
|
|
|
|
//Side blocker
|
|
if ((x2-x1)*((*x)-x1) + (y2-y1)*((*y)-y1) < 0)
|
|
{ addclipline(x1-day,y1+dax,x1+dax,y1+day,(short)j+49152); }
|
|
else if ((x1-x2)*((*x)-x2) + (y1-y2)*((*y)-y2) < 0)
|
|
{ addclipline(x2+day,y2-dax,x2-dax,y2-day,(short)j+49152); }
|
|
}
|
|
}
|
|
break;
|
|
case 32:
|
|
daz = spr->z+ceildist;
|
|
daz2 = spr->z-flordist;
|
|
if (((*z) < daz) && ((*z) > daz2))
|
|
{
|
|
if ((cstat&64) != 0)
|
|
if (((*z) > spr->z) == ((cstat&8)==0)) continue;
|
|
|
|
tilenum = spr->picnum;
|
|
xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
|
|
yoff = (long)((signed char)((picanm[tilenum]>>16)&255))+((long)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]-(*x))*(ryi[1]-(*y)) < (rxi[1]-(*x))*(ryi[0]-(*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,(short)j+49152);
|
|
}
|
|
else if ((rxi[2]-(*x))*(ryi[3]-(*y)) < (rxi[3]-(*x))*(ryi[2]-(*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,(short)j+49152);
|
|
}
|
|
|
|
if ((rxi[1]-(*x))*(ryi[2]-(*y)) < (rxi[2]-(*x))*(ryi[1]-(*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,(short)j+49152);
|
|
}
|
|
else if ((rxi[3]-(*x))*(ryi[0]-(*y)) < (rxi[0]-(*x))*(ryi[3]-(*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,(short)j+49152);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
} while (clipsectcnt < clipsectnum);
|
|
|
|
|
|
hitwall = 0;
|
|
cnt = clipmoveboxtracenum;
|
|
do
|
|
{
|
|
intx = goalx; inty = goaly;
|
|
if ((hitwall = raytrace(*x, *y, &intx, &inty)) >= 0)
|
|
{
|
|
lx = clipit[hitwall].x2-clipit[hitwall].x1;
|
|
ly = clipit[hitwall].y2-clipit[hitwall].y1;
|
|
templong2 = lx*lx + ly*ly;
|
|
if (templong2 > 0)
|
|
{
|
|
templong1 = (goalx-intx)*lx + (goaly-inty)*ly;
|
|
|
|
if ((klabs(templong1)>>11) < templong2)
|
|
i = divscale20(templong1,templong2);
|
|
else
|
|
i = 0;
|
|
goalx = mulscale20(lx,i)+intx;
|
|
goaly = mulscale20(ly,i)+inty;
|
|
}
|
|
|
|
templong1 = dmulscale6(lx,oxvect,ly,oyvect);
|
|
for (i=cnt+1;i<=clipmoveboxtracenum;i++)
|
|
{
|
|
j = hitwalls[i];
|
|
templong2 = dmulscale6(clipit[j].x2-clipit[j].x1,oxvect,clipit[j].y2-clipit[j].y1,oyvect);
|
|
if ((templong1^templong2) < 0)
|
|
{
|
|
updatesector(*x,*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--;
|
|
|
|
*x = intx;
|
|
*y = inty;
|
|
} while (((xvect|yvect) != 0) && (hitwall >= 0) && (cnt > 0));
|
|
|
|
for (j=0;j<clipsectnum;j++)
|
|
if (inside(*x,*y,clipsectorlist[j]) == 1)
|
|
{
|
|
*sectnum = clipsectorlist[j];
|
|
return(retval);
|
|
}
|
|
|
|
*sectnum = -1; templong1 = 0x7fffffff;
|
|
for (j=numsectors-1;j>=0;j--)
|
|
if (inside(*x,*y,j) == 1)
|
|
{
|
|
if (sector[j].ceilingstat&2)
|
|
templong2 = (getceilzofslope((short)j,*x,*y)-(*z));
|
|
else
|
|
templong2 = (sector[j].ceilingz-(*z));
|
|
|
|
if (templong2 > 0)
|
|
{
|
|
if (templong2 < templong1)
|
|
{ *sectnum = j; templong1 = templong2; }
|
|
}
|
|
else
|
|
{
|
|
if (sector[j].floorstat&2)
|
|
templong2 = ((*z)-getflorzofslope((short)j,*x,*y));
|
|
else
|
|
templong2 = ((*z)-sector[j].floorz);
|
|
|
|
if (templong2 <= 0)
|
|
{
|
|
*sectnum = j;
|
|
return(retval);
|
|
}
|
|
if (templong2 < templong1)
|
|
{ *sectnum = j; templong1 = templong2; }
|
|
}
|
|
}
|
|
|
|
return(retval);
|
|
}
|
|
|
|
|
|
//
|
|
// pushmove
|
|
//
|
|
long pushmove (long *x, long *y, long *z, short *sectnum,
|
|
long walldist, long ceildist, long flordist, unsigned long cliptype)
|
|
{
|
|
sectortype *sec, *sec2;
|
|
walltype *wal, *wal2;
|
|
spritetype *spr;
|
|
long i, j, k, t, dx, dy, dax, day, daz, daz2, bad, dir;
|
|
long dasprclipmask, dawalclipmask;
|
|
short 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 = (*x)-spr->x; day = (*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 -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
|
|
if (((*z) < daz+ceildist) && ((*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
|
|
{
|
|
*x = (*x) + dx; *y = (*y) + dy;
|
|
bad2--; if (bad2 == 0) break;
|
|
} while ((klabs((*x)-spr->x) < t) && (klabs((*y)-spr->y) < t));
|
|
bad = -1;
|
|
k--; if (k <= 0) return(bad);
|
|
updatesector(*x,*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(*x,*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 (*x, *y)
|
|
dax = wall[wal->point2].x-wal->x;
|
|
day = wall[wal->point2].y-wal->y;
|
|
daz = dax*((*x)-wal->x) + day*((*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 (*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 (*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
|
|
{
|
|
*x = (*x) + dx; *y = (*y) + dy;
|
|
bad2--; if (bad2 == 0) break;
|
|
} while (clipinsidebox(*x,*y,i,walldist-4) != 0);
|
|
bad = -1;
|
|
k--; if (k <= 0) return(bad);
|
|
updatesector(*x,*y,sectnum);
|
|
}
|
|
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(long x, long y, short *sectnum)
|
|
{
|
|
walltype *wal;
|
|
long 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,(short)i) == 1)
|
|
{
|
|
*sectnum = i;
|
|
return;
|
|
}
|
|
wal++;
|
|
j--;
|
|
} while (j != 0);
|
|
}
|
|
|
|
for (i=numsectors-1;i>=0;i--)
|
|
if (inside(x,y,(short)i) == 1)
|
|
{
|
|
*sectnum = i;
|
|
return;
|
|
}
|
|
|
|
*sectnum = -1;
|
|
}
|
|
|
|
void updatesectorz(long x, long y, long z, short *sectnum)
|
|
{
|
|
walltype *wal;
|
|
long i, j, cz, fz;
|
|
|
|
getzsofslope(*sectnum, x, y, &cz, &fz);
|
|
if ((z >= cz) && (z <= fz))
|
|
if (inside(x,y,*sectnum) != 0) return;
|
|
|
|
if ((*sectnum >= 0) && (*sectnum < numsectors))
|
|
{
|
|
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,(short)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,(short)i) == 1)
|
|
{ *sectnum = i; return; }
|
|
}
|
|
|
|
*sectnum = -1;
|
|
}
|
|
|
|
|
|
//
|
|
// rotatepoint
|
|
//
|
|
void rotatepoint(long xpivot, long ypivot, long x, long y, short daang, long *x2, long *y2)
|
|
{
|
|
long 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(long *mousx, long *mousy, long *bstatus)
|
|
{
|
|
readmousexy(mousx,mousy);
|
|
readmousebstatus(bstatus);
|
|
}
|
|
|
|
|
|
//
|
|
// krand
|
|
//
|
|
long krand(void)
|
|
{
|
|
randomseed = (randomseed*27584621)+1;
|
|
return(((unsigned long)randomseed)>>16);
|
|
}
|
|
|
|
|
|
//
|
|
// getzrange
|
|
//
|
|
void getzrange(long x, long y, long z, short sectnum,
|
|
long *ceilz, long *ceilhit, long *florz, long *florhit,
|
|
long walldist, unsigned long cliptype)
|
|
{
|
|
sectortype *sec;
|
|
walltype *wal, *wal2;
|
|
spritetype *spr;
|
|
long clipsectcnt, startwall, endwall, tilenum, xoff, yoff, dax, day;
|
|
long xmin, ymin, xmax, ymax, i, j, k, l, daz, daz2, dx, dy;
|
|
long x1, y1, x2, y2, x3, y3, x4, y4, ang, cosang, sinang;
|
|
long xspan, yspan, xrepeat, yrepeat, dasprclipmask, dawalclipmask;
|
|
short cstat;
|
|
char clipyou;
|
|
|
|
if (sectnum < 0)
|
|
{
|
|
*ceilz = 0x80000000; *ceilhit = -1;
|
|
*florz = 0x7fffffff; *florhit = -1;
|
|
return;
|
|
}
|
|
|
|
//Extra walldist for sprites on sector lines
|
|
i = walldist+MAXCLIPDIST+1;
|
|
xmin = x-i; ymin = y-i;
|
|
xmax = x+i; ymax = y+i;
|
|
|
|
getzsofslope(sectnum,x,y,ceilz,florz);
|
|
*ceilhit = sectnum+16384; *florhit = sectnum+16384;
|
|
|
|
dawalclipmask = (cliptype&65535);
|
|
dasprclipmask = (cliptype>>16);
|
|
|
|
clipsectorlist[0] = sectnum;
|
|
clipsectcnt = 0; clipsectnum = 1;
|
|
|
|
do //Collect sectors inside your square first
|
|
{
|
|
sec = §or[clipsectorlist[clipsectcnt]];
|
|
startwall = sec->wallptr; endwall = startwall + sec->wallnum;
|
|
for (j=startwall,wal=&wall[startwall];j<endwall;j++,wal++)
|
|
{
|
|
k = wal->nextsector;
|
|
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*(y-y1) < (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 (editstatus == 0)
|
|
{
|
|
if (((sec->ceilingstat&1) == 0) && (z <= sec->ceilingz+(3<<8))) continue;
|
|
if (((sec->floorstat&1) == 0) && (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((short)k,x,y,&daz,&daz2);
|
|
if (daz > *ceilz) { *ceilz = daz; *ceilhit = k+16384; }
|
|
if (daz2 < *florz) { *florz = daz2; *florhit = k+16384; }
|
|
}
|
|
}
|
|
clipsectcnt++;
|
|
} while (clipsectcnt < clipsectnum);
|
|
|
|
for (i=0;i<clipsectnum;i++)
|
|
{
|
|
for (j=headspritesect[clipsectorlist[i]];j>=0;j=nextspritesect[j])
|
|
{
|
|
spr = &sprite[j];
|
|
cstat = spr->cstat;
|
|
if (cstat&dasprclipmask)
|
|
{
|
|
x1 = spr->x; y1 = spr->y;
|
|
|
|
clipyou = 0;
|
|
switch (cstat&48)
|
|
{
|
|
case 0:
|
|
k = walldist+(spr->clipdist<<2)+1;
|
|
if ((klabs(x1-x) <= k) && (klabs(y1-y) <= k))
|
|
{
|
|
daz = spr->z;
|
|
k = ((tilesizy[spr->picnum]*spr->yrepeat)<<1);
|
|
if (cstat&128) daz += k;
|
|
if (picanm[spr->picnum]&0x00ff0000) daz -= ((long)((signed char)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
|
|
daz2 = daz - (k<<1);
|
|
clipyou = 1;
|
|
}
|
|
break;
|
|
case 16:
|
|
tilenum = spr->picnum;
|
|
xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)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(x,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 -= ((long)((signed char)((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 ((z > daz) == ((cstat&8)==0)) continue;
|
|
|
|
tilenum = spr->picnum;
|
|
xoff = (long)((signed char)((picanm[tilenum]>>8)&255))+((long)spr->xoffset);
|
|
yoff = (long)((signed char)((picanm[tilenum]>>16)&255))+((long)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)-x;
|
|
y1 += dmulscale16(sinang,day,-cosang,dax)-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<x2*y1)^(y1<y2);
|
|
else if (x1 >= 0) clipyou ^= 1;
|
|
}
|
|
if ((y2^y3) < 0)
|
|
{
|
|
if ((x2^x3) < 0) clipyou ^= (x2*y3<x3*y2)^(y2<y3);
|
|
else if (x2 >= 0) clipyou ^= 1;
|
|
}
|
|
if ((y3^y4) < 0)
|
|
{
|
|
if ((x3^x4) < 0) clipyou ^= (x3*y4<x4*y3)^(y3<y4);
|
|
else if (x3 >= 0) clipyou ^= 1;
|
|
}
|
|
if ((y4^y1) < 0)
|
|
{
|
|
if ((x4^x1) < 0) clipyou ^= (x4*y1<x1*y4)^(y4<y1);
|
|
else if (x4 >= 0) clipyou ^= 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (clipyou != 0)
|
|
{
|
|
if ((z > daz) && (daz > *ceilz)) { *ceilz = daz; *ceilhit = j+49152; }
|
|
if ((z < daz2) && (daz2 < *florz)) { *florz = daz2; *florhit = j+49152; }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// setview
|
|
//
|
|
void setview(long x1, long y1, long x2, long y2)
|
|
{
|
|
long 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(65536L,(long)divscale16(ydim*320L,xdim*200L));
|
|
|
|
for (i=0;i<windowx1;i++) { startumost[i] = 1, startdmost[i] = 0; }
|
|
for (i=windowx1;i<=windowx2;i++)
|
|
{ startumost[i] = windowy1, startdmost[i] = windowy2+1; }
|
|
for (i=windowx2+1;i<xdim;i++) { startumost[i] = 1, startdmost[i] = 0; }
|
|
|
|
/*
|
|
begindrawing(); //{{{
|
|
viewoffset = windowy1*bytesperline + windowx1;
|
|
enddrawing(); //}}}
|
|
*/
|
|
}
|
|
|
|
|
|
//
|
|
// setaspect
|
|
//
|
|
void setaspect(long daxrange, long daaspect)
|
|
{
|
|
viewingrange = daxrange;
|
|
viewingrangerecip = divscale32(1L,daxrange);
|
|
|
|
yxaspect = daaspect;
|
|
xyaspect = divscale32(1,yxaspect);
|
|
xdimenscale = scale(xdimen,yxaspect,320);
|
|
xdimscale = scale(320,xyaspect,xdimen);
|
|
}
|
|
|
|
|
|
//
|
|
// flushperms
|
|
//
|
|
void flushperms(void)
|
|
{
|
|
permhead = permtail = 0;
|
|
}
|
|
|
|
|
|
//
|
|
// rotatesprite
|
|
//
|
|
void rotatesprite(long sx, long sy, long z, short a, short picnum, signed char dashade, char dapalnum, char dastat, long cx1, long cy1, long cx2, long cy2)
|
|
{
|
|
long i;
|
|
permfifotype *per, *per2;
|
|
|
|
if ((cx1 > cx2) || (cy1 > cy2)) return;
|
|
if (z <= 16) return;
|
|
if (picanm[picnum]&192) picnum += animateoffs(picnum,(short)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(long palnum, char *remapbuf, signed char r, signed char g, signed char b, char dastat)
|
|
{
|
|
long i, j, palscale;
|
|
char *ptr, *ptr2;
|
|
|
|
if (paletteloaded == 0) return;
|
|
|
|
if (palookup[palnum] == NULL)
|
|
{
|
|
//Allocate palookup buffer
|
|
if ((palookup[palnum] = (char *)kkmalloc(numpalookups<<8)) == NULL)
|
|
allocache((long*)&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<numpalookups;j++)
|
|
{ *ptr2 = *ptr; ptr += 256; ptr2 += 256; }
|
|
}
|
|
#if defined(USE_OPENGL)
|
|
palookupfog[palnum].r = 0;
|
|
palookupfog[palnum].g = 0;
|
|
palookupfog[palnum].b = 0;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
ptr2 = palookup[palnum];
|
|
for (i=0;i<numpalookups;i++)
|
|
{
|
|
palscale = divscale16(i,numpalookups);
|
|
for (j=0;j<256;j++)
|
|
{
|
|
ptr = (char *)&palette[remapbuf[j]*3];
|
|
*ptr2++ = getclosestcol((long)ptr[0]+mulscale16(r-ptr[0],palscale),
|
|
(long)ptr[1]+mulscale16(g-ptr[1],palscale),
|
|
(long)ptr[2]+mulscale16(b-ptr[2],palscale));
|
|
}
|
|
}
|
|
#if defined(USE_OPENGL)
|
|
palookupfog[palnum].r = r;
|
|
palookupfog[palnum].g = g;
|
|
palookupfog[palnum].b = b;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
void setvgapalette(void)
|
|
{
|
|
int i;
|
|
|
|
for (i=0;i<256;i++) {
|
|
curpalettefaded[i].b = curpalette[i].b = vgapal16[4*i] << 2;
|
|
curpalettefaded[i].g = curpalette[i].g = vgapal16[4*i+1] << 2;
|
|
curpalettefaded[i].r = curpalette[i].r = vgapal16[4*i+2] << 2;
|
|
}
|
|
setpalette(0,256,vgapal16);
|
|
}
|
|
|
|
//
|
|
// setbrightness
|
|
//
|
|
static unsigned long lastpalettesum = 0;
|
|
void setbrightness(char dabrightness, char *dapal, char noapply)
|
|
{
|
|
long i, k, j;
|
|
float f;
|
|
unsigned long newpalettesum, lastbright;
|
|
|
|
lastbright = curbrightness;
|
|
if (!(noapply&4))
|
|
curbrightness = min(max((long)dabrightness,0),15);
|
|
|
|
f = 1.0 + ((float)curbrightness / 10.0);
|
|
if (setgamma(f,f,f)) 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 = (tempbuf[k++] = britable[j][ curpalette[i].b ]);
|
|
curpalettefaded[i].g = (tempbuf[k++] = britable[j][ curpalette[i].g ]);
|
|
curpalettefaded[i].r = (tempbuf[k++] = britable[j][ curpalette[i].r ]);
|
|
curpalettefaded[i].f = tempbuf[k++] = 0;
|
|
}
|
|
|
|
if ((noapply&1) == 0) setpalette(0,256,(char*)tempbuf);
|
|
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
if (rendmode >= 3) {
|
|
newpalettesum = crc32once((unsigned char *)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();
|
|
lastpalettesum = newpalettesum;
|
|
}
|
|
#endif
|
|
|
|
palfadergb.r = palfadergb.g = palfadergb.b = 0;
|
|
palfadedelta = 0;
|
|
}
|
|
|
|
|
|
//
|
|
// setpalettefade
|
|
//
|
|
void setpalettefade(char r, char g, char b, char offset)
|
|
{
|
|
int i,k;
|
|
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;
|
|
|
|
k = 0;
|
|
for (i=0;i<256;i++) {
|
|
if (gammabrightness) p = curpalette[i];
|
|
else {
|
|
p.b = britable[curbrightness][ curpalette[i].b ];
|
|
p.g = britable[curbrightness][ curpalette[i].g ];
|
|
p.r = britable[curbrightness][ curpalette[i].r ];
|
|
}
|
|
|
|
tempbuf[k++] =
|
|
(curpalettefaded[i].b =
|
|
p.b + ( ( ( (long)palfadergb.b - (long)p.b ) * (long)offset ) >> 6 ) ) >> 2;
|
|
tempbuf[k++] =
|
|
(curpalettefaded[i].g =
|
|
p.g + ( ( ( (long)palfadergb.g - (long)p.g ) * (long)offset ) >> 6 ) ) >> 2;
|
|
tempbuf[k++] =
|
|
(curpalettefaded[i].r =
|
|
p.r + ( ( ( (long)palfadergb.r - (long)p.r ) * (long)offset ) >> 6 ) ) >> 2;
|
|
tempbuf[k++] = curpalettefaded[i].f = 0;
|
|
}
|
|
|
|
setpalette(0,256,(char*)tempbuf);
|
|
}
|
|
|
|
|
|
//
|
|
// clearview
|
|
//
|
|
void clearview(long dacol)
|
|
{
|
|
long p, y, dx;
|
|
|
|
if (qsetmode != 200) return;
|
|
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
if (rendmode >= 3) {
|
|
palette_t p;
|
|
if (gammabrightness) p = curpalette[dacol];
|
|
else {
|
|
p.r = britable[curbrightness][ curpalette[dacol].r ];
|
|
p.g = britable[curbrightness][ curpalette[dacol].g ];
|
|
p.b = britable[curbrightness][ curpalette[dacol].b ];
|
|
}
|
|
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(long dacol)
|
|
{
|
|
if (qsetmode != 200) return;
|
|
//dacol += (dacol<<8); dacol += (dacol<<16);
|
|
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
if (rendmode >= 3) {
|
|
palette_t p;
|
|
if (gammabrightness) p = curpalette[dacol];
|
|
else {
|
|
p.r = britable[curbrightness][ curpalette[dacol].r ];
|
|
p.g = britable[curbrightness][ curpalette[dacol].g ];
|
|
p.b = britable[curbrightness][ curpalette[dacol].b ];
|
|
}
|
|
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(long x, long y, char col)
|
|
{
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
if (rendmode >= 3 && qsetmode == 200) {
|
|
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
|
|
|
|
bglBegin(GL_POINTS);
|
|
bglColor4ub(p.r,p.g,p.b,255);
|
|
bglVertex2i(x,y);
|
|
bglEnd();
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
begindrawing(); //{{{
|
|
drawpixel((void*)(ylookup[y]+x+frameplace),(long)col);
|
|
enddrawing(); //}}}
|
|
}
|
|
|
|
|
|
//
|
|
// getpixel
|
|
//
|
|
char getpixel(long x, long y)
|
|
{
|
|
char r;
|
|
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
if (rendmode >= 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(short tilenume, long xsiz, long ysiz)
|
|
{
|
|
long 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)
|
|
{
|
|
long 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(short tilenume)
|
|
{
|
|
long i, j, k, xsiz, ysiz;
|
|
char *ptr1, *ptr2;
|
|
|
|
xsiz = tilesizx[tilenume]; ysiz = tilesizy[tilenume];
|
|
|
|
//supports square tiles only for rotation part
|
|
if (xsiz == ysiz)
|
|
{
|
|
k = (xsiz<<1);
|
|
for (i=xsiz-1;i>=0;i--)
|
|
{
|
|
ptr1 = (char *)(waloff[tilenume]+i*(xsiz+1)); ptr2 = ptr1;
|
|
if ((i&1) != 0) { ptr1--; ptr2 -= xsiz; swapchar(ptr1,ptr2); }
|
|
for (j=(i>>1)-1;j>=0;j--)
|
|
{ ptr1 -= 2; ptr2 -= k; swapchar2(ptr1,ptr2,xsiz); }
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// preparemirror
|
|
//
|
|
void preparemirror(long dax, long day, long daz, short daang, long dahoriz, short dawall, short dasector, long *tposx, long *tposy, short *tang)
|
|
{
|
|
long i, j, x, y, dx, dy;
|
|
|
|
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)
|
|
{
|
|
long i, dy, 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
|
|
//
|
|
long sectorofwall(short theline)
|
|
{
|
|
long i, gap;
|
|
|
|
if ((theline < 0) || (theline >= numwalls)) return(-1);
|
|
i = wall[theline].nextwall; if (i >= 0) 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
|
|
//
|
|
long getceilzofslope(short sectnum, long dax, long day)
|
|
{
|
|
long dx, dy, i, j;
|
|
walltype *wal;
|
|
|
|
if (!(sector[sectnum].ceilingstat&2)) return(sector[sectnum].ceilingz);
|
|
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,i));
|
|
}
|
|
|
|
|
|
//
|
|
// getflorzofslope
|
|
//
|
|
long getflorzofslope(short sectnum, long dax, long day)
|
|
{
|
|
long dx, dy, i, j;
|
|
walltype *wal;
|
|
|
|
if (!(sector[sectnum].floorstat&2)) return(sector[sectnum].floorz);
|
|
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,i));
|
|
}
|
|
|
|
|
|
//
|
|
// getzsofslope
|
|
//
|
|
void getzsofslope(short sectnum, long dax, long day, long *ceilz, long *florz)
|
|
{
|
|
long 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,i);
|
|
if (sec->floorstat&2) *florz = (*florz)+scale(sec->floorheinum,j,i);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// alignceilslope
|
|
//
|
|
void alignceilslope(short dasect, long x, long y, long z)
|
|
{
|
|
long 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(short dasect, long x, long y, long z)
|
|
{
|
|
long 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
|
|
//
|
|
long loopnumofsector(short sectnum, short wallnum)
|
|
{
|
|
long i, numloops, startwall, endwall;
|
|
|
|
numloops = 0;
|
|
startwall = sector[sectnum].wallptr;
|
|
endwall = startwall + sector[sectnum].wallnum;
|
|
for (i=startwall;i<endwall;i++)
|
|
{
|
|
if (i == wallnum) return(numloops);
|
|
if (wall[i].point2 < i) numloops++;
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
|
|
//
|
|
// setfirstwall
|
|
//
|
|
void setfirstwall(short sectnum, short newfirstwall)
|
|
{
|
|
long i, j, k, numwallsofloop;
|
|
long startwall, endwall, danumwalls, dagoalloop;
|
|
|
|
startwall = sector[sectnum].wallptr;
|
|
danumwalls = sector[sectnum].wallnum;
|
|
endwall = startwall+danumwalls;
|
|
if ((newfirstwall < startwall) || (newfirstwall >= startwall+danumwalls)) return;
|
|
for (i=0;i<danumwalls;i++)
|
|
Bmemcpy(&wall[i+numwalls],&wall[i+startwall],sizeof(walltype));
|
|
|
|
numwallsofloop = 0;
|
|
i = newfirstwall;
|
|
do
|
|
{
|
|
numwallsofloop++;
|
|
i = wall[i].point2;
|
|
} while (i != newfirstwall);
|
|
|
|
//Put correct loop at beginning
|
|
dagoalloop = loopnumofsector(sectnum,newfirstwall);
|
|
if (dagoalloop > 0)
|
|
{
|
|
j = 0;
|
|
while (loopnumofsector(sectnum,j+startwall) != dagoalloop) j++;
|
|
for (i=0;i<danumwalls;i++)
|
|
{
|
|
k = i+j; if (k >= danumwalls) k -= danumwalls;
|
|
Bmemcpy(&wall[startwall+i],&wall[numwalls+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;i++)
|
|
Bmemcpy(&wall[i+numwalls],&wall[i+startwall],sizeof(walltype));
|
|
for (i=0;i<numwallsofloop;i++)
|
|
{
|
|
k = i+newfirstwall-startwall;
|
|
if (k >= numwallsofloop) k -= numwallsofloop;
|
|
Bmemcpy(&wall[startwall+i],&wall[numwalls+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<endwall;i++)
|
|
if (wall[i].nextwall >= 0) wall[wall[i].nextwall].nextwall = i;
|
|
}
|
|
|
|
|
|
//
|
|
// drawline256
|
|
//
|
|
void drawline256(long x1, long y1, long x2, long y2, char col)
|
|
{
|
|
long dx, dy, i, j, p, inc, plc, daend;
|
|
|
|
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<daend;i++)
|
|
{
|
|
j = (plc>>12);
|
|
if ((j >= startumost[i]) && (j < startdmost[i]))
|
|
drawpixel((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<daend;i++)
|
|
{
|
|
j = (plc>>12);
|
|
if ((i >= startumost[j]) && (i < startdmost[j]))
|
|
drawpixel((void*)(j+p),col);
|
|
plc += inc; p += ylookup[1];
|
|
}
|
|
enddrawing(); //}}}
|
|
}
|
|
}
|
|
|
|
//
|
|
// drawline16
|
|
//
|
|
// JBF: Had to add extra tests to make sure x-coordinates weren't winding up -'ve
|
|
// after clipping or crashes would ensue
|
|
unsigned long drawlinepat = 0xffffffff;
|
|
|
|
void drawline16(long x1, long y1, long x2, long y2, char col)
|
|
{
|
|
long i, dx, dy, p, pinc, d;
|
|
unsigned long patc=0;
|
|
|
|
dx = x2-x1; dy = y2-y1;
|
|
if (dx >= 0)
|
|
{
|
|
if ((x1 >= xres) || (x2 < 0)) return;
|
|
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;
|
|
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;
|
|
if (y1 < 0) { if (dx) x1 += scale(0-y1,dx,dy); y1 = 0; if (x1 < 0) x1 = 0; }
|
|
if (y2 >= ydim16) { if (dx) x2 += scale(ydim16-1-y2,dx,dy); y2 = ydim16-1; if (x2 < 0) x2 = 0; }
|
|
}
|
|
else
|
|
{
|
|
if ((y2 >= ydim16) || (y1 < 0)) return;
|
|
if (y2 < 0) { if (dx) x2 += scale(0-y2,dx,dy); y2 = 0; if (x2 < 0) x2 = 0; }
|
|
if (y1 >= ydim16) { if (dx) x1 += scale(ydim16-1-y1,dx,dy); y1 = ydim16-1; if (x1 < 0) x1 = 0; }
|
|
}
|
|
|
|
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 = ((long)col<<24)|((long)col<<16)|((long)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;
|
|
}
|
|
|
|
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(); //}}}
|
|
}
|
|
|
|
void drawcircle16(long x1, long y1, long r, char col)
|
|
{
|
|
#if 1
|
|
long p, 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 ((unsigned long)y1 < (unsigned long)ydim16 && (unsigned long)(x1+r) < (unsigned long)xres )
|
|
drawpixel((char *)(p+r), col); // a
|
|
if ((unsigned long)x1 < (unsigned long)xres && (unsigned long)(y1+r) < (unsigned long)ydim16)
|
|
drawpixel((char *)(p+(r*bytesperline)), col); // b
|
|
if ((unsigned long)y1 < (unsigned long)ydim16 && (unsigned long)(x1-r) < (unsigned long)xres )
|
|
drawpixel((char *)(p-r), col); // c
|
|
if ((unsigned long)x1 < (unsigned long)xres && (unsigned long)(y1-r) < (unsigned long)ydim16)
|
|
drawpixel((char *)(p-(r*bytesperline)), col); // d
|
|
}
|
|
|
|
while (yp > xp) {
|
|
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 ((unsigned long)(x1+yp) < (unsigned long)xres && (unsigned long)(y1+xp) < (unsigned long)ydim16)
|
|
drawpixel((char *)(p+yp+xpbpl), col); // 1
|
|
if ((unsigned long)(x1+xp) < (unsigned long)xres && (unsigned long)(y1+yp) < (unsigned long)ydim16)
|
|
drawpixel((char *)(p+xp+ypbpl), col); // 2
|
|
if ((unsigned long)(x1-xp) < (unsigned long)xres && (unsigned long)(y1+yp) < (unsigned long)ydim16)
|
|
drawpixel((char *)(p-xp+ypbpl), col); // 3
|
|
if ((unsigned long)(x1-yp) < (unsigned long)xres && (unsigned long)(y1+xp) < (unsigned long)ydim16)
|
|
drawpixel((char *)(p-yp+xpbpl), col); // 4
|
|
if ((unsigned long)(x1-yp) < (unsigned long)xres && (unsigned long)(y1-xp) < (unsigned long)ydim16)
|
|
drawpixel((char *)(p-yp-xpbpl), col); // 5
|
|
if ((unsigned long)(x1-xp) < (unsigned long)xres && (unsigned long)(y1-yp) < (unsigned long)ydim16)
|
|
drawpixel((char *)(p-xp-ypbpl), col); // 6
|
|
if ((unsigned long)(x1+xp) < (unsigned long)xres && (unsigned long)(y1-yp) < (unsigned long)ydim16)
|
|
drawpixel((char *)(p+xp-ypbpl), col); // 7
|
|
if ((unsigned long)(x1+yp) < (unsigned long)xres && (unsigned long)(y1-xp) < (unsigned long)ydim16)
|
|
drawpixel((char *)(p+yp-xpbpl), col); // 8
|
|
}
|
|
}
|
|
enddrawing();
|
|
#else
|
|
// JonoF's rough approximation of a circle
|
|
long l,spx,spy,lpx,lpy,px,py;
|
|
|
|
spx = lpx = x1+mulscale14(r,sintable[0]);
|
|
spy = lpy = y1+mulscale14(r,sintable[512]);
|
|
|
|
for (l=64;l<2048;l+=64) {
|
|
px = x1+mulscale14(r,sintable[l]);
|
|
py = y1+mulscale14(r,sintable[(l+512)&2047]);
|
|
|
|
drawline16(lpx,lpy,px,py,col);
|
|
|
|
lpx = px;
|
|
lpy = py;
|
|
}
|
|
|
|
drawline16(lpx,lpy,spx,spy,col);
|
|
#endif
|
|
}
|
|
|
|
|
|
//
|
|
// 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(long daxdim, long 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 - STATUS2DSIZ;
|
|
halfxdim16 = xres >> 1;
|
|
midydim16 = scale(200,yres,480);
|
|
|
|
begindrawing(); //{{{
|
|
clearbuf((char *)(frameplace + (ydim16*bytesperline)), (bytesperline*STATUS2DSIZ) >> 2, 0x08080808l);
|
|
clearbuf((char *)frameplace, (ydim16*bytesperline) >> 2, 0L);
|
|
enddrawing(); //}}}
|
|
}
|
|
|
|
qsetmode = ((daxdim<<16)|(daydim&0xffff));
|
|
}
|
|
|
|
|
|
//
|
|
// clear2dscreen
|
|
//
|
|
void clear2dscreen(void)
|
|
{
|
|
int clearsz;
|
|
|
|
begindrawing(); //{{{
|
|
if (qsetmode == 350) clearsz = 350;
|
|
else {
|
|
if (ydim16 <= yres-STATUS2DSIZ) clearsz = yres - STATUS2DSIZ;
|
|
else clearsz = yres;
|
|
}
|
|
clearbuf((char *)frameplace, (bytesperline*clearsz) >> 2, 0);
|
|
enddrawing(); //}}}
|
|
}
|
|
|
|
|
|
//
|
|
// draw2dgrid
|
|
//
|
|
void draw2dgrid(long posxe, long posye, short ange, long zoome, short gride)
|
|
{
|
|
long i, xp1, yp1, xp2=0, yp2, tempy;
|
|
|
|
if (gride > 0)
|
|
{
|
|
begindrawing(); //{{{
|
|
|
|
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,8);
|
|
}
|
|
}
|
|
}
|
|
if ((i >= editorgridextent) && (xp1 < xdim))
|
|
xp2 = xp1;
|
|
if ((xp2 >= 0) && (xp2 < xdim))
|
|
{
|
|
drawline16(xp2,yp1,xp2,yp2,8);
|
|
}
|
|
}
|
|
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))
|
|
{
|
|
drawline16(halfxdim16-xp1,midydim16-yp1,halfxdim16-xp2,midydim16-yp1,8);
|
|
tempy = yp1;
|
|
}
|
|
}
|
|
}
|
|
enddrawing(); //}}}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// draw2dscreen
|
|
//
|
|
|
|
char spritecol2d[MAXTILES][2];
|
|
|
|
void draw2dscreen(long posxe, long posye, short ange, long zoome, short gride)
|
|
{
|
|
walltype *wal;
|
|
long i, j, k, xp1, yp1, xp2, yp2, tempy, templong;
|
|
char col, mask;
|
|
|
|
if (qsetmode == 200) return;
|
|
|
|
begindrawing(); //{{{
|
|
|
|
if (editstatus == 0)
|
|
{
|
|
faketimerhandler();
|
|
clear2dscreen();
|
|
|
|
faketimerhandler();
|
|
draw2dgrid(posxe,posye,ange,zoome,gride);
|
|
}
|
|
|
|
faketimerhandler();
|
|
for (i=numwalls-1,wal=&wall[i];i>=0;i--,wal--)
|
|
{
|
|
if (editstatus == 0)
|
|
{
|
|
if ((show2dwall[i>>3]&pow2char[i&7]) == 0) continue;
|
|
j = wal->nextwall;
|
|
if ((j >= 0) && (i > j))
|
|
if ((show2dwall[j>>3]&pow2char[j&7]) > 0) continue;
|
|
}
|
|
else
|
|
{
|
|
j = wal->nextwall;
|
|
if ((j >= 0) && (i > j)) continue;
|
|
}
|
|
|
|
if (j < 0)
|
|
{
|
|
col = 7;
|
|
if (i == linehighlight) if (totalclock & 16) col += (2<<2);
|
|
}
|
|
else
|
|
{
|
|
col = 4;
|
|
if ((wal->cstat&1) != 0) col = 5;
|
|
if ((i == linehighlight) || ((linehighlight >= 0) && (i == wall[linehighlight].nextwall)))
|
|
if (totalclock & 16) col += (2<<2);
|
|
}
|
|
|
|
xp1 = mulscale14(wal->x-posxe,zoome);
|
|
yp1 = mulscale14(wal->y-posye,zoome);
|
|
xp2 = mulscale14(wall[wal->point2].x-posxe,zoome);
|
|
yp2 = mulscale14(wall[wal->point2].y-posye,zoome);
|
|
|
|
if ((wal->cstat&64) > 0)
|
|
{
|
|
if (klabs(xp2-xp1) >= klabs(yp2-yp1))
|
|
{
|
|
drawline16(halfxdim16+xp1,midydim16+yp1+1,halfxdim16+xp2,midydim16+yp2+1,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1-1,halfxdim16+xp2,midydim16+yp2-1,col);
|
|
}
|
|
else
|
|
{
|
|
drawline16(halfxdim16+xp1+1,midydim16+yp1,halfxdim16+xp2+1,midydim16+yp2,col);
|
|
drawline16(halfxdim16+xp1-1,midydim16+yp1,halfxdim16+xp2-1,midydim16+yp2,col);
|
|
}
|
|
col += 8;
|
|
}
|
|
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp2,midydim16+yp2,col);
|
|
if ((zoome >= 256) && (editstatus == 1))
|
|
if (((halfxdim16+xp1) >= 2) && ((halfxdim16+xp1) <= xdim-3))
|
|
if (((midydim16+yp1) >= 2) && ((midydim16+yp1) <= ydim16-3))
|
|
{
|
|
char pointsize;
|
|
col = 6;
|
|
pointsize=2;
|
|
if (i == pointhighlight || ((wall[i].x == wall[pointhighlight].x) && (wall[i].y == wall[pointhighlight].y)))
|
|
{
|
|
if (totalclock & 16)
|
|
{
|
|
col += (2<<2); // JBF 20040116: two braces is all this needed. man I'm a fool sometimes.
|
|
pointsize += 1;
|
|
}
|
|
}
|
|
else if ((highlightcnt > 0) && (editstatus == 1))
|
|
{
|
|
if (show2dwall[i>>3]&pow2char[i&7])
|
|
if (totalclock & 16)
|
|
{
|
|
col += (2<<2); // JBF 20040116: two braces is all this needed. man I'm a fool sometimes.
|
|
pointsize += 1;
|
|
}
|
|
}
|
|
|
|
templong = ((midydim16+yp1)*bytesperline)+(halfxdim16+xp1)+frameplace;
|
|
|
|
drawline16(halfxdim16+xp1-pointsize,midydim16+yp1+pointsize,halfxdim16+xp1+pointsize,midydim16+yp1+pointsize,col);
|
|
drawline16(halfxdim16+xp1+pointsize,midydim16+yp1+pointsize,halfxdim16+xp1+pointsize,midydim16+yp1-pointsize,col);
|
|
drawline16(halfxdim16+xp1+pointsize,midydim16+yp1-pointsize,halfxdim16+xp1-pointsize,midydim16+yp1-pointsize,col);
|
|
drawline16(halfxdim16+xp1-pointsize,midydim16+yp1-pointsize,halfxdim16+xp1-pointsize,midydim16+yp1+pointsize,col);
|
|
|
|
}
|
|
}
|
|
faketimerhandler();
|
|
|
|
if ((zoome >= 256) || (editstatus == 0))
|
|
for (i=0;i<numsectors;i++)
|
|
for (j=headspritesect[i];j>=0;j=nextspritesect[j])
|
|
if ((editstatus == 1) || (show2dsprite[j>>3]&pow2char[j&7]))
|
|
{
|
|
col = 3;
|
|
if (spritecol2d[sprite[j].picnum][0])
|
|
col = spritecol2d[sprite[j].picnum][0];
|
|
if ((sprite[j].cstat&1) > 0)
|
|
{
|
|
col = 5;
|
|
if (spritecol2d[sprite[j].picnum][1])
|
|
col = spritecol2d[sprite[j].picnum][1];
|
|
}
|
|
if (editstatus == 1)
|
|
{
|
|
if (j+16384 == pointhighlight || ((sprite[j].x == sprite[pointhighlight-16384].x) && (sprite[j].y == sprite[pointhighlight-16384].y))) {
|
|
if (totalclock & 32) col += (2<<2);
|
|
}
|
|
else if ((highlightcnt > 0) && (editstatus == 1))
|
|
{
|
|
if (show2dsprite[j>>3]&pow2char[j&7])
|
|
if (totalclock & 32) col += (2<<2);
|
|
}
|
|
}
|
|
|
|
xp1 = mulscale14(sprite[j].x-posxe,zoome);
|
|
yp1 = mulscale14(sprite[j].y-posye,zoome);
|
|
if (((halfxdim16+xp1) >= 4) && ((halfxdim16+xp1) <= xdim-6))
|
|
if (((midydim16+yp1) >= 4) && ((midydim16+yp1) <= ydim16-6))
|
|
{
|
|
long temp;
|
|
templong = ((midydim16+yp1)*bytesperline)+(halfxdim16+xp1)+frameplace;
|
|
|
|
|
|
for (temp=0;temp<2;temp++)
|
|
{
|
|
drawpixel((char *)(templong+3+(bytesperline*temp)), col);
|
|
drawpixel((char *)(templong-3-(bytesperline*temp)), col);
|
|
drawpixel((char *)(templong-3+(bytesperline*temp)), col);
|
|
drawpixel((char *)(templong+3-(bytesperline*temp)), col);
|
|
}
|
|
|
|
drawpixel((char *)(templong+2+(bytesperline*2)), col);
|
|
drawpixel((char *)(templong-2-(bytesperline*2)), col);
|
|
drawpixel((char *)(templong-2+(bytesperline*2)), col);
|
|
drawpixel((char *)(templong+2-(bytesperline*2)), col);
|
|
|
|
for (temp=0;temp<2;temp++)
|
|
{
|
|
drawpixel((char *)(templong+temp+(bytesperline*3)), col);
|
|
drawpixel((char *)(templong-temp-(bytesperline*3)), col);
|
|
drawpixel((char *)(templong-temp+(bytesperline*3)), col);
|
|
drawpixel((char *)(templong+temp-(bytesperline*3)), col);
|
|
}
|
|
|
|
|
|
xp2 = mulscale11(sintable[(sprite[j].ang+2560)&2047],zoome) / 768;
|
|
yp2 = mulscale11(sintable[(sprite[j].ang+2048)&2047],zoome) / 768;
|
|
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1+xp2,midydim16+yp1+yp2,col);
|
|
|
|
if ((sprite[j].cstat&256) > 0)
|
|
{
|
|
if (((sprite[j].ang+256)&512) == 0)
|
|
{
|
|
drawline16(halfxdim16+xp1,midydim16+yp1+1,halfxdim16+xp1+xp2,midydim16+yp1+yp2+1,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1-1,halfxdim16+xp1+xp2,midydim16+yp1+yp2-1,col);
|
|
drawline16(halfxdim16+xp1-1,midydim16+yp1,halfxdim16+xp1+xp2-1,midydim16+yp1+yp2,col);
|
|
drawline16(halfxdim16+xp1+1,midydim16+yp1,halfxdim16+xp1+xp2+1,midydim16+yp1+yp2,col);
|
|
|
|
}
|
|
else
|
|
{
|
|
drawline16(halfxdim16+xp1,midydim16+yp1+1,halfxdim16+xp1+xp2,midydim16+yp1+yp2+1,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1-1,halfxdim16+xp1+xp2,midydim16+yp1+yp2-1,col);
|
|
drawline16(halfxdim16+xp1-1,midydim16+yp1,halfxdim16+xp1+xp2-1,midydim16+yp1+yp2,col);
|
|
drawline16(halfxdim16+xp1+1,midydim16+yp1,halfxdim16+xp1+xp2+1,midydim16+yp1+yp2,col);
|
|
|
|
}
|
|
|
|
if ((sprite[j].cstat&32) > 0) {
|
|
long fx = mulscale6(tilesizx[sprite[j].picnum], sprite[j].xrepeat);
|
|
long fy = mulscale6(tilesizy[sprite[j].picnum], sprite[j].yrepeat);
|
|
long co[4][2], ii;
|
|
long sinang = sintable[(sprite[j].ang+512+1024)&2047];
|
|
long cosang = sintable[(sprite[j].ang+1024)&2047];
|
|
long r,s;
|
|
|
|
fx = mulscale10(fx,zoome) >> 1;
|
|
fy = mulscale10(fy,zoome) >> 1;
|
|
|
|
co[0][0] = -fx;
|
|
co[0][1] = -fy;
|
|
co[1][0] = fx;
|
|
co[1][1] = -fy;
|
|
co[2][0] = fx;
|
|
co[2][1] = fy;
|
|
co[3][0] = -fx;
|
|
co[3][1] = fy;
|
|
|
|
for (ii=0;ii<4;ii++) {
|
|
r = mulscale14(cosang,co[ii][0]) - mulscale14(sinang,co[ii][1]);
|
|
s = mulscale14(sinang,co[ii][0]) + mulscale14(cosang,co[ii][1]);
|
|
co[ii][0] = r;
|
|
co[ii][1] = s;
|
|
}
|
|
drawlinepat = 0xcfcfcfcf;
|
|
for (ii=0;ii<4;ii++)
|
|
{
|
|
drawline16(halfxdim16 + xp1 + co[ii][0], midydim16 + yp1 - co[ii][1],
|
|
halfxdim16 + xp1 + co[(ii+1)&3][0], midydim16 + yp1 - co[(ii+1)&3][1],
|
|
col);
|
|
drawline16(halfxdim16 + xp1 + co[ii][0], midydim16 + yp1 - co[ii][1] + 1,
|
|
halfxdim16 + xp1 + co[(ii+1)&3][0], midydim16 + yp1 - co[(ii+1)&3][1] + 1,
|
|
col);
|
|
drawline16(halfxdim16 + xp1 + co[ii][0], midydim16 + yp1 - co[ii][1] - 1,
|
|
halfxdim16 + xp1 + co[(ii+1)&3][0], midydim16 + yp1 - co[(ii+1)&3][1] - 1,
|
|
col);
|
|
drawline16(halfxdim16 + xp1 + co[ii][0] + 1, midydim16 + yp1 - co[ii][1],
|
|
halfxdim16 + xp1 + co[(ii+1)&3][0] + 1, midydim16 + yp1 - co[(ii+1)&3][1],
|
|
col);
|
|
drawline16(halfxdim16 + xp1 + co[ii][0] - 1, midydim16 + yp1 - co[ii][1],
|
|
halfxdim16 + xp1 + co[(ii+1)&3][0] - 1, midydim16 + yp1 - co[(ii+1)&3][1],
|
|
col);
|
|
drawline16(halfxdim16 + xp1, midydim16 + yp1,
|
|
halfxdim16 + xp1 + co[(ii+1)&3][0], midydim16 + yp1 - co[(ii+1)&3][1],
|
|
col);
|
|
}
|
|
drawlinepat = 0xffffffff;
|
|
}
|
|
|
|
else if ((sprite[j].cstat&16) > 0)
|
|
{
|
|
long fx = mulscale6(tilesizx[sprite[j].picnum], sprite[j].xrepeat);
|
|
xp2 = mulscale11(sintable[(sprite[j].ang+2560)&2047],zoome) / 6144;
|
|
yp2 = mulscale11(sintable[(sprite[j].ang+2048)&2047],zoome) / 6144;
|
|
|
|
|
|
if (((sprite[j].ang+256)&512) == 0)
|
|
{
|
|
if (!(sprite[j].cstat&64))
|
|
{
|
|
drawline16(halfxdim16+xp1,midydim16+yp1-1,halfxdim16+xp1-xp2,midydim16+yp1-yp2-1,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1-xp2,midydim16+yp1-yp2,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1+1,halfxdim16+xp1-xp2,midydim16+yp1-yp2+1,col);
|
|
}
|
|
drawline16(halfxdim16+xp1,midydim16+yp1-1,halfxdim16+xp1+xp2,midydim16+yp1+yp2-1,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1+xp2,midydim16+yp1+yp2,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1+1,halfxdim16+xp1+xp2,midydim16+yp1+yp2+1,col);
|
|
xp2 = mulscale13(sintable[(sprite[j].ang+1024)&2047],zoome) * fx / 4096;
|
|
yp2 = mulscale13(sintable[(sprite[j].ang+512)&2047],zoome) * fx / 4096;
|
|
drawline16(halfxdim16+xp1+1,midydim16+yp1,halfxdim16+xp1+xp2+1,midydim16+yp1+yp2,col);
|
|
drawline16(halfxdim16+xp1-1,midydim16+yp1,halfxdim16+xp1-xp2-1,midydim16+yp1-yp2,col);
|
|
drawline16(halfxdim16+xp1-1,midydim16+yp1,halfxdim16+xp1+xp2-1,midydim16+yp1+yp2,col);
|
|
drawline16(halfxdim16+xp1+1,midydim16+yp1,halfxdim16+xp1-xp2+1,midydim16+yp1-yp2,col);
|
|
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1-xp2,midydim16+yp1-yp2,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1+xp2,midydim16+yp1+yp2,col);
|
|
|
|
drawline16(halfxdim16+xp1,midydim16+yp1-1,halfxdim16+xp1+xp2,midydim16+yp1+yp2-1,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1+1,halfxdim16+xp1-xp2,midydim16+yp1-yp2+1,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1+1,halfxdim16+xp1+xp2,midydim16+yp1+yp2+1,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1-1,halfxdim16+xp1-xp2,midydim16+yp1-yp2-1,col);
|
|
}
|
|
else
|
|
{
|
|
if (!(sprite[j].cstat&64))
|
|
{
|
|
drawline16(halfxdim16+xp1-1,midydim16+yp1,halfxdim16+xp1-xp2-1,midydim16+yp1-yp2,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1-xp2,midydim16+yp1-yp2,col);
|
|
drawline16(halfxdim16+xp1+1,midydim16+yp1,halfxdim16+xp1-xp2+1,midydim16+yp1-yp2,col);
|
|
}
|
|
drawline16(halfxdim16+xp1-1,midydim16+yp1,halfxdim16+xp1+xp2-1,midydim16+yp1+yp2,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1+xp2,midydim16+yp1+yp2,col);
|
|
drawline16(halfxdim16+xp1+1,midydim16+yp1,halfxdim16+xp1+xp2+1,midydim16+yp1+yp2,col);
|
|
xp2 = mulscale13(sintable[(sprite[j].ang+1024)&2047],zoome) * fx / 4096;
|
|
yp2 = mulscale13(sintable[(sprite[j].ang+512)&2047],zoome) * fx / 4096;
|
|
drawline16(halfxdim16+xp1+1,midydim16+yp1,halfxdim16+xp1+xp2+1,midydim16+yp1+yp2,col);
|
|
drawline16(halfxdim16+xp1-1,midydim16+yp1,halfxdim16+xp1-xp2-1,midydim16+yp1-yp2,col);
|
|
drawline16(halfxdim16+xp1-1,midydim16+yp1,halfxdim16+xp1+xp2-1,midydim16+yp1+yp2,col);
|
|
drawline16(halfxdim16+xp1+1,midydim16+yp1,halfxdim16+xp1-xp2+1,midydim16+yp1-yp2,col);
|
|
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1-xp2,midydim16+yp1-yp2,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1+xp2,midydim16+yp1+yp2,col);
|
|
|
|
drawline16(halfxdim16+xp1,midydim16+yp1-1,halfxdim16+xp1+xp2,midydim16+yp1+yp2-1,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1+1,halfxdim16+xp1-xp2,midydim16+yp1-yp2+1,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1+1,halfxdim16+xp1+xp2,midydim16+yp1+yp2+1,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1-1,halfxdim16+xp1-xp2,midydim16+yp1-yp2-1,col);
|
|
}
|
|
|
|
}
|
|
|
|
col += 8;
|
|
}
|
|
|
|
else if ((sprite[j].cstat&16) > 0)
|
|
{
|
|
long fx = mulscale6(tilesizx[sprite[j].picnum], sprite[j].xrepeat);
|
|
|
|
xp2 = mulscale11(sintable[(sprite[j].ang+2560)&2047],zoome) / 6144;
|
|
yp2 = mulscale11(sintable[(sprite[j].ang+2048)&2047],zoome) / 6144;
|
|
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1+xp2,midydim16+yp1+yp2,col);
|
|
if (!(sprite[j].cstat&64)) drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1-xp2,midydim16+yp1-yp2,col);
|
|
xp2 = mulscale13(sintable[(sprite[j].ang+1024)&2047],zoome) * fx / 4096;
|
|
yp2 = mulscale13(sintable[(sprite[j].ang+512)&2047],zoome) * fx / 4096;
|
|
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1+xp2,midydim16+yp1+yp2,col);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+xp1-xp2,midydim16+yp1-yp2,col);
|
|
|
|
|
|
col += 8;
|
|
}
|
|
|
|
else if ((sprite[j].cstat&32) > 0)
|
|
{
|
|
long fx = mulscale6(tilesizx[sprite[j].picnum], sprite[j].xrepeat);
|
|
long fy = mulscale6(tilesizy[sprite[j].picnum], sprite[j].yrepeat);
|
|
long co[4][2], ii;
|
|
long sinang = sintable[(sprite[j].ang+512+1024)&2047];
|
|
long cosang = sintable[(sprite[j].ang+1024)&2047];
|
|
long r,s;
|
|
|
|
fx = mulscale10(fx,zoome) >> 1;
|
|
fy = mulscale10(fy,zoome) >> 1;
|
|
|
|
co[0][0] = -fx;
|
|
co[0][1] = -fy;
|
|
co[1][0] = fx;
|
|
co[1][1] = -fy;
|
|
co[2][0] = fx;
|
|
co[2][1] = fy;
|
|
co[3][0] = -fx;
|
|
co[3][1] = fy;
|
|
|
|
for (ii=0;ii<4;ii++) {
|
|
r = mulscale14(cosang,co[ii][0]) - mulscale14(sinang,co[ii][1]);
|
|
s = mulscale14(sinang,co[ii][0]) + mulscale14(cosang,co[ii][1]);
|
|
co[ii][0] = r;
|
|
co[ii][1] = s;
|
|
}
|
|
|
|
drawlinepat = 0xcfcfcfcf;
|
|
for (ii=0;ii<4;ii++) {
|
|
drawline16(halfxdim16 + xp1 + co[ii][0], midydim16 + yp1 - co[ii][1],
|
|
halfxdim16 + xp1 + co[(ii+1)&3][0], midydim16 + yp1 - co[(ii+1)&3][1],
|
|
col);
|
|
drawline16(halfxdim16 + xp1, midydim16 + yp1,
|
|
halfxdim16 + xp1 + co[(ii+1)&3][0], midydim16 + yp1 - co[(ii+1)&3][1],
|
|
col);
|
|
}
|
|
drawlinepat = 0xffffffff;
|
|
}
|
|
}
|
|
}
|
|
|
|
faketimerhandler();
|
|
xp1 = mulscale11(sintable[(ange+2560)&2047],zoome) / 768; //Draw white arrow
|
|
yp1 = mulscale11(sintable[(ange+2048)&2047],zoome) / 768;
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16-xp1,midydim16-yp1,15);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16+yp1,midydim16-xp1,15);
|
|
drawline16(halfxdim16+xp1,midydim16+yp1,halfxdim16-yp1,midydim16+xp1,15);
|
|
|
|
|
|
enddrawing(); //}}}
|
|
}
|
|
|
|
|
|
//
|
|
// printext16
|
|
//
|
|
void printext16(long xpos, long ypos, short col, short backcol, char *name, char fontsize)
|
|
{
|
|
long stx, i, x, y, charxsiz;
|
|
char *fontptr, *letptr, *ptr;
|
|
|
|
stx = xpos;
|
|
|
|
if (fontsize) { fontptr = smalltextfont; charxsiz = 4; }
|
|
else { fontptr = textfont; charxsiz = 8; }
|
|
|
|
begindrawing(); //{{{
|
|
for (i=0;name[i];i++)
|
|
{
|
|
letptr = &fontptr[name[i]<<3];
|
|
ptr = (char *)(bytesperline*(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] = (char)col;
|
|
else if (backcol >= 0)
|
|
ptr[x] = (char)backcol;
|
|
}
|
|
ptr -= bytesperline;
|
|
}
|
|
stx += charxsiz;
|
|
}
|
|
enddrawing(); //}}}
|
|
}
|
|
|
|
|
|
//
|
|
// printext256
|
|
//
|
|
void printext256(long xpos, long ypos, short col, short backcol, char *name, char fontsize)
|
|
{
|
|
long 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) {
|
|
long xx, yy;
|
|
int lc=-1;
|
|
palette_t p,b;
|
|
|
|
if (gammabrightness) {
|
|
p = curpalette[col];
|
|
b = curpalette[backcol];
|
|
} else {
|
|
p.r = britable[curbrightness][ curpalette[col].r ];
|
|
p.g = britable[curbrightness][ curpalette[col].g ];
|
|
p.b = britable[curbrightness][ curpalette[col].b ];
|
|
b.r = britable[curbrightness][ curpalette[backcol].r ];
|
|
b.g = britable[curbrightness][ curpalette[backcol].g ];
|
|
b.b = britable[curbrightness][ curpalette[backcol].b ];
|
|
}
|
|
|
|
setpolymost2dview();
|
|
bglDisable(GL_ALPHA_TEST);
|
|
bglDepthMask(GL_FALSE); // disable writing to the z-buffer
|
|
|
|
bglBegin(GL_POINTS);
|
|
|
|
for (i=0;name[i];i++) {
|
|
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++)
|
|
{
|
|
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] = (char)col;
|
|
else if (backcol >= 0)
|
|
ptr[x] = (char)backcol;
|
|
}
|
|
ptr -= ylookup[1];
|
|
}
|
|
stx += charxsiz;
|
|
}
|
|
enddrawing(); //}}}
|
|
}
|
|
|
|
|
|
//
|
|
// screencapture
|
|
//
|
|
long screencapture_tga(char *filename, char inverseit)
|
|
{
|
|
long 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, c;
|
|
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 *)kmalloc(bytesperline);
|
|
if (inversebuf) {
|
|
for (i=ydim-1; i>=0; i--) {
|
|
copybuf(ptr+i*bytesperline, inversebuf, xdim >> 2);
|
|
for (j=0; j < (bytesperline>>2); j++) ((long *)inversebuf)[j] ^= 0x0f0f0f0fL;
|
|
Bfwrite(inversebuf, xdim, 1, fil);
|
|
}
|
|
kfree(inversebuf);
|
|
}
|
|
} else {
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
if (rendmode >= 3 && qsetmode == 200) {
|
|
// 24bit
|
|
inversebuf = (char *)kmalloc(xdim*ydim*3);
|
|
if (inversebuf) {
|
|
bglReadPixels(0,0,xdim,ydim,GL_RGB,GL_UNSIGNED_BYTE,inversebuf);
|
|
j = xdim*ydim*3;
|
|
for (i=0; i<j; i+=3) {
|
|
c = inversebuf[i];
|
|
inversebuf[i] = inversebuf[i+2];
|
|
inversebuf[i+2] = c;
|
|
}
|
|
Bfwrite(inversebuf, xdim*ydim, 3, fil);
|
|
kfree(inversebuf);
|
|
}
|
|
} else {
|
|
#endif
|
|
for (i=ydim-1; 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 int writepcxbyte(char colour, unsigned 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, long bytes, long step, BFILE *fp)
|
|
{
|
|
char ths, last;
|
|
int srcIndex, i;
|
|
unsigned char runCount;
|
|
|
|
runCount = 1;
|
|
last = *buf;
|
|
|
|
for (srcIndex=1; srcIndex<bytes; srcIndex++) {
|
|
buf += step;
|
|
ths = *buf;
|
|
if (ths == last) {
|
|
runCount++;
|
|
if (runCount == 63) {
|
|
writepcxbyte(last, runCount, fp);
|
|
runCount = 0;
|
|
}
|
|
} else {
|
|
if (runCount)
|
|
writepcxbyte(last, runCount, fp);
|
|
last = ths;
|
|
runCount = 1;
|
|
}
|
|
}
|
|
|
|
if (runCount) writepcxbyte(last, runCount, fp);
|
|
if (bytes&1) writepcxbyte(0, 1, fp);
|
|
}
|
|
|
|
long screencapture_pcx(char *filename, char inverseit)
|
|
{
|
|
long i,j,bpl;
|
|
char *ptr, head[128];
|
|
//char palette[4*256];
|
|
char *fn = Bstrdup(filename), *inversebuf, c;
|
|
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++] = '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 *)kmalloc(bytesperline);
|
|
if (inversebuf) {
|
|
for (i=0; i<ydim; i++) {
|
|
copybuf(ptr+i*bytesperline, inversebuf, xdim >> 2);
|
|
for (j=0; j < (bytesperline>>2); j++) ((long *)inversebuf)[j] ^= 0x0f0f0f0fL;
|
|
writepcxline(inversebuf, xdim, 1, fil);
|
|
}
|
|
kfree(inversebuf);
|
|
}
|
|
} else {
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
if (rendmode >= 3 && qsetmode == 200) {
|
|
// 24bit
|
|
inversebuf = (char *)kmalloc(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);
|
|
}
|
|
kfree(inversebuf);
|
|
}
|
|
} else {
|
|
#endif
|
|
for (i=0; i<ydim; i++)
|
|
writepcxline(ptr+i*bytesperline, xdim, 1, fil);
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
enddrawing(); //}}}
|
|
|
|
// palette last
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
if (rendmode < 3 || (rendmode >= 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);
|
|
}
|
|
|
|
long screencapture(char *filename, char inverseit)
|
|
{
|
|
if (captureformat == 0) return screencapture_tga(filename,inverseit);
|
|
else return screencapture_pcx(filename,inverseit);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// setrendermode
|
|
//
|
|
int setrendermode(int renderer)
|
|
{
|
|
#ifdef POLYMOST
|
|
int method;
|
|
|
|
if (bpp == 8) {
|
|
if (renderer < 0) renderer = 0;
|
|
else if (renderer > 2) renderer = 2;
|
|
} else {
|
|
if (renderer < 3) renderer = 3;
|
|
else if (renderer > 4) renderer = 4;
|
|
}
|
|
|
|
if (renderer == 4)
|
|
polymer_init();
|
|
|
|
rendmode = renderer;
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// getrendermode
|
|
//
|
|
int getrendermode(void)
|
|
{
|
|
#ifndef POLYMOST
|
|
return 0;
|
|
#else
|
|
return rendmode;
|
|
#endif
|
|
}
|
|
|
|
|
|
//
|
|
// setrollangle
|
|
//
|
|
void setrollangle(long rolla)
|
|
{
|
|
#ifdef POLYMOST
|
|
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(short tilenume, long pal, long how)
|
|
{
|
|
#if defined(POLYMOST) && defined(USE_OPENGL)
|
|
int numpal, firstpal, np;
|
|
int 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
|
|
}
|
|
|
|
|
|
//
|
|
// 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
|
|
}
|
|
|
|
|
|
/*
|
|
* vim:ts=8:
|
|
*/
|
|
|