2006-04-13 20:47:06 +00:00
|
|
|
// "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
|
2012-03-12 04:47:04 +00:00
|
|
|
// by Jonathon Fowler (jf@jonof.id.au)
|
2018-11-05 07:28:01 +00:00
|
|
|
// by the EDuke32 team (development@voidpoint.com)
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-11-18 18:09:48 +00:00
|
|
|
#define engine_c_
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-11-18 18:09:48 +00:00
|
|
|
#include "a.h"
|
|
|
|
#include "baselayer.h"
|
2006-04-13 20:47:06 +00:00
|
|
|
#include "build.h"
|
|
|
|
#include "cache1d.h"
|
2018-11-18 18:09:48 +00:00
|
|
|
#include "colmatch.h"
|
2019-09-19 21:02:57 +00:00
|
|
|
#include "common.h"
|
2018-11-18 18:09:48 +00:00
|
|
|
#include "compat.h"
|
2019-09-22 21:15:46 +00:00
|
|
|
#include "crc32_.h"
|
2018-11-18 18:09:48 +00:00
|
|
|
#include "engine_priv.h"
|
2014-02-10 10:55:49 +00:00
|
|
|
#include "lz4.h"
|
2018-11-18 18:09:48 +00:00
|
|
|
#include "osd.h"
|
|
|
|
#include "palette.h"
|
|
|
|
#include "pragmas.h"
|
2008-11-25 13:06:36 +00:00
|
|
|
#include "scriptfile.h"
|
2018-07-14 21:36:44 +00:00
|
|
|
#include "softsurface.h"
|
2018-11-18 18:09:48 +00:00
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-02-16 06:38:21 +00:00
|
|
|
# include "glad/glad.h"
|
2018-06-13 19:15:16 +00:00
|
|
|
# include "glsurface.h"
|
2018-11-18 18:09:48 +00:00
|
|
|
# include "hightile.h"
|
2011-10-02 07:18:17 +00:00
|
|
|
# include "mdsprite.h"
|
2008-12-02 10:44:39 +00:00
|
|
|
# include "polymost.h"
|
2019-10-04 16:12:03 +00:00
|
|
|
#include "../../glbackend/glbackend.h"
|
2008-05-10 01:29:37 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-05-06 19:43:34 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
#include "vfs.h"
|
|
|
|
|
2015-02-07 17:29:10 +00:00
|
|
|
//////////
|
|
|
|
// Compilation switches for optional/extended engine features
|
|
|
|
|
2014-09-30 04:06:32 +00:00
|
|
|
#if !defined(__arm__) && !defined(GEKKO)
|
2015-02-07 17:29:10 +00:00
|
|
|
# define HIGH_PRECISION_SPRITE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined EDUKE32_TOUCH_DEVICES && !defined GEKKO && !defined __OPENDINGUX__
|
|
|
|
// Handle absolute z difference of floor/ceiling to camera >= 1<<24.
|
2015-02-19 17:41:53 +00:00
|
|
|
// Also: higher precision view-relative x and y for drawvox().
|
2015-02-07 17:29:10 +00:00
|
|
|
# define CLASSIC_Z_DIFF_64
|
2014-09-30 04:06:32 +00:00
|
|
|
#endif
|
|
|
|
|
2012-12-23 13:59:56 +00:00
|
|
|
#define MULTI_COLUMN_VLINE
|
2012-12-23 13:59:52 +00:00
|
|
|
//#define DEBUG_TILESIZY_512
|
2013-05-16 21:54:55 +00:00
|
|
|
//#define DEBUG_TILEOFFSETS
|
2015-02-07 17:29:10 +00:00
|
|
|
//////////
|
2012-12-23 13:59:52 +00:00
|
|
|
|
2013-07-04 19:38:53 +00:00
|
|
|
#ifdef LUNATIC
|
|
|
|
# if !defined DEBUG_MAIN_ARRAYS
|
|
|
|
LUNATIC_EXTERN const int32_t engine_main_arrays_are_static = 0; // for Lunatic
|
|
|
|
# else
|
|
|
|
LUNATIC_EXTERN const int32_t engine_main_arrays_are_static = 1;
|
|
|
|
# endif
|
Inreased debugging level for catching oob accesses to 'main' arrays.
If enabled, this makes the following arrays be allocated statically:
spriteext, spritesmooth, sector, wall, sprite, tsprite, while
necessarily disabling the clipshape feature (because it relies on
setting sector/wall to different malloc'd block temporarily).
To compile, pass DEBUGANYWAY=1 in addition to RELEASE=0 to 'make',
and it's really only useful with CC=clang, of course.
git-svn-id: https://svn.eduke32.com/eduke32@2270 1a8010ca-5511-0410-912e-c29ae57300e0
2012-01-19 23:17:34 +00:00
|
|
|
|
2012-05-18 12:45:52 +00:00
|
|
|
#if MAXSECTORS==MAXSECTORSV8
|
2013-07-04 19:38:53 +00:00
|
|
|
LUNATIC_EXTERN const int32_t engine_v8 = 1;
|
2012-05-18 12:45:52 +00:00
|
|
|
#else
|
2013-07-04 19:38:53 +00:00
|
|
|
LUNATIC_EXTERN const int32_t engine_v8 = 0;
|
2012-05-18 12:45:52 +00:00
|
|
|
#endif
|
2014-02-10 10:55:13 +00:00
|
|
|
#endif
|
2012-05-18 12:45:52 +00:00
|
|
|
|
2012-12-31 01:50:45 +00:00
|
|
|
#ifdef DEBUGGINGAIDS
|
2010-08-26 15:24:12 +00:00
|
|
|
float debug1, debug2;
|
2012-12-31 01:50:45 +00:00
|
|
|
#endif
|
2010-08-26 15:24:12 +00:00
|
|
|
|
2013-06-01 20:09:39 +00:00
|
|
|
int32_t mapversion=7; // JBF 20040211: default mapversion to 7
|
2013-06-28 14:07:44 +00:00
|
|
|
int32_t g_loadedMapVersion = -1; // -1: none (e.g. started new)
|
2013-06-01 20:09:39 +00:00
|
|
|
|
|
|
|
static int32_t get_mapversion(void);
|
|
|
|
|
2013-07-04 19:38:37 +00:00
|
|
|
// Handle nonpow2-ysize walls the old way?
|
2019-04-18 17:25:38 +00:00
|
|
|
static FORCE_INLINE int32_t oldnonpow2(void)
|
2013-06-01 20:09:39 +00:00
|
|
|
{
|
|
|
|
#if !defined CLASSIC_NONPOW2_YSIZE_WALLS
|
|
|
|
return 1;
|
|
|
|
#else
|
2013-07-04 19:38:37 +00:00
|
|
|
return (g_loadedMapVersion < 10);
|
2013-06-01 20:09:39 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-02-15 03:49:23 +00:00
|
|
|
uint8_t globalr = 255, globalg = 255, globalb = 255;
|
|
|
|
|
2015-05-19 22:05:20 +00:00
|
|
|
int16_t pskybits_override = -1;
|
|
|
|
|
2019-09-19 20:02:45 +00:00
|
|
|
void (*loadvoxel_replace)(int32_t voxindex) = NULL;
|
2012-01-19 21:57:46 +00:00
|
|
|
int16_t tiletovox[MAXTILES];
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t usevoxels = 1;
|
2014-12-26 17:29:53 +00:00
|
|
|
#ifdef USE_OPENGL
|
2019-08-13 02:53:38 +00:00
|
|
|
static char *voxfilenames[MAXVOXELS];
|
2014-12-26 17:29:53 +00:00
|
|
|
#endif
|
2019-08-13 02:53:38 +00:00
|
|
|
char g_haveVoxels;
|
2011-10-17 18:42:10 +00:00
|
|
|
//#define kloadvoxel loadvoxel
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-06-18 13:02:08 +00:00
|
|
|
int32_t novoxmips = 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//These variables need to be copied into BUILD
|
2006-04-13 20:47:06 +00:00
|
|
|
#define MAXXSIZ 256
|
|
|
|
#define MAXYSIZ 256
|
|
|
|
#define MAXZSIZ 255
|
2015-01-06 19:56:44 +00:00
|
|
|
#ifdef EDUKE32_TOUCH_DEVICES
|
|
|
|
# define DISTRECIPSIZ (65536+256)
|
|
|
|
#else
|
|
|
|
# define DISTRECIPSIZ 131072
|
|
|
|
#endif
|
2019-09-22 21:15:46 +00:00
|
|
|
static uint8_t voxlock[MAXVOXELS][MAXVOXMIPS];
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t voxscale[MAXVOXELS];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t ggxinc[MAXXSIZ+1], ggyinc[MAXXSIZ+1];
|
2014-10-25 03:29:21 +00:00
|
|
|
static int32_t lowrecip[1024], nytooclose;
|
2015-01-06 19:56:44 +00:00
|
|
|
static const int32_t nytoofar = DISTRECIPSIZ*16384ull - 1048576;
|
2014-10-29 17:04:28 +00:00
|
|
|
static uint32_t *distrecip;
|
2019-08-01 06:50:26 +00:00
|
|
|
#define DISTRECIPCACHESIZE 3
|
|
|
|
static struct {
|
|
|
|
uint32_t *distrecip;
|
|
|
|
int32_t xdimen;
|
|
|
|
int32_t age;
|
|
|
|
} distrecipcache[DISTRECIPCACHESIZE];
|
|
|
|
static int32_t distrecipagecnt = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-05-26 21:58:31 +00:00
|
|
|
static int32_t *lookups = NULL;
|
2017-06-23 03:58:36 +00:00
|
|
|
static int32_t beforedrawrooms = 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-06-25 18:34:52 +00:00
|
|
|
int32_t benchmarkScreenshot = 0;
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t oxdimen = -1, oviewingrange = -1, oxyaspect = -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2010-10-17 14:49:39 +00:00
|
|
|
// r_usenewaspect is the cvar, newaspect_enable to trigger the new behaviour in the code
|
2011-08-06 11:50:45 +00:00
|
|
|
int32_t r_usenewaspect = 1, newaspect_enable=0;
|
2012-08-24 18:51:49 +00:00
|
|
|
uint32_t r_screenxy = 0;
|
2010-10-17 14:49:39 +00:00
|
|
|
|
2019-07-06 16:30:18 +00:00
|
|
|
int32_t r_fpgrouscan = 1;
|
2019-08-29 20:06:31 +00:00
|
|
|
int32_t r_displayindex = 0;
|
|
|
|
int32_t r_borderless = 2;
|
2015-03-09 20:32:36 +00:00
|
|
|
int32_t globalflags;
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
float g_videoGamma = DEFAULT_GAMMA;
|
|
|
|
float g_videoContrast = DEFAULT_CONTRAST;
|
|
|
|
float g_videoBrightness = DEFAULT_BRIGHTNESS;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Textured Map variables
|
2006-04-13 20:47:06 +00:00
|
|
|
static char globalpolytype;
|
2014-10-29 17:04:28 +00:00
|
|
|
static int16_t **dotp1, **dotp2;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
static int8_t tempbuf[MAXWALLS];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-11-15 14:28:11 +00:00
|
|
|
// referenced from asm
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t ebpbak, espbak;
|
2012-11-15 14:28:11 +00:00
|
|
|
int32_t reciptable[2048], fpuasm;
|
|
|
|
intptr_t asm1, asm2, asm3, asm4, palookupoffse[4];
|
|
|
|
uint32_t vplce[4];
|
|
|
|
int32_t vince[4];
|
|
|
|
intptr_t bufplce[4];
|
|
|
|
int32_t globaltilesizy;
|
|
|
|
int32_t globalx1, globaly2, globalx3, globaly3;
|
|
|
|
|
2019-06-25 11:30:03 +00:00
|
|
|
int32_t sloptable[SLOPTABLESIZ];
|
2011-08-17 18:52:54 +00:00
|
|
|
static intptr_t slopalookup[16384]; // was 2048
|
2014-12-13 22:33:04 +00:00
|
|
|
|
2012-09-02 14:10:55 +00:00
|
|
|
static int32_t no_radarang2 = 0;
|
2019-06-25 11:29:42 +00:00
|
|
|
static int16_t radarang[1280];
|
|
|
|
static int32_t qradarang[10240], *radarang2;
|
2018-11-18 18:05:26 +00:00
|
|
|
const char ATTRIBUTE((used)) pow2char_[8] = {1,2,4,8,16,32,64,128};
|
2012-11-05 02:49:08 +00:00
|
|
|
|
2019-09-22 19:26:07 +00:00
|
|
|
uint16_t ATTRIBUTE((used)) sqrtable[4096], ATTRIBUTE((used)) shlookup[4096+256], ATTRIBUTE((used)) sqrtable_old[2048];
|
2012-11-05 02:49:08 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
char britable[16][256]; // JBF 20040207: full 8bit precision
|
2008-12-02 10:44:39 +00:00
|
|
|
|
|
|
|
extern char textfont[2048], smalltextfont[2048];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
static char kensmessage[128];
|
2011-02-21 23:08:21 +00:00
|
|
|
const char *engineerrstr = "No error";
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-11-18 01:17:56 +00:00
|
|
|
int32_t showfirstwall=0;
|
2013-08-12 15:18:05 +00:00
|
|
|
int32_t showheightindicators=1;
|
2009-11-18 01:17:56 +00:00
|
|
|
int32_t circlewall=-1;
|
|
|
|
|
2018-04-12 21:04:00 +00:00
|
|
|
static void classicScanSector(int16_t startsectnum);
|
2012-03-22 22:46:23 +00:00
|
|
|
static void draw_rainbow_background(void);
|
2011-04-28 21:28:33 +00:00
|
|
|
|
2011-03-13 11:59:32 +00:00
|
|
|
int16_t editstatus = 0;
|
2018-03-07 04:21:05 +00:00
|
|
|
static fix16_t global100horiz; // (-100..300)-scale horiz (the one passed to drawrooms)
|
2011-03-13 11:59:32 +00:00
|
|
|
|
2019-09-19 21:02:57 +00:00
|
|
|
int32_t(*getpalookup_replace)(int32_t davis, int32_t dashade) = NULL;
|
|
|
|
|
|
|
|
int32_t bloodhack = 0;
|
|
|
|
|
2019-04-18 17:24:30 +00:00
|
|
|
// adapted from build.c
|
2019-08-27 06:52:42 +00:00
|
|
|
static void getclosestpointonwall_internal(vec2_t const p, int32_t const dawall, vec2_t *const closest)
|
2019-04-18 17:24:30 +00:00
|
|
|
{
|
2019-06-25 11:28:25 +00:00
|
|
|
vec2_t const w = wall[dawall].pos;
|
|
|
|
vec2_t const w2 = wall[wall[dawall].point2].pos;
|
2019-04-18 17:24:30 +00:00
|
|
|
vec2_t const d = { w2.x - w.x, w2.y - w.y };
|
|
|
|
|
|
|
|
int64_t i = d.x * ((int64_t)p.x - w.x) + d.y * ((int64_t)p.y - w.y);
|
|
|
|
|
|
|
|
if (i <= 0)
|
|
|
|
{
|
|
|
|
*closest = w;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t const j = (int64_t)d.x * d.x + (int64_t)d.y * d.y;
|
|
|
|
|
|
|
|
if (i >= j)
|
|
|
|
{
|
|
|
|
*closest = w2;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = tabledivide64((i << 15), j) << 15;
|
|
|
|
|
|
|
|
*closest = { (int32_t)(w.x + ((d.x * i) >> 30)), (int32_t)(w.y + ((d.y * i) >> 30)) };
|
|
|
|
}
|
2011-03-02 21:21:47 +00:00
|
|
|
|
|
|
|
////////// YAX //////////
|
|
|
|
|
2011-05-29 12:30:38 +00:00
|
|
|
int32_t numgraysects = 0;
|
2019-04-18 17:24:43 +00:00
|
|
|
uint8_t graysectbitmap[(MAXSECTORS+7)>>3];
|
|
|
|
uint8_t graywallbitmap[(MAXWALLS+7)>>3];
|
2011-07-04 21:20:59 +00:00
|
|
|
int32_t autogray = 0, showinnergray = 1;
|
2011-05-07 18:23:34 +00:00
|
|
|
|
2012-06-05 22:21:26 +00:00
|
|
|
//#define YAX_DEBUG_YMOSTS
|
|
|
|
|
2011-09-15 17:05:00 +00:00
|
|
|
#ifdef YAX_DEBUG
|
2013-07-07 20:59:05 +00:00
|
|
|
// XXX: This could be replaced with the use of gethiticks().
|
2013-07-07 20:59:00 +00:00
|
|
|
double u64tickspersec;
|
2011-09-15 17:05:00 +00:00
|
|
|
#endif
|
2011-05-07 18:23:34 +00:00
|
|
|
#ifdef ENGINE_SCREENSHOT_DEBUG
|
|
|
|
int32_t engine_screenshot = 0;
|
|
|
|
#endif
|
|
|
|
|
2019-09-21 20:53:00 +00:00
|
|
|
void faketimerhandler()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-03-29 15:59:14 +00:00
|
|
|
int32_t get_alwaysshowgray(void)
|
|
|
|
{
|
|
|
|
return showinnergray || !(editorzrange[0]==INT32_MIN && editorzrange[1]==INT32_MAX);
|
|
|
|
}
|
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
void yax_updategrays(int32_t posze)
|
|
|
|
{
|
2015-10-31 19:35:25 +00:00
|
|
|
int32_t i, j;
|
2011-05-18 22:44:09 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
int32_t mingoodz=INT32_MAX, maxgoodz=INT32_MIN;
|
|
|
|
#else
|
2011-05-07 18:23:34 +00:00
|
|
|
UNREFERENCED_PARAMETER(posze);
|
|
|
|
#endif
|
2011-05-18 22:44:09 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
Bmemset(graysectbitmap, 0, sizeof(graysectbitmap));
|
|
|
|
Bmemset(graywallbitmap, 0, sizeof(graywallbitmap));
|
|
|
|
|
|
|
|
for (i=0; i<numsectors; i++)
|
|
|
|
{
|
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
int16_t cb, fb;
|
|
|
|
yax_getbunches(i, &cb, &fb);
|
2015-10-31 19:35:25 +00:00
|
|
|
|
|
|
|
// Update grayouts due to TROR, has to be --v-- half-open --v--
|
|
|
|
// because only one level should ever be v v
|
|
|
|
// active. v v
|
|
|
|
int32_t keep = ((cb<0 || sector[i].ceilingz < posze) && (fb<0 || posze <= sector[i].floorz));
|
2011-05-18 22:44:09 +00:00
|
|
|
if (autogray && (cb>=0 || fb>=0) && (sector[i].ceilingz <= posze && posze <= sector[i].floorz))
|
|
|
|
{
|
2018-10-16 06:09:54 +00:00
|
|
|
mingoodz = min(mingoodz, TrackerCast(sector[i].ceilingz));
|
|
|
|
maxgoodz = max(maxgoodz, TrackerCast(sector[i].floorz));
|
2011-05-18 22:44:09 +00:00
|
|
|
}
|
2011-05-07 18:23:34 +00:00
|
|
|
#endif
|
2011-05-15 22:37:24 +00:00
|
|
|
// update grayouts due to editorzrange
|
2015-10-31 19:35:25 +00:00
|
|
|
keep &= (sector[i].ceilingz >= editorzrange[0] && sector[i].floorz <= editorzrange[1]);
|
2011-05-07 18:23:34 +00:00
|
|
|
|
2015-10-31 19:35:25 +00:00
|
|
|
if (!keep) // outside bounds, gray out!
|
2019-08-04 02:51:50 +00:00
|
|
|
graysectbitmap[i>>3] |= pow2char[i&7];
|
2011-05-18 22:44:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (autogray && mingoodz<=maxgoodz)
|
|
|
|
{
|
|
|
|
for (i=0; i<numsectors; i++)
|
|
|
|
if (!(mingoodz <= sector[i].ceilingz && sector[i].floorz <= maxgoodz))
|
2019-08-04 02:51:50 +00:00
|
|
|
graysectbitmap[i>>3] |= pow2char[i&7];
|
2011-05-18 22:44:09 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-05-29 12:30:38 +00:00
|
|
|
numgraysects = 0;
|
2011-05-18 22:44:09 +00:00
|
|
|
for (i=0; i<numsectors; i++)
|
|
|
|
{
|
2019-08-04 02:51:50 +00:00
|
|
|
if (graysectbitmap[i>>3]&pow2char[i&7])
|
2011-05-29 12:30:38 +00:00
|
|
|
{
|
|
|
|
numgraysects++;
|
2011-05-07 18:23:34 +00:00
|
|
|
for (j=sector[i].wallptr; j<sector[i].wallptr+sector[i].wallnum; j++)
|
2019-08-04 02:51:50 +00:00
|
|
|
graywallbitmap[j>>3] |= pow2char[j&7];
|
2011-05-29 12:30:38 +00:00
|
|
|
}
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-25 15:33:02 +00:00
|
|
|
#if !defined YAX_ENABLE
|
|
|
|
# warning Non-TROR builds are supported only for debugging. Expect savegame breakage etc...
|
|
|
|
#endif
|
|
|
|
|
2011-03-13 11:59:32 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
// all references to floor/ceiling bunchnums should be through the
|
|
|
|
// get/set functions!
|
|
|
|
|
2011-09-04 19:44:07 +00:00
|
|
|
int32_t g_nodraw = 0;
|
2011-05-22 21:52:22 +00:00
|
|
|
int32_t scansector_retfast = 0;
|
2019-03-19 17:07:53 +00:00
|
|
|
int32_t scansector_collectsprites = 1;
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
int32_t yax_globalcf = -1, yax_nomaskpass=0, yax_nomaskdidit; // engine internal
|
|
|
|
int32_t r_tror_nomaskpass = 1; // cvar
|
2011-09-15 17:02:12 +00:00
|
|
|
int32_t yax_globallev = YAX_MAXDRAWS;
|
|
|
|
int32_t yax_globalbunch = -1;
|
2019-03-19 17:07:53 +00:00
|
|
|
int32_t yax_polymostclearzbuffer = 1;
|
2011-05-07 18:23:34 +00:00
|
|
|
|
|
|
|
// duplicated tsprites
|
|
|
|
// [i]:
|
|
|
|
// i==MAXDRAWS: base level
|
|
|
|
// i<MAXDRAWS: MAXDRAWS-i-1 is level towards ceiling
|
|
|
|
// i>MAXDRAWS: i-MAXDRAWS-1 is level towards floor
|
|
|
|
static int16_t yax_spritesortcnt[1 + 2*YAX_MAXDRAWS];
|
2011-09-28 20:30:41 +00:00
|
|
|
static uint16_t yax_tsprite[1 + 2*YAX_MAXDRAWS][MAXSPRITESONSCREEN];
|
|
|
|
static uint8_t yax_tsprfrombunch[1 + 2*YAX_MAXDRAWS][MAXSPRITESONSCREEN];
|
2011-04-28 21:28:33 +00:00
|
|
|
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
// drawn sectors
|
2019-04-18 17:24:43 +00:00
|
|
|
uint8_t yax_gotsector[(MAXSECTORS+7)>>3]; // engine internal
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
|
2013-04-09 17:35:11 +00:00
|
|
|
# if !defined NEW_MAP_FORMAT
|
|
|
|
// Game-time YAX data structures, V7-V9 map formats.
|
2011-05-12 23:31:13 +00:00
|
|
|
int16_t yax_bunchnum[MAXSECTORS][2];
|
|
|
|
int16_t yax_nextwall[MAXWALLS][2];
|
2011-04-11 22:28:58 +00:00
|
|
|
|
2017-02-25 08:15:53 +00:00
|
|
|
static FORCE_INLINE int32_t yax_islockededge(int32_t line, int32_t cf)
|
2011-04-11 22:28:58 +00:00
|
|
|
{
|
|
|
|
return !!(wall[line].cstat&(YAX_NEXTWALLBIT(cf)));
|
|
|
|
}
|
2011-03-13 11:59:32 +00:00
|
|
|
|
2012-02-16 19:25:18 +00:00
|
|
|
#define YAX_PTRBUNCHNUM(Ptr, Sect, Cf) (*(&Ptr[Sect].ceilingxpanning + 8*Cf))
|
|
|
|
#define YAX_BUNCHNUM(Sect, Cf) YAX_PTRBUNCHNUM(sector, Sect, Cf)
|
2011-04-11 22:28:58 +00:00
|
|
|
|
|
|
|
//// bunch getters/setters
|
2011-03-02 21:21:47 +00:00
|
|
|
int16_t yax_getbunch(int16_t i, int16_t cf)
|
|
|
|
{
|
2011-03-13 11:59:32 +00:00
|
|
|
if (editstatus==0)
|
|
|
|
return yax_bunchnum[i][cf];
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
return (*(§or[i].ceilingstat + cf) & YAX_BIT) ? YAX_BUNCHNUM(i, cf) : -1;
|
2011-03-02 21:21:47 +00:00
|
|
|
}
|
2013-04-09 17:35:11 +00:00
|
|
|
# else
|
|
|
|
# define YAX_PTRBUNCHNUM(Ptr, Sect, Cf) (*((Cf) ? &(Ptr)[Sect].floorbunch : &(Ptr)[Sect].ceilingbunch))
|
|
|
|
# define YAX_BUNCHNUM(Sect, Cf) YAX_PTRBUNCHNUM(sector, Sect, Cf)
|
|
|
|
|
|
|
|
# if !defined NEW_MAP_FORMAT
|
2017-02-25 08:15:53 +00:00
|
|
|
static FORCE_INLINE int32_t yax_islockededge(int32_t line, int32_t cf)
|
2013-04-09 17:35:11 +00:00
|
|
|
{
|
|
|
|
return (yax_getnextwall(line, cf) >= 0);
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
# endif
|
2011-03-13 11:59:32 +00:00
|
|
|
|
2011-11-26 22:39:50 +00:00
|
|
|
// bunchnum: -1: also clear yax-nextwalls (forward and reverse)
|
|
|
|
// -2: don't clear reverse yax-nextwalls
|
|
|
|
// -3: don't clear either forward or reverse yax-nextwalls
|
2011-03-02 21:21:47 +00:00
|
|
|
void yax_setbunch(int16_t i, int16_t cf, int16_t bunchnum)
|
|
|
|
{
|
2011-03-13 11:59:32 +00:00
|
|
|
if (editstatus==0)
|
2011-04-11 22:28:58 +00:00
|
|
|
{
|
2013-04-09 17:35:11 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
YAX_BUNCHNUM(i, cf) = bunchnum;
|
|
|
|
#else
|
2011-03-13 11:59:32 +00:00
|
|
|
yax_bunchnum[i][cf] = bunchnum;
|
2013-04-09 17:35:11 +00:00
|
|
|
#endif
|
2011-04-11 22:28:58 +00:00
|
|
|
return;
|
|
|
|
}
|
2011-03-13 11:59:32 +00:00
|
|
|
|
2011-11-26 22:39:50 +00:00
|
|
|
if (bunchnum < 0)
|
2011-03-02 21:21:47 +00:00
|
|
|
{
|
2011-11-26 22:39:50 +00:00
|
|
|
if (bunchnum > -3)
|
2011-04-22 22:48:06 +00:00
|
|
|
{
|
2011-11-26 22:39:50 +00:00
|
|
|
// TODO: for in-game too?
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t ynw, j=sector[i].wallptr; j<sector[i].wallptr+sector[i].wallnum; j++)
|
2011-05-22 21:52:22 +00:00
|
|
|
{
|
2011-11-26 22:39:50 +00:00
|
|
|
ynw = yax_getnextwall(j, cf);
|
|
|
|
if (ynw >= 0)
|
|
|
|
{
|
|
|
|
if (bunchnum > -2)
|
|
|
|
yax_setnextwall(ynw, !cf, -1);
|
|
|
|
yax_setnextwall(j, cf, -1);
|
|
|
|
}
|
2011-05-22 21:52:22 +00:00
|
|
|
}
|
2011-04-22 22:48:06 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 17:35:11 +00:00
|
|
|
#if !defined NEW_MAP_FORMAT
|
2011-03-02 21:21:47 +00:00
|
|
|
*(§or[i].ceilingstat + cf) &= ~YAX_BIT;
|
2014-01-28 19:03:47 +00:00
|
|
|
// NOTE: Don't reset xpanning-as-index, since we can be called from
|
|
|
|
// e.g. Mapster32's "Inner loop made into new sector" functionality.
|
|
|
|
// YAX_BUNCHNUM(i, cf) = 0;
|
2013-06-01 20:09:39 +00:00
|
|
|
#else
|
|
|
|
YAX_BUNCHNUM(i, cf) = -1;
|
|
|
|
#endif
|
2011-03-02 21:21:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-04-09 17:35:11 +00:00
|
|
|
#if !defined NEW_MAP_FORMAT
|
2011-03-02 21:21:47 +00:00
|
|
|
*(§or[i].ceilingstat + cf) |= YAX_BIT;
|
2013-04-09 17:35:11 +00:00
|
|
|
#endif
|
2011-03-02 21:21:47 +00:00
|
|
|
YAX_BUNCHNUM(i, cf) = bunchnum;
|
|
|
|
}
|
|
|
|
|
2011-03-13 11:59:32 +00:00
|
|
|
void yax_setbunches(int16_t i, int16_t cb, int16_t fb)
|
|
|
|
{
|
|
|
|
yax_setbunch(i, YAX_CEILING, cb);
|
|
|
|
yax_setbunch(i, YAX_FLOOR, fb);
|
|
|
|
}
|
|
|
|
|
2013-04-09 17:35:11 +00:00
|
|
|
# if !defined NEW_MAP_FORMAT
|
2011-04-11 22:28:58 +00:00
|
|
|
//// nextwall getters/setters
|
|
|
|
int16_t yax_getnextwall(int16_t wal, int16_t cf)
|
|
|
|
{
|
|
|
|
if (editstatus==0)
|
|
|
|
return yax_nextwall[wal][cf];
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
return yax_islockededge(wal, cf) ? YAX_NEXTWALL(wal, cf) : -1;
|
2011-04-11 22:28:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// unchecked!
|
|
|
|
void yax_setnextwall(int16_t wal, int16_t cf, int16_t thenextwall)
|
|
|
|
{
|
|
|
|
if (editstatus==0)
|
|
|
|
{
|
|
|
|
yax_nextwall[wal][cf] = thenextwall;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (thenextwall >= 0)
|
2011-04-14 20:48:08 +00:00
|
|
|
{
|
2011-04-11 22:28:58 +00:00
|
|
|
wall[wal].cstat |= YAX_NEXTWALLBIT(cf);
|
2011-04-14 20:48:08 +00:00
|
|
|
YAX_NEXTWALL(wal, cf) = thenextwall;
|
|
|
|
}
|
2011-04-11 22:28:58 +00:00
|
|
|
else
|
2011-04-14 20:48:08 +00:00
|
|
|
{
|
2011-04-11 22:28:58 +00:00
|
|
|
wall[wal].cstat &= ~YAX_NEXTWALLBIT(cf);
|
2012-08-26 22:10:40 +00:00
|
|
|
YAX_NEXTWALL(wal, cf) = YAX_NEXTWALLDEFAULT(cf);
|
2011-04-14 20:48:08 +00:00
|
|
|
}
|
2011-04-11 22:28:58 +00:00
|
|
|
}
|
2013-04-09 17:35:11 +00:00
|
|
|
# endif
|
2011-04-11 22:28:58 +00:00
|
|
|
|
2011-09-15 17:02:12 +00:00
|
|
|
// make one step in the vertical direction, and if the wall we arrive at
|
|
|
|
// is red, return its nextsector.
|
|
|
|
int16_t yax_vnextsec(int16_t line, int16_t cf)
|
|
|
|
{
|
2015-02-11 05:21:53 +00:00
|
|
|
int16_t const ynw = yax_getnextwall(line, cf);
|
|
|
|
return (ynw < 0) ? -1 : wall[ynw].nextsector;
|
2011-09-15 17:02:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
//// in-struct --> array transfer (only resetstat==0); list construction
|
2011-05-12 23:31:13 +00:00
|
|
|
// resetstat: 0: reset and read data from structs and construct linked lists etc.
|
|
|
|
// 1: only reset
|
|
|
|
// 2: read data from game-time arrays and construct linked lists etc.
|
|
|
|
void yax_update(int32_t resetstat)
|
2011-03-23 17:41:01 +00:00
|
|
|
{
|
2013-04-09 17:35:11 +00:00
|
|
|
int32_t i;
|
|
|
|
#if !defined NEW_MAP_FORMAT
|
|
|
|
int32_t j;
|
|
|
|
const int32_t oeditstatus=editstatus;
|
|
|
|
#endif
|
|
|
|
int16_t cb, fb;
|
2011-03-23 17:41:01 +00:00
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
if (resetstat != 2)
|
|
|
|
numyaxbunches = 0;
|
2011-03-23 17:41:01 +00:00
|
|
|
|
|
|
|
for (i=0; i<MAXSECTORS; i++)
|
|
|
|
{
|
2013-04-09 17:35:11 +00:00
|
|
|
#if !defined NEW_MAP_FORMAT
|
2011-05-12 23:31:13 +00:00
|
|
|
if (resetstat != 2 || i>=numsectors)
|
|
|
|
yax_bunchnum[i][0] = yax_bunchnum[i][1] = -1;
|
2013-04-09 17:35:11 +00:00
|
|
|
#endif
|
2011-03-23 17:41:01 +00:00
|
|
|
nextsectbunch[0][i] = nextsectbunch[1][i] = -1;
|
|
|
|
}
|
|
|
|
for (i=0; i<YAX_MAXBUNCHES; i++)
|
|
|
|
headsectbunch[0][i] = headsectbunch[1][i] = -1;
|
2013-04-09 17:35:11 +00:00
|
|
|
#if !defined NEW_MAP_FORMAT
|
2011-04-11 22:28:58 +00:00
|
|
|
for (i=0; i<MAXWALLS; i++)
|
2011-05-12 23:31:13 +00:00
|
|
|
if (resetstat != 2 || i>=numwalls)
|
|
|
|
yax_nextwall[i][0] = yax_nextwall[i][1] = -1;
|
2013-04-09 17:35:11 +00:00
|
|
|
#endif
|
2011-03-23 17:41:01 +00:00
|
|
|
|
2011-05-12 23:31:13 +00:00
|
|
|
if (resetstat==1)
|
2011-03-23 17:41:01 +00:00
|
|
|
return;
|
|
|
|
|
2013-04-09 17:35:11 +00:00
|
|
|
// Constuct singly linked list of sectors-of-bunch.
|
2012-02-16 19:25:18 +00:00
|
|
|
|
2013-04-09 17:35:11 +00:00
|
|
|
#if !defined NEW_MAP_FORMAT
|
|
|
|
// Read bunchnums directly from the sector struct in yax_[gs]etbunch{es}!
|
2012-02-16 19:25:18 +00:00
|
|
|
editstatus = (resetstat==0);
|
2013-04-09 17:35:11 +00:00
|
|
|
// NOTE: Use oeditstatus to check for in-gamedness from here on!
|
|
|
|
#endif
|
2011-05-15 22:37:24 +00:00
|
|
|
|
|
|
|
if (resetstat==0)
|
|
|
|
{
|
|
|
|
// make bunchnums consecutive
|
|
|
|
uint8_t *const havebunch = (uint8_t *)tempbuf;
|
2019-07-19 01:49:19 +00:00
|
|
|
uint8_t *const bunchmap = havebunch + ((YAX_MAXBUNCHES+7)>>3);
|
2011-05-15 22:37:24 +00:00
|
|
|
int32_t dasub = 0;
|
|
|
|
|
2019-07-19 01:49:19 +00:00
|
|
|
Bmemset(havebunch, 0, (YAX_MAXBUNCHES+7)>>3);
|
2011-05-15 22:37:24 +00:00
|
|
|
for (i=0; i<numsectors; i++)
|
|
|
|
{
|
|
|
|
yax_getbunches(i, &cb, &fb);
|
|
|
|
if (cb>=0)
|
2019-08-04 02:51:50 +00:00
|
|
|
havebunch[cb>>3] |= pow2char[cb&7];
|
2011-05-15 22:37:24 +00:00
|
|
|
if (fb>=0)
|
2019-08-04 02:51:50 +00:00
|
|
|
havebunch[fb>>3] |= pow2char[fb&7];
|
2011-05-15 22:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i=0; i<YAX_MAXBUNCHES; i++)
|
|
|
|
{
|
2019-08-04 02:51:50 +00:00
|
|
|
if ((havebunch[i>>3]&pow2char[i&7])==0)
|
2011-05-15 22:37:24 +00:00
|
|
|
{
|
|
|
|
bunchmap[i] = 255;
|
|
|
|
dasub++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
bunchmap[i] = i-dasub;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=0; i<numsectors; i++)
|
|
|
|
{
|
|
|
|
yax_getbunches(i, &cb, &fb);
|
|
|
|
if (cb>=0)
|
|
|
|
yax_setbunch(i, YAX_CEILING, bunchmap[cb]);
|
2011-10-03 17:43:16 +00:00
|
|
|
if (fb>=0)
|
2011-05-15 22:37:24 +00:00
|
|
|
yax_setbunch(i, YAX_FLOOR, bunchmap[fb]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-09 17:35:11 +00:00
|
|
|
// In-struct --> array transfer (resetstat==0 and !defined NEW_MAP_FORMAT)
|
|
|
|
// and list construction.
|
2011-03-23 17:41:01 +00:00
|
|
|
for (i=numsectors-1; i>=0; i--)
|
|
|
|
{
|
|
|
|
yax_getbunches(i, &cb, &fb);
|
2013-04-09 17:35:11 +00:00
|
|
|
#if !defined NEW_MAP_FORMAT
|
2011-05-12 23:31:13 +00:00
|
|
|
if (resetstat==0)
|
|
|
|
{
|
|
|
|
yax_bunchnum[i][0] = cb;
|
|
|
|
yax_bunchnum[i][1] = fb;
|
|
|
|
}
|
2013-04-09 17:35:11 +00:00
|
|
|
#endif
|
2011-03-23 17:41:01 +00:00
|
|
|
|
|
|
|
if (cb >= 0)
|
|
|
|
{
|
2013-04-09 17:35:11 +00:00
|
|
|
#if !defined NEW_MAP_FORMAT
|
2011-05-12 23:31:13 +00:00
|
|
|
if (resetstat==0)
|
|
|
|
for (j=sector[i].wallptr; j<sector[i].wallptr+sector[i].wallnum; j++)
|
|
|
|
{
|
|
|
|
if (yax_islockededge(j,YAX_CEILING))
|
2012-02-16 19:25:18 +00:00
|
|
|
{
|
2011-05-12 23:31:13 +00:00
|
|
|
yax_nextwall[j][0] = YAX_NEXTWALL(j,0);
|
2012-02-16 19:25:18 +00:00
|
|
|
if (oeditstatus==0)
|
|
|
|
YAX_NEXTWALL(j,0) = 0; // reset lotag!
|
|
|
|
}
|
2011-05-12 23:31:13 +00:00
|
|
|
}
|
2013-04-09 17:35:11 +00:00
|
|
|
#endif
|
2011-03-23 17:41:01 +00:00
|
|
|
if (headsectbunch[0][cb] == -1)
|
|
|
|
{
|
|
|
|
headsectbunch[0][cb] = i;
|
|
|
|
// not duplicated in floors, since every extended ceiling
|
|
|
|
// must have a corresponding floor:
|
2011-05-12 23:31:13 +00:00
|
|
|
if (resetstat==0)
|
|
|
|
numyaxbunches++;
|
2011-03-23 17:41:01 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-04-09 17:35:11 +00:00
|
|
|
int32_t tmpsect = headsectbunch[0][cb];
|
2011-03-23 17:41:01 +00:00
|
|
|
headsectbunch[0][cb] = i;
|
|
|
|
nextsectbunch[0][i] = tmpsect;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fb >= 0)
|
|
|
|
{
|
2013-04-09 17:35:11 +00:00
|
|
|
#if !defined NEW_MAP_FORMAT
|
2011-05-12 23:31:13 +00:00
|
|
|
if (resetstat==0)
|
|
|
|
for (j=sector[i].wallptr; j<sector[i].wallptr+sector[i].wallnum; j++)
|
|
|
|
{
|
|
|
|
if (yax_islockededge(j,YAX_FLOOR))
|
2012-02-16 19:25:18 +00:00
|
|
|
{
|
2011-05-12 23:31:13 +00:00
|
|
|
yax_nextwall[j][1] = YAX_NEXTWALL(j,1);
|
2012-02-16 19:25:18 +00:00
|
|
|
if (oeditstatus==0)
|
|
|
|
YAX_NEXTWALL(j,1) = -1; // reset extra!
|
|
|
|
}
|
2011-05-12 23:31:13 +00:00
|
|
|
}
|
2013-04-09 17:35:11 +00:00
|
|
|
#endif
|
2011-03-23 17:41:01 +00:00
|
|
|
if (headsectbunch[1][fb] == -1)
|
|
|
|
headsectbunch[1][fb] = i;
|
|
|
|
else
|
|
|
|
{
|
2013-04-09 17:35:11 +00:00
|
|
|
int32_t tmpsect = headsectbunch[1][fb];
|
2011-03-23 17:41:01 +00:00
|
|
|
headsectbunch[1][fb] = i;
|
|
|
|
nextsectbunch[1][i] = tmpsect;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-02-16 19:25:18 +00:00
|
|
|
|
2013-04-09 17:35:11 +00:00
|
|
|
#if !defined NEW_MAP_FORMAT
|
2011-03-23 17:41:01 +00:00
|
|
|
editstatus = oeditstatus;
|
2013-06-01 20:09:39 +00:00
|
|
|
#else
|
2014-03-10 20:08:27 +00:00
|
|
|
mapversion = get_mapversion();
|
2013-04-09 17:35:11 +00:00
|
|
|
#endif
|
2011-03-23 17:41:01 +00:00
|
|
|
}
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2012-10-01 17:52:18 +00:00
|
|
|
int32_t yax_getneighborsect(int32_t x, int32_t y, int32_t sectnum, int32_t cf)
|
2011-04-22 22:48:06 +00:00
|
|
|
{
|
|
|
|
int16_t bunchnum = yax_getbunch(sectnum, cf);
|
|
|
|
|
|
|
|
if (bunchnum < 0)
|
|
|
|
return -1;
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t SECTORS_OF_BUNCH(bunchnum, !cf, i))
|
2011-04-22 22:48:06 +00:00
|
|
|
if (inside(x, y, i)==1)
|
|
|
|
return i;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
// indexed as a list:
|
|
|
|
static int16_t bunches[2][YAX_MAXBUNCHES];
|
|
|
|
// indexed with bunchnums directly:
|
|
|
|
static int16_t bunchsec[YAX_MAXBUNCHES], bunchdist[YAX_MAXBUNCHES];
|
2011-05-12 23:31:13 +00:00
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
static int32_t ymostallocsize = 0; // numyaxbunches*xdimen (no sizeof(int16_t) here!)
|
|
|
|
static int16_t *yumost=NULL, *ydmost=NULL; // used as if [numyaxbunches][xdimen]
|
2019-07-19 01:49:19 +00:00
|
|
|
uint8_t haveymost[(YAX_MAXBUNCHES+7)>>3];
|
2011-05-15 22:37:24 +00:00
|
|
|
|
|
|
|
static inline int32_t yax_walldist(int32_t w)
|
|
|
|
{
|
2019-04-18 17:24:30 +00:00
|
|
|
vec2_t closest;
|
|
|
|
getclosestpointonwall_internal({ globalposx, globalposy }, w, &closest);
|
|
|
|
return klabs(closest.x-globalposx) + klabs(closest.y-globalposy);
|
2011-04-22 22:48:06 +00:00
|
|
|
}
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
// calculate distances to bunches and best start-drawing sectors
|
|
|
|
static void yax_scanbunches(int32_t bbeg, int32_t numhere, const uint8_t *lastgotsector)
|
2011-04-22 22:48:06 +00:00
|
|
|
{
|
2011-05-15 23:16:37 +00:00
|
|
|
int32_t bnchcnt, bunchnum, j, k;
|
2011-05-15 22:37:24 +00:00
|
|
|
int32_t startwall, endwall;
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-05-15 23:16:37 +00:00
|
|
|
UNREFERENCED_PARAMETER(lastgotsector);
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
scansector_retfast = 1;
|
|
|
|
scansector_collectsprites = 0;
|
2011-05-12 23:31:13 +00:00
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
for (bnchcnt=bbeg; bnchcnt<bbeg+numhere; bnchcnt++)
|
2011-05-07 18:23:34 +00:00
|
|
|
{
|
2011-05-15 22:37:24 +00:00
|
|
|
int32_t walldist, bestsec=-1;
|
|
|
|
int32_t bestwalldist=INT32_MAX, bestbestdist=INT32_MAX;
|
|
|
|
|
|
|
|
bunchnum = bunches[yax_globalcf][bnchcnt];
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
for (SECTORS_OF_BUNCH(bunchnum,!yax_globalcf, k))
|
2011-05-07 18:23:34 +00:00
|
|
|
{
|
2011-05-15 22:37:24 +00:00
|
|
|
int32_t checkthisec = 0;
|
|
|
|
|
|
|
|
if (inside(globalposx, globalposy, k)==1)
|
|
|
|
{
|
|
|
|
bestsec = k;
|
|
|
|
bestbestdist = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-05-12 23:31:13 +00:00
|
|
|
startwall = sector[k].wallptr;
|
|
|
|
endwall = startwall+sector[k].wallnum;
|
|
|
|
|
|
|
|
for (j=startwall; j<endwall; j++)
|
|
|
|
{
|
|
|
|
/*
|
2011-05-15 22:37:24 +00:00
|
|
|
if ((w=yax_getnextwall(j,!yax_globalcf))>=0)
|
|
|
|
if ((ns=wall[w].nextsector)>=0)
|
2019-08-04 02:51:50 +00:00
|
|
|
if ((lastgotsector[ns>>3]&pow2char[ns&7])==0)
|
2011-05-15 22:37:24 +00:00
|
|
|
continue;
|
2011-05-12 23:31:13 +00:00
|
|
|
*/
|
|
|
|
walldist = yax_walldist(j);
|
|
|
|
if (walldist < bestwalldist)
|
|
|
|
{
|
2011-05-15 22:37:24 +00:00
|
|
|
checkthisec = 1;
|
2011-05-12 23:31:13 +00:00
|
|
|
bestwalldist = walldist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
if (checkthisec)
|
2011-05-12 23:31:13 +00:00
|
|
|
{
|
|
|
|
numscans = numbunches = 0;
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_CLASSIC)
|
2018-04-12 21:04:00 +00:00
|
|
|
classicScanSector(k);
|
2011-05-22 21:52:22 +00:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
else
|
|
|
|
polymost_scansector(k);
|
|
|
|
#endif
|
2011-05-12 23:31:13 +00:00
|
|
|
if (numbunches > 0)
|
2011-05-15 22:37:24 +00:00
|
|
|
{
|
2011-05-12 23:31:13 +00:00
|
|
|
bestsec = k;
|
2011-05-15 22:37:24 +00:00
|
|
|
bestbestdist = bestwalldist;
|
|
|
|
}
|
2011-05-12 23:31:13 +00:00
|
|
|
}
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
2011-05-12 23:31:13 +00:00
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
bunchsec[bunchnum] = bestsec;
|
|
|
|
bunchdist[bunchnum] = bestbestdist;
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
2011-05-15 22:37:24 +00:00
|
|
|
|
|
|
|
scansector_collectsprites = 1;
|
|
|
|
scansector_retfast = 0;
|
|
|
|
}
|
|
|
|
|
2013-09-21 13:38:44 +00:00
|
|
|
static int yax_cmpbunches(const void *b1, const void *b2)
|
2011-05-15 22:37:24 +00:00
|
|
|
{
|
2015-05-03 07:03:48 +00:00
|
|
|
return (bunchdist[B_UNBUF16(b2)] - bunchdist[B_UNBUF16(b1)]);
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2012-02-16 19:25:42 +00:00
|
|
|
|
|
|
|
void yax_tweakpicnums(int32_t bunchnum, int32_t cf, int32_t restore)
|
2011-05-07 18:23:34 +00:00
|
|
|
{
|
2012-02-16 19:25:18 +00:00
|
|
|
// for polymer, this is called before polymer_drawrooms() with restore==0
|
|
|
|
// and after polymer_drawmasks() with restore==1
|
|
|
|
|
2011-05-23 22:42:39 +00:00
|
|
|
int32_t i, dastat;
|
2012-02-16 19:25:42 +00:00
|
|
|
static int16_t opicnum[2][MAXSECTORS];
|
|
|
|
#ifdef DEBUGGINGAIDS
|
|
|
|
static uint8_t expect_restore[2][YAX_MAXBUNCHES];
|
|
|
|
|
|
|
|
// must call this with restore == 0, 1, 0, 1, 0, 1, ...
|
2012-03-26 22:04:44 +00:00
|
|
|
Bassert(expect_restore[cf][bunchnum] == restore);
|
2012-02-16 19:25:42 +00:00
|
|
|
expect_restore[cf][bunchnum] = !expect_restore[cf][bunchnum];
|
|
|
|
#endif
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
for (SECTORS_OF_BUNCH(bunchnum, cf, i))
|
2011-05-18 22:44:09 +00:00
|
|
|
{
|
2011-05-23 22:42:39 +00:00
|
|
|
dastat = (SECTORFLD(i,stat, cf)&(128+256));
|
2011-10-02 22:38:09 +00:00
|
|
|
|
2012-02-16 19:25:18 +00:00
|
|
|
// only consider non-masked ceilings/floors
|
2011-10-02 22:38:09 +00:00
|
|
|
if (dastat==0 || (restore==1 && opicnum[cf][i]&0x8000))
|
2011-05-07 18:23:34 +00:00
|
|
|
{
|
|
|
|
if (!restore)
|
|
|
|
{
|
|
|
|
opicnum[cf][i] = SECTORFLD(i,picnum, cf);
|
|
|
|
if (editstatus && showinvisibility)
|
2011-05-23 22:42:39 +00:00
|
|
|
SECTORFLD(i,picnum, cf) = MAXTILES-1;
|
2011-10-02 22:38:09 +00:00
|
|
|
else //if ((dastat&(128+256))==0)
|
2019-06-29 18:15:51 +00:00
|
|
|
SECTORFLD(i,picnum, cf) = bloodhack ? MAXTILES-2 : 13; //FOF;
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SECTORFLD(i,picnum, cf) = opicnum[cf][i];
|
|
|
|
}
|
2011-10-02 22:38:09 +00:00
|
|
|
#ifdef POLYMER
|
|
|
|
// will be called only in editor
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMER)
|
2011-10-02 22:38:09 +00:00
|
|
|
{
|
|
|
|
if (!restore)
|
|
|
|
{
|
|
|
|
SECTORFLD(i,stat, cf) |= 128;
|
|
|
|
opicnum[cf][i] |= 0x8000;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SECTORFLD(i,stat, cf) &= ~128;
|
|
|
|
SECTORFLD(i,picnum, cf) &= 0x7fff;
|
|
|
|
opicnum[cf][i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
2011-05-18 22:44:09 +00:00
|
|
|
}
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-09-28 20:30:41 +00:00
|
|
|
static void yax_copytsprites()
|
2011-05-07 18:23:34 +00:00
|
|
|
{
|
2011-09-28 20:30:41 +00:00
|
|
|
int32_t i, spritenum, gotthrough, sectnum;
|
2011-05-07 18:23:34 +00:00
|
|
|
int32_t sortcnt = yax_spritesortcnt[yax_globallev];
|
2019-04-18 17:25:24 +00:00
|
|
|
uspriteptr_t spr;
|
2011-05-07 18:23:34 +00:00
|
|
|
|
|
|
|
for (i=0; i<sortcnt; i++)
|
2011-04-22 22:48:06 +00:00
|
|
|
{
|
2011-05-07 18:23:34 +00:00
|
|
|
spritenum = yax_tsprite[yax_globallev][i];
|
|
|
|
|
2011-09-28 20:30:41 +00:00
|
|
|
gotthrough = spritenum&(MAXSPRITES|(MAXSPRITES<<1));
|
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
spritenum &= MAXSPRITES-1;
|
2019-04-18 17:25:24 +00:00
|
|
|
spr = (uspriteptr_t)&sprite[spritenum];
|
2011-05-07 18:23:34 +00:00
|
|
|
sectnum = spr->sectnum;
|
|
|
|
|
2011-09-28 20:30:41 +00:00
|
|
|
if (gotthrough == (MAXSPRITES|(MAXSPRITES<<1)))
|
2011-04-22 22:48:06 +00:00
|
|
|
{
|
2011-09-28 20:30:41 +00:00
|
|
|
if (yax_globalbunch != yax_tsprfrombunch[yax_globallev][i])
|
2011-05-07 18:23:34 +00:00
|
|
|
continue;
|
2011-04-22 22:48:06 +00:00
|
|
|
}
|
2011-09-28 20:30:41 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
int32_t cf = -1;
|
|
|
|
|
|
|
|
if (gotthrough == MAXSPRITES)
|
|
|
|
cf = YAX_CEILING; // sprite got here through the ceiling of lower sector
|
|
|
|
else if (gotthrough == (MAXSPRITES<<1))
|
|
|
|
cf = YAX_FLOOR; // sprite got here through the floor of upper sector
|
|
|
|
|
|
|
|
if (cf != -1)
|
|
|
|
{
|
|
|
|
if ((yax_globallev-YAX_MAXDRAWS)*(-1 + 2*cf) > 0)
|
|
|
|
if (yax_getbunch(sectnum, cf) != yax_globalbunch)
|
|
|
|
continue;
|
|
|
|
|
2012-10-01 17:52:18 +00:00
|
|
|
sectnum = yax_getneighborsect(spr->x, spr->y, sectnum, cf);
|
2011-09-28 20:30:41 +00:00
|
|
|
if (sectnum < 0)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2011-05-07 18:23:34 +00:00
|
|
|
|
2017-07-08 19:42:11 +00:00
|
|
|
if (spritesortcnt >= maxspritesonscreen)
|
2011-05-12 23:31:13 +00:00
|
|
|
break;
|
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
Bmemcpy(&tsprite[spritesortcnt], spr, sizeof(spritetype));
|
|
|
|
tsprite[spritesortcnt].owner = spritenum;
|
2015-10-21 19:54:14 +00:00
|
|
|
tsprite[spritesortcnt].extra = 0;
|
2011-09-28 20:30:41 +00:00
|
|
|
tsprite[spritesortcnt].sectnum = sectnum; // potentially tweak sectnum!
|
2011-05-07 18:23:34 +00:00
|
|
|
spritesortcnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-22 21:52:22 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
void yax_preparedrawrooms(void)
|
|
|
|
{
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMER || numyaxbunches==0)
|
2011-05-07 18:23:34 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
g_nodraw = 1;
|
|
|
|
Bmemset(yax_spritesortcnt, 0, sizeof(yax_spritesortcnt));
|
2011-05-15 22:37:24 +00:00
|
|
|
Bmemset(haveymost, 0, (numyaxbunches+7)>>3);
|
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_CLASSIC && ymostallocsize < xdimen*numyaxbunches)
|
2011-05-15 22:37:24 +00:00
|
|
|
{
|
|
|
|
ymostallocsize = xdimen*numyaxbunches;
|
2014-05-30 00:02:19 +00:00
|
|
|
yumost = (int16_t *)Xrealloc(yumost, ymostallocsize*sizeof(int16_t));
|
|
|
|
ydmost = (int16_t *)Xrealloc(ydmost, ymostallocsize*sizeof(int16_t));
|
2011-05-15 22:37:24 +00:00
|
|
|
}
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
|
|
|
|
2019-06-29 17:48:05 +00:00
|
|
|
void yax_drawrooms(void (*SpriteAnimFunc)(int32_t,int32_t,int32_t,int32_t,int32_t),
|
2012-08-13 18:25:37 +00:00
|
|
|
int16_t sectnum, int32_t didmirror, int32_t smoothr)
|
2011-05-07 18:23:34 +00:00
|
|
|
{
|
2019-07-19 01:49:19 +00:00
|
|
|
static uint8_t havebunch[(YAX_MAXBUNCHES+7)>>3];
|
2011-05-07 18:23:34 +00:00
|
|
|
|
2018-03-07 04:21:05 +00:00
|
|
|
const fix16_t horiz = global100horiz;
|
2012-08-13 18:25:37 +00:00
|
|
|
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
int32_t i, j, k, lev, cf, nmp;
|
2011-05-07 18:23:34 +00:00
|
|
|
int32_t bnchcnt, bnchnum[2] = {0,0}, maxlev[2];
|
|
|
|
int16_t ourbunch[2] = {-1,-1}, osectnum=sectnum;
|
|
|
|
int32_t bnchbeg[YAX_MAXDRAWS][2], bnchend[YAX_MAXDRAWS][2];
|
|
|
|
int32_t bbeg, numhere;
|
|
|
|
|
|
|
|
// original (1st-draw) and accumulated ('per-level') gotsector bitmaps
|
2019-04-18 17:24:43 +00:00
|
|
|
static uint8_t ogotsector[(MAXSECTORS+7)>>3], lgotsector[(MAXSECTORS+7)>>3];
|
2011-05-12 23:31:13 +00:00
|
|
|
#ifdef YAX_DEBUG
|
2011-09-15 17:05:00 +00:00
|
|
|
uint64_t t;
|
2011-05-12 23:31:13 +00:00
|
|
|
#endif
|
2011-05-07 18:23:34 +00:00
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMER || numyaxbunches==0)
|
2011-05-07 18:23:34 +00:00
|
|
|
{
|
|
|
|
return;
|
2011-04-22 22:48:06 +00:00
|
|
|
}
|
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
// if we're here, there was just a drawrooms() call with g_nodraw=1
|
|
|
|
|
|
|
|
Bmemcpy(ogotsector, gotsector, (numsectors+7)>>3);
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
if (sectnum >= 0)
|
|
|
|
yax_getbunches(sectnum, &ourbunch[0], &ourbunch[1]);
|
|
|
|
Bmemset(&havebunch, 0, (numyaxbunches+7)>>3);
|
|
|
|
|
|
|
|
// first scan all bunches above, then all below...
|
2011-04-22 22:48:06 +00:00
|
|
|
for (cf=0; cf<2; cf++)
|
|
|
|
{
|
2011-05-07 18:23:34 +00:00
|
|
|
yax_globalcf = cf;
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
if (cf==1)
|
|
|
|
{
|
|
|
|
sectnum = osectnum;
|
|
|
|
Bmemcpy(gotsector, ogotsector, (numsectors+7)>>3);
|
|
|
|
}
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
for (lev=0; /*lev<YAX_MAXDRAWS*/; lev++)
|
2011-04-22 22:48:06 +00:00
|
|
|
{
|
2011-05-07 18:23:34 +00:00
|
|
|
yax_globallev = YAX_MAXDRAWS + (-1 + 2*cf)*(lev+1);
|
|
|
|
|
|
|
|
bbeg = bnchbeg[lev][cf] = bnchend[lev][cf] = bnchnum[cf];
|
|
|
|
numhere = 0;
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
for (i=0; i<numsectors; i++)
|
2011-04-22 22:48:06 +00:00
|
|
|
{
|
2019-08-04 02:51:50 +00:00
|
|
|
if (!(gotsector[i>>3]&pow2char[i&7]))
|
2011-04-22 22:48:06 +00:00
|
|
|
continue;
|
2011-05-07 18:23:34 +00:00
|
|
|
|
|
|
|
j = yax_getbunch(i, cf);
|
2019-08-04 02:51:50 +00:00
|
|
|
if (j >= 0 && !(havebunch[j>>3]&pow2char[j&7]))
|
2011-04-28 21:28:33 +00:00
|
|
|
{
|
2019-08-04 02:51:50 +00:00
|
|
|
if (videoGetRenderMode() == REND_CLASSIC && (haveymost[j>>3]&pow2char[j&7])==0)
|
2011-05-15 22:37:24 +00:00
|
|
|
{
|
|
|
|
yaxdebug("%s, l %d: skipped bunch %d (no *most)", cf?"v":"^", lev, j);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-05-12 23:31:13 +00:00
|
|
|
if ((SECTORFLD(i,stat, cf)&2) ||
|
2019-08-01 06:49:50 +00:00
|
|
|
(cf==0 && globalposz >= sector[i].ceilingz) ||
|
|
|
|
(cf==1 && globalposz <= sector[i].floorz))
|
2011-05-12 23:31:13 +00:00
|
|
|
{
|
2019-08-04 02:51:50 +00:00
|
|
|
havebunch[j>>3] |= pow2char[j&7];
|
2011-05-12 23:31:13 +00:00
|
|
|
bunches[cf][bnchnum[cf]++] = j;
|
|
|
|
bnchend[lev][cf]++;
|
|
|
|
numhere++;
|
|
|
|
}
|
2011-04-28 21:28:33 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
if (numhere > 0)
|
2011-04-28 21:28:33 +00:00
|
|
|
{
|
2011-05-07 18:23:34 +00:00
|
|
|
// found bunches -- need to fake-draw
|
2011-05-15 22:37:24 +00:00
|
|
|
|
|
|
|
yax_scanbunches(bbeg, numhere, (uint8_t *)gotsector);
|
2011-05-07 18:23:34 +00:00
|
|
|
|
2013-09-21 13:38:44 +00:00
|
|
|
qsort(&bunches[cf][bbeg], numhere, sizeof(int16_t), &yax_cmpbunches);
|
2011-05-07 18:23:34 +00:00
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
if (numhere > 1 && lev != YAX_MAXDRAWS-1)
|
2019-09-03 04:09:20 +00:00
|
|
|
Bmemset(lgotsector, 0, sizeof(lgotsector));
|
2011-05-15 22:37:24 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
for (bnchcnt=bbeg; bnchcnt < bbeg+numhere; bnchcnt++)
|
2011-04-22 22:48:06 +00:00
|
|
|
{
|
2011-05-07 18:23:34 +00:00
|
|
|
j = bunches[cf][bnchcnt]; // the actual bunchnum...
|
2011-05-15 22:37:24 +00:00
|
|
|
yax_globalbunch = j;
|
2011-05-12 23:31:13 +00:00
|
|
|
#ifdef YAX_DEBUG
|
2018-04-12 21:02:51 +00:00
|
|
|
t=timerGetTicksU64();
|
2011-05-12 23:31:13 +00:00
|
|
|
#endif
|
2011-05-15 22:37:24 +00:00
|
|
|
k = bunchsec[j];
|
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
if (k < 0)
|
|
|
|
{
|
2011-05-15 22:37:24 +00:00
|
|
|
yaxprintf("%s, l %d: skipped bunch %d\n", cf?"v":"^", lev, j);
|
2011-05-07 18:23:34 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lev != YAX_MAXDRAWS-1)
|
|
|
|
{
|
2011-09-28 20:30:41 +00:00
|
|
|
#ifdef YAX_DEBUG
|
|
|
|
int32_t odsprcnt = yax_spritesortcnt[yax_globallev];
|
|
|
|
#endif
|
2011-05-07 18:23:34 +00:00
|
|
|
// +MAXSECTORS: force
|
2018-04-12 21:03:47 +00:00
|
|
|
renderDrawRoomsQ16(globalposx,globalposy,globalposz,qglobalang,horiz,k+MAXSECTORS);
|
2011-05-07 18:23:34 +00:00
|
|
|
if (numhere > 1)
|
|
|
|
for (i=0; i<(numsectors+7)>>3; i++)
|
|
|
|
lgotsector[i] |= gotsector[i];
|
|
|
|
|
2011-09-28 20:30:41 +00:00
|
|
|
yaxdebug("l%d: faked (bn %2d) sec %4d,%3d dspr, ob=[%2d,%2d], sn=%4d, %.3f ms",
|
|
|
|
yax_globallev-YAX_MAXDRAWS, j, k, yax_spritesortcnt[yax_globallev]-odsprcnt,
|
2011-09-15 17:05:00 +00:00
|
|
|
ourbunch[0],ourbunch[1],sectnum,
|
2018-04-12 21:02:51 +00:00
|
|
|
(double)(1000*(timerGetTicksU64()-t))/u64tickspersec);
|
2011-05-12 23:31:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ourbunch[cf]==j)
|
|
|
|
{
|
|
|
|
ourbunch[cf] = yax_getbunch(k, cf);
|
|
|
|
sectnum = k;
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
if (numhere > 1 && lev != YAX_MAXDRAWS-1)
|
|
|
|
Bmemcpy(gotsector, lgotsector, (numsectors+7)>>3);
|
|
|
|
}
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
if (numhere==0 || lev==YAX_MAXDRAWS-1)
|
|
|
|
{
|
|
|
|
// no new bunches or max level reached
|
|
|
|
maxlev[cf] = lev - (numhere==0);
|
|
|
|
break;
|
|
|
|
}
|
2011-04-22 22:48:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
// yax_globalcf = -1;
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
// now comes the real drawing!
|
|
|
|
g_nodraw = 0;
|
|
|
|
scansector_collectsprites = 0;
|
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
|
|
|
{
|
2019-10-04 19:13:04 +00:00
|
|
|
GLInterface.ClearScreen(0, 0, 0, true);
|
|
|
|
yax_polymostclearzbuffer = 0;
|
2019-03-19 17:07:53 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
for (cf=0; cf<2; cf++)
|
|
|
|
{
|
2011-05-15 22:37:24 +00:00
|
|
|
yax_globalcf = cf;
|
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
for (lev=maxlev[cf]; lev>=0; lev--)
|
2011-04-22 22:48:06 +00:00
|
|
|
{
|
2011-05-07 18:23:34 +00:00
|
|
|
yax_globallev = YAX_MAXDRAWS + (-1 + 2*cf)*(lev+1);
|
2011-05-12 23:31:13 +00:00
|
|
|
scansector_collectsprites = (lev == YAX_MAXDRAWS-1);
|
2011-04-22 22:48:06 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
for (bnchcnt=bnchbeg[lev][cf]; bnchcnt<bnchend[lev][cf]; bnchcnt++)
|
|
|
|
{
|
|
|
|
j = bunches[cf][bnchcnt]; // the actual bunchnum...
|
2011-05-15 22:37:24 +00:00
|
|
|
k = bunchsec[j]; // best start-drawing sector
|
|
|
|
yax_globalbunch = j;
|
2011-05-12 23:31:13 +00:00
|
|
|
#ifdef YAX_DEBUG
|
2018-04-12 21:02:51 +00:00
|
|
|
t=timerGetTicksU64();
|
2011-05-12 23:31:13 +00:00
|
|
|
#endif
|
2011-05-07 18:23:34 +00:00
|
|
|
yax_tweakpicnums(j, cf, 0);
|
|
|
|
if (k < 0)
|
|
|
|
continue;
|
|
|
|
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
yax_nomaskdidit = 0;
|
|
|
|
for (nmp=r_tror_nomaskpass; nmp>=0; nmp--)
|
|
|
|
{
|
|
|
|
yax_nomaskpass = nmp;
|
2018-04-12 21:03:47 +00:00
|
|
|
renderDrawRoomsQ16(globalposx,globalposy,globalposz,qglobalang,horiz,k+MAXSECTORS); // +MAXSECTORS: force
|
2011-05-07 18:23:34 +00:00
|
|
|
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
if (nmp==1)
|
|
|
|
{
|
2011-09-28 20:30:41 +00:00
|
|
|
yaxdebug("nm1 l%d: DRAWN (bn %2d) sec %4d, %.3f ms",
|
|
|
|
yax_globallev-YAX_MAXDRAWS, j, k,
|
2018-04-12 21:02:51 +00:00
|
|
|
(double)(1000*(timerGetTicksU64()-t))/u64tickspersec);
|
2011-09-28 20:30:41 +00:00
|
|
|
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
if (!yax_nomaskdidit)
|
|
|
|
{
|
|
|
|
yax_nomaskpass = 0;
|
|
|
|
break; // no need to draw the same stuff twice
|
|
|
|
}
|
|
|
|
Bmemcpy(yax_gotsector, gotsector, (numsectors+7)>>3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-28 20:30:41 +00:00
|
|
|
if (!scansector_collectsprites)
|
|
|
|
spritesortcnt = 0;
|
|
|
|
yax_copytsprites();
|
|
|
|
yaxdebug("nm0 l%d: DRAWN (bn %2d) sec %4d,%3d tspr, %.3f ms",
|
|
|
|
yax_globallev-YAX_MAXDRAWS, j, k, spritesortcnt,
|
2018-04-12 21:02:51 +00:00
|
|
|
(double)(1000*(timerGetTicksU64()-t))/u64tickspersec);
|
2011-05-07 18:23:34 +00:00
|
|
|
|
2019-06-29 17:48:05 +00:00
|
|
|
SpriteAnimFunc(globalposx, globalposy, globalposz, globalang, smoothr);
|
2018-04-12 21:03:47 +00:00
|
|
|
renderDrawMasks();
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (lev < maxlev[cf])
|
|
|
|
for (bnchcnt=bnchbeg[lev+1][cf]; bnchcnt<bnchend[lev+1][cf]; bnchcnt++)
|
|
|
|
yax_tweakpicnums(bunches[cf][bnchcnt], cf, 1); // restore picnums
|
2011-04-22 22:48:06 +00:00
|
|
|
}
|
|
|
|
}
|
2011-05-07 18:23:34 +00:00
|
|
|
|
2011-05-12 23:31:13 +00:00
|
|
|
#ifdef YAX_DEBUG
|
2018-04-12 21:02:51 +00:00
|
|
|
t=timerGetTicksU64();
|
2011-05-12 23:31:13 +00:00
|
|
|
#endif
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
yax_globalcf = -1;
|
2011-05-15 22:37:24 +00:00
|
|
|
yax_globalbunch = -1;
|
2011-05-07 18:23:34 +00:00
|
|
|
yax_globallev = YAX_MAXDRAWS;
|
2011-05-12 23:31:13 +00:00
|
|
|
scansector_collectsprites = 0;
|
2011-05-07 18:23:34 +00:00
|
|
|
|
|
|
|
// draw base level
|
2018-04-12 21:03:47 +00:00
|
|
|
renderDrawRoomsQ16(globalposx,globalposy,globalposz,qglobalang,horiz,
|
2012-07-06 15:36:46 +00:00
|
|
|
osectnum + MAXSECTORS*didmirror);
|
2011-09-28 20:30:41 +00:00
|
|
|
// if (scansector_collectsprites)
|
|
|
|
// spritesortcnt = 0;
|
|
|
|
yax_copytsprites();
|
|
|
|
yaxdebug("DRAWN base level sec %d,%3d tspr, %.3f ms", osectnum,
|
2018-04-12 21:02:51 +00:00
|
|
|
spritesortcnt, (double)(1000*(timerGetTicksU64()-t))/u64tickspersec);
|
2011-05-07 18:23:34 +00:00
|
|
|
scansector_collectsprites = 1;
|
|
|
|
|
|
|
|
for (cf=0; cf<2; cf++)
|
|
|
|
if (maxlev[cf] >= 0)
|
|
|
|
for (bnchcnt=bnchbeg[0][cf]; bnchcnt<bnchend[0][cf]; bnchcnt++)
|
|
|
|
yax_tweakpicnums(bunches[cf][bnchcnt], cf, 1); // restore picnums
|
|
|
|
|
|
|
|
#ifdef ENGINE_SCREENSHOT_DEBUG
|
|
|
|
engine_screenshot = 0;
|
|
|
|
#endif
|
2011-05-15 22:37:24 +00:00
|
|
|
|
|
|
|
#ifdef YAX_DEBUG_YMOSTS
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_CLASSIC && numyaxbunches>0)
|
2011-05-15 22:37:24 +00:00
|
|
|
{
|
2018-04-12 21:03:47 +00:00
|
|
|
char purple = paletteGetClosestColor(255, 0, 255);
|
|
|
|
char yellow = paletteGetClosestColor(255, 255, 0);
|
2011-06-18 13:02:08 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing();
|
2011-05-18 22:44:09 +00:00
|
|
|
for (i=0; i<numyaxbunches; i++)
|
|
|
|
{
|
|
|
|
int32_t x, x1;
|
2011-05-15 22:37:24 +00:00
|
|
|
|
2011-05-18 22:44:09 +00:00
|
|
|
if ((haveymost[i>>3]&(1<<i&7))==0)
|
|
|
|
continue;
|
2011-05-15 22:37:24 +00:00
|
|
|
|
2011-05-18 22:44:09 +00:00
|
|
|
x1 = i*xdimen;
|
2011-05-15 22:37:24 +00:00
|
|
|
|
2011-05-18 22:44:09 +00:00
|
|
|
for (x=x1; x<x1+xdimen; x++)
|
|
|
|
{
|
2011-06-18 13:02:08 +00:00
|
|
|
if (yumost[x] >= 0 && yumost[x] < ydim && (x&1))
|
2011-05-18 22:44:09 +00:00
|
|
|
*((char *)frameplace + yumost[x]*bytesperline + x-x1) = purple;
|
2011-05-15 22:37:24 +00:00
|
|
|
|
2011-06-18 13:02:08 +00:00
|
|
|
if (ydmost[x]-1 >= 0 && ydmost[x]-1 < ydim && !(x&1))
|
2011-05-18 22:44:09 +00:00
|
|
|
*((char *)frameplace + (ydmost[x]-1)*bytesperline + x-x1) = yellow;
|
|
|
|
}
|
2011-05-15 22:37:24 +00:00
|
|
|
}
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing();
|
2011-05-15 22:37:24 +00:00
|
|
|
}
|
|
|
|
#endif
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
|
|
|
yax_polymostclearzbuffer = 1;
|
|
|
|
#endif
|
2011-04-22 22:48:06 +00:00
|
|
|
}
|
|
|
|
|
2012-03-22 22:46:23 +00:00
|
|
|
#endif // defined YAX_ENABLE
|
2011-03-02 21:21:47 +00:00
|
|
|
|
2012-03-22 22:46:23 +00:00
|
|
|
// must have writable frame buffer, i.e. done begindrawing()
|
|
|
|
static void draw_rainbow_background(void)
|
|
|
|
{
|
2013-05-01 17:42:05 +00:00
|
|
|
int32_t y, i;
|
|
|
|
const int32_t N = 240; // don't use fullbright colors
|
|
|
|
const int32_t numfull=bytesperline/N, numrest=bytesperline%N;
|
2012-03-22 22:46:23 +00:00
|
|
|
|
2013-05-01 17:42:05 +00:00
|
|
|
const char *const src = palookup[0] + 256*18;
|
|
|
|
char *dst = (char *)frameplace;
|
|
|
|
|
|
|
|
for (y=0; y<ydim; y++)
|
2012-03-22 22:46:23 +00:00
|
|
|
{
|
2013-05-01 17:42:05 +00:00
|
|
|
for (i=0; i<numfull; i++)
|
|
|
|
Bmemcpy(&dst[N*i], src, N);
|
|
|
|
if (numrest > 0)
|
|
|
|
Bmemcpy(&dst[N*i], src, numrest);
|
|
|
|
|
|
|
|
dst += bytesperline;
|
2012-03-22 22:46:23 +00:00
|
|
|
}
|
|
|
|
}
|
2013-05-01 17:42:05 +00:00
|
|
|
|
2011-04-14 20:48:08 +00:00
|
|
|
//
|
|
|
|
// setslope
|
|
|
|
//
|
|
|
|
void setslope(int32_t sectnum, int32_t cf, int16_t slope)
|
|
|
|
{
|
|
|
|
if (slope==0)
|
|
|
|
{
|
|
|
|
SECTORFLD(sectnum,stat, cf) &= ~2;
|
|
|
|
SECTORFLD(sectnum,heinum, cf) = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SECTORFLD(sectnum,stat, cf) |= 2;
|
|
|
|
SECTORFLD(sectnum,heinum, cf) = slope;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
#define WALLS_ARE_CONSISTENT(k) ((wall[k].x == x2 && wall[k].y == y2) \
|
|
|
|
&& ((wall[wall[k].point2]).x == x1 && (wall[wall[k].point2]).y == y1))
|
|
|
|
|
2011-06-04 00:06:08 +00:00
|
|
|
static int32_t getscore(int32_t w1c, int32_t w1f, int32_t w2c, int32_t w2f)
|
|
|
|
{
|
|
|
|
if (w1c > w1f)
|
|
|
|
swaplong(&w1c, &w1f);
|
|
|
|
if (w2c > w2f)
|
|
|
|
swaplong(&w2c, &w2f);
|
|
|
|
|
|
|
|
// now: c <= f for each "wall-vline"
|
|
|
|
|
2015-02-11 05:21:53 +00:00
|
|
|
int32_t maxceil = max(w1c, w2c);
|
|
|
|
int32_t minflor = min(w1f, w2f);
|
2011-06-04 00:06:08 +00:00
|
|
|
|
|
|
|
return minflor-maxceil;
|
|
|
|
}
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
const int16_t *chsecptr_onextwall = NULL;
|
2010-10-28 20:17:22 +00:00
|
|
|
|
2011-01-16 00:23:39 +00:00
|
|
|
int32_t checksectorpointer(int16_t i, int16_t sectnum)
|
|
|
|
{
|
2011-09-30 13:52:02 +00:00
|
|
|
int32_t startsec, endsec;
|
2011-01-16 00:23:39 +00:00
|
|
|
int32_t j, k, startwall, endwall, x1, y1, x2, y2, numnewwalls=0;
|
2011-06-04 00:06:08 +00:00
|
|
|
int32_t bestnextwall=-1, bestnextsec=-1, bestwallscore=INT32_MIN;
|
|
|
|
int32_t cz[4], fz[4], tmp[2], tmpscore=0;
|
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
int16_t cb[2], fb[2];
|
|
|
|
#endif
|
2011-01-16 00:23:39 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (checksectorpointer_warn && (i<0 || i>=max(numwalls,newnumwalls)))
|
|
|
|
{
|
|
|
|
char buf[128];
|
|
|
|
Bsprintf(buf, "WARN: checksectorpointer called with i=%d but (new)numwalls=%d", i, max(numwalls,newnumwalls));
|
|
|
|
OSD_Printf("%s\n", buf);
|
|
|
|
printmessage16("%s", buf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
x1 = wall[i].x;
|
|
|
|
y1 = wall[i].y;
|
|
|
|
x2 = (wall[wall[i].point2]).x;
|
|
|
|
y2 = (wall[wall[i].point2]).y;
|
|
|
|
|
2011-04-14 20:48:08 +00:00
|
|
|
k = wall[i].nextwall;
|
|
|
|
if (k >= 0) //Check for early exit
|
2011-01-16 00:23:39 +00:00
|
|
|
{
|
2011-05-15 22:37:24 +00:00
|
|
|
if (WALLS_ARE_CONSISTENT(k))
|
|
|
|
return 0;
|
2011-04-14 20:48:08 +00:00
|
|
|
|
|
|
|
wall[k].nextwall = wall[k].nextsector = -1;
|
2011-01-16 00:23:39 +00:00
|
|
|
}
|
|
|
|
|
2011-09-30 13:52:02 +00:00
|
|
|
if ((unsigned)wall[i].nextsector < (unsigned)numsectors && wall[i].nextwall < 0)
|
|
|
|
{
|
|
|
|
// if we have a nextsector but no nextwall, take this as a hint
|
|
|
|
// to search only the walls of that sector
|
|
|
|
startsec = wall[i].nextsector;
|
|
|
|
endsec = startsec+1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
startsec = 0;
|
|
|
|
endsec = numsectors;
|
|
|
|
}
|
|
|
|
|
2011-04-14 20:48:08 +00:00
|
|
|
wall[i].nextsector = wall[i].nextwall = -1;
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
if (chsecptr_onextwall && (k=chsecptr_onextwall[i])>=0 && wall[k].nextwall<0)
|
|
|
|
{
|
2011-06-04 00:06:08 +00:00
|
|
|
// old next wall found
|
2011-05-15 22:37:24 +00:00
|
|
|
if (WALLS_ARE_CONSISTENT(k))
|
|
|
|
{
|
|
|
|
j = sectorofwall(k);
|
|
|
|
|
|
|
|
wall[i].nextsector = j;
|
|
|
|
wall[i].nextwall = k;
|
|
|
|
wall[k].nextsector = sectnum;
|
|
|
|
wall[k].nextwall = i;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-30 13:52:02 +00:00
|
|
|
for (j=startsec; j<endsec; j++)
|
2011-01-16 00:23:39 +00:00
|
|
|
{
|
2011-05-02 16:58:11 +00:00
|
|
|
if (j == sectnum)
|
|
|
|
continue;
|
|
|
|
|
2011-04-22 22:48:06 +00:00
|
|
|
YAX_SKIPSECTOR(j);
|
|
|
|
|
2011-01-16 00:23:39 +00:00
|
|
|
startwall = sector[j].wallptr;
|
2011-05-15 22:37:24 +00:00
|
|
|
endwall = startwall + sector[j].wallnum;
|
|
|
|
for (k=startwall; k<endwall; k++)
|
2011-01-16 00:23:39 +00:00
|
|
|
{
|
2011-05-15 22:37:24 +00:00
|
|
|
if (!WALLS_ARE_CONSISTENT(k))
|
2011-04-14 20:48:08 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Don't create link if the other side is connected to another wall.
|
|
|
|
// The nextwall relation should be definitely one-to-one at all times!
|
|
|
|
if (wall[k].nextwall>=0 && wall[k].nextwall != i)
|
|
|
|
continue;
|
2011-06-04 00:06:08 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
yax_getbunches(sectnum, &cb[0], &fb[0]);
|
|
|
|
yax_getbunches(j, &cb[1], &fb[1]);
|
2011-04-14 20:48:08 +00:00
|
|
|
|
2011-06-04 00:06:08 +00:00
|
|
|
if ((cb[0]>=0 && cb[0]==cb[1]) || (fb[0]>=0 && fb[0]==fb[1]))
|
2011-04-14 20:48:08 +00:00
|
|
|
{
|
2011-06-04 00:06:08 +00:00
|
|
|
tmpscore = INT32_MAX;
|
2011-04-14 20:48:08 +00:00
|
|
|
}
|
2011-06-04 00:06:08 +00:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
getzsofslope(sectnum, x1,y1, &cz[0],&fz[0]);
|
|
|
|
getzsofslope(sectnum, x2,y2, &cz[1],&fz[1]);
|
|
|
|
getzsofslope(j, x1,y1, &cz[2],&fz[2]);
|
|
|
|
getzsofslope(j, x2,y2, &cz[3],&fz[3]);
|
2011-04-14 20:48:08 +00:00
|
|
|
|
2011-06-04 00:06:08 +00:00
|
|
|
tmp[0] = getscore(cz[0],fz[0], cz[2],fz[2]);
|
|
|
|
tmp[1] = getscore(cz[1],fz[1], cz[3],fz[3]);
|
|
|
|
|
|
|
|
if ((tmp[0]^tmp[1]) >= 0)
|
|
|
|
tmpscore = tmp[0]+tmp[1];
|
|
|
|
else
|
|
|
|
tmpscore = max(tmp[0], tmp[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bestnextwall == -1 || tmpscore > bestwallscore)
|
|
|
|
{
|
|
|
|
bestwallscore = tmpscore;
|
|
|
|
bestnextwall = k;
|
|
|
|
bestnextsec = j;
|
|
|
|
}
|
|
|
|
|
|
|
|
numnewwalls++;
|
2011-01-16 00:23:39 +00:00
|
|
|
}
|
|
|
|
}
|
2011-05-15 22:37:24 +00:00
|
|
|
|
2011-06-04 00:06:08 +00:00
|
|
|
// sectnum -2 means dry run
|
|
|
|
if (bestnextwall >= 0 && sectnum!=-2)
|
|
|
|
#ifdef YAX_ENABLE
|
2011-09-30 13:52:02 +00:00
|
|
|
// for walls with TROR neighbors, be conservative in case if score <=0
|
|
|
|
// (meaning that no wall area is mutually visible) -- it could be that
|
|
|
|
// another sector is a better candidate later on
|
2011-06-04 00:06:08 +00:00
|
|
|
if ((yax_getnextwall(i, 0)<0 && yax_getnextwall(i, 1)<0) || bestwallscore>0)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// initprintf("w%d new nw=%d (score %d)\n", i, bestnextwall, bestwallscore)
|
|
|
|
wall[i].nextsector = bestnextsec;
|
|
|
|
wall[i].nextwall = bestnextwall;
|
|
|
|
wall[bestnextwall].nextsector = sectnum;
|
|
|
|
wall[bestnextwall].nextwall = i;
|
|
|
|
}
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
return numnewwalls;
|
2011-01-16 00:23:39 +00:00
|
|
|
}
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
#undef WALLS_ARE_CONSISTENT
|
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t xb1[MAXWALLSB]; // Polymost uses this as a temp array
|
|
|
|
static int32_t yb1[MAXWALLSB], xb2[MAXWALLSB], yb2[MAXWALLSB];
|
|
|
|
int32_t rx1[MAXWALLSB], ry1[MAXWALLSB];
|
|
|
|
static int32_t rx2[MAXWALLSB], ry2[MAXWALLSB];
|
|
|
|
int16_t bunchp2[MAXWALLSB], thesector[MAXWALLSB];
|
2011-01-16 00:23:39 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int16_t bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
static int32_t nodesperline, ysavecnt;
|
|
|
|
static int16_t *smost, *umost, *dmost, *bakumost, *bakdmost;
|
|
|
|
static int16_t *uplc, *dplc, *uwall, *dwall;
|
|
|
|
static int32_t *swplc, *lplc, *swall, *lwall;
|
|
|
|
#ifdef HIGH_PRECISION_SPRITE
|
|
|
|
static float *swallf;
|
|
|
|
#endif
|
2014-10-29 17:04:28 +00:00
|
|
|
|
2019-06-25 18:35:05 +00:00
|
|
|
uint8_t* mirrorBuffer;
|
|
|
|
|
2011-07-13 16:42:29 +00:00
|
|
|
static int32_t smostcnt;
|
2011-12-27 14:22:45 +00:00
|
|
|
static int32_t smoststart[MAXWALLSB];
|
2006-04-13 20:47:06 +00:00
|
|
|
static char smostwalltype[MAXWALLSB];
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
static int32_t smostwall[MAXWALLSB], smostwallcnt = -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-10-29 17:04:43 +00:00
|
|
|
static vec3_t spritesxyz[MAXSPRITESONSCREEN+1];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t xdimen = -1, xdimenrecip, halfxdimen, xdimenscale, xdimscale;
|
2014-11-28 08:14:00 +00:00
|
|
|
float fxdimen = -1.f;
|
2011-09-15 17:02:52 +00:00
|
|
|
int32_t ydimen;
|
2013-01-17 21:59:01 +00:00
|
|
|
intptr_t frameoffset;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t nrx1[8], nry1[8], nrx2[8], nry2[8]; // JBF 20031206: Thanks Ken
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t rxi[8], ryi[8];
|
|
|
|
static int32_t rzi[8], rxi2[8], ryi2[8], rzi2[8];
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t xsi[8], ysi[8], horizycent;
|
2012-05-26 21:58:31 +00:00
|
|
|
static int32_t *horizlookup=0, *horizlookup2=0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t globalposx, globalposy, globalposz, globalhoriz;
|
2018-03-07 04:21:05 +00:00
|
|
|
fix16_t qglobalhoriz;
|
2014-10-25 03:32:26 +00:00
|
|
|
float fglobalposx, fglobalposy, fglobalposz;
|
2009-01-09 09:29:17 +00:00
|
|
|
int16_t globalang, globalcursectnum;
|
2018-03-07 04:21:18 +00:00
|
|
|
fix16_t qglobalang;
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t globalpal, cosglobalang, singlobalang;
|
|
|
|
int32_t cosviewingrangeglobalang, sinviewingrangeglobalang;
|
2013-05-15 02:19:14 +00:00
|
|
|
static int32_t globaluclip, globaldclip;
|
|
|
|
int32_t globvis, globalvisibility;
|
|
|
|
int32_t globalhisibility, globalpisibility, globalcisibility;
|
2019-03-19 17:08:39 +00:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
int32_t globvis2, globalvisibility2, globalhisibility2, globalpisibility2, globalcisibility2;
|
|
|
|
#endif
|
2012-01-26 21:58:08 +00:00
|
|
|
//char globparaceilclip, globparaflorclip;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-01-26 21:58:08 +00:00
|
|
|
int32_t xyaspect;
|
|
|
|
static int32_t viewingrangerecip;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-01-26 21:58:08 +00:00
|
|
|
static char globalxshift, globalyshift;
|
|
|
|
static int32_t globalxpanning, globalypanning;
|
|
|
|
int32_t globalshade, globalorientation;
|
|
|
|
int16_t globalpicnum;
|
|
|
|
static int16_t globalshiftval;
|
2013-02-14 16:02:12 +00:00
|
|
|
#ifdef HIGH_PRECISION_SPRITE
|
|
|
|
static int64_t globalzd;
|
|
|
|
#else
|
|
|
|
static int32_t globalzd;
|
|
|
|
#endif
|
|
|
|
static int32_t globalyscale;
|
2011-04-14 20:48:08 +00:00
|
|
|
static int32_t globalxspan, globalyspan, globalispow2=1; // true if texture has power-of-two x and y size
|
2012-01-26 21:58:08 +00:00
|
|
|
static intptr_t globalbufplc;
|
|
|
|
|
2014-04-05 11:28:06 +00:00
|
|
|
static int32_t globaly1, globalx2;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-04-21 17:00:54 +00:00
|
|
|
int16_t sectorborder[256];
|
2012-01-20 13:24:15 +00:00
|
|
|
int32_t ydim16, qsetmode = 0;
|
2011-03-13 11:59:32 +00:00
|
|
|
int16_t pointhighlight=-1, linehighlight=-1, highlightcnt=0;
|
2014-10-29 17:04:28 +00:00
|
|
|
static int32_t *lastx;
|
2012-01-26 21:58:08 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t halfxdim16, midydim16;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t sx, sy, z;
|
|
|
|
int16_t a, picnum;
|
|
|
|
int8_t dashade;
|
2019-09-22 21:15:46 +00:00
|
|
|
uint8_t dapalnum, dastat;
|
2014-03-05 21:12:54 +00:00
|
|
|
uint8_t daalpha, dablend;
|
2013-03-25 04:32:24 +00:00
|
|
|
char pagesleft;
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t cx1, cy1, cx2, cy2;
|
|
|
|
int32_t uniqid; //JF extension
|
2006-04-13 20:47:06 +00:00
|
|
|
} permfifotype;
|
|
|
|
static permfifotype permfifo[MAXPERMS];
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t permhead = 0, permtail = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-04-19 22:42:22 +00:00
|
|
|
EDUKE32_STATIC_ASSERT(MAXWALLSB < INT16_MAX);
|
2012-01-26 21:58:08 +00:00
|
|
|
int16_t numscans, numbunches;
|
|
|
|
static int16_t numhits;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-09-23 17:55:11 +00:00
|
|
|
uint8_t vgapal16[4*256] =
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2015-09-23 17:55:11 +00:00
|
|
|
0,0,0,0, 170,0,0,0, 0,170,0,0, 170,170,0,0, 0,0,170,0,
|
|
|
|
170,0,170,0, 0,85,170,0, 170,170,170,0, 85,85,85,0, 255,85,85,0,
|
|
|
|
85,255,85,0, 255,255,85,0, 85,85,255,0, 255,85,255,0, 85,255,255,0,
|
|
|
|
255,255,255,0
|
2007-12-12 17:42:14 +00:00
|
|
|
};
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int16_t searchit;
|
|
|
|
int32_t searchx = -1, searchy; //search input
|
|
|
|
int16_t searchsector, searchwall, searchstat; //search output
|
2010-09-06 23:08:35 +00:00
|
|
|
|
2011-03-17 23:37:38 +00:00
|
|
|
// SEARCHBOTTOMWALL:
|
|
|
|
// When aiming at a the bottom part of a 2-sided wall whose bottom part
|
|
|
|
// is swapped (.cstat&2), searchbottomwall equals that wall's .nextwall. In all
|
|
|
|
// other cases (when aiming at a wall), searchbottomwall equals searchwall.
|
|
|
|
//
|
|
|
|
// SEARCHISBOTTOM:
|
|
|
|
// When aiming at a 2-sided wall, 1 if aiming at the bottom part, 0 else
|
|
|
|
int16_t searchbottomwall, searchisbottom;
|
2010-09-06 23:08:35 +00:00
|
|
|
|
2019-06-25 18:35:05 +00:00
|
|
|
char inpreparemirror = 0;
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t mirrorsx1, mirrorsy1, mirrorsx2, mirrorsy2;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-04-18 17:24:37 +00:00
|
|
|
#define MAXSETVIEW 4
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t setviewcnt = 0; // interface layers use this now
|
2019-04-18 17:24:37 +00:00
|
|
|
static intptr_t bakframeplace[MAXSETVIEW];
|
|
|
|
static int32_t bakxsiz[MAXSETVIEW], bakysiz[MAXSETVIEW];
|
|
|
|
static vec2_t bakwindowxy1[MAXSETVIEW], bakwindowxy2[MAXSETVIEW];
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2014-09-30 04:06:32 +00:00
|
|
|
static int32_t bakrendmode;
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
2014-09-30 04:06:32 +00:00
|
|
|
static int32_t baktile;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-08-08 01:48:55 +00:00
|
|
|
#ifdef APPNAME
|
|
|
|
char apptitle[256] = APPNAME;
|
|
|
|
#else
|
2006-04-13 20:47:06 +00:00
|
|
|
char apptitle[256] = "Build Engine";
|
2019-08-08 01:48:55 +00:00
|
|
|
#endif
|
2011-01-27 06:35:52 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// Internal Engine Functions
|
|
|
|
//
|
|
|
|
|
2011-06-18 13:02:08 +00:00
|
|
|
// returns: 0=continue sprite collecting;
|
|
|
|
// 1=break out of sprite collecting;
|
2018-04-12 21:04:00 +00:00
|
|
|
int32_t renderAddTsprite(int16_t z, int16_t sectnum)
|
2011-05-22 21:52:22 +00:00
|
|
|
{
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const spr = (uspriteptr_t)&sprite[z];
|
2011-05-22 21:52:22 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (g_nodraw==0)
|
|
|
|
{
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
if (numyaxbunches==0)
|
|
|
|
{
|
2011-05-22 21:52:22 +00:00
|
|
|
#endif
|
2017-07-08 19:42:11 +00:00
|
|
|
if (spritesortcnt >= maxspritesonscreen)
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
return 1;
|
|
|
|
|
2013-02-01 13:05:08 +00:00
|
|
|
Bmemcpy(&tsprite[spritesortcnt], spr, sizeof(spritetype));
|
2015-10-21 19:54:14 +00:00
|
|
|
tsprite[spritesortcnt].extra = 0;
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
tsprite[spritesortcnt++].owner = z;
|
|
|
|
|
2011-05-22 21:52:22 +00:00
|
|
|
#ifdef YAX_ENABLE
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
}
|
2011-05-22 21:52:22 +00:00
|
|
|
}
|
|
|
|
else
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
if (yax_nomaskpass==0)
|
2011-05-22 21:52:22 +00:00
|
|
|
{
|
2015-07-17 00:12:40 +00:00
|
|
|
int16_t *sortcnt = &yax_spritesortcnt[yax_globallev];
|
|
|
|
|
2017-07-08 19:42:11 +00:00
|
|
|
if (*sortcnt >= maxspritesonscreen)
|
2011-12-17 18:51:29 +00:00
|
|
|
return 1;
|
2011-05-22 21:52:22 +00:00
|
|
|
|
|
|
|
yax_tsprite[yax_globallev][*sortcnt] = z;
|
2011-09-28 20:30:41 +00:00
|
|
|
if (yax_globalbunch >= 0)
|
|
|
|
{
|
|
|
|
yax_tsprite[yax_globallev][*sortcnt] |= (MAXSPRITES|(MAXSPRITES<<1));
|
|
|
|
yax_tsprfrombunch[yax_globallev][*sortcnt] = yax_globalbunch;
|
|
|
|
}
|
2011-05-22 21:52:22 +00:00
|
|
|
(*sortcnt)++;
|
|
|
|
|
|
|
|
// now check whether the tsprite needs duplication into another level
|
|
|
|
if ((spr->cstat&48)==32)
|
|
|
|
return 0;
|
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
int16_t cb, fb;
|
|
|
|
|
2011-05-22 21:52:22 +00:00
|
|
|
yax_getbunches(sectnum, &cb, &fb);
|
|
|
|
if (cb < 0 && fb < 0)
|
|
|
|
return 0;
|
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t spheight;
|
|
|
|
int16_t spzofs = spriteheightofs(z, &spheight, 1);
|
2011-05-22 21:52:22 +00:00
|
|
|
|
|
|
|
// TODO: get*zofslope?
|
|
|
|
if (cb>=0 && spr->z+spzofs-spheight < sector[sectnum].ceilingz)
|
|
|
|
{
|
|
|
|
sortcnt = &yax_spritesortcnt[yax_globallev-1];
|
2017-07-08 19:42:11 +00:00
|
|
|
if (*sortcnt < maxspritesonscreen)
|
2011-05-22 21:52:22 +00:00
|
|
|
{
|
|
|
|
yax_tsprite[yax_globallev-1][*sortcnt] = z|MAXSPRITES;
|
|
|
|
(*sortcnt)++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fb>=0 && spr->z+spzofs > sector[sectnum].floorz)
|
|
|
|
{
|
|
|
|
sortcnt = &yax_spritesortcnt[yax_globallev+1];
|
2017-07-08 19:42:11 +00:00
|
|
|
if (*sortcnt < maxspritesonscreen)
|
2011-05-22 21:52:22 +00:00
|
|
|
{
|
|
|
|
yax_tsprite[yax_globallev+1][*sortcnt] = z|(MAXSPRITES<<1);
|
|
|
|
(*sortcnt)++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:25:38 +00:00
|
|
|
static FORCE_INLINE vec2_t get_rel_coords(int32_t const x, int32_t const y)
|
2015-01-04 18:45:00 +00:00
|
|
|
{
|
2019-04-18 17:25:38 +00:00
|
|
|
return { dmulscale6(y, cosglobalang, -x, singlobalang),
|
|
|
|
dmulscale6(x, cosviewingrangeglobalang, y, sinviewingrangeglobalang) };
|
2015-01-04 18:45:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Note: the returned y coordinates are not actually screen coordinates, but
|
|
|
|
// potentially clipped player-relative y coordinates.
|
2018-10-07 05:22:17 +00:00
|
|
|
static int get_screen_coords(const vec2_t &p1, const vec2_t &p2,
|
2015-01-04 18:45:00 +00:00
|
|
|
int32_t *sx1ptr, int32_t *sy1ptr,
|
|
|
|
int32_t *sx2ptr, int32_t *sy2ptr)
|
|
|
|
{
|
|
|
|
int32_t sx1, sy1, sx2, sy2;
|
|
|
|
|
|
|
|
// First point.
|
|
|
|
|
|
|
|
if (p1.x >= -p1.y)
|
|
|
|
{
|
|
|
|
if (p1.x > p1.y || p1.y == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
sx1 = halfxdimen + scale(p1.x, halfxdimen, p1.y)
|
|
|
|
+ (p1.x >= 0); // Fix for SIGNED divide
|
|
|
|
if (sx1 >= xdimen)
|
|
|
|
sx1 = xdimen-1;
|
|
|
|
|
|
|
|
sy1 = p1.y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (p2.x < -p2.y)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
sx1 = 0;
|
|
|
|
|
|
|
|
int32_t tempint = (p1.x + p1.y) - (p2.x + p2.y);
|
|
|
|
if (tempint == 0)
|
|
|
|
return 0;
|
|
|
|
sy1 = p1.y + scale(p2.y-p1.y, p1.x+p1.y, tempint);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sy1 < 256)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Second point.
|
|
|
|
|
|
|
|
if (p2.x <= p2.y)
|
|
|
|
{
|
|
|
|
if (p2.x < -p2.y || p2.y == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
sx2 = halfxdimen + scale(p2.x,halfxdimen,p2.y) - 1
|
|
|
|
+ (p2.x >= 0); // Fix for SIGNED divide
|
|
|
|
if (sx2 >= xdimen)
|
|
|
|
sx2 = xdimen-1;
|
|
|
|
|
|
|
|
sy2 = p2.y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (p1.x > p1.y)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
sx2 = xdimen-1;
|
|
|
|
|
2018-10-10 19:14:51 +00:00
|
|
|
int32_t const tempint = (p1.y - p1.x) + (p2.x - p2.y);
|
|
|
|
|
2015-01-04 18:45:00 +00:00
|
|
|
sy2 = p1.y + scale(p2.y-p1.y, p1.y-p1.x, tempint);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sy2 < 256 || sx1 > sx2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*sx1ptr = sx1; *sy1ptr = sy1;
|
|
|
|
*sx2ptr = sx2; *sy2ptr = sy2;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-11-18 18:13:48 +00:00
|
|
|
|
|
|
|
static inline int findUnusedTile(void)
|
|
|
|
{
|
2019-04-18 17:25:38 +00:00
|
|
|
static int lastUnusedTile = MAXUSERTILES-1;
|
|
|
|
|
2018-11-18 21:17:59 +00:00
|
|
|
for (; lastUnusedTile >= 0; --lastUnusedTile)
|
2019-04-18 17:25:38 +00:00
|
|
|
if ((tilesiz[lastUnusedTile].x|tilesiz[lastUnusedTile].y) == 0)
|
2018-11-18 18:13:48 +00:00
|
|
|
return lastUnusedTile;
|
|
|
|
|
2018-11-18 21:17:59 +00:00
|
|
|
return -1;
|
2018-11-18 18:13:48 +00:00
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// scansector (internal)
|
|
|
|
//
|
2018-04-12 21:04:00 +00:00
|
|
|
static void classicScanSector(int16_t startsectnum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-04-21 17:00:54 +00:00
|
|
|
if (startsectnum < 0)
|
|
|
|
return;
|
2019-09-19 20:02:45 +00:00
|
|
|
|
2019-08-01 06:50:56 +00:00
|
|
|
if (automapping)
|
2019-09-19 20:02:45 +00:00
|
|
|
show2dsector[startsectnum>>3] |= pow2char[startsectnum&7];
|
2014-04-21 17:00:54 +00:00
|
|
|
|
2016-09-09 03:12:20 +00:00
|
|
|
sectorborder[0] = startsectnum;
|
|
|
|
int32_t sectorbordercnt = 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2014-04-21 17:00:54 +00:00
|
|
|
const int32_t sectnum = sectorborder[--sectorbordercnt];
|
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (scansector_collectsprites)
|
|
|
|
#endif
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=headspritesect[sectnum]; i>=0; i=nextspritesect[i])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const spr = (uspriteptr_t)&sprite[i];
|
2014-04-21 17:00:54 +00:00
|
|
|
|
2016-09-09 03:12:20 +00:00
|
|
|
if (((spr->cstat & 0x8000) && !showinvisibility) || spr->xrepeat == 0 || spr->yrepeat == 0)
|
|
|
|
continue;
|
2015-12-23 04:05:58 +00:00
|
|
|
|
2016-09-09 03:12:20 +00:00
|
|
|
vec2_t const s = { spr->x-globalposx, spr->y-globalposy };
|
|
|
|
|
|
|
|
if ((spr->cstat&48) || ((coord_t)s.x*cosglobalang+(coord_t)s.y*singlobalang > 0))
|
|
|
|
if ((spr->cstat&(64+48))!=(64+16) || dmulscale6(sintable[(spr->ang+512)&2047],-s.x, sintable[spr->ang&2047],-s.y) > 0)
|
2018-04-12 21:04:00 +00:00
|
|
|
if (renderAddTsprite(i, sectnum))
|
2016-09-09 03:12:20 +00:00
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gotsector[sectnum>>3] |= pow2char[sectnum&7];
|
|
|
|
|
2015-01-04 18:45:00 +00:00
|
|
|
const int32_t onumbunches = numbunches;
|
|
|
|
const int32_t onumscans = numscans;
|
|
|
|
|
|
|
|
const int32_t startwall = sector[sectnum].wallptr;
|
|
|
|
const int32_t endwall = startwall + sector[sectnum].wallnum;
|
|
|
|
int32_t scanfirst = numscans;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-01-04 18:45:00 +00:00
|
|
|
vec2_t p1, p2 = { 0, 0 };
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t w=startwall; w<endwall; w++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const wal = (uwallptr_t)&wall[w];
|
2014-04-21 17:00:54 +00:00
|
|
|
const int32_t nextsectnum = wal->nextsector;
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const wal2 = (uwallptr_t)&wall[wal->point2];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-04-21 17:00:54 +00:00
|
|
|
const int32_t x1 = wal->x-globalposx, y1 = wal->y-globalposy;
|
|
|
|
const int32_t x2 = wal2->x-globalposx, y2 = wal2->y-globalposy;
|
2015-01-04 18:45:03 +00:00
|
|
|
|
|
|
|
// The following block checks for a potential collection of a
|
|
|
|
// sector that is "thin" in screen space. This is necessary because
|
|
|
|
// not all sectors that are needed to be drawn may be collected via
|
|
|
|
// drawalls() -> scansector() (although those are the majority).
|
|
|
|
// Example: standing at exactly the intersection of a large sector
|
|
|
|
// into four quadrant sub-sectors.
|
2015-01-04 18:45:00 +00:00
|
|
|
#if 1
|
2015-01-04 18:45:03 +00:00
|
|
|
if (nextsectnum >= 0 && (wal->cstat&32) == 0 && sectorbordercnt < ARRAY_SSIZE(sectorborder))
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2015-01-04 18:45:00 +00:00
|
|
|
if (yax_nomaskpass==0 || !yax_isislandwall(w, !yax_globalcf) || (yax_nomaskdidit=1, 0))
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((gotsector[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0)
|
|
|
|
{
|
Integer Overflow Offensive continued: first round of -ftrapv - cleanness.
That is, "clang -ftrapv" builds don't abort almost immediately after entering
a level.
There are various classes of overflow bugs, needing different handling:
- Some texture mapping code was written with signed integer wrapping semantics
in mind. In some places, we're able to get away with unsigned casts.
- sometimes, we really need a wider range, like when calculating distances or
dot products
- negating INT_MIN. Here, we cast to int64_t temporarily. Note that if the
result is 32-bit wide, no 64-bit code may actually need to be generated.
- shifting into a signed integer's sign bit. We cast to uint32 here.
- in hitscan(), at the "abyss crash prevention code" comment, it's clearly
the other code that is better...
This is not merely done for pedantry, but rather makes it easier to track down
overflow bugs having a real impact on the game.
git-svn-id: https://svn.eduke32.com/eduke32@2784 1a8010ca-5511-0410-912e-c29ae57300e0
2012-06-26 19:49:53 +00:00
|
|
|
// OV: E2L10
|
2014-08-23 10:28:18 +00:00
|
|
|
coord_t temp = (coord_t)x1*y2-(coord_t)x2*y1;
|
2015-01-04 18:45:00 +00:00
|
|
|
int32_t tempint = temp;
|
Integer Overflow Offensive continued: first round of -ftrapv - cleanness.
That is, "clang -ftrapv" builds don't abort almost immediately after entering
a level.
There are various classes of overflow bugs, needing different handling:
- Some texture mapping code was written with signed integer wrapping semantics
in mind. In some places, we're able to get away with unsigned casts.
- sometimes, we really need a wider range, like when calculating distances or
dot products
- negating INT_MIN. Here, we cast to int64_t temporarily. Note that if the
result is 32-bit wide, no 64-bit code may actually need to be generated.
- shifting into a signed integer's sign bit. We cast to uint32 here.
- in hitscan(), at the "abyss crash prevention code" comment, it's clearly
the other code that is better...
This is not merely done for pedantry, but rather makes it easier to track down
overflow bugs having a real impact on the game.
git-svn-id: https://svn.eduke32.com/eduke32@2784 1a8010ca-5511-0410-912e-c29ae57300e0
2012-06-26 19:49:53 +00:00
|
|
|
if (((uint64_t)tempint+262144) < 524288) // BXY_MAX?
|
2007-12-12 17:42:14 +00:00
|
|
|
if (mulscale5(tempint,tempint) <= (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
|
2015-01-04 18:45:03 +00:00
|
|
|
{
|
2006-04-13 20:47:06 +00:00
|
|
|
sectorborder[sectorbordercnt++] = nextsectnum;
|
2015-01-04 18:45:03 +00:00
|
|
|
gotsector[nextsectnum>>3] |= pow2char[nextsectnum&7];
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2015-01-04 18:45:00 +00:00
|
|
|
#endif
|
2015-02-11 05:21:53 +00:00
|
|
|
p1 = (w == startwall || wall[w - 1].point2 != w) ? get_rel_coords(x1, y1) : p2;
|
2015-01-04 18:45:00 +00:00
|
|
|
p2 = get_rel_coords(x2, y2);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-01-04 18:45:00 +00:00
|
|
|
if (p1.y < 256 && p2.y < 256)
|
|
|
|
goto skipitaddwall;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-01-04 18:45:00 +00:00
|
|
|
// If wall's NOT facing you
|
|
|
|
if (dmulscale32(p1.x, p2.y, -p2.x, p1.y) >= 0)
|
|
|
|
goto skipitaddwall;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-03-21 09:28:01 +00:00
|
|
|
if (numscans >= MAXWALLSB-1)
|
|
|
|
{
|
|
|
|
OSD_Printf("!!numscans\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-01-04 18:45:00 +00:00
|
|
|
if (get_screen_coords(p1, p2, &xb1[numscans], &yb1[numscans], &xb2[numscans], &yb2[numscans]))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-01-04 18:45:00 +00:00
|
|
|
// Made it all the way!
|
|
|
|
thesector[numscans] = sectnum; thewall[numscans] = w;
|
|
|
|
rx1[numscans] = p1.x; ry1[numscans] = p1.y;
|
|
|
|
rx2[numscans] = p2.x; ry2[numscans] = p2.y;
|
|
|
|
bunchp2[numscans] = numscans+1;
|
|
|
|
numscans++;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2011-04-14 20:48:08 +00:00
|
|
|
skipitaddwall:
|
2015-01-04 18:45:00 +00:00
|
|
|
if (wall[w].point2 < w && scanfirst < numscans)
|
2014-09-30 04:14:21 +00:00
|
|
|
bunchp2[numscans-1] = scanfirst, scanfirst = numscans;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t s=onumscans; s<numscans; s++)
|
2015-01-04 18:45:00 +00:00
|
|
|
if (wall[thewall[s]].point2 != thewall[bunchp2[s]] || xb2[s] >= xb1[bunchp2[s]])
|
2011-04-28 21:28:33 +00:00
|
|
|
{
|
2015-01-04 18:45:00 +00:00
|
|
|
bunchfirst[numbunches++] = bunchp2[s], bunchp2[s] = -1;
|
2011-04-28 21:28:33 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (scansector_retfast)
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t bn=onumbunches; bn<numbunches; bn++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-01-04 18:45:00 +00:00
|
|
|
int32_t s;
|
|
|
|
for (s=bunchfirst[bn]; bunchp2[s]>=0; s=bunchp2[s])
|
|
|
|
/* do nothing */;
|
|
|
|
bunchlast[bn] = s;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (sectorbordercnt > 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2015-01-04 18:45:03 +00:00
|
|
|
#if DEBUGGINGAIDS >= 2
|
|
|
|
// Printing functions for collected scans (called "wall proxies" by
|
|
|
|
// http://fabiensanglard.net/duke3d/build_engine_internals.php) and
|
|
|
|
// bunches. For use from within the debugger.
|
|
|
|
|
|
|
|
void printscans(void)
|
|
|
|
{
|
|
|
|
static uint8_t didscan[(MAXWALLSB+7)>>3];
|
|
|
|
|
|
|
|
Bmemset(didscan, 0, sizeof(didscan));
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t s=0; s<numscans; s++)
|
2015-01-04 18:45:03 +00:00
|
|
|
{
|
2019-08-04 02:51:50 +00:00
|
|
|
if (bunchp2[s] >= 0 && (didscan[s>>3] & pow2char[s&7])==0)
|
2015-01-04 18:45:03 +00:00
|
|
|
{
|
|
|
|
printf("scan ");
|
|
|
|
|
|
|
|
int z = s;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
const int cond = (wall[thewall[z]].point2 != thewall[bunchp2[z]] ||
|
|
|
|
xb2[z] >= xb1[bunchp2[z]]);
|
|
|
|
|
|
|
|
printf("%s%d(%d) ", cond ? "!" : "", z, thewall[z]);
|
|
|
|
|
2019-08-04 02:51:50 +00:00
|
|
|
if (didscan[z>>3] & pow2char[z&7])
|
2015-01-04 18:45:03 +00:00
|
|
|
{
|
|
|
|
printf("*");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-08-04 02:51:50 +00:00
|
|
|
didscan[z>>3] |= pow2char[z&7];
|
2015-01-04 18:45:03 +00:00
|
|
|
z = bunchp2[z];
|
|
|
|
} while (z >= 0);
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void printbunches(void)
|
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t bn=0; bn<numbunches; bn++)
|
2015-01-04 18:45:03 +00:00
|
|
|
{
|
|
|
|
printf("bunch %d: ", bn);
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t s=bunchfirst[bn]; s>=0; s=bunchp2[s])
|
2015-01-04 18:45:03 +00:00
|
|
|
printf("%d(%d) ", s, thewall[s]);
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2013-02-14 16:02:06 +00:00
|
|
|
|
|
|
|
////////// *WALLSCAN HELPERS //////////
|
|
|
|
|
|
|
|
#define WSHELPER_DECL inline //ATTRIBUTE((always_inline))
|
|
|
|
|
2019-06-25 11:28:09 +00:00
|
|
|
static WSHELPER_DECL void tweak_tsizes(vec2_16_t *tsiz)
|
2013-02-14 16:02:06 +00:00
|
|
|
{
|
2014-09-30 04:14:21 +00:00
|
|
|
if (pow2long[picsiz[globalpicnum]&15] == tsiz->x)
|
|
|
|
tsiz->x--;
|
2013-02-14 16:02:06 +00:00
|
|
|
else
|
2014-09-30 04:14:21 +00:00
|
|
|
tsiz->x = -tsiz->x;
|
2013-02-14 16:02:06 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
if (pow2long[picsiz[globalpicnum]>>4] == tsiz->y)
|
|
|
|
tsiz->y = (picsiz[globalpicnum]>>4);
|
2013-02-14 16:02:06 +00:00
|
|
|
else
|
2014-09-30 04:14:21 +00:00
|
|
|
tsiz->y = -tsiz->y;
|
2013-02-14 16:02:06 +00:00
|
|
|
}
|
|
|
|
|
2019-06-25 11:28:09 +00:00
|
|
|
static WSHELPER_DECL void calc_bufplc(intptr_t *bufplc, int32_t lw, vec2_16_t tsiz)
|
2013-02-14 16:02:06 +00:00
|
|
|
{
|
2014-02-02 10:50:44 +00:00
|
|
|
// CAUTION: lw can be negative!
|
2013-02-14 16:02:06 +00:00
|
|
|
int32_t i = lw + globalxpanning;
|
|
|
|
|
2014-02-02 10:50:44 +00:00
|
|
|
// if (i >= tsizx)
|
2013-02-14 16:02:06 +00:00
|
|
|
{
|
2014-09-30 04:14:21 +00:00
|
|
|
if (tsiz.x < 0)
|
|
|
|
i = (uint32_t)i % -tsiz.x;
|
2013-02-14 16:02:06 +00:00
|
|
|
else
|
2014-09-30 04:14:21 +00:00
|
|
|
i &= tsiz.x;
|
2013-02-14 16:02:06 +00:00
|
|
|
}
|
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
if (tsiz.y < 0)
|
|
|
|
i *= -tsiz.y;
|
2013-02-14 16:02:06 +00:00
|
|
|
else
|
2014-09-30 04:14:21 +00:00
|
|
|
i <<= tsiz.y;
|
2013-02-14 16:02:06 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
// Bassert(i >= 0 && i < tilesiz[globalpicnum].x*tilesiz[globalpicnum].y);
|
2014-02-02 15:56:09 +00:00
|
|
|
|
2013-02-14 16:02:06 +00:00
|
|
|
// Address is at the first row of tile storage (which is column-major).
|
|
|
|
*bufplc = waloff[globalpicnum] + i;
|
|
|
|
}
|
|
|
|
|
2014-08-23 10:28:18 +00:00
|
|
|
static WSHELPER_DECL void calc_vplcinc_wall(uint32_t *vplc, int32_t *vinc, inthi_t sw, int32_t y1v)
|
2013-02-14 16:02:06 +00:00
|
|
|
{
|
|
|
|
*vinc = sw*globalyscale;
|
|
|
|
*vplc = globalzd + (uint32_t)(*vinc)*(y1v-globalhoriz+1);
|
|
|
|
}
|
|
|
|
|
2013-02-14 16:02:12 +00:00
|
|
|
#ifdef HIGH_PRECISION_SPRITE
|
|
|
|
static WSHELPER_DECL void calc_vplcinc_sprite(uint32_t *vplc, int32_t *vinc, int32_t x, int32_t y1v)
|
|
|
|
{
|
2017-07-22 04:00:30 +00:00
|
|
|
inthi_t const tmpvinc = inthi_rintf(swallf[x]);
|
2015-07-17 00:12:40 +00:00
|
|
|
inthi_t const tmpvplc = globalzd + tmpvinc*(y1v-globalhoriz+1);
|
2013-02-14 16:02:12 +00:00
|
|
|
|
|
|
|
*vinc = tmpvinc;
|
|
|
|
// Clamp the vertical texture coordinate!
|
2018-10-25 23:31:40 +00:00
|
|
|
*vplc = min<inthi_t>(max<inthi_t>(0, tmpvplc), UINT32_MAX);
|
2013-02-14 16:02:12 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int32_t drawing_sprite = 0;
|
|
|
|
|
|
|
|
static WSHELPER_DECL void calc_vplcinc(uint32_t *vplc, int32_t *vinc, const int32_t *swal, int32_t x, int32_t y1v)
|
|
|
|
{
|
|
|
|
#if !defined HIGH_PRECISION_SPRITE
|
|
|
|
(void)drawing_sprite;
|
|
|
|
#else
|
|
|
|
if (drawing_sprite)
|
|
|
|
calc_vplcinc_sprite(vplc, vinc, x, y1v);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
calc_vplcinc_wall(vplc, vinc, swal[x], y1v);
|
|
|
|
}
|
|
|
|
|
2012-09-28 15:20:03 +00:00
|
|
|
#undef NONPOW2_YSIZE_ASM
|
2012-09-28 15:20:13 +00:00
|
|
|
#if !defined ENGINE_USING_A_C
|
|
|
|
# if defined CLASSIC_NONPOW2_YSIZE_WALLS || defined CLASSIC_NONPOW2_YSIZE_SPRITES
|
|
|
|
# define NONPOW2_YSIZE_ASM
|
|
|
|
# endif
|
2012-09-28 15:20:03 +00:00
|
|
|
#endif
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// maskwallscan (internal)
|
|
|
|
//
|
2013-11-16 18:47:11 +00:00
|
|
|
static void maskwallscan(int32_t x1, int32_t x2, int32_t saturatevplc)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-07-17 00:12:40 +00:00
|
|
|
if (globalshiftval < 0) return;
|
2013-02-14 16:01:59 +00:00
|
|
|
if ((uwall[x1] > ydimen) && (uwall[x2] > ydimen)) return;
|
|
|
|
if ((dwall[x1] < 0) && (dwall[x2] < 0)) return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-06-25 11:28:09 +00:00
|
|
|
vec2_16_t tsiz = tilesiz[globalpicnum];
|
2015-07-17 00:12:40 +00:00
|
|
|
if ((tsiz.x <= 0) || (tsiz.y <= 0)) return;
|
|
|
|
|
|
|
|
setgotpic(globalpicnum);
|
|
|
|
|
2018-04-12 21:03:30 +00:00
|
|
|
if (waloff[globalpicnum] == 0) tileLoad(globalpicnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
tweak_tsizes(&tsiz);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-10-25 03:36:34 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(palookup[globalpal] == NULL))
|
2006-11-20 04:56:22 +00:00
|
|
|
globalpal = 0;
|
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
intptr_t const fpalookup = FP_OFF(palookup[globalpal]);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-11-16 18:47:11 +00:00
|
|
|
setupmvlineasm(globalshiftval, saturatevplc);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t x = x1;
|
2016-06-21 00:34:18 +00:00
|
|
|
while ((x <= x2) && (startumost[x+windowxy1.x] > startdmost[x+windowxy1.x]))
|
2013-02-10 16:24:15 +00:00
|
|
|
x++;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
intptr_t p = x+frameoffset;
|
|
|
|
|
|
|
|
int32_t y1ve[4], y2ve[4];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-09-28 15:20:03 +00:00
|
|
|
#ifdef NONPOW2_YSIZE_ASM
|
2012-07-06 11:27:49 +00:00
|
|
|
if (globalshiftval==0)
|
|
|
|
goto do_mvlineasm1;
|
|
|
|
#endif
|
|
|
|
|
2012-12-23 13:59:56 +00:00
|
|
|
#ifdef MULTI_COLUMN_VLINE
|
2009-02-19 16:47:54 +00:00
|
|
|
for (; (x<=x2)&&(p&3); x++,p++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-10-16 06:09:54 +00:00
|
|
|
y1ve[0] = max<int>(uwall[x],startumost[x+windowxy1.x]-windowxy1.y);
|
|
|
|
y2ve[0] = min<int>(dwall[x],startdmost[x+windowxy1.x]-windowxy1.y);
|
2006-04-13 20:47:06 +00:00
|
|
|
if (y2ve[0] <= y1ve[0]) continue;
|
|
|
|
|
2013-02-14 16:01:59 +00:00
|
|
|
palookupoffse[0] = fpalookup + getpalookupsh(mulscale16(swall[x],globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
calc_bufplc(&bufplce[0], lwall[x], tsiz);
|
2013-02-14 16:02:12 +00:00
|
|
|
calc_vplcinc(&vplce[0], &vince[0], swall, x, y1ve[0]);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-02-14 16:02:06 +00:00
|
|
|
mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0],p+ylookup[y1ve[0]]);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2009-02-19 16:47:54 +00:00
|
|
|
for (; x<=x2-3; x+=4,p+=4)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-07-17 00:12:40 +00:00
|
|
|
char bad = 0;
|
2012-12-23 13:59:56 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t z=3,dax=x+3; z>=0; z--,dax--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-10-16 06:09:54 +00:00
|
|
|
y1ve[z] = max<int>(uwall[dax],startumost[dax+windowxy1.x]-windowxy1.y);
|
|
|
|
y2ve[z] = min<int>(dwall[dax],startdmost[dax+windowxy1.x]-windowxy1.y)-1;
|
2006-04-13 20:47:06 +00:00
|
|
|
if (y2ve[z] < y1ve[z]) { bad += pow2char[z]; continue; }
|
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
calc_bufplc(&bufplce[z], lwall[dax], tsiz);
|
2013-02-14 16:02:12 +00:00
|
|
|
calc_vplcinc(&vplce[z], &vince[z], swall, dax, y1ve[z]);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
if (bad == 15) continue;
|
|
|
|
|
2013-02-14 16:01:59 +00:00
|
|
|
palookupoffse[0] = fpalookup + getpalookupsh(mulscale16(swall[x],globvis));
|
|
|
|
palookupoffse[3] = fpalookup + getpalookupsh(mulscale16(swall[x+3],globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
|
|
|
|
{
|
|
|
|
palookupoffse[1] = palookupoffse[0];
|
|
|
|
palookupoffse[2] = palookupoffse[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-02-14 16:01:59 +00:00
|
|
|
palookupoffse[1] = fpalookup + getpalookupsh(mulscale16(swall[x+1],globvis));
|
|
|
|
palookupoffse[2] = fpalookup + getpalookupsh(mulscale16(swall[x+2],globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t const u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
|
|
|
|
int32_t const d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2012-11-04 23:03:26 +00:00
|
|
|
if (d4 >= u4) mvlineasm4(d4-u4+1, (char *)(ylookup[u4]+p));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
intptr_t const pp = p+ylookup[d4+1];
|
|
|
|
|
2012-03-18 23:16:57 +00:00
|
|
|
if (y2ve[0] > d4) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],pp+0);
|
|
|
|
if (y2ve[1] > d4) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],pp+1);
|
|
|
|
if (y2ve[2] > d4) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],pp+2);
|
|
|
|
if (y2ve[3] > d4) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],pp+3);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-12-23 13:59:56 +00:00
|
|
|
#endif
|
|
|
|
|
2012-09-28 15:20:03 +00:00
|
|
|
#ifdef NONPOW2_YSIZE_ASM
|
2012-07-06 11:27:49 +00:00
|
|
|
do_mvlineasm1:
|
|
|
|
#endif
|
2009-02-19 16:47:54 +00:00
|
|
|
for (; x<=x2; x++,p++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-10-16 06:09:54 +00:00
|
|
|
y1ve[0] = max<int>(uwall[x],startumost[x+windowxy1.x]-windowxy1.y);
|
|
|
|
y2ve[0] = min<int>(dwall[x],startdmost[x+windowxy1.x]-windowxy1.y);
|
2006-04-13 20:47:06 +00:00
|
|
|
if (y2ve[0] <= y1ve[0]) continue;
|
|
|
|
|
2013-02-14 16:01:59 +00:00
|
|
|
palookupoffse[0] = fpalookup + getpalookupsh(mulscale16(swall[x],globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
calc_bufplc(&bufplce[0], lwall[x], tsiz);
|
2013-02-14 16:02:12 +00:00
|
|
|
calc_vplcinc(&vplce[0], &vince[0], swall, x, y1ve[0]);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-09-28 15:20:03 +00:00
|
|
|
#ifdef NONPOW2_YSIZE_ASM
|
2012-07-06 11:27:49 +00:00
|
|
|
if (globalshiftval==0)
|
2013-02-14 16:02:06 +00:00
|
|
|
mvlineasm1nonpow2(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0],p+ylookup[y1ve[0]]);
|
2012-07-06 11:27:49 +00:00
|
|
|
else
|
|
|
|
#endif
|
2013-02-14 16:02:06 +00:00
|
|
|
mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0],p+ylookup[y1ve[0]]);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
faketimerhandler();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// wallfront (internal)
|
|
|
|
//
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t wallfront(int32_t l1, int32_t l2)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-06-25 11:28:25 +00:00
|
|
|
vec2_t const l1vect = wall[thewall[l1]].pos;
|
|
|
|
vec2_t const l1p2vect = wall[wall[thewall[l1]].point2].pos;
|
|
|
|
vec2_t const l2vect = wall[thewall[l2]].pos;
|
|
|
|
vec2_t const l2p2vect = wall[wall[thewall[l2]].point2].pos;
|
2015-03-24 00:40:48 +00:00
|
|
|
vec2_t d = { l1p2vect.x - l1vect.x, l1p2vect.y - l1vect.y };
|
|
|
|
int32_t t1 = dmulscale2(l2vect.x-l1vect.x, d.y, -d.x, l2vect.y-l1vect.y); //p1(l2) vs. l1
|
|
|
|
int32_t t2 = dmulscale2(l2p2vect.x-l1vect.x, d.y, -d.x, l2p2vect.y-l1vect.y); //p2(l2) vs. l1
|
2014-10-25 03:34:25 +00:00
|
|
|
|
|
|
|
if (t1 == 0) { if (t2 == 0) return -1; t1 = t2; }
|
|
|
|
if (t2 == 0) t2 = t1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-10-25 03:34:25 +00:00
|
|
|
if ((t1^t2) >= 0) //pos vs. l1
|
2015-03-24 00:40:48 +00:00
|
|
|
return (dmulscale2(globalposx-l1vect.x, d.y, -d.x, globalposy-l1vect.y) ^ t1) >= 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
d.x = l2p2vect.x-l2vect.x;
|
|
|
|
d.y = l2p2vect.y-l2vect.y;
|
2014-10-25 03:34:25 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
t1 = dmulscale2(l1vect.x-l2vect.x, d.y, -d.x, l1vect.y-l2vect.y); //p1(l1) vs. l2
|
|
|
|
t2 = dmulscale2(l1p2vect.x-l2vect.x, d.y, -d.x, l1p2vect.y-l2vect.y); //p2(l1) vs. l2
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-10-25 03:34:25 +00:00
|
|
|
if (t1 == 0) { if (t2 == 0) return -1; t1 = t2; }
|
2006-04-13 20:47:06 +00:00
|
|
|
if (t2 == 0) t2 = t1;
|
|
|
|
|
2014-10-25 03:34:25 +00:00
|
|
|
if ((t1^t2) >= 0) //pos vs. l2
|
2015-03-24 00:40:48 +00:00
|
|
|
return (dmulscale2(globalposx-l2vect.x,d.y,-d.x,globalposy-l2vect.y) ^ t1) < 0;
|
2014-10-25 03:34:25 +00:00
|
|
|
|
|
|
|
return -2;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// spritewallfront (internal)
|
|
|
|
//
|
2019-04-18 17:25:24 +00:00
|
|
|
static inline int32_t spritewallfront(uspriteptr_t s, int32_t w)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const wal = (uwallptr_t)&wall[w];
|
|
|
|
auto const wal2 = (uwallptr_t)&wall[wal->point2];
|
2015-03-24 00:40:48 +00:00
|
|
|
const vec2_t v = { wal->x, wal->y };
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
return dmulscale32(wal2->x - v.x, s->y - v.y, -(s->x - v.x), wal2->y - v.y) >= 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// spritebehindwall(internal)
|
|
|
|
//
|
2008-03-22 10:23:57 +00:00
|
|
|
#if 0
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t spriteobstructswall(spritetype *s, int32_t w)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
walltype *wal;
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t x, y;
|
|
|
|
int32_t x1, y1;
|
|
|
|
int32_t x2, y2;
|
2006-04-13 20:47:06 +00:00
|
|
|
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));
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
// 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;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
// 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);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
// distance between the intersection point and the player
|
|
|
|
d2 = (x * x + y * y);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
// 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)))
|
2016-06-21 00:34:41 +00:00
|
|
|
return 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
2016-06-21 00:34:41 +00:00
|
|
|
return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2008-03-22 10:23:57 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// bunchfront (internal)
|
|
|
|
//
|
2009-02-02 01:49:14 +00:00
|
|
|
static inline int32_t bunchfront(int32_t b1, int32_t b2)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
int b1f = bunchfirst[b1];
|
|
|
|
int const x1b1 = xb1[b1f];
|
|
|
|
int const x2b2 = xb2[bunchlast[b2]] + 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (x1b1 >= x2b2)
|
2016-06-21 00:34:41 +00:00
|
|
|
return -1;
|
2015-03-24 00:40:48 +00:00
|
|
|
|
|
|
|
int b2f = bunchfirst[b2];
|
|
|
|
int const x1b2 = xb1[b2f];
|
|
|
|
int const x2b1 = xb2[bunchlast[b1]] + 1;
|
|
|
|
|
|
|
|
if (x1b2 >= x2b1)
|
2016-06-21 00:34:41 +00:00
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (x1b1 >= x1b2)
|
|
|
|
{
|
2016-01-12 10:31:12 +00:00
|
|
|
for (; xb2[b2f] < x1b1; b2f = bunchp2[b2f]) { }
|
2015-03-24 00:40:48 +00:00
|
|
|
return wallfront(b1f, b2f);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2015-03-24 00:40:48 +00:00
|
|
|
|
2016-01-12 10:31:12 +00:00
|
|
|
for (; xb2[b1f] < x1b2; b1f = bunchp2[b1f]) { }
|
2015-03-24 00:40:48 +00:00
|
|
|
return wallfront(b1f, b2f);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// hline (internal)
|
|
|
|
//
|
2009-02-02 01:49:14 +00:00
|
|
|
static inline void hline(int32_t xr, int32_t yp)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t const xl = lastx[yp];
|
|
|
|
if (xl > xr) return;
|
|
|
|
int32_t const r = horizlookup2[yp-globalhoriz+horizycent];
|
2019-06-25 11:29:46 +00:00
|
|
|
asm1 = (inthi_t)mulscale6(globalx1, r);
|
|
|
|
asm2 = (inthi_t)mulscale6(globaly2, r);
|
|
|
|
int32_t const s = getpalookupsh(mulscale22(r,globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-06-25 11:29:46 +00:00
|
|
|
hlineasm4(xr-xl,0,s,(uint32_t)mulscale6(globalx2,r)+globalypanning,(uint32_t)mulscale6(globaly1,r)+globalxpanning,
|
2006-04-24 19:04:22 +00:00
|
|
|
ylookup[yp]+xr+frameoffset);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// slowhline (internal)
|
|
|
|
//
|
2009-02-02 01:49:14 +00:00
|
|
|
static inline void slowhline(int32_t xr, int32_t yp)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t const xl = lastx[yp]; if (xl > xr) return;
|
|
|
|
int32_t const r = horizlookup2[yp-globalhoriz+horizycent];
|
2019-06-25 11:29:46 +00:00
|
|
|
asm1 = (inthi_t)mulscale6(globalx1, r);
|
|
|
|
asm2 = (inthi_t)mulscale6(globaly2, r);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-06-25 11:29:46 +00:00
|
|
|
asm3 = (intptr_t)globalpalwritten + getpalookupsh(mulscale22(r,globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
if (!(globalorientation&256))
|
|
|
|
{
|
2019-06-25 11:29:46 +00:00
|
|
|
mhline(globalbufplc,(uint32_t)mulscale6(globaly1,r)+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,
|
|
|
|
(uint32_t)mulscale6(globalx2,r)+globalypanning-asm2*(xr-xl),ylookup[yp]+xl+frameoffset);
|
2006-04-13 20:47:06 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-06-25 11:29:46 +00:00
|
|
|
thline(globalbufplc,(uint32_t)mulscale6(globaly1,r)+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,
|
|
|
|
(uint32_t)mulscale6(globalx2,r)+globalypanning-asm2*(xr-xl),ylookup[yp]+xl+frameoffset);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// prepwall (internal)
|
|
|
|
//
|
2019-04-18 17:25:24 +00:00
|
|
|
static void prepwall(int32_t z, uwallptr_t wal)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-06-05 22:21:26 +00:00
|
|
|
int32_t l=0, ol=0, x;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-06-05 22:21:26 +00:00
|
|
|
int32_t walxrepeat = (wal->xrepeat<<3);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//lwall calculation
|
2012-06-05 22:21:26 +00:00
|
|
|
int32_t tmpx = xb1[z]-halfxdimen;
|
|
|
|
|
|
|
|
const int32_t topinc = -(ry1[z]>>2);
|
|
|
|
const int32_t botinc = (ry2[z]-ry1[z])>>8;
|
|
|
|
int32_t top = mulscale5(rx1[z],xdimen) + mulscale2(topinc,tmpx);
|
|
|
|
int32_t bot = mulscale11(rx1[z]-rx2[z],xdimen) + mulscale2(botinc,tmpx);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-06-05 22:21:26 +00:00
|
|
|
const int32_t splc = mulscale19(ry1[z],xdimscale);
|
|
|
|
const int32_t sinc = mulscale16(ry2[z]-ry1[z],xdimscale);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
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])
|
|
|
|
{
|
2012-06-05 22:21:26 +00:00
|
|
|
int32_t i;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
|
|
|
}
|
2012-06-05 22:21:26 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
|
|
|
}
|
2012-06-05 22:21:26 +00:00
|
|
|
lwall[x+1] = (l+ol)>>19;
|
|
|
|
swall[x+1] = (swall[x]+swall[x+2])>>1;
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-05 22:21:26 +00:00
|
|
|
if (lwall[xb1[z]] < 0)
|
|
|
|
lwall[xb1[z]] = 0;
|
|
|
|
if (lwall[xb2[z]] >= walxrepeat && walxrepeat)
|
|
|
|
lwall[xb2[z]] = walxrepeat-1;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (wal->cstat&8)
|
|
|
|
{
|
|
|
|
walxrepeat--;
|
2012-06-05 22:21:26 +00:00
|
|
|
for (x=xb1[z]; x<=xb2[z]; x++)
|
|
|
|
lwall[x] = walxrepeat-lwall[x];
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// animateoffs (internal)
|
|
|
|
//
|
2019-09-19 20:02:45 +00:00
|
|
|
int32_t (*animateoffs_replace)(int const tilenum, int fakevar) = NULL;
|
|
|
|
int32_t animateoffs(int const tilenum, int fakevar)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-09-19 20:02:45 +00:00
|
|
|
if (animateoffs_replace)
|
|
|
|
{
|
|
|
|
return animateoffs_replace(tilenum, fakevar);
|
|
|
|
}
|
|
|
|
|
2015-01-11 04:55:07 +00:00
|
|
|
int const animnum = picanm[tilenum].num;
|
2008-03-22 10:23:57 +00:00
|
|
|
|
2014-10-29 17:04:28 +00:00
|
|
|
if (animnum <= 0)
|
|
|
|
return 0;
|
2012-11-17 19:46:28 +00:00
|
|
|
|
2019-08-27 13:39:54 +00:00
|
|
|
int const i = (int) totalclocklock >> (picanm[tilenum].sf & PICANM_ANIMSPEED_MASK);
|
2015-01-11 04:55:07 +00:00
|
|
|
int offs = 0;
|
2014-10-29 17:04:28 +00:00
|
|
|
|
|
|
|
switch (picanm[tilenum].sf & PICANM_ANIMTYPE_MASK)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-11-17 19:46:28 +00:00
|
|
|
case PICANM_ANIMTYPE_OSC:
|
2015-01-11 04:55:07 +00:00
|
|
|
{
|
|
|
|
int k = (i % (animnum << 1));
|
2014-10-29 17:04:28 +00:00
|
|
|
offs = (k < animnum) ? k : (animnum << 1) - k;
|
2015-01-11 04:55:07 +00:00
|
|
|
}
|
|
|
|
break;
|
2014-10-29 17:04:28 +00:00
|
|
|
case PICANM_ANIMTYPE_FWD: offs = i % (animnum + 1); break;
|
|
|
|
case PICANM_ANIMTYPE_BACK: offs = -(i % (animnum + 1)); break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-11-17 19:46:28 +00:00
|
|
|
|
2014-10-29 17:04:28 +00:00
|
|
|
return offs;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-05 11:28:06 +00:00
|
|
|
static inline void wallmosts_finish(int16_t *mostbuf, int32_t z1, int32_t z2,
|
|
|
|
int32_t ix1, int32_t iy1, int32_t ix2, int32_t iy2)
|
|
|
|
{
|
|
|
|
const int32_t y = scale(z1, xdimenscale, iy1)<<4;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
// enable for paranoia:
|
2018-07-14 21:36:44 +00:00
|
|
|
ix1 = clamp(ix1, 0, xdim-1);
|
|
|
|
ix2 = clamp(ix2, 0, xdim-1);
|
2014-04-05 11:28:06 +00:00
|
|
|
if (ix2-ix1 < 0)
|
|
|
|
swaplong(&ix1, &ix2);
|
|
|
|
#endif
|
2015-01-11 04:55:07 +00:00
|
|
|
// PK 20110423: a bit consistency checking is a good thing:
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t const tmp = (ix2 - ix1 >= 0) ? (ix2 - ix1 + 1) : 1;
|
|
|
|
int32_t const yinc = tabledivide32((scale(z2, xdimenscale, iy2) << 4) - y, tmp);
|
2014-04-05 11:28:06 +00:00
|
|
|
|
2015-01-11 04:55:07 +00:00
|
|
|
qinterpolatedown16short((intptr_t)&mostbuf[ix1], tmp, y + (globalhoriz << 16), yinc);
|
2014-04-05 11:28:06 +00:00
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
mostbuf[ix1] = clamp(mostbuf[ix1], 0, ydimen);
|
|
|
|
mostbuf[ix2] = clamp(mostbuf[ix2], 0, ydimen);
|
2014-04-05 11:28:06 +00:00
|
|
|
}
|
|
|
|
|
2015-02-07 17:29:10 +00:00
|
|
|
#ifdef CLASSIC_Z_DIFF_64
|
|
|
|
typedef int64_t zint_t;
|
|
|
|
|
2015-02-19 17:41:53 +00:00
|
|
|
// For drawvox()
|
2017-02-25 08:15:53 +00:00
|
|
|
static FORCE_INLINE zint_t mulscale16z(int32_t a, int32_t d)
|
2015-02-19 17:41:53 +00:00
|
|
|
{
|
|
|
|
return ((zint_t)a * d)>>16;
|
|
|
|
}
|
|
|
|
|
2017-02-25 08:15:53 +00:00
|
|
|
static FORCE_INLINE zint_t mulscale20z(int32_t a, int32_t d)
|
2015-02-07 17:29:10 +00:00
|
|
|
{
|
|
|
|
return ((zint_t)a * d)>>20;
|
|
|
|
}
|
|
|
|
|
2017-02-25 08:15:53 +00:00
|
|
|
static FORCE_INLINE zint_t dmulscale24z(int32_t a, int32_t d, int32_t S, int32_t D)
|
2015-02-07 17:29:10 +00:00
|
|
|
{
|
|
|
|
return (((zint_t)a * d) + ((zint_t)S * D)) >> 24;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
typedef int32_t zint_t;
|
2015-02-19 17:41:53 +00:00
|
|
|
# define mulscale16z mulscale16
|
2015-02-07 17:29:10 +00:00
|
|
|
# define mulscale20z mulscale20
|
|
|
|
# define dmulscale24z dmulscale24
|
|
|
|
#endif
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// owallmost (internal)
|
|
|
|
//
|
2015-02-07 17:29:10 +00:00
|
|
|
static int32_t owallmost(int16_t *mostbuf, int32_t w, zint_t z)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
z <<= 7;
|
2015-02-07 17:29:10 +00:00
|
|
|
const zint_t s1 = mulscale20z(globaluclip,yb1[w]), s2 = mulscale20z(globaluclip,yb2[w]);
|
|
|
|
const zint_t s3 = mulscale20z(globaldclip,yb1[w]), s4 = mulscale20z(globaldclip,yb2[w]);
|
2015-02-07 17:29:08 +00:00
|
|
|
const int32_t bad = (z<s1)+((z<s2)<<1)+((z>s3)<<2)+((z>s4)<<3);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-07 17:29:08 +00:00
|
|
|
int32_t ix1 = xb1[w], iy1 = yb1[w];
|
|
|
|
int32_t ix2 = xb2[w], iy2 = yb2[w];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((bad&3) == 3)
|
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=ix1; i<=ix2; i++)
|
2014-04-05 11:28:06 +00:00
|
|
|
mostbuf[i] = 0;
|
|
|
|
return bad;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((bad&12) == 12)
|
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=ix1; i<=ix2; i++)
|
2014-04-05 11:28:06 +00:00
|
|
|
mostbuf[i] = ydimen;
|
|
|
|
return bad;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bad&3)
|
|
|
|
{
|
2015-02-07 17:29:08 +00:00
|
|
|
int32_t t = divscale30(z-s1,s2-s1);
|
|
|
|
int32_t inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
|
|
|
|
int32_t xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((bad&3) == 2)
|
|
|
|
{
|
|
|
|
if (xb1[w] <= xcross) { iy2 = inty; ix2 = xcross; }
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=xcross+1; i<=xb2[w]; i++)
|
2014-04-05 11:28:06 +00:00
|
|
|
mostbuf[i] = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (xcross <= xb2[w]) { iy1 = inty; ix1 = xcross; }
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=xb1[w]; i<=xcross; i++)
|
2014-04-05 11:28:06 +00:00
|
|
|
mostbuf[i] = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bad&12)
|
|
|
|
{
|
2015-02-07 17:29:08 +00:00
|
|
|
int32_t t = divscale30(z-s3,s4-s3);
|
|
|
|
int32_t inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
|
|
|
|
int32_t xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((bad&12) == 8)
|
|
|
|
{
|
|
|
|
if (xb1[w] <= xcross) { iy2 = inty; ix2 = xcross; }
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=xcross+1; i<=xb2[w]; i++)
|
2014-04-05 11:28:06 +00:00
|
|
|
mostbuf[i] = ydimen;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (xcross <= xb2[w]) { iy1 = inty; ix1 = xcross; }
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=xb1[w]; i<=xcross; i++)
|
2014-04-05 11:28:06 +00:00
|
|
|
mostbuf[i] = ydimen;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-05 11:28:06 +00:00
|
|
|
wallmosts_finish(mostbuf, z, z, ix1, iy1, ix2, iy2);
|
2011-04-25 19:50:08 +00:00
|
|
|
|
2014-04-05 11:28:06 +00:00
|
|
|
return bad;
|
|
|
|
}
|
2011-04-25 19:50:08 +00:00
|
|
|
|
2015-02-07 17:29:10 +00:00
|
|
|
static inline zint_t wallmost_getz(int32_t fw, int32_t t, zint_t z,
|
|
|
|
int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
|
|
|
int32_t xv, int32_t yv, int32_t dx, int32_t dy)
|
2014-04-05 11:28:06 +00:00
|
|
|
{
|
|
|
|
// XXX: OVERFLOW with huge sectors and sloped ceilngs/floors!
|
|
|
|
int32_t i = xv*(y1-globalposy) - yv*(x1-globalposx);
|
|
|
|
const int32_t j = yv*x2 - xv*y2;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-04-05 11:28:06 +00:00
|
|
|
if (klabs(j) > klabs(i>>3))
|
|
|
|
i = divscale28(i,j);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-07 17:29:10 +00:00
|
|
|
return dmulscale24z(dx*t, mulscale20z(y2,i)+((y1-wall[fw].y)<<8),
|
|
|
|
-dy*t, mulscale20z(x2,i)+((x1-wall[fw].x)<<8)) + ((z-globalposz)<<7);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// wallmost (internal)
|
|
|
|
//
|
2010-06-07 09:03:16 +00:00
|
|
|
static int32_t wallmost(int16_t *mostbuf, int32_t w, int32_t sectnum, char dastat)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-02-07 17:29:08 +00:00
|
|
|
int32_t t, z;
|
|
|
|
int32_t xv, yv;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (dastat == 0)
|
|
|
|
{
|
|
|
|
z = sector[sectnum].ceilingz-globalposz;
|
2014-04-05 11:28:06 +00:00
|
|
|
if ((sector[sectnum].ceilingstat&2) == 0)
|
|
|
|
return owallmost(mostbuf,w,z);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
z = sector[sectnum].floorz-globalposz;
|
2014-04-05 11:28:06 +00:00
|
|
|
if ((sector[sectnum].floorstat&2) == 0)
|
|
|
|
return owallmost(mostbuf,w,z);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2015-02-07 17:29:08 +00:00
|
|
|
const int wi = thewall[w];
|
|
|
|
if (wi == sector[sectnum].wallptr)
|
2014-04-05 11:28:06 +00:00
|
|
|
return owallmost(mostbuf,w,z);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const wal = (uwallptr_t)&wall[wi];
|
2015-02-07 17:29:08 +00:00
|
|
|
const int32_t x1 = wal->x, x2 = wall[wal->point2].x-x1;
|
|
|
|
const int32_t y1 = wal->y, y2 = wall[wal->point2].y-y1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-07 17:29:08 +00:00
|
|
|
const int w1 = sector[sectnum].wallptr, w2 = wall[w1].point2;
|
|
|
|
const int32_t dx = wall[w2].x-wall[w1].x, dy = wall[w2].y-wall[w1].y;
|
|
|
|
const int32_t dasqr = krecipasm(nsqrtasm(uhypsq(dx,dy)));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (dastat == 0)
|
|
|
|
{
|
2014-04-05 11:28:06 +00:00
|
|
|
t = mulscale15(sector[sectnum].ceilingheinum, dasqr);
|
|
|
|
z = sector[sectnum].ceilingz;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
t = mulscale15(sector[sectnum].floorheinum,dasqr);
|
2014-04-05 11:28:06 +00:00
|
|
|
z = sector[sectnum].floorz;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2014-04-05 11:28:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (xb1[w] == 0)
|
|
|
|
{ xv = cosglobalang+sinviewingrangeglobalang; yv = singlobalang-cosviewingrangeglobalang; }
|
|
|
|
else
|
|
|
|
{ xv = x1-globalposx; yv = y1-globalposy; }
|
2015-02-07 17:29:10 +00:00
|
|
|
zint_t z1 = wallmost_getz(w1, t, z, x1, y1, x2, y2, xv, yv, dx, dy);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (xb2[w] == xdimen-1)
|
2007-12-12 17:42:14 +00:00
|
|
|
{ xv = cosglobalang-sinviewingrangeglobalang; yv = singlobalang+cosviewingrangeglobalang; }
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
2007-12-12 17:42:14 +00:00
|
|
|
{ xv = (x2+x1)-globalposx; yv = (y2+y1)-globalposy; }
|
2015-02-07 17:29:10 +00:00
|
|
|
zint_t z2 = wallmost_getz(w1, t, z, x1, y1, x2, y2, xv, yv, dx, dy);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
|
2015-02-07 17:29:10 +00:00
|
|
|
const zint_t s1 = mulscale20(globaluclip,yb1[w]), s2 = mulscale20(globaluclip,yb2[w]);
|
|
|
|
const zint_t s3 = mulscale20(globaldclip,yb1[w]), s4 = mulscale20(globaldclip,yb2[w]);
|
2015-02-07 17:29:08 +00:00
|
|
|
const int32_t bad = (z1<s1)+((z2<s2)<<1)+((z1>s3)<<2)+((z2>s4)<<3);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-07 17:29:08 +00:00
|
|
|
int32_t ix1 = xb1[w], ix2 = xb2[w];
|
|
|
|
int32_t iy1 = yb1[w], iy2 = yb2[w];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((bad&3) == 3)
|
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=ix1; i<=ix2; i++)
|
2014-04-05 11:28:06 +00:00
|
|
|
mostbuf[i] = 0;
|
|
|
|
return bad;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((bad&12) == 12)
|
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=ix1; i<=ix2; i++)
|
2014-04-05 11:28:06 +00:00
|
|
|
mostbuf[i] = ydimen;
|
|
|
|
return bad;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2015-02-07 17:29:10 +00:00
|
|
|
const int32_t oz1 = z1, oz2 = z2;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (bad&3)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
//inty = intz / (globaluclip>>16)
|
2006-04-13 20:47:06 +00:00
|
|
|
t = divscale30(oz1-s1,s2-s1+oz1-oz2);
|
2015-02-07 17:29:08 +00:00
|
|
|
int32_t inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
|
|
|
|
int32_t intz = oz1 + mulscale30(oz2-oz1,t);
|
|
|
|
int32_t xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//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; }
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=xcross+1; i<=xb2[w]; i++)
|
2014-04-05 11:28:06 +00:00
|
|
|
mostbuf[i] = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (xcross <= xb2[w]) { z1 = intz; iy1 = inty; ix1 = xcross; }
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=xb1[w]; i<=xcross; i++)
|
2014-04-05 11:28:06 +00:00
|
|
|
mostbuf[i] = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bad&12)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
//inty = intz / (globaldclip>>16)
|
2006-04-13 20:47:06 +00:00
|
|
|
t = divscale30(oz1-s3,s4-s3+oz1-oz2);
|
2015-02-07 17:29:08 +00:00
|
|
|
int32_t inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
|
|
|
|
int32_t intz = oz1 + mulscale30(oz2-oz1,t);
|
|
|
|
int32_t xcross = xb1[w] + scale(mulscale30(yb2[w],t),xb2[w]-xb1[w],inty);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//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; }
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=xcross+1; i<=xb2[w]; i++)
|
2014-04-05 11:28:06 +00:00
|
|
|
mostbuf[i] = ydimen;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (xcross <= xb2[w]) { z1 = intz; iy1 = inty; ix1 = xcross; }
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=xb1[w]; i<=xcross; i++)
|
2014-04-05 11:28:06 +00:00
|
|
|
mostbuf[i] = ydimen;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-05 11:28:06 +00:00
|
|
|
wallmosts_finish(mostbuf, z1, z2, ix1, iy1, ix2, iy2);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-04-05 11:28:06 +00:00
|
|
|
return bad;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2014-04-05 11:28:06 +00:00
|
|
|
|
2012-12-14 19:28:14 +00:00
|
|
|
// globalpicnum --> globalxshift, globalyshift
|
|
|
|
static void calc_globalshifts(void)
|
|
|
|
{
|
|
|
|
globalxshift = (8-(picsiz[globalpicnum]&15));
|
|
|
|
globalyshift = (8-(picsiz[globalpicnum]>>4));
|
|
|
|
if (globalorientation&8) { globalxshift++; globalyshift++; }
|
|
|
|
// PK: the following can happen for large (>= 512) tile sizes.
|
|
|
|
// NOTE that global[xy]shift are unsigned chars.
|
|
|
|
if (globalxshift > 31) globalxshift=0;
|
|
|
|
if (globalyshift > 31) globalyshift=0;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
static int32_t setup_globals_cf1(usectorptr_t sec, int32_t pal, int32_t zd,
|
2012-03-25 13:54:31 +00:00
|
|
|
int32_t picnum, int32_t shade, int32_t stat,
|
|
|
|
int32_t xpanning, int32_t ypanning, int32_t x1)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-09-08 01:01:40 +00:00
|
|
|
int32_t i;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-03-25 13:54:31 +00:00
|
|
|
if (palookup[pal] != globalpalwritten)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-03-25 13:54:31 +00:00
|
|
|
globalpalwritten = palookup[pal];
|
2006-04-13 20:47:06 +00:00
|
|
|
if (!globalpalwritten) globalpalwritten = palookup[globalpal]; // JBF: fixes null-pointer crash
|
|
|
|
setpalookupaddress(globalpalwritten);
|
|
|
|
}
|
|
|
|
|
2012-03-25 13:54:31 +00:00
|
|
|
globalzd = zd;
|
|
|
|
if (globalzd > 0) return 1;
|
|
|
|
|
|
|
|
globalpicnum = picnum;
|
|
|
|
if ((unsigned)globalpicnum >= MAXTILES) globalpicnum = 0;
|
2019-06-25 11:30:22 +00:00
|
|
|
tileUpdatePicnum(&globalpicnum, 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
setgotpic(globalpicnum);
|
2014-09-30 04:14:21 +00:00
|
|
|
if ((tilesiz[globalpicnum].x <= 0) || (tilesiz[globalpicnum].y <= 0)) return 1;
|
2018-04-12 21:03:30 +00:00
|
|
|
if (waloff[globalpicnum] == 0) tileLoad(globalpicnum);
|
2016-08-27 01:42:07 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
globalbufplc = waloff[globalpicnum];
|
|
|
|
|
2012-03-25 13:54:31 +00:00
|
|
|
globalshade = shade;
|
2006-04-13 20:47:06 +00:00
|
|
|
globvis = globalcisibility;
|
2012-12-14 19:28:05 +00:00
|
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis, (uint8_t)(sec->visibility+16));
|
2012-03-25 13:54:31 +00:00
|
|
|
globalorientation = stat;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((globalorientation&64) == 0)
|
|
|
|
{
|
|
|
|
globalx1 = singlobalang; globalx2 = singlobalang;
|
|
|
|
globaly1 = cosglobalang; globaly2 = cosglobalang;
|
2014-08-23 10:28:18 +00:00
|
|
|
globalxpanning = ((inthi_t)globalposx<<20);
|
|
|
|
globalypanning = -((inthi_t)globalposy<<20);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-09-08 01:01:40 +00:00
|
|
|
vec2_t const xy = { wall[wall[sec->wallptr].point2].x - wall[sec->wallptr].x,
|
|
|
|
wall[wall[sec->wallptr].point2].y - wall[sec->wallptr].y };
|
|
|
|
i = nsqrtasm(uhypsq(xy.x,xy.y)); if (i == 0) i = 1024; else i = tabledivide32(1048576, i);
|
|
|
|
int const wcos = mulscale6(xy.x, i), wsin = mulscale6(xy.y, i);
|
|
|
|
globalx1 = dmulscale14(wcos,singlobalang,-wsin,cosglobalang);
|
|
|
|
globaly1 = dmulscale14(wcos,cosglobalang,wsin,singlobalang);
|
2006-04-13 20:47:06 +00:00
|
|
|
globalx2 = -globalx1;
|
|
|
|
globaly2 = -globaly1;
|
|
|
|
|
2019-09-08 01:01:40 +00:00
|
|
|
globalxpanning = (coord_t)((globalposx - wall[sec->wallptr].x)<<6) * wcos + (coord_t)((globalposy - wall[sec->wallptr].y)<<6) * wsin;
|
|
|
|
globalypanning = (coord_t)((globalposy - wall[sec->wallptr].y)<<6) * wcos - (coord_t)((globalposx - wall[sec->wallptr].x)<<6) * wsin;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
globalx2 = mulscale16(globalx2,viewingrangerecip);
|
|
|
|
globaly1 = mulscale16(globaly1,viewingrangerecip);
|
2012-12-14 19:28:14 +00:00
|
|
|
|
|
|
|
calc_globalshifts();
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((globalorientation&0x4) > 0)
|
|
|
|
{
|
|
|
|
i = globalxpanning; globalxpanning = globalypanning; globalypanning = i;
|
|
|
|
i = globalx2; globalx2 = -globaly1; globaly1 = -i;
|
|
|
|
i = globalx1; globalx1 = globaly2; globaly2 = i;
|
|
|
|
}
|
2014-08-23 10:28:18 +00:00
|
|
|
if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalxpanning = -(inthi_t)globalxpanning;
|
|
|
|
if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalypanning = -(inthi_t)globalypanning;
|
2006-04-13 20:47:06 +00:00
|
|
|
globalx1 <<= globalxshift; globaly1 <<= globalxshift;
|
|
|
|
globalx2 <<= globalyshift; globaly2 <<= globalyshift;
|
|
|
|
globalxpanning <<= globalxshift; globalypanning <<= globalyshift;
|
Integer Overflow Offensive continued: first round of -ftrapv - cleanness.
That is, "clang -ftrapv" builds don't abort almost immediately after entering
a level.
There are various classes of overflow bugs, needing different handling:
- Some texture mapping code was written with signed integer wrapping semantics
in mind. In some places, we're able to get away with unsigned casts.
- sometimes, we really need a wider range, like when calculating distances or
dot products
- negating INT_MIN. Here, we cast to int64_t temporarily. Note that if the
result is 32-bit wide, no 64-bit code may actually need to be generated.
- shifting into a signed integer's sign bit. We cast to uint32 here.
- in hitscan(), at the "abyss crash prevention code" comment, it's clearly
the other code that is better...
This is not merely done for pedantry, but rather makes it easier to track down
overflow bugs having a real impact on the game.
git-svn-id: https://svn.eduke32.com/eduke32@2784 1a8010ca-5511-0410-912e-c29ae57300e0
2012-06-26 19:49:53 +00:00
|
|
|
globalxpanning = (uint32_t)globalxpanning + (xpanning<<24);
|
|
|
|
globalypanning = (uint32_t)globalypanning + (ypanning<<24);
|
2006-04-13 20:47:06 +00:00
|
|
|
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));
|
|
|
|
|
2012-03-25 13:54:31 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// ceilscan (internal)
|
|
|
|
//
|
|
|
|
static void ceilscan(int32_t x1, int32_t x2, int32_t sectnum)
|
|
|
|
{
|
|
|
|
int32_t x, y1, y2;
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const sec = (usectorptr_t)§or[sectnum];
|
2012-03-25 13:54:31 +00:00
|
|
|
|
|
|
|
if (setup_globals_cf1(sec, sec->ceilingpal, sec->ceilingz-globalposz,
|
|
|
|
sec->ceilingpicnum, sec->ceilingshade, sec->ceilingstat,
|
|
|
|
sec->ceilingxpanning, sec->ceilingypanning, x1))
|
|
|
|
return;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (!(globalorientation&0x180))
|
|
|
|
{
|
|
|
|
y1 = umost[x1]; y2 = y1;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<=x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-01-18 23:16:37 +00:00
|
|
|
const int32_t twall = umost[x]-1;
|
|
|
|
const int32_t bwall = min(uplc[x],dmost[x]);
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2007-12-12 17:42:14 +00:00
|
|
|
if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
|
2006-04-13 20:47:06 +00:00
|
|
|
y1 = umost[x+1]; y2 = y1;
|
|
|
|
}
|
|
|
|
globalx2 += globaly2; globaly1 += globalx1;
|
|
|
|
}
|
|
|
|
while (y1 < y2-1) hline(x2,++y1);
|
|
|
|
faketimerhandler();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (globalorientation&0x180)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
case 128:
|
2012-02-18 17:55:27 +00:00
|
|
|
msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
|
2006-04-24 19:04:22 +00:00
|
|
|
break;
|
|
|
|
case 256:
|
2014-02-19 19:47:28 +00:00
|
|
|
setup_blend(0, 0);
|
2006-04-24 19:04:22 +00:00
|
|
|
tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
|
|
|
|
break;
|
|
|
|
case 384:
|
2019-03-19 17:09:03 +00:00
|
|
|
setup_blend(0, 1);
|
2006-04-24 19:04:22 +00:00
|
|
|
tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
|
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
y1 = umost[x1]; y2 = y1;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<=x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-01-18 23:16:37 +00:00
|
|
|
const int32_t twall = umost[x]-1;
|
|
|
|
const int32_t bwall = min(uplc[x],dmost[x]);
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2007-12-12 17:42:14 +00:00
|
|
|
if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
|
2006-04-13 20:47:06 +00:00
|
|
|
y1 = umost[x+1]; y2 = y1;
|
|
|
|
}
|
|
|
|
globalx2 += globaly2; globaly1 += globalx1;
|
|
|
|
}
|
|
|
|
while (y1 < y2-1) slowhline(x2,++y1);
|
|
|
|
faketimerhandler();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// florscan (internal)
|
|
|
|
//
|
2009-01-09 09:29:17 +00:00
|
|
|
static void florscan(int32_t x1, int32_t x2, int32_t sectnum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-03-25 13:54:31 +00:00
|
|
|
int32_t x, y1, y2;
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const sec = (usectorptr_t)§or[sectnum];
|
2012-03-25 13:54:31 +00:00
|
|
|
|
|
|
|
if (setup_globals_cf1(sec, sec->floorpal, globalposz-sec->floorz,
|
|
|
|
sec->floorpicnum, sec->floorshade, sec->floorstat,
|
|
|
|
sec->floorxpanning, sec->floorypanning, x1))
|
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (!(globalorientation&0x180))
|
|
|
|
{
|
|
|
|
y1 = max(dplc[x1],umost[x1]); y2 = y1;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<=x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-01-18 23:16:37 +00:00
|
|
|
const int32_t twall = max(dplc[x],umost[x])-1;
|
|
|
|
const int32_t bwall = dmost[x];
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2007-12-12 17:42:14 +00:00
|
|
|
if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
|
2006-04-13 20:47:06 +00:00
|
|
|
y1 = max(dplc[x+1],umost[x+1]); y2 = y1;
|
|
|
|
}
|
|
|
|
globalx2 += globaly2; globaly1 += globalx1;
|
|
|
|
}
|
|
|
|
while (y1 < y2-1) hline(x2,++y1);
|
|
|
|
faketimerhandler();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (globalorientation&0x180)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
case 128:
|
2012-02-18 17:55:27 +00:00
|
|
|
msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
|
2006-04-24 19:04:22 +00:00
|
|
|
break;
|
|
|
|
case 256:
|
2014-02-19 19:47:28 +00:00
|
|
|
setup_blend(0, 0);
|
2006-04-24 19:04:22 +00:00
|
|
|
tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
|
|
|
|
break;
|
|
|
|
case 384:
|
2014-02-19 19:47:28 +00:00
|
|
|
setup_blend(0, 1);
|
2006-04-24 19:04:22 +00:00
|
|
|
tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
|
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
y1 = max(dplc[x1],umost[x1]); y2 = y1;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<=x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-01-18 23:16:37 +00:00
|
|
|
const int32_t twall = max(dplc[x],umost[x])-1;
|
|
|
|
const int32_t bwall = dmost[x];
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2007-12-12 17:42:14 +00:00
|
|
|
if (x == x2) { globalx2 += globaly2; globaly1 += globalx1; break; }
|
2006-04-13 20:47:06 +00:00
|
|
|
y1 = max(dplc[x+1],umost[x+1]); y2 = y1;
|
|
|
|
}
|
|
|
|
globalx2 += globaly2; globaly1 += globalx1;
|
|
|
|
}
|
|
|
|
while (y1 < y2-1) slowhline(x2,++y1);
|
|
|
|
faketimerhandler();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// wallscan (internal)
|
|
|
|
//
|
2012-06-05 22:21:26 +00:00
|
|
|
static void wallscan(int32_t x1, int32_t x2,
|
|
|
|
const int16_t *uwal, const int16_t *dwal,
|
|
|
|
const int32_t *swal, const int32_t *lwal)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-02-14 16:02:06 +00:00
|
|
|
int32_t x;
|
2009-11-04 08:11:21 +00:00
|
|
|
intptr_t fpalookup;
|
2014-09-30 04:14:21 +00:00
|
|
|
int32_t y1ve[4], y2ve[4];
|
2019-06-25 11:28:09 +00:00
|
|
|
vec2_16_t tsiz;
|
2012-12-23 13:59:56 +00:00
|
|
|
#ifdef MULTI_COLUMN_VLINE
|
2006-04-13 20:47:06 +00:00
|
|
|
char bad;
|
2013-02-14 16:02:06 +00:00
|
|
|
int32_t u4, d4, z;
|
2012-03-18 23:16:57 +00:00
|
|
|
uintptr_t p;
|
2008-10-25 11:21:50 +00:00
|
|
|
#endif
|
2012-12-23 13:59:56 +00:00
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (g_nodraw)
|
|
|
|
return;
|
|
|
|
#endif
|
2012-07-06 14:16:31 +00:00
|
|
|
setgotpic(globalpicnum);
|
|
|
|
if (globalshiftval < 0)
|
|
|
|
return;
|
|
|
|
|
2014-11-22 18:37:21 +00:00
|
|
|
if (x2 >= xdim)
|
|
|
|
x2 = xdim-1;
|
|
|
|
assert((unsigned)x1 < (unsigned)xdim);
|
2007-08-16 23:25:24 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
tsiz = tilesiz[globalpicnum];
|
|
|
|
|
|
|
|
if ((tsiz.x <= 0) || (tsiz.y <= 0)) return;
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen)) return;
|
|
|
|
if ((dwal[x1] < 0) && (dwal[x2] < 0)) return;
|
|
|
|
|
2018-04-12 21:03:30 +00:00
|
|
|
if (waloff[globalpicnum] == 0) tileLoad(globalpicnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
tweak_tsizes(&tsiz);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
fpalookup = FP_OFF(palookup[globalpal]);
|
|
|
|
|
|
|
|
setupvlineasm(globalshiftval);
|
|
|
|
|
|
|
|
|
|
|
|
x = x1;
|
2014-11-22 18:37:21 +00:00
|
|
|
while ((x <= x2) && (umost[x] > dmost[x]))
|
|
|
|
x++;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-09-28 15:20:03 +00:00
|
|
|
#ifdef NONPOW2_YSIZE_ASM
|
2012-07-06 11:27:49 +00:00
|
|
|
if (globalshiftval==0)
|
|
|
|
goto do_vlineasm1;
|
|
|
|
#endif
|
|
|
|
|
2012-12-23 13:59:56 +00:00
|
|
|
#ifdef MULTI_COLUMN_VLINE
|
2009-02-19 16:47:54 +00:00
|
|
|
for (; (x<=x2)&&((x+frameoffset)&3); x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
y1ve[0] = max(uwal[x],umost[x]);
|
|
|
|
y2ve[0] = min(dwal[x],dmost[x]);
|
|
|
|
if (y2ve[0] <= y1ve[0]) continue;
|
|
|
|
|
2012-12-14 19:27:58 +00:00
|
|
|
palookupoffse[0] = fpalookup + getpalookupsh(mulscale16(swal[x],globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
calc_bufplc(&bufplce[0], lwal[x], tsiz);
|
2013-02-14 16:02:12 +00:00
|
|
|
calc_vplcinc(&vplce[0], &vince[0], swal, x, y1ve[0]);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-02-14 16:02:06 +00:00
|
|
|
vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0],x+frameoffset+ylookup[y1ve[0]]);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2009-02-19 16:47:54 +00:00
|
|
|
for (; x<=x2-3; x+=4)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
bad = 0;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=3; z>=0; z--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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; }
|
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
calc_bufplc(&bufplce[z], lwal[x+z], tsiz);
|
2013-02-14 16:02:12 +00:00
|
|
|
calc_vplcinc(&vplce[z], &vince[z], swal, x+z, y1ve[z]);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
if (bad == 15) continue;
|
|
|
|
|
2012-12-14 19:27:58 +00:00
|
|
|
palookupoffse[0] = fpalookup + getpalookupsh(mulscale16(swal[x],globvis));
|
|
|
|
palookupoffse[3] = fpalookup + getpalookupsh(mulscale16(swal[x+3],globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
|
|
|
|
{
|
|
|
|
palookupoffse[1] = palookupoffse[0];
|
|
|
|
palookupoffse[2] = palookupoffse[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-12-14 19:27:58 +00:00
|
|
|
palookupoffse[1] = fpalookup + getpalookupsh(mulscale16(swal[x+1],globvis));
|
|
|
|
palookupoffse[2] = fpalookup + getpalookupsh(mulscale16(swal[x+2],globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2012-11-04 23:03:26 +00:00
|
|
|
if (d4 >= u4) vlineasm4(d4-u4+1, (char *)(ylookup[u4]+x+frameoffset));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-03-18 23:16:57 +00:00
|
|
|
p = x+frameoffset+ylookup[d4+1];
|
|
|
|
if (y2ve[0] > d4) prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],p+0);
|
|
|
|
if (y2ve[1] > d4) prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],p+1);
|
|
|
|
if (y2ve[2] > d4) prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],p+2);
|
|
|
|
if (y2ve[3] > d4) prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],p+3);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-12-23 13:59:56 +00:00
|
|
|
#endif
|
|
|
|
|
2012-09-28 15:20:03 +00:00
|
|
|
#ifdef NONPOW2_YSIZE_ASM
|
2012-07-06 11:27:49 +00:00
|
|
|
do_vlineasm1:
|
|
|
|
#endif
|
2009-02-19 16:47:54 +00:00
|
|
|
for (; x<=x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
y1ve[0] = max(uwal[x],umost[x]);
|
|
|
|
y2ve[0] = min(dwal[x],dmost[x]);
|
|
|
|
if (y2ve[0] <= y1ve[0]) continue;
|
|
|
|
|
2012-12-14 19:27:58 +00:00
|
|
|
palookupoffse[0] = fpalookup + getpalookupsh(mulscale16(swal[x],globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
calc_bufplc(&bufplce[0], lwal[x], tsiz);
|
2013-02-14 16:02:12 +00:00
|
|
|
calc_vplcinc(&vplce[0], &vince[0], swal, x, y1ve[0]);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-09-28 15:20:03 +00:00
|
|
|
#ifdef NONPOW2_YSIZE_ASM
|
2012-07-06 11:27:49 +00:00
|
|
|
if (globalshiftval==0)
|
2013-02-14 16:02:06 +00:00
|
|
|
vlineasm1nonpow2(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0],x+frameoffset+ylookup[y1ve[0]]);
|
2012-07-06 11:27:49 +00:00
|
|
|
else
|
|
|
|
#endif
|
2013-02-14 16:02:06 +00:00
|
|
|
vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0],x+frameoffset+ylookup[y1ve[0]]);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
faketimerhandler();
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// transmaskvline (internal)
|
|
|
|
//
|
2009-01-09 09:29:17 +00:00
|
|
|
static void transmaskvline(int32_t x)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
if ((unsigned)x >= (unsigned)xdimen) return;
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2018-10-16 06:09:54 +00:00
|
|
|
int32_t const y1v = max<int>(uwall[x],startumost[x+windowxy1.x]-windowxy1.y);
|
|
|
|
int32_t const y2v = min<int>(dwall[x],startdmost[x+windowxy1.x]-windowxy1.y) - 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (y2v < y1v) return;
|
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
intptr_t palookupoffs = FP_OFF(palookup[globalpal]) + getpalookupsh(mulscale16(swall[x],globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-06-25 11:28:09 +00:00
|
|
|
vec2_16_t const ntsiz = { (int16_t)-tilesiz[globalpicnum].x, (int16_t)-tilesiz[globalpicnum].y };
|
2016-06-21 00:33:30 +00:00
|
|
|
intptr_t bufplc;
|
2014-09-30 04:14:21 +00:00
|
|
|
calc_bufplc(&bufplc, lwall[x], ntsiz);
|
2016-06-21 00:33:30 +00:00
|
|
|
uint32_t vplc;
|
|
|
|
int32_t vinc;
|
2013-02-14 16:02:12 +00:00
|
|
|
calc_vplcinc(&vplc, &vinc, swall, x, y1v);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
intptr_t p = ylookup[y1v]+x+frameoffset;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-09-28 15:20:03 +00:00
|
|
|
#ifdef NONPOW2_YSIZE_ASM
|
2012-07-06 11:27:49 +00:00
|
|
|
if (globalshiftval==0)
|
|
|
|
tvlineasm1nonpow2(vinc,palookupoffs,y2v-y1v,vplc,bufplc,p);
|
|
|
|
else
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
tvlineasm1(vinc,palookupoffs,y2v-y1v,vplc,bufplc,p);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// transmaskvline2 (internal)
|
|
|
|
//
|
2012-12-23 13:59:56 +00:00
|
|
|
#ifdef MULTI_COLUMN_VLINE
|
2009-01-09 09:29:17 +00:00
|
|
|
static void transmaskvline2(int32_t x)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
if ((unsigned)x >= (unsigned)xdimen) return;
|
2007-12-12 17:42:14 +00:00
|
|
|
if (x == xdimen-1) { transmaskvline(x); return; }
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t y1ve[2], y2ve[2];
|
|
|
|
int32_t x2 = x+1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-10-16 06:09:54 +00:00
|
|
|
y1ve[0] = max<int>(uwall[x],startumost[x+windowxy1.x]-windowxy1.y);
|
|
|
|
y2ve[0] = min<int>(dwall[x],startdmost[x+windowxy1.x]-windowxy1.y)-1;
|
2006-04-13 20:47:06 +00:00
|
|
|
if (y2ve[0] < y1ve[0]) { transmaskvline(x2); return; }
|
2018-10-16 06:09:54 +00:00
|
|
|
y1ve[1] = max<int>(uwall[x2],startumost[x2+windowxy1.x]-windowxy1.y);
|
|
|
|
y2ve[1] = min<int>(dwall[x2],startdmost[x2+windowxy1.x]-windowxy1.y)-1;
|
2006-04-13 20:47:06 +00:00
|
|
|
if (y2ve[1] < y1ve[1]) { transmaskvline(x); return; }
|
|
|
|
|
2012-12-14 19:27:58 +00:00
|
|
|
palookupoffse[0] = FP_OFF(palookup[globalpal]) + getpalookupsh(mulscale16(swall[x],globvis));
|
|
|
|
palookupoffse[1] = FP_OFF(palookup[globalpal]) + getpalookupsh(mulscale16(swall[x2],globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
setuptvlineasm2(globalshiftval,palookupoffse[0],palookupoffse[1]);
|
|
|
|
|
2019-06-25 11:28:09 +00:00
|
|
|
vec2_16_t const ntsiz = { (int16_t)-tilesiz[globalpicnum].x, (int16_t)-tilesiz[globalpicnum].y };
|
2014-09-30 04:14:21 +00:00
|
|
|
|
|
|
|
calc_bufplc(&bufplce[0], lwall[x], ntsiz);
|
|
|
|
calc_bufplc(&bufplce[1], lwall[x2], ntsiz);
|
2013-02-14 16:02:12 +00:00
|
|
|
calc_vplcinc(&vplce[0], &vince[0], swall, x, y1ve[0]);
|
|
|
|
calc_vplcinc(&vplce[1], &vince[1], swall, x2, y1ve[1]);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t const y1 = max(y1ve[0],y1ve[1]);
|
|
|
|
int32_t const y2 = min(y2ve[0],y2ve[1]);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
uintptr_t p = x+frameoffset;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (y1ve[0] != y1ve[1])
|
|
|
|
{
|
|
|
|
if (y1ve[0] < y1)
|
2012-03-11 17:36:49 +00:00
|
|
|
vplce[0] = tvlineasm1(vince[0],palookupoffse[0],y1-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+p);
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
2012-03-11 17:36:49 +00:00
|
|
|
vplce[1] = tvlineasm1(vince[1],palookupoffse[1],y1-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (y2 > y1)
|
|
|
|
{
|
|
|
|
asm1 = vince[1];
|
2012-03-11 17:36:49 +00:00
|
|
|
asm2 = ylookup[y2]+p+1;
|
|
|
|
tvlineasm2(vplce[1],vince[0],bufplce[0],bufplce[1],vplce[0],ylookup[y1]+p);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
asm1 = vplce[0];
|
|
|
|
asm2 = vplce[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (y2ve[0] > y2ve[1])
|
2012-03-11 17:36:49 +00:00
|
|
|
tvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y2-1,asm1,bufplce[0],ylookup[y2+1]+p);
|
2006-04-13 20:47:06 +00:00
|
|
|
else if (y2ve[0] < y2ve[1])
|
2012-03-11 17:36:49 +00:00
|
|
|
tvlineasm1(vince[1],palookupoffse[1],y2ve[1]-y2-1,asm2,bufplce[1],ylookup[y2+1]+p+1);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
faketimerhandler();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//
|
|
|
|
// transmaskwallscan (internal)
|
|
|
|
//
|
2013-11-16 18:47:11 +00:00
|
|
|
static void transmaskwallscan(int32_t x1, int32_t x2, int32_t saturatevplc)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
setgotpic(globalpicnum);
|
2012-07-06 14:16:31 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
Bassert(globalshiftval>=0 || ((tilesiz[globalpicnum].x <= 0) || (tilesiz[globalpicnum].y <= 0)));
|
2012-07-06 14:16:31 +00:00
|
|
|
// globalshiftval<0 implies following condition
|
2014-09-30 04:14:21 +00:00
|
|
|
if ((tilesiz[globalpicnum].x <= 0) || (tilesiz[globalpicnum].y <= 0))
|
2012-07-06 14:16:31 +00:00
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:03:30 +00:00
|
|
|
if (waloff[globalpicnum] == 0) tileLoad(globalpicnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-11-16 18:47:11 +00:00
|
|
|
setuptvlineasm(globalshiftval, saturatevplc);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t x = x1;
|
2016-06-21 00:34:18 +00:00
|
|
|
while ((x <= x2) && (startumost[x+windowxy1.x] > startdmost[x+windowxy1.x]))
|
2016-06-21 00:33:30 +00:00
|
|
|
++x;
|
2012-07-06 11:27:49 +00:00
|
|
|
|
|
|
|
#ifndef ENGINE_USING_A_C
|
|
|
|
if (globalshiftval==0)
|
|
|
|
{
|
2016-06-21 00:33:30 +00:00
|
|
|
while (x <= x2) transmaskvline(x++);
|
2012-07-06 11:27:49 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
2012-12-23 13:59:56 +00:00
|
|
|
#ifdef MULTI_COLUMN_VLINE
|
2016-06-21 00:33:30 +00:00
|
|
|
if ((x <= x2) && (x&1)) transmaskvline(x++);
|
2012-07-06 11:27:49 +00:00
|
|
|
while (x < x2) transmaskvline2(x), x += 2;
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
2016-06-21 00:33:30 +00:00
|
|
|
while (x <= x2) transmaskvline(x++);
|
2012-07-06 11:27:49 +00:00
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
faketimerhandler();
|
|
|
|
}
|
|
|
|
|
2012-02-27 19:40:01 +00:00
|
|
|
|
2011-04-14 20:48:08 +00:00
|
|
|
////////// NON-power-of-two replacements for mhline/thline, adapted from a.c //////////
|
2012-02-27 19:40:01 +00:00
|
|
|
#if defined(__GNUC__) && defined(__i386__) && !defined(NOASM)
|
|
|
|
// from pragmas.h
|
|
|
|
# define ourdivscale32(d,b) \
|
2017-12-09 02:56:31 +00:00
|
|
|
({ int32_t __d=(d), __b=(b), __r; \
|
|
|
|
__asm__ __volatile__ ("xorl %%eax, %%eax; divl %%ebx" \
|
|
|
|
: "=a" (__r), "=d" (__d) : "d" (__d), "b" (__b) : "cc"); \
|
|
|
|
__r; })
|
2012-02-27 19:40:01 +00:00
|
|
|
#else
|
|
|
|
# define ourdivscale32(d,b) divscale32(d,b)
|
|
|
|
#endif
|
|
|
|
|
2012-03-04 20:13:16 +00:00
|
|
|
// cntup16>>16 iterations
|
2014-10-25 03:29:21 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
static void nonpow2_mhline(intptr_t bufplc, uint32_t bx, int32_t cntup16, uint32_t by, char *p)
|
2011-04-14 20:48:08 +00:00
|
|
|
{
|
|
|
|
char ch;
|
|
|
|
|
2014-10-29 17:06:43 +00:00
|
|
|
const char *const A_C_RESTRICT buf = (char *)bufplc;
|
|
|
|
const char *const A_C_RESTRICT pal = (char *)asm3;
|
2011-04-14 20:48:08 +00:00
|
|
|
|
2019-03-02 23:21:05 +00:00
|
|
|
const uint32_t xmul = globalxspan;
|
|
|
|
const uint32_t ymul = globalyspan;
|
2012-03-04 20:13:16 +00:00
|
|
|
const uint32_t yspan = globalyspan;
|
|
|
|
const int32_t xinc = asm1, yinc = asm2;
|
2012-02-27 19:40:01 +00:00
|
|
|
|
2011-04-14 20:48:08 +00:00
|
|
|
for (cntup16>>=16; cntup16>0; cntup16--)
|
|
|
|
{
|
2019-03-02 23:21:05 +00:00
|
|
|
ch = buf[mulscale31(bx>>1, xmul)*yspan + mulscale31(by>>1, ymul)];
|
2012-03-04 20:13:16 +00:00
|
|
|
|
|
|
|
if (ch != 255) *p = pal[ch];
|
|
|
|
bx += xinc;
|
|
|
|
by += yinc;
|
2011-04-14 20:48:08 +00:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-04 20:13:16 +00:00
|
|
|
// cntup16>>16 iterations
|
2016-06-21 00:33:30 +00:00
|
|
|
static void nonpow2_thline(intptr_t bufplc, uint32_t bx, int32_t cntup16, uint32_t by, char *p)
|
2011-04-14 20:48:08 +00:00
|
|
|
{
|
|
|
|
char ch;
|
|
|
|
|
2014-10-29 17:06:43 +00:00
|
|
|
const char *const A_C_RESTRICT buf = (char *)bufplc;
|
|
|
|
const char *const A_C_RESTRICT pal = (char *)asm3;
|
2018-04-12 21:03:12 +00:00
|
|
|
const char *const A_C_RESTRICT trans = paletteGetBlendTable(globalblend);
|
2011-04-14 20:48:08 +00:00
|
|
|
|
2019-03-02 23:21:05 +00:00
|
|
|
const uint32_t xmul = globalxspan;
|
|
|
|
const uint32_t ymul = globalyspan;
|
2012-03-04 20:13:16 +00:00
|
|
|
const uint32_t yspan = globalyspan;
|
|
|
|
const int32_t xinc = asm1, yinc = asm2;
|
2012-02-27 19:40:01 +00:00
|
|
|
|
2011-04-14 20:48:08 +00:00
|
|
|
if (globalorientation&512)
|
|
|
|
{
|
|
|
|
for (cntup16>>=16; cntup16>0; cntup16--)
|
|
|
|
{
|
2019-03-02 23:21:05 +00:00
|
|
|
ch = buf[mulscale31(bx>>1, xmul)*yspan + mulscale31(by>>1, ymul)];
|
2012-03-04 20:13:16 +00:00
|
|
|
if (ch != 255) *p = trans[(*p)|(pal[ch]<<8)];
|
|
|
|
bx += xinc;
|
|
|
|
by += yinc;
|
2011-04-14 20:48:08 +00:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (cntup16>>=16; cntup16>0; cntup16--)
|
|
|
|
{
|
2019-03-02 23:21:05 +00:00
|
|
|
ch = buf[mulscale31(bx>>1, xmul)*yspan + mulscale31(by>>1, ymul)];
|
2012-03-04 20:13:16 +00:00
|
|
|
if (ch != 255) *p = trans[((*p)<<8)|pal[ch]];
|
|
|
|
bx += xinc;
|
|
|
|
by += yinc;
|
2011-04-14 20:48:08 +00:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
////////// END non-power-of-two replacements //////////
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// ceilspritehline (internal)
|
|
|
|
//
|
2014-10-25 03:30:38 +00:00
|
|
|
static void ceilspritehline(int32_t x2, int32_t y)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t x1, v, bx, by;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//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
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
x1 = lastx[y]; if (x2 < x1) return;
|
|
|
|
|
|
|
|
v = mulscale20(globalzd,horizlookup[y-globalhoriz+horizycent]);
|
Integer Overflow Offensive continued: first round of -ftrapv - cleanness.
That is, "clang -ftrapv" builds don't abort almost immediately after entering
a level.
There are various classes of overflow bugs, needing different handling:
- Some texture mapping code was written with signed integer wrapping semantics
in mind. In some places, we're able to get away with unsigned casts.
- sometimes, we really need a wider range, like when calculating distances or
dot products
- negating INT_MIN. Here, we cast to int64_t temporarily. Note that if the
result is 32-bit wide, no 64-bit code may actually need to be generated.
- shifting into a signed integer's sign bit. We cast to uint32 here.
- in hitscan(), at the "abyss crash prevention code" comment, it's clearly
the other code that is better...
This is not merely done for pedantry, but rather makes it easier to track down
overflow bugs having a real impact on the game.
git-svn-id: https://svn.eduke32.com/eduke32@2784 1a8010ca-5511-0410-912e-c29ae57300e0
2012-06-26 19:49:53 +00:00
|
|
|
bx = (uint32_t)mulscale14(globalx2*x1+globalx1,v) + globalxpanning;
|
|
|
|
by = (uint32_t)mulscale14(globaly2*x1+globaly1,v) + globalypanning;
|
2006-04-13 20:47:06 +00:00
|
|
|
asm1 = mulscale14(globalx2,v);
|
|
|
|
asm2 = mulscale14(globaly2,v);
|
|
|
|
|
2012-12-14 19:27:58 +00:00
|
|
|
asm3 = FP_OFF(palookup[globalpal]) + getpalookupsh(mulscale28(klabs(v),globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-04-14 20:48:08 +00:00
|
|
|
if (globalispow2)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
|
|
|
{
|
2011-04-14 20:48:08 +00:00
|
|
|
if ((globalorientation&2) == 0)
|
2016-06-21 00:33:30 +00:00
|
|
|
nonpow2_mhline(globalbufplc,bx,(x2-x1)<<16,by,(char *)(ylookup[y]+x1+frameoffset));
|
2011-04-14 20:48:08 +00:00
|
|
|
else
|
2016-06-21 00:33:30 +00:00
|
|
|
nonpow2_thline(globalbufplc,bx,(x2-x1)<<16,by,(char *)(ylookup[y]+x1+frameoffset));
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// ceilspritescan (internal)
|
|
|
|
//
|
2014-10-25 03:30:38 +00:00
|
|
|
static void ceilspritescan(int32_t x1, int32_t x2)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-12-13 22:32:57 +00:00
|
|
|
int32_t y1 = uwall[x1];
|
|
|
|
int32_t y2 = y1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t x=x1; x<=x2; ++x)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-12-13 22:32:57 +00:00
|
|
|
const int32_t twall = uwall[x]-1;
|
|
|
|
const int32_t bwall = dwall[x];
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2011-05-17 21:48:13 +00:00
|
|
|
////////// translucent slope vline, based on a-c.c's slopevlin //////////
|
|
|
|
static int32_t gglogx, gglogy, ggpinc;
|
|
|
|
static char *ggbuf, *ggpal;
|
|
|
|
|
2014-10-25 03:30:38 +00:00
|
|
|
#ifdef ENGINE_USING_A_C
|
2014-11-22 18:37:23 +00:00
|
|
|
extern int32_t gpinc;
|
2014-10-25 03:30:38 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static inline void setupslopevlin_alsotrans(int32_t logylogx, intptr_t bufplc, int32_t pinc)
|
2011-05-17 21:48:13 +00:00
|
|
|
{
|
2014-10-25 03:30:38 +00:00
|
|
|
#ifdef ENGINE_USING_A_C
|
2014-11-22 18:37:23 +00:00
|
|
|
sethlinesizes(logylogx&255, logylogx>>8, bufplc);
|
|
|
|
gpinc = pinc;
|
2014-10-25 03:30:38 +00:00
|
|
|
#else
|
2011-05-17 21:48:13 +00:00
|
|
|
setupslopevlin(logylogx, bufplc, pinc);
|
2014-10-25 03:30:38 +00:00
|
|
|
#endif
|
2011-05-17 21:48:13 +00:00
|
|
|
gglogx = (logylogx&255); gglogy = (logylogx>>8);
|
|
|
|
ggbuf = (char *)bufplc; ggpinc = pinc;
|
2012-12-14 19:27:58 +00:00
|
|
|
ggpal = palookup[globalpal] + getpalookupsh(0);
|
2011-05-17 21:48:13 +00:00
|
|
|
}
|
|
|
|
|
2012-03-04 20:12:46 +00:00
|
|
|
// cnt iterations
|
2016-08-27 01:41:21 +00:00
|
|
|
static void tslopevlin(uint8_t *p, const intptr_t *slopalptr, bssize_t cnt, int32_t bx, int32_t by)
|
2011-05-17 21:48:13 +00:00
|
|
|
{
|
2014-10-29 17:06:43 +00:00
|
|
|
const char *const A_C_RESTRICT buf = ggbuf;
|
2018-04-12 21:03:12 +00:00
|
|
|
const char *const A_C_RESTRICT trans = paletteGetBlendTable(0);
|
2012-03-04 20:12:46 +00:00
|
|
|
const int32_t bzinc = (asm1>>3), pinc = ggpinc;
|
2011-05-17 21:48:13 +00:00
|
|
|
|
2012-03-04 20:12:46 +00:00
|
|
|
const int32_t transmode = (globalorientation&128);
|
Integer Overflow Offensive continued: first round of -ftrapv - cleanness.
That is, "clang -ftrapv" builds don't abort almost immediately after entering
a level.
There are various classes of overflow bugs, needing different handling:
- Some texture mapping code was written with signed integer wrapping semantics
in mind. In some places, we're able to get away with unsigned casts.
- sometimes, we really need a wider range, like when calculating distances or
dot products
- negating INT_MIN. Here, we cast to int64_t temporarily. Note that if the
result is 32-bit wide, no 64-bit code may actually need to be generated.
- shifting into a signed integer's sign bit. We cast to uint32 here.
- in hitscan(), at the "abyss crash prevention code" comment, it's clearly
the other code that is better...
This is not merely done for pedantry, but rather makes it easier to track down
overflow bugs having a real impact on the game.
git-svn-id: https://svn.eduke32.com/eduke32@2784 1a8010ca-5511-0410-912e-c29ae57300e0
2012-06-26 19:49:53 +00:00
|
|
|
const uint32_t xtou = globalx3, ytov = globaly3;
|
2012-03-04 20:12:46 +00:00
|
|
|
const int32_t logx = gglogx, logy = gglogy;
|
2011-05-17 21:48:13 +00:00
|
|
|
|
2012-03-04 20:12:46 +00:00
|
|
|
int32_t bz = asm3;
|
2011-05-17 21:48:13 +00:00
|
|
|
|
2012-03-04 20:12:46 +00:00
|
|
|
do
|
2011-05-17 21:48:13 +00:00
|
|
|
{
|
2019-06-25 11:30:03 +00:00
|
|
|
int const i = (sloptable[(bz>>6)+HALFSLOPTABLESIZ]); bz += bzinc;
|
2016-06-21 00:33:30 +00:00
|
|
|
uint32_t u = bx + xtou*i;
|
|
|
|
uint32_t v = by + ytov*i;
|
2019-03-19 17:09:03 +00:00
|
|
|
uint8_t ch = buf[((u>>(32-logx))<<logy)+(v>>(32-logy))];
|
|
|
|
if (ch != 255)
|
|
|
|
{
|
|
|
|
ch = *(uint8_t *)(slopalptr[0] + ch);
|
|
|
|
*p = trans[transmode ? *p|(ch<<8) : (*p<<8)|ch];
|
|
|
|
}
|
|
|
|
|
|
|
|
slopalptr--;
|
|
|
|
p += pinc;
|
|
|
|
}
|
|
|
|
while (--cnt);
|
|
|
|
}
|
|
|
|
|
|
|
|
// cnt iterations
|
|
|
|
static void mslopevlin(uint8_t *p, const intptr_t *slopalptr, bssize_t cnt, int32_t bx, int32_t by)
|
|
|
|
{
|
|
|
|
const char *const A_C_RESTRICT buf = ggbuf;
|
|
|
|
const int32_t bzinc = (asm1>>3), pinc = ggpinc;
|
2012-02-16 19:24:59 +00:00
|
|
|
|
2019-03-19 17:09:03 +00:00
|
|
|
const uint32_t xtou = globalx3, ytov = globaly3;
|
|
|
|
const int32_t logx = gglogx, logy = gglogy;
|
|
|
|
|
|
|
|
int32_t bz = asm3;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2019-06-25 11:30:03 +00:00
|
|
|
int const i = (sloptable[(bz>>6)+HALFSLOPTABLESIZ]); bz += bzinc;
|
2019-03-19 17:09:03 +00:00
|
|
|
uint32_t u = bx + xtou*i;
|
|
|
|
uint32_t v = by + ytov*i;
|
|
|
|
uint8_t ch = buf[((u>>(32-logx))<<logy)+(v>>(32-logy))];
|
2014-10-25 03:29:21 +00:00
|
|
|
if (ch != 255)
|
2019-03-19 17:09:03 +00:00
|
|
|
*p = *(uint8_t *)(slopalptr[0] + ch);
|
2011-05-17 21:48:13 +00:00
|
|
|
|
|
|
|
slopalptr--;
|
2012-03-04 20:12:46 +00:00
|
|
|
p += pinc;
|
2011-05-17 21:48:13 +00:00
|
|
|
}
|
2012-03-04 20:12:46 +00:00
|
|
|
while (--cnt);
|
2011-05-17 21:48:13 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// grouscan (internal)
|
|
|
|
//
|
|
|
|
#define BITSOFPRECISION 3 //Don't forget to change this in A.ASM also!
|
2019-07-06 16:30:18 +00:00
|
|
|
static void fgrouscan(int32_t dax1, int32_t dax2, int32_t sectnum, char dastat)
|
|
|
|
{
|
2019-08-01 06:50:33 +00:00
|
|
|
int32_t i, j, l, globalx1, globaly1, y1, y2, daslope, daz, wxi, wyi;
|
2019-07-06 16:30:18 +00:00
|
|
|
float fi, wx, wy, dasqr;
|
|
|
|
float globalx, globaly, globalx2, globaly2, globalx3, globaly3, globalz, globalzd, globalzx;
|
|
|
|
int32_t shoffs, m1, m2;
|
|
|
|
intptr_t *mptr1, *mptr2;
|
|
|
|
|
|
|
|
const usectortype *const sec = (usectortype *)§or[sectnum];
|
|
|
|
const uwalltype *wal;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
tileUpdatePicnum(&globalpicnum, sectnum);
|
|
|
|
setgotpic(globalpicnum);
|
|
|
|
if ((tilesiz[globalpicnum].x <= 0) || (tilesiz[globalpicnum].y <= 0)) return;
|
|
|
|
if (waloff[globalpicnum] == 0) tileLoad(globalpicnum);
|
|
|
|
|
|
|
|
wal = (uwalltype *)&wall[sec->wallptr];
|
2019-08-01 06:50:33 +00:00
|
|
|
wxi = wall[wal->point2].x - wal->x;
|
|
|
|
wyi = wall[wal->point2].y - wal->y;
|
|
|
|
dasqr = 1073741824.f/nsqrtasm(uhypsq(wxi,wyi));
|
2019-07-06 16:30:18 +00:00
|
|
|
fi = daslope*dasqr*(1.f/2097152.f);
|
2019-08-01 06:50:33 +00:00
|
|
|
wx = wxi*fi; wy = wyi*fi;
|
2019-07-06 16:30:18 +00:00
|
|
|
|
|
|
|
globalx = -float(singlobalang)*float(xdimenrecip)*(1.f/524288.f);
|
|
|
|
globaly = float(cosglobalang)*float(xdimenrecip)*(1.f/524288.f);
|
|
|
|
globalx1 = globalposx<<8;
|
|
|
|
globaly1 = -globalposy<<8;
|
|
|
|
fi = (dax1-halfxdimen)*xdimenrecip;
|
|
|
|
globalx2 = float(cosglobalang)*float(viewingrangerecip)*(1.f/4096.f) - float(singlobalang)*fi*(1.f/134217728.f);
|
|
|
|
globaly2 = float(singlobalang)*float(viewingrangerecip)*(1.f/4096.f) + float(cosglobalang)*fi*(1.f/134217728.f);
|
|
|
|
globalzd = xdimscale*512.f;
|
|
|
|
globalzx = -(wx*globaly2-wy*globalx2)*(1.f/131072.f) + (1-globalhoriz)*globalzd*(1.f/1024.f);
|
|
|
|
globalz = -(wx*globaly-wy*globalx)*(1.f/33554432.f);
|
|
|
|
|
|
|
|
if (globalorientation&64) //Relative alignment
|
|
|
|
{
|
|
|
|
float dx, dy, x, y;
|
|
|
|
dx = (wall[wal->point2].x-wal->x)*dasqr*(1.f/16384.f);
|
|
|
|
dy = (wall[wal->point2].y-wal->y)*dasqr*(1.f/16384.f);
|
|
|
|
|
2019-08-01 06:50:33 +00:00
|
|
|
fi = float(nsqrtasm(daslope*daslope+16777216));
|
2019-07-06 16:30:18 +00:00
|
|
|
|
|
|
|
x = globalx; y = globaly;
|
|
|
|
globalx = (x*dx+y*dy)*(1.f/65536.f);
|
|
|
|
globaly = (-y*dx+x*dy)*fi*(1.f/268435456.f);
|
|
|
|
|
|
|
|
x = (wal->x-globalposx)*256.f; y = (wal->y-globalposy)*256.f;
|
|
|
|
globalx1 = Blrintf((-x*dx-y*dy)*(1.f/65536.f));
|
|
|
|
globaly1 = Blrintf((-y*dx+x*dy)*fi*(1.f/268435456.f));
|
|
|
|
|
|
|
|
x = globalx2; y = globaly2;
|
|
|
|
globalx2 = (x*dx+y*dy)*(1.f/65536.f);
|
|
|
|
globaly2 = (-y*dx+x*dy)*fi*(1.f/268435456.f);
|
|
|
|
}
|
|
|
|
if (globalorientation&0x4)
|
|
|
|
{
|
|
|
|
fi = globalx; globalx = -globaly; globaly = -fi;
|
|
|
|
i = globalx1; globalx1 = globaly1; globaly1 = i;
|
|
|
|
fi = globalx2; globalx2 = -globaly2; globaly2 = -fi;
|
|
|
|
}
|
|
|
|
if (globalorientation&0x10) { globalx1 = -globalx1, globalx2 = -globalx2, globalx = -globalx; }
|
|
|
|
if (globalorientation&0x20) { globaly1 = -globaly1, globaly2 = -globaly2, globaly = -globaly; }
|
|
|
|
|
|
|
|
float fdaz = (wx*(globalposy-wal->y)-wy*(globalposx-wal->x))*(1.f/512.f) + (daz-globalposz)*256.f;
|
|
|
|
globalx2 = (globalx2*fdaz)*(1.f/1048576.f); globalx = (globalx*fdaz)*(1.f/268435456.f);
|
|
|
|
globaly2 = (globaly2*-fdaz)*(1.f/1048576.f); globaly = (globaly*-fdaz)*(1.f/268435456.f);
|
|
|
|
|
|
|
|
i = 8-(picsiz[globalpicnum]&15); j = 8-(picsiz[globalpicnum]>>4);
|
|
|
|
if (globalorientation&8) { i++; j++; }
|
|
|
|
globalx1 <<= (i+12); globalx2 *= 1<<i; globalx *= 1<<i;
|
|
|
|
globaly1 <<= (j+12); globaly2 *= 1<<j; globaly *= 1<<j;
|
|
|
|
|
|
|
|
if (dastat == 0)
|
|
|
|
{
|
|
|
|
globalx1 += (uint32_t)sec->ceilingxpanning<<24;
|
|
|
|
globaly1 += (uint32_t)sec->ceilingypanning<<24;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
globalx1 += (uint32_t)sec->floorxpanning<<24;
|
|
|
|
globaly1 += (uint32_t)sec->floorypanning<<24;
|
|
|
|
}
|
|
|
|
|
|
|
|
globalx1 >>= 16;
|
|
|
|
globaly1 >>= 16;
|
|
|
|
|
|
|
|
//asm1 = -(globalzd>>(16-BITSOFPRECISION));
|
|
|
|
float bzinc = -globalzd*(1.f/65536.f);
|
|
|
|
|
|
|
|
{
|
|
|
|
int32_t vis = globalvisibility;
|
|
|
|
int64_t lvis;
|
|
|
|
|
|
|
|
if (sec->visibility != 0) vis = mulscale4(vis, (uint8_t)(sec->visibility+16));
|
|
|
|
lvis = ((uint64_t)(vis*fdaz)) >> 13; // NOTE: lvis can be negative now!
|
|
|
|
lvis = (lvis * xdimscale) >> 16;
|
|
|
|
globvis = lvis;
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t fj = FP_OFF(palookup[globalpal]);
|
|
|
|
|
|
|
|
setupslopevlin_alsotrans((picsiz[globalpicnum]&15) + ((picsiz[globalpicnum]>>4)<<8),
|
|
|
|
waloff[globalpicnum],-ylookup[1]);
|
|
|
|
|
|
|
|
l = Blrintf((globalzd)*(1.f/65536.f));
|
|
|
|
|
|
|
|
int32_t const shinc = Blrintf(globalz*xdimenscale*(1.f/65536.f));
|
|
|
|
|
|
|
|
shoffs = (shinc > 0) ? (4 << 15) : ((16380 - ydimen) << 15); // JBF: was 2044
|
|
|
|
y1 = (dastat == 0) ? umost[dax1] : max(umost[dax1], dplc[dax1]);
|
|
|
|
|
|
|
|
m1 = Blrintf((y1*globalzd)*(1.f/65536.f) + globalzx*(1.f/64.f));
|
|
|
|
//Avoid visibility overflow by crossing horizon
|
|
|
|
m1 += klabs(l);
|
|
|
|
m2 = m1+l;
|
|
|
|
mptr1 = (intptr_t *)&slopalookup[y1+(shoffs>>15)]; mptr2 = mptr1+1;
|
|
|
|
|
|
|
|
for (int 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)
|
|
|
|
{
|
|
|
|
intptr_t *nptr1 = &slopalookup[y1+(shoffs>>15)];
|
|
|
|
intptr_t *nptr2 = &slopalookup[y2+(shoffs>>15)];
|
|
|
|
|
|
|
|
while (nptr1 <= mptr1)
|
|
|
|
{
|
|
|
|
*mptr1-- = fj + getpalookupsh(mulscale24(krecipasm(m1),globvis));
|
|
|
|
m1 -= l;
|
|
|
|
}
|
|
|
|
while (nptr2 >= mptr2)
|
|
|
|
{
|
|
|
|
*mptr2++ = fj + getpalookupsh(mulscale24(krecipasm(m2),globvis));
|
|
|
|
m2 += l;
|
|
|
|
}
|
|
|
|
|
|
|
|
globalx3 = globalx2*(1.f/1024.f);
|
|
|
|
globaly3 = globaly2*(1.f/1024.f);
|
|
|
|
float bz = (y2*globalzd)*(1.f/65536.f) + globalzx*(1.f/64.f);
|
|
|
|
uint8_t *p = (uint8_t*)(ylookup[y2]+x+frameoffset);
|
|
|
|
intptr_t* A_C_RESTRICT slopalptr = (intptr_t*)nptr2;
|
|
|
|
const char* const A_C_RESTRICT trans = paletteGetBlendTable(0);
|
|
|
|
uint32_t u, v;
|
|
|
|
int cnt = y2-y1+1;
|
|
|
|
#define LINTERPSIZ 4
|
|
|
|
int u0 = Blrintf(1048576.f*globalx3/bz);
|
|
|
|
int v0 = Blrintf(1048576.f*globaly3/bz);
|
|
|
|
switch (globalorientation&0x180)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
while (cnt > 0)
|
|
|
|
{
|
|
|
|
bz += bzinc*(1<<LINTERPSIZ);
|
|
|
|
int u1 = Blrintf(1048576.f*globalx3/bz);
|
|
|
|
int v1 = Blrintf(1048576.f*globaly3/bz);
|
|
|
|
u1 = (u1-u0)>>LINTERPSIZ;
|
|
|
|
v1 = (v1-v0)>>LINTERPSIZ;
|
|
|
|
int cnt2 = min(cnt, 1<<LINTERPSIZ);
|
|
|
|
for (; cnt2>0; cnt2--)
|
|
|
|
{
|
|
|
|
u = (globalx1+u0)&0xffff;
|
|
|
|
v = (globaly1+v0)&0xffff;
|
|
|
|
*p = *(uint8_t *)(((intptr_t)slopalptr[0])+ggbuf[((u>>(16-gglogx))<<gglogy)+(v>>(16-gglogy))]);
|
|
|
|
slopalptr--;
|
|
|
|
p += ggpinc;
|
|
|
|
u0 += u1;
|
|
|
|
v0 += v1;
|
|
|
|
}
|
|
|
|
cnt -= 1<<LINTERPSIZ;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
while (cnt > 0)
|
|
|
|
{
|
|
|
|
bz += bzinc*(1<<LINTERPSIZ);
|
|
|
|
int u1 = Blrintf(1048576.f*globalx3/bz);
|
|
|
|
int v1 = Blrintf(1048576.f*globaly3/bz);
|
|
|
|
u1 = (u1-u0)>>LINTERPSIZ;
|
|
|
|
v1 = (v1-v0)>>LINTERPSIZ;
|
|
|
|
int cnt2 = min(cnt, 1<<LINTERPSIZ);
|
|
|
|
for (; cnt2>0; cnt2--)
|
|
|
|
{
|
|
|
|
u = (globalx1+u0)&0xffff;
|
|
|
|
v = (globaly1+v0)&0xffff;
|
|
|
|
uint8_t ch = ggbuf[((u>>(16-gglogx))<<gglogy)+(v>>(16-gglogy))];
|
|
|
|
if (ch != 255)
|
|
|
|
*p = *(uint8_t *)(((intptr_t)slopalptr[0])+ch);
|
|
|
|
slopalptr--;
|
|
|
|
p += ggpinc;
|
|
|
|
u0 += u1;
|
|
|
|
v0 += v1;
|
|
|
|
}
|
|
|
|
cnt -= 1<<LINTERPSIZ;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 256:
|
|
|
|
while (cnt > 0)
|
|
|
|
{
|
|
|
|
bz += bzinc*(1<<LINTERPSIZ);
|
|
|
|
int u1 = Blrintf(1048576.f*globalx3/bz);
|
|
|
|
int v1 = Blrintf(1048576.f*globaly3/bz);
|
|
|
|
u1 = (u1-u0)>>LINTERPSIZ;
|
|
|
|
v1 = (v1-v0)>>LINTERPSIZ;
|
|
|
|
int cnt2 = min(cnt, 1<<LINTERPSIZ);
|
|
|
|
for (; cnt2>0; cnt2--)
|
|
|
|
{
|
|
|
|
u = (globalx1+u0)&0xffff;
|
|
|
|
v = (globaly1+v0)&0xffff;
|
|
|
|
uint8_t ch = ggbuf[((u>>(16-gglogx))<<gglogy)+(v>>(16-gglogy))];
|
|
|
|
if (ch != 255)
|
|
|
|
{
|
|
|
|
ch = *(uint8_t *)(((intptr_t)slopalptr[0])+ch);
|
|
|
|
*p = trans[(*p<<8)|ch];
|
|
|
|
}
|
|
|
|
slopalptr--;
|
|
|
|
p += ggpinc;
|
|
|
|
u0 += u1;
|
|
|
|
v0 += v1;
|
|
|
|
}
|
|
|
|
cnt -= 1<<LINTERPSIZ;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 384:
|
|
|
|
while (cnt > 0)
|
|
|
|
{
|
|
|
|
bz += bzinc*(1<<LINTERPSIZ);
|
|
|
|
int u1 = Blrintf(1048576.f*globalx3/bz);
|
|
|
|
int v1 = Blrintf(1048576.f*globaly3/bz);
|
|
|
|
u1 = (u1-u0)>>LINTERPSIZ;
|
|
|
|
v1 = (v1-v0)>>LINTERPSIZ;
|
|
|
|
int cnt2 = min(cnt, 1<<LINTERPSIZ);
|
|
|
|
for (; cnt2>0; cnt2--)
|
|
|
|
{
|
|
|
|
u = (globalx1+u0)&0xffff;
|
|
|
|
v = (globaly1+v0)&0xffff;
|
|
|
|
uint8_t ch = ggbuf[((u>>(16-gglogx))<<gglogy)+(v>>(16-gglogy))];
|
|
|
|
if (ch != 255)
|
|
|
|
{
|
|
|
|
ch = *(uint8_t *)(((intptr_t)slopalptr[0])+ch);
|
|
|
|
*p = trans[ch<<8|*p];
|
|
|
|
}
|
|
|
|
slopalptr--;
|
|
|
|
p += ggpinc;
|
|
|
|
u0 += u1;
|
|
|
|
v0 += v1;
|
|
|
|
}
|
|
|
|
cnt -= 1<<LINTERPSIZ;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#undef LINTERPSIZ
|
|
|
|
if ((x&15) == 0) faketimerhandler();
|
|
|
|
}
|
|
|
|
globalx2 += globalx;
|
|
|
|
globaly2 += globaly;
|
|
|
|
globalzx += globalz;
|
|
|
|
shoffs += shinc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
static void grouscan(int32_t dax1, int32_t dax2, int32_t sectnum, char dastat)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-07-06 16:30:18 +00:00
|
|
|
if (r_fpgrouscan)
|
|
|
|
{
|
|
|
|
fgrouscan(dax1, dax2, sectnum, dastat);
|
|
|
|
return;
|
|
|
|
}
|
2009-11-04 08:11:21 +00:00
|
|
|
int32_t i, l, x, y, dx, dy, wx, wy, y1, y2, daz;
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t daslope, dasqr;
|
2017-06-09 06:41:23 +00:00
|
|
|
int32_t shoffs, m1, m2;
|
2014-04-05 11:28:06 +00:00
|
|
|
intptr_t *mptr1, *mptr2, j;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-04-05 11:28:06 +00:00
|
|
|
// Er, yes, they're not global anymore:
|
|
|
|
int32_t globalx, globaly, globalz, globalzx;
|
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const sec = (usectorptr_t)§or[sectnum];
|
|
|
|
uwallptr_t wal;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-06-25 11:30:22 +00:00
|
|
|
tileUpdatePicnum(&globalpicnum, sectnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
setgotpic(globalpicnum);
|
2014-09-30 04:14:21 +00:00
|
|
|
if ((tilesiz[globalpicnum].x <= 0) || (tilesiz[globalpicnum].y <= 0)) return;
|
2018-04-12 21:03:30 +00:00
|
|
|
if (waloff[globalpicnum] == 0) tileLoad(globalpicnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
wal = (uwallptr_t)&wall[sec->wallptr];
|
2006-04-13 20:47:06 +00:00
|
|
|
wx = wall[wal->point2].x - wal->x;
|
|
|
|
wy = wall[wal->point2].y - wal->y;
|
2012-07-01 22:11:14 +00:00
|
|
|
dasqr = krecipasm(nsqrtasm(uhypsq(wx,wy)));
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2018-11-18 18:07:25 +00:00
|
|
|
globalzd = decltype(globalzd)(xdimscale)<<9;
|
2006-04-13 20:47:06 +00:00
|
|
|
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)
|
|
|
|
{
|
Integer Overflow Offensive continued: first round of -ftrapv - cleanness.
That is, "clang -ftrapv" builds don't abort almost immediately after entering
a level.
There are various classes of overflow bugs, needing different handling:
- Some texture mapping code was written with signed integer wrapping semantics
in mind. In some places, we're able to get away with unsigned casts.
- sometimes, we really need a wider range, like when calculating distances or
dot products
- negating INT_MIN. Here, we cast to int64_t temporarily. Note that if the
result is 32-bit wide, no 64-bit code may actually need to be generated.
- shifting into a signed integer's sign bit. We cast to uint32 here.
- in hitscan(), at the "abyss crash prevention code" comment, it's clearly
the other code that is better...
This is not merely done for pedantry, but rather makes it easier to track down
overflow bugs having a real impact on the game.
git-svn-id: https://svn.eduke32.com/eduke32@2784 1a8010ca-5511-0410-912e-c29ae57300e0
2012-06-26 19:49:53 +00:00
|
|
|
globalx1 += (uint32_t)sec->ceilingxpanning<<24;
|
|
|
|
globaly1 += (uint32_t)sec->ceilingypanning<<24;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Integer Overflow Offensive continued: first round of -ftrapv - cleanness.
That is, "clang -ftrapv" builds don't abort almost immediately after entering
a level.
There are various classes of overflow bugs, needing different handling:
- Some texture mapping code was written with signed integer wrapping semantics
in mind. In some places, we're able to get away with unsigned casts.
- sometimes, we really need a wider range, like when calculating distances or
dot products
- negating INT_MIN. Here, we cast to int64_t temporarily. Note that if the
result is 32-bit wide, no 64-bit code may actually need to be generated.
- shifting into a signed integer's sign bit. We cast to uint32 here.
- in hitscan(), at the "abyss crash prevention code" comment, it's clearly
the other code that is better...
This is not merely done for pedantry, but rather makes it easier to track down
overflow bugs having a real impact on the game.
git-svn-id: https://svn.eduke32.com/eduke32@2784 1a8010ca-5511-0410-912e-c29ae57300e0
2012-06-26 19:49:53 +00:00
|
|
|
globalx1 += (uint32_t)sec->floorxpanning<<24;
|
|
|
|
globaly1 += (uint32_t)sec->floorypanning<<24;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
asm1 = -(globalzd>>(16-BITSOFPRECISION));
|
|
|
|
|
2014-04-21 17:00:51 +00:00
|
|
|
{
|
|
|
|
int32_t vis = globalvisibility;
|
|
|
|
int64_t lvis;
|
|
|
|
|
|
|
|
if (sec->visibility != 0) vis = mulscale4(vis, (uint8_t)(sec->visibility+16));
|
2014-04-22 18:10:19 +00:00
|
|
|
lvis = ((uint64_t)vis*daz) >> 13; // NOTE: lvis can be negative now!
|
2014-04-21 17:00:51 +00:00
|
|
|
lvis = (lvis * xdimscale) >> 16;
|
2014-04-22 18:10:19 +00:00
|
|
|
globvis = lvis;
|
2014-04-21 17:00:51 +00:00
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
j = FP_OFF(palookup[globalpal]);
|
|
|
|
|
2012-06-05 22:21:26 +00:00
|
|
|
setupslopevlin_alsotrans((picsiz[globalpicnum]&15) + ((picsiz[globalpicnum]>>4)<<8),
|
2011-05-17 21:48:13 +00:00
|
|
|
waloff[globalpicnum],-ylookup[1]);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
l = (globalzd>>16);
|
|
|
|
|
2017-06-09 06:41:23 +00:00
|
|
|
int32_t const shinc = mulscale16(globalz,xdimenscale);
|
|
|
|
|
|
|
|
shoffs = (shinc > 0) ? (4 << 15) : ((16380 - ydimen) << 15); // JBF: was 2044
|
|
|
|
y1 = (dastat == 0) ? umost[dax1] : max(umost[dax1], dplc[dax1]);
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
m1 = mulscale16(y1,globalzd) + (globalzx>>6);
|
2006-04-24 19:04:22 +00:00
|
|
|
//Avoid visibility overflow by crossing horizon
|
2017-06-09 06:41:23 +00:00
|
|
|
m1 += klabs((int32_t) (globalzd>>16));
|
2006-04-13 20:47:06 +00:00
|
|
|
m2 = m1+l;
|
2009-11-04 08:11:21 +00:00
|
|
|
mptr1 = (intptr_t *)&slopalookup[y1+(shoffs>>15)]; mptr2 = mptr1+1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=dax1; x<=dax2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2014-04-05 11:28:06 +00:00
|
|
|
intptr_t *nptr1 = &slopalookup[y1+(shoffs>>15)];
|
|
|
|
intptr_t *nptr2 = &slopalookup[y2+(shoffs>>15)];
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
while (nptr1 <= mptr1)
|
|
|
|
{
|
2012-12-14 19:27:58 +00:00
|
|
|
*mptr1-- = j + getpalookupsh(mulscale24(krecipasm(m1),globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
m1 -= l;
|
|
|
|
}
|
|
|
|
while (nptr2 >= mptr2)
|
|
|
|
{
|
2012-12-14 19:27:58 +00:00
|
|
|
*mptr2++ = j + getpalookupsh(mulscale24(krecipasm(m2),globvis));
|
2006-04-13 20:47:06 +00:00
|
|
|
m2 += l;
|
|
|
|
}
|
|
|
|
|
|
|
|
globalx3 = (globalx2>>10);
|
|
|
|
globaly3 = (globaly2>>10);
|
|
|
|
asm3 = mulscale16(y2,globalzd) + (globalzx>>6);
|
2019-03-19 17:09:03 +00:00
|
|
|
switch (globalorientation&0x180)
|
|
|
|
{
|
|
|
|
case 0:
|
2011-05-17 21:48:13 +00:00
|
|
|
slopevlin(ylookup[y2]+x+frameoffset,krecipasm(asm3>>3),(intptr_t)nptr2,y2-y1+1,globalx1,globaly1);
|
2019-03-19 17:09:03 +00:00
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
mslopevlin((uint8_t *)(ylookup[y2]+x+frameoffset),nptr2,y2-y1+1,globalx1,globaly1);
|
|
|
|
break;
|
|
|
|
case 256:
|
|
|
|
case 384:
|
2016-06-21 00:33:30 +00:00
|
|
|
tslopevlin((uint8_t *)(ylookup[y2]+x+frameoffset),nptr2,y2-y1+1,globalx1,globaly1);
|
2019-03-19 17:09:03 +00:00
|
|
|
break;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((x&15) == 0) faketimerhandler();
|
|
|
|
}
|
|
|
|
globalx2 += globalx;
|
|
|
|
globaly2 += globaly;
|
|
|
|
globalzx += globalz;
|
|
|
|
shoffs += shinc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// parascan (internal)
|
|
|
|
//
|
2018-10-07 05:21:53 +00:00
|
|
|
static void parascan(char dastat, int32_t bunch)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t j, k, l, m, n, x, z, wallnum, nextsectnum, globalhorizbak;
|
|
|
|
int16_t *topptr, *botptr;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-12-23 13:59:52 +00:00
|
|
|
int32_t logtilesizy, tsizy;
|
|
|
|
|
2019-04-18 17:24:10 +00:00
|
|
|
int32_t sectnum = thesector[bunchfirst[bunch]];
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const sec = (usectorptr_t)§or[sectnum];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
globalhorizbak = globalhoriz;
|
|
|
|
globvis = globalpisibility;
|
|
|
|
//globalorientation = 0L;
|
2012-12-23 13:59:52 +00:00
|
|
|
if (sec->visibility != 0)
|
|
|
|
globvis = mulscale4(globvis, (uint8_t)(sec->visibility+16));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (dastat == 0)
|
|
|
|
{
|
|
|
|
globalpal = sec->ceilingpal;
|
|
|
|
globalpicnum = sec->ceilingpicnum;
|
2009-01-09 09:29:17 +00:00
|
|
|
globalshade = (int32_t)sec->ceilingshade;
|
|
|
|
globalxpanning = (int32_t)sec->ceilingxpanning;
|
|
|
|
globalypanning = (int32_t)sec->ceilingypanning;
|
2006-04-13 20:47:06 +00:00
|
|
|
topptr = umost;
|
|
|
|
botptr = uplc;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
globalpal = sec->floorpal;
|
|
|
|
globalpicnum = sec->floorpicnum;
|
2009-01-09 09:29:17 +00:00
|
|
|
globalshade = (int32_t)sec->floorshade;
|
|
|
|
globalxpanning = (int32_t)sec->floorxpanning;
|
|
|
|
globalypanning = (int32_t)sec->floorypanning;
|
2006-04-13 20:47:06 +00:00
|
|
|
topptr = dplc;
|
|
|
|
botptr = dmost;
|
|
|
|
}
|
|
|
|
|
2012-06-05 22:21:26 +00:00
|
|
|
if ((unsigned)globalpicnum >= MAXTILES) globalpicnum = 0;
|
2019-06-25 11:30:22 +00:00
|
|
|
tileUpdatePicnum(&globalpicnum, sectnum);
|
2017-07-08 19:41:21 +00:00
|
|
|
setgotpic(globalpicnum);
|
2012-12-23 13:59:52 +00:00
|
|
|
|
|
|
|
logtilesizy = (picsiz[globalpicnum]>>4);
|
2014-09-30 04:14:21 +00:00
|
|
|
tsizy = tilesiz[globalpicnum].y;
|
2012-12-23 13:59:52 +00:00
|
|
|
|
2013-06-15 12:52:08 +00:00
|
|
|
if (tsizy==0)
|
|
|
|
return;
|
|
|
|
|
2016-10-14 07:40:50 +00:00
|
|
|
|
2017-11-29 07:29:48 +00:00
|
|
|
int32_t dapyscale, dapskybits, dapyoffs, daptileyscale;
|
|
|
|
int8_t const * const dapskyoff = getpsky(globalpicnum, &dapyscale, &dapskybits, &dapyoffs, &daptileyscale);
|
Clean up parallaxed sky functionality, part 2.
- Rename sky_t members: yscale -> horizfrac, bits -> lognumtiles.
- Add default sky (8 tiles, horizfrac=32768 (i.e. 1/2 the scene horiz), offsets
all zero) and CLOUDYOCEAN sky (8 tiles, horizfrac=65536, offsets all zero)
to multipsky[].
- Get rid of "psky_t g_psky", merely maintaining a g_pskyidx instead. Set it up
at map load time so as to keep the behavior of the legacy per-map psky:
the last sector index with a matching psky ceiling wins.
- In mapstate_t, save g_pskyidx too, not (former) pskybits and pskyoffs[].
- Make on-map-load global psky setup consistent for the game and editor by
factoring it out into common.c: G_SetupGlobalPsky().
- Remove a couple of useless initializations, add some static assertions.
This commit is more likely to introduce subtle differences in behavior.
Specifically, getpsky() now always returns the default sky properties instead of
the global sky ones (but with all-zero offsets) when no match for a suiting
multi-psky is found. This is only likely to affect the yscale/horizfrac of
non-multi-pskies when a global non-default multi-psky has been set up.
Bump BYTEVERSION again.
git-svn-id: https://svn.eduke32.com/eduke32@3976 1a8010ca-5511-0410-912e-c29ae57300e0
2013-08-04 20:37:48 +00:00
|
|
|
|
2012-12-23 13:59:52 +00:00
|
|
|
globalshiftval = logtilesizy;
|
2013-06-01 20:09:39 +00:00
|
|
|
|
2012-12-23 13:59:52 +00:00
|
|
|
// before proper non-power-of-two tilesizy drawing
|
2013-06-01 20:09:39 +00:00
|
|
|
if (oldnonpow2() && pow2long[logtilesizy] != tsizy)
|
2012-12-23 13:59:52 +00:00
|
|
|
globalshiftval++;
|
2013-06-01 20:09:39 +00:00
|
|
|
#ifdef CLASSIC_NONPOW2_YSIZE_WALLS
|
2012-12-23 13:59:52 +00:00
|
|
|
// non power-of-two y size textures!
|
2013-06-01 20:09:39 +00:00
|
|
|
if ((!oldnonpow2() && pow2long[logtilesizy] != tsizy) || tsizy >= 512)
|
2012-12-23 13:59:52 +00:00
|
|
|
{
|
|
|
|
globaltilesizy = tsizy;
|
|
|
|
globalyscale = 65536 / tsizy;
|
|
|
|
globalshiftval = 0;
|
2016-10-14 07:40:50 +00:00
|
|
|
globalzd = divscale32(((tsizy>>1)+dapyoffs), tsizy) + ((uint32_t)globalypanning<<24);
|
2012-12-23 13:59:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
globalshiftval = 32-globalshiftval;
|
|
|
|
globalyscale = (8<<(globalshiftval-19));
|
2018-11-18 18:07:25 +00:00
|
|
|
globalzd = (decltype(globalzd)((tsizy >> 1) + dapyoffs) << globalshiftval) + (decltype(globalzd)(globalypanning) << 24);
|
2012-12-23 13:59:52 +00:00
|
|
|
}
|
2017-11-29 07:29:48 +00:00
|
|
|
globalyscale = divscale16(globalyscale,daptileyscale);
|
2012-12-23 13:59:52 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
if (dapyscale != 65536)
|
|
|
|
globalhoriz = mulscale16(globalhoriz-(ydimen>>1),dapyscale) + (ydimen>>1);
|
|
|
|
|
2019-06-25 11:29:42 +00:00
|
|
|
k = 27 - (picsiz[globalpicnum]&15) - dapskybits;
|
2011-12-09 19:11:08 +00:00
|
|
|
|
|
|
|
// WGR2 SVN: select new episode after playing wgmicky1 with Polymer
|
|
|
|
// (maybe switched to classic earlier).
|
2013-05-17 10:41:59 +00:00
|
|
|
// --> rendmode==0, glrendermode == REND_POLYMER, we end up with globalpicnum==266,
|
2011-12-09 19:11:08 +00:00
|
|
|
// picsiz...==9 and dapskybits==3
|
|
|
|
// FIXME ?
|
|
|
|
if (k < 0)
|
|
|
|
k = 0;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
x = -1;
|
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
for (z=bunchfirst[bunch]; z>=0; z=bunchp2[z])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
wallnum = thewall[z]; nextsectnum = wall[wallnum].nextsector;
|
|
|
|
|
2008-07-01 11:14:18 +00:00
|
|
|
if (nextsectnum >= 0) //else negative array access
|
|
|
|
{
|
|
|
|
if (dastat == 0) j = sector[nextsectnum].ceilingstat;
|
|
|
|
else j = sector[nextsectnum].floorstat;
|
2008-06-13 15:16:14 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((nextsectnum < 0) || (wall[wallnum].cstat&32) || ((j&1) == 0))
|
|
|
|
{
|
|
|
|
if (x == -1) x = xb1[z];
|
|
|
|
|
2012-09-02 14:10:55 +00:00
|
|
|
if (parallaxtype == 0 || no_radarang2)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
n = mulscale16(xdimenrecip,viewingrange);
|
2009-02-19 16:47:54 +00:00
|
|
|
for (j=xb1[z]; j<=xb2[z]; j++)
|
2019-06-25 11:29:42 +00:00
|
|
|
lplc[j] = ((mulscale7(j-halfxdimen,n)+qglobalang)&0x7FFFFFF)>>k;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-19 16:47:54 +00:00
|
|
|
for (j=xb1[z]; j<=xb2[z]; j++)
|
2019-06-25 11:29:42 +00:00
|
|
|
lplc[j] = ((radarang2[j]+qglobalang)&0x7FFFFFF)>>k;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-09-02 14:10:55 +00:00
|
|
|
|
|
|
|
if (parallaxtype == 2 && !no_radarang2)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
n = mulscale16(xdimscale,viewingrange);
|
2009-02-19 16:47:54 +00:00
|
|
|
for (j=xb1[z]; j<=xb2[z]; j++)
|
2019-06-25 11:29:42 +00:00
|
|
|
swplc[j] = mulscale14(sintable[((radarang2[j]>>16)+512)&2047],n);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
clearbuf(&swplc[xb1[z]],xb2[z]-xb1[z]+1,mulscale16(xdimscale,viewingrange));
|
|
|
|
}
|
|
|
|
else if (x >= 0)
|
|
|
|
{
|
|
|
|
l = globalpicnum; m = (picsiz[globalpicnum]&15);
|
2011-05-12 23:31:13 +00:00
|
|
|
globalpicnum = l + dapskyoff[lplc[x]>>m];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
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])
|
|
|
|
{
|
2011-05-12 23:31:13 +00:00
|
|
|
n = l + dapskyoff[lplc[x]>>m];
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2011-05-12 23:31:13 +00:00
|
|
|
globalpicnum = l + dapskyoff[lplc[x]>>m];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
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]])
|
|
|
|
{
|
2011-05-12 23:31:13 +00:00
|
|
|
n = l + dapskyoff[lplc[x]>>m];
|
2006-04-13 20:47:06 +00:00
|
|
|
if (n != globalpicnum)
|
|
|
|
{
|
|
|
|
wallscan(j,x-1,topptr,botptr,swplc,lplc);
|
|
|
|
j = x;
|
|
|
|
globalpicnum = n;
|
|
|
|
}
|
|
|
|
x++;
|
|
|
|
}
|
|
|
|
if (j <= x)
|
2007-02-26 01:46:38 +00:00
|
|
|
wallscan(j,x-1,topptr,botptr,swplc,lplc);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
globalpicnum = l;
|
|
|
|
}
|
|
|
|
globalhoriz = globalhorizbak;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-25 13:54:14 +00:00
|
|
|
// set orientation, panning, shade, pal; picnum
|
2019-04-18 17:25:24 +00:00
|
|
|
static void setup_globals_wall1(uwallptr_t wal, int32_t dapicnum)
|
2012-03-25 13:54:14 +00:00
|
|
|
{
|
|
|
|
globalorientation = wal->cstat;
|
|
|
|
|
|
|
|
globalpicnum = dapicnum;
|
2012-06-05 22:21:26 +00:00
|
|
|
if ((unsigned)globalpicnum >= MAXTILES) globalpicnum = 0;
|
2019-06-25 11:30:22 +00:00
|
|
|
tileUpdatePicnum(&globalpicnum, 16384);
|
2012-03-25 13:54:14 +00:00
|
|
|
|
|
|
|
globalxpanning = wal->xpanning;
|
|
|
|
globalypanning = wal->ypanning;
|
|
|
|
|
|
|
|
globalshade = wal->shade;
|
|
|
|
globalpal = wal->pal;
|
|
|
|
if (palookup[globalpal] == NULL) globalpal = 0; // JBF: fixes crash
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
static void setup_globals_wall2(uwallptr_t wal, uint8_t secvisibility, int32_t topzref, int32_t botzref)
|
2012-03-25 13:54:14 +00:00
|
|
|
{
|
2012-07-06 11:26:24 +00:00
|
|
|
const int32_t logtilesizy = (picsiz[globalpicnum]>>4);
|
2014-09-30 04:14:21 +00:00
|
|
|
const int32_t tsizy = tilesiz[globalpicnum].y;
|
2012-07-06 11:26:24 +00:00
|
|
|
|
|
|
|
if (tsizy==0)
|
|
|
|
{
|
|
|
|
globalshiftval = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-25 13:54:14 +00:00
|
|
|
globvis = globalvisibility;
|
|
|
|
if (secvisibility != 0)
|
2012-12-14 19:28:05 +00:00
|
|
|
globvis = mulscale4(globvis, (uint8_t)(secvisibility+16));
|
2012-03-25 13:54:14 +00:00
|
|
|
|
2012-07-06 11:26:24 +00:00
|
|
|
globalshiftval = logtilesizy;
|
2013-06-01 20:09:39 +00:00
|
|
|
|
2012-07-06 11:26:24 +00:00
|
|
|
// before proper non-power-of-two tilesizy drawing
|
2013-06-01 20:09:39 +00:00
|
|
|
if (oldnonpow2() && pow2long[logtilesizy] != tsizy)
|
2012-07-06 11:26:24 +00:00
|
|
|
globalshiftval++;
|
2013-06-01 20:09:39 +00:00
|
|
|
#ifdef CLASSIC_NONPOW2_YSIZE_WALLS
|
2012-07-06 11:26:24 +00:00
|
|
|
// non power-of-two y size textures!
|
2013-06-01 20:09:39 +00:00
|
|
|
if ((!oldnonpow2() && pow2long[logtilesizy] != tsizy) || tsizy >= 512)
|
2012-12-23 13:59:52 +00:00
|
|
|
{
|
|
|
|
globaltilesizy = tsizy;
|
|
|
|
globalyscale = divscale13(wal->yrepeat, tsizy);
|
|
|
|
globalshiftval = 0;
|
|
|
|
}
|
|
|
|
else
|
2012-07-06 11:26:24 +00:00
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// globalshiftval==13 --> globalshiftval==19
|
|
|
|
// ==> upper texture y size limit *here* = 8192
|
|
|
|
globalshiftval = 32-globalshiftval;
|
|
|
|
globalyscale = wal->yrepeat<<(globalshiftval-19);
|
|
|
|
}
|
2012-03-25 13:54:14 +00:00
|
|
|
|
|
|
|
if ((globalorientation&4) == 0)
|
Integer Overflow Offensive continued: first round of -ftrapv - cleanness.
That is, "clang -ftrapv" builds don't abort almost immediately after entering
a level.
There are various classes of overflow bugs, needing different handling:
- Some texture mapping code was written with signed integer wrapping semantics
in mind. In some places, we're able to get away with unsigned casts.
- sometimes, we really need a wider range, like when calculating distances or
dot products
- negating INT_MIN. Here, we cast to int64_t temporarily. Note that if the
result is 32-bit wide, no 64-bit code may actually need to be generated.
- shifting into a signed integer's sign bit. We cast to uint32 here.
- in hitscan(), at the "abyss crash prevention code" comment, it's clearly
the other code that is better...
This is not merely done for pedantry, but rather makes it easier to track down
overflow bugs having a real impact on the game.
git-svn-id: https://svn.eduke32.com/eduke32@2784 1a8010ca-5511-0410-912e-c29ae57300e0
2012-06-26 19:49:53 +00:00
|
|
|
globalzd = (((int64_t)(globalposz-topzref)*globalyscale)<<8);
|
2012-03-25 13:54:14 +00:00
|
|
|
else // bottom-aligned
|
Integer Overflow Offensive continued: first round of -ftrapv - cleanness.
That is, "clang -ftrapv" builds don't abort almost immediately after entering
a level.
There are various classes of overflow bugs, needing different handling:
- Some texture mapping code was written with signed integer wrapping semantics
in mind. In some places, we're able to get away with unsigned casts.
- sometimes, we really need a wider range, like when calculating distances or
dot products
- negating INT_MIN. Here, we cast to int64_t temporarily. Note that if the
result is 32-bit wide, no 64-bit code may actually need to be generated.
- shifting into a signed integer's sign bit. We cast to uint32 here.
- in hitscan(), at the "abyss crash prevention code" comment, it's clearly
the other code that is better...
This is not merely done for pedantry, but rather makes it easier to track down
overflow bugs having a real impact on the game.
git-svn-id: https://svn.eduke32.com/eduke32@2784 1a8010ca-5511-0410-912e-c29ae57300e0
2012-06-26 19:49:53 +00:00
|
|
|
globalzd = (((int64_t)(globalposz-botzref)*globalyscale)<<8);
|
2018-11-18 18:07:25 +00:00
|
|
|
|
|
|
|
globalzd += decltype(globalzd)(globalypanning) << 24;
|
2012-03-25 13:54:14 +00:00
|
|
|
|
|
|
|
if (globalorientation&256) // y-flipped
|
2014-08-23 10:28:18 +00:00
|
|
|
globalyscale = -globalyscale, globalzd = -(inthi_t)globalzd;
|
2012-03-25 13:54:14 +00:00
|
|
|
}
|
|
|
|
|
2012-06-06 22:03:32 +00:00
|
|
|
|
|
|
|
/* _______________
|
|
|
|
* X umost #######
|
|
|
|
* ###### ________
|
|
|
|
* ______/
|
|
|
|
* X dwall
|
|
|
|
*
|
|
|
|
* ________
|
|
|
|
* X uwall \______
|
|
|
|
* ///////////////
|
|
|
|
* _______________
|
|
|
|
* X dmost
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
// returns: should dmost be raised when drawing a "ceiling wall"?
|
|
|
|
static int32_t should_clip_cwall(int32_t x1, int32_t x2)
|
|
|
|
{
|
|
|
|
int32_t x;
|
|
|
|
|
|
|
|
if (yax_globallev <= YAX_MAXDRAWS)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
for (x=x1; x<=x2; x++)
|
|
|
|
if (dwall[x] < dmost[x] || uplc[x] < dmost[x])
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns: should umost be lowered when drawing a "floor wall"?
|
|
|
|
static int32_t should_clip_fwall(int32_t x1, int32_t x2)
|
|
|
|
{
|
|
|
|
int32_t x;
|
|
|
|
|
|
|
|
if (yax_globallev >= YAX_MAXDRAWS)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
for (x=x1; x<=x2; x++)
|
|
|
|
if (uwall[x] > umost[x] || dplc[x] > umost[x])
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// drawalls (internal)
|
|
|
|
//
|
2018-04-12 21:04:00 +00:00
|
|
|
static void classicDrawBunches(int32_t bunch)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-12-27 17:17:50 +00:00
|
|
|
int32_t i, x;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-27 17:17:50 +00:00
|
|
|
int32_t z = bunchfirst[bunch];
|
|
|
|
|
|
|
|
const int32_t sectnum = thesector[z];
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const sec = (usectorptr_t)§or[sectnum];
|
2014-12-27 17:17:50 +00:00
|
|
|
|
|
|
|
uint8_t andwstat1 = 0xff, andwstat2 = 0xff;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
for (; z>=0; z=bunchp2[z]) //uplc/dplc calculation
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
andwstat1 &= wallmost(uplc,z,sectnum,(uint8_t)0);
|
|
|
|
andwstat2 &= wallmost(dplc,z,sectnum,(uint8_t)1);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2011-05-15 22:37:24 +00:00
|
|
|
if (g_nodraw)
|
|
|
|
{
|
2011-08-18 22:01:18 +00:00
|
|
|
int32_t baselevp, checkcf;
|
|
|
|
int16_t bn[2];
|
|
|
|
# if 0
|
|
|
|
int32_t obunchchk = (1 && yax_globalbunch>=0 &&
|
2019-08-04 02:51:50 +00:00
|
|
|
haveymost[yax_globalbunch>>3]&pow2char[yax_globalbunch&7]);
|
2011-08-18 22:01:18 +00:00
|
|
|
|
|
|
|
// if (obunchchk)
|
2014-12-27 17:17:50 +00:00
|
|
|
const int32_t x2 = yax_globalbunch*xdimen;
|
2011-08-18 22:01:18 +00:00
|
|
|
# endif
|
2011-05-15 22:37:24 +00:00
|
|
|
baselevp = (yax_globallev == YAX_MAXDRAWS);
|
|
|
|
|
|
|
|
yax_getbunches(sectnum, &bn[0], &bn[1]);
|
|
|
|
checkcf = (bn[0]>=0) + ((bn[1]>=0)<<1);
|
|
|
|
if (!baselevp)
|
|
|
|
checkcf &= (1<<yax_globalcf);
|
|
|
|
|
|
|
|
if ((andwstat1&3) == 3) // ceilings clipped
|
|
|
|
checkcf &= ~1;
|
|
|
|
if ((andwstat2&12) == 12) // floors clipped
|
|
|
|
checkcf &= ~2;
|
|
|
|
|
|
|
|
for (i=0; i<2; i++)
|
|
|
|
if (checkcf&(1<<i))
|
|
|
|
{
|
2019-08-04 02:51:50 +00:00
|
|
|
if ((haveymost[bn[i]>>3]&pow2char[bn[i]&7])==0)
|
2011-05-15 22:37:24 +00:00
|
|
|
{
|
|
|
|
// init yax *most arrays for that bunch
|
2019-08-04 02:51:50 +00:00
|
|
|
haveymost[bn[i]>>3] |= pow2char[bn[i]&7];
|
2011-05-15 22:37:24 +00:00
|
|
|
for (x=xdimen*bn[i]; x<xdimen*(bn[i]+1); x++)
|
|
|
|
{
|
|
|
|
yumost[x] = ydimen;
|
|
|
|
ydmost[x] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-27 17:17:50 +00:00
|
|
|
const int32_t x1 = bn[i]*xdimen;
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
for (x=x1+xb1[bunchfirst[bunch]]; x<=x1+xb2[bunchlast[bunch]]; x++)
|
|
|
|
{
|
2011-06-18 13:02:08 +00:00
|
|
|
if (i==YAX_CEILING)
|
|
|
|
{
|
2011-05-15 22:37:24 +00:00
|
|
|
yumost[x] = min(yumost[x], umost[x-x1]);
|
2011-06-18 13:02:08 +00:00
|
|
|
ydmost[x] = max(ydmost[x], min(dmost[x-x1], uplc[x-x1]));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
yumost[x] = min(yumost[x], max(umost[x-x1], dplc[x-x1]));
|
2011-05-15 22:37:24 +00:00
|
|
|
ydmost[x] = max(ydmost[x], dmost[x-x1]);
|
2011-06-18 13:02:08 +00:00
|
|
|
}
|
2011-08-18 22:01:18 +00:00
|
|
|
# if 0
|
|
|
|
if (obunchchk)
|
|
|
|
{
|
|
|
|
yumost[x] = max(yumost[x], yumost[x-x1+x2]);
|
|
|
|
ydmost[x] = min(ydmost[x], ydmost[x-x1+x2]);
|
|
|
|
}
|
|
|
|
# endif
|
2011-05-15 22:37:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2011-05-07 18:23:34 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2011-05-07 18:23:34 +00:00
|
|
|
if ((andwstat1&3) != 3) //draw ceilings
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
// this is to prevent double-drawing of translucent masked ceilings
|
|
|
|
if (r_tror_nomaskpass==0 || yax_globallev==YAX_MAXDRAWS || (sec->ceilingstat&256)==0 ||
|
2019-08-04 02:51:50 +00:00
|
|
|
yax_nomaskpass==1 || !(yax_gotsector[sectnum>>3]&pow2char[sectnum&7]))
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
#endif
|
2011-05-07 18:23:34 +00:00
|
|
|
{
|
|
|
|
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
|
2018-10-07 05:21:53 +00:00
|
|
|
parascan(0,bunch);
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
|
2012-03-13 20:06:37 +00:00
|
|
|
if ((andwstat2&12) != 12) //draw floors
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2012-03-13 20:06:37 +00:00
|
|
|
// this is to prevent double-drawing of translucent masked floors
|
|
|
|
if (r_tror_nomaskpass==0 || yax_globallev==YAX_MAXDRAWS || (sec->floorstat&256)==0 ||
|
2019-08-04 02:51:50 +00:00
|
|
|
yax_nomaskpass==1 || !(yax_gotsector[sectnum>>3]&pow2char[sectnum&7]))
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
#endif
|
2011-05-07 18:23:34 +00:00
|
|
|
{
|
|
|
|
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
|
2018-10-07 05:21:53 +00:00
|
|
|
parascan(1,bunch);
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2012-03-13 20:07:40 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//DRAW WALLS SECTION!
|
2014-09-30 04:14:21 +00:00
|
|
|
for (z=bunchfirst[bunch]; z>=0; z=bunchp2[z])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-12-27 17:17:50 +00:00
|
|
|
const int32_t x1 = xb1[z], x2 = xb2[z];
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (umost[x2] >= dmost[x2])
|
|
|
|
{
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<x2; x++)
|
2014-12-27 17:17:50 +00:00
|
|
|
if (umost[x] < dmost[x])
|
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
if (x >= x2)
|
|
|
|
{
|
|
|
|
smostwall[smostwallcnt] = z;
|
|
|
|
smostwalltype[smostwallcnt] = 0;
|
|
|
|
smostwallcnt++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-27 17:17:50 +00:00
|
|
|
const int32_t wallnum = thewall[z];
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const wal = (uwallptr_t)&wall[wallnum];
|
2014-12-27 17:17:50 +00:00
|
|
|
|
|
|
|
const int32_t nextsectnum = wal->nextsector;
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const nextsec = nextsectnum>=0 ? (usectorptr_t)§or[nextsectnum] : NULL;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-10-10 19:14:46 +00:00
|
|
|
int32_t gotswall = 0;
|
|
|
|
|
|
|
|
const int32_t startsmostwallcnt = smostwallcnt;
|
|
|
|
const int32_t startsmostcnt = smostcnt;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-27 17:17:50 +00:00
|
|
|
if (searchit == 2 && (searchx >= x1 && searchx <= x2))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2011-09-17 14:26:02 +00:00
|
|
|
if (searchy <= uplc[searchx]
|
|
|
|
#ifdef YAX_ENABLE
|
2011-09-17 15:26:52 +00:00
|
|
|
&& umost[searchx] <= searchy && getceilzofslope(sectnum, globalposx, globalposy) <= globalposz
|
2011-09-17 14:26:02 +00:00
|
|
|
&& (yax_getbunch(sectnum, YAX_CEILING) < 0 || showinvisibility || (sec->ceilingstat&(256+128)) || klabs(yax_globallev-YAX_MAXDRAWS)==YAX_MAXDRAWS)
|
|
|
|
#endif
|
|
|
|
) //ceiling
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
searchsector = sectnum; searchwall = wallnum;
|
|
|
|
searchstat = 1; searchit = 1;
|
|
|
|
}
|
2011-09-17 14:26:02 +00:00
|
|
|
else if (dplc[searchx] <= searchy
|
|
|
|
#ifdef YAX_ENABLE
|
2011-09-17 15:26:52 +00:00
|
|
|
&& searchy < dmost[searchx] && getflorzofslope(sectnum, globalposx, globalposy) >= globalposz
|
2011-09-17 14:26:02 +00:00
|
|
|
&& (yax_getbunch(sectnum, YAX_FLOOR) < 0 || showinvisibility || (sec->floorstat&(256+128)) || klabs(yax_globallev-YAX_MAXDRAWS)==YAX_MAXDRAWS)
|
|
|
|
#endif
|
|
|
|
) //floor
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
searchsector = sectnum; searchwall = wallnum;
|
|
|
|
searchstat = 2; searchit = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (yax_nomaskpass==0 || !yax_isislandwall(wallnum, !yax_globalcf) || (yax_nomaskdidit=1, 0))
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
if (nextsectnum >= 0)
|
|
|
|
{
|
2012-01-10 23:44:35 +00:00
|
|
|
// 2 <--- 3
|
|
|
|
// x------------------x
|
|
|
|
// 0 ---> 1
|
|
|
|
//
|
2012-02-16 19:25:18 +00:00
|
|
|
// 4 (our pos, z wrt the nextsector!)
|
2012-01-10 23:44:35 +00:00
|
|
|
|
2014-12-27 17:17:50 +00:00
|
|
|
int32_t cz[5], fz[5];
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
getzsofslope((int16_t)sectnum,wal->x,wal->y,&cz[0],&fz[0]);
|
|
|
|
getzsofslope((int16_t)sectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[1],&fz[1]);
|
|
|
|
getzsofslope((int16_t)nextsectnum,wal->x,wal->y,&cz[2],&fz[2]);
|
|
|
|
getzsofslope((int16_t)nextsectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[3],&fz[3]);
|
|
|
|
getzsofslope((int16_t)nextsectnum,globalposx,globalposy,&cz[4],&fz[4]);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-27 17:17:50 +00:00
|
|
|
if ((wal->cstat&48) == 16)
|
|
|
|
maskwall[maskwallcnt++] = z;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (((sec->ceilingstat&1) == 0) || ((nextsec->ceilingstat&1) == 0))
|
|
|
|
{
|
|
|
|
if ((cz[2] <= cz[0]) && (cz[3] <= cz[1]))
|
|
|
|
{
|
2011-05-23 14:22:32 +00:00
|
|
|
// if (globparaceilclip)
|
|
|
|
if (getceilzofslope(sectnum, globalposx, globalposy) <= globalposz)
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<=x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (uplc[x] > umost[x])
|
|
|
|
if (umost[x] <= dmost[x])
|
|
|
|
{
|
|
|
|
umost[x] = uplc[x];
|
|
|
|
if (umost[x] > dmost[x]) numhits--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
wallmost(dwall,z,nextsectnum,(uint8_t)0);
|
2012-06-05 22:21:26 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((cz[2] > fz[0]) || (cz[3] > fz[1]))
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=x1; i<=x2; i++) if (dwall[i] > dplc[i]) dwall[i] = dplc[i];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-27 17:17:50 +00:00
|
|
|
if (searchit == 2 && (searchx >= x1 && searchx <= x2))
|
2011-09-17 14:26:02 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (uplc[searchx] <= searchy)
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
if (searchy <= dwall[searchx]) //wall
|
|
|
|
{
|
2009-07-25 20:16:22 +00:00
|
|
|
searchsector = sectnum; searchbottomwall = searchwall = wallnum;
|
2011-03-17 23:37:38 +00:00
|
|
|
searchisbottom = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
searchstat = 0; searchit = 1;
|
|
|
|
}
|
|
|
|
|
2012-03-25 13:54:14 +00:00
|
|
|
setup_globals_wall1(wal, wal->picnum);
|
|
|
|
setup_globals_wall2(wal, sec->visibility, nextsec->ceilingz, sec->ceilingz);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-10-25 23:29:38 +00:00
|
|
|
gotswall = 1;
|
|
|
|
prepwall(z,wal);
|
2012-07-06 14:16:31 +00:00
|
|
|
wallscan(x1,x2,uplc,dwall,swall,lwall);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((cz[2] >= cz[0]) && (cz[3] >= cz[1]))
|
|
|
|
{
|
2012-06-05 22:21:22 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2012-06-06 22:03:32 +00:00
|
|
|
if (should_clip_cwall(x1, x2))
|
2012-06-05 22:21:22 +00:00
|
|
|
#endif
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<=x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (dwall[x] > umost[x])
|
|
|
|
if (umost[x] <= dmost[x])
|
|
|
|
{
|
|
|
|
umost[x] = dwall[x];
|
|
|
|
if (umost[x] > dmost[x]) numhits--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-06 22:03:32 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (should_clip_cwall(x1, x2))
|
|
|
|
#endif
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<=x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (umost[x] <= dmost[x])
|
|
|
|
{
|
|
|
|
i = max(uplc[x],dwall[x]);
|
|
|
|
if (i > umost[x])
|
|
|
|
{
|
|
|
|
umost[x] = i;
|
|
|
|
if (umost[x] > dmost[x]) numhits--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-01-10 23:44:35 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((cz[2] < cz[0]) || (cz[3] < cz[1]) || (globalposz < cz[4]))
|
|
|
|
{
|
|
|
|
i = x2-x1+1;
|
2014-10-29 17:04:28 +00:00
|
|
|
if (smostcnt+i < ysavecnt)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
smoststart[smostwallcnt] = smostcnt;
|
|
|
|
smostwall[smostwallcnt] = z;
|
|
|
|
smostwalltype[smostwallcnt] = 1; //1 for umost
|
|
|
|
smostwallcnt++;
|
|
|
|
copybufbyte(&umost[x1],&smost[smostcnt],i*sizeof(smost[0]));
|
|
|
|
smostcnt += i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (((sec->floorstat&1) == 0) || ((nextsec->floorstat&1) == 0))
|
|
|
|
{
|
|
|
|
if ((fz[2] >= fz[0]) && (fz[3] >= fz[1]))
|
|
|
|
{
|
2011-05-23 14:22:32 +00:00
|
|
|
// if (globparaflorclip)
|
|
|
|
if (getflorzofslope(sectnum, globalposx, globalposy) >= globalposz)
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<=x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (dplc[x] < dmost[x])
|
|
|
|
if (umost[x] <= dmost[x])
|
|
|
|
{
|
|
|
|
dmost[x] = dplc[x];
|
|
|
|
if (umost[x] > dmost[x]) numhits--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
wallmost(uwall,z,nextsectnum,(uint8_t)1);
|
2012-06-05 22:21:26 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((fz[2] < cz[0]) || (fz[3] < cz[1]))
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=x1; i<=x2; i++) if (uwall[i] < uplc[i]) uwall[i] = uplc[i];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-27 17:17:50 +00:00
|
|
|
if (searchit == 2 && (searchx >= x1 && searchx <= x2))
|
2011-09-17 14:26:02 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (dplc[searchx] >= searchy)
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
if (searchy >= uwall[searchx]) //wall
|
|
|
|
{
|
2009-07-25 20:16:22 +00:00
|
|
|
searchsector = sectnum; searchbottomwall = searchwall = wallnum;
|
|
|
|
if ((wal->cstat&2) > 0) searchbottomwall = wal->nextwall;
|
2011-03-17 23:37:38 +00:00
|
|
|
searchisbottom = 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
searchstat = 0; searchit = 1;
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const twal = (wal->cstat&2) ? (uwallptr_t)&wall[wal->nextwall] : wal;
|
2016-06-21 00:33:30 +00:00
|
|
|
setup_globals_wall1(twal, twal->picnum);
|
2012-03-25 13:54:14 +00:00
|
|
|
|
|
|
|
setup_globals_wall2(wal, sec->visibility, nextsec->floorz, sec->ceilingz);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-07-06 14:16:31 +00:00
|
|
|
if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
|
|
|
|
wallscan(x1,x2,uwall,dplc,swall,lwall);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((fz[2] <= fz[0]) && (fz[3] <= fz[1]))
|
|
|
|
{
|
2012-06-05 22:21:22 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2012-06-06 22:03:32 +00:00
|
|
|
if (should_clip_fwall(x1, x2))
|
2012-06-05 22:21:22 +00:00
|
|
|
#endif
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<=x2; x++)
|
2016-06-21 00:33:30 +00:00
|
|
|
if (uwall[x] < dmost[x] && umost[x] <= dmost[x])
|
|
|
|
{
|
|
|
|
dmost[x] = uwall[x];
|
|
|
|
if (umost[x] > dmost[x]) numhits--;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-06 22:03:32 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (should_clip_fwall(x1, x2))
|
|
|
|
#endif
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<=x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (umost[x] <= dmost[x])
|
|
|
|
{
|
|
|
|
i = min(dplc[x],uwall[x]);
|
|
|
|
if (i < dmost[x])
|
|
|
|
{
|
|
|
|
dmost[x] = i;
|
|
|
|
if (umost[x] > dmost[x]) numhits--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-01-10 23:44:35 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((fz[2] > fz[0]) || (fz[3] > fz[1]) || (globalposz > fz[4]))
|
|
|
|
{
|
|
|
|
i = x2-x1+1;
|
2014-10-29 17:04:28 +00:00
|
|
|
if (smostcnt+i < ysavecnt)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
smoststart[smostwallcnt] = smostcnt;
|
|
|
|
smostwall[smostwallcnt] = z;
|
|
|
|
smostwalltype[smostwallcnt] = 2; //2 for dmost
|
|
|
|
smostwallcnt++;
|
|
|
|
copybufbyte(&dmost[x1],&smost[smostcnt],i*sizeof(smost[0]));
|
|
|
|
smostcnt += i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
|
2014-12-27 17:17:50 +00:00
|
|
|
if (numhits < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!(wal->cstat&32) && (gotsector[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
if (umost[x2] < dmost[x2])
|
2018-04-12 21:04:00 +00:00
|
|
|
classicScanSector(nextsectnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
|
|
|
{
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (umost[x] < dmost[x])
|
2018-04-12 21:04:00 +00:00
|
|
|
{ classicScanSector(nextsectnum); break; }
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//If can't see sector beyond, then cancel smost array and just
|
|
|
|
//store wall!
|
2006-04-13 20:47:06 +00:00
|
|
|
if (x == x2)
|
|
|
|
{
|
|
|
|
smostwallcnt = startsmostwallcnt;
|
|
|
|
smostcnt = startsmostcnt;
|
|
|
|
smostwall[smostwallcnt] = z;
|
|
|
|
smostwalltype[smostwallcnt] = 0;
|
|
|
|
smostwallcnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-09-15 17:02:12 +00:00
|
|
|
|
2014-12-27 17:17:50 +00:00
|
|
|
if (nextsectnum < 0 || (wal->cstat&32)) //White/1-way wall
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-03-25 13:54:14 +00:00
|
|
|
setup_globals_wall1(wal, (nextsectnum < 0) ? wal->picnum : wal->overpicnum);
|
|
|
|
setup_globals_wall2(wal, sec->visibility,
|
|
|
|
(nextsectnum >= 0) ? nextsec->ceilingz : sec->ceilingz,
|
|
|
|
(nextsectnum >= 0) ? sec->ceilingz : sec->floorz);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-07-06 14:16:31 +00:00
|
|
|
if (gotswall == 0) { gotswall = 1; prepwall(z,wal); }
|
|
|
|
wallscan(x1,x2,uplc,dplc,swall,lwall);
|
2011-09-15 17:02:12 +00:00
|
|
|
|
2011-05-02 16:58:11 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2011-05-07 18:23:34 +00:00
|
|
|
// TODO: slopes?
|
2011-06-04 00:06:08 +00:00
|
|
|
|
2011-09-15 17:02:12 +00:00
|
|
|
if (globalposz > sec->floorz && yax_isislandwall(wallnum, YAX_FLOOR))
|
2011-05-02 16:58:11 +00:00
|
|
|
{
|
|
|
|
for (x=x1; x<=x2; x++)
|
|
|
|
if (dplc[x] > umost[x] && umost[x] <= dmost[x])
|
|
|
|
{
|
|
|
|
umost[x] = dplc[x];
|
|
|
|
if (umost[x] > dmost[x]) numhits--;
|
|
|
|
}
|
|
|
|
}
|
2011-09-15 17:02:12 +00:00
|
|
|
else if (globalposz < sec->ceilingz && yax_isislandwall(wallnum, YAX_CEILING))
|
2011-05-02 16:58:11 +00:00
|
|
|
{
|
|
|
|
for (x=x1; x<=x2; x++)
|
|
|
|
if (uplc[x] < dmost[x] && umost[x] <= dmost[x])
|
|
|
|
{
|
|
|
|
dmost[x] = uplc[x];
|
|
|
|
if (umost[x] > dmost[x]) numhits--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<=x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (umost[x] <= dmost[x])
|
2007-12-12 17:42:14 +00:00
|
|
|
{ umost[x] = 1; dmost[x] = 0; numhits--; }
|
2006-04-13 20:47:06 +00:00
|
|
|
smostwall[smostwallcnt] = z;
|
|
|
|
smostwalltype[smostwallcnt] = 0;
|
|
|
|
smostwallcnt++;
|
|
|
|
|
2014-12-27 17:17:50 +00:00
|
|
|
if (searchit == 2 && (x1 <= searchx && searchx <= x2))
|
2011-09-17 14:26:02 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (uplc[searchx] <= searchy && searchy < dplc[searchx])
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-12-27 17:17:50 +00:00
|
|
|
searchit = 1; searchsector = sectnum;
|
|
|
|
searchbottomwall = searchwall = wallnum;
|
|
|
|
searchstat = (nextsectnum < 0) ? 0 : 4;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
2011-05-07 18:23:34 +00:00
|
|
|
|
|
|
|
#ifdef ENGINE_SCREENSHOT_DEBUG
|
2011-05-12 23:31:13 +00:00
|
|
|
if (engine_screenshot)
|
2011-12-28 20:34:10 +00:00
|
|
|
# ifdef YAX_ENABLE
|
2011-05-12 23:31:13 +00:00
|
|
|
if (!g_nodraw)
|
2011-12-28 20:34:10 +00:00
|
|
|
# endif
|
2011-05-07 18:23:34 +00:00
|
|
|
{
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
static char fn[32], tmpbuf[80];
|
2018-04-12 21:03:47 +00:00
|
|
|
char purple = paletteGetClosestColor(255, 0, 255);
|
|
|
|
char yellow = paletteGetClosestColor(255, 255, 0);
|
2014-10-29 17:04:28 +00:00
|
|
|
char *bakframe = (char *)Xaligned_alloc(16, xdim*ydim);
|
2011-05-12 23:31:13 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2011-05-12 23:31:13 +00:00
|
|
|
Bmemcpy(bakframe, (char *)frameplace, xdim*ydim);
|
|
|
|
for (x=0; x<xdim; x++)
|
|
|
|
{
|
|
|
|
if (umost[x] > dmost[x])
|
|
|
|
{
|
|
|
|
*((char *)frameplace + (ydim/2)*bytesperline + x) = yellow;
|
|
|
|
*((char *)frameplace + (ydim/2+1)*bytesperline + x) = purple;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
if (umost[x] >= 0 && umost[x] < ydim)
|
2011-05-12 23:31:13 +00:00
|
|
|
*((char *)frameplace + umost[x]*bytesperline + x) = purple;
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
if (dmost[x]-1 >= 0 && dmost[x]-1 < ydim)
|
2011-05-12 23:31:13 +00:00
|
|
|
*((char *)frameplace + (dmost[x]-1)*bytesperline + x) = yellow;
|
|
|
|
}
|
2011-05-07 18:23:34 +00:00
|
|
|
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
Bsprintf(tmpbuf, "nmp%d l%d b%d s%d w%d", yax_nomaskpass, yax_globallev-YAX_MAXDRAWS,
|
|
|
|
yax_globalbunch, sectnum, wallnum);
|
|
|
|
printext256(8,8, whitecol,0, tmpbuf, 0);
|
|
|
|
|
2011-05-07 18:23:34 +00:00
|
|
|
Bsprintf(fn, "engshot%04d.png", engine_screenshot);
|
2018-04-12 21:03:47 +00:00
|
|
|
videoCaptureScreen(fn, 0);
|
2011-05-07 18:23:34 +00:00
|
|
|
engine_screenshot++;
|
2011-05-12 23:31:13 +00:00
|
|
|
|
|
|
|
Bmemcpy((char *)frameplace, bakframe, xdim*ydim);
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2014-10-29 17:04:28 +00:00
|
|
|
|
2019-06-25 11:29:08 +00:00
|
|
|
Xaligned_free(bakframe);
|
2011-05-07 18:23:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-19 17:41:53 +00:00
|
|
|
// High-precision integer type for view-relative x and y in drawvox().
|
|
|
|
typedef zint_t voxint_t;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// drawvox
|
|
|
|
//
|
2018-04-12 21:04:00 +00:00
|
|
|
static void classicDrawVoxel(int32_t dasprx, int32_t daspry, int32_t dasprz, int32_t dasprang,
|
|
|
|
int32_t daxscale, int32_t dayscale, int32_t daindex,
|
2019-06-25 11:30:27 +00:00
|
|
|
int8_t dashade, char dapal, const int32_t *daumost, const int32_t *dadmost,
|
2019-07-09 05:42:15 +00:00
|
|
|
const int8_t cstat, const int32_t clipcf, int32_t floorz, int32_t ceilingz)
|
2009-01-09 09:29:17 +00:00
|
|
|
{
|
2019-08-01 06:50:37 +00:00
|
|
|
int32_t i, j, k, x, y, mip;
|
2014-12-26 17:29:48 +00:00
|
|
|
|
2019-06-25 11:29:42 +00:00
|
|
|
int32_t cosang = cosglobalang;
|
|
|
|
int32_t sinang = singlobalang;
|
2014-12-26 17:29:48 +00:00
|
|
|
int32_t sprcosang = sintable[(dasprang+512)&2047];
|
|
|
|
int32_t sprsinang = sintable[dasprang&2047];
|
|
|
|
|
|
|
|
i = klabs(dmulscale6(dasprx-globalposx, cosang, daspry-globalposy, sinang));
|
2012-12-14 19:27:58 +00:00
|
|
|
j = getpalookup(mulscale21(globvis,i), dashade)<<8;
|
2014-12-26 17:29:48 +00:00
|
|
|
setupdrawslab(ylookup[1], FP_OFF(palookup[dapal])+j);
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
j = 1310720;
|
2019-08-01 06:50:37 +00:00
|
|
|
//j *= min(daxscale,dayscale); j >>= 6; //New hacks (for sized-down voxels)
|
2009-02-19 16:47:54 +00:00
|
|
|
for (k=0; k<MAXVOXMIPS; k++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
if (i < j) { i = k; break; }
|
|
|
|
j <<= 1;
|
|
|
|
}
|
2014-12-26 17:29:48 +00:00
|
|
|
if (k >= MAXVOXMIPS)
|
|
|
|
i = MAXVOXMIPS-1;
|
|
|
|
|
2019-08-01 06:50:37 +00:00
|
|
|
mip = 0;
|
|
|
|
|
2014-12-26 17:29:48 +00:00
|
|
|
if (novoxmips)
|
2019-08-01 06:50:37 +00:00
|
|
|
{
|
|
|
|
mip = i;
|
2014-12-26 17:29:48 +00:00
|
|
|
i = 0;
|
2019-08-01 06:50:37 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-26 17:29:48 +00:00
|
|
|
char *davoxptr = (char *)voxoff[daindex][i];
|
2019-08-01 06:50:37 +00:00
|
|
|
if (!davoxptr && i > 0) { davoxptr = (char *)voxoff[daindex][0]; mip = i; i = 0;}
|
2014-12-26 17:29:48 +00:00
|
|
|
if (!davoxptr)
|
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (voxscale[daindex] == 65536)
|
2007-12-12 17:42:14 +00:00
|
|
|
{ daxscale <<= (i+8); dayscale <<= (i+8); }
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
daxscale = mulscale8(daxscale<<i,voxscale[daindex]);
|
|
|
|
dayscale = mulscale8(dayscale<<i,voxscale[daindex]);
|
|
|
|
}
|
|
|
|
|
2014-12-26 17:29:48 +00:00
|
|
|
const int32_t odayscale = dayscale;
|
2006-04-13 20:47:06 +00:00
|
|
|
daxscale = mulscale16(daxscale,xyaspect);
|
2014-12-26 17:29:48 +00:00
|
|
|
daxscale = scale(daxscale, xdimenscale, xdimen<<8);
|
|
|
|
dayscale = scale(dayscale, mulscale16(xdimenscale,viewingrangerecip), xdimen<<8);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-26 17:29:48 +00:00
|
|
|
const int32_t daxscalerecip = divideu32_noinline(1<<30, daxscale);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-26 17:29:48 +00:00
|
|
|
int32_t *longptr = (int32_t *)davoxptr;
|
2018-05-23 15:04:52 +00:00
|
|
|
const int32_t daxsiz = B_LITTLE32(longptr[0]), daysiz = B_LITTLE32(longptr[1]), dazsiz = B_LITTLE32(longptr[2]);
|
2019-07-13 03:20:17 +00:00
|
|
|
int32_t daxpivot = B_LITTLE32(longptr[3]), daypivot = B_LITTLE32(longptr[4]), dazpivot = B_LITTLE32(longptr[5]);
|
2019-06-25 11:30:27 +00:00
|
|
|
if (cstat & 4) daxpivot = (daxsiz<<8)-daxpivot;
|
2006-04-13 20:47:06 +00:00
|
|
|
davoxptr += (6<<2);
|
|
|
|
|
2014-12-26 17:29:48 +00:00
|
|
|
x = mulscale16(globalposx-dasprx, daxscalerecip);
|
|
|
|
y = mulscale16(globalposy-daspry, daxscalerecip);
|
|
|
|
const int32_t backx = (dmulscale10(x,sprcosang, y,sprsinang)+daxpivot)>>8;
|
|
|
|
const int32_t backy = (dmulscale10(y,sprcosang, x,-sprsinang)+daypivot)>>8;
|
|
|
|
const int32_t cbackx = min(max(backx,0),daxsiz-1);
|
|
|
|
const int32_t cbacky = min(max(backy,0),daysiz-1);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-26 17:29:48 +00:00
|
|
|
sprcosang = mulscale14(daxscale, sprcosang);
|
|
|
|
sprsinang = mulscale14(daxscale, sprsinang);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-26 17:29:48 +00:00
|
|
|
x = (dasprx-globalposx) - dmulscale18(daxpivot,sprcosang, daypivot,-sprsinang);
|
|
|
|
y = (daspry-globalposy) - dmulscale18(daypivot,sprcosang, daxpivot,sprsinang);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-07-13 03:20:17 +00:00
|
|
|
cosang <<= 2;
|
|
|
|
sinang <<= 2;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-08-01 06:50:37 +00:00
|
|
|
cosang >>= mip;
|
|
|
|
sinang >>= mip;
|
|
|
|
|
2015-02-19 17:41:53 +00:00
|
|
|
const voxint_t gxstart = (voxint_t)y*cosang - (voxint_t)x*sinang;
|
|
|
|
const voxint_t gystart = (voxint_t)x*cosang + (voxint_t)y*sinang;
|
2014-12-26 17:29:48 +00:00
|
|
|
const int32_t gxinc = dmulscale10(sprsinang,cosang, sprcosang,-sinang);
|
|
|
|
const int32_t gyinc = dmulscale10(sprcosang,cosang, sprsinang,sinang);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
x = 0; y = 0; j = max(daxsiz,daysiz);
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<=j; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
ggxinc[i] = x; x += gxinc;
|
|
|
|
ggyinc[i] = y; y += gyinc;
|
|
|
|
}
|
|
|
|
|
2014-12-26 17:29:48 +00:00
|
|
|
if ((klabs(globalposz-dasprz)>>10) >= klabs(odayscale))
|
|
|
|
return;
|
|
|
|
|
2019-07-13 03:20:17 +00:00
|
|
|
int32_t zoff = dazsiz<<14;
|
|
|
|
if (!(cstat & 128))
|
|
|
|
zoff += dazpivot<<7;
|
|
|
|
else if ((cstat&48) != 48)
|
|
|
|
{
|
|
|
|
zoff += dazpivot<<7;
|
|
|
|
zoff -= dazsiz<<14;
|
|
|
|
}
|
|
|
|
|
|
|
|
const int32_t syoff = divscale21(globalposz-dasprz,odayscale)+zoff;
|
|
|
|
floorz = min(floorz, dasprz+mulscale21(-zoff+(dazsiz<<15),odayscale));
|
|
|
|
ceilingz = max(ceilingz, dasprz+mulscale21(-zoff, odayscale));
|
2019-07-09 05:42:15 +00:00
|
|
|
const int32_t flooroff = divscale21(floorz-globalposz,odayscale);
|
|
|
|
const int32_t ceilingoff = divscale21(ceilingz-globalposz,odayscale);
|
2014-12-26 17:29:48 +00:00
|
|
|
int32_t yoff = (klabs(gxinc)+klabs(gyinc))>>1;
|
2009-01-09 09:29:17 +00:00
|
|
|
longptr = (int32_t *)davoxptr;
|
2014-12-26 17:29:48 +00:00
|
|
|
int32_t xyvoxoffs = (daxsiz+1)<<2;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t cnt=0; cnt<8; cnt++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-12-26 17:29:48 +00:00
|
|
|
int32_t xs=0, ys=0, xi=0, yi=0;
|
|
|
|
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (cnt)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-11-13 23:12:47 +00:00
|
|
|
case 0:
|
2012-02-18 17:55:27 +00:00
|
|
|
xs = 0; ys = 0; xi = 1; yi = 1; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 1:
|
2012-02-18 17:55:27 +00:00
|
|
|
xs = daxsiz-1; ys = 0; xi = -1; yi = 1; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 2:
|
2012-02-18 17:55:27 +00:00
|
|
|
xs = 0; ys = daysiz-1; xi = 1; yi = -1; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 3:
|
2012-02-18 17:55:27 +00:00
|
|
|
xs = daxsiz-1; ys = daysiz-1; xi = -1; yi = -1; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 4:
|
2012-02-18 17:55:27 +00:00
|
|
|
xs = 0; ys = cbacky; xi = 1; yi = 2; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 5:
|
2012-02-18 17:55:27 +00:00
|
|
|
xs = daxsiz-1; ys = cbacky; xi = -1; yi = 2; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 6:
|
2012-02-18 17:55:27 +00:00
|
|
|
xs = cbackx; ys = 0; xi = 2; yi = 1; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 7:
|
2012-02-18 17:55:27 +00:00
|
|
|
xs = cbackx; ys = daysiz-1; xi = 2; yi = -1; break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2014-12-26 17:29:48 +00:00
|
|
|
|
|
|
|
int32_t xe = cbackx, ye = cbacky;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-12-26 17:29:48 +00:00
|
|
|
int32_t x1=0, y1=0, z1, x2=0, y2=0, z2;
|
|
|
|
|
|
|
|
i = ksgn(ys-backy) + ksgn(xs-backx)*3 + 4;
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (i)
|
|
|
|
{
|
|
|
|
case 6:
|
2012-01-15 22:39:38 +00:00
|
|
|
case 7:
|
|
|
|
x1 = 0; y1 = 0; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 8:
|
2012-01-15 22:39:38 +00:00
|
|
|
case 5:
|
|
|
|
x1 = gxinc; y1 = gyinc; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 0:
|
2012-01-15 22:39:38 +00:00
|
|
|
case 3:
|
|
|
|
x1 = gyinc; y1 = -gxinc; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 2:
|
2012-01-15 22:39:38 +00:00
|
|
|
case 1:
|
|
|
|
x1 = gxinc+gyinc; y1 = gyinc-gxinc; break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (i)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-11-13 23:12:47 +00:00
|
|
|
case 2:
|
2012-01-15 22:39:38 +00:00
|
|
|
case 5:
|
|
|
|
x2 = 0; y2 = 0; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 0:
|
2012-01-15 22:39:38 +00:00
|
|
|
case 1:
|
|
|
|
x2 = gxinc; y2 = gyinc; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 8:
|
2012-01-15 22:39:38 +00:00
|
|
|
case 7:
|
|
|
|
x2 = gyinc; y2 = -gxinc; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 6:
|
2012-01-15 22:39:38 +00:00
|
|
|
case 3:
|
|
|
|
x2 = gxinc+gyinc; y2 = gyinc-gxinc; break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2014-12-26 17:29:48 +00:00
|
|
|
|
2019-06-25 11:30:27 +00:00
|
|
|
char oand = pow2char[(xs<backx)+0] + pow2char[(ys<backy)+2];
|
|
|
|
|
|
|
|
if (cstat&4)
|
|
|
|
oand ^= 3;
|
|
|
|
|
|
|
|
char oand16 = oand+16;
|
|
|
|
char oand32 = oand+32;
|
|
|
|
|
|
|
|
if (cstat&8)
|
|
|
|
{
|
|
|
|
oand16 = oand+32;
|
|
|
|
oand32 = oand+16;
|
|
|
|
}
|
2014-12-26 17:29:48 +00:00
|
|
|
|
|
|
|
int32_t dagxinc, dagyinc;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (yi > 0) { dagxinc = gxinc; dagyinc = mulscale16(gyinc,viewingrangerecip); }
|
2006-04-13 20:47:06 +00:00
|
|
|
else { dagxinc = -gxinc; dagyinc = -mulscale16(gyinc,viewingrangerecip); }
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Fix for non 90 degree viewing ranges
|
2014-12-26 17:29:48 +00:00
|
|
|
const int32_t nxoff = mulscale16(x2-x1,viewingrangerecip);
|
|
|
|
x1 = mulscale16(x1, viewingrangerecip);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-19 17:41:53 +00:00
|
|
|
const voxint_t ggxstart = gxstart + ggyinc[ys];
|
|
|
|
const voxint_t ggystart = gystart - ggxinc[ys];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=xs; x!=xe; x+=xi)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-06-25 11:30:27 +00:00
|
|
|
const int32_t xf = (cstat & 4) ? daxsiz-1-x : x;
|
|
|
|
const intptr_t slabxoffs = (intptr_t)&davoxptr[B_LITTLE32(longptr[xf])];
|
|
|
|
int16_t *const shortptr = (int16_t *)&davoxptr[((xf*(daysiz+1))<<1) + xyvoxoffs];
|
2014-12-26 17:29:48 +00:00
|
|
|
|
2015-02-19 17:41:53 +00:00
|
|
|
voxint_t nx = mulscale16z(ggxstart+ggxinc[x], viewingrangerecip) + x1;
|
|
|
|
voxint_t ny = ggystart + ggyinc[x];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (y=ys; y!=ye; y+=yi,nx+=dagyinc,ny-=dagxinc)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-12-26 17:29:48 +00:00
|
|
|
if (ny <= nytooclose || ny >= nytoofar)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
char *voxptr = (char *)(B_LITTLE16(shortptr[y])+slabxoffs);
|
|
|
|
char *const voxend = (char *)(B_LITTLE16(shortptr[y+1])+slabxoffs);
|
|
|
|
if (voxptr == voxend)
|
|
|
|
continue;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-12-26 15:44:09 +00:00
|
|
|
// AMCTC V1 MEGABASE: (ny+y1)>>14 == 65547
|
|
|
|
// (after long corridor with the blinds)
|
2014-12-26 17:29:59 +00:00
|
|
|
//
|
|
|
|
// Also, OOB (<0?) in my amcvoxels_crash.map.
|
|
|
|
const int32_t il = clamp((ny+y1)>>14, 1, DISTRECIPSIZ-1);
|
|
|
|
int32_t lx = mulscale32(nx>>3, distrecip[il]) + halfxdimen;
|
2014-12-26 17:29:48 +00:00
|
|
|
if (lx < 0)
|
|
|
|
lx = 0;
|
|
|
|
|
2014-12-26 17:29:59 +00:00
|
|
|
const int32_t ir = clamp((ny+y2)>>14, 1, DISTRECIPSIZ-1);
|
|
|
|
int32_t rx = mulscale32((nx+nxoff)>>3, distrecip[ir]) + halfxdimen;
|
2014-12-26 17:29:48 +00:00
|
|
|
if (rx > xdimen)
|
|
|
|
rx = xdimen;
|
|
|
|
|
|
|
|
if (rx <= lx)
|
|
|
|
continue;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
rx -= lx;
|
|
|
|
|
2019-08-01 06:50:37 +00:00
|
|
|
const int32_t l1 = mulscale(distrecip[clamp((ny-yoff)>>14, 1, DISTRECIPSIZ-1)], dayscale, 12+mip);
|
2011-12-15 22:42:42 +00:00
|
|
|
// FIXME! AMCTC RC2/beta shotgun voxel
|
|
|
|
// (e.g. training map right after M16 shooting):
|
2019-08-01 06:50:37 +00:00
|
|
|
const int32_t l2 = mulscale(distrecip[clamp((ny+yoff)>>14, 1, DISTRECIPSIZ-1)], dayscale, 12+mip);
|
2019-07-09 05:42:15 +00:00
|
|
|
int32_t cz1 = 0, cz2 = INT32_MAX;
|
|
|
|
|
|
|
|
if (clipcf)
|
|
|
|
{
|
|
|
|
cz1 = mulscale32((ceilingoff < 0) ? l1 : l2, ceilingoff) + globalhoriz;
|
|
|
|
cz2 = mulscale32((flooroff < 0) ? l2 : l1, flooroff) + globalhoriz;
|
|
|
|
}
|
2014-12-26 17:29:48 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (; voxptr<voxend; voxptr+=voxptr[1]+3)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-06-25 11:30:27 +00:00
|
|
|
if (cstat&8)
|
|
|
|
j = dazsiz-voxptr[0]-voxptr[1];
|
|
|
|
else
|
|
|
|
j = voxptr[0];
|
|
|
|
j = (j<<15)-syoff;
|
2014-12-26 17:29:48 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-12-26 17:29:48 +00:00
|
|
|
int32_t yplc, yinc=0;
|
|
|
|
|
2019-07-09 05:42:15 +00:00
|
|
|
const int32_t um = max(daumost[lx], cz1);
|
|
|
|
const int32_t dm = min(dadmost[lx], cz2);
|
2006-04-13 20:47:06 +00:00
|
|
|
if (voxptr[1] == 1)
|
|
|
|
{
|
|
|
|
yplc = 0; yinc = 0;
|
2019-07-09 05:42:15 +00:00
|
|
|
if (z1 < um)
|
|
|
|
z1 = um;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-12-26 17:29:48 +00:00
|
|
|
if (z2-z1 >= 1024)
|
|
|
|
yinc = divscale16(voxptr[1], z2-z1);
|
|
|
|
else if (z2 > z1)
|
|
|
|
yinc = lowrecip[z2-z1]*voxptr[1]>>8;
|
|
|
|
|
2019-07-09 05:42:15 +00:00
|
|
|
if (z1 < um) { yplc = yinc*(um-z1); z1 = um; }
|
2007-12-12 17:42:14 +00:00
|
|
|
else yplc = 0;
|
2019-06-25 11:30:27 +00:00
|
|
|
|
|
|
|
if (cstat & 8)
|
|
|
|
yinc = -yinc;
|
|
|
|
if (cstat & 8)
|
|
|
|
yplc = ((voxptr[1])<<16) - yplc + yinc;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2019-07-09 05:42:15 +00:00
|
|
|
if (z2 > dm)
|
|
|
|
z2 = dm;
|
2014-12-26 17:29:48 +00:00
|
|
|
z2 -= z1;
|
|
|
|
if (z2 <= 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
drawslab(rx, yplc, z2, yinc, (intptr_t)&voxptr[3], ylookup[z1]+lx+frameoffset);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-18 13:02:08 +00:00
|
|
|
#if 0
|
|
|
|
for (x=0; x<xdimen; x++)
|
|
|
|
{
|
|
|
|
if (daumost[x]>=0 && daumost[x]<ydimen)
|
|
|
|
*(char *)(frameplace + x + bytesperline*daumost[x]) = editorcolors[13];
|
|
|
|
if (dadmost[x]>=0 && dadmost[x]<ydimen)
|
|
|
|
*(char *)(frameplace + x + bytesperline*dadmost[x]) = editorcolors[14];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2012-07-06 11:26:24 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
static void setup_globals_sprite1(tspriteptr_t tspr, usectorptr_t sec,
|
2012-06-26 19:49:48 +00:00
|
|
|
int32_t yspan, int32_t yoff, int32_t tilenum,
|
|
|
|
int32_t cstat, int32_t *z1ptr, int32_t *z2ptr)
|
|
|
|
{
|
2012-07-06 11:26:24 +00:00
|
|
|
int32_t logtilesizy, tsizy;
|
2012-06-26 19:49:48 +00:00
|
|
|
int32_t z1, 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 >= MAXTILES) globalpicnum = 0;
|
2013-11-22 19:26:21 +00:00
|
|
|
// sprite panning
|
2014-09-30 04:14:21 +00:00
|
|
|
globalxpanning = (((256-spriteext[tspr->owner].xpanning)&255) * tilesiz[globalpicnum].x)>>8;
|
2012-06-26 19:49:48 +00:00
|
|
|
globalypanning = 0;
|
|
|
|
|
|
|
|
globvis = globalvisibility;
|
2012-12-14 19:28:05 +00:00
|
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis, (uint8_t)(sec->visibility+16));
|
2012-06-26 19:49:48 +00:00
|
|
|
|
2012-07-06 11:26:24 +00:00
|
|
|
logtilesizy = (picsiz[globalpicnum]>>4);
|
2014-09-30 04:14:21 +00:00
|
|
|
tsizy = tilesiz[globalpicnum].y;
|
2012-07-06 11:26:24 +00:00
|
|
|
|
|
|
|
globalshiftval = logtilesizy;
|
2012-09-28 15:20:13 +00:00
|
|
|
#if !defined CLASSIC_NONPOW2_YSIZE_SPRITES
|
2012-07-06 11:26:24 +00:00
|
|
|
// before proper non-power-of-two tilesizy drawing
|
2012-09-28 15:20:03 +00:00
|
|
|
if (pow2long[logtilesizy] != tsizy)
|
2012-07-06 11:26:24 +00:00
|
|
|
globalshiftval++;
|
|
|
|
#else
|
|
|
|
// non power-of-two y size textures!
|
2012-12-23 13:59:52 +00:00
|
|
|
if (pow2long[logtilesizy] != tsizy || tsizy >= 512)
|
2012-07-06 11:26:24 +00:00
|
|
|
{
|
|
|
|
globaltilesizy = tsizy;
|
|
|
|
globalyscale = (1<<22)/(tsizy*tspr->yrepeat);
|
|
|
|
globalshiftval = 0;
|
|
|
|
}
|
2012-12-23 13:59:52 +00:00
|
|
|
else
|
2012-09-28 15:20:03 +00:00
|
|
|
#endif
|
2012-12-23 13:59:52 +00:00
|
|
|
{
|
|
|
|
globalshiftval = 32-globalshiftval;
|
|
|
|
globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
|
|
|
|
}
|
2012-06-26 19:49:48 +00:00
|
|
|
|
|
|
|
globalzd = ((int64_t)(globalposz-z1)*globalyscale)<<8;
|
|
|
|
if ((cstat&8) > 0)
|
|
|
|
{
|
|
|
|
globalyscale = -globalyscale;
|
|
|
|
globalzd = ((int64_t)(globalposz-z2)*globalyscale)<<8;
|
|
|
|
}
|
|
|
|
|
|
|
|
*z1ptr = z1;
|
|
|
|
*z2ptr = z2;
|
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// drawsprite (internal)
|
|
|
|
//
|
|
|
|
|
2016-10-14 07:33:30 +00:00
|
|
|
static size_t falpha_to_blend(float alpha, int32_t *cstatptr, uint8_t *blendptr, int32_t transbit1, int32_t transbit2)
|
2014-04-09 18:51:31 +00:00
|
|
|
{
|
2016-10-09 07:55:18 +00:00
|
|
|
int32_t cstat = *cstatptr | transbit1;
|
2014-04-09 18:51:31 +00:00
|
|
|
|
2016-10-14 07:40:32 +00:00
|
|
|
int32_t const twonumalphatabs = 2*numalphatabs + (numalphatabs&1);
|
2016-10-14 07:33:30 +00:00
|
|
|
int32_t blendidx = Blrintf(alpha * twonumalphatabs);
|
2014-04-09 18:51:31 +00:00
|
|
|
if (blendidx > numalphatabs)
|
|
|
|
{
|
2016-10-14 07:33:30 +00:00
|
|
|
blendidx = twonumalphatabs - blendidx;
|
2014-04-09 18:51:31 +00:00
|
|
|
cstat |= transbit2;
|
|
|
|
}
|
2016-10-09 07:55:18 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cstat &= ~transbit2;
|
|
|
|
}
|
2016-10-14 07:33:30 +00:00
|
|
|
|
|
|
|
if (blendidx < 1)
|
|
|
|
return cstat&transbit2;
|
|
|
|
|
2014-04-09 18:51:31 +00:00
|
|
|
// blendidx now in [1 .. numalphatabs]
|
|
|
|
|
|
|
|
*cstatptr = cstat;
|
2016-10-14 07:33:30 +00:00
|
|
|
*blendptr = blendidx;
|
|
|
|
return 0;
|
2014-04-09 18:51:31 +00:00
|
|
|
}
|
|
|
|
|
2017-02-25 08:15:53 +00:00
|
|
|
static FORCE_INLINE int32_t mulscale_triple30(int32_t a, int32_t b, int32_t c)
|
2015-02-19 17:41:53 +00:00
|
|
|
{
|
|
|
|
return ((int64_t)a * b * c)>>30;
|
|
|
|
}
|
|
|
|
|
2018-04-12 21:04:00 +00:00
|
|
|
static void classicDrawSprite(int32_t snum)
|
2013-02-10 16:24:04 +00:00
|
|
|
{
|
2019-04-18 17:24:10 +00:00
|
|
|
auto const tspr = tspriteptr[snum];
|
2013-02-10 16:24:04 +00:00
|
|
|
const int32_t sectnum = tspr->sectnum;
|
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
if (sectnum < 0 || bad_tspr(tspr))
|
2013-04-29 19:24:19 +00:00
|
|
|
return;
|
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t x1, y1, x2, y2, i, j, k, x;
|
|
|
|
int32_t z, zz, z1, z2, xp1, yp1, xp2, yp2;
|
|
|
|
int32_t dax, day, dax1, dax2, y;
|
|
|
|
int32_t vtilenum = 0;
|
|
|
|
|
2013-04-29 19:24:19 +00:00
|
|
|
|
2014-12-30 20:05:20 +00:00
|
|
|
uint8_t blendidx = tspr->blend;
|
|
|
|
const int32_t xb = spritesxyz[snum].x;
|
|
|
|
const int32_t yp = spritesxyz[snum].y;
|
|
|
|
|
|
|
|
const int32_t spritenum = tspr->owner;
|
|
|
|
const float alpha = spriteext[spritenum].alpha;
|
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const sec = (usectorptr_t)§or[sectnum];
|
2014-12-30 20:05:20 +00:00
|
|
|
|
|
|
|
int32_t cstat=tspr->cstat, tilenum;
|
|
|
|
|
2019-07-09 05:42:10 +00:00
|
|
|
if ((cstat&48) != 48)
|
|
|
|
tileUpdatePicnum(&tspr->picnum, spritenum+32768);
|
2013-03-25 04:31:31 +00:00
|
|
|
|
2016-10-09 07:55:18 +00:00
|
|
|
if (!(cstat&2) && alpha > 0.0f)
|
2013-03-25 04:31:31 +00:00
|
|
|
{
|
2014-04-09 18:51:31 +00:00
|
|
|
if (alpha >= 1.0f)
|
|
|
|
return;
|
2013-03-25 04:31:31 +00:00
|
|
|
|
2014-04-09 18:51:31 +00:00
|
|
|
if (numalphatabs != 0)
|
|
|
|
{
|
2016-10-14 07:33:30 +00:00
|
|
|
if (falpha_to_blend(alpha, &cstat, &blendidx, 2, 512))
|
|
|
|
return;
|
2014-04-09 18:51:31 +00:00
|
|
|
}
|
2016-10-09 07:55:13 +00:00
|
|
|
else if (alpha >= 1.f/3.f)
|
2013-03-25 04:31:31 +00:00
|
|
|
{
|
|
|
|
cstat |= 2;
|
|
|
|
|
2016-10-09 07:55:13 +00:00
|
|
|
if (alpha >= 2.f/3.f)
|
2013-03-25 04:31:31 +00:00
|
|
|
cstat |= 512;
|
2016-10-09 07:55:18 +00:00
|
|
|
else
|
|
|
|
cstat &= ~512;
|
2019-09-19 20:02:45 +00:00
|
|
|
|
|
|
|
// Blood's transparency table is inverted
|
|
|
|
if (bloodhack)
|
|
|
|
cstat ^= 512;
|
2013-03-25 04:31:31 +00:00
|
|
|
}
|
2016-10-09 07:55:13 +00:00
|
|
|
|
|
|
|
tspr->cstat = cstat;
|
2013-03-25 04:31:31 +00:00
|
|
|
}
|
2013-03-19 06:23:38 +00:00
|
|
|
|
|
|
|
tilenum = tspr->picnum;
|
|
|
|
|
2013-02-10 16:24:04 +00:00
|
|
|
if ((cstat&48)==48)
|
|
|
|
vtilenum = tilenum; // if the game wants voxels, it gets voxels
|
2019-07-09 05:42:15 +00:00
|
|
|
else if ((cstat & 48) != 32 && usevoxels && tiletovox[tilenum] != -1 && spritenum != -1 && !(spriteext[spritenum].flags&SPREXT_NOTMD))
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2006-04-13 20:47:06 +00:00
|
|
|
vtilenum = tiletovox[tilenum];
|
|
|
|
cstat |= 48;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((cstat&48) != 48)
|
|
|
|
{
|
2014-09-30 04:14:21 +00:00
|
|
|
if (spritenum < 0 || tilesiz[tilenum].x <= 0 || tilesiz[tilenum].y <= 0)
|
2006-04-13 20:47:06 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-10-25 23:29:38 +00:00
|
|
|
if (!tspr->xrepeat || !tspr->yrepeat)
|
2013-02-10 16:24:04 +00:00
|
|
|
return;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
globalpal = tspr->pal;
|
2006-11-20 04:56:22 +00:00
|
|
|
if (palookup[globalpal] == NULL) globalpal = 0; // JBF: fixes null-pointer crash
|
2006-04-13 20:47:06 +00:00
|
|
|
globalshade = tspr->shade;
|
2013-02-10 16:24:04 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (cstat&2)
|
2014-04-09 18:51:31 +00:00
|
|
|
setup_blend(blendidx, cstat&512);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
vec2_t off = { picanm[tilenum].xofs + tspr->xoffset, picanm[tilenum].yofs + tspr->yoffset };
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((cstat&48) == 0)
|
|
|
|
{
|
2014-12-13 22:32:57 +00:00
|
|
|
int32_t startum, startdm;
|
2014-12-05 23:12:36 +00:00
|
|
|
int32_t linum, linuminc;
|
2013-02-10 16:24:04 +00:00
|
|
|
|
2012-06-07 17:37:57 +00:00
|
|
|
draw_as_face_sprite:
|
2006-04-13 20:47:06 +00:00
|
|
|
if (yp <= (4<<8)) return;
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
int const isiz = divscale19(xdimenscale,yp);
|
|
|
|
int const xv = mulscale16(((int32_t)tspr->xrepeat)<<16,xyaspect);
|
2019-06-25 11:28:09 +00:00
|
|
|
vec2_16_t const span = tilesiz[tilenum];
|
2016-06-21 00:34:18 +00:00
|
|
|
vec2_t const siz = { mulscale30(isiz, xv * span.x), mulscale14(isiz, tspr->yrepeat * span.y) };
|
2014-12-05 23:12:36 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((span.x>>11) >= siz.x || span.y >= (siz.y>>1)))
|
2006-04-13 20:47:06 +00:00
|
|
|
return; //Watch out for divscale overflow
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
x1 = xb-(siz.x>>1);
|
|
|
|
if (span.x&1) x1 += mulscale31(isiz,xv); //Odd xspans
|
|
|
|
i = mulscale30(isiz,xv*off.x);
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((cstat&4) == 0) x1 -= i; else x1 += i;
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
y1 = mulscale16(tspr->z-globalposz,isiz);
|
|
|
|
y1 -= mulscale14(isiz,tspr->yrepeat*off.y);
|
|
|
|
y1 += (globalhoriz<<8)-siz.y;
|
2006-04-13 20:47:06 +00:00
|
|
|
if (cstat&128)
|
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
y1 += (siz.y>>1);
|
|
|
|
if (span.y&1) y1 += mulscale15(isiz,tspr->yrepeat); //Odd yspans
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
x2 = x1+siz.x-1;
|
|
|
|
y2 = y1+siz.y-1;
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((y1|255) >= (y2|255)) return;
|
|
|
|
|
2014-12-13 22:32:57 +00:00
|
|
|
int32_t lx = (x1>>8)+1; if (lx < 0) lx = 0;
|
|
|
|
int32_t rx = (x2>>8); if (rx >= xdimen) rx = xdimen-1;
|
2006-04-13 20:47:06 +00:00
|
|
|
if (lx > rx) return;
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
startum = ((sec->ceilingstat&3) == 0) ? globalhoriz+mulscale24(isiz,sec->ceilingz-globalposz)-1 : 0;
|
|
|
|
startdm = ((sec->floorstat&3) == 0) ? globalhoriz+mulscale24(isiz,sec->floorz-globalposz)+1 : INT32_MAX;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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)
|
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
linuminc = divscale24(span.x,siz.x);
|
2006-04-13 20:47:06 +00:00
|
|
|
linum = mulscale8((lx<<8)-x1,linuminc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
linuminc = -divscale24(span.x,siz.x);
|
2006-04-13 20:47:06 +00:00
|
|
|
linum = mulscale8((lx<<8)-x2,linuminc);
|
|
|
|
}
|
2013-02-10 16:24:04 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((cstat&8) > 0)
|
2013-02-10 16:24:04 +00:00
|
|
|
swaplong(&y1, &y2);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-10-25 03:29:21 +00:00
|
|
|
x = lx;
|
|
|
|
#ifdef CLASSIC_SLICE_BY_4
|
|
|
|
for (; x<=rx-4; x+=4)
|
|
|
|
{
|
2018-10-16 06:09:54 +00:00
|
|
|
uwall[x] = max<int>(startumost[windowxy1.x+x]-windowxy1.y, startum);
|
|
|
|
uwall[x+1] = max<int>(startumost[windowxy1.x+x+1]-windowxy1.y, startum);
|
|
|
|
uwall[x+2] = max<int>(startumost[windowxy1.x+x+2]-windowxy1.y, startum);
|
|
|
|
uwall[x+3] = max<int>(startumost[windowxy1.x+x+3]-windowxy1.y, startum);
|
2014-10-25 03:29:21 +00:00
|
|
|
|
2018-10-16 06:09:54 +00:00
|
|
|
dwall[x] = min<int>(startdmost[windowxy1.x+x]-windowxy1.y, startdm);
|
|
|
|
dwall[x+1] = min<int>(startdmost[windowxy1.x+x+1]-windowxy1.y, startdm);
|
|
|
|
dwall[x+2] = min<int>(startdmost[windowxy1.x+x+2]-windowxy1.y, startdm);
|
|
|
|
dwall[x+3] = min<int>(startdmost[windowxy1.x+x+3]-windowxy1.y, startdm);
|
2014-10-25 03:29:21 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
for (; x<=rx; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-10-16 06:09:54 +00:00
|
|
|
uwall[x] = max<int>(startumost[windowxy1.x+x]-windowxy1.y,startum);
|
|
|
|
dwall[x] = min<int>(startdmost[windowxy1.x+x]-windowxy1.y,startdm);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2013-02-10 16:24:04 +00:00
|
|
|
|
2014-12-13 22:32:57 +00:00
|
|
|
int32_t daclip = 0;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=smostwallcnt-1; i>=0; i--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
if (smostwalltype[i]&daclip) continue;
|
|
|
|
j = smostwall[i];
|
|
|
|
if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
|
|
|
|
if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
|
2009-01-09 09:29:17 +00:00
|
|
|
if (spritewallfront(tspr,(int32_t)thewall[j]) && ((yp <= yb1[j]) || (yp <= yb2[j]))) continue;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-13 22:32:57 +00:00
|
|
|
const int32_t dalx2 = max(xb1[j],lx);
|
|
|
|
const int32_t darx2 = min(xb2[j],rx);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (smostwalltype[i])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
case 0:
|
2012-02-18 17:55:27 +00:00
|
|
|
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;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
2012-02-18 17:55:27 +00:00
|
|
|
k = smoststart[i] - xb1[j];
|
2014-10-25 03:29:21 +00:00
|
|
|
x = dalx2;
|
|
|
|
#ifdef CLASSIC_SLICE_BY_4 // ok, this one is really by 2 ;)
|
2014-10-25 03:30:38 +00:00
|
|
|
for (; x<=darx2-2; x+=2)
|
2014-10-25 03:29:21 +00:00
|
|
|
{
|
|
|
|
if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
|
|
|
|
if (smost[k+x+1] > uwall[x+1]) uwall[x+1] = smost[k+x+1];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
for (; x<=darx2; x++)
|
2006-04-24 19:04:22 +00:00
|
|
|
if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
|
|
|
|
if ((dalx2 == lx) && (darx2 == rx)) daclip |= 1;
|
|
|
|
break;
|
|
|
|
case 2:
|
2012-02-18 17:55:27 +00:00
|
|
|
k = smoststart[i] - xb1[j];
|
2014-10-25 03:29:21 +00:00
|
|
|
x = dalx2;
|
|
|
|
#ifdef CLASSIC_SLICE_BY_4
|
|
|
|
for (; x<=darx2-4; x+=4)
|
|
|
|
{
|
|
|
|
if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
|
|
|
|
if (smost[k+x+1] < dwall[x+1]) dwall[x+1] = smost[k+x+1];
|
|
|
|
if (smost[k+x+2] < dwall[x+2]) dwall[x+2] = smost[k+x+2];
|
|
|
|
if (smost[k+x+3] < dwall[x+3]) dwall[x+3] = smost[k+x+3];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
for (; x<=darx2; x++)
|
2006-04-24 19:04:22 +00:00
|
|
|
if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
|
|
|
|
if ((dalx2 == lx) && (darx2 == rx)) daclip |= 2;
|
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uwall[rx] >= dwall[rx])
|
|
|
|
{
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=lx; x<rx; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (uwall[x] < dwall[x]) break;
|
|
|
|
if (x == rx) return;
|
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//sprite
|
2011-08-18 22:01:18 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (yax_globallev==YAX_MAXDRAWS || searchit==2)
|
|
|
|
#endif
|
2014-12-27 17:17:50 +00:00
|
|
|
if (searchit >= 1 && (searchx >= lx && searchx <= rx))
|
|
|
|
if (searchy >= uwall[searchx] && searchy < dwall[searchx])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
searchsector = sectnum; searchwall = spritenum;
|
|
|
|
searchstat = 3; searchit = 1;
|
|
|
|
}
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
setup_globals_sprite1(tspr, sec, span.y, off.y, tilenum, cstat, &z1, &z2);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2008-04-25 11:21:08 +00:00
|
|
|
qinterpolatedown16((intptr_t)&lwall[lx],rx-lx+1,linum,linuminc);
|
2006-04-13 20:47:06 +00:00
|
|
|
clearbuf(&swall[lx],rx-lx+1,mulscale19(yp,xdimscale));
|
|
|
|
|
2013-02-14 16:02:12 +00:00
|
|
|
{
|
|
|
|
#ifdef HIGH_PRECISION_SPRITE
|
|
|
|
union { float f; int32_t i; } sw = {
|
|
|
|
// initialize the float of the union
|
|
|
|
((cstat&8) ? -1 : 1)
|
|
|
|
* (float)yp * xdimscale
|
2016-06-21 00:34:18 +00:00
|
|
|
* (1<<(22-19)) / (span.y*tspr->yrepeat)
|
2013-02-14 16:02:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
clearbuf(&swallf[lx], rx-lx+1, sw.i);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
drawing_sprite = 1;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((cstat&2) == 0)
|
2013-11-16 18:47:11 +00:00
|
|
|
maskwallscan(lx,rx, (cstat&8)==0);
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
2013-11-16 18:47:11 +00:00
|
|
|
transmaskwallscan(lx,rx, (cstat&8)==0);
|
2013-02-14 16:02:12 +00:00
|
|
|
|
|
|
|
drawing_sprite = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else if ((cstat&48) == 16)
|
|
|
|
{
|
2014-12-05 23:12:36 +00:00
|
|
|
const int32_t xspan = tilesiz[tilenum].x;
|
|
|
|
const int32_t yspan = tilesiz[tilenum].y;
|
2014-12-13 22:32:57 +00:00
|
|
|
const int32_t xv = tspr->xrepeat*sintable[(tspr->ang+2560+1536)&2047];
|
|
|
|
const int32_t yv = tspr->xrepeat*sintable[(tspr->ang+2048+1536)&2047];
|
2015-01-04 18:45:00 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
if ((cstat&4) > 0) off.x = -off.x;
|
|
|
|
if ((cstat&8) > 0) off.y = -off.y;
|
2015-01-04 18:45:00 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
i = (xspan>>1) + off.x;
|
2006-04-13 20:47:06 +00:00
|
|
|
x1 = tspr->x-globalposx-mulscale16(xv,i); x2 = x1+mulscale16(xv,xspan);
|
|
|
|
y1 = tspr->y-globalposy-mulscale16(yv,i); y2 = y1+mulscale16(yv,xspan);
|
|
|
|
|
2015-01-04 18:45:00 +00:00
|
|
|
vec2_t p1 = get_rel_coords(x1, y1);
|
|
|
|
vec2_t p2 = get_rel_coords(x2, y2);
|
|
|
|
|
|
|
|
if (p1.y <= 0 && p2.y <= 0)
|
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
x1 += globalposx; y1 += globalposy;
|
|
|
|
x2 += globalposx; y2 += globalposy;
|
|
|
|
|
2014-12-13 22:32:57 +00:00
|
|
|
int32_t swapped = 0;
|
2015-01-04 18:45:00 +00:00
|
|
|
if (dmulscale32(p1.x, p2.y, -p2.x, p1.y) >= 0) // If wall's NOT facing you
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-01-04 18:45:00 +00:00
|
|
|
if ((cstat&64) != 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const vec2_t pt = p2;
|
|
|
|
p2 = p1;
|
|
|
|
p1 = pt;
|
2006-04-13 20:47:06 +00:00
|
|
|
i = x1, x1 = x2, x2 = i;
|
|
|
|
i = y1, y1 = y2, y2 = i;
|
|
|
|
swapped = 1;
|
|
|
|
}
|
|
|
|
|
2015-01-04 18:45:00 +00:00
|
|
|
int32_t sx1, sx2, sy1, sy2;
|
|
|
|
if (!get_screen_coords(p1, p2, &sx1, &sy1, &sx2, &sy2))
|
2006-04-13 20:47:06 +00:00
|
|
|
return;
|
|
|
|
|
2015-01-04 18:45:00 +00:00
|
|
|
const int32_t topinc = -mulscale10(p1.y,xspan);
|
|
|
|
int32_t top = ((mulscale10(p1.x,xdimen) - mulscale9(sx1-halfxdimen,p1.y))*xspan)>>3;
|
|
|
|
const int32_t botinc = (p2.y-p1.y)>>8;
|
|
|
|
int32_t bot = mulscale11(p1.x-p2.x,xdimen) + mulscale2(sx1-halfxdimen,botinc);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-02-10 16:24:15 +00:00
|
|
|
j = sx2+3;
|
2006-04-13 20:47:06 +00:00
|
|
|
z = mulscale20(top,krecipasm(bot));
|
2013-02-10 16:24:15 +00:00
|
|
|
lwall[sx1] = (z>>8);
|
|
|
|
for (x=sx1+4; x<=j; x+=4)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
top += topinc; bot += botinc;
|
|
|
|
zz = z; z = mulscale20(top,krecipasm(bot));
|
|
|
|
i = ((z+zz)>>1);
|
|
|
|
lwall[x-3] = ((i+zz)>>9);
|
2014-10-29 17:04:28 +00:00
|
|
|
lwall[x-2] = (i>>8);
|
2006-04-13 20:47:06 +00:00
|
|
|
lwall[x-1] = ((i+z)>>9);
|
2014-10-29 17:04:28 +00:00
|
|
|
lwall[x] = (z>>8);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2013-02-10 16:24:15 +00:00
|
|
|
if (lwall[sx1] < 0) lwall[sx1] = 0;
|
|
|
|
if (lwall[sx2] >= xspan) lwall[sx2] = xspan-1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((swapped^((cstat&4)>0)) > 0)
|
|
|
|
{
|
|
|
|
j = xspan-1;
|
2013-02-10 16:24:15 +00:00
|
|
|
for (x=sx1; x<=sx2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
lwall[x] = j-lwall[x];
|
|
|
|
}
|
|
|
|
|
2013-02-10 16:24:15 +00:00
|
|
|
// XXX: UNUSED?
|
2015-01-04 18:45:00 +00:00
|
|
|
rx1[MAXWALLSB-1] = p1.x; ry1[MAXWALLSB-1] = p1.y;
|
|
|
|
rx2[MAXWALLSB-1] = p2.x; ry2[MAXWALLSB-1] = p2.y;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
setup_globals_sprite1(tspr, sec, yspan, off.y, tilenum, cstat, &z1, &z2);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-01-04 18:45:00 +00:00
|
|
|
if ((sec->ceilingstat&1) == 0 && z1 < sec->ceilingz)
|
2006-04-13 20:47:06 +00:00
|
|
|
z1 = sec->ceilingz;
|
2015-01-04 18:45:00 +00:00
|
|
|
if ((sec->floorstat&1) == 0 && z2 > sec->floorz)
|
2006-04-13 20:47:06 +00:00
|
|
|
z2 = sec->floorz;
|
|
|
|
|
2013-02-10 16:24:15 +00:00
|
|
|
xb1[MAXWALLSB-1] = sx1;
|
|
|
|
xb2[MAXWALLSB-1] = sx2;
|
|
|
|
yb1[MAXWALLSB-1] = sy1;
|
|
|
|
yb2[MAXWALLSB-1] = sy2;
|
|
|
|
owallmost(uwall, MAXWALLSB-1, z1-globalposz);
|
|
|
|
owallmost(dwall, MAXWALLSB-1, z2-globalposz);
|
2013-02-14 16:02:12 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t hplc = divscale19(xdimenscale,sy1);
|
|
|
|
const int32_t hplc2 = divscale19(xdimenscale,sy2);
|
|
|
|
const int32_t idiv = sx2-sx1;
|
|
|
|
int32_t hinc[4] = { idiv ? tabledivide32(hplc2-hplc, idiv) : 0 };
|
2013-02-14 16:02:12 +00:00
|
|
|
|
|
|
|
#ifdef HIGH_PRECISION_SPRITE
|
2018-11-18 18:07:25 +00:00
|
|
|
float const cc = ((1<<19) * fxdimen * (float)yxaspect) * (1.f/320.f);
|
|
|
|
float const loopcc = ((cstat&8) ? -1.f : 1.f) * (float(1<<30) * float(1<<24)) / float(yspan * tspr->yrepeat);
|
|
|
|
|
|
|
|
float hplcf = cc / sy1;
|
|
|
|
float hincf[4] = { idiv ? (cc / sy2 - hplcf) / idiv : 0 };
|
2014-10-25 03:30:38 +00:00
|
|
|
|
|
|
|
#ifdef CLASSIC_SLICE_BY_4
|
2016-06-21 00:33:30 +00:00
|
|
|
hincf[1] = hincf[0] * 2.f;
|
|
|
|
hincf[2] = hincf[0] * 3.f;
|
|
|
|
hincf[3] = hincf[0] * 4.f;
|
2014-10-25 03:30:38 +00:00
|
|
|
#endif // CLASSIC_SLICE_BY_4
|
|
|
|
#endif // HIGH_PRECISION_SPRITE
|
|
|
|
#ifdef CLASSIC_SLICE_BY_4
|
2016-06-21 00:33:30 +00:00
|
|
|
hinc[1] = hinc[0]<<1;
|
|
|
|
hinc[2] = hinc[0]*3;
|
|
|
|
hinc[3] = hinc[0]<<2;
|
2013-02-14 16:02:12 +00:00
|
|
|
#endif
|
2016-06-21 00:33:30 +00:00
|
|
|
i = sx1;
|
2014-10-25 03:30:38 +00:00
|
|
|
|
|
|
|
#ifdef CLASSIC_SLICE_BY_4
|
2016-06-21 00:33:30 +00:00
|
|
|
for (; i<=sx2-4; i+=4)
|
|
|
|
{
|
|
|
|
swall[i] = (krecipasm(hplc)<<2);
|
|
|
|
swall[i+1] = (krecipasm(hplc+hinc[0])<<2);
|
|
|
|
swall[i+2] = (krecipasm(hplc+hinc[1])<<2);
|
|
|
|
swall[i+3] = (krecipasm(hplc+hinc[2])<<2);
|
|
|
|
hplc += hinc[3];
|
2014-10-25 03:30:38 +00:00
|
|
|
#ifdef HIGH_PRECISION_SPRITE
|
2016-06-21 00:33:30 +00:00
|
|
|
swallf[i] = loopcc/hplcf;
|
|
|
|
swallf[i+1] = loopcc/(hplcf+hincf[0]);
|
|
|
|
swallf[i+2] = loopcc/(hplcf+hincf[1]);
|
|
|
|
swallf[i+3] = loopcc/(hplcf+hincf[2]);
|
|
|
|
hplcf += hincf[3];
|
2014-10-25 03:30:38 +00:00
|
|
|
#endif // HIGH_PRECISION_SPRITE
|
2016-06-21 00:33:30 +00:00
|
|
|
}
|
2014-10-25 03:30:38 +00:00
|
|
|
#endif // CLASSIC_SLICE_BY_4
|
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
for (; i<=sx2; i++)
|
|
|
|
{
|
|
|
|
swall[i] = (krecipasm(hplc)<<2);
|
|
|
|
hplc += hinc[0];
|
2013-02-14 16:02:12 +00:00
|
|
|
#ifdef HIGH_PRECISION_SPRITE
|
2016-06-21 00:33:30 +00:00
|
|
|
swallf[i] = loopcc/hplcf;
|
|
|
|
hplcf += hincf[0];
|
2013-02-14 16:02:12 +00:00
|
|
|
#endif
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=smostwallcnt-1; i>=0; i--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
j = smostwall[i];
|
|
|
|
|
2015-01-04 18:45:00 +00:00
|
|
|
if (xb1[j] > sx2 || xb2[j] < sx1)
|
|
|
|
continue;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-13 22:32:57 +00:00
|
|
|
int32_t dalx2 = xb1[j];
|
|
|
|
int32_t darx2 = xb2[j];
|
|
|
|
|
2013-02-10 16:24:15 +00:00
|
|
|
if (max(sy1,sy2) > min(yb1[j],yb2[j]))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-02-10 16:24:15 +00:00
|
|
|
if (min(sy1,sy2) > max(yb1[j],yb2[j]))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-02-14 23:13:53 +00:00
|
|
|
x = INT32_MIN;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
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)
|
2012-02-14 23:13:53 +00:00
|
|
|
x = INT32_MIN;
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
2012-02-14 23:13:53 +00:00
|
|
|
x = INT32_MAX;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
|
|
|
//INTERSECTION!
|
2006-04-13 20:47:06 +00:00
|
|
|
x = (xp1-globalposx) + scale(xp2-xp1,z1,z1-z2);
|
|
|
|
y = (yp1-globalposy) + scale(yp2-yp1,z1,z1-z2);
|
|
|
|
|
2012-02-14 23:13:16 +00:00
|
|
|
yp1 = dmulscale14(x,cosviewingrangeglobalang,y,sinviewingrangeglobalang);
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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)
|
2007-12-12 17:42:14 +00:00
|
|
|
{ if (dalx2 < x) dalx2 = x; }
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
2007-12-12 17:42:14 +00:00
|
|
|
{ if (darx2 > x) darx2 = x; }
|
2012-02-14 23:13:53 +00:00
|
|
|
x = INT32_MIN+1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
2012-02-14 23:13:53 +00:00
|
|
|
x = INT32_MAX;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-02-14 23:13:53 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (x < 0)
|
|
|
|
{
|
2013-02-10 16:24:15 +00:00
|
|
|
if (dalx2 < sx1) dalx2 = sx1;
|
|
|
|
if (darx2 > sx2) darx2 = sx2;
|
2012-02-14 23:13:53 +00:00
|
|
|
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (smostwalltype[i])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
case 0:
|
2012-02-18 17:55:27 +00:00
|
|
|
if (dalx2 <= darx2)
|
|
|
|
{
|
2013-02-10 16:24:15 +00:00
|
|
|
if ((dalx2 == sx1) && (darx2 == sx2)) return;
|
2012-02-18 17:55:27 +00:00
|
|
|
//clearbufbyte(&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
|
|
|
|
for (k=dalx2; k<=darx2; k++) dwall[k] = 0;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
2012-02-18 17:55:27 +00:00
|
|
|
k = smoststart[i] - xb1[j];
|
2014-10-25 03:30:38 +00:00
|
|
|
x = dalx2;
|
|
|
|
#ifdef CLASSIC_SLICE_BY_4
|
|
|
|
for (; x<=darx2-2; x+=2)
|
|
|
|
{
|
|
|
|
if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
|
|
|
|
if (smost[k+x+1] > uwall[x+1]) uwall[x+1] = smost[k+x+1];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
for (; x<=darx2; x++)
|
2006-04-24 19:04:22 +00:00
|
|
|
if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
|
|
|
|
break;
|
|
|
|
case 2:
|
2012-02-18 17:55:27 +00:00
|
|
|
k = smoststart[i] - xb1[j];
|
2014-10-25 03:30:38 +00:00
|
|
|
x = dalx2;
|
|
|
|
#ifdef CLASSIC_SLICE_BY_4
|
|
|
|
for (; x<=darx2-4; x+=4)
|
|
|
|
{
|
|
|
|
if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
|
|
|
|
if (smost[k+x+1] < dwall[x+1]) dwall[x+1] = smost[k+x+1];
|
|
|
|
if (smost[k+x+2] < dwall[x+2]) dwall[x+2] = smost[k+x+2];
|
|
|
|
if (smost[k+x+3] < dwall[x+3]) dwall[x+3] = smost[k+x+3];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
for (; x<=darx2; x++)
|
2006-04-24 19:04:22 +00:00
|
|
|
if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
|
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//sprite
|
2011-08-18 22:01:18 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (yax_globallev==YAX_MAXDRAWS || searchit==2)
|
|
|
|
#endif
|
2014-12-27 17:17:50 +00:00
|
|
|
if (searchit >= 1 && (searchx >= sx1 && searchx <= sx2))
|
|
|
|
if (searchy >= uwall[searchx] && searchy <= dwall[searchx])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
searchsector = sectnum; searchwall = spritenum;
|
|
|
|
searchstat = 3; searchit = 1;
|
|
|
|
}
|
|
|
|
|
2013-02-14 16:02:12 +00:00
|
|
|
drawing_sprite = 1;
|
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if ((cstat&2) == 0)
|
2013-11-16 18:47:11 +00:00
|
|
|
maskwallscan(sx1,sx2, (cstat&8)==0);
|
2007-12-12 17:42:14 +00:00
|
|
|
else
|
2013-11-16 18:47:11 +00:00
|
|
|
transmaskwallscan(sx1,sx2, (cstat&8)==0);
|
2013-02-14 16:02:12 +00:00
|
|
|
|
|
|
|
drawing_sprite = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else if ((cstat&48) == 32)
|
|
|
|
{
|
|
|
|
if ((cstat&64) != 0)
|
|
|
|
if ((globalposz > tspr->z) == ((cstat&8)==0))
|
|
|
|
return;
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
if ((cstat&4) > 0) off.x = -off.x;
|
|
|
|
if ((cstat&8) > 0) off.y = -off.y;
|
2014-12-05 23:12:36 +00:00
|
|
|
|
|
|
|
const int32_t xspan = tilesiz[tilenum].x;
|
|
|
|
const int32_t yspan = tilesiz[tilenum].y;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Rotate center point
|
2006-04-13 20:47:06 +00:00
|
|
|
dax = tspr->x-globalposx;
|
|
|
|
day = tspr->y-globalposy;
|
|
|
|
rzi[0] = dmulscale10(cosglobalang,dax,singlobalang,day);
|
|
|
|
rxi[0] = dmulscale10(cosglobalang,day,-singlobalang,dax);
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Get top-left corner
|
2019-06-25 11:29:42 +00:00
|
|
|
int32_t cosang = dmulscale14(sintable[(tspr->ang+512)&2047], cosglobalang, sintable[tspr->ang&2047], singlobalang);
|
|
|
|
int32_t sinang = dmulscale14(sintable[(tspr->ang+512)&2047], -singlobalang, sintable[tspr->ang&2047], cosglobalang);
|
2016-06-21 00:34:18 +00:00
|
|
|
dax = ((xspan>>1)+off.x)*tspr->xrepeat;
|
|
|
|
day = ((yspan>>1)+off.y)*tspr->yrepeat;
|
2006-04-13 20:47:06 +00:00
|
|
|
rzi[0] += dmulscale12(sinang,dax,cosang,day);
|
|
|
|
rxi[0] += dmulscale12(sinang,day,-cosang,dax);
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Get other 3 corners
|
2006-04-13 20:47:06 +00:00
|
|
|
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;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Put all points on same z
|
2006-04-13 20:47:06 +00:00
|
|
|
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)
|
2007-12-12 17:42:14 +00:00
|
|
|
{ z = 0; z1 = 1; z2 = 3; }
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
2007-12-12 17:42:14 +00:00
|
|
|
{ z = 1; z1 = 0; z2 = 2; }
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
dax = rzi[z1]-rzi[z]; day = rxi[z1]-rxi[z];
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t bot = dmulscale8(dax,dax,day,day);
|
2013-02-10 16:24:04 +00:00
|
|
|
if ((klabs(dax)>>13) >= bot || (klabs(day)>>13) >= bot)
|
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
globalx1 = divscale18(dax,bot);
|
|
|
|
globalx2 = divscale18(day,bot);
|
|
|
|
|
|
|
|
dax = rzi[z2]-rzi[z]; day = rxi[z2]-rxi[z];
|
|
|
|
bot = dmulscale8(dax,dax,day,day);
|
2013-02-10 16:24:04 +00:00
|
|
|
if ((klabs(dax)>>13) >= bot || (klabs(day)>>13) >= bot)
|
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
globaly1 = divscale18(dax,bot);
|
|
|
|
globaly2 = divscale18(day,bot);
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Calculate globals for hline texture mapping function
|
2006-04-13 20:47:06 +00:00
|
|
|
globalxpanning = (rxi[z]<<12);
|
|
|
|
globalypanning = (rzi[z]<<12);
|
2018-11-18 18:07:25 +00:00
|
|
|
globalzd = decltype(globalzd)(ryi[z])<<12;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Clip polygon in 3-space
|
2014-12-13 22:32:57 +00:00
|
|
|
int32_t npoints = 4;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Clip edge 1
|
2014-12-13 22:32:57 +00:00
|
|
|
int32_t npoints2 = 0;
|
|
|
|
int32_t zzsgn = rxi[0]+rzi[0], zsgn;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=0; z<npoints; z++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2013-02-10 16:24:04 +00:00
|
|
|
int32_t t = divscale30(zsgn,zsgn-zzsgn);
|
2006-04-13 20:47:06 +00:00
|
|
|
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;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Clip edge 2
|
2006-04-13 20:47:06 +00:00
|
|
|
npoints = 0;
|
|
|
|
zzsgn = rxi2[0]-rzi2[0];
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=0; z<npoints2; z++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2013-02-10 16:24:04 +00:00
|
|
|
int32_t t = divscale30(zsgn,zsgn-zzsgn);
|
2006-04-13 20:47:06 +00:00
|
|
|
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;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Clip edge 3
|
2006-04-13 20:47:06 +00:00
|
|
|
npoints2 = 0;
|
|
|
|
zzsgn = ryi[0]*halfxdimen + (rzi[0]*(globalhoriz-0));
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=0; z<npoints; z++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2013-02-10 16:24:04 +00:00
|
|
|
int32_t t = divscale30(zsgn,zsgn-zzsgn);
|
2006-04-13 20:47:06 +00:00
|
|
|
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;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Clip edge 4
|
2006-04-13 20:47:06 +00:00
|
|
|
npoints = 0;
|
|
|
|
zzsgn = ryi2[0]*halfxdimen + (rzi2[0]*(globalhoriz-ydimen));
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=0; z<npoints2; z++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2013-02-10 16:24:04 +00:00
|
|
|
int32_t t = divscale30(zsgn,zsgn-zzsgn);
|
2006-04-13 20:47:06 +00:00
|
|
|
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;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Project onto screen
|
2014-12-13 22:32:57 +00:00
|
|
|
int32_t lpoint = -1, lmax = INT32_MAX;
|
|
|
|
int32_t rpoint = -1, rmax = INT32_MIN;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=0; z<npoints; z++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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);
|
2009-01-09 09:29:17 +00:00
|
|
|
if (ysi[z] < ((int32_t)0<<16)) ysi[z] = ((int32_t)0<<16);
|
|
|
|
if (ysi[z] > ((int32_t)ydimen<<16)) ysi[z] = ((int32_t)ydimen<<16);
|
2006-04-13 20:47:06 +00:00
|
|
|
if (xsi[z] < lmax) lmax = xsi[z], lpoint = z;
|
|
|
|
if (xsi[z] > rmax) rmax = xsi[z], rpoint = z;
|
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Get uwall arrays
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=lpoint; z!=rpoint; z=zz)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
zz = z+1; if (zz == npoints) zz = 0;
|
|
|
|
|
|
|
|
dax1 = ((xsi[z]+65535)>>16);
|
|
|
|
dax2 = ((xsi[zz]+65535)>>16);
|
|
|
|
if (dax2 > dax1)
|
|
|
|
{
|
2013-02-10 16:24:04 +00:00
|
|
|
int32_t yinc = divscale16(ysi[zz]-ysi[z],xsi[zz]-xsi[z]);
|
2006-04-13 20:47:06 +00:00
|
|
|
y = ysi[z] + mulscale16((dax1<<16)-xsi[z],yinc);
|
2008-04-25 11:21:08 +00:00
|
|
|
qinterpolatedown16short((intptr_t)(&uwall[dax1]),dax2-dax1,y,yinc);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Get dwall arrays
|
2009-02-19 16:47:54 +00:00
|
|
|
for (; z!=lpoint; z=zz)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
zz = z+1; if (zz == npoints) zz = 0;
|
|
|
|
|
|
|
|
dax1 = ((xsi[zz]+65535)>>16);
|
|
|
|
dax2 = ((xsi[z]+65535)>>16);
|
|
|
|
if (dax2 > dax1)
|
|
|
|
{
|
2013-02-10 16:24:04 +00:00
|
|
|
int32_t yinc = divscale16(ysi[zz]-ysi[z],xsi[zz]-xsi[z]);
|
2006-04-13 20:47:06 +00:00
|
|
|
y = ysi[zz] + mulscale16((dax1<<16)-xsi[zz],yinc);
|
2008-04-25 11:21:08 +00:00
|
|
|
qinterpolatedown16short((intptr_t)(&dwall[dax1]),dax2-dax1,y,yinc);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-13 22:32:57 +00:00
|
|
|
const int32_t lx = ((lmax+65535)>>16);
|
|
|
|
const int32_t rx = min(((rmax+65535)>>16), xdim-1);
|
|
|
|
// min(): OOB prevention. Simple test case: have a floor-aligned sprite
|
|
|
|
// to the right of the player. Slowly rotate right toward it. When it
|
|
|
|
// just becomes visible, the condition rx == xdim can occur.
|
2014-11-06 23:43:50 +00:00
|
|
|
|
2014-12-13 22:33:02 +00:00
|
|
|
// Don't pointlessly keep going. If the following condition holds, the
|
|
|
|
// ceilspritescan() at the end of our block would not draw any lines,
|
|
|
|
// and moreover may access uwall[] OOB (with x1==xdim).
|
|
|
|
if (rx-1 < lx)
|
|
|
|
return;
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=lx; x<=rx; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-10-16 06:09:54 +00:00
|
|
|
uwall[x] = max<int>(uwall[x],startumost[x+windowxy1.x]-windowxy1.y);
|
|
|
|
dwall[x] = min<int>(dwall[x],startdmost[x+windowxy1.x]-windowxy1.y);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Additional uwall/dwall clipping goes here
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=smostwallcnt-1; i>=0; i--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
j = smostwall[i];
|
|
|
|
if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
|
|
|
|
if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//if (spritewallfront(tspr,thewall[j]) == 0)
|
2006-04-13 20:47:06 +00:00
|
|
|
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;
|
|
|
|
|
2014-12-13 22:32:57 +00:00
|
|
|
const int32_t dalx2 = max(xb1[j],lx);
|
|
|
|
const int32_t darx2 = min(xb2[j],rx);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (smostwalltype[i])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
case 0:
|
2012-01-20 13:24:15 +00:00
|
|
|
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;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
2012-01-20 13:24:15 +00:00
|
|
|
k = smoststart[i] - xb1[j];
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=dalx2; x<=darx2; x++)
|
2006-04-24 19:04:22 +00:00
|
|
|
if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
|
|
|
|
break;
|
|
|
|
case 2:
|
2012-01-20 13:24:15 +00:00
|
|
|
k = smoststart[i] - xb1[j];
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=dalx2; x<=darx2; x++)
|
2006-04-24 19:04:22 +00:00
|
|
|
if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
|
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//sprite
|
2011-08-18 22:01:18 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (yax_globallev==YAX_MAXDRAWS || searchit==2)
|
|
|
|
#endif
|
2014-12-27 17:17:50 +00:00
|
|
|
if (searchit >= 1 && (searchx >= lx && searchx <= rx))
|
|
|
|
if (searchy >= uwall[searchx] && searchy <= dwall[searchx])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
searchsector = sectnum; searchwall = spritenum;
|
|
|
|
searchstat = 3; searchit = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
globalorientation = cstat;
|
|
|
|
globalpicnum = tilenum;
|
|
|
|
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
|
|
|
|
|
2018-04-12 21:03:30 +00:00
|
|
|
if (waloff[globalpicnum] == 0) tileLoad(globalpicnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
setgotpic(globalpicnum);
|
|
|
|
globalbufplc = waloff[globalpicnum];
|
|
|
|
|
|
|
|
globvis = mulscale16(globalhisibility,viewingrange);
|
2012-12-14 19:28:05 +00:00
|
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis, (uint8_t)(sec->visibility+16));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
x = picsiz[globalpicnum]; y = ((x>>4)&15); x &= 15;
|
2011-04-14 20:48:08 +00:00
|
|
|
#if 0
|
2006-04-13 20:47:06 +00:00
|
|
|
if (pow2long[x] != xspan)
|
|
|
|
{
|
|
|
|
x++;
|
|
|
|
globalx1 = mulscale(globalx1,xspan,x);
|
|
|
|
globalx2 = mulscale(globalx2,xspan,x);
|
|
|
|
}
|
2011-04-14 20:48:08 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
|
|
|
|
2011-04-14 20:48:08 +00:00
|
|
|
globalispow2 = (pow2long[x]==xspan && pow2long[y]==yspan);
|
|
|
|
globalxspan = xspan;
|
|
|
|
globalyspan = yspan;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Draw it!
|
2006-04-13 20:47:06 +00:00
|
|
|
ceilspritescan(lx,rx-1);
|
2011-04-14 20:48:08 +00:00
|
|
|
globalispow2 = 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else if ((cstat&48) == 48)
|
|
|
|
{
|
2014-12-13 22:32:57 +00:00
|
|
|
const int32_t daxrepeat = ((sprite[spritenum].cstat&48)==16) ?
|
|
|
|
(tspr->xrepeat * 5) / 4 :
|
|
|
|
tspr->xrepeat;
|
2011-06-18 13:02:08 +00:00
|
|
|
|
2014-12-13 22:32:57 +00:00
|
|
|
const int32_t lx = 0, rx = xdim-1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=lx; x<=rx; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
lwall[x] = startumost[x+windowxy1.x]-windowxy1.y;
|
|
|
|
swall[x] = startdmost[x+windowxy1.x]-windowxy1.y;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=smostwallcnt-1; i>=0; i--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
j = smostwall[i];
|
|
|
|
if ((xb1[j] > rx) || (xb2[j] < lx)) continue;
|
|
|
|
if ((yp <= yb1[j]) && (yp <= yb2[j])) continue;
|
2009-01-09 09:29:17 +00:00
|
|
|
if (spritewallfront(tspr,(int32_t)thewall[j]) && ((yp <= yb1[j]) || (yp <= yb2[j]))) continue;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-13 22:32:57 +00:00
|
|
|
const int32_t dalx2 = max(xb1[j],lx);
|
|
|
|
const int32_t darx2 = min(xb2[j],rx);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (smostwalltype[i])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
case 0:
|
2012-02-18 17:55:27 +00:00
|
|
|
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;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
2012-02-18 17:55:27 +00:00
|
|
|
k = smoststart[i] - xb1[j];
|
2014-10-25 03:30:38 +00:00
|
|
|
x = dalx2;
|
|
|
|
#ifdef CLASSIC_SLICE_BY_4
|
|
|
|
for (; x<=darx2-2; x+=2)
|
|
|
|
{
|
|
|
|
if (smost[k+x] > lwall[x]) lwall[x] = smost[k+x];
|
|
|
|
if (smost[k+x+1] > lwall[x+1]) lwall[x+1] = smost[k+x+1];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
for (; x<=darx2; x++)
|
2006-04-24 19:04:22 +00:00
|
|
|
if (smost[k+x] > lwall[x]) lwall[x] = smost[k+x];
|
|
|
|
break;
|
|
|
|
case 2:
|
2012-02-18 17:55:27 +00:00
|
|
|
k = smoststart[i] - xb1[j];
|
2014-10-25 03:30:38 +00:00
|
|
|
x = dalx2;
|
|
|
|
#ifdef CLASSIC_SLICE_BY_4
|
|
|
|
for (; x<=darx2-4; x+=4)
|
|
|
|
{
|
|
|
|
if (smost[k+x] < swall[x]) swall[x] = smost[k+x];
|
|
|
|
if (smost[k+x+1] < swall[x+1]) swall[x+1] = smost[k+x+1];
|
|
|
|
if (smost[k+x+2] < swall[x+2]) swall[x+2] = smost[k+x+2];
|
|
|
|
if (smost[k+x+3] < swall[x+3]) swall[x+3] = smost[k+x+3];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
for (; x<=darx2; x++)
|
2006-04-24 19:04:22 +00:00
|
|
|
if (smost[k+x] < swall[x]) swall[x] = smost[k+x];
|
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lwall[rx] >= swall[rx])
|
|
|
|
{
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=lx; x<rx; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (lwall[x] < swall[x]) break;
|
|
|
|
if (x == rx) return;
|
|
|
|
}
|
2019-09-19 20:02:45 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<MAXVOXMIPS; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (!voxoff[vtilenum][i])
|
|
|
|
{
|
2019-09-21 11:02:17 +00:00
|
|
|
if (loadvoxel_replace)
|
2019-09-19 20:02:45 +00:00
|
|
|
loadvoxel_replace(vtilenum);
|
2006-04-13 20:47:06 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-09-19 20:02:45 +00:00
|
|
|
|
2014-12-13 22:32:57 +00:00
|
|
|
const int32_t *const longptr = (int32_t *)voxoff[vtilenum][0];
|
2012-06-07 17:37:57 +00:00
|
|
|
if (longptr == NULL)
|
|
|
|
{
|
|
|
|
globalshade = 32;
|
|
|
|
tspr->xrepeat = tspr->yrepeat = 255;
|
|
|
|
goto draw_as_face_sprite;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-13 22:32:57 +00:00
|
|
|
int32_t nxrepeat, nyrepeat;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (voxscale[vtilenum] == 65536)
|
|
|
|
{
|
2011-06-18 13:02:08 +00:00
|
|
|
nxrepeat = (daxrepeat<<16);
|
2009-01-09 09:29:17 +00:00
|
|
|
nyrepeat = (((int32_t)tspr->yrepeat)<<16);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-06-18 13:02:08 +00:00
|
|
|
nxrepeat = daxrepeat*voxscale[vtilenum];
|
2009-01-09 09:29:17 +00:00
|
|
|
nyrepeat = ((int32_t)tspr->yrepeat)*voxscale[vtilenum];
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2019-06-25 11:30:27 +00:00
|
|
|
off.x = tspr->xoffset;
|
2016-06-21 00:34:18 +00:00
|
|
|
off.y = /*picanm[sprite[tspr->owner].picnum].yofs +*/ tspr->yoffset;
|
2019-06-25 11:30:27 +00:00
|
|
|
if (cstat & 4) off.x = -off.x;
|
2019-07-09 05:42:15 +00:00
|
|
|
if ((cstat & 8) && (tspr->cstat&48) != 0) off.y = -off.y;
|
2019-06-25 11:30:27 +00:00
|
|
|
tspr->z -= off.y * tspr->yrepeat << 2;
|
|
|
|
|
|
|
|
if ((sprite[spritenum].cstat&CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_WALL)
|
|
|
|
{
|
|
|
|
const int32_t xv = tspr->xrepeat*sintable[(tspr->ang+2560+1536)&2047];
|
|
|
|
const int32_t yv = tspr->xrepeat*sintable[(tspr->ang+2048+1536)&2047];
|
|
|
|
|
|
|
|
tspr->x -= mulscale16(xv, off.x);
|
|
|
|
tspr->y -= mulscale16(yv, off.x);
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
globvis = globalvisibility;
|
2012-12-14 19:28:05 +00:00
|
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis, (uint8_t)(sec->visibility+16));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-08-18 22:01:18 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (yax_globallev==YAX_MAXDRAWS || searchit==2)
|
|
|
|
#endif
|
2014-12-27 17:17:50 +00:00
|
|
|
if (searchit >= 1 && yp > (4<<8) && (searchy >= lwall[searchx] && searchy < swall[searchx]))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t const xdsiz = divscale19(xdimenscale,yp);
|
|
|
|
int32_t const xv = mulscale16(nxrepeat,xyaspect);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t const xspan = ((B_LITTLE32(longptr[0]) + B_LITTLE32(longptr[1])) >> 1);
|
|
|
|
int32_t const yspan = B_LITTLE32(longptr[2]);
|
2014-12-05 23:12:36 +00:00
|
|
|
|
2017-02-05 20:58:33 +00:00
|
|
|
vec2_t const siz = { mulscale_triple30(xdsiz, xv, xspan), mulscale_triple30(xdsiz, nyrepeat, yspan) };
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Watch out for divscale overflow
|
2016-06-21 00:33:30 +00:00
|
|
|
if (((xspan>>11) < siz.x) && (yspan < (siz.y>>1)))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:33:30 +00:00
|
|
|
x1 = xb-(siz.x>>1);
|
|
|
|
if (xspan&1) x1 += mulscale31(xdsiz,xv); //Odd xspans
|
2016-06-21 00:34:18 +00:00
|
|
|
i = mulscale30(xdsiz,xv*off.x);
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((cstat&4) == 0) x1 -= i; else x1 += i;
|
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
y1 = mulscale16(tspr->z-globalposz,xdsiz);
|
2019-07-13 03:20:17 +00:00
|
|
|
|
|
|
|
if (!(cstat & 128))
|
|
|
|
y1 -= mulscale16(mulscale22(B_LITTLE32(longptr[5]), nyrepeat), xdsiz);
|
2016-06-21 00:33:30 +00:00
|
|
|
//y1 -= mulscale30(xdsiz,nyrepeat*yoff);
|
|
|
|
y1 += (globalhoriz<<8)-siz.y;
|
2006-04-13 20:47:06 +00:00
|
|
|
//if (cstat&128) //Already fixed up above
|
2016-06-21 00:33:30 +00:00
|
|
|
y1 += (siz.y>>1);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
x2 = x1+siz.x-1;
|
|
|
|
y2 = y1+siz.y-1;
|
2013-02-10 16:24:04 +00:00
|
|
|
if ((y1|255) < (y2|255) && searchx >= (x1>>8)+1 && searchx <= (x2>>8))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-02-10 16:24:04 +00:00
|
|
|
int32_t startum, startdm;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((sec->ceilingstat&3) == 0)
|
2016-06-21 00:33:30 +00:00
|
|
|
startum = globalhoriz+mulscale24(xdsiz,sec->ceilingz-globalposz)-1;
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
|
|
|
startum = 0;
|
2013-02-10 16:24:04 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((sec->floorstat&3) == 0)
|
2016-06-21 00:33:30 +00:00
|
|
|
startdm = globalhoriz+mulscale24(xdsiz,sec->floorz-globalposz)+1;
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
2012-02-14 23:13:53 +00:00
|
|
|
startdm = INT32_MAX;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//sprite
|
2013-02-10 16:24:04 +00:00
|
|
|
if (searchy >= max(startum,(y1>>8)) && searchy < min(startdm,(y2>>8)))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
searchsector = sectnum; searchwall = spritenum;
|
|
|
|
searchstat = 3; searchit = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
i = (int32_t)tspr->ang+1536;
|
2013-05-01 17:42:07 +00:00
|
|
|
i += spriteext[spritenum].angoff;
|
2019-07-09 05:42:15 +00:00
|
|
|
|
|
|
|
const int32_t ceilingz = (sec->ceilingstat&3) == 0 ? sec->ceilingz : INT32_MIN;
|
|
|
|
const int32_t floorz = (sec->floorstat&3) == 0 ? sec->floorz : INT32_MAX;
|
|
|
|
|
|
|
|
classicDrawVoxel(tspr->x,tspr->y,tspr->z,i,daxrepeat,(int32_t)tspr->yrepeat,vtilenum,
|
2019-07-13 03:20:17 +00:00
|
|
|
tspr->shade,tspr->pal,lwall,swall,tspr->cstat,(tspr->cstat&48)!=48,floorz,ceilingz);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2019-08-01 06:50:56 +00:00
|
|
|
|
|
|
|
if (automapping == 1 && (unsigned)spritenum < MAXSPRITES)
|
|
|
|
show2dsprite[spritenum>>3] |= pow2char[spritenum&7];
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2018-04-12 21:04:00 +00:00
|
|
|
static void renderDrawSprite(int32_t snum)
|
2013-02-10 16:24:04 +00:00
|
|
|
{
|
2018-04-12 21:03:12 +00:00
|
|
|
switch (videoGetRenderMode())
|
2014-09-30 04:06:32 +00:00
|
|
|
{
|
|
|
|
case REND_CLASSIC:
|
2018-04-12 21:04:00 +00:00
|
|
|
classicDrawSprite(snum);
|
2014-09-30 04:06:32 +00:00
|
|
|
return;
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
case REND_POLYMOST:
|
|
|
|
polymost_drawsprite(snum);
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
}
|
2013-02-10 16:24:04 +00:00
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// drawmaskwall (internal)
|
|
|
|
//
|
2018-04-12 21:04:00 +00:00
|
|
|
static void renderDrawMaskedWall(int16_t damaskwallcnt)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
//============================================================================= //POLYMOST BEGINS
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMOST) { polymost_drawmaskwall(damaskwallcnt); return; }
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
|
|
|
//============================================================================= //POLYMOST ENDS
|
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t z = maskwall[damaskwallcnt];
|
2019-04-18 17:25:24 +00:00
|
|
|
auto wal = (uwallptr_t)&wall[thewall[z]];
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t sectnum = thesector[z];
|
2019-04-18 17:25:24 +00:00
|
|
|
auto sec = (usectorptr_t)§or[sectnum];
|
|
|
|
auto nsec = (usectorptr_t)§or[wal->nextsector];
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t z1 = max(nsec->ceilingz,sec->ceilingz);
|
|
|
|
int32_t z2 = min(nsec->floorz,sec->floorz);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
wallmost(uwall,z,sectnum,(uint8_t)0);
|
|
|
|
wallmost(uplc,z,(int32_t)wal->nextsector,(uint8_t)0);
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t x=xb1[z]; x<=xb2[z]; x++)
|
2012-02-18 17:55:27 +00:00
|
|
|
if (uplc[x] > uwall[x])
|
|
|
|
uwall[x] = uplc[x];
|
2009-01-09 09:29:17 +00:00
|
|
|
wallmost(dwall,z,sectnum,(uint8_t)1);
|
|
|
|
wallmost(dplc,z,(int32_t)wal->nextsector,(uint8_t)1);
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t x=xb1[z]; x<=xb2[z]; x++)
|
2012-02-18 17:55:27 +00:00
|
|
|
if (dplc[x] < dwall[x])
|
|
|
|
dwall[x] = dplc[x];
|
2006-04-13 20:47:06 +00:00
|
|
|
prepwall(z,wal);
|
|
|
|
|
2012-03-25 13:54:14 +00:00
|
|
|
setup_globals_wall1(wal, wal->overpicnum);
|
|
|
|
setup_globals_wall2(wal, sec->visibility, z1, z2);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=smostwallcnt-1; i>=0; i--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-07-04 14:09:05 +00:00
|
|
|
int j=smostwall[i];
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((xb1[j] > xb2[z]) || (xb2[j] < xb1[z])) continue;
|
|
|
|
if (wallfront(j,z)) continue;
|
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int lx = max(xb1[j],xb1[z]);
|
|
|
|
int rx = min(xb2[j],xb2[z]);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (smostwalltype[i])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
case 0:
|
2012-02-18 17:55:27 +00:00
|
|
|
if (lx <= rx)
|
|
|
|
{
|
|
|
|
if ((lx == xb1[z]) && (rx == xb2[z])) return;
|
|
|
|
//clearbufbyte(&dwall[lx],(rx-lx+1)*sizeof(dwall[0]),0L);
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t x=lx; x<=rx; x++) dwall[x] = 0;
|
2012-02-18 17:55:27 +00:00
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t x=lx, k = smoststart[i] - xb1[j]; x<=rx; x++)
|
2006-04-24 19:04:22 +00:00
|
|
|
if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
|
|
|
|
break;
|
|
|
|
case 2:
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t x=lx, k = smoststart[i] - xb1[j]; x<=rx; x++)
|
2006-04-24 19:04:22 +00:00
|
|
|
if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
|
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//maskwall
|
2014-12-27 17:17:50 +00:00
|
|
|
if (searchit >= 1 && (searchx >= xb1[z] && searchx <= xb2[z]))
|
|
|
|
if (searchy >= uwall[searchx] && searchy <= dwall[searchx])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-04-10 20:14:17 +00:00
|
|
|
searchsector = sectnum; searchbottomwall = searchwall = thewall[z];
|
2006-04-13 20:47:06 +00:00
|
|
|
searchstat = 4; searchit = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((globalorientation&128) == 0)
|
2012-07-06 11:26:24 +00:00
|
|
|
{
|
2013-11-16 18:47:11 +00:00
|
|
|
maskwallscan(xb1[z],xb2[z], 0);
|
2012-07-06 11:26:24 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (globalorientation&128)
|
2014-03-10 20:08:27 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
setup_blend(wal->blend, globalorientation&512);
|
|
|
|
#else
|
2017-06-25 11:23:53 +00:00
|
|
|
setup_blend(wallext[thewall[z]].blend, globalorientation&512);
|
2014-03-10 20:08:27 +00:00
|
|
|
#endif
|
2013-11-16 18:47:11 +00:00
|
|
|
transmaskwallscan(xb1[z],xb2[z], 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// fillpolygon (internal)
|
|
|
|
//
|
2018-04-12 21:04:00 +00:00
|
|
|
static void renderFillPolygon(int32_t npoints)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-06-13 17:10:59 +00:00
|
|
|
int32_t i, z, y, miny, maxy;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-04-28 21:28:33 +00:00
|
|
|
// fix for bad next-point (xb1) values...
|
|
|
|
for (z=0; z<npoints; z++)
|
|
|
|
if ((unsigned)xb1[z] >= (unsigned)npoints)
|
|
|
|
xb1[z] = 0;
|
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() >= REND_POLYMOST && in3dmode())
|
2013-06-13 17:10:59 +00:00
|
|
|
{
|
|
|
|
polymost_fillpolygon(npoints);
|
|
|
|
return;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
|
|
|
|
2013-06-13 17:10:59 +00:00
|
|
|
// 1. Calculate y bounds.
|
2012-02-14 23:13:53 +00:00
|
|
|
miny = INT32_MAX; maxy = INT32_MIN;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=npoints-1; z>=0; z--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-06-13 17:10:59 +00:00
|
|
|
y = ry1[z];
|
|
|
|
miny = min(miny,y);
|
|
|
|
maxy = max(maxy,y);
|
|
|
|
}
|
|
|
|
|
|
|
|
miny >>= 12;
|
|
|
|
maxy >>= 12;
|
|
|
|
|
|
|
|
if (miny < 0)
|
|
|
|
miny = 0;
|
|
|
|
if (maxy >= ydim)
|
|
|
|
maxy = ydim-1;
|
|
|
|
|
|
|
|
for (i=0, y=miny; y<=maxy; y++, i++)
|
|
|
|
{
|
|
|
|
//They're pointers! - watch how you optimize this thing
|
2014-10-29 17:04:28 +00:00
|
|
|
dotp1[y] = &smost[i*nodesperline];
|
|
|
|
dotp2[y] = &smost[i*nodesperline + (nodesperline>>1)];
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=npoints-1; z>=0; z--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-06-13 17:10:59 +00:00
|
|
|
const int32_t zz=xb1[z];
|
|
|
|
|
|
|
|
// NOTE: clamp for crash prevention... :-/
|
|
|
|
// r1874 says: "Fix more overheadmap crashes, this time with 'Last
|
|
|
|
// Pissed Time'"
|
2013-06-13 17:11:00 +00:00
|
|
|
const int32_t y1 = clamp(ry1[z], 0, (ydim<<12)-1);
|
|
|
|
const int32_t y2 = clamp(ry1[zz], 0, (ydim<<12)-1);
|
|
|
|
|
|
|
|
const int32_t day1 = y1>>12;
|
|
|
|
const int32_t day2 = y2>>12;
|
2013-06-13 17:10:59 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (day1 != day2)
|
|
|
|
{
|
2013-06-13 17:10:59 +00:00
|
|
|
int32_t x1=rx1[z], x2=rx1[zz];
|
|
|
|
const int32_t xinc = divscale12(x2-x1, y2-y1);
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (day2 > day1)
|
|
|
|
{
|
2013-06-13 17:10:59 +00:00
|
|
|
x1 += mulscale12((day1<<12)+4095-y1, xinc);
|
2012-02-18 17:55:27 +00:00
|
|
|
for (y=day1; y<day2; y++)
|
|
|
|
{
|
2015-07-11 23:07:47 +00:00
|
|
|
Bassert(dotp2[y]);
|
|
|
|
*(dotp2[y]++) = x1>>12;
|
2013-06-13 17:10:59 +00:00
|
|
|
x1 += xinc;
|
2012-02-18 17:55:27 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-06-13 17:10:59 +00:00
|
|
|
x2 += mulscale12((day2<<12)+4095-y2, xinc);
|
2012-02-18 17:55:27 +00:00
|
|
|
for (y=day2; y<day1; y++)
|
|
|
|
{
|
2015-07-11 23:07:47 +00:00
|
|
|
Bassert(dotp1[y]);
|
|
|
|
*(dotp1[y]++) = x2>>12;
|
2013-06-13 17:10:59 +00:00
|
|
|
x2 += xinc;
|
2012-02-18 17:55:27 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
globalx1 = mulscale16(globalx1,xyaspect);
|
|
|
|
globaly2 = mulscale16(globaly2,xyaspect);
|
|
|
|
|
2013-06-13 17:10:59 +00:00
|
|
|
{
|
|
|
|
const int32_t oy = miny+1-(ydim>>1);
|
|
|
|
globalposx += oy*(int64_t)globalx1;
|
|
|
|
globalposy += oy*(int64_t)globaly2;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
setuphlineasm4(asm1,asm2);
|
|
|
|
|
2013-06-13 17:10:59 +00:00
|
|
|
for (i=0, y=miny; y<=maxy; y++, i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-10-29 17:04:28 +00:00
|
|
|
int16_t *const xptr = &smost[i*nodesperline];
|
|
|
|
int16_t *const xptr2 = &smost[i*nodesperline + (nodesperline>>1)];
|
2013-06-13 17:10:59 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
const bssize_t cnt = dotp1[y]-xptr;
|
2013-06-13 17:10:59 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=cnt-1; z>=0; z--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-06-13 17:10:59 +00:00
|
|
|
int32_t x1, x2;
|
|
|
|
int32_t zz, i1=0, i2=0; // point indices (like loop z)
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (zz=z; zz>0; zz--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-06-13 17:10:59 +00:00
|
|
|
if (xptr[zz] < xptr[i1])
|
|
|
|
i1 = zz;
|
|
|
|
if (xptr2[zz] < xptr2[i2])
|
|
|
|
i2 = zz;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2013-06-13 17:10:59 +00:00
|
|
|
|
|
|
|
x1 = xptr[i1];
|
|
|
|
xptr[i1] = xptr[z];
|
|
|
|
|
|
|
|
x2 = xptr2[i2]-1;
|
|
|
|
xptr2[i2] = xptr2[z];
|
|
|
|
|
|
|
|
if (x1 > x2)
|
|
|
|
continue;
|
|
|
|
|
2013-06-13 17:11:00 +00:00
|
|
|
if ((unsigned)x1 >= xdim+0u || (unsigned)x2 >= xdim+0u)
|
|
|
|
continue;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (globalpolytype < 1)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
//maphline
|
2013-06-13 17:10:59 +00:00
|
|
|
const int32_t ox = x2+1-(xdim>>1);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-07-11 23:07:47 +00:00
|
|
|
hlineasm4(x2 - x1, -1L, globalshade << 8,
|
|
|
|
ox * asm2 - globalposy, ox * asm1 + globalposx,
|
|
|
|
ylookup[y] + x2 + frameplace);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
//maphline
|
2013-06-13 17:10:59 +00:00
|
|
|
const int32_t ox = x1+1-(xdim>>1);
|
|
|
|
const int32_t bx = ox*asm1 + globalposx;
|
|
|
|
const int32_t by = ox*asm2 - globalposy;
|
|
|
|
|
|
|
|
const intptr_t p = ylookup[y]+x1+frameplace;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (globalpolytype == 1)
|
|
|
|
mhline(globalbufplc,bx,(x2-x1)<<16,0L,by,p);
|
|
|
|
else
|
|
|
|
thline(globalbufplc,bx,(x2-x1)<<16,0L,by,p);
|
|
|
|
}
|
|
|
|
}
|
2013-06-13 17:10:59 +00:00
|
|
|
|
Integer Overflow Offensive continued: first round of -ftrapv - cleanness.
That is, "clang -ftrapv" builds don't abort almost immediately after entering
a level.
There are various classes of overflow bugs, needing different handling:
- Some texture mapping code was written with signed integer wrapping semantics
in mind. In some places, we're able to get away with unsigned casts.
- sometimes, we really need a wider range, like when calculating distances or
dot products
- negating INT_MIN. Here, we cast to int64_t temporarily. Note that if the
result is 32-bit wide, no 64-bit code may actually need to be generated.
- shifting into a signed integer's sign bit. We cast to uint32 here.
- in hitscan(), at the "abyss crash prevention code" comment, it's clearly
the other code that is better...
This is not merely done for pedantry, but rather makes it easier to track down
overflow bugs having a real impact on the game.
git-svn-id: https://svn.eduke32.com/eduke32@2784 1a8010ca-5511-0410-912e-c29ae57300e0
2012-06-26 19:49:53 +00:00
|
|
|
globalposx += (int64_t)globalx1;
|
|
|
|
globalposy += (int64_t)globaly2;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2013-06-13 17:10:59 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
faketimerhandler();
|
|
|
|
}
|
|
|
|
|
2012-11-15 21:10:00 +00:00
|
|
|
static inline int32_t addscaleclamp(int32_t a, int32_t b, int32_t s1, int32_t s2)
|
|
|
|
{
|
|
|
|
// a + scale(b, s1, s1-s2), but without arithmetic exception when the
|
|
|
|
// scale() expression overflows
|
|
|
|
|
2014-10-25 03:36:34 +00:00
|
|
|
int64_t tmp = (int64_t)a + tabledivide64((int64_t)b*s1, s1-s2);
|
2012-11-15 21:10:00 +00:00
|
|
|
|
2014-10-25 03:36:34 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(tmp <= INT32_MIN+1))
|
2012-11-15 21:10:00 +00:00
|
|
|
return INT32_MIN+1;
|
2014-10-25 03:36:34 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(tmp >= INT32_MAX))
|
2012-11-15 21:10:00 +00:00
|
|
|
return INT32_MAX;
|
|
|
|
return tmp;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// clippoly (internal)
|
|
|
|
//
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t clippoly(int32_t npoints, int32_t clipstat)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t z, zz, s1, s2, t, npoints2, start2, z1, z2, z3, z4, splitcnt;
|
|
|
|
int32_t cx1, cy1, cx2, cy2;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
cx1 = windowxy1.x;
|
|
|
|
cy1 = windowxy1.y;
|
|
|
|
cx2 = windowxy2.x+1;
|
|
|
|
cy2 = windowxy2.y+1;
|
2006-04-13 20:47:06 +00:00
|
|
|
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)
|
|
|
|
{
|
2012-11-15 21:10:00 +00:00
|
|
|
rx2[npoints2] = addscaleclamp(rx1[z], rx1[zz]-rx1[z], s1, s2);
|
|
|
|
ry2[npoints2] = addscaleclamp(ry1[z], ry1[zz]-ry1[z], s1, s2);
|
2014-09-30 04:14:21 +00:00
|
|
|
if (s1 < 0) bunchp2[splitcnt++] = npoints2;
|
2006-04-13 20:47:06 +00:00
|
|
|
xb2[npoints2] = npoints2+1;
|
|
|
|
npoints2++;
|
|
|
|
}
|
|
|
|
z = zz;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (xb1[z] >= 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (npoints2 >= start2+3)
|
|
|
|
xb2[npoints2-1] = start2, start2 = npoints2;
|
|
|
|
else
|
|
|
|
npoints2 = start2;
|
|
|
|
|
|
|
|
z = 1;
|
|
|
|
while ((z < npoints) && (xb1[z] < 0)) z++;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (z < npoints);
|
2016-06-21 00:34:41 +00:00
|
|
|
if (npoints2 <= 2) return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=1; z<splitcnt; z++)
|
|
|
|
for (zz=0; zz<z; zz++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-09-30 04:14:21 +00:00
|
|
|
z1 = bunchp2[z]; z2 = xb2[z1]; z3 = bunchp2[zz]; z4 = xb2[z3];
|
2006-04-13 20:47:06 +00:00
|
|
|
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)
|
2014-09-30 04:14:21 +00:00
|
|
|
{ t = xb2[bunchp2[z]]; xb2[bunchp2[z]] = xb2[bunchp2[zz]]; xb2[bunchp2[zz]] = t; }
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2012-11-15 21:10:00 +00:00
|
|
|
rx1[npoints] = addscaleclamp(rx2[z], rx2[zz]-rx2[z], s1, s2);
|
|
|
|
ry1[npoints] = addscaleclamp(ry2[z], ry2[zz]-ry2[z], s1, s2);
|
2014-09-30 04:14:21 +00:00
|
|
|
if (s1 < 0) bunchp2[splitcnt++] = npoints;
|
2006-04-13 20:47:06 +00:00
|
|
|
xb1[npoints] = npoints+1;
|
|
|
|
npoints++;
|
|
|
|
}
|
|
|
|
z = zz;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (xb2[z] >= 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (npoints >= start2+3)
|
|
|
|
xb1[npoints-1] = start2, start2 = npoints;
|
|
|
|
else
|
|
|
|
npoints = start2;
|
|
|
|
|
|
|
|
z = 1;
|
|
|
|
while ((z < npoints2) && (xb2[z] < 0)) z++;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (z < npoints2);
|
2016-06-21 00:34:41 +00:00
|
|
|
if (npoints <= 2) return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=1; z<splitcnt; z++)
|
|
|
|
for (zz=0; zz<z; zz++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-09-30 04:14:21 +00:00
|
|
|
z1 = bunchp2[z]; z2 = xb1[z1]; z3 = bunchp2[zz]; z4 = xb1[z3];
|
2006-04-13 20:47:06 +00:00
|
|
|
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)
|
2014-09-30 04:14:21 +00:00
|
|
|
{ t = xb1[bunchp2[z]]; xb1[bunchp2[z]] = xb1[bunchp2[zz]]; xb1[bunchp2[zz]] = t; }
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
2012-11-15 21:10:00 +00:00
|
|
|
rx2[npoints2] = addscaleclamp(rx1[z], rx1[zz]-rx1[z], s1, s2);
|
|
|
|
ry2[npoints2] = addscaleclamp(ry1[z], ry1[zz]-ry1[z], s1, s2);
|
2014-09-30 04:14:21 +00:00
|
|
|
if (s1 < 0) bunchp2[splitcnt++] = npoints2;
|
2006-04-13 20:47:06 +00:00
|
|
|
xb2[npoints2] = npoints2+1;
|
|
|
|
npoints2++;
|
|
|
|
}
|
|
|
|
z = zz;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (xb1[z] >= 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (npoints2 >= start2+3)
|
|
|
|
xb2[npoints2-1] = start2, start2 = npoints2;
|
|
|
|
else
|
|
|
|
npoints2 = start2;
|
|
|
|
|
|
|
|
z = 1;
|
|
|
|
while ((z < npoints) && (xb1[z] < 0)) z++;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (z < npoints);
|
2016-06-21 00:34:41 +00:00
|
|
|
if (npoints2 <= 2) return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=1; z<splitcnt; z++)
|
|
|
|
for (zz=0; zz<z; zz++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-09-30 04:14:21 +00:00
|
|
|
z1 = bunchp2[z]; z2 = xb2[z1]; z3 = bunchp2[zz]; z4 = xb2[z3];
|
2006-04-13 20:47:06 +00:00
|
|
|
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)
|
2014-09-30 04:14:21 +00:00
|
|
|
{ t = xb2[bunchp2[z]]; xb2[bunchp2[z]] = xb2[bunchp2[zz]]; xb2[bunchp2[zz]] = t; }
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2012-11-15 21:10:00 +00:00
|
|
|
rx1[npoints] = addscaleclamp(rx2[z], rx2[zz]-rx2[z], s1, s2);
|
|
|
|
ry1[npoints] = addscaleclamp(ry2[z], ry2[zz]-ry2[z], s1, s2);
|
2014-09-30 04:14:21 +00:00
|
|
|
if (s1 < 0) bunchp2[splitcnt++] = npoints;
|
2006-04-13 20:47:06 +00:00
|
|
|
xb1[npoints] = npoints+1;
|
|
|
|
npoints++;
|
|
|
|
}
|
|
|
|
z = zz;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (xb2[z] >= 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (npoints >= start2+3)
|
|
|
|
xb1[npoints-1] = start2, start2 = npoints;
|
|
|
|
else
|
|
|
|
npoints = start2;
|
|
|
|
|
|
|
|
z = 1;
|
|
|
|
while ((z < npoints2) && (xb2[z] < 0)) z++;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (z < npoints2);
|
2016-06-21 00:34:41 +00:00
|
|
|
if (npoints <= 2) return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=1; z<splitcnt; z++)
|
|
|
|
for (zz=0; zz<z; zz++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-09-30 04:14:21 +00:00
|
|
|
z1 = bunchp2[z]; z2 = xb1[z1]; z3 = bunchp2[zz]; z4 = xb1[z3];
|
2006-04-13 20:47:06 +00:00
|
|
|
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)
|
2014-09-30 04:14:21 +00:00
|
|
|
{ t = xb1[bunchp2[z]]; xb1[bunchp2[z]] = xb1[bunchp2[zz]]; xb1[bunchp2[zz]] = t; }
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
2016-06-21 00:34:41 +00:00
|
|
|
return npoints;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// clippoly4 (internal)
|
|
|
|
//
|
2006-04-24 19:04:22 +00:00
|
|
|
//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
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t clippoly4(int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t n, nn, z, zz, x, x1, x2, y, y1, y2, t;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
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;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (z != 0);
|
2016-06-21 00:34:41 +00:00
|
|
|
if (nn < 3) return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
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;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (z != 0);
|
2016-06-21 00:34:41 +00:00
|
|
|
return n;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-16 21:48:50 +00:00
|
|
|
// INTERNAL helper function for classic/polymost dorotatesprite
|
2012-08-19 12:51:04 +00:00
|
|
|
// sxptr, sxptr, z: in/out
|
|
|
|
// ret_yxaspect, ret_xyaspect: out
|
|
|
|
void dorotspr_handle_bit2(int32_t *sxptr, int32_t *syptr, int32_t *z, int32_t dastat,
|
|
|
|
int32_t cx1_plus_cx2, int32_t cy1_plus_cy2,
|
|
|
|
int32_t *ret_yxaspect, int32_t *ret_xyaspect)
|
2012-08-16 21:48:50 +00:00
|
|
|
{
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat & RS_AUTO) == 0)
|
2012-08-19 12:55:45 +00:00
|
|
|
{
|
2013-11-22 19:26:52 +00:00
|
|
|
if (!(dastat & RS_STRETCH) && 4*ydim <= 3*xdim)
|
2012-08-16 21:48:50 +00:00
|
|
|
{
|
2012-08-19 12:51:04 +00:00
|
|
|
*ret_yxaspect = (12<<16)/10;
|
2012-08-19 12:57:57 +00:00
|
|
|
*ret_xyaspect = (10<<16)/12;
|
2012-08-16 21:48:50 +00:00
|
|
|
}
|
2012-11-10 14:11:13 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
*ret_yxaspect = yxaspect;
|
|
|
|
*ret_xyaspect = xyaspect;
|
|
|
|
}
|
|
|
|
|
|
|
|
// *sxptr and *syptr and *z are left unchanged
|
2012-08-16 21:48:50 +00:00
|
|
|
|
2012-08-19 12:55:45 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
2012-08-16 21:48:50 +00:00
|
|
|
{
|
2012-08-19 12:55:45 +00:00
|
|
|
// dastat&2: Auto window size scaling
|
2012-08-16 21:48:50 +00:00
|
|
|
const int32_t oxdim = xdim;
|
2015-05-27 08:48:22 +00:00
|
|
|
const int32_t oydim = ydim;
|
2012-08-16 21:48:50 +00:00
|
|
|
int32_t xdim = oxdim; // SHADOWS global
|
2015-05-27 08:48:22 +00:00
|
|
|
int32_t ydim = oydim;
|
2012-08-16 21:48:50 +00:00
|
|
|
|
2012-08-19 12:57:57 +00:00
|
|
|
int32_t zoomsc, sx=*sxptr, sy=*syptr;
|
2012-08-19 12:55:45 +00:00
|
|
|
int32_t ouryxaspect = yxaspect, ourxyaspect = xyaspect;
|
2012-08-16 21:48:50 +00:00
|
|
|
|
2019-01-30 00:19:56 +00:00
|
|
|
sy += rotatesprite_y_offset;
|
|
|
|
|
2012-08-19 12:57:57 +00:00
|
|
|
// screen center to s[xy], 320<<16 coords.
|
|
|
|
const int32_t normxofs = sx-(320<<15), normyofs = sy-(200<<15);
|
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if (!(dastat & RS_STRETCH) && 4*ydim <= 3*xdim)
|
2012-08-16 21:48:50 +00:00
|
|
|
{
|
2015-05-27 08:48:22 +00:00
|
|
|
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
|
|
|
|
ydim = scale(xdim, 3, 4);
|
|
|
|
else
|
|
|
|
xdim = scale(ydim, 4, 3);
|
2012-08-19 12:51:04 +00:00
|
|
|
|
|
|
|
ouryxaspect = (12<<16)/10;
|
2012-08-19 12:57:57 +00:00
|
|
|
ourxyaspect = (10<<16)/12;
|
2012-08-16 21:48:50 +00:00
|
|
|
}
|
|
|
|
|
2019-01-30 00:19:56 +00:00
|
|
|
ouryxaspect = mulscale16(ouryxaspect, rotatesprite_yxaspect);
|
|
|
|
ourxyaspect = divscale16(ourxyaspect, rotatesprite_yxaspect);
|
|
|
|
|
2012-08-19 12:55:45 +00:00
|
|
|
// nasty hacks go here
|
2013-11-22 19:26:52 +00:00
|
|
|
if (!(dastat & RS_NOCLIP))
|
2012-08-16 21:48:50 +00:00
|
|
|
{
|
2012-08-19 12:57:57 +00:00
|
|
|
const int32_t twice_midcx = cx1_plus_cx2+2;
|
2012-08-16 21:48:50 +00:00
|
|
|
|
2012-08-19 12:57:57 +00:00
|
|
|
// screen x center to sx1, scaled to viewport
|
|
|
|
const int32_t scaledxofs = scale(normxofs, scale(xdimen, xdim, oxdim), 320);
|
2012-08-16 21:48:50 +00:00
|
|
|
|
2012-08-19 12:57:57 +00:00
|
|
|
int32_t xbord = 0;
|
2012-08-16 21:48:50 +00:00
|
|
|
|
2015-05-27 08:48:22 +00:00
|
|
|
if ((dastat & RS_ALIGN_MASK) && (dastat & RS_ALIGN_MASK) != RS_ALIGN_MASK)
|
2012-08-19 12:55:45 +00:00
|
|
|
{
|
2012-08-19 12:57:57 +00:00
|
|
|
xbord = scale(oxdim-xdim, twice_midcx, oxdim);
|
2012-08-16 21:48:50 +00:00
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat & RS_ALIGN_R)==0)
|
2012-08-19 12:57:57 +00:00
|
|
|
xbord = -xbord;
|
2012-08-19 12:55:45 +00:00
|
|
|
}
|
2012-08-19 12:51:04 +00:00
|
|
|
|
2012-08-19 12:57:57 +00:00
|
|
|
sx = ((twice_midcx+xbord)<<15) + scaledxofs;
|
|
|
|
|
|
|
|
zoomsc = xdimenscale; //= scale(xdimen,yxaspect,320);
|
2019-01-30 00:19:56 +00:00
|
|
|
zoomsc = mulscale16(zoomsc, rotatesprite_yxaspect);
|
2015-05-27 08:48:22 +00:00
|
|
|
|
|
|
|
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
|
|
|
|
zoomsc = scale(zoomsc, ydim, oydim);
|
|
|
|
|
2012-08-19 12:57:57 +00:00
|
|
|
sy = ((cy1_plus_cy2+2)<<15) + mulscale16(normyofs, zoomsc);
|
2012-08-16 21:48:50 +00:00
|
|
|
}
|
2012-08-19 12:55:45 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
//If not clipping to startmosts, & auto-scaling on, as a
|
|
|
|
//hard-coded bonus, scale to full screen instead
|
2012-08-16 21:48:50 +00:00
|
|
|
|
2012-08-19 12:57:57 +00:00
|
|
|
sx = (xdim<<15)+32768 + scale(normxofs,xdim,320);
|
2012-08-16 21:48:50 +00:00
|
|
|
|
2015-05-27 08:48:22 +00:00
|
|
|
zoomsc = scale(xdim, ouryxaspect, 320);
|
|
|
|
sy = (ydim<<15)+32768 + mulscale16(normyofs, zoomsc);
|
|
|
|
|
|
|
|
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
|
|
|
|
sy += (oydim-ydim)<<15;
|
|
|
|
else if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_R)
|
2012-08-19 12:55:45 +00:00
|
|
|
sx += (oxdim-xdim)<<16;
|
2015-05-27 08:48:22 +00:00
|
|
|
else if ((dastat & RS_ALIGN_MASK) == 0)
|
2012-08-19 12:55:45 +00:00
|
|
|
sx += (oxdim-xdim)<<15;
|
2012-08-19 12:57:57 +00:00
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_CENTERORIGIN)
|
2012-08-19 12:57:57 +00:00
|
|
|
sx += oxdim<<15;
|
2012-08-19 12:55:45 +00:00
|
|
|
}
|
2012-08-16 21:48:50 +00:00
|
|
|
|
2012-08-19 12:55:45 +00:00
|
|
|
*sxptr = sx;
|
|
|
|
*syptr = sy;
|
2012-08-19 12:57:57 +00:00
|
|
|
*z = mulscale16(*z, zoomsc);
|
2012-08-16 21:48:50 +00:00
|
|
|
|
2012-08-19 12:55:45 +00:00
|
|
|
*ret_yxaspect = ouryxaspect;
|
|
|
|
*ret_xyaspect = ourxyaspect;
|
|
|
|
}
|
2012-08-16 21:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// dorotatesprite (internal)
|
|
|
|
//
|
2006-04-24 19:04:22 +00:00
|
|
|
//JBF 20031206: Thanks to Ken's hunting, s/(rx1|ry1|rx2|ry2)/n\1/ in this function
|
2012-08-16 21:48:44 +00:00
|
|
|
static void dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
|
2019-09-22 21:15:46 +00:00
|
|
|
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
|
2012-08-16 21:48:44 +00:00
|
|
|
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2,
|
|
|
|
int32_t uniqid)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-05-12 18:51:30 +00:00
|
|
|
// NOTE: if these are made unsigned (for safety), angled tiles may draw
|
|
|
|
// incorrectly, showing vertical seams at intervals.
|
|
|
|
int32_t bx, by;
|
|
|
|
|
|
|
|
int32_t cosang, sinang, v, nextv, dax1, dax2, oy;
|
2012-08-16 21:48:44 +00:00
|
|
|
int32_t i, x, y, x1, y1, x2, y2, gx1, gy1;
|
2008-04-25 11:21:08 +00:00
|
|
|
intptr_t p, bufplc, palookupoffs;
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t xsiz, ysiz, xoff, yoff, npoints, yplc, yinc, lx, rx;
|
|
|
|
int32_t xv, yv, xv2, yv2;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-08-19 12:51:04 +00:00
|
|
|
int32_t ouryxaspect, ourxyaspect;
|
|
|
|
|
2012-12-14 19:27:55 +00:00
|
|
|
if (g_rotatespriteNoWidescreen)
|
|
|
|
{
|
2013-11-22 19:26:52 +00:00
|
|
|
dastat |= RS_STRETCH;
|
|
|
|
dastat &= ~RS_ALIGN_MASK;
|
2012-12-14 19:27:55 +00:00
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//============================================================================= //POLYMOST BEGINS
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() >= REND_POLYMOST && in3dmode())
|
2012-08-16 21:48:44 +00:00
|
|
|
{
|
2016-10-09 07:55:23 +00:00
|
|
|
polymost_dorotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,daalpha,dablend,cx1,cy1,cx2,cy2,uniqid);
|
2012-08-16 21:48:44 +00:00
|
|
|
return;
|
|
|
|
}
|
2013-11-22 19:26:44 +00:00
|
|
|
#else
|
|
|
|
UNREFERENCED_PARAMETER(uniqid);
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
|
|
|
//============================================================================= //POLYMOST ENDS
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2012-08-16 21:48:44 +00:00
|
|
|
// bound clipping rectangle to screen
|
2006-04-13 20:47:06 +00:00
|
|
|
if (cx1 < 0) cx1 = 0;
|
2018-07-14 21:36:44 +00:00
|
|
|
else if (cx1 > xdim-1) cx1 = xdim-1;
|
2006-04-13 20:47:06 +00:00
|
|
|
if (cy1 < 0) cy1 = 0;
|
2018-07-14 21:36:44 +00:00
|
|
|
else if (cy1 > ydim-1) cy1 = ydim-1;
|
2015-01-17 00:27:46 +00:00
|
|
|
if (cx2 < 0) cx2 = 0;
|
2018-07-14 21:36:44 +00:00
|
|
|
else if (cx2 > xdim-1) cx2 = xdim-1;
|
2015-01-17 00:27:46 +00:00
|
|
|
if (cy2 < 0) cy2 = 0;
|
2018-07-14 21:36:44 +00:00
|
|
|
else if (cy2 > ydim-1) cy2 = ydim-1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
xsiz = tilesiz[picnum].x;
|
|
|
|
ysiz = tilesiz[picnum].y;
|
2012-08-16 21:48:44 +00:00
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_TOPLEFT)
|
2012-08-16 21:48:44 +00:00
|
|
|
{
|
|
|
|
// Bit 1<<4 set: origin is top left corner?
|
|
|
|
xoff = 0;
|
|
|
|
yoff = 0;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
|
|
|
{
|
2012-08-16 21:48:44 +00:00
|
|
|
// Bit 1<<4 clear: origin is center of tile, and per-tile offset is applied.
|
|
|
|
// TODO: split the two?
|
2012-11-17 19:46:28 +00:00
|
|
|
xoff = picanm[picnum].xofs + (xsiz>>1);
|
|
|
|
yoff = picanm[picnum].yofs + (ysiz>>1);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2012-08-16 21:48:44 +00:00
|
|
|
// Bit 1<<2: invert y
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_YFLIP)
|
2012-08-16 21:48:44 +00:00
|
|
|
yoff = ysiz-yoff;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-08-16 21:48:44 +00:00
|
|
|
cosang = sintable[(a+512)&2047];
|
|
|
|
sinang = sintable[a&2047];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-08-19 12:51:04 +00:00
|
|
|
dorotspr_handle_bit2(&sx, &sy, &z, dastat, cx1+cx2, cy1+cy2, &ouryxaspect, &ourxyaspect);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
xv = mulscale14(cosang,z);
|
|
|
|
yv = mulscale14(sinang,z);
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat&RS_AUTO) || (dastat&RS_NOCLIP) == 0) //Don't aspect unscaled perms
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-08-19 12:51:04 +00:00
|
|
|
xv2 = mulscale16(xv,ourxyaspect);
|
|
|
|
yv2 = mulscale16(yv,ourxyaspect);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
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
|
|
|
|
|
2012-08-16 21:48:44 +00:00
|
|
|
npoints = clippoly4(cx1<<16,cy1<<16,(cx2+1)<<16,(cy2+1)<<16);
|
|
|
|
if (npoints < 3) return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
lx = nrx1[0]; rx = nrx1[0];
|
|
|
|
|
|
|
|
nextv = 0;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (v=npoints-1; v>=0; v--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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);
|
2013-05-12 18:51:30 +00:00
|
|
|
// Assertion fails with DNF mod: in mapster32,
|
|
|
|
// set dt_t 3864 (bike HUD, 700x220)
|
|
|
|
// set dt_a 100
|
|
|
|
// set dt_z 1280000 <- CRASH!
|
|
|
|
Bassert((unsigned)dax1 < MAXXDIM && (unsigned)dax2 < MAXXDIM+1);
|
|
|
|
qinterpolatedown16short((intptr_t)&uplc[dax1], dax2-dax1, yplc, yinc);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
yplc = y2 + mulscale16((dax2<<16)+65535-x2,yinc);
|
2013-05-12 18:51:30 +00:00
|
|
|
Bassert((unsigned)dax2 < MAXXDIM && (unsigned)dax1 < MAXXDIM+1);
|
|
|
|
qinterpolatedown16short((intptr_t)&dplc[dax2], dax1-dax2, yplc, yinc);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
nextv = v;
|
|
|
|
}
|
|
|
|
|
2018-04-12 21:03:30 +00:00
|
|
|
if (waloff[picnum] == 0) tileLoad(picnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
setgotpic(picnum);
|
|
|
|
bufplc = waloff[picnum];
|
|
|
|
|
2006-11-20 04:56:22 +00:00
|
|
|
if (palookup[dapalnum] == NULL) dapalnum = 0;
|
2012-12-14 19:27:58 +00:00
|
|
|
palookupoffs = FP_OFF(palookup[dapalnum]) + (getpalookup(0, dashade)<<8);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-04-09 18:51:31 +00:00
|
|
|
// Alpha handling
|
2016-10-09 07:55:18 +00:00
|
|
|
if (!(dastat&RS_TRANS1) && daalpha > 0)
|
2013-03-25 04:32:24 +00:00
|
|
|
{
|
2014-04-09 18:51:31 +00:00
|
|
|
if (daalpha == 255)
|
|
|
|
return;
|
2013-03-25 04:32:24 +00:00
|
|
|
|
2014-04-09 18:51:31 +00:00
|
|
|
if (numalphatabs != 0)
|
|
|
|
{
|
2016-10-14 07:33:30 +00:00
|
|
|
if (falpha_to_blend((float)daalpha / 255.0f, &dastat, &dablend, RS_TRANS1, RS_TRANS2))
|
|
|
|
return;
|
2014-04-09 18:51:31 +00:00
|
|
|
}
|
|
|
|
else if (daalpha > 84)
|
2013-03-25 04:32:24 +00:00
|
|
|
{
|
2014-04-09 18:51:31 +00:00
|
|
|
dastat |= RS_TRANS1;
|
|
|
|
|
|
|
|
if (daalpha > 168)
|
|
|
|
dastat |= RS_TRANS2;
|
2016-10-09 07:55:18 +00:00
|
|
|
else
|
|
|
|
dastat &= ~RS_TRANS2;
|
2019-09-21 11:02:17 +00:00
|
|
|
|
|
|
|
// Blood's transparency table is inverted
|
|
|
|
if (bloodhack)
|
|
|
|
dastat ^= RS_TRANS2;
|
2013-03-25 04:32:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
i = divscale32(1L,z);
|
|
|
|
xv = mulscale14(sinang,i);
|
|
|
|
yv = mulscale14(cosang,i);
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat&RS_AUTO) || (dastat&RS_NOCLIP)==0) //Don't aspect unscaled perms
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-08-19 12:51:04 +00:00
|
|
|
yv2 = mulscale16(-xv,ouryxaspect);
|
|
|
|
xv2 = mulscale16(yv,ouryxaspect);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
yv2 = -xv;
|
|
|
|
xv2 = yv;
|
|
|
|
}
|
|
|
|
|
2012-08-16 21:48:44 +00:00
|
|
|
x1 = (lx>>16);
|
|
|
|
x2 = (rx>>16);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
oy = 0;
|
2012-08-16 21:48:44 +00:00
|
|
|
x = (x1<<16)-1-gx1;
|
|
|
|
y = (oy<<16)+65535-gy1;
|
2006-04-13 20:47:06 +00:00
|
|
|
bx = dmulscale16(x,xv2,y,xv);
|
|
|
|
by = dmulscale16(x,yv2,y,yv);
|
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_YFLIP)
|
2012-08-16 21:48:44 +00:00
|
|
|
{
|
|
|
|
yv = -yv;
|
|
|
|
yv2 = -yv2;
|
|
|
|
by = (ysiz<<16)-1-by;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-03-18 23:17:32 +00:00
|
|
|
#if defined ENGINE_USING_A_C
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat&RS_TRANS1)==0 && ((a&1023) == 0) && (ysiz <= 256)) //vlineasm4 has 256 high limit!
|
2012-03-18 23:17:32 +00:00
|
|
|
#else
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat&RS_TRANS1) == 0)
|
2012-03-18 23:17:32 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-03-25 22:01:03 +00:00
|
|
|
int32_t y1ve[4], y2ve[4], u4, d4;
|
2012-02-12 13:46:57 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (((a&1023) == 0) && (ysiz <= 256)) //vlineasm4 has 256 high limit!
|
|
|
|
{
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK)
|
2012-08-16 21:48:44 +00:00
|
|
|
setupvlineasm(24L);
|
|
|
|
else
|
2013-11-16 18:47:11 +00:00
|
|
|
setupmvlineasm(24L, 0);
|
2012-08-16 21:48:44 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
by <<= 8; yv <<= 8; yv2 <<= 8;
|
|
|
|
|
|
|
|
palookupoffse[0] = palookupoffse[1] = palookupoffse[2] = palookupoffse[3] = palookupoffs;
|
|
|
|
vince[0] = vince[1] = vince[2] = vince[3] = yv;
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<x2; x+=4)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-04-05 19:49:54 +00:00
|
|
|
char bad;
|
|
|
|
int32_t xx, xend;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
bad = 15; xend = min(x2-x,4);
|
2009-02-19 16:47:54 +00:00
|
|
|
for (xx=0; xx<xend; xx++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
bx += xv2;
|
|
|
|
|
|
|
|
y1 = uplc[x+xx]; y2 = dplc[x+xx];
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat & RS_NOCLIP) == 0)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
if (startumost[x+xx] > y1) y1 = startumost[x+xx];
|
|
|
|
if (startdmost[x+xx] < y2) y2 = startdmost[x+xx];
|
|
|
|
}
|
|
|
|
if (y2 <= y1) continue;
|
|
|
|
|
Integer Overflow Offensive continued: first round of -ftrapv - cleanness.
That is, "clang -ftrapv" builds don't abort almost immediately after entering
a level.
There are various classes of overflow bugs, needing different handling:
- Some texture mapping code was written with signed integer wrapping semantics
in mind. In some places, we're able to get away with unsigned casts.
- sometimes, we really need a wider range, like when calculating distances or
dot products
- negating INT_MIN. Here, we cast to int64_t temporarily. Note that if the
result is 32-bit wide, no 64-bit code may actually need to be generated.
- shifting into a signed integer's sign bit. We cast to uint32 here.
- in hitscan(), at the "abyss crash prevention code" comment, it's clearly
the other code that is better...
This is not merely done for pedantry, but rather makes it easier to track down
overflow bugs having a real impact on the game.
git-svn-id: https://svn.eduke32.com/eduke32@2784 1a8010ca-5511-0410-912e-c29ae57300e0
2012-06-26 19:49:53 +00:00
|
|
|
by += (uint32_t)yv*(y1-oy); oy = y1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-05-12 18:51:32 +00:00
|
|
|
// Assertion would fail with DNF mod without (uint32_t) below: in mapster32,
|
2013-05-12 18:51:30 +00:00
|
|
|
// set dt_t 3864 (bike HUD, 700x220)
|
|
|
|
// set dt_z 16777216
|
|
|
|
// <Increase yxaspect by pressing [9]> <-- CRASH!
|
|
|
|
// (It also fails when wrecking the bike in-game by driving into a wall.)
|
2013-05-12 18:51:32 +00:00
|
|
|
// Bassert(bx >= 0);
|
2012-11-04 23:03:26 +00:00
|
|
|
|
2013-05-12 18:51:32 +00:00
|
|
|
bufplce[xx] = ((uint32_t)bx>>16)*ysiz+bufplc;
|
2006-04-13 20:47:06 +00:00
|
|
|
vplce[xx] = by;
|
|
|
|
y1ve[xx] = y1;
|
|
|
|
y2ve[xx] = y2-1;
|
|
|
|
bad &= ~pow2char[xx];
|
|
|
|
}
|
|
|
|
|
|
|
|
p = x+frameplace;
|
|
|
|
|
2012-03-25 13:55:03 +00:00
|
|
|
u4 = INT32_MIN;
|
|
|
|
d4 = INT32_MAX;
|
|
|
|
for (xx=0; xx<4; xx++)
|
2012-02-12 13:46:57 +00:00
|
|
|
if (!(bad&pow2char[xx]))
|
|
|
|
{
|
|
|
|
u4 = max(u4, y1ve[xx]);
|
|
|
|
d4 = min(d4, y2ve[xx]);
|
|
|
|
}
|
|
|
|
// This version may access uninitialized y?ve[] values with
|
|
|
|
// thin tiles, e.g. 3085 (MINIFONT period, 1x5):
|
|
|
|
// u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
|
|
|
|
// d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
2012-11-04 23:03:26 +00:00
|
|
|
if (d4 >= u4) vlineasm4(d4-u4+1, (char *)(ylookup[u4]+p));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2012-11-04 23:03:26 +00:00
|
|
|
if (d4 >= u4) mvlineasm4(d4-u4+1, (char *)(ylookup[u4]+p));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
2012-03-18 23:17:32 +00:00
|
|
|
#ifndef ENGINE_USING_A_C
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
|
|
|
{
|
2012-03-25 22:01:03 +00:00
|
|
|
int32_t ny1, ny2;
|
|
|
|
int32_t qlinemode = 0;
|
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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];
|
2013-11-22 19:26:52 +00:00
|
|
|
if (((dastat & RS_NOCLIP) == 0) && startumost[x1] > y1)
|
|
|
|
y1 = startumost[x1];
|
2006-04-13 20:47:06 +00:00
|
|
|
y2 = y1;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
ny1 = uplc[x]-1; ny2 = dplc[x];
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat & RS_NOCLIP) == 0)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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();
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//x,y1
|
2006-04-13 20:47:06 +00:00
|
|
|
bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1;
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
else rmhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
y1 = ny1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (y1 < ny1)
|
|
|
|
{
|
|
|
|
y1++; if ((y1&31) == 0) faketimerhandler();
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//x,y1
|
2006-04-13 20:47:06 +00:00
|
|
|
bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1;
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
else rmhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-02-18 17:55:43 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
while (y1 > ny1) lastx[y1--] = x;
|
|
|
|
}
|
2012-02-18 17:55:43 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
while (y2 > ny2)
|
|
|
|
{
|
|
|
|
y2--; if ((y2&31) == 0) faketimerhandler();
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//x,y2
|
2006-04-13 20:47:06 +00:00
|
|
|
bx += xv*(y2-oy); by += yv*(y2-oy); oy = y2;
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
else rmhlineasm4(x-lastx[y2],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y2]+x+frameplace);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-02-18 17:55:43 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
while (y2 < ny2) lastx[y2++] = x;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (y1 < y2-1)
|
|
|
|
{
|
|
|
|
y1++; if ((y1&31) == 0) faketimerhandler();
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//x,y1
|
2006-04-13 20:47:06 +00:00
|
|
|
bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1;
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
else rmhlineasm4(x-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-02-18 17:55:43 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (x == x2-1) { bx += xv2; by += yv2; break; }
|
2006-04-13 20:47:06 +00:00
|
|
|
y1 = uplc[x+1];
|
2013-11-22 19:26:52 +00:00
|
|
|
if (((dastat & RS_NOCLIP) == 0) && startumost[x+1] > y1)
|
|
|
|
y1 = startumost[x+1];
|
2006-04-13 20:47:06 +00:00
|
|
|
y2 = y1;
|
|
|
|
}
|
|
|
|
bx += xv2; by += yv2;
|
|
|
|
}
|
2012-02-18 17:55:43 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
while (y1 < y2-1)
|
|
|
|
{
|
|
|
|
y1++; if ((y1&31) == 0) faketimerhandler();
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//x2,y1
|
2006-04-13 20:47:06 +00:00
|
|
|
bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1;
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
else rmhlineasm4(x2-lastx[y1],(bx>>16)*ysiz+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x2+frameplace);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
2012-03-18 23:17:32 +00:00
|
|
|
#endif // !defined ENGINE_USING_A_C
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat & RS_TRANS1) == 0)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-02-18 17:55:43 +00:00
|
|
|
#if !defined ENGINE_USING_A_C
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK)
|
2006-04-13 20:47:06 +00:00
|
|
|
setupspritevline(palookupoffs,(xv>>16)*ysiz,xv<<16,ysiz,yv,0L);
|
|
|
|
else
|
|
|
|
msetupspritevline(palookupoffs,(xv>>16)*ysiz,xv<<16,ysiz,yv,0L);
|
2012-02-18 17:55:43 +00:00
|
|
|
#else
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK)
|
2012-02-18 17:55:43 +00:00
|
|
|
setupspritevline(palookupoffs,xv,yv,ysiz);
|
|
|
|
else
|
|
|
|
msetupspritevline(palookupoffs,xv,yv,ysiz);
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-02-18 17:55:59 +00:00
|
|
|
#if !defined ENGINE_USING_A_C
|
2006-04-13 20:47:06 +00:00
|
|
|
tsetupspritevline(palookupoffs,(xv>>16)*ysiz,xv<<16,ysiz,yv,0L);
|
2012-02-18 17:55:59 +00:00
|
|
|
#else
|
|
|
|
tsetupspritevline(palookupoffs,xv,yv,ysiz);
|
|
|
|
#endif
|
2014-03-05 21:12:54 +00:00
|
|
|
setup_blend(dablend, dastat & RS_TRANS2);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-03-18 23:17:32 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=x1; x<x2; x++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
bx += xv2; by += yv2;
|
|
|
|
|
|
|
|
y1 = uplc[x]; y2 = dplc[x];
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat & RS_NOCLIP) == 0)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
if (startumost[x] > y1) y1 = startumost[x];
|
|
|
|
if (startdmost[x] < y2) y2 = startdmost[x];
|
|
|
|
}
|
|
|
|
if (y2 <= y1) continue;
|
|
|
|
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (y1-oy)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-11-13 23:12:47 +00:00
|
|
|
case -1:
|
2012-02-18 17:55:27 +00:00
|
|
|
bx -= xv; by -= yv; oy = y1; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 0:
|
2012-02-18 17:55:27 +00:00
|
|
|
break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 1:
|
2012-02-18 17:55:27 +00:00
|
|
|
bx += xv; by += yv; oy = y1; break;
|
2006-11-13 23:12:47 +00:00
|
|
|
default:
|
2012-02-18 17:55:27 +00:00
|
|
|
bx += xv*(y1-oy); by += yv*(y1-oy); oy = y1; break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
p = ylookup[y1]+x+frameplace;
|
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat & RS_TRANS1) == 0)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-02-18 17:55:43 +00:00
|
|
|
#if !defined ENGINE_USING_A_C
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK)
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2012-02-18 17:55:43 +00:00
|
|
|
#else
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK)
|
2012-02-18 17:55:43 +00:00
|
|
|
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);
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-02-18 17:55:43 +00:00
|
|
|
#if !defined ENGINE_USING_A_C
|
2006-04-13 20:47:06 +00:00
|
|
|
tspritevline(0L,by<<16,y2-y1+1,bx<<16,(bx>>16)*ysiz+(by>>16)+bufplc,p);
|
2012-02-18 17:55:43 +00:00
|
|
|
#else
|
|
|
|
tspritevline(bx&65535,by&65535,y2-y1+1,(bx>>16)*ysiz+(by>>16)+bufplc,p);
|
|
|
|
//transarea += (y2-y1);
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 17:55:43 +00:00
|
|
|
faketimerhandler();
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
/* if ((dastat & RS_PERM) && (origbuffermode == 0))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
buffermode = obuffermode;
|
|
|
|
setactivepage(activepage);
|
|
|
|
}*/
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2016-10-23 19:47:36 +00:00
|
|
|
static uint32_t msqrtasm(uint32_t c)
|
|
|
|
{
|
|
|
|
uint32_t a = 0x40000000l, b = 0x20000000l;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (c >= a)
|
|
|
|
{
|
|
|
|
c -= a;
|
|
|
|
a += b*4;
|
|
|
|
}
|
|
|
|
a -= b;
|
|
|
|
a >>= 1;
|
|
|
|
b >>= 2;
|
|
|
|
} while (b);
|
|
|
|
|
|
|
|
if (c >= a)
|
|
|
|
a++;
|
|
|
|
|
|
|
|
return a >> 1;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// initksqrt (internal)
|
|
|
|
//
|
2009-02-19 09:39:19 +00:00
|
|
|
static inline void initksqrt(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t i, j, k;
|
2019-09-22 19:26:07 +00:00
|
|
|
uint32_t root, num;
|
|
|
|
int32_t temp;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
j = 1; k = 0;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<4096; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
if (i >= j) { j <<= 2; k++; }
|
2009-01-09 09:29:17 +00:00
|
|
|
sqrtable[i] = (uint16_t)(msqrtasm((i<<18)+131072)<<1);
|
2006-04-13 20:47:06 +00:00
|
|
|
shlookup[i] = (k<<1)+((10-k)<<8);
|
|
|
|
if (i < 256) shlookup[i+4096] = ((k+6)<<1)+((10-(k+6))<<8);
|
|
|
|
}
|
2019-09-22 19:26:07 +00:00
|
|
|
|
|
|
|
for(i=0;i<2048;i++)
|
|
|
|
{
|
|
|
|
root = 128;
|
|
|
|
num = i<<20;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
temp = root;
|
|
|
|
root = (root+num/root)>>1;
|
|
|
|
} while((temp-root+1) > 2);
|
|
|
|
temp = root*root-num;
|
|
|
|
while (klabs(int32_t(temp-2*root+1)) < klabs(temp))
|
|
|
|
{
|
|
|
|
temp += -(2*root)+1;
|
|
|
|
root--;
|
|
|
|
}
|
|
|
|
while (klabs(int32_t(temp+2*root+1)) < klabs(temp))
|
|
|
|
{
|
|
|
|
temp += 2*root+1;
|
|
|
|
root++;
|
|
|
|
}
|
|
|
|
sqrtable_old[i] = root;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// dosetaspect
|
|
|
|
//
|
|
|
|
static void dosetaspect(void)
|
|
|
|
{
|
2012-09-02 14:10:55 +00:00
|
|
|
int32_t i, j;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (xyaspect != oxyaspect)
|
|
|
|
{
|
|
|
|
oxyaspect = xyaspect;
|
|
|
|
j = xyaspect*320;
|
2019-06-25 11:29:46 +00:00
|
|
|
horizlookup2[horizycent-1] = divscale32(131072,j);
|
2014-10-29 17:04:28 +00:00
|
|
|
|
2014-10-25 03:30:38 +00:00
|
|
|
for (i=0; i < horizycent-1; i++)
|
2014-10-25 03:29:21 +00:00
|
|
|
{
|
|
|
|
horizlookup[i] = divscale28(1, i-(horizycent-1));
|
2019-06-25 11:29:46 +00:00
|
|
|
horizlookup2[i] = divscale20(klabs(horizlookup[i]), j);
|
2014-10-25 03:29:21 +00:00
|
|
|
}
|
|
|
|
|
2014-10-25 03:30:38 +00:00
|
|
|
for (i=horizycent; i < ydim*4-1; i++)
|
2014-10-25 03:29:21 +00:00
|
|
|
{
|
|
|
|
horizlookup[i] = divscale28(1, i-(horizycent-1));
|
2019-06-25 11:29:46 +00:00
|
|
|
horizlookup2[i] = divscale20(klabs(horizlookup[i]), j);
|
2014-10-25 03:29:21 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-09-02 14:10:55 +00:00
|
|
|
|
|
|
|
if (xdimen != oxdimen || viewingrange != oviewingrange)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-09-02 14:10:55 +00:00
|
|
|
int32_t k, x, xinc;
|
|
|
|
|
|
|
|
no_radarang2 = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
oviewingrange = viewingrange;
|
2012-09-02 14:10:55 +00:00
|
|
|
|
2019-06-25 11:29:42 +00:00
|
|
|
xinc = mulscale32(viewingrange*2560,xdimenrecip);
|
|
|
|
x = (5120<<16)-mulscale1(xinc,xdimen);
|
2012-09-02 14:10:55 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<xdimen; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
j = (x&65535); k = (x>>16); x += xinc;
|
2012-09-02 14:10:55 +00:00
|
|
|
|
2019-06-25 11:29:42 +00:00
|
|
|
if (k < 0 || k >= (int32_t)ARRAY_SIZE(qradarang)-1)
|
2012-09-02 14:10:55 +00:00
|
|
|
{
|
|
|
|
no_radarang2 = 1;
|
|
|
|
#ifdef DEBUGGINGAIDS
|
|
|
|
if (editstatus)
|
|
|
|
initprintf("no rad2\n");
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j != 0)
|
2019-06-25 11:29:42 +00:00
|
|
|
j = mulscale16(qradarang[k+1]-qradarang[k], j);
|
|
|
|
radarang2[i] = ((qradarang[k]+j)>>6);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-09-02 14:10:55 +00:00
|
|
|
|
2019-07-28 09:01:06 +00:00
|
|
|
if (xdimen != oxdimen && (voxoff[0][0] || bloodhack))
|
2014-08-23 09:00:36 +00:00
|
|
|
{
|
2019-08-01 06:50:26 +00:00
|
|
|
distrecip = NULL;
|
|
|
|
for (i = 0; i < DISTRECIPCACHESIZE; i++)
|
2015-01-11 04:55:23 +00:00
|
|
|
{
|
2019-08-01 06:50:26 +00:00
|
|
|
if (distrecipcache[i].xdimen == xdimen)
|
|
|
|
distrecip = distrecipcache[i].distrecip;
|
2015-01-11 04:55:23 +00:00
|
|
|
}
|
2019-08-01 06:50:26 +00:00
|
|
|
if (distrecip == NULL)
|
2015-01-11 04:55:23 +00:00
|
|
|
{
|
2019-08-01 06:50:26 +00:00
|
|
|
int32_t minAge = 0;
|
|
|
|
for (i = 1; i < DISTRECIPCACHESIZE; i++)
|
|
|
|
{
|
|
|
|
if (distrecipcache[i].age < distrecipcache[minAge].age)
|
|
|
|
minAge = i;
|
|
|
|
}
|
|
|
|
if (distrecipcache[minAge].distrecip == NULL)
|
|
|
|
distrecipcache[minAge].distrecip = (uint32_t *)Xaligned_alloc(16, DISTRECIPSIZ * sizeof(uint32_t));
|
|
|
|
|
|
|
|
distrecipcache[minAge].age = ++distrecipagecnt;
|
|
|
|
distrecipcache[minAge].xdimen = xdimen;
|
|
|
|
|
|
|
|
distrecip = distrecipcache[minAge].distrecip;
|
|
|
|
|
|
|
|
if (xdimen < 1 << 11)
|
|
|
|
{
|
|
|
|
for (i = 1; i < DISTRECIPSIZ; i++)
|
|
|
|
distrecip[i] = tabledivide32(xdimen << 20, i);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 1; i < DISTRECIPSIZ; i++)
|
|
|
|
distrecip[i] = tabledivide64((uint64_t)xdimen << 20, i);
|
|
|
|
}
|
2015-01-11 04:55:23 +00:00
|
|
|
}
|
2014-10-25 03:29:21 +00:00
|
|
|
|
|
|
|
nytooclose = xdimen*2100;
|
2014-08-23 09:00:36 +00:00
|
|
|
}
|
2012-09-02 14:10:55 +00:00
|
|
|
|
2014-10-25 03:29:21 +00:00
|
|
|
oxdimen = xdimen;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// loadtables (internal)
|
|
|
|
//
|
2009-02-19 09:39:19 +00:00
|
|
|
static inline void calcbritable(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-09-30 04:18:43 +00:00
|
|
|
int32_t i, j;
|
|
|
|
float a, b;
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<16; i++)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2014-09-30 04:18:43 +00:00
|
|
|
a = 8.f / ((float)i+8.f);
|
|
|
|
b = 255.f / powf(255.f, a);
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (j=0; j<256; j++) // JBF 20040207: full 8bit precision
|
2014-09-30 04:18:43 +00:00
|
|
|
britable[i][j] = (uint8_t) (powf((float)j, a) * b);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
static int32_t engineLoadTables(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-09-02 14:08:43 +00:00
|
|
|
static char tablesloaded = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (tablesloaded == 0)
|
|
|
|
{
|
2012-09-02 14:08:43 +00:00
|
|
|
int32_t i;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
initksqrt();
|
|
|
|
|
2012-03-22 22:48:06 +00:00
|
|
|
for (i=0; i<2048; i++)
|
|
|
|
reciptable[i] = divscale30(2048, i+2048);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-06-25 11:30:03 +00:00
|
|
|
for (i=0; i<SLOPTABLESIZ; i++)
|
|
|
|
sloptable[i] = krecipasm(i-HALFSLOPTABLESIZ);
|
2014-11-02 05:35:06 +00:00
|
|
|
|
2012-09-02 14:08:43 +00:00
|
|
|
for (i=0; i<=512; i++)
|
2014-09-30 04:15:04 +00:00
|
|
|
sintable[i] = (int16_t)(16384.f * sinf((float)i * BANG2RAD));
|
2012-09-02 14:08:43 +00:00
|
|
|
for (i=513; i<1024; i++)
|
|
|
|
sintable[i] = sintable[1024-i];
|
|
|
|
for (i=1024; i<2048; i++)
|
|
|
|
sintable[i] = -sintable[i-1024];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-09-02 14:08:43 +00:00
|
|
|
for (i=0; i<640; i++)
|
2014-09-30 04:15:04 +00:00
|
|
|
radarang[i] = (int16_t)(atanf(((float)(640-i)-0.5f) * (1.f/160.f)) * (-64.f * (1.f/BANG2RAD)));
|
2012-09-02 14:08:43 +00:00
|
|
|
for (i=0; i<640; i++)
|
|
|
|
radarang[1279-i] = -radarang[i];
|
|
|
|
|
2019-06-25 11:29:42 +00:00
|
|
|
for (i=0; i<5120; i++)
|
2019-09-08 13:51:07 +00:00
|
|
|
qradarang[i] = fix16_from_float(atanf(((float)(5120-i)-0.5f) * (1.f/1280.f)) * (-64.f * (1.f/BANG2RAD)));
|
2019-06-25 11:29:42 +00:00
|
|
|
for (i=0; i<5120; i++)
|
|
|
|
qradarang[10239-i] = -qradarang[i];
|
|
|
|
|
2012-09-02 14:08:43 +00:00
|
|
|
#ifdef B_LITTLE_ENDIAN
|
|
|
|
i = 0;
|
2014-10-01 17:09:54 +00:00
|
|
|
if (Bcrc32((uint8_t *)sintable, sizeof(sintable), 0) != 0xee1e7aba)
|
2012-09-02 14:08:43 +00:00
|
|
|
i |= 1;
|
2014-10-01 17:09:54 +00:00
|
|
|
if (Bcrc32((uint8_t *)radarang, 640*sizeof(radarang[0]), 0) != 0xee893d92)
|
2012-09-02 14:08:43 +00:00
|
|
|
i |= 2;
|
|
|
|
|
|
|
|
if (i != 0)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2012-09-02 14:08:43 +00:00
|
|
|
static const char *str[3] = { "sine table", "arctangent table",
|
|
|
|
"sine and arctangent tables" };
|
|
|
|
initprintf("WARNING: Calculated %s differ%s from original!\n",
|
|
|
|
str[i-1], i==3 ? "" : "s");
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-09-02 14:08:43 +00:00
|
|
|
#endif
|
|
|
|
// TABLES.DAT format:
|
|
|
|
//kread(fil,sintable,2048*2);
|
|
|
|
//kread(fil,radarang,640*2);
|
|
|
|
//kread(fil,textfont,1024);
|
|
|
|
//kread(fil,smalltextfont,1024);
|
|
|
|
//kread(fil,britable,1024);
|
|
|
|
|
|
|
|
calcbritable();
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
tablesloaded = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-13 20:06:07 +00:00
|
|
|
////////// SPRITE LIST MANIPULATION FUNCTIONS //////////
|
|
|
|
|
2013-12-31 11:51:54 +00:00
|
|
|
#ifdef NETCODE_DISABLE
|
|
|
|
# define LISTFN_STATIC static
|
|
|
|
#else
|
|
|
|
# define LISTFN_STATIC
|
|
|
|
#endif
|
|
|
|
|
2012-03-13 20:07:17 +00:00
|
|
|
///// sector lists of sprites /////
|
2012-03-13 20:06:07 +00:00
|
|
|
|
|
|
|
// insert sprite at the head of sector list, change .sectnum
|
2013-12-31 11:51:54 +00:00
|
|
|
LISTFN_STATIC void do_insertsprite_at_headofsect(int16_t spritenum, int16_t sectnum)
|
2012-03-13 20:06:07 +00:00
|
|
|
{
|
2016-06-21 00:33:39 +00:00
|
|
|
int16_t const ohead = headspritesect[sectnum];
|
2012-03-13 20:06:07 +00:00
|
|
|
|
|
|
|
prevspritesect[spritenum] = -1;
|
|
|
|
nextspritesect[spritenum] = ohead;
|
|
|
|
if (ohead >= 0)
|
|
|
|
prevspritesect[ohead] = spritenum;
|
|
|
|
headspritesect[sectnum] = spritenum;
|
|
|
|
|
|
|
|
sprite[spritenum].sectnum = sectnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove sprite 'deleteme' from its sector list
|
2013-12-31 11:51:54 +00:00
|
|
|
LISTFN_STATIC void do_deletespritesect(int16_t deleteme)
|
2012-03-13 20:06:07 +00:00
|
|
|
{
|
2016-06-21 00:33:39 +00:00
|
|
|
int32_t const sectnum = sprite[deleteme].sectnum;
|
|
|
|
int32_t const prev = prevspritesect[deleteme];
|
|
|
|
int32_t const next = nextspritesect[deleteme];
|
2012-03-13 20:06:07 +00:00
|
|
|
|
|
|
|
if (headspritesect[sectnum] == deleteme)
|
|
|
|
headspritesect[sectnum] = next;
|
|
|
|
if (prev >= 0)
|
|
|
|
nextspritesect[prev] = next;
|
|
|
|
if (next >= 0)
|
|
|
|
prevspritesect[next] = prev;
|
|
|
|
}
|
|
|
|
|
2012-03-14 22:29:45 +00:00
|
|
|
///// now, status lists /////
|
2012-03-13 20:06:07 +00:00
|
|
|
|
2012-03-13 20:07:17 +00:00
|
|
|
// insert sprite at head of status list, change .statnum
|
2013-12-31 11:51:54 +00:00
|
|
|
LISTFN_STATIC void do_insertsprite_at_headofstat(int16_t spritenum, int16_t statnum)
|
2012-03-13 20:06:07 +00:00
|
|
|
{
|
2016-06-21 00:33:39 +00:00
|
|
|
int16_t const ohead = headspritestat[statnum];
|
2012-03-13 20:06:07 +00:00
|
|
|
|
|
|
|
prevspritestat[spritenum] = -1;
|
|
|
|
nextspritestat[spritenum] = ohead;
|
|
|
|
if (ohead >= 0)
|
|
|
|
prevspritestat[ohead] = spritenum;
|
|
|
|
headspritestat[statnum] = spritenum;
|
|
|
|
|
|
|
|
sprite[spritenum].statnum = statnum;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
// insertspritestat (internal)
|
2013-12-31 11:51:54 +00:00
|
|
|
LISTFN_STATIC int32_t insertspritestat(int16_t statnum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
if ((statnum >= MAXSTATUS) || (headspritestat[MAXSTATUS] == -1))
|
2016-06-21 00:33:39 +00:00
|
|
|
return -1; //list full
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-03-13 20:04:56 +00:00
|
|
|
// remove one sprite from the statnum-freelist
|
2016-06-21 00:33:39 +00:00
|
|
|
int16_t const blanktouse = headspritestat[MAXSTATUS];
|
2006-04-13 20:47:06 +00:00
|
|
|
headspritestat[MAXSTATUS] = nextspritestat[blanktouse];
|
2012-03-13 20:04:56 +00:00
|
|
|
|
2012-03-13 20:06:07 +00:00
|
|
|
// make back-link of the new freelist head point to nil
|
2006-04-13 20:47:06 +00:00
|
|
|
if (headspritestat[MAXSTATUS] >= 0)
|
|
|
|
prevspritestat[headspritestat[MAXSTATUS]] = -1;
|
2019-09-22 19:26:07 +00:00
|
|
|
else if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE)
|
2012-03-13 20:07:17 +00:00
|
|
|
tailspritefree = -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-03-13 20:06:07 +00:00
|
|
|
do_insertsprite_at_headofstat(blanktouse, statnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:39 +00:00
|
|
|
return blanktouse;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2012-03-13 20:06:07 +00:00
|
|
|
// remove sprite 'deleteme' from its status list
|
2018-12-08 00:40:39 +00:00
|
|
|
LISTFN_STATIC void do_deletespritestat(int16_t deleteme)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:33:39 +00:00
|
|
|
int32_t const sectnum = sprite[deleteme].statnum;
|
|
|
|
int32_t const prev = prevspritestat[deleteme];
|
|
|
|
int32_t const next = nextspritestat[deleteme];
|
2012-03-13 20:06:07 +00:00
|
|
|
|
|
|
|
if (headspritestat[sectnum] == deleteme)
|
|
|
|
headspritestat[sectnum] = next;
|
|
|
|
if (prev >= 0)
|
|
|
|
nextspritestat[prev] = next;
|
|
|
|
if (next >= 0)
|
|
|
|
prevspritestat[next] = prev;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-13 20:05:51 +00:00
|
|
|
//
|
|
|
|
// insertsprite
|
|
|
|
//
|
2019-09-19 20:02:45 +00:00
|
|
|
int32_t(*insertsprite_replace)(int16_t sectnum, int16_t statnum) = NULL;
|
2012-03-13 20:05:51 +00:00
|
|
|
int32_t insertsprite(int16_t sectnum, int16_t statnum)
|
|
|
|
{
|
2019-09-19 20:02:45 +00:00
|
|
|
if (insertsprite_replace)
|
|
|
|
return insertsprite_replace(sectnum, statnum);
|
2012-03-14 22:30:57 +00:00
|
|
|
// TODO: guard against bad sectnum?
|
2016-06-21 00:33:39 +00:00
|
|
|
int32_t const newspritenum = insertspritestat(statnum);
|
2012-03-14 22:29:45 +00:00
|
|
|
|
|
|
|
if (newspritenum >= 0)
|
2012-03-14 22:30:24 +00:00
|
|
|
{
|
2012-03-26 22:04:44 +00:00
|
|
|
Bassert((unsigned)sectnum < MAXSECTORS);
|
2012-03-14 22:30:57 +00:00
|
|
|
|
2012-03-14 22:29:45 +00:00
|
|
|
do_insertsprite_at_headofsect(newspritenum, sectnum);
|
2012-03-14 22:30:24 +00:00
|
|
|
Numsprites++;
|
|
|
|
}
|
2012-03-14 22:29:45 +00:00
|
|
|
|
|
|
|
return newspritenum;
|
|
|
|
|
2012-03-13 20:05:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// deletesprite
|
|
|
|
//
|
2019-09-19 20:02:45 +00:00
|
|
|
int32_t (*deletesprite_replace)(int16_t spritenum) = NULL;
|
2012-03-13 20:05:51 +00:00
|
|
|
int32_t deletesprite(int16_t spritenum)
|
|
|
|
{
|
2019-09-19 20:02:45 +00:00
|
|
|
if (deletesprite_replace)
|
|
|
|
return deletesprite_replace(spritenum);
|
2012-03-26 22:04:44 +00:00
|
|
|
Bassert((sprite[spritenum].statnum == MAXSTATUS)
|
|
|
|
== (sprite[spritenum].sectnum == MAXSECTORS));
|
2012-03-13 20:07:17 +00:00
|
|
|
|
|
|
|
if (sprite[spritenum].statnum == MAXSTATUS)
|
2016-06-21 00:33:39 +00:00
|
|
|
return -1; // already not in the world
|
2012-03-13 20:07:17 +00:00
|
|
|
|
|
|
|
do_deletespritestat(spritenum);
|
|
|
|
do_deletespritesect(spritenum);
|
|
|
|
|
2012-03-14 22:29:45 +00:00
|
|
|
// (dummy) insert at tail of sector freelist, compat
|
|
|
|
// for code that checks .sectnum==MAXSECTOR
|
2012-03-13 20:07:17 +00:00
|
|
|
sprite[spritenum].sectnum = MAXSECTORS;
|
|
|
|
|
|
|
|
// insert at tail of status freelist
|
2019-09-22 19:26:07 +00:00
|
|
|
if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE)
|
2019-09-21 11:02:17 +00:00
|
|
|
do_insertsprite_at_headofstat(spritenum, MAXSTATUS);
|
2012-03-13 20:07:17 +00:00
|
|
|
else
|
2019-09-21 11:02:17 +00:00
|
|
|
{
|
|
|
|
prevspritestat[spritenum] = tailspritefree;
|
|
|
|
nextspritestat[spritenum] = -1;
|
|
|
|
if (tailspritefree >= 0)
|
|
|
|
nextspritestat[tailspritefree] = spritenum;
|
|
|
|
else
|
|
|
|
headspritestat[MAXSTATUS] = spritenum;
|
|
|
|
sprite[spritenum].statnum = MAXSTATUS;
|
2012-03-13 20:07:17 +00:00
|
|
|
|
2019-09-21 11:02:17 +00:00
|
|
|
tailspritefree = spritenum;
|
|
|
|
}
|
2012-03-14 22:30:24 +00:00
|
|
|
Numsprites--;
|
2012-03-13 20:07:17 +00:00
|
|
|
|
|
|
|
return 0;
|
2012-03-13 20:05:51 +00:00
|
|
|
}
|
|
|
|
|
2012-03-13 20:06:22 +00:00
|
|
|
//
|
|
|
|
// changespritesect
|
|
|
|
//
|
2019-09-19 20:02:45 +00:00
|
|
|
int32_t (*changespritesect_replace)(int16_t spritenum, int16_t newsectnum) = NULL;
|
2012-03-13 20:06:22 +00:00
|
|
|
int32_t changespritesect(int16_t spritenum, int16_t newsectnum)
|
|
|
|
{
|
2019-09-19 20:02:45 +00:00
|
|
|
if (changespritesect_replace)
|
|
|
|
return changespritesect_replace(spritenum, newsectnum);
|
2013-02-10 16:24:27 +00:00
|
|
|
// XXX: NOTE: MAXSECTORS is allowed
|
2016-06-21 00:33:39 +00:00
|
|
|
if ((newsectnum < 0 || newsectnum > MAXSECTORS) || (sprite[spritenum].sectnum == MAXSECTORS))
|
|
|
|
return -1;
|
|
|
|
|
2013-02-10 16:24:27 +00:00
|
|
|
if (sprite[spritenum].sectnum == newsectnum)
|
2016-06-21 00:33:39 +00:00
|
|
|
return 0;
|
2012-03-13 20:06:22 +00:00
|
|
|
|
2012-03-13 20:06:52 +00:00
|
|
|
do_deletespritesect(spritenum);
|
|
|
|
do_insertsprite_at_headofsect(spritenum, newsectnum);
|
2012-03-13 20:06:22 +00:00
|
|
|
|
2016-06-21 00:33:39 +00:00
|
|
|
return 0;
|
2012-03-13 20:06:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// changespritestat
|
|
|
|
//
|
2019-09-19 20:02:45 +00:00
|
|
|
int32_t (*changespritestat_replace)(int16_t spritenum, int16_t newstatnum) = NULL;
|
2012-03-13 20:06:22 +00:00
|
|
|
int32_t changespritestat(int16_t spritenum, int16_t newstatnum)
|
|
|
|
{
|
2019-09-19 20:02:45 +00:00
|
|
|
if (changespritestat_replace)
|
|
|
|
return changespritestat_replace(spritenum, newstatnum);
|
2013-02-10 16:24:27 +00:00
|
|
|
// XXX: NOTE: MAXSTATUS is allowed
|
2016-06-21 00:33:39 +00:00
|
|
|
if ((newstatnum < 0 || newstatnum > MAXSTATUS) || (sprite[spritenum].statnum == MAXSTATUS))
|
|
|
|
return -1; // can't set the statnum of a sprite not in the world
|
|
|
|
|
2013-02-10 16:24:27 +00:00
|
|
|
if (sprite[spritenum].statnum == newstatnum)
|
2016-06-21 00:33:39 +00:00
|
|
|
return 0; // sprite already has desired statnum
|
2012-03-13 20:06:22 +00:00
|
|
|
|
2012-03-13 20:06:52 +00:00
|
|
|
do_deletespritestat(spritenum);
|
|
|
|
do_insertsprite_at_headofstat(spritenum, newstatnum);
|
2012-03-13 20:06:22 +00:00
|
|
|
|
2016-06-21 00:34:41 +00:00
|
|
|
return 0;
|
2012-03-13 20:06:22 +00:00
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// lintersect (internal)
|
|
|
|
//
|
2019-04-05 17:45:16 +00:00
|
|
|
int32_t lintersect(const int32_t originX, const int32_t originY, const int32_t originZ,
|
|
|
|
const int32_t destX, const int32_t destY, const int32_t destZ,
|
|
|
|
const int32_t lineStartX, const int32_t lineStartY, const int32_t lineEndX, const int32_t lineEndY,
|
|
|
|
int32_t *intersectionX, int32_t *intersectionY, int32_t *intersectionZ)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2019-04-05 17:45:16 +00:00
|
|
|
const vec2_t ray = { destX-originX,
|
|
|
|
destY-originY };
|
|
|
|
const vec2_t lineVec = { lineEndX-lineStartX,
|
|
|
|
lineEndY-lineStartY };
|
|
|
|
const vec2_t originDiff = { lineStartX-originX,
|
|
|
|
lineStartY-originY };
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2019-04-05 17:45:16 +00:00
|
|
|
const int32_t rayCrossLineVec = ray.x*lineVec.y - ray.y*lineVec.x;
|
|
|
|
const int32_t originDiffCrossRay = originDiff.x*ray.y - originDiff.y*ray.x;
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2019-04-05 17:45:16 +00:00
|
|
|
if (rayCrossLineVec == 0)
|
2018-05-15 16:45:34 +00:00
|
|
|
{
|
2019-09-22 19:26:07 +00:00
|
|
|
if (originDiffCrossRay != 0 || enginecompatibility_mode != ENGINECOMPATIBILITY_NONE)
|
2019-04-05 17:45:16 +00:00
|
|
|
{
|
|
|
|
// line segments are parallel
|
|
|
|
return 0;
|
|
|
|
}
|
2018-12-15 01:40:31 +00:00
|
|
|
|
2019-04-05 17:45:16 +00:00
|
|
|
// line segments are collinear
|
|
|
|
const int32_t rayLengthSquared = ray.x*ray.x + ray.y*ray.y;
|
|
|
|
const int32_t rayDotOriginDiff = ray.x*originDiff.x + ray.y*originDiff.y;
|
|
|
|
const int32_t rayDotLineEndDiff = rayDotOriginDiff + ray.x*lineVec.x + ray.y*lineVec.y;
|
2019-04-05 17:45:19 +00:00
|
|
|
int64_t t = min(rayDotOriginDiff, rayDotLineEndDiff);
|
2019-04-05 17:45:16 +00:00
|
|
|
if (rayDotOriginDiff < 0)
|
|
|
|
{
|
|
|
|
if (rayDotLineEndDiff < 0)
|
|
|
|
return 0;
|
2018-12-15 01:40:31 +00:00
|
|
|
|
2019-04-05 17:45:16 +00:00
|
|
|
t = 0;
|
|
|
|
}
|
|
|
|
else if (rayDotOriginDiff > rayLengthSquared)
|
|
|
|
{
|
|
|
|
if (rayDotLineEndDiff > rayLengthSquared)
|
|
|
|
return 0;
|
2018-12-15 01:40:31 +00:00
|
|
|
|
2019-04-05 17:45:16 +00:00
|
|
|
t = rayDotLineEndDiff;
|
|
|
|
}
|
2019-04-05 17:45:19 +00:00
|
|
|
t = tabledivide64(t << 24L, rayLengthSquared);
|
|
|
|
|
2019-04-05 17:45:16 +00:00
|
|
|
*intersectionX = originX + mulscale24(ray.x, t);
|
|
|
|
*intersectionY = originY + mulscale24(ray.y, t);
|
|
|
|
*intersectionZ = originZ + mulscale24(destZ-originZ, t);
|
2018-12-15 01:40:31 +00:00
|
|
|
|
2019-04-05 17:45:16 +00:00
|
|
|
return 1;
|
2018-05-15 16:45:34 +00:00
|
|
|
}
|
2018-12-15 01:40:31 +00:00
|
|
|
|
2019-04-05 17:45:16 +00:00
|
|
|
const int32_t originDiffCrossLineVec = originDiff.x*lineVec.y - originDiff.y*lineVec.x;
|
|
|
|
static const int32_t signBit = 1u<<31u;
|
2019-04-05 17:45:19 +00:00
|
|
|
// Any point on either line can be expressed as p+t*r and q+u*s
|
|
|
|
// The two line segments intersect when we can find a t & u such that p+t*r = q+u*s
|
|
|
|
// If the point is outside of the bounds of the line segment, we know we don't have an intersection.
|
2019-04-05 17:45:16 +00:00
|
|
|
// t is < 0 if (originDiffCrossLineVec^rayCrossLineVec) & signBit)
|
|
|
|
// u is < 0 if (originDiffCrossRay^rayCrossLineVec) & signBit
|
2019-04-05 20:41:04 +00:00
|
|
|
// t is > 1 if klabs(originDiffCrossLineVec) > klabs(rayCrossLineVec)
|
|
|
|
// u is > 1 if klabs(originDiffCrossRay) > klabs(rayCrossLineVec)
|
2019-04-05 17:45:19 +00:00
|
|
|
// where int32_t u = tabledivide64(((int64_t) originDiffCrossRay) << 24L, rayCrossLineVec);
|
|
|
|
if (((originDiffCrossLineVec^rayCrossLineVec) & signBit) ||
|
|
|
|
((originDiffCrossRay^rayCrossLineVec) & signBit) ||
|
2019-04-05 20:41:04 +00:00
|
|
|
klabs(originDiffCrossLineVec) > klabs(rayCrossLineVec) ||
|
|
|
|
klabs(originDiffCrossRay) > klabs(rayCrossLineVec))
|
2019-04-05 17:45:16 +00:00
|
|
|
{
|
|
|
|
// line segments do not overlap
|
|
|
|
return 0;
|
|
|
|
}
|
2019-04-05 17:45:19 +00:00
|
|
|
|
|
|
|
int64_t t = tabledivide64(((int64_t) originDiffCrossLineVec) << 24L, rayCrossLineVec);
|
|
|
|
// For sake of completeness/readability, alternative to the above approach for an early out & avoidance of an extra division:
|
|
|
|
#if 0
|
|
|
|
int64_t u = tabledivide64(((int64_t) originDiffCrossRay) << 24L, rayCrossLineVec);
|
|
|
|
if (u < 0 || u > 1 << 24 || t < 0 || t > 1 << 24)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-04-05 17:45:16 +00:00
|
|
|
*intersectionX = originX + mulscale24(ray.x, t);
|
|
|
|
*intersectionY = originY + mulscale24(ray.y, t);
|
|
|
|
*intersectionZ = originZ + mulscale24(destZ-originZ, t);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-01-11 04:56:58 +00:00
|
|
|
return 1;
|
2010-09-27 21:52:04 +00:00
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// rintersect (internal)
|
|
|
|
//
|
2012-10-14 20:41:34 +00:00
|
|
|
// returns: -1 if didn't intersect, coefficient (x3--x4 fraction)<<16 else
|
2019-07-29 11:12:06 +00:00
|
|
|
int32_t rintersect_old(int32_t x1, int32_t y1, int32_t z1,
|
|
|
|
int32_t vx, int32_t vy, int32_t vz,
|
|
|
|
int32_t x3, int32_t y3, int32_t x4, int32_t y4,
|
|
|
|
int32_t *intx, int32_t *inty, int32_t *intz)
|
|
|
|
{
|
|
|
|
//p1 towards p2 is a ray
|
|
|
|
|
|
|
|
int32_t const x34=x3-x4, y34=y3-y4;
|
|
|
|
int32_t const x31=x3-x1, y31=y3-y1;
|
|
|
|
|
|
|
|
int32_t const bot = vx*y34 - vy*x34;
|
|
|
|
int32_t const topt = x31*y34 - y31*x34;
|
|
|
|
|
|
|
|
if (bot == 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
int32_t const topu = vx*y31 - vy*x31;
|
|
|
|
|
|
|
|
if (bot > 0 && (topt < 0 || topu < 0 || topu >= bot))
|
|
|
|
return -1;
|
|
|
|
else if (bot < 0 && (topt > 0 || topu > 0 || topu <= bot))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
int32_t t = divscale16(topt, bot);
|
|
|
|
*intx = x1 + mulscale16(vx, t);
|
|
|
|
*inty = y1 + mulscale16(vy, t);
|
|
|
|
*intz = z1 + mulscale16(vz, t);
|
|
|
|
|
|
|
|
t = divscale16(topu, bot);
|
|
|
|
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t rintersect(int32_t x1, int32_t y1, int32_t z1,
|
2019-06-25 11:28:40 +00:00
|
|
|
int32_t vx, int32_t vy, int32_t vz,
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t x3, int32_t y3, int32_t x4, int32_t y4,
|
|
|
|
int32_t *intx, int32_t *inty, int32_t *intz)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
|
|
|
//p1 towards p2 is a ray
|
2012-06-13 23:13:39 +00:00
|
|
|
|
2019-09-22 19:26:07 +00:00
|
|
|
if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE)
|
2019-07-29 11:12:06 +00:00
|
|
|
return rintersect_old(x1,y1,z1,vx,vy,vz,x3,y3,x4,y4,intx,inty,intz);
|
|
|
|
|
2019-06-25 11:28:40 +00:00
|
|
|
int64_t const x34=x3-x4, y34=y3-y4;
|
|
|
|
int64_t const x31=x3-x1, y31=y3-y1;
|
|
|
|
|
|
|
|
int64_t const bot = vx*y34 - vy*x34;
|
|
|
|
int64_t const topt = x31*y34 - y31*x34;
|
2013-03-24 18:55:40 +00:00
|
|
|
|
|
|
|
if (bot == 0)
|
|
|
|
return -1;
|
2012-06-13 23:13:39 +00:00
|
|
|
|
2019-06-25 11:28:40 +00:00
|
|
|
int64_t const topu = vx*y31 - vy*x31;
|
|
|
|
|
|
|
|
if (bot > 0 && (topt < 0 || topu < 0 || topu >= bot))
|
|
|
|
return -1;
|
|
|
|
else if (bot < 0 && (topt > 0 || topu > 0 || topu <= bot))
|
|
|
|
return -1;
|
|
|
|
|
2019-07-24 01:37:28 +00:00
|
|
|
int64_t t = tabledivide64_noinline(topt<<16, bot);
|
2012-06-13 23:13:39 +00:00
|
|
|
*intx = x1 + ((vx*t)>>16);
|
|
|
|
*inty = y1 + ((vy*t)>>16);
|
|
|
|
*intz = z1 + ((vz*t)>>16);
|
|
|
|
|
2019-07-24 01:37:28 +00:00
|
|
|
t = tabledivide64_noinline(topu<<16, bot);
|
2019-06-25 11:28:40 +00:00
|
|
|
|
2012-10-14 20:41:34 +00:00
|
|
|
Bassert((unsigned)t < 65536);
|
|
|
|
|
|
|
|
return t;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2010-09-27 21:52:04 +00:00
|
|
|
int32_t rayintersect(int32_t x1, int32_t y1, int32_t z1, int32_t vx, int32_t vy, int32_t vz, int32_t x3,
|
|
|
|
int32_t y3, int32_t x4, int32_t y4, int32_t *intx, int32_t *inty, int32_t *intz)
|
|
|
|
{
|
2012-10-14 20:41:34 +00:00
|
|
|
return (rintersect(x1, y1, z1, vx, vy, vz, x3, y3, x4, y4, intx, inty, intz) != -1);
|
2010-09-27 21:52:04 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-05-27 08:47:34 +00:00
|
|
|
//
|
|
|
|
// multi-pskies
|
|
|
|
//
|
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
psky_t * tileSetupSky(int32_t const tilenum)
|
2015-05-27 08:47:34 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i = 0; i < pskynummultis; i++)
|
2015-05-27 08:47:34 +00:00
|
|
|
if (multipskytile[i] == tilenum)
|
|
|
|
return &multipsky[i];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-05-27 08:47:34 +00:00
|
|
|
int32_t const newPskyID = pskynummultis++;
|
|
|
|
multipsky = (psky_t *)Xrealloc(multipsky, pskynummultis * sizeof(psky_t));
|
|
|
|
multipskytile = (int32_t *)Xrealloc(multipskytile, pskynummultis * sizeof(int32_t));
|
|
|
|
|
|
|
|
psky_t * const newPsky = &multipsky[newPskyID];
|
|
|
|
Bmemset(newPsky, 0, sizeof(psky_t));
|
|
|
|
multipskytile[newPskyID] = tilenum;
|
2017-11-29 07:29:48 +00:00
|
|
|
newPsky->yscale = 65536;
|
2015-05-27 08:47:34 +00:00
|
|
|
|
|
|
|
return newPsky;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Exported Engine Functions
|
|
|
|
//
|
|
|
|
|
2012-05-20 07:25:25 +00:00
|
|
|
#if !defined _WIN32 && defined DEBUGGINGAIDS && !defined GEKKO
|
|
|
|
#ifdef GEKKO
|
|
|
|
#define __rtems__
|
|
|
|
#define _POSIX_REALTIME_SIGNALS
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
#include <signal.h>
|
2013-09-21 13:38:44 +00:00
|
|
|
static void sighandler(int sig, siginfo_t *info, void *ctx)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
const char *s;
|
2008-03-23 00:06:42 +00:00
|
|
|
UNREFERENCED_PARAMETER(ctx);
|
2007-12-12 17:42:14 +00:00
|
|
|
switch (sig)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
case SIGFPE:
|
2012-02-18 17:55:27 +00:00
|
|
|
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;
|
|
|
|
}
|
2011-07-20 23:04:20 +00:00
|
|
|
ERRprintf("Caught SIGFPE at address %p, code %s. Aborting.\n", info->si_addr, s);
|
2006-04-24 19:04:22 +00:00
|
|
|
break;
|
2006-11-13 23:12:47 +00:00
|
|
|
default:
|
2012-02-18 17:55:27 +00:00
|
|
|
break;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
abort();
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-09-23 17:54:50 +00:00
|
|
|
//
|
|
|
|
// E_FatalError
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
int32_t engineFatalError(char const * const msg)
|
2015-09-23 17:54:50 +00:00
|
|
|
{
|
|
|
|
engineerrstr = msg;
|
|
|
|
initprintf("ERROR: %s\n", engineerrstr);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2006-07-07 18:41:05 +00:00
|
|
|
//
|
|
|
|
// preinitengine
|
|
|
|
//
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t preinitcalled = 0;
|
2008-05-31 01:57:14 +00:00
|
|
|
|
2019-06-25 11:29:23 +00:00
|
|
|
#if !defined DEBUG_MAIN_ARRAYS
|
2009-01-10 07:38:50 +00:00
|
|
|
static spriteext_t spriteext_s[MAXSPRITES+MAXUNIQHUDID];
|
|
|
|
static spritesmooth_t spritesmooth_s[MAXSPRITES+MAXUNIQHUDID];
|
2011-02-25 22:49:56 +00:00
|
|
|
static sectortype sector_s[MAXSECTORS + M32_FIXME_SECTORS];
|
|
|
|
static walltype wall_s[MAXWALLS + M32_FIXME_WALLS];
|
2017-06-25 11:23:53 +00:00
|
|
|
#ifndef NEW_MAP_FORMAT
|
|
|
|
static wallext_t wallext_s[MAXWALLS];
|
|
|
|
#endif
|
2008-08-03 11:45:15 +00:00
|
|
|
static spritetype sprite_s[MAXSPRITES];
|
2019-04-18 17:25:24 +00:00
|
|
|
static tspritetype tsprite_s[MAXSPRITESONSCREEN];
|
2008-05-31 01:57:14 +00:00
|
|
|
#endif
|
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
int32_t enginePreInit(void)
|
2006-07-07 18:41:05 +00:00
|
|
|
{
|
2018-04-12 21:02:51 +00:00
|
|
|
baselayer_init();
|
2017-12-09 02:56:12 +00:00
|
|
|
initdivtables();
|
2014-06-13 09:02:37 +00:00
|
|
|
if (initsystem()) Bexit(9);
|
2007-09-06 10:43:42 +00:00
|
|
|
|
2019-06-25 11:29:23 +00:00
|
|
|
#if !defined DEBUG_MAIN_ARRAYS
|
2008-05-31 01:57:14 +00:00
|
|
|
sector = sector_s;
|
|
|
|
wall = wall_s;
|
2017-06-25 11:23:53 +00:00
|
|
|
# ifndef NEW_MAP_FORMAT
|
|
|
|
wallext = wallext_s;
|
|
|
|
# endif
|
2008-05-31 01:57:14 +00:00
|
|
|
sprite = sprite_s;
|
|
|
|
tsprite = tsprite_s;
|
|
|
|
spriteext = spriteext_s;
|
|
|
|
spritesmooth = spritesmooth_s;
|
|
|
|
#endif
|
2007-09-06 10:43:42 +00:00
|
|
|
|
2017-06-23 03:58:36 +00:00
|
|
|
#if !defined ENGINE_USING_A_C
|
|
|
|
mmxoverlay();
|
|
|
|
#endif
|
2006-07-07 18:41:05 +00:00
|
|
|
|
2006-07-24 02:47:47 +00:00
|
|
|
validmodecnt = 0;
|
2018-04-12 21:02:51 +00:00
|
|
|
videoGetModes();
|
2006-07-07 18:41:05 +00:00
|
|
|
|
2006-07-24 02:47:47 +00:00
|
|
|
initcrc32table();
|
2014-09-30 04:18:43 +00:00
|
|
|
|
Inreased debugging level for catching oob accesses to 'main' arrays.
If enabled, this makes the following arrays be allocated statically:
spriteext, spritesmooth, sector, wall, sprite, tsprite, while
necessarily disabling the clipshape feature (because it relies on
setting sector/wall to different malloc'd block temporarily).
To compile, pass DEBUGANYWAY=1 in addition to RELEASE=0 to 'make',
and it's really only useful with CC=clang, of course.
git-svn-id: https://svn.eduke32.com/eduke32@2270 1a8010ca-5511-0410-912e-c29ae57300e0
2012-01-19 23:17:34 +00:00
|
|
|
#ifdef HAVE_CLIPSHAPE_FEATURE
|
2018-04-12 21:03:47 +00:00
|
|
|
engineInitClipMaps();
|
Inreased debugging level for catching oob accesses to 'main' arrays.
If enabled, this makes the following arrays be allocated statically:
spriteext, spritesmooth, sector, wall, sprite, tsprite, while
necessarily disabling the clipshape feature (because it relies on
setting sector/wall to different malloc'd block temporarily).
To compile, pass DEBUGANYWAY=1 in addition to RELEASE=0 to 'make',
and it's really only useful with CC=clang, of course.
git-svn-id: https://svn.eduke32.com/eduke32@2270 1a8010ca-5511-0410-912e-c29ae57300e0
2012-01-19 23:17:34 +00:00
|
|
|
#endif
|
2006-07-24 02:47:47 +00:00
|
|
|
preinitcalled = 1;
|
|
|
|
return 0;
|
2006-07-07 18:41:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// initengine
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
int32_t engineInit(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t i, j;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-05-20 07:25:25 +00:00
|
|
|
#if !defined _WIN32 && defined DEBUGGINGAIDS && !defined GEKKO
|
2006-04-24 19:04:22 +00:00
|
|
|
struct sigaction sigact, oldact;
|
|
|
|
memset(&sigact, 0, sizeof(sigact));
|
2013-09-21 13:38:44 +00:00
|
|
|
sigact.sa_sigaction = &sighandler;
|
2006-04-24 19:04:22 +00:00
|
|
|
sigact.sa_flags = SA_SIGINFO;
|
|
|
|
sigaction(SIGFPE, &sigact, &oldact);
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
2007-09-06 10:43:42 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (!preinitcalled)
|
|
|
|
{
|
2018-04-12 21:03:47 +00:00
|
|
|
i = enginePreInit();
|
2006-07-24 02:47:47 +00:00
|
|
|
if (i) return i;
|
|
|
|
}
|
|
|
|
|
2011-09-15 17:05:00 +00:00
|
|
|
#ifdef YAX_DEBUG
|
2018-04-12 21:02:51 +00:00
|
|
|
u64tickspersec = (double)timerGetFreqU64();
|
2013-07-07 20:59:00 +00:00
|
|
|
if (u64tickspersec==0.0)
|
|
|
|
u64tickspersec = 1.0;
|
2011-09-15 17:05:00 +00:00
|
|
|
#endif
|
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
if (engineLoadTables())
|
2012-03-22 22:46:39 +00:00
|
|
|
return 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
xyaspect = -1;
|
|
|
|
|
2019-01-30 00:19:56 +00:00
|
|
|
rotatesprite_y_offset = 0;
|
|
|
|
rotatesprite_yxaspect = 65536;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
showinvisibility = 0;
|
|
|
|
|
2013-04-07 15:20:24 +00:00
|
|
|
for (i=1; i<1024; i++)
|
|
|
|
lowrecip[i] = ((1<<24)-1)/i;
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<MAXVOXELS; i++)
|
|
|
|
for (j=0; j<MAXVOXMIPS; j++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
voxoff[i][j] = 0L;
|
|
|
|
voxlock[i][j] = 200;
|
|
|
|
}
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<MAXTILES; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
tiletovox[i] = -1;
|
2013-04-07 15:20:24 +00:00
|
|
|
clearbuf(voxscale, sizeof(voxscale)>>2, 65536);
|
2019-09-17 05:07:28 +00:00
|
|
|
clearbufbyte(voxrotate, sizeof(voxrotate), 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
paletteloaded = 0;
|
|
|
|
|
|
|
|
searchit = 0; searchstat = -1;
|
|
|
|
|
|
|
|
totalclock = 0;
|
2012-12-14 19:28:05 +00:00
|
|
|
g_visibility = 512;
|
2006-04-13 20:47:06 +00:00
|
|
|
parallaxvisibility = 512;
|
|
|
|
|
2017-07-08 19:42:11 +00:00
|
|
|
maxspritesonscreen = MAXSPRITESONSCREEN;
|
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
paletteLoadFromDisk();
|
2012-03-22 22:46:39 +00:00
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2014-09-30 04:06:32 +00:00
|
|
|
if (!hicinitcounter) hicinit();
|
2006-04-13 20:47:06 +00:00
|
|
|
if (!mdinited) mdinit();
|
|
|
|
#endif
|
|
|
|
|
2013-05-06 19:43:34 +00:00
|
|
|
#ifdef LUNATIC
|
|
|
|
if (L_CreateState(&g_engState, "eng", NULL))
|
2018-04-12 21:03:47 +00:00
|
|
|
return engineFatalError("Failed creating engine Lua state!");
|
2013-05-06 19:43:34 +00:00
|
|
|
|
|
|
|
{
|
2016-01-27 07:30:28 +00:00
|
|
|
static char const * const luastr = "_LUNATIC_AUX=true; decl=require('ffi').cdef; require'defs_common'";
|
2013-05-06 19:43:34 +00:00
|
|
|
|
2016-01-27 07:30:23 +00:00
|
|
|
if (L_RunString(&g_engState, luastr, -1, "eng"))
|
2018-04-12 21:03:47 +00:00
|
|
|
return engineFatalError("Failed setting up engine Lua state");
|
2013-05-06 19:43:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2016-12-26 06:01:32 +00:00
|
|
|
//
|
|
|
|
// E_PostInit
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
int32_t enginePostInit(void)
|
2016-12-26 06:01:32 +00:00
|
|
|
{
|
|
|
|
if (!(paletteloaded & PALETTE_MAIN))
|
2018-04-12 21:03:47 +00:00
|
|
|
return engineFatalError("No palette found.");
|
2016-12-26 06:01:32 +00:00
|
|
|
if (!(paletteloaded & PALETTE_SHADE))
|
2018-04-12 21:03:47 +00:00
|
|
|
return engineFatalError("No shade table found.");
|
2016-12-26 06:01:32 +00:00
|
|
|
if (!(paletteloaded & PALETTE_TRANSLUC))
|
2018-04-12 21:03:47 +00:00
|
|
|
return engineFatalError("No translucency table found.");
|
2016-12-26 06:01:32 +00:00
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
palettePostLoadTables();
|
2016-12-26 06:01:32 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// uninitengine
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
void engineUnInit(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2006-04-13 20:47:06 +00:00
|
|
|
polymost_glreset();
|
|
|
|
hicinit();
|
|
|
|
freeallmodels();
|
2012-01-10 23:44:35 +00:00
|
|
|
# ifdef POLYMER
|
2009-05-22 23:49:25 +00:00
|
|
|
polymer_uninit();
|
2012-01-10 23:44:35 +00:00
|
|
|
# endif
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
2017-06-27 11:01:22 +00:00
|
|
|
|
2016-06-21 00:34:25 +00:00
|
|
|
Buninitart();
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-11-25 13:19:02 +00:00
|
|
|
DO_FREE_AND_NULL(lookups);
|
2019-08-01 06:50:26 +00:00
|
|
|
for (bssize_t i=0; i<DISTRECIPCACHESIZE; i++)
|
|
|
|
ALIGNED_FREE_AND_NULL(distrecipcache[i].distrecip);
|
|
|
|
Bmemset(distrecipcache, 0, sizeof(distrecipcache));
|
2009-04-23 09:09:41 +00:00
|
|
|
|
2015-09-23 17:54:50 +00:00
|
|
|
paletteloaded = 0;
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<MAXPALOOKUPS; i++)
|
2015-09-23 17:55:31 +00:00
|
|
|
if (i==0 || palookup[i] != palookup[0])
|
2012-03-29 21:17:35 +00:00
|
|
|
{
|
2012-11-25 13:19:02 +00:00
|
|
|
// Take care of handling aliased ^^^ cases!
|
2019-06-25 11:29:08 +00:00
|
|
|
Xaligned_free(palookup[i]);
|
2012-03-29 21:17:35 +00:00
|
|
|
}
|
2015-09-23 17:54:50 +00:00
|
|
|
Bmemset(palookup, 0, sizeof(palookup));
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<MAXBLENDTABS; i++)
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(blendtable[i]);
|
2015-09-23 17:54:50 +00:00
|
|
|
Bmemset(blendtable, 0, sizeof(blendtable));
|
2007-09-06 10:43:42 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=1; i<MAXBASEPALS; i++)
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(basepaltable[i]);
|
2015-09-23 17:55:02 +00:00
|
|
|
Bmemset(basepaltable, 0, sizeof(basepaltable));
|
|
|
|
basepaltable[0] = palette;
|
|
|
|
|
2014-09-30 04:18:43 +00:00
|
|
|
DO_FREE_AND_NULL(kpzbuf);
|
2015-05-27 08:47:03 +00:00
|
|
|
kpzbufsiz = 0;
|
2014-10-29 17:04:28 +00:00
|
|
|
|
2010-05-19 10:02:35 +00:00
|
|
|
uninitsystem();
|
2015-01-08 15:14:00 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i = 0; i < num_usermaphacks; i++)
|
2015-01-08 15:14:00 +00:00
|
|
|
{
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(usermaphacks[i].mhkfile);
|
|
|
|
Xfree(usermaphacks[i].title);
|
2015-01-08 15:14:00 +00:00
|
|
|
}
|
2015-09-23 17:55:31 +00:00
|
|
|
DO_FREE_AND_NULL(usermaphacks);
|
|
|
|
num_usermaphacks = 0;
|
2015-05-27 08:47:34 +00:00
|
|
|
|
|
|
|
DO_FREE_AND_NULL(multipsky);
|
|
|
|
DO_FREE_AND_NULL(multipskytile);
|
|
|
|
pskynummultis = 0;
|
2018-02-11 05:03:55 +00:00
|
|
|
|
|
|
|
DO_FREE_AND_NULL(g_defNamePtr);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// initspritelists
|
|
|
|
//
|
2019-09-19 20:02:45 +00:00
|
|
|
void (*initspritelists_replace)(void) = NULL;
|
2006-04-13 20:47:06 +00:00
|
|
|
void initspritelists(void)
|
|
|
|
{
|
2019-09-19 20:02:45 +00:00
|
|
|
if (initspritelists_replace)
|
|
|
|
{
|
|
|
|
initspritelists_replace();
|
|
|
|
return;
|
|
|
|
}
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t i;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-03-22 22:48:06 +00:00
|
|
|
// initial list state for statnum lists:
|
2012-03-13 20:04:56 +00:00
|
|
|
//
|
2012-03-22 22:48:06 +00:00
|
|
|
// statnum 0: nil
|
|
|
|
// statnum 1: nil
|
2012-03-13 20:04:56 +00:00
|
|
|
// . . .
|
2012-03-22 22:48:06 +00:00
|
|
|
// statnum MAXSTATUS-1: nil
|
|
|
|
// "statnum MAXSTATUS": nil <- 0 <-> 1 <-> 2 <-> ... <-> MAXSPRITES-1 -> nil
|
2012-03-13 20:04:56 +00:00
|
|
|
//
|
2012-03-22 22:48:06 +00:00
|
|
|
// That is, the dummy MAXSTATUS statnum has all sprites.
|
2012-03-13 20:04:56 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<MAXSECTORS; i++) //Init doubly-linked sprite sector lists
|
2006-04-13 20:47:06 +00:00
|
|
|
headspritesect[i] = -1;
|
|
|
|
headspritesect[MAXSECTORS] = 0;
|
2012-03-13 20:06:37 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<MAXSPRITES; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
prevspritesect[i] = i-1;
|
|
|
|
nextspritesect[i] = i+1;
|
|
|
|
sprite[i].sectnum = MAXSECTORS;
|
|
|
|
}
|
|
|
|
prevspritesect[0] = -1;
|
|
|
|
nextspritesect[MAXSPRITES-1] = -1;
|
|
|
|
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<MAXSTATUS; i++) //Init doubly-linked sprite status lists
|
2006-04-13 20:47:06 +00:00
|
|
|
headspritestat[i] = -1;
|
|
|
|
headspritestat[MAXSTATUS] = 0;
|
2012-03-13 20:06:37 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<MAXSPRITES; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
prevspritestat[i] = i-1;
|
|
|
|
nextspritestat[i] = i+1;
|
|
|
|
sprite[i].statnum = MAXSTATUS;
|
|
|
|
}
|
|
|
|
prevspritestat[0] = -1;
|
|
|
|
nextspritestat[MAXSPRITES-1] = -1;
|
2012-03-13 20:07:17 +00:00
|
|
|
|
|
|
|
tailspritefree = MAXSPRITES-1;
|
2012-03-14 22:30:24 +00:00
|
|
|
Numsprites = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-04-18 17:24:10 +00:00
|
|
|
void set_globalang(fix16_t const ang)
|
2013-02-10 16:24:11 +00:00
|
|
|
{
|
2018-03-07 04:21:18 +00:00
|
|
|
globalang = fix16_to_int(ang)&2047;
|
|
|
|
qglobalang = ang & 0x7FFFFFF;
|
|
|
|
|
|
|
|
float const f_ang = fix16_to_float(ang);
|
|
|
|
float const f_ang_radians = f_ang * M_PI * (1.f/1024.f);
|
|
|
|
|
2019-06-25 11:29:42 +00:00
|
|
|
float const fcosang = cosf(f_ang_radians) * 16384.f;
|
|
|
|
float const fsinang = sinf(f_ang_radians) * 16384.f;
|
|
|
|
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
fcosglobalang = fcosang;
|
|
|
|
fsinglobalang = fsinang;
|
2016-10-03 02:43:42 +00:00
|
|
|
#endif
|
2019-06-25 11:29:42 +00:00
|
|
|
|
|
|
|
cosglobalang = (int)fcosang;
|
|
|
|
singlobalang = (int)fsinang;
|
2018-03-07 04:21:18 +00:00
|
|
|
|
2013-02-10 16:24:11 +00:00
|
|
|
cosviewingrangeglobalang = mulscale16(cosglobalang,viewingrange);
|
|
|
|
sinviewingrangeglobalang = mulscale16(singlobalang,viewingrange);
|
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// drawrooms
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
int32_t renderDrawRoomsQ16(int32_t daposx, int32_t daposy, int32_t daposz,
|
|
|
|
fix16_t daang, fix16_t dahoriz, int16_t dacursectnum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2011-05-23 14:22:32 +00:00
|
|
|
int32_t i, j, /*cz, fz,*/ closest;
|
2009-01-09 09:29:17 +00:00
|
|
|
int16_t *shortptr1, *shortptr2;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
beforedrawrooms = 0;
|
|
|
|
|
2014-10-25 03:32:26 +00:00
|
|
|
set_globalpos(daposx, daposy, daposz);
|
2018-03-07 04:21:18 +00:00
|
|
|
set_globalang(daang);
|
2018-03-07 12:02:03 +00:00
|
|
|
|
2012-08-13 18:25:37 +00:00
|
|
|
global100horiz = dahoriz;
|
|
|
|
|
2012-03-04 20:14:48 +00:00
|
|
|
// xdimenscale is scale(xdimen,yxaspect,320);
|
|
|
|
// normalization by viewingrange so that center-of-aim doesn't depend on it
|
2018-03-07 04:21:05 +00:00
|
|
|
qglobalhoriz = mulscale16(dahoriz-F16(100), divscale16(xdimenscale, viewingrange))+fix16_from_int(ydimen>>1);
|
2019-06-25 11:29:42 +00:00
|
|
|
globalhoriz = fix16_to_int(qglobalhoriz);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
globaluclip = (0-globalhoriz)*xdimscale;
|
|
|
|
globaldclip = (ydimen-globalhoriz)*xdimscale;
|
|
|
|
|
|
|
|
i = mulscale16(xdimenscale,viewingrangerecip);
|
|
|
|
globalpisibility = mulscale16(parallaxvisibility,i);
|
2018-04-12 21:03:12 +00:00
|
|
|
switch (videoGetRenderMode())
|
2011-07-24 18:40:10 +00:00
|
|
|
{
|
|
|
|
// switch on renderers to make fog look almost the same everywhere
|
|
|
|
|
2012-12-30 20:34:34 +00:00
|
|
|
case REND_CLASSIC:
|
2012-12-14 19:28:05 +00:00
|
|
|
globalvisibility = mulscale16(g_visibility,i);
|
2011-07-24 18:40:10 +00:00
|
|
|
break;
|
|
|
|
#ifdef USE_OPENGL
|
2012-12-30 20:34:34 +00:00
|
|
|
case REND_POLYMOST:
|
2012-12-20 12:04:34 +00:00
|
|
|
// NOTE: In Polymost, the fragment depth depends on the x screen size!
|
2017-11-29 07:29:33 +00:00
|
|
|
if (r_usenewshading == 4)
|
2017-12-12 05:14:02 +00:00
|
|
|
globalvisibility = g_visibility * xdimen;
|
2017-11-29 07:29:33 +00:00
|
|
|
else if (r_usenewshading >= 2)
|
2012-12-20 12:04:34 +00:00
|
|
|
globalvisibility = scale(g_visibility<<2, xdimen, 1680);
|
|
|
|
else
|
|
|
|
globalvisibility = scale(g_visibility<<2, xdimen, 1100);
|
2019-03-19 17:08:39 +00:00
|
|
|
globalvisibility2 = mulscale16(g_visibility, i);
|
2011-07-24 18:40:10 +00:00
|
|
|
break;
|
|
|
|
# ifdef POLYMER
|
2012-12-30 20:34:34 +00:00
|
|
|
case REND_POLYMER:
|
2017-12-12 05:14:02 +00:00
|
|
|
if (r_usenewshading == 4)
|
2018-01-26 04:35:06 +00:00
|
|
|
globalvisibility = g_visibility<<5;
|
|
|
|
else if (r_usenewshading > 1)
|
|
|
|
/* 0.65127==150/230, another constant found out by experiment. :/
|
|
|
|
* (150 is Polymost's old FOGDISTCONST.) */
|
|
|
|
globalvisibility = (g_visibility<<2) * 150 / (230 * 35);
|
2017-12-12 05:14:02 +00:00
|
|
|
else
|
2018-01-26 04:35:06 +00:00
|
|
|
globalvisibility = (g_visibility<<2) / 35;
|
2011-07-24 18:40:10 +00:00
|
|
|
break;
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
globalhisibility = mulscale16(globalvisibility,xyaspect);
|
|
|
|
globalcisibility = mulscale8(globalhisibility,320);
|
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
globalhisibility2 = mulscale16(globalvisibility2,xyaspect);
|
|
|
|
globalcisibility2 = mulscale8(globalhisibility2,320);
|
|
|
|
#endif
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
globalcursectnum = dacursectnum;
|
2015-03-08 23:39:51 +00:00
|
|
|
totalclocklock = totalclock;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((xyaspect != oxyaspect) || (xdimen != oxdimen) || (viewingrange != oviewingrange))
|
|
|
|
dosetaspect();
|
|
|
|
|
2019-09-03 04:09:20 +00:00
|
|
|
Bmemset(gotsector, 0, sizeof(gotsector));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() != REND_CLASSIC
|
2011-09-15 17:02:52 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
|| yax_globallev==YAX_MAXDRAWS
|
|
|
|
#endif
|
|
|
|
)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
shortptr1 = (int16_t *)&startumost[windowxy1.x];
|
|
|
|
shortptr2 = (int16_t *)&startdmost[windowxy1.x];
|
2011-09-15 17:02:52 +00:00
|
|
|
i = xdimen-1;
|
|
|
|
do
|
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
umost[i] = shortptr1[i]-windowxy1.y;
|
|
|
|
dmost[i] = shortptr2[i]-windowxy1.y;
|
2011-09-15 17:02:52 +00:00
|
|
|
}
|
2012-03-31 11:22:19 +00:00
|
|
|
while (i--); // xdimen == 1 is OK!
|
2016-06-21 00:34:18 +00:00
|
|
|
umost[0] = shortptr1[0]-windowxy1.y;
|
|
|
|
dmost[0] = shortptr2[0]-windowxy1.y;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2006-04-23 06:44:19 +00:00
|
|
|
|
2019-06-26 13:20:03 +00:00
|
|
|
for (int i = 0; i < numwalls; ++i)
|
2018-11-18 18:13:48 +00:00
|
|
|
{
|
2019-06-26 13:20:03 +00:00
|
|
|
if (wall[i].cstat & CSTAT_WALL_ROTATE_90)
|
2018-11-18 18:13:48 +00:00
|
|
|
{
|
2019-06-26 13:20:03 +00:00
|
|
|
auto &w = wall[i];
|
|
|
|
auto &tile = rottile[w.picnum+animateoffs(w.picnum,16384)];
|
2019-09-19 21:02:57 +00:00
|
|
|
|
2019-06-26 13:20:03 +00:00
|
|
|
if (tile.newtile == -1 && tile.owner == -1)
|
|
|
|
{
|
|
|
|
tile.newtile = findUnusedTile();
|
|
|
|
Bassert(tile.newtile != -1);
|
2018-11-18 18:13:48 +00:00
|
|
|
|
2019-06-26 13:20:03 +00:00
|
|
|
rottile[tile.newtile].owner = w.picnum+animateoffs(w.picnum,16384);
|
2018-11-18 18:13:48 +00:00
|
|
|
|
2019-06-26 13:20:03 +00:00
|
|
|
auto &siz = tilesiz[w.picnum+animateoffs(w.picnum,16384)];
|
|
|
|
tileSetSize(tile.newtile, siz.x, siz.y);
|
2018-11-18 18:13:48 +00:00
|
|
|
|
2019-06-26 13:20:03 +00:00
|
|
|
tileLoad(tile.newtile);
|
|
|
|
// Bassert(waloff[tile.newtile]);
|
2018-11-18 18:13:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-22 12:43:02 +00:00
|
|
|
// Update starting sector number (common to classic and Polymost).
|
2015-08-01 08:41:14 +00:00
|
|
|
// ADJUST_GLOBALCURSECTNUM.
|
2015-02-22 12:43:02 +00:00
|
|
|
if (globalcursectnum >= MAXSECTORS)
|
|
|
|
globalcursectnum -= MAXSECTORS;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
i = globalcursectnum;
|
2019-04-06 06:38:10 +00:00
|
|
|
updatesector(globalposx,globalposy,&globalcursectnum);
|
2015-02-22 12:43:02 +00:00
|
|
|
if (globalcursectnum < 0) globalcursectnum = i;
|
|
|
|
|
|
|
|
// PK 20110123: I'm not sure what the line above is supposed to do, but 'i'
|
|
|
|
// *can* be negative, so let's just quit here in that case...
|
|
|
|
if (globalcursectnum<0)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-10-29 16:59:21 +00:00
|
|
|
#ifdef USE_OPENGL
|
2006-04-13 20:47:06 +00:00
|
|
|
//============================================================================= //POLYMOST BEGINS
|
2007-01-06 01:29:45 +00:00
|
|
|
polymost_drawrooms();
|
2013-05-17 03:44:09 +00:00
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() != REND_CLASSIC)
|
2019-06-25 18:35:05 +00:00
|
|
|
return inpreparemirror;
|
2006-04-13 20:47:06 +00:00
|
|
|
//============================================================================= //POLYMOST ENDS
|
2011-09-15 17:02:52 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2011-05-12 23:31:13 +00:00
|
|
|
#ifdef ENGINE_CLEAR_SCREEN
|
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (!g_nodraw)
|
|
|
|
#endif
|
|
|
|
if (numyaxbunches==0)
|
2012-03-22 22:46:23 +00:00
|
|
|
draw_rainbow_background();
|
2011-05-12 23:31:13 +00:00
|
|
|
#endif
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
frameoffset = frameplace + windowxy1.y*bytesperline + windowxy1.x;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//if (smostwallcnt < 0)
|
|
|
|
// if (getkensmessagecrc(FP_OFF(kensmessage)) != 0x56c764d4)
|
2014-06-13 09:02:37 +00:00
|
|
|
// { /* setvmode(0x3);*/ OSD_Printf("Nice try.\n"); Bexit(0); }
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
numhits = xdimen; numscans = 0; numbunches = 0;
|
|
|
|
maskwallcnt = 0; smostwallcnt = 0; smostcnt = 0; spritesortcnt = 0;
|
|
|
|
|
2011-05-15 22:37:24 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (yax_globallev != YAX_MAXDRAWS)
|
|
|
|
{
|
|
|
|
j = yax_globalbunch*xdimen;
|
|
|
|
|
|
|
|
Bmemcpy(umost, yumost+j, xdimen*sizeof(int16_t));
|
|
|
|
Bmemcpy(dmost, ydmost+j, xdimen*sizeof(int16_t));
|
|
|
|
|
|
|
|
for (i=0; i<xdimen; i++)
|
|
|
|
if (umost[i] > dmost[i])
|
|
|
|
numhits--;
|
|
|
|
|
|
|
|
// yaxdebug("cf %d, tlev %d, bunch %d: numhits=%d", yax_globalcf, yax_globallev, yax_globalbunch, numhits);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-05-23 14:22:32 +00:00
|
|
|
/*
|
2006-04-13 20:47:06 +00:00
|
|
|
globparaceilclip = 1;
|
|
|
|
globparaflorclip = 1;
|
|
|
|
getzsofslope(globalcursectnum,globalposx,globalposy,&cz,&fz);
|
|
|
|
if (globalposz < cz) globparaceilclip = 0;
|
|
|
|
if (globalposz > fz) globparaflorclip = 0;
|
2011-05-23 14:22:32 +00:00
|
|
|
*/
|
2018-04-12 21:04:00 +00:00
|
|
|
classicScanSector(globalcursectnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (inpreparemirror)
|
|
|
|
{
|
2012-03-08 19:15:03 +00:00
|
|
|
// INPREPAREMIRROR_NO_BUNCHES
|
2011-04-25 19:50:08 +00:00
|
|
|
// numbunches==0 can happen if the mirror is far away... the game code decides
|
|
|
|
// to draw it, but scansector gets zero bunches. Result: big screwup!
|
2019-06-25 18:35:05 +00:00
|
|
|
// Set inpreparemirror to 0 to indicate that we were unable to render the mirror
|
2011-04-25 19:50:08 +00:00
|
|
|
if (numbunches==0)
|
2011-04-28 21:28:33 +00:00
|
|
|
{
|
2019-06-25 18:35:05 +00:00
|
|
|
inpreparemirror = 0;
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //!!!
|
2012-07-06 15:36:46 +00:00
|
|
|
return 0;
|
2011-04-28 21:28:33 +00:00
|
|
|
}
|
2011-04-25 19:50:08 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
mirrorsx1 = xdimen-1; mirrorsx2 = 0;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=numscans-1; i>=0; i--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-05-04 16:36:12 +00:00
|
|
|
if (wall[thewall[i]].nextsector >= 0)
|
|
|
|
{
|
|
|
|
if (xb1[i] < mirrorsx1) mirrorsx1 = xb1[i];
|
|
|
|
if (xb2[i] > mirrorsx2) mirrorsx2 = xb2[i];
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<mirrorsx1; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (umost[i] <= dmost[i])
|
2007-12-12 17:42:14 +00:00
|
|
|
{ umost[i] = 1; dmost[i] = 0; numhits--; }
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=mirrorsx2+1; i<xdimen; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (umost[i] <= dmost[i])
|
2007-12-12 17:42:14 +00:00
|
|
|
{ umost[i] = 1; dmost[i] = 0; numhits--; }
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:04:00 +00:00
|
|
|
classicDrawBunches(0L);
|
2006-04-13 20:47:06 +00:00
|
|
|
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))
|
|
|
|
{
|
2011-09-15 17:03:50 +00:00
|
|
|
Bmemset(tempbuf, 0, numbunches);
|
2006-04-13 20:47:06 +00:00
|
|
|
tempbuf[0] = 1;
|
|
|
|
|
|
|
|
closest = 0; //Almost works, but not quite :(
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=1; i<numbunches; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
if ((j = bunchfront(i,closest)) < 0) continue;
|
|
|
|
tempbuf[i] = 1;
|
|
|
|
if (j == 0) tempbuf[closest] = 1, closest = i;
|
|
|
|
}
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<numbunches; i++) //Double-check
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
if (tempbuf[i]) continue;
|
|
|
|
if ((j = bunchfront(i,closest)) < 0) continue;
|
|
|
|
tempbuf[i] = 1;
|
|
|
|
if (j == 0) tempbuf[closest] = 1, closest = i, i = 0;
|
|
|
|
}
|
|
|
|
|
2018-04-12 21:04:00 +00:00
|
|
|
classicDrawBunches(closest);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-08-01 06:50:56 +00:00
|
|
|
if (automapping)
|
|
|
|
{
|
|
|
|
for (int z=bunchfirst[closest]; z>=0; z=bunchp2[z])
|
|
|
|
show2dwall[thewall[z]>>3] |= pow2char[thewall[z]&7];
|
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
numbunches--;
|
|
|
|
bunchfirst[closest] = bunchfirst[numbunches];
|
|
|
|
bunchlast[closest] = bunchlast[numbunches];
|
|
|
|
}
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2012-07-06 15:36:46 +00:00
|
|
|
|
2019-06-25 18:35:05 +00:00
|
|
|
return inpreparemirror;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2006-08-29 01:58:59 +00:00
|
|
|
// UTILITY TYPES AND FUNCTIONS FOR DRAWMASKS OCCLUSION TREE
|
2009-03-03 14:01:14 +00:00
|
|
|
// typedef struct s_maskleaf
|
|
|
|
// {
|
|
|
|
// int32_t index;
|
|
|
|
// _point2d p1, p2;
|
|
|
|
// _equation maskeq, p1eq, p2eq;
|
|
|
|
// struct s_maskleaf* branch[MAXWALLSB];
|
|
|
|
// int32_t drawing;
|
|
|
|
// } _maskleaf;
|
2009-06-24 08:20:10 +00:00
|
|
|
//
|
2009-03-03 14:01:14 +00:00
|
|
|
// _maskleaf maskleaves[MAXWALLSB];
|
2006-08-29 01:58:59 +00:00
|
|
|
|
|
|
|
// returns equation of a line given two points
|
2019-04-18 17:24:10 +00:00
|
|
|
static inline _equation equation(float const x1, float const y1, float const x2, float const y2)
|
2006-08-29 01:58:59 +00:00
|
|
|
{
|
2014-10-25 03:30:38 +00:00
|
|
|
const float f = x2-x1;
|
2006-08-29 01:58:59 +00:00
|
|
|
|
2014-10-25 03:30:38 +00:00
|
|
|
// vertical
|
|
|
|
if (f == 0.f)
|
2019-04-18 17:24:34 +00:00
|
|
|
return { 1, 0, -x1 };
|
|
|
|
else
|
2006-08-29 01:58:59 +00:00
|
|
|
{
|
2019-04-18 17:24:34 +00:00
|
|
|
float const ff = (y2 - y1) / f;
|
|
|
|
return { ff, -1, (y1 - (ff * x1)) };
|
2006-08-29 01:58:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-18 17:24:10 +00:00
|
|
|
int32_t wallvisible(int32_t const x, int32_t const y, int16_t const wallnum)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
|
|
|
// 1 if wall is in front of player 0 otherwise
|
2019-04-18 17:25:24 +00:00
|
|
|
auto w1 = (uwallptr_t)&wall[wallnum];
|
|
|
|
auto w2 = (uwallptr_t)&wall[w1->point2];
|
2007-07-01 06:32:03 +00:00
|
|
|
|
2019-04-18 17:24:10 +00:00
|
|
|
int32_t const a1 = getangle(w1->x - x, w1->y - y);
|
|
|
|
int32_t const a2 = getangle(w2->x - x, w2->y - y);
|
2007-07-01 06:32:03 +00:00
|
|
|
|
2016-06-21 00:33:39 +00:00
|
|
|
return (((a2 + (2048 - a1)) & 2047) <= 1024);
|
2007-07-01 06:32:03 +00:00
|
|
|
}
|
2011-05-02 16:58:11 +00:00
|
|
|
|
|
|
|
#if 0
|
2006-08-31 01:56:43 +00:00
|
|
|
// returns the intersection point between two lines
|
2006-08-29 01:58:59 +00:00
|
|
|
_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);
|
|
|
|
|
2016-06-21 00:34:41 +00:00
|
|
|
return ret;
|
2006-08-29 01:58:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// check if a point that's on the line is within the segment boundaries
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t pointonmask(_point2d point, _maskleaf* wall)
|
2006-08-29 01:58:59 +00:00
|
|
|
{
|
|
|
|
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)))
|
2016-06-21 00:34:41 +00:00
|
|
|
return 1;
|
|
|
|
return 0;
|
2006-08-29 01:58:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// returns 1 if wall2 is hidden by wall1
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t wallobstructswall(_maskleaf* wall1, _maskleaf* wall2)
|
2006-08-29 01:58:59 +00:00
|
|
|
{
|
|
|
|
_point2d cross;
|
|
|
|
|
|
|
|
cross = intersection(wall2->p1eq, wall1->maskeq);
|
|
|
|
if (pointonmask(cross, wall1))
|
2016-06-21 00:34:41 +00:00
|
|
|
return 1;
|
2006-08-29 01:58:59 +00:00
|
|
|
|
|
|
|
cross = intersection(wall2->p2eq, wall1->maskeq);
|
|
|
|
if (pointonmask(cross, wall1))
|
2016-06-21 00:34:41 +00:00
|
|
|
return 1;
|
2006-08-29 01:58:59 +00:00
|
|
|
|
|
|
|
cross = intersection(wall1->p1eq, wall2->maskeq);
|
|
|
|
if (pointonmask(cross, wall2))
|
2016-06-21 00:34:41 +00:00
|
|
|
return 1;
|
2006-08-29 01:58:59 +00:00
|
|
|
|
|
|
|
cross = intersection(wall1->p2eq, wall2->maskeq);
|
|
|
|
if (pointonmask(cross, wall2))
|
2016-06-21 00:34:41 +00:00
|
|
|
return 1;
|
2006-08-29 01:58:59 +00:00
|
|
|
|
2016-06-21 00:34:41 +00:00
|
|
|
return 0;
|
2006-08-29 01:58:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// recursive mask drawing function
|
2009-02-19 09:39:19 +00:00
|
|
|
static inline void drawmaskleaf(_maskleaf* wall)
|
2006-08-29 01:58:59 +00:00
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t i;
|
2006-08-29 01:58:59 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2011-05-02 16:58:11 +00:00
|
|
|
#endif
|
2006-08-29 01:58:59 +00:00
|
|
|
|
2014-10-25 03:30:38 +00:00
|
|
|
static inline int32_t sameside(const _equation *eq, const vec2f_t *p1, const vec2f_t *p2)
|
2006-08-29 01:58:59 +00:00
|
|
|
{
|
2014-10-25 03:30:38 +00:00
|
|
|
const float sign1 = (eq->a * p1->x) + (eq->b * p1->y) + eq->c;
|
|
|
|
const float sign2 = (eq->a * p2->x) + (eq->b * p2->y) + eq->c;
|
|
|
|
return (sign1 * sign2) > 0.f;
|
2006-08-29 01:58:59 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-01-24 21:39:02 +00:00
|
|
|
// x1, y1: in/out
|
|
|
|
// rest x/y: out
|
2018-10-16 06:09:09 +00:00
|
|
|
|
|
|
|
|
2014-01-24 21:39:02 +00:00
|
|
|
|
2014-01-19 20:17:14 +00:00
|
|
|
#ifdef DEBUG_MASK_DRAWING
|
|
|
|
int32_t g_maskDrawMode = 0;
|
|
|
|
#endif
|
2006-12-31 06:32:04 +00:00
|
|
|
|
2019-09-25 20:57:14 +00:00
|
|
|
static inline int comparetsprites(int const k, int const l)
|
|
|
|
{
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
|
|
|
{
|
|
|
|
if ((tspriteptr[k]->cstat & 48) != (tspriteptr[l]->cstat & 48))
|
|
|
|
return (tspriteptr[k]->cstat & 48) - (tspriteptr[l]->cstat & 48);
|
|
|
|
|
|
|
|
if ((tspriteptr[k]->cstat & 48) == 16 && tspriteptr[k]->ang != tspriteptr[l]->ang)
|
|
|
|
return tspriteptr[k]->ang - tspriteptr[l]->ang;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (tspriteptr[k]->statnum != tspriteptr[l]->statnum)
|
|
|
|
return tspriteptr[k]->statnum - tspriteptr[l]->statnum;
|
|
|
|
|
|
|
|
if (tspriteptr[k]->x == tspriteptr[l]->x &&
|
|
|
|
tspriteptr[k]->y == tspriteptr[l]->y &&
|
|
|
|
tspriteptr[k]->z == tspriteptr[l]->z &&
|
|
|
|
(tspriteptr[k]->cstat & 48) == (tspriteptr[l]->cstat & 48) &&
|
|
|
|
tspriteptr[k]->owner != tspriteptr[l]->owner)
|
|
|
|
return tspriteptr[k]->owner - tspriteptr[l]->owner;
|
|
|
|
|
|
|
|
if (klabs(spritesxyz[k].z-globalposz) != klabs(spritesxyz[l].z-globalposz))
|
|
|
|
return klabs(spritesxyz[k].z-globalposz)-klabs(spritesxyz[l].z-globalposz);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-25 20:33:22 +00:00
|
|
|
static void sortsprites(int const start, int const end)
|
|
|
|
{
|
|
|
|
int32_t i, gap, y, ys;
|
|
|
|
|
|
|
|
if (start >= end)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gap = 1; while (gap < end - start) gap = (gap<<1)+1;
|
|
|
|
for (gap>>=1; gap>0; gap>>=1) //Sort sprite list
|
|
|
|
for (i=start; i<end-gap; i++)
|
|
|
|
for (bssize_t l=i; l>=start; l-=gap)
|
|
|
|
{
|
|
|
|
if (spritesxyz[l].y <= spritesxyz[l+gap].y) break;
|
|
|
|
swapptr(&tspriteptr[l],&tspriteptr[l+gap]);
|
|
|
|
swaplong(&spritesxyz[l].x,&spritesxyz[l+gap].x);
|
|
|
|
swaplong(&spritesxyz[l].y,&spritesxyz[l+gap].y);
|
|
|
|
}
|
|
|
|
|
|
|
|
ys = spritesxyz[start].y; i = start;
|
|
|
|
for (bssize_t j=start+1; j<=end; j++)
|
|
|
|
{
|
|
|
|
if (j < end)
|
|
|
|
{
|
|
|
|
y = spritesxyz[j].y;
|
|
|
|
if (y == ys)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ys = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j > i+1)
|
|
|
|
{
|
|
|
|
for (bssize_t k=i; k<j; k++)
|
|
|
|
{
|
|
|
|
auto const s = tspriteptr[k];
|
|
|
|
|
|
|
|
spritesxyz[k].z = s->z;
|
|
|
|
if ((s->cstat&48) != 32)
|
|
|
|
{
|
|
|
|
int32_t yoff = picanm[s->picnum].yofs + s->yoffset;
|
|
|
|
int32_t yspan = (tilesiz[s->picnum].y*s->yrepeat<<2);
|
|
|
|
|
|
|
|
spritesxyz[k].z -= (yoff*s->yrepeat)<<2;
|
|
|
|
|
|
|
|
if (!(s->cstat&128))
|
|
|
|
spritesxyz[k].z -= (yspan>>1);
|
|
|
|
if (klabs(spritesxyz[k].z-globalposz) < (yspan>>1))
|
|
|
|
spritesxyz[k].z = globalposz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (bssize_t k=i+1; k<j; k++)
|
|
|
|
for (bssize_t l=i; l<k; l++)
|
2019-09-25 20:57:14 +00:00
|
|
|
if (comparetsprites(k, l) < 0)
|
2019-09-25 20:33:22 +00:00
|
|
|
{
|
|
|
|
swapptr(&tspriteptr[k],&tspriteptr[l]);
|
|
|
|
vec3_t tv3 = spritesxyz[k];
|
|
|
|
spritesxyz[k] = spritesxyz[l];
|
|
|
|
spritesxyz[l] = tv3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
i = j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// drawmasks
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
void renderDrawMasks(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-01-19 20:17:14 +00:00
|
|
|
#ifdef DEBUG_MASK_DRAWING
|
|
|
|
static struct {
|
|
|
|
int16_t di; // &32768: &32767 is tspriteptr[], else thewall[] index
|
|
|
|
int16_t i; // sprite[] or wall[] index
|
|
|
|
} debugmask[MAXWALLSB + MAXSPRITESONSCREEN + 1];
|
|
|
|
|
|
|
|
int32_t dmasknum = 0;
|
|
|
|
|
|
|
|
# define debugmask_add(dispidx, idx) do { \
|
2018-04-12 21:03:12 +00:00
|
|
|
if (g_maskDrawMode && videoGetRenderMode()==REND_CLASSIC) { \
|
2014-01-19 20:17:14 +00:00
|
|
|
debugmask[dmasknum].di = dispidx; \
|
|
|
|
debugmask[dmasknum++].i = idx; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
#else
|
|
|
|
# define debugmask_add(dispidx, idx) do {} while (0)
|
|
|
|
#endif
|
2019-04-19 21:45:22 +00:00
|
|
|
int32_t i = spritesortcnt-1;
|
|
|
|
int32_t numSprites = spritesortcnt;
|
2012-11-25 13:19:02 +00:00
|
|
|
|
2019-09-08 01:01:22 +00:00
|
|
|
#ifdef USE_OPENGL
|
2019-04-19 21:45:22 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
|
|
|
{
|
|
|
|
spritesortcnt = 0;
|
|
|
|
int32_t back = i;
|
|
|
|
for (; i >= 0; --i)
|
|
|
|
{
|
|
|
|
if (polymost_spriteHasTranslucency(&tsprite[i]))
|
|
|
|
{
|
|
|
|
tspriteptr[spritesortcnt] = &tsprite[i];
|
|
|
|
++spritesortcnt;
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
tspriteptr[back] = &tsprite[i];
|
|
|
|
--back;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else
|
2019-09-08 01:01:22 +00:00
|
|
|
#endif
|
2019-04-19 21:45:22 +00:00
|
|
|
{
|
|
|
|
for (; i >= 0; --i)
|
|
|
|
{
|
|
|
|
tspriteptr[i] = &tsprite[i];
|
|
|
|
}
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-09-25 20:33:22 +00:00
|
|
|
for (i=numSprites-1; i>=0; --i)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2012-11-25 13:19:02 +00:00
|
|
|
const int32_t xs = tspriteptr[i]->x-globalposx, ys = tspriteptr[i]->y-globalposy;
|
|
|
|
const int32_t yp = dmulscale6(xs,cosviewingrangeglobalang,ys,sinviewingrangeglobalang);
|
2011-05-22 21:52:22 +00:00
|
|
|
#ifdef USE_OPENGL
|
2014-01-24 21:39:02 +00:00
|
|
|
const int32_t modelp = (usemodels && tile2model[tspriteptr[i]->picnum].modelid >= 0);
|
2011-05-22 21:52:22 +00:00
|
|
|
#endif
|
2014-09-30 04:06:32 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (yp > (4<<8))
|
|
|
|
{
|
2012-11-25 13:19:02 +00:00
|
|
|
const int32_t xp = dmulscale6(ys,cosglobalang,-xs,singlobalang);
|
|
|
|
|
|
|
|
if (mulscale24(labs(xp+yp),xdimen) >= yp)
|
|
|
|
goto killsprite;
|
|
|
|
|
2014-10-29 17:04:43 +00:00
|
|
|
spritesxyz[i].x = scale(xp+yp,xdimen<<7,yp);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
else if ((tspriteptr[i]->cstat&48) == 0)
|
|
|
|
{
|
2011-05-07 18:23:34 +00:00
|
|
|
killsprite:
|
2014-01-30 16:13:53 +00:00
|
|
|
#ifdef USE_OPENGL
|
2011-05-22 21:52:22 +00:00
|
|
|
if (!modelp)
|
2014-01-30 16:13:53 +00:00
|
|
|
#endif
|
2011-05-22 21:52:22 +00:00
|
|
|
{
|
2019-04-19 21:45:22 +00:00
|
|
|
//Delete face sprite if on wrong side!
|
2019-09-25 20:33:22 +00:00
|
|
|
if (i >= spritesortcnt)
|
|
|
|
{
|
|
|
|
--numSprites;
|
|
|
|
if (i != numSprites)
|
|
|
|
{
|
|
|
|
tspriteptr[i] = tspriteptr[numSprites];
|
|
|
|
spritesxyz[i].x = spritesxyz[numSprites].x;
|
|
|
|
spritesxyz[i].y = spritesxyz[numSprites].y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2012-11-25 13:19:02 +00:00
|
|
|
{
|
2019-09-25 20:33:22 +00:00
|
|
|
--numSprites;
|
|
|
|
--spritesortcnt;
|
|
|
|
if (i != numSprites)
|
|
|
|
{
|
|
|
|
tspriteptr[i] = tspriteptr[spritesortcnt];
|
|
|
|
spritesxyz[i].x = spritesxyz[spritesortcnt].x;
|
|
|
|
spritesxyz[i].y = spritesxyz[spritesortcnt].y;
|
|
|
|
tspriteptr[spritesortcnt] = tspriteptr[numSprites];
|
|
|
|
spritesxyz[spritesortcnt].x = spritesxyz[numSprites].x;
|
|
|
|
spritesxyz[spritesortcnt].y = spritesxyz[numSprites].y;
|
|
|
|
}
|
2012-11-25 13:19:02 +00:00
|
|
|
}
|
2011-05-22 21:52:22 +00:00
|
|
|
continue;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2014-10-29 17:04:43 +00:00
|
|
|
spritesxyz[i].y = yp;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-09-25 20:33:22 +00:00
|
|
|
sortsprites(0, spritesortcnt);
|
|
|
|
sortsprites(spritesortcnt, numSprites);
|
2013-04-21 19:55:38 +00:00
|
|
|
|
2019-09-25 20:33:22 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-09-25 20:33:22 +00:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
2015-10-21 19:54:14 +00:00
|
|
|
{
|
2019-10-04 16:12:03 +00:00
|
|
|
GLInterface.EnableBlend(false);
|
|
|
|
GLInterface.EnableAlphaTest(true);
|
2019-09-25 20:33:22 +00:00
|
|
|
polymost_setClamp(1+2);
|
2012-11-25 13:19:02 +00:00
|
|
|
|
2019-09-25 20:33:22 +00:00
|
|
|
if (spritesortcnt < numSprites)
|
2015-10-21 19:54:14 +00:00
|
|
|
{
|
2019-09-25 20:33:22 +00:00
|
|
|
int32_t py = spritesxyz[spritesortcnt].y;
|
|
|
|
int32_t pcstat = tspriteptr[spritesortcnt]->cstat & 48;
|
|
|
|
int32_t pangle = tspriteptr[spritesortcnt]->ang;
|
|
|
|
i = spritesortcnt;
|
|
|
|
for (bssize_t j = spritesortcnt + 1; j <= numSprites; j++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-09-25 20:33:22 +00:00
|
|
|
if (j < numSprites)
|
2015-10-21 19:54:14 +00:00
|
|
|
{
|
2019-09-25 20:33:22 +00:00
|
|
|
if (py == spritesxyz[j].y && pcstat == (tspriteptr[j]->cstat & 48) && (pcstat != 16 || pangle == tspriteptr[j]->ang))
|
|
|
|
continue;
|
|
|
|
py = spritesxyz[j].y;
|
|
|
|
pcstat = (tspriteptr[j]->cstat & 48);
|
|
|
|
pangle = tspriteptr[j]->ang;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2019-09-25 20:33:22 +00:00
|
|
|
if (j - i == 1)
|
|
|
|
{
|
|
|
|
debugmask_add(i | 32768, tspriteptr[i]->owner);
|
|
|
|
renderDrawSprite(i);
|
|
|
|
tspriteptr[i] = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-10-04 17:17:55 +00:00
|
|
|
GLInterface.SetDepthMask(false);
|
2014-10-29 17:04:43 +00:00
|
|
|
|
2019-09-25 20:33:22 +00:00
|
|
|
for (bssize_t k = j-1; k >= i; k--)
|
2015-10-21 19:54:14 +00:00
|
|
|
{
|
2019-09-25 20:33:22 +00:00
|
|
|
debugmask_add(k | 32768, tspriteptr[k]->owner);
|
|
|
|
renderDrawSprite(k);
|
2015-10-21 19:54:14 +00:00
|
|
|
}
|
2015-10-20 07:15:25 +00:00
|
|
|
|
2019-10-04 17:17:55 +00:00
|
|
|
GLInterface.SetDepthMask(true);
|
2019-09-25 20:33:22 +00:00
|
|
|
|
2019-10-04 17:17:55 +00:00
|
|
|
GLInterface.SetColorMask(false);
|
2019-09-25 20:33:22 +00:00
|
|
|
|
|
|
|
for (bssize_t k = j-1; k >= i; k--)
|
2015-10-21 19:54:14 +00:00
|
|
|
{
|
2019-09-25 20:33:22 +00:00
|
|
|
renderDrawSprite(k);
|
|
|
|
tspriteptr[k] = NULL;
|
2015-10-21 19:54:14 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-10-04 17:17:55 +00:00
|
|
|
GLInterface.SetColorMask(true);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-09-25 20:33:22 +00:00
|
|
|
}
|
|
|
|
i = j;
|
2019-04-19 21:45:22 +00:00
|
|
|
}
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-09-03 04:09:25 +00:00
|
|
|
polymost_setClamp(0);
|
2019-07-13 21:26:10 +00:00
|
|
|
int32_t numMaskWalls = maskwallcnt;
|
|
|
|
maskwallcnt = 0;
|
|
|
|
for (i = 0; i < numMaskWalls; i++)
|
2012-11-25 13:19:02 +00:00
|
|
|
{
|
2019-07-13 21:26:10 +00:00
|
|
|
if (polymost_maskWallHasTranslucency((uwalltype *) &wall[thewall[maskwall[i]]]))
|
2019-04-19 21:45:22 +00:00
|
|
|
{
|
2019-07-13 21:26:10 +00:00
|
|
|
maskwall[maskwallcnt] = maskwall[i];
|
|
|
|
maskwallcnt++;
|
2019-04-19 21:45:22 +00:00
|
|
|
}
|
|
|
|
else
|
2019-07-13 21:26:10 +00:00
|
|
|
renderDrawMaskedWall(i);
|
2012-11-25 13:19:02 +00:00
|
|
|
}
|
2019-04-30 11:12:16 +00:00
|
|
|
|
2019-10-04 16:12:03 +00:00
|
|
|
GLInterface.EnableBlend(true);
|
|
|
|
GLInterface.EnableAlphaTest(true);
|
2019-10-04 17:17:55 +00:00
|
|
|
GLInterface.SetDepthMask(false);
|
|
|
|
}
|
2019-04-19 21:45:22 +00:00
|
|
|
#endif
|
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
vec2f_t pos;
|
2006-08-29 01:58:59 +00:00
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
pos.x = fglobalposx;
|
|
|
|
pos.y = fglobalposy;
|
|
|
|
|
|
|
|
// CAUTION: maskwallcnt and spritesortcnt may be zero!
|
|
|
|
// Writing e.g. "while (maskwallcnt--)" is wrong!
|
|
|
|
while (maskwallcnt)
|
|
|
|
{
|
|
|
|
// PLAG: sorting stuff
|
2018-04-12 21:03:12 +00:00
|
|
|
const int32_t w = (videoGetRenderMode()==REND_POLYMER) ?
|
2015-10-21 19:54:14 +00:00
|
|
|
maskwall[maskwallcnt-1] : thewall[maskwall[maskwallcnt-1]];
|
2013-04-21 19:55:38 +00:00
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
maskwallcnt--;
|
2013-04-22 10:35:48 +00:00
|
|
|
|
2017-06-09 06:41:23 +00:00
|
|
|
vec2f_t dot = { (float)wall[w].x, (float)wall[w].y };
|
|
|
|
vec2f_t dot2 = { (float)wall[wall[w].point2].x, (float)wall[wall[w].point2].y };
|
|
|
|
vec2f_t middle = { (dot.x + dot2.x) * .5f, (dot.y + dot2.y) * .5f };
|
2006-08-29 01:58:59 +00:00
|
|
|
|
2017-06-09 06:41:23 +00:00
|
|
|
_equation maskeq = equation(dot.x, dot.y, dot2.x, dot2.y);
|
|
|
|
_equation p1eq = equation(pos.x, pos.y, dot.x, dot.y);
|
|
|
|
_equation p2eq = equation(pos.x, pos.y, dot2.x, dot2.y);
|
2006-08-29 01:58:59 +00:00
|
|
|
|
2019-07-12 08:44:40 +00:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
2019-09-03 04:09:25 +00:00
|
|
|
polymost_setClamp(1+2);
|
2019-07-12 08:44:40 +00:00
|
|
|
#endif
|
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
i = spritesortcnt;
|
|
|
|
while (i)
|
|
|
|
{
|
|
|
|
i--;
|
2019-04-19 21:45:22 +00:00
|
|
|
if (tspriteptr[i] != NULL)
|
2006-08-29 01:58:59 +00:00
|
|
|
{
|
2015-10-21 19:54:14 +00:00
|
|
|
vec2f_t spr;
|
2019-04-18 17:24:10 +00:00
|
|
|
auto const tspr = tspriteptr[i];
|
2012-11-25 13:19:02 +00:00
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
spr.x = (float)tspr->x;
|
|
|
|
spr.y = (float)tspr->y;
|
2007-12-12 17:42:14 +00:00
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
if (!sameside(&maskeq, &spr, &pos))
|
|
|
|
{
|
|
|
|
// Sprite and camera are on different sides of the
|
|
|
|
// masked wall.
|
2014-01-24 21:39:02 +00:00
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
// Check if the sprite is inside the 'cone' given by
|
|
|
|
// the rays from the camera to the two wall-points.
|
|
|
|
const int32_t inleft = sameside(&p1eq, &middle, &spr);
|
|
|
|
const int32_t inright = sameside(&p2eq, &middle, &spr);
|
2014-01-24 21:39:02 +00:00
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
int32_t ok = (inleft && inright);
|
2014-01-24 21:39:02 +00:00
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
if (!ok)
|
|
|
|
{
|
|
|
|
// If not, check if any of the border points are...
|
|
|
|
int32_t xx[4] = { tspr->x };
|
|
|
|
int32_t yy[4] = { tspr->y };
|
|
|
|
int32_t numpts, jj;
|
2014-01-24 21:39:02 +00:00
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
const _equation pineq = inleft ? p1eq : p2eq;
|
2014-01-24 21:39:02 +00:00
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
if ((tspr->cstat & 48) == 32)
|
|
|
|
{
|
|
|
|
numpts = 4;
|
|
|
|
get_floorspr_points(tspr, 0, 0,
|
|
|
|
&xx[0], &xx[1], &xx[2], &xx[3],
|
|
|
|
&yy[0], &yy[1], &yy[2], &yy[3]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const int32_t oang = tspr->ang;
|
|
|
|
numpts = 2;
|
2014-01-24 21:39:02 +00:00
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
// Consider face sprites as wall sprites with camera ang.
|
|
|
|
// XXX: factor 4/5 needed?
|
|
|
|
if ((tspr->cstat & 48) != 16)
|
|
|
|
tspriteptr[i]->ang = globalang;
|
2014-01-24 21:39:02 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
get_wallspr_points((uspriteptr_t)tspr, &xx[0], &xx[1], &yy[0], &yy[1]);
|
2014-01-24 21:39:02 +00:00
|
|
|
|
2019-09-19 21:02:57 +00:00
|
|
|
if (!playing_blood? ((tspr->cstat & 48) == 0) : ((tspr->cstat & 48) != 16))
|
2015-10-21 19:54:14 +00:00
|
|
|
tspriteptr[i]->ang = oang;
|
2014-01-24 21:39:02 +00:00
|
|
|
}
|
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
for (jj=0; jj<numpts; jj++)
|
2014-01-24 21:39:02 +00:00
|
|
|
{
|
2015-10-21 19:54:14 +00:00
|
|
|
spr.x = (float)xx[jj];
|
|
|
|
spr.y = (float)yy[jj];
|
|
|
|
|
|
|
|
if (!sameside(&maskeq, &spr, &pos)) // behind the maskwall,
|
|
|
|
if ((sameside(&p1eq, &middle, &spr) && // inside the 'cone',
|
|
|
|
sameside(&p2eq, &middle, &spr))
|
|
|
|
|| !sameside(&pineq, &middle, &spr)) // or on the other outside.
|
|
|
|
{
|
|
|
|
ok = 1;
|
|
|
|
break;
|
|
|
|
}
|
2014-01-24 21:39:02 +00:00
|
|
|
}
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2015-10-21 19:54:14 +00:00
|
|
|
|
|
|
|
if (ok)
|
|
|
|
{
|
|
|
|
debugmask_add(i | 32768, tspr->owner);
|
2018-04-12 21:04:00 +00:00
|
|
|
renderDrawSprite(i);
|
2016-09-09 03:12:23 +00:00
|
|
|
|
2015-10-21 19:54:14 +00:00
|
|
|
tspriteptr[i] = NULL;
|
|
|
|
}
|
2006-08-29 01:58:59 +00:00
|
|
|
}
|
|
|
|
}
|
2015-10-21 19:54:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
debugmask_add(maskwall[maskwallcnt], thewall[maskwall[maskwallcnt]]);
|
2019-07-12 08:44:40 +00:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
2019-09-03 04:09:25 +00:00
|
|
|
polymost_setClamp(0);
|
2019-07-12 08:44:40 +00:00
|
|
|
#endif
|
2018-04-12 21:04:00 +00:00
|
|
|
renderDrawMaskedWall(maskwallcnt);
|
2015-10-21 19:54:14 +00:00
|
|
|
}
|
2013-04-21 19:55:38 +00:00
|
|
|
|
2019-07-12 08:44:40 +00:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
2019-09-03 04:09:25 +00:00
|
|
|
polymost_setClamp(1+2);
|
2019-07-12 08:44:40 +00:00
|
|
|
#endif
|
2019-04-19 21:45:22 +00:00
|
|
|
while (spritesortcnt)
|
|
|
|
{
|
|
|
|
--spritesortcnt;
|
|
|
|
if (tspriteptr[spritesortcnt] != NULL)
|
2015-10-21 19:54:14 +00:00
|
|
|
{
|
|
|
|
debugmask_add(i | 32768, tspriteptr[i]->owner);
|
2019-04-19 21:45:22 +00:00
|
|
|
renderDrawSprite(spritesortcnt);
|
|
|
|
tspriteptr[spritesortcnt] = NULL;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2015-10-21 19:54:14 +00:00
|
|
|
}
|
|
|
|
#ifdef USE_OPENGL
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
2019-07-12 08:44:40 +00:00
|
|
|
{
|
2019-10-04 17:17:55 +00:00
|
|
|
GLInterface.SetDepthMask(true);
|
|
|
|
polymost_setClamp(0);
|
2019-07-12 08:44:40 +00:00
|
|
|
}
|
2015-10-21 19:54:14 +00:00
|
|
|
#endif
|
|
|
|
|
2011-08-20 21:05:38 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2006-12-31 06:32:04 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// drawmapview
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
void renderDrawMapView(int32_t dax, int32_t day, int32_t zoome, int16_t ang)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-11-17 19:46:50 +00:00
|
|
|
int32_t i, j, k, l;
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t x, y;
|
|
|
|
int32_t s, ox, oy;
|
2010-06-22 21:50:01 +00:00
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t const oyxaspect = yxaspect, oviewingrange = viewingrange;
|
2010-10-17 14:49:39 +00:00
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
renderSetAspect(65536, divscale16((320*5)/8, 200));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
beforedrawrooms = 0;
|
|
|
|
|
2019-09-03 04:09:20 +00:00
|
|
|
Bmemset(gotsector, 0, sizeof(gotsector));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2017-02-05 20:58:33 +00:00
|
|
|
vec2_t const c1 = { (windowxy1.x<<12), (windowxy1.y<<12) };
|
|
|
|
vec2_t const c2 = { ((windowxy2.x+1)<<12)-1, ((windowxy2.y+1)<<12)-1 };
|
2009-09-09 07:19:14 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
zoome <<= 8;
|
2009-09-09 07:19:14 +00:00
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
vec2_t const bakgvect = { divscale28(sintable[(1536 - ang) & 2047], zoome),
|
|
|
|
divscale28(sintable[(2048 - ang) & 2047], zoome) };
|
|
|
|
vec2_t const vect = { mulscale8(sintable[(2048 - ang) & 2047], zoome), mulscale8(sintable[(1536 - ang) & 2047], zoome) };
|
|
|
|
vec2_t const vect2 = { mulscale16(vect.x, yxaspect), mulscale16(vect.y, yxaspect) };
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t sortnum = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
usectorptr_t sec;
|
2015-07-17 00:12:40 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
for (s=0,sec=(usectorptr_t)§or[s]; s<numsectors; s++,sec++)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (show2dsector[s>>3]&pow2char[s&7])
|
|
|
|
{
|
2012-03-22 22:45:41 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (yax_getbunch(s, YAX_FLOOR) >= 0 && (sector[s].floorstat&(256+128))==0)
|
|
|
|
continue;
|
|
|
|
#endif
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t npoints = 0; i = 0;
|
|
|
|
int32_t startwall = sec->wallptr;
|
2006-04-13 20:47:06 +00:00
|
|
|
#if 0
|
2009-02-19 16:47:54 +00:00
|
|
|
for (w=sec->wallnum,wal=&wall[startwall]; w>0; w--,wal++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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;
|
2019-04-18 17:25:24 +00:00
|
|
|
uwallptr_t wal;
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t w;
|
2019-04-18 17:25:24 +00:00
|
|
|
for (w=sec->wallnum,wal=(uwallptr_t)&wall[startwall]; w>0; w--,wal++,j++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
k = lastwall(j);
|
|
|
|
if ((k > j) && (npoints > 0)) { xb1[npoints-1] = l; l = npoints; } //overwrite point2
|
2006-04-24 19:04:22 +00:00
|
|
|
//wall[k].x wal->x wall[wal->point2].x
|
|
|
|
//wall[k].y wal->y wall[wal->point2].y
|
2006-04-13 20:47:06 +00:00
|
|
|
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;
|
2015-07-17 00:12:40 +00:00
|
|
|
x = dmulscale16(ox,vect.x,-oy,vect.y) + (xdim<<11);
|
|
|
|
y = dmulscale16(oy,vect2.x,ox,vect2.y) + (ydim<<11);
|
|
|
|
i |= getclipmask(x-c1.x,c2.x-x,y-c1.y,c2.y-y);
|
2006-04-13 20:47:06 +00:00
|
|
|
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;
|
2015-07-17 00:12:40 +00:00
|
|
|
|
2017-02-05 20:58:33 +00:00
|
|
|
vec2_t bak = { rx1[0], mulscale16(ry1[0]-(ydim<<11),xyaspect)+(ydim<<11) };
|
2015-07-17 00:12:40 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (i&0x0f)
|
|
|
|
{
|
|
|
|
npoints = clippoly(npoints,i);
|
|
|
|
if (npoints < 3) continue;
|
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Collect floor sprites to draw
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=headspritesect[s]; i>=0; i=nextspritesect[i])
|
2019-08-16 12:05:29 +00:00
|
|
|
{
|
|
|
|
if (sprite[i].cstat & 32768)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((sprite[i].cstat & 48) == 32)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-08-16 12:05:29 +00:00
|
|
|
if ((sprite[i].cstat & (64 + 8)) == (64 + 8))
|
|
|
|
continue;
|
2006-04-13 20:47:06 +00:00
|
|
|
tsprite[sortnum++].owner = i;
|
|
|
|
}
|
2019-08-16 12:05:29 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
gotsector[s>>3] |= pow2char[s&7];
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
globalorientation = (int32_t)sec->floorstat;
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((globalorientation&1) != 0) continue;
|
|
|
|
|
2006-04-23 08:23:40 +00:00
|
|
|
globalpal = sec->floorpal;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (palookup[sec->floorpal] != globalpalwritten)
|
|
|
|
{
|
|
|
|
globalpalwritten = palookup[sec->floorpal];
|
2006-04-26 19:32:18 +00:00
|
|
|
if (!globalpalwritten) globalpalwritten = palookup[0]; // JBF: fixes null-pointer crash
|
2006-04-13 20:47:06 +00:00
|
|
|
setpalookupaddress(globalpalwritten);
|
|
|
|
}
|
|
|
|
globalpicnum = sec->floorpicnum;
|
|
|
|
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
|
2019-06-25 11:30:22 +00:00
|
|
|
tileUpdatePicnum(&globalpicnum, s);
|
2006-04-13 20:47:06 +00:00
|
|
|
setgotpic(globalpicnum);
|
2014-09-30 04:14:21 +00:00
|
|
|
if ((tilesiz[globalpicnum].x <= 0) || (tilesiz[globalpicnum].y <= 0)) continue;
|
2018-04-12 21:03:30 +00:00
|
|
|
if (waloff[globalpicnum] == 0) tileLoad(globalpicnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
globalbufplc = waloff[globalpicnum];
|
2018-10-16 06:09:54 +00:00
|
|
|
globalshade = max(min<int>(sec->floorshade,numshades-1),0);
|
2006-04-13 20:47:06 +00:00
|
|
|
globvis = globalhisibility;
|
2012-12-14 19:28:05 +00:00
|
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis, (uint8_t)(sec->visibility+16));
|
2006-04-13 20:47:06 +00:00
|
|
|
globalpolytype = 0;
|
|
|
|
if ((globalorientation&64) == 0)
|
|
|
|
{
|
2014-10-25 03:32:26 +00:00
|
|
|
set_globalpos(dax, day, globalposz);
|
2015-07-17 00:12:40 +00:00
|
|
|
globalx1 = bakgvect.x; globaly1 = bakgvect.y;
|
|
|
|
globalx2 = bakgvect.x; globaly2 = bakgvect.y;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ox = wall[wall[startwall].point2].x - wall[startwall].x;
|
|
|
|
oy = wall[wall[startwall].point2].y - wall[startwall].y;
|
2012-07-01 22:11:14 +00:00
|
|
|
i = nsqrtasm(uhypsq(ox,oy)); if (i == 0) continue;
|
2006-04-13 20:47:06 +00:00
|
|
|
i = 1048576/i;
|
2015-07-17 00:12:40 +00:00
|
|
|
globalx1 = mulscale10(dmulscale10(ox,bakgvect.x,oy,bakgvect.y),i);
|
|
|
|
globaly1 = mulscale10(dmulscale10(ox,bakgvect.y,-oy,bakgvect.x),i);
|
|
|
|
ox = (bak.x>>4)-(xdim<<7); oy = (bak.y>>4)-(ydim<<7);
|
2014-10-25 03:32:26 +00:00
|
|
|
globalposx = dmulscale28(-oy, globalx1, -ox, globaly1);
|
|
|
|
globalposy = dmulscale28(-ox, globalx1, oy, globaly1);
|
2006-04-13 20:47:06 +00:00
|
|
|
globalx2 = -globalx1;
|
|
|
|
globaly2 = -globaly1;
|
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t const daslope = sector[s].floorheinum;
|
2006-04-13 20:47:06 +00:00
|
|
|
i = nsqrtasm(daslope*daslope+16777216);
|
2014-10-25 03:32:26 +00:00
|
|
|
set_globalpos(globalposx, mulscale12(globalposy,i), globalposz);
|
2006-04-13 20:47:06 +00:00
|
|
|
globalx2 = mulscale12(globalx2,i);
|
|
|
|
globaly2 = mulscale12(globaly2,i);
|
|
|
|
}
|
2012-12-14 19:28:14 +00:00
|
|
|
|
|
|
|
calc_globalshifts();
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
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;
|
2014-10-25 03:32:26 +00:00
|
|
|
set_globalpos(((int64_t) globalposx<<(20+globalxshift))+(((uint32_t) sec->floorxpanning)<<24),
|
|
|
|
((int64_t) globalposy<<(20+globalyshift))-(((uint32_t) sec->floorypanning)<<24),
|
|
|
|
globalposz);
|
2018-04-12 21:04:00 +00:00
|
|
|
renderFillPolygon(npoints);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Sort sprite list
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t gap = 1;
|
|
|
|
|
|
|
|
while (gap < sortnum) gap = (gap << 1) + 1;
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (gap>>=1; gap>0; gap>>=1)
|
|
|
|
for (i=0; i<sortnum-gap; i++)
|
|
|
|
for (j=i; j>=0; j-=gap)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
if (sprite[tsprite[j].owner].z <= sprite[tsprite[j+gap].owner].z) break;
|
|
|
|
swapshort(&tsprite[j].owner,&tsprite[j+gap].owner);
|
|
|
|
}
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (s=sortnum-1; s>=0; s--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-04-18 17:24:10 +00:00
|
|
|
auto const spr = (uspritetype * )&sprite[tsprite[s].owner];
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((spr->cstat&48) == 32)
|
|
|
|
{
|
2014-12-05 23:12:36 +00:00
|
|
|
const int32_t xspan = tilesiz[spr->picnum].x;
|
2012-11-17 19:46:50 +00:00
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
int32_t npoints = 0;
|
2017-02-05 20:58:33 +00:00
|
|
|
vec2_t v1 = { spr->x, spr->y }, v2, v3, v4;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
get_floorspr_points(spr, 0, 0, &v1.x, &v2.x, &v3.x, &v4.x,
|
|
|
|
&v1.y, &v2.y, &v3.y, &v4.y);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
xb1[0] = 1; xb1[1] = 2; xb1[2] = 3; xb1[3] = 0;
|
|
|
|
npoints = 4;
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
ox = v1.x - dax; oy = v1.y - day;
|
|
|
|
x = dmulscale16(ox,vect.x,-oy,vect.y) + (xdim<<11);
|
|
|
|
y = dmulscale16(oy,vect2.x,ox,vect2.y) + (ydim<<11);
|
|
|
|
i |= getclipmask(x-c1.x,c2.x-x,y-c1.y,c2.y-y);
|
2006-04-13 20:47:06 +00:00
|
|
|
rx1[0] = x; ry1[0] = y;
|
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
ox = v2.x - dax; oy = v2.y - day;
|
|
|
|
x = dmulscale16(ox,vect.x,-oy,vect.y) + (xdim<<11);
|
|
|
|
y = dmulscale16(oy,vect2.x,ox,vect2.y) + (ydim<<11);
|
|
|
|
i |= getclipmask(x-c1.x,c2.x-x,y-c1.y,c2.y-y);
|
2006-04-13 20:47:06 +00:00
|
|
|
rx1[1] = x; ry1[1] = y;
|
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
ox = v3.x - dax; oy = v3.y - day;
|
|
|
|
x = dmulscale16(ox,vect.x,-oy,vect.y) + (xdim<<11);
|
|
|
|
y = dmulscale16(oy,vect2.x,ox,vect2.y) + (ydim<<11);
|
|
|
|
i |= getclipmask(x-c1.x,c2.x-x,y-c1.y,c2.y-y);
|
2006-04-13 20:47:06 +00:00
|
|
|
rx1[2] = x; ry1[2] = y;
|
|
|
|
|
|
|
|
x = rx1[0]+rx1[2]-rx1[1];
|
|
|
|
y = ry1[0]+ry1[2]-ry1[1];
|
2015-07-17 00:12:40 +00:00
|
|
|
i |= getclipmask(x-c1.x,c2.x-x,y-c1.y,c2.y-y);
|
2006-04-13 20:47:06 +00:00
|
|
|
rx1[3] = x; ry1[3] = y;
|
|
|
|
|
|
|
|
if ((i&0xf0) != 0xf0) continue;
|
2015-07-17 00:12:40 +00:00
|
|
|
|
|
|
|
vec2_t bak = { rx1[0], mulscale16(ry1[0] - (ydim << 11), xyaspect) + (ydim << 11) };
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (i&0x0f)
|
|
|
|
{
|
|
|
|
npoints = clippoly(npoints,i);
|
|
|
|
if (npoints < 3) continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
globalpicnum = spr->picnum;
|
2010-01-18 11:40:40 +00:00
|
|
|
globalpal = spr->pal; // GL needs this, software doesn't
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0;
|
2019-06-25 11:30:22 +00:00
|
|
|
tileUpdatePicnum(&globalpicnum, s);
|
2006-04-13 20:47:06 +00:00
|
|
|
setgotpic(globalpicnum);
|
2014-09-30 04:14:21 +00:00
|
|
|
if ((tilesiz[globalpicnum].x <= 0) || (tilesiz[globalpicnum].y <= 0)) continue;
|
2018-04-12 21:03:30 +00:00
|
|
|
if (waloff[globalpicnum] == 0) tileLoad(globalpicnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
globalbufplc = waloff[globalpicnum];
|
2011-04-25 19:50:08 +00:00
|
|
|
|
|
|
|
// 'loading' the tile doesn't actually guarantee that it's there afterwards.
|
|
|
|
// This can really happen when drawing the second frame of a floor-aligned
|
|
|
|
// 'storm icon' sprite (4894+1)
|
|
|
|
if (!globalbufplc)
|
|
|
|
continue;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((sector[spr->sectnum].ceilingstat&1) > 0)
|
2009-01-09 09:29:17 +00:00
|
|
|
globalshade = ((int32_t)sector[spr->sectnum].ceilingshade);
|
2006-04-13 20:47:06 +00:00
|
|
|
else
|
2009-01-09 09:29:17 +00:00
|
|
|
globalshade = ((int32_t)sector[spr->sectnum].floorshade);
|
2012-03-20 18:32:00 +00:00
|
|
|
globalshade = max(min(globalshade+spr->shade+6,numshades-1),0);
|
2006-04-13 20:47:06 +00:00
|
|
|
asm3 = FP_OFF(palookup[spr->pal]+(globalshade<<8));
|
|
|
|
globvis = globalhisibility;
|
2012-12-14 19:28:05 +00:00
|
|
|
if (sec->visibility != 0) globvis = mulscale4(globvis, (uint8_t)(sec->visibility+16));
|
2006-04-13 20:47:06 +00:00
|
|
|
globalpolytype = ((spr->cstat&2)>>1)+1;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//relative alignment stuff
|
2015-07-17 00:12:40 +00:00
|
|
|
ox = v2.x-v1.x; oy = v2.y-v1.y;
|
2014-10-25 03:29:21 +00:00
|
|
|
i = ox*ox+oy*oy; if (i == 0) continue; i = tabledivide32_noinline(65536*16384, i);
|
2015-07-17 00:12:40 +00:00
|
|
|
globalx1 = mulscale10(dmulscale10(ox,bakgvect.x,oy,bakgvect.y),i);
|
|
|
|
globaly1 = mulscale10(dmulscale10(ox,bakgvect.y,-oy,bakgvect.x),i);
|
|
|
|
ox = v1.y-v4.y; oy = v4.x-v1.x;
|
2014-10-25 03:29:21 +00:00
|
|
|
i = ox*ox+oy*oy; if (i == 0) continue; i = tabledivide32_noinline(65536*16384, i);
|
2015-07-17 00:12:40 +00:00
|
|
|
globalx2 = mulscale10(dmulscale10(ox,bakgvect.x,oy,bakgvect.y),i);
|
|
|
|
globaly2 = mulscale10(dmulscale10(ox,bakgvect.y,-oy,bakgvect.x),i);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
ox = picsiz[globalpicnum]; oy = ((ox>>4)&15); ox &= 15;
|
|
|
|
if (pow2long[ox] != xspan)
|
|
|
|
{
|
|
|
|
ox++;
|
|
|
|
globalx1 = mulscale(globalx1,xspan,ox);
|
|
|
|
globaly1 = mulscale(globaly1,xspan,ox);
|
|
|
|
}
|
|
|
|
|
2015-07-17 00:12:40 +00:00
|
|
|
bak.x = (bak.x>>4)-(xdim<<7); bak.y = (bak.y>>4)-(ydim<<7);
|
|
|
|
globalposx = dmulscale28(-bak.y,globalx1,-bak.x,globaly1);
|
|
|
|
globalposy = dmulscale28(bak.x,globalx2,-bak.y,globaly2);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if ((spr->cstat&2) == 0)
|
|
|
|
msethlineshift(ox,oy);
|
2007-12-12 17:42:14 +00:00
|
|
|
else
|
|
|
|
{
|
2014-02-19 19:47:28 +00:00
|
|
|
setup_blend(spr->blend, spr->cstat&512);
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
|
|
|
|
2014-10-25 03:32:26 +00:00
|
|
|
set_globalpos(globalposx, globalposy, globalposz);
|
|
|
|
|
2012-03-13 20:06:37 +00:00
|
|
|
// so polymost can get the translucency. ignored in software mode:
|
|
|
|
globalorientation = ((spr->cstat&2)<<7) | ((spr->cstat&512)>>2);
|
2018-04-12 21:04:00 +00:00
|
|
|
renderFillPolygon(npoints);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2012-02-14 23:13:53 +00:00
|
|
|
|
2010-10-17 14:49:39 +00:00
|
|
|
if (r_usenewaspect)
|
2018-04-12 21:03:47 +00:00
|
|
|
renderSetAspect(oviewingrange, oyxaspect);
|
2010-10-17 14:49:39 +00:00
|
|
|
else
|
2018-04-12 21:03:47 +00:00
|
|
|
renderSetAspect(65536, divscale16(ydim*320, xdim*200));
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2012-10-01 17:52:37 +00:00
|
|
|
//////////////////// LOADING AND SAVING ROUTINES ////////////////////
|
|
|
|
|
2017-02-25 08:15:53 +00:00
|
|
|
static FORCE_INLINE int32_t have_maptext(void)
|
2013-05-06 19:43:42 +00:00
|
|
|
{
|
|
|
|
return (mapversion >= 10);
|
|
|
|
}
|
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
static void enginePrepareLoadBoard(buildvfs_kfd fil, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum)
|
2012-10-01 17:52:37 +00:00
|
|
|
{
|
|
|
|
initspritelists();
|
|
|
|
|
|
|
|
Bmemset(show2dsector, 0, sizeof(show2dsector));
|
|
|
|
Bmemset(show2dsprite, 0, sizeof(show2dsprite));
|
|
|
|
Bmemset(show2dwall, 0, sizeof(show2dwall));
|
2019-08-01 06:50:42 +00:00
|
|
|
Bmemset(editwall, 0, sizeof(editwall));
|
2019-06-25 11:28:14 +00:00
|
|
|
#ifdef USE_STRUCT_TRACKERS
|
2015-01-11 04:56:58 +00:00
|
|
|
Bmemset(sectorchanged, 0, sizeof(sectorchanged));
|
|
|
|
Bmemset(spritechanged, 0, sizeof(spritechanged));
|
|
|
|
Bmemset(wallchanged, 0, sizeof(wallchanged));
|
2018-03-17 03:26:01 +00:00
|
|
|
#endif
|
2012-10-01 17:52:37 +00:00
|
|
|
|
2016-10-24 21:30:34 +00:00
|
|
|
#ifdef USE_OPENGL
|
2016-10-25 05:43:46 +00:00
|
|
|
Polymost_prepare_loadboard();
|
2016-10-24 21:30:34 +00:00
|
|
|
#endif
|
|
|
|
|
2013-05-06 19:43:42 +00:00
|
|
|
if (!have_maptext())
|
|
|
|
{
|
|
|
|
kread(fil,&dapos->x,4); dapos->x = B_LITTLE32(dapos->x);
|
|
|
|
kread(fil,&dapos->y,4); dapos->y = B_LITTLE32(dapos->y);
|
|
|
|
kread(fil,&dapos->z,4); dapos->z = B_LITTLE32(dapos->z);
|
|
|
|
kread(fil,daang,2); *daang = B_LITTLE16(*daang) & 2047;
|
|
|
|
kread(fil,dacursectnum,2); *dacursectnum = B_LITTLE16(*dacursectnum);
|
|
|
|
}
|
2012-10-01 17:52:37 +00:00
|
|
|
}
|
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
static int32_t engineFinishLoadBoard(const vec3_t *dapos, int16_t *dacursectnum, int16_t numsprites, char myflags)
|
2012-10-01 17:52:37 +00:00
|
|
|
{
|
2013-04-21 19:55:22 +00:00
|
|
|
int32_t i, realnumsprites=numsprites, numremoved;
|
2012-10-01 17:52:37 +00:00
|
|
|
|
2013-01-08 06:17:10 +00:00
|
|
|
#if !defined USE_OPENGL || !defined POLYMER
|
|
|
|
UNREFERENCED_PARAMETER(myflags);
|
|
|
|
#endif
|
|
|
|
|
2012-10-01 17:52:37 +00:00
|
|
|
for (i=0; i<numsprites; i++)
|
|
|
|
{
|
2013-04-21 19:55:18 +00:00
|
|
|
int32_t removeit = 0;
|
|
|
|
|
2012-10-01 17:52:37 +00:00
|
|
|
if ((sprite[i].cstat & 48) == 48)
|
2019-09-18 22:19:02 +00:00
|
|
|
{
|
|
|
|
// If I understand this correctly, both of these essentially do the same thing...
|
|
|
|
if (!playing_rr) sprite[i].cstat &= ~48;
|
|
|
|
else sprite[i].cstat |= 32768;
|
|
|
|
}
|
2012-10-01 17:52:37 +00:00
|
|
|
|
2013-04-21 19:55:18 +00:00
|
|
|
if (sprite[i].statnum == MAXSTATUS)
|
|
|
|
{
|
|
|
|
// Sprite was removed in loadboard() -> check_sprite(). Insert it
|
|
|
|
// for now, because we must maintain the sprite numbering.
|
|
|
|
sprite[i].statnum = sprite[i].sectnum = 0;
|
|
|
|
removeit = 1;
|
|
|
|
}
|
|
|
|
|
2012-10-01 17:52:37 +00:00
|
|
|
insertsprite(sprite[i].sectnum, sprite[i].statnum);
|
2013-04-21 19:55:18 +00:00
|
|
|
|
|
|
|
if (removeit)
|
|
|
|
{
|
|
|
|
// Flag .statnum==MAXSTATUS, temporarily creating an inconsistency
|
|
|
|
// with sprite list.
|
|
|
|
sprite[i].statnum = MAXSTATUS;
|
|
|
|
realnumsprites--;
|
|
|
|
}
|
2012-10-01 17:52:37 +00:00
|
|
|
}
|
|
|
|
|
2013-04-21 19:55:18 +00:00
|
|
|
if (numsprites != realnumsprites)
|
|
|
|
{
|
|
|
|
for (i=0; i<numsprites; i++)
|
|
|
|
if (sprite[i].statnum == MAXSTATUS)
|
|
|
|
{
|
|
|
|
// Now remove it for real!
|
|
|
|
sprite[i].statnum = 0;
|
|
|
|
deletesprite(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-21 19:55:22 +00:00
|
|
|
numremoved = (numsprites-realnumsprites);
|
2013-04-21 19:55:18 +00:00
|
|
|
numsprites = realnumsprites;
|
|
|
|
Bassert(numsprites == Numsprites);
|
|
|
|
|
2012-10-01 17:52:37 +00:00
|
|
|
//Must be after loading sectors, etc!
|
|
|
|
updatesector(dapos->x, dapos->y, dacursectnum);
|
|
|
|
|
|
|
|
#ifdef HAVE_CLIPSHAPE_FEATURE
|
|
|
|
if (!quickloadboard)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
Bmemset(spriteext, 0, sizeof(spriteext_t)*MAXSPRITES);
|
2017-06-25 11:23:53 +00:00
|
|
|
#ifndef NEW_MAP_FORMAT
|
|
|
|
Bmemset(wallext, 0, sizeof(wallext_t)*MAXWALLS);
|
|
|
|
#endif
|
2012-10-01 17:52:37 +00:00
|
|
|
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
Bmemset(spritesmooth, 0, sizeof(spritesmooth_t)*(MAXSPRITES+MAXUNIQHUDID));
|
|
|
|
|
|
|
|
# ifdef POLYMER
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMER)
|
2012-10-01 17:52:37 +00:00
|
|
|
{
|
|
|
|
if ((myflags&4)==0)
|
|
|
|
polymer_loadboard();
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
guniqhudid = 0;
|
2013-04-21 19:55:22 +00:00
|
|
|
|
2015-07-08 03:34:46 +00:00
|
|
|
Bmemset(tilecols, 0, sizeof(tilecols));
|
2013-04-21 19:55:22 +00:00
|
|
|
return numremoved;
|
2012-10-01 17:52:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define MYMAXSECTORS() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXSECTORSV7 : MAXSECTORSV8)
|
|
|
|
#define MYMAXWALLS() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXWALLSV7 : MAXWALLSV8)
|
|
|
|
#define MYMAXSPRITES() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXSPRITESV7 : MAXSPRITESV8)
|
|
|
|
|
2013-04-21 19:55:18 +00:00
|
|
|
// Sprite checking
|
|
|
|
|
|
|
|
static void remove_sprite(int32_t i)
|
|
|
|
{
|
|
|
|
Bmemset(&sprite[i], 0, sizeof(spritetype));
|
|
|
|
sprite[i].statnum = MAXSTATUS;
|
|
|
|
sprite[i].sectnum = MAXSECTORS;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is only to be run after reading the sprite array!
|
2012-10-01 17:52:37 +00:00
|
|
|
static void check_sprite(int32_t i)
|
|
|
|
{
|
2013-04-21 19:55:18 +00:00
|
|
|
if ((unsigned)sprite[i].statnum >= MAXSTATUS)
|
2012-10-01 17:52:37 +00:00
|
|
|
{
|
2017-06-27 02:24:14 +00:00
|
|
|
initprintf("%sMap error: sprite #%d (%d,%d) with illegal statnum (%d) REMOVED.\n", osd->draw.errorfmt,
|
2013-04-21 19:55:18 +00:00
|
|
|
i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), TrackerCast(sprite[i].statnum));
|
|
|
|
remove_sprite(i);
|
|
|
|
}
|
|
|
|
else if ((unsigned)sprite[i].picnum >= MAXTILES)
|
|
|
|
{
|
2017-06-27 02:24:14 +00:00
|
|
|
initprintf("%sMap error: sprite #%d (%d,%d) with illegal picnum (%d) REMOVED.\n", osd->draw.errorfmt,
|
2012-11-26 08:26:04 +00:00
|
|
|
i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), TrackerCast(sprite[i].sectnum));
|
2013-04-21 19:55:18 +00:00
|
|
|
remove_sprite(i);
|
|
|
|
}
|
|
|
|
else if ((unsigned)sprite[i].sectnum >= (unsigned)numsectors)
|
|
|
|
{
|
|
|
|
const int32_t osectnum = sprite[i].sectnum;
|
2012-10-01 17:52:37 +00:00
|
|
|
|
2013-04-21 19:55:18 +00:00
|
|
|
sprite[i].sectnum = -1;
|
2012-10-01 17:52:37 +00:00
|
|
|
updatesector(sprite[i].x, sprite[i].y, &sprite[i].sectnum);
|
|
|
|
|
|
|
|
if (sprite[i].sectnum < 0)
|
2013-04-21 19:55:18 +00:00
|
|
|
remove_sprite(i);
|
2012-10-01 17:52:37 +00:00
|
|
|
|
2017-06-27 02:24:14 +00:00
|
|
|
initprintf("%sMap error: sprite #%d (%d,%d) with illegal sector (%d) ", osd->draw.errorfmt,
|
2013-04-21 19:55:18 +00:00
|
|
|
i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), osectnum);
|
2012-10-01 17:52:37 +00:00
|
|
|
|
2013-04-21 19:55:18 +00:00
|
|
|
if (sprite[i].statnum != MAXSTATUS)
|
2014-11-25 21:08:58 +00:00
|
|
|
initprintf("changed to sector %d.\n", TrackerCast(sprite[i].sectnum));
|
2013-04-21 19:55:18 +00:00
|
|
|
else
|
2014-11-25 21:08:58 +00:00
|
|
|
initprintf("REMOVED.\n");
|
2012-10-01 17:52:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-06 19:43:42 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
// Returns the number of sprites, or <0 on error.
|
2019-03-01 08:51:50 +00:00
|
|
|
LUNATIC_CB int32_t (*loadboard_maptext)(buildvfs_kfd fil, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum);
|
2013-05-06 19:43:42 +00:00
|
|
|
#endif
|
2012-10-01 17:52:37 +00:00
|
|
|
|
2015-01-08 15:14:00 +00:00
|
|
|
#include "md4.h"
|
|
|
|
|
2019-06-28 16:03:47 +00:00
|
|
|
int32_t(*loadboard_replace)(const char *filename, char flags, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum) = NULL;
|
|
|
|
|
2011-01-16 00:23:39 +00:00
|
|
|
// flags: 1, 2: former parameter "fromwhere"
|
|
|
|
// 4: don't call polymer_loadboard
|
2013-12-24 09:44:23 +00:00
|
|
|
// 8: don't autoexec <mapname>.cfg
|
|
|
|
// returns: on success, number of removed sprites
|
|
|
|
// -1: file not found
|
2012-05-25 18:39:19 +00:00
|
|
|
// -2: invalid version
|
2013-05-06 19:43:42 +00:00
|
|
|
// -3: invalid number of sectors, walls or sprites
|
|
|
|
// <= -4: map-text error
|
2018-04-12 21:03:47 +00:00
|
|
|
int32_t engineLoadBoard(const char *filename, char flags, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-06-28 16:03:47 +00:00
|
|
|
if (loadboard_replace)
|
|
|
|
return loadboard_replace(filename, flags, dapos, daang, dacursectnum);
|
2019-09-21 11:02:17 +00:00
|
|
|
int32_t i;
|
2012-10-01 17:52:37 +00:00
|
|
|
int16_t numsprites;
|
2013-04-09 17:35:11 +00:00
|
|
|
const char myflags = flags&(~3);
|
2011-01-16 00:23:39 +00:00
|
|
|
|
|
|
|
flags &= 3;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_kfd fil;
|
|
|
|
if ((fil = kopen4load(filename,flags)) == buildvfs_kfd_invalid)
|
2013-05-06 19:43:42 +00:00
|
|
|
{ mapversion = 7; return -1; }
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-05-06 19:43:42 +00:00
|
|
|
if (kread(fil, &mapversion, 4) != 4)
|
2017-12-18 23:36:05 +00:00
|
|
|
{
|
2017-12-19 00:03:12 +00:00
|
|
|
kclose(fil);
|
2013-05-06 19:43:42 +00:00
|
|
|
return -2;
|
2017-12-18 23:36:05 +00:00
|
|
|
}
|
2012-05-25 18:39:19 +00:00
|
|
|
|
|
|
|
{
|
2013-05-06 19:43:42 +00:00
|
|
|
int32_t ok = 0;
|
|
|
|
|
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
// Check for map-text first.
|
|
|
|
if (!Bmemcmp(&mapversion, "--ED", 4))
|
|
|
|
{
|
|
|
|
mapversion = 10;
|
|
|
|
ok = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// Not map-text. We expect a little-endian version int now.
|
|
|
|
mapversion = B_LITTLE32(mapversion);
|
2011-04-28 21:28:33 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2013-05-06 19:43:42 +00:00
|
|
|
ok |= (mapversion==9);
|
2011-04-28 21:28:33 +00:00
|
|
|
#endif
|
2012-05-25 18:39:19 +00:00
|
|
|
#if MAXSECTORS==MAXSECTORSV8
|
2013-05-06 19:43:42 +00:00
|
|
|
// v8 engine
|
|
|
|
ok |= (mapversion==8);
|
2012-05-25 18:39:19 +00:00
|
|
|
#endif
|
2013-05-06 19:43:42 +00:00
|
|
|
ok |= (mapversion==7);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ok)
|
|
|
|
{
|
|
|
|
kclose(fil);
|
|
|
|
return -2;
|
|
|
|
}
|
2012-05-25 18:39:19 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
enginePrepareLoadBoard(fil, dapos, daang, dacursectnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-05-06 19:43:42 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
if (have_maptext())
|
|
|
|
{
|
|
|
|
int32_t ret = klseek(fil, 0, SEEK_SET);
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
ret = loadboard_maptext(fil, dapos, daang, dacursectnum);
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
kclose(fil);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
numsprites = ret;
|
|
|
|
goto skip_reading_mapbin;
|
|
|
|
}
|
|
|
|
#endif
|
2013-04-09 17:35:11 +00:00
|
|
|
|
|
|
|
////////// Read sectors //////////
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
kread(fil,&numsectors,2); numsectors = B_LITTLE16(numsectors);
|
2018-11-18 18:11:50 +00:00
|
|
|
if ((unsigned)numsectors >= MYMAXSECTORS() + 1)
|
|
|
|
{
|
|
|
|
error:
|
|
|
|
numsectors = 0;
|
|
|
|
numwalls = 0;
|
|
|
|
numsprites = 0;
|
|
|
|
kclose(fil);
|
|
|
|
return -3;
|
|
|
|
}
|
2013-04-09 17:35:11 +00:00
|
|
|
|
|
|
|
kread(fil, sector, sizeof(sectortypev7)*numsectors);
|
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
for (i=numsectors-1; i>=0; i--)
|
|
|
|
{
|
2013-04-09 17:35:11 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
Bmemmove(§or[i], &(((sectortypev7 *)sector)[i]), sizeof(sectortypevx));
|
|
|
|
inplace_vx_from_v7_sector(§or[i]);
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2013-04-09 17:35:11 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
inplace_vx_tweak_sector(§or[i], mapversion==9);
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 17:35:11 +00:00
|
|
|
|
|
|
|
////////// Read walls //////////
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
kread(fil,&numwalls,2); numwalls = B_LITTLE16(numwalls);
|
2018-11-18 18:11:50 +00:00
|
|
|
if ((unsigned)numwalls >= MYMAXWALLS()+1) goto error;
|
2013-04-09 17:35:11 +00:00
|
|
|
|
|
|
|
kread(fil, wall, sizeof(walltypev7)*numwalls);
|
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
for (i=numwalls-1; i>=0; i--)
|
|
|
|
{
|
2013-04-09 17:35:11 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
Bmemmove(&wall[i], &(((walltypev7 *)wall)[i]), sizeof(walltypevx));
|
|
|
|
inplace_vx_from_v7_wall(&wall[i]);
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
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);
|
2013-04-09 17:35:11 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
inplace_vx_tweak_wall(&wall[i], mapversion==9);
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 17:35:11 +00:00
|
|
|
|
|
|
|
////////// Read sprites //////////
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
kread(fil,&numsprites,2); numsprites = B_LITTLE16(numsprites);
|
2018-11-18 18:11:50 +00:00
|
|
|
if ((unsigned)numsprites >= MYMAXSPRITES()+1) goto error;
|
2013-04-09 17:35:11 +00:00
|
|
|
|
|
|
|
kread(fil, sprite, sizeof(spritetype)*numsprites);
|
|
|
|
|
2013-05-06 19:43:42 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
skip_reading_mapbin:
|
|
|
|
#endif
|
2015-01-08 15:14:00 +00:00
|
|
|
|
|
|
|
klseek(fil, 0, SEEK_SET);
|
|
|
|
int32_t boardsize = kfilelength(fil);
|
|
|
|
uint8_t *fullboard = (uint8_t*)Xmalloc(boardsize);
|
|
|
|
kread(fil, fullboard, boardsize);
|
2015-01-18 20:31:37 +00:00
|
|
|
md4once(fullboard, boardsize, g_loadedMapHack.md4);
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(fullboard);
|
2015-01-08 15:14:00 +00:00
|
|
|
|
2013-04-21 19:55:18 +00:00
|
|
|
kclose(fil);
|
|
|
|
// Done reading file.
|
|
|
|
|
2019-08-01 06:50:46 +00:00
|
|
|
if (!have_maptext())
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2019-08-01 06:50:46 +00:00
|
|
|
for (i=numsprites-1; i>=0; i--)
|
2013-05-06 19:43:42 +00:00
|
|
|
{
|
|
|
|
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);
|
2008-02-06 03:49:35 +00:00
|
|
|
|
2019-08-01 06:50:46 +00:00
|
|
|
check_sprite(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i=numsprites-1; i>=0; i--)
|
|
|
|
check_sprite(i);
|
2012-10-01 17:52:37 +00:00
|
|
|
}
|
2012-03-14 22:30:57 +00:00
|
|
|
|
2013-06-28 14:07:44 +00:00
|
|
|
// Back up the map version of the *loaded* map. Must be before yax_update().
|
|
|
|
g_loadedMapVersion = mapversion;
|
2011-04-09 13:27:08 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2011-04-28 21:28:33 +00:00
|
|
|
yax_update(mapversion<9);
|
2011-04-22 22:48:06 +00:00
|
|
|
if (editstatus)
|
2012-10-01 17:52:30 +00:00
|
|
|
yax_updategrays(dapos->z);
|
2011-04-09 13:27:08 +00:00
|
|
|
#endif
|
2006-09-29 21:36:12 +00:00
|
|
|
|
2013-12-24 09:44:23 +00:00
|
|
|
if ((myflags&8)==0)
|
2013-04-25 17:48:37 +00:00
|
|
|
{
|
2013-05-06 19:43:38 +00:00
|
|
|
char fn[BMAX_PATH];
|
2013-04-25 17:48:37 +00:00
|
|
|
|
|
|
|
Bstrcpy(fn, filename);
|
2013-05-06 19:43:38 +00:00
|
|
|
append_ext_UNSAFE(fn, ".cfg");
|
2013-04-29 15:13:48 +00:00
|
|
|
|
|
|
|
OSD_Exec(fn);
|
2013-10-08 10:00:25 +00:00
|
|
|
|
|
|
|
system_getcvars();
|
2014-01-12 14:54:36 +00:00
|
|
|
|
|
|
|
// Per-map ART
|
2018-04-12 21:03:30 +00:00
|
|
|
artSetupMapArt(filename);
|
2013-04-25 17:48:37 +00:00
|
|
|
}
|
|
|
|
|
2015-01-08 15:14:00 +00:00
|
|
|
// initprintf("Loaded map \"%s\" (md4sum: %08x%08x%08x%08x)\n", filename, B_BIG32(*((int32_t*)&md4out[0])), B_BIG32(*((int32_t*)&md4out[4])), B_BIG32(*((int32_t*)&md4out[8])), B_BIG32(*((int32_t*)&md4out[12])));
|
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
return engineFinishLoadBoard(dapos, dacursectnum, numsprites, myflags);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// loadboardv5/6
|
|
|
|
//
|
2013-04-25 21:10:22 +00:00
|
|
|
#include "engine_oldmap.h"
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
// Powerslave uses v6
|
2009-02-19 09:39:19 +00:00
|
|
|
// Witchaven 1 and TekWar and LameDuke use v5
|
2018-04-12 21:03:47 +00:00
|
|
|
int32_t engineLoadBoardV5V6(const char *filename, char fromwhere, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-03-01 08:51:50 +00:00
|
|
|
int32_t i;
|
2012-10-01 17:52:37 +00:00
|
|
|
int16_t numsprites;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
struct sectortypev5 v5sect;
|
|
|
|
struct walltypev5 v5wall;
|
|
|
|
struct spritetypev5 v5spr;
|
|
|
|
struct sectortypev6 v6sect;
|
|
|
|
struct walltypev6 v6wall;
|
|
|
|
struct spritetypev6 v6spr;
|
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_kfd fil;
|
|
|
|
if ((fil = kopen4load(filename,fromwhere)) == buildvfs_kfd_invalid)
|
2016-06-21 00:34:41 +00:00
|
|
|
{ mapversion = 5L; return -1; }
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
kread(fil,&mapversion,4); mapversion = B_LITTLE32(mapversion);
|
2016-06-21 00:34:41 +00:00
|
|
|
if (mapversion != 5L && mapversion != 6L) { kclose(fil); return -2; }
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
enginePrepareLoadBoard(fil, dapos, daang, dacursectnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
kread(fil,&numsectors,2); numsectors = B_LITTLE16(numsectors);
|
2016-06-21 00:34:41 +00:00
|
|
|
if (numsectors > MAXSECTORS) { kclose(fil); return -1; }
|
2007-12-12 17:42:14 +00:00
|
|
|
for (i=0; i<numsectors; i++)
|
|
|
|
{
|
|
|
|
switch (mapversion)
|
|
|
|
{
|
2006-11-13 23:12:47 +00:00
|
|
|
case 5:
|
2012-02-18 17:55:27 +00:00
|
|
|
kread(fil,&v5sect,sizeof(struct sectortypev5));
|
2006-04-24 19:04:22 +00:00
|
|
|
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;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 6:
|
2012-02-18 17:55:27 +00:00
|
|
|
kread(fil,&v6sect,sizeof(struct sectortypev6));
|
2006-04-24 19:04:22 +00:00
|
|
|
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;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-10-01 17:52:37 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
switch (mapversion)
|
|
|
|
{
|
2006-11-13 23:12:47 +00:00
|
|
|
case 5:
|
2012-02-18 17:55:27 +00:00
|
|
|
convertv5sectv6(&v5sect,&v6sect);
|
2017-07-18 20:53:41 +00:00
|
|
|
fallthrough__;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 6:
|
2012-02-18 17:55:27 +00:00
|
|
|
convertv6sectv7(&v6sect,§or[i]);
|
2017-07-18 20:53:41 +00:00
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
kread(fil,&numwalls,2); numwalls = B_LITTLE16(numwalls);
|
2016-06-21 00:34:41 +00:00
|
|
|
if (numwalls > MAXWALLS) { kclose(fil); return -1; }
|
2007-12-12 17:42:14 +00:00
|
|
|
for (i=0; i<numwalls; i++)
|
|
|
|
{
|
|
|
|
switch (mapversion)
|
|
|
|
{
|
2006-11-13 23:12:47 +00:00
|
|
|
case 5:
|
2012-02-18 17:55:27 +00:00
|
|
|
kread(fil,&v5wall,sizeof(struct walltypev5));
|
2006-04-24 19:04:22 +00:00
|
|
|
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;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 6:
|
2012-02-18 17:55:27 +00:00
|
|
|
kread(fil,&v6wall,sizeof(struct walltypev6));
|
2006-04-24 19:04:22 +00:00
|
|
|
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;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-10-01 17:52:37 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
switch (mapversion)
|
|
|
|
{
|
2006-11-13 23:12:47 +00:00
|
|
|
case 5:
|
2012-02-18 17:55:27 +00:00
|
|
|
convertv5wallv6(&v5wall,&v6wall,i);
|
2017-07-18 20:53:41 +00:00
|
|
|
fallthrough__;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 6:
|
2012-02-18 17:55:27 +00:00
|
|
|
convertv6wallv7(&v6wall,&wall[i]);
|
2017-07-18 20:53:41 +00:00
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
kread(fil,&numsprites,2); numsprites = B_LITTLE16(numsprites);
|
2016-06-21 00:34:41 +00:00
|
|
|
if (numsprites > MAXSPRITES) { kclose(fil); return -1; }
|
2007-12-12 17:42:14 +00:00
|
|
|
for (i=0; i<numsprites; i++)
|
|
|
|
{
|
|
|
|
switch (mapversion)
|
|
|
|
{
|
2006-11-13 23:12:47 +00:00
|
|
|
case 5:
|
2012-02-18 17:55:27 +00:00
|
|
|
kread(fil,&v5spr,sizeof(struct spritetypev5));
|
2006-04-24 19:04:22 +00:00
|
|
|
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;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 6:
|
2012-02-18 17:55:27 +00:00
|
|
|
kread(fil,&v6spr,sizeof(struct spritetypev6));
|
2006-04-24 19:04:22 +00:00
|
|
|
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;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-10-01 17:52:37 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
switch (mapversion)
|
|
|
|
{
|
2006-11-13 23:12:47 +00:00
|
|
|
case 5:
|
2012-02-18 17:55:27 +00:00
|
|
|
convertv5sprv6(&v5spr,&v6spr);
|
2017-07-18 20:53:41 +00:00
|
|
|
fallthrough__;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 6:
|
2012-02-18 17:55:27 +00:00
|
|
|
convertv6sprv7(&v6spr,&sprite[i]);
|
2017-07-18 20:53:41 +00:00
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2012-10-01 17:52:37 +00:00
|
|
|
check_sprite(i);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
kclose(fil);
|
2012-10-01 17:52:37 +00:00
|
|
|
// Done reading file.
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
return engineFinishLoadBoard(dapos, dacursectnum, numsprites, 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2013-04-25 21:10:22 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
LUNATIC_CB int32_t (*saveboard_maptext)(const char *filename, const vec3_t *dapos, int16_t daang, int16_t dacursectnum);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Get map version of external map format (<10: old binary format, ==10: new
|
|
|
|
// 'VX' map-text format).
|
|
|
|
static int32_t get_mapversion(void)
|
2011-01-16 00:23:39 +00:00
|
|
|
{
|
2016-06-21 00:33:30 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (numyaxbunches > 0)
|
|
|
|
# ifdef NEW_MAP_FORMAT
|
|
|
|
return 10;
|
|
|
|
# else
|
|
|
|
return 9;
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef NEW_MAP_FORMAT
|
2011-01-16 00:23:39 +00:00
|
|
|
{
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t i;
|
|
|
|
for (i=0; i<numwalls; i++)
|
|
|
|
if (wall[i].blend != 0)
|
|
|
|
return 10;
|
2011-01-16 00:23:39 +00:00
|
|
|
}
|
2016-06-21 00:33:30 +00:00
|
|
|
#endif
|
|
|
|
if (numsectors > MAXSECTORSV7 || numwalls > MAXWALLSV7 || Numsprites > MAXSPRITESV7)
|
|
|
|
return 8;
|
2011-08-17 18:52:54 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
return 7;
|
2011-01-16 00:23:39 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
2016-06-21 00:33:30 +00:00
|
|
|
// saveboard
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
2019-06-29 15:37:04 +00:00
|
|
|
int32_t(*saveboard_replace)(const char *filename, const vec3_t *dapos, int16_t daang, int16_t dacursectnum) = NULL;
|
2016-06-21 00:33:30 +00:00
|
|
|
int32_t saveboard(const char *filename, const vec3_t *dapos, int16_t daang, int16_t dacursectnum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-06-29 15:37:04 +00:00
|
|
|
if (saveboard_replace)
|
|
|
|
return saveboard_replace(filename, dapos, daang, dacursectnum);
|
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
int16_t numsprites, ts;
|
2019-03-01 08:51:50 +00:00
|
|
|
int32_t i, j, tl;
|
2016-06-21 00:33:30 +00:00
|
|
|
|
|
|
|
// First, some checking.
|
|
|
|
for (j=0; j<MAXSPRITES; j++)
|
2007-01-24 03:42:54 +00:00
|
|
|
{
|
2016-06-21 00:33:30 +00:00
|
|
|
if ((unsigned)sprite[j].statnum > MAXSTATUS)
|
|
|
|
{
|
|
|
|
initprintf("Map error: sprite #%d(%d,%d) with an illegal statnum(%d)\n",
|
|
|
|
j,TrackerCast(sprite[j].x),TrackerCast(sprite[j].y),TrackerCast(sprite[j].statnum));
|
|
|
|
changespritestat(j,0);
|
|
|
|
}
|
2007-01-24 03:42:54 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
if ((unsigned)sprite[j].sectnum > MAXSECTORS)
|
|
|
|
{
|
|
|
|
initprintf("Map error: sprite #%d(%d,%d) with an illegal sectnum(%d)\n",
|
|
|
|
j,TrackerCast(sprite[j].x),TrackerCast(sprite[j].y),TrackerCast(sprite[j].sectnum));
|
|
|
|
changespritesect(j,0);
|
|
|
|
}
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
// Count the number of sprites.
|
|
|
|
numsprites = 0;
|
|
|
|
for (j=0; j<MAXSPRITES; j++)
|
|
|
|
{
|
|
|
|
if (sprite[j].statnum != MAXSTATUS)
|
|
|
|
numsprites++;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
// Check consistency of sprite-in-the-world predicate (.statnum != MAXSTATUS)
|
|
|
|
// and the engine-reported number of sprites 'Numsprites'.
|
|
|
|
Bassert(numsprites == Numsprites);
|
2011-07-20 22:08:05 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
// Determine the map version.
|
|
|
|
mapversion = get_mapversion();
|
2011-01-16 00:23:39 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
if (mapversion == 10)
|
2011-08-17 18:52:54 +00:00
|
|
|
{
|
2016-06-21 00:33:30 +00:00
|
|
|
initprintf("Saving of TROR maps not yet accessible in the Lunatic preview build\n");
|
|
|
|
return -1;
|
|
|
|
// return saveboard_maptext(filename, dapos, daang, dacursectnum);
|
2011-08-17 18:52:54 +00:00
|
|
|
}
|
2016-06-21 00:33:30 +00:00
|
|
|
#endif
|
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_fd fil = buildvfs_open_write(filename);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
if (fil == buildvfs_fd_invalid)
|
2010-05-25 10:56:00 +00:00
|
|
|
{
|
2016-06-21 00:33:30 +00:00
|
|
|
initprintf("Couldn't open \"%s\" for writing: %s\n", filename, strerror(errno));
|
2010-05-25 10:56:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
tl = B_LITTLE32(mapversion); buildvfs_write(fil,&tl,4);
|
2010-05-25 10:56:00 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
tl = B_LITTLE32(dapos->x); buildvfs_write(fil,&tl,4);
|
|
|
|
tl = B_LITTLE32(dapos->y); buildvfs_write(fil,&tl,4);
|
|
|
|
tl = B_LITTLE32(dapos->z); buildvfs_write(fil,&tl,4);
|
|
|
|
ts = B_LITTLE16(daang); buildvfs_write(fil,&ts,2);
|
|
|
|
ts = B_LITTLE16(dacursectnum); buildvfs_write(fil,&ts,2);
|
2010-05-25 10:56:00 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
ts = B_LITTLE16(numsectors); buildvfs_write(fil,&ts,2);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
while (1) // if, really
|
|
|
|
{
|
2017-01-05 05:30:00 +00:00
|
|
|
usectortypev7 *const tsect = (usectortypev7 *)Xmalloc(sizeof(usectortypev7) * numsectors);
|
|
|
|
uwalltypev7 *twall;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
for (i=0; i<numsectors; i++)
|
|
|
|
copy_v7_from_vx_sector(&tsect[i], §or[i]);
|
|
|
|
#else
|
|
|
|
Bmemcpy(tsect, sector, sizeof(sectortypev7)*numsectors);
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
for (i=0; i<numsectors; i++)
|
2012-02-18 17:55:27 +00:00
|
|
|
{
|
2017-01-05 05:30:00 +00:00
|
|
|
usectortypev7 *const sec = &tsect[i];
|
2013-04-09 17:35:11 +00:00
|
|
|
|
2007-09-03 01:12:05 +00:00
|
|
|
sec->wallptr = B_LITTLE16(sec->wallptr);
|
|
|
|
sec->wallnum = B_LITTLE16(sec->wallnum);
|
|
|
|
sec->ceilingz = B_LITTLE32(sec->ceilingz);
|
|
|
|
sec->floorz = B_LITTLE32(sec->floorz);
|
|
|
|
sec->ceilingstat = B_LITTLE16(sec->ceilingstat);
|
|
|
|
sec->floorstat = B_LITTLE16(sec->floorstat);
|
|
|
|
sec->ceilingpicnum = B_LITTLE16(sec->ceilingpicnum);
|
|
|
|
sec->ceilingheinum = B_LITTLE16(sec->ceilingheinum);
|
|
|
|
sec->floorpicnum = B_LITTLE16(sec->floorpicnum);
|
|
|
|
sec->floorheinum = B_LITTLE16(sec->floorheinum);
|
|
|
|
sec->lotag = B_LITTLE16(sec->lotag);
|
|
|
|
sec->hitag = B_LITTLE16(sec->hitag);
|
|
|
|
sec->extra = B_LITTLE16(sec->extra);
|
2013-04-09 17:35:11 +00:00
|
|
|
#ifdef YAX_ENABLE__COMPAT
|
2012-02-16 19:25:18 +00:00
|
|
|
if (editstatus == 0)
|
|
|
|
{
|
|
|
|
// if in-game, pack game-time bunchnum data back into structs
|
|
|
|
int32_t cf, bn;
|
|
|
|
|
|
|
|
for (cf=0; cf<2; cf++)
|
|
|
|
if ((bn=yax_getbunch(i, cf)) >= 0)
|
|
|
|
YAX_PTRBUNCHNUM(tsect, i, cf) = bn;
|
|
|
|
}
|
|
|
|
#endif
|
2007-09-03 01:12:05 +00:00
|
|
|
}
|
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_write(fil, tsect, sizeof(sectortypev7)*numsectors);
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(tsect);
|
2007-09-03 01:12:05 +00:00
|
|
|
|
2008-06-04 07:38:11 +00:00
|
|
|
ts = B_LITTLE16(numwalls);
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_write(fil,&ts,2);
|
2007-09-03 01:12:05 +00:00
|
|
|
|
2017-01-05 05:30:00 +00:00
|
|
|
twall = (uwalltypev7 *)Xmalloc(sizeof(uwalltypev7) * numwalls);
|
2007-09-03 01:12:05 +00:00
|
|
|
|
2013-04-09 17:35:11 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
for (i=0; i<numwalls; i++)
|
|
|
|
copy_v7_from_vx_wall(&twall[i], &wall[i]);
|
|
|
|
#else
|
|
|
|
Bmemcpy(twall, wall, sizeof(walltypev7)*numwalls);
|
|
|
|
#endif
|
2007-09-03 01:12:05 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
for (i=0; i<numwalls; i++)
|
|
|
|
{
|
2017-01-05 05:30:00 +00:00
|
|
|
uwalltypev7 *const wal = &twall[i];
|
2013-04-09 17:35:11 +00:00
|
|
|
|
2007-09-03 01:12:05 +00:00
|
|
|
wal->x = B_LITTLE32(wal->x);
|
|
|
|
wal->y = B_LITTLE32(wal->y);
|
|
|
|
wal->point2 = B_LITTLE16(wal->point2);
|
|
|
|
wal->nextwall = B_LITTLE16(wal->nextwall);
|
|
|
|
wal->nextsector = B_LITTLE16(wal->nextsector);
|
|
|
|
wal->cstat = B_LITTLE16(wal->cstat);
|
|
|
|
wal->picnum = B_LITTLE16(wal->picnum);
|
|
|
|
wal->overpicnum = B_LITTLE16(wal->overpicnum);
|
2013-04-09 17:35:11 +00:00
|
|
|
#ifdef YAX_ENABLE__COMPAT
|
2012-02-16 19:25:18 +00:00
|
|
|
if (editstatus == 0)
|
|
|
|
{
|
|
|
|
// if in-game, pack game-time yax-nextwall data back into structs
|
|
|
|
int16_t ynw;
|
|
|
|
if ((ynw=yax_getnextwall(i, YAX_CEILING))>=0)
|
|
|
|
YAX_PTRNEXTWALL(twall,i,YAX_CEILING) = ynw;
|
|
|
|
if ((ynw=yax_getnextwall(i, YAX_FLOOR))>=0)
|
|
|
|
YAX_PTRNEXTWALL(twall,i,YAX_FLOOR) = ynw;
|
|
|
|
}
|
|
|
|
#endif
|
2007-09-03 01:12:05 +00:00
|
|
|
wal->lotag = B_LITTLE16(wal->lotag);
|
|
|
|
wal->hitag = B_LITTLE16(wal->hitag);
|
|
|
|
wal->extra = B_LITTLE16(wal->extra);
|
|
|
|
}
|
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_write(fil, twall, sizeof(walltypev7)*numwalls);
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(twall);
|
2007-09-03 01:12:05 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
ts = B_LITTLE16(numsprites); buildvfs_write(fil,&ts,2);
|
2007-09-03 01:12:05 +00:00
|
|
|
|
2011-09-12 15:03:51 +00:00
|
|
|
if (numsprites > 0)
|
|
|
|
{
|
2019-04-18 17:24:10 +00:00
|
|
|
auto const tspri = (uspritetype *)Xmalloc(sizeof(spritetype) * numsprites);
|
|
|
|
auto spri = tspri;
|
2007-09-03 01:12:05 +00:00
|
|
|
|
2011-09-12 15:03:51 +00:00
|
|
|
for (j=0; j<MAXSPRITES; j++)
|
2007-09-03 01:12:05 +00:00
|
|
|
{
|
2011-09-12 15:03:51 +00:00
|
|
|
if (sprite[j].statnum != MAXSTATUS)
|
|
|
|
{
|
2013-04-09 17:35:11 +00:00
|
|
|
Bmemcpy(spri, &sprite[j], sizeof(spritetype));
|
2011-09-12 15:03:51 +00:00
|
|
|
spri->x = B_LITTLE32(spri->x);
|
|
|
|
spri->y = B_LITTLE32(spri->y);
|
|
|
|
spri->z = B_LITTLE32(spri->z);
|
|
|
|
spri->cstat = B_LITTLE16(spri->cstat);
|
|
|
|
spri->picnum = B_LITTLE16(spri->picnum);
|
|
|
|
spri->sectnum = B_LITTLE16(spri->sectnum);
|
|
|
|
spri->statnum = B_LITTLE16(spri->statnum);
|
|
|
|
spri->ang = B_LITTLE16(spri->ang);
|
|
|
|
spri->owner = B_LITTLE16(spri->owner);
|
|
|
|
spri->xvel = B_LITTLE16(spri->xvel);
|
|
|
|
spri->yvel = B_LITTLE16(spri->yvel);
|
|
|
|
spri->zvel = B_LITTLE16(spri->zvel);
|
|
|
|
spri->lotag = B_LITTLE16(spri->lotag);
|
|
|
|
spri->hitag = B_LITTLE16(spri->hitag);
|
|
|
|
spri->extra = B_LITTLE16(spri->extra);
|
|
|
|
spri++;
|
|
|
|
}
|
2007-09-03 01:12:05 +00:00
|
|
|
}
|
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_write(fil, tspri, sizeof(spritetype)*numsprites);
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(tspri);
|
2011-09-12 15:03:51 +00:00
|
|
|
}
|
2007-09-03 01:12:05 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_close(fil);
|
2013-05-06 19:43:34 +00:00
|
|
|
return 0;
|
2007-09-03 01:12:05 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_close(fil);
|
2013-05-06 19:43:34 +00:00
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2014-10-29 17:04:28 +00:00
|
|
|
#define YSAVES ((xdim*MAXSPRITES)>>7)
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
static void videoAllocateBuffers(void)
|
2014-10-29 17:04:28 +00:00
|
|
|
{
|
|
|
|
int32_t i;
|
2015-02-07 17:29:15 +00:00
|
|
|
// Needed for the game's TILT_SETVIEWTOTILE_320.
|
|
|
|
const int32_t clamped_ydim = max(ydim, 320);
|
2014-10-29 17:04:28 +00:00
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
void **ptr;
|
|
|
|
size_t size;
|
|
|
|
} dynarray[] = {
|
|
|
|
{ (void **)&smost, YSAVES * sizeof(int16_t) },
|
|
|
|
{ (void **)&umost, xdim * sizeof(int16_t) },
|
|
|
|
{ (void **)&dmost, xdim * sizeof(int16_t) },
|
|
|
|
{ (void **)&startumost, xdim * sizeof(int16_t) },
|
|
|
|
{ (void **)&startdmost, xdim * sizeof(int16_t) },
|
|
|
|
{ (void **)&bakumost, xdim * sizeof(int16_t) },
|
|
|
|
{ (void **)&bakdmost, xdim * sizeof(int16_t) },
|
|
|
|
{ (void **)&uplc, xdim * sizeof(int16_t) },
|
|
|
|
{ (void **)&dplc, xdim * sizeof(int16_t) },
|
|
|
|
{ (void **)&uwall, xdim * sizeof(int16_t) },
|
|
|
|
{ (void **)&dwall, xdim * sizeof(int16_t) },
|
|
|
|
{ (void **)&swplc, xdim * sizeof(int32_t) },
|
|
|
|
{ (void **)&lplc, xdim * sizeof(int32_t) },
|
|
|
|
{ (void **)&swall, xdim * sizeof(int32_t) },
|
|
|
|
{ (void **)&lwall, (xdim + 4) * sizeof(int32_t) },
|
2019-06-25 11:29:42 +00:00
|
|
|
{ (void **)&radarang2, xdim * sizeof(int32_t) },
|
2015-02-07 17:29:15 +00:00
|
|
|
{ (void **)&dotp1, clamped_ydim * sizeof(intptr_t) },
|
|
|
|
{ (void **)&dotp2, clamped_ydim * sizeof(intptr_t) },
|
|
|
|
{ (void **)&lastx, clamped_ydim * sizeof(int32_t) },
|
2019-06-25 18:35:05 +00:00
|
|
|
{ (void **)&mirrorBuffer, (size_t) (xdim * ydim)},
|
2014-10-29 17:04:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
for (i = 0; i < (signed)ARRAY_SIZE(dynarray); i++)
|
|
|
|
{
|
2019-06-25 11:29:08 +00:00
|
|
|
Xaligned_free(*dynarray[i].ptr);
|
2014-10-29 17:04:28 +00:00
|
|
|
|
|
|
|
*dynarray[i].ptr = Xaligned_alloc(16, dynarray[i].size);
|
|
|
|
}
|
|
|
|
|
|
|
|
ysavecnt = YSAVES;
|
|
|
|
nodesperline = tabledivide32_noinline(YSAVES, ydim);
|
2018-06-25 14:53:42 +00:00
|
|
|
|
2018-07-14 21:36:44 +00:00
|
|
|
#ifdef RENDERTYPESDL
|
|
|
|
if (videoGetRenderMode() == REND_CLASSIC)
|
2018-06-25 14:53:42 +00:00
|
|
|
{
|
2018-07-14 21:36:44 +00:00
|
|
|
# ifdef USE_OPENGL
|
|
|
|
if (!nogl)
|
|
|
|
{
|
|
|
|
glsurface_initialize({ xdim, ydim });
|
|
|
|
}
|
|
|
|
else
|
|
|
|
# endif
|
|
|
|
{
|
|
|
|
softsurface_initialize({ xdim, ydim },
|
|
|
|
{ xres, yres });
|
|
|
|
}
|
2018-06-25 14:53:42 +00:00
|
|
|
}
|
|
|
|
#endif
|
2014-10-29 17:04:28 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-26 17:29:53 +00:00
|
|
|
#ifdef USE_OPENGL
|
2019-09-19 20:02:45 +00:00
|
|
|
void (*PolymostProcessVoxels_Callback)(void) = NULL;
|
2014-12-26 17:29:53 +00:00
|
|
|
static void PolymostProcessVoxels(void)
|
|
|
|
{
|
2019-08-13 02:53:38 +00:00
|
|
|
if (g_haveVoxels != 1)
|
2014-12-26 17:29:53 +00:00
|
|
|
return;
|
|
|
|
|
2019-08-13 02:53:38 +00:00
|
|
|
g_haveVoxels = 2;
|
2014-12-26 17:29:53 +00:00
|
|
|
|
|
|
|
OSD_Printf("Generating voxel models for Polymost. This may take a while...\n");
|
2018-04-12 21:02:51 +00:00
|
|
|
videoNextPage();
|
2014-12-26 17:29:53 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<MAXVOXELS; i++)
|
2014-12-26 17:29:53 +00:00
|
|
|
{
|
|
|
|
if (voxfilenames[i])
|
|
|
|
{
|
|
|
|
voxmodels[i] = voxload(voxfilenames[i]);
|
2018-05-30 12:01:42 +00:00
|
|
|
voxmodels[i]->scale = voxscale[i]*(1.f/65536.f);
|
2014-12-26 17:29:53 +00:00
|
|
|
DO_FREE_AND_NULL(voxfilenames[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// setgamemode
|
|
|
|
//
|
|
|
|
// JBF: davidoption now functions as a windowed-mode flag (0 == windowed, 1 == fullscreen)
|
|
|
|
extern char videomodereset;
|
2018-07-14 21:36:44 +00:00
|
|
|
int32_t videoSetGameMode(char davidoption, int32_t daupscaledxdim, int32_t daupscaledydim, int32_t dabpp, int32_t daupscalefactor)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-12-14 19:28:17 +00:00
|
|
|
int32_t j;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2008-08-26 19:50:34 +00:00
|
|
|
if (nogl) dabpp = 8;
|
|
|
|
#endif
|
2018-07-14 21:36:44 +00:00
|
|
|
daupscaledxdim = max(320, daupscaledxdim);
|
|
|
|
daupscaledydim = max(200, daupscaledydim);
|
2011-07-01 12:22:12 +00:00
|
|
|
|
2018-07-14 21:36:44 +00:00
|
|
|
if (in3dmode() && videomodereset == 0 && (davidoption == fullscreen) &&
|
|
|
|
(xres == daupscaledxdim) && (yres == daupscaledydim) && (bpp == dabpp) && (upscalefactor == daupscalefactor))
|
2016-06-21 00:34:41 +00:00
|
|
|
return 0;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2012-03-13 20:06:37 +00:00
|
|
|
Bstrcpy(kensmessage,"!!!! BUILD engine&tools programmed by Ken Silverman of E.G. RI."
|
|
|
|
" (c) Copyright 1995 Ken Silverman. Summary: BUILD = Ken. !!!!");
|
2006-04-24 19:04:22 +00:00
|
|
|
// if (getkensmessagecrc(FP_OFF(kensmessage)) != 0x56c764d4)
|
2014-06-13 09:02:37 +00:00
|
|
|
// { OSD_Printf("Nice try.\n"); Bexit(0); }
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:34:41 +00:00
|
|
|
//if (checkvideomode(&daxdim, &daydim, dabpp, davidoption)<0) return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//bytesperline is set in this function
|
2008-08-26 19:50:34 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
j = bpp;
|
2010-08-14 21:32:28 +00:00
|
|
|
|
2011-09-10 15:45:11 +00:00
|
|
|
g_lastpalettesum = 0;
|
2018-07-14 21:36:44 +00:00
|
|
|
if (videoSetMode(daupscaledxdim,daupscaledydim,dabpp,davidoption) < 0) return -1;
|
2011-01-16 02:50:27 +00:00
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2009-03-27 21:54:55 +00:00
|
|
|
if (dabpp > 8) rendmode = glrendmode; // GL renderer
|
2018-06-24 00:55:23 +00:00
|
|
|
else rendmode = REND_CLASSIC;
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
|
|
|
|
2018-07-14 21:36:44 +00:00
|
|
|
upscalefactor = max(1, min(tabledivide32(yres, 200), daupscalefactor));
|
|
|
|
//POGOTODO: Polymost/Polymer could work with upscaling with a couple more changes
|
|
|
|
int32_t scalefactor = upscalefactor;
|
|
|
|
#ifdef RENDERTYPESDL
|
|
|
|
if (bpp != 8)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
scalefactor = 1;
|
|
|
|
}
|
|
|
|
xdim = daupscaledxdim/scalefactor;
|
|
|
|
ydim = daupscaledydim/scalefactor;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-10-25 03:27:35 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-07-14 21:36:44 +00:00
|
|
|
fxdim = (float) xdim;
|
|
|
|
fydim = (float) ydim;
|
2014-10-25 03:27:35 +00:00
|
|
|
#endif
|
2014-10-29 17:04:28 +00:00
|
|
|
|
2018-07-14 21:36:44 +00:00
|
|
|
OSD_ResizeDisplay(xdim, ydim);
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoAllocateBuffers();
|
2014-10-29 17:04:28 +00:00
|
|
|
|
|
|
|
#ifdef HIGH_PRECISION_SPRITE
|
|
|
|
swallf = (float *) Xrealloc(swallf, xdim * sizeof(float));
|
|
|
|
#endif
|
|
|
|
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(lookups);
|
2012-05-26 21:58:31 +00:00
|
|
|
|
|
|
|
j = ydim*4; //Leave room for horizlookup&horizlookup2
|
2014-05-30 00:02:19 +00:00
|
|
|
lookups = (int32_t *)Xmalloc(2*j*sizeof(lookups[0]));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2008-02-16 22:27:08 +00:00
|
|
|
horizlookup = lookups;
|
2012-05-26 21:58:31 +00:00
|
|
|
horizlookup2 = lookups + j;
|
2006-04-13 20:47:06 +00:00
|
|
|
horizycent = ((ydim*4)>>1);
|
|
|
|
|
|
|
|
//Force drawrooms to call dosetaspect & recalculate stuff
|
|
|
|
oxyaspect = oxdimen = oviewingrange = -1;
|
|
|
|
|
2012-12-14 19:28:17 +00:00
|
|
|
calc_ylookup(bytesperline, ydim);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoSetViewableArea(0L,0L,xdim-1,ydim-1);
|
|
|
|
videoClearScreen(0L);
|
2018-04-12 21:03:12 +00:00
|
|
|
videoSetPalette(curbrightness,0,0);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (searchx < 0) { searchx = halfxdimen; searchy = (ydimen>>1); }
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() >= REND_POLYMOST)
|
2006-10-14 23:33:10 +00:00
|
|
|
{
|
|
|
|
polymost_glreset();
|
2007-01-06 01:29:45 +00:00
|
|
|
polymost_glinit();
|
2018-10-10 21:04:42 +00:00
|
|
|
|
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
|
|
|
PolymostProcessVoxels();
|
2006-10-14 23:33:10 +00:00
|
|
|
}
|
2008-05-10 01:29:37 +00:00
|
|
|
# ifdef POLYMER
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMER)
|
2009-09-30 01:26:13 +00:00
|
|
|
{
|
|
|
|
if (!polymer_init())
|
2013-05-17 03:44:09 +00:00
|
|
|
rendmode = REND_POLYMOST;
|
2009-09-30 01:26:13 +00:00
|
|
|
}
|
2008-05-10 01:29:37 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
|
|
|
qsetmode = 200;
|
2016-06-21 00:34:41 +00:00
|
|
|
return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// nextpage
|
|
|
|
//
|
2018-04-12 21:02:51 +00:00
|
|
|
void videoNextPage(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
permfifotype *per;
|
|
|
|
|
|
|
|
//char snotbuf[32];
|
|
|
|
//j = 0; k = 0;
|
|
|
|
//for(i=0;i<4096;i++)
|
|
|
|
// if (waloff[i] != 0)
|
|
|
|
// {
|
2007-12-12 17:42:14 +00:00
|
|
|
// sprintf(snotbuf,"%d-%d",i,tilesizx[i]*tilesizy[i]);
|
2006-04-13 20:47:06 +00:00
|
|
|
// printext256((j>>5)*40+32,(j&31)*6,walock[i]>>3,-1,snotbuf,1);
|
|
|
|
// k += tilesizx[i]*tilesizy[i];
|
|
|
|
// j++;
|
|
|
|
// }
|
2007-12-12 17:42:14 +00:00
|
|
|
//sprintf(snotbuf,"Total: %d",k);
|
2006-04-13 20:47:06 +00:00
|
|
|
//printext256((j>>5)*40+32,(j&31)*6,31,-1,snotbuf,1);
|
|
|
|
|
2018-04-06 01:42:47 +00:00
|
|
|
if (in3dmode())
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=permtail; i!=permhead; i=((i+1)&(MAXPERMS-1)))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
per = &permfifo[i];
|
|
|
|
if ((per->pagesleft > 0) && (per->pagesleft <= numpages))
|
|
|
|
dorotatesprite(per->sx,per->sy,per->z,per->a,per->picnum,
|
2014-03-05 21:12:54 +00:00
|
|
|
per->dashade,per->dapalnum,per->dastat,per->daalpha,per->dablend,
|
2006-04-24 19:04:22 +00:00
|
|
|
per->cx1,per->cy1,per->cx2,per->cy2,per->uniqid);
|
|
|
|
}
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-06-25 18:34:52 +00:00
|
|
|
if (benchmarkScreenshot)
|
|
|
|
{
|
|
|
|
videoCaptureScreen("reference0000.png", 0);
|
|
|
|
benchmarkScreenshot = 0;
|
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
OSD_Draw();
|
2018-04-12 21:02:51 +00:00
|
|
|
videoShowFrame(0);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=permtail; i!=permhead; i=((i+1)&(MAXPERMS-1)))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
per = &permfifo[i];
|
|
|
|
if (per->pagesleft >= 130)
|
|
|
|
dorotatesprite(per->sx,per->sy,per->z,per->a,per->picnum,
|
2014-03-05 21:12:54 +00:00
|
|
|
per->dashade,per->dapalnum,per->dastat,per->daalpha,per->dablend,
|
2006-04-24 19:04:22 +00:00
|
|
|
per->cx1,per->cy1,per->cx2,per->cy2,per->uniqid);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (per->pagesleft&127) per->pagesleft--;
|
|
|
|
if (((per->pagesleft&127) == 0) && (i == permtail))
|
|
|
|
permtail = ((permtail+1)&(MAXPERMS-1));
|
|
|
|
}
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2018-04-05 04:39:30 +00:00
|
|
|
faketimerhandler();
|
2018-04-12 21:03:30 +00:00
|
|
|
cacheAgeEntries();
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-04-06 01:42:47 +00:00
|
|
|
omdtims = mdtims;
|
2018-04-12 21:02:51 +00:00
|
|
|
mdtims = timerGetTicks();
|
2008-02-02 16:38:30 +00:00
|
|
|
|
2018-04-06 01:42:47 +00:00
|
|
|
for (native_t i = 0; i < Numsprites; ++i)
|
2015-03-24 00:40:18 +00:00
|
|
|
if ((mdpause && spriteext[i].mdanimtims) || (spriteext[i].flags & SPREXT_NOMDANIM))
|
|
|
|
spriteext[i].mdanimtims += mdtims - omdtims;
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
beforedrawrooms = 1;
|
|
|
|
numframes++;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// qloadkvx
|
|
|
|
//
|
2011-01-16 00:23:39 +00:00
|
|
|
int32_t qloadkvx(int32_t voxindex, const char *filename)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-03-01 08:51:50 +00:00
|
|
|
const buildvfs_kfd fil = kopen4load(filename, 0);
|
|
|
|
if (fil == buildvfs_kfd_invalid)
|
2014-12-26 17:29:48 +00:00
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-26 17:29:48 +00:00
|
|
|
int32_t lengcnt = 0;
|
|
|
|
const int32_t lengtot = kfilelength(fil);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<MAXVOXMIPS; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-12-26 17:29:48 +00:00
|
|
|
int32_t dasiz;
|
|
|
|
kread(fil, &dasiz, 4); dasiz = B_LITTLE32(dasiz);
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Must store filenames to use cacheing system :(
|
2006-04-13 20:47:06 +00:00
|
|
|
voxlock[voxindex][i] = 200;
|
2018-04-12 21:03:30 +00:00
|
|
|
cacheAllocateBlock(&voxoff[voxindex][i], dasiz, &voxlock[voxindex][i]);
|
2014-12-26 17:29:48 +00:00
|
|
|
|
2016-06-21 00:34:25 +00:00
|
|
|
char *ptr = (char *) voxoff[voxindex][i];
|
2014-12-26 17:29:48 +00:00
|
|
|
kread(fil, ptr, dasiz);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
lengcnt += dasiz+4;
|
2014-12-26 17:29:48 +00:00
|
|
|
if (lengcnt >= lengtot-768)
|
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2014-12-26 17:29:48 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
kclose(fil);
|
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2007-12-12 17:42:14 +00:00
|
|
|
if (voxmodels[voxindex])
|
|
|
|
{
|
2006-04-13 20:47:06 +00:00
|
|
|
voxfree(voxmodels[voxindex]);
|
|
|
|
voxmodels[voxindex] = NULL;
|
|
|
|
}
|
2014-12-26 17:29:48 +00:00
|
|
|
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(voxfilenames[voxindex]);
|
2018-10-25 23:28:56 +00:00
|
|
|
voxfilenames[voxindex] = Xstrdup(filename);
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
2014-12-26 17:29:48 +00:00
|
|
|
|
2019-08-13 02:53:38 +00:00
|
|
|
g_haveVoxels = 1;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-10-25 05:43:50 +00:00
|
|
|
void vox_undefine(int32_t const tile)
|
|
|
|
{
|
|
|
|
ssize_t voxindex = tiletovox[tile];
|
|
|
|
if (voxindex < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
if (voxmodels[voxindex])
|
|
|
|
{
|
|
|
|
voxfree(voxmodels[voxindex]);
|
|
|
|
voxmodels[voxindex] = NULL;
|
|
|
|
}
|
|
|
|
DO_FREE_AND_NULL(voxfilenames[voxindex]);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
for (ssize_t j = 0; j < MAXVOXMIPS; ++j)
|
|
|
|
{
|
|
|
|
// CACHE1D_FREE
|
|
|
|
voxlock[voxindex][j] = 1;
|
|
|
|
voxoff[voxindex][j] = 0;
|
|
|
|
}
|
|
|
|
voxscale[voxindex] = 65536;
|
2019-09-17 05:07:28 +00:00
|
|
|
voxrotate[voxindex>>3] &= ~pow2char[voxindex&7];
|
2016-10-25 05:43:50 +00:00
|
|
|
tiletovox[tile] = -1;
|
|
|
|
|
|
|
|
// TODO: nextvoxid
|
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// inside
|
|
|
|
//
|
2013-06-22 11:31:16 +00:00
|
|
|
// See http://fabiensanglard.net/duke3d/build_engine_internals.php,
|
|
|
|
// "Inside details" for the idea behind the algorithm.
|
2019-09-22 19:26:07 +00:00
|
|
|
int32_t inside_ps(int32_t x, int32_t y, int16_t sectnum)
|
|
|
|
{
|
|
|
|
if (sectnum >= 0 && sectnum < numsectors)
|
|
|
|
{
|
|
|
|
int32_t cnt = 0;
|
|
|
|
auto wal = (uwallptr_t)&wall[sector[sectnum].wallptr];
|
|
|
|
int wallsleft = sector[sectnum].wallnum;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
vec2_t v1 = { wal->x - x, wal->y - y };
|
|
|
|
auto const &wal2 = *(uwallptr_t)&wall[wal->point2];
|
|
|
|
vec2_t v2 = { wal2.x - x, wal2.y - y };
|
|
|
|
|
|
|
|
if ((v1.y^v2.y) < 0)
|
|
|
|
cnt ^= (((v1.x^v2.x) < 0) ? (v1.x*v2.y<v2.x*v1.y)^(v1.y<v2.y) : (v1.x >= 0));
|
|
|
|
|
|
|
|
wal++;
|
|
|
|
}
|
|
|
|
while (--wallsleft);
|
|
|
|
|
|
|
|
return cnt;
|
|
|
|
}
|
2019-09-21 11:02:17 +00:00
|
|
|
|
2019-09-22 19:26:07 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-09-21 11:02:17 +00:00
|
|
|
int32_t inside_old(int32_t x, int32_t y, int16_t sectnum)
|
|
|
|
{
|
|
|
|
if (sectnum >= 0 && sectnum < numsectors)
|
|
|
|
{
|
|
|
|
uint32_t cnt = 0;
|
|
|
|
auto wal = (uwallptr_t)&wall[sector[sectnum].wallptr];
|
|
|
|
int wallsleft = sector[sectnum].wallnum;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
// Get the x and y components of the [tested point]-->[wall
|
|
|
|
// point{1,2}] vectors.
|
|
|
|
vec2_t v1 = { wal->x - x, wal->y - y };
|
|
|
|
auto const &wal2 = *(uwallptr_t)&wall[wal->point2];
|
|
|
|
vec2_t v2 = { wal2.x - x, wal2.y - y };
|
|
|
|
|
|
|
|
// If their signs differ[*], ...
|
|
|
|
//
|
|
|
|
// [*] where '-' corresponds to <0 and '+' corresponds to >=0.
|
|
|
|
// Equivalently, the branch is taken iff
|
|
|
|
// y1 != y2 AND y_m <= y < y_M,
|
|
|
|
// where y_m := min(y1, y2) and y_M := max(y1, y2).
|
|
|
|
if ((v1.y^v2.y) < 0)
|
|
|
|
cnt ^= (((v1.x^v2.x) >= 0) ? v1.x : (v1.x*v2.y-v2.x*v1.y)^v2.y);
|
|
|
|
|
|
|
|
wal++;
|
|
|
|
}
|
|
|
|
while (--wallsleft);
|
|
|
|
|
|
|
|
return cnt>>31;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t inside(int32_t x, int32_t y, int16_t sectnum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-09-22 19:26:07 +00:00
|
|
|
switch (enginecompatibility_mode)
|
|
|
|
{
|
|
|
|
case ENGINECOMPATIBILITY_NONE:
|
|
|
|
break;
|
|
|
|
case ENGINECOMPATIBILITY_19950829:
|
|
|
|
return inside_ps(x, y, sectnum);
|
|
|
|
default:
|
2019-09-21 11:02:17 +00:00
|
|
|
return inside_old(x, y, sectnum);
|
2019-09-22 19:26:07 +00:00
|
|
|
}
|
2019-04-18 17:23:35 +00:00
|
|
|
if ((unsigned)sectnum < (unsigned)numsectors)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-06-22 11:31:16 +00:00
|
|
|
uint32_t cnt1 = 0, cnt2 = 0;
|
2019-04-18 17:25:24 +00:00
|
|
|
|
|
|
|
auto wal = (uwallptr_t)&wall[sector[sectnum].wallptr];
|
|
|
|
int wallsleft = sector[sectnum].wallnum;
|
2013-06-22 11:31:15 +00:00
|
|
|
|
|
|
|
do
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-06-22 11:31:16 +00:00
|
|
|
// Get the x and y components of the [tested point]-->[wall
|
|
|
|
// point{1,2}] vectors.
|
2016-06-21 00:33:30 +00:00
|
|
|
vec2_t v1 = { wal->x - x, wal->y - y };
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const &wal2 = *(uwallptr_t)&wall[wal->point2];
|
2019-04-18 17:23:35 +00:00
|
|
|
vec2_t v2 = { wal2.x - x, wal2.y - y };
|
2013-06-22 11:31:16 +00:00
|
|
|
|
|
|
|
// First, test if the point is EXACTLY_ON_WALL_POINT.
|
2016-06-21 00:33:30 +00:00
|
|
|
if ((v1.x|v1.y) == 0 || (v2.x|v2.y)==0)
|
2013-06-22 11:31:16 +00:00
|
|
|
return 1;
|
2013-06-22 11:31:15 +00:00
|
|
|
|
|
|
|
// If their signs differ[*], ...
|
|
|
|
//
|
|
|
|
// [*] where '-' corresponds to <0 and '+' corresponds to >=0.
|
|
|
|
// Equivalently, the branch is taken iff
|
2013-06-28 14:07:33 +00:00
|
|
|
// y1 != y2 AND y_m <= y < y_M,
|
2013-06-22 11:31:15 +00:00
|
|
|
// where y_m := min(y1, y2) and y_M := max(y1, y2).
|
2016-06-21 00:33:30 +00:00
|
|
|
if ((v1.y^v2.y) < 0)
|
|
|
|
cnt1 ^= (((v1.x^v2.x) >= 0) ? v1.x : (v1.x*v2.y-v2.x*v1.y)^v2.y);
|
2013-06-22 11:31:16 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
v1.y--;
|
|
|
|
v2.y--;
|
2013-06-22 11:31:16 +00:00
|
|
|
|
|
|
|
// Now, do the same comparisons, but with the interval half-open on
|
|
|
|
// the other side! That is, take the branch iff
|
2013-06-28 14:07:33 +00:00
|
|
|
// y1 != y2 AND y_m < y <= y_M,
|
2013-06-22 11:31:16 +00:00
|
|
|
// For a rectangular sector, without EXACTLY_ON_WALL_POINT, this
|
|
|
|
// would still leave the lower left and upper right points
|
|
|
|
// "outside" the sector.
|
2016-06-21 00:33:30 +00:00
|
|
|
if ((v1.y^v2.y) < 0)
|
2013-06-22 11:31:16 +00:00
|
|
|
{
|
2016-06-21 00:33:30 +00:00
|
|
|
v1.x--;
|
|
|
|
v2.x--;
|
2013-06-22 11:31:15 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
cnt2 ^= (((v1.x^v2.x) >= 0) ? v1.x : (v1.x*v2.y-v2.x*v1.y)^v2.y);
|
2013-06-22 11:31:15 +00:00
|
|
|
}
|
|
|
|
|
2016-06-21 00:34:29 +00:00
|
|
|
wal++;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2016-06-21 00:34:29 +00:00
|
|
|
while (--wallsleft);
|
2013-06-22 11:31:15 +00:00
|
|
|
|
2013-06-22 11:31:16 +00:00
|
|
|
return (cnt1|cnt2)>>31;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2013-06-22 11:31:15 +00:00
|
|
|
|
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2017-01-23 11:20:03 +00:00
|
|
|
int32_t LUNATIC_FASTCALL getangle(int32_t xvect, int32_t yvect)
|
2012-09-02 14:12:01 +00:00
|
|
|
{
|
2015-01-11 04:56:58 +00:00
|
|
|
int32_t rv;
|
|
|
|
|
|
|
|
if ((xvect | yvect) == 0)
|
|
|
|
rv = 0;
|
|
|
|
else if (xvect == 0)
|
|
|
|
rv = 512 + ((yvect < 0) << 10);
|
|
|
|
else if (yvect == 0)
|
|
|
|
rv = ((xvect < 0) << 10);
|
|
|
|
else if (xvect == yvect)
|
|
|
|
rv = 256 + ((xvect < 0) << 10);
|
|
|
|
else if (xvect == -yvect)
|
|
|
|
rv = 768 + ((xvect > 0) << 10);
|
|
|
|
else if (klabs(xvect) > klabs(yvect))
|
|
|
|
rv = ((radarang[640 + scale(160, yvect, xvect)] >> 6) + ((xvect < 0) << 10)) & 2047;
|
|
|
|
else rv = ((radarang[640 - scale(160, xvect, yvect)] >> 6) + 512 + ((yvect < 0) << 10)) & 2047;
|
|
|
|
|
|
|
|
return rv;
|
2012-09-02 14:12:01 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// ksqrt
|
|
|
|
//
|
2012-07-01 22:11:14 +00:00
|
|
|
int32_t ksqrt(uint32_t num)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-04-12 11:59:26 +00:00
|
|
|
return nsqrtasm(num);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2013-02-16 18:53:15 +00:00
|
|
|
#ifdef LUNATIC
|
|
|
|
int32_t Mulscale(int32_t a, int32_t b, int32_t sh)
|
|
|
|
{
|
|
|
|
return mulscale(a, b, sh);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-11-17 19:46:43 +00:00
|
|
|
// Gets the BUILD unit height and z offset of a sprite.
|
|
|
|
// Returns the z offset, 'height' may be NULL.
|
2019-04-18 17:25:24 +00:00
|
|
|
int32_t spriteheightofsptr(uspriteptr_t spr, int32_t *height, int32_t alsotileyofs)
|
2011-03-02 21:21:47 +00:00
|
|
|
{
|
2012-11-17 19:46:43 +00:00
|
|
|
int32_t hei, zofs=0;
|
2012-11-25 13:18:57 +00:00
|
|
|
const int32_t picnum=spr->picnum, yrepeat=spr->yrepeat;
|
2011-03-23 17:41:01 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
hei = (tilesiz[picnum].y*yrepeat)<<2;
|
2019-03-19 17:08:12 +00:00
|
|
|
if (height != NULL)
|
|
|
|
*height = hei;
|
2011-03-02 21:21:47 +00:00
|
|
|
|
2012-11-25 13:18:57 +00:00
|
|
|
if (spr->cstat&128)
|
2012-11-17 19:46:43 +00:00
|
|
|
zofs = hei>>1;
|
2011-09-04 19:44:51 +00:00
|
|
|
|
2012-11-17 19:46:43 +00:00
|
|
|
// NOTE: a positive per-tile yoffset translates the sprite into the
|
|
|
|
// negative world z direction (i.e. upward).
|
|
|
|
if (alsotileyofs)
|
|
|
|
zofs -= picanm[picnum].yofs*yrepeat<<2;
|
2012-11-17 19:46:37 +00:00
|
|
|
|
2012-11-17 19:46:43 +00:00
|
|
|
return zofs;
|
2011-03-02 21:21:47 +00:00
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// setsprite
|
|
|
|
//
|
2012-11-05 02:49:08 +00:00
|
|
|
int32_t setsprite(int16_t spritenum, const vec3_t *newpos)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-01-19 00:58:39 +00:00
|
|
|
int16_t tempsectnum = sprite[spritenum].sectnum;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2017-06-23 03:58:48 +00:00
|
|
|
if ((void const *) newpos != (void *) &sprite[spritenum])
|
2019-08-13 14:44:00 +00:00
|
|
|
sprite[spritenum].pos = *newpos;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-11-05 02:49:08 +00:00
|
|
|
updatesector(newpos->x,newpos->y,&tempsectnum);
|
2007-08-16 23:25:24 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (tempsectnum < 0)
|
2016-06-21 00:34:41 +00:00
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
if (tempsectnum != sprite[spritenum].sectnum)
|
|
|
|
changespritesect(spritenum,tempsectnum);
|
|
|
|
|
2016-06-21 00:34:41 +00:00
|
|
|
return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2012-11-05 02:49:08 +00:00
|
|
|
int32_t setspritez(int16_t spritenum, const vec3_t *newpos)
|
2007-08-16 23:25:24 +00:00
|
|
|
{
|
2009-01-19 00:58:39 +00:00
|
|
|
int16_t tempsectnum = sprite[spritenum].sectnum;
|
2007-08-16 23:25:24 +00:00
|
|
|
|
2016-01-11 05:05:38 +00:00
|
|
|
if ((void const *)newpos != (void *)&sprite[spritenum])
|
2019-08-13 14:44:00 +00:00
|
|
|
sprite[spritenum].pos = *newpos;
|
2007-08-16 23:25:24 +00:00
|
|
|
|
2012-11-05 02:49:08 +00:00
|
|
|
updatesectorz(newpos->x,newpos->y,newpos->z,&tempsectnum);
|
2007-08-16 23:25:24 +00:00
|
|
|
|
|
|
|
if (tempsectnum < 0)
|
2016-06-21 00:34:41 +00:00
|
|
|
return -1;
|
2007-08-16 23:25:24 +00:00
|
|
|
if (tempsectnum != sprite[spritenum].sectnum)
|
|
|
|
changespritesect(spritenum,tempsectnum);
|
|
|
|
|
2016-06-21 00:34:41 +00:00
|
|
|
return 0;
|
2007-08-16 23:25:24 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// nextsectorneighborz
|
|
|
|
//
|
2012-08-26 22:15:02 +00:00
|
|
|
// -1: ceiling or up
|
|
|
|
// 1: floor or down
|
2014-03-25 21:04:33 +00:00
|
|
|
int32_t nextsectorneighborz(int16_t sectnum, int32_t refz, int16_t topbottom, int16_t direction)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-08-26 22:15:02 +00:00
|
|
|
int32_t nextz = (direction==1) ? INT32_MAX : INT32_MIN;
|
|
|
|
int32_t sectortouse = -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
auto wal = (uwallptr_t)&wall[sector[sectnum].wallptr];
|
2012-08-26 22:15:02 +00:00
|
|
|
int32_t i = sector[sectnum].wallnum;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2012-08-26 22:15:02 +00:00
|
|
|
const int32_t ns = wal->nextsector;
|
|
|
|
|
|
|
|
if (ns >= 0)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-01-31 21:12:56 +00:00
|
|
|
const int32_t testz = (topbottom == 1) ?
|
2012-08-26 22:15:02 +00:00
|
|
|
sector[ns].floorz : sector[ns].ceilingz;
|
|
|
|
|
2014-01-31 21:12:56 +00:00
|
|
|
const int32_t update = (direction == 1) ?
|
2014-03-25 21:04:33 +00:00
|
|
|
(nextz > testz && testz > refz) :
|
|
|
|
(nextz < testz && testz < refz);
|
2012-08-26 22:15:02 +00:00
|
|
|
|
2014-01-31 21:12:56 +00:00
|
|
|
if (update)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-08-26 22:15:02 +00:00
|
|
|
nextz = testz;
|
2014-01-31 21:12:56 +00:00
|
|
|
sectortouse = ns;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
2012-08-26 22:15:02 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
wal++;
|
|
|
|
i--;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (i != 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-01-31 21:12:56 +00:00
|
|
|
return sectortouse;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// cansee
|
|
|
|
//
|
2019-09-22 19:26:07 +00:00
|
|
|
int32_t cansee_old(int32_t xs, int32_t ys, int32_t zs, int16_t sectnums, int32_t xe, int32_t ye, int32_t ze, int16_t sectnume)
|
|
|
|
{
|
|
|
|
sectortype *sec, *nsec;
|
|
|
|
walltype *wal, *wal2;
|
|
|
|
int32_t intx, inty, intz, i, cnt, nextsector, dasectnum, dacnt, danum;
|
|
|
|
|
|
|
|
if ((xs == xe) && (ys == ye) && (sectnums == sectnume)) return 1;
|
|
|
|
|
|
|
|
clipsectorlist[0] = sectnums; 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];
|
|
|
|
if (lintersect(xs,ys,zs,xe,ye,ze,wal->x,wal->y,wal2->x,wal2->y,&intx,&inty,&intz) != 0)
|
|
|
|
{
|
|
|
|
nextsector = wal->nextsector; if (nextsector < 0) return 0;
|
|
|
|
|
|
|
|
if (intz <= sec->ceilingz) return 0;
|
|
|
|
if (intz >= sec->floorz) return 0;
|
|
|
|
nsec = §or[nextsector];
|
|
|
|
if (intz <= nsec->ceilingz) return 0;
|
|
|
|
if (intz >= nsec->floorz) return 0;
|
|
|
|
|
|
|
|
for(i=danum-1;i>=0;i--)
|
|
|
|
if (clipsectorlist[i] == nextsector) break;
|
|
|
|
if (i < 0) clipsectorlist[danum++] = nextsector;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (clipsectorlist[dacnt] == sectnume)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t cansee(int32_t x1, int32_t y1, int32_t z1, int16_t sect1, int32_t x2, int32_t y2, int32_t z2, int16_t sect2)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-09-22 19:26:07 +00:00
|
|
|
if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829)
|
|
|
|
return cansee_old(x1, y1, z2, sect1, x2, y2, z2, sect2);
|
2012-11-17 19:46:47 +00:00
|
|
|
int32_t dacnt, danum;
|
|
|
|
const int32_t x21 = x2-x1, y21 = y2-y1, z21 = z2-z1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-04-18 17:24:43 +00:00
|
|
|
static uint8_t sectbitmap[(MAXSECTORS+7)>>3];
|
2011-07-01 17:15:07 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
int16_t pendingsectnum;
|
|
|
|
vec3_t pendingvec;
|
|
|
|
|
2013-03-24 18:55:18 +00:00
|
|
|
// Negative sectnums can happen, for example if the player is using noclip.
|
|
|
|
// MAXSECTORS can happen from C-CON, e.g. canseespr with a sprite not in
|
|
|
|
// the game world.
|
|
|
|
if ((unsigned)sect1 >= MAXSECTORS || (unsigned)sect2 >= MAXSECTORS)
|
2012-02-14 23:13:38 +00:00
|
|
|
return 0;
|
|
|
|
|
2011-07-01 17:15:07 +00:00
|
|
|
Bmemset(&pendingvec, 0, sizeof(vec3_t)); // compiler-happy
|
2011-10-30 19:46:51 +00:00
|
|
|
#endif
|
2019-09-03 04:09:20 +00:00
|
|
|
Bmemset(sectbitmap, 0, sizeof(sectbitmap));
|
2011-07-01 17:15:07 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
restart_grand:
|
|
|
|
#endif
|
2012-11-17 19:46:47 +00:00
|
|
|
if (x1 == x2 && y1 == y2)
|
|
|
|
return (sect1 == sect2);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-12-25 15:33:02 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2011-07-01 17:15:07 +00:00
|
|
|
pendingsectnum = -1;
|
2011-12-25 15:33:02 +00:00
|
|
|
#endif
|
2019-08-04 02:51:50 +00:00
|
|
|
sectbitmap[sect1>>3] |= pow2char[sect1&7];
|
2006-04-13 20:47:06 +00:00
|
|
|
clipsectorlist[0] = sect1; danum = 1;
|
2011-07-01 17:15:07 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (dacnt=0; dacnt<danum; dacnt++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-11-17 19:46:47 +00:00
|
|
|
const int32_t dasectnum = clipsectorlist[dacnt];
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const sec = (usectorptr_t)§or[dasectnum];
|
|
|
|
uwallptr_t wal;
|
2016-08-27 01:41:21 +00:00
|
|
|
bssize_t cnt;
|
2011-07-01 17:15:07 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2012-11-17 19:46:47 +00:00
|
|
|
int32_t cfz1[2], cfz2[2]; // both wrt dasectnum
|
|
|
|
int16_t bn[2];
|
|
|
|
|
2011-07-01 17:15:07 +00:00
|
|
|
yax_getbunches(dasectnum, &bn[0], &bn[1]);
|
|
|
|
getzsofslope(dasectnum, x1,y1, &cfz1[0], &cfz1[1]);
|
|
|
|
getzsofslope(dasectnum, x2,y2, &cfz2[0], &cfz2[1]);
|
|
|
|
#endif
|
2019-04-18 17:25:24 +00:00
|
|
|
for (cnt=sec->wallnum,wal=(uwallptr_t)&wall[sec->wallptr]; cnt>0; cnt--,wal++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const wal2 = (uwallptr_t)&wall[wal->point2];
|
2012-11-17 19:46:47 +00:00
|
|
|
const int32_t x31 = wal->x-x1, x34 = wal->x-wal2->x;
|
|
|
|
const int32_t y31 = wal->y-y1, y34 = wal->y-wal2->y;
|
|
|
|
|
|
|
|
int32_t x, y, z, nexts, t, bot;
|
|
|
|
int32_t cfz[2];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
bot = y21*x34-x21*y34; if (bot <= 0) continue;
|
2012-06-13 23:13:39 +00:00
|
|
|
// XXX: OVERFLOW
|
2006-04-13 20:47:06 +00:00
|
|
|
t = y21*x31-x21*y31; if ((unsigned)t >= (unsigned)bot) continue;
|
2011-07-01 17:15:07 +00:00
|
|
|
t = y31*x34-x31*y34;
|
|
|
|
if ((unsigned)t >= (unsigned)bot)
|
|
|
|
{
|
2011-12-25 15:33:02 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2011-07-01 17:15:07 +00:00
|
|
|
if (t >= bot)
|
|
|
|
{
|
|
|
|
int32_t cf, frac, ns;
|
|
|
|
for (cf=0; cf<2; cf++)
|
|
|
|
{
|
|
|
|
if ((cf==0 && bn[0]>=0 && z1 > cfz1[0] && cfz2[0] > z2) ||
|
|
|
|
(cf==1 && bn[1]>=0 && z1 < cfz1[1] && cfz2[1] < z2))
|
|
|
|
{
|
|
|
|
if ((cfz1[cf]-cfz2[cf])-(z1-z2)==0)
|
|
|
|
continue;
|
|
|
|
frac = divscale24(z1-cfz1[cf], (z1-z2)-(cfz1[cf]-cfz2[cf]));
|
|
|
|
|
|
|
|
if ((unsigned)frac >= (1<<24))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
x = x1 + mulscale24(x21,frac);
|
|
|
|
y = y1 + mulscale24(y21,frac);
|
|
|
|
|
2012-10-01 17:52:18 +00:00
|
|
|
ns = yax_getneighborsect(x, y, dasectnum, cf);
|
2011-07-01 17:15:07 +00:00
|
|
|
if (ns < 0)
|
|
|
|
continue;
|
|
|
|
|
2019-08-04 02:51:50 +00:00
|
|
|
if (!(sectbitmap[ns>>3] & pow2char[ns&7]) && pendingsectnum==-1)
|
2011-07-01 17:15:07 +00:00
|
|
|
{
|
2019-08-04 02:51:50 +00:00
|
|
|
sectbitmap[ns>>3] |= pow2char[ns&7];
|
2011-07-01 17:15:07 +00:00
|
|
|
pendingsectnum = ns;
|
|
|
|
pendingvec.x = x;
|
|
|
|
pendingvec.y = y;
|
|
|
|
pendingvec.z = z1 + mulscale24(z21,frac);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
nexts = wal->nextsector;
|
2011-07-01 17:15:07 +00:00
|
|
|
|
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (bn[0]<0 && bn[1]<0)
|
|
|
|
#endif
|
2013-04-15 10:48:09 +00:00
|
|
|
if (nexts < 0 || wal->cstat&32)
|
|
|
|
return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
t = divscale24(t,bot);
|
|
|
|
x = x1 + mulscale24(x21,t);
|
|
|
|
y = y1 + mulscale24(y21,t);
|
|
|
|
z = z1 + mulscale24(z21,t);
|
|
|
|
|
2013-04-15 10:48:09 +00:00
|
|
|
getzsofslope(dasectnum, x,y, &cfz[0],&cfz[1]);
|
2011-07-01 17:15:07 +00:00
|
|
|
|
2013-04-12 11:59:22 +00:00
|
|
|
if (z <= cfz[0] || z >= cfz[1])
|
2011-07-01 17:15:07 +00:00
|
|
|
{
|
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
int32_t cf, frac;
|
|
|
|
|
|
|
|
// XXX: Is this any good?
|
|
|
|
for (cf=0; cf<2; cf++)
|
|
|
|
if ((cf==0 && bn[0]>=0 && z <= cfz[0] && z1 >= cfz1[0]) ||
|
|
|
|
(cf==1 && bn[1]>=0 && z >= cfz[1] && z1 <= cfz1[1]))
|
|
|
|
{
|
|
|
|
if ((cfz1[cf]-cfz[cf])-(z1-z)==0)
|
|
|
|
continue;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-07-01 17:15:07 +00:00
|
|
|
frac = divscale24(z1-cfz1[cf], (z1-z)-(cfz1[cf]-cfz[cf]));
|
|
|
|
t = mulscale24(t, frac);
|
|
|
|
|
|
|
|
if ((unsigned)t < (1<<24))
|
|
|
|
{
|
|
|
|
x = x1 + mulscale24(x21,t);
|
|
|
|
y = y1 + mulscale24(y21,t);
|
|
|
|
|
2012-10-01 17:52:18 +00:00
|
|
|
nexts = yax_getneighborsect(x, y, dasectnum, cf);
|
2011-07-01 17:15:07 +00:00
|
|
|
if (nexts >= 0)
|
|
|
|
goto add_nextsector;
|
|
|
|
}
|
|
|
|
}
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2011-07-01 17:15:07 +00:00
|
|
|
#endif
|
2013-04-15 10:48:09 +00:00
|
|
|
return 0;
|
2011-07-01 17:15:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef YAX_ENABLE
|
2013-04-15 10:48:09 +00:00
|
|
|
if (nexts < 0 || (wal->cstat&32))
|
2011-07-01 17:15:07 +00:00
|
|
|
return 0;
|
|
|
|
#endif
|
2013-04-15 10:48:09 +00:00
|
|
|
getzsofslope(nexts, x,y, &cfz[0],&cfz[1]);
|
|
|
|
if (z <= cfz[0] || z >= cfz[1])
|
|
|
|
return 0;
|
2011-07-01 17:15:07 +00:00
|
|
|
|
|
|
|
add_nextsector:
|
2019-08-04 02:51:50 +00:00
|
|
|
if (!(sectbitmap[nexts>>3] & pow2char[nexts&7]))
|
2011-07-01 17:15:07 +00:00
|
|
|
{
|
2019-08-04 02:51:50 +00:00
|
|
|
sectbitmap[nexts>>3] |= pow2char[nexts&7];
|
2011-07-01 17:15:07 +00:00
|
|
|
clipsectorlist[danum++] = nexts;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (pendingsectnum>=0)
|
|
|
|
{
|
|
|
|
sect1 = pendingsectnum;
|
|
|
|
x1 = pendingvec.x;
|
|
|
|
y1 = pendingvec.y;
|
|
|
|
z1 = pendingvec.z;
|
|
|
|
goto restart_grand;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2011-07-01 17:15:07 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2011-07-01 17:15:07 +00:00
|
|
|
|
2019-08-04 02:51:50 +00:00
|
|
|
if (sectbitmap[sect2>>3] & pow2char[sect2&7])
|
2011-07-01 17:15:07 +00:00
|
|
|
return 1;
|
|
|
|
|
2013-04-15 10:48:09 +00:00
|
|
|
return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2012-11-17 19:46:50 +00:00
|
|
|
// x1, y1: in/out
|
|
|
|
// rest x/y: out
|
2019-04-18 17:25:24 +00:00
|
|
|
void get_wallspr_points(uspriteptr_t const spr, int32_t *x1, int32_t *x2,
|
2014-01-24 21:39:02 +00:00
|
|
|
int32_t *y1, int32_t *y2)
|
2012-11-17 19:46:50 +00:00
|
|
|
{
|
|
|
|
//These lines get the 2 points of the rotated sprite
|
|
|
|
//Given: (x1, y1) starts out as the center point
|
|
|
|
|
|
|
|
const int32_t tilenum=spr->picnum, ang=spr->ang;
|
|
|
|
const int32_t xrepeat = spr->xrepeat;
|
|
|
|
int32_t xoff = picanm[tilenum].xofs + spr->xoffset;
|
|
|
|
int32_t k, l, dax, day;
|
|
|
|
|
|
|
|
if (spr->cstat&4)
|
|
|
|
xoff = -xoff;
|
|
|
|
|
|
|
|
dax = sintable[ang&2047]*xrepeat;
|
|
|
|
day = sintable[(ang+1536)&2047]*xrepeat;
|
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
l = tilesiz[tilenum].x;
|
2012-11-17 19:46:50 +00:00
|
|
|
k = (l>>1)+xoff;
|
|
|
|
|
|
|
|
*x1 -= mulscale16(dax,k);
|
|
|
|
*x2 = *x1 + mulscale16(dax,l);
|
|
|
|
|
|
|
|
*y1 -= mulscale16(day,k);
|
|
|
|
*y2 = *y1 + mulscale16(day,l);
|
|
|
|
}
|
|
|
|
|
|
|
|
// x1, y1: in/out
|
|
|
|
// rest x/y: out
|
2019-04-18 17:25:24 +00:00
|
|
|
void get_floorspr_points(uspriteptr_t const spr, int32_t px, int32_t py,
|
2014-01-24 21:39:02 +00:00
|
|
|
int32_t *x1, int32_t *x2, int32_t *x3, int32_t *x4,
|
|
|
|
int32_t *y1, int32_t *y2, int32_t *y3, int32_t *y4)
|
2012-11-17 19:46:50 +00:00
|
|
|
{
|
|
|
|
const int32_t tilenum = spr->picnum;
|
|
|
|
const int32_t cosang = sintable[(spr->ang+512)&2047];
|
|
|
|
const int32_t sinang = sintable[spr->ang&2047];
|
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
vec2_t const span = { tilesiz[tilenum].x, tilesiz[tilenum].y};
|
|
|
|
vec2_t const repeat = { spr->xrepeat, spr->yrepeat };
|
2012-11-17 19:46:50 +00:00
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
vec2_t adjofs = { picanm[tilenum].xofs + spr->xoffset, picanm[tilenum].yofs + spr->yoffset };
|
2012-11-17 19:46:50 +00:00
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
if (spr->cstat & 4)
|
|
|
|
adjofs.x = -adjofs.x;
|
|
|
|
|
|
|
|
if (spr->cstat & 8)
|
|
|
|
adjofs.y = -adjofs.y;
|
2012-11-17 19:46:50 +00:00
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
vec2_t const center = { ((span.x >> 1) + adjofs.x) * repeat.x, ((span.y >> 1) + adjofs.y) * repeat.y };
|
|
|
|
vec2_t const rspan = { span.x * repeat.x, span.y * repeat.y };
|
|
|
|
vec2_t const ofs = { -mulscale16(cosang, rspan.y), -mulscale16(sinang, rspan.y) };
|
2012-11-17 19:46:50 +00:00
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
*x1 += dmulscale16(sinang, center.x, cosang, center.y) - px;
|
|
|
|
*y1 += dmulscale16(sinang, center.y, -cosang, center.x) - py;
|
2012-11-17 19:46:50 +00:00
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
*x2 = *x1 - mulscale16(sinang, rspan.x);
|
|
|
|
*y2 = *y1 + mulscale16(cosang, rspan.x);
|
2012-11-17 19:46:50 +00:00
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
*x3 = *x2 + ofs.x, *x4 = *x1 + ofs.x;
|
|
|
|
*y3 = *y2 + ofs.y, *y4 = *y1 + ofs.y;
|
2012-11-17 19:46:50 +00:00
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// neartag
|
|
|
|
//
|
2014-01-31 21:13:00 +00:00
|
|
|
void neartag(int32_t xs, int32_t ys, int32_t zs, int16_t sectnum, int16_t ange,
|
|
|
|
int16_t *neartagsector, int16_t *neartagwall, int16_t *neartagsprite, int32_t *neartaghitdist, /* out */
|
|
|
|
int32_t neartagrange, uint8_t tagsearch,
|
2012-02-20 19:54:24 +00:00
|
|
|
int32_t (*blacklist_sprite_func)(int32_t))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-11-17 19:46:47 +00:00
|
|
|
int16_t tempshortcnt, tempshortnum;
|
|
|
|
|
|
|
|
const int32_t vx = mulscale14(sintable[(ange+2560)&2047],neartagrange);
|
|
|
|
const int32_t vy = mulscale14(sintable[(ange+2048)&2047],neartagrange);
|
2012-11-25 13:18:57 +00:00
|
|
|
vec3_t hitv = { xs+vx, ys+vy, 0 };
|
|
|
|
const vec3_t sv = { xs, ys, zs };
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
*neartagsector = -1; *neartagwall = -1; *neartagsprite = -1;
|
|
|
|
*neartaghitdist = 0;
|
|
|
|
|
2012-11-17 19:46:47 +00:00
|
|
|
if (sectnum < 0 || (tagsearch & 3) == 0)
|
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
clipsectorlist[0] = sectnum;
|
|
|
|
tempshortcnt = 0; tempshortnum = 1;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2012-11-17 19:46:47 +00:00
|
|
|
const int32_t dasector = clipsectorlist[tempshortcnt];
|
|
|
|
|
|
|
|
const int32_t startwall = sector[dasector].wallptr;
|
|
|
|
const int32_t endwall = startwall + sector[dasector].wallnum - 1;
|
2019-04-18 17:25:24 +00:00
|
|
|
uwallptr_t wal;
|
2012-11-17 19:46:47 +00:00
|
|
|
int32_t z;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
for (z=startwall,wal=(uwallptr_t)&wall[startwall]; z<=endwall; z++,wal++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const wal2 = (uwallptr_t)&wall[wal->point2];
|
2012-11-17 19:46:47 +00:00
|
|
|
const int32_t nextsector = wal->nextsector;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-11-17 19:46:47 +00:00
|
|
|
const int32_t x1=wal->x, y1=wal->y, x2=wal2->x, y2=wal2->y;
|
|
|
|
int32_t intx, inty, intz, good = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
if (nextsector >= 0)
|
|
|
|
{
|
|
|
|
if ((tagsearch&1) && sector[nextsector].lotag) good |= 1;
|
|
|
|
if ((tagsearch&2) && sector[nextsector].hitag) good |= 1;
|
|
|
|
}
|
2012-11-17 19:46:47 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((tagsearch&1) && wal->lotag) good |= 2;
|
|
|
|
if ((tagsearch&2) && wal->hitag) good |= 2;
|
|
|
|
|
|
|
|
if ((good == 0) && (nextsector < 0)) continue;
|
2014-08-23 10:28:18 +00:00
|
|
|
if ((coord_t)(x1-xs)*(y2-ys) < (coord_t)(x2-xs)*(y1-ys)) continue;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-11-25 13:18:57 +00:00
|
|
|
if (lintersect(xs,ys,zs,hitv.x,hitv.y,hitv.z,x1,y1,x2,y2,&intx,&inty,&intz) == 1)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
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]);
|
2012-11-25 13:18:57 +00:00
|
|
|
hitv.x = intx; hitv.y = inty; hitv.z = intz;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2012-11-17 19:46:47 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (nextsector >= 0)
|
|
|
|
{
|
2012-11-17 19:46:47 +00:00
|
|
|
int32_t zz;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (zz=tempshortnum-1; zz>=0; zz--)
|
2006-04-13 20:47:06 +00:00
|
|
|
if (clipsectorlist[zz] == nextsector) break;
|
|
|
|
if (zz < 0) clipsectorlist[tempshortnum++] = nextsector;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
tempshortcnt++;
|
|
|
|
|
2012-11-17 19:46:47 +00:00
|
|
|
if (tagsearch & 4)
|
|
|
|
continue; // skip sprite search
|
2011-03-04 08:50:58 +00:00
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=headspritesect[dasector]; z>=0; z=nextspritesect[z])
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const spr = (uspriteptr_t)&sprite[z];
|
2012-11-17 19:46:47 +00:00
|
|
|
|
2012-02-20 19:54:24 +00:00
|
|
|
if (blacklist_sprite_func && blacklist_sprite_func(z))
|
|
|
|
continue;
|
|
|
|
|
2012-11-25 13:18:57 +00:00
|
|
|
if (((tagsearch&1) && spr->lotag) || ((tagsearch&2) && spr->hitag))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-08-09 09:28:27 +00:00
|
|
|
if (try_facespr_intersect(spr, sv, vx, vy, 0, &hitv, 1))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-11-25 13:18:57 +00:00
|
|
|
*neartagsprite = z;
|
|
|
|
*neartaghitdist = dmulscale14(hitv.x-xs, sintable[(ange+2560)&2047],
|
|
|
|
hitv.y-ys, sintable[(ange+2048)&2047]);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (tempshortcnt < tempshortnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// dragpoint
|
|
|
|
//
|
2013-01-16 20:38:41 +00:00
|
|
|
// flags:
|
|
|
|
// 1: don't reset walbitmap[] (the bitmap of already dragged vertices)
|
|
|
|
// 2: In the editor, do wall[].cstat |= (1<<14) also for the lastwall().
|
|
|
|
void dragpoint(int16_t pointhighlight, int32_t dax, int32_t day, uint8_t flags)
|
2011-04-14 20:48:08 +00:00
|
|
|
{
|
2012-11-17 19:46:47 +00:00
|
|
|
int32_t i, numyaxwalls=0;
|
2011-04-14 20:48:08 +00:00
|
|
|
static int16_t yaxwalls[MAXWALLS];
|
|
|
|
|
2012-11-17 19:46:47 +00:00
|
|
|
uint8_t *const walbitmap = (uint8_t *)tempbuf;
|
2011-04-14 20:48:08 +00:00
|
|
|
|
2013-01-16 20:38:41 +00:00
|
|
|
if ((flags&1)==0)
|
2011-05-29 12:30:38 +00:00
|
|
|
Bmemset(walbitmap, 0, (numwalls+7)>>3);
|
2011-04-14 20:48:08 +00:00
|
|
|
yaxwalls[numyaxwalls++] = pointhighlight;
|
|
|
|
|
|
|
|
for (i=0; i<numyaxwalls; i++)
|
|
|
|
{
|
2012-11-17 19:46:47 +00:00
|
|
|
int32_t clockwise = 0;
|
|
|
|
int32_t w = yaxwalls[i];
|
|
|
|
const int32_t tmpstartwall = w;
|
2011-10-03 17:43:51 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
bssize_t cnt = MAXWALLS;
|
2011-04-14 20:48:08 +00:00
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
2012-11-17 19:46:47 +00:00
|
|
|
int32_t j, tmpcf;
|
|
|
|
|
2011-04-14 20:48:08 +00:00
|
|
|
wall[w].x = dax;
|
|
|
|
wall[w].y = day;
|
2019-08-04 02:51:50 +00:00
|
|
|
walbitmap[w>>3] |= pow2char[w&7];
|
2011-04-14 20:48:08 +00:00
|
|
|
|
|
|
|
for (YAX_ITER_WALLS(w, j, tmpcf))
|
|
|
|
{
|
2019-08-04 02:51:50 +00:00
|
|
|
if ((walbitmap[j>>3]&pow2char[j&7])==0)
|
2011-04-14 20:48:08 +00:00
|
|
|
{
|
2019-08-04 02:51:50 +00:00
|
|
|
walbitmap[j>>3] |= pow2char[j&7];
|
2011-04-14 20:48:08 +00:00
|
|
|
yaxwalls[numyaxwalls++] = j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-01 22:01:35 +00:00
|
|
|
if (!clockwise) //search points CCW
|
2011-04-14 20:48:08 +00:00
|
|
|
{
|
|
|
|
if (wall[w].nextwall >= 0)
|
|
|
|
w = wall[wall[w].nextwall].point2;
|
|
|
|
else
|
2011-10-03 17:43:51 +00:00
|
|
|
{
|
|
|
|
w = tmpstartwall;
|
2011-04-14 20:48:08 +00:00
|
|
|
clockwise = 1;
|
2011-10-03 17:43:51 +00:00
|
|
|
}
|
2011-04-14 20:48:08 +00:00
|
|
|
}
|
|
|
|
|
2011-11-01 22:01:35 +00:00
|
|
|
cnt--;
|
|
|
|
if (cnt==0)
|
|
|
|
{
|
|
|
|
initprintf("dragpoint %d: infloop!\n", pointhighlight);
|
|
|
|
i = numyaxwalls;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (clockwise)
|
2011-04-14 20:48:08 +00:00
|
|
|
{
|
2012-11-17 19:46:47 +00:00
|
|
|
int32_t thelastwall = lastwall(w);
|
2011-04-14 20:48:08 +00:00
|
|
|
if (wall[thelastwall].nextwall >= 0)
|
|
|
|
w = wall[thelastwall].nextwall;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-08-04 02:51:50 +00:00
|
|
|
if ((walbitmap[w>>3] & pow2char[w&7]))
|
2011-11-01 22:01:35 +00:00
|
|
|
{
|
|
|
|
if (clockwise)
|
|
|
|
break;
|
|
|
|
|
|
|
|
w = tmpstartwall;
|
|
|
|
clockwise = 1;
|
|
|
|
continue;
|
|
|
|
}
|
2011-04-14 20:48:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (editstatus)
|
|
|
|
{
|
2012-11-17 19:46:47 +00:00
|
|
|
int32_t w;
|
|
|
|
// TODO: extern a separate bitmap instead?
|
2011-04-14 20:48:08 +00:00
|
|
|
for (w=0; w<numwalls; w++)
|
2019-08-04 02:51:50 +00:00
|
|
|
if (walbitmap[w>>3] & pow2char[w&7])
|
2013-01-16 20:38:41 +00:00
|
|
|
{
|
2019-08-01 06:50:42 +00:00
|
|
|
editwall[w>>3] |= 1<<(w&7);
|
2013-01-16 20:38:41 +00:00
|
|
|
if (flags&2)
|
2019-08-01 06:50:42 +00:00
|
|
|
{
|
|
|
|
int wn = lastwall(w);
|
|
|
|
editwall[wn>>3] |= 1<<(wn&7);
|
|
|
|
}
|
2013-01-16 20:38:41 +00:00
|
|
|
}
|
2011-04-14 20:48:08 +00:00
|
|
|
}
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// lastwall
|
|
|
|
//
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t lastwall(int16_t point)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-11-17 19:46:47 +00:00
|
|
|
if (point > 0 && wall[point-1].point2 == point)
|
|
|
|
return point-1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-04-10 09:30:49 +00:00
|
|
|
int i = point, cnt = numwalls;
|
2006-04-13 20:47:06 +00:00
|
|
|
do
|
|
|
|
{
|
2015-07-11 23:07:47 +00:00
|
|
|
int const j = wall[i].point2;
|
|
|
|
|
|
|
|
if (j == point)
|
|
|
|
{
|
|
|
|
point = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
i = j;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2015-07-11 23:07:47 +00:00
|
|
|
while (--cnt);
|
2012-11-17 19:46:47 +00:00
|
|
|
|
2015-07-11 23:07:47 +00:00
|
|
|
return point;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
////////// UPDATESECTOR* FAMILY OF FUNCTIONS //////////
|
|
|
|
|
|
|
|
/* Different "is inside" predicates.
|
|
|
|
* NOTE: The redundant bound checks are expected to be optimized away in the
|
|
|
|
* inlined code. */
|
2010-10-28 20:17:22 +00:00
|
|
|
|
2019-04-18 17:24:10 +00:00
|
|
|
static FORCE_INLINE CONSTEXPR bool inside_exclude_p(int32_t const x, int32_t const y, int const sectnum, const uint8_t *excludesectbitmap)
|
2010-10-28 20:17:22 +00:00
|
|
|
{
|
2019-04-06 06:37:42 +00:00
|
|
|
return (sectnum>=0 && !bitmap_test(excludesectbitmap, sectnum) && inside_p(x, y, sectnum));
|
2016-06-21 00:33:30 +00:00
|
|
|
}
|
2013-04-12 11:59:22 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
/* NOTE: no bound check */
|
2019-04-06 06:37:42 +00:00
|
|
|
static inline bool inside_z_p(int32_t const x, int32_t const y, int32_t const z, int const sectnum)
|
2016-06-21 00:33:30 +00:00
|
|
|
{
|
|
|
|
int32_t cz, fz;
|
2019-04-06 06:37:42 +00:00
|
|
|
getzsofslope(sectnum, x, y, &cz, &fz);
|
|
|
|
return (z >= cz && z <= fz && inside_p(x, y, sectnum));
|
2016-06-21 00:33:30 +00:00
|
|
|
}
|
2012-10-01 17:52:09 +00:00
|
|
|
|
2019-08-27 06:52:42 +00:00
|
|
|
int32_t getwalldist(vec2_t const in, int const wallnum)
|
2019-04-18 17:24:30 +00:00
|
|
|
{
|
|
|
|
vec2_t closest;
|
2019-04-19 08:31:47 +00:00
|
|
|
getclosestpointonwall_internal(in, wallnum, &closest);
|
|
|
|
return klabs(closest.x - in.x) + klabs(closest.y - in.y);
|
2019-04-18 17:24:30 +00:00
|
|
|
}
|
|
|
|
|
2019-08-27 06:52:42 +00:00
|
|
|
int32_t getwalldist(vec2_t const in, int const wallnum, vec2_t * const out)
|
2019-08-04 02:51:59 +00:00
|
|
|
{
|
|
|
|
getclosestpointonwall_internal(in, wallnum, out);
|
|
|
|
return klabs(out->x - in.x) + klabs(out->y - in.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-08-27 06:52:42 +00:00
|
|
|
int32_t getsectordist(vec2_t const in, int const sectnum, vec2_t * const out /*= nullptr*/)
|
2019-04-18 17:24:30 +00:00
|
|
|
{
|
2019-04-19 08:31:47 +00:00
|
|
|
if (inside_p(in.x, in.y, sectnum))
|
|
|
|
{
|
|
|
|
if (out)
|
|
|
|
*out = in;
|
2019-04-18 17:24:30 +00:00
|
|
|
return 0;
|
2019-04-19 08:31:47 +00:00
|
|
|
}
|
2019-04-18 17:24:30 +00:00
|
|
|
|
|
|
|
int32_t distance = INT32_MAX;
|
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const sec = (usectorptr_t)§or[sectnum];
|
2019-04-18 17:24:30 +00:00
|
|
|
int const startwall = sec->wallptr;
|
|
|
|
int const endwall = sec->wallptr + sec->wallnum;
|
2019-04-18 17:25:24 +00:00
|
|
|
auto uwal = (uwallptr_t)&wall[startwall];
|
2019-04-19 08:31:47 +00:00
|
|
|
vec2_t closest = {};
|
2019-04-18 17:24:30 +00:00
|
|
|
|
|
|
|
for (int j = startwall; j < endwall; j++, uwal++)
|
|
|
|
{
|
2019-04-19 08:31:47 +00:00
|
|
|
vec2_t p;
|
|
|
|
int32_t const walldist = getwalldist(in, j, &p);
|
|
|
|
|
|
|
|
if (walldist < distance)
|
|
|
|
{
|
|
|
|
distance = walldist;
|
|
|
|
closest = p;
|
|
|
|
}
|
2019-04-18 17:24:30 +00:00
|
|
|
}
|
|
|
|
|
2019-04-19 08:31:47 +00:00
|
|
|
if (out)
|
|
|
|
*out = closest;
|
|
|
|
|
2019-04-18 17:24:30 +00:00
|
|
|
return distance;
|
|
|
|
}
|
|
|
|
|
2019-04-19 08:31:42 +00:00
|
|
|
int findwallbetweensectors(int sect1, int sect2)
|
2019-04-18 17:24:05 +00:00
|
|
|
{
|
|
|
|
if (sector[sect1].wallnum > sector[sect2].wallnum)
|
|
|
|
swaplong(§1, §2);
|
|
|
|
|
2019-04-19 08:31:42 +00:00
|
|
|
auto const sec = (usectorptr_t)§or[sect1];
|
|
|
|
int const last = sec->wallptr + sec->wallnum;
|
2019-04-18 17:24:05 +00:00
|
|
|
|
2019-04-19 08:31:42 +00:00
|
|
|
for (int i = sec->wallptr; i < last; i++)
|
|
|
|
if (wall[i].nextsector == sect2)
|
|
|
|
return i;
|
|
|
|
|
|
|
|
return -1;
|
2019-04-18 17:24:05 +00:00
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// updatesector[z]
|
|
|
|
//
|
2019-04-06 06:37:42 +00:00
|
|
|
void updatesector(int32_t const x, int32_t const y, int16_t * const sectnum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-09-22 19:26:07 +00:00
|
|
|
if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE)
|
2019-07-29 15:12:01 +00:00
|
|
|
{
|
|
|
|
if (inside_p(x, y, *sectnum))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((unsigned)*sectnum < (unsigned)numsectors)
|
|
|
|
{
|
|
|
|
const uwalltype *wal = (uwalltype *)&wall[sector[*sectnum].wallptr];
|
|
|
|
int wallsleft = sector[*sectnum].wallnum;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
int const next = wal->nextsector;
|
|
|
|
if (inside_p(x, y, next))
|
|
|
|
SET_AND_RETURN(*sectnum, next);
|
|
|
|
wal++;
|
|
|
|
}
|
|
|
|
while (--wallsleft);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int16_t sect = *sectnum;
|
|
|
|
updatesectorneighbor(x, y, §, INITIALUPDATESECTORDIST, MAXUPDATESECTORDIST);
|
|
|
|
if (sect != -1)
|
|
|
|
SET_AND_RETURN(*sectnum, sect);
|
|
|
|
}
|
2012-01-14 14:48:30 +00:00
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
// we need to support passing in a sectnum of -1, unfortunately
|
|
|
|
|
|
|
|
for (int i = numsectors - 1; i >= 0; --i)
|
|
|
|
if (inside_p(x, y, i))
|
|
|
|
SET_AND_RETURN(*sectnum, i);
|
|
|
|
|
2012-01-14 14:48:30 +00:00
|
|
|
*sectnum = -1;
|
|
|
|
}
|
|
|
|
|
2019-04-06 06:37:42 +00:00
|
|
|
void updatesectorexclude(int32_t const x, int32_t const y, int16_t * const sectnum, const uint8_t * const excludesectbitmap)
|
2010-11-27 22:12:24 +00:00
|
|
|
{
|
2012-10-01 17:52:09 +00:00
|
|
|
if (inside_exclude_p(x, y, *sectnum, excludesectbitmap))
|
2010-11-27 22:12:24 +00:00
|
|
|
return;
|
|
|
|
|
2012-10-01 17:52:09 +00:00
|
|
|
if (*sectnum >= 0 && *sectnum < numsectors)
|
2010-11-27 22:12:24 +00:00
|
|
|
{
|
2019-04-18 17:25:24 +00:00
|
|
|
auto wal = (uwallptr_t)&wall[sector[*sectnum].wallptr];
|
2016-06-21 00:34:29 +00:00
|
|
|
int wallsleft = sector[*sectnum].wallnum;
|
2012-10-01 17:52:09 +00:00
|
|
|
|
2010-11-27 22:12:24 +00:00
|
|
|
do
|
|
|
|
{
|
2016-06-21 00:34:29 +00:00
|
|
|
int const next = wal->nextsector;
|
|
|
|
if (inside_exclude_p(x, y, next, excludesectbitmap))
|
|
|
|
SET_AND_RETURN(*sectnum, next);
|
|
|
|
wal++;
|
2010-11-27 22:12:24 +00:00
|
|
|
}
|
2016-06-21 00:34:29 +00:00
|
|
|
while (--wallsleft);
|
2010-11-27 22:12:24 +00:00
|
|
|
}
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=numsectors-1; i>=0; --i)
|
2012-10-01 17:52:09 +00:00
|
|
|
if (inside_exclude_p(x, y, i, excludesectbitmap))
|
|
|
|
SET_AND_RETURN(*sectnum, i);
|
2010-11-27 22:12:24 +00:00
|
|
|
|
|
|
|
*sectnum = -1;
|
|
|
|
}
|
|
|
|
|
2011-09-01 18:38:13 +00:00
|
|
|
// new: if *sectnum >= MAXSECTORS, *sectnum-=MAXSECTORS is considered instead
|
|
|
|
// as starting sector and the 'initial' z check is skipped
|
|
|
|
// (not initial anymore because it follows the sector updating due to TROR)
|
|
|
|
|
2019-04-06 06:38:10 +00:00
|
|
|
void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum)
|
2019-07-19 01:46:32 +00:00
|
|
|
{
|
2019-09-22 19:26:07 +00:00
|
|
|
if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE)
|
2019-07-29 15:12:01 +00:00
|
|
|
{
|
|
|
|
if ((uint32_t)(*sectnum) < 2*MAXSECTORS)
|
|
|
|
{
|
|
|
|
int32_t nofirstzcheck = 0;
|
|
|
|
|
|
|
|
if (*sectnum >= MAXSECTORS)
|
|
|
|
{
|
|
|
|
*sectnum -= MAXSECTORS;
|
|
|
|
nofirstzcheck = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// this block used to be outside the "if" and caused crashes in Polymost Mapster32
|
|
|
|
int32_t cz, fz;
|
|
|
|
getzsofslope(*sectnum, x, y, &cz, &fz);
|
|
|
|
|
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (z < cz)
|
|
|
|
{
|
|
|
|
int const next = yax_getneighborsect(x, y, *sectnum, YAX_CEILING);
|
|
|
|
if (next >= 0 && z >= getceilzofslope(next, x, y))
|
|
|
|
SET_AND_RETURN(*sectnum, next);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (z > fz)
|
|
|
|
{
|
|
|
|
int const next = yax_getneighborsect(x, y, *sectnum, YAX_FLOOR);
|
|
|
|
if (next >= 0 && z <= getflorzofslope(next, x, y))
|
|
|
|
SET_AND_RETURN(*sectnum, next);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (nofirstzcheck || (z >= cz && z <= fz))
|
|
|
|
if (inside_p(x, y, *sectnum))
|
|
|
|
return;
|
|
|
|
|
|
|
|
uwalltype const * wal = (uwalltype *)&wall[sector[*sectnum].wallptr];
|
|
|
|
int wallsleft = sector[*sectnum].wallnum;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
// YAX: TODO: check neighboring sectors here too?
|
|
|
|
int const next = wal->nextsector;
|
|
|
|
if (next>=0 && inside_z_p(x,y,z, next))
|
|
|
|
SET_AND_RETURN(*sectnum, next);
|
|
|
|
|
|
|
|
wal++;
|
|
|
|
}
|
|
|
|
while (--wallsleft);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int16_t sect = *sectnum;
|
|
|
|
updatesectorneighborz(x, y, z, §, INITIALUPDATESECTORDIST, MAXUPDATESECTORDIST);
|
|
|
|
if (sect != -1)
|
|
|
|
SET_AND_RETURN(*sectnum, sect);
|
|
|
|
}
|
2019-07-19 01:46:32 +00:00
|
|
|
|
|
|
|
// we need to support passing in a sectnum of -1, unfortunately
|
|
|
|
for (int i = numsectors - 1; i >= 0; --i)
|
|
|
|
if (inside_z_p(x, y, z, i))
|
|
|
|
SET_AND_RETURN(*sectnum, i);
|
|
|
|
|
|
|
|
*sectnum = -1;
|
|
|
|
}
|
|
|
|
|
2019-07-19 03:14:53 +00:00
|
|
|
void updatesectorneighbor(int32_t const x, int32_t const y, int16_t * const sectnum, int32_t initialMaxDistance /*= INITIALUPDATESECTORDIST*/, int32_t maxDistance /*= MAXUPDATESECTORDIST*/)
|
2019-07-19 01:46:32 +00:00
|
|
|
{
|
|
|
|
int const initialsectnum = *sectnum;
|
|
|
|
|
|
|
|
if ((unsigned)initialsectnum < (unsigned)numsectors && getsectordist({x, y}, initialsectnum) <= initialMaxDistance)
|
|
|
|
{
|
|
|
|
if (inside_p(x, y, initialsectnum))
|
|
|
|
return;
|
|
|
|
|
|
|
|
static int16_t sectlist[MAXSECTORS];
|
|
|
|
static uint8_t sectbitmap[(MAXSECTORS+7)>>3];
|
|
|
|
int16_t nsecs;
|
|
|
|
|
|
|
|
bfirst_search_init(sectlist, sectbitmap, &nsecs, MAXSECTORS, initialsectnum);
|
|
|
|
|
|
|
|
for (int sectcnt=0; sectcnt<nsecs; sectcnt++)
|
|
|
|
{
|
|
|
|
int const listsectnum = sectlist[sectcnt];
|
|
|
|
|
|
|
|
if (inside_p(x, y, listsectnum))
|
|
|
|
SET_AND_RETURN(*sectnum, listsectnum);
|
|
|
|
|
|
|
|
auto const sec = §or[listsectnum];
|
|
|
|
int const startwall = sec->wallptr;
|
|
|
|
int const endwall = sec->wallptr + sec->wallnum;
|
|
|
|
auto uwal = (uwallptr_t)&wall[startwall];
|
|
|
|
|
|
|
|
for (int j=startwall; j<endwall; j++, uwal++)
|
|
|
|
if (uwal->nextsector >= 0 && getsectordist({x, y}, uwal->nextsector) <= maxDistance)
|
|
|
|
bfirst_search_try(sectlist, sectbitmap, &nsecs, uwal->nextsector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*sectnum = -1;
|
|
|
|
}
|
|
|
|
|
2019-07-19 03:14:53 +00:00
|
|
|
void updatesectorneighborz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum, int32_t initialMaxDistance /*= 0*/, int32_t maxDistance /*= 0*/)
|
2019-04-06 06:38:00 +00:00
|
|
|
{
|
|
|
|
bool nofirstzcheck = false;
|
|
|
|
|
2019-04-20 21:57:02 +00:00
|
|
|
if (*sectnum >= MAXSECTORS && *sectnum - MAXSECTORS < numsectors)
|
2019-04-06 06:38:00 +00:00
|
|
|
{
|
2019-04-18 17:25:11 +00:00
|
|
|
*sectnum -= MAXSECTORS;
|
|
|
|
nofirstzcheck = true;
|
|
|
|
}
|
2019-04-06 06:38:00 +00:00
|
|
|
|
2019-04-20 21:57:02 +00:00
|
|
|
uint32_t const correctedsectnum = (unsigned)*sectnum;
|
2019-04-06 06:38:00 +00:00
|
|
|
|
2019-07-19 01:46:32 +00:00
|
|
|
if (correctedsectnum < (unsigned)numsectors && getsectordist({x, y}, correctedsectnum) <= initialMaxDistance)
|
2019-04-18 17:25:11 +00:00
|
|
|
{
|
|
|
|
int32_t cz, fz;
|
|
|
|
getzsofslope(correctedsectnum, x, y, &cz, &fz);
|
2019-04-06 06:38:00 +00:00
|
|
|
|
|
|
|
#ifdef YAX_ENABLE
|
2019-04-18 17:25:11 +00:00
|
|
|
if (z < cz)
|
|
|
|
{
|
|
|
|
int const next = yax_getneighborsect(x, y, correctedsectnum, YAX_CEILING);
|
|
|
|
if (next >= 0 && z >= getceilzofslope(next, x, y))
|
|
|
|
SET_AND_RETURN(*sectnum, next);
|
|
|
|
}
|
2019-04-06 06:38:00 +00:00
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
if (z > fz)
|
|
|
|
{
|
|
|
|
int const next = yax_getneighborsect(x, y, correctedsectnum, YAX_FLOOR);
|
|
|
|
if (next >= 0 && z <= getflorzofslope(next, x, y))
|
|
|
|
SET_AND_RETURN(*sectnum, next);
|
|
|
|
}
|
2019-04-06 06:38:00 +00:00
|
|
|
#endif
|
2019-04-20 21:57:02 +00:00
|
|
|
if ((nofirstzcheck || (z >= cz && z <= fz)) && inside_p(x, y, *sectnum))
|
2019-04-06 06:38:00 +00:00
|
|
|
return;
|
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
static int16_t sectlist[MAXSECTORS];
|
|
|
|
static uint8_t sectbitmap[(MAXSECTORS+7)>>3];
|
2019-05-19 03:52:54 +00:00
|
|
|
int16_t nsecs;
|
2019-04-06 06:38:00 +00:00
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
bfirst_search_init(sectlist, sectbitmap, &nsecs, MAXSECTORS, correctedsectnum);
|
2019-04-06 06:38:00 +00:00
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
for (int sectcnt=0; sectcnt<nsecs; sectcnt++)
|
|
|
|
{
|
|
|
|
int const listsectnum = sectlist[sectcnt];
|
|
|
|
|
|
|
|
if (inside_z_p(x, y, z, listsectnum))
|
|
|
|
SET_AND_RETURN(*sectnum, listsectnum);
|
2019-04-06 06:38:00 +00:00
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
auto const sec = §or[listsectnum];
|
|
|
|
int const startwall = sec->wallptr;
|
|
|
|
int const endwall = sec->wallptr + sec->wallnum;
|
2019-04-18 17:25:24 +00:00
|
|
|
auto uwal = (uwallptr_t)&wall[startwall];
|
2019-04-06 06:38:00 +00:00
|
|
|
|
2019-04-18 17:25:11 +00:00
|
|
|
for (int j=startwall; j<endwall; j++, uwal++)
|
2019-07-19 01:46:32 +00:00
|
|
|
if (uwal->nextsector >= 0 && getsectordist({x, y}, uwal->nextsector) <= maxDistance)
|
2019-04-18 17:25:11 +00:00
|
|
|
bfirst_search_try(sectlist, sectbitmap, &nsecs, uwal->nextsector);
|
|
|
|
}
|
2019-04-06 06:38:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*sectnum = -1;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// rotatepoint
|
|
|
|
//
|
2019-04-18 17:24:10 +00:00
|
|
|
void rotatepoint(vec2_t const pivot, vec2_t p, int16_t const daang, vec2_t * const p2)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-05-26 00:47:54 +00:00
|
|
|
int const dacos = sintable[(daang+2560)&2047];
|
|
|
|
int const dasin = sintable[(daang+2048)&2047];
|
|
|
|
p.x -= pivot.x;
|
|
|
|
p.y -= pivot.y;
|
|
|
|
p2->x = dmulscale14(p.x, dacos, -p.y, dasin) + pivot.x;
|
|
|
|
p2->y = dmulscale14(p.y, dacos, p.x, dasin) + pivot.y;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// getmousevalues
|
|
|
|
//
|
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
void mouseGetValues(int32_t *mousx, int32_t *mousy, int32_t *bstatus)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-11-18 18:08:53 +00:00
|
|
|
mouseReadPos(mousx, mousy);
|
|
|
|
*bstatus = mouseReadButtons();
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-24 23:33:17 +00:00
|
|
|
#if KRANDDEBUG
|
|
|
|
# include <execinfo.h>
|
|
|
|
# define KRD_MAXCALLS 262144
|
|
|
|
# define KRD_DEPTH 8
|
2010-02-13 21:46:42 +00:00
|
|
|
static int32_t krd_numcalls=0;
|
2010-01-24 23:33:17 +00:00
|
|
|
static void *krd_fromwhere[KRD_MAXCALLS][KRD_DEPTH];
|
|
|
|
static int32_t krd_enabled=0;
|
|
|
|
|
2010-02-13 21:46:42 +00:00
|
|
|
void krd_enable(int which) // 0: disable, 1: rec, 2: play
|
2010-01-24 23:33:17 +00:00
|
|
|
{
|
2010-02-13 21:46:42 +00:00
|
|
|
krd_enabled = which;
|
|
|
|
|
|
|
|
if (which)
|
|
|
|
Bmemset(krd_fromwhere, 0, sizeof(krd_fromwhere));
|
2010-01-24 23:33:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int32_t krd_print(const char *filename)
|
|
|
|
{
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_FILE fp;
|
2010-02-13 21:46:42 +00:00
|
|
|
int32_t i, j;
|
2010-01-24 23:33:17 +00:00
|
|
|
|
2010-02-13 21:46:42 +00:00
|
|
|
if (!krd_enabled) return 1;
|
2010-01-24 23:33:17 +00:00
|
|
|
krd_enabled = 0;
|
2010-02-13 21:46:42 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
fp = buildvfs_fopen_write(filename);
|
2010-02-13 21:46:42 +00:00
|
|
|
if (!fp) { OSD_Printf("krd_print (2): fopen"); return 1; }
|
2010-01-24 23:33:17 +00:00
|
|
|
|
|
|
|
for (i=0; i<krd_numcalls; i++)
|
|
|
|
{
|
|
|
|
for (j=1;; j++) // skip self entry
|
|
|
|
{
|
|
|
|
if (j>=KRD_DEPTH || krd_fromwhere[i][j]==NULL)
|
|
|
|
{
|
2010-02-13 21:46:42 +00:00
|
|
|
fprintf(fp, "\n");
|
2010-01-24 23:33:17 +00:00
|
|
|
break;
|
|
|
|
}
|
2010-02-13 21:46:42 +00:00
|
|
|
fprintf(fp, " [%p]", krd_fromwhere[i][j]);
|
2010-01-24 23:33:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
krd_numcalls = 0;
|
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_fclose(fp);
|
2010-01-24 23:33:17 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2014-11-22 18:37:24 +00:00
|
|
|
#endif // KRANDDEBUG
|
2010-01-24 23:33:17 +00:00
|
|
|
|
2014-11-22 18:37:24 +00:00
|
|
|
#if KRANDDEBUG || defined LUNATIC
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// krand
|
|
|
|
//
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t krand(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2008-11-20 14:06:36 +00:00
|
|
|
// randomseed = (randomseed*27584621)+1;
|
|
|
|
randomseed = (randomseed * 1664525ul) + 221297ul;
|
2014-11-22 18:37:24 +00:00
|
|
|
#ifdef KRANDDEBUG
|
2010-01-24 23:33:17 +00:00
|
|
|
if (krd_enabled)
|
|
|
|
if (krd_numcalls < KRD_MAXCALLS)
|
|
|
|
{
|
2010-02-13 21:46:42 +00:00
|
|
|
backtrace(krd_fromwhere[krd_numcalls], KRD_DEPTH);
|
2010-01-24 23:33:17 +00:00
|
|
|
krd_numcalls++;
|
|
|
|
}
|
2014-11-22 18:37:24 +00:00
|
|
|
#endif
|
2012-11-17 19:46:47 +00:00
|
|
|
return ((uint32_t)randomseed)>>16;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2014-11-22 18:37:24 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-08-16 21:48:56 +00:00
|
|
|
int32_t setaspect_new_use_dimen = 0;
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
void videoSetCorrectedAspect()
|
2010-10-17 14:49:39 +00:00
|
|
|
{
|
2018-04-12 21:03:12 +00:00
|
|
|
if (r_usenewaspect && newaspect_enable && videoGetRenderMode() != REND_POLYMER)
|
2010-10-17 14:49:39 +00:00
|
|
|
{
|
2019-02-18 22:02:33 +00:00
|
|
|
// In DOS the game world is displayed with an aspect of 1.28 instead 1.333,
|
|
|
|
// meaning we have to stretch it by a factor of 1.25 instead of 1.2
|
|
|
|
// to get perfect squares
|
|
|
|
int32_t yx = (65536 * 5) / 4;
|
|
|
|
int32_t vr, y, x;
|
2010-10-17 14:49:39 +00:00
|
|
|
|
2012-08-16 21:48:56 +00:00
|
|
|
const int32_t xd = setaspect_new_use_dimen ? xdimen : xdim;
|
|
|
|
const int32_t yd = setaspect_new_use_dimen ? ydimen : ydim;
|
|
|
|
|
2012-09-15 15:28:21 +00:00
|
|
|
if (fullscreen && !setaspect_new_use_dimen)
|
2010-10-17 14:49:39 +00:00
|
|
|
{
|
2012-09-15 15:28:21 +00:00
|
|
|
const int32_t screenw = r_screenxy/100;
|
|
|
|
const int32_t screenh = r_screenxy%100;
|
2012-04-09 19:22:31 +00:00
|
|
|
|
2012-09-15 15:28:21 +00:00
|
|
|
if (screenw==0 || screenh==0)
|
2012-08-24 18:51:49 +00:00
|
|
|
{
|
|
|
|
// Assume square pixel aspect.
|
2012-09-15 15:28:21 +00:00
|
|
|
x = xd;
|
|
|
|
y = yd;
|
2012-08-24 18:51:49 +00:00
|
|
|
}
|
2012-09-15 15:28:21 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
int32_t pixratio;
|
2012-04-09 19:22:31 +00:00
|
|
|
|
2012-09-15 15:28:21 +00:00
|
|
|
x = screenw;
|
|
|
|
y = screenh;
|
|
|
|
|
|
|
|
pixratio = divscale16(xdim*screenh, ydim*screenw);
|
|
|
|
yx = divscale16(yx, pixratio);
|
|
|
|
}
|
2010-10-17 14:49:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-08-16 21:48:56 +00:00
|
|
|
x = xd;
|
|
|
|
y = yd;
|
2010-10-17 14:49:39 +00:00
|
|
|
}
|
|
|
|
|
2012-04-09 19:22:31 +00:00
|
|
|
vr = divscale16(x*3, y*4);
|
2010-10-17 14:49:39 +00:00
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
renderSetAspect(vr, yx);
|
2010-10-17 14:49:39 +00:00
|
|
|
}
|
|
|
|
else
|
2018-04-12 21:03:47 +00:00
|
|
|
renderSetAspect(65536, divscale16(ydim*320, xdim*200));
|
2010-10-17 14:49:39 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// setview
|
|
|
|
//
|
2018-04-12 21:02:51 +00:00
|
|
|
void videoSetViewableArea(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
windowxy1.x = x1; wx1 = (x1<<12);
|
|
|
|
windowxy1.y = y1; wy1 = (y1<<12);
|
|
|
|
windowxy2.x = x2; wx2 = ((x2+1)<<12);
|
|
|
|
windowxy2.y = y2; wy2 = ((y2+1)<<12);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
xdimen = (x2-x1)+1; halfxdimen = (xdimen>>1);
|
|
|
|
xdimenrecip = divscale32(1L,xdimen);
|
|
|
|
ydimen = (y2-y1)+1;
|
|
|
|
|
2014-10-25 03:27:35 +00:00
|
|
|
fxdimen = (float) xdimen;
|
2014-11-28 08:14:00 +00:00
|
|
|
#ifdef USE_OPENGL
|
2014-10-25 03:27:35 +00:00
|
|
|
fydimen = (float) ydimen;
|
|
|
|
#endif
|
2018-04-12 21:02:51 +00:00
|
|
|
videoSetCorrectedAspect();
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<windowxy1.x; i++) { startumost[i] = 1, startdmost[i] = 0; }
|
2016-06-21 00:34:18 +00:00
|
|
|
Bassert(windowxy2.x < xdim); // xdim is the number of alloc'd elements in start*most[].
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=windowxy1.x; i<=windowxy2.x; i++)
|
2016-06-21 00:34:18 +00:00
|
|
|
{ startumost[i] = windowxy1.y, startdmost[i] = windowxy2.y+1; }
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=windowxy2.x+1; i<xdim; i++) { startumost[i] = 1, startdmost[i] = 0; }
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// setaspect
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
void renderSetAspect(int32_t daxrange, int32_t daaspect)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
viewingrange = daxrange;
|
2011-10-17 18:41:38 +00:00
|
|
|
viewingrangerecip = divscale32(1,daxrange);
|
2016-10-03 02:43:42 +00:00
|
|
|
#ifdef USE_OPENGL
|
|
|
|
fviewingrange = (float) daxrange;
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
yxaspect = daaspect;
|
|
|
|
xyaspect = divscale32(1,yxaspect);
|
|
|
|
xdimenscale = scale(xdimen,yxaspect,320);
|
|
|
|
xdimscale = scale(320,xyaspect,xdimen);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// flushperms
|
|
|
|
//
|
2018-04-12 21:04:00 +00:00
|
|
|
void renderFlushPerms(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
permhead = permtail = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// rotatesprite
|
|
|
|
//
|
2013-03-25 04:32:24 +00:00
|
|
|
void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
|
2019-09-22 21:15:46 +00:00
|
|
|
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
|
2014-03-05 21:12:54 +00:00
|
|
|
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t i;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-03-25 22:01:21 +00:00
|
|
|
if ((unsigned)picnum >= MAXTILES)
|
|
|
|
return;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((cx1 > cx2) || (cy1 > cy2)) return;
|
|
|
|
if (z <= 16) return;
|
2019-06-25 11:30:22 +00:00
|
|
|
tileUpdatePicnum(&picnum, (int16_t)0xc000);
|
2014-09-30 04:14:21 +00:00
|
|
|
if ((tilesiz[picnum].x <= 0) || (tilesiz[picnum].y <= 0)) return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-08-19 12:57:57 +00:00
|
|
|
// Experimental / development bits. ONLY FOR INTERNAL USE!
|
2012-08-19 13:02:37 +00:00
|
|
|
// bit RS_CENTERORIGIN: see dorotspr_handle_bit2
|
2012-08-19 12:57:57 +00:00
|
|
|
////////////////////
|
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if (((dastat & RS_PERM) == 0) || (numpages < 2) || (beforedrawrooms != 0))
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2014-03-05 21:12:54 +00:00
|
|
|
dorotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,daalpha,dablend,cx1,cy1,cx2,cy2,guniqhudid);
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat & RS_NOMASK) && (cx1 <= 0) && (cy1 <= 0) && (cx2 >= xdim-1) && (cy2 >= ydim-1) &&
|
|
|
|
(sx == (160<<16)) && (sy == (100<<16)) && (z == 65536L) && (a == 0) && ((dastat&RS_TRANS1) == 0))
|
2006-04-13 20:47:06 +00:00
|
|
|
permhead = permtail = 0;
|
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if ((dastat & RS_PERM) == 0)
|
|
|
|
return;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if (numpages >= 2)
|
|
|
|
{
|
2014-03-05 21:12:54 +00:00
|
|
|
permfifotype *per = &permfifo[permhead];
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
per->sx = sx; per->sy = sy; per->z = z; per->a = a;
|
|
|
|
per->picnum = picnum;
|
|
|
|
per->dashade = dashade; per->dapalnum = dapalnum;
|
|
|
|
per->dastat = dastat;
|
2013-03-25 04:32:24 +00:00
|
|
|
per->daalpha = daalpha;
|
2014-03-05 21:12:54 +00:00
|
|
|
per->dablend = dablend;
|
2006-04-13 20:47:06 +00:00
|
|
|
per->pagesleft = numpages+((beforedrawrooms&1)<<7);
|
|
|
|
per->cx1 = cx1; per->cy1 = cy1; per->cx2 = cx2; per->cy2 = cy2;
|
|
|
|
per->uniqid = guniqhudid; //JF extension
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Would be better to optimize out true bounding boxes
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_NOMASK) //If non-masking write, checking for overlapping cases
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=permtail; i!=permhead; i=((i+1)&(MAXPERMS-1)))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-03-05 21:12:54 +00:00
|
|
|
permfifotype *per2 = &permfifo[i];
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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;
|
2014-09-30 04:14:21 +00:00
|
|
|
if (tilesiz[per2->picnum].x > tilesiz[per->picnum].x) continue;
|
|
|
|
if (tilesiz[per2->picnum].y > tilesiz[per->picnum].y) continue;
|
2006-04-13 20:47:06 +00:00
|
|
|
if (per2->cx1 < per->cx1) continue;
|
|
|
|
if (per2->cy1 < per->cy1) continue;
|
|
|
|
if (per2->cx2 > per->cx2) continue;
|
|
|
|
if (per2->cy2 > per->cy2) continue;
|
2014-03-05 21:12:54 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
per2->pagesleft = 0;
|
|
|
|
}
|
2014-03-05 21:12:54 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
if ((per->z == 65536) && (per->a == 0))
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=permtail; i!=permhead; i=((i+1)&(MAXPERMS-1)))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-03-05 21:12:54 +00:00
|
|
|
permfifotype *per2 = &permfifo[i];
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
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;
|
2014-09-30 04:14:21 +00:00
|
|
|
if ((per2->sx>>16)+tilesiz[per2->picnum].x > (per->sx>>16)+tilesiz[per->picnum].x) continue;
|
|
|
|
if ((per2->sy>>16)+tilesiz[per2->picnum].y > (per->sy>>16)+tilesiz[per->picnum].y) continue;
|
2014-03-05 21:12:54 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
per2->pagesleft = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
permhead = ((permhead+1)&(MAXPERMS-1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// clearview
|
|
|
|
//
|
2018-04-12 21:02:51 +00:00
|
|
|
void videoClearViewableArea(int32_t dacol)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-07-08 03:34:42 +00:00
|
|
|
if (!in3dmode() && dacol != -1) return;
|
|
|
|
|
|
|
|
if (dacol == -1) dacol = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() >= REND_POLYMOST)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2018-04-12 21:03:12 +00:00
|
|
|
palette_t const p = paletteGetColor(dacol);
|
2010-08-14 21:32:28 +00:00
|
|
|
|
2019-10-04 19:13:04 +00:00
|
|
|
GLInterface.ClearScreen((float)p.r * (1.f/255.f),
|
2014-10-25 03:29:21 +00:00
|
|
|
(float)p.g * (1.f/255.f),
|
|
|
|
(float)p.b * (1.f/255.f),
|
2019-10-04 19:13:04 +00:00
|
|
|
false);
|
2006-04-24 19:04:22 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2006-04-13 20:47:06 +00:00
|
|
|
//dacol += (dacol<<8); dacol += (dacol<<16);
|
2016-06-21 00:34:29 +00:00
|
|
|
int const dx = windowxy2.x-windowxy1.x+1;
|
|
|
|
intptr_t p = frameplace+ylookup[windowxy1.y]+windowxy1.x;
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t y=windowxy1.y; y<=windowxy2.y; ++y)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2006-04-13 20:47:06 +00:00
|
|
|
//clearbufbyte((void*)p,dx,dacol);
|
2011-01-16 02:50:27 +00:00
|
|
|
Bmemset((void *)p,dacol,dx);
|
2006-04-13 20:47:06 +00:00
|
|
|
p += ylookup[1];
|
|
|
|
}
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
faketimerhandler();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// clearallviews
|
|
|
|
//
|
2018-04-12 21:02:51 +00:00
|
|
|
void videoClearScreen(int32_t dacol)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-05-30 09:13:32 +00:00
|
|
|
if (!in3dmode()) return;
|
2006-04-13 20:47:06 +00:00
|
|
|
//dacol += (dacol<<8); dacol += (dacol<<16);
|
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() >= REND_POLYMOST)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2018-04-12 21:03:12 +00:00
|
|
|
palette_t const p = paletteGetColor(dacol);
|
2010-08-14 21:32:28 +00:00
|
|
|
|
2019-10-04 19:13:04 +00:00
|
|
|
GLInterface.SetViewport(0,0,xdim,ydim); glox1 = -1;
|
|
|
|
GLInterface.ClearScreen((float)p.r * (1.f/255.f),
|
2014-10-25 03:29:21 +00:00
|
|
|
(float)p.g * (1.f/255.f),
|
|
|
|
(float)p.b * (1.f/255.f),
|
2019-10-04 19:13:04 +00:00
|
|
|
false);
|
2006-04-24 19:04:22 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2018-07-14 21:36:44 +00:00
|
|
|
Bmemset((void *)frameplace,dacol,bytesperline*ydim);
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2006-04-13 20:47:06 +00:00
|
|
|
//nextpage();
|
|
|
|
|
|
|
|
faketimerhandler();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//MUST USE RESTOREFORDRAWROOMS AFTER DRAWING
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// setviewtotile
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
void renderSetTarget(int16_t tilenume, int32_t xsiz, int32_t ysiz)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-04-18 17:24:37 +00:00
|
|
|
if (setviewcnt >= MAXSETVIEW-1)
|
|
|
|
return;
|
2019-08-07 16:18:57 +00:00
|
|
|
if (xsiz <= 0 ||
|
|
|
|
ysiz <= 0)
|
|
|
|
return;
|
2019-04-18 17:24:37 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//DRAWROOMS TO TILE BACKUP&SET CODE
|
2014-09-30 04:14:21 +00:00
|
|
|
tilesiz[tilenume].x = xsiz; tilesiz[tilenume].y = ysiz;
|
2019-08-01 00:08:00 +00:00
|
|
|
bakxsiz[setviewcnt] = xdim; bakysiz[setviewcnt] = ydim;
|
2006-04-13 20:47:06 +00:00
|
|
|
bakframeplace[setviewcnt] = frameplace; frameplace = waloff[tilenume];
|
2016-06-21 00:34:29 +00:00
|
|
|
bakwindowxy1[setviewcnt] = windowxy1;
|
|
|
|
bakwindowxy2[setviewcnt] = windowxy2;
|
2014-09-30 04:06:32 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (setviewcnt == 0)
|
|
|
|
{
|
2014-09-30 04:06:32 +00:00
|
|
|
#ifdef USE_OPENGL
|
2006-04-13 20:47:06 +00:00
|
|
|
bakrendmode = rendmode;
|
2014-09-30 04:06:32 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
baktile = tilenume;
|
|
|
|
}
|
2014-09-30 04:06:32 +00:00
|
|
|
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
rendmode = REND_CLASSIC;
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
2014-09-30 04:06:32 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
copybufbyte(&startumost[windowxy1.x],&bakumost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(bakumost[0]));
|
|
|
|
copybufbyte(&startdmost[windowxy1.x],&bakdmost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(bakdmost[0]));
|
2006-04-13 20:47:06 +00:00
|
|
|
setviewcnt++;
|
|
|
|
|
|
|
|
offscreenrendering = 1;
|
2019-08-01 00:08:00 +00:00
|
|
|
xdim = ysiz;
|
|
|
|
ydim = xsiz;
|
2018-04-12 21:02:51 +00:00
|
|
|
videoSetViewableArea(0,0,ysiz-1,xsiz-1);
|
2018-04-12 21:03:47 +00:00
|
|
|
renderSetAspect(65536,65536);
|
2012-12-14 19:28:17 +00:00
|
|
|
|
|
|
|
calc_ylookup(ysiz, xsiz);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// setviewback
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
void renderRestoreTarget(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
if (setviewcnt <= 0) return;
|
|
|
|
setviewcnt--;
|
|
|
|
|
|
|
|
offscreenrendering = (setviewcnt>0);
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2007-12-12 17:42:14 +00:00
|
|
|
if (setviewcnt == 0)
|
|
|
|
{
|
2006-04-13 20:47:06 +00:00
|
|
|
rendmode = bakrendmode;
|
2018-04-12 21:03:47 +00:00
|
|
|
tileInvalidate(baktile,-1,-1);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-08-01 00:08:00 +00:00
|
|
|
xdim = bakxsiz[setviewcnt];
|
|
|
|
ydim = bakysiz[setviewcnt];
|
2018-04-12 21:02:51 +00:00
|
|
|
videoSetViewableArea(bakwindowxy1[setviewcnt].x,bakwindowxy1[setviewcnt].y,
|
2016-06-21 00:34:29 +00:00
|
|
|
bakwindowxy2[setviewcnt].x,bakwindowxy2[setviewcnt].y);
|
2016-06-21 00:34:18 +00:00
|
|
|
copybufbyte(&bakumost[windowxy1.x],&startumost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(startumost[0]));
|
|
|
|
copybufbyte(&bakdmost[windowxy1.x],&startdmost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(startdmost[0]));
|
2006-04-13 20:47:06 +00:00
|
|
|
frameplace = bakframeplace[setviewcnt];
|
2012-12-14 19:28:17 +00:00
|
|
|
|
2019-08-01 00:08:00 +00:00
|
|
|
calc_ylookup((setviewcnt == 0) ? bytesperline : bakxsiz[setviewcnt],
|
|
|
|
bakysiz[setviewcnt]);
|
2012-12-14 19:28:17 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
modechange=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// squarerotatetile
|
|
|
|
//
|
2009-01-09 09:29:17 +00:00
|
|
|
void squarerotatetile(int16_t tilenume)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:34:29 +00:00
|
|
|
int const siz = tilesiz[tilenume].x;
|
2010-01-16 20:17:33 +00:00
|
|
|
|
2014-10-25 03:30:38 +00:00
|
|
|
if (siz != tilesiz[tilenume].y)
|
|
|
|
return;
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2016-06-21 00:33:39 +00:00
|
|
|
char *ptr1, *ptr2;
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=siz-1, j; i>=3; i-=4)
|
2014-10-25 03:30:38 +00:00
|
|
|
{
|
|
|
|
ptr2 = ptr1 = (char *) (waloff[tilenume]+i*(siz+1));
|
|
|
|
swapchar(--ptr1, (ptr2 -= siz));
|
2016-06-21 00:34:29 +00:00
|
|
|
for (j=(i>>1)-1; j>=0; --j)
|
|
|
|
swapchar2((ptr1 -= 2), (ptr2 -= (siz<<1)), siz);
|
2014-10-25 03:30:38 +00:00
|
|
|
|
|
|
|
ptr2 = ptr1 = (char *) (waloff[tilenume]+(i-1)*(siz+1));
|
2016-06-21 00:34:29 +00:00
|
|
|
for (j=((i-1)>>1)-1; j>=0; --j)
|
|
|
|
swapchar2((ptr1 -= 2), (ptr2 -= (siz<<1)), siz);
|
2014-10-25 03:30:38 +00:00
|
|
|
|
|
|
|
ptr2 = ptr1 = (char *) (waloff[tilenume]+(i-2)*(siz+1));
|
|
|
|
swapchar(--ptr1, (ptr2 -= siz));
|
2017-06-27 11:01:22 +00:00
|
|
|
|
2016-06-21 00:34:29 +00:00
|
|
|
for (j=((i-2)>>1)-1; j>=0; --j)
|
|
|
|
swapchar2((ptr1 -= 2), (ptr2 -= (siz<<1)), siz);
|
2014-10-25 03:30:38 +00:00
|
|
|
|
|
|
|
ptr2 = ptr1 = (char *) (waloff[tilenume]+(i-3)*(siz+1));
|
2017-06-27 11:01:22 +00:00
|
|
|
|
2016-06-21 00:34:29 +00:00
|
|
|
for (j=((i-3)>>1)-1; j>=0; --j)
|
|
|
|
swapchar2((ptr1 -= 2), (ptr2 -= (siz<<1)), siz);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// preparemirror
|
|
|
|
//
|
2019-06-25 18:35:16 +00:00
|
|
|
void renderPrepareMirror(int32_t dax, int32_t day, int32_t daz, fix16_t daang, fix16_t dahoriz, int16_t dawall,
|
2018-04-12 21:03:47 +00:00
|
|
|
int32_t *tposx, int32_t *tposy, fix16_t *tang)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-05-01 17:41:59 +00:00
|
|
|
const int32_t x = wall[dawall].x, dx = wall[wall[dawall].point2].x-x;
|
|
|
|
const int32_t y = wall[dawall].y, dy = wall[wall[dawall].point2].y-y;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-05-01 17:41:59 +00:00
|
|
|
const int32_t j = dx*dx + dy*dy;
|
|
|
|
if (j == 0)
|
|
|
|
return;
|
|
|
|
|
2016-06-21 00:33:39 +00:00
|
|
|
int i = ((dax-x)*dx + (day-y)*dy)<<1;
|
2008-03-22 10:23:57 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
*tposx = (x<<1) + scale(dx,i,j) - dax;
|
|
|
|
*tposy = (y<<1) + scale(dy,i,j) - day;
|
2018-03-07 04:21:18 +00:00
|
|
|
*tang = (fix16_from_int(getangle(dx, dy) << 1) - daang) & 0x7FFFFFF;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
inpreparemirror = 1;
|
2019-06-25 18:35:16 +00:00
|
|
|
|
|
|
|
#ifdef USE_OPENGL
|
2019-07-19 01:49:34 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
2019-06-25 18:35:16 +00:00
|
|
|
polymost_prepareMirror(dax, day, daz, daang, dahoriz, dawall);
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2019-09-21 11:02:17 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
|
|
|
// completemirror
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
void renderCompleteMirror(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-06-25 18:35:16 +00:00
|
|
|
#ifdef USE_OPENGL
|
2019-07-19 01:49:34 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
2019-06-25 18:35:16 +00:00
|
|
|
polymost_completeMirror();
|
|
|
|
#endif
|
|
|
|
|
2019-06-25 18:35:05 +00:00
|
|
|
// Don't try to complete a mirror if we haven't drawn the reflection for one
|
|
|
|
if (!inpreparemirror) { return; }
|
|
|
|
inpreparemirror = 0;
|
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() != REND_CLASSIC)
|
2013-05-04 16:36:12 +00:00
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
|
|
|
|
2013-05-04 16:36:12 +00:00
|
|
|
// The mirroring code maps the rightmost pixel to the right neighbor of the
|
|
|
|
// leftmost one (see copybufreverse() call below). Thus, the leftmost would
|
|
|
|
// be mapped to the right neighbor of the rightmost one, which would be out
|
|
|
|
// of bounds.
|
|
|
|
if (mirrorsx1 == 0)
|
|
|
|
mirrorsx1 = 1;
|
2013-05-01 17:41:59 +00:00
|
|
|
|
2013-05-04 16:36:12 +00:00
|
|
|
// Require that the mirror is at least one pixel wide before padding.
|
2013-05-01 17:41:59 +00:00
|
|
|
if (mirrorsx1 > mirrorsx2)
|
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-05-04 16:36:12 +00:00
|
|
|
// Variables mirrorsx{1,2} refer to the source scene here, the one drawn
|
|
|
|
// from the inside of the mirror.
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing();
|
2013-05-04 16:36:12 +00:00
|
|
|
|
2016-06-21 00:33:39 +00:00
|
|
|
// Width in pixels (screen x's are inclusive on both sides):
|
2016-06-21 00:34:29 +00:00
|
|
|
int const width = mirrorsx2-mirrorsx1+1;
|
2016-06-21 00:33:39 +00:00
|
|
|
// Height in pixels (screen y's are half-open because they come from umost/dmost):
|
2016-06-21 00:34:29 +00:00
|
|
|
int const height = mirrorsy2-mirrorsy1;
|
2013-05-04 16:36:12 +00:00
|
|
|
|
2016-06-21 00:33:39 +00:00
|
|
|
// Address of the mirror wall's top left corner in the source scene:
|
2019-06-25 18:35:05 +00:00
|
|
|
intptr_t s = (intptr_t) mirrorBuffer + ylookup[windowxy1.y+mirrorsy1] + windowxy1.x+mirrorsx1;
|
2013-05-04 16:36:12 +00:00
|
|
|
|
2019-06-25 18:35:05 +00:00
|
|
|
// Pointer to the mirror line's left corner in the destination:
|
|
|
|
intptr_t d = (intptr_t) frameplace + ylookup[windowxy1.y+mirrorsy1] + windowxy2.x-mirrorsx2;
|
2013-05-01 17:41:59 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t y=0; y<height; y++)
|
2016-06-21 00:33:39 +00:00
|
|
|
{
|
2013-05-01 17:41:59 +00:00
|
|
|
#if 0
|
2019-06-25 18:35:05 +00:00
|
|
|
if ((p-mirrorBuffer) + width-1 >= bytesperline*ydim)
|
2016-06-21 00:33:39 +00:00
|
|
|
printf("oob read: mirrorsx1=%d, mirrorsx2=%d\n", mirrorsx1, mirrorsx2);
|
2013-05-01 17:41:59 +00:00
|
|
|
#endif
|
2019-06-25 18:35:05 +00:00
|
|
|
copybufreverse((void *)(s+width-1), (void *)(d+1), width);
|
2013-05-01 17:41:59 +00:00
|
|
|
|
2019-06-25 18:35:05 +00:00
|
|
|
s += ylookup[1];
|
|
|
|
d += ylookup[1];
|
2016-06-21 00:33:39 +00:00
|
|
|
faketimerhandler();
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2016-06-21 00:33:39 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing();
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// sectorofwall
|
|
|
|
//
|
2018-04-02 22:00:23 +00:00
|
|
|
static int32_t sectorofwall_internal(int16_t wallNum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-04-02 22:00:23 +00:00
|
|
|
native_t gap = numsectors>>1, sectNum = gap;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
while (gap > 1)
|
|
|
|
{
|
|
|
|
gap >>= 1;
|
2018-04-02 22:00:23 +00:00
|
|
|
native_t const n = !!(sector[sectNum].wallptr < wallNum);
|
|
|
|
sectNum += (n ^ (n - 1)) * gap;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2018-04-02 22:00:23 +00:00
|
|
|
while (sector[sectNum].wallptr > wallNum) sectNum--;
|
|
|
|
while (sector[sectNum].wallptr + sector[sectNum].wallnum <= wallNum) sectNum++;
|
2013-04-12 11:59:26 +00:00
|
|
|
|
2018-04-02 22:00:23 +00:00
|
|
|
return sectNum;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2018-04-02 22:00:23 +00:00
|
|
|
int32_t sectorofwall(int16_t wallNum)
|
2011-02-10 23:15:02 +00:00
|
|
|
{
|
2018-04-02 22:00:23 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned)wallNum >= (unsigned)numwalls))
|
2013-04-12 11:59:26 +00:00
|
|
|
return -1;
|
|
|
|
|
2018-04-02 22:00:23 +00:00
|
|
|
native_t const w = wall[wallNum].nextwall;
|
2011-02-10 23:15:02 +00:00
|
|
|
|
2018-04-02 22:00:23 +00:00
|
|
|
return ((unsigned)w < MAXWALLS) ? wall[w].nextsector : sectorofwall_internal(wallNum);
|
2011-02-10 23:15:02 +00:00
|
|
|
}
|
|
|
|
|
2018-04-02 22:00:23 +00:00
|
|
|
int32_t sectorofwall_noquick(int16_t wallNum)
|
2011-02-10 23:15:02 +00:00
|
|
|
{
|
2018-04-02 22:00:23 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned) wallNum >= (unsigned) numwalls))
|
2013-04-12 11:59:26 +00:00
|
|
|
return -1;
|
2011-02-10 23:15:02 +00:00
|
|
|
|
2018-04-02 22:00:23 +00:00
|
|
|
return sectorofwall_internal(wallNum);
|
2011-02-10 23:15:02 +00:00
|
|
|
}
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
int32_t getceilzofslopeptr(usectorptr_t sec, int32_t dax, int32_t day)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-04-12 11:59:26 +00:00
|
|
|
if (!(sec->ceilingstat&2))
|
|
|
|
return sec->ceilingz;
|
2009-06-07 03:13:55 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const wal = (uwallptr_t)&wall[sec->wallptr];
|
|
|
|
auto const wal2 = (uwallptr_t)&wall[wal->point2];
|
2009-06-07 03:13:55 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
vec2_t const w = *(vec2_t const *)wal;
|
2019-04-18 17:23:53 +00:00
|
|
|
vec2_t const d = { wal2->x - w.x, wal2->y - w.y };
|
2013-04-12 11:59:26 +00:00
|
|
|
|
2016-06-21 00:34:29 +00:00
|
|
|
int const i = nsqrtasm(uhypsq(d.x,d.y))<<5;
|
2016-06-21 00:33:30 +00:00
|
|
|
if (i == 0) return sec->ceilingz;
|
2013-04-12 11:59:26 +00:00
|
|
|
|
2016-06-21 00:34:29 +00:00
|
|
|
int const j = dmulscale3(d.x, day-w.y, -d.y, dax-w.x);
|
2019-09-22 19:26:07 +00:00
|
|
|
int const shift = enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? 0 : 1;
|
2019-09-21 11:02:17 +00:00
|
|
|
return sec->ceilingz + (scale(sec->ceilingheinum,j>>shift,i)<<shift);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
int32_t getflorzofslopeptr(usectorptr_t sec, int32_t dax, int32_t day)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-04-12 11:59:26 +00:00
|
|
|
if (!(sec->floorstat&2))
|
|
|
|
return sec->floorz;
|
2009-06-07 03:13:55 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const wal = (uwallptr_t)&wall[sec->wallptr];
|
|
|
|
auto const wal2 = (uwallptr_t)&wall[wal->point2];
|
2009-06-07 03:13:55 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
vec2_t const w = *(vec2_t const *)wal;
|
2019-04-18 17:23:53 +00:00
|
|
|
vec2_t const d = { wal2->x - w.x, wal2->y - w.y };
|
2013-04-12 11:59:26 +00:00
|
|
|
|
2016-06-21 00:34:29 +00:00
|
|
|
int const i = nsqrtasm(uhypsq(d.x,d.y))<<5;
|
2016-06-21 00:33:30 +00:00
|
|
|
if (i == 0) return sec->floorz;
|
2013-04-12 11:59:26 +00:00
|
|
|
|
2016-06-21 00:34:29 +00:00
|
|
|
int const j = dmulscale3(d.x, day-w.y, -d.y, dax-w.x);
|
2019-09-22 19:26:07 +00:00
|
|
|
int const shift = enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? 0 : 1;
|
2019-09-21 11:02:17 +00:00
|
|
|
return sec->floorz + (scale(sec->floorheinum,j>>shift,i)<<shift);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
void getzsofslopeptr(usectorptr_t sec, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
*ceilz = sec->ceilingz; *florz = sec->floorz;
|
2013-04-12 11:59:26 +00:00
|
|
|
|
2016-06-21 00:33:30 +00:00
|
|
|
if (((sec->ceilingstat|sec->floorstat)&2) != 2)
|
|
|
|
return;
|
2013-04-12 11:59:26 +00:00
|
|
|
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const wal = (uwallptr_t)&wall[sec->wallptr];
|
|
|
|
auto const wal2 = (uwallptr_t)&wall[wal->point2];
|
2019-04-18 17:23:53 +00:00
|
|
|
|
|
|
|
vec2_t const d = { wal2->x - wal->x, wal2->y - wal->y };
|
2013-04-12 11:59:26 +00:00
|
|
|
|
2016-06-21 00:34:29 +00:00
|
|
|
int const i = nsqrtasm(uhypsq(d.x,d.y))<<5;
|
2016-06-21 00:33:30 +00:00
|
|
|
if (i == 0) return;
|
|
|
|
|
2016-06-21 00:34:29 +00:00
|
|
|
int const j = dmulscale3(d.x,day-wal->y, -d.y,dax-wal->x);
|
2019-09-22 19:26:07 +00:00
|
|
|
int const shift = enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? 0 : 1;
|
2016-06-21 00:33:30 +00:00
|
|
|
if (sec->ceilingstat&2)
|
2019-09-21 11:02:17 +00:00
|
|
|
*ceilz += scale(sec->ceilingheinum,j>>shift,i)<<shift;
|
2016-06-21 00:33:30 +00:00
|
|
|
if (sec->floorstat&2)
|
2019-09-21 11:02:17 +00:00
|
|
|
*florz += scale(sec->floorheinum,j>>shift,i)<<shift;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2019-09-17 03:20:38 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
void yax_getzsofslope(int sectNum, int playerX, int playerY, int32_t *pCeilZ, int32_t *pFloorZ)
|
|
|
|
{
|
|
|
|
int didCeiling = 0;
|
|
|
|
int didFloor = 0;
|
|
|
|
int testSector = 0;
|
|
|
|
|
|
|
|
if ((sector[sectNum].ceilingstat & 512) == 0)
|
|
|
|
{
|
|
|
|
testSector = yax_getneighborsect(playerX, playerY, sectNum, YAX_CEILING);
|
|
|
|
|
|
|
|
if (testSector >= 0)
|
|
|
|
{
|
|
|
|
ceiling:
|
|
|
|
*pCeilZ = getcorrectceilzofslope(testSector, playerX, playerY);
|
|
|
|
didCeiling = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((sector[sectNum].floorstat & 512) == 0)
|
|
|
|
{
|
|
|
|
testSector = yax_getneighborsect(playerX, playerY, sectNum, YAX_FLOOR);
|
|
|
|
|
|
|
|
if (testSector >= 0)
|
|
|
|
{
|
|
|
|
floor:
|
|
|
|
*pFloorZ = getcorrectflorzofslope(testSector, playerX, playerY);
|
|
|
|
didFloor = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
testSector = sectNum;
|
|
|
|
|
|
|
|
if (!didCeiling)
|
|
|
|
goto ceiling;
|
|
|
|
else if (!didFloor)
|
|
|
|
goto floor;
|
|
|
|
}
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// alignceilslope
|
|
|
|
//
|
2009-01-09 09:29:17 +00:00
|
|
|
void alignceilslope(int16_t dasect, int32_t x, int32_t y, int32_t z)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const wal = (uwallptr_t)&wall[sector[dasect].wallptr];
|
2013-04-12 11:59:26 +00:00
|
|
|
const int32_t dax = wall[wal->point2].x-wal->x;
|
|
|
|
const int32_t day = wall[wal->point2].y-wal->y;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-04-12 11:59:26 +00:00
|
|
|
const int32_t i = (y-wal->y)*dax - (x-wal->x)*day;
|
|
|
|
if (i == 0)
|
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
sector[dasect].ceilingheinum = scale((z-sector[dasect].ceilingz)<<8,
|
2012-07-01 22:11:14 +00:00
|
|
|
nsqrtasm(uhypsq(dax,day)), i);
|
2013-04-12 11:59:26 +00:00
|
|
|
if (sector[dasect].ceilingheinum == 0)
|
|
|
|
sector[dasect].ceilingstat &= ~2;
|
2006-04-13 20:47:06 +00:00
|
|
|
else sector[dasect].ceilingstat |= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// alignflorslope
|
|
|
|
//
|
2009-01-09 09:29:17 +00:00
|
|
|
void alignflorslope(int16_t dasect, int32_t x, int32_t y, int32_t z)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-04-18 17:25:24 +00:00
|
|
|
auto const wal = (uwallptr_t)&wall[sector[dasect].wallptr];
|
2013-04-12 11:59:26 +00:00
|
|
|
const int32_t dax = wall[wal->point2].x-wal->x;
|
|
|
|
const int32_t day = wall[wal->point2].y-wal->y;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-04-12 11:59:26 +00:00
|
|
|
const int32_t i = (y-wal->y)*dax - (x-wal->x)*day;
|
|
|
|
if (i == 0)
|
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
sector[dasect].floorheinum = scale((z-sector[dasect].floorz)<<8,
|
2012-07-01 22:11:14 +00:00
|
|
|
nsqrtasm(uhypsq(dax,day)), i);
|
2013-04-12 11:59:26 +00:00
|
|
|
if (sector[dasect].floorheinum == 0)
|
|
|
|
sector[dasect].floorstat &= ~2;
|
2006-04-13 20:47:06 +00:00
|
|
|
else sector[dasect].floorstat |= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// loopnumofsector
|
|
|
|
//
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t loopnumofsector(int16_t sectnum, int16_t wallnum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-04-12 11:59:26 +00:00
|
|
|
int32_t numloops = 0;
|
|
|
|
const int32_t startwall = sector[sectnum].wallptr;
|
|
|
|
const int32_t endwall = startwall + sector[sectnum].wallnum;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=startwall; i<endwall; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-04-12 11:59:26 +00:00
|
|
|
if (i == wallnum)
|
|
|
|
return numloops;
|
|
|
|
|
|
|
|
if (wall[i].point2 < i)
|
|
|
|
numloops++;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2013-04-12 11:59:26 +00:00
|
|
|
|
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// setfirstwall
|
|
|
|
//
|
2009-01-09 09:29:17 +00:00
|
|
|
void setfirstwall(int16_t sectnum, int16_t newfirstwall)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-04-12 11:59:26 +00:00
|
|
|
int32_t i, j, numwallsofloop;
|
|
|
|
int32_t dagoalloop;
|
2016-06-21 00:33:58 +00:00
|
|
|
uwalltype *tmpwall;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-04-12 11:59:26 +00:00
|
|
|
const int32_t startwall = sector[sectnum].wallptr;
|
|
|
|
const int32_t danumwalls = sector[sectnum].wallnum;
|
|
|
|
const int32_t endwall = startwall+danumwalls;
|
2010-09-30 23:05:40 +00:00
|
|
|
|
2013-04-12 11:59:26 +00:00
|
|
|
if (newfirstwall < startwall || newfirstwall >= startwall+danumwalls)
|
|
|
|
return;
|
2010-09-30 23:05:40 +00:00
|
|
|
|
2016-06-21 00:33:58 +00:00
|
|
|
tmpwall = (uwalltype *)Xmalloc(danumwalls * sizeof(walltype));
|
2010-09-30 23:05:40 +00:00
|
|
|
|
|
|
|
Bmemcpy(tmpwall, &wall[startwall], danumwalls*sizeof(walltype));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
numwallsofloop = 0;
|
|
|
|
i = newfirstwall;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
numwallsofloop++;
|
|
|
|
i = wall[i].point2;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (i != newfirstwall);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Put correct loop at beginning
|
2006-04-13 20:47:06 +00:00
|
|
|
dagoalloop = loopnumofsector(sectnum,newfirstwall);
|
|
|
|
if (dagoalloop > 0)
|
|
|
|
{
|
|
|
|
j = 0;
|
2011-09-30 13:52:02 +00:00
|
|
|
while (loopnumofsector(sectnum,j+startwall) != dagoalloop)
|
|
|
|
j++;
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<danumwalls; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-04-12 11:59:26 +00:00
|
|
|
int32_t k = i+j;
|
|
|
|
if (k >= danumwalls) k -= danumwalls;
|
2010-09-30 23:05:40 +00:00
|
|
|
Bmemcpy(&wall[startwall+i], &tmpwall[k], sizeof(walltype));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
wall[startwall+i].point2 += danumwalls-startwall-j;
|
|
|
|
if (wall[startwall+i].point2 >= danumwalls)
|
|
|
|
wall[startwall+i].point2 -= danumwalls;
|
|
|
|
wall[startwall+i].point2 += startwall;
|
|
|
|
}
|
2011-09-30 13:52:02 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
newfirstwall += danumwalls-j;
|
2011-09-30 13:52:02 +00:00
|
|
|
if (newfirstwall >= startwall+danumwalls)
|
|
|
|
newfirstwall -= danumwalls;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<numwallsofloop; i++)
|
2010-09-30 23:05:40 +00:00
|
|
|
Bmemcpy(&tmpwall[i], &wall[i+startwall], sizeof(walltype));
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<numwallsofloop; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-04-12 11:59:26 +00:00
|
|
|
int32_t k = i+newfirstwall-startwall;
|
2006-04-13 20:47:06 +00:00
|
|
|
if (k >= numwallsofloop) k -= numwallsofloop;
|
2010-09-30 23:05:40 +00:00
|
|
|
Bmemcpy(&wall[startwall+i], &tmpwall[k], sizeof(walltype));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
wall[startwall+i].point2 += numwallsofloop-newfirstwall;
|
|
|
|
if (wall[startwall+i].point2 >= numwallsofloop)
|
|
|
|
wall[startwall+i].point2 -= numwallsofloop;
|
|
|
|
wall[startwall+i].point2 += startwall;
|
|
|
|
}
|
|
|
|
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=startwall; i<endwall; i++)
|
2011-09-30 13:52:02 +00:00
|
|
|
if (wall[i].nextwall >= 0)
|
|
|
|
wall[wall[i].nextwall].nextwall = i;
|
|
|
|
|
2011-04-11 22:28:58 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2016-06-21 00:34:18 +00:00
|
|
|
int16_t cb, fb;
|
|
|
|
yax_getbunches(sectnum, &cb, &fb);
|
2011-04-11 22:28:58 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
if (cb>=0 || fb>=0)
|
|
|
|
{
|
|
|
|
for (i=startwall; i<endwall; i++)
|
2011-04-11 22:28:58 +00:00
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
j = yax_getnextwall(i, YAX_CEILING);
|
|
|
|
if (j >= 0)
|
|
|
|
yax_setnextwall(j, YAX_FLOOR, i);
|
2011-04-11 22:28:58 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
j = yax_getnextwall(i, YAX_FLOOR);
|
|
|
|
if (j >= 0)
|
|
|
|
yax_setnextwall(j, YAX_CEILING, i);
|
2011-04-11 22:28:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2010-09-30 23:05:40 +00:00
|
|
|
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(tmpwall);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
2016-06-21 00:33:14 +00:00
|
|
|
// qsetmodeany
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
2018-04-12 21:02:51 +00:00
|
|
|
void videoSet2dMode(int32_t daxdim, int32_t daydim)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:33:14 +00:00
|
|
|
if (daxdim < 640) daxdim = 640;
|
|
|
|
if (daydim < 480) daydim = 480;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
if (qsetmode != ((daxdim<<16)|(daydim&0xffff)))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2016-06-21 00:33:14 +00:00
|
|
|
g_lastpalettesum = 0;
|
2018-04-12 21:02:51 +00:00
|
|
|
if (videoSetMode(daxdim, daydim, 8, fullscreen) < 0)
|
2016-06-21 00:33:14 +00:00
|
|
|
return;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
xdim = xres;
|
|
|
|
ydim = yres;
|
2015-02-11 05:23:04 +00:00
|
|
|
|
2016-10-03 02:43:42 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-07-14 21:36:44 +00:00
|
|
|
fxdim = (float) xdim;
|
|
|
|
fydim = (float) ydim;
|
2016-10-03 02:43:42 +00:00
|
|
|
|
2018-06-25 14:53:42 +00:00
|
|
|
rendmode = REND_CLASSIC;
|
2018-06-24 00:55:23 +00:00
|
|
|
#endif
|
2018-06-25 14:53:42 +00:00
|
|
|
|
2018-07-14 21:36:44 +00:00
|
|
|
OSD_ResizeDisplay(xdim, ydim);
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoAllocateBuffers();
|
2015-02-11 05:23:04 +00:00
|
|
|
|
2018-07-14 21:36:44 +00:00
|
|
|
ydim16 = ydim - STATUS2DSIZ2;
|
|
|
|
halfxdim16 = xdim >> 1;
|
|
|
|
midydim16 = ydim16 >> 1; // scale(200,ydim,480);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-06-25 14:53:42 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2018-07-14 21:36:44 +00:00
|
|
|
Bmemset((char *)frameplace, 0, ydim*bytesperline);
|
2018-06-25 14:53:42 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2016-06-21 00:33:14 +00:00
|
|
|
}
|
2015-02-11 05:23:04 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
qsetmode = ((daxdim<<16)|(daydim&0xffff));
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
static int32_t printext_checkypos(int32_t ypos, int32_t *yminptr, int32_t *ymaxptr)
|
|
|
|
{
|
|
|
|
int32_t ymin=0, ymax=7;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
if (ypos < 0)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:33:14 +00:00
|
|
|
/*
|
|
|
|
ymin = 0-ypos;
|
|
|
|
if (ymin > 7)
|
|
|
|
return 1;
|
|
|
|
*/
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2016-06-21 00:33:14 +00:00
|
|
|
else if (ypos+7 >= ydim)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:33:14 +00:00
|
|
|
ymax = ydim-ypos-1;
|
|
|
|
if (ymax < 0)
|
|
|
|
return 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
*yminptr = ymin;
|
|
|
|
*ymaxptr = ymax;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
2016-06-21 00:33:14 +00:00
|
|
|
// printext16
|
2006-04-13 20:47:06 +00:00
|
|
|
//
|
2016-06-21 00:33:14 +00:00
|
|
|
int32_t printext16(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol, const char *name, char fontsize)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:33:14 +00:00
|
|
|
int32_t ymin, ymax;
|
2015-07-10 21:19:41 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
if (printext_checkypos(ypos, &ymin, &ymax))
|
2015-07-10 21:19:41 +00:00
|
|
|
return 0;
|
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
if (fontsize & 2) printext16(xpos+1, ypos+1, 0, -1, name, (fontsize & ~2) | 4);
|
2010-12-05 17:39:52 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
int32_t const ocol = col, obackcol = backcol;
|
|
|
|
char smallbuf[4];
|
2015-07-10 21:19:41 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
int32_t stx = xpos;
|
|
|
|
const int32_t xpos0 = xpos;
|
2015-07-10 21:19:41 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
char const * const fontptr = (fontsize & 1) ? smalltextfont : textfont;
|
|
|
|
int const charxsiz = 8 - ((fontsize & 1)<<2);
|
2015-07-10 21:19:41 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; name[i]; i++)
|
2015-07-10 21:19:41 +00:00
|
|
|
{
|
2016-06-21 00:33:14 +00:00
|
|
|
if (name[i] == '^')
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
if (name[i] == 'O') // ^O resets formatting
|
|
|
|
{
|
|
|
|
if (fontsize & 4) continue;
|
2015-07-10 21:19:41 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
col = ocol;
|
|
|
|
backcol = obackcol;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (isdigit(name[i]))
|
|
|
|
{
|
|
|
|
if (isdigit(name[i+1]))
|
|
|
|
{
|
|
|
|
if (isdigit(name[i+2]))
|
|
|
|
{
|
|
|
|
Bmemcpy(&smallbuf[0],&name[i],3);
|
|
|
|
i += 2;
|
|
|
|
smallbuf[3] = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Bmemcpy(&smallbuf[0],&name[i],2);
|
|
|
|
i++;
|
|
|
|
smallbuf[2] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
smallbuf[0] = name[i];
|
|
|
|
smallbuf[1] = '\0';
|
|
|
|
}
|
|
|
|
if (!(fontsize & 4))
|
|
|
|
col = editorcolors[Batol(smallbuf)];
|
2015-07-10 21:19:41 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
if (name[i+1] == ',' && isdigit(name[i+2]))
|
|
|
|
{
|
|
|
|
i+=2;
|
|
|
|
if (isdigit(name[i+1]))
|
|
|
|
{
|
|
|
|
if (isdigit(name[i+2]))
|
|
|
|
{
|
|
|
|
Bmemcpy(&smallbuf[0],&name[i],3);
|
|
|
|
i += 2;
|
|
|
|
smallbuf[3] = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Bmemcpy(&smallbuf[0],&name[i],2);
|
|
|
|
i++;
|
|
|
|
smallbuf[2] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
smallbuf[0] = name[i];
|
|
|
|
smallbuf[1] = '\0';
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
if (!(fontsize & 4))
|
|
|
|
backcol = editorcolors[Batol(smallbuf)];
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2010-12-07 19:05:55 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
if (name[i] == '\n')
|
|
|
|
{
|
|
|
|
xpos = stx = xpos0;
|
|
|
|
ypos += 8;
|
|
|
|
if (printext_checkypos(ypos, &ymin, &ymax))
|
|
|
|
return 0;
|
|
|
|
continue;
|
|
|
|
}
|
2015-07-10 21:19:41 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
if (stx<0)
|
|
|
|
{
|
|
|
|
stx += charxsiz;
|
|
|
|
continue;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
char const * const letptr = &fontptr[name[i]<<3];
|
2010-11-27 22:12:24 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2016-06-21 00:33:14 +00:00
|
|
|
char *ptr = (char *)(bytesperline*ypos + (stx-(fontsize&1)) + frameplace);
|
|
|
|
int const trans = (obackcol < -1);
|
2015-07-10 21:19:41 +00:00
|
|
|
|
2016-06-21 00:33:14 +00:00
|
|
|
if (trans && backcol < 0)
|
|
|
|
backcol = -backcol;
|
2015-07-10 21:19:41 +00:00
|
|
|
|
|
|
|
if (backcol >= 0)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t y=ymin; y<=ymax; y++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t x=0; x<charxsiz; x++)
|
2015-07-10 21:19:41 +00:00
|
|
|
{
|
|
|
|
if ((unsigned) (stx+x) >= (unsigned)xdim || ptr < (char *) frameplace) break;
|
2015-07-17 00:12:40 +00:00
|
|
|
ptr[x] = (letptr[y] & pow2char[7 - (fontsize & 1) - x]) ?
|
|
|
|
(uint8_t)col :
|
|
|
|
trans ? (uint8_t)blendtable[0][(ptr[x] * 256) + backcol] : backcol;
|
2015-07-10 21:19:41 +00:00
|
|
|
}
|
|
|
|
ptr += bytesperline;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t y=ymin; y<=ymax; y++)
|
2015-07-10 21:19:41 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t x=0; x<charxsiz; x++)
|
2015-07-10 21:19:41 +00:00
|
|
|
{
|
|
|
|
if ((unsigned) (stx+x) >= (unsigned)xdim || ptr < (char *) frameplace) break;
|
2015-07-17 00:12:40 +00:00
|
|
|
if (letptr[y]&pow2char[7-(fontsize&1)-x]) ptr[x] = (uint8_t) col;
|
2015-07-10 21:19:41 +00:00
|
|
|
}
|
|
|
|
ptr += bytesperline;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
}
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2015-07-10 21:19:41 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
stx += charxsiz;
|
2015-07-10 21:19:41 +00:00
|
|
|
|
2011-01-16 00:23:39 +00:00
|
|
|
if (stx >= xdim)
|
|
|
|
break;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2008-09-15 02:47:02 +00:00
|
|
|
|
|
|
|
return stx;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// printext256
|
|
|
|
//
|
2010-05-18 05:14:17 +00:00
|
|
|
void printext256(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol, const char *name, char fontsize)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t stx, i, x, y, charxsiz;
|
2006-04-13 20:47:06 +00:00
|
|
|
char *fontptr, *letptr, *ptr;
|
|
|
|
|
|
|
|
stx = xpos;
|
|
|
|
|
|
|
|
if (fontsize) { fontptr = smalltextfont; charxsiz = 4; }
|
|
|
|
else { fontptr = textfont; charxsiz = 8; }
|
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2006-04-13 20:47:06 +00:00
|
|
|
if (!polymost_printext256(xpos,ypos,col,backcol,name,fontsize)) return;
|
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing(); //{{{
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; name[i]; i++)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2008-05-16 19:51:38 +00:00
|
|
|
if (name[i] == '^' && isdigit(name[i+1]))
|
|
|
|
{
|
|
|
|
char smallbuf[8];
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t bi=0;
|
2012-12-20 12:04:39 +00:00
|
|
|
while (isdigit(name[i+1]) && bi<3)
|
2008-05-16 19:51:38 +00:00
|
|
|
{
|
|
|
|
smallbuf[bi++]=name[i+1];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
smallbuf[bi++]=0;
|
2012-02-20 21:17:39 +00:00
|
|
|
if (col)col = Batol(smallbuf);
|
2008-05-16 19:51:38 +00:00
|
|
|
continue;
|
|
|
|
}
|
2012-12-25 16:13:36 +00:00
|
|
|
|
|
|
|
if (stx-fontsize+charxsiz > xdim)
|
|
|
|
break;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
letptr = &fontptr[name[i]<<3];
|
|
|
|
ptr = (char *)(ylookup[ypos+7]+(stx-fontsize)+frameplace);
|
2009-02-19 16:47:54 +00:00
|
|
|
for (y=7; y>=0; y--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-02-19 16:47:54 +00:00
|
|
|
for (x=charxsiz-1; x>=0; x--)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
if (letptr[y]&pow2char[7-fontsize-x])
|
2009-01-09 09:29:17 +00:00
|
|
|
ptr[x] = (uint8_t)col;
|
2006-04-13 20:47:06 +00:00
|
|
|
else if (backcol >= 0)
|
2009-01-09 09:29:17 +00:00
|
|
|
ptr[x] = (uint8_t)backcol;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
ptr -= ylookup[1];
|
|
|
|
}
|
|
|
|
stx += charxsiz;
|
|
|
|
}
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing(); //}}}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-26 17:29:52 +00:00
|
|
|
#ifdef POLYMER
|
|
|
|
static void PolymerProcessModels(void)
|
|
|
|
{
|
|
|
|
// potentially deferred MD3 postprocessing
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<nextmodelid; i++)
|
2014-12-26 17:29:52 +00:00
|
|
|
{
|
|
|
|
if (models[i]->mdnum==3 && ((md3model_t *)models[i])->head.surfs[0].geometry == NULL)
|
|
|
|
{
|
|
|
|
static int32_t warned=0;
|
|
|
|
|
|
|
|
if (!warned)
|
|
|
|
{
|
|
|
|
OSD_Printf("Post-processing MD3 models for Polymer. This may take a while...\n");
|
2018-04-12 21:02:51 +00:00
|
|
|
videoNextPage();
|
2014-12-26 17:29:52 +00:00
|
|
|
warned = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!md3postload_polymer((md3model_t *)models[i]))
|
|
|
|
OSD_Printf("INTERNAL ERROR: mdmodel %s failed postprocessing!\n",
|
|
|
|
((md3model_t *)models[i])->head.nam);
|
|
|
|
|
|
|
|
if (((md3model_t *)models[i])->head.surfs[0].geometry == NULL)
|
|
|
|
OSD_Printf("INTERNAL ERROR: wtf?\n");
|
|
|
|
}
|
|
|
|
// else
|
|
|
|
// OSD_Printf("mdmodel %d already postprocessed.\n", i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// setrendermode
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
int32_t videoSetRenderMode(int32_t renderer)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2008-07-24 11:16:20 +00:00
|
|
|
UNREFERENCED_PARAMETER(renderer);
|
2014-12-26 17:29:52 +00:00
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2014-12-26 17:29:52 +00:00
|
|
|
if (bpp == 8)
|
2019-06-25 11:28:18 +00:00
|
|
|
{
|
2019-10-04 16:12:03 +00:00
|
|
|
GLInterface.EnableBlend(false);
|
|
|
|
GLInterface.EnableAlphaTest(false);
|
2014-12-26 17:29:52 +00:00
|
|
|
renderer = REND_CLASSIC;
|
2019-06-25 11:28:18 +00:00
|
|
|
}
|
2008-05-10 01:29:37 +00:00
|
|
|
# ifdef POLYMER
|
2014-12-26 17:29:52 +00:00
|
|
|
else
|
|
|
|
renderer = clamp(renderer, REND_POLYMOST, REND_POLYMER);
|
2009-08-09 05:32:17 +00:00
|
|
|
|
2014-12-26 17:29:52 +00:00
|
|
|
if (renderer == REND_POLYMER)
|
2009-09-30 01:26:13 +00:00
|
|
|
{
|
2014-12-26 17:29:52 +00:00
|
|
|
PolymerProcessModels();
|
2011-01-01 18:35:59 +00:00
|
|
|
|
|
|
|
if (!polymer_init())
|
2014-12-26 17:29:52 +00:00
|
|
|
renderer = REND_POLYMOST;
|
2009-09-30 01:26:13 +00:00
|
|
|
}
|
2018-04-12 21:03:12 +00:00
|
|
|
else if (videoGetRenderMode() == REND_POLYMER) // going from Polymer to another renderer
|
2011-09-06 17:45:21 +00:00
|
|
|
{
|
2018-04-12 21:03:47 +00:00
|
|
|
engineClearLightsFromMHK();
|
2011-09-06 17:45:21 +00:00
|
|
|
G_Polymer_UnInit();
|
2011-07-24 15:15:57 +00:00
|
|
|
polymer_uninit();
|
2011-09-06 17:45:21 +00:00
|
|
|
}
|
2017-10-16 21:17:53 +00:00
|
|
|
# else
|
|
|
|
else renderer = REND_POLYMOST;
|
2008-05-10 01:29:37 +00:00
|
|
|
# endif
|
2006-08-29 01:58:59 +00:00
|
|
|
|
2012-05-05 22:22:34 +00:00
|
|
|
basepalreset = 1;
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
rendmode = renderer;
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() >= REND_POLYMOST)
|
2009-03-27 21:54:55 +00:00
|
|
|
glrendmode = rendmode;
|
2018-03-21 20:41:26 +00:00
|
|
|
|
|
|
|
if (renderer == REND_POLYMOST)
|
|
|
|
{
|
|
|
|
polymost_init();
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// setrollangle
|
|
|
|
//
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2018-04-12 21:03:47 +00:00
|
|
|
void renderSetRollAngle(int32_t rolla)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-10-03 02:43:48 +00:00
|
|
|
gtang = (float)rolla * (fPI * (1.f/1024.f));
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2008-07-24 11:16:20 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//
|
2018-04-12 21:03:47 +00:00
|
|
|
void tileInvalidate(int16_t tilenume, int32_t pal, int32_t how)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-02-08 14:37:52 +00:00
|
|
|
#if !defined USE_OPENGL
|
|
|
|
UNREFERENCED_PARAMETER(tilenume);
|
|
|
|
UNREFERENCED_PARAMETER(pal);
|
|
|
|
UNREFERENCED_PARAMETER(how);
|
|
|
|
#else
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() >= REND_POLYMOST)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2014-02-08 14:37:52 +00:00
|
|
|
const int32_t firstpal = (pal < 0) ? 0 : pal;
|
|
|
|
const int32_t numpals = (pal < 0) ? MAXPALOOKUPS : 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t hp = 0; hp <= 4; hp+=4)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2014-02-08 14:37:52 +00:00
|
|
|
if (how & pow2long[hp])
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t np = firstpal; np < firstpal+numpals; np++)
|
2014-02-08 14:37:52 +00:00
|
|
|
gltexinvalidate(tilenume, np, hp);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2014-02-08 14:37:53 +00:00
|
|
|
|
2014-03-07 22:17:38 +00:00
|
|
|
#ifdef POLYMER
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMER)
|
2014-02-08 14:37:53 +00:00
|
|
|
polymer_invalidateartmap(tilenume);
|
2014-03-07 22:17:38 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* vim:ts=8:
|
|
|
|
*/
|
|
|
|
|