This commit is contained in:
Literally A Penguin
2024-09-25 15:39:25 -05:00
committed by GitHub
parent e8bd66b89c
commit 0bf99969fd
86 changed files with 51093 additions and 0 deletions

205
linux/q_shlinux.c Normal file
View File

@ -0,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;
}
//============================================

459
linux/qasm.h Normal file
View File

@ -0,0 +1,459 @@
#ifndef __ASM_I386__
#define __ASM_I386__
#ifdef ELF
#define C(label) label
#else
#define C(label) _##label
#endif
//#define GLQUAKE 1
#if defined(_WIN32) && !defined(WINDED)
#if defined(_M_IX86)
#define __i386__ 1
#endif
#endif
#ifdef __i386__
#define id386 1
#else
#define id386 0
#endif
// !!! must be kept the same as in d_iface.h !!!
#define TRANSPARENT_COLOR 255
#ifndef GLQUAKE
.extern C(d_zistepu)
.extern C(d_pzbuffer)
.extern C(d_zistepv)
.extern C(d_zrowbytes)
.extern C(d_ziorigin)
.extern C(r_turb_s)
.extern C(r_turb_t)
.extern C(r_turb_pdest)
.extern C(r_turb_spancount)
.extern C(r_turb_turb)
.extern C(r_turb_pbase)
.extern C(r_turb_sstep)
.extern C(r_turb_tstep)
.extern C(r_bmodelactive)
.extern C(d_sdivzstepu)
.extern C(d_tdivzstepu)
.extern C(d_sdivzstepv)
.extern C(d_tdivzstepv)
.extern C(d_sdivzorigin)
.extern C(d_tdivzorigin)
.extern C(sadjust)
.extern C(tadjust)
.extern C(bbextents)
.extern C(bbextentt)
.extern C(cacheblock)
.extern C(d_viewbuffer)
.extern C(cachewidth)
.extern C(d_pzbuffer)
.extern C(d_zrowbytes)
.extern C(d_zwidth)
.extern C(d_scantable)
.extern C(r_lightptr)
.extern C(r_numvblocks)
.extern C(prowdestbase)
.extern C(pbasesource)
.extern C(r_lightwidth)
.extern C(lightright)
.extern C(lightrightstep)
.extern C(lightdeltastep)
.extern C(lightdelta)
.extern C(lightright)
.extern C(lightdelta)
.extern C(sourcetstep)
.extern C(surfrowbytes)
.extern C(lightrightstep)
.extern C(lightdeltastep)
.extern C(r_sourcemax)
.extern C(r_stepback)
.extern C(colormap)
.extern C(blocksize)
.extern C(sourcesstep)
.extern C(lightleft)
.extern C(blockdivshift)
.extern C(blockdivmask)
.extern C(lightleftstep)
.extern C(r_origin)
.extern C(r_ppn)
.extern C(r_pup)
.extern C(r_pright)
.extern C(ycenter)
.extern C(xcenter)
.extern C(d_vrectbottom_particle)
.extern C(d_vrectright_particle)
.extern C(d_vrecty)
.extern C(d_vrectx)
.extern C(d_pix_shift)
.extern C(d_pix_min)
.extern C(d_pix_max)
.extern C(d_y_aspect_shift)
.extern C(screenwidth)
.extern C(r_leftclipped)
.extern C(r_leftenter)
.extern C(r_rightclipped)
.extern C(r_rightenter)
.extern C(modelorg)
.extern C(xscale)
.extern C(r_refdef)
.extern C(yscale)
.extern C(r_leftexit)
.extern C(r_rightexit)
.extern C(r_lastvertvalid)
.extern C(cacheoffset)
.extern C(newedges)
.extern C(removeedges)
.extern C(r_pedge)
.extern C(r_framecount)
.extern C(r_u1)
.extern C(r_emitted)
.extern C(edge_p)
.extern C(surface_p)
.extern C(surfaces)
.extern C(r_lzi1)
.extern C(r_v1)
.extern C(r_ceilv1)
.extern C(r_nearzi)
.extern C(r_nearzionly)
.extern C(edge_aftertail)
.extern C(edge_tail)
.extern C(current_iv)
.extern C(edge_head_u_shift20)
.extern C(span_p)
.extern C(edge_head)
.extern C(fv)
.extern C(edge_tail_u_shift20)
.extern C(r_apverts)
.extern C(r_anumverts)
.extern C(aliastransform)
.extern C(r_avertexnormals)
.extern C(r_plightvec)
.extern C(r_ambientlight)
.extern C(r_shadelight)
.extern C(aliasxcenter)
.extern C(aliasycenter)
.extern C(a_sstepxfrac)
.extern C(r_affinetridesc)
.extern C(acolormap)
.extern C(d_pcolormap)
.extern C(r_affinetridesc)
.extern C(d_sfrac)
.extern C(d_ptex)
.extern C(d_pedgespanpackage)
.extern C(d_tfrac)
.extern C(d_light)
.extern C(d_zi)
.extern C(d_pdest)
.extern C(d_pz)
.extern C(d_aspancount)
.extern C(erroradjustup)
.extern C(errorterm)
.extern C(d_xdenom)
.extern C(r_p0)
.extern C(r_p1)
.extern C(r_p2)
.extern C(a_tstepxfrac)
.extern C(r_sstepx)
.extern C(r_tstepx)
.extern C(a_ststepxwhole)
.extern C(zspantable)
.extern C(skintable)
.extern C(r_zistepx)
.extern C(erroradjustdown)
.extern C(d_countextrastep)
.extern C(ubasestep)
.extern C(a_ststepxwhole)
.extern C(a_tstepxfrac)
.extern C(r_lstepx)
.extern C(a_spans)
.extern C(erroradjustdown)
.extern C(d_pdestextrastep)
.extern C(d_pzextrastep)
.extern C(d_sfracextrastep)
.extern C(d_ptexextrastep)
.extern C(d_countextrastep)
.extern C(d_tfracextrastep)
.extern C(d_lightextrastep)
.extern C(d_ziextrastep)
.extern C(d_pdestbasestep)
.extern C(d_pzbasestep)
.extern C(d_sfracbasestep)
.extern C(d_ptexbasestep)
.extern C(ubasestep)
.extern C(d_tfracbasestep)
.extern C(d_lightbasestep)
.extern C(d_zibasestep)
.extern C(zspantable)
.extern C(r_lstepy)
.extern C(r_sstepy)
.extern C(r_tstepy)
.extern C(r_zistepy)
.extern C(D_PolysetSetEdgeTable)
.extern C(D_RasterizeAliasPolySmooth)
.extern float_point5
.extern Float2ToThe31nd
.extern izistep
.extern izi
.extern FloatMinus2ToThe31nd
.extern float_1
.extern float_particle_z_clip
.extern float_minus_1
.extern float_0
.extern fp_16
.extern fp_64k
.extern fp_1m
.extern fp_1m_minus_1
.extern fp_8
.extern entryvec_table
.extern advancetable
.extern sstep
.extern tstep
.extern pspantemp
.extern counttemp
.extern jumptemp
.extern reciprocal_table
.extern DP_Count
.extern DP_u
.extern DP_v
.extern DP_32768
.extern DP_Color
.extern DP_Pix
.extern DP_EntryTable
.extern pbase
.extern s
.extern t
.extern sfracf
.extern tfracf
.extern snext
.extern tnext
.extern spancountminus1
.extern zi16stepu
.extern sdivz16stepu
.extern tdivz16stepu
.extern zi8stepu
.extern sdivz8stepu
.extern tdivz8stepu
.extern reciprocal_table_16
.extern entryvec_table_16
.extern ceil_cw
.extern single_cw
.extern fp_64kx64k
.extern pz
.extern spr8entryvec_table
#endif
.extern C(snd_scaletable)
.extern C(paintbuffer)
.extern C(snd_linear_count)
.extern C(snd_p)
.extern C(snd_vol)
.extern C(snd_out)
.extern C(vright)
.extern C(vup)
.extern C(vpn)
.extern C(BOPS_Error)
//
// !!! note that this file must match the corresponding C structures at all
// times !!!
//
// plane_t structure
// !!! if this is changed, it must be changed in model.h too !!!
// !!! if the size of this is changed, the array lookup in SV_HullPointContents
// must be changed too !!!
#define pl_normal 0
#define pl_dist 12
#define pl_type 16
#define pl_signbits 17
#define pl_pad 18
#define pl_size 20
// hull_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define hu_clipnodes 0
#define hu_planes 4
#define hu_firstclipnode 8
#define hu_lastclipnode 12
#define hu_clip_mins 16
#define hu_clip_maxs 28
#define hu_size 40
// dnode_t structure
// !!! if this is changed, it must be changed in bspfile.h too !!!
#define nd_planenum 0
#define nd_children 4
#define nd_mins 8
#define nd_maxs 20
#define nd_firstface 32
#define nd_numfaces 36
#define nd_size 40
// sfxcache_t structure
// !!! if this is changed, it much be changed in sound.h too !!!
#define sfxc_length 0
#define sfxc_loopstart 4
#define sfxc_speed 8
#define sfxc_width 12
#define sfxc_stereo 16
#define sfxc_data 20
// channel_t structure
// !!! if this is changed, it much be changed in sound.h too !!!
#define ch_sfx 0
#define ch_leftvol 4
#define ch_rightvol 8
#define ch_end 12
#define ch_pos 16
#define ch_looping 20
#define ch_entnum 24
#define ch_entchannel 28
#define ch_origin 32
#define ch_dist_mult 44
#define ch_master_vol 48
#define ch_size 52
// portable_samplepair_t structure
// !!! if this is changed, it much be changed in sound.h too !!!
#define psp_left 0
#define psp_right 4
#define psp_size 8
//
// !!! note that this file must match the corresponding C structures at all
// times !!!
//
// !!! if this is changed, it must be changed in r_local.h too !!!
#define NEAR_CLIP 0.01
// !!! if this is changed, it must be changed in r_local.h too !!!
#define CYCLE 128
// espan_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define espan_t_u 0
#define espan_t_v 4
#define espan_t_count 8
#define espan_t_pnext 12
#define espan_t_size 16
// sspan_t structure
// !!! if this is changed, it must be changed in d_local.h too !!!
#define sspan_t_u 0
#define sspan_t_v 4
#define sspan_t_count 8
#define sspan_t_size 12
// spanpackage_t structure
// !!! if this is changed, it must be changed in d_polyset.c too !!!
#define spanpackage_t_pdest 0
#define spanpackage_t_pz 4
#define spanpackage_t_count 8
#define spanpackage_t_ptex 12
#define spanpackage_t_sfrac 16
#define spanpackage_t_tfrac 20
#define spanpackage_t_light 24
#define spanpackage_t_zi 28
#define spanpackage_t_size 32
// edge_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define et_u 0
#define et_u_step 4
#define et_prev 8
#define et_next 12
#define et_surfs 16
#define et_nextremove 20
#define et_nearzi 24
#define et_owner 28
#define et_size 32
// surf_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define SURF_T_SHIFT 6
#define st_next 0
#define st_prev 4
#define st_spans 8
#define st_key 12
#define st_last_u 16
#define st_spanstate 20
#define st_flags 24
#define st_data 28
#define st_entity 32
#define st_nearzi 36
#define st_insubmodel 40
#define st_d_ziorigin 44
#define st_d_zistepu 48
#define st_d_zistepv 52
#define st_pad 56
#define st_size 64
// clipplane_t structure
// !!! if this is changed, it must be changed in r_local.h too !!!
#define cp_normal 0
#define cp_dist 12
#define cp_next 16
#define cp_leftedge 20
#define cp_rightedge 21
#define cp_reserved 22
#define cp_size 24
// medge_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define me_v 0
#define me_cachededgeoffset 4
#define me_size 8
// mvertex_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define mv_position 0
#define mv_size 12
// refdef_t structure
// !!! if this is changed, it must be changed in render.h too !!!
#define rd_vrect 0
#define rd_aliasvrect 20
#define rd_vrectright 40
#define rd_vrectbottom 44
#define rd_aliasvrectright 48
#define rd_aliasvrectbottom 52
#define rd_vrectrightedge 56
#define rd_fvrectx 60
#define rd_fvrecty 64
#define rd_fvrectx_adj 68
#define rd_fvrecty_adj 72
#define rd_vrect_x_adj_shift20 76
#define rd_vrectright_adj_shift20 80
#define rd_fvrectright_adj 84
#define rd_fvrectbottom_adj 88
#define rd_fvrectright 92
#define rd_fvrectbottom 96
#define rd_horizontalFieldOfView 100
#define rd_xOrigin 104
#define rd_yOrigin 108
#define rd_vieworg 112
#define rd_viewangles 124
#define rd_ambientlight 136
#define rd_size 140
// mtriangle_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define mtri_facesfront 0
#define mtri_vertindex 4
#define mtri_size 16 // !!! if this changes, array indexing in !!!
// !!! d_polysa.s must be changed to match !!!
#define mtri_shift 4
#endif

3994
linux/qgl_linux.c Normal file

File diff suppressed because it is too large Load Diff

195
linux/r_aclipa.s Normal file
View File

@ -0,0 +1,195 @@
//
// r_aliasa.s
// x86 assembly-language Alias model transform and project code.
//
#include "qasm.h"
#include "d_ifacea.h"
#if id386
.data
Ltemp0: .long 0
Ltemp1: .long 0
.text
#define pfv0 8+4
#define pfv1 8+8
#define out 8+12
.globl C(R_Alias_clip_bottom)
C(R_Alias_clip_bottom):
pushl %esi
pushl %edi
movl pfv0(%esp),%esi
movl pfv1(%esp),%edi
movl C(r_refdef)+rd_aliasvrectbottom,%eax
LDoForwardOrBackward:
movl fv_v+4(%esi),%edx
movl fv_v+4(%edi),%ecx
cmpl %ecx,%edx
jl LDoForward
movl fv_v+4(%esi),%ecx
movl fv_v+4(%edi),%edx
movl pfv0(%esp),%edi
movl pfv1(%esp),%esi
LDoForward:
subl %edx,%ecx
subl %edx,%eax
movl %ecx,Ltemp1
movl %eax,Ltemp0
fildl Ltemp1
fildl Ltemp0
movl out(%esp),%edx
movl $2,%eax
fdivp %st(0),%st(1) // scale
LDo3Forward:
fildl fv_v+0(%esi) // fv0v0 | scale
fildl fv_v+0(%edi) // fv1v0 | fv0v0 | scale
fildl fv_v+4(%esi) // fv0v1 | fv1v0 | fv0v0 | scale
fildl fv_v+4(%edi) // fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale
fildl fv_v+8(%esi) // fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale
fildl fv_v+8(%edi) // fv1v2 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 |
// scale
fxch %st(5) // fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv1v2 |
// scale
fsubr %st(0),%st(4) // fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0-fv0v0 |
// fv1v2 | scale
fxch %st(3) // fv0v1 | fv0v2 | fv1v1 | fv0v0 | fv1v0-fv0v0 |
// fv1v2 | scale
fsubr %st(0),%st(2) // fv0v1 | fv0v2 | fv1v1-fv0v1 | fv0v0 |
// fv1v0-fv0v0 | fv1v2 | scale
fxch %st(1) // fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 |
// fv1v0-fv0v0 | fv1v2 | scale
fsubr %st(0),%st(5) // fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 |
// fv1v0-fv0v0 | fv1v2-fv0v2 | scale
fxch %st(6) // scale | fv0v1 | fv1v1-fv0v1 | fv0v0 |
// fv1v0-fv0v0 | fv1v2-fv0v2 | fv0v2
fmul %st(0),%st(4) // scale | fv0v1 | fv1v1-fv0v1 | fv0v0 |
// (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2
addl $12,%edi
fmul %st(0),%st(2) // scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 |
// (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2
addl $12,%esi
addl $12,%edx
fmul %st(0),%st(5) // scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 |
// (fv1v0-fv0v0)*scale | (fv1v2-fv0v2)*scale |
// fv0v2
fxch %st(3) // fv0v0 | fv0v1 | (fv1v1-fv0v1)*scale | scale |
// (fv1v0-fv0v0)*scale | (fv1v2-fv0v2)*scale |
// fv0v2
faddp %st(0),%st(4) // fv0v1 | (fv1v1-fv0v1)*scale | scale |
// fv0v0+(fv1v0-fv0v0)*scale |
// (fv1v2-fv0v2)*scale | fv0v2
faddp %st(0),%st(1) // fv0v1+(fv1v1-fv0v1)*scale | scale |
// fv0v0+(fv1v0-fv0v0)*scale |
// (fv1v2-fv0v2)*scale | fv0v2
fxch %st(4) // fv0v2 | scale | fv0v0+(fv1v0-fv0v0)*scale |
// (fv1v2-fv0v2)*scale | fv0v1+(fv1v1-fv0v1)*scale
faddp %st(0),%st(3) // scale | fv0v0+(fv1v0-fv0v0)*scale |
// fv0v2+(fv1v2-fv0v2)*scale |
// fv0v1+(fv1v1-fv0v1)*scale
fxch %st(1) // fv0v0+(fv1v0-fv0v0)*scale | scale |
// fv0v2+(fv1v2-fv0v2)*scale |
// fv0v1+(fv1v1-fv0v1)*scale
fadds float_point5
fxch %st(3) // fv0v1+(fv1v1-fv0v1)*scale | scale |
// fv0v2+(fv1v2-fv0v2)*scale |
// fv0v0+(fv1v0-fv0v0)*scale
fadds float_point5
fxch %st(2) // fv0v2+(fv1v2-fv0v2)*scale | scale |
// fv0v1+(fv1v1-fv0v1)*scale |
// fv0v0+(fv1v0-fv0v0)*scale
fadds float_point5
fxch %st(3) // fv0v0+(fv1v0-fv0v0)*scale | scale |
// fv0v1+(fv1v1-fv0v1)*scale |
// fv0v2+(fv1v2-fv0v2)*scale
fistpl fv_v+0-12(%edx) // scale | fv0v1+(fv1v1-fv0v1)*scale |
// fv0v2+(fv1v2-fv0v2)*scale
fxch %st(1) // fv0v1+(fv1v1-fv0v1)*scale | scale |
// fv0v2+(fv1v2-fv0v2)*scale | scale
fistpl fv_v+4-12(%edx) // scale | fv0v2+(fv1v2-fv0v2)*scale
fxch %st(1) // fv0v2+(fv1v2-fv0v2)*sc | scale
fistpl fv_v+8-12(%edx) // scale
decl %eax
jnz LDo3Forward
fstp %st(0)
popl %edi
popl %esi
ret
.globl C(R_Alias_clip_top)
C(R_Alias_clip_top):
pushl %esi
pushl %edi
movl pfv0(%esp),%esi
movl pfv1(%esp),%edi
movl C(r_refdef)+rd_aliasvrect+4,%eax
jmp LDoForwardOrBackward
.globl C(R_Alias_clip_right)
C(R_Alias_clip_right):
pushl %esi
pushl %edi
movl pfv0(%esp),%esi
movl pfv1(%esp),%edi
movl C(r_refdef)+rd_aliasvrectright,%eax
LRightLeftEntry:
movl fv_v+4(%esi),%edx
movl fv_v+4(%edi),%ecx
cmpl %ecx,%edx
movl fv_v+0(%esi),%edx
movl fv_v+0(%edi),%ecx
jl LDoForward2
movl fv_v+0(%esi),%ecx
movl fv_v+0(%edi),%edx
movl pfv0(%esp),%edi
movl pfv1(%esp),%esi
LDoForward2:
jmp LDoForward
.globl C(R_Alias_clip_left)
C(R_Alias_clip_left):
pushl %esi
pushl %edi
movl pfv0(%esp),%esi
movl pfv1(%esp),%edi
movl C(r_refdef)+rd_aliasvrect+0,%eax
jmp LRightLeftEntry
#endif // id386

1227
linux/r_draw16.s Normal file

File diff suppressed because it is too large Load Diff

817
linux/r_drawa.s Normal file
View File

@ -0,0 +1,817 @@
//
// r_drawa.s
// x86 assembly-language edge clipping and emission code
//
#include "qasm.h"
#include "d_ifacea.h"
#if id386
// !!! if these are changed, they must be changed in r_draw.c too !!!
#define FULLY_CLIPPED_CACHED 0x80000000
#define FRAMECOUNT_MASK 0x7FFFFFFF
.data
Ld0: .single 0.0
Ld1: .single 0.0
Lstack: .long 0
Lfp_near_clip: .single NEAR_CLIP
Lceilv0: .long 0
Lv: .long 0
Lu0: .long 0
Lv0: .long 0
Lzi0: .long 0
.text
//----------------------------------------------------------------------
// edge clipping code
//----------------------------------------------------------------------
#define pv0 4+12
#define pv1 8+12
#define clip 12+12
.align 4
.globl C(R_ClipEdge)
C(R_ClipEdge):
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
movl %esp,Lstack // for clearing the stack later
// float d0, d1, f;
// mvertex_t clipvert;
movl clip(%esp),%ebx
movl pv0(%esp),%esi
movl pv1(%esp),%edx
// if (clip)
// {
testl %ebx,%ebx
jz Lemit
// do
// {
Lcliploop:
// d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
// d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
flds mv_position+0(%esi)
fmuls cp_normal+0(%ebx)
flds mv_position+4(%esi)
fmuls cp_normal+4(%ebx)
flds mv_position+8(%esi)
fmuls cp_normal+8(%ebx)
fxch %st(1)
faddp %st(0),%st(2) // d0mul2 | d0add0
flds mv_position+0(%edx)
fmuls cp_normal+0(%ebx)
flds mv_position+4(%edx)
fmuls cp_normal+4(%ebx)
flds mv_position+8(%edx)
fmuls cp_normal+8(%ebx)
fxch %st(1)
faddp %st(0),%st(2) // d1mul2 | d1add0 | d0mul2 | d0add0
fxch %st(3) // d0add0 | d1add0 | d0mul2 | d1mul2
faddp %st(0),%st(2) // d1add0 | dot0 | d1mul2
faddp %st(0),%st(2) // dot0 | dot1
fsubs cp_dist(%ebx) // d0 | dot1
fxch %st(1) // dot1 | d0
fsubs cp_dist(%ebx) // d1 | d0
fxch %st(1)
fstps Ld0
fstps Ld1
// if (d0 >= 0)
// {
movl Ld0,%eax
movl Ld1,%ecx
orl %eax,%ecx
js Lp2
// both points are unclipped
Lcontinue:
//
// R_ClipEdge (&clipvert, pv1, clip->next);
// return;
// }
// } while ((clip = clip->next) != NULL);
movl cp_next(%ebx),%ebx
testl %ebx,%ebx
jnz Lcliploop
// }
//// add the edge
// R_EmitEdge (pv0, pv1);
Lemit:
//
// set integer rounding to ceil mode, set to single precision
//
// FIXME: do away with by manually extracting integers from floats?
// FIXME: set less often
fldcw ceil_cw
// 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)
// {
cmpl $0,C(r_lastvertvalid)
jz LCalcFirst
// u0 = r_u1;
// v0 = r_v1;
// lzi0 = r_lzi1;
// ceilv0 = r_ceilv1;
movl C(r_lzi1),%eax
movl C(r_u1),%ecx
movl %eax,Lzi0
movl %ecx,Lu0
movl C(r_v1),%ecx
movl C(r_ceilv1),%eax
movl %ecx,Lv0
movl %eax,Lceilv0
jmp LCalcSecond
// }
LCalcFirst:
// else
// {
// world = &pv0->position[0];
call LTransformAndProject // v0 | lzi0 | u0
fsts Lv0
fxch %st(2) // u0 | lzi0 | v0
fstps Lu0 // lzi0 | v0
fstps Lzi0 // v0
// ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
fistpl Lceilv0
// }
LCalcSecond:
// world = &pv1->position[0];
movl %edx,%esi
call LTransformAndProject // v1 | lzi1 | u1
flds Lu0 // u0 | v1 | lzi1 | u1
fxch %st(3) // u1 | v1 | lzi1 | u0
flds Lzi0 // lzi0 | u1 | v1 | lzi1 | u0
fxch %st(3) // lzi1 | u1 | v1 | lzi0 | u0
flds Lv0 // v0 | lzi1 | u1 | v1 | lzi0 | u0
fxch %st(3) // v1 | lzi1 | u1 | v0 | lzi0 | u0
// r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
fistl C(r_ceilv1)
fldcw single_cw // put back normal floating-point state
fsts C(r_v1)
fxch %st(4) // lzi0 | lzi1 | u1 | v0 | v1 | u0
// if (r_lzi1 > lzi0)
// lzi0 = r_lzi1;
fcom %st(1)
fnstsw %ax
testb $1,%ah
jz LP0
fstp %st(0)
fld %st(0)
LP0:
fxch %st(1) // lzi1 | lzi0 | u1 | v0 | v1 | u0
fstps C(r_lzi1) // lzi0 | u1 | v0 | v1 | u0
fxch %st(1)
fsts C(r_u1)
fxch %st(1)
// if (lzi0 > r_nearzi) // for mipmap finding
// r_nearzi = lzi0;
fcoms C(r_nearzi)
fnstsw %ax
testb $0x45,%ah
jnz LP1
fsts C(r_nearzi)
LP1:
// // for right edges, all we want is the effect on 1/z
// if (r_nearzionly)
// return;
movl C(r_nearzionly),%eax
testl %eax,%eax
jz LP2
LPop5AndDone:
movl C(cacheoffset),%eax
movl C(r_framecount),%edx
cmpl $0x7FFFFFFF,%eax
jz LDoPop
andl $(FRAMECOUNT_MASK),%edx
orl $(FULLY_CLIPPED_CACHED),%edx
movl %edx,C(cacheoffset)
LDoPop:
fstp %st(0) // u1 | v0 | v1 | u0
fstp %st(0) // v0 | v1 | u0
fstp %st(0) // v1 | u0
fstp %st(0) // u0
fstp %st(0)
jmp Ldone
LP2:
// // create the edge
// if (ceilv0 == r_ceilv1)
// return; // horizontal edge
movl Lceilv0,%ebx
movl C(edge_p),%edi
movl C(r_ceilv1),%ecx
movl %edi,%edx
movl C(r_pedge),%esi
addl $(et_size),%edx
cmpl %ecx,%ebx
jz LPop5AndDone
movl C(r_pedge),%eax
movl %eax,et_owner(%edi)
// side = ceilv0 > r_ceilv1;
//
// edge->nearzi = lzi0;
fstps et_nearzi(%edi) // u1 | v0 | v1 | u0
// if (side == 1)
// {
jc LSide0
LSide1:
// // leading edge (go from p2 to p1)
// u_step = ((u0 - r_u1) / (v0 - r_v1));
fsubrp %st(0),%st(3) // v0 | v1 | u0-u1
fsub %st(1),%st(0) // v0-v1 | v1 | u0-u1
fdivrp %st(0),%st(2) // v1 | ustep
// r_emitted = 1;
movl $1,C(r_emitted)
// edge = edge_p++;
movl %edx,C(edge_p)
// pretouch next edge
movl (%edx),%eax
// v2 = ceilv0 - 1;
// v = r_ceilv1;
movl %ecx,%eax
leal -1(%ebx),%ecx
movl %eax,%ebx
// edge->surfs[0] = 0;
// edge->surfs[1] = surface_p - surfaces;
movl C(surface_p),%eax
movl C(surfaces),%esi
subl %edx,%edx
subl %esi,%eax
shrl $(SURF_T_SHIFT),%eax
movl %edx,et_surfs(%edi)
movl %eax,et_surfs+2(%edi)
subl %esi,%esi
// u = r_u1 + ((float)v - r_v1) * u_step;
movl %ebx,Lv
fildl Lv // v | v1 | ustep
fsubp %st(0),%st(1) // v-v1 | ustep
fmul %st(1),%st(0) // (v-v1)*ustep | ustep
fadds C(r_u1) // u | ustep
jmp LSideDone
// }
LSide0:
// else
// {
// // trailing edge (go from p1 to p2)
// u_step = ((r_u1 - u0) / (r_v1 - v0));
fsub %st(3),%st(0) // u1-u0 | v0 | v1 | u0
fxch %st(2) // v1 | v0 | u1-u0 | u0
fsub %st(1),%st(0) // v1-v0 | v0 | u1-u0 | u0
fdivrp %st(0),%st(2) // v0 | ustep | u0
// r_emitted = 1;
movl $1,C(r_emitted)
// edge = edge_p++;
movl %edx,C(edge_p)
// pretouch next edge
movl (%edx),%eax
// v = ceilv0;
// v2 = r_ceilv1 - 1;
decl %ecx
// edge->surfs[0] = surface_p - surfaces;
// edge->surfs[1] = 0;
movl C(surface_p),%eax
movl C(surfaces),%esi
subl %edx,%edx
subl %esi,%eax
shrl $(SURF_T_SHIFT),%eax
movl %edx,et_surfs+2(%edi)
movl %eax,et_surfs(%edi)
movl $1,%esi
// u = u0 + ((float)v - v0) * u_step;
movl %ebx,Lv
fildl Lv // v | v0 | ustep | u0
fsubp %st(0),%st(1) // v-v0 | ustep | u0
fmul %st(1),%st(0) // (v-v0)*ustep | ustep | u0
faddp %st(0),%st(2) // ustep | u
fxch %st(1) // u | ustep
// }
LSideDone:
// edge->u_step = u_step*0x100000;
// edge->u = u*0x100000 + 0xFFFFF;
fmuls fp_1m // u*0x100000 | ustep
fxch %st(1) // ustep | u*0x100000
fmuls fp_1m // ustep*0x100000 | u*0x100000
fxch %st(1) // u*0x100000 | ustep*0x100000
fadds fp_1m_minus_1 // u*0x100000 + 0xFFFFF | ustep*0x100000
fxch %st(1) // ustep*0x100000 | u*0x100000 + 0xFFFFF
fistpl et_u_step(%edi) // u*0x100000 + 0xFFFFF
fistpl et_u(%edi)
// // 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;
movl et_u(%edi),%eax
movl C(r_refdef)+rd_vrect_x_adj_shift20,%edx
cmpl %edx,%eax
jl LP4
movl C(r_refdef)+rd_vrectright_adj_shift20,%edx
cmpl %edx,%eax
jng LP5
LP4:
movl %edx,et_u(%edi)
movl %edx,%eax
LP5:
// // sort the edge in normally
// u_check = edge->u;
//
// if (edge->surfs[0])
// u_check++; // sort trailers after leaders
addl %esi,%eax
// if (!newedges[v] || newedges[v]->u >= u_check)
// {
movl C(newedges)(,%ebx,4),%esi
testl %esi,%esi
jz LDoFirst
cmpl %eax,et_u(%esi)
jl LNotFirst
LDoFirst:
// edge->next = newedges[v];
// newedges[v] = edge;
movl %esi,et_next(%edi)
movl %edi,C(newedges)(,%ebx,4)
jmp LSetRemove
// }
LNotFirst:
// else
// {
// pcheck = newedges[v];
//
// while (pcheck->next && pcheck->next->u < u_check)
// pcheck = pcheck->next;
LFindInsertLoop:
movl %esi,%edx
movl et_next(%esi),%esi
testl %esi,%esi
jz LInsertFound
cmpl %eax,et_u(%esi)
jl LFindInsertLoop
LInsertFound:
// edge->next = pcheck->next;
// pcheck->next = edge;
movl %esi,et_next(%edi)
movl %edi,et_next(%edx)
// }
LSetRemove:
// edge->nextremove = removeedges[v2];
// removeedges[v2] = edge;
movl C(removeedges)(,%ecx,4),%eax
movl %edi,C(removeedges)(,%ecx,4)
movl %eax,et_nextremove(%edi)
Ldone:
movl Lstack,%esp // clear temporary variables from stack
popl %ebx // restore register variables
popl %edi
popl %esi
ret
// at least one point is clipped
Lp2:
testl %eax,%eax
jns Lp1
// else
// {
// // point 0 is clipped
// if (d1 < 0)
// {
movl Ld1,%eax
testl %eax,%eax
jns Lp3
// // both points are clipped
// // we do cache fully clipped edges
// if (!leftclipped)
movl C(r_leftclipped),%eax
movl C(r_pedge),%ecx
testl %eax,%eax
jnz Ldone
// r_pedge->framecount = r_framecount;
movl C(r_framecount),%eax
andl $(FRAMECOUNT_MASK),%eax
orl $(FULLY_CLIPPED_CACHED),%eax
movl %eax,C(cacheoffset)
// return;
jmp Ldone
// }
Lp1:
// // point 0 is unclipped
// if (d1 >= 0)
// {
// // both points are unclipped
// continue;
// // only point 1 is clipped
// f = d0 / (d0 - d1);
flds Ld0
flds Ld1
fsubr %st(1),%st(0)
// // we don't cache partially clipped edges
movl $0x7FFFFFFF,C(cacheoffset)
fdivrp %st(0),%st(1)
subl $(mv_size),%esp // allocate space for clipvert
// 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]);
flds mv_position+8(%edx)
fsubs mv_position+8(%esi)
flds mv_position+4(%edx)
fsubs mv_position+4(%esi)
flds mv_position+0(%edx)
fsubs mv_position+0(%esi) // 0 | 1 | 2
// replace pv1 with the clip point
movl %esp,%edx
movl cp_leftedge(%ebx),%eax
testb %al,%al
fmul %st(3),%st(0)
fxch %st(1) // 1 | 0 | 2
fmul %st(3),%st(0)
fxch %st(2) // 2 | 0 | 1
fmulp %st(0),%st(3) // 0 | 1 | 2
fadds mv_position+0(%esi)
fxch %st(1) // 1 | 0 | 2
fadds mv_position+4(%esi)
fxch %st(2) // 2 | 0 | 1
fadds mv_position+8(%esi)
fxch %st(1) // 0 | 2 | 1
fstps mv_position+0(%esp) // 2 | 1
fstps mv_position+8(%esp) // 1
fstps mv_position+4(%esp)
// if (clip->leftedge)
// {
jz Ltestright
// r_leftclipped = true;
// r_leftexit = clipvert;
movl $1,C(r_leftclipped)
movl mv_position+0(%esp),%eax
movl %eax,C(r_leftexit)+mv_position+0
movl mv_position+4(%esp),%eax
movl %eax,C(r_leftexit)+mv_position+4
movl mv_position+8(%esp),%eax
movl %eax,C(r_leftexit)+mv_position+8
jmp Lcontinue
// }
Ltestright:
// else if (clip->rightedge)
// {
testb %ah,%ah
jz Lcontinue
// r_rightclipped = true;
// r_rightexit = clipvert;
movl $1,C(r_rightclipped)
movl mv_position+0(%esp),%eax
movl %eax,C(r_rightexit)+mv_position+0
movl mv_position+4(%esp),%eax
movl %eax,C(r_rightexit)+mv_position+4
movl mv_position+8(%esp),%eax
movl %eax,C(r_rightexit)+mv_position+8
// }
//
// R_ClipEdge (pv0, &clipvert, clip->next);
// return;
// }
jmp Lcontinue
// }
Lp3:
// // only point 0 is clipped
// r_lastvertvalid = false;
movl $0,C(r_lastvertvalid)
// f = d0 / (d0 - d1);
flds Ld0
flds Ld1
fsubr %st(1),%st(0)
// // we don't cache partially clipped edges
movl $0x7FFFFFFF,C(cacheoffset)
fdivrp %st(0),%st(1)
subl $(mv_size),%esp // allocate space for clipvert
// 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]);
flds mv_position+8(%edx)
fsubs mv_position+8(%esi)
flds mv_position+4(%edx)
fsubs mv_position+4(%esi)
flds mv_position+0(%edx)
fsubs mv_position+0(%esi) // 0 | 1 | 2
movl cp_leftedge(%ebx),%eax
testb %al,%al
fmul %st(3),%st(0)
fxch %st(1) // 1 | 0 | 2
fmul %st(3),%st(0)
fxch %st(2) // 2 | 0 | 1
fmulp %st(0),%st(3) // 0 | 1 | 2
fadds mv_position+0(%esi)
fxch %st(1) // 1 | 0 | 2
fadds mv_position+4(%esi)
fxch %st(2) // 2 | 0 | 1
fadds mv_position+8(%esi)
fxch %st(1) // 0 | 2 | 1
fstps mv_position+0(%esp) // 2 | 1
fstps mv_position+8(%esp) // 1
fstps mv_position+4(%esp)
// replace pv0 with the clip point
movl %esp,%esi
// if (clip->leftedge)
// {
jz Ltestright2
// r_leftclipped = true;
// r_leftenter = clipvert;
movl $1,C(r_leftclipped)
movl mv_position+0(%esp),%eax
movl %eax,C(r_leftenter)+mv_position+0
movl mv_position+4(%esp),%eax
movl %eax,C(r_leftenter)+mv_position+4
movl mv_position+8(%esp),%eax
movl %eax,C(r_leftenter)+mv_position+8
jmp Lcontinue
// }
Ltestright2:
// else if (clip->rightedge)
// {
testb %ah,%ah
jz Lcontinue
// r_rightclipped = true;
// r_rightenter = clipvert;
movl $1,C(r_rightclipped)
movl mv_position+0(%esp),%eax
movl %eax,C(r_rightenter)+mv_position+0
movl mv_position+4(%esp),%eax
movl %eax,C(r_rightenter)+mv_position+4
movl mv_position+8(%esp),%eax
movl %eax,C(r_rightenter)+mv_position+8
// }
jmp Lcontinue
// %esi = vec3_t point to transform and project
// %edx preserved
LTransformAndProject:
// // transform and project
// VectorSubtract (world, modelorg, local);
flds mv_position+0(%esi)
fsubs C(modelorg)+0
flds mv_position+4(%esi)
fsubs C(modelorg)+4
flds mv_position+8(%esi)
fsubs C(modelorg)+8
fxch %st(2) // local[0] | local[1] | local[2]
// TransformVector (local, transformed);
//
// if (transformed[2] < NEAR_CLIP)
// transformed[2] = NEAR_CLIP;
//
// lzi0 = 1.0 / transformed[2];
fld %st(0) // local[0] | local[0] | local[1] | local[2]
fmuls C(vpn)+0 // zm0 | local[0] | local[1] | local[2]
fld %st(1) // local[0] | zm0 | local[0] | local[1] |
// local[2]
fmuls C(vright)+0 // xm0 | zm0 | local[0] | local[1] | local[2]
fxch %st(2) // local[0] | zm0 | xm0 | local[1] | local[2]
fmuls C(vup)+0 // ym0 | zm0 | xm0 | local[1] | local[2]
fld %st(3) // local[1] | ym0 | zm0 | xm0 | local[1] |
// local[2]
fmuls C(vpn)+4 // zm1 | ym0 | zm0 | xm0 | local[1] |
// local[2]
fld %st(4) // local[1] | zm1 | ym0 | zm0 | xm0 |
// local[1] | local[2]
fmuls C(vright)+4 // xm1 | zm1 | ym0 | zm0 | xm0 |
// local[1] | local[2]
fxch %st(5) // local[1] | zm1 | ym0 | zm0 | xm0 |
// xm1 | local[2]
fmuls C(vup)+4 // ym1 | zm1 | ym0 | zm0 | xm0 |
// xm1 | local[2]
fxch %st(1) // zm1 | ym1 | ym0 | zm0 | xm0 |
// xm1 | local[2]
faddp %st(0),%st(3) // ym1 | ym0 | zm2 | xm0 | xm1 | local[2]
fxch %st(3) // xm0 | ym0 | zm2 | ym1 | xm1 | local[2]
faddp %st(0),%st(4) // ym0 | zm2 | ym1 | xm2 | local[2]
faddp %st(0),%st(2) // zm2 | ym2 | xm2 | local[2]
fld %st(3) // local[2] | zm2 | ym2 | xm2 | local[2]
fmuls C(vpn)+8 // zm3 | zm2 | ym2 | xm2 | local[2]
fld %st(4) // local[2] | zm3 | zm2 | ym2 | xm2 | local[2]
fmuls C(vright)+8 // xm3 | zm3 | zm2 | ym2 | xm2 | local[2]
fxch %st(5) // local[2] | zm3 | zm2 | ym2 | xm2 | xm3
fmuls C(vup)+8 // ym3 | zm3 | zm2 | ym2 | xm2 | xm3
fxch %st(1) // zm3 | ym3 | zm2 | ym2 | xm2 | xm3
faddp %st(0),%st(2) // ym3 | zm4 | ym2 | xm2 | xm3
fxch %st(4) // xm3 | zm4 | ym2 | xm2 | ym3
faddp %st(0),%st(3) // zm4 | ym2 | xm4 | ym3
fxch %st(1) // ym2 | zm4 | xm4 | ym3
faddp %st(0),%st(3) // zm4 | xm4 | ym4
fcoms Lfp_near_clip
fnstsw %ax
testb $1,%ah
jz LNoClip
fstp %st(0)
flds Lfp_near_clip
LNoClip:
fdivrs float_1 // lzi0 | x | y
fxch %st(1) // x | lzi0 | y
// // FIXME: build x/yscale into transform?
// scale = xscale * lzi0;
// u0 = (xcenter + scale*transformed[0]);
flds C(xscale) // xscale | x | lzi0 | y
fmul %st(2),%st(0) // scale | x | lzi0 | y
fmulp %st(0),%st(1) // scale*x | lzi0 | y
fadds C(xcenter) // u0 | lzi0 | y
// if (u0 < r_refdef.fvrectx_adj)
// u0 = r_refdef.fvrectx_adj;
// if (u0 > r_refdef.fvrectright_adj)
// u0 = r_refdef.fvrectright_adj;
// FIXME: use integer compares of floats?
fcoms C(r_refdef)+rd_fvrectx_adj
fnstsw %ax
testb $1,%ah
jz LClampP0
fstp %st(0)
flds C(r_refdef)+rd_fvrectx_adj
LClampP0:
fcoms C(r_refdef)+rd_fvrectright_adj
fnstsw %ax
testb $0x45,%ah
jnz LClampP1
fstp %st(0)
flds C(r_refdef)+rd_fvrectright_adj
LClampP1:
fld %st(1) // lzi0 | u0 | lzi0 | y
// scale = yscale * lzi0;
// v0 = (ycenter - scale*transformed[1]);
fmuls C(yscale) // scale | u0 | lzi0 | y
fmulp %st(0),%st(3) // u0 | lzi0 | scale*y
fxch %st(2) // scale*y | lzi0 | u0
fsubrs C(ycenter) // v0 | lzi0 | u0
// if (v0 < r_refdef.fvrecty_adj)
// v0 = r_refdef.fvrecty_adj;
// if (v0 > r_refdef.fvrectbottom_adj)
// v0 = r_refdef.fvrectbottom_adj;
// FIXME: use integer compares of floats?
fcoms C(r_refdef)+rd_fvrecty_adj
fnstsw %ax
testb $1,%ah
jz LClampP2
fstp %st(0)
flds C(r_refdef)+rd_fvrecty_adj
LClampP2:
fcoms C(r_refdef)+rd_fvrectbottom_adj
fnstsw %ax
testb $0x45,%ah
jnz LClampP3
fstp %st(0)
flds C(r_refdef)+rd_fvrectbottom_adj
LClampP3:
ret
#endif // id386

729
linux/r_edgea.s Normal file
View File

@ -0,0 +1,729 @@
//
// r_edgea.s
// x86 assembly-language edge-processing code.
//
#include "qasm.h"
#if id386
.data
Ltemp: .long 0
float_1_div_0100000h: .long 0x35800000 // 1.0/(float)0x100000
float_point_999: .single 0.999
float_1_point_001: .single 1.001
.text
//--------------------------------------------------------------------
#define edgestoadd 4+8 // note odd stack offsets because of interleaving
#define edgelist 8+12 // with pushes
.globl C(R_EdgeCodeStart)
C(R_EdgeCodeStart):
.globl C(R_InsertNewEdges)
C(R_InsertNewEdges):
pushl %edi
pushl %esi // preserve register variables
movl edgestoadd(%esp),%edx
pushl %ebx
movl edgelist(%esp),%ecx
LDoNextEdge:
movl et_u(%edx),%eax
movl %edx,%edi
LContinueSearch:
movl et_u(%ecx),%ebx
movl et_next(%ecx),%esi
cmpl %ebx,%eax
jle LAddedge
movl et_u(%esi),%ebx
movl et_next(%esi),%ecx
cmpl %ebx,%eax
jle LAddedge2
movl et_u(%ecx),%ebx
movl et_next(%ecx),%esi
cmpl %ebx,%eax
jle LAddedge
movl et_u(%esi),%ebx
movl et_next(%esi),%ecx
cmpl %ebx,%eax
jg LContinueSearch
LAddedge2:
movl et_next(%edx),%edx
movl et_prev(%esi),%ebx
movl %esi,et_next(%edi)
movl %ebx,et_prev(%edi)
movl %edi,et_next(%ebx)
movl %edi,et_prev(%esi)
movl %esi,%ecx
cmpl $0,%edx
jnz LDoNextEdge
jmp LDone
.align 4
LAddedge:
movl et_next(%edx),%edx
movl et_prev(%ecx),%ebx
movl %ecx,et_next(%edi)
movl %ebx,et_prev(%edi)
movl %edi,et_next(%ebx)
movl %edi,et_prev(%ecx)
cmpl $0,%edx
jnz LDoNextEdge
LDone:
popl %ebx // restore register variables
popl %esi
popl %edi
ret
//--------------------------------------------------------------------
#define predge 4+4
.globl C(R_RemoveEdges)
C(R_RemoveEdges):
pushl %ebx
movl predge(%esp),%eax
Lre_loop:
movl et_next(%eax),%ecx
movl et_nextremove(%eax),%ebx
movl et_prev(%eax),%edx
testl %ebx,%ebx
movl %edx,et_prev(%ecx)
jz Lre_done
movl %ecx,et_next(%edx)
movl et_next(%ebx),%ecx
movl et_prev(%ebx),%edx
movl et_nextremove(%ebx),%eax
movl %edx,et_prev(%ecx)
testl %eax,%eax
movl %ecx,et_next(%edx)
jnz Lre_loop
popl %ebx
ret
Lre_done:
movl %ecx,et_next(%edx)
popl %ebx
ret
//--------------------------------------------------------------------
#define pedgelist 4+4 // note odd stack offset because of interleaving
// with pushes
.globl C(R_StepActiveU)
C(R_StepActiveU):
pushl %edi
movl pedgelist(%esp),%edx
pushl %esi // preserve register variables
pushl %ebx
movl et_prev(%edx),%esi
LNewEdge:
movl et_u(%esi),%edi
LNextEdge:
movl et_u(%edx),%eax
movl et_u_step(%edx),%ebx
addl %ebx,%eax
movl et_next(%edx),%esi
movl %eax,et_u(%edx)
cmpl %edi,%eax
jl LPushBack
movl et_u(%esi),%edi
movl et_u_step(%esi),%ebx
addl %ebx,%edi
movl et_next(%esi),%edx
movl %edi,et_u(%esi)
cmpl %eax,%edi
jl LPushBack2
movl et_u(%edx),%eax
movl et_u_step(%edx),%ebx
addl %ebx,%eax
movl et_next(%edx),%esi
movl %eax,et_u(%edx)
cmpl %edi,%eax
jl LPushBack
movl et_u(%esi),%edi
movl et_u_step(%esi),%ebx
addl %ebx,%edi
movl et_next(%esi),%edx
movl %edi,et_u(%esi)
cmpl %eax,%edi
jnl LNextEdge
LPushBack2:
movl %edx,%ebx
movl %edi,%eax
movl %esi,%edx
movl %ebx,%esi
LPushBack:
// push it back to keep it sorted
movl et_prev(%edx),%ecx
movl et_next(%edx),%ebx
// done if the -1 in edge_aftertail triggered this
cmpl $(C(edge_aftertail)),%edx
jz LUDone
// pull the edge out of the edge list
movl et_prev(%ecx),%edi
movl %ecx,et_prev(%esi)
movl %ebx,et_next(%ecx)
// find out where the edge goes in the edge list
LPushBackLoop:
movl et_prev(%edi),%ecx
movl et_u(%edi),%ebx
cmpl %ebx,%eax
jnl LPushBackFound
movl et_prev(%ecx),%edi
movl et_u(%ecx),%ebx
cmpl %ebx,%eax
jl LPushBackLoop
movl %ecx,%edi
// put the edge back into the edge list
LPushBackFound:
movl et_next(%edi),%ebx
movl %edi,et_prev(%edx)
movl %ebx,et_next(%edx)
movl %edx,et_next(%edi)
movl %edx,et_prev(%ebx)
movl %esi,%edx
movl et_prev(%esi),%esi
cmpl $(C(edge_tail)),%edx
jnz LNewEdge
LUDone:
popl %ebx // restore register variables
popl %esi
popl %edi
ret
//--------------------------------------------------------------------
#define surf 4 // note this is loaded before any pushes
.align 4
TrailingEdge:
movl st_spanstate(%esi),%eax // check for edge inversion
decl %eax
jnz LInverted
movl %eax,st_spanstate(%esi)
movl st_insubmodel(%esi),%ecx
movl 0x12345678,%edx // surfaces[1].st_next
LPatch0:
movl C(r_bmodelactive),%eax
subl %ecx,%eax
cmpl %esi,%edx
movl %eax,C(r_bmodelactive)
jnz LNoEmit // surface isn't on top, just remove
// emit a span (current top going away)
movl et_u(%ebx),%eax
shrl $20,%eax // iu = integral pixel u
movl st_last_u(%esi),%edx
movl st_next(%esi),%ecx
cmpl %edx,%eax
jle LNoEmit2 // iu <= surf->last_u, so nothing to emit
movl %eax,st_last_u(%ecx) // surf->next->last_u = iu;
subl %edx,%eax
movl %edx,espan_t_u(%ebp) // span->u = surf->last_u;
movl %eax,espan_t_count(%ebp) // span->count = iu - span->u;
movl C(current_iv),%eax
movl %eax,espan_t_v(%ebp) // span->v = current_iv;
movl st_spans(%esi),%eax
movl %eax,espan_t_pnext(%ebp) // span->pnext = surf->spans;
movl %ebp,st_spans(%esi) // surf->spans = span;
addl $(espan_t_size),%ebp
movl st_next(%esi),%edx // remove the surface from the surface
movl st_prev(%esi),%esi // stack
movl %edx,st_next(%esi)
movl %esi,st_prev(%edx)
ret
LNoEmit2:
movl %eax,st_last_u(%ecx) // surf->next->last_u = iu;
movl st_next(%esi),%edx // remove the surface from the surface
movl st_prev(%esi),%esi // stack
movl %edx,st_next(%esi)
movl %esi,st_prev(%edx)
ret
LNoEmit:
movl st_next(%esi),%edx // remove the surface from the surface
movl st_prev(%esi),%esi // stack
movl %edx,st_next(%esi)
movl %esi,st_prev(%edx)
ret
LInverted:
movl %eax,st_spanstate(%esi)
ret
//--------------------------------------------------------------------
// trailing edge only
Lgs_trailing:
pushl $Lgs_nextedge
jmp TrailingEdge
.globl C(R_GenerateSpans)
C(R_GenerateSpans):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
// clear active surfaces to just the background surface
movl C(surfaces),%eax
movl C(edge_head_u_shift20),%edx
addl $(st_size),%eax
// %ebp = span_p throughout
movl C(span_p),%ebp
movl $0,C(r_bmodelactive)
movl %eax,st_next(%eax)
movl %eax,st_prev(%eax)
movl %edx,st_last_u(%eax)
movl C(edge_head)+et_next,%ebx // edge=edge_head.next
// generate spans
cmpl $(C(edge_tail)),%ebx // done if empty list
jz Lgs_lastspan
Lgs_edgeloop:
movl et_surfs(%ebx),%edi
movl C(surfaces),%eax
movl %edi,%esi
andl $0xFFFF0000,%edi
andl $0xFFFF,%esi
jz Lgs_leading // not a trailing edge
// it has a left surface, so a surface is going away for this span
shll $(SURF_T_SHIFT),%esi
addl %eax,%esi
testl %edi,%edi
jz Lgs_trailing
// both leading and trailing
call TrailingEdge
movl C(surfaces),%eax
// ---------------------------------------------------------------
// handle a leading edge
// ---------------------------------------------------------------
Lgs_leading:
shrl $16-SURF_T_SHIFT,%edi
movl C(surfaces),%eax
addl %eax,%edi
movl 0x12345678,%esi // surf2 = surfaces[1].next;
LPatch2:
movl st_spanstate(%edi),%edx
movl st_insubmodel(%edi),%eax
testl %eax,%eax
jnz Lbmodel_leading
// handle a leading non-bmodel edge
// 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)
testl %edx,%edx
jnz Lxl_done
// if (surf->key < surf2->key)
// goto newtop;
incl %edx
movl st_key(%edi),%eax
movl %edx,st_spanstate(%edi)
movl st_key(%esi),%ecx
cmpl %ecx,%eax
jl Lnewtop
// main sorting loop to search through surface stack until insertion point
// found. Always terminates because background surface is sentinel
// do
// {
// surf2 = surf2->next;
// } while (surf->key >= surf2->key);
Lsortloopnb:
movl st_next(%esi),%esi
movl st_key(%esi),%ecx
cmpl %ecx,%eax
jge Lsortloopnb
jmp LInsertAndExit
// handle a leading bmodel edge
.align 4
Lbmodel_leading:
// 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)
testl %edx,%edx
jnz Lxl_done
movl C(r_bmodelactive),%ecx
incl %edx
incl %ecx
movl %edx,st_spanstate(%edi)
movl %ecx,C(r_bmodelactive)
// if (surf->key < surf2->key)
// goto newtop;
movl st_key(%edi),%eax
movl st_key(%esi),%ecx
cmpl %ecx,%eax
jl Lnewtop
// if ((surf->key == surf2->key) && surf->insubmodel)
// {
jz Lzcheck_for_newtop
// main sorting loop to search through surface stack until insertion point
// found. Always terminates because background surface is sentinel
// do
// {
// surf2 = surf2->next;
// } while (surf->key > surf2->key);
Lsortloop:
movl st_next(%esi),%esi
movl st_key(%esi),%ecx
cmpl %ecx,%eax
jg Lsortloop
jne LInsertAndExit
// Do 1/z sorting to see if we've arrived in the right position
movl et_u(%ebx),%eax
subl $0xFFFFF,%eax
movl %eax,Ltemp
fildl Ltemp
fmuls float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) *
// (1.0 / 0x100000);
fld %st(0) // fu | fu
fmuls st_d_zistepu(%edi) // fu*surf->d_zistepu | fu
flds C(fv) // fv | fu*surf->d_zistepu | fu
fmuls st_d_zistepv(%edi) // fv*surf->d_zistepv | fu*surf->d_zistepu | fu
fxch %st(1) // fu*surf->d_zistepu | fv*surf->d_zistepv | fu
fadds st_d_ziorigin(%edi) // fu*surf->d_zistepu + surf->d_ziorigin |
// fv*surf->d_zistepv | fu
flds st_d_zistepu(%esi) // surf2->d_zistepu |
// fu*surf->d_zistepu + surf->d_ziorigin |
// fv*surf->d_zistepv | fu
fmul %st(3),%st(0) // fu*surf2->d_zistepu |
// fu*surf->d_zistepu + surf->d_ziorigin |
// fv*surf->d_zistepv | fu
fxch %st(1) // fu*surf->d_zistepu + surf->d_ziorigin |
// fu*surf2->d_zistepu |
// fv*surf->d_zistepv | fu
faddp %st(0),%st(2) // fu*surf2->d_zistepu | newzi | fu
flds C(fv) // fv | fu*surf2->d_zistepu | newzi | fu
fmuls st_d_zistepv(%esi) // fv*surf2->d_zistepv |
// fu*surf2->d_zistepu | newzi | fu
fld %st(2) // newzi | fv*surf2->d_zistepv |
// fu*surf2->d_zistepu | newzi | fu
fmuls float_point_999 // newzibottom | fv*surf2->d_zistepv |
// fu*surf2->d_zistepu | newzi | fu
fxch %st(2) // fu*surf2->d_zistepu | fv*surf2->d_zistepv |
// newzibottom | newzi | fu
fadds st_d_ziorigin(%esi) // fu*surf2->d_zistepu + surf2->d_ziorigin |
// fv*surf2->d_zistepv | newzibottom | newzi |
// fu
faddp %st(0),%st(1) // testzi | newzibottom | newzi | fu
fxch %st(1) // newzibottom | testzi | newzi | fu
// if (newzibottom >= testzi)
// goto Lgotposition;
fcomp %st(1) // testzi | newzi | fu
fxch %st(1) // newzi | testzi | fu
fmuls float_1_point_001 // newzitop | testzi | fu
fxch %st(1) // testzi | newzitop | fu
fnstsw %ax
testb $0x01,%ah
jz Lgotposition_fpop3
// if (newzitop >= testzi)
// {
fcomp %st(1) // newzitop | fu
fnstsw %ax
testb $0x45,%ah
jz Lsortloop_fpop2
// if (surf->d_zistepu >= surf2->d_zistepu)
// goto newtop;
flds st_d_zistepu(%edi) // surf->d_zistepu | newzitop| fu
fcomps st_d_zistepu(%esi) // newzitop | fu
fnstsw %ax
testb $0x01,%ah
jz Lgotposition_fpop2
fstp %st(0) // clear the FPstack
fstp %st(0)
movl st_key(%edi),%eax
jmp Lsortloop
Lgotposition_fpop3:
fstp %st(0)
Lgotposition_fpop2:
fstp %st(0)
fstp %st(0)
jmp LInsertAndExit
// emit a span (obscures current top)
Lnewtop_fpop3:
fstp %st(0)
Lnewtop_fpop2:
fstp %st(0)
fstp %st(0)
movl st_key(%edi),%eax // reload the sorting key
Lnewtop:
movl et_u(%ebx),%eax
movl st_last_u(%esi),%edx
shrl $20,%eax // iu = integral pixel u
movl %eax,st_last_u(%edi) // surf->last_u = iu;
cmpl %edx,%eax
jle LInsertAndExit // iu <= surf->last_u, so nothing to emit
subl %edx,%eax
movl %edx,espan_t_u(%ebp) // span->u = surf->last_u;
movl %eax,espan_t_count(%ebp) // span->count = iu - span->u;
movl C(current_iv),%eax
movl %eax,espan_t_v(%ebp) // span->v = current_iv;
movl st_spans(%esi),%eax
movl %eax,espan_t_pnext(%ebp) // span->pnext = surf->spans;
movl %ebp,st_spans(%esi) // surf->spans = span;
addl $(espan_t_size),%ebp
LInsertAndExit:
// insert before surf2
movl %esi,st_next(%edi) // surf->next = surf2;
movl st_prev(%esi),%eax
movl %eax,st_prev(%edi) // surf->prev = surf2->prev;
movl %edi,st_prev(%esi) // surf2->prev = surf;
movl %edi,st_next(%eax) // surf2->prev->next = surf;
// ---------------------------------------------------------------
// leading edge done
// ---------------------------------------------------------------
// ---------------------------------------------------------------
// see if there are any more edges
// ---------------------------------------------------------------
Lgs_nextedge:
movl et_next(%ebx),%ebx
cmpl $(C(edge_tail)),%ebx
jnz Lgs_edgeloop
// clean up at the right edge
Lgs_lastspan:
// 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
movl 0x12345678,%esi // surfaces[1].st_next
LPatch3:
movl C(edge_tail_u_shift20),%eax
xorl %ecx,%ecx
movl st_last_u(%esi),%edx
subl %edx,%eax
jle Lgs_resetspanstate
movl %edx,espan_t_u(%ebp)
movl %eax,espan_t_count(%ebp)
movl C(current_iv),%eax
movl %eax,espan_t_v(%ebp)
movl st_spans(%esi),%eax
movl %eax,espan_t_pnext(%ebp)
movl %ebp,st_spans(%esi)
addl $(espan_t_size),%ebp
// reset spanstate for all surfaces in the surface stack
Lgs_resetspanstate:
movl %ecx,st_spanstate(%esi)
movl st_next(%esi),%esi
cmpl $0x12345678,%esi // &surfaces[1]
LPatch4:
jnz Lgs_resetspanstate
// store the final span_p
movl %ebp,C(span_p)
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
// ---------------------------------------------------------------
// 1/z sorting for bmodels in the same leaf
// ---------------------------------------------------------------
.align 4
Lxl_done:
incl %edx
movl %edx,st_spanstate(%edi)
jmp Lgs_nextedge
.align 4
Lzcheck_for_newtop:
movl et_u(%ebx),%eax
subl $0xFFFFF,%eax
movl %eax,Ltemp
fildl Ltemp
fmuls float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) *
// (1.0 / 0x100000);
fld %st(0) // fu | fu
fmuls st_d_zistepu(%edi) // fu*surf->d_zistepu | fu
flds C(fv) // fv | fu*surf->d_zistepu | fu
fmuls st_d_zistepv(%edi) // fv*surf->d_zistepv | fu*surf->d_zistepu | fu
fxch %st(1) // fu*surf->d_zistepu | fv*surf->d_zistepv | fu
fadds st_d_ziorigin(%edi) // fu*surf->d_zistepu + surf->d_ziorigin |
// fv*surf->d_zistepv | fu
flds st_d_zistepu(%esi) // surf2->d_zistepu |
// fu*surf->d_zistepu + surf->d_ziorigin |
// fv*surf->d_zistepv | fu
fmul %st(3),%st(0) // fu*surf2->d_zistepu |
// fu*surf->d_zistepu + surf->d_ziorigin |
// fv*surf->d_zistepv | fu
fxch %st(1) // fu*surf->d_zistepu + surf->d_ziorigin |
// fu*surf2->d_zistepu |
// fv*surf->d_zistepv | fu
faddp %st(0),%st(2) // fu*surf2->d_zistepu | newzi | fu
flds C(fv) // fv | fu*surf2->d_zistepu | newzi | fu
fmuls st_d_zistepv(%esi) // fv*surf2->d_zistepv |
// fu*surf2->d_zistepu | newzi | fu
fld %st(2) // newzi | fv*surf2->d_zistepv |
// fu*surf2->d_zistepu | newzi | fu
fmuls float_point_999 // newzibottom | fv*surf2->d_zistepv |
// fu*surf2->d_zistepu | newzi | fu
fxch %st(2) // fu*surf2->d_zistepu | fv*surf2->d_zistepv |
// newzibottom | newzi | fu
fadds st_d_ziorigin(%esi) // fu*surf2->d_zistepu + surf2->d_ziorigin |
// fv*surf2->d_zistepv | newzibottom | newzi |
// fu
faddp %st(0),%st(1) // testzi | newzibottom | newzi | fu
fxch %st(1) // newzibottom | testzi | newzi | fu
// if (newzibottom >= testzi)
// goto newtop;
fcomp %st(1) // testzi | newzi | fu
fxch %st(1) // newzi | testzi | fu
fmuls float_1_point_001 // newzitop | testzi | fu
fxch %st(1) // testzi | newzitop | fu
fnstsw %ax
testb $0x01,%ah
jz Lnewtop_fpop3
// if (newzitop >= testzi)
// {
fcomp %st(1) // newzitop | fu
fnstsw %ax
testb $0x45,%ah
jz Lsortloop_fpop2
// if (surf->d_zistepu >= surf2->d_zistepu)
// goto newtop;
flds st_d_zistepu(%edi) // surf->d_zistepu | newzitop | fu
fcomps st_d_zistepu(%esi) // newzitop | fu
fnstsw %ax
testb $0x01,%ah
jz Lnewtop_fpop2
Lsortloop_fpop2:
fstp %st(0) // clear the FP stack
fstp %st(0)
movl st_key(%edi),%eax
jmp Lsortloop
.globl C(R_EdgeCodeEnd)
C(R_EdgeCodeEnd):
//----------------------------------------------------------------------
// Surface array address code patching routine
//----------------------------------------------------------------------
.align 4
.globl C(R_SurfacePatch)
C(R_SurfacePatch):
movl C(surfaces),%eax
addl $(st_size),%eax
movl %eax,LPatch4-4
addl $(st_next),%eax
movl %eax,LPatch0-4
movl %eax,LPatch2-4
movl %eax,LPatch3-4
ret
#endif // id386

68
linux/r_scana.s Normal file
View File

@ -0,0 +1,68 @@
//
// d_scana.s
// x86 assembly-language turbulent texture mapping code
//
#include "qasm.h"
#include "d_ifacea.h"
#if id386
.data
.text
//----------------------------------------------------------------------
// turbulent texture mapping code
//----------------------------------------------------------------------
.align 4
.globl C(D_DrawTurbulent8Span)
C(D_DrawTurbulent8Span):
pushl %ebp // preserve caller's stack frame pointer
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
movl C(r_turb_s),%esi
movl C(r_turb_t),%ecx
movl C(r_turb_pdest),%edi
movl C(r_turb_spancount),%ebx
Llp:
movl %ecx,%eax
movl %esi,%edx
sarl $16,%eax
movl C(r_turb_turb),%ebp
sarl $16,%edx
andl $(CYCLE-1),%eax
andl $(CYCLE-1),%edx
movl (%ebp,%eax,4),%eax
movl (%ebp,%edx,4),%edx
addl %esi,%eax
sarl $16,%eax
addl %ecx,%edx
sarl $16,%edx
andl $(TURB_TEX_SIZE-1),%eax
andl $(TURB_TEX_SIZE-1),%edx
shll $6,%edx
movl C(r_turb_pbase),%ebp
addl %eax,%edx
incl %edi
addl C(r_turb_sstep),%esi
addl C(r_turb_tstep),%ecx
movb (%ebp,%edx,1),%dl
decl %ebx
movb %dl,-1(%edi)
jnz Llp
movl %edi,C(r_turb_pdest)
popl %ebx // restore register variables
popl %edi
popl %esi
popl %ebp // restore caller's stack frame pointer
ret
#endif // id386

879
linux/r_spr8.s Normal file
View File

@ -0,0 +1,879 @@
//
// d_spr8.s
// x86 assembly-language horizontal 8-bpp transparent span-drawing code.
//
#include "qasm.h"
#if id386
//----------------------------------------------------------------------
// 8-bpp horizontal span drawing code for polygons, with transparency.
//----------------------------------------------------------------------
.text
// out-of-line, rarely-needed clamping code
LClampHigh0:
movl C(bbextents),%esi
jmp LClampReentry0
LClampHighOrLow0:
jg LClampHigh0
xorl %esi,%esi
jmp LClampReentry0
LClampHigh1:
movl C(bbextentt),%edx
jmp LClampReentry1
LClampHighOrLow1:
jg LClampHigh1
xorl %edx,%edx
jmp LClampReentry1
LClampLow2:
movl $2048,%ebp
jmp LClampReentry2
LClampHigh2:
movl C(bbextents),%ebp
jmp LClampReentry2
LClampLow3:
movl $2048,%ecx
jmp LClampReentry3
LClampHigh3:
movl C(bbextentt),%ecx
jmp LClampReentry3
LClampLow4:
movl $2048,%eax
jmp LClampReentry4
LClampHigh4:
movl C(bbextents),%eax
jmp LClampReentry4
LClampLow5:
movl $2048,%ebx
jmp LClampReentry5
LClampHigh5:
movl C(bbextentt),%ebx
jmp LClampReentry5
#define pspans 4+16
.align 4
.globl C(D_SpriteDrawSpans)
C(D_SpriteDrawSpans):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
//
// set up scaled-by-8 steps, for 8-long segments; also set up cacheblock
// and span list pointers, and 1/z step in 0.32 fixed-point
//
// FIXME: any overlap from rearranging?
flds C(d_sdivzstepu)
fmuls fp_8
movl C(cacheblock),%edx
flds C(d_tdivzstepu)
fmuls fp_8
movl pspans(%esp),%ebx // point to the first span descriptor
flds C(d_zistepu)
fmuls fp_8
movl %edx,pbase // pbase = cacheblock
flds C(d_zistepu)
fmuls fp_64kx64k
fxch %st(3)
fstps sdivz8stepu
fstps zi8stepu
fstps tdivz8stepu
fistpl izistep
movl izistep,%eax
rorl $16,%eax // put upper 16 bits in low word
movl sspan_t_count(%ebx),%ecx
movl %eax,izistep
cmpl $0,%ecx
jle LNextSpan
LSpanLoop:
//
// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
// initial s and t values
//
// FIXME: pipeline FILD?
fildl sspan_t_v(%ebx)
fildl sspan_t_u(%ebx)
fld %st(1) // dv | du | dv
fmuls C(d_sdivzstepv) // dv*d_sdivzstepv | du | dv
fld %st(1) // du | dv*d_sdivzstepv | du | dv
fmuls C(d_sdivzstepu) // du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
fld %st(2) // du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
fmuls C(d_tdivzstepu) // du*d_tdivzstepu | du*d_sdivzstepu |
// dv*d_sdivzstepv | du | dv
fxch %st(1) // du*d_sdivzstepu | du*d_tdivzstepu |
// dv*d_sdivzstepv | du | dv
faddp %st(0),%st(2) // du*d_tdivzstepu |
// du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fld %st(3) // dv | du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fmuls C(d_tdivzstepv) // dv*d_tdivzstepv |
// du*d_sdivzstepu + dv*d_sdivzstepv |
// du*d_tdivzstepu | du | dv
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
// dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
fadds C(d_sdivzorigin) // sdivz = d_sdivzorigin + dv*d_sdivzstepv +
// du*d_sdivzstepu; stays in %st(2) at end
fxch %st(4) // dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
// s/z
fmuls C(d_zistepv) // dv*d_zistepv | dv*d_tdivzstepv |
// du*d_tdivzstepu | du | s/z
fxch %st(1) // dv*d_tdivzstepv | dv*d_zistepv |
// du*d_tdivzstepu | du | s/z
faddp %st(0),%st(2) // dv*d_zistepv |
// dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
fxch %st(2) // du | dv*d_tdivzstepv + du*d_tdivzstepu |
// dv*d_zistepv | s/z
fmuls C(d_zistepu) // du*d_zistepu |
// dv*d_tdivzstepv + du*d_tdivzstepu |
// dv*d_zistepv | s/z
fxch %st(1) // dv*d_tdivzstepv + du*d_tdivzstepu |
// du*d_zistepu | dv*d_zistepv | s/z
fadds C(d_tdivzorigin) // tdivz = d_tdivzorigin + dv*d_tdivzstepv +
// du*d_tdivzstepu; stays in %st(1) at end
fxch %st(2) // dv*d_zistepv | du*d_zistepu | t/z | s/z
faddp %st(0),%st(1) // dv*d_zistepv + du*d_zistepu | t/z | s/z
flds fp_64k // fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
fxch %st(1) // dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
fadds C(d_ziorigin) // zi = d_ziorigin + dv*d_zistepv +
// du*d_zistepu; stays in %st(0) at end
// 1/z | fp_64k | t/z | s/z
fld %st(0) // FIXME: get rid of stall on FMUL?
fmuls fp_64kx64k
fxch %st(1)
//
// calculate and clamp s & t
//
fdivr %st(0),%st(2) // 1/z | z*64k | t/z | s/z
fxch %st(1)
fistpl izi // 0.32 fixed-point 1/z
movl izi,%ebp
//
// set pz to point to the first z-buffer pixel in the span
//
rorl $16,%ebp // put upper 16 bits in low word
movl sspan_t_v(%ebx),%eax
movl %ebp,izi
movl sspan_t_u(%ebx),%ebp
imull C(d_zrowbytes)
shll $1,%ebp // a word per pixel
addl C(d_pzbuffer),%eax
addl %ebp,%eax
movl %eax,pz
//
// point %edi to the first pixel in the span
//
movl C(d_viewbuffer),%ebp
movl sspan_t_v(%ebx),%eax
pushl %ebx // preserve spans pointer
movl C(tadjust),%edx
movl C(sadjust),%esi
movl C(d_scantable)(,%eax,4),%edi // v * screenwidth
addl %ebp,%edi
movl sspan_t_u(%ebx),%ebp
addl %ebp,%edi // pdest = &pdestspan[scans->u];
//
// now start the FDIV for the end of the span
//
cmpl $8,%ecx
ja LSetupNotLast1
decl %ecx
jz LCleanup1 // if only one pixel, no need to start an FDIV
movl %ecx,spancountminus1
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
fildl spancountminus1
flds C(d_tdivzstepu) // _d_tdivzstepu | spancountminus1
flds C(d_zistepu) // _d_zistepu | _d_tdivzstepu | spancountminus1
fmul %st(2),%st(0) // _d_zistepu*scm1 | _d_tdivzstepu | scm1
fxch %st(1) // _d_tdivzstepu | _d_zistepu*scm1 | scm1
fmul %st(2),%st(0) // _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
fxch %st(2) // scm1 | _d_zistepu*scm1 | _d_tdivzstepu*scm1
fmuls C(d_sdivzstepu) // _d_sdivzstepu*scm1 | _d_zistepu*scm1 |
// _d_tdivzstepu*scm1
fxch %st(1) // _d_zistepu*scm1 | _d_sdivzstepu*scm1 |
// _d_tdivzstepu*scm1
faddp %st(0),%st(3) // _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
fxch %st(1) // _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
faddp %st(0),%st(3) // _d_sdivzstepu*scm1
faddp %st(0),%st(3)
flds fp_64k
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
// overlap
jmp LFDIVInFlight1
LCleanup1:
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
jmp LFDIVInFlight1
.align 4
LSetupNotLast1:
// finish up the s and t calcs
fxch %st(1) // z*64k | 1/z | t/z | s/z
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
fxch %st(1) // s | t | 1/z | t/z | s/z
fistpl s // 1/z | t | t/z | s/z
fistpl t // 1/z | t/z | s/z
fadds zi8stepu
fxch %st(2)
fadds sdivz8stepu
fxch %st(2)
flds tdivz8stepu
faddp %st(0),%st(2)
flds fp_64k
fdiv %st(1),%st(0) // z = 1/1/z
// this is what we've gone to all this trouble to
// overlap
LFDIVInFlight1:
addl s,%esi
addl t,%edx
movl C(bbextents),%ebx
movl C(bbextentt),%ebp
cmpl %ebx,%esi
ja LClampHighOrLow0
LClampReentry0:
movl %esi,s
movl pbase,%ebx
shll $16,%esi
cmpl %ebp,%edx
movl %esi,sfracf
ja LClampHighOrLow1
LClampReentry1:
movl %edx,t
movl s,%esi // sfrac = scans->sfrac;
shll $16,%edx
movl t,%eax // tfrac = scans->tfrac;
sarl $16,%esi
movl %edx,tfracf
//
// calculate the texture starting address
//
sarl $16,%eax
addl %ebx,%esi
imull C(cachewidth),%eax // (tfrac >> 16) * cachewidth
addl %eax,%esi // psource = pbase + (sfrac >> 16) +
// ((tfrac >> 16) * cachewidth);
//
// determine whether last span or not
//
cmpl $8,%ecx
jna LLastSegment
//
// not the last segment; do full 8-wide segment
//
LNotLastSegment:
//
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
// get there
//
// pick up after the FDIV that was left in flight previously
fld %st(0) // duplicate it
fmul %st(4),%st(0) // s = s/z * z
fxch %st(1)
fmul %st(3),%st(0) // t = t/z * z
fxch %st(1)
fistpl snext
fistpl tnext
movl snext,%eax
movl tnext,%edx
subl $8,%ecx // count off this segments' pixels
movl C(sadjust),%ebp
pushl %ecx // remember count of remaining pixels
movl C(tadjust),%ecx
addl %eax,%ebp
addl %edx,%ecx
movl C(bbextents),%eax
movl C(bbextentt),%edx
cmpl $2048,%ebp
jl LClampLow2
cmpl %eax,%ebp
ja LClampHigh2
LClampReentry2:
cmpl $2048,%ecx
jl LClampLow3
cmpl %edx,%ecx
ja LClampHigh3
LClampReentry3:
movl %ebp,snext
movl %ecx,tnext
subl s,%ebp
subl t,%ecx
//
// set up advancetable
//
movl %ecx,%eax
movl %ebp,%edx
sarl $19,%edx // sstep >>= 16;
movl C(cachewidth),%ebx
sarl $19,%eax // tstep >>= 16;
jz LIsZero
imull %ebx,%eax // (tstep >> 16) * cachewidth;
LIsZero:
addl %edx,%eax // add in sstep
// (tstep >> 16) * cachewidth + (sstep >> 16);
movl tfracf,%edx
movl %eax,advancetable+4 // advance base in t
addl %ebx,%eax // ((tstep >> 16) + 1) * cachewidth +
// (sstep >> 16);
shll $13,%ebp // left-justify sstep fractional part
movl %ebp,sstep
movl sfracf,%ebx
shll $13,%ecx // left-justify tstep fractional part
movl %eax,advancetable // advance extra in t
movl %ecx,tstep
movl pz,%ecx
movl izi,%ebp
cmpw (%ecx),%bp
jl Lp1
movb (%esi),%al // get first source texel
cmpb $(TRANSPARENT_COLOR),%al
jz Lp1
movw %bp,(%ecx)
movb %al,(%edi) // store first dest pixel
Lp1:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx // advance tfrac fractional part by tstep frac
sbbl %eax,%eax // turn tstep carry into -1 (0 if none)
addl sstep,%ebx // advance sfrac fractional part by sstep frac
adcl advancetable+4(,%eax,4),%esi // point to next source texel
cmpw 2(%ecx),%bp
jl Lp2
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp2
movw %bp,2(%ecx)
movb %al,1(%edi)
Lp2:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
cmpw 4(%ecx),%bp
jl Lp3
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp3
movw %bp,4(%ecx)
movb %al,2(%edi)
Lp3:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
cmpw 6(%ecx),%bp
jl Lp4
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp4
movw %bp,6(%ecx)
movb %al,3(%edi)
Lp4:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
cmpw 8(%ecx),%bp
jl Lp5
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp5
movw %bp,8(%ecx)
movb %al,4(%edi)
Lp5:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
//
// start FDIV for end of next segment in flight, so it can overlap
//
popl %eax
cmpl $8,%eax // more than one segment after this?
ja LSetupNotLast2 // yes
decl %eax
jz LFDIVInFlight2 // if only one pixel, no need to start an FDIV
movl %eax,spancountminus1
fildl spancountminus1
flds C(d_zistepu) // _d_zistepu | spancountminus1
fmul %st(1),%st(0) // _d_zistepu*scm1 | scm1
flds C(d_tdivzstepu) // _d_tdivzstepu | _d_zistepu*scm1 | scm1
fmul %st(2),%st(0) // _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
fxch %st(1) // _d_zistepu*scm1 | _d_tdivzstepu*scm1 | scm1
faddp %st(0),%st(3) // _d_tdivzstepu*scm1 | scm1
fxch %st(1) // scm1 | _d_tdivzstepu*scm1
fmuls C(d_sdivzstepu) // _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
fxch %st(1) // _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
faddp %st(0),%st(3) // _d_sdivzstepu*scm1
flds fp_64k // 64k | _d_sdivzstepu*scm1
fxch %st(1) // _d_sdivzstepu*scm1 | 64k
faddp %st(0),%st(4) // 64k
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
// overlap
jmp LFDIVInFlight2
.align 4
LSetupNotLast2:
fadds zi8stepu
fxch %st(2)
fadds sdivz8stepu
fxch %st(2)
flds tdivz8stepu
faddp %st(0),%st(2)
flds fp_64k
fdiv %st(1),%st(0) // z = 1/1/z
// this is what we've gone to all this trouble to
// overlap
LFDIVInFlight2:
pushl %eax
cmpw 10(%ecx),%bp
jl Lp6
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp6
movw %bp,10(%ecx)
movb %al,5(%edi)
Lp6:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
cmpw 12(%ecx),%bp
jl Lp7
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp7
movw %bp,12(%ecx)
movb %al,6(%edi)
Lp7:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
cmpw 14(%ecx),%bp
jl Lp8
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp8
movw %bp,14(%ecx)
movb %al,7(%edi)
Lp8:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
addl $8,%edi
addl $16,%ecx
movl %edx,tfracf
movl snext,%edx
movl %ebx,sfracf
movl tnext,%ebx
movl %edx,s
movl %ebx,t
movl %ecx,pz
movl %ebp,izi
popl %ecx // retrieve count
//
// determine whether last span or not
//
cmpl $8,%ecx // are there multiple segments remaining?
ja LNotLastSegment // yes
//
// last segment of scan
//
LLastSegment:
//
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
// get there. The number of pixels left is variable, and we want to land on the
// last pixel, not step one past it, so we can't run into arithmetic problems
//
testl %ecx,%ecx
jz LNoSteps // just draw the last pixel and we're done
// pick up after the FDIV that was left in flight previously
fld %st(0) // duplicate it
fmul %st(4),%st(0) // s = s/z * z
fxch %st(1)
fmul %st(3),%st(0) // t = t/z * z
fxch %st(1)
fistpl snext
fistpl tnext
movl C(tadjust),%ebx
movl C(sadjust),%eax
addl snext,%eax
addl tnext,%ebx
movl C(bbextents),%ebp
movl C(bbextentt),%edx
cmpl $2048,%eax
jl LClampLow4
cmpl %ebp,%eax
ja LClampHigh4
LClampReentry4:
movl %eax,snext
cmpl $2048,%ebx
jl LClampLow5
cmpl %edx,%ebx
ja LClampHigh5
LClampReentry5:
cmpl $1,%ecx // don't bother
je LOnlyOneStep // if two pixels in segment, there's only one step,
// of the segment length
subl s,%eax
subl t,%ebx
addl %eax,%eax // convert to 15.17 format so multiply by 1.31
addl %ebx,%ebx // reciprocal yields 16.48
imull reciprocal_table-8(,%ecx,4) // sstep = (snext - s) / (spancount-1)
movl %edx,%ebp
movl %ebx,%eax
imull reciprocal_table-8(,%ecx,4) // tstep = (tnext - t) / (spancount-1)
LSetEntryvec:
//
// set up advancetable
//
movl spr8entryvec_table(,%ecx,4),%ebx
movl %edx,%eax
pushl %ebx // entry point into code for RET later
movl %ebp,%ecx
sarl $16,%ecx // sstep >>= 16;
movl C(cachewidth),%ebx
sarl $16,%edx // tstep >>= 16;
jz LIsZeroLast
imull %ebx,%edx // (tstep >> 16) * cachewidth;
LIsZeroLast:
addl %ecx,%edx // add in sstep
// (tstep >> 16) * cachewidth + (sstep >> 16);
movl tfracf,%ecx
movl %edx,advancetable+4 // advance base in t
addl %ebx,%edx // ((tstep >> 16) + 1) * cachewidth +
// (sstep >> 16);
shll $16,%ebp // left-justify sstep fractional part
movl sfracf,%ebx
shll $16,%eax // left-justify tstep fractional part
movl %edx,advancetable // advance extra in t
movl %eax,tstep
movl %ebp,sstep
movl %ecx,%edx
movl pz,%ecx
movl izi,%ebp
ret // jump to the number-of-pixels handler
//----------------------------------------
LNoSteps:
movl pz,%ecx
subl $7,%edi // adjust for hardwired offset
subl $14,%ecx
jmp LEndSpan
LOnlyOneStep:
subl s,%eax
subl t,%ebx
movl %eax,%ebp
movl %ebx,%edx
jmp LSetEntryvec
//----------------------------------------
.globl Spr8Entry2_8
Spr8Entry2_8:
subl $6,%edi // adjust for hardwired offsets
subl $12,%ecx
movb (%esi),%al
jmp LLEntry2_8
//----------------------------------------
.globl Spr8Entry3_8
Spr8Entry3_8:
subl $5,%edi // adjust for hardwired offsets
subl $10,%ecx
jmp LLEntry3_8
//----------------------------------------
.globl Spr8Entry4_8
Spr8Entry4_8:
subl $4,%edi // adjust for hardwired offsets
subl $8,%ecx
jmp LLEntry4_8
//----------------------------------------
.globl Spr8Entry5_8
Spr8Entry5_8:
subl $3,%edi // adjust for hardwired offsets
subl $6,%ecx
jmp LLEntry5_8
//----------------------------------------
.globl Spr8Entry6_8
Spr8Entry6_8:
subl $2,%edi // adjust for hardwired offsets
subl $4,%ecx
jmp LLEntry6_8
//----------------------------------------
.globl Spr8Entry7_8
Spr8Entry7_8:
decl %edi // adjust for hardwired offsets
subl $2,%ecx
jmp LLEntry7_8
//----------------------------------------
.globl Spr8Entry8_8
Spr8Entry8_8:
cmpw (%ecx),%bp
jl Lp9
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp9
movw %bp,(%ecx)
movb %al,(%edi)
Lp9:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry7_8:
cmpw 2(%ecx),%bp
jl Lp10
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp10
movw %bp,2(%ecx)
movb %al,1(%edi)
Lp10:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry6_8:
cmpw 4(%ecx),%bp
jl Lp11
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp11
movw %bp,4(%ecx)
movb %al,2(%edi)
Lp11:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry5_8:
cmpw 6(%ecx),%bp
jl Lp12
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp12
movw %bp,6(%ecx)
movb %al,3(%edi)
Lp12:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry4_8:
cmpw 8(%ecx),%bp
jl Lp13
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp13
movw %bp,8(%ecx)
movb %al,4(%edi)
Lp13:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry3_8:
cmpw 10(%ecx),%bp
jl Lp14
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp14
movw %bp,10(%ecx)
movb %al,5(%edi)
Lp14:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LLEntry2_8:
cmpw 12(%ecx),%bp
jl Lp15
movb (%esi),%al
cmpb $(TRANSPARENT_COLOR),%al
jz Lp15
movw %bp,12(%ecx)
movb %al,6(%edi)
Lp15:
addl izistep,%ebp
adcl $0,%ebp
addl tstep,%edx
sbbl %eax,%eax
addl sstep,%ebx
adcl advancetable+4(,%eax,4),%esi
LEndSpan:
cmpw 14(%ecx),%bp
jl Lp16
movb (%esi),%al // load first texel in segment
cmpb $(TRANSPARENT_COLOR),%al
jz Lp16
movw %bp,14(%ecx)
movb %al,7(%edi)
Lp16:
//
// clear s/z, t/z, 1/z from FP stack
//
fstp %st(0)
fstp %st(0)
fstp %st(0)
popl %ebx // restore spans pointer
LNextSpan:
addl $(sspan_t_size),%ebx // point to next span
movl sspan_t_count(%ebx),%ecx
cmpl $0,%ecx // any more spans?
jg LSpanLoop // yes
jz LNextSpan // yes, but this one's empty
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
#endif // id386

762
linux/r_surf8.s Normal file
View File

@ -0,0 +1,762 @@
//
// surf8.s
// x86 assembly-language 8 bpp surface block drawing code.
//
#include "qasm.h"
#if id386
.data
sb_v: .long 0
.text
.align 4
.globl C(R_Surf8Start)
C(R_Surf8Start):
//----------------------------------------------------------------------
// Surface block drawer for mip level 0
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock8_mip0)
C(R_DrawSurfaceBlock8_mip0):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
Lv_loop_mip0:
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
movl %eax,%ebp
movl C(r_lightwidth),%ecx
movl %edx,C(lightright)
subl %edx,%ebp
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
// lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
// lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
// 0xF0000000;
movl 4(%ebx),%ecx // lightptr[1]
movl (%ebx),%ebx // lightptr[0]
subl %eax,%ebx
subl %edx,%ecx
sarl $4,%ecx
orl $0xF0000000,%ebp
sarl $4,%ebx
movl %ecx,C(lightrightstep)
subl %ecx,%ebx
andl $0xFFFFF,%ebx
orl $0xF0000000,%ebx
subl %ecx,%ecx // high word must be 0 in loop for addressing
movl %ebx,C(lightdeltastep)
subl %ebx,%ebx // high word must be 0 in loop for addressing
Lblockloop8_mip0:
movl %ebp,C(lightdelta)
movb 14(%esi),%cl
sarl $4,%ebp
movb %dh,%bh
movb 15(%esi),%bl
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch0:
movb 13(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch1:
movb 12(%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch2:
movb 11(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch3:
movb 10(%esi),%cl
movl %eax,12(%edi)
movb %dh,%bh
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch4:
movb 9(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch5:
movb 8(%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch6:
movb 7(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch7:
movb 6(%esi),%cl
movl %eax,8(%edi)
movb %dh,%bh
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch8:
movb 5(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch9:
movb 4(%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch10:
movb 3(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch11:
movb 2(%esi),%cl
movl %eax,4(%edi)
movb %dh,%bh
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch12:
movb 1(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch13:
movb (%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
movb 0x12345678(%ebx),%ah
LBPatch14:
movl C(lightright),%edx
movb 0x12345678(%ecx),%al
LBPatch15:
movl C(lightdelta),%ebp
movl %eax,(%edi)
addl C(sourcetstep),%esi
addl C(surfrowbytes),%edi
addl C(lightrightstep),%edx
addl C(lightdeltastep),%ebp
movl %edx,C(lightright)
jc Lblockloop8_mip0
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
cmpl C(r_sourcemax),%esi
jb LSkip_mip0
subl C(r_stepback),%esi
LSkip_mip0:
movl C(r_lightptr),%ebx
decl sb_v
jnz Lv_loop_mip0
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
//----------------------------------------------------------------------
// Surface block drawer for mip level 1
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock8_mip1)
C(R_DrawSurfaceBlock8_mip1):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
Lv_loop_mip1:
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
movl %eax,%ebp
movl C(r_lightwidth),%ecx
movl %edx,C(lightright)
subl %edx,%ebp
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
// lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
// lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
// 0xF0000000;
movl 4(%ebx),%ecx // lightptr[1]
movl (%ebx),%ebx // lightptr[0]
subl %eax,%ebx
subl %edx,%ecx
sarl $3,%ecx
orl $0x70000000,%ebp
sarl $3,%ebx
movl %ecx,C(lightrightstep)
subl %ecx,%ebx
andl $0xFFFFF,%ebx
orl $0xF0000000,%ebx
subl %ecx,%ecx // high word must be 0 in loop for addressing
movl %ebx,C(lightdeltastep)
subl %ebx,%ebx // high word must be 0 in loop for addressing
Lblockloop8_mip1:
movl %ebp,C(lightdelta)
movb 6(%esi),%cl
sarl $3,%ebp
movb %dh,%bh
movb 7(%esi),%bl
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch22:
movb 5(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch23:
movb 4(%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch24:
movb 3(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch25:
movb 2(%esi),%cl
movl %eax,4(%edi)
movb %dh,%bh
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch26:
movb 1(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch27:
movb (%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
movb 0x12345678(%ebx),%ah
LBPatch28:
movl C(lightright),%edx
movb 0x12345678(%ecx),%al
LBPatch29:
movl C(lightdelta),%ebp
movl %eax,(%edi)
movl C(sourcetstep),%eax
addl %eax,%esi
movl C(surfrowbytes),%eax
addl %eax,%edi
movl C(lightrightstep),%eax
addl %eax,%edx
movl C(lightdeltastep),%eax
addl %eax,%ebp
movl %edx,C(lightright)
jc Lblockloop8_mip1
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
cmpl C(r_sourcemax),%esi
jb LSkip_mip1
subl C(r_stepback),%esi
LSkip_mip1:
movl C(r_lightptr),%ebx
decl sb_v
jnz Lv_loop_mip1
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
//----------------------------------------------------------------------
// Surface block drawer for mip level 2
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock8_mip2)
C(R_DrawSurfaceBlock8_mip2):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
Lv_loop_mip2:
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
movl %eax,%ebp
movl C(r_lightwidth),%ecx
movl %edx,C(lightright)
subl %edx,%ebp
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
// lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
// lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
// 0xF0000000;
movl 4(%ebx),%ecx // lightptr[1]
movl (%ebx),%ebx // lightptr[0]
subl %eax,%ebx
subl %edx,%ecx
sarl $2,%ecx
orl $0x30000000,%ebp
sarl $2,%ebx
movl %ecx,C(lightrightstep)
subl %ecx,%ebx
andl $0xFFFFF,%ebx
orl $0xF0000000,%ebx
subl %ecx,%ecx // high word must be 0 in loop for addressing
movl %ebx,C(lightdeltastep)
subl %ebx,%ebx // high word must be 0 in loop for addressing
Lblockloop8_mip2:
movl %ebp,C(lightdelta)
movb 2(%esi),%cl
sarl $2,%ebp
movb %dh,%bh
movb 3(%esi),%bl
addl %ebp,%edx
movb %dh,%ch
addl %ebp,%edx
movb 0x12345678(%ebx),%ah
LBPatch18:
movb 1(%esi),%bl
movb 0x12345678(%ecx),%al
LBPatch19:
movb (%esi),%cl
movb %dh,%bh
addl %ebp,%edx
rorl $16,%eax
movb %dh,%ch
movb 0x12345678(%ebx),%ah
LBPatch20:
movl C(lightright),%edx
movb 0x12345678(%ecx),%al
LBPatch21:
movl C(lightdelta),%ebp
movl %eax,(%edi)
movl C(sourcetstep),%eax
addl %eax,%esi
movl C(surfrowbytes),%eax
addl %eax,%edi
movl C(lightrightstep),%eax
addl %eax,%edx
movl C(lightdeltastep),%eax
addl %eax,%ebp
movl %edx,C(lightright)
jc Lblockloop8_mip2
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
cmpl C(r_sourcemax),%esi
jb LSkip_mip2
subl C(r_stepback),%esi
LSkip_mip2:
movl C(r_lightptr),%ebx
decl sb_v
jnz Lv_loop_mip2
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
//----------------------------------------------------------------------
// Surface block drawer for mip level 3
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock8_mip3)
C(R_DrawSurfaceBlock8_mip3):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
Lv_loop_mip3:
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
movl %eax,%ebp
movl C(r_lightwidth),%ecx
movl %edx,C(lightright)
subl %edx,%ebp
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
movl %ebp,C(lightdelta)
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
// lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
// lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
// 0xF0000000;
movl 4(%ebx),%ecx // lightptr[1]
movl (%ebx),%ebx // lightptr[0]
subl %eax,%ebx
subl %edx,%ecx
sarl $1,%ecx
sarl $1,%ebx
movl %ecx,C(lightrightstep)
subl %ecx,%ebx
andl $0xFFFFF,%ebx
sarl $1,%ebp
orl $0xF0000000,%ebx
movl %ebx,C(lightdeltastep)
subl %ebx,%ebx // high word must be 0 in loop for addressing
movb 1(%esi),%bl
subl %ecx,%ecx // high word must be 0 in loop for addressing
movb %dh,%bh
movb (%esi),%cl
addl %ebp,%edx
movb %dh,%ch
movb 0x12345678(%ebx),%al
LBPatch16:
movl C(lightright),%edx
movb %al,1(%edi)
movb 0x12345678(%ecx),%al
LBPatch17:
movb %al,(%edi)
movl C(sourcetstep),%eax
addl %eax,%esi
movl C(surfrowbytes),%eax
addl %eax,%edi
movl C(lightdeltastep),%eax
movl C(lightdelta),%ebp
movb (%esi),%cl
addl %eax,%ebp
movl C(lightrightstep),%eax
sarl $1,%ebp
addl %eax,%edx
movb %dh,%bh
movb 1(%esi),%bl
addl %ebp,%edx
movb %dh,%ch
movb 0x12345678(%ebx),%al
LBPatch30:
movl C(sourcetstep),%edx
movb %al,1(%edi)
movb 0x12345678(%ecx),%al
LBPatch31:
movb %al,(%edi)
movl C(surfrowbytes),%ebp
addl %edx,%esi
addl %ebp,%edi
// if (pbasesource >= r_sourcemax)
// pbasesource -= stepback;
cmpl C(r_sourcemax),%esi
jb LSkip_mip3
subl C(r_stepback),%esi
LSkip_mip3:
movl C(r_lightptr),%ebx
decl sb_v
jnz Lv_loop_mip3
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
.globl C(R_Surf8End)
C(R_Surf8End):
//----------------------------------------------------------------------
// Code patching routines
//----------------------------------------------------------------------
.data
.align 4
LPatchTable8:
.long LBPatch0-4
.long LBPatch1-4
.long LBPatch2-4
.long LBPatch3-4
.long LBPatch4-4
.long LBPatch5-4
.long LBPatch6-4
.long LBPatch7-4
.long LBPatch8-4
.long LBPatch9-4
.long LBPatch10-4
.long LBPatch11-4
.long LBPatch12-4
.long LBPatch13-4
.long LBPatch14-4
.long LBPatch15-4
.long LBPatch16-4
.long LBPatch17-4
.long LBPatch18-4
.long LBPatch19-4
.long LBPatch20-4
.long LBPatch21-4
.long LBPatch22-4
.long LBPatch23-4
.long LBPatch24-4
.long LBPatch25-4
.long LBPatch26-4
.long LBPatch27-4
.long LBPatch28-4
.long LBPatch29-4
.long LBPatch30-4
.long LBPatch31-4
.text
.align 4
.globl C(R_Surf8Patch)
C(R_Surf8Patch):
pushl %ebx
movl C(colormap),%eax
movl $LPatchTable8,%ebx
movl $32,%ecx
LPatchLoop8:
movl (%ebx),%edx
addl $4,%ebx
movl %eax,(%edx)
decl %ecx
jnz LPatchLoop8
popl %ebx
ret
#endif // id386

223
linux/r_varsa.s Normal file
View File

@ -0,0 +1,223 @@
//
// r_varsa.s
//
#include "qasm.h"
#include "d_ifacea.h"
#if id386
.data
//-------------------------------------------------------
// ASM-only variables
//-------------------------------------------------------
.globl float_1, float_particle_z_clip, float_point5
.globl float_minus_1, float_0
float_0: .single 0.0
float_1: .single 1.0
float_minus_1: .single -1.0
float_particle_z_clip: .single PARTICLE_Z_CLIP
float_point5: .single 0.5
.globl fp_16, fp_64k, fp_1m, fp_64kx64k
.globl fp_1m_minus_1
.globl fp_8
fp_1m: .single 1048576.0
fp_1m_minus_1: .single 1048575.0
fp_64k: .single 65536.0
fp_8: .single 8.0
fp_16: .single 16.0
fp_64kx64k: .long 0x4f000000 // (float)0x8000*0x10000
.globl FloatZero, Float2ToThe31nd, FloatMinus2ToThe31nd
FloatZero: .long 0
Float2ToThe31nd: .long 0x4f000000
FloatMinus2ToThe31nd: .long 0xcf000000
.globl C(r_bmodelactive)
C(r_bmodelactive): .long 0
//-------------------------------------------------------
// global refresh variables
//-------------------------------------------------------
// FIXME: put all refresh variables into one contiguous block. Make into one
// big structure, like cl or sv?
.align 4
.globl C(d_sdivzstepu)
.globl C(d_tdivzstepu)
.globl C(d_zistepu)
.globl C(d_sdivzstepv)
.globl C(d_tdivzstepv)
.globl C(d_zistepv)
.globl C(d_sdivzorigin)
.globl C(d_tdivzorigin)
.globl C(d_ziorigin)
C(d_sdivzstepu): .single 0
C(d_tdivzstepu): .single 0
C(d_zistepu): .single 0
C(d_sdivzstepv): .single 0
C(d_tdivzstepv): .single 0
C(d_zistepv): .single 0
C(d_sdivzorigin): .single 0
C(d_tdivzorigin): .single 0
C(d_ziorigin): .single 0
.globl C(sadjust)
.globl C(tadjust)
.globl C(bbextents)
.globl C(bbextentt)
C(sadjust): .long 0
C(tadjust): .long 0
C(bbextents): .long 0
C(bbextentt): .long 0
.globl C(cacheblock)
.globl C(d_viewbuffer)
.globl C(cachewidth)
.globl C(d_pzbuffer)
.globl C(d_zrowbytes)
.globl C(d_zwidth)
C(cacheblock): .long 0
C(cachewidth): .long 0
C(d_viewbuffer): .long 0
C(d_pzbuffer): .long 0
C(d_zrowbytes): .long 0
C(d_zwidth): .long 0
//-------------------------------------------------------
// ASM-only variables
//-------------------------------------------------------
.globl izi
izi: .long 0
.globl pbase, s, t, sfracf, tfracf, snext, tnext
.globl spancountminus1, zi16stepu, sdivz16stepu, tdivz16stepu
.globl zi8stepu, sdivz8stepu, tdivz8stepu, pz
s: .long 0
t: .long 0
snext: .long 0
tnext: .long 0
sfracf: .long 0
tfracf: .long 0
pbase: .long 0
zi8stepu: .long 0
sdivz8stepu: .long 0
tdivz8stepu: .long 0
zi16stepu: .long 0
sdivz16stepu: .long 0
tdivz16stepu: .long 0
spancountminus1: .long 0
pz: .long 0
.globl izistep
izistep: .long 0
//-------------------------------------------------------
// local variables for d_draw16.s
//-------------------------------------------------------
.globl reciprocal_table_16, entryvec_table_16
// 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, and 1/15 in 0.32 form
reciprocal_table_16: .long 0x40000000, 0x2aaaaaaa, 0x20000000
.long 0x19999999, 0x15555555, 0x12492492
.long 0x10000000, 0xe38e38e, 0xccccccc, 0xba2e8ba
.long 0xaaaaaaa, 0x9d89d89, 0x9249249, 0x8888888
#ifndef NeXT
.extern Entry2_16
.extern Entry3_16
.extern Entry4_16
.extern Entry5_16
.extern Entry6_16
.extern Entry7_16
.extern Entry8_16
.extern Entry9_16
.extern Entry10_16
.extern Entry11_16
.extern Entry12_16
.extern Entry13_16
.extern Entry14_16
.extern Entry15_16
.extern Entry16_16
#endif
entryvec_table_16: .long 0, Entry2_16, Entry3_16, Entry4_16
.long Entry5_16, Entry6_16, Entry7_16, Entry8_16
.long Entry9_16, Entry10_16, Entry11_16, Entry12_16
.long Entry13_16, Entry14_16, Entry15_16, Entry16_16
//-------------------------------------------------------
// local variables for d_parta.s
//-------------------------------------------------------
.globl DP_Count, DP_u, DP_v, DP_32768, DP_Color, DP_Pix, DP_EntryTable
DP_Count: .long 0
DP_u: .long 0
DP_v: .long 0
DP_32768: .single 32768.0
DP_Color: .long 0
DP_Pix: .long 0
#if 0
.extern DP_1x1
.extern DP_2x2
.extern DP_3x3
.extern DP_4x4
DP_EntryTable: .long DP_1x1, DP_2x2, DP_3x3, DP_4x4
#endif
//
// advancetable is 8 bytes, but points to the middle of that range so negative
// offsets will work
//
.globl advancetable, sstep, tstep, pspantemp, counttemp, jumptemp
advancetable: .long 0, 0
sstep: .long 0
tstep: .long 0
pspantemp: .long 0
counttemp: .long 0
jumptemp: .long 0
// 1/2, 1/3, 1/4, 1/5, 1/6, and 1/7 in 0.32 form
.globl reciprocal_table, entryvec_table
reciprocal_table: .long 0x40000000, 0x2aaaaaaa, 0x20000000
.long 0x19999999, 0x15555555, 0x12492492
#if 0
.extern Entry2_8
.extern Entry3_8
.extern Entry4_8
.extern Entry5_8
.extern Entry6_8
.extern Entry7_8
.extern Entry8_8
entryvec_table: .long 0, Entry2_8, Entry3_8, Entry4_8
.long Entry5_8, Entry6_8, Entry7_8, Entry8_8
#endif
#ifndef NeXT
.extern Spr8Entry2_8
.extern Spr8Entry3_8
.extern Spr8Entry4_8
.extern Spr8Entry5_8
.extern Spr8Entry6_8
.extern Spr8Entry7_8
.extern Spr8Entry8_8
#endif
.globl spr8entryvec_table
spr8entryvec_table: .long 0, Spr8Entry2_8, Spr8Entry3_8, Spr8Entry4_8
.long Spr8Entry5_8, Spr8Entry6_8, Spr8Entry7_8, Spr8Entry8_8
#endif // id386

374
linux/rw_in_svgalib.c Normal file
View File

@ -0,0 +1,374 @@
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/vt.h>
#include <stdarg.h>
#include <stdio.h>
#include <signal.h>
#include <sys/mman.h>
#include <asm/io.h>
#include "vga.h"
#include "vgakeyboard.h"
#include "vgamouse.h"
#include "../ref_soft/r_local.h"
#include "../client/keys.h"
#include "../linux/rw_linux.h"
/*****************************************************************************/
/* KEYBOARD */
/*****************************************************************************/
static unsigned char scantokey[128];
Key_Event_fp_t Key_Event_fp;
static void keyhandler(int scancode, int state)
{
int sc;
sc = scancode & 0x7f;
//ri.Con_Printf(PRINT_ALL, "scancode=%x (%d%s)\n", scancode, sc, scancode&0x80?"+128":"");
Key_Event_fp(scantokey[sc], state == KEY_EVENTPRESS);
}
void KBD_Init(Key_Event_fp_t fp)
{
int i;
Key_Event_fp = fp;
for (i=0 ; i<128 ; i++)
scantokey[i] = ' ';
scantokey[ 1] = K_ESCAPE;
scantokey[ 2] = '1';
scantokey[ 3] = '2';
scantokey[ 4] = '3';
scantokey[ 5] = '4';
scantokey[ 6] = '5';
scantokey[ 7] = '6';
scantokey[ 8] = '7';
scantokey[ 9] = '8';
scantokey[ 10] = '9';
scantokey[ 11] = '0';
scantokey[ 12] = '-';
scantokey[ 13] = '=';
scantokey[ 14] = K_BACKSPACE;
scantokey[ 15] = K_TAB;
scantokey[ 16] = 'q';
scantokey[ 17] = 'w';
scantokey[ 18] = 'e';
scantokey[ 19] = 'r';
scantokey[ 20] = 't';
scantokey[ 21] = 'y';
scantokey[ 22] = 'u';
scantokey[ 23] = 'i';
scantokey[ 24] = 'o';
scantokey[ 25] = 'p';
scantokey[ 26] = '[';
scantokey[ 27] = ']';
scantokey[ 28] = K_ENTER;
scantokey[ 29] = K_CTRL; //left
scantokey[ 30] = 'a';
scantokey[ 31] = 's';
scantokey[ 32] = 'd';
scantokey[ 33] = 'f';
scantokey[ 34] = 'g';
scantokey[ 35] = 'h';
scantokey[ 36] = 'j';
scantokey[ 37] = 'k';
scantokey[ 38] = 'l';
scantokey[ 39] = ';';
scantokey[ 40] = '\'';
scantokey[ 41] = '`';
scantokey[ 42] = K_SHIFT; //left
scantokey[ 43] = '\\';
scantokey[ 44] = 'z';
scantokey[ 45] = 'x';
scantokey[ 46] = 'c';
scantokey[ 47] = 'v';
scantokey[ 48] = 'b';
scantokey[ 49] = 'n';
scantokey[ 50] = 'm';
scantokey[ 51] = ',';
scantokey[ 52] = '.';
scantokey[ 53] = '/';
scantokey[ 54] = K_SHIFT; //right
scantokey[ 55] = '*'; //keypad
scantokey[ 56] = K_ALT; //left
scantokey[ 57] = ' ';
// 58 caps lock
scantokey[ 59] = K_F1;
scantokey[ 60] = K_F2;
scantokey[ 61] = K_F3;
scantokey[ 62] = K_F4;
scantokey[ 63] = K_F5;
scantokey[ 64] = K_F6;
scantokey[ 65] = K_F7;
scantokey[ 66] = K_F8;
scantokey[ 67] = K_F9;
scantokey[ 68] = K_F10;
// 69 numlock
// 70 scrollock
scantokey[ 71] = K_KP_HOME;
scantokey[ 72] = K_KP_UPARROW;
scantokey[ 73] = K_KP_PGUP;
scantokey[ 74] = K_KP_MINUS;
scantokey[ 75] = K_KP_LEFTARROW;
scantokey[ 76] = K_KP_5;
scantokey[ 77] = K_KP_RIGHTARROW;
scantokey[ 79] = K_KP_END;
scantokey[ 78] = K_KP_PLUS;
scantokey[ 80] = K_KP_DOWNARROW;
scantokey[ 81] = K_KP_PGDN;
scantokey[ 82] = K_KP_INS;
scantokey[ 83] = K_KP_DEL;
// 84 to 86 not used
scantokey[ 87] = K_F11;
scantokey[ 88] = K_F12;
// 89 to 95 not used
scantokey[ 96] = K_KP_ENTER; //keypad enter
scantokey[ 97] = K_CTRL; //right
scantokey[ 98] = K_KP_SLASH;
scantokey[ 99] = K_F12; // print screen, bind to screenshot by default
scantokey[100] = K_ALT; // right
scantokey[101] = K_PAUSE; // break
scantokey[102] = K_HOME;
scantokey[103] = K_UPARROW;
scantokey[104] = K_PGUP;
scantokey[105] = K_LEFTARROW;
scantokey[106] = K_RIGHTARROW;
scantokey[107] = K_END;
scantokey[108] = K_DOWNARROW;
scantokey[109] = K_PGDN;
scantokey[110] = K_INS;
scantokey[111] = K_DEL;
scantokey[119] = K_PAUSE;
if (keyboard_init())
Sys_Error("keyboard_init() failed");
keyboard_seteventhandler(keyhandler);
keyboard_translatekeys(DONT_CATCH_CTRLC);
}
void KBD_Update(void)
{
while (keyboard_update())
;
}
void KBD_Close(void)
{
keyboard_close();
}
/*****************************************************************************/
/* MOUSE */
/*****************************************************************************/
// this is inside the renderer shared lib, so these are called from vid_so
static qboolean UseMouse = true;
static int mouserate = MOUSE_DEFAULTSAMPLERATE;
static int mouse_buttons;
static int mouse_buttonstate;
static int mouse_oldbuttonstate;
static float mouse_x, mouse_y;
static float old_mouse_x, old_mouse_y;
static int mx, my;
static cvar_t *m_filter;
static cvar_t *in_mouse;
static cvar_t *mdev;
static cvar_t *mrate;
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 ();
}
static void mousehandler(int buttonstate, int dx, int dy)
{
mouse_buttonstate = buttonstate;
mx += dx;
my += dy;
}
void RW_IN_Init(in_state_t *in_state_p)
{
int mtype;
int i;
in_state = in_state_p;
// mouse variables
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_buttons = 3;
mtype = vga_getmousetype();
mdev = ri.Cvar_Get ("mdev", "/dev/mouse", 0);
mrate = ri.Cvar_Get ("mrate", "1200", 0);
// printf("Mouse: dev=%s,type=%s,speed=%d\n",
// mousedev, mice[mtype].name, mouserate);
if (mouse_init(mdev->string, mtype, (int)mrate->value))
{
ri.Con_Printf(PRINT_ALL, "No mouse found\n");
UseMouse = false;
}
else
mouse_seteventhandler(mousehandler);
}
void RW_IN_Shutdown(void)
{
mouse_close();
}
/*
===========
IN_Commands
===========
*/
void RW_IN_Commands (void)
{
if (!UseMouse)
return;
// poll mouse values
mouse_update();
// perform button actions
if ((mouse_buttonstate & MOUSE_LEFTBUTTON) &&
!(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
in_state->Key_Event_fp (K_MOUSE1, true);
else if (!(mouse_buttonstate & MOUSE_LEFTBUTTON) &&
(mouse_oldbuttonstate & MOUSE_LEFTBUTTON))
in_state->Key_Event_fp (K_MOUSE1, false);
if ((mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
!(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
in_state->Key_Event_fp (K_MOUSE2, true);
else if (!(mouse_buttonstate & MOUSE_RIGHTBUTTON) &&
(mouse_oldbuttonstate & MOUSE_RIGHTBUTTON))
in_state->Key_Event_fp (K_MOUSE2, false);
if ((mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
!(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
Key_Event_fp (K_MOUSE3, true);
else if (!(mouse_buttonstate & MOUSE_MIDDLEBUTTON) &&
(mouse_oldbuttonstate & MOUSE_MIDDLEBUTTON))
in_state->Key_Event_fp (K_MOUSE3, false);
mouse_oldbuttonstate = mouse_buttonstate;
}
/*
===========
IN_Move
===========
*/
void RW_IN_Move (usercmd_t *cmd)
{
if (!UseMouse)
return;
// poll mouse values
mouse_update();
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 (!mx && !my)
return;
mx = my = 0; // clear for next update
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;
}
}
void RW_IN_Frame (void)
{
}
void RW_IN_Activate(void)
{
}

16
linux/rw_linux.h Normal file
View File

@ -0,0 +1,16 @@
typedef void (*Key_Event_fp_t)(int key, qboolean down);
extern void (*KBD_Update_fp)(void);
extern void (*KBD_Init_fp)(Key_Event_fp_t fp);
extern void (*KBD_Close_fp)(void);
typedef struct in_state {
// Pointers to functions back in client, set by vid_so
void (*IN_CenterView_fp)(void);
Key_Event_fp_t Key_Event_fp;
vec_t *viewangles;
int *in_strafe_state;
} in_state_t;

311
linux/rw_svgalib.c Normal file
View File

@ -0,0 +1,311 @@
/*
** RW_SVGALBI.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 <termios.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/vt.h>
#include <stdarg.h>
#include <stdio.h>
#include <signal.h>
#include <sys/mman.h>
#include <asm/io.h>
#include "vga.h"
#include "vgakeyboard.h"
#include "vgamouse.h"
#include "../ref_soft/r_local.h"
#include "../client/keys.h"
#include "../linux/rw_linux.h"
/*****************************************************************************/
int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
byte *VGA_pagebase;
char *framebuffer_ptr;
void VGA_UpdatePlanarScreen (void *srcbuffer);
int num_modes;
vga_modeinfo *modes;
int current_mode;
// Console variables that we need to access from this module
/*****************************************************************************/
void VID_InitModes(void)
{
int i;
// get complete information on all modes
num_modes = vga_lastmodenumber()+1;
modes = malloc(num_modes * sizeof(vga_modeinfo));
for (i=0 ; i<num_modes ; i++)
{
if (vga_hasmode(i))
memcpy(&modes[i], vga_getmodeinfo(i), sizeof (vga_modeinfo));
else
modes[i].width = 0; // means not available
}
// filter for modes i don't support
for (i=0 ; i<num_modes ; i++)
{
if (modes[i].bytesperpixel != 1 && modes[i].colors != 256)
modes[i].width = 0;
}
for (i = 0; i < num_modes; i++)
if (modes[i].width)
ri.Con_Printf(PRINT_ALL, "mode %d: %d %d\n", modes[i].width, modes[i].height);
}
/*
** SWimp_Init
**
** This routine is responsible for initializing the implementation
** specific stuff in a software rendering subsystem.
*/
int SWimp_Init( void *hInstance, void *wndProc )
{
vga_init();
VID_InitModes();
return true;
}
int get_mode(int width, int height)
{
int i;
int ok, match;
for (i=0 ; i<num_modes ; i++)
if (modes[i].width &&
modes[i].width == width && modes[i].height == height)
break;
if (i==num_modes)
return -1; // not found
return i;
}
/*
** 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 bsize, zsize, tsize;
SWimp_Shutdown();
current_mode = get_mode(vid.width, vid.height);
if (current_mode < 0) {
ri.Con_Printf (PRINT_ALL, "Mode %d %d not found\n", vid.width, vid.height);
return false; // mode not found
}
// let the sound and input subsystems know about the new window
ri.Vid_NewWindow (vid.width, vid.height);
ri.Con_Printf (PRINT_ALL, "Setting VGAMode: %d\n", current_mode );
// Cvar_SetValue ("vid_mode", (float)modenum);
VGA_width = modes[current_mode].width;
VGA_height = modes[current_mode].height;
VGA_planar = modes[current_mode].bytesperpixel == 0;
VGA_rowbytes = modes[current_mode].linewidth;
vid.rowbytes = modes[current_mode].linewidth;
if (VGA_planar) {
VGA_bufferrowbytes = modes[current_mode].linewidth * 4;
vid.rowbytes = modes[current_mode].linewidth*4;
}
// get goin'
vga_setmode(current_mode);
VGA_pagebase = framebuffer_ptr = (char *) vga_getgraphmem();
// if (vga_setlinearaddressing()>0)
// framebuffer_ptr = (char *) vga_getgraphmem();
if (!framebuffer_ptr)
Sys_Error("This mode isn't hapnin'\n");
vga_setpage(0);
vid.buffer = malloc(vid.rowbytes * vid.height);
if (!vid.buffer)
Sys_Error("Unabled to alloc vid.buffer!\n");
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 (!vga_oktowrite())
return; // can't update screen if it's not active
// if (vid_waitforrefresh.value)
// vga_waitretrace();
if (VGA_planar)
VGA_UpdatePlanarScreen (vid.buffer);
else {
int total = vid.rowbytes * vid.height;
int offset;
for (offset=0;offset<total;offset+=0x10000) {
vga_setpage(offset/0x10000);
memcpy(framebuffer_ptr,
vid.buffer + offset,
((total-offset>0x10000)?0x10000:(total-offset)));
}
}
}
/*
** 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 )
{
static int tmppal[256*3];
const unsigned char *pal;
int *tp;
int i;
if ( !palette )
palette = ( const unsigned char * ) sw_state.currentpalette;
if (vga_getcolors() == 256)
{
tp = tmppal;
pal = palette;
for (i=0 ; i < 256 ; i++, pal += 4, tp += 3) {
tp[0] = pal[0] >> 2;
tp[1] = pal[1] >> 2;
tp[2] = pal[2] >> 2;
}
if (vga_oktowrite())
vga_setpalvec(0, 256, tmppal);
}
}
/*
** SWimp_Shutdown
**
** System specific graphics subsystem shutdown routine. Destroys
** DIBs or DDRAW surfaces as appropriate.
*/
void SWimp_Shutdown( void )
{
if (vid.buffer) {
free(vid.buffer);
vid.buffer = NULL;
}
vga_setmode(TEXT);
}
/*
** 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");
}

1093
linux/rw_x11.c Normal file

File diff suppressed because it is too large Load Diff

266
linux/snd_linux.c Normal file
View File

@ -0,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)
{
}

193
linux/snd_mixa.s Normal file
View File

@ -0,0 +1,193 @@
//
// snd_mixa.s
// x86 assembly-language sound code
//
#include "qasm.h"
#if id386
.text
//----------------------------------------------------------------------
// 8-bit sound-mixing code
//----------------------------------------------------------------------
#define ch 4+16
#define sc 8+16
#define count 12+16
.globl C(S_PaintChannelFrom8)
C(S_PaintChannelFrom8):
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
pushl %ebp
// int data;
// short *lscale, *rscale;
// unsigned char *sfx;
// int i;
movl ch(%esp),%ebx
movl sc(%esp),%esi
// if (ch->leftvol > 255)
// ch->leftvol = 255;
// if (ch->rightvol > 255)
// ch->rightvol = 255;
movl ch_leftvol(%ebx),%eax
movl ch_rightvol(%ebx),%edx
cmpl $255,%eax
jna LLeftSet
movl $255,%eax
LLeftSet:
cmpl $255,%edx
jna LRightSet
movl $255,%edx
LRightSet:
// lscale = snd_scaletable[ch->leftvol >> 3];
// rscale = snd_scaletable[ch->rightvol >> 3];
// sfx = (signed char *)sc->data + ch->pos;
// ch->pos += count;
andl $0xF8,%eax
addl $(sfxc_data),%esi
andl $0xF8,%edx
movl ch_pos(%ebx),%edi
movl count(%esp),%ecx
addl %edi,%esi
shll $7,%eax
addl %ecx,%edi
shll $7,%edx
movl %edi,ch_pos(%ebx)
addl $(C(snd_scaletable)),%eax
addl $(C(snd_scaletable)),%edx
subl %ebx,%ebx
movb -1(%esi,%ecx,1),%bl
testl $1,%ecx
jz LMix8Loop
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
addl C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
movl %edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
movb -2(%esi,%ecx,1),%bl
decl %ecx
jz LDone
// for (i=0 ; i<count ; i++)
// {
LMix8Loop:
// data = sfx[i];
// paintbuffer[i].left += lscale[data];
// paintbuffer[i].right += rscale[data];
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
addl C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
movb -2(%esi,%ecx,1),%bl
movl %edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
movb -3(%esi,%ecx,1),%bl
addl C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size),%ebp
movl %edi,C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size)
// }
subl $2,%ecx
jnz LMix8Loop
LDone:
popl %ebp
popl %ebx
popl %edi
popl %esi
ret
//----------------------------------------------------------------------
// Transfer of stereo buffer to 16-bit DMA buffer code
//----------------------------------------------------------------------
.globl C(S_WriteLinearBlastStereo16)
C(S_WriteLinearBlastStereo16):
pushl %edi
pushl %ebx
// int i;
// int val;
movl C(snd_linear_count),%ecx
movl C(snd_p),%ebx
movl C(snd_out),%edi
// for (i=0 ; i<snd_linear_count ; i+=2)
// {
LWLBLoopTop:
// val = (snd_p[i]*snd_vol)>>8;
// if (val > 0x7fff)
// snd_out[i] = 0x7fff;
// else if (val < (short)0x8000)
// snd_out[i] = (short)0x8000;
// else
// snd_out[i] = val;
movl -8(%ebx,%ecx,4),%eax
sarl $8,%eax
cmpl $0x7FFF,%eax
jg LClampHigh
cmpl $0xFFFF8000,%eax
jnl LClampDone
movl $0xFFFF8000,%eax
jmp LClampDone
LClampHigh:
movl $0x7FFF,%eax
LClampDone:
// val = (snd_p[i+1]*snd_vol)>>8;
// if (val > 0x7fff)
// snd_out[i+1] = 0x7fff;
// else if (val < (short)0x8000)
// snd_out[i+1] = (short)0x8000;
// else
// snd_out[i+1] = val;
movl -4(%ebx,%ecx,4),%edx
sarl $8,%edx
cmpl $0x7FFF,%edx
jg LClampHigh2
cmpl $0xFFFF8000,%edx
jnl LClampDone2
movl $0xFFFF8000,%edx
jmp LClampDone2
LClampHigh2:
movl $0x7FFF,%edx
LClampDone2:
shll $16,%edx
andl $0xFFFF,%eax
orl %eax,%edx
movl %edx,-4(%edi,%ecx,2)
// }
subl $2,%ecx
jnz LWLBLoopTop
// snd_p += snd_linear_count;
popl %ebx
popl %edi
ret
#endif // id386

94
linux/sys_dosa.s Normal file
View File

@ -0,0 +1,94 @@
//
// sys_dosa.s
// x86 assembly-language DOS-dependent routines.
#include "qasm.h"
.data
.align 4
fpenv:
.long 0, 0, 0, 0, 0, 0, 0, 0
.text
.globl C(MaskExceptions)
C(MaskExceptions):
fnstenv fpenv
orl $0x3F,fpenv
fldenv fpenv
ret
#if 0
.globl C(unmaskexceptions)
C(unmaskexceptions):
fnstenv fpenv
andl $0xFFFFFFE0,fpenv
fldenv fpenv
ret
#endif
.data
.align 4
.globl ceil_cw, single_cw, full_cw, cw, pushed_cw
ceil_cw: .long 0
single_cw: .long 0
full_cw: .long 0
cw: .long 0
pushed_cw: .long 0
.text
.globl C(Sys_LowFPPrecision)
C(Sys_LowFPPrecision):
fldcw single_cw
ret
.globl C(Sys_HighFPPrecision)
C(Sys_HighFPPrecision):
fldcw full_cw
ret
.globl C(Sys_PushFPCW_SetHigh)
C(Sys_PushFPCW_SetHigh):
fnstcw pushed_cw
fldcw full_cw
ret
.globl C(Sys_PopFPCW)
C(Sys_PopFPCW):
fldcw pushed_cw
ret
.globl C(Sys_SetFPCW)
C(Sys_SetFPCW):
fnstcw cw
movl cw,%eax
#if id386
andb $0xF0,%ah
orb $0x03,%ah // round mode, 64-bit precision
#endif
movl %eax,full_cw
#if id386
andb $0xF0,%ah
orb $0x0C,%ah // chop mode, single precision
#endif
movl %eax,single_cw
#if id386
andb $0xF0,%ah
orb $0x08,%ah // ceil mode, single precision
#endif
movl %eax,ceil_cw
ret

379
linux/sys_linux.c Normal file
View File

@ -0,0 +1,379 @@
#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;
}
}
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

437
linux/vid_menu.c Normal file
View File

@ -0,0 +1,437 @@
#include "../client/client.h"
#include "../client/qmenu.h"
#define REF_SOFT 0
#define REF_SOFTX11 1
#define REF_OPENGL 2
extern cvar_t *vid_ref;
extern cvar_t *vid_fullscreen;
extern cvar_t *vid_gamma;
extern cvar_t *scr_viewsize;
static cvar_t *gl_mode;
static cvar_t *gl_driver;
static cvar_t *gl_picmip;
static cvar_t *gl_ext_palettedtexture;
static cvar_t *sw_mode;
static cvar_t *sw_stipplealpha;
static cvar_t *_windowed_mouse;
extern void M_ForceMenuOff( void );
/*
====================================================================
MENU INTERACTION
====================================================================
*/
#define SOFTWARE_MENU 0
#define OPENGL_MENU 1
static menuframework_s s_software_menu;
static menuframework_s s_opengl_menu;
static menuframework_s *s_current_menu;
static int s_current_menu_index;
static menulist_s s_mode_list[2];
static menulist_s s_ref_list[2];
static menuslider_s s_tq_slider;
static menuslider_s s_screensize_slider[2];
static menuslider_s s_brightness_slider[2];
static menulist_s s_fs_box[2];
static menulist_s s_stipple_box;
static menulist_s s_paletted_texture_box;
static menulist_s s_windowed_mouse;
static menuaction_s s_apply_action[2];
static menuaction_s s_defaults_action[2];
static void DriverCallback( void *unused )
{
s_ref_list[!s_current_menu_index].curvalue = s_ref_list[s_current_menu_index].curvalue;
if ( s_ref_list[s_current_menu_index].curvalue < 2 )
{
s_current_menu = &s_software_menu;
s_current_menu_index = 0;
}
else
{
s_current_menu = &s_opengl_menu;
s_current_menu_index = 1;
}
}
static void ScreenSizeCallback( void *s )
{
menuslider_s *slider = ( menuslider_s * ) s;
Cvar_SetValue( "viewsize", slider->curvalue * 10 );
}
static void BrightnessCallback( void *s )
{
menuslider_s *slider = ( menuslider_s * ) s;
if ( s_current_menu_index == 0)
s_brightness_slider[1].curvalue = s_brightness_slider[0].curvalue;
else
s_brightness_slider[0].curvalue = s_brightness_slider[1].curvalue;
if ( stricmp( vid_ref->string, "soft" ) == 0 ||
stricmp( vid_ref->string, "softx" ) == 0 )
{
float gamma = ( 0.8 - ( slider->curvalue/10.0 - 0.5 ) ) + 0.5;
Cvar_SetValue( "vid_gamma", gamma );
}
}
static void ResetDefaults( void *unused )
{
VID_MenuInit();
}
static void ApplyChanges( void *unused )
{
float gamma;
/*
** make values consistent
*/
s_fs_box[!s_current_menu_index].curvalue = s_fs_box[s_current_menu_index].curvalue;
s_brightness_slider[!s_current_menu_index].curvalue = s_brightness_slider[s_current_menu_index].curvalue;
s_ref_list[!s_current_menu_index].curvalue = s_ref_list[s_current_menu_index].curvalue;
/*
** invert sense so greater = brighter, and scale to a range of 0.5 to 1.3
*/
gamma = ( 0.8 - ( s_brightness_slider[s_current_menu_index].curvalue/10.0 - 0.5 ) ) + 0.5;
Cvar_SetValue( "vid_gamma", gamma );
Cvar_SetValue( "sw_stipplealpha", s_stipple_box.curvalue );
Cvar_SetValue( "gl_picmip", 3 - s_tq_slider.curvalue );
Cvar_SetValue( "vid_fullscreen", s_fs_box[s_current_menu_index].curvalue );
Cvar_SetValue( "gl_ext_palettedtexture", s_paletted_texture_box.curvalue );
Cvar_SetValue( "sw_mode", s_mode_list[SOFTWARE_MENU].curvalue );
Cvar_SetValue( "gl_mode", s_mode_list[OPENGL_MENU].curvalue );
Cvar_SetValue( "_windowed_mouse", s_windowed_mouse.curvalue);
switch ( s_ref_list[s_current_menu_index].curvalue )
{
case REF_SOFT:
Cvar_Set( "vid_ref", "soft" );
break;
case REF_SOFTX11:
Cvar_Set( "vid_ref", "softx" );
break;
case REF_OPENGL:
Cvar_Set( "vid_ref", "gl" );
Cvar_Set( "gl_driver", "opengl32" );
break;
}
#if 0
/*
** update appropriate stuff if we're running OpenGL and gamma
** has been modified
*/
if ( stricmp( vid_ref->string, "gl" ) == 0 )
{
if ( vid_gamma->modified )
{
vid_ref->modified = true;
if ( stricmp( gl_driver->string, "3dfxgl" ) == 0 )
{
char envbuffer[1024];
float g;
vid_ref->modified = true;
g = 2.00 * ( 0.8 - ( vid_gamma->value - 0.5 ) ) + 1.0F;
Com_sprintf( envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g );
putenv( envbuffer );
vid_gamma->modified = false;
}
}
}
#endif
M_ForceMenuOff();
}
/*
** VID_MenuInit
*/
void VID_MenuInit( void )
{
static const char *resolutions[] =
{
"[320 240 ]",
"[400 300 ]",
"[512 384 ]",
"[640 480 ]",
"[800 600 ]",
"[960 720 ]",
"[1024 768 ]",
"[1152 864 ]",
"[1280 1024]",
"[1600 1200]",
0
};
static const char *refs[] =
{
"[software ]",
"[software X11 ]",
"[default OpenGL]",
0
};
static const char *yesno_names[] =
{
"no",
"yes",
0
};
int i;
if ( !gl_driver )
gl_driver = Cvar_Get( "gl_driver", "opengl32", 0 );
if ( !gl_picmip )
gl_picmip = Cvar_Get( "gl_picmip", "0", 0 );
if ( !gl_mode )
gl_mode = Cvar_Get( "gl_mode", "3", 0 );
if ( !sw_mode )
sw_mode = Cvar_Get( "sw_mode", "0", 0 );
if ( !gl_ext_palettedtexture )
gl_ext_palettedtexture = Cvar_Get( "gl_ext_palettedtexture", "1", CVAR_ARCHIVE );
if ( !sw_stipplealpha )
sw_stipplealpha = Cvar_Get( "sw_stipplealpha", "0", CVAR_ARCHIVE );
if ( !_windowed_mouse)
_windowed_mouse = Cvar_Get( "_windowed_mouse", "0", CVAR_ARCHIVE );
s_mode_list[SOFTWARE_MENU].curvalue = sw_mode->value;
s_mode_list[OPENGL_MENU].curvalue = gl_mode->value;
if ( !scr_viewsize )
scr_viewsize = Cvar_Get ("viewsize", "100", CVAR_ARCHIVE);
s_screensize_slider[SOFTWARE_MENU].curvalue = scr_viewsize->value/10;
s_screensize_slider[OPENGL_MENU].curvalue = scr_viewsize->value/10;
if ( strcmp( vid_ref->string, "soft" ) == 0)
{
s_current_menu_index = SOFTWARE_MENU;
s_ref_list[0].curvalue = s_ref_list[1].curvalue = REF_SOFT;
}
else if (strcmp( vid_ref->string, "softx" ) == 0 )
{
s_current_menu_index = SOFTWARE_MENU;
s_ref_list[0].curvalue = s_ref_list[1].curvalue = REF_SOFTX11;
}
else if ( strcmp( vid_ref->string, "gl" ) == 0 )
{
s_current_menu_index = OPENGL_MENU;
s_ref_list[s_current_menu_index].curvalue = REF_OPENGL;
#if 0
if ( strcmp( gl_driver->string, "3dfxgl" ) == 0 )
s_ref_list[s_current_menu_index].curvalue = REF_3DFX;
else if ( strcmp( gl_driver->string, "pvrgl" ) == 0 )
s_ref_list[s_current_menu_index].curvalue = REF_POWERVR;
else if ( strcmp( gl_driver->string, "opengl32" ) == 0 )
s_ref_list[s_current_menu_index].curvalue = REF_OPENGL;
else
s_ref_list[s_current_menu_index].curvalue = REF_VERITE;
#endif
}
s_software_menu.x = viddef.width * 0.50;
s_software_menu.nitems = 0;
s_opengl_menu.x = viddef.width * 0.50;
s_opengl_menu.nitems = 0;
for ( i = 0; i < 2; i++ )
{
s_ref_list[i].generic.type = MTYPE_SPINCONTROL;
s_ref_list[i].generic.name = "driver";
s_ref_list[i].generic.x = 0;
s_ref_list[i].generic.y = 0;
s_ref_list[i].generic.callback = DriverCallback;
s_ref_list[i].itemnames = refs;
s_mode_list[i].generic.type = MTYPE_SPINCONTROL;
s_mode_list[i].generic.name = "video mode";
s_mode_list[i].generic.x = 0;
s_mode_list[i].generic.y = 10;
s_mode_list[i].itemnames = resolutions;
s_screensize_slider[i].generic.type = MTYPE_SLIDER;
s_screensize_slider[i].generic.x = 0;
s_screensize_slider[i].generic.y = 20;
s_screensize_slider[i].generic.name = "screen size";
s_screensize_slider[i].minvalue = 3;
s_screensize_slider[i].maxvalue = 12;
s_screensize_slider[i].generic.callback = ScreenSizeCallback;
s_brightness_slider[i].generic.type = MTYPE_SLIDER;
s_brightness_slider[i].generic.x = 0;
s_brightness_slider[i].generic.y = 30;
s_brightness_slider[i].generic.name = "brightness";
s_brightness_slider[i].generic.callback = BrightnessCallback;
s_brightness_slider[i].minvalue = 5;
s_brightness_slider[i].maxvalue = 13;
s_brightness_slider[i].curvalue = ( 1.3 - vid_gamma->value + 0.5 ) * 10;
s_fs_box[i].generic.type = MTYPE_SPINCONTROL;
s_fs_box[i].generic.x = 0;
s_fs_box[i].generic.y = 40;
s_fs_box[i].generic.name = "fullscreen";
s_fs_box[i].itemnames = yesno_names;
s_fs_box[i].curvalue = vid_fullscreen->value;
s_defaults_action[i].generic.type = MTYPE_ACTION;
s_defaults_action[i].generic.name = "reset to default";
s_defaults_action[i].generic.x = 0;
s_defaults_action[i].generic.y = 90;
s_defaults_action[i].generic.callback = ResetDefaults;
s_apply_action[i].generic.type = MTYPE_ACTION;
s_apply_action[i].generic.name = "apply";
s_apply_action[i].generic.x = 0;
s_apply_action[i].generic.y = 100;
s_apply_action[i].generic.callback = ApplyChanges;
}
s_stipple_box.generic.type = MTYPE_SPINCONTROL;
s_stipple_box.generic.x = 0;
s_stipple_box.generic.y = 60;
s_stipple_box.generic.name = "stipple alpha";
s_stipple_box.curvalue = sw_stipplealpha->value;
s_stipple_box.itemnames = yesno_names;
s_windowed_mouse.generic.type = MTYPE_SPINCONTROL;
s_windowed_mouse.generic.x = 0;
s_windowed_mouse.generic.y = 72;
s_windowed_mouse.generic.name = "windowed mouse";
s_windowed_mouse.curvalue = _windowed_mouse->value;
s_windowed_mouse.itemnames = yesno_names;
s_tq_slider.generic.type = MTYPE_SLIDER;
s_tq_slider.generic.x = 0;
s_tq_slider.generic.y = 60;
s_tq_slider.generic.name = "texture quality";
s_tq_slider.minvalue = 0;
s_tq_slider.maxvalue = 3;
s_tq_slider.curvalue = 3-gl_picmip->value;
s_paletted_texture_box.generic.type = MTYPE_SPINCONTROL;
s_paletted_texture_box.generic.x = 0;
s_paletted_texture_box.generic.y = 70;
s_paletted_texture_box.generic.name = "8-bit textures";
s_paletted_texture_box.itemnames = yesno_names;
s_paletted_texture_box.curvalue = gl_ext_palettedtexture->value;
Menu_AddItem( &s_software_menu, ( void * ) &s_ref_list[SOFTWARE_MENU] );
Menu_AddItem( &s_software_menu, ( void * ) &s_mode_list[SOFTWARE_MENU] );
Menu_AddItem( &s_software_menu, ( void * ) &s_screensize_slider[SOFTWARE_MENU] );
Menu_AddItem( &s_software_menu, ( void * ) &s_brightness_slider[SOFTWARE_MENU] );
Menu_AddItem( &s_software_menu, ( void * ) &s_fs_box[SOFTWARE_MENU] );
Menu_AddItem( &s_software_menu, ( void * ) &s_stipple_box );
Menu_AddItem( &s_software_menu, ( void * ) &s_windowed_mouse );
Menu_AddItem( &s_opengl_menu, ( void * ) &s_ref_list[OPENGL_MENU] );
Menu_AddItem( &s_opengl_menu, ( void * ) &s_mode_list[OPENGL_MENU] );
Menu_AddItem( &s_opengl_menu, ( void * ) &s_screensize_slider[OPENGL_MENU] );
Menu_AddItem( &s_opengl_menu, ( void * ) &s_brightness_slider[OPENGL_MENU] );
Menu_AddItem( &s_opengl_menu, ( void * ) &s_fs_box[OPENGL_MENU] );
Menu_AddItem( &s_opengl_menu, ( void * ) &s_tq_slider );
Menu_AddItem( &s_opengl_menu, ( void * ) &s_paletted_texture_box );
Menu_AddItem( &s_software_menu, ( void * ) &s_defaults_action[SOFTWARE_MENU] );
Menu_AddItem( &s_software_menu, ( void * ) &s_apply_action[SOFTWARE_MENU] );
Menu_AddItem( &s_opengl_menu, ( void * ) &s_defaults_action[OPENGL_MENU] );
Menu_AddItem( &s_opengl_menu, ( void * ) &s_apply_action[OPENGL_MENU] );
Menu_Center( &s_software_menu );
Menu_Center( &s_opengl_menu );
s_opengl_menu.x -= 8;
s_software_menu.x -= 8;
}
/*
================
VID_MenuDraw
================
*/
void VID_MenuDraw (void)
{
int w, h;
if ( s_current_menu_index == 0 )
s_current_menu = &s_software_menu;
else
s_current_menu = &s_opengl_menu;
/*
** draw the banner
*/
re.DrawGetPicSize( &w, &h, "m_banner_video" );
re.DrawPic( viddef.width / 2 - w / 2, viddef.height /2 - 110, "m_banner_video" );
/*
** move cursor to a reasonable starting position
*/
Menu_AdjustCursor( s_current_menu, 1 );
/*
** draw the menu
*/
Menu_Draw( s_current_menu );
}
/*
================
VID_MenuKey
================
*/
const char *VID_MenuKey( int key )
{
extern void M_PopMenu( void );
menuframework_s *m = s_current_menu;
static const char *sound = "misc/menu1.wav";
switch ( key )
{
case K_ESCAPE:
M_PopMenu();
return NULL;
case K_UPARROW:
m->cursor--;
Menu_AdjustCursor( m, -1 );
break;
case K_DOWNARROW:
m->cursor++;
Menu_AdjustCursor( m, 1 );
break;
case K_LEFTARROW:
Menu_SlideItem( m, -1 );
break;
case K_RIGHTARROW:
Menu_SlideItem( m, 1 );
break;
case K_ENTER:
Menu_SelectItem( m );
break;
}
return sound;
}

489
linux/vid_so.c Normal file
View File

@ -0,0 +1,489 @@
// Main windowed and fullscreen graphics interface module. This module
// is used for both the software and OpenGL rendering versions of the
// Quake refresh engine.
#define SO_FILE "/etc/quake2.conf"
#include <assert.h>
#include <dlfcn.h> // ELF dl loader
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include "../client/client.h"
#include "../linux/rw_linux.h"
// Structure containing functions exported from refresh DLL
refexport_t re;
// Console variables that we need to access from this module
cvar_t *vid_gamma;
cvar_t *vid_ref; // Name of Refresh DLL loaded
cvar_t *vid_xpos; // X coordinate of window position
cvar_t *vid_ypos; // Y coordinate of window position
cvar_t *vid_fullscreen;
// Global variables used internally by this module
viddef_t viddef; // global video state; used by other modules
void *reflib_library; // Handle to refresh DLL
qboolean reflib_active = 0;
#define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) )
/** KEYBOARD **************************************************************/
void Do_Key_Event(int key, qboolean down);
void (*KBD_Update_fp)(void);
void (*KBD_Init_fp)(Key_Event_fp_t fp);
void (*KBD_Close_fp)(void);
/** MOUSE *****************************************************************/
in_state_t in_state;
void (*RW_IN_Init_fp)(in_state_t *in_state_p);
void (*RW_IN_Shutdown_fp)(void);
void (*RW_IN_Activate_fp)(qboolean active);
void (*RW_IN_Commands_fp)(void);
void (*RW_IN_Move_fp)(usercmd_t *cmd);
void (*RW_IN_Frame_fp)(void);
void Real_IN_Init (void);
/*
==========================================================================
DLL GLUE
==========================================================================
*/
#define MAXPRINTMSG 4096
void VID_Printf (int print_level, char *fmt, ...)
{
va_list argptr;
char msg[MAXPRINTMSG];
static qboolean inupdate;
va_start (argptr,fmt);
vsprintf (msg,fmt,argptr);
va_end (argptr);
if (print_level == PRINT_ALL)
Com_Printf ("%s", msg);
else
Com_DPrintf ("%s", msg);
}
void VID_Error (int err_level, char *fmt, ...)
{
va_list argptr;
char msg[MAXPRINTMSG];
static qboolean inupdate;
va_start (argptr,fmt);
vsprintf (msg,fmt,argptr);
va_end (argptr);
Com_Error (err_level,"%s", msg);
}
//==========================================================================
/*
============
VID_Restart_f
Console command to re-start the video mode and refresh DLL. We do this
simply by setting the modified flag for the vid_ref variable, which will
cause the entire video mode and refresh DLL to be reset on the next frame.
============
*/
void VID_Restart_f (void)
{
vid_ref->modified = true;
}
/*
** VID_GetModeInfo
*/
typedef struct vidmode_s
{
const char *description;
int width, height;
int mode;
} vidmode_t;
vidmode_t vid_modes[] =
{
{ "Mode 0: 320x240", 320, 240, 0 },
{ "Mode 1: 400x300", 400, 300, 1 },
{ "Mode 2: 512x384", 512, 384, 2 },
{ "Mode 3: 640x480", 640, 480, 3 },
{ "Mode 4: 800x600", 800, 600, 4 },
{ "Mode 5: 960x720", 960, 720, 5 },
{ "Mode 6: 1024x768", 1024, 768, 6 },
{ "Mode 7: 1152x864", 1152, 864, 7 },
{ "Mode 8: 1280x1024", 1280, 1024, 8 },
{ "Mode 9: 1600x1200", 1600, 1200, 9 }
};
qboolean VID_GetModeInfo( int *width, int *height, int mode )
{
if ( mode < 0 || mode >= VID_NUM_MODES )
return false;
*width = vid_modes[mode].width;
*height = vid_modes[mode].height;
return true;
}
/*
** VID_NewWindow
*/
void VID_NewWindow ( int width, int height)
{
viddef.width = width;
viddef.height = height;
}
void VID_FreeReflib (void)
{
if (reflib_library) {
if (KBD_Close_fp)
KBD_Close_fp();
if (RW_IN_Shutdown_fp)
RW_IN_Shutdown_fp();
dlclose(reflib_library);
}
KBD_Init_fp = NULL;
KBD_Update_fp = NULL;
KBD_Close_fp = NULL;
RW_IN_Init_fp = NULL;
RW_IN_Shutdown_fp = NULL;
RW_IN_Activate_fp = NULL;
RW_IN_Commands_fp = NULL;
RW_IN_Move_fp = NULL;
RW_IN_Frame_fp = NULL;
memset (&re, 0, sizeof(re));
reflib_library = NULL;
reflib_active = false;
}
/*
==============
VID_LoadRefresh
==============
*/
qboolean VID_LoadRefresh( char *name )
{
refimport_t ri;
GetRefAPI_t GetRefAPI;
char fn[MAX_OSPATH];
struct stat st;
extern uid_t saved_euid;
FILE *fp;
if ( reflib_active )
{
if (KBD_Close_fp)
KBD_Close_fp();
if (RW_IN_Shutdown_fp)
RW_IN_Shutdown_fp();
KBD_Close_fp = NULL;
RW_IN_Shutdown_fp = NULL;
re.Shutdown();
VID_FreeReflib ();
}
Com_Printf( "------- Loading %s -------\n", name );
//regain root
seteuid(saved_euid);
if ((fp = fopen(SO_FILE, "r")) == NULL) {
Com_Printf( "LoadLibrary(\"%s\") failed: can't open " SO_FILE " (required for location of ref libraries)\n", name);
return false;
}
fgets(fn, sizeof(fn), fp);
fclose(fp);
if (*fn && fn[strlen(fn) - 1] == '\n')
fn[strlen(fn) - 1] = 0;
strcat(fn, "/");
strcat(fn, name);
// permission checking
if (strstr(fn, "softx") == NULL) { // softx doesn't require root
if (stat(fn, &st) == -1) {
Com_Printf( "LoadLibrary(\"%s\") failed: %s\n", name, strerror(errno));
return false;
}
if (st.st_uid != 0) {
Com_Printf( "LoadLibrary(\"%s\") failed: ref is not owned by root\n", name);
return false;
}
#if 0
if ((st.st_mode & 0777) & ~0700) {
Com_Printf( "LoadLibrary(\"%s\") failed: invalid permissions, must be 700 for security considerations\n", name);
return false;
}
#endif
} else {
// softx requires we give up root now
setreuid(getuid(), getuid());
setegid(getgid());
}
if ( ( reflib_library = dlopen( fn, RTLD_NOW ) ) == 0 )
{
Com_Printf( "LoadLibrary(\"%s\") failed: %s\n", name , dlerror());
return false;
}
ri.Cmd_AddCommand = Cmd_AddCommand;
ri.Cmd_RemoveCommand = Cmd_RemoveCommand;
ri.Cmd_Argc = Cmd_Argc;
ri.Cmd_Argv = Cmd_Argv;
ri.Cmd_ExecuteText = Cbuf_ExecuteText;
ri.Con_Printf = VID_Printf;
ri.Sys_Error = VID_Error;
ri.FS_LoadFile = FS_LoadFile;
ri.FS_FreeFile = FS_FreeFile;
ri.FS_Gamedir = FS_Gamedir;
ri.Cvar_Get = Cvar_Get;
ri.Cvar_Set = Cvar_Set;
ri.Cvar_SetValue = Cvar_SetValue;
ri.Vid_GetModeInfo = VID_GetModeInfo;
ri.Vid_MenuInit = VID_MenuInit;
ri.Vid_NewWindow = VID_NewWindow;
if ( ( GetRefAPI = (void *) dlsym( reflib_library, "GetRefAPI" ) ) == 0 )
Com_Error( ERR_FATAL, "dlsym failed on %s", name );
re = GetRefAPI( ri );
if (re.api_version != API_VERSION)
{
VID_FreeReflib ();
Com_Error (ERR_FATAL, "%s has incompatible api_version", name);
}
/* Init IN (Mouse) */
in_state.IN_CenterView_fp = IN_CenterView;
in_state.Key_Event_fp = Do_Key_Event;
in_state.viewangles = cl.viewangles;
in_state.in_strafe_state = &in_strafe.state;
if ((RW_IN_Init_fp = dlsym(reflib_library, "RW_IN_Init")) == NULL ||
(RW_IN_Shutdown_fp = dlsym(reflib_library, "RW_IN_Shutdown")) == NULL ||
(RW_IN_Activate_fp = dlsym(reflib_library, "RW_IN_Activate")) == NULL ||
(RW_IN_Commands_fp = dlsym(reflib_library, "RW_IN_Commands")) == NULL ||
(RW_IN_Move_fp = dlsym(reflib_library, "RW_IN_Move")) == NULL ||
(RW_IN_Frame_fp = dlsym(reflib_library, "RW_IN_Frame")) == NULL)
Sys_Error("No RW_IN functions in REF.\n");
Real_IN_Init();
if ( re.Init( 0, 0 ) == -1 )
{
re.Shutdown();
VID_FreeReflib ();
return false;
}
/* Init KBD */
#if 1
if ((KBD_Init_fp = dlsym(reflib_library, "KBD_Init")) == NULL ||
(KBD_Update_fp = dlsym(reflib_library, "KBD_Update")) == NULL ||
(KBD_Close_fp = dlsym(reflib_library, "KBD_Close")) == NULL)
Sys_Error("No KBD functions in REF.\n");
#else
{
void KBD_Init(void);
void KBD_Update(void);
void KBD_Close(void);
KBD_Init_fp = KBD_Init;
KBD_Update_fp = KBD_Update;
KBD_Close_fp = KBD_Close;
}
#endif
KBD_Init_fp(Do_Key_Event);
// give up root now
setreuid(getuid(), getuid());
setegid(getgid());
Com_Printf( "------------------------------------\n");
reflib_active = true;
return true;
}
/*
============
VID_CheckChanges
This function gets called once just before drawing each frame, and it's sole purpose in life
is to check to see if any of the video mode parameters have changed, and if they have to
update the rendering DLL and/or video mode to match.
============
*/
void VID_CheckChanges (void)
{
char name[100];
cvar_t *sw_mode;
if ( vid_ref->modified )
{
S_StopAllSounds();
}
while (vid_ref->modified)
{
/*
** refresh has changed
*/
vid_ref->modified = false;
vid_fullscreen->modified = true;
cl.refresh_prepped = false;
cls.disable_screen = true;
sprintf( name, "ref_%s.so", vid_ref->string );
if ( !VID_LoadRefresh( name ) )
{
if ( strcmp (vid_ref->string, "soft") == 0 ||
strcmp (vid_ref->string, "softx") == 0 ) {
Com_Printf("Refresh failed\n");
sw_mode = Cvar_Get( "sw_mode", "0", 0 );
if (sw_mode->value != 0) {
Com_Printf("Trying mode 0\n");
Cvar_SetValue("sw_mode", 0);
if ( !VID_LoadRefresh( name ) )
Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!");
} else
Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!");
}
Cvar_Set( "vid_ref", "soft" );
/*
** drop the console if we fail to load a refresh
*/
if ( cls.key_dest != key_console )
{
Con_ToggleConsole_f();
}
}
cls.disable_screen = false;
}
}
/*
============
VID_Init
============
*/
void VID_Init (void)
{
/* Create the video variables so we know how to start the graphics drivers */
// if DISPLAY is defined, try X
if (getenv("DISPLAY"))
vid_ref = Cvar_Get ("vid_ref", "softx", CVAR_ARCHIVE);
else
vid_ref = Cvar_Get ("vid_ref", "soft", CVAR_ARCHIVE);
vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE);
vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE);
vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE);
vid_gamma = Cvar_Get( "vid_gamma", "1", CVAR_ARCHIVE );
/* Add some console commands that we want to handle */
Cmd_AddCommand ("vid_restart", VID_Restart_f);
/* Disable the 3Dfx splash screen */
putenv("FX_GLIDE_NO_SPLASH=0");
/* Start the graphics mode and load refresh DLL */
VID_CheckChanges();
}
/*
============
VID_Shutdown
============
*/
void VID_Shutdown (void)
{
if ( reflib_active )
{
if (KBD_Close_fp)
KBD_Close_fp();
if (RW_IN_Shutdown_fp)
RW_IN_Shutdown_fp();
KBD_Close_fp = NULL;
RW_IN_Shutdown_fp = NULL;
re.Shutdown ();
VID_FreeReflib ();
}
}
/*****************************************************************************/
/* INPUT */
/*****************************************************************************/
cvar_t *in_joystick;
// This if fake, it's acutally done by the Refresh load
void IN_Init (void)
{
in_joystick = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE);
}
void Real_IN_Init (void)
{
if (RW_IN_Init_fp)
RW_IN_Init_fp(&in_state);
}
void IN_Shutdown (void)
{
if (RW_IN_Shutdown_fp)
RW_IN_Shutdown_fp();
}
void IN_Commands (void)
{
if (RW_IN_Commands_fp)
RW_IN_Commands_fp();
}
void IN_Move (usercmd_t *cmd)
{
if (RW_IN_Move_fp)
RW_IN_Move_fp(cmd);
}
void IN_Frame (void)
{
if (RW_IN_Frame_fp)
RW_IN_Frame_fp();
}
void IN_Activate (qboolean active)
{
if (RW_IN_Activate_fp)
RW_IN_Activate_fp(active);
}
void Do_Key_Event(int key, qboolean down)
{
Key_Event(key, down, Sys_Milliseconds());
}

31
null/cd_null.c Normal file
View File

@ -0,0 +1,31 @@
#include "../client/client.h"
void CDAudio_Play(int track, qboolean looping)
{
}
void CDAudio_Stop(void)
{
}
void CDAudio_Resume(void)
{
}
void CDAudio_Update(void)
{
}
int CDAudio_Init(void)
{
return 0;
}
void CDAudio_Shutdown(void)
{
}

55
null/cl_null.c Normal file
View File

@ -0,0 +1,55 @@
// cl_null.c -- this file can stub out the entire client system
// for pure dedicated servers
#include "../qcommon/qcommon.h"
void Key_Bind_Null_f(void)
{
}
void CL_Init (void)
{
}
void CL_Drop (void)
{
}
void CL_Shutdown (void)
{
}
void CL_Frame (int msec)
{
}
void Con_Print (char *text)
{
}
void Cmd_ForwardToServer (void)
{
char *cmd;
cmd = Cmd_Argv(0);
Com_Printf ("Unknown command \"%s\"\n", cmd);
}
void SCR_DebugGraph (float value, int color)
{
}
void SCR_BeginLoadingPlaque (void)
{
}
void SCR_EndLoadingPlaque (void)
{
}
void Key_Init (void)
{
Cmd_AddCommand ("bind", Key_Bind_Null_f);
}

34
null/glimp_null.c Normal file
View File

@ -0,0 +1,34 @@
#include "../ref_gl/gl_local.h"
void GLimp_BeginFrame( float camera_separation )
{
}
void GLimp_EndFrame( void )
{
}
int GLimp_Init( void *hinstance, void *hWnd )
{
}
void GLimp_Shutdown( void )
{
}
int GLimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
{
}
void GLimp_AppActivate( qboolean active )
{
}
void GLimp_EnableLogging( qboolean enable )
{
}
void GLimp_LogNewFrame( void )
{
}

36
null/in_null.c Normal file
View File

@ -0,0 +1,36 @@
// in_null.c -- for systems without a mouse
#include "../client/client.h"
void IN_Init (void)
{
}
void IN_Shutdown (void)
{
}
void IN_Commands (void)
{
}
void IN_Frame (void)
{
}
void IN_Move (usercmd_t *cmd)
{
}
void IN_Activate (qboolean active)
{
}
void IN_ActivateMouse (void)
{
}
void IN_DeactivateMouse (void)
{
}

28
null/snddma_null.c Normal file
View File

@ -0,0 +1,28 @@
// snddma_null.c
// all other sound mixing is portable
#include "../client/client.h"
#include "../client/snd_loc.h"
qboolean SNDDMA_Init(void)
{
return false;
}
int SNDDMA_GetDMAPos(void)
{
return 0;
}
void SNDDMA_Shutdown(void)
{
}
void SNDDMA_BeginPainting (void)
{
}
void SNDDMA_Submit(void)
{
}

30
null/swimp_null.c Normal file
View File

@ -0,0 +1,30 @@
#include "../ref_soft/r_local.h"
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 )
{
}

127
null/sys_null.c Normal file
View File

@ -0,0 +1,127 @@
// sys_null.h -- null system driver to aid porting efforts
#include "../qcommon/qcommon.h"
#include "errno.h"
int curtime;
unsigned sys_frame_time;
void Sys_mkdir (char *path)
{
}
void Sys_Error (char *error, ...)
{
va_list argptr;
printf ("Sys_Error: ");
va_start (argptr,error);
vprintf (error,argptr);
va_end (argptr);
printf ("\n");
exit (1);
}
void Sys_Quit (void)
{
exit (0);
}
void Sys_UnloadGame (void)
{
}
void *Sys_GetGameAPI (void *parms)
{
return NULL;
}
char *Sys_ConsoleInput (void)
{
return NULL;
}
void Sys_ConsoleOutput (char *string)
{
}
void Sys_SendKeyEvents (void)
{
}
void Sys_AppActivate (void)
{
}
void Sys_CopyProtect (void)
{
}
char *Sys_GetClipboardData( void )
{
return NULL;
}
void *Hunk_Begin (int maxsize)
{
return NULL;
}
void *Hunk_Alloc (int size)
{
return NULL;
}
void Hunk_Free (void *buf)
{
}
int Hunk_End (void)
{
return 0;
}
int Sys_Milliseconds (void)
{
return 0;
}
void Sys_Mkdir (char *path)
{
}
char *Sys_FindFirst (char *path, unsigned musthave, unsigned canthave)
{
return NULL;
}
char *Sys_FindNext (unsigned musthave, unsigned canthave)
{
return NULL;
}
void Sys_FindClose (void)
{
}
void Sys_Init (void)
{
}
//=============================================================================
void main (int argc, char **argv)
{
Qcommon_Init (argc, argv);
while (1)
{
Qcommon_Frame (0.1);
}
}

145
null/vid_null.c Normal file
View File

@ -0,0 +1,145 @@
// vid_null.c -- null video driver to aid porting efforts
// this assumes that one of the refs is statically linked to the executable
#include "../client/client.h"
viddef_t viddef; // global video state
refexport_t re;
refexport_t GetRefAPI (refimport_t rimp);
/*
==========================================================================
DIRECT LINK GLUE
==========================================================================
*/
#define MAXPRINTMSG 4096
void VID_Printf (int print_level, char *fmt, ...)
{
va_list argptr;
char msg[MAXPRINTMSG];
va_start (argptr,fmt);
vsprintf (msg,fmt,argptr);
va_end (argptr);
if (print_level == PRINT_ALL)
Com_Printf ("%s", msg);
else
Com_DPrintf ("%s", msg);
}
void VID_Error (int err_level, char *fmt, ...)
{
va_list argptr;
char msg[MAXPRINTMSG];
va_start (argptr,fmt);
vsprintf (msg,fmt,argptr);
va_end (argptr);
Com_Error (err_level, "%s", msg);
}
void VID_NewWindow (int width, int height)
{
viddef.width = width;
viddef.height = height;
}
/*
** VID_GetModeInfo
*/
typedef struct vidmode_s
{
const char *description;
int width, height;
int mode;
} vidmode_t;
vidmode_t vid_modes[] =
{
{ "Mode 0: 320x240", 320, 240, 0 },
{ "Mode 1: 400x300", 400, 300, 1 },
{ "Mode 2: 512x384", 512, 384, 2 },
{ "Mode 3: 640x480", 640, 480, 3 },
{ "Mode 4: 800x600", 800, 600, 4 },
{ "Mode 5: 960x720", 960, 720, 5 },
{ "Mode 6: 1024x768", 1024, 768, 6 },
{ "Mode 7: 1152x864", 1152, 864, 7 },
{ "Mode 8: 1280x960", 1280, 960, 8 },
{ "Mode 9: 1600x1200", 1600, 1200, 9 }
};
#define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) )
qboolean VID_GetModeInfo( int *width, int *height, int mode )
{
if ( mode < 0 || mode >= VID_NUM_MODES )
return false;
*width = vid_modes[mode].width;
*height = vid_modes[mode].height;
return true;
}
void VID_Init (void)
{
refimport_t ri;
viddef.width = 320;
viddef.height = 240;
ri.Cmd_AddCommand = Cmd_AddCommand;
ri.Cmd_RemoveCommand = Cmd_RemoveCommand;
ri.Cmd_Argc = Cmd_Argc;
ri.Cmd_Argv = Cmd_Argv;
ri.Cmd_ExecuteText = Cbuf_ExecuteText;
ri.Con_Printf = VID_Printf;
ri.Sys_Error = VID_Error;
ri.FS_LoadFile = FS_LoadFile;
ri.FS_FreeFile = FS_FreeFile;
ri.FS_Gamedir = FS_Gamedir;
ri.Vid_NewWindow = VID_NewWindow;
ri.Cvar_Get = Cvar_Get;
ri.Cvar_Set = Cvar_Set;
ri.Cvar_SetValue = Cvar_SetValue;
ri.Vid_GetModeInfo = VID_GetModeInfo;
re = GetRefAPI(ri);
if (re.api_version != API_VERSION)
Com_Error (ERR_FATAL, "Re has incompatible api_version");
// call the init function
if (re.Init (NULL, NULL) == -1)
Com_Error (ERR_FATAL, "Couldn't start refresh");
}
void VID_Shutdown (void)
{
if (re.Shutdown)
re.Shutdown ();
}
void VID_CheckChanges (void)
{
}
void VID_MenuInit (void)
{
}
void VID_MenuDraw (void)
{
}
const char *VID_MenuKey( int k)
{
return NULL;
}

892
qcommon/cmd.c Normal file
View File

@ -0,0 +1,892 @@
/*
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.
*/
// cmd.c -- Quake script command processing module
#include "qcommon.h"
void Cmd_ForwardToServer (void);
#define MAX_ALIAS_NAME 32
typedef struct cmdalias_s
{
struct cmdalias_s *next;
char name[MAX_ALIAS_NAME];
char *value;
} cmdalias_t;
cmdalias_t *cmd_alias;
qboolean cmd_wait;
#define ALIAS_LOOP_COUNT 16
int alias_count; // for detecting runaway loops
//=============================================================================
/*
============
Cmd_Wait_f
Causes execution of the remainder of the command buffer to be delayed until
next frame. This allows commands like:
bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2"
============
*/
void Cmd_Wait_f (void)
{
cmd_wait = true;
}
/*
=============================================================================
COMMAND BUFFER
=============================================================================
*/
sizebuf_t cmd_text;
byte cmd_text_buf[8192];
byte defer_text_buf[8192];
/*
============
Cbuf_Init
============
*/
void Cbuf_Init (void)
{
SZ_Init (&cmd_text, cmd_text_buf, sizeof(cmd_text_buf));
}
/*
============
Cbuf_AddText
Adds command text at the end of the buffer
============
*/
void Cbuf_AddText (char *text)
{
int l;
l = strlen (text);
if (cmd_text.cursize + l >= cmd_text.maxsize)
{
Com_Printf ("Cbuf_AddText: overflow\n");
return;
}
SZ_Write (&cmd_text, text, strlen (text));
}
/*
============
Cbuf_InsertText
Adds command text immediately after the current command
Adds a \n to the text
FIXME: actually change the command buffer to do less copying
============
*/
void Cbuf_InsertText (char *text)
{
char *temp;
int templen;
// copy off any commands still remaining in the exec buffer
templen = cmd_text.cursize;
if (templen)
{
temp = Z_Malloc (templen);
memcpy (temp, cmd_text.data, templen);
SZ_Clear (&cmd_text);
}
else
temp = NULL; // shut up compiler
// add the entire text of the file
Cbuf_AddText (text);
// add the copied off data
if (templen)
{
SZ_Write (&cmd_text, temp, templen);
Z_Free (temp);
}
}
/*
============
Cbuf_CopyToDefer
============
*/
void Cbuf_CopyToDefer (void)
{
memcpy(defer_text_buf, cmd_text_buf, cmd_text.cursize);
defer_text_buf[cmd_text.cursize] = 0;
cmd_text.cursize = 0;
}
/*
============
Cbuf_InsertFromDefer
============
*/
void Cbuf_InsertFromDefer (void)
{
Cbuf_InsertText (defer_text_buf);
defer_text_buf[0] = 0;
}
/*
============
Cbuf_ExecuteText
============
*/
void Cbuf_ExecuteText (int exec_when, char *text)
{
switch (exec_when)
{
case EXEC_NOW:
Cmd_ExecuteString (text);
break;
case EXEC_INSERT:
Cbuf_InsertText (text);
break;
case EXEC_APPEND:
Cbuf_AddText (text);
break;
default:
Com_Error (ERR_FATAL, "Cbuf_ExecuteText: bad exec_when");
}
}
/*
============
Cbuf_Execute
============
*/
void Cbuf_Execute (void)
{
int i;
char *text;
char line[1024];
int quotes;
alias_count = 0; // don't allow infinite alias loops
while (cmd_text.cursize)
{
// find a \n or ; line break
text = (char *)cmd_text.data;
quotes = 0;
for (i=0 ; i< cmd_text.cursize ; i++)
{
if (text[i] == '"')
quotes++;
if ( !(quotes&1) && text[i] == ';')
break; // don't break if inside a quoted string
if (text[i] == '\n')
break;
}
memcpy (line, text, i);
line[i] = 0;
// delete the text from the command buffer and move remaining commands down
// this is necessary because commands (exec, alias) can insert data at the
// beginning of the text buffer
if (i == cmd_text.cursize)
cmd_text.cursize = 0;
else
{
i++;
cmd_text.cursize -= i;
memmove (text, text+i, cmd_text.cursize);
}
// execute the command line
Cmd_ExecuteString (line);
if (cmd_wait)
{
// skip out while text still remains in buffer, leaving it
// for next frame
cmd_wait = false;
break;
}
}
}
/*
===============
Cbuf_AddEarlyCommands
Adds command line parameters as script statements
Commands lead with a +, and continue until another +
Set commands are added early, so they are guaranteed to be set before
the client and server initialize for the first time.
Other commands are added late, after all initialization is complete.
===============
*/
void Cbuf_AddEarlyCommands (qboolean clear)
{
int i;
char *s;
for (i=0 ; i<COM_Argc() ; i++)
{
s = COM_Argv(i);
if (strcmp (s, "+set"))
continue;
Cbuf_AddText (va("set %s %s\n", COM_Argv(i+1), COM_Argv(i+2)));
if (clear)
{
COM_ClearArgv(i);
COM_ClearArgv(i+1);
COM_ClearArgv(i+2);
}
i+=2;
}
}
/*
=================
Cbuf_AddLateCommands
Adds command line parameters as script statements
Commands lead with a + and continue until another + or -
quake +vid_ref gl +map amlev1
Returns true if any late commands were added, which
will keep the demoloop from immediately starting
=================
*/
qboolean Cbuf_AddLateCommands (void)
{
int i, j;
int s;
char *text, *build, c;
int argc;
qboolean ret;
// build the combined string to parse from
s = 0;
argc = COM_Argc();
for (i=1 ; i<argc ; i++)
{
s += strlen (COM_Argv(i)) + 1;
}
if (!s)
return false;
text = Z_Malloc (s+1);
text[0] = 0;
for (i=1 ; i<argc ; i++)
{
strcat (text,COM_Argv(i));
if (i != argc-1)
strcat (text, " ");
}
// pull out the commands
build = Z_Malloc (s+1);
build[0] = 0;
for (i=0 ; i<s-1 ; i++)
{
if (text[i] == '+')
{
i++;
for (j=i ; (text[j] != '+') && (text[j] != '-') && (text[j] != 0) ; j++)
;
c = text[j];
text[j] = 0;
strcat (build, text+i);
strcat (build, "\n");
text[j] = c;
i = j-1;
}
}
ret = (build[0] != 0);
if (ret)
Cbuf_AddText (build);
Z_Free (text);
Z_Free (build);
return ret;
}
/*
==============================================================================
SCRIPT COMMANDS
==============================================================================
*/
/*
===============
Cmd_Exec_f
===============
*/
void Cmd_Exec_f (void)
{
char *f, *f2;
int len;
if (Cmd_Argc () != 2)
{
Com_Printf ("exec <filename> : execute a script file\n");
return;
}
len = FS_LoadFile (Cmd_Argv(1), (void **)&f);
if (!f)
{
Com_Printf ("couldn't exec %s\n",Cmd_Argv(1));
return;
}
Com_Printf ("execing %s\n",Cmd_Argv(1));
// the file doesn't have a trailing 0, so we need to copy it off
f2 = Z_Malloc(len+1);
memcpy (f2, f, len);
f2[len] = 0;
Cbuf_InsertText (f2);
Z_Free (f2);
FS_FreeFile (f);
}
/*
===============
Cmd_Echo_f
Just prints the rest of the line to the console
===============
*/
void Cmd_Echo_f (void)
{
int i;
for (i=1 ; i<Cmd_Argc() ; i++)
Com_Printf ("%s ",Cmd_Argv(i));
Com_Printf ("\n");
}
/*
===============
Cmd_Alias_f
Creates a new command that executes a command string (possibly ; seperated)
===============
*/
void Cmd_Alias_f (void)
{
cmdalias_t *a;
char cmd[1024];
int i, c;
char *s;
if (Cmd_Argc() == 1)
{
Com_Printf ("Current alias commands:\n");
for (a = cmd_alias ; a ; a=a->next)
Com_Printf ("%s : %s\n", a->name, a->value);
return;
}
s = Cmd_Argv(1);
if (strlen(s) >= MAX_ALIAS_NAME)
{
Com_Printf ("Alias name is too long\n");
return;
}
// if the alias already exists, reuse it
for (a = cmd_alias ; a ; a=a->next)
{
if (!strcmp(s, a->name))
{
Z_Free (a->value);
break;
}
}
if (!a)
{
a = Z_Malloc (sizeof(cmdalias_t));
a->next = cmd_alias;
cmd_alias = a;
}
strcpy (a->name, s);
// copy the rest of the command line
cmd[0] = 0; // start out with a null string
c = Cmd_Argc();
for (i=2 ; i< c ; i++)
{
strcat (cmd, Cmd_Argv(i));
if (i != (c - 1))
strcat (cmd, " ");
}
strcat (cmd, "\n");
a->value = CopyString (cmd);
}
/*
=============================================================================
COMMAND EXECUTION
=============================================================================
*/
typedef struct cmd_function_s
{
struct cmd_function_s *next;
char *name;
xcommand_t function;
} cmd_function_t;
static int cmd_argc;
static char *cmd_argv[MAX_STRING_TOKENS];
static char *cmd_null_string = "";
static char cmd_args[MAX_STRING_CHARS];
static cmd_function_t *cmd_functions; // possible commands to execute
/*
============
Cmd_Argc
============
*/
int Cmd_Argc (void)
{
return cmd_argc;
}
/*
============
Cmd_Argv
============
*/
char *Cmd_Argv (int arg)
{
if ( (unsigned)arg >= cmd_argc )
return cmd_null_string;
return cmd_argv[arg];
}
/*
============
Cmd_Args
Returns a single string containing argv(1) to argv(argc()-1)
============
*/
char *Cmd_Args (void)
{
return cmd_args;
}
/*
======================
Cmd_MacroExpandString
======================
*/
char *Cmd_MacroExpandString (char *text)
{
int i, j, count, len;
qboolean inquote;
char *scan;
static char expanded[MAX_STRING_CHARS];
char temporary[MAX_STRING_CHARS];
char *token, *start;
inquote = false;
scan = text;
len = strlen (scan);
if (len >= MAX_STRING_CHARS)
{
Com_Printf ("Line exceeded %i chars, discarded.\n", MAX_STRING_CHARS);
return NULL;
}
count = 0;
for (i=0 ; i<len ; i++)
{
if (scan[i] == '"')
inquote ^= 1;
if (inquote)
continue; // don't expand inside quotes
if (scan[i] != '$')
continue;
// scan out the complete macro
start = scan+i+1;
token = COM_Parse (&start);
if (!start)
continue;
token = Cvar_VariableString (token);
j = strlen(token);
len += j;
if (len >= MAX_STRING_CHARS)
{
Com_Printf ("Expanded line exceeded %i chars, discarded.\n", MAX_STRING_CHARS);
return NULL;
}
strncpy (temporary, scan, i);
strcpy (temporary+i, token);
strcpy (temporary+i+j, start);
strcpy (expanded, temporary);
scan = expanded;
i--;
if (++count == 100)
{
Com_Printf ("Macro expansion loop, discarded.\n");
return NULL;
}
}
if (inquote)
{
Com_Printf ("Line has unmatched quote, discarded.\n");
return NULL;
}
return scan;
}
/*
============
Cmd_TokenizeString
Parses the given string into command line tokens.
$Cvars will be expanded unless they are in a quoted token
============
*/
void Cmd_TokenizeString (char *text, qboolean macroExpand)
{
int i;
char *com_token;
// clear the args from the last string
for (i=0 ; i<cmd_argc ; i++)
Z_Free (cmd_argv[i]);
cmd_argc = 0;
cmd_args[0] = 0;
// macro expand the text
if (macroExpand)
text = Cmd_MacroExpandString (text);
if (!text)
return;
while (1)
{
// skip whitespace up to a /n
while (*text && *text <= ' ' && *text != '\n')
{
text++;
}
if (*text == '\n')
{ // a newline seperates commands in the buffer
text++;
break;
}
if (!*text)
return;
// set cmd_args to everything after the first arg
if (cmd_argc == 1)
{
int l;
strcpy (cmd_args, text);
// strip off any trailing whitespace
l = strlen(cmd_args) - 1;
for ( ; l >= 0 ; l--)
if (cmd_args[l] <= ' ')
cmd_args[l] = 0;
else
break;
}
com_token = COM_Parse (&text);
if (!text)
return;
if (cmd_argc < MAX_STRING_TOKENS)
{
cmd_argv[cmd_argc] = Z_Malloc (strlen(com_token)+1);
strcpy (cmd_argv[cmd_argc], com_token);
cmd_argc++;
}
}
}
/*
============
Cmd_AddCommand
============
*/
void Cmd_AddCommand (char *cmd_name, xcommand_t function)
{
cmd_function_t *cmd;
// fail if the command is a variable name
if (Cvar_VariableString(cmd_name)[0])
{
Com_Printf ("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
return;
}
// fail if the command already exists
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
{
if (!strcmp (cmd_name, cmd->name))
{
Com_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name);
return;
}
}
cmd = Z_Malloc (sizeof(cmd_function_t));
cmd->name = cmd_name;
cmd->function = function;
cmd->next = cmd_functions;
cmd_functions = cmd;
}
/*
============
Cmd_RemoveCommand
============
*/
void Cmd_RemoveCommand (char *cmd_name)
{
cmd_function_t *cmd, **back;
back = &cmd_functions;
while (1)
{
cmd = *back;
if (!cmd)
{
Com_Printf ("Cmd_RemoveCommand: %s not added\n", cmd_name);
return;
}
if (!strcmp (cmd_name, cmd->name))
{
*back = cmd->next;
Z_Free (cmd);
return;
}
back = &cmd->next;
}
}
/*
============
Cmd_Exists
============
*/
qboolean Cmd_Exists (char *cmd_name)
{
cmd_function_t *cmd;
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
{
if (!strcmp (cmd_name,cmd->name))
return true;
}
return false;
}
/*
============
Cmd_CompleteCommand
============
*/
char *Cmd_CompleteCommand (char *partial)
{
cmd_function_t *cmd;
int len;
cmdalias_t *a;
len = strlen(partial);
if (!len)
return NULL;
// check for exact match
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
if (!strcmp (partial,cmd->name))
return cmd->name;
for (a=cmd_alias ; a ; a=a->next)
if (!strcmp (partial, a->name))
return a->name;
// check for partial match
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
if (!strncmp (partial,cmd->name, len))
return cmd->name;
for (a=cmd_alias ; a ; a=a->next)
if (!strncmp (partial, a->name, len))
return a->name;
return NULL;
}
/*
============
Cmd_ExecuteString
A complete command line has been parsed, so try to execute it
FIXME: lookupnoadd the token to speed search?
============
*/
void Cmd_ExecuteString (char *text)
{
cmd_function_t *cmd;
cmdalias_t *a;
Cmd_TokenizeString (text, true);
// execute the command line
if (!Cmd_Argc())
return; // no tokens
// check functions
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
{
if (!Q_strcasecmp (cmd_argv[0],cmd->name))
{
if (!cmd->function)
{ // forward to server command
Cmd_ExecuteString (va("cmd %s", text));
}
else
cmd->function ();
return;
}
}
// check alias
for (a=cmd_alias ; a ; a=a->next)
{
if (!Q_strcasecmp (cmd_argv[0], a->name))
{
if (++alias_count == ALIAS_LOOP_COUNT)
{
Com_Printf ("ALIAS_LOOP_COUNT\n");
return;
}
Cbuf_InsertText (a->value);
return;
}
}
// check cvars
if (Cvar_Command ())
return;
// send it as a server command if we are connected
Cmd_ForwardToServer ();
}
/*
============
Cmd_List_f
============
*/
void Cmd_List_f (void)
{
cmd_function_t *cmd;
int i;
i = 0;
for (cmd=cmd_functions ; cmd ; cmd=cmd->next, i++)
Com_Printf ("%s\n", cmd->name);
Com_Printf ("%i commands\n", i);
}
/*
============
Cmd_Init
============
*/
void Cmd_Init (void)
{
//
// register our commands
//
Cmd_AddCommand ("cmdlist",Cmd_List_f);
Cmd_AddCommand ("exec",Cmd_Exec_f);
Cmd_AddCommand ("echo",Cmd_Echo_f);
Cmd_AddCommand ("alias",Cmd_Alias_f);
Cmd_AddCommand ("wait", Cmd_Wait_f);
}

1770
qcommon/cmodel.c Normal file

File diff suppressed because it is too large Load Diff

1588
qcommon/common.c Normal file

File diff suppressed because it is too large Load Diff

92
qcommon/crc.c Normal file
View File

@ -0,0 +1,92 @@
/*
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.
*/
/* crc.c */
#include "qcommon.h"
// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
// and the initial and final xor values shown below... in other words, the
// CCITT standard CRC used by XMODEM
#define CRC_INIT_VALUE 0xffff
#define CRC_XOR_VALUE 0x0000
static unsigned short crctable[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
void CRC_Init(unsigned short *crcvalue)
{
*crcvalue = CRC_INIT_VALUE;
}
void CRC_ProcessByte(unsigned short *crcvalue, byte data)
{
*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
}
unsigned short CRC_Value(unsigned short crcvalue)
{
return crcvalue ^ CRC_XOR_VALUE;
}
unsigned short CRC_Block (byte *start, int count)
{
unsigned short crc;
CRC_Init (&crc);
while (count--)
crc = (crc << 8) ^ crctable[(crc >> 8) ^ *start++];
return crc;
}

6
qcommon/crc.h Normal file
View File

@ -0,0 +1,6 @@
/* crc.h */
void CRC_Init(unsigned short *crcvalue);
void CRC_ProcessByte(unsigned short *crcvalue, byte data);
unsigned short CRC_Value(unsigned short crcvalue);
unsigned short CRC_Block (byte *start, int count);

527
qcommon/cvar.c Normal file
View File

@ -0,0 +1,527 @@
/*
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.
*/
// cvar.c -- dynamic variable tracking
#include "qcommon.h"
cvar_t *cvar_vars;
/*
============
Cvar_InfoValidate
============
*/
static qboolean Cvar_InfoValidate (char *s)
{
if (strstr (s, "\\"))
return false;
if (strstr (s, "\""))
return false;
if (strstr (s, ";"))
return false;
return true;
}
/*
============
Cvar_FindVar
============
*/
static cvar_t *Cvar_FindVar (char *var_name)
{
cvar_t *var;
for (var=cvar_vars ; var ; var=var->next)
if (!strcmp (var_name, var->name))
return var;
return NULL;
}
/*
============
Cvar_VariableValue
============
*/
float Cvar_VariableValue (char *var_name)
{
cvar_t *var;
var = Cvar_FindVar (var_name);
if (!var)
return 0;
return atof (var->string);
}
/*
============
Cvar_VariableString
============
*/
char *Cvar_VariableString (char *var_name)
{
cvar_t *var;
var = Cvar_FindVar (var_name);
if (!var)
return "";
return var->string;
}
/*
============
Cvar_CompleteVariable
============
*/
char *Cvar_CompleteVariable (char *partial)
{
cvar_t *cvar;
int len;
len = strlen(partial);
if (!len)
return NULL;
// check exact match
for (cvar=cvar_vars ; cvar ; cvar=cvar->next)
if (!strcmp (partial,cvar->name))
return cvar->name;
// check partial match
for (cvar=cvar_vars ; cvar ; cvar=cvar->next)
if (!strncmp (partial,cvar->name, len))
return cvar->name;
return NULL;
}
/*
============
Cvar_Get
If the variable already exists, the value will not be set
The flags will be or'ed in if the variable exists.
============
*/
cvar_t *Cvar_Get (char *var_name, char *var_value, int flags)
{
cvar_t *var;
if (flags & (CVAR_USERINFO | CVAR_SERVERINFO))
{
if (!Cvar_InfoValidate (var_name))
{
Com_Printf("invalid info cvar name\n");
return NULL;
}
}
var = Cvar_FindVar (var_name);
if (var)
{
var->flags |= flags;
return var;
}
if (!var_value)
return NULL;
if (flags & (CVAR_USERINFO | CVAR_SERVERINFO))
{
if (!Cvar_InfoValidate (var_value))
{
Com_Printf("invalid info cvar value\n");
return NULL;
}
}
var = Z_Malloc (sizeof(*var));
var->name = CopyString (var_name);
var->string = CopyString (var_value);
var->modified = true;
var->value = atof (var->string);
// link the variable in
var->next = cvar_vars;
cvar_vars = var;
var->flags = flags;
return var;
}
/*
============
Cvar_Set2
============
*/
cvar_t *Cvar_Set2 (char *var_name, char *value, qboolean force)
{
cvar_t *var;
var = Cvar_FindVar (var_name);
if (!var)
{ // create it
return Cvar_Get (var_name, value, 0);
}
if (var->flags & (CVAR_USERINFO | CVAR_SERVERINFO))
{
if (!Cvar_InfoValidate (value))
{
Com_Printf("invalid info cvar value\n");
return var;
}
}
if (!force)
{
if (var->flags & CVAR_NOSET)
{
Com_Printf ("%s is write protected.\n", var_name);
return var;
}
if (var->flags & CVAR_LATCH)
{
if (var->latched_string)
{
if (strcmp(value, var->latched_string) == 0)
return var;
Z_Free (var->latched_string);
}
else
{
if (strcmp(value, var->string) == 0)
return var;
}
if (Com_ServerState())
{
Com_Printf ("%s will be changed for next game.\n", var_name);
var->latched_string = CopyString(value);
}
else
{
var->string = CopyString(value);
var->value = atof (var->string);
if (!strcmp(var->name, "game"))
{
FS_SetGamedir (var->string);
FS_ExecAutoexec ();
}
}
return var;
}
}
else
{
if (var->latched_string)
{
Z_Free (var->latched_string);
var->latched_string = NULL;
}
}
if (!strcmp(value, var->string))
return var; // not changed
var->modified = true;
if (var->flags & CVAR_USERINFO)
userinfo_modified = true; // transmit at next oportunity
Z_Free (var->string); // free the old value string
var->string = CopyString(value);
var->value = atof (var->string);
return var;
}
/*
============
Cvar_ForceSet
============
*/
cvar_t *Cvar_ForceSet (char *var_name, char *value)
{
return Cvar_Set2 (var_name, value, true);
}
/*
============
Cvar_Set
============
*/
cvar_t *Cvar_Set (char *var_name, char *value)
{
return Cvar_Set2 (var_name, value, false);
}
/*
============
Cvar_FullSet
============
*/
cvar_t *Cvar_FullSet (char *var_name, char *value, int flags)
{
cvar_t *var;
var = Cvar_FindVar (var_name);
if (!var)
{ // create it
return Cvar_Get (var_name, value, flags);
}
var->modified = true;
if (var->flags & CVAR_USERINFO)
userinfo_modified = true; // transmit at next oportunity
Z_Free (var->string); // free the old value string
var->string = CopyString(value);
var->value = atof (var->string);
var->flags = flags;
return var;
}
/*
============
Cvar_SetValue
============
*/
void Cvar_SetValue (char *var_name, float value)
{
char val[32];
if (value == (int)value)
Com_sprintf (val, sizeof(val), "%i",(int)value);
else
Com_sprintf (val, sizeof(val), "%f",value);
Cvar_Set (var_name, val);
}
/*
============
Cvar_GetLatchedVars
Any variables with latched values will now be updated
============
*/
void Cvar_GetLatchedVars (void)
{
cvar_t *var;
for (var = cvar_vars ; var ; var = var->next)
{
if (!var->latched_string)
continue;
Z_Free (var->string);
var->string = var->latched_string;
var->latched_string = NULL;
var->value = atof(var->string);
if (!strcmp(var->name, "game"))
{
FS_SetGamedir (var->string);
FS_ExecAutoexec ();
}
}
}
/*
============
Cvar_Command
Handles variable inspection and changing from the console
============
*/
qboolean Cvar_Command (void)
{
cvar_t *v;
// check variables
v = Cvar_FindVar (Cmd_Argv(0));
if (!v)
return false;
// perform a variable print or set
if (Cmd_Argc() == 1)
{
Com_Printf ("\"%s\" is \"%s\"\n", v->name, v->string);
return true;
}
Cvar_Set (v->name, Cmd_Argv(1));
return true;
}
/*
============
Cvar_Set_f
Allows setting and defining of arbitrary cvars from console
============
*/
void Cvar_Set_f (void)
{
int c;
int flags;
c = Cmd_Argc();
if (c != 3 && c != 4)
{
Com_Printf ("usage: set <variable> <value> [u / s]\n");
return;
}
if (c == 4)
{
if (!strcmp(Cmd_Argv(3), "u"))
flags = CVAR_USERINFO;
else if (!strcmp(Cmd_Argv(3), "s"))
flags = CVAR_SERVERINFO;
else
{
Com_Printf ("flags can only be 'u' or 's'\n");
return;
}
Cvar_FullSet (Cmd_Argv(1), Cmd_Argv(2), flags);
}
else
Cvar_Set (Cmd_Argv(1), Cmd_Argv(2));
}
/*
============
Cvar_WriteVariables
Appends lines containing "set variable value" for all variables
with the archive flag set to true.
============
*/
void Cvar_WriteVariables (char *path)
{
cvar_t *var;
char buffer[1024];
FILE *f;
f = fopen (path, "a");
for (var = cvar_vars ; var ; var = var->next)
{
if (var->flags & CVAR_ARCHIVE)
{
Com_sprintf (buffer, sizeof(buffer), "set %s \"%s\"\n", var->name, var->string);
fprintf (f, "%s", buffer);
}
}
fclose (f);
}
/*
============
Cvar_List_f
============
*/
void Cvar_List_f (void)
{
cvar_t *var;
int i;
i = 0;
for (var = cvar_vars ; var ; var = var->next, i++)
{
if (var->flags & CVAR_ARCHIVE)
Com_Printf ("*");
else
Com_Printf (" ");
if (var->flags & CVAR_USERINFO)
Com_Printf ("U");
else
Com_Printf (" ");
if (var->flags & CVAR_SERVERINFO)
Com_Printf ("S");
else
Com_Printf (" ");
if (var->flags & CVAR_NOSET)
Com_Printf ("-");
else if (var->flags & CVAR_LATCH)
Com_Printf ("L");
else
Com_Printf (" ");
Com_Printf (" %s \"%s\"\n", var->name, var->string);
}
Com_Printf ("%i cvars\n", i);
}
qboolean userinfo_modified;
char *Cvar_BitInfo (int bit)
{
static char info[MAX_INFO_STRING];
cvar_t *var;
info[0] = 0;
for (var = cvar_vars ; var ; var = var->next)
{
if (var->flags & bit)
Info_SetValueForKey (info, var->name, var->string);
}
return info;
}
// returns an info string containing all the CVAR_USERINFO cvars
char *Cvar_Userinfo (void)
{
return Cvar_BitInfo (CVAR_USERINFO);
}
// returns an info string containing all the CVAR_SERVERINFO cvars
char *Cvar_Serverinfo (void)
{
return Cvar_BitInfo (CVAR_SERVERINFO);
}
/*
============
Cvar_Init
Reads in all archived cvars
============
*/
void Cvar_Init (void)
{
Cmd_AddCommand ("set", Cvar_Set_f);
Cmd_AddCommand ("cvarlist", Cvar_List_f);
}

877
qcommon/files.c Normal file
View File

@ -0,0 +1,877 @@
/*
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 "qcommon.h"
// define this to dissalow any data but the demo pak file
//#define NO_ADDONS
// if a packfile directory differs from this, it is assumed to be hacked
// Full version
#define PAK0_CHECKSUM 0x40e614e0
// Demo
//#define PAK0_CHECKSUM 0xb2c6d7ea
// OEM
//#define PAK0_CHECKSUM 0x78e135c
/*
=============================================================================
QUAKE FILESYSTEM
=============================================================================
*/
//
// in memory
//
typedef struct
{
char name[MAX_QPATH];
int filepos, filelen;
} packfile_t;
typedef struct pack_s
{
char filename[MAX_OSPATH];
FILE *handle;
int numfiles;
packfile_t *files;
} pack_t;
char fs_gamedir[MAX_OSPATH];
cvar_t *fs_basedir;
cvar_t *fs_cddir;
cvar_t *fs_gamedirvar;
typedef struct filelink_s
{
struct filelink_s *next;
char *from;
int fromlength;
char *to;
} filelink_t;
filelink_t *fs_links;
typedef struct searchpath_s
{
char filename[MAX_OSPATH];
pack_t *pack; // only one of filename / pack will be used
struct searchpath_s *next;
} searchpath_t;
searchpath_t *fs_searchpaths;
searchpath_t *fs_base_searchpaths; // without gamedirs
/*
All of Quake's data access is through a hierchal file system, but the contents of the file system can be transparently merged from several sources.
The "base directory" is the path to the directory holding the quake.exe and all game directories. The sys_* files pass this to host_init in quakeparms_t->basedir. This can be overridden with the "-basedir" command line parm to allow code debugging in a different directory. The base directory is
only used during filesystem initialization.
The "game directory" is the first tree on the search path and directory that all generated files (savegames, screenshots, demos, config files) will be saved to. This can be overridden with the "-game" command line parameter. The game directory can never be changed while quake is executing. This is a precacution against having a malicious server instruct clients to write files over areas they shouldn't.
*/
/*
================
FS_filelength
================
*/
int FS_filelength (FILE *f)
{
int pos;
int end;
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
return end;
}
/*
============
FS_CreatePath
Creates any directories needed to store the given filename
============
*/
void FS_CreatePath (char *path)
{
char *ofs;
for (ofs = path+1 ; *ofs ; ofs++)
{
if (*ofs == '/')
{ // create the directory
*ofs = 0;
Sys_Mkdir (path);
*ofs = '/';
}
}
}
/*
==============
FS_FCloseFile
For some reason, other dll's can't just cal fclose()
on files returned by FS_FOpenFile...
==============
*/
void FS_FCloseFile (FILE *f)
{
fclose (f);
}
// RAFAEL
/*
Developer_searchpath
*/
int Developer_searchpath (int who)
{
int ch;
// PMM - warning removal
// char *start;
searchpath_t *search;
if (who == 1) // xatrix
ch = 'x';
else if (who == 2)
ch = 'r';
for (search = fs_searchpaths ; search ; search = search->next)
{
if (strstr (search->filename, "xatrix"))
return 1;
if (strstr (search->filename, "rogue"))
return 2;
/*
start = strchr (search->filename, ch);
if (start == NULL)
continue;
if (strcmp (start ,"xatrix") == 0)
return (1);
*/
}
return (0);
}
/*
===========
FS_FOpenFile
Finds the file in the search path.
returns filesize and an open FILE *
Used for streaming data out of either a pak file or
a seperate file.
===========
*/
int file_from_pak = 0;
#ifndef NO_ADDONS
int FS_FOpenFile (char *filename, FILE **file)
{
searchpath_t *search;
char netpath[MAX_OSPATH];
pack_t *pak;
int i;
filelink_t *link;
file_from_pak = 0;
// check for links first
for (link = fs_links ; link ; link=link->next)
{
if (!strncmp (filename, link->from, link->fromlength))
{
Com_sprintf (netpath, sizeof(netpath), "%s%s",link->to, filename+link->fromlength);
*file = fopen (netpath, "rb");
if (*file)
{
Com_DPrintf ("link file: %s\n",netpath);
return FS_filelength (*file);
}
return -1;
}
}
//
// search through the path, one element at a time
//
for (search = fs_searchpaths ; search ; search = search->next)
{
// is the element a pak file?
if (search->pack)
{
// look through all the pak file elements
pak = search->pack;
for (i=0 ; i<pak->numfiles ; i++)
if (!Q_strcasecmp (pak->files[i].name, filename))
{ // found it!
file_from_pak = 1;
Com_DPrintf ("PackFile: %s : %s\n",pak->filename, filename);
// open a new file on the pakfile
*file = fopen (pak->filename, "rb");
if (!*file)
Com_Error (ERR_FATAL, "Couldn't reopen %s", pak->filename);
fseek (*file, pak->files[i].filepos, SEEK_SET);
return pak->files[i].filelen;
}
}
else
{
// check a file in the directory tree
Com_sprintf (netpath, sizeof(netpath), "%s/%s",search->filename, filename);
*file = fopen (netpath, "rb");
if (!*file)
continue;
Com_DPrintf ("FindFile: %s\n",netpath);
return FS_filelength (*file);
}
}
Com_DPrintf ("FindFile: can't find %s\n", filename);
*file = NULL;
return -1;
}
#else
// this is just for demos to prevent add on hacking
int FS_FOpenFile (char *filename, FILE **file)
{
searchpath_t *search;
char netpath[MAX_OSPATH];
pack_t *pak;
int i;
file_from_pak = 0;
// get config from directory, everything else from pak
if (!strcmp(filename, "config.cfg") || !strncmp(filename, "players/", 8))
{
Com_sprintf (netpath, sizeof(netpath), "%s/%s",FS_Gamedir(), filename);
*file = fopen (netpath, "rb");
if (!*file)
return -1;
Com_DPrintf ("FindFile: %s\n",netpath);
return FS_filelength (*file);
}
for (search = fs_searchpaths ; search ; search = search->next)
if (search->pack)
break;
if (!search)
{
*file = NULL;
return -1;
}
pak = search->pack;
for (i=0 ; i<pak->numfiles ; i++)
if (!Q_strcasecmp (pak->files[i].name, filename))
{ // found it!
file_from_pak = 1;
Com_DPrintf ("PackFile: %s : %s\n",pak->filename, filename);
// open a new file on the pakfile
*file = fopen (pak->filename, "rb");
if (!*file)
Com_Error (ERR_FATAL, "Couldn't reopen %s", pak->filename);
fseek (*file, pak->files[i].filepos, SEEK_SET);
return pak->files[i].filelen;
}
Com_DPrintf ("FindFile: can't find %s\n", filename);
*file = NULL;
return -1;
}
#endif
/*
=================
FS_ReadFile
Properly handles partial reads
=================
*/
void CDAudio_Stop(void);
#define MAX_READ 0x10000 // read in blocks of 64k
void FS_Read (void *buffer, int len, FILE *f)
{
int block, remaining;
int read;
byte *buf;
int tries;
buf = (byte *)buffer;
// read in chunks for progress bar
remaining = len;
tries = 0;
while (remaining)
{
block = remaining;
if (block > MAX_READ)
block = MAX_READ;
read = fread (buf, 1, block, f);
if (read == 0)
{
// we might have been trying to read from a CD
if (!tries)
{
tries = 1;
CDAudio_Stop();
}
else
Com_Error (ERR_FATAL, "FS_Read: 0 bytes read");
}
if (read == -1)
Com_Error (ERR_FATAL, "FS_Read: -1 bytes read");
// do some progress bar thing here...
remaining -= read;
buf += read;
}
}
/*
============
FS_LoadFile
Filename are reletive to the quake search path
a null buffer will just return the file length without loading
============
*/
int FS_LoadFile (char *path, void **buffer)
{
FILE *h;
byte *buf;
int len;
buf = NULL; // quiet compiler warning
// look for it in the filesystem or pack files
len = FS_FOpenFile (path, &h);
if (!h)
{
if (buffer)
*buffer = NULL;
return -1;
}
if (!buffer)
{
fclose (h);
return len;
}
buf = Z_Malloc(len);
*buffer = buf;
FS_Read (buf, len, h);
fclose (h);
return len;
}
/*
=============
FS_FreeFile
=============
*/
void FS_FreeFile (void *buffer)
{
Z_Free (buffer);
}
/*
=================
FS_LoadPackFile
Takes an explicit (not game tree related) path to a pak file.
Loads the header and directory, adding the files at the beginning
of the list so they override previous pack files.
=================
*/
pack_t *FS_LoadPackFile (char *packfile)
{
dpackheader_t header;
int i;
packfile_t *newfiles;
int numpackfiles;
pack_t *pack;
FILE *packhandle;
dpackfile_t info[MAX_FILES_IN_PACK];
unsigned checksum;
packhandle = fopen(packfile, "rb");
if (!packhandle)
return NULL;
fread (&header, 1, sizeof(header), packhandle);
if (LittleLong(header.ident) != IDPAKHEADER)
Com_Error (ERR_FATAL, "%s is not a packfile", packfile);
header.dirofs = LittleLong (header.dirofs);
header.dirlen = LittleLong (header.dirlen);
numpackfiles = header.dirlen / sizeof(dpackfile_t);
if (numpackfiles > MAX_FILES_IN_PACK)
Com_Error (ERR_FATAL, "%s has %i files", packfile, numpackfiles);
newfiles = Z_Malloc (numpackfiles * sizeof(packfile_t));
fseek (packhandle, header.dirofs, SEEK_SET);
fread (info, 1, header.dirlen, packhandle);
// crc the directory to check for modifications
checksum = Com_BlockChecksum ((void *)info, header.dirlen);
#ifdef NO_ADDONS
if (checksum != PAK0_CHECKSUM)
return NULL;
#endif
// parse the directory
for (i=0 ; i<numpackfiles ; i++)
{
strcpy (newfiles[i].name, info[i].name);
newfiles[i].filepos = LittleLong(info[i].filepos);
newfiles[i].filelen = LittleLong(info[i].filelen);
}
pack = Z_Malloc (sizeof (pack_t));
strcpy (pack->filename, packfile);
pack->handle = packhandle;
pack->numfiles = numpackfiles;
pack->files = newfiles;
Com_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles);
return pack;
}
/*
================
FS_AddGameDirectory
Sets fs_gamedir, adds the directory to the head of the path,
then loads and adds pak1.pak pak2.pak ...
================
*/
void FS_AddGameDirectory (char *dir)
{
int i;
searchpath_t *search;
pack_t *pak;
char pakfile[MAX_OSPATH];
strcpy (fs_gamedir, dir);
//
// add the directory to the search path
//
search = Z_Malloc (sizeof(searchpath_t));
strcpy (search->filename, dir);
search->next = fs_searchpaths;
fs_searchpaths = search;
//
// add any pak files in the format pak0.pak pak1.pak, ...
//
for (i=0; i<10; i++)
{
Com_sprintf (pakfile, sizeof(pakfile), "%s/pak%i.pak", dir, i);
pak = FS_LoadPackFile (pakfile);
if (!pak)
continue;
search = Z_Malloc (sizeof(searchpath_t));
search->pack = pak;
search->next = fs_searchpaths;
fs_searchpaths = search;
}
}
/*
============
FS_Gamedir
Called to find where to write a file (demos, savegames, etc)
============
*/
char *FS_Gamedir (void)
{
return fs_gamedir;
}
/*
=============
FS_ExecAutoexec
=============
*/
void FS_ExecAutoexec (void)
{
char *dir;
char name [MAX_QPATH];
dir = Cvar_VariableString("gamedir");
if (*dir)
Com_sprintf(name, sizeof(name), "%s/%s/autoexec.cfg", fs_basedir->string, dir);
else
Com_sprintf(name, sizeof(name), "%s/%s/autoexec.cfg", fs_basedir->string, BASEDIRNAME);
if (Sys_FindFirst(name, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM))
Cbuf_AddText ("exec autoexec.cfg\n");
Sys_FindClose();
}
/*
================
FS_SetGamedir
Sets the gamedir and path to a different directory.
================
*/
void FS_SetGamedir (char *dir)
{
searchpath_t *next;
if (strstr(dir, "..") || strstr(dir, "/")
|| strstr(dir, "\\") || strstr(dir, ":") )
{
Com_Printf ("Gamedir should be a single filename, not a path\n");
return;
}
//
// free up any current game dir info
//
while (fs_searchpaths != fs_base_searchpaths)
{
if (fs_searchpaths->pack)
{
fclose (fs_searchpaths->pack->handle);
Z_Free (fs_searchpaths->pack->files);
Z_Free (fs_searchpaths->pack);
}
next = fs_searchpaths->next;
Z_Free (fs_searchpaths);
fs_searchpaths = next;
}
//
// flush all data, so it will be forced to reload
//
if (dedicated && !dedicated->value)
Cbuf_AddText ("vid_restart\nsnd_restart\n");
Com_sprintf (fs_gamedir, sizeof(fs_gamedir), "%s/%s", fs_basedir->string, dir);
if (!strcmp(dir,BASEDIRNAME) || (*dir == 0))
{
Cvar_FullSet ("gamedir", "", CVAR_SERVERINFO|CVAR_NOSET);
Cvar_FullSet ("game", "", CVAR_LATCH|CVAR_SERVERINFO);
}
else
{
Cvar_FullSet ("gamedir", dir, CVAR_SERVERINFO|CVAR_NOSET);
if (fs_cddir->string[0])
FS_AddGameDirectory (va("%s/%s", fs_cddir->string, dir) );
FS_AddGameDirectory (va("%s/%s", fs_basedir->string, dir) );
}
}
/*
================
FS_Link_f
Creates a filelink_t
================
*/
void FS_Link_f (void)
{
filelink_t *l, **prev;
if (Cmd_Argc() != 3)
{
Com_Printf ("USAGE: link <from> <to>\n");
return;
}
// see if the link already exists
prev = &fs_links;
for (l=fs_links ; l ; l=l->next)
{
if (!strcmp (l->from, Cmd_Argv(1)))
{
Z_Free (l->to);
if (!strlen(Cmd_Argv(2)))
{ // delete it
*prev = l->next;
Z_Free (l->from);
Z_Free (l);
return;
}
l->to = CopyString (Cmd_Argv(2));
return;
}
prev = &l->next;
}
// create a new link
l = Z_Malloc(sizeof(*l));
l->next = fs_links;
fs_links = l;
l->from = CopyString(Cmd_Argv(1));
l->fromlength = strlen(l->from);
l->to = CopyString(Cmd_Argv(2));
}
/*
** FS_ListFiles
*/
char **FS_ListFiles( char *findname, int *numfiles, unsigned musthave, unsigned canthave )
{
char *s;
int nfiles = 0;
char **list = 0;
s = Sys_FindFirst( findname, musthave, canthave );
while ( s )
{
if ( s[strlen(s)-1] != '.' )
nfiles++;
s = Sys_FindNext( musthave, canthave );
}
Sys_FindClose ();
if ( !nfiles )
return NULL;
nfiles++; // add space for a guard
*numfiles = nfiles;
list = malloc( sizeof( char * ) * nfiles );
memset( list, 0, sizeof( char * ) * nfiles );
s = Sys_FindFirst( findname, musthave, canthave );
nfiles = 0;
while ( s )
{
if ( s[strlen(s)-1] != '.' )
{
list[nfiles] = strdup( s );
#ifdef _WIN32
strlwr( list[nfiles] );
#endif
nfiles++;
}
s = Sys_FindNext( musthave, canthave );
}
Sys_FindClose ();
return list;
}
/*
** FS_Dir_f
*/
void FS_Dir_f( void )
{
char *path = NULL;
char findname[1024];
char wildcard[1024] = "*.*";
char **dirnames;
int ndirs;
if ( Cmd_Argc() != 1 )
{
strcpy( wildcard, Cmd_Argv( 1 ) );
}
while ( ( path = FS_NextPath( path ) ) != NULL )
{
char *tmp = findname;
Com_sprintf( findname, sizeof(findname), "%s/%s", path, wildcard );
while ( *tmp != 0 )
{
if ( *tmp == '\\' )
*tmp = '/';
tmp++;
}
Com_Printf( "Directory of %s\n", findname );
Com_Printf( "----\n" );
if ( ( dirnames = FS_ListFiles( findname, &ndirs, 0, 0 ) ) != 0 )
{
int i;
for ( i = 0; i < ndirs-1; i++ )
{
if ( strrchr( dirnames[i], '/' ) )
Com_Printf( "%s\n", strrchr( dirnames[i], '/' ) + 1 );
else
Com_Printf( "%s\n", dirnames[i] );
free( dirnames[i] );
}
free( dirnames );
}
Com_Printf( "\n" );
};
}
/*
============
FS_Path_f
============
*/
void FS_Path_f (void)
{
searchpath_t *s;
filelink_t *l;
Com_Printf ("Current search path:\n");
for (s=fs_searchpaths ; s ; s=s->next)
{
if (s == fs_base_searchpaths)
Com_Printf ("----------\n");
if (s->pack)
Com_Printf ("%s (%i files)\n", s->pack->filename, s->pack->numfiles);
else
Com_Printf ("%s\n", s->filename);
}
Com_Printf ("\nLinks:\n");
for (l=fs_links ; l ; l=l->next)
Com_Printf ("%s : %s\n", l->from, l->to);
}
/*
================
FS_NextPath
Allows enumerating all of the directories in the search path
================
*/
char *FS_NextPath (char *prevpath)
{
searchpath_t *s;
char *prev;
if (!prevpath)
return fs_gamedir;
prev = fs_gamedir;
for (s=fs_searchpaths ; s ; s=s->next)
{
if (s->pack)
continue;
if (prevpath == prev)
return s->filename;
prev = s->filename;
}
return NULL;
}
/*
================
FS_InitFilesystem
================
*/
void FS_InitFilesystem (void)
{
Cmd_AddCommand ("path", FS_Path_f);
Cmd_AddCommand ("link", FS_Link_f);
Cmd_AddCommand ("dir", FS_Dir_f );
//
// basedir <path>
// allows the game to run from outside the data tree
//
fs_basedir = Cvar_Get ("basedir", ".", CVAR_NOSET);
//
// cddir <path>
// Logically concatenates the cddir after the basedir for
// allows the game to run from outside the data tree
//
fs_cddir = Cvar_Get ("cddir", "", CVAR_NOSET);
if (fs_cddir->string[0])
FS_AddGameDirectory (va("%s/"BASEDIRNAME, fs_cddir->string) );
//
// start up with baseq2 by default
//
FS_AddGameDirectory (va("%s/"BASEDIRNAME, fs_basedir->string) );
// any set gamedirs will be freed up to here
fs_base_searchpaths = fs_searchpaths;
// check for game override
fs_gamedirvar = Cvar_Get ("game", "", CVAR_LATCH|CVAR_SERVERINFO);
if (fs_gamedirvar->string[0])
FS_SetGamedir (fs_gamedirvar->string);
}

278
qcommon/md4.c Normal file
View File

@ -0,0 +1,278 @@
/* GLOBAL.H - RSAREF types and constants */
#include <string.h>
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
#ifdef __alpha__
typedef unsigned int UINT4;
#else
typedef unsigned long int UINT4;
#endif
/* MD4.H - header file for MD4C.C */
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991.
All rights reserved.
License to copy and use this software is granted provided that it is identified as the <20>RSA Data Security, Inc. MD4 Message-Digest Algorithm<68> in all material mentioning or referencing this software or this function.
License is also granted to make and use derivative works provided that such works are identified as <20>derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm<68> in all material mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided <20>as is<69> without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this documentation and/or software. */
/* MD4 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD4_CTX;
void MD4Init (MD4_CTX *);
void MD4Update (MD4_CTX *, unsigned char *, unsigned int);
void MD4Final (unsigned char [16], MD4_CTX *);
/* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm */
/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
License to copy and use this software is granted provided that it is identified as the
RSA Data Security, Inc. MD4 Message-Digest Algorithm
in all material mentioning or referencing this software or this function.
License is also granted to make and use derivative works provided that such works are identified as
derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm
in all material mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided
as is without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this documentation and/or software. */
/* Constants for MD4Transform routine. */
#define S11 3
#define S12 7
#define S13 11
#define S14 19
#define S21 3
#define S22 5
#define S23 9
#define S24 13
#define S31 3
#define S32 9
#define S33 11
#define S34 15
static void MD4Transform (UINT4 [4], unsigned char [64]);
static void Encode (unsigned char *, UINT4 *, unsigned int);
static void Decode (UINT4 *, unsigned char *, unsigned int);
static unsigned char PADDING[64] = {
0x80, 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
};
/* F, G and H are basic MD4 functions. */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
/* ROTATE_LEFT rotates x left n bits. */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s) {(a) += F ((b), (c), (d)) + (x); (a) = ROTATE_LEFT ((a), (s));}
#define GG(a, b, c, d, x, s) {(a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; (a) = ROTATE_LEFT ((a), (s));}
#define HH(a, b, c, d, x, s) {(a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; (a) = ROTATE_LEFT ((a), (s));}
/* MD4 initialization. Begins an MD4 operation, writing a new context. */
void MD4Init (MD4_CTX *context)
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD4 block update operation. Continues an MD4 message-digest operation, processing another message block, and updating the context. */
void MD4Update (MD4_CTX *context, unsigned char *input, unsigned int inputLen)
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.*/
if (inputLen >= partLen)
{
memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD4Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD4Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);
}
/* MD4 finalization. Ends an MD4 message-digest operation, writing the the message digest and zeroizing the context. */
void MD4Final (unsigned char digest[16], MD4_CTX *context)
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD4Update (context, PADDING, padLen);
/* Append length (before padding) */
MD4Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information.*/
memset ((POINTER)context, 0, sizeof (*context));
}
/* MD4 basic transformation. Transforms state based on block. */
static void MD4Transform (UINT4 state[4], unsigned char block[64])
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11); /* 1 */
FF (d, a, b, c, x[ 1], S12); /* 2 */
FF (c, d, a, b, x[ 2], S13); /* 3 */
FF (b, c, d, a, x[ 3], S14); /* 4 */
FF (a, b, c, d, x[ 4], S11); /* 5 */
FF (d, a, b, c, x[ 5], S12); /* 6 */
FF (c, d, a, b, x[ 6], S13); /* 7 */
FF (b, c, d, a, x[ 7], S14); /* 8 */
FF (a, b, c, d, x[ 8], S11); /* 9 */
FF (d, a, b, c, x[ 9], S12); /* 10 */
FF (c, d, a, b, x[10], S13); /* 11 */
FF (b, c, d, a, x[11], S14); /* 12 */
FF (a, b, c, d, x[12], S11); /* 13 */
FF (d, a, b, c, x[13], S12); /* 14 */
FF (c, d, a, b, x[14], S13); /* 15 */
FF (b, c, d, a, x[15], S14); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 0], S21); /* 17 */
GG (d, a, b, c, x[ 4], S22); /* 18 */
GG (c, d, a, b, x[ 8], S23); /* 19 */
GG (b, c, d, a, x[12], S24); /* 20 */
GG (a, b, c, d, x[ 1], S21); /* 21 */
GG (d, a, b, c, x[ 5], S22); /* 22 */
GG (c, d, a, b, x[ 9], S23); /* 23 */
GG (b, c, d, a, x[13], S24); /* 24 */
GG (a, b, c, d, x[ 2], S21); /* 25 */
GG (d, a, b, c, x[ 6], S22); /* 26 */
GG (c, d, a, b, x[10], S23); /* 27 */
GG (b, c, d, a, x[14], S24); /* 28 */
GG (a, b, c, d, x[ 3], S21); /* 29 */
GG (d, a, b, c, x[ 7], S22); /* 30 */
GG (c, d, a, b, x[11], S23); /* 31 */
GG (b, c, d, a, x[15], S24); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 0], S31); /* 33 */
HH (d, a, b, c, x[ 8], S32); /* 34 */
HH (c, d, a, b, x[ 4], S33); /* 35 */
HH (b, c, d, a, x[12], S34); /* 36 */
HH (a, b, c, d, x[ 2], S31); /* 37 */
HH (d, a, b, c, x[10], S32); /* 38 */
HH (c, d, a, b, x[ 6], S33); /* 39 */
HH (b, c, d, a, x[14], S34); /* 40 */
HH (a, b, c, d, x[ 1], S31); /* 41 */
HH (d, a, b, c, x[ 9], S32); /* 42 */
HH (c, d, a, b, x[ 5], S33); /* 43 */
HH (b, c, d, a, x[13], S34); /* 44 */
HH (a, b, c, d, x[ 3], S31); /* 45 */
HH (d, a, b, c, x[11], S32); /* 46 */
HH (c, d, a, b, x[ 7], S33); /* 47 */
HH (b, c, d, a, x[15], S34); /* 48 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information.*/
memset ((POINTER)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */
static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */
static void Decode (UINT4 *output, unsigned char *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
//===================================================================
unsigned Com_BlockChecksum (void *buffer, int length)
{
int digest[4];
unsigned val;
MD4_CTX ctx;
MD4Init (&ctx);
MD4Update (&ctx, (unsigned char *)buffer, length);
MD4Final ( (unsigned char *)digest, &ctx);
val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
return val;
}

387
qcommon/net_chan.c Normal file
View File

@ -0,0 +1,387 @@
/*
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 "qcommon.h"
/*
packet header
-------------
31 sequence
1 does this message contain a reliable payload
31 acknowledge sequence
1 acknowledge receipt of even/odd message
16 qport
The remote connection never knows if it missed a reliable message, the
local side detects that it has been dropped by seeing a sequence acknowledge
higher thatn the last reliable sequence, but without the correct evon/odd
bit for the reliable set.
If the sender notices that a reliable message has been dropped, it will be
retransmitted. It will not be retransmitted again until a message after
the retransmit has been acknowledged and the reliable still failed to get there.
if the sequence number is -1, the packet should be handled without a netcon
The reliable message can be added to at any time by doing
MSG_Write* (&netchan->message, <data>).
If the message buffer is overflowed, either by a single message, or by
multiple frames worth piling up while the last reliable transmit goes
unacknowledged, the netchan signals a fatal error.
Reliable messages are always placed first in a packet, then the unreliable
message is included if there is sufficient room.
To the receiver, there is no distinction between the reliable and unreliable
parts of the message, they are just processed out as a single larger message.
Illogical packet sequence numbers cause the packet to be dropped, but do
not kill the connection. This, combined with the tight window of valid
reliable acknowledgement numbers provides protection against malicious
address spoofing.
The qport field is a workaround for bad address translating routers that
sometimes remap the client's source port on a packet during gameplay.
If the base part of the net address matches and the qport matches, then the
channel matches even if the IP port differs. The IP port should be updated
to the new value before sending out any replies.
If there is no information that needs to be transfered on a given frame,
such as during the connection stage while waiting for the client to load,
then a packet only needs to be delivered if there is something in the
unacknowledged reliable
*/
cvar_t *showpackets;
cvar_t *showdrop;
cvar_t *qport;
netadr_t net_from;
sizebuf_t net_message;
byte net_message_buffer[MAX_MSGLEN];
/*
===============
Netchan_Init
===============
*/
void Netchan_Init (void)
{
int port;
// pick a port value that should be nice and random
port = Sys_Milliseconds() & 0xffff;
showpackets = Cvar_Get ("showpackets", "0", 0);
showdrop = Cvar_Get ("showdrop", "0", 0);
qport = Cvar_Get ("qport", va("%i", port), CVAR_NOSET);
}
/*
===============
Netchan_OutOfBand
Sends an out-of-band datagram
================
*/
void Netchan_OutOfBand (int net_socket, netadr_t adr, int length, byte *data)
{
sizebuf_t send;
byte send_buf[MAX_MSGLEN];
// write the packet header
SZ_Init (&send, send_buf, sizeof(send_buf));
MSG_WriteLong (&send, -1); // -1 sequence means out of band
SZ_Write (&send, data, length);
// send the datagram
NET_SendPacket (net_socket, send.cursize, send.data, adr);
}
/*
===============
Netchan_OutOfBandPrint
Sends a text message in an out-of-band datagram
================
*/
void Netchan_OutOfBandPrint (int net_socket, netadr_t adr, char *format, ...)
{
va_list argptr;
static char string[MAX_MSGLEN - 4];
va_start (argptr, format);
vsprintf (string, format,argptr);
va_end (argptr);
Netchan_OutOfBand (net_socket, adr, strlen(string), (byte *)string);
}
/*
==============
Netchan_Setup
called to open a channel to a remote system
==============
*/
void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t adr, int qport)
{
memset (chan, 0, sizeof(*chan));
chan->sock = sock;
chan->remote_address = adr;
chan->qport = qport;
chan->last_received = curtime;
chan->incoming_sequence = 0;
chan->outgoing_sequence = 1;
SZ_Init (&chan->message, chan->message_buf, sizeof(chan->message_buf));
chan->message.allowoverflow = true;
}
/*
===============
Netchan_CanReliable
Returns true if the last reliable message has acked
================
*/
qboolean Netchan_CanReliable (netchan_t *chan)
{
if (chan->reliable_length)
return false; // waiting for ack
return true;
}
qboolean Netchan_NeedReliable (netchan_t *chan)
{
qboolean send_reliable;
// if the remote side dropped the last reliable message, resend it
send_reliable = false;
if (chan->incoming_acknowledged > chan->last_reliable_sequence
&& chan->incoming_reliable_acknowledged != chan->reliable_sequence)
send_reliable = true;
// if the reliable transmit buffer is empty, copy the current message out
if (!chan->reliable_length && chan->message.cursize)
{
send_reliable = true;
}
return send_reliable;
}
/*
===============
Netchan_Transmit
tries to send an unreliable message to a connection, and handles the
transmition / retransmition of the reliable messages.
A 0 length will still generate a packet and deal with the reliable messages.
================
*/
void Netchan_Transmit (netchan_t *chan, int length, byte *data)
{
sizebuf_t send;
byte send_buf[MAX_MSGLEN];
qboolean send_reliable;
unsigned w1, w2;
// check for message overflow
if (chan->message.overflowed)
{
chan->fatal_error = true;
Com_Printf ("%s:Outgoing message overflow\n"
, NET_AdrToString (chan->remote_address));
return;
}
send_reliable = Netchan_NeedReliable (chan);
if (!chan->reliable_length && chan->message.cursize)
{
memcpy (chan->reliable_buf, chan->message_buf, chan->message.cursize);
chan->reliable_length = chan->message.cursize;
chan->message.cursize = 0;
chan->reliable_sequence ^= 1;
}
// write the packet header
SZ_Init (&send, send_buf, sizeof(send_buf));
w1 = ( chan->outgoing_sequence & ~(1<<31) ) | (send_reliable<<31);
w2 = ( chan->incoming_sequence & ~(1<<31) ) | (chan->incoming_reliable_sequence<<31);
chan->outgoing_sequence++;
chan->last_sent = curtime;
MSG_WriteLong (&send, w1);
MSG_WriteLong (&send, w2);
// send the qport if we are a client
if (chan->sock == NS_CLIENT)
MSG_WriteShort (&send, qport->value);
// copy the reliable message to the packet first
if (send_reliable)
{
SZ_Write (&send, chan->reliable_buf, chan->reliable_length);
chan->last_reliable_sequence = chan->outgoing_sequence;
}
// add the unreliable part if space is available
if (send.maxsize - send.cursize >= length)
SZ_Write (&send, data, length);
else
Com_Printf ("Netchan_Transmit: dumped unreliable\n");
// send the datagram
NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address);
if (showpackets->value)
{
if (send_reliable)
Com_Printf ("send %4i : s=%i reliable=%i ack=%i rack=%i\n"
, send.cursize
, chan->outgoing_sequence - 1
, chan->reliable_sequence
, chan->incoming_sequence
, chan->incoming_reliable_sequence);
else
Com_Printf ("send %4i : s=%i ack=%i rack=%i\n"
, send.cursize
, chan->outgoing_sequence - 1
, chan->incoming_sequence
, chan->incoming_reliable_sequence);
}
}
/*
=================
Netchan_Process
called when the current net_message is from remote_address
modifies net_message so that it points to the packet payload
=================
*/
qboolean Netchan_Process (netchan_t *chan, sizebuf_t *msg)
{
unsigned sequence, sequence_ack;
unsigned reliable_ack, reliable_message;
int qport;
// get sequence numbers
MSG_BeginReading (msg);
sequence = MSG_ReadLong (msg);
sequence_ack = MSG_ReadLong (msg);
// read the qport if we are a server
if (chan->sock == NS_SERVER)
qport = MSG_ReadShort (msg);
reliable_message = sequence >> 31;
reliable_ack = sequence_ack >> 31;
sequence &= ~(1<<31);
sequence_ack &= ~(1<<31);
if (showpackets->value)
{
if (reliable_message)
Com_Printf ("recv %4i : s=%i reliable=%i ack=%i rack=%i\n"
, msg->cursize
, sequence
, chan->incoming_reliable_sequence ^ 1
, sequence_ack
, reliable_ack);
else
Com_Printf ("recv %4i : s=%i ack=%i rack=%i\n"
, msg->cursize
, sequence
, sequence_ack
, reliable_ack);
}
//
// discard stale or duplicated packets
//
if (sequence <= chan->incoming_sequence)
{
if (showdrop->value)
Com_Printf ("%s:Out of order packet %i at %i\n"
, NET_AdrToString (chan->remote_address)
, sequence
, chan->incoming_sequence);
return false;
}
//
// dropped packets don't keep the message from being used
//
chan->dropped = sequence - (chan->incoming_sequence+1);
if (chan->dropped > 0)
{
if (showdrop->value)
Com_Printf ("%s:Dropped %i packets at %i\n"
, NET_AdrToString (chan->remote_address)
, chan->dropped
, sequence);
}
//
// if the current outgoing reliable message has been acknowledged
// clear the buffer to make way for the next
//
if (reliable_ack == chan->reliable_sequence)
chan->reliable_length = 0; // it has been received
//
// if this message contains a reliable message, bump incoming_reliable_sequence
//
chan->incoming_sequence = sequence;
chan->incoming_acknowledged = sequence_ack;
chan->incoming_reliable_acknowledged = reliable_ack;
if (reliable_message)
{
chan->incoming_reliable_sequence ^= 1;
}
//
// the message can now be read from the current message pointer
//
chan->last_received = curtime;
return true;
}

1360
qcommon/pmove.c Normal file

File diff suppressed because it is too large Load Diff

826
qcommon/qcommon.h Normal file
View File

@ -0,0 +1,826 @@
/*
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.
*/
// qcommon.h -- definitions common between client and server, but not game.dll
#include "../game/q_shared.h"
#define VERSION 3.19
#define BASEDIRNAME "baseq2"
#ifdef WIN32
#ifdef NDEBUG
#define BUILDSTRING "Win32 RELEASE"
#else
#define BUILDSTRING "Win32 DEBUG"
#endif
#ifdef _M_IX86
#define CPUSTRING "x86"
#elif defined _M_ALPHA
#define CPUSTRING "AXP"
#endif
#elif defined __linux__
#define BUILDSTRING "Linux"
#ifdef __i386__
#define CPUSTRING "i386"
#elif defined __alpha__
#define CPUSTRING "axp"
#else
#define CPUSTRING "Unknown"
#endif
#elif defined __sun__
#define BUILDSTRING "Solaris"
#ifdef __i386__
#define CPUSTRING "i386"
#else
#define CPUSTRING "sparc"
#endif
#else // !WIN32
#define BUILDSTRING "NON-WIN32"
#define CPUSTRING "NON-WIN32"
#endif
//============================================================================
typedef struct sizebuf_s
{
qboolean allowoverflow; // if false, do a Com_Error
qboolean overflowed; // set to true if the buffer size failed
byte *data;
int maxsize;
int cursize;
int readcount;
} sizebuf_t;
void SZ_Init (sizebuf_t *buf, byte *data, int length);
void SZ_Clear (sizebuf_t *buf);
void *SZ_GetSpace (sizebuf_t *buf, int length);
void SZ_Write (sizebuf_t *buf, void *data, int length);
void SZ_Print (sizebuf_t *buf, char *data); // strcats onto the sizebuf
//============================================================================
struct usercmd_s;
struct entity_state_s;
void MSG_WriteChar (sizebuf_t *sb, int c);
void MSG_WriteByte (sizebuf_t *sb, int c);
void MSG_WriteShort (sizebuf_t *sb, int c);
void MSG_WriteLong (sizebuf_t *sb, int c);
void MSG_WriteFloat (sizebuf_t *sb, float f);
void MSG_WriteString (sizebuf_t *sb, char *s);
void MSG_WriteCoord (sizebuf_t *sb, float f);
void MSG_WritePos (sizebuf_t *sb, vec3_t pos);
void MSG_WriteAngle (sizebuf_t *sb, float f);
void MSG_WriteAngle16 (sizebuf_t *sb, float f);
void MSG_WriteDeltaUsercmd (sizebuf_t *sb, struct usercmd_s *from, struct usercmd_s *cmd);
void MSG_WriteDeltaEntity (struct entity_state_s *from, struct entity_state_s *to, sizebuf_t *msg, qboolean force, qboolean newentity);
void MSG_WriteDir (sizebuf_t *sb, vec3_t vector);
void MSG_BeginReading (sizebuf_t *sb);
int MSG_ReadChar (sizebuf_t *sb);
int MSG_ReadByte (sizebuf_t *sb);
int MSG_ReadShort (sizebuf_t *sb);
int MSG_ReadLong (sizebuf_t *sb);
float MSG_ReadFloat (sizebuf_t *sb);
char *MSG_ReadString (sizebuf_t *sb);
char *MSG_ReadStringLine (sizebuf_t *sb);
float MSG_ReadCoord (sizebuf_t *sb);
void MSG_ReadPos (sizebuf_t *sb, vec3_t pos);
float MSG_ReadAngle (sizebuf_t *sb);
float MSG_ReadAngle16 (sizebuf_t *sb);
void MSG_ReadDeltaUsercmd (sizebuf_t *sb, struct usercmd_s *from, struct usercmd_s *cmd);
void MSG_ReadDir (sizebuf_t *sb, vec3_t vector);
void MSG_ReadData (sizebuf_t *sb, void *buffer, int size);
//============================================================================
extern qboolean bigendien;
extern short BigShort (short l);
extern short LittleShort (short l);
extern int BigLong (int l);
extern int LittleLong (int l);
extern float BigFloat (float l);
extern float LittleFloat (float l);
//============================================================================
int COM_Argc (void);
char *COM_Argv (int arg); // range and null checked
void COM_ClearArgv (int arg);
int COM_CheckParm (char *parm);
void COM_AddParm (char *parm);
void COM_Init (void);
void COM_InitArgv (int argc, char **argv);
char *CopyString (char *in);
//============================================================================
void Info_Print (char *s);
/* crc.h */
void CRC_Init(unsigned short *crcvalue);
void CRC_ProcessByte(unsigned short *crcvalue, byte data);
unsigned short CRC_Value(unsigned short crcvalue);
unsigned short CRC_Block (byte *start, int count);
/*
==============================================================
PROTOCOL
==============================================================
*/
// protocol.h -- communications protocols
#define PROTOCOL_VERSION 34
//=========================================
#define PORT_MASTER 27900
#define PORT_CLIENT 27901
#define PORT_SERVER 27910
//=========================================
#define UPDATE_BACKUP 16 // copies of entity_state_t to keep buffered
// must be power of two
#define UPDATE_MASK (UPDATE_BACKUP-1)
//==================
// the svc_strings[] array in cl_parse.c should mirror this
//==================
//
// server to client
//
enum svc_ops_e
{
svc_bad,
// these ops are known to the game dll
svc_muzzleflash,
svc_muzzleflash2,
svc_temp_entity,
svc_layout,
svc_inventory,
// the rest are private to the client and server
svc_nop,
svc_disconnect,
svc_reconnect,
svc_sound, // <see code>
svc_print, // [byte] id [string] null terminated string
svc_stufftext, // [string] stuffed into client's console buffer, should be \n terminated
svc_serverdata, // [long] protocol ...
svc_configstring, // [short] [string]
svc_spawnbaseline,
svc_centerprint, // [string] to put in center of the screen
svc_download, // [short] size [size bytes]
svc_playerinfo, // variable
svc_packetentities, // [...]
svc_deltapacketentities, // [...]
svc_frame
};
//==============================================
//
// client to server
//
enum clc_ops_e
{
clc_bad,
clc_nop,
clc_move, // [[usercmd_t]
clc_userinfo, // [[userinfo string]
clc_stringcmd // [string] message
};
//==============================================
// plyer_state_t communication
#define PS_M_TYPE (1<<0)
#define PS_M_ORIGIN (1<<1)
#define PS_M_VELOCITY (1<<2)
#define PS_M_TIME (1<<3)
#define PS_M_FLAGS (1<<4)
#define PS_M_GRAVITY (1<<5)
#define PS_M_DELTA_ANGLES (1<<6)
#define PS_VIEWOFFSET (1<<7)
#define PS_VIEWANGLES (1<<8)
#define PS_KICKANGLES (1<<9)
#define PS_BLEND (1<<10)
#define PS_FOV (1<<11)
#define PS_WEAPONINDEX (1<<12)
#define PS_WEAPONFRAME (1<<13)
#define PS_RDFLAGS (1<<14)
//==============================================
// user_cmd_t communication
// ms and light always sent, the others are optional
#define CM_ANGLE1 (1<<0)
#define CM_ANGLE2 (1<<1)
#define CM_ANGLE3 (1<<2)
#define CM_FORWARD (1<<3)
#define CM_SIDE (1<<4)
#define CM_UP (1<<5)
#define CM_BUTTONS (1<<6)
#define CM_IMPULSE (1<<7)
//==============================================
// a sound without an ent or pos will be a local only sound
#define SND_VOLUME (1<<0) // a byte
#define SND_ATTENUATION (1<<1) // a byte
#define SND_POS (1<<2) // three coordinates
#define SND_ENT (1<<3) // a short 0-2: channel, 3-12: entity
#define SND_OFFSET (1<<4) // a byte, msec offset from frame start
#define DEFAULT_SOUND_PACKET_VOLUME 1.0
#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0
//==============================================
// entity_state_t communication
// try to pack the common update flags into the first byte
#define U_ORIGIN1 (1<<0)
#define U_ORIGIN2 (1<<1)
#define U_ANGLE2 (1<<2)
#define U_ANGLE3 (1<<3)
#define U_FRAME8 (1<<4) // frame is a byte
#define U_EVENT (1<<5)
#define U_REMOVE (1<<6) // REMOVE this entity, don't add it
#define U_MOREBITS1 (1<<7) // read one additional byte
// second byte
#define U_NUMBER16 (1<<8) // NUMBER8 is implicit if not set
#define U_ORIGIN3 (1<<9)
#define U_ANGLE1 (1<<10)
#define U_MODEL (1<<11)
#define U_RENDERFX8 (1<<12) // fullbright, etc
#define U_EFFECTS8 (1<<14) // autorotate, trails, etc
#define U_MOREBITS2 (1<<15) // read one additional byte
// third byte
#define U_SKIN8 (1<<16)
#define U_FRAME16 (1<<17) // frame is a short
#define U_RENDERFX16 (1<<18) // 8 + 16 = 32
#define U_EFFECTS16 (1<<19) // 8 + 16 = 32
#define U_MODEL2 (1<<20) // weapons, flags, etc
#define U_MODEL3 (1<<21)
#define U_MODEL4 (1<<22)
#define U_MOREBITS3 (1<<23) // read one additional byte
// fourth byte
#define U_OLDORIGIN (1<<24) // FIXME: get rid of this
#define U_SKIN16 (1<<25)
#define U_SOUND (1<<26)
#define U_SOLID (1<<27)
/*
==============================================================
CMD
Command text buffering and command execution
==============================================================
*/
/*
Any number of commands can be added in a frame, from several different sources.
Most commands come from either keybindings or console line input, but remote
servers can also send across commands and entire text files can be execed.
The + command line options are also added to the command buffer.
The game starts with a Cbuf_AddText ("exec quake.rc\n"); Cbuf_Execute ();
*/
#define EXEC_NOW 0 // don't return until completed
#define EXEC_INSERT 1 // insert at current position, but don't run yet
#define EXEC_APPEND 2 // add to end of the command buffer
void Cbuf_Init (void);
// allocates an initial text buffer that will grow as needed
void Cbuf_AddText (char *text);
// as new commands are generated from the console or keybindings,
// the text is added to the end of the command buffer.
void Cbuf_InsertText (char *text);
// when a command wants to issue other commands immediately, the text is
// inserted at the beginning of the buffer, before any remaining unexecuted
// commands.
void Cbuf_ExecuteText (int exec_when, char *text);
// this can be used in place of either Cbuf_AddText or Cbuf_InsertText
void Cbuf_AddEarlyCommands (qboolean clear);
// adds all the +set commands from the command line
qboolean Cbuf_AddLateCommands (void);
// adds all the remaining + commands from the command line
// Returns true if any late commands were added, which
// will keep the demoloop from immediately starting
void Cbuf_Execute (void);
// Pulls off \n terminated lines of text from the command buffer and sends
// them through Cmd_ExecuteString. Stops when the buffer is empty.
// Normally called once per frame, but may be explicitly invoked.
// Do not call inside a command function!
void Cbuf_CopyToDefer (void);
void Cbuf_InsertFromDefer (void);
// These two functions are used to defer any pending commands while a map
// is being loaded
//===========================================================================
/*
Command execution takes a null terminated string, breaks it into tokens,
then searches for a command or variable that matches the first token.
*/
typedef void (*xcommand_t) (void);
void Cmd_Init (void);
void Cmd_AddCommand (char *cmd_name, xcommand_t function);
// called by the init functions of other parts of the program to
// register commands and functions to call for them.
// The cmd_name is referenced later, so it should not be in temp memory
// if function is NULL, the command will be forwarded to the server
// as a clc_stringcmd instead of executed locally
void Cmd_RemoveCommand (char *cmd_name);
qboolean Cmd_Exists (char *cmd_name);
// used by the cvar code to check for cvar / command name overlap
char *Cmd_CompleteCommand (char *partial);
// attempts to match a partial command for automatic command line completion
// returns NULL if nothing fits
int Cmd_Argc (void);
char *Cmd_Argv (int arg);
char *Cmd_Args (void);
// The functions that execute commands get their parameters with these
// functions. Cmd_Argv () will return an empty string, not a NULL
// if arg > argc, so string operations are always safe.
void Cmd_TokenizeString (char *text, qboolean macroExpand);
// Takes a null terminated string. Does not need to be /n terminated.
// breaks the string up into arg tokens.
void Cmd_ExecuteString (char *text);
// Parses a single line of text into arguments and tries to execute it
// as if it was typed at the console
void Cmd_ForwardToServer (void);
// adds the current command line as a clc_stringcmd to the client message.
// things like godmode, noclip, etc, are commands directed to the server,
// so when they are typed in at the console, they will need to be forwarded.
/*
==============================================================
CVAR
==============================================================
*/
/*
cvar_t variables are used to hold scalar or string variables that can be changed or displayed at the console or prog code as well as accessed directly
in C code.
The user can access cvars from the console in three ways:
r_draworder prints the current value
r_draworder 0 sets the current value to 0
set r_draworder 0 as above, but creates the cvar if not present
Cvars are restricted from having the same names as commands to keep this
interface from being ambiguous.
*/
extern cvar_t *cvar_vars;
cvar_t *Cvar_Get (char *var_name, char *value, int flags);
// creates the variable if it doesn't exist, or returns the existing one
// if it exists, the value will not be changed, but flags will be ORed in
// that allows variables to be unarchived without needing bitflags
cvar_t *Cvar_Set (char *var_name, char *value);
// will create the variable if it doesn't exist
cvar_t *Cvar_ForceSet (char *var_name, char *value);
// will set the variable even if NOSET or LATCH
cvar_t *Cvar_FullSet (char *var_name, char *value, int flags);
void Cvar_SetValue (char *var_name, float value);
// expands value to a string and calls Cvar_Set
float Cvar_VariableValue (char *var_name);
// returns 0 if not defined or non numeric
char *Cvar_VariableString (char *var_name);
// returns an empty string if not defined
char *Cvar_CompleteVariable (char *partial);
// attempts to match a partial variable name for command line completion
// returns NULL if nothing fits
void Cvar_GetLatchedVars (void);
// any CVAR_LATCHED variables that have been set will now take effect
qboolean Cvar_Command (void);
// called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known
// command. Returns true if the command was a variable reference that
// was handled. (print or change)
void Cvar_WriteVariables (char *path);
// appends lines containing "set variable value" for all variables
// with the archive flag set to true.
void Cvar_Init (void);
char *Cvar_Userinfo (void);
// returns an info string containing all the CVAR_USERINFO cvars
char *Cvar_Serverinfo (void);
// returns an info string containing all the CVAR_SERVERINFO cvars
extern qboolean userinfo_modified;
// this is set each time a CVAR_USERINFO variable is changed
// so that the client knows to send it to the server
/*
==============================================================
NET
==============================================================
*/
// net.h -- quake's interface to the networking layer
#define PORT_ANY -1
#define MAX_MSGLEN 1400 // max length of a message
#define PACKET_HEADER 10 // two ints and a short
typedef enum {NA_LOOPBACK, NA_BROADCAST, NA_IP, NA_IPX, NA_BROADCAST_IPX} netadrtype_t;
typedef enum {NS_CLIENT, NS_SERVER} netsrc_t;
typedef struct
{
netadrtype_t type;
byte ip[4];
byte ipx[10];
unsigned short port;
} netadr_t;
void NET_Init (void);
void NET_Shutdown (void);
void NET_Config (qboolean multiplayer);
qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message);
void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to);
qboolean NET_CompareAdr (netadr_t a, netadr_t b);
qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b);
qboolean NET_IsLocalAddress (netadr_t adr);
char *NET_AdrToString (netadr_t a);
qboolean NET_StringToAdr (char *s, netadr_t *a);
void NET_Sleep(int msec);
//============================================================================
#define OLD_AVG 0.99 // total = oldtotal*OLD_AVG + new*(1-OLD_AVG)
#define MAX_LATENT 32
typedef struct
{
qboolean fatal_error;
netsrc_t sock;
int dropped; // between last packet and previous
int last_received; // for timeouts
int last_sent; // for retransmits
netadr_t remote_address;
int qport; // qport value to write when transmitting
// sequencing variables
int incoming_sequence;
int incoming_acknowledged;
int incoming_reliable_acknowledged; // single bit
int incoming_reliable_sequence; // single bit, maintained local
int outgoing_sequence;
int reliable_sequence; // single bit
int last_reliable_sequence; // sequence number of last send
// reliable staging and holding areas
sizebuf_t message; // writing buffer to send to server
byte message_buf[MAX_MSGLEN-16]; // leave space for header
// message is copied to this buffer when it is first transfered
int reliable_length;
byte reliable_buf[MAX_MSGLEN-16]; // unacked reliable message
} netchan_t;
extern netadr_t net_from;
extern sizebuf_t net_message;
extern byte net_message_buffer[MAX_MSGLEN];
void Netchan_Init (void);
void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t adr, int qport);
qboolean Netchan_NeedReliable (netchan_t *chan);
void Netchan_Transmit (netchan_t *chan, int length, byte *data);
void Netchan_OutOfBand (int net_socket, netadr_t adr, int length, byte *data);
void Netchan_OutOfBandPrint (int net_socket, netadr_t adr, char *format, ...);
qboolean Netchan_Process (netchan_t *chan, sizebuf_t *msg);
qboolean Netchan_CanReliable (netchan_t *chan);
/*
==============================================================
CMODEL
==============================================================
*/
#include "../qcommon/qfiles.h"
cmodel_t *CM_LoadMap (char *name, qboolean clientload, unsigned *checksum);
cmodel_t *CM_InlineModel (char *name); // *1, *2, etc
int CM_NumClusters (void);
int CM_NumInlineModels (void);
char *CM_EntityString (void);
// creates a clipping hull for an arbitrary box
int CM_HeadnodeForBox (vec3_t mins, vec3_t maxs);
// returns an ORed contents mask
int CM_PointContents (vec3_t p, int headnode);
int CM_TransformedPointContents (vec3_t p, int headnode, vec3_t origin, vec3_t angles);
trace_t CM_BoxTrace (vec3_t start, vec3_t end,
vec3_t mins, vec3_t maxs,
int headnode, int brushmask);
trace_t CM_TransformedBoxTrace (vec3_t start, vec3_t end,
vec3_t mins, vec3_t maxs,
int headnode, int brushmask,
vec3_t origin, vec3_t angles);
byte *CM_ClusterPVS (int cluster);
byte *CM_ClusterPHS (int cluster);
int CM_PointLeafnum (vec3_t p);
// call with topnode set to the headnode, returns with topnode
// set to the first node that splits the box
int CM_BoxLeafnums (vec3_t mins, vec3_t maxs, int *list,
int listsize, int *topnode);
int CM_LeafContents (int leafnum);
int CM_LeafCluster (int leafnum);
int CM_LeafArea (int leafnum);
void CM_SetAreaPortalState (int portalnum, qboolean open);
qboolean CM_AreasConnected (int area1, int area2);
int CM_WriteAreaBits (byte *buffer, int area);
qboolean CM_HeadnodeVisible (int headnode, byte *visbits);
void CM_WritePortalState (FILE *f);
void CM_ReadPortalState (FILE *f);
/*
==============================================================
PLAYER MOVEMENT CODE
Common between server and client so prediction matches
==============================================================
*/
extern float pm_airaccelerate;
void Pmove (pmove_t *pmove);
/*
==============================================================
FILESYSTEM
==============================================================
*/
void FS_InitFilesystem (void);
void FS_SetGamedir (char *dir);
char *FS_Gamedir (void);
char *FS_NextPath (char *prevpath);
void FS_ExecAutoexec (void);
int FS_FOpenFile (char *filename, FILE **file);
void FS_FCloseFile (FILE *f);
// note: this can't be called from another DLL, due to MS libc issues
int FS_LoadFile (char *path, void **buffer);
// a null buffer will just return the file length without loading
// a -1 length is not present
void FS_Read (void *buffer, int len, FILE *f);
// properly handles partial reads
void FS_FreeFile (void *buffer);
void FS_CreatePath (char *path);
/*
==============================================================
MISC
==============================================================
*/
#define ERR_FATAL 0 // exit the entire game with a popup window
#define ERR_DROP 1 // print to console and disconnect from game
#define ERR_QUIT 2 // not an error, just a normal exit
#define EXEC_NOW 0 // don't return until completed
#define EXEC_INSERT 1 // insert at current position, but don't run yet
#define EXEC_APPEND 2 // add to end of the command buffer
#define PRINT_ALL 0
#define PRINT_DEVELOPER 1 // only print when "developer 1"
void Com_BeginRedirect (int target, char *buffer, int buffersize, void (*flush));
void Com_EndRedirect (void);
void Com_Printf (char *fmt, ...);
void Com_DPrintf (char *fmt, ...);
void Com_Error (int code, char *fmt, ...);
void Com_Quit (void);
int Com_ServerState (void); // this should have just been a cvar...
void Com_SetServerState (int state);
unsigned Com_BlockChecksum (void *buffer, int length);
byte COM_BlockSequenceCRCByte (byte *base, int length, int sequence);
float frand(void); // 0 ti 1
float crand(void); // -1 to 1
extern cvar_t *developer;
extern cvar_t *dedicated;
extern cvar_t *host_speeds;
extern cvar_t *log_stats;
extern FILE *log_stats_file;
// host_speeds times
extern int time_before_game;
extern int time_after_game;
extern int time_before_ref;
extern int time_after_ref;
void Z_Free (void *ptr);
void *Z_Malloc (int size); // returns 0 filled memory
void *Z_TagMalloc (int size, int tag);
void Z_FreeTags (int tag);
void Qcommon_Init (int argc, char **argv);
void Qcommon_Frame (int msec);
void Qcommon_Shutdown (void);
#define NUMVERTEXNORMALS 162
extern vec3_t bytedirs[NUMVERTEXNORMALS];
// this is in the client code, but can be used for debugging from server
void SCR_DebugGraph (float value, int color);
/*
==============================================================
NON-PORTABLE SYSTEM SERVICES
==============================================================
*/
void Sys_Init (void);
void Sys_AppActivate (void);
void Sys_UnloadGame (void);
void *Sys_GetGameAPI (void *parms);
// loads the game dll and calls the api init function
char *Sys_ConsoleInput (void);
void Sys_ConsoleOutput (char *string);
void Sys_SendKeyEvents (void);
void Sys_Error (char *error, ...);
void Sys_Quit (void);
char *Sys_GetClipboardData( void );
void Sys_CopyProtect (void);
/*
==============================================================
CLIENT / SERVER SYSTEMS
==============================================================
*/
void CL_Init (void);
void CL_Drop (void);
void CL_Shutdown (void);
void CL_Frame (int msec);
void Con_Print (char *text);
void SCR_BeginLoadingPlaque (void);
void SV_Init (void);
void SV_Shutdown (char *finalmsg, qboolean reconnect);
void SV_Frame (int msec);

482
qcommon/qfiles.h Normal file
View File

@ -0,0 +1,482 @@
/*
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.
*/
//
// qfiles.h: quake file formats
// This file must be identical in the quake and utils directories
//
/*
========================================================================
The .pak files are just a linear collapse of a directory tree
========================================================================
*/
#define IDPAKHEADER (('K'<<24)+('C'<<16)+('A'<<8)+'P')
typedef struct
{
char name[56];
int filepos, filelen;
} dpackfile_t;
typedef struct
{
int ident; // == IDPAKHEADER
int dirofs;
int dirlen;
} dpackheader_t;
#define MAX_FILES_IN_PACK 4096
/*
========================================================================
PCX files are used for as many images as possible
========================================================================
*/
typedef struct
{
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
unsigned short xmin,ymin,xmax,ymax;
unsigned short hres,vres;
unsigned char palette[48];
char reserved;
char color_planes;
unsigned short bytes_per_line;
unsigned short palette_type;
char filler[58];
unsigned char data; // unbounded
} pcx_t;
/*
========================================================================
.MD2 triangle model file format
========================================================================
*/
#define IDALIASHEADER (('2'<<24)+('P'<<16)+('D'<<8)+'I')
#define ALIAS_VERSION 8
#define MAX_TRIANGLES 4096
#define MAX_VERTS 2048
#define MAX_FRAMES 512
#define MAX_MD2SKINS 32
#define MAX_SKINNAME 64
typedef struct
{
short s;
short t;
} dstvert_t;
typedef struct
{
short index_xyz[3];
short index_st[3];
} dtriangle_t;
typedef struct
{
byte v[3]; // scaled byte to fit in frame mins/maxs
byte lightnormalindex;
} dtrivertx_t;
#define DTRIVERTX_V0 0
#define DTRIVERTX_V1 1
#define DTRIVERTX_V2 2
#define DTRIVERTX_LNI 3
#define DTRIVERTX_SIZE 4
typedef struct
{
float scale[3]; // multiply byte verts by this
float translate[3]; // then add this
char name[16]; // frame name from grabbing
dtrivertx_t verts[1]; // variable sized
} daliasframe_t;
// the glcmd format:
// a positive integer starts a tristrip command, followed by that many
// vertex structures.
// a negative integer starts a trifan command, followed by -x vertexes
// a zero indicates the end of the command list.
// a vertex consists of a floating point s, a floating point t,
// and an integer vertex index.
typedef struct
{
int ident;
int version;
int skinwidth;
int skinheight;
int framesize; // byte size of each frame
int num_skins;
int num_xyz;
int num_st; // greater than num_xyz for seams
int num_tris;
int num_glcmds; // dwords in strip/fan command list
int num_frames;
int ofs_skins; // each skin is a MAX_SKINNAME string
int ofs_st; // byte offset from start for stverts
int ofs_tris; // offset for dtriangles
int ofs_frames; // offset for first frame
int ofs_glcmds;
int ofs_end; // end of file
} dmdl_t;
/*
========================================================================
.SP2 sprite file format
========================================================================
*/
#define IDSPRITEHEADER (('2'<<24)+('S'<<16)+('D'<<8)+'I')
// little-endian "IDS2"
#define SPRITE_VERSION 2
typedef struct
{
int width, height;
int origin_x, origin_y; // raster coordinates inside pic
char name[MAX_SKINNAME]; // name of pcx file
} dsprframe_t;
typedef struct {
int ident;
int version;
int numframes;
dsprframe_t frames[1]; // variable sized
} dsprite_t;
/*
==============================================================================
.WAL texture file format
==============================================================================
*/
#define MIPLEVELS 4
typedef struct miptex_s
{
char name[32];
unsigned width, height;
unsigned offsets[MIPLEVELS]; // four mip maps stored
char animname[32]; // next frame in animation chain
int flags;
int contents;
int value;
} miptex_t;
/*
==============================================================================
.BSP file format
==============================================================================
*/
#define IDBSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I')
// little-endian "IBSP"
#define BSPVERSION 38
// upper design bounds
// leaffaces, leafbrushes, planes, and verts are still bounded by
// 16 bit short limits
#define MAX_MAP_MODELS 1024
#define MAX_MAP_BRUSHES 8192
#define MAX_MAP_ENTITIES 2048
#define MAX_MAP_ENTSTRING 0x40000
#define MAX_MAP_TEXINFO 8192
#define MAX_MAP_AREAS 256
#define MAX_MAP_AREAPORTALS 1024
#define MAX_MAP_PLANES 65536
#define MAX_MAP_NODES 65536
#define MAX_MAP_BRUSHSIDES 65536
#define MAX_MAP_LEAFS 65536
#define MAX_MAP_VERTS 65536
#define MAX_MAP_FACES 65536
#define MAX_MAP_LEAFFACES 65536
#define MAX_MAP_LEAFBRUSHES 65536
#define MAX_MAP_PORTALS 65536
#define MAX_MAP_EDGES 128000
#define MAX_MAP_SURFEDGES 256000
#define MAX_MAP_LIGHTING 0x200000
#define MAX_MAP_VISIBILITY 0x100000
// key / value pair sizes
#define MAX_KEY 32
#define MAX_VALUE 1024
//=============================================================================
typedef struct
{
int fileofs, filelen;
} lump_t;
#define LUMP_ENTITIES 0
#define LUMP_PLANES 1
#define LUMP_VERTEXES 2
#define LUMP_VISIBILITY 3
#define LUMP_NODES 4
#define LUMP_TEXINFO 5
#define LUMP_FACES 6
#define LUMP_LIGHTING 7
#define LUMP_LEAFS 8
#define LUMP_LEAFFACES 9
#define LUMP_LEAFBRUSHES 10
#define LUMP_EDGES 11
#define LUMP_SURFEDGES 12
#define LUMP_MODELS 13
#define LUMP_BRUSHES 14
#define LUMP_BRUSHSIDES 15
#define LUMP_POP 16
#define LUMP_AREAS 17
#define LUMP_AREAPORTALS 18
#define HEADER_LUMPS 19
typedef struct
{
int ident;
int version;
lump_t lumps[HEADER_LUMPS];
} dheader_t;
typedef struct
{
float mins[3], maxs[3];
float origin[3]; // for sounds or lights
int headnode;
int firstface, numfaces; // submodels just draw faces
// without walking the bsp tree
} dmodel_t;
typedef struct
{
float point[3];
} dvertex_t;
// 0-2 are axial planes
#define PLANE_X 0
#define PLANE_Y 1
#define PLANE_Z 2
// 3-5 are non-axial planes snapped to the nearest
#define PLANE_ANYX 3
#define PLANE_ANYY 4
#define PLANE_ANYZ 5
// planes (x&~1) and (x&~1)+1 are always opposites
typedef struct
{
float normal[3];
float dist;
int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
} dplane_t;
// contents flags are seperate bits
// a given brush can contribute multiple content bits
// multiple brushes can be in a single leaf
// these definitions also need to be in q_shared.h!
// lower bits are stronger, and will eat weaker brushes completely
#define CONTENTS_SOLID 1 // an eye is never valid in a solid
#define CONTENTS_WINDOW 2 // translucent, but not watery
#define CONTENTS_AUX 4
#define CONTENTS_LAVA 8
#define CONTENTS_SLIME 16
#define CONTENTS_WATER 32
#define CONTENTS_MIST 64
#define LAST_VISIBLE_CONTENTS 64
// remaining contents are non-visible, and don't eat brushes
#define CONTENTS_AREAPORTAL 0x8000
#define CONTENTS_PLAYERCLIP 0x10000
#define CONTENTS_MONSTERCLIP 0x20000
// currents can be added to any other contents, and may be mixed
#define CONTENTS_CURRENT_0 0x40000
#define CONTENTS_CURRENT_90 0x80000
#define CONTENTS_CURRENT_180 0x100000
#define CONTENTS_CURRENT_270 0x200000
#define CONTENTS_CURRENT_UP 0x400000
#define CONTENTS_CURRENT_DOWN 0x800000
#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity
#define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game
#define CONTENTS_DEADMONSTER 0x4000000
#define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs
#define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans
#define CONTENTS_LADDER 0x20000000
#define SURF_LIGHT 0x1 // value will hold the light strength
#define SURF_SLICK 0x2 // effects game physics
#define SURF_SKY 0x4 // don't draw, but add to skybox
#define SURF_WARP 0x8 // turbulent water warp
#define SURF_TRANS33 0x10
#define SURF_TRANS66 0x20
#define SURF_FLOWING 0x40 // scroll towards angle
#define SURF_NODRAW 0x80 // don't bother referencing the texture
typedef struct
{
int planenum;
int children[2]; // negative numbers are -(leafs+1), not nodes
short mins[3]; // for frustom culling
short maxs[3];
unsigned short firstface;
unsigned short numfaces; // counting both sides
} dnode_t;
typedef struct texinfo_s
{
float vecs[2][4]; // [s/t][xyz offset]
int flags; // miptex flags + overrides
int value; // light emission, etc
char texture[32]; // texture name (textures/*.wal)
int nexttexinfo; // for animations, -1 = end of chain
} texinfo_t;
// note that edge 0 is never used, because negative edge nums are used for
// counterclockwise use of the edge in a face
typedef struct
{
unsigned short v[2]; // vertex numbers
} dedge_t;
#define MAXLIGHTMAPS 4
typedef struct
{
unsigned short planenum;
short side;
int firstedge; // we must support > 64k edges
short numedges;
short texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
int lightofs; // start of [numstyles*surfsize] samples
} dface_t;
typedef struct
{
int contents; // OR of all brushes (not needed?)
short cluster;
short area;
short mins[3]; // for frustum culling
short maxs[3];
unsigned short firstleafface;
unsigned short numleaffaces;
unsigned short firstleafbrush;
unsigned short numleafbrushes;
} dleaf_t;
typedef struct
{
unsigned short planenum; // facing out of the leaf
short texinfo;
} dbrushside_t;
typedef struct
{
int firstside;
int numsides;
int contents;
} dbrush_t;
#define ANGLE_UP -1
#define ANGLE_DOWN -2
// the visibility lump consists of a header with a count, then
// byte offsets for the PVS and PHS of each cluster, then the raw
// compressed bit vectors
#define DVIS_PVS 0
#define DVIS_PHS 1
typedef struct
{
int numclusters;
int bitofs[8][2]; // bitofs[numclusters][2]
} dvis_t;
// each area has a list of portals that lead into other areas
// when portals are closed, other areas may not be visible or
// hearable even if the vis info says that it should be
typedef struct
{
int portalnum;
int otherarea;
} dareaportal_t;
typedef struct
{
int numareaportals;
int firstareaportal;
} darea_t;

181
ref_gl/anorms.h Normal file
View File

@ -0,0 +1,181 @@
/*
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.
*/
{-0.525731, 0.000000, 0.850651},
{-0.442863, 0.238856, 0.864188},
{-0.295242, 0.000000, 0.955423},
{-0.309017, 0.500000, 0.809017},
{-0.162460, 0.262866, 0.951056},
{0.000000, 0.000000, 1.000000},
{0.000000, 0.850651, 0.525731},
{-0.147621, 0.716567, 0.681718},
{0.147621, 0.716567, 0.681718},
{0.000000, 0.525731, 0.850651},
{0.309017, 0.500000, 0.809017},
{0.525731, 0.000000, 0.850651},
{0.295242, 0.000000, 0.955423},
{0.442863, 0.238856, 0.864188},
{0.162460, 0.262866, 0.951056},
{-0.681718, 0.147621, 0.716567},
{-0.809017, 0.309017, 0.500000},
{-0.587785, 0.425325, 0.688191},
{-0.850651, 0.525731, 0.000000},
{-0.864188, 0.442863, 0.238856},
{-0.716567, 0.681718, 0.147621},
{-0.688191, 0.587785, 0.425325},
{-0.500000, 0.809017, 0.309017},
{-0.238856, 0.864188, 0.442863},
{-0.425325, 0.688191, 0.587785},
{-0.716567, 0.681718, -0.147621},
{-0.500000, 0.809017, -0.309017},
{-0.525731, 0.850651, 0.000000},
{0.000000, 0.850651, -0.525731},
{-0.238856, 0.864188, -0.442863},
{0.000000, 0.955423, -0.295242},
{-0.262866, 0.951056, -0.162460},
{0.000000, 1.000000, 0.000000},
{0.000000, 0.955423, 0.295242},
{-0.262866, 0.951056, 0.162460},
{0.238856, 0.864188, 0.442863},
{0.262866, 0.951056, 0.162460},
{0.500000, 0.809017, 0.309017},
{0.238856, 0.864188, -0.442863},
{0.262866, 0.951056, -0.162460},
{0.500000, 0.809017, -0.309017},
{0.850651, 0.525731, 0.000000},
{0.716567, 0.681718, 0.147621},
{0.716567, 0.681718, -0.147621},
{0.525731, 0.850651, 0.000000},
{0.425325, 0.688191, 0.587785},
{0.864188, 0.442863, 0.238856},
{0.688191, 0.587785, 0.425325},
{0.809017, 0.309017, 0.500000},
{0.681718, 0.147621, 0.716567},
{0.587785, 0.425325, 0.688191},
{0.955423, 0.295242, 0.000000},
{1.000000, 0.000000, 0.000000},
{0.951056, 0.162460, 0.262866},
{0.850651, -0.525731, 0.000000},
{0.955423, -0.295242, 0.000000},
{0.864188, -0.442863, 0.238856},
{0.951056, -0.162460, 0.262866},
{0.809017, -0.309017, 0.500000},
{0.681718, -0.147621, 0.716567},
{0.850651, 0.000000, 0.525731},
{0.864188, 0.442863, -0.238856},
{0.809017, 0.309017, -0.500000},
{0.951056, 0.162460, -0.262866},
{0.525731, 0.000000, -0.850651},
{0.681718, 0.147621, -0.716567},
{0.681718, -0.147621, -0.716567},
{0.850651, 0.000000, -0.525731},
{0.809017, -0.309017, -0.500000},
{0.864188, -0.442863, -0.238856},
{0.951056, -0.162460, -0.262866},
{0.147621, 0.716567, -0.681718},
{0.309017, 0.500000, -0.809017},
{0.425325, 0.688191, -0.587785},
{0.442863, 0.238856, -0.864188},
{0.587785, 0.425325, -0.688191},
{0.688191, 0.587785, -0.425325},
{-0.147621, 0.716567, -0.681718},
{-0.309017, 0.500000, -0.809017},
{0.000000, 0.525731, -0.850651},
{-0.525731, 0.000000, -0.850651},
{-0.442863, 0.238856, -0.864188},
{-0.295242, 0.000000, -0.955423},
{-0.162460, 0.262866, -0.951056},
{0.000000, 0.000000, -1.000000},
{0.295242, 0.000000, -0.955423},
{0.162460, 0.262866, -0.951056},
{-0.442863, -0.238856, -0.864188},
{-0.309017, -0.500000, -0.809017},
{-0.162460, -0.262866, -0.951056},
{0.000000, -0.850651, -0.525731},
{-0.147621, -0.716567, -0.681718},
{0.147621, -0.716567, -0.681718},
{0.000000, -0.525731, -0.850651},
{0.309017, -0.500000, -0.809017},
{0.442863, -0.238856, -0.864188},
{0.162460, -0.262866, -0.951056},
{0.238856, -0.864188, -0.442863},
{0.500000, -0.809017, -0.309017},
{0.425325, -0.688191, -0.587785},
{0.716567, -0.681718, -0.147621},
{0.688191, -0.587785, -0.425325},
{0.587785, -0.425325, -0.688191},
{0.000000, -0.955423, -0.295242},
{0.000000, -1.000000, 0.000000},
{0.262866, -0.951056, -0.162460},
{0.000000, -0.850651, 0.525731},
{0.000000, -0.955423, 0.295242},
{0.238856, -0.864188, 0.442863},
{0.262866, -0.951056, 0.162460},
{0.500000, -0.809017, 0.309017},
{0.716567, -0.681718, 0.147621},
{0.525731, -0.850651, 0.000000},
{-0.238856, -0.864188, -0.442863},
{-0.500000, -0.809017, -0.309017},
{-0.262866, -0.951056, -0.162460},
{-0.850651, -0.525731, 0.000000},
{-0.716567, -0.681718, -0.147621},
{-0.716567, -0.681718, 0.147621},
{-0.525731, -0.850651, 0.000000},
{-0.500000, -0.809017, 0.309017},
{-0.238856, -0.864188, 0.442863},
{-0.262866, -0.951056, 0.162460},
{-0.864188, -0.442863, 0.238856},
{-0.809017, -0.309017, 0.500000},
{-0.688191, -0.587785, 0.425325},
{-0.681718, -0.147621, 0.716567},
{-0.442863, -0.238856, 0.864188},
{-0.587785, -0.425325, 0.688191},
{-0.309017, -0.500000, 0.809017},
{-0.147621, -0.716567, 0.681718},
{-0.425325, -0.688191, 0.587785},
{-0.162460, -0.262866, 0.951056},
{0.442863, -0.238856, 0.864188},
{0.162460, -0.262866, 0.951056},
{0.309017, -0.500000, 0.809017},
{0.147621, -0.716567, 0.681718},
{0.000000, -0.525731, 0.850651},
{0.425325, -0.688191, 0.587785},
{0.587785, -0.425325, 0.688191},
{0.688191, -0.587785, 0.425325},
{-0.955423, 0.295242, 0.000000},
{-0.951056, 0.162460, 0.262866},
{-1.000000, 0.000000, 0.000000},
{-0.850651, 0.000000, 0.525731},
{-0.955423, -0.295242, 0.000000},
{-0.951056, -0.162460, 0.262866},
{-0.864188, 0.442863, -0.238856},
{-0.951056, 0.162460, -0.262866},
{-0.809017, 0.309017, -0.500000},
{-0.864188, -0.442863, -0.238856},
{-0.951056, -0.162460, -0.262866},
{-0.809017, -0.309017, -0.500000},
{-0.681718, 0.147621, -0.716567},
{-0.681718, -0.147621, -0.716567},
{-0.850651, 0.000000, -0.525731},
{-0.688191, 0.587785, -0.425325},
{-0.587785, 0.425325, -0.688191},
{-0.425325, 0.688191, -0.587785},
{-0.425325, -0.688191, -0.587785},
{-0.587785, -0.425325, -0.688191},
{-0.688191, -0.587785, -0.425325},

37
ref_gl/anormtab.h Normal file
View File

@ -0,0 +1,37 @@
/*
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.
*/
{
{1.23,1.30,1.47,1.35,1.56,1.71,1.37,1.38,1.59,1.60,1.79,1.97,1.88,1.92,1.79,1.02,0.93,1.07,0.82,0.87,0.88,0.94,0.96,1.14,1.11,0.82,0.83,0.89,0.89,0.86,0.94,0.91,1.00,1.21,0.98,1.48,1.30,1.57,0.96,1.07,1.14,1.60,1.61,1.40,1.37,1.72,1.78,1.79,1.93,1.99,1.90,1.68,1.71,1.86,1.60,1.68,1.78,1.86,1.93,1.99,1.97,1.44,1.22,1.49,0.93,0.99,0.99,1.23,1.22,1.44,1.49,0.89,0.89,0.97,0.91,0.98,1.19,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.19,0.98,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.87,0.93,0.94,1.02,1.30,1.07,1.35,1.38,1.11,1.56,1.92,1.79,1.79,1.59,1.60,1.72,1.90,1.79,0.80,0.85,0.79,0.93,0.80,0.85,0.77,0.74,0.72,0.77,0.74,0.72,0.70,0.70,0.71,0.76,0.73,0.79,0.79,0.73,0.76,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.26,1.26,1.48,1.23,1.50,1.71,1.14,1.19,1.38,1.46,1.64,1.94,1.87,1.84,1.71,1.02,0.92,1.00,0.79,0.85,0.84,0.91,0.90,0.98,0.99,0.77,0.77,0.83,0.82,0.79,0.86,0.84,0.92,0.99,0.91,1.24,1.03,1.33,0.88,0.94,0.97,1.41,1.39,1.18,1.11,1.51,1.61,1.59,1.80,1.91,1.76,1.54,1.65,1.76,1.70,1.70,1.85,1.85,1.97,1.99,1.93,1.28,1.09,1.39,0.92,0.97,0.99,1.18,1.26,1.52,1.48,0.83,0.85,0.90,0.88,0.93,1.00,0.77,0.73,0.78,0.72,0.71,0.74,0.75,0.79,0.86,0.81,0.75,0.81,0.79,0.96,0.88,0.94,0.86,0.93,0.92,0.85,1.08,1.33,1.05,1.55,1.31,1.01,1.05,1.27,1.31,1.60,1.47,1.70,1.54,1.76,1.76,1.57,0.93,0.90,0.99,0.88,0.88,0.95,0.97,1.11,1.39,1.20,0.92,0.97,1.01,1.10,1.39,1.22,1.51,1.58,1.32,1.64,1.97,1.85,1.91,1.77,1.74,1.88,1.99,1.91,0.79,0.86,0.80,0.94,0.84,0.88,0.74,0.74,0.71,0.82,0.77,0.76,0.70,0.73,0.72,0.73,0.70,0.74,0.85,0.77,0.82,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.34,1.27,1.53,1.17,1.46,1.71,0.98,1.05,1.20,1.34,1.48,1.86,1.82,1.71,1.62,1.09,0.94,0.99,0.79,0.85,0.82,0.90,0.87,0.93,0.96,0.76,0.74,0.79,0.76,0.74,0.79,0.78,0.85,0.92,0.85,1.00,0.93,1.06,0.81,0.86,0.89,1.16,1.12,0.97,0.95,1.28,1.38,1.35,1.60,1.77,1.57,1.33,1.50,1.58,1.69,1.63,1.82,1.74,1.91,1.92,1.80,1.04,0.97,1.21,0.90,0.93,0.97,1.05,1.21,1.48,1.37,0.77,0.80,0.84,0.85,0.88,0.92,0.73,0.71,0.74,0.74,0.71,0.75,0.73,0.79,0.84,0.78,0.79,0.86,0.81,1.05,0.94,0.99,0.90,0.95,0.92,0.86,1.24,1.44,1.14,1.59,1.34,1.02,1.27,1.50,1.49,1.80,1.69,1.86,1.72,1.87,1.80,1.69,1.00,0.98,1.23,0.95,0.96,1.09,1.16,1.37,1.63,1.46,0.99,1.10,1.25,1.24,1.51,1.41,1.67,1.77,1.55,1.72,1.95,1.89,1.98,1.91,1.86,1.97,1.99,1.94,0.81,0.89,0.85,0.98,0.90,0.94,0.75,0.78,0.73,0.89,0.83,0.82,0.72,0.77,0.76,0.72,0.70,0.71,0.91,0.83,0.89,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.46,1.34,1.60,1.16,1.46,1.71,0.94,0.99,1.05,1.26,1.33,1.74,1.76,1.57,1.54,1.23,0.98,1.05,0.83,0.89,0.84,0.92,0.87,0.91,0.96,0.78,0.74,0.79,0.72,0.72,0.75,0.76,0.80,0.88,0.83,0.94,0.87,0.95,0.76,0.80,0.82,0.97,0.96,0.89,0.88,1.08,1.11,1.10,1.37,1.59,1.37,1.07,1.27,1.34,1.57,1.45,1.69,1.55,1.77,1.79,1.60,0.93,0.90,0.99,0.86,0.87,0.93,0.96,1.07,1.35,1.18,0.73,0.76,0.77,0.81,0.82,0.85,0.70,0.71,0.72,0.78,0.73,0.77,0.73,0.79,0.82,0.76,0.83,0.90,0.84,1.18,0.98,1.03,0.92,0.95,0.90,0.86,1.32,1.45,1.15,1.53,1.27,0.99,1.42,1.65,1.58,1.93,1.83,1.94,1.81,1.88,1.74,1.70,1.19,1.17,1.44,1.11,1.15,1.36,1.41,1.61,1.81,1.67,1.22,1.34,1.50,1.42,1.65,1.61,1.82,1.91,1.75,1.80,1.89,1.89,1.98,1.99,1.94,1.98,1.92,1.87,0.86,0.95,0.92,1.14,0.98,1.03,0.79,0.84,0.77,0.97,0.90,0.89,0.76,0.82,0.82,0.74,0.72,0.71,0.98,0.89,0.97,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.60,1.44,1.68,1.22,1.49,1.71,0.93,0.99,0.99,1.23,1.22,1.60,1.68,1.44,1.49,1.40,1.14,1.19,0.89,0.96,0.89,0.97,0.89,0.91,0.98,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.91,0.83,0.89,0.72,0.76,0.76,0.89,0.89,0.82,0.82,0.98,0.96,0.97,1.14,1.40,1.19,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.70,0.72,0.73,0.77,0.76,0.79,0.70,0.72,0.71,0.82,0.77,0.80,0.74,0.79,0.80,0.74,0.87,0.93,0.85,1.23,1.02,1.02,0.93,0.93,0.87,0.85,1.30,1.35,1.07,1.38,1.11,0.94,1.47,1.71,1.56,1.97,1.88,1.92,1.79,1.79,1.59,1.60,1.30,1.35,1.56,1.37,1.38,1.59,1.60,1.79,1.92,1.79,1.48,1.57,1.72,1.61,1.78,1.79,1.93,1.99,1.90,1.86,1.78,1.86,1.93,1.99,1.97,1.90,1.79,1.72,0.94,1.07,1.00,1.37,1.21,1.30,0.86,0.91,0.83,1.14,0.98,0.96,0.82,0.88,0.89,0.79,0.76,0.73,1.07,0.94,1.11,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.74,1.57,1.76,1.33,1.54,1.71,0.94,1.05,0.99,1.26,1.16,1.46,1.60,1.34,1.46,1.59,1.37,1.37,0.97,1.11,0.96,1.10,0.95,0.94,1.08,0.89,0.82,0.88,0.72,0.76,0.75,0.80,0.80,0.88,0.87,0.91,0.83,0.87,0.72,0.76,0.74,0.83,0.84,0.78,0.79,0.96,0.89,0.92,0.98,1.23,1.05,0.86,0.92,0.95,1.11,0.98,1.22,1.03,1.34,1.42,1.14,0.79,0.77,0.84,0.78,0.76,0.82,0.82,0.89,0.97,0.90,0.70,0.71,0.71,0.73,0.72,0.74,0.73,0.76,0.72,0.86,0.81,0.82,0.76,0.79,0.77,0.73,0.90,0.95,0.86,1.18,1.03,0.98,0.92,0.90,0.83,0.84,1.19,1.17,0.98,1.15,0.97,0.89,1.42,1.65,1.44,1.93,1.83,1.81,1.67,1.61,1.36,1.41,1.32,1.45,1.58,1.57,1.53,1.74,1.70,1.88,1.94,1.81,1.69,1.77,1.87,1.79,1.89,1.92,1.98,1.99,1.98,1.89,1.65,1.80,1.82,1.91,1.94,1.75,1.61,1.50,1.07,1.34,1.27,1.60,1.45,1.55,0.93,0.99,0.90,1.35,1.18,1.07,0.87,0.93,0.96,0.85,0.82,0.77,1.15,0.99,1.27,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.86,1.71,1.82,1.48,1.62,1.71,0.98,1.20,1.05,1.34,1.17,1.34,1.53,1.27,1.46,1.77,1.60,1.57,1.16,1.38,1.12,1.35,1.06,1.00,1.28,0.97,0.89,0.95,0.76,0.81,0.79,0.86,0.85,0.92,0.93,0.93,0.85,0.87,0.74,0.78,0.74,0.79,0.82,0.76,0.79,0.96,0.85,0.90,0.94,1.09,0.99,0.81,0.85,0.89,0.95,0.90,0.99,0.94,1.10,1.24,0.98,0.75,0.73,0.78,0.74,0.72,0.77,0.76,0.82,0.89,0.83,0.73,0.71,0.71,0.71,0.70,0.72,0.77,0.80,0.74,0.90,0.85,0.84,0.78,0.79,0.75,0.73,0.92,0.95,0.86,1.05,0.99,0.94,0.90,0.86,0.79,0.81,1.00,0.98,0.91,0.96,0.89,0.83,1.27,1.50,1.23,1.80,1.69,1.63,1.46,1.37,1.09,1.16,1.24,1.44,1.49,1.69,1.59,1.80,1.69,1.87,1.86,1.72,1.82,1.91,1.94,1.92,1.95,1.99,1.98,1.91,1.97,1.89,1.51,1.72,1.67,1.77,1.86,1.55,1.41,1.25,1.33,1.58,1.50,1.80,1.63,1.74,1.04,1.21,0.97,1.48,1.37,1.21,0.93,0.97,1.05,0.92,0.88,0.84,1.14,1.02,1.34,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.94,1.84,1.87,1.64,1.71,1.71,1.14,1.38,1.19,1.46,1.23,1.26,1.48,1.26,1.50,1.91,1.80,1.76,1.41,1.61,1.39,1.59,1.33,1.24,1.51,1.18,0.97,1.11,0.82,0.88,0.86,0.94,0.92,0.99,1.03,0.98,0.91,0.90,0.79,0.84,0.77,0.79,0.84,0.77,0.83,0.99,0.85,0.91,0.92,1.02,1.00,0.79,0.80,0.86,0.88,0.84,0.92,0.88,0.97,1.10,0.94,0.74,0.71,0.74,0.72,0.70,0.73,0.72,0.76,0.82,0.77,0.77,0.73,0.74,0.71,0.70,0.73,0.83,0.85,0.78,0.92,0.88,0.86,0.81,0.79,0.74,0.75,0.92,0.93,0.85,0.96,0.94,0.88,0.86,0.81,0.75,0.79,0.93,0.90,0.85,0.88,0.82,0.77,1.05,1.27,0.99,1.60,1.47,1.39,1.20,1.11,0.95,0.97,1.08,1.33,1.31,1.70,1.55,1.76,1.57,1.76,1.70,1.54,1.85,1.97,1.91,1.99,1.97,1.99,1.91,1.77,1.88,1.85,1.39,1.64,1.51,1.58,1.74,1.32,1.22,1.01,1.54,1.76,1.65,1.93,1.70,1.85,1.28,1.39,1.09,1.52,1.48,1.26,0.97,0.99,1.18,1.00,0.93,0.90,1.05,1.01,1.31,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.97,1.92,1.88,1.79,1.79,1.71,1.37,1.59,1.38,1.60,1.35,1.23,1.47,1.30,1.56,1.99,1.93,1.90,1.60,1.78,1.61,1.79,1.57,1.48,1.72,1.40,1.14,1.37,0.89,0.96,0.94,1.07,1.00,1.21,1.30,1.14,0.98,0.96,0.86,0.91,0.83,0.82,0.88,0.82,0.89,1.11,0.87,0.94,0.93,1.02,1.07,0.80,0.79,0.85,0.82,0.80,0.87,0.85,0.93,1.02,0.93,0.77,0.72,0.74,0.71,0.70,0.70,0.71,0.72,0.77,0.74,0.82,0.76,0.79,0.72,0.73,0.76,0.89,0.89,0.82,0.93,0.91,0.86,0.83,0.79,0.73,0.76,0.91,0.89,0.83,0.89,0.89,0.82,0.82,0.76,0.72,0.76,0.86,0.83,0.79,0.82,0.76,0.73,0.94,1.00,0.91,1.37,1.21,1.14,0.98,0.96,0.88,0.89,0.96,1.14,1.07,1.60,1.40,1.61,1.37,1.57,1.48,1.30,1.78,1.93,1.79,1.99,1.92,1.90,1.79,1.59,1.72,1.79,1.30,1.56,1.35,1.38,1.60,1.11,1.07,0.94,1.68,1.86,1.71,1.97,1.68,1.86,1.44,1.49,1.22,1.44,1.49,1.22,0.99,0.99,1.23,1.19,0.98,0.97,0.97,0.98,1.19,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.94,1.97,1.87,1.91,1.85,1.71,1.60,1.77,1.58,1.74,1.51,1.26,1.48,1.39,1.64,1.99,1.97,1.99,1.70,1.85,1.76,1.91,1.76,1.70,1.88,1.55,1.33,1.57,0.96,1.08,1.05,1.31,1.27,1.47,1.54,1.39,1.20,1.11,0.93,0.99,0.90,0.88,0.95,0.88,0.97,1.32,0.92,1.01,0.97,1.10,1.22,0.84,0.80,0.88,0.79,0.79,0.85,0.86,0.92,1.02,0.94,0.82,0.76,0.77,0.72,0.73,0.70,0.72,0.71,0.74,0.74,0.88,0.81,0.85,0.75,0.77,0.82,0.94,0.93,0.86,0.92,0.92,0.86,0.85,0.79,0.74,0.79,0.88,0.85,0.81,0.82,0.83,0.77,0.78,0.73,0.71,0.75,0.79,0.77,0.74,0.77,0.73,0.70,0.86,0.92,0.84,1.14,0.99,0.98,0.91,0.90,0.84,0.83,0.88,0.97,0.94,1.41,1.18,1.39,1.11,1.33,1.24,1.03,1.61,1.80,1.59,1.91,1.84,1.76,1.64,1.38,1.51,1.71,1.26,1.50,1.23,1.19,1.46,0.99,1.00,0.91,1.70,1.85,1.65,1.93,1.54,1.76,1.52,1.48,1.26,1.28,1.39,1.09,0.99,0.97,1.18,1.31,1.01,1.05,0.90,0.93,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.86,1.95,1.82,1.98,1.89,1.71,1.80,1.91,1.77,1.86,1.67,1.34,1.53,1.51,1.72,1.92,1.91,1.99,1.69,1.82,1.80,1.94,1.87,1.86,1.97,1.59,1.44,1.69,1.05,1.24,1.27,1.49,1.50,1.69,1.72,1.63,1.46,1.37,1.00,1.23,0.98,0.95,1.09,0.96,1.16,1.55,0.99,1.25,1.10,1.24,1.41,0.90,0.85,0.94,0.79,0.81,0.85,0.89,0.94,1.09,0.98,0.89,0.82,0.83,0.74,0.77,0.72,0.76,0.73,0.75,0.78,0.94,0.86,0.91,0.79,0.83,0.89,0.99,0.95,0.90,0.90,0.92,0.84,0.86,0.79,0.75,0.81,0.85,0.80,0.78,0.76,0.77,0.73,0.74,0.71,0.71,0.73,0.74,0.74,0.71,0.76,0.72,0.70,0.79,0.85,0.78,0.98,0.92,0.93,0.85,0.87,0.82,0.79,0.81,0.89,0.86,1.16,0.97,1.12,0.95,1.06,1.00,0.93,1.38,1.60,1.35,1.77,1.71,1.57,1.48,1.20,1.28,1.62,1.27,1.46,1.17,1.05,1.34,0.96,0.99,0.90,1.63,1.74,1.50,1.80,1.33,1.58,1.48,1.37,1.21,1.04,1.21,0.97,0.97,0.93,1.05,1.34,1.02,1.14,0.84,0.88,0.92,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.74,1.89,1.76,1.98,1.89,1.71,1.93,1.99,1.91,1.94,1.82,1.46,1.60,1.65,1.80,1.79,1.77,1.92,1.57,1.69,1.74,1.87,1.88,1.94,1.98,1.53,1.45,1.70,1.18,1.32,1.42,1.58,1.65,1.83,1.81,1.81,1.67,1.61,1.19,1.44,1.17,1.11,1.36,1.15,1.41,1.75,1.22,1.50,1.34,1.42,1.61,0.98,0.92,1.03,0.83,0.86,0.89,0.95,0.98,1.23,1.14,0.97,0.89,0.90,0.78,0.82,0.76,0.82,0.77,0.79,0.84,0.98,0.90,0.98,0.83,0.89,0.97,1.03,0.95,0.92,0.86,0.90,0.82,0.86,0.79,0.77,0.84,0.81,0.76,0.76,0.72,0.73,0.70,0.72,0.71,0.73,0.73,0.72,0.74,0.71,0.78,0.74,0.72,0.75,0.80,0.76,0.94,0.88,0.91,0.83,0.87,0.84,0.79,0.76,0.82,0.80,0.97,0.89,0.96,0.88,0.95,0.94,0.87,1.11,1.37,1.10,1.59,1.57,1.37,1.33,1.05,1.08,1.54,1.34,1.46,1.16,0.99,1.26,0.96,1.05,0.92,1.45,1.55,1.27,1.60,1.07,1.34,1.35,1.18,1.07,0.93,0.99,0.90,0.93,0.87,0.96,1.27,0.99,1.15,0.77,0.82,0.85,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.60,1.78,1.68,1.93,1.86,1.71,1.97,1.99,1.99,1.97,1.93,1.60,1.68,1.78,1.86,1.61,1.57,1.79,1.37,1.48,1.59,1.72,1.79,1.92,1.90,1.38,1.35,1.60,1.23,1.30,1.47,1.56,1.71,1.88,1.79,1.92,1.79,1.79,1.30,1.56,1.35,1.37,1.59,1.38,1.60,1.90,1.48,1.72,1.57,1.61,1.79,1.21,1.00,1.30,0.89,0.94,0.96,1.07,1.14,1.40,1.37,1.14,0.96,0.98,0.82,0.88,0.82,0.89,0.83,0.86,0.91,1.02,0.93,1.07,0.87,0.94,1.11,1.02,0.93,0.93,0.82,0.87,0.80,0.85,0.79,0.80,0.85,0.77,0.72,0.74,0.71,0.70,0.70,0.71,0.72,0.77,0.74,0.72,0.76,0.73,0.82,0.79,0.76,0.73,0.79,0.76,0.93,0.86,0.91,0.83,0.89,0.89,0.82,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.44,1.19,1.22,0.99,0.98,1.49,1.44,1.49,1.22,0.99,1.23,0.98,1.19,0.97,1.21,1.30,1.00,1.37,0.94,1.07,1.14,0.98,0.96,0.86,0.91,0.83,0.88,0.82,0.89,1.11,0.94,1.07,0.73,0.76,0.79,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.46,1.65,1.60,1.82,1.80,1.71,1.93,1.91,1.99,1.94,1.98,1.74,1.76,1.89,1.89,1.42,1.34,1.61,1.11,1.22,1.36,1.50,1.61,1.81,1.75,1.15,1.17,1.41,1.18,1.19,1.42,1.44,1.65,1.83,1.67,1.94,1.81,1.88,1.32,1.58,1.45,1.57,1.74,1.53,1.70,1.98,1.69,1.87,1.77,1.79,1.92,1.45,1.27,1.55,0.97,1.07,1.11,1.34,1.37,1.59,1.60,1.35,1.07,1.18,0.86,0.93,0.87,0.96,0.90,0.93,0.99,1.03,0.95,1.15,0.90,0.99,1.27,0.98,0.90,0.92,0.78,0.83,0.77,0.84,0.79,0.82,0.86,0.73,0.71,0.73,0.72,0.70,0.73,0.72,0.76,0.81,0.76,0.76,0.82,0.77,0.89,0.85,0.82,0.75,0.80,0.80,0.94,0.88,0.94,0.87,0.95,0.96,0.88,0.72,0.74,0.76,0.83,0.78,0.84,0.79,0.87,0.91,0.83,0.89,0.98,0.92,1.23,1.34,1.05,1.16,0.99,0.96,1.46,1.57,1.54,1.33,1.05,1.26,1.08,1.37,1.10,0.98,1.03,0.92,1.14,0.86,0.95,0.97,0.90,0.89,0.79,0.84,0.77,0.82,0.76,0.82,0.97,0.89,0.98,0.71,0.72,0.74,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.34,1.51,1.53,1.67,1.72,1.71,1.80,1.77,1.91,1.86,1.98,1.86,1.82,1.95,1.89,1.24,1.10,1.41,0.95,0.99,1.09,1.25,1.37,1.63,1.55,0.96,0.98,1.16,1.05,1.00,1.27,1.23,1.50,1.69,1.46,1.86,1.72,1.87,1.24,1.49,1.44,1.69,1.80,1.59,1.69,1.97,1.82,1.94,1.91,1.92,1.99,1.63,1.50,1.74,1.16,1.33,1.38,1.58,1.60,1.77,1.80,1.48,1.21,1.37,0.90,0.97,0.93,1.05,0.97,1.04,1.21,0.99,0.95,1.14,0.92,1.02,1.34,0.94,0.86,0.90,0.74,0.79,0.75,0.81,0.79,0.84,0.86,0.71,0.71,0.73,0.76,0.73,0.77,0.74,0.80,0.85,0.78,0.81,0.89,0.84,0.97,0.92,0.88,0.79,0.85,0.86,0.98,0.92,1.00,0.93,1.06,1.12,0.95,0.74,0.74,0.78,0.79,0.76,0.82,0.79,0.87,0.93,0.85,0.85,0.94,0.90,1.09,1.27,0.99,1.17,1.05,0.96,1.46,1.71,1.62,1.48,1.20,1.34,1.28,1.57,1.35,0.90,0.94,0.85,0.98,0.81,0.89,0.89,0.83,0.82,0.75,0.78,0.73,0.77,0.72,0.76,0.89,0.83,0.91,0.71,0.70,0.72,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00},
{1.26,1.39,1.48,1.51,1.64,1.71,1.60,1.58,1.77,1.74,1.91,1.94,1.87,1.97,1.85,1.10,0.97,1.22,0.88,0.92,0.95,1.01,1.11,1.39,1.32,0.88,0.90,0.97,0.96,0.93,1.05,0.99,1.27,1.47,1.20,1.70,1.54,1.76,1.08,1.31,1.33,1.70,1.76,1.55,1.57,1.88,1.85,1.91,1.97,1.99,1.99,1.70,1.65,1.85,1.41,1.54,1.61,1.76,1.80,1.91,1.93,1.52,1.26,1.48,0.92,0.99,0.97,1.18,1.09,1.28,1.39,0.94,0.93,1.05,0.92,1.01,1.31,0.88,0.81,0.86,0.72,0.75,0.74,0.79,0.79,0.86,0.85,0.71,0.73,0.75,0.82,0.77,0.83,0.78,0.85,0.88,0.81,0.88,0.97,0.90,1.18,1.00,0.93,0.86,0.92,0.94,1.14,0.99,1.24,1.03,1.33,1.39,1.11,0.79,0.77,0.84,0.79,0.77,0.84,0.83,0.90,0.98,0.91,0.85,0.92,0.91,1.02,1.26,1.00,1.23,1.19,0.99,1.50,1.84,1.71,1.64,1.38,1.46,1.51,1.76,1.59,0.84,0.88,0.80,0.94,0.79,0.86,0.82,0.77,0.76,0.74,0.74,0.71,0.73,0.70,0.72,0.82,0.77,0.85,0.74,0.70,0.73,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}
}

415
ref_gl/gl_draw.c Normal file
View File

@ -0,0 +1,415 @@
/*
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 "gl_local.h"
image_t *draw_chars;
extern qboolean scrap_dirty;
void Scrap_Upload (void);
/*
===============
Draw_InitLocal
===============
*/
void Draw_InitLocal (void)
{
// load console characters (don't bilerp characters)
draw_chars = GL_FindImage ("pics/conchars.pcx", it_pic);
GL_Bind( draw_chars->texnum );
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
/*
================
Draw_Char
Draws one 8*8 graphics character with 0 being transparent.
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)
{
int row, col;
float frow, fcol, size;
num &= 255;
if ( (num&127) == 32 )
return; // space
if (y <= -8)
return; // totally off screen
row = num>>4;
col = num&15;
frow = row*0.0625;
fcol = col*0.0625;
size = 0.0625;
GL_Bind (draw_chars->texnum);
qglBegin (GL_QUADS);
qglTexCoord2f (fcol, frow);
qglVertex2f (x, y);
qglTexCoord2f (fcol + size, frow);
qglVertex2f (x+8, y);
qglTexCoord2f (fcol + size, frow + size);
qglVertex2f (x+8, y+8);
qglTexCoord2f (fcol, frow + size);
qglVertex2f (x, y+8);
qglEnd ();
}
/*
=============
Draw_FindPic
=============
*/
image_t *Draw_FindPic (char *name)
{
image_t *gl;
char fullname[MAX_QPATH];
if (name[0] != '/' && name[0] != '\\')
{
Com_sprintf (fullname, sizeof(fullname), "pics/%s.pcx", name);
gl = GL_FindImage (fullname, it_pic);
}
else
gl = GL_FindImage (name+1, it_pic);
return gl;
}
/*
=============
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_StretchPic
=============
*/
void Draw_StretchPic (int x, int y, int w, int h, char *pic)
{
image_t *gl;
gl = Draw_FindPic (pic);
if (!gl)
{
ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", pic);
return;
}
if (scrap_dirty)
Scrap_Upload ();
if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !gl->has_alpha)
qglDisable (GL_ALPHA_TEST);
GL_Bind (gl->texnum);
qglBegin (GL_QUADS);
qglTexCoord2f (gl->sl, gl->tl);
qglVertex2f (x, y);
qglTexCoord2f (gl->sh, gl->tl);
qglVertex2f (x+w, y);
qglTexCoord2f (gl->sh, gl->th);
qglVertex2f (x+w, y+h);
qglTexCoord2f (gl->sl, gl->th);
qglVertex2f (x, y+h);
qglEnd ();
if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !gl->has_alpha)
qglEnable (GL_ALPHA_TEST);
}
/*
=============
Draw_Pic
=============
*/
void Draw_Pic (int x, int y, char *pic)
{
image_t *gl;
gl = Draw_FindPic (pic);
if (!gl)
{
ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", pic);
return;
}
if (scrap_dirty)
Scrap_Upload ();
if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !gl->has_alpha)
qglDisable (GL_ALPHA_TEST);
GL_Bind (gl->texnum);
qglBegin (GL_QUADS);
qglTexCoord2f (gl->sl, gl->tl);
qglVertex2f (x, y);
qglTexCoord2f (gl->sh, gl->tl);
qglVertex2f (x+gl->width, y);
qglTexCoord2f (gl->sh, gl->th);
qglVertex2f (x+gl->width, y+gl->height);
qglTexCoord2f (gl->sl, gl->th);
qglVertex2f (x, y+gl->height);
qglEnd ();
if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !gl->has_alpha)
qglEnable (GL_ALPHA_TEST);
}
/*
=============
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 *pic)
{
image_t *image;
image = Draw_FindPic (pic);
if (!image)
{
ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", pic);
return;
}
if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !image->has_alpha)
qglDisable (GL_ALPHA_TEST);
GL_Bind (image->texnum);
qglBegin (GL_QUADS);
qglTexCoord2f (x/64.0, y/64.0);
qglVertex2f (x, y);
qglTexCoord2f ( (x+w)/64.0, y/64.0);
qglVertex2f (x+w, y);
qglTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
qglVertex2f (x+w, y+h);
qglTexCoord2f ( x/64.0, (y+h)/64.0 );
qglVertex2f (x, y+h);
qglEnd ();
if ( ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) ) && !image->has_alpha)
qglEnable (GL_ALPHA_TEST);
}
/*
=============
Draw_Fill
Fills a box of pixels with a single color
=============
*/
void Draw_Fill (int x, int y, int w, int h, int c)
{
union
{
unsigned c;
byte v[4];
} color;
if ( (unsigned)c > 255)
ri.Sys_Error (ERR_FATAL, "Draw_Fill: bad color");
qglDisable (GL_TEXTURE_2D);
color.c = d_8to24table[c];
qglColor3f (color.v[0]/255.0,
color.v[1]/255.0,
color.v[2]/255.0);
qglBegin (GL_QUADS);
qglVertex2f (x,y);
qglVertex2f (x+w, y);
qglVertex2f (x+w, y+h);
qglVertex2f (x, y+h);
qglEnd ();
qglColor3f (1,1,1);
qglEnable (GL_TEXTURE_2D);
}
//=============================================================================
/*
================
Draw_FadeScreen
================
*/
void Draw_FadeScreen (void)
{
qglEnable (GL_BLEND);
qglDisable (GL_TEXTURE_2D);
qglColor4f (0, 0, 0, 0.8);
qglBegin (GL_QUADS);
qglVertex2f (0,0);
qglVertex2f (vid.width, 0);
qglVertex2f (vid.width, vid.height);
qglVertex2f (0, vid.height);
qglEnd ();
qglColor4f (1,1,1,1);
qglEnable (GL_TEXTURE_2D);
qglDisable (GL_BLEND);
}
//====================================================================
/*
=============
Draw_StretchRaw
=============
*/
extern unsigned r_rawpalette[256];
void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
{
unsigned image32[256*256];
unsigned char image8[256*256];
int i, j, trows;
byte *source;
int frac, fracstep;
float hscale;
int row;
float t;
GL_Bind (0);
if (rows<=256)
{
hscale = 1;
trows = rows;
}
else
{
hscale = rows/256.0;
trows = 256;
}
t = rows*hscale / 256;
if ( !qglColorTableEXT )
{
unsigned *dest;
for (i=0 ; i<trows ; i++)
{
row = (int)(i*hscale);
if (row > rows)
break;
source = data + cols*row;
dest = &image32[i*256];
fracstep = cols*0x10000/256;
frac = fracstep >> 1;
for (j=0 ; j<256 ; j++)
{
dest[j] = r_rawpalette[source[frac>>16]];
frac += fracstep;
}
}
qglTexImage2D (GL_TEXTURE_2D, 0, gl_tex_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, image32);
}
else
{
unsigned char *dest;
for (i=0 ; i<trows ; i++)
{
row = (int)(i*hscale);
if (row > rows)
break;
source = data + cols*row;
dest = &image8[i*256];
fracstep = cols*0x10000/256;
frac = fracstep >> 1;
for (j=0 ; j<256 ; j++)
{
dest[j] = source[frac>>16];
frac += fracstep;
}
}
qglTexImage2D( GL_TEXTURE_2D,
0,
GL_COLOR_INDEX8_EXT,
256, 256,
0,
GL_COLOR_INDEX,
GL_UNSIGNED_BYTE,
image8 );
}
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )
qglDisable (GL_ALPHA_TEST);
qglBegin (GL_QUADS);
qglTexCoord2f (0, 0);
qglVertex2f (x, y);
qglTexCoord2f (1, 0);
qglVertex2f (x+w, y);
qglTexCoord2f (1, t);
qglVertex2f (x+w, y+h);
qglTexCoord2f (0, t);
qglVertex2f (x, y+h);
qglEnd ();
if ( ( gl_config.renderer == GL_RENDERER_MCD ) || ( gl_config.renderer & GL_RENDERER_RENDITION ) )
qglEnable (GL_ALPHA_TEST);
}

1571
ref_gl/gl_image.c Normal file

File diff suppressed because it is too large Load Diff

729
ref_gl/gl_light.c Normal file
View File

@ -0,0 +1,729 @@
/*
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 "gl_local.h"
int r_dlightframecount;
#define DLIGHT_CUTOFF 64
/*
=============================================================================
DYNAMIC LIGHTS BLEND RENDERING
=============================================================================
*/
void R_RenderDlight (dlight_t *light)
{
int i, j;
float a;
vec3_t v;
float rad;
rad = light->intensity * 0.35;
VectorSubtract (light->origin, r_origin, v);
#if 0
// FIXME?
if (VectorLength (v) < rad)
{ // view is inside the dlight
V_AddBlend (light->color[0], light->color[1], light->color[2], light->intensity * 0.0003, v_blend);
return;
}
#endif
qglBegin (GL_TRIANGLE_FAN);
qglColor3f (light->color[0]*0.2, light->color[1]*0.2, light->color[2]*0.2);
for (i=0 ; i<3 ; i++)
v[i] = light->origin[i] - vpn[i]*rad;
qglVertex3fv (v);
qglColor3f (0,0,0);
for (i=16 ; i>=0 ; i--)
{
a = i/16.0 * M_PI*2;
for (j=0 ; j<3 ; j++)
v[j] = light->origin[j] + vright[j]*cos(a)*rad
+ vup[j]*sin(a)*rad;
qglVertex3fv (v);
}
qglEnd ();
}
/*
=============
R_RenderDlights
=============
*/
void R_RenderDlights (void)
{
int i;
dlight_t *l;
if (!gl_flashblend->value)
return;
r_dlightframecount = r_framecount + 1; // because the count hasn't
// advanced yet for this frame
qglDepthMask (0);
qglDisable (GL_TEXTURE_2D);
qglShadeModel (GL_SMOOTH);
qglEnable (GL_BLEND);
qglBlendFunc (GL_ONE, GL_ONE);
l = r_newrefdef.dlights;
for (i=0 ; i<r_newrefdef.num_dlights ; i++, l++)
R_RenderDlight (l);
qglColor3f (1,1,1);
qglDisable (GL_BLEND);
qglEnable (GL_TEXTURE_2D);
qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
qglDepthMask (1);
}
/*
=============================================================================
DYNAMIC LIGHTS
=============================================================================
*/
/*
=============
R_MarkLights
=============
*/
void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
{
cplane_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;
if (dist > light->intensity-DLIGHT_CUTOFF)
{
R_MarkLights (light, bit, node->children[0]);
return;
}
if (dist < -light->intensity+DLIGHT_CUTOFF)
{
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 (void)
{
int i;
dlight_t *l;
if (gl_flashblend->value)
return;
r_dlightframecount = r_framecount + 1; // because the count hasn't
// advanced yet for this frame
l = r_newrefdef.dlights;
for (i=0 ; i<r_newrefdef.num_dlights ; i++, l++)
R_MarkLights ( l, 1<<i, r_worldmodel->nodes );
}
/*
=============================================================================
LIGHT SAMPLING
=============================================================================
*/
vec3_t pointcolor;
cplane_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;
cplane_t *plane;
vec3_t mid;
msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
int maps;
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;
// 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)
{
vec3_t scale;
lightmap += 3*(dt * ((surf->extents[0]>>4)+1) + ds);
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
for (i=0 ; i<3 ; i++)
scale[i] = gl_modulate->value*r_newrefdef.lightstyles[surf->styles[maps]].rgb[i];
pointcolor[0] += lightmap[0] * scale[0] * (1.0/255);
pointcolor[1] += lightmap[1] * scale[1] * (1.0/255);
pointcolor[2] += lightmap[2] * scale[2] * (1.0/255);
lightmap += 3*((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;
dl = r_newrefdef.dlights;
for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++, dl++)
{
VectorSubtract (currententity->origin,
dl->origin,
dist);
add = dl->intensity - VectorLength(dist);
add *= (1.0/256);
if (add > 0)
{
VectorMA (color, add, dl->color, color);
}
}
VectorScale (color, gl_modulate->value, color);
}
//===================================================================
static float s_blocklights[34*34*3];
/*
===============
R_AddDynamicLights
===============
*/
void R_AddDynamicLights (msurface_t *surf)
{
int lnum;
int sd, td;
float fdist, frad, fminlight;
vec3_t impact, local;
int s, t;
int i;
int smax, tmax;
mtexinfo_t *tex;
dlight_t *dl;
float *pfBL;
float fsacc, ftacc;
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];
frad = dl->intensity;
fdist = DotProduct (dl->origin, surf->plane->normal) -
surf->plane->dist;
frad -= fabs(fdist);
// rad is now the highest intensity on the plane
fminlight = DLIGHT_CUTOFF; // FIXME: make configurable?
if (frad < fminlight)
continue;
fminlight = frad - fminlight;
for (i=0 ; i<3 ; i++)
{
impact[i] = dl->origin[i] -
surf->plane->normal[i]*fdist;
}
local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3] - surf->texturemins[0];
local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3] - surf->texturemins[1];
pfBL = s_blocklights;
for (t = 0, ftacc = 0 ; t<tmax ; t++, ftacc += 16)
{
td = local[1] - ftacc;
if ( td < 0 )
td = -td;
for ( s=0, fsacc = 0 ; s<smax ; s++, fsacc += 16, pfBL += 3)
{
sd = Q_ftol( local[0] - fsacc );
if ( sd < 0 )
sd = -sd;
if (sd > td)
fdist = sd + (td>>1);
else
fdist = td + (sd>>1);
if ( fdist < fminlight )
{
pfBL[0] += ( frad - fdist ) * dl->color[0];
pfBL[1] += ( frad - fdist ) * dl->color[1];
pfBL[2] += ( frad - fdist ) * dl->color[2];
}
}
}
}
}
/*
** R_SetCacheState
*/
void R_SetCacheState( msurface_t *surf )
{
int maps;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
surf->cached_light[maps] = r_newrefdef.lightstyles[surf->styles[maps]].white;
}
}
/*
===============
R_BuildLightMap
Combine and scale multiple lightmaps into the floating format in blocklights
===============
*/
void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
{
int smax, tmax;
int r, g, b, a, max;
int i, j, size;
byte *lightmap;
float scale[4];
int nummaps;
float *bl;
lightstyle_t *style;
int monolightmap;
if ( surf->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP) )
ri.Sys_Error (ERR_DROP, "R_BuildLightMap called for non-lit surface");
smax = (surf->extents[0]>>4)+1;
tmax = (surf->extents[1]>>4)+1;
size = smax*tmax;
if (size > (sizeof(s_blocklights)>>4) )
ri.Sys_Error (ERR_DROP, "Bad s_blocklights size");
// set to full bright if no light data
if (!surf->samples)
{
int maps;
for (i=0 ; i<size*3 ; i++)
s_blocklights[i] = 255;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
style = &r_newrefdef.lightstyles[surf->styles[maps]];
}
goto store;
}
// count the # of maps
for ( nummaps = 0 ; nummaps < MAXLIGHTMAPS && surf->styles[nummaps] != 255 ;
nummaps++)
;
lightmap = surf->samples;
// add all the lightmaps
if ( nummaps == 1 )
{
int maps;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
bl = s_blocklights;
for (i=0 ; i<3 ; i++)
scale[i] = gl_modulate->value*r_newrefdef.lightstyles[surf->styles[maps]].rgb[i];
if ( scale[0] == 1.0F &&
scale[1] == 1.0F &&
scale[2] == 1.0F )
{
for (i=0 ; i<size ; i++, bl+=3)
{
bl[0] = lightmap[i*3+0];
bl[1] = lightmap[i*3+1];
bl[2] = lightmap[i*3+2];
}
}
else
{
for (i=0 ; i<size ; i++, bl+=3)
{
bl[0] = lightmap[i*3+0] * scale[0];
bl[1] = lightmap[i*3+1] * scale[1];
bl[2] = lightmap[i*3+2] * scale[2];
}
}
lightmap += size*3; // skip to next lightmap
}
}
else
{
int maps;
memset( s_blocklights, 0, sizeof( s_blocklights[0] ) * size * 3 );
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
bl = s_blocklights;
for (i=0 ; i<3 ; i++)
scale[i] = gl_modulate->value*r_newrefdef.lightstyles[surf->styles[maps]].rgb[i];
if ( scale[0] == 1.0F &&
scale[1] == 1.0F &&
scale[2] == 1.0F )
{
for (i=0 ; i<size ; i++, bl+=3 )
{
bl[0] += lightmap[i*3+0];
bl[1] += lightmap[i*3+1];
bl[2] += lightmap[i*3+2];
}
}
else
{
for (i=0 ; i<size ; i++, bl+=3)
{
bl[0] += lightmap[i*3+0] * scale[0];
bl[1] += lightmap[i*3+1] * scale[1];
bl[2] += lightmap[i*3+2] * scale[2];
}
}
lightmap += size*3; // skip to next lightmap
}
}
// add all the dynamic lights
if (surf->dlightframe == r_framecount)
R_AddDynamicLights (surf);
// put into texture format
store:
stride -= (smax<<2);
bl = s_blocklights;
monolightmap = gl_monolightmap->string[0];
if ( monolightmap == '0' )
{
for (i=0 ; i<tmax ; i++, dest += stride)
{
for (j=0 ; j<smax ; j++)
{
r = Q_ftol( bl[0] );
g = Q_ftol( bl[1] );
b = Q_ftol( bl[2] );
// catch negative lights
if (r < 0)
r = 0;
if (g < 0)
g = 0;
if (b < 0)
b = 0;
/*
** determine the brightest of the three color components
*/
if (r > g)
max = r;
else
max = g;
if (b > max)
max = b;
/*
** alpha is ONLY used for the mono lightmap case. For this reason
** we set it to the brightest of the color components so that
** things don't get too dim.
*/
a = max;
/*
** rescale all the color components if the intensity of the greatest
** channel exceeds 1.0
*/
if (max > 255)
{
float t = 255.0F / max;
r = r*t;
g = g*t;
b = b*t;
a = a*t;
}
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest[3] = a;
bl += 3;
dest += 4;
}
}
}
else
{
for (i=0 ; i<tmax ; i++, dest += stride)
{
for (j=0 ; j<smax ; j++)
{
r = Q_ftol( bl[0] );
g = Q_ftol( bl[1] );
b = Q_ftol( bl[2] );
// catch negative lights
if (r < 0)
r = 0;
if (g < 0)
g = 0;
if (b < 0)
b = 0;
/*
** determine the brightest of the three color components
*/
if (r > g)
max = r;
else
max = g;
if (b > max)
max = b;
/*
** alpha is ONLY used for the mono lightmap case. For this reason
** we set it to the brightest of the color components so that
** things don't get too dim.
*/
a = max;
/*
** rescale all the color components if the intensity of the greatest
** channel exceeds 1.0
*/
if (max > 255)
{
float t = 255.0F / max;
r = r*t;
g = g*t;
b = b*t;
a = a*t;
}
/*
** So if we are doing alpha lightmaps we need to set the R, G, and B
** components to 0 and we need to set alpha to 1-alpha.
*/
switch ( monolightmap )
{
case 'L':
case 'I':
r = a;
g = b = 0;
break;
case 'C':
// try faking colored lighting
a = 255 - ((r+g+b)/3);
r *= a/255.0;
g *= a/255.0;
b *= a/255.0;
break;
case 'A':
default:
r = g = b = 0;
a = 255 - a;
break;
}
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest[3] = a;
bl += 3;
dest += 4;
}
}
}
}

460
ref_gl/gl_local.h Normal file
View File

@ -0,0 +1,460 @@
/*
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.
*/
// disable data conversion warnings
#if 0
#pragma warning(disable : 4244) // MIPS
#pragma warning(disable : 4136) // X86
#pragma warning(disable : 4051) // ALPHA
#endif
#ifdef _WIN32
# include <windows.h>
#endif
#include <stdio.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <math.h>
#ifndef GL_COLOR_INDEX8_EXT
#define GL_COLOR_INDEX8_EXT GL_COLOR_INDEX
#endif
#include "../client/ref.h"
#include "qgl.h"
#define REF_VERSION "GL 0.01"
// up / down
#define PITCH 0
// left / right
#define YAW 1
// fall over
#define ROLL 2
typedef struct
{
unsigned width, height; // coordinates from main game
} viddef_t;
extern viddef_t vid;
/*
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; // source image
int upload_width, upload_height; // after power of two and picmip
int registration_sequence; // 0 = free
struct msurface_s *texturechain; // for sort-by-texture world drawing
int texnum; // gl texture binding
float sl, tl, sh, th; // 0,0 - 1,1 unless part of the scrap
qboolean scrap;
qboolean has_alpha;
qboolean paletted;
} image_t;
#define TEXNUM_LIGHTMAPS 1024
#define TEXNUM_SCRAPS 1152
#define TEXNUM_IMAGES 1153
#define MAX_GLTEXTURES 1024
//===================================================================
typedef enum
{
rserr_ok,
rserr_invalid_fullscreen,
rserr_invalid_mode,
rserr_unknown
} rserr_t;
#include "gl_model.h"
void GL_BeginRendering (int *x, int *y, int *width, int *height);
void GL_EndRendering (void);
void GL_SetDefaultState( void );
void GL_UpdateSwapInterval( void );
extern float gldepthmin, gldepthmax;
typedef struct
{
float x, y, z;
float s, t;
float r, g, b;
} glvert_t;
#define MAX_LBM_HEIGHT 480
#define BACKFACE_EPSILON 0.01
//====================================================
extern image_t gltextures[MAX_GLTEXTURES];
extern int numgltextures;
extern image_t *r_notexture;
extern image_t *r_particletexture;
extern entity_t *currententity;
extern model_t *currentmodel;
extern int r_visframecount;
extern int r_framecount;
extern cplane_t frustum[4];
extern int c_brush_polys, c_alias_polys;
extern int gl_filter_min, gl_filter_max;
//
// view origin
//
extern vec3_t vup;
extern vec3_t vpn;
extern vec3_t vright;
extern vec3_t r_origin;
//
// screen size info
//
extern refdef_t r_newrefdef;
extern int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
extern cvar_t *r_norefresh;
extern cvar_t *r_lefthand;
extern cvar_t *r_drawentities;
extern cvar_t *r_drawworld;
extern cvar_t *r_speeds;
extern cvar_t *r_fullbright;
extern cvar_t *r_novis;
extern cvar_t *r_nocull;
extern cvar_t *r_lerpmodels;
extern cvar_t *r_lightlevel; // FIXME: This is a HACK to get the client's light level
extern cvar_t *gl_vertex_arrays;
extern cvar_t *gl_ext_swapinterval;
extern cvar_t *gl_ext_palettedtexture;
extern cvar_t *gl_ext_multitexture;
extern cvar_t *gl_ext_pointparameters;
extern cvar_t *gl_ext_compiled_vertex_array;
extern cvar_t *gl_particle_min_size;
extern cvar_t *gl_particle_max_size;
extern cvar_t *gl_particle_size;
extern cvar_t *gl_particle_att_a;
extern cvar_t *gl_particle_att_b;
extern cvar_t *gl_particle_att_c;
extern cvar_t *gl_nosubimage;
extern cvar_t *gl_bitdepth;
extern cvar_t *gl_mode;
extern cvar_t *gl_log;
extern cvar_t *gl_lightmap;
extern cvar_t *gl_shadows;
extern cvar_t *gl_dynamic;
extern cvar_t *gl_monolightmap;
extern cvar_t *gl_nobind;
extern cvar_t *gl_round_down;
extern cvar_t *gl_picmip;
extern cvar_t *gl_skymip;
extern cvar_t *gl_showtris;
extern cvar_t *gl_finish;
extern cvar_t *gl_ztrick;
extern cvar_t *gl_clear;
extern cvar_t *gl_cull;
extern cvar_t *gl_poly;
extern cvar_t *gl_texsort;
extern cvar_t *gl_polyblend;
extern cvar_t *gl_flashblend;
extern cvar_t *gl_lightmaptype;
extern cvar_t *gl_modulate;
extern cvar_t *gl_playermip;
extern cvar_t *gl_drawbuffer;
extern cvar_t *gl_3dlabs_broken;
extern cvar_t *gl_driver;
extern cvar_t *gl_swapinterval;
extern cvar_t *gl_texturemode;
extern cvar_t *gl_texturealphamode;
extern cvar_t *gl_texturesolidmode;
extern cvar_t *gl_saturatelighting;
extern cvar_t *gl_lockpvs;
extern cvar_t *vid_fullscreen;
extern cvar_t *vid_gamma;
extern cvar_t *intensity;
extern int gl_lightmap_format;
extern int gl_solid_format;
extern int gl_alpha_format;
extern int gl_tex_solid_format;
extern int gl_tex_alpha_format;
extern int c_visible_lightmaps;
extern int c_visible_textures;
extern float r_world_matrix[16];
void R_TranslatePlayerSkin (int playernum);
void GL_Bind (int texnum);
void GL_MBind( GLenum target, int texnum );
void GL_TexEnv( GLenum value );
void GL_EnableMultitexture( qboolean enable );
void GL_SelectTexture( GLenum );
void R_LightPoint (vec3_t p, vec3_t color);
void R_PushDlights (void);
//====================================================================
extern model_t *r_worldmodel;
extern unsigned d_8to24table[256];
extern int registration_sequence;
void V_AddBlend (float r, float g, float b, float a, float *v_blend);
int R_Init( void *hinstance, void *hWnd );
void R_Shutdown( void );
void R_RenderView (refdef_t *fd);
void GL_ScreenShot_f (void);
void R_DrawAliasModel (entity_t *e);
void R_DrawBrushModel (entity_t *e);
void R_DrawSpriteModel (entity_t *e);
void R_DrawBeam( entity_t *e );
void R_DrawWorld (void);
void R_RenderDlights (void);
void R_DrawAlphaSurfaces (void);
void R_RenderBrushPoly (msurface_t *fa);
void R_InitParticleTexture (void);
void Draw_InitLocal (void);
void GL_SubdivideSurface (msurface_t *fa);
qboolean R_CullBox (vec3_t mins, vec3_t maxs);
void R_RotateForEntity (entity_t *e);
void R_MarkLeaves (void);
glpoly_t *WaterWarpPolyVerts (glpoly_t *p);
void EmitWaterPolys (msurface_t *fa);
void R_AddSkySurface (msurface_t *fa);
void R_ClearSkyBox (void);
void R_DrawSkyBox (void);
void R_MarkLights (dlight_t *light, int bit, mnode_t *node);
#if 0
short LittleShort (short l);
short BigShort (short l);
int LittleLong (int l);
float LittleFloat (float f);
char *va(char *format, ...);
// does a varargs printf into a temp buffer
#endif
void COM_StripExtension (char *in, char *out);
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_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_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data);
void R_BeginFrame( float camera_separation );
void R_SwapBuffers( int );
void R_SetPalette ( const unsigned char *palette);
int Draw_GetPalette (void);
void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight);
struct image_s *R_RegisterSkin (char *name);
void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height);
image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type, int bits);
image_t *GL_FindImage (char *name, imagetype_t type);
void GL_TextureMode( char *string );
void GL_ImageList_f (void);
void GL_SetTexturePalette( unsigned palette[256] );
void GL_InitImages (void);
void GL_ShutdownImages (void);
void GL_FreeUnusedImages (void);
void GL_TextureAlphaMode( char *string );
void GL_TextureSolidMode( char *string );
/*
** GL extension emulation functions
*/
void GL_DrawParticles( int n, const particle_t particles[], const unsigned colortable[768] );
/*
** GL config stuff
*/
#define GL_RENDERER_VOODOO 0x00000001
#define GL_RENDERER_VOODOO2 0x00000002
#define GL_RENDERER_VOODOO_RUSH 0x00000004
#define GL_RENDERER_BANSHEE 0x00000008
#define GL_RENDERER_3DFX 0x0000000F
#define GL_RENDERER_PCX1 0x00000010
#define GL_RENDERER_PCX2 0x00000020
#define GL_RENDERER_PMX 0x00000040
#define GL_RENDERER_POWERVR 0x00000070
#define GL_RENDERER_PERMEDIA2 0x00000100
#define GL_RENDERER_GLINT_MX 0x00000200
#define GL_RENDERER_GLINT_TX 0x00000400
#define GL_RENDERER_3DLABS_MISC 0x00000800
#define GL_RENDERER_3DLABS 0x00000F00
#define GL_RENDERER_REALIZM 0x00001000
#define GL_RENDERER_REALIZM2 0x00002000
#define GL_RENDERER_INTERGRAPH 0x00003000
#define GL_RENDERER_3DPRO 0x00004000
#define GL_RENDERER_REAL3D 0x00008000
#define GL_RENDERER_RIVA128 0x00010000
#define GL_RENDERER_DYPIC 0x00020000
#define GL_RENDERER_V1000 0x00040000
#define GL_RENDERER_V2100 0x00080000
#define GL_RENDERER_V2200 0x00100000
#define GL_RENDERER_RENDITION 0x001C0000
#define GL_RENDERER_O2 0x00100000
#define GL_RENDERER_IMPACT 0x00200000
#define GL_RENDERER_RE 0x00400000
#define GL_RENDERER_IR 0x00800000
#define GL_RENDERER_SGI 0x00F00000
#define GL_RENDERER_MCD 0x01000000
#define GL_RENDERER_OTHER 0x80000000
typedef struct
{
int renderer;
const char *renderer_string;
const char *vendor_string;
const char *version_string;
const char *extensions_string;
qboolean allow_cds;
} glconfig_t;
typedef struct
{
float inverse_intensity;
qboolean fullscreen;
int prev_mode;
unsigned char *d_16to8table;
int lightmap_textures;
int currenttextures[2];
int currenttmu;
float camera_separation;
qboolean stereo_enabled;
unsigned char originalRedGammaTable[256];
unsigned char originalGreenGammaTable[256];
unsigned char originalBlueGammaTable[256];
} glstate_t;
extern glconfig_t gl_config;
extern glstate_t gl_state;
/*
====================================================================
IMPORTED FUNCTIONS
====================================================================
*/
extern refimport_t ri;
/*
====================================================================
IMPLEMENTATION SPECIFIC FUNCTIONS
====================================================================
*/
void GLimp_BeginFrame( float camera_separation );
void GLimp_EndFrame( void );
int GLimp_Init( void *hinstance, void *hWnd );
void GLimp_Shutdown( void );
int GLimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen );
void GLimp_AppActivate( qboolean active );
void GLimp_EnableLogging( qboolean enable );
void GLimp_LogNewFrame( void );

839
ref_gl/gl_mesh.c Normal file
View File

@ -0,0 +1,839 @@
/*
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.
*/
// gl_mesh.c: triangle model functions
#include "gl_local.h"
/*
=============================================================
ALIAS MODELS
=============================================================
*/
#define NUMVERTEXNORMALS 162
float r_avertexnormals[NUMVERTEXNORMALS][3] = {
#include "anorms.h"
};
typedef float vec4_t[4];
static vec4_t s_lerped[MAX_VERTS];
//static vec3_t lerped[MAX_VERTS];
vec3_t shadevector;
float shadelight[3];
// precalculated dot products for quantized angles
#define SHADEDOT_QUANT 16
float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
#include "anormtab.h"
;
float *shadedots = r_avertexnormal_dots[0];
void GL_LerpVerts( int nverts, dtrivertx_t *v, dtrivertx_t *ov, dtrivertx_t *verts, float *lerp, float move[3], float frontv[3], float backv[3] )
{
int i;
//PMM -- added RF_SHELL_DOUBLE, RF_SHELL_HALF_DAM
if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
{
for (i=0 ; i < nverts; i++, v++, ov++, lerp+=4 )
{
float *normal = r_avertexnormals[verts[i].lightnormalindex];
lerp[0] = move[0] + ov->v[0]*backv[0] + v->v[0]*frontv[0] + normal[0] * POWERSUIT_SCALE;
lerp[1] = move[1] + ov->v[1]*backv[1] + v->v[1]*frontv[1] + normal[1] * POWERSUIT_SCALE;
lerp[2] = move[2] + ov->v[2]*backv[2] + v->v[2]*frontv[2] + normal[2] * POWERSUIT_SCALE;
}
}
else
{
for (i=0 ; i < nverts; i++, v++, ov++, lerp+=4)
{
lerp[0] = move[0] + ov->v[0]*backv[0] + v->v[0]*frontv[0];
lerp[1] = move[1] + ov->v[1]*backv[1] + v->v[1]*frontv[1];
lerp[2] = move[2] + ov->v[2]*backv[2] + v->v[2]*frontv[2];
}
}
}
/*
=============
GL_DrawAliasFrameLerp
interpolates between two frames and origins
FIXME: batch lerp all vertexes
=============
*/
void GL_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp)
{
float l;
daliasframe_t *frame, *oldframe;
dtrivertx_t *v, *ov, *verts;
int *order;
int count;
float frontlerp;
float alpha;
vec3_t move, delta, vectors[3];
vec3_t frontv, backv;
int i;
int index_xyz;
float *lerp;
frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
+ currententity->frame * paliashdr->framesize);
verts = v = frame->verts;
oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
+ currententity->oldframe * paliashdr->framesize);
ov = oldframe->verts;
order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
// glTranslatef (frame->translate[0], frame->translate[1], frame->translate[2]);
// glScalef (frame->scale[0], frame->scale[1], frame->scale[2]);
if (currententity->flags & RF_TRANSLUCENT)
alpha = currententity->alpha;
else
alpha = 1.0;
// PMM - added double shell
if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
qglDisable( GL_TEXTURE_2D );
frontlerp = 1.0 - backlerp;
// move should be the delta back to the previous frame * backlerp
VectorSubtract (currententity->oldorigin, currententity->origin, delta);
AngleVectors (currententity->angles, vectors[0], vectors[1], vectors[2]);
move[0] = DotProduct (delta, vectors[0]); // forward
move[1] = -DotProduct (delta, vectors[1]); // left
move[2] = DotProduct (delta, vectors[2]); // up
VectorAdd (move, oldframe->translate, move);
for (i=0 ; i<3 ; i++)
{
move[i] = backlerp*move[i] + frontlerp*frame->translate[i];
}
for (i=0 ; i<3 ; i++)
{
frontv[i] = frontlerp*frame->scale[i];
backv[i] = backlerp*oldframe->scale[i];
}
lerp = s_lerped[0];
GL_LerpVerts( paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv );
if ( gl_vertex_arrays->value )
{
float colorArray[MAX_VERTS*4];
qglEnableClientState( GL_VERTEX_ARRAY );
qglVertexPointer( 3, GL_FLOAT, 16, s_lerped ); // padded for SIMD
// if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
// PMM - added double damage shell
if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
{
qglColor4f( shadelight[0], shadelight[1], shadelight[2], alpha );
}
else
{
qglEnableClientState( GL_COLOR_ARRAY );
qglColorPointer( 3, GL_FLOAT, 0, colorArray );
//
// pre light everything
//
for ( i = 0; i < paliashdr->num_xyz; i++ )
{
float l = shadedots[verts[i].lightnormalindex];
colorArray[i*3+0] = l * shadelight[0];
colorArray[i*3+1] = l * shadelight[1];
colorArray[i*3+2] = l * shadelight[2];
}
}
if ( qglLockArraysEXT != 0 )
qglLockArraysEXT( 0, paliashdr->num_xyz );
while (1)
{
// get the vertex count and primitive type
count = *order++;
if (!count)
break; // done
if (count < 0)
{
count = -count;
qglBegin (GL_TRIANGLE_FAN);
}
else
{
qglBegin (GL_TRIANGLE_STRIP);
}
// PMM - added double damage shell
if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
{
do
{
index_xyz = order[2];
order += 3;
qglVertex3fv( s_lerped[index_xyz] );
} while (--count);
}
else
{
do
{
// texture coordinates come from the draw list
qglTexCoord2f (((float *)order)[0], ((float *)order)[1]);
index_xyz = order[2];
order += 3;
// normals and vertexes come from the frame list
// l = shadedots[verts[index_xyz].lightnormalindex];
// qglColor4f (l* shadelight[0], l*shadelight[1], l*shadelight[2], alpha);
qglArrayElement( index_xyz );
} while (--count);
}
qglEnd ();
}
if ( qglUnlockArraysEXT != 0 )
qglUnlockArraysEXT();
}
else
{
while (1)
{
// get the vertex count and primitive type
count = *order++;
if (!count)
break; // done
if (count < 0)
{
count = -count;
qglBegin (GL_TRIANGLE_FAN);
}
else
{
qglBegin (GL_TRIANGLE_STRIP);
}
if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
{
do
{
index_xyz = order[2];
order += 3;
qglColor4f( shadelight[0], shadelight[1], shadelight[2], alpha);
qglVertex3fv (s_lerped[index_xyz]);
} while (--count);
}
else
{
do
{
// texture coordinates come from the draw list
qglTexCoord2f (((float *)order)[0], ((float *)order)[1]);
index_xyz = order[2];
order += 3;
// normals and vertexes come from the frame list
l = shadedots[verts[index_xyz].lightnormalindex];
qglColor4f (l* shadelight[0], l*shadelight[1], l*shadelight[2], alpha);
qglVertex3fv (s_lerped[index_xyz]);
} while (--count);
}
qglEnd ();
}
}
// if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
// PMM - added double damage shell
if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
qglEnable( GL_TEXTURE_2D );
}
#if 1
/*
=============
GL_DrawAliasShadow
=============
*/
extern vec3_t lightspot;
void GL_DrawAliasShadow (dmdl_t *paliashdr, int posenum)
{
dtrivertx_t *verts;
int *order;
vec3_t point;
float height, lheight;
int count;
daliasframe_t *frame;
lheight = currententity->origin[2] - lightspot[2];
frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
+ currententity->frame * paliashdr->framesize);
verts = frame->verts;
height = 0;
order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
height = -lheight + 1.0;
while (1)
{
// get the vertex count and primitive type
count = *order++;
if (!count)
break; // done
if (count < 0)
{
count = -count;
qglBegin (GL_TRIANGLE_FAN);
}
else
qglBegin (GL_TRIANGLE_STRIP);
do
{
// normals and vertexes come from the frame list
/*
point[0] = verts[order[2]].v[0] * frame->scale[0] + frame->translate[0];
point[1] = verts[order[2]].v[1] * frame->scale[1] + frame->translate[1];
point[2] = verts[order[2]].v[2] * frame->scale[2] + frame->translate[2];
*/
memcpy( point, s_lerped[order[2]], sizeof( point ) );
point[0] -= shadevector[0]*(point[2]+lheight);
point[1] -= shadevector[1]*(point[2]+lheight);
point[2] = height;
// height -= 0.001;
qglVertex3fv (point);
order += 3;
// verts++;
} while (--count);
qglEnd ();
}
}
#endif
/*
** R_CullAliasModel
*/
static qboolean R_CullAliasModel( vec3_t bbox[8], entity_t *e )
{
int i;
vec3_t mins, maxs;
dmdl_t *paliashdr;
vec3_t vectors[3];
vec3_t thismins, oldmins, thismaxs, oldmaxs;
daliasframe_t *pframe, *poldframe;
vec3_t angles;
paliashdr = (dmdl_t *)currentmodel->extradata;
if ( ( e->frame >= paliashdr->num_frames ) || ( e->frame < 0 ) )
{
ri.Con_Printf (PRINT_ALL, "R_CullAliasModel %s: no such frame %d\n",
currentmodel->name, e->frame);
e->frame = 0;
}
if ( ( e->oldframe >= paliashdr->num_frames ) || ( e->oldframe < 0 ) )
{
ri.Con_Printf (PRINT_ALL, "R_CullAliasModel %s: no such oldframe %d\n",
currentmodel->name, e->oldframe);
e->oldframe = 0;
}
pframe = ( daliasframe_t * ) ( ( byte * ) paliashdr +
paliashdr->ofs_frames +
e->frame * paliashdr->framesize);
poldframe = ( daliasframe_t * ) ( ( byte * ) paliashdr +
paliashdr->ofs_frames +
e->oldframe * paliashdr->framesize);
/*
** compute axially aligned mins and maxs
*/
if ( pframe == poldframe )
{
for ( i = 0; i < 3; i++ )
{
mins[i] = pframe->translate[i];
maxs[i] = mins[i] + pframe->scale[i]*255;
}
}
else
{
for ( i = 0; i < 3; i++ )
{
thismins[i] = pframe->translate[i];
thismaxs[i] = thismins[i] + pframe->scale[i]*255;
oldmins[i] = poldframe->translate[i];
oldmaxs[i] = oldmins[i] + poldframe->scale[i]*255;
if ( thismins[i] < oldmins[i] )
mins[i] = thismins[i];
else
mins[i] = oldmins[i];
if ( thismaxs[i] > oldmaxs[i] )
maxs[i] = thismaxs[i];
else
maxs[i] = oldmaxs[i];
}
}
/*
** compute a full bounding box
*/
for ( i = 0; i < 8; i++ )
{
vec3_t tmp;
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];
VectorCopy( tmp, bbox[i] );
}
/*
** rotate the bounding box
*/
VectorCopy( e->angles, angles );
angles[YAW] = -angles[YAW];
AngleVectors( angles, vectors[0], vectors[1], vectors[2] );
for ( i = 0; i < 8; i++ )
{
vec3_t tmp;
VectorCopy( bbox[i], tmp );
bbox[i][0] = DotProduct( vectors[0], tmp );
bbox[i][1] = -DotProduct( vectors[1], tmp );
bbox[i][2] = DotProduct( vectors[2], tmp );
VectorAdd( e->origin, bbox[i], bbox[i] );
}
{
int p, f, aggregatemask = ~0;
for ( p = 0; p < 8; p++ )
{
int mask = 0;
for ( f = 0; f < 4; f++ )
{
float dp = DotProduct( frustum[f].normal, bbox[p] );
if ( ( dp - frustum[f].dist ) < 0 )
{
mask |= ( 1 << f );
}
}
aggregatemask &= mask;
}
if ( aggregatemask )
{
return true;
}
return false;
}
}
/*
=================
R_DrawAliasModel
=================
*/
void R_DrawAliasModel (entity_t *e)
{
int i;
dmdl_t *paliashdr;
float an;
vec3_t bbox[8];
image_t *skin;
if ( !( e->flags & RF_WEAPONMODEL ) )
{
if ( R_CullAliasModel( bbox, e ) )
return;
}
if ( e->flags & RF_WEAPONMODEL )
{
if ( r_lefthand->value == 2 )
return;
}
paliashdr = (dmdl_t *)currentmodel->extradata;
//
// get lighting information
//
// PMM - rewrote, reordered to handle new shells & mixing
//
if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
{
// PMM -special case for godmode
if ( (currententity->flags & RF_SHELL_RED) &&
(currententity->flags & RF_SHELL_BLUE) &&
(currententity->flags & RF_SHELL_GREEN) )
{
for (i=0 ; i<3 ; i++)
shadelight[i] = 1.0;
}
else if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
{
VectorClear (shadelight);
if ( currententity->flags & RF_SHELL_RED )
{
shadelight[0] = 1.0;
if (currententity->flags & (RF_SHELL_BLUE|RF_SHELL_DOUBLE) )
shadelight[2] = 1.0;
}
else if ( currententity->flags & RF_SHELL_BLUE )
{
if ( currententity->flags & RF_SHELL_DOUBLE )
{
shadelight[1] = 1.0;
shadelight[2] = 1.0;
}
else
{
shadelight[2] = 1.0;
}
}
else if ( currententity->flags & RF_SHELL_DOUBLE )
{
shadelight[0] = 0.9;
shadelight[1] = 0.7;
}
}
else if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN ) )
{
VectorClear (shadelight);
// PMM - new colors
if ( currententity->flags & RF_SHELL_HALF_DAM )
{
shadelight[0] = 0.56;
shadelight[1] = 0.59;
shadelight[2] = 0.45;
}
if ( currententity->flags & RF_SHELL_GREEN )
{
shadelight[1] = 1.0;
}
}
}
//PMM - ok, now flatten these down to range from 0 to 1.0.
// max_shell_val = max(shadelight[0], max(shadelight[1], shadelight[2]));
// if (max_shell_val > 0)
// {
// for (i=0; i<3; i++)
// {
// shadelight[i] = shadelight[i] / max_shell_val;
// }
// }
// pmm
else if ( currententity->flags & RF_FULLBRIGHT )
{
for (i=0 ; i<3 ; i++)
shadelight[i] = 1.0;
}
else
{
R_LightPoint (currententity->origin, shadelight);
// player lighting hack for communication back to server
// big hack!
if ( currententity->flags & RF_WEAPONMODEL )
{
// pick the greatest component, which should be the same
// as the mono value returned by software
if (shadelight[0] > shadelight[1])
{
if (shadelight[0] > shadelight[2])
r_lightlevel->value = 150*shadelight[0];
else
r_lightlevel->value = 150*shadelight[2];
}
else
{
if (shadelight[1] > shadelight[2])
r_lightlevel->value = 150*shadelight[1];
else
r_lightlevel->value = 150*shadelight[2];
}
}
if ( gl_monolightmap->string[0] != '0' )
{
float s = shadelight[0];
if ( s < shadelight[1] )
s = shadelight[1];
if ( s < shadelight[2] )
s = shadelight[2];
shadelight[0] = s;
shadelight[1] = s;
shadelight[2] = s;
}
}
if ( currententity->flags & RF_MINLIGHT )
{
for (i=0 ; i<3 ; i++)
if (shadelight[i] > 0.1)
break;
if (i == 3)
{
shadelight[0] = 0.1;
shadelight[1] = 0.1;
shadelight[2] = 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 = shadelight[i] * 0.8;
shadelight[i] += scale;
if (shadelight[i] < min)
shadelight[i] = min;
}
}
// =================
// PGM ir goggles color override
if ( r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
{
shadelight[0] = 1.0;
shadelight[1] = 0.0;
shadelight[2] = 0.0;
}
// PGM
// =================
shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
an = currententity->angles[1]/180*M_PI;
shadevector[0] = cos(-an);
shadevector[1] = sin(-an);
shadevector[2] = 1;
VectorNormalize (shadevector);
//
// locate the proper data
//
c_alias_polys += paliashdr->num_tris;
//
// draw all the triangles
//
if (currententity->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls
qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
{
extern void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar );
qglMatrixMode( GL_PROJECTION );
qglPushMatrix();
qglLoadIdentity();
qglScalef( -1, 1, 1 );
MYgluPerspective( r_newrefdef.fov_y, ( float ) r_newrefdef.width / r_newrefdef.height, 4, 4096);
qglMatrixMode( GL_MODELVIEW );
qglCullFace( GL_BACK );
}
qglPushMatrix ();
e->angles[PITCH] = -e->angles[PITCH]; // sigh.
R_RotateForEntity (e);
e->angles[PITCH] = -e->angles[PITCH]; // sigh.
// select skin
if (currententity->skin)
skin = currententity->skin; // custom player skin
else
{
if (currententity->skinnum >= MAX_MD2SKINS)
skin = currentmodel->skins[0];
else
{
skin = currentmodel->skins[currententity->skinnum];
if (!skin)
skin = currentmodel->skins[0];
}
}
if (!skin)
skin = r_notexture; // fallback...
GL_Bind(skin->texnum);
// draw it
qglShadeModel (GL_SMOOTH);
GL_TexEnv( GL_MODULATE );
if ( currententity->flags & RF_TRANSLUCENT )
{
qglEnable (GL_BLEND);
}
if ( (currententity->frame >= paliashdr->num_frames)
|| (currententity->frame < 0) )
{
ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n",
currentmodel->name, currententity->frame);
currententity->frame = 0;
currententity->oldframe = 0;
}
if ( (currententity->oldframe >= paliashdr->num_frames)
|| (currententity->oldframe < 0))
{
ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n",
currentmodel->name, currententity->oldframe);
currententity->frame = 0;
currententity->oldframe = 0;
}
if ( !r_lerpmodels->value )
currententity->backlerp = 0;
GL_DrawAliasFrameLerp (paliashdr, currententity->backlerp);
GL_TexEnv( GL_REPLACE );
qglShadeModel (GL_FLAT);
qglPopMatrix ();
#if 0
qglDisable( GL_CULL_FACE );
qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
qglDisable( GL_TEXTURE_2D );
qglBegin( GL_TRIANGLE_STRIP );
for ( i = 0; i < 8; i++ )
{
qglVertex3fv( bbox[i] );
}
qglEnd();
qglEnable( GL_TEXTURE_2D );
qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
qglEnable( GL_CULL_FACE );
#endif
if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
{
qglMatrixMode( GL_PROJECTION );
qglPopMatrix();
qglMatrixMode( GL_MODELVIEW );
qglCullFace( GL_FRONT );
}
if ( currententity->flags & RF_TRANSLUCENT )
{
qglDisable (GL_BLEND);
}
if (currententity->flags & RF_DEPTHHACK)
qglDepthRange (gldepthmin, gldepthmax);
#if 1
if (gl_shadows->value && !(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL)))
{
qglPushMatrix ();
R_RotateForEntity (e);
qglDisable (GL_TEXTURE_2D);
qglEnable (GL_BLEND);
qglColor4f (0,0,0,0.5);
GL_DrawAliasShadow (paliashdr, currententity->frame );
qglEnable (GL_TEXTURE_2D);
qglDisable (GL_BLEND);
qglPopMatrix ();
}
#endif
qglColor4f (1,1,1,1);
}

1223
ref_gl/gl_model.c Normal file

File diff suppressed because it is too large Load Diff

261
ref_gl/gl_model.h Normal file
View File

@ -0,0 +1,261 @@
/*
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*_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;
typedef struct
{
vec3_t mins, maxs;
vec3_t origin; // for sounds or lights
float radius;
int headnode;
int visleafs; // not including the solid leaf 0
int firstface, numfaces;
} mmodel_t;
#define SIDE_FRONT 0
#define SIDE_BACK 1
#define SIDE_ON 2
#define SURF_PLANEBACK 2
#define SURF_DRAWSKY 4
#define SURF_DRAWTURB 0x10
#define SURF_DRAWBACKGROUND 0x40
#define SURF_UNDERWATER 0x80
// !!! 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];
int flags;
int numframes;
struct mtexinfo_s *next; // animation chain
image_t *image;
} mtexinfo_t;
#define VERTEXSIZE 7
typedef struct glpoly_s
{
struct glpoly_s *next;
struct glpoly_s *chain;
int numverts;
int flags; // for SURF_UNDERWATER (not needed anymore?)
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
} glpoly_t;
typedef struct msurface_s
{
int visframe; // should be drawn when node is crossed
cplane_t *plane;
int flags;
int firstedge; // look up in model->surfedges[], negative numbers
int numedges; // are backwards edges
short texturemins[2];
short extents[2];
int light_s, light_t; // gl lightmap coordinates
int dlight_s, dlight_t; // gl lightmap coordinates for dynamic lightmaps
glpoly_t *polys; // multiple if warped
struct msurface_s *texturechain;
struct msurface_s *lightmapchain;
mtexinfo_t *texinfo;
// lighting info
int dlightframe;
int dlightbits;
int lightmaptexturenum;
byte styles[MAXLIGHTMAPS];
float cached_light[MAXLIGHTMAPS]; // values currently used in lightmap
byte *samples; // [numstyles*surfsize]
} msurface_t;
typedef struct mnode_s
{
// common with leaf
int contents; // -1, to differentiate from leafs
int visframe; // node needs to be traversed if current
float minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
// node specific
cplane_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 a negative contents number
int visframe; // node needs to be traversed if current
float minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
// leaf specific
int cluster;
int area;
msurface_t **firstmarksurface;
int nummarksurfaces;
} 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;
float radius;
//
// solid volume for clipping
//
qboolean clipbox;
vec3_t clipmins, clipmaxs;
//
// brush model
//
int firstmodelsurface, nummodelsurfaces;
int lightmap; // only for submodels
int numsubmodels;
mmodel_t *submodels;
int numplanes;
cplane_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 skins
image_t *skins[MAX_MD2SKINS];
int extradatasize;
void *extradata;
} model_t;
//============================================================================
void Mod_Init (void);
void Mod_ClearAll (void);
model_t *Mod_ForName (char *name, qboolean crash);
mleaf_t *Mod_PointInLeaf (float *p, model_t *model);
byte *Mod_ClusterPVS (int cluster, model_t *model);
void Mod_Modellist_f (void);
void *Hunk_Begin (int maxsize);
void *Hunk_Alloc (int size);
int Hunk_End (void);
void Hunk_Free (void *base);
void Mod_FreeAll (void);
void Mod_Free (model_t *mod);

1692
ref_gl/gl_rmain.c Normal file

File diff suppressed because it is too large Load Diff

246
ref_gl/gl_rmisc.c Normal file
View File

@ -0,0 +1,246 @@
/*
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 "gl_local.h"
/*
==================
R_InitParticleTexture
==================
*/
byte dottexture[8][8] =
{
{0,0,0,0,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,1,1,1,1,0,0,0},
{0,1,1,1,1,0,0,0},
{0,0,1,1,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},
};
void R_InitParticleTexture (void)
{
int x,y;
byte data[8][8][4];
//
// particle texture
//
for (x=0 ; x<8 ; x++)
{
for (y=0 ; y<8 ; y++)
{
data[y][x][0] = 255;
data[y][x][1] = 255;
data[y][x][2] = 255;
data[y][x][3] = dottexture[x][y]*255;
}
}
r_particletexture = GL_LoadPic ("***particle***", (byte *)data, 8, 8, it_sprite, 32);
//
// also use this for bad textures, but without alpha
//
for (x=0 ; x<8 ; x++)
{
for (y=0 ; y<8 ; y++)
{
data[y][x][0] = dottexture[x&3][y&3]*255;
data[y][x][1] = 0; // dottexture[x&3][y&3]*255;
data[y][x][2] = 0; //dottexture[x&3][y&3]*255;
data[y][x][3] = 255;
}
}
r_notexture = GL_LoadPic ("***r_notexture***", (byte *)data, 8, 8, it_wall, 32);
}
/*
==============================================================================
SCREEN SHOTS
==============================================================================
*/
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;
/*
==================
GL_ScreenShot_f
==================
*/
void GL_ScreenShot_f (void)
{
byte *buffer;
char picname[80];
char checkname[MAX_OSPATH];
int i, c, temp;
FILE *f;
// 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(picname,"quake00.tga");
for (i=0 ; i<=99 ; i++)
{
picname[5] = i/10 + '0';
picname[6] = i%10 + '0';
Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/%s", ri.FS_Gamedir(), picname);
f = fopen (checkname, "rb");
if (!f)
break; // file doesn't exist
fclose (f);
}
if (i==100)
{
ri.Con_Printf (PRINT_ALL, "SCR_ScreenShot_f: Couldn't create a file\n");
return;
}
buffer = malloc(vid.width*vid.height*3 + 18);
memset (buffer, 0, 18);
buffer[2] = 2; // uncompressed type
buffer[12] = vid.width&255;
buffer[13] = vid.width>>8;
buffer[14] = vid.height&255;
buffer[15] = vid.height>>8;
buffer[16] = 24; // pixel size
qglReadPixels (0, 0, vid.width, vid.height, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 );
// swap rgb to bgr
c = 18+vid.width*vid.height*3;
for (i=18 ; i<c ; i+=3)
{
temp = buffer[i];
buffer[i] = buffer[i+2];
buffer[i+2] = temp;
}
f = fopen (checkname, "wb");
fwrite (buffer, 1, c, f);
fclose (f);
free (buffer);
ri.Con_Printf (PRINT_ALL, "Wrote %s\n", picname);
}
/*
** GL_Strings_f
*/
void GL_Strings_f( void )
{
ri.Con_Printf (PRINT_ALL, "GL_VENDOR: %s\n", gl_config.vendor_string );
ri.Con_Printf (PRINT_ALL, "GL_RENDERER: %s\n", gl_config.renderer_string );
ri.Con_Printf (PRINT_ALL, "GL_VERSION: %s\n", gl_config.version_string );
ri.Con_Printf (PRINT_ALL, "GL_EXTENSIONS: %s\n", gl_config.extensions_string );
}
/*
** GL_SetDefaultState
*/
void GL_SetDefaultState( void )
{
qglClearColor (1,0, 0.5 , 0.5);
qglCullFace(GL_FRONT);
qglEnable(GL_TEXTURE_2D);
qglEnable(GL_ALPHA_TEST);
qglAlphaFunc(GL_GREATER, 0.666);
qglDisable (GL_DEPTH_TEST);
qglDisable (GL_CULL_FACE);
qglDisable (GL_BLEND);
qglColor4f (1,1,1,1);
qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
qglShadeModel (GL_FLAT);
GL_TextureMode( gl_texturemode->string );
GL_TextureAlphaMode( gl_texturealphamode->string );
GL_TextureSolidMode( gl_texturesolidmode->string );
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_TexEnv( GL_REPLACE );
if ( qglPointParameterfEXT )
{
float attenuations[3];
attenuations[0] = gl_particle_att_a->value;
attenuations[1] = gl_particle_att_b->value;
attenuations[2] = gl_particle_att_c->value;
qglEnable( GL_POINT_SMOOTH );
qglPointParameterfEXT( GL_POINT_SIZE_MIN_EXT, gl_particle_min_size->value );
qglPointParameterfEXT( GL_POINT_SIZE_MAX_EXT, gl_particle_max_size->value );
qglPointParameterfvEXT( GL_DISTANCE_ATTENUATION_EXT, attenuations );
}
if ( qglColorTableEXT && gl_ext_palettedtexture->value )
{
qglEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
GL_SetTexturePalette( d_8to24table );
}
GL_UpdateSwapInterval();
}
void GL_UpdateSwapInterval( void )
{
if ( gl_swapinterval->modified )
{
gl_swapinterval->modified = false;
if ( !gl_state.stereo_enabled )
{
#ifdef _WIN32
if ( qwglSwapIntervalEXT )
qwglSwapIntervalEXT( gl_swapinterval->value );
#endif
}
}
}

1660
ref_gl/gl_rsurf.c Normal file

File diff suppressed because it is too large Load Diff

662
ref_gl/gl_warp.c Normal file
View File

@ -0,0 +1,662 @@
/*
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.
*/
// gl_warp.c -- sky and water polygons
#include "gl_local.h"
extern model_t *loadmodel;
char skyname[MAX_QPATH];
float skyrotate;
vec3_t skyaxis;
image_t *sky_images[6];
msurface_t *warpface;
#define SUBDIVIDE_SIZE 64
//#define SUBDIVIDE_SIZE 1024
void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
{
int i, j;
float *v;
mins[0] = mins[1] = mins[2] = 9999;
maxs[0] = maxs[1] = maxs[2] = -9999;
v = verts;
for (i=0 ; i<numverts ; i++)
for (j=0 ; j<3 ; j++, v++)
{
if (*v < mins[j])
mins[j] = *v;
if (*v > maxs[j])
maxs[j] = *v;
}
}
void SubdividePolygon (int numverts, float *verts)
{
int i, j, k;
vec3_t mins, maxs;
float m;
float *v;
vec3_t front[64], back[64];
int f, b;
float dist[64];
float frac;
glpoly_t *poly;
float s, t;
vec3_t total;
float total_s, total_t;
if (numverts > 60)
ri.Sys_Error (ERR_DROP, "numverts = %i", numverts);
BoundPoly (numverts, verts, mins, maxs);
for (i=0 ; i<3 ; i++)
{
m = (mins[i] + maxs[i]) * 0.5;
m = SUBDIVIDE_SIZE * floor (m/SUBDIVIDE_SIZE + 0.5);
if (maxs[i] - m < 8)
continue;
if (m - mins[i] < 8)
continue;
// cut it
v = verts + i;
for (j=0 ; j<numverts ; j++, v+= 3)
dist[j] = *v - m;
// wrap cases
dist[j] = dist[0];
v-=i;
VectorCopy (verts, v);
f = b = 0;
v = verts;
for (j=0 ; j<numverts ; j++, v+= 3)
{
if (dist[j] >= 0)
{
VectorCopy (v, front[f]);
f++;
}
if (dist[j] <= 0)
{
VectorCopy (v, back[b]);
b++;
}
if (dist[j] == 0 || dist[j+1] == 0)
continue;
if ( (dist[j] > 0) != (dist[j+1] > 0) )
{
// clip point
frac = dist[j] / (dist[j] - dist[j+1]);
for (k=0 ; k<3 ; k++)
front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]);
f++;
b++;
}
}
SubdividePolygon (f, front[0]);
SubdividePolygon (b, back[0]);
return;
}
// add a point in the center to help keep warp valid
poly = Hunk_Alloc (sizeof(glpoly_t) + ((numverts-4)+2) * VERTEXSIZE*sizeof(float));
poly->next = warpface->polys;
warpface->polys = poly;
poly->numverts = numverts+2;
VectorClear (total);
total_s = 0;
total_t = 0;
for (i=0 ; i<numverts ; i++, verts+= 3)
{
VectorCopy (verts, poly->verts[i+1]);
s = DotProduct (verts, warpface->texinfo->vecs[0]);
t = DotProduct (verts, warpface->texinfo->vecs[1]);
total_s += s;
total_t += t;
VectorAdd (total, verts, total);
poly->verts[i+1][3] = s;
poly->verts[i+1][4] = t;
}
VectorScale (total, (1.0/numverts), poly->verts[0]);
poly->verts[0][3] = total_s/numverts;
poly->verts[0][4] = total_t/numverts;
// copy first vertex to last
memcpy (poly->verts[i+1], poly->verts[1], sizeof(poly->verts[0]));
}
/*
================
GL_SubdivideSurface
Breaks a polygon up along axial 64 unit
boundaries so that turbulent and sky warps
can be done reasonably.
================
*/
void GL_SubdivideSurface (msurface_t *fa)
{
vec3_t verts[64];
int numverts;
int i;
int lindex;
float *vec;
warpface = fa;
//
// convert edges back to a normal polygon
//
numverts = 0;
for (i=0 ; i<fa->numedges ; i++)
{
lindex = loadmodel->surfedges[fa->firstedge + i];
if (lindex > 0)
vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position;
else
vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position;
VectorCopy (vec, verts[numverts]);
numverts++;
}
SubdividePolygon (numverts, verts[0]);
}
//=========================================================
// speed up sin calculations - Ed
float r_turbsin[] =
{
#include "warpsin.h"
};
#define TURBSCALE (256.0 / (2 * M_PI))
/*
=============
EmitWaterPolys
Does a water warp on the pre-fragmented glpoly_t chain
=============
*/
void EmitWaterPolys (msurface_t *fa)
{
glpoly_t *p, *bp;
float *v;
int i;
float s, t, os, ot;
float scroll;
float rdt = r_newrefdef.time;
if (fa->texinfo->flags & SURF_FLOWING)
scroll = -64 * ( (r_newrefdef.time*0.5) - (int)(r_newrefdef.time*0.5) );
else
scroll = 0;
for (bp=fa->polys ; bp ; bp=bp->next)
{
p = bp;
qglBegin (GL_TRIANGLE_FAN);
for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
{
os = v[3];
ot = v[4];
#if !id386
s = os + r_turbsin[(int)((ot*0.125+r_newrefdef.time) * TURBSCALE) & 255];
#else
s = os + r_turbsin[Q_ftol( ((ot*0.125+rdt) * TURBSCALE) ) & 255];
#endif
s += scroll;
s *= (1.0/64);
#if !id386
t = ot + r_turbsin[(int)((os*0.125+rdt) * TURBSCALE) & 255];
#else
t = ot + r_turbsin[Q_ftol( ((os*0.125+rdt) * TURBSCALE) ) & 255];
#endif
t *= (1.0/64);
qglTexCoord2f (s, t);
qglVertex3fv (v);
}
qglEnd ();
}
}
//===================================================================
vec3_t skyclip[6] = {
{1,1,0},
{1,-1,0},
{0,-1,1},
{0,1,1},
{1,0,1},
{-1,0,1}
};
int c_sky;
// 1 = s, 2 = t, 3 = 2048
int st_to_vec[6][3] =
{
{3,-1,2},
{-3,1,2},
{1,3,2},
{-1,-3,2},
{-2,-1,3}, // 0 degrees yaw, look straight up
{2,-1,-3} // look straight down
// {-1,2,3},
// {1,2,-3}
};
// s = [0]/[2], t = [1]/[2]
int vec_to_st[6][3] =
{
{-2,3,1},
{2,3,-1},
{1,3,2},
{-1,3,-2},
{-2,-1,3},
{-2,1,-3}
// {-1,2,3},
// {1,2,-3}
};
float skymins[2][6], skymaxs[2][6];
float sky_min, sky_max;
void DrawSkyPolygon (int nump, vec3_t vecs)
{
int i,j;
vec3_t v, av;
float s, t, dv;
int axis;
float *vp;
c_sky++;
#if 0
glBegin (GL_POLYGON);
for (i=0 ; i<nump ; i++, vecs+=3)
{
VectorAdd(vecs, r_origin, v);
qglVertex3fv (v);
}
glEnd();
return;
#endif
// decide which face it maps to
VectorCopy (vec3_origin, v);
for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
{
VectorAdd (vp, v, v);
}
av[0] = fabs(v[0]);
av[1] = fabs(v[1]);
av[2] = fabs(v[2]);
if (av[0] > av[1] && av[0] > av[2])
{
if (v[0] < 0)
axis = 1;
else
axis = 0;
}
else if (av[1] > av[2] && av[1] > av[0])
{
if (v[1] < 0)
axis = 3;
else
axis = 2;
}
else
{
if (v[2] < 0)
axis = 5;
else
axis = 4;
}
// project new texture coords
for (i=0 ; i<nump ; i++, vecs+=3)
{
j = vec_to_st[axis][2];
if (j > 0)
dv = vecs[j - 1];
else
dv = -vecs[-j - 1];
if (dv < 0.001)
continue; // don't divide by zero
j = vec_to_st[axis][0];
if (j < 0)
s = -vecs[-j -1] / dv;
else
s = vecs[j-1] / dv;
j = vec_to_st[axis][1];
if (j < 0)
t = -vecs[-j -1] / dv;
else
t = vecs[j-1] / dv;
if (s < skymins[0][axis])
skymins[0][axis] = s;
if (t < skymins[1][axis])
skymins[1][axis] = t;
if (s > skymaxs[0][axis])
skymaxs[0][axis] = s;
if (t > skymaxs[1][axis])
skymaxs[1][axis] = t;
}
}
#define ON_EPSILON 0.1 // point on plane side epsilon
#define MAX_CLIP_VERTS 64
void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
{
float *norm;
float *v;
qboolean front, back;
float d, e;
float dists[MAX_CLIP_VERTS];
int sides[MAX_CLIP_VERTS];
vec3_t newv[2][MAX_CLIP_VERTS];
int newc[2];
int i, j;
if (nump > MAX_CLIP_VERTS-2)
ri.Sys_Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS");
if (stage == 6)
{ // fully clipped, so draw it
DrawSkyPolygon (nump, vecs);
return;
}
front = back = false;
norm = skyclip[stage];
for (i=0, v = vecs ; i<nump ; i++, v+=3)
{
d = DotProduct (v, norm);
if (d > ON_EPSILON)
{
front = true;
sides[i] = SIDE_FRONT;
}
else if (d < -ON_EPSILON)
{
back = true;
sides[i] = SIDE_BACK;
}
else
sides[i] = SIDE_ON;
dists[i] = d;
}
if (!front || !back)
{ // not clipped
ClipSkyPolygon (nump, vecs, stage+1);
return;
}
// clip it
sides[i] = sides[0];
dists[i] = dists[0];
VectorCopy (vecs, (vecs+(i*3)) );
newc[0] = newc[1] = 0;
for (i=0, v = vecs ; i<nump ; i++, v+=3)
{
switch (sides[i])
{
case SIDE_FRONT:
VectorCopy (v, newv[0][newc[0]]);
newc[0]++;
break;
case SIDE_BACK:
VectorCopy (v, newv[1][newc[1]]);
newc[1]++;
break;
case SIDE_ON:
VectorCopy (v, newv[0][newc[0]]);
newc[0]++;
VectorCopy (v, newv[1][newc[1]]);
newc[1]++;
break;
}
if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
d = dists[i] / (dists[i] - dists[i+1]);
for (j=0 ; j<3 ; j++)
{
e = v[j] + d*(v[j+3] - v[j]);
newv[0][newc[0]][j] = e;
newv[1][newc[1]][j] = e;
}
newc[0]++;
newc[1]++;
}
// continue
ClipSkyPolygon (newc[0], newv[0][0], stage+1);
ClipSkyPolygon (newc[1], newv[1][0], stage+1);
}
/*
=================
R_AddSkySurface
=================
*/
void R_AddSkySurface (msurface_t *fa)
{
int i;
vec3_t verts[MAX_CLIP_VERTS];
glpoly_t *p;
// calculate vertex values for sky box
for (p=fa->polys ; p ; p=p->next)
{
for (i=0 ; i<p->numverts ; i++)
{
VectorSubtract (p->verts[i], r_origin, verts[i]);
}
ClipSkyPolygon (p->numverts, verts[0], 0);
}
}
/*
==============
R_ClearSkyBox
==============
*/
void R_ClearSkyBox (void)
{
int i;
for (i=0 ; i<6 ; i++)
{
skymins[0][i] = skymins[1][i] = 9999;
skymaxs[0][i] = skymaxs[1][i] = -9999;
}
}
void MakeSkyVec (float s, float t, int axis)
{
vec3_t v, b;
int j, k;
b[0] = s*2300;
b[1] = t*2300;
b[2] = 2300;
for (j=0 ; j<3 ; j++)
{
k = st_to_vec[axis][j];
if (k < 0)
v[j] = -b[-k - 1];
else
v[j] = b[k - 1];
}
// avoid bilerp seam
s = (s+1)*0.5;
t = (t+1)*0.5;
if (s < sky_min)
s = sky_min;
else if (s > sky_max)
s = sky_max;
if (t < sky_min)
t = sky_min;
else if (t > sky_max)
t = sky_max;
t = 1.0 - t;
qglTexCoord2f (s, t);
qglVertex3fv (v);
}
/*
==============
R_DrawSkyBox
==============
*/
int skytexorder[6] = {0,2,1,3,4,5};
void R_DrawSkyBox (void)
{
int i;
#if 0
qglEnable (GL_BLEND);
GL_TexEnv( GL_MODULATE );
qglColor4f (1,1,1,0.5);
qglDisable (GL_DEPTH_TEST);
#endif
if (skyrotate)
{ // check for no sky at all
for (i=0 ; i<6 ; i++)
if (skymins[0][i] < skymaxs[0][i]
&& skymins[1][i] < skymaxs[1][i])
break;
if (i == 6)
return; // nothing visible
}
qglPushMatrix ();
qglTranslatef (r_origin[0], r_origin[1], r_origin[2]);
qglRotatef (r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]);
for (i=0 ; i<6 ; i++)
{
if (skyrotate)
{ // hack, forces full sky to draw when rotating
skymins[0][i] = -1;
skymins[1][i] = -1;
skymaxs[0][i] = 1;
skymaxs[1][i] = 1;
}
if (skymins[0][i] >= skymaxs[0][i]
|| skymins[1][i] >= skymaxs[1][i])
continue;
GL_Bind (sky_images[skytexorder[i]]->texnum);
qglBegin (GL_QUADS);
MakeSkyVec (skymins[0][i], skymins[1][i], i);
MakeSkyVec (skymins[0][i], skymaxs[1][i], i);
MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i);
MakeSkyVec (skymaxs[0][i], skymins[1][i], i);
qglEnd ();
}
qglPopMatrix ();
#if 0
glDisable (GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor4f (1,1,1,0.5);
glEnable (GL_DEPTH_TEST);
#endif
}
/*
============
R_SetSky
============
*/
// 3dstudio environment map names
char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
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++)
{
// chop down rotating skies for less memory
if (gl_skymip->value || skyrotate)
gl_picmip->value++;
if ( qglColorTableEXT && gl_ext_palettedtexture->value )
Com_sprintf (pathname, sizeof(pathname), "env/%s%s.pcx", skyname, suf[i]);
else
Com_sprintf (pathname, sizeof(pathname), "env/%s%s.tga", skyname, suf[i]);
sky_images[i] = GL_FindImage (pathname, it_sky);
if (!sky_images[i])
sky_images[i] = r_notexture;
if (gl_skymip->value || skyrotate)
{ // take less memory
gl_picmip->value--;
sky_min = 1.0/256;
sky_max = 255.0/256;
}
else
{
sky_min = 1.0/512;
sky_max = 511.0/512;
}
}
}

442
ref_gl/qgl.h Normal file
View File

@ -0,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.
*/
/*
** QGL.H
*/
#ifndef __QGL_H__
#define __QGL_H__
#ifdef _WIN32
# include <windows.h>
#endif
#include <GL/gl.h>
qboolean QGL_Init( const char *dllname );
void QGL_Shutdown( void );
#ifndef APIENTRY
# define APIENTRY
#endif
extern void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
extern void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
extern GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
extern void ( APIENTRY * qglArrayElement )(GLint i);
extern void ( APIENTRY * qglBegin )(GLenum mode);
extern void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
extern void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
extern void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
extern void ( APIENTRY * qglCallList )(GLuint list);
extern void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
extern void ( APIENTRY * qglClear )(GLbitfield mask);
extern void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
extern void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
extern void ( APIENTRY * qglClearDepth )(GLclampd depth);
extern void ( APIENTRY * qglClearIndex )(GLfloat c);
extern void ( APIENTRY * qglClearStencil )(GLint s);
extern void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
extern void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
extern void ( APIENTRY * qglColor3bv )(const GLbyte *v);
extern void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
extern void ( APIENTRY * qglColor3dv )(const GLdouble *v);
extern void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
extern void ( APIENTRY * qglColor3fv )(const GLfloat *v);
extern void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
extern void ( APIENTRY * qglColor3iv )(const GLint *v);
extern void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
extern void ( APIENTRY * qglColor3sv )(const GLshort *v);
extern void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
extern void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
extern void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
extern void ( APIENTRY * qglColor3uiv )(const GLuint *v);
extern void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
extern void ( APIENTRY * qglColor3usv )(const GLushort *v);
extern void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
extern void ( APIENTRY * qglColor4bv )(const GLbyte *v);
extern void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
extern void ( APIENTRY * qglColor4dv )(const GLdouble *v);
extern void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
extern void ( APIENTRY * qglColor4fv )(const GLfloat *v);
extern void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
extern void ( APIENTRY * qglColor4iv )(const GLint *v);
extern void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
extern void ( APIENTRY * qglColor4sv )(const GLshort *v);
extern void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
extern void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
extern void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
extern void ( APIENTRY * qglColor4uiv )(const GLuint *v);
extern void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
extern void ( APIENTRY * qglColor4usv )(const GLushort *v);
extern void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
extern void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
extern void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
extern void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
extern void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
extern void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
extern void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
extern void ( APIENTRY * qglCullFace )(GLenum mode);
extern void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
extern void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
extern void ( APIENTRY * qglDepthFunc )(GLenum func);
extern void ( APIENTRY * qglDepthMask )(GLboolean flag);
extern void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
extern void ( APIENTRY * qglDisable )(GLenum cap);
extern void ( APIENTRY * qglDisableClientState )(GLenum array);
extern void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
extern void ( APIENTRY * qglDrawBuffer )(GLenum mode);
extern void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
extern void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
extern void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
extern void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
extern void ( APIENTRY * qglEnable )(GLenum cap);
extern void ( APIENTRY * qglEnableClientState )(GLenum array);
extern void ( APIENTRY * qglEnd )(void);
extern void ( APIENTRY * qglEndList )(void);
extern void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
extern void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
extern void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
extern void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
extern void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
extern void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
extern void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
extern void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
extern void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
extern void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
extern void ( APIENTRY * qglEvalPoint1 )(GLint i);
extern void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
extern void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
extern void ( APIENTRY * qglFinish )(void);
extern void ( APIENTRY * qglFlush )(void);
extern void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
extern void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
extern void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
extern void ( APIENTRY * qglFrontFace )(GLenum mode);
extern void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
extern GLuint ( APIENTRY * qglGenLists )(GLsizei range);
extern void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
extern void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
extern void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
extern void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
extern GLenum ( APIENTRY * qglGetError )(void);
extern void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
extern void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
extern void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
extern void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
extern void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
extern void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
extern void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
extern void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
extern void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
extern void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
extern void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
extern const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
extern void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
extern void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
extern void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
extern void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
extern void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
extern void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
extern void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
extern void ( APIENTRY * qglIndexMask )(GLuint mask);
extern void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglIndexd )(GLdouble c);
extern void ( APIENTRY * qglIndexdv )(const GLdouble *c);
extern void ( APIENTRY * qglIndexf )(GLfloat c);
extern void ( APIENTRY * qglIndexfv )(const GLfloat *c);
extern void ( APIENTRY * qglIndexi )(GLint c);
extern void ( APIENTRY * qglIndexiv )(const GLint *c);
extern void ( APIENTRY * qglIndexs )(GLshort c);
extern void ( APIENTRY * qglIndexsv )(const GLshort *c);
extern void ( APIENTRY * qglIndexub )(GLubyte c);
extern void ( APIENTRY * qglIndexubv )(const GLubyte *c);
extern void ( APIENTRY * qglInitNames )(void);
extern void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
extern GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
extern GLboolean ( APIENTRY * qglIsList )(GLuint list);
extern GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
extern void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
extern void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
extern void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
extern void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
extern void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
extern void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
extern void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
extern void ( APIENTRY * qglLineWidth )(GLfloat width);
extern void ( APIENTRY * qglListBase )(GLuint base);
extern void ( APIENTRY * qglLoadIdentity )(void);
extern void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
extern void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
extern void ( APIENTRY * qglLoadName )(GLuint name);
extern void ( APIENTRY * qglLogicOp )(GLenum opcode);
extern void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
extern void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
extern void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
extern void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
extern void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
extern void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
extern void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
extern void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
extern void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
extern void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
extern void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
extern void ( APIENTRY * qglMatrixMode )(GLenum mode);
extern void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
extern void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
extern void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
extern void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
extern void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
extern void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
extern void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
extern void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
extern void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
extern void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
extern void ( APIENTRY * qglNormal3iv )(const GLint *v);
extern void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
extern void ( APIENTRY * qglNormal3sv )(const GLshort *v);
extern void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
extern void ( APIENTRY * qglPassThrough )(GLfloat token);
extern void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
extern void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
extern void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
extern void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
extern void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
extern void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
extern void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
extern void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
extern void ( APIENTRY * qglPointSize )(GLfloat size);
extern void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
extern void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
extern void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
extern void ( APIENTRY * qglPopAttrib )(void);
extern void ( APIENTRY * qglPopClientAttrib )(void);
extern void ( APIENTRY * qglPopMatrix )(void);
extern void ( APIENTRY * qglPopName )(void);
extern void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
extern void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
extern void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
extern void ( APIENTRY * qglPushMatrix )(void);
extern void ( APIENTRY * qglPushName )(GLuint name);
extern void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
extern void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
extern void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
extern void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
extern void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
extern void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
extern void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
extern void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
extern void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
extern void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
extern void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
extern void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
extern void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
extern void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
extern void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
extern void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
extern void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
extern void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
extern void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
extern void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
extern void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
extern void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
extern void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
extern void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
extern void ( APIENTRY * qglReadBuffer )(GLenum mode);
extern void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
extern void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
extern void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
extern void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
extern void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
extern void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
extern void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
extern void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
extern void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
extern GLint ( APIENTRY * qglRenderMode )(GLenum mode);
extern void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
extern void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
extern void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
extern void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
extern void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
extern void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
extern void ( APIENTRY * qglShadeModel )(GLenum mode);
extern void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
extern void ( APIENTRY * qglStencilMask )(GLuint mask);
extern void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
extern void ( APIENTRY * qglTexCoord1d )(GLdouble s);
extern void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
extern void ( APIENTRY * qglTexCoord1f )(GLfloat s);
extern void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
extern void ( APIENTRY * qglTexCoord1i )(GLint s);
extern void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
extern void ( APIENTRY * qglTexCoord1s )(GLshort s);
extern void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
extern void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
extern void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
extern void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
extern void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
extern void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
extern void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
extern void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
extern void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
extern void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
extern void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
extern void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
extern void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
extern void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
extern void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
extern void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
extern void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
extern void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
extern void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
extern void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
extern void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
extern void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
extern void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
extern void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
extern void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
extern void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
extern void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
extern void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
extern void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
extern void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
extern void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
extern void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
extern void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
extern void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
extern void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
extern void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
extern void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
extern void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
extern void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
extern void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
extern void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
extern void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
extern void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
extern void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
extern void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
extern void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
extern void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
extern void ( APIENTRY * qglVertex2iv )(const GLint *v);
extern void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
extern void ( APIENTRY * qglVertex2sv )(const GLshort *v);
extern void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
extern void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
extern void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
extern void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
extern void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
extern void ( APIENTRY * qglVertex3iv )(const GLint *v);
extern void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
extern void ( APIENTRY * qglVertex3sv )(const GLshort *v);
extern void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
extern void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
extern void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
extern void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
extern void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
extern void ( APIENTRY * qglVertex4iv )(const GLint *v);
extern void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
extern void ( APIENTRY * qglVertex4sv )(const GLshort *v);
extern void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
extern void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value );
extern void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value );
extern void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
extern void ( APIENTRY * qglLockArraysEXT) (int , int);
extern void ( APIENTRY * qglUnlockArraysEXT) (void);
extern void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat );
extern void ( APIENTRY * qglSelectTextureSGIS)( GLenum );
#ifdef _WIN32
extern int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
extern int ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
extern int ( WINAPI * qwglGetPixelFormat)(HDC);
extern BOOL ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
extern BOOL ( WINAPI * qwglSwapBuffers)(HDC);
extern BOOL ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT);
extern HGLRC ( WINAPI * qwglCreateContext)(HDC);
extern HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int);
extern BOOL ( WINAPI * qwglDeleteContext)(HGLRC);
extern HGLRC ( WINAPI * qwglGetCurrentContext)(VOID);
extern HDC ( WINAPI * qwglGetCurrentDC)(VOID);
extern PROC ( WINAPI * qwglGetProcAddress)(LPCSTR);
extern BOOL ( WINAPI * qwglMakeCurrent)(HDC, HGLRC);
extern BOOL ( WINAPI * qwglShareLists)(HGLRC, HGLRC);
extern BOOL ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD);
extern BOOL ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT,
FLOAT, int, LPGLYPHMETRICSFLOAT);
extern BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT,
LPLAYERPLANEDESCRIPTOR);
extern int ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int,
CONST COLORREF *);
extern int ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int,
COLORREF *);
extern BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL);
extern BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT);
extern BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval );
extern BOOL ( WINAPI * qwglGetDeviceGammaRampEXT ) ( unsigned char *pRed, unsigned char *pGreen, unsigned char *pBlue );
extern BOOL ( WINAPI * qwglSetDeviceGammaRampEXT ) ( const unsigned char *pRed, const unsigned char *pGreen, const unsigned char *pBlue );
#endif
/*
** extension constants
*/
#define GL_POINT_SIZE_MIN_EXT 0x8126
#define GL_POINT_SIZE_MAX_EXT 0x8127
#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128
#define GL_DISTANCE_ATTENUATION_EXT 0x8129
#ifdef __sgi
#define GL_SHARED_TEXTURE_PALETTE_EXT GL_TEXTURE_COLOR_TABLE_SGI
#else
#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
#endif
#define GL_TEXTURE0_SGIS 0x835E
#define GL_TEXTURE1_SGIS 0x835F
#endif

752
ref_gl/ref_gl.001 Normal file
View File

@ -0,0 +1,752 @@
# Microsoft Developer Studio Project File - Name="ref_gl" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 5.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602
CFG=ref_gl - Win32 Debug Alpha
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "ref_gl.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ref_gl.mak" CFG="ref_gl - Win32 Debug Alpha"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ref_gl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "ref_gl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "ref_gl - Win32 Debug Alpha" (based on\
"Win32 (ALPHA) Dynamic-Link Library")
!MESSAGE "ref_gl - Win32 Release Alpha" (based on\
"Win32 (ALPHA) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
!IF "$(CFG)" == "ref_gl - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ".\ref_gl__"
# PROP BASE Intermediate_Dir ".\ref_gl__"
# PROP BASE Target_Dir "."
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "..\release"
# PROP Intermediate_Dir ".\release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir "."
CPP=cl.exe
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /G5 /MT /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /YX /FD /c
MTL=midl.exe
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
RSC=rc.exe
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /machine:I386
# SUBTRACT LINK32 /incremental:yes /debug
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ".\ref_gl__"
# PROP BASE Intermediate_Dir ".\ref_gl__"
# PROP BASE Target_Dir "."
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "..\debug"
# PROP Intermediate_Dir ".\debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir "."
CPP=cl.exe
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /G5 /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /FR /YX /FD /c
MTL=midl.exe
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
RSC=rc.exe
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386
# SUBTRACT LINK32 /profile
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug Alpha"
# PROP BASE Intermediate_Dir "Debug Alpha"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "..\DebugAxp"
# PROP Intermediate_Dir ".\DebugAxp"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
MTL=midl.exe
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
CPP=cl.exe
# ADD BASE CPP /nologo /MTd /Gt0 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /QA21164 /MTd /Gt0 /W3 /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "C_ONLY" /YX /FD /QAieee1 /c
RSC=rc.exe
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 winmm.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:ALPHA
# ADD LINK32 opengl32.lib kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:ALPHA
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "ref_gl__"
# PROP BASE Intermediate_Dir "ref_gl__"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "..\ReleaseAXP"
# PROP Intermediate_Dir ".\ReleaseAXP"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
MTL=midl.exe
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
CPP=cl.exe
# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /QA21164 /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "C_ONLY" /YX /FD /QAieee1 /c
# SUBTRACT CPP /Z<none> /Fr
RSC=rc.exe
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:ALPHA
# SUBTRACT BASE LINK32 /debug
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /machine:ALPHA
# SUBTRACT LINK32 /debug
!ENDIF
# Begin Target
# Name "ref_gl - Win32 Release"
# Name "ref_gl - Win32 Debug"
# Name "ref_gl - Win32 Debug Alpha"
# Name "ref_gl - Win32 Release Alpha"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
# Begin Source File
SOURCE=.\gl_draw.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_DR=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_DR=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_DR=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
{$(INCLUDE)}"GL\gl.h"\
{$(INCLUDE)}"GL\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_image.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_IM=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_IM=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_IM=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
{$(INCLUDE)}"GL\gl.h"\
{$(INCLUDE)}"GL\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_light.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_LI=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_LI=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_LI=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
{$(INCLUDE)}"GL\gl.h"\
{$(INCLUDE)}"GL\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_mesh.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_ME=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\anorms.h"\
".\anormtab.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_ME=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_ME=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\anorms.h"\
".\anormtab.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
{$(INCLUDE)}"GL\gl.h"\
{$(INCLUDE)}"GL\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_model.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_MO=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_MO=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_MO=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
{$(INCLUDE)}"GL\gl.h"\
{$(INCLUDE)}"GL\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_rmain.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_RM=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_RM=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_RM=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
{$(INCLUDE)}"GL\gl.h"\
{$(INCLUDE)}"GL\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_rmisc.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_RMI=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_RMI=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_RMI=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
{$(INCLUDE)}"GL\gl.h"\
{$(INCLUDE)}"GL\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_rsurf.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_RS=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_RS=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_RS=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
{$(INCLUDE)}"GL\gl.h"\
{$(INCLUDE)}"GL\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_warp.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_WA=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
".\warpsin.h"\
NODEP_CPP_GL_WA=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_WA=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
".\warpsin.h"\
{$(INCLUDE)}"GL\gl.h"\
{$(INCLUDE)}"GL\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\win32\glw_imp.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GLW_I=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
"..\win32\glw_win.h"\
"..\win32\winquake.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GLW_I=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GLW_I=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
"..\win32\glw_win.h"\
"..\win32\winquake.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
{$(INCLUDE)}"GL\gl.h"\
{$(INCLUDE)}"GL\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\game\q_shared.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_Q_SHA=\
"..\game\q_shared.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_Q_SHA=\
"..\game\q_shared.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\win32\q_shwin.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_Q_SHW=\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
"..\win32\winquake.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_Q_SHW=\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
"..\win32\winquake.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\win32\qgl_win.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_QGL_W=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
"..\win32\glw_win.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_QGL_W=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_QGL_W=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
"..\win32\glw_win.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
{$(INCLUDE)}"GL\gl.h"\
{$(INCLUDE)}"GL\glu.h"\
!ENDIF
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
SOURCE=.\anorms.h
# End Source File
# Begin Source File
SOURCE=.\anormtab.h
# End Source File
# Begin Source File
SOURCE=.\gl_local.h
# End Source File
# Begin Source File
SOURCE=.\gl_model.h
# End Source File
# Begin Source File
SOURCE=..\win32\glw_win.h
# End Source File
# Begin Source File
SOURCE=..\game\q_shared.h
# End Source File
# Begin Source File
SOURCE=..\qcommon\qcommon.h
# End Source File
# Begin Source File
SOURCE=..\qcommon\qfiles.h
# End Source File
# Begin Source File
SOURCE=.\qgl.h
# End Source File
# Begin Source File
SOURCE=.\qmenu.h
# End Source File
# Begin Source File
SOURCE=..\client\ref.h
# End Source File
# Begin Source File
SOURCE=.\ref_gl.h
# End Source File
# Begin Source File
SOURCE=.\warpsin.h
# End Source File
# Begin Source File
SOURCE=..\win32\winquake.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
# Begin Source File
SOURCE=.\ref_gl.def
# End Source File
# End Group
# End Target
# End Project

2
ref_gl/ref_gl.def Normal file
View File

@ -0,0 +1,2 @@
EXPORTS
GetRefAPI

773
ref_gl/ref_gl.dsp Normal file
View File

@ -0,0 +1,773 @@
# Microsoft Developer Studio Project File - Name="ref_gl" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602
CFG=ref_gl - Win32 Debug Alpha
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "ref_gl.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ref_gl.mak" CFG="ref_gl - Win32 Debug Alpha"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ref_gl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "ref_gl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "ref_gl - Win32 Debug Alpha" (based on "Win32 (ALPHA) Dynamic-Link Library")
!MESSAGE "ref_gl - Win32 Release Alpha" (based on "Win32 (ALPHA) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
!IF "$(CFG)" == "ref_gl - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ".\ref_gl__"
# PROP BASE Intermediate_Dir ".\ref_gl__"
# PROP BASE Target_Dir "."
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "..\release"
# PROP Intermediate_Dir ".\release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir "."
CPP=cl.exe
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /G5 /MT /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /YX /FD /c
MTL=midl.exe
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
RSC=rc.exe
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /machine:I386
# SUBTRACT LINK32 /incremental:yes /debug
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ".\ref_gl__"
# PROP BASE Intermediate_Dir ".\ref_gl__"
# PROP BASE Target_Dir "."
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "..\debug"
# PROP Intermediate_Dir ".\debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir "."
CPP=cl.exe
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /G5 /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /FR /YX /FD /c
MTL=midl.exe
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
RSC=rc.exe
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386
# SUBTRACT LINK32 /profile
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug Alpha"
# PROP BASE Intermediate_Dir "Debug Alpha"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "..\DebugAxp"
# PROP Intermediate_Dir ".\DebugAxp"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
CPP=cl.exe
# ADD BASE CPP /nologo /MTd /Gt0 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /QA21164 /MTd /Gt0 /W3 /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "C_ONLY" /YX /FD /QAieee1 /c
MTL=midl.exe
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
RSC=rc.exe
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 winmm.lib opengl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:ALPHA
# ADD LINK32 opengl32.lib kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:ALPHA
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "ref_gl__"
# PROP BASE Intermediate_Dir "ref_gl__"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "..\ReleaseAXP"
# PROP Intermediate_Dir ".\ReleaseAXP"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
CPP=cl.exe
# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /QA21164 /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "C_ONLY" /YX /FD /QAieee1 /c
# SUBTRACT CPP /Z<none> /Fr
MTL=midl.exe
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
RSC=rc.exe
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:ALPHA
# SUBTRACT BASE LINK32 /debug
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /machine:ALPHA
# SUBTRACT LINK32 /debug
!ENDIF
# Begin Target
# Name "ref_gl - Win32 Release"
# Name "ref_gl - Win32 Debug"
# Name "ref_gl - Win32 Debug Alpha"
# Name "ref_gl - Win32 Release Alpha"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
# Begin Source File
SOURCE=.\gl_draw.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_DR=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_DR=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_DR=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_DR=\
".\L\gl.h"\
".\L\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_image.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_IM=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_IM=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_IM=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_IM=\
".\L\gl.h"\
".\L\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_light.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_LI=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_LI=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_LI=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_LI=\
".\L\gl.h"\
".\L\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_mesh.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_ME=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\anorms.h"\
".\anormtab.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_ME=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_ME=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\anorms.h"\
".\anormtab.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_ME=\
".\L\gl.h"\
".\L\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_model.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_MO=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_MO=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_MO=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_MO=\
".\L\gl.h"\
".\L\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_rmain.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_RM=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_RM=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_RM=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_RM=\
".\L\gl.h"\
".\L\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_rmisc.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_RMI=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_RMI=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_RMI=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_RMI=\
".\L\gl.h"\
".\L\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_rsurf.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_RS=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_RS=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_RS=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GL_RS=\
".\L\gl.h"\
".\L\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\gl_warp.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GL_WA=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
".\warpsin.h"\
NODEP_CPP_GL_WA=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GL_WA=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
".\warpsin.h"\
NODEP_CPP_GL_WA=\
".\L\gl.h"\
".\L\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\win32\glw_imp.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_GLW_I=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
"..\win32\glw_win.h"\
"..\win32\winquake.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GLW_I=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_GLW_I=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
"..\win32\glw_win.h"\
"..\win32\winquake.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_GLW_I=\
".\L\gl.h"\
".\L\glu.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\game\q_shared.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_Q_SHA=\
"..\game\q_shared.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_Q_SHA=\
"..\game\q_shared.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\win32\q_shwin.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_Q_SHW=\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
"..\win32\winquake.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_Q_SHW=\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
"..\win32\winquake.h"\
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\win32\qgl_win.c
!IF "$(CFG)" == "ref_gl - Win32 Release"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug"
!ELSEIF "$(CFG)" == "ref_gl - Win32 Debug Alpha"
DEP_CPP_QGL_W=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
"..\win32\glw_win.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_QGL_W=\
".\L\gl.h"\
".\L\glu.h"\
!ELSEIF "$(CFG)" == "ref_gl - Win32 Release Alpha"
DEP_CPP_QGL_W=\
"..\client\ref.h"\
"..\game\q_shared.h"\
"..\qcommon\qcommon.h"\
"..\qcommon\qfiles.h"\
"..\win32\glw_win.h"\
".\gl_local.h"\
".\gl_model.h"\
".\qgl.h"\
NODEP_CPP_QGL_W=\
".\L\gl.h"\
".\L\glu.h"\
!ENDIF
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
SOURCE=.\anorms.h
# End Source File
# Begin Source File
SOURCE=.\anormtab.h
# End Source File
# Begin Source File
SOURCE=.\gl_local.h
# End Source File
# Begin Source File
SOURCE=.\gl_model.h
# End Source File
# Begin Source File
SOURCE=..\win32\glw_win.h
# End Source File
# Begin Source File
SOURCE=..\game\q_shared.h
# End Source File
# Begin Source File
SOURCE=..\qcommon\qcommon.h
# End Source File
# Begin Source File
SOURCE=..\qcommon\qfiles.h
# End Source File
# Begin Source File
SOURCE=.\qgl.h
# End Source File
# Begin Source File
SOURCE=.\qmenu.h
# End Source File
# Begin Source File
SOURCE=..\client\ref.h
# End Source File
# Begin Source File
SOURCE=.\ref_gl.h
# End Source File
# Begin Source File
SOURCE=.\warpsin.h
# End Source File
# Begin Source File
SOURCE=..\win32\winquake.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
# Begin Source File
SOURCE=.\ref_gl.def
# End Source File
# End Group
# End Target
# End Project

17
ref_gl/ref_gl.plg Normal file
View File

@ -0,0 +1,17 @@
--------------------Configuration: ref_gl - Win32 Release Alpha--------------------
Begining build with project "G:\quake2\code\ref_gl\ref_gl.dsp", at root.
Active configuration is Win32 (ALPHA) Dynamic-Link Library (based on Win32 (ALPHA) Dynamic-Link Library)
Project's tools are:
"OLE Type Library Maker" with flags "/nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 "
"C/C++ Compiler for Alpha" with flags "/nologo /QA21164 /MT /Gt0 /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "C_ONLY" /Fp".\ReleaseAXP/ref_gl.pch" /YX /Fo".\ReleaseAXP/" /Fd".\ReleaseAXP/" /FD /QAieee1 /c "
"Win32 Resource Compiler" with flags "/l 0x409 /d "NDEBUG" "
"Browser Database Maker" with flags "/nologo /o"..\ReleaseAXP/ref_gl.bsc" "
"COFF Linker for Alpha" with flags "kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"..\ReleaseAXP/ref_gl.pdb" /debug /machine:ALPHA /def:".\ref_gl.def" /out:"..\ReleaseAXP/ref_gl.dll" /implib:"..\ReleaseAXP/ref_gl.lib" "
"Custom Build" with flags ""
"<Component 0xa>" with flags ""
ref_gl.dll - 0 error(s), 0 warning(s)

51
ref_gl/warpsin.h Normal file
View File

@ -0,0 +1,51 @@
/*
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.
*/
0, 0.19633, 0.392541, 0.588517, 0.784137, 0.979285, 1.17384, 1.3677,
1.56072, 1.75281, 1.94384, 2.1337, 2.32228, 2.50945, 2.69512, 2.87916,
3.06147, 3.24193, 3.42044, 3.59689, 3.77117, 3.94319, 4.11282, 4.27998,
4.44456, 4.60647, 4.76559, 4.92185, 5.07515, 5.22538, 5.37247, 5.51632,
5.65685, 5.79398, 5.92761, 6.05767, 6.18408, 6.30677, 6.42566, 6.54068,
6.65176, 6.75883, 6.86183, 6.9607, 7.05537, 7.14579, 7.23191, 7.31368,
7.39104, 7.46394, 7.53235, 7.59623, 7.65552, 7.71021, 7.76025, 7.80562,
7.84628, 7.88222, 7.91341, 7.93984, 7.96148, 7.97832, 7.99036, 7.99759,
8, 7.99759, 7.99036, 7.97832, 7.96148, 7.93984, 7.91341, 7.88222,
7.84628, 7.80562, 7.76025, 7.71021, 7.65552, 7.59623, 7.53235, 7.46394,
7.39104, 7.31368, 7.23191, 7.14579, 7.05537, 6.9607, 6.86183, 6.75883,
6.65176, 6.54068, 6.42566, 6.30677, 6.18408, 6.05767, 5.92761, 5.79398,
5.65685, 5.51632, 5.37247, 5.22538, 5.07515, 4.92185, 4.76559, 4.60647,
4.44456, 4.27998, 4.11282, 3.94319, 3.77117, 3.59689, 3.42044, 3.24193,
3.06147, 2.87916, 2.69512, 2.50945, 2.32228, 2.1337, 1.94384, 1.75281,
1.56072, 1.3677, 1.17384, 0.979285, 0.784137, 0.588517, 0.392541, 0.19633,
9.79717e-16, -0.19633, -0.392541, -0.588517, -0.784137, -0.979285, -1.17384, -1.3677,
-1.56072, -1.75281, -1.94384, -2.1337, -2.32228, -2.50945, -2.69512, -2.87916,
-3.06147, -3.24193, -3.42044, -3.59689, -3.77117, -3.94319, -4.11282, -4.27998,
-4.44456, -4.60647, -4.76559, -4.92185, -5.07515, -5.22538, -5.37247, -5.51632,
-5.65685, -5.79398, -5.92761, -6.05767, -6.18408, -6.30677, -6.42566, -6.54068,
-6.65176, -6.75883, -6.86183, -6.9607, -7.05537, -7.14579, -7.23191, -7.31368,
-7.39104, -7.46394, -7.53235, -7.59623, -7.65552, -7.71021, -7.76025, -7.80562,
-7.84628, -7.88222, -7.91341, -7.93984, -7.96148, -7.97832, -7.99036, -7.99759,
-8, -7.99759, -7.99036, -7.97832, -7.96148, -7.93984, -7.91341, -7.88222,
-7.84628, -7.80562, -7.76025, -7.71021, -7.65552, -7.59623, -7.53235, -7.46394,
-7.39104, -7.31368, -7.23191, -7.14579, -7.05537, -6.9607, -6.86183, -6.75883,
-6.65176, -6.54068, -6.42566, -6.30677, -6.18408, -6.05767, -5.92761, -5.79398,
-5.65685, -5.51632, -5.37247, -5.22538, -5.07515, -4.92185, -4.76559, -4.60647,
-4.44456, -4.27998, -4.11282, -3.94319, -3.77117, -3.59689, -3.42044, -3.24193,
-3.06147, -2.87916, -2.69512, -2.50945, -2.32228, -2.1337, -1.94384, -1.75281,
-1.56072, -1.3677, -1.17384, -0.979285, -0.784137, -0.588517, -0.392541, -0.19633,

1077
ref_soft/adivtab.h Normal file

File diff suppressed because it is too large Load Diff

181
ref_soft/anorms.h Normal file
View File

@ -0,0 +1,181 @@
/*
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.
*/
{-0.525731, 0.000000, 0.850651},
{-0.442863, 0.238856, 0.864188},
{-0.295242, 0.000000, 0.955423},
{-0.309017, 0.500000, 0.809017},
{-0.162460, 0.262866, 0.951056},
{0.000000, 0.000000, 1.000000},
{0.000000, 0.850651, 0.525731},
{-0.147621, 0.716567, 0.681718},
{0.147621, 0.716567, 0.681718},
{0.000000, 0.525731, 0.850651},
{0.309017, 0.500000, 0.809017},
{0.525731, 0.000000, 0.850651},
{0.295242, 0.000000, 0.955423},
{0.442863, 0.238856, 0.864188},
{0.162460, 0.262866, 0.951056},
{-0.681718, 0.147621, 0.716567},
{-0.809017, 0.309017, 0.500000},
{-0.587785, 0.425325, 0.688191},
{-0.850651, 0.525731, 0.000000},
{-0.864188, 0.442863, 0.238856},
{-0.716567, 0.681718, 0.147621},
{-0.688191, 0.587785, 0.425325},
{-0.500000, 0.809017, 0.309017},
{-0.238856, 0.864188, 0.442863},
{-0.425325, 0.688191, 0.587785},
{-0.716567, 0.681718, -0.147621},
{-0.500000, 0.809017, -0.309017},
{-0.525731, 0.850651, 0.000000},
{0.000000, 0.850651, -0.525731},
{-0.238856, 0.864188, -0.442863},
{0.000000, 0.955423, -0.295242},
{-0.262866, 0.951056, -0.162460},
{0.000000, 1.000000, 0.000000},
{0.000000, 0.955423, 0.295242},
{-0.262866, 0.951056, 0.162460},
{0.238856, 0.864188, 0.442863},
{0.262866, 0.951056, 0.162460},
{0.500000, 0.809017, 0.309017},
{0.238856, 0.864188, -0.442863},
{0.262866, 0.951056, -0.162460},
{0.500000, 0.809017, -0.309017},
{0.850651, 0.525731, 0.000000},
{0.716567, 0.681718, 0.147621},
{0.716567, 0.681718, -0.147621},
{0.525731, 0.850651, 0.000000},
{0.425325, 0.688191, 0.587785},
{0.864188, 0.442863, 0.238856},
{0.688191, 0.587785, 0.425325},
{0.809017, 0.309017, 0.500000},
{0.681718, 0.147621, 0.716567},
{0.587785, 0.425325, 0.688191},
{0.955423, 0.295242, 0.000000},
{1.000000, 0.000000, 0.000000},
{0.951056, 0.162460, 0.262866},
{0.850651, -0.525731, 0.000000},
{0.955423, -0.295242, 0.000000},
{0.864188, -0.442863, 0.238856},
{0.951056, -0.162460, 0.262866},
{0.809017, -0.309017, 0.500000},
{0.681718, -0.147621, 0.716567},
{0.850651, 0.000000, 0.525731},
{0.864188, 0.442863, -0.238856},
{0.809017, 0.309017, -0.500000},
{0.951056, 0.162460, -0.262866},
{0.525731, 0.000000, -0.850651},
{0.681718, 0.147621, -0.716567},
{0.681718, -0.147621, -0.716567},
{0.850651, 0.000000, -0.525731},
{0.809017, -0.309017, -0.500000},
{0.864188, -0.442863, -0.238856},
{0.951056, -0.162460, -0.262866},
{0.147621, 0.716567, -0.681718},
{0.309017, 0.500000, -0.809017},
{0.425325, 0.688191, -0.587785},
{0.442863, 0.238856, -0.864188},
{0.587785, 0.425325, -0.688191},
{0.688191, 0.587785, -0.425325},
{-0.147621, 0.716567, -0.681718},
{-0.309017, 0.500000, -0.809017},
{0.000000, 0.525731, -0.850651},
{-0.525731, 0.000000, -0.850651},
{-0.442863, 0.238856, -0.864188},
{-0.295242, 0.000000, -0.955423},
{-0.162460, 0.262866, -0.951056},
{0.000000, 0.000000, -1.000000},
{0.295242, 0.000000, -0.955423},
{0.162460, 0.262866, -0.951056},
{-0.442863, -0.238856, -0.864188},
{-0.309017, -0.500000, -0.809017},
{-0.162460, -0.262866, -0.951056},
{0.000000, -0.850651, -0.525731},
{-0.147621, -0.716567, -0.681718},
{0.147621, -0.716567, -0.681718},
{0.000000, -0.525731, -0.850651},
{0.309017, -0.500000, -0.809017},
{0.442863, -0.238856, -0.864188},
{0.162460, -0.262866, -0.951056},
{0.238856, -0.864188, -0.442863},
{0.500000, -0.809017, -0.309017},
{0.425325, -0.688191, -0.587785},
{0.716567, -0.681718, -0.147621},
{0.688191, -0.587785, -0.425325},
{0.587785, -0.425325, -0.688191},
{0.000000, -0.955423, -0.295242},
{0.000000, -1.000000, 0.000000},
{0.262866, -0.951056, -0.162460},
{0.000000, -0.850651, 0.525731},
{0.000000, -0.955423, 0.295242},
{0.238856, -0.864188, 0.442863},
{0.262866, -0.951056, 0.162460},
{0.500000, -0.809017, 0.309017},
{0.716567, -0.681718, 0.147621},
{0.525731, -0.850651, 0.000000},
{-0.238856, -0.864188, -0.442863},
{-0.500000, -0.809017, -0.309017},
{-0.262866, -0.951056, -0.162460},
{-0.850651, -0.525731, 0.000000},
{-0.716567, -0.681718, -0.147621},
{-0.716567, -0.681718, 0.147621},
{-0.525731, -0.850651, 0.000000},
{-0.500000, -0.809017, 0.309017},
{-0.238856, -0.864188, 0.442863},
{-0.262866, -0.951056, 0.162460},
{-0.864188, -0.442863, 0.238856},
{-0.809017, -0.309017, 0.500000},
{-0.688191, -0.587785, 0.425325},
{-0.681718, -0.147621, 0.716567},
{-0.442863, -0.238856, 0.864188},
{-0.587785, -0.425325, 0.688191},
{-0.309017, -0.500000, 0.809017},
{-0.147621, -0.716567, 0.681718},
{-0.425325, -0.688191, 0.587785},
{-0.162460, -0.262866, 0.951056},
{0.442863, -0.238856, 0.864188},
{0.162460, -0.262866, 0.951056},
{0.309017, -0.500000, 0.809017},
{0.147621, -0.716567, 0.681718},
{0.000000, -0.525731, 0.850651},
{0.425325, -0.688191, 0.587785},
{0.587785, -0.425325, 0.688191},
{0.688191, -0.587785, 0.425325},
{-0.955423, 0.295242, 0.000000},
{-0.951056, 0.162460, 0.262866},
{-1.000000, 0.000000, 0.000000},
{-0.850651, 0.000000, 0.525731},
{-0.955423, -0.295242, 0.000000},
{-0.951056, -0.162460, 0.262866},
{-0.864188, 0.442863, -0.238856},
{-0.951056, 0.162460, -0.262866},
{-0.809017, 0.309017, -0.500000},
{-0.864188, -0.442863, -0.238856},
{-0.951056, -0.162460, -0.262866},
{-0.809017, -0.309017, -0.500000},
{-0.681718, 0.147621, -0.716567},
{-0.681718, -0.147621, -0.716567},
{-0.850651, 0.000000, -0.525731},
{-0.688191, 0.587785, -0.425325},
{-0.587785, 0.425325, -0.688191},
{-0.425325, 0.688191, -0.587785},
{-0.425325, -0.688191, -0.587785},
{-0.587785, -0.425325, -0.688191},
{-0.688191, -0.587785, -0.425325},

121
ref_soft/asm_draw.h Normal file
View File

@ -0,0 +1,121 @@
//
// asm_draw.h
//
// Include file for asm drawing routines.
//
//
// !!! note that this file must match the corresponding C structures at all
// times !!!
//
// !!! if this is changed, it must be changed in r_local.h too !!!
#define NEAR_CLIP 0.01
// !!! if this is changed, it must be changed in r_local.h too !!!
#define CYCLE 128
// espan_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define espan_t_u 0
#define espan_t_v 4
#define espan_t_count 8
#define espan_t_pnext 12
#define espan_t_size 16
// sspan_t structure
// !!! if this is changed, it must be changed in d_local.h too !!!
#define sspan_t_u 0
#define sspan_t_v 4
#define sspan_t_count 8
#define sspan_t_pnext 12
#define sspan_t_size 16
// edge_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define et_u 0
#define et_u_step 4
#define et_prev 8
#define et_next 12
#define et_surfs 16
#define et_nextremove 20
#define et_nearzi 24
#define et_owner 28
#define et_size 32
// surf_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define SURF_T_SHIFT 6
#define st_next 0
#define st_prev 4
#define st_spans 8
#define st_key 12
#define st_last_u 16
#define st_spanstate 20
#define st_flags 24
#define st_data 28
#define st_entity 32
#define st_nearzi 36
#define st_insubmodel 40
#define st_d_ziorigin 44
#define st_d_zistepu 48
#define st_d_zistepv 52
#define st_pad 56
#define st_size 64
// clipplane_t structure
// !!! if this is changed, it must be changed in r_local.h too !!!
#define cp_normal 0
#define cp_dist 12
#define cp_next 16
#define cp_leftedge 20
#define cp_rightedge 21
#define cp_reserved 22
#define cp_size 24
// medge_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define me_v 0
#define me_cachededgeoffset 4
#define me_size 8
// mvertex_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define mv_position 0
#define mv_size 12
// refdef_t structure
// !!! if this is changed, it must be changed in render.h too !!!
#define rd_vrect 0
#define rd_aliasvrect 20
#define rd_vrectright 40
#define rd_vrectbottom 44
#define rd_aliasvrectright 48
#define rd_aliasvrectbottom 52
#define rd_vrectrightedge 56
#define rd_fvrectx 60
#define rd_fvrecty 64
#define rd_fvrectx_adj 68
#define rd_fvrecty_adj 72
#define rd_vrect_x_adj_shift20 76
#define rd_vrectright_adj_shift20 80
#define rd_fvrectright_adj 84
#define rd_fvrectbottom_adj 88
#define rd_fvrectright 92
#define rd_fvrectbottom 96
#define rd_horizontalFieldOfView 100
#define rd_xOrigin 104
#define rd_yOrigin 108
#define rd_vieworg 112
#define rd_viewangles 124
#define rd_ambientlight 136
#define rd_size 140
// mtriangle_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define mtri_facesfront 0
#define mtri_vertindex 4
#define mtri_size 16 // !!! if this changes, array indexing in !!!
// !!! d_polysa.s must be changed to match !!!
#define mtri_shift 4

116
ref_soft/block16.inc Normal file
View File

@ -0,0 +1,116 @@
LEnter16_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch0:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch1:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch2:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch3:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch4:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch5:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch6:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch7:
mov ds:word ptr[2+edi],cx
add edi,04h
LEnter8_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch8:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch9:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch10:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch11:
mov ds:word ptr[2+edi],cx
add edi,04h
LEnter4_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch12:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch13:
mov ds:word ptr[2+edi],cx
add edi,04h
LEnter2_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch14:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch15:
mov ds:word ptr[2+edi],cx
add edi,04h

116
ref_soft/block8.inc Normal file
View File

@ -0,0 +1,116 @@
LEnter16_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch0:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch1:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch2:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch3:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch4:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch5:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch6:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch7:
mov ds:word ptr[2+edi],cx
add edi,04h
LEnter8_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch8:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch9:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch10:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch11:
mov ds:word ptr[2+edi],cx
add edi,04h
LEnter4_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch12:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch13:
mov ds:word ptr[2+edi],cx
add edi,04h
LEnter2_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch14:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch15:
mov ds:word ptr[2+edi],cx
add edi,04h

81
ref_soft/d_if.inc Normal file
View File

@ -0,0 +1,81 @@
;
; d_ifacea.h
;
; Include file for asm driver interface.
;
;
; !!! note that this file must match the corresponding C structures in
; d_iface.h at all times !!!
;
; !!! if this is changed, it must be changed in r_shared.h too !!!
ALIAS_ONSEAM equ 00020h
; !!! if this is changed, it must be changed in d_iface.h too !!!
TURB_TEX_SIZE equ 64
; !!! if this is changed, it must be changed in d_iface.h too !!!
CYCLE equ 128
; !!! if this is changed, it must be changed in r_shared.h too !!!
MAXHEIGHT equ 1024
; !!! if this is changed, it must be changed in quakedef.h too !!!
CACHE_SIZE equ 32
; particle_t structure
; !!! if this is changed, it must be changed in d_iface.h too !!!
; driver-usable fields
pt_org equ 0
pt_color equ 12
; drivers never touch the following fields
pt_next equ 16
pt_vel equ 20
pt_ramp equ 32
pt_die equ 36
pt_type equ 40
pt_size equ 44
PARTICLE_Z_CLIP equ 8.0
; finalvert_t structure
; !!! if this is changed, it must be changed in d_iface.h too !!!
fv_v equ 0 ; !!! if this is moved, cases where the !!!
; !!! address of this field is pushed in !!!
; !!! d_polysa.s must be changed !!!
fv_flags equ 24
fv_reserved equ 28
fv_size equ 32
fv_shift equ 5
; stvert_t structure
; !!! if this is changed, it must be changed in modelgen.h too !!!
stv_onseam equ 0
stv_s equ 4
stv_t equ 8
stv_size equ 12
; trivertx_t structure
; !!! if this is changed, it must be changed in modelgen.h too !!!
tv_v equ 0
tv_lightnormalindex equ 3
tv_size equ 4
; affinetridesc_t structure
; !!! if this is changed, it must be changed in d_iface.h too !!!
atd_pskin equ 0
atd_pskindesc equ 4
atd_skinwidth equ 8
atd_skinheight equ 12
atd_ptriangles equ 16
atd_pfinalverts equ 20
atd_numtriangles equ 24
atd_drawtype equ 28
atd_seamfixupX16 equ 32
atd_do_vis_thresh equ 36
atd_vis_thresh equ 40
atd_size equ 44

76
ref_soft/d_ifacea.h Normal file
View File

@ -0,0 +1,76 @@
//
// d_ifacea.h
//
// Include file for asm driver interface.
//
//
// !!! note that this file must match the corresponding C structures in
// d_iface.h at all times !!!
//
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define TURB_TEX_SIZE 64 // base turbulent texture size
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define CYCLE 128
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define MAXHEIGHT 1200
// !!! if this is changed, it must be changed in qcommon.h too !!!
#define CACHE_SIZE 32 // used to align key data structures
// particle_t structure
// !!! if this is changed, it must be changed in d_iface.h too !!!
// driver-usable fields
#define pt_org 0
#define pt_color 12
// drivers never touch the following fields
#define pt_next 16
#define pt_vel 20
#define pt_ramp 32
#define pt_die 36
#define pt_type 40
#define pt_size 44
#define PARTICLE_Z_CLIP 8.0
// finalvert_t structure
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define fv_v 0 // !!! if this is moved, cases where the !!!
// !!! address of this field is pushed in !!!
// !!! d_polysa.s must be changed !!!
#define fv_flags 24
#define fv_reserved 28
#define fv_size 32
#define fv_shift 5
// stvert_t structure
// !!! if this is changed, it must be changed in modelgen.h too !!!
#define stv_onseam 0
#define stv_s 4
#define stv_t 8
#define stv_size 12
// trivertx_t structure
// !!! if this is changed, it must be changed in modelgen.h too !!!
#define tv_v 0
#define tv_lightnormalindex 3
#define tv_size 4
// affinetridesc_t structure
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define atd_pskin 0
#define atd_pskindesc 4
#define atd_skinwidth 8
#define atd_skinheight 12
#define atd_ptriangles 16
#define atd_pfinalverts 20
#define atd_numtriangles 24
#define atd_drawtype 28
#define atd_seamfixupX16 32
#define atd_size 36

435
ref_soft/qasm.inc Normal file
View File

@ -0,0 +1,435 @@
;
; qasm.inc
;
; Include file for asm routines.
;
;
; !!! note that this file must match the corresponding C structures at all
; times !!!
;
; set to 0 to skip all asm code
id386 equ 1
; !!! must be kept the same as in d_iface.h !!!
TRANSPARENT_COLOR equ 255
ifndef GLQUAKE
externdef _d_zistepu:dword
externdef _d_pzbuffer:dword
externdef _d_zistepv:dword
externdef _d_zrowbytes:dword
externdef _d_ziorigin:dword
externdef _r_turb_s:dword
externdef _r_turb_t:dword
externdef _r_turb_pdest:dword
externdef _r_turb_spancount:dword
externdef _r_turb_turb:dword
externdef _r_turb_pbase:dword
externdef _r_turb_sstep:dword
externdef _r_turb_tstep:dword
externdef _r_bmodelactive:dword
externdef _d_sdivzstepu:dword
externdef _d_tdivzstepu:dword
externdef _d_sdivzstepv:dword
externdef _d_tdivzstepv:dword
externdef _d_sdivzorigin:dword
externdef _d_tdivzorigin:dword
externdef _sadjust:dword
externdef _tadjust:dword
externdef _bbextents:dword
externdef _bbextentt:dword
externdef _cacheblock:dword
externdef _d_viewbuffer:dword
externdef _cachewidth:dword
externdef _d_pzbuffer:dword
externdef _d_zrowbytes:dword
externdef _d_zwidth:dword
externdef _d_scantable:dword
externdef _r_lightptr:dword
externdef _r_numvblocks:dword
externdef _prowdestbase:dword
externdef _pbasesource:dword
externdef _r_lightwidth:dword
externdef _lightright:dword
externdef _lightrightstep:dword
externdef _lightdeltastep:dword
externdef _lightdelta:dword
externdef _lightright:dword
externdef _lightdelta:dword
externdef _sourcetstep:dword
externdef _surfrowbytes:dword
externdef _lightrightstep:dword
externdef _lightdeltastep:dword
externdef _r_sourcemax:dword
externdef _r_stepback:dword
externdef _colormap:dword
externdef _blocksize:dword
externdef _sourcesstep:dword
externdef _lightleft:dword
externdef _blockdivshift:dword
externdef _blockdivmask:dword
externdef _lightleftstep:dword
externdef _r_origin:dword
externdef _r_ppn:dword
externdef _r_pup:dword
externdef _r_pright:dword
externdef _ycenter:dword
externdef _xcenter:dword
externdef _d_vrectbottom_particle:dword
externdef _d_vrectright_particle:dword
externdef _d_vrecty:dword
externdef _d_vrectx:dword
externdef _d_pix_shift:dword
externdef _d_pix_min:dword
externdef _d_pix_max:dword
externdef _d_y_aspect_shift:dword
externdef _screenwidth:dword
externdef _r_leftclipped:dword
externdef _r_leftenter:dword
externdef _r_rightclipped:dword
externdef _r_rightenter:dword
externdef _modelorg:dword
externdef _xscale:dword
externdef _r_refdef:dword
externdef _yscale:dword
externdef _r_leftexit:dword
externdef _r_rightexit:dword
externdef _r_lastvertvalid:dword
externdef _cacheoffset:dword
externdef _newedges:dword
externdef _removeedges:dword
externdef _r_pedge:dword
externdef _r_framecount:dword
externdef _r_u1:dword
externdef _r_emitted:dword
externdef _edge_p:dword
externdef _surface_p:dword
externdef _surfaces:dword
externdef _r_lzi1:dword
externdef _r_v1:dword
externdef _r_ceilv1:dword
externdef _r_nearzi:dword
externdef _r_nearzionly:dword
externdef _edge_aftertail:dword
externdef _edge_tail:dword
externdef _current_iv:dword
externdef _edge_head_u_shift20:dword
externdef _span_p:dword
externdef _edge_head:dword
externdef _fv:dword
externdef _edge_tail_u_shift20:dword
externdef _r_apverts:dword
externdef _r_anumverts:dword
externdef _aliastransform:dword
externdef _r_avertexnormals:dword
externdef _r_plightvec:dword
externdef _r_ambientlight:dword
externdef _r_shadelight:dword
externdef _aliasxcenter:dword
externdef _aliasycenter:dword
externdef _a_sstepxfrac:dword
externdef _r_affinetridesc:dword
externdef _acolormap:dword
externdef _d_pcolormap:dword
externdef _r_affinetridesc:dword
externdef _d_sfrac:dword
externdef _d_ptex:dword
externdef _d_pedgespanpackage:dword
externdef _d_tfrac:dword
externdef _d_light:dword
externdef _d_zi:dword
externdef _d_pdest:dword
externdef _d_pz:dword
externdef _d_aspancount:dword
externdef _erroradjustup:dword
externdef _errorterm:dword
externdef _d_xdenom:dword
externdef _r_p0:dword
externdef _r_p1:dword
externdef _r_p2:dword
externdef _a_tstepxfrac:dword
externdef _r_sstepx:dword
externdef _r_tstepx:dword
externdef _a_ststepxwhole:dword
externdef _zspantable:dword
externdef _skintable:dword
externdef _r_zistepx:dword
externdef _erroradjustdown:dword
externdef _d_countextrastep:dword
externdef _ubasestep:dword
externdef _a_ststepxwhole:dword
externdef _a_tstepxfrac:dword
externdef _r_lstepx:dword
externdef _a_spans:dword
externdef _erroradjustdown:dword
externdef _d_pdestextrastep:dword
externdef _d_pzextrastep:dword
externdef _d_sfracextrastep:dword
externdef _d_ptexextrastep:dword
externdef _d_countextrastep:dword
externdef _d_tfracextrastep:dword
externdef _d_lightextrastep:dword
externdef _d_ziextrastep:dword
externdef _d_pdestbasestep:dword
externdef _d_pzbasestep:dword
externdef _d_sfracbasestep:dword
externdef _d_ptexbasestep:dword
externdef _ubasestep:dword
externdef _d_tfracbasestep:dword
externdef _d_lightbasestep:dword
externdef _d_zibasestep:dword
externdef _zspantable:dword
externdef _r_lstepy:dword
externdef _r_sstepy:dword
externdef _r_tstepy:dword
externdef _r_zistepy:dword
externdef _D_PolysetSetEdgeTable:dword
externdef _D_RasterizeAliasPolySmooth:dword
externdef float_point5:dword
externdef Float2ToThe31nd:dword
externdef izistep:dword
externdef izi:dword
externdef FloatMinus2ToThe31nd:dword
externdef float_1:dword
externdef float_particle_z_clip:dword
externdef float_minus_1:dword
externdef float_0:dword
externdef fp_16:dword
externdef fp_64k:dword
externdef fp_1m:dword
externdef fp_1m_minus_1:dword
externdef fp_8 :dword
externdef entryvec_table:dword
externdef advancetable:dword
externdef sstep:dword
externdef tstep:dword
externdef pspantemp:dword
externdef counttemp:dword
externdef jumptemp:dword
externdef reciprocal_table:dword
externdef DP_Count:dword
externdef DP_u:dword
externdef DP_v:dword
externdef DP_32768:dword
externdef DP_Color:dword
externdef DP_Pix:dword
externdef DP_EntryTable:dword
externdef pbase:dword
externdef s:dword
externdef t:dword
externdef sfracf:dword
externdef tfracf:dword
externdef snext:dword
externdef tnext:dword
externdef spancountminus1:dword
externdef zi16stepu:dword
externdef sdivz16stepu:dword
externdef tdivz16stepu:dword
externdef zi8stepu:dword
externdef sdivz8stepu:dword
externdef tdivz8stepu:dword
externdef reciprocal_table_16:dword
externdef entryvec_table_16:dword
externdef fp_64kx64k:dword
externdef pz:dword
externdef spr8entryvec_table:dword
endif
externdef _fpu_ceil_cw:dword
externdef _fpu_chop_cw:dword
externdef _snd_scaletable:dword
externdef _paintbuffer:dword
externdef _snd_linear_count:dword
externdef _snd_p:dword
externdef _snd_vol:dword
externdef _snd_out:dword
externdef _vright:dword
externdef _vup:dword
externdef _vpn:dword
externdef _BOPS_Error:dword
; plane_t structure
; !!! if this is changed, it must be changed in model.h too !!!
; !!! if the size of this is changed, the array lookup in SV_HullPointContents
; must be changed too !!!
pl_normal equ 0
pl_dist equ 12
pl_type equ 16
pl_signbits equ 17
pl_pad equ 18
pl_size equ 20
; hull_t structure
; !!! if this is changed, it must be changed in model.h too !!!
hu_clipnodes equ 0
hu_planes equ 4
hu_firstclipnode equ 8
hu_lastclipnode equ 12
hu_clip_mins equ 16
hu_clip_maxs equ 28
hu_size equ 40
; dnode_t structure
; !!! if this is changed, it must be changed in bspfile.h too !!!
nd_planenum equ 0
nd_children equ 4
nd_mins equ 8
nd_maxs equ 20
nd_firstface equ 32
nd_numfaces equ 36
nd_size equ 40
; sfxcache_t structure
; !!! if this is changed, it much be changed in sound.h too !!!
sfxc_length equ 0
sfxc_loopstart equ 4
sfxc_speed equ 8
sfxc_width equ 12
sfxc_stereo equ 16
sfxc_data equ 20
; channel_t structure
; !!! if this is changed, it much be changed in sound.h too !!!
ch_sfx equ 0
ch_leftvol equ 4
ch_rightvol equ 8
ch_end equ 12
ch_pos equ 16
ch_looping equ 20
ch_entnum equ 24
ch_entchannel equ 28
ch_origin equ 32
ch_dist_mult equ 44
ch_master_vol equ 48
ch_size equ 52
; portable_samplepair_t structure
; !!! if this is changed, it much be changed in sound.h too !!!
psp_left equ 0
psp_right equ 4
psp_size equ 8
; !!! if this is changed, it must be changed in r_local.h too !!!
NEAR_CLIP equ 0.01
; !!! if this is changed, it must be changed in r_local.h too !!!
CYCLE equ 128
; espan_t structure
; !!! if this is changed, it must be changed in r_shared.h too !!!
espan_t_u equ 0
espan_t_v equ 4
espan_t_count equ 8
espan_t_pnext equ 12
espan_t_size equ 16
; sspan_t structure
; !!! if this is changed, it must be changed in d_local.h too !!!
sspan_t_u equ 0
sspan_t_v equ 4
sspan_t_count equ 8
sspan_t_size equ 12
; spanpackage_t structure
; !!! if this is changed, it must be changed in d_polyset.c too !!!
spanpackage_t_pdest equ 0
spanpackage_t_pz equ 4
spanpackage_t_count equ 8
spanpackage_t_ptex equ 12
spanpackage_t_sfrac equ 16
spanpackage_t_tfrac equ 20
spanpackage_t_light equ 24
spanpackage_t_zi equ 28
spanpackage_t_size equ 32
; edge_t structure
; !!! if this is changed, it must be changed in r_shared.h too !!!
et_u equ 0
et_u_step equ 4
et_prev equ 8
et_next equ 12
et_surfs equ 16
et_nextremove equ 20
et_nearzi equ 24
et_owner equ 28
et_size equ 32
; surf_t structure
; !!! if this is changed, it must be changed in r_shared.h too !!!
SURF_T_SHIFT equ 6
st_next equ 0
st_prev equ 4
st_spans equ 8
st_key equ 12
st_last_u equ 16
st_spanstate equ 20
st_flags equ 24
st_data equ 28
st_entity equ 32
st_nearzi equ 36
st_insubmodel equ 40
st_d_ziorigin equ 44
st_d_zistepu equ 48
st_d_zistepv equ 52
st_pad equ 56
st_size equ 64
; clipplane_t structure
; !!! if this is changed, it must be changed in r_local.h too !!!
cp_normal equ 0
cp_dist equ 12
cp_next equ 16
cp_leftedge equ 20
cp_rightedge equ 21
cp_reserved equ 22
cp_size equ 24
; medge_t structure
; !!! if this is changed, it must be changed in model.h too !!!
me_v equ 0
me_cachededgeoffset equ 4
me_size equ 8
; mvertex_t structure
; !!! if this is changed, it must be changed in model.h too !!!
mv_position equ 0
mv_size equ 12
; refdef_t structure
; !!! if this is changed, it must be changed in render.h too !!!
rd_vrect equ 0
rd_aliasvrect equ 20
rd_vrectright equ 40
rd_vrectbottom equ 44
rd_aliasvrectright equ 48
rd_aliasvrectbottom equ 52
rd_vrectrightedge equ 56
rd_fvrectx equ 60
rd_fvrecty equ 64
rd_fvrectx_adj equ 68
rd_fvrecty_adj equ 72
rd_vrect_x_adj_shift20 equ 76
rd_vrectright_adj_shift20 equ 80
rd_fvrectright_adj equ 84
rd_fvrectbottom_adj equ 88
rd_fvrectright equ 92
rd_fvrectbottom equ 96
rd_horizontalFieldOfView equ 100
rd_xOrigin equ 104
rd_yOrigin equ 108
rd_vieworg equ 112
rd_viewangles equ 124
rd_ambientlight equ 136
rd_size equ 140
; mtriangle_t structure
; !!! if this is changed, it must be changed in model.h too !!!
mtri_facesfront equ 0
mtri_vertindex equ 4
mtri_size equ 16 ; !!! if this changes, array indexing in !!!
; !!! d_polysa.s must be changed to match !!!
mtri_shift equ 4

323
ref_soft/r_aclip.c Normal file
View File

@ -0,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();
}
}

200
ref_soft/r_aclipa.asm Normal file
View File

@ -0,0 +1,200 @@
.386P
.model FLAT
;
; r_aliasa.s
; x86 assembly-language Alias model transform and project code.
;
include qasm.inc
include d_if.inc
if id386
_DATA SEGMENT
Ltemp0 dd 0
Ltemp1 dd 0
_DATA ENDS
_TEXT SEGMENT
pfv0 equ 8+4
pfv1 equ 8+8
outparm equ 8+12
public _R_Alias_clip_bottom
_R_Alias_clip_bottom:
push esi
push edi
mov esi,ds:dword ptr[pfv0+esp]
mov edi,ds:dword ptr[pfv1+esp]
mov eax,ds:dword ptr[_r_refdef+rd_aliasvrectbottom]
LDoForwardOrBackward:
mov edx,ds:dword ptr[fv_v+4+esi]
mov ecx,ds:dword ptr[fv_v+4+edi]
cmp edx,ecx
jl LDoForward
mov ecx,ds:dword ptr[fv_v+4+esi]
mov edx,ds:dword ptr[fv_v+4+edi]
mov edi,ds:dword ptr[pfv0+esp]
mov esi,ds:dword ptr[pfv1+esp]
LDoForward:
sub ecx,edx
sub eax,edx
mov ds:dword ptr[Ltemp1],ecx
mov ds:dword ptr[Ltemp0],eax
fild ds:dword ptr[Ltemp1]
fild ds:dword ptr[Ltemp0]
mov edx,ds:dword ptr[outparm+esp]
mov eax,2
fdivrp st(1),st(0) ; scale
LDo3Forward:
fild ds:dword ptr[fv_v+0+esi] ; fv0v0 | scale
fild ds:dword ptr[fv_v+0+edi] ; fv1v0 | fv0v0 | scale
fild ds:dword ptr[fv_v+4+esi] ; fv0v1 | fv1v0 | fv0v0 | scale
fild ds:dword ptr[fv_v+4+edi] ; fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale
fild ds:dword ptr[fv_v+8+esi] ; fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale
fild ds:dword ptr[fv_v+8+edi] ; fv1v2 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 |
; scale
fxch st(5) ; fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv1v2 |
; scale
fsub st(4),st(0) ; fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0-fv0v0 |
; fv1v2 | scale
fxch st(3) ; fv0v1 | fv0v2 | fv1v1 | fv0v0 | fv1v0-fv0v0 |
; fv1v2 | scale
fsub st(2),st(0) ; fv0v1 | fv0v2 | fv1v1-fv0v1 | fv0v0 |
; fv1v0-fv0v0 | fv1v2 | scale
fxch st(1) ; fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 |
; fv1v0-fv0v0 | fv1v2 | scale
fsub st(5),st(0) ; fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 |
; fv1v0-fv0v0 | fv1v2-fv0v2 | scale
fxch st(6) ; scale | fv0v1 | fv1v1-fv0v1 | fv0v0 |
; fv1v0-fv0v0 | fv1v2-fv0v2 | fv0v2
fmul st(4),st(0) ; scale | fv0v1 | fv1v1-fv0v1 | fv0v0 |
; (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2
add edi,12
fmul st(2),st(0) ; scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 |
; (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2
add esi,12
add edx,12
fmul st(5),st(0) ; scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 |
; (fv1v0-fv0v0)*scale | (fv1v2-fv0v2)*scale |
; fv0v2
fxch st(3) ; fv0v0 | fv0v1 | (fv1v1-fv0v1)*scale | scale |
; (fv1v0-fv0v0)*scale | (fv1v2-fv0v2)*scale |
; fv0v2
faddp st(4),st(0) ; fv0v1 | (fv1v1-fv0v1)*scale | scale |
; fv0v0+(fv1v0-fv0v0)*scale |
; (fv1v2-fv0v2)*scale | fv0v2
faddp st(1),st(0) ; fv0v1+(fv1v1-fv0v1)*scale | scale |
; fv0v0+(fv1v0-fv0v0)*scale |
; (fv1v2-fv0v2)*scale | fv0v2
fxch st(4) ; fv0v2 | scale | fv0v0+(fv1v0-fv0v0)*scale |
; (fv1v2-fv0v2)*scale | fv0v1+(fv1v1-fv0v1)*scale
faddp st(3),st(0) ; scale | fv0v0+(fv1v0-fv0v0)*scale |
; fv0v2+(fv1v2-fv0v2)*scale |
; fv0v1+(fv1v1-fv0v1)*scale
fxch st(1) ; fv0v0+(fv1v0-fv0v0)*scale | scale |
; fv0v2+(fv1v2-fv0v2)*scale |
; fv0v1+(fv1v1-fv0v1)*scale
fadd ds:dword ptr[float_point5]
fxch st(3) ; fv0v1+(fv1v1-fv0v1)*scale | scale |
; fv0v2+(fv1v2-fv0v2)*scale |
; fv0v0+(fv1v0-fv0v0)*scale
fadd ds:dword ptr[float_point5]
fxch st(2) ; fv0v2+(fv1v2-fv0v2)*scale | scale |
; fv0v1+(fv1v1-fv0v1)*scale |
; fv0v0+(fv1v0-fv0v0)*scale
fadd ds:dword ptr[float_point5]
fxch st(3) ; fv0v0+(fv1v0-fv0v0)*scale | scale |
; fv0v1+(fv1v1-fv0v1)*scale |
; fv0v2+(fv1v2-fv0v2)*scale
fistp ds:dword ptr[fv_v+0-12+edx] ; scale | fv0v1+(fv1v1-fv0v1)*scale |
; fv0v2+(fv1v2-fv0v2)*scale
fxch st(1) ; fv0v1+(fv1v1-fv0v1)*scale | scale |
; fv0v2+(fv1v2-fv0v2)*scale | scale
fistp ds:dword ptr[fv_v+4-12+edx] ; scale | fv0v2+(fv1v2-fv0v2)*scale
fxch st(1) ; fv0v2+(fv1v2-fv0v2)*sc | scale
fistp ds:dword ptr[fv_v+8-12+edx] ; scale
dec eax
jnz LDo3Forward
fstp st(0)
pop edi
pop esi
ret
public _R_Alias_clip_top
_R_Alias_clip_top:
push esi
push edi
mov esi,ds:dword ptr[pfv0+esp]
mov edi,ds:dword ptr[pfv1+esp]
mov eax,ds:dword ptr[_r_refdef+rd_aliasvrect+4]
jmp LDoForwardOrBackward
public _R_Alias_clip_right
_R_Alias_clip_right:
push esi
push edi
mov esi,ds:dword ptr[pfv0+esp]
mov edi,ds:dword ptr[pfv1+esp]
mov eax,ds:dword ptr[_r_refdef+rd_aliasvrectright]
LRightLeftEntry:
mov edx,ds:dword ptr[fv_v+4+esi]
mov ecx,ds:dword ptr[fv_v+4+edi]
cmp edx,ecx
mov edx,ds:dword ptr[fv_v+0+esi]
mov ecx,ds:dword ptr[fv_v+0+edi]
jl LDoForward2
mov ecx,ds:dword ptr[fv_v+0+esi]
mov edx,ds:dword ptr[fv_v+0+edi]
mov edi,ds:dword ptr[pfv0+esp]
mov esi,ds:dword ptr[pfv1+esp]
LDoForward2:
jmp LDoForward
public _R_Alias_clip_left
_R_Alias_clip_left:
push esi
push edi
mov esi,ds:dword ptr[pfv0+esp]
mov edi,ds:dword ptr[pfv1+esp]
mov eax,ds:dword ptr[_r_refdef+rd_aliasvrect+0]
jmp LRightLeftEntry
_TEXT ENDS
endif ;id386
END

1198
ref_soft/r_alias.c Normal file

File diff suppressed because it is too large Load Diff

637
ref_soft/r_bsp.c Normal file
View File

@ -0,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);
}

445
ref_soft/r_draw.c Normal file
View File

@ -0,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;
}
}
}

1234
ref_soft/r_draw16.asm Normal file

File diff suppressed because it is too large Load Diff

822
ref_soft/r_drawa.asm Normal file
View File

@ -0,0 +1,822 @@
.386P
.model FLAT
;
; r_drawa.s
; x86 assembly-language edge clipping and emission code
;
include qasm.inc
include d_if.inc
if id386
; !!! if these are changed, they must be changed in r_draw.c too !!!
FULLY_CLIPPED_CACHED equ 080000000h
FRAMECOUNT_MASK equ 07FFFFFFFh
_DATA SEGMENT
Ld0 dd 0.0
Ld1 dd 0.0
Lstack dd 0
Lfp_near_clip dd NEAR_CLIP
Lceilv0 dd 0
Lv dd 0
Lu0 dd 0
Lv0 dd 0
Lzi0 dd 0
_DATA ENDS
_TEXT SEGMENT
;----------------------------------------------------------------------
; edge clipping code
;----------------------------------------------------------------------
pv0 equ 4+12
pv1 equ 8+12
clip equ 12+12
align 4
public _R_ClipEdge
_R_ClipEdge:
push esi ; preserve register variables
push edi
push ebx
mov ds:dword ptr[Lstack],esp ; for clearing the stack later
; float d0, d1, f;
; mvertex_t clipvert;
mov ebx,ds:dword ptr[clip+esp]
mov esi,ds:dword ptr[pv0+esp]
mov edx,ds:dword ptr[pv1+esp]
; if (clip)
; {
test ebx,ebx
jz Lemit
; do
; {
Lcliploop:
; d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
; d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
fld ds:dword ptr[mv_position+0+esi]
fmul ds:dword ptr[cp_normal+0+ebx]
fld ds:dword ptr[mv_position+4+esi]
fmul ds:dword ptr[cp_normal+4+ebx]
fld ds:dword ptr[mv_position+8+esi]
fmul ds:dword ptr[cp_normal+8+ebx]
fxch st(1)
faddp st(2),st(0) ; d0mul2 | d0add0
fld ds:dword ptr[mv_position+0+edx]
fmul ds:dword ptr[cp_normal+0+ebx]
fld ds:dword ptr[mv_position+4+edx]
fmul ds:dword ptr[cp_normal+4+ebx]
fld ds:dword ptr[mv_position+8+edx]
fmul ds:dword ptr[cp_normal+8+ebx]
fxch st(1)
faddp st(2),st(0) ; d1mul2 | d1add0 | d0mul2 | d0add0
fxch st(3) ; d0add0 | d1add0 | d0mul2 | d1mul2
faddp st(2),st(0) ; d1add0 | dot0 | d1mul2
faddp st(2),st(0) ; dot0 | dot1
fsub ds:dword ptr[cp_dist+ebx] ; d0 | dot1
fxch st(1) ; dot1 | d0
fsub ds:dword ptr[cp_dist+ebx] ; d1 | d0
fxch st(1)
fstp ds:dword ptr[Ld0]
fstp ds:dword ptr[Ld1]
; if (d0 >= 0)
; {
mov eax,ds:dword ptr[Ld0]
mov ecx,ds:dword ptr[Ld1]
or ecx,eax
js Lp2
; both points are unclipped
Lcontinue:
;
; R_ClipEdge (&clipvert, pv1, clip->next);
; return;
; }
; } while ((clip = clip->next) != NULL);
mov ebx,ds:dword ptr[cp_next+ebx]
test ebx,ebx
jnz Lcliploop
; }
;// add the edge
; R_EmitEdge (pv0, pv1);
Lemit:
;
; set integer rounding to ceil mode, set to single precision
;
; FIXME: do away with by manually extracting integers from floats?
; FIXME: set less often
fldcw ds:word ptr[_fpu_ceil_cw]
; 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)
; {
cmp ds:dword ptr[_r_lastvertvalid],0
jz LCalcFirst
; u0 = r_u1;
; v0 = r_v1;
; lzi0 = r_lzi1;
; ceilv0 = r_ceilv1;
mov eax,ds:dword ptr[_r_lzi1]
mov ecx,ds:dword ptr[_r_u1]
mov ds:dword ptr[Lzi0],eax
mov ds:dword ptr[Lu0],ecx
mov ecx,ds:dword ptr[_r_v1]
mov eax,ds:dword ptr[_r_ceilv1]
mov ds:dword ptr[Lv0],ecx
mov ds:dword ptr[Lceilv0],eax
jmp LCalcSecond
; }
LCalcFirst:
; else
; {
; world = &pv0->position[0];
call near ptr LTransformAndProject ; v0 | lzi0 | u0
fst ds:dword ptr[Lv0]
fxch st(2) ; u0 | lzi0 | v0
fstp ds:dword ptr[Lu0] ; lzi0 | v0
fstp ds:dword ptr[Lzi0] ; v0
; ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
fistp ds:dword ptr[Lceilv0]
; }
LCalcSecond:
; world = &pv1->position[0];
mov esi,edx
call near ptr LTransformAndProject ; v1 | lzi1 | u1
fld ds:dword ptr[Lu0] ; u0 | v1 | lzi1 | u1
fxch st(3) ; u1 | v1 | lzi1 | u0
fld ds:dword ptr[Lzi0] ; lzi0 | u1 | v1 | lzi1 | u0
fxch st(3) ; lzi1 | u1 | v1 | lzi0 | u0
fld ds:dword ptr[Lv0] ; v0 | lzi1 | u1 | v1 | lzi0 | u0
fxch st(3) ; v1 | lzi1 | u1 | v0 | lzi0 | u0
; r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
fist ds:dword ptr[_r_ceilv1]
fldcw ds:word ptr[_fpu_chop_cw] ; put back normal floating-point state
fst ds:dword ptr[_r_v1]
fxch st(4) ; lzi0 | lzi1 | u1 | v0 | v1 | u0
; if (r_lzi1 > lzi0)
; lzi0 = r_lzi1;
fcom st(1)
fnstsw ax
test ah,1
jz LP0
fstp st(0)
fld st(0)
LP0:
fxch st(1) ; lzi1 | lzi0 | u1 | v0 | v1 | u0
fstp ds:dword ptr[_r_lzi1] ; lzi0 | u1 | v0 | v1 | u0
fxch st(1)
fst ds:dword ptr[_r_u1]
fxch st(1)
; if (lzi0 > r_nearzi) // for mipmap finding
; r_nearzi = lzi0;
fcom ds:dword ptr[_r_nearzi]
fnstsw ax
test ah,045h
jnz LP1
fst ds:dword ptr[_r_nearzi]
LP1:
; // for right edges, all we want is the effect on 1/z
; if (r_nearzionly)
; return;
mov eax,ds:dword ptr[_r_nearzionly]
test eax,eax
jz LP2
LPop5AndDone:
mov eax,ds:dword ptr[_cacheoffset]
mov edx,ds:dword ptr[_r_framecount]
cmp eax,07FFFFFFFh
jz LDoPop
and edx,offset FRAMECOUNT_MASK
or edx,offset FULLY_CLIPPED_CACHED
mov ds:dword ptr[_cacheoffset],edx
LDoPop:
fstp st(0) ; u1 | v0 | v1 | u0
fstp st(0) ; v0 | v1 | u0
fstp st(0) ; v1 | u0
fstp st(0) ; u0
fstp st(0)
jmp Ldone
LP2:
; // create the edge
; if (ceilv0 == r_ceilv1)
; return; // horizontal edge
mov ebx,ds:dword ptr[Lceilv0]
mov edi,ds:dword ptr[_edge_p]
mov ecx,ds:dword ptr[_r_ceilv1]
mov edx,edi
mov esi,ds:dword ptr[_r_pedge]
add edx,offset et_size
cmp ebx,ecx
jz LPop5AndDone
mov eax,ds:dword ptr[_r_pedge]
mov ds:dword ptr[et_owner+edi],eax
; side = ceilv0 > r_ceilv1;
;
; edge->nearzi = lzi0;
fstp ds:dword ptr[et_nearzi+edi] ; u1 | v0 | v1 | u0
; if (side == 1)
; {
jc LSide0
LSide1:
; // leading edge (go from p2 to p1)
; u_step = ((u0 - r_u1) / (v0 - r_v1));
fsubp st(3),st(0) ; v0 | v1 | u0-u1
fsub st(0),st(1) ; v0-v1 | v1 | u0-u1
fdivp st(2),st(0) ; v1 | ustep
; r_emitted = 1;
mov ds:dword ptr[_r_emitted],1
; edge = edge_p++;
mov ds:dword ptr[_edge_p],edx
; pretouch next edge
mov eax,ds:dword ptr[edx]
; v2 = ceilv0 - 1;
; v = r_ceilv1;
mov eax,ecx
lea ecx,ds:dword ptr[-1+ebx]
mov ebx,eax
; edge->surfs[0] = 0;
; edge->surfs[1] = surface_p - surfaces;
mov eax,ds:dword ptr[_surface_p]
mov esi,ds:dword ptr[_surfaces]
sub edx,edx
sub eax,esi
shr eax,offset SURF_T_SHIFT
mov ds:dword ptr[et_surfs+edi],edx
mov ds:dword ptr[et_surfs+2+edi],eax
sub esi,esi
; u = r_u1 + ((float)v - r_v1) * u_step;
mov ds:dword ptr[Lv],ebx
fild ds:dword ptr[Lv] ; v | v1 | ustep
fsubrp st(1),st(0) ; v-v1 | ustep
fmul st(0),st(1) ; (v-v1)*ustep | ustep
fadd ds:dword ptr[_r_u1] ; u | ustep
jmp LSideDone
; }
LSide0:
; else
; {
; // trailing edge (go from p1 to p2)
; u_step = ((r_u1 - u0) / (r_v1 - v0));
fsub st(0),st(3) ; u1-u0 | v0 | v1 | u0
fxch st(2) ; v1 | v0 | u1-u0 | u0
fsub st(0),st(1) ; v1-v0 | v0 | u1-u0 | u0
fdivp st(2),st(0) ; v0 | ustep | u0
; r_emitted = 1;
mov ds:dword ptr[_r_emitted],1
; edge = edge_p++;
mov ds:dword ptr[_edge_p],edx
; pretouch next edge
mov eax,ds:dword ptr[edx]
; v = ceilv0;
; v2 = r_ceilv1 - 1;
dec ecx
; edge->surfs[0] = surface_p - surfaces;
; edge->surfs[1] = 0;
mov eax,ds:dword ptr[_surface_p]
mov esi,ds:dword ptr[_surfaces]
sub edx,edx
sub eax,esi
shr eax,offset SURF_T_SHIFT
mov ds:dword ptr[et_surfs+2+edi],edx
mov ds:dword ptr[et_surfs+edi],eax
mov esi,1
; u = u0 + ((float)v - v0) * u_step;
mov ds:dword ptr[Lv],ebx
fild ds:dword ptr[Lv] ; v | v0 | ustep | u0
fsubrp st(1),st(0) ; v-v0 | ustep | u0
fmul st(0),st(1) ; (v-v0)*ustep | ustep | u0
faddp st(2),st(0) ; ustep | u
fxch st(1) ; u | ustep
; }
LSideDone:
; edge->u_step = u_step*0x100000;
; edge->u = u*0x100000 + 0xFFFFF;
fmul ds:dword ptr[fp_1m] ; u*0x100000 | ustep
fxch st(1) ; ustep | u*0x100000
fmul ds:dword ptr[fp_1m] ; ustep*0x100000 | u*0x100000
fxch st(1) ; u*0x100000 | ustep*0x100000
fadd ds:dword ptr[fp_1m_minus_1] ; u*0x100000 + 0xFFFFF | ustep*0x100000
fxch st(1) ; ustep*0x100000 | u*0x100000 + 0xFFFFF
fistp ds:dword ptr[et_u_step+edi] ; u*0x100000 + 0xFFFFF
fistp ds:dword ptr[et_u+edi]
; // 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;
mov eax,ds:dword ptr[et_u+edi]
mov edx,ds:dword ptr[_r_refdef+rd_vrect_x_adj_shift20]
cmp eax,edx
jl LP4
mov edx,ds:dword ptr[_r_refdef+rd_vrectright_adj_shift20]
cmp eax,edx
jng LP5
LP4:
mov ds:dword ptr[et_u+edi],edx
mov eax,edx
LP5:
; // sort the edge in normally
; u_check = edge->u;
;
; if (edge->surfs[0])
; u_check++; // sort trailers after leaders
add eax,esi
; if (!newedges[v] || newedges[v]->u >= u_check)
; {
mov esi,ds:dword ptr[_newedges+ebx*4]
test esi,esi
jz LDoFirst
cmp ds:dword ptr[et_u+esi],eax
jl LNotFirst
LDoFirst:
; edge->next = newedges[v];
; newedges[v] = edge;
mov ds:dword ptr[et_next+edi],esi
mov ds:dword ptr[_newedges+ebx*4],edi
jmp LSetRemove
; }
LNotFirst:
; else
; {
; pcheck = newedges[v];
;
; while (pcheck->next && pcheck->next->u < u_check)
; pcheck = pcheck->next;
LFindInsertLoop:
mov edx,esi
mov esi,ds:dword ptr[et_next+esi]
test esi,esi
jz LInsertFound
cmp ds:dword ptr[et_u+esi],eax
jl LFindInsertLoop
LInsertFound:
; edge->next = pcheck->next;
; pcheck->next = edge;
mov ds:dword ptr[et_next+edi],esi
mov ds:dword ptr[et_next+edx],edi
; }
LSetRemove:
; edge->nextremove = removeedges[v2];
; removeedges[v2] = edge;
mov eax,ds:dword ptr[_removeedges+ecx*4]
mov ds:dword ptr[_removeedges+ecx*4],edi
mov ds:dword ptr[et_nextremove+edi],eax
Ldone:
mov esp,ds:dword ptr[Lstack] ; clear temporary variables from stack
pop ebx ; restore register variables
pop edi
pop esi
ret
; at least one point is clipped
Lp2:
test eax,eax
jns Lp1
; else
; {
; // point 0 is clipped
; if (d1 < 0)
; {
mov eax,ds:dword ptr[Ld1]
test eax,eax
jns Lp3
; // both points are clipped
; // we do cache fully clipped edges
; if (!leftclipped)
mov eax,ds:dword ptr[_r_leftclipped]
mov ecx,ds:dword ptr[_r_pedge]
test eax,eax
jnz Ldone
; r_pedge->framecount = r_framecount;
mov eax,ds:dword ptr[_r_framecount]
and eax,offset FRAMECOUNT_MASK
or eax,offset FULLY_CLIPPED_CACHED
mov ds:dword ptr[_cacheoffset],eax
; return;
jmp Ldone
; }
Lp1:
; // point 0 is unclipped
; if (d1 >= 0)
; {
; // both points are unclipped
; continue;
; // only point 1 is clipped
; f = d0 / (d0 - d1);
fld ds:dword ptr[Ld0]
fld ds:dword ptr[Ld1]
fsubr st(0),st(1)
; // we don't cache partially clipped edges
mov ds:dword ptr[_cacheoffset],07FFFFFFFh
fdivp st(1),st(0)
sub esp,offset mv_size ; allocate space for clipvert
; 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]);
fld ds:dword ptr[mv_position+8+edx]
fsub ds:dword ptr[mv_position+8+esi]
fld ds:dword ptr[mv_position+4+edx]
fsub ds:dword ptr[mv_position+4+esi]
fld ds:dword ptr[mv_position+0+edx]
fsub ds:dword ptr[mv_position+0+esi] ; 0 | 1 | 2
; replace pv1 with the clip point
mov edx,esp
mov eax,ds:dword ptr[cp_leftedge+ebx]
test al,al
fmul st(0),st(3)
fxch st(1) ; 1 | 0 | 2
fmul st(0),st(3)
fxch st(2) ; 2 | 0 | 1
fmulp st(3),st(0) ; 0 | 1 | 2
fadd ds:dword ptr[mv_position+0+esi]
fxch st(1) ; 1 | 0 | 2
fadd ds:dword ptr[mv_position+4+esi]
fxch st(2) ; 2 | 0 | 1
fadd ds:dword ptr[mv_position+8+esi]
fxch st(1) ; 0 | 2 | 1
fstp ds:dword ptr[mv_position+0+esp] ; 2 | 1
fstp ds:dword ptr[mv_position+8+esp] ; 1
fstp ds:dword ptr[mv_position+4+esp]
; if (clip->leftedge)
; {
jz Ltestright
; r_leftclipped = true;
; r_leftexit = clipvert;
mov ds:dword ptr[_r_leftclipped],1
mov eax,ds:dword ptr[mv_position+0+esp]
mov ds:dword ptr[_r_leftexit+mv_position+0],eax
mov eax,ds:dword ptr[mv_position+4+esp]
mov ds:dword ptr[_r_leftexit+mv_position+4],eax
mov eax,ds:dword ptr[mv_position+8+esp]
mov ds:dword ptr[_r_leftexit+mv_position+8],eax
jmp Lcontinue
; }
Ltestright:
; else if (clip->rightedge)
; {
test ah,ah
jz Lcontinue
; r_rightclipped = true;
; r_rightexit = clipvert;
mov ds:dword ptr[_r_rightclipped],1
mov eax,ds:dword ptr[mv_position+0+esp]
mov ds:dword ptr[_r_rightexit+mv_position+0],eax
mov eax,ds:dword ptr[mv_position+4+esp]
mov ds:dword ptr[_r_rightexit+mv_position+4],eax
mov eax,ds:dword ptr[mv_position+8+esp]
mov ds:dword ptr[_r_rightexit+mv_position+8],eax
; }
;
; R_ClipEdge (pv0, &clipvert, clip->next);
; return;
; }
jmp Lcontinue
; }
Lp3:
; // only point 0 is clipped
; r_lastvertvalid = false;
mov ds:dword ptr[_r_lastvertvalid],0
; f = d0 / (d0 - d1);
fld ds:dword ptr[Ld0]
fld ds:dword ptr[Ld1]
fsubr st(0),st(1)
; // we don't cache partially clipped edges
mov ds:dword ptr[_cacheoffset],07FFFFFFFh
fdivp st(1),st(0)
sub esp,offset mv_size ; allocate space for clipvert
; 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]);
fld ds:dword ptr[mv_position+8+edx]
fsub ds:dword ptr[mv_position+8+esi]
fld ds:dword ptr[mv_position+4+edx]
fsub ds:dword ptr[mv_position+4+esi]
fld ds:dword ptr[mv_position+0+edx]
fsub ds:dword ptr[mv_position+0+esi] ; 0 | 1 | 2
mov eax,ds:dword ptr[cp_leftedge+ebx]
test al,al
fmul st(0),st(3)
fxch st(1) ; 1 | 0 | 2
fmul st(0),st(3)
fxch st(2) ; 2 | 0 | 1
fmulp st(3),st(0) ; 0 | 1 | 2
fadd ds:dword ptr[mv_position+0+esi]
fxch st(1) ; 1 | 0 | 2
fadd ds:dword ptr[mv_position+4+esi]
fxch st(2) ; 2 | 0 | 1
fadd ds:dword ptr[mv_position+8+esi]
fxch st(1) ; 0 | 2 | 1
fstp ds:dword ptr[mv_position+0+esp] ; 2 | 1
fstp ds:dword ptr[mv_position+8+esp] ; 1
fstp ds:dword ptr[mv_position+4+esp]
; replace pv0 with the clip point
mov esi,esp
; if (clip->leftedge)
; {
jz Ltestright2
; r_leftclipped = true;
; r_leftenter = clipvert;
mov ds:dword ptr[_r_leftclipped],1
mov eax,ds:dword ptr[mv_position+0+esp]
mov ds:dword ptr[_r_leftenter+mv_position+0],eax
mov eax,ds:dword ptr[mv_position+4+esp]
mov ds:dword ptr[_r_leftenter+mv_position+4],eax
mov eax,ds:dword ptr[mv_position+8+esp]
mov ds:dword ptr[_r_leftenter+mv_position+8],eax
jmp Lcontinue
; }
Ltestright2:
; else if (clip->rightedge)
; {
test ah,ah
jz Lcontinue
; r_rightclipped = true;
; r_rightenter = clipvert;
mov ds:dword ptr[_r_rightclipped],1
mov eax,ds:dword ptr[mv_position+0+esp]
mov ds:dword ptr[_r_rightenter+mv_position+0],eax
mov eax,ds:dword ptr[mv_position+4+esp]
mov ds:dword ptr[_r_rightenter+mv_position+4],eax
mov eax,ds:dword ptr[mv_position+8+esp]
mov ds:dword ptr[_r_rightenter+mv_position+8],eax
; }
jmp Lcontinue
; %esi = vec3_t point to transform and project
; %edx preserved
LTransformAndProject:
; // transform and project
; VectorSubtract (world, modelorg, local);
fld ds:dword ptr[mv_position+0+esi]
fsub ds:dword ptr[_modelorg+0]
fld ds:dword ptr[mv_position+4+esi]
fsub ds:dword ptr[_modelorg+4]
fld ds:dword ptr[mv_position+8+esi]
fsub ds:dword ptr[_modelorg+8]
fxch st(2) ; local[0] | local[1] | local[2]
; TransformVector (local, transformed);
;
; if (transformed[2] < NEAR_CLIP)
; transformed[2] = NEAR_CLIP;
;
; lzi0 = 1.0 / transformed[2];
fld st(0) ; local[0] | local[0] | local[1] | local[2]
fmul ds:dword ptr[_vpn+0] ; zm0 | local[0] | local[1] | local[2]
fld st(1) ; local[0] | zm0 | local[0] | local[1] |
; local[2]
fmul ds:dword ptr[_vright+0] ; xm0 | zm0 | local[0] | local[1] | local[2]
fxch st(2) ; local[0] | zm0 | xm0 | local[1] | local[2]
fmul ds:dword ptr[_vup+0] ; ym0 | zm0 | xm0 | local[1] | local[2]
fld st(3) ; local[1] | ym0 | zm0 | xm0 | local[1] |
; local[2]
fmul ds:dword ptr[_vpn+4] ; zm1 | ym0 | zm0 | xm0 | local[1] |
; local[2]
fld st(4) ; local[1] | zm1 | ym0 | zm0 | xm0 |
; local[1] | local[2]
fmul ds:dword ptr[_vright+4] ; xm1 | zm1 | ym0 | zm0 | xm0 |
; local[1] | local[2]
fxch st(5) ; local[1] | zm1 | ym0 | zm0 | xm0 |
; xm1 | local[2]
fmul ds:dword ptr[_vup+4] ; ym1 | zm1 | ym0 | zm0 | xm0 |
; xm1 | local[2]
fxch st(1) ; zm1 | ym1 | ym0 | zm0 | xm0 |
; xm1 | local[2]
faddp st(3),st(0) ; ym1 | ym0 | zm2 | xm0 | xm1 | local[2]
fxch st(3) ; xm0 | ym0 | zm2 | ym1 | xm1 | local[2]
faddp st(4),st(0) ; ym0 | zm2 | ym1 | xm2 | local[2]
faddp st(2),st(0) ; zm2 | ym2 | xm2 | local[2]
fld st(3) ; local[2] | zm2 | ym2 | xm2 | local[2]
fmul ds:dword ptr[_vpn+8] ; zm3 | zm2 | ym2 | xm2 | local[2]
fld st(4) ; local[2] | zm3 | zm2 | ym2 | xm2 | local[2]
fmul ds:dword ptr[_vright+8] ; xm3 | zm3 | zm2 | ym2 | xm2 | local[2]
fxch st(5) ; local[2] | zm3 | zm2 | ym2 | xm2 | xm3
fmul ds:dword ptr[_vup+8] ; ym3 | zm3 | zm2 | ym2 | xm2 | xm3
fxch st(1) ; zm3 | ym3 | zm2 | ym2 | xm2 | xm3
faddp st(2),st(0) ; ym3 | zm4 | ym2 | xm2 | xm3
fxch st(4) ; xm3 | zm4 | ym2 | xm2 | ym3
faddp st(3),st(0) ; zm4 | ym2 | xm4 | ym3
fxch st(1) ; ym2 | zm4 | xm4 | ym3
faddp st(3),st(0) ; zm4 | xm4 | ym4
fcom ds:dword ptr[Lfp_near_clip]
fnstsw ax
test ah,1
jz LNoClip
fstp st(0)
fld ds:dword ptr[Lfp_near_clip]
LNoClip:
fdivr ds:dword ptr[float_1] ; lzi0 | x | y
fxch st(1) ; x | lzi0 | y
; // FIXME: build x/yscale into transform?
; scale = xscale * lzi0;
; u0 = (xcenter + scale*transformed[0]);
fld ds:dword ptr[_xscale] ; xscale | x | lzi0 | y
fmul st(0),st(2) ; scale | x | lzi0 | y
fmulp st(1),st(0) ; scale*x | lzi0 | y
fadd ds:dword ptr[_xcenter] ; u0 | lzi0 | y
; if (u0 < r_refdef.fvrectx_adj)
; u0 = r_refdef.fvrectx_adj;
; if (u0 > r_refdef.fvrectright_adj)
; u0 = r_refdef.fvrectright_adj;
; FIXME: use integer compares of floats?
fcom ds:dword ptr[_r_refdef+rd_fvrectx_adj]
fnstsw ax
test ah,1
jz LClampP0
fstp st(0)
fld ds:dword ptr[_r_refdef+rd_fvrectx_adj]
LClampP0:
fcom ds:dword ptr[_r_refdef+rd_fvrectright_adj]
fnstsw ax
test ah,045h
jnz LClampP1
fstp st(0)
fld ds:dword ptr[_r_refdef+rd_fvrectright_adj]
LClampP1:
fld st(1) ; lzi0 | u0 | lzi0 | y
; scale = yscale * lzi0;
; v0 = (ycenter - scale*transformed[1]);
fmul ds:dword ptr[_yscale] ; scale | u0 | lzi0 | y
fmulp st(3),st(0) ; u0 | lzi0 | scale*y
fxch st(2) ; scale*y | lzi0 | u0
fsubr ds:dword ptr[_ycenter] ; v0 | lzi0 | u0
; if (v0 < r_refdef.fvrecty_adj)
; v0 = r_refdef.fvrecty_adj;
; if (v0 > r_refdef.fvrectbottom_adj)
; v0 = r_refdef.fvrectbottom_adj;
; FIXME: use integer compares of floats?
fcom ds:dword ptr[_r_refdef+rd_fvrecty_adj]
fnstsw ax
test ah,1
jz LClampP2
fstp st(0)
fld ds:dword ptr[_r_refdef+rd_fvrecty_adj]
LClampP2:
fcom ds:dword ptr[_r_refdef+rd_fvrectbottom_adj]
fnstsw ax
test ah,045h
jnz LClampP3
fstp st(0)
fld ds:dword ptr[_r_refdef+rd_fvrectbottom_adj]
LClampP3:
ret
_TEXT ENDS
endif ;id386
END

1125
ref_soft/r_edge.c Normal file

File diff suppressed because it is too large Load Diff

733
ref_soft/r_edgea.asm Normal file
View File

@ -0,0 +1,733 @@
.386P
.model FLAT
;
; r_edgea.s
; x86 assembly-language edge-processing code.
;
include qasm.inc
if id386
_DATA SEGMENT
Ltemp dd 0
float_1_div_0100000h dd 035800000h ; 1.0/(float)0x100000
float_point_999 dd 0.999
float_1_point_001 dd 1.001
_DATA ENDS
_TEXT SEGMENT
;--------------------------------------------------------------------
edgestoadd equ 4+8 ; note odd stack offsets because of interleaving
edgelist equ 8+12 ; with pushes
public _R_EdgeCodeStart
_R_EdgeCodeStart:
public _R_InsertNewEdges
_R_InsertNewEdges:
push edi
push esi ; preserve register variables
mov edx,ds:dword ptr[edgestoadd+esp]
push ebx
mov ecx,ds:dword ptr[edgelist+esp]
LDoNextEdge:
mov eax,ds:dword ptr[et_u+edx]
mov edi,edx
LContinueSearch:
mov ebx,ds:dword ptr[et_u+ecx]
mov esi,ds:dword ptr[et_next+ecx]
cmp eax,ebx
jle LAddedge
mov ebx,ds:dword ptr[et_u+esi]
mov ecx,ds:dword ptr[et_next+esi]
cmp eax,ebx
jle LAddedge2
mov ebx,ds:dword ptr[et_u+ecx]
mov esi,ds:dword ptr[et_next+ecx]
cmp eax,ebx
jle LAddedge
mov ebx,ds:dword ptr[et_u+esi]
mov ecx,ds:dword ptr[et_next+esi]
cmp eax,ebx
jg LContinueSearch
LAddedge2:
mov edx,ds:dword ptr[et_next+edx]
mov ebx,ds:dword ptr[et_prev+esi]
mov ds:dword ptr[et_next+edi],esi
mov ds:dword ptr[et_prev+edi],ebx
mov ds:dword ptr[et_next+ebx],edi
mov ds:dword ptr[et_prev+esi],edi
mov ecx,esi
cmp edx,0
jnz LDoNextEdge
jmp LDone
align 4
LAddedge:
mov edx,ds:dword ptr[et_next+edx]
mov ebx,ds:dword ptr[et_prev+ecx]
mov ds:dword ptr[et_next+edi],ecx
mov ds:dword ptr[et_prev+edi],ebx
mov ds:dword ptr[et_next+ebx],edi
mov ds:dword ptr[et_prev+ecx],edi
cmp edx,0
jnz LDoNextEdge
LDone:
pop ebx ; restore register variables
pop esi
pop edi
ret
;--------------------------------------------------------------------
predge equ 4+4
public _R_RemoveEdges
_R_RemoveEdges:
push ebx
mov eax,ds:dword ptr[predge+esp]
Lre_loop:
mov ecx,ds:dword ptr[et_next+eax]
mov ebx,ds:dword ptr[et_nextremove+eax]
mov edx,ds:dword ptr[et_prev+eax]
test ebx,ebx
mov ds:dword ptr[et_prev+ecx],edx
jz Lre_done
mov ds:dword ptr[et_next+edx],ecx
mov ecx,ds:dword ptr[et_next+ebx]
mov edx,ds:dword ptr[et_prev+ebx]
mov eax,ds:dword ptr[et_nextremove+ebx]
mov ds:dword ptr[et_prev+ecx],edx
test eax,eax
mov ds:dword ptr[et_next+edx],ecx
jnz Lre_loop
pop ebx
ret
Lre_done:
mov ds:dword ptr[et_next+edx],ecx
pop ebx
ret
;--------------------------------------------------------------------
pedgelist equ 4+4 ; note odd stack offset because of interleaving
; with pushes
public _R_StepActiveU
_R_StepActiveU:
push edi
mov edx,ds:dword ptr[pedgelist+esp]
push esi ; preserve register variables
push ebx
mov esi,ds:dword ptr[et_prev+edx]
LNewEdge:
mov edi,ds:dword ptr[et_u+esi]
LNextEdge:
mov eax,ds:dword ptr[et_u+edx]
mov ebx,ds:dword ptr[et_u_step+edx]
add eax,ebx
mov esi,ds:dword ptr[et_next+edx]
mov ds:dword ptr[et_u+edx],eax
cmp eax,edi
jl LPushBack
mov edi,ds:dword ptr[et_u+esi]
mov ebx,ds:dword ptr[et_u_step+esi]
add edi,ebx
mov edx,ds:dword ptr[et_next+esi]
mov ds:dword ptr[et_u+esi],edi
cmp edi,eax
jl LPushBack2
mov eax,ds:dword ptr[et_u+edx]
mov ebx,ds:dword ptr[et_u_step+edx]
add eax,ebx
mov esi,ds:dword ptr[et_next+edx]
mov ds:dword ptr[et_u+edx],eax
cmp eax,edi
jl LPushBack
mov edi,ds:dword ptr[et_u+esi]
mov ebx,ds:dword ptr[et_u_step+esi]
add edi,ebx
mov edx,ds:dword ptr[et_next+esi]
mov ds:dword ptr[et_u+esi],edi
cmp edi,eax
jnl LNextEdge
LPushBack2:
mov ebx,edx
mov eax,edi
mov edx,esi
mov esi,ebx
LPushBack:
; push it back to keep it sorted
mov ecx,ds:dword ptr[et_prev+edx]
mov ebx,ds:dword ptr[et_next+edx]
; done if the -1 in edge_aftertail triggered this
cmp edx,offset _edge_aftertail
jz LUDone
; pull the edge out of the edge list
mov edi,ds:dword ptr[et_prev+ecx]
mov ds:dword ptr[et_prev+esi],ecx
mov ds:dword ptr[et_next+ecx],ebx
; find out where the edge goes in the edge list
LPushBackLoop:
mov ecx,ds:dword ptr[et_prev+edi]
mov ebx,ds:dword ptr[et_u+edi]
cmp eax,ebx
jnl LPushBackFound
mov edi,ds:dword ptr[et_prev+ecx]
mov ebx,ds:dword ptr[et_u+ecx]
cmp eax,ebx
jl LPushBackLoop
mov edi,ecx
; put the edge back into the edge list
LPushBackFound:
mov ebx,ds:dword ptr[et_next+edi]
mov ds:dword ptr[et_prev+edx],edi
mov ds:dword ptr[et_next+edx],ebx
mov ds:dword ptr[et_next+edi],edx
mov ds:dword ptr[et_prev+ebx],edx
mov edx,esi
mov esi,ds:dword ptr[et_prev+esi]
cmp edx,offset _edge_tail
jnz LNewEdge
LUDone:
pop ebx ; restore register variables
pop esi
pop edi
ret
;--------------------------------------------------------------------
surf equ 4 ; note this is loaded before any pushes
align 4
TrailingEdge:
mov eax,ds:dword ptr[st_spanstate+esi] ; check for edge inversion
dec eax
jnz LInverted
mov ds:dword ptr[st_spanstate+esi],eax
mov ecx,ds:dword ptr[st_insubmodel+esi]
mov edx,ds:dword ptr[12345678h] ; surfaces[1].st_next
LPatch0:
mov eax,ds:dword ptr[_r_bmodelactive]
sub eax,ecx
cmp edx,esi
mov ds:dword ptr[_r_bmodelactive],eax
jnz LNoEmit ; surface isn't on top, just remove
; emit a span (current top going away)
mov eax,ds:dword ptr[et_u+ebx]
shr eax,20 ; iu = integral pixel u
mov edx,ds:dword ptr[st_last_u+esi]
mov ecx,ds:dword ptr[st_next+esi]
cmp eax,edx
jle LNoEmit2 ; iu <= surf->last_u, so nothing to emit
mov ds:dword ptr[st_last_u+ecx],eax ; surf->next->last_u = iu;
sub eax,edx
mov ds:dword ptr[espan_t_u+ebp],edx ; span->u = surf->last_u;
mov ds:dword ptr[espan_t_count+ebp],eax ; span->count = iu - span->u;
mov eax,ds:dword ptr[_current_iv]
mov ds:dword ptr[espan_t_v+ebp],eax ; span->v = current_iv;
mov eax,ds:dword ptr[st_spans+esi]
mov ds:dword ptr[espan_t_pnext+ebp],eax ; span->pnext = surf->spans;
mov ds:dword ptr[st_spans+esi],ebp ; surf->spans = span;
add ebp,offset espan_t_size
mov edx,ds:dword ptr[st_next+esi] ; remove the surface from the surface
mov esi,ds:dword ptr[st_prev+esi] ; stack
mov ds:dword ptr[st_next+esi],edx
mov ds:dword ptr[st_prev+edx],esi
ret
LNoEmit2:
mov ds:dword ptr[st_last_u+ecx],eax ; surf->next->last_u = iu;
mov edx,ds:dword ptr[st_next+esi] ; remove the surface from the surface
mov esi,ds:dword ptr[st_prev+esi] ; stack
mov ds:dword ptr[st_next+esi],edx
mov ds:dword ptr[st_prev+edx],esi
ret
LNoEmit:
mov edx,ds:dword ptr[st_next+esi] ; remove the surface from the surface
mov esi,ds:dword ptr[st_prev+esi] ; stack
mov ds:dword ptr[st_next+esi],edx
mov ds:dword ptr[st_prev+edx],esi
ret
LInverted:
mov ds:dword ptr[st_spanstate+esi],eax
ret
;--------------------------------------------------------------------
; trailing edge only
Lgs_trailing:
push offset Lgs_nextedge
jmp TrailingEdge
public _R_GenerateSpans
_R_GenerateSpans:
push ebp ; preserve caller's stack frame
push edi
push esi ; preserve register variables
push ebx
; clear active surfaces to just the background surface
mov eax,ds:dword ptr[_surfaces]
mov edx,ds:dword ptr[_edge_head_u_shift20]
add eax,offset st_size
; %ebp = span_p throughout
mov ebp,ds:dword ptr[_span_p]
mov ds:dword ptr[_r_bmodelactive],0
mov ds:dword ptr[st_next+eax],eax
mov ds:dword ptr[st_prev+eax],eax
mov ds:dword ptr[st_last_u+eax],edx
mov ebx,ds:dword ptr[_edge_head+et_next] ; edge=edge_head.next
; generate spans
cmp ebx,offset _edge_tail ; done if empty list
jz Lgs_lastspan
Lgs_edgeloop:
mov edi,ds:dword ptr[et_surfs+ebx]
mov eax,ds:dword ptr[_surfaces]
mov esi,edi
and edi,0FFFF0000h
and esi,0FFFFh
jz Lgs_leading ; not a trailing edge
; it has a left surface, so a surface is going away for this span
shl esi,offset SURF_T_SHIFT
add esi,eax
test edi,edi
jz Lgs_trailing
; both leading and trailing
call near ptr TrailingEdge
mov eax,ds:dword ptr[_surfaces]
; ---------------------------------------------------------------
; handle a leading edge
; ---------------------------------------------------------------
Lgs_leading:
shr edi,16-SURF_T_SHIFT
mov eax,ds:dword ptr[_surfaces]
add edi,eax
mov esi,ds:dword ptr[12345678h] ; surf2 = surfaces[1].next;
LPatch2:
mov edx,ds:dword ptr[st_spanstate+edi]
mov eax,ds:dword ptr[st_insubmodel+edi]
test eax,eax
jnz Lbmodel_leading
; handle a leading non-bmodel edge
; 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)
test edx,edx
jnz Lxl_done
; if (surf->key < surf2->key)
; goto newtop;
inc edx
mov eax,ds:dword ptr[st_key+edi]
mov ds:dword ptr[st_spanstate+edi],edx
mov ecx,ds:dword ptr[st_key+esi]
cmp eax,ecx
jl Lnewtop
; main sorting loop to search through surface stack until insertion point
; found. Always terminates because background surface is sentinel
; do
; {
; surf2 = surf2->next;
; } while (surf->key >= surf2->key);
Lsortloopnb:
mov esi,ds:dword ptr[st_next+esi]
mov ecx,ds:dword ptr[st_key+esi]
cmp eax,ecx
jge Lsortloopnb
jmp LInsertAndExit
; handle a leading bmodel edge
align 4
Lbmodel_leading:
; 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)
test edx,edx
jnz Lxl_done
mov ecx,ds:dword ptr[_r_bmodelactive]
inc edx
inc ecx
mov ds:dword ptr[st_spanstate+edi],edx
mov ds:dword ptr[_r_bmodelactive],ecx
; if (surf->key < surf2->key)
; goto newtop;
mov eax,ds:dword ptr[st_key+edi]
mov ecx,ds:dword ptr[st_key+esi]
cmp eax,ecx
jl Lnewtop
; if ((surf->key == surf2->key) && surf->insubmodel)
; {
jz Lzcheck_for_newtop
; main sorting loop to search through surface stack until insertion point
; found. Always terminates because background surface is sentinel
; do
; {
; surf2 = surf2->next;
; } while (surf->key > surf2->key);
Lsortloop:
mov esi,ds:dword ptr[st_next+esi]
mov ecx,ds:dword ptr[st_key+esi]
cmp eax,ecx
jg Lsortloop
jne LInsertAndExit
; Do 1/z sorting to see if we've arrived in the right position
mov eax,ds:dword ptr[et_u+ebx]
sub eax,0FFFFFh
mov ds:dword ptr[Ltemp],eax
fild ds:dword ptr[Ltemp]
fmul ds:dword ptr[float_1_div_0100000h] ; fu = (float)(edge->u - 0xFFFFF) *
; (1.0 / 0x100000);
fld st(0) ; fu | fu
fmul ds:dword ptr[st_d_zistepu+edi] ; fu*surf->d_zistepu | fu
fld ds:dword ptr[_fv] ; fv | fu*surf->d_zistepu | fu
fmul ds:dword ptr[st_d_zistepv+edi] ; fv*surf->d_zistepv | fu*surf->d_zistepu | fu
fxch st(1) ; fu*surf->d_zistepu | fv*surf->d_zistepv | fu
fadd ds:dword ptr[st_d_ziorigin+edi] ; fu*surf->d_zistepu + surf->d_ziorigin |
; fv*surf->d_zistepv | fu
fld ds:dword ptr[st_d_zistepu+esi] ; surf2->d_zistepu |
; fu*surf->d_zistepu + surf->d_ziorigin |
; fv*surf->d_zistepv | fu
fmul st(0),st(3) ; fu*surf2->d_zistepu |
; fu*surf->d_zistepu + surf->d_ziorigin |
; fv*surf->d_zistepv | fu
fxch st(1) ; fu*surf->d_zistepu + surf->d_ziorigin |
; fu*surf2->d_zistepu |
; fv*surf->d_zistepv | fu
faddp st(2),st(0) ; fu*surf2->d_zistepu | newzi | fu
fld ds:dword ptr[_fv] ; fv | fu*surf2->d_zistepu | newzi | fu
fmul ds:dword ptr[st_d_zistepv+esi] ; fv*surf2->d_zistepv |
; fu*surf2->d_zistepu | newzi | fu
fld st(2) ; newzi | fv*surf2->d_zistepv |
; fu*surf2->d_zistepu | newzi | fu
fmul ds:dword ptr[float_point_999] ; newzibottom | fv*surf2->d_zistepv |
; fu*surf2->d_zistepu | newzi | fu
fxch st(2) ; fu*surf2->d_zistepu | fv*surf2->d_zistepv |
; newzibottom | newzi | fu
fadd ds:dword ptr[st_d_ziorigin+esi] ; fu*surf2->d_zistepu + surf2->d_ziorigin |
; fv*surf2->d_zistepv | newzibottom | newzi |
; fu
faddp st(1),st(0) ; testzi | newzibottom | newzi | fu
fxch st(1) ; newzibottom | testzi | newzi | fu
; if (newzibottom >= testzi)
; goto Lgotposition;
fcomp st(1) ; testzi | newzi | fu
fxch st(1) ; newzi | testzi | fu
fmul ds:dword ptr[float_1_point_001] ; newzitop | testzi | fu
fxch st(1) ; testzi | newzitop | fu
fnstsw ax
test ah,001h
jz Lgotposition_fpop3
; if (newzitop >= testzi)
; {
fcomp st(1) ; newzitop | fu
fnstsw ax
test ah,045h
jz Lsortloop_fpop2
; if (surf->d_zistepu >= surf2->d_zistepu)
; goto newtop;
fld ds:dword ptr[st_d_zistepu+edi] ; surf->d_zistepu | newzitop| fu
fcomp ds:dword ptr[st_d_zistepu+esi] ; newzitop | fu
fnstsw ax
test ah,001h
jz Lgotposition_fpop2
fstp st(0) ; clear the FPstack
fstp st(0)
mov eax,ds:dword ptr[st_key+edi]
jmp Lsortloop
Lgotposition_fpop3:
fstp st(0)
Lgotposition_fpop2:
fstp st(0)
fstp st(0)
jmp LInsertAndExit
; emit a span (obscures current top)
Lnewtop_fpop3:
fstp st(0)
Lnewtop_fpop2:
fstp st(0)
fstp st(0)
mov eax,ds:dword ptr[st_key+edi] ; reload the sorting key
Lnewtop:
mov eax,ds:dword ptr[et_u+ebx]
mov edx,ds:dword ptr[st_last_u+esi]
shr eax,20 ; iu = integral pixel u
mov ds:dword ptr[st_last_u+edi],eax ; surf->last_u = iu;
cmp eax,edx
jle LInsertAndExit ; iu <= surf->last_u, so nothing to emit
sub eax,edx
mov ds:dword ptr[espan_t_u+ebp],edx ; span->u = surf->last_u;
mov ds:dword ptr[espan_t_count+ebp],eax ; span->count = iu - span->u;
mov eax,ds:dword ptr[_current_iv]
mov ds:dword ptr[espan_t_v+ebp],eax ; span->v = current_iv;
mov eax,ds:dword ptr[st_spans+esi]
mov ds:dword ptr[espan_t_pnext+ebp],eax ; span->pnext = surf->spans;
mov ds:dword ptr[st_spans+esi],ebp ; surf->spans = span;
add ebp,offset espan_t_size
LInsertAndExit:
; insert before surf2
mov ds:dword ptr[st_next+edi],esi ; surf->next = surf2;
mov eax,ds:dword ptr[st_prev+esi]
mov ds:dword ptr[st_prev+edi],eax ; surf->prev = surf2->prev;
mov ds:dword ptr[st_prev+esi],edi ; surf2->prev = surf;
mov ds:dword ptr[st_next+eax],edi ; surf2->prev->next = surf;
; ---------------------------------------------------------------
; leading edge done
; ---------------------------------------------------------------
; ---------------------------------------------------------------
; see if there are any more edges
; ---------------------------------------------------------------
Lgs_nextedge:
mov ebx,ds:dword ptr[et_next+ebx]
cmp ebx,offset _edge_tail
jnz Lgs_edgeloop
; clean up at the right edge
Lgs_lastspan:
; 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
mov esi,ds:dword ptr[12345678h] ; surfaces[1].st_next
LPatch3:
mov eax,ds:dword ptr[_edge_tail_u_shift20]
xor ecx,ecx
mov edx,ds:dword ptr[st_last_u+esi]
sub eax,edx
jle Lgs_resetspanstate
mov ds:dword ptr[espan_t_u+ebp],edx
mov ds:dword ptr[espan_t_count+ebp],eax
mov eax,ds:dword ptr[_current_iv]
mov ds:dword ptr[espan_t_v+ebp],eax
mov eax,ds:dword ptr[st_spans+esi]
mov ds:dword ptr[espan_t_pnext+ebp],eax
mov ds:dword ptr[st_spans+esi],ebp
add ebp,offset espan_t_size
; reset spanstate for all surfaces in the surface stack
Lgs_resetspanstate:
mov ds:dword ptr[st_spanstate+esi],ecx
mov esi,ds:dword ptr[st_next+esi]
cmp esi,012345678h ; &surfaces[1]
LPatch4:
jnz Lgs_resetspanstate
; store the final span_p
mov ds:dword ptr[_span_p],ebp
pop ebx ; restore register variables
pop esi
pop edi
pop ebp ; restore the caller's stack frame
ret
; ---------------------------------------------------------------
; 1/z sorting for bmodels in the same leaf
; ---------------------------------------------------------------
align 4
Lxl_done:
inc edx
mov ds:dword ptr[st_spanstate+edi],edx
jmp Lgs_nextedge
align 4
Lzcheck_for_newtop:
mov eax,ds:dword ptr[et_u+ebx]
sub eax,0FFFFFh
mov ds:dword ptr[Ltemp],eax
fild ds:dword ptr[Ltemp]
fmul ds:dword ptr[float_1_div_0100000h] ; fu = (float)(edge->u - 0xFFFFF) *
; (1.0 / 0x100000);
fld st(0) ; fu | fu
fmul ds:dword ptr[st_d_zistepu+edi] ; fu*surf->d_zistepu | fu
fld ds:dword ptr[_fv] ; fv | fu*surf->d_zistepu | fu
fmul ds:dword ptr[st_d_zistepv+edi] ; fv*surf->d_zistepv | fu*surf->d_zistepu | fu
fxch st(1) ; fu*surf->d_zistepu | fv*surf->d_zistepv | fu
fadd ds:dword ptr[st_d_ziorigin+edi] ; fu*surf->d_zistepu + surf->d_ziorigin |
; fv*surf->d_zistepv | fu
fld ds:dword ptr[st_d_zistepu+esi] ; surf2->d_zistepu |
; fu*surf->d_zistepu + surf->d_ziorigin |
; fv*surf->d_zistepv | fu
fmul st(0),st(3) ; fu*surf2->d_zistepu |
; fu*surf->d_zistepu + surf->d_ziorigin |
; fv*surf->d_zistepv | fu
fxch st(1) ; fu*surf->d_zistepu + surf->d_ziorigin |
; fu*surf2->d_zistepu |
; fv*surf->d_zistepv | fu
faddp st(2),st(0) ; fu*surf2->d_zistepu | newzi | fu
fld ds:dword ptr[_fv] ; fv | fu*surf2->d_zistepu | newzi | fu
fmul ds:dword ptr[st_d_zistepv+esi] ; fv*surf2->d_zistepv |
; fu*surf2->d_zistepu | newzi | fu
fld st(2) ; newzi | fv*surf2->d_zistepv |
; fu*surf2->d_zistepu | newzi | fu
fmul ds:dword ptr[float_point_999] ; newzibottom | fv*surf2->d_zistepv |
; fu*surf2->d_zistepu | newzi | fu
fxch st(2) ; fu*surf2->d_zistepu | fv*surf2->d_zistepv |
; newzibottom | newzi | fu
fadd ds:dword ptr[st_d_ziorigin+esi] ; fu*surf2->d_zistepu + surf2->d_ziorigin |
; fv*surf2->d_zistepv | newzibottom | newzi |
; fu
faddp st(1),st(0) ; testzi | newzibottom | newzi | fu
fxch st(1) ; newzibottom | testzi | newzi | fu
; if (newzibottom >= testzi)
; goto newtop;
fcomp st(1) ; testzi | newzi | fu
fxch st(1) ; newzi | testzi | fu
fmul ds:dword ptr[float_1_point_001] ; newzitop | testzi | fu
fxch st(1) ; testzi | newzitop | fu
fnstsw ax
test ah,001h
jz Lnewtop_fpop3
; if (newzitop >= testzi)
; {
fcomp st(1) ; newzitop | fu
fnstsw ax
test ah,045h
jz Lsortloop_fpop2
; if (surf->d_zistepu >= surf2->d_zistepu)
; goto newtop;
fld ds:dword ptr[st_d_zistepu+edi] ; surf->d_zistepu | newzitop | fu
fcomp ds:dword ptr[st_d_zistepu+esi] ; newzitop | fu
fnstsw ax
test ah,001h
jz Lnewtop_fpop2
Lsortloop_fpop2:
fstp st(0) ; clear the FP stack
fstp st(0)
mov eax,ds:dword ptr[st_key+edi]
jmp Lsortloop
public _R_EdgeCodeEnd
_R_EdgeCodeEnd:
;----------------------------------------------------------------------
; Surface array address code patching routine
;----------------------------------------------------------------------
align 4
public _R_SurfacePatch
_R_SurfacePatch:
mov eax,ds:dword ptr[_surfaces]
add eax,offset st_size
mov ds:dword ptr[LPatch4-4],eax
add eax,offset st_next
mov ds:dword ptr[LPatch0-4],eax
mov ds:dword ptr[LPatch2-4],eax
mov ds:dword ptr[LPatch3-4],eax
ret
_TEXT ENDS
endif ;id386
END

617
ref_soft/r_image.c Normal file
View File

@ -0,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));
}
}

442
ref_soft/r_light.c Normal file
View File

@ -0,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;
}
}

849
ref_soft/r_local.h Normal file
View File

@ -0,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 );

1422
ref_soft/r_main.c Normal file

File diff suppressed because it is too large Load Diff

670
ref_soft/r_misc.c Normal file
View File

@ -0,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);
}

1241
ref_soft/r_model.c Normal file

File diff suppressed because it is too large Load Diff

256
ref_soft/r_model.h Normal file
View File

@ -0,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__

638
ref_soft/r_part.c Normal file
View File

@ -0,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
}

1244
ref_soft/r_poly.c Normal file

File diff suppressed because it is too large Load Diff