ref: 0a3f54086a5d97c57bd6ffb1ca4a6296ed19b441
parent: fe87c990e0e84be637a8a743f2dd9d48ae6f5895
author: Konstantinn Bonnet <qu7uux@gmail.com>
date: Fri Mar 13 08:11:31 EDT 2015
shuffle code around more
--- a/mkfile
+++ b/mkfile
@@ -5,7 +5,7 @@
CLDIR=client
SVDIR=server
-SRDIR=ref_soft
+SRDIR=ref
CMDIR=qcommon
P9DIR=plan9
GMDIR=game
@@ -51,12 +51,12 @@
$SVDIR/sv_send.$O\
$SVDIR/sv_user.$O\
$SVDIR/sv_world.$O\
- $P9DIR/cd_linux.$O\
- $P9DIR/q_shlinux.$O\
+ $P9DIR/cd_9.$O\
+ $P9DIR/q_sh9.$O\
$P9DIR/vid_menu.$O\
$P9DIR/vid_so.$O\
- $P9DIR/snd_linux.$O\
- $P9DIR/sys_linux.$O\
+ $P9DIR/snd_9.$O\
+ $P9DIR/sys_9.$O\
$P9DIR/glob.$O\
$P9DIR/net_udp.$O\
@@ -260,9 +260,9 @@
$SRDIR/r_sprite.$O\
$SRDIR/r_surf.$O\
$GMDIR/q_shared.$O\
- $P9DIR/q_shlinux.$O\
+ $P9DIR/q_sh9.$O\
$P9DIR/glob.$O\
- $P9DIR/rw_x11.$O\
+ $P9DIR/rw_9.$O\
SRHFILES=\
$SRDIR/adivtab.h\
--- /dev/null
+++ b/plan9/cd_9.c
@@ -1,0 +1,420 @@
+// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
+// rights reserved.
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include <linux/cdrom.h>
+
+#include "../client/client.h"
+
+static qboolean cdValid = false;
+static qboolean playing = false;
+static qboolean wasPlaying = false;
+static qboolean initialized = false;
+static qboolean enabled = true;
+static qboolean playLooping = false;
+static float cdvolume;
+static byte remap[100];
+static byte playTrack;
+static byte maxTrack;
+
+static int cdfile = -1;
+
+//static char cd_dev[64] = "/dev/cdrom";
+
+cvar_t *cd_volume;
+cvar_t *cd_nocd;
+cvar_t *cd_dev;
+
+void CDAudio_Pause(void);
+
+static void CDAudio_Eject(void)
+{
+ if (cdfile == -1 || !enabled)
+ return; // no cd init'd
+
+ if ( ioctl(cdfile, CDROMEJECT) == -1 )
+ Com_DPrintf("ioctl cdromeject failed\n");
+}
+
+
+static void CDAudio_CloseDoor(void)
+{
+ if (cdfile == -1 || !enabled)
+ return; // no cd init'd
+
+ if ( ioctl(cdfile, CDROMCLOSETRAY) == -1 )
+ Com_DPrintf("ioctl cdromclosetray failed\n");
+}
+
+static int CDAudio_GetAudioDiskInfo(void)
+{
+ struct cdrom_tochdr tochdr;
+
+ cdValid = false;
+
+ if ( ioctl(cdfile, CDROMREADTOCHDR, &tochdr) == -1 )
+ {
+ Com_DPrintf("ioctl cdromreadtochdr failed\n");
+ return -1;
+ }
+
+ if (tochdr.cdth_trk0 < 1)
+ {
+ Com_DPrintf("CDAudio: no music tracks\n");
+ return -1;
+ }
+
+ cdValid = true;
+ maxTrack = tochdr.cdth_trk1;
+
+ return 0;
+}
+
+
+void CDAudio_Play(int track, qboolean looping)
+{
+ struct cdrom_tocentry entry;
+ struct cdrom_ti ti;
+
+ if (cdfile == -1 || !enabled)
+ return;
+
+ if (!cdValid)
+ {
+ CDAudio_GetAudioDiskInfo();
+ if (!cdValid)
+ return;
+ }
+
+ track = remap[track];
+
+ if (track < 1 || track > maxTrack)
+ {
+ Com_DPrintf("CDAudio: Bad track number %u.\n", track);
+ return;
+ }
+
+ // don't try to play a non-audio track
+ entry.cdte_track = track;
+ entry.cdte_format = CDROM_MSF;
+ if ( ioctl(cdfile, CDROMREADTOCENTRY, &entry) == -1 )
+ {
+ Com_DPrintf("ioctl cdromreadtocentry failed\n");
+ return;
+ }
+ if (entry.cdte_ctrl == CDROM_DATA_TRACK)
+ {
+ Com_Printf("CDAudio: track %i is not audio\n", track);
+ return;
+ }
+
+ if (playing)
+ {
+ if (playTrack == track)
+ return;
+ CDAudio_Stop();
+ }
+
+ ti.cdti_trk0 = track;
+ ti.cdti_trk1 = track;
+ ti.cdti_ind0 = 1;
+ ti.cdti_ind1 = 99;
+
+ if ( ioctl(cdfile, CDROMPLAYTRKIND, &ti) == -1 )
+ {
+ Com_DPrintf("ioctl cdromplaytrkind failed\n");
+ return;
+ }
+
+ if ( ioctl(cdfile, CDROMRESUME) == -1 )
+ Com_DPrintf("ioctl cdromresume failed\n");
+
+ playLooping = looping;
+ playTrack = track;
+ playing = true;
+
+ if (cd_volume->value == 0.0)
+ CDAudio_Pause ();
+}
+
+
+void CDAudio_Stop(void)
+{
+ if (cdfile == -1 || !enabled)
+ return;
+
+ if (!playing)
+ return;
+
+ if ( ioctl(cdfile, CDROMSTOP) == -1 )
+ Com_DPrintf("ioctl cdromstop failed (%d)\n", errno);
+
+ wasPlaying = false;
+ playing = false;
+}
+
+void CDAudio_Pause(void)
+{
+ if (cdfile == -1 || !enabled)
+ return;
+
+ if (!playing)
+ return;
+
+ if ( ioctl(cdfile, CDROMPAUSE) == -1 )
+ Com_DPrintf("ioctl cdrompause failed\n");
+
+ wasPlaying = playing;
+ playing = false;
+}
+
+
+void CDAudio_Resume(void)
+{
+ if (cdfile == -1 || !enabled)
+ return;
+
+ if (!cdValid)
+ return;
+
+ if (!wasPlaying)
+ return;
+
+ if ( ioctl(cdfile, CDROMRESUME) == -1 )
+ Com_DPrintf("ioctl cdromresume failed\n");
+ playing = true;
+}
+
+static void CD_f (void)
+{
+ char *command;
+ int ret;
+ int n;
+
+ if (Cmd_Argc() < 2)
+ return;
+
+ command = Cmd_Argv (1);
+
+ if (Q_strcasecmp(command, "on") == 0)
+ {
+ enabled = true;
+ return;
+ }
+
+ if (Q_strcasecmp(command, "off") == 0)
+ {
+ if (playing)
+ CDAudio_Stop();
+ enabled = false;
+ return;
+ }
+
+ if (Q_strcasecmp(command, "reset") == 0)
+ {
+ enabled = true;
+ if (playing)
+ CDAudio_Stop();
+ for (n = 0; n < 100; n++)
+ remap[n] = n;
+ CDAudio_GetAudioDiskInfo();
+ return;
+ }
+
+ if (Q_strcasecmp(command, "remap") == 0)
+ {
+ ret = Cmd_Argc() - 2;
+ if (ret <= 0)
+ {
+ for (n = 1; n < 100; n++)
+ if (remap[n] != n)
+ Com_Printf(" %u -> %u\n", n, remap[n]);
+ return;
+ }
+ for (n = 1; n <= ret; n++)
+ remap[n] = atoi(Cmd_Argv (n+1));
+ return;
+ }
+
+ if (Q_strcasecmp(command, "close") == 0)
+ {
+ CDAudio_CloseDoor();
+ return;
+ }
+
+ if (!cdValid)
+ {
+ CDAudio_GetAudioDiskInfo();
+ if (!cdValid)
+ {
+ Com_Printf("No CD in player.\n");
+ return;
+ }
+ }
+
+ if (Q_strcasecmp(command, "play") == 0)
+ {
+ CDAudio_Play((byte)atoi(Cmd_Argv (2)), false);
+ return;
+ }
+
+ if (Q_strcasecmp(command, "loop") == 0)
+ {
+ CDAudio_Play((byte)atoi(Cmd_Argv (2)), true);
+ return;
+ }
+
+ if (Q_strcasecmp(command, "stop") == 0)
+ {
+ CDAudio_Stop();
+ return;
+ }
+
+ if (Q_strcasecmp(command, "pause") == 0)
+ {
+ CDAudio_Pause();
+ return;
+ }
+
+ if (Q_strcasecmp(command, "resume") == 0)
+ {
+ CDAudio_Resume();
+ return;
+ }
+
+ if (Q_strcasecmp(command, "eject") == 0)
+ {
+ if (playing)
+ CDAudio_Stop();
+ CDAudio_Eject();
+ cdValid = false;
+ return;
+ }
+
+ if (Q_strcasecmp(command, "info") == 0)
+ {
+ Com_Printf("%u tracks\n", maxTrack);
+ if (playing)
+ Com_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+ else if (wasPlaying)
+ Com_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+ Com_Printf("Volume is %f\n", cdvolume);
+ return;
+ }
+}
+
+void CDAudio_Update(void)
+{
+ struct cdrom_subchnl subchnl;
+ static time_t lastchk;
+
+ if (cdfile == -1 || !enabled)
+ return;
+
+ if (cd_volume && cd_volume->value != cdvolume)
+ {
+ if (cdvolume)
+ {
+ Cvar_SetValue ("cd_volume", 0.0);
+ cdvolume = cd_volume->value;
+ CDAudio_Pause ();
+ }
+ else
+ {
+ Cvar_SetValue ("cd_volume", 1.0);
+ cdvolume = cd_volume->value;
+ CDAudio_Resume ();
+ }
+ }
+
+ if (playing && lastchk < time(NULL)) {
+ lastchk = time(NULL) + 2; //two seconds between chks
+ subchnl.cdsc_format = CDROM_MSF;
+ if (ioctl(cdfile, CDROMSUBCHNL, &subchnl) == -1 ) {
+ Com_DPrintf("ioctl cdromsubchnl failed\n");
+ playing = false;
+ return;
+ }
+ if (subchnl.cdsc_audiostatus != CDROM_AUDIO_PLAY &&
+ subchnl.cdsc_audiostatus != CDROM_AUDIO_PAUSED) {
+ playing = false;
+ if (playLooping)
+ CDAudio_Play(playTrack, true);
+ }
+ }
+}
+
+int CDAudio_Init(void)
+{
+ int i;
+ cvar_t *cv;
+ extern uid_t saved_euid;
+
+ cv = Cvar_Get ("nocdaudio", "0", CVAR_NOSET);
+ if (cv->value)
+ return -1;
+
+ cd_nocd = Cvar_Get ("cd_nocd", "0", CVAR_ARCHIVE );
+ if ( cd_nocd->value)
+ return -1;
+
+ cd_volume = Cvar_Get ("cd_volume", "1", CVAR_ARCHIVE);
+
+ cd_dev = Cvar_Get("cd_dev", "/dev/cdrom", CVAR_ARCHIVE);
+
+ seteuid(saved_euid);
+
+ cdfile = open(cd_dev->string, O_RDONLY);
+
+ seteuid(getuid());
+
+ if (cdfile == -1) {
+ Com_Printf("CDAudio_Init: open of \"%s\" failed (%i)\n", cd_dev->string, errno);
+ cdfile = -1;
+ return -1;
+ }
+
+ for (i = 0; i < 100; i++)
+ remap[i] = i;
+ initialized = true;
+ enabled = true;
+
+ if (CDAudio_GetAudioDiskInfo())
+ {
+ Com_Printf("CDAudio_Init: No CD in player.\n");
+ cdValid = false;
+ }
+
+ Cmd_AddCommand ("cd", CD_f);
+
+ Com_Printf("CD Audio Initialized\n");
+
+ return 0;
+}
+
+void CDAudio_Activate (qboolean active)
+{
+ if (active)
+ CDAudio_Resume ();
+ else
+ CDAudio_Pause ();
+}
+
+void CDAudio_Shutdown(void)
+{
+ if (!initialized)
+ return;
+ CDAudio_Stop();
+ close(cdfile);
+ cdfile = -1;
+}
--- a/plan9/cd_linux.c
+++ /dev/null
@@ -1,420 +1,0 @@
-// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
-// rights reserved.
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <sys/file.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-
-#include <linux/cdrom.h>
-
-#include "../client/client.h"
-
-static qboolean cdValid = false;
-static qboolean playing = false;
-static qboolean wasPlaying = false;
-static qboolean initialized = false;
-static qboolean enabled = true;
-static qboolean playLooping = false;
-static float cdvolume;
-static byte remap[100];
-static byte playTrack;
-static byte maxTrack;
-
-static int cdfile = -1;
-
-//static char cd_dev[64] = "/dev/cdrom";
-
-cvar_t *cd_volume;
-cvar_t *cd_nocd;
-cvar_t *cd_dev;
-
-void CDAudio_Pause(void);
-
-static void CDAudio_Eject(void)
-{
- if (cdfile == -1 || !enabled)
- return; // no cd init'd
-
- if ( ioctl(cdfile, CDROMEJECT) == -1 )
- Com_DPrintf("ioctl cdromeject failed\n");
-}
-
-
-static void CDAudio_CloseDoor(void)
-{
- if (cdfile == -1 || !enabled)
- return; // no cd init'd
-
- if ( ioctl(cdfile, CDROMCLOSETRAY) == -1 )
- Com_DPrintf("ioctl cdromclosetray failed\n");
-}
-
-static int CDAudio_GetAudioDiskInfo(void)
-{
- struct cdrom_tochdr tochdr;
-
- cdValid = false;
-
- if ( ioctl(cdfile, CDROMREADTOCHDR, &tochdr) == -1 )
- {
- Com_DPrintf("ioctl cdromreadtochdr failed\n");
- return -1;
- }
-
- if (tochdr.cdth_trk0 < 1)
- {
- Com_DPrintf("CDAudio: no music tracks\n");
- return -1;
- }
-
- cdValid = true;
- maxTrack = tochdr.cdth_trk1;
-
- return 0;
-}
-
-
-void CDAudio_Play(int track, qboolean looping)
-{
- struct cdrom_tocentry entry;
- struct cdrom_ti ti;
-
- if (cdfile == -1 || !enabled)
- return;
-
- if (!cdValid)
- {
- CDAudio_GetAudioDiskInfo();
- if (!cdValid)
- return;
- }
-
- track = remap[track];
-
- if (track < 1 || track > maxTrack)
- {
- Com_DPrintf("CDAudio: Bad track number %u.\n", track);
- return;
- }
-
- // don't try to play a non-audio track
- entry.cdte_track = track;
- entry.cdte_format = CDROM_MSF;
- if ( ioctl(cdfile, CDROMREADTOCENTRY, &entry) == -1 )
- {
- Com_DPrintf("ioctl cdromreadtocentry failed\n");
- return;
- }
- if (entry.cdte_ctrl == CDROM_DATA_TRACK)
- {
- Com_Printf("CDAudio: track %i is not audio\n", track);
- return;
- }
-
- if (playing)
- {
- if (playTrack == track)
- return;
- CDAudio_Stop();
- }
-
- ti.cdti_trk0 = track;
- ti.cdti_trk1 = track;
- ti.cdti_ind0 = 1;
- ti.cdti_ind1 = 99;
-
- if ( ioctl(cdfile, CDROMPLAYTRKIND, &ti) == -1 )
- {
- Com_DPrintf("ioctl cdromplaytrkind failed\n");
- return;
- }
-
- if ( ioctl(cdfile, CDROMRESUME) == -1 )
- Com_DPrintf("ioctl cdromresume failed\n");
-
- playLooping = looping;
- playTrack = track;
- playing = true;
-
- if (cd_volume->value == 0.0)
- CDAudio_Pause ();
-}
-
-
-void CDAudio_Stop(void)
-{
- if (cdfile == -1 || !enabled)
- return;
-
- if (!playing)
- return;
-
- if ( ioctl(cdfile, CDROMSTOP) == -1 )
- Com_DPrintf("ioctl cdromstop failed (%d)\n", errno);
-
- wasPlaying = false;
- playing = false;
-}
-
-void CDAudio_Pause(void)
-{
- if (cdfile == -1 || !enabled)
- return;
-
- if (!playing)
- return;
-
- if ( ioctl(cdfile, CDROMPAUSE) == -1 )
- Com_DPrintf("ioctl cdrompause failed\n");
-
- wasPlaying = playing;
- playing = false;
-}
-
-
-void CDAudio_Resume(void)
-{
- if (cdfile == -1 || !enabled)
- return;
-
- if (!cdValid)
- return;
-
- if (!wasPlaying)
- return;
-
- if ( ioctl(cdfile, CDROMRESUME) == -1 )
- Com_DPrintf("ioctl cdromresume failed\n");
- playing = true;
-}
-
-static void CD_f (void)
-{
- char *command;
- int ret;
- int n;
-
- if (Cmd_Argc() < 2)
- return;
-
- command = Cmd_Argv (1);
-
- if (Q_strcasecmp(command, "on") == 0)
- {
- enabled = true;
- return;
- }
-
- if (Q_strcasecmp(command, "off") == 0)
- {
- if (playing)
- CDAudio_Stop();
- enabled = false;
- return;
- }
-
- if (Q_strcasecmp(command, "reset") == 0)
- {
- enabled = true;
- if (playing)
- CDAudio_Stop();
- for (n = 0; n < 100; n++)
- remap[n] = n;
- CDAudio_GetAudioDiskInfo();
- return;
- }
-
- if (Q_strcasecmp(command, "remap") == 0)
- {
- ret = Cmd_Argc() - 2;
- if (ret <= 0)
- {
- for (n = 1; n < 100; n++)
- if (remap[n] != n)
- Com_Printf(" %u -> %u\n", n, remap[n]);
- return;
- }
- for (n = 1; n <= ret; n++)
- remap[n] = atoi(Cmd_Argv (n+1));
- return;
- }
-
- if (Q_strcasecmp(command, "close") == 0)
- {
- CDAudio_CloseDoor();
- return;
- }
-
- if (!cdValid)
- {
- CDAudio_GetAudioDiskInfo();
- if (!cdValid)
- {
- Com_Printf("No CD in player.\n");
- return;
- }
- }
-
- if (Q_strcasecmp(command, "play") == 0)
- {
- CDAudio_Play((byte)atoi(Cmd_Argv (2)), false);
- return;
- }
-
- if (Q_strcasecmp(command, "loop") == 0)
- {
- CDAudio_Play((byte)atoi(Cmd_Argv (2)), true);
- return;
- }
-
- if (Q_strcasecmp(command, "stop") == 0)
- {
- CDAudio_Stop();
- return;
- }
-
- if (Q_strcasecmp(command, "pause") == 0)
- {
- CDAudio_Pause();
- return;
- }
-
- if (Q_strcasecmp(command, "resume") == 0)
- {
- CDAudio_Resume();
- return;
- }
-
- if (Q_strcasecmp(command, "eject") == 0)
- {
- if (playing)
- CDAudio_Stop();
- CDAudio_Eject();
- cdValid = false;
- return;
- }
-
- if (Q_strcasecmp(command, "info") == 0)
- {
- Com_Printf("%u tracks\n", maxTrack);
- if (playing)
- Com_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
- else if (wasPlaying)
- Com_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
- Com_Printf("Volume is %f\n", cdvolume);
- return;
- }
-}
-
-void CDAudio_Update(void)
-{
- struct cdrom_subchnl subchnl;
- static time_t lastchk;
-
- if (cdfile == -1 || !enabled)
- return;
-
- if (cd_volume && cd_volume->value != cdvolume)
- {
- if (cdvolume)
- {
- Cvar_SetValue ("cd_volume", 0.0);
- cdvolume = cd_volume->value;
- CDAudio_Pause ();
- }
- else
- {
- Cvar_SetValue ("cd_volume", 1.0);
- cdvolume = cd_volume->value;
- CDAudio_Resume ();
- }
- }
-
- if (playing && lastchk < time(NULL)) {
- lastchk = time(NULL) + 2; //two seconds between chks
- subchnl.cdsc_format = CDROM_MSF;
- if (ioctl(cdfile, CDROMSUBCHNL, &subchnl) == -1 ) {
- Com_DPrintf("ioctl cdromsubchnl failed\n");
- playing = false;
- return;
- }
- if (subchnl.cdsc_audiostatus != CDROM_AUDIO_PLAY &&
- subchnl.cdsc_audiostatus != CDROM_AUDIO_PAUSED) {
- playing = false;
- if (playLooping)
- CDAudio_Play(playTrack, true);
- }
- }
-}
-
-int CDAudio_Init(void)
-{
- int i;
- cvar_t *cv;
- extern uid_t saved_euid;
-
- cv = Cvar_Get ("nocdaudio", "0", CVAR_NOSET);
- if (cv->value)
- return -1;
-
- cd_nocd = Cvar_Get ("cd_nocd", "0", CVAR_ARCHIVE );
- if ( cd_nocd->value)
- return -1;
-
- cd_volume = Cvar_Get ("cd_volume", "1", CVAR_ARCHIVE);
-
- cd_dev = Cvar_Get("cd_dev", "/dev/cdrom", CVAR_ARCHIVE);
-
- seteuid(saved_euid);
-
- cdfile = open(cd_dev->string, O_RDONLY);
-
- seteuid(getuid());
-
- if (cdfile == -1) {
- Com_Printf("CDAudio_Init: open of \"%s\" failed (%i)\n", cd_dev->string, errno);
- cdfile = -1;
- return -1;
- }
-
- for (i = 0; i < 100; i++)
- remap[i] = i;
- initialized = true;
- enabled = true;
-
- if (CDAudio_GetAudioDiskInfo())
- {
- Com_Printf("CDAudio_Init: No CD in player.\n");
- cdValid = false;
- }
-
- Cmd_AddCommand ("cd", CD_f);
-
- Com_Printf("CD Audio Initialized\n");
-
- return 0;
-}
-
-void CDAudio_Activate (qboolean active)
-{
- if (active)
- CDAudio_Resume ();
- else
- CDAudio_Pause ();
-}
-
-void CDAudio_Shutdown(void)
-{
- if (!initialized)
- return;
- CDAudio_Stop();
- close(cdfile);
- cdfile = -1;
-}
--- /dev/null
+++ b/plan9/in_9.c
@@ -1,0 +1,29 @@
+// in_null.c -- for systems without a mouse
+
+#include "../client/client.h"
+
+cvar_t *in_mouse;
+cvar_t *in_joystick;
+
+void IN_Init (void)
+{
+ in_mouse = Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE);
+ in_joystick = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE);
+}
+
+void IN_Shutdown (void)
+{
+}
+
+void IN_Commands (void)
+{
+}
+
+void IN_Move (usercmd_t *cmd)
+{
+}
+
+void IN_Activate (qboolean active)
+{
+}
+
--- a/plan9/in_linux.c
+++ /dev/null
@@ -1,29 +1,0 @@
-// in_null.c -- for systems without a mouse
-
-#include "../client/client.h"
-
-cvar_t *in_mouse;
-cvar_t *in_joystick;
-
-void IN_Init (void)
-{
- in_mouse = Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE);
- in_joystick = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE);
-}
-
-void IN_Shutdown (void)
-{
-}
-
-void IN_Commands (void)
-{
-}
-
-void IN_Move (usercmd_t *cmd)
-{
-}
-
-void IN_Activate (qboolean active)
-{
-}
-
--- /dev/null
+++ b/plan9/q_sh9.c
@@ -1,0 +1,205 @@
+#include <sys/types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+
+#include "../linux/glob.h"
+
+#include "../qcommon/qcommon.h"
+
+//===============================================================================
+
+byte *membase;
+int maxhunksize;
+int curhunksize;
+
+void *Hunk_Begin (int maxsize)
+{
+ // reserve a huge chunk of memory, but don't commit any yet
+ maxhunksize = maxsize + sizeof(int);
+ curhunksize = 0;
+ membase = mmap(0, maxhunksize, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if (membase == NULL || membase == (byte *)-1)
+ Sys_Error("unable to virtual allocate %d bytes", maxsize);
+
+ *((int *)membase) = curhunksize;
+
+ return membase + sizeof(int);
+}
+
+void *Hunk_Alloc (int size)
+{
+ byte *buf;
+
+ // round to cacheline
+ size = (size+31)&~31;
+ if (curhunksize + size > maxhunksize)
+ Sys_Error("Hunk_Alloc overflow");
+ buf = membase + sizeof(int) + curhunksize;
+ curhunksize += size;
+ return buf;
+}
+
+int Hunk_End (void)
+{
+ byte *n;
+
+ n = mremap(membase, maxhunksize, curhunksize + sizeof(int), 0);
+ if (n != membase)
+ Sys_Error("Hunk_End: Could not remap virtual block (%d)", errno);
+ *((int *)membase) = curhunksize + sizeof(int);
+
+ return curhunksize;
+}
+
+void Hunk_Free (void *base)
+{
+ byte *m;
+
+ if (base) {
+ m = ((byte *)base) - sizeof(int);
+ if (munmap(m, *((int *)m)))
+ Sys_Error("Hunk_Free: munmap failed (%d)", errno);
+ }
+}
+
+//===============================================================================
+
+
+/*
+================
+Sys_Milliseconds
+================
+*/
+int curtime;
+int Sys_Milliseconds (void)
+{
+ struct timeval tp;
+ struct timezone tzp;
+ static int secbase;
+
+ gettimeofday(&tp, &tzp);
+
+ if (!secbase)
+ {
+ secbase = tp.tv_sec;
+ return tp.tv_usec/1000;
+ }
+
+ curtime = (tp.tv_sec - secbase)*1000 + tp.tv_usec/1000;
+
+ return curtime;
+}
+
+void Sys_Mkdir (char *path)
+{
+ mkdir (path, 0777);
+}
+
+char *strlwr (char *s)
+{
+ while (*s) {
+ *s = tolower(*s);
+ s++;
+ }
+}
+
+//============================================
+
+static char findbase[MAX_OSPATH];
+static char findpath[MAX_OSPATH];
+static char findpattern[MAX_OSPATH];
+static DIR *fdir;
+
+static qboolean CompareAttributes(char *path, char *name,
+ unsigned musthave, unsigned canthave )
+{
+ struct stat st;
+ char fn[MAX_OSPATH];
+
+// . and .. never match
+ if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
+ return false;
+
+ sprintf(fn, "%s/%s", path, name);
+ if (stat(fn, &st) == -1)
+ return false; // shouldn't happen
+
+ if ( ( st.st_mode & S_IFDIR ) && ( canthave & SFF_SUBDIR ) )
+ return false;
+
+ if ( ( musthave & SFF_SUBDIR ) && !( st.st_mode & S_IFDIR ) )
+ return false;
+
+ return true;
+}
+
+char *Sys_FindFirst (char *path, unsigned musthave, unsigned canhave)
+{
+ struct dirent *d;
+ char *p;
+
+ if (fdir)
+ Sys_Error ("Sys_BeginFind without close");
+
+// COM_FilePath (path, findbase);
+ strcpy(findbase, path);
+
+ if ((p = strrchr(findbase, '/')) != NULL) {
+ *p = 0;
+ strcpy(findpattern, p + 1);
+ } else
+ strcpy(findpattern, "*");
+
+ if (strcmp(findpattern, "*.*") == 0)
+ strcpy(findpattern, "*");
+
+ if ((fdir = opendir(findbase)) == NULL)
+ return NULL;
+ while ((d = readdir(fdir)) != NULL) {
+ if (!*findpattern || glob_match(findpattern, d->d_name)) {
+// if (*findpattern)
+// printf("%s matched %s\n", findpattern, d->d_name);
+ if (CompareAttributes(findbase, d->d_name, musthave, canhave)) {
+ sprintf (findpath, "%s/%s", findbase, d->d_name);
+ return findpath;
+ }
+ }
+ }
+ return NULL;
+}
+
+char *Sys_FindNext (unsigned musthave, unsigned canhave)
+{
+ struct dirent *d;
+
+ if (fdir == NULL)
+ return NULL;
+ while ((d = readdir(fdir)) != NULL) {
+ if (!*findpattern || glob_match(findpattern, d->d_name)) {
+// if (*findpattern)
+// printf("%s matched %s\n", findpattern, d->d_name);
+ if (CompareAttributes(findbase, d->d_name, musthave, canhave)) {
+ sprintf (findpath, "%s/%s", findbase, d->d_name);
+ return findpath;
+ }
+ }
+ }
+ return NULL;
+}
+
+void Sys_FindClose (void)
+{
+ if (fdir != NULL)
+ closedir(fdir);
+ fdir = NULL;
+}
+
+
+//============================================
+
--- a/plan9/q_shlinux.c
+++ /dev/null
@@ -1,205 +1,0 @@
-#include <sys/types.h>
-#include <errno.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-
-#include "../linux/glob.h"
-
-#include "../qcommon/qcommon.h"
-
-//===============================================================================
-
-byte *membase;
-int maxhunksize;
-int curhunksize;
-
-void *Hunk_Begin (int maxsize)
-{
- // reserve a huge chunk of memory, but don't commit any yet
- maxhunksize = maxsize + sizeof(int);
- curhunksize = 0;
- membase = mmap(0, maxhunksize, PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
- if (membase == NULL || membase == (byte *)-1)
- Sys_Error("unable to virtual allocate %d bytes", maxsize);
-
- *((int *)membase) = curhunksize;
-
- return membase + sizeof(int);
-}
-
-void *Hunk_Alloc (int size)
-{
- byte *buf;
-
- // round to cacheline
- size = (size+31)&~31;
- if (curhunksize + size > maxhunksize)
- Sys_Error("Hunk_Alloc overflow");
- buf = membase + sizeof(int) + curhunksize;
- curhunksize += size;
- return buf;
-}
-
-int Hunk_End (void)
-{
- byte *n;
-
- n = mremap(membase, maxhunksize, curhunksize + sizeof(int), 0);
- if (n != membase)
- Sys_Error("Hunk_End: Could not remap virtual block (%d)", errno);
- *((int *)membase) = curhunksize + sizeof(int);
-
- return curhunksize;
-}
-
-void Hunk_Free (void *base)
-{
- byte *m;
-
- if (base) {
- m = ((byte *)base) - sizeof(int);
- if (munmap(m, *((int *)m)))
- Sys_Error("Hunk_Free: munmap failed (%d)", errno);
- }
-}
-
-//===============================================================================
-
-
-/*
-================
-Sys_Milliseconds
-================
-*/
-int curtime;
-int Sys_Milliseconds (void)
-{
- struct timeval tp;
- struct timezone tzp;
- static int secbase;
-
- gettimeofday(&tp, &tzp);
-
- if (!secbase)
- {
- secbase = tp.tv_sec;
- return tp.tv_usec/1000;
- }
-
- curtime = (tp.tv_sec - secbase)*1000 + tp.tv_usec/1000;
-
- return curtime;
-}
-
-void Sys_Mkdir (char *path)
-{
- mkdir (path, 0777);
-}
-
-char *strlwr (char *s)
-{
- while (*s) {
- *s = tolower(*s);
- s++;
- }
-}
-
-//============================================
-
-static char findbase[MAX_OSPATH];
-static char findpath[MAX_OSPATH];
-static char findpattern[MAX_OSPATH];
-static DIR *fdir;
-
-static qboolean CompareAttributes(char *path, char *name,
- unsigned musthave, unsigned canthave )
-{
- struct stat st;
- char fn[MAX_OSPATH];
-
-// . and .. never match
- if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
- return false;
-
- sprintf(fn, "%s/%s", path, name);
- if (stat(fn, &st) == -1)
- return false; // shouldn't happen
-
- if ( ( st.st_mode & S_IFDIR ) && ( canthave & SFF_SUBDIR ) )
- return false;
-
- if ( ( musthave & SFF_SUBDIR ) && !( st.st_mode & S_IFDIR ) )
- return false;
-
- return true;
-}
-
-char *Sys_FindFirst (char *path, unsigned musthave, unsigned canhave)
-{
- struct dirent *d;
- char *p;
-
- if (fdir)
- Sys_Error ("Sys_BeginFind without close");
-
-// COM_FilePath (path, findbase);
- strcpy(findbase, path);
-
- if ((p = strrchr(findbase, '/')) != NULL) {
- *p = 0;
- strcpy(findpattern, p + 1);
- } else
- strcpy(findpattern, "*");
-
- if (strcmp(findpattern, "*.*") == 0)
- strcpy(findpattern, "*");
-
- if ((fdir = opendir(findbase)) == NULL)
- return NULL;
- while ((d = readdir(fdir)) != NULL) {
- if (!*findpattern || glob_match(findpattern, d->d_name)) {
-// if (*findpattern)
-// printf("%s matched %s\n", findpattern, d->d_name);
- if (CompareAttributes(findbase, d->d_name, musthave, canhave)) {
- sprintf (findpath, "%s/%s", findbase, d->d_name);
- return findpath;
- }
- }
- }
- return NULL;
-}
-
-char *Sys_FindNext (unsigned musthave, unsigned canhave)
-{
- struct dirent *d;
-
- if (fdir == NULL)
- return NULL;
- while ((d = readdir(fdir)) != NULL) {
- if (!*findpattern || glob_match(findpattern, d->d_name)) {
-// if (*findpattern)
-// printf("%s matched %s\n", findpattern, d->d_name);
- if (CompareAttributes(findbase, d->d_name, musthave, canhave)) {
- sprintf (findpath, "%s/%s", findbase, d->d_name);
- return findpath;
- }
- }
- }
- return NULL;
-}
-
-void Sys_FindClose (void)
-{
- if (fdir != NULL)
- closedir(fdir);
- fdir = NULL;
-}
-
-
-//============================================
-
--- /dev/null
+++ b/plan9/rw_9.c
@@ -1,0 +1,1093 @@
+/*
+** RW_X11.C
+**
+** This file contains ALL Linux specific stuff having to do with the
+** software refresh. When a port is being made the following functions
+** must be implemented by the port:
+**
+** SWimp_EndFrame
+** SWimp_Init
+** SWimp_InitGraphics
+** SWimp_SetPalette
+** SWimp_Shutdown
+** SWimp_SwitchFullscreen
+*/
+
+#include <ctype.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/extensions/XShm.h>
+
+#include "../ref_soft/r_local.h"
+#include "../client/keys.h"
+#include "../linux/rw_linux.h"
+
+/*****************************************************************************/
+
+static qboolean doShm;
+static Display *x_disp;
+static Colormap x_cmap;
+static Window x_win;
+static GC x_gc;
+static Visual *x_vis;
+static XVisualInfo *x_visinfo;
+//static XImage *x_image;
+
+#define STD_EVENT_MASK (StructureNotifyMask | KeyPressMask \
+ | KeyReleaseMask | ExposureMask | PointerMotionMask | \
+ ButtonPressMask | ButtonReleaseMask)
+
+static int x_shmeventtype;
+//static XShmSegmentInfo x_shminfo;
+
+static qboolean oktodraw = false;
+static qboolean X11_active = false;
+
+int XShmQueryExtension(Display *);
+int XShmGetEventBase(Display *);
+
+int current_framebuffer;
+static XImage *x_framebuffer[2] = { 0, 0 };
+static XShmSegmentInfo x_shminfo[2];
+
+struct
+{
+ int key;
+ int down;
+} keyq[64];
+int keyq_head=0;
+int keyq_tail=0;
+
+int config_notify=0;
+int config_notify_width;
+int config_notify_height;
+
+typedef unsigned short PIXEL;
+
+// Console variables that we need to access from this module
+
+/*****************************************************************************/
+/* MOUSE */
+/*****************************************************************************/
+
+// this is inside the renderer shared lib, so these are called from vid_so
+
+static qboolean mouse_avail;
+static int mouse_buttonstate;
+static int mouse_oldbuttonstate;
+static int mouse_x, mouse_y;
+static int old_mouse_x, old_mouse_y;
+static int mx, my;
+static float old_windowed_mouse;
+static int p_mouse_x, p_mouse_y;
+
+static cvar_t *_windowed_mouse;
+static cvar_t *m_filter;
+static cvar_t *in_mouse;
+
+static qboolean mlooking;
+
+// state struct passed in Init
+static in_state_t *in_state;
+
+static cvar_t *sensitivity;
+static cvar_t *lookstrafe;
+static cvar_t *m_side;
+static cvar_t *m_yaw;
+static cvar_t *m_pitch;
+static cvar_t *m_forward;
+static cvar_t *freelook;
+
+static void Force_CenterView_f (void)
+{
+ in_state->viewangles[PITCH] = 0;
+}
+
+static void RW_IN_MLookDown (void)
+{
+ mlooking = true;
+}
+
+static void RW_IN_MLookUp (void)
+{
+ mlooking = false;
+ in_state->IN_CenterView_fp ();
+}
+
+void RW_IN_Init(in_state_t *in_state_p)
+{
+ int mtype;
+ int i;
+
+ in_state = in_state_p;
+
+ // mouse variables
+ _windowed_mouse = ri.Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE);
+ m_filter = ri.Cvar_Get ("m_filter", "0", 0);
+ in_mouse = ri.Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE);
+ freelook = ri.Cvar_Get( "freelook", "0", 0 );
+ lookstrafe = ri.Cvar_Get ("lookstrafe", "0", 0);
+ sensitivity = ri.Cvar_Get ("sensitivity", "3", 0);
+ m_pitch = ri.Cvar_Get ("m_pitch", "0.022", 0);
+ m_yaw = ri.Cvar_Get ("m_yaw", "0.022", 0);
+ m_forward = ri.Cvar_Get ("m_forward", "1", 0);
+ m_side = ri.Cvar_Get ("m_side", "0.8", 0);
+
+ ri.Cmd_AddCommand ("+mlook", RW_IN_MLookDown);
+ ri.Cmd_AddCommand ("-mlook", RW_IN_MLookUp);
+
+ ri.Cmd_AddCommand ("force_centerview", Force_CenterView_f);
+
+ mouse_x = mouse_y = 0.0;
+ mouse_avail = true;
+}
+
+void RW_IN_Shutdown(void)
+{
+ mouse_avail = false;
+}
+
+/*
+===========
+IN_Commands
+===========
+*/
+void RW_IN_Commands (void)
+{
+ int i;
+
+ if (!mouse_avail)
+ return;
+
+ for (i=0 ; i<3 ; i++) {
+ if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
+ in_state->Key_Event_fp (K_MOUSE1 + i, true);
+
+ if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
+ in_state->Key_Event_fp (K_MOUSE1 + i, false);
+ }
+ mouse_oldbuttonstate = mouse_buttonstate;
+}
+
+/*
+===========
+IN_Move
+===========
+*/
+void RW_IN_Move (usercmd_t *cmd)
+{
+ if (!mouse_avail)
+ return;
+
+ if (m_filter->value)
+ {
+ mouse_x = (mx + old_mouse_x) * 0.5;
+ mouse_y = (my + old_mouse_y) * 0.5;
+ } else {
+ mouse_x = mx;
+ mouse_y = my;
+ }
+
+ old_mouse_x = mx;
+ old_mouse_y = my;
+
+ if (!mouse_x && !mouse_y)
+ return;
+
+ mouse_x *= sensitivity->value;
+ mouse_y *= sensitivity->value;
+
+// add mouse X/Y movement to cmd
+ if ( (*in_state->in_strafe_state & 1) ||
+ (lookstrafe->value && mlooking ))
+ cmd->sidemove += m_side->value * mouse_x;
+ else
+ in_state->viewangles[YAW] -= m_yaw->value * mouse_x;
+
+ if ( (mlooking || freelook->value) &&
+ !(*in_state->in_strafe_state & 1))
+ {
+ in_state->viewangles[PITCH] += m_pitch->value * mouse_y;
+ }
+ else
+ {
+ cmd->forwardmove -= m_forward->value * mouse_y;
+ }
+ mx = my = 0;
+}
+
+void RW_IN_Frame (void)
+{
+}
+
+void RW_IN_Activate(void)
+{
+}
+
+/*****************************************************************************/
+
+static PIXEL st2d_8to16table[256];
+static int shiftmask_fl=0;
+static long r_shift,g_shift,b_shift;
+static unsigned long r_mask,g_mask,b_mask;
+
+void shiftmask_init()
+{
+ unsigned int x;
+ r_mask=x_vis->red_mask;
+ g_mask=x_vis->green_mask;
+ b_mask=x_vis->blue_mask;
+ for(r_shift=-8,x=1;x<r_mask;x=x<<1)r_shift++;
+ for(g_shift=-8,x=1;x<g_mask;x=x<<1)g_shift++;
+ for(b_shift=-8,x=1;x<b_mask;x=x<<1)b_shift++;
+ shiftmask_fl=1;
+}
+
+PIXEL xlib_rgb(int r,int g,int b)
+{
+ PIXEL p;
+ if(shiftmask_fl==0) shiftmask_init();
+ p=0;
+
+ if(r_shift>0) {
+ p=(r<<(r_shift))&r_mask;
+ } else if(r_shift<0) {
+ p=(r>>(-r_shift))&r_mask;
+ } else p|=(r&r_mask);
+
+ if(g_shift>0) {
+ p|=(g<<(g_shift))&g_mask;
+ } else if(g_shift<0) {
+ p|=(g>>(-g_shift))&g_mask;
+ } else p|=(g&g_mask);
+
+ if(b_shift>0) {
+ p|=(b<<(b_shift))&b_mask;
+ } else if(b_shift<0) {
+ p|=(b>>(-b_shift))&b_mask;
+ } else p|=(b&b_mask);
+
+ return p;
+}
+
+void st2_fixup( XImage *framebuf, int x, int y, int width, int height)
+{
+ int xi,yi;
+ unsigned char *src;
+ PIXEL *dest;
+
+ if( (x<0)||(y<0) )return;
+
+ for (yi = y; yi < (y+height); yi++) {
+ src = &framebuf->data [yi * framebuf->bytes_per_line];
+ dest = (PIXEL*)src;
+ for(xi = (x+width-1); xi >= x; xi -= 8) {
+ dest[xi ] = st2d_8to16table[src[xi ]];
+ dest[xi-1] = st2d_8to16table[src[xi-1]];
+ dest[xi-2] = st2d_8to16table[src[xi-2]];
+ dest[xi-3] = st2d_8to16table[src[xi-3]];
+ dest[xi-4] = st2d_8to16table[src[xi-4]];
+ dest[xi-5] = st2d_8to16table[src[xi-5]];
+ dest[xi-6] = st2d_8to16table[src[xi-6]];
+ dest[xi-7] = st2d_8to16table[src[xi-7]];
+ }
+ }
+}
+
+// ========================================================================
+// makes a null cursor
+// ========================================================================
+
+static Cursor CreateNullCursor(Display *display, Window root)
+{
+ Pixmap cursormask;
+ XGCValues xgc;
+ GC gc;
+ XColor dummycolour;
+ Cursor cursor;
+
+ cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
+ xgc.function = GXclear;
+ gc = XCreateGC(display, cursormask, GCFunction, &xgc);
+ XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
+ dummycolour.pixel = 0;
+ dummycolour.red = 0;
+ dummycolour.flags = 04;
+ cursor = XCreatePixmapCursor(display, cursormask, cursormask,
+ &dummycolour,&dummycolour, 0,0);
+ XFreePixmap(display,cursormask);
+ XFreeGC(display,gc);
+ return cursor;
+}
+
+void ResetFrameBuffer(void)
+{
+ int mem;
+ int pwidth;
+
+ if (x_framebuffer[0])
+ {
+ free(x_framebuffer[0]->data);
+ free(x_framebuffer[0]);
+ }
+
+// alloc an extra line in case we want to wrap, and allocate the z-buffer
+ pwidth = x_visinfo->depth / 8;
+ if (pwidth == 3) pwidth = 4;
+ mem = ((vid.width*pwidth+7)&~7) * vid.height;
+
+ x_framebuffer[0] = XCreateImage( x_disp,
+ x_vis,
+ x_visinfo->depth,
+ ZPixmap,
+ 0,
+ malloc(mem),
+ vid.width, vid.height,
+ 32,
+ 0);
+
+ if (!x_framebuffer[0])
+ Sys_Error("VID: XCreateImage failed\n");
+
+ vid.buffer = (byte*) (x_framebuffer[0]);
+}
+
+void ResetSharedFrameBuffers(void)
+{
+ int size;
+ int key;
+ int minsize = getpagesize();
+ int frm;
+
+ for (frm=0 ; frm<2 ; frm++)
+ {
+ // free up old frame buffer memory
+ if (x_framebuffer[frm])
+ {
+ XShmDetach(x_disp, &x_shminfo[frm]);
+ free(x_framebuffer[frm]);
+ shmdt(x_shminfo[frm].shmaddr);
+ }
+
+ // create the image
+ x_framebuffer[frm] = XShmCreateImage( x_disp,
+ x_vis,
+ x_visinfo->depth,
+ ZPixmap,
+ 0,
+ &x_shminfo[frm],
+ vid.width,
+ vid.height );
+
+ // grab shared memory
+
+ size = x_framebuffer[frm]->bytes_per_line
+ * x_framebuffer[frm]->height;
+ if (size < minsize)
+ Sys_Error("VID: Window must use at least %d bytes\n", minsize);
+
+ key = random();
+ x_shminfo[frm].shmid = shmget((key_t)key, size, IPC_CREAT|0777);
+ if (x_shminfo[frm].shmid==-1)
+ Sys_Error("VID: Could not get any shared memory\n");
+
+ // attach to the shared memory segment
+ x_shminfo[frm].shmaddr =
+ (void *) shmat(x_shminfo[frm].shmid, 0, 0);
+
+ ri.Con_Printf(PRINT_ALL,
+ "MITSHM shared memory (id=%d, addr=0x%lx)\n",
+ x_shminfo[frm].shmid,
+ (long) x_shminfo[frm].shmaddr);
+
+ x_framebuffer[frm]->data = x_shminfo[frm].shmaddr;
+
+ // get the X server to attach to it
+
+ if (!XShmAttach(x_disp, &x_shminfo[frm]))
+ Sys_Error("VID: XShmAttach() failed\n");
+ XSync(x_disp, 0);
+ shmctl(x_shminfo[frm].shmid, IPC_RMID, 0);
+ }
+
+}
+
+// ========================================================================
+// Tragic death handler
+// ========================================================================
+
+void TragicDeath(int signal_num)
+{
+ XAutoRepeatOn(x_disp);
+ XCloseDisplay(x_disp);
+ Sys_Error("This death brought to you by the number %d\n", signal_num);
+}
+
+int XLateKey(XKeyEvent *ev)
+{
+
+ int key;
+ char buf[64];
+ KeySym keysym;
+
+ key = 0;
+
+ XLookupString(ev, buf, sizeof buf, &keysym, 0);
+
+ switch(keysym)
+ {
+ case XK_KP_Page_Up: key = K_KP_PGUP; break;
+ case XK_Page_Up: key = K_PGUP; break;
+
+ case XK_KP_Page_Down: key = K_KP_PGDN; break;
+ case XK_Page_Down: key = K_PGDN; break;
+
+ case XK_KP_Home: key = K_KP_HOME; break;
+ case XK_Home: key = K_HOME; break;
+
+ case XK_KP_End: key = K_KP_END; break;
+ case XK_End: key = K_END; break;
+
+ case XK_KP_Left: key = K_KP_LEFTARROW; break;
+ case XK_Left: key = K_LEFTARROW; break;
+
+ case XK_KP_Right: key = K_KP_RIGHTARROW; break;
+ case XK_Right: key = K_RIGHTARROW; break;
+
+ case XK_KP_Down: key = K_KP_DOWNARROW; break;
+ case XK_Down: key = K_DOWNARROW; break;
+
+ case XK_KP_Up: key = K_KP_UPARROW; break;
+ case XK_Up: key = K_UPARROW; break;
+
+ case XK_Escape: key = K_ESCAPE; break;
+
+ case XK_KP_Enter: key = K_KP_ENTER; break;
+ case XK_Return: key = K_ENTER; break;
+
+ case XK_Tab: key = K_TAB; break;
+
+ case XK_F1: key = K_F1; break;
+
+ case XK_F2: key = K_F2; break;
+
+ case XK_F3: key = K_F3; break;
+
+ case XK_F4: key = K_F4; break;
+
+ case XK_F5: key = K_F5; break;
+
+ case XK_F6: key = K_F6; break;
+
+ case XK_F7: key = K_F7; break;
+
+ case XK_F8: key = K_F8; break;
+
+ case XK_F9: key = K_F9; break;
+
+ case XK_F10: key = K_F10; break;
+
+ case XK_F11: key = K_F11; break;
+
+ case XK_F12: key = K_F12; break;
+
+ case XK_BackSpace: key = K_BACKSPACE; break;
+
+ case XK_KP_Delete: key = K_KP_DEL; break;
+ case XK_Delete: key = K_DEL; break;
+
+ case XK_Pause: key = K_PAUSE; break;
+
+ case XK_Shift_L:
+ case XK_Shift_R: key = K_SHIFT; break;
+
+ case XK_Execute:
+ case XK_Control_L:
+ case XK_Control_R: key = K_CTRL; break;
+
+ case XK_Alt_L:
+ case XK_Meta_L:
+ case XK_Alt_R:
+ case XK_Meta_R: key = K_ALT; break;
+
+ case XK_KP_Begin: key = K_KP_5; break;
+
+ case XK_Insert:key = K_INS; break;
+ case XK_KP_Insert: key = K_KP_INS; break;
+
+ case XK_KP_Multiply: key = '*'; break;
+ case XK_KP_Add: key = K_KP_PLUS; break;
+ case XK_KP_Subtract: key = K_KP_MINUS; break;
+ case XK_KP_Divide: key = K_KP_SLASH; break;
+
+#if 0
+ case 0x021: key = '1';break;/* [!] */
+ case 0x040: key = '2';break;/* [@] */
+ case 0x023: key = '3';break;/* [#] */
+ case 0x024: key = '4';break;/* [$] */
+ case 0x025: key = '5';break;/* [%] */
+ case 0x05e: key = '6';break;/* [^] */
+ case 0x026: key = '7';break;/* [&] */
+ case 0x02a: key = '8';break;/* [*] */
+ case 0x028: key = '9';;break;/* [(] */
+ case 0x029: key = '0';break;/* [)] */
+ case 0x05f: key = '-';break;/* [_] */
+ case 0x02b: key = '=';break;/* [+] */
+ case 0x07c: key = '\'';break;/* [|] */
+ case 0x07d: key = '[';break;/* [}] */
+ case 0x07b: key = ']';break;/* [{] */
+ case 0x022: key = '\'';break;/* ["] */
+ case 0x03a: key = ';';break;/* [:] */
+ case 0x03f: key = '/';break;/* [?] */
+ case 0x03e: key = '.';break;/* [>] */
+ case 0x03c: key = ',';break;/* [<] */
+#endif
+
+ default:
+ key = *(unsigned char*)buf;
+ if (key >= 'A' && key <= 'Z')
+ key = key - 'A' + 'a';
+ break;
+ }
+
+ return key;
+}
+
+void GetEvent(void)
+{
+ XEvent x_event;
+ int b;
+
+ XNextEvent(x_disp, &x_event);
+ switch(x_event.type) {
+ case KeyPress:
+ keyq[keyq_head].key = XLateKey(&x_event.xkey);
+ keyq[keyq_head].down = true;
+ keyq_head = (keyq_head + 1) & 63;
+ break;
+ case KeyRelease:
+ keyq[keyq_head].key = XLateKey(&x_event.xkey);
+ keyq[keyq_head].down = false;
+ keyq_head = (keyq_head + 1) & 63;
+ break;
+
+ case MotionNotify:
+ if (_windowed_mouse->value) {
+ mx += ((int)x_event.xmotion.x - (int)(vid.width/2));
+ my += ((int)x_event.xmotion.y - (int)(vid.height/2));
+
+ /* move the mouse to the window center again */
+ XSelectInput(x_disp,x_win, STD_EVENT_MASK & ~PointerMotionMask);
+ XWarpPointer(x_disp,None,x_win,0,0,0,0,
+ (vid.width/2),(vid.height/2));
+ XSelectInput(x_disp,x_win, STD_EVENT_MASK);
+ } else {
+ mx = ((int)x_event.xmotion.x - (int)p_mouse_x);
+ my = ((int)x_event.xmotion.y - (int)p_mouse_y);
+ p_mouse_x=x_event.xmotion.x;
+ p_mouse_y=x_event.xmotion.y;
+ }
+ break;
+
+ case ButtonPress:
+ b=-1;
+ if (x_event.xbutton.button == 1)
+ b = 0;
+ else if (x_event.xbutton.button == 2)
+ b = 2;
+ else if (x_event.xbutton.button == 3)
+ b = 1;
+ if (b>=0)
+ mouse_buttonstate |= 1<<b;
+ break;
+
+ case ButtonRelease:
+ b=-1;
+ if (x_event.xbutton.button == 1)
+ b = 0;
+ else if (x_event.xbutton.button == 2)
+ b = 2;
+ else if (x_event.xbutton.button == 3)
+ b = 1;
+ if (b>=0)
+ mouse_buttonstate &= ~(1<<b);
+ break;
+
+ case ConfigureNotify:
+ config_notify_width = x_event.xconfigure.width;
+ config_notify_height = x_event.xconfigure.height;
+ config_notify = 1;
+ break;
+
+ default:
+ if (doShm && x_event.type == x_shmeventtype)
+ oktodraw = true;
+ }
+
+ if (old_windowed_mouse != _windowed_mouse->value) {
+ old_windowed_mouse = _windowed_mouse->value;
+
+ if (!_windowed_mouse->value) {
+ /* ungrab the pointer */
+ XUngrabPointer(x_disp,CurrentTime);
+ } else {
+ /* grab the pointer */
+ XGrabPointer(x_disp,x_win,True,0,GrabModeAsync,
+ GrabModeAsync,x_win,None,CurrentTime);
+ }
+ }
+}
+
+/*****************************************************************************/
+
+/*
+** SWimp_Init
+**
+** This routine is responsible for initializing the implementation
+** specific stuff in a software rendering subsystem.
+*/
+int SWimp_Init( void *hInstance, void *wndProc )
+{
+// open the display
+ x_disp = XOpenDisplay(0);
+ if (!x_disp)
+ {
+ if (getenv("DISPLAY"))
+ Sys_Error("VID: Could not open display [%s]\n",
+ getenv("DISPLAY"));
+ else
+ Sys_Error("VID: Could not open local display\n");
+ }
+
+// catch signals so i can turn on auto-repeat
+
+ {
+ struct sigaction sa;
+ sigaction(SIGINT, 0, &sa);
+ sa.sa_handler = TragicDeath;
+ sigaction(SIGINT, &sa, 0);
+ sigaction(SIGTERM, &sa, 0);
+ }
+
+ return true;
+}
+
+/*
+** SWimp_InitGraphics
+**
+** This initializes the software refresh's implementation specific
+** graphics subsystem. In the case of Windows it creates DIB or
+** DDRAW surfaces.
+**
+** The necessary width and height parameters are grabbed from
+** vid.width and vid.height.
+*/
+static qboolean SWimp_InitGraphics( qboolean fullscreen )
+{
+ int pnum, i;
+ XVisualInfo template;
+ int num_visuals;
+ int template_mask;
+
+ srandom(getpid());
+
+ // free resources in use
+ SWimp_Shutdown ();
+
+ // let the sound and input subsystems know about the new window
+ ri.Vid_NewWindow (vid.width, vid.height);
+
+ XAutoRepeatOff(x_disp);
+
+// for debugging only
+ XSynchronize(x_disp, True);
+
+// check for command-line window size
+ template_mask = 0;
+
+#if 0
+// specify a visual id
+ if ((pnum=COM_CheckParm("-visualid")))
+ {
+ if (pnum >= com_argc-1)
+ Sys_Error("VID: -visualid <id#>\n");
+ template.visualid = Q_atoi(com_argv[pnum+1]);
+ template_mask = VisualIDMask;
+ }
+
+// If not specified, use default visual
+ else
+#endif
+ {
+ int screen;
+ screen = XDefaultScreen(x_disp);
+ template.visualid =
+ XVisualIDFromVisual(XDefaultVisual(x_disp, screen));
+ template_mask = VisualIDMask;
+ }
+
+// pick a visual- warn if more than one was available
+ x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &num_visuals);
+ if (num_visuals > 1)
+ {
+ printf("Found more than one visual id at depth %d:\n", template.depth);
+ for (i=0 ; i<num_visuals ; i++)
+ printf(" -visualid %d\n", (int)(x_visinfo[i].visualid));
+ }
+ else if (num_visuals == 0)
+ {
+ if (template_mask == VisualIDMask)
+ Sys_Error("VID: Bad visual id %d\n", template.visualid);
+ else
+ Sys_Error("VID: No visuals at depth %d\n", template.depth);
+ }
+
+#if 0
+ if (verbose)
+ {
+ printf("Using visualid %d:\n", (int)(x_visinfo->visualid));
+ printf(" screen %d\n", x_visinfo->screen);
+ printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask));
+ printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask));
+ printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask));
+ printf(" colormap_size %d\n", x_visinfo->colormap_size);
+ printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb);
+ }
+#endif
+
+ x_vis = x_visinfo->visual;
+
+// setup attributes for main window
+ {
+ int attribmask = CWEventMask | CWColormap | CWBorderPixel;
+ XSetWindowAttributes attribs;
+ Colormap tmpcmap;
+
+ tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp,
+ x_visinfo->screen), x_vis, AllocNone);
+
+ attribs.event_mask = STD_EVENT_MASK;
+ attribs.border_pixel = 0;
+ attribs.colormap = tmpcmap;
+
+// create the main window
+ x_win = XCreateWindow( x_disp,
+ XRootWindow(x_disp, x_visinfo->screen),
+ 0, 0, // x, y
+ vid.width, vid.height,
+ 0, // borderwidth
+ x_visinfo->depth,
+ InputOutput,
+ x_vis,
+ attribmask,
+ &attribs );
+ XStoreName(x_disp, x_win, "Quake II");
+
+ if (x_visinfo->class != TrueColor)
+ XFreeColormap(x_disp, tmpcmap);
+ }
+
+ if (x_visinfo->depth == 8)
+ {
+ // create and upload the palette
+ if (x_visinfo->class == PseudoColor)
+ {
+ x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll);
+ XSetWindowColormap(x_disp, x_win, x_cmap);
+ }
+
+ }
+
+// inviso cursor
+ XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win));
+
+// create the GC
+ {
+ XGCValues xgcvalues;
+ int valuemask = GCGraphicsExposures;
+ xgcvalues.graphics_exposures = False;
+ x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues );
+ }
+
+// map the window
+ XMapWindow(x_disp, x_win);
+
+// wait for first exposure event
+ {
+ XEvent event;
+ do
+ {
+ XNextEvent(x_disp, &event);
+ if (event.type == Expose && !event.xexpose.count)
+ oktodraw = true;
+ } while (!oktodraw);
+ }
+// now safe to draw
+
+// even if MITSHM is available, make sure it's a local connection
+ if (XShmQueryExtension(x_disp))
+ {
+ char *displayname;
+ doShm = true;
+ displayname = (char *) getenv("DISPLAY");
+ if (displayname)
+ {
+ char *d = displayname;
+ while (*d && (*d != ':')) d++;
+ if (*d) *d = 0;
+ if (!(!strcasecmp(displayname, "unix") || !*displayname))
+ doShm = false;
+ }
+ }
+
+ if (doShm)
+ {
+ x_shmeventtype = XShmGetEventBase(x_disp) + ShmCompletion;
+ ResetSharedFrameBuffers();
+ }
+ else
+ ResetFrameBuffer();
+
+ current_framebuffer = 0;
+ vid.rowbytes = x_framebuffer[0]->bytes_per_line;
+ vid.buffer = x_framebuffer[0]->data;
+
+// XSynchronize(x_disp, False);
+
+ X11_active = true;
+
+ return true;
+}
+
+/*
+** SWimp_EndFrame
+**
+** This does an implementation specific copy from the backbuffer to the
+** front buffer. In the Win32 case it uses BitBlt or BltFast depending
+** on whether we're using DIB sections/GDI or DDRAW.
+*/
+void SWimp_EndFrame (void)
+{
+// if the window changes dimension, skip this frame
+#if 0
+ if (config_notify)
+ {
+ fprintf(stderr, "config notify\n");
+ config_notify = 0;
+ vid.width = config_notify_width & ~7;
+ vid.height = config_notify_height;
+ if (doShm)
+ ResetSharedFrameBuffers();
+ else
+ ResetFrameBuffer();
+ vid.rowbytes = x_framebuffer[0]->bytes_per_line;
+ vid.buffer = x_framebuffer[current_framebuffer]->data;
+ vid.recalc_refdef = 1; // force a surface cache flush
+ Con_CheckResize();
+ Con_Clear_f();
+ return;
+ }
+#endif
+
+ if (doShm)
+ {
+
+ if (x_visinfo->depth != 8)
+ st2_fixup( x_framebuffer[current_framebuffer],
+ 0, 0, vid.width, vid.height);
+ if (!XShmPutImage(x_disp, x_win, x_gc,
+ x_framebuffer[current_framebuffer], 0, 0,
+ 0, 0, vid.width, vid.height, True))
+ Sys_Error("VID_Update: XShmPutImage failed\n");
+ oktodraw = false;
+ while (!oktodraw)
+ GetEvent();
+ current_framebuffer = !current_framebuffer;
+ vid.buffer = x_framebuffer[current_framebuffer]->data;
+ XSync(x_disp, False);
+ }
+ else
+ {
+ if (x_visinfo->depth != 8)
+ st2_fixup( x_framebuffer[current_framebuffer],
+ 0, 0, vid.width, vid.height);
+ XPutImage(x_disp, x_win, x_gc, x_framebuffer[0],
+ 0, 0, 0, 0, vid.width, vid.height);
+ XSync(x_disp, False);
+ }
+}
+
+/*
+** SWimp_SetMode
+*/
+rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
+{
+ rserr_t retval = rserr_ok;
+
+ ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode );
+
+ if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) )
+ {
+ ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
+ return rserr_invalid_mode;
+ }
+
+ ri.Con_Printf( PRINT_ALL, " %d %d\n", *pwidth, *pheight);
+
+ if ( !SWimp_InitGraphics( false ) ) {
+ // failed to set a valid mode in windowed mode
+ return rserr_invalid_mode;
+ }
+
+ R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
+
+ return retval;
+}
+
+/*
+** SWimp_SetPalette
+**
+** System specific palette setting routine. A NULL palette means
+** to use the existing palette. The palette is expected to be in
+** a padded 4-byte xRGB format.
+*/
+void SWimp_SetPalette( const unsigned char *palette )
+{
+ int i;
+ XColor colors[256];
+
+ if (!X11_active)
+ return;
+
+ if ( !palette )
+ palette = ( const unsigned char * ) sw_state.currentpalette;
+
+ for(i=0;i<256;i++)
+ st2d_8to16table[i]= xlib_rgb(palette[i*4],
+ palette[i*4+1],palette[i*4+2]);
+
+ if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8)
+ {
+ for (i=0 ; i<256 ; i++)
+ {
+ colors[i].pixel = i;
+ colors[i].flags = DoRed|DoGreen|DoBlue;
+ colors[i].red = palette[i*4] * 257;
+ colors[i].green = palette[i*4+1] * 257;
+ colors[i].blue = palette[i*4+2] * 257;
+ }
+ XStoreColors(x_disp, x_cmap, colors, 256);
+ }
+}
+
+/*
+** SWimp_Shutdown
+**
+** System specific graphics subsystem shutdown routine. Destroys
+** DIBs or DDRAW surfaces as appropriate.
+*/
+void SWimp_Shutdown( void )
+{
+ int i;
+
+ if (!X11_active)
+ return;
+
+ if (doShm) {
+ for (i = 0; i < 2; i++)
+ if (x_framebuffer[i]) {
+ XShmDetach(x_disp, &x_shminfo[i]);
+ free(x_framebuffer[i]);
+ shmdt(x_shminfo[i].shmaddr);
+ x_framebuffer[i] = NULL;
+ }
+ } else if (x_framebuffer[0]) {
+ free(x_framebuffer[0]->data);
+ free(x_framebuffer[0]);
+ x_framebuffer[0] = NULL;
+ }
+
+ XDestroyWindow( x_disp, x_win );
+
+ XAutoRepeatOn(x_disp);
+// XCloseDisplay(x_disp);
+
+ X11_active = false;
+}
+
+/*
+** SWimp_AppActivate
+*/
+void SWimp_AppActivate( qboolean active )
+{
+}
+
+//===============================================================================
+
+/*
+================
+Sys_MakeCodeWriteable
+================
+*/
+void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
+{
+
+ int r;
+ unsigned long addr;
+ int psize = getpagesize();
+
+ addr = (startaddr & ~(psize-1)) - psize;
+
+// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
+// addr, startaddr+length, length);
+
+ r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
+
+ if (r < 0)
+ Sys_Error("Protection change failed\n");
+
+}
+
+/*****************************************************************************/
+/* KEYBOARD */
+/*****************************************************************************/
+
+Key_Event_fp_t Key_Event_fp;
+
+void KBD_Init(Key_Event_fp_t fp)
+{
+ Key_Event_fp = fp;
+}
+
+void KBD_Update(void)
+{
+// get events from x server
+ if (x_disp)
+ {
+ while (XPending(x_disp))
+ GetEvent();
+ while (keyq_head != keyq_tail)
+ {
+ Key_Event_fp(keyq[keyq_tail].key, keyq[keyq_tail].down);
+ keyq_tail = (keyq_tail + 1) & 63;
+ }
+ }
+}
+
+void KBD_Close(void)
+{
+}
+
+
--- a/plan9/rw_x11.c
+++ /dev/null
@@ -1,1093 +1,0 @@
-/*
-** RW_X11.C
-**
-** This file contains ALL Linux specific stuff having to do with the
-** software refresh. When a port is being made the following functions
-** must be implemented by the port:
-**
-** SWimp_EndFrame
-** SWimp_Init
-** SWimp_InitGraphics
-** SWimp_SetPalette
-** SWimp_Shutdown
-** SWimp_SwitchFullscreen
-*/
-
-#include <ctype.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-#include <X11/extensions/XShm.h>
-
-#include "../ref_soft/r_local.h"
-#include "../client/keys.h"
-#include "../linux/rw_linux.h"
-
-/*****************************************************************************/
-
-static qboolean doShm;
-static Display *x_disp;
-static Colormap x_cmap;
-static Window x_win;
-static GC x_gc;
-static Visual *x_vis;
-static XVisualInfo *x_visinfo;
-//static XImage *x_image;
-
-#define STD_EVENT_MASK (StructureNotifyMask | KeyPressMask \
- | KeyReleaseMask | ExposureMask | PointerMotionMask | \
- ButtonPressMask | ButtonReleaseMask)
-
-static int x_shmeventtype;
-//static XShmSegmentInfo x_shminfo;
-
-static qboolean oktodraw = false;
-static qboolean X11_active = false;
-
-int XShmQueryExtension(Display *);
-int XShmGetEventBase(Display *);
-
-int current_framebuffer;
-static XImage *x_framebuffer[2] = { 0, 0 };
-static XShmSegmentInfo x_shminfo[2];
-
-struct
-{
- int key;
- int down;
-} keyq[64];
-int keyq_head=0;
-int keyq_tail=0;
-
-int config_notify=0;
-int config_notify_width;
-int config_notify_height;
-
-typedef unsigned short PIXEL;
-
-// Console variables that we need to access from this module
-
-/*****************************************************************************/
-/* MOUSE */
-/*****************************************************************************/
-
-// this is inside the renderer shared lib, so these are called from vid_so
-
-static qboolean mouse_avail;
-static int mouse_buttonstate;
-static int mouse_oldbuttonstate;
-static int mouse_x, mouse_y;
-static int old_mouse_x, old_mouse_y;
-static int mx, my;
-static float old_windowed_mouse;
-static int p_mouse_x, p_mouse_y;
-
-static cvar_t *_windowed_mouse;
-static cvar_t *m_filter;
-static cvar_t *in_mouse;
-
-static qboolean mlooking;
-
-// state struct passed in Init
-static in_state_t *in_state;
-
-static cvar_t *sensitivity;
-static cvar_t *lookstrafe;
-static cvar_t *m_side;
-static cvar_t *m_yaw;
-static cvar_t *m_pitch;
-static cvar_t *m_forward;
-static cvar_t *freelook;
-
-static void Force_CenterView_f (void)
-{
- in_state->viewangles[PITCH] = 0;
-}
-
-static void RW_IN_MLookDown (void)
-{
- mlooking = true;
-}
-
-static void RW_IN_MLookUp (void)
-{
- mlooking = false;
- in_state->IN_CenterView_fp ();
-}
-
-void RW_IN_Init(in_state_t *in_state_p)
-{
- int mtype;
- int i;
-
- in_state = in_state_p;
-
- // mouse variables
- _windowed_mouse = ri.Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE);
- m_filter = ri.Cvar_Get ("m_filter", "0", 0);
- in_mouse = ri.Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE);
- freelook = ri.Cvar_Get( "freelook", "0", 0 );
- lookstrafe = ri.Cvar_Get ("lookstrafe", "0", 0);
- sensitivity = ri.Cvar_Get ("sensitivity", "3", 0);
- m_pitch = ri.Cvar_Get ("m_pitch", "0.022", 0);
- m_yaw = ri.Cvar_Get ("m_yaw", "0.022", 0);
- m_forward = ri.Cvar_Get ("m_forward", "1", 0);
- m_side = ri.Cvar_Get ("m_side", "0.8", 0);
-
- ri.Cmd_AddCommand ("+mlook", RW_IN_MLookDown);
- ri.Cmd_AddCommand ("-mlook", RW_IN_MLookUp);
-
- ri.Cmd_AddCommand ("force_centerview", Force_CenterView_f);
-
- mouse_x = mouse_y = 0.0;
- mouse_avail = true;
-}
-
-void RW_IN_Shutdown(void)
-{
- mouse_avail = false;
-}
-
-/*
-===========
-IN_Commands
-===========
-*/
-void RW_IN_Commands (void)
-{
- int i;
-
- if (!mouse_avail)
- return;
-
- for (i=0 ; i<3 ; i++) {
- if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
- in_state->Key_Event_fp (K_MOUSE1 + i, true);
-
- if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
- in_state->Key_Event_fp (K_MOUSE1 + i, false);
- }
- mouse_oldbuttonstate = mouse_buttonstate;
-}
-
-/*
-===========
-IN_Move
-===========
-*/
-void RW_IN_Move (usercmd_t *cmd)
-{
- if (!mouse_avail)
- return;
-
- if (m_filter->value)
- {
- mouse_x = (mx + old_mouse_x) * 0.5;
- mouse_y = (my + old_mouse_y) * 0.5;
- } else {
- mouse_x = mx;
- mouse_y = my;
- }
-
- old_mouse_x = mx;
- old_mouse_y = my;
-
- if (!mouse_x && !mouse_y)
- return;
-
- mouse_x *= sensitivity->value;
- mouse_y *= sensitivity->value;
-
-// add mouse X/Y movement to cmd
- if ( (*in_state->in_strafe_state & 1) ||
- (lookstrafe->value && mlooking ))
- cmd->sidemove += m_side->value * mouse_x;
- else
- in_state->viewangles[YAW] -= m_yaw->value * mouse_x;
-
- if ( (mlooking || freelook->value) &&
- !(*in_state->in_strafe_state & 1))
- {
- in_state->viewangles[PITCH] += m_pitch->value * mouse_y;
- }
- else
- {
- cmd->forwardmove -= m_forward->value * mouse_y;
- }
- mx = my = 0;
-}
-
-void RW_IN_Frame (void)
-{
-}
-
-void RW_IN_Activate(void)
-{
-}
-
-/*****************************************************************************/
-
-static PIXEL st2d_8to16table[256];
-static int shiftmask_fl=0;
-static long r_shift,g_shift,b_shift;
-static unsigned long r_mask,g_mask,b_mask;
-
-void shiftmask_init()
-{
- unsigned int x;
- r_mask=x_vis->red_mask;
- g_mask=x_vis->green_mask;
- b_mask=x_vis->blue_mask;
- for(r_shift=-8,x=1;x<r_mask;x=x<<1)r_shift++;
- for(g_shift=-8,x=1;x<g_mask;x=x<<1)g_shift++;
- for(b_shift=-8,x=1;x<b_mask;x=x<<1)b_shift++;
- shiftmask_fl=1;
-}
-
-PIXEL xlib_rgb(int r,int g,int b)
-{
- PIXEL p;
- if(shiftmask_fl==0) shiftmask_init();
- p=0;
-
- if(r_shift>0) {
- p=(r<<(r_shift))&r_mask;
- } else if(r_shift<0) {
- p=(r>>(-r_shift))&r_mask;
- } else p|=(r&r_mask);
-
- if(g_shift>0) {
- p|=(g<<(g_shift))&g_mask;
- } else if(g_shift<0) {
- p|=(g>>(-g_shift))&g_mask;
- } else p|=(g&g_mask);
-
- if(b_shift>0) {
- p|=(b<<(b_shift))&b_mask;
- } else if(b_shift<0) {
- p|=(b>>(-b_shift))&b_mask;
- } else p|=(b&b_mask);
-
- return p;
-}
-
-void st2_fixup( XImage *framebuf, int x, int y, int width, int height)
-{
- int xi,yi;
- unsigned char *src;
- PIXEL *dest;
-
- if( (x<0)||(y<0) )return;
-
- for (yi = y; yi < (y+height); yi++) {
- src = &framebuf->data [yi * framebuf->bytes_per_line];
- dest = (PIXEL*)src;
- for(xi = (x+width-1); xi >= x; xi -= 8) {
- dest[xi ] = st2d_8to16table[src[xi ]];
- dest[xi-1] = st2d_8to16table[src[xi-1]];
- dest[xi-2] = st2d_8to16table[src[xi-2]];
- dest[xi-3] = st2d_8to16table[src[xi-3]];
- dest[xi-4] = st2d_8to16table[src[xi-4]];
- dest[xi-5] = st2d_8to16table[src[xi-5]];
- dest[xi-6] = st2d_8to16table[src[xi-6]];
- dest[xi-7] = st2d_8to16table[src[xi-7]];
- }
- }
-}
-
-// ========================================================================
-// makes a null cursor
-// ========================================================================
-
-static Cursor CreateNullCursor(Display *display, Window root)
-{
- Pixmap cursormask;
- XGCValues xgc;
- GC gc;
- XColor dummycolour;
- Cursor cursor;
-
- cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
- xgc.function = GXclear;
- gc = XCreateGC(display, cursormask, GCFunction, &xgc);
- XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
- dummycolour.pixel = 0;
- dummycolour.red = 0;
- dummycolour.flags = 04;
- cursor = XCreatePixmapCursor(display, cursormask, cursormask,
- &dummycolour,&dummycolour, 0,0);
- XFreePixmap(display,cursormask);
- XFreeGC(display,gc);
- return cursor;
-}
-
-void ResetFrameBuffer(void)
-{
- int mem;
- int pwidth;
-
- if (x_framebuffer[0])
- {
- free(x_framebuffer[0]->data);
- free(x_framebuffer[0]);
- }
-
-// alloc an extra line in case we want to wrap, and allocate the z-buffer
- pwidth = x_visinfo->depth / 8;
- if (pwidth == 3) pwidth = 4;
- mem = ((vid.width*pwidth+7)&~7) * vid.height;
-
- x_framebuffer[0] = XCreateImage( x_disp,
- x_vis,
- x_visinfo->depth,
- ZPixmap,
- 0,
- malloc(mem),
- vid.width, vid.height,
- 32,
- 0);
-
- if (!x_framebuffer[0])
- Sys_Error("VID: XCreateImage failed\n");
-
- vid.buffer = (byte*) (x_framebuffer[0]);
-}
-
-void ResetSharedFrameBuffers(void)
-{
- int size;
- int key;
- int minsize = getpagesize();
- int frm;
-
- for (frm=0 ; frm<2 ; frm++)
- {
- // free up old frame buffer memory
- if (x_framebuffer[frm])
- {
- XShmDetach(x_disp, &x_shminfo[frm]);
- free(x_framebuffer[frm]);
- shmdt(x_shminfo[frm].shmaddr);
- }
-
- // create the image
- x_framebuffer[frm] = XShmCreateImage( x_disp,
- x_vis,
- x_visinfo->depth,
- ZPixmap,
- 0,
- &x_shminfo[frm],
- vid.width,
- vid.height );
-
- // grab shared memory
-
- size = x_framebuffer[frm]->bytes_per_line
- * x_framebuffer[frm]->height;
- if (size < minsize)
- Sys_Error("VID: Window must use at least %d bytes\n", minsize);
-
- key = random();
- x_shminfo[frm].shmid = shmget((key_t)key, size, IPC_CREAT|0777);
- if (x_shminfo[frm].shmid==-1)
- Sys_Error("VID: Could not get any shared memory\n");
-
- // attach to the shared memory segment
- x_shminfo[frm].shmaddr =
- (void *) shmat(x_shminfo[frm].shmid, 0, 0);
-
- ri.Con_Printf(PRINT_ALL,
- "MITSHM shared memory (id=%d, addr=0x%lx)\n",
- x_shminfo[frm].shmid,
- (long) x_shminfo[frm].shmaddr);
-
- x_framebuffer[frm]->data = x_shminfo[frm].shmaddr;
-
- // get the X server to attach to it
-
- if (!XShmAttach(x_disp, &x_shminfo[frm]))
- Sys_Error("VID: XShmAttach() failed\n");
- XSync(x_disp, 0);
- shmctl(x_shminfo[frm].shmid, IPC_RMID, 0);
- }
-
-}
-
-// ========================================================================
-// Tragic death handler
-// ========================================================================
-
-void TragicDeath(int signal_num)
-{
- XAutoRepeatOn(x_disp);
- XCloseDisplay(x_disp);
- Sys_Error("This death brought to you by the number %d\n", signal_num);
-}
-
-int XLateKey(XKeyEvent *ev)
-{
-
- int key;
- char buf[64];
- KeySym keysym;
-
- key = 0;
-
- XLookupString(ev, buf, sizeof buf, &keysym, 0);
-
- switch(keysym)
- {
- case XK_KP_Page_Up: key = K_KP_PGUP; break;
- case XK_Page_Up: key = K_PGUP; break;
-
- case XK_KP_Page_Down: key = K_KP_PGDN; break;
- case XK_Page_Down: key = K_PGDN; break;
-
- case XK_KP_Home: key = K_KP_HOME; break;
- case XK_Home: key = K_HOME; break;
-
- case XK_KP_End: key = K_KP_END; break;
- case XK_End: key = K_END; break;
-
- case XK_KP_Left: key = K_KP_LEFTARROW; break;
- case XK_Left: key = K_LEFTARROW; break;
-
- case XK_KP_Right: key = K_KP_RIGHTARROW; break;
- case XK_Right: key = K_RIGHTARROW; break;
-
- case XK_KP_Down: key = K_KP_DOWNARROW; break;
- case XK_Down: key = K_DOWNARROW; break;
-
- case XK_KP_Up: key = K_KP_UPARROW; break;
- case XK_Up: key = K_UPARROW; break;
-
- case XK_Escape: key = K_ESCAPE; break;
-
- case XK_KP_Enter: key = K_KP_ENTER; break;
- case XK_Return: key = K_ENTER; break;
-
- case XK_Tab: key = K_TAB; break;
-
- case XK_F1: key = K_F1; break;
-
- case XK_F2: key = K_F2; break;
-
- case XK_F3: key = K_F3; break;
-
- case XK_F4: key = K_F4; break;
-
- case XK_F5: key = K_F5; break;
-
- case XK_F6: key = K_F6; break;
-
- case XK_F7: key = K_F7; break;
-
- case XK_F8: key = K_F8; break;
-
- case XK_F9: key = K_F9; break;
-
- case XK_F10: key = K_F10; break;
-
- case XK_F11: key = K_F11; break;
-
- case XK_F12: key = K_F12; break;
-
- case XK_BackSpace: key = K_BACKSPACE; break;
-
- case XK_KP_Delete: key = K_KP_DEL; break;
- case XK_Delete: key = K_DEL; break;
-
- case XK_Pause: key = K_PAUSE; break;
-
- case XK_Shift_L:
- case XK_Shift_R: key = K_SHIFT; break;
-
- case XK_Execute:
- case XK_Control_L:
- case XK_Control_R: key = K_CTRL; break;
-
- case XK_Alt_L:
- case XK_Meta_L:
- case XK_Alt_R:
- case XK_Meta_R: key = K_ALT; break;
-
- case XK_KP_Begin: key = K_KP_5; break;
-
- case XK_Insert:key = K_INS; break;
- case XK_KP_Insert: key = K_KP_INS; break;
-
- case XK_KP_Multiply: key = '*'; break;
- case XK_KP_Add: key = K_KP_PLUS; break;
- case XK_KP_Subtract: key = K_KP_MINUS; break;
- case XK_KP_Divide: key = K_KP_SLASH; break;
-
-#if 0
- case 0x021: key = '1';break;/* [!] */
- case 0x040: key = '2';break;/* [@] */
- case 0x023: key = '3';break;/* [#] */
- case 0x024: key = '4';break;/* [$] */
- case 0x025: key = '5';break;/* [%] */
- case 0x05e: key = '6';break;/* [^] */
- case 0x026: key = '7';break;/* [&] */
- case 0x02a: key = '8';break;/* [*] */
- case 0x028: key = '9';;break;/* [(] */
- case 0x029: key = '0';break;/* [)] */
- case 0x05f: key = '-';break;/* [_] */
- case 0x02b: key = '=';break;/* [+] */
- case 0x07c: key = '\'';break;/* [|] */
- case 0x07d: key = '[';break;/* [}] */
- case 0x07b: key = ']';break;/* [{] */
- case 0x022: key = '\'';break;/* ["] */
- case 0x03a: key = ';';break;/* [:] */
- case 0x03f: key = '/';break;/* [?] */
- case 0x03e: key = '.';break;/* [>] */
- case 0x03c: key = ',';break;/* [<] */
-#endif
-
- default:
- key = *(unsigned char*)buf;
- if (key >= 'A' && key <= 'Z')
- key = key - 'A' + 'a';
- break;
- }
-
- return key;
-}
-
-void GetEvent(void)
-{
- XEvent x_event;
- int b;
-
- XNextEvent(x_disp, &x_event);
- switch(x_event.type) {
- case KeyPress:
- keyq[keyq_head].key = XLateKey(&x_event.xkey);
- keyq[keyq_head].down = true;
- keyq_head = (keyq_head + 1) & 63;
- break;
- case KeyRelease:
- keyq[keyq_head].key = XLateKey(&x_event.xkey);
- keyq[keyq_head].down = false;
- keyq_head = (keyq_head + 1) & 63;
- break;
-
- case MotionNotify:
- if (_windowed_mouse->value) {
- mx += ((int)x_event.xmotion.x - (int)(vid.width/2));
- my += ((int)x_event.xmotion.y - (int)(vid.height/2));
-
- /* move the mouse to the window center again */
- XSelectInput(x_disp,x_win, STD_EVENT_MASK & ~PointerMotionMask);
- XWarpPointer(x_disp,None,x_win,0,0,0,0,
- (vid.width/2),(vid.height/2));
- XSelectInput(x_disp,x_win, STD_EVENT_MASK);
- } else {
- mx = ((int)x_event.xmotion.x - (int)p_mouse_x);
- my = ((int)x_event.xmotion.y - (int)p_mouse_y);
- p_mouse_x=x_event.xmotion.x;
- p_mouse_y=x_event.xmotion.y;
- }
- break;
-
- case ButtonPress:
- b=-1;
- if (x_event.xbutton.button == 1)
- b = 0;
- else if (x_event.xbutton.button == 2)
- b = 2;
- else if (x_event.xbutton.button == 3)
- b = 1;
- if (b>=0)
- mouse_buttonstate |= 1<<b;
- break;
-
- case ButtonRelease:
- b=-1;
- if (x_event.xbutton.button == 1)
- b = 0;
- else if (x_event.xbutton.button == 2)
- b = 2;
- else if (x_event.xbutton.button == 3)
- b = 1;
- if (b>=0)
- mouse_buttonstate &= ~(1<<b);
- break;
-
- case ConfigureNotify:
- config_notify_width = x_event.xconfigure.width;
- config_notify_height = x_event.xconfigure.height;
- config_notify = 1;
- break;
-
- default:
- if (doShm && x_event.type == x_shmeventtype)
- oktodraw = true;
- }
-
- if (old_windowed_mouse != _windowed_mouse->value) {
- old_windowed_mouse = _windowed_mouse->value;
-
- if (!_windowed_mouse->value) {
- /* ungrab the pointer */
- XUngrabPointer(x_disp,CurrentTime);
- } else {
- /* grab the pointer */
- XGrabPointer(x_disp,x_win,True,0,GrabModeAsync,
- GrabModeAsync,x_win,None,CurrentTime);
- }
- }
-}
-
-/*****************************************************************************/
-
-/*
-** SWimp_Init
-**
-** This routine is responsible for initializing the implementation
-** specific stuff in a software rendering subsystem.
-*/
-int SWimp_Init( void *hInstance, void *wndProc )
-{
-// open the display
- x_disp = XOpenDisplay(0);
- if (!x_disp)
- {
- if (getenv("DISPLAY"))
- Sys_Error("VID: Could not open display [%s]\n",
- getenv("DISPLAY"));
- else
- Sys_Error("VID: Could not open local display\n");
- }
-
-// catch signals so i can turn on auto-repeat
-
- {
- struct sigaction sa;
- sigaction(SIGINT, 0, &sa);
- sa.sa_handler = TragicDeath;
- sigaction(SIGINT, &sa, 0);
- sigaction(SIGTERM, &sa, 0);
- }
-
- return true;
-}
-
-/*
-** SWimp_InitGraphics
-**
-** This initializes the software refresh's implementation specific
-** graphics subsystem. In the case of Windows it creates DIB or
-** DDRAW surfaces.
-**
-** The necessary width and height parameters are grabbed from
-** vid.width and vid.height.
-*/
-static qboolean SWimp_InitGraphics( qboolean fullscreen )
-{
- int pnum, i;
- XVisualInfo template;
- int num_visuals;
- int template_mask;
-
- srandom(getpid());
-
- // free resources in use
- SWimp_Shutdown ();
-
- // let the sound and input subsystems know about the new window
- ri.Vid_NewWindow (vid.width, vid.height);
-
- XAutoRepeatOff(x_disp);
-
-// for debugging only
- XSynchronize(x_disp, True);
-
-// check for command-line window size
- template_mask = 0;
-
-#if 0
-// specify a visual id
- if ((pnum=COM_CheckParm("-visualid")))
- {
- if (pnum >= com_argc-1)
- Sys_Error("VID: -visualid <id#>\n");
- template.visualid = Q_atoi(com_argv[pnum+1]);
- template_mask = VisualIDMask;
- }
-
-// If not specified, use default visual
- else
-#endif
- {
- int screen;
- screen = XDefaultScreen(x_disp);
- template.visualid =
- XVisualIDFromVisual(XDefaultVisual(x_disp, screen));
- template_mask = VisualIDMask;
- }
-
-// pick a visual- warn if more than one was available
- x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &num_visuals);
- if (num_visuals > 1)
- {
- printf("Found more than one visual id at depth %d:\n", template.depth);
- for (i=0 ; i<num_visuals ; i++)
- printf(" -visualid %d\n", (int)(x_visinfo[i].visualid));
- }
- else if (num_visuals == 0)
- {
- if (template_mask == VisualIDMask)
- Sys_Error("VID: Bad visual id %d\n", template.visualid);
- else
- Sys_Error("VID: No visuals at depth %d\n", template.depth);
- }
-
-#if 0
- if (verbose)
- {
- printf("Using visualid %d:\n", (int)(x_visinfo->visualid));
- printf(" screen %d\n", x_visinfo->screen);
- printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask));
- printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask));
- printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask));
- printf(" colormap_size %d\n", x_visinfo->colormap_size);
- printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb);
- }
-#endif
-
- x_vis = x_visinfo->visual;
-
-// setup attributes for main window
- {
- int attribmask = CWEventMask | CWColormap | CWBorderPixel;
- XSetWindowAttributes attribs;
- Colormap tmpcmap;
-
- tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp,
- x_visinfo->screen), x_vis, AllocNone);
-
- attribs.event_mask = STD_EVENT_MASK;
- attribs.border_pixel = 0;
- attribs.colormap = tmpcmap;
-
-// create the main window
- x_win = XCreateWindow( x_disp,
- XRootWindow(x_disp, x_visinfo->screen),
- 0, 0, // x, y
- vid.width, vid.height,
- 0, // borderwidth
- x_visinfo->depth,
- InputOutput,
- x_vis,
- attribmask,
- &attribs );
- XStoreName(x_disp, x_win, "Quake II");
-
- if (x_visinfo->class != TrueColor)
- XFreeColormap(x_disp, tmpcmap);
- }
-
- if (x_visinfo->depth == 8)
- {
- // create and upload the palette
- if (x_visinfo->class == PseudoColor)
- {
- x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll);
- XSetWindowColormap(x_disp, x_win, x_cmap);
- }
-
- }
-
-// inviso cursor
- XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win));
-
-// create the GC
- {
- XGCValues xgcvalues;
- int valuemask = GCGraphicsExposures;
- xgcvalues.graphics_exposures = False;
- x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues );
- }
-
-// map the window
- XMapWindow(x_disp, x_win);
-
-// wait for first exposure event
- {
- XEvent event;
- do
- {
- XNextEvent(x_disp, &event);
- if (event.type == Expose && !event.xexpose.count)
- oktodraw = true;
- } while (!oktodraw);
- }
-// now safe to draw
-
-// even if MITSHM is available, make sure it's a local connection
- if (XShmQueryExtension(x_disp))
- {
- char *displayname;
- doShm = true;
- displayname = (char *) getenv("DISPLAY");
- if (displayname)
- {
- char *d = displayname;
- while (*d && (*d != ':')) d++;
- if (*d) *d = 0;
- if (!(!strcasecmp(displayname, "unix") || !*displayname))
- doShm = false;
- }
- }
-
- if (doShm)
- {
- x_shmeventtype = XShmGetEventBase(x_disp) + ShmCompletion;
- ResetSharedFrameBuffers();
- }
- else
- ResetFrameBuffer();
-
- current_framebuffer = 0;
- vid.rowbytes = x_framebuffer[0]->bytes_per_line;
- vid.buffer = x_framebuffer[0]->data;
-
-// XSynchronize(x_disp, False);
-
- X11_active = true;
-
- return true;
-}
-
-/*
-** SWimp_EndFrame
-**
-** This does an implementation specific copy from the backbuffer to the
-** front buffer. In the Win32 case it uses BitBlt or BltFast depending
-** on whether we're using DIB sections/GDI or DDRAW.
-*/
-void SWimp_EndFrame (void)
-{
-// if the window changes dimension, skip this frame
-#if 0
- if (config_notify)
- {
- fprintf(stderr, "config notify\n");
- config_notify = 0;
- vid.width = config_notify_width & ~7;
- vid.height = config_notify_height;
- if (doShm)
- ResetSharedFrameBuffers();
- else
- ResetFrameBuffer();
- vid.rowbytes = x_framebuffer[0]->bytes_per_line;
- vid.buffer = x_framebuffer[current_framebuffer]->data;
- vid.recalc_refdef = 1; // force a surface cache flush
- Con_CheckResize();
- Con_Clear_f();
- return;
- }
-#endif
-
- if (doShm)
- {
-
- if (x_visinfo->depth != 8)
- st2_fixup( x_framebuffer[current_framebuffer],
- 0, 0, vid.width, vid.height);
- if (!XShmPutImage(x_disp, x_win, x_gc,
- x_framebuffer[current_framebuffer], 0, 0,
- 0, 0, vid.width, vid.height, True))
- Sys_Error("VID_Update: XShmPutImage failed\n");
- oktodraw = false;
- while (!oktodraw)
- GetEvent();
- current_framebuffer = !current_framebuffer;
- vid.buffer = x_framebuffer[current_framebuffer]->data;
- XSync(x_disp, False);
- }
- else
- {
- if (x_visinfo->depth != 8)
- st2_fixup( x_framebuffer[current_framebuffer],
- 0, 0, vid.width, vid.height);
- XPutImage(x_disp, x_win, x_gc, x_framebuffer[0],
- 0, 0, 0, 0, vid.width, vid.height);
- XSync(x_disp, False);
- }
-}
-
-/*
-** SWimp_SetMode
-*/
-rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
-{
- rserr_t retval = rserr_ok;
-
- ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode );
-
- if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) )
- {
- ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
- return rserr_invalid_mode;
- }
-
- ri.Con_Printf( PRINT_ALL, " %d %d\n", *pwidth, *pheight);
-
- if ( !SWimp_InitGraphics( false ) ) {
- // failed to set a valid mode in windowed mode
- return rserr_invalid_mode;
- }
-
- R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
-
- return retval;
-}
-
-/*
-** SWimp_SetPalette
-**
-** System specific palette setting routine. A NULL palette means
-** to use the existing palette. The palette is expected to be in
-** a padded 4-byte xRGB format.
-*/
-void SWimp_SetPalette( const unsigned char *palette )
-{
- int i;
- XColor colors[256];
-
- if (!X11_active)
- return;
-
- if ( !palette )
- palette = ( const unsigned char * ) sw_state.currentpalette;
-
- for(i=0;i<256;i++)
- st2d_8to16table[i]= xlib_rgb(palette[i*4],
- palette[i*4+1],palette[i*4+2]);
-
- if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8)
- {
- for (i=0 ; i<256 ; i++)
- {
- colors[i].pixel = i;
- colors[i].flags = DoRed|DoGreen|DoBlue;
- colors[i].red = palette[i*4] * 257;
- colors[i].green = palette[i*4+1] * 257;
- colors[i].blue = palette[i*4+2] * 257;
- }
- XStoreColors(x_disp, x_cmap, colors, 256);
- }
-}
-
-/*
-** SWimp_Shutdown
-**
-** System specific graphics subsystem shutdown routine. Destroys
-** DIBs or DDRAW surfaces as appropriate.
-*/
-void SWimp_Shutdown( void )
-{
- int i;
-
- if (!X11_active)
- return;
-
- if (doShm) {
- for (i = 0; i < 2; i++)
- if (x_framebuffer[i]) {
- XShmDetach(x_disp, &x_shminfo[i]);
- free(x_framebuffer[i]);
- shmdt(x_shminfo[i].shmaddr);
- x_framebuffer[i] = NULL;
- }
- } else if (x_framebuffer[0]) {
- free(x_framebuffer[0]->data);
- free(x_framebuffer[0]);
- x_framebuffer[0] = NULL;
- }
-
- XDestroyWindow( x_disp, x_win );
-
- XAutoRepeatOn(x_disp);
-// XCloseDisplay(x_disp);
-
- X11_active = false;
-}
-
-/*
-** SWimp_AppActivate
-*/
-void SWimp_AppActivate( qboolean active )
-{
-}
-
-//===============================================================================
-
-/*
-================
-Sys_MakeCodeWriteable
-================
-*/
-void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
-{
-
- int r;
- unsigned long addr;
- int psize = getpagesize();
-
- addr = (startaddr & ~(psize-1)) - psize;
-
-// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
-// addr, startaddr+length, length);
-
- r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
-
- if (r < 0)
- Sys_Error("Protection change failed\n");
-
-}
-
-/*****************************************************************************/
-/* KEYBOARD */
-/*****************************************************************************/
-
-Key_Event_fp_t Key_Event_fp;
-
-void KBD_Init(Key_Event_fp_t fp)
-{
- Key_Event_fp = fp;
-}
-
-void KBD_Update(void)
-{
-// get events from x server
- if (x_disp)
- {
- while (XPending(x_disp))
- GetEvent();
- while (keyq_head != keyq_tail)
- {
- Key_Event_fp(keyq[keyq_tail].key, keyq[keyq_tail].down);
- keyq_tail = (keyq_tail + 1) & 63;
- }
- }
-}
-
-void KBD_Close(void)
-{
-}
-
-
--- /dev/null
+++ b/plan9/snd_9.c
@@ -1,0 +1,266 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <sys/wait.h>
+#include <linux/soundcard.h>
+#include <stdio.h>
+
+#include "../client/client.h"
+#include "../client/snd_loc.h"
+
+int audio_fd;
+int snd_inited;
+
+cvar_t *sndbits;
+cvar_t *sndspeed;
+cvar_t *sndchannels;
+cvar_t *snddevice;
+
+static int tryrates[] = { 11025, 22051, 44100, 8000 };
+
+qboolean SNDDMA_Init(void)
+{
+
+ int rc;
+ int fmt;
+ int tmp;
+ int i;
+ char *s;
+ struct audio_buf_info info;
+ int caps;
+ extern uid_t saved_euid;
+
+ if (snd_inited)
+ return;
+
+ if (!snddevice) {
+ sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE);
+ sndspeed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE);
+ sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE);
+ snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
+ }
+
+// open /dev/dsp, confirm capability to mmap, and get size of dma buffer
+
+ if (!audio_fd) {
+ seteuid(saved_euid);
+
+ audio_fd = open(snddevice->string, O_RDWR);
+
+ seteuid(getuid());
+
+ if (audio_fd < 0)
+ {
+ perror(snddevice->string);
+ Com_Printf("Could not open %s\n", snddevice->string);
+ return 0;
+ }
+ }
+
+ rc = ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
+ if (rc < 0)
+ {
+ perror(snddevice->string);
+ Com_Printf("Could not reset %s\n", snddevice->string);
+ close(audio_fd);
+ return 0;
+ }
+
+ if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1)
+ {
+ perror(snddevice->string);
+ Com_Printf("Sound driver too old\n");
+ close(audio_fd);
+ return 0;
+ }
+
+ if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP))
+ {
+ Com_Printf("Sorry but your soundcard can't do this\n");
+ close(audio_fd);
+ return 0;
+ }
+
+ if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
+ {
+ perror("GETOSPACE");
+ Com_Printf("Um, can't do GETOSPACE?\n");
+ close(audio_fd);
+ return 0;
+ }
+
+// set sample bits & speed
+
+ dma.samplebits = (int)sndbits->value;
+ if (dma.samplebits != 16 && dma.samplebits != 8)
+ {
+ ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
+ if (fmt & AFMT_S16_LE) dma.samplebits = 16;
+ else if (fmt & AFMT_U8) dma.samplebits = 8;
+ }
+
+ dma.speed = (int)sndspeed->value;
+ if (!dma.speed) {
+ for (i=0 ; i<sizeof(tryrates)/4 ; i++)
+ if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) break;
+ dma.speed = tryrates[i];
+ }
+
+ dma.channels = (int)sndchannels->value;
+ if (dma.channels < 1 || dma.channels > 2)
+ dma.channels = 2;
+
+ dma.samples = info.fragstotal * info.fragsize / (dma.samplebits/8);
+ dma.submission_chunk = 1;
+
+// memory map the dma buffer
+
+ if (!dma.buffer)
+ dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal
+ * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0);
+ if (!dma.buffer)
+ {
+ perror(snddevice->string);
+ Com_Printf("Could not mmap %s\n", snddevice->string);
+ close(audio_fd);
+ return 0;
+ }
+
+ tmp = 0;
+ if (dma.channels == 2)
+ tmp = 1;
+ rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
+ if (rc < 0)
+ {
+ perror(snddevice->string);
+ Com_Printf("Could not set %s to stereo=%d", snddevice->string, dma.channels);
+ close(audio_fd);
+ return 0;
+ }
+ if (tmp)
+ dma.channels = 2;
+ else
+ dma.channels = 1;
+
+ rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &dma.speed);
+ if (rc < 0)
+ {
+ perror(snddevice->string);
+ Com_Printf("Could not set %s speed to %d", snddevice->string, dma.speed);
+ close(audio_fd);
+ return 0;
+ }
+
+ if (dma.samplebits == 16)
+ {
+ rc = AFMT_S16_LE;
+ rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
+ if (rc < 0)
+ {
+ perror(snddevice->string);
+ Com_Printf("Could not support 16-bit data. Try 8-bit.\n");
+ close(audio_fd);
+ return 0;
+ }
+ }
+ else if (dma.samplebits == 8)
+ {
+ rc = AFMT_U8;
+ rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
+ if (rc < 0)
+ {
+ perror(snddevice->string);
+ Com_Printf("Could not support 8-bit data.\n");
+ close(audio_fd);
+ return 0;
+ }
+ }
+ else
+ {
+ perror(snddevice->string);
+ Com_Printf("%d-bit sound not supported.", dma.samplebits);
+ close(audio_fd);
+ return 0;
+ }
+
+// toggle the trigger & start her up
+
+ tmp = 0;
+ rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
+ if (rc < 0)
+ {
+ perror(snddevice->string);
+ Com_Printf("Could not toggle.\n");
+ close(audio_fd);
+ return 0;
+ }
+ tmp = PCM_ENABLE_OUTPUT;
+ rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
+ if (rc < 0)
+ {
+ perror(snddevice->string);
+ Com_Printf("Could not toggle.\n");
+ close(audio_fd);
+ return 0;
+ }
+
+ dma.samplepos = 0;
+
+ snd_inited = 1;
+ return 1;
+
+}
+
+int SNDDMA_GetDMAPos(void)
+{
+
+ struct count_info count;
+
+ if (!snd_inited) return 0;
+
+ if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1)
+ {
+ perror(snddevice->string);
+ Com_Printf("Uh, sound dead.\n");
+ close(audio_fd);
+ snd_inited = 0;
+ return 0;
+ }
+// dma.samplepos = (count.bytes / (dma.samplebits / 8)) & (dma.samples-1);
+// fprintf(stderr, "%d \r", count.ptr);
+ dma.samplepos = count.ptr / (dma.samplebits / 8);
+
+ return dma.samplepos;
+
+}
+
+void SNDDMA_Shutdown(void)
+{
+#if 0
+ if (snd_inited)
+ {
+ close(audio_fd);
+ snd_inited = 0;
+ }
+#endif
+}
+
+/*
+==============
+SNDDMA_Submit
+
+Send sound to device if buffer isn't really the dma buffer
+===============
+*/
+void SNDDMA_Submit(void)
+{
+}
+
+void SNDDMA_BeginPainting (void)
+{
+}
+
--- a/plan9/snd_linux.c
+++ /dev/null
@@ -1,266 +1,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/shm.h>
-#include <sys/wait.h>
-#include <linux/soundcard.h>
-#include <stdio.h>
-
-#include "../client/client.h"
-#include "../client/snd_loc.h"
-
-int audio_fd;
-int snd_inited;
-
-cvar_t *sndbits;
-cvar_t *sndspeed;
-cvar_t *sndchannels;
-cvar_t *snddevice;
-
-static int tryrates[] = { 11025, 22051, 44100, 8000 };
-
-qboolean SNDDMA_Init(void)
-{
-
- int rc;
- int fmt;
- int tmp;
- int i;
- char *s;
- struct audio_buf_info info;
- int caps;
- extern uid_t saved_euid;
-
- if (snd_inited)
- return;
-
- if (!snddevice) {
- sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE);
- sndspeed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE);
- sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE);
- snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
- }
-
-// open /dev/dsp, confirm capability to mmap, and get size of dma buffer
-
- if (!audio_fd) {
- seteuid(saved_euid);
-
- audio_fd = open(snddevice->string, O_RDWR);
-
- seteuid(getuid());
-
- if (audio_fd < 0)
- {
- perror(snddevice->string);
- Com_Printf("Could not open %s\n", snddevice->string);
- return 0;
- }
- }
-
- rc = ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
- if (rc < 0)
- {
- perror(snddevice->string);
- Com_Printf("Could not reset %s\n", snddevice->string);
- close(audio_fd);
- return 0;
- }
-
- if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1)
- {
- perror(snddevice->string);
- Com_Printf("Sound driver too old\n");
- close(audio_fd);
- return 0;
- }
-
- if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP))
- {
- Com_Printf("Sorry but your soundcard can't do this\n");
- close(audio_fd);
- return 0;
- }
-
- if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
- {
- perror("GETOSPACE");
- Com_Printf("Um, can't do GETOSPACE?\n");
- close(audio_fd);
- return 0;
- }
-
-// set sample bits & speed
-
- dma.samplebits = (int)sndbits->value;
- if (dma.samplebits != 16 && dma.samplebits != 8)
- {
- ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
- if (fmt & AFMT_S16_LE) dma.samplebits = 16;
- else if (fmt & AFMT_U8) dma.samplebits = 8;
- }
-
- dma.speed = (int)sndspeed->value;
- if (!dma.speed) {
- for (i=0 ; i<sizeof(tryrates)/4 ; i++)
- if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) break;
- dma.speed = tryrates[i];
- }
-
- dma.channels = (int)sndchannels->value;
- if (dma.channels < 1 || dma.channels > 2)
- dma.channels = 2;
-
- dma.samples = info.fragstotal * info.fragsize / (dma.samplebits/8);
- dma.submission_chunk = 1;
-
-// memory map the dma buffer
-
- if (!dma.buffer)
- dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal
- * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0);
- if (!dma.buffer)
- {
- perror(snddevice->string);
- Com_Printf("Could not mmap %s\n", snddevice->string);
- close(audio_fd);
- return 0;
- }
-
- tmp = 0;
- if (dma.channels == 2)
- tmp = 1;
- rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
- if (rc < 0)
- {
- perror(snddevice->string);
- Com_Printf("Could not set %s to stereo=%d", snddevice->string, dma.channels);
- close(audio_fd);
- return 0;
- }
- if (tmp)
- dma.channels = 2;
- else
- dma.channels = 1;
-
- rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &dma.speed);
- if (rc < 0)
- {
- perror(snddevice->string);
- Com_Printf("Could not set %s speed to %d", snddevice->string, dma.speed);
- close(audio_fd);
- return 0;
- }
-
- if (dma.samplebits == 16)
- {
- rc = AFMT_S16_LE;
- rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
- if (rc < 0)
- {
- perror(snddevice->string);
- Com_Printf("Could not support 16-bit data. Try 8-bit.\n");
- close(audio_fd);
- return 0;
- }
- }
- else if (dma.samplebits == 8)
- {
- rc = AFMT_U8;
- rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
- if (rc < 0)
- {
- perror(snddevice->string);
- Com_Printf("Could not support 8-bit data.\n");
- close(audio_fd);
- return 0;
- }
- }
- else
- {
- perror(snddevice->string);
- Com_Printf("%d-bit sound not supported.", dma.samplebits);
- close(audio_fd);
- return 0;
- }
-
-// toggle the trigger & start her up
-
- tmp = 0;
- rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
- if (rc < 0)
- {
- perror(snddevice->string);
- Com_Printf("Could not toggle.\n");
- close(audio_fd);
- return 0;
- }
- tmp = PCM_ENABLE_OUTPUT;
- rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
- if (rc < 0)
- {
- perror(snddevice->string);
- Com_Printf("Could not toggle.\n");
- close(audio_fd);
- return 0;
- }
-
- dma.samplepos = 0;
-
- snd_inited = 1;
- return 1;
-
-}
-
-int SNDDMA_GetDMAPos(void)
-{
-
- struct count_info count;
-
- if (!snd_inited) return 0;
-
- if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1)
- {
- perror(snddevice->string);
- Com_Printf("Uh, sound dead.\n");
- close(audio_fd);
- snd_inited = 0;
- return 0;
- }
-// dma.samplepos = (count.bytes / (dma.samplebits / 8)) & (dma.samples-1);
-// fprintf(stderr, "%d \r", count.ptr);
- dma.samplepos = count.ptr / (dma.samplebits / 8);
-
- return dma.samplepos;
-
-}
-
-void SNDDMA_Shutdown(void)
-{
-#if 0
- if (snd_inited)
- {
- close(audio_fd);
- snd_inited = 0;
- }
-#endif
-}
-
-/*
-==============
-SNDDMA_Submit
-
-Send sound to device if buffer isn't really the dma buffer
-===============
-*/
-void SNDDMA_Submit(void)
-{
-}
-
-void SNDDMA_BeginPainting (void)
-{
-}
-
--- /dev/null
+++ b/plan9/sys_9.c
@@ -1,0 +1,381 @@
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <mntent.h>
+
+#include <dlfcn.h>
+
+#include "../qcommon/qcommon.h"
+
+#include "../linux/rw_linux.h"
+
+cvar_t *nostdout;
+
+unsigned sys_frame_time;
+
+uid_t saved_euid;
+qboolean stdin_active = true;
+
+// =======================================================================
+// General routines
+// =======================================================================
+
+void Sys_ConsoleOutput (char *string)
+{
+ if (nostdout && nostdout->value)
+ return;
+
+ fputs(string, stdout);
+}
+
+void Sys_Printf (char *fmt, ...)
+{
+ va_list argptr;
+ char text[1024];
+ unsigned char *p;
+
+ va_start (argptr,fmt);
+ vsprintf (text,fmt,argptr);
+ va_end (argptr);
+
+ if (strlen(text) > sizeof(text))
+ Sys_Error("memory overwrite in Sys_Printf");
+
+ if (nostdout && nostdout->value)
+ return;
+
+ for (p = (unsigned char *)text; *p; p++) {
+ *p &= 0x7f;
+ if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9)
+ printf("[%02x]", *p);
+ else
+ putc(*p, stdout);
+ }
+}
+
+void Sys_Quit (void)
+{
+ CL_Shutdown ();
+ Qcommon_Shutdown ();
+ fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
+ _exit(0);
+}
+
+void Sys_Init(void)
+{
+#if id386
+// Sys_SetFPCW();
+#endif
+}
+
+void Sys_Error (char *error, ...)
+{
+ va_list argptr;
+ char string[1024];
+
+// change stdin to non blocking
+ fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
+
+ CL_Shutdown ();
+ Qcommon_Shutdown ();
+
+ va_start (argptr,error);
+ vsprintf (string,error,argptr);
+ va_end (argptr);
+ fprintf(stderr, "Error: %s\n", string);
+
+ _exit (1);
+
+}
+
+void Sys_Warn (char *warning, ...)
+{
+ va_list argptr;
+ char string[1024];
+
+ va_start (argptr,warning);
+ vsprintf (string,warning,argptr);
+ va_end (argptr);
+ fprintf(stderr, "Warning: %s", string);
+}
+
+/*
+============
+Sys_FileTime
+
+returns -1 if not present
+============
+*/
+int Sys_FileTime (char *path)
+{
+ struct stat buf;
+
+ if (stat (path,&buf) == -1)
+ return -1;
+
+ return buf.st_mtime;
+}
+
+void floating_point_exception_handler(int whatever)
+{
+// Sys_Warn("floating point exception\n");
+ signal(SIGFPE, floating_point_exception_handler);
+}
+
+char *Sys_ConsoleInput(void)
+{
+ static char text[256];
+ int len;
+ fd_set fdset;
+ struct timeval timeout;
+
+ if (!dedicated || !dedicated->value)
+ return NULL;
+
+ if (!stdin_active)
+ return NULL;
+
+ FD_ZERO(&fdset);
+ FD_SET(0, &fdset); // stdin
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset))
+ return NULL;
+
+ len = read (0, text, sizeof(text));
+ if (len == 0) { // eof!
+ stdin_active = false;
+ return NULL;
+ }
+
+ if (len < 1)
+ return NULL;
+ text[len-1] = 0; // rip off the /n and terminate
+
+ return text;
+}
+
+/*****************************************************************************/
+
+static void *game_library;
+
+/*
+=================
+Sys_UnloadGame
+=================
+*/
+void Sys_UnloadGame (void)
+{
+ if (game_library)
+ dlclose (game_library);
+ game_library = NULL;
+}
+
+/*
+=================
+Sys_GetGameAPI
+
+Loads the game dll
+=================
+*/
+void *Sys_GetGameAPI (void *parms)
+{
+ void *(*GetGameAPI) (void *);
+
+ char name[MAX_OSPATH];
+ char curpath[MAX_OSPATH];
+ char *path;
+#ifdef __i386__
+ const char *gamename = "gamei386.so";
+#elif defined __alpha__
+ const char *gamename = "gameaxp.so";
+#else
+#error Unknown arch
+#endif
+
+ setreuid(getuid(), getuid());
+ setegid(getgid());
+
+ if (game_library)
+ Com_Error (ERR_FATAL, "Sys_GetGameAPI without Sys_UnloadingGame");
+
+ getcwd(curpath, sizeof(curpath));
+
+ Com_Printf("------- Loading %s -------", gamename);
+
+ // now run through the search paths
+ path = NULL;
+ while (1)
+ {
+ path = FS_NextPath (path);
+ if (!path)
+ return NULL; // couldn't find one anywhere
+ sprintf (name, "%s/%s/%s", curpath, path, gamename);
+ game_library = dlopen (name, RTLD_NOW );
+ if (game_library)
+ {
+ Com_DPrintf ("LoadLibrary (%s)\n",name);
+ break;
+ }
+ else
+ printf("dlerror: %s\n", dlerror());
+ }
+
+ GetGameAPI = (void *)dlsym (game_library, "GetGameAPI");
+ if (!GetGameAPI)
+ {
+ Sys_UnloadGame ();
+ return NULL;
+ }
+
+ return GetGameAPI (parms);
+}
+
+/*****************************************************************************/
+
+void Sys_AppActivate (void)
+{
+}
+
+void Sys_SendKeyEvents (void)
+{
+#ifndef DEDICATED_ONLY
+ if (KBD_Update_fp)
+ KBD_Update_fp();
+#endif
+
+ // grab frame time
+ sys_frame_time = Sys_Milliseconds();
+}
+
+/*****************************************************************************/
+
+char *Sys_GetClipboardData(void)
+{
+ return NULL;
+}
+
+int main (int argc, char **argv)
+{
+ int time, oldtime, newtime;
+
+ // go back to real user for config loads
+ saved_euid = geteuid();
+ seteuid(getuid());
+
+ Qcommon_Init(argc, argv);
+
+ fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
+
+ nostdout = Cvar_Get("nostdout", "0", 0);
+ if (!nostdout->value) {
+ fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
+// printf ("Linux Quake -- Version %0.3f\n", LINUX_VERSION);
+ }
+
+ oldtime = Sys_Milliseconds ();
+ while (1)
+ {
+// find time spent rendering last frame
+ do {
+ newtime = Sys_Milliseconds ();
+ time = newtime - oldtime;
+ } while (time < 1);
+ Qcommon_Frame (time);
+ oldtime = newtime;
+ }
+
+}
+
+void Sys_CopyProtect(void)
+{
+ FILE *mnt;
+ struct mntent *ent;
+ char path[MAX_OSPATH];
+ struct stat st;
+ qboolean found_cd = false;
+
+ static qboolean checked = false;
+
+ if (checked)
+ return;
+
+ if ((mnt = setmntent("/etc/mtab", "r")) == NULL)
+ Com_Error(ERR_FATAL, "Can't read mount table to determine mounted cd location.");
+
+ while ((ent = getmntent(mnt)) != NULL) {
+ if (strcmp(ent->mnt_type, "iso9660") == 0) {
+ // found a cd file system
+ found_cd = true;
+ sprintf(path, "%s/%s", ent->mnt_dir, "install/data/quake2.exe");
+ if (stat(path, &st) == 0) {
+ // found it
+ checked = true;
+ endmntent(mnt);
+ return;
+ }
+ sprintf(path, "%s/%s", ent->mnt_dir, "Install/Data/quake2.exe");
+ if (stat(path, &st) == 0) {
+ // found it
+ checked = true;
+ endmntent(mnt);
+ return;
+ }
+ sprintf(path, "%s/%s", ent->mnt_dir, "quake2.exe");
+ if (stat(path, &st) == 0) {
+ // found it
+ checked = true;
+ endmntent(mnt);
+ return;
+ }
+ }
+ }
+ endmntent(mnt);
+
+ if (found_cd)
+ Com_Error (ERR_FATAL, "Could not find a Quake2 CD in your CD drive.");
+ Com_Error (ERR_FATAL, "Unable to find a mounted iso9660 file system.\n"
+ "You must mount the Quake2 CD in a cdrom drive in order to play.");
+}
+
+#if 0
+/*
+================
+Sys_MakeCodeWriteable
+================
+*/
+void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
+{
+
+ int r;
+ unsigned long addr;
+ int psize = getpagesize();
+
+ addr = (startaddr & ~(psize-1)) - psize;
+
+// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
+// addr, startaddr+length, length);
+
+ r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
+
+ if (r < 0)
+ Sys_Error("Protection change failed\n");
+
+}
+
+#endif
--- a/plan9/sys_linux.c
+++ /dev/null
@@ -1,381 +1,0 @@
-#include <unistd.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/wait.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <mntent.h>
-
-#include <dlfcn.h>
-
-#include "../qcommon/qcommon.h"
-
-#include "../linux/rw_linux.h"
-
-cvar_t *nostdout;
-
-unsigned sys_frame_time;
-
-uid_t saved_euid;
-qboolean stdin_active = true;
-
-// =======================================================================
-// General routines
-// =======================================================================
-
-void Sys_ConsoleOutput (char *string)
-{
- if (nostdout && nostdout->value)
- return;
-
- fputs(string, stdout);
-}
-
-void Sys_Printf (char *fmt, ...)
-{
- va_list argptr;
- char text[1024];
- unsigned char *p;
-
- va_start (argptr,fmt);
- vsprintf (text,fmt,argptr);
- va_end (argptr);
-
- if (strlen(text) > sizeof(text))
- Sys_Error("memory overwrite in Sys_Printf");
-
- if (nostdout && nostdout->value)
- return;
-
- for (p = (unsigned char *)text; *p; p++) {
- *p &= 0x7f;
- if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9)
- printf("[%02x]", *p);
- else
- putc(*p, stdout);
- }
-}
-
-void Sys_Quit (void)
-{
- CL_Shutdown ();
- Qcommon_Shutdown ();
- fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
- _exit(0);
-}
-
-void Sys_Init(void)
-{
-#if id386
-// Sys_SetFPCW();
-#endif
-}
-
-void Sys_Error (char *error, ...)
-{
- va_list argptr;
- char string[1024];
-
-// change stdin to non blocking
- fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
-
- CL_Shutdown ();
- Qcommon_Shutdown ();
-
- va_start (argptr,error);
- vsprintf (string,error,argptr);
- va_end (argptr);
- fprintf(stderr, "Error: %s\n", string);
-
- _exit (1);
-
-}
-
-void Sys_Warn (char *warning, ...)
-{
- va_list argptr;
- char string[1024];
-
- va_start (argptr,warning);
- vsprintf (string,warning,argptr);
- va_end (argptr);
- fprintf(stderr, "Warning: %s", string);
-}
-
-/*
-============
-Sys_FileTime
-
-returns -1 if not present
-============
-*/
-int Sys_FileTime (char *path)
-{
- struct stat buf;
-
- if (stat (path,&buf) == -1)
- return -1;
-
- return buf.st_mtime;
-}
-
-void floating_point_exception_handler(int whatever)
-{
-// Sys_Warn("floating point exception\n");
- signal(SIGFPE, floating_point_exception_handler);
-}
-
-char *Sys_ConsoleInput(void)
-{
- static char text[256];
- int len;
- fd_set fdset;
- struct timeval timeout;
-
- if (!dedicated || !dedicated->value)
- return NULL;
-
- if (!stdin_active)
- return NULL;
-
- FD_ZERO(&fdset);
- FD_SET(0, &fdset); // stdin
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset))
- return NULL;
-
- len = read (0, text, sizeof(text));
- if (len == 0) { // eof!
- stdin_active = false;
- return NULL;
- }
-
- if (len < 1)
- return NULL;
- text[len-1] = 0; // rip off the /n and terminate
-
- return text;
-}
-
-/*****************************************************************************/
-
-static void *game_library;
-
-/*
-=================
-Sys_UnloadGame
-=================
-*/
-void Sys_UnloadGame (void)
-{
- if (game_library)
- dlclose (game_library);
- game_library = NULL;
-}
-
-/*
-=================
-Sys_GetGameAPI
-
-Loads the game dll
-=================
-*/
-void *Sys_GetGameAPI (void *parms)
-{
- void *(*GetGameAPI) (void *);
-
- char name[MAX_OSPATH];
- char curpath[MAX_OSPATH];
- char *path;
-#ifdef __i386__
- const char *gamename = "gamei386.so";
-#elif defined __alpha__
- const char *gamename = "gameaxp.so";
-#else
-#error Unknown arch
-#endif
-
- setreuid(getuid(), getuid());
- setegid(getgid());
-
- if (game_library)
- Com_Error (ERR_FATAL, "Sys_GetGameAPI without Sys_UnloadingGame");
-
- getcwd(curpath, sizeof(curpath));
-
- Com_Printf("------- Loading %s -------", gamename);
-
- // now run through the search paths
- path = NULL;
- while (1)
- {
- path = FS_NextPath (path);
- if (!path)
- return NULL; // couldn't find one anywhere
- sprintf (name, "%s/%s/%s", curpath, path, gamename);
- game_library = dlopen (name, RTLD_NOW );
- if (game_library)
- {
- Com_DPrintf ("LoadLibrary (%s)\n",name);
- break;
- }
- else
- printf("dlerror: %s\n", dlerror());
- }
-
- GetGameAPI = (void *)dlsym (game_library, "GetGameAPI");
- if (!GetGameAPI)
- {
- Sys_UnloadGame ();
- return NULL;
- }
-
- return GetGameAPI (parms);
-}
-
-/*****************************************************************************/
-
-void Sys_AppActivate (void)
-{
-}
-
-void Sys_SendKeyEvents (void)
-{
-#ifndef DEDICATED_ONLY
- if (KBD_Update_fp)
- KBD_Update_fp();
-#endif
-
- // grab frame time
- sys_frame_time = Sys_Milliseconds();
-}
-
-/*****************************************************************************/
-
-char *Sys_GetClipboardData(void)
-{
- return NULL;
-}
-
-int main (int argc, char **argv)
-{
- int time, oldtime, newtime;
-
- // go back to real user for config loads
- saved_euid = geteuid();
- seteuid(getuid());
-
- Qcommon_Init(argc, argv);
-
- fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
-
- nostdout = Cvar_Get("nostdout", "0", 0);
- if (!nostdout->value) {
- fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
-// printf ("Linux Quake -- Version %0.3f\n", LINUX_VERSION);
- }
-
- oldtime = Sys_Milliseconds ();
- while (1)
- {
-// find time spent rendering last frame
- do {
- newtime = Sys_Milliseconds ();
- time = newtime - oldtime;
- } while (time < 1);
- Qcommon_Frame (time);
- oldtime = newtime;
- }
-
-}
-
-void Sys_CopyProtect(void)
-{
- FILE *mnt;
- struct mntent *ent;
- char path[MAX_OSPATH];
- struct stat st;
- qboolean found_cd = false;
-
- static qboolean checked = false;
-
- if (checked)
- return;
-
- if ((mnt = setmntent("/etc/mtab", "r")) == NULL)
- Com_Error(ERR_FATAL, "Can't read mount table to determine mounted cd location.");
-
- while ((ent = getmntent(mnt)) != NULL) {
- if (strcmp(ent->mnt_type, "iso9660") == 0) {
- // found a cd file system
- found_cd = true;
- sprintf(path, "%s/%s", ent->mnt_dir, "install/data/quake2.exe");
- if (stat(path, &st) == 0) {
- // found it
- checked = true;
- endmntent(mnt);
- return;
- }
- sprintf(path, "%s/%s", ent->mnt_dir, "Install/Data/quake2.exe");
- if (stat(path, &st) == 0) {
- // found it
- checked = true;
- endmntent(mnt);
- return;
- }
- sprintf(path, "%s/%s", ent->mnt_dir, "quake2.exe");
- if (stat(path, &st) == 0) {
- // found it
- checked = true;
- endmntent(mnt);
- return;
- }
- }
- }
- endmntent(mnt);
-
- if (found_cd)
- Com_Error (ERR_FATAL, "Could not find a Quake2 CD in your CD drive.");
- Com_Error (ERR_FATAL, "Unable to find a mounted iso9660 file system.\n"
- "You must mount the Quake2 CD in a cdrom drive in order to play.");
-}
-
-#if 0
-/*
-================
-Sys_MakeCodeWriteable
-================
-*/
-void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
-{
-
- int r;
- unsigned long addr;
- int psize = getpagesize();
-
- addr = (startaddr & ~(psize-1)) - psize;
-
-// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
-// addr, startaddr+length, length);
-
- r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
-
- if (r < 0)
- Sys_Error("Protection change failed\n");
-
-}
-
-#endif
--- /dev/null
+++ b/ref/adivtab.h
@@ -1,0 +1,1077 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// table of quotients and remainders for [-15...16] / [-15...16]
+
+// numerator = -15
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{1, -6},
+{1, -7},
+{2, -1},
+{2, -3},
+{3, 0},
+{3, -3},
+{5, 0},
+{7, -1},
+{15, 0},
+{0, 0},
+{-15, 0},
+{-8, 1},
+{-5, 0},
+{-4, 1},
+{-3, 0},
+{-3, 3},
+{-3, 6},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-2, 7},
+{-2, 9},
+{-2, 11},
+{-2, 13},
+{-1, 0},
+{-1, 1},
+// numerator = -14
+{0, -14},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{1, -6},
+{2, 0},
+{2, -2},
+{2, -4},
+{3, -2},
+{4, -2},
+{7, 0},
+{14, 0},
+{0, 0},
+{-14, 0},
+{-7, 0},
+{-5, 1},
+{-4, 2},
+{-3, 1},
+{-3, 4},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-2, 6},
+{-2, 8},
+{-2, 10},
+{-2, 12},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+// numerator = -13
+{0, -13},
+{0, -13},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{1, -6},
+{2, -1},
+{2, -3},
+{3, -1},
+{4, -1},
+{6, -1},
+{13, 0},
+{0, 0},
+{-13, 0},
+{-7, 1},
+{-5, 2},
+{-4, 3},
+{-3, 2},
+{-3, 5},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-2, 7},
+{-2, 9},
+{-2, 11},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+// numerator = -12
+{0, -12},
+{0, -12},
+{0, -12},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{2, 0},
+{2, -2},
+{3, 0},
+{4, 0},
+{6, 0},
+{12, 0},
+{0, 0},
+{-12, 0},
+{-6, 0},
+{-4, 0},
+{-3, 0},
+{-3, 3},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-2, 6},
+{-2, 8},
+{-2, 10},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+// numerator = -11
+{0, -11},
+{0, -11},
+{0, -11},
+{0, -11},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{1, -5},
+{2, -1},
+{2, -3},
+{3, -2},
+{5, -1},
+{11, 0},
+{0, 0},
+{-11, 0},
+{-6, 1},
+{-4, 1},
+{-3, 1},
+{-3, 4},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-2, 7},
+{-2, 9},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+// numerator = -10
+{0, -10},
+{0, -10},
+{0, -10},
+{0, -10},
+{0, -10},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{2, 0},
+{2, -2},
+{3, -1},
+{5, 0},
+{10, 0},
+{0, 0},
+{-10, 0},
+{-5, 0},
+{-4, 2},
+{-3, 2},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-2, 6},
+{-2, 8},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+// numerator = -9
+{0, -9},
+{0, -9},
+{0, -9},
+{0, -9},
+{0, -9},
+{0, -9},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{1, -4},
+{2, -1},
+{3, 0},
+{4, -1},
+{9, 0},
+{0, 0},
+{-9, 0},
+{-5, 1},
+{-3, 0},
+{-3, 3},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-2, 7},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+// numerator = -8
+{0, -8},
+{0, -8},
+{0, -8},
+{0, -8},
+{0, -8},
+{0, -8},
+{0, -8},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{2, 0},
+{2, -2},
+{4, 0},
+{8, 0},
+{0, 0},
+{-8, 0},
+{-4, 0},
+{-3, 1},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-2, 6},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+// numerator = -7
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{0, -7},
+{1, 0},
+{1, -1},
+{1, -2},
+{1, -3},
+{2, -1},
+{3, -1},
+{7, 0},
+{0, 0},
+{-7, 0},
+{-4, 1},
+{-3, 2},
+{-2, 1},
+{-2, 3},
+{-2, 5},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+// numerator = -6
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{0, -6},
+{1, 0},
+{1, -1},
+{1, -2},
+{2, 0},
+{3, 0},
+{6, 0},
+{0, 0},
+{-6, 0},
+{-3, 0},
+{-2, 0},
+{-2, 2},
+{-2, 4},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+// numerator = -5
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{0, -5},
+{1, 0},
+{1, -1},
+{1, -2},
+{2, -1},
+{5, 0},
+{0, 0},
+{-5, 0},
+{-3, 1},
+{-2, 1},
+{-2, 3},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+// numerator = -4
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{0, -4},
+{1, 0},
+{1, -1},
+{2, 0},
+{4, 0},
+{0, 0},
+{-4, 0},
+{-2, 0},
+{-2, 2},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+{-1, 12},
+// numerator = -3
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{0, -3},
+{1, 0},
+{1, -1},
+{3, 0},
+{0, 0},
+{-3, 0},
+{-2, 1},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+{-1, 12},
+{-1, 13},
+// numerator = -2
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{0, -2},
+{1, 0},
+{2, 0},
+{0, 0},
+{-2, 0},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+{-1, 12},
+{-1, 13},
+{-1, 14},
+// numerator = -1
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{0, -1},
+{1, 0},
+{0, 0},
+{-1, 0},
+{-1, 1},
+{-1, 2},
+{-1, 3},
+{-1, 4},
+{-1, 5},
+{-1, 6},
+{-1, 7},
+{-1, 8},
+{-1, 9},
+{-1, 10},
+{-1, 11},
+{-1, 12},
+{-1, 13},
+{-1, 14},
+{-1, 15},
+// numerator = 0
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+{0, 0},
+// numerator = 1
+{-1, -14},
+{-1, -13},
+{-1, -12},
+{-1, -11},
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{0, 0},
+{1, 0},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+{0, 1},
+// numerator = 2
+{-1, -13},
+{-1, -12},
+{-1, -11},
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, 0},
+{0, 0},
+{2, 0},
+{1, 0},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+{0, 2},
+// numerator = 3
+{-1, -12},
+{-1, -11},
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -1},
+{-3, 0},
+{0, 0},
+{3, 0},
+{1, 1},
+{1, 0},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+{0, 3},
+// numerator = 4
+{-1, -11},
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -2},
+{-2, 0},
+{-4, 0},
+{0, 0},
+{4, 0},
+{2, 0},
+{1, 1},
+{1, 0},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+{0, 4},
+// numerator = 5
+{-1, -10},
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -3},
+{-2, -1},
+{-3, -1},
+{-5, 0},
+{0, 0},
+{5, 0},
+{2, 1},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+{0, 5},
+// numerator = 6
+{-1, -9},
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, 0},
+{-6, 0},
+{0, 0},
+{6, 0},
+{3, 0},
+{2, 0},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+{0, 6},
+// numerator = 7
+{-1, -8},
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -2},
+{-4, -1},
+{-7, 0},
+{0, 0},
+{7, 0},
+{3, 1},
+{2, 1},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+{0, 7},
+// numerator = 8
+{-1, -7},
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -1},
+{-4, 0},
+{-8, 0},
+{0, 0},
+{8, 0},
+{4, 0},
+{2, 2},
+{2, 0},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+{0, 8},
+// numerator = 9
+{-1, -6},
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -7},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -3},
+{-3, 0},
+{-5, -1},
+{-9, 0},
+{0, 0},
+{9, 0},
+{4, 1},
+{3, 0},
+{2, 1},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 9},
+{0, 9},
+{0, 9},
+{0, 9},
+{0, 9},
+{0, 9},
+{0, 9},
+// numerator = 10
+{-1, -5},
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -8},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -2},
+{-4, -2},
+{-5, 0},
+{-10, 0},
+{0, 0},
+{10, 0},
+{5, 0},
+{3, 1},
+{2, 2},
+{2, 0},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 10},
+{0, 10},
+{0, 10},
+{0, 10},
+{0, 10},
+{0, 10},
+// numerator = 11
+{-1, -4},
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -9},
+{-2, -7},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -4},
+{-3, -1},
+{-4, -1},
+{-6, -1},
+{-11, 0},
+{0, 0},
+{11, 0},
+{5, 1},
+{3, 2},
+{2, 3},
+{2, 1},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 11},
+{0, 11},
+{0, 11},
+{0, 11},
+{0, 11},
+// numerator = 12
+{-1, -3},
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -10},
+{-2, -8},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -3},
+{-3, 0},
+{-4, 0},
+{-6, 0},
+{-12, 0},
+{0, 0},
+{12, 0},
+{6, 0},
+{4, 0},
+{3, 0},
+{2, 2},
+{2, 0},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 12},
+{0, 12},
+{0, 12},
+{0, 12},
+// numerator = 13
+{-1, -2},
+{-1, -1},
+{-1, 0},
+{-2, -11},
+{-2, -9},
+{-2, -7},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -5},
+{-3, -2},
+{-4, -3},
+{-5, -2},
+{-7, -1},
+{-13, 0},
+{0, 0},
+{13, 0},
+{6, 1},
+{4, 1},
+{3, 1},
+{2, 3},
+{2, 1},
+{1, 6},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 13},
+{0, 13},
+{0, 13},
+// numerator = 14
+{-1, -1},
+{-1, 0},
+{-2, -12},
+{-2, -10},
+{-2, -8},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -4},
+{-3, -1},
+{-4, -2},
+{-5, -1},
+{-7, 0},
+{-14, 0},
+{0, 0},
+{14, 0},
+{7, 0},
+{4, 2},
+{3, 2},
+{2, 4},
+{2, 2},
+{2, 0},
+{1, 6},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 14},
+{0, 14},
+// numerator = 15
+{-1, 0},
+{-2, -13},
+{-2, -11},
+{-2, -9},
+{-2, -7},
+{-2, -5},
+{-2, -3},
+{-2, -1},
+{-3, -6},
+{-3, -3},
+{-3, 0},
+{-4, -1},
+{-5, 0},
+{-8, -1},
+{-15, 0},
+{0, 0},
+{15, 0},
+{7, 1},
+{5, 0},
+{3, 3},
+{3, 0},
+{2, 3},
+{2, 1},
+{1, 7},
+{1, 6},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
+{0, 15},
+// numerator = 16
+{-2, -14},
+{-2, -12},
+{-2, -10},
+{-2, -8},
+{-2, -6},
+{-2, -4},
+{-2, -2},
+{-2, 0},
+{-3, -5},
+{-3, -2},
+{-4, -4},
+{-4, 0},
+{-6, -2},
+{-8, 0},
+{-16, 0},
+{0, 0},
+{16, 0},
+{8, 0},
+{5, 1},
+{4, 0},
+{3, 1},
+{2, 4},
+{2, 2},
+{2, 0},
+{1, 7},
+{1, 6},
+{1, 5},
+{1, 4},
+{1, 3},
+{1, 2},
+{1, 1},
+{1, 0},
--- /dev/null
+++ b/ref/r_aclip.c
@@ -1,0 +1,323 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// r_aclip.c: clip routines for drawing Alias models directly to the screen
+
+#include "r_local.h"
+
+static finalvert_t fv[2][8];
+
+void R_AliasProjectAndClipTestFinalVert (finalvert_t *fv);
+void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1,
+ finalvert_t *out);
+void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
+ finalvert_t *out);
+void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1,
+ finalvert_t *out);
+void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
+ finalvert_t *out);
+
+
+/*
+================
+R_Alias_clip_z
+
+pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
+================
+*/
+void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
+{
+ float scale;
+
+ scale = (ALIAS_Z_CLIP_PLANE - pfv0->xyz[2]) /
+ (pfv1->xyz[2] - pfv0->xyz[2]);
+
+ out->xyz[0] = pfv0->xyz[0] + (pfv1->xyz[0] - pfv0->xyz[0]) * scale;
+ out->xyz[1] = pfv0->xyz[1] + (pfv1->xyz[1] - pfv0->xyz[1]) * scale;
+ out->xyz[2] = ALIAS_Z_CLIP_PLANE;
+
+ out->s = pfv0->s + (pfv1->s - pfv0->s) * scale;
+ out->t = pfv0->t + (pfv1->t - pfv0->t) * scale;
+ out->l = pfv0->l + (pfv1->l - pfv0->l) * scale;
+
+ R_AliasProjectAndClipTestFinalVert (out);
+}
+
+
+#if !id386
+
+void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
+{
+ float scale;
+
+ if (pfv0->v >= pfv1->v )
+ {
+ scale = (float)(r_refdef.aliasvrect.x - pfv0->u) /
+ (pfv1->u - pfv0->u);
+ out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
+ out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
+ out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
+ out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
+ out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
+ out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
+ }
+ else
+ {
+ scale = (float)(r_refdef.aliasvrect.x - pfv1->u) /
+ (pfv0->u - pfv1->u);
+ out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
+ out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
+ out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
+ out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
+ out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
+ out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
+ }
+}
+
+
+void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
+{
+ float scale;
+
+ if ( pfv0->v >= pfv1->v )
+ {
+ scale = (float)(r_refdef.aliasvrectright - pfv0->u ) /
+ (pfv1->u - pfv0->u );
+ out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
+ out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
+ out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
+ out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
+ out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
+ out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
+ }
+ else
+ {
+ scale = (float)(r_refdef.aliasvrectright - pfv1->u ) /
+ (pfv0->u - pfv1->u );
+ out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
+ out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
+ out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
+ out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
+ out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
+ out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
+ }
+}
+
+
+void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
+{
+ float scale;
+
+ if (pfv0->v >= pfv1->v)
+ {
+ scale = (float)(r_refdef.aliasvrect.y - pfv0->v) /
+ (pfv1->v - pfv0->v);
+ out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
+ out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
+ out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
+ out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
+ out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
+ out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
+ }
+ else
+ {
+ scale = (float)(r_refdef.aliasvrect.y - pfv1->v) /
+ (pfv0->v - pfv1->v);
+ out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
+ out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
+ out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
+ out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
+ out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
+ out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
+ }
+}
+
+
+void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
+ finalvert_t *out)
+{
+ float scale;
+
+ if (pfv0->v >= pfv1->v)
+ {
+ scale = (float)(r_refdef.aliasvrectbottom - pfv0->v) /
+ (pfv1->v - pfv0->v);
+
+ out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
+ out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
+ out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
+ out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
+ out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
+ out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
+ }
+ else
+ {
+ scale = (float)(r_refdef.aliasvrectbottom - pfv1->v) /
+ (pfv0->v - pfv1->v);
+
+ out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
+ out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
+ out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
+ out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
+ out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
+ out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
+ }
+}
+
+#endif
+
+
+int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count,
+ void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) )
+{
+ int i,j,k;
+ int flags, oldflags;
+
+ j = count-1;
+ k = 0;
+ for (i=0 ; i<count ; j = i, i++)
+ {
+ oldflags = in[j].flags & flag;
+ flags = in[i].flags & flag;
+
+ if (flags && oldflags)
+ continue;
+ if (oldflags ^ flags)
+ {
+ clip (&in[j], &in[i], &out[k]);
+ out[k].flags = 0;
+ if (out[k].u < r_refdef.aliasvrect.x)
+ out[k].flags |= ALIAS_LEFT_CLIP;
+ if (out[k].v < r_refdef.aliasvrect.y)
+ out[k].flags |= ALIAS_TOP_CLIP;
+ if (out[k].u > r_refdef.aliasvrectright)
+ out[k].flags |= ALIAS_RIGHT_CLIP;
+ if (out[k].v > r_refdef.aliasvrectbottom)
+ out[k].flags |= ALIAS_BOTTOM_CLIP;
+ k++;
+ }
+ if (!flags)
+ {
+ out[k] = in[i];
+ k++;
+ }
+ }
+
+ return k;
+}
+
+
+/*
+================
+R_AliasClipTriangle
+================
+*/
+void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2)
+{
+ int i, k, pingpong;
+ unsigned clipflags;
+
+// copy vertexes and fix seam texture coordinates
+ fv[0][0] = *index0;
+ fv[0][1] = *index1;
+ fv[0][2] = *index2;
+
+// clip
+ clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
+
+ if (clipflags & ALIAS_Z_CLIP)
+ {
+ k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z);
+ if (k == 0)
+ return;
+
+ pingpong = 1;
+ clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags;
+ }
+ else
+ {
+ pingpong = 0;
+ k = 3;
+ }
+
+ if (clipflags & ALIAS_LEFT_CLIP)
+ {
+ k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
+ ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
+ if (k == 0)
+ return;
+
+ pingpong ^= 1;
+ }
+
+ if (clipflags & ALIAS_RIGHT_CLIP)
+ {
+ k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
+ ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
+ if (k == 0)
+ return;
+
+ pingpong ^= 1;
+ }
+
+ if (clipflags & ALIAS_BOTTOM_CLIP)
+ {
+ k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
+ ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
+ if (k == 0)
+ return;
+
+ pingpong ^= 1;
+ }
+
+ if (clipflags & ALIAS_TOP_CLIP)
+ {
+ k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
+ ALIAS_TOP_CLIP, k, R_Alias_clip_top);
+ if (k == 0)
+ return;
+
+ pingpong ^= 1;
+ }
+
+ for (i=0 ; i<k ; i++)
+ {
+ if (fv[pingpong][i].u < r_refdef.aliasvrect.x)
+ fv[pingpong][i].u = r_refdef.aliasvrect.x;
+ else if (fv[pingpong][i].u > r_refdef.aliasvrectright)
+ fv[pingpong][i].u = r_refdef.aliasvrectright;
+
+ if (fv[pingpong][i].v < r_refdef.aliasvrect.y)
+ fv[pingpong][i].v = r_refdef.aliasvrect.y;
+ else if (fv[pingpong][i].v > r_refdef.aliasvrectbottom)
+ fv[pingpong][i].v = r_refdef.aliasvrectbottom;
+
+ fv[pingpong][i].flags = 0;
+ }
+
+// draw triangles
+ for (i=1 ; i<k-1 ; i++)
+ {
+ aliastriangleparms.a = &fv[pingpong][0];
+ aliastriangleparms.b = &fv[pingpong][i];
+ aliastriangleparms.c = &fv[pingpong][i+1];
+ R_DrawTriangle();
+ }
+}
+
--- /dev/null
+++ b/ref/r_alias.c
@@ -1,0 +1,1198 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// r_alias.c: routines for setting up to draw alias models
+
+/*
+** use a real variable to control lerping
+*/
+#include "r_local.h"
+
+#define LIGHT_MIN 5 // lowest light value we'll allow, to avoid the
+ // need for inner-loop light clamping
+
+//PGM
+extern byte iractive;
+//PGM
+
+int r_amodels_drawn;
+
+affinetridesc_t r_affinetridesc;
+
+vec3_t r_plightvec;
+vec3_t r_lerped[1024];
+vec3_t r_lerp_frontv, r_lerp_backv, r_lerp_move;
+
+int r_ambientlight;
+int r_aliasblendcolor;
+float r_shadelight;
+
+
+daliasframe_t *r_thisframe, *r_lastframe;
+dmdl_t *s_pmdl;
+
+float aliastransform[3][4];
+float aliasworldtransform[3][4];
+float aliasoldworldtransform[3][4];
+
+static float s_ziscale;
+static vec3_t s_alias_forward, s_alias_right, s_alias_up;
+
+
+#define NUMVERTEXNORMALS 162
+
+float r_avertexnormals[NUMVERTEXNORMALS][3] = {
+#include "../anorms.h"
+};
+
+
+void R_AliasSetUpLerpData( dmdl_t *pmdl, float backlerp );
+void R_AliasSetUpTransform (void);
+void R_AliasTransformVector (vec3_t in, vec3_t out, float m[3][4] );
+void R_AliasProjectAndClipTestFinalVert (finalvert_t *fv);
+
+void R_AliasTransformFinalVerts( int numpoints, finalvert_t *fv, dtrivertx_t *oldv, dtrivertx_t *newv );
+
+void R_AliasLerpFrames( dmdl_t *paliashdr, float backlerp );
+
+/*
+================
+R_AliasCheckBBox
+================
+*/
+typedef struct {
+ int index0;
+ int index1;
+} aedge_t;
+
+static aedge_t aedges[12] = {
+{0, 1}, {1, 2}, {2, 3}, {3, 0},
+{4, 5}, {5, 6}, {6, 7}, {7, 4},
+{0, 5}, {1, 4}, {2, 7}, {3, 6}
+};
+
+#define BBOX_TRIVIAL_ACCEPT 0
+#define BBOX_MUST_CLIP_XY 1
+#define BBOX_MUST_CLIP_Z 2
+#define BBOX_TRIVIAL_REJECT 8
+
+/*
+** R_AliasCheckFrameBBox
+**
+** Checks a specific alias frame bounding box
+*/
+unsigned long R_AliasCheckFrameBBox( daliasframe_t *frame, float worldxf[3][4] )
+{
+ unsigned long aggregate_and_clipcode = ~0U,
+ aggregate_or_clipcode = 0;
+ int i;
+ vec3_t mins, maxs;
+ vec3_t transformed_min, transformed_max;
+ qboolean zclipped = false, zfullyclipped = true;
+ float minz = 9999.0F;
+
+ /*
+ ** get the exact frame bounding box
+ */
+ for (i=0 ; i<3 ; i++)
+ {
+ mins[i] = frame->translate[i];
+ maxs[i] = mins[i] + frame->scale[i]*255;
+ }
+
+ /*
+ ** transform the min and max values into view space
+ */
+ R_AliasTransformVector( mins, transformed_min, aliastransform );
+ R_AliasTransformVector( maxs, transformed_max, aliastransform );
+
+ if ( transformed_min[2] >= ALIAS_Z_CLIP_PLANE )
+ zfullyclipped = false;
+ if ( transformed_max[2] >= ALIAS_Z_CLIP_PLANE )
+ zfullyclipped = false;
+
+ if ( zfullyclipped )
+ {
+ return BBOX_TRIVIAL_REJECT;
+ }
+ if ( zclipped )
+ {
+ return ( BBOX_MUST_CLIP_XY | BBOX_MUST_CLIP_Z );
+ }
+
+ /*
+ ** build a transformed bounding box from the given min and max
+ */
+ for ( i = 0; i < 8; i++ )
+ {
+ int j;
+ vec3_t tmp, transformed;
+ unsigned long clipcode = 0;
+
+ if ( i & 1 )
+ tmp[0] = mins[0];
+ else
+ tmp[0] = maxs[0];
+
+ if ( i & 2 )
+ tmp[1] = mins[1];
+ else
+ tmp[1] = maxs[1];
+
+ if ( i & 4 )
+ tmp[2] = mins[2];
+ else
+ tmp[2] = maxs[2];
+
+ R_AliasTransformVector( tmp, transformed, worldxf );
+
+ for ( j = 0; j < 4; j++ )
+ {
+ float dp = DotProduct( transformed, view_clipplanes[j].normal );
+
+ if ( ( dp - view_clipplanes[j].dist ) < 0.0F )
+ clipcode |= 1 << j;
+ }
+
+ aggregate_and_clipcode &= clipcode;
+ aggregate_or_clipcode |= clipcode;
+ }
+
+ if ( aggregate_and_clipcode )
+ {
+ return BBOX_TRIVIAL_REJECT;
+ }
+ if ( !aggregate_or_clipcode )
+ {
+ return BBOX_TRIVIAL_ACCEPT;
+ }
+
+ return BBOX_MUST_CLIP_XY;
+}
+
+qboolean R_AliasCheckBBox (void)
+{
+ unsigned long ccodes[2] = { 0, 0 };
+
+ ccodes[0] = R_AliasCheckFrameBBox( r_thisframe, aliasworldtransform );
+
+ /*
+ ** non-lerping model
+ */
+ if ( currententity->backlerp == 0 )
+ {
+ if ( ccodes[0] == BBOX_TRIVIAL_ACCEPT )
+ return BBOX_TRIVIAL_ACCEPT;
+ else if ( ccodes[0] & BBOX_TRIVIAL_REJECT )
+ return BBOX_TRIVIAL_REJECT;
+ else
+ return ( ccodes[0] & ~BBOX_TRIVIAL_REJECT );
+ }
+
+ ccodes[1] = R_AliasCheckFrameBBox( r_lastframe, aliasoldworldtransform );
+
+ if ( ( ccodes[0] | ccodes[1] ) == BBOX_TRIVIAL_ACCEPT )
+ return BBOX_TRIVIAL_ACCEPT;
+ else if ( ( ccodes[0] & ccodes[1] ) & BBOX_TRIVIAL_REJECT )
+ return BBOX_TRIVIAL_REJECT;
+ else
+ return ( ccodes[0] | ccodes[1] ) & ~BBOX_TRIVIAL_REJECT;
+}
+
+
+/*
+================
+R_AliasTransformVector
+================
+*/
+void R_AliasTransformVector(vec3_t in, vec3_t out, float xf[3][4] )
+{
+ out[0] = DotProduct(in, xf[0]) + xf[0][3];
+ out[1] = DotProduct(in, xf[1]) + xf[1][3];
+ out[2] = DotProduct(in, xf[2]) + xf[2][3];
+}
+
+
+/*
+================
+R_AliasPreparePoints
+
+General clipped case
+================
+*/
+typedef struct
+{
+ int num_points;
+ dtrivertx_t *last_verts; // verts from the last frame
+ dtrivertx_t *this_verts; // verts from this frame
+ finalvert_t *dest_verts; // destination for transformed verts
+} aliasbatchedtransformdata_t;
+
+aliasbatchedtransformdata_t aliasbatchedtransformdata;
+
+void R_AliasPreparePoints (void)
+{
+ int i;
+ dstvert_t *pstverts;
+ dtriangle_t *ptri;
+ finalvert_t *pfv[3];
+ finalvert_t finalverts[MAXALIASVERTS +
+ ((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 3];
+ finalvert_t *pfinalverts;
+
+//PGM
+ iractive = (r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE);
+// iractive = 0;
+// if(r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
+// iractive = 1;
+//PGM
+
+ // put work vertexes on stack, cache aligned
+ pfinalverts = (finalvert_t *)
+ (((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+
+ aliasbatchedtransformdata.num_points = s_pmdl->num_xyz;
+ aliasbatchedtransformdata.last_verts = r_lastframe->verts;
+ aliasbatchedtransformdata.this_verts = r_thisframe->verts;
+ aliasbatchedtransformdata.dest_verts = pfinalverts;
+
+ R_AliasTransformFinalVerts( aliasbatchedtransformdata.num_points,
+ aliasbatchedtransformdata.dest_verts,
+ aliasbatchedtransformdata.last_verts,
+ aliasbatchedtransformdata.this_verts );
+
+// clip and draw all triangles
+//
+ pstverts = (dstvert_t *)((byte *)s_pmdl + s_pmdl->ofs_st);
+ ptri = (dtriangle_t *)((byte *)s_pmdl + s_pmdl->ofs_tris);
+
+ if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
+ {
+ for (i=0 ; i<s_pmdl->num_tris ; i++, ptri++)
+ {
+ pfv[0] = &pfinalverts[ptri->index_xyz[0]];
+ pfv[1] = &pfinalverts[ptri->index_xyz[1]];
+ pfv[2] = &pfinalverts[ptri->index_xyz[2]];
+
+ if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags )
+ continue; // completely clipped
+
+ // insert s/t coordinates
+ pfv[0]->s = pstverts[ptri->index_st[0]].s << 16;
+ pfv[0]->t = pstverts[ptri->index_st[0]].t << 16;
+
+ pfv[1]->s = pstverts[ptri->index_st[1]].s << 16;
+ pfv[1]->t = pstverts[ptri->index_st[1]].t << 16;
+
+ pfv[2]->s = pstverts[ptri->index_st[2]].s << 16;
+ pfv[2]->t = pstverts[ptri->index_st[2]].t << 16;
+
+ if ( ! (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) )
+ { // totally unclipped
+ aliastriangleparms.a = pfv[2];
+ aliastriangleparms.b = pfv[1];
+ aliastriangleparms.c = pfv[0];
+
+ R_DrawTriangle();
+ }
+ else
+ {
+ R_AliasClipTriangle (pfv[2], pfv[1], pfv[0]);
+ }
+ }
+ }
+ else
+ {
+ for (i=0 ; i<s_pmdl->num_tris ; i++, ptri++)
+ {
+ pfv[0] = &pfinalverts[ptri->index_xyz[0]];
+ pfv[1] = &pfinalverts[ptri->index_xyz[1]];
+ pfv[2] = &pfinalverts[ptri->index_xyz[2]];
+
+ if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags )
+ continue; // completely clipped
+
+ // insert s/t coordinates
+ pfv[0]->s = pstverts[ptri->index_st[0]].s << 16;
+ pfv[0]->t = pstverts[ptri->index_st[0]].t << 16;
+
+ pfv[1]->s = pstverts[ptri->index_st[1]].s << 16;
+ pfv[1]->t = pstverts[ptri->index_st[1]].t << 16;
+
+ pfv[2]->s = pstverts[ptri->index_st[2]].s << 16;
+ pfv[2]->t = pstverts[ptri->index_st[2]].t << 16;
+
+ if ( ! (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) )
+ { // totally unclipped
+ aliastriangleparms.a = pfv[0];
+ aliastriangleparms.b = pfv[1];
+ aliastriangleparms.c = pfv[2];
+
+ R_DrawTriangle();
+ }
+ else
+ { // partially clipped
+ R_AliasClipTriangle (pfv[0], pfv[1], pfv[2]);
+ }
+ }
+ }
+}
+
+
+/*
+================
+R_AliasSetUpTransform
+================
+*/
+void R_AliasSetUpTransform (void)
+{
+ int i;
+ static float viewmatrix[3][4];
+ vec3_t angles;
+
+// TODO: should really be stored with the entity instead of being reconstructed
+// TODO: should use a look-up table
+// TODO: could cache lazily, stored in the entity
+//
+ angles[ROLL] = currententity->angles[ROLL];
+ angles[PITCH] = currententity->angles[PITCH];
+ angles[YAW] = currententity->angles[YAW];
+ AngleVectors( angles, s_alias_forward, s_alias_right, s_alias_up );
+
+// TODO: can do this with simple matrix rearrangement
+
+ memset( aliasworldtransform, 0, sizeof( aliasworldtransform ) );
+ memset( aliasoldworldtransform, 0, sizeof( aliasworldtransform ) );
+
+ for (i=0 ; i<3 ; i++)
+ {
+ aliasoldworldtransform[i][0] = aliasworldtransform[i][0] = s_alias_forward[i];
+ aliasoldworldtransform[i][0] = aliasworldtransform[i][1] = -s_alias_right[i];
+ aliasoldworldtransform[i][0] = aliasworldtransform[i][2] = s_alias_up[i];
+ }
+
+ aliasworldtransform[0][3] = currententity->origin[0]-r_origin[0];
+ aliasworldtransform[1][3] = currententity->origin[1]-r_origin[1];
+ aliasworldtransform[2][3] = currententity->origin[2]-r_origin[2];
+
+ aliasoldworldtransform[0][3] = currententity->oldorigin[0]-r_origin[0];
+ aliasoldworldtransform[1][3] = currententity->oldorigin[1]-r_origin[1];
+ aliasoldworldtransform[2][3] = currententity->oldorigin[2]-r_origin[2];
+
+// FIXME: can do more efficiently than full concatenation
+// memcpy( rotationmatrix, t2matrix, sizeof( rotationmatrix ) );
+
+// R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix);
+
+// TODO: should be global, set when vright, etc., set
+ VectorCopy (vright, viewmatrix[0]);
+ VectorCopy (vup, viewmatrix[1]);
+ VectorInverse (viewmatrix[1]);
+ VectorCopy (vpn, viewmatrix[2]);
+
+ viewmatrix[0][3] = 0;
+ viewmatrix[1][3] = 0;
+ viewmatrix[2][3] = 0;
+
+// memcpy( aliasworldtransform, rotationmatrix, sizeof( aliastransform ) );
+
+ R_ConcatTransforms (viewmatrix, aliasworldtransform, aliastransform);
+
+ aliasworldtransform[0][3] = currententity->origin[0];
+ aliasworldtransform[1][3] = currententity->origin[1];
+ aliasworldtransform[2][3] = currententity->origin[2];
+
+ aliasoldworldtransform[0][3] = currententity->oldorigin[0];
+ aliasoldworldtransform[1][3] = currententity->oldorigin[1];
+ aliasoldworldtransform[2][3] = currententity->oldorigin[2];
+}
+
+
+/*
+================
+R_AliasTransformFinalVerts
+================
+*/
+#if id386 && !defined __linux__
+void R_AliasTransformFinalVerts( int numpoints, finalvert_t *fv, dtrivertx_t *oldv, dtrivertx_t *newv )
+{
+ float lightcos;
+ float lerped_vert[3];
+ int byte_to_dword_ptr_var;
+ int tmpint;
+
+ float one = 1.0F;
+ float zi;
+
+ static float FALIAS_Z_CLIP_PLANE = ALIAS_Z_CLIP_PLANE;
+ static float PS_SCALE = POWERSUIT_SCALE;
+
+ __asm mov ecx, numpoints
+
+ /*
+ lerped_vert[0] = r_lerp_move[0] + oldv->v[0]*r_lerp_backv[0] + newv->v[0]*r_lerp_frontv[0];
+ lerped_vert[1] = r_lerp_move[1] + oldv->v[1]*r_lerp_backv[1] + newv->v[1]*r_lerp_frontv[1];
+ lerped_vert[2] = r_lerp_move[2] + oldv->v[2]*r_lerp_backv[2] + newv->v[2]*r_lerp_frontv[2];
+ */
+top_of_loop:
+
+ __asm mov esi, oldv
+ __asm mov edi, newv
+
+ __asm xor ebx, ebx
+
+ __asm mov bl, byte ptr [esi+DTRIVERTX_V0]
+ __asm mov byte_to_dword_ptr_var, ebx
+ __asm fild dword ptr byte_to_dword_ptr_var
+ __asm fmul dword ptr [r_lerp_backv+0] ; oldv[0]*rlb[0]
+
+ __asm mov bl, byte ptr [esi+DTRIVERTX_V1]
+ __asm mov byte_to_dword_ptr_var, ebx
+ __asm fild dword ptr byte_to_dword_ptr_var
+ __asm fmul dword ptr [r_lerp_backv+4] ; oldv[1]*rlb[1] | oldv[0]*rlb[0]
+
+ __asm mov bl, byte ptr [esi+DTRIVERTX_V2]
+ __asm mov byte_to_dword_ptr_var, ebx
+ __asm fild dword ptr byte_to_dword_ptr_var
+ __asm fmul dword ptr [r_lerp_backv+8] ; oldv[2]*rlb[2] | oldv[1]*rlb[1] | oldv[0]*rlb[0]
+
+ __asm mov bl, byte ptr [edi+DTRIVERTX_V0]
+ __asm mov byte_to_dword_ptr_var, ebx
+ __asm fild dword ptr byte_to_dword_ptr_var
+ __asm fmul dword ptr [r_lerp_frontv+0] ; newv[0]*rlf[0] | oldv[2]*rlb[2] | oldv[1]*rlb[1] | oldv[0]*rlb[0]
+
+ __asm mov bl, byte ptr [edi+DTRIVERTX_V1]
+ __asm mov byte_to_dword_ptr_var, ebx
+ __asm fild dword ptr byte_to_dword_ptr_var
+ __asm fmul dword ptr [r_lerp_frontv+4] ; newv[1]*rlf[1] | newv[0]*rlf[0] | oldv[2]*rlb[2] | oldv[1]*rlb[1] | oldv[0]*rlb[0]
+
+ __asm mov bl, byte ptr [edi+DTRIVERTX_V2]
+ __asm mov byte_to_dword_ptr_var, ebx
+ __asm fild dword ptr byte_to_dword_ptr_var
+ __asm fmul dword ptr [r_lerp_frontv+8] ; newv[2]*rlf[2] | newv[1]*rlf[1] | newv[0]*rlf[0] | oldv[2]*rlb[2] | oldv[1]*rlb[1] | oldv[0]*rlb[0]
+
+ __asm fxch st(5) ; oldv[0]*rlb[0] | newv[1]*rlf[1] | newv[0]*rlf[0] | oldv[2]*rlb[2] | oldv[1]*rlb[1] | newv[2]*rlf[2]
+ __asm faddp st(2), st ; newv[1]*rlf[1] | oldv[0]*rlb[0] + newv[0]*rlf[0] | oldv[2]*rlb[2] | oldv[1]*rlb[1] | newv[2]*rlf[2]
+ __asm faddp st(3), st ; oldv[0]*rlb[0] + newv[0]*rlf[0] | oldv[2]*rlb[2] | oldv[1]*rlb[1] + newv[1]*rlf[1] | newv[2]*rlf[2]
+ __asm fxch st(1) ; oldv[2]*rlb[2] | oldv[0]*rlb[0] + newv[0]*rlf[0] | oldv[1]*rlb[1] + newv[1]*rlf[1] | newv[2]*rlf[2]
+ __asm faddp st(3), st ; oldv[0]*rlb[0] + newv[0]*rlf[0] | oldv[1]*rlb[1] + newv[1]*rlf[1] | oldv[2]*rlb[2] + newv[2]*rlf[2]
+ __asm fadd dword ptr [r_lerp_move+0] ; lv0 | oldv[1]*rlb[1] + newv[1]*rlf[1] | oldv[2]*rlb[2] + newv[2]*rlf[2]
+ __asm fxch st(1) ; oldv[1]*rlb[1] + newv[1]*rlf[1] | lv0 | oldv[2]*rlb[2] + newv[2]*rlf[2]
+ __asm fadd dword ptr [r_lerp_move+4] ; lv1 | lv0 | oldv[2]*rlb[2] + newv[2]*rlf[2]
+ __asm fxch st(2) ; oldv[2]*rlb[2] + newv[2]*rlf[2] | lv0 | lv1
+ __asm fadd dword ptr [r_lerp_move+8] ; lv2 | lv0 | lv1
+ __asm fxch st(1) ; lv0 | lv2 | lv1
+ __asm fstp dword ptr [lerped_vert+0] ; lv2 | lv1
+ __asm fstp dword ptr [lerped_vert+8] ; lv2
+ __asm fstp dword ptr [lerped_vert+4] ; (empty)
+
+ __asm mov eax, currententity
+ __asm mov eax, dword ptr [eax+ENTITY_FLAGS]
+ __asm mov ebx, RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM
+ __asm and eax, ebx
+ __asm jz not_powersuit
+
+ /*
+ ** lerped_vert[0] += lightnormal[0] * POWERSUIT_SCALE
+ ** lerped_vert[1] += lightnormal[1] * POWERSUIT_SCALE
+ ** lerped_vert[2] += lightnormal[2] * POWERSUIT_SCALE
+ */
+
+ __asm xor ebx, ebx
+ __asm mov bl, byte ptr [edi+DTRIVERTX_LNI]
+ __asm mov eax, 12
+ __asm mul ebx
+ __asm lea eax, [r_avertexnormals+eax]
+
+ __asm fld dword ptr [eax+0] ; n[0]
+ __asm fmul PS_SCALE ; n[0] * PS
+ __asm fld dword ptr [eax+4] ; n[1] | n[0] * PS
+ __asm fmul PS_SCALE ; n[1] * PS | n[0] * PS
+ __asm fld dword ptr [eax+8] ; n[2] | n[1] * PS | n[0] * PS
+ __asm fmul PS_SCALE ; n[2] * PS | n[1] * PS | n[0] * PS
+ __asm fld dword ptr [lerped_vert+0] ; lv0 | n[2] * PS | n[1] * PS | n[0] * PS
+ __asm faddp st(3), st ; n[2] * PS | n[1] * PS | n[0] * PS + lv0
+ __asm fld dword ptr [lerped_vert+4] ; lv1 | n[2] * PS | n[1] * PS | n[0] * PS + lv0
+ __asm faddp st(2), st ; n[2] * PS | n[1] * PS + lv1 | n[0] * PS + lv0
+ __asm fadd dword ptr [lerped_vert+8] ; n[2] * PS + lv2 | n[1] * PS + lv1 | n[0] * PS + lv0
+ __asm fxch st(2) ; LV0 | LV1 | LV2
+ __asm fstp dword ptr [lerped_vert+0] ; LV1 | LV2
+ __asm fstp dword ptr [lerped_vert+4] ; LV2
+ __asm fstp dword ptr [lerped_vert+8] ; (empty)
+
+not_powersuit:
+
+ /*
+ fv->flags = 0;
+
+ fv->xyz[0] = DotProduct(lerped_vert, aliastransform[0]) + aliastransform[0][3];
+ fv->xyz[1] = DotProduct(lerped_vert, aliastransform[1]) + aliastransform[1][3];
+ fv->xyz[2] = DotProduct(lerped_vert, aliastransform[2]) + aliastransform[2][3];
+ */
+ __asm mov eax, fv
+ __asm mov dword ptr [eax+FINALVERT_FLAGS], 0
+
+ __asm fld dword ptr [lerped_vert+0] ; lv0
+ __asm fmul dword ptr [aliastransform+0] ; lv0*at[0][0]
+ __asm fld dword ptr [lerped_vert+4] ; lv1 | lv0*at[0][0]
+ __asm fmul dword ptr [aliastransform+4] ; lv1*at[0][1] | lv0*at[0][0]
+ __asm fld dword ptr [lerped_vert+8] ; lv2 | lv1*at[0][1] | lv0*at[0][0]
+ __asm fmul dword ptr [aliastransform+8] ; lv2*at[0][2] | lv1*at[0][1] | lv0*at[0][0]
+ __asm fxch st(2) ; lv0*at[0][0] | lv1*at[0][1] | lv2*at[0][2]
+ __asm faddp st(1), st ; lv0*at[0][0] + lv1*at[0][1] | lv2*at[0][2]
+ __asm faddp st(1), st ; lv0*at[0][0] + lv1*at[0][1] + lv2*at[0][2]
+ __asm fadd dword ptr [aliastransform+12] ; FV.X
+
+ __asm fld dword ptr [lerped_vert+0] ; lv0
+ __asm fmul dword ptr [aliastransform+16] ; lv0*at[1][0]
+ __asm fld dword ptr [lerped_vert+4] ; lv1 | lv0*at[1][0]
+ __asm fmul dword ptr [aliastransform+20] ; lv1*at[1][1] | lv0*at[1][0]
+ __asm fld dword ptr [lerped_vert+8] ; lv2 | lv1*at[1][1] | lv0*at[1][0]
+ __asm fmul dword ptr [aliastransform+24] ; lv2*at[1][2] | lv1*at[1][1] | lv0*at[1][0]
+ __asm fxch st(2) ; lv0*at[1][0] | lv1*at[1][1] | lv2*at[1][2]
+ __asm faddp st(1), st ; lv0*at[1][0] + lv1*at[1][1] | lv2*at[1][2]
+ __asm faddp st(1), st ; lv0*at[1][0] + lv1*at[1][1] + lv2*at[1][2]
+ __asm fadd dword ptr [aliastransform+28] ; FV.Y | FV.X
+ __asm fxch st(1) ; FV.X | FV.Y
+ __asm fstp dword ptr [eax+FINALVERT_X] ; FV.Y
+
+ __asm fld dword ptr [lerped_vert+0] ; lv0
+ __asm fmul dword ptr [aliastransform+32] ; lv0*at[2][0]
+ __asm fld dword ptr [lerped_vert+4] ; lv1 | lv0*at[2][0]
+ __asm fmul dword ptr [aliastransform+36] ; lv1*at[2][1] | lv0*at[2][0]
+ __asm fld dword ptr [lerped_vert+8] ; lv2 | lv1*at[2][1] | lv0*at[2][0]
+ __asm fmul dword ptr [aliastransform+40] ; lv2*at[2][2] | lv1*at[2][1] | lv0*at[2][0]
+ __asm fxch st(2) ; lv0*at[2][0] | lv1*at[2][1] | lv2*at[2][2]
+ __asm faddp st(1), st ; lv0*at[2][0] + lv1*at[2][1] | lv2*at[2][2]
+ __asm faddp st(1), st ; lv0*at[2][0] + lv1*at[2][1] + lv2*at[2][2]
+ __asm fadd dword ptr [aliastransform+44] ; FV.Z | FV.Y
+ __asm fxch st(1) ; FV.Y | FV.Z
+ __asm fstp dword ptr [eax+FINALVERT_Y] ; FV.Z
+ __asm fstp dword ptr [eax+FINALVERT_Z] ; (empty)
+
+ /*
+ ** lighting
+ **
+ ** plightnormal = r_avertexnormals[newv->lightnormalindex];
+ ** lightcos = DotProduct (plightnormal, r_plightvec);
+ ** temp = r_ambientlight;
+ */
+ __asm xor ebx, ebx
+ __asm mov bl, byte ptr [edi+DTRIVERTX_LNI]
+ __asm mov eax, 12
+ __asm mul ebx
+ __asm lea eax, [r_avertexnormals+eax]
+ __asm lea ebx, r_plightvec
+
+ __asm fld dword ptr [eax+0]
+ __asm fmul dword ptr [ebx+0]
+ __asm fld dword ptr [eax+4]
+ __asm fmul dword ptr [ebx+4]
+ __asm fld dword ptr [eax+8]
+ __asm fmul dword ptr [ebx+8]
+ __asm fxch st(2)
+ __asm faddp st(1), st
+ __asm faddp st(1), st
+ __asm fstp dword ptr lightcos
+ __asm mov eax, lightcos
+ __asm mov ebx, r_ambientlight
+
+ /*
+ if (lightcos < 0)
+ {
+ temp += (int)(r_shadelight * lightcos);
+
+ // clamp; because we limited the minimum ambient and shading light, we
+ // don't have to clamp low light, just bright
+ if (temp < 0)
+ temp = 0;
+ }
+
+ fv->v[4] = temp;
+ */
+ __asm or eax, eax
+ __asm jns store_fv4
+
+ __asm fld dword ptr r_shadelight
+ __asm fmul dword ptr lightcos
+ __asm fistp dword ptr tmpint
+ __asm add ebx, tmpint
+
+ __asm or ebx, ebx
+ __asm jns store_fv4
+ __asm mov ebx, 0
+
+store_fv4:
+ __asm mov edi, fv
+ __asm mov dword ptr [edi+FINALVERT_V4], ebx
+
+ __asm mov edx, dword ptr [edi+FINALVERT_FLAGS]
+
+ /*
+ ** do clip testing and projection here
+ */
+ /*
+ if ( dest_vert->xyz[2] < ALIAS_Z_CLIP_PLANE )
+ {
+ dest_vert->flags |= ALIAS_Z_CLIP;
+ }
+ else
+ {
+ R_AliasProjectAndClipTestFinalVert( dest_vert );
+ }
+ */
+ __asm mov eax, dword ptr [edi+FINALVERT_Z]
+ __asm and eax, eax
+ __asm js alias_z_clip
+ __asm cmp eax, FALIAS_Z_CLIP_PLANE
+ __asm jl alias_z_clip
+
+ /*
+ This is the code to R_AliasProjectAndClipTestFinalVert
+
+ float zi;
+ float x, y, z;
+
+ x = fv->xyz[0];
+ y = fv->xyz[1];
+ z = fv->xyz[2];
+ zi = 1.0 / z;
+
+ fv->v[5] = zi * s_ziscale;
+
+ fv->v[0] = (x * aliasxscale * zi) + aliasxcenter;
+ fv->v[1] = (y * aliasyscale * zi) + aliasycenter;
+ */
+ __asm fld one ; 1
+ __asm fdiv dword ptr [edi+FINALVERT_Z] ; zi
+
+ __asm mov eax, dword ptr [edi+32]
+ __asm mov eax, dword ptr [edi+64]
+
+ __asm fst zi ; zi
+ __asm fmul s_ziscale ; fv5
+ __asm fld dword ptr [edi+FINALVERT_X] ; x | fv5
+ __asm fmul aliasxscale ; x * aliasxscale | fv5
+ __asm fld dword ptr [edi+FINALVERT_Y] ; y | x * aliasxscale | fv5
+ __asm fmul aliasyscale ; y * aliasyscale | x * aliasxscale | fv5
+ __asm fxch st(1) ; x * aliasxscale | y * aliasyscale | fv5
+ __asm fmul zi ; x * asx * zi | y * asy | fv5
+ __asm fadd aliasxcenter ; fv0 | y * asy | fv5
+ __asm fxch st(1) ; y * asy | fv0 | fv5
+ __asm fmul zi ; y * asy * zi | fv0 | fv5
+ __asm fadd aliasycenter ; fv1 | fv0 | fv5
+ __asm fxch st(2) ; fv5 | fv0 | fv1
+ __asm fistp dword ptr [edi+FINALVERT_V5] ; fv0 | fv1
+ __asm fistp dword ptr [edi+FINALVERT_V0] ; fv1
+ __asm fistp dword ptr [edi+FINALVERT_V1] ; (empty)
+
+ /*
+ if (fv->v[0] < r_refdef.aliasvrect.x)
+ fv->flags |= ALIAS_LEFT_CLIP;
+ if (fv->v[1] < r_refdef.aliasvrect.y)
+ fv->flags |= ALIAS_TOP_CLIP;
+ if (fv->v[0] > r_refdef.aliasvrectright)
+ fv->flags |= ALIAS_RIGHT_CLIP;
+ if (fv->v[1] > r_refdef.aliasvrectbottom)
+ fv->flags |= ALIAS_BOTTOM_CLIP;
+ */
+ __asm mov eax, dword ptr [edi+FINALVERT_V0]
+ __asm mov ebx, dword ptr [edi+FINALVERT_V1]
+
+ __asm cmp eax, r_refdef.aliasvrect.x
+ __asm jge ct_alias_top
+ __asm or edx, ALIAS_LEFT_CLIP
+ct_alias_top:
+ __asm cmp ebx, r_refdef.aliasvrect.y
+ __asm jge ct_alias_right
+ __asm or edx, ALIAS_TOP_CLIP
+ct_alias_right:
+ __asm cmp eax, r_refdef.aliasvrectright
+ __asm jle ct_alias_bottom
+ __asm or edx, ALIAS_RIGHT_CLIP
+ct_alias_bottom:
+ __asm cmp ebx, r_refdef.aliasvrectbottom
+ __asm jle end_of_loop
+ __asm or edx, ALIAS_BOTTOM_CLIP
+
+ __asm jmp end_of_loop
+
+alias_z_clip:
+ __asm or edx, ALIAS_Z_CLIP
+
+end_of_loop:
+
+ __asm mov dword ptr [edi+FINALVERT_FLAGS], edx
+ __asm add oldv, DTRIVERTX_SIZE
+ __asm add newv, DTRIVERTX_SIZE
+ __asm add fv, FINALVERT_SIZE
+
+ __asm dec ecx
+ __asm jnz top_of_loop
+}
+#else
+void R_AliasTransformFinalVerts( int numpoints, finalvert_t *fv, dtrivertx_t *oldv, dtrivertx_t *newv )
+{
+ int i;
+
+ for ( i = 0; i < numpoints; i++, fv++, oldv++, newv++ )
+ {
+ int temp;
+ float lightcos, *plightnormal;
+ vec3_t lerped_vert;
+
+ lerped_vert[0] = r_lerp_move[0] + oldv->v[0]*r_lerp_backv[0] + newv->v[0]*r_lerp_frontv[0];
+ lerped_vert[1] = r_lerp_move[1] + oldv->v[1]*r_lerp_backv[1] + newv->v[1]*r_lerp_frontv[1];
+ lerped_vert[2] = r_lerp_move[2] + oldv->v[2]*r_lerp_backv[2] + newv->v[2]*r_lerp_frontv[2];
+
+ plightnormal = r_avertexnormals[newv->lightnormalindex];
+
+ // PMM - added double damage shell
+ if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
+ {
+ lerped_vert[0] += plightnormal[0] * POWERSUIT_SCALE;
+ lerped_vert[1] += plightnormal[1] * POWERSUIT_SCALE;
+ lerped_vert[2] += plightnormal[2] * POWERSUIT_SCALE;
+ }
+
+ fv->xyz[0] = DotProduct(lerped_vert, aliastransform[0]) + aliastransform[0][3];
+ fv->xyz[1] = DotProduct(lerped_vert, aliastransform[1]) + aliastransform[1][3];
+ fv->xyz[2] = DotProduct(lerped_vert, aliastransform[2]) + aliastransform[2][3];
+
+ fv->flags = 0;
+
+ // lighting
+ lightcos = DotProduct (plightnormal, r_plightvec);
+ temp = r_ambientlight;
+
+ if (lightcos < 0)
+ {
+ temp += (int)(r_shadelight * lightcos);
+
+ // clamp; because we limited the minimum ambient and shading light, we
+ // don't have to clamp low light, just bright
+ if (temp < 0)
+ temp = 0;
+ }
+
+ fv->l = temp;
+
+ if ( fv->xyz[2] < ALIAS_Z_CLIP_PLANE )
+ {
+ fv->flags |= ALIAS_Z_CLIP;
+ }
+ else
+ {
+ R_AliasProjectAndClipTestFinalVert( fv );
+ }
+ }
+}
+
+#endif
+
+/*
+================
+R_AliasProjectAndClipTestFinalVert
+================
+*/
+void R_AliasProjectAndClipTestFinalVert( finalvert_t *fv )
+{
+ float zi;
+ float x, y, z;
+
+ // project points
+ x = fv->xyz[0];
+ y = fv->xyz[1];
+ z = fv->xyz[2];
+ zi = 1.0 / z;
+
+ fv->zi = zi * s_ziscale;
+
+ fv->u = (x * aliasxscale * zi) + aliasxcenter;
+ fv->v = (y * aliasyscale * zi) + aliasycenter;
+
+ if (fv->u < r_refdef.aliasvrect.x)
+ fv->flags |= ALIAS_LEFT_CLIP;
+ if (fv->v < r_refdef.aliasvrect.y)
+ fv->flags |= ALIAS_TOP_CLIP;
+ if (fv->u > r_refdef.aliasvrectright)
+ fv->flags |= ALIAS_RIGHT_CLIP;
+ if (fv->v > r_refdef.aliasvrectbottom)
+ fv->flags |= ALIAS_BOTTOM_CLIP;
+}
+
+/*
+===============
+R_AliasSetupSkin
+===============
+*/
+static qboolean R_AliasSetupSkin (void)
+{
+ int skinnum;
+ image_t *pskindesc;
+
+ if (currententity->skin)
+ pskindesc = currententity->skin;
+ else
+ {
+ skinnum = currententity->skinnum;
+ if ((skinnum >= s_pmdl->num_skins) || (skinnum < 0))
+ {
+ ri.Con_Printf (PRINT_ALL, "R_AliasSetupSkin %s: no such skin # %d\n",
+ currentmodel->name, skinnum);
+ skinnum = 0;
+ }
+
+ pskindesc = currentmodel->skins[skinnum];
+ }
+
+ if ( !pskindesc )
+ return false;
+
+ r_affinetridesc.pskin = pskindesc->pixels[0];
+ r_affinetridesc.skinwidth = pskindesc->width;
+ r_affinetridesc.skinheight = pskindesc->height;
+
+ R_PolysetUpdateTables (); // FIXME: precalc edge lookups
+
+ return true;
+}
+
+
+/*
+================
+R_AliasSetupLighting
+
+ FIXME: put lighting into tables
+================
+*/
+void R_AliasSetupLighting (void)
+{
+ alight_t lighting;
+ float lightvec[3] = {-1, 0, 0};
+ vec3_t light;
+ int i, j;
+
+ // all components of light should be identical in software
+ if ( currententity->flags & RF_FULLBRIGHT )
+ {
+ for (i=0 ; i<3 ; i++)
+ light[i] = 1.0;
+ }
+ else
+ {
+ R_LightPoint (currententity->origin, light);
+ }
+
+ // save off light value for server to look at (BIG HACK!)
+ if ( currententity->flags & RF_WEAPONMODEL )
+ r_lightlevel->value = 150.0 * light[0];
+
+
+ if ( currententity->flags & RF_MINLIGHT )
+ {
+ for (i=0 ; i<3 ; i++)
+ if (light[i] < 0.1)
+ light[i] = 0.1;
+ }
+
+ if ( currententity->flags & RF_GLOW )
+ { // bonus items will pulse with time
+ float scale;
+ float min;
+
+ scale = 0.1 * sin(r_newrefdef.time*7);
+ for (i=0 ; i<3 ; i++)
+ {
+ min = light[i] * 0.8;
+ light[i] += scale;
+ if (light[i] < min)
+ light[i] = min;
+ }
+ }
+
+ j = (light[0] + light[1] + light[2])*0.3333*255;
+
+ lighting.ambientlight = j;
+ lighting.shadelight = j;
+
+ lighting.plightvec = lightvec;
+
+// clamp lighting so it doesn't overbright as much
+ if (lighting.ambientlight > 128)
+ lighting.ambientlight = 128;
+ if (lighting.ambientlight + lighting.shadelight > 192)
+ lighting.shadelight = 192 - lighting.ambientlight;
+
+// guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have
+// to clamp off the bottom
+ r_ambientlight = lighting.ambientlight;
+
+ if (r_ambientlight < LIGHT_MIN)
+ r_ambientlight = LIGHT_MIN;
+
+ r_ambientlight = (255 - r_ambientlight) << VID_CBITS;
+
+ if (r_ambientlight < LIGHT_MIN)
+ r_ambientlight = LIGHT_MIN;
+
+ r_shadelight = lighting.shadelight;
+
+ if (r_shadelight < 0)
+ r_shadelight = 0;
+
+ r_shadelight *= VID_GRADES;
+
+// rotate the lighting vector into the model's frame of reference
+ r_plightvec[0] = DotProduct( lighting.plightvec, s_alias_forward );
+ r_plightvec[1] = -DotProduct( lighting.plightvec, s_alias_right );
+ r_plightvec[2] = DotProduct( lighting.plightvec, s_alias_up );
+}
+
+
+/*
+=================
+R_AliasSetupFrames
+
+=================
+*/
+void R_AliasSetupFrames( dmdl_t *pmdl )
+{
+ int thisframe = currententity->frame;
+ int lastframe = currententity->oldframe;
+
+ if ( ( thisframe >= pmdl->num_frames ) || ( thisframe < 0 ) )
+ {
+ ri.Con_Printf (PRINT_ALL, "R_AliasSetupFrames %s: no such thisframe %d\n",
+ currentmodel->name, thisframe);
+ thisframe = 0;
+ }
+ if ( ( lastframe >= pmdl->num_frames ) || ( lastframe < 0 ) )
+ {
+ ri.Con_Printf (PRINT_ALL, "R_AliasSetupFrames %s: no such lastframe %d\n",
+ currentmodel->name, lastframe);
+ lastframe = 0;
+ }
+
+ r_thisframe = (daliasframe_t *)((byte *)pmdl + pmdl->ofs_frames
+ + thisframe * pmdl->framesize);
+
+ r_lastframe = (daliasframe_t *)((byte *)pmdl + pmdl->ofs_frames
+ + lastframe * pmdl->framesize);
+}
+
+/*
+** R_AliasSetUpLerpData
+**
+** Precomputes lerp coefficients used for the whole frame.
+*/
+void R_AliasSetUpLerpData( dmdl_t *pmdl, float backlerp )
+{
+ float frontlerp;
+ vec3_t translation, vectors[3];
+ int i;
+
+ frontlerp = 1.0F - backlerp;
+
+ /*
+ ** convert entity's angles into discrete vectors for R, U, and F
+ */
+ AngleVectors (currententity->angles, vectors[0], vectors[1], vectors[2]);
+
+ /*
+ ** translation is the vector from last position to this position
+ */
+ VectorSubtract (currententity->oldorigin, currententity->origin, translation);
+
+ /*
+ ** move should be the delta back to the previous frame * backlerp
+ */
+ r_lerp_move[0] = DotProduct(translation, vectors[0]); // forward
+ r_lerp_move[1] = -DotProduct(translation, vectors[1]); // left
+ r_lerp_move[2] = DotProduct(translation, vectors[2]); // up
+
+ VectorAdd( r_lerp_move, r_lastframe->translate, r_lerp_move );
+
+ for (i=0 ; i<3 ; i++)
+ {
+ r_lerp_move[i] = backlerp*r_lerp_move[i] + frontlerp * r_thisframe->translate[i];
+ }
+
+ for (i=0 ; i<3 ; i++)
+ {
+ r_lerp_frontv[i] = frontlerp * r_thisframe->scale[i];
+ r_lerp_backv[i] = backlerp * r_lastframe->scale[i];
+ }
+}
+
+/*
+================
+R_AliasDrawModel
+================
+*/
+void R_AliasDrawModel (void)
+{
+ extern void (*d_pdrawspans)(void *);
+ extern void R_PolysetDrawSpans8_Opaque( void * );
+ extern void R_PolysetDrawSpans8_33( void * );
+ extern void R_PolysetDrawSpans8_66( void * );
+ extern void R_PolysetDrawSpansConstant8_33( void * );
+ extern void R_PolysetDrawSpansConstant8_66( void * );
+
+ s_pmdl = (dmdl_t *)currentmodel->extradata;
+
+ if ( r_lerpmodels->value == 0 )
+ currententity->backlerp = 0;
+
+ if ( currententity->flags & RF_WEAPONMODEL )
+ {
+ if ( r_lefthand->value == 1.0F )
+ aliasxscale = -aliasxscale;
+ else if ( r_lefthand->value == 2.0F )
+ return;
+ }
+
+ /*
+ ** we have to set our frame pointers and transformations before
+ ** doing any real work
+ */
+ R_AliasSetupFrames( s_pmdl );
+ R_AliasSetUpTransform();
+
+ // see if the bounding box lets us trivially reject, also sets
+ // trivial accept status
+ if ( R_AliasCheckBBox() == BBOX_TRIVIAL_REJECT )
+ {
+ if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
+ {
+ aliasxscale = -aliasxscale;
+ }
+ return;
+ }
+
+ // set up the skin and verify it exists
+ if ( !R_AliasSetupSkin () )
+ {
+ ri.Con_Printf( PRINT_ALL, "R_AliasDrawModel %s: NULL skin found\n",
+ currentmodel->name);
+ return;
+ }
+
+ r_amodels_drawn++;
+ R_AliasSetupLighting ();
+
+ /*
+ ** select the proper span routine based on translucency
+ */
+ // PMM - added double damage shell
+ // PMM - reordered to handle blending
+ if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
+ {
+ int color;
+
+ // PMM - added double
+ color = currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM);
+ // PMM - reordered, old code first
+/*
+ if ( color == RF_SHELL_RED )
+ r_aliasblendcolor = SHELL_RED_COLOR;
+ else if ( color == RF_SHELL_GREEN )
+ r_aliasblendcolor = SHELL_GREEN_COLOR;
+ else if ( color == RF_SHELL_BLUE )
+ r_aliasblendcolor = SHELL_BLUE_COLOR;
+ else if ( color == (RF_SHELL_RED | RF_SHELL_GREEN) )
+ r_aliasblendcolor = SHELL_RG_COLOR;
+ else if ( color == (RF_SHELL_RED | RF_SHELL_BLUE) )
+ r_aliasblendcolor = SHELL_RB_COLOR;
+ else if ( color == (RF_SHELL_BLUE | RF_SHELL_GREEN) )
+ r_aliasblendcolor = SHELL_BG_COLOR;
+ // PMM - added this .. it's yellowish
+ else if ( color == (RF_SHELL_DOUBLE) )
+ r_aliasblendcolor = SHELL_DOUBLE_COLOR;
+ else if ( color == (RF_SHELL_HALF_DAM) )
+ r_aliasblendcolor = SHELL_HALF_DAM_COLOR;
+ // pmm
+ else
+ r_aliasblendcolor = SHELL_WHITE_COLOR;
+*/
+ if ( color & RF_SHELL_RED )
+ {
+ if ( ( color & RF_SHELL_BLUE) && ( color & RF_SHELL_GREEN) )
+ r_aliasblendcolor = SHELL_WHITE_COLOR;
+ else if ( color & (RF_SHELL_BLUE | RF_SHELL_DOUBLE))
+ r_aliasblendcolor = SHELL_RB_COLOR;
+ else
+ r_aliasblendcolor = SHELL_RED_COLOR;
+ }
+ else if ( color & RF_SHELL_BLUE)
+ {
+ if ( color & RF_SHELL_DOUBLE )
+ r_aliasblendcolor = SHELL_CYAN_COLOR;
+ else
+ r_aliasblendcolor = SHELL_BLUE_COLOR;
+ }
+ else if ( color & (RF_SHELL_DOUBLE) )
+ r_aliasblendcolor = SHELL_DOUBLE_COLOR;
+ else if ( color & (RF_SHELL_HALF_DAM) )
+ r_aliasblendcolor = SHELL_HALF_DAM_COLOR;
+ else if ( color & RF_SHELL_GREEN )
+ r_aliasblendcolor = SHELL_GREEN_COLOR;
+ else
+ r_aliasblendcolor = SHELL_WHITE_COLOR;
+
+
+ if ( currententity->alpha > 0.33 )
+ d_pdrawspans = R_PolysetDrawSpansConstant8_66;
+ else
+ d_pdrawspans = R_PolysetDrawSpansConstant8_33;
+ }
+ else if ( currententity->flags & RF_TRANSLUCENT )
+ {
+ if ( currententity->alpha > 0.66 )
+ d_pdrawspans = R_PolysetDrawSpans8_Opaque;
+ else if ( currententity->alpha > 0.33 )
+ d_pdrawspans = R_PolysetDrawSpans8_66;
+ else
+ d_pdrawspans = R_PolysetDrawSpans8_33;
+ }
+ else
+ {
+ d_pdrawspans = R_PolysetDrawSpans8_Opaque;
+ }
+
+ /*
+ ** compute this_frame and old_frame addresses
+ */
+ R_AliasSetUpLerpData( s_pmdl, currententity->backlerp );
+
+ if (currententity->flags & RF_DEPTHHACK)
+ s_ziscale = (float)0x8000 * (float)0x10000 * 3.0;
+ else
+ s_ziscale = (float)0x8000 * (float)0x10000;
+
+ R_AliasPreparePoints ();
+
+ if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
+ {
+ aliasxscale = -aliasxscale;
+ }
+}
+
+
+
--- /dev/null
+++ b/ref/r_bsp.c
@@ -1,0 +1,637 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// r_bsp.c
+
+#include "r_local.h"
+
+//
+// current entity info
+//
+qboolean insubmodel;
+entity_t *currententity;
+vec3_t modelorg; // modelorg is the viewpoint reletive to
+ // the currently rendering entity
+vec3_t r_entorigin; // the currently rendering entity in world
+ // coordinates
+
+float entity_rotation[3][3];
+
+int r_currentbkey;
+
+typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t;
+
+#define MAX_BMODEL_VERTS 500 // 6K
+#define MAX_BMODEL_EDGES 1000 // 12K
+
+static mvertex_t *pbverts;
+static bedge_t *pbedges;
+static int numbverts, numbedges;
+
+static mvertex_t *pfrontenter, *pfrontexit;
+
+static qboolean makeclippededge;
+
+
+//===========================================================================
+
+/*
+================
+R_EntityRotate
+================
+*/
+void R_EntityRotate (vec3_t vec)
+{
+ vec3_t tvec;
+
+ VectorCopy (vec, tvec);
+ vec[0] = DotProduct (entity_rotation[0], tvec);
+ vec[1] = DotProduct (entity_rotation[1], tvec);
+ vec[2] = DotProduct (entity_rotation[2], tvec);
+}
+
+
+/*
+================
+R_RotateBmodel
+================
+*/
+void R_RotateBmodel (void)
+{
+ float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
+
+// TODO: should use a look-up table
+// TODO: should really be stored with the entity instead of being reconstructed
+// TODO: could cache lazily, stored in the entity
+// TODO: share work with R_SetUpAliasTransform
+
+// yaw
+ angle = currententity->angles[YAW];
+ angle = angle * M_PI*2 / 360;
+ s = sin(angle);
+ c = cos(angle);
+
+ temp1[0][0] = c;
+ temp1[0][1] = s;
+ temp1[0][2] = 0;
+ temp1[1][0] = -s;
+ temp1[1][1] = c;
+ temp1[1][2] = 0;
+ temp1[2][0] = 0;
+ temp1[2][1] = 0;
+ temp1[2][2] = 1;
+
+
+// pitch
+ angle = currententity->angles[PITCH];
+ angle = angle * M_PI*2 / 360;
+ s = sin(angle);
+ c = cos(angle);
+
+ temp2[0][0] = c;
+ temp2[0][1] = 0;
+ temp2[0][2] = -s;
+ temp2[1][0] = 0;
+ temp2[1][1] = 1;
+ temp2[1][2] = 0;
+ temp2[2][0] = s;
+ temp2[2][1] = 0;
+ temp2[2][2] = c;
+
+ R_ConcatRotations (temp2, temp1, temp3);
+
+// roll
+ angle = currententity->angles[ROLL];
+ angle = angle * M_PI*2 / 360;
+ s = sin(angle);
+ c = cos(angle);
+
+ temp1[0][0] = 1;
+ temp1[0][1] = 0;
+ temp1[0][2] = 0;
+ temp1[1][0] = 0;
+ temp1[1][1] = c;
+ temp1[1][2] = s;
+ temp1[2][0] = 0;
+ temp1[2][1] = -s;
+ temp1[2][2] = c;
+
+ R_ConcatRotations (temp1, temp3, entity_rotation);
+
+//
+// rotate modelorg and the transformation matrix
+//
+ R_EntityRotate (modelorg);
+ R_EntityRotate (vpn);
+ R_EntityRotate (vright);
+ R_EntityRotate (vup);
+
+ R_TransformFrustum ();
+}
+
+
+/*
+================
+R_RecursiveClipBPoly
+
+Clip a bmodel poly down the world bsp tree
+================
+*/
+void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf)
+{
+ bedge_t *psideedges[2], *pnextedge, *ptedge;
+ int i, side, lastside;
+ float dist, frac, lastdist;
+ mplane_t *splitplane, tplane;
+ mvertex_t *pvert, *plastvert, *ptvert;
+ mnode_t *pn;
+ int area;
+
+ psideedges[0] = psideedges[1] = NULL;
+
+ makeclippededge = false;
+
+// transform the BSP plane into model space
+// FIXME: cache these?
+ splitplane = pnode->plane;
+ tplane.dist = splitplane->dist -
+ DotProduct(r_entorigin, splitplane->normal);
+ tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal);
+ tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal);
+ tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal);
+
+// clip edges to BSP plane
+ for ( ; pedges ; pedges = pnextedge)
+ {
+ pnextedge = pedges->pnext;
+
+ // set the status for the last point as the previous point
+ // FIXME: cache this stuff somehow?
+ plastvert = pedges->v[0];
+ lastdist = DotProduct (plastvert->position, tplane.normal) -
+ tplane.dist;
+
+ if (lastdist > 0)
+ lastside = 0;
+ else
+ lastside = 1;
+
+ pvert = pedges->v[1];
+
+ dist = DotProduct (pvert->position, tplane.normal) - tplane.dist;
+
+ if (dist > 0)
+ side = 0;
+ else
+ side = 1;
+
+ if (side != lastside)
+ {
+ // clipped
+ if (numbverts >= MAX_BMODEL_VERTS)
+ return;
+
+ // generate the clipped vertex
+ frac = lastdist / (lastdist - dist);
+ ptvert = &pbverts[numbverts++];
+ ptvert->position[0] = plastvert->position[0] +
+ frac * (pvert->position[0] -
+ plastvert->position[0]);
+ ptvert->position[1] = plastvert->position[1] +
+ frac * (pvert->position[1] -
+ plastvert->position[1]);
+ ptvert->position[2] = plastvert->position[2] +
+ frac * (pvert->position[2] -
+ plastvert->position[2]);
+
+ // split into two edges, one on each side, and remember entering
+ // and exiting points
+ // FIXME: share the clip edge by having a winding direction flag?
+ if (numbedges >= (MAX_BMODEL_EDGES - 1))
+ {
+ ri.Con_Printf (PRINT_ALL,"Out of edges for bmodel\n");
+ return;
+ }
+
+ ptedge = &pbedges[numbedges];
+ ptedge->pnext = psideedges[lastside];
+ psideedges[lastside] = ptedge;
+ ptedge->v[0] = plastvert;
+ ptedge->v[1] = ptvert;
+
+ ptedge = &pbedges[numbedges + 1];
+ ptedge->pnext = psideedges[side];
+ psideedges[side] = ptedge;
+ ptedge->v[0] = ptvert;
+ ptedge->v[1] = pvert;
+
+ numbedges += 2;
+
+ if (side == 0)
+ {
+ // entering for front, exiting for back
+ pfrontenter = ptvert;
+ makeclippededge = true;
+ }
+ else
+ {
+ pfrontexit = ptvert;
+ makeclippededge = true;
+ }
+ }
+ else
+ {
+ // add the edge to the appropriate side
+ pedges->pnext = psideedges[side];
+ psideedges[side] = pedges;
+ }
+ }
+
+// if anything was clipped, reconstitute and add the edges along the clip
+// plane to both sides (but in opposite directions)
+ if (makeclippededge)
+ {
+ if (numbedges >= (MAX_BMODEL_EDGES - 2))
+ {
+ ri.Con_Printf (PRINT_ALL,"Out of edges for bmodel\n");
+ return;
+ }
+
+ ptedge = &pbedges[numbedges];
+ ptedge->pnext = psideedges[0];
+ psideedges[0] = ptedge;
+ ptedge->v[0] = pfrontexit;
+ ptedge->v[1] = pfrontenter;
+
+ ptedge = &pbedges[numbedges + 1];
+ ptedge->pnext = psideedges[1];
+ psideedges[1] = ptedge;
+ ptedge->v[0] = pfrontenter;
+ ptedge->v[1] = pfrontexit;
+
+ numbedges += 2;
+ }
+
+// draw or recurse further
+ for (i=0 ; i<2 ; i++)
+ {
+ if (psideedges[i])
+ {
+ // draw if we've reached a non-solid leaf, done if all that's left is a
+ // solid leaf, and continue down the tree if it's not a leaf
+ pn = pnode->children[i];
+
+ // we're done with this branch if the node or leaf isn't in the PVS
+ if (pn->visframe == r_visframecount)
+ {
+ if (pn->contents != CONTENTS_NODE)
+ {
+ if (pn->contents != CONTENTS_SOLID)
+ {
+ if (r_newrefdef.areabits)
+ {
+ area = ((mleaf_t *)pn)->area;
+ if (! (r_newrefdef.areabits[area>>3] & (1<<(area&7)) ) )
+ continue; // not visible
+ }
+
+ r_currentbkey = ((mleaf_t *)pn)->key;
+ R_RenderBmodelFace (psideedges[i], psurf);
+ }
+ }
+ else
+ {
+ R_RecursiveClipBPoly (psideedges[i], pnode->children[i],
+ psurf);
+ }
+ }
+ }
+ }
+}
+
+
+/*
+================
+R_DrawSolidClippedSubmodelPolygons
+
+Bmodel crosses multiple leafs
+================
+*/
+void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode)
+{
+ int i, j, lindex;
+ vec_t dot;
+ msurface_t *psurf;
+ int numsurfaces;
+ mplane_t *pplane;
+ mvertex_t bverts[MAX_BMODEL_VERTS];
+ bedge_t bedges[MAX_BMODEL_EDGES], *pbedge;
+ medge_t *pedge, *pedges;
+
+// FIXME: use bounding-box-based frustum clipping info?
+
+ psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
+ numsurfaces = pmodel->nummodelsurfaces;
+ pedges = pmodel->edges;
+
+ for (i=0 ; i<numsurfaces ; i++, psurf++)
+ {
+ // find which side of the node we are on
+ pplane = psurf->plane;
+
+ dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
+
+ // draw the polygon
+ if (( !(psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
+ ((psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
+ continue;
+
+ // FIXME: use bounding-box-based frustum clipping info?
+
+ // copy the edges to bedges, flipping if necessary so always
+ // clockwise winding
+ // FIXME: if edges and vertices get caches, these assignments must move
+ // outside the loop, and overflow checking must be done here
+ pbverts = bverts;
+ pbedges = bedges;
+ numbverts = numbedges = 0;
+ pbedge = &bedges[numbedges];
+ numbedges += psurf->numedges;
+
+ for (j=0 ; j<psurf->numedges ; j++)
+ {
+ lindex = pmodel->surfedges[psurf->firstedge+j];
+
+ if (lindex > 0)
+ {
+ pedge = &pedges[lindex];
+ pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]];
+ pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]];
+ }
+ else
+ {
+ lindex = -lindex;
+ pedge = &pedges[lindex];
+ pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]];
+ pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]];
+ }
+
+ pbedge[j].pnext = &pbedge[j+1];
+ }
+
+ pbedge[j-1].pnext = NULL; // mark end of edges
+
+ if ( !( psurf->texinfo->flags & ( SURF_TRANS66 | SURF_TRANS33 ) ) )
+ R_RecursiveClipBPoly (pbedge, topnode, psurf);
+ else
+ R_RenderBmodelFace( pbedge, psurf );
+ }
+}
+
+
+/*
+================
+R_DrawSubmodelPolygons
+
+All in one leaf
+================
+*/
+void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode)
+{
+ int i;
+ vec_t dot;
+ msurface_t *psurf;
+ int numsurfaces;
+ mplane_t *pplane;
+
+// FIXME: use bounding-box-based frustum clipping info?
+
+ psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
+ numsurfaces = pmodel->nummodelsurfaces;
+
+ for (i=0 ; i<numsurfaces ; i++, psurf++)
+ {
+ // find which side of the node we are on
+ pplane = psurf->plane;
+
+ dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
+
+ // draw the polygon
+ if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
+ (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
+ {
+ r_currentkey = ((mleaf_t *)topnode)->key;
+
+ // FIXME: use bounding-box-based frustum clipping info?
+ R_RenderFace (psurf, clipflags);
+ }
+ }
+}
+
+
+int c_drawnode;
+
+/*
+================
+R_RecursiveWorldNode
+================
+*/
+void R_RecursiveWorldNode (mnode_t *node, int clipflags)
+{
+ int i, c, side, *pindex;
+ vec3_t acceptpt, rejectpt;
+ mplane_t *plane;
+ msurface_t *surf, **mark;
+ float d, dot;
+ mleaf_t *pleaf;
+
+ if (node->contents == CONTENTS_SOLID)
+ return; // solid
+
+ if (node->visframe != r_visframecount)
+ return;
+
+// cull the clipping planes if not trivial accept
+// FIXME: the compiler is doing a lousy job of optimizing here; it could be
+// twice as fast in ASM
+ if (clipflags)
+ {
+ for (i=0 ; i<4 ; i++)
+ {
+ if (! (clipflags & (1<<i)) )
+ continue; // don't need to clip against it
+
+ // generate accept and reject points
+ // FIXME: do with fast look-ups or integer tests based on the sign bit
+ // of the floating point values
+
+ pindex = pfrustum_indexes[i];
+
+ rejectpt[0] = (float)node->minmaxs[pindex[0]];
+ rejectpt[1] = (float)node->minmaxs[pindex[1]];
+ rejectpt[2] = (float)node->minmaxs[pindex[2]];
+
+ d = DotProduct (rejectpt, view_clipplanes[i].normal);
+ d -= view_clipplanes[i].dist;
+ if (d <= 0)
+ return;
+ acceptpt[0] = (float)node->minmaxs[pindex[3+0]];
+ acceptpt[1] = (float)node->minmaxs[pindex[3+1]];
+ acceptpt[2] = (float)node->minmaxs[pindex[3+2]];
+
+ d = DotProduct (acceptpt, view_clipplanes[i].normal);
+ d -= view_clipplanes[i].dist;
+
+ if (d >= 0)
+ clipflags &= ~(1<<i); // node is entirely on screen
+ }
+ }
+
+c_drawnode++;
+
+// if a leaf node, draw stuff
+ if (node->contents != -1)
+ {
+ pleaf = (mleaf_t *)node;
+
+ // check for door connected areas
+ if (r_newrefdef.areabits)
+ {
+ if (! (r_newrefdef.areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) )
+ return; // not visible
+ }
+
+ mark = pleaf->firstmarksurface;
+ c = pleaf->nummarksurfaces;
+
+ if (c)
+ {
+ do
+ {
+ (*mark)->visframe = r_framecount;
+ mark++;
+ } while (--c);
+ }
+
+ pleaf->key = r_currentkey;
+ r_currentkey++; // all bmodels in a leaf share the same key
+ }
+ else
+ {
+ // node is just a decision point, so go down the apropriate sides
+
+ // find which side of the node we are on
+ plane = node->plane;
+
+ switch (plane->type)
+ {
+ case PLANE_X:
+ dot = modelorg[0] - plane->dist;
+ break;
+ case PLANE_Y:
+ dot = modelorg[1] - plane->dist;
+ break;
+ case PLANE_Z:
+ dot = modelorg[2] - plane->dist;
+ break;
+ default:
+ dot = DotProduct (modelorg, plane->normal) - plane->dist;
+ break;
+ }
+
+ if (dot >= 0)
+ side = 0;
+ else
+ side = 1;
+
+ // recurse down the children, front side first
+ R_RecursiveWorldNode (node->children[side], clipflags);
+
+ // draw stuff
+ c = node->numsurfaces;
+
+ if (c)
+ {
+ surf = r_worldmodel->surfaces + node->firstsurface;
+
+ if (dot < -BACKFACE_EPSILON)
+ {
+ do
+ {
+ if ((surf->flags & SURF_PLANEBACK) &&
+ (surf->visframe == r_framecount))
+ {
+ R_RenderFace (surf, clipflags);
+ }
+
+ surf++;
+ } while (--c);
+ }
+ else if (dot > BACKFACE_EPSILON)
+ {
+ do
+ {
+ if (!(surf->flags & SURF_PLANEBACK) &&
+ (surf->visframe == r_framecount))
+ {
+ R_RenderFace (surf, clipflags);
+ }
+
+ surf++;
+ } while (--c);
+ }
+
+ // all surfaces on the same node share the same sequence number
+ r_currentkey++;
+ }
+
+ // recurse down the back side
+ R_RecursiveWorldNode (node->children[!side], clipflags);
+ }
+}
+
+
+
+/*
+================
+R_RenderWorld
+================
+*/
+void R_RenderWorld (void)
+{
+
+ if (!r_drawworld->value)
+ return;
+ if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
+ return;
+
+ c_drawnode=0;
+
+ // auto cycle the world frame for texture animation
+ r_worldentity.frame = (int)(r_newrefdef.time*2);
+ currententity = &r_worldentity;
+
+ VectorCopy (r_origin, modelorg);
+ currentmodel = r_worldmodel;
+ r_pcurrentvertbase = currentmodel->vertexes;
+
+ R_RecursiveWorldNode (currentmodel->nodes, 15);
+}
+
+
--- /dev/null
+++ b/ref/r_draw.c
@@ -1,0 +1,445 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+// draw.c
+
+#include "r_local.h"
+
+
+image_t *draw_chars; // 8*8 graphic characters
+
+//=============================================================================
+
+/*
+================
+Draw_FindPic
+================
+*/
+image_t *Draw_FindPic (char *name)
+{
+ image_t *image;
+ char fullname[MAX_QPATH];
+
+ if (name[0] != '/' && name[0] != '\\')
+ {
+ Com_sprintf (fullname, sizeof(fullname), "pics/%s.pcx", name);
+ image = R_FindImage (fullname, it_pic);
+ }
+ else
+ image = R_FindImage (name+1, it_pic);
+
+ return image;
+}
+
+
+
+/*
+===============
+Draw_InitLocal
+===============
+*/
+void Draw_InitLocal (void)
+{
+ draw_chars = Draw_FindPic ("conchars");
+}
+
+
+
+/*
+================
+Draw_Char
+
+Draws one 8*8 graphics character
+It can be clipped to the top of the screen to allow the console to be
+smoothly scrolled off.
+================
+*/
+void Draw_Char (int x, int y, int num)
+{
+ byte *dest;
+ byte *source;
+ int drawline;
+ int row, col;
+
+ num &= 255;
+
+ if (num == 32 || num == 32+128)
+ return;
+
+ if (y <= -8)
+ return; // totally off screen
+
+// if ( ( y + 8 ) >= vid.height )
+ if ( ( y + 8 ) > vid.height ) // PGM - status text was missing in sw...
+ return;
+
+#ifdef PARANOID
+ if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
+ ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: (%i, %i)", x, y);
+ if (num < 0 || num > 255)
+ ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: char %i", num);
+#endif
+
+ row = num>>4;
+ col = num&15;
+ source = draw_chars->pixels[0] + (row<<10) + (col<<3);
+
+ if (y < 0)
+ { // clipped
+ drawline = 8 + y;
+ source -= 128*y;
+ y = 0;
+ }
+ else
+ drawline = 8;
+
+
+ dest = vid.buffer + y*vid.rowbytes + x;
+
+ while (drawline--)
+ {
+ if (source[0] != TRANSPARENT_COLOR)
+ dest[0] = source[0];
+ if (source[1] != TRANSPARENT_COLOR)
+ dest[1] = source[1];
+ if (source[2] != TRANSPARENT_COLOR)
+ dest[2] = source[2];
+ if (source[3] != TRANSPARENT_COLOR)
+ dest[3] = source[3];
+ if (source[4] != TRANSPARENT_COLOR)
+ dest[4] = source[4];
+ if (source[5] != TRANSPARENT_COLOR)
+ dest[5] = source[5];
+ if (source[6] != TRANSPARENT_COLOR)
+ dest[6] = source[6];
+ if (source[7] != TRANSPARENT_COLOR)
+ dest[7] = source[7];
+ source += 128;
+ dest += vid.rowbytes;
+ }
+}
+
+/*
+=============
+Draw_GetPicSize
+=============
+*/
+void Draw_GetPicSize (int *w, int *h, char *pic)
+{
+ image_t *gl;
+
+ gl = Draw_FindPic (pic);
+ if (!gl)
+ {
+ *w = *h = -1;
+ return;
+ }
+ *w = gl->width;
+ *h = gl->height;
+}
+
+/*
+=============
+Draw_StretchPicImplementation
+=============
+*/
+void Draw_StretchPicImplementation (int x, int y, int w, int h, image_t *pic)
+{
+ byte *dest, *source;
+ int v, u, sv;
+ int height;
+ int f, fstep;
+ int skip;
+
+ if ((x < 0) ||
+ (x + w > vid.width) ||
+ (y + h > vid.height))
+ {
+ ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");
+ }
+
+ height = h;
+ if (y < 0)
+ {
+ skip = -y;
+ height += y;
+ y = 0;
+ }
+ else
+ skip = 0;
+
+ dest = vid.buffer + y * vid.rowbytes + x;
+
+ for (v=0 ; v<height ; v++, dest += vid.rowbytes)
+ {
+ sv = (skip + v)*pic->height/h;
+ source = pic->pixels[0] + sv*pic->width;
+ if (w == pic->width)
+ memcpy (dest, source, w);
+ else
+ {
+ f = 0;
+ fstep = pic->width*0x10000/w;
+ for (u=0 ; u<w ; u+=4)
+ {
+ dest[u] = source[f>>16];
+ f += fstep;
+ dest[u+1] = source[f>>16];
+ f += fstep;
+ dest[u+2] = source[f>>16];
+ f += fstep;
+ dest[u+3] = source[f>>16];
+ f += fstep;
+ }
+ }
+ }
+}
+
+/*
+=============
+Draw_StretchPic
+=============
+*/
+void Draw_StretchPic (int x, int y, int w, int h, char *name)
+{
+ image_t *pic;
+
+ pic = Draw_FindPic (name);
+ if (!pic)
+ {
+ ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
+ return;
+ }
+ Draw_StretchPicImplementation (x, y, w, h, pic);
+}
+
+/*
+=============
+Draw_StretchRaw
+=============
+*/
+void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
+{
+ image_t pic;
+
+ pic.pixels[0] = data;
+ pic.width = cols;
+ pic.height = rows;
+ Draw_StretchPicImplementation (x, y, w, h, &pic);
+}
+
+/*
+=============
+Draw_Pic
+=============
+*/
+void Draw_Pic (int x, int y, char *name)
+{
+ image_t *pic;
+ byte *dest, *source;
+ int v, u;
+ int tbyte;
+ int height;
+
+ pic = Draw_FindPic (name);
+ if (!pic)
+ {
+ ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
+ return;
+ }
+
+ if ((x < 0) ||
+ (x + pic->width > vid.width) ||
+ (y + pic->height > vid.height))
+ return; // ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");
+
+ height = pic->height;
+ source = pic->pixels[0];
+ if (y < 0)
+ {
+ height += y;
+ source += pic->width*-y;
+ y = 0;
+ }
+
+ dest = vid.buffer + y * vid.rowbytes + x;
+
+ if (!pic->transparent)
+ {
+ for (v=0 ; v<height ; v++)
+ {
+ memcpy (dest, source, pic->width);
+ dest += vid.rowbytes;
+ source += pic->width;
+ }
+ }
+ else
+ {
+ if (pic->width & 7)
+ { // general
+ for (v=0 ; v<height ; v++)
+ {
+ for (u=0 ; u<pic->width ; u++)
+ if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
+ dest[u] = tbyte;
+
+ dest += vid.rowbytes;
+ source += pic->width;
+ }
+ }
+ else
+ { // unwound
+ for (v=0 ; v<height ; v++)
+ {
+ for (u=0 ; u<pic->width ; u+=8)
+ {
+ if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
+ dest[u] = tbyte;
+ if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
+ dest[u+1] = tbyte;
+ if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
+ dest[u+2] = tbyte;
+ if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
+ dest[u+3] = tbyte;
+ if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
+ dest[u+4] = tbyte;
+ if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
+ dest[u+5] = tbyte;
+ if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
+ dest[u+6] = tbyte;
+ if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
+ dest[u+7] = tbyte;
+ }
+ dest += vid.rowbytes;
+ source += pic->width;
+ }
+ }
+ }
+}
+
+/*
+=============
+Draw_TileClear
+
+This repeats a 64*64 tile graphic to fill the screen around a sized down
+refresh window.
+=============
+*/
+void Draw_TileClear (int x, int y, int w, int h, char *name)
+{
+ int i, j;
+ byte *psrc;
+ byte *pdest;
+ image_t *pic;
+ int x2;
+
+ if (x < 0)
+ {
+ w += x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ h += y;
+ y = 0;
+ }
+ if (x + w > vid.width)
+ w = vid.width - x;
+ if (y + h > vid.height)
+ h = vid.height - y;
+ if (w <= 0 || h <= 0)
+ return;
+
+ pic = Draw_FindPic (name);
+ if (!pic)
+ {
+ ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
+ return;
+ }
+ x2 = x + w;
+ pdest = vid.buffer + y*vid.rowbytes;
+ for (i=0 ; i<h ; i++, pdest += vid.rowbytes)
+ {
+ psrc = pic->pixels[0] + pic->width * ((i+y)&63);
+ for (j=x ; j<x2 ; j++)
+ pdest[j] = psrc[j&63];
+ }
+}
+
+
+/*
+=============
+Draw_Fill
+
+Fills a box of pixels with a single color
+=============
+*/
+void Draw_Fill (int x, int y, int w, int h, int c)
+{
+ byte *dest;
+ int u, v;
+
+ if (x+w > vid.width)
+ w = vid.width - x;
+ if (y+h > vid.height)
+ h = vid.height - y;
+ if (x < 0)
+ {
+ w += x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ h += y;
+ y = 0;
+ }
+ if (w < 0 || h < 0)
+ return;
+ dest = vid.buffer + y*vid.rowbytes + x;
+ for (v=0 ; v<h ; v++, dest += vid.rowbytes)
+ for (u=0 ; u<w ; u++)
+ dest[u] = c;
+}
+//=============================================================================
+
+/*
+================
+Draw_FadeScreen
+
+================
+*/
+void Draw_FadeScreen (void)
+{
+ int x,y;
+ byte *pbuf;
+ int t;
+
+ for (y=0 ; y<vid.height ; y++)
+ {
+ pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
+ t = (y & 1) << 1;
+
+ for (x=0 ; x<vid.width ; x++)
+ {
+ if ((x & 3) != t)
+ pbuf[x] = 0;
+ }
+ }
+}
--- /dev/null
+++ b/ref/r_edge.c
@@ -1,0 +1,1125 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// r_edge.c
+
+#include "r_local.h"
+
+#ifndef id386
+void R_SurfacePatch (void)
+{
+}
+
+void R_EdgeCodeStart (void)
+{
+}
+
+void R_EdgeCodeEnd (void)
+{
+}
+#endif
+
+
+#if 0
+the complex cases add new polys on most lines, so dont optimize for keeping them the same
+have multiple free span lists to try to get better coherence?
+low depth complexity -- 1 to 3 or so
+
+have a sentinal at both ends?
+#endif
+
+
+edge_t *auxedges;
+edge_t *r_edges, *edge_p, *edge_max;
+
+surf_t *surfaces, *surface_p, *surf_max;
+
+// surfaces are generated in back to front order by the bsp, so if a surf
+// pointer is greater than another one, it should be drawn in front
+// surfaces[1] is the background, and is used as the active surface stack
+
+edge_t *newedges[MAXHEIGHT];
+edge_t *removeedges[MAXHEIGHT];
+
+espan_t *span_p, *max_span_p;
+
+int r_currentkey;
+
+int current_iv;
+
+int edge_head_u_shift20, edge_tail_u_shift20;
+
+static void (*pdrawfunc)(void);
+
+edge_t edge_head;
+edge_t edge_tail;
+edge_t edge_aftertail;
+edge_t edge_sentinel;
+
+float fv;
+
+static int miplevel;
+
+float scale_for_mip;
+int ubasestep, errorterm, erroradjustup, erroradjustdown;
+
+// FIXME: should go away
+extern void R_RotateBmodel (void);
+extern void R_TransformFrustum (void);
+
+
+
+void R_GenerateSpans (void);
+void R_GenerateSpansBackward (void);
+
+void R_LeadingEdge (edge_t *edge);
+void R_LeadingEdgeBackwards (edge_t *edge);
+void R_TrailingEdge (surf_t *surf, edge_t *edge);
+
+
+/*
+===============================================================================
+
+EDGE SCANNING
+
+===============================================================================
+*/
+
+/*
+==============
+R_BeginEdgeFrame
+==============
+*/
+void R_BeginEdgeFrame (void)
+{
+ int v;
+
+ edge_p = r_edges;
+ edge_max = &r_edges[r_numallocatededges];
+
+ surface_p = &surfaces[2]; // background is surface 1,
+ // surface 0 is a dummy
+ surfaces[1].spans = NULL; // no background spans yet
+ surfaces[1].flags = SURF_DRAWBACKGROUND;
+
+// put the background behind everything in the world
+ if (sw_draworder->value)
+ {
+ pdrawfunc = R_GenerateSpansBackward;
+ surfaces[1].key = 0;
+ r_currentkey = 1;
+ }
+ else
+ {
+ pdrawfunc = R_GenerateSpans;
+ surfaces[1].key = 0x7FFfFFFF;
+ r_currentkey = 0;
+ }
+
+// FIXME: set with memset
+ for (v=r_refdef.vrect.y ; v<r_refdef.vrectbottom ; v++)
+ {
+ newedges[v] = removeedges[v] = NULL;
+ }
+}
+
+
+#if !id386
+
+/*
+==============
+R_InsertNewEdges
+
+Adds the edges in the linked list edgestoadd, adding them to the edges in the
+linked list edgelist. edgestoadd is assumed to be sorted on u, and non-empty (this is actually newedges[v]). edgelist is assumed to be sorted on u, with a
+sentinel at the end (actually, this is the active edge table starting at
+edge_head.next).
+==============
+*/
+void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist)
+{
+ edge_t *next_edge;
+
+ do
+ {
+ next_edge = edgestoadd->next;
+edgesearch:
+ if (edgelist->u >= edgestoadd->u)
+ goto addedge;
+ edgelist=edgelist->next;
+ if (edgelist->u >= edgestoadd->u)
+ goto addedge;
+ edgelist=edgelist->next;
+ if (edgelist->u >= edgestoadd->u)
+ goto addedge;
+ edgelist=edgelist->next;
+ if (edgelist->u >= edgestoadd->u)
+ goto addedge;
+ edgelist=edgelist->next;
+ goto edgesearch;
+
+ // insert edgestoadd before edgelist
+addedge:
+ edgestoadd->next = edgelist;
+ edgestoadd->prev = edgelist->prev;
+ edgelist->prev->next = edgestoadd;
+ edgelist->prev = edgestoadd;
+ } while ((edgestoadd = next_edge) != NULL);
+}
+
+#endif // !id386
+
+
+#if !id386
+
+/*
+==============
+R_RemoveEdges
+==============
+*/
+void R_RemoveEdges (edge_t *pedge)
+{
+
+ do
+ {
+ pedge->next->prev = pedge->prev;
+ pedge->prev->next = pedge->next;
+ } while ((pedge = pedge->nextremove) != NULL);
+}
+
+#endif // !id386
+
+
+#if !id386
+
+/*
+==============
+R_StepActiveU
+==============
+*/
+void R_StepActiveU (edge_t *pedge)
+{
+ edge_t *pnext_edge, *pwedge;
+
+ while (1)
+ {
+nextedge:
+ pedge->u += pedge->u_step;
+ if (pedge->u < pedge->prev->u)
+ goto pushback;
+ pedge = pedge->next;
+
+ pedge->u += pedge->u_step;
+ if (pedge->u < pedge->prev->u)
+ goto pushback;
+ pedge = pedge->next;
+
+ pedge->u += pedge->u_step;
+ if (pedge->u < pedge->prev->u)
+ goto pushback;
+ pedge = pedge->next;
+
+ pedge->u += pedge->u_step;
+ if (pedge->u < pedge->prev->u)
+ goto pushback;
+ pedge = pedge->next;
+
+ goto nextedge;
+
+pushback:
+ if (pedge == &edge_aftertail)
+ return;
+
+ // push it back to keep it sorted
+ pnext_edge = pedge->next;
+
+ // pull the edge out of the edge list
+ pedge->next->prev = pedge->prev;
+ pedge->prev->next = pedge->next;
+
+ // find out where the edge goes in the edge list
+ pwedge = pedge->prev->prev;
+
+ while (pwedge->u > pedge->u)
+ {
+ pwedge = pwedge->prev;
+ }
+
+ // put the edge back into the edge list
+ pedge->next = pwedge->next;
+ pedge->prev = pwedge;
+ pedge->next->prev = pedge;
+ pwedge->next = pedge;
+
+ pedge = pnext_edge;
+ if (pedge == &edge_tail)
+ return;
+ }
+}
+
+#endif // !id386
+
+
+/*
+==============
+R_CleanupSpan
+==============
+*/
+void R_CleanupSpan (void)
+{
+ surf_t *surf;
+ int iu;
+ espan_t *span;
+
+// now that we've reached the right edge of the screen, we're done with any
+// unfinished surfaces, so emit a span for whatever's on top
+ surf = surfaces[1].next;
+ iu = edge_tail_u_shift20;
+ if (iu > surf->last_u)
+ {
+ span = span_p++;
+ span->u = surf->last_u;
+ span->count = iu - span->u;
+ span->v = current_iv;
+ span->pnext = surf->spans;
+ surf->spans = span;
+ }
+
+// reset spanstate for all surfaces in the surface stack
+ do
+ {
+ surf->spanstate = 0;
+ surf = surf->next;
+ } while (surf != &surfaces[1]);
+}
+
+
+/*
+==============
+R_LeadingEdgeBackwards
+==============
+*/
+void R_LeadingEdgeBackwards (edge_t *edge)
+{
+ espan_t *span;
+ surf_t *surf, *surf2;
+ int iu;
+
+// it's adding a new surface in, so find the correct place
+ surf = &surfaces[edge->surfs[1]];
+
+// don't start a span if this is an inverted span, with the end
+// edge preceding the start edge (that is, we've already seen the
+// end edge)
+ if (++surf->spanstate == 1)
+ {
+ surf2 = surfaces[1].next;
+
+ if (surf->key > surf2->key)
+ goto newtop;
+
+ // if it's two surfaces on the same plane, the one that's already
+ // active is in front, so keep going unless it's a bmodel
+ if (surf->insubmodel && (surf->key == surf2->key))
+ {
+ // must be two bmodels in the same leaf; don't care, because they'll
+ // never be farthest anyway
+ goto newtop;
+ }
+
+continue_search:
+
+ do
+ {
+ surf2 = surf2->next;
+ } while (surf->key < surf2->key);
+
+ if (surf->key == surf2->key)
+ {
+ // if it's two surfaces on the same plane, the one that's already
+ // active is in front, so keep going unless it's a bmodel
+ if (!surf->insubmodel)
+ goto continue_search;
+
+ // must be two bmodels in the same leaf; don't care which is really
+ // in front, because they'll never be farthest anyway
+ }
+
+ goto gotposition;
+
+newtop:
+ // emit a span (obscures current top)
+ iu = edge->u >> 20;
+
+ if (iu > surf2->last_u)
+ {
+ span = span_p++;
+ span->u = surf2->last_u;
+ span->count = iu - span->u;
+ span->v = current_iv;
+ span->pnext = surf2->spans;
+ surf2->spans = span;
+ }
+
+ // set last_u on the new span
+ surf->last_u = iu;
+
+gotposition:
+ // insert before surf2
+ surf->next = surf2;
+ surf->prev = surf2->prev;
+ surf2->prev->next = surf;
+ surf2->prev = surf;
+ }
+}
+
+
+/*
+==============
+R_TrailingEdge
+==============
+*/
+void R_TrailingEdge (surf_t *surf, edge_t *edge)
+{
+ espan_t *span;
+ int iu;
+
+// don't generate a span if this is an inverted span, with the end
+// edge preceding the start edge (that is, we haven't seen the
+// start edge yet)
+ if (--surf->spanstate == 0)
+ {
+ if (surf == surfaces[1].next)
+ {
+ // emit a span (current top going away)
+ iu = edge->u >> 20;
+ if (iu > surf->last_u)
+ {
+ span = span_p++;
+ span->u = surf->last_u;
+ span->count = iu - span->u;
+ span->v = current_iv;
+ span->pnext = surf->spans;
+ surf->spans = span;
+ }
+
+ // set last_u on the surface below
+ surf->next->last_u = iu;
+ }
+
+ surf->prev->next = surf->next;
+ surf->next->prev = surf->prev;
+ }
+}
+
+
+#if !id386
+
+/*
+==============
+R_LeadingEdge
+==============
+*/
+void R_LeadingEdge (edge_t *edge)
+{
+ espan_t *span;
+ surf_t *surf, *surf2;
+ int iu;
+ float fu, newzi, testzi, newzitop, newzibottom;
+
+ if (edge->surfs[1])
+ {
+ // it's adding a new surface in, so find the correct place
+ surf = &surfaces[edge->surfs[1]];
+
+ // don't start a span if this is an inverted span, with the end
+ // edge preceding the start edge (that is, we've already seen the
+ // end edge)
+ if (++surf->spanstate == 1)
+ {
+ surf2 = surfaces[1].next;
+
+ if (surf->key < surf2->key)
+ goto newtop;
+
+ // if it's two surfaces on the same plane, the one that's already
+ // active is in front, so keep going unless it's a bmodel
+ if (surf->insubmodel && (surf->key == surf2->key))
+ {
+ // must be two bmodels in the same leaf; sort on 1/z
+ fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
+ newzi = surf->d_ziorigin + fv*surf->d_zistepv +
+ fu*surf->d_zistepu;
+ newzibottom = newzi * 0.99;
+
+ testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
+ fu*surf2->d_zistepu;
+
+ if (newzibottom >= testzi)
+ {
+ goto newtop;
+ }
+
+ newzitop = newzi * 1.01;
+ if (newzitop >= testzi)
+ {
+ if (surf->d_zistepu >= surf2->d_zistepu)
+ {
+ goto newtop;
+ }
+ }
+ }
+
+continue_search:
+
+ do
+ {
+ surf2 = surf2->next;
+ } while (surf->key > surf2->key);
+
+ if (surf->key == surf2->key)
+ {
+ // if it's two surfaces on the same plane, the one that's already
+ // active is in front, so keep going unless it's a bmodel
+ if (!surf->insubmodel)
+ goto continue_search;
+
+ // must be two bmodels in the same leaf; sort on 1/z
+ fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
+ newzi = surf->d_ziorigin + fv*surf->d_zistepv +
+ fu*surf->d_zistepu;
+ newzibottom = newzi * 0.99;
+
+ testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
+ fu*surf2->d_zistepu;
+
+ if (newzibottom >= testzi)
+ {
+ goto gotposition;
+ }
+
+ newzitop = newzi * 1.01;
+ if (newzitop >= testzi)
+ {
+ if (surf->d_zistepu >= surf2->d_zistepu)
+ {
+ goto gotposition;
+ }
+ }
+
+ goto continue_search;
+ }
+
+ goto gotposition;
+
+newtop:
+ // emit a span (obscures current top)
+ iu = edge->u >> 20;
+
+ if (iu > surf2->last_u)
+ {
+ span = span_p++;
+ span->u = surf2->last_u;
+ span->count = iu - span->u;
+ span->v = current_iv;
+ span->pnext = surf2->spans;
+ surf2->spans = span;
+ }
+
+ // set last_u on the new span
+ surf->last_u = iu;
+
+gotposition:
+ // insert before surf2
+ surf->next = surf2;
+ surf->prev = surf2->prev;
+ surf2->prev->next = surf;
+ surf2->prev = surf;
+ }
+ }
+}
+
+
+/*
+==============
+R_GenerateSpans
+==============
+*/
+void R_GenerateSpans (void)
+{
+ edge_t *edge;
+ surf_t *surf;
+
+// clear active surfaces to just the background surface
+ surfaces[1].next = surfaces[1].prev = &surfaces[1];
+ surfaces[1].last_u = edge_head_u_shift20;
+
+// generate spans
+ for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
+ {
+ if (edge->surfs[0])
+ {
+ // it has a left surface, so a surface is going away for this span
+ surf = &surfaces[edge->surfs[0]];
+
+ R_TrailingEdge (surf, edge);
+
+ if (!edge->surfs[1])
+ continue;
+ }
+
+ R_LeadingEdge (edge);
+ }
+
+ R_CleanupSpan ();
+}
+
+#endif // !id386
+
+
+/*
+==============
+R_GenerateSpansBackward
+==============
+*/
+void R_GenerateSpansBackward (void)
+{
+ edge_t *edge;
+
+// clear active surfaces to just the background surface
+ surfaces[1].next = surfaces[1].prev = &surfaces[1];
+ surfaces[1].last_u = edge_head_u_shift20;
+
+// generate spans
+ for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
+ {
+ if (edge->surfs[0])
+ R_TrailingEdge (&surfaces[edge->surfs[0]], edge);
+
+ if (edge->surfs[1])
+ R_LeadingEdgeBackwards (edge);
+ }
+
+ R_CleanupSpan ();
+}
+
+
+/*
+==============
+R_ScanEdges
+
+Input:
+newedges[] array
+ this has links to edges, which have links to surfaces
+
+Output:
+Each surface has a linked list of its visible spans
+==============
+*/
+void R_ScanEdges (void)
+{
+ int iv, bottom;
+ byte basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE];
+ espan_t *basespan_p;
+ surf_t *s;
+
+ basespan_p = (espan_t *)
+ ((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+ max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width];
+
+ span_p = basespan_p;
+
+// clear active edges to just the background edges around the whole screen
+// FIXME: most of this only needs to be set up once
+ edge_head.u = r_refdef.vrect.x << 20;
+ edge_head_u_shift20 = edge_head.u >> 20;
+ edge_head.u_step = 0;
+ edge_head.prev = NULL;
+ edge_head.next = &edge_tail;
+ edge_head.surfs[0] = 0;
+ edge_head.surfs[1] = 1;
+
+ edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF;
+ edge_tail_u_shift20 = edge_tail.u >> 20;
+ edge_tail.u_step = 0;
+ edge_tail.prev = &edge_head;
+ edge_tail.next = &edge_aftertail;
+ edge_tail.surfs[0] = 1;
+ edge_tail.surfs[1] = 0;
+
+ edge_aftertail.u = -1; // force a move
+ edge_aftertail.u_step = 0;
+ edge_aftertail.next = &edge_sentinel;
+ edge_aftertail.prev = &edge_tail;
+
+// FIXME: do we need this now that we clamp x in r_draw.c?
+ edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this
+ edge_sentinel.prev = &edge_aftertail;
+
+//
+// process all scan lines
+//
+ bottom = r_refdef.vrectbottom - 1;
+
+ for (iv=r_refdef.vrect.y ; iv<bottom ; iv++)
+ {
+ current_iv = iv;
+ fv = (float)iv;
+
+ // mark that the head (background start) span is pre-included
+ surfaces[1].spanstate = 1;
+
+ if (newedges[iv])
+ {
+ R_InsertNewEdges (newedges[iv], edge_head.next);
+ }
+
+ (*pdrawfunc) ();
+
+ // flush the span list if we can't be sure we have enough spans left for
+ // the next scan
+ if (span_p > max_span_p)
+ {
+ D_DrawSurfaces ();
+
+ // clear the surface span pointers
+ for (s = &surfaces[1] ; s<surface_p ; s++)
+ s->spans = NULL;
+
+ span_p = basespan_p;
+ }
+
+ if (removeedges[iv])
+ R_RemoveEdges (removeedges[iv]);
+
+ if (edge_head.next != &edge_tail)
+ R_StepActiveU (edge_head.next);
+ }
+
+// do the last scan (no need to step or sort or remove on the last scan)
+
+ current_iv = iv;
+ fv = (float)iv;
+
+// mark that the head (background start) span is pre-included
+ surfaces[1].spanstate = 1;
+
+ if (newedges[iv])
+ R_InsertNewEdges (newedges[iv], edge_head.next);
+
+ (*pdrawfunc) ();
+
+// draw whatever's left in the span list
+ D_DrawSurfaces ();
+}
+
+
+/*
+=========================================================================
+
+SURFACE FILLING
+
+=========================================================================
+*/
+
+msurface_t *pface;
+surfcache_t *pcurrentcache;
+vec3_t transformed_modelorg;
+vec3_t world_transformed_modelorg;
+vec3_t local_modelorg;
+
+/*
+=============
+D_MipLevelForScale
+=============
+*/
+int D_MipLevelForScale (float scale)
+{
+ int lmiplevel;
+
+ if (scale >= d_scalemip[0] )
+ lmiplevel = 0;
+ else if (scale >= d_scalemip[1] )
+ lmiplevel = 1;
+ else if (scale >= d_scalemip[2] )
+ lmiplevel = 2;
+ else
+ lmiplevel = 3;
+
+ if (lmiplevel < d_minmip)
+ lmiplevel = d_minmip;
+
+ return lmiplevel;
+}
+
+
+/*
+==============
+D_FlatFillSurface
+
+Simple single color fill with no texture mapping
+==============
+*/
+void D_FlatFillSurface (surf_t *surf, int color)
+{
+ espan_t *span;
+ byte *pdest;
+ int u, u2;
+
+ for (span=surf->spans ; span ; span=span->pnext)
+ {
+ pdest = (byte *)d_viewbuffer + r_screenwidth*span->v;
+ u = span->u;
+ u2 = span->u + span->count - 1;
+ for ( ; u <= u2 ; u++)
+ pdest[u] = color;
+ }
+}
+
+
+/*
+==============
+D_CalcGradients
+==============
+*/
+void D_CalcGradients (msurface_t *pface)
+{
+ mplane_t *pplane;
+ float mipscale;
+ vec3_t p_temp1;
+ vec3_t p_saxis, p_taxis;
+ float t;
+
+ pplane = pface->plane;
+
+ mipscale = 1.0 / (float)(1 << miplevel);
+
+ TransformVector (pface->texinfo->vecs[0], p_saxis);
+ TransformVector (pface->texinfo->vecs[1], p_taxis);
+
+ t = xscaleinv * mipscale;
+ d_sdivzstepu = p_saxis[0] * t;
+ d_tdivzstepu = p_taxis[0] * t;
+
+ t = yscaleinv * mipscale;
+ d_sdivzstepv = -p_saxis[1] * t;
+ d_tdivzstepv = -p_taxis[1] * t;
+
+ d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu -
+ ycenter * d_sdivzstepv;
+ d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu -
+ ycenter * d_tdivzstepv;
+
+ VectorScale (transformed_modelorg, mipscale, p_temp1);
+
+ t = 0x10000*mipscale;
+ sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
+ ((pface->texturemins[0] << 16) >> miplevel)
+ + pface->texinfo->vecs[0][3]*t;
+ tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
+ ((pface->texturemins[1] << 16) >> miplevel)
+ + pface->texinfo->vecs[1][3]*t;
+
+ // PGM - changing flow speed for non-warping textures.
+ if (pface->texinfo->flags & SURF_FLOWING)
+ {
+ if(pface->texinfo->flags & SURF_WARP)
+ sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.25) - (int)(r_newrefdef.time * 0.25) ));
+ else
+ sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.77) - (int)(r_newrefdef.time * 0.77) ));
+ }
+ // PGM
+
+//
+// -1 (-epsilon) so we never wander off the edge of the texture
+//
+ bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
+ bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
+}
+
+
+/*
+==============
+D_BackgroundSurf
+
+The grey background filler seen when there is a hole in the map
+==============
+*/
+void D_BackgroundSurf (surf_t *s)
+{
+// set up a gradient for the background surface that places it
+// effectively at infinity distance from the viewpoint
+ d_zistepu = 0;
+ d_zistepv = 0;
+ d_ziorigin = -0.9;
+
+ D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFF);
+ D_DrawZSpans (s->spans);
+}
+
+/*
+=================
+D_TurbulentSurf
+=================
+*/
+void D_TurbulentSurf (surf_t *s)
+{
+ d_zistepu = s->d_zistepu;
+ d_zistepv = s->d_zistepv;
+ d_ziorigin = s->d_ziorigin;
+
+ pface = s->msurf;
+ miplevel = 0;
+ cacheblock = pface->texinfo->image->pixels[0];
+ cachewidth = 64;
+
+ if (s->insubmodel)
+ {
+ // FIXME: we don't want to do all this for every polygon!
+ // TODO: store once at start of frame
+ currententity = s->entity; //FIXME: make this passed in to
+ // R_RotateBmodel ()
+ VectorSubtract (r_origin, currententity->origin,
+ local_modelorg);
+ TransformVector (local_modelorg, transformed_modelorg);
+
+ R_RotateBmodel (); // FIXME: don't mess with the frustum,
+ // make entity passed in
+ }
+
+ D_CalcGradients (pface);
+
+//============
+//PGM
+ // textures that aren't warping are just flowing. Use NonTurbulent8 instead
+ if(!(pface->texinfo->flags & SURF_WARP))
+ NonTurbulent8 (s->spans);
+ else
+ Turbulent8 (s->spans);
+//PGM
+//============
+
+ D_DrawZSpans (s->spans);
+
+ if (s->insubmodel)
+ {
+ //
+ // restore the old drawing state
+ // FIXME: we don't want to do this every time!
+ // TODO: speed up
+ //
+ currententity = NULL; // &r_worldentity;
+ VectorCopy (world_transformed_modelorg,
+ transformed_modelorg);
+ VectorCopy (base_vpn, vpn);
+ VectorCopy (base_vup, vup);
+ VectorCopy (base_vright, vright);
+ R_TransformFrustum ();
+ }
+}
+
+/*
+==============
+D_SkySurf
+==============
+*/
+void D_SkySurf (surf_t *s)
+{
+ pface = s->msurf;
+ miplevel = 0;
+ if (!pface->texinfo->image)
+ return;
+ cacheblock = pface->texinfo->image->pixels[0];
+ cachewidth = 256;
+
+ d_zistepu = s->d_zistepu;
+ d_zistepv = s->d_zistepv;
+ d_ziorigin = s->d_ziorigin;
+
+ D_CalcGradients (pface);
+
+ D_DrawSpans16 (s->spans);
+
+// set up a gradient for the background surface that places it
+// effectively at infinity distance from the viewpoint
+ d_zistepu = 0;
+ d_zistepv = 0;
+ d_ziorigin = -0.9;
+
+ D_DrawZSpans (s->spans);
+}
+
+/*
+==============
+D_SolidSurf
+
+Normal surface cached, texture mapped surface
+==============
+*/
+void D_SolidSurf (surf_t *s)
+{
+ d_zistepu = s->d_zistepu;
+ d_zistepv = s->d_zistepv;
+ d_ziorigin = s->d_ziorigin;
+
+ if (s->insubmodel)
+ {
+ // FIXME: we don't want to do all this for every polygon!
+ // TODO: store once at start of frame
+ currententity = s->entity; //FIXME: make this passed in to
+ // R_RotateBmodel ()
+ VectorSubtract (r_origin, currententity->origin, local_modelorg);
+ TransformVector (local_modelorg, transformed_modelorg);
+
+ R_RotateBmodel (); // FIXME: don't mess with the frustum,
+ // make entity passed in
+ }
+ else
+ currententity = &r_worldentity;
+
+ pface = s->msurf;
+#if 1
+ miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust);
+#else
+ {
+ float dot;
+ float normal[3];
+
+ if ( s->insubmodel )
+ {
+ VectorCopy( pface->plane->normal, normal );
+// TransformVector( pface->plane->normal, normal);
+ dot = DotProduct( normal, vpn );
+ }
+ else
+ {
+ VectorCopy( pface->plane->normal, normal );
+ dot = DotProduct( normal, vpn );
+ }
+
+ if ( pface->flags & SURF_PLANEBACK )
+ dot = -dot;
+
+ if ( dot > 0 )
+ printf( "blah" );
+
+ miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust);
+ }
+#endif
+
+// FIXME: make this passed in to D_CacheSurface
+ pcurrentcache = D_CacheSurface (pface, miplevel);
+
+ cacheblock = (pixel_t *)pcurrentcache->data;
+ cachewidth = pcurrentcache->width;
+
+ D_CalcGradients (pface);
+
+ D_DrawSpans16 (s->spans);
+
+ D_DrawZSpans (s->spans);
+
+ if (s->insubmodel)
+ {
+ //
+ // restore the old drawing state
+ // FIXME: we don't want to do this every time!
+ // TODO: speed up
+ //
+ VectorCopy (world_transformed_modelorg,
+ transformed_modelorg);
+ VectorCopy (base_vpn, vpn);
+ VectorCopy (base_vup, vup);
+ VectorCopy (base_vright, vright);
+ R_TransformFrustum ();
+ currententity = NULL; //&r_worldentity;
+ }
+}
+
+/*
+=============
+D_DrawflatSurfaces
+
+To allow developers to see the polygon carving of the world
+=============
+*/
+void D_DrawflatSurfaces (void)
+{
+ surf_t *s;
+
+ for (s = &surfaces[1] ; s<surface_p ; s++)
+ {
+ if (!s->spans)
+ continue;
+
+ d_zistepu = s->d_zistepu;
+ d_zistepv = s->d_zistepv;
+ d_ziorigin = s->d_ziorigin;
+
+ // make a stable color for each surface by taking the low
+ // bits of the msurface pointer
+ D_FlatFillSurface (s, (int)s->msurf & 0xFF);
+ D_DrawZSpans (s->spans);
+ }
+}
+
+/*
+==============
+D_DrawSurfaces
+
+Rasterize all the span lists. Guaranteed zero overdraw.
+May be called more than once a frame if the surf list overflows (higher res)
+==============
+*/
+void D_DrawSurfaces (void)
+{
+ surf_t *s;
+
+// currententity = NULL; //&r_worldentity;
+ VectorSubtract (r_origin, vec3_origin, modelorg);
+ TransformVector (modelorg, transformed_modelorg);
+ VectorCopy (transformed_modelorg, world_transformed_modelorg);
+
+ if (!sw_drawflat->value)
+ {
+ for (s = &surfaces[1] ; s<surface_p ; s++)
+ {
+ if (!s->spans)
+ continue;
+
+ r_drawnpolycount++;
+
+ if (! (s->flags & (SURF_DRAWSKYBOX|SURF_DRAWBACKGROUND|SURF_DRAWTURB) ) )
+ D_SolidSurf (s);
+ else if (s->flags & SURF_DRAWSKYBOX)
+ D_SkySurf (s);
+ else if (s->flags & SURF_DRAWBACKGROUND)
+ D_BackgroundSurf (s);
+ else if (s->flags & SURF_DRAWTURB)
+ D_TurbulentSurf (s);
+ }
+ }
+ else
+ D_DrawflatSurfaces ();
+
+ currententity = NULL; //&r_worldentity;
+ VectorSubtract (r_origin, vec3_origin, modelorg);
+ R_TransformFrustum ();
+}
+
--- /dev/null
+++ b/ref/r_image.c
@@ -1,0 +1,617 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "r_local.h"
+
+
+#define MAX_RIMAGES 1024
+image_t r_images[MAX_RIMAGES];
+int numr_images;
+
+
+/*
+===============
+R_ImageList_f
+===============
+*/
+void R_ImageList_f (void)
+{
+ int i;
+ image_t *image;
+ int texels;
+
+ ri.Con_Printf (PRINT_ALL, "------------------\n");
+ texels = 0;
+
+ for (i=0, image=r_images ; i<numr_images ; i++, image++)
+ {
+ if (image->registration_sequence <= 0)
+ continue;
+ texels += image->width*image->height;
+ switch (image->type)
+ {
+ case it_skin:
+ ri.Con_Printf (PRINT_ALL, "M");
+ break;
+ case it_sprite:
+ ri.Con_Printf (PRINT_ALL, "S");
+ break;
+ case it_wall:
+ ri.Con_Printf (PRINT_ALL, "W");
+ break;
+ case it_pic:
+ ri.Con_Printf (PRINT_ALL, "P");
+ break;
+ default:
+ ri.Con_Printf (PRINT_ALL, " ");
+ break;
+ }
+
+ ri.Con_Printf (PRINT_ALL, " %3i %3i : %s\n",
+ image->width, image->height, image->name);
+ }
+ ri.Con_Printf (PRINT_ALL, "Total texel count: %i\n", texels);
+}
+
+
+/*
+=================================================================
+
+PCX LOADING
+
+=================================================================
+*/
+
+/*
+==============
+LoadPCX
+==============
+*/
+void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
+{
+ byte *raw;
+ pcx_t *pcx;
+ int x, y;
+ int len;
+ int dataByte, runLength;
+ byte *out, *pix;
+
+ *pic = NULL;
+
+ //
+ // load the file
+ //
+ len = ri.FS_LoadFile (filename, (void **)&raw);
+ if (!raw)
+ {
+ ri.Con_Printf (PRINT_DEVELOPER, "Bad pcx file %s\n", filename);
+ return;
+ }
+
+ //
+ // parse the PCX file
+ //
+ pcx = (pcx_t *)raw;
+
+ pcx->xmin = LittleShort(pcx->xmin);
+ pcx->ymin = LittleShort(pcx->ymin);
+ pcx->xmax = LittleShort(pcx->xmax);
+ pcx->ymax = LittleShort(pcx->ymax);
+ pcx->hres = LittleShort(pcx->hres);
+ pcx->vres = LittleShort(pcx->vres);
+ pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
+ pcx->palette_type = LittleShort(pcx->palette_type);
+
+ raw = &pcx->data;
+
+ if (pcx->manufacturer != 0x0a
+ || pcx->version != 5
+ || pcx->encoding != 1
+ || pcx->bits_per_pixel != 8
+ || pcx->xmax >= 640
+ || pcx->ymax >= 480)
+ {
+ ri.Con_Printf (PRINT_ALL, "Bad pcx file %s\n", filename);
+ return;
+ }
+
+ out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
+
+ *pic = out;
+
+ pix = out;
+
+ if (palette)
+ {
+ *palette = malloc(768);
+ memcpy (*palette, (byte *)pcx + len - 768, 768);
+ }
+
+ if (width)
+ *width = pcx->xmax+1;
+ if (height)
+ *height = pcx->ymax+1;
+
+ for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
+ {
+ for (x=0 ; x<=pcx->xmax ; )
+ {
+ dataByte = *raw++;
+
+ if((dataByte & 0xC0) == 0xC0)
+ {
+ runLength = dataByte & 0x3F;
+ dataByte = *raw++;
+ }
+ else
+ runLength = 1;
+
+ while(runLength-- > 0)
+ pix[x++] = dataByte;
+ }
+
+ }
+
+ if ( raw - (byte *)pcx > len)
+ {
+ ri.Con_Printf (PRINT_DEVELOPER, "PCX file %s was malformed", filename);
+ free (*pic);
+ *pic = NULL;
+ }
+
+ ri.FS_FreeFile (pcx);
+}
+
+/*
+=========================================================
+
+TARGA LOADING
+
+=========================================================
+*/
+
+typedef struct _TargaHeader {
+ unsigned char id_length, colormap_type, image_type;
+ unsigned short colormap_index, colormap_length;
+ unsigned char colormap_size;
+ unsigned short x_origin, y_origin, width, height;
+ unsigned char pixel_size, attributes;
+} TargaHeader;
+
+
+/*
+=============
+LoadTGA
+=============
+*/
+void LoadTGA (char *name, byte **pic, int *width, int *height)
+{
+ int columns, rows, numPixels;
+ byte *pixbuf;
+ int row, column;
+ byte *buf_p;
+ byte *buffer;
+ int length;
+ TargaHeader targa_header;
+ byte *targa_rgba;
+
+ *pic = NULL;
+
+ //
+ // load the file
+ //
+ length = ri.FS_LoadFile (name, (void **)&buffer);
+ if (!buffer)
+ {
+ ri.Con_Printf (PRINT_DEVELOPER, "Bad tga file %s\n", name);
+ return;
+ }
+
+ buf_p = buffer;
+
+ targa_header.id_length = *buf_p++;
+ targa_header.colormap_type = *buf_p++;
+ targa_header.image_type = *buf_p++;
+
+ targa_header.colormap_index = LittleShort ( *((short *)buf_p) );
+ buf_p+=2;
+ targa_header.colormap_length = LittleShort ( *((short *)buf_p) );
+ buf_p+=2;
+ targa_header.colormap_size = *buf_p++;
+ targa_header.x_origin = LittleShort ( *((short *)buf_p) );
+ buf_p+=2;
+ targa_header.y_origin = LittleShort ( *((short *)buf_p) );
+ buf_p+=2;
+ targa_header.width = LittleShort ( *((short *)buf_p) );
+ buf_p+=2;
+ targa_header.height = LittleShort ( *((short *)buf_p) );
+ buf_p+=2;
+ targa_header.pixel_size = *buf_p++;
+ targa_header.attributes = *buf_p++;
+
+ if (targa_header.image_type!=2
+ && targa_header.image_type!=10)
+ ri.Sys_Error (ERR_DROP, "LoadTGA: Only type 2 and 10 targa RGB images supported\n");
+
+ if (targa_header.colormap_type !=0
+ || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
+ ri.Sys_Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
+
+ columns = targa_header.width;
+ rows = targa_header.height;
+ numPixels = columns * rows;
+
+ if (width)
+ *width = columns;
+ if (height)
+ *height = rows;
+
+ targa_rgba = malloc (numPixels*4);
+ *pic = targa_rgba;
+
+ if (targa_header.id_length != 0)
+ buf_p += targa_header.id_length; // skip TARGA image comment
+
+ if (targa_header.image_type==2) { // Uncompressed, RGB images
+ for(row=rows-1; row>=0; row--) {
+ pixbuf = targa_rgba + row*columns*4;
+ for(column=0; column<columns; column++) {
+ unsigned char red,green,blue,alphabyte;
+ switch (targa_header.pixel_size) {
+ case 24:
+
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ *pixbuf++ = red;
+ *pixbuf++ = green;
+ *pixbuf++ = blue;
+ *pixbuf++ = 255;
+ break;
+ case 32:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ alphabyte = *buf_p++;
+ *pixbuf++ = red;
+ *pixbuf++ = green;
+ *pixbuf++ = blue;
+ *pixbuf++ = alphabyte;
+ break;
+ }
+ }
+ }
+ }
+ else if (targa_header.image_type==10) { // Runlength encoded RGB images
+ unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
+ for(row=rows-1; row>=0; row--) {
+ pixbuf = targa_rgba + row*columns*4;
+ for(column=0; column<columns; ) {
+ packetHeader= *buf_p++;
+ packetSize = 1 + (packetHeader & 0x7f);
+ if (packetHeader & 0x80) { // run-length packet
+ switch (targa_header.pixel_size) {
+ case 24:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ alphabyte = 255;
+ break;
+ case 32:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ alphabyte = *buf_p++;
+ break;
+ }
+
+ for(j=0;j<packetSize;j++) {
+ *pixbuf++=red;
+ *pixbuf++=green;
+ *pixbuf++=blue;
+ *pixbuf++=alphabyte;
+ column++;
+ if (column==columns) { // run spans across rows
+ column=0;
+ if (row>0)
+ row--;
+ else
+ goto breakOut;
+ pixbuf = targa_rgba + row*columns*4;
+ }
+ }
+ }
+ else { // non run-length packet
+ for(j=0;j<packetSize;j++) {
+ switch (targa_header.pixel_size) {
+ case 24:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ *pixbuf++ = red;
+ *pixbuf++ = green;
+ *pixbuf++ = blue;
+ *pixbuf++ = 255;
+ break;
+ case 32:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ alphabyte = *buf_p++;
+ *pixbuf++ = red;
+ *pixbuf++ = green;
+ *pixbuf++ = blue;
+ *pixbuf++ = alphabyte;
+ break;
+ }
+ column++;
+ if (column==columns) { // pixel packet run spans across rows
+ column=0;
+ if (row>0)
+ row--;
+ else
+ goto breakOut;
+ pixbuf = targa_rgba + row*columns*4;
+ }
+ }
+ }
+ }
+ breakOut:;
+ }
+ }
+
+ ri.FS_FreeFile (buffer);
+}
+
+
+//=======================================================
+
+image_t *R_FindFreeImage (void)
+{
+ image_t *image;
+ int i;
+
+ // find a free image_t
+ for (i=0, image=r_images ; i<numr_images ; i++,image++)
+ {
+ if (!image->registration_sequence)
+ break;
+ }
+ if (i == numr_images)
+ {
+ if (numr_images == MAX_RIMAGES)
+ ri.Sys_Error (ERR_DROP, "MAX_RIMAGES");
+ numr_images++;
+ }
+ image = &r_images[i];
+
+ return image;
+}
+
+/*
+================
+GL_LoadPic
+
+================
+*/
+image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type)
+{
+ image_t *image;
+ int i, c, b;
+
+ image = R_FindFreeImage ();
+ if (strlen(name) >= sizeof(image->name))
+ ri.Sys_Error (ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
+ strcpy (image->name, name);
+ image->registration_sequence = registration_sequence;
+
+ image->width = width;
+ image->height = height;
+ image->type = type;
+
+ c = width*height;
+ image->pixels[0] = malloc (c);
+ image->transparent = false;
+ for (i=0 ; i<c ; i++)
+ {
+ b = pic[i];
+ if (b == 255)
+ image->transparent = true;
+ image->pixels[0][i] = b;
+ }
+
+ return image;
+}
+
+/*
+================
+R_LoadWal
+================
+*/
+image_t *R_LoadWal (char *name)
+{
+ miptex_t *mt;
+ int ofs;
+ image_t *image;
+ int size;
+
+ ri.FS_LoadFile (name, (void **)&mt);
+ if (!mt)
+ {
+ ri.Con_Printf (PRINT_ALL, "R_LoadWal: can't load %s\n", name);
+ return r_notexture_mip;
+ }
+
+ image = R_FindFreeImage ();
+ strcpy (image->name, name);
+ image->width = LittleLong (mt->width);
+ image->height = LittleLong (mt->height);
+ image->type = it_wall;
+ image->registration_sequence = registration_sequence;
+
+ size = image->width*image->height * (256+64+16+4)/256;
+ image->pixels[0] = malloc (size);
+ image->pixels[1] = image->pixels[0] + image->width*image->height;
+ image->pixels[2] = image->pixels[1] + image->width*image->height/4;
+ image->pixels[3] = image->pixels[2] + image->width*image->height/16;
+
+ ofs = LittleLong (mt->offsets[0]);
+ memcpy ( image->pixels[0], (byte *)mt + ofs, size);
+
+ ri.FS_FreeFile ((void *)mt);
+
+ return image;
+}
+
+
+/*
+===============
+R_FindImage
+
+Finds or loads the given image
+===============
+*/
+image_t *R_FindImage (char *name, imagetype_t type)
+{
+ image_t *image;
+ int i, len;
+ byte *pic, *palette;
+ int width, height;
+
+ if (!name)
+ return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: NULL name");
+ len = strlen(name);
+ if (len<5)
+ return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad name: %s", name);
+
+ // look for it
+ for (i=0, image=r_images ; i<numr_images ; i++,image++)
+ {
+ if (!strcmp(name, image->name))
+ {
+ image->registration_sequence = registration_sequence;
+ return image;
+ }
+ }
+
+ //
+ // load the pic from disk
+ //
+ pic = NULL;
+ palette = NULL;
+ if (!strcmp(name+len-4, ".pcx"))
+ {
+ LoadPCX (name, &pic, &palette, &width, &height);
+ if (!pic)
+ return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s", name);
+ image = GL_LoadPic (name, pic, width, height, type);
+ }
+ else if (!strcmp(name+len-4, ".wal"))
+ {
+ image = R_LoadWal (name);
+ }
+ else if (!strcmp(name+len-4, ".tga"))
+ return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s in software renderer", name);
+ else
+ return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad extension on: %s", name);
+
+ if (pic)
+ free(pic);
+ if (palette)
+ free(palette);
+
+ return image;
+}
+
+
+
+/*
+===============
+R_RegisterSkin
+===============
+*/
+struct image_s *R_RegisterSkin (char *name)
+{
+ return R_FindImage (name, it_skin);
+}
+
+
+/*
+================
+R_FreeUnusedImages
+
+Any image that was not touched on this registration sequence
+will be freed.
+================
+*/
+void R_FreeUnusedImages (void)
+{
+ int i;
+ image_t *image;
+
+ for (i=0, image=r_images ; i<numr_images ; i++, image++)
+ {
+ if (image->registration_sequence == registration_sequence)
+ {
+ Com_PageInMemory ((byte *)image->pixels[0], image->width*image->height);
+ continue; // used this sequence
+ }
+ if (!image->registration_sequence)
+ continue; // free texture
+ if (image->type == it_pic)
+ continue; // don't free pics
+ // free it
+ free (image->pixels[0]); // the other mip levels just follow
+ memset (image, 0, sizeof(*image));
+ }
+}
+
+
+
+/*
+===============
+R_InitImages
+===============
+*/
+void R_InitImages (void)
+{
+ registration_sequence = 1;
+}
+
+/*
+===============
+R_ShutdownImages
+===============
+*/
+void R_ShutdownImages (void)
+{
+ int i;
+ image_t *image;
+
+ for (i=0, image=r_images ; i<numr_images ; i++, image++)
+ {
+ if (!image->registration_sequence)
+ continue; // free texture
+ // free it
+ free (image->pixels[0]); // the other mip levels just follow
+ memset (image, 0, sizeof(*image));
+ }
+}
+
--- /dev/null
+++ b/ref/r_light.c
@@ -1,0 +1,442 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// r_light.c
+
+#include "r_local.h"
+
+int r_dlightframecount;
+
+
+/*
+=============================================================================
+
+DYNAMIC LIGHTS
+
+=============================================================================
+*/
+
+/*
+=============
+R_MarkLights
+=============
+*/
+void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
+{
+ mplane_t *splitplane;
+ float dist;
+ msurface_t *surf;
+ int i;
+
+ if (node->contents != -1)
+ return;
+
+ splitplane = node->plane;
+ dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
+
+//=====
+//PGM
+ i=light->intensity;
+ if(i<0)
+ i=-i;
+//PGM
+//=====
+
+ if (dist > i) // PGM (dist > light->intensity)
+ {
+ R_MarkLights (light, bit, node->children[0]);
+ return;
+ }
+ if (dist < -i) // PGM (dist < -light->intensity)
+ {
+ R_MarkLights (light, bit, node->children[1]);
+ return;
+ }
+
+// mark the polygons
+ surf = r_worldmodel->surfaces + node->firstsurface;
+ for (i=0 ; i<node->numsurfaces ; i++, surf++)
+ {
+ if (surf->dlightframe != r_dlightframecount)
+ {
+ surf->dlightbits = 0;
+ surf->dlightframe = r_dlightframecount;
+ }
+ surf->dlightbits |= bit;
+ }
+
+ R_MarkLights (light, bit, node->children[0]);
+ R_MarkLights (light, bit, node->children[1]);
+}
+
+
+/*
+=============
+R_PushDlights
+=============
+*/
+void R_PushDlights (model_t *model)
+{
+ int i;
+ dlight_t *l;
+
+ r_dlightframecount = r_framecount;
+ for (i=0, l = r_newrefdef.dlights ; i<r_newrefdef.num_dlights ; i++, l++)
+ {
+ R_MarkLights ( l, 1<<i,
+ model->nodes + model->firstnode);
+ }
+}
+
+
+/*
+=============================================================================
+
+LIGHT SAMPLING
+
+=============================================================================
+*/
+
+vec3_t pointcolor;
+mplane_t *lightplane; // used as shadow plane
+vec3_t lightspot;
+
+int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
+{
+ float front, back, frac;
+ int side;
+ mplane_t *plane;
+ vec3_t mid;
+ msurface_t *surf;
+ int s, t, ds, dt;
+ int i;
+ mtexinfo_t *tex;
+ byte *lightmap;
+ float *scales;
+ int maps;
+ float samp;
+ int r;
+
+ if (node->contents != -1)
+ return -1; // didn't hit anything
+
+// calculate mid point
+
+// FIXME: optimize for axial
+ plane = node->plane;
+ front = DotProduct (start, plane->normal) - plane->dist;
+ back = DotProduct (end, plane->normal) - plane->dist;
+ side = front < 0;
+
+ if ( (back < 0) == side)
+ return RecursiveLightPoint (node->children[side], start, end);
+
+ frac = front / (front-back);
+ mid[0] = start[0] + (end[0] - start[0])*frac;
+ mid[1] = start[1] + (end[1] - start[1])*frac;
+ mid[2] = start[2] + (end[2] - start[2])*frac;
+ if (plane->type < 3) // axial planes
+ mid[plane->type] = plane->dist;
+
+// go down front side
+ r = RecursiveLightPoint (node->children[side], start, mid);
+ if (r >= 0)
+ return r; // hit something
+
+ if ( (back < 0) == side )
+ return -1; // didn't hit anuthing
+
+// check for impact on this node
+ VectorCopy (mid, lightspot);
+ lightplane = plane;
+
+ surf = r_worldmodel->surfaces + node->firstsurface;
+ for (i=0 ; i<node->numsurfaces ; i++, surf++)
+ {
+ if (surf->flags&(SURF_DRAWTURB|SURF_DRAWSKY))
+ continue; // no lightmaps
+
+ tex = surf->texinfo;
+
+ s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
+ t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];
+ if (s < surf->texturemins[0] ||
+ t < surf->texturemins[1])
+ continue;
+
+ ds = s - surf->texturemins[0];
+ dt = t - surf->texturemins[1];
+
+ if ( ds > surf->extents[0] || dt > surf->extents[1] )
+ continue;
+
+ if (!surf->samples)
+ return 0;
+
+ ds >>= 4;
+ dt >>= 4;
+
+ lightmap = surf->samples;
+ VectorCopy (vec3_origin, pointcolor);
+ if (lightmap)
+ {
+ lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
+
+ for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
+ maps++)
+ {
+ samp = *lightmap * /* 0.5 * */ (1.0/255); // adjust for gl scale
+ scales = r_newrefdef.lightstyles[surf->styles[maps]].rgb;
+ VectorMA (pointcolor, samp, scales, pointcolor);
+ lightmap += ((surf->extents[0]>>4)+1) *
+ ((surf->extents[1]>>4)+1);
+ }
+ }
+
+ return 1;
+ }
+
+// go down back side
+ return RecursiveLightPoint (node->children[!side], mid, end);
+}
+
+/*
+===============
+R_LightPoint
+===============
+*/
+void R_LightPoint (vec3_t p, vec3_t color)
+{
+ vec3_t end;
+ float r;
+ int lnum;
+ dlight_t *dl;
+ float light;
+ vec3_t dist;
+ float add;
+
+ if (!r_worldmodel->lightdata)
+ {
+ color[0] = color[1] = color[2] = 1.0;
+ return;
+ }
+
+ end[0] = p[0];
+ end[1] = p[1];
+ end[2] = p[2] - 2048;
+
+ r = RecursiveLightPoint (r_worldmodel->nodes, p, end);
+
+ if (r == -1)
+ {
+ VectorCopy (vec3_origin, color);
+ }
+ else
+ {
+ VectorCopy (pointcolor, color);
+ }
+
+ //
+ // add dynamic lights
+ //
+ light = 0;
+ for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
+ {
+ dl = &r_newrefdef.dlights[lnum];
+ VectorSubtract (currententity->origin,
+ dl->origin,
+ dist);
+ add = dl->intensity - VectorLength(dist);
+ add *= (1.0/256);
+ if (add > 0)
+ {
+ VectorMA (color, add, dl->color, color);
+ }
+ }
+}
+
+//===================================================================
+
+
+unsigned blocklights[1024]; // allow some very large lightmaps
+
+/*
+===============
+R_AddDynamicLights
+===============
+*/
+void R_AddDynamicLights (void)
+{
+ msurface_t *surf;
+ int lnum;
+ int sd, td;
+ float dist, rad, minlight;
+ vec3_t impact, local;
+ int s, t;
+ int i;
+ int smax, tmax;
+ mtexinfo_t *tex;
+ dlight_t *dl;
+ int negativeLight; //PGM
+
+ surf = r_drawsurf.surf;
+ smax = (surf->extents[0]>>4)+1;
+ tmax = (surf->extents[1]>>4)+1;
+ tex = surf->texinfo;
+
+ for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
+ {
+ if ( !(surf->dlightbits & (1<<lnum) ) )
+ continue; // not lit by this light
+
+ dl = &r_newrefdef.dlights[lnum];
+ rad = dl->intensity;
+
+//=====
+//PGM
+ negativeLight = 0;
+ if(rad < 0)
+ {
+ negativeLight = 1;
+ rad = -rad;
+ }
+//PGM
+//=====
+
+ dist = DotProduct (dl->origin, surf->plane->normal) -
+ surf->plane->dist;
+ rad -= fabs(dist);
+ minlight = 32; // dl->minlight;
+ if (rad < minlight)
+ continue;
+ minlight = rad - minlight;
+
+ for (i=0 ; i<3 ; i++)
+ {
+ impact[i] = dl->origin[i] -
+ surf->plane->normal[i]*dist;
+ }
+
+ local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
+ local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
+
+ local[0] -= surf->texturemins[0];
+ local[1] -= surf->texturemins[1];
+
+ for (t = 0 ; t<tmax ; t++)
+ {
+ td = local[1] - t*16;
+ if (td < 0)
+ td = -td;
+ for (s=0 ; s<smax ; s++)
+ {
+ sd = local[0] - s*16;
+ if (sd < 0)
+ sd = -sd;
+ if (sd > td)
+ dist = sd + (td>>1);
+ else
+ dist = td + (sd>>1);
+//====
+//PGM
+ if(!negativeLight)
+ {
+ if (dist < minlight)
+ blocklights[t*smax + s] += (rad - dist)*256;
+ }
+ else
+ {
+ if (dist < minlight)
+ blocklights[t*smax + s] -= (rad - dist)*256;
+ if(blocklights[t*smax + s] < minlight)
+ blocklights[t*smax + s] = minlight;
+ }
+//PGM
+//====
+ }
+ }
+ }
+}
+
+/*
+===============
+R_BuildLightMap
+
+Combine and scale multiple lightmaps into the 8.8 format in blocklights
+===============
+*/
+void R_BuildLightMap (void)
+{
+ int smax, tmax;
+ int t;
+ int i, size;
+ byte *lightmap;
+ unsigned scale;
+ int maps;
+ msurface_t *surf;
+
+ surf = r_drawsurf.surf;
+
+ smax = (surf->extents[0]>>4)+1;
+ tmax = (surf->extents[1]>>4)+1;
+ size = smax*tmax;
+
+ if (r_fullbright->value || !r_worldmodel->lightdata)
+ {
+ for (i=0 ; i<size ; i++)
+ blocklights[i] = 0;
+ return;
+ }
+
+// clear to no light
+ for (i=0 ; i<size ; i++)
+ blocklights[i] = 0;
+
+
+// add all the lightmaps
+ lightmap = surf->samples;
+ if (lightmap)
+ for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
+ maps++)
+ {
+ scale = r_drawsurf.lightadj[maps]; // 8.8 fraction
+ for (i=0 ; i<size ; i++)
+ blocklights[i] += lightmap[i] * scale;
+ lightmap += size; // skip to next lightmap
+ }
+
+// add all the dynamic lights
+ if (surf->dlightframe == r_framecount)
+ R_AddDynamicLights ();
+
+// bound, invert, and shift
+ for (i=0 ; i<size ; i++)
+ {
+ t = (int)blocklights[i];
+ if (t < 0)
+ t = 0;
+ t = (255*256 - t) >> (8 - VID_CBITS);
+
+ if (t < (1 << 6))
+ t = (1 << 6);
+
+ blocklights[i] = t;
+ }
+}
+
--- /dev/null
+++ b/ref/r_local.h
@@ -1,0 +1,849 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <stdarg.h>
+
+#include "../client/ref.h"
+
+#define REF_VERSION "SOFT 0.01"
+
+// up / down
+#define PITCH 0
+
+// left / right
+#define YAW 1
+
+// fall over
+#define ROLL 2
+
+
+/*
+
+ skins will be outline flood filled and mip mapped
+ pics and sprites with alpha will be outline flood filled
+ pic won't be mip mapped
+
+ model skin
+ sprite frame
+ wall texture
+ pic
+
+*/
+
+typedef enum
+{
+ it_skin,
+ it_sprite,
+ it_wall,
+ it_pic,
+ it_sky
+} imagetype_t;
+
+typedef struct image_s
+{
+ char name[MAX_QPATH]; // game path, including extension
+ imagetype_t type;
+ int width, height;
+ qboolean transparent; // true if any 255 pixels in image
+ int registration_sequence; // 0 = free
+ byte *pixels[4]; // mip levels
+} image_t;
+
+
+//===================================================================
+
+typedef unsigned char pixel_t;
+
+typedef struct vrect_s
+{
+ int x,y,width,height;
+ struct vrect_s *pnext;
+} vrect_t;
+
+typedef struct
+{
+ pixel_t *buffer; // invisible buffer
+ pixel_t *colormap; // 256 * VID_GRADES size
+ pixel_t *alphamap; // 256 * 256 translucency map
+ int rowbytes; // may be > width if displayed in a window
+ // can be negative for stupid dibs
+ int width;
+ int height;
+} viddef_t;
+
+typedef enum
+{
+ rserr_ok,
+
+ rserr_invalid_fullscreen,
+ rserr_invalid_mode,
+
+ rserr_unknown
+} rserr_t;
+
+extern viddef_t vid;
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct
+{
+ vrect_t vrect; // subwindow in video for refresh
+ // FIXME: not need vrect next field here?
+ vrect_t aliasvrect; // scaled Alias version
+ int vrectright, vrectbottom; // right & bottom screen coords
+ int aliasvrectright, aliasvrectbottom; // scaled Alias versions
+ float vrectrightedge; // rightmost right edge we care about,
+ // for use in edge list
+ float fvrectx, fvrecty; // for floating-point compares
+ float fvrectx_adj, fvrecty_adj; // left and top edges, for clamping
+ int vrect_x_adj_shift20; // (vrect.x + 0.5 - epsilon) << 20
+ int vrectright_adj_shift20; // (vrectright + 0.5 - epsilon) << 20
+ float fvrectright_adj, fvrectbottom_adj;
+ // right and bottom edges, for clamping
+ float fvrectright; // rightmost edge, for Alias clamping
+ float fvrectbottom; // bottommost edge, for Alias clamping
+ float horizontalFieldOfView; // at Z = 1.0, this many X is visible
+ // 2.0 = 90 degrees
+ float xOrigin; // should probably always be 0.5
+ float yOrigin; // between be around 0.3 to 0.5
+
+ vec3_t vieworg;
+ vec3_t viewangles;
+
+ int ambientlight;
+} oldrefdef_t;
+
+extern oldrefdef_t r_refdef;
+
+#include "r_model.h"
+
+#define CACHE_SIZE 32
+
+/*
+====================================================
+
+ CONSTANTS
+
+====================================================
+*/
+
+#define VID_CBITS 6
+#define VID_GRADES (1 << VID_CBITS)
+
+
+// r_shared.h: general refresh-related stuff shared between the refresh and the
+// driver
+
+
+#define MAXVERTS 64 // max points in a surface polygon
+#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate
+ // polygon (while processing)
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+#define MAXHEIGHT 1200
+#define MAXWIDTH 1600
+
+#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to
+ // be farther away than anything in
+ // the scene
+
+
+// d_iface.h: interface header file for rasterization driver modules
+
+#define WARP_WIDTH 320
+#define WARP_HEIGHT 240
+
+#define MAX_LBM_HEIGHT 480
+
+
+#define PARTICLE_Z_CLIP 8.0
+
+// !!! must be kept the same as in quakeasm.h !!!
+#define TRANSPARENT_COLOR 0xFF
+
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+#define TURB_TEX_SIZE 64 // base turbulent texture size
+
+// !!! if this is changed, it must be changed in d_ifacea.h too !!!
+#define CYCLE 128 // turbulent cycle size
+
+#define SCANBUFFERPAD 0x1000
+
+#define DS_SPAN_LIST_END -128
+
+#define NUMSTACKEDGES 2000
+#define MINEDGES NUMSTACKEDGES
+#define NUMSTACKSURFACES 1000
+#define MINSURFACES NUMSTACKSURFACES
+#define MAXSPANS 3000
+
+// flags in finalvert_t.flags
+#define ALIAS_LEFT_CLIP 0x0001
+#define ALIAS_TOP_CLIP 0x0002
+#define ALIAS_RIGHT_CLIP 0x0004
+#define ALIAS_BOTTOM_CLIP 0x0008
+#define ALIAS_Z_CLIP 0x0010
+#define ALIAS_XY_CLIP_MASK 0x000F
+
+#define SURFCACHE_SIZE_AT_320X240 1024*768
+
+#define BMODEL_FULLY_CLIPPED 0x10 // value returned by R_BmodelCheckBBox ()
+ // if bbox is trivially rejected
+
+#define XCENTERING (1.0 / 2.0)
+#define YCENTERING (1.0 / 2.0)
+
+#define CLIP_EPSILON 0.001
+
+#define BACKFACE_EPSILON 0.01
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+#define NEAR_CLIP 0.01
+
+
+#define MAXALIASVERTS 2000 // TODO: tune this
+#define ALIAS_Z_CLIP_PLANE 4
+
+// turbulence stuff
+
+#define AMP 8*0x10000
+#define AMP2 3
+#define SPEED 20
+
+
+/*
+====================================================
+
+TYPES
+
+====================================================
+*/
+
+typedef struct
+{
+ float u, v;
+ float s, t;
+ float zi;
+} emitpoint_t;
+
+/*
+** if you change this structure be sure to change the #defines
+** listed after it!
+*/
+#define SMALL_FINALVERT 0
+
+#if SMALL_FINALVERT
+
+typedef struct finalvert_s {
+ short u, v, s, t;
+ int l;
+ int zi;
+ int flags;
+ float xyz[3]; // eye space
+} finalvert_t;
+
+#define FINALVERT_V0 0
+#define FINALVERT_V1 2
+#define FINALVERT_V2 4
+#define FINALVERT_V3 6
+#define FINALVERT_V4 8
+#define FINALVERT_V5 12
+#define FINALVERT_FLAGS 16
+#define FINALVERT_X 20
+#define FINALVERT_Y 24
+#define FINALVERT_Z 28
+#define FINALVERT_SIZE 32
+
+#else
+
+typedef struct finalvert_s {
+ int u, v, s, t;
+ int l;
+ int zi;
+ int flags;
+ float xyz[3]; // eye space
+} finalvert_t;
+
+#define FINALVERT_V0 0
+#define FINALVERT_V1 4
+#define FINALVERT_V2 8
+#define FINALVERT_V3 12
+#define FINALVERT_V4 16
+#define FINALVERT_V5 20
+#define FINALVERT_FLAGS 24
+#define FINALVERT_X 28
+#define FINALVERT_Y 32
+#define FINALVERT_Z 36
+#define FINALVERT_SIZE 40
+
+#endif
+
+typedef struct
+{
+ void *pskin;
+ int pskindesc;
+ int skinwidth;
+ int skinheight;
+ dtriangle_t *ptriangles;
+ finalvert_t *pfinalverts;
+ int numtriangles;
+ int drawtype;
+ int seamfixupX16;
+ qboolean do_vis_thresh;
+ int vis_thresh;
+} affinetridesc_t;
+
+typedef struct
+{
+ byte *surfdat; // destination for generated surface
+ int rowbytes; // destination logical width in bytes
+ msurface_t *surf; // description for surface to generate
+ fixed8_t lightadj[MAXLIGHTMAPS];
+ // adjust for lightmap levels for dynamic lighting
+ image_t *image;
+ int surfmip; // mipmapped ratio of surface texels / world pixels
+ int surfwidth; // in mipmapped texels
+ int surfheight; // in mipmapped texels
+} drawsurf_t;
+
+
+
+typedef struct {
+ int ambientlight;
+ int shadelight;
+ float *plightvec;
+} alight_t;
+
+// clipped bmodel edges
+
+typedef struct bedge_s
+{
+ mvertex_t *v[2];
+ struct bedge_s *pnext;
+} bedge_t;
+
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct clipplane_s
+{
+ vec3_t normal;
+ float dist;
+ struct clipplane_s *next;
+ byte leftedge;
+ byte rightedge;
+ byte reserved[2];
+} clipplane_t;
+
+
+typedef struct surfcache_s
+{
+ struct surfcache_s *next;
+ struct surfcache_s **owner; // NULL is an empty chunk of memory
+ int lightadj[MAXLIGHTMAPS]; // checked for strobe flush
+ int dlight;
+ int size; // including header
+ unsigned width;
+ unsigned height; // DEBUG only needed for debug
+ float mipscale;
+ image_t *image;
+ byte data[4]; // width*height elements
+} surfcache_t;
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct espan_s
+{
+ int u, v, count;
+ struct espan_s *pnext;
+} espan_t;
+
+// used by the polygon drawer (R_POLY.C) and sprite setup code (R_SPRITE.C)
+typedef struct
+{
+ int nump;
+ emitpoint_t *pverts;
+ byte *pixels; // image
+ int pixel_width; // image width
+ int pixel_height; // image height
+ vec3_t vup, vright, vpn; // in worldspace, for plane eq
+ float dist;
+ float s_offset, t_offset;
+ float viewer_position[3];
+ void (*drawspanlet)( void );
+ int stipple_parity;
+} polydesc_t;
+
+// FIXME: compress, make a union if that will help
+// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte
+typedef struct surf_s
+{
+ struct surf_s *next; // active surface stack in r_edge.c
+ struct surf_s *prev; // used in r_edge.c for active surf stack
+ struct espan_s *spans; // pointer to linked list of spans to draw
+ int key; // sorting key (BSP order)
+ int last_u; // set during tracing
+ int spanstate; // 0 = not in span
+ // 1 = in span
+ // -1 = in inverted span (end before
+ // start)
+ int flags; // currentface flags
+ msurface_t *msurf;
+ entity_t *entity;
+ float nearzi; // nearest 1/z on surface, for mipmapping
+ qboolean insubmodel;
+ float d_ziorigin, d_zistepu, d_zistepv;
+
+ int pad[2]; // to 64 bytes
+} surf_t;
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct edge_s
+{
+ fixed16_t u;
+ fixed16_t u_step;
+ struct edge_s *prev, *next;
+ unsigned short surfs[2];
+ struct edge_s *nextremove;
+ float nearzi;
+ medge_t *owner;
+} edge_t;
+
+
+/*
+====================================================
+
+VARS
+
+====================================================
+*/
+
+extern int d_spanpixcount;
+extern int r_framecount; // sequence # of current frame since Quake
+ // started
+extern float r_aliasuvscale; // scale-up factor for screen u and v
+ // on Alias vertices passed to driver
+extern qboolean r_dowarp;
+
+extern affinetridesc_t r_affinetridesc;
+
+extern vec3_t r_pright, r_pup, r_ppn;
+
+void D_DrawSurfaces (void);
+void R_DrawParticle( void );
+void D_ViewChanged (void);
+void D_WarpScreen (void);
+void R_PolysetUpdateTables (void);
+
+extern void *acolormap; // FIXME: should go away
+
+//=======================================================================//
+
+// callbacks to Quake
+
+extern drawsurf_t r_drawsurf;
+
+void R_DrawSurface (void);
+
+extern int c_surf;
+
+extern byte r_warpbuffer[WARP_WIDTH * WARP_HEIGHT];
+
+
+
+
+extern float scale_for_mip;
+
+extern qboolean d_roverwrapped;
+extern surfcache_t *sc_rover;
+extern surfcache_t *d_initial_rover;
+
+extern float d_sdivzstepu, d_tdivzstepu, d_zistepu;
+extern float d_sdivzstepv, d_tdivzstepv, d_zistepv;
+extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
+
+extern fixed16_t sadjust, tadjust;
+extern fixed16_t bbextents, bbextentt;
+
+
+void D_DrawSpans16 (espan_t *pspans);
+void D_DrawZSpans (espan_t *pspans);
+void Turbulent8 (espan_t *pspan);
+void NonTurbulent8 (espan_t *pspan); //PGM
+
+surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel);
+
+extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
+
+extern int d_pix_min, d_pix_max, d_pix_shift;
+
+extern pixel_t *d_viewbuffer;
+extern short *d_pzbuffer;
+extern unsigned int d_zrowbytes, d_zwidth;
+extern short *zspantable[MAXHEIGHT];
+extern int d_scantable[MAXHEIGHT];
+
+extern int d_minmip;
+extern float d_scalemip[3];
+
+//===================================================================
+
+extern int cachewidth;
+extern pixel_t *cacheblock;
+extern int r_screenwidth;
+
+extern int r_drawnpolycount;
+
+extern int sintable[1280];
+extern int intsintable[1280];
+extern int blanktable[1280]; // PGM
+
+extern vec3_t vup, base_vup;
+extern vec3_t vpn, base_vpn;
+extern vec3_t vright, base_vright;
+
+extern surf_t *surfaces, *surface_p, *surf_max;
+
+// surfaces are generated in back to front order by the bsp, so if a surf
+// pointer is greater than another one, it should be drawn in front
+// surfaces[1] is the background, and is used as the active surface stack.
+// surfaces[0] is a dummy, because index 0 is used to indicate no surface
+// attached to an edge_t
+
+//===================================================================
+
+extern vec3_t sxformaxis[4]; // s axis transformed into viewspace
+extern vec3_t txformaxis[4]; // t axis transformed into viewspac
+
+extern float xcenter, ycenter;
+extern float xscale, yscale;
+extern float xscaleinv, yscaleinv;
+extern float xscaleshrink, yscaleshrink;
+
+extern void TransformVector (vec3_t in, vec3_t out);
+extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
+ fixed8_t endvertu, fixed8_t endvertv);
+
+extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
+
+//===========================================================================
+
+extern cvar_t *sw_aliasstats;
+extern cvar_t *sw_clearcolor;
+extern cvar_t *sw_drawflat;
+extern cvar_t *sw_draworder;
+extern cvar_t *sw_maxedges;
+extern cvar_t *sw_maxsurfs;
+extern cvar_t *sw_mipcap;
+extern cvar_t *sw_mipscale;
+extern cvar_t *sw_mode;
+extern cvar_t *sw_reportsurfout;
+extern cvar_t *sw_reportedgeout;
+extern cvar_t *sw_stipplealpha;
+extern cvar_t *sw_surfcacheoverride;
+extern cvar_t *sw_waterwarp;
+
+extern cvar_t *r_fullbright;
+extern cvar_t *r_lefthand;
+extern cvar_t *r_drawentities;
+extern cvar_t *r_drawworld;
+extern cvar_t *r_dspeeds;
+extern cvar_t *r_lerpmodels;
+
+extern cvar_t *r_speeds;
+
+extern cvar_t *r_lightlevel; //FIXME HACK
+
+extern cvar_t *vid_fullscreen;
+extern cvar_t *vid_gamma;
+
+
+extern clipplane_t view_clipplanes[4];
+extern int *pfrustum_indexes[4];
+
+
+//=============================================================================
+
+void R_RenderWorld (void);
+
+//=============================================================================
+
+extern mplane_t screenedge[4];
+
+extern vec3_t r_origin;
+
+extern entity_t r_worldentity;
+extern model_t *currentmodel;
+extern entity_t *currententity;
+extern vec3_t modelorg;
+extern vec3_t r_entorigin;
+
+extern float verticalFieldOfView;
+extern float xOrigin, yOrigin;
+
+extern int r_visframecount;
+
+extern msurface_t *r_alpha_surfaces;
+
+//=============================================================================
+
+void R_ClearPolyList (void);
+void R_DrawPolyList (void);
+
+//
+// current entity info
+//
+extern qboolean insubmodel;
+
+void R_DrawAlphaSurfaces( void );
+
+void R_DrawSprite (void);
+void R_DrawBeam( entity_t *e );
+
+void R_RenderFace (msurface_t *fa, int clipflags);
+void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf);
+void R_TransformPlane (mplane_t *p, float *normal, float *dist);
+void R_TransformFrustum (void);
+void R_DrawSurfaceBlock16 (void);
+void R_DrawSurfaceBlock8 (void);
+
+#if id386
+
+void R_DrawSurfaceBlock8_mip0 (void);
+void R_DrawSurfaceBlock8_mip1 (void);
+void R_DrawSurfaceBlock8_mip2 (void);
+void R_DrawSurfaceBlock8_mip3 (void);
+
+#endif
+
+void R_GenSkyTile (void *pdest);
+void R_GenSkyTile16 (void *pdest);
+void R_Surf8Patch (void);
+void R_Surf16Patch (void);
+void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode);
+void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode);
+
+void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
+surf_t *R_GetSurf (void);
+void R_AliasDrawModel (void);
+void R_BeginEdgeFrame (void);
+void R_ScanEdges (void);
+void D_DrawSurfaces (void);
+void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist);
+void R_StepActiveU (edge_t *pedge);
+void R_RemoveEdges (edge_t *pedge);
+void R_PushDlights (model_t *model);
+
+extern void R_Surf8Start (void);
+extern void R_Surf8End (void);
+extern void R_Surf16Start (void);
+extern void R_Surf16End (void);
+extern void R_EdgeCodeStart (void);
+extern void R_EdgeCodeEnd (void);
+
+extern void R_RotateBmodel (void);
+
+extern int c_faceclip;
+extern int r_polycount;
+extern int r_wholepolycount;
+
+extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
+
+extern fixed16_t sadjust, tadjust;
+extern fixed16_t bbextents, bbextentt;
+
+extern mvertex_t *r_ptverts, *r_ptvertsmax;
+
+extern float entity_rotation[3][3];
+
+extern int r_currentkey;
+extern int r_currentbkey;
+
+void R_InitTurb (void);
+
+void R_DrawParticles (void);
+void R_SurfacePatch (void);
+
+extern int r_amodels_drawn;
+extern edge_t *auxedges;
+extern int r_numallocatededges;
+extern edge_t *r_edges, *edge_p, *edge_max;
+
+extern edge_t *newedges[MAXHEIGHT];
+extern edge_t *removeedges[MAXHEIGHT];
+
+// FIXME: make stack vars when debugging done
+extern edge_t edge_head;
+extern edge_t edge_tail;
+extern edge_t edge_aftertail;
+
+extern int r_aliasblendcolor;
+
+extern float aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
+
+extern int r_outofsurfaces;
+extern int r_outofedges;
+
+extern mvertex_t *r_pcurrentvertbase;
+extern int r_maxvalidedgeoffset;
+
+typedef struct
+{
+ finalvert_t *a, *b, *c;
+} aliastriangleparms_t;
+
+extern aliastriangleparms_t aliastriangleparms;
+
+void R_DrawTriangle( void );
+//void R_DrawTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2);
+void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2);
+
+
+extern float r_time1;
+extern float da_time1, da_time2;
+extern float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
+extern float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2;
+extern int r_frustum_indexes[4*6];
+extern int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs;
+extern qboolean r_surfsonstack;
+
+extern mleaf_t *r_viewleaf;
+extern int r_viewcluster, r_oldviewcluster;
+
+extern int r_clipflags;
+extern int r_dlightframecount;
+extern qboolean r_fov_greater_than_90;
+
+extern image_t *r_notexture_mip;
+extern model_t *r_worldmodel;
+
+void R_PrintAliasStats (void);
+void R_PrintTimes (void);
+void R_PrintDSpeeds (void);
+void R_AnimateLight (void);
+void R_LightPoint (vec3_t p, vec3_t color);
+void R_SetupFrame (void);
+void R_cshift_f (void);
+void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1);
+void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip);
+void R_SplitEntityOnNode2 (mnode_t *node);
+
+extern refdef_t r_newrefdef;
+
+extern surfcache_t *sc_rover, *sc_base;
+
+extern void *colormap;
+
+//====================================================================
+
+float R_DLightPoint (vec3_t p);
+
+void R_NewMap (void);
+void R_Register (void);
+void R_UnRegister (void);
+void Draw_InitLocal (void);
+qboolean R_Init( void *hInstance, void *wndProc );
+void R_Shutdown (void);
+void R_InitCaches (void);
+void D_FlushCaches (void);
+
+void R_ScreenShot_f( void );
+void R_BeginRegistration (char *map);
+struct model_s *R_RegisterModel (char *name);
+void R_EndRegistration (void);
+
+void R_RenderFrame (refdef_t *fd);
+
+struct image_s *Draw_FindPic (char *name);
+
+void Draw_GetPicSize (int *w, int *h, char *name);
+void Draw_Pic (int x, int y, char *name);
+void Draw_StretchPic (int x, int y, int w, int h, char *name);
+void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data);
+void Draw_Char (int x, int y, int c);
+void Draw_TileClear (int x, int y, int w, int h, char *name);
+void Draw_Fill (int x, int y, int w, int h, int c);
+void Draw_FadeScreen (void);
+
+void Draw_GetPalette (void);
+
+void R_BeginFrame( float camera_separation );
+
+void R_CinematicSetPalette( const unsigned char *palette );
+
+extern unsigned d_8to24table[256]; // base
+
+void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length);
+void Sys_SetFPCW (void);
+
+void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height);
+
+void R_InitImages (void);
+void R_ShutdownImages (void);
+image_t *R_FindImage (char *name, imagetype_t type);
+void R_FreeUnusedImages (void);
+
+void R_GammaCorrectAndSetPalette( const unsigned char *pal );
+
+extern mtexinfo_t *sky_texinfo[6];
+
+void R_InitSkyBox (void);
+
+typedef struct swstate_s
+{
+ qboolean fullscreen;
+ int prev_mode; // last valid SW mode
+
+ byte gammatable[256];
+ byte currentpalette[1024];
+
+} swstate_t;
+
+void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha );
+
+extern swstate_t sw_state;
+
+/*
+====================================================================
+
+IMPORTED FUNCTIONS
+
+====================================================================
+*/
+
+extern refimport_t ri;
+
+/*
+====================================================================
+
+IMPLEMENTATION FUNCTIONS
+
+====================================================================
+*/
+
+void SWimp_BeginFrame( float camera_separation );
+void SWimp_EndFrame (void);
+int SWimp_Init( void *hInstance, void *wndProc );
+void SWimp_SetPalette( const unsigned char *palette);
+void SWimp_Shutdown( void );
+rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen );
+void SWimp_AppActivate( qboolean active );
+
--- /dev/null
+++ b/ref/r_main.c
@@ -1,0 +1,1422 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// r_main.c
+
+#include "r_local.h"
+
+viddef_t vid;
+refimport_t ri;
+
+unsigned d_8to24table[256];
+
+entity_t r_worldentity;
+
+char skyname[MAX_QPATH];
+float skyrotate;
+vec3_t skyaxis;
+image_t *sky_images[6];
+
+refdef_t r_newrefdef;
+model_t *currentmodel;
+
+model_t *r_worldmodel;
+
+byte r_warpbuffer[WARP_WIDTH * WARP_HEIGHT];
+
+swstate_t sw_state;
+
+void *colormap;
+vec3_t viewlightvec;
+alight_t r_viewlighting = {128, 192, viewlightvec};
+float r_time1;
+int r_numallocatededges;
+float r_aliasuvscale = 1.0;
+int r_outofsurfaces;
+int r_outofedges;
+
+qboolean r_dowarp;
+
+mvertex_t *r_pcurrentvertbase;
+
+int c_surf;
+int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs;
+qboolean r_surfsonstack;
+int r_clipflags;
+
+//
+// view origin
+//
+vec3_t vup, base_vup;
+vec3_t vpn, base_vpn;
+vec3_t vright, base_vright;
+vec3_t r_origin;
+
+//
+// screen size info
+//
+oldrefdef_t r_refdef;
+float xcenter, ycenter;
+float xscale, yscale;
+float xscaleinv, yscaleinv;
+float xscaleshrink, yscaleshrink;
+float aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
+
+int r_screenwidth;
+
+float verticalFieldOfView;
+float xOrigin, yOrigin;
+
+mplane_t screenedge[4];
+
+//
+// refresh flags
+//
+int r_framecount = 1; // so frame counts initialized to 0 don't match
+int r_visframecount;
+int d_spanpixcount;
+int r_polycount;
+int r_drawnpolycount;
+int r_wholepolycount;
+
+int *pfrustum_indexes[4];
+int r_frustum_indexes[4*6];
+
+mleaf_t *r_viewleaf;
+int r_viewcluster, r_oldviewcluster;
+
+image_t *r_notexture_mip;
+
+float da_time1, da_time2, dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
+float se_time1, se_time2, de_time1, de_time2;
+
+void R_MarkLeaves (void);
+
+cvar_t *r_lefthand;
+cvar_t *sw_aliasstats;
+cvar_t *sw_allow_modex;
+cvar_t *sw_clearcolor;
+cvar_t *sw_drawflat;
+cvar_t *sw_draworder;
+cvar_t *sw_maxedges;
+cvar_t *sw_maxsurfs;
+cvar_t *sw_mode;
+cvar_t *sw_reportedgeout;
+cvar_t *sw_reportsurfout;
+cvar_t *sw_stipplealpha;
+cvar_t *sw_surfcacheoverride;
+cvar_t *sw_waterwarp;
+
+cvar_t *r_drawworld;
+cvar_t *r_drawentities;
+cvar_t *r_dspeeds;
+cvar_t *r_fullbright;
+cvar_t *r_lerpmodels;
+cvar_t *r_novis;
+
+cvar_t *r_speeds;
+cvar_t *r_lightlevel; //FIXME HACK
+
+cvar_t *vid_fullscreen;
+cvar_t *vid_gamma;
+
+//PGM
+cvar_t *sw_lockpvs;
+//PGM
+
+#define STRINGER(x) "x"
+
+
+#if !id386
+
+// r_vars.c
+
+// all global and static refresh variables are collected in a contiguous block
+// to avoid cache conflicts.
+
+//-------------------------------------------------------
+// global refresh variables
+//-------------------------------------------------------
+
+// FIXME: make into one big structure, like cl or sv
+// FIXME: do separately for refresh engine and driver
+
+
+// d_vars.c
+
+// all global and static refresh variables are collected in a contiguous block
+// to avoid cache conflicts.
+
+//-------------------------------------------------------
+// global refresh variables
+//-------------------------------------------------------
+
+// FIXME: make into one big structure, like cl or sv
+// FIXME: do separately for refresh engine and driver
+
+float d_sdivzstepu, d_tdivzstepu, d_zistepu;
+float d_sdivzstepv, d_tdivzstepv, d_zistepv;
+float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
+
+fixed16_t sadjust, tadjust, bbextents, bbextentt;
+
+pixel_t *cacheblock;
+int cachewidth;
+pixel_t *d_viewbuffer;
+short *d_pzbuffer;
+unsigned int d_zrowbytes;
+unsigned int d_zwidth;
+
+
+#endif // !id386
+
+byte r_notexture_buffer[1024];
+
+/*
+==================
+R_InitTextures
+==================
+*/
+void R_InitTextures (void)
+{
+ int x,y, m;
+ byte *dest;
+
+// create a simple checkerboard texture for the default
+ r_notexture_mip = (image_t *)&r_notexture_buffer;
+
+ r_notexture_mip->width = r_notexture_mip->height = 16;
+ r_notexture_mip->pixels[0] = &r_notexture_buffer[sizeof(image_t)];
+ r_notexture_mip->pixels[1] = r_notexture_mip->pixels[0] + 16*16;
+ r_notexture_mip->pixels[2] = r_notexture_mip->pixels[1] + 8*8;
+ r_notexture_mip->pixels[3] = r_notexture_mip->pixels[2] + 4*4;
+
+ for (m=0 ; m<4 ; m++)
+ {
+ dest = r_notexture_mip->pixels[m];
+ for (y=0 ; y< (16>>m) ; y++)
+ for (x=0 ; x< (16>>m) ; x++)
+ {
+ if ( (y< (8>>m) ) ^ (x< (8>>m) ) )
+
+ *dest++ = 0;
+ else
+ *dest++ = 0xff;
+ }
+ }
+}
+
+
+/*
+================
+R_InitTurb
+================
+*/
+void R_InitTurb (void)
+{
+ int i;
+
+ for (i=0 ; i<1280 ; i++)
+ {
+ sintable[i] = AMP + sin(i*3.14159*2/CYCLE)*AMP;
+ intsintable[i] = AMP2 + sin(i*3.14159*2/CYCLE)*AMP2; // AMP2, not 20
+ blanktable[i] = 0; //PGM
+ }
+}
+
+void R_ImageList_f( void );
+
+void R_Register (void)
+{
+ sw_aliasstats = ri.Cvar_Get ("sw_polymodelstats", "0", 0);
+ sw_allow_modex = ri.Cvar_Get( "sw_allow_modex", "1", CVAR_ARCHIVE );
+ sw_clearcolor = ri.Cvar_Get ("sw_clearcolor", "2", 0);
+ sw_drawflat = ri.Cvar_Get ("sw_drawflat", "0", 0);
+ sw_draworder = ri.Cvar_Get ("sw_draworder", "0", 0);
+ sw_maxedges = ri.Cvar_Get ("sw_maxedges", STRINGER(MAXSTACKSURFACES), 0);
+ sw_maxsurfs = ri.Cvar_Get ("sw_maxsurfs", "0", 0);
+ sw_mipcap = ri.Cvar_Get ("sw_mipcap", "0", 0);
+ sw_mipscale = ri.Cvar_Get ("sw_mipscale", "1", 0);
+ sw_reportedgeout = ri.Cvar_Get ("sw_reportedgeout", "0", 0);
+ sw_reportsurfout = ri.Cvar_Get ("sw_reportsurfout", "0", 0);
+ sw_stipplealpha = ri.Cvar_Get( "sw_stipplealpha", "0", CVAR_ARCHIVE );
+ sw_surfcacheoverride = ri.Cvar_Get ("sw_surfcacheoverride", "0", 0);
+ sw_waterwarp = ri.Cvar_Get ("sw_waterwarp", "1", 0);
+ sw_mode = ri.Cvar_Get( "sw_mode", "0", CVAR_ARCHIVE );
+
+ r_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
+ r_speeds = ri.Cvar_Get ("r_speeds", "0", 0);
+ r_fullbright = ri.Cvar_Get ("r_fullbright", "0", 0);
+ r_drawentities = ri.Cvar_Get ("r_drawentities", "1", 0);
+ r_drawworld = ri.Cvar_Get ("r_drawworld", "1", 0);
+ r_dspeeds = ri.Cvar_Get ("r_dspeeds", "0", 0);
+ r_lightlevel = ri.Cvar_Get ("r_lightlevel", "0", 0);
+ r_lerpmodels = ri.Cvar_Get( "r_lerpmodels", "1", 0 );
+ r_novis = ri.Cvar_Get( "r_novis", "0", 0 );
+
+ vid_fullscreen = ri.Cvar_Get( "vid_fullscreen", "0", CVAR_ARCHIVE );
+ vid_gamma = ri.Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE );
+
+ ri.Cmd_AddCommand ("modellist", Mod_Modellist_f);
+ ri.Cmd_AddCommand( "screenshot", R_ScreenShot_f );
+ ri.Cmd_AddCommand( "imagelist", R_ImageList_f );
+
+ sw_mode->modified = true; // force us to do mode specific stuff later
+ vid_gamma->modified = true; // force us to rebuild the gamma table later
+
+//PGM
+ sw_lockpvs = ri.Cvar_Get ("sw_lockpvs", "0", 0);
+//PGM
+}
+
+void R_UnRegister (void)
+{
+ ri.Cmd_RemoveCommand( "screenshot" );
+ ri.Cmd_RemoveCommand ("modellist");
+ ri.Cmd_RemoveCommand( "imagelist" );
+}
+
+/*
+===============
+R_Init
+===============
+*/
+qboolean R_Init( void *hInstance, void *wndProc )
+{
+ R_InitImages ();
+ Mod_Init ();
+ Draw_InitLocal ();
+ R_InitTextures ();
+
+ R_InitTurb ();
+
+ view_clipplanes[0].leftedge = true;
+ view_clipplanes[1].rightedge = true;
+ view_clipplanes[1].leftedge = view_clipplanes[2].leftedge =
+ view_clipplanes[3].leftedge = false;
+ view_clipplanes[0].rightedge = view_clipplanes[2].rightedge =
+ view_clipplanes[3].rightedge = false;
+
+ r_refdef.xOrigin = XCENTERING;
+ r_refdef.yOrigin = YCENTERING;
+
+// TODO: collect 386-specific code in one place
+#if id386
+ Sys_MakeCodeWriteable ((long)R_EdgeCodeStart,
+ (long)R_EdgeCodeEnd - (long)R_EdgeCodeStart);
+ Sys_SetFPCW (); // get bit masks for FPCW (FIXME: is this id386?)
+#endif // id386
+
+ r_aliasuvscale = 1.0;
+
+ R_Register ();
+ Draw_GetPalette ();
+ SWimp_Init( hInstance, wndProc );
+
+ // create the window
+ R_BeginFrame( 0 );
+
+ ri.Con_Printf (PRINT_ALL, "ref_soft version: "REF_VERSION"\n");
+
+ return true;
+}
+
+/*
+===============
+R_Shutdown
+===============
+*/
+void R_Shutdown (void)
+{
+ // free z buffer
+ if (d_pzbuffer)
+ {
+ free (d_pzbuffer);
+ d_pzbuffer = NULL;
+ }
+ // free surface cache
+ if (sc_base)
+ {
+ D_FlushCaches ();
+ free (sc_base);
+ sc_base = NULL;
+ }
+
+ // free colormap
+ if (vid.colormap)
+ {
+ free (vid.colormap);
+ vid.colormap = NULL;
+ }
+ R_UnRegister ();
+ Mod_FreeAll ();
+ R_ShutdownImages ();
+
+ SWimp_Shutdown();
+}
+
+/*
+===============
+R_NewMap
+===============
+*/
+void R_NewMap (void)
+{
+ r_viewcluster = -1;
+
+ r_cnumsurfs = sw_maxsurfs->value;
+
+ if (r_cnumsurfs <= MINSURFACES)
+ r_cnumsurfs = MINSURFACES;
+
+ if (r_cnumsurfs > NUMSTACKSURFACES)
+ {
+ surfaces = malloc (r_cnumsurfs * sizeof(surf_t));
+ surface_p = surfaces;
+ surf_max = &surfaces[r_cnumsurfs];
+ r_surfsonstack = false;
+ // surface 0 doesn't really exist; it's just a dummy because index 0
+ // is used to indicate no edge attached to surface
+ surfaces--;
+ R_SurfacePatch ();
+ }
+ else
+ {
+ r_surfsonstack = true;
+ }
+
+ r_maxedgesseen = 0;
+ r_maxsurfsseen = 0;
+
+ r_numallocatededges = sw_maxedges->value;
+
+ if (r_numallocatededges < MINEDGES)
+ r_numallocatededges = MINEDGES;
+
+ if (r_numallocatededges <= NUMSTACKEDGES)
+ {
+ auxedges = NULL;
+ }
+ else
+ {
+ auxedges = malloc (r_numallocatededges * sizeof(edge_t));
+ }
+}
+
+
+/*
+===============
+R_MarkLeaves
+
+Mark the leaves and nodes that are in the PVS for the current
+cluster
+===============
+*/
+void R_MarkLeaves (void)
+{
+ byte *vis;
+ mnode_t *node;
+ int i;
+ mleaf_t *leaf;
+ int cluster;
+
+ if (r_oldviewcluster == r_viewcluster && !r_novis->value && r_viewcluster != -1)
+ return;
+
+ // development aid to let you run around and see exactly where
+ // the pvs ends
+ if (sw_lockpvs->value)
+ return;
+
+ r_visframecount++;
+ r_oldviewcluster = r_viewcluster;
+
+ if (r_novis->value || r_viewcluster == -1 || !r_worldmodel->vis)
+ {
+ // mark everything
+ for (i=0 ; i<r_worldmodel->numleafs ; i++)
+ r_worldmodel->leafs[i].visframe = r_visframecount;
+ for (i=0 ; i<r_worldmodel->numnodes ; i++)
+ r_worldmodel->nodes[i].visframe = r_visframecount;
+ return;
+ }
+
+ vis = Mod_ClusterPVS (r_viewcluster, r_worldmodel);
+
+ for (i=0,leaf=r_worldmodel->leafs ; i<r_worldmodel->numleafs ; i++, leaf++)
+ {
+ cluster = leaf->cluster;
+ if (cluster == -1)
+ continue;
+ if (vis[cluster>>3] & (1<<(cluster&7)))
+ {
+ node = (mnode_t *)leaf;
+ do
+ {
+ if (node->visframe == r_visframecount)
+ break;
+ node->visframe = r_visframecount;
+ node = node->parent;
+ } while (node);
+ }
+ }
+
+#if 0
+ for (i=0 ; i<r_worldmodel->vis->numclusters ; i++)
+ {
+ if (vis[i>>3] & (1<<(i&7)))
+ {
+ node = (mnode_t *)&r_worldmodel->leafs[i]; // FIXME: cluster
+ do
+ {
+ if (node->visframe == r_visframecount)
+ break;
+ node->visframe = r_visframecount;
+ node = node->parent;
+ } while (node);
+ }
+ }
+#endif
+}
+
+/*
+** R_DrawNullModel
+**
+** IMPLEMENT THIS!
+*/
+void R_DrawNullModel( void )
+{
+}
+
+/*
+=============
+R_DrawEntitiesOnList
+=============
+*/
+void R_DrawEntitiesOnList (void)
+{
+ int i;
+ qboolean translucent_entities = false;
+
+ if (!r_drawentities->value)
+ return;
+
+ // all bmodels have already been drawn by the edge list
+ for (i=0 ; i<r_newrefdef.num_entities ; i++)
+ {
+ currententity = &r_newrefdef.entities[i];
+
+ if ( currententity->flags & RF_TRANSLUCENT )
+ {
+ translucent_entities = true;
+ continue;
+ }
+
+ if ( currententity->flags & RF_BEAM )
+ {
+ modelorg[0] = -r_origin[0];
+ modelorg[1] = -r_origin[1];
+ modelorg[2] = -r_origin[2];
+ VectorCopy( vec3_origin, r_entorigin );
+ R_DrawBeam( currententity );
+ }
+ else
+ {
+ currentmodel = currententity->model;
+ if (!currentmodel)
+ {
+ R_DrawNullModel();
+ continue;
+ }
+ VectorCopy (currententity->origin, r_entorigin);
+ VectorSubtract (r_origin, r_entorigin, modelorg);
+
+ switch (currentmodel->type)
+ {
+ case mod_sprite:
+ R_DrawSprite ();
+ break;
+
+ case mod_alias:
+ R_AliasDrawModel ();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if ( !translucent_entities )
+ return;
+
+ for (i=0 ; i<r_newrefdef.num_entities ; i++)
+ {
+ currententity = &r_newrefdef.entities[i];
+
+ if ( !( currententity->flags & RF_TRANSLUCENT ) )
+ continue;
+
+ if ( currententity->flags & RF_BEAM )
+ {
+ modelorg[0] = -r_origin[0];
+ modelorg[1] = -r_origin[1];
+ modelorg[2] = -r_origin[2];
+ VectorCopy( vec3_origin, r_entorigin );
+ R_DrawBeam( currententity );
+ }
+ else
+ {
+ currentmodel = currententity->model;
+ if (!currentmodel)
+ {
+ R_DrawNullModel();
+ continue;
+ }
+ VectorCopy (currententity->origin, r_entorigin);
+ VectorSubtract (r_origin, r_entorigin, modelorg);
+
+ switch (currentmodel->type)
+ {
+ case mod_sprite:
+ R_DrawSprite ();
+ break;
+
+ case mod_alias:
+ R_AliasDrawModel ();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+
+/*
+=============
+R_BmodelCheckBBox
+=============
+*/
+int R_BmodelCheckBBox (float *minmaxs)
+{
+ int i, *pindex, clipflags;
+ vec3_t acceptpt, rejectpt;
+ float d;
+
+ clipflags = 0;
+
+ for (i=0 ; i<4 ; i++)
+ {
+ // generate accept and reject points
+ // FIXME: do with fast look-ups or integer tests based on the sign bit
+ // of the floating point values
+
+ pindex = pfrustum_indexes[i];
+
+ rejectpt[0] = minmaxs[pindex[0]];
+ rejectpt[1] = minmaxs[pindex[1]];
+ rejectpt[2] = minmaxs[pindex[2]];
+
+ d = DotProduct (rejectpt, view_clipplanes[i].normal);
+ d -= view_clipplanes[i].dist;
+
+ if (d <= 0)
+ return BMODEL_FULLY_CLIPPED;
+
+ acceptpt[0] = minmaxs[pindex[3+0]];
+ acceptpt[1] = minmaxs[pindex[3+1]];
+ acceptpt[2] = minmaxs[pindex[3+2]];
+
+ d = DotProduct (acceptpt, view_clipplanes[i].normal);
+ d -= view_clipplanes[i].dist;
+
+ if (d <= 0)
+ clipflags |= (1<<i);
+ }
+
+ return clipflags;
+}
+
+
+/*
+===================
+R_FindTopnode
+
+Find the first node that splits the given box
+===================
+*/
+mnode_t *R_FindTopnode (vec3_t mins, vec3_t maxs)
+{
+ mplane_t *splitplane;
+ int sides;
+ mnode_t *node;
+
+ node = r_worldmodel->nodes;
+
+ while (1)
+ {
+ if (node->visframe != r_visframecount)
+ return NULL; // not visible at all
+
+ if (node->contents != CONTENTS_NODE)
+ {
+ if (node->contents != CONTENTS_SOLID)
+ return node; // we've reached a non-solid leaf, so it's
+ // visible and not BSP clipped
+ return NULL; // in solid, so not visible
+ }
+
+ splitplane = node->plane;
+ sides = BOX_ON_PLANE_SIDE(mins, maxs, (cplane_t *)splitplane);
+
+ if (sides == 3)
+ return node; // this is the splitter
+
+ // not split yet; recurse down the contacted side
+ if (sides & 1)
+ node = node->children[0];
+ else
+ node = node->children[1];
+ }
+}
+
+
+/*
+=============
+RotatedBBox
+
+Returns an axially aligned box that contains the input box at the given rotation
+=============
+*/
+void RotatedBBox (vec3_t mins, vec3_t maxs, vec3_t angles, vec3_t tmins, vec3_t tmaxs)
+{
+ vec3_t tmp, v;
+ int i, j;
+ vec3_t forward, right, up;
+
+ if (!angles[0] && !angles[1] && !angles[2])
+ {
+ VectorCopy (mins, tmins);
+ VectorCopy (maxs, tmaxs);
+ return;
+ }
+
+ for (i=0 ; i<3 ; i++)
+ {
+ tmins[i] = 99999;
+ tmaxs[i] = -99999;
+ }
+
+ AngleVectors (angles, forward, right, up);
+
+ for ( i = 0; i < 8; i++ )
+ {
+ if ( i & 1 )
+ tmp[0] = mins[0];
+ else
+ tmp[0] = maxs[0];
+
+ if ( i & 2 )
+ tmp[1] = mins[1];
+ else
+ tmp[1] = maxs[1];
+
+ if ( i & 4 )
+ tmp[2] = mins[2];
+ else
+ tmp[2] = maxs[2];
+
+
+ VectorScale (forward, tmp[0], v);
+ VectorMA (v, -tmp[1], right, v);
+ VectorMA (v, tmp[2], up, v);
+
+ for (j=0 ; j<3 ; j++)
+ {
+ if (v[j] < tmins[j])
+ tmins[j] = v[j];
+ if (v[j] > tmaxs[j])
+ tmaxs[j] = v[j];
+ }
+ }
+}
+
+/*
+=============
+R_DrawBEntitiesOnList
+=============
+*/
+void R_DrawBEntitiesOnList (void)
+{
+ int i, clipflags;
+ vec3_t oldorigin;
+ vec3_t mins, maxs;
+ float minmaxs[6];
+ mnode_t *topnode;
+
+ if (!r_drawentities->value)
+ return;
+
+ VectorCopy (modelorg, oldorigin);
+ insubmodel = true;
+ r_dlightframecount = r_framecount;
+
+ for (i=0 ; i<r_newrefdef.num_entities ; i++)
+ {
+ currententity = &r_newrefdef.entities[i];
+ currentmodel = currententity->model;
+ if (!currentmodel)
+ continue;
+ if (currentmodel->nummodelsurfaces == 0)
+ continue; // clip brush only
+ if ( currententity->flags & RF_BEAM )
+ continue;
+ if (currentmodel->type != mod_brush)
+ continue;
+ // see if the bounding box lets us trivially reject, also sets
+ // trivial accept status
+ RotatedBBox (currentmodel->mins, currentmodel->maxs,
+ currententity->angles, mins, maxs);
+ VectorAdd (mins, currententity->origin, minmaxs);
+ VectorAdd (maxs, currententity->origin, (minmaxs+3));
+
+ clipflags = R_BmodelCheckBBox (minmaxs);
+ if (clipflags == BMODEL_FULLY_CLIPPED)
+ continue; // off the edge of the screen
+
+ topnode = R_FindTopnode (minmaxs, minmaxs+3);
+ if (!topnode)
+ continue; // no part in a visible leaf
+
+ VectorCopy (currententity->origin, r_entorigin);
+ VectorSubtract (r_origin, r_entorigin, modelorg);
+
+ r_pcurrentvertbase = currentmodel->vertexes;
+
+ // FIXME: stop transforming twice
+ R_RotateBmodel ();
+
+ // calculate dynamic lighting for bmodel
+ R_PushDlights (currentmodel);
+
+ if (topnode->contents == CONTENTS_NODE)
+ {
+ // not a leaf; has to be clipped to the world BSP
+ r_clipflags = clipflags;
+ R_DrawSolidClippedSubmodelPolygons (currentmodel, topnode);
+ }
+ else
+ {
+ // falls entirely in one leaf, so we just put all the
+ // edges in the edge list and let 1/z sorting handle
+ // drawing order
+ R_DrawSubmodelPolygons (currentmodel, clipflags, topnode);
+ }
+
+ // put back world rotation and frustum clipping
+ // FIXME: R_RotateBmodel should just work off base_vxx
+ VectorCopy (base_vpn, vpn);
+ VectorCopy (base_vup, vup);
+ VectorCopy (base_vright, vright);
+ VectorCopy (oldorigin, modelorg);
+ R_TransformFrustum ();
+ }
+
+ insubmodel = false;
+}
+
+
+/*
+================
+R_EdgeDrawing
+================
+*/
+void R_EdgeDrawing (void)
+{
+ edge_t ledges[NUMSTACKEDGES +
+ ((CACHE_SIZE - 1) / sizeof(edge_t)) + 1];
+ surf_t lsurfs[NUMSTACKSURFACES +
+ ((CACHE_SIZE - 1) / sizeof(surf_t)) + 1];
+
+ if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
+ return;
+
+ if (auxedges)
+ {
+ r_edges = auxedges;
+ }
+ else
+ {
+ r_edges = (edge_t *)
+ (((long)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+ }
+
+ if (r_surfsonstack)
+ {
+ surfaces = (surf_t *)
+ (((long)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+ surf_max = &surfaces[r_cnumsurfs];
+ // surface 0 doesn't really exist; it's just a dummy because index 0
+ // is used to indicate no edge attached to surface
+ surfaces--;
+ R_SurfacePatch ();
+ }
+
+ R_BeginEdgeFrame ();
+
+ if (r_dspeeds->value)
+ {
+ rw_time1 = Sys_Milliseconds ();
+ }
+
+ R_RenderWorld ();
+
+ if (r_dspeeds->value)
+ {
+ rw_time2 = Sys_Milliseconds ();
+ db_time1 = rw_time2;
+ }
+
+ R_DrawBEntitiesOnList ();
+
+ if (r_dspeeds->value)
+ {
+ db_time2 = Sys_Milliseconds ();
+ se_time1 = db_time2;
+ }
+
+ R_ScanEdges ();
+}
+
+//=======================================================================
+
+
+/*
+=============
+R_CalcPalette
+
+=============
+*/
+void R_CalcPalette (void)
+{
+ static qboolean modified;
+ byte palette[256][4], *in, *out;
+ int i, j;
+ float alpha, one_minus_alpha;
+ vec3_t premult;
+ int v;
+
+ alpha = r_newrefdef.blend[3];
+ if (alpha <= 0)
+ {
+ if (modified)
+ { // set back to default
+ modified = false;
+ R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
+ return;
+ }
+ return;
+ }
+
+ modified = true;
+ if (alpha > 1)
+ alpha = 1;
+
+ premult[0] = r_newrefdef.blend[0]*alpha*255;
+ premult[1] = r_newrefdef.blend[1]*alpha*255;
+ premult[2] = r_newrefdef.blend[2]*alpha*255;
+
+ one_minus_alpha = (1.0 - alpha);
+
+ in = (byte *)d_8to24table;
+ out = palette[0];
+ for (i=0 ; i<256 ; i++, in+=4, out+=4)
+ {
+ for (j=0 ; j<3 ; j++)
+ {
+ v = premult[j] + one_minus_alpha * in[j];
+ if (v > 255)
+ v = 255;
+ out[j] = v;
+ }
+ out[3] = 255;
+ }
+
+ R_GammaCorrectAndSetPalette( ( const unsigned char * ) palette[0] );
+// SWimp_SetPalette( palette[0] );
+}
+
+//=======================================================================
+
+void R_SetLightLevel (void)
+{
+ vec3_t light;
+
+ if ((r_newrefdef.rdflags & RDF_NOWORLDMODEL) || (!r_drawentities->value) || (!currententity))
+ {
+ r_lightlevel->value = 150.0;
+ return;
+ }
+
+ // save off light value for server to look at (BIG HACK!)
+ R_LightPoint (r_newrefdef.vieworg, light);
+ r_lightlevel->value = 150.0 * light[0];
+}
+
+
+/*
+@@@@@@@@@@@@@@@@
+R_RenderFrame
+
+@@@@@@@@@@@@@@@@
+*/
+void R_RenderFrame (refdef_t *fd)
+{
+ r_newrefdef = *fd;
+
+ if (!r_worldmodel && !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
+ ri.Sys_Error (ERR_FATAL,"R_RenderView: NULL worldmodel");
+
+ VectorCopy (fd->vieworg, r_refdef.vieworg);
+ VectorCopy (fd->viewangles, r_refdef.viewangles);
+
+ if (r_speeds->value || r_dspeeds->value)
+ r_time1 = Sys_Milliseconds ();
+
+ R_SetupFrame ();
+
+ R_MarkLeaves (); // done here so we know if we're in water
+
+ R_PushDlights (r_worldmodel);
+
+ R_EdgeDrawing ();
+
+ if (r_dspeeds->value)
+ {
+ se_time2 = Sys_Milliseconds ();
+ de_time1 = se_time2;
+ }
+
+ R_DrawEntitiesOnList ();
+
+ if (r_dspeeds->value)
+ {
+ de_time2 = Sys_Milliseconds ();
+ dp_time1 = Sys_Milliseconds ();
+ }
+
+ R_DrawParticles ();
+
+ if (r_dspeeds->value)
+ dp_time2 = Sys_Milliseconds ();
+
+ R_DrawAlphaSurfaces();
+
+ R_SetLightLevel ();
+
+ if (r_dowarp)
+ D_WarpScreen ();
+
+ if (r_dspeeds->value)
+ da_time1 = Sys_Milliseconds ();
+
+ if (r_dspeeds->value)
+ da_time2 = Sys_Milliseconds ();
+
+ R_CalcPalette ();
+
+ if (sw_aliasstats->value)
+ R_PrintAliasStats ();
+
+ if (r_speeds->value)
+ R_PrintTimes ();
+
+ if (r_dspeeds->value)
+ R_PrintDSpeeds ();
+
+ if (sw_reportsurfout->value && r_outofsurfaces)
+ ri.Con_Printf (PRINT_ALL,"Short %d surfaces\n", r_outofsurfaces);
+
+ if (sw_reportedgeout->value && r_outofedges)
+ ri.Con_Printf (PRINT_ALL,"Short roughly %d edges\n", r_outofedges * 2 / 3);
+}
+
+/*
+** R_InitGraphics
+*/
+void R_InitGraphics( int width, int height )
+{
+ vid.width = width;
+ vid.height = height;
+
+ // free z buffer
+ if ( d_pzbuffer )
+ {
+ free( d_pzbuffer );
+ d_pzbuffer = NULL;
+ }
+
+ // free surface cache
+ if ( sc_base )
+ {
+ D_FlushCaches ();
+ free( sc_base );
+ sc_base = NULL;
+ }
+
+ d_pzbuffer = malloc(vid.width*vid.height*2);
+
+ R_InitCaches ();
+
+ R_GammaCorrectAndSetPalette( ( const unsigned char *) d_8to24table );
+}
+
+/*
+** R_BeginFrame
+*/
+void R_BeginFrame( float camera_separation )
+{
+ extern void Draw_BuildGammaTable( void );
+
+ /*
+ ** rebuild the gamma correction palette if necessary
+ */
+ if ( vid_gamma->modified )
+ {
+ Draw_BuildGammaTable();
+ R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
+
+ vid_gamma->modified = false;
+ }
+
+ while ( sw_mode->modified || vid_fullscreen->modified )
+ {
+ rserr_t err;
+
+ /*
+ ** if this returns rserr_invalid_fullscreen then it set the mode but not as a
+ ** fullscreen mode, e.g. 320x200 on a system that doesn't support that res
+ */
+ if ( ( err = SWimp_SetMode( &vid.width, &vid.height, sw_mode->value, vid_fullscreen->value ) ) == rserr_ok )
+ {
+ R_InitGraphics( vid.width, vid.height );
+
+ sw_state.prev_mode = sw_mode->value;
+ vid_fullscreen->modified = false;
+ sw_mode->modified = false;
+ }
+ else
+ {
+ if ( err == rserr_invalid_mode )
+ {
+ ri.Cvar_SetValue( "sw_mode", sw_state.prev_mode );
+ ri.Con_Printf( PRINT_ALL, "ref_soft::R_BeginFrame() - could not set mode\n" );
+ }
+ else if ( err == rserr_invalid_fullscreen )
+ {
+ R_InitGraphics( vid.width, vid.height );
+
+ ri.Cvar_SetValue( "vid_fullscreen", 0);
+ ri.Con_Printf( PRINT_ALL, "ref_soft::R_BeginFrame() - fullscreen unavailable in this mode\n" );
+ sw_state.prev_mode = sw_mode->value;
+// vid_fullscreen->modified = false;
+// sw_mode->modified = false;
+ }
+ else
+ {
+ ri.Sys_Error( ERR_FATAL, "ref_soft::R_BeginFrame() - catastrophic mode change failure\n" );
+ }
+ }
+ }
+}
+
+/*
+** R_GammaCorrectAndSetPalette
+*/
+void R_GammaCorrectAndSetPalette( const unsigned char *palette )
+{
+ int i;
+
+ for ( i = 0; i < 256; i++ )
+ {
+ sw_state.currentpalette[i*4+0] = sw_state.gammatable[palette[i*4+0]];
+ sw_state.currentpalette[i*4+1] = sw_state.gammatable[palette[i*4+1]];
+ sw_state.currentpalette[i*4+2] = sw_state.gammatable[palette[i*4+2]];
+ }
+
+ SWimp_SetPalette( sw_state.currentpalette );
+}
+
+/*
+** R_CinematicSetPalette
+*/
+void R_CinematicSetPalette( const unsigned char *palette )
+{
+ byte palette32[1024];
+ int i, j, w;
+ int *d;
+
+ // clear screen to black to avoid any palette flash
+ w = abs(vid.rowbytes)>>2; // stupid negative pitch win32 stuff...
+ for (i=0 ; i<vid.height ; i++, d+=w)
+ {
+ d = (int *)(vid.buffer + i*vid.rowbytes);
+ for (j=0 ; j<w ; j++)
+ d[j] = 0;
+ }
+ // flush it to the screen
+ SWimp_EndFrame ();
+
+ if ( palette )
+ {
+ for ( i = 0; i < 256; i++ )
+ {
+ palette32[i*4+0] = palette[i*3+0];
+ palette32[i*4+1] = palette[i*3+1];
+ palette32[i*4+2] = palette[i*3+2];
+ palette32[i*4+3] = 0xFF;
+ }
+
+ R_GammaCorrectAndSetPalette( palette32 );
+ }
+ else
+ {
+ R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
+ }
+}
+
+/*
+================
+Draw_BuildGammaTable
+================
+*/
+void Draw_BuildGammaTable (void)
+{
+ int i, inf;
+ float g;
+
+ g = vid_gamma->value;
+
+ if (g == 1.0)
+ {
+ for (i=0 ; i<256 ; i++)
+ sw_state.gammatable[i] = i;
+ return;
+ }
+
+ for (i=0 ; i<256 ; i++)
+ {
+ inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5;
+ if (inf < 0)
+ inf = 0;
+ if (inf > 255)
+ inf = 255;
+ sw_state.gammatable[i] = inf;
+ }
+}
+
+/*
+** R_DrawBeam
+*/
+void R_DrawBeam( entity_t *e )
+{
+#define NUM_BEAM_SEGS 6
+
+ int i;
+
+ vec3_t perpvec;
+ vec3_t direction, normalized_direction;
+ vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
+ vec3_t oldorigin, origin;
+
+ oldorigin[0] = e->oldorigin[0];
+ oldorigin[1] = e->oldorigin[1];
+ oldorigin[2] = e->oldorigin[2];
+
+ origin[0] = e->origin[0];
+ origin[1] = e->origin[1];
+ origin[2] = e->origin[2];
+
+ normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
+ normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
+ normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
+
+ if ( VectorNormalize( normalized_direction ) == 0 )
+ return;
+
+ PerpendicularVector( perpvec, normalized_direction );
+ VectorScale( perpvec, e->frame / 2, perpvec );
+
+ for ( i = 0; i < NUM_BEAM_SEGS; i++ )
+ {
+ RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i );
+ VectorAdd( start_points[i], origin, start_points[i] );
+ VectorAdd( start_points[i], direction, end_points[i] );
+ }
+
+ for ( i = 0; i < NUM_BEAM_SEGS; i++ )
+ {
+ R_IMFlatShadedQuad( start_points[i],
+ end_points[i],
+ end_points[(i+1)%NUM_BEAM_SEGS],
+ start_points[(i+1)%NUM_BEAM_SEGS],
+ e->skinnum & 0xFF,
+ e->alpha );
+ }
+}
+
+
+//===================================================================
+
+/*
+============
+R_SetSky
+============
+*/
+// 3dstudio environment map names
+char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
+int r_skysideimage[6] = {5, 2, 4, 1, 0, 3};
+extern mtexinfo_t r_skytexinfo[6];
+void R_SetSky (char *name, float rotate, vec3_t axis)
+{
+ int i;
+ char pathname[MAX_QPATH];
+
+ strncpy (skyname, name, sizeof(skyname)-1);
+ skyrotate = rotate;
+ VectorCopy (axis, skyaxis);
+
+ for (i=0 ; i<6 ; i++)
+ {
+ Com_sprintf (pathname, sizeof(pathname), "env/%s%s.pcx", skyname, suf[r_skysideimage[i]]);
+ r_skytexinfo[i].image = R_FindImage (pathname, it_sky);
+ }
+}
+
+
+/*
+===============
+Draw_GetPalette
+===============
+*/
+void Draw_GetPalette (void)
+{
+ byte *pal, *out;
+ int i;
+ int r, g, b;
+
+ // get the palette and colormap
+ LoadPCX ("pics/colormap.pcx", &vid.colormap, &pal, NULL, NULL);
+ if (!vid.colormap)
+ ri.Sys_Error (ERR_FATAL, "Couldn't load pics/colormap.pcx");
+ vid.alphamap = vid.colormap + 64*256;
+
+ out = (byte *)d_8to24table;
+ for (i=0 ; i<256 ; i++, out+=4)
+ {
+ r = pal[i*3+0];
+ g = pal[i*3+1];
+ b = pal[i*3+2];
+
+ out[0] = r;
+ out[1] = g;
+ out[2] = b;
+ }
+
+ free (pal);
+}
+
+struct image_s *R_RegisterSkin (char *name);
+
+/*
+@@@@@@@@@@@@@@@@@@@@@
+GetRefAPI
+
+@@@@@@@@@@@@@@@@@@@@@
+*/
+refexport_t GetRefAPI (refimport_t rimp)
+{
+ refexport_t re;
+
+ ri = rimp;
+
+ re.api_version = API_VERSION;
+
+ re.BeginRegistration = R_BeginRegistration;
+ re.RegisterModel = R_RegisterModel;
+ re.RegisterSkin = R_RegisterSkin;
+ re.RegisterPic = Draw_FindPic;
+ re.SetSky = R_SetSky;
+ re.EndRegistration = R_EndRegistration;
+
+ re.RenderFrame = R_RenderFrame;
+
+ re.DrawGetPicSize = Draw_GetPicSize;
+ re.DrawPic = Draw_Pic;
+ re.DrawStretchPic = Draw_StretchPic;
+ re.DrawChar = Draw_Char;
+ re.DrawTileClear = Draw_TileClear;
+ re.DrawFill = Draw_Fill;
+ re.DrawFadeScreen= Draw_FadeScreen;
+
+ re.DrawStretchRaw = Draw_StretchRaw;
+
+ re.Init = R_Init;
+ re.Shutdown = R_Shutdown;
+
+ re.CinematicSetPalette = R_CinematicSetPalette;
+ re.BeginFrame = R_BeginFrame;
+ re.EndFrame = SWimp_EndFrame;
+
+ re.AppActivate = SWimp_AppActivate;
+
+ Swap_Init ();
+
+ return re;
+}
+
+#ifndef REF_HARD_LINKED
+// this is only here so the functions in q_shared.c and q_shwin.c can link
+void Sys_Error (char *error, ...)
+{
+ va_list argptr;
+ char text[1024];
+
+ va_start (argptr, error);
+ vsprintf (text, error, argptr);
+ va_end (argptr);
+
+ ri.Sys_Error (ERR_FATAL, "%s", text);
+}
+
+void Com_Printf (char *fmt, ...)
+{
+ va_list argptr;
+ char text[1024];
+
+ va_start (argptr, fmt);
+ vsprintf (text, fmt, argptr);
+ va_end (argptr);
+
+ ri.Con_Printf (PRINT_ALL, "%s", text);
+}
+
+#endif
--- /dev/null
+++ b/ref/r_misc.c
@@ -1,0 +1,670 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// r_misc.c
+
+#include "r_local.h"
+
+#define NUM_MIPS 4
+
+cvar_t *sw_mipcap;
+cvar_t *sw_mipscale;
+
+surfcache_t *d_initial_rover;
+qboolean d_roverwrapped;
+int d_minmip;
+float d_scalemip[NUM_MIPS-1];
+
+static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8};
+
+extern int d_aflatcolor;
+
+int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
+
+int d_pix_min, d_pix_max, d_pix_shift;
+
+int d_scantable[MAXHEIGHT];
+short *zspantable[MAXHEIGHT];
+
+/*
+================
+D_Patch
+================
+*/
+void D_Patch (void)
+{
+#if id386
+ extern void D_Aff8Patch( void );
+ static qboolean protectset8 = false;
+ extern void D_PolysetAff8Start( void );
+
+ if (!protectset8)
+ {
+ Sys_MakeCodeWriteable ((int)D_PolysetAff8Start,
+ (int)D_Aff8Patch - (int)D_PolysetAff8Start);
+ Sys_MakeCodeWriteable ((long)R_Surf8Start,
+ (long)R_Surf8End - (long)R_Surf8Start);
+ protectset8 = true;
+ }
+ colormap = vid.colormap;
+
+ R_Surf8Patch ();
+ D_Aff8Patch();
+#endif
+}
+/*
+================
+D_ViewChanged
+================
+*/
+unsigned char *alias_colormap;
+
+void D_ViewChanged (void)
+{
+ int i;
+
+ scale_for_mip = xscale;
+ if (yscale > xscale)
+ scale_for_mip = yscale;
+
+ d_zrowbytes = vid.width * 2;
+ d_zwidth = vid.width;
+
+ d_pix_min = r_refdef.vrect.width / 320;
+ if (d_pix_min < 1)
+ d_pix_min = 1;
+
+ d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5);
+ d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5);
+ if (d_pix_max < 1)
+ d_pix_max = 1;
+
+ d_vrectx = r_refdef.vrect.x;
+ d_vrecty = r_refdef.vrect.y;
+ d_vrectright_particle = r_refdef.vrectright - d_pix_max;
+ d_vrectbottom_particle =
+ r_refdef.vrectbottom - d_pix_max;
+
+ for (i=0 ; i<vid.height; i++)
+ {
+ d_scantable[i] = i*r_screenwidth;
+ zspantable[i] = d_pzbuffer + i*d_zwidth;
+ }
+
+ /*
+ ** clear Z-buffer and color-buffers if we're doing the gallery
+ */
+ if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
+ {
+ memset( d_pzbuffer, 0xff, vid.width * vid.height * sizeof( d_pzbuffer[0] ) );
+ Draw_Fill( r_newrefdef.x, r_newrefdef.y, r_newrefdef.width, r_newrefdef.height,( int ) sw_clearcolor->value & 0xff );
+ }
+
+ alias_colormap = vid.colormap;
+
+ D_Patch ();
+}
+
+
+
+/*
+=============
+R_PrintTimes
+=============
+*/
+void R_PrintTimes (void)
+{
+ int r_time2;
+ int ms;
+
+ r_time2 = Sys_Milliseconds ();
+
+ ms = r_time2 - r_time1;
+
+ ri.Con_Printf (PRINT_ALL,"%5i ms %3i/%3i/%3i poly %3i surf\n",
+ ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf);
+ c_surf = 0;
+}
+
+
+/*
+=============
+R_PrintDSpeeds
+=============
+*/
+void R_PrintDSpeeds (void)
+{
+ int ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, da_time;
+
+ r_time2 = Sys_Milliseconds ();
+
+ da_time = (da_time2 - da_time1);
+ dp_time = (dp_time2 - dp_time1);
+ rw_time = (rw_time2 - rw_time1);
+ db_time = (db_time2 - db_time1);
+ se_time = (se_time2 - se_time1);
+ de_time = (de_time2 - de_time1);
+ ms = (r_time2 - r_time1);
+
+ ri.Con_Printf (PRINT_ALL,"%3i %2ip %2iw %2ib %2is %2ie %2ia\n",
+ ms, dp_time, rw_time, db_time, se_time, de_time, da_time);
+}
+
+
+/*
+=============
+R_PrintAliasStats
+=============
+*/
+void R_PrintAliasStats (void)
+{
+ ri.Con_Printf (PRINT_ALL,"%3i polygon model drawn\n", r_amodels_drawn);
+}
+
+
+
+/*
+===================
+R_TransformFrustum
+===================
+*/
+void R_TransformFrustum (void)
+{
+ int i;
+ vec3_t v, v2;
+
+ for (i=0 ; i<4 ; i++)
+ {
+ v[0] = screenedge[i].normal[2];
+ v[1] = -screenedge[i].normal[0];
+ v[2] = screenedge[i].normal[1];
+
+ v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0];
+ v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1];
+ v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2];
+
+ VectorCopy (v2, view_clipplanes[i].normal);
+
+ view_clipplanes[i].dist = DotProduct (modelorg, v2);
+ }
+}
+
+
+#if !(defined __linux__ && defined __i386__)
+#if !id386
+
+/*
+================
+TransformVector
+================
+*/
+void TransformVector (vec3_t in, vec3_t out)
+{
+ out[0] = DotProduct(in,vright);
+ out[1] = DotProduct(in,vup);
+ out[2] = DotProduct(in,vpn);
+}
+
+#else
+
+__declspec( naked ) void TransformVector( vec3_t vin, vec3_t vout )
+{
+ __asm mov eax, dword ptr [esp+4]
+ __asm mov edx, dword ptr [esp+8]
+
+ __asm fld dword ptr [eax+0]
+ __asm fmul dword ptr [vright+0]
+ __asm fld dword ptr [eax+0]
+ __asm fmul dword ptr [vup+0]
+ __asm fld dword ptr [eax+0]
+ __asm fmul dword ptr [vpn+0]
+
+ __asm fld dword ptr [eax+4]
+ __asm fmul dword ptr [vright+4]
+ __asm fld dword ptr [eax+4]
+ __asm fmul dword ptr [vup+4]
+ __asm fld dword ptr [eax+4]
+ __asm fmul dword ptr [vpn+4]
+
+ __asm fxch st(2)
+
+ __asm faddp st(5), st(0)
+ __asm faddp st(3), st(0)
+ __asm faddp st(1), st(0)
+
+ __asm fld dword ptr [eax+8]
+ __asm fmul dword ptr [vright+8]
+ __asm fld dword ptr [eax+8]
+ __asm fmul dword ptr [vup+8]
+ __asm fld dword ptr [eax+8]
+ __asm fmul dword ptr [vpn+8]
+
+ __asm fxch st(2)
+
+ __asm faddp st(5), st(0)
+ __asm faddp st(3), st(0)
+ __asm faddp st(1), st(0)
+
+ __asm fstp dword ptr [edx+8]
+ __asm fstp dword ptr [edx+4]
+ __asm fstp dword ptr [edx+0]
+
+ __asm ret
+}
+
+#endif
+#endif
+
+
+/*
+================
+R_TransformPlane
+================
+*/
+void R_TransformPlane (mplane_t *p, float *normal, float *dist)
+{
+ float d;
+
+ d = DotProduct (r_origin, p->normal);
+ *dist = p->dist - d;
+// TODO: when we have rotating entities, this will need to use the view matrix
+ TransformVector (p->normal, normal);
+}
+
+
+/*
+===============
+R_SetUpFrustumIndexes
+===============
+*/
+void R_SetUpFrustumIndexes (void)
+{
+ int i, j, *pindex;
+
+ pindex = r_frustum_indexes;
+
+ for (i=0 ; i<4 ; i++)
+ {
+ for (j=0 ; j<3 ; j++)
+ {
+ if (view_clipplanes[i].normal[j] < 0)
+ {
+ pindex[j] = j;
+ pindex[j+3] = j+3;
+ }
+ else
+ {
+ pindex[j] = j+3;
+ pindex[j+3] = j;
+ }
+ }
+
+ // FIXME: do just once at start
+ pfrustum_indexes[i] = pindex;
+ pindex += 6;
+ }
+}
+
+/*
+===============
+R_ViewChanged
+
+Called every time the vid structure or r_refdef changes.
+Guaranteed to be called before the first refresh
+===============
+*/
+void R_ViewChanged (vrect_t *vr)
+{
+ int i;
+
+ r_refdef.vrect = *vr;
+
+ r_refdef.horizontalFieldOfView = 2*tan((float)r_newrefdef.fov_x/360*M_PI);;
+ verticalFieldOfView = 2*tan((float)r_newrefdef.fov_y/360*M_PI);
+
+ r_refdef.fvrectx = (float)r_refdef.vrect.x;
+ r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5;
+ r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1;
+ r_refdef.fvrecty = (float)r_refdef.vrect.y;
+ r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5;
+ r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
+ r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1;
+ r_refdef.fvrectright = (float)r_refdef.vrectright;
+ r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5;
+ r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99;
+ r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
+ r_refdef.fvrectbottom = (float)r_refdef.vrectbottom;
+ r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5;
+
+ r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale);
+ r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale);
+ r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale);
+ r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale);
+ r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
+ r_refdef.aliasvrect.width;
+ r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
+ r_refdef.aliasvrect.height;
+
+ xOrigin = r_refdef.xOrigin;
+ yOrigin = r_refdef.yOrigin;
+
+// values for perspective projection
+// if math were exact, the values would range from 0.5 to to range+0.5
+// hopefully they wll be in the 0.000001 to range+.999999 and truncate
+// the polygon rasterization will never render in the first row or column
+// but will definately render in the [range] row and column, so adjust the
+// buffer origin to get an exact edge to edge fill
+ xcenter = ((float)r_refdef.vrect.width * XCENTERING) +
+ r_refdef.vrect.x - 0.5;
+ aliasxcenter = xcenter * r_aliasuvscale;
+ ycenter = ((float)r_refdef.vrect.height * YCENTERING) +
+ r_refdef.vrect.y - 0.5;
+ aliasycenter = ycenter * r_aliasuvscale;
+
+ xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
+ aliasxscale = xscale * r_aliasuvscale;
+ xscaleinv = 1.0 / xscale;
+
+ yscale = xscale;
+ aliasyscale = yscale * r_aliasuvscale;
+ yscaleinv = 1.0 / yscale;
+ xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView;
+ yscaleshrink = xscaleshrink;
+
+// left side clip
+ screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView);
+ screenedge[0].normal[1] = 0;
+ screenedge[0].normal[2] = 1;
+ screenedge[0].type = PLANE_ANYZ;
+
+// right side clip
+ screenedge[1].normal[0] =
+ 1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView);
+ screenedge[1].normal[1] = 0;
+ screenedge[1].normal[2] = 1;
+ screenedge[1].type = PLANE_ANYZ;
+
+// top side clip
+ screenedge[2].normal[0] = 0;
+ screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView);
+ screenedge[2].normal[2] = 1;
+ screenedge[2].type = PLANE_ANYZ;
+
+// bottom side clip
+ screenedge[3].normal[0] = 0;
+ screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView);
+ screenedge[3].normal[2] = 1;
+ screenedge[3].type = PLANE_ANYZ;
+
+ for (i=0 ; i<4 ; i++)
+ VectorNormalize (screenedge[i].normal);
+
+ D_ViewChanged ();
+}
+
+
+/*
+===============
+R_SetupFrame
+===============
+*/
+void R_SetupFrame (void)
+{
+ int i;
+ vrect_t vrect;
+
+ if (r_fullbright->modified)
+ {
+ r_fullbright->modified = false;
+ D_FlushCaches (); // so all lighting changes
+ }
+
+ r_framecount++;
+
+
+// build the transformation matrix for the given view angles
+ VectorCopy (r_refdef.vieworg, modelorg);
+ VectorCopy (r_refdef.vieworg, r_origin);
+
+ AngleVectors (r_refdef.viewangles, vpn, vright, vup);
+
+// current viewleaf
+ if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
+ {
+ r_viewleaf = Mod_PointInLeaf (r_origin, r_worldmodel);
+ r_viewcluster = r_viewleaf->cluster;
+ }
+
+ if (sw_waterwarp->value && (r_newrefdef.rdflags & RDF_UNDERWATER) )
+ r_dowarp = true;
+ else
+ r_dowarp = false;
+
+ if (r_dowarp)
+ { // warp into off screen buffer
+ vrect.x = 0;
+ vrect.y = 0;
+ vrect.width = r_newrefdef.width < WARP_WIDTH ? r_newrefdef.width : WARP_WIDTH;
+ vrect.height = r_newrefdef.height < WARP_HEIGHT ? r_newrefdef.height : WARP_HEIGHT;
+
+ d_viewbuffer = r_warpbuffer;
+ r_screenwidth = WARP_WIDTH;
+ }
+ else
+ {
+ vrect.x = r_newrefdef.x;
+ vrect.y = r_newrefdef.y;
+ vrect.width = r_newrefdef.width;
+ vrect.height = r_newrefdef.height;
+
+ d_viewbuffer = (void *)vid.buffer;
+ r_screenwidth = vid.rowbytes;
+ }
+
+ R_ViewChanged (&vrect);
+
+// start off with just the four screen edge clip planes
+ R_TransformFrustum ();
+ R_SetUpFrustumIndexes ();
+
+// save base values
+ VectorCopy (vpn, base_vpn);
+ VectorCopy (vright, base_vright);
+ VectorCopy (vup, base_vup);
+
+// clear frame counts
+ c_faceclip = 0;
+ d_spanpixcount = 0;
+ r_polycount = 0;
+ r_drawnpolycount = 0;
+ r_wholepolycount = 0;
+ r_amodels_drawn = 0;
+ r_outofsurfaces = 0;
+ r_outofedges = 0;
+
+// d_setup
+ d_roverwrapped = false;
+ d_initial_rover = sc_rover;
+
+ d_minmip = sw_mipcap->value;
+ if (d_minmip > 3)
+ d_minmip = 3;
+ else if (d_minmip < 0)
+ d_minmip = 0;
+
+ for (i=0 ; i<(NUM_MIPS-1) ; i++)
+ d_scalemip[i] = basemip[i] * sw_mipscale->value;
+
+ d_aflatcolor = 0;
+}
+
+
+#if !id386
+
+/*
+================
+R_SurfacePatch
+================
+*/
+void R_SurfacePatch (void)
+{
+ // we only patch code on Intel
+}
+
+#endif // !id386
+
+
+/*
+==============================================================================
+
+ SCREEN SHOTS
+
+==============================================================================
+*/
+
+
+/*
+==============
+WritePCXfile
+==============
+*/
+void WritePCXfile (char *filename, byte *data, int width, int height,
+ int rowbytes, byte *palette)
+{
+ int i, j, length;
+ pcx_t *pcx;
+ byte *pack;
+ FILE *f;
+
+ pcx = (pcx_t *)malloc (width*height*2+1000);
+ if (!pcx)
+ return;
+
+ pcx->manufacturer = 0x0a; // PCX id
+ pcx->version = 5; // 256 color
+ pcx->encoding = 1; // uncompressed
+ pcx->bits_per_pixel = 8; // 256 color
+ pcx->xmin = 0;
+ pcx->ymin = 0;
+ pcx->xmax = LittleShort((short)(width-1));
+ pcx->ymax = LittleShort((short)(height-1));
+ pcx->hres = LittleShort((short)width);
+ pcx->vres = LittleShort((short)height);
+ memset (pcx->palette,0,sizeof(pcx->palette));
+ pcx->color_planes = 1; // chunky image
+ pcx->bytes_per_line = LittleShort((short)width);
+ pcx->palette_type = LittleShort(2); // not a grey scale
+ memset (pcx->filler,0,sizeof(pcx->filler));
+
+// pack the image
+ pack = &pcx->data;
+
+ for (i=0 ; i<height ; i++)
+ {
+ for (j=0 ; j<width ; j++)
+ {
+ if ( (*data & 0xc0) != 0xc0)
+ *pack++ = *data++;
+ else
+ {
+ *pack++ = 0xc1;
+ *pack++ = *data++;
+ }
+ }
+
+ data += rowbytes - width;
+ }
+
+// write the palette
+ *pack++ = 0x0c; // palette ID byte
+ for (i=0 ; i<768 ; i++)
+ *pack++ = *palette++;
+
+// write output file
+ length = pack - (byte *)pcx;
+ f = fopen (filename, "wb");
+ if (!f)
+ ri.Con_Printf (PRINT_ALL, "Failed to open to %s\n", filename);
+ else
+ {
+ fwrite ((void *)pcx, 1, length, f);
+ fclose (f);
+ }
+
+ free (pcx);
+}
+
+
+
+/*
+==================
+R_ScreenShot_f
+==================
+*/
+void R_ScreenShot_f (void)
+{
+ int i;
+ char pcxname[80];
+ char checkname[MAX_OSPATH];
+ FILE *f;
+ byte palette[768];
+
+ // create the scrnshots directory if it doesn't exist
+ Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot", ri.FS_Gamedir());
+ Sys_Mkdir (checkname);
+
+//
+// find a file name to save it to
+//
+ strcpy(pcxname,"quake00.pcx");
+
+ for (i=0 ; i<=99 ; i++)
+ {
+ pcxname[5] = i/10 + '0';
+ pcxname[6] = i%10 + '0';
+ Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/%s", ri.FS_Gamedir(), pcxname);
+ f = fopen (checkname, "r");
+ if (!f)
+ break; // file doesn't exist
+ fclose (f);
+ }
+ if (i==100)
+ {
+ ri.Con_Printf (PRINT_ALL, "R_ScreenShot_f: Couldn't create a PCX");
+ return;
+ }
+
+ // turn the current 32 bit palette into a 24 bit palette
+ for (i=0 ; i<256 ; i++)
+ {
+ palette[i*3+0] = sw_state.currentpalette[i*4+0];
+ palette[i*3+1] = sw_state.currentpalette[i*4+1];
+ palette[i*3+2] = sw_state.currentpalette[i*4+2];
+ }
+
+//
+// save the pcx file
+//
+
+ WritePCXfile (checkname, vid.buffer, vid.width, vid.height, vid.rowbytes,
+ palette);
+
+ ri.Con_Printf (PRINT_ALL, "Wrote %s\n", checkname);
+}
+
--- /dev/null
+++ b/ref/r_model.c
@@ -1,0 +1,1241 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// models.c -- model loading and caching
+
+// models are the only shared resource between a client and server running
+// on the same machine.
+
+#include "r_local.h"
+
+model_t *loadmodel;
+char loadname[32]; // for hunk tags
+
+void Mod_LoadSpriteModel (model_t *mod, void *buffer);
+void Mod_LoadBrushModel (model_t *mod, void *buffer);
+void Mod_LoadAliasModel (model_t *mod, void *buffer);
+model_t *Mod_LoadModel (model_t *mod, qboolean crash);
+
+byte mod_novis[MAX_MAP_LEAFS/8];
+
+#define MAX_MOD_KNOWN 256
+model_t mod_known[MAX_MOD_KNOWN];
+int mod_numknown;
+
+// the inline * models from the current map are kept seperate
+model_t mod_inline[MAX_MOD_KNOWN];
+
+int registration_sequence;
+int modfilelen;
+
+//===============================================================================
+
+
+/*
+================
+Mod_Modellist_f
+================
+*/
+void Mod_Modellist_f (void)
+{
+ int i;
+ model_t *mod;
+ int total;
+
+ total = 0;
+ ri.Con_Printf (PRINT_ALL,"Loaded models:\n");
+ for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
+ {
+ if (!mod->name[0])
+ continue;
+ ri.Con_Printf (PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name);
+ total += mod->extradatasize;
+ }
+ ri.Con_Printf (PRINT_ALL, "Total resident: %i\n", total);
+}
+
+/*
+===============
+Mod_Init
+===============
+*/
+void Mod_Init (void)
+{
+ memset (mod_novis, 0xff, sizeof(mod_novis));
+}
+
+/*
+==================
+Mod_ForName
+
+Loads in a model for the given name
+==================
+*/
+model_t *Mod_ForName (char *name, qboolean crash)
+{
+ model_t *mod;
+ unsigned *buf;
+ int i;
+
+ if (!name[0])
+ ri.Sys_Error (ERR_DROP,"Mod_ForName: NULL name");
+
+ //
+ // inline models are grabbed only from worldmodel
+ //
+ if (name[0] == '*')
+ {
+ i = atoi(name+1);
+ if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels)
+ ri.Sys_Error (ERR_DROP, "bad inline model number");
+ return &mod_inline[i];
+ }
+
+ //
+ // search the currently loaded models
+ //
+ for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
+ if (!strcmp (mod->name, name) )
+ return mod;
+
+ //
+ // find a free model slot spot
+ //
+ for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
+ {
+ if (!mod->name[0])
+ break; // free spot
+ }
+ if (i == mod_numknown)
+ {
+ if (mod_numknown == MAX_MOD_KNOWN)
+ ri.Sys_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN");
+ mod_numknown++;
+ }
+ strcpy (mod->name, name);
+
+ //
+ // load the file
+ //
+ modfilelen = ri.FS_LoadFile (mod->name, (void **)&buf);
+ if (!buf)
+ {
+ if (crash)
+ ri.Sys_Error (ERR_DROP,"Mod_NumForName: %s not found", mod->name);
+ memset (mod->name, 0, sizeof(mod->name));
+ return NULL;
+ }
+
+ loadmodel = mod;
+
+ //
+ // fill it in
+ //
+
+ // call the apropriate loader
+
+ switch (LittleLong(*(unsigned *)buf))
+ {
+ case IDALIASHEADER:
+ loadmodel->extradata = Hunk_Begin (0x200000);
+ Mod_LoadAliasModel (mod, buf);
+ break;
+
+ case IDSPRITEHEADER:
+ loadmodel->extradata = Hunk_Begin (0x10000);
+ Mod_LoadSpriteModel (mod, buf);
+ break;
+
+ case IDBSPHEADER:
+ loadmodel->extradata = Hunk_Begin (0x1000000);
+ Mod_LoadBrushModel (mod, buf);
+ break;
+
+ default:
+ ri.Sys_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name);
+ break;
+ }
+
+ loadmodel->extradatasize = Hunk_End ();
+
+ ri.FS_FreeFile (buf);
+
+ return mod;
+}
+
+
+/*
+===============
+Mod_PointInLeaf
+===============
+*/
+mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
+{
+ mnode_t *node;
+ float d;
+ mplane_t *plane;
+
+ if (!model || !model->nodes)
+ ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model");
+
+ node = model->nodes;
+ while (1)
+ {
+ if (node->contents != -1)
+ return (mleaf_t *)node;
+ plane = node->plane;
+ d = DotProduct (p,plane->normal) - plane->dist;
+ if (d > 0)
+ node = node->children[0];
+ else
+ node = node->children[1];
+ }
+
+ return NULL; // never reached
+}
+
+
+/*
+===================
+Mod_DecompressVis
+===================
+*/
+byte *Mod_DecompressVis (byte *in, model_t *model)
+{
+ static byte decompressed[MAX_MAP_LEAFS/8];
+ int c;
+ byte *out;
+ int row;
+
+ row = (model->vis->numclusters+7)>>3;
+ out = decompressed;
+
+#if 0
+ memcpy (out, in, row);
+#else
+ if (!in)
+ { // no vis info, so make all visible
+ while (row)
+ {
+ *out++ = 0xff;
+ row--;
+ }
+ return decompressed;
+ }
+
+ do
+ {
+ if (*in)
+ {
+ *out++ = *in++;
+ continue;
+ }
+
+ c = in[1];
+ in += 2;
+ while (c)
+ {
+ *out++ = 0;
+ c--;
+ }
+ } while (out - decompressed < row);
+#endif
+
+ return decompressed;
+}
+
+/*
+==============
+Mod_ClusterPVS
+==============
+*/
+byte *Mod_ClusterPVS (int cluster, model_t *model)
+{
+ if (cluster == -1 || !model->vis)
+ return mod_novis;
+ return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS],
+ model);
+}
+
+/*
+===============================================================================
+
+ BRUSHMODEL LOADING
+
+===============================================================================
+*/
+
+byte *mod_base;
+
+
+/*
+=================
+Mod_LoadLighting
+
+Converts the 24 bit lighting down to 8 bit
+by taking the brightest component
+=================
+*/
+void Mod_LoadLighting (lump_t *l)
+{
+ int i, size;
+ byte *in;
+
+ if (!l->filelen)
+ {
+ loadmodel->lightdata = NULL;
+ return;
+ }
+ size = l->filelen/3;
+ loadmodel->lightdata = Hunk_Alloc (size);
+ in = (void *)(mod_base + l->fileofs);
+ for (i=0 ; i<size ; i++, in+=3)
+ {
+ if (in[0] > in[1] && in[0] > in[2])
+ loadmodel->lightdata[i] = in[0];
+ else if (in[1] > in[0] && in[1] > in[2])
+ loadmodel->lightdata[i] = in[1];
+ else
+ loadmodel->lightdata[i] = in[2];
+ }
+}
+
+
+int r_leaftovis[MAX_MAP_LEAFS];
+int r_vistoleaf[MAX_MAP_LEAFS];
+int r_numvisleafs;
+
+void R_NumberLeafs (mnode_t *node)
+{
+ mleaf_t *leaf;
+ int leafnum;
+
+ if (node->contents != -1)
+ {
+ leaf = (mleaf_t *)node;
+ leafnum = leaf - loadmodel->leafs;
+ if (leaf->contents & CONTENTS_SOLID)
+ return;
+ r_leaftovis[leafnum] = r_numvisleafs;
+ r_vistoleaf[r_numvisleafs] = leafnum;
+ r_numvisleafs++;
+ return;
+ }
+
+ R_NumberLeafs (node->children[0]);
+ R_NumberLeafs (node->children[1]);
+}
+
+
+/*
+=================
+Mod_LoadVisibility
+=================
+*/
+void Mod_LoadVisibility (lump_t *l)
+{
+ int i;
+
+ if (!l->filelen)
+ {
+ loadmodel->vis = NULL;
+ return;
+ }
+ loadmodel->vis = Hunk_Alloc ( l->filelen);
+ memcpy (loadmodel->vis, mod_base + l->fileofs, l->filelen);
+
+ loadmodel->vis->numclusters = LittleLong (loadmodel->vis->numclusters);
+ for (i=0 ; i<loadmodel->vis->numclusters ; i++)
+ {
+ loadmodel->vis->bitofs[i][0] = LittleLong (loadmodel->vis->bitofs[i][0]);
+ loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]);
+ }
+}
+
+
+/*
+=================
+Mod_LoadVertexes
+=================
+*/
+void Mod_LoadVertexes (lump_t *l)
+{
+ dvertex_t *in;
+ mvertex_t *out;
+ int i, count;
+
+ in = (void *)(mod_base + l->fileofs);
+ if (l->filelen % sizeof(*in))
+ ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+ count = l->filelen / sizeof(*in);
+ out = Hunk_Alloc ( (count+8)*sizeof(*out)); // extra for skybox
+
+ loadmodel->vertexes = out;
+ loadmodel->numvertexes = count;
+
+ for ( i=0 ; i<count ; i++, in++, out++)
+ {
+ out->position[0] = LittleFloat (in->point[0]);
+ out->position[1] = LittleFloat (in->point[1]);
+ out->position[2] = LittleFloat (in->point[2]);
+ }
+}
+
+/*
+=================
+Mod_LoadSubmodels
+=================
+*/
+void Mod_LoadSubmodels (lump_t *l)
+{
+ dmodel_t *in;
+ dmodel_t *out;
+ int i, j, count;
+
+ in = (void *)(mod_base + l->fileofs);
+ if (l->filelen % sizeof(*in))
+ ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+ count = l->filelen / sizeof(*in);
+ out = Hunk_Alloc ( count*sizeof(*out));
+
+ loadmodel->submodels = out;
+ loadmodel->numsubmodels = count;
+
+ for ( i=0 ; i<count ; i++, in++, out++)
+ {
+ for (j=0 ; j<3 ; j++)
+ { // spread the mins / maxs by a pixel
+ out->mins[j] = LittleFloat (in->mins[j]) - 1;
+ out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
+ out->origin[j] = LittleFloat (in->origin[j]);
+ }
+ out->headnode = LittleLong (in->headnode);
+ out->firstface = LittleLong (in->firstface);
+ out->numfaces = LittleLong (in->numfaces);
+ }
+}
+
+/*
+=================
+Mod_LoadEdges
+=================
+*/
+void Mod_LoadEdges (lump_t *l)
+{
+ dedge_t *in;
+ medge_t *out;
+ int i, count;
+
+ in = (void *)(mod_base + l->fileofs);
+ if (l->filelen % sizeof(*in))
+ ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+ count = l->filelen / sizeof(*in);
+ out = Hunk_Alloc ( (count + 13) * sizeof(*out)); // extra for skybox
+
+ loadmodel->edges = out;
+ loadmodel->numedges = count;
+
+ for ( i=0 ; i<count ; i++, in++, out++)
+ {
+ out->v[0] = (unsigned short)LittleShort(in->v[0]);
+ out->v[1] = (unsigned short)LittleShort(in->v[1]);
+ }
+}
+
+/*
+=================
+Mod_LoadTexinfo
+=================
+*/
+void Mod_LoadTexinfo (lump_t *l)
+{
+ texinfo_t *in;
+ mtexinfo_t *out, *step;
+ int i, j, count;
+ float len1, len2;
+ char name[MAX_QPATH];
+ int next;
+
+ in = (void *)(mod_base + l->fileofs);
+ if (l->filelen % sizeof(*in))
+ ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+ count = l->filelen / sizeof(*in);
+ out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox
+
+ loadmodel->texinfo = out;
+ loadmodel->numtexinfo = count;
+
+ for ( i=0 ; i<count ; i++, in++, out++)
+ {
+ for (j=0 ; j<8 ; j++)
+ out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
+ len1 = VectorLength (out->vecs[0]);
+ len2 = VectorLength (out->vecs[1]);
+ len1 = (len1 + len2)/2;
+ if (len1 < 0.32)
+ out->mipadjust = 4;
+ else if (len1 < 0.49)
+ out->mipadjust = 3;
+ else if (len1 < 0.99)
+ out->mipadjust = 2;
+ else
+ out->mipadjust = 1;
+#if 0
+ if (len1 + len2 < 0.001)
+ out->mipadjust = 1; // don't crash
+ else
+ out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
+#endif
+
+ out->flags = LittleLong (in->flags);
+
+ next = LittleLong (in->nexttexinfo);
+ if (next > 0)
+ out->next = loadmodel->texinfo + next;
+
+ Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture);
+ out->image = R_FindImage (name, it_wall);
+ if (!out->image)
+ {
+ out->image = r_notexture_mip; // texture not found
+ out->flags = 0;
+ }
+ }
+
+ // count animation frames
+ for (i=0 ; i<count ; i++)
+ {
+ out = &loadmodel->texinfo[i];
+ out->numframes = 1;
+ for (step = out->next ; step && step != out ; step=step->next)
+ out->numframes++;
+ }
+}
+
+/*
+================
+CalcSurfaceExtents
+
+Fills in s->texturemins[] and s->extents[]
+================
+*/
+void CalcSurfaceExtents (msurface_t *s)
+{
+ float mins[2], maxs[2], val;
+ int i,j, e;
+ mvertex_t *v;
+ mtexinfo_t *tex;
+ int bmins[2], bmaxs[2];
+
+ mins[0] = mins[1] = 999999;
+ maxs[0] = maxs[1] = -99999;
+
+ tex = s->texinfo;
+
+ for (i=0 ; i<s->numedges ; i++)
+ {
+ e = loadmodel->surfedges[s->firstedge+i];
+ if (e >= 0)
+ v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
+ else
+ v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
+
+ for (j=0 ; j<2 ; j++)
+ {
+ val = v->position[0] * tex->vecs[j][0] +
+ v->position[1] * tex->vecs[j][1] +
+ v->position[2] * tex->vecs[j][2] +
+ tex->vecs[j][3];
+ if (val < mins[j])
+ mins[j] = val;
+ if (val > maxs[j])
+ maxs[j] = val;
+ }
+ }
+
+ for (i=0 ; i<2 ; i++)
+ {
+ bmins[i] = floor(mins[i]/16);
+ bmaxs[i] = ceil(maxs[i]/16);
+
+ s->texturemins[i] = bmins[i] * 16;
+ s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
+ if (s->extents[i] < 16)
+ s->extents[i] = 16; // take at least one cache block
+ if ( !(tex->flags & (SURF_WARP|SURF_SKY)) && s->extents[i] > 256)
+ ri.Sys_Error (ERR_DROP,"Bad surface extents");
+ }
+}
+
+
+/*
+=================
+Mod_LoadFaces
+=================
+*/
+void Mod_LoadFaces (lump_t *l)
+{
+ dface_t *in;
+ msurface_t *out;
+ int i, count, surfnum;
+ int planenum, side;
+
+ in = (void *)(mod_base + l->fileofs);
+ if (l->filelen % sizeof(*in))
+ ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+ count = l->filelen / sizeof(*in);
+ out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox
+
+ loadmodel->surfaces = out;
+ loadmodel->numsurfaces = count;
+
+ for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
+ {
+ out->firstedge = LittleLong(in->firstedge);
+ out->numedges = LittleShort(in->numedges);
+ if (out->numedges < 3)
+ ri.Sys_Error (ERR_DROP,"Surface with %s edges", out->numedges);
+ out->flags = 0;
+
+ planenum = LittleShort(in->planenum);
+ side = LittleShort(in->side);
+ if (side)
+ out->flags |= SURF_PLANEBACK;
+
+ out->plane = loadmodel->planes + planenum;
+
+ out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
+
+ CalcSurfaceExtents (out);
+
+ // lighting info is converted from 24 bit on disk to 8 bit
+
+ for (i=0 ; i<MAXLIGHTMAPS ; i++)
+ out->styles[i] = in->styles[i];
+ i = LittleLong(in->lightofs);
+ if (i == -1)
+ out->samples = NULL;
+ else
+ out->samples = loadmodel->lightdata + i/3;
+
+ // set the drawing flags flag
+
+ if (!out->texinfo->image)
+ continue;
+ if (out->texinfo->flags & SURF_SKY)
+ {
+ out->flags |= SURF_DRAWSKY;
+ continue;
+ }
+
+ if (out->texinfo->flags & SURF_WARP)
+ {
+ out->flags |= SURF_DRAWTURB;
+ for (i=0 ; i<2 ; i++)
+ {
+ out->extents[i] = 16384;
+ out->texturemins[i] = -8192;
+ }
+ continue;
+ }
+//==============
+//PGM
+ // this marks flowing surfaces as turbulent, but with the new
+ // SURF_FLOW flag.
+ if (out->texinfo->flags & SURF_FLOWING)
+ {
+ out->flags |= SURF_DRAWTURB | SURF_FLOW;
+ for (i=0 ; i<2 ; i++)
+ {
+ out->extents[i] = 16384;
+ out->texturemins[i] = -8192;
+ }
+ continue;
+ }
+//PGM
+//==============
+ }
+}
+
+
+/*
+=================
+Mod_SetParent
+=================
+*/
+void Mod_SetParent (mnode_t *node, mnode_t *parent)
+{
+ node->parent = parent;
+ if (node->contents != -1)
+ return;
+ Mod_SetParent (node->children[0], node);
+ Mod_SetParent (node->children[1], node);
+}
+
+/*
+=================
+Mod_LoadNodes
+=================
+*/
+void Mod_LoadNodes (lump_t *l)
+{
+ int i, j, count, p;
+ dnode_t *in;
+ mnode_t *out;
+
+ in = (void *)(mod_base + l->fileofs);
+ if (l->filelen % sizeof(*in))
+ ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+ count = l->filelen / sizeof(*in);
+ out = Hunk_Alloc ( count*sizeof(*out));
+
+ loadmodel->nodes = out;
+ loadmodel->numnodes = count;
+
+ for ( i=0 ; i<count ; i++, in++, out++)
+ {
+ for (j=0 ; j<3 ; j++)
+ {
+ out->minmaxs[j] = LittleShort (in->mins[j]);
+ out->minmaxs[3+j] = LittleShort (in->maxs[j]);
+ }
+
+ p = LittleLong(in->planenum);
+ out->plane = loadmodel->planes + p;
+
+ out->firstsurface = LittleShort (in->firstface);
+ out->numsurfaces = LittleShort (in->numfaces);
+ out->contents = CONTENTS_NODE; // differentiate from leafs
+
+ for (j=0 ; j<2 ; j++)
+ {
+ p = LittleLong (in->children[j]);
+ if (p >= 0)
+ out->children[j] = loadmodel->nodes + p;
+ else
+ out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
+ }
+ }
+
+ Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
+}
+
+/*
+=================
+Mod_LoadLeafs
+=================
+*/
+void Mod_LoadLeafs (lump_t *l)
+{
+ dleaf_t *in;
+ mleaf_t *out;
+ int i, j, count;
+
+ in = (void *)(mod_base + l->fileofs);
+ if (l->filelen % sizeof(*in))
+ ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+ count = l->filelen / sizeof(*in);
+ out = Hunk_Alloc ( count*sizeof(*out));
+
+ loadmodel->leafs = out;
+ loadmodel->numleafs = count;
+
+ for ( i=0 ; i<count ; i++, in++, out++)
+ {
+ for (j=0 ; j<3 ; j++)
+ {
+ out->minmaxs[j] = LittleShort (in->mins[j]);
+ out->minmaxs[3+j] = LittleShort (in->maxs[j]);
+ }
+
+ out->contents = LittleLong(in->contents);
+ out->cluster = LittleShort(in->cluster);
+ out->area = LittleShort(in->area);
+
+ out->firstmarksurface = loadmodel->marksurfaces +
+ LittleShort(in->firstleafface);
+ out->nummarksurfaces = LittleShort(in->numleaffaces);
+ }
+}
+
+
+/*
+=================
+Mod_LoadMarksurfaces
+=================
+*/
+void Mod_LoadMarksurfaces (lump_t *l)
+{
+ int i, j, count;
+ short *in;
+ msurface_t **out;
+
+ in = (void *)(mod_base + l->fileofs);
+ if (l->filelen % sizeof(*in))
+ ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+ count = l->filelen / sizeof(*in);
+ out = Hunk_Alloc ( count*sizeof(*out));
+
+ loadmodel->marksurfaces = out;
+ loadmodel->nummarksurfaces = count;
+
+ for ( i=0 ; i<count ; i++)
+ {
+ j = LittleShort(in[i]);
+ if (j >= loadmodel->numsurfaces)
+ ri.Sys_Error (ERR_DROP,"Mod_ParseMarksurfaces: bad surface number");
+ out[i] = loadmodel->surfaces + j;
+ }
+}
+
+/*
+=================
+Mod_LoadSurfedges
+=================
+*/
+void Mod_LoadSurfedges (lump_t *l)
+{
+ int i, count;
+ int *in, *out;
+
+ in = (void *)(mod_base + l->fileofs);
+ if (l->filelen % sizeof(*in))
+ ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+ count = l->filelen / sizeof(*in);
+ out = Hunk_Alloc ( (count+24)*sizeof(*out)); // extra for skybox
+
+ loadmodel->surfedges = out;
+ loadmodel->numsurfedges = count;
+
+ for ( i=0 ; i<count ; i++)
+ out[i] = LittleLong (in[i]);
+}
+
+/*
+=================
+Mod_LoadPlanes
+=================
+*/
+void Mod_LoadPlanes (lump_t *l)
+{
+ int i, j;
+ mplane_t *out;
+ dplane_t *in;
+ int count;
+ int bits;
+
+ in = (void *)(mod_base + l->fileofs);
+ if (l->filelen % sizeof(*in))
+ ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
+ count = l->filelen / sizeof(*in);
+ out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox
+
+ loadmodel->planes = out;
+ loadmodel->numplanes = count;
+
+ for ( i=0 ; i<count ; i++, in++, out++)
+ {
+ bits = 0;
+ for (j=0 ; j<3 ; j++)
+ {
+ out->normal[j] = LittleFloat (in->normal[j]);
+ if (out->normal[j] < 0)
+ bits |= 1<<j;
+ }
+
+ out->dist = LittleFloat (in->dist);
+ out->type = LittleLong (in->type);
+ out->signbits = bits;
+ }
+}
+
+
+/*
+=================
+Mod_LoadBrushModel
+=================
+*/
+void Mod_LoadBrushModel (model_t *mod, void *buffer)
+{
+ int i;
+ dheader_t *header;
+ dmodel_t *bm;
+
+ loadmodel->type = mod_brush;
+ if (loadmodel != mod_known)
+ ri.Sys_Error (ERR_DROP, "Loaded a brush model after the world");
+
+ header = (dheader_t *)buffer;
+
+ i = LittleLong (header->version);
+ if (i != BSPVERSION)
+ ri.Sys_Error (ERR_DROP,"Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
+
+// swap all the lumps
+ mod_base = (byte *)header;
+
+ for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
+ ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
+
+// load into heap
+
+ Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
+ Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
+ Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
+ Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
+ Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
+ Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
+ Mod_LoadFaces (&header->lumps[LUMP_FACES]);
+ Mod_LoadMarksurfaces (&header->lumps[LUMP_LEAFFACES]);
+ Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
+ Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
+ Mod_LoadNodes (&header->lumps[LUMP_NODES]);
+ Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
+ r_numvisleafs = 0;
+ R_NumberLeafs (loadmodel->nodes);
+
+//
+// set up the submodels
+//
+ for (i=0 ; i<mod->numsubmodels ; i++)
+ {
+ model_t *starmod;
+
+ bm = &mod->submodels[i];
+ starmod = &mod_inline[i];
+
+ *starmod = *loadmodel;
+
+ starmod->firstmodelsurface = bm->firstface;
+ starmod->nummodelsurfaces = bm->numfaces;
+ starmod->firstnode = bm->headnode;
+ if (starmod->firstnode >= loadmodel->numnodes)
+ ri.Sys_Error (ERR_DROP, "Inline model %i has bad firstnode", i);
+
+ VectorCopy (bm->maxs, starmod->maxs);
+ VectorCopy (bm->mins, starmod->mins);
+
+ if (i == 0)
+ *loadmodel = *starmod;
+ }
+
+ R_InitSkyBox ();
+}
+
+/*
+==============================================================================
+
+ALIAS MODELS
+
+==============================================================================
+*/
+
+/*
+=================
+Mod_LoadAliasModel
+=================
+*/
+void Mod_LoadAliasModel (model_t *mod, void *buffer)
+{
+ int i, j;
+ dmdl_t *pinmodel, *pheader;
+ dstvert_t *pinst, *poutst;
+ dtriangle_t *pintri, *pouttri;
+ daliasframe_t *pinframe, *poutframe;
+ int *pincmd, *poutcmd;
+ int version;
+
+ pinmodel = (dmdl_t *)buffer;
+
+ version = LittleLong (pinmodel->version);
+ if (version != ALIAS_VERSION)
+ ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
+ mod->name, version, ALIAS_VERSION);
+
+ pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end));
+
+ // byte swap the header fields and sanity check
+ for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
+ ((int *)pheader)[i] = LittleLong (((int *)buffer)[i]);
+
+ if (pheader->skinheight > MAX_LBM_HEIGHT)
+ ri.Sys_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name,
+ MAX_LBM_HEIGHT);
+
+ if (pheader->num_xyz <= 0)
+ ri.Sys_Error (ERR_DROP, "model %s has no vertices", mod->name);
+
+ if (pheader->num_xyz > MAX_VERTS)
+ ri.Sys_Error (ERR_DROP, "model %s has too many vertices", mod->name);
+
+ if (pheader->num_st <= 0)
+ ri.Sys_Error (ERR_DROP, "model %s has no st vertices", mod->name);
+
+ if (pheader->num_tris <= 0)
+ ri.Sys_Error (ERR_DROP, "model %s has no triangles", mod->name);
+
+ if (pheader->num_frames <= 0)
+ ri.Sys_Error (ERR_DROP, "model %s has no frames", mod->name);
+
+//
+// load base s and t vertices (not used in gl version)
+//
+ pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st);
+ poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st);
+
+ for (i=0 ; i<pheader->num_st ; i++)
+ {
+ poutst[i].s = LittleShort (pinst[i].s);
+ poutst[i].t = LittleShort (pinst[i].t);
+ }
+
+//
+// load triangle lists
+//
+ pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris);
+ pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris);
+
+ for (i=0 ; i<pheader->num_tris ; i++)
+ {
+ for (j=0 ; j<3 ; j++)
+ {
+ pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]);
+ pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]);
+ }
+ }
+
+//
+// load the frames
+//
+ for (i=0 ; i<pheader->num_frames ; i++)
+ {
+ pinframe = (daliasframe_t *) ((byte *)pinmodel
+ + pheader->ofs_frames + i * pheader->framesize);
+ poutframe = (daliasframe_t *) ((byte *)pheader
+ + pheader->ofs_frames + i * pheader->framesize);
+
+ memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name));
+ for (j=0 ; j<3 ; j++)
+ {
+ poutframe->scale[j] = LittleFloat (pinframe->scale[j]);
+ poutframe->translate[j] = LittleFloat (pinframe->translate[j]);
+ }
+ // verts are all 8 bit, so no swapping needed
+ memcpy (poutframe->verts, pinframe->verts,
+ pheader->num_xyz*sizeof(dtrivertx_t));
+
+ }
+
+ mod->type = mod_alias;
+
+ //
+ // load the glcmds
+ //
+ pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds);
+ poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds);
+ for (i=0 ; i<pheader->num_glcmds ; i++)
+ poutcmd[i] = LittleLong (pincmd[i]);
+
+
+ // register all skins
+ memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins,
+ pheader->num_skins*MAX_SKINNAME);
+ for (i=0 ; i<pheader->num_skins ; i++)
+ {
+ mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
+ }
+}
+
+/*
+==============================================================================
+
+SPRITE MODELS
+
+==============================================================================
+*/
+
+/*
+=================
+Mod_LoadSpriteModel
+=================
+*/
+void Mod_LoadSpriteModel (model_t *mod, void *buffer)
+{
+ dsprite_t *sprin, *sprout;
+ int i;
+
+ sprin = (dsprite_t *)buffer;
+ sprout = Hunk_Alloc (modfilelen);
+
+ sprout->ident = LittleLong (sprin->ident);
+ sprout->version = LittleLong (sprin->version);
+ sprout->numframes = LittleLong (sprin->numframes);
+
+ if (sprout->version != SPRITE_VERSION)
+ ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
+ mod->name, sprout->version, SPRITE_VERSION);
+
+ if (sprout->numframes > MAX_MD2SKINS)
+ ri.Sys_Error (ERR_DROP, "%s has too many frames (%i > %i)",
+ mod->name, sprout->numframes, MAX_MD2SKINS);
+
+ // byte swap everything
+ for (i=0 ; i<sprout->numframes ; i++)
+ {
+ sprout->frames[i].width = LittleLong (sprin->frames[i].width);
+ sprout->frames[i].height = LittleLong (sprin->frames[i].height);
+ sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x);
+ sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y);
+ memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME);
+ mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite);
+ }
+
+ mod->type = mod_sprite;
+}
+
+//=============================================================================
+
+/*
+@@@@@@@@@@@@@@@@@@@@@
+R_BeginRegistration
+
+Specifies the model that will be used as the world
+@@@@@@@@@@@@@@@@@@@@@
+*/
+void R_BeginRegistration (char *model)
+{
+ char fullname[MAX_QPATH];
+ cvar_t *flushmap;
+
+ registration_sequence++;
+ r_oldviewcluster = -1; // force markleafs
+ Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model);
+
+ D_FlushCaches ();
+ // explicitly free the old map if different
+ // this guarantees that mod_known[0] is the world map
+ flushmap = ri.Cvar_Get ("flushmap", "0", 0);
+ if ( strcmp(mod_known[0].name, fullname) || flushmap->value)
+ Mod_Free (&mod_known[0]);
+ r_worldmodel = R_RegisterModel (fullname);
+ R_NewMap ();
+}
+
+
+/*
+@@@@@@@@@@@@@@@@@@@@@
+R_RegisterModel
+
+@@@@@@@@@@@@@@@@@@@@@
+*/
+struct model_s *R_RegisterModel (char *name)
+{
+ model_t *mod;
+ int i;
+ dsprite_t *sprout;
+ dmdl_t *pheader;
+
+ mod = Mod_ForName (name, false);
+ if (mod)
+ {
+ mod->registration_sequence = registration_sequence;
+
+ // register any images used by the models
+ if (mod->type == mod_sprite)
+ {
+ sprout = (dsprite_t *)mod->extradata;
+ for (i=0 ; i<sprout->numframes ; i++)
+ mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite);
+ }
+ else if (mod->type == mod_alias)
+ {
+ pheader = (dmdl_t *)mod->extradata;
+ for (i=0 ; i<pheader->num_skins ; i++)
+ mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
+//PGM
+ mod->numframes = pheader->num_frames;
+//PGM
+ }
+ else if (mod->type == mod_brush)
+ {
+ for (i=0 ; i<mod->numtexinfo ; i++)
+ mod->texinfo[i].image->registration_sequence = registration_sequence;
+ }
+ }
+ return mod;
+}
+
+/*
+@@@@@@@@@@@@@@@@@@@@@
+R_EndRegistration
+
+@@@@@@@@@@@@@@@@@@@@@
+*/
+void R_EndRegistration (void)
+{
+ int i;
+ model_t *mod;
+
+ for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++)
+ {
+ if (!mod->name[0])
+ continue;
+ if (mod->registration_sequence != registration_sequence)
+ { // don't need this model
+ Hunk_Free (mod->extradata);
+ memset (mod, 0, sizeof(*mod));
+ }
+ else
+ { // make sure it is paged in
+ Com_PageInMemory (mod->extradata, mod->extradatasize);
+ }
+ }
+
+ R_FreeUnusedImages ();
+}
+
+
+//=============================================================================
+
+/*
+================
+Mod_Free
+================
+*/
+void Mod_Free (model_t *mod)
+{
+ Hunk_Free (mod->extradata);
+ memset (mod, 0, sizeof(*mod));
+}
+
+/*
+================
+Mod_FreeAll
+================
+*/
+void Mod_FreeAll (void)
+{
+ int i;
+
+ for (i=0 ; i<mod_numknown ; i++)
+ {
+ if (mod_known[i].extradatasize)
+ Mod_Free (&mod_known[i]);
+ }
+}
--- /dev/null
+++ b/ref/r_model.h
@@ -1,0 +1,256 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef __MODEL__
+#define __MODEL__
+
+/*
+
+d*_t structures are on-disk representations
+m*_t structures are in-memory
+
+*/
+
+
+/*
+==============================================================================
+
+BRUSH MODELS
+
+==============================================================================
+*/
+
+
+//
+// in memory representation
+//
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct
+{
+ vec3_t position;
+} mvertex_t;
+
+#define SIDE_FRONT 0
+#define SIDE_BACK 1
+#define SIDE_ON 2
+
+
+// plane_t structure
+// !!! if this is changed, it must be changed in asm_i386.h too !!!
+typedef struct mplane_s
+{
+ vec3_t normal;
+ float dist;
+ byte type; // for texture axis selection and fast side tests
+ byte signbits; // signx + signy<<1 + signz<<1
+ byte pad[2];
+} mplane_t;
+
+
+// FIXME: differentiate from texinfo SURF_ flags
+#define SURF_PLANEBACK 2
+#define SURF_DRAWSKY 4 // sky brush face
+#define SURF_DRAWTURB 0x10
+#define SURF_DRAWBACKGROUND 0x40
+#define SURF_DRAWSKYBOX 0x80 // sky box
+
+#define SURF_FLOW 0x100 //PGM
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct
+{
+ unsigned short v[2];
+ unsigned int cachededgeoffset;
+} medge_t;
+
+typedef struct mtexinfo_s
+{
+ float vecs[2][4];
+ float mipadjust;
+ image_t *image;
+ int flags;
+ int numframes;
+ struct mtexinfo_s *next; // animation chain
+} mtexinfo_t;
+
+typedef struct msurface_s
+{
+ int visframe; // should be drawn when node is crossed
+
+ int dlightframe;
+ int dlightbits;
+
+ mplane_t *plane;
+ int flags;
+
+ int firstedge; // look up in model->surfedges[], negative numbers
+ int numedges; // are backwards edges
+
+// surface generation data
+ struct surfcache_s *cachespots[MIPLEVELS];
+
+ short texturemins[2];
+ short extents[2];
+
+ mtexinfo_t *texinfo;
+
+// lighting info
+ byte styles[MAXLIGHTMAPS];
+ byte *samples; // [numstyles*surfsize]
+
+ struct msurface_s *nextalphasurface;
+} msurface_t;
+
+
+#define CONTENTS_NODE -1
+typedef struct mnode_s
+{
+// common with leaf
+ int contents; // CONTENTS_NODE, to differentiate from leafs
+ int visframe; // node needs to be traversed if current
+
+ short minmaxs[6]; // for bounding box culling
+
+ struct mnode_s *parent;
+
+// node specific
+ mplane_t *plane;
+ struct mnode_s *children[2];
+
+ unsigned short firstsurface;
+ unsigned short numsurfaces;
+} mnode_t;
+
+
+
+typedef struct mleaf_s
+{
+// common with node
+ int contents; // wil be something other than CONTENTS_NODE
+ int visframe; // node needs to be traversed if current
+
+ short minmaxs[6]; // for bounding box culling
+
+ struct mnode_s *parent;
+
+// leaf specific
+ int cluster;
+ int area;
+
+ msurface_t **firstmarksurface;
+ int nummarksurfaces;
+ int key; // BSP sequence number for leaf's contents
+} mleaf_t;
+
+
+//===================================================================
+
+//
+// Whole model
+//
+
+typedef enum {mod_bad, mod_brush, mod_sprite, mod_alias } modtype_t;
+
+typedef struct model_s
+{
+ char name[MAX_QPATH];
+
+ int registration_sequence;
+
+ modtype_t type;
+ int numframes;
+
+ int flags;
+
+//
+// volume occupied by the model graphics
+//
+ vec3_t mins, maxs;
+
+//
+// solid volume for clipping (sent from server)
+//
+ qboolean clipbox;
+ vec3_t clipmins, clipmaxs;
+
+//
+// brush model
+//
+ int firstmodelsurface, nummodelsurfaces;
+
+ int numsubmodels;
+ dmodel_t *submodels;
+
+ int numplanes;
+ mplane_t *planes;
+
+ int numleafs; // number of visible leafs, not counting 0
+ mleaf_t *leafs;
+
+ int numvertexes;
+ mvertex_t *vertexes;
+
+ int numedges;
+ medge_t *edges;
+
+ int numnodes;
+ int firstnode;
+ mnode_t *nodes;
+
+ int numtexinfo;
+ mtexinfo_t *texinfo;
+
+ int numsurfaces;
+ msurface_t *surfaces;
+
+ int numsurfedges;
+ int *surfedges;
+
+ int nummarksurfaces;
+ msurface_t **marksurfaces;
+
+ dvis_t *vis;
+
+ byte *lightdata;
+
+ // for alias models and sprites
+ image_t *skins[MAX_MD2SKINS];
+ void *extradata;
+ int extradatasize;
+} model_t;
+
+//============================================================================
+
+void Mod_Init (void);
+void Mod_ClearAll (void);
+model_t *Mod_ForName (char *name, qboolean crash);
+void *Mod_Extradata (model_t *mod); // handles caching
+void Mod_TouchModel (char *name);
+
+mleaf_t *Mod_PointInLeaf (float *p, model_t *model);
+byte *Mod_ClusterPVS (int cluster, model_t *model);
+
+void Mod_Modellist_f (void);
+void Mod_FreeAll (void);
+void Mod_Free (model_t *mod);
+
+extern int registration_sequence;
+
+#endif // __MODEL__
--- /dev/null
+++ b/ref/r_part.c
@@ -1,0 +1,638 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "r_local.h"
+
+vec3_t r_pright, r_pup, r_ppn;
+
+#define PARTICLE_33 0
+#define PARTICLE_66 1
+#define PARTICLE_OPAQUE 2
+
+typedef struct
+{
+ particle_t *particle;
+ int level;
+ int color;
+} partparms_t;
+
+static partparms_t partparms;
+
+#if id386 && !defined __linux__
+
+static unsigned s_prefetch_address;
+
+/*
+** BlendParticleXX
+**
+** Inputs:
+** EAX = color
+** EDI = pdest
+**
+** Scratch:
+** EBX = scratch (dstcolor)
+** EBP = scratch
+**
+** Outputs:
+** none
+*/
+__declspec(naked) void BlendParticle33( void )
+{
+ // return vid.alphamap[color + dstcolor*256];
+ __asm mov ebp, vid.alphamap
+ __asm xor ebx, ebx
+
+ __asm mov bl, byte ptr [edi]
+ __asm shl ebx, 8
+
+ __asm add ebp, ebx
+ __asm add ebp, eax
+
+ __asm mov al, byte ptr [ebp]
+
+ __asm mov byte ptr [edi], al
+
+ __asm ret
+}
+
+__declspec(naked) void BlendParticle66( void )
+{
+ // return vid.alphamap[pcolor*256 + dstcolor];
+ __asm mov ebp, vid.alphamap
+ __asm xor ebx, ebx
+
+ __asm shl eax, 8
+ __asm mov bl, byte ptr [edi]
+
+ __asm add ebp, ebx
+ __asm add ebp, eax
+
+ __asm mov al, byte ptr [ebp]
+
+ __asm mov byte ptr [edi], al
+
+ __asm ret
+}
+
+__declspec(naked) void BlendParticle100( void )
+{
+ __asm mov byte ptr [edi], al
+ __asm ret
+}
+
+/*
+** R_DrawParticle (asm version)
+**
+** Since we use __declspec( naked ) we don't have a stack frame
+** that we can use. Since I want to reserve EBP anyway, I tossed
+** all the important variables into statics. This routine isn't
+** meant to be re-entrant, so this shouldn't cause any problems
+** other than a slightly higher global memory footprint.
+**
+*/
+__declspec(naked) void R_DrawParticle( void )
+{
+ static vec3_t local, transformed;
+ static float zi;
+ static int u, v, tmp;
+ static short izi;
+ static int ebpsave;
+
+ static byte (*blendfunc)(void);
+
+ /*
+ ** must be memvars since x86 can't load constants
+ ** directly. I guess I could use fld1, but that
+ ** actually costs one more clock than fld [one]!
+ */
+ static float particle_z_clip = PARTICLE_Z_CLIP;
+ static float one = 1.0F;
+ static float point_five = 0.5F;
+ static float eight_thousand_hex = 0x8000;
+
+ /*
+ ** save trashed variables
+ */
+ __asm mov ebpsave, ebp
+ __asm push esi
+ __asm push edi
+
+ /*
+ ** transform the particle
+ */
+ // VectorSubtract (pparticle->origin, r_origin, local);
+ __asm mov esi, partparms.particle
+ __asm fld dword ptr [esi+0] ; p_o.x
+ __asm fsub dword ptr [r_origin+0] ; p_o.x-r_o.x
+ __asm fld dword ptr [esi+4] ; p_o.y | p_o.x-r_o.x
+ __asm fsub dword ptr [r_origin+4] ; p_o.y-r_o.y | p_o.x-r_o.x
+ __asm fld dword ptr [esi+8] ; p_o.z | p_o.y-r_o.y | p_o.x-r_o.x
+ __asm fsub dword ptr [r_origin+8] ; p_o.z-r_o.z | p_o.y-r_o.y | p_o.x-r_o.x
+ __asm fxch st(2) ; p_o.x-r_o.x | p_o.y-r_o.y | p_o.z-r_o.z
+ __asm fstp dword ptr [local+0] ; p_o.y-r_o.y | p_o.z-r_o.z
+ __asm fstp dword ptr [local+4] ; p_o.z-r_o.z
+ __asm fstp dword ptr [local+8] ; (empty)
+
+ // transformed[0] = DotProduct(local, r_pright);
+ // transformed[1] = DotProduct(local, r_pup);
+ // transformed[2] = DotProduct(local, r_ppn);
+ __asm fld dword ptr [local+0] ; l.x
+ __asm fmul dword ptr [r_pright+0] ; l.x*pr.x
+ __asm fld dword ptr [local+4] ; l.y | l.x*pr.x
+ __asm fmul dword ptr [r_pright+4] ; l.y*pr.y | l.x*pr.x
+ __asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
+ __asm fmul dword ptr [r_pright+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
+ __asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
+ __asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
+ __asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
+ __asm fstp dword ptr [transformed+0] ; (empty)
+
+ __asm fld dword ptr [local+0] ; l.x
+ __asm fmul dword ptr [r_pup+0] ; l.x*pr.x
+ __asm fld dword ptr [local+4] ; l.y | l.x*pr.x
+ __asm fmul dword ptr [r_pup+4] ; l.y*pr.y | l.x*pr.x
+ __asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
+ __asm fmul dword ptr [r_pup+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
+ __asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
+ __asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
+ __asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
+ __asm fstp dword ptr [transformed+4] ; (empty)
+
+ __asm fld dword ptr [local+0] ; l.x
+ __asm fmul dword ptr [r_ppn+0] ; l.x*pr.x
+ __asm fld dword ptr [local+4] ; l.y | l.x*pr.x
+ __asm fmul dword ptr [r_ppn+4] ; l.y*pr.y | l.x*pr.x
+ __asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
+ __asm fmul dword ptr [r_ppn+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
+ __asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
+ __asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
+ __asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
+ __asm fstp dword ptr [transformed+8] ; (empty)
+
+ /*
+ ** make sure that the transformed particle is not in front of
+ ** the particle Z clip plane. We can do the comparison in
+ ** integer space since we know the sign of one of the inputs
+ ** and can figure out the sign of the other easily enough.
+ */
+ // if (transformed[2] < PARTICLE_Z_CLIP)
+ // return;
+
+ __asm mov eax, dword ptr [transformed+8]
+ __asm and eax, eax
+ __asm js end
+ __asm cmp eax, particle_z_clip
+ __asm jl end
+
+ /*
+ ** project the point by initiating the 1/z calc
+ */
+ // zi = 1.0 / transformed[2];
+ __asm fld one
+ __asm fdiv dword ptr [transformed+8]
+
+ /*
+ ** bind the blend function pointer to the appropriate blender
+ ** while we're dividing
+ */
+ //if ( level == PARTICLE_33 )
+ // blendparticle = BlendParticle33;
+ //else if ( level == PARTICLE_66 )
+ // blendparticle = BlendParticle66;
+ //else
+ // blendparticle = BlendParticle100;
+
+ __asm cmp partparms.level, PARTICLE_66
+ __asm je blendfunc_66
+ __asm jl blendfunc_33
+ __asm lea ebx, BlendParticle100
+ __asm jmp done_selecting_blend_func
+blendfunc_33:
+ __asm lea ebx, BlendParticle33
+ __asm jmp done_selecting_blend_func
+blendfunc_66:
+ __asm lea ebx, BlendParticle66
+done_selecting_blend_func:
+ __asm mov blendfunc, ebx
+
+ // prefetch the next particle
+ __asm mov ebp, s_prefetch_address
+ __asm mov ebp, [ebp]
+
+ // finish the above divide
+ __asm fstp zi
+
+ // u = (int)(xcenter + zi * transformed[0] + 0.5);
+ // v = (int)(ycenter - zi * transformed[1] + 0.5);
+ __asm fld zi ; zi
+ __asm fmul dword ptr [transformed+0] ; zi * transformed[0]
+ __asm fld zi ; zi | zi * transformed[0]
+ __asm fmul dword ptr [transformed+4] ; zi * transformed[1] | zi * transformed[0]
+ __asm fxch st(1) ; zi * transformed[0] | zi * transformed[1]
+ __asm fadd xcenter ; xcenter + zi * transformed[0] | zi * transformed[1]
+ __asm fxch st(1) ; zi * transformed[1] | xcenter + zi * transformed[0]
+ __asm fld ycenter ; ycenter | zi * transformed[1] | xcenter + zi * transformed[0]
+ __asm fsubrp st(1), st(0) ; ycenter - zi * transformed[1] | xcenter + zi * transformed[0]
+ __asm fxch st(1) ; xcenter + zi * transformed[0] | ycenter + zi * transformed[1]
+ __asm fadd point_five ; xcenter + zi * transformed[0] + 0.5 | ycenter - zi * transformed[1]
+ __asm fxch st(1) ; ycenter - zi * transformed[1] | xcenter + zi * transformed[0] + 0.5
+ __asm fadd point_five ; ycenter - zi * transformed[1] + 0.5 | xcenter + zi * transformed[0] + 0.5
+ __asm fxch st(1) ; u | v
+ __asm fistp dword ptr [u] ; v
+ __asm fistp dword ptr [v] ; (empty)
+
+ /*
+ ** clip out the particle
+ */
+
+ // if ((v > d_vrectbottom_particle) ||
+ // (u > d_vrectright_particle) ||
+ // (v < d_vrecty) ||
+ // (u < d_vrectx))
+ // {
+ // return;
+ // }
+
+ __asm mov ebx, u
+ __asm mov ecx, v
+ __asm cmp ecx, d_vrectbottom_particle
+ __asm jg end
+ __asm cmp ecx, d_vrecty
+ __asm jl end
+ __asm cmp ebx, d_vrectright_particle
+ __asm jg end
+ __asm cmp ebx, d_vrectx
+ __asm jl end
+
+ /*
+ ** compute addresses of zbuffer, framebuffer, and
+ ** compute the Z-buffer reference value.
+ **
+ ** EBX = U
+ ** ECX = V
+ **
+ ** Outputs:
+ ** ESI = Z-buffer address
+ ** EDI = framebuffer address
+ */
+ // ESI = d_pzbuffer + (d_zwidth * v) + u;
+ __asm mov esi, d_pzbuffer ; esi = d_pzbuffer
+ __asm mov eax, d_zwidth ; eax = d_zwidth
+ __asm mul ecx ; eax = d_zwidth*v
+ __asm add eax, ebx ; eax = d_zwidth*v+u
+ __asm shl eax, 1 ; eax = 2*(d_zwidth*v+u)
+ __asm add esi, eax ; esi = ( short * ) ( d_pzbuffer + ( d_zwidth * v ) + u )
+
+ // initiate
+ // izi = (int)(zi * 0x8000);
+ __asm fld zi
+ __asm fmul eight_thousand_hex
+
+ // EDI = pdest = d_viewbuffer + d_scantable[v] + u;
+ __asm lea edi, [d_scantable+ecx*4]
+ __asm mov edi, [edi]
+ __asm add edi, d_viewbuffer
+ __asm add edi, ebx
+
+ // complete
+ // izi = (int)(zi * 0x8000);
+ __asm fistp tmp
+ __asm mov eax, tmp
+ __asm mov izi, ax
+
+ /*
+ ** determine the screen area covered by the particle,
+ ** which also means clamping to a min and max
+ */
+ // pix = izi >> d_pix_shift;
+ __asm xor edx, edx
+ __asm mov dx, izi
+ __asm mov ecx, d_pix_shift
+ __asm shr dx, cl
+
+ // if (pix < d_pix_min)
+ // pix = d_pix_min;
+ __asm cmp edx, d_pix_min
+ __asm jge check_pix_max
+ __asm mov edx, d_pix_min
+ __asm jmp skip_pix_clamp
+
+ // else if (pix > d_pix_max)
+ // pix = d_pix_max;
+check_pix_max:
+ __asm cmp edx, d_pix_max
+ __asm jle skip_pix_clamp
+ __asm mov edx, d_pix_max
+
+skip_pix_clamp:
+
+ /*
+ ** render the appropriate pixels
+ **
+ ** ECX = count (used for inner loop)
+ ** EDX = count (used for outer loop)
+ ** ESI = zbuffer
+ ** EDI = framebuffer
+ */
+ __asm mov ecx, edx
+
+ __asm cmp ecx, 1
+ __asm ja over
+
+over:
+
+ /*
+ ** at this point:
+ **
+ ** ECX = count
+ */
+ __asm push ecx
+ __asm push edi
+ __asm push esi
+
+top_of_pix_vert_loop:
+
+top_of_pix_horiz_loop:
+
+ // for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
+ // {
+ // for (i=0 ; i<pix ; i++)
+ // {
+ // if (pz[i] <= izi)
+ // {
+ // pdest[i] = blendparticle( color, pdest[i] );
+ // }
+ // }
+ // }
+ __asm xor eax, eax
+
+ __asm mov ax, word ptr [esi]
+
+ __asm cmp ax, izi
+ __asm jg end_of_horiz_loop
+
+#if ENABLE_ZWRITES_FOR_PARTICLES
+ __asm mov bp, izi
+ __asm mov word ptr [esi], bp
+#endif
+
+ __asm mov eax, partparms.color
+
+ __asm call [blendfunc]
+
+ __asm add edi, 1
+ __asm add esi, 2
+
+end_of_horiz_loop:
+
+ __asm dec ecx
+ __asm jnz top_of_pix_horiz_loop
+
+ __asm pop esi
+ __asm pop edi
+
+ __asm mov ebp, d_zwidth
+ __asm shl ebp, 1
+
+ __asm add esi, ebp
+ __asm add edi, [r_screenwidth]
+
+ __asm pop ecx
+ __asm push ecx
+
+ __asm push edi
+ __asm push esi
+
+ __asm dec edx
+ __asm jnz top_of_pix_vert_loop
+
+ __asm pop ecx
+ __asm pop ecx
+ __asm pop ecx
+
+end:
+ __asm pop edi
+ __asm pop esi
+ __asm mov ebp, ebpsave
+ __asm ret
+}
+
+#else
+
+static byte BlendParticle33( int pcolor, int dstcolor )
+{
+ return vid.alphamap[pcolor + dstcolor*256];
+}
+
+static byte BlendParticle66( int pcolor, int dstcolor )
+{
+ return vid.alphamap[pcolor*256+dstcolor];
+}
+
+static byte BlendParticle100( int pcolor, int dstcolor )
+{
+ dstcolor = dstcolor;
+ return pcolor;
+}
+
+/*
+** R_DrawParticle
+**
+** Yes, this is amazingly slow, but it's the C reference
+** implementation and should be both robust and vaguely
+** understandable. The only time this path should be
+** executed is if we're debugging on x86 or if we're
+** recompiling and deploying on a non-x86 platform.
+**
+** To minimize error and improve readability I went the
+** function pointer route. This exacts some overhead, but
+** it pays off in clean and easy to understand code.
+*/
+void R_DrawParticle( void )
+{
+ particle_t *pparticle = partparms.particle;
+ int level = partparms.level;
+ vec3_t local, transformed;
+ float zi;
+ byte *pdest;
+ short *pz;
+ int color = pparticle->color;
+ int i, izi, pix, count, u, v;
+ byte (*blendparticle)( int, int );
+
+ /*
+ ** transform the particle
+ */
+ VectorSubtract (pparticle->origin, r_origin, local);
+
+ transformed[0] = DotProduct(local, r_pright);
+ transformed[1] = DotProduct(local, r_pup);
+ transformed[2] = DotProduct(local, r_ppn);
+
+ if (transformed[2] < PARTICLE_Z_CLIP)
+ return;
+
+ /*
+ ** bind the blend function pointer to the appropriate blender
+ */
+ if ( level == PARTICLE_33 )
+ blendparticle = BlendParticle33;
+ else if ( level == PARTICLE_66 )
+ blendparticle = BlendParticle66;
+ else
+ blendparticle = BlendParticle100;
+
+ /*
+ ** project the point
+ */
+ // FIXME: preadjust xcenter and ycenter
+ zi = 1.0 / transformed[2];
+ u = (int)(xcenter + zi * transformed[0] + 0.5);
+ v = (int)(ycenter - zi * transformed[1] + 0.5);
+
+ if ((v > d_vrectbottom_particle) ||
+ (u > d_vrectright_particle) ||
+ (v < d_vrecty) ||
+ (u < d_vrectx))
+ {
+ return;
+ }
+
+ /*
+ ** compute addresses of zbuffer, framebuffer, and
+ ** compute the Z-buffer reference value.
+ */
+ pz = d_pzbuffer + (d_zwidth * v) + u;
+ pdest = d_viewbuffer + d_scantable[v] + u;
+ izi = (int)(zi * 0x8000);
+
+ /*
+ ** determine the screen area covered by the particle,
+ ** which also means clamping to a min and max
+ */
+ pix = izi >> d_pix_shift;
+ if (pix < d_pix_min)
+ pix = d_pix_min;
+ else if (pix > d_pix_max)
+ pix = d_pix_max;
+
+ /*
+ ** render the appropriate pixels
+ */
+ count = pix;
+
+ switch (level) {
+ case PARTICLE_33 :
+ for ( ; count ; count--, pz += d_zwidth, pdest += r_screenwidth)
+ {
+//FIXME--do it in blocks of 8?
+ for (i=0 ; i<pix ; i++)
+ {
+ if (pz[i] <= izi)
+ {
+ pz[i] = izi;
+ pdest[i] = vid.alphamap[color + ((int)pdest[i]<<8)];
+ }
+ }
+ }
+ break;
+
+ case PARTICLE_66 :
+ for ( ; count ; count--, pz += d_zwidth, pdest += r_screenwidth)
+ {
+ for (i=0 ; i<pix ; i++)
+ {
+ if (pz[i] <= izi)
+ {
+ pz[i] = izi;
+ pdest[i] = vid.alphamap[(color<<8) + (int)pdest[i]];
+ }
+ }
+ }
+ break;
+
+ default: //100
+ for ( ; count ; count--, pz += d_zwidth, pdest += r_screenwidth)
+ {
+ for (i=0 ; i<pix ; i++)
+ {
+ if (pz[i] <= izi)
+ {
+ pz[i] = izi;
+ pdest[i] = color;
+ }
+ }
+ }
+ break;
+ }
+}
+
+#endif // !id386
+
+/*
+** R_DrawParticles
+**
+** Responsible for drawing all of the particles in the particle list
+** throughout the world. Doesn't care if we're using the C path or
+** if we're using the asm path, it simply assigns a function pointer
+** and goes.
+*/
+void R_DrawParticles (void)
+{
+ particle_t *p;
+ int i;
+ extern unsigned long fpu_sp24_cw, fpu_chop_cw;
+
+ VectorScale( vright, xscaleshrink, r_pright );
+ VectorScale( vup, yscaleshrink, r_pup );
+ VectorCopy( vpn, r_ppn );
+
+#if id386 && !defined __linux__
+ __asm fldcw word ptr [fpu_sp24_cw]
+#endif
+
+ for (p=r_newrefdef.particles, i=0 ; i<r_newrefdef.num_particles ; i++,p++)
+ {
+
+ if ( p->alpha > 0.66 )
+ partparms.level = PARTICLE_OPAQUE;
+ else if ( p->alpha > 0.33 )
+ partparms.level = PARTICLE_66;
+ else
+ partparms.level = PARTICLE_33;
+
+ partparms.particle = p;
+ partparms.color = p->color;
+
+#if id386 && !defined __linux__
+ if ( i < r_newrefdef.num_particles-1 )
+ s_prefetch_address = ( unsigned int ) ( p + 1 );
+ else
+ s_prefetch_address = ( unsigned int ) r_newrefdef.particles;
+#endif
+
+ R_DrawParticle();
+ }
+
+#if id386 && !defined __linux__
+ __asm fldcw word ptr [fpu_chop_cw]
+#endif
+
+}
+
--- /dev/null
+++ b/ref/r_poly.c
@@ -1,0 +1,1244 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include <assert.h>
+#include "r_local.h"
+
+#define AFFINE_SPANLET_SIZE 16
+#define AFFINE_SPANLET_SIZE_BITS 4
+
+typedef struct
+{
+ byte *pbase, *pdest;
+ short *pz;
+ fixed16_t s, t;
+ fixed16_t sstep, tstep;
+ int izi, izistep, izistep_times_2;
+ int spancount;
+ unsigned u, v;
+} spanletvars_t;
+
+spanletvars_t s_spanletvars;
+
+static int r_polyblendcolor;
+
+static espan_t *s_polygon_spans;
+
+polydesc_t r_polydesc;
+
+msurface_t *r_alpha_surfaces;
+
+extern int *r_turb_turb;
+
+static int clip_current;
+vec5_t r_clip_verts[2][MAXWORKINGVERTS+2];
+
+static int s_minindex, s_maxindex;
+
+static void R_DrawPoly( qboolean iswater );
+
+/*
+** R_DrawSpanletOpaque
+*/
+void R_DrawSpanletOpaque( void )
+{
+ unsigned btemp;
+
+ do
+ {
+ unsigned ts, tt;
+
+ ts = s_spanletvars.s >> 16;
+ tt = s_spanletvars.t >> 16;
+
+ btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth);
+ if (btemp != 255)
+ {
+ if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
+ {
+ *s_spanletvars.pz = s_spanletvars.izi >> 16;
+ *s_spanletvars.pdest = btemp;
+ }
+ }
+
+ s_spanletvars.izi += s_spanletvars.izistep;
+ s_spanletvars.pdest++;
+ s_spanletvars.pz++;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+ } while (--s_spanletvars.spancount > 0);
+}
+
+/*
+** R_DrawSpanletTurbulentStipple33
+*/
+void R_DrawSpanletTurbulentStipple33( void )
+{
+ unsigned btemp;
+ int sturb, tturb;
+ byte *pdest = s_spanletvars.pdest;
+ short *pz = s_spanletvars.pz;
+ int izi = s_spanletvars.izi;
+
+ if ( s_spanletvars.v & 1 )
+ {
+ s_spanletvars.pdest += s_spanletvars.spancount;
+ s_spanletvars.pz += s_spanletvars.spancount;
+
+ if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
+ s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
+ else
+ s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
+
+ if ( s_spanletvars.u & 1 )
+ {
+ izi += s_spanletvars.izistep;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+
+ pdest++;
+ pz++;
+ s_spanletvars.spancount--;
+ }
+
+ s_spanletvars.sstep *= 2;
+ s_spanletvars.tstep *= 2;
+
+ while ( s_spanletvars.spancount > 0 )
+ {
+ sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
+ tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
+
+ btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
+
+ if ( *pz <= ( izi >> 16 ) )
+ *pdest = btemp;
+
+ izi += s_spanletvars.izistep_times_2;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+
+ pdest += 2;
+ pz += 2;
+
+ s_spanletvars.spancount -= 2;
+ }
+ }
+}
+
+/*
+** R_DrawSpanletTurbulentStipple66
+*/
+void R_DrawSpanletTurbulentStipple66( void )
+{
+ unsigned btemp;
+ int sturb, tturb;
+ byte *pdest = s_spanletvars.pdest;
+ short *pz = s_spanletvars.pz;
+ int izi = s_spanletvars.izi;
+
+ if ( !( s_spanletvars.v & 1 ) )
+ {
+ s_spanletvars.pdest += s_spanletvars.spancount;
+ s_spanletvars.pz += s_spanletvars.spancount;
+
+ if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
+ s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
+ else
+ s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
+
+ if ( s_spanletvars.u & 1 )
+ {
+ izi += s_spanletvars.izistep;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+
+ pdest++;
+ pz++;
+ s_spanletvars.spancount--;
+ }
+
+ s_spanletvars.sstep *= 2;
+ s_spanletvars.tstep *= 2;
+
+ while ( s_spanletvars.spancount > 0 )
+ {
+ sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
+ tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
+
+ btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
+
+ if ( *pz <= ( izi >> 16 ) )
+ *pdest = btemp;
+
+ izi += s_spanletvars.izistep_times_2;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+
+ pdest += 2;
+ pz += 2;
+
+ s_spanletvars.spancount -= 2;
+ }
+ }
+ else
+ {
+ s_spanletvars.pdest += s_spanletvars.spancount;
+ s_spanletvars.pz += s_spanletvars.spancount;
+
+ if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
+ s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
+ else
+ s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
+
+ while ( s_spanletvars.spancount > 0 )
+ {
+ sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
+ tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
+
+ btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
+
+ if ( *pz <= ( izi >> 16 ) )
+ *pdest = btemp;
+
+ izi += s_spanletvars.izistep;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+
+ pdest++;
+ pz++;
+
+ s_spanletvars.spancount--;
+ }
+ }
+}
+
+/*
+** R_DrawSpanletTurbulentBlended
+*/
+void R_DrawSpanletTurbulentBlended66( void )
+{
+ unsigned btemp;
+ int sturb, tturb;
+
+ do
+ {
+ sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
+ tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
+
+ btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
+
+ if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) )
+ *s_spanletvars.pdest = vid.alphamap[btemp*256+*s_spanletvars.pdest];
+
+ s_spanletvars.izi += s_spanletvars.izistep;
+ s_spanletvars.pdest++;
+ s_spanletvars.pz++;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+
+ } while ( --s_spanletvars.spancount > 0 );
+}
+
+void R_DrawSpanletTurbulentBlended33( void )
+{
+ unsigned btemp;
+ int sturb, tturb;
+
+ do
+ {
+ sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
+ tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
+
+ btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
+
+ if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) )
+ *s_spanletvars.pdest = vid.alphamap[btemp+*s_spanletvars.pdest*256];
+
+ s_spanletvars.izi += s_spanletvars.izistep;
+ s_spanletvars.pdest++;
+ s_spanletvars.pz++;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+
+ } while ( --s_spanletvars.spancount > 0 );
+}
+
+/*
+** R_DrawSpanlet33
+*/
+void R_DrawSpanlet33( void )
+{
+ unsigned btemp;
+
+ do
+ {
+ unsigned ts, tt;
+
+ ts = s_spanletvars.s >> 16;
+ tt = s_spanletvars.t >> 16;
+
+ btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth);
+
+ if ( btemp != 255 )
+ {
+ if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
+ {
+ *s_spanletvars.pdest = vid.alphamap[btemp+*s_spanletvars.pdest*256];
+ }
+ }
+
+ s_spanletvars.izi += s_spanletvars.izistep;
+ s_spanletvars.pdest++;
+ s_spanletvars.pz++;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+ } while (--s_spanletvars.spancount > 0);
+}
+
+void R_DrawSpanletConstant33( void )
+{
+ do
+ {
+ if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
+ {
+ *s_spanletvars.pdest = vid.alphamap[r_polyblendcolor+*s_spanletvars.pdest*256];
+ }
+
+ s_spanletvars.izi += s_spanletvars.izistep;
+ s_spanletvars.pdest++;
+ s_spanletvars.pz++;
+ } while (--s_spanletvars.spancount > 0);
+}
+
+/*
+** R_DrawSpanlet66
+*/
+void R_DrawSpanlet66( void )
+{
+ unsigned btemp;
+
+ do
+ {
+ unsigned ts, tt;
+
+ ts = s_spanletvars.s >> 16;
+ tt = s_spanletvars.t >> 16;
+
+ btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth);
+
+ if ( btemp != 255 )
+ {
+ if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
+ {
+ *s_spanletvars.pdest = vid.alphamap[btemp*256+*s_spanletvars.pdest];
+ }
+ }
+
+ s_spanletvars.izi += s_spanletvars.izistep;
+ s_spanletvars.pdest++;
+ s_spanletvars.pz++;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+ } while (--s_spanletvars.spancount > 0);
+}
+
+/*
+** R_DrawSpanlet33Stipple
+*/
+void R_DrawSpanlet33Stipple( void )
+{
+ unsigned btemp;
+ byte *pdest = s_spanletvars.pdest;
+ short *pz = s_spanletvars.pz;
+ int izi = s_spanletvars.izi;
+
+ if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) )
+ {
+ s_spanletvars.pdest += s_spanletvars.spancount;
+ s_spanletvars.pz += s_spanletvars.spancount;
+
+ if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
+ s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
+ else
+ s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
+
+ if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) )
+ {
+ izi += s_spanletvars.izistep;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+
+ pdest++;
+ pz++;
+ s_spanletvars.spancount--;
+ }
+
+ s_spanletvars.sstep *= 2;
+ s_spanletvars.tstep *= 2;
+
+ while ( s_spanletvars.spancount > 0 )
+ {
+ unsigned s = s_spanletvars.s >> 16;
+ unsigned t = s_spanletvars.t >> 16;
+
+ btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
+
+ if ( btemp != 255 )
+ {
+ if ( *pz <= ( izi >> 16 ) )
+ *pdest = btemp;
+ }
+
+ izi += s_spanletvars.izistep_times_2;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+
+ pdest += 2;
+ pz += 2;
+
+ s_spanletvars.spancount -= 2;
+ }
+ }
+}
+
+/*
+** R_DrawSpanlet66Stipple
+*/
+void R_DrawSpanlet66Stipple( void )
+{
+ unsigned btemp;
+ byte *pdest = s_spanletvars.pdest;
+ short *pz = s_spanletvars.pz;
+ int izi = s_spanletvars.izi;
+
+ s_spanletvars.pdest += s_spanletvars.spancount;
+ s_spanletvars.pz += s_spanletvars.spancount;
+
+ if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
+ s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
+ else
+ s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
+
+ if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) )
+ {
+ if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) )
+ {
+ izi += s_spanletvars.izistep;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+
+ pdest++;
+ pz++;
+ s_spanletvars.spancount--;
+ }
+
+ s_spanletvars.sstep *= 2;
+ s_spanletvars.tstep *= 2;
+
+ while ( s_spanletvars.spancount > 0 )
+ {
+ unsigned s = s_spanletvars.s >> 16;
+ unsigned t = s_spanletvars.t >> 16;
+
+ btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
+
+ if ( btemp != 255 )
+ {
+ if ( *pz <= ( izi >> 16 ) )
+ *pdest = btemp;
+ }
+
+ izi += s_spanletvars.izistep_times_2;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+
+ pdest += 2;
+ pz += 2;
+
+ s_spanletvars.spancount -= 2;
+ }
+ }
+ else
+ {
+ while ( s_spanletvars.spancount > 0 )
+ {
+ unsigned s = s_spanletvars.s >> 16;
+ unsigned t = s_spanletvars.t >> 16;
+
+ btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
+
+ if ( btemp != 255 )
+ {
+ if ( *pz <= ( izi >> 16 ) )
+ *pdest = btemp;
+ }
+
+ izi += s_spanletvars.izistep;
+ s_spanletvars.s += s_spanletvars.sstep;
+ s_spanletvars.t += s_spanletvars.tstep;
+
+ pdest++;
+ pz++;
+
+ s_spanletvars.spancount--;
+ }
+ }
+}
+
+/*
+** R_ClipPolyFace
+**
+** Clips the winding at clip_verts[clip_current] and changes clip_current
+** Throws out the back side
+*/
+int R_ClipPolyFace (int nump, clipplane_t *pclipplane)
+{
+ int i, outcount;
+ float dists[MAXWORKINGVERTS+3];
+ float frac, clipdist, *pclipnormal;
+ float *in, *instep, *outstep, *vert2;
+
+ clipdist = pclipplane->dist;
+ pclipnormal = pclipplane->normal;
+
+// calc dists
+ if (clip_current)
+ {
+ in = r_clip_verts[1][0];
+ outstep = r_clip_verts[0][0];
+ clip_current = 0;
+ }
+ else
+ {
+ in = r_clip_verts[0][0];
+ outstep = r_clip_verts[1][0];
+ clip_current = 1;
+ }
+
+ instep = in;
+ for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
+ {
+ dists[i] = DotProduct (instep, pclipnormal) - clipdist;
+ }
+
+// handle wraparound case
+ dists[nump] = dists[0];
+ memcpy (instep, in, sizeof (vec5_t));
+
+
+// clip the winding
+ instep = in;
+ outcount = 0;
+
+ for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
+ {
+ if (dists[i] >= 0)
+ {
+ memcpy (outstep, instep, sizeof (vec5_t));
+ outstep += sizeof (vec5_t) / sizeof (float);
+ outcount++;
+ }
+
+ if (dists[i] == 0 || dists[i+1] == 0)
+ continue;
+
+ if ( (dists[i] > 0) == (dists[i+1] > 0) )
+ continue;
+
+ // split it into a new vertex
+ frac = dists[i] / (dists[i] - dists[i+1]);
+
+ vert2 = instep + sizeof (vec5_t) / sizeof (float);
+
+ outstep[0] = instep[0] + frac*(vert2[0] - instep[0]);
+ outstep[1] = instep[1] + frac*(vert2[1] - instep[1]);
+ outstep[2] = instep[2] + frac*(vert2[2] - instep[2]);
+ outstep[3] = instep[3] + frac*(vert2[3] - instep[3]);
+ outstep[4] = instep[4] + frac*(vert2[4] - instep[4]);
+
+ outstep += sizeof (vec5_t) / sizeof (float);
+ outcount++;
+ }
+
+ return outcount;
+}
+
+/*
+** R_PolygonDrawSpans
+*/
+void R_PolygonDrawSpans(espan_t *pspan, qboolean iswater )
+{
+ int count;
+ fixed16_t snext, tnext;
+ float sdivz, tdivz, zi, z, du, dv, spancountminus1;
+ float sdivzspanletstepu, tdivzspanletstepu, zispanletstepu;
+
+ s_spanletvars.pbase = cacheblock;
+
+ if ( iswater )
+ r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
+
+ sdivzspanletstepu = d_sdivzstepu * AFFINE_SPANLET_SIZE;
+ tdivzspanletstepu = d_tdivzstepu * AFFINE_SPANLET_SIZE;
+ zispanletstepu = d_zistepu * AFFINE_SPANLET_SIZE;
+
+// we count on FP exceptions being turned off to avoid range problems
+ s_spanletvars.izistep = (int)(d_zistepu * 0x8000 * 0x10000);
+ s_spanletvars.izistep_times_2 = s_spanletvars.izistep * 2;
+
+ s_spanletvars.pz = 0;
+
+ do
+ {
+ s_spanletvars.pdest = (byte *)d_viewbuffer + ( d_scantable[pspan->v] /*r_screenwidth * pspan->v*/) + pspan->u;
+ s_spanletvars.pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
+ s_spanletvars.u = pspan->u;
+ s_spanletvars.v = pspan->v;
+
+ count = pspan->count;
+
+ if (count <= 0)
+ goto NextSpan;
+
+ // calculate the initial s/z, t/z, 1/z, s, and t and clamp
+ du = (float)pspan->u;
+ dv = (float)pspan->v;
+
+ sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
+ tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
+
+ zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+ z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
+ // we count on FP exceptions being turned off to avoid range problems
+ s_spanletvars.izi = (int)(zi * 0x8000 * 0x10000);
+
+ s_spanletvars.s = (int)(sdivz * z) + sadjust;
+ s_spanletvars.t = (int)(tdivz * z) + tadjust;
+
+ if ( !iswater )
+ {
+ if (s_spanletvars.s > bbextents)
+ s_spanletvars.s = bbextents;
+ else if (s_spanletvars.s < 0)
+ s_spanletvars.s = 0;
+
+ if (s_spanletvars.t > bbextentt)
+ s_spanletvars.t = bbextentt;
+ else if (s_spanletvars.t < 0)
+ s_spanletvars.t = 0;
+ }
+
+ do
+ {
+ // calculate s and t at the far end of the span
+ if (count >= AFFINE_SPANLET_SIZE )
+ s_spanletvars.spancount = AFFINE_SPANLET_SIZE;
+ else
+ s_spanletvars.spancount = count;
+
+ count -= s_spanletvars.spancount;
+
+ if (count)
+ {
+ // calculate s/z, t/z, zi->fixed s and t at far end of span,
+ // calculate s and t steps across span by shifting
+ sdivz += sdivzspanletstepu;
+ tdivz += tdivzspanletstepu;
+ zi += zispanletstepu;
+ z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
+
+ snext = (int)(sdivz * z) + sadjust;
+ tnext = (int)(tdivz * z) + tadjust;
+
+ if ( !iswater )
+ {
+ if (snext > bbextents)
+ snext = bbextents;
+ else if (snext < AFFINE_SPANLET_SIZE)
+ snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
+ // from causing overstepping & running off the
+ // edge of the texture
+
+ if (tnext > bbextentt)
+ tnext = bbextentt;
+ else if (tnext < AFFINE_SPANLET_SIZE)
+ tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
+ }
+
+ s_spanletvars.sstep = (snext - s_spanletvars.s) >> AFFINE_SPANLET_SIZE_BITS;
+ s_spanletvars.tstep = (tnext - s_spanletvars.t) >> AFFINE_SPANLET_SIZE_BITS;
+ }
+ else
+ {
+ // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
+ // can't step off polygon), clamp, calculate s and t steps across
+ // span by division, biasing steps low so we don't run off the
+ // texture
+ spancountminus1 = (float)(s_spanletvars.spancount - 1);
+ sdivz += d_sdivzstepu * spancountminus1;
+ tdivz += d_tdivzstepu * spancountminus1;
+ zi += d_zistepu * spancountminus1;
+ z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
+ snext = (int)(sdivz * z) + sadjust;
+ tnext = (int)(tdivz * z) + tadjust;
+
+ if ( !iswater )
+ {
+ if (snext > bbextents)
+ snext = bbextents;
+ else if (snext < AFFINE_SPANLET_SIZE)
+ snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
+ // from causing overstepping & running off the
+ // edge of the texture
+
+ if (tnext > bbextentt)
+ tnext = bbextentt;
+ else if (tnext < AFFINE_SPANLET_SIZE)
+ tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
+ }
+
+ if (s_spanletvars.spancount > 1)
+ {
+ s_spanletvars.sstep = (snext - s_spanletvars.s) / (s_spanletvars.spancount - 1);
+ s_spanletvars.tstep = (tnext - s_spanletvars.t) / (s_spanletvars.spancount - 1);
+ }
+ }
+
+ if ( iswater )
+ {
+ s_spanletvars.s = s_spanletvars.s & ((CYCLE<<16)-1);
+ s_spanletvars.t = s_spanletvars.t & ((CYCLE<<16)-1);
+ }
+
+ r_polydesc.drawspanlet();
+
+ s_spanletvars.s = snext;
+ s_spanletvars.t = tnext;
+
+ } while (count > 0);
+
+NextSpan:
+ pspan++;
+
+ } while (pspan->count != DS_SPAN_LIST_END);
+}
+
+/*
+**
+** R_PolygonScanLeftEdge
+**
+** Goes through the polygon and scans the left edge, filling in
+** screen coordinate data for the spans
+*/
+void R_PolygonScanLeftEdge (void)
+{
+ int i, v, itop, ibottom, lmaxindex;
+ emitpoint_t *pvert, *pnext;
+ espan_t *pspan;
+ float du, dv, vtop, vbottom, slope;
+ fixed16_t u, u_step;
+
+ pspan = s_polygon_spans;
+ i = s_minindex;
+ if (i == 0)
+ i = r_polydesc.nump;
+
+ lmaxindex = s_maxindex;
+ if (lmaxindex == 0)
+ lmaxindex = r_polydesc.nump;
+
+ vtop = ceil (r_polydesc.pverts[i].v);
+
+ do
+ {
+ pvert = &r_polydesc.pverts[i];
+ pnext = pvert - 1;
+
+ vbottom = ceil (pnext->v);
+
+ if (vtop < vbottom)
+ {
+ du = pnext->u - pvert->u;
+ dv = pnext->v - pvert->v;
+
+ slope = du / dv;
+ u_step = (int)(slope * 0x10000);
+ // adjust u to ceil the integer portion
+ u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
+ (0x10000 - 1);
+ itop = (int)vtop;
+ ibottom = (int)vbottom;
+
+ for (v=itop ; v<ibottom ; v++)
+ {
+ pspan->u = u >> 16;
+ pspan->v = v;
+ u += u_step;
+ pspan++;
+ }
+ }
+
+ vtop = vbottom;
+
+ i--;
+ if (i == 0)
+ i = r_polydesc.nump;
+
+ } while (i != lmaxindex);
+}
+
+/*
+** R_PolygonScanRightEdge
+**
+** Goes through the polygon and scans the right edge, filling in
+** count values.
+*/
+void R_PolygonScanRightEdge (void)
+{
+ int i, v, itop, ibottom;
+ emitpoint_t *pvert, *pnext;
+ espan_t *pspan;
+ float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
+ fixed16_t u, u_step;
+
+ pspan = s_polygon_spans;
+ i = s_minindex;
+
+ vvert = r_polydesc.pverts[i].v;
+ if (vvert < r_refdef.fvrecty_adj)
+ vvert = r_refdef.fvrecty_adj;
+ if (vvert > r_refdef.fvrectbottom_adj)
+ vvert = r_refdef.fvrectbottom_adj;
+
+ vtop = ceil (vvert);
+
+ do
+ {
+ pvert = &r_polydesc.pverts[i];
+ pnext = pvert + 1;
+
+ vnext = pnext->v;
+ if (vnext < r_refdef.fvrecty_adj)
+ vnext = r_refdef.fvrecty_adj;
+ if (vnext > r_refdef.fvrectbottom_adj)
+ vnext = r_refdef.fvrectbottom_adj;
+
+ vbottom = ceil (vnext);
+
+ if (vtop < vbottom)
+ {
+ uvert = pvert->u;
+ if (uvert < r_refdef.fvrectx_adj)
+ uvert = r_refdef.fvrectx_adj;
+ if (uvert > r_refdef.fvrectright_adj)
+ uvert = r_refdef.fvrectright_adj;
+
+ unext = pnext->u;
+ if (unext < r_refdef.fvrectx_adj)
+ unext = r_refdef.fvrectx_adj;
+ if (unext > r_refdef.fvrectright_adj)
+ unext = r_refdef.fvrectright_adj;
+
+ du = unext - uvert;
+ dv = vnext - vvert;
+ slope = du / dv;
+ u_step = (int)(slope * 0x10000);
+ // adjust u to ceil the integer portion
+ u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
+ (0x10000 - 1);
+ itop = (int)vtop;
+ ibottom = (int)vbottom;
+
+ for (v=itop ; v<ibottom ; v++)
+ {
+ pspan->count = (u >> 16) - pspan->u;
+ u += u_step;
+ pspan++;
+ }
+ }
+
+ vtop = vbottom;
+ vvert = vnext;
+
+ i++;
+ if (i == r_polydesc.nump)
+ i = 0;
+
+ } while (i != s_maxindex);
+
+ pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
+}
+
+/*
+** R_ClipAndDrawPoly
+*/
+void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured )
+{
+ emitpoint_t outverts[MAXWORKINGVERTS+3], *pout;
+ float *pv;
+ int i, nump;
+ float scale;
+ vec3_t transformed, local;
+
+ if ( !textured )
+ {
+ r_polydesc.drawspanlet = R_DrawSpanletConstant33;
+ }
+ else
+ {
+
+ /*
+ ** choose the correct spanlet routine based on alpha
+ */
+ if ( alpha == 1 )
+ {
+ // isturbulent is ignored because we know that turbulent surfaces
+ // can't be opaque
+ r_polydesc.drawspanlet = R_DrawSpanletOpaque;
+ }
+ else
+ {
+ if ( sw_stipplealpha->value )
+ {
+ if ( isturbulent )
+ {
+ if ( alpha > 0.33 )
+ r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple66;
+ else
+ r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple33;
+ }
+ else
+ {
+ if ( alpha > 0.33 )
+ r_polydesc.drawspanlet = R_DrawSpanlet66Stipple;
+ else
+ r_polydesc.drawspanlet = R_DrawSpanlet33Stipple;
+ }
+ }
+ else
+ {
+ if ( isturbulent )
+ {
+ if ( alpha > 0.33 )
+ r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended66;
+ else
+ r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended33;
+ }
+ else
+ {
+ if ( alpha > 0.33 )
+ r_polydesc.drawspanlet = R_DrawSpanlet66;
+ else
+ r_polydesc.drawspanlet = R_DrawSpanlet33;
+ }
+ }
+ }
+ }
+
+ // clip to the frustum in worldspace
+ nump = r_polydesc.nump;
+ clip_current = 0;
+
+ for (i=0 ; i<4 ; i++)
+ {
+ nump = R_ClipPolyFace (nump, &view_clipplanes[i]);
+ if (nump < 3)
+ return;
+ if (nump > MAXWORKINGVERTS)
+ ri.Sys_Error(ERR_DROP, "R_ClipAndDrawPoly: too many points: %d", nump );
+ }
+
+// transform vertices into viewspace and project
+ pv = &r_clip_verts[clip_current][0][0];
+
+ for (i=0 ; i<nump ; i++)
+ {
+ VectorSubtract (pv, r_origin, local);
+ TransformVector (local, transformed);
+
+ if (transformed[2] < NEAR_CLIP)
+ transformed[2] = NEAR_CLIP;
+
+ pout = &outverts[i];
+ pout->zi = 1.0 / transformed[2];
+
+ pout->s = pv[3];
+ pout->t = pv[4];
+
+ scale = xscale * pout->zi;
+ pout->u = (xcenter + scale * transformed[0]);
+
+ scale = yscale * pout->zi;
+ pout->v = (ycenter - scale * transformed[1]);
+
+ pv += sizeof (vec5_t) / sizeof (pv);
+ }
+
+// draw it
+ r_polydesc.nump = nump;
+ r_polydesc.pverts = outverts;
+
+ R_DrawPoly( isturbulent );
+}
+
+/*
+** R_BuildPolygonFromSurface
+*/
+void R_BuildPolygonFromSurface(msurface_t *fa)
+{
+ int i, lindex, lnumverts;
+ medge_t *pedges, *r_pedge;
+ int vertpage;
+ float *vec;
+ vec5_t *pverts;
+ float tmins[2] = { 0, 0 };
+
+ r_polydesc.nump = 0;
+
+ // reconstruct the polygon
+ pedges = currentmodel->edges;
+ lnumverts = fa->numedges;
+ vertpage = 0;
+
+ pverts = r_clip_verts[0];
+
+ for (i=0 ; i<lnumverts ; i++)
+ {
+ lindex = currentmodel->surfedges[fa->firstedge + i];
+
+ if (lindex > 0)
+ {
+ r_pedge = &pedges[lindex];
+ vec = currentmodel->vertexes[r_pedge->v[0]].position;
+ }
+ else
+ {
+ r_pedge = &pedges[-lindex];
+ vec = currentmodel->vertexes[r_pedge->v[1]].position;
+ }
+
+ VectorCopy (vec, pverts[i] );
+ }
+
+ VectorCopy( fa->texinfo->vecs[0], r_polydesc.vright );
+ VectorCopy( fa->texinfo->vecs[1], r_polydesc.vup );
+ VectorCopy( fa->plane->normal, r_polydesc.vpn );
+ VectorCopy( r_origin, r_polydesc.viewer_position );
+
+ if ( fa->flags & SURF_PLANEBACK )
+ {
+ VectorSubtract( vec3_origin, r_polydesc.vpn, r_polydesc.vpn );
+ }
+
+ if ( fa->texinfo->flags & SURF_WARP )
+ {
+ r_polydesc.pixels = fa->texinfo->image->pixels[0];
+ r_polydesc.pixel_width = fa->texinfo->image->width;
+ r_polydesc.pixel_height = fa->texinfo->image->height;
+ }
+ else
+ {
+ surfcache_t *scache;
+
+ scache = D_CacheSurface( fa, 0 );
+
+ r_polydesc.pixels = scache->data;
+ r_polydesc.pixel_width = scache->width;
+ r_polydesc.pixel_height = scache->height;
+
+ tmins[0] = fa->texturemins[0];
+ tmins[1] = fa->texturemins[1];
+ }
+
+ r_polydesc.dist = DotProduct( r_polydesc.vpn, pverts[0] );
+
+ r_polydesc.s_offset = fa->texinfo->vecs[0][3] - tmins[0];
+ r_polydesc.t_offset = fa->texinfo->vecs[1][3] - tmins[1];
+
+ // scrolling texture addition
+ if (fa->texinfo->flags & SURF_FLOWING)
+ {
+ r_polydesc.s_offset += -128 * ( (r_newrefdef.time*0.25) - (int)(r_newrefdef.time*0.25) );
+ }
+
+ r_polydesc.nump = lnumverts;
+}
+
+/*
+** R_PolygonCalculateGradients
+*/
+void R_PolygonCalculateGradients (void)
+{
+ vec3_t p_normal, p_saxis, p_taxis;
+ float distinv;
+
+ TransformVector (r_polydesc.vpn, p_normal);
+ TransformVector (r_polydesc.vright, p_saxis);
+ TransformVector (r_polydesc.vup, p_taxis);
+
+ distinv = 1.0 / (-(DotProduct (r_polydesc.viewer_position, r_polydesc.vpn)) + r_polydesc.dist );
+
+ d_sdivzstepu = p_saxis[0] * xscaleinv;
+ d_sdivzstepv = -p_saxis[1] * yscaleinv;
+ d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv;
+
+ d_tdivzstepu = p_taxis[0] * xscaleinv;
+ d_tdivzstepv = -p_taxis[1] * yscaleinv;
+ d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv;
+
+ d_zistepu = p_normal[0] * xscaleinv * distinv;
+ d_zistepv = -p_normal[1] * yscaleinv * distinv;
+ d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - ycenter * d_zistepv;
+
+ sadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vright) + r_polydesc.s_offset ) * 0x10000 );
+ tadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vup ) + r_polydesc.t_offset ) * 0x10000 );
+
+// -1 (-epsilon) so we never wander off the edge of the texture
+ bbextents = (r_polydesc.pixel_width << 16) - 1;
+ bbextentt = (r_polydesc.pixel_height << 16) - 1;
+}
+
+/*
+** R_DrawPoly
+**
+** Polygon drawing function. Uses the polygon described in r_polydesc
+** to calculate edges and gradients, then renders the resultant spans.
+**
+** This should NOT be called externally since it doesn't do clipping!
+*/
+static void R_DrawPoly( qboolean iswater )
+{
+ int i, nump;
+ float ymin, ymax;
+ emitpoint_t *pverts;
+ espan_t spans[MAXHEIGHT+1];
+
+ s_polygon_spans = spans;
+
+// find the top and bottom vertices, and make sure there's at least one scan to
+// draw
+ ymin = 999999.9;
+ ymax = -999999.9;
+ pverts = r_polydesc.pverts;
+
+ for (i=0 ; i<r_polydesc.nump ; i++)
+ {
+ if (pverts->v < ymin)
+ {
+ ymin = pverts->v;
+ s_minindex = i;
+ }
+
+ if (pverts->v > ymax)
+ {
+ ymax = pverts->v;
+ s_maxindex = i;
+ }
+
+ pverts++;
+ }
+
+ ymin = ceil (ymin);
+ ymax = ceil (ymax);
+
+ if (ymin >= ymax)
+ return; // doesn't cross any scans at all
+
+ cachewidth = r_polydesc.pixel_width;
+ cacheblock = r_polydesc.pixels;
+
+// copy the first vertex to the last vertex, so we don't have to deal with
+// wrapping
+ nump = r_polydesc.nump;
+ pverts = r_polydesc.pverts;
+ pverts[nump] = pverts[0];
+
+ R_PolygonCalculateGradients ();
+ R_PolygonScanLeftEdge ();
+ R_PolygonScanRightEdge ();
+
+ R_PolygonDrawSpans( s_polygon_spans, iswater );
+}
+
+/*
+** R_DrawAlphaSurfaces
+*/
+void R_DrawAlphaSurfaces( void )
+{
+ msurface_t *s = r_alpha_surfaces;
+
+ currentmodel = r_worldmodel;
+
+ modelorg[0] = -r_origin[0];
+ modelorg[1] = -r_origin[1];
+ modelorg[2] = -r_origin[2];
+
+ while ( s )
+ {
+ R_BuildPolygonFromSurface( s );
+
+ if (s->texinfo->flags & SURF_TRANS66)
+ R_ClipAndDrawPoly( 0.60f, ( s->texinfo->flags & SURF_WARP) != 0, true );
+ else
+ R_ClipAndDrawPoly( 0.30f, ( s->texinfo->flags & SURF_WARP) != 0, true );
+
+ s = s->nextalphasurface;
+ }
+
+ r_alpha_surfaces = NULL;
+}
+
+/*
+** R_IMFlatShadedQuad
+*/
+void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha )
+{
+ vec3_t s0, s1;
+
+ r_polydesc.nump = 4;
+ VectorCopy( r_origin, r_polydesc.viewer_position );
+
+ VectorCopy( a, r_clip_verts[0][0] );
+ VectorCopy( b, r_clip_verts[0][1] );
+ VectorCopy( c, r_clip_verts[0][2] );
+ VectorCopy( d, r_clip_verts[0][3] );
+
+ r_clip_verts[0][0][3] = 0;
+ r_clip_verts[0][1][3] = 0;
+ r_clip_verts[0][2][3] = 0;
+ r_clip_verts[0][3][3] = 0;
+
+ r_clip_verts[0][0][4] = 0;
+ r_clip_verts[0][1][4] = 0;
+ r_clip_verts[0][2][4] = 0;
+ r_clip_verts[0][3][4] = 0;
+
+ VectorSubtract( d, c, s0 );
+ VectorSubtract( c, b, s1 );
+ CrossProduct( s0, s1, r_polydesc.vpn );
+ VectorNormalize( r_polydesc.vpn );
+
+ r_polydesc.dist = DotProduct( r_polydesc.vpn, r_clip_verts[0][0] );
+
+ r_polyblendcolor = color;
+
+ R_ClipAndDrawPoly( alpha, false, false );
+}
+
--- /dev/null
+++ b/ref/r_polyse.c
@@ -1,0 +1,1539 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// d_polyset.c: routines for drawing sets of polygons sharing the same
+// texture (used for Alias models)
+
+#include "r_local.h"
+
+int rand1k[] = {
+#include "rand1k.h"
+};
+
+#define MASK_1K 0x3FF
+
+int rand1k_index = 0;
+
+// TODO: put in span spilling to shrink list size
+// !!! if this is changed, it must be changed in d_polysa.s too !!!
+#define DPS_MAXSPANS MAXHEIGHT+1
+ // 1 extra for spanpackage that marks end
+
+// !!! if this is changed, it must be changed in asm_draw.h too !!!
+typedef struct {
+ void *pdest;
+ short *pz;
+ int count;
+ byte *ptex;
+ int sfrac, tfrac, light, zi;
+} spanpackage_t;
+
+typedef struct {
+ int isflattop;
+ int numleftedges;
+ int *pleftedgevert0;
+ int *pleftedgevert1;
+ int *pleftedgevert2;
+ int numrightedges;
+ int *prightedgevert0;
+ int *prightedgevert1;
+ int *prightedgevert2;
+} edgetable;
+
+aliastriangleparms_t aliastriangleparms;
+
+int r_p0[6], r_p1[6], r_p2[6];
+
+byte *d_pcolormap;
+
+int d_aflatcolor;
+int d_xdenom;
+
+edgetable *pedgetable;
+
+edgetable edgetables[12] = {
+ {0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 },
+ {0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL},
+ {1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL},
+ {0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 },
+ {0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL},
+ {0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL},
+ {0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 },
+ {0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL},
+ {0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL},
+ {1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL},
+ {1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL},
+ {0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL},
+};
+
+// FIXME: some of these can become statics
+int a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole;
+int r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy;
+int r_zistepx, r_zistepy;
+int d_aspancount, d_countextrastep;
+
+spanpackage_t *a_spans;
+spanpackage_t *d_pedgespanpackage;
+static int ystart;
+byte *d_pdest, *d_ptex;
+short *d_pz;
+int d_sfrac, d_tfrac, d_light, d_zi;
+int d_ptexextrastep, d_sfracextrastep;
+int d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
+int d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
+int d_sfracbasestep, d_tfracbasestep;
+int d_ziextrastep, d_zibasestep;
+int d_pzextrastep, d_pzbasestep;
+
+typedef struct {
+ int quotient;
+ int remainder;
+} adivtab_t;
+
+static adivtab_t adivtab[32*32] = {
+#include "adivtab.h"
+};
+
+byte *skintable[MAX_LBM_HEIGHT];
+int skinwidth;
+byte *skinstart;
+
+void (*d_pdrawspans)(spanpackage_t *pspanpackage);
+
+void R_PolysetDrawSpans8_33 (spanpackage_t *pspanpackage);
+void R_PolysetDrawSpans8_66 (spanpackage_t *pspanpackage);
+void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage);
+
+void R_PolysetDrawThreshSpans8 (spanpackage_t *pspanpackage);
+void R_PolysetCalcGradients (int skinwidth);
+void R_DrawNonSubdiv (void);
+void R_PolysetSetEdgeTable (void);
+void R_RasterizeAliasPolySmooth (void);
+void R_PolysetScanLeftEdge(int height);
+void R_PolysetScanLeftEdge_C(int height);
+
+// ======================
+// PGM
+// 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
+byte iractive = 0;
+byte irtable[256] = { 79, 78, 77, 76, 75, 74, 73, 72, // black/white
+ 71, 70, 69, 68, 67, 66, 65, 64,
+ 64, 65, 66, 67, 68, 69, 70, 71, // dark taupe
+ 72, 73, 74, 75, 76, 77, 78, 79,
+
+ 64, 65, 66, 67, 68, 69, 70, 71, // slate grey
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 208, 208, 208, 208, 208, 208, 208, 208, // unused?'
+ 64, 66, 68, 70, 72, 74, 76, 78, // dark yellow
+
+ 64, 65, 66, 67, 68, 69, 70, 71, // dark red
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 64, 65, 66, 67, 68, 69, 70, 71, // grey/tan
+ 72, 73, 74, 75, 76, 77, 78, 79,
+
+ 64, 66, 68, 70, 72, 74, 76, 78, // chocolate
+ 68, 67, 66, 65, 64, 65, 66, 67, // mauve / teal
+ 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 76, 77, 77, 78, 78, 79, 79,
+
+ 64, 65, 66, 67, 68, 69, 70, 71, // more mauve
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 64, 65, 66, 67, 68, 69, 70, 71, // olive
+ 72, 73, 74, 75, 76, 77, 78, 79,
+
+ 64, 65, 66, 67, 68, 69, 70, 71, // maroon
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 64, 65, 66, 67, 68, 69, 70, 71, // sky blue
+ 72, 73, 74, 75, 76, 77, 78, 79,
+
+ 64, 65, 66, 67, 68, 69, 70, 71, // olive again
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 64, 65, 66, 67, 68, 69, 70, 71, // nuclear green
+ 64, 65, 66, 67, 68, 69, 70, 71, // bright yellow
+
+ 64, 65, 66, 67, 68, 69, 70, 71, // fire colors
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 208, 208, 64, 64, 70, 71, 72, 64, // mishmash1
+ 66, 68, 70, 64, 65, 66, 67, 68}; // mishmash2
+// PGM
+// ======================
+
+/*
+================
+R_PolysetUpdateTables
+================
+*/
+void R_PolysetUpdateTables (void)
+{
+ int i;
+ byte *s;
+
+ if (r_affinetridesc.skinwidth != skinwidth ||
+ r_affinetridesc.pskin != skinstart)
+ {
+ skinwidth = r_affinetridesc.skinwidth;
+ skinstart = r_affinetridesc.pskin;
+ s = skinstart;
+ for (i=0 ; i<MAX_LBM_HEIGHT ; i++, s+=skinwidth)
+ skintable[i] = s;
+ }
+}
+
+
+/*
+================
+R_DrawTriangle
+================
+*/
+void R_DrawTriangle( void )
+{
+ spanpackage_t spans[DPS_MAXSPANS];
+
+ int dv1_ab, dv0_ac;
+ int dv0_ab, dv1_ac;
+
+ /*
+ d_xdenom = ( aliastriangleparms.a->v[1] - aliastriangleparms.b->v[1] ) * ( aliastriangleparms.a->v[0] - aliastriangleparms.c->v[0] ) -
+ ( aliastriangleparms.a->v[0] - aliastriangleparms.b->v[0] ) * ( aliastriangleparms.a->v[1] - aliastriangleparms.c->v[1] );
+ */
+
+ dv0_ab = aliastriangleparms.a->u - aliastriangleparms.b->u;
+ dv1_ab = aliastriangleparms.a->v - aliastriangleparms.b->v;
+
+ if ( !( dv0_ab | dv1_ab ) )
+ return;
+
+ dv0_ac = aliastriangleparms.a->u - aliastriangleparms.c->u;
+ dv1_ac = aliastriangleparms.a->v - aliastriangleparms.c->v;
+
+ if ( !( dv0_ac | dv1_ac ) )
+ return;
+
+ d_xdenom = ( dv0_ac * dv1_ab ) - ( dv0_ab * dv1_ac );
+
+ if ( d_xdenom < 0 )
+ {
+ a_spans = spans;
+
+ r_p0[0] = aliastriangleparms.a->u; // u
+ r_p0[1] = aliastriangleparms.a->v; // v
+ r_p0[2] = aliastriangleparms.a->s; // s
+ r_p0[3] = aliastriangleparms.a->t; // t
+ r_p0[4] = aliastriangleparms.a->l; // light
+ r_p0[5] = aliastriangleparms.a->zi; // iz
+
+ r_p1[0] = aliastriangleparms.b->u;
+ r_p1[1] = aliastriangleparms.b->v;
+ r_p1[2] = aliastriangleparms.b->s;
+ r_p1[3] = aliastriangleparms.b->t;
+ r_p1[4] = aliastriangleparms.b->l;
+ r_p1[5] = aliastriangleparms.b->zi;
+
+ r_p2[0] = aliastriangleparms.c->u;
+ r_p2[1] = aliastriangleparms.c->v;
+ r_p2[2] = aliastriangleparms.c->s;
+ r_p2[3] = aliastriangleparms.c->t;
+ r_p2[4] = aliastriangleparms.c->l;
+ r_p2[5] = aliastriangleparms.c->zi;
+
+ R_PolysetSetEdgeTable ();
+ R_RasterizeAliasPolySmooth ();
+ }
+}
+
+
+/*
+===================
+R_PolysetScanLeftEdge_C
+====================
+*/
+void R_PolysetScanLeftEdge_C(int height)
+{
+ do
+ {
+ d_pedgespanpackage->pdest = d_pdest;
+ d_pedgespanpackage->pz = d_pz;
+ d_pedgespanpackage->count = d_aspancount;
+ d_pedgespanpackage->ptex = d_ptex;
+
+ d_pedgespanpackage->sfrac = d_sfrac;
+ d_pedgespanpackage->tfrac = d_tfrac;
+
+ // FIXME: need to clamp l, s, t, at both ends?
+ d_pedgespanpackage->light = d_light;
+ d_pedgespanpackage->zi = d_zi;
+
+ d_pedgespanpackage++;
+
+ errorterm += erroradjustup;
+ if (errorterm >= 0)
+ {
+ d_pdest += d_pdestextrastep;
+ d_pz += d_pzextrastep;
+ d_aspancount += d_countextrastep;
+ d_ptex += d_ptexextrastep;
+ d_sfrac += d_sfracextrastep;
+ d_ptex += d_sfrac >> 16;
+
+ d_sfrac &= 0xFFFF;
+ d_tfrac += d_tfracextrastep;
+ if (d_tfrac & 0x10000)
+ {
+ d_ptex += r_affinetridesc.skinwidth;
+ d_tfrac &= 0xFFFF;
+ }
+ d_light += d_lightextrastep;
+ d_zi += d_ziextrastep;
+ errorterm -= erroradjustdown;
+ }
+ else
+ {
+ d_pdest += d_pdestbasestep;
+ d_pz += d_pzbasestep;
+ d_aspancount += ubasestep;
+ d_ptex += d_ptexbasestep;
+ d_sfrac += d_sfracbasestep;
+ d_ptex += d_sfrac >> 16;
+ d_sfrac &= 0xFFFF;
+ d_tfrac += d_tfracbasestep;
+ if (d_tfrac & 0x10000)
+ {
+ d_ptex += r_affinetridesc.skinwidth;
+ d_tfrac &= 0xFFFF;
+ }
+ d_light += d_lightbasestep;
+ d_zi += d_zibasestep;
+ }
+ } while (--height);
+}
+
+/*
+===================
+FloorDivMod
+
+Returns mathematically correct (floor-based) quotient and remainder for
+numer and denom, both of which should contain no fractional part. The
+quotient must fit in 32 bits.
+FIXME: GET RID OF THIS! (FloorDivMod)
+====================
+*/
+void FloorDivMod (float numer, float denom, int *quotient,
+ int *rem)
+{
+ int q, r;
+ float x;
+
+ if (numer >= 0.0)
+ {
+
+ x = floor(numer / denom);
+ q = (int)x;
+ r = (int)floor(numer - (x * denom));
+ }
+ else
+ {
+ //
+ // perform operations with positive values, and fix mod to make floor-based
+ //
+ x = floor(-numer / denom);
+ q = -(int)x;
+ r = (int)floor(-numer - (x * denom));
+ if (r != 0)
+ {
+ q--;
+ r = (int)denom - r;
+ }
+ }
+
+ *quotient = q;
+ *rem = r;
+}
+
+
+/*
+===================
+R_PolysetSetUpForLineScan
+====================
+*/
+void R_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
+ fixed8_t endvertu, fixed8_t endvertv)
+{
+ float dm, dn;
+ int tm, tn;
+ adivtab_t *ptemp;
+
+// TODO: implement x86 version
+
+ errorterm = -1;
+
+ tm = endvertu - startvertu;
+ tn = endvertv - startvertv;
+
+ if (((tm <= 16) && (tm >= -15)) &&
+ ((tn <= 16) && (tn >= -15)))
+ {
+ ptemp = &adivtab[((tm+15) << 5) + (tn+15)];
+ ubasestep = ptemp->quotient;
+ erroradjustup = ptemp->remainder;
+ erroradjustdown = tn;
+ }
+ else
+ {
+ dm = tm;
+ dn = tn;
+
+ FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
+
+ erroradjustdown = dn;
+ }
+}
+
+
+
+/*
+================
+R_PolysetCalcGradients
+================
+*/
+#if id386 && !defined __linux__
+void R_PolysetCalcGradients( int skinwidth )
+{
+ static float xstepdenominv, ystepdenominv, t0, t1;
+ static float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
+ static float one = 1.0F, negative_one = -1.0F;
+ static unsigned long t0_int, t1_int;
+
+ extern unsigned long fpu_sp24_ceil_cw, fpu_ceil_cw, fpu_chop_cw;
+
+ /*
+ p00_minus_p20 = r_p0[0] - r_p2[0];
+ p01_minus_p21 = r_p0[1] - r_p2[1];
+ p10_minus_p20 = r_p1[0] - r_p2[0];
+ p11_minus_p21 = r_p1[1] - r_p2[1];
+ */
+
+ __asm mov eax, dword ptr [r_p0+0]
+ __asm mov ebx, dword ptr [r_p0+4]
+ __asm sub eax, dword ptr [r_p2+0]
+ __asm sub ebx, dword ptr [r_p2+4]
+ __asm mov p00_minus_p20, eax
+ __asm mov p01_minus_p21, ebx
+ __asm fild dword ptr p00_minus_p20
+ __asm fild dword ptr p01_minus_p21
+ __asm mov eax, dword ptr [r_p1+0]
+ __asm mov ebx, dword ptr [r_p1+4]
+ __asm sub eax, dword ptr [r_p2+0]
+ __asm sub ebx, dword ptr [r_p2+4]
+ __asm fstp p01_minus_p21
+ __asm fstp p00_minus_p20
+ __asm mov p10_minus_p20, eax
+ __asm mov p11_minus_p21, ebx
+ __asm fild dword ptr p10_minus_p20
+ __asm fild dword ptr p11_minus_p21
+ __asm fstp p11_minus_p21
+ __asm fstp p10_minus_p20
+
+ /*
+ xstepdenominv = 1.0 / (float)d_xdenom;
+
+ ystepdenominv = -xstepdenominv;
+ */
+
+ /*
+ ** put FPU in single precision ceil mode
+ */
+ __asm fldcw word ptr [fpu_sp24_ceil_cw]
+// __asm fldcw word ptr [fpu_ceil_cw]
+
+ __asm fild dword ptr d_xdenom ; d_xdenom
+ __asm fdivr one ; 1 / d_xdenom
+ __asm fst xstepdenominv ;
+ __asm fmul negative_one ; -( 1 / d_xdenom )
+
+// ceil () for light so positive steps are exaggerated, negative steps
+// diminished, pushing us away from underflow toward overflow. Underflow is
+// very visible, overflow is very unlikely, because of ambient lighting
+ /*
+ t0 = r_p0[4] - r_p2[4];
+ t1 = r_p1[4] - r_p2[4];
+ r_lstepx = (int)
+ ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
+ r_lstepy = (int)
+ ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
+ */
+ __asm mov eax, dword ptr [r_p0+16]
+ __asm mov ebx, dword ptr [r_p1+16]
+ __asm sub eax, dword ptr [r_p2+16]
+ __asm sub ebx, dword ptr [r_p2+16]
+
+ __asm fstp ystepdenominv ; (empty)
+
+ __asm mov t0_int, eax
+ __asm mov t1_int, ebx
+ __asm fild t0_int ; t0
+ __asm fild t1_int ; t1 | t0
+ __asm fxch st(1) ; t0 | t1
+ __asm fstp t0 ; t1
+ __asm fst t1 ; t1
+ __asm fmul p01_minus_p21 ; t1 * p01_minus_p21
+ __asm fld t0 ; t0 | t1 * p01_minus_p21
+ __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21
+ __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
+ __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
+ __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20
+ __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20
+ __asm fxch st(1)
+ __asm fmul ystepdenominv ; r_lstepy | r_lstepx
+ __asm fxch st(1) ; r_lstepx | r_lstepy
+ __asm fistp dword ptr [r_lstepx]
+ __asm fistp dword ptr [r_lstepy]
+
+ /*
+ ** put FPU back into extended precision chop mode
+ */
+ __asm fldcw word ptr [fpu_chop_cw]
+
+ /*
+ t0 = r_p0[2] - r_p2[2];
+ t1 = r_p1[2] - r_p2[2];
+ r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+ xstepdenominv);
+ r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) *
+ ystepdenominv);
+ */
+ __asm mov eax, dword ptr [r_p0+8]
+ __asm mov ebx, dword ptr [r_p1+8]
+ __asm sub eax, dword ptr [r_p2+8]
+ __asm sub ebx, dword ptr [r_p2+8]
+ __asm mov t0_int, eax
+ __asm mov t1_int, ebx
+ __asm fild t0_int ; t0
+ __asm fild t1_int ; t1 | t0
+ __asm fxch st(1) ; t0 | t1
+ __asm fstp t0 ; t1
+ __asm fst t1 ; (empty)
+
+ __asm fmul p01_minus_p21 ; t1 * p01_minus_p21
+ __asm fld t0 ; t0 | t1 * p01_minus_p21
+ __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21
+ __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
+ __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
+ __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20
+ __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20
+ __asm fxch st(1)
+ __asm fmul ystepdenominv ; r_lstepy | r_lstepx
+ __asm fxch st(1) ; r_lstepx | r_lstepy
+ __asm fistp dword ptr [r_sstepx]
+ __asm fistp dword ptr [r_sstepy]
+
+ /*
+ t0 = r_p0[3] - r_p2[3];
+ t1 = r_p1[3] - r_p2[3];
+ r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+ xstepdenominv);
+ r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+ ystepdenominv);
+ */
+ __asm mov eax, dword ptr [r_p0+12]
+ __asm mov ebx, dword ptr [r_p1+12]
+ __asm sub eax, dword ptr [r_p2+12]
+ __asm sub ebx, dword ptr [r_p2+12]
+
+ __asm mov t0_int, eax
+ __asm mov t1_int, ebx
+ __asm fild t0_int ; t0
+ __asm fild t1_int ; t1 | t0
+ __asm fxch st(1) ; t0 | t1
+ __asm fstp t0 ; t1
+ __asm fst t1 ; (empty)
+
+ __asm fmul p01_minus_p21 ; t1 * p01_minus_p21
+ __asm fld t0 ; t0 | t1 * p01_minus_p21
+ __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21
+ __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
+ __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
+ __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20
+ __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20
+ __asm fxch st(1)
+ __asm fmul ystepdenominv ; r_lstepy | r_lstepx
+ __asm fxch st(1) ; r_lstepx | r_lstepy
+ __asm fistp dword ptr [r_tstepx]
+ __asm fistp dword ptr [r_tstepy]
+
+ /*
+ t0 = r_p0[5] - r_p2[5];
+ t1 = r_p1[5] - r_p2[5];
+ r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+ xstepdenominv);
+ r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+ ystepdenominv);
+ */
+ __asm mov eax, dword ptr [r_p0+20]
+ __asm mov ebx, dword ptr [r_p1+20]
+ __asm sub eax, dword ptr [r_p2+20]
+ __asm sub ebx, dword ptr [r_p2+20]
+
+ __asm mov t0_int, eax
+ __asm mov t1_int, ebx
+ __asm fild t0_int ; t0
+ __asm fild t1_int ; t1 | t0
+ __asm fxch st(1) ; t0 | t1
+ __asm fstp t0 ; t1
+ __asm fst t1 ; (empty)
+
+ __asm fmul p01_minus_p21 ; t1 * p01_minus_p21
+ __asm fld t0 ; t0 | t1 * p01_minus_p21
+ __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
+ __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21
+ __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
+ __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
+ __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20
+ __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20
+ __asm fxch st(1)
+ __asm fmul ystepdenominv ; r_lstepy | r_lstepx
+ __asm fxch st(1) ; r_lstepx | r_lstepy
+ __asm fistp dword ptr [r_zistepx]
+ __asm fistp dword ptr [r_zistepy]
+
+ /*
+#if id386ALIAS
+ a_sstepxfrac = r_sstepx << 16;
+ a_tstepxfrac = r_tstepx << 16;
+#else
+ a_sstepxfrac = r_sstepx & 0xFFFF;
+ a_tstepxfrac = r_tstepx & 0xFFFF;
+#endif
+ */
+ __asm mov eax, d_pdrawspans
+ __asm cmp eax, offset R_PolysetDrawSpans8_Opaque
+ __asm mov eax, r_sstepx
+ __asm mov ebx, r_tstepx
+ __asm jne translucent
+//#if id386ALIAS
+ __asm shl eax, 16
+ __asm shl ebx, 16
+ __asm jmp done_with_steps
+//#else
+translucent:
+ __asm and eax, 0ffffh
+ __asm and ebx, 0ffffh
+//#endif
+done_with_steps:
+ __asm mov a_sstepxfrac, eax
+ __asm mov a_tstepxfrac, ebx
+
+ /*
+ a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
+ */
+ __asm mov ebx, r_tstepx
+ __asm mov ecx, r_sstepx
+ __asm sar ebx, 16
+ __asm mov eax, skinwidth
+ __asm mul ebx
+ __asm sar ecx, 16
+ __asm add eax, ecx
+ __asm mov a_ststepxwhole, eax
+}
+#else
+void R_PolysetCalcGradients (int skinwidth)
+{
+ float xstepdenominv, ystepdenominv, t0, t1;
+ float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
+
+ p00_minus_p20 = r_p0[0] - r_p2[0];
+ p01_minus_p21 = r_p0[1] - r_p2[1];
+ p10_minus_p20 = r_p1[0] - r_p2[0];
+ p11_minus_p21 = r_p1[1] - r_p2[1];
+
+ xstepdenominv = 1.0 / (float)d_xdenom;
+
+ ystepdenominv = -xstepdenominv;
+
+// ceil () for light so positive steps are exaggerated, negative steps
+// diminished, pushing us away from underflow toward overflow. Underflow is
+// very visible, overflow is very unlikely, because of ambient lighting
+ t0 = r_p0[4] - r_p2[4];
+ t1 = r_p1[4] - r_p2[4];
+ r_lstepx = (int)
+ ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
+ r_lstepy = (int)
+ ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
+
+ t0 = r_p0[2] - r_p2[2];
+ t1 = r_p1[2] - r_p2[2];
+ r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+ xstepdenominv);
+ r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) *
+ ystepdenominv);
+
+ t0 = r_p0[3] - r_p2[3];
+ t1 = r_p1[3] - r_p2[3];
+ r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+ xstepdenominv);
+ r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+ ystepdenominv);
+
+ t0 = r_p0[5] - r_p2[5];
+ t1 = r_p1[5] - r_p2[5];
+ r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
+ xstepdenominv);
+ r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
+ ystepdenominv);
+
+//#if id386ALIAS
+#if id386
+ if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
+ {
+ a_sstepxfrac = r_sstepx << 16;
+ a_tstepxfrac = r_tstepx << 16;
+ }
+ else
+#endif
+ {
+//#else
+ a_sstepxfrac = r_sstepx & 0xFFFF;
+ a_tstepxfrac = r_tstepx & 0xFFFF;
+ }
+//#endif
+
+ a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
+}
+#endif
+
+/*
+================
+R_PolysetDrawThreshSpans8
+
+Random fizzle fade rasterizer
+================
+*/
+void R_PolysetDrawThreshSpans8 (spanpackage_t *pspanpackage)
+{
+ int lcount;
+ byte *lpdest;
+ byte *lptex;
+ int lsfrac, ltfrac;
+ int llight;
+ int lzi;
+ short *lpz;
+
+ do
+ {
+ lcount = d_aspancount - pspanpackage->count;
+
+ errorterm += erroradjustup;
+ if (errorterm >= 0)
+ {
+ d_aspancount += d_countextrastep;
+ errorterm -= erroradjustdown;
+ }
+ else
+ {
+ d_aspancount += ubasestep;
+ }
+
+ if (lcount)
+ {
+ lpdest = pspanpackage->pdest;
+ lptex = pspanpackage->ptex;
+ lpz = pspanpackage->pz;
+ lsfrac = pspanpackage->sfrac;
+ ltfrac = pspanpackage->tfrac;
+ llight = pspanpackage->light;
+ lzi = pspanpackage->zi;
+
+ do
+ {
+ if ((lzi >> 16) >= *lpz)
+ {
+ rand1k_index = (rand1k_index + 1) & MASK_1K;
+
+ if (rand1k[rand1k_index] <= r_affinetridesc.vis_thresh)
+ {
+ *lpdest = ((byte *)vid.colormap)[*lptex + (llight & 0xFF00)];
+ *lpz = lzi >> 16;
+ }
+ }
+
+ lpdest++;
+ lzi += r_zistepx;
+ lpz++;
+ llight += r_lstepx;
+ lptex += a_ststepxwhole;
+ lsfrac += a_sstepxfrac;
+ lptex += lsfrac >> 16;
+ lsfrac &= 0xFFFF;
+ ltfrac += a_tstepxfrac;
+ if (ltfrac & 0x10000)
+ {
+ lptex += r_affinetridesc.skinwidth;
+ ltfrac &= 0xFFFF;
+ }
+ } while (--lcount);
+ }
+
+ pspanpackage++;
+ } while (pspanpackage->count != -999999);
+}
+
+
+/*
+================
+R_PolysetDrawSpans8
+================
+*/
+void R_PolysetDrawSpans8_33( spanpackage_t *pspanpackage)
+{
+ int lcount;
+ byte *lpdest;
+ byte *lptex;
+ int lsfrac, ltfrac;
+ int llight;
+ int lzi;
+ short *lpz;
+
+ do
+ {
+ lcount = d_aspancount - pspanpackage->count;
+
+ errorterm += erroradjustup;
+ if (errorterm >= 0)
+ {
+ d_aspancount += d_countextrastep;
+ errorterm -= erroradjustdown;
+ }
+ else
+ {
+ d_aspancount += ubasestep;
+ }
+
+ if (lcount)
+ {
+ lpdest = pspanpackage->pdest;
+ lptex = pspanpackage->ptex;
+ lpz = pspanpackage->pz;
+ lsfrac = pspanpackage->sfrac;
+ ltfrac = pspanpackage->tfrac;
+ llight = pspanpackage->light;
+ lzi = pspanpackage->zi;
+
+ do
+ {
+ if ((lzi >> 16) >= *lpz)
+ {
+ int temp = vid.colormap[*lptex + ( llight & 0xFF00 )];
+
+ *lpdest = vid.alphamap[temp+ *lpdest*256];
+ }
+ lpdest++;
+ lzi += r_zistepx;
+ lpz++;
+ llight += r_lstepx;
+ lptex += a_ststepxwhole;
+ lsfrac += a_sstepxfrac;
+ lptex += lsfrac >> 16;
+ lsfrac &= 0xFFFF;
+ ltfrac += a_tstepxfrac;
+ if (ltfrac & 0x10000)
+ {
+ lptex += r_affinetridesc.skinwidth;
+ ltfrac &= 0xFFFF;
+ }
+ } while (--lcount);
+ }
+
+ pspanpackage++;
+ } while (pspanpackage->count != -999999);
+}
+
+void R_PolysetDrawSpansConstant8_33( spanpackage_t *pspanpackage)
+{
+ int lcount;
+ byte *lpdest;
+ int lzi;
+ short *lpz;
+
+ do
+ {
+ lcount = d_aspancount - pspanpackage->count;
+
+ errorterm += erroradjustup;
+ if (errorterm >= 0)
+ {
+ d_aspancount += d_countextrastep;
+ errorterm -= erroradjustdown;
+ }
+ else
+ {
+ d_aspancount += ubasestep;
+ }
+
+ if (lcount)
+ {
+ lpdest = pspanpackage->pdest;
+ lpz = pspanpackage->pz;
+ lzi = pspanpackage->zi;
+
+ do
+ {
+ if ((lzi >> 16) >= *lpz)
+ {
+ *lpdest = vid.alphamap[r_aliasblendcolor + *lpdest*256];
+ }
+ lpdest++;
+ lzi += r_zistepx;
+ lpz++;
+ } while (--lcount);
+ }
+
+ pspanpackage++;
+ } while (pspanpackage->count != -999999);
+}
+
+void R_PolysetDrawSpans8_66(spanpackage_t *pspanpackage)
+{
+ int lcount;
+ byte *lpdest;
+ byte *lptex;
+ int lsfrac, ltfrac;
+ int llight;
+ int lzi;
+ short *lpz;
+
+ do
+ {
+ lcount = d_aspancount - pspanpackage->count;
+
+ errorterm += erroradjustup;
+ if (errorterm >= 0)
+ {
+ d_aspancount += d_countextrastep;
+ errorterm -= erroradjustdown;
+ }
+ else
+ {
+ d_aspancount += ubasestep;
+ }
+
+ if (lcount)
+ {
+ lpdest = pspanpackage->pdest;
+ lptex = pspanpackage->ptex;
+ lpz = pspanpackage->pz;
+ lsfrac = pspanpackage->sfrac;
+ ltfrac = pspanpackage->tfrac;
+ llight = pspanpackage->light;
+ lzi = pspanpackage->zi;
+
+ do
+ {
+ if ((lzi >> 16) >= *lpz)
+ {
+ int temp = vid.colormap[*lptex + ( llight & 0xFF00 )];
+
+ *lpdest = vid.alphamap[temp*256 + *lpdest];
+ *lpz = lzi >> 16;
+ }
+ lpdest++;
+ lzi += r_zistepx;
+ lpz++;
+ llight += r_lstepx;
+ lptex += a_ststepxwhole;
+ lsfrac += a_sstepxfrac;
+ lptex += lsfrac >> 16;
+ lsfrac &= 0xFFFF;
+ ltfrac += a_tstepxfrac;
+ if (ltfrac & 0x10000)
+ {
+ lptex += r_affinetridesc.skinwidth;
+ ltfrac &= 0xFFFF;
+ }
+ } while (--lcount);
+ }
+
+ pspanpackage++;
+ } while (pspanpackage->count != -999999);
+}
+
+void R_PolysetDrawSpansConstant8_66( spanpackage_t *pspanpackage)
+{
+ int lcount;
+ byte *lpdest;
+ int lzi;
+ short *lpz;
+
+ do
+ {
+ lcount = d_aspancount - pspanpackage->count;
+
+ errorterm += erroradjustup;
+ if (errorterm >= 0)
+ {
+ d_aspancount += d_countextrastep;
+ errorterm -= erroradjustdown;
+ }
+ else
+ {
+ d_aspancount += ubasestep;
+ }
+
+ if (lcount)
+ {
+ lpdest = pspanpackage->pdest;
+ lpz = pspanpackage->pz;
+ lzi = pspanpackage->zi;
+
+ do
+ {
+ if ((lzi >> 16) >= *lpz)
+ {
+ *lpdest = vid.alphamap[r_aliasblendcolor*256 + *lpdest];
+ }
+ lpdest++;
+ lzi += r_zistepx;
+ lpz++;
+ } while (--lcount);
+ }
+
+ pspanpackage++;
+ } while (pspanpackage->count != -999999);
+}
+
+#if !id386
+void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage)
+{
+ int lcount;
+
+ do
+ {
+ lcount = d_aspancount - pspanpackage->count;
+
+ errorterm += erroradjustup;
+ if (errorterm >= 0)
+ {
+ d_aspancount += d_countextrastep;
+ errorterm -= erroradjustdown;
+ }
+ else
+ {
+ d_aspancount += ubasestep;
+ }
+
+ if (lcount)
+ {
+ int lsfrac, ltfrac;
+ byte *lpdest;
+ byte *lptex;
+ int llight;
+ int lzi;
+ short *lpz;
+
+ lpdest = pspanpackage->pdest;
+ lptex = pspanpackage->ptex;
+ lpz = pspanpackage->pz;
+ lsfrac = pspanpackage->sfrac;
+ ltfrac = pspanpackage->tfrac;
+ llight = pspanpackage->light;
+ lzi = pspanpackage->zi;
+
+ do
+ {
+ if ((lzi >> 16) >= *lpz)
+ {
+//PGM
+ if(r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
+ *lpdest = ((byte *)vid.colormap)[irtable[*lptex]];
+ else
+ *lpdest = ((byte *)vid.colormap)[*lptex + (llight & 0xFF00)];
+//PGM
+ *lpz = lzi >> 16;
+ }
+ lpdest++;
+ lzi += r_zistepx;
+ lpz++;
+ llight += r_lstepx;
+ lptex += a_ststepxwhole;
+ lsfrac += a_sstepxfrac;
+ lptex += lsfrac >> 16;
+ lsfrac &= 0xFFFF;
+ ltfrac += a_tstepxfrac;
+ if (ltfrac & 0x10000)
+ {
+ lptex += r_affinetridesc.skinwidth;
+ ltfrac &= 0xFFFF;
+ }
+ } while (--lcount);
+ }
+
+ pspanpackage++;
+ } while (pspanpackage->count != -999999);
+}
+#endif
+
+
+/*
+================
+R_PolysetFillSpans8
+================
+*/
+void R_PolysetFillSpans8 (spanpackage_t *pspanpackage)
+{
+ int color;
+
+// FIXME: do z buffering
+
+ color = d_aflatcolor++;
+
+ while (1)
+ {
+ int lcount;
+ byte *lpdest;
+
+ lcount = pspanpackage->count;
+
+ if (lcount == -1)
+ return;
+
+ if (lcount)
+ {
+ lpdest = pspanpackage->pdest;
+
+ do
+ {
+ *lpdest++ = color;
+ } while (--lcount);
+ }
+
+ pspanpackage++;
+ }
+}
+
+/*
+================
+R_RasterizeAliasPolySmooth
+================
+*/
+void R_RasterizeAliasPolySmooth (void)
+{
+ int initialleftheight, initialrightheight;
+ int *plefttop, *prighttop, *pleftbottom, *prightbottom;
+ int working_lstepx, originalcount;
+
+ plefttop = pedgetable->pleftedgevert0;
+ prighttop = pedgetable->prightedgevert0;
+
+ pleftbottom = pedgetable->pleftedgevert1;
+ prightbottom = pedgetable->prightedgevert1;
+
+ initialleftheight = pleftbottom[1] - plefttop[1];
+ initialrightheight = prightbottom[1] - prighttop[1];
+
+//
+// set the s, t, and light gradients, which are consistent across the triangle
+// because being a triangle, things are affine
+//
+ R_PolysetCalcGradients (r_affinetridesc.skinwidth);
+//
+// rasterize the polygon
+//
+
+//
+// scan out the top (and possibly only) part of the left edge
+//
+ d_pedgespanpackage = a_spans;
+
+ ystart = plefttop[1];
+ d_aspancount = plefttop[0] - prighttop[0];
+
+ d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
+ (plefttop[3] >> 16) * r_affinetridesc.skinwidth;
+//#if id386ALIAS
+#if id386
+ if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
+ {
+ d_sfrac = (plefttop[2] & 0xFFFF) << 16;
+ d_tfrac = (plefttop[3] & 0xFFFF) << 16;
+ }
+//#else
+ else
+#endif
+ {
+ d_sfrac = plefttop[2] & 0xFFFF;
+ d_tfrac = plefttop[3] & 0xFFFF;
+ }
+//#endif
+ d_light = plefttop[4];
+ d_zi = plefttop[5];
+
+ d_pdest = (byte *)d_viewbuffer +
+ ystart * r_screenwidth + plefttop[0];
+ d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
+
+ if (initialleftheight == 1)
+ {
+ d_pedgespanpackage->pdest = d_pdest;
+ d_pedgespanpackage->pz = d_pz;
+ d_pedgespanpackage->count = d_aspancount;
+ d_pedgespanpackage->ptex = d_ptex;
+
+ d_pedgespanpackage->sfrac = d_sfrac;
+ d_pedgespanpackage->tfrac = d_tfrac;
+
+ // FIXME: need to clamp l, s, t, at both ends?
+ d_pedgespanpackage->light = d_light;
+ d_pedgespanpackage->zi = d_zi;
+
+ d_pedgespanpackage++;
+ }
+ else
+ {
+ R_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
+ pleftbottom[0], pleftbottom[1]);
+
+//#if id386ALIAS
+#if id386
+ if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
+ {
+ d_pzbasestep = (d_zwidth + ubasestep) << 1;
+ d_pzextrastep = d_pzbasestep + 2;
+ }
+//#else
+ else
+#endif
+ {
+ d_pzbasestep = d_zwidth + ubasestep;
+ d_pzextrastep = d_pzbasestep + 1;
+ }
+//#endif
+
+ d_pdestbasestep = r_screenwidth + ubasestep;
+ d_pdestextrastep = d_pdestbasestep + 1;
+
+ // TODO: can reuse partial expressions here
+
+ // for negative steps in x along left edge, bias toward overflow rather than
+ // underflow (sort of turning the floor () we did in the gradient calcs into
+ // ceil (), but plus a little bit)
+ if (ubasestep < 0)
+ working_lstepx = r_lstepx - 1;
+ else
+ working_lstepx = r_lstepx;
+
+ d_countextrastep = ubasestep + 1;
+ d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
+ ((r_tstepy + r_tstepx * ubasestep) >> 16) *
+ r_affinetridesc.skinwidth;
+//#if id386ALIAS
+#if id386
+ if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
+ {
+ d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
+ d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
+ }
+ else
+#endif
+ {
+//#else
+ d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
+ d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
+ }
+//#endif
+ d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
+ d_zibasestep = r_zistepy + r_zistepx * ubasestep;
+
+ d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
+ ((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
+ r_affinetridesc.skinwidth;
+//#if id386ALIAS
+#if id386
+ if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
+ {
+ d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16;
+ d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16;
+ }
+ else
+#endif
+ {
+//#else
+ d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF;
+ d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF;
+ }
+//#endif
+ d_lightextrastep = d_lightbasestep + working_lstepx;
+ d_ziextrastep = d_zibasestep + r_zistepx;
+
+#if id386
+ if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
+ {
+ R_PolysetScanLeftEdge (initialleftheight);
+ }
+ else
+#endif
+ {
+ R_PolysetScanLeftEdge_C(initialleftheight);
+ }
+ }
+
+//
+// scan out the bottom part of the left edge, if it exists
+//
+ if (pedgetable->numleftedges == 2)
+ {
+ int height;
+
+ plefttop = pleftbottom;
+ pleftbottom = pedgetable->pleftedgevert2;
+
+ height = pleftbottom[1] - plefttop[1];
+
+// TODO: make this a function; modularize this function in general
+
+ ystart = plefttop[1];
+ d_aspancount = plefttop[0] - prighttop[0];
+ d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
+ (plefttop[3] >> 16) * r_affinetridesc.skinwidth;
+ d_sfrac = 0;
+ d_tfrac = 0;
+ d_light = plefttop[4];
+ d_zi = plefttop[5];
+
+ d_pdest = (byte *)d_viewbuffer + ystart * r_screenwidth + plefttop[0];
+ d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
+
+ if (height == 1)
+ {
+ d_pedgespanpackage->pdest = d_pdest;
+ d_pedgespanpackage->pz = d_pz;
+ d_pedgespanpackage->count = d_aspancount;
+ d_pedgespanpackage->ptex = d_ptex;
+
+ d_pedgespanpackage->sfrac = d_sfrac;
+ d_pedgespanpackage->tfrac = d_tfrac;
+
+ // FIXME: need to clamp l, s, t, at both ends?
+ d_pedgespanpackage->light = d_light;
+ d_pedgespanpackage->zi = d_zi;
+
+ d_pedgespanpackage++;
+ }
+ else
+ {
+ R_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
+ pleftbottom[0], pleftbottom[1]);
+
+ d_pdestbasestep = r_screenwidth + ubasestep;
+ d_pdestextrastep = d_pdestbasestep + 1;
+
+//#if id386ALIAS
+#if id386
+ if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
+ {
+ d_pzbasestep = (d_zwidth + ubasestep) << 1;
+ d_pzextrastep = d_pzbasestep + 2;
+ }
+//#else
+ else
+#endif
+ {
+ d_pzbasestep = d_zwidth + ubasestep;
+ d_pzextrastep = d_pzbasestep + 1;
+ }
+//#endif
+
+ if (ubasestep < 0)
+ working_lstepx = r_lstepx - 1;
+ else
+ working_lstepx = r_lstepx;
+
+ d_countextrastep = ubasestep + 1;
+ d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
+ ((r_tstepy + r_tstepx * ubasestep) >> 16) *
+ r_affinetridesc.skinwidth;
+//#if id386ALIAS
+#if id386
+ if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
+ {
+ d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
+ d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
+ }
+//#else
+ else
+#endif
+ {
+ d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
+ d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
+ }
+//#endif
+ d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
+ d_zibasestep = r_zistepy + r_zistepx * ubasestep;
+
+ d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
+ ((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
+ r_affinetridesc.skinwidth;
+//#if id386ALIAS
+#if id386
+ if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
+ {
+ d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16;
+ d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16;
+ }
+ else
+#endif
+//#endif
+ {
+ d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF;
+ d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF;
+ }
+//#endif
+ d_lightextrastep = d_lightbasestep + working_lstepx;
+ d_ziextrastep = d_zibasestep + r_zistepx;
+
+#if id386
+ if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
+ {
+ R_PolysetScanLeftEdge (height);
+ }
+ else
+#endif
+ {
+ R_PolysetScanLeftEdge_C(height);
+ }
+ }
+ }
+
+// scan out the top (and possibly only) part of the right edge, updating the
+// count field
+ d_pedgespanpackage = a_spans;
+
+ R_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
+ prightbottom[0], prightbottom[1]);
+ d_aspancount = 0;
+ d_countextrastep = ubasestep + 1;
+ originalcount = a_spans[initialrightheight].count;
+ a_spans[initialrightheight].count = -999999; // mark end of the spanpackages
+ (*d_pdrawspans) (a_spans);
+
+// scan out the bottom part of the right edge, if it exists
+ if (pedgetable->numrightedges == 2)
+ {
+ int height;
+ spanpackage_t *pstart;
+
+ pstart = a_spans + initialrightheight;
+ pstart->count = originalcount;
+
+ d_aspancount = prightbottom[0] - prighttop[0];
+
+ prighttop = prightbottom;
+ prightbottom = pedgetable->prightedgevert2;
+
+ height = prightbottom[1] - prighttop[1];
+
+ R_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
+ prightbottom[0], prightbottom[1]);
+
+ d_countextrastep = ubasestep + 1;
+ a_spans[initialrightheight + height].count = -999999;
+ // mark end of the spanpackages
+ (*d_pdrawspans) (pstart);
+ }
+}
+
+
+/*
+================
+R_PolysetSetEdgeTable
+================
+*/
+void R_PolysetSetEdgeTable (void)
+{
+ int edgetableindex;
+
+ edgetableindex = 0; // assume the vertices are already in
+ // top to bottom order
+
+//
+// determine which edges are right & left, and the order in which
+// to rasterize them
+//
+ if (r_p0[1] >= r_p1[1])
+ {
+ if (r_p0[1] == r_p1[1])
+ {
+ if (r_p0[1] < r_p2[1])
+ pedgetable = &edgetables[2];
+ else
+ pedgetable = &edgetables[5];
+
+ return;
+ }
+ else
+ {
+ edgetableindex = 1;
+ }
+ }
+
+ if (r_p0[1] == r_p2[1])
+ {
+ if (edgetableindex)
+ pedgetable = &edgetables[8];
+ else
+ pedgetable = &edgetables[9];
+
+ return;
+ }
+ else if (r_p1[1] == r_p2[1])
+ {
+ if (edgetableindex)
+ pedgetable = &edgetables[10];
+ else
+ pedgetable = &edgetables[11];
+
+ return;
+ }
+
+ if (r_p0[1] > r_p2[1])
+ edgetableindex += 2;
+
+ if (r_p1[1] > r_p2[1])
+ edgetableindex += 4;
+
+ pedgetable = &edgetables[edgetableindex];
+}
+
+
--- /dev/null
+++ b/ref/r_rast.c
@@ -1,0 +1,852 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// r_rast.c
+
+#include <assert.h>
+
+#include "r_local.h"
+
+#define MAXLEFTCLIPEDGES 100
+
+// !!! if these are changed, they must be changed in asm_draw.h too !!!
+#define FULLY_CLIPPED_CACHED 0x80000000
+#define FRAMECOUNT_MASK 0x7FFFFFFF
+
+unsigned int cacheoffset;
+
+int c_faceclip; // number of faces clipped
+
+
+clipplane_t *entity_clipplanes;
+clipplane_t view_clipplanes[4];
+clipplane_t world_clipplanes[16];
+
+medge_t *r_pedge;
+
+qboolean r_leftclipped, r_rightclipped;
+static qboolean makeleftedge, makerightedge;
+qboolean r_nearzionly;
+
+int sintable[1280];
+int intsintable[1280];
+int blanktable[1280]; // PGM
+
+mvertex_t r_leftenter, r_leftexit;
+mvertex_t r_rightenter, r_rightexit;
+
+typedef struct
+{
+ float u,v;
+ int ceilv;
+} evert_t;
+
+int r_emitted;
+float r_nearzi;
+float r_u1, r_v1, r_lzi1;
+int r_ceilv1;
+
+qboolean r_lastvertvalid;
+int r_skyframe;
+
+msurface_t *r_skyfaces;
+mplane_t r_skyplanes[6];
+mtexinfo_t r_skytexinfo[6];
+mvertex_t *r_skyverts;
+medge_t *r_skyedges;
+int *r_skysurfedges;
+
+// I just copied this data from a box map...
+int skybox_planes[12] = {2,-128, 0,-128, 2,128, 1,128, 0,128, 1,-128};
+
+int box_surfedges[24] = { 1,2,3,4, -1,5,6,7, 8,9,-6,10, -2,-7,-9,11,
+ 12,-3,-11,-8, -12,-10,-5,-4};
+int box_edges[24] = { 1,2, 2,3, 3,4, 4,1, 1,5, 5,6, 6,2, 7,8, 8,6, 5,7, 8,3, 7,4};
+
+int box_faces[6] = {0,0,2,2,2,0};
+
+vec3_t box_vecs[6][2] = {
+ { {0,-1,0}, {-1,0,0} },
+ { {0,1,0}, {0,0,-1} },
+ { {0,-1,0}, {1,0,0} },
+ { {1,0,0}, {0,0,-1} },
+ { {0,-1,0}, {0,0,-1} },
+ { {-1,0,0}, {0,0,-1} }
+};
+
+float box_verts[8][3] = {
+ {-1,-1,-1},
+ {-1,1,-1},
+ {1,1,-1},
+ {1,-1,-1},
+ {-1,-1,1},
+ {-1,1,1},
+ {1,-1,1},
+ {1,1,1}
+};
+
+// down, west, up, north, east, south
+// {"rt", "bk", "lf", "ft", "up", "dn"};
+
+/*
+================
+R_InitSkyBox
+
+================
+*/
+void R_InitSkyBox (void)
+{
+ int i;
+ extern model_t *loadmodel;
+
+ r_skyfaces = loadmodel->surfaces + loadmodel->numsurfaces;
+ loadmodel->numsurfaces += 6;
+ r_skyverts = loadmodel->vertexes + loadmodel->numvertexes;
+ loadmodel->numvertexes += 8;
+ r_skyedges = loadmodel->edges + loadmodel->numedges;
+ loadmodel->numedges += 12;
+ r_skysurfedges = loadmodel->surfedges + loadmodel->numsurfedges;
+ loadmodel->numsurfedges += 24;
+ if (loadmodel->numsurfaces > MAX_MAP_FACES
+ || loadmodel->numvertexes > MAX_MAP_VERTS
+ || loadmodel->numedges > MAX_MAP_EDGES)
+ ri.Sys_Error (ERR_DROP, "InitSkyBox: map overflow");
+
+ memset (r_skyfaces, 0, 6*sizeof(*r_skyfaces));
+ for (i=0 ; i<6 ; i++)
+ {
+ r_skyplanes[i].normal[skybox_planes[i*2]] = 1;
+ r_skyplanes[i].dist = skybox_planes[i*2+1];
+
+ VectorCopy (box_vecs[i][0], r_skytexinfo[i].vecs[0]);
+ VectorCopy (box_vecs[i][1], r_skytexinfo[i].vecs[1]);
+
+ r_skyfaces[i].plane = &r_skyplanes[i];
+ r_skyfaces[i].numedges = 4;
+ r_skyfaces[i].flags = box_faces[i] | SURF_DRAWSKYBOX;
+ r_skyfaces[i].firstedge = loadmodel->numsurfedges-24+i*4;
+ r_skyfaces[i].texinfo = &r_skytexinfo[i];
+ r_skyfaces[i].texturemins[0] = -128;
+ r_skyfaces[i].texturemins[1] = -128;
+ r_skyfaces[i].extents[0] = 256;
+ r_skyfaces[i].extents[1] = 256;
+ }
+
+ for (i=0 ; i<24 ; i++)
+ if (box_surfedges[i] > 0)
+ r_skysurfedges[i] = loadmodel->numedges-13 + box_surfedges[i];
+ else
+ r_skysurfedges[i] = - (loadmodel->numedges-13 + -box_surfedges[i]);
+
+ for(i=0 ; i<12 ; i++)
+ {
+ r_skyedges[i].v[0] = loadmodel->numvertexes-9+box_edges[i*2+0];
+ r_skyedges[i].v[1] = loadmodel->numvertexes-9+box_edges[i*2+1];
+ r_skyedges[i].cachededgeoffset = 0;
+ }
+}
+
+/*
+================
+R_EmitSkyBox
+================
+*/
+void R_EmitSkyBox (void)
+{
+ int i, j;
+ int oldkey;
+
+ if (insubmodel)
+ return; // submodels should never have skies
+ if (r_skyframe == r_framecount)
+ return; // already set this frame
+
+ r_skyframe = r_framecount;
+
+ // set the eight fake vertexes
+ for (i=0 ; i<8 ; i++)
+ for (j=0 ; j<3 ; j++)
+ r_skyverts[i].position[j] = r_origin[j] + box_verts[i][j]*128;
+
+ // set the six fake planes
+ for (i=0 ; i<6 ; i++)
+ if (skybox_planes[i*2+1] > 0)
+ r_skyplanes[i].dist = r_origin[skybox_planes[i*2]]+128;
+ else
+ r_skyplanes[i].dist = r_origin[skybox_planes[i*2]]-128;
+
+ // fix texture offseets
+ for (i=0 ; i<6 ; i++)
+ {
+ r_skytexinfo[i].vecs[0][3] = -DotProduct (r_origin, r_skytexinfo[i].vecs[0]);
+ r_skytexinfo[i].vecs[1][3] = -DotProduct (r_origin, r_skytexinfo[i].vecs[1]);
+ }
+
+ // emit the six faces
+ oldkey = r_currentkey;
+ r_currentkey = 0x7ffffff0;
+ for (i=0 ; i<6 ; i++)
+ {
+ R_RenderFace (r_skyfaces + i, 15);
+ }
+ r_currentkey = oldkey; // bsp sorting order
+}
+
+
+#if !id386
+
+/*
+================
+R_EmitEdge
+================
+*/
+void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
+{
+ edge_t *edge, *pcheck;
+ int u_check;
+ float u, u_step;
+ vec3_t local, transformed;
+ float *world;
+ int v, v2, ceilv0;
+ float scale, lzi0, u0, v0;
+ int side;
+
+ if (r_lastvertvalid)
+ {
+ u0 = r_u1;
+ v0 = r_v1;
+ lzi0 = r_lzi1;
+ ceilv0 = r_ceilv1;
+ }
+ else
+ {
+ world = &pv0->position[0];
+
+ // transform and project
+ VectorSubtract (world, modelorg, local);
+ TransformVector (local, transformed);
+
+ if (transformed[2] < NEAR_CLIP)
+ transformed[2] = NEAR_CLIP;
+
+ lzi0 = 1.0 / transformed[2];
+
+ // FIXME: build x/yscale into transform?
+ scale = xscale * lzi0;
+ u0 = (xcenter + scale*transformed[0]);
+ if (u0 < r_refdef.fvrectx_adj)
+ u0 = r_refdef.fvrectx_adj;
+ if (u0 > r_refdef.fvrectright_adj)
+ u0 = r_refdef.fvrectright_adj;
+
+ scale = yscale * lzi0;
+ v0 = (ycenter - scale*transformed[1]);
+ if (v0 < r_refdef.fvrecty_adj)
+ v0 = r_refdef.fvrecty_adj;
+ if (v0 > r_refdef.fvrectbottom_adj)
+ v0 = r_refdef.fvrectbottom_adj;
+
+ ceilv0 = (int) ceil(v0);
+ }
+
+ world = &pv1->position[0];
+
+// transform and project
+ VectorSubtract (world, modelorg, local);
+ TransformVector (local, transformed);
+
+ if (transformed[2] < NEAR_CLIP)
+ transformed[2] = NEAR_CLIP;
+
+ r_lzi1 = 1.0 / transformed[2];
+
+ scale = xscale * r_lzi1;
+ r_u1 = (xcenter + scale*transformed[0]);
+ if (r_u1 < r_refdef.fvrectx_adj)
+ r_u1 = r_refdef.fvrectx_adj;
+ if (r_u1 > r_refdef.fvrectright_adj)
+ r_u1 = r_refdef.fvrectright_adj;
+
+ scale = yscale * r_lzi1;
+ r_v1 = (ycenter - scale*transformed[1]);
+ if (r_v1 < r_refdef.fvrecty_adj)
+ r_v1 = r_refdef.fvrecty_adj;
+ if (r_v1 > r_refdef.fvrectbottom_adj)
+ r_v1 = r_refdef.fvrectbottom_adj;
+
+ if (r_lzi1 > lzi0)
+ lzi0 = r_lzi1;
+
+ if (lzi0 > r_nearzi) // for mipmap finding
+ r_nearzi = lzi0;
+
+// for right edges, all we want is the effect on 1/z
+ if (r_nearzionly)
+ return;
+
+ r_emitted = 1;
+
+ r_ceilv1 = (int) ceil(r_v1);
+
+
+// create the edge
+ if (ceilv0 == r_ceilv1)
+ {
+ // we cache unclipped horizontal edges as fully clipped
+ if (cacheoffset != 0x7FFFFFFF)
+ {
+ cacheoffset = FULLY_CLIPPED_CACHED |
+ (r_framecount & FRAMECOUNT_MASK);
+ }
+
+ return; // horizontal edge
+ }
+
+ side = ceilv0 > r_ceilv1;
+
+ edge = edge_p++;
+
+ edge->owner = r_pedge;
+
+ edge->nearzi = lzi0;
+
+ if (side == 0)
+ {
+ // trailing edge (go from p1 to p2)
+ v = ceilv0;
+ v2 = r_ceilv1 - 1;
+
+ edge->surfs[0] = surface_p - surfaces;
+ edge->surfs[1] = 0;
+
+ u_step = ((r_u1 - u0) / (r_v1 - v0));
+ u = u0 + ((float)v - v0) * u_step;
+ }
+ else
+ {
+ // leading edge (go from p2 to p1)
+ v2 = ceilv0 - 1;
+ v = r_ceilv1;
+
+ edge->surfs[0] = 0;
+ edge->surfs[1] = surface_p - surfaces;
+
+ u_step = ((u0 - r_u1) / (v0 - r_v1));
+ u = r_u1 + ((float)v - r_v1) * u_step;
+ }
+
+ edge->u_step = u_step*0x100000;
+ edge->u = u*0x100000 + 0xFFFFF;
+
+// we need to do this to avoid stepping off the edges if a very nearly
+// horizontal edge is less than epsilon above a scan, and numeric error causes
+// it to incorrectly extend to the scan, and the extension of the line goes off
+// the edge of the screen
+// FIXME: is this actually needed?
+ if (edge->u < r_refdef.vrect_x_adj_shift20)
+ edge->u = r_refdef.vrect_x_adj_shift20;
+ if (edge->u > r_refdef.vrectright_adj_shift20)
+ edge->u = r_refdef.vrectright_adj_shift20;
+
+//
+// sort the edge in normally
+//
+ u_check = edge->u;
+ if (edge->surfs[0])
+ u_check++; // sort trailers after leaders
+
+ if (!newedges[v] || newedges[v]->u >= u_check)
+ {
+ edge->next = newedges[v];
+ newedges[v] = edge;
+ }
+ else
+ {
+ pcheck = newedges[v];
+ while (pcheck->next && pcheck->next->u < u_check)
+ pcheck = pcheck->next;
+ edge->next = pcheck->next;
+ pcheck->next = edge;
+ }
+
+ edge->nextremove = removeedges[v2];
+ removeedges[v2] = edge;
+}
+
+
+/*
+================
+R_ClipEdge
+================
+*/
+void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
+{
+ float d0, d1, f;
+ mvertex_t clipvert;
+
+ if (clip)
+ {
+ do
+ {
+ d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
+ d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
+
+ if (d0 >= 0)
+ {
+ // point 0 is unclipped
+ if (d1 >= 0)
+ {
+ // both points are unclipped
+ continue;
+ }
+
+ // only point 1 is clipped
+
+ // we don't cache clipped edges
+ cacheoffset = 0x7FFFFFFF;
+
+ f = d0 / (d0 - d1);
+ clipvert.position[0] = pv0->position[0] +
+ f * (pv1->position[0] - pv0->position[0]);
+ clipvert.position[1] = pv0->position[1] +
+ f * (pv1->position[1] - pv0->position[1]);
+ clipvert.position[2] = pv0->position[2] +
+ f * (pv1->position[2] - pv0->position[2]);
+
+ if (clip->leftedge)
+ {
+ r_leftclipped = true;
+ r_leftexit = clipvert;
+ }
+ else if (clip->rightedge)
+ {
+ r_rightclipped = true;
+ r_rightexit = clipvert;
+ }
+
+ R_ClipEdge (pv0, &clipvert, clip->next);
+ return;
+ }
+ else
+ {
+ // point 0 is clipped
+ if (d1 < 0)
+ {
+ // both points are clipped
+ // we do cache fully clipped edges
+ if (!r_leftclipped)
+ cacheoffset = FULLY_CLIPPED_CACHED |
+ (r_framecount & FRAMECOUNT_MASK);
+ return;
+ }
+
+ // only point 0 is clipped
+ r_lastvertvalid = false;
+
+ // we don't cache partially clipped edges
+ cacheoffset = 0x7FFFFFFF;
+
+ f = d0 / (d0 - d1);
+ clipvert.position[0] = pv0->position[0] +
+ f * (pv1->position[0] - pv0->position[0]);
+ clipvert.position[1] = pv0->position[1] +
+ f * (pv1->position[1] - pv0->position[1]);
+ clipvert.position[2] = pv0->position[2] +
+ f * (pv1->position[2] - pv0->position[2]);
+
+ if (clip->leftedge)
+ {
+ r_leftclipped = true;
+ r_leftenter = clipvert;
+ }
+ else if (clip->rightedge)
+ {
+ r_rightclipped = true;
+ r_rightenter = clipvert;
+ }
+
+ R_ClipEdge (&clipvert, pv1, clip->next);
+ return;
+ }
+ } while ((clip = clip->next) != NULL);
+ }
+
+// add the edge
+ R_EmitEdge (pv0, pv1);
+}
+
+#endif // !id386
+
+
+/*
+================
+R_EmitCachedEdge
+================
+*/
+void R_EmitCachedEdge (void)
+{
+ edge_t *pedge_t;
+
+ pedge_t = (edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset);
+
+ if (!pedge_t->surfs[0])
+ pedge_t->surfs[0] = surface_p - surfaces;
+ else
+ pedge_t->surfs[1] = surface_p - surfaces;
+
+ if (pedge_t->nearzi > r_nearzi) // for mipmap finding
+ r_nearzi = pedge_t->nearzi;
+
+ r_emitted = 1;
+}
+
+
+/*
+================
+R_RenderFace
+================
+*/
+void R_RenderFace (msurface_t *fa, int clipflags)
+{
+ int i, lindex;
+ unsigned mask;
+ mplane_t *pplane;
+ float distinv;
+ vec3_t p_normal;
+ medge_t *pedges, tedge;
+ clipplane_t *pclip;
+
+ // translucent surfaces are not drawn by the edge renderer
+ if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
+ {
+ fa->nextalphasurface = r_alpha_surfaces;
+ r_alpha_surfaces = fa;
+ return;
+ }
+
+ // sky surfaces encountered in the world will cause the
+ // environment box surfaces to be emited
+ if ( fa->texinfo->flags & SURF_SKY )
+ {
+ R_EmitSkyBox ();
+ return;
+ }
+
+// skip out if no more surfs
+ if ((surface_p) >= surf_max)
+ {
+ r_outofsurfaces++;
+ return;
+ }
+
+// ditto if not enough edges left, or switch to auxedges if possible
+ if ((edge_p + fa->numedges + 4) >= edge_max)
+ {
+ r_outofedges += fa->numedges;
+ return;
+ }
+
+ c_faceclip++;
+
+// set up clip planes
+ pclip = NULL;
+
+ for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
+ {
+ if (clipflags & mask)
+ {
+ view_clipplanes[i].next = pclip;
+ pclip = &view_clipplanes[i];
+ }
+ }
+
+// push the edges through
+ r_emitted = 0;
+ r_nearzi = 0;
+ r_nearzionly = false;
+ makeleftedge = makerightedge = false;
+ pedges = currentmodel->edges;
+ r_lastvertvalid = false;
+
+ for (i=0 ; i<fa->numedges ; i++)
+ {
+ lindex = currentmodel->surfedges[fa->firstedge + i];
+
+ if (lindex > 0)
+ {
+ r_pedge = &pedges[lindex];
+
+ // if the edge is cached, we can just reuse the edge
+ if (!insubmodel)
+ {
+ if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
+ {
+ if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
+ r_framecount)
+ {
+ r_lastvertvalid = false;
+ continue;
+ }
+ }
+ else
+ {
+ if ((((unsigned long)edge_p - (unsigned long)r_edges) >
+ r_pedge->cachededgeoffset) &&
+ (((edge_t *)((unsigned long)r_edges +
+ r_pedge->cachededgeoffset))->owner == r_pedge))
+ {
+ R_EmitCachedEdge ();
+ r_lastvertvalid = false;
+ continue;
+ }
+ }
+ }
+
+ // assume it's cacheable
+ cacheoffset = (byte *)edge_p - (byte *)r_edges;
+ r_leftclipped = r_rightclipped = false;
+ R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]],
+ &r_pcurrentvertbase[r_pedge->v[1]],
+ pclip);
+ r_pedge->cachededgeoffset = cacheoffset;
+
+ if (r_leftclipped)
+ makeleftedge = true;
+ if (r_rightclipped)
+ makerightedge = true;
+ r_lastvertvalid = true;
+ }
+ else
+ {
+ lindex = -lindex;
+ r_pedge = &pedges[lindex];
+ // if the edge is cached, we can just reuse the edge
+ if (!insubmodel)
+ {
+ if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
+ {
+ if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
+ r_framecount)
+ {
+ r_lastvertvalid = false;
+ continue;
+ }
+ }
+ else
+ {
+ // it's cached if the cached edge is valid and is owned
+ // by this medge_t
+ if ((((unsigned long)edge_p - (unsigned long)r_edges) >
+ r_pedge->cachededgeoffset) &&
+ (((edge_t *)((unsigned long)r_edges +
+ r_pedge->cachededgeoffset))->owner == r_pedge))
+ {
+ R_EmitCachedEdge ();
+ r_lastvertvalid = false;
+ continue;
+ }
+ }
+ }
+
+ // assume it's cacheable
+ cacheoffset = (byte *)edge_p - (byte *)r_edges;
+ r_leftclipped = r_rightclipped = false;
+ R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]],
+ &r_pcurrentvertbase[r_pedge->v[0]],
+ pclip);
+ r_pedge->cachededgeoffset = cacheoffset;
+
+ if (r_leftclipped)
+ makeleftedge = true;
+ if (r_rightclipped)
+ makerightedge = true;
+ r_lastvertvalid = true;
+ }
+ }
+
+// if there was a clip off the left edge, add that edge too
+// FIXME: faster to do in screen space?
+// FIXME: share clipped edges?
+ if (makeleftedge)
+ {
+ r_pedge = &tedge;
+ r_lastvertvalid = false;
+ R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
+ }
+
+// if there was a clip off the right edge, get the right r_nearzi
+ if (makerightedge)
+ {
+ r_pedge = &tedge;
+ r_lastvertvalid = false;
+ r_nearzionly = true;
+ R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
+ }
+
+// if no edges made it out, return without posting the surface
+ if (!r_emitted)
+ return;
+
+ r_polycount++;
+
+ surface_p->msurf = fa;
+ surface_p->nearzi = r_nearzi;
+ surface_p->flags = fa->flags;
+ surface_p->insubmodel = insubmodel;
+ surface_p->spanstate = 0;
+ surface_p->entity = currententity;
+ surface_p->key = r_currentkey++;
+ surface_p->spans = NULL;
+
+ pplane = fa->plane;
+// FIXME: cache this?
+ TransformVector (pplane->normal, p_normal);
+// FIXME: cache this?
+ distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
+
+ surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
+ surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
+ surface_p->d_ziorigin = p_normal[2] * distinv -
+ xcenter * surface_p->d_zistepu -
+ ycenter * surface_p->d_zistepv;
+
+ surface_p++;
+}
+
+
+/*
+================
+R_RenderBmodelFace
+================
+*/
+void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
+{
+ int i;
+ unsigned mask;
+ mplane_t *pplane;
+ float distinv;
+ vec3_t p_normal;
+ medge_t tedge;
+ clipplane_t *pclip;
+
+ if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
+ {
+ psurf->nextalphasurface = r_alpha_surfaces;
+ r_alpha_surfaces = psurf;
+ return;
+ }
+
+// skip out if no more surfs
+ if (surface_p >= surf_max)
+ {
+ r_outofsurfaces++;
+ return;
+ }
+
+// ditto if not enough edges left, or switch to auxedges if possible
+ if ((edge_p + psurf->numedges + 4) >= edge_max)
+ {
+ r_outofedges += psurf->numedges;
+ return;
+ }
+
+ c_faceclip++;
+
+// this is a dummy to give the caching mechanism someplace to write to
+ r_pedge = &tedge;
+
+// set up clip planes
+ pclip = NULL;
+
+ for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
+ {
+ if (r_clipflags & mask)
+ {
+ view_clipplanes[i].next = pclip;
+ pclip = &view_clipplanes[i];
+ }
+ }
+
+// push the edges through
+ r_emitted = 0;
+ r_nearzi = 0;
+ r_nearzionly = false;
+ makeleftedge = makerightedge = false;
+// FIXME: keep clipped bmodel edges in clockwise order so last vertex caching
+// can be used?
+ r_lastvertvalid = false;
+
+ for ( ; pedges ; pedges = pedges->pnext)
+ {
+ r_leftclipped = r_rightclipped = false;
+ R_ClipEdge (pedges->v[0], pedges->v[1], pclip);
+
+ if (r_leftclipped)
+ makeleftedge = true;
+ if (r_rightclipped)
+ makerightedge = true;
+ }
+
+// if there was a clip off the left edge, add that edge too
+// FIXME: faster to do in screen space?
+// FIXME: share clipped edges?
+ if (makeleftedge)
+ {
+ r_pedge = &tedge;
+ R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
+ }
+
+// if there was a clip off the right edge, get the right r_nearzi
+ if (makerightedge)
+ {
+ r_pedge = &tedge;
+ r_nearzionly = true;
+ R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
+ }
+
+// if no edges made it out, return without posting the surface
+ if (!r_emitted)
+ return;
+
+ r_polycount++;
+
+ surface_p->msurf = psurf;
+ surface_p->nearzi = r_nearzi;
+ surface_p->flags = psurf->flags;
+ surface_p->insubmodel = true;
+ surface_p->spanstate = 0;
+ surface_p->entity = currententity;
+ surface_p->key = r_currentbkey;
+ surface_p->spans = NULL;
+
+ pplane = psurf->plane;
+// FIXME: cache this?
+ TransformVector (pplane->normal, p_normal);
+// FIXME: cache this?
+ distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
+
+ surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
+ surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
+ surface_p->d_ziorigin = p_normal[2] * distinv -
+ xcenter * surface_p->d_zistepu -
+ ycenter * surface_p->d_zistepv;
+
+ surface_p++;
+}
+
--- /dev/null
+++ b/ref/r_scan.c
@@ -1,0 +1,591 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// d_scan.c
+//
+// Portable C scan-level rasterization code, all pixel depths.
+
+#include "r_local.h"
+
+unsigned char *r_turb_pbase, *r_turb_pdest;
+fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
+int *r_turb_turb;
+int r_turb_spancount;
+
+void D_DrawTurbulent8Span (void);
+
+
+/*
+=============
+D_WarpScreen
+
+this performs a slight compression of the screen at the same time as
+the sine warp, to keep the edges from wrapping
+=============
+*/
+void D_WarpScreen (void)
+{
+ int w, h;
+ int u,v, u2, v2;
+ byte *dest;
+ int *turb;
+ int *col;
+ byte **row;
+
+ static int cached_width, cached_height;
+ static byte *rowptr[1200+AMP2*2];
+ static int column[1600+AMP2*2];
+
+ //
+ // these are constant over resolutions, and can be saved
+ //
+ w = r_newrefdef.width;
+ h = r_newrefdef.height;
+ if (w != cached_width || h != cached_height)
+ {
+ cached_width = w;
+ cached_height = h;
+ for (v=0 ; v<h+AMP2*2 ; v++)
+ {
+ v2 = (int)((float)v/(h + AMP2 * 2) * r_refdef.vrect.height);
+ rowptr[v] = r_warpbuffer + (WARP_WIDTH * v2);
+ }
+
+ for (u=0 ; u<w+AMP2*2 ; u++)
+ {
+ u2 = (int)((float)u/(w + AMP2 * 2) * r_refdef.vrect.width);
+ column[u] = u2;
+ }
+ }
+
+ turb = intsintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
+ dest = vid.buffer + r_newrefdef.y * vid.rowbytes + r_newrefdef.x;
+
+ for (v=0 ; v<h ; v++, dest += vid.rowbytes)
+ {
+ col = &column[turb[v]];
+ row = &rowptr[v];
+ for (u=0 ; u<w ; u+=4)
+ {
+ dest[u+0] = row[turb[u+0]][col[u+0]];
+ dest[u+1] = row[turb[u+1]][col[u+1]];
+ dest[u+2] = row[turb[u+2]][col[u+2]];
+ dest[u+3] = row[turb[u+3]][col[u+3]];
+ }
+ }
+}
+
+
+#if !id386
+
+/*
+=============
+D_DrawTurbulent8Span
+=============
+*/
+void D_DrawTurbulent8Span (void)
+{
+ int sturb, tturb;
+
+ do
+ {
+ sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
+ tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
+ *r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
+ r_turb_s += r_turb_sstep;
+ r_turb_t += r_turb_tstep;
+ } while (--r_turb_spancount > 0);
+}
+
+#endif // !id386
+
+
+/*
+=============
+Turbulent8
+=============
+*/
+void Turbulent8 (espan_t *pspan)
+{
+ int count;
+ fixed16_t snext, tnext;
+ float sdivz, tdivz, zi, z, du, dv, spancountminus1;
+ float sdivz16stepu, tdivz16stepu, zi16stepu;
+
+ r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
+
+ r_turb_sstep = 0; // keep compiler happy
+ r_turb_tstep = 0; // ditto
+
+ r_turb_pbase = (unsigned char *)cacheblock;
+
+ sdivz16stepu = d_sdivzstepu * 16;
+ tdivz16stepu = d_tdivzstepu * 16;
+ zi16stepu = d_zistepu * 16;
+
+ do
+ {
+ r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
+ (r_screenwidth * pspan->v) + pspan->u);
+
+ count = pspan->count;
+
+ // calculate the initial s/z, t/z, 1/z, s, and t and clamp
+ du = (float)pspan->u;
+ dv = (float)pspan->v;
+
+ sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
+ tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
+ zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+ z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
+
+ r_turb_s = (int)(sdivz * z) + sadjust;
+ if (r_turb_s > bbextents)
+ r_turb_s = bbextents;
+ else if (r_turb_s < 0)
+ r_turb_s = 0;
+
+ r_turb_t = (int)(tdivz * z) + tadjust;
+ if (r_turb_t > bbextentt)
+ r_turb_t = bbextentt;
+ else if (r_turb_t < 0)
+ r_turb_t = 0;
+
+ do
+ {
+ // calculate s and t at the far end of the span
+ if (count >= 16)
+ r_turb_spancount = 16;
+ else
+ r_turb_spancount = count;
+
+ count -= r_turb_spancount;
+
+ if (count)
+ {
+ // calculate s/z, t/z, zi->fixed s and t at far end of span,
+ // calculate s and t steps across span by shifting
+ sdivz += sdivz16stepu;
+ tdivz += tdivz16stepu;
+ zi += zi16stepu;
+ z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
+
+ snext = (int)(sdivz * z) + sadjust;
+ if (snext > bbextents)
+ snext = bbextents;
+ else if (snext < 16)
+ snext = 16; // prevent round-off error on <0 steps from
+ // from causing overstepping & running off the
+ // edge of the texture
+
+ tnext = (int)(tdivz * z) + tadjust;
+ if (tnext > bbextentt)
+ tnext = bbextentt;
+ else if (tnext < 16)
+ tnext = 16; // guard against round-off error on <0 steps
+
+ r_turb_sstep = (snext - r_turb_s) >> 4;
+ r_turb_tstep = (tnext - r_turb_t) >> 4;
+ }
+ else
+ {
+ // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
+ // can't step off polygon), clamp, calculate s and t steps across
+ // span by division, biasing steps low so we don't run off the
+ // texture
+ spancountminus1 = (float)(r_turb_spancount - 1);
+ sdivz += d_sdivzstepu * spancountminus1;
+ tdivz += d_tdivzstepu * spancountminus1;
+ zi += d_zistepu * spancountminus1;
+ z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
+ snext = (int)(sdivz * z) + sadjust;
+ if (snext > bbextents)
+ snext = bbextents;
+ else if (snext < 16)
+ snext = 16; // prevent round-off error on <0 steps from
+ // from causing overstepping & running off the
+ // edge of the texture
+
+ tnext = (int)(tdivz * z) + tadjust;
+ if (tnext > bbextentt)
+ tnext = bbextentt;
+ else if (tnext < 16)
+ tnext = 16; // guard against round-off error on <0 steps
+
+ if (r_turb_spancount > 1)
+ {
+ r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
+ r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
+ }
+ }
+
+ r_turb_s = r_turb_s & ((CYCLE<<16)-1);
+ r_turb_t = r_turb_t & ((CYCLE<<16)-1);
+
+ D_DrawTurbulent8Span ();
+
+ r_turb_s = snext;
+ r_turb_t = tnext;
+
+ } while (count > 0);
+
+ } while ((pspan = pspan->pnext) != NULL);
+}
+
+//====================
+//PGM
+/*
+=============
+NonTurbulent8 - this is for drawing scrolling textures. they're warping water textures
+ but the turbulence is automatically 0.
+=============
+*/
+void NonTurbulent8 (espan_t *pspan)
+{
+ int count;
+ fixed16_t snext, tnext;
+ float sdivz, tdivz, zi, z, du, dv, spancountminus1;
+ float sdivz16stepu, tdivz16stepu, zi16stepu;
+
+// r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
+ r_turb_turb = blanktable;
+
+ r_turb_sstep = 0; // keep compiler happy
+ r_turb_tstep = 0; // ditto
+
+ r_turb_pbase = (unsigned char *)cacheblock;
+
+ sdivz16stepu = d_sdivzstepu * 16;
+ tdivz16stepu = d_tdivzstepu * 16;
+ zi16stepu = d_zistepu * 16;
+
+ do
+ {
+ r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
+ (r_screenwidth * pspan->v) + pspan->u);
+
+ count = pspan->count;
+
+ // calculate the initial s/z, t/z, 1/z, s, and t and clamp
+ du = (float)pspan->u;
+ dv = (float)pspan->v;
+
+ sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
+ tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
+ zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+ z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
+
+ r_turb_s = (int)(sdivz * z) + sadjust;
+ if (r_turb_s > bbextents)
+ r_turb_s = bbextents;
+ else if (r_turb_s < 0)
+ r_turb_s = 0;
+
+ r_turb_t = (int)(tdivz * z) + tadjust;
+ if (r_turb_t > bbextentt)
+ r_turb_t = bbextentt;
+ else if (r_turb_t < 0)
+ r_turb_t = 0;
+
+ do
+ {
+ // calculate s and t at the far end of the span
+ if (count >= 16)
+ r_turb_spancount = 16;
+ else
+ r_turb_spancount = count;
+
+ count -= r_turb_spancount;
+
+ if (count)
+ {
+ // calculate s/z, t/z, zi->fixed s and t at far end of span,
+ // calculate s and t steps across span by shifting
+ sdivz += sdivz16stepu;
+ tdivz += tdivz16stepu;
+ zi += zi16stepu;
+ z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
+
+ snext = (int)(sdivz * z) + sadjust;
+ if (snext > bbextents)
+ snext = bbextents;
+ else if (snext < 16)
+ snext = 16; // prevent round-off error on <0 steps from
+ // from causing overstepping & running off the
+ // edge of the texture
+
+ tnext = (int)(tdivz * z) + tadjust;
+ if (tnext > bbextentt)
+ tnext = bbextentt;
+ else if (tnext < 16)
+ tnext = 16; // guard against round-off error on <0 steps
+
+ r_turb_sstep = (snext - r_turb_s) >> 4;
+ r_turb_tstep = (tnext - r_turb_t) >> 4;
+ }
+ else
+ {
+ // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
+ // can't step off polygon), clamp, calculate s and t steps across
+ // span by division, biasing steps low so we don't run off the
+ // texture
+ spancountminus1 = (float)(r_turb_spancount - 1);
+ sdivz += d_sdivzstepu * spancountminus1;
+ tdivz += d_tdivzstepu * spancountminus1;
+ zi += d_zistepu * spancountminus1;
+ z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
+ snext = (int)(sdivz * z) + sadjust;
+ if (snext > bbextents)
+ snext = bbextents;
+ else if (snext < 16)
+ snext = 16; // prevent round-off error on <0 steps from
+ // from causing overstepping & running off the
+ // edge of the texture
+
+ tnext = (int)(tdivz * z) + tadjust;
+ if (tnext > bbextentt)
+ tnext = bbextentt;
+ else if (tnext < 16)
+ tnext = 16; // guard against round-off error on <0 steps
+
+ if (r_turb_spancount > 1)
+ {
+ r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
+ r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
+ }
+ }
+
+ r_turb_s = r_turb_s & ((CYCLE<<16)-1);
+ r_turb_t = r_turb_t & ((CYCLE<<16)-1);
+
+ D_DrawTurbulent8Span ();
+
+ r_turb_s = snext;
+ r_turb_t = tnext;
+
+ } while (count > 0);
+
+ } while ((pspan = pspan->pnext) != NULL);
+}
+//PGM
+//====================
+
+
+#if !id386
+
+/*
+=============
+D_DrawSpans16
+
+ FIXME: actually make this subdivide by 16 instead of 8!!!
+=============
+*/
+void D_DrawSpans16 (espan_t *pspan)
+{
+ int count, spancount;
+ unsigned char *pbase, *pdest;
+ fixed16_t s, t, snext, tnext, sstep, tstep;
+ float sdivz, tdivz, zi, z, du, dv, spancountminus1;
+ float sdivz8stepu, tdivz8stepu, zi8stepu;
+
+ sstep = 0; // keep compiler happy
+ tstep = 0; // ditto
+
+ pbase = (unsigned char *)cacheblock;
+
+ sdivz8stepu = d_sdivzstepu * 8;
+ tdivz8stepu = d_tdivzstepu * 8;
+ zi8stepu = d_zistepu * 8;
+
+ do
+ {
+ pdest = (unsigned char *)((byte *)d_viewbuffer +
+ (r_screenwidth * pspan->v) + pspan->u);
+
+ count = pspan->count;
+
+ // calculate the initial s/z, t/z, 1/z, s, and t and clamp
+ du = (float)pspan->u;
+ dv = (float)pspan->v;
+
+ sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
+ tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
+ zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+ z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
+
+ s = (int)(sdivz * z) + sadjust;
+ if (s > bbextents)
+ s = bbextents;
+ else if (s < 0)
+ s = 0;
+
+ t = (int)(tdivz * z) + tadjust;
+ if (t > bbextentt)
+ t = bbextentt;
+ else if (t < 0)
+ t = 0;
+
+ do
+ {
+ // calculate s and t at the far end of the span
+ if (count >= 8)
+ spancount = 8;
+ else
+ spancount = count;
+
+ count -= spancount;
+
+ if (count)
+ {
+ // calculate s/z, t/z, zi->fixed s and t at far end of span,
+ // calculate s and t steps across span by shifting
+ sdivz += sdivz8stepu;
+ tdivz += tdivz8stepu;
+ zi += zi8stepu;
+ z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
+
+ snext = (int)(sdivz * z) + sadjust;
+ if (snext > bbextents)
+ snext = bbextents;
+ else if (snext < 8)
+ snext = 8; // prevent round-off error on <0 steps from
+ // from causing overstepping & running off the
+ // edge of the texture
+
+ tnext = (int)(tdivz * z) + tadjust;
+ if (tnext > bbextentt)
+ tnext = bbextentt;
+ else if (tnext < 8)
+ tnext = 8; // guard against round-off error on <0 steps
+
+ sstep = (snext - s) >> 3;
+ tstep = (tnext - t) >> 3;
+ }
+ else
+ {
+ // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
+ // can't step off polygon), clamp, calculate s and t steps across
+ // span by division, biasing steps low so we don't run off the
+ // texture
+ spancountminus1 = (float)(spancount - 1);
+ sdivz += d_sdivzstepu * spancountminus1;
+ tdivz += d_tdivzstepu * spancountminus1;
+ zi += d_zistepu * spancountminus1;
+ z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
+ snext = (int)(sdivz * z) + sadjust;
+ if (snext > bbextents)
+ snext = bbextents;
+ else if (snext < 8)
+ snext = 8; // prevent round-off error on <0 steps from
+ // from causing overstepping & running off the
+ // edge of the texture
+
+ tnext = (int)(tdivz * z) + tadjust;
+ if (tnext > bbextentt)
+ tnext = bbextentt;
+ else if (tnext < 8)
+ tnext = 8; // guard against round-off error on <0 steps
+
+ if (spancount > 1)
+ {
+ sstep = (snext - s) / (spancount - 1);
+ tstep = (tnext - t) / (spancount - 1);
+ }
+ }
+
+ do
+ {
+ *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
+ s += sstep;
+ t += tstep;
+ } while (--spancount > 0);
+
+ s = snext;
+ t = tnext;
+
+ } while (count > 0);
+
+ } while ((pspan = pspan->pnext) != NULL);
+}
+
+#endif
+
+
+#if !id386
+
+/*
+=============
+D_DrawZSpans
+=============
+*/
+void D_DrawZSpans (espan_t *pspan)
+{
+ int count, doublecount, izistep;
+ int izi;
+ short *pdest;
+ unsigned ltemp;
+ float zi;
+ float du, dv;
+
+// FIXME: check for clamping/range problems
+// we count on FP exceptions being turned off to avoid range problems
+ izistep = (int)(d_zistepu * 0x8000 * 0x10000);
+
+ do
+ {
+ pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
+
+ count = pspan->count;
+
+ // calculate the initial 1/z
+ du = (float)pspan->u;
+ dv = (float)pspan->v;
+
+ zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
+ // we count on FP exceptions being turned off to avoid range problems
+ izi = (int)(zi * 0x8000 * 0x10000);
+
+ if ((long)pdest & 0x02)
+ {
+ *pdest++ = (short)(izi >> 16);
+ izi += izistep;
+ count--;
+ }
+
+ if ((doublecount = count >> 1) > 0)
+ {
+ do
+ {
+ ltemp = izi >> 16;
+ izi += izistep;
+ ltemp |= izi & 0xFFFF0000;
+ izi += izistep;
+ *(int *)pdest = ltemp;
+ pdest += 2;
+ } while (--doublecount > 0);
+ }
+
+ if (count & 1)
+ *pdest = (short)(izi >> 16);
+
+ } while ((pspan = pspan->pnext) != NULL);
+}
+
+#endif
+
--- /dev/null
+++ b/ref/r_sprite.c
@@ -1,0 +1,123 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// r_sprite.c
+#include "r_local.h"
+
+extern polydesc_t r_polydesc;
+
+void R_BuildPolygonFromSurface(msurface_t *fa);
+void R_PolygonCalculateGradients (void);
+
+extern void R_PolyChooseSpanletRoutine( float alpha, qboolean isturbulent );
+
+extern vec5_t r_clip_verts[2][MAXWORKINGVERTS+2];
+
+extern void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured );
+
+/*
+** R_DrawSprite
+**
+** Draw currententity / currentmodel as a single texture
+** mapped polygon
+*/
+void R_DrawSprite (void)
+{
+ vec5_t *pverts;
+ vec3_t left, up, right, down;
+ dsprite_t *s_psprite;
+ dsprframe_t *s_psprframe;
+
+
+ s_psprite = (dsprite_t *)currentmodel->extradata;
+#if 0
+ if (currententity->frame >= s_psprite->numframes
+ || currententity->frame < 0)
+ {
+ ri.Con_Printf (PRINT_ALL, "No such sprite frame %i\n",
+ currententity->frame);
+ currententity->frame = 0;
+ }
+#endif
+ currententity->frame %= s_psprite->numframes;
+
+ s_psprframe = &s_psprite->frames[currententity->frame];
+
+ r_polydesc.pixels = currentmodel->skins[currententity->frame]->pixels[0];
+ r_polydesc.pixel_width = s_psprframe->width;
+ r_polydesc.pixel_height = s_psprframe->height;
+ r_polydesc.dist = 0;
+
+ // generate the sprite's axes, completely parallel to the viewplane.
+ VectorCopy (vup, r_polydesc.vup);
+ VectorCopy (vright, r_polydesc.vright);
+ VectorCopy (vpn, r_polydesc.vpn);
+
+// build the sprite poster in worldspace
+ VectorScale (r_polydesc.vright,
+ s_psprframe->width - s_psprframe->origin_x, right);
+ VectorScale (r_polydesc.vup,
+ s_psprframe->height - s_psprframe->origin_y, up);
+ VectorScale (r_polydesc.vright,
+ -s_psprframe->origin_x, left);
+ VectorScale (r_polydesc.vup,
+ -s_psprframe->origin_y, down);
+
+ // invert UP vector for sprites
+ VectorInverse( r_polydesc.vup );
+
+ pverts = r_clip_verts[0];
+
+ pverts[0][0] = r_entorigin[0] + up[0] + left[0];
+ pverts[0][1] = r_entorigin[1] + up[1] + left[1];
+ pverts[0][2] = r_entorigin[2] + up[2] + left[2];
+ pverts[0][3] = 0;
+ pverts[0][4] = 0;
+
+ pverts[1][0] = r_entorigin[0] + up[0] + right[0];
+ pverts[1][1] = r_entorigin[1] + up[1] + right[1];
+ pverts[1][2] = r_entorigin[2] + up[2] + right[2];
+ pverts[1][3] = s_psprframe->width;
+ pverts[1][4] = 0;
+
+ pverts[2][0] = r_entorigin[0] + down[0] + right[0];
+ pverts[2][1] = r_entorigin[1] + down[1] + right[1];
+ pverts[2][2] = r_entorigin[2] + down[2] + right[2];
+ pverts[2][3] = s_psprframe->width;
+ pverts[2][4] = s_psprframe->height;
+
+ pverts[3][0] = r_entorigin[0] + down[0] + left[0];
+ pverts[3][1] = r_entorigin[1] + down[1] + left[1];
+ pverts[3][2] = r_entorigin[2] + down[2] + left[2];
+ pverts[3][3] = 0;
+ pverts[3][4] = s_psprframe->height;
+
+ r_polydesc.nump = 4;
+ r_polydesc.s_offset = ( r_polydesc.pixel_width >> 1);
+ r_polydesc.t_offset = ( r_polydesc.pixel_height >> 1);
+ VectorCopy( modelorg, r_polydesc.viewer_position );
+
+ r_polydesc.stipple_parity = 1;
+ if ( currententity->flags & RF_TRANSLUCENT )
+ R_ClipAndDrawPoly ( currententity->alpha, false, true );
+ else
+ R_ClipAndDrawPoly ( 1.0F, false, true );
+ r_polydesc.stipple_parity = 0;
+}
+
--- /dev/null
+++ b/ref/r_surf.c
@@ -1,0 +1,651 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// r_surf.c: surface-related refresh code
+
+#include "r_local.h"
+
+drawsurf_t r_drawsurf;
+
+int lightleft, sourcesstep, blocksize, sourcetstep;
+int lightdelta, lightdeltastep;
+int lightright, lightleftstep, lightrightstep, blockdivshift;
+unsigned blockdivmask;
+void *prowdestbase;
+unsigned char *pbasesource;
+int surfrowbytes; // used by ASM files
+unsigned *r_lightptr;
+int r_stepback;
+int r_lightwidth;
+int r_numhblocks, r_numvblocks;
+unsigned char *r_source, *r_sourcemax;
+
+void R_DrawSurfaceBlock8_mip0 (void);
+void R_DrawSurfaceBlock8_mip1 (void);
+void R_DrawSurfaceBlock8_mip2 (void);
+void R_DrawSurfaceBlock8_mip3 (void);
+
+static void (*surfmiptable[4])(void) = {
+ R_DrawSurfaceBlock8_mip0,
+ R_DrawSurfaceBlock8_mip1,
+ R_DrawSurfaceBlock8_mip2,
+ R_DrawSurfaceBlock8_mip3
+};
+
+void R_BuildLightMap (void);
+extern unsigned blocklights[1024]; // allow some very large lightmaps
+
+float surfscale;
+qboolean r_cache_thrash; // set if surface cache is thrashing
+
+int sc_size;
+surfcache_t *sc_rover, *sc_base;
+
+/*
+===============
+R_TextureAnimation
+
+Returns the proper texture for a given time and base texture
+===============
+*/
+image_t *R_TextureAnimation (mtexinfo_t *tex)
+{
+ int c;
+
+ if (!tex->next)
+ return tex->image;
+
+ c = currententity->frame % tex->numframes;
+ while (c)
+ {
+ tex = tex->next;
+ c--;
+ }
+
+ return tex->image;
+}
+
+
+/*
+===============
+R_DrawSurface
+===============
+*/
+void R_DrawSurface (void)
+{
+ unsigned char *basetptr;
+ int smax, tmax, twidth;
+ int u;
+ int soffset, basetoffset, texwidth;
+ int horzblockstep;
+ unsigned char *pcolumndest;
+ void (*pblockdrawer)(void);
+ image_t *mt;
+
+ surfrowbytes = r_drawsurf.rowbytes;
+
+ mt = r_drawsurf.image;
+
+ r_source = mt->pixels[r_drawsurf.surfmip];
+
+// the fractional light values should range from 0 to (VID_GRADES - 1) << 16
+// from a source range of 0 - 255
+
+ texwidth = mt->width >> r_drawsurf.surfmip;
+
+ blocksize = 16 >> r_drawsurf.surfmip;
+ blockdivshift = 4 - r_drawsurf.surfmip;
+ blockdivmask = (1 << blockdivshift) - 1;
+
+ r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1;
+
+ r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
+ r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
+
+//==============================
+
+ pblockdrawer = surfmiptable[r_drawsurf.surfmip];
+// TODO: only needs to be set when there is a display settings change
+ horzblockstep = blocksize;
+
+ smax = mt->width >> r_drawsurf.surfmip;
+ twidth = texwidth;
+ tmax = mt->height >> r_drawsurf.surfmip;
+ sourcetstep = texwidth;
+ r_stepback = tmax * twidth;
+
+ r_sourcemax = r_source + (tmax * smax);
+
+ soffset = r_drawsurf.surf->texturemins[0];
+ basetoffset = r_drawsurf.surf->texturemins[1];
+
+// << 16 components are to guarantee positive values for %
+ soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
+ basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip)
+ + (tmax << 16)) % tmax) * twidth)];
+
+ pcolumndest = r_drawsurf.surfdat;
+
+ for (u=0 ; u<r_numhblocks; u++)
+ {
+ r_lightptr = blocklights + u;
+
+ prowdestbase = pcolumndest;
+
+ pbasesource = basetptr + soffset;
+
+ (*pblockdrawer)();
+
+ soffset = soffset + blocksize;
+ if (soffset >= smax)
+ soffset = 0;
+
+ pcolumndest += horzblockstep;
+ }
+}
+
+
+//=============================================================================
+
+#if !id386
+
+/*
+================
+R_DrawSurfaceBlock8_mip0
+================
+*/
+void R_DrawSurfaceBlock8_mip0 (void)
+{
+ int v, i, b, lightstep, lighttemp, light;
+ unsigned char pix, *psource, *prowdest;
+
+ psource = pbasesource;
+ prowdest = prowdestbase;
+
+ for (v=0 ; v<r_numvblocks ; v++)
+ {
+ // FIXME: make these locals?
+ // FIXME: use delta rather than both right and left, like ASM?
+ lightleft = r_lightptr[0];
+ lightright = r_lightptr[1];
+ r_lightptr += r_lightwidth;
+ lightleftstep = (r_lightptr[0] - lightleft) >> 4;
+ lightrightstep = (r_lightptr[1] - lightright) >> 4;
+
+ for (i=0 ; i<16 ; i++)
+ {
+ lighttemp = lightleft - lightright;
+ lightstep = lighttemp >> 4;
+
+ light = lightright;
+
+ for (b=15; b>=0; b--)
+ {
+ pix = psource[b];
+ prowdest[b] = ((unsigned char *)vid.colormap)
+ [(light & 0xFF00) + pix];
+ light += lightstep;
+ }
+
+ psource += sourcetstep;
+ lightright += lightrightstep;
+ lightleft += lightleftstep;
+ prowdest += surfrowbytes;
+ }
+
+ if (psource >= r_sourcemax)
+ psource -= r_stepback;
+ }
+}
+
+
+/*
+================
+R_DrawSurfaceBlock8_mip1
+================
+*/
+void R_DrawSurfaceBlock8_mip1 (void)
+{
+ int v, i, b, lightstep, lighttemp, light;
+ unsigned char pix, *psource, *prowdest;
+
+ psource = pbasesource;
+ prowdest = prowdestbase;
+
+ for (v=0 ; v<r_numvblocks ; v++)
+ {
+ // FIXME: make these locals?
+ // FIXME: use delta rather than both right and left, like ASM?
+ lightleft = r_lightptr[0];
+ lightright = r_lightptr[1];
+ r_lightptr += r_lightwidth;
+ lightleftstep = (r_lightptr[0] - lightleft) >> 3;
+ lightrightstep = (r_lightptr[1] - lightright) >> 3;
+
+ for (i=0 ; i<8 ; i++)
+ {
+ lighttemp = lightleft - lightright;
+ lightstep = lighttemp >> 3;
+
+ light = lightright;
+
+ for (b=7; b>=0; b--)
+ {
+ pix = psource[b];
+ prowdest[b] = ((unsigned char *)vid.colormap)
+ [(light & 0xFF00) + pix];
+ light += lightstep;
+ }
+
+ psource += sourcetstep;
+ lightright += lightrightstep;
+ lightleft += lightleftstep;
+ prowdest += surfrowbytes;
+ }
+
+ if (psource >= r_sourcemax)
+ psource -= r_stepback;
+ }
+}
+
+
+/*
+================
+R_DrawSurfaceBlock8_mip2
+================
+*/
+void R_DrawSurfaceBlock8_mip2 (void)
+{
+ int v, i, b, lightstep, lighttemp, light;
+ unsigned char pix, *psource, *prowdest;
+
+ psource = pbasesource;
+ prowdest = prowdestbase;
+
+ for (v=0 ; v<r_numvblocks ; v++)
+ {
+ // FIXME: make these locals?
+ // FIXME: use delta rather than both right and left, like ASM?
+ lightleft = r_lightptr[0];
+ lightright = r_lightptr[1];
+ r_lightptr += r_lightwidth;
+ lightleftstep = (r_lightptr[0] - lightleft) >> 2;
+ lightrightstep = (r_lightptr[1] - lightright) >> 2;
+
+ for (i=0 ; i<4 ; i++)
+ {
+ lighttemp = lightleft - lightright;
+ lightstep = lighttemp >> 2;
+
+ light = lightright;
+
+ for (b=3; b>=0; b--)
+ {
+ pix = psource[b];
+ prowdest[b] = ((unsigned char *)vid.colormap)
+ [(light & 0xFF00) + pix];
+ light += lightstep;
+ }
+
+ psource += sourcetstep;
+ lightright += lightrightstep;
+ lightleft += lightleftstep;
+ prowdest += surfrowbytes;
+ }
+
+ if (psource >= r_sourcemax)
+ psource -= r_stepback;
+ }
+}
+
+
+/*
+================
+R_DrawSurfaceBlock8_mip3
+================
+*/
+void R_DrawSurfaceBlock8_mip3 (void)
+{
+ int v, i, b, lightstep, lighttemp, light;
+ unsigned char pix, *psource, *prowdest;
+
+ psource = pbasesource;
+ prowdest = prowdestbase;
+
+ for (v=0 ; v<r_numvblocks ; v++)
+ {
+ // FIXME: make these locals?
+ // FIXME: use delta rather than both right and left, like ASM?
+ lightleft = r_lightptr[0];
+ lightright = r_lightptr[1];
+ r_lightptr += r_lightwidth;
+ lightleftstep = (r_lightptr[0] - lightleft) >> 1;
+ lightrightstep = (r_lightptr[1] - lightright) >> 1;
+
+ for (i=0 ; i<2 ; i++)
+ {
+ lighttemp = lightleft - lightright;
+ lightstep = lighttemp >> 1;
+
+ light = lightright;
+
+ for (b=1; b>=0; b--)
+ {
+ pix = psource[b];
+ prowdest[b] = ((unsigned char *)vid.colormap)
+ [(light & 0xFF00) + pix];
+ light += lightstep;
+ }
+
+ psource += sourcetstep;
+ lightright += lightrightstep;
+ lightleft += lightleftstep;
+ prowdest += surfrowbytes;
+ }
+
+ if (psource >= r_sourcemax)
+ psource -= r_stepback;
+ }
+}
+
+#endif
+
+
+//============================================================================
+
+
+/*
+================
+R_InitCaches
+
+================
+*/
+void R_InitCaches (void)
+{
+ int size;
+ int pix;
+
+ // calculate size to allocate
+ if (sw_surfcacheoverride->value)
+ {
+ size = sw_surfcacheoverride->value;
+ }
+ else
+ {
+ size = SURFCACHE_SIZE_AT_320X240;
+
+ pix = vid.width*vid.height;
+ if (pix > 64000)
+ size += (pix-64000)*3;
+ }
+
+ // round up to page size
+ size = (size + 8191) & ~8191;
+
+ ri.Con_Printf (PRINT_ALL,"%ik surface cache\n", size/1024);
+
+ sc_size = size;
+ sc_base = (surfcache_t *)malloc(size);
+ sc_rover = sc_base;
+
+ sc_base->next = NULL;
+ sc_base->owner = NULL;
+ sc_base->size = sc_size;
+}
+
+
+/*
+==================
+D_FlushCaches
+==================
+*/
+void D_FlushCaches (void)
+{
+ surfcache_t *c;
+
+ if (!sc_base)
+ return;
+
+ for (c = sc_base ; c ; c = c->next)
+ {
+ if (c->owner)
+ *c->owner = NULL;
+ }
+
+ sc_rover = sc_base;
+ sc_base->next = NULL;
+ sc_base->owner = NULL;
+ sc_base->size = sc_size;
+}
+
+/*
+=================
+D_SCAlloc
+=================
+*/
+surfcache_t *D_SCAlloc (int width, int size)
+{
+ surfcache_t *new;
+ qboolean wrapped_this_time;
+
+ if ((width < 0) || (width > 256))
+ ri.Sys_Error (ERR_FATAL,"D_SCAlloc: bad cache width %d\n", width);
+
+ if ((size <= 0) || (size > 0x10000))
+ ri.Sys_Error (ERR_FATAL,"D_SCAlloc: bad cache size %d\n", size);
+
+ size = (int)&((surfcache_t *)0)->data[size];
+ size = (size + 3) & ~3;
+ if (size > sc_size)
+ ri.Sys_Error (ERR_FATAL,"D_SCAlloc: %i > cache size of %i",size, sc_size);
+
+// if there is not size bytes after the rover, reset to the start
+ wrapped_this_time = false;
+
+ if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
+ {
+ if (sc_rover)
+ {
+ wrapped_this_time = true;
+ }
+ sc_rover = sc_base;
+ }
+
+// colect and free surfcache_t blocks until the rover block is large enough
+ new = sc_rover;
+ if (sc_rover->owner)
+ *sc_rover->owner = NULL;
+
+ while (new->size < size)
+ {
+ // free another
+ sc_rover = sc_rover->next;
+ if (!sc_rover)
+ ri.Sys_Error (ERR_FATAL,"D_SCAlloc: hit the end of memory");
+ if (sc_rover->owner)
+ *sc_rover->owner = NULL;
+
+ new->size += sc_rover->size;
+ new->next = sc_rover->next;
+ }
+
+// create a fragment out of any leftovers
+ if (new->size - size > 256)
+ {
+ sc_rover = (surfcache_t *)( (byte *)new + size);
+ sc_rover->size = new->size - size;
+ sc_rover->next = new->next;
+ sc_rover->width = 0;
+ sc_rover->owner = NULL;
+ new->next = sc_rover;
+ new->size = size;
+ }
+ else
+ sc_rover = new->next;
+
+ new->width = width;
+// DEBUG
+ if (width > 0)
+ new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
+
+ new->owner = NULL; // should be set properly after return
+
+ if (d_roverwrapped)
+ {
+ if (wrapped_this_time || (sc_rover >= d_initial_rover))
+ r_cache_thrash = true;
+ }
+ else if (wrapped_this_time)
+ {
+ d_roverwrapped = true;
+ }
+
+ return new;
+}
+
+
+/*
+=================
+D_SCDump
+=================
+*/
+void D_SCDump (void)
+{
+ surfcache_t *test;
+
+ for (test = sc_base ; test ; test = test->next)
+ {
+ if (test == sc_rover)
+ ri.Con_Printf (PRINT_ALL,"ROVER:\n");
+ ri.Con_Printf (PRINT_ALL,"%p : %i bytes %i width\n",test, test->size, test->width);
+ }
+}
+
+//=============================================================================
+
+// if the num is not a power of 2, assume it will not repeat
+
+int MaskForNum (int num)
+{
+ if (num==128)
+ return 127;
+ if (num==64)
+ return 63;
+ if (num==32)
+ return 31;
+ if (num==16)
+ return 15;
+ return 255;
+}
+
+int D_log2 (int num)
+{
+ int c;
+
+ c = 0;
+
+ while (num>>=1)
+ c++;
+ return c;
+}
+
+//=============================================================================
+
+/*
+================
+D_CacheSurface
+================
+*/
+surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
+{
+ surfcache_t *cache;
+
+//
+// if the surface is animating or flashing, flush the cache
+//
+ r_drawsurf.image = R_TextureAnimation (surface->texinfo);
+ r_drawsurf.lightadj[0] = r_newrefdef.lightstyles[surface->styles[0]].white*128;
+ r_drawsurf.lightadj[1] = r_newrefdef.lightstyles[surface->styles[1]].white*128;
+ r_drawsurf.lightadj[2] = r_newrefdef.lightstyles[surface->styles[2]].white*128;
+ r_drawsurf.lightadj[3] = r_newrefdef.lightstyles[surface->styles[3]].white*128;
+
+//
+// see if the cache holds apropriate data
+//
+ cache = surface->cachespots[miplevel];
+
+ if (cache && !cache->dlight && surface->dlightframe != r_framecount
+ && cache->image == r_drawsurf.image
+ && cache->lightadj[0] == r_drawsurf.lightadj[0]
+ && cache->lightadj[1] == r_drawsurf.lightadj[1]
+ && cache->lightadj[2] == r_drawsurf.lightadj[2]
+ && cache->lightadj[3] == r_drawsurf.lightadj[3] )
+ return cache;
+
+//
+// determine shape of surface
+//
+ surfscale = 1.0 / (1<<miplevel);
+ r_drawsurf.surfmip = miplevel;
+ r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
+ r_drawsurf.rowbytes = r_drawsurf.surfwidth;
+ r_drawsurf.surfheight = surface->extents[1] >> miplevel;
+
+//
+// allocate memory if needed
+//
+ if (!cache) // if a texture just animated, don't reallocate it
+ {
+ cache = D_SCAlloc (r_drawsurf.surfwidth,
+ r_drawsurf.surfwidth * r_drawsurf.surfheight);
+ surface->cachespots[miplevel] = cache;
+ cache->owner = &surface->cachespots[miplevel];
+ cache->mipscale = surfscale;
+ }
+
+ if (surface->dlightframe == r_framecount)
+ cache->dlight = 1;
+ else
+ cache->dlight = 0;
+
+ r_drawsurf.surfdat = (pixel_t *)cache->data;
+
+ cache->image = r_drawsurf.image;
+ cache->lightadj[0] = r_drawsurf.lightadj[0];
+ cache->lightadj[1] = r_drawsurf.lightadj[1];
+ cache->lightadj[2] = r_drawsurf.lightadj[2];
+ cache->lightadj[3] = r_drawsurf.lightadj[3];
+
+//
+// draw and light the surface texture
+//
+ r_drawsurf.surf = surface;
+
+ c_surf++;
+
+ // calculate the lightings
+ R_BuildLightMap ();
+
+ // rasterize the surface into the cache
+ R_DrawSurface ();
+
+ return cache;
+}
+
+
--- /dev/null
+++ b/ref/rand1k.h
@@ -1,0 +1,123 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// 1K random numbers in the range 0-255
+0, 144, 49, 207, 149, 122, 89, 229, 210, 191,
+44, 219, 181, 131, 77, 3, 23, 93, 37, 42,
+253, 114, 30, 1, 2, 96, 136, 146, 154, 155,
+42, 169, 115, 90, 14, 155, 200, 205, 133, 77,
+224, 186, 244, 236, 138, 36, 118, 60, 220, 53,
+199, 215, 255, 255, 156, 100, 68, 76, 215, 6,
+96, 23, 173, 14, 2, 235, 70, 69, 150, 176,
+214, 185, 124, 52, 190, 119, 117, 242, 190, 27,
+153, 98, 188, 155, 146, 92, 38, 57, 108, 205,
+132, 253, 192, 88, 43, 168, 125, 16, 179, 129,
+37, 243, 36, 231, 177, 77, 109, 18, 247, 174,
+39, 224, 210, 149, 48, 45, 209, 121, 39, 129,
+187, 103, 71, 145, 174, 193, 184, 121, 31, 94,
+213, 8, 132, 169, 109, 26, 243, 235, 140, 88,
+120, 95, 216, 81, 116, 69, 251, 76, 189, 145,
+50, 194, 214, 101, 128, 227, 7, 254, 146, 12,
+136, 49, 215, 160, 168, 50, 215, 31, 28, 190,
+80, 240, 73, 86, 35, 187, 213, 181, 153, 191,
+64, 36, 0, 15, 206, 218, 53, 29, 141, 3,
+29, 116, 192, 175, 139, 18, 111, 51, 178, 74,
+111, 59, 147, 136, 160, 41, 129, 246, 178, 236,
+48, 86, 45, 254, 117, 255, 24, 160, 24, 112,
+238, 12, 229, 74, 58, 196, 105, 51, 160, 154,
+115, 119, 153, 162, 218, 212, 159, 184, 144, 96,
+47, 188, 142, 231, 62, 48, 154, 178, 149, 89,
+126, 20, 189, 156, 158, 176, 205, 38, 147, 222,
+233, 157, 186, 11, 170, 249, 80, 145, 78, 44,
+27, 222, 217, 190, 39, 83, 20, 19, 164, 209,
+139, 114, 104, 76, 119, 128, 39, 82, 188, 80,
+211, 245, 223, 185, 76, 241, 32, 16, 200, 134,
+156, 244, 18, 224, 167, 82, 26, 129, 58, 74,
+235, 141, 169, 29, 126, 97, 127, 203, 130, 97,
+176, 136, 155, 101, 1, 181, 25, 159, 220, 125,
+191, 127, 97, 201, 141, 91, 244, 161, 45, 95,
+33, 190, 243, 156, 7, 84, 14, 163, 33, 216,
+221, 152, 184, 218, 3, 32, 181, 157, 55, 16,
+43, 159, 87, 81, 94, 169, 205, 206, 134, 156,
+204, 230, 37, 161, 103, 64, 34, 218, 16, 109,
+146, 77, 140, 57, 79, 28, 206, 34, 72, 201,
+229, 202, 190, 157, 92, 219, 58, 221, 58, 63,
+138, 252, 13, 20, 134, 109, 24, 66, 228, 59,
+37, 32, 238, 20, 12, 15, 86, 234, 102, 110,
+242, 214, 136, 215, 177, 101, 66, 1, 134, 244,
+102, 61, 149, 65, 175, 241, 111, 227, 1, 240,
+153, 201, 147, 36, 56, 98, 1, 106, 21, 168,
+218, 16, 207, 169, 177, 205, 135, 175, 36, 176,
+186, 199, 7, 222, 164, 180, 21, 141, 242, 15,
+70, 37, 251, 158, 74, 236, 94, 177, 55, 39,
+61, 133, 230, 27, 231, 113, 20, 200, 43, 249,
+198, 222, 53, 116, 0, 192, 29, 103, 79, 254,
+9, 64, 48, 63, 39, 158, 226, 240, 50, 199,
+165, 168, 232, 116, 235, 170, 38, 162, 145, 108,
+241, 138, 148, 137, 65, 101, 89, 9, 203, 50,
+17, 99, 151, 18, 50, 39, 164, 116, 154, 178,
+112, 175, 101, 213, 151, 51, 243, 224, 100, 252,
+47, 229, 147, 113, 160, 181, 12, 73, 66, 104,
+229, 181, 186, 229, 100, 101, 231, 79, 99, 146,
+90, 187, 190, 188, 189, 35, 51, 69, 174, 233,
+94, 132, 28, 232, 51, 132, 167, 112, 176, 23,
+20, 19, 7, 90, 78, 178, 36, 101, 17, 172,
+185, 50, 177, 157, 167, 139, 25, 139, 12, 249,
+118, 248, 186, 135, 174, 177, 95, 99, 12, 207,
+43, 15, 79, 200, 54, 82, 124, 2, 112, 130,
+155, 194, 102, 89, 215, 241, 159, 255, 13, 144,
+221, 99, 78, 72, 6, 156, 100, 4, 7, 116,
+219, 239, 102, 186, 156, 206, 224, 149, 152, 20,
+203, 118, 151, 150, 145, 208, 172, 87, 2, 68,
+87, 59, 197, 95, 222, 29, 185, 161, 228, 46,
+137, 230, 199, 247, 50, 230, 204, 244, 217, 227,
+160, 47, 157, 67, 64, 187, 201, 43, 182, 123,
+20, 206, 218, 31, 78, 146, 121, 195, 49, 186,
+254, 3, 165, 177, 44, 18, 70, 173, 214, 142,
+95, 199, 59, 163, 59, 52, 248, 72, 5, 196,
+38, 12, 2, 89, 164, 87, 106, 106, 23, 139,
+179, 86, 168, 224, 137, 145, 13, 119, 66, 109,
+221, 124, 22, 144, 181, 199, 221, 217, 75, 221,
+165, 191, 212, 195, 223, 232, 233, 133, 112, 27,
+90, 210, 109, 43, 0, 168, 198, 16, 22, 98,
+175, 206, 39, 36, 12, 88, 4, 250, 165, 13,
+234, 163, 110, 5, 62, 100, 167, 200, 5, 211,
+35, 162, 140, 251, 118, 54, 76, 200, 87, 123,
+155, 26, 252, 193, 38, 116, 182, 255, 198, 164,
+159, 242, 176, 74, 145, 74, 140, 182, 63, 139,
+126, 243, 171, 195, 159, 114, 204, 190, 253, 52,
+161, 232, 151, 235, 129, 125, 115, 227, 240, 46,
+64, 51, 187, 240, 160, 10, 164, 8, 142, 139,
+114, 15, 254, 32, 153, 12, 44, 169, 85, 80,
+167, 105, 109, 56, 173, 42, 127, 129, 205, 111,
+1, 86, 96, 32, 211, 187, 228, 164, 166, 131,
+187, 188, 245, 119, 92, 28, 231, 210, 116, 27,
+222, 194, 10, 106, 239, 17, 42, 54, 29, 151,
+30, 158, 148, 176, 187, 234, 171, 76, 207, 96,
+255, 197, 52, 43, 99, 46, 148, 50, 245, 48,
+97, 77, 30, 50, 11, 197, 194, 225, 0, 114,
+109, 205, 118, 126, 191, 61, 143, 23, 236, 228,
+219, 15, 125, 161, 191, 193, 65, 232, 202, 51,
+141, 13, 133, 202, 180, 6, 187, 141, 234, 224,
+204, 78, 101, 123, 13, 166, 0, 196, 193, 56,
+39, 14, 171, 8, 88, 178, 204, 111, 251, 162,
+75, 122, 223, 20, 25, 36, 36, 235, 79, 95,
+208, 11, 208, 61, 229, 65, 68, 53, 58, 216,
+223, 227, 216, 155, 10, 44, 47, 91, 115, 47,
+228, 159, 139, 233
--- a/ref_soft/adivtab.h
+++ /dev/null
@@ -1,1077 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// table of quotients and remainders for [-15...16] / [-15...16]
-
-// numerator = -15
-{1, 0},
-{1, -1},
-{1, -2},
-{1, -3},
-{1, -4},
-{1, -5},
-{1, -6},
-{1, -7},
-{2, -1},
-{2, -3},
-{3, 0},
-{3, -3},
-{5, 0},
-{7, -1},
-{15, 0},
-{0, 0},
-{-15, 0},
-{-8, 1},
-{-5, 0},
-{-4, 1},
-{-3, 0},
-{-3, 3},
-{-3, 6},
-{-2, 1},
-{-2, 3},
-{-2, 5},
-{-2, 7},
-{-2, 9},
-{-2, 11},
-{-2, 13},
-{-1, 0},
-{-1, 1},
-// numerator = -14
-{0, -14},
-{1, 0},
-{1, -1},
-{1, -2},
-{1, -3},
-{1, -4},
-{1, -5},
-{1, -6},
-{2, 0},
-{2, -2},
-{2, -4},
-{3, -2},
-{4, -2},
-{7, 0},
-{14, 0},
-{0, 0},
-{-14, 0},
-{-7, 0},
-{-5, 1},
-{-4, 2},
-{-3, 1},
-{-3, 4},
-{-2, 0},
-{-2, 2},
-{-2, 4},
-{-2, 6},
-{-2, 8},
-{-2, 10},
-{-2, 12},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-// numerator = -13
-{0, -13},
-{0, -13},
-{1, 0},
-{1, -1},
-{1, -2},
-{1, -3},
-{1, -4},
-{1, -5},
-{1, -6},
-{2, -1},
-{2, -3},
-{3, -1},
-{4, -1},
-{6, -1},
-{13, 0},
-{0, 0},
-{-13, 0},
-{-7, 1},
-{-5, 2},
-{-4, 3},
-{-3, 2},
-{-3, 5},
-{-2, 1},
-{-2, 3},
-{-2, 5},
-{-2, 7},
-{-2, 9},
-{-2, 11},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-// numerator = -12
-{0, -12},
-{0, -12},
-{0, -12},
-{1, 0},
-{1, -1},
-{1, -2},
-{1, -3},
-{1, -4},
-{1, -5},
-{2, 0},
-{2, -2},
-{3, 0},
-{4, 0},
-{6, 0},
-{12, 0},
-{0, 0},
-{-12, 0},
-{-6, 0},
-{-4, 0},
-{-3, 0},
-{-3, 3},
-{-2, 0},
-{-2, 2},
-{-2, 4},
-{-2, 6},
-{-2, 8},
-{-2, 10},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-{-1, 4},
-// numerator = -11
-{0, -11},
-{0, -11},
-{0, -11},
-{0, -11},
-{1, 0},
-{1, -1},
-{1, -2},
-{1, -3},
-{1, -4},
-{1, -5},
-{2, -1},
-{2, -3},
-{3, -2},
-{5, -1},
-{11, 0},
-{0, 0},
-{-11, 0},
-{-6, 1},
-{-4, 1},
-{-3, 1},
-{-3, 4},
-{-2, 1},
-{-2, 3},
-{-2, 5},
-{-2, 7},
-{-2, 9},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-{-1, 4},
-{-1, 5},
-// numerator = -10
-{0, -10},
-{0, -10},
-{0, -10},
-{0, -10},
-{0, -10},
-{1, 0},
-{1, -1},
-{1, -2},
-{1, -3},
-{1, -4},
-{2, 0},
-{2, -2},
-{3, -1},
-{5, 0},
-{10, 0},
-{0, 0},
-{-10, 0},
-{-5, 0},
-{-4, 2},
-{-3, 2},
-{-2, 0},
-{-2, 2},
-{-2, 4},
-{-2, 6},
-{-2, 8},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-{-1, 4},
-{-1, 5},
-{-1, 6},
-// numerator = -9
-{0, -9},
-{0, -9},
-{0, -9},
-{0, -9},
-{0, -9},
-{0, -9},
-{1, 0},
-{1, -1},
-{1, -2},
-{1, -3},
-{1, -4},
-{2, -1},
-{3, 0},
-{4, -1},
-{9, 0},
-{0, 0},
-{-9, 0},
-{-5, 1},
-{-3, 0},
-{-3, 3},
-{-2, 1},
-{-2, 3},
-{-2, 5},
-{-2, 7},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-{-1, 4},
-{-1, 5},
-{-1, 6},
-{-1, 7},
-// numerator = -8
-{0, -8},
-{0, -8},
-{0, -8},
-{0, -8},
-{0, -8},
-{0, -8},
-{0, -8},
-{1, 0},
-{1, -1},
-{1, -2},
-{1, -3},
-{2, 0},
-{2, -2},
-{4, 0},
-{8, 0},
-{0, 0},
-{-8, 0},
-{-4, 0},
-{-3, 1},
-{-2, 0},
-{-2, 2},
-{-2, 4},
-{-2, 6},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-{-1, 4},
-{-1, 5},
-{-1, 6},
-{-1, 7},
-{-1, 8},
-// numerator = -7
-{0, -7},
-{0, -7},
-{0, -7},
-{0, -7},
-{0, -7},
-{0, -7},
-{0, -7},
-{0, -7},
-{1, 0},
-{1, -1},
-{1, -2},
-{1, -3},
-{2, -1},
-{3, -1},
-{7, 0},
-{0, 0},
-{-7, 0},
-{-4, 1},
-{-3, 2},
-{-2, 1},
-{-2, 3},
-{-2, 5},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-{-1, 4},
-{-1, 5},
-{-1, 6},
-{-1, 7},
-{-1, 8},
-{-1, 9},
-// numerator = -6
-{0, -6},
-{0, -6},
-{0, -6},
-{0, -6},
-{0, -6},
-{0, -6},
-{0, -6},
-{0, -6},
-{0, -6},
-{1, 0},
-{1, -1},
-{1, -2},
-{2, 0},
-{3, 0},
-{6, 0},
-{0, 0},
-{-6, 0},
-{-3, 0},
-{-2, 0},
-{-2, 2},
-{-2, 4},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-{-1, 4},
-{-1, 5},
-{-1, 6},
-{-1, 7},
-{-1, 8},
-{-1, 9},
-{-1, 10},
-// numerator = -5
-{0, -5},
-{0, -5},
-{0, -5},
-{0, -5},
-{0, -5},
-{0, -5},
-{0, -5},
-{0, -5},
-{0, -5},
-{0, -5},
-{1, 0},
-{1, -1},
-{1, -2},
-{2, -1},
-{5, 0},
-{0, 0},
-{-5, 0},
-{-3, 1},
-{-2, 1},
-{-2, 3},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-{-1, 4},
-{-1, 5},
-{-1, 6},
-{-1, 7},
-{-1, 8},
-{-1, 9},
-{-1, 10},
-{-1, 11},
-// numerator = -4
-{0, -4},
-{0, -4},
-{0, -4},
-{0, -4},
-{0, -4},
-{0, -4},
-{0, -4},
-{0, -4},
-{0, -4},
-{0, -4},
-{0, -4},
-{1, 0},
-{1, -1},
-{2, 0},
-{4, 0},
-{0, 0},
-{-4, 0},
-{-2, 0},
-{-2, 2},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-{-1, 4},
-{-1, 5},
-{-1, 6},
-{-1, 7},
-{-1, 8},
-{-1, 9},
-{-1, 10},
-{-1, 11},
-{-1, 12},
-// numerator = -3
-{0, -3},
-{0, -3},
-{0, -3},
-{0, -3},
-{0, -3},
-{0, -3},
-{0, -3},
-{0, -3},
-{0, -3},
-{0, -3},
-{0, -3},
-{0, -3},
-{1, 0},
-{1, -1},
-{3, 0},
-{0, 0},
-{-3, 0},
-{-2, 1},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-{-1, 4},
-{-1, 5},
-{-1, 6},
-{-1, 7},
-{-1, 8},
-{-1, 9},
-{-1, 10},
-{-1, 11},
-{-1, 12},
-{-1, 13},
-// numerator = -2
-{0, -2},
-{0, -2},
-{0, -2},
-{0, -2},
-{0, -2},
-{0, -2},
-{0, -2},
-{0, -2},
-{0, -2},
-{0, -2},
-{0, -2},
-{0, -2},
-{0, -2},
-{1, 0},
-{2, 0},
-{0, 0},
-{-2, 0},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-{-1, 4},
-{-1, 5},
-{-1, 6},
-{-1, 7},
-{-1, 8},
-{-1, 9},
-{-1, 10},
-{-1, 11},
-{-1, 12},
-{-1, 13},
-{-1, 14},
-// numerator = -1
-{0, -1},
-{0, -1},
-{0, -1},
-{0, -1},
-{0, -1},
-{0, -1},
-{0, -1},
-{0, -1},
-{0, -1},
-{0, -1},
-{0, -1},
-{0, -1},
-{0, -1},
-{0, -1},
-{1, 0},
-{0, 0},
-{-1, 0},
-{-1, 1},
-{-1, 2},
-{-1, 3},
-{-1, 4},
-{-1, 5},
-{-1, 6},
-{-1, 7},
-{-1, 8},
-{-1, 9},
-{-1, 10},
-{-1, 11},
-{-1, 12},
-{-1, 13},
-{-1, 14},
-{-1, 15},
-// numerator = 0
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-{0, 0},
-// numerator = 1
-{-1, -14},
-{-1, -13},
-{-1, -12},
-{-1, -11},
-{-1, -10},
-{-1, -9},
-{-1, -8},
-{-1, -7},
-{-1, -6},
-{-1, -5},
-{-1, -4},
-{-1, -3},
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{0, 0},
-{1, 0},
-{0, 1},
-{0, 1},
-{0, 1},
-{0, 1},
-{0, 1},
-{0, 1},
-{0, 1},
-{0, 1},
-{0, 1},
-{0, 1},
-{0, 1},
-{0, 1},
-{0, 1},
-{0, 1},
-{0, 1},
-// numerator = 2
-{-1, -13},
-{-1, -12},
-{-1, -11},
-{-1, -10},
-{-1, -9},
-{-1, -8},
-{-1, -7},
-{-1, -6},
-{-1, -5},
-{-1, -4},
-{-1, -3},
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{-2, 0},
-{0, 0},
-{2, 0},
-{1, 0},
-{0, 2},
-{0, 2},
-{0, 2},
-{0, 2},
-{0, 2},
-{0, 2},
-{0, 2},
-{0, 2},
-{0, 2},
-{0, 2},
-{0, 2},
-{0, 2},
-{0, 2},
-{0, 2},
-// numerator = 3
-{-1, -12},
-{-1, -11},
-{-1, -10},
-{-1, -9},
-{-1, -8},
-{-1, -7},
-{-1, -6},
-{-1, -5},
-{-1, -4},
-{-1, -3},
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{-2, -1},
-{-3, 0},
-{0, 0},
-{3, 0},
-{1, 1},
-{1, 0},
-{0, 3},
-{0, 3},
-{0, 3},
-{0, 3},
-{0, 3},
-{0, 3},
-{0, 3},
-{0, 3},
-{0, 3},
-{0, 3},
-{0, 3},
-{0, 3},
-{0, 3},
-// numerator = 4
-{-1, -11},
-{-1, -10},
-{-1, -9},
-{-1, -8},
-{-1, -7},
-{-1, -6},
-{-1, -5},
-{-1, -4},
-{-1, -3},
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{-2, -2},
-{-2, 0},
-{-4, 0},
-{0, 0},
-{4, 0},
-{2, 0},
-{1, 1},
-{1, 0},
-{0, 4},
-{0, 4},
-{0, 4},
-{0, 4},
-{0, 4},
-{0, 4},
-{0, 4},
-{0, 4},
-{0, 4},
-{0, 4},
-{0, 4},
-{0, 4},
-// numerator = 5
-{-1, -10},
-{-1, -9},
-{-1, -8},
-{-1, -7},
-{-1, -6},
-{-1, -5},
-{-1, -4},
-{-1, -3},
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{-2, -3},
-{-2, -1},
-{-3, -1},
-{-5, 0},
-{0, 0},
-{5, 0},
-{2, 1},
-{1, 2},
-{1, 1},
-{1, 0},
-{0, 5},
-{0, 5},
-{0, 5},
-{0, 5},
-{0, 5},
-{0, 5},
-{0, 5},
-{0, 5},
-{0, 5},
-{0, 5},
-{0, 5},
-// numerator = 6
-{-1, -9},
-{-1, -8},
-{-1, -7},
-{-1, -6},
-{-1, -5},
-{-1, -4},
-{-1, -3},
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{-2, -4},
-{-2, -2},
-{-2, 0},
-{-3, 0},
-{-6, 0},
-{0, 0},
-{6, 0},
-{3, 0},
-{2, 0},
-{1, 2},
-{1, 1},
-{1, 0},
-{0, 6},
-{0, 6},
-{0, 6},
-{0, 6},
-{0, 6},
-{0, 6},
-{0, 6},
-{0, 6},
-{0, 6},
-{0, 6},
-// numerator = 7
-{-1, -8},
-{-1, -7},
-{-1, -6},
-{-1, -5},
-{-1, -4},
-{-1, -3},
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{-2, -5},
-{-2, -3},
-{-2, -1},
-{-3, -2},
-{-4, -1},
-{-7, 0},
-{0, 0},
-{7, 0},
-{3, 1},
-{2, 1},
-{1, 3},
-{1, 2},
-{1, 1},
-{1, 0},
-{0, 7},
-{0, 7},
-{0, 7},
-{0, 7},
-{0, 7},
-{0, 7},
-{0, 7},
-{0, 7},
-{0, 7},
-// numerator = 8
-{-1, -7},
-{-1, -6},
-{-1, -5},
-{-1, -4},
-{-1, -3},
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{-2, -6},
-{-2, -4},
-{-2, -2},
-{-2, 0},
-{-3, -1},
-{-4, 0},
-{-8, 0},
-{0, 0},
-{8, 0},
-{4, 0},
-{2, 2},
-{2, 0},
-{1, 3},
-{1, 2},
-{1, 1},
-{1, 0},
-{0, 8},
-{0, 8},
-{0, 8},
-{0, 8},
-{0, 8},
-{0, 8},
-{0, 8},
-{0, 8},
-// numerator = 9
-{-1, -6},
-{-1, -5},
-{-1, -4},
-{-1, -3},
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{-2, -7},
-{-2, -5},
-{-2, -3},
-{-2, -1},
-{-3, -3},
-{-3, 0},
-{-5, -1},
-{-9, 0},
-{0, 0},
-{9, 0},
-{4, 1},
-{3, 0},
-{2, 1},
-{1, 4},
-{1, 3},
-{1, 2},
-{1, 1},
-{1, 0},
-{0, 9},
-{0, 9},
-{0, 9},
-{0, 9},
-{0, 9},
-{0, 9},
-{0, 9},
-// numerator = 10
-{-1, -5},
-{-1, -4},
-{-1, -3},
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{-2, -8},
-{-2, -6},
-{-2, -4},
-{-2, -2},
-{-2, 0},
-{-3, -2},
-{-4, -2},
-{-5, 0},
-{-10, 0},
-{0, 0},
-{10, 0},
-{5, 0},
-{3, 1},
-{2, 2},
-{2, 0},
-{1, 4},
-{1, 3},
-{1, 2},
-{1, 1},
-{1, 0},
-{0, 10},
-{0, 10},
-{0, 10},
-{0, 10},
-{0, 10},
-{0, 10},
-// numerator = 11
-{-1, -4},
-{-1, -3},
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{-2, -9},
-{-2, -7},
-{-2, -5},
-{-2, -3},
-{-2, -1},
-{-3, -4},
-{-3, -1},
-{-4, -1},
-{-6, -1},
-{-11, 0},
-{0, 0},
-{11, 0},
-{5, 1},
-{3, 2},
-{2, 3},
-{2, 1},
-{1, 5},
-{1, 4},
-{1, 3},
-{1, 2},
-{1, 1},
-{1, 0},
-{0, 11},
-{0, 11},
-{0, 11},
-{0, 11},
-{0, 11},
-// numerator = 12
-{-1, -3},
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{-2, -10},
-{-2, -8},
-{-2, -6},
-{-2, -4},
-{-2, -2},
-{-2, 0},
-{-3, -3},
-{-3, 0},
-{-4, 0},
-{-6, 0},
-{-12, 0},
-{0, 0},
-{12, 0},
-{6, 0},
-{4, 0},
-{3, 0},
-{2, 2},
-{2, 0},
-{1, 5},
-{1, 4},
-{1, 3},
-{1, 2},
-{1, 1},
-{1, 0},
-{0, 12},
-{0, 12},
-{0, 12},
-{0, 12},
-// numerator = 13
-{-1, -2},
-{-1, -1},
-{-1, 0},
-{-2, -11},
-{-2, -9},
-{-2, -7},
-{-2, -5},
-{-2, -3},
-{-2, -1},
-{-3, -5},
-{-3, -2},
-{-4, -3},
-{-5, -2},
-{-7, -1},
-{-13, 0},
-{0, 0},
-{13, 0},
-{6, 1},
-{4, 1},
-{3, 1},
-{2, 3},
-{2, 1},
-{1, 6},
-{1, 5},
-{1, 4},
-{1, 3},
-{1, 2},
-{1, 1},
-{1, 0},
-{0, 13},
-{0, 13},
-{0, 13},
-// numerator = 14
-{-1, -1},
-{-1, 0},
-{-2, -12},
-{-2, -10},
-{-2, -8},
-{-2, -6},
-{-2, -4},
-{-2, -2},
-{-2, 0},
-{-3, -4},
-{-3, -1},
-{-4, -2},
-{-5, -1},
-{-7, 0},
-{-14, 0},
-{0, 0},
-{14, 0},
-{7, 0},
-{4, 2},
-{3, 2},
-{2, 4},
-{2, 2},
-{2, 0},
-{1, 6},
-{1, 5},
-{1, 4},
-{1, 3},
-{1, 2},
-{1, 1},
-{1, 0},
-{0, 14},
-{0, 14},
-// numerator = 15
-{-1, 0},
-{-2, -13},
-{-2, -11},
-{-2, -9},
-{-2, -7},
-{-2, -5},
-{-2, -3},
-{-2, -1},
-{-3, -6},
-{-3, -3},
-{-3, 0},
-{-4, -1},
-{-5, 0},
-{-8, -1},
-{-15, 0},
-{0, 0},
-{15, 0},
-{7, 1},
-{5, 0},
-{3, 3},
-{3, 0},
-{2, 3},
-{2, 1},
-{1, 7},
-{1, 6},
-{1, 5},
-{1, 4},
-{1, 3},
-{1, 2},
-{1, 1},
-{1, 0},
-{0, 15},
-// numerator = 16
-{-2, -14},
-{-2, -12},
-{-2, -10},
-{-2, -8},
-{-2, -6},
-{-2, -4},
-{-2, -2},
-{-2, 0},
-{-3, -5},
-{-3, -2},
-{-4, -4},
-{-4, 0},
-{-6, -2},
-{-8, 0},
-{-16, 0},
-{0, 0},
-{16, 0},
-{8, 0},
-{5, 1},
-{4, 0},
-{3, 1},
-{2, 4},
-{2, 2},
-{2, 0},
-{1, 7},
-{1, 6},
-{1, 5},
-{1, 4},
-{1, 3},
-{1, 2},
-{1, 1},
-{1, 0},
--- a/ref_soft/r_aclip.c
+++ /dev/null
@@ -1,323 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// r_aclip.c: clip routines for drawing Alias models directly to the screen
-
-#include "r_local.h"
-
-static finalvert_t fv[2][8];
-
-void R_AliasProjectAndClipTestFinalVert (finalvert_t *fv);
-void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1,
- finalvert_t *out);
-void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
- finalvert_t *out);
-void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1,
- finalvert_t *out);
-void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
- finalvert_t *out);
-
-
-/*
-================
-R_Alias_clip_z
-
-pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
-================
-*/
-void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
-{
- float scale;
-
- scale = (ALIAS_Z_CLIP_PLANE - pfv0->xyz[2]) /
- (pfv1->xyz[2] - pfv0->xyz[2]);
-
- out->xyz[0] = pfv0->xyz[0] + (pfv1->xyz[0] - pfv0->xyz[0]) * scale;
- out->xyz[1] = pfv0->xyz[1] + (pfv1->xyz[1] - pfv0->xyz[1]) * scale;
- out->xyz[2] = ALIAS_Z_CLIP_PLANE;
-
- out->s = pfv0->s + (pfv1->s - pfv0->s) * scale;
- out->t = pfv0->t + (pfv1->t - pfv0->t) * scale;
- out->l = pfv0->l + (pfv1->l - pfv0->l) * scale;
-
- R_AliasProjectAndClipTestFinalVert (out);
-}
-
-
-#if !id386
-
-void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
-{
- float scale;
-
- if (pfv0->v >= pfv1->v )
- {
- scale = (float)(r_refdef.aliasvrect.x - pfv0->u) /
- (pfv1->u - pfv0->u);
- out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
- out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
- out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
- out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
- out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
- out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
- }
- else
- {
- scale = (float)(r_refdef.aliasvrect.x - pfv1->u) /
- (pfv0->u - pfv1->u);
- out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
- out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
- out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
- out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
- out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
- out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
- }
-}
-
-
-void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
-{
- float scale;
-
- if ( pfv0->v >= pfv1->v )
- {
- scale = (float)(r_refdef.aliasvrectright - pfv0->u ) /
- (pfv1->u - pfv0->u );
- out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
- out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
- out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
- out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
- out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
- out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
- }
- else
- {
- scale = (float)(r_refdef.aliasvrectright - pfv1->u ) /
- (pfv0->u - pfv1->u );
- out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
- out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
- out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
- out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
- out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
- out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
- }
-}
-
-
-void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
-{
- float scale;
-
- if (pfv0->v >= pfv1->v)
- {
- scale = (float)(r_refdef.aliasvrect.y - pfv0->v) /
- (pfv1->v - pfv0->v);
- out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
- out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
- out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
- out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
- out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
- out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
- }
- else
- {
- scale = (float)(r_refdef.aliasvrect.y - pfv1->v) /
- (pfv0->v - pfv1->v);
- out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
- out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
- out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
- out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
- out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
- out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
- }
-}
-
-
-void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
- finalvert_t *out)
-{
- float scale;
-
- if (pfv0->v >= pfv1->v)
- {
- scale = (float)(r_refdef.aliasvrectbottom - pfv0->v) /
- (pfv1->v - pfv0->v);
-
- out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
- out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
- out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
- out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
- out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
- out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
- }
- else
- {
- scale = (float)(r_refdef.aliasvrectbottom - pfv1->v) /
- (pfv0->v - pfv1->v);
-
- out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
- out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
- out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
- out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
- out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
- out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
- }
-}
-
-#endif
-
-
-int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count,
- void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) )
-{
- int i,j,k;
- int flags, oldflags;
-
- j = count-1;
- k = 0;
- for (i=0 ; i<count ; j = i, i++)
- {
- oldflags = in[j].flags & flag;
- flags = in[i].flags & flag;
-
- if (flags && oldflags)
- continue;
- if (oldflags ^ flags)
- {
- clip (&in[j], &in[i], &out[k]);
- out[k].flags = 0;
- if (out[k].u < r_refdef.aliasvrect.x)
- out[k].flags |= ALIAS_LEFT_CLIP;
- if (out[k].v < r_refdef.aliasvrect.y)
- out[k].flags |= ALIAS_TOP_CLIP;
- if (out[k].u > r_refdef.aliasvrectright)
- out[k].flags |= ALIAS_RIGHT_CLIP;
- if (out[k].v > r_refdef.aliasvrectbottom)
- out[k].flags |= ALIAS_BOTTOM_CLIP;
- k++;
- }
- if (!flags)
- {
- out[k] = in[i];
- k++;
- }
- }
-
- return k;
-}
-
-
-/*
-================
-R_AliasClipTriangle
-================
-*/
-void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2)
-{
- int i, k, pingpong;
- unsigned clipflags;
-
-// copy vertexes and fix seam texture coordinates
- fv[0][0] = *index0;
- fv[0][1] = *index1;
- fv[0][2] = *index2;
-
-// clip
- clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
-
- if (clipflags & ALIAS_Z_CLIP)
- {
- k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z);
- if (k == 0)
- return;
-
- pingpong = 1;
- clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags;
- }
- else
- {
- pingpong = 0;
- k = 3;
- }
-
- if (clipflags & ALIAS_LEFT_CLIP)
- {
- k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
- ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
- if (k == 0)
- return;
-
- pingpong ^= 1;
- }
-
- if (clipflags & ALIAS_RIGHT_CLIP)
- {
- k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
- ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
- if (k == 0)
- return;
-
- pingpong ^= 1;
- }
-
- if (clipflags & ALIAS_BOTTOM_CLIP)
- {
- k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
- ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
- if (k == 0)
- return;
-
- pingpong ^= 1;
- }
-
- if (clipflags & ALIAS_TOP_CLIP)
- {
- k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
- ALIAS_TOP_CLIP, k, R_Alias_clip_top);
- if (k == 0)
- return;
-
- pingpong ^= 1;
- }
-
- for (i=0 ; i<k ; i++)
- {
- if (fv[pingpong][i].u < r_refdef.aliasvrect.x)
- fv[pingpong][i].u = r_refdef.aliasvrect.x;
- else if (fv[pingpong][i].u > r_refdef.aliasvrectright)
- fv[pingpong][i].u = r_refdef.aliasvrectright;
-
- if (fv[pingpong][i].v < r_refdef.aliasvrect.y)
- fv[pingpong][i].v = r_refdef.aliasvrect.y;
- else if (fv[pingpong][i].v > r_refdef.aliasvrectbottom)
- fv[pingpong][i].v = r_refdef.aliasvrectbottom;
-
- fv[pingpong][i].flags = 0;
- }
-
-// draw triangles
- for (i=1 ; i<k-1 ; i++)
- {
- aliastriangleparms.a = &fv[pingpong][0];
- aliastriangleparms.b = &fv[pingpong][i];
- aliastriangleparms.c = &fv[pingpong][i+1];
- R_DrawTriangle();
- }
-}
-
--- a/ref_soft/r_alias.c
+++ /dev/null
@@ -1,1198 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// r_alias.c: routines for setting up to draw alias models
-
-/*
-** use a real variable to control lerping
-*/
-#include "r_local.h"
-
-#define LIGHT_MIN 5 // lowest light value we'll allow, to avoid the
- // need for inner-loop light clamping
-
-//PGM
-extern byte iractive;
-//PGM
-
-int r_amodels_drawn;
-
-affinetridesc_t r_affinetridesc;
-
-vec3_t r_plightvec;
-vec3_t r_lerped[1024];
-vec3_t r_lerp_frontv, r_lerp_backv, r_lerp_move;
-
-int r_ambientlight;
-int r_aliasblendcolor;
-float r_shadelight;
-
-
-daliasframe_t *r_thisframe, *r_lastframe;
-dmdl_t *s_pmdl;
-
-float aliastransform[3][4];
-float aliasworldtransform[3][4];
-float aliasoldworldtransform[3][4];
-
-static float s_ziscale;
-static vec3_t s_alias_forward, s_alias_right, s_alias_up;
-
-
-#define NUMVERTEXNORMALS 162
-
-float r_avertexnormals[NUMVERTEXNORMALS][3] = {
-#include "../anorms.h"
-};
-
-
-void R_AliasSetUpLerpData( dmdl_t *pmdl, float backlerp );
-void R_AliasSetUpTransform (void);
-void R_AliasTransformVector (vec3_t in, vec3_t out, float m[3][4] );
-void R_AliasProjectAndClipTestFinalVert (finalvert_t *fv);
-
-void R_AliasTransformFinalVerts( int numpoints, finalvert_t *fv, dtrivertx_t *oldv, dtrivertx_t *newv );
-
-void R_AliasLerpFrames( dmdl_t *paliashdr, float backlerp );
-
-/*
-================
-R_AliasCheckBBox
-================
-*/
-typedef struct {
- int index0;
- int index1;
-} aedge_t;
-
-static aedge_t aedges[12] = {
-{0, 1}, {1, 2}, {2, 3}, {3, 0},
-{4, 5}, {5, 6}, {6, 7}, {7, 4},
-{0, 5}, {1, 4}, {2, 7}, {3, 6}
-};
-
-#define BBOX_TRIVIAL_ACCEPT 0
-#define BBOX_MUST_CLIP_XY 1
-#define BBOX_MUST_CLIP_Z 2
-#define BBOX_TRIVIAL_REJECT 8
-
-/*
-** R_AliasCheckFrameBBox
-**
-** Checks a specific alias frame bounding box
-*/
-unsigned long R_AliasCheckFrameBBox( daliasframe_t *frame, float worldxf[3][4] )
-{
- unsigned long aggregate_and_clipcode = ~0U,
- aggregate_or_clipcode = 0;
- int i;
- vec3_t mins, maxs;
- vec3_t transformed_min, transformed_max;
- qboolean zclipped = false, zfullyclipped = true;
- float minz = 9999.0F;
-
- /*
- ** get the exact frame bounding box
- */
- for (i=0 ; i<3 ; i++)
- {
- mins[i] = frame->translate[i];
- maxs[i] = mins[i] + frame->scale[i]*255;
- }
-
- /*
- ** transform the min and max values into view space
- */
- R_AliasTransformVector( mins, transformed_min, aliastransform );
- R_AliasTransformVector( maxs, transformed_max, aliastransform );
-
- if ( transformed_min[2] >= ALIAS_Z_CLIP_PLANE )
- zfullyclipped = false;
- if ( transformed_max[2] >= ALIAS_Z_CLIP_PLANE )
- zfullyclipped = false;
-
- if ( zfullyclipped )
- {
- return BBOX_TRIVIAL_REJECT;
- }
- if ( zclipped )
- {
- return ( BBOX_MUST_CLIP_XY | BBOX_MUST_CLIP_Z );
- }
-
- /*
- ** build a transformed bounding box from the given min and max
- */
- for ( i = 0; i < 8; i++ )
- {
- int j;
- vec3_t tmp, transformed;
- unsigned long clipcode = 0;
-
- if ( i & 1 )
- tmp[0] = mins[0];
- else
- tmp[0] = maxs[0];
-
- if ( i & 2 )
- tmp[1] = mins[1];
- else
- tmp[1] = maxs[1];
-
- if ( i & 4 )
- tmp[2] = mins[2];
- else
- tmp[2] = maxs[2];
-
- R_AliasTransformVector( tmp, transformed, worldxf );
-
- for ( j = 0; j < 4; j++ )
- {
- float dp = DotProduct( transformed, view_clipplanes[j].normal );
-
- if ( ( dp - view_clipplanes[j].dist ) < 0.0F )
- clipcode |= 1 << j;
- }
-
- aggregate_and_clipcode &= clipcode;
- aggregate_or_clipcode |= clipcode;
- }
-
- if ( aggregate_and_clipcode )
- {
- return BBOX_TRIVIAL_REJECT;
- }
- if ( !aggregate_or_clipcode )
- {
- return BBOX_TRIVIAL_ACCEPT;
- }
-
- return BBOX_MUST_CLIP_XY;
-}
-
-qboolean R_AliasCheckBBox (void)
-{
- unsigned long ccodes[2] = { 0, 0 };
-
- ccodes[0] = R_AliasCheckFrameBBox( r_thisframe, aliasworldtransform );
-
- /*
- ** non-lerping model
- */
- if ( currententity->backlerp == 0 )
- {
- if ( ccodes[0] == BBOX_TRIVIAL_ACCEPT )
- return BBOX_TRIVIAL_ACCEPT;
- else if ( ccodes[0] & BBOX_TRIVIAL_REJECT )
- return BBOX_TRIVIAL_REJECT;
- else
- return ( ccodes[0] & ~BBOX_TRIVIAL_REJECT );
- }
-
- ccodes[1] = R_AliasCheckFrameBBox( r_lastframe, aliasoldworldtransform );
-
- if ( ( ccodes[0] | ccodes[1] ) == BBOX_TRIVIAL_ACCEPT )
- return BBOX_TRIVIAL_ACCEPT;
- else if ( ( ccodes[0] & ccodes[1] ) & BBOX_TRIVIAL_REJECT )
- return BBOX_TRIVIAL_REJECT;
- else
- return ( ccodes[0] | ccodes[1] ) & ~BBOX_TRIVIAL_REJECT;
-}
-
-
-/*
-================
-R_AliasTransformVector
-================
-*/
-void R_AliasTransformVector(vec3_t in, vec3_t out, float xf[3][4] )
-{
- out[0] = DotProduct(in, xf[0]) + xf[0][3];
- out[1] = DotProduct(in, xf[1]) + xf[1][3];
- out[2] = DotProduct(in, xf[2]) + xf[2][3];
-}
-
-
-/*
-================
-R_AliasPreparePoints
-
-General clipped case
-================
-*/
-typedef struct
-{
- int num_points;
- dtrivertx_t *last_verts; // verts from the last frame
- dtrivertx_t *this_verts; // verts from this frame
- finalvert_t *dest_verts; // destination for transformed verts
-} aliasbatchedtransformdata_t;
-
-aliasbatchedtransformdata_t aliasbatchedtransformdata;
-
-void R_AliasPreparePoints (void)
-{
- int i;
- dstvert_t *pstverts;
- dtriangle_t *ptri;
- finalvert_t *pfv[3];
- finalvert_t finalverts[MAXALIASVERTS +
- ((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 3];
- finalvert_t *pfinalverts;
-
-//PGM
- iractive = (r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE);
-// iractive = 0;
-// if(r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
-// iractive = 1;
-//PGM
-
- // put work vertexes on stack, cache aligned
- pfinalverts = (finalvert_t *)
- (((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
-
- aliasbatchedtransformdata.num_points = s_pmdl->num_xyz;
- aliasbatchedtransformdata.last_verts = r_lastframe->verts;
- aliasbatchedtransformdata.this_verts = r_thisframe->verts;
- aliasbatchedtransformdata.dest_verts = pfinalverts;
-
- R_AliasTransformFinalVerts( aliasbatchedtransformdata.num_points,
- aliasbatchedtransformdata.dest_verts,
- aliasbatchedtransformdata.last_verts,
- aliasbatchedtransformdata.this_verts );
-
-// clip and draw all triangles
-//
- pstverts = (dstvert_t *)((byte *)s_pmdl + s_pmdl->ofs_st);
- ptri = (dtriangle_t *)((byte *)s_pmdl + s_pmdl->ofs_tris);
-
- if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
- {
- for (i=0 ; i<s_pmdl->num_tris ; i++, ptri++)
- {
- pfv[0] = &pfinalverts[ptri->index_xyz[0]];
- pfv[1] = &pfinalverts[ptri->index_xyz[1]];
- pfv[2] = &pfinalverts[ptri->index_xyz[2]];
-
- if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags )
- continue; // completely clipped
-
- // insert s/t coordinates
- pfv[0]->s = pstverts[ptri->index_st[0]].s << 16;
- pfv[0]->t = pstverts[ptri->index_st[0]].t << 16;
-
- pfv[1]->s = pstverts[ptri->index_st[1]].s << 16;
- pfv[1]->t = pstverts[ptri->index_st[1]].t << 16;
-
- pfv[2]->s = pstverts[ptri->index_st[2]].s << 16;
- pfv[2]->t = pstverts[ptri->index_st[2]].t << 16;
-
- if ( ! (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) )
- { // totally unclipped
- aliastriangleparms.a = pfv[2];
- aliastriangleparms.b = pfv[1];
- aliastriangleparms.c = pfv[0];
-
- R_DrawTriangle();
- }
- else
- {
- R_AliasClipTriangle (pfv[2], pfv[1], pfv[0]);
- }
- }
- }
- else
- {
- for (i=0 ; i<s_pmdl->num_tris ; i++, ptri++)
- {
- pfv[0] = &pfinalverts[ptri->index_xyz[0]];
- pfv[1] = &pfinalverts[ptri->index_xyz[1]];
- pfv[2] = &pfinalverts[ptri->index_xyz[2]];
-
- if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags )
- continue; // completely clipped
-
- // insert s/t coordinates
- pfv[0]->s = pstverts[ptri->index_st[0]].s << 16;
- pfv[0]->t = pstverts[ptri->index_st[0]].t << 16;
-
- pfv[1]->s = pstverts[ptri->index_st[1]].s << 16;
- pfv[1]->t = pstverts[ptri->index_st[1]].t << 16;
-
- pfv[2]->s = pstverts[ptri->index_st[2]].s << 16;
- pfv[2]->t = pstverts[ptri->index_st[2]].t << 16;
-
- if ( ! (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) )
- { // totally unclipped
- aliastriangleparms.a = pfv[0];
- aliastriangleparms.b = pfv[1];
- aliastriangleparms.c = pfv[2];
-
- R_DrawTriangle();
- }
- else
- { // partially clipped
- R_AliasClipTriangle (pfv[0], pfv[1], pfv[2]);
- }
- }
- }
-}
-
-
-/*
-================
-R_AliasSetUpTransform
-================
-*/
-void R_AliasSetUpTransform (void)
-{
- int i;
- static float viewmatrix[3][4];
- vec3_t angles;
-
-// TODO: should really be stored with the entity instead of being reconstructed
-// TODO: should use a look-up table
-// TODO: could cache lazily, stored in the entity
-//
- angles[ROLL] = currententity->angles[ROLL];
- angles[PITCH] = currententity->angles[PITCH];
- angles[YAW] = currententity->angles[YAW];
- AngleVectors( angles, s_alias_forward, s_alias_right, s_alias_up );
-
-// TODO: can do this with simple matrix rearrangement
-
- memset( aliasworldtransform, 0, sizeof( aliasworldtransform ) );
- memset( aliasoldworldtransform, 0, sizeof( aliasworldtransform ) );
-
- for (i=0 ; i<3 ; i++)
- {
- aliasoldworldtransform[i][0] = aliasworldtransform[i][0] = s_alias_forward[i];
- aliasoldworldtransform[i][0] = aliasworldtransform[i][1] = -s_alias_right[i];
- aliasoldworldtransform[i][0] = aliasworldtransform[i][2] = s_alias_up[i];
- }
-
- aliasworldtransform[0][3] = currententity->origin[0]-r_origin[0];
- aliasworldtransform[1][3] = currententity->origin[1]-r_origin[1];
- aliasworldtransform[2][3] = currententity->origin[2]-r_origin[2];
-
- aliasoldworldtransform[0][3] = currententity->oldorigin[0]-r_origin[0];
- aliasoldworldtransform[1][3] = currententity->oldorigin[1]-r_origin[1];
- aliasoldworldtransform[2][3] = currententity->oldorigin[2]-r_origin[2];
-
-// FIXME: can do more efficiently than full concatenation
-// memcpy( rotationmatrix, t2matrix, sizeof( rotationmatrix ) );
-
-// R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix);
-
-// TODO: should be global, set when vright, etc., set
- VectorCopy (vright, viewmatrix[0]);
- VectorCopy (vup, viewmatrix[1]);
- VectorInverse (viewmatrix[1]);
- VectorCopy (vpn, viewmatrix[2]);
-
- viewmatrix[0][3] = 0;
- viewmatrix[1][3] = 0;
- viewmatrix[2][3] = 0;
-
-// memcpy( aliasworldtransform, rotationmatrix, sizeof( aliastransform ) );
-
- R_ConcatTransforms (viewmatrix, aliasworldtransform, aliastransform);
-
- aliasworldtransform[0][3] = currententity->origin[0];
- aliasworldtransform[1][3] = currententity->origin[1];
- aliasworldtransform[2][3] = currententity->origin[2];
-
- aliasoldworldtransform[0][3] = currententity->oldorigin[0];
- aliasoldworldtransform[1][3] = currententity->oldorigin[1];
- aliasoldworldtransform[2][3] = currententity->oldorigin[2];
-}
-
-
-/*
-================
-R_AliasTransformFinalVerts
-================
-*/
-#if id386 && !defined __linux__
-void R_AliasTransformFinalVerts( int numpoints, finalvert_t *fv, dtrivertx_t *oldv, dtrivertx_t *newv )
-{
- float lightcos;
- float lerped_vert[3];
- int byte_to_dword_ptr_var;
- int tmpint;
-
- float one = 1.0F;
- float zi;
-
- static float FALIAS_Z_CLIP_PLANE = ALIAS_Z_CLIP_PLANE;
- static float PS_SCALE = POWERSUIT_SCALE;
-
- __asm mov ecx, numpoints
-
- /*
- lerped_vert[0] = r_lerp_move[0] + oldv->v[0]*r_lerp_backv[0] + newv->v[0]*r_lerp_frontv[0];
- lerped_vert[1] = r_lerp_move[1] + oldv->v[1]*r_lerp_backv[1] + newv->v[1]*r_lerp_frontv[1];
- lerped_vert[2] = r_lerp_move[2] + oldv->v[2]*r_lerp_backv[2] + newv->v[2]*r_lerp_frontv[2];
- */
-top_of_loop:
-
- __asm mov esi, oldv
- __asm mov edi, newv
-
- __asm xor ebx, ebx
-
- __asm mov bl, byte ptr [esi+DTRIVERTX_V0]
- __asm mov byte_to_dword_ptr_var, ebx
- __asm fild dword ptr byte_to_dword_ptr_var
- __asm fmul dword ptr [r_lerp_backv+0] ; oldv[0]*rlb[0]
-
- __asm mov bl, byte ptr [esi+DTRIVERTX_V1]
- __asm mov byte_to_dword_ptr_var, ebx
- __asm fild dword ptr byte_to_dword_ptr_var
- __asm fmul dword ptr [r_lerp_backv+4] ; oldv[1]*rlb[1] | oldv[0]*rlb[0]
-
- __asm mov bl, byte ptr [esi+DTRIVERTX_V2]
- __asm mov byte_to_dword_ptr_var, ebx
- __asm fild dword ptr byte_to_dword_ptr_var
- __asm fmul dword ptr [r_lerp_backv+8] ; oldv[2]*rlb[2] | oldv[1]*rlb[1] | oldv[0]*rlb[0]
-
- __asm mov bl, byte ptr [edi+DTRIVERTX_V0]
- __asm mov byte_to_dword_ptr_var, ebx
- __asm fild dword ptr byte_to_dword_ptr_var
- __asm fmul dword ptr [r_lerp_frontv+0] ; newv[0]*rlf[0] | oldv[2]*rlb[2] | oldv[1]*rlb[1] | oldv[0]*rlb[0]
-
- __asm mov bl, byte ptr [edi+DTRIVERTX_V1]
- __asm mov byte_to_dword_ptr_var, ebx
- __asm fild dword ptr byte_to_dword_ptr_var
- __asm fmul dword ptr [r_lerp_frontv+4] ; newv[1]*rlf[1] | newv[0]*rlf[0] | oldv[2]*rlb[2] | oldv[1]*rlb[1] | oldv[0]*rlb[0]
-
- __asm mov bl, byte ptr [edi+DTRIVERTX_V2]
- __asm mov byte_to_dword_ptr_var, ebx
- __asm fild dword ptr byte_to_dword_ptr_var
- __asm fmul dword ptr [r_lerp_frontv+8] ; newv[2]*rlf[2] | newv[1]*rlf[1] | newv[0]*rlf[0] | oldv[2]*rlb[2] | oldv[1]*rlb[1] | oldv[0]*rlb[0]
-
- __asm fxch st(5) ; oldv[0]*rlb[0] | newv[1]*rlf[1] | newv[0]*rlf[0] | oldv[2]*rlb[2] | oldv[1]*rlb[1] | newv[2]*rlf[2]
- __asm faddp st(2), st ; newv[1]*rlf[1] | oldv[0]*rlb[0] + newv[0]*rlf[0] | oldv[2]*rlb[2] | oldv[1]*rlb[1] | newv[2]*rlf[2]
- __asm faddp st(3), st ; oldv[0]*rlb[0] + newv[0]*rlf[0] | oldv[2]*rlb[2] | oldv[1]*rlb[1] + newv[1]*rlf[1] | newv[2]*rlf[2]
- __asm fxch st(1) ; oldv[2]*rlb[2] | oldv[0]*rlb[0] + newv[0]*rlf[0] | oldv[1]*rlb[1] + newv[1]*rlf[1] | newv[2]*rlf[2]
- __asm faddp st(3), st ; oldv[0]*rlb[0] + newv[0]*rlf[0] | oldv[1]*rlb[1] + newv[1]*rlf[1] | oldv[2]*rlb[2] + newv[2]*rlf[2]
- __asm fadd dword ptr [r_lerp_move+0] ; lv0 | oldv[1]*rlb[1] + newv[1]*rlf[1] | oldv[2]*rlb[2] + newv[2]*rlf[2]
- __asm fxch st(1) ; oldv[1]*rlb[1] + newv[1]*rlf[1] | lv0 | oldv[2]*rlb[2] + newv[2]*rlf[2]
- __asm fadd dword ptr [r_lerp_move+4] ; lv1 | lv0 | oldv[2]*rlb[2] + newv[2]*rlf[2]
- __asm fxch st(2) ; oldv[2]*rlb[2] + newv[2]*rlf[2] | lv0 | lv1
- __asm fadd dword ptr [r_lerp_move+8] ; lv2 | lv0 | lv1
- __asm fxch st(1) ; lv0 | lv2 | lv1
- __asm fstp dword ptr [lerped_vert+0] ; lv2 | lv1
- __asm fstp dword ptr [lerped_vert+8] ; lv2
- __asm fstp dword ptr [lerped_vert+4] ; (empty)
-
- __asm mov eax, currententity
- __asm mov eax, dword ptr [eax+ENTITY_FLAGS]
- __asm mov ebx, RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM
- __asm and eax, ebx
- __asm jz not_powersuit
-
- /*
- ** lerped_vert[0] += lightnormal[0] * POWERSUIT_SCALE
- ** lerped_vert[1] += lightnormal[1] * POWERSUIT_SCALE
- ** lerped_vert[2] += lightnormal[2] * POWERSUIT_SCALE
- */
-
- __asm xor ebx, ebx
- __asm mov bl, byte ptr [edi+DTRIVERTX_LNI]
- __asm mov eax, 12
- __asm mul ebx
- __asm lea eax, [r_avertexnormals+eax]
-
- __asm fld dword ptr [eax+0] ; n[0]
- __asm fmul PS_SCALE ; n[0] * PS
- __asm fld dword ptr [eax+4] ; n[1] | n[0] * PS
- __asm fmul PS_SCALE ; n[1] * PS | n[0] * PS
- __asm fld dword ptr [eax+8] ; n[2] | n[1] * PS | n[0] * PS
- __asm fmul PS_SCALE ; n[2] * PS | n[1] * PS | n[0] * PS
- __asm fld dword ptr [lerped_vert+0] ; lv0 | n[2] * PS | n[1] * PS | n[0] * PS
- __asm faddp st(3), st ; n[2] * PS | n[1] * PS | n[0] * PS + lv0
- __asm fld dword ptr [lerped_vert+4] ; lv1 | n[2] * PS | n[1] * PS | n[0] * PS + lv0
- __asm faddp st(2), st ; n[2] * PS | n[1] * PS + lv1 | n[0] * PS + lv0
- __asm fadd dword ptr [lerped_vert+8] ; n[2] * PS + lv2 | n[1] * PS + lv1 | n[0] * PS + lv0
- __asm fxch st(2) ; LV0 | LV1 | LV2
- __asm fstp dword ptr [lerped_vert+0] ; LV1 | LV2
- __asm fstp dword ptr [lerped_vert+4] ; LV2
- __asm fstp dword ptr [lerped_vert+8] ; (empty)
-
-not_powersuit:
-
- /*
- fv->flags = 0;
-
- fv->xyz[0] = DotProduct(lerped_vert, aliastransform[0]) + aliastransform[0][3];
- fv->xyz[1] = DotProduct(lerped_vert, aliastransform[1]) + aliastransform[1][3];
- fv->xyz[2] = DotProduct(lerped_vert, aliastransform[2]) + aliastransform[2][3];
- */
- __asm mov eax, fv
- __asm mov dword ptr [eax+FINALVERT_FLAGS], 0
-
- __asm fld dword ptr [lerped_vert+0] ; lv0
- __asm fmul dword ptr [aliastransform+0] ; lv0*at[0][0]
- __asm fld dword ptr [lerped_vert+4] ; lv1 | lv0*at[0][0]
- __asm fmul dword ptr [aliastransform+4] ; lv1*at[0][1] | lv0*at[0][0]
- __asm fld dword ptr [lerped_vert+8] ; lv2 | lv1*at[0][1] | lv0*at[0][0]
- __asm fmul dword ptr [aliastransform+8] ; lv2*at[0][2] | lv1*at[0][1] | lv0*at[0][0]
- __asm fxch st(2) ; lv0*at[0][0] | lv1*at[0][1] | lv2*at[0][2]
- __asm faddp st(1), st ; lv0*at[0][0] + lv1*at[0][1] | lv2*at[0][2]
- __asm faddp st(1), st ; lv0*at[0][0] + lv1*at[0][1] + lv2*at[0][2]
- __asm fadd dword ptr [aliastransform+12] ; FV.X
-
- __asm fld dword ptr [lerped_vert+0] ; lv0
- __asm fmul dword ptr [aliastransform+16] ; lv0*at[1][0]
- __asm fld dword ptr [lerped_vert+4] ; lv1 | lv0*at[1][0]
- __asm fmul dword ptr [aliastransform+20] ; lv1*at[1][1] | lv0*at[1][0]
- __asm fld dword ptr [lerped_vert+8] ; lv2 | lv1*at[1][1] | lv0*at[1][0]
- __asm fmul dword ptr [aliastransform+24] ; lv2*at[1][2] | lv1*at[1][1] | lv0*at[1][0]
- __asm fxch st(2) ; lv0*at[1][0] | lv1*at[1][1] | lv2*at[1][2]
- __asm faddp st(1), st ; lv0*at[1][0] + lv1*at[1][1] | lv2*at[1][2]
- __asm faddp st(1), st ; lv0*at[1][0] + lv1*at[1][1] + lv2*at[1][2]
- __asm fadd dword ptr [aliastransform+28] ; FV.Y | FV.X
- __asm fxch st(1) ; FV.X | FV.Y
- __asm fstp dword ptr [eax+FINALVERT_X] ; FV.Y
-
- __asm fld dword ptr [lerped_vert+0] ; lv0
- __asm fmul dword ptr [aliastransform+32] ; lv0*at[2][0]
- __asm fld dword ptr [lerped_vert+4] ; lv1 | lv0*at[2][0]
- __asm fmul dword ptr [aliastransform+36] ; lv1*at[2][1] | lv0*at[2][0]
- __asm fld dword ptr [lerped_vert+8] ; lv2 | lv1*at[2][1] | lv0*at[2][0]
- __asm fmul dword ptr [aliastransform+40] ; lv2*at[2][2] | lv1*at[2][1] | lv0*at[2][0]
- __asm fxch st(2) ; lv0*at[2][0] | lv1*at[2][1] | lv2*at[2][2]
- __asm faddp st(1), st ; lv0*at[2][0] + lv1*at[2][1] | lv2*at[2][2]
- __asm faddp st(1), st ; lv0*at[2][0] + lv1*at[2][1] + lv2*at[2][2]
- __asm fadd dword ptr [aliastransform+44] ; FV.Z | FV.Y
- __asm fxch st(1) ; FV.Y | FV.Z
- __asm fstp dword ptr [eax+FINALVERT_Y] ; FV.Z
- __asm fstp dword ptr [eax+FINALVERT_Z] ; (empty)
-
- /*
- ** lighting
- **
- ** plightnormal = r_avertexnormals[newv->lightnormalindex];
- ** lightcos = DotProduct (plightnormal, r_plightvec);
- ** temp = r_ambientlight;
- */
- __asm xor ebx, ebx
- __asm mov bl, byte ptr [edi+DTRIVERTX_LNI]
- __asm mov eax, 12
- __asm mul ebx
- __asm lea eax, [r_avertexnormals+eax]
- __asm lea ebx, r_plightvec
-
- __asm fld dword ptr [eax+0]
- __asm fmul dword ptr [ebx+0]
- __asm fld dword ptr [eax+4]
- __asm fmul dword ptr [ebx+4]
- __asm fld dword ptr [eax+8]
- __asm fmul dword ptr [ebx+8]
- __asm fxch st(2)
- __asm faddp st(1), st
- __asm faddp st(1), st
- __asm fstp dword ptr lightcos
- __asm mov eax, lightcos
- __asm mov ebx, r_ambientlight
-
- /*
- if (lightcos < 0)
- {
- temp += (int)(r_shadelight * lightcos);
-
- // clamp; because we limited the minimum ambient and shading light, we
- // don't have to clamp low light, just bright
- if (temp < 0)
- temp = 0;
- }
-
- fv->v[4] = temp;
- */
- __asm or eax, eax
- __asm jns store_fv4
-
- __asm fld dword ptr r_shadelight
- __asm fmul dword ptr lightcos
- __asm fistp dword ptr tmpint
- __asm add ebx, tmpint
-
- __asm or ebx, ebx
- __asm jns store_fv4
- __asm mov ebx, 0
-
-store_fv4:
- __asm mov edi, fv
- __asm mov dword ptr [edi+FINALVERT_V4], ebx
-
- __asm mov edx, dword ptr [edi+FINALVERT_FLAGS]
-
- /*
- ** do clip testing and projection here
- */
- /*
- if ( dest_vert->xyz[2] < ALIAS_Z_CLIP_PLANE )
- {
- dest_vert->flags |= ALIAS_Z_CLIP;
- }
- else
- {
- R_AliasProjectAndClipTestFinalVert( dest_vert );
- }
- */
- __asm mov eax, dword ptr [edi+FINALVERT_Z]
- __asm and eax, eax
- __asm js alias_z_clip
- __asm cmp eax, FALIAS_Z_CLIP_PLANE
- __asm jl alias_z_clip
-
- /*
- This is the code to R_AliasProjectAndClipTestFinalVert
-
- float zi;
- float x, y, z;
-
- x = fv->xyz[0];
- y = fv->xyz[1];
- z = fv->xyz[2];
- zi = 1.0 / z;
-
- fv->v[5] = zi * s_ziscale;
-
- fv->v[0] = (x * aliasxscale * zi) + aliasxcenter;
- fv->v[1] = (y * aliasyscale * zi) + aliasycenter;
- */
- __asm fld one ; 1
- __asm fdiv dword ptr [edi+FINALVERT_Z] ; zi
-
- __asm mov eax, dword ptr [edi+32]
- __asm mov eax, dword ptr [edi+64]
-
- __asm fst zi ; zi
- __asm fmul s_ziscale ; fv5
- __asm fld dword ptr [edi+FINALVERT_X] ; x | fv5
- __asm fmul aliasxscale ; x * aliasxscale | fv5
- __asm fld dword ptr [edi+FINALVERT_Y] ; y | x * aliasxscale | fv5
- __asm fmul aliasyscale ; y * aliasyscale | x * aliasxscale | fv5
- __asm fxch st(1) ; x * aliasxscale | y * aliasyscale | fv5
- __asm fmul zi ; x * asx * zi | y * asy | fv5
- __asm fadd aliasxcenter ; fv0 | y * asy | fv5
- __asm fxch st(1) ; y * asy | fv0 | fv5
- __asm fmul zi ; y * asy * zi | fv0 | fv5
- __asm fadd aliasycenter ; fv1 | fv0 | fv5
- __asm fxch st(2) ; fv5 | fv0 | fv1
- __asm fistp dword ptr [edi+FINALVERT_V5] ; fv0 | fv1
- __asm fistp dword ptr [edi+FINALVERT_V0] ; fv1
- __asm fistp dword ptr [edi+FINALVERT_V1] ; (empty)
-
- /*
- if (fv->v[0] < r_refdef.aliasvrect.x)
- fv->flags |= ALIAS_LEFT_CLIP;
- if (fv->v[1] < r_refdef.aliasvrect.y)
- fv->flags |= ALIAS_TOP_CLIP;
- if (fv->v[0] > r_refdef.aliasvrectright)
- fv->flags |= ALIAS_RIGHT_CLIP;
- if (fv->v[1] > r_refdef.aliasvrectbottom)
- fv->flags |= ALIAS_BOTTOM_CLIP;
- */
- __asm mov eax, dword ptr [edi+FINALVERT_V0]
- __asm mov ebx, dword ptr [edi+FINALVERT_V1]
-
- __asm cmp eax, r_refdef.aliasvrect.x
- __asm jge ct_alias_top
- __asm or edx, ALIAS_LEFT_CLIP
-ct_alias_top:
- __asm cmp ebx, r_refdef.aliasvrect.y
- __asm jge ct_alias_right
- __asm or edx, ALIAS_TOP_CLIP
-ct_alias_right:
- __asm cmp eax, r_refdef.aliasvrectright
- __asm jle ct_alias_bottom
- __asm or edx, ALIAS_RIGHT_CLIP
-ct_alias_bottom:
- __asm cmp ebx, r_refdef.aliasvrectbottom
- __asm jle end_of_loop
- __asm or edx, ALIAS_BOTTOM_CLIP
-
- __asm jmp end_of_loop
-
-alias_z_clip:
- __asm or edx, ALIAS_Z_CLIP
-
-end_of_loop:
-
- __asm mov dword ptr [edi+FINALVERT_FLAGS], edx
- __asm add oldv, DTRIVERTX_SIZE
- __asm add newv, DTRIVERTX_SIZE
- __asm add fv, FINALVERT_SIZE
-
- __asm dec ecx
- __asm jnz top_of_loop
-}
-#else
-void R_AliasTransformFinalVerts( int numpoints, finalvert_t *fv, dtrivertx_t *oldv, dtrivertx_t *newv )
-{
- int i;
-
- for ( i = 0; i < numpoints; i++, fv++, oldv++, newv++ )
- {
- int temp;
- float lightcos, *plightnormal;
- vec3_t lerped_vert;
-
- lerped_vert[0] = r_lerp_move[0] + oldv->v[0]*r_lerp_backv[0] + newv->v[0]*r_lerp_frontv[0];
- lerped_vert[1] = r_lerp_move[1] + oldv->v[1]*r_lerp_backv[1] + newv->v[1]*r_lerp_frontv[1];
- lerped_vert[2] = r_lerp_move[2] + oldv->v[2]*r_lerp_backv[2] + newv->v[2]*r_lerp_frontv[2];
-
- plightnormal = r_avertexnormals[newv->lightnormalindex];
-
- // PMM - added double damage shell
- if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
- {
- lerped_vert[0] += plightnormal[0] * POWERSUIT_SCALE;
- lerped_vert[1] += plightnormal[1] * POWERSUIT_SCALE;
- lerped_vert[2] += plightnormal[2] * POWERSUIT_SCALE;
- }
-
- fv->xyz[0] = DotProduct(lerped_vert, aliastransform[0]) + aliastransform[0][3];
- fv->xyz[1] = DotProduct(lerped_vert, aliastransform[1]) + aliastransform[1][3];
- fv->xyz[2] = DotProduct(lerped_vert, aliastransform[2]) + aliastransform[2][3];
-
- fv->flags = 0;
-
- // lighting
- lightcos = DotProduct (plightnormal, r_plightvec);
- temp = r_ambientlight;
-
- if (lightcos < 0)
- {
- temp += (int)(r_shadelight * lightcos);
-
- // clamp; because we limited the minimum ambient and shading light, we
- // don't have to clamp low light, just bright
- if (temp < 0)
- temp = 0;
- }
-
- fv->l = temp;
-
- if ( fv->xyz[2] < ALIAS_Z_CLIP_PLANE )
- {
- fv->flags |= ALIAS_Z_CLIP;
- }
- else
- {
- R_AliasProjectAndClipTestFinalVert( fv );
- }
- }
-}
-
-#endif
-
-/*
-================
-R_AliasProjectAndClipTestFinalVert
-================
-*/
-void R_AliasProjectAndClipTestFinalVert( finalvert_t *fv )
-{
- float zi;
- float x, y, z;
-
- // project points
- x = fv->xyz[0];
- y = fv->xyz[1];
- z = fv->xyz[2];
- zi = 1.0 / z;
-
- fv->zi = zi * s_ziscale;
-
- fv->u = (x * aliasxscale * zi) + aliasxcenter;
- fv->v = (y * aliasyscale * zi) + aliasycenter;
-
- if (fv->u < r_refdef.aliasvrect.x)
- fv->flags |= ALIAS_LEFT_CLIP;
- if (fv->v < r_refdef.aliasvrect.y)
- fv->flags |= ALIAS_TOP_CLIP;
- if (fv->u > r_refdef.aliasvrectright)
- fv->flags |= ALIAS_RIGHT_CLIP;
- if (fv->v > r_refdef.aliasvrectbottom)
- fv->flags |= ALIAS_BOTTOM_CLIP;
-}
-
-/*
-===============
-R_AliasSetupSkin
-===============
-*/
-static qboolean R_AliasSetupSkin (void)
-{
- int skinnum;
- image_t *pskindesc;
-
- if (currententity->skin)
- pskindesc = currententity->skin;
- else
- {
- skinnum = currententity->skinnum;
- if ((skinnum >= s_pmdl->num_skins) || (skinnum < 0))
- {
- ri.Con_Printf (PRINT_ALL, "R_AliasSetupSkin %s: no such skin # %d\n",
- currentmodel->name, skinnum);
- skinnum = 0;
- }
-
- pskindesc = currentmodel->skins[skinnum];
- }
-
- if ( !pskindesc )
- return false;
-
- r_affinetridesc.pskin = pskindesc->pixels[0];
- r_affinetridesc.skinwidth = pskindesc->width;
- r_affinetridesc.skinheight = pskindesc->height;
-
- R_PolysetUpdateTables (); // FIXME: precalc edge lookups
-
- return true;
-}
-
-
-/*
-================
-R_AliasSetupLighting
-
- FIXME: put lighting into tables
-================
-*/
-void R_AliasSetupLighting (void)
-{
- alight_t lighting;
- float lightvec[3] = {-1, 0, 0};
- vec3_t light;
- int i, j;
-
- // all components of light should be identical in software
- if ( currententity->flags & RF_FULLBRIGHT )
- {
- for (i=0 ; i<3 ; i++)
- light[i] = 1.0;
- }
- else
- {
- R_LightPoint (currententity->origin, light);
- }
-
- // save off light value for server to look at (BIG HACK!)
- if ( currententity->flags & RF_WEAPONMODEL )
- r_lightlevel->value = 150.0 * light[0];
-
-
- if ( currententity->flags & RF_MINLIGHT )
- {
- for (i=0 ; i<3 ; i++)
- if (light[i] < 0.1)
- light[i] = 0.1;
- }
-
- if ( currententity->flags & RF_GLOW )
- { // bonus items will pulse with time
- float scale;
- float min;
-
- scale = 0.1 * sin(r_newrefdef.time*7);
- for (i=0 ; i<3 ; i++)
- {
- min = light[i] * 0.8;
- light[i] += scale;
- if (light[i] < min)
- light[i] = min;
- }
- }
-
- j = (light[0] + light[1] + light[2])*0.3333*255;
-
- lighting.ambientlight = j;
- lighting.shadelight = j;
-
- lighting.plightvec = lightvec;
-
-// clamp lighting so it doesn't overbright as much
- if (lighting.ambientlight > 128)
- lighting.ambientlight = 128;
- if (lighting.ambientlight + lighting.shadelight > 192)
- lighting.shadelight = 192 - lighting.ambientlight;
-
-// guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have
-// to clamp off the bottom
- r_ambientlight = lighting.ambientlight;
-
- if (r_ambientlight < LIGHT_MIN)
- r_ambientlight = LIGHT_MIN;
-
- r_ambientlight = (255 - r_ambientlight) << VID_CBITS;
-
- if (r_ambientlight < LIGHT_MIN)
- r_ambientlight = LIGHT_MIN;
-
- r_shadelight = lighting.shadelight;
-
- if (r_shadelight < 0)
- r_shadelight = 0;
-
- r_shadelight *= VID_GRADES;
-
-// rotate the lighting vector into the model's frame of reference
- r_plightvec[0] = DotProduct( lighting.plightvec, s_alias_forward );
- r_plightvec[1] = -DotProduct( lighting.plightvec, s_alias_right );
- r_plightvec[2] = DotProduct( lighting.plightvec, s_alias_up );
-}
-
-
-/*
-=================
-R_AliasSetupFrames
-
-=================
-*/
-void R_AliasSetupFrames( dmdl_t *pmdl )
-{
- int thisframe = currententity->frame;
- int lastframe = currententity->oldframe;
-
- if ( ( thisframe >= pmdl->num_frames ) || ( thisframe < 0 ) )
- {
- ri.Con_Printf (PRINT_ALL, "R_AliasSetupFrames %s: no such thisframe %d\n",
- currentmodel->name, thisframe);
- thisframe = 0;
- }
- if ( ( lastframe >= pmdl->num_frames ) || ( lastframe < 0 ) )
- {
- ri.Con_Printf (PRINT_ALL, "R_AliasSetupFrames %s: no such lastframe %d\n",
- currentmodel->name, lastframe);
- lastframe = 0;
- }
-
- r_thisframe = (daliasframe_t *)((byte *)pmdl + pmdl->ofs_frames
- + thisframe * pmdl->framesize);
-
- r_lastframe = (daliasframe_t *)((byte *)pmdl + pmdl->ofs_frames
- + lastframe * pmdl->framesize);
-}
-
-/*
-** R_AliasSetUpLerpData
-**
-** Precomputes lerp coefficients used for the whole frame.
-*/
-void R_AliasSetUpLerpData( dmdl_t *pmdl, float backlerp )
-{
- float frontlerp;
- vec3_t translation, vectors[3];
- int i;
-
- frontlerp = 1.0F - backlerp;
-
- /*
- ** convert entity's angles into discrete vectors for R, U, and F
- */
- AngleVectors (currententity->angles, vectors[0], vectors[1], vectors[2]);
-
- /*
- ** translation is the vector from last position to this position
- */
- VectorSubtract (currententity->oldorigin, currententity->origin, translation);
-
- /*
- ** move should be the delta back to the previous frame * backlerp
- */
- r_lerp_move[0] = DotProduct(translation, vectors[0]); // forward
- r_lerp_move[1] = -DotProduct(translation, vectors[1]); // left
- r_lerp_move[2] = DotProduct(translation, vectors[2]); // up
-
- VectorAdd( r_lerp_move, r_lastframe->translate, r_lerp_move );
-
- for (i=0 ; i<3 ; i++)
- {
- r_lerp_move[i] = backlerp*r_lerp_move[i] + frontlerp * r_thisframe->translate[i];
- }
-
- for (i=0 ; i<3 ; i++)
- {
- r_lerp_frontv[i] = frontlerp * r_thisframe->scale[i];
- r_lerp_backv[i] = backlerp * r_lastframe->scale[i];
- }
-}
-
-/*
-================
-R_AliasDrawModel
-================
-*/
-void R_AliasDrawModel (void)
-{
- extern void (*d_pdrawspans)(void *);
- extern void R_PolysetDrawSpans8_Opaque( void * );
- extern void R_PolysetDrawSpans8_33( void * );
- extern void R_PolysetDrawSpans8_66( void * );
- extern void R_PolysetDrawSpansConstant8_33( void * );
- extern void R_PolysetDrawSpansConstant8_66( void * );
-
- s_pmdl = (dmdl_t *)currentmodel->extradata;
-
- if ( r_lerpmodels->value == 0 )
- currententity->backlerp = 0;
-
- if ( currententity->flags & RF_WEAPONMODEL )
- {
- if ( r_lefthand->value == 1.0F )
- aliasxscale = -aliasxscale;
- else if ( r_lefthand->value == 2.0F )
- return;
- }
-
- /*
- ** we have to set our frame pointers and transformations before
- ** doing any real work
- */
- R_AliasSetupFrames( s_pmdl );
- R_AliasSetUpTransform();
-
- // see if the bounding box lets us trivially reject, also sets
- // trivial accept status
- if ( R_AliasCheckBBox() == BBOX_TRIVIAL_REJECT )
- {
- if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
- {
- aliasxscale = -aliasxscale;
- }
- return;
- }
-
- // set up the skin and verify it exists
- if ( !R_AliasSetupSkin () )
- {
- ri.Con_Printf( PRINT_ALL, "R_AliasDrawModel %s: NULL skin found\n",
- currentmodel->name);
- return;
- }
-
- r_amodels_drawn++;
- R_AliasSetupLighting ();
-
- /*
- ** select the proper span routine based on translucency
- */
- // PMM - added double damage shell
- // PMM - reordered to handle blending
- if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
- {
- int color;
-
- // PMM - added double
- color = currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM);
- // PMM - reordered, old code first
-/*
- if ( color == RF_SHELL_RED )
- r_aliasblendcolor = SHELL_RED_COLOR;
- else if ( color == RF_SHELL_GREEN )
- r_aliasblendcolor = SHELL_GREEN_COLOR;
- else if ( color == RF_SHELL_BLUE )
- r_aliasblendcolor = SHELL_BLUE_COLOR;
- else if ( color == (RF_SHELL_RED | RF_SHELL_GREEN) )
- r_aliasblendcolor = SHELL_RG_COLOR;
- else if ( color == (RF_SHELL_RED | RF_SHELL_BLUE) )
- r_aliasblendcolor = SHELL_RB_COLOR;
- else if ( color == (RF_SHELL_BLUE | RF_SHELL_GREEN) )
- r_aliasblendcolor = SHELL_BG_COLOR;
- // PMM - added this .. it's yellowish
- else if ( color == (RF_SHELL_DOUBLE) )
- r_aliasblendcolor = SHELL_DOUBLE_COLOR;
- else if ( color == (RF_SHELL_HALF_DAM) )
- r_aliasblendcolor = SHELL_HALF_DAM_COLOR;
- // pmm
- else
- r_aliasblendcolor = SHELL_WHITE_COLOR;
-*/
- if ( color & RF_SHELL_RED )
- {
- if ( ( color & RF_SHELL_BLUE) && ( color & RF_SHELL_GREEN) )
- r_aliasblendcolor = SHELL_WHITE_COLOR;
- else if ( color & (RF_SHELL_BLUE | RF_SHELL_DOUBLE))
- r_aliasblendcolor = SHELL_RB_COLOR;
- else
- r_aliasblendcolor = SHELL_RED_COLOR;
- }
- else if ( color & RF_SHELL_BLUE)
- {
- if ( color & RF_SHELL_DOUBLE )
- r_aliasblendcolor = SHELL_CYAN_COLOR;
- else
- r_aliasblendcolor = SHELL_BLUE_COLOR;
- }
- else if ( color & (RF_SHELL_DOUBLE) )
- r_aliasblendcolor = SHELL_DOUBLE_COLOR;
- else if ( color & (RF_SHELL_HALF_DAM) )
- r_aliasblendcolor = SHELL_HALF_DAM_COLOR;
- else if ( color & RF_SHELL_GREEN )
- r_aliasblendcolor = SHELL_GREEN_COLOR;
- else
- r_aliasblendcolor = SHELL_WHITE_COLOR;
-
-
- if ( currententity->alpha > 0.33 )
- d_pdrawspans = R_PolysetDrawSpansConstant8_66;
- else
- d_pdrawspans = R_PolysetDrawSpansConstant8_33;
- }
- else if ( currententity->flags & RF_TRANSLUCENT )
- {
- if ( currententity->alpha > 0.66 )
- d_pdrawspans = R_PolysetDrawSpans8_Opaque;
- else if ( currententity->alpha > 0.33 )
- d_pdrawspans = R_PolysetDrawSpans8_66;
- else
- d_pdrawspans = R_PolysetDrawSpans8_33;
- }
- else
- {
- d_pdrawspans = R_PolysetDrawSpans8_Opaque;
- }
-
- /*
- ** compute this_frame and old_frame addresses
- */
- R_AliasSetUpLerpData( s_pmdl, currententity->backlerp );
-
- if (currententity->flags & RF_DEPTHHACK)
- s_ziscale = (float)0x8000 * (float)0x10000 * 3.0;
- else
- s_ziscale = (float)0x8000 * (float)0x10000;
-
- R_AliasPreparePoints ();
-
- if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
- {
- aliasxscale = -aliasxscale;
- }
-}
-
-
-
--- a/ref_soft/r_bsp.c
+++ /dev/null
@@ -1,637 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// r_bsp.c
-
-#include "r_local.h"
-
-//
-// current entity info
-//
-qboolean insubmodel;
-entity_t *currententity;
-vec3_t modelorg; // modelorg is the viewpoint reletive to
- // the currently rendering entity
-vec3_t r_entorigin; // the currently rendering entity in world
- // coordinates
-
-float entity_rotation[3][3];
-
-int r_currentbkey;
-
-typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t;
-
-#define MAX_BMODEL_VERTS 500 // 6K
-#define MAX_BMODEL_EDGES 1000 // 12K
-
-static mvertex_t *pbverts;
-static bedge_t *pbedges;
-static int numbverts, numbedges;
-
-static mvertex_t *pfrontenter, *pfrontexit;
-
-static qboolean makeclippededge;
-
-
-//===========================================================================
-
-/*
-================
-R_EntityRotate
-================
-*/
-void R_EntityRotate (vec3_t vec)
-{
- vec3_t tvec;
-
- VectorCopy (vec, tvec);
- vec[0] = DotProduct (entity_rotation[0], tvec);
- vec[1] = DotProduct (entity_rotation[1], tvec);
- vec[2] = DotProduct (entity_rotation[2], tvec);
-}
-
-
-/*
-================
-R_RotateBmodel
-================
-*/
-void R_RotateBmodel (void)
-{
- float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
-
-// TODO: should use a look-up table
-// TODO: should really be stored with the entity instead of being reconstructed
-// TODO: could cache lazily, stored in the entity
-// TODO: share work with R_SetUpAliasTransform
-
-// yaw
- angle = currententity->angles[YAW];
- angle = angle * M_PI*2 / 360;
- s = sin(angle);
- c = cos(angle);
-
- temp1[0][0] = c;
- temp1[0][1] = s;
- temp1[0][2] = 0;
- temp1[1][0] = -s;
- temp1[1][1] = c;
- temp1[1][2] = 0;
- temp1[2][0] = 0;
- temp1[2][1] = 0;
- temp1[2][2] = 1;
-
-
-// pitch
- angle = currententity->angles[PITCH];
- angle = angle * M_PI*2 / 360;
- s = sin(angle);
- c = cos(angle);
-
- temp2[0][0] = c;
- temp2[0][1] = 0;
- temp2[0][2] = -s;
- temp2[1][0] = 0;
- temp2[1][1] = 1;
- temp2[1][2] = 0;
- temp2[2][0] = s;
- temp2[2][1] = 0;
- temp2[2][2] = c;
-
- R_ConcatRotations (temp2, temp1, temp3);
-
-// roll
- angle = currententity->angles[ROLL];
- angle = angle * M_PI*2 / 360;
- s = sin(angle);
- c = cos(angle);
-
- temp1[0][0] = 1;
- temp1[0][1] = 0;
- temp1[0][2] = 0;
- temp1[1][0] = 0;
- temp1[1][1] = c;
- temp1[1][2] = s;
- temp1[2][0] = 0;
- temp1[2][1] = -s;
- temp1[2][2] = c;
-
- R_ConcatRotations (temp1, temp3, entity_rotation);
-
-//
-// rotate modelorg and the transformation matrix
-//
- R_EntityRotate (modelorg);
- R_EntityRotate (vpn);
- R_EntityRotate (vright);
- R_EntityRotate (vup);
-
- R_TransformFrustum ();
-}
-
-
-/*
-================
-R_RecursiveClipBPoly
-
-Clip a bmodel poly down the world bsp tree
-================
-*/
-void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf)
-{
- bedge_t *psideedges[2], *pnextedge, *ptedge;
- int i, side, lastside;
- float dist, frac, lastdist;
- mplane_t *splitplane, tplane;
- mvertex_t *pvert, *plastvert, *ptvert;
- mnode_t *pn;
- int area;
-
- psideedges[0] = psideedges[1] = NULL;
-
- makeclippededge = false;
-
-// transform the BSP plane into model space
-// FIXME: cache these?
- splitplane = pnode->plane;
- tplane.dist = splitplane->dist -
- DotProduct(r_entorigin, splitplane->normal);
- tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal);
- tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal);
- tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal);
-
-// clip edges to BSP plane
- for ( ; pedges ; pedges = pnextedge)
- {
- pnextedge = pedges->pnext;
-
- // set the status for the last point as the previous point
- // FIXME: cache this stuff somehow?
- plastvert = pedges->v[0];
- lastdist = DotProduct (plastvert->position, tplane.normal) -
- tplane.dist;
-
- if (lastdist > 0)
- lastside = 0;
- else
- lastside = 1;
-
- pvert = pedges->v[1];
-
- dist = DotProduct (pvert->position, tplane.normal) - tplane.dist;
-
- if (dist > 0)
- side = 0;
- else
- side = 1;
-
- if (side != lastside)
- {
- // clipped
- if (numbverts >= MAX_BMODEL_VERTS)
- return;
-
- // generate the clipped vertex
- frac = lastdist / (lastdist - dist);
- ptvert = &pbverts[numbverts++];
- ptvert->position[0] = plastvert->position[0] +
- frac * (pvert->position[0] -
- plastvert->position[0]);
- ptvert->position[1] = plastvert->position[1] +
- frac * (pvert->position[1] -
- plastvert->position[1]);
- ptvert->position[2] = plastvert->position[2] +
- frac * (pvert->position[2] -
- plastvert->position[2]);
-
- // split into two edges, one on each side, and remember entering
- // and exiting points
- // FIXME: share the clip edge by having a winding direction flag?
- if (numbedges >= (MAX_BMODEL_EDGES - 1))
- {
- ri.Con_Printf (PRINT_ALL,"Out of edges for bmodel\n");
- return;
- }
-
- ptedge = &pbedges[numbedges];
- ptedge->pnext = psideedges[lastside];
- psideedges[lastside] = ptedge;
- ptedge->v[0] = plastvert;
- ptedge->v[1] = ptvert;
-
- ptedge = &pbedges[numbedges + 1];
- ptedge->pnext = psideedges[side];
- psideedges[side] = ptedge;
- ptedge->v[0] = ptvert;
- ptedge->v[1] = pvert;
-
- numbedges += 2;
-
- if (side == 0)
- {
- // entering for front, exiting for back
- pfrontenter = ptvert;
- makeclippededge = true;
- }
- else
- {
- pfrontexit = ptvert;
- makeclippededge = true;
- }
- }
- else
- {
- // add the edge to the appropriate side
- pedges->pnext = psideedges[side];
- psideedges[side] = pedges;
- }
- }
-
-// if anything was clipped, reconstitute and add the edges along the clip
-// plane to both sides (but in opposite directions)
- if (makeclippededge)
- {
- if (numbedges >= (MAX_BMODEL_EDGES - 2))
- {
- ri.Con_Printf (PRINT_ALL,"Out of edges for bmodel\n");
- return;
- }
-
- ptedge = &pbedges[numbedges];
- ptedge->pnext = psideedges[0];
- psideedges[0] = ptedge;
- ptedge->v[0] = pfrontexit;
- ptedge->v[1] = pfrontenter;
-
- ptedge = &pbedges[numbedges + 1];
- ptedge->pnext = psideedges[1];
- psideedges[1] = ptedge;
- ptedge->v[0] = pfrontenter;
- ptedge->v[1] = pfrontexit;
-
- numbedges += 2;
- }
-
-// draw or recurse further
- for (i=0 ; i<2 ; i++)
- {
- if (psideedges[i])
- {
- // draw if we've reached a non-solid leaf, done if all that's left is a
- // solid leaf, and continue down the tree if it's not a leaf
- pn = pnode->children[i];
-
- // we're done with this branch if the node or leaf isn't in the PVS
- if (pn->visframe == r_visframecount)
- {
- if (pn->contents != CONTENTS_NODE)
- {
- if (pn->contents != CONTENTS_SOLID)
- {
- if (r_newrefdef.areabits)
- {
- area = ((mleaf_t *)pn)->area;
- if (! (r_newrefdef.areabits[area>>3] & (1<<(area&7)) ) )
- continue; // not visible
- }
-
- r_currentbkey = ((mleaf_t *)pn)->key;
- R_RenderBmodelFace (psideedges[i], psurf);
- }
- }
- else
- {
- R_RecursiveClipBPoly (psideedges[i], pnode->children[i],
- psurf);
- }
- }
- }
- }
-}
-
-
-/*
-================
-R_DrawSolidClippedSubmodelPolygons
-
-Bmodel crosses multiple leafs
-================
-*/
-void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode)
-{
- int i, j, lindex;
- vec_t dot;
- msurface_t *psurf;
- int numsurfaces;
- mplane_t *pplane;
- mvertex_t bverts[MAX_BMODEL_VERTS];
- bedge_t bedges[MAX_BMODEL_EDGES], *pbedge;
- medge_t *pedge, *pedges;
-
-// FIXME: use bounding-box-based frustum clipping info?
-
- psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
- numsurfaces = pmodel->nummodelsurfaces;
- pedges = pmodel->edges;
-
- for (i=0 ; i<numsurfaces ; i++, psurf++)
- {
- // find which side of the node we are on
- pplane = psurf->plane;
-
- dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
-
- // draw the polygon
- if (( !(psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
- ((psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
- continue;
-
- // FIXME: use bounding-box-based frustum clipping info?
-
- // copy the edges to bedges, flipping if necessary so always
- // clockwise winding
- // FIXME: if edges and vertices get caches, these assignments must move
- // outside the loop, and overflow checking must be done here
- pbverts = bverts;
- pbedges = bedges;
- numbverts = numbedges = 0;
- pbedge = &bedges[numbedges];
- numbedges += psurf->numedges;
-
- for (j=0 ; j<psurf->numedges ; j++)
- {
- lindex = pmodel->surfedges[psurf->firstedge+j];
-
- if (lindex > 0)
- {
- pedge = &pedges[lindex];
- pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]];
- pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]];
- }
- else
- {
- lindex = -lindex;
- pedge = &pedges[lindex];
- pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]];
- pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]];
- }
-
- pbedge[j].pnext = &pbedge[j+1];
- }
-
- pbedge[j-1].pnext = NULL; // mark end of edges
-
- if ( !( psurf->texinfo->flags & ( SURF_TRANS66 | SURF_TRANS33 ) ) )
- R_RecursiveClipBPoly (pbedge, topnode, psurf);
- else
- R_RenderBmodelFace( pbedge, psurf );
- }
-}
-
-
-/*
-================
-R_DrawSubmodelPolygons
-
-All in one leaf
-================
-*/
-void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode)
-{
- int i;
- vec_t dot;
- msurface_t *psurf;
- int numsurfaces;
- mplane_t *pplane;
-
-// FIXME: use bounding-box-based frustum clipping info?
-
- psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
- numsurfaces = pmodel->nummodelsurfaces;
-
- for (i=0 ; i<numsurfaces ; i++, psurf++)
- {
- // find which side of the node we are on
- pplane = psurf->plane;
-
- dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
-
- // draw the polygon
- if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
- (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
- {
- r_currentkey = ((mleaf_t *)topnode)->key;
-
- // FIXME: use bounding-box-based frustum clipping info?
- R_RenderFace (psurf, clipflags);
- }
- }
-}
-
-
-int c_drawnode;
-
-/*
-================
-R_RecursiveWorldNode
-================
-*/
-void R_RecursiveWorldNode (mnode_t *node, int clipflags)
-{
- int i, c, side, *pindex;
- vec3_t acceptpt, rejectpt;
- mplane_t *plane;
- msurface_t *surf, **mark;
- float d, dot;
- mleaf_t *pleaf;
-
- if (node->contents == CONTENTS_SOLID)
- return; // solid
-
- if (node->visframe != r_visframecount)
- return;
-
-// cull the clipping planes if not trivial accept
-// FIXME: the compiler is doing a lousy job of optimizing here; it could be
-// twice as fast in ASM
- if (clipflags)
- {
- for (i=0 ; i<4 ; i++)
- {
- if (! (clipflags & (1<<i)) )
- continue; // don't need to clip against it
-
- // generate accept and reject points
- // FIXME: do with fast look-ups or integer tests based on the sign bit
- // of the floating point values
-
- pindex = pfrustum_indexes[i];
-
- rejectpt[0] = (float)node->minmaxs[pindex[0]];
- rejectpt[1] = (float)node->minmaxs[pindex[1]];
- rejectpt[2] = (float)node->minmaxs[pindex[2]];
-
- d = DotProduct (rejectpt, view_clipplanes[i].normal);
- d -= view_clipplanes[i].dist;
- if (d <= 0)
- return;
- acceptpt[0] = (float)node->minmaxs[pindex[3+0]];
- acceptpt[1] = (float)node->minmaxs[pindex[3+1]];
- acceptpt[2] = (float)node->minmaxs[pindex[3+2]];
-
- d = DotProduct (acceptpt, view_clipplanes[i].normal);
- d -= view_clipplanes[i].dist;
-
- if (d >= 0)
- clipflags &= ~(1<<i); // node is entirely on screen
- }
- }
-
-c_drawnode++;
-
-// if a leaf node, draw stuff
- if (node->contents != -1)
- {
- pleaf = (mleaf_t *)node;
-
- // check for door connected areas
- if (r_newrefdef.areabits)
- {
- if (! (r_newrefdef.areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) )
- return; // not visible
- }
-
- mark = pleaf->firstmarksurface;
- c = pleaf->nummarksurfaces;
-
- if (c)
- {
- do
- {
- (*mark)->visframe = r_framecount;
- mark++;
- } while (--c);
- }
-
- pleaf->key = r_currentkey;
- r_currentkey++; // all bmodels in a leaf share the same key
- }
- else
- {
- // node is just a decision point, so go down the apropriate sides
-
- // find which side of the node we are on
- plane = node->plane;
-
- switch (plane->type)
- {
- case PLANE_X:
- dot = modelorg[0] - plane->dist;
- break;
- case PLANE_Y:
- dot = modelorg[1] - plane->dist;
- break;
- case PLANE_Z:
- dot = modelorg[2] - plane->dist;
- break;
- default:
- dot = DotProduct (modelorg, plane->normal) - plane->dist;
- break;
- }
-
- if (dot >= 0)
- side = 0;
- else
- side = 1;
-
- // recurse down the children, front side first
- R_RecursiveWorldNode (node->children[side], clipflags);
-
- // draw stuff
- c = node->numsurfaces;
-
- if (c)
- {
- surf = r_worldmodel->surfaces + node->firstsurface;
-
- if (dot < -BACKFACE_EPSILON)
- {
- do
- {
- if ((surf->flags & SURF_PLANEBACK) &&
- (surf->visframe == r_framecount))
- {
- R_RenderFace (surf, clipflags);
- }
-
- surf++;
- } while (--c);
- }
- else if (dot > BACKFACE_EPSILON)
- {
- do
- {
- if (!(surf->flags & SURF_PLANEBACK) &&
- (surf->visframe == r_framecount))
- {
- R_RenderFace (surf, clipflags);
- }
-
- surf++;
- } while (--c);
- }
-
- // all surfaces on the same node share the same sequence number
- r_currentkey++;
- }
-
- // recurse down the back side
- R_RecursiveWorldNode (node->children[!side], clipflags);
- }
-}
-
-
-
-/*
-================
-R_RenderWorld
-================
-*/
-void R_RenderWorld (void)
-{
-
- if (!r_drawworld->value)
- return;
- if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
- return;
-
- c_drawnode=0;
-
- // auto cycle the world frame for texture animation
- r_worldentity.frame = (int)(r_newrefdef.time*2);
- currententity = &r_worldentity;
-
- VectorCopy (r_origin, modelorg);
- currentmodel = r_worldmodel;
- r_pcurrentvertbase = currentmodel->vertexes;
-
- R_RecursiveWorldNode (currentmodel->nodes, 15);
-}
-
-
--- a/ref_soft/r_draw.c
+++ /dev/null
@@ -1,445 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-// draw.c
-
-#include "r_local.h"
-
-
-image_t *draw_chars; // 8*8 graphic characters
-
-//=============================================================================
-
-/*
-================
-Draw_FindPic
-================
-*/
-image_t *Draw_FindPic (char *name)
-{
- image_t *image;
- char fullname[MAX_QPATH];
-
- if (name[0] != '/' && name[0] != '\\')
- {
- Com_sprintf (fullname, sizeof(fullname), "pics/%s.pcx", name);
- image = R_FindImage (fullname, it_pic);
- }
- else
- image = R_FindImage (name+1, it_pic);
-
- return image;
-}
-
-
-
-/*
-===============
-Draw_InitLocal
-===============
-*/
-void Draw_InitLocal (void)
-{
- draw_chars = Draw_FindPic ("conchars");
-}
-
-
-
-/*
-================
-Draw_Char
-
-Draws one 8*8 graphics character
-It can be clipped to the top of the screen to allow the console to be
-smoothly scrolled off.
-================
-*/
-void Draw_Char (int x, int y, int num)
-{
- byte *dest;
- byte *source;
- int drawline;
- int row, col;
-
- num &= 255;
-
- if (num == 32 || num == 32+128)
- return;
-
- if (y <= -8)
- return; // totally off screen
-
-// if ( ( y + 8 ) >= vid.height )
- if ( ( y + 8 ) > vid.height ) // PGM - status text was missing in sw...
- return;
-
-#ifdef PARANOID
- if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
- ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: (%i, %i)", x, y);
- if (num < 0 || num > 255)
- ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: char %i", num);
-#endif
-
- row = num>>4;
- col = num&15;
- source = draw_chars->pixels[0] + (row<<10) + (col<<3);
-
- if (y < 0)
- { // clipped
- drawline = 8 + y;
- source -= 128*y;
- y = 0;
- }
- else
- drawline = 8;
-
-
- dest = vid.buffer + y*vid.rowbytes + x;
-
- while (drawline--)
- {
- if (source[0] != TRANSPARENT_COLOR)
- dest[0] = source[0];
- if (source[1] != TRANSPARENT_COLOR)
- dest[1] = source[1];
- if (source[2] != TRANSPARENT_COLOR)
- dest[2] = source[2];
- if (source[3] != TRANSPARENT_COLOR)
- dest[3] = source[3];
- if (source[4] != TRANSPARENT_COLOR)
- dest[4] = source[4];
- if (source[5] != TRANSPARENT_COLOR)
- dest[5] = source[5];
- if (source[6] != TRANSPARENT_COLOR)
- dest[6] = source[6];
- if (source[7] != TRANSPARENT_COLOR)
- dest[7] = source[7];
- source += 128;
- dest += vid.rowbytes;
- }
-}
-
-/*
-=============
-Draw_GetPicSize
-=============
-*/
-void Draw_GetPicSize (int *w, int *h, char *pic)
-{
- image_t *gl;
-
- gl = Draw_FindPic (pic);
- if (!gl)
- {
- *w = *h = -1;
- return;
- }
- *w = gl->width;
- *h = gl->height;
-}
-
-/*
-=============
-Draw_StretchPicImplementation
-=============
-*/
-void Draw_StretchPicImplementation (int x, int y, int w, int h, image_t *pic)
-{
- byte *dest, *source;
- int v, u, sv;
- int height;
- int f, fstep;
- int skip;
-
- if ((x < 0) ||
- (x + w > vid.width) ||
- (y + h > vid.height))
- {
- ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");
- }
-
- height = h;
- if (y < 0)
- {
- skip = -y;
- height += y;
- y = 0;
- }
- else
- skip = 0;
-
- dest = vid.buffer + y * vid.rowbytes + x;
-
- for (v=0 ; v<height ; v++, dest += vid.rowbytes)
- {
- sv = (skip + v)*pic->height/h;
- source = pic->pixels[0] + sv*pic->width;
- if (w == pic->width)
- memcpy (dest, source, w);
- else
- {
- f = 0;
- fstep = pic->width*0x10000/w;
- for (u=0 ; u<w ; u+=4)
- {
- dest[u] = source[f>>16];
- f += fstep;
- dest[u+1] = source[f>>16];
- f += fstep;
- dest[u+2] = source[f>>16];
- f += fstep;
- dest[u+3] = source[f>>16];
- f += fstep;
- }
- }
- }
-}
-
-/*
-=============
-Draw_StretchPic
-=============
-*/
-void Draw_StretchPic (int x, int y, int w, int h, char *name)
-{
- image_t *pic;
-
- pic = Draw_FindPic (name);
- if (!pic)
- {
- ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
- return;
- }
- Draw_StretchPicImplementation (x, y, w, h, pic);
-}
-
-/*
-=============
-Draw_StretchRaw
-=============
-*/
-void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
-{
- image_t pic;
-
- pic.pixels[0] = data;
- pic.width = cols;
- pic.height = rows;
- Draw_StretchPicImplementation (x, y, w, h, &pic);
-}
-
-/*
-=============
-Draw_Pic
-=============
-*/
-void Draw_Pic (int x, int y, char *name)
-{
- image_t *pic;
- byte *dest, *source;
- int v, u;
- int tbyte;
- int height;
-
- pic = Draw_FindPic (name);
- if (!pic)
- {
- ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
- return;
- }
-
- if ((x < 0) ||
- (x + pic->width > vid.width) ||
- (y + pic->height > vid.height))
- return; // ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");
-
- height = pic->height;
- source = pic->pixels[0];
- if (y < 0)
- {
- height += y;
- source += pic->width*-y;
- y = 0;
- }
-
- dest = vid.buffer + y * vid.rowbytes + x;
-
- if (!pic->transparent)
- {
- for (v=0 ; v<height ; v++)
- {
- memcpy (dest, source, pic->width);
- dest += vid.rowbytes;
- source += pic->width;
- }
- }
- else
- {
- if (pic->width & 7)
- { // general
- for (v=0 ; v<height ; v++)
- {
- for (u=0 ; u<pic->width ; u++)
- if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
- dest[u] = tbyte;
-
- dest += vid.rowbytes;
- source += pic->width;
- }
- }
- else
- { // unwound
- for (v=0 ; v<height ; v++)
- {
- for (u=0 ; u<pic->width ; u+=8)
- {
- if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
- dest[u] = tbyte;
- if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
- dest[u+1] = tbyte;
- if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
- dest[u+2] = tbyte;
- if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
- dest[u+3] = tbyte;
- if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
- dest[u+4] = tbyte;
- if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
- dest[u+5] = tbyte;
- if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
- dest[u+6] = tbyte;
- if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
- dest[u+7] = tbyte;
- }
- dest += vid.rowbytes;
- source += pic->width;
- }
- }
- }
-}
-
-/*
-=============
-Draw_TileClear
-
-This repeats a 64*64 tile graphic to fill the screen around a sized down
-refresh window.
-=============
-*/
-void Draw_TileClear (int x, int y, int w, int h, char *name)
-{
- int i, j;
- byte *psrc;
- byte *pdest;
- image_t *pic;
- int x2;
-
- if (x < 0)
- {
- w += x;
- x = 0;
- }
- if (y < 0)
- {
- h += y;
- y = 0;
- }
- if (x + w > vid.width)
- w = vid.width - x;
- if (y + h > vid.height)
- h = vid.height - y;
- if (w <= 0 || h <= 0)
- return;
-
- pic = Draw_FindPic (name);
- if (!pic)
- {
- ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
- return;
- }
- x2 = x + w;
- pdest = vid.buffer + y*vid.rowbytes;
- for (i=0 ; i<h ; i++, pdest += vid.rowbytes)
- {
- psrc = pic->pixels[0] + pic->width * ((i+y)&63);
- for (j=x ; j<x2 ; j++)
- pdest[j] = psrc[j&63];
- }
-}
-
-
-/*
-=============
-Draw_Fill
-
-Fills a box of pixels with a single color
-=============
-*/
-void Draw_Fill (int x, int y, int w, int h, int c)
-{
- byte *dest;
- int u, v;
-
- if (x+w > vid.width)
- w = vid.width - x;
- if (y+h > vid.height)
- h = vid.height - y;
- if (x < 0)
- {
- w += x;
- x = 0;
- }
- if (y < 0)
- {
- h += y;
- y = 0;
- }
- if (w < 0 || h < 0)
- return;
- dest = vid.buffer + y*vid.rowbytes + x;
- for (v=0 ; v<h ; v++, dest += vid.rowbytes)
- for (u=0 ; u<w ; u++)
- dest[u] = c;
-}
-//=============================================================================
-
-/*
-================
-Draw_FadeScreen
-
-================
-*/
-void Draw_FadeScreen (void)
-{
- int x,y;
- byte *pbuf;
- int t;
-
- for (y=0 ; y<vid.height ; y++)
- {
- pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
- t = (y & 1) << 1;
-
- for (x=0 ; x<vid.width ; x++)
- {
- if ((x & 3) != t)
- pbuf[x] = 0;
- }
- }
-}
--- a/ref_soft/r_edge.c
+++ /dev/null
@@ -1,1125 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// r_edge.c
-
-#include "r_local.h"
-
-#ifndef id386
-void R_SurfacePatch (void)
-{
-}
-
-void R_EdgeCodeStart (void)
-{
-}
-
-void R_EdgeCodeEnd (void)
-{
-}
-#endif
-
-
-#if 0
-the complex cases add new polys on most lines, so dont optimize for keeping them the same
-have multiple free span lists to try to get better coherence?
-low depth complexity -- 1 to 3 or so
-
-have a sentinal at both ends?
-#endif
-
-
-edge_t *auxedges;
-edge_t *r_edges, *edge_p, *edge_max;
-
-surf_t *surfaces, *surface_p, *surf_max;
-
-// surfaces are generated in back to front order by the bsp, so if a surf
-// pointer is greater than another one, it should be drawn in front
-// surfaces[1] is the background, and is used as the active surface stack
-
-edge_t *newedges[MAXHEIGHT];
-edge_t *removeedges[MAXHEIGHT];
-
-espan_t *span_p, *max_span_p;
-
-int r_currentkey;
-
-int current_iv;
-
-int edge_head_u_shift20, edge_tail_u_shift20;
-
-static void (*pdrawfunc)(void);
-
-edge_t edge_head;
-edge_t edge_tail;
-edge_t edge_aftertail;
-edge_t edge_sentinel;
-
-float fv;
-
-static int miplevel;
-
-float scale_for_mip;
-int ubasestep, errorterm, erroradjustup, erroradjustdown;
-
-// FIXME: should go away
-extern void R_RotateBmodel (void);
-extern void R_TransformFrustum (void);
-
-
-
-void R_GenerateSpans (void);
-void R_GenerateSpansBackward (void);
-
-void R_LeadingEdge (edge_t *edge);
-void R_LeadingEdgeBackwards (edge_t *edge);
-void R_TrailingEdge (surf_t *surf, edge_t *edge);
-
-
-/*
-===============================================================================
-
-EDGE SCANNING
-
-===============================================================================
-*/
-
-/*
-==============
-R_BeginEdgeFrame
-==============
-*/
-void R_BeginEdgeFrame (void)
-{
- int v;
-
- edge_p = r_edges;
- edge_max = &r_edges[r_numallocatededges];
-
- surface_p = &surfaces[2]; // background is surface 1,
- // surface 0 is a dummy
- surfaces[1].spans = NULL; // no background spans yet
- surfaces[1].flags = SURF_DRAWBACKGROUND;
-
-// put the background behind everything in the world
- if (sw_draworder->value)
- {
- pdrawfunc = R_GenerateSpansBackward;
- surfaces[1].key = 0;
- r_currentkey = 1;
- }
- else
- {
- pdrawfunc = R_GenerateSpans;
- surfaces[1].key = 0x7FFfFFFF;
- r_currentkey = 0;
- }
-
-// FIXME: set with memset
- for (v=r_refdef.vrect.y ; v<r_refdef.vrectbottom ; v++)
- {
- newedges[v] = removeedges[v] = NULL;
- }
-}
-
-
-#if !id386
-
-/*
-==============
-R_InsertNewEdges
-
-Adds the edges in the linked list edgestoadd, adding them to the edges in the
-linked list edgelist. edgestoadd is assumed to be sorted on u, and non-empty (this is actually newedges[v]). edgelist is assumed to be sorted on u, with a
-sentinel at the end (actually, this is the active edge table starting at
-edge_head.next).
-==============
-*/
-void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist)
-{
- edge_t *next_edge;
-
- do
- {
- next_edge = edgestoadd->next;
-edgesearch:
- if (edgelist->u >= edgestoadd->u)
- goto addedge;
- edgelist=edgelist->next;
- if (edgelist->u >= edgestoadd->u)
- goto addedge;
- edgelist=edgelist->next;
- if (edgelist->u >= edgestoadd->u)
- goto addedge;
- edgelist=edgelist->next;
- if (edgelist->u >= edgestoadd->u)
- goto addedge;
- edgelist=edgelist->next;
- goto edgesearch;
-
- // insert edgestoadd before edgelist
-addedge:
- edgestoadd->next = edgelist;
- edgestoadd->prev = edgelist->prev;
- edgelist->prev->next = edgestoadd;
- edgelist->prev = edgestoadd;
- } while ((edgestoadd = next_edge) != NULL);
-}
-
-#endif // !id386
-
-
-#if !id386
-
-/*
-==============
-R_RemoveEdges
-==============
-*/
-void R_RemoveEdges (edge_t *pedge)
-{
-
- do
- {
- pedge->next->prev = pedge->prev;
- pedge->prev->next = pedge->next;
- } while ((pedge = pedge->nextremove) != NULL);
-}
-
-#endif // !id386
-
-
-#if !id386
-
-/*
-==============
-R_StepActiveU
-==============
-*/
-void R_StepActiveU (edge_t *pedge)
-{
- edge_t *pnext_edge, *pwedge;
-
- while (1)
- {
-nextedge:
- pedge->u += pedge->u_step;
- if (pedge->u < pedge->prev->u)
- goto pushback;
- pedge = pedge->next;
-
- pedge->u += pedge->u_step;
- if (pedge->u < pedge->prev->u)
- goto pushback;
- pedge = pedge->next;
-
- pedge->u += pedge->u_step;
- if (pedge->u < pedge->prev->u)
- goto pushback;
- pedge = pedge->next;
-
- pedge->u += pedge->u_step;
- if (pedge->u < pedge->prev->u)
- goto pushback;
- pedge = pedge->next;
-
- goto nextedge;
-
-pushback:
- if (pedge == &edge_aftertail)
- return;
-
- // push it back to keep it sorted
- pnext_edge = pedge->next;
-
- // pull the edge out of the edge list
- pedge->next->prev = pedge->prev;
- pedge->prev->next = pedge->next;
-
- // find out where the edge goes in the edge list
- pwedge = pedge->prev->prev;
-
- while (pwedge->u > pedge->u)
- {
- pwedge = pwedge->prev;
- }
-
- // put the edge back into the edge list
- pedge->next = pwedge->next;
- pedge->prev = pwedge;
- pedge->next->prev = pedge;
- pwedge->next = pedge;
-
- pedge = pnext_edge;
- if (pedge == &edge_tail)
- return;
- }
-}
-
-#endif // !id386
-
-
-/*
-==============
-R_CleanupSpan
-==============
-*/
-void R_CleanupSpan (void)
-{
- surf_t *surf;
- int iu;
- espan_t *span;
-
-// now that we've reached the right edge of the screen, we're done with any
-// unfinished surfaces, so emit a span for whatever's on top
- surf = surfaces[1].next;
- iu = edge_tail_u_shift20;
- if (iu > surf->last_u)
- {
- span = span_p++;
- span->u = surf->last_u;
- span->count = iu - span->u;
- span->v = current_iv;
- span->pnext = surf->spans;
- surf->spans = span;
- }
-
-// reset spanstate for all surfaces in the surface stack
- do
- {
- surf->spanstate = 0;
- surf = surf->next;
- } while (surf != &surfaces[1]);
-}
-
-
-/*
-==============
-R_LeadingEdgeBackwards
-==============
-*/
-void R_LeadingEdgeBackwards (edge_t *edge)
-{
- espan_t *span;
- surf_t *surf, *surf2;
- int iu;
-
-// it's adding a new surface in, so find the correct place
- surf = &surfaces[edge->surfs[1]];
-
-// don't start a span if this is an inverted span, with the end
-// edge preceding the start edge (that is, we've already seen the
-// end edge)
- if (++surf->spanstate == 1)
- {
- surf2 = surfaces[1].next;
-
- if (surf->key > surf2->key)
- goto newtop;
-
- // if it's two surfaces on the same plane, the one that's already
- // active is in front, so keep going unless it's a bmodel
- if (surf->insubmodel && (surf->key == surf2->key))
- {
- // must be two bmodels in the same leaf; don't care, because they'll
- // never be farthest anyway
- goto newtop;
- }
-
-continue_search:
-
- do
- {
- surf2 = surf2->next;
- } while (surf->key < surf2->key);
-
- if (surf->key == surf2->key)
- {
- // if it's two surfaces on the same plane, the one that's already
- // active is in front, so keep going unless it's a bmodel
- if (!surf->insubmodel)
- goto continue_search;
-
- // must be two bmodels in the same leaf; don't care which is really
- // in front, because they'll never be farthest anyway
- }
-
- goto gotposition;
-
-newtop:
- // emit a span (obscures current top)
- iu = edge->u >> 20;
-
- if (iu > surf2->last_u)
- {
- span = span_p++;
- span->u = surf2->last_u;
- span->count = iu - span->u;
- span->v = current_iv;
- span->pnext = surf2->spans;
- surf2->spans = span;
- }
-
- // set last_u on the new span
- surf->last_u = iu;
-
-gotposition:
- // insert before surf2
- surf->next = surf2;
- surf->prev = surf2->prev;
- surf2->prev->next = surf;
- surf2->prev = surf;
- }
-}
-
-
-/*
-==============
-R_TrailingEdge
-==============
-*/
-void R_TrailingEdge (surf_t *surf, edge_t *edge)
-{
- espan_t *span;
- int iu;
-
-// don't generate a span if this is an inverted span, with the end
-// edge preceding the start edge (that is, we haven't seen the
-// start edge yet)
- if (--surf->spanstate == 0)
- {
- if (surf == surfaces[1].next)
- {
- // emit a span (current top going away)
- iu = edge->u >> 20;
- if (iu > surf->last_u)
- {
- span = span_p++;
- span->u = surf->last_u;
- span->count = iu - span->u;
- span->v = current_iv;
- span->pnext = surf->spans;
- surf->spans = span;
- }
-
- // set last_u on the surface below
- surf->next->last_u = iu;
- }
-
- surf->prev->next = surf->next;
- surf->next->prev = surf->prev;
- }
-}
-
-
-#if !id386
-
-/*
-==============
-R_LeadingEdge
-==============
-*/
-void R_LeadingEdge (edge_t *edge)
-{
- espan_t *span;
- surf_t *surf, *surf2;
- int iu;
- float fu, newzi, testzi, newzitop, newzibottom;
-
- if (edge->surfs[1])
- {
- // it's adding a new surface in, so find the correct place
- surf = &surfaces[edge->surfs[1]];
-
- // don't start a span if this is an inverted span, with the end
- // edge preceding the start edge (that is, we've already seen the
- // end edge)
- if (++surf->spanstate == 1)
- {
- surf2 = surfaces[1].next;
-
- if (surf->key < surf2->key)
- goto newtop;
-
- // if it's two surfaces on the same plane, the one that's already
- // active is in front, so keep going unless it's a bmodel
- if (surf->insubmodel && (surf->key == surf2->key))
- {
- // must be two bmodels in the same leaf; sort on 1/z
- fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
- newzi = surf->d_ziorigin + fv*surf->d_zistepv +
- fu*surf->d_zistepu;
- newzibottom = newzi * 0.99;
-
- testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
- fu*surf2->d_zistepu;
-
- if (newzibottom >= testzi)
- {
- goto newtop;
- }
-
- newzitop = newzi * 1.01;
- if (newzitop >= testzi)
- {
- if (surf->d_zistepu >= surf2->d_zistepu)
- {
- goto newtop;
- }
- }
- }
-
-continue_search:
-
- do
- {
- surf2 = surf2->next;
- } while (surf->key > surf2->key);
-
- if (surf->key == surf2->key)
- {
- // if it's two surfaces on the same plane, the one that's already
- // active is in front, so keep going unless it's a bmodel
- if (!surf->insubmodel)
- goto continue_search;
-
- // must be two bmodels in the same leaf; sort on 1/z
- fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
- newzi = surf->d_ziorigin + fv*surf->d_zistepv +
- fu*surf->d_zistepu;
- newzibottom = newzi * 0.99;
-
- testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
- fu*surf2->d_zistepu;
-
- if (newzibottom >= testzi)
- {
- goto gotposition;
- }
-
- newzitop = newzi * 1.01;
- if (newzitop >= testzi)
- {
- if (surf->d_zistepu >= surf2->d_zistepu)
- {
- goto gotposition;
- }
- }
-
- goto continue_search;
- }
-
- goto gotposition;
-
-newtop:
- // emit a span (obscures current top)
- iu = edge->u >> 20;
-
- if (iu > surf2->last_u)
- {
- span = span_p++;
- span->u = surf2->last_u;
- span->count = iu - span->u;
- span->v = current_iv;
- span->pnext = surf2->spans;
- surf2->spans = span;
- }
-
- // set last_u on the new span
- surf->last_u = iu;
-
-gotposition:
- // insert before surf2
- surf->next = surf2;
- surf->prev = surf2->prev;
- surf2->prev->next = surf;
- surf2->prev = surf;
- }
- }
-}
-
-
-/*
-==============
-R_GenerateSpans
-==============
-*/
-void R_GenerateSpans (void)
-{
- edge_t *edge;
- surf_t *surf;
-
-// clear active surfaces to just the background surface
- surfaces[1].next = surfaces[1].prev = &surfaces[1];
- surfaces[1].last_u = edge_head_u_shift20;
-
-// generate spans
- for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
- {
- if (edge->surfs[0])
- {
- // it has a left surface, so a surface is going away for this span
- surf = &surfaces[edge->surfs[0]];
-
- R_TrailingEdge (surf, edge);
-
- if (!edge->surfs[1])
- continue;
- }
-
- R_LeadingEdge (edge);
- }
-
- R_CleanupSpan ();
-}
-
-#endif // !id386
-
-
-/*
-==============
-R_GenerateSpansBackward
-==============
-*/
-void R_GenerateSpansBackward (void)
-{
- edge_t *edge;
-
-// clear active surfaces to just the background surface
- surfaces[1].next = surfaces[1].prev = &surfaces[1];
- surfaces[1].last_u = edge_head_u_shift20;
-
-// generate spans
- for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
- {
- if (edge->surfs[0])
- R_TrailingEdge (&surfaces[edge->surfs[0]], edge);
-
- if (edge->surfs[1])
- R_LeadingEdgeBackwards (edge);
- }
-
- R_CleanupSpan ();
-}
-
-
-/*
-==============
-R_ScanEdges
-
-Input:
-newedges[] array
- this has links to edges, which have links to surfaces
-
-Output:
-Each surface has a linked list of its visible spans
-==============
-*/
-void R_ScanEdges (void)
-{
- int iv, bottom;
- byte basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE];
- espan_t *basespan_p;
- surf_t *s;
-
- basespan_p = (espan_t *)
- ((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
- max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width];
-
- span_p = basespan_p;
-
-// clear active edges to just the background edges around the whole screen
-// FIXME: most of this only needs to be set up once
- edge_head.u = r_refdef.vrect.x << 20;
- edge_head_u_shift20 = edge_head.u >> 20;
- edge_head.u_step = 0;
- edge_head.prev = NULL;
- edge_head.next = &edge_tail;
- edge_head.surfs[0] = 0;
- edge_head.surfs[1] = 1;
-
- edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF;
- edge_tail_u_shift20 = edge_tail.u >> 20;
- edge_tail.u_step = 0;
- edge_tail.prev = &edge_head;
- edge_tail.next = &edge_aftertail;
- edge_tail.surfs[0] = 1;
- edge_tail.surfs[1] = 0;
-
- edge_aftertail.u = -1; // force a move
- edge_aftertail.u_step = 0;
- edge_aftertail.next = &edge_sentinel;
- edge_aftertail.prev = &edge_tail;
-
-// FIXME: do we need this now that we clamp x in r_draw.c?
- edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this
- edge_sentinel.prev = &edge_aftertail;
-
-//
-// process all scan lines
-//
- bottom = r_refdef.vrectbottom - 1;
-
- for (iv=r_refdef.vrect.y ; iv<bottom ; iv++)
- {
- current_iv = iv;
- fv = (float)iv;
-
- // mark that the head (background start) span is pre-included
- surfaces[1].spanstate = 1;
-
- if (newedges[iv])
- {
- R_InsertNewEdges (newedges[iv], edge_head.next);
- }
-
- (*pdrawfunc) ();
-
- // flush the span list if we can't be sure we have enough spans left for
- // the next scan
- if (span_p > max_span_p)
- {
- D_DrawSurfaces ();
-
- // clear the surface span pointers
- for (s = &surfaces[1] ; s<surface_p ; s++)
- s->spans = NULL;
-
- span_p = basespan_p;
- }
-
- if (removeedges[iv])
- R_RemoveEdges (removeedges[iv]);
-
- if (edge_head.next != &edge_tail)
- R_StepActiveU (edge_head.next);
- }
-
-// do the last scan (no need to step or sort or remove on the last scan)
-
- current_iv = iv;
- fv = (float)iv;
-
-// mark that the head (background start) span is pre-included
- surfaces[1].spanstate = 1;
-
- if (newedges[iv])
- R_InsertNewEdges (newedges[iv], edge_head.next);
-
- (*pdrawfunc) ();
-
-// draw whatever's left in the span list
- D_DrawSurfaces ();
-}
-
-
-/*
-=========================================================================
-
-SURFACE FILLING
-
-=========================================================================
-*/
-
-msurface_t *pface;
-surfcache_t *pcurrentcache;
-vec3_t transformed_modelorg;
-vec3_t world_transformed_modelorg;
-vec3_t local_modelorg;
-
-/*
-=============
-D_MipLevelForScale
-=============
-*/
-int D_MipLevelForScale (float scale)
-{
- int lmiplevel;
-
- if (scale >= d_scalemip[0] )
- lmiplevel = 0;
- else if (scale >= d_scalemip[1] )
- lmiplevel = 1;
- else if (scale >= d_scalemip[2] )
- lmiplevel = 2;
- else
- lmiplevel = 3;
-
- if (lmiplevel < d_minmip)
- lmiplevel = d_minmip;
-
- return lmiplevel;
-}
-
-
-/*
-==============
-D_FlatFillSurface
-
-Simple single color fill with no texture mapping
-==============
-*/
-void D_FlatFillSurface (surf_t *surf, int color)
-{
- espan_t *span;
- byte *pdest;
- int u, u2;
-
- for (span=surf->spans ; span ; span=span->pnext)
- {
- pdest = (byte *)d_viewbuffer + r_screenwidth*span->v;
- u = span->u;
- u2 = span->u + span->count - 1;
- for ( ; u <= u2 ; u++)
- pdest[u] = color;
- }
-}
-
-
-/*
-==============
-D_CalcGradients
-==============
-*/
-void D_CalcGradients (msurface_t *pface)
-{
- mplane_t *pplane;
- float mipscale;
- vec3_t p_temp1;
- vec3_t p_saxis, p_taxis;
- float t;
-
- pplane = pface->plane;
-
- mipscale = 1.0 / (float)(1 << miplevel);
-
- TransformVector (pface->texinfo->vecs[0], p_saxis);
- TransformVector (pface->texinfo->vecs[1], p_taxis);
-
- t = xscaleinv * mipscale;
- d_sdivzstepu = p_saxis[0] * t;
- d_tdivzstepu = p_taxis[0] * t;
-
- t = yscaleinv * mipscale;
- d_sdivzstepv = -p_saxis[1] * t;
- d_tdivzstepv = -p_taxis[1] * t;
-
- d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu -
- ycenter * d_sdivzstepv;
- d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu -
- ycenter * d_tdivzstepv;
-
- VectorScale (transformed_modelorg, mipscale, p_temp1);
-
- t = 0x10000*mipscale;
- sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
- ((pface->texturemins[0] << 16) >> miplevel)
- + pface->texinfo->vecs[0][3]*t;
- tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
- ((pface->texturemins[1] << 16) >> miplevel)
- + pface->texinfo->vecs[1][3]*t;
-
- // PGM - changing flow speed for non-warping textures.
- if (pface->texinfo->flags & SURF_FLOWING)
- {
- if(pface->texinfo->flags & SURF_WARP)
- sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.25) - (int)(r_newrefdef.time * 0.25) ));
- else
- sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.77) - (int)(r_newrefdef.time * 0.77) ));
- }
- // PGM
-
-//
-// -1 (-epsilon) so we never wander off the edge of the texture
-//
- bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
- bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
-}
-
-
-/*
-==============
-D_BackgroundSurf
-
-The grey background filler seen when there is a hole in the map
-==============
-*/
-void D_BackgroundSurf (surf_t *s)
-{
-// set up a gradient for the background surface that places it
-// effectively at infinity distance from the viewpoint
- d_zistepu = 0;
- d_zistepv = 0;
- d_ziorigin = -0.9;
-
- D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFF);
- D_DrawZSpans (s->spans);
-}
-
-/*
-=================
-D_TurbulentSurf
-=================
-*/
-void D_TurbulentSurf (surf_t *s)
-{
- d_zistepu = s->d_zistepu;
- d_zistepv = s->d_zistepv;
- d_ziorigin = s->d_ziorigin;
-
- pface = s->msurf;
- miplevel = 0;
- cacheblock = pface->texinfo->image->pixels[0];
- cachewidth = 64;
-
- if (s->insubmodel)
- {
- // FIXME: we don't want to do all this for every polygon!
- // TODO: store once at start of frame
- currententity = s->entity; //FIXME: make this passed in to
- // R_RotateBmodel ()
- VectorSubtract (r_origin, currententity->origin,
- local_modelorg);
- TransformVector (local_modelorg, transformed_modelorg);
-
- R_RotateBmodel (); // FIXME: don't mess with the frustum,
- // make entity passed in
- }
-
- D_CalcGradients (pface);
-
-//============
-//PGM
- // textures that aren't warping are just flowing. Use NonTurbulent8 instead
- if(!(pface->texinfo->flags & SURF_WARP))
- NonTurbulent8 (s->spans);
- else
- Turbulent8 (s->spans);
-//PGM
-//============
-
- D_DrawZSpans (s->spans);
-
- if (s->insubmodel)
- {
- //
- // restore the old drawing state
- // FIXME: we don't want to do this every time!
- // TODO: speed up
- //
- currententity = NULL; // &r_worldentity;
- VectorCopy (world_transformed_modelorg,
- transformed_modelorg);
- VectorCopy (base_vpn, vpn);
- VectorCopy (base_vup, vup);
- VectorCopy (base_vright, vright);
- R_TransformFrustum ();
- }
-}
-
-/*
-==============
-D_SkySurf
-==============
-*/
-void D_SkySurf (surf_t *s)
-{
- pface = s->msurf;
- miplevel = 0;
- if (!pface->texinfo->image)
- return;
- cacheblock = pface->texinfo->image->pixels[0];
- cachewidth = 256;
-
- d_zistepu = s->d_zistepu;
- d_zistepv = s->d_zistepv;
- d_ziorigin = s->d_ziorigin;
-
- D_CalcGradients (pface);
-
- D_DrawSpans16 (s->spans);
-
-// set up a gradient for the background surface that places it
-// effectively at infinity distance from the viewpoint
- d_zistepu = 0;
- d_zistepv = 0;
- d_ziorigin = -0.9;
-
- D_DrawZSpans (s->spans);
-}
-
-/*
-==============
-D_SolidSurf
-
-Normal surface cached, texture mapped surface
-==============
-*/
-void D_SolidSurf (surf_t *s)
-{
- d_zistepu = s->d_zistepu;
- d_zistepv = s->d_zistepv;
- d_ziorigin = s->d_ziorigin;
-
- if (s->insubmodel)
- {
- // FIXME: we don't want to do all this for every polygon!
- // TODO: store once at start of frame
- currententity = s->entity; //FIXME: make this passed in to
- // R_RotateBmodel ()
- VectorSubtract (r_origin, currententity->origin, local_modelorg);
- TransformVector (local_modelorg, transformed_modelorg);
-
- R_RotateBmodel (); // FIXME: don't mess with the frustum,
- // make entity passed in
- }
- else
- currententity = &r_worldentity;
-
- pface = s->msurf;
-#if 1
- miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust);
-#else
- {
- float dot;
- float normal[3];
-
- if ( s->insubmodel )
- {
- VectorCopy( pface->plane->normal, normal );
-// TransformVector( pface->plane->normal, normal);
- dot = DotProduct( normal, vpn );
- }
- else
- {
- VectorCopy( pface->plane->normal, normal );
- dot = DotProduct( normal, vpn );
- }
-
- if ( pface->flags & SURF_PLANEBACK )
- dot = -dot;
-
- if ( dot > 0 )
- printf( "blah" );
-
- miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust);
- }
-#endif
-
-// FIXME: make this passed in to D_CacheSurface
- pcurrentcache = D_CacheSurface (pface, miplevel);
-
- cacheblock = (pixel_t *)pcurrentcache->data;
- cachewidth = pcurrentcache->width;
-
- D_CalcGradients (pface);
-
- D_DrawSpans16 (s->spans);
-
- D_DrawZSpans (s->spans);
-
- if (s->insubmodel)
- {
- //
- // restore the old drawing state
- // FIXME: we don't want to do this every time!
- // TODO: speed up
- //
- VectorCopy (world_transformed_modelorg,
- transformed_modelorg);
- VectorCopy (base_vpn, vpn);
- VectorCopy (base_vup, vup);
- VectorCopy (base_vright, vright);
- R_TransformFrustum ();
- currententity = NULL; //&r_worldentity;
- }
-}
-
-/*
-=============
-D_DrawflatSurfaces
-
-To allow developers to see the polygon carving of the world
-=============
-*/
-void D_DrawflatSurfaces (void)
-{
- surf_t *s;
-
- for (s = &surfaces[1] ; s<surface_p ; s++)
- {
- if (!s->spans)
- continue;
-
- d_zistepu = s->d_zistepu;
- d_zistepv = s->d_zistepv;
- d_ziorigin = s->d_ziorigin;
-
- // make a stable color for each surface by taking the low
- // bits of the msurface pointer
- D_FlatFillSurface (s, (int)s->msurf & 0xFF);
- D_DrawZSpans (s->spans);
- }
-}
-
-/*
-==============
-D_DrawSurfaces
-
-Rasterize all the span lists. Guaranteed zero overdraw.
-May be called more than once a frame if the surf list overflows (higher res)
-==============
-*/
-void D_DrawSurfaces (void)
-{
- surf_t *s;
-
-// currententity = NULL; //&r_worldentity;
- VectorSubtract (r_origin, vec3_origin, modelorg);
- TransformVector (modelorg, transformed_modelorg);
- VectorCopy (transformed_modelorg, world_transformed_modelorg);
-
- if (!sw_drawflat->value)
- {
- for (s = &surfaces[1] ; s<surface_p ; s++)
- {
- if (!s->spans)
- continue;
-
- r_drawnpolycount++;
-
- if (! (s->flags & (SURF_DRAWSKYBOX|SURF_DRAWBACKGROUND|SURF_DRAWTURB) ) )
- D_SolidSurf (s);
- else if (s->flags & SURF_DRAWSKYBOX)
- D_SkySurf (s);
- else if (s->flags & SURF_DRAWBACKGROUND)
- D_BackgroundSurf (s);
- else if (s->flags & SURF_DRAWTURB)
- D_TurbulentSurf (s);
- }
- }
- else
- D_DrawflatSurfaces ();
-
- currententity = NULL; //&r_worldentity;
- VectorSubtract (r_origin, vec3_origin, modelorg);
- R_TransformFrustum ();
-}
-
--- a/ref_soft/r_image.c
+++ /dev/null
@@ -1,617 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "r_local.h"
-
-
-#define MAX_RIMAGES 1024
-image_t r_images[MAX_RIMAGES];
-int numr_images;
-
-
-/*
-===============
-R_ImageList_f
-===============
-*/
-void R_ImageList_f (void)
-{
- int i;
- image_t *image;
- int texels;
-
- ri.Con_Printf (PRINT_ALL, "------------------\n");
- texels = 0;
-
- for (i=0, image=r_images ; i<numr_images ; i++, image++)
- {
- if (image->registration_sequence <= 0)
- continue;
- texels += image->width*image->height;
- switch (image->type)
- {
- case it_skin:
- ri.Con_Printf (PRINT_ALL, "M");
- break;
- case it_sprite:
- ri.Con_Printf (PRINT_ALL, "S");
- break;
- case it_wall:
- ri.Con_Printf (PRINT_ALL, "W");
- break;
- case it_pic:
- ri.Con_Printf (PRINT_ALL, "P");
- break;
- default:
- ri.Con_Printf (PRINT_ALL, " ");
- break;
- }
-
- ri.Con_Printf (PRINT_ALL, " %3i %3i : %s\n",
- image->width, image->height, image->name);
- }
- ri.Con_Printf (PRINT_ALL, "Total texel count: %i\n", texels);
-}
-
-
-/*
-=================================================================
-
-PCX LOADING
-
-=================================================================
-*/
-
-/*
-==============
-LoadPCX
-==============
-*/
-void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
-{
- byte *raw;
- pcx_t *pcx;
- int x, y;
- int len;
- int dataByte, runLength;
- byte *out, *pix;
-
- *pic = NULL;
-
- //
- // load the file
- //
- len = ri.FS_LoadFile (filename, (void **)&raw);
- if (!raw)
- {
- ri.Con_Printf (PRINT_DEVELOPER, "Bad pcx file %s\n", filename);
- return;
- }
-
- //
- // parse the PCX file
- //
- pcx = (pcx_t *)raw;
-
- pcx->xmin = LittleShort(pcx->xmin);
- pcx->ymin = LittleShort(pcx->ymin);
- pcx->xmax = LittleShort(pcx->xmax);
- pcx->ymax = LittleShort(pcx->ymax);
- pcx->hres = LittleShort(pcx->hres);
- pcx->vres = LittleShort(pcx->vres);
- pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
- pcx->palette_type = LittleShort(pcx->palette_type);
-
- raw = &pcx->data;
-
- if (pcx->manufacturer != 0x0a
- || pcx->version != 5
- || pcx->encoding != 1
- || pcx->bits_per_pixel != 8
- || pcx->xmax >= 640
- || pcx->ymax >= 480)
- {
- ri.Con_Printf (PRINT_ALL, "Bad pcx file %s\n", filename);
- return;
- }
-
- out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
-
- *pic = out;
-
- pix = out;
-
- if (palette)
- {
- *palette = malloc(768);
- memcpy (*palette, (byte *)pcx + len - 768, 768);
- }
-
- if (width)
- *width = pcx->xmax+1;
- if (height)
- *height = pcx->ymax+1;
-
- for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
- {
- for (x=0 ; x<=pcx->xmax ; )
- {
- dataByte = *raw++;
-
- if((dataByte & 0xC0) == 0xC0)
- {
- runLength = dataByte & 0x3F;
- dataByte = *raw++;
- }
- else
- runLength = 1;
-
- while(runLength-- > 0)
- pix[x++] = dataByte;
- }
-
- }
-
- if ( raw - (byte *)pcx > len)
- {
- ri.Con_Printf (PRINT_DEVELOPER, "PCX file %s was malformed", filename);
- free (*pic);
- *pic = NULL;
- }
-
- ri.FS_FreeFile (pcx);
-}
-
-/*
-=========================================================
-
-TARGA LOADING
-
-=========================================================
-*/
-
-typedef struct _TargaHeader {
- unsigned char id_length, colormap_type, image_type;
- unsigned short colormap_index, colormap_length;
- unsigned char colormap_size;
- unsigned short x_origin, y_origin, width, height;
- unsigned char pixel_size, attributes;
-} TargaHeader;
-
-
-/*
-=============
-LoadTGA
-=============
-*/
-void LoadTGA (char *name, byte **pic, int *width, int *height)
-{
- int columns, rows, numPixels;
- byte *pixbuf;
- int row, column;
- byte *buf_p;
- byte *buffer;
- int length;
- TargaHeader targa_header;
- byte *targa_rgba;
-
- *pic = NULL;
-
- //
- // load the file
- //
- length = ri.FS_LoadFile (name, (void **)&buffer);
- if (!buffer)
- {
- ri.Con_Printf (PRINT_DEVELOPER, "Bad tga file %s\n", name);
- return;
- }
-
- buf_p = buffer;
-
- targa_header.id_length = *buf_p++;
- targa_header.colormap_type = *buf_p++;
- targa_header.image_type = *buf_p++;
-
- targa_header.colormap_index = LittleShort ( *((short *)buf_p) );
- buf_p+=2;
- targa_header.colormap_length = LittleShort ( *((short *)buf_p) );
- buf_p+=2;
- targa_header.colormap_size = *buf_p++;
- targa_header.x_origin = LittleShort ( *((short *)buf_p) );
- buf_p+=2;
- targa_header.y_origin = LittleShort ( *((short *)buf_p) );
- buf_p+=2;
- targa_header.width = LittleShort ( *((short *)buf_p) );
- buf_p+=2;
- targa_header.height = LittleShort ( *((short *)buf_p) );
- buf_p+=2;
- targa_header.pixel_size = *buf_p++;
- targa_header.attributes = *buf_p++;
-
- if (targa_header.image_type!=2
- && targa_header.image_type!=10)
- ri.Sys_Error (ERR_DROP, "LoadTGA: Only type 2 and 10 targa RGB images supported\n");
-
- if (targa_header.colormap_type !=0
- || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
- ri.Sys_Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
-
- columns = targa_header.width;
- rows = targa_header.height;
- numPixels = columns * rows;
-
- if (width)
- *width = columns;
- if (height)
- *height = rows;
-
- targa_rgba = malloc (numPixels*4);
- *pic = targa_rgba;
-
- if (targa_header.id_length != 0)
- buf_p += targa_header.id_length; // skip TARGA image comment
-
- if (targa_header.image_type==2) { // Uncompressed, RGB images
- for(row=rows-1; row>=0; row--) {
- pixbuf = targa_rgba + row*columns*4;
- for(column=0; column<columns; column++) {
- unsigned char red,green,blue,alphabyte;
- switch (targa_header.pixel_size) {
- case 24:
-
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = 255;
- break;
- case 32:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- alphabyte = *buf_p++;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = alphabyte;
- break;
- }
- }
- }
- }
- else if (targa_header.image_type==10) { // Runlength encoded RGB images
- unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
- for(row=rows-1; row>=0; row--) {
- pixbuf = targa_rgba + row*columns*4;
- for(column=0; column<columns; ) {
- packetHeader= *buf_p++;
- packetSize = 1 + (packetHeader & 0x7f);
- if (packetHeader & 0x80) { // run-length packet
- switch (targa_header.pixel_size) {
- case 24:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- alphabyte = 255;
- break;
- case 32:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- alphabyte = *buf_p++;
- break;
- }
-
- for(j=0;j<packetSize;j++) {
- *pixbuf++=red;
- *pixbuf++=green;
- *pixbuf++=blue;
- *pixbuf++=alphabyte;
- column++;
- if (column==columns) { // run spans across rows
- column=0;
- if (row>0)
- row--;
- else
- goto breakOut;
- pixbuf = targa_rgba + row*columns*4;
- }
- }
- }
- else { // non run-length packet
- for(j=0;j<packetSize;j++) {
- switch (targa_header.pixel_size) {
- case 24:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = 255;
- break;
- case 32:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- alphabyte = *buf_p++;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = alphabyte;
- break;
- }
- column++;
- if (column==columns) { // pixel packet run spans across rows
- column=0;
- if (row>0)
- row--;
- else
- goto breakOut;
- pixbuf = targa_rgba + row*columns*4;
- }
- }
- }
- }
- breakOut:;
- }
- }
-
- ri.FS_FreeFile (buffer);
-}
-
-
-//=======================================================
-
-image_t *R_FindFreeImage (void)
-{
- image_t *image;
- int i;
-
- // find a free image_t
- for (i=0, image=r_images ; i<numr_images ; i++,image++)
- {
- if (!image->registration_sequence)
- break;
- }
- if (i == numr_images)
- {
- if (numr_images == MAX_RIMAGES)
- ri.Sys_Error (ERR_DROP, "MAX_RIMAGES");
- numr_images++;
- }
- image = &r_images[i];
-
- return image;
-}
-
-/*
-================
-GL_LoadPic
-
-================
-*/
-image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type)
-{
- image_t *image;
- int i, c, b;
-
- image = R_FindFreeImage ();
- if (strlen(name) >= sizeof(image->name))
- ri.Sys_Error (ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
- strcpy (image->name, name);
- image->registration_sequence = registration_sequence;
-
- image->width = width;
- image->height = height;
- image->type = type;
-
- c = width*height;
- image->pixels[0] = malloc (c);
- image->transparent = false;
- for (i=0 ; i<c ; i++)
- {
- b = pic[i];
- if (b == 255)
- image->transparent = true;
- image->pixels[0][i] = b;
- }
-
- return image;
-}
-
-/*
-================
-R_LoadWal
-================
-*/
-image_t *R_LoadWal (char *name)
-{
- miptex_t *mt;
- int ofs;
- image_t *image;
- int size;
-
- ri.FS_LoadFile (name, (void **)&mt);
- if (!mt)
- {
- ri.Con_Printf (PRINT_ALL, "R_LoadWal: can't load %s\n", name);
- return r_notexture_mip;
- }
-
- image = R_FindFreeImage ();
- strcpy (image->name, name);
- image->width = LittleLong (mt->width);
- image->height = LittleLong (mt->height);
- image->type = it_wall;
- image->registration_sequence = registration_sequence;
-
- size = image->width*image->height * (256+64+16+4)/256;
- image->pixels[0] = malloc (size);
- image->pixels[1] = image->pixels[0] + image->width*image->height;
- image->pixels[2] = image->pixels[1] + image->width*image->height/4;
- image->pixels[3] = image->pixels[2] + image->width*image->height/16;
-
- ofs = LittleLong (mt->offsets[0]);
- memcpy ( image->pixels[0], (byte *)mt + ofs, size);
-
- ri.FS_FreeFile ((void *)mt);
-
- return image;
-}
-
-
-/*
-===============
-R_FindImage
-
-Finds or loads the given image
-===============
-*/
-image_t *R_FindImage (char *name, imagetype_t type)
-{
- image_t *image;
- int i, len;
- byte *pic, *palette;
- int width, height;
-
- if (!name)
- return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: NULL name");
- len = strlen(name);
- if (len<5)
- return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad name: %s", name);
-
- // look for it
- for (i=0, image=r_images ; i<numr_images ; i++,image++)
- {
- if (!strcmp(name, image->name))
- {
- image->registration_sequence = registration_sequence;
- return image;
- }
- }
-
- //
- // load the pic from disk
- //
- pic = NULL;
- palette = NULL;
- if (!strcmp(name+len-4, ".pcx"))
- {
- LoadPCX (name, &pic, &palette, &width, &height);
- if (!pic)
- return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s", name);
- image = GL_LoadPic (name, pic, width, height, type);
- }
- else if (!strcmp(name+len-4, ".wal"))
- {
- image = R_LoadWal (name);
- }
- else if (!strcmp(name+len-4, ".tga"))
- return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s in software renderer", name);
- else
- return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad extension on: %s", name);
-
- if (pic)
- free(pic);
- if (palette)
- free(palette);
-
- return image;
-}
-
-
-
-/*
-===============
-R_RegisterSkin
-===============
-*/
-struct image_s *R_RegisterSkin (char *name)
-{
- return R_FindImage (name, it_skin);
-}
-
-
-/*
-================
-R_FreeUnusedImages
-
-Any image that was not touched on this registration sequence
-will be freed.
-================
-*/
-void R_FreeUnusedImages (void)
-{
- int i;
- image_t *image;
-
- for (i=0, image=r_images ; i<numr_images ; i++, image++)
- {
- if (image->registration_sequence == registration_sequence)
- {
- Com_PageInMemory ((byte *)image->pixels[0], image->width*image->height);
- continue; // used this sequence
- }
- if (!image->registration_sequence)
- continue; // free texture
- if (image->type == it_pic)
- continue; // don't free pics
- // free it
- free (image->pixels[0]); // the other mip levels just follow
- memset (image, 0, sizeof(*image));
- }
-}
-
-
-
-/*
-===============
-R_InitImages
-===============
-*/
-void R_InitImages (void)
-{
- registration_sequence = 1;
-}
-
-/*
-===============
-R_ShutdownImages
-===============
-*/
-void R_ShutdownImages (void)
-{
- int i;
- image_t *image;
-
- for (i=0, image=r_images ; i<numr_images ; i++, image++)
- {
- if (!image->registration_sequence)
- continue; // free texture
- // free it
- free (image->pixels[0]); // the other mip levels just follow
- memset (image, 0, sizeof(*image));
- }
-}
-
--- a/ref_soft/r_light.c
+++ /dev/null
@@ -1,442 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// r_light.c
-
-#include "r_local.h"
-
-int r_dlightframecount;
-
-
-/*
-=============================================================================
-
-DYNAMIC LIGHTS
-
-=============================================================================
-*/
-
-/*
-=============
-R_MarkLights
-=============
-*/
-void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
-{
- mplane_t *splitplane;
- float dist;
- msurface_t *surf;
- int i;
-
- if (node->contents != -1)
- return;
-
- splitplane = node->plane;
- dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
-
-//=====
-//PGM
- i=light->intensity;
- if(i<0)
- i=-i;
-//PGM
-//=====
-
- if (dist > i) // PGM (dist > light->intensity)
- {
- R_MarkLights (light, bit, node->children[0]);
- return;
- }
- if (dist < -i) // PGM (dist < -light->intensity)
- {
- R_MarkLights (light, bit, node->children[1]);
- return;
- }
-
-// mark the polygons
- surf = r_worldmodel->surfaces + node->firstsurface;
- for (i=0 ; i<node->numsurfaces ; i++, surf++)
- {
- if (surf->dlightframe != r_dlightframecount)
- {
- surf->dlightbits = 0;
- surf->dlightframe = r_dlightframecount;
- }
- surf->dlightbits |= bit;
- }
-
- R_MarkLights (light, bit, node->children[0]);
- R_MarkLights (light, bit, node->children[1]);
-}
-
-
-/*
-=============
-R_PushDlights
-=============
-*/
-void R_PushDlights (model_t *model)
-{
- int i;
- dlight_t *l;
-
- r_dlightframecount = r_framecount;
- for (i=0, l = r_newrefdef.dlights ; i<r_newrefdef.num_dlights ; i++, l++)
- {
- R_MarkLights ( l, 1<<i,
- model->nodes + model->firstnode);
- }
-}
-
-
-/*
-=============================================================================
-
-LIGHT SAMPLING
-
-=============================================================================
-*/
-
-vec3_t pointcolor;
-mplane_t *lightplane; // used as shadow plane
-vec3_t lightspot;
-
-int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
-{
- float front, back, frac;
- int side;
- mplane_t *plane;
- vec3_t mid;
- msurface_t *surf;
- int s, t, ds, dt;
- int i;
- mtexinfo_t *tex;
- byte *lightmap;
- float *scales;
- int maps;
- float samp;
- int r;
-
- if (node->contents != -1)
- return -1; // didn't hit anything
-
-// calculate mid point
-
-// FIXME: optimize for axial
- plane = node->plane;
- front = DotProduct (start, plane->normal) - plane->dist;
- back = DotProduct (end, plane->normal) - plane->dist;
- side = front < 0;
-
- if ( (back < 0) == side)
- return RecursiveLightPoint (node->children[side], start, end);
-
- frac = front / (front-back);
- mid[0] = start[0] + (end[0] - start[0])*frac;
- mid[1] = start[1] + (end[1] - start[1])*frac;
- mid[2] = start[2] + (end[2] - start[2])*frac;
- if (plane->type < 3) // axial planes
- mid[plane->type] = plane->dist;
-
-// go down front side
- r = RecursiveLightPoint (node->children[side], start, mid);
- if (r >= 0)
- return r; // hit something
-
- if ( (back < 0) == side )
- return -1; // didn't hit anuthing
-
-// check for impact on this node
- VectorCopy (mid, lightspot);
- lightplane = plane;
-
- surf = r_worldmodel->surfaces + node->firstsurface;
- for (i=0 ; i<node->numsurfaces ; i++, surf++)
- {
- if (surf->flags&(SURF_DRAWTURB|SURF_DRAWSKY))
- continue; // no lightmaps
-
- tex = surf->texinfo;
-
- s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
- t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];
- if (s < surf->texturemins[0] ||
- t < surf->texturemins[1])
- continue;
-
- ds = s - surf->texturemins[0];
- dt = t - surf->texturemins[1];
-
- if ( ds > surf->extents[0] || dt > surf->extents[1] )
- continue;
-
- if (!surf->samples)
- return 0;
-
- ds >>= 4;
- dt >>= 4;
-
- lightmap = surf->samples;
- VectorCopy (vec3_origin, pointcolor);
- if (lightmap)
- {
- lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
-
- for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
- maps++)
- {
- samp = *lightmap * /* 0.5 * */ (1.0/255); // adjust for gl scale
- scales = r_newrefdef.lightstyles[surf->styles[maps]].rgb;
- VectorMA (pointcolor, samp, scales, pointcolor);
- lightmap += ((surf->extents[0]>>4)+1) *
- ((surf->extents[1]>>4)+1);
- }
- }
-
- return 1;
- }
-
-// go down back side
- return RecursiveLightPoint (node->children[!side], mid, end);
-}
-
-/*
-===============
-R_LightPoint
-===============
-*/
-void R_LightPoint (vec3_t p, vec3_t color)
-{
- vec3_t end;
- float r;
- int lnum;
- dlight_t *dl;
- float light;
- vec3_t dist;
- float add;
-
- if (!r_worldmodel->lightdata)
- {
- color[0] = color[1] = color[2] = 1.0;
- return;
- }
-
- end[0] = p[0];
- end[1] = p[1];
- end[2] = p[2] - 2048;
-
- r = RecursiveLightPoint (r_worldmodel->nodes, p, end);
-
- if (r == -1)
- {
- VectorCopy (vec3_origin, color);
- }
- else
- {
- VectorCopy (pointcolor, color);
- }
-
- //
- // add dynamic lights
- //
- light = 0;
- for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
- {
- dl = &r_newrefdef.dlights[lnum];
- VectorSubtract (currententity->origin,
- dl->origin,
- dist);
- add = dl->intensity - VectorLength(dist);
- add *= (1.0/256);
- if (add > 0)
- {
- VectorMA (color, add, dl->color, color);
- }
- }
-}
-
-//===================================================================
-
-
-unsigned blocklights[1024]; // allow some very large lightmaps
-
-/*
-===============
-R_AddDynamicLights
-===============
-*/
-void R_AddDynamicLights (void)
-{
- msurface_t *surf;
- int lnum;
- int sd, td;
- float dist, rad, minlight;
- vec3_t impact, local;
- int s, t;
- int i;
- int smax, tmax;
- mtexinfo_t *tex;
- dlight_t *dl;
- int negativeLight; //PGM
-
- surf = r_drawsurf.surf;
- smax = (surf->extents[0]>>4)+1;
- tmax = (surf->extents[1]>>4)+1;
- tex = surf->texinfo;
-
- for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
- {
- if ( !(surf->dlightbits & (1<<lnum) ) )
- continue; // not lit by this light
-
- dl = &r_newrefdef.dlights[lnum];
- rad = dl->intensity;
-
-//=====
-//PGM
- negativeLight = 0;
- if(rad < 0)
- {
- negativeLight = 1;
- rad = -rad;
- }
-//PGM
-//=====
-
- dist = DotProduct (dl->origin, surf->plane->normal) -
- surf->plane->dist;
- rad -= fabs(dist);
- minlight = 32; // dl->minlight;
- if (rad < minlight)
- continue;
- minlight = rad - minlight;
-
- for (i=0 ; i<3 ; i++)
- {
- impact[i] = dl->origin[i] -
- surf->plane->normal[i]*dist;
- }
-
- local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
- local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
-
- local[0] -= surf->texturemins[0];
- local[1] -= surf->texturemins[1];
-
- for (t = 0 ; t<tmax ; t++)
- {
- td = local[1] - t*16;
- if (td < 0)
- td = -td;
- for (s=0 ; s<smax ; s++)
- {
- sd = local[0] - s*16;
- if (sd < 0)
- sd = -sd;
- if (sd > td)
- dist = sd + (td>>1);
- else
- dist = td + (sd>>1);
-//====
-//PGM
- if(!negativeLight)
- {
- if (dist < minlight)
- blocklights[t*smax + s] += (rad - dist)*256;
- }
- else
- {
- if (dist < minlight)
- blocklights[t*smax + s] -= (rad - dist)*256;
- if(blocklights[t*smax + s] < minlight)
- blocklights[t*smax + s] = minlight;
- }
-//PGM
-//====
- }
- }
- }
-}
-
-/*
-===============
-R_BuildLightMap
-
-Combine and scale multiple lightmaps into the 8.8 format in blocklights
-===============
-*/
-void R_BuildLightMap (void)
-{
- int smax, tmax;
- int t;
- int i, size;
- byte *lightmap;
- unsigned scale;
- int maps;
- msurface_t *surf;
-
- surf = r_drawsurf.surf;
-
- smax = (surf->extents[0]>>4)+1;
- tmax = (surf->extents[1]>>4)+1;
- size = smax*tmax;
-
- if (r_fullbright->value || !r_worldmodel->lightdata)
- {
- for (i=0 ; i<size ; i++)
- blocklights[i] = 0;
- return;
- }
-
-// clear to no light
- for (i=0 ; i<size ; i++)
- blocklights[i] = 0;
-
-
-// add all the lightmaps
- lightmap = surf->samples;
- if (lightmap)
- for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
- maps++)
- {
- scale = r_drawsurf.lightadj[maps]; // 8.8 fraction
- for (i=0 ; i<size ; i++)
- blocklights[i] += lightmap[i] * scale;
- lightmap += size; // skip to next lightmap
- }
-
-// add all the dynamic lights
- if (surf->dlightframe == r_framecount)
- R_AddDynamicLights ();
-
-// bound, invert, and shift
- for (i=0 ; i<size ; i++)
- {
- t = (int)blocklights[i];
- if (t < 0)
- t = 0;
- t = (255*256 - t) >> (8 - VID_CBITS);
-
- if (t < (1 << 6))
- t = (1 << 6);
-
- blocklights[i] = t;
- }
-}
-
--- a/ref_soft/r_local.h
+++ /dev/null
@@ -1,849 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <stdarg.h>
-
-#include "../client/ref.h"
-
-#define REF_VERSION "SOFT 0.01"
-
-// up / down
-#define PITCH 0
-
-// left / right
-#define YAW 1
-
-// fall over
-#define ROLL 2
-
-
-/*
-
- skins will be outline flood filled and mip mapped
- pics and sprites with alpha will be outline flood filled
- pic won't be mip mapped
-
- model skin
- sprite frame
- wall texture
- pic
-
-*/
-
-typedef enum
-{
- it_skin,
- it_sprite,
- it_wall,
- it_pic,
- it_sky
-} imagetype_t;
-
-typedef struct image_s
-{
- char name[MAX_QPATH]; // game path, including extension
- imagetype_t type;
- int width, height;
- qboolean transparent; // true if any 255 pixels in image
- int registration_sequence; // 0 = free
- byte *pixels[4]; // mip levels
-} image_t;
-
-
-//===================================================================
-
-typedef unsigned char pixel_t;
-
-typedef struct vrect_s
-{
- int x,y,width,height;
- struct vrect_s *pnext;
-} vrect_t;
-
-typedef struct
-{
- pixel_t *buffer; // invisible buffer
- pixel_t *colormap; // 256 * VID_GRADES size
- pixel_t *alphamap; // 256 * 256 translucency map
- int rowbytes; // may be > width if displayed in a window
- // can be negative for stupid dibs
- int width;
- int height;
-} viddef_t;
-
-typedef enum
-{
- rserr_ok,
-
- rserr_invalid_fullscreen,
- rserr_invalid_mode,
-
- rserr_unknown
-} rserr_t;
-
-extern viddef_t vid;
-
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
-typedef struct
-{
- vrect_t vrect; // subwindow in video for refresh
- // FIXME: not need vrect next field here?
- vrect_t aliasvrect; // scaled Alias version
- int vrectright, vrectbottom; // right & bottom screen coords
- int aliasvrectright, aliasvrectbottom; // scaled Alias versions
- float vrectrightedge; // rightmost right edge we care about,
- // for use in edge list
- float fvrectx, fvrecty; // for floating-point compares
- float fvrectx_adj, fvrecty_adj; // left and top edges, for clamping
- int vrect_x_adj_shift20; // (vrect.x + 0.5 - epsilon) << 20
- int vrectright_adj_shift20; // (vrectright + 0.5 - epsilon) << 20
- float fvrectright_adj, fvrectbottom_adj;
- // right and bottom edges, for clamping
- float fvrectright; // rightmost edge, for Alias clamping
- float fvrectbottom; // bottommost edge, for Alias clamping
- float horizontalFieldOfView; // at Z = 1.0, this many X is visible
- // 2.0 = 90 degrees
- float xOrigin; // should probably always be 0.5
- float yOrigin; // between be around 0.3 to 0.5
-
- vec3_t vieworg;
- vec3_t viewangles;
-
- int ambientlight;
-} oldrefdef_t;
-
-extern oldrefdef_t r_refdef;
-
-#include "r_model.h"
-
-#define CACHE_SIZE 32
-
-/*
-====================================================
-
- CONSTANTS
-
-====================================================
-*/
-
-#define VID_CBITS 6
-#define VID_GRADES (1 << VID_CBITS)
-
-
-// r_shared.h: general refresh-related stuff shared between the refresh and the
-// driver
-
-
-#define MAXVERTS 64 // max points in a surface polygon
-#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate
- // polygon (while processing)
-// !!! if this is changed, it must be changed in d_ifacea.h too !!!
-#define MAXHEIGHT 1200
-#define MAXWIDTH 1600
-
-#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to
- // be farther away than anything in
- // the scene
-
-
-// d_iface.h: interface header file for rasterization driver modules
-
-#define WARP_WIDTH 320
-#define WARP_HEIGHT 240
-
-#define MAX_LBM_HEIGHT 480
-
-
-#define PARTICLE_Z_CLIP 8.0
-
-// !!! must be kept the same as in quakeasm.h !!!
-#define TRANSPARENT_COLOR 0xFF
-
-
-// !!! if this is changed, it must be changed in d_ifacea.h too !!!
-#define TURB_TEX_SIZE 64 // base turbulent texture size
-
-// !!! if this is changed, it must be changed in d_ifacea.h too !!!
-#define CYCLE 128 // turbulent cycle size
-
-#define SCANBUFFERPAD 0x1000
-
-#define DS_SPAN_LIST_END -128
-
-#define NUMSTACKEDGES 2000
-#define MINEDGES NUMSTACKEDGES
-#define NUMSTACKSURFACES 1000
-#define MINSURFACES NUMSTACKSURFACES
-#define MAXSPANS 3000
-
-// flags in finalvert_t.flags
-#define ALIAS_LEFT_CLIP 0x0001
-#define ALIAS_TOP_CLIP 0x0002
-#define ALIAS_RIGHT_CLIP 0x0004
-#define ALIAS_BOTTOM_CLIP 0x0008
-#define ALIAS_Z_CLIP 0x0010
-#define ALIAS_XY_CLIP_MASK 0x000F
-
-#define SURFCACHE_SIZE_AT_320X240 1024*768
-
-#define BMODEL_FULLY_CLIPPED 0x10 // value returned by R_BmodelCheckBBox ()
- // if bbox is trivially rejected
-
-#define XCENTERING (1.0 / 2.0)
-#define YCENTERING (1.0 / 2.0)
-
-#define CLIP_EPSILON 0.001
-
-#define BACKFACE_EPSILON 0.01
-
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
-#define NEAR_CLIP 0.01
-
-
-#define MAXALIASVERTS 2000 // TODO: tune this
-#define ALIAS_Z_CLIP_PLANE 4
-
-// turbulence stuff
-
-#define AMP 8*0x10000
-#define AMP2 3
-#define SPEED 20
-
-
-/*
-====================================================
-
-TYPES
-
-====================================================
-*/
-
-typedef struct
-{
- float u, v;
- float s, t;
- float zi;
-} emitpoint_t;
-
-/*
-** if you change this structure be sure to change the #defines
-** listed after it!
-*/
-#define SMALL_FINALVERT 0
-
-#if SMALL_FINALVERT
-
-typedef struct finalvert_s {
- short u, v, s, t;
- int l;
- int zi;
- int flags;
- float xyz[3]; // eye space
-} finalvert_t;
-
-#define FINALVERT_V0 0
-#define FINALVERT_V1 2
-#define FINALVERT_V2 4
-#define FINALVERT_V3 6
-#define FINALVERT_V4 8
-#define FINALVERT_V5 12
-#define FINALVERT_FLAGS 16
-#define FINALVERT_X 20
-#define FINALVERT_Y 24
-#define FINALVERT_Z 28
-#define FINALVERT_SIZE 32
-
-#else
-
-typedef struct finalvert_s {
- int u, v, s, t;
- int l;
- int zi;
- int flags;
- float xyz[3]; // eye space
-} finalvert_t;
-
-#define FINALVERT_V0 0
-#define FINALVERT_V1 4
-#define FINALVERT_V2 8
-#define FINALVERT_V3 12
-#define FINALVERT_V4 16
-#define FINALVERT_V5 20
-#define FINALVERT_FLAGS 24
-#define FINALVERT_X 28
-#define FINALVERT_Y 32
-#define FINALVERT_Z 36
-#define FINALVERT_SIZE 40
-
-#endif
-
-typedef struct
-{
- void *pskin;
- int pskindesc;
- int skinwidth;
- int skinheight;
- dtriangle_t *ptriangles;
- finalvert_t *pfinalverts;
- int numtriangles;
- int drawtype;
- int seamfixupX16;
- qboolean do_vis_thresh;
- int vis_thresh;
-} affinetridesc_t;
-
-typedef struct
-{
- byte *surfdat; // destination for generated surface
- int rowbytes; // destination logical width in bytes
- msurface_t *surf; // description for surface to generate
- fixed8_t lightadj[MAXLIGHTMAPS];
- // adjust for lightmap levels for dynamic lighting
- image_t *image;
- int surfmip; // mipmapped ratio of surface texels / world pixels
- int surfwidth; // in mipmapped texels
- int surfheight; // in mipmapped texels
-} drawsurf_t;
-
-
-
-typedef struct {
- int ambientlight;
- int shadelight;
- float *plightvec;
-} alight_t;
-
-// clipped bmodel edges
-
-typedef struct bedge_s
-{
- mvertex_t *v[2];
- struct bedge_s *pnext;
-} bedge_t;
-
-
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
-typedef struct clipplane_s
-{
- vec3_t normal;
- float dist;
- struct clipplane_s *next;
- byte leftedge;
- byte rightedge;
- byte reserved[2];
-} clipplane_t;
-
-
-typedef struct surfcache_s
-{
- struct surfcache_s *next;
- struct surfcache_s **owner; // NULL is an empty chunk of memory
- int lightadj[MAXLIGHTMAPS]; // checked for strobe flush
- int dlight;
- int size; // including header
- unsigned width;
- unsigned height; // DEBUG only needed for debug
- float mipscale;
- image_t *image;
- byte data[4]; // width*height elements
-} surfcache_t;
-
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
-typedef struct espan_s
-{
- int u, v, count;
- struct espan_s *pnext;
-} espan_t;
-
-// used by the polygon drawer (R_POLY.C) and sprite setup code (R_SPRITE.C)
-typedef struct
-{
- int nump;
- emitpoint_t *pverts;
- byte *pixels; // image
- int pixel_width; // image width
- int pixel_height; // image height
- vec3_t vup, vright, vpn; // in worldspace, for plane eq
- float dist;
- float s_offset, t_offset;
- float viewer_position[3];
- void (*drawspanlet)( void );
- int stipple_parity;
-} polydesc_t;
-
-// FIXME: compress, make a union if that will help
-// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte
-typedef struct surf_s
-{
- struct surf_s *next; // active surface stack in r_edge.c
- struct surf_s *prev; // used in r_edge.c for active surf stack
- struct espan_s *spans; // pointer to linked list of spans to draw
- int key; // sorting key (BSP order)
- int last_u; // set during tracing
- int spanstate; // 0 = not in span
- // 1 = in span
- // -1 = in inverted span (end before
- // start)
- int flags; // currentface flags
- msurface_t *msurf;
- entity_t *entity;
- float nearzi; // nearest 1/z on surface, for mipmapping
- qboolean insubmodel;
- float d_ziorigin, d_zistepu, d_zistepv;
-
- int pad[2]; // to 64 bytes
-} surf_t;
-
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
-typedef struct edge_s
-{
- fixed16_t u;
- fixed16_t u_step;
- struct edge_s *prev, *next;
- unsigned short surfs[2];
- struct edge_s *nextremove;
- float nearzi;
- medge_t *owner;
-} edge_t;
-
-
-/*
-====================================================
-
-VARS
-
-====================================================
-*/
-
-extern int d_spanpixcount;
-extern int r_framecount; // sequence # of current frame since Quake
- // started
-extern float r_aliasuvscale; // scale-up factor for screen u and v
- // on Alias vertices passed to driver
-extern qboolean r_dowarp;
-
-extern affinetridesc_t r_affinetridesc;
-
-extern vec3_t r_pright, r_pup, r_ppn;
-
-void D_DrawSurfaces (void);
-void R_DrawParticle( void );
-void D_ViewChanged (void);
-void D_WarpScreen (void);
-void R_PolysetUpdateTables (void);
-
-extern void *acolormap; // FIXME: should go away
-
-//=======================================================================//
-
-// callbacks to Quake
-
-extern drawsurf_t r_drawsurf;
-
-void R_DrawSurface (void);
-
-extern int c_surf;
-
-extern byte r_warpbuffer[WARP_WIDTH * WARP_HEIGHT];
-
-
-
-
-extern float scale_for_mip;
-
-extern qboolean d_roverwrapped;
-extern surfcache_t *sc_rover;
-extern surfcache_t *d_initial_rover;
-
-extern float d_sdivzstepu, d_tdivzstepu, d_zistepu;
-extern float d_sdivzstepv, d_tdivzstepv, d_zistepv;
-extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
-
-extern fixed16_t sadjust, tadjust;
-extern fixed16_t bbextents, bbextentt;
-
-
-void D_DrawSpans16 (espan_t *pspans);
-void D_DrawZSpans (espan_t *pspans);
-void Turbulent8 (espan_t *pspan);
-void NonTurbulent8 (espan_t *pspan); //PGM
-
-surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel);
-
-extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
-
-extern int d_pix_min, d_pix_max, d_pix_shift;
-
-extern pixel_t *d_viewbuffer;
-extern short *d_pzbuffer;
-extern unsigned int d_zrowbytes, d_zwidth;
-extern short *zspantable[MAXHEIGHT];
-extern int d_scantable[MAXHEIGHT];
-
-extern int d_minmip;
-extern float d_scalemip[3];
-
-//===================================================================
-
-extern int cachewidth;
-extern pixel_t *cacheblock;
-extern int r_screenwidth;
-
-extern int r_drawnpolycount;
-
-extern int sintable[1280];
-extern int intsintable[1280];
-extern int blanktable[1280]; // PGM
-
-extern vec3_t vup, base_vup;
-extern vec3_t vpn, base_vpn;
-extern vec3_t vright, base_vright;
-
-extern surf_t *surfaces, *surface_p, *surf_max;
-
-// surfaces are generated in back to front order by the bsp, so if a surf
-// pointer is greater than another one, it should be drawn in front
-// surfaces[1] is the background, and is used as the active surface stack.
-// surfaces[0] is a dummy, because index 0 is used to indicate no surface
-// attached to an edge_t
-
-//===================================================================
-
-extern vec3_t sxformaxis[4]; // s axis transformed into viewspace
-extern vec3_t txformaxis[4]; // t axis transformed into viewspac
-
-extern float xcenter, ycenter;
-extern float xscale, yscale;
-extern float xscaleinv, yscaleinv;
-extern float xscaleshrink, yscaleshrink;
-
-extern void TransformVector (vec3_t in, vec3_t out);
-extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
- fixed8_t endvertu, fixed8_t endvertv);
-
-extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
-
-//===========================================================================
-
-extern cvar_t *sw_aliasstats;
-extern cvar_t *sw_clearcolor;
-extern cvar_t *sw_drawflat;
-extern cvar_t *sw_draworder;
-extern cvar_t *sw_maxedges;
-extern cvar_t *sw_maxsurfs;
-extern cvar_t *sw_mipcap;
-extern cvar_t *sw_mipscale;
-extern cvar_t *sw_mode;
-extern cvar_t *sw_reportsurfout;
-extern cvar_t *sw_reportedgeout;
-extern cvar_t *sw_stipplealpha;
-extern cvar_t *sw_surfcacheoverride;
-extern cvar_t *sw_waterwarp;
-
-extern cvar_t *r_fullbright;
-extern cvar_t *r_lefthand;
-extern cvar_t *r_drawentities;
-extern cvar_t *r_drawworld;
-extern cvar_t *r_dspeeds;
-extern cvar_t *r_lerpmodels;
-
-extern cvar_t *r_speeds;
-
-extern cvar_t *r_lightlevel; //FIXME HACK
-
-extern cvar_t *vid_fullscreen;
-extern cvar_t *vid_gamma;
-
-
-extern clipplane_t view_clipplanes[4];
-extern int *pfrustum_indexes[4];
-
-
-//=============================================================================
-
-void R_RenderWorld (void);
-
-//=============================================================================
-
-extern mplane_t screenedge[4];
-
-extern vec3_t r_origin;
-
-extern entity_t r_worldentity;
-extern model_t *currentmodel;
-extern entity_t *currententity;
-extern vec3_t modelorg;
-extern vec3_t r_entorigin;
-
-extern float verticalFieldOfView;
-extern float xOrigin, yOrigin;
-
-extern int r_visframecount;
-
-extern msurface_t *r_alpha_surfaces;
-
-//=============================================================================
-
-void R_ClearPolyList (void);
-void R_DrawPolyList (void);
-
-//
-// current entity info
-//
-extern qboolean insubmodel;
-
-void R_DrawAlphaSurfaces( void );
-
-void R_DrawSprite (void);
-void R_DrawBeam( entity_t *e );
-
-void R_RenderFace (msurface_t *fa, int clipflags);
-void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf);
-void R_TransformPlane (mplane_t *p, float *normal, float *dist);
-void R_TransformFrustum (void);
-void R_DrawSurfaceBlock16 (void);
-void R_DrawSurfaceBlock8 (void);
-
-#if id386
-
-void R_DrawSurfaceBlock8_mip0 (void);
-void R_DrawSurfaceBlock8_mip1 (void);
-void R_DrawSurfaceBlock8_mip2 (void);
-void R_DrawSurfaceBlock8_mip3 (void);
-
-#endif
-
-void R_GenSkyTile (void *pdest);
-void R_GenSkyTile16 (void *pdest);
-void R_Surf8Patch (void);
-void R_Surf16Patch (void);
-void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode);
-void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode);
-
-void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
-surf_t *R_GetSurf (void);
-void R_AliasDrawModel (void);
-void R_BeginEdgeFrame (void);
-void R_ScanEdges (void);
-void D_DrawSurfaces (void);
-void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist);
-void R_StepActiveU (edge_t *pedge);
-void R_RemoveEdges (edge_t *pedge);
-void R_PushDlights (model_t *model);
-
-extern void R_Surf8Start (void);
-extern void R_Surf8End (void);
-extern void R_Surf16Start (void);
-extern void R_Surf16End (void);
-extern void R_EdgeCodeStart (void);
-extern void R_EdgeCodeEnd (void);
-
-extern void R_RotateBmodel (void);
-
-extern int c_faceclip;
-extern int r_polycount;
-extern int r_wholepolycount;
-
-extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
-
-extern fixed16_t sadjust, tadjust;
-extern fixed16_t bbextents, bbextentt;
-
-extern mvertex_t *r_ptverts, *r_ptvertsmax;
-
-extern float entity_rotation[3][3];
-
-extern int r_currentkey;
-extern int r_currentbkey;
-
-void R_InitTurb (void);
-
-void R_DrawParticles (void);
-void R_SurfacePatch (void);
-
-extern int r_amodels_drawn;
-extern edge_t *auxedges;
-extern int r_numallocatededges;
-extern edge_t *r_edges, *edge_p, *edge_max;
-
-extern edge_t *newedges[MAXHEIGHT];
-extern edge_t *removeedges[MAXHEIGHT];
-
-// FIXME: make stack vars when debugging done
-extern edge_t edge_head;
-extern edge_t edge_tail;
-extern edge_t edge_aftertail;
-
-extern int r_aliasblendcolor;
-
-extern float aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
-
-extern int r_outofsurfaces;
-extern int r_outofedges;
-
-extern mvertex_t *r_pcurrentvertbase;
-extern int r_maxvalidedgeoffset;
-
-typedef struct
-{
- finalvert_t *a, *b, *c;
-} aliastriangleparms_t;
-
-extern aliastriangleparms_t aliastriangleparms;
-
-void R_DrawTriangle( void );
-//void R_DrawTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2);
-void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2);
-
-
-extern float r_time1;
-extern float da_time1, da_time2;
-extern float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
-extern float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2;
-extern int r_frustum_indexes[4*6];
-extern int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs;
-extern qboolean r_surfsonstack;
-
-extern mleaf_t *r_viewleaf;
-extern int r_viewcluster, r_oldviewcluster;
-
-extern int r_clipflags;
-extern int r_dlightframecount;
-extern qboolean r_fov_greater_than_90;
-
-extern image_t *r_notexture_mip;
-extern model_t *r_worldmodel;
-
-void R_PrintAliasStats (void);
-void R_PrintTimes (void);
-void R_PrintDSpeeds (void);
-void R_AnimateLight (void);
-void R_LightPoint (vec3_t p, vec3_t color);
-void R_SetupFrame (void);
-void R_cshift_f (void);
-void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1);
-void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip);
-void R_SplitEntityOnNode2 (mnode_t *node);
-
-extern refdef_t r_newrefdef;
-
-extern surfcache_t *sc_rover, *sc_base;
-
-extern void *colormap;
-
-//====================================================================
-
-float R_DLightPoint (vec3_t p);
-
-void R_NewMap (void);
-void R_Register (void);
-void R_UnRegister (void);
-void Draw_InitLocal (void);
-qboolean R_Init( void *hInstance, void *wndProc );
-void R_Shutdown (void);
-void R_InitCaches (void);
-void D_FlushCaches (void);
-
-void R_ScreenShot_f( void );
-void R_BeginRegistration (char *map);
-struct model_s *R_RegisterModel (char *name);
-void R_EndRegistration (void);
-
-void R_RenderFrame (refdef_t *fd);
-
-struct image_s *Draw_FindPic (char *name);
-
-void Draw_GetPicSize (int *w, int *h, char *name);
-void Draw_Pic (int x, int y, char *name);
-void Draw_StretchPic (int x, int y, int w, int h, char *name);
-void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data);
-void Draw_Char (int x, int y, int c);
-void Draw_TileClear (int x, int y, int w, int h, char *name);
-void Draw_Fill (int x, int y, int w, int h, int c);
-void Draw_FadeScreen (void);
-
-void Draw_GetPalette (void);
-
-void R_BeginFrame( float camera_separation );
-
-void R_CinematicSetPalette( const unsigned char *palette );
-
-extern unsigned d_8to24table[256]; // base
-
-void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length);
-void Sys_SetFPCW (void);
-
-void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height);
-
-void R_InitImages (void);
-void R_ShutdownImages (void);
-image_t *R_FindImage (char *name, imagetype_t type);
-void R_FreeUnusedImages (void);
-
-void R_GammaCorrectAndSetPalette( const unsigned char *pal );
-
-extern mtexinfo_t *sky_texinfo[6];
-
-void R_InitSkyBox (void);
-
-typedef struct swstate_s
-{
- qboolean fullscreen;
- int prev_mode; // last valid SW mode
-
- byte gammatable[256];
- byte currentpalette[1024];
-
-} swstate_t;
-
-void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha );
-
-extern swstate_t sw_state;
-
-/*
-====================================================================
-
-IMPORTED FUNCTIONS
-
-====================================================================
-*/
-
-extern refimport_t ri;
-
-/*
-====================================================================
-
-IMPLEMENTATION FUNCTIONS
-
-====================================================================
-*/
-
-void SWimp_BeginFrame( float camera_separation );
-void SWimp_EndFrame (void);
-int SWimp_Init( void *hInstance, void *wndProc );
-void SWimp_SetPalette( const unsigned char *palette);
-void SWimp_Shutdown( void );
-rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen );
-void SWimp_AppActivate( qboolean active );
-
--- a/ref_soft/r_main.c
+++ /dev/null
@@ -1,1422 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// r_main.c
-
-#include "r_local.h"
-
-viddef_t vid;
-refimport_t ri;
-
-unsigned d_8to24table[256];
-
-entity_t r_worldentity;
-
-char skyname[MAX_QPATH];
-float skyrotate;
-vec3_t skyaxis;
-image_t *sky_images[6];
-
-refdef_t r_newrefdef;
-model_t *currentmodel;
-
-model_t *r_worldmodel;
-
-byte r_warpbuffer[WARP_WIDTH * WARP_HEIGHT];
-
-swstate_t sw_state;
-
-void *colormap;
-vec3_t viewlightvec;
-alight_t r_viewlighting = {128, 192, viewlightvec};
-float r_time1;
-int r_numallocatededges;
-float r_aliasuvscale = 1.0;
-int r_outofsurfaces;
-int r_outofedges;
-
-qboolean r_dowarp;
-
-mvertex_t *r_pcurrentvertbase;
-
-int c_surf;
-int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs;
-qboolean r_surfsonstack;
-int r_clipflags;
-
-//
-// view origin
-//
-vec3_t vup, base_vup;
-vec3_t vpn, base_vpn;
-vec3_t vright, base_vright;
-vec3_t r_origin;
-
-//
-// screen size info
-//
-oldrefdef_t r_refdef;
-float xcenter, ycenter;
-float xscale, yscale;
-float xscaleinv, yscaleinv;
-float xscaleshrink, yscaleshrink;
-float aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
-
-int r_screenwidth;
-
-float verticalFieldOfView;
-float xOrigin, yOrigin;
-
-mplane_t screenedge[4];
-
-//
-// refresh flags
-//
-int r_framecount = 1; // so frame counts initialized to 0 don't match
-int r_visframecount;
-int d_spanpixcount;
-int r_polycount;
-int r_drawnpolycount;
-int r_wholepolycount;
-
-int *pfrustum_indexes[4];
-int r_frustum_indexes[4*6];
-
-mleaf_t *r_viewleaf;
-int r_viewcluster, r_oldviewcluster;
-
-image_t *r_notexture_mip;
-
-float da_time1, da_time2, dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
-float se_time1, se_time2, de_time1, de_time2;
-
-void R_MarkLeaves (void);
-
-cvar_t *r_lefthand;
-cvar_t *sw_aliasstats;
-cvar_t *sw_allow_modex;
-cvar_t *sw_clearcolor;
-cvar_t *sw_drawflat;
-cvar_t *sw_draworder;
-cvar_t *sw_maxedges;
-cvar_t *sw_maxsurfs;
-cvar_t *sw_mode;
-cvar_t *sw_reportedgeout;
-cvar_t *sw_reportsurfout;
-cvar_t *sw_stipplealpha;
-cvar_t *sw_surfcacheoverride;
-cvar_t *sw_waterwarp;
-
-cvar_t *r_drawworld;
-cvar_t *r_drawentities;
-cvar_t *r_dspeeds;
-cvar_t *r_fullbright;
-cvar_t *r_lerpmodels;
-cvar_t *r_novis;
-
-cvar_t *r_speeds;
-cvar_t *r_lightlevel; //FIXME HACK
-
-cvar_t *vid_fullscreen;
-cvar_t *vid_gamma;
-
-//PGM
-cvar_t *sw_lockpvs;
-//PGM
-
-#define STRINGER(x) "x"
-
-
-#if !id386
-
-// r_vars.c
-
-// all global and static refresh variables are collected in a contiguous block
-// to avoid cache conflicts.
-
-//-------------------------------------------------------
-// global refresh variables
-//-------------------------------------------------------
-
-// FIXME: make into one big structure, like cl or sv
-// FIXME: do separately for refresh engine and driver
-
-
-// d_vars.c
-
-// all global and static refresh variables are collected in a contiguous block
-// to avoid cache conflicts.
-
-//-------------------------------------------------------
-// global refresh variables
-//-------------------------------------------------------
-
-// FIXME: make into one big structure, like cl or sv
-// FIXME: do separately for refresh engine and driver
-
-float d_sdivzstepu, d_tdivzstepu, d_zistepu;
-float d_sdivzstepv, d_tdivzstepv, d_zistepv;
-float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
-
-fixed16_t sadjust, tadjust, bbextents, bbextentt;
-
-pixel_t *cacheblock;
-int cachewidth;
-pixel_t *d_viewbuffer;
-short *d_pzbuffer;
-unsigned int d_zrowbytes;
-unsigned int d_zwidth;
-
-
-#endif // !id386
-
-byte r_notexture_buffer[1024];
-
-/*
-==================
-R_InitTextures
-==================
-*/
-void R_InitTextures (void)
-{
- int x,y, m;
- byte *dest;
-
-// create a simple checkerboard texture for the default
- r_notexture_mip = (image_t *)&r_notexture_buffer;
-
- r_notexture_mip->width = r_notexture_mip->height = 16;
- r_notexture_mip->pixels[0] = &r_notexture_buffer[sizeof(image_t)];
- r_notexture_mip->pixels[1] = r_notexture_mip->pixels[0] + 16*16;
- r_notexture_mip->pixels[2] = r_notexture_mip->pixels[1] + 8*8;
- r_notexture_mip->pixels[3] = r_notexture_mip->pixels[2] + 4*4;
-
- for (m=0 ; m<4 ; m++)
- {
- dest = r_notexture_mip->pixels[m];
- for (y=0 ; y< (16>>m) ; y++)
- for (x=0 ; x< (16>>m) ; x++)
- {
- if ( (y< (8>>m) ) ^ (x< (8>>m) ) )
-
- *dest++ = 0;
- else
- *dest++ = 0xff;
- }
- }
-}
-
-
-/*
-================
-R_InitTurb
-================
-*/
-void R_InitTurb (void)
-{
- int i;
-
- for (i=0 ; i<1280 ; i++)
- {
- sintable[i] = AMP + sin(i*3.14159*2/CYCLE)*AMP;
- intsintable[i] = AMP2 + sin(i*3.14159*2/CYCLE)*AMP2; // AMP2, not 20
- blanktable[i] = 0; //PGM
- }
-}
-
-void R_ImageList_f( void );
-
-void R_Register (void)
-{
- sw_aliasstats = ri.Cvar_Get ("sw_polymodelstats", "0", 0);
- sw_allow_modex = ri.Cvar_Get( "sw_allow_modex", "1", CVAR_ARCHIVE );
- sw_clearcolor = ri.Cvar_Get ("sw_clearcolor", "2", 0);
- sw_drawflat = ri.Cvar_Get ("sw_drawflat", "0", 0);
- sw_draworder = ri.Cvar_Get ("sw_draworder", "0", 0);
- sw_maxedges = ri.Cvar_Get ("sw_maxedges", STRINGER(MAXSTACKSURFACES), 0);
- sw_maxsurfs = ri.Cvar_Get ("sw_maxsurfs", "0", 0);
- sw_mipcap = ri.Cvar_Get ("sw_mipcap", "0", 0);
- sw_mipscale = ri.Cvar_Get ("sw_mipscale", "1", 0);
- sw_reportedgeout = ri.Cvar_Get ("sw_reportedgeout", "0", 0);
- sw_reportsurfout = ri.Cvar_Get ("sw_reportsurfout", "0", 0);
- sw_stipplealpha = ri.Cvar_Get( "sw_stipplealpha", "0", CVAR_ARCHIVE );
- sw_surfcacheoverride = ri.Cvar_Get ("sw_surfcacheoverride", "0", 0);
- sw_waterwarp = ri.Cvar_Get ("sw_waterwarp", "1", 0);
- sw_mode = ri.Cvar_Get( "sw_mode", "0", CVAR_ARCHIVE );
-
- r_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
- r_speeds = ri.Cvar_Get ("r_speeds", "0", 0);
- r_fullbright = ri.Cvar_Get ("r_fullbright", "0", 0);
- r_drawentities = ri.Cvar_Get ("r_drawentities", "1", 0);
- r_drawworld = ri.Cvar_Get ("r_drawworld", "1", 0);
- r_dspeeds = ri.Cvar_Get ("r_dspeeds", "0", 0);
- r_lightlevel = ri.Cvar_Get ("r_lightlevel", "0", 0);
- r_lerpmodels = ri.Cvar_Get( "r_lerpmodels", "1", 0 );
- r_novis = ri.Cvar_Get( "r_novis", "0", 0 );
-
- vid_fullscreen = ri.Cvar_Get( "vid_fullscreen", "0", CVAR_ARCHIVE );
- vid_gamma = ri.Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE );
-
- ri.Cmd_AddCommand ("modellist", Mod_Modellist_f);
- ri.Cmd_AddCommand( "screenshot", R_ScreenShot_f );
- ri.Cmd_AddCommand( "imagelist", R_ImageList_f );
-
- sw_mode->modified = true; // force us to do mode specific stuff later
- vid_gamma->modified = true; // force us to rebuild the gamma table later
-
-//PGM
- sw_lockpvs = ri.Cvar_Get ("sw_lockpvs", "0", 0);
-//PGM
-}
-
-void R_UnRegister (void)
-{
- ri.Cmd_RemoveCommand( "screenshot" );
- ri.Cmd_RemoveCommand ("modellist");
- ri.Cmd_RemoveCommand( "imagelist" );
-}
-
-/*
-===============
-R_Init
-===============
-*/
-qboolean R_Init( void *hInstance, void *wndProc )
-{
- R_InitImages ();
- Mod_Init ();
- Draw_InitLocal ();
- R_InitTextures ();
-
- R_InitTurb ();
-
- view_clipplanes[0].leftedge = true;
- view_clipplanes[1].rightedge = true;
- view_clipplanes[1].leftedge = view_clipplanes[2].leftedge =
- view_clipplanes[3].leftedge = false;
- view_clipplanes[0].rightedge = view_clipplanes[2].rightedge =
- view_clipplanes[3].rightedge = false;
-
- r_refdef.xOrigin = XCENTERING;
- r_refdef.yOrigin = YCENTERING;
-
-// TODO: collect 386-specific code in one place
-#if id386
- Sys_MakeCodeWriteable ((long)R_EdgeCodeStart,
- (long)R_EdgeCodeEnd - (long)R_EdgeCodeStart);
- Sys_SetFPCW (); // get bit masks for FPCW (FIXME: is this id386?)
-#endif // id386
-
- r_aliasuvscale = 1.0;
-
- R_Register ();
- Draw_GetPalette ();
- SWimp_Init( hInstance, wndProc );
-
- // create the window
- R_BeginFrame( 0 );
-
- ri.Con_Printf (PRINT_ALL, "ref_soft version: "REF_VERSION"\n");
-
- return true;
-}
-
-/*
-===============
-R_Shutdown
-===============
-*/
-void R_Shutdown (void)
-{
- // free z buffer
- if (d_pzbuffer)
- {
- free (d_pzbuffer);
- d_pzbuffer = NULL;
- }
- // free surface cache
- if (sc_base)
- {
- D_FlushCaches ();
- free (sc_base);
- sc_base = NULL;
- }
-
- // free colormap
- if (vid.colormap)
- {
- free (vid.colormap);
- vid.colormap = NULL;
- }
- R_UnRegister ();
- Mod_FreeAll ();
- R_ShutdownImages ();
-
- SWimp_Shutdown();
-}
-
-/*
-===============
-R_NewMap
-===============
-*/
-void R_NewMap (void)
-{
- r_viewcluster = -1;
-
- r_cnumsurfs = sw_maxsurfs->value;
-
- if (r_cnumsurfs <= MINSURFACES)
- r_cnumsurfs = MINSURFACES;
-
- if (r_cnumsurfs > NUMSTACKSURFACES)
- {
- surfaces = malloc (r_cnumsurfs * sizeof(surf_t));
- surface_p = surfaces;
- surf_max = &surfaces[r_cnumsurfs];
- r_surfsonstack = false;
- // surface 0 doesn't really exist; it's just a dummy because index 0
- // is used to indicate no edge attached to surface
- surfaces--;
- R_SurfacePatch ();
- }
- else
- {
- r_surfsonstack = true;
- }
-
- r_maxedgesseen = 0;
- r_maxsurfsseen = 0;
-
- r_numallocatededges = sw_maxedges->value;
-
- if (r_numallocatededges < MINEDGES)
- r_numallocatededges = MINEDGES;
-
- if (r_numallocatededges <= NUMSTACKEDGES)
- {
- auxedges = NULL;
- }
- else
- {
- auxedges = malloc (r_numallocatededges * sizeof(edge_t));
- }
-}
-
-
-/*
-===============
-R_MarkLeaves
-
-Mark the leaves and nodes that are in the PVS for the current
-cluster
-===============
-*/
-void R_MarkLeaves (void)
-{
- byte *vis;
- mnode_t *node;
- int i;
- mleaf_t *leaf;
- int cluster;
-
- if (r_oldviewcluster == r_viewcluster && !r_novis->value && r_viewcluster != -1)
- return;
-
- // development aid to let you run around and see exactly where
- // the pvs ends
- if (sw_lockpvs->value)
- return;
-
- r_visframecount++;
- r_oldviewcluster = r_viewcluster;
-
- if (r_novis->value || r_viewcluster == -1 || !r_worldmodel->vis)
- {
- // mark everything
- for (i=0 ; i<r_worldmodel->numleafs ; i++)
- r_worldmodel->leafs[i].visframe = r_visframecount;
- for (i=0 ; i<r_worldmodel->numnodes ; i++)
- r_worldmodel->nodes[i].visframe = r_visframecount;
- return;
- }
-
- vis = Mod_ClusterPVS (r_viewcluster, r_worldmodel);
-
- for (i=0,leaf=r_worldmodel->leafs ; i<r_worldmodel->numleafs ; i++, leaf++)
- {
- cluster = leaf->cluster;
- if (cluster == -1)
- continue;
- if (vis[cluster>>3] & (1<<(cluster&7)))
- {
- node = (mnode_t *)leaf;
- do
- {
- if (node->visframe == r_visframecount)
- break;
- node->visframe = r_visframecount;
- node = node->parent;
- } while (node);
- }
- }
-
-#if 0
- for (i=0 ; i<r_worldmodel->vis->numclusters ; i++)
- {
- if (vis[i>>3] & (1<<(i&7)))
- {
- node = (mnode_t *)&r_worldmodel->leafs[i]; // FIXME: cluster
- do
- {
- if (node->visframe == r_visframecount)
- break;
- node->visframe = r_visframecount;
- node = node->parent;
- } while (node);
- }
- }
-#endif
-}
-
-/*
-** R_DrawNullModel
-**
-** IMPLEMENT THIS!
-*/
-void R_DrawNullModel( void )
-{
-}
-
-/*
-=============
-R_DrawEntitiesOnList
-=============
-*/
-void R_DrawEntitiesOnList (void)
-{
- int i;
- qboolean translucent_entities = false;
-
- if (!r_drawentities->value)
- return;
-
- // all bmodels have already been drawn by the edge list
- for (i=0 ; i<r_newrefdef.num_entities ; i++)
- {
- currententity = &r_newrefdef.entities[i];
-
- if ( currententity->flags & RF_TRANSLUCENT )
- {
- translucent_entities = true;
- continue;
- }
-
- if ( currententity->flags & RF_BEAM )
- {
- modelorg[0] = -r_origin[0];
- modelorg[1] = -r_origin[1];
- modelorg[2] = -r_origin[2];
- VectorCopy( vec3_origin, r_entorigin );
- R_DrawBeam( currententity );
- }
- else
- {
- currentmodel = currententity->model;
- if (!currentmodel)
- {
- R_DrawNullModel();
- continue;
- }
- VectorCopy (currententity->origin, r_entorigin);
- VectorSubtract (r_origin, r_entorigin, modelorg);
-
- switch (currentmodel->type)
- {
- case mod_sprite:
- R_DrawSprite ();
- break;
-
- case mod_alias:
- R_AliasDrawModel ();
- break;
-
- default:
- break;
- }
- }
- }
-
- if ( !translucent_entities )
- return;
-
- for (i=0 ; i<r_newrefdef.num_entities ; i++)
- {
- currententity = &r_newrefdef.entities[i];
-
- if ( !( currententity->flags & RF_TRANSLUCENT ) )
- continue;
-
- if ( currententity->flags & RF_BEAM )
- {
- modelorg[0] = -r_origin[0];
- modelorg[1] = -r_origin[1];
- modelorg[2] = -r_origin[2];
- VectorCopy( vec3_origin, r_entorigin );
- R_DrawBeam( currententity );
- }
- else
- {
- currentmodel = currententity->model;
- if (!currentmodel)
- {
- R_DrawNullModel();
- continue;
- }
- VectorCopy (currententity->origin, r_entorigin);
- VectorSubtract (r_origin, r_entorigin, modelorg);
-
- switch (currentmodel->type)
- {
- case mod_sprite:
- R_DrawSprite ();
- break;
-
- case mod_alias:
- R_AliasDrawModel ();
- break;
-
- default:
- break;
- }
- }
- }
-}
-
-
-/*
-=============
-R_BmodelCheckBBox
-=============
-*/
-int R_BmodelCheckBBox (float *minmaxs)
-{
- int i, *pindex, clipflags;
- vec3_t acceptpt, rejectpt;
- float d;
-
- clipflags = 0;
-
- for (i=0 ; i<4 ; i++)
- {
- // generate accept and reject points
- // FIXME: do with fast look-ups or integer tests based on the sign bit
- // of the floating point values
-
- pindex = pfrustum_indexes[i];
-
- rejectpt[0] = minmaxs[pindex[0]];
- rejectpt[1] = minmaxs[pindex[1]];
- rejectpt[2] = minmaxs[pindex[2]];
-
- d = DotProduct (rejectpt, view_clipplanes[i].normal);
- d -= view_clipplanes[i].dist;
-
- if (d <= 0)
- return BMODEL_FULLY_CLIPPED;
-
- acceptpt[0] = minmaxs[pindex[3+0]];
- acceptpt[1] = minmaxs[pindex[3+1]];
- acceptpt[2] = minmaxs[pindex[3+2]];
-
- d = DotProduct (acceptpt, view_clipplanes[i].normal);
- d -= view_clipplanes[i].dist;
-
- if (d <= 0)
- clipflags |= (1<<i);
- }
-
- return clipflags;
-}
-
-
-/*
-===================
-R_FindTopnode
-
-Find the first node that splits the given box
-===================
-*/
-mnode_t *R_FindTopnode (vec3_t mins, vec3_t maxs)
-{
- mplane_t *splitplane;
- int sides;
- mnode_t *node;
-
- node = r_worldmodel->nodes;
-
- while (1)
- {
- if (node->visframe != r_visframecount)
- return NULL; // not visible at all
-
- if (node->contents != CONTENTS_NODE)
- {
- if (node->contents != CONTENTS_SOLID)
- return node; // we've reached a non-solid leaf, so it's
- // visible and not BSP clipped
- return NULL; // in solid, so not visible
- }
-
- splitplane = node->plane;
- sides = BOX_ON_PLANE_SIDE(mins, maxs, (cplane_t *)splitplane);
-
- if (sides == 3)
- return node; // this is the splitter
-
- // not split yet; recurse down the contacted side
- if (sides & 1)
- node = node->children[0];
- else
- node = node->children[1];
- }
-}
-
-
-/*
-=============
-RotatedBBox
-
-Returns an axially aligned box that contains the input box at the given rotation
-=============
-*/
-void RotatedBBox (vec3_t mins, vec3_t maxs, vec3_t angles, vec3_t tmins, vec3_t tmaxs)
-{
- vec3_t tmp, v;
- int i, j;
- vec3_t forward, right, up;
-
- if (!angles[0] && !angles[1] && !angles[2])
- {
- VectorCopy (mins, tmins);
- VectorCopy (maxs, tmaxs);
- return;
- }
-
- for (i=0 ; i<3 ; i++)
- {
- tmins[i] = 99999;
- tmaxs[i] = -99999;
- }
-
- AngleVectors (angles, forward, right, up);
-
- for ( i = 0; i < 8; i++ )
- {
- if ( i & 1 )
- tmp[0] = mins[0];
- else
- tmp[0] = maxs[0];
-
- if ( i & 2 )
- tmp[1] = mins[1];
- else
- tmp[1] = maxs[1];
-
- if ( i & 4 )
- tmp[2] = mins[2];
- else
- tmp[2] = maxs[2];
-
-
- VectorScale (forward, tmp[0], v);
- VectorMA (v, -tmp[1], right, v);
- VectorMA (v, tmp[2], up, v);
-
- for (j=0 ; j<3 ; j++)
- {
- if (v[j] < tmins[j])
- tmins[j] = v[j];
- if (v[j] > tmaxs[j])
- tmaxs[j] = v[j];
- }
- }
-}
-
-/*
-=============
-R_DrawBEntitiesOnList
-=============
-*/
-void R_DrawBEntitiesOnList (void)
-{
- int i, clipflags;
- vec3_t oldorigin;
- vec3_t mins, maxs;
- float minmaxs[6];
- mnode_t *topnode;
-
- if (!r_drawentities->value)
- return;
-
- VectorCopy (modelorg, oldorigin);
- insubmodel = true;
- r_dlightframecount = r_framecount;
-
- for (i=0 ; i<r_newrefdef.num_entities ; i++)
- {
- currententity = &r_newrefdef.entities[i];
- currentmodel = currententity->model;
- if (!currentmodel)
- continue;
- if (currentmodel->nummodelsurfaces == 0)
- continue; // clip brush only
- if ( currententity->flags & RF_BEAM )
- continue;
- if (currentmodel->type != mod_brush)
- continue;
- // see if the bounding box lets us trivially reject, also sets
- // trivial accept status
- RotatedBBox (currentmodel->mins, currentmodel->maxs,
- currententity->angles, mins, maxs);
- VectorAdd (mins, currententity->origin, minmaxs);
- VectorAdd (maxs, currententity->origin, (minmaxs+3));
-
- clipflags = R_BmodelCheckBBox (minmaxs);
- if (clipflags == BMODEL_FULLY_CLIPPED)
- continue; // off the edge of the screen
-
- topnode = R_FindTopnode (minmaxs, minmaxs+3);
- if (!topnode)
- continue; // no part in a visible leaf
-
- VectorCopy (currententity->origin, r_entorigin);
- VectorSubtract (r_origin, r_entorigin, modelorg);
-
- r_pcurrentvertbase = currentmodel->vertexes;
-
- // FIXME: stop transforming twice
- R_RotateBmodel ();
-
- // calculate dynamic lighting for bmodel
- R_PushDlights (currentmodel);
-
- if (topnode->contents == CONTENTS_NODE)
- {
- // not a leaf; has to be clipped to the world BSP
- r_clipflags = clipflags;
- R_DrawSolidClippedSubmodelPolygons (currentmodel, topnode);
- }
- else
- {
- // falls entirely in one leaf, so we just put all the
- // edges in the edge list and let 1/z sorting handle
- // drawing order
- R_DrawSubmodelPolygons (currentmodel, clipflags, topnode);
- }
-
- // put back world rotation and frustum clipping
- // FIXME: R_RotateBmodel should just work off base_vxx
- VectorCopy (base_vpn, vpn);
- VectorCopy (base_vup, vup);
- VectorCopy (base_vright, vright);
- VectorCopy (oldorigin, modelorg);
- R_TransformFrustum ();
- }
-
- insubmodel = false;
-}
-
-
-/*
-================
-R_EdgeDrawing
-================
-*/
-void R_EdgeDrawing (void)
-{
- edge_t ledges[NUMSTACKEDGES +
- ((CACHE_SIZE - 1) / sizeof(edge_t)) + 1];
- surf_t lsurfs[NUMSTACKSURFACES +
- ((CACHE_SIZE - 1) / sizeof(surf_t)) + 1];
-
- if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
- return;
-
- if (auxedges)
- {
- r_edges = auxedges;
- }
- else
- {
- r_edges = (edge_t *)
- (((long)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
- }
-
- if (r_surfsonstack)
- {
- surfaces = (surf_t *)
- (((long)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
- surf_max = &surfaces[r_cnumsurfs];
- // surface 0 doesn't really exist; it's just a dummy because index 0
- // is used to indicate no edge attached to surface
- surfaces--;
- R_SurfacePatch ();
- }
-
- R_BeginEdgeFrame ();
-
- if (r_dspeeds->value)
- {
- rw_time1 = Sys_Milliseconds ();
- }
-
- R_RenderWorld ();
-
- if (r_dspeeds->value)
- {
- rw_time2 = Sys_Milliseconds ();
- db_time1 = rw_time2;
- }
-
- R_DrawBEntitiesOnList ();
-
- if (r_dspeeds->value)
- {
- db_time2 = Sys_Milliseconds ();
- se_time1 = db_time2;
- }
-
- R_ScanEdges ();
-}
-
-//=======================================================================
-
-
-/*
-=============
-R_CalcPalette
-
-=============
-*/
-void R_CalcPalette (void)
-{
- static qboolean modified;
- byte palette[256][4], *in, *out;
- int i, j;
- float alpha, one_minus_alpha;
- vec3_t premult;
- int v;
-
- alpha = r_newrefdef.blend[3];
- if (alpha <= 0)
- {
- if (modified)
- { // set back to default
- modified = false;
- R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
- return;
- }
- return;
- }
-
- modified = true;
- if (alpha > 1)
- alpha = 1;
-
- premult[0] = r_newrefdef.blend[0]*alpha*255;
- premult[1] = r_newrefdef.blend[1]*alpha*255;
- premult[2] = r_newrefdef.blend[2]*alpha*255;
-
- one_minus_alpha = (1.0 - alpha);
-
- in = (byte *)d_8to24table;
- out = palette[0];
- for (i=0 ; i<256 ; i++, in+=4, out+=4)
- {
- for (j=0 ; j<3 ; j++)
- {
- v = premult[j] + one_minus_alpha * in[j];
- if (v > 255)
- v = 255;
- out[j] = v;
- }
- out[3] = 255;
- }
-
- R_GammaCorrectAndSetPalette( ( const unsigned char * ) palette[0] );
-// SWimp_SetPalette( palette[0] );
-}
-
-//=======================================================================
-
-void R_SetLightLevel (void)
-{
- vec3_t light;
-
- if ((r_newrefdef.rdflags & RDF_NOWORLDMODEL) || (!r_drawentities->value) || (!currententity))
- {
- r_lightlevel->value = 150.0;
- return;
- }
-
- // save off light value for server to look at (BIG HACK!)
- R_LightPoint (r_newrefdef.vieworg, light);
- r_lightlevel->value = 150.0 * light[0];
-}
-
-
-/*
-@@@@@@@@@@@@@@@@
-R_RenderFrame
-
-@@@@@@@@@@@@@@@@
-*/
-void R_RenderFrame (refdef_t *fd)
-{
- r_newrefdef = *fd;
-
- if (!r_worldmodel && !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
- ri.Sys_Error (ERR_FATAL,"R_RenderView: NULL worldmodel");
-
- VectorCopy (fd->vieworg, r_refdef.vieworg);
- VectorCopy (fd->viewangles, r_refdef.viewangles);
-
- if (r_speeds->value || r_dspeeds->value)
- r_time1 = Sys_Milliseconds ();
-
- R_SetupFrame ();
-
- R_MarkLeaves (); // done here so we know if we're in water
-
- R_PushDlights (r_worldmodel);
-
- R_EdgeDrawing ();
-
- if (r_dspeeds->value)
- {
- se_time2 = Sys_Milliseconds ();
- de_time1 = se_time2;
- }
-
- R_DrawEntitiesOnList ();
-
- if (r_dspeeds->value)
- {
- de_time2 = Sys_Milliseconds ();
- dp_time1 = Sys_Milliseconds ();
- }
-
- R_DrawParticles ();
-
- if (r_dspeeds->value)
- dp_time2 = Sys_Milliseconds ();
-
- R_DrawAlphaSurfaces();
-
- R_SetLightLevel ();
-
- if (r_dowarp)
- D_WarpScreen ();
-
- if (r_dspeeds->value)
- da_time1 = Sys_Milliseconds ();
-
- if (r_dspeeds->value)
- da_time2 = Sys_Milliseconds ();
-
- R_CalcPalette ();
-
- if (sw_aliasstats->value)
- R_PrintAliasStats ();
-
- if (r_speeds->value)
- R_PrintTimes ();
-
- if (r_dspeeds->value)
- R_PrintDSpeeds ();
-
- if (sw_reportsurfout->value && r_outofsurfaces)
- ri.Con_Printf (PRINT_ALL,"Short %d surfaces\n", r_outofsurfaces);
-
- if (sw_reportedgeout->value && r_outofedges)
- ri.Con_Printf (PRINT_ALL,"Short roughly %d edges\n", r_outofedges * 2 / 3);
-}
-
-/*
-** R_InitGraphics
-*/
-void R_InitGraphics( int width, int height )
-{
- vid.width = width;
- vid.height = height;
-
- // free z buffer
- if ( d_pzbuffer )
- {
- free( d_pzbuffer );
- d_pzbuffer = NULL;
- }
-
- // free surface cache
- if ( sc_base )
- {
- D_FlushCaches ();
- free( sc_base );
- sc_base = NULL;
- }
-
- d_pzbuffer = malloc(vid.width*vid.height*2);
-
- R_InitCaches ();
-
- R_GammaCorrectAndSetPalette( ( const unsigned char *) d_8to24table );
-}
-
-/*
-** R_BeginFrame
-*/
-void R_BeginFrame( float camera_separation )
-{
- extern void Draw_BuildGammaTable( void );
-
- /*
- ** rebuild the gamma correction palette if necessary
- */
- if ( vid_gamma->modified )
- {
- Draw_BuildGammaTable();
- R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
-
- vid_gamma->modified = false;
- }
-
- while ( sw_mode->modified || vid_fullscreen->modified )
- {
- rserr_t err;
-
- /*
- ** if this returns rserr_invalid_fullscreen then it set the mode but not as a
- ** fullscreen mode, e.g. 320x200 on a system that doesn't support that res
- */
- if ( ( err = SWimp_SetMode( &vid.width, &vid.height, sw_mode->value, vid_fullscreen->value ) ) == rserr_ok )
- {
- R_InitGraphics( vid.width, vid.height );
-
- sw_state.prev_mode = sw_mode->value;
- vid_fullscreen->modified = false;
- sw_mode->modified = false;
- }
- else
- {
- if ( err == rserr_invalid_mode )
- {
- ri.Cvar_SetValue( "sw_mode", sw_state.prev_mode );
- ri.Con_Printf( PRINT_ALL, "ref_soft::R_BeginFrame() - could not set mode\n" );
- }
- else if ( err == rserr_invalid_fullscreen )
- {
- R_InitGraphics( vid.width, vid.height );
-
- ri.Cvar_SetValue( "vid_fullscreen", 0);
- ri.Con_Printf( PRINT_ALL, "ref_soft::R_BeginFrame() - fullscreen unavailable in this mode\n" );
- sw_state.prev_mode = sw_mode->value;
-// vid_fullscreen->modified = false;
-// sw_mode->modified = false;
- }
- else
- {
- ri.Sys_Error( ERR_FATAL, "ref_soft::R_BeginFrame() - catastrophic mode change failure\n" );
- }
- }
- }
-}
-
-/*
-** R_GammaCorrectAndSetPalette
-*/
-void R_GammaCorrectAndSetPalette( const unsigned char *palette )
-{
- int i;
-
- for ( i = 0; i < 256; i++ )
- {
- sw_state.currentpalette[i*4+0] = sw_state.gammatable[palette[i*4+0]];
- sw_state.currentpalette[i*4+1] = sw_state.gammatable[palette[i*4+1]];
- sw_state.currentpalette[i*4+2] = sw_state.gammatable[palette[i*4+2]];
- }
-
- SWimp_SetPalette( sw_state.currentpalette );
-}
-
-/*
-** R_CinematicSetPalette
-*/
-void R_CinematicSetPalette( const unsigned char *palette )
-{
- byte palette32[1024];
- int i, j, w;
- int *d;
-
- // clear screen to black to avoid any palette flash
- w = abs(vid.rowbytes)>>2; // stupid negative pitch win32 stuff...
- for (i=0 ; i<vid.height ; i++, d+=w)
- {
- d = (int *)(vid.buffer + i*vid.rowbytes);
- for (j=0 ; j<w ; j++)
- d[j] = 0;
- }
- // flush it to the screen
- SWimp_EndFrame ();
-
- if ( palette )
- {
- for ( i = 0; i < 256; i++ )
- {
- palette32[i*4+0] = palette[i*3+0];
- palette32[i*4+1] = palette[i*3+1];
- palette32[i*4+2] = palette[i*3+2];
- palette32[i*4+3] = 0xFF;
- }
-
- R_GammaCorrectAndSetPalette( palette32 );
- }
- else
- {
- R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
- }
-}
-
-/*
-================
-Draw_BuildGammaTable
-================
-*/
-void Draw_BuildGammaTable (void)
-{
- int i, inf;
- float g;
-
- g = vid_gamma->value;
-
- if (g == 1.0)
- {
- for (i=0 ; i<256 ; i++)
- sw_state.gammatable[i] = i;
- return;
- }
-
- for (i=0 ; i<256 ; i++)
- {
- inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5;
- if (inf < 0)
- inf = 0;
- if (inf > 255)
- inf = 255;
- sw_state.gammatable[i] = inf;
- }
-}
-
-/*
-** R_DrawBeam
-*/
-void R_DrawBeam( entity_t *e )
-{
-#define NUM_BEAM_SEGS 6
-
- int i;
-
- vec3_t perpvec;
- vec3_t direction, normalized_direction;
- vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
- vec3_t oldorigin, origin;
-
- oldorigin[0] = e->oldorigin[0];
- oldorigin[1] = e->oldorigin[1];
- oldorigin[2] = e->oldorigin[2];
-
- origin[0] = e->origin[0];
- origin[1] = e->origin[1];
- origin[2] = e->origin[2];
-
- normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
- normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
- normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
-
- if ( VectorNormalize( normalized_direction ) == 0 )
- return;
-
- PerpendicularVector( perpvec, normalized_direction );
- VectorScale( perpvec, e->frame / 2, perpvec );
-
- for ( i = 0; i < NUM_BEAM_SEGS; i++ )
- {
- RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i );
- VectorAdd( start_points[i], origin, start_points[i] );
- VectorAdd( start_points[i], direction, end_points[i] );
- }
-
- for ( i = 0; i < NUM_BEAM_SEGS; i++ )
- {
- R_IMFlatShadedQuad( start_points[i],
- end_points[i],
- end_points[(i+1)%NUM_BEAM_SEGS],
- start_points[(i+1)%NUM_BEAM_SEGS],
- e->skinnum & 0xFF,
- e->alpha );
- }
-}
-
-
-//===================================================================
-
-/*
-============
-R_SetSky
-============
-*/
-// 3dstudio environment map names
-char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
-int r_skysideimage[6] = {5, 2, 4, 1, 0, 3};
-extern mtexinfo_t r_skytexinfo[6];
-void R_SetSky (char *name, float rotate, vec3_t axis)
-{
- int i;
- char pathname[MAX_QPATH];
-
- strncpy (skyname, name, sizeof(skyname)-1);
- skyrotate = rotate;
- VectorCopy (axis, skyaxis);
-
- for (i=0 ; i<6 ; i++)
- {
- Com_sprintf (pathname, sizeof(pathname), "env/%s%s.pcx", skyname, suf[r_skysideimage[i]]);
- r_skytexinfo[i].image = R_FindImage (pathname, it_sky);
- }
-}
-
-
-/*
-===============
-Draw_GetPalette
-===============
-*/
-void Draw_GetPalette (void)
-{
- byte *pal, *out;
- int i;
- int r, g, b;
-
- // get the palette and colormap
- LoadPCX ("pics/colormap.pcx", &vid.colormap, &pal, NULL, NULL);
- if (!vid.colormap)
- ri.Sys_Error (ERR_FATAL, "Couldn't load pics/colormap.pcx");
- vid.alphamap = vid.colormap + 64*256;
-
- out = (byte *)d_8to24table;
- for (i=0 ; i<256 ; i++, out+=4)
- {
- r = pal[i*3+0];
- g = pal[i*3+1];
- b = pal[i*3+2];
-
- out[0] = r;
- out[1] = g;
- out[2] = b;
- }
-
- free (pal);
-}
-
-struct image_s *R_RegisterSkin (char *name);
-
-/*
-@@@@@@@@@@@@@@@@@@@@@
-GetRefAPI
-
-@@@@@@@@@@@@@@@@@@@@@
-*/
-refexport_t GetRefAPI (refimport_t rimp)
-{
- refexport_t re;
-
- ri = rimp;
-
- re.api_version = API_VERSION;
-
- re.BeginRegistration = R_BeginRegistration;
- re.RegisterModel = R_RegisterModel;
- re.RegisterSkin = R_RegisterSkin;
- re.RegisterPic = Draw_FindPic;
- re.SetSky = R_SetSky;
- re.EndRegistration = R_EndRegistration;
-
- re.RenderFrame = R_RenderFrame;
-
- re.DrawGetPicSize = Draw_GetPicSize;
- re.DrawPic = Draw_Pic;
- re.DrawStretchPic = Draw_StretchPic;
- re.DrawChar = Draw_Char;
- re.DrawTileClear = Draw_TileClear;
- re.DrawFill = Draw_Fill;
- re.DrawFadeScreen= Draw_FadeScreen;
-
- re.DrawStretchRaw = Draw_StretchRaw;
-
- re.Init = R_Init;
- re.Shutdown = R_Shutdown;
-
- re.CinematicSetPalette = R_CinematicSetPalette;
- re.BeginFrame = R_BeginFrame;
- re.EndFrame = SWimp_EndFrame;
-
- re.AppActivate = SWimp_AppActivate;
-
- Swap_Init ();
-
- return re;
-}
-
-#ifndef REF_HARD_LINKED
-// this is only here so the functions in q_shared.c and q_shwin.c can link
-void Sys_Error (char *error, ...)
-{
- va_list argptr;
- char text[1024];
-
- va_start (argptr, error);
- vsprintf (text, error, argptr);
- va_end (argptr);
-
- ri.Sys_Error (ERR_FATAL, "%s", text);
-}
-
-void Com_Printf (char *fmt, ...)
-{
- va_list argptr;
- char text[1024];
-
- va_start (argptr, fmt);
- vsprintf (text, fmt, argptr);
- va_end (argptr);
-
- ri.Con_Printf (PRINT_ALL, "%s", text);
-}
-
-#endif
--- a/ref_soft/r_misc.c
+++ /dev/null
@@ -1,670 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// r_misc.c
-
-#include "r_local.h"
-
-#define NUM_MIPS 4
-
-cvar_t *sw_mipcap;
-cvar_t *sw_mipscale;
-
-surfcache_t *d_initial_rover;
-qboolean d_roverwrapped;
-int d_minmip;
-float d_scalemip[NUM_MIPS-1];
-
-static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8};
-
-extern int d_aflatcolor;
-
-int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
-
-int d_pix_min, d_pix_max, d_pix_shift;
-
-int d_scantable[MAXHEIGHT];
-short *zspantable[MAXHEIGHT];
-
-/*
-================
-D_Patch
-================
-*/
-void D_Patch (void)
-{
-#if id386
- extern void D_Aff8Patch( void );
- static qboolean protectset8 = false;
- extern void D_PolysetAff8Start( void );
-
- if (!protectset8)
- {
- Sys_MakeCodeWriteable ((int)D_PolysetAff8Start,
- (int)D_Aff8Patch - (int)D_PolysetAff8Start);
- Sys_MakeCodeWriteable ((long)R_Surf8Start,
- (long)R_Surf8End - (long)R_Surf8Start);
- protectset8 = true;
- }
- colormap = vid.colormap;
-
- R_Surf8Patch ();
- D_Aff8Patch();
-#endif
-}
-/*
-================
-D_ViewChanged
-================
-*/
-unsigned char *alias_colormap;
-
-void D_ViewChanged (void)
-{
- int i;
-
- scale_for_mip = xscale;
- if (yscale > xscale)
- scale_for_mip = yscale;
-
- d_zrowbytes = vid.width * 2;
- d_zwidth = vid.width;
-
- d_pix_min = r_refdef.vrect.width / 320;
- if (d_pix_min < 1)
- d_pix_min = 1;
-
- d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5);
- d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5);
- if (d_pix_max < 1)
- d_pix_max = 1;
-
- d_vrectx = r_refdef.vrect.x;
- d_vrecty = r_refdef.vrect.y;
- d_vrectright_particle = r_refdef.vrectright - d_pix_max;
- d_vrectbottom_particle =
- r_refdef.vrectbottom - d_pix_max;
-
- for (i=0 ; i<vid.height; i++)
- {
- d_scantable[i] = i*r_screenwidth;
- zspantable[i] = d_pzbuffer + i*d_zwidth;
- }
-
- /*
- ** clear Z-buffer and color-buffers if we're doing the gallery
- */
- if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
- {
- memset( d_pzbuffer, 0xff, vid.width * vid.height * sizeof( d_pzbuffer[0] ) );
- Draw_Fill( r_newrefdef.x, r_newrefdef.y, r_newrefdef.width, r_newrefdef.height,( int ) sw_clearcolor->value & 0xff );
- }
-
- alias_colormap = vid.colormap;
-
- D_Patch ();
-}
-
-
-
-/*
-=============
-R_PrintTimes
-=============
-*/
-void R_PrintTimes (void)
-{
- int r_time2;
- int ms;
-
- r_time2 = Sys_Milliseconds ();
-
- ms = r_time2 - r_time1;
-
- ri.Con_Printf (PRINT_ALL,"%5i ms %3i/%3i/%3i poly %3i surf\n",
- ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf);
- c_surf = 0;
-}
-
-
-/*
-=============
-R_PrintDSpeeds
-=============
-*/
-void R_PrintDSpeeds (void)
-{
- int ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, da_time;
-
- r_time2 = Sys_Milliseconds ();
-
- da_time = (da_time2 - da_time1);
- dp_time = (dp_time2 - dp_time1);
- rw_time = (rw_time2 - rw_time1);
- db_time = (db_time2 - db_time1);
- se_time = (se_time2 - se_time1);
- de_time = (de_time2 - de_time1);
- ms = (r_time2 - r_time1);
-
- ri.Con_Printf (PRINT_ALL,"%3i %2ip %2iw %2ib %2is %2ie %2ia\n",
- ms, dp_time, rw_time, db_time, se_time, de_time, da_time);
-}
-
-
-/*
-=============
-R_PrintAliasStats
-=============
-*/
-void R_PrintAliasStats (void)
-{
- ri.Con_Printf (PRINT_ALL,"%3i polygon model drawn\n", r_amodels_drawn);
-}
-
-
-
-/*
-===================
-R_TransformFrustum
-===================
-*/
-void R_TransformFrustum (void)
-{
- int i;
- vec3_t v, v2;
-
- for (i=0 ; i<4 ; i++)
- {
- v[0] = screenedge[i].normal[2];
- v[1] = -screenedge[i].normal[0];
- v[2] = screenedge[i].normal[1];
-
- v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0];
- v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1];
- v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2];
-
- VectorCopy (v2, view_clipplanes[i].normal);
-
- view_clipplanes[i].dist = DotProduct (modelorg, v2);
- }
-}
-
-
-#if !(defined __linux__ && defined __i386__)
-#if !id386
-
-/*
-================
-TransformVector
-================
-*/
-void TransformVector (vec3_t in, vec3_t out)
-{
- out[0] = DotProduct(in,vright);
- out[1] = DotProduct(in,vup);
- out[2] = DotProduct(in,vpn);
-}
-
-#else
-
-__declspec( naked ) void TransformVector( vec3_t vin, vec3_t vout )
-{
- __asm mov eax, dword ptr [esp+4]
- __asm mov edx, dword ptr [esp+8]
-
- __asm fld dword ptr [eax+0]
- __asm fmul dword ptr [vright+0]
- __asm fld dword ptr [eax+0]
- __asm fmul dword ptr [vup+0]
- __asm fld dword ptr [eax+0]
- __asm fmul dword ptr [vpn+0]
-
- __asm fld dword ptr [eax+4]
- __asm fmul dword ptr [vright+4]
- __asm fld dword ptr [eax+4]
- __asm fmul dword ptr [vup+4]
- __asm fld dword ptr [eax+4]
- __asm fmul dword ptr [vpn+4]
-
- __asm fxch st(2)
-
- __asm faddp st(5), st(0)
- __asm faddp st(3), st(0)
- __asm faddp st(1), st(0)
-
- __asm fld dword ptr [eax+8]
- __asm fmul dword ptr [vright+8]
- __asm fld dword ptr [eax+8]
- __asm fmul dword ptr [vup+8]
- __asm fld dword ptr [eax+8]
- __asm fmul dword ptr [vpn+8]
-
- __asm fxch st(2)
-
- __asm faddp st(5), st(0)
- __asm faddp st(3), st(0)
- __asm faddp st(1), st(0)
-
- __asm fstp dword ptr [edx+8]
- __asm fstp dword ptr [edx+4]
- __asm fstp dword ptr [edx+0]
-
- __asm ret
-}
-
-#endif
-#endif
-
-
-/*
-================
-R_TransformPlane
-================
-*/
-void R_TransformPlane (mplane_t *p, float *normal, float *dist)
-{
- float d;
-
- d = DotProduct (r_origin, p->normal);
- *dist = p->dist - d;
-// TODO: when we have rotating entities, this will need to use the view matrix
- TransformVector (p->normal, normal);
-}
-
-
-/*
-===============
-R_SetUpFrustumIndexes
-===============
-*/
-void R_SetUpFrustumIndexes (void)
-{
- int i, j, *pindex;
-
- pindex = r_frustum_indexes;
-
- for (i=0 ; i<4 ; i++)
- {
- for (j=0 ; j<3 ; j++)
- {
- if (view_clipplanes[i].normal[j] < 0)
- {
- pindex[j] = j;
- pindex[j+3] = j+3;
- }
- else
- {
- pindex[j] = j+3;
- pindex[j+3] = j;
- }
- }
-
- // FIXME: do just once at start
- pfrustum_indexes[i] = pindex;
- pindex += 6;
- }
-}
-
-/*
-===============
-R_ViewChanged
-
-Called every time the vid structure or r_refdef changes.
-Guaranteed to be called before the first refresh
-===============
-*/
-void R_ViewChanged (vrect_t *vr)
-{
- int i;
-
- r_refdef.vrect = *vr;
-
- r_refdef.horizontalFieldOfView = 2*tan((float)r_newrefdef.fov_x/360*M_PI);;
- verticalFieldOfView = 2*tan((float)r_newrefdef.fov_y/360*M_PI);
-
- r_refdef.fvrectx = (float)r_refdef.vrect.x;
- r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5;
- r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1;
- r_refdef.fvrecty = (float)r_refdef.vrect.y;
- r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5;
- r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
- r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1;
- r_refdef.fvrectright = (float)r_refdef.vrectright;
- r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5;
- r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99;
- r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
- r_refdef.fvrectbottom = (float)r_refdef.vrectbottom;
- r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5;
-
- r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale);
- r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale);
- r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale);
- r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale);
- r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
- r_refdef.aliasvrect.width;
- r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
- r_refdef.aliasvrect.height;
-
- xOrigin = r_refdef.xOrigin;
- yOrigin = r_refdef.yOrigin;
-
-// values for perspective projection
-// if math were exact, the values would range from 0.5 to to range+0.5
-// hopefully they wll be in the 0.000001 to range+.999999 and truncate
-// the polygon rasterization will never render in the first row or column
-// but will definately render in the [range] row and column, so adjust the
-// buffer origin to get an exact edge to edge fill
- xcenter = ((float)r_refdef.vrect.width * XCENTERING) +
- r_refdef.vrect.x - 0.5;
- aliasxcenter = xcenter * r_aliasuvscale;
- ycenter = ((float)r_refdef.vrect.height * YCENTERING) +
- r_refdef.vrect.y - 0.5;
- aliasycenter = ycenter * r_aliasuvscale;
-
- xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
- aliasxscale = xscale * r_aliasuvscale;
- xscaleinv = 1.0 / xscale;
-
- yscale = xscale;
- aliasyscale = yscale * r_aliasuvscale;
- yscaleinv = 1.0 / yscale;
- xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView;
- yscaleshrink = xscaleshrink;
-
-// left side clip
- screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView);
- screenedge[0].normal[1] = 0;
- screenedge[0].normal[2] = 1;
- screenedge[0].type = PLANE_ANYZ;
-
-// right side clip
- screenedge[1].normal[0] =
- 1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView);
- screenedge[1].normal[1] = 0;
- screenedge[1].normal[2] = 1;
- screenedge[1].type = PLANE_ANYZ;
-
-// top side clip
- screenedge[2].normal[0] = 0;
- screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView);
- screenedge[2].normal[2] = 1;
- screenedge[2].type = PLANE_ANYZ;
-
-// bottom side clip
- screenedge[3].normal[0] = 0;
- screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView);
- screenedge[3].normal[2] = 1;
- screenedge[3].type = PLANE_ANYZ;
-
- for (i=0 ; i<4 ; i++)
- VectorNormalize (screenedge[i].normal);
-
- D_ViewChanged ();
-}
-
-
-/*
-===============
-R_SetupFrame
-===============
-*/
-void R_SetupFrame (void)
-{
- int i;
- vrect_t vrect;
-
- if (r_fullbright->modified)
- {
- r_fullbright->modified = false;
- D_FlushCaches (); // so all lighting changes
- }
-
- r_framecount++;
-
-
-// build the transformation matrix for the given view angles
- VectorCopy (r_refdef.vieworg, modelorg);
- VectorCopy (r_refdef.vieworg, r_origin);
-
- AngleVectors (r_refdef.viewangles, vpn, vright, vup);
-
-// current viewleaf
- if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
- {
- r_viewleaf = Mod_PointInLeaf (r_origin, r_worldmodel);
- r_viewcluster = r_viewleaf->cluster;
- }
-
- if (sw_waterwarp->value && (r_newrefdef.rdflags & RDF_UNDERWATER) )
- r_dowarp = true;
- else
- r_dowarp = false;
-
- if (r_dowarp)
- { // warp into off screen buffer
- vrect.x = 0;
- vrect.y = 0;
- vrect.width = r_newrefdef.width < WARP_WIDTH ? r_newrefdef.width : WARP_WIDTH;
- vrect.height = r_newrefdef.height < WARP_HEIGHT ? r_newrefdef.height : WARP_HEIGHT;
-
- d_viewbuffer = r_warpbuffer;
- r_screenwidth = WARP_WIDTH;
- }
- else
- {
- vrect.x = r_newrefdef.x;
- vrect.y = r_newrefdef.y;
- vrect.width = r_newrefdef.width;
- vrect.height = r_newrefdef.height;
-
- d_viewbuffer = (void *)vid.buffer;
- r_screenwidth = vid.rowbytes;
- }
-
- R_ViewChanged (&vrect);
-
-// start off with just the four screen edge clip planes
- R_TransformFrustum ();
- R_SetUpFrustumIndexes ();
-
-// save base values
- VectorCopy (vpn, base_vpn);
- VectorCopy (vright, base_vright);
- VectorCopy (vup, base_vup);
-
-// clear frame counts
- c_faceclip = 0;
- d_spanpixcount = 0;
- r_polycount = 0;
- r_drawnpolycount = 0;
- r_wholepolycount = 0;
- r_amodels_drawn = 0;
- r_outofsurfaces = 0;
- r_outofedges = 0;
-
-// d_setup
- d_roverwrapped = false;
- d_initial_rover = sc_rover;
-
- d_minmip = sw_mipcap->value;
- if (d_minmip > 3)
- d_minmip = 3;
- else if (d_minmip < 0)
- d_minmip = 0;
-
- for (i=0 ; i<(NUM_MIPS-1) ; i++)
- d_scalemip[i] = basemip[i] * sw_mipscale->value;
-
- d_aflatcolor = 0;
-}
-
-
-#if !id386
-
-/*
-================
-R_SurfacePatch
-================
-*/
-void R_SurfacePatch (void)
-{
- // we only patch code on Intel
-}
-
-#endif // !id386
-
-
-/*
-==============================================================================
-
- SCREEN SHOTS
-
-==============================================================================
-*/
-
-
-/*
-==============
-WritePCXfile
-==============
-*/
-void WritePCXfile (char *filename, byte *data, int width, int height,
- int rowbytes, byte *palette)
-{
- int i, j, length;
- pcx_t *pcx;
- byte *pack;
- FILE *f;
-
- pcx = (pcx_t *)malloc (width*height*2+1000);
- if (!pcx)
- return;
-
- pcx->manufacturer = 0x0a; // PCX id
- pcx->version = 5; // 256 color
- pcx->encoding = 1; // uncompressed
- pcx->bits_per_pixel = 8; // 256 color
- pcx->xmin = 0;
- pcx->ymin = 0;
- pcx->xmax = LittleShort((short)(width-1));
- pcx->ymax = LittleShort((short)(height-1));
- pcx->hres = LittleShort((short)width);
- pcx->vres = LittleShort((short)height);
- memset (pcx->palette,0,sizeof(pcx->palette));
- pcx->color_planes = 1; // chunky image
- pcx->bytes_per_line = LittleShort((short)width);
- pcx->palette_type = LittleShort(2); // not a grey scale
- memset (pcx->filler,0,sizeof(pcx->filler));
-
-// pack the image
- pack = &pcx->data;
-
- for (i=0 ; i<height ; i++)
- {
- for (j=0 ; j<width ; j++)
- {
- if ( (*data & 0xc0) != 0xc0)
- *pack++ = *data++;
- else
- {
- *pack++ = 0xc1;
- *pack++ = *data++;
- }
- }
-
- data += rowbytes - width;
- }
-
-// write the palette
- *pack++ = 0x0c; // palette ID byte
- for (i=0 ; i<768 ; i++)
- *pack++ = *palette++;
-
-// write output file
- length = pack - (byte *)pcx;
- f = fopen (filename, "wb");
- if (!f)
- ri.Con_Printf (PRINT_ALL, "Failed to open to %s\n", filename);
- else
- {
- fwrite ((void *)pcx, 1, length, f);
- fclose (f);
- }
-
- free (pcx);
-}
-
-
-
-/*
-==================
-R_ScreenShot_f
-==================
-*/
-void R_ScreenShot_f (void)
-{
- int i;
- char pcxname[80];
- char checkname[MAX_OSPATH];
- FILE *f;
- byte palette[768];
-
- // create the scrnshots directory if it doesn't exist
- Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot", ri.FS_Gamedir());
- Sys_Mkdir (checkname);
-
-//
-// find a file name to save it to
-//
- strcpy(pcxname,"quake00.pcx");
-
- for (i=0 ; i<=99 ; i++)
- {
- pcxname[5] = i/10 + '0';
- pcxname[6] = i%10 + '0';
- Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/%s", ri.FS_Gamedir(), pcxname);
- f = fopen (checkname, "r");
- if (!f)
- break; // file doesn't exist
- fclose (f);
- }
- if (i==100)
- {
- ri.Con_Printf (PRINT_ALL, "R_ScreenShot_f: Couldn't create a PCX");
- return;
- }
-
- // turn the current 32 bit palette into a 24 bit palette
- for (i=0 ; i<256 ; i++)
- {
- palette[i*3+0] = sw_state.currentpalette[i*4+0];
- palette[i*3+1] = sw_state.currentpalette[i*4+1];
- palette[i*3+2] = sw_state.currentpalette[i*4+2];
- }
-
-//
-// save the pcx file
-//
-
- WritePCXfile (checkname, vid.buffer, vid.width, vid.height, vid.rowbytes,
- palette);
-
- ri.Con_Printf (PRINT_ALL, "Wrote %s\n", checkname);
-}
-
--- a/ref_soft/r_model.c
+++ /dev/null
@@ -1,1241 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// models.c -- model loading and caching
-
-// models are the only shared resource between a client and server running
-// on the same machine.
-
-#include "r_local.h"
-
-model_t *loadmodel;
-char loadname[32]; // for hunk tags
-
-void Mod_LoadSpriteModel (model_t *mod, void *buffer);
-void Mod_LoadBrushModel (model_t *mod, void *buffer);
-void Mod_LoadAliasModel (model_t *mod, void *buffer);
-model_t *Mod_LoadModel (model_t *mod, qboolean crash);
-
-byte mod_novis[MAX_MAP_LEAFS/8];
-
-#define MAX_MOD_KNOWN 256
-model_t mod_known[MAX_MOD_KNOWN];
-int mod_numknown;
-
-// the inline * models from the current map are kept seperate
-model_t mod_inline[MAX_MOD_KNOWN];
-
-int registration_sequence;
-int modfilelen;
-
-//===============================================================================
-
-
-/*
-================
-Mod_Modellist_f
-================
-*/
-void Mod_Modellist_f (void)
-{
- int i;
- model_t *mod;
- int total;
-
- total = 0;
- ri.Con_Printf (PRINT_ALL,"Loaded models:\n");
- for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
- {
- if (!mod->name[0])
- continue;
- ri.Con_Printf (PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name);
- total += mod->extradatasize;
- }
- ri.Con_Printf (PRINT_ALL, "Total resident: %i\n", total);
-}
-
-/*
-===============
-Mod_Init
-===============
-*/
-void Mod_Init (void)
-{
- memset (mod_novis, 0xff, sizeof(mod_novis));
-}
-
-/*
-==================
-Mod_ForName
-
-Loads in a model for the given name
-==================
-*/
-model_t *Mod_ForName (char *name, qboolean crash)
-{
- model_t *mod;
- unsigned *buf;
- int i;
-
- if (!name[0])
- ri.Sys_Error (ERR_DROP,"Mod_ForName: NULL name");
-
- //
- // inline models are grabbed only from worldmodel
- //
- if (name[0] == '*')
- {
- i = atoi(name+1);
- if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels)
- ri.Sys_Error (ERR_DROP, "bad inline model number");
- return &mod_inline[i];
- }
-
- //
- // search the currently loaded models
- //
- for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
- if (!strcmp (mod->name, name) )
- return mod;
-
- //
- // find a free model slot spot
- //
- for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
- {
- if (!mod->name[0])
- break; // free spot
- }
- if (i == mod_numknown)
- {
- if (mod_numknown == MAX_MOD_KNOWN)
- ri.Sys_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN");
- mod_numknown++;
- }
- strcpy (mod->name, name);
-
- //
- // load the file
- //
- modfilelen = ri.FS_LoadFile (mod->name, (void **)&buf);
- if (!buf)
- {
- if (crash)
- ri.Sys_Error (ERR_DROP,"Mod_NumForName: %s not found", mod->name);
- memset (mod->name, 0, sizeof(mod->name));
- return NULL;
- }
-
- loadmodel = mod;
-
- //
- // fill it in
- //
-
- // call the apropriate loader
-
- switch (LittleLong(*(unsigned *)buf))
- {
- case IDALIASHEADER:
- loadmodel->extradata = Hunk_Begin (0x200000);
- Mod_LoadAliasModel (mod, buf);
- break;
-
- case IDSPRITEHEADER:
- loadmodel->extradata = Hunk_Begin (0x10000);
- Mod_LoadSpriteModel (mod, buf);
- break;
-
- case IDBSPHEADER:
- loadmodel->extradata = Hunk_Begin (0x1000000);
- Mod_LoadBrushModel (mod, buf);
- break;
-
- default:
- ri.Sys_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name);
- break;
- }
-
- loadmodel->extradatasize = Hunk_End ();
-
- ri.FS_FreeFile (buf);
-
- return mod;
-}
-
-
-/*
-===============
-Mod_PointInLeaf
-===============
-*/
-mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
-{
- mnode_t *node;
- float d;
- mplane_t *plane;
-
- if (!model || !model->nodes)
- ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model");
-
- node = model->nodes;
- while (1)
- {
- if (node->contents != -1)
- return (mleaf_t *)node;
- plane = node->plane;
- d = DotProduct (p,plane->normal) - plane->dist;
- if (d > 0)
- node = node->children[0];
- else
- node = node->children[1];
- }
-
- return NULL; // never reached
-}
-
-
-/*
-===================
-Mod_DecompressVis
-===================
-*/
-byte *Mod_DecompressVis (byte *in, model_t *model)
-{
- static byte decompressed[MAX_MAP_LEAFS/8];
- int c;
- byte *out;
- int row;
-
- row = (model->vis->numclusters+7)>>3;
- out = decompressed;
-
-#if 0
- memcpy (out, in, row);
-#else
- if (!in)
- { // no vis info, so make all visible
- while (row)
- {
- *out++ = 0xff;
- row--;
- }
- return decompressed;
- }
-
- do
- {
- if (*in)
- {
- *out++ = *in++;
- continue;
- }
-
- c = in[1];
- in += 2;
- while (c)
- {
- *out++ = 0;
- c--;
- }
- } while (out - decompressed < row);
-#endif
-
- return decompressed;
-}
-
-/*
-==============
-Mod_ClusterPVS
-==============
-*/
-byte *Mod_ClusterPVS (int cluster, model_t *model)
-{
- if (cluster == -1 || !model->vis)
- return mod_novis;
- return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS],
- model);
-}
-
-/*
-===============================================================================
-
- BRUSHMODEL LOADING
-
-===============================================================================
-*/
-
-byte *mod_base;
-
-
-/*
-=================
-Mod_LoadLighting
-
-Converts the 24 bit lighting down to 8 bit
-by taking the brightest component
-=================
-*/
-void Mod_LoadLighting (lump_t *l)
-{
- int i, size;
- byte *in;
-
- if (!l->filelen)
- {
- loadmodel->lightdata = NULL;
- return;
- }
- size = l->filelen/3;
- loadmodel->lightdata = Hunk_Alloc (size);
- in = (void *)(mod_base + l->fileofs);
- for (i=0 ; i<size ; i++, in+=3)
- {
- if (in[0] > in[1] && in[0] > in[2])
- loadmodel->lightdata[i] = in[0];
- else if (in[1] > in[0] && in[1] > in[2])
- loadmodel->lightdata[i] = in[1];
- else
- loadmodel->lightdata[i] = in[2];
- }
-}
-
-
-int r_leaftovis[MAX_MAP_LEAFS];
-int r_vistoleaf[MAX_MAP_LEAFS];
-int r_numvisleafs;
-
-void R_NumberLeafs (mnode_t *node)
-{
- mleaf_t *leaf;
- int leafnum;
-
- if (node->contents != -1)
- {
- leaf = (mleaf_t *)node;
- leafnum = leaf - loadmodel->leafs;
- if (leaf->contents & CONTENTS_SOLID)
- return;
- r_leaftovis[leafnum] = r_numvisleafs;
- r_vistoleaf[r_numvisleafs] = leafnum;
- r_numvisleafs++;
- return;
- }
-
- R_NumberLeafs (node->children[0]);
- R_NumberLeafs (node->children[1]);
-}
-
-
-/*
-=================
-Mod_LoadVisibility
-=================
-*/
-void Mod_LoadVisibility (lump_t *l)
-{
- int i;
-
- if (!l->filelen)
- {
- loadmodel->vis = NULL;
- return;
- }
- loadmodel->vis = Hunk_Alloc ( l->filelen);
- memcpy (loadmodel->vis, mod_base + l->fileofs, l->filelen);
-
- loadmodel->vis->numclusters = LittleLong (loadmodel->vis->numclusters);
- for (i=0 ; i<loadmodel->vis->numclusters ; i++)
- {
- loadmodel->vis->bitofs[i][0] = LittleLong (loadmodel->vis->bitofs[i][0]);
- loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]);
- }
-}
-
-
-/*
-=================
-Mod_LoadVertexes
-=================
-*/
-void Mod_LoadVertexes (lump_t *l)
-{
- dvertex_t *in;
- mvertex_t *out;
- int i, count;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc ( (count+8)*sizeof(*out)); // extra for skybox
-
- loadmodel->vertexes = out;
- loadmodel->numvertexes = count;
-
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- out->position[0] = LittleFloat (in->point[0]);
- out->position[1] = LittleFloat (in->point[1]);
- out->position[2] = LittleFloat (in->point[2]);
- }
-}
-
-/*
-=================
-Mod_LoadSubmodels
-=================
-*/
-void Mod_LoadSubmodels (lump_t *l)
-{
- dmodel_t *in;
- dmodel_t *out;
- int i, j, count;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc ( count*sizeof(*out));
-
- loadmodel->submodels = out;
- loadmodel->numsubmodels = count;
-
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- for (j=0 ; j<3 ; j++)
- { // spread the mins / maxs by a pixel
- out->mins[j] = LittleFloat (in->mins[j]) - 1;
- out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
- out->origin[j] = LittleFloat (in->origin[j]);
- }
- out->headnode = LittleLong (in->headnode);
- out->firstface = LittleLong (in->firstface);
- out->numfaces = LittleLong (in->numfaces);
- }
-}
-
-/*
-=================
-Mod_LoadEdges
-=================
-*/
-void Mod_LoadEdges (lump_t *l)
-{
- dedge_t *in;
- medge_t *out;
- int i, count;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc ( (count + 13) * sizeof(*out)); // extra for skybox
-
- loadmodel->edges = out;
- loadmodel->numedges = count;
-
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- out->v[0] = (unsigned short)LittleShort(in->v[0]);
- out->v[1] = (unsigned short)LittleShort(in->v[1]);
- }
-}
-
-/*
-=================
-Mod_LoadTexinfo
-=================
-*/
-void Mod_LoadTexinfo (lump_t *l)
-{
- texinfo_t *in;
- mtexinfo_t *out, *step;
- int i, j, count;
- float len1, len2;
- char name[MAX_QPATH];
- int next;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox
-
- loadmodel->texinfo = out;
- loadmodel->numtexinfo = count;
-
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- for (j=0 ; j<8 ; j++)
- out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
- len1 = VectorLength (out->vecs[0]);
- len2 = VectorLength (out->vecs[1]);
- len1 = (len1 + len2)/2;
- if (len1 < 0.32)
- out->mipadjust = 4;
- else if (len1 < 0.49)
- out->mipadjust = 3;
- else if (len1 < 0.99)
- out->mipadjust = 2;
- else
- out->mipadjust = 1;
-#if 0
- if (len1 + len2 < 0.001)
- out->mipadjust = 1; // don't crash
- else
- out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
-#endif
-
- out->flags = LittleLong (in->flags);
-
- next = LittleLong (in->nexttexinfo);
- if (next > 0)
- out->next = loadmodel->texinfo + next;
-
- Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture);
- out->image = R_FindImage (name, it_wall);
- if (!out->image)
- {
- out->image = r_notexture_mip; // texture not found
- out->flags = 0;
- }
- }
-
- // count animation frames
- for (i=0 ; i<count ; i++)
- {
- out = &loadmodel->texinfo[i];
- out->numframes = 1;
- for (step = out->next ; step && step != out ; step=step->next)
- out->numframes++;
- }
-}
-
-/*
-================
-CalcSurfaceExtents
-
-Fills in s->texturemins[] and s->extents[]
-================
-*/
-void CalcSurfaceExtents (msurface_t *s)
-{
- float mins[2], maxs[2], val;
- int i,j, e;
- mvertex_t *v;
- mtexinfo_t *tex;
- int bmins[2], bmaxs[2];
-
- mins[0] = mins[1] = 999999;
- maxs[0] = maxs[1] = -99999;
-
- tex = s->texinfo;
-
- for (i=0 ; i<s->numedges ; i++)
- {
- e = loadmodel->surfedges[s->firstedge+i];
- if (e >= 0)
- v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
- else
- v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
-
- for (j=0 ; j<2 ; j++)
- {
- val = v->position[0] * tex->vecs[j][0] +
- v->position[1] * tex->vecs[j][1] +
- v->position[2] * tex->vecs[j][2] +
- tex->vecs[j][3];
- if (val < mins[j])
- mins[j] = val;
- if (val > maxs[j])
- maxs[j] = val;
- }
- }
-
- for (i=0 ; i<2 ; i++)
- {
- bmins[i] = floor(mins[i]/16);
- bmaxs[i] = ceil(maxs[i]/16);
-
- s->texturemins[i] = bmins[i] * 16;
- s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
- if (s->extents[i] < 16)
- s->extents[i] = 16; // take at least one cache block
- if ( !(tex->flags & (SURF_WARP|SURF_SKY)) && s->extents[i] > 256)
- ri.Sys_Error (ERR_DROP,"Bad surface extents");
- }
-}
-
-
-/*
-=================
-Mod_LoadFaces
-=================
-*/
-void Mod_LoadFaces (lump_t *l)
-{
- dface_t *in;
- msurface_t *out;
- int i, count, surfnum;
- int planenum, side;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox
-
- loadmodel->surfaces = out;
- loadmodel->numsurfaces = count;
-
- for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
- {
- out->firstedge = LittleLong(in->firstedge);
- out->numedges = LittleShort(in->numedges);
- if (out->numedges < 3)
- ri.Sys_Error (ERR_DROP,"Surface with %s edges", out->numedges);
- out->flags = 0;
-
- planenum = LittleShort(in->planenum);
- side = LittleShort(in->side);
- if (side)
- out->flags |= SURF_PLANEBACK;
-
- out->plane = loadmodel->planes + planenum;
-
- out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
-
- CalcSurfaceExtents (out);
-
- // lighting info is converted from 24 bit on disk to 8 bit
-
- for (i=0 ; i<MAXLIGHTMAPS ; i++)
- out->styles[i] = in->styles[i];
- i = LittleLong(in->lightofs);
- if (i == -1)
- out->samples = NULL;
- else
- out->samples = loadmodel->lightdata + i/3;
-
- // set the drawing flags flag
-
- if (!out->texinfo->image)
- continue;
- if (out->texinfo->flags & SURF_SKY)
- {
- out->flags |= SURF_DRAWSKY;
- continue;
- }
-
- if (out->texinfo->flags & SURF_WARP)
- {
- out->flags |= SURF_DRAWTURB;
- for (i=0 ; i<2 ; i++)
- {
- out->extents[i] = 16384;
- out->texturemins[i] = -8192;
- }
- continue;
- }
-//==============
-//PGM
- // this marks flowing surfaces as turbulent, but with the new
- // SURF_FLOW flag.
- if (out->texinfo->flags & SURF_FLOWING)
- {
- out->flags |= SURF_DRAWTURB | SURF_FLOW;
- for (i=0 ; i<2 ; i++)
- {
- out->extents[i] = 16384;
- out->texturemins[i] = -8192;
- }
- continue;
- }
-//PGM
-//==============
- }
-}
-
-
-/*
-=================
-Mod_SetParent
-=================
-*/
-void Mod_SetParent (mnode_t *node, mnode_t *parent)
-{
- node->parent = parent;
- if (node->contents != -1)
- return;
- Mod_SetParent (node->children[0], node);
- Mod_SetParent (node->children[1], node);
-}
-
-/*
-=================
-Mod_LoadNodes
-=================
-*/
-void Mod_LoadNodes (lump_t *l)
-{
- int i, j, count, p;
- dnode_t *in;
- mnode_t *out;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc ( count*sizeof(*out));
-
- loadmodel->nodes = out;
- loadmodel->numnodes = count;
-
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- for (j=0 ; j<3 ; j++)
- {
- out->minmaxs[j] = LittleShort (in->mins[j]);
- out->minmaxs[3+j] = LittleShort (in->maxs[j]);
- }
-
- p = LittleLong(in->planenum);
- out->plane = loadmodel->planes + p;
-
- out->firstsurface = LittleShort (in->firstface);
- out->numsurfaces = LittleShort (in->numfaces);
- out->contents = CONTENTS_NODE; // differentiate from leafs
-
- for (j=0 ; j<2 ; j++)
- {
- p = LittleLong (in->children[j]);
- if (p >= 0)
- out->children[j] = loadmodel->nodes + p;
- else
- out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
- }
- }
-
- Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
-}
-
-/*
-=================
-Mod_LoadLeafs
-=================
-*/
-void Mod_LoadLeafs (lump_t *l)
-{
- dleaf_t *in;
- mleaf_t *out;
- int i, j, count;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc ( count*sizeof(*out));
-
- loadmodel->leafs = out;
- loadmodel->numleafs = count;
-
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- for (j=0 ; j<3 ; j++)
- {
- out->minmaxs[j] = LittleShort (in->mins[j]);
- out->minmaxs[3+j] = LittleShort (in->maxs[j]);
- }
-
- out->contents = LittleLong(in->contents);
- out->cluster = LittleShort(in->cluster);
- out->area = LittleShort(in->area);
-
- out->firstmarksurface = loadmodel->marksurfaces +
- LittleShort(in->firstleafface);
- out->nummarksurfaces = LittleShort(in->numleaffaces);
- }
-}
-
-
-/*
-=================
-Mod_LoadMarksurfaces
-=================
-*/
-void Mod_LoadMarksurfaces (lump_t *l)
-{
- int i, j, count;
- short *in;
- msurface_t **out;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc ( count*sizeof(*out));
-
- loadmodel->marksurfaces = out;
- loadmodel->nummarksurfaces = count;
-
- for ( i=0 ; i<count ; i++)
- {
- j = LittleShort(in[i]);
- if (j >= loadmodel->numsurfaces)
- ri.Sys_Error (ERR_DROP,"Mod_ParseMarksurfaces: bad surface number");
- out[i] = loadmodel->surfaces + j;
- }
-}
-
-/*
-=================
-Mod_LoadSurfedges
-=================
-*/
-void Mod_LoadSurfedges (lump_t *l)
-{
- int i, count;
- int *in, *out;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc ( (count+24)*sizeof(*out)); // extra for skybox
-
- loadmodel->surfedges = out;
- loadmodel->numsurfedges = count;
-
- for ( i=0 ; i<count ; i++)
- out[i] = LittleLong (in[i]);
-}
-
-/*
-=================
-Mod_LoadPlanes
-=================
-*/
-void Mod_LoadPlanes (lump_t *l)
-{
- int i, j;
- mplane_t *out;
- dplane_t *in;
- int count;
- int bits;
-
- in = (void *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox
-
- loadmodel->planes = out;
- loadmodel->numplanes = count;
-
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- bits = 0;
- for (j=0 ; j<3 ; j++)
- {
- out->normal[j] = LittleFloat (in->normal[j]);
- if (out->normal[j] < 0)
- bits |= 1<<j;
- }
-
- out->dist = LittleFloat (in->dist);
- out->type = LittleLong (in->type);
- out->signbits = bits;
- }
-}
-
-
-/*
-=================
-Mod_LoadBrushModel
-=================
-*/
-void Mod_LoadBrushModel (model_t *mod, void *buffer)
-{
- int i;
- dheader_t *header;
- dmodel_t *bm;
-
- loadmodel->type = mod_brush;
- if (loadmodel != mod_known)
- ri.Sys_Error (ERR_DROP, "Loaded a brush model after the world");
-
- header = (dheader_t *)buffer;
-
- i = LittleLong (header->version);
- if (i != BSPVERSION)
- ri.Sys_Error (ERR_DROP,"Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
-
-// swap all the lumps
- mod_base = (byte *)header;
-
- for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
- ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
-
-// load into heap
-
- Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
- Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
- Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
- Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
- Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
- Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
- Mod_LoadFaces (&header->lumps[LUMP_FACES]);
- Mod_LoadMarksurfaces (&header->lumps[LUMP_LEAFFACES]);
- Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
- Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
- Mod_LoadNodes (&header->lumps[LUMP_NODES]);
- Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
- r_numvisleafs = 0;
- R_NumberLeafs (loadmodel->nodes);
-
-//
-// set up the submodels
-//
- for (i=0 ; i<mod->numsubmodels ; i++)
- {
- model_t *starmod;
-
- bm = &mod->submodels[i];
- starmod = &mod_inline[i];
-
- *starmod = *loadmodel;
-
- starmod->firstmodelsurface = bm->firstface;
- starmod->nummodelsurfaces = bm->numfaces;
- starmod->firstnode = bm->headnode;
- if (starmod->firstnode >= loadmodel->numnodes)
- ri.Sys_Error (ERR_DROP, "Inline model %i has bad firstnode", i);
-
- VectorCopy (bm->maxs, starmod->maxs);
- VectorCopy (bm->mins, starmod->mins);
-
- if (i == 0)
- *loadmodel = *starmod;
- }
-
- R_InitSkyBox ();
-}
-
-/*
-==============================================================================
-
-ALIAS MODELS
-
-==============================================================================
-*/
-
-/*
-=================
-Mod_LoadAliasModel
-=================
-*/
-void Mod_LoadAliasModel (model_t *mod, void *buffer)
-{
- int i, j;
- dmdl_t *pinmodel, *pheader;
- dstvert_t *pinst, *poutst;
- dtriangle_t *pintri, *pouttri;
- daliasframe_t *pinframe, *poutframe;
- int *pincmd, *poutcmd;
- int version;
-
- pinmodel = (dmdl_t *)buffer;
-
- version = LittleLong (pinmodel->version);
- if (version != ALIAS_VERSION)
- ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
- mod->name, version, ALIAS_VERSION);
-
- pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end));
-
- // byte swap the header fields and sanity check
- for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
- ((int *)pheader)[i] = LittleLong (((int *)buffer)[i]);
-
- if (pheader->skinheight > MAX_LBM_HEIGHT)
- ri.Sys_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name,
- MAX_LBM_HEIGHT);
-
- if (pheader->num_xyz <= 0)
- ri.Sys_Error (ERR_DROP, "model %s has no vertices", mod->name);
-
- if (pheader->num_xyz > MAX_VERTS)
- ri.Sys_Error (ERR_DROP, "model %s has too many vertices", mod->name);
-
- if (pheader->num_st <= 0)
- ri.Sys_Error (ERR_DROP, "model %s has no st vertices", mod->name);
-
- if (pheader->num_tris <= 0)
- ri.Sys_Error (ERR_DROP, "model %s has no triangles", mod->name);
-
- if (pheader->num_frames <= 0)
- ri.Sys_Error (ERR_DROP, "model %s has no frames", mod->name);
-
-//
-// load base s and t vertices (not used in gl version)
-//
- pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st);
- poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st);
-
- for (i=0 ; i<pheader->num_st ; i++)
- {
- poutst[i].s = LittleShort (pinst[i].s);
- poutst[i].t = LittleShort (pinst[i].t);
- }
-
-//
-// load triangle lists
-//
- pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris);
- pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris);
-
- for (i=0 ; i<pheader->num_tris ; i++)
- {
- for (j=0 ; j<3 ; j++)
- {
- pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]);
- pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]);
- }
- }
-
-//
-// load the frames
-//
- for (i=0 ; i<pheader->num_frames ; i++)
- {
- pinframe = (daliasframe_t *) ((byte *)pinmodel
- + pheader->ofs_frames + i * pheader->framesize);
- poutframe = (daliasframe_t *) ((byte *)pheader
- + pheader->ofs_frames + i * pheader->framesize);
-
- memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name));
- for (j=0 ; j<3 ; j++)
- {
- poutframe->scale[j] = LittleFloat (pinframe->scale[j]);
- poutframe->translate[j] = LittleFloat (pinframe->translate[j]);
- }
- // verts are all 8 bit, so no swapping needed
- memcpy (poutframe->verts, pinframe->verts,
- pheader->num_xyz*sizeof(dtrivertx_t));
-
- }
-
- mod->type = mod_alias;
-
- //
- // load the glcmds
- //
- pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds);
- poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds);
- for (i=0 ; i<pheader->num_glcmds ; i++)
- poutcmd[i] = LittleLong (pincmd[i]);
-
-
- // register all skins
- memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins,
- pheader->num_skins*MAX_SKINNAME);
- for (i=0 ; i<pheader->num_skins ; i++)
- {
- mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
- }
-}
-
-/*
-==============================================================================
-
-SPRITE MODELS
-
-==============================================================================
-*/
-
-/*
-=================
-Mod_LoadSpriteModel
-=================
-*/
-void Mod_LoadSpriteModel (model_t *mod, void *buffer)
-{
- dsprite_t *sprin, *sprout;
- int i;
-
- sprin = (dsprite_t *)buffer;
- sprout = Hunk_Alloc (modfilelen);
-
- sprout->ident = LittleLong (sprin->ident);
- sprout->version = LittleLong (sprin->version);
- sprout->numframes = LittleLong (sprin->numframes);
-
- if (sprout->version != SPRITE_VERSION)
- ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
- mod->name, sprout->version, SPRITE_VERSION);
-
- if (sprout->numframes > MAX_MD2SKINS)
- ri.Sys_Error (ERR_DROP, "%s has too many frames (%i > %i)",
- mod->name, sprout->numframes, MAX_MD2SKINS);
-
- // byte swap everything
- for (i=0 ; i<sprout->numframes ; i++)
- {
- sprout->frames[i].width = LittleLong (sprin->frames[i].width);
- sprout->frames[i].height = LittleLong (sprin->frames[i].height);
- sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x);
- sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y);
- memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME);
- mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite);
- }
-
- mod->type = mod_sprite;
-}
-
-//=============================================================================
-
-/*
-@@@@@@@@@@@@@@@@@@@@@
-R_BeginRegistration
-
-Specifies the model that will be used as the world
-@@@@@@@@@@@@@@@@@@@@@
-*/
-void R_BeginRegistration (char *model)
-{
- char fullname[MAX_QPATH];
- cvar_t *flushmap;
-
- registration_sequence++;
- r_oldviewcluster = -1; // force markleafs
- Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model);
-
- D_FlushCaches ();
- // explicitly free the old map if different
- // this guarantees that mod_known[0] is the world map
- flushmap = ri.Cvar_Get ("flushmap", "0", 0);
- if ( strcmp(mod_known[0].name, fullname) || flushmap->value)
- Mod_Free (&mod_known[0]);
- r_worldmodel = R_RegisterModel (fullname);
- R_NewMap ();
-}
-
-
-/*
-@@@@@@@@@@@@@@@@@@@@@
-R_RegisterModel
-
-@@@@@@@@@@@@@@@@@@@@@
-*/
-struct model_s *R_RegisterModel (char *name)
-{
- model_t *mod;
- int i;
- dsprite_t *sprout;
- dmdl_t *pheader;
-
- mod = Mod_ForName (name, false);
- if (mod)
- {
- mod->registration_sequence = registration_sequence;
-
- // register any images used by the models
- if (mod->type == mod_sprite)
- {
- sprout = (dsprite_t *)mod->extradata;
- for (i=0 ; i<sprout->numframes ; i++)
- mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite);
- }
- else if (mod->type == mod_alias)
- {
- pheader = (dmdl_t *)mod->extradata;
- for (i=0 ; i<pheader->num_skins ; i++)
- mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
-//PGM
- mod->numframes = pheader->num_frames;
-//PGM
- }
- else if (mod->type == mod_brush)
- {
- for (i=0 ; i<mod->numtexinfo ; i++)
- mod->texinfo[i].image->registration_sequence = registration_sequence;
- }
- }
- return mod;
-}
-
-/*
-@@@@@@@@@@@@@@@@@@@@@
-R_EndRegistration
-
-@@@@@@@@@@@@@@@@@@@@@
-*/
-void R_EndRegistration (void)
-{
- int i;
- model_t *mod;
-
- for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++)
- {
- if (!mod->name[0])
- continue;
- if (mod->registration_sequence != registration_sequence)
- { // don't need this model
- Hunk_Free (mod->extradata);
- memset (mod, 0, sizeof(*mod));
- }
- else
- { // make sure it is paged in
- Com_PageInMemory (mod->extradata, mod->extradatasize);
- }
- }
-
- R_FreeUnusedImages ();
-}
-
-
-//=============================================================================
-
-/*
-================
-Mod_Free
-================
-*/
-void Mod_Free (model_t *mod)
-{
- Hunk_Free (mod->extradata);
- memset (mod, 0, sizeof(*mod));
-}
-
-/*
-================
-Mod_FreeAll
-================
-*/
-void Mod_FreeAll (void)
-{
- int i;
-
- for (i=0 ; i<mod_numknown ; i++)
- {
- if (mod_known[i].extradatasize)
- Mod_Free (&mod_known[i]);
- }
-}
--- a/ref_soft/r_model.h
+++ /dev/null
@@ -1,256 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#ifndef __MODEL__
-#define __MODEL__
-
-/*
-
-d*_t structures are on-disk representations
-m*_t structures are in-memory
-
-*/
-
-
-/*
-==============================================================================
-
-BRUSH MODELS
-
-==============================================================================
-*/
-
-
-//
-// in memory representation
-//
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
-typedef struct
-{
- vec3_t position;
-} mvertex_t;
-
-#define SIDE_FRONT 0
-#define SIDE_BACK 1
-#define SIDE_ON 2
-
-
-// plane_t structure
-// !!! if this is changed, it must be changed in asm_i386.h too !!!
-typedef struct mplane_s
-{
- vec3_t normal;
- float dist;
- byte type; // for texture axis selection and fast side tests
- byte signbits; // signx + signy<<1 + signz<<1
- byte pad[2];
-} mplane_t;
-
-
-// FIXME: differentiate from texinfo SURF_ flags
-#define SURF_PLANEBACK 2
-#define SURF_DRAWSKY 4 // sky brush face
-#define SURF_DRAWTURB 0x10
-#define SURF_DRAWBACKGROUND 0x40
-#define SURF_DRAWSKYBOX 0x80 // sky box
-
-#define SURF_FLOW 0x100 //PGM
-
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
-typedef struct
-{
- unsigned short v[2];
- unsigned int cachededgeoffset;
-} medge_t;
-
-typedef struct mtexinfo_s
-{
- float vecs[2][4];
- float mipadjust;
- image_t *image;
- int flags;
- int numframes;
- struct mtexinfo_s *next; // animation chain
-} mtexinfo_t;
-
-typedef struct msurface_s
-{
- int visframe; // should be drawn when node is crossed
-
- int dlightframe;
- int dlightbits;
-
- mplane_t *plane;
- int flags;
-
- int firstedge; // look up in model->surfedges[], negative numbers
- int numedges; // are backwards edges
-
-// surface generation data
- struct surfcache_s *cachespots[MIPLEVELS];
-
- short texturemins[2];
- short extents[2];
-
- mtexinfo_t *texinfo;
-
-// lighting info
- byte styles[MAXLIGHTMAPS];
- byte *samples; // [numstyles*surfsize]
-
- struct msurface_s *nextalphasurface;
-} msurface_t;
-
-
-#define CONTENTS_NODE -1
-typedef struct mnode_s
-{
-// common with leaf
- int contents; // CONTENTS_NODE, to differentiate from leafs
- int visframe; // node needs to be traversed if current
-
- short minmaxs[6]; // for bounding box culling
-
- struct mnode_s *parent;
-
-// node specific
- mplane_t *plane;
- struct mnode_s *children[2];
-
- unsigned short firstsurface;
- unsigned short numsurfaces;
-} mnode_t;
-
-
-
-typedef struct mleaf_s
-{
-// common with node
- int contents; // wil be something other than CONTENTS_NODE
- int visframe; // node needs to be traversed if current
-
- short minmaxs[6]; // for bounding box culling
-
- struct mnode_s *parent;
-
-// leaf specific
- int cluster;
- int area;
-
- msurface_t **firstmarksurface;
- int nummarksurfaces;
- int key; // BSP sequence number for leaf's contents
-} mleaf_t;
-
-
-//===================================================================
-
-//
-// Whole model
-//
-
-typedef enum {mod_bad, mod_brush, mod_sprite, mod_alias } modtype_t;
-
-typedef struct model_s
-{
- char name[MAX_QPATH];
-
- int registration_sequence;
-
- modtype_t type;
- int numframes;
-
- int flags;
-
-//
-// volume occupied by the model graphics
-//
- vec3_t mins, maxs;
-
-//
-// solid volume for clipping (sent from server)
-//
- qboolean clipbox;
- vec3_t clipmins, clipmaxs;
-
-//
-// brush model
-//
- int firstmodelsurface, nummodelsurfaces;
-
- int numsubmodels;
- dmodel_t *submodels;
-
- int numplanes;
- mplane_t *planes;
-
- int numleafs; // number of visible leafs, not counting 0
- mleaf_t *leafs;
-
- int numvertexes;
- mvertex_t *vertexes;
-
- int numedges;
- medge_t *edges;
-
- int numnodes;
- int firstnode;
- mnode_t *nodes;
-
- int numtexinfo;
- mtexinfo_t *texinfo;
-
- int numsurfaces;
- msurface_t *surfaces;
-
- int numsurfedges;
- int *surfedges;
-
- int nummarksurfaces;
- msurface_t **marksurfaces;
-
- dvis_t *vis;
-
- byte *lightdata;
-
- // for alias models and sprites
- image_t *skins[MAX_MD2SKINS];
- void *extradata;
- int extradatasize;
-} model_t;
-
-//============================================================================
-
-void Mod_Init (void);
-void Mod_ClearAll (void);
-model_t *Mod_ForName (char *name, qboolean crash);
-void *Mod_Extradata (model_t *mod); // handles caching
-void Mod_TouchModel (char *name);
-
-mleaf_t *Mod_PointInLeaf (float *p, model_t *model);
-byte *Mod_ClusterPVS (int cluster, model_t *model);
-
-void Mod_Modellist_f (void);
-void Mod_FreeAll (void);
-void Mod_Free (model_t *mod);
-
-extern int registration_sequence;
-
-#endif // __MODEL__
--- a/ref_soft/r_part.c
+++ /dev/null
@@ -1,638 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-#include "r_local.h"
-
-vec3_t r_pright, r_pup, r_ppn;
-
-#define PARTICLE_33 0
-#define PARTICLE_66 1
-#define PARTICLE_OPAQUE 2
-
-typedef struct
-{
- particle_t *particle;
- int level;
- int color;
-} partparms_t;
-
-static partparms_t partparms;
-
-#if id386 && !defined __linux__
-
-static unsigned s_prefetch_address;
-
-/*
-** BlendParticleXX
-**
-** Inputs:
-** EAX = color
-** EDI = pdest
-**
-** Scratch:
-** EBX = scratch (dstcolor)
-** EBP = scratch
-**
-** Outputs:
-** none
-*/
-__declspec(naked) void BlendParticle33( void )
-{
- // return vid.alphamap[color + dstcolor*256];
- __asm mov ebp, vid.alphamap
- __asm xor ebx, ebx
-
- __asm mov bl, byte ptr [edi]
- __asm shl ebx, 8
-
- __asm add ebp, ebx
- __asm add ebp, eax
-
- __asm mov al, byte ptr [ebp]
-
- __asm mov byte ptr [edi], al
-
- __asm ret
-}
-
-__declspec(naked) void BlendParticle66( void )
-{
- // return vid.alphamap[pcolor*256 + dstcolor];
- __asm mov ebp, vid.alphamap
- __asm xor ebx, ebx
-
- __asm shl eax, 8
- __asm mov bl, byte ptr [edi]
-
- __asm add ebp, ebx
- __asm add ebp, eax
-
- __asm mov al, byte ptr [ebp]
-
- __asm mov byte ptr [edi], al
-
- __asm ret
-}
-
-__declspec(naked) void BlendParticle100( void )
-{
- __asm mov byte ptr [edi], al
- __asm ret
-}
-
-/*
-** R_DrawParticle (asm version)
-**
-** Since we use __declspec( naked ) we don't have a stack frame
-** that we can use. Since I want to reserve EBP anyway, I tossed
-** all the important variables into statics. This routine isn't
-** meant to be re-entrant, so this shouldn't cause any problems
-** other than a slightly higher global memory footprint.
-**
-*/
-__declspec(naked) void R_DrawParticle( void )
-{
- static vec3_t local, transformed;
- static float zi;
- static int u, v, tmp;
- static short izi;
- static int ebpsave;
-
- static byte (*blendfunc)(void);
-
- /*
- ** must be memvars since x86 can't load constants
- ** directly. I guess I could use fld1, but that
- ** actually costs one more clock than fld [one]!
- */
- static float particle_z_clip = PARTICLE_Z_CLIP;
- static float one = 1.0F;
- static float point_five = 0.5F;
- static float eight_thousand_hex = 0x8000;
-
- /*
- ** save trashed variables
- */
- __asm mov ebpsave, ebp
- __asm push esi
- __asm push edi
-
- /*
- ** transform the particle
- */
- // VectorSubtract (pparticle->origin, r_origin, local);
- __asm mov esi, partparms.particle
- __asm fld dword ptr [esi+0] ; p_o.x
- __asm fsub dword ptr [r_origin+0] ; p_o.x-r_o.x
- __asm fld dword ptr [esi+4] ; p_o.y | p_o.x-r_o.x
- __asm fsub dword ptr [r_origin+4] ; p_o.y-r_o.y | p_o.x-r_o.x
- __asm fld dword ptr [esi+8] ; p_o.z | p_o.y-r_o.y | p_o.x-r_o.x
- __asm fsub dword ptr [r_origin+8] ; p_o.z-r_o.z | p_o.y-r_o.y | p_o.x-r_o.x
- __asm fxch st(2) ; p_o.x-r_o.x | p_o.y-r_o.y | p_o.z-r_o.z
- __asm fstp dword ptr [local+0] ; p_o.y-r_o.y | p_o.z-r_o.z
- __asm fstp dword ptr [local+4] ; p_o.z-r_o.z
- __asm fstp dword ptr [local+8] ; (empty)
-
- // transformed[0] = DotProduct(local, r_pright);
- // transformed[1] = DotProduct(local, r_pup);
- // transformed[2] = DotProduct(local, r_ppn);
- __asm fld dword ptr [local+0] ; l.x
- __asm fmul dword ptr [r_pright+0] ; l.x*pr.x
- __asm fld dword ptr [local+4] ; l.y | l.x*pr.x
- __asm fmul dword ptr [r_pright+4] ; l.y*pr.y | l.x*pr.x
- __asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
- __asm fmul dword ptr [r_pright+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
- __asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
- __asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
- __asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
- __asm fstp dword ptr [transformed+0] ; (empty)
-
- __asm fld dword ptr [local+0] ; l.x
- __asm fmul dword ptr [r_pup+0] ; l.x*pr.x
- __asm fld dword ptr [local+4] ; l.y | l.x*pr.x
- __asm fmul dword ptr [r_pup+4] ; l.y*pr.y | l.x*pr.x
- __asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
- __asm fmul dword ptr [r_pup+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
- __asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
- __asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
- __asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
- __asm fstp dword ptr [transformed+4] ; (empty)
-
- __asm fld dword ptr [local+0] ; l.x
- __asm fmul dword ptr [r_ppn+0] ; l.x*pr.x
- __asm fld dword ptr [local+4] ; l.y | l.x*pr.x
- __asm fmul dword ptr [r_ppn+4] ; l.y*pr.y | l.x*pr.x
- __asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
- __asm fmul dword ptr [r_ppn+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
- __asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
- __asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
- __asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
- __asm fstp dword ptr [transformed+8] ; (empty)
-
- /*
- ** make sure that the transformed particle is not in front of
- ** the particle Z clip plane. We can do the comparison in
- ** integer space since we know the sign of one of the inputs
- ** and can figure out the sign of the other easily enough.
- */
- // if (transformed[2] < PARTICLE_Z_CLIP)
- // return;
-
- __asm mov eax, dword ptr [transformed+8]
- __asm and eax, eax
- __asm js end
- __asm cmp eax, particle_z_clip
- __asm jl end
-
- /*
- ** project the point by initiating the 1/z calc
- */
- // zi = 1.0 / transformed[2];
- __asm fld one
- __asm fdiv dword ptr [transformed+8]
-
- /*
- ** bind the blend function pointer to the appropriate blender
- ** while we're dividing
- */
- //if ( level == PARTICLE_33 )
- // blendparticle = BlendParticle33;
- //else if ( level == PARTICLE_66 )
- // blendparticle = BlendParticle66;
- //else
- // blendparticle = BlendParticle100;
-
- __asm cmp partparms.level, PARTICLE_66
- __asm je blendfunc_66
- __asm jl blendfunc_33
- __asm lea ebx, BlendParticle100
- __asm jmp done_selecting_blend_func
-blendfunc_33:
- __asm lea ebx, BlendParticle33
- __asm jmp done_selecting_blend_func
-blendfunc_66:
- __asm lea ebx, BlendParticle66
-done_selecting_blend_func:
- __asm mov blendfunc, ebx
-
- // prefetch the next particle
- __asm mov ebp, s_prefetch_address
- __asm mov ebp, [ebp]
-
- // finish the above divide
- __asm fstp zi
-
- // u = (int)(xcenter + zi * transformed[0] + 0.5);
- // v = (int)(ycenter - zi * transformed[1] + 0.5);
- __asm fld zi ; zi
- __asm fmul dword ptr [transformed+0] ; zi * transformed[0]
- __asm fld zi ; zi | zi * transformed[0]
- __asm fmul dword ptr [transformed+4] ; zi * transformed[1] | zi * transformed[0]
- __asm fxch st(1) ; zi * transformed[0] | zi * transformed[1]
- __asm fadd xcenter ; xcenter + zi * transformed[0] | zi * transformed[1]
- __asm fxch st(1) ; zi * transformed[1] | xcenter + zi * transformed[0]
- __asm fld ycenter ; ycenter | zi * transformed[1] | xcenter + zi * transformed[0]
- __asm fsubrp st(1), st(0) ; ycenter - zi * transformed[1] | xcenter + zi * transformed[0]
- __asm fxch st(1) ; xcenter + zi * transformed[0] | ycenter + zi * transformed[1]
- __asm fadd point_five ; xcenter + zi * transformed[0] + 0.5 | ycenter - zi * transformed[1]
- __asm fxch st(1) ; ycenter - zi * transformed[1] | xcenter + zi * transformed[0] + 0.5
- __asm fadd point_five ; ycenter - zi * transformed[1] + 0.5 | xcenter + zi * transformed[0] + 0.5
- __asm fxch st(1) ; u | v
- __asm fistp dword ptr [u] ; v
- __asm fistp dword ptr [v] ; (empty)
-
- /*
- ** clip out the particle
- */
-
- // if ((v > d_vrectbottom_particle) ||
- // (u > d_vrectright_particle) ||
- // (v < d_vrecty) ||
- // (u < d_vrectx))
- // {
- // return;
- // }
-
- __asm mov ebx, u
- __asm mov ecx, v
- __asm cmp ecx, d_vrectbottom_particle
- __asm jg end
- __asm cmp ecx, d_vrecty
- __asm jl end
- __asm cmp ebx, d_vrectright_particle
- __asm jg end
- __asm cmp ebx, d_vrectx
- __asm jl end
-
- /*
- ** compute addresses of zbuffer, framebuffer, and
- ** compute the Z-buffer reference value.
- **
- ** EBX = U
- ** ECX = V
- **
- ** Outputs:
- ** ESI = Z-buffer address
- ** EDI = framebuffer address
- */
- // ESI = d_pzbuffer + (d_zwidth * v) + u;
- __asm mov esi, d_pzbuffer ; esi = d_pzbuffer
- __asm mov eax, d_zwidth ; eax = d_zwidth
- __asm mul ecx ; eax = d_zwidth*v
- __asm add eax, ebx ; eax = d_zwidth*v+u
- __asm shl eax, 1 ; eax = 2*(d_zwidth*v+u)
- __asm add esi, eax ; esi = ( short * ) ( d_pzbuffer + ( d_zwidth * v ) + u )
-
- // initiate
- // izi = (int)(zi * 0x8000);
- __asm fld zi
- __asm fmul eight_thousand_hex
-
- // EDI = pdest = d_viewbuffer + d_scantable[v] + u;
- __asm lea edi, [d_scantable+ecx*4]
- __asm mov edi, [edi]
- __asm add edi, d_viewbuffer
- __asm add edi, ebx
-
- // complete
- // izi = (int)(zi * 0x8000);
- __asm fistp tmp
- __asm mov eax, tmp
- __asm mov izi, ax
-
- /*
- ** determine the screen area covered by the particle,
- ** which also means clamping to a min and max
- */
- // pix = izi >> d_pix_shift;
- __asm xor edx, edx
- __asm mov dx, izi
- __asm mov ecx, d_pix_shift
- __asm shr dx, cl
-
- // if (pix < d_pix_min)
- // pix = d_pix_min;
- __asm cmp edx, d_pix_min
- __asm jge check_pix_max
- __asm mov edx, d_pix_min
- __asm jmp skip_pix_clamp
-
- // else if (pix > d_pix_max)
- // pix = d_pix_max;
-check_pix_max:
- __asm cmp edx, d_pix_max
- __asm jle skip_pix_clamp
- __asm mov edx, d_pix_max
-
-skip_pix_clamp:
-
- /*
- ** render the appropriate pixels
- **
- ** ECX = count (used for inner loop)
- ** EDX = count (used for outer loop)
- ** ESI = zbuffer
- ** EDI = framebuffer
- */
- __asm mov ecx, edx
-
- __asm cmp ecx, 1
- __asm ja over
-
-over:
-
- /*
- ** at this point:
- **
- ** ECX = count
- */
- __asm push ecx
- __asm push edi
- __asm push esi
-
-top_of_pix_vert_loop:
-
-top_of_pix_horiz_loop:
-
- // for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
- // {
- // for (i=0 ; i<pix ; i++)
- // {
- // if (pz[i] <= izi)
- // {
- // pdest[i] = blendparticle( color, pdest[i] );
- // }
- // }
- // }
- __asm xor eax, eax
-
- __asm mov ax, word ptr [esi]
-
- __asm cmp ax, izi
- __asm jg end_of_horiz_loop
-
-#if ENABLE_ZWRITES_FOR_PARTICLES
- __asm mov bp, izi
- __asm mov word ptr [esi], bp
-#endif
-
- __asm mov eax, partparms.color
-
- __asm call [blendfunc]
-
- __asm add edi, 1
- __asm add esi, 2
-
-end_of_horiz_loop:
-
- __asm dec ecx
- __asm jnz top_of_pix_horiz_loop
-
- __asm pop esi
- __asm pop edi
-
- __asm mov ebp, d_zwidth
- __asm shl ebp, 1
-
- __asm add esi, ebp
- __asm add edi, [r_screenwidth]
-
- __asm pop ecx
- __asm push ecx
-
- __asm push edi
- __asm push esi
-
- __asm dec edx
- __asm jnz top_of_pix_vert_loop
-
- __asm pop ecx
- __asm pop ecx
- __asm pop ecx
-
-end:
- __asm pop edi
- __asm pop esi
- __asm mov ebp, ebpsave
- __asm ret
-}
-
-#else
-
-static byte BlendParticle33( int pcolor, int dstcolor )
-{
- return vid.alphamap[pcolor + dstcolor*256];
-}
-
-static byte BlendParticle66( int pcolor, int dstcolor )
-{
- return vid.alphamap[pcolor*256+dstcolor];
-}
-
-static byte BlendParticle100( int pcolor, int dstcolor )
-{
- dstcolor = dstcolor;
- return pcolor;
-}
-
-/*
-** R_DrawParticle
-**
-** Yes, this is amazingly slow, but it's the C reference
-** implementation and should be both robust and vaguely
-** understandable. The only time this path should be
-** executed is if we're debugging on x86 or if we're
-** recompiling and deploying on a non-x86 platform.
-**
-** To minimize error and improve readability I went the
-** function pointer route. This exacts some overhead, but
-** it pays off in clean and easy to understand code.
-*/
-void R_DrawParticle( void )
-{
- particle_t *pparticle = partparms.particle;
- int level = partparms.level;
- vec3_t local, transformed;
- float zi;
- byte *pdest;
- short *pz;
- int color = pparticle->color;
- int i, izi, pix, count, u, v;
- byte (*blendparticle)( int, int );
-
- /*
- ** transform the particle
- */
- VectorSubtract (pparticle->origin, r_origin, local);
-
- transformed[0] = DotProduct(local, r_pright);
- transformed[1] = DotProduct(local, r_pup);
- transformed[2] = DotProduct(local, r_ppn);
-
- if (transformed[2] < PARTICLE_Z_CLIP)
- return;
-
- /*
- ** bind the blend function pointer to the appropriate blender
- */
- if ( level == PARTICLE_33 )
- blendparticle = BlendParticle33;
- else if ( level == PARTICLE_66 )
- blendparticle = BlendParticle66;
- else
- blendparticle = BlendParticle100;
-
- /*
- ** project the point
- */
- // FIXME: preadjust xcenter and ycenter
- zi = 1.0 / transformed[2];
- u = (int)(xcenter + zi * transformed[0] + 0.5);
- v = (int)(ycenter - zi * transformed[1] + 0.5);
-
- if ((v > d_vrectbottom_particle) ||
- (u > d_vrectright_particle) ||
- (v < d_vrecty) ||
- (u < d_vrectx))
- {
- return;
- }
-
- /*
- ** compute addresses of zbuffer, framebuffer, and
- ** compute the Z-buffer reference value.
- */
- pz = d_pzbuffer + (d_zwidth * v) + u;
- pdest = d_viewbuffer + d_scantable[v] + u;
- izi = (int)(zi * 0x8000);
-
- /*
- ** determine the screen area covered by the particle,
- ** which also means clamping to a min and max
- */
- pix = izi >> d_pix_shift;
- if (pix < d_pix_min)
- pix = d_pix_min;
- else if (pix > d_pix_max)
- pix = d_pix_max;
-
- /*
- ** render the appropriate pixels
- */
- count = pix;
-
- switch (level) {
- case PARTICLE_33 :
- for ( ; count ; count--, pz += d_zwidth, pdest += r_screenwidth)
- {
-//FIXME--do it in blocks of 8?
- for (i=0 ; i<pix ; i++)
- {
- if (pz[i] <= izi)
- {
- pz[i] = izi;
- pdest[i] = vid.alphamap[color + ((int)pdest[i]<<8)];
- }
- }
- }
- break;
-
- case PARTICLE_66 :
- for ( ; count ; count--, pz += d_zwidth, pdest += r_screenwidth)
- {
- for (i=0 ; i<pix ; i++)
- {
- if (pz[i] <= izi)
- {
- pz[i] = izi;
- pdest[i] = vid.alphamap[(color<<8) + (int)pdest[i]];
- }
- }
- }
- break;
-
- default: //100
- for ( ; count ; count--, pz += d_zwidth, pdest += r_screenwidth)
- {
- for (i=0 ; i<pix ; i++)
- {
- if (pz[i] <= izi)
- {
- pz[i] = izi;
- pdest[i] = color;
- }
- }
- }
- break;
- }
-}
-
-#endif // !id386
-
-/*
-** R_DrawParticles
-**
-** Responsible for drawing all of the particles in the particle list
-** throughout the world. Doesn't care if we're using the C path or
-** if we're using the asm path, it simply assigns a function pointer
-** and goes.
-*/
-void R_DrawParticles (void)
-{
- particle_t *p;
- int i;
- extern unsigned long fpu_sp24_cw, fpu_chop_cw;
-
- VectorScale( vright, xscaleshrink, r_pright );
- VectorScale( vup, yscaleshrink, r_pup );
- VectorCopy( vpn, r_ppn );
-
-#if id386 && !defined __linux__
- __asm fldcw word ptr [fpu_sp24_cw]
-#endif
-
- for (p=r_newrefdef.particles, i=0 ; i<r_newrefdef.num_particles ; i++,p++)
- {
-
- if ( p->alpha > 0.66 )
- partparms.level = PARTICLE_OPAQUE;
- else if ( p->alpha > 0.33 )
- partparms.level = PARTICLE_66;
- else
- partparms.level = PARTICLE_33;
-
- partparms.particle = p;
- partparms.color = p->color;
-
-#if id386 && !defined __linux__
- if ( i < r_newrefdef.num_particles-1 )
- s_prefetch_address = ( unsigned int ) ( p + 1 );
- else
- s_prefetch_address = ( unsigned int ) r_newrefdef.particles;
-#endif
-
- R_DrawParticle();
- }
-
-#if id386 && !defined __linux__
- __asm fldcw word ptr [fpu_chop_cw]
-#endif
-
-}
-
--- a/ref_soft/r_poly.c
+++ /dev/null
@@ -1,1244 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-#include <assert.h>
-#include "r_local.h"
-
-#define AFFINE_SPANLET_SIZE 16
-#define AFFINE_SPANLET_SIZE_BITS 4
-
-typedef struct
-{
- byte *pbase, *pdest;
- short *pz;
- fixed16_t s, t;
- fixed16_t sstep, tstep;
- int izi, izistep, izistep_times_2;
- int spancount;
- unsigned u, v;
-} spanletvars_t;
-
-spanletvars_t s_spanletvars;
-
-static int r_polyblendcolor;
-
-static espan_t *s_polygon_spans;
-
-polydesc_t r_polydesc;
-
-msurface_t *r_alpha_surfaces;
-
-extern int *r_turb_turb;
-
-static int clip_current;
-vec5_t r_clip_verts[2][MAXWORKINGVERTS+2];
-
-static int s_minindex, s_maxindex;
-
-static void R_DrawPoly( qboolean iswater );
-
-/*
-** R_DrawSpanletOpaque
-*/
-void R_DrawSpanletOpaque( void )
-{
- unsigned btemp;
-
- do
- {
- unsigned ts, tt;
-
- ts = s_spanletvars.s >> 16;
- tt = s_spanletvars.t >> 16;
-
- btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth);
- if (btemp != 255)
- {
- if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
- {
- *s_spanletvars.pz = s_spanletvars.izi >> 16;
- *s_spanletvars.pdest = btemp;
- }
- }
-
- s_spanletvars.izi += s_spanletvars.izistep;
- s_spanletvars.pdest++;
- s_spanletvars.pz++;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
- } while (--s_spanletvars.spancount > 0);
-}
-
-/*
-** R_DrawSpanletTurbulentStipple33
-*/
-void R_DrawSpanletTurbulentStipple33( void )
-{
- unsigned btemp;
- int sturb, tturb;
- byte *pdest = s_spanletvars.pdest;
- short *pz = s_spanletvars.pz;
- int izi = s_spanletvars.izi;
-
- if ( s_spanletvars.v & 1 )
- {
- s_spanletvars.pdest += s_spanletvars.spancount;
- s_spanletvars.pz += s_spanletvars.spancount;
-
- if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
- s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
- else
- s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
-
- if ( s_spanletvars.u & 1 )
- {
- izi += s_spanletvars.izistep;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
-
- pdest++;
- pz++;
- s_spanletvars.spancount--;
- }
-
- s_spanletvars.sstep *= 2;
- s_spanletvars.tstep *= 2;
-
- while ( s_spanletvars.spancount > 0 )
- {
- sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
- tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
-
- btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
-
- if ( *pz <= ( izi >> 16 ) )
- *pdest = btemp;
-
- izi += s_spanletvars.izistep_times_2;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
-
- pdest += 2;
- pz += 2;
-
- s_spanletvars.spancount -= 2;
- }
- }
-}
-
-/*
-** R_DrawSpanletTurbulentStipple66
-*/
-void R_DrawSpanletTurbulentStipple66( void )
-{
- unsigned btemp;
- int sturb, tturb;
- byte *pdest = s_spanletvars.pdest;
- short *pz = s_spanletvars.pz;
- int izi = s_spanletvars.izi;
-
- if ( !( s_spanletvars.v & 1 ) )
- {
- s_spanletvars.pdest += s_spanletvars.spancount;
- s_spanletvars.pz += s_spanletvars.spancount;
-
- if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
- s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
- else
- s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
-
- if ( s_spanletvars.u & 1 )
- {
- izi += s_spanletvars.izistep;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
-
- pdest++;
- pz++;
- s_spanletvars.spancount--;
- }
-
- s_spanletvars.sstep *= 2;
- s_spanletvars.tstep *= 2;
-
- while ( s_spanletvars.spancount > 0 )
- {
- sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
- tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
-
- btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
-
- if ( *pz <= ( izi >> 16 ) )
- *pdest = btemp;
-
- izi += s_spanletvars.izistep_times_2;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
-
- pdest += 2;
- pz += 2;
-
- s_spanletvars.spancount -= 2;
- }
- }
- else
- {
- s_spanletvars.pdest += s_spanletvars.spancount;
- s_spanletvars.pz += s_spanletvars.spancount;
-
- if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
- s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
- else
- s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
-
- while ( s_spanletvars.spancount > 0 )
- {
- sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
- tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
-
- btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
-
- if ( *pz <= ( izi >> 16 ) )
- *pdest = btemp;
-
- izi += s_spanletvars.izistep;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
-
- pdest++;
- pz++;
-
- s_spanletvars.spancount--;
- }
- }
-}
-
-/*
-** R_DrawSpanletTurbulentBlended
-*/
-void R_DrawSpanletTurbulentBlended66( void )
-{
- unsigned btemp;
- int sturb, tturb;
-
- do
- {
- sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
- tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
-
- btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
-
- if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) )
- *s_spanletvars.pdest = vid.alphamap[btemp*256+*s_spanletvars.pdest];
-
- s_spanletvars.izi += s_spanletvars.izistep;
- s_spanletvars.pdest++;
- s_spanletvars.pz++;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
-
- } while ( --s_spanletvars.spancount > 0 );
-}
-
-void R_DrawSpanletTurbulentBlended33( void )
-{
- unsigned btemp;
- int sturb, tturb;
-
- do
- {
- sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63;
- tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63;
-
- btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) );
-
- if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) )
- *s_spanletvars.pdest = vid.alphamap[btemp+*s_spanletvars.pdest*256];
-
- s_spanletvars.izi += s_spanletvars.izistep;
- s_spanletvars.pdest++;
- s_spanletvars.pz++;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
-
- } while ( --s_spanletvars.spancount > 0 );
-}
-
-/*
-** R_DrawSpanlet33
-*/
-void R_DrawSpanlet33( void )
-{
- unsigned btemp;
-
- do
- {
- unsigned ts, tt;
-
- ts = s_spanletvars.s >> 16;
- tt = s_spanletvars.t >> 16;
-
- btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth);
-
- if ( btemp != 255 )
- {
- if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
- {
- *s_spanletvars.pdest = vid.alphamap[btemp+*s_spanletvars.pdest*256];
- }
- }
-
- s_spanletvars.izi += s_spanletvars.izistep;
- s_spanletvars.pdest++;
- s_spanletvars.pz++;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
- } while (--s_spanletvars.spancount > 0);
-}
-
-void R_DrawSpanletConstant33( void )
-{
- do
- {
- if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
- {
- *s_spanletvars.pdest = vid.alphamap[r_polyblendcolor+*s_spanletvars.pdest*256];
- }
-
- s_spanletvars.izi += s_spanletvars.izistep;
- s_spanletvars.pdest++;
- s_spanletvars.pz++;
- } while (--s_spanletvars.spancount > 0);
-}
-
-/*
-** R_DrawSpanlet66
-*/
-void R_DrawSpanlet66( void )
-{
- unsigned btemp;
-
- do
- {
- unsigned ts, tt;
-
- ts = s_spanletvars.s >> 16;
- tt = s_spanletvars.t >> 16;
-
- btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth);
-
- if ( btemp != 255 )
- {
- if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16))
- {
- *s_spanletvars.pdest = vid.alphamap[btemp*256+*s_spanletvars.pdest];
- }
- }
-
- s_spanletvars.izi += s_spanletvars.izistep;
- s_spanletvars.pdest++;
- s_spanletvars.pz++;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
- } while (--s_spanletvars.spancount > 0);
-}
-
-/*
-** R_DrawSpanlet33Stipple
-*/
-void R_DrawSpanlet33Stipple( void )
-{
- unsigned btemp;
- byte *pdest = s_spanletvars.pdest;
- short *pz = s_spanletvars.pz;
- int izi = s_spanletvars.izi;
-
- if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) )
- {
- s_spanletvars.pdest += s_spanletvars.spancount;
- s_spanletvars.pz += s_spanletvars.spancount;
-
- if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
- s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
- else
- s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
-
- if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) )
- {
- izi += s_spanletvars.izistep;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
-
- pdest++;
- pz++;
- s_spanletvars.spancount--;
- }
-
- s_spanletvars.sstep *= 2;
- s_spanletvars.tstep *= 2;
-
- while ( s_spanletvars.spancount > 0 )
- {
- unsigned s = s_spanletvars.s >> 16;
- unsigned t = s_spanletvars.t >> 16;
-
- btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
-
- if ( btemp != 255 )
- {
- if ( *pz <= ( izi >> 16 ) )
- *pdest = btemp;
- }
-
- izi += s_spanletvars.izistep_times_2;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
-
- pdest += 2;
- pz += 2;
-
- s_spanletvars.spancount -= 2;
- }
- }
-}
-
-/*
-** R_DrawSpanlet66Stipple
-*/
-void R_DrawSpanlet66Stipple( void )
-{
- unsigned btemp;
- byte *pdest = s_spanletvars.pdest;
- short *pz = s_spanletvars.pz;
- int izi = s_spanletvars.izi;
-
- s_spanletvars.pdest += s_spanletvars.spancount;
- s_spanletvars.pz += s_spanletvars.spancount;
-
- if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
- s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
- else
- s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
-
- if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) )
- {
- if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) )
- {
- izi += s_spanletvars.izistep;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
-
- pdest++;
- pz++;
- s_spanletvars.spancount--;
- }
-
- s_spanletvars.sstep *= 2;
- s_spanletvars.tstep *= 2;
-
- while ( s_spanletvars.spancount > 0 )
- {
- unsigned s = s_spanletvars.s >> 16;
- unsigned t = s_spanletvars.t >> 16;
-
- btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
-
- if ( btemp != 255 )
- {
- if ( *pz <= ( izi >> 16 ) )
- *pdest = btemp;
- }
-
- izi += s_spanletvars.izistep_times_2;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
-
- pdest += 2;
- pz += 2;
-
- s_spanletvars.spancount -= 2;
- }
- }
- else
- {
- while ( s_spanletvars.spancount > 0 )
- {
- unsigned s = s_spanletvars.s >> 16;
- unsigned t = s_spanletvars.t >> 16;
-
- btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
-
- if ( btemp != 255 )
- {
- if ( *pz <= ( izi >> 16 ) )
- *pdest = btemp;
- }
-
- izi += s_spanletvars.izistep;
- s_spanletvars.s += s_spanletvars.sstep;
- s_spanletvars.t += s_spanletvars.tstep;
-
- pdest++;
- pz++;
-
- s_spanletvars.spancount--;
- }
- }
-}
-
-/*
-** R_ClipPolyFace
-**
-** Clips the winding at clip_verts[clip_current] and changes clip_current
-** Throws out the back side
-*/
-int R_ClipPolyFace (int nump, clipplane_t *pclipplane)
-{
- int i, outcount;
- float dists[MAXWORKINGVERTS+3];
- float frac, clipdist, *pclipnormal;
- float *in, *instep, *outstep, *vert2;
-
- clipdist = pclipplane->dist;
- pclipnormal = pclipplane->normal;
-
-// calc dists
- if (clip_current)
- {
- in = r_clip_verts[1][0];
- outstep = r_clip_verts[0][0];
- clip_current = 0;
- }
- else
- {
- in = r_clip_verts[0][0];
- outstep = r_clip_verts[1][0];
- clip_current = 1;
- }
-
- instep = in;
- for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
- {
- dists[i] = DotProduct (instep, pclipnormal) - clipdist;
- }
-
-// handle wraparound case
- dists[nump] = dists[0];
- memcpy (instep, in, sizeof (vec5_t));
-
-
-// clip the winding
- instep = in;
- outcount = 0;
-
- for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
- {
- if (dists[i] >= 0)
- {
- memcpy (outstep, instep, sizeof (vec5_t));
- outstep += sizeof (vec5_t) / sizeof (float);
- outcount++;
- }
-
- if (dists[i] == 0 || dists[i+1] == 0)
- continue;
-
- if ( (dists[i] > 0) == (dists[i+1] > 0) )
- continue;
-
- // split it into a new vertex
- frac = dists[i] / (dists[i] - dists[i+1]);
-
- vert2 = instep + sizeof (vec5_t) / sizeof (float);
-
- outstep[0] = instep[0] + frac*(vert2[0] - instep[0]);
- outstep[1] = instep[1] + frac*(vert2[1] - instep[1]);
- outstep[2] = instep[2] + frac*(vert2[2] - instep[2]);
- outstep[3] = instep[3] + frac*(vert2[3] - instep[3]);
- outstep[4] = instep[4] + frac*(vert2[4] - instep[4]);
-
- outstep += sizeof (vec5_t) / sizeof (float);
- outcount++;
- }
-
- return outcount;
-}
-
-/*
-** R_PolygonDrawSpans
-*/
-void R_PolygonDrawSpans(espan_t *pspan, qboolean iswater )
-{
- int count;
- fixed16_t snext, tnext;
- float sdivz, tdivz, zi, z, du, dv, spancountminus1;
- float sdivzspanletstepu, tdivzspanletstepu, zispanletstepu;
-
- s_spanletvars.pbase = cacheblock;
-
- if ( iswater )
- r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
-
- sdivzspanletstepu = d_sdivzstepu * AFFINE_SPANLET_SIZE;
- tdivzspanletstepu = d_tdivzstepu * AFFINE_SPANLET_SIZE;
- zispanletstepu = d_zistepu * AFFINE_SPANLET_SIZE;
-
-// we count on FP exceptions being turned off to avoid range problems
- s_spanletvars.izistep = (int)(d_zistepu * 0x8000 * 0x10000);
- s_spanletvars.izistep_times_2 = s_spanletvars.izistep * 2;
-
- s_spanletvars.pz = 0;
-
- do
- {
- s_spanletvars.pdest = (byte *)d_viewbuffer + ( d_scantable[pspan->v] /*r_screenwidth * pspan->v*/) + pspan->u;
- s_spanletvars.pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
- s_spanletvars.u = pspan->u;
- s_spanletvars.v = pspan->v;
-
- count = pspan->count;
-
- if (count <= 0)
- goto NextSpan;
-
- // calculate the initial s/z, t/z, 1/z, s, and t and clamp
- du = (float)pspan->u;
- dv = (float)pspan->v;
-
- sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
- tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
-
- zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
- z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
- // we count on FP exceptions being turned off to avoid range problems
- s_spanletvars.izi = (int)(zi * 0x8000 * 0x10000);
-
- s_spanletvars.s = (int)(sdivz * z) + sadjust;
- s_spanletvars.t = (int)(tdivz * z) + tadjust;
-
- if ( !iswater )
- {
- if (s_spanletvars.s > bbextents)
- s_spanletvars.s = bbextents;
- else if (s_spanletvars.s < 0)
- s_spanletvars.s = 0;
-
- if (s_spanletvars.t > bbextentt)
- s_spanletvars.t = bbextentt;
- else if (s_spanletvars.t < 0)
- s_spanletvars.t = 0;
- }
-
- do
- {
- // calculate s and t at the far end of the span
- if (count >= AFFINE_SPANLET_SIZE )
- s_spanletvars.spancount = AFFINE_SPANLET_SIZE;
- else
- s_spanletvars.spancount = count;
-
- count -= s_spanletvars.spancount;
-
- if (count)
- {
- // calculate s/z, t/z, zi->fixed s and t at far end of span,
- // calculate s and t steps across span by shifting
- sdivz += sdivzspanletstepu;
- tdivz += tdivzspanletstepu;
- zi += zispanletstepu;
- z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
-
- snext = (int)(sdivz * z) + sadjust;
- tnext = (int)(tdivz * z) + tadjust;
-
- if ( !iswater )
- {
- if (snext > bbextents)
- snext = bbextents;
- else if (snext < AFFINE_SPANLET_SIZE)
- snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
- // from causing overstepping & running off the
- // edge of the texture
-
- if (tnext > bbextentt)
- tnext = bbextentt;
- else if (tnext < AFFINE_SPANLET_SIZE)
- tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
- }
-
- s_spanletvars.sstep = (snext - s_spanletvars.s) >> AFFINE_SPANLET_SIZE_BITS;
- s_spanletvars.tstep = (tnext - s_spanletvars.t) >> AFFINE_SPANLET_SIZE_BITS;
- }
- else
- {
- // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
- // can't step off polygon), clamp, calculate s and t steps across
- // span by division, biasing steps low so we don't run off the
- // texture
- spancountminus1 = (float)(s_spanletvars.spancount - 1);
- sdivz += d_sdivzstepu * spancountminus1;
- tdivz += d_tdivzstepu * spancountminus1;
- zi += d_zistepu * spancountminus1;
- z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
- snext = (int)(sdivz * z) + sadjust;
- tnext = (int)(tdivz * z) + tadjust;
-
- if ( !iswater )
- {
- if (snext > bbextents)
- snext = bbextents;
- else if (snext < AFFINE_SPANLET_SIZE)
- snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
- // from causing overstepping & running off the
- // edge of the texture
-
- if (tnext > bbextentt)
- tnext = bbextentt;
- else if (tnext < AFFINE_SPANLET_SIZE)
- tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
- }
-
- if (s_spanletvars.spancount > 1)
- {
- s_spanletvars.sstep = (snext - s_spanletvars.s) / (s_spanletvars.spancount - 1);
- s_spanletvars.tstep = (tnext - s_spanletvars.t) / (s_spanletvars.spancount - 1);
- }
- }
-
- if ( iswater )
- {
- s_spanletvars.s = s_spanletvars.s & ((CYCLE<<16)-1);
- s_spanletvars.t = s_spanletvars.t & ((CYCLE<<16)-1);
- }
-
- r_polydesc.drawspanlet();
-
- s_spanletvars.s = snext;
- s_spanletvars.t = tnext;
-
- } while (count > 0);
-
-NextSpan:
- pspan++;
-
- } while (pspan->count != DS_SPAN_LIST_END);
-}
-
-/*
-**
-** R_PolygonScanLeftEdge
-**
-** Goes through the polygon and scans the left edge, filling in
-** screen coordinate data for the spans
-*/
-void R_PolygonScanLeftEdge (void)
-{
- int i, v, itop, ibottom, lmaxindex;
- emitpoint_t *pvert, *pnext;
- espan_t *pspan;
- float du, dv, vtop, vbottom, slope;
- fixed16_t u, u_step;
-
- pspan = s_polygon_spans;
- i = s_minindex;
- if (i == 0)
- i = r_polydesc.nump;
-
- lmaxindex = s_maxindex;
- if (lmaxindex == 0)
- lmaxindex = r_polydesc.nump;
-
- vtop = ceil (r_polydesc.pverts[i].v);
-
- do
- {
- pvert = &r_polydesc.pverts[i];
- pnext = pvert - 1;
-
- vbottom = ceil (pnext->v);
-
- if (vtop < vbottom)
- {
- du = pnext->u - pvert->u;
- dv = pnext->v - pvert->v;
-
- slope = du / dv;
- u_step = (int)(slope * 0x10000);
- // adjust u to ceil the integer portion
- u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
- (0x10000 - 1);
- itop = (int)vtop;
- ibottom = (int)vbottom;
-
- for (v=itop ; v<ibottom ; v++)
- {
- pspan->u = u >> 16;
- pspan->v = v;
- u += u_step;
- pspan++;
- }
- }
-
- vtop = vbottom;
-
- i--;
- if (i == 0)
- i = r_polydesc.nump;
-
- } while (i != lmaxindex);
-}
-
-/*
-** R_PolygonScanRightEdge
-**
-** Goes through the polygon and scans the right edge, filling in
-** count values.
-*/
-void R_PolygonScanRightEdge (void)
-{
- int i, v, itop, ibottom;
- emitpoint_t *pvert, *pnext;
- espan_t *pspan;
- float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
- fixed16_t u, u_step;
-
- pspan = s_polygon_spans;
- i = s_minindex;
-
- vvert = r_polydesc.pverts[i].v;
- if (vvert < r_refdef.fvrecty_adj)
- vvert = r_refdef.fvrecty_adj;
- if (vvert > r_refdef.fvrectbottom_adj)
- vvert = r_refdef.fvrectbottom_adj;
-
- vtop = ceil (vvert);
-
- do
- {
- pvert = &r_polydesc.pverts[i];
- pnext = pvert + 1;
-
- vnext = pnext->v;
- if (vnext < r_refdef.fvrecty_adj)
- vnext = r_refdef.fvrecty_adj;
- if (vnext > r_refdef.fvrectbottom_adj)
- vnext = r_refdef.fvrectbottom_adj;
-
- vbottom = ceil (vnext);
-
- if (vtop < vbottom)
- {
- uvert = pvert->u;
- if (uvert < r_refdef.fvrectx_adj)
- uvert = r_refdef.fvrectx_adj;
- if (uvert > r_refdef.fvrectright_adj)
- uvert = r_refdef.fvrectright_adj;
-
- unext = pnext->u;
- if (unext < r_refdef.fvrectx_adj)
- unext = r_refdef.fvrectx_adj;
- if (unext > r_refdef.fvrectright_adj)
- unext = r_refdef.fvrectright_adj;
-
- du = unext - uvert;
- dv = vnext - vvert;
- slope = du / dv;
- u_step = (int)(slope * 0x10000);
- // adjust u to ceil the integer portion
- u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
- (0x10000 - 1);
- itop = (int)vtop;
- ibottom = (int)vbottom;
-
- for (v=itop ; v<ibottom ; v++)
- {
- pspan->count = (u >> 16) - pspan->u;
- u += u_step;
- pspan++;
- }
- }
-
- vtop = vbottom;
- vvert = vnext;
-
- i++;
- if (i == r_polydesc.nump)
- i = 0;
-
- } while (i != s_maxindex);
-
- pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
-}
-
-/*
-** R_ClipAndDrawPoly
-*/
-void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured )
-{
- emitpoint_t outverts[MAXWORKINGVERTS+3], *pout;
- float *pv;
- int i, nump;
- float scale;
- vec3_t transformed, local;
-
- if ( !textured )
- {
- r_polydesc.drawspanlet = R_DrawSpanletConstant33;
- }
- else
- {
-
- /*
- ** choose the correct spanlet routine based on alpha
- */
- if ( alpha == 1 )
- {
- // isturbulent is ignored because we know that turbulent surfaces
- // can't be opaque
- r_polydesc.drawspanlet = R_DrawSpanletOpaque;
- }
- else
- {
- if ( sw_stipplealpha->value )
- {
- if ( isturbulent )
- {
- if ( alpha > 0.33 )
- r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple66;
- else
- r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple33;
- }
- else
- {
- if ( alpha > 0.33 )
- r_polydesc.drawspanlet = R_DrawSpanlet66Stipple;
- else
- r_polydesc.drawspanlet = R_DrawSpanlet33Stipple;
- }
- }
- else
- {
- if ( isturbulent )
- {
- if ( alpha > 0.33 )
- r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended66;
- else
- r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended33;
- }
- else
- {
- if ( alpha > 0.33 )
- r_polydesc.drawspanlet = R_DrawSpanlet66;
- else
- r_polydesc.drawspanlet = R_DrawSpanlet33;
- }
- }
- }
- }
-
- // clip to the frustum in worldspace
- nump = r_polydesc.nump;
- clip_current = 0;
-
- for (i=0 ; i<4 ; i++)
- {
- nump = R_ClipPolyFace (nump, &view_clipplanes[i]);
- if (nump < 3)
- return;
- if (nump > MAXWORKINGVERTS)
- ri.Sys_Error(ERR_DROP, "R_ClipAndDrawPoly: too many points: %d", nump );
- }
-
-// transform vertices into viewspace and project
- pv = &r_clip_verts[clip_current][0][0];
-
- for (i=0 ; i<nump ; i++)
- {
- VectorSubtract (pv, r_origin, local);
- TransformVector (local, transformed);
-
- if (transformed[2] < NEAR_CLIP)
- transformed[2] = NEAR_CLIP;
-
- pout = &outverts[i];
- pout->zi = 1.0 / transformed[2];
-
- pout->s = pv[3];
- pout->t = pv[4];
-
- scale = xscale * pout->zi;
- pout->u = (xcenter + scale * transformed[0]);
-
- scale = yscale * pout->zi;
- pout->v = (ycenter - scale * transformed[1]);
-
- pv += sizeof (vec5_t) / sizeof (pv);
- }
-
-// draw it
- r_polydesc.nump = nump;
- r_polydesc.pverts = outverts;
-
- R_DrawPoly( isturbulent );
-}
-
-/*
-** R_BuildPolygonFromSurface
-*/
-void R_BuildPolygonFromSurface(msurface_t *fa)
-{
- int i, lindex, lnumverts;
- medge_t *pedges, *r_pedge;
- int vertpage;
- float *vec;
- vec5_t *pverts;
- float tmins[2] = { 0, 0 };
-
- r_polydesc.nump = 0;
-
- // reconstruct the polygon
- pedges = currentmodel->edges;
- lnumverts = fa->numedges;
- vertpage = 0;
-
- pverts = r_clip_verts[0];
-
- for (i=0 ; i<lnumverts ; i++)
- {
- lindex = currentmodel->surfedges[fa->firstedge + i];
-
- if (lindex > 0)
- {
- r_pedge = &pedges[lindex];
- vec = currentmodel->vertexes[r_pedge->v[0]].position;
- }
- else
- {
- r_pedge = &pedges[-lindex];
- vec = currentmodel->vertexes[r_pedge->v[1]].position;
- }
-
- VectorCopy (vec, pverts[i] );
- }
-
- VectorCopy( fa->texinfo->vecs[0], r_polydesc.vright );
- VectorCopy( fa->texinfo->vecs[1], r_polydesc.vup );
- VectorCopy( fa->plane->normal, r_polydesc.vpn );
- VectorCopy( r_origin, r_polydesc.viewer_position );
-
- if ( fa->flags & SURF_PLANEBACK )
- {
- VectorSubtract( vec3_origin, r_polydesc.vpn, r_polydesc.vpn );
- }
-
- if ( fa->texinfo->flags & SURF_WARP )
- {
- r_polydesc.pixels = fa->texinfo->image->pixels[0];
- r_polydesc.pixel_width = fa->texinfo->image->width;
- r_polydesc.pixel_height = fa->texinfo->image->height;
- }
- else
- {
- surfcache_t *scache;
-
- scache = D_CacheSurface( fa, 0 );
-
- r_polydesc.pixels = scache->data;
- r_polydesc.pixel_width = scache->width;
- r_polydesc.pixel_height = scache->height;
-
- tmins[0] = fa->texturemins[0];
- tmins[1] = fa->texturemins[1];
- }
-
- r_polydesc.dist = DotProduct( r_polydesc.vpn, pverts[0] );
-
- r_polydesc.s_offset = fa->texinfo->vecs[0][3] - tmins[0];
- r_polydesc.t_offset = fa->texinfo->vecs[1][3] - tmins[1];
-
- // scrolling texture addition
- if (fa->texinfo->flags & SURF_FLOWING)
- {
- r_polydesc.s_offset += -128 * ( (r_newrefdef.time*0.25) - (int)(r_newrefdef.time*0.25) );
- }
-
- r_polydesc.nump = lnumverts;
-}
-
-/*
-** R_PolygonCalculateGradients
-*/
-void R_PolygonCalculateGradients (void)
-{
- vec3_t p_normal, p_saxis, p_taxis;
- float distinv;
-
- TransformVector (r_polydesc.vpn, p_normal);
- TransformVector (r_polydesc.vright, p_saxis);
- TransformVector (r_polydesc.vup, p_taxis);
-
- distinv = 1.0 / (-(DotProduct (r_polydesc.viewer_position, r_polydesc.vpn)) + r_polydesc.dist );
-
- d_sdivzstepu = p_saxis[0] * xscaleinv;
- d_sdivzstepv = -p_saxis[1] * yscaleinv;
- d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv;
-
- d_tdivzstepu = p_taxis[0] * xscaleinv;
- d_tdivzstepv = -p_taxis[1] * yscaleinv;
- d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv;
-
- d_zistepu = p_normal[0] * xscaleinv * distinv;
- d_zistepv = -p_normal[1] * yscaleinv * distinv;
- d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - ycenter * d_zistepv;
-
- sadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vright) + r_polydesc.s_offset ) * 0x10000 );
- tadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vup ) + r_polydesc.t_offset ) * 0x10000 );
-
-// -1 (-epsilon) so we never wander off the edge of the texture
- bbextents = (r_polydesc.pixel_width << 16) - 1;
- bbextentt = (r_polydesc.pixel_height << 16) - 1;
-}
-
-/*
-** R_DrawPoly
-**
-** Polygon drawing function. Uses the polygon described in r_polydesc
-** to calculate edges and gradients, then renders the resultant spans.
-**
-** This should NOT be called externally since it doesn't do clipping!
-*/
-static void R_DrawPoly( qboolean iswater )
-{
- int i, nump;
- float ymin, ymax;
- emitpoint_t *pverts;
- espan_t spans[MAXHEIGHT+1];
-
- s_polygon_spans = spans;
-
-// find the top and bottom vertices, and make sure there's at least one scan to
-// draw
- ymin = 999999.9;
- ymax = -999999.9;
- pverts = r_polydesc.pverts;
-
- for (i=0 ; i<r_polydesc.nump ; i++)
- {
- if (pverts->v < ymin)
- {
- ymin = pverts->v;
- s_minindex = i;
- }
-
- if (pverts->v > ymax)
- {
- ymax = pverts->v;
- s_maxindex = i;
- }
-
- pverts++;
- }
-
- ymin = ceil (ymin);
- ymax = ceil (ymax);
-
- if (ymin >= ymax)
- return; // doesn't cross any scans at all
-
- cachewidth = r_polydesc.pixel_width;
- cacheblock = r_polydesc.pixels;
-
-// copy the first vertex to the last vertex, so we don't have to deal with
-// wrapping
- nump = r_polydesc.nump;
- pverts = r_polydesc.pverts;
- pverts[nump] = pverts[0];
-
- R_PolygonCalculateGradients ();
- R_PolygonScanLeftEdge ();
- R_PolygonScanRightEdge ();
-
- R_PolygonDrawSpans( s_polygon_spans, iswater );
-}
-
-/*
-** R_DrawAlphaSurfaces
-*/
-void R_DrawAlphaSurfaces( void )
-{
- msurface_t *s = r_alpha_surfaces;
-
- currentmodel = r_worldmodel;
-
- modelorg[0] = -r_origin[0];
- modelorg[1] = -r_origin[1];
- modelorg[2] = -r_origin[2];
-
- while ( s )
- {
- R_BuildPolygonFromSurface( s );
-
- if (s->texinfo->flags & SURF_TRANS66)
- R_ClipAndDrawPoly( 0.60f, ( s->texinfo->flags & SURF_WARP) != 0, true );
- else
- R_ClipAndDrawPoly( 0.30f, ( s->texinfo->flags & SURF_WARP) != 0, true );
-
- s = s->nextalphasurface;
- }
-
- r_alpha_surfaces = NULL;
-}
-
-/*
-** R_IMFlatShadedQuad
-*/
-void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha )
-{
- vec3_t s0, s1;
-
- r_polydesc.nump = 4;
- VectorCopy( r_origin, r_polydesc.viewer_position );
-
- VectorCopy( a, r_clip_verts[0][0] );
- VectorCopy( b, r_clip_verts[0][1] );
- VectorCopy( c, r_clip_verts[0][2] );
- VectorCopy( d, r_clip_verts[0][3] );
-
- r_clip_verts[0][0][3] = 0;
- r_clip_verts[0][1][3] = 0;
- r_clip_verts[0][2][3] = 0;
- r_clip_verts[0][3][3] = 0;
-
- r_clip_verts[0][0][4] = 0;
- r_clip_verts[0][1][4] = 0;
- r_clip_verts[0][2][4] = 0;
- r_clip_verts[0][3][4] = 0;
-
- VectorSubtract( d, c, s0 );
- VectorSubtract( c, b, s1 );
- CrossProduct( s0, s1, r_polydesc.vpn );
- VectorNormalize( r_polydesc.vpn );
-
- r_polydesc.dist = DotProduct( r_polydesc.vpn, r_clip_verts[0][0] );
-
- r_polyblendcolor = color;
-
- R_ClipAndDrawPoly( alpha, false, false );
-}
-
--- a/ref_soft/r_polyse.c
+++ /dev/null
@@ -1,1539 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// d_polyset.c: routines for drawing sets of polygons sharing the same
-// texture (used for Alias models)
-
-#include "r_local.h"
-
-int rand1k[] = {
-#include "rand1k.h"
-};
-
-#define MASK_1K 0x3FF
-
-int rand1k_index = 0;
-
-// TODO: put in span spilling to shrink list size
-// !!! if this is changed, it must be changed in d_polysa.s too !!!
-#define DPS_MAXSPANS MAXHEIGHT+1
- // 1 extra for spanpackage that marks end
-
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
-typedef struct {
- void *pdest;
- short *pz;
- int count;
- byte *ptex;
- int sfrac, tfrac, light, zi;
-} spanpackage_t;
-
-typedef struct {
- int isflattop;
- int numleftedges;
- int *pleftedgevert0;
- int *pleftedgevert1;
- int *pleftedgevert2;
- int numrightedges;
- int *prightedgevert0;
- int *prightedgevert1;
- int *prightedgevert2;
-} edgetable;
-
-aliastriangleparms_t aliastriangleparms;
-
-int r_p0[6], r_p1[6], r_p2[6];
-
-byte *d_pcolormap;
-
-int d_aflatcolor;
-int d_xdenom;
-
-edgetable *pedgetable;
-
-edgetable edgetables[12] = {
- {0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 },
- {0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL},
- {1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL},
- {0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 },
- {0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL},
- {0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL},
- {0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 },
- {0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL},
- {0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL},
- {1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL},
- {1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL},
- {0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL},
-};
-
-// FIXME: some of these can become statics
-int a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole;
-int r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy;
-int r_zistepx, r_zistepy;
-int d_aspancount, d_countextrastep;
-
-spanpackage_t *a_spans;
-spanpackage_t *d_pedgespanpackage;
-static int ystart;
-byte *d_pdest, *d_ptex;
-short *d_pz;
-int d_sfrac, d_tfrac, d_light, d_zi;
-int d_ptexextrastep, d_sfracextrastep;
-int d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
-int d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
-int d_sfracbasestep, d_tfracbasestep;
-int d_ziextrastep, d_zibasestep;
-int d_pzextrastep, d_pzbasestep;
-
-typedef struct {
- int quotient;
- int remainder;
-} adivtab_t;
-
-static adivtab_t adivtab[32*32] = {
-#include "adivtab.h"
-};
-
-byte *skintable[MAX_LBM_HEIGHT];
-int skinwidth;
-byte *skinstart;
-
-void (*d_pdrawspans)(spanpackage_t *pspanpackage);
-
-void R_PolysetDrawSpans8_33 (spanpackage_t *pspanpackage);
-void R_PolysetDrawSpans8_66 (spanpackage_t *pspanpackage);
-void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage);
-
-void R_PolysetDrawThreshSpans8 (spanpackage_t *pspanpackage);
-void R_PolysetCalcGradients (int skinwidth);
-void R_DrawNonSubdiv (void);
-void R_PolysetSetEdgeTable (void);
-void R_RasterizeAliasPolySmooth (void);
-void R_PolysetScanLeftEdge(int height);
-void R_PolysetScanLeftEdge_C(int height);
-
-// ======================
-// PGM
-// 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
-byte iractive = 0;
-byte irtable[256] = { 79, 78, 77, 76, 75, 74, 73, 72, // black/white
- 71, 70, 69, 68, 67, 66, 65, 64,
- 64, 65, 66, 67, 68, 69, 70, 71, // dark taupe
- 72, 73, 74, 75, 76, 77, 78, 79,
-
- 64, 65, 66, 67, 68, 69, 70, 71, // slate grey
- 72, 73, 74, 75, 76, 77, 78, 79,
- 208, 208, 208, 208, 208, 208, 208, 208, // unused?'
- 64, 66, 68, 70, 72, 74, 76, 78, // dark yellow
-
- 64, 65, 66, 67, 68, 69, 70, 71, // dark red
- 72, 73, 74, 75, 76, 77, 78, 79,
- 64, 65, 66, 67, 68, 69, 70, 71, // grey/tan
- 72, 73, 74, 75, 76, 77, 78, 79,
-
- 64, 66, 68, 70, 72, 74, 76, 78, // chocolate
- 68, 67, 66, 65, 64, 65, 66, 67, // mauve / teal
- 68, 69, 70, 71, 72, 73, 74, 75,
- 76, 76, 77, 77, 78, 78, 79, 79,
-
- 64, 65, 66, 67, 68, 69, 70, 71, // more mauve
- 72, 73, 74, 75, 76, 77, 78, 79,
- 64, 65, 66, 67, 68, 69, 70, 71, // olive
- 72, 73, 74, 75, 76, 77, 78, 79,
-
- 64, 65, 66, 67, 68, 69, 70, 71, // maroon
- 72, 73, 74, 75, 76, 77, 78, 79,
- 64, 65, 66, 67, 68, 69, 70, 71, // sky blue
- 72, 73, 74, 75, 76, 77, 78, 79,
-
- 64, 65, 66, 67, 68, 69, 70, 71, // olive again
- 72, 73, 74, 75, 76, 77, 78, 79,
- 64, 65, 66, 67, 68, 69, 70, 71, // nuclear green
- 64, 65, 66, 67, 68, 69, 70, 71, // bright yellow
-
- 64, 65, 66, 67, 68, 69, 70, 71, // fire colors
- 72, 73, 74, 75, 76, 77, 78, 79,
- 208, 208, 64, 64, 70, 71, 72, 64, // mishmash1
- 66, 68, 70, 64, 65, 66, 67, 68}; // mishmash2
-// PGM
-// ======================
-
-/*
-================
-R_PolysetUpdateTables
-================
-*/
-void R_PolysetUpdateTables (void)
-{
- int i;
- byte *s;
-
- if (r_affinetridesc.skinwidth != skinwidth ||
- r_affinetridesc.pskin != skinstart)
- {
- skinwidth = r_affinetridesc.skinwidth;
- skinstart = r_affinetridesc.pskin;
- s = skinstart;
- for (i=0 ; i<MAX_LBM_HEIGHT ; i++, s+=skinwidth)
- skintable[i] = s;
- }
-}
-
-
-/*
-================
-R_DrawTriangle
-================
-*/
-void R_DrawTriangle( void )
-{
- spanpackage_t spans[DPS_MAXSPANS];
-
- int dv1_ab, dv0_ac;
- int dv0_ab, dv1_ac;
-
- /*
- d_xdenom = ( aliastriangleparms.a->v[1] - aliastriangleparms.b->v[1] ) * ( aliastriangleparms.a->v[0] - aliastriangleparms.c->v[0] ) -
- ( aliastriangleparms.a->v[0] - aliastriangleparms.b->v[0] ) * ( aliastriangleparms.a->v[1] - aliastriangleparms.c->v[1] );
- */
-
- dv0_ab = aliastriangleparms.a->u - aliastriangleparms.b->u;
- dv1_ab = aliastriangleparms.a->v - aliastriangleparms.b->v;
-
- if ( !( dv0_ab | dv1_ab ) )
- return;
-
- dv0_ac = aliastriangleparms.a->u - aliastriangleparms.c->u;
- dv1_ac = aliastriangleparms.a->v - aliastriangleparms.c->v;
-
- if ( !( dv0_ac | dv1_ac ) )
- return;
-
- d_xdenom = ( dv0_ac * dv1_ab ) - ( dv0_ab * dv1_ac );
-
- if ( d_xdenom < 0 )
- {
- a_spans = spans;
-
- r_p0[0] = aliastriangleparms.a->u; // u
- r_p0[1] = aliastriangleparms.a->v; // v
- r_p0[2] = aliastriangleparms.a->s; // s
- r_p0[3] = aliastriangleparms.a->t; // t
- r_p0[4] = aliastriangleparms.a->l; // light
- r_p0[5] = aliastriangleparms.a->zi; // iz
-
- r_p1[0] = aliastriangleparms.b->u;
- r_p1[1] = aliastriangleparms.b->v;
- r_p1[2] = aliastriangleparms.b->s;
- r_p1[3] = aliastriangleparms.b->t;
- r_p1[4] = aliastriangleparms.b->l;
- r_p1[5] = aliastriangleparms.b->zi;
-
- r_p2[0] = aliastriangleparms.c->u;
- r_p2[1] = aliastriangleparms.c->v;
- r_p2[2] = aliastriangleparms.c->s;
- r_p2[3] = aliastriangleparms.c->t;
- r_p2[4] = aliastriangleparms.c->l;
- r_p2[5] = aliastriangleparms.c->zi;
-
- R_PolysetSetEdgeTable ();
- R_RasterizeAliasPolySmooth ();
- }
-}
-
-
-/*
-===================
-R_PolysetScanLeftEdge_C
-====================
-*/
-void R_PolysetScanLeftEdge_C(int height)
-{
- do
- {
- d_pedgespanpackage->pdest = d_pdest;
- d_pedgespanpackage->pz = d_pz;
- d_pedgespanpackage->count = d_aspancount;
- d_pedgespanpackage->ptex = d_ptex;
-
- d_pedgespanpackage->sfrac = d_sfrac;
- d_pedgespanpackage->tfrac = d_tfrac;
-
- // FIXME: need to clamp l, s, t, at both ends?
- d_pedgespanpackage->light = d_light;
- d_pedgespanpackage->zi = d_zi;
-
- d_pedgespanpackage++;
-
- errorterm += erroradjustup;
- if (errorterm >= 0)
- {
- d_pdest += d_pdestextrastep;
- d_pz += d_pzextrastep;
- d_aspancount += d_countextrastep;
- d_ptex += d_ptexextrastep;
- d_sfrac += d_sfracextrastep;
- d_ptex += d_sfrac >> 16;
-
- d_sfrac &= 0xFFFF;
- d_tfrac += d_tfracextrastep;
- if (d_tfrac & 0x10000)
- {
- d_ptex += r_affinetridesc.skinwidth;
- d_tfrac &= 0xFFFF;
- }
- d_light += d_lightextrastep;
- d_zi += d_ziextrastep;
- errorterm -= erroradjustdown;
- }
- else
- {
- d_pdest += d_pdestbasestep;
- d_pz += d_pzbasestep;
- d_aspancount += ubasestep;
- d_ptex += d_ptexbasestep;
- d_sfrac += d_sfracbasestep;
- d_ptex += d_sfrac >> 16;
- d_sfrac &= 0xFFFF;
- d_tfrac += d_tfracbasestep;
- if (d_tfrac & 0x10000)
- {
- d_ptex += r_affinetridesc.skinwidth;
- d_tfrac &= 0xFFFF;
- }
- d_light += d_lightbasestep;
- d_zi += d_zibasestep;
- }
- } while (--height);
-}
-
-/*
-===================
-FloorDivMod
-
-Returns mathematically correct (floor-based) quotient and remainder for
-numer and denom, both of which should contain no fractional part. The
-quotient must fit in 32 bits.
-FIXME: GET RID OF THIS! (FloorDivMod)
-====================
-*/
-void FloorDivMod (float numer, float denom, int *quotient,
- int *rem)
-{
- int q, r;
- float x;
-
- if (numer >= 0.0)
- {
-
- x = floor(numer / denom);
- q = (int)x;
- r = (int)floor(numer - (x * denom));
- }
- else
- {
- //
- // perform operations with positive values, and fix mod to make floor-based
- //
- x = floor(-numer / denom);
- q = -(int)x;
- r = (int)floor(-numer - (x * denom));
- if (r != 0)
- {
- q--;
- r = (int)denom - r;
- }
- }
-
- *quotient = q;
- *rem = r;
-}
-
-
-/*
-===================
-R_PolysetSetUpForLineScan
-====================
-*/
-void R_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
- fixed8_t endvertu, fixed8_t endvertv)
-{
- float dm, dn;
- int tm, tn;
- adivtab_t *ptemp;
-
-// TODO: implement x86 version
-
- errorterm = -1;
-
- tm = endvertu - startvertu;
- tn = endvertv - startvertv;
-
- if (((tm <= 16) && (tm >= -15)) &&
- ((tn <= 16) && (tn >= -15)))
- {
- ptemp = &adivtab[((tm+15) << 5) + (tn+15)];
- ubasestep = ptemp->quotient;
- erroradjustup = ptemp->remainder;
- erroradjustdown = tn;
- }
- else
- {
- dm = tm;
- dn = tn;
-
- FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
-
- erroradjustdown = dn;
- }
-}
-
-
-
-/*
-================
-R_PolysetCalcGradients
-================
-*/
-#if id386 && !defined __linux__
-void R_PolysetCalcGradients( int skinwidth )
-{
- static float xstepdenominv, ystepdenominv, t0, t1;
- static float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
- static float one = 1.0F, negative_one = -1.0F;
- static unsigned long t0_int, t1_int;
-
- extern unsigned long fpu_sp24_ceil_cw, fpu_ceil_cw, fpu_chop_cw;
-
- /*
- p00_minus_p20 = r_p0[0] - r_p2[0];
- p01_minus_p21 = r_p0[1] - r_p2[1];
- p10_minus_p20 = r_p1[0] - r_p2[0];
- p11_minus_p21 = r_p1[1] - r_p2[1];
- */
-
- __asm mov eax, dword ptr [r_p0+0]
- __asm mov ebx, dword ptr [r_p0+4]
- __asm sub eax, dword ptr [r_p2+0]
- __asm sub ebx, dword ptr [r_p2+4]
- __asm mov p00_minus_p20, eax
- __asm mov p01_minus_p21, ebx
- __asm fild dword ptr p00_minus_p20
- __asm fild dword ptr p01_minus_p21
- __asm mov eax, dword ptr [r_p1+0]
- __asm mov ebx, dword ptr [r_p1+4]
- __asm sub eax, dword ptr [r_p2+0]
- __asm sub ebx, dword ptr [r_p2+4]
- __asm fstp p01_minus_p21
- __asm fstp p00_minus_p20
- __asm mov p10_minus_p20, eax
- __asm mov p11_minus_p21, ebx
- __asm fild dword ptr p10_minus_p20
- __asm fild dword ptr p11_minus_p21
- __asm fstp p11_minus_p21
- __asm fstp p10_minus_p20
-
- /*
- xstepdenominv = 1.0 / (float)d_xdenom;
-
- ystepdenominv = -xstepdenominv;
- */
-
- /*
- ** put FPU in single precision ceil mode
- */
- __asm fldcw word ptr [fpu_sp24_ceil_cw]
-// __asm fldcw word ptr [fpu_ceil_cw]
-
- __asm fild dword ptr d_xdenom ; d_xdenom
- __asm fdivr one ; 1 / d_xdenom
- __asm fst xstepdenominv ;
- __asm fmul negative_one ; -( 1 / d_xdenom )
-
-// ceil () for light so positive steps are exaggerated, negative steps
-// diminished, pushing us away from underflow toward overflow. Underflow is
-// very visible, overflow is very unlikely, because of ambient lighting
- /*
- t0 = r_p0[4] - r_p2[4];
- t1 = r_p1[4] - r_p2[4];
- r_lstepx = (int)
- ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
- r_lstepy = (int)
- ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
- */
- __asm mov eax, dword ptr [r_p0+16]
- __asm mov ebx, dword ptr [r_p1+16]
- __asm sub eax, dword ptr [r_p2+16]
- __asm sub ebx, dword ptr [r_p2+16]
-
- __asm fstp ystepdenominv ; (empty)
-
- __asm mov t0_int, eax
- __asm mov t1_int, ebx
- __asm fild t0_int ; t0
- __asm fild t1_int ; t1 | t0
- __asm fxch st(1) ; t0 | t1
- __asm fstp t0 ; t1
- __asm fst t1 ; t1
- __asm fmul p01_minus_p21 ; t1 * p01_minus_p21
- __asm fld t0 ; t0 | t1 * p01_minus_p21
- __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21
- __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
- __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
- __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20
- __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20
- __asm fxch st(1)
- __asm fmul ystepdenominv ; r_lstepy | r_lstepx
- __asm fxch st(1) ; r_lstepx | r_lstepy
- __asm fistp dword ptr [r_lstepx]
- __asm fistp dword ptr [r_lstepy]
-
- /*
- ** put FPU back into extended precision chop mode
- */
- __asm fldcw word ptr [fpu_chop_cw]
-
- /*
- t0 = r_p0[2] - r_p2[2];
- t1 = r_p1[2] - r_p2[2];
- r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
- xstepdenominv);
- r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) *
- ystepdenominv);
- */
- __asm mov eax, dword ptr [r_p0+8]
- __asm mov ebx, dword ptr [r_p1+8]
- __asm sub eax, dword ptr [r_p2+8]
- __asm sub ebx, dword ptr [r_p2+8]
- __asm mov t0_int, eax
- __asm mov t1_int, ebx
- __asm fild t0_int ; t0
- __asm fild t1_int ; t1 | t0
- __asm fxch st(1) ; t0 | t1
- __asm fstp t0 ; t1
- __asm fst t1 ; (empty)
-
- __asm fmul p01_minus_p21 ; t1 * p01_minus_p21
- __asm fld t0 ; t0 | t1 * p01_minus_p21
- __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21
- __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
- __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
- __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20
- __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20
- __asm fxch st(1)
- __asm fmul ystepdenominv ; r_lstepy | r_lstepx
- __asm fxch st(1) ; r_lstepx | r_lstepy
- __asm fistp dword ptr [r_sstepx]
- __asm fistp dword ptr [r_sstepy]
-
- /*
- t0 = r_p0[3] - r_p2[3];
- t1 = r_p1[3] - r_p2[3];
- r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
- xstepdenominv);
- r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
- ystepdenominv);
- */
- __asm mov eax, dword ptr [r_p0+12]
- __asm mov ebx, dword ptr [r_p1+12]
- __asm sub eax, dword ptr [r_p2+12]
- __asm sub ebx, dword ptr [r_p2+12]
-
- __asm mov t0_int, eax
- __asm mov t1_int, ebx
- __asm fild t0_int ; t0
- __asm fild t1_int ; t1 | t0
- __asm fxch st(1) ; t0 | t1
- __asm fstp t0 ; t1
- __asm fst t1 ; (empty)
-
- __asm fmul p01_minus_p21 ; t1 * p01_minus_p21
- __asm fld t0 ; t0 | t1 * p01_minus_p21
- __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21
- __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
- __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
- __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20
- __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20
- __asm fxch st(1)
- __asm fmul ystepdenominv ; r_lstepy | r_lstepx
- __asm fxch st(1) ; r_lstepx | r_lstepy
- __asm fistp dword ptr [r_tstepx]
- __asm fistp dword ptr [r_tstepy]
-
- /*
- t0 = r_p0[5] - r_p2[5];
- t1 = r_p1[5] - r_p2[5];
- r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
- xstepdenominv);
- r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
- ystepdenominv);
- */
- __asm mov eax, dword ptr [r_p0+20]
- __asm mov ebx, dword ptr [r_p1+20]
- __asm sub eax, dword ptr [r_p2+20]
- __asm sub ebx, dword ptr [r_p2+20]
-
- __asm mov t0_int, eax
- __asm mov t1_int, ebx
- __asm fild t0_int ; t0
- __asm fild t1_int ; t1 | t0
- __asm fxch st(1) ; t0 | t1
- __asm fstp t0 ; t1
- __asm fst t1 ; (empty)
-
- __asm fmul p01_minus_p21 ; t1 * p01_minus_p21
- __asm fld t0 ; t0 | t1 * p01_minus_p21
- __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
- __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21
- __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
- __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
- __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20
- __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20
- __asm fxch st(1)
- __asm fmul ystepdenominv ; r_lstepy | r_lstepx
- __asm fxch st(1) ; r_lstepx | r_lstepy
- __asm fistp dword ptr [r_zistepx]
- __asm fistp dword ptr [r_zistepy]
-
- /*
-#if id386ALIAS
- a_sstepxfrac = r_sstepx << 16;
- a_tstepxfrac = r_tstepx << 16;
-#else
- a_sstepxfrac = r_sstepx & 0xFFFF;
- a_tstepxfrac = r_tstepx & 0xFFFF;
-#endif
- */
- __asm mov eax, d_pdrawspans
- __asm cmp eax, offset R_PolysetDrawSpans8_Opaque
- __asm mov eax, r_sstepx
- __asm mov ebx, r_tstepx
- __asm jne translucent
-//#if id386ALIAS
- __asm shl eax, 16
- __asm shl ebx, 16
- __asm jmp done_with_steps
-//#else
-translucent:
- __asm and eax, 0ffffh
- __asm and ebx, 0ffffh
-//#endif
-done_with_steps:
- __asm mov a_sstepxfrac, eax
- __asm mov a_tstepxfrac, ebx
-
- /*
- a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
- */
- __asm mov ebx, r_tstepx
- __asm mov ecx, r_sstepx
- __asm sar ebx, 16
- __asm mov eax, skinwidth
- __asm mul ebx
- __asm sar ecx, 16
- __asm add eax, ecx
- __asm mov a_ststepxwhole, eax
-}
-#else
-void R_PolysetCalcGradients (int skinwidth)
-{
- float xstepdenominv, ystepdenominv, t0, t1;
- float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
-
- p00_minus_p20 = r_p0[0] - r_p2[0];
- p01_minus_p21 = r_p0[1] - r_p2[1];
- p10_minus_p20 = r_p1[0] - r_p2[0];
- p11_minus_p21 = r_p1[1] - r_p2[1];
-
- xstepdenominv = 1.0 / (float)d_xdenom;
-
- ystepdenominv = -xstepdenominv;
-
-// ceil () for light so positive steps are exaggerated, negative steps
-// diminished, pushing us away from underflow toward overflow. Underflow is
-// very visible, overflow is very unlikely, because of ambient lighting
- t0 = r_p0[4] - r_p2[4];
- t1 = r_p1[4] - r_p2[4];
- r_lstepx = (int)
- ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
- r_lstepy = (int)
- ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
-
- t0 = r_p0[2] - r_p2[2];
- t1 = r_p1[2] - r_p2[2];
- r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
- xstepdenominv);
- r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) *
- ystepdenominv);
-
- t0 = r_p0[3] - r_p2[3];
- t1 = r_p1[3] - r_p2[3];
- r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
- xstepdenominv);
- r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
- ystepdenominv);
-
- t0 = r_p0[5] - r_p2[5];
- t1 = r_p1[5] - r_p2[5];
- r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
- xstepdenominv);
- r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
- ystepdenominv);
-
-//#if id386ALIAS
-#if id386
- if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
- {
- a_sstepxfrac = r_sstepx << 16;
- a_tstepxfrac = r_tstepx << 16;
- }
- else
-#endif
- {
-//#else
- a_sstepxfrac = r_sstepx & 0xFFFF;
- a_tstepxfrac = r_tstepx & 0xFFFF;
- }
-//#endif
-
- a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
-}
-#endif
-
-/*
-================
-R_PolysetDrawThreshSpans8
-
-Random fizzle fade rasterizer
-================
-*/
-void R_PolysetDrawThreshSpans8 (spanpackage_t *pspanpackage)
-{
- int lcount;
- byte *lpdest;
- byte *lptex;
- int lsfrac, ltfrac;
- int llight;
- int lzi;
- short *lpz;
-
- do
- {
- lcount = d_aspancount - pspanpackage->count;
-
- errorterm += erroradjustup;
- if (errorterm >= 0)
- {
- d_aspancount += d_countextrastep;
- errorterm -= erroradjustdown;
- }
- else
- {
- d_aspancount += ubasestep;
- }
-
- if (lcount)
- {
- lpdest = pspanpackage->pdest;
- lptex = pspanpackage->ptex;
- lpz = pspanpackage->pz;
- lsfrac = pspanpackage->sfrac;
- ltfrac = pspanpackage->tfrac;
- llight = pspanpackage->light;
- lzi = pspanpackage->zi;
-
- do
- {
- if ((lzi >> 16) >= *lpz)
- {
- rand1k_index = (rand1k_index + 1) & MASK_1K;
-
- if (rand1k[rand1k_index] <= r_affinetridesc.vis_thresh)
- {
- *lpdest = ((byte *)vid.colormap)[*lptex + (llight & 0xFF00)];
- *lpz = lzi >> 16;
- }
- }
-
- lpdest++;
- lzi += r_zistepx;
- lpz++;
- llight += r_lstepx;
- lptex += a_ststepxwhole;
- lsfrac += a_sstepxfrac;
- lptex += lsfrac >> 16;
- lsfrac &= 0xFFFF;
- ltfrac += a_tstepxfrac;
- if (ltfrac & 0x10000)
- {
- lptex += r_affinetridesc.skinwidth;
- ltfrac &= 0xFFFF;
- }
- } while (--lcount);
- }
-
- pspanpackage++;
- } while (pspanpackage->count != -999999);
-}
-
-
-/*
-================
-R_PolysetDrawSpans8
-================
-*/
-void R_PolysetDrawSpans8_33( spanpackage_t *pspanpackage)
-{
- int lcount;
- byte *lpdest;
- byte *lptex;
- int lsfrac, ltfrac;
- int llight;
- int lzi;
- short *lpz;
-
- do
- {
- lcount = d_aspancount - pspanpackage->count;
-
- errorterm += erroradjustup;
- if (errorterm >= 0)
- {
- d_aspancount += d_countextrastep;
- errorterm -= erroradjustdown;
- }
- else
- {
- d_aspancount += ubasestep;
- }
-
- if (lcount)
- {
- lpdest = pspanpackage->pdest;
- lptex = pspanpackage->ptex;
- lpz = pspanpackage->pz;
- lsfrac = pspanpackage->sfrac;
- ltfrac = pspanpackage->tfrac;
- llight = pspanpackage->light;
- lzi = pspanpackage->zi;
-
- do
- {
- if ((lzi >> 16) >= *lpz)
- {
- int temp = vid.colormap[*lptex + ( llight & 0xFF00 )];
-
- *lpdest = vid.alphamap[temp+ *lpdest*256];
- }
- lpdest++;
- lzi += r_zistepx;
- lpz++;
- llight += r_lstepx;
- lptex += a_ststepxwhole;
- lsfrac += a_sstepxfrac;
- lptex += lsfrac >> 16;
- lsfrac &= 0xFFFF;
- ltfrac += a_tstepxfrac;
- if (ltfrac & 0x10000)
- {
- lptex += r_affinetridesc.skinwidth;
- ltfrac &= 0xFFFF;
- }
- } while (--lcount);
- }
-
- pspanpackage++;
- } while (pspanpackage->count != -999999);
-}
-
-void R_PolysetDrawSpansConstant8_33( spanpackage_t *pspanpackage)
-{
- int lcount;
- byte *lpdest;
- int lzi;
- short *lpz;
-
- do
- {
- lcount = d_aspancount - pspanpackage->count;
-
- errorterm += erroradjustup;
- if (errorterm >= 0)
- {
- d_aspancount += d_countextrastep;
- errorterm -= erroradjustdown;
- }
- else
- {
- d_aspancount += ubasestep;
- }
-
- if (lcount)
- {
- lpdest = pspanpackage->pdest;
- lpz = pspanpackage->pz;
- lzi = pspanpackage->zi;
-
- do
- {
- if ((lzi >> 16) >= *lpz)
- {
- *lpdest = vid.alphamap[r_aliasblendcolor + *lpdest*256];
- }
- lpdest++;
- lzi += r_zistepx;
- lpz++;
- } while (--lcount);
- }
-
- pspanpackage++;
- } while (pspanpackage->count != -999999);
-}
-
-void R_PolysetDrawSpans8_66(spanpackage_t *pspanpackage)
-{
- int lcount;
- byte *lpdest;
- byte *lptex;
- int lsfrac, ltfrac;
- int llight;
- int lzi;
- short *lpz;
-
- do
- {
- lcount = d_aspancount - pspanpackage->count;
-
- errorterm += erroradjustup;
- if (errorterm >= 0)
- {
- d_aspancount += d_countextrastep;
- errorterm -= erroradjustdown;
- }
- else
- {
- d_aspancount += ubasestep;
- }
-
- if (lcount)
- {
- lpdest = pspanpackage->pdest;
- lptex = pspanpackage->ptex;
- lpz = pspanpackage->pz;
- lsfrac = pspanpackage->sfrac;
- ltfrac = pspanpackage->tfrac;
- llight = pspanpackage->light;
- lzi = pspanpackage->zi;
-
- do
- {
- if ((lzi >> 16) >= *lpz)
- {
- int temp = vid.colormap[*lptex + ( llight & 0xFF00 )];
-
- *lpdest = vid.alphamap[temp*256 + *lpdest];
- *lpz = lzi >> 16;
- }
- lpdest++;
- lzi += r_zistepx;
- lpz++;
- llight += r_lstepx;
- lptex += a_ststepxwhole;
- lsfrac += a_sstepxfrac;
- lptex += lsfrac >> 16;
- lsfrac &= 0xFFFF;
- ltfrac += a_tstepxfrac;
- if (ltfrac & 0x10000)
- {
- lptex += r_affinetridesc.skinwidth;
- ltfrac &= 0xFFFF;
- }
- } while (--lcount);
- }
-
- pspanpackage++;
- } while (pspanpackage->count != -999999);
-}
-
-void R_PolysetDrawSpansConstant8_66( spanpackage_t *pspanpackage)
-{
- int lcount;
- byte *lpdest;
- int lzi;
- short *lpz;
-
- do
- {
- lcount = d_aspancount - pspanpackage->count;
-
- errorterm += erroradjustup;
- if (errorterm >= 0)
- {
- d_aspancount += d_countextrastep;
- errorterm -= erroradjustdown;
- }
- else
- {
- d_aspancount += ubasestep;
- }
-
- if (lcount)
- {
- lpdest = pspanpackage->pdest;
- lpz = pspanpackage->pz;
- lzi = pspanpackage->zi;
-
- do
- {
- if ((lzi >> 16) >= *lpz)
- {
- *lpdest = vid.alphamap[r_aliasblendcolor*256 + *lpdest];
- }
- lpdest++;
- lzi += r_zistepx;
- lpz++;
- } while (--lcount);
- }
-
- pspanpackage++;
- } while (pspanpackage->count != -999999);
-}
-
-#if !id386
-void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage)
-{
- int lcount;
-
- do
- {
- lcount = d_aspancount - pspanpackage->count;
-
- errorterm += erroradjustup;
- if (errorterm >= 0)
- {
- d_aspancount += d_countextrastep;
- errorterm -= erroradjustdown;
- }
- else
- {
- d_aspancount += ubasestep;
- }
-
- if (lcount)
- {
- int lsfrac, ltfrac;
- byte *lpdest;
- byte *lptex;
- int llight;
- int lzi;
- short *lpz;
-
- lpdest = pspanpackage->pdest;
- lptex = pspanpackage->ptex;
- lpz = pspanpackage->pz;
- lsfrac = pspanpackage->sfrac;
- ltfrac = pspanpackage->tfrac;
- llight = pspanpackage->light;
- lzi = pspanpackage->zi;
-
- do
- {
- if ((lzi >> 16) >= *lpz)
- {
-//PGM
- if(r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
- *lpdest = ((byte *)vid.colormap)[irtable[*lptex]];
- else
- *lpdest = ((byte *)vid.colormap)[*lptex + (llight & 0xFF00)];
-//PGM
- *lpz = lzi >> 16;
- }
- lpdest++;
- lzi += r_zistepx;
- lpz++;
- llight += r_lstepx;
- lptex += a_ststepxwhole;
- lsfrac += a_sstepxfrac;
- lptex += lsfrac >> 16;
- lsfrac &= 0xFFFF;
- ltfrac += a_tstepxfrac;
- if (ltfrac & 0x10000)
- {
- lptex += r_affinetridesc.skinwidth;
- ltfrac &= 0xFFFF;
- }
- } while (--lcount);
- }
-
- pspanpackage++;
- } while (pspanpackage->count != -999999);
-}
-#endif
-
-
-/*
-================
-R_PolysetFillSpans8
-================
-*/
-void R_PolysetFillSpans8 (spanpackage_t *pspanpackage)
-{
- int color;
-
-// FIXME: do z buffering
-
- color = d_aflatcolor++;
-
- while (1)
- {
- int lcount;
- byte *lpdest;
-
- lcount = pspanpackage->count;
-
- if (lcount == -1)
- return;
-
- if (lcount)
- {
- lpdest = pspanpackage->pdest;
-
- do
- {
- *lpdest++ = color;
- } while (--lcount);
- }
-
- pspanpackage++;
- }
-}
-
-/*
-================
-R_RasterizeAliasPolySmooth
-================
-*/
-void R_RasterizeAliasPolySmooth (void)
-{
- int initialleftheight, initialrightheight;
- int *plefttop, *prighttop, *pleftbottom, *prightbottom;
- int working_lstepx, originalcount;
-
- plefttop = pedgetable->pleftedgevert0;
- prighttop = pedgetable->prightedgevert0;
-
- pleftbottom = pedgetable->pleftedgevert1;
- prightbottom = pedgetable->prightedgevert1;
-
- initialleftheight = pleftbottom[1] - plefttop[1];
- initialrightheight = prightbottom[1] - prighttop[1];
-
-//
-// set the s, t, and light gradients, which are consistent across the triangle
-// because being a triangle, things are affine
-//
- R_PolysetCalcGradients (r_affinetridesc.skinwidth);
-//
-// rasterize the polygon
-//
-
-//
-// scan out the top (and possibly only) part of the left edge
-//
- d_pedgespanpackage = a_spans;
-
- ystart = plefttop[1];
- d_aspancount = plefttop[0] - prighttop[0];
-
- d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
- (plefttop[3] >> 16) * r_affinetridesc.skinwidth;
-//#if id386ALIAS
-#if id386
- if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
- {
- d_sfrac = (plefttop[2] & 0xFFFF) << 16;
- d_tfrac = (plefttop[3] & 0xFFFF) << 16;
- }
-//#else
- else
-#endif
- {
- d_sfrac = plefttop[2] & 0xFFFF;
- d_tfrac = plefttop[3] & 0xFFFF;
- }
-//#endif
- d_light = plefttop[4];
- d_zi = plefttop[5];
-
- d_pdest = (byte *)d_viewbuffer +
- ystart * r_screenwidth + plefttop[0];
- d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
-
- if (initialleftheight == 1)
- {
- d_pedgespanpackage->pdest = d_pdest;
- d_pedgespanpackage->pz = d_pz;
- d_pedgespanpackage->count = d_aspancount;
- d_pedgespanpackage->ptex = d_ptex;
-
- d_pedgespanpackage->sfrac = d_sfrac;
- d_pedgespanpackage->tfrac = d_tfrac;
-
- // FIXME: need to clamp l, s, t, at both ends?
- d_pedgespanpackage->light = d_light;
- d_pedgespanpackage->zi = d_zi;
-
- d_pedgespanpackage++;
- }
- else
- {
- R_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
- pleftbottom[0], pleftbottom[1]);
-
-//#if id386ALIAS
-#if id386
- if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
- {
- d_pzbasestep = (d_zwidth + ubasestep) << 1;
- d_pzextrastep = d_pzbasestep + 2;
- }
-//#else
- else
-#endif
- {
- d_pzbasestep = d_zwidth + ubasestep;
- d_pzextrastep = d_pzbasestep + 1;
- }
-//#endif
-
- d_pdestbasestep = r_screenwidth + ubasestep;
- d_pdestextrastep = d_pdestbasestep + 1;
-
- // TODO: can reuse partial expressions here
-
- // for negative steps in x along left edge, bias toward overflow rather than
- // underflow (sort of turning the floor () we did in the gradient calcs into
- // ceil (), but plus a little bit)
- if (ubasestep < 0)
- working_lstepx = r_lstepx - 1;
- else
- working_lstepx = r_lstepx;
-
- d_countextrastep = ubasestep + 1;
- d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
- ((r_tstepy + r_tstepx * ubasestep) >> 16) *
- r_affinetridesc.skinwidth;
-//#if id386ALIAS
-#if id386
- if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
- {
- d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
- d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
- }
- else
-#endif
- {
-//#else
- d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
- d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
- }
-//#endif
- d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
- d_zibasestep = r_zistepy + r_zistepx * ubasestep;
-
- d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
- ((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
- r_affinetridesc.skinwidth;
-//#if id386ALIAS
-#if id386
- if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
- {
- d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16;
- d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16;
- }
- else
-#endif
- {
-//#else
- d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF;
- d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF;
- }
-//#endif
- d_lightextrastep = d_lightbasestep + working_lstepx;
- d_ziextrastep = d_zibasestep + r_zistepx;
-
-#if id386
- if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
- {
- R_PolysetScanLeftEdge (initialleftheight);
- }
- else
-#endif
- {
- R_PolysetScanLeftEdge_C(initialleftheight);
- }
- }
-
-//
-// scan out the bottom part of the left edge, if it exists
-//
- if (pedgetable->numleftedges == 2)
- {
- int height;
-
- plefttop = pleftbottom;
- pleftbottom = pedgetable->pleftedgevert2;
-
- height = pleftbottom[1] - plefttop[1];
-
-// TODO: make this a function; modularize this function in general
-
- ystart = plefttop[1];
- d_aspancount = plefttop[0] - prighttop[0];
- d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
- (plefttop[3] >> 16) * r_affinetridesc.skinwidth;
- d_sfrac = 0;
- d_tfrac = 0;
- d_light = plefttop[4];
- d_zi = plefttop[5];
-
- d_pdest = (byte *)d_viewbuffer + ystart * r_screenwidth + plefttop[0];
- d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
-
- if (height == 1)
- {
- d_pedgespanpackage->pdest = d_pdest;
- d_pedgespanpackage->pz = d_pz;
- d_pedgespanpackage->count = d_aspancount;
- d_pedgespanpackage->ptex = d_ptex;
-
- d_pedgespanpackage->sfrac = d_sfrac;
- d_pedgespanpackage->tfrac = d_tfrac;
-
- // FIXME: need to clamp l, s, t, at both ends?
- d_pedgespanpackage->light = d_light;
- d_pedgespanpackage->zi = d_zi;
-
- d_pedgespanpackage++;
- }
- else
- {
- R_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
- pleftbottom[0], pleftbottom[1]);
-
- d_pdestbasestep = r_screenwidth + ubasestep;
- d_pdestextrastep = d_pdestbasestep + 1;
-
-//#if id386ALIAS
-#if id386
- if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
- {
- d_pzbasestep = (d_zwidth + ubasestep) << 1;
- d_pzextrastep = d_pzbasestep + 2;
- }
-//#else
- else
-#endif
- {
- d_pzbasestep = d_zwidth + ubasestep;
- d_pzextrastep = d_pzbasestep + 1;
- }
-//#endif
-
- if (ubasestep < 0)
- working_lstepx = r_lstepx - 1;
- else
- working_lstepx = r_lstepx;
-
- d_countextrastep = ubasestep + 1;
- d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
- ((r_tstepy + r_tstepx * ubasestep) >> 16) *
- r_affinetridesc.skinwidth;
-//#if id386ALIAS
-#if id386
- if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
- {
- d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
- d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
- }
-//#else
- else
-#endif
- {
- d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
- d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
- }
-//#endif
- d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
- d_zibasestep = r_zistepy + r_zistepx * ubasestep;
-
- d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
- ((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
- r_affinetridesc.skinwidth;
-//#if id386ALIAS
-#if id386
- if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
- {
- d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16;
- d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16;
- }
- else
-#endif
-//#endif
- {
- d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF;
- d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF;
- }
-//#endif
- d_lightextrastep = d_lightbasestep + working_lstepx;
- d_ziextrastep = d_zibasestep + r_zistepx;
-
-#if id386
- if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
- {
- R_PolysetScanLeftEdge (height);
- }
- else
-#endif
- {
- R_PolysetScanLeftEdge_C(height);
- }
- }
- }
-
-// scan out the top (and possibly only) part of the right edge, updating the
-// count field
- d_pedgespanpackage = a_spans;
-
- R_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
- prightbottom[0], prightbottom[1]);
- d_aspancount = 0;
- d_countextrastep = ubasestep + 1;
- originalcount = a_spans[initialrightheight].count;
- a_spans[initialrightheight].count = -999999; // mark end of the spanpackages
- (*d_pdrawspans) (a_spans);
-
-// scan out the bottom part of the right edge, if it exists
- if (pedgetable->numrightedges == 2)
- {
- int height;
- spanpackage_t *pstart;
-
- pstart = a_spans + initialrightheight;
- pstart->count = originalcount;
-
- d_aspancount = prightbottom[0] - prighttop[0];
-
- prighttop = prightbottom;
- prightbottom = pedgetable->prightedgevert2;
-
- height = prightbottom[1] - prighttop[1];
-
- R_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
- prightbottom[0], prightbottom[1]);
-
- d_countextrastep = ubasestep + 1;
- a_spans[initialrightheight + height].count = -999999;
- // mark end of the spanpackages
- (*d_pdrawspans) (pstart);
- }
-}
-
-
-/*
-================
-R_PolysetSetEdgeTable
-================
-*/
-void R_PolysetSetEdgeTable (void)
-{
- int edgetableindex;
-
- edgetableindex = 0; // assume the vertices are already in
- // top to bottom order
-
-//
-// determine which edges are right & left, and the order in which
-// to rasterize them
-//
- if (r_p0[1] >= r_p1[1])
- {
- if (r_p0[1] == r_p1[1])
- {
- if (r_p0[1] < r_p2[1])
- pedgetable = &edgetables[2];
- else
- pedgetable = &edgetables[5];
-
- return;
- }
- else
- {
- edgetableindex = 1;
- }
- }
-
- if (r_p0[1] == r_p2[1])
- {
- if (edgetableindex)
- pedgetable = &edgetables[8];
- else
- pedgetable = &edgetables[9];
-
- return;
- }
- else if (r_p1[1] == r_p2[1])
- {
- if (edgetableindex)
- pedgetable = &edgetables[10];
- else
- pedgetable = &edgetables[11];
-
- return;
- }
-
- if (r_p0[1] > r_p2[1])
- edgetableindex += 2;
-
- if (r_p1[1] > r_p2[1])
- edgetableindex += 4;
-
- pedgetable = &edgetables[edgetableindex];
-}
-
-
--- a/ref_soft/r_rast.c
+++ /dev/null
@@ -1,852 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// r_rast.c
-
-#include <assert.h>
-
-#include "r_local.h"
-
-#define MAXLEFTCLIPEDGES 100
-
-// !!! if these are changed, they must be changed in asm_draw.h too !!!
-#define FULLY_CLIPPED_CACHED 0x80000000
-#define FRAMECOUNT_MASK 0x7FFFFFFF
-
-unsigned int cacheoffset;
-
-int c_faceclip; // number of faces clipped
-
-
-clipplane_t *entity_clipplanes;
-clipplane_t view_clipplanes[4];
-clipplane_t world_clipplanes[16];
-
-medge_t *r_pedge;
-
-qboolean r_leftclipped, r_rightclipped;
-static qboolean makeleftedge, makerightedge;
-qboolean r_nearzionly;
-
-int sintable[1280];
-int intsintable[1280];
-int blanktable[1280]; // PGM
-
-mvertex_t r_leftenter, r_leftexit;
-mvertex_t r_rightenter, r_rightexit;
-
-typedef struct
-{
- float u,v;
- int ceilv;
-} evert_t;
-
-int r_emitted;
-float r_nearzi;
-float r_u1, r_v1, r_lzi1;
-int r_ceilv1;
-
-qboolean r_lastvertvalid;
-int r_skyframe;
-
-msurface_t *r_skyfaces;
-mplane_t r_skyplanes[6];
-mtexinfo_t r_skytexinfo[6];
-mvertex_t *r_skyverts;
-medge_t *r_skyedges;
-int *r_skysurfedges;
-
-// I just copied this data from a box map...
-int skybox_planes[12] = {2,-128, 0,-128, 2,128, 1,128, 0,128, 1,-128};
-
-int box_surfedges[24] = { 1,2,3,4, -1,5,6,7, 8,9,-6,10, -2,-7,-9,11,
- 12,-3,-11,-8, -12,-10,-5,-4};
-int box_edges[24] = { 1,2, 2,3, 3,4, 4,1, 1,5, 5,6, 6,2, 7,8, 8,6, 5,7, 8,3, 7,4};
-
-int box_faces[6] = {0,0,2,2,2,0};
-
-vec3_t box_vecs[6][2] = {
- { {0,-1,0}, {-1,0,0} },
- { {0,1,0}, {0,0,-1} },
- { {0,-1,0}, {1,0,0} },
- { {1,0,0}, {0,0,-1} },
- { {0,-1,0}, {0,0,-1} },
- { {-1,0,0}, {0,0,-1} }
-};
-
-float box_verts[8][3] = {
- {-1,-1,-1},
- {-1,1,-1},
- {1,1,-1},
- {1,-1,-1},
- {-1,-1,1},
- {-1,1,1},
- {1,-1,1},
- {1,1,1}
-};
-
-// down, west, up, north, east, south
-// {"rt", "bk", "lf", "ft", "up", "dn"};
-
-/*
-================
-R_InitSkyBox
-
-================
-*/
-void R_InitSkyBox (void)
-{
- int i;
- extern model_t *loadmodel;
-
- r_skyfaces = loadmodel->surfaces + loadmodel->numsurfaces;
- loadmodel->numsurfaces += 6;
- r_skyverts = loadmodel->vertexes + loadmodel->numvertexes;
- loadmodel->numvertexes += 8;
- r_skyedges = loadmodel->edges + loadmodel->numedges;
- loadmodel->numedges += 12;
- r_skysurfedges = loadmodel->surfedges + loadmodel->numsurfedges;
- loadmodel->numsurfedges += 24;
- if (loadmodel->numsurfaces > MAX_MAP_FACES
- || loadmodel->numvertexes > MAX_MAP_VERTS
- || loadmodel->numedges > MAX_MAP_EDGES)
- ri.Sys_Error (ERR_DROP, "InitSkyBox: map overflow");
-
- memset (r_skyfaces, 0, 6*sizeof(*r_skyfaces));
- for (i=0 ; i<6 ; i++)
- {
- r_skyplanes[i].normal[skybox_planes[i*2]] = 1;
- r_skyplanes[i].dist = skybox_planes[i*2+1];
-
- VectorCopy (box_vecs[i][0], r_skytexinfo[i].vecs[0]);
- VectorCopy (box_vecs[i][1], r_skytexinfo[i].vecs[1]);
-
- r_skyfaces[i].plane = &r_skyplanes[i];
- r_skyfaces[i].numedges = 4;
- r_skyfaces[i].flags = box_faces[i] | SURF_DRAWSKYBOX;
- r_skyfaces[i].firstedge = loadmodel->numsurfedges-24+i*4;
- r_skyfaces[i].texinfo = &r_skytexinfo[i];
- r_skyfaces[i].texturemins[0] = -128;
- r_skyfaces[i].texturemins[1] = -128;
- r_skyfaces[i].extents[0] = 256;
- r_skyfaces[i].extents[1] = 256;
- }
-
- for (i=0 ; i<24 ; i++)
- if (box_surfedges[i] > 0)
- r_skysurfedges[i] = loadmodel->numedges-13 + box_surfedges[i];
- else
- r_skysurfedges[i] = - (loadmodel->numedges-13 + -box_surfedges[i]);
-
- for(i=0 ; i<12 ; i++)
- {
- r_skyedges[i].v[0] = loadmodel->numvertexes-9+box_edges[i*2+0];
- r_skyedges[i].v[1] = loadmodel->numvertexes-9+box_edges[i*2+1];
- r_skyedges[i].cachededgeoffset = 0;
- }
-}
-
-/*
-================
-R_EmitSkyBox
-================
-*/
-void R_EmitSkyBox (void)
-{
- int i, j;
- int oldkey;
-
- if (insubmodel)
- return; // submodels should never have skies
- if (r_skyframe == r_framecount)
- return; // already set this frame
-
- r_skyframe = r_framecount;
-
- // set the eight fake vertexes
- for (i=0 ; i<8 ; i++)
- for (j=0 ; j<3 ; j++)
- r_skyverts[i].position[j] = r_origin[j] + box_verts[i][j]*128;
-
- // set the six fake planes
- for (i=0 ; i<6 ; i++)
- if (skybox_planes[i*2+1] > 0)
- r_skyplanes[i].dist = r_origin[skybox_planes[i*2]]+128;
- else
- r_skyplanes[i].dist = r_origin[skybox_planes[i*2]]-128;
-
- // fix texture offseets
- for (i=0 ; i<6 ; i++)
- {
- r_skytexinfo[i].vecs[0][3] = -DotProduct (r_origin, r_skytexinfo[i].vecs[0]);
- r_skytexinfo[i].vecs[1][3] = -DotProduct (r_origin, r_skytexinfo[i].vecs[1]);
- }
-
- // emit the six faces
- oldkey = r_currentkey;
- r_currentkey = 0x7ffffff0;
- for (i=0 ; i<6 ; i++)
- {
- R_RenderFace (r_skyfaces + i, 15);
- }
- r_currentkey = oldkey; // bsp sorting order
-}
-
-
-#if !id386
-
-/*
-================
-R_EmitEdge
-================
-*/
-void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
-{
- edge_t *edge, *pcheck;
- int u_check;
- float u, u_step;
- vec3_t local, transformed;
- float *world;
- int v, v2, ceilv0;
- float scale, lzi0, u0, v0;
- int side;
-
- if (r_lastvertvalid)
- {
- u0 = r_u1;
- v0 = r_v1;
- lzi0 = r_lzi1;
- ceilv0 = r_ceilv1;
- }
- else
- {
- world = &pv0->position[0];
-
- // transform and project
- VectorSubtract (world, modelorg, local);
- TransformVector (local, transformed);
-
- if (transformed[2] < NEAR_CLIP)
- transformed[2] = NEAR_CLIP;
-
- lzi0 = 1.0 / transformed[2];
-
- // FIXME: build x/yscale into transform?
- scale = xscale * lzi0;
- u0 = (xcenter + scale*transformed[0]);
- if (u0 < r_refdef.fvrectx_adj)
- u0 = r_refdef.fvrectx_adj;
- if (u0 > r_refdef.fvrectright_adj)
- u0 = r_refdef.fvrectright_adj;
-
- scale = yscale * lzi0;
- v0 = (ycenter - scale*transformed[1]);
- if (v0 < r_refdef.fvrecty_adj)
- v0 = r_refdef.fvrecty_adj;
- if (v0 > r_refdef.fvrectbottom_adj)
- v0 = r_refdef.fvrectbottom_adj;
-
- ceilv0 = (int) ceil(v0);
- }
-
- world = &pv1->position[0];
-
-// transform and project
- VectorSubtract (world, modelorg, local);
- TransformVector (local, transformed);
-
- if (transformed[2] < NEAR_CLIP)
- transformed[2] = NEAR_CLIP;
-
- r_lzi1 = 1.0 / transformed[2];
-
- scale = xscale * r_lzi1;
- r_u1 = (xcenter + scale*transformed[0]);
- if (r_u1 < r_refdef.fvrectx_adj)
- r_u1 = r_refdef.fvrectx_adj;
- if (r_u1 > r_refdef.fvrectright_adj)
- r_u1 = r_refdef.fvrectright_adj;
-
- scale = yscale * r_lzi1;
- r_v1 = (ycenter - scale*transformed[1]);
- if (r_v1 < r_refdef.fvrecty_adj)
- r_v1 = r_refdef.fvrecty_adj;
- if (r_v1 > r_refdef.fvrectbottom_adj)
- r_v1 = r_refdef.fvrectbottom_adj;
-
- if (r_lzi1 > lzi0)
- lzi0 = r_lzi1;
-
- if (lzi0 > r_nearzi) // for mipmap finding
- r_nearzi = lzi0;
-
-// for right edges, all we want is the effect on 1/z
- if (r_nearzionly)
- return;
-
- r_emitted = 1;
-
- r_ceilv1 = (int) ceil(r_v1);
-
-
-// create the edge
- if (ceilv0 == r_ceilv1)
- {
- // we cache unclipped horizontal edges as fully clipped
- if (cacheoffset != 0x7FFFFFFF)
- {
- cacheoffset = FULLY_CLIPPED_CACHED |
- (r_framecount & FRAMECOUNT_MASK);
- }
-
- return; // horizontal edge
- }
-
- side = ceilv0 > r_ceilv1;
-
- edge = edge_p++;
-
- edge->owner = r_pedge;
-
- edge->nearzi = lzi0;
-
- if (side == 0)
- {
- // trailing edge (go from p1 to p2)
- v = ceilv0;
- v2 = r_ceilv1 - 1;
-
- edge->surfs[0] = surface_p - surfaces;
- edge->surfs[1] = 0;
-
- u_step = ((r_u1 - u0) / (r_v1 - v0));
- u = u0 + ((float)v - v0) * u_step;
- }
- else
- {
- // leading edge (go from p2 to p1)
- v2 = ceilv0 - 1;
- v = r_ceilv1;
-
- edge->surfs[0] = 0;
- edge->surfs[1] = surface_p - surfaces;
-
- u_step = ((u0 - r_u1) / (v0 - r_v1));
- u = r_u1 + ((float)v - r_v1) * u_step;
- }
-
- edge->u_step = u_step*0x100000;
- edge->u = u*0x100000 + 0xFFFFF;
-
-// we need to do this to avoid stepping off the edges if a very nearly
-// horizontal edge is less than epsilon above a scan, and numeric error causes
-// it to incorrectly extend to the scan, and the extension of the line goes off
-// the edge of the screen
-// FIXME: is this actually needed?
- if (edge->u < r_refdef.vrect_x_adj_shift20)
- edge->u = r_refdef.vrect_x_adj_shift20;
- if (edge->u > r_refdef.vrectright_adj_shift20)
- edge->u = r_refdef.vrectright_adj_shift20;
-
-//
-// sort the edge in normally
-//
- u_check = edge->u;
- if (edge->surfs[0])
- u_check++; // sort trailers after leaders
-
- if (!newedges[v] || newedges[v]->u >= u_check)
- {
- edge->next = newedges[v];
- newedges[v] = edge;
- }
- else
- {
- pcheck = newedges[v];
- while (pcheck->next && pcheck->next->u < u_check)
- pcheck = pcheck->next;
- edge->next = pcheck->next;
- pcheck->next = edge;
- }
-
- edge->nextremove = removeedges[v2];
- removeedges[v2] = edge;
-}
-
-
-/*
-================
-R_ClipEdge
-================
-*/
-void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
-{
- float d0, d1, f;
- mvertex_t clipvert;
-
- if (clip)
- {
- do
- {
- d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
- d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
-
- if (d0 >= 0)
- {
- // point 0 is unclipped
- if (d1 >= 0)
- {
- // both points are unclipped
- continue;
- }
-
- // only point 1 is clipped
-
- // we don't cache clipped edges
- cacheoffset = 0x7FFFFFFF;
-
- f = d0 / (d0 - d1);
- clipvert.position[0] = pv0->position[0] +
- f * (pv1->position[0] - pv0->position[0]);
- clipvert.position[1] = pv0->position[1] +
- f * (pv1->position[1] - pv0->position[1]);
- clipvert.position[2] = pv0->position[2] +
- f * (pv1->position[2] - pv0->position[2]);
-
- if (clip->leftedge)
- {
- r_leftclipped = true;
- r_leftexit = clipvert;
- }
- else if (clip->rightedge)
- {
- r_rightclipped = true;
- r_rightexit = clipvert;
- }
-
- R_ClipEdge (pv0, &clipvert, clip->next);
- return;
- }
- else
- {
- // point 0 is clipped
- if (d1 < 0)
- {
- // both points are clipped
- // we do cache fully clipped edges
- if (!r_leftclipped)
- cacheoffset = FULLY_CLIPPED_CACHED |
- (r_framecount & FRAMECOUNT_MASK);
- return;
- }
-
- // only point 0 is clipped
- r_lastvertvalid = false;
-
- // we don't cache partially clipped edges
- cacheoffset = 0x7FFFFFFF;
-
- f = d0 / (d0 - d1);
- clipvert.position[0] = pv0->position[0] +
- f * (pv1->position[0] - pv0->position[0]);
- clipvert.position[1] = pv0->position[1] +
- f * (pv1->position[1] - pv0->position[1]);
- clipvert.position[2] = pv0->position[2] +
- f * (pv1->position[2] - pv0->position[2]);
-
- if (clip->leftedge)
- {
- r_leftclipped = true;
- r_leftenter = clipvert;
- }
- else if (clip->rightedge)
- {
- r_rightclipped = true;
- r_rightenter = clipvert;
- }
-
- R_ClipEdge (&clipvert, pv1, clip->next);
- return;
- }
- } while ((clip = clip->next) != NULL);
- }
-
-// add the edge
- R_EmitEdge (pv0, pv1);
-}
-
-#endif // !id386
-
-
-/*
-================
-R_EmitCachedEdge
-================
-*/
-void R_EmitCachedEdge (void)
-{
- edge_t *pedge_t;
-
- pedge_t = (edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset);
-
- if (!pedge_t->surfs[0])
- pedge_t->surfs[0] = surface_p - surfaces;
- else
- pedge_t->surfs[1] = surface_p - surfaces;
-
- if (pedge_t->nearzi > r_nearzi) // for mipmap finding
- r_nearzi = pedge_t->nearzi;
-
- r_emitted = 1;
-}
-
-
-/*
-================
-R_RenderFace
-================
-*/
-void R_RenderFace (msurface_t *fa, int clipflags)
-{
- int i, lindex;
- unsigned mask;
- mplane_t *pplane;
- float distinv;
- vec3_t p_normal;
- medge_t *pedges, tedge;
- clipplane_t *pclip;
-
- // translucent surfaces are not drawn by the edge renderer
- if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
- {
- fa->nextalphasurface = r_alpha_surfaces;
- r_alpha_surfaces = fa;
- return;
- }
-
- // sky surfaces encountered in the world will cause the
- // environment box surfaces to be emited
- if ( fa->texinfo->flags & SURF_SKY )
- {
- R_EmitSkyBox ();
- return;
- }
-
-// skip out if no more surfs
- if ((surface_p) >= surf_max)
- {
- r_outofsurfaces++;
- return;
- }
-
-// ditto if not enough edges left, or switch to auxedges if possible
- if ((edge_p + fa->numedges + 4) >= edge_max)
- {
- r_outofedges += fa->numedges;
- return;
- }
-
- c_faceclip++;
-
-// set up clip planes
- pclip = NULL;
-
- for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
- {
- if (clipflags & mask)
- {
- view_clipplanes[i].next = pclip;
- pclip = &view_clipplanes[i];
- }
- }
-
-// push the edges through
- r_emitted = 0;
- r_nearzi = 0;
- r_nearzionly = false;
- makeleftedge = makerightedge = false;
- pedges = currentmodel->edges;
- r_lastvertvalid = false;
-
- for (i=0 ; i<fa->numedges ; i++)
- {
- lindex = currentmodel->surfedges[fa->firstedge + i];
-
- if (lindex > 0)
- {
- r_pedge = &pedges[lindex];
-
- // if the edge is cached, we can just reuse the edge
- if (!insubmodel)
- {
- if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
- {
- if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
- r_framecount)
- {
- r_lastvertvalid = false;
- continue;
- }
- }
- else
- {
- if ((((unsigned long)edge_p - (unsigned long)r_edges) >
- r_pedge->cachededgeoffset) &&
- (((edge_t *)((unsigned long)r_edges +
- r_pedge->cachededgeoffset))->owner == r_pedge))
- {
- R_EmitCachedEdge ();
- r_lastvertvalid = false;
- continue;
- }
- }
- }
-
- // assume it's cacheable
- cacheoffset = (byte *)edge_p - (byte *)r_edges;
- r_leftclipped = r_rightclipped = false;
- R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]],
- &r_pcurrentvertbase[r_pedge->v[1]],
- pclip);
- r_pedge->cachededgeoffset = cacheoffset;
-
- if (r_leftclipped)
- makeleftedge = true;
- if (r_rightclipped)
- makerightedge = true;
- r_lastvertvalid = true;
- }
- else
- {
- lindex = -lindex;
- r_pedge = &pedges[lindex];
- // if the edge is cached, we can just reuse the edge
- if (!insubmodel)
- {
- if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
- {
- if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
- r_framecount)
- {
- r_lastvertvalid = false;
- continue;
- }
- }
- else
- {
- // it's cached if the cached edge is valid and is owned
- // by this medge_t
- if ((((unsigned long)edge_p - (unsigned long)r_edges) >
- r_pedge->cachededgeoffset) &&
- (((edge_t *)((unsigned long)r_edges +
- r_pedge->cachededgeoffset))->owner == r_pedge))
- {
- R_EmitCachedEdge ();
- r_lastvertvalid = false;
- continue;
- }
- }
- }
-
- // assume it's cacheable
- cacheoffset = (byte *)edge_p - (byte *)r_edges;
- r_leftclipped = r_rightclipped = false;
- R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]],
- &r_pcurrentvertbase[r_pedge->v[0]],
- pclip);
- r_pedge->cachededgeoffset = cacheoffset;
-
- if (r_leftclipped)
- makeleftedge = true;
- if (r_rightclipped)
- makerightedge = true;
- r_lastvertvalid = true;
- }
- }
-
-// if there was a clip off the left edge, add that edge too
-// FIXME: faster to do in screen space?
-// FIXME: share clipped edges?
- if (makeleftedge)
- {
- r_pedge = &tedge;
- r_lastvertvalid = false;
- R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
- }
-
-// if there was a clip off the right edge, get the right r_nearzi
- if (makerightedge)
- {
- r_pedge = &tedge;
- r_lastvertvalid = false;
- r_nearzionly = true;
- R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
- }
-
-// if no edges made it out, return without posting the surface
- if (!r_emitted)
- return;
-
- r_polycount++;
-
- surface_p->msurf = fa;
- surface_p->nearzi = r_nearzi;
- surface_p->flags = fa->flags;
- surface_p->insubmodel = insubmodel;
- surface_p->spanstate = 0;
- surface_p->entity = currententity;
- surface_p->key = r_currentkey++;
- surface_p->spans = NULL;
-
- pplane = fa->plane;
-// FIXME: cache this?
- TransformVector (pplane->normal, p_normal);
-// FIXME: cache this?
- distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
-
- surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
- surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
- surface_p->d_ziorigin = p_normal[2] * distinv -
- xcenter * surface_p->d_zistepu -
- ycenter * surface_p->d_zistepv;
-
- surface_p++;
-}
-
-
-/*
-================
-R_RenderBmodelFace
-================
-*/
-void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
-{
- int i;
- unsigned mask;
- mplane_t *pplane;
- float distinv;
- vec3_t p_normal;
- medge_t tedge;
- clipplane_t *pclip;
-
- if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
- {
- psurf->nextalphasurface = r_alpha_surfaces;
- r_alpha_surfaces = psurf;
- return;
- }
-
-// skip out if no more surfs
- if (surface_p >= surf_max)
- {
- r_outofsurfaces++;
- return;
- }
-
-// ditto if not enough edges left, or switch to auxedges if possible
- if ((edge_p + psurf->numedges + 4) >= edge_max)
- {
- r_outofedges += psurf->numedges;
- return;
- }
-
- c_faceclip++;
-
-// this is a dummy to give the caching mechanism someplace to write to
- r_pedge = &tedge;
-
-// set up clip planes
- pclip = NULL;
-
- for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
- {
- if (r_clipflags & mask)
- {
- view_clipplanes[i].next = pclip;
- pclip = &view_clipplanes[i];
- }
- }
-
-// push the edges through
- r_emitted = 0;
- r_nearzi = 0;
- r_nearzionly = false;
- makeleftedge = makerightedge = false;
-// FIXME: keep clipped bmodel edges in clockwise order so last vertex caching
-// can be used?
- r_lastvertvalid = false;
-
- for ( ; pedges ; pedges = pedges->pnext)
- {
- r_leftclipped = r_rightclipped = false;
- R_ClipEdge (pedges->v[0], pedges->v[1], pclip);
-
- if (r_leftclipped)
- makeleftedge = true;
- if (r_rightclipped)
- makerightedge = true;
- }
-
-// if there was a clip off the left edge, add that edge too
-// FIXME: faster to do in screen space?
-// FIXME: share clipped edges?
- if (makeleftedge)
- {
- r_pedge = &tedge;
- R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
- }
-
-// if there was a clip off the right edge, get the right r_nearzi
- if (makerightedge)
- {
- r_pedge = &tedge;
- r_nearzionly = true;
- R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
- }
-
-// if no edges made it out, return without posting the surface
- if (!r_emitted)
- return;
-
- r_polycount++;
-
- surface_p->msurf = psurf;
- surface_p->nearzi = r_nearzi;
- surface_p->flags = psurf->flags;
- surface_p->insubmodel = true;
- surface_p->spanstate = 0;
- surface_p->entity = currententity;
- surface_p->key = r_currentbkey;
- surface_p->spans = NULL;
-
- pplane = psurf->plane;
-// FIXME: cache this?
- TransformVector (pplane->normal, p_normal);
-// FIXME: cache this?
- distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
-
- surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
- surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
- surface_p->d_ziorigin = p_normal[2] * distinv -
- xcenter * surface_p->d_zistepu -
- ycenter * surface_p->d_zistepv;
-
- surface_p++;
-}
-
--- a/ref_soft/r_scan.c
+++ /dev/null
@@ -1,591 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// d_scan.c
-//
-// Portable C scan-level rasterization code, all pixel depths.
-
-#include "r_local.h"
-
-unsigned char *r_turb_pbase, *r_turb_pdest;
-fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
-int *r_turb_turb;
-int r_turb_spancount;
-
-void D_DrawTurbulent8Span (void);
-
-
-/*
-=============
-D_WarpScreen
-
-this performs a slight compression of the screen at the same time as
-the sine warp, to keep the edges from wrapping
-=============
-*/
-void D_WarpScreen (void)
-{
- int w, h;
- int u,v, u2, v2;
- byte *dest;
- int *turb;
- int *col;
- byte **row;
-
- static int cached_width, cached_height;
- static byte *rowptr[1200+AMP2*2];
- static int column[1600+AMP2*2];
-
- //
- // these are constant over resolutions, and can be saved
- //
- w = r_newrefdef.width;
- h = r_newrefdef.height;
- if (w != cached_width || h != cached_height)
- {
- cached_width = w;
- cached_height = h;
- for (v=0 ; v<h+AMP2*2 ; v++)
- {
- v2 = (int)((float)v/(h + AMP2 * 2) * r_refdef.vrect.height);
- rowptr[v] = r_warpbuffer + (WARP_WIDTH * v2);
- }
-
- for (u=0 ; u<w+AMP2*2 ; u++)
- {
- u2 = (int)((float)u/(w + AMP2 * 2) * r_refdef.vrect.width);
- column[u] = u2;
- }
- }
-
- turb = intsintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
- dest = vid.buffer + r_newrefdef.y * vid.rowbytes + r_newrefdef.x;
-
- for (v=0 ; v<h ; v++, dest += vid.rowbytes)
- {
- col = &column[turb[v]];
- row = &rowptr[v];
- for (u=0 ; u<w ; u+=4)
- {
- dest[u+0] = row[turb[u+0]][col[u+0]];
- dest[u+1] = row[turb[u+1]][col[u+1]];
- dest[u+2] = row[turb[u+2]][col[u+2]];
- dest[u+3] = row[turb[u+3]][col[u+3]];
- }
- }
-}
-
-
-#if !id386
-
-/*
-=============
-D_DrawTurbulent8Span
-=============
-*/
-void D_DrawTurbulent8Span (void)
-{
- int sturb, tturb;
-
- do
- {
- sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
- tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
- *r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
- r_turb_s += r_turb_sstep;
- r_turb_t += r_turb_tstep;
- } while (--r_turb_spancount > 0);
-}
-
-#endif // !id386
-
-
-/*
-=============
-Turbulent8
-=============
-*/
-void Turbulent8 (espan_t *pspan)
-{
- int count;
- fixed16_t snext, tnext;
- float sdivz, tdivz, zi, z, du, dv, spancountminus1;
- float sdivz16stepu, tdivz16stepu, zi16stepu;
-
- r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
-
- r_turb_sstep = 0; // keep compiler happy
- r_turb_tstep = 0; // ditto
-
- r_turb_pbase = (unsigned char *)cacheblock;
-
- sdivz16stepu = d_sdivzstepu * 16;
- tdivz16stepu = d_tdivzstepu * 16;
- zi16stepu = d_zistepu * 16;
-
- do
- {
- r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
- (r_screenwidth * pspan->v) + pspan->u);
-
- count = pspan->count;
-
- // calculate the initial s/z, t/z, 1/z, s, and t and clamp
- du = (float)pspan->u;
- dv = (float)pspan->v;
-
- sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
- tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
- zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
- z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
-
- r_turb_s = (int)(sdivz * z) + sadjust;
- if (r_turb_s > bbextents)
- r_turb_s = bbextents;
- else if (r_turb_s < 0)
- r_turb_s = 0;
-
- r_turb_t = (int)(tdivz * z) + tadjust;
- if (r_turb_t > bbextentt)
- r_turb_t = bbextentt;
- else if (r_turb_t < 0)
- r_turb_t = 0;
-
- do
- {
- // calculate s and t at the far end of the span
- if (count >= 16)
- r_turb_spancount = 16;
- else
- r_turb_spancount = count;
-
- count -= r_turb_spancount;
-
- if (count)
- {
- // calculate s/z, t/z, zi->fixed s and t at far end of span,
- // calculate s and t steps across span by shifting
- sdivz += sdivz16stepu;
- tdivz += tdivz16stepu;
- zi += zi16stepu;
- z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
-
- snext = (int)(sdivz * z) + sadjust;
- if (snext > bbextents)
- snext = bbextents;
- else if (snext < 16)
- snext = 16; // prevent round-off error on <0 steps from
- // from causing overstepping & running off the
- // edge of the texture
-
- tnext = (int)(tdivz * z) + tadjust;
- if (tnext > bbextentt)
- tnext = bbextentt;
- else if (tnext < 16)
- tnext = 16; // guard against round-off error on <0 steps
-
- r_turb_sstep = (snext - r_turb_s) >> 4;
- r_turb_tstep = (tnext - r_turb_t) >> 4;
- }
- else
- {
- // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
- // can't step off polygon), clamp, calculate s and t steps across
- // span by division, biasing steps low so we don't run off the
- // texture
- spancountminus1 = (float)(r_turb_spancount - 1);
- sdivz += d_sdivzstepu * spancountminus1;
- tdivz += d_tdivzstepu * spancountminus1;
- zi += d_zistepu * spancountminus1;
- z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
- snext = (int)(sdivz * z) + sadjust;
- if (snext > bbextents)
- snext = bbextents;
- else if (snext < 16)
- snext = 16; // prevent round-off error on <0 steps from
- // from causing overstepping & running off the
- // edge of the texture
-
- tnext = (int)(tdivz * z) + tadjust;
- if (tnext > bbextentt)
- tnext = bbextentt;
- else if (tnext < 16)
- tnext = 16; // guard against round-off error on <0 steps
-
- if (r_turb_spancount > 1)
- {
- r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
- r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
- }
- }
-
- r_turb_s = r_turb_s & ((CYCLE<<16)-1);
- r_turb_t = r_turb_t & ((CYCLE<<16)-1);
-
- D_DrawTurbulent8Span ();
-
- r_turb_s = snext;
- r_turb_t = tnext;
-
- } while (count > 0);
-
- } while ((pspan = pspan->pnext) != NULL);
-}
-
-//====================
-//PGM
-/*
-=============
-NonTurbulent8 - this is for drawing scrolling textures. they're warping water textures
- but the turbulence is automatically 0.
-=============
-*/
-void NonTurbulent8 (espan_t *pspan)
-{
- int count;
- fixed16_t snext, tnext;
- float sdivz, tdivz, zi, z, du, dv, spancountminus1;
- float sdivz16stepu, tdivz16stepu, zi16stepu;
-
-// r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
- r_turb_turb = blanktable;
-
- r_turb_sstep = 0; // keep compiler happy
- r_turb_tstep = 0; // ditto
-
- r_turb_pbase = (unsigned char *)cacheblock;
-
- sdivz16stepu = d_sdivzstepu * 16;
- tdivz16stepu = d_tdivzstepu * 16;
- zi16stepu = d_zistepu * 16;
-
- do
- {
- r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
- (r_screenwidth * pspan->v) + pspan->u);
-
- count = pspan->count;
-
- // calculate the initial s/z, t/z, 1/z, s, and t and clamp
- du = (float)pspan->u;
- dv = (float)pspan->v;
-
- sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
- tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
- zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
- z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
-
- r_turb_s = (int)(sdivz * z) + sadjust;
- if (r_turb_s > bbextents)
- r_turb_s = bbextents;
- else if (r_turb_s < 0)
- r_turb_s = 0;
-
- r_turb_t = (int)(tdivz * z) + tadjust;
- if (r_turb_t > bbextentt)
- r_turb_t = bbextentt;
- else if (r_turb_t < 0)
- r_turb_t = 0;
-
- do
- {
- // calculate s and t at the far end of the span
- if (count >= 16)
- r_turb_spancount = 16;
- else
- r_turb_spancount = count;
-
- count -= r_turb_spancount;
-
- if (count)
- {
- // calculate s/z, t/z, zi->fixed s and t at far end of span,
- // calculate s and t steps across span by shifting
- sdivz += sdivz16stepu;
- tdivz += tdivz16stepu;
- zi += zi16stepu;
- z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
-
- snext = (int)(sdivz * z) + sadjust;
- if (snext > bbextents)
- snext = bbextents;
- else if (snext < 16)
- snext = 16; // prevent round-off error on <0 steps from
- // from causing overstepping & running off the
- // edge of the texture
-
- tnext = (int)(tdivz * z) + tadjust;
- if (tnext > bbextentt)
- tnext = bbextentt;
- else if (tnext < 16)
- tnext = 16; // guard against round-off error on <0 steps
-
- r_turb_sstep = (snext - r_turb_s) >> 4;
- r_turb_tstep = (tnext - r_turb_t) >> 4;
- }
- else
- {
- // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
- // can't step off polygon), clamp, calculate s and t steps across
- // span by division, biasing steps low so we don't run off the
- // texture
- spancountminus1 = (float)(r_turb_spancount - 1);
- sdivz += d_sdivzstepu * spancountminus1;
- tdivz += d_tdivzstepu * spancountminus1;
- zi += d_zistepu * spancountminus1;
- z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
- snext = (int)(sdivz * z) + sadjust;
- if (snext > bbextents)
- snext = bbextents;
- else if (snext < 16)
- snext = 16; // prevent round-off error on <0 steps from
- // from causing overstepping & running off the
- // edge of the texture
-
- tnext = (int)(tdivz * z) + tadjust;
- if (tnext > bbextentt)
- tnext = bbextentt;
- else if (tnext < 16)
- tnext = 16; // guard against round-off error on <0 steps
-
- if (r_turb_spancount > 1)
- {
- r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
- r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
- }
- }
-
- r_turb_s = r_turb_s & ((CYCLE<<16)-1);
- r_turb_t = r_turb_t & ((CYCLE<<16)-1);
-
- D_DrawTurbulent8Span ();
-
- r_turb_s = snext;
- r_turb_t = tnext;
-
- } while (count > 0);
-
- } while ((pspan = pspan->pnext) != NULL);
-}
-//PGM
-//====================
-
-
-#if !id386
-
-/*
-=============
-D_DrawSpans16
-
- FIXME: actually make this subdivide by 16 instead of 8!!!
-=============
-*/
-void D_DrawSpans16 (espan_t *pspan)
-{
- int count, spancount;
- unsigned char *pbase, *pdest;
- fixed16_t s, t, snext, tnext, sstep, tstep;
- float sdivz, tdivz, zi, z, du, dv, spancountminus1;
- float sdivz8stepu, tdivz8stepu, zi8stepu;
-
- sstep = 0; // keep compiler happy
- tstep = 0; // ditto
-
- pbase = (unsigned char *)cacheblock;
-
- sdivz8stepu = d_sdivzstepu * 8;
- tdivz8stepu = d_tdivzstepu * 8;
- zi8stepu = d_zistepu * 8;
-
- do
- {
- pdest = (unsigned char *)((byte *)d_viewbuffer +
- (r_screenwidth * pspan->v) + pspan->u);
-
- count = pspan->count;
-
- // calculate the initial s/z, t/z, 1/z, s, and t and clamp
- du = (float)pspan->u;
- dv = (float)pspan->v;
-
- sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
- tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
- zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
- z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
-
- s = (int)(sdivz * z) + sadjust;
- if (s > bbextents)
- s = bbextents;
- else if (s < 0)
- s = 0;
-
- t = (int)(tdivz * z) + tadjust;
- if (t > bbextentt)
- t = bbextentt;
- else if (t < 0)
- t = 0;
-
- do
- {
- // calculate s and t at the far end of the span
- if (count >= 8)
- spancount = 8;
- else
- spancount = count;
-
- count -= spancount;
-
- if (count)
- {
- // calculate s/z, t/z, zi->fixed s and t at far end of span,
- // calculate s and t steps across span by shifting
- sdivz += sdivz8stepu;
- tdivz += tdivz8stepu;
- zi += zi8stepu;
- z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
-
- snext = (int)(sdivz * z) + sadjust;
- if (snext > bbextents)
- snext = bbextents;
- else if (snext < 8)
- snext = 8; // prevent round-off error on <0 steps from
- // from causing overstepping & running off the
- // edge of the texture
-
- tnext = (int)(tdivz * z) + tadjust;
- if (tnext > bbextentt)
- tnext = bbextentt;
- else if (tnext < 8)
- tnext = 8; // guard against round-off error on <0 steps
-
- sstep = (snext - s) >> 3;
- tstep = (tnext - t) >> 3;
- }
- else
- {
- // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
- // can't step off polygon), clamp, calculate s and t steps across
- // span by division, biasing steps low so we don't run off the
- // texture
- spancountminus1 = (float)(spancount - 1);
- sdivz += d_sdivzstepu * spancountminus1;
- tdivz += d_tdivzstepu * spancountminus1;
- zi += d_zistepu * spancountminus1;
- z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
- snext = (int)(sdivz * z) + sadjust;
- if (snext > bbextents)
- snext = bbextents;
- else if (snext < 8)
- snext = 8; // prevent round-off error on <0 steps from
- // from causing overstepping & running off the
- // edge of the texture
-
- tnext = (int)(tdivz * z) + tadjust;
- if (tnext > bbextentt)
- tnext = bbextentt;
- else if (tnext < 8)
- tnext = 8; // guard against round-off error on <0 steps
-
- if (spancount > 1)
- {
- sstep = (snext - s) / (spancount - 1);
- tstep = (tnext - t) / (spancount - 1);
- }
- }
-
- do
- {
- *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
- s += sstep;
- t += tstep;
- } while (--spancount > 0);
-
- s = snext;
- t = tnext;
-
- } while (count > 0);
-
- } while ((pspan = pspan->pnext) != NULL);
-}
-
-#endif
-
-
-#if !id386
-
-/*
-=============
-D_DrawZSpans
-=============
-*/
-void D_DrawZSpans (espan_t *pspan)
-{
- int count, doublecount, izistep;
- int izi;
- short *pdest;
- unsigned ltemp;
- float zi;
- float du, dv;
-
-// FIXME: check for clamping/range problems
-// we count on FP exceptions being turned off to avoid range problems
- izistep = (int)(d_zistepu * 0x8000 * 0x10000);
-
- do
- {
- pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
-
- count = pspan->count;
-
- // calculate the initial 1/z
- du = (float)pspan->u;
- dv = (float)pspan->v;
-
- zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
- // we count on FP exceptions being turned off to avoid range problems
- izi = (int)(zi * 0x8000 * 0x10000);
-
- if ((long)pdest & 0x02)
- {
- *pdest++ = (short)(izi >> 16);
- izi += izistep;
- count--;
- }
-
- if ((doublecount = count >> 1) > 0)
- {
- do
- {
- ltemp = izi >> 16;
- izi += izistep;
- ltemp |= izi & 0xFFFF0000;
- izi += izistep;
- *(int *)pdest = ltemp;
- pdest += 2;
- } while (--doublecount > 0);
- }
-
- if (count & 1)
- *pdest = (short)(izi >> 16);
-
- } while ((pspan = pspan->pnext) != NULL);
-}
-
-#endif
-
--- a/ref_soft/r_sprite.c
+++ /dev/null
@@ -1,123 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// r_sprite.c
-#include "r_local.h"
-
-extern polydesc_t r_polydesc;
-
-void R_BuildPolygonFromSurface(msurface_t *fa);
-void R_PolygonCalculateGradients (void);
-
-extern void R_PolyChooseSpanletRoutine( float alpha, qboolean isturbulent );
-
-extern vec5_t r_clip_verts[2][MAXWORKINGVERTS+2];
-
-extern void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured );
-
-/*
-** R_DrawSprite
-**
-** Draw currententity / currentmodel as a single texture
-** mapped polygon
-*/
-void R_DrawSprite (void)
-{
- vec5_t *pverts;
- vec3_t left, up, right, down;
- dsprite_t *s_psprite;
- dsprframe_t *s_psprframe;
-
-
- s_psprite = (dsprite_t *)currentmodel->extradata;
-#if 0
- if (currententity->frame >= s_psprite->numframes
- || currententity->frame < 0)
- {
- ri.Con_Printf (PRINT_ALL, "No such sprite frame %i\n",
- currententity->frame);
- currententity->frame = 0;
- }
-#endif
- currententity->frame %= s_psprite->numframes;
-
- s_psprframe = &s_psprite->frames[currententity->frame];
-
- r_polydesc.pixels = currentmodel->skins[currententity->frame]->pixels[0];
- r_polydesc.pixel_width = s_psprframe->width;
- r_polydesc.pixel_height = s_psprframe->height;
- r_polydesc.dist = 0;
-
- // generate the sprite's axes, completely parallel to the viewplane.
- VectorCopy (vup, r_polydesc.vup);
- VectorCopy (vright, r_polydesc.vright);
- VectorCopy (vpn, r_polydesc.vpn);
-
-// build the sprite poster in worldspace
- VectorScale (r_polydesc.vright,
- s_psprframe->width - s_psprframe->origin_x, right);
- VectorScale (r_polydesc.vup,
- s_psprframe->height - s_psprframe->origin_y, up);
- VectorScale (r_polydesc.vright,
- -s_psprframe->origin_x, left);
- VectorScale (r_polydesc.vup,
- -s_psprframe->origin_y, down);
-
- // invert UP vector for sprites
- VectorInverse( r_polydesc.vup );
-
- pverts = r_clip_verts[0];
-
- pverts[0][0] = r_entorigin[0] + up[0] + left[0];
- pverts[0][1] = r_entorigin[1] + up[1] + left[1];
- pverts[0][2] = r_entorigin[2] + up[2] + left[2];
- pverts[0][3] = 0;
- pverts[0][4] = 0;
-
- pverts[1][0] = r_entorigin[0] + up[0] + right[0];
- pverts[1][1] = r_entorigin[1] + up[1] + right[1];
- pverts[1][2] = r_entorigin[2] + up[2] + right[2];
- pverts[1][3] = s_psprframe->width;
- pverts[1][4] = 0;
-
- pverts[2][0] = r_entorigin[0] + down[0] + right[0];
- pverts[2][1] = r_entorigin[1] + down[1] + right[1];
- pverts[2][2] = r_entorigin[2] + down[2] + right[2];
- pverts[2][3] = s_psprframe->width;
- pverts[2][4] = s_psprframe->height;
-
- pverts[3][0] = r_entorigin[0] + down[0] + left[0];
- pverts[3][1] = r_entorigin[1] + down[1] + left[1];
- pverts[3][2] = r_entorigin[2] + down[2] + left[2];
- pverts[3][3] = 0;
- pverts[3][4] = s_psprframe->height;
-
- r_polydesc.nump = 4;
- r_polydesc.s_offset = ( r_polydesc.pixel_width >> 1);
- r_polydesc.t_offset = ( r_polydesc.pixel_height >> 1);
- VectorCopy( modelorg, r_polydesc.viewer_position );
-
- r_polydesc.stipple_parity = 1;
- if ( currententity->flags & RF_TRANSLUCENT )
- R_ClipAndDrawPoly ( currententity->alpha, false, true );
- else
- R_ClipAndDrawPoly ( 1.0F, false, true );
- r_polydesc.stipple_parity = 0;
-}
-
--- a/ref_soft/r_surf.c
+++ /dev/null
@@ -1,651 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// r_surf.c: surface-related refresh code
-
-#include "r_local.h"
-
-drawsurf_t r_drawsurf;
-
-int lightleft, sourcesstep, blocksize, sourcetstep;
-int lightdelta, lightdeltastep;
-int lightright, lightleftstep, lightrightstep, blockdivshift;
-unsigned blockdivmask;
-void *prowdestbase;
-unsigned char *pbasesource;
-int surfrowbytes; // used by ASM files
-unsigned *r_lightptr;
-int r_stepback;
-int r_lightwidth;
-int r_numhblocks, r_numvblocks;
-unsigned char *r_source, *r_sourcemax;
-
-void R_DrawSurfaceBlock8_mip0 (void);
-void R_DrawSurfaceBlock8_mip1 (void);
-void R_DrawSurfaceBlock8_mip2 (void);
-void R_DrawSurfaceBlock8_mip3 (void);
-
-static void (*surfmiptable[4])(void) = {
- R_DrawSurfaceBlock8_mip0,
- R_DrawSurfaceBlock8_mip1,
- R_DrawSurfaceBlock8_mip2,
- R_DrawSurfaceBlock8_mip3
-};
-
-void R_BuildLightMap (void);
-extern unsigned blocklights[1024]; // allow some very large lightmaps
-
-float surfscale;
-qboolean r_cache_thrash; // set if surface cache is thrashing
-
-int sc_size;
-surfcache_t *sc_rover, *sc_base;
-
-/*
-===============
-R_TextureAnimation
-
-Returns the proper texture for a given time and base texture
-===============
-*/
-image_t *R_TextureAnimation (mtexinfo_t *tex)
-{
- int c;
-
- if (!tex->next)
- return tex->image;
-
- c = currententity->frame % tex->numframes;
- while (c)
- {
- tex = tex->next;
- c--;
- }
-
- return tex->image;
-}
-
-
-/*
-===============
-R_DrawSurface
-===============
-*/
-void R_DrawSurface (void)
-{
- unsigned char *basetptr;
- int smax, tmax, twidth;
- int u;
- int soffset, basetoffset, texwidth;
- int horzblockstep;
- unsigned char *pcolumndest;
- void (*pblockdrawer)(void);
- image_t *mt;
-
- surfrowbytes = r_drawsurf.rowbytes;
-
- mt = r_drawsurf.image;
-
- r_source = mt->pixels[r_drawsurf.surfmip];
-
-// the fractional light values should range from 0 to (VID_GRADES - 1) << 16
-// from a source range of 0 - 255
-
- texwidth = mt->width >> r_drawsurf.surfmip;
-
- blocksize = 16 >> r_drawsurf.surfmip;
- blockdivshift = 4 - r_drawsurf.surfmip;
- blockdivmask = (1 << blockdivshift) - 1;
-
- r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1;
-
- r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
- r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
-
-//==============================
-
- pblockdrawer = surfmiptable[r_drawsurf.surfmip];
-// TODO: only needs to be set when there is a display settings change
- horzblockstep = blocksize;
-
- smax = mt->width >> r_drawsurf.surfmip;
- twidth = texwidth;
- tmax = mt->height >> r_drawsurf.surfmip;
- sourcetstep = texwidth;
- r_stepback = tmax * twidth;
-
- r_sourcemax = r_source + (tmax * smax);
-
- soffset = r_drawsurf.surf->texturemins[0];
- basetoffset = r_drawsurf.surf->texturemins[1];
-
-// << 16 components are to guarantee positive values for %
- soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
- basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip)
- + (tmax << 16)) % tmax) * twidth)];
-
- pcolumndest = r_drawsurf.surfdat;
-
- for (u=0 ; u<r_numhblocks; u++)
- {
- r_lightptr = blocklights + u;
-
- prowdestbase = pcolumndest;
-
- pbasesource = basetptr + soffset;
-
- (*pblockdrawer)();
-
- soffset = soffset + blocksize;
- if (soffset >= smax)
- soffset = 0;
-
- pcolumndest += horzblockstep;
- }
-}
-
-
-//=============================================================================
-
-#if !id386
-
-/*
-================
-R_DrawSurfaceBlock8_mip0
-================
-*/
-void R_DrawSurfaceBlock8_mip0 (void)
-{
- int v, i, b, lightstep, lighttemp, light;
- unsigned char pix, *psource, *prowdest;
-
- psource = pbasesource;
- prowdest = prowdestbase;
-
- for (v=0 ; v<r_numvblocks ; v++)
- {
- // FIXME: make these locals?
- // FIXME: use delta rather than both right and left, like ASM?
- lightleft = r_lightptr[0];
- lightright = r_lightptr[1];
- r_lightptr += r_lightwidth;
- lightleftstep = (r_lightptr[0] - lightleft) >> 4;
- lightrightstep = (r_lightptr[1] - lightright) >> 4;
-
- for (i=0 ; i<16 ; i++)
- {
- lighttemp = lightleft - lightright;
- lightstep = lighttemp >> 4;
-
- light = lightright;
-
- for (b=15; b>=0; b--)
- {
- pix = psource[b];
- prowdest[b] = ((unsigned char *)vid.colormap)
- [(light & 0xFF00) + pix];
- light += lightstep;
- }
-
- psource += sourcetstep;
- lightright += lightrightstep;
- lightleft += lightleftstep;
- prowdest += surfrowbytes;
- }
-
- if (psource >= r_sourcemax)
- psource -= r_stepback;
- }
-}
-
-
-/*
-================
-R_DrawSurfaceBlock8_mip1
-================
-*/
-void R_DrawSurfaceBlock8_mip1 (void)
-{
- int v, i, b, lightstep, lighttemp, light;
- unsigned char pix, *psource, *prowdest;
-
- psource = pbasesource;
- prowdest = prowdestbase;
-
- for (v=0 ; v<r_numvblocks ; v++)
- {
- // FIXME: make these locals?
- // FIXME: use delta rather than both right and left, like ASM?
- lightleft = r_lightptr[0];
- lightright = r_lightptr[1];
- r_lightptr += r_lightwidth;
- lightleftstep = (r_lightptr[0] - lightleft) >> 3;
- lightrightstep = (r_lightptr[1] - lightright) >> 3;
-
- for (i=0 ; i<8 ; i++)
- {
- lighttemp = lightleft - lightright;
- lightstep = lighttemp >> 3;
-
- light = lightright;
-
- for (b=7; b>=0; b--)
- {
- pix = psource[b];
- prowdest[b] = ((unsigned char *)vid.colormap)
- [(light & 0xFF00) + pix];
- light += lightstep;
- }
-
- psource += sourcetstep;
- lightright += lightrightstep;
- lightleft += lightleftstep;
- prowdest += surfrowbytes;
- }
-
- if (psource >= r_sourcemax)
- psource -= r_stepback;
- }
-}
-
-
-/*
-================
-R_DrawSurfaceBlock8_mip2
-================
-*/
-void R_DrawSurfaceBlock8_mip2 (void)
-{
- int v, i, b, lightstep, lighttemp, light;
- unsigned char pix, *psource, *prowdest;
-
- psource = pbasesource;
- prowdest = prowdestbase;
-
- for (v=0 ; v<r_numvblocks ; v++)
- {
- // FIXME: make these locals?
- // FIXME: use delta rather than both right and left, like ASM?
- lightleft = r_lightptr[0];
- lightright = r_lightptr[1];
- r_lightptr += r_lightwidth;
- lightleftstep = (r_lightptr[0] - lightleft) >> 2;
- lightrightstep = (r_lightptr[1] - lightright) >> 2;
-
- for (i=0 ; i<4 ; i++)
- {
- lighttemp = lightleft - lightright;
- lightstep = lighttemp >> 2;
-
- light = lightright;
-
- for (b=3; b>=0; b--)
- {
- pix = psource[b];
- prowdest[b] = ((unsigned char *)vid.colormap)
- [(light & 0xFF00) + pix];
- light += lightstep;
- }
-
- psource += sourcetstep;
- lightright += lightrightstep;
- lightleft += lightleftstep;
- prowdest += surfrowbytes;
- }
-
- if (psource >= r_sourcemax)
- psource -= r_stepback;
- }
-}
-
-
-/*
-================
-R_DrawSurfaceBlock8_mip3
-================
-*/
-void R_DrawSurfaceBlock8_mip3 (void)
-{
- int v, i, b, lightstep, lighttemp, light;
- unsigned char pix, *psource, *prowdest;
-
- psource = pbasesource;
- prowdest = prowdestbase;
-
- for (v=0 ; v<r_numvblocks ; v++)
- {
- // FIXME: make these locals?
- // FIXME: use delta rather than both right and left, like ASM?
- lightleft = r_lightptr[0];
- lightright = r_lightptr[1];
- r_lightptr += r_lightwidth;
- lightleftstep = (r_lightptr[0] - lightleft) >> 1;
- lightrightstep = (r_lightptr[1] - lightright) >> 1;
-
- for (i=0 ; i<2 ; i++)
- {
- lighttemp = lightleft - lightright;
- lightstep = lighttemp >> 1;
-
- light = lightright;
-
- for (b=1; b>=0; b--)
- {
- pix = psource[b];
- prowdest[b] = ((unsigned char *)vid.colormap)
- [(light & 0xFF00) + pix];
- light += lightstep;
- }
-
- psource += sourcetstep;
- lightright += lightrightstep;
- lightleft += lightleftstep;
- prowdest += surfrowbytes;
- }
-
- if (psource >= r_sourcemax)
- psource -= r_stepback;
- }
-}
-
-#endif
-
-
-//============================================================================
-
-
-/*
-================
-R_InitCaches
-
-================
-*/
-void R_InitCaches (void)
-{
- int size;
- int pix;
-
- // calculate size to allocate
- if (sw_surfcacheoverride->value)
- {
- size = sw_surfcacheoverride->value;
- }
- else
- {
- size = SURFCACHE_SIZE_AT_320X240;
-
- pix = vid.width*vid.height;
- if (pix > 64000)
- size += (pix-64000)*3;
- }
-
- // round up to page size
- size = (size + 8191) & ~8191;
-
- ri.Con_Printf (PRINT_ALL,"%ik surface cache\n", size/1024);
-
- sc_size = size;
- sc_base = (surfcache_t *)malloc(size);
- sc_rover = sc_base;
-
- sc_base->next = NULL;
- sc_base->owner = NULL;
- sc_base->size = sc_size;
-}
-
-
-/*
-==================
-D_FlushCaches
-==================
-*/
-void D_FlushCaches (void)
-{
- surfcache_t *c;
-
- if (!sc_base)
- return;
-
- for (c = sc_base ; c ; c = c->next)
- {
- if (c->owner)
- *c->owner = NULL;
- }
-
- sc_rover = sc_base;
- sc_base->next = NULL;
- sc_base->owner = NULL;
- sc_base->size = sc_size;
-}
-
-/*
-=================
-D_SCAlloc
-=================
-*/
-surfcache_t *D_SCAlloc (int width, int size)
-{
- surfcache_t *new;
- qboolean wrapped_this_time;
-
- if ((width < 0) || (width > 256))
- ri.Sys_Error (ERR_FATAL,"D_SCAlloc: bad cache width %d\n", width);
-
- if ((size <= 0) || (size > 0x10000))
- ri.Sys_Error (ERR_FATAL,"D_SCAlloc: bad cache size %d\n", size);
-
- size = (int)&((surfcache_t *)0)->data[size];
- size = (size + 3) & ~3;
- if (size > sc_size)
- ri.Sys_Error (ERR_FATAL,"D_SCAlloc: %i > cache size of %i",size, sc_size);
-
-// if there is not size bytes after the rover, reset to the start
- wrapped_this_time = false;
-
- if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
- {
- if (sc_rover)
- {
- wrapped_this_time = true;
- }
- sc_rover = sc_base;
- }
-
-// colect and free surfcache_t blocks until the rover block is large enough
- new = sc_rover;
- if (sc_rover->owner)
- *sc_rover->owner = NULL;
-
- while (new->size < size)
- {
- // free another
- sc_rover = sc_rover->next;
- if (!sc_rover)
- ri.Sys_Error (ERR_FATAL,"D_SCAlloc: hit the end of memory");
- if (sc_rover->owner)
- *sc_rover->owner = NULL;
-
- new->size += sc_rover->size;
- new->next = sc_rover->next;
- }
-
-// create a fragment out of any leftovers
- if (new->size - size > 256)
- {
- sc_rover = (surfcache_t *)( (byte *)new + size);
- sc_rover->size = new->size - size;
- sc_rover->next = new->next;
- sc_rover->width = 0;
- sc_rover->owner = NULL;
- new->next = sc_rover;
- new->size = size;
- }
- else
- sc_rover = new->next;
-
- new->width = width;
-// DEBUG
- if (width > 0)
- new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
-
- new->owner = NULL; // should be set properly after return
-
- if (d_roverwrapped)
- {
- if (wrapped_this_time || (sc_rover >= d_initial_rover))
- r_cache_thrash = true;
- }
- else if (wrapped_this_time)
- {
- d_roverwrapped = true;
- }
-
- return new;
-}
-
-
-/*
-=================
-D_SCDump
-=================
-*/
-void D_SCDump (void)
-{
- surfcache_t *test;
-
- for (test = sc_base ; test ; test = test->next)
- {
- if (test == sc_rover)
- ri.Con_Printf (PRINT_ALL,"ROVER:\n");
- ri.Con_Printf (PRINT_ALL,"%p : %i bytes %i width\n",test, test->size, test->width);
- }
-}
-
-//=============================================================================
-
-// if the num is not a power of 2, assume it will not repeat
-
-int MaskForNum (int num)
-{
- if (num==128)
- return 127;
- if (num==64)
- return 63;
- if (num==32)
- return 31;
- if (num==16)
- return 15;
- return 255;
-}
-
-int D_log2 (int num)
-{
- int c;
-
- c = 0;
-
- while (num>>=1)
- c++;
- return c;
-}
-
-//=============================================================================
-
-/*
-================
-D_CacheSurface
-================
-*/
-surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
-{
- surfcache_t *cache;
-
-//
-// if the surface is animating or flashing, flush the cache
-//
- r_drawsurf.image = R_TextureAnimation (surface->texinfo);
- r_drawsurf.lightadj[0] = r_newrefdef.lightstyles[surface->styles[0]].white*128;
- r_drawsurf.lightadj[1] = r_newrefdef.lightstyles[surface->styles[1]].white*128;
- r_drawsurf.lightadj[2] = r_newrefdef.lightstyles[surface->styles[2]].white*128;
- r_drawsurf.lightadj[3] = r_newrefdef.lightstyles[surface->styles[3]].white*128;
-
-//
-// see if the cache holds apropriate data
-//
- cache = surface->cachespots[miplevel];
-
- if (cache && !cache->dlight && surface->dlightframe != r_framecount
- && cache->image == r_drawsurf.image
- && cache->lightadj[0] == r_drawsurf.lightadj[0]
- && cache->lightadj[1] == r_drawsurf.lightadj[1]
- && cache->lightadj[2] == r_drawsurf.lightadj[2]
- && cache->lightadj[3] == r_drawsurf.lightadj[3] )
- return cache;
-
-//
-// determine shape of surface
-//
- surfscale = 1.0 / (1<<miplevel);
- r_drawsurf.surfmip = miplevel;
- r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
- r_drawsurf.rowbytes = r_drawsurf.surfwidth;
- r_drawsurf.surfheight = surface->extents[1] >> miplevel;
-
-//
-// allocate memory if needed
-//
- if (!cache) // if a texture just animated, don't reallocate it
- {
- cache = D_SCAlloc (r_drawsurf.surfwidth,
- r_drawsurf.surfwidth * r_drawsurf.surfheight);
- surface->cachespots[miplevel] = cache;
- cache->owner = &surface->cachespots[miplevel];
- cache->mipscale = surfscale;
- }
-
- if (surface->dlightframe == r_framecount)
- cache->dlight = 1;
- else
- cache->dlight = 0;
-
- r_drawsurf.surfdat = (pixel_t *)cache->data;
-
- cache->image = r_drawsurf.image;
- cache->lightadj[0] = r_drawsurf.lightadj[0];
- cache->lightadj[1] = r_drawsurf.lightadj[1];
- cache->lightadj[2] = r_drawsurf.lightadj[2];
- cache->lightadj[3] = r_drawsurf.lightadj[3];
-
-//
-// draw and light the surface texture
-//
- r_drawsurf.surf = surface;
-
- c_surf++;
-
- // calculate the lightings
- R_BuildLightMap ();
-
- // rasterize the surface into the cache
- R_DrawSurface ();
-
- return cache;
-}
-
-
--- a/ref_soft/rand1k.h
+++ /dev/null
@@ -1,123 +1,0 @@
-/*
-Copyright (C) 1997-2001 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-// 1K random numbers in the range 0-255
-0, 144, 49, 207, 149, 122, 89, 229, 210, 191,
-44, 219, 181, 131, 77, 3, 23, 93, 37, 42,
-253, 114, 30, 1, 2, 96, 136, 146, 154, 155,
-42, 169, 115, 90, 14, 155, 200, 205, 133, 77,
-224, 186, 244, 236, 138, 36, 118, 60, 220, 53,
-199, 215, 255, 255, 156, 100, 68, 76, 215, 6,
-96, 23, 173, 14, 2, 235, 70, 69, 150, 176,
-214, 185, 124, 52, 190, 119, 117, 242, 190, 27,
-153, 98, 188, 155, 146, 92, 38, 57, 108, 205,
-132, 253, 192, 88, 43, 168, 125, 16, 179, 129,
-37, 243, 36, 231, 177, 77, 109, 18, 247, 174,
-39, 224, 210, 149, 48, 45, 209, 121, 39, 129,
-187, 103, 71, 145, 174, 193, 184, 121, 31, 94,
-213, 8, 132, 169, 109, 26, 243, 235, 140, 88,
-120, 95, 216, 81, 116, 69, 251, 76, 189, 145,
-50, 194, 214, 101, 128, 227, 7, 254, 146, 12,
-136, 49, 215, 160, 168, 50, 215, 31, 28, 190,
-80, 240, 73, 86, 35, 187, 213, 181, 153, 191,
-64, 36, 0, 15, 206, 218, 53, 29, 141, 3,
-29, 116, 192, 175, 139, 18, 111, 51, 178, 74,
-111, 59, 147, 136, 160, 41, 129, 246, 178, 236,
-48, 86, 45, 254, 117, 255, 24, 160, 24, 112,
-238, 12, 229, 74, 58, 196, 105, 51, 160, 154,
-115, 119, 153, 162, 218, 212, 159, 184, 144, 96,
-47, 188, 142, 231, 62, 48, 154, 178, 149, 89,
-126, 20, 189, 156, 158, 176, 205, 38, 147, 222,
-233, 157, 186, 11, 170, 249, 80, 145, 78, 44,
-27, 222, 217, 190, 39, 83, 20, 19, 164, 209,
-139, 114, 104, 76, 119, 128, 39, 82, 188, 80,
-211, 245, 223, 185, 76, 241, 32, 16, 200, 134,
-156, 244, 18, 224, 167, 82, 26, 129, 58, 74,
-235, 141, 169, 29, 126, 97, 127, 203, 130, 97,
-176, 136, 155, 101, 1, 181, 25, 159, 220, 125,
-191, 127, 97, 201, 141, 91, 244, 161, 45, 95,
-33, 190, 243, 156, 7, 84, 14, 163, 33, 216,
-221, 152, 184, 218, 3, 32, 181, 157, 55, 16,
-43, 159, 87, 81, 94, 169, 205, 206, 134, 156,
-204, 230, 37, 161, 103, 64, 34, 218, 16, 109,
-146, 77, 140, 57, 79, 28, 206, 34, 72, 201,
-229, 202, 190, 157, 92, 219, 58, 221, 58, 63,
-138, 252, 13, 20, 134, 109, 24, 66, 228, 59,
-37, 32, 238, 20, 12, 15, 86, 234, 102, 110,
-242, 214, 136, 215, 177, 101, 66, 1, 134, 244,
-102, 61, 149, 65, 175, 241, 111, 227, 1, 240,
-153, 201, 147, 36, 56, 98, 1, 106, 21, 168,
-218, 16, 207, 169, 177, 205, 135, 175, 36, 176,
-186, 199, 7, 222, 164, 180, 21, 141, 242, 15,
-70, 37, 251, 158, 74, 236, 94, 177, 55, 39,
-61, 133, 230, 27, 231, 113, 20, 200, 43, 249,
-198, 222, 53, 116, 0, 192, 29, 103, 79, 254,
-9, 64, 48, 63, 39, 158, 226, 240, 50, 199,
-165, 168, 232, 116, 235, 170, 38, 162, 145, 108,
-241, 138, 148, 137, 65, 101, 89, 9, 203, 50,
-17, 99, 151, 18, 50, 39, 164, 116, 154, 178,
-112, 175, 101, 213, 151, 51, 243, 224, 100, 252,
-47, 229, 147, 113, 160, 181, 12, 73, 66, 104,
-229, 181, 186, 229, 100, 101, 231, 79, 99, 146,
-90, 187, 190, 188, 189, 35, 51, 69, 174, 233,
-94, 132, 28, 232, 51, 132, 167, 112, 176, 23,
-20, 19, 7, 90, 78, 178, 36, 101, 17, 172,
-185, 50, 177, 157, 167, 139, 25, 139, 12, 249,
-118, 248, 186, 135, 174, 177, 95, 99, 12, 207,
-43, 15, 79, 200, 54, 82, 124, 2, 112, 130,
-155, 194, 102, 89, 215, 241, 159, 255, 13, 144,
-221, 99, 78, 72, 6, 156, 100, 4, 7, 116,
-219, 239, 102, 186, 156, 206, 224, 149, 152, 20,
-203, 118, 151, 150, 145, 208, 172, 87, 2, 68,
-87, 59, 197, 95, 222, 29, 185, 161, 228, 46,
-137, 230, 199, 247, 50, 230, 204, 244, 217, 227,
-160, 47, 157, 67, 64, 187, 201, 43, 182, 123,
-20, 206, 218, 31, 78, 146, 121, 195, 49, 186,
-254, 3, 165, 177, 44, 18, 70, 173, 214, 142,
-95, 199, 59, 163, 59, 52, 248, 72, 5, 196,
-38, 12, 2, 89, 164, 87, 106, 106, 23, 139,
-179, 86, 168, 224, 137, 145, 13, 119, 66, 109,
-221, 124, 22, 144, 181, 199, 221, 217, 75, 221,
-165, 191, 212, 195, 223, 232, 233, 133, 112, 27,
-90, 210, 109, 43, 0, 168, 198, 16, 22, 98,
-175, 206, 39, 36, 12, 88, 4, 250, 165, 13,
-234, 163, 110, 5, 62, 100, 167, 200, 5, 211,
-35, 162, 140, 251, 118, 54, 76, 200, 87, 123,
-155, 26, 252, 193, 38, 116, 182, 255, 198, 164,
-159, 242, 176, 74, 145, 74, 140, 182, 63, 139,
-126, 243, 171, 195, 159, 114, 204, 190, 253, 52,
-161, 232, 151, 235, 129, 125, 115, 227, 240, 46,
-64, 51, 187, 240, 160, 10, 164, 8, 142, 139,
-114, 15, 254, 32, 153, 12, 44, 169, 85, 80,
-167, 105, 109, 56, 173, 42, 127, 129, 205, 111,
-1, 86, 96, 32, 211, 187, 228, 164, 166, 131,
-187, 188, 245, 119, 92, 28, 231, 210, 116, 27,
-222, 194, 10, 106, 239, 17, 42, 54, 29, 151,
-30, 158, 148, 176, 187, 234, 171, 76, 207, 96,
-255, 197, 52, 43, 99, 46, 148, 50, 245, 48,
-97, 77, 30, 50, 11, 197, 194, 225, 0, 114,
-109, 205, 118, 126, 191, 61, 143, 23, 236, 228,
-219, 15, 125, 161, 191, 193, 65, 232, 202, 51,
-141, 13, 133, 202, 180, 6, 187, 141, 234, 224,
-204, 78, 101, 123, 13, 166, 0, 196, 193, 56,
-39, 14, 171, 8, 88, 178, 204, 111, 251, 162,
-75, 122, 223, 20, 25, 36, 36, 235, 79, 95,
-208, 11, 208, 61, 229, 65, 68, 53, 58, 216,
-223, 227, 216, 155, 10, 44, 47, 91, 115, 47,
-228, 159, 139, 233