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