Added bzip2 lib and Quake (thanks to Lubomyr)

This commit is contained in:
pelya
2011-02-14 12:05:30 +00:00
parent 892c4813b9
commit 1e468ea75d
152 changed files with 88466 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
# The application settings for Android libSDL port
AppSettingVersion=16
LibSdlVersion=1.2
AppName="Quake r2tec"
AppFullName=quake.r2tec.sdl
ScreenOrientation=h
InhibitSuspend=y
AppDataDownloadUrl="Data size is 1 Mb|quake-data.zip"
SdlVideoResize=y
SdlVideoResizeKeepAspect=n
NeedDepthBuffer=n
AppUsesMouse=y
AppNeedsTwoButtonMouse=n
AppNeedsArrowKeys=y
AppNeedsTextInput=y
AppUsesJoystick=n
AppHandlesJoystickSensitivity=y
AppUsesMultitouch=n
NonBlockingSwapBuffers=n
RedefinedKeys="LCTRL LCTRL INSERT LCTRL SPACE ESCAPE 7"
AppTouchscreenKeyboardKeysAmount=4
AppTouchscreenKeyboardKeysAmountAutoFire=0
RedefinedKeysScreenKb="LCTRL SLASH SPACE INSERT"
MultiABI=n
AppVersionCode=2010090601
AppVersionName="2010.09.06.01"
CompiledLibraries="jpeg png sdl_ttf sdl_image sdl_mixer"
CustomBuildScript=n
AppCflags='-D_inline=inline'
AppLdflags=''
AppSubdirsBuild=''
AppUseCrystaXToolchain=y
AppCmdline='-winsize 480 320'
ReadmeText='^You may press "Home" now - the data will be downloaded in background'

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -0,0 +1,133 @@
#
# DINGUX SDK for Cygwin / Version: 0.1
# DINGUX Makefile by Rikku2000
#
#
#========================================(Config)
#
# Software Name
PROGRAM = quake_r2-tec.dge
# Phat
DINGUXDIR := /dingux
DINGUXBIN := $(DINGUXDIR)/bin
DINGUXLIB := $(DINGUXDIR)/mipsel-linux-uclibc/lib
DINGUXINC := $(DINGUXDIR)/mipsel-linux-uclibc/include
# Compiler Name
ARCH := mipsel-linux-uclibc-
# Compiler
CC := ${DINGUXBIN}/$(ARCH)gcc
CXX := ${DINGUXBIN}/$(ARCH)g++
STRIP := ${DINGUXBIN}/$(ARCH)strip
# Linker
LDFLAGS = $(shell $(DINGUXBIN)/sdl-config --libs) -lSDL -lSDL_gfx -lSDL_ttf -lSDL_image -lSDL_mixer -ljpeg -lpng12 -lz -lm
CFLAGS = $(shell $(DINGUXBIN)/sdl-config --cflags) -Wall -pipe -c -O2 -msoft-float -ffast-math -funroll-loops -falign-loops=2 -falign-jumps=2 -falign-functions=2 -fno-strict-aliasing
CXXFLAGS = $(shell $(DINGUXBIN)/sdl-config --cflags)
# Include
INCLUDES := -I${DINGUXINC} -I${DINGUXINC}/SDL
# Libs
LIBS += $(shell $(DINGUXBIN)/sdl-config --libs)
#
#========================================(Files)
#
CFILES = source/cd_null.c \
source/cpu.c \
source/vid_sdl.c \
source/snd_sdl.c \
source/sys_sdl.c \
source/chase.c \
source/cl_demo.c \
source/cl_input.c \
source/cl_main.c \
source/cl_parse.c \
source/cl_tent.c \
source/cmd.c \
source/common.c \
source/console.c \
source/crc.c \
source/cvar.c \
source/d_edge.c \
source/d_fill.c \
source/d_init.c \
source/d_modech.c \
source/d_part.c \
source/d_polyse.c \
source/d_scan.c \
source/d_sky.c \
source/d_sprite.c \
source/d_surf.c \
source/d_vars.c \
source/d_zpoint.c \
source/draw.c \
source/FixedPointMath.c \
source/host.c \
source/host_cmd.c \
source/keys.c \
source/mathlib.c \
source/menu.c \
source/model.c \
source/net_dgrm.c \
source/net_loop.c \
source/net_main.c \
source/net_vcr.c \
source/net_udp.c \
source/net_bsd.c \
source/nonintel.c \
source/pr_cmds.c \
source/pr_edict.c \
source/pr_exec.c \
source/r_aclip.c \
source/r_alias.c \
source/r_bsp.c \
source/r_draw.c \
source/r_edge.c \
source/r_efrag.c \
source/r_light.c \
source/r_main.c \
source/r_misc.c \
source/r_part.c \
source/r_sky.c \
source/r_sprite.c \
source/r_surf.c \
source/r_vars.c \
source/sbar.c \
source/screen.c \
source/snd_dma.c \
source/snd_mix.c \
source/slist.c \
source/sv_main.c \
source/sv_move.c \
source/sv_phys.c \
source/sv_user.c \
source/snd_mem.c \
source/view.c \
source/wad.c \
source/world.c \
source/zone.c
#
#========================================(Compile)
#
OFILES = $(SFILES:.S=.o) $(CFILES:.c=.o)
$(PROGRAM): $(OFILES)
$(CXX) $(OFILES) $(LDFLAGS) -o $@
$(STRIP) $(PROGRAM)
all: $(PROGRAM)
%.o: %.c
$(CC) $(ALL_INCLUDES) $(CFLAGS) -c $< -o $@
clean:
-rm -f $(OFILES) $(MAPFILE) $(PROGRAM)

View File

@@ -0,0 +1,89 @@
diff -ru orig/source/cpu.c source/cpu.c
--- orig/source/cpu.c 2010-08-15 11:52:04.000000000 -0400
+++ source/cpu.c 2011-02-08 13:20:14.000000000 -0500
@@ -123,7 +123,7 @@
munmap((void *)jz_cpmregl, 0x80);
munmap((void *)jz_emcregl, 0x90);
close(jz_dev);
- fcloseall();
+// fcloseall();
sync();
}
diff -ru orig/source/menu.c source/menu.c
--- orig/source/menu.c 2010-09-07 06:17:42.000000000 -0400
+++ source/menu.c 2011-02-08 08:47:59.000000000 -0500
@@ -464,7 +464,7 @@
// char name[MAX_OSPATH];
FILE *f;
int version;
- ulong dummy,fsize;
+ unsigned long dummy,fsize;
char name[45];
char *line;
Only in orig/source: snd_linux.c
Only in orig/source: sound.c
diff -ru orig/source/sys_sdl.c source/sys_sdl.c
--- orig/source/sys_sdl.c 2010-09-03 07:05:16.000000000 -0400
+++ source/sys_sdl.c 2011-02-08 13:36:34.000000000 -0500
@@ -11,10 +11,11 @@
#include <string.h>
#include <ctype.h>
#include <errno.h>
+#include <SDL.h>
#ifndef __WIN32__
#include <sys/ipc.h>
-#include <sys/shm.h>
+//#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/mman.h>
diff -ru orig/source/vid_sdl.c source/vid_sdl.c
--- orig/source/vid_sdl.c 2010-09-06 15:26:04.000000000 -0400
+++ source/vid_sdl.c 2011-02-09 07:21:04.000000000 -0500
@@ -1,10 +1,10 @@
// vid_sdl.h -- sdl video driver
-
-#include <sys/stat.h>
-#include <sys/dir.h>
-#include <unistd.h>
-#include <SDL.h>
-#include <SDL_ttf.h>
+
+#include <sys/stat.h>
+//#include <sys/dir.h>
+#include <unistd.h>
+#include <SDL.h>
+#include <SDL_ttf.h>
#include <SDL_image.h>
#include "quakedef.h"
#include "d_local.h"
@@ -81,13 +81,13 @@
int handle = -1;
TTF_Init();
- gTTFFont = TTF_OpenFont("q_sys/gfx/dpquake.ttf", 12);
+ gTTFFont = TTF_OpenFont("q_sys/gfx/dpquake.ttf", 16);
// Load the SDL library
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) != 0)
Sys_Error("VID: Couldn't load SDL: %s", SDL_GetError());
- if (!(hwscreen = SDL_SetVideoMode(320, 240, 32, SDL_SWSURFACE|SDL_ASYNCBLIT|SDL_ANYFORMAT|SDL_HWPALETTE)))
+ if (!(hwscreen = SDL_SetVideoMode(480, 320, 32, SDL_SWSURFACE|SDL_ASYNCBLIT|SDL_ANYFORMAT|SDL_HWPALETTE)))
Sys_Error("VID: Couldn't set video mode: %s\n", SDL_GetError());
// Background
@@ -208,8 +208,8 @@
case SDLK_LCTRL:
if(option == 2) {
// Set up display mode (width and height)
- vid.width = 320;
- vid.height = 240;
+ vid.width = 480;
+ vid.height = 320;
if ((pnum=COM_CheckParm("-winsize"))) {
if (pnum >= com_argc-2)

View File

@@ -0,0 +1,344 @@
//Fixed Point Math Routines
//Copyright 2/2/01 Dan East
#include "quakedef.h"
#include "FixedPointMath.h"
#include <math.h>
#if defined(DEBUG)&&defined(_X86_)
#include "windows.h"
#define FPM_VALIDATE
#endif
fixedpoint_t fpm_FromFloat(double f) {
# if defined(DEBUG)&&defined(FPM_VALIDATE)
fixedpoint_t fxp=(fixedpoint_t) (f*65536.0);
if (f) ASSERT(fxp);
# endif
return (fixedpoint_t) (f*65536.0);
}
float fpm_ToFloat(fixedpoint_t fxp) {
return (float)(fxp/65536.0);
}
fixedpoint_t fpm_FromLong(long l) {
# if defined(DEBUG)&&defined(FPM_VALIDATE)
if (l>0) ASSERT((l<<16)>0);
else if (l<0) ASSERT((l<<16)<0);
# endif
return l<<16;
}
long fpm_ToLong(fixedpoint_t fxp) {
if (fxp<0)
return -((long)((fxp^0xffffffff)>>16)+1);
else
return (fxp>>16)&0x0000ffff;
}
fixedpoint_t fpm_Add(fixedpoint_t fxp1, fixedpoint_t fxp2) {
# if defined(DEBUG)&&defined(FPM_VALIDATE)
if (fxp1>0&&fxp2>0) ASSERT((fxp1+fxp2)>0);
if (fxp1<0&&fxp2<0) ASSERT((fxp1+fxp2)<0);
# endif
return fxp1+fxp2;
}
fixedpoint_t fpm_Add3(fixedpoint_t fxp1, fixedpoint_t fxp2, fixedpoint_t fxp3) {
return fxp1+fxp2+fxp3;
}
/*
fixedpoint_t fpm_Inc(fixedpoint_t fxp) {
return fxp=fxp+FPM_FROMLONG(1);
}
*/
fixedpoint_t fpm_Sub(fixedpoint_t fxp1, fixedpoint_t fxp2) {
return fxp1-fxp2;
}
/*
fixedpoint_t fpm_Dec(fixedpoint_t &fxp) {
return fxp=fxp-FPM_FROMLONG(1);
}
*/
fixedpoint_t fpm_Mul(fixedpoint_t fxp1, fixedpoint_t fxp2) {
__int64 tmp=fxp1;
# if defined(DEBUG)&&defined(FPM_VALIDATE)
fixedpoint_t fxp;
tmp*=fxp2;
fxp=(fixedpoint_t)(tmp>>16);
if (fxp1&&fxp2) {
/*
//Dan: Temp hack
if (!fxp) {
if ((fxp1>0&&fxp2>0)||(fxp1<0&&fxp2<0)) fxp=1;
else fxp=-1;
return fxp;
}
*/
ASSERT(fxp);
if ((fxp1>0&&fxp2>0)||(fxp1<0&&fxp2<0)) ASSERT(fxp>0);
else ASSERT(fxp<0);
}
return fxp;
# endif
tmp*=fxp2;
return (fixedpoint_t)(tmp>>16);
}
fixedpoint_t fpm_Div(fixedpoint_t fxp1, fixedpoint_t fxp2) {
__int64 tmp=fxp1;
# if defined(DEBUG)&&defined(FPM_VALIDATE)
fixedpoint_t fxp;
ASSERT(fxp2);
tmp<<=16;
fxp=(fixedpoint_t)(tmp/fxp2);
if (fxp1) {
/*
//Dan: Temp hack
if (!fxp) {
if ((fxp1>0&&fxp2>0)||(fxp1<0&&fxp2<0)) fxp=1;
else fxp=-1;
return fxp;
}
*/
ASSERT(fxp);
if ((fxp1>0&&fxp2>0)||(fxp1<0&&fxp2<0)) ASSERT(fxp>0);
else ASSERT(fxp<0);
}
return fxp;
#endif
tmp<<=16;
return (fixedpoint_t)(tmp/fxp2);
}
fixedpoint_t fpm_DivInt(fixedpoint_t fxp1, long l) {
return fxp1/l;
}
fixedpoint_t fpm_Abs(fixedpoint_t fxp) {
return abs(fxp);
}
//TODO: could be more efficient
fixedpoint_t fpm_Ceil(fixedpoint_t fxp) {
if (fxp&0x0000ffff) {
if (fxp<=0) return -(fixedpoint_t)((-fxp)&0xffff0000);
return (fxp&0xffff0000)+FPM_FROMLONGC(1);
}
return fxp;
}
//TODO: could be more efficient
fixedpoint_t fpm_Floor(fixedpoint_t fxp) {
if (fxp&0x0000ffff) {
if (fxp<0) return -(long)(((-fxp)&0xffff0000)+FPM_FROMLONGC(1));
return fxp&0xffff0000;
}
return fxp;
}
//TODO: Implement sqrt mathematically instead of converting to float and back
fixedpoint_t fpm_Sqrt(fixedpoint_t fxp) {
return fpm_FromFloat(sqrt(fpm_ToFloat(fxp)));
}
fixedpoint_t fpm_Sqr(fixedpoint_t fxp) {
return fpm_Mul(fxp,fxp);
}
fixedpoint_t fpm_Inv(fixedpoint_t fxp) {
# if defined(DEBUG)&&defined(FPM_VALIDATE)
ASSERT(fxp);
# endif
return fpm_Div(FPM_FROMLONGC(1),fxp);
}
//TODO: Calc trig functions (or lookup) instead of converting to float and back
//These take radians
fixedpoint_t fpm_Sin(fixedpoint_t fxp) {
return fpm_FromFloat(sin(fpm_ToFloat(fxp)));
}
fixedpoint_t fpm_Cos(fixedpoint_t fxp) {
return fpm_FromFloat(cos(fpm_ToFloat(fxp)));
}
fixedpoint_t fpm_Tan(fixedpoint_t fxp) {
return fpm_FromFloat(tan(fpm_ToFloat(fxp)));
}
fixedpoint_t fpm_ATan(fixedpoint_t fxp) {
return fpm_FromFloat(atan(fpm_ToFloat(fxp)));
}
//These take degrees
fixedpoint_t fpm_SinDeg(fixedpoint_t fxp) {
return fpm_Sin(fpm_DivInt(fpm_Mul(fxp, FPM_PI), 180));
}
fixedpoint_t fpm_CosDeg(fixedpoint_t fxp) {
return fpm_Cos(fpm_DivInt(fpm_Mul(fxp, FPM_PI), 180));
}
fixedpoint_t fpm_TanDeg(fixedpoint_t fxp) {
return fpm_Tan(fpm_DivInt(fpm_Mul(fxp, FPM_PI), 180));
}
fixedpoint_t fpm_ATanDeg(fixedpoint_t fxp) {
return fpm_ATan(fpm_DivInt(fpm_Mul(fxp, FPM_PI), 180));
}
/*********************************************/
/* 8.24 routines: */
/*********************************************/
fixedpoint8_24_t fpm_FromFloat8_24(double f) {
# if defined(DEBUG)&&defined(FPM_VALIDATE)
if (f) ASSERT((fixedpoint_t) (f*16777216.0));
# endif
return (fixedpoint8_24_t) (f*16777216.0);
}
float fpm_ToFloat8_24(fixedpoint8_24_t fxp) {
return (float)(fxp/16777216.0);
}
fixedpoint8_24_t fpm_FromLong8_24(long l) {
# if defined(DEBUG)&&defined(FPM_VALIDATE)
if (l>0) ASSERT((l<<24)>0);
else if (l<0) ASSERT((l<<24)<0);
# endif
return l<<24;
}
long fpm_ToLong8_24(fixedpoint8_24_t fxp) {
if (fxp<0)
return -((long)((fxp^0xffffffff)>>24)+1);
else
return (fxp>>24)&0x000000ff;
}
fixedpoint8_24_t fpm_FromFixedPoint(fixedpoint_t fxp) {
return fxp<<8;
}
fixedpoint_t fpm_ToFixedPoint(fixedpoint8_24_t fxp) {
if (fxp<0)
return -((long)((fxp^0xffffffff)>>8)+1);
else
return (fxp>>8)&0x00ffffff;
}
fixedpoint8_24_t fpm_Add8_24(fixedpoint8_24_t fxp1, fixedpoint8_24_t fxp2) {
return fxp1+fxp2;
}
fixedpoint8_24_t fpm_Add38_24(fixedpoint8_24_t fxp1, fixedpoint8_24_t fxp2, fixedpoint8_24_t fxp3) {
return fxp1+fxp2+fxp3;
}
/*
fixedpoint_t fpm_Inc(fixedpoint_t fxp) {
return fxp=fxp+FPM_FROMLONG(1);
}
*/
fixedpoint8_24_t fpm_Sub8_24(fixedpoint8_24_t fxp1, fixedpoint8_24_t fxp2) {
return fxp1-fxp2;
}
/*
fixedpoint_t fpm_Dec(fixedpoint_t &fxp) {
return fxp=fxp-FPM_FROMLONG(1);
}
*/
fixedpoint8_24_t fpm_Mul8_24(fixedpoint8_24_t fxp1, fixedpoint8_24_t fxp2) {
__int64 tmp=fxp1;
# if defined(DEBUG)&&defined(FPM_VALIDATE)
fixedpoint8_24_t fxp;
tmp*=fxp2;
fxp=(fixedpoint8_24_t)(tmp>>24);
if (fxp1&&fxp2) {
ASSERT(fxp);
if ((fxp1>0&&fxp2>0)||(fxp1<0&&fxp2<0)) ASSERT(fxp>0);
else ASSERT(fxp<0);
}
return fxp;
# endif
tmp*=fxp2;
return (fixedpoint_t)(tmp>>24);
}
fixedpoint_t fpm_MulMixed8_24(fixedpoint8_24_t fxp1, fixedpoint_t fxp2) {
__int64 tmp=fxp1;
tmp*=fxp2;
return (fixedpoint_t)(tmp>>24);
}
fixedpoint8_24_t fpm_Div8_24(fixedpoint8_24_t fxp1, fixedpoint8_24_t fxp2) {
__int64 tmp=fxp1;
# if defined(DEBUG)&&defined(FPM_VALIDATE)
//The purpose of this is to cause an exception in Windows CE
//that will be handled right here by the debugger. Otherwise a
//divide by zero will be thrown which cannot be used to find
//where the exception actually occured with the debugger.
ASSERT(fxp2);
if (!fxp2)
(*(int *)fxp2)=0;
# endif
tmp<<=24;
return (fixedpoint8_24_t)(tmp/fxp2);
}
fixedpoint8_24_t fpm_DivInt8_24(fixedpoint8_24_t fxp1, long l) {
return fxp1/l;
}
fixedpoint8_24_t fpm_DivInt64_8_24(fixedpoint8_24_t fxp1, __int64 l) {
return (fixedpoint8_24_t) (fxp1/l);
}
fixedpoint8_24_t fpm_Abs8_24(fixedpoint8_24_t fxp) {
return abs(fxp);
}
//TODO: could be more efficient
fixedpoint8_24_t fpm_Ceil8_24(fixedpoint8_24_t fxp) {
if (fxp&0x00ffffff) {
if (fxp<=0) return (fxp&0xff000000);
return (fxp&0xff000000)+FPM_FROMLONGC8_24(1);
}
return fxp;
}
//TODO: could be more efficient
fixedpoint8_24_t fpm_Floor8_24(fixedpoint8_24_t fxp) {
if (fxp&0x00ffffff) {
if (fxp<0) return -(long)((fxp&0xff000000)+FPM_FROMLONG8_24(1));
return fxp&0xff000000;
}
return fxp;
}
//TODO: Implement sqrt mathematically instead of converting to float and back
fixedpoint8_24_t fpm_Sqrt8_24(fixedpoint8_24_t fxp) {
return fpm_FromFloat8_24(sqrt(fpm_ToFloat8_24(fxp)));
}
fixedpoint8_24_t fpm_Sqr8_24(fixedpoint8_24_t fxp) {
return fpm_Mul8_24(fxp,fxp);
}
fixedpoint8_24_t fpm_Inv8_24(fixedpoint8_24_t fxp) {
# if defined(DEBUG)&&defined(FPM_VALIDATE)
ASSERT(fxp);
# endif
return fpm_Div8_24(FPM_FROMLONGC8_24(1), fxp);
}

View File

@@ -0,0 +1,247 @@
#ifndef _FIXEDPOINTMATH_H
#define _FIXEDPOINTMATH_H
//Fixed point math routines (16.16)
//Dan East
//01-24-2001
#define FPM_PI 205887L
#define FPM_2PI 411775L
#define FPM_E 178144L
#define FPM_ROOT2 74804L
#define FPM_ROOT3 113512L
#define FPM_GOLDEN 106039L
#define FPM_MAX 0x7fff0000
typedef long fixedpoint_t;
typedef long fixedpoint8_24_t;
fixedpoint_t fpm_FromFloat(double f);
float fpm_ToFloat(fixedpoint_t fxp);
fixedpoint_t fpm_FromLong(long l);
long fpm_ToLong(fixedpoint_t fxp);
fixedpoint_t fpm_Add(fixedpoint_t fxp1, fixedpoint_t fxp2);
fixedpoint_t fpm_Add3(fixedpoint_t fxp1, fixedpoint_t fxp2, fixedpoint_t fxp3);
fixedpoint_t fpm_Sub(fixedpoint_t fxp1, fixedpoint_t fxp2);
fixedpoint_t fpm_Mul(fixedpoint_t fxp1, fixedpoint_t fxp2);
fixedpoint_t fpm_Div(fixedpoint_t fxp1, fixedpoint_t fxp2);
fixedpoint_t fpm_DivInt(fixedpoint_t fxp1, long l);
fixedpoint_t fpm_Abs(fixedpoint_t fxp);
fixedpoint_t fpm_Ceil(fixedpoint_t fxp);
fixedpoint_t fpm_Floor(fixedpoint_t fxp);
fixedpoint_t fpm_Sqrt(fixedpoint_t fxp);
fixedpoint_t fpm_Sqr(fixedpoint_t fxp);
fixedpoint_t fpm_Inv(fixedpoint_t fxp);
fixedpoint_t fpm_Sin(fixedpoint_t fxp);
fixedpoint_t fpm_Cos(fixedpoint_t fxp);
fixedpoint_t fpm_Tan(fixedpoint_t fxp);
fixedpoint_t fpm_ATan(fixedpoint_t fxp);
//These take degrees
fixedpoint_t fpm_SinDeg(fixedpoint_t fxp);
fixedpoint_t fpm_CosDeg(fixedpoint_t fxp);
fixedpoint_t fpm_TanDeg(fixedpoint_t fxp);
fixedpoint_t fpm_ATanDeg(fixedpoint_t fxp);
#define FPM_FROMFLOAT(f) fpm_FromFloat(f)
#define FPM_FROMFLOATC(f) ((long)((f) * 65536.0 )) //Constant version
#define FPM_TOFLOAT(fxp) fpm_ToFloat(fxp)
#define FPM_FROMLONG(l) fpm_FromLong(l)
#define FPM_FROMLONGC(l) ((l)<<16) //Constant version
#define FPM_TOLONG(l) fpm_ToLong(l)
#define FPM_ADD(f1, f2) fpm_Add(f1, f2)
#define FPM_ADD3(f1, f2, f3) fpm_Add3(f1, f2, f3)
#define FPM_INC(f1) ((f1)=FPM_ADD(f1, FPM_FROMLONG(1)))
#define FPM_SUB(f1, f2) fpm_Sub(f1, f2)
#define FPM_DEC(f1) ((f1)=FPM_SUB(f1, FPM_FROMLONG(1)))
#define FPM_MUL(f1, f2) fpm_Mul(f1, f2)
#define FPM_DIV(n, d) fpm_Div(n, d)
#define FPM_DIVINT(n, d) fpm_DivInt(n, d)
#define FPM_ABS(fxp) fpm_Abs(fxp)
#define FPM_CEIL(fxp) fpm_Ceil(fxp)
#define FPM_FLOOR(fxp) fpm_Floor(fxp)
#define FPM_SQRT(fxp) fpm_Sqrt(fxp)
#define FPM_SQR(fxp) fpm_Sqr(fxp)
#define FPM_INV(fxp) fpm_Inv(fxp)
//These take radians
#define FPM_SIN(r) fpm_Sin(r)
#define FPM_COS(r) fpm_Cos(r)
#define FPM_TAN(r) fpm_Tan(r)
#define FPM_ATAN(r) fpm_ATan(r)
//These take degrees
#define FPM_SIN_DEG(d) fpm_SinDeg(d)
#define FPM_COS_DEG(d) fpm_CosDeg(d)
#define FPM_TAN_DEG(d) fpm_TanDeg(d)
#define FPM_ATAN_DEG(d) fpm_ATanDeg(d)
fixedpoint8_24_t fpm_FromFloat(double f);
float fpm_ToFloat8_24(fixedpoint8_24_t fxp);
fixedpoint8_24_t fpm_FromLong8_24(long l);
long fpm_ToLong8_24(fixedpoint8_24_t fxp);
fixedpoint8_24_t fpm_FromFixedPoint(fixedpoint_t fxp);
fixedpoint_t fpm_ToFixedPoint(fixedpoint8_24_t fxp);
fixedpoint8_24_t fpm_Add8_24(fixedpoint8_24_t fxp1, fixedpoint8_24_t fxp2);
fixedpoint8_24_t fpm_Add38_24(fixedpoint8_24_t fxp1, fixedpoint8_24_t fxp2, fixedpoint8_24_t fxp3);
fixedpoint8_24_t fpm_Sub8_24(fixedpoint8_24_t fxp1, fixedpoint8_24_t fxp2);
fixedpoint8_24_t fpm_Mul8_24(fixedpoint8_24_t fxp1, fixedpoint8_24_t fxp2);
fixedpoint_t fpm_MulMixed8_24(fixedpoint8_24_t fxp1, fixedpoint_t fxp2);
fixedpoint8_24_t fpm_Div8_24(fixedpoint8_24_t fxp1, fixedpoint8_24_t fxp2);
fixedpoint8_24_t fpm_DivInt8_24(fixedpoint8_24_t fxp1, long l);
fixedpoint8_24_t fpm_DivInt64_8_24(fixedpoint8_24_t fxp1, __int64 l);
fixedpoint8_24_t fpm_Abs8_24(fixedpoint8_24_t fxp);
fixedpoint8_24_t fpm_Ceil8_24(fixedpoint8_24_t fxp);
fixedpoint8_24_t fpm_Floor8_24(fixedpoint8_24_t fxp);
fixedpoint8_24_t fpm_Sqrt8_24(fixedpoint8_24_t fxp);
fixedpoint8_24_t fpm_Sqr8_24(fixedpoint8_24_t fxp);
fixedpoint8_24_t fpm_Inv8_24(fixedpoint8_24_t fxp);
#define FPM_FROMFLOAT8_24(f) fpm_FromFloat8_24(f)
#define FPM_FROMFLOATC8_24(f) ((long)((f) * 16777216.0 )) //Constant version
#define FPM_TOFLOAT8_24(fxp) fpm_ToFloat8_24(fxp)
#define FPM_FROMLONG8_24(l) fpm_FromLong8_24(l)
#define FPM_FROMLONGC8_24(l) ((l)<<24) //Constant version
#define FPM_TOLONG8_24(l) fpm_ToLong8_24(l)
/*
extern __int64 FPM_TMPVAR_INT64;
#define FPM_FROMFLOAT(f) ((long)((f) * 65536.0 )) //+0.5
#define FPM_TOFLOAT(fxp) (((float)(fxp)) / 65536.0)
#define FPM_FROMLONG(l) ((l)<<16)
#define FPM_TOLONG(l) ((l)<0?(-(long)((l)^0xffffffff)>>16):(((l)>>16)&0x0000ffff))
#define FPM_ADD(f1, f2) ((f1)+(f2))
#define FPM_ADD3(f1, f2, f3) ((f1)+(f2)+(f3))
#define FPM_INC(f1) ((f1)=FPM_ADD(f1, FPM_FROMLONG(1)))
#define FPM_SUB(f1, f2) ((f1)-(f2))
#define FPM_DEC(f1) ((f1)=FPM_SUB(f1, FPM_FROMLONG(1)))
#define FPM_MUL(f1, f2) (((f1)>>8)*((f2)>>8))
//#define FPM_MUL(f1, f2) ((fixedpoint_t)((FPM_TMPVAR_INT64=(f1))*(f2))>>16)
//#define FPM_MUL(f1, f2) (((f1)*(f2))>>16)
//TODO: This needs to be done without copying to another var
#define FPM_DIV(n, d) ((fixedpoint_t)(((FPM_TMPVAR_INT64=(n))<<16)/d))
#define FPM_DIVINT(n, d) ((fixedpoint_t)((n)/(d)))
//#define FPM_DIV(n, d) ((long)(((__int64)n)<<16)/(d))
#define FPM_ABS(fxp) (abs(fxp))
//TODO: could be more effecient
#define FPM_CEIL(fxp) ((fxp)&0x0000ffff?((fxp)<=0?((fxp)&0xffff0000):(((fxp)&0xffff0000)+FPM_FROMLONG(1))):(fxp))
#define FPM_FLOOR(fxp) ((fxp)&0x0000ffff?((fxp)<0?(((fxp)&0xffff0000)-FPM_FROMLONG(1)):((fxp)&0xffff0000)):(fxp))
//TODO: Implement sqrt mathematically instead of converting to float and back
#define FPM_SQRT(fxp) (FPM_FROMFLOAT(sqrt(FPM_TOFLOAT(fxp))))
#define FPM_SQR(fxp) (FPM_MUL(fxp,fxp)>>16)
#define FPM_INV(fxp) (FPM_DIV(0x10000, fxp))
//TODO: Calc trig functions (or lookup) instead of converting to float and back
//These take radians
#define FPM_SIN(r) (FPM_FROMFLOAT(sin(FPM_TOFLOAT(r))))
#define FPM_COS(r) (FPM_FROMFLOAT(cos(FPM_TOFLOAT(r))))
#define FPM_TAN(r) (FPM_FROMFLOAT(tan(FPM_TOFLOAT(r))))
#define FPM_ATAN(r) (FPM_FROMFLOAT(atan(FPM_TOFLOAT(r))))
//These take degrees
#define FPM_SIN_DEG(d) (FPM_SIN(FPM_DIV(FPM_MUL(d,FPM_PI),0xB40000))) //0xB40000 = 180.0
#define FPM_COS_DEG(d) (FPM_COS(FPM_DIV(FPM_MUL(d,FPM_PI),0xB40000)))
#define FPM_TAN_DEG(d) (FPM_TAN(FPM_DIV(FPM_MUL(d,FPM_PI),0xB40000)))
#define FPM_ATAN_DEG(d) (FPM_ATAN(FPM_DIV(FPM_MUL(d,FPM_PI),0xB40000)))
*/
/*
#define FPM_PI 3.14
#define FPM_2PI (3.14*2)
#define FPM_E 178144L
#define FPM_ROOT2 74804L
#define FPM_ROOT3 113512L
#define FPM_GOLDEN 106039L
typedef float fixedpoint_t;
//This variable must be declared in one of the implementation files.
extern __int64 FPM_TMPVAR_INT64;
#define FPM_FROMFLOAT(f) (f)
#define FPM_TOFLOAT(fxp) (fxp)
#define FPM_FROMLONG(l) ((float)l)
#define FPM_TOLONG(fxp) ((long)fxp)
#define FPM_ADD(f1, f2) ((f1)+(f2))
#define FPM_ADD3(f1, f2, f3) ((f1)+(f2)+(f3))
#define FPM_INC(f1) ((f1)++)
#define FPM_SUB(f1, f2) ((f1)-(f2))
#define FPM_DEC(f1) ((f1)--)
#define FPM_MUL(f1, f2) ((f1)*(f2))
//#define FPM_MUL(f1, f2) ((fixedpoint_t)((FPM_TMPVAR_INT64=(f1))*(f2))>>16)
//#define FPM_MUL(f1, f2) (((f1)*(f2))>>16)
//TODO: This needs to be done without copying to another var
#define FPM_DIV(n, d) ((n)/(d))
//#define FPM_DIV(n, d) ((long)(((__int64)n)<<16)/(d))
#define FPM_ABS(fxp) (abs(fxp))
//TODO: Implement ceil mathematically instead of converting to float and back
#define FPM_CEIL(fxp) (ceil(fxp))
#define FPM_FLOOR(fxp) (floor(fxp))
//TODO: Implement sqrt mathematically instead of converting to float and back
#define FPM_SQRT(fxp) (sqrt(fxp))
#define FPM_SQR(fxp) ((fxp)*(fxp))
#define FPM_INV(fxp) (1/(fxp))
//TODO: Calc trig functions (or lookup) instead of converting to float and back
//These take radians
#define FPM_SIN(r) (sin(r))
#define FPM_COS(r) (cos(r))
#define FPM_TAN(r) (tan(r))
#define FPM_ATAN(r) (atan(r))
//These take degrees
#define FPM_SIN_DEG(d) FPM_SIN(((d)*FPM_PI)/180.0) //0xB40000 = 180.0
#define FPM_COS_DEG(d) FPM_COS(((d)*FPM_PI)/180.0)
#define FPM_TAN_DEG(d) FPM_TAN(((d)*FPM_PI)/180.0)
#define FPM_ATAN_DEG(d) FPM_ATAN(((d)*FPM_PI)/180.0)
*/
#endif //_FIXEDPOINTMATH_H

View File

@@ -0,0 +1,113 @@
//LogFloat.c
//Logs max, min and precision of a floating point value
#include <stdio.h>
#include "LogFloat.h"
struct LogFloatEntry {
char id[128];
float min, max, precision;
int counter;
};
#define MAX_LF_ENTRIES 1000
struct LogFloatEntry lf_entries[MAX_LF_ENTRIES];
int lf_total=0;
_inline struct LogFloatEntry *_lfAdd(char *id) {
//Adds a new entry.
//NULL == Array full.
if (lf_total==MAX_LF_ENTRIES) return NULL;
strcpy(lf_entries[lf_total].id, id);
lf_entries[lf_total].max=lf_entries[lf_total].min=0.0f;
lf_entries[lf_total].precision=1.0f;
lf_entries[lf_total].counter=0;
return &lf_entries[lf_total++];
}
_inline struct LogFloatEntry *_lfFind(char *id) {
//Finds an existing entry.
//NULL == No matching id
struct LogFloatEntry *cur=&lf_entries[0], *last=&lf_entries[lf_total];
while (cur<=last) {
//Change this is case insensitive matching is desired.
if (!strcmp(id, cur->id)) return cur;
cur++;
}
return NULL;
}
_inline struct LogFloatEntry *_lfGet(char *id) {
//Gets an entry. Returns an entry if it already exists, otherwise a new entry is created.
struct LogFloatEntry *cur=_lfFind(id);
if (!cur) cur=_lfAdd(id);
return cur;
}
int LogFloatInit() {
lf_total=0;
return 1;
}
void LogFloatClose() {
lf_total=0;
}
void LogFloatResults(char *fn) {
int i;
FILE *f=fopen(fn, "w+");
if (f) {
fprintf(f, "ID\tMin\tMax\tPrecision\tCount\n\n");
for (i=0; i<lf_total; i++)
fprintf(f, "%s:\t%f\t%f\t%e\t%d\n", lf_entries[i].id, lf_entries[i].min, lf_entries[i].max, lf_entries[i].precision, lf_entries[i].counter);
fprintf(f, "\nTotal items logged: %d", lf_total);
fclose(f);
}
}
float LogFloat(float f, char *id, int index, int precision) {
//Params:
// f: Float value to be logged
// id: string ID (name) of the float variable
// index: index of f in the event that f is a member of an array. Specify index < 0 for no index.
//precision: Indicates max precision truncation to be applied to the return float. If no precision
// truncating is desired, set precision < 0.
//Return value:
//if precision >=0 && <= 32, return value is f truncated to the fixed point precision "precision".
//otherwise return value == f.
struct LogFloatEntry *cur;
float tmp;
if (index>=0) {
char newId[256];
sprintf(newId, "%s[%d]", id, index);
cur=_lfGet(newId);
} else cur=_lfGet(id);
if (cur) {
cur->counter++;
if (cur->max<f) cur->max=f;
if (cur->min>f) cur->min=f;
tmp=(float)fabs(f);
if (tmp<1.0f&&f!=0.0f)
if (tmp<cur->precision) cur->precision=tmp;
} //else Error: we ran out of entry storage
if (precision>=0) {
float f2=(float)(2^precision);
tmp=f*f2;
return tmp/f2;
}
return f;
}

View File

@@ -0,0 +1,10 @@
#ifndef LOGFLOAT_H
#define LOGFLOAT_H
int LogFloatInit();
void LogFloatClose();
void LogFloatResults(char *fn);
float LogFloat(float f, char *id, int index, int precision);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,183 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//Dan: I added all the float casts because I was tired of seeing 508 warnings
//every time I compiled.
{(float)-0.525731, (float)0.000000, (float)0.850651},
{(float)-0.442863, (float)0.238856, (float)0.864188},
{(float)-0.295242, (float)0.000000, (float)0.955423},
{(float)-0.309017, (float)0.500000, (float)0.809017},
{(float)-0.162460, (float)0.262866, (float)0.951056},
{(float)0.000000, (float)0.000000, (float)1.000000},
{(float)0.000000, (float)0.850651, (float)0.525731},
{(float)-0.147621, (float)0.716567, (float)0.681718},
{(float)0.147621, (float)0.716567, (float)0.681718},
{(float)0.000000, (float)0.525731, (float)0.850651},
{(float)0.309017, (float)0.500000, (float)0.809017},
{(float)0.525731, (float)0.000000, (float)0.850651},
{(float)0.295242, (float)0.000000, (float)0.955423},
{(float)0.442863, (float)0.238856, (float)0.864188},
{(float)0.162460, (float)0.262866, (float)0.951056},
{(float)-0.681718, (float)0.147621, (float)0.716567},
{(float)-0.809017, (float)0.309017, (float)0.500000},
{(float)-0.587785, (float)0.425325, (float)0.688191},
{(float)-0.850651, (float)0.525731, (float)0.000000},
{(float)-0.864188, (float)0.442863, (float)0.238856},
{(float)-0.716567, (float)0.681718, (float)0.147621},
{(float)-0.688191, (float)0.587785, (float)0.425325},
{(float)-0.500000, (float)0.809017, (float)0.309017},
{(float)-0.238856, (float)0.864188, (float)0.442863},
{(float)-0.425325, (float)0.688191, (float)0.587785},
{(float)-0.716567, (float)0.681718, (float)-0.147621},
{(float)-0.500000, (float)0.809017, (float)-0.309017},
{(float)-0.525731, (float)0.850651, (float)0.000000},
{(float)0.000000, (float)0.850651, (float)-0.525731},
{(float)-0.238856, (float)0.864188, (float)-0.442863},
{(float)0.000000, (float)0.955423, (float)-0.295242},
{(float)-0.262866, (float)0.951056, (float)-0.162460},
{(float)0.000000, (float)1.000000, (float)0.000000},
{(float)0.000000, (float)0.955423, (float)0.295242},
{(float)-0.262866, (float)0.951056, (float)0.162460},
{(float)0.238856, (float)0.864188, (float)0.442863},
{(float)0.262866, (float)0.951056, (float)0.162460},
{(float)0.500000, (float)0.809017, (float)0.309017},
{(float)0.238856, (float)0.864188, (float)-0.442863},
{(float)0.262866, (float)0.951056, (float)-0.162460},
{(float)0.500000, (float)0.809017, (float)-0.309017},
{(float)0.850651, (float)0.525731, (float)0.000000},
{(float)0.716567, (float)0.681718, (float)0.147621},
{(float)0.716567, (float)0.681718, (float)-0.147621},
{(float)0.525731, (float)0.850651, (float)0.000000},
{(float)0.425325, (float)0.688191, (float)0.587785},
{(float)0.864188, (float)0.442863, (float)0.238856},
{(float)0.688191, (float)0.587785, (float)0.425325},
{(float)0.809017, (float)0.309017, (float)0.500000},
{(float)0.681718, (float)0.147621, (float)0.716567},
{(float)0.587785, (float)0.425325, (float)0.688191},
{(float)0.955423, (float)0.295242, (float)0.000000},
{(float)1.000000, (float)0.000000, (float)0.000000},
{(float)0.951056, (float)0.162460, (float)0.262866},
{(float)0.850651, (float)-0.525731, (float)0.000000},
{(float)0.955423, (float)-0.295242, (float)0.000000},
{(float)0.864188, (float)-0.442863, (float)0.238856},
{(float)0.951056, (float)-0.162460, (float)0.262866},
{(float)0.809017, (float)-0.309017, (float)0.500000},
{(float)0.681718, (float)-0.147621, (float)0.716567},
{(float)0.850651, (float)0.000000, (float)0.525731},
{(float)0.864188, (float)0.442863, (float)-0.238856},
{(float)0.809017, (float)0.309017, (float)-0.500000},
{(float)0.951056, (float)0.162460, (float)-0.262866},
{(float)0.525731, (float)0.000000, (float)-0.850651},
{(float)0.681718, (float)0.147621, (float)-0.716567},
{(float)0.681718, (float)-0.147621, (float)-0.716567},
{(float)0.850651, (float)0.000000, (float)-0.525731},
{(float)0.809017, (float)-0.309017, (float)-0.500000},
{(float)0.864188, (float)-0.442863, (float)-0.238856},
{(float)0.951056, (float)-0.162460, (float)-0.262866},
{(float)0.147621, (float)0.716567, (float)-0.681718},
{(float)0.309017, (float)0.500000, (float)-0.809017},
{(float)0.425325, (float)0.688191, (float)-0.587785},
{(float)0.442863, (float)0.238856, (float)-0.864188},
{(float)0.587785, (float)0.425325, (float)-0.688191},
{(float)0.688191, (float)0.587785, (float)-0.425325},
{(float)-0.147621, (float)0.716567, (float)-0.681718},
{(float)-0.309017, (float)0.500000, (float)-0.809017},
{(float)0.000000, (float)0.525731, (float)-0.850651},
{(float)-0.525731, (float)0.000000, (float)-0.850651},
{(float)-0.442863, (float)0.238856, (float)-0.864188},
{(float)-0.295242, (float)0.000000, (float)-0.955423},
{(float)-0.162460, (float)0.262866, (float)-0.951056},
{(float)0.000000, (float)0.000000, (float)-1.000000},
{(float)0.295242, (float)0.000000, (float)-0.955423},
{(float)0.162460, (float)0.262866, (float)-0.951056},
{(float)-0.442863, (float)-0.238856, (float)-0.864188},
{(float)-0.309017, (float)-0.500000, (float)-0.809017},
{(float)-0.162460, (float)-0.262866, (float)-0.951056},
{(float)0.000000, (float)-0.850651, (float)-0.525731},
{(float)-0.147621, (float)-0.716567, (float)-0.681718},
{(float)0.147621, (float)-0.716567, (float)-0.681718},
{(float)0.000000, (float)-0.525731, (float)-0.850651},
{(float)0.309017, (float)-0.500000, (float)-0.809017},
{(float)0.442863, (float)-0.238856, (float)-0.864188},
{(float)0.162460, (float)-0.262866, (float)-0.951056},
{(float)0.238856, (float)-0.864188, (float)-0.442863},
{(float)0.500000, (float)-0.809017, (float)-0.309017},
{(float)0.425325, (float)-0.688191, (float)-0.587785},
{(float)0.716567, (float)-0.681718, (float)-0.147621},
{(float)0.688191, (float)-0.587785, (float)-0.425325},
{(float)0.587785, (float)-0.425325, (float)-0.688191},
{(float)0.000000, (float)-0.955423, (float)-0.295242},
{(float)0.000000, (float)-1.000000, (float)0.000000},
{(float)0.262866, (float)-0.951056, (float)-0.162460},
{(float)0.000000, (float)-0.850651, (float)0.525731},
{(float)0.000000, (float)-0.955423, (float)0.295242},
{(float)0.238856, (float)-0.864188, (float)0.442863},
{(float)0.262866, (float)-0.951056, (float)0.162460},
{(float)0.500000, (float)-0.809017, (float)0.309017},
{(float)0.716567, (float)-0.681718, (float)0.147621},
{(float)0.525731, (float)-0.850651, (float)0.000000},
{(float)-0.238856, (float)-0.864188, (float)-0.442863},
{(float)-0.500000, (float)-0.809017, (float)-0.309017},
{(float)-0.262866, (float)-0.951056, (float)-0.162460},
{(float)-0.850651, (float)-0.525731, (float)0.000000},
{(float)-0.716567, (float)-0.681718, (float)-0.147621},
{(float)-0.716567, (float)-0.681718, (float)0.147621},
{(float)-0.525731, (float)-0.850651, (float)0.000000},
{(float)-0.500000, (float)-0.809017, (float)0.309017},
{(float)-0.238856, (float)-0.864188, (float)0.442863},
{(float)-0.262866, (float)-0.951056, (float)0.162460},
{(float)-0.864188, (float)-0.442863, (float)0.238856},
{(float)-0.809017, (float)-0.309017, (float)0.500000},
{(float)-0.688191, (float)-0.587785, (float)0.425325},
{(float)-0.681718, (float)-0.147621, (float)0.716567},
{(float)-0.442863, (float)-0.238856, (float)0.864188},
{(float)-0.587785, (float)-0.425325, (float)0.688191},
{(float)-0.309017, (float)-0.500000, (float)0.809017},
{(float)-0.147621, (float)-0.716567, (float)0.681718},
{(float)-0.425325, (float)-0.688191, (float)0.587785},
{(float)-0.162460, (float)-0.262866, (float)0.951056},
{(float)0.442863, (float)-0.238856, (float)0.864188},
{(float)0.162460, (float)-0.262866, (float)0.951056},
{(float)0.309017, (float)-0.500000, (float)0.809017},
{(float)0.147621, (float)-0.716567, (float)0.681718},
{(float)0.000000, (float)-0.525731, (float)0.850651},
{(float)0.425325, (float)-0.688191, (float)0.587785},
{(float)0.587785, (float)-0.425325, (float)0.688191},
{(float)0.688191, (float)-0.587785, (float)0.425325},
{(float)-0.955423, (float)0.295242, (float)0.000000},
{(float)-0.951056, (float)0.162460, (float)0.262866},
{(float)-1.000000, (float)0.000000, (float)0.000000},
{(float)-0.850651, (float)0.000000, (float)0.525731},
{(float)-0.955423, (float)-0.295242, (float)0.000000},
{(float)-0.951056, (float)-0.162460, (float)0.262866},
{(float)-0.864188, (float)0.442863, (float)-0.238856},
{(float)-0.951056, (float)0.162460, (float)-0.262866},
{(float)-0.809017, (float)0.309017, (float)-0.500000},
{(float)-0.864188, (float)-0.442863, (float)-0.238856},
{(float)-0.951056, (float)-0.162460, (float)-0.262866},
{(float)-0.809017, (float)-0.309017, (float)-0.500000},
{(float)-0.681718, (float)0.147621, (float)-0.716567},
{(float)-0.681718, (float)-0.147621, (float)-0.716567},
{(float)-0.850651, (float)0.000000, (float)-0.525731},
{(float)-0.688191, (float)0.587785, (float)-0.425325},
{(float)-0.587785, (float)0.425325, (float)-0.688191},
{(float)-0.425325, (float)0.688191, (float)-0.587785},
{(float)-0.425325, (float)-0.688191, (float)-0.587785},
{(float)-0.587785, (float)-0.425325, (float)-0.688191},
{(float)-0.688191, (float)-0.587785, (float)-0.425325},

View File

@@ -0,0 +1,333 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// upper design bounds
#define MAX_MAP_HULLS 4
#define MAX_MAP_MODELS 256
#define MAX_MAP_BRUSHES 4096
#define MAX_MAP_ENTITIES 1024
#define MAX_MAP_ENTSTRING 65536
#define MAX_MAP_PLANES 32767
#define MAX_MAP_NODES 32767 // because negative shorts are contents
#define MAX_MAP_CLIPNODES 32767 //
#define MAX_MAP_LEAFS 8192
#define MAX_MAP_VERTS 65535
#define MAX_MAP_FACES 65535
#define MAX_MAP_MARKSURFACES 65535
#define MAX_MAP_TEXINFO 4096
#define MAX_MAP_EDGES 256000
#define MAX_MAP_SURFEDGES 512000
#define MAX_MAP_TEXTURES 512
#define MAX_MAP_MIPTEX 0x200000
#define MAX_MAP_LIGHTING 0x100000
#define MAX_MAP_VISIBILITY 0x100000
#define MAX_MAP_PORTALS 65536
// key / value pair sizes
#define MAX_KEY 32
#define MAX_VALUE 1024
//=============================================================================
#define BSPVERSION 29
#define TOOLVERSION 2
typedef struct
{
int fileofs, filelen;
} lump_t;
#define LUMP_ENTITIES 0
#define LUMP_PLANES 1
#define LUMP_TEXTURES 2
#define LUMP_VERTEXES 3
#define LUMP_VISIBILITY 4
#define LUMP_NODES 5
#define LUMP_TEXINFO 6
#define LUMP_FACES 7
#define LUMP_LIGHTING 8
#define LUMP_CLIPNODES 9
#define LUMP_LEAFS 10
#define LUMP_MARKSURFACES 11
#define LUMP_EDGES 12
#define LUMP_SURFEDGES 13
#define LUMP_MODELS 14
#define HEADER_LUMPS 15
typedef struct
{
float mins[3], maxs[3];
float origin[3];
int headnode[MAX_MAP_HULLS];
int visleafs; // not including the solid leaf 0
int firstface, numfaces;
} dmodel_t;
/*
typedef struct
{
fixedpoint_t mins[3], maxs[3];
fixedpoint_t origin[3];
int headnode[MAX_MAP_HULLS];
int visleafs; // not including the solid leaf 0
int firstface, numfaces;
} dmodel_FPM_t;
*/
typedef struct
{
int version;
lump_t lumps[HEADER_LUMPS];
} dheader_t;
typedef struct
{
int nummiptex;
int dataofs[4]; // [nummiptex]
} dmiptexlump_t;
#define MIPLEVELS 4
typedef struct miptex_s
{
char name[16];
unsigned width, height;
unsigned offsets[MIPLEVELS]; // four mip maps stored
} miptex_t;
typedef struct
{
float point[3];
} dvertex_t;
// 0-2 are axial planes
#define PLANE_X 0
#define PLANE_Y 1
#define PLANE_Z 2
// 3-5 are non-axial planes snapped to the nearest
#define PLANE_ANYX 3
#define PLANE_ANYY 4
#define PLANE_ANYZ 5
typedef struct
{
float normal[3];
float dist;
int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
} dplane_t;
#define CONTENTS_EMPTY -1
#define CONTENTS_SOLID -2
#define CONTENTS_WATER -3
#define CONTENTS_SLIME -4
#define CONTENTS_LAVA -5
#define CONTENTS_SKY -6
#define CONTENTS_ORIGIN -7 // removed at csg time
#define CONTENTS_CLIP -8 // changed to contents_solid
#define CONTENTS_CURRENT_0 -9
#define CONTENTS_CURRENT_90 -10
#define CONTENTS_CURRENT_180 -11
#define CONTENTS_CURRENT_270 -12
#define CONTENTS_CURRENT_UP -13
#define CONTENTS_CURRENT_DOWN -14
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct
{
int planenum;
short children[2]; // negative numbers are -(leafs+1), not nodes
short mins[3]; // for sphere culling
short maxs[3];
unsigned short firstface;
unsigned short numfaces; // counting both sides
} dnode_t;
typedef struct
{
int planenum;
short children[2]; // negative numbers are contents
} dclipnode_t;
typedef struct texinfo_s
{
float vecs[2][4]; // [s/t][xyz offset]
int miptex;
int flags;
} texinfo_t;
#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision
// note that edge 0 is never used, because negative edge nums are used for
// counterclockwise use of the edge in a face
typedef struct
{
unsigned short v[2]; // vertex numbers
} dedge_t;
#define MAXLIGHTMAPS 4
typedef struct
{
short planenum;
short side;
int firstedge; // we must support > 64k edges
short numedges;
short texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
int lightofs; // start of [numstyles*surfsize] samples
} dface_t;
#define AMBIENT_WATER 0
#define AMBIENT_SKY 1
#define AMBIENT_SLIME 2
#define AMBIENT_LAVA 3
#define NUM_AMBIENTS 4 // automatic ambient sounds
// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas
// all other leafs need visibility info
typedef struct
{
int contents;
int visofs; // -1 = no visibility info
short mins[3]; // for frustum culling
short maxs[3];
unsigned short firstmarksurface;
unsigned short nummarksurfaces;
byte ambient_level[NUM_AMBIENTS];
} dleaf_t;
//============================================================================
#ifndef QUAKE_GAME
#define ANGLE_UP -1
#define ANGLE_DOWN -2
// the utilities get to be lazy and just use large static arrays
extern int nummodels;
extern dmodel_t dmodels[MAX_MAP_MODELS];
extern int visdatasize;
extern byte dvisdata[MAX_MAP_VISIBILITY];
extern int lightdatasize;
extern byte dlightdata[MAX_MAP_LIGHTING];
extern int texdatasize;
extern byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t)
extern int entdatasize;
extern char dentdata[MAX_MAP_ENTSTRING];
extern int numleafs;
extern dleaf_t dleafs[MAX_MAP_LEAFS];
extern int numplanes;
extern dplane_t dplanes[MAX_MAP_PLANES];
extern int numvertexes;
extern dvertex_t dvertexes[MAX_MAP_VERTS];
extern int numnodes;
extern dnode_t dnodes[MAX_MAP_NODES];
extern int numtexinfo;
extern texinfo_t texinfo[MAX_MAP_TEXINFO];
extern int numfaces;
extern dface_t dfaces[MAX_MAP_FACES];
extern int numclipnodes;
extern dclipnode_t dclipnodes[MAX_MAP_CLIPNODES];
extern int numedges;
extern dedge_t dedges[MAX_MAP_EDGES];
extern int nummarksurfaces;
extern unsigned short dmarksurfaces[MAX_MAP_MARKSURFACES];
extern int numsurfedges;
extern int dsurfedges[MAX_MAP_SURFEDGES];
void DecompressVis (byte *in, byte *decompressed);
int CompressVis (byte *vis, byte *dest);
void LoadBSPFile (char *filename);
void WriteBSPFile (char *filename);
void PrintBSPFileSizes (void);
//===============
typedef struct epair_s
{
struct epair_s *next;
char *key;
char *value;
} epair_t;
typedef struct
{
vec3_t origin;
int firstbrush;
int numbrushes;
epair_t *epairs;
} entity_t;
extern int num_entities;
extern entity_t entities[MAX_MAP_ENTITIES];
void ParseEntities (void);
void UnparseEntities (void);
void SetKeyValue (entity_t *ent, char *key, char *value);
char *ValueForKey (entity_t *ent, char *key);
// will return "" if not present
vec_t FloatForKey (entity_t *ent, char *key);
void GetVectorForKey (entity_t *ent, char *key, vec3_t vec);
epair_t *ParseEpair (void);
#endif

View File

@@ -0,0 +1,55 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
void CDAudio_Play(byte track, qboolean looping)
{
}
void CDAudio_Stop(void)
{
}
void CDAudio_Pause(void)
{
}
void CDAudio_Resume(void)
{
}
void CDAudio_Update(void)
{
}
int CDAudio_Init(void)
{
return 0;
}
void CDAudio_Shutdown(void)
{
}

View File

@@ -0,0 +1,33 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
unsigned int * musicPos;
unsigned int musicFilePos;
unsigned char musicBuffer[32768];
//F_HANDLE music_fh;
int block_in;
int CDAudio_Init(void);
void CDAudio_Play(byte track, qboolean looping);
void CDAudio_Stop(void);
void CDAudio_Pause(void);
void CDAudio_Resume(void);
void CDAudio_Shutdown(void);
void CDAudio_Update(void);

View File

@@ -0,0 +1,149 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// chase.c -- chase camera code
#include "quakedef.h"
cvar_t chase_back = {"chase_back", "100"};
cvar_t chase_up = {"chase_up", "16"};
cvar_t chase_right = {"chase_right", "0"};
cvar_t chase_active = {"chase_active", "0"};
vec3_t chase_pos;
vec3_t chase_angles;
vec3_t chase_dest;
vec3_t chase_dest_angles;
#ifdef USEFPM
vec3_FPM_t chase_posFPM;
vec3_FPM_t chase_anglesFPM;
vec3_FPM_t chase_destFPM;
vec3_FPM_t chase_dest_anglesFPM;
#endif
void Chase_Init (void)
{
Cvar_RegisterVariable (&chase_back);
Cvar_RegisterVariable (&chase_up);
Cvar_RegisterVariable (&chase_right);
Cvar_RegisterVariable (&chase_active);
}
void Chase_Reset (void)
{
// for respawning and teleporting
// start position 12 units behind head
}
//Dan: Added forward declaration to prevent compiler warning
qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace);
void TraceLine (vec3_t start, vec3_t end, vec3_t impact)
{
trace_t trace;
Q_memset (&trace, 0, sizeof(trace));
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
VectorCopy (trace.endpos, impact);
}
#ifdef USEFPM
void TraceLineFPM (vec3_FPM_t start, vec3_FPM_t end, vec3_FPM_t impact)
{
trace_FPM_t trace;
Q_memset (&trace, 0, sizeof(trace));
//Dan: TODO: This links us to the world of networked quake...
//SV_RecursiveHullCheckFPM (clFPM.worldmodel->hulls, 0, 0, 1, start, end, &trace);
VectorCopy (trace.endpos, impact);
}
#endif
void Chase_Update (void)
{
int i;
float dist;
vec3_t forward, up, right;
vec3_t dest, stop;
// if can't see player, reset
AngleVectors (cl.viewangles, forward, right, up);
// calc exact destination
for (i=0 ; i<3 ; i++)
chase_dest[i] = r_refdef.vieworg[i]
- forward[i]*chase_back.value
- right[i]*chase_right.value;
chase_dest[2] = r_refdef.vieworg[2] + chase_up.value;
// find the spot the player is looking at
VectorMA (r_refdef.vieworg, 4096, forward, dest);
TraceLine (r_refdef.vieworg, dest, stop);
// calculate pitch to look at the same spot from camera
VectorSubtract (stop, r_refdef.vieworg, stop);
dist = DotProduct (stop, forward);
if (dist < 1)
dist = 1;
r_refdef.viewangles[PITCH] = (float)(-atan(stop[2] / dist) / M_PI * 180);
// move towards destination
VectorCopy (chase_dest, r_refdef.vieworg);
}
#ifdef USEFPM
void Chase_UpdateFPM (void)
{
int i;
fixedpoint_t dist;
vec3_FPM_t forward, up, right;
vec3_FPM_t dest, stop;
// if can't see player, reset
AngleVectorsFPM (clFPM.viewangles, forward, right, up);
// calc exact destination
for (i=0 ; i<3 ; i++)
chase_destFPM[i] = FPM_SUB(FPM_SUB(r_refdefFPM.vieworg[i],
FPM_MUL(forward[i],FPM_FROMFLOAT(chase_back.value))),
FPM_MUL(right[i],FPM_FROMFLOAT(chase_right.value)));
chase_destFPM[2] = FPM_ADD(r_refdefFPM.vieworg[2], FPM_FROMFLOAT(chase_up.value));
// find the spot the player is looking at
VectorMAFPM (r_refdefFPM.vieworg, FPM_FROMLONG(4096), forward, dest);
TraceLineFPM (r_refdefFPM.vieworg, dest, stop);
// calculate pitch to look at the same spot from camera
VectorSubtractFPM (stop, r_refdefFPM.vieworg, stop);
dist = DotProductFPM (stop, forward);
if (dist < FPM_FROMLONG(1))
dist = FPM_FROMLONG(1);
r_refdefFPM.viewangles[PITCH] = -FPM_MUL(FPM_DIV(FPM_ATAN(FPM_DIV(stop[2], dist)), FPM_PI), FPM_FROMLONG(180));
// move towards destination
VectorCopy (chase_destFPM, r_refdefFPM.vieworg);
}
#endif

View File

@@ -0,0 +1,475 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
//Dan
//#include "../zlib/zlib.h"
#ifdef _X86_
#include "../LogFloat.h"
#endif
void CL_FinishTimeDemo (void);
/*
==============================================================================
DEMO CODE
When a demo is playing back, all NET_SendMessages are skipped, and
NET_GetMessages are read from the demo file.
Whenever cl.time gets past the last received message, another message is
read from the demo file.
==============================================================================
*/
/*
==============
CL_StopPlayback
Called when a demo file runs out, or the user starts a game
==============
*/
void CL_StopPlayback (void)
{
if (!cls.demoplayback)
return;
//Dan:
fclose (cls.demofile);
cls.demoplayback = false;
cls.demofile = NULL;
cls.state = ca_disconnected;
if (cls.timedemo)
CL_FinishTimeDemo ();
}
/*
====================
CL_WriteDemoMessage
Dumps the current net message, prefixed by the length and view angles
====================
*/
void CL_WriteDemoMessage (void)
{
int len;
int i;
float f;
len = LittleLong (net_message.cursize);
fwrite (&len, 4, 1, cls.demofile);
for (i=0 ; i<3 ; i++)
{
f = LittleFloat (cl.viewangles[i]);
fwrite (&f, 4, 1, cls.demofile);
}
fwrite (net_message.data, net_message.cursize, 1, cls.demofile);
fflush (cls.demofile);
}
/*
====================
CL_GetMessage
Handles recording and playback of demos, on top of NET_ code
====================
*/
int CL_GetMessage (void)
{
int r, i;
float f;
if (cls.demoplayback)
{
// decide if it is time to grab the next message
if (cls.signon == SIGNONS) // allways grab until fully connected
{
if (cls.timedemo)
{
if (host_framecount == cls.td_lastframe)
return 0; // allready read this frame's message
cls.td_lastframe = host_framecount;
// if this is the second frame, grab the real td_starttime
// so the bogus time on the first frame doesn't count
if (host_framecount == cls.td_startframe + 1)
cls.td_starttime = (float)realtime;
}
else if ( /* cl.time > 0 && */ cl.time <= cl.mtime[0])
{
return 0; // don't need another message yet
}
}
// get the next message
fread (&net_message.cursize, 4, 1, cls.demofile);
VectorCopy (cl.mviewangles[0], cl.mviewangles[1]);
for (i=0 ; i<3 ; i++)
{
r = fread (&f, 4, 1, cls.demofile);
cl.mviewangles[0][i] = LittleFloat (f);
}
net_message.cursize = LittleLong (net_message.cursize);
if (net_message.cursize > MAX_MSGLEN)
Sys_Error ("Demo message > MAX_MSGLEN");
r = fread (net_message.data, net_message.cursize, 1, cls.demofile);
if (r != /*net_message.cursize*/1)
{
CL_StopPlayback ();
return 0;
}
return 1;
}
while (1)
{
r = NET_GetMessage (cls.netcon);
if (r != 1 && r != 2)
return r;
// discard nop keepalive message
if (net_message.cursize == 1 && net_message.data[0] == svc_nop)
Con_Printf ("<-- server to client keepalive\n");
else
break;
}
if (cls.demorecording)
CL_WriteDemoMessage ();
return r;
}
#ifdef USEFPM
int CL_GetMessageFPM (void)
{
int r, i;
float f;
if (cls.demoplayback)
{
// decide if it is time to grab the next message
if (cls.signon == SIGNONS) // allways grab until fully connected
{
if (cls.timedemo)
{
if (host_framecount == cls.td_lastframe)
return 0; // allready read this frame's message
cls.td_lastframe = host_framecount;
// if this is the second frame, grab the real td_starttime
// so the bogus time on the first frame doesn't count
if (host_framecount == cls.td_startframe + 1)
cls.td_starttime = (float)realtime;
}
else if ( /* cl.time > 0 && */ clFPM.time <= clFPM.mtime[0])
{
return 0; // don't need another message yet
}
}
// get the next message
//Dan
fread (&net_message.cursize, 4, 1, cls.demofile);
VectorCopy (clFPM.mviewangles[0], clFPM.mviewangles[1]);
for (i=0 ; i<3 ; i++)
{
//Dan
r = fread (&f, 4, 1, cls.demofile);
clFPM.mviewangles[0][i] = FPM_FROMFLOAT(LittleFloat (f));
}
net_message.cursize = LittleLong (net_message.cursize);
if (net_message.cursize > MAX_MSGLEN)
Sys_Error ("Demo message > MAX_MSGLEN");
//Dan
r = fread (net_message.data, net_message.cursize, 1, cls.demofile);
if (r != net_message.cursize/*1*/)
{
CL_StopPlayback ();
return 0;
}
return 1;
}
while (1)
{
r = NET_GetMessage (cls.netcon);
if (r != 1 && r != 2)
return r;
// discard nop keepalive message
if (net_message.cursize == 1 && net_message.data[0] == svc_nop)
Con_Printf ("<-- server to client keepalive\n");
else
break;
}
if (cls.demorecording)
CL_WriteDemoMessage ();
return r;
}
#endif
/*
====================
CL_Stop_f
stop recording a demo
====================
*/
void CL_Stop_f (void)
{
if (cmd_source != src_command)
return;
if (!cls.demorecording)
{
Con_Printf ("Not recording a demo.\n");
return;
}
// write a disconnect message to the demo file
SZ_Clear (&net_message);
MSG_WriteByte (&net_message, svc_disconnect);
CL_WriteDemoMessage ();
// finish up
fclose (cls.demofile);
cls.demofile = NULL;
cls.demorecording = false;
Con_Printf ("Completed demo\n");
}
/*
====================
CL_Record_f
record <demoname> <map> [cd track]
====================
*/
void CL_Record_f (void)
{
int c;
char name[MAX_OSPATH];
int track;
if (cmd_source != src_command)
return;
c = Cmd_Argc();
if (c != 2 && c != 3 && c != 4)
{
Con_Printf ("record <demoname> [<map> [cd track]]\n");
return;
}
if (strstr(Cmd_Argv(1), ".."))
{
Con_Printf ("Relative pathnames are not allowed.\n");
return;
}
if (c == 2 && cls.state == ca_connected)
{
Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
return;
}
// write the forced cd track number, or -1
if (c == 4)
{
track = atoi(Cmd_Argv(3));
Con_Printf ("Forcing CD track to %i\n", cls.forcetrack);
}
else
track = -1;
sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
//
// start the map up
//
if (c > 2)
Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command);
//
// open the demo file
//
COM_DefaultExtension (name, ".dem");
Con_Printf ("recording to %s.\n", name);
cls.demofile = fopen (name, "wb");
if (!cls.demofile)
{
Con_Printf ("ERROR: couldn't open.\n");
return;
}
cls.forcetrack = track;
fprintf (cls.demofile, "%i\n", cls.forcetrack);
cls.demorecording = true;
}
// Demos disabled at start to allow game to play. Playdemo command remapped to gpplaydemo so this function allows for silent fail of playdemo command.
void CL_PlayDemo_silentfail (void)
{
}
/*
====================
CL_PlayDemo_f
play [demoname]
====================
*/
void CL_PlayDemo_f (void)
{
char name[256];
int c;
qboolean neg = false;
if (cmd_source != src_command)
return;
if (Cmd_Argc() != 2)
{
Con_Printf ("play <demoname> : plays a demo\n");
return;
}
//
// disconnect from server
//
#ifndef USEFPM
CL_Disconnect ();
#else
CL_DisconnectFPM ();
#endif
//
// open the demo file
//
strcpy (name, Cmd_Argv(1));
COM_DefaultExtension (name, ".dem");
Con_Printf ("Playing demo from %s.\n", name);
COM_FOpenFile (name, &cls.demofile);
if (!cls.demofile)
{
Con_Printf ("ERROR: couldn't open.\n");
cls.demonum = -1; // stop demo loop
return;
}
cls.demoplayback = true;
cls.state = ca_connected;
cls.forcetrack = 0;
while ((c = fgetc(cls.demofile)) != '\n')
if (c == '-')
neg = true;
else
cls.forcetrack = cls.forcetrack * 10 + (c - '0');
if (neg)
cls.forcetrack = -cls.forcetrack;
// ZOID, fscanf is evil
// fscanf (cls.demofile, "%i\n", &cls.forcetrack);
}
/*
====================
CL_FinishTimeDemo
====================
*/
void CL_FinishTimeDemo (void)
{
int frames;
float time;
cls.timedemo = false;
// the first frame didn't count
frames = (host_framecount - cls.td_startframe) - 1;
time = (float)(realtime - cls.td_starttime);
if (!time)
time = 1;
Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames, time, frames/time);
#ifdef _X86_
//Dan East:
//The following generates Floating Point totals if floating point logging was performed
LogFloatResults("\\LogFloat.txt");
#endif
/*
//Dan East:
//The following is used to popup a message box with the timedemo results.
//The purpose of this is to make the results known when screen output is
//disabled (in the case of various benchmark testing).
{
TCHAR s[250];
_stprintf(s, _T("%i frames %5.1f seconds %5.1f fps\n"), frames, time, frames/time);
MessageBox(NULL, s, _T("TimeDemo Results"), MB_OK);
}
*/
}
/*
====================
CL_TimeDemo_f
timedemo [demoname]
====================
*/
void CL_TimeDemo_f (void)
{
if (cmd_source != src_command)
return;
if (Cmd_Argc() != 2)
{
Con_Printf ("timedemo <demoname> : gets demo speeds\n");
return;
}
CL_PlayDemo_f ();
// cls.td_starttime will be grabbed at the second frame of the demo, so
// all the loading time doesn't get counted
cls.timedemo = true;
cls.td_startframe = host_framecount;
cls.td_lastframe = -1; // get a new message this frame
}

View File

@@ -0,0 +1,649 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cl.input.c -- builds an intended movement command to send to the server
// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
// rights reserved.
#include "quakedef.h"
/*
===============================================================================
KEY BUTTONS
Continuous button event tracking is complicated by the fact that two different
input sources (say, mouse button 1 and the control key) can both press the
same button, but the button should only be released when both of the
pressing key have been released.
When a key event issues a button command (+forward, +attack, etc), it appends
its key number as a parameter to the command so it can be matched up with
the release.
state bit 0 is the current state of the key
state bit 1 is edge triggered on the up to down transition
state bit 2 is edge triggered on the down to up transition
===============================================================================
*/
kbutton_t in_mlook, in_klook;
kbutton_t in_left, in_right, in_forward, in_back;
kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright;
kbutton_t in_strafe, in_speed, in_use, in_jump, in_attack;
kbutton_t in_up, in_down;
int in_impulse;
void KeyDown (kbutton_t *b)
{
int k;
char *c;
c = Cmd_Argv(1);
if (c[0])
k = atoi(c);
else
k = -1; // typed manually at the console for continuous down
if (k == b->down[0] || k == b->down[1])
return; // repeating key
if (!b->down[0])
b->down[0] = k;
else if (!b->down[1])
b->down[1] = k;
else
{
Con_Printf ("Three keys down for a button!\n");
return;
}
if (b->state & 1)
return; // still down
b->state |= 1 + 2; // down + impulse down
}
void KeyUp (kbutton_t *b)
{
int k;
char *c;
c = Cmd_Argv(1);
if (c[0])
k = atoi(c);
else
{ // typed manually at the console, assume for unsticking, so clear all
b->down[0] = b->down[1] = 0;
b->state = 4; // impulse up
return;
}
if (b->down[0] == k)
b->down[0] = 0;
else if (b->down[1] == k)
b->down[1] = 0;
else
return; // key up without coresponding down (menu pass through)
if (b->down[0] || b->down[1])
return; // some other key is still holding it down
if (!(b->state & 1))
return; // still up (this should not happen)
b->state &= ~1; // now up
b->state |= 4; // impulse up
}
void IN_KLookDown (void) {KeyDown(&in_klook);}
void IN_KLookUp (void) {KeyUp(&in_klook);}
void IN_MLookDown (void) {KeyDown(&in_mlook);}
void IN_MLookUp (void) {
KeyUp(&in_mlook);
if ( !(in_mlook.state&1) && lookspring.value)
V_StartPitchDrift();
}
void IN_UpDown(void) {KeyDown(&in_up);}
void IN_UpUp(void) {KeyUp(&in_up);}
void IN_DownDown(void) {KeyDown(&in_down);}
void IN_DownUp(void) {KeyUp(&in_down);}
void IN_LeftDown(void) {KeyDown(&in_left);}
void IN_LeftUp(void) {KeyUp(&in_left);}
void IN_RightDown(void) {KeyDown(&in_right);}
void IN_RightUp(void) {KeyUp(&in_right);}
void IN_ForwardDown(void) {KeyDown(&in_forward);}
void IN_ForwardUp(void) {KeyUp(&in_forward);}
void IN_BackDown(void) {KeyDown(&in_back);}
void IN_BackUp(void) {KeyUp(&in_back);}
void IN_LookupDown(void) {KeyDown(&in_lookup);}
void IN_LookupUp(void) {KeyUp(&in_lookup);}
void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
void IN_MoverightDown(void) {KeyDown(&in_moveright);}
void IN_MoverightUp(void) {KeyUp(&in_moveright);}
void IN_SpeedDown(void) {KeyDown(&in_speed);}
void IN_SpeedUp(void) {KeyUp(&in_speed);}
void IN_StrafeDown(void) {KeyDown(&in_strafe);}
void IN_StrafeUp(void) {KeyUp(&in_strafe);}
void IN_AttackDown(void) {KeyDown(&in_attack);}
void IN_AttackUp(void) {KeyUp(&in_attack);}
void IN_UseDown (void) {KeyDown(&in_use);}
void IN_UseUp (void) {KeyUp(&in_use);}
void IN_JumpDown (void) {KeyDown(&in_jump);}
void IN_JumpUp (void) {KeyUp(&in_jump);}
void IN_Impulse (void) {in_impulse=Q_atoi(Cmd_Argv(1));}
/*
===============
CL_KeyState
Returns 0.25 if a key was pressed and released during the frame,
0.5 if it was pressed and held
0 if held then released, and
1.0 if held for the entire time
===============
*/
float CL_KeyState (kbutton_t *key)
{
float val;
qboolean impulsedown, impulseup, down;
impulsedown = key->state & 2;
impulseup = key->state & 4;
down = key->state & 1;
val = 0;
if (impulsedown && !impulseup)
if (down)
val = 0.5; // pressed and held this frame
else
val = 0; // I_Error ();
if (impulseup && !impulsedown)
if (down)
val = 0; // I_Error ();
else
val = 0; // released this frame
if (!impulsedown && !impulseup)
if (down)
val = 1.0; // held the entire frame
else
val = 0; // up the entire frame
if (impulsedown && impulseup)
if (down)
val = 0.75; // released and re-pressed this frame
else
val = 0.25; // pressed and released this frame
key->state &= 1; // clear impulses
return val;
}
#ifdef USEFPM
fixedpoint_t CL_KeyStateFPM (kbutton_t *key)
{
fixedpoint_t val;
qboolean impulsedown, impulseup, down;
impulsedown = key->state & 2;
impulseup = key->state & 4;
down = key->state & 1;
val = 0;
if (impulsedown && !impulseup)
if (down)
val = FPM_FROMFLOATC(0.5); // pressed and held this frame
else
val = 0; // I_Error ();
if (impulseup && !impulsedown)
if (down)
val = 0; // I_Error ();
else
val = 0; // released this frame
if (!impulsedown && !impulseup)
if (down)
val = FPM_FROMFLOATC(1.0); // held the entire frame
else
val = 0; // up the entire frame
if (impulsedown && impulseup)
if (down)
val = FPM_FROMFLOATC(0.75); // released and re-pressed this frame
else
val = FPM_FROMFLOATC(0.25); // pressed and released this frame
key->state &= 1; // clear impulses
return val;
}
#endif
//==========================================================================
cvar_t cl_upspeed = {"cl_upspeed","200"};
cvar_t cl_forwardspeed = {"cl_forwardspeed","200", true};
cvar_t cl_backspeed = {"cl_backspeed","200", true};
cvar_t cl_sidespeed = {"cl_sidespeed","350"};
cvar_t cl_movespeedkey = {"cl_movespeedkey","2.0"};
cvar_t cl_yawspeed = {"cl_yawspeed","140"};
cvar_t cl_pitchspeed = {"cl_pitchspeed","150"};
cvar_t cl_anglespeedkey = {"cl_anglespeedkey","1.5"};
/*
================
CL_AdjustAngles
Moves the local angle positions
================
*/
void CL_AdjustAngles (void)
{
float speed;
float up, down;
if (in_speed.state & 1)
speed = (float)(host_frametime * cl_anglespeedkey.value);
else
speed = (float)host_frametime;
if (!(in_strafe.state & 1))
{
cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right);
cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left);
cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
}
if (in_klook.state & 1)
{
V_StopPitchDrift ();
cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward);
cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back);
}
up = CL_KeyState (&in_lookup);
down = CL_KeyState(&in_lookdown);
cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up;
cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down;
if (up || down)
V_StopPitchDrift ();
if (cl.viewangles[PITCH] > 80)
cl.viewangles[PITCH] = 80;
if (cl.viewangles[PITCH] < -70)
cl.viewangles[PITCH] = -70;
if (cl.viewangles[ROLL] > 50)
cl.viewangles[ROLL] = 50;
if (cl.viewangles[ROLL] < -50)
cl.viewangles[ROLL] = -50;
}
#ifdef USEFPM
void CL_AdjustAnglesFPM (void)
{
fixedpoint_t speed;
fixedpoint_t up, down;
fixedpoint_t clpitchspeed=FPM_FROMFLOAT(cl_pitchspeed.value);
if (in_speed.state & 1)
speed = FPM_FROMFLOAT(host_frametime * cl_anglespeedkey.value);
else
speed = FPM_FROMFLOAT(host_frametime);
if (!(in_strafe.state & 1))
{
fixedpoint_t clyawspeed=FPM_FROMFLOAT(cl_yawspeed.value);
clFPM.viewangles[YAW] = FPM_SUB(clFPM.viewangles[YAW], FPM_MUL(FPM_MUL(speed,clyawspeed), CL_KeyStateFPM (&in_right)));
clFPM.viewangles[YAW] = FPM_ADD(clFPM.viewangles[YAW], FPM_MUL(FPM_MUL(speed,clyawspeed), CL_KeyStateFPM (&in_left)));
clFPM.viewangles[YAW] = anglemodFPM(clFPM.viewangles[YAW]);
}
if (in_klook.state & 1)
{
V_StopPitchDriftFPM ();
clFPM.viewangles[PITCH] = FPM_SUB(clFPM.viewangles[PITCH], FPM_MUL(FPM_MUL(speed,clpitchspeed), CL_KeyStateFPM (&in_forward)));
clFPM.viewangles[PITCH] = FPM_ADD(clFPM.viewangles[PITCH], FPM_MUL(FPM_MUL(speed,clpitchspeed), CL_KeyStateFPM (&in_back)));
}
up = CL_KeyStateFPM (&in_lookup);
down = CL_KeyStateFPM(&in_lookdown);
clFPM.viewangles[PITCH] = FPM_SUB(clFPM.viewangles[PITCH], FPM_MUL(FPM_MUL(speed, clpitchspeed), up));
clFPM.viewangles[PITCH] = FPM_ADD(clFPM.viewangles[PITCH], FPM_MUL(FPM_MUL(speed, clpitchspeed), down));
if (up || down)
V_StopPitchDriftFPM ();
if (clFPM.viewangles[PITCH] > FPM_FROMLONGC(80))
clFPM.viewangles[PITCH] = FPM_FROMLONGC(80);
if (clFPM.viewangles[PITCH] < FPM_FROMLONGC(-70))
clFPM.viewangles[PITCH] = FPM_FROMLONGC(-70);
if (clFPM.viewangles[ROLL] > FPM_FROMLONGC(50))
clFPM.viewangles[ROLL] = FPM_FROMLONGC(50);
if (clFPM.viewangles[ROLL] < FPM_FROMLONGC(-50))
clFPM.viewangles[ROLL] = FPM_FROMLONGC(-50);
}
#endif
/*
================
CL_BaseMove
Send the intended movement message to the server
================
*/
void CL_BaseMove (usercmd_t *cmd)
{
if (cls.signon != SIGNONS)
return;
CL_AdjustAngles ();
Q_memset (cmd, 0, sizeof(*cmd));
if (in_strafe.state & 1)
{
cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right);
cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left);
}
cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright);
cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft);
cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up);
cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down);
if (! (in_klook.state & 1) )
{
cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
}
//
// adjust for speed key
//
if (in_speed.state & 1)
{
cmd->forwardmove *= cl_movespeedkey.value;
cmd->sidemove *= cl_movespeedkey.value;
cmd->upmove *= cl_movespeedkey.value;
}
#ifdef QUAKE2
cmd->lightlevel = cl.light_level;
#endif
}
#ifdef USEFPM
void CL_BaseMoveFPM (usercmd_FPM_t *cmd)
{
if (cls.signon != SIGNONS)
return;
CL_AdjustAnglesFPM ();
Q_memset (cmd, 0, sizeof(*cmd));
if (in_strafe.state & 1)
{
cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right);
cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left);
}
cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright);
cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft);
cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up);
cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down);
if (! (in_klook.state & 1) )
{
cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
}
//
// adjust for speed key
//
if (in_speed.state & 1)
{
cmd->forwardmove *= cl_movespeedkey.value;
cmd->sidemove *= cl_movespeedkey.value;
cmd->upmove *= cl_movespeedkey.value;
}
#ifdef QUAKE2
cmd->lightlevel = clFPM.light_level;
#endif
}
#endif
/*
==============
CL_SendMove
==============
*/
void CL_SendMove (usercmd_t *cmd)
{
int i;
int bits;
sizebuf_t buf;
byte data[128];
buf.maxsize = 128;
buf.cursize = 0;
buf.data = data;
cl.cmd = *cmd;
//
// send the movement message
//
MSG_WriteByte (&buf, clc_move);
MSG_WriteFloat (&buf, (float)cl.mtime[0]); // so server can get ping times
for (i=0 ; i<3 ; i++)
MSG_WriteAngle (&buf, cl.viewangles[i]);
MSG_WriteShort (&buf, (int)cmd->forwardmove);
MSG_WriteShort (&buf, (int)cmd->sidemove);
MSG_WriteShort (&buf, (int)cmd->upmove);
//
// send button bits
//
bits = 0;
if ( in_attack.state & 3 )
bits |= 1;
in_attack.state &= ~2;
if (in_jump.state & 3)
bits |= 2;
in_jump.state &= ~2;
MSG_WriteByte (&buf, bits);
MSG_WriteByte (&buf, in_impulse);
in_impulse = 0;
#ifdef QUAKE2
//
// light level
//
MSG_WriteByte (&buf, cmd->lightlevel);
#endif
//
// deliver the message
//
if (cls.demoplayback)
return;
//
// allways dump the first two message, because it may contain leftover inputs
// from the last level
//
if (++cl.movemessages <= 2)
return;
if (NET_SendUnreliableMessage (cls.netcon, &buf) == -1)
{
GpError("CL_SendMove, -1",2);
Con_Printf ("CL_SendMove: lost server connection\n");
CL_Disconnect ();
}
}
#ifdef USEFPM
void CL_SendMoveFPM (usercmd_FPM_t *cmd)
{
int i;
int bits;
sizebuf_t buf;
byte data[128];
buf.maxsize = 128;
buf.cursize = 0;
buf.data = data;
clFPM.cmd = *cmd;
//
// send the movement message
//
MSG_WriteByte (&buf, clc_move);
MSG_WriteFloat (&buf, (float)clFPM.mtime[0]); // so server can get ping times
for (i=0 ; i<3 ; i++)
MSG_WriteAngle (&buf, FPM_TOFLOAT(clFPM.viewangles[i]));
MSG_WriteShort (&buf, (int)cmd->forwardmove);
MSG_WriteShort (&buf, (int)cmd->sidemove);
MSG_WriteShort (&buf, (int)cmd->upmove);
//
// send button bits
//
bits = 0;
if ( in_attack.state & 3 )
bits |= 1;
in_attack.state &= ~2;
if (in_jump.state & 3)
bits |= 2;
in_jump.state &= ~2;
MSG_WriteByte (&buf, bits);
MSG_WriteByte (&buf, in_impulse);
in_impulse = 0;
#ifdef QUAKE2
//
// light level
//
MSG_WriteByte (&buf, cmd->lightlevel);
#endif
//
// deliver the message
//
if (cls.demoplayback)
return;
//
// allways dump the first two message, because it may contain leftover inputs
// from the last level
//
if (++cl.movemessages <= 2)
return;
if (NET_SendUnreliableMessage (cls.netcon, &buf) == -1)
{
Con_Printf ("CL_SendMove: lost server connection\n");
CL_Disconnect ();
}
}
#endif
/*
============
CL_InitInput
============
*/
void CL_InitInput (void)
{
Cmd_AddCommand ("+moveup",IN_UpDown);
Cmd_AddCommand ("-moveup",IN_UpUp);
Cmd_AddCommand ("+movedown",IN_DownDown);
Cmd_AddCommand ("-movedown",IN_DownUp);
Cmd_AddCommand ("+left",IN_LeftDown);
Cmd_AddCommand ("-left",IN_LeftUp);
Cmd_AddCommand ("+right",IN_RightDown);
Cmd_AddCommand ("-right",IN_RightUp);
Cmd_AddCommand ("+forward",IN_ForwardDown);
Cmd_AddCommand ("-forward",IN_ForwardUp);
Cmd_AddCommand ("+back",IN_BackDown);
Cmd_AddCommand ("-back",IN_BackUp);
Cmd_AddCommand ("+lookup", IN_LookupDown);
Cmd_AddCommand ("-lookup", IN_LookupUp);
Cmd_AddCommand ("+lookdown", IN_LookdownDown);
Cmd_AddCommand ("-lookdown", IN_LookdownUp);
Cmd_AddCommand ("+strafe", IN_StrafeDown);
Cmd_AddCommand ("-strafe", IN_StrafeUp);
Cmd_AddCommand ("+moveleft", IN_MoveleftDown);
Cmd_AddCommand ("-moveleft", IN_MoveleftUp);
Cmd_AddCommand ("+moveright", IN_MoverightDown);
Cmd_AddCommand ("-moveright", IN_MoverightUp);
Cmd_AddCommand ("+speed", IN_SpeedDown);
Cmd_AddCommand ("-speed", IN_SpeedUp);
Cmd_AddCommand ("+attack", IN_AttackDown);
Cmd_AddCommand ("-attack", IN_AttackUp);
Cmd_AddCommand ("+use", IN_UseDown);
Cmd_AddCommand ("-use", IN_UseUp);
Cmd_AddCommand ("+jump", IN_JumpDown);
Cmd_AddCommand ("-jump", IN_JumpUp);
Cmd_AddCommand ("impulse", IN_Impulse);
Cmd_AddCommand ("+klook", IN_KLookDown);
Cmd_AddCommand ("-klook", IN_KLookUp);
Cmd_AddCommand ("+mlook", IN_MLookDown);
Cmd_AddCommand ("-mlook", IN_MLookUp);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,713 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cl_tent.c -- client side temporary entities
#include "quakedef.h"
int num_temp_entities;
entity_t cl_temp_entities[MAX_TEMP_ENTITIES];
beam_t cl_beams[MAX_BEAMS];
#ifdef USEFPM
entity_FPM_t cl_temp_entitiesFPM[MAX_TEMP_ENTITIES];
beam_FPM_t cl_beamsFPM[MAX_BEAMS];
#endif
sfx_t *cl_sfx_wizhit;
sfx_t *cl_sfx_knighthit;
sfx_t *cl_sfx_tink1;
sfx_t *cl_sfx_ric1;
sfx_t *cl_sfx_ric2;
sfx_t *cl_sfx_ric3;
sfx_t *cl_sfx_r_exp3;
#ifdef QUAKE2
sfx_t *cl_sfx_imp;
sfx_t *cl_sfx_rail;
#endif
/*
=================
CL_ParseTEnt
=================
*/
void CL_InitTEnts (void)
{
cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
#ifdef QUAKE2
cl_sfx_imp = S_PrecacheSound ("shambler/sattck1.wav");
cl_sfx_rail = S_PrecacheSound ("weapons/lstart.wav");
#endif
}
/*
=================
CL_ParseBeam
=================
*/
void CL_ParseBeam (model_t *m)
{
int ent;
vec3_t start, end;
beam_t *b;
int i;
ent = MSG_ReadShort ();
start[0] = MSG_ReadCoord ();
start[1] = MSG_ReadCoord ();
start[2] = MSG_ReadCoord ();
end[0] = MSG_ReadCoord ();
end[1] = MSG_ReadCoord ();
end[2] = MSG_ReadCoord ();
// override any beam with the same entity
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
if (b->entity == ent)
{
b->entity = ent;
b->model = m;
b->endtime = (float)(cl.time + 0.2);
VectorCopy (start, b->start);
VectorCopy (end, b->end);
return;
}
// find a free beam
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
{
if (!b->model || b->endtime < cl.time)
{
b->entity = ent;
b->model = m;
b->endtime = (float)(cl.time + 0.2);
VectorCopy (start, b->start);
VectorCopy (end, b->end);
return;
}
}
Con_Printf ("beam list overflow!\n");
}
#ifdef USEFPM
void CL_ParseBeamFPM (model_FPM_t *m)
{
int ent;
vec3_FPM_t start, end;
beam_FPM_t *b;
int i;
ent = MSG_ReadShort ();
start[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
start[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
start[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
end[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
end[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
end[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
// override any beam with the same entity
for (i=0, b=cl_beamsFPM ; i< MAX_BEAMS ; i++, b++)
if (b->entity == ent)
{
b->entity = ent;
b->model = m;
b->endtime = (float)(clFPM.time + 0.2);
VectorCopy (start, b->start);
VectorCopy (end, b->end);
return;
}
// find a free beam
for (i=0, b=cl_beamsFPM ; i< MAX_BEAMS ; i++, b++)
{
if (!b->model || b->endtime < clFPM.time)
{
b->entity = ent;
b->model = m;
b->endtime = (float)(clFPM.time + 0.2);
VectorCopy (start, b->start);
VectorCopy (end, b->end);
return;
}
}
Con_Printf ("beam list overflow!\n");
}
#endif
/*
=================
CL_ParseTEnt
=================
*/
void CL_ParseTEnt (void)
{
int type;
vec3_t pos;
#ifdef QUAKE2
vec3_t endpos;
#endif
dlight_t *dl;
int rnd;
int colorStart, colorLength;
type = MSG_ReadByte ();
switch (type)
{
case TE_WIZSPIKE: // spike hitting wall
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
R_RunParticleEffect (pos, vec3_origin, 20, 30);
S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
break;
case TE_KNIGHTSPIKE: // spike hitting wall
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
R_RunParticleEffect (pos, vec3_origin, 226, 20);
S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
break;
case TE_SPIKE: // spike hitting wall
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
#ifdef GLTEST
Test_Spawn (pos);
#else
R_RunParticleEffect (pos, vec3_origin, 0, 10);
#endif
if ( rand() % 5 )
S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
else
{
rnd = rand() & 3;
if (rnd == 1)
S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
else if (rnd == 2)
S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
else
S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
}
break;
case TE_SUPERSPIKE: // super spike hitting wall
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
R_RunParticleEffect (pos, vec3_origin, 0, 20);
if ( rand() % 5 )
S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
else
{
rnd = rand() & 3;
if (rnd == 1)
S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
else if (rnd == 2)
S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
else
S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
}
break;
case TE_GUNSHOT: // bullet hitting wall
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
R_RunParticleEffect (pos, vec3_origin, 0, 20);
break;
case TE_EXPLOSION: // rocket explosion
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
R_ParticleExplosion (pos);
dl = CL_AllocDlight (0);
VectorCopy (pos, dl->origin);
dl->radius = 350;
dl->die = (float)(cl.time + 0.5);
dl->decay = 300;
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
break;
case TE_TAREXPLOSION: // tarbaby explosion
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
R_BlobExplosion (pos);
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
break;
case TE_LIGHTNING1: // lightning bolts
CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
break;
case TE_LIGHTNING2: // lightning bolts
CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
break;
case TE_LIGHTNING3: // lightning bolts
CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
break;
// PGM 01/21/97
case TE_BEAM: // grappling hook beam
CL_ParseBeam (Mod_ForName("progs/beam.mdl", true));
break;
// PGM 01/21/97
case TE_LAVASPLASH:
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
R_LavaSplash (pos);
break;
case TE_TELEPORT:
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
R_TeleportSplash (pos);
break;
case TE_EXPLOSION2: // color mapped explosion
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
colorStart = MSG_ReadByte ();
colorLength = MSG_ReadByte ();
R_ParticleExplosion2 (pos, colorStart, colorLength);
dl = CL_AllocDlight (0);
VectorCopy (pos, dl->origin);
dl->radius = 350;
dl->die = (float)(cl.time + 0.5);
dl->decay = 300;
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
break;
#ifdef QUAKE2
case TE_IMPLOSION:
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
S_StartSound (-1, 0, cl_sfx_imp, pos, 1, 1);
break;
case TE_RAILTRAIL:
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
endpos[0] = MSG_ReadCoord ();
endpos[1] = MSG_ReadCoord ();
endpos[2] = MSG_ReadCoord ();
S_StartSound (-1, 0, cl_sfx_rail, pos, 1, 1);
S_StartSound (-1, 1, cl_sfx_r_exp3, endpos, 1, 1);
R_RocketTrail (pos, endpos, 0+128);
R_ParticleExplosion (endpos);
dl = CL_AllocDlight (-1);
VectorCopy (endpos, dl->origin);
dl->radius = 350;
dl->die = cl.time + 0.5;
dl->decay = 300;
break;
#endif
default:
Sys_Error ("CL_ParseTEnt: bad type");
}
}
#ifdef USEFPM
void CL_ParseTEntFPM (void)
{
int type;
vec3_FPM_t pos;
#ifdef QUAKE2
vec3_FPM_t endpos;
#endif
dlight_FPM_t *dl;
int rnd;
int colorStart, colorLength;
type = MSG_ReadByte ();
switch (type)
{
case TE_WIZSPIKE: // spike hitting wall
pos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
R_RunParticleEffectFPM (pos, vec3_originFPM, 20, 30);
S_StartSoundFPM (-1, 0, cl_sfx_wizhit, pos, 1, 1);
break;
case TE_KNIGHTSPIKE: // spike hitting wall
pos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
R_RunParticleEffectFPM (pos, vec3_originFPM, 226, 20);
S_StartSoundFPM (-1, 0, cl_sfx_knighthit, pos, 1, 1);
break;
case TE_SPIKE: // spike hitting wall
pos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
#ifdef GLTEST
Test_Spawn (pos);
#else
R_RunParticleEffectFPM (pos, vec3_originFPM, 0, 10);
#endif
if ( rand() % 5 )
S_StartSoundFPM (-1, 0, cl_sfx_tink1, pos, 1, 1);
else
{
rnd = rand() & 3;
if (rnd == 1)
S_StartSoundFPM (-1, 0, cl_sfx_ric1, pos, 1, 1);
else if (rnd == 2)
S_StartSoundFPM (-1, 0, cl_sfx_ric2, pos, 1, 1);
else
S_StartSoundFPM (-1, 0, cl_sfx_ric3, pos, 1, 1);
}
break;
case TE_SUPERSPIKE: // super spike hitting wall
pos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
R_RunParticleEffectFPM (pos, vec3_originFPM, 0, 20);
if ( rand() % 5 )
S_StartSoundFPM (-1, 0, cl_sfx_tink1, pos, 1, 1);
else
{
rnd = rand() & 3;
if (rnd == 1)
S_StartSoundFPM (-1, 0, cl_sfx_ric1, pos, 1, 1);
else if (rnd == 2)
S_StartSoundFPM (-1, 0, cl_sfx_ric2, pos, 1, 1);
else
S_StartSoundFPM (-1, 0, cl_sfx_ric3, pos, 1, 1);
}
break;
case TE_GUNSHOT: // bullet hitting wall
pos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
R_RunParticleEffectFPM (pos, vec3_originFPM, 0, 20);
break;
case TE_EXPLOSION: // rocket explosion
pos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
R_ParticleExplosionFPM (pos);
dl = CL_AllocDlightFPM (0);
VectorCopy (pos, dl->origin);
dl->radius = 350;
dl->die = FPM_ADD(FPM_FROMFLOAT(cl.time), FPM_FROMFLOAT(0.5));
dl->decay = 300;
S_StartSoundFPM (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
break;
case TE_TAREXPLOSION: // tarbaby explosion
pos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
R_BlobExplosionFPM (pos);
S_StartSoundFPM (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
break;
case TE_LIGHTNING1: // lightning bolts
CL_ParseBeamFPM (Mod_ForNameFPM("progs/bolt.mdl", true));
break;
case TE_LIGHTNING2: // lightning bolts
CL_ParseBeamFPM (Mod_ForNameFPM("progs/bolt2.mdl", true));
break;
case TE_LIGHTNING3: // lightning bolts
CL_ParseBeamFPM (Mod_ForNameFPM("progs/bolt3.mdl", true));
break;
// PGM 01/21/97
case TE_BEAM: // grappling hook beam
CL_ParseBeamFPM (Mod_ForNameFPM("progs/beam.mdl", true));
break;
// PGM 01/21/97
case TE_LAVASPLASH:
pos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
R_LavaSplashFPM (pos);
break;
case TE_TELEPORT:
pos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
R_TeleportSplashFPM (pos);
break;
case TE_EXPLOSION2: // color mapped explosion
pos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
colorStart = MSG_ReadByte ();
colorLength = MSG_ReadByte ();
R_ParticleExplosion2FPM (pos, colorStart, colorLength);
dl = CL_AllocDlightFPM (0);
VectorCopy (pos, dl->origin);
dl->radius = 350;
dl->die = FPM_ADD(FPM_FROMFLOAT(cl.time), FPM_FROMFLOAT(0.5));
dl->decay = 300;
S_StartSoundFPM (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
break;
#ifdef QUAKE2
case TE_IMPLOSION:
pos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
S_StartSoundFPM (-1, 0, cl_sfx_imp, pos, 1, 1);
break;
case TE_RAILTRAIL:
pos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
pos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
endpos[0] = FPM_FROMFLOAT(MSG_ReadCoord ());
endpos[1] = FPM_FROMFLOAT(MSG_ReadCoord ());
endpos[2] = FPM_FROMFLOAT(MSG_ReadCoord ());
S_StartSoundFPM (-1, 0, cl_sfx_rail, pos, 1, 1);
S_StartSoundFPM (-1, 1, cl_sfx_r_exp3, endpos, 1, 1);
R_RocketTrailFPM (pos, endpos, 0+128);
R_ParticleExplosionFPM (endpos);
dl = CL_AllocDlightFPM (-1);
VectorCopy (endpos, dl->origin);
dl->radius = 350;
dl->die = FPM_ADD(FPM_FROMFLOAT(cl.time), FPM_FROMFLOAT(0.5));
dl->decay = 300;
break;
#endif
default:
Sys_Error ("CL_ParseTEnt: bad type");
}
}
#endif
/*
=================
CL_NewTempEntity
=================
*/
entity_t *CL_NewTempEntity (void)
{
entity_t *ent;
if (cl_numvisedicts == MAX_VISEDICTS)
return NULL;
if (num_temp_entities == MAX_TEMP_ENTITIES)
return NULL;
ent = &cl_temp_entities[num_temp_entities];
Q_memset (ent, 0, sizeof(*ent));
num_temp_entities++;
cl_visedicts[cl_numvisedicts] = ent;
cl_numvisedicts++;
ent->colormap = vid.colormap;
return ent;
}
#ifdef USEFPM
entity_FPM_t *CL_NewTempEntityFPM (void)
{
entity_FPM_t *ent;
if (cl_numvisedicts == MAX_VISEDICTS)
return NULL;
if (num_temp_entities == MAX_TEMP_ENTITIES)
return NULL;
ent = &cl_temp_entitiesFPM[num_temp_entities];
Q_memset (ent, 0, sizeof(*ent));
num_temp_entities++;
cl_visedictsFPM[cl_numvisedicts] = ent;
cl_numvisedicts++;
ent->colormap = vid.colormap;
return ent;
}
#endif
/*
=================
CL_UpdateTEnts
=================
*/
void CL_UpdateTEnts (void)
{
int i;
beam_t *b;
vec3_t dist, org;
float d;
entity_t *ent;
float yaw, pitch;
float forward;
num_temp_entities = 0;
// update lightning
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
{
if (!b->model || b->endtime < cl.time)
continue;
// if coming from the player, update the start position
if (b->entity == cl.viewentity)
{
VectorCopy (cl_entities[cl.viewentity].origin, b->start);
}
// calculate pitch and yaw
VectorSubtract (b->end, b->start, dist);
if (dist[1] == 0 && dist[0] == 0)
{
yaw = 0;
if (dist[2] > 0)
pitch = 90;
else
pitch = 270;
}
else
{
yaw = (float)(int) (atan2(dist[1], dist[0]) * 180 / M_PI);
if (yaw < 0)
yaw += 360;
forward = (float)sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
pitch = (float)(int) (atan2(dist[2], forward) * 180 / M_PI);
if (pitch < 0)
pitch += 360;
}
// add new entities for the lightning
VectorCopy (b->start, org);
d = VectorNormalize(dist);
while (d > 0)
{
ent = CL_NewTempEntity ();
if (!ent)
return;
VectorCopy (org, ent->origin);
ent->model = b->model;
ent->angles[0] = pitch;
ent->angles[1] = yaw;
ent->angles[2] = (float)(rand()%360);
for (i=0 ; i<3 ; i++)
org[i] += dist[i]*30;
d -= 30;
}
}
}
#ifdef USEFPM
void CL_UpdateTEntsFPM (void)
{
int i;
beam_FPM_t *b;
vec3_FPM_t dist, org;
fixedpoint_t d;
entity_FPM_t *ent;
fixedpoint_t yaw, pitch;
fixedpoint_t forward;
num_temp_entities = 0;
// update lightning
for (i=0, b=cl_beamsFPM ; i< MAX_BEAMS ; i++, b++)
{
if (!b->model || b->endtime < clFPM.time)
continue;
// if coming from the player, update the start position
if (b->entity == clFPM.viewentity)
{
VectorCopy (cl_entitiesFPM[clFPM.viewentity].origin, b->start);
}
// calculate pitch and yaw
VectorSubtractFPM (b->end, b->start, dist);
if (dist[1] == 0 && dist[0] == 0)
{
yaw = 0;
if (dist[2] > 0)
pitch = FPM_FROMLONG(90);
else
pitch = FPM_FROMLONG(270);
}
else
{
yaw = FPM_DIV(FPM_MUL(FPM_FROMFLOAT(atan2(dist[1], dist[0])), FPM_FROMLONG(180)), FPM_PI);
if (yaw < 0)
yaw = FPM_ADD(yaw, FPM_FROMLONG(360));
forward = FPM_SQRT(FPM_ADD(FPM_SQR(dist[0]), FPM_SQR(dist[1])));
pitch = FPM_DIV(FPM_MUL(FPM_FROMFLOAT(atan2(dist[2], forward)), FPM_FROMLONG(180)), FPM_PI);
if (pitch < 0)
pitch = FPM_ADD(pitch, FPM_FROMLONG(360));
}
// add new entities for the lightning
VectorCopy (b->start, org);
d = VectorNormalizeFPM(dist);
while (d > 0)
{
ent = CL_NewTempEntityFPM ();
if (!ent)
return;
VectorCopy (org, ent->origin);
ent->model = b->model;
ent->angles[0] = pitch;
ent->angles[1] = yaw;
ent->angles[2] = FPM_FROMLONG(rand()%360);
for (i=0 ; i<3 ; i++)
org[i] = FPM_ADD(org[i], FPM_MUL(dist[i], FPM_FROMLONG(30)));
d = FPM_SUB(d, FPM_FROMLONG(30));
}
}
}
#endif

View File

@@ -0,0 +1,530 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// client.h
typedef struct
{
vec3_t viewangles;
// intended velocities
float forwardmove;
float sidemove;
float upmove;
#ifdef QUAKE2
byte lightlevel;
#endif
} usercmd_t;
typedef struct
{
vec3_FPM_t viewangles;
// intended velocities
fixedpoint_t forwardmove;
fixedpoint_t sidemove;
fixedpoint_t upmove;
#ifdef QUAKE2
byte lightlevel;
#endif
} usercmd_FPM_t;
typedef struct
{
int length;
char map[MAX_STYLESTRING];
} lightstyle_t;
typedef struct
{
char name[MAX_SCOREBOARDNAME];
float entertime;
int frags;
int colors; // two 4 bit fields
byte translations[VID_GRADES*256];
} scoreboard_t;
typedef struct
{
int destcolor[3];
int percent; // 0-256
} cshift_t;
#define CSHIFT_CONTENTS 0
#define CSHIFT_DAMAGE 1
#define CSHIFT_BONUS 2
#define CSHIFT_POWERUP 3
#define NUM_CSHIFTS 4
#define NAME_LENGTH 64
//
// client_state_t should hold all pieces of the client state
//
#define SIGNONS 4 // signon messages to receive before connected
#define MAX_DLIGHTS 32
typedef struct
{
vec3_t origin;
float radius;
float die; // stop lighting after this time
float decay; // drop this each second
float minlight; // don't add when contributing less
int key;
#ifdef QUAKE2
qboolean dark; // subtracts light instead of adding
#endif
} dlight_t;
typedef struct
{
vec3_FPM_t origin;
fixedpoint_t radius;
fixedpoint_t die; // stop lighting after this time
fixedpoint_t decay; // drop this each second
fixedpoint_t minlight; // don't add when contributing less
int key;
#ifdef QUAKE2
qboolean dark; // subtracts light instead of adding
#endif
} dlight_FPM_t;
#define MAX_BEAMS 24
typedef struct
{
int entity;
struct model_s *model;
float endtime;
vec3_t start, end;
} beam_t;
typedef struct
{
int entity;
struct model_FPM_s *model;
float endtime;
vec3_FPM_t start, end;
} beam_FPM_t;
#define MAX_EFRAGS 640
#define MAX_MAPSTRING 2048
#define MAX_DEMOS 8
#define MAX_DEMONAME 16
typedef enum {
ca_dedicated, // a dedicated server with no ability to start a client
ca_disconnected, // full screen console with no connection
ca_connected // valid netcon, talking to a server
} cactive_t;
//
// the client_static_t structure is persistant through an arbitrary number
// of server connections
//
typedef struct
{
cactive_t state;
// personalization data sent to server
char mapstring[MAX_QPATH];
char spawnparms[MAX_MAPSTRING]; // to restart a level
// demo loop control
int demonum; // -1 = don't play demos
char demos[MAX_DEMOS][MAX_DEMONAME]; // when not playing
// demo recording info must be here, because record is started before
// entering a map (and clearing client_state_t)
qboolean demorecording;
qboolean demoplayback;
qboolean timedemo;
int forcetrack; // -1 = use normal cd track
FILE *demofile;
int td_lastframe; // to meter out one message a frame
int td_startframe; // host_framecount at start
float td_starttime; // realtime at second frame of timedemo
// connection information
int signon; // 0 to SIGNONS
struct qsocket_s *netcon;
sizebuf_t message; // writing buffer to send to server
} client_static_t;
extern client_static_t cls;
//
// the client_state_t structure is wiped completely at every
// server signon
//
typedef struct
{
int movemessages; // since connecting to this server
// throw out the first couple, so the player
// doesn't accidentally do something the
// first frame
usercmd_t cmd; // last command sent to the server
// information for local display
int stats[MAX_CL_STATS]; // health, etc
int items; // inventory bit flags
float item_gettime[32]; // cl.time of aquiring item, for blinking
float faceanimtime; // use anim frame if cl.time < this
cshift_t cshifts[NUM_CSHIFTS]; // color shifts for damage, powerups
cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types
// the client maintains its own idea of view angles, which are
// sent to the server each frame. The server sets punchangle when
// the view is temporarliy offset, and an angle reset commands at the start
// of each level and after teleporting.
vec3_t mviewangles[2]; // during demo playback viewangles is lerped
// between these
vec3_t viewangles;
vec3_t mvelocity[2]; // update by server, used for lean+bob
// (0 is newest)
vec3_t velocity; // lerped between mvelocity[0] and [1]
vec3_t punchangle; // temporary offset
// pitch drifting vars
float idealpitch;
float pitchvel;
qboolean nodrift;
float driftmove;
double laststop;
float viewheight;
float crouch; // local amount for smoothing stepups
qboolean paused; // send over by server
qboolean onground;
qboolean inwater;
int intermission; // don't change view angle, full screen, etc
int completed_time; // latched at intermission start
double mtime[2]; // the timestamp of last two messages
double time; // clients view of time, should be between
// servertime and oldservertime to generate
// a lerp point for other data
double oldtime; // previous cl.time, time-oldtime is used
// to decay light values and smooth step ups
float last_received_message; // (realtime) for net trouble icon
//
// information that is static for the entire time connected to a server
//
struct model_s *model_precache[MAX_MODELS];
struct sfx_s *sound_precache[MAX_SOUNDS];
char levelname[40]; // for display on solo scoreboard
int viewentity; // cl_entitites[cl.viewentity] = player
int maxclients;
int gametype;
// refresh related state
struct model_s *worldmodel; // cl_entitites[0].model
struct efrag_s *free_efrags;
int num_entities; // held in cl_entities array
int num_statics; // held in cl_staticentities array
entity_t viewent; // the gun model
int cdtrack, looptrack; // cd audio
// frag scoreboard
scoreboard_t *scores; // [cl.maxclients]
#ifdef QUAKE2
// light level at player's position including dlights
// this is sent back to the server each frame
// architectually ugly but it works
int light_level;
#endif
} client_state_t;
typedef struct
{
int movemessages; // since connecting to this server
// throw out the first couple, so the player
// doesn't accidentally do something the
// first frame
usercmd_FPM_t cmd; // last command sent to the server
// information for local display
int stats[MAX_CL_STATS]; // health, etc
int items; // inventory bit flags
float item_gettime[32]; // cl.time of aquiring item, for blinking
float faceanimtime; // use anim frame if cl.time < this
cshift_t cshifts[NUM_CSHIFTS]; // color shifts for damage, powerups
cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types
// the client maintains its own idea of view angles, which are
// sent to the server each frame. The server sets punchangle when
// the view is temporarliy offset, and an angle reset commands at the start
// of each level and after teleporting.
vec3_FPM_t mviewangles[2]; // during demo playback viewangles is lerped
// between these
vec3_FPM_t viewangles;
vec3_FPM_t mvelocity[2]; // update by server, used for lean+bob
// (0 is newest)
vec3_FPM_t velocity; // lerped between mvelocity[0] and [1]
vec3_FPM_t punchangle; // temporary offset
// pitch drifting vars
fixedpoint_t idealpitch;
fixedpoint_t pitchvel;
qboolean nodrift;
fixedpoint_t driftmove;
double laststop;
fixedpoint_t viewheight;
fixedpoint_t crouch; // local amount for smoothing stepups
qboolean paused; // send over by server
qboolean onground;
qboolean inwater;
int intermission; // don't change view angle, full screen, etc
int completed_time; // latched at intermission start
double mtime[2]; // the timestamp of last two messages
double time; // clients view of time, should be between
// servertime and oldservertime to generate
// a lerp point for other data
double oldtime; // previous cl.time, time-oldtime is used
// to decay light values and smooth step ups
float last_received_message; // (realtime) for net trouble icon
//
// information that is static for the entire time connected to a server
//
struct model_FPM_s *model_precache[MAX_MODELS];
struct sfx_s *sound_precache[MAX_SOUNDS];
char levelname[40]; // for display on solo scoreboard
int viewentity; // cl_entitites[cl.viewentity] = player
int maxclients;
int gametype;
// refresh related state
struct model_FPM_s *worldmodel; // cl_entitites[0].model
struct efrag_FPM_s *free_efrags;
int num_entities; // held in cl_entities array
int num_statics; // held in cl_staticentities array
entity_FPM_t viewent; // the gun model
int cdtrack, looptrack; // cd audio
// frag scoreboard
scoreboard_t *scores; // [cl.maxclients]
#ifdef QUAKE2
// light level at player's position including dlights
// this is sent back to the server each frame
// architectually ugly but it works
int light_level;
#endif
} client_state_FPM_t;
//
// cvars
//
extern cvar_t command;
extern cvar_t cl_name;
extern cvar_t cl_color;
extern cvar_t cl_upspeed;
extern cvar_t cl_forwardspeed;
extern cvar_t cl_backspeed;
extern cvar_t cl_sidespeed;
extern cvar_t cl_movespeedkey;
extern cvar_t cl_yawspeed;
extern cvar_t cl_pitchspeed;
extern cvar_t cl_anglespeedkey;
extern cvar_t cl_autofire;
extern cvar_t cl_showfps;// 2001-11-31 FPS display by QuakeForge/Muff
extern int fps_count;// 2001-11-31 FPS display by QuakeForge/Muff
extern cvar_t cl_shownet;
extern cvar_t cl_nolerp;
extern cvar_t cl_pitchdriftspeed;
extern cvar_t lookspring;
extern cvar_t lookstrafe;
extern cvar_t sensitivity;
extern cvar_t cl_config;
extern cvar_t doublesizeset;
extern cvar_t doublesizestatus;
extern cvar_t m_pitch;
extern cvar_t m_yaw;
extern cvar_t m_forward;
extern cvar_t m_side;
#define MAX_TEMP_ENTITIES 64 // lightning bolts, etc
#define MAX_STATIC_ENTITIES 128 // torches, etc
extern client_state_t cl;
extern client_state_FPM_t clFPM;
// FIXME, allocate dynamically
extern efrag_t cl_efrags[MAX_EFRAGS];
extern entity_t cl_entities[MAX_EDICTS];
extern entity_FPM_t cl_entitiesFPM[MAX_EDICTS];
extern entity_t cl_static_entities[MAX_STATIC_ENTITIES];
extern entity_FPM_t cl_static_entitiesFPM[MAX_STATIC_ENTITIES];
extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
extern dlight_t cl_dlights[MAX_DLIGHTS];
extern dlight_FPM_t cl_dlightsFPM[MAX_DLIGHTS];
extern entity_t cl_temp_entities[MAX_TEMP_ENTITIES];
extern entity_FPM_t cl_temp_entitiesFPM[MAX_TEMP_ENTITIES];
extern beam_t cl_beams[MAX_BEAMS];
extern beam_FPM_t cl_beamsFPM[MAX_BEAMS];
//=============================================================================
//
// cl_main
//
dlight_t *CL_AllocDlight (int key);
dlight_FPM_t *CL_AllocDlightFPM (int key);
void CL_DecayLights (void);
void CL_DecayLightsFPM (void);
void CL_Init (void);
void CL_EstablishConnection (char *host);
void CL_EstablishConnectionFPM (char *host);
void CL_Signon1 (void);
void CL_Signon2 (void);
void CL_Signon3 (void);
void CL_Signon4 (void);
void CL_Disconnect (void);
void CL_DisconnectFPM (void);
void CL_Disconnect_f (void);
void CL_Disconnect_FPM_f (void);
void CL_NextDemo (void);
#define MAX_VISEDICTS 256
extern int cl_numvisedicts;
extern entity_t *cl_visedicts[MAX_VISEDICTS];
extern entity_FPM_t *cl_visedictsFPM[MAX_VISEDICTS];
//
// cl_input
//
typedef struct
{
int down[2]; // key nums holding it down
int state; // low bit is down state
} kbutton_t;
extern kbutton_t in_mlook, in_klook;
extern kbutton_t in_strafe;
extern kbutton_t in_speed;
void CL_InitInput (void);
void CL_SendCmd (void);
void CL_SendMove (usercmd_t *cmd);
void CL_SendMoveFPM (usercmd_FPM_t *cmd);
void CL_ParseTEnt (void);
void CL_ParseTEntFPM (void);
void CL_UpdateTEnts (void);
void CL_UpdateTEntsFPM (void);
void CL_ClearState (void);
void CL_ClearStateFPM (void);
int CL_ReadFromServer (void);
int CL_ReadFromServerFPM (void);
void CL_WriteToServer (usercmd_t *cmd);
void CL_BaseMove (usercmd_t *cmd);
void CL_BaseMoveFPM (usercmd_FPM_t *cmd);
int CL_GetMessage();
float CL_KeyState (kbutton_t *key);
char *Key_KeynumToString (int keynum);
//
// cl_demo.c
//
void CL_StopPlayback (void);
int CL_GetMessageFPM (void);
void CL_Stop_f (void);
void CL_Record_f (void);
void CL_PlayDemo_f (void);
void CL_PlayDemo_silentfail (void);
void CL_TimeDemo_f (void);
//
// cl_parse.c
//
void CL_ParseServerMessage (void);
void CL_ParseServerMessageFPM (void);
void CL_NewTranslation (int slot);
//
// view
//
void V_StartPitchDrift (void);
void V_StopPitchDrift (void);
void V_StopPitchDriftFPM (void);
void V_RenderView (void);
void V_RenderViewFPM (void);
void V_UpdatePalette (void);
void V_Register (void);
void V_ParseDamage (void);
void V_ParseDamageFPM (void);
void V_SetContentsColor (int contents);
void V_SetContentsColorFPM (int contents);
//
// cl_tent
//
void CL_InitTEnts (void);
void CL_SignonReply (void);

View File

@@ -0,0 +1,804 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cmd.c -- Quake script command processing module
#include "quakedef.h"
void Cmd_ForwardToServer (void);
#define MAX_ALIAS_NAME 32
typedef struct cmdalias_s
{
struct cmdalias_s *next;
char name[MAX_ALIAS_NAME];
char *value;
} cmdalias_t;
cmdalias_t *cmd_alias;
int trashtest;
int *trashspot;
qboolean cmd_wait;
//=============================================================================
/*
============
Cmd_Wait_f
Causes execution of the remainder of the command buffer to be delayed until
next frame. This allows commands like:
bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2"
============
*/
void Cmd_Wait_f (void)
{
cmd_wait = true;
}
/*
=============================================================================
COMMAND BUFFER
=============================================================================
*/
sizebuf_t cmd_text;
/*
============
Cbuf_Init
============
*/
void Cbuf_Init (void)
{
SZ_Alloc (&cmd_text, 8192); // space for commands and script files
}
/*
============
Cbuf_AddText
Adds command text at the end of the buffer
============
*/
void Cbuf_AddText (char *text)
{
int l;
l = Q_strlen (text);
if (cmd_text.cursize + l >= cmd_text.maxsize)
{
Con_Printf ("Cbuf_AddText: overflow\n");
return;
}
SZ_Write (&cmd_text, text, Q_strlen (text));
}
/*
============
Cbuf_InsertText
Adds command text immediately after the current command
Adds a \n to the text
FIXME: actually change the command buffer to do less copying
============
*/
void Cbuf_InsertText (char *text)
{
char *temp;
int templen;
// copy off any commands still remaining in the exec buffer
templen = cmd_text.cursize;
if (templen)
{
temp = Z_Malloc (templen);
Q_memcpy (temp, cmd_text.data, templen);
SZ_Clear (&cmd_text);
}
else
temp = NULL; // shut up compiler
// add the entire text of the file
Cbuf_AddText (text);
// add the copied off data
if (templen)
{
SZ_Write (&cmd_text, temp, templen);
Z_Free (temp);
}
}
/*
============
Cbuf_Execute
============
*/
void Cbuf_Execute (void)
{
int i;
char *text;
char line[1024];
int quotes;
while (cmd_text.cursize)
{
// find a \n or ; line break
text = (char *)cmd_text.data;
quotes = 0;
for (i=0 ; i< cmd_text.cursize ; i++)
{
if (text[i] == '"')
quotes++;
if ( !(quotes&1) && text[i] == ';')
break; // don't break if inside a quoted string
if (text[i] == '\n')
break;
}
Q_memcpy (line, text, i);
line[i] = 0;
// delete the text from the command buffer and move remaining commands down
// this is necessary because commands (exec, alias) can insert data at the
// beginning of the text buffer
if (i == cmd_text.cursize)
cmd_text.cursize = 0;
else
{
i++;
cmd_text.cursize -= i;
Q_memcpy (text, text+i, cmd_text.cursize);
}
// execute the command line
Cmd_ExecuteString (line, src_command);
if (cmd_wait)
{ // skip out while text still remains in buffer, leaving it
// for next frame
cmd_wait = false;
break;
}
}
}
/*
==============================================================================
SCRIPT COMMANDS
==============================================================================
*/
/*
===============
Cmd_StuffCmds_f
Adds command line parameters as script statements
Commands lead with a +, and continue until a - or another +
quake +prog jctest.qp +cmd amlev1
quake -nosound +cmd amlev1
===============
*/
void Cmd_StuffCmds_f (void)
{
int i, j;
int s;
char *text, *build, c;
if (Cmd_Argc () != 1)
{
Con_Printf ("stuffcmds : execute command line parameters\n");
return;
}
// build the combined string to parse from
s = 0;
for (i=1 ; i<com_argc ; i++)
{
if (!com_argv[i])
continue; // NEXTSTEP nulls out -NXHost
s += Q_strlen (com_argv[i]) + 1;
}
if (!s)
return;
text = Z_Malloc (s+1);
text[0] = 0;
for (i=1 ; i<com_argc ; i++)
{
if (!com_argv[i])
continue; // NEXTSTEP nulls out -NXHost
Q_strcat (text,com_argv[i]);
if (i != com_argc-1)
Q_strcat (text, " ");
}
// pull out the commands
build = Z_Malloc (s+1);
build[0] = 0;
for (i=0 ; i<s-1 ; i++)
{
if (text[i] == '+')
{
i++;
for (j=i ; (text[j] != '+') && (text[j] != '-') && (text[j] != 0) ; j++)
;
c = text[j];
text[j] = 0;
Q_strcat (build, text+i);
Q_strcat (build, "\n");
text[j] = c;
i = j-1;
}
}
if (build[0])
Cbuf_InsertText (build);
Z_Free (text);
Z_Free (build);
}
/*
===============
Cmd_Exec_f
===============
*/
void Cmd_Exec_f (void)
{
char *f;
int mark;
if (Cmd_Argc () != 2)
{
Con_Printf ("exec <filename> : execute a script file\n");
return;
}
mark = Hunk_LowMark ();
f = (char *)COM_LoadHunkFile (Cmd_Argv(1));
if (!f)
{
Con_Printf ("couldn't exec %s\n",Cmd_Argv(1));
return;
}
Con_Printf ("execing %s\n",Cmd_Argv(1));
Cbuf_InsertText (f);
Hunk_FreeToLowMark (mark);
}
/*
===============
Cmd_Echo_f
Just prints the rest of the line to the console
===============
*/
void Cmd_Echo_f (void)
{
int i;
for (i=1 ; i<Cmd_Argc() ; i++)
Con_Printf ("%s ",Cmd_Argv(i));
Con_Printf ("\n");
}
/*
===============
Cmd_Alias_f
Creates a new command that executes a command string (possibly ; seperated)
===============
*/
char *CopyString (char *in)
{
char *out;
out = Z_Malloc (strlen(in)+1);
strcpy (out, in);
return out;
}
void Cmd_Alias_f (void)
{
cmdalias_t *a;
char cmd[1024];
int i, c;
char *s;
if (Cmd_Argc() == 1)
{
Con_Printf ("Current alias commands:\n");
for (a = cmd_alias ; a ; a=a->next)
Con_Printf ("%s : %s\n", a->name, a->value);
return;
}
s = Cmd_Argv(1);
if (strlen(s) >= MAX_ALIAS_NAME)
{
Con_Printf ("Alias name is too long\n");
return;
}
// if the alias allready exists, reuse it
for (a = cmd_alias ; a ; a=a->next)
{
if (!strcmp(s, a->name))
{
Z_Free (a->value);
break;
}
}
if (!a)
{
a = Z_Malloc (sizeof(cmdalias_t));
a->next = cmd_alias;
cmd_alias = a;
}
strcpy (a->name, s);
// copy the rest of the command line
cmd[0] = 0; // start out with a null string
c = Cmd_Argc();
for (i=2 ; i< c ; i++)
{
strcat (cmd, Cmd_Argv(i));
if (i != c)
strcat (cmd, " ");
}
strcat (cmd, "\n");
a->value = CopyString (cmd);
}
/*
=============================================================================
COMMAND EXECUTION
=============================================================================
*/
typedef struct cmd_function_s
{
struct cmd_function_s *next;
char *name;
xcommand_t function;
} cmd_function_t;
#define MAX_ARGS 80
static int cmd_argc;
static char *cmd_argv[MAX_ARGS];
static char *cmd_null_string = "";
static char *cmd_args = NULL;
cmd_source_t cmd_source;
static cmd_function_t *cmd_functions; // possible commands to execute
// 2000-01-09 CmdList command by Maddes start
/*
========
Cmd_List
========
*/
void Cmd_List_f (void)
{
cmd_function_t *cmd;
char *partial;
int len;
int count;
if (Cmd_Argc() > 1)
{
partial = Cmd_Argv (1);
len = Q_strlen(partial);
}
else
{
partial = NULL;
len = 0;
}
count=0;
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
{
if (partial && Q_strncmp (partial,cmd->name, len))
{
continue;
}
Con_Printf ("\"%s\"\n", cmd->name);
count++;
}
Con_Printf ("%i command(s)", count);
if (partial)
{
Con_Printf (" beginning with \"%s\"", partial);
}
Con_Printf ("\n");
}
// 2000-01-09 CmdList command by Maddes end
/*
============
Cmd_Init
============
*/
void Cmd_Init (void)
{
//
// register our commands
//
Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f);
Cmd_AddCommand ("exec",Cmd_Exec_f);
Cmd_AddCommand ("echo",Cmd_Echo_f);
Cmd_AddCommand ("alias",Cmd_Alias_f);
Cmd_AddCommand ("cmd", Cmd_ForwardToServer);
Cmd_AddCommand ("wait", Cmd_Wait_f);
Cmd_AddCommand ("cmdlist", Cmd_List_f); // 2000-01-09 CmdList command by Maddes
Cmd_AddCommand ("cvarlist", Cvar_List_f); // 2000-01-09 CvarList command by Maddes
}
/*
============
Cmd_Argc
============
*/
int Cmd_Argc (void)
{
return cmd_argc;
}
/*
============
Cmd_Argv
============
*/
char *Cmd_Argv (int arg)
{
if ( (unsigned)arg >= (unsigned)cmd_argc )
return cmd_null_string;
return cmd_argv[arg];
}
/*
============
Cmd_Args
============
*/
char *Cmd_Args (void)
{
return cmd_args;
}
/*
============
Cmd_TokenizeString
Parses the given string into command line tokens.
============
*/
void Cmd_TokenizeString (char *text)
{
int i;
// clear the args from the last string
for (i=0 ; i<cmd_argc ; i++)
Z_Free (cmd_argv[i]);
cmd_argc = 0;
cmd_args = NULL;
while (1)
{
// skip whitespace up to a /n
while (*text && *text <= ' ' && *text != '\n')
{
text++;
}
if (*text == '\n')
{ // a newline seperates commands in the buffer
text++;
break;
}
if (!*text)
return;
if (cmd_argc == 1)
cmd_args = text;
text = COM_Parse (text);
if (!text)
return;
if (cmd_argc < MAX_ARGS)
{
cmd_argv[cmd_argc] = Z_Malloc (Q_strlen(com_token)+1);
Q_strcpy (cmd_argv[cmd_argc], com_token);
cmd_argc++;
}
}
}
/*
============
Cmd_AddCommand
============
*/
void Cmd_AddCommand (char *cmd_name, xcommand_t function)
{
cmd_function_t *cmd;
if (host_initialized) // because hunk allocation would get stomped
Sys_Error ("Cmd_AddCommand after host_initialized");
// fail if the command is a variable name
if (Cvar_VariableString(cmd_name)[0])
{
Con_Printf ("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
return;
}
// fail if the command already exists
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
{
if (!Q_strcmp (cmd_name, cmd->name))
{
Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name);
return;
}
}
cmd = Hunk_Alloc (sizeof(cmd_function_t));
cmd->name = cmd_name;
cmd->function = function;
cmd->next = cmd_functions;
cmd_functions = cmd;
}
/*
============
Cmd_Exists
============
*/
qboolean Cmd_Exists (char *cmd_name)
{
cmd_function_t *cmd;
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
{
if (!Q_strcmp (cmd_name,cmd->name))
return true;
}
return false;
}
/*
============
Cmd_CompleteCommand
============
*/
char *Cmd_CompleteCommand (char *partial) {
cmd_function_t *cmd;
int len;
cmdalias_t *a; // Added for alias cmd completion
len = Q_strlen(partial);
if (!len)
return NULL;
// check functions
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
if (!Q_strncmp (partial,cmd->name, len))
return cmd->name;
//The next For loop adds alias cmd completion
for (a=cmd_alias ; a ; a=a->next)
if (!Q_strncmp (partial, a->name, len))
return a->name;
return NULL;
}
/*
============
Cmd_ExecuteString
A complete command line has been parsed, so try to execute it
FIXME: lookupnoadd the token to speed search?
============
*/
void Cmd_ExecuteString (char *text, cmd_source_t src)
{
cmd_function_t *cmd;
cmdalias_t *a;
cmd_source = src;
Cmd_TokenizeString (text);
// sprintf(gpstr, "cmdexec: %s", text);
// GpError(gpstr,1);
// execute the command line
if (!Cmd_Argc())
return; // no tokens
// check functions
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
{
if (!Q_strcasecmp (cmd_argv[0],cmd->name))
{
cmd->function ();
return;
}
}
// check alias
for (a=cmd_alias ; a ; a=a->next)
{
if (!Q_strcasecmp (cmd_argv[0], a->name))
{
Cbuf_InsertText (a->value);
return;
}
}
// check cvars
if (!Cvar_Command ())
Con_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0));
}
/*
===================
Cmd_ForwardToServer
Sends the entire command line over to the server
===================
*/
void Cmd_ForwardToServer (void)
{
if (cls.state != ca_connected)
{
Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
return;
}
if (cls.demoplayback)
return; // not really connected
MSG_WriteByte (&cls.message, clc_stringcmd);
if (Q_strcasecmp(Cmd_Argv(0), "cmd") != 0)
{
SZ_Print (&cls.message, Cmd_Argv(0));
SZ_Print (&cls.message, " ");
}
if (Cmd_Argc() > 1)
SZ_Print (&cls.message, Cmd_Args());
else
SZ_Print (&cls.message, "\n");
}
/*
================
Cmd_CheckParm
Returns the position (1 to argc-1) in the command's argument list
where the given parameter apears, or 0 if not present
================
*/
int Cmd_CheckParm (char *parm)
{
int i;
if (!parm)
Sys_Error ("Cmd_CheckParm: NULL");
for (i = 1; i < Cmd_Argc (); i++)
if (! Q_strcasecmp (parm, Cmd_Argv (i)))
return i;
return 0;
}

View File

@@ -0,0 +1,120 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cmd.h -- Command buffer and command execution
//===========================================================================
/*
Any number of commands can be added in a frame, from several different sources.
Most commands come from either keybindings or console line input, but remote
servers can also send across commands and entire text files can be execed.
The + command line options are also added to the command buffer.
The game starts with a Cbuf_AddText ("exec quake.rc\n"); Cbuf_Execute ();
*/
void Cbuf_Init (void);
// allocates an initial text buffer that will grow as needed
void Cbuf_AddText (char *text);
// as new commands are generated from the console or keybindings,
// the text is added to the end of the command buffer.
void Cbuf_InsertText (char *text);
// when a command wants to issue other commands immediately, the text is
// inserted at the beginning of the buffer, before any remaining unexecuted
// commands.
void Cbuf_Execute (void);
// Pulls off \n terminated lines of text from the command buffer and sends
// them through Cmd_ExecuteString. Stops when the buffer is empty.
// Normally called once per frame, but may be explicitly invoked.
// Do not call inside a command function!
//===========================================================================
/*
Command execution takes a null terminated string, breaks it into tokens,
then searches for a command or variable that matches the first token.
Commands can come from three sources, but the handler functions may choose
to dissallow the action or forward it to a remote server if the source is
not apropriate.
*/
typedef void (*xcommand_t) (void);
typedef enum
{
src_client, // came in over a net connection as a clc_stringcmd
// host_client will be valid during this state.
src_command // from the command buffer
} cmd_source_t;
extern cmd_source_t cmd_source;
void Cmd_Init (void);
void Cmd_AddCommand (char *cmd_name, xcommand_t function);
// called by the init functions of other parts of the program to
// register commands and functions to call for them.
// The cmd_name is referenced later, so it should not be in temp memory
qboolean Cmd_Exists (char *cmd_name);
// used by the cvar code to check for cvar / command name overlap
char *Cmd_CompleteCommand (char *partial);
// attempts to match a partial command for automatic command line completion
// returns NULL if nothing fits
int Cmd_Argc (void);
char *Cmd_Argv (int arg);
char *Cmd_Args (void);
// The functions that execute commands get their parameters with these
// functions. Cmd_Argv () will return an empty string, not a NULL
// if arg > argc, so string operations are allways safe.
int Cmd_CheckParm (char *parm);
// Returns the position (1 to argc-1) in the command's argument list
// where the given parameter apears, or 0 if not present
void Cmd_TokenizeString (char *text);
// Takes a null terminated string. Does not need to be /n terminated.
// breaks the string up into arg tokens.
void Cmd_ExecuteString (char *text, cmd_source_t src);
// Parses a single line of text into arguments and tries to execute it.
// The text can come from the command buffer, a remote client, or stdin.
void Cmd_ForwardToServer (void);
// adds the current command line as a clc_stringcmd to the client message.
// things like godmode, noclip, etc, are commands directed to the server,
// so when they are typed in at the console, they will need to be forwarded.
void Cmd_Print (char *text);
// used by command functions to send output to either the graphics console or
// passed as a print message to the client

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,198 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// comndef.h -- general definitions
#ifndef _COMMON_H_
#define _COMMON_H_
//#include "zlib.h"
//#ifndef BYTE_DEFINED
typedef unsigned char byte;
//#define BYTE_DEFINED 1
//#endif
#undef true
#undef false
typedef enum {false, true} qboolean;
int doublesize;
//============================================================================
typedef struct sizebuf_s
{
qboolean allowoverflow; // if false, do a Sys_Error
qboolean overflowed; // set to true if the buffer size failed
byte *data;
int maxsize;
int cursize;
} sizebuf_t;
void SZ_Alloc (sizebuf_t *buf, int startsize);
void SZ_Free (sizebuf_t *buf);
void SZ_Clear (sizebuf_t *buf);
void *SZ_GetSpace (sizebuf_t *buf, int length);
void SZ_Write (sizebuf_t *buf, void *data, int length);
void SZ_Print (sizebuf_t *buf, char *data); // strcats onto the sizebuf
//============================================================================
typedef struct link_s
{
struct link_s *prev, *next;
} link_t;
void ClearLink (link_t *l);
void RemoveLink (link_t *l);
void InsertLinkBefore (link_t *l, link_t *before);
void InsertLinkAfter (link_t *l, link_t *after);
// (type *)STRUCT_FROM_LINK(link_t *link, type, member)
// ent = STRUCT_FROM_LINK(link,entity_t,order)
// FIXME: remove this mess!
#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m)))
//============================================================================
#ifndef NULL
#define NULL ((void *)0)
#endif
#define Q_MAXCHAR ((char)0x7f)
#define Q_MAXSHORT ((short)0x7fff)
#define Q_MAXINT ((int)0x7fffffff)
#define Q_MAXLONG ((int)0x7fffffff)
#define Q_MAXFLOAT ((int)0x7fffffff)
#define Q_MINCHAR ((char)0x80)
#define Q_MINSHORT ((short)0x8000)
#define Q_MININT ((int)0x80000000)
#define Q_MINLONG ((int)0x80000000)
#define Q_MINFLOAT ((int)0x7fffffff)
//============================================================================
extern qboolean bigendien;
extern short (*BigShort) (short l);
extern short (*LittleShort) (short l);
extern int (*BigLong) (int l);
extern int (*LittleLong) (int l);
extern float (*BigFloat) (float l);
extern float (*LittleFloat) (float l);
//============================================================================
void MSG_WriteChar (sizebuf_t *sb, int c);
void MSG_WriteByte (sizebuf_t *sb, int c);
void MSG_WriteShort (sizebuf_t *sb, int c);
void MSG_WriteLong (sizebuf_t *sb, int c);
void MSG_WriteFloat (sizebuf_t *sb, float f);
void MSG_WriteString (sizebuf_t *sb, char *s);
void MSG_WriteCoord (sizebuf_t *sb, float f);
//void MSG_WriteCoordFPM (sizebuf_t *sb, fixedpoint_t f);
void MSG_WriteAngle (sizebuf_t *sb, float f);
//void MSG_WriteAngleFPM (sizebuf_t *sb, fixedpoint_t f);
extern int msg_readcount;
extern qboolean msg_badread; // set if a read goes beyond end of message
void MSG_BeginReading (void);
int MSG_ReadChar (void);
int MSG_ReadByte (void);
int MSG_ReadShort (void);
int MSG_ReadLong (void);
float MSG_ReadFloat (void);
char *MSG_ReadString (void);
float MSG_ReadCoord (void);
float MSG_ReadAngle (void);
//============================================================================
void Q_memset (void *dest, int fill, int count);
/*__inline*/ // inline static void Q_memcpy (void *dest, void *src, int count) {gm_memcpy(dest, src, count);};
void Q_memcpy (void *dest, void *src, int count);
int Q_memcmp (void *m1, void *m2, int count);
void Q_strcpy (char *dest, char *src);
void Q_strncpy (char *dest, char *src, int count);
int Q_strlen (char *str);
char *Q_strrchr (char *s, char c);
void Q_strcat (char *dest, char *src);
int Q_strcmp (char *s1, char *s2);
int Q_strncmp (char *s1, char *s2, int count);
int Q_strcasecmp (char *s1, char *s2);
int Q_strncasecmp (char *s1, char *s2, int n);
int Q_atoi (char *str);
float Q_atof (char *str);
void Q_strncpyz (char *dest, char *src, size_t size);
//============================================================================
extern char com_token[1024];
extern qboolean com_eof;
char *COM_Parse (char *data);
extern int com_argc;
extern char **com_argv;
int COM_CheckParm (char *parm);
void COM_Init (char *path);
void COM_InitArgv (int argc, char **argv);
char *COM_SkipPath (char *pathname);
void COM_StripExtension (char *in, char *out);
void COM_FileBase (char *in, char *out);
void COM_DefaultExtension (char *path, char *extension);
char *va(char *format, ...);
// does a varargs printf into a temp buffer
//============================================================================
extern int com_filesize;
struct cache_user_s;
extern char com_gamedir[MAX_OSPATH];
void COM_WriteFile (char *filename, void *data, int len);
int COM_OpenFile (char *filename, int *hndl);
int COM_FOpenFile (char *filename, FILE **file);
void COM_CloseFile (int h);
byte *COM_LoadStackFile (char *path, void *buffer, int bufsize);
byte *COM_LoadTempFile (char *path);
byte *COM_LoadHunkFile (char *path);
void COM_LoadCacheFile (char *path, struct cache_user_s *cu);
extern struct cvar_s registered;
extern qboolean standard_quake, rogue, hipnotic;
#endif // _COMMON_H_

View File

@@ -0,0 +1,641 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// console.c
#ifdef NeXT
#include <libc.h>
#endif
#ifndef _MSC_VER
#include <unistd.h>
#endif
//#include <fcntl.h>
#include "quakedef.h"
extern int min_vid_width;
int con_linewidth;
float con_cursorspeed = 4;
#define CON_TEXTSIZE 16384
qboolean con_forcedup; // because no entities to refresh
int con_totallines; // total lines in console scrollback
int con_backscroll; // lines up from bottom to display
int con_current; // where next message will be printed
int con_x; // offset in current line for next print
char *con_text=0;
cvar_t con_notifytime = {"con_notifytime","3"}; //seconds
#define NUM_CON_TIMES 4
float con_times[NUM_CON_TIMES]; // realtime time the line was generated
// for transparent notify lines
int con_vislines;
qboolean con_debuglog;
#define MAXCMDLINE 256
extern char key_lines[32][MAXCMDLINE];
extern int edit_line;
extern int key_linepos;
qboolean con_initialized;
int con_notifylines; // scan lines to clear for notify lines
extern void M_Menu_Main_f (void);
/*
================
Con_ToggleConsole_f
================
*/
void Con_ToggleConsole_f (void) {
if (key_dest == key_console) {
if (cls.state == ca_connected) {
key_dest = key_game;
key_lines[edit_line][1] = 0;
key_linepos = 1;
} else {
M_Menu_Main_f ();
}
} else {
key_dest = key_console;
}
SCR_EndLoadingPlaque ();
Q_memset (con_times, 0, sizeof(con_times));
}
/*
================
Con_Clear_f
================
*/
void Con_Clear_f (void) {
if (con_text)
Q_memset (con_text, ' ', CON_TEXTSIZE);
}
/*
================
Con_ClearNotify
================
*/
void Con_ClearNotify (void) {
int i;
for (i=0 ; i<NUM_CON_TIMES ; i++)
con_times[i] = 0;
}
/*
================
Con_MessageMode_f
================
*/
extern qboolean team_message;
void Con_MessageMode_f (void) {
key_dest = key_message;
team_message = false;
}
/*
================
Con_MessageMode2_f
================
*/
void Con_MessageMode2_f (void) {
key_dest = key_message;
team_message = true;
}
/*
================
Con_CheckResize
If the line width has changed, reformat the buffer.
================
*/
void Con_CheckResize (void) {
int i, j, width, oldwidth, oldtotallines, numlines, numchars;
char tbuf[CON_TEXTSIZE];
width = (vid.width >> 3) - 2;
if (width == con_linewidth)
return;
if (width < 1) // video hasn't been initialized yet
{
width = 38;
con_linewidth = width;
con_totallines = CON_TEXTSIZE / con_linewidth;
Q_memset (con_text, ' ', CON_TEXTSIZE);
}
else
{
oldwidth = con_linewidth;
con_linewidth = width;
oldtotallines = con_totallines;
con_totallines = CON_TEXTSIZE / con_linewidth;
numlines = oldtotallines;
if (con_totallines < numlines)
numlines = con_totallines;
numchars = oldwidth;
if (con_linewidth < numchars)
numchars = con_linewidth;
Q_memcpy (tbuf, con_text, CON_TEXTSIZE);
Q_memset (con_text, ' ', CON_TEXTSIZE);
for (i=0 ; i<numlines ; i++)
{
for (j=0 ; j<numchars ; j++)
{
con_text[(con_totallines - 1 - i) * con_linewidth + j] =
tbuf[((con_current - i + oldtotallines) %
oldtotallines) * oldwidth + j];
}
}
Con_ClearNotify ();
}
con_backscroll = 0;
con_current = con_totallines - 1;
}
/*
================
Con_Init
================
*/
void Con_Init (void)
{
#define MAXGAMEDIRLEN 1000
char temp[MAXGAMEDIRLEN+1];
char *t2 = "/qconsole.log";
con_debuglog = COM_CheckParm("-condebug");
/* if (con_debuglog)
{
if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (t2)))
{
sprintf (temp, "%s%s", com_gamedir, t2);
unlink (temp);
}
}
*/
con_text = Hunk_AllocName (CON_TEXTSIZE, "context");
Q_memset (con_text, ' ', CON_TEXTSIZE);
con_linewidth = -1;
Con_CheckResize ();
Con_Printf ("Console initialized.\n");
//
// register our commands
//
Cvar_RegisterVariable (&con_notifytime);
Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
Cmd_AddCommand ("messagemode", Con_MessageMode_f);
Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
Cmd_AddCommand ("clear", Con_Clear_f);
con_initialized = true;
}
/*
===============
Con_Linefeed
===============
*/
void Con_Linefeed (void)
{
con_x = 0;
con_current++;
Q_memset (&con_text[(con_current%con_totallines)*con_linewidth]
, ' ', con_linewidth);
}
/*
================
Con_Print
Handles cursor positioning, line wrapping, etc
All console printing must go through this in order to be logged to disk
If no console is visible, the notify window will pop up.
================
*/
void Con_Print (char *txt)
{
int y;
int c, l;
static int cr;
int mask;
con_backscroll = 0;
if (txt[0] == 1)
{
mask = 128; // go to colored text
S_LocalSound ("misc/talk.wav");
// play talk wav
txt++;
}
else if (txt[0] == 2)
{
mask = 128; // go to colored text
txt++;
}
else
mask = 0;
while ( (c = *txt) )
{
// count word length
for (l=0 ; l< con_linewidth ; l++)
if ( txt[l] <= ' ')
break;
// word wrap
if (l != con_linewidth && (con_x + l > con_linewidth) )
con_x = 0;
txt++;
if (cr)
{
con_current--;
cr = false;
}
if (!con_x)
{
Con_Linefeed ();
// mark time for transparent overlay
if (con_current >= 0)
con_times[con_current % NUM_CON_TIMES] = realtime;
}
switch (c)
{
case '\n':
con_x = 0;
break;
case '\r':
con_x = 0;
cr = 1;
break;
default: // display character and advance
y = con_current % con_totallines;
con_text[y*con_linewidth+con_x] = c | mask;
con_x++;
if (con_x >= con_linewidth)
con_x = 0;
break;
}
}
}
/*
================
Con_DebugLog
================
*/
void Con_DebugLog(char *file, char *fmt, ...)
{
va_list argptr;
static char data[1024];
FILE *fd;
long old;
/*
va_start(argptr, fmt);
vsprintf(data, fmt, argptr);
va_end(argptr);
fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666);
write(fd, data, strlen(data));
close(fd);
*/
}
/*
================
Con_Printf
Handles cursor positioning, line wrapping, etc
================
*/
#define MAXPRINTMSG 4096
// FIXME: make a buffer size safe vsprintf?
void Con_Printf (char *fmt, ...)
{
va_list argptr;
char msg[MAXPRINTMSG];
static qboolean inupdate;
va_start (argptr,fmt);
vsprintf (msg,fmt,argptr);
va_end (argptr);
// also echo to debugging console
Sys_Printf ("%s", msg); // also echo to debugging console
// log all messages to file
if (con_debuglog)
Con_DebugLog(va("%s\\qconsole.log",com_gamedir), "%s", msg);
if (!con_initialized)
return;
if (cls.state == ca_dedicated)
return; // no graphics mode
// write it to the scrollable buffer
Con_Print (msg);
// update the screen if the console is displayed
if (cls.signon != SIGNONS && !scr_disabled_for_loading )
{
// protect against infinite loop if something in SCR_UpdateScreen calls
// Con_Printd
if (!inupdate)
{
inupdate = true;
SCR_UpdateScreen ();
inupdate = false;
}
}
}
/*
================
Con_DPrintf
A Con_Printf that only shows up if the "developer" cvar is set
================
*/
void Con_DPrintf (char *fmt, ...)
{
va_list argptr;
char msg[MAXPRINTMSG];
if (!developer.value)
return; // don't confuse non-developers with techie stuff...
va_start (argptr,fmt);
vsprintf (msg,fmt,argptr);
va_end (argptr);
Con_Printf ("%s", msg);
}
/*
==================
Con_SafePrintf
Okay to call even when the screen can't be updated
==================
*/
void Con_SafePrintf (char *fmt, ...)
{
va_list argptr;
char msg[1024];
int temp;
va_start (argptr,fmt);
vsprintf (msg,fmt,argptr);
va_end (argptr);
temp = scr_disabled_for_loading;
scr_disabled_for_loading = true;
Con_Printf ("%s", msg);
scr_disabled_for_loading = temp;
}
/*
==============================================================================
DRAWING
==============================================================================
*/
/*
================
Con_DrawInput
The input line scrolls horizontally if typing goes beyond the right edge
================
*/
void Con_DrawInput (void)
{
int y;
int i;
char *text;
if (key_dest != key_console && !con_forcedup)
return; // don't draw anything
text = key_lines[edit_line];
// add the cursor frame
text[key_linepos] = 10+((int)(realtime*con_cursorspeed)&1);
// fill out remainder with spaces
for (i=key_linepos+1 ; i< con_linewidth ; i++)
text[i] = ' ';
// prestep if horizontally scrolling
if (key_linepos >= con_linewidth)
text += 1 + key_linepos - con_linewidth;
// draw it
y = con_vislines-16;
for (i=0 ; i<con_linewidth ; i++)
Draw_Character ( (i+1)<<3, con_vislines - 16, text[i]);
// remove cursor
key_lines[edit_line][key_linepos] = 0;
}
/*
================
Con_DrawNotify
Draws the last few lines of output transparently over the game top
================
*/
void Con_DrawNotify (void)
{
int x, v;
char *text;
int i;
float time;
extern char chat_buffer[];
v = 0;
for (i= con_current-NUM_CON_TIMES+1 ; i<=con_current ; i++)
{
if (i < 0)
continue;
time = con_times[i % NUM_CON_TIMES];
if (time == 0)
continue;
time = realtime - time;
if (time > con_notifytime.value)
continue;
text = con_text + (i % con_totallines)*con_linewidth;
clearnotify = 0;
scr_copytop = 1;
for (x = 0 ; x < con_linewidth ; x++)
Draw_Character ( (x+1)<<3, v, text[x]);
v += 8;
}
if (key_dest == key_message)
{
clearnotify = 0;
scr_copytop = 1;
x = 0;
Draw_String (8, v, "say:");
while(chat_buffer[x])
{
Draw_Character ( (x+5)<<3, v, chat_buffer[x]);
x++;
}
Draw_Character ( (x+5)<<3, v, 10+((int)(realtime*con_cursorspeed)&1));
v += 8;
}
if (v > con_notifylines)
con_notifylines = v;
}
/*
================
Con_DrawConsole
Draws the console with the solid background
The typing input line at the bottom should only be drawn if typing is allowed
================
*/
void Con_DrawConsole (int lines, qboolean drawinput) {
int i, x, y, con_x, con_y;
int rows;
char *text;
int j;
if (lines <= 0)
return;
// draw the background
Draw_ConsoleBackground (lines);
// draw the text
con_vislines = lines;
rows = (lines-16)>>3; // rows of text to draw
y = lines - 16 - (rows<<3); // may start slightly negative
for (i= con_current - rows + 1 ; i<=con_current ; i++, y+=8 ) {
j = i - con_backscroll;
if (j<0)
j = 0;
text = con_text + (j % con_totallines)*con_linewidth;
for (x=0 ; x<con_linewidth ; x++)
Draw_Character ( (x+1)<<3, y, text[x]);
}
// draw the input prompt, user text, and cursor if desired
if (drawinput)
Con_DrawInput ();
}
/*
==================
Con_NotifyBox
==================
*/
void Con_NotifyBox (char *text)
{
double t1, t2;
// during startup for sound / cd warnings
Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
Con_Printf (text);
Con_Printf ("Press a key.\n");
Con_Printf("\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
key_count = -2; // wait for a key down and up
key_dest = key_console;
do
{
t1 = Sys_FloatTime ();
SCR_UpdateScreen ();
Sys_SendKeyEvents ();
t2 = Sys_FloatTime ();
realtime += t2-t1; // make the cursor blink
} while (key_count < 0);
Con_Printf ("\n");
key_dest = key_game;
realtime = 0; // put the cursor back to invisible
}

View File

@@ -0,0 +1,46 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//
// console
//
extern int con_totallines;
extern int con_backscroll;
extern qboolean con_forcedup; // because no entities to refresh
extern qboolean con_initialized;
extern byte *con_chars;
extern int con_notifylines; // scan lines to clear for notify lines
void Con_DrawCharacter (int cx, int line, int num);
void Con_CheckResize (void);
void Con_Init (void);
void Con_DrawConsole (int lines, qboolean drawinput);
void Con_Print (char *txt);
void Con_Printf (char *fmt, ...);
void Con_DPrintf (char *fmt, ...);
void Con_SafePrintf (char *fmt, ...);
void Con_Clear_f (void);
void Con_DrawNotify (void);
void Con_ClearNotify (void);
void Con_ToggleConsole_f (void);
void Con_NotifyBox (char *text); // during startup for sound / cd warnings

View File

@@ -0,0 +1,156 @@
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include "cpu.h"
/* Define this to the CPU frequency */
#define CPU_FREQ 336000000 /* CPU clock: 336 MHz */
#define CFG_EXTAL 12000000 /* EXT clock: 12 Mhz */
// SDRAM Timings, unit: ns
#define SDRAM_TRAS 45 /* RAS# Active Time */
#define SDRAM_RCD 20 /* RAS# to CAS# Delay */
#define SDRAM_TPC 20 /* RAS# Precharge Time */
#define SDRAM_TRWL 7 /* Write Latency Time */
#define SDRAM_TREF 15625 /* Refresh period: 4096 refresh cycles/64ms */
//#define SDRAM_TREF 7812 /* Refresh period: 8192 refresh cycles/64ms */
#include "jz4740.h"
static unsigned long jz_dev=0;
static volatile unsigned long *jz_cpmregl, *jz_emcregl;
volatile unsigned short *jz_emcregs;
static inline int sdram_convert(unsigned int pllin,unsigned int *sdram_freq)
{
register unsigned int ns, tmp;
ns = 1000000000 / pllin;
/* Set refresh registers */
tmp = SDRAM_TREF/ns;
tmp = tmp/64 + 1;
if (tmp > 0xff) tmp = 0xff;
*sdram_freq = tmp;
return 0;
}
static int
pll_init(unsigned int clock)
{
register unsigned int cfcr, plcr1;
unsigned int sdramclock = 0;
int n2FR[33] = {
0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
9
};
//int div[5] = {1, 4, 4, 4, 4}; /* divisors of I:S:P:L:M */
int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */
int nf, pllout2;
cfcr = CPM_CPCCR_CLKOEN |
(n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
(n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
(n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
(n2FR[div[3]] << CPM_CPCCR_MDIV_BIT) |
(n2FR[div[4]] << CPM_CPCCR_LDIV_BIT);
pllout2 = (cfcr & CPM_CPCCR_PCS) ? clock : (clock / 2);
/* Init UHC clock */
// REG_CPM_UHCCDR = pllout2 / 48000000 - 1;
jz_cpmregl[0x6C>>2] = pllout2 / 48000000 - 1;
nf = clock * 2 / CFG_EXTAL;
plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
(0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */
(0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */
(0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
CPM_CPPCR_PLLEN; /* enable PLL */
/* init PLL */
// REG_CPM_CPCCR = cfcr;
// REG_CPM_CPPCR = plcr1;
jz_cpmregl[0] = cfcr;
jz_cpmregl[0x10>>2] = plcr1;
sdram_convert(clock,&sdramclock);
if (sdramclock > 0) {
// REG_EMC_RTCOR = sdramclock;
// REG_EMC_RTCNT = sdramclock;
jz_emcregs[0x8C>>1] = sdramclock;
jz_emcregs[0x88>>1] = sdramclock;
}
}
void
cpu_init()
{
jz_dev = open("/dev/mem", O_RDWR);
jz_cpmregl=(unsigned long *)mmap(0, 0x80, PROT_READ|PROT_WRITE, MAP_SHARED, jz_dev, 0x10000000);
jz_emcregl=(unsigned long *)mmap(0, 0x90, PROT_READ|PROT_WRITE, MAP_SHARED, jz_dev, 0x13010000);
jz_emcregs=(unsigned short *)jz_emcregl;
}
void
cpu_deinit()
{
cpu_set_clock( GP2X_MAX_CLOCK );
munmap((void *)jz_cpmregl, 0x80);
munmap((void *)jz_emcregl, 0x90);
close(jz_dev);
// fcloseall();
sync();
}
static void
loc_set_clock(int clock_in_mhz )
{
if (clock_in_mhz >= GP2X_MIN_CLOCK && clock_in_mhz <= GP2X_MAX_CLOCK) {
pll_init( clock_in_mhz * 1000000 );
}
}
static unsigned int loc_clock_in_mhz = GP2X_DEF_CLOCK;
void
cpu_set_clock(unsigned int clock_in_mhz)
{
if (clock_in_mhz == loc_clock_in_mhz) return;
loc_clock_in_mhz = clock_in_mhz;
loc_set_clock(clock_in_mhz);
return;
}
unsigned int
cpu_get_clock()
{
return loc_clock_in_mhz;
}

View File

@@ -0,0 +1,40 @@
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __CPUDINGUX_H__
#define __CPUDINGUX_H__
#ifdef __cplusplus
extern "C" {
#endif
# define GP2X_DEF_CLOCK 383
# define GP2X_MIN_CLOCK 336
# define GP2X_DEF_EMU_CLOCK 383
# define GP2X_MAX_CLOCK 420
void cpu_init(void);
void cpu_deinit(void);
extern unsigned int cpu_get_clock(void);
extern void cpu_set_clock(unsigned int clock_in_mhz);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,81 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* crc.c */
#include "quakedef.h"
#include "crc.h"
// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
// and the initial and final xor values shown below... in other words, the
// CCITT standard CRC used by XMODEM
#define CRC_INIT_VALUE 0xffff
#define CRC_XOR_VALUE 0x0000
static unsigned short crctable[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
void CRC_Init(unsigned short *crcvalue)
{
*crcvalue = CRC_INIT_VALUE;
}
void CRC_ProcessByte(unsigned short *crcvalue, byte data)
{
*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
}
unsigned short CRC_Value(unsigned short crcvalue)
{
return crcvalue ^ CRC_XOR_VALUE;
}

View File

@@ -0,0 +1,24 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* crc.h */
void CRC_Init(unsigned short *crcvalue);
void CRC_ProcessByte(unsigned short *crcvalue, byte data);
unsigned short CRC_Value(unsigned short crcvalue);

View File

@@ -0,0 +1,310 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cvar.c -- dynamic variable tracking
#include "quakedef.h"
cvar_t *cvar_vars;
char *cvar_null_string = "";
// 2000-01-09 CvarList command by Maddes start
/*
=========
Cvar_List
=========
*/
void Cvar_List_f (void)
{
cvar_t *cvar;
char *partial;
int len;
int count;
if (Cmd_Argc() > 1)
{
partial = Cmd_Argv (1);
len = Q_strlen(partial);
}
else
{
partial = NULL;
len = 0;
}
count=0;
for (cvar=cvar_vars ; cvar ; cvar=cvar->next)
{
if (partial && Q_strncmp (partial,cvar->name, len))
{
continue;
}
Con_Printf ("\"%s\" is \"%s\"\n", cvar->name, cvar->string);
count++;
}
Con_Printf ("%i cvar(s)", count);
if (partial)
{
Con_Printf (" beginning with \"%s\"", partial);
}
Con_Printf ("\n");
}
// 2000-01-09 CvarList command by Maddes end
/*
============
Cvar_FindVar
============
*/
cvar_t *Cvar_FindVar (char *var_name)
{
cvar_t *var;
for (var=cvar_vars ; var ; var=var->next)
if (!Q_strcmp (var_name, var->name))
return var;
return NULL;
}
/*
============
Cvar_VariableValue
============
*/
float Cvar_VariableValue (char *var_name)
{
cvar_t *var;
var = Cvar_FindVar (var_name);
if (!var)
return 0;
return Q_atof (var->string);
}
/*
============
Cvar_VariableString
============
*/
char *Cvar_VariableString (char *var_name)
{
cvar_t *var;
var = Cvar_FindVar (var_name);
if (!var)
return cvar_null_string;
return var->string;
}
/*
============
Cvar_CompleteVariable
============
*/
char *Cvar_CompleteVariable (char *partial)
{
cvar_t *cvar;
int len;
len = Q_strlen(partial);
if (!len)
return NULL;
// check functions
for (cvar=cvar_vars ; cvar ; cvar=cvar->next)
if (!Q_strncmp (partial,cvar->name, len))
return cvar->name;
return NULL;
}
/*
============
Cvar_Set
============
*/
void Cvar_Set (char *var_name, char *value)
{
cvar_t *var;
qboolean changed;
var = Cvar_FindVar (var_name);
if (!var)
{ // there is an error in C code if this happens
Con_Printf ("Cvar_Set: variable %s not found\n", var_name);
return;
}
changed = Q_strcmp(var->string, value);
Z_Free (var->string); // free the old value string
var->string = Z_Malloc (Q_strlen(value)+1);
Q_strcpy (var->string, value);
var->value = Q_atof (var->string);
if (var->server && changed)
{
if (sv.active)
SV_BroadcastPrintf ("\"%s\" changed to \"%s\"\n", var->name, var->string);
}
}
/*
============
Cvar_SetValue
============
*/
void Cvar_SetValue (char *var_name, float value)
{
char val[32];
sprintf (val, "%f",value);
Cvar_Set (var_name, val);
}
/*
============
Cvar_RegisterVariable
Adds a freestanding variable to the variable list.
============
*/
void Cvar_RegisterVariable (cvar_t *variable)
{
char *oldstr;
// first check to see if it has allready been defined
if (Cvar_FindVar (variable->name))
{
Con_Printf ("Can't register variable %s, allready defined\n", variable->name);
return;
}
// check for overlap with a command
if (Cmd_Exists (variable->name))
{
Con_Printf ("Cvar_RegisterVariable: %s is a command\n", variable->name);
return;
}
// copy the value off, because future sets will Z_Free it
oldstr = variable->string;
variable->string = Z_Malloc (Q_strlen(variable->string)+1);
Q_strcpy (variable->string, oldstr);
variable->value = Q_atof (variable->string);
// link the variable in
variable->next = cvar_vars;
cvar_vars = variable;
}
/*
============
Cvar_Command
Handles variable inspection and changing from the console
============
*/
qboolean Cvar_Command (void)
{
cvar_t *v;
// check variables
v = Cvar_FindVar (Cmd_Argv(0));
if (!v)
return false;
// perform a variable print or set
if (Cmd_Argc() == 1)
{
Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->string);
return true;
}
Cvar_Set (v->name, Cmd_Argv(1));
return true;
}
/*
============
Cvar_WriteVariables
Writes lines containing "set variable value" for all variables
with the archive flag set to true.
============
*/
void Cvar_WriteVariables (FILE *f)
{
cvar_t *var;
for (var = cvar_vars ; var ; var = var->next)
if (var->archive)
fprintf (f, "%s \"%s\"\n", var->name, var->string);
}

View File

@@ -0,0 +1,109 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cvar.h
/*
cvar_t variables are used to hold scalar or string variables that can be changed or displayed at the console or prog code as well as accessed directly
in C code.
it is sufficient to initialize a cvar_t with just the first two fields, or
you can add a ,true flag for variables that you want saved to the configuration
file when the game is quit:
cvar_t r_draworder = {"r_draworder","1"};
cvar_t scr_screensize = {"screensize","1",true};
Cvars must be registered before use, or they will have a 0 value instead of the float interpretation of the string. Generally, all cvar_t declarations should be registered in the apropriate init function before any console commands are executed:
Cvar_RegisterVariable (&host_framerate);
C code usually just references a cvar in place:
if ( r_draworder.value )
It could optionally ask for the value to be looked up for a string name:
if (Cvar_VariableValue ("r_draworder"))
Interpreted prog code can access cvars with the cvar(name) or
cvar_set (name, value) internal functions:
teamplay = cvar("teamplay");
cvar_set ("registered", "1");
The user can access cvars from the console in two ways:
r_draworder prints the current value
r_draworder 0 sets the current value to 0
Cvars are restricted from having the same names as commands to keep this
interface from being ambiguous.
*/
typedef struct cvar_s
{
char *name;
char *string;
qboolean archive; // set to true to cause it to be saved to vars.rc
qboolean server; // notifies players when changed
float value;
struct cvar_s *next;
} cvar_t;
typedef struct cvar_FPM_s
{
char *name;
char *string;
qboolean archive; // set to true to cause it to be saved to vars.rc
qboolean server; // notifies players when changed
fixedpoint_t value;
struct cvar_FPM_s *next;
} cvar_FPM_t;
void Cvar_List_f (void); // 2000-01-09 CvarList command by Maddes
void Cvar_RegisterVariable (cvar_t *variable);
// registers a cvar that allready has the name, string, and optionally the
// archive elements set.
void Cvar_Set (char *var_name, char *value);
// equivelant to "<name> <variable>" typed at the console
void Cvar_SetValue (char *var_name, float value);
// expands value to a string and calls Cvar_Set
float Cvar_VariableValue (char *var_name);
// returns 0 if not defined or non numeric
char *Cvar_VariableString (char *var_name);
// returns an empty string if not defined
char *Cvar_CompleteVariable (char *partial);
// attempts to match a partial variable name for command line completion
// returns NULL if nothing fits
qboolean Cvar_Command (void);
// called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known
// command. Returns true if the command was a variable reference that
// was handled. (print or change)
void Cvar_WriteVariables (FILE *f);
// Writes lines containing "set variable value" for all variables
// with the archive flag set to true.
cvar_t *Cvar_FindVar (char *var_name);
extern cvar_t *cvar_vars;

View File

@@ -0,0 +1,738 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// d_edge.c
#include "quakedef.h"
#include "d_local.h"
#include "LogFloat.h"
static int miplevel;
float scale_for_mip;
int screenwidth;
int ubasestep, errorterm, erroradjustup, erroradjustdown;
int vstartscan;
#ifdef USEFPM
fixedpoint_t scale_for_mipFPM;
#endif
// FIXME: should go away
extern void R_RotateBmodel (void);
extern void R_TransformFrustum (void);
vec3_t transformed_modelorg;
#ifdef USEFPM
extern void R_RotateBmodelFPM (void);
extern void R_TransformFrustumFPM (void);
vec3_FPM_t transformed_modelorgFPM;
#endif
/*
==============
D_DrawPoly
==============
*/
void D_DrawPoly (void)
{
// this driver takes spans, not polygons
}
#ifdef USEFPM
void D_DrawPolyFPM (void)
{
// this driver takes spans, not polygons
}
#endif
/*
=============
D_MipLevelForScale
=============
*/
int D_MipLevelForScale (float scale)
{
int lmiplevel;
if (scale >= d_scalemip[0] )
lmiplevel = 0;
else if (scale >= d_scalemip[1] )
lmiplevel = 1;
else if (scale >= d_scalemip[2] )
lmiplevel = 2;
else
lmiplevel = 3;
if (lmiplevel < d_minmip)
lmiplevel = d_minmip;
return lmiplevel;
}
#ifdef USEFPM
int D_MipLevelForScaleFPM (fixedpoint_t scale)
{
int lmiplevel;
if (scale >= d_scalemipFPM[0] )
lmiplevel = 0;
else if (scale >= d_scalemipFPM[1] )
lmiplevel = 1;
else if (scale >= d_scalemipFPM[2] )
lmiplevel = 2;
else
lmiplevel = 3;
if (lmiplevel < d_minmip)
lmiplevel = d_minmip;
return lmiplevel;
}
#endif
/*
==============
D_DrawSolidSurface
==============
*/
// FIXME: clean this up
void D_DrawSolidSurface (surf_t *surf, int color)
{
espan_t *span;
byte *pdest;
int u, u2, pix;
pix = (color<<24) | (color<<16) | (color<<8) | color;
for (span=surf->spans ; span ; span=span->pnext)
{
pdest = (byte *)d_viewbuffer + screenwidth*span->v;
u = span->u;
u2 = span->u + span->count - 1;
((byte *)pdest)[u] = pix;
if (u2 - u < 8)
{
for (u++ ; u <= u2 ; u++)
((byte *)pdest)[u] = pix;
}
else
{
for (u++ ; u & 3 ; u++)
((byte *)pdest)[u] = pix;
u2 -= 4;
for ( ; u <= u2 ; u+=4)
*(int *)((byte *)pdest + u) = pix;
u2 += 4;
for ( ; u <= u2 ; u++)
((byte *)pdest)[u] = pix;
}
}
}
/*
==============
D_CalcGradients
==============
*/
#ifndef USE_PQ_OPT3
void D_CalcGradients (msurface_t *pface)
{
mplane_t *pplane;
float mipscale;
vec3_t p_temp1;
vec3_t p_saxis, p_taxis;
float t;
pplane = pface->plane;
mipscale = (float)(1.0 / (float)(1 << miplevel));
//LogFloat((int)miplevel, "miplevel", -1, -1);
//LogFloat(mipscale, "mipscale", -1, -1);
TransformVector (pface->texinfo->vecs[0], p_saxis);
TransformVector (pface->texinfo->vecs[1], p_taxis);
//LogFloat(p_saxis[0], "p_saxis", 0, -1);
//LogFloat(p_saxis[1], "p_saxis", 1, -1);
//LogFloat(p_saxis[2], "p_saxis", 2, -1);
//LogFloat(p_taxis[0], "p_taxis", 0, -1);
//LogFloat(p_taxis[1], "p_taxis", 1, -1);
//LogFloat(p_taxis[2], "p_taxis", 2, -1);
t = xscaleinv * mipscale;
d_sdivzstepu = p_saxis[0] * t;
d_tdivzstepu = p_taxis[0] * t;
//LogFloat(xscaleinv, "xscaleinv", -1, -1);
//LogFloat(d_sdivzstepu, "d_sdivzstepu", -1, -1);
//LogFloat(d_tdivzstepu, "d_tdivzstepu", -1, -1);
t = yscaleinv * mipscale;
d_sdivzstepv = -p_saxis[1] * t;
d_tdivzstepv = -p_taxis[1] * t;
//LogFloat(yscaleinv, "yscaleinv", -1, -1);
//LogFloat(d_sdivzstepv, "d_sdivzstepv", -1, -1);
//LogFloat(d_tdivzstepv, "d_tdivzstepv", -1, -1);
d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu -
ycenter * d_sdivzstepv;
d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu -
ycenter * d_tdivzstepv;
//LogFloat(d_sdivzorigin, "d_sdivzorigin", -1, -1);
//LogFloat(d_tdivzorigin, "d_tdivzorigin", -1, -1);
VectorScale (transformed_modelorg, mipscale, p_temp1);
//LogFloat(p_temp1[0], "p_temp1", 0, -1);
//LogFloat(p_temp1[1], "p_temp1", 1, -1);
//LogFloat(p_temp1[2], "p_temp1", 2, -1);
t = 0x10000*mipscale;
//LogFloat(t, "t", -1, -1);
sadjust = (int)(((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
((pface->texturemins[0] << 16) >> miplevel)
+ pface->texinfo->vecs[0][3]*t);
tadjust = (int)(((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
((pface->texturemins[1] << 16) >> miplevel)
+ pface->texinfo->vecs[1][3]*t);
//LogFloat(sadjust, "sadjust", -1, -1);
//LogFloat(tadjust, "tadjust", -1, -1);
//
// -1 (-epsilon) so we never wander off the edge of the texture
//
bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
//LogFloat(bbextents, "bbextents", -1, -1);
//LogFloat(bbextentt, "bbextentt", -1, -1);
}
#else
void D_CalcGradients (msurface_t *pface)
{
mplane_t *pplane;
int mipscale_fxp;
int p_temp1_fxp[3];
int p_saxis_fxp[3], p_taxis_fxp[3];
int t_fxp;
pplane = pface->plane;
//Dan: TODO: get miplevel ranges
mipscale_fxp = (1 << miplevel);
//(26.6->11.21) / 24.8 = 19.13
p_saxis_fxp[0]= (pface->texinfo->vecs_fxp[0][0]<<15)/vright_fxp[0]+
(pface->texinfo->vecs_fxp[0][1]<<15)/vright_fxp[1]+
(pface->texinfo->vecs_fxp[0][2]<<15)/vright_fxp[2];
p_saxis_fxp[1]= (pface->texinfo->vecs_fxp[0][0]<<15)/vup_fxp[0]+
(pface->texinfo->vecs_fxp[0][1]<<15)/vup_fxp[1]+
(pface->texinfo->vecs_fxp[0][2]<<15)/vup_fxp[2];
p_saxis_fxp[2]= (pface->texinfo->vecs_fxp[0][0]<<15)/vpn_fxp[0]+
(pface->texinfo->vecs_fxp[0][1]<<15)/vpn_fxp[1]+
(pface->texinfo->vecs_fxp[0][2]<<15)/vpn_fxp[2];
p_taxis_fxp[0]= (pface->texinfo->vecs_fxp[1][0]<<15)/vright_fxp[0]+
(pface->texinfo->vecs_fxp[1][1]<<15)/vright_fxp[1]+
(pface->texinfo->vecs_fxp[1][2]<<15)/vright_fxp[2];
p_taxis_fxp[1]= (pface->texinfo->vecs_fxp[1][0]<<15)/vup_fxp[0]+
(pface->texinfo->vecs_fxp[1][1]<<15)/vup_fxp[1]+
(pface->texinfo->vecs_fxp[1][2]<<15)/vup_fxp[2];
p_taxis_fxp[2]= (pface->texinfo->vecs_fxp[1][0]<<15)/vpn_fxp[0]+
(pface->texinfo->vecs_fxp[1][1]<<15)/vpn_fxp[1]+
(pface->texinfo->vecs_fxp[1][2]<<15)/vpn_fxp[2];
//TransformVector (pface->texinfo->vecs[0], p_saxis);
//TransformVector (pface->texinfo->vecs[1], p_taxis);
//Dan: Maybe not enough precision here
//19.13 -> 3.29 / 9.23 = 26.6
d_sdivzstepu_fxp=(p_saxis_fxp[0]<<16)/xscale_fxp;
//26.6 / 32.0 = 26.6
d_sdivzstepu_fxp/=mipscale_fxp;
//19.13 -> 3.29 / 9.23 = 26.6
d_tdivzstepu_fxp=(p_taxis_fxp[0]<<16)/xscale_fxp;
//26.6 / 32.0 = 26.6
d_sdivzstepu_fxp/=mipscale_fxp;
//19.13 -> 3.29 / 9.23 = 26.6
d_sdivzstepv_fxp=(p_saxis_fxp[1]<<16)/yscale_fxp;
//26.6 / 32.0 = 26.6
d_sdivzstepv_fxp/=mipscale_fxp;
//19.13 -> 3.29 / 9.23 = 26.6
d_tdivzstepv_fxp=(p_taxis_fxp[1]<<16)/yscale_fxp;
//26.6 / 32.0 = 26.6
d_tdivzstepv_fxp/=mipscale_fxp;
//Dan: left off here
d_sdivzorigin = p_saxis_fxp[2] * mipscale_fxp - xcenter_fxp * d_sdivzstepu_fxp -
ycenter_fxp * d_sdivzstepv_fxp;
d_tdivzorigin = p_taxis_fxp[2] * mipscale_fxp - xcenter_fxp * d_tdivzstepu_fxp -
ycenter_fxp * d_tdivzstepv_fxp;
VectorScale (transformed_modelorg, mipscale_fxp, p_temp1_fxp);
t_fxp = 0x10000*mipscale_fxp;
sadjust = (int)(((fixed16_t)(DotProduct (p_temp1_fxp, p_saxis_fxp) * 0x10000 + 0.5)) -
((pface->texturemins[0] << 16) >> miplevel)
+ pface->texinfo->vecs_fxp[0][3]*t_fxp);
tadjust = (int)(((fixed16_t)(DotProduct (p_temp1_fxp, p_taxis_fxp) * 0x10000 + 0.5)) -
((pface->texturemins[1] << 16) >> miplevel)
+ pface->texinfo->vecs_fxp[1][3]*t_fxp);
//
// -1 (-epsilon) so we never wander off the edge of the texture
//
bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
}
#endif
/*
#else
//JB: Optimization
extern int fpxscale, fpyscale;
extern int fpxcenter, fpycenter;
static fpvec3 mo;
static float tmo;
void D_CalcGradients (msurface_t *pface)
{
fpvec3 v0, v1, p_saxis, p_taxis, p_temp1;
int dps, dpt;
v0[0] = (int)(16384.0f * pface->texinfo->vecs[0][0]); // 18.14
v0[1] = (int)(16384.0f * pface->texinfo->vecs[0][1]);
v0[2] = (int)(16384.0f * pface->texinfo->vecs[0][2]);
v1[0] = (int)(16384.0f * pface->texinfo->vecs[1][0]);
v1[1] = (int)(16384.0f * pface->texinfo->vecs[1][1]);
v1[2] = (int)(16384.0f * pface->texinfo->vecs[1][2]);
FPTransformVector (v0, p_saxis);
FPTransformVector (v1, p_taxis);
sdivzstepu = ((p_saxis[0] >> miplevel) / fpxscale) << 8;
tdivzstepu = ((p_taxis[0] >> miplevel) / fpxscale) << 8;
sdivzstepv = ((-p_saxis[1] >> miplevel) / fpyscale) << 8;
tdivzstepv = ((-p_taxis[1] >> miplevel) / fpyscale) << 8;
sdivzorigin = ((p_saxis[2] >> 2) >> miplevel) - fpxcenter * (sdivzstepu >> 6) - fpycenter * (sdivzstepv >> 6);
tdivzorigin = ((p_taxis[2] >> 2) >> miplevel) - fpxcenter * (tdivzstepu >> 6) - fpycenter * (tdivzstepv >> 6);
if (tmo != transformed_modelorg[0])
{
tmo = transformed_modelorg[0];
mo[0] = (int)(256.0f * transformed_modelorg[0]);
mo[1] = (int)(256.0f * transformed_modelorg[1]);
mo[2] = (int)(256.0f * transformed_modelorg[2]);
}
p_temp1[0] = mo[0] >> miplevel;
p_temp1[1] = mo[1] >> miplevel;
p_temp1[2] = mo[2] >> miplevel;
dps = ((p_temp1[0] * (p_saxis[0] >> 14)) >> 2 ) +
((p_temp1[1] * (p_saxis[1] >> 14)) >> 2 ) +
((p_temp1[2] * (p_saxis[2] >> 14)) >> 2 );
dpt = ((p_temp1[0] * (p_taxis[0] >> 14)) >> 2 ) +
((p_temp1[1] * (p_taxis[1] >> 14)) >> 2 ) +
((p_temp1[2] * (p_taxis[2] >> 14)) >> 2 );
sadjust = dps - (pface->texturemins[0] << (16 - miplevel)) + ((int)(pface->texinfo->vecs[0][3]) << (16 - miplevel));
tadjust = dpt - (pface->texturemins[1] << (16 - miplevel)) + ((int)(pface->texinfo->vecs[1][3]) << (16 - miplevel));
bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
}
#endif
*/
/*
==============
D_DrawSurfaces
==============
*/
#ifndef USE_PQ_OPT
void D_DrawSurfaces (void)
{
surf_t *s;
msurface_t *pface;
surfcache_t *pcurrentcache;
vec3_t world_transformed_modelorg;
vec3_t local_modelorg;
currententity = &cl_entities[0];
TransformVector (modelorg, transformed_modelorg);
VectorCopy (transformed_modelorg, world_transformed_modelorg);
// TODO: could preset a lot of this at mode set time
if (r_drawflat.value)
{
for (s = &surfaces[1] ; s<surface_p ; s++)
{
if (!s->spans)
continue;
// r_drawnpolycount++;
/*
#ifndef USE_PQ_OPT3
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
#else
d_zistepu_fxp = s->d_zistepu_fxp;
d_zistepv_fxp = s->d_zistepv_fxp;
d_ziorigin_fxp = s->d_ziorigin_fxp;
#endif
*/
pface = s->data;
char *surfcol;
surfcol=(char *)((byte*) pface->texinfo->texture + sizeof(texture_t));
// GpError(va("%d",(int)*((byte*) tx + tx->offsets[0]) & 0xFF),666);
D_DrawSolidSurface (s, surfcol[0] & 0xFF);
//D_DrawSolidSurface (s, (int)s->data & 0xFF);
D_DrawZSpans (s->spans);
}
}
else
{
for (s = &surfaces[1] ; s<surface_p ; s++)
{
if (!s->spans)
continue;
r_drawnpolycount++;
#ifndef USE_PQ_OPT3
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
#else
d_zistepu_fxp = s->d_zistepu_fxp;
d_zistepv_fxp = s->d_zistepv_fxp;
d_ziorigin_fxp = s->d_ziorigin_fxp;
//d_zistepu = s->d_zistepu_fxp/4194304.0f;
//d_zistepv = s->d_zistepv_fxp/4194304.0f;
//d_ziorigin = s->d_ziorigin_fxp/4194304.0f;
#endif
if (s->flags & SURF_DRAWSKY)
{
extern cvar_t r_fastsky;
extern cvar_t r_skycolor;
if (r_fastsky.value)
D_DrawSolidSurface (s, (int)r_skycolor.value & 0xFF);
else {
if (!r_skymade)
{
R_MakeSky ();
}
D_DrawSkyScans8 (s->spans);
}
D_DrawZSpans (s->spans);
}
else if (s->flags & SURF_DRAWBACKGROUND)
{
// set up a gradient for the background surface that places it
// effectively at infinity distance from the viewpoint
d_zistepu = 0;
d_zistepv = 0;
d_ziorigin = (float)-0.9;
D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF);
D_DrawZSpans (s->spans);
}
else if (s->flags & SURF_DRAWTURB)
{
extern cvar_t r_fastturb;
if (r_fastturb.value) {
texture_t *tx;
pface = s->data;
tx = pface->texinfo->texture;
D_DrawSolidSurface (s, *((byte*) tx + tx->offsets[0] + ((tx->width * tx->height) >> 1)));
D_DrawZSpans(s->spans);
continue;
}
pface = s->data;
miplevel = 0;
cacheblock = (pixel_t *)
((byte *)pface->texinfo->texture +
pface->texinfo->texture->offsets[0]);
cachewidth = 64;
if (s->insubmodel)
{
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; //FIXME: make this passed in to
// R_RotateBmodel ()
VectorSubtract (r_origin, currententity->origin,
local_modelorg);
TransformVector (local_modelorg, transformed_modelorg);
R_RotateBmodel (); // FIXME: don't mess with the frustum,
// make entity passed in
}
D_CalcGradients (pface);
Turbulent8 (s->spans);
D_DrawZSpans (s->spans);
if (s->insubmodel)
{
//
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
//
currententity = &cl_entities[0];
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
R_TransformFrustum ();
}
}
else
{
if (s->insubmodel)
{
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; //FIXME: make this passed in to
// R_RotateBmodel ()
VectorSubtract (r_origin, currententity->origin, local_modelorg);
TransformVector (local_modelorg, transformed_modelorg);
R_RotateBmodel (); // FIXME: don't mess with the frustum,
// make entity passed in
}
pface = s->data;
miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip
* pface->texinfo->mipadjust);
// FIXME: make this passed in to D_CacheSurface
pcurrentcache = D_CacheSurface (pface, miplevel);
cacheblock = (pixel_t *)pcurrentcache->data;
cachewidth = pcurrentcache->width;
D_CalcGradients (pface);
(*d_drawspans) (s->spans);
D_DrawZSpans (s->spans);
if (s->insubmodel)
{
//
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
//
currententity = &cl_entities[0];
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
R_TransformFrustum ();
}
}
}
}
}
#else
//JB: Optimization
void D_DrawSurfaces (void)
{
surf_t *s;
msurface_t *pface;
surfcache_t *pcurrentcache;
vec3_t world_transformed_modelorg;
vec3_t local_modelorg;
currententity = &cl_entities[0];
TransformVector (modelorg, transformed_modelorg);
VectorCopy (transformed_modelorg, world_transformed_modelorg);
// TODO: could preset a lot of this at mode set time
if (r_drawflat.value)
{
for (s = &surfaces[1] ; s<surface_p ; s++)
{
if (!s->spans)
continue;
zistepu = (int)(4194304.0f * s->d_zistepu);
zistepv = (int)(4194304.0f * s->d_zistepv);
ziorigin = (int)(4194304.0f * s->d_ziorigin);
D_DrawSolidSurface (s, (int)s->data & 0xFF);
D_DrawZSpans (s->spans);
}
}
else
{
for (s = &surfaces[1] ; s<surface_p ; s++)
{
if (!s->spans)
continue;
r_drawnpolycount++;
zistepu = (int)(4194304.0f * s->d_zistepu);
zistepv = (int)(4194304.0f * s->d_zistepv);
ziorigin = (int)(4194304.0f * s->d_ziorigin);
if (s->flags & SURF_DRAWSKY)
{
if (!r_skymade)
{
R_MakeSky ();
}
D_DrawSkyScans8 (s->spans);
D_DrawZSpans (s->spans);
}
else if (s->flags & SURF_DRAWBACKGROUND)
{
// set up a gradient for the background surface that places it
// effectively at infinity distance from the viewpoint
zistepu = 0;
zistepv = 0;
ziorigin = 3774873;
D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF);
D_DrawZSpans (s->spans);
}
else if (s->flags & SURF_DRAWTURB)
{
pface = s->data;
miplevel = 0;
cacheblock = (pixel_t *)
((byte *)pface->texinfo->texture +
pface->texinfo->texture->offsets[0]);
cachewidth = 64;
if (s->insubmodel)
{
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; //FIXME: make this passed in to
// R_RotateBmodel ()
VectorSubtract (r_origin, currententity->origin,
local_modelorg);
TransformVector (local_modelorg, transformed_modelorg);
R_RotateBmodel (); // FIXME: don't mess with the frustum,
// make entity passed in
}
D_CalcGradients (pface);
Turbulent8 (s->spans);
D_DrawZSpans (s->spans);
if (s->insubmodel)
{
//
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
//
currententity = &cl_entities[0];
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
R_TransformFrustum ();
}
}
else
{
if (s->insubmodel)
{
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; //FIXME: make this passed in to
// R_RotateBmodel ()
VectorSubtract (r_origin, currententity->origin, local_modelorg);
TransformVector (local_modelorg, transformed_modelorg);
R_RotateBmodel (); // FIXME: don't mess with the frustum,
// make entity passed in
}
pface = s->data;
miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip
* pface->texinfo->mipadjust);
// FIXME: make this passed in to D_CacheSurface
pcurrentcache = D_CacheSurface (pface, miplevel);
cacheblock = (pixel_t *)pcurrentcache->data;
cachewidth = pcurrentcache->width;
D_CalcGradients (pface);
D_DrawSpans8WithZ(s->spans);
// D_DrawZSpans (s->spans);
if (s->insubmodel)
{
//
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
//
currententity = &cl_entities[0];
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
R_TransformFrustum ();
}
}
}
}
}
#endif

View File

@@ -0,0 +1,88 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// d_clear: clears a specified rectangle to the specified color
#include "quakedef.h"
/*
================
D_FillRect
================
*/
void D_FillRect (vrect_t *rect, int color)
{
int rx, ry, rwidth, rheight;
unsigned char *dest;
unsigned *ldest;
rx = rect->x;
ry = rect->y;
rwidth = rect->width;
rheight = rect->height;
if (rx < 0)
{
rwidth += rx;
rx = 0;
}
if (ry < 0)
{
rheight += ry;
ry = 0;
}
if (rx+rwidth > (int)vid.width) //Dan: added cast to prevent warning
rwidth = vid.width - rx;
if (ry+rheight > (int)vid.height) //Dan: added cast to prevent warning
rheight = vid.height - rx;
if (rwidth < 1 || rheight < 1)
return;
dest = ((byte *)vid.buffer + ry*vid.rowbytes + rx);
if (((rwidth & 0x03) == 0) && (((long)dest & 0x03) == 0))
{
// faster aligned dword clear
ldest = (unsigned *)dest;
color += color << 16;
rwidth >>= 2;
color += color << 8;
for (ry=0 ; ry<rheight ; ry++)
{
for (rx=0 ; rx<rwidth ; rx++)
ldest[rx] = color;
ldest = (unsigned *)((byte*)ldest + vid.rowbytes);
}
}
else
{
// slower byte-by-byte clear for unaligned cases
for (ry=0 ; ry<rheight ; ry++)
{
for (rx=0 ; rx<rwidth ; rx++)
dest[rx] = color;
dest += vid.rowbytes;
}
}
}

View File

@@ -0,0 +1,304 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// d_iface.h: interface header file for rasterization driver modules
#define WARP_WIDTH 320
#define WARP_HEIGHT 200
#define MAX_LBM_HEIGHT 480
typedef struct
{
float u, v;
float s, t;
float zi;
} emitpoint_t;
/*
typedef struct
{
fixedpoint_t u, v;
fixedpoint_t s, t;
fixedpoint_t zi;
} emitpoint_FPM_t;
*/
typedef enum {
pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2
} ptype_t;
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct particle_s
{
// driver-usable fields
vec3_t org;
float color;
// drivers never touch the following fields
struct particle_s *next;
vec3_t vel;
float ramp;
float die;
ptype_t type;
} particle_t;
/*
typedef struct particle_FPM_s
{
// driver-usable fields
vec3_FPM_t org;
//Dan: why is color defined as a float? Changed to int.
int color;
// drivers never touch the following fields
struct particle_FPM_s *next;
vec3_FPM_t vel;
fixedpoint_t ramp;
fixedpoint_t die;
ptype_t type;
} particle_FPM_t;
*/
#define PARTICLE_Z_CLIP 8.0
//#define PARTICLE_Z_CLIP_FPM FPM_FROMFLOAT(8.0)
typedef struct polyvert_s {
float u, v, zi, s, t;
} polyvert_t;
/*
typedef struct polyvert_FPM_s {
fixedpoint_t u, v, zi, s, t;
} polyvert_FPM_t;
*/
typedef struct polydesc_s {
int numverts;
float nearzi;
msurface_t *pcurrentface;
polyvert_t *pverts;
} polydesc_t;
/*
typedef struct polydesc_FPM_s {
int numverts;
fixedpoint_t nearzi;
msurface_FPM_t *pcurrentface;
polyvert_FPM_t *pverts;
} polydesc_FPM_t;
*/
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct finalvert_s {
int v[6]; // u, v, s, t, l, 1/z
int flags;
// float reserved;
} finalvert_t;
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct
{
void *pskin;
maliasskindesc_t *pskindesc;
int skinwidth;
int skinheight;
mtriangle_t *ptriangles;
finalvert_t *pfinalverts;
int numtriangles;
int drawtype;
int seamfixupX16;
} affinetridesc_t;
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct {
float u, v, zi, color;
} screenpart_t;
typedef struct
{
int nump;
emitpoint_t *pverts;// there's room for an extra element at [nump],
// if the driver wants to duplicate element [0] at
// element [nump] to avoid dealing with wrapping
mspriteframe_t *pspriteframe;
vec3_t vup, vright, vpn; // in worldspace
float nearzi;
} spritedesc_t;
/*
typedef struct
{
int nump;
emitpoint_FPM_t *pverts; // there's room for an extra element at [nump],
// if the driver wants to duplicate element [0] at
// element [nump] to avoid dealing with wrapping
mspriteframe_FPM_t *pspriteframe;
vec3_FPM_t vup, vright, vpn; // in worldspace
fixedpoint_t nearzi;
} spritedesc_FPM_t;
*/
typedef struct
{
int u, v;
float zi;
int color;
} zpointdesc_t;
/*
typedef struct
{
int u, v;
fixedpoint_t zi;
int color;
} zpointdesc_FPM_t;
*/
extern cvar_t r_drawflat;
extern int d_spanpixcount;
extern int r_framecount; // sequence # of current frame since Quake
// started
extern qboolean r_drawpolys; // 1 if driver wants clipped polygons
// rather than a span list
extern qboolean r_drawculledpolys; // 1 if driver wants clipped polygons that
// have been culled by the edge list
extern qboolean r_worldpolysbacktofront; // 1 if driver wants polygons
// delivered back to front rather
// than front to back
extern qboolean r_recursiveaffinetriangles; // true if a driver wants to use
// recursive triangular subdivison
// and vertex drawing via
// D_PolysetDrawFinalVerts() past
// a certain distance (normally
// only used by the software
// driver)
extern float r_aliasuvscale; // scale-up factor for screen u and v
//extern fixedpoint_t r_aliasuvscaleFPM; // on Alias vertices passed to driver
extern int r_pixbytes;
extern qboolean r_dowarp;
extern affinetridesc_t r_affinetridesc;
extern spritedesc_t r_spritedesc;
//extern spritedesc_FPM_t r_spritedescFPM;
extern zpointdesc_t r_zpointdesc;
//extern zpointdesc_FPM_t r_zpointdescFPM;
extern polydesc_t r_polydesc;
extern int d_con_indirect; // if 0, Quake will draw console directly
// to vid.buffer; if 1, Quake will
// draw console via D_DrawRect. Must be
// defined by driver
extern vec3_t r_pright, r_pup, r_ppn;
//extern vec3_FPM_t r_prightFPM, r_pupFPM, r_ppnFPM;
void D_Aff8Patch (void *pcolormap);
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height);
void D_DisableBackBufferAccess (void);
void D_EndDirectRect (int x, int y, int width, int height);
void D_PolysetDraw (void);
void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts);
//void D_PolysetDrawFinalVertsFPM (finalvert_t *fv, int numverts);
void D_DrawParticle (particle_t *pparticle);
//void D_DrawParticleFPM (particle_FPM_t *pparticleFPM);
void D_DrawPoly (void);
//void D_DrawPolyFPM (void);
void D_DrawSprite (void);
//void D_DrawSpriteFPM (void);
void D_DrawSurfaces (void);
void D_DrawZPoint (void);
void D_EnableBackBufferAccess (void);
void D_EndParticles (void);
void D_Init (void);
void D_InitFPM (void);
void D_ViewChanged (void);
//void D_ViewChangedFPM (void);
void D_SetupFrame (void);
//void D_SetupFrameFPM (void);
void D_StartParticles (void);
void D_TurnZOn (void);
void D_WarpScreen (void);
void D_FillRect (vrect_t *vrect, int color);
void D_DrawRect (void);
void D_UpdateRects (vrect_t *prect);
// currently for internal use only, and should be a do-nothing function in
// hardware drivers
// FIXME: this should go away
void D_PolysetUpdateTables (void);
// these are currently for internal use only, and should not be used by drivers
extern int r_skydirect;
extern byte *r_skysource;
// transparency types for D_DrawRect ()
#define DR_SOLID 0
#define DR_TRANSPARENT 1
// !!! must be kept the same as in quakeasm.h !!!
#define TRANSPARENT_COLOR 0xFF
extern void *acolormap; // FIXME: should go away
//=======================================================================//
// callbacks to Quake
typedef struct
{
pixel_t *surfdat; // destination for generated surface
int rowbytes; // destination logical width in bytes
msurface_t *surf; // description for surface to generate
fixed8_t lightadj[MAXLIGHTMAPS];
// adjust for lightmap levels for dynamic lighting
texture_t *texture; // corrected for animating textures
int surfmip; // mipmapped ratio of surface texels / world pixels
int surfwidth; // in mipmapped texels
int surfheight; // in mipmapped texels
} drawsurf_t;
/*
typedef struct
{
pixel_t *surfdat; // destination for generated surface
int rowbytes; // destination logical width in bytes
msurface_FPM_t *surf; // description for surface to generate
fixed8_t lightadj[MAXLIGHTMAPS];
// adjust for lightmap levels for dynamic lighting
texture_t *texture; // corrected for animating textures
int surfmip; // mipmapped ratio of surface texels / world pixels
int surfwidth; // in mipmapped texels
int surfheight; // in mipmapped texels
} drawsurf_FPM_t;
*/
extern drawsurf_t r_drawsurf;
//extern drawsurf_FPM_t r_drawsurfFPM;
void R_DrawSurface (void);
//void R_DrawSurfaceFPM (void);
void R_GenTile (msurface_t *psurf, void *pdest);
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define TURB_TEX_SIZE 64 // base turbulent texture size
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define CYCLE 128 // turbulent cycle size
#define TILE_SIZE 128 // size of textures generated by R_GenTiledSurf
#define SKYSHIFT 7
#define SKYSIZE (1 << SKYSHIFT)
#define SKYMASK (SKYSIZE - 1)
extern float skyspeed, skyspeed2;
extern float skytime;
extern int c_surf;
extern vrect_t scr_vrect;
extern byte *r_warpbuffer;

View File

@@ -0,0 +1,240 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// d_init.c: rasterization driver initialization
#include "quakedef.h"
#include "d_local.h"
#define NUM_MIPS 4
cvar_t d_subdiv16 = {"d_subdiv16", "1"};
cvar_t d_mipcap = {"d_mipcap", "0"};
cvar_t d_mipscale = {"d_mipscale", "1"};
surfcache_t *d_initial_rover;
qboolean d_roverwrapped;
int d_minmip;
float d_scalemip[NUM_MIPS-1];
static float basemip[NUM_MIPS-1] = {(float)1.0, (float)(0.5*0.8), (float)(0.25*0.8)};
#ifdef USEFPM
surfcache_FPM_t *d_initial_roverFPM;
fixedpoint_t d_scalemipFPM[NUM_MIPS-1];
static fixedpoint_t basemipFPM[NUM_MIPS-1] = {FPM_FROMFLOATC(1.0), FPM_FROMFLOATC(0.5*0.8), FPM_FROMFLOATC(0.25*0.8)};
#endif
extern int d_aflatcolor;
void (*d_drawspans) (espan_t *pspan);
/*
===============
D_Init
===============
*/
void D_Init (void)
{
r_skydirect = 1;
Cvar_RegisterVariable (&d_subdiv16);
Cvar_RegisterVariable (&d_mipcap);
Cvar_RegisterVariable (&d_mipscale);
r_drawpolys = false;
r_worldpolysbacktofront = false;
r_recursiveaffinetriangles = true;
r_pixbytes = 1;
r_aliasuvscale = 1.0;
}
#ifdef USEFPM
void D_InitFPM (void)
{
r_skydirect = 1;
#ifndef USEFLOAT
Cvar_RegisterVariable (&d_subdiv16);
Cvar_RegisterVariable (&d_mipcap);
Cvar_RegisterVariable (&d_mipscale);
#endif
r_drawpolys = false;
r_worldpolysbacktofront = false;
r_recursiveaffinetriangles = true;
r_pixbytes = 1;
r_aliasuvscaleFPM = FPM_FROMFLOAT(1.0);
}
#endif
/*
===============
D_CopyRects
===============
*/
void D_CopyRects (vrect_t *prects, int transparent)
{
// this function is only required if the CPU doesn't have direct access to the
// back buffer, and there's some driver interface function that the driver
// doesn't support and requires Quake to do in software (such as drawing the
// console); Quake will then draw into wherever the driver points vid.buffer
// and will call this function before swapping buffers
UNUSED(prects);
UNUSED(transparent);
}
/*
===============
D_EnableBackBufferAccess
===============
*/
void D_EnableBackBufferAccess (void)
{
VID_LockBuffer ();
}
/*
===============
D_TurnZOn
===============
*/
void D_TurnZOn (void)
{
// not needed for software version
}
/*
===============
D_DisableBackBufferAccess
===============
*/
void D_DisableBackBufferAccess (void)
{
VID_UnlockBuffer ();
}
/*
===============
D_SetupFrame
===============
*/
void D_SetupFrame (void)
{
int i;
if (r_dowarp)
d_viewbuffer = r_warpbuffer;
else
d_viewbuffer = (void *)(byte *)vid.buffer;
if (r_dowarp)
screenwidth = WARP_WIDTH;
else
screenwidth = vid.rowbytes;
d_roverwrapped = false;
d_initial_rover = sc_rover;
d_minmip = (int)d_mipcap.value;
if (d_minmip > 3)
d_minmip = 3;
else if (d_minmip < 0)
d_minmip = 0;
for (i=0 ; i<(NUM_MIPS-1) ; i++)
d_scalemip[i] = basemip[i] * d_mipscale.value;
/*#if id386
if (d_subdiv16.value)
d_drawspans = D_DrawSpans16;
else
d_drawspans = D_DrawSpans8;
#else*/
d_drawspans = D_DrawSpans8;
//#endif
d_aflatcolor = 0;
}
#ifdef USEFPM
void D_SetupFrameFPM (void)
{
int i;
fixedpoint_t d_mipscale_value=FPM_FROMFLOAT(d_mipscale.value);
if (r_dowarp)
d_viewbuffer = r_warpbuffer;
else
d_viewbuffer = (void *)(byte *)vid.buffer;
if (r_dowarp)
screenwidth = WARP_WIDTH;
else
screenwidth = vid.rowbytes;
d_roverwrapped = false;
d_initial_roverFPM = sc_roverFPM;
d_minmip = (int)d_mipcap.value;
if (d_minmip > 3)
d_minmip = 3;
else if (d_minmip < 0)
d_minmip = 0;
for (i=0 ; i<(NUM_MIPS-1) ; i++)
d_scalemipFPM[i] = FPM_MUL(basemipFPM[i], d_mipscale_value);
//Dan: id386 is not defined for Pocket PC builds
#if id386
if (d_subdiv16.value)
d_drawspans = D_DrawSpans16;
else
d_drawspans = D_DrawSpans8;
#else
d_drawspans = D_DrawSpans8FPM; // FPM version doesn't seem to exist
d_drawspans = D_DrawSpans8;
#endif
d_aflatcolor = 0;
}
#endif
/*
===============
D_UpdateRects
===============
*/
void D_UpdateRects (vrect_t *prect)
{
// the software driver draws these directly to the vid buffer
UNUSED(prect);
}

View File

@@ -0,0 +1,160 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// d_local.h: private rasterization driver defs
#include "r_shared.h"
//
// TODO: fine-tune this; it's based on providing some overage even if there
// is a 2k-wide scan, with subdivision every 8, for 256 spans of 12 bytes each
//
#define SCANBUFFERPAD 0x1000
#define R_SKY_SMASK 0x007F0000
#define R_SKY_TMASK 0x007F0000
#define DS_SPAN_LIST_END -128
#define SURFCACHE_SIZE_AT_320X200 600*1024
typedef struct surfcache_s
{
struct surfcache_s *next;
struct surfcache_s **owner; // NULL is an empty chunk of memory
int lightadj[MAXLIGHTMAPS]; // checked for strobe flush
int dlight;
int size; // including header
unsigned width;
unsigned height; // DEBUG only needed for debug
float mipscale;
struct texture_s *texture; // checked for animating textures
byte data[4]; // width*height elements
} surfcache_t;
typedef struct surfcache_FPM_s
{
struct surfcache_FPM_s *next;
struct surfcache_FPM_s **owner; // NULL is an empty chunk of memory
int lightadj[MAXLIGHTMAPS]; // checked for strobe flush
int dlight;
int size; // including header
unsigned width;
unsigned height; // DEBUG only needed for debug
fixedpoint_t mipscale;
struct texture_s *texture; // checked for animating textures
byte data[4]; // width*height elements
} surfcache_FPM_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct sspan_s
{
int u, v, count;
} sspan_t;
extern cvar_t d_subdiv16;
extern float scale_for_mip;
extern fixedpoint_t scale_for_mipFPM;
extern qboolean d_roverwrapped;
extern surfcache_t *sc_rover;
extern surfcache_FPM_t *sc_roverFPM;
extern surfcache_t *d_initial_rover;
extern surfcache_FPM_t *d_initial_roverFPM;
extern float d_sdivzstepu, d_tdivzstepu, d_zistepu;
extern float d_sdivzstepv, d_tdivzstepv, d_zistepv;
extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
extern int d_zistepu_fxp, d_zistepv_fxp, d_ziorigin_fxp;
#ifdef USE_PQ_OPT3
extern int d_sdivzstepu_fxp, d_tdivzstepu_fxp, d_zistepu_fxp;
extern int d_sdivzstepv_fxp, d_tdivzstepv_fxp, d_zistepv_fxp;
extern int d_sdivzorigin_fxp, d_tdivzorigin_fxp, d_ziorigin_fxp;
#endif
#ifdef USE_PQ_OPT
//JB:Optimization
extern int sdivzstepu, tdivzstepu, zistepu;
extern int sdivzstepv, tdivzstepv, zistepv;
extern int sdivzorigin, tdivzorigin, ziorigin;
#endif
extern fixedpoint_t d_sdivzstepuFPM, d_tdivzstepuFPM, d_zistepuFPM;
extern fixedpoint_t d_sdivzstepvFPM, d_tdivzstepvFPM, d_zistepvFPM;
extern fixedpoint_t d_sdivzoriginFPM, d_tdivzoriginFPM, d_zioriginFPM;
//Dan: ID Software was already using a minute amount of fixed point. I duplicated
//these just for consistancy in the conversion, and so the types would match.
fixed16_t sadjust, tadjust;
fixed16_t bbextents, bbextentt;
fixedpoint_t sadjustFPM, tadjustFPM;
fixedpoint_t bbextentsFPM, bbextenttFPM;
void D_DrawSpans8 (espan_t *pspans);
#ifdef USE_PQ_OPT
//JB:Optimization
void D_DrawSpans8WithZ (espan_t *pspans);
#endif
void D_DrawSpans8FPM (espan_t *pspans);
void D_DrawSpans16 (espan_t *pspans);
void D_DrawZSpans (espan_t *pspans);
void Turbulent8 (espan_t *pspan);
void D_SpriteDrawSpans (sspan_t *pspan);
void D_DrawSkyScans8 (espan_t *pspan);
void D_DrawSkyScans8FPM (espan_t *pspan);
void D_DrawSkyScans16 (espan_t *pspan);
void R_ShowSubDiv (void);
void (*prealspandrawer)(void);
surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel);
//surfcache_FPM_t *D_CacheSurfaceFPM (msurface_FPM_t *surface, int miplevel);
extern int D_MipLevelForScale (float scale);
#if id386
extern void D_PolysetAff8Start (void);
extern void D_PolysetAff8End (void);
#endif
extern short *d_pzbuffer;
extern unsigned int d_zrowbytes, d_zwidth;
extern int *d_pscantable;
extern int d_scantable[MAXHEIGHT];
extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
extern int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
extern pixel_t *d_viewbuffer;
extern short *zspantable[MAXHEIGHT];
extern int d_minmip;
extern float d_scalemip[3];
extern fixedpoint_t d_scalemipFPM[3];
extern void (*d_drawspans) (espan_t *pspan);

View File

@@ -0,0 +1,161 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// d_modech.c: called when mode has just changed
#include "quakedef.h"
#include "d_local.h"
int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
int d_scantable[MAXHEIGHT];
short *zspantable[MAXHEIGHT];
//Dan East:
extern int min_vid_width;
/*
================
D_Patch
================
*/
void D_Patch (void)
{
#if id386
static qboolean protectset8 = false;
if (!protectset8)
{
Sys_MakeCodeWriteable ((int)D_PolysetAff8Start,
(int)D_PolysetAff8End - (int)D_PolysetAff8Start);
protectset8 = true;
}
#endif // id386
}
/*
================
D_ViewChanged
================
*/
void D_ViewChanged (void)
{
int rowbytes;
if (r_dowarp)
rowbytes = WARP_WIDTH;
else
rowbytes = vid.rowbytes;
scale_for_mip = xscale;
if (yscale > xscale)
scale_for_mip = yscale;
d_zrowbytes = vid.width * 2;
d_zwidth = vid.width;
d_pix_min = r_refdef.vrect.width / min_vid_width/*320*/;
if (d_pix_min < 1)
d_pix_min = 1;
d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5);
d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5);
if (d_pix_max < 1)
d_pix_max = 1;
if (pixelAspect > 1.4)
d_y_aspect_shift = 1;
else
d_y_aspect_shift = 0;
d_vrectx = r_refdef.vrect.x;
d_vrecty = r_refdef.vrect.y;
d_vrectright_particle = r_refdef.vrectright - d_pix_max;
d_vrectbottom_particle =
r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift);
{
//Dan: changed to unsigned to shut compiler up
unsigned int i;
for (i=0 ; i<vid.height; i++)
{
d_scantable[i] = i*rowbytes;
zspantable[i] = d_pzbuffer + i*d_zwidth;
}
}
D_Patch ();
}
#ifdef USEFPM
void D_ViewChangedFPM (void)
{
int rowbytes;
if (r_dowarp)
rowbytes = WARP_WIDTH;
else
rowbytes = vid.rowbytes;
scale_for_mipFPM = xscaleFPM;
if (yscaleFPM > xscaleFPM)
scale_for_mipFPM = yscaleFPM;
d_zrowbytes = vid.width * 2;
d_zwidth = vid.width;
d_pix_min = r_refdef.vrect.width / min_vid_width/*320*/;
if (d_pix_min < 1)
d_pix_min = 1;
d_pix_max = FPM_TOLONG(FPM_ADD(FPM_DIV(r_refdef.vrect.width, FPM_FROMFLOAT(320.0 / 4.0)), FPM_FROMFLOAT(0.5)));
d_pix_shift = 8 - FPM_TOLONG(FPM_ADD(FPM_DIV(r_refdef.vrect.width, FPM_FROMFLOAT(320.0)), FPM_FROMFLOAT(0.5)));
if (d_pix_max < 1)
d_pix_max = 1;
if (pixelAspectFPM > FPM_FROMFLOAT(1.4))
d_y_aspect_shift = 1;
else
d_y_aspect_shift = 0;
d_vrectx = r_refdef.vrect.x;
d_vrecty = r_refdef.vrect.y;
d_vrectright_particle = r_refdef.vrectright - d_pix_max;
d_vrectbottom_particle =
r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift);
{
unsigned int i;
for (i=0 ; i<vid.height; i++)
{
d_scantable[i] = i*rowbytes;
zspantable[i] = d_pzbuffer + i*d_zwidth;
}
}
D_Patch ();
}
#endif

View File

@@ -0,0 +1,359 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// d_part.c: software driver module for drawing particles
#include "quakedef.h"
#include "d_local.h"
/*
==============
D_EndParticles
==============
*/
void D_EndParticles (void)
{
// not used by software driver
}
/*
==============
D_StartParticles
==============
*/
void D_StartParticles (void)
{
// not used by software driver
}
#if !id386
/*
==============
D_DrawParticle
==============
*/
void D_DrawParticle (particle_t *pparticle)
{
vec3_t local, transformed;
float zi;
byte *pdest;
short *pz;
int i, izi, pix, count, u, v;
// transform point
VectorSubtract (pparticle->org, r_origin, local);
transformed[0] = DotProduct(local, r_pright);
transformed[1] = DotProduct(local, r_pup);
transformed[2] = DotProduct(local, r_ppn);
if (transformed[2] < PARTICLE_Z_CLIP)
return;
// project the point
// FIXME: preadjust xcenter and ycenter
zi = (float)(1.0 / transformed[2]);
u = (int)(xcenter + zi * transformed[0] + 0.5);
v = (int)(ycenter - zi * transformed[1] + 0.5);
if ((v > d_vrectbottom_particle) ||
(u > d_vrectright_particle) ||
(v < d_vrecty) ||
(u < d_vrectx))
{
return;
}
pz = d_pzbuffer + (d_zwidth * v) + u;
pdest = d_viewbuffer + d_scantable[v] + u;
izi = (int)(zi * 0x8000);
pix = izi >> d_pix_shift;
if (pix < d_pix_min)
pix = d_pix_min;
else if (pix > d_pix_max)
pix = d_pix_max;
switch (pix)
{
case 1:
count = 1 << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = (byte)pparticle->color;
}
}
break;
case 2:
count = 2 << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = (byte)pparticle->color;
}
if (pz[1] <= izi)
{
pz[1] = izi;
pdest[1] = (byte)pparticle->color;
}
}
break;
case 3:
count = 3 << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = (byte)pparticle->color;
}
if (pz[1] <= izi)
{
pz[1] = izi;
pdest[1] = (byte)pparticle->color;
}
if (pz[2] <= izi)
{
pz[2] = izi;
pdest[2] = (byte)pparticle->color;
}
}
break;
case 4:
count = 4 << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = (byte)pparticle->color;
}
if (pz[1] <= izi)
{
pz[1] = izi;
pdest[1] = (byte)pparticle->color;
}
if (pz[2] <= izi)
{
pz[2] = izi;
pdest[2] = (byte)pparticle->color;
}
if (pz[3] <= izi)
{
pz[3] = izi;
pdest[3] = (byte)pparticle->color;
}
}
break;
default:
count = pix << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
for (i=0 ; i<pix ; i++)
{
if (pz[i] <= izi)
{
pz[i] = izi;
pdest[i] = (byte)pparticle->color;
}
}
}
break;
}
}
#ifdef USEFPM
void D_DrawParticleFPM (particle_FPM_t *pparticle)
{
vec3_FPM_t local, transformed;
fixedpoint_t zi;
byte *pdest;
short *pz;
int i, izi, pix, count, u, v;
// transform point
VectorSubtractFPM (pparticle->org, r_originFPM, local);
transformed[0] = DotProductFPM(local, r_prightFPM);
transformed[1] = DotProductFPM(local, r_pupFPM);
transformed[2] = DotProductFPM(local, r_ppnFPM);
if (transformed[2] < PARTICLE_Z_CLIP_FPM)
return;
// project the point
// FIXME: preadjust xcenter and ycenter
zi = FPM_DIV(FPM_FROMFLOAT(1.0), transformed[2]);
u = FPM_TOLONG(FPM_ADD3(xcenterFPM, FPM_MUL(zi, transformed[0]), FPM_FROMFLOAT(0.5)));
v = FPM_TOLONG(FPM_SUB(ycenterFPM, FPM_ADD(FPM_MUL(zi, transformed[1]), FPM_FROMFLOAT(0.5))));
if ((v > d_vrectbottom_particle) ||
(u > d_vrectright_particle) ||
(v < d_vrecty) ||
(u < d_vrectx))
{
return;
}
pz = d_pzbuffer + (d_zwidth * v) + u;
pdest = d_viewbuffer + d_scantable[v] + u;
izi = FPM_TOLONG(FPM_MUL(zi, FPM_FROMLONG(0x8000)));
pix = izi >> d_pix_shift;
if (pix < d_pix_min)
pix = d_pix_min;
else if (pix > d_pix_max)
pix = d_pix_max;
switch (pix)
{
case 1:
count = 1 << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = pparticle->color;
}
}
break;
case 2:
count = 2 << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = pparticle->color;
}
if (pz[1] <= izi)
{
pz[1] = izi;
pdest[1] = pparticle->color;
}
}
break;
case 3:
count = 3 << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = pparticle->color;
}
if (pz[1] <= izi)
{
pz[1] = izi;
pdest[1] = pparticle->color;
}
if (pz[2] <= izi)
{
pz[2] = izi;
pdest[2] = pparticle->color;
}
}
break;
case 4:
count = 4 << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
if (pz[0] <= izi)
{
pz[0] = izi;
pdest[0] = pparticle->color;
}
if (pz[1] <= izi)
{
pz[1] = izi;
pdest[1] = pparticle->color;
}
if (pz[2] <= izi)
{
pz[2] = izi;
pdest[2] = pparticle->color;
}
if (pz[3] <= izi)
{
pz[3] = izi;
pdest[3] = pparticle->color;
}
}
break;
default:
count = pix << d_y_aspect_shift;
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
{
for (i=0 ; i<pix ; i++)
{
if (pz[i] <= izi)
{
pz[i] = izi;
pdest[i] = pparticle->color;
}
}
}
break;
}
}
#endif
#endif // !id386

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,594 @@
// d_scan.c
// Portable C scan-level rasterization code, all pixel depths.
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h"
unsigned char *r_turb_pbase, *r_turb_pdest;
fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
int *r_turb_turb;
int r_turb_spancount;
void D_DrawTurbulent8Span (void);
/*==============================================
// D_WarpScreen
// this performs a slight compression of the screen at the same time as
// the sine warp, to keep the edges from wrapping
//============================================*/
void D_WarpScreen (void)
{
int w, h;
int u,v;
byte *dest;
int *turb;
int *col;
byte **row;
byte *rowptr[MAXHEIGHT+(AMP2*2)];
int column[MAXWIDTH+(AMP2*2)];
float wratio, hratio;
w = r_refdef.vrect.width;
h = r_refdef.vrect.height;
wratio = w / (float)scr_vrect.width;
hratio = h / (float)scr_vrect.height;
for (v=0 ; v<scr_vrect.height+AMP2*2 ; v++)
{
rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) +
(screenwidth * (int)((float)v * hratio * h / (h + AMP2 * 2)));
}
for (u=0 ; u<scr_vrect.width+AMP2*2 ; u++)
{
column[u] = r_refdef.vrect.x +
(int)((float)u * wratio * w / (w + AMP2 * 2));
}
turb = intsintable + ((int)(cl.time*SPEED)&(CYCLE-1));
dest = vid.buffer + scr_vrect.y * vid.rowbytes + scr_vrect.x;
for (v=0 ; v<scr_vrect.height ; v++, dest += vid.rowbytes)
{
col = &column[turb[v]];
row = &rowptr[v];
for (u=0 ; u<scr_vrect.width ; u+=4)
{
dest[u+0] = row[turb[u+0]][col[u+0]];
dest[u+1] = row[turb[u+1]][col[u+1]];
dest[u+2] = row[turb[u+2]][col[u+2]];
dest[u+3] = row[turb[u+3]][col[u+3]];
}
}
}
#if !id386
/*==============================================
// D_DrawTurbulent8Span
//============================================*/
void D_DrawTurbulent8Span (void)
{
int sturb, tturb;
do
{
sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
*r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
r_turb_s += r_turb_sstep;
r_turb_t += r_turb_tstep;
} while (--r_turb_spancount > 0);
}
#endif // !id386
/*==============================================
// Turbulent8
//============================================*/
void Turbulent8 (espan_t *pspan)
{
int count;
fixed16_t snext, tnext;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz16stepu, tdivz16stepu, zi16stepu;
r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
r_turb_sstep = 0; // keep compiler happy
r_turb_tstep = 0; // ditto
r_turb_pbase = (unsigned char *)cacheblock;
sdivz16stepu = d_sdivzstepu * 16;
tdivz16stepu = d_tdivzstepu * 16;
zi16stepu = d_zistepu * 16;
do
{
r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
r_turb_s = (int)(sdivz * z) + sadjust;
if (r_turb_s > bbextents) r_turb_s = bbextents;
else if (r_turb_s < 0) r_turb_s = 0;
r_turb_t = (int)(tdivz * z) + tadjust;
if (r_turb_t > bbextentt) r_turb_t = bbextentt;
else if (r_turb_t < 0) r_turb_t = 0;
do
{
// calculate s and t at the far end of the span
if (count >= 16) r_turb_spancount = 16;
else r_turb_spancount = count;
count -= r_turb_spancount;
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz16stepu;
tdivz += tdivz16stepu;
zi += zi16stepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents) snext = bbextents;
else if (snext < 16) snext = 16;
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt) tnext = bbextentt;
else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps
r_turb_sstep = (snext - r_turb_s) >> 4;
r_turb_tstep = (tnext - r_turb_t) >> 4;
}
else
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
// can't step off polygon), clamp, calculate s and t steps across
// span by division, biasing steps low so we don't run off the
// texture
spancountminus1 = (float)(r_turb_spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents) snext = bbextents;
else if (snext < 16) snext = 16;
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt) tnext = bbextentt;
else if (tnext < 16) tnext = 16; // guard against round-off error on <0 steps
if (r_turb_spancount > 1)
{
r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
}
}
r_turb_s = r_turb_s & ((CYCLE<<16)-1);
r_turb_t = r_turb_t & ((CYCLE<<16)-1);
D_DrawTurbulent8Span ();
r_turb_s = snext;
r_turb_t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}
#if !id386
/*==============================================
// D_DrawSpans8
//============================================*/
#ifndef USE_PQ_OPT5
void D_DrawSpans8 (espan_t *pspan)
{
int count, spancount;
unsigned char *pbase, *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = (unsigned char *)cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
do
{
pdest = (unsigned char *)((byte *)d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
s = (int)(sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int)(tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
else if (t < 0)
t = 0;
do
{
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
}
else
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
// can't step off polygon), clamp, calculate s and t steps across
// span by division, biasing steps low so we don't run off the
// texture
spancountminus1 = (float)(spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
if (spancount > 1)
{
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
do
{
*pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}
#else
static int sdivzorig, sdivzstepv, sdivzstepu, sdivz8stepu;
static int tdivzorig, tdivzstepv, tdivzstepu, tdivz8stepu;
static int zi8stepu;
static float last = 0;
/*==============================================
// UpdateFixedPointVars
//============================================*/
void UpdateFixedPointVars( int all )
{
// JB: Store texture transformation matrix in fixed point vars
if (all)
{
/*
sdivzorig = (int)(524288.0f * d_sdivzorigin); // 13.19 fixed point
tdivzorig = (int)(524288.0f * d_tdivzorigin);
sdivzstepv = (int)(524288.0f * d_sdivzstepv);
tdivzstepv = (int)(524288.0f * d_tdivzstepv);
sdivzstepu = (int)(524288.0f * d_sdivzstepu);
sdivz8stepu = sdivzstepu*8;
tdivzstepu = (int)(524288.0f * d_tdivzstepu);
tdivz8stepu = tdivzstepu*8;
*/
sdivzorig = (int)(4194304.0f * d_sdivzorigin); // 10.22 fixed point
tdivzorig = (int)(4194304.0f * d_tdivzorigin);
sdivzstepv = (int)(4194304.0f * d_sdivzstepv);
tdivzstepv = (int)(4194304.0f * d_tdivzstepv);
sdivzstepu = (int)(4194304.0f * d_sdivzstepu);
sdivz8stepu = sdivzstepu*8;
tdivzstepu = (int)(4194304.0f * d_tdivzstepu);
tdivz8stepu = tdivzstepu*8;
}
/*
ziorig = (int)(524288.0f * d_ziorigin); // 13.19 fixed point
zistepv = (int)(524288.0f * d_zistepv );
zistepu = (int)(524288.0f * d_zistepu );
*/
#ifndef USE_PQ_OPT3
d_ziorigin_fxp = (int)(4194304.0f * d_ziorigin); // 10.22 fixed point
d_zistepv_fxp = (int)(4194304.0f * d_zistepv );
d_zistepu_fxp = (int)(4194304.0f * d_zistepu );
#endif
zi8stepu = d_zistepu_fxp * 8;
last = d_zistepv;
}
void D_DrawSpans8 (espan_t *pspan)
{
int count, spancount, spancountminus1;
unsigned char *pbase, *pdest;
fixed16_t s1, t1;
int zi, sdivz, tdivz, sstep, tstep;
int snext, tnext;
pbase = (unsigned char *)cacheblock;
//Jacco Biker's fixed point conversion
// Recalc fixed point values
UpdateFixedPointVars( 1 );
do
{
pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u);
count = pspan->count;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
sdivz = sdivzorig + pspan->v * sdivzstepv + pspan->u * sdivzstepu;
tdivz = tdivzorig + pspan->v * tdivzstepv + pspan->u * tdivzstepu;
zi = d_ziorigin_fxp + pspan->v * d_zistepv_fxp + pspan->u * d_zistepu_fxp;
if (zi == 0) zi = 1;
s1 = (((sdivz << 8) / zi) << 8) + sadjust; // 5.27 / 13.19 = 24.8 >> 8 = 16.16
if (s1 > bbextents) s1 = bbextents; else if (s1 < 0) s1 = 0;
t1 = (((tdivz << 8) / zi) << 8) + tadjust;
if (t1 > bbextentt) t1 = bbextentt; else if (t1 < 0) t1 = 0;
// calculate final s/z, t/z, 1/z, s, and t and clamp
//sdivz += sdivzstepu * (count - 1);
//tdivz += tdivzstepu * (count - 1);
//zi += d_zistepu_fxp * (count - 1);
//if (zi == 0) zi = 1;
#if 0
s2 = (((sdivz << 8) / zi) << 8) + sadjust;
if (s2 > bbextents) s2 = bbextents; else if (s2 < 8) s2 = 8;
t2 = (((tdivz << 8) / zi) << 8) + tadjust;
if (t2 > bbextentt) t2 = bbextentt; else if (t2 < 8) t2 = 8;
if (count > 1)
{
sstep = (s2 - s1) / (count - 1);
tstep = (t2 - t1) / (count - 1);
}
#else
//End Jacco Biker mod
//Dan East: Fixed point conversion for perspective correction
do
{
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
if (!zi) zi = 1;
//z = zi;
//z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (((sdivz<<8)/zi)<<8)+sadjust;
//snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (((tdivz<<8)/zi)<<8) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
sstep = (snext - s1) >> 3;
tstep = (tnext - t1) >> 3;
}
else
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
// can't step off polygon), clamp, calculate s and t steps across
// span by division, biasing steps low so we don't run off the
// texture
spancountminus1 = spancount - 1;
sdivz += sdivzstepu * spancountminus1;
tdivz += tdivzstepu * spancountminus1;
zi += d_zistepu_fxp * spancountminus1;
if (!zi) zi = 1;
//z = zi;//(float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (((sdivz<<8) / zi)<<8) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (((tdivz<<8) / zi)<<8) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
if (spancount > 1)
{
sstep = ((snext - s1)) / ((spancount - 1));
tstep = ((tnext - t1)) / ((spancount - 1));
}
}
do
{
*pdest++ = *(pbase + (s1 >> 16) + (t1 >> 16) * cachewidth);
s1 += sstep;
t1 += tstep;
} while (--spancount > 0);
s1 = snext;
t1 = tnext;
} while (count > 0);
#endif
#if 0
// Draw span
for ( i = 0; i < count; i++ )
{
*pdest++ = *(pbase + (s1 >> 16) + (t1 >> 16) * cachewidth);
s1 += sstep;
t1 += tstep;
}
#endif
} while ((pspan = pspan->pnext) != NULL);
}
#endif
#endif //USE_PQ_OPT5
#ifdef USE_PQ_OPT5
#if !id386
/*==============================================
// D_DrawZSpans
//============================================*/
void D_DrawZSpans (espan_t *pspan)
{
int count, doublecount, izistep;
int izi;
short *pdest;
unsigned ltemp;
#ifdef USE_PQ_OPT5
// Recalc fixed point values
UpdateFixedPointVars( 0 );
#endif
izistep = d_zistepu_fxp << 9;
do
{
pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
// calculate the initial 1/z
izi = (d_ziorigin_fxp + pspan->v * d_zistepv_fxp + pspan->u * d_zistepu_fxp) << 9; // 1.31 fixed point
if ((long)pdest & 0x02)
{
*pdest++ = (short)(izi >> 16);
izi += izistep;
count--;
}
if ((doublecount = count >> 1) > 0)
{
do
{
ltemp = izi >> 16;
izi += izistep;
ltemp |= izi & 0xFFFF0000;
izi += izistep;
*(int *)pdest = ltemp;
pdest += 2;
} while (--doublecount > 0);
}
if (count & 1) *pdest = (short)(izi >> 16);
} while ((pspan = pspan->pnext) != NULL);
}
#endif
#else
void D_DrawZSpans (espan_t *pspan)
{
int count, doublecount, izistep;
int izi;
short *pdest;
unsigned ltemp;
double zi;
float du, dv;
// FIXME: check for clamping/range problems
// we count on FP exceptions being turned off to avoid range problems
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
do
{
pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
// calculate the initial 1/z
du = (float)pspan->u;
dv = (float)pspan->v;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
// we count on FP exceptions being turned off to avoid range problems
izi = (int)(zi * 0x8000 * 0x10000);
if ((long)pdest & 0x02)
{
*pdest++ = (short)(izi >> 16);
izi += izistep;
count--;
}
if ((doublecount = count >> 1) > 0)
{
do
{
ltemp = izi >> 16;
izi += izistep;
ltemp |= izi & 0xFFFF0000;
izi += izistep;
*(int *)pdest = ltemp;
pdest += 2;
} while (--doublecount > 0);
}
if (count & 1)
*pdest = (short)(izi >> 16);
} while ((pspan = pspan->pnext) != NULL);
}
#endif

View File

@@ -0,0 +1,207 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// d_sky.c
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h"
#define SKY_SPAN_SHIFT 5
#define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT)
/*
=================
D_Sky_uv_To_st
=================
*/
void D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
{
float wu, wv, temp;
vec3_t end;
if (r_refdef.vrect.width >= r_refdef.vrect.height)
temp = (float)r_refdef.vrect.width;
else
temp = (float)r_refdef.vrect.height;
wu = (float)(8192.0 * (float)(u-((int)vid.width>>1)) / temp);
wv = (float)(8192.0 * (float)(((int)vid.height>>1)-v) / temp);
end[0] = 4096*vpn[0] + wu*vright[0] + wv*vup[0];
end[1] = 4096*vpn[1] + wu*vright[1] + wv*vup[1];
end[2] = 4096*vpn[2] + wu*vright[2] + wv*vup[2];
end[2] *= 3;
VectorNormalize (end);
temp = skytime*skyspeed; // TODO: add D_SetupFrame & set this there
*s = (int)((temp + 6*(SKYSIZE/2-1)*end[0]) * 0x10000);
*t = (int)((temp + 6*(SKYSIZE/2-1)*end[1]) * 0x10000);
}
#ifdef USEFPM
void D_Sky_uv_To_stFPM (int u, int v, fixed16_t *s, fixed16_t *t)
{
fixedpoint_t wu, wv, temp;
vec3_FPM_t end;
if (r_refdefFPM.vrect.width >= r_refdefFPM.vrect.height)
temp = FPM_FROMLONG(r_refdefFPM.vrect.width);
else
temp = FPM_FROMLONG(r_refdefFPM.vrect.height);
wu = FPM_DIV(FPM_MUL(FPM_FROMFLOAT(8192.0), FPM_FROMLONG(u-(vid.width>>1))), temp);
wv = FPM_DIV(FPM_MUL(FPM_FROMFLOAT(8192.0), FPM_FROMLONG(((int)vid.height>>1)-v)), temp);
end[0] = FPM_ADD3(FPM_MUL(FPM_FROMLONG(4096),vpnFPM[0]), FPM_MUL(wu,vrightFPM[0]), FPM_MUL(wv,vupFPM[0]));
end[1] = FPM_ADD3(FPM_MUL(FPM_FROMLONG(4096),vpnFPM[1]), FPM_MUL(wu,vrightFPM[1]), FPM_MUL(wv,vupFPM[1]));
end[2] = FPM_ADD3(FPM_MUL(FPM_FROMLONG(4096),vpnFPM[2]), FPM_MUL(wu,vrightFPM[2]), FPM_MUL(wv,vupFPM[2]));
end[2] = FPM_MUL(end[2], FPM_FROMLONG(3));
VectorNormalizeFPM (end);
temp = FPM_MUL(FPM_FROMFLOAT(skytime),FPM_FROMFLOAT(skyspeed)); // TODO: add D_SetupFrame & set this there
*s = FPM_ADD(temp, FPM_MUL(FPM_FROMLONG(6*(SKYSIZE/2-1)),end[0]));// * 0x10000);
*t = FPM_ADD(temp, FPM_MUL(FPM_FROMLONG(6*(SKYSIZE/2-1)),end[1]));// * 0x10000);
}
#endif
/*
=================
D_DrawSkyScans8
=================
*/
#ifndef USE_PQ_OPT
void D_DrawSkyScans8 (espan_t *pspan)
{
int count, spancount, u, v;
unsigned char *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
int spancountminus1;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
do
{
pdest = (unsigned char *)((byte *)d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
count = pspan->count;
// calculate the initial s & t
u = pspan->u;
v = pspan->v;
D_Sky_uv_To_st (u, v, &s, &t);
do
{
if (count >= SKY_SPAN_MAX)
spancount = SKY_SPAN_MAX;
else
spancount = count;
count -= spancount;
if (count)
{
u += spancount;
// calculate s and t at far end of span,
// calculate s and t steps across span by shifting
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) >> SKY_SPAN_SHIFT;
tstep = (tnext - t) >> SKY_SPAN_SHIFT;
}
else
{
// calculate s and t at last pixel in span,
// calculate s and t steps across span by division
//Dan: I don't know why they were casting this to a float?? I removed the cast.
spancountminus1 = /*(float)*/(spancount - 1);
if (spancountminus1 > 0)
{
u += spancountminus1;
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) / spancountminus1;
tstep = (tnext - t) / spancountminus1;
}
}
do
{
*pdest++ = r_skysource[((t & R_SKY_TMASK) >> 8) +
((s & R_SKY_SMASK) >> 16)];
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
} while ((pspan = pspan->pnext) != NULL);
}
#else
//JB: Optimization
//Dan East: Will result in sky image distortion (although possibly not noticeable).
void D_DrawSkyScans8 (espan_t *pspan)
{
int count, spancount, u, v;
unsigned char *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
int spancountminus1;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
do
{
pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u);
count = pspan->count;
// calculate the initial s & t
u = pspan->u;
v = pspan->v;
D_Sky_uv_To_st (u, v, &s, &t);
spancount = count;
count -= spancount;
// calculate s and t at last pixel in span,
// calculate s and t steps across span by division
spancountminus1 = /*(float)*/(spancount - 1);
if (spancountminus1 > 0)
{
u += spancountminus1;
D_Sky_uv_To_st (u, v, &snext, &tnext);
sstep = (snext - s) / spancountminus1;
tstep = (tnext - t) / spancountminus1;
}
do
{
*pdest++ = r_skysource[((t & R_SKY_TMASK) >> 8) +
((s & R_SKY_SMASK) >> 16)];
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while ((pspan = pspan->pnext) != NULL);
}
#endif

View File

@@ -0,0 +1,839 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// d_sprite.c: software top-level rasterization driver module for drawing
// sprites
#include "quakedef.h"
#include "d_local.h"
static int sprite_height;
static int minindex, maxindex;
static sspan_t *sprite_spans;
#if !id386
/*
=====================
D_SpriteDrawSpans
=====================
*/
void D_SpriteDrawSpans (sspan_t *pspan)
{
int count, spancount, izistep;
int izi;
byte *pbase, *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
byte btemp;
short *pz;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
do
{
pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
// we count on FP exceptions being turned off to avoid range problems
izi = (int)(zi * 0x8000 * 0x10000);
s = (int)(sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int)(tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
else if (t < 0)
t = 0;
do
{
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
}
else
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
// can't step off polygon), clamp, calculate s and t steps across
// span by division, biasing steps low so we don't run off the
// texture
spancountminus1 = (float)(spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
if (spancount > 1)
{
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
do
{
btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
if (btemp != 255)
{
if (*pz <= (izi >> 16))
{
*pz = izi >> 16;
*pdest = btemp;
}
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
#ifdef USEFPM
void D_SpriteDrawSpansFPM (sspan_t *pspan)
{
//Dan: Sprite routines not yet converted to fixed point
/*
int count, spancount, izistep;
int izi;
byte *pbase, *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
byte btemp;
short *pz;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
do
{
pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
// we count on FP exceptions being turned off to avoid range problems
izi = (int)(zi * 0x8000 * 0x10000);
s = (int)(sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int)(tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
else if (t < 0)
t = 0;
do
{
// calculate s and t at the far end of the span
if (count >= 8)
spancount = 8;
else
spancount = count;
count -= spancount;
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivz8stepu;
tdivz += tdivz8stepu;
zi += zi8stepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
}
else
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
// can't step off polygon), clamp, calculate s and t steps across
// span by division, biasing steps low so we don't run off the
// texture
spancountminus1 = (float)(spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
if (spancount > 1)
{
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
do
{
btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
if (btemp != 255)
{
if (*pz <= (izi >> 16))
{
*pz = izi >> 16;
*pdest = btemp;
}
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
*/
}
#endif
#endif
/*
=====================
D_SpriteScanLeftEdge
=====================
*/
void D_SpriteScanLeftEdge (void)
{
int i, v, itop, ibottom, lmaxindex;
emitpoint_t *pvert, *pnext;
sspan_t *pspan;
float du, dv, vtop, vbottom, slope;
fixed16_t u, u_step;
pspan = sprite_spans;
i = minindex;
if (i == 0)
i = r_spritedesc.nump;
lmaxindex = maxindex;
if (lmaxindex == 0)
lmaxindex = r_spritedesc.nump;
vtop = (float)ceil (r_spritedesc.pverts[i].v);
do
{
pvert = &r_spritedesc.pverts[i];
pnext = pvert - 1;
vbottom = (float)ceil (pnext->v);
if (vtop < vbottom)
{
du = pnext->u - pvert->u;
dv = pnext->v - pvert->v;
slope = du / dv;
u_step = (int)(slope * 0x10000);
// adjust u to ceil the integer portion
u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
(0x10000 - 1);
itop = (int)vtop;
ibottom = (int)vbottom;
for (v=itop ; v<ibottom ; v++)
{
pspan->u = u >> 16;
pspan->v = v;
u += u_step;
pspan++;
}
}
vtop = vbottom;
i--;
if (i == 0)
i = r_spritedesc.nump;
} while (i != lmaxindex);
}
#ifdef USEFPM
void D_SpriteScanLeftEdgeFPM (void)
{
//Dan: Sprite routines not yet converted to fixed point
/*
int i, v, itop, ibottom, lmaxindex;
emitpoint_t *pvert, *pnext;
sspan_t *pspan;
float du, dv, vtop, vbottom, slope;
fixed16_t u, u_step;
pspan = sprite_spans;
i = minindex;
if (i == 0)
i = r_spritedesc.nump;
lmaxindex = maxindex;
if (lmaxindex == 0)
lmaxindex = r_spritedesc.nump;
vtop = ceil (r_spritedesc.pverts[i].v);
do
{
pvert = &r_spritedesc.pverts[i];
pnext = pvert - 1;
vbottom = ceil (pnext->v);
if (vtop < vbottom)
{
du = pnext->u - pvert->u;
dv = pnext->v - pvert->v;
slope = du / dv;
u_step = (int)(slope * 0x10000);
// adjust u to ceil the integer portion
u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
(0x10000 - 1);
itop = (int)vtop;
ibottom = (int)vbottom;
for (v=itop ; v<ibottom ; v++)
{
pspan->u = u >> 16;
pspan->v = v;
u += u_step;
pspan++;
}
}
vtop = vbottom;
i--;
if (i == 0)
i = r_spritedesc.nump;
} while (i != lmaxindex);
*/
}
#endif
/*
=====================
D_SpriteScanRightEdge
=====================
*/
void D_SpriteScanRightEdge (void)
{
int i, v, itop, ibottom;
emitpoint_t *pvert, *pnext;
sspan_t *pspan;
float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
fixed16_t u, u_step;
pspan = sprite_spans;
i = minindex;
vvert = r_spritedesc.pverts[i].v;
if (vvert < r_refdef.fvrecty_adj)
vvert = r_refdef.fvrecty_adj;
if (vvert > r_refdef.fvrectbottom_adj)
vvert = r_refdef.fvrectbottom_adj;
vtop = (float)ceil (vvert);
do
{
pvert = &r_spritedesc.pverts[i];
pnext = pvert + 1;
vnext = pnext->v;
if (vnext < r_refdef.fvrecty_adj)
vnext = r_refdef.fvrecty_adj;
if (vnext > r_refdef.fvrectbottom_adj)
vnext = r_refdef.fvrectbottom_adj;
vbottom = (float)ceil (vnext);
if (vtop < vbottom)
{
uvert = pvert->u;
if (uvert < r_refdef.fvrectx_adj)
uvert = r_refdef.fvrectx_adj;
if (uvert > r_refdef.fvrectright_adj)
uvert = r_refdef.fvrectright_adj;
unext = pnext->u;
if (unext < r_refdef.fvrectx_adj)
unext = r_refdef.fvrectx_adj;
if (unext > r_refdef.fvrectright_adj)
unext = r_refdef.fvrectright_adj;
du = unext - uvert;
dv = vnext - vvert;
slope = du / dv;
u_step = (int)(slope * 0x10000);
// adjust u to ceil the integer portion
u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
(0x10000 - 1);
itop = (int)vtop;
ibottom = (int)vbottom;
for (v=itop ; v<ibottom ; v++)
{
pspan->count = (u >> 16) - pspan->u;
u += u_step;
pspan++;
}
}
vtop = vbottom;
vvert = vnext;
i++;
if (i == r_spritedesc.nump)
i = 0;
} while (i != maxindex);
pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
}
#ifdef USEFPM
void D_SpriteScanRightEdgeFPM (void)
{
//Dan: Sprite routines not yet converted to fixed point
/*
int i, v, itop, ibottom;
emitpoint_t *pvert, *pnext;
sspan_t *pspan;
float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
fixed16_t u, u_step;
pspan = sprite_spans;
i = minindex;
vvert = r_spritedesc.pverts[i].v;
if (vvert < r_refdef.fvrecty_adj)
vvert = r_refdef.fvrecty_adj;
if (vvert > r_refdef.fvrectbottom_adj)
vvert = r_refdef.fvrectbottom_adj;
vtop = ceil (vvert);
do
{
pvert = &r_spritedesc.pverts[i];
pnext = pvert + 1;
vnext = pnext->v;
if (vnext < r_refdef.fvrecty_adj)
vnext = r_refdef.fvrecty_adj;
if (vnext > r_refdef.fvrectbottom_adj)
vnext = r_refdef.fvrectbottom_adj;
vbottom = ceil (vnext);
if (vtop < vbottom)
{
uvert = pvert->u;
if (uvert < r_refdef.fvrectx_adj)
uvert = r_refdef.fvrectx_adj;
if (uvert > r_refdef.fvrectright_adj)
uvert = r_refdef.fvrectright_adj;
unext = pnext->u;
if (unext < r_refdef.fvrectx_adj)
unext = r_refdef.fvrectx_adj;
if (unext > r_refdef.fvrectright_adj)
unext = r_refdef.fvrectright_adj;
du = unext - uvert;
dv = vnext - vvert;
slope = du / dv;
u_step = (int)(slope * 0x10000);
// adjust u to ceil the integer portion
u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
(0x10000 - 1);
itop = (int)vtop;
ibottom = (int)vbottom;
for (v=itop ; v<ibottom ; v++)
{
pspan->count = (u >> 16) - pspan->u;
u += u_step;
pspan++;
}
}
vtop = vbottom;
vvert = vnext;
i++;
if (i == r_spritedesc.nump)
i = 0;
} while (i != maxindex);
pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
*/
}
#endif
/*
=====================
D_SpriteCalculateGradients
=====================
*/
void D_SpriteCalculateGradients (void)
{
vec3_t p_normal, p_saxis, p_taxis, p_temp1;
float distinv;
TransformVector (r_spritedesc.vpn, p_normal);
TransformVector (r_spritedesc.vright, p_saxis);
TransformVector (r_spritedesc.vup, p_taxis);
VectorInverse (p_taxis);
distinv = (float)(1.0 / (-DotProduct (modelorg, r_spritedesc.vpn)));
d_sdivzstepu = p_saxis[0] * xscaleinv;
d_tdivzstepu = p_taxis[0] * xscaleinv;
d_sdivzstepv = -p_saxis[1] * yscaleinv;
d_tdivzstepv = -p_taxis[1] * yscaleinv;
d_zistepu = p_normal[0] * xscaleinv * distinv;
d_zistepv = -p_normal[1] * yscaleinv * distinv;
d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu -
ycenter * d_sdivzstepv;
d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu -
ycenter * d_tdivzstepv;
d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu -
ycenter * d_zistepv;
TransformVector (modelorg, p_temp1);
sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
(-(cachewidth >> 1) << 16);
tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
(-(sprite_height >> 1) << 16);
// -1 (-epsilon) so we never wander off the edge of the texture
bbextents = (cachewidth << 16) - 1;
bbextentt = (sprite_height << 16) - 1;
}
#ifdef USEFPM
void D_SpriteCalculateGradientsFPM (void)
{
//Dan: Sprite routines not yet converted to fixed point
/*
vec3_t p_normal, p_saxis, p_taxis, p_temp1;
float distinv;
TransformVector (r_spritedesc.vpn, p_normal);
TransformVector (r_spritedesc.vright, p_saxis);
TransformVector (r_spritedesc.vup, p_taxis);
VectorInverse (p_taxis);
distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn));
d_sdivzstepu = p_saxis[0] * xscaleinv;
d_tdivzstepu = p_taxis[0] * xscaleinv;
d_sdivzstepv = -p_saxis[1] * yscaleinv;
d_tdivzstepv = -p_taxis[1] * yscaleinv;
d_zistepu = p_normal[0] * xscaleinv * distinv;
d_zistepv = -p_normal[1] * yscaleinv * distinv;
d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu -
ycenter * d_sdivzstepv;
d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu -
ycenter * d_tdivzstepv;
d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu -
ycenter * d_zistepv;
TransformVector (modelorg, p_temp1);
sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
(-(cachewidth >> 1) << 16);
tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
(-(sprite_height >> 1) << 16);
// -1 (-epsilon) so we never wander off the edge of the texture
bbextents = (cachewidth << 16) - 1;
bbextentt = (sprite_height << 16) - 1;
*/
}
#endif
/*
=====================
D_DrawSprite
=====================
*/
void D_DrawSprite (void)
{
int i, nump;
float ymin, ymax;
emitpoint_t *pverts;
sspan_t spans[MAXHEIGHT+1];
sprite_spans = spans;
// find the top and bottom vertices, and make sure there's at least one scan to
// draw
ymin = (float)999999.9;
ymax = (float)-999999.9;
pverts = r_spritedesc.pverts;
for (i=0 ; i<r_spritedesc.nump ; i++)
{
if (pverts->v < ymin)
{
ymin = pverts->v;
minindex = i;
}
if (pverts->v > ymax)
{
ymax = pverts->v;
maxindex = i;
}
pverts++;
}
ymin = (float)ceil (ymin);
ymax = (float)ceil (ymax);
if (ymin >= ymax)
return; // doesn't cross any scans at all
cachewidth = r_spritedesc.pspriteframe->width;
sprite_height = r_spritedesc.pspriteframe->height;
cacheblock = (byte *)&r_spritedesc.pspriteframe->pixels[0];
// copy the first vertex to the last vertex, so we don't have to deal with
// wrapping
nump = r_spritedesc.nump;
pverts = r_spritedesc.pverts;
pverts[nump] = pverts[0];
D_SpriteCalculateGradients ();
D_SpriteScanLeftEdge ();
D_SpriteScanRightEdge ();
D_SpriteDrawSpans (sprite_spans);
}
#ifdef USEFPM
void D_DrawSpriteFPM (void)
{
int i, nump;
fixedpoint_t ymin, ymax;
emitpoint_FPM_t *pverts;
sspan_t spans[MAXHEIGHT+1];
sprite_spans = spans;
// find the top and bottom vertices, and make sure there's at least one scan to
// draw
ymin = FPM_FROMFLOAT(999999.9);
ymax = FPM_FROMFLOAT(-999999.9);
pverts = r_spritedescFPM.pverts;
for (i=0 ; i<r_spritedescFPM.nump ; i++)
{
if (pverts->v < ymin)
{
ymin = pverts->v;
minindex = i;
}
if (pverts->v > ymax)
{
ymax = pverts->v;
maxindex = i;
}
pverts++;
}
ymin = FPM_CEIL (ymin);
ymax = FPM_CEIL (ymax);
if (ymin >= ymax)
return; // doesn't cross any scans at all
cachewidth = r_spritedescFPM.pspriteframe->width;
sprite_height = r_spritedescFPM.pspriteframe->height;
cacheblock = (byte *)&r_spritedescFPM.pspriteframe->pixels[0];
// copy the first vertex to the last vertex, so we don't have to deal with
// wrapping
nump = r_spritedescFPM.nump;
pverts = r_spritedescFPM.pverts;
pverts[nump] = pverts[0];
D_SpriteCalculateGradientsFPM ();
D_SpriteScanLeftEdgeFPM ();
D_SpriteScanRightEdgeFPM ();
D_SpriteDrawSpansFPM (sprite_spans);
}
#endif

View File

@@ -0,0 +1,571 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// d_surf.c: rasterization driver surface heap manager
#include "quakedef.h"
#include "d_local.h"
#include "r_local.h"
float surfscale;
qboolean r_cache_thrash; // set if surface cache is thrashing
int sc_size;
surfcache_t *sc_rover, *sc_base;
#ifdef USEFPM
fixedpoint_t surfscaleFPM;
surfcache_FPM_t *sc_roverFPM, *sc_baseFPM;
#endif
#define GUARDSIZE 4
int D_SurfaceCacheForRes (int width, int height)
{
int size, pix;
if (COM_CheckParm ("-surfcachesize"))
{
size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024;
return size;
}
size = SURFCACHE_SIZE_AT_320X200;
pix = width*height;
if (pix > 64000)
size += (pix-64000)*3;
return size;
}
void D_CheckCacheGuard (void)
{
byte *s;
int i;
s = (byte *)sc_base + sc_size;
for (i=0 ; i<GUARDSIZE ; i++)
if (s[i] != (byte)i)
Sys_Error ("D_CheckCacheGuard: failed");
}
#ifdef USEFPM
void D_CheckCacheGuardFPM (void)
{
byte *s;
int i;
s = (byte *)sc_baseFPM + sc_size;
for (i=0 ; i<GUARDSIZE ; i++)
if (s[i] != (byte)i)
Sys_Error ("D_CheckCacheGuard: failed");
}
#endif
void D_ClearCacheGuard (void)
{
byte *s;
int i;
s = (byte *)sc_base + sc_size;
for (i=0 ; i<GUARDSIZE ; i++)
s[i] = (byte)i;
}
#ifdef USEFPM
void D_ClearCacheGuardFPM (void)
{
byte *s;
int i;
s = (byte *)sc_baseFPM + sc_size;
for (i=0 ; i<GUARDSIZE ; i++)
s[i] = (byte)i;
}
#endif
/*
================
D_InitCaches
================
*/
void D_InitCaches (void *buffer, int size)
{
if (!msg_suppress_1)
Con_Printf ("%ik surface cache\n", size/1024);
sc_size = size - GUARDSIZE;
sc_base = (surfcache_t *)buffer;
sc_rover = sc_base;
sc_base->next = NULL;
sc_base->owner = NULL;
sc_base->size = sc_size;
D_ClearCacheGuard ();
}
#ifdef USEFPM
void D_InitCachesFPM (void *buffer, int size)
{
if (!msg_suppress_1)
Con_Printf ("%ik surface cache\n", size/1024);
sc_size = size - GUARDSIZE;
sc_baseFPM = (surfcache_FPM_t *)buffer;
sc_roverFPM = sc_baseFPM;
sc_baseFPM->next = NULL;
sc_baseFPM->owner = NULL;
sc_baseFPM->size = sc_size;
D_ClearCacheGuardFPM ();
}
#endif
/*
==================
D_FlushCaches
==================
*/
void D_FlushCaches (void)
{
surfcache_t *c;
if (!sc_base)
return;
for (c = sc_base ; c ; c = c->next)
{
if (c->owner)
*c->owner = NULL;
}
sc_rover = sc_base;
sc_base->next = NULL;
sc_base->owner = NULL;
sc_base->size = sc_size;
}
#ifdef USEFPM
void D_FlushCachesFPM (void)
{
surfcache_FPM_t *c;
if (!sc_baseFPM)
return;
for (c = sc_baseFPM ; c ; c = c->next)
{
if (c->owner)
*c->owner = NULL;
}
sc_roverFPM = sc_baseFPM;
sc_baseFPM->next = NULL;
sc_baseFPM->owner = NULL;
sc_baseFPM->size = sc_size;
}
#endif
/*
=================
D_SCAlloc
=================
*/
surfcache_t *D_SCAlloc (int width, int size)
{
surfcache_t *new;
qboolean wrapped_this_time;
if ((width < 0) || (width > 256))
Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
if ((size <= 0) || (size > 0x10000))
Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
size = (int)&((surfcache_t *)0)->data[size];
size = (size + 3) & ~3;
if (size > sc_size)
Sys_Error ("D_SCAlloc: %i > cache size",size);
// if there is not size bytes after the rover, reset to the start
wrapped_this_time = false;
if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
{
if (sc_rover)
{
wrapped_this_time = true;
}
sc_rover = sc_base;
}
// colect and free surfcache_t blocks until the rover block is large enough
new = sc_rover;
if (sc_rover->owner)
*sc_rover->owner = NULL;
while (new->size < size)
{
// free another
sc_rover = sc_rover->next;
if (!sc_rover)
Sys_Error ("D_SCAlloc: hit the end of memory");
if (sc_rover->owner)
*sc_rover->owner = NULL;
new->size += sc_rover->size;
new->next = sc_rover->next;
}
// create a fragment out of any leftovers
if (new->size - size > 256)
{
sc_rover = (surfcache_t *)( (byte *)new + size);
sc_rover->size = new->size - size;
sc_rover->next = new->next;
sc_rover->width = 0;
sc_rover->owner = NULL;
new->next = sc_rover;
new->size = size;
}
else
sc_rover = new->next;
new->width = width;
// DEBUG
if (width > 0)
new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
new->owner = NULL; // should be set properly after return
if (d_roverwrapped)
{
if (wrapped_this_time || (sc_rover >= d_initial_rover))
r_cache_thrash = true;
}
else if (wrapped_this_time)
{
d_roverwrapped = true;
}
D_CheckCacheGuard (); // DEBUG
return new;
}
#ifdef USEFPM
surfcache_FPM_t *D_SCAllocFPM (int width, int size)
{
surfcache_FPM_t *new;
qboolean wrapped_this_time;
if ((width < 0) || (width > 256))
Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
if ((size <= 0) || (size > 0x10000))
Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
size = (int)&((surfcache_FPM_t *)0)->data[size];
size = (size + 3) & ~3;
if (size > sc_size)
Sys_Error ("D_SCAlloc: %i > cache size",size);
// if there is not size bytes after the rover, reset to the start
wrapped_this_time = false;
if ( !sc_roverFPM || (byte *)sc_roverFPM - (byte *)sc_baseFPM > sc_size - size)
{
if (sc_roverFPM)
{
wrapped_this_time = true;
}
sc_roverFPM = sc_baseFPM;
}
// colect and free surfcache_t blocks until the rover block is large enough
new = sc_roverFPM;
if (sc_roverFPM->owner)
*sc_roverFPM->owner = NULL;
while (new->size < size)
{
// free another
sc_roverFPM = sc_roverFPM->next;
if (!sc_roverFPM)
Sys_Error ("D_SCAlloc: hit the end of memory");
if (sc_roverFPM->owner)
*sc_roverFPM->owner = NULL;
new->size += sc_roverFPM->size;
new->next = sc_roverFPM->next;
}
// create a fragment out of any leftovers
if (new->size - size > 256)
{
sc_roverFPM = (surfcache_FPM_t *)( (byte *)new + size);
sc_roverFPM->size = new->size - size;
sc_roverFPM->next = new->next;
sc_roverFPM->width = 0;
sc_roverFPM->owner = NULL;
new->next = sc_roverFPM;
new->size = size;
}
else
sc_roverFPM = new->next;
new->width = width;
// DEBUG
if (width > 0)
new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
new->owner = NULL; // should be set properly after return
if (d_roverwrapped)
{
if (wrapped_this_time || (sc_roverFPM >= d_initial_roverFPM))
r_cache_thrash = true;
}
else if (wrapped_this_time)
{
d_roverwrapped = true;
}
D_CheckCacheGuardFPM (); // DEBUG
return new;
}
#endif
/*
=================
D_SCDump
=================
*/
void D_SCDump (void)
{
surfcache_t *test;
for (test = sc_base ; test ; test = test->next)
{
if (test == sc_rover)
Sys_Printf ("ROVER:\n");
printf ("%p : %i bytes %i width\n",test, test->size, test->width);
}
}
#ifdef USEFPM
void D_SCDumpFPM (void)
{
surfcache_FPM_t *test;
for (test = sc_baseFPM ; test ; test = test->next)
{
if (test == sc_roverFPM)
Sys_Printf ("ROVER:\n");
printf ("%p : %i bytes %i width\n",test, test->size, test->width);
}
}
#endif
//=============================================================================
// if the num is not a power of 2, assume it will not repeat
int MaskForNum (int num)
{
if (num==128)
return 127;
if (num==64)
return 63;
if (num==32)
return 31;
if (num==16)
return 15;
return 255;
}
int D_log2 (int num)
{
int c;
c = 0;
while (num>>=1)
c++;
return c;
}
//=============================================================================
/*
================
D_CacheSurface
================
*/
surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
{
surfcache_t *cache;
//
// if the surface is animating or flashing, flush the cache
//
r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
//
// see if the cache holds apropriate data
//
cache = surface->cachespots[miplevel];
if (cache && !cache->dlight && surface->dlightframe != r_framecount
&& cache->texture == r_drawsurf.texture
&& cache->lightadj[0] == r_drawsurf.lightadj[0]
&& cache->lightadj[1] == r_drawsurf.lightadj[1]
&& cache->lightadj[2] == r_drawsurf.lightadj[2]
&& cache->lightadj[3] == r_drawsurf.lightadj[3] )
return cache;
//
// determine shape of surface
//
surfscale = (float) 1.0 / (1<<miplevel);
r_drawsurf.surfmip = miplevel;
r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
r_drawsurf.rowbytes = r_drawsurf.surfwidth;
r_drawsurf.surfheight = surface->extents[1] >> miplevel;
//
// allocate memory if needed
//
if (!cache) // if a texture just animated, don't reallocate it
{
cache = D_SCAlloc (r_drawsurf.surfwidth,
r_drawsurf.surfwidth * r_drawsurf.surfheight);
surface->cachespots[miplevel] = cache;
cache->owner = &surface->cachespots[miplevel];
cache->mipscale = surfscale;
}
if (surface->dlightframe == r_framecount)
cache->dlight = 1;
else
cache->dlight = 0;
r_drawsurf.surfdat = (pixel_t *)cache->data;
cache->texture = r_drawsurf.texture;
cache->lightadj[0] = r_drawsurf.lightadj[0];
cache->lightadj[1] = r_drawsurf.lightadj[1];
cache->lightadj[2] = r_drawsurf.lightadj[2];
cache->lightadj[3] = r_drawsurf.lightadj[3];
//
// draw and light the surface texture
//
r_drawsurf.surf = surface;
c_surf++;
R_DrawSurface ();
return surface->cachespots[miplevel];
}
#ifdef USEFPM
surfcache_FPM_t *D_CacheSurfaceFPM (msurface_FPM_t *surface, int miplevel)
{
surfcache_FPM_t *cache;
//
// if the surface is animating or flashing, flush the cache
//
r_drawsurfFPM.texture = R_TextureAnimationFPM (surface->texinfo->texture);
r_drawsurfFPM.lightadj[0] = d_lightstylevalue[surface->styles[0]];
r_drawsurfFPM.lightadj[1] = d_lightstylevalue[surface->styles[1]];
r_drawsurfFPM.lightadj[2] = d_lightstylevalue[surface->styles[2]];
r_drawsurfFPM.lightadj[3] = d_lightstylevalue[surface->styles[3]];
//
// see if the cache holds apropriate data
//
cache = surface->cachespots[miplevel];
if (cache && !cache->dlight && surface->dlightframe != r_framecount
&& cache->texture == r_drawsurfFPM.texture
&& cache->lightadj[0] == r_drawsurfFPM.lightadj[0]
&& cache->lightadj[1] == r_drawsurfFPM.lightadj[1]
&& cache->lightadj[2] == r_drawsurfFPM.lightadj[2]
&& cache->lightadj[3] == r_drawsurfFPM.lightadj[3] )
return cache;
//
// determine shape of surface
//
surfscaleFPM = FPM_INV(FPM_FROMLONG(1<<miplevel));
r_drawsurfFPM.surfmip = miplevel;
r_drawsurfFPM.surfwidth = surface->extents[0] >> miplevel;
r_drawsurfFPM.rowbytes = r_drawsurfFPM.surfwidth;
r_drawsurfFPM.surfheight = surface->extents[1] >> miplevel;
//
// allocate memory if needed
//
if (!cache) // if a texture just animated, don't reallocate it
{
cache = (surfcache_FPM_t *)D_SCAllocFPM (r_drawsurfFPM.surfwidth,
r_drawsurfFPM.surfwidth * r_drawsurfFPM.surfheight);
surface->cachespots[miplevel] = cache;
cache->owner = &surface->cachespots[miplevel];
cache->mipscale = surfscaleFPM;
}
if (surface->dlightframe == r_framecount)
cache->dlight = 1;
else
cache->dlight = 0;
r_drawsurfFPM.surfdat = (pixel_t *)cache->data;
cache->texture = r_drawsurfFPM.texture;
cache->lightadj[0] = r_drawsurfFPM.lightadj[0];
cache->lightadj[1] = r_drawsurfFPM.lightadj[1];
cache->lightadj[2] = r_drawsurfFPM.lightadj[2];
cache->lightadj[3] = r_drawsurfFPM.lightadj[3];
//
// draw and light the surface texture
//
r_drawsurfFPM.surf = surface;
c_surf++;
R_DrawSurfaceFPM ();
return surface->cachespots[miplevel];
}
#endif

View File

@@ -0,0 +1,70 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_vars.c: global refresh variables
#if !id386
#include "quakedef.h"
// all global and static refresh variables are collected in a contiguous block
// to avoid cache conflicts.
//-------------------------------------------------------
// global refresh variables
//-------------------------------------------------------
// FIXME: make into one big structure, like cl or sv
// FIXME: do separately for refresh engine and driver
float d_sdivzstepu, d_tdivzstepu, d_zistepu;
float d_sdivzstepv, d_tdivzstepv, d_zistepv;
float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
#ifdef USE_PQ_OPT3
int d_sdivzstepu_fxp, d_tdivzstepu_fxp, d_zistepu_fxp;
int d_sdivzstepv_fxp, d_tdivzstepv_fxp, d_zistepv_fxp;
int d_sdivzorigin_fxp, d_tdivzorigin_fxp, d_ziorigin_fxp;
#endif
int d_ziorigin_fxp, d_zistepv_fxp, d_zistepu_fxp;
#ifdef USE_PQ_OPT
//JB: Optimization
int sdivzstepu, tdivzstepu, zistepu;
int sdivzstepv, tdivzstepv, zistepv;
int sdivzorigin, tdivzorigin, ziorigin;
#endif
#ifdef USEFPM
fixedpoint_t d_sdivzstepuFPM, d_tdivzstepuFPM, d_zistepuFPM;
fixedpoint_t d_sdivzstepvFPM, d_tdivzstepvFPM, d_zistepvFPM;
fixedpoint_t d_sdivzoriginFPM, d_tdivzoriginFPM, d_zioriginFPM;
#endif
fixed16_t sadjust, tadjust, bbextents, bbextentt;
pixel_t *cacheblock;
int cachewidth;
pixel_t *d_viewbuffer;
short *d_pzbuffer;
unsigned int d_zrowbytes;
unsigned int d_zwidth;
#endif // !id386

View File

@@ -0,0 +1,67 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// d_zpoint.c: software driver module for drawing z-buffered points
#include "quakedef.h"
#include "d_local.h"
/*
=====================
D_DrawZPoint
=====================
*/
void D_DrawZPoint (void)
{
byte *pdest;
short *pz;
int izi;
pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u;
pdest = d_viewbuffer + d_scantable[r_zpointdesc.v] + r_zpointdesc.u;
izi = (int)(r_zpointdesc.zi * 0x8000);
if (*pz <= izi)
{
*pz = izi;
*pdest = r_zpointdesc.color;
}
}
#ifdef USEFPM
void D_DrawZPointFPM (void)
{
byte *pdest;
short *pz;
int izi;
pz = d_pzbuffer + (d_zwidth * r_zpointdescFPM.v) + r_zpointdescFPM.u;
pdest = d_viewbuffer + d_scantable[r_zpointdescFPM.v] + r_zpointdescFPM.u;
//Dan: Is this right?
izi = FPM_TOLONG(r_zpointdescFPM.zi>>1);
// izi = (int)(r_zpointdescFPM.zi * 0x8000);
if (*pz <= izi)
{
*pz = izi;
*pdest = r_zpointdescFPM.color;
}
}
#endif

View File

@@ -0,0 +1,938 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// draw.c -- this is the only file outside the refresh that touches the
// vid buffer
#include "quakedef.h"
typedef struct {
vrect_t rect;
int width;
int height;
byte *ptexbytes;
int rowbytes;
} rectdesc_t;
static rectdesc_t r_rectdesc;
byte *draw_chars; // 8*8 graphic characters
qpic_t *draw_disc;
qpic_t *draw_backtile;
//=============================================================================
/* Support Routines */
typedef struct cachepic_s
{
char name[MAX_QPATH];
cache_user_t cache;
} cachepic_t;
#define MAX_CACHED_PICS 128
cachepic_t menu_cachepics[MAX_CACHED_PICS];
int menu_numcachepics;
qpic_t *Draw_PicFromWad (char *name)
{
return W_GetLumpName (name);
}
/*
================
Draw_CachePic
================
*/
qpic_t *Draw_CachePic (char *path)
{
cachepic_t *pic;
int i;
qpic_t *dat;
for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
if (!strcmp (path, pic->name))
break;
if (i == menu_numcachepics)
{
if (menu_numcachepics == MAX_CACHED_PICS)
Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
menu_numcachepics++;
strcpy (pic->name, path);
}
dat = Cache_Check (&pic->cache);
if (dat)
return dat;
//
// load the pic from disk
//
COM_LoadCacheFile (path, &pic->cache);
dat = (qpic_t *)pic->cache.data;
if (!dat)
{
Sys_Error ("Draw_CachePic: failed to load %s", path);
}
SwapPic (dat);
return dat;
}
/*
===============
Draw_Init
===============
*/
void Draw_Init (void)
{
// int i;
draw_chars = W_GetLumpName ("conchars");
draw_disc = W_GetLumpName ("disc");
draw_backtile = W_GetLumpName ("backtile");
r_rectdesc.width = draw_backtile->width;
r_rectdesc.height = draw_backtile->height;
r_rectdesc.ptexbytes = draw_backtile->data;
r_rectdesc.rowbytes = draw_backtile->width;
}
/*
================
Draw_Character
Draws one 8*8 graphics character with 0 being transparent.
It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off.
================
*/
void Draw_Character (int x, int y, int num)
{
byte *dest;
byte *source;
unsigned short *pusdest;
int drawline;
int row, col;
num &= 255;
if (y <= -8)
return; // totally off screen
#ifdef PARANOID
if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
Sys_Error ("Con_DrawCharacter: (%i, %i)", x, y);
if (num < 0 || num > 255)
Sys_Error ("Con_DrawCharacter: char %i", num);
#endif
row = num>>4;
col = num&15;
source = draw_chars + (row<<10) + (col<<3);
if (y < 0)
{ // clipped
drawline = 8 + y;
source -= 128*y;
y = 0;
}
else
drawline = 8;
if (r_pixbytes == 1)
{
dest = vid.conbuffer + y*vid.conrowbytes + x;
while (drawline--)
{
if (source[0])
dest[0] = source[0];
if (source[1])
dest[1] = source[1];
if (source[2])
dest[2] = source[2];
if (source[3])
dest[3] = source[3];
if (source[4])
dest[4] = source[4];
if (source[5])
dest[5] = source[5];
if (source[6])
dest[6] = source[6];
if (source[7])
dest[7] = source[7];
source += 128;
dest += vid.conrowbytes;
}
}
else
{
// FIXME: pre-expand to native format?
pusdest = (unsigned short *)
((byte *)vid.conbuffer + y*vid.conrowbytes + (x<<1));
while (drawline--)
{
if (source[0])
pusdest[0] = d_8to16table[source[0]];
if (source[1])
pusdest[1] = d_8to16table[source[1]];
if (source[2])
pusdest[2] = d_8to16table[source[2]];
if (source[3])
pusdest[3] = d_8to16table[source[3]];
if (source[4])
pusdest[4] = d_8to16table[source[4]];
if (source[5])
pusdest[5] = d_8to16table[source[5]];
if (source[6])
pusdest[6] = d_8to16table[source[6]];
if (source[7])
pusdest[7] = d_8to16table[source[7]];
source += 128;
pusdest += (vid.conrowbytes >> 1);
}
}
}
/*
================
Draw_String
================
*/
void Draw_String (int x, int y, char *str)
{
while (*str)
{
Draw_Character (x, y, *str);
str++;
x += 8;
}
}
/*
================
Draw_DebugChar
Draws a single character directly to the upper right corner of the screen.
This is for debugging lockups by drawing different chars in different parts
of the code.
================
*/
void Draw_DebugChar (char num)
{
byte *dest;
byte *source;
int drawline;
extern byte *draw_chars;
int row, col;
if (!vid.direct)
return; // don't have direct FB access, so no debugchars...
drawline = 8;
row = num>>4;
col = num&15;
source = draw_chars + (row<<10) + (col<<3);
dest = vid.direct + 312;
while (drawline--)
{
dest[0] = source[0];
dest[1] = source[1];
dest[2] = source[2];
dest[3] = source[3];
dest[4] = source[4];
dest[5] = source[5];
dest[6] = source[6];
dest[7] = source[7];
source += 128;
dest += 320;
}
}
/*
=============
Draw_Pic
=============
*/
void Draw_Pic (int x, int y, qpic_t *pic)
{
// byte *dest, *source;
// unsigned short *pusdest;
// int v, u;
Draw_TransPic(x, y, pic);
/*
if ((x < 0) ||
(x + pic->width > vid.width) ||
(y < 0) ||
(y + pic->height > vid.height))
{
Sys_Error ("Draw_Pic: bad coordinates");
}
source = pic->data;
if (r_pixbytes == 1)
{
dest = vid.buffer + y * vid.rowbytes + x;
for (v=0 ; v<pic->height ; v++)
{
Q_memcpy (dest, source, pic->width);
dest += vid.rowbytes;
source += pic->width;
}
}
else
{
// FIXME: pretranslate at load time?
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
for (v=0 ; v<pic->height ; v++)
{
for (u=0 ; u<pic->width ; u++)
{
pusdest[u] = d_8to16table[source[u]];
}
pusdest += vid.rowbytes >> 1;
source += pic->width;
}
}
*/
}
/*
=============
Draw_TransPic
=============
*/
void Draw_TransPic (int x, int y, qpic_t *pic)
{
byte *dest, *source, tbyte;
unsigned short *pusdest;
int v, u;
int w, h;
if (x < 0 || y < 0)
{
Sys_Error ("Draw_TransPic: bad coordinates");
}
if ((unsigned)(x + pic->width) > vid.width) w=vid.width-x;
else w=pic->width;
if ((unsigned)(y + pic->height) > vid.height) h=vid.height-y;
else h=pic->height;
/*
if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
(unsigned)(y + pic->height) > vid.height)
{
Sys_Error ("Draw_TransPic: bad coordinates");
}
*/
source = pic->data;
if (r_pixbytes == 1)
{
dest = vid.buffer + y * vid.rowbytes + x;
if (pic->width & 7)
{ // general
for (v=0 ; v<h/*pic->height*/ ; v++)
{
for (u=0 ; u<w/*pic->width*/ ; u++)
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
dest[u] = tbyte;
dest += vid.rowbytes;
source += pic->width;
}
}
else
{ // unwound
for (v=0 ; v<h/*pic->height*/ ; v++)
{
for (u=0 ; u<w/*pic->width*/ ; u+=8)
{
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
dest[u] = tbyte;
if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
dest[u+1] = tbyte;
if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
dest[u+2] = tbyte;
if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
dest[u+3] = tbyte;
if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
dest[u+4] = tbyte;
if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
dest[u+5] = tbyte;
if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
dest[u+6] = tbyte;
if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
dest[u+7] = tbyte;
}
dest += vid.rowbytes;
source += pic->width;
}
}
}
else
{
// FIXME: pretranslate at load time?
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
for (v=0 ; v<h/*pic->height*/ ; v++)
{
for (u=0 ; u<w/*pic->width*/ ; u++)
{
tbyte = source[u];
if (tbyte != TRANSPARENT_COLOR)
{
pusdest[u] = d_8to16table[tbyte];
}
}
pusdest += vid.rowbytes >> 1;
source += pic->width;
}
}
}
/*
=============
Draw_TransPicTranslate
=============
*/
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
{
byte *dest, *source, tbyte;
unsigned short *pusdest;
int v, u;
int w, h;
/*
if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
(unsigned)(y + pic->height) > vid.height)
{
Sys_Error ("Draw_TransPic: bad coordinates");
}
*/
if (x < 0 || y < 0)
{
Sys_Error ("Draw_TransPicTranslate: bad coordinates");
}
if ((unsigned)(x + pic->width) > vid.width) w=vid.width-x;
else w=pic->width;
if ((unsigned)(y + pic->height) > vid.height) w=vid.height-y;
else h=pic->height;
source = pic->data;
if (r_pixbytes == 1)
{
dest = vid.buffer + y * vid.rowbytes + x;
if (w /*pic->width*/ & 7)
{ // general
for (v=0 ; v<h/*pic->height*/ ; v++)
{
for (u=0 ; u<w/*pic->width*/ ; u++)
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
dest[u] = translation[tbyte];
dest += vid.rowbytes;
source += pic->width;
}
}
else
{ // unwound
for (v=0 ; v<h/*pic->height*/ ; v++)
{
for (u=0 ; u<w/*pic->width*/ ; u+=8)
{
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
dest[u] = translation[tbyte];
if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
dest[u+1] = translation[tbyte];
if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
dest[u+2] = translation[tbyte];
if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
dest[u+3] = translation[tbyte];
if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
dest[u+4] = translation[tbyte];
if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
dest[u+5] = translation[tbyte];
if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
dest[u+6] = translation[tbyte];
if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
dest[u+7] = translation[tbyte];
}
dest += vid.rowbytes;
source += pic->width;
}
}
}
else
{
// FIXME: pretranslate at load time?
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
for (v=0 ; v<h/*pic->height*/ ; v++)
{
for (u=0 ; u<w/*pic->width*/ ; u++)
{
tbyte = source[u];
if (tbyte != TRANSPARENT_COLOR)
{
pusdest[u] = d_8to16table[tbyte];
}
}
pusdest += vid.rowbytes >> 1;
source += pic->width;
}
}
}
void Draw_CharToConback (int num, byte *dest)
{
int row, col;
byte *source;
int drawline;
int x;
row = num>>4;
col = num&15;
source = draw_chars + (row<<10) + (col<<3);
drawline = 8;
while (drawline--)
{
for (x=0 ; x<8 ; x++)
if (source[x])
dest[x] = 0x60 + source[x];
source += 128;
dest += 320;
}
}
/*
================
Draw_ConsoleBackground
================
*/
void Draw_ConsoleBackground (int lines)
{
int x, y, v;
byte *src, *dest;
unsigned short *pusdest;
int f, fstep;
qpic_t *conback;
char ver[256];
conback = Draw_CachePic ("gfx/conback.lmp");
// hack the version number directly into the pic
// sprintf (ver, "(Pocket Quake) %4.2f", (float)VERSION);
sprintf (ver, "Quake(SDL) %4.2f R2-Tec", (float)GP2X_VERSION);
dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
/*
#ifdef _WIN32
sprintf (ver, "(WinQuake) %4.2f", (float)VERSION);
dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
#elif defined(X11)
sprintf (ver, "(X11 Quake %2.2f) %4.2f", (float)X11_VERSION, (float)VERSION);
dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
#elif defined(__linux__)
sprintf (ver, "(Linux Quake %2.2f) %4.2f", (float)LINUX_VERSION, (float)VERSION);
dest = conback->data + 320*186 + 320 - 11 - 8*strlen(ver);
#else
dest = conback->data + 320 - 43 + 320*186;
sprintf (ver, "%4.2f", VERSION);
#endif
*/
for (x=0 ; x<(int)strlen(ver) ; x++)
Draw_CharToConback (ver[x], dest+(x<<3));
// draw the pic
if (r_pixbytes == 1)
{
dest = vid.conbuffer;
for (y=0 ; y<lines ; y++, dest += vid.conrowbytes)
{
v = (vid.conheight - lines + y)*200/vid.conheight;
src = conback->data + v*320;
if (vid.conwidth == 320){
Q_memcpy (dest, src, vid.conwidth);
}
else
{
f = 0;
fstep = 320*0x10000/vid.conwidth;
for (x=0 ; x<(int)vid.conwidth ; x+=4)
{
dest[x] = src[f>>16];
f += fstep;
dest[x+1] = src[f>>16];
f += fstep;
dest[x+2] = src[f>>16];
f += fstep;
dest[x+3] = src[f>>16];
f += fstep;
}
}
}
}
else
{
GpError("r_pixbytes = 1", 0);
pusdest = (unsigned short *)vid.conbuffer;
for (y=0 ; y<lines ; y++, pusdest += (vid.conrowbytes >> 1))
{
// FIXME: pre-expand to native format?
// FIXME: does the endian switching go away in production?
v = (vid.conheight - lines + y)*200/vid.conheight;
src = conback->data + v*320;
f = 0;
fstep = 320*0x10000/vid.conwidth;
for (x=0 ; x<(int)vid.conwidth ; x+=4)
{
pusdest[x] = d_8to16table[src[f>>16]];
f += fstep;
pusdest[x+1] = d_8to16table[src[f>>16]];
f += fstep;
pusdest[x+2] = d_8to16table[src[f>>16]];
f += fstep;
pusdest[x+3] = d_8to16table[src[f>>16]];
f += fstep;
}
}
}
}
/*
==============
R_DrawRect8
==============
*/
void R_DrawRect8 (vrect_t *prect, int rowbytes, byte *psrc,
int transparent)
{
byte t;
int i, j, srcdelta, destdelta;
byte *pdest;
pdest = vid.buffer + (prect->y * vid.rowbytes) + prect->x;
srcdelta = rowbytes - prect->width;
destdelta = vid.rowbytes - prect->width;
if (transparent)
{
for (i=0 ; i<prect->height ; i++)
{
for (j=0 ; j<prect->width ; j++)
{
t = *psrc;
if (t != TRANSPARENT_COLOR)
{
*pdest = t;
}
psrc++;
pdest++;
}
psrc += srcdelta;
pdest += destdelta;
}
}
else
{
for (i=0 ; i<prect->height ; i++)
{
Q_memcpy (pdest, psrc, prect->width);
psrc += rowbytes;
pdest += vid.rowbytes;
}
}
}
/*
==============
R_DrawRect16
==============
*/
void R_DrawRect16 (vrect_t *prect, int rowbytes, byte *psrc,
int transparent)
{
byte t;
int i, j, srcdelta, destdelta;
unsigned short *pdest;
// FIXME: would it be better to pre-expand native-format versions?
pdest = (unsigned short *)vid.buffer +
(prect->y * (vid.rowbytes >> 1)) + prect->x;
srcdelta = rowbytes - prect->width;
destdelta = (vid.rowbytes >> 1) - prect->width;
if (transparent)
{
for (i=0 ; i<prect->height ; i++)
{
for (j=0 ; j<prect->width ; j++)
{
t = *psrc;
if (t != TRANSPARENT_COLOR)
{
*pdest = d_8to16table[t];
}
psrc++;
pdest++;
}
psrc += srcdelta;
pdest += destdelta;
}
}
else
{
for (i=0 ; i<prect->height ; i++)
{
for (j=0 ; j<prect->width ; j++)
{
*pdest = d_8to16table[*psrc];
psrc++;
pdest++;
}
psrc += srcdelta;
pdest += destdelta;
}
}
}
/*
=============
Draw_TileClear
This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
=============
*/
void Draw_TileClear (int x, int y, int w, int h)
{
int width, height, tileoffsetx, tileoffsety;
byte *psrc;
vrect_t vr;
r_rectdesc.rect.x = x;
r_rectdesc.rect.y = y;
r_rectdesc.rect.width = w;
r_rectdesc.rect.height = h;
vr.y = r_rectdesc.rect.y;
height = r_rectdesc.rect.height;
tileoffsety = vr.y % r_rectdesc.height;
while (height > 0)
{
vr.x = r_rectdesc.rect.x;
width = r_rectdesc.rect.width;
if (tileoffsety != 0)
vr.height = r_rectdesc.height - tileoffsety;
else
vr.height = r_rectdesc.height;
if (vr.height > height)
vr.height = height;
tileoffsetx = vr.x % r_rectdesc.width;
while (width > 0)
{
if (tileoffsetx != 0)
vr.width = r_rectdesc.width - tileoffsetx;
else
vr.width = r_rectdesc.width;
if (vr.width > width)
vr.width = width;
psrc = r_rectdesc.ptexbytes +
(tileoffsety * r_rectdesc.rowbytes) + tileoffsetx;
if (r_pixbytes == 1)
{
R_DrawRect8 (&vr, r_rectdesc.rowbytes, psrc, 0);
}
else
{
R_DrawRect16 (&vr, r_rectdesc.rowbytes, psrc, 0);
}
vr.x += vr.width;
width -= vr.width;
tileoffsetx = 0; // only the left tile can be left-clipped
}
vr.y += vr.height;
height -= vr.height;
tileoffsety = 0; // only the top tile can be top-clipped
}
}
/*
=============
Draw_Fill
Fills a box of pixels with a single color
=============
*/
void Draw_Fill (int x, int y, int w, int h, int c)
{
byte *dest;
unsigned short *pusdest;
unsigned uc;
int u, v;
if (r_pixbytes == 1)
{
dest = vid.buffer + y*vid.rowbytes + x;
for (v=0 ; v<h ; v++, dest += vid.rowbytes)
for (u=0 ; u<w ; u++)
dest[u] = c;
}
else
{
uc = d_8to16table[c];
pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x;
for (v=0 ; v<h ; v++, pusdest += (vid.rowbytes >> 1))
for (u=0 ; u<w ; u++)
pusdest[u] = uc;
}
}
//=============================================================================
/*
================
Draw_FadeScreen
================
*/
void Draw_FadeScreen (void)
{
int x,y;
byte *pbuf;
VID_UnlockBuffer ();
S_ExtraUpdate ();
VID_LockBuffer ();
for (y=0 ; y<(int)vid.height ; y++)
{
int t;
pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
t = (y & 1) << 1;
for (x=0 ; x<(int)vid.width ; x++)
{
if ((x & 3) != t)
pbuf[x] = 0;
}
}
VID_UnlockBuffer ();
S_ExtraUpdate ();
VID_LockBuffer ();
}
//=============================================================================
/*
================
Draw_BeginDisc
Draws the little blue disc in the corner of the screen.
Call before beginning any disc IO.
================
*/
void Draw_BeginDisc (void)
{
D_BeginDirectRect (vid.width - 24, 0, draw_disc->data, 24, 24);
}
/*
================
Draw_EndDisc
Erases the disc icon.
Call after completing any disc IO
================
*/
void Draw_EndDisc (void)
{
D_EndDirectRect (vid.width - 24, 0, 24, 24);
}

View File

@@ -0,0 +1,40 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// draw.h -- these are the only functions outside the refresh allowed
// to touch the vid buffer
extern qpic_t *draw_disc; // also used on sbar
void Draw_Init (void);
void Draw_Character (int x, int y, int num);
void Draw_DebugChar (char num);
void Draw_Pic (int x, int y, qpic_t *pic);
void Draw_TransPic (int x, int y, qpic_t *pic);
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation);
void Draw_ConsoleBackground (int lines);
void Draw_BeginDisc (void);
void Draw_EndDisc (void);
void Draw_TileClear (int x, int y, int w, int h);
void Draw_Fill (int x, int y, int w, int h, int c);
void Draw_FadeScreen (void);
void Draw_String (int x, int y, char *str);
qpic_t *Draw_PicFromWad (char *name);
qpic_t *Draw_CachePic (char *path);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// input.h -- external (non-keyboard) input devices
void IN_Init (void);
void IN_Shutdown (void);
void IN_Commands (void);
// oportunity for devices to stick commands on the script buffer
void IN_Move (usercmd_t *cmd);
// add additional movement on top of the keyboard move cmd
void IN_ClearStates (void);
// restores all button and position states to defaults

View File

@@ -0,0 +1,29 @@
/* io.h
Copyright 1999, 2000, 2001 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef _IO_H_
#define _IO_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
* Function to return a Win32 HANDLE from a fd.
*/
extern long get_osfhandle(int);
extern int setmode (int __fd, int __mode);
int access(const char *__path, int __amode);
#ifdef __cplusplus
};
#endif /* __cplusplus */
#endif /* _IO_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,798 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
/*
key up events are sent even if in console mode
*/
#define MAXCMDLINE 256
char key_lines[32][MAXCMDLINE];
int key_linepos;
int shift_down=false;
int key_lastpress;
int edit_line=0;
int history_line=0;
keydest_t key_dest;
int key_count; // incremented every key event
char *keybindings[256];
qboolean consolekeys[256]; // if true, can't be rebound while in console
qboolean menubound[256]; // if true, can't be rebound while in menu
int keyshift[256]; // key to map to if shift held down in console
int key_repeats[256]; // if > 1, it is autorepeating
qboolean keydown[256];
typedef struct
{
char *name;
int keynum;
} keyname_t;
keyname_t keynames[] =
{
{"TAB", K_TAB},
{"ENTER", K_ENTER},
{"ESCAPE", K_ESCAPE},
{"SPACE", K_SPACE},
{"BACKSPACE", K_BACKSPACE},
{"UPARROW", K_UPARROW},
{"DOWNARROW", K_DOWNARROW},
{"LEFTARROW", K_LEFTARROW},
{"RIGHTARROW", K_RIGHTARROW},
{"ALT", K_ALT},
{"CTRL", K_CTRL},
{"SHIFT", K_SHIFT},
{"F1", K_F1},
{"F2", K_F2},
{"F3", K_F3},
{"F4", K_F4},
{"F5", K_F5},
{"F6", K_F6},
{"F7", K_F7},
{"F8", K_F8},
{"F9", K_F9},
{"F10", K_F10},
{"F11", K_F11},
{"F12", K_F12},
{"INS", K_INS},
{"DEL", K_DEL},
{"PGDN", K_PGDN},
{"PGUP", K_PGUP},
{"HOME", K_HOME},
{"END", K_END},
{"MOUSE1", K_MOUSE1},
{"MOUSE2", K_MOUSE2},
{"MOUSE3", K_MOUSE3},
{"JOY1", K_JOY1},
{"JOY2", K_JOY2},
{"JOY3", K_JOY3},
{"JOY4", K_JOY4},
{"AUX1", K_AUX1},
{"AUX2", K_AUX2},
{"AUX3", K_AUX3},
{"AUX4", K_AUX4},
{"AUX5", K_AUX5},
{"AUX6", K_AUX6},
{"AUX7", K_AUX7},
{"AUX8", K_AUX8},
{"AUX9", K_AUX9},
{"AUX10", K_AUX10},
{"AUX11", K_AUX11},
{"AUX12", K_AUX12},
{"AUX13", K_AUX13},
{"AUX14", K_AUX14},
{"AUX15", K_AUX15},
{"AUX16", K_AUX16},
{"AUX17", K_AUX17},
{"AUX18", K_AUX18},
{"AUX19", K_AUX19},
{"AUX20", K_AUX20},
{"AUX21", K_AUX21},
{"AUX22", K_AUX22},
{"AUX23", K_AUX23},
{"AUX24", K_AUX24},
{"AUX25", K_AUX25},
{"AUX26", K_AUX26},
{"AUX27", K_AUX27},
{"AUX28", K_AUX28},
{"AUX29", K_AUX29},
{"AUX30", K_AUX30},
{"AUX31", K_AUX31},
{"AUX32", K_AUX32},
{"PAUSE", K_PAUSE},
{"MWHEELUP", K_MWHEELUP},
{"MWHEELDOWN", K_MWHEELDOWN},
{"SEMICOLON", ';'}, // because a raw semicolon seperates commands
{NULL,0}
};
/*
==============================================================================
LINE TYPING INTO THE CONSOLE
==============================================================================
*/
/*
====================
Key_Console
Interactive line editing and console scrollback
====================
*/
void Key_Console (int key)
{
char *cmd;
if (key == K_ENTER|| key==K_JOY1 )
{
Cbuf_AddText (key_lines[edit_line]+1); // skip the >
Cbuf_AddText ("\n");
Con_Printf ("%s\n",key_lines[edit_line]);
edit_line = (edit_line + 1) & 31;
history_line = edit_line;
key_lines[edit_line][0] = ']';
key_linepos = 1;
if (cls.state == ca_disconnected)
SCR_UpdateScreen (); // force an update, because the command
// may take some time
return;
}
if (key == K_TAB)
{ // command completion
cmd = Cmd_CompleteCommand (key_lines[edit_line]+1);
if (!cmd)
cmd = Cvar_CompleteVariable (key_lines[edit_line]+1);
if (cmd)
{
Q_strcpy (key_lines[edit_line]+1, cmd);
key_linepos = Q_strlen(cmd)+1;
key_lines[edit_line][key_linepos] = ' ';
key_linepos++;
key_lines[edit_line][key_linepos] = 0;
return;
}
}
if (key == K_BACKSPACE || key == K_LEFTARROW)
{
if (key_linepos > 1)
key_linepos--;
return;
}
if (key == K_UPARROW)
{
do
{
history_line = (history_line - 1) & 31;
} while (history_line != edit_line
&& !key_lines[history_line][1]);
if (history_line == edit_line)
history_line = (edit_line+1)&31;
Q_strcpy(key_lines[edit_line], key_lines[history_line]);
key_linepos = Q_strlen(key_lines[edit_line]);
return;
}
if (key == K_DOWNARROW)
{
if (history_line == edit_line) return;
do
{
history_line = (history_line + 1) & 31;
}
while (history_line != edit_line
&& !key_lines[history_line][1]);
if (history_line == edit_line)
{
key_lines[edit_line][0] = ']';
key_linepos = 1;
}
else
{
Q_strcpy(key_lines[edit_line], key_lines[history_line]);
key_linepos = Q_strlen(key_lines[edit_line]);
}
return;
}
if (key == K_PGUP || key==K_MWHEELUP)
{
con_backscroll += 2;
if ((unsigned int)con_backscroll > con_totallines - (vid.height>>3) - 1)
con_backscroll = con_totallines - (vid.height>>3) - 1;
return;
}
if (key == K_PGDN || key==K_MWHEELDOWN)
{
con_backscroll -= 2;
if (con_backscroll < 0)
con_backscroll = 0;
return;
}
if (key == K_HOME)
{
con_backscroll = con_totallines - (vid.height>>3) - 1;
return;
}
if (key == K_END)
{
con_backscroll = 0;
return;
}
if (key < 32 || key > 127)
return; // non printable
if (key_linepos < MAXCMDLINE-1)
{
key_lines[edit_line][key_linepos] = key;
key_linepos++;
key_lines[edit_line][key_linepos] = 0;
}
}
//============================================================================
char chat_buffer[32];
qboolean team_message = false;
void Key_Message (int key)
{
static int chat_bufferlen = 0;
if (key == K_ENTER)
{
if (team_message)
Cbuf_AddText ("say_team \"");
else
Cbuf_AddText ("say \"");
Cbuf_AddText(chat_buffer);
Cbuf_AddText("\"\n");
key_dest = key_game;
chat_bufferlen = 0;
chat_buffer[0] = 0;
return;
}
if (key == K_ESCAPE)
{
key_dest = key_game;
chat_bufferlen = 0;
chat_buffer[0] = 0;
return;
}
if (key < 32 || key > 127)
return; // non printable
if (key == K_BACKSPACE)
{
if (chat_bufferlen)
{
chat_bufferlen--;
chat_buffer[chat_bufferlen] = 0;
}
return;
}
if (chat_bufferlen == 31)
return; // all full
chat_buffer[chat_bufferlen++] = key;
chat_buffer[chat_bufferlen] = 0;
}
//============================================================================
/*
===================
Key_StringToKeynum
Returns a key number to be used to index keybindings[] by looking at
the given string. Single ascii characters return themselves, while
the K_* names are matched up.
===================
*/
int Key_StringToKeynum (char *str)
{
keyname_t *kn;
if (!str || !str[0])
return -1;
if (!str[1])
return str[0];
for (kn=keynames ; kn->name ; kn++)
{
if (!Q_strcasecmp(str,kn->name))
return kn->keynum;
}
return -1;
}
/*
===================
Key_KeynumToString
Returns a string (either a single ascii char, or a K_* name) for the
given keynum.
FIXME: handle quote special (general escape sequence?)
===================
*/
char *Key_KeynumToString (int keynum)
{
keyname_t *kn;
static char tinystr[2];
if (keynum == -1)
return "<KEY NOT FOUND>";
if (keynum > 32 && keynum < 127)
{ // printable ascii
tinystr[0] = keynum;
tinystr[1] = 0;
return tinystr;
}
for (kn=keynames ; kn->name ; kn++)
if (keynum == kn->keynum)
return kn->name;
return "<UNKNOWN KEYNUM>";
}
/*
===================
Key_SetBinding
===================
*/
void Key_SetBinding (int keynum, char *binding)
{
char *new;
int l;
if (keynum == -1)
return;
// free old bindings
if (keybindings[keynum])
{
Z_Free (keybindings[keynum]);
keybindings[keynum] = NULL;
}
// allocate memory for new binding
l = Q_strlen (binding);
new = Z_Malloc (l+1);
Q_strcpy (new, binding);
new[l] = 0;
keybindings[keynum] = new;
}
/*
===================
Key_Unbind_f
===================
*/
void Key_Unbind_f (void)
{
int b;
if (Cmd_Argc() != 2)
{
Con_Printf ("unbind <key> : remove commands from a key\n");
return;
}
b = Key_StringToKeynum (Cmd_Argv(1));
if (b==-1)
{
Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
return;
}
Key_SetBinding (b, "");
}
void Key_Unbindall_f (void)
{
int i;
for (i=0 ; i<256 ; i++)
if (keybindings[i])
Key_SetBinding (i, "");
}
/*
===================
Key_Bind_f
===================
*/
void Key_Bind_f (void)
{
int i, c, b;
char cmd[1024];
c = Cmd_Argc();
if (c != 2 && c != 3)
{
Con_Printf ("bind <key> [command] : attach a command to a key\n");
return;
}
b = Key_StringToKeynum (Cmd_Argv(1));
if (b==-1)
{
Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
return;
}
if (c == 2)
{
if (keybindings[b])
Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keybindings[b] );
else
Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) );
return;
}
// copy the rest of the command line
cmd[0] = 0; // start out with a null string
for (i=2 ; i< c ; i++)
{
if (i > 2)
strcat (cmd, " ");
strcat (cmd, Cmd_Argv(i));
}
Key_SetBinding (b, cmd);
}
/*
============
Key_WriteBindings
Writes lines containing "bind key value"
============
*/
void Key_WriteBindings (FILE *f)
{
int i;
for (i=0 ; i<256 ; i++)
if (keybindings[i])
if (*keybindings[i])
fprintf (f, "bind \"%s\" \"%s\"\n", Key_KeynumToString(i), keybindings[i]);
}
/*
===================
Key_Init
===================
*/
void Key_Init (void)
{
int i;
for (i=0 ; i<32 ; i++)
{
key_lines[i][0] = ']';
key_lines[i][1] = 0;
}
key_linepos = 1;
//
// init ascii characters in console mode
//
for (i=32 ; i<128 ; i++)
consolekeys[i] = true;
consolekeys[K_ENTER] = true;
consolekeys[K_TAB] = true;
consolekeys[K_LEFTARROW] = true;
consolekeys[K_RIGHTARROW] = true;
consolekeys[K_UPARROW] = true;
consolekeys[K_DOWNARROW] = true;
consolekeys[K_BACKSPACE] = true;
consolekeys[K_PGUP] = true;
consolekeys[K_PGDN] = true;
consolekeys[K_SHIFT] = true;
consolekeys[K_MWHEELUP] = true;
consolekeys[K_MWHEELDOWN] = true;
consolekeys[K_JOY1] = true;
consolekeys['`'] = false;
consolekeys['~'] = false;
for (i=0 ; i<256 ; i++)
keyshift[i] = i;
for (i='a' ; i<='z' ; i++)
keyshift[i] = i - 'a' + 'A';
keyshift['1'] = '!';
keyshift['2'] = '@';
keyshift['3'] = '#';
keyshift['4'] = '$';
keyshift['5'] = '%';
keyshift['6'] = '^';
keyshift['7'] = '&';
keyshift['8'] = '*';
keyshift['9'] = '(';
keyshift['0'] = ')';
keyshift['-'] = '_';
keyshift['='] = '+';
keyshift[','] = '<';
keyshift['.'] = '>';
keyshift['/'] = '?';
keyshift[';'] = ':';
keyshift['\''] = '"';
keyshift['['] = '{';
keyshift[']'] = '}';
keyshift['`'] = '~';
keyshift['\\'] = '|';
menubound[K_ESCAPE] = true;
for (i=0 ; i<12 ; i++)
menubound[K_F1+i] = true;
//
// register our functions
//
Cmd_AddCommand ("bind",Key_Bind_f);
Cmd_AddCommand ("unbind",Key_Unbind_f);
Cmd_AddCommand ("unbindall",Key_Unbindall_f);
//Dan East: Allow our skin keys to register when menu is up
#ifdef _ARM_
menubound[K_AUX5]=true;
#elif defined(_MIPS_)
menubound[K_AUX2]=true;
#else
//Don't know what this should be for HP, etc.
menubound[K_AUX5]=true;
#endif
}
/*
===================
Key_Event
Called by the system between frames for both key up and key down events
Should NOT be called during an interrupt!
===================
*/
void Key_Event (int key, qboolean down)
{
char *kb;
char cmd[1024];
keydown[key] = down;
if (!down)
key_repeats[key] = 0;
key_lastpress = key;
key_count++;
if (key_count <= 0)
{
return; // just catching keys for Con_NotifyBox
}
// update auto-repeat status
if (down)
{
key_repeats[key]++;
if (key != K_BACKSPACE && key != K_PAUSE && key_repeats[key] > 1)
{
return; // ignore most autorepeats
}
if (key >= 200 && !keybindings[key])
Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key) );
}
if (key == K_SHIFT)
shift_down = down;
//
// handle escape specialy, so the user can never unbind it
//
if (key == K_ESCAPE)
{
if (!down)
return;
switch (key_dest)
{
case key_message:
Key_Message (key);
break;
case key_menu:
M_Keydown (key);
break;
case key_game:
case key_console:
M_ToggleMenu_f ();
break;
default:
Sys_Error ("Bad key_dest");
}
return;
}
//
// key up events only generate commands if the game key binding is
// a button command (leading + sign). These will occur even in console mode,
// to keep the character from continuing an action started before a console
// switch. Button commands include the kenum as a parameter, so multiple
// downs can be matched with ups
//
if (!down)
{
kb = keybindings[key];
if (kb && kb[0] == '+')
{
sprintf (cmd, "-%s %i\n", kb+1, key);
Cbuf_AddText (cmd);
}
if (keyshift[key] != key)
{
kb = keybindings[keyshift[key]];
if (kb && kb[0] == '+')
{
sprintf (cmd, "-%s %i\n", kb+1, key);
Cbuf_AddText (cmd);
}
}
return;
}
//
// during demo playback, most keys bring up the main menu
//
if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game)
{
M_ToggleMenu_f ();
return;
}
//
// if not a consolekey, send to the interpreter no matter what mode is
//
if ( (key_dest == key_menu && menubound[key])
|| (key_dest == key_console && !consolekeys[key])
|| (key_dest == key_game && ( !con_forcedup || !consolekeys[key] ) ) )
{
kb = keybindings[key];
if (kb)
{
if (kb[0] == '+')
{ // button commands add keynum as a parm
sprintf (cmd, "%s %i\n", kb, key);
Cbuf_AddText (cmd);
}
else
{
Cbuf_AddText (kb);
Cbuf_AddText ("\n");
}
}
return;
}
if (!down)
return; // other systems only care about key down events
if (shift_down)
{
key = keyshift[key];
}
switch (key_dest)
{
case key_message:
Key_Message (key);
break;
case key_menu:
M_Keydown (key);
break;
case key_game:
case key_console:
Key_Console (key);
break;
default:
Sys_Error ("Bad key_dest");
}
}
void Key_Extra (int *key) {
if (keydown[K_CTRL]) {
if (*key >= '0' && *key <= '9') {
*key = *key - '0' + 0x12;
} else {
switch (*key) {
case '[': *key = 0x10; break;
case ']': *key = 0x11; break;
case 'g': *key = 0x86; break;
case 'r': *key = 0x87; break;
case 'y': *key = 0x88; break;
case 'b': *key = 0x89; break;
case '(': *key = 0x80; break;
case '=': *key = 0x81; break;
case ')': *key = 0x82; break;
case 'a': *key = 0x83; break;
case '<': *key = 0x1d; break;
case '-': *key = 0x1e; break;
case '>': *key = 0x1f; break;
case ',': *key = 0x1c; break;
case '.': *key = 0x9c; break;
case 'B': *key = 0x8b; break;
case 'C': *key = 0x8d; break;
}
}
}
if (keydown[K_ALT])
*key |= 0x80;
}
/*
===================
Key_ClearStates
===================
*/
void Key_ClearStates (void)
{
int i;
for (i=0 ; i<256 ; i++)
{
keydown[i] = false;
key_repeats[i] = 0;
}
}

View File

@@ -0,0 +1,134 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//
// these are the key numbers that should be passed to Key_Event
//
#define K_TAB 9
#define K_ENTER 13
#define K_ESCAPE 27
#define K_SPACE 32
// normal keys should be passed as lowercased ascii
#define K_BACKSPACE 127
#define K_UPARROW 128
#define K_DOWNARROW 129
#define K_LEFTARROW 130
#define K_RIGHTARROW 131
#define K_ALT 132
#define K_CTRL 133
#define K_SHIFT 134
#define K_F1 135
#define K_F2 136
#define K_F3 137
#define K_F4 138
#define K_F5 139
#define K_F6 140
#define K_F7 141
#define K_F8 142
#define K_F9 143
#define K_F10 144
#define K_F11 145
#define K_F12 146
#define K_INS 147
#define K_DEL 148
#define K_PGDN 149
#define K_PGUP 150
#define K_HOME 151
#define K_END 152
#define K_PAUSE 255
//
// mouse buttons generate virtual keys
//
#define K_MOUSE1 200
#define K_MOUSE2 201
#define K_MOUSE3 202
//
// joystick buttons
//
#define K_JOY1 203
#define K_JOY2 204
#define K_JOY3 205
#define K_JOY4 206
//
// aux keys are for multi-buttoned joysticks to generate so they can use
// the normal binding process
//
#define K_AUX1 207
#define K_AUX2 208
#define K_AUX3 209
#define K_AUX4 210
#define K_AUX5 211
#define K_AUX6 212
#define K_AUX7 213
#define K_AUX8 214
#define K_AUX9 215
#define K_AUX10 216
#define K_AUX11 217
#define K_AUX12 218
#define K_AUX13 219
#define K_AUX14 220
#define K_AUX15 221
#define K_AUX16 222
#define K_AUX17 223
#define K_AUX18 224
#define K_AUX19 225
#define K_AUX20 226
#define K_AUX21 227
#define K_AUX22 228
#define K_AUX23 229
#define K_AUX24 230
#define K_AUX25 231
#define K_AUX26 232
#define K_AUX27 233
#define K_AUX28 234
#define K_AUX29 235
#define K_AUX30 236
#define K_AUX31 237
#define K_AUX32 238
// JACK: Intellimouse(c) Mouse Wheel Support
#define K_MWHEELUP 239
#define K_MWHEELDOWN 240
typedef enum {key_game, key_console, key_message, key_menu} keydest_t;
extern keydest_t key_dest;
extern char *keybindings[256];
extern int key_repeats[256];
extern int key_count; // incremented every key event
extern int key_lastpress;
void Key_Event (int key, qboolean down);
void Key_Init (void);
void Key_WriteBindings (FILE *f);
void Key_SetBinding (int keynum, char *binding);
void Key_Extra (int *key);
void Key_ClearStates (void);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,146 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// mathlib.h
#ifndef __MATHLIB_H__
#define __MATHLIB_H__
//Dan East:
#include "FixedPointMath.h"
#ifdef USE_PQ_OPT
typedef int fpvec3[3];
#endif
typedef fixedpoint_t vec3_FPM_t[3];
typedef fixedpoint8_24_t vec3_8_24FPM_t[3];
typedef fixedpoint_t vec5_FPM_t[5];
//End Dan
typedef float vec_t;
typedef vec_t vec3_t[3];
typedef vec_t vec5_t[5];
typedef int fixed4_t;
typedef int fixed8_t;
typedef int fixed16_t;
#ifndef M_PI
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
#endif
//struct mplane_s;
extern vec3_t vec3_origin;
extern vec3_FPM_t vec3_originFPM;
extern int nanmask;
#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
//Dan East:
#define DotProductFPM(x,y) FPM_ADD3(FPM_MUL(x[0],y[0]),FPM_MUL(x[1],y[1]),FPM_MUL(x[2],y[2]))
#define DotProduct8_24FPM(x,y) fpm_Add3(fpm_MulMixed8_24(x[0],y[0]),fpm_MulMixed8_24(x[1],y[1]),fpm_MulMixed8_24(x[2],y[2]))
#define VectorSubtractFPM(a,b,c) {c[0]=FPM_SUB(a[0],b[0]);c[1]=FPM_SUB(a[1],b[1]);c[2]=FPM_SUB(a[2],b[2]);}
#define VectorAddFPM(a,b,c) {c[0]=FPM_ADD(a[0],b[0]);c[1]=FPM_ADD(a[1],b[1]);c[2]=FPM_ADD(a[2],b[2]);}
//Int the following two macros b represents the destination (following ID's convention)
#define VectorToFPM(a,b) {b[0]=FPM_FROMFLOAT(a[0]);b[1]=FPM_FROMFLOAT(a[1]);b[2]=FPM_FROMFLOAT(a[2]);}
#define FPMToVector(a,b) {b[0]=FPM_TOFLOAT(a[0]);b[1]=FPM_TOFLOAT(a[1]);b[2]=FPM_TOFLOAT(a[2]);}
//End Dan
#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
//Dan: Can't this be done with memcpy?
#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc);
void VectorMAFPM (vec3_FPM_t veca, fixedpoint_t scale, vec3_FPM_t vecb, vec3_FPM_t vecc);
int VectorCompare (vec3_t v1, vec3_t v2);
vec_t Length (vec3_t v);
fixedpoint_t LengthFPM (vec3_FPM_t v);
void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
void CrossProductFPM (vec3_FPM_t v1, vec3_FPM_t v2, vec3_FPM_t cross);
float VectorNormalize (vec3_t v); // returns vector length
fixedpoint_t VectorNormalizeFPM (vec3_FPM_t v); // returns vector length
void VectorInverse (vec3_t v);
void VectorInverseFPM (vec3_FPM_t v);
void VectorScale (vec3_t in, vec_t scale, vec3_t out);
void VectorScaleFPM (vec3_FPM_t in, fixedpoint_t scale, vec3_FPM_t out);
int Q_log2(int val);
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]);
void R_ConcatRotationsFPM (fixedpoint_t in1[3][3], fixedpoint_t in2[3][3], fixedpoint_t out[3][3]);
void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]);
void R_ConcatTransformsFPM (fixedpoint_t in1[3][4], fixedpoint_t in2[3][4], fixedpoint_t out[3][4]);
void R_ConcatTransforms8_24FPM (fixedpoint_t in1[3][4], fixedpoint_t in2[3][4], fixedpoint8_24_t out[3][4]);
void FloorDivMod (double numer, double denom, int *quotient,
int *rem);
fixed16_t Invert24To16(fixed16_t val);
int GreatestCommonDivisor (int i1, int i2);
void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
void AngleVectorsFPM (vec3_FPM_t angles, vec3_FPM_t forward, vec3_FPM_t right, vec3_FPM_t up);
//int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct mplane_s *plane);
//int BoxOnPlaneSideFPM (vec3_FPM_t emins, vec3_FPM_t emaxs, struct mplane_FPM_s *plane);
float anglemod(float a);
fixedpoint_t anglemodFPM(fixedpoint_t a);
#define BOX_ON_PLANE_SIDE(emins, emaxs, p) \
(((p)->type < 3)? \
( \
((p)->dist <= (emins)[(p)->type])? \
1 \
: \
( \
((p)->dist >= (emaxs)[(p)->type])?\
2 \
: \
3 \
) \
) \
: \
BoxOnPlaneSide( (emins), (emaxs), (p)))
#define BOX_ON_PLANE_SIDE_FPM(emins, emaxs, p) \
(((p)->type < 3)? \
( \
((p)->dist <= (emins)[(p)->type])? \
1 \
: \
( \
((p)->dist >= (emaxs)[(p)->type])?\
2 \
: \
3 \
) \
) \
: \
BoxOnPlaneSideFPM( (emins), (emaxs), (p)))
int ParseFloats(char *s, float *f, int *f_size);
#endif // _MATHLIB_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//
// the net drivers should just set the apropriate bits in m_activenet,
// instead of having the menu code look through their internal tables
//
#define MNET_IPX 1
#define MNET_TCP 2
extern int m_activenet;
//
// menus
//
void M_Init (void);
void M_Keydown (int key);
void M_Draw (void);
void M_ToggleMenu_f (void);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,605 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __MODEL__
#define __MODEL__
#include "modelgen.h"
#include "spritegn.h"
/*
d*_t structures are on-disk representations
m*_t structures are in-memory
*/
/*
==============================================================================
BRUSH MODELS
==============================================================================
*/
//
// in memory representation
//
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
vec3_t position;
} mvertex_t;
typedef struct
{
int position[3];
} mvertex_fxp_t;
/*
typedef struct
{
vec3_FPM_t position;
} mvertex_FPM_t;
*/
#define SIDE_FRONT 0
#define SIDE_BACK 1
#define SIDE_ON 2
// plane_t structure
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct mplane_s
{
vec3_t normal;
float dist;
byte type; // for texture axis selection and fast side tests
byte signbits; // signx + signy<<1 + signz<<1
byte pad[2];
} mplane_t;
//Dan East: Fixed Point Math addition
/*
typedef struct mplane_FPM_s
{
vec3_FPM_t normal;
fixedpoint_t dist;
byte type; // for texture axis selection and fast side tests
byte signbits; // signx + signy<<1 + signz<<1
byte pad[2];
} mplane_FPM_t;
*/
typedef struct texture_s
{
char name[16];
unsigned width, height;
int anim_total; // total tenths in sequence ( 0 = no)
int anim_min, anim_max; // time for this frame min <=time< max
struct texture_s *anim_next; // in the animation sequence
struct texture_s *alternate_anims; // bmodels in frmae 1 use these
unsigned offsets[MIPLEVELS]; // four mip maps stored
} texture_t;
#define SURF_PLANEBACK 2
#define SURF_DRAWSKY 4
#define SURF_DRAWSPRITE 8
#define SURF_DRAWTURB 0x10
#define SURF_DRAWTILED 0x20
#define SURF_DRAWBACKGROUND 0x40
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
unsigned short v[2];
unsigned int cachededgeoffset;
} medge_t;
typedef struct
{
#ifndef USE_PQ_OPT3
float vecs[2][4];
float mipadjust;
#else
int vecs_fxp[2][4];
int mipadjust_fxp;
#endif
texture_t *texture;
int flags;
} mtexinfo_t;
/*
typedef struct
{
fixedpoint_t vecs[2][4];
fixedpoint_t mipadjust;
texture_t *texture;
int flags;
} mtexinfo_FPM_t;
*/
typedef struct msurface_s
{
int visframe; // should be drawn when node is crossed
int dlightframe;
int dlightbits;
mplane_t *plane;
int flags;
int firstedge; // look up in model->surfedges[], negative numbers
int numedges; // are backwards edges
// surface generation data
struct surfcache_s *cachespots[MIPLEVELS];
short texturemins[2];
short extents[2];
mtexinfo_t *texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
byte *samples; // [numstyles*surfsize]
} msurface_t;
/*
typedef struct msurface_FPM_s
{
int visframe; // should be drawn when node is crossed
int dlightframe;
int dlightbits;
mplane_FPM_t *plane;
int flags;
int firstedge; // look up in model->surfedges[], negative numbers
int numedges; // are backwards edges
// surface generation data
struct surfcache_FPM_s *cachespots[MIPLEVELS];
short texturemins[2];
short extents[2];
mtexinfo_FPM_t *texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
byte *samples; // [numstyles*surfsize]
} msurface_FPM_t;
*/
typedef struct mnode_s
{
// common with leaf
int contents; // 0, to differentiate from leafs
int visframe; // node needs to be traversed if current
short minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
// node specific
mplane_t *plane;
struct mnode_s *children[2];
unsigned short firstsurface;
unsigned short numsurfaces;
} mnode_t;
/*
typedef struct mnode_FPM_s
{
// common with leaf
int contents; // 0, to differentiate from leafs
int visframe; // node needs to be traversed if current
short minmaxs[6]; // for bounding box culling
struct mnode_FPM_s *parent;
// node specific
mplane_FPM_t *plane;
struct mnode_FPM_s *children[2];
unsigned short firstsurface;
unsigned short numsurfaces;
} mnode_FPM_t;
*/
typedef struct mleaf_s
{
// common with node
int contents; // wil be a negative contents number
int visframe; // node needs to be traversed if current
short minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
// leaf specific
byte *compressed_vis;
efrag_t *efrags;
msurface_t **firstmarksurface;
int nummarksurfaces;
int key; // BSP sequence number for leaf's contents
byte ambient_sound_level[NUM_AMBIENTS];
} mleaf_t;
/*
typedef struct mleaf_FPM_s
{
// common with node
int contents; // wil be a negative contents number
int visframe; // node needs to be traversed if current
short minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
// leaf specific
byte *compressed_vis;
efrag_FPM_t *efrags;
msurface_FPM_t **firstmarksurface;
int nummarksurfaces;
int key; // BSP sequence number for leaf's contents
byte ambient_sound_level[NUM_AMBIENTS];
} mleaf_FPM_t;
*/
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct
{
dclipnode_t *clipnodes;
mplane_t *planes;
int firstclipnode;
int lastclipnode;
vec3_t clip_mins;
vec3_t clip_maxs;
} hull_t;
/*
typedef struct
{
dclipnode_t *clipnodes;
mplane_FPM_t *planes;
int firstclipnode;
int lastclipnode;
vec3_FPM_t clip_mins;
vec3_FPM_t clip_maxs;
} hull_FPM_t;
*/
/*
==============================================================================
SPRITE MODELS
==============================================================================
*/
// FIXME: shorten these?
typedef struct mspriteframe_s
{
int width;
int height;
void *pcachespot; // remove?
float up, down, left, right;
byte pixels[4];
} mspriteframe_t;
/*
typedef struct mspriteframe_FPM_s
{
int width;
int height;
void *pcachespot; // remove?
fixedpoint_t up, down, left, right;
byte pixels[4];
} mspriteframe_FPM_t;
*/
typedef struct
{
int numframes;
float *intervals;
mspriteframe_t *frames[1];
} mspritegroup_t;
/*
typedef struct
{
int numframes;
fixedpoint_t *intervals;
mspriteframe_FPM_t *frames[1];
} mspritegroup_FPM_t;
*/
typedef struct
{
spriteframetype_t type;
mspriteframe_t *frameptr;
} mspriteframedesc_t;
/*
typedef struct
{
spriteframetype_t type;
mspriteframe_FPM_t *frameptr;
} mspriteframedesc_FPM_t;
*/
typedef struct
{
int type;
int maxwidth;
int maxheight;
int numframes;
float beamlength; // remove?
void *cachespot; // remove?
mspriteframedesc_t frames[1];
} msprite_t;
/*
typedef struct
{
int type;
int maxwidth;
int maxheight;
int numframes;
fixedpoint_t beamlength; // remove?
void *cachespot; // remove?
mspriteframedesc_FPM_t frames[1];
} msprite_FPM_t;
*/
/*
==============================================================================
ALIAS MODELS
Alias models are position independent, so the cache manager can move them.
==============================================================================
*/
typedef struct
{
aliasframetype_t type;
trivertx_t bboxmin;
trivertx_t bboxmax;
int frame;
char name[16];
} maliasframedesc_t;
typedef struct
{
aliasskintype_t type;
void *pcachespot;
int skin;
} maliasskindesc_t;
typedef struct
{
trivertx_t bboxmin;
trivertx_t bboxmax;
int frame;
} maliasgroupframedesc_t;
typedef struct
{
int numframes;
int intervals;
maliasgroupframedesc_t frames[1];
} maliasgroup_t;
typedef struct
{
int numskins;
int intervals;
maliasskindesc_t skindescs[1];
} maliasskingroup_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct mtriangle_s {
int facesfront;
int vertindex[3];
} mtriangle_t;
typedef struct {
int model;
int stverts;
int skindesc;
int triangles;
maliasframedesc_t frames[1];
} aliashdr_t;
//===================================================================
//
// Whole model
//
typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t;
#define EF_ROCKET 1 // leave a trail
#define EF_GRENADE 2 // leave a trail
#define EF_GIB 4 // leave a trail
#define EF_ROTATE 8 // rotate (bonus items)
#define EF_TRACER 16 // green split trail
#define EF_ZOMGIB 32 // small blood trail
#define EF_TRACER2 64 // orange split trail + rotate
#define EF_TRACER3 128 // purple trail
typedef struct model_s
{
char name[MAX_QPATH];
qboolean needload; // bmodels and sprites don't cache normally
modtype_t type;
int numframes;
synctype_t synctype;
int flags;
//
// volume occupied by the model
//
vec3_t mins, maxs;
float radius;
//
// brush model
//
int firstmodelsurface, nummodelsurfaces;
int numsubmodels;
dmodel_t *submodels;
int numplanes;
mplane_t *planes;
int numleafs; // number of visible leafs, not counting 0
mleaf_t *leafs;
int numvertexes;
mvertex_t *vertexes;
#ifdef USE_PQ_OPT2
mvertex_fxp_t *vertexes_fxp;
#endif
int numedges;
medge_t *edges;
int numnodes;
mnode_t *nodes;
int numtexinfo;
mtexinfo_t *texinfo;
int numsurfaces;
msurface_t *surfaces;
int numsurfedges;
int *surfedges;
int numclipnodes;
dclipnode_t *clipnodes;
int nummarksurfaces;
msurface_t **marksurfaces;
hull_t hulls[MAX_MAP_HULLS];
int numtextures;
texture_t **textures;
byte *visdata;
byte *lightdata;
char *entities;
//
// additional model data
//
cache_user_t cache; // only access through Mod_Extradata
} model_t;
/*
typedef struct model_FPM_s
{
char name[MAX_QPATH];
qboolean needload; // bmodels and sprites don't cache normally
modtype_t type;
int numframes;
synctype_t synctype;
int flags;
//
// volume occupied by the model
//
vec3_FPM_t mins, maxs;
fixedpoint_t radius;
//
// brush model
//
int firstmodelsurface, nummodelsurfaces;
int numsubmodels;
dmodel_FPM_t *submodels;
int numplanes;
mplane_FPM_t *planes;
int numleafs; // number of visible leafs, not counting 0
mleaf_FPM_t *leafs;
int numvertexes;
mvertex_FPM_t *vertexes;
int numedges;
medge_t *edges;
int numnodes;
mnode_FPM_t *nodes;
int numtexinfo;
mtexinfo_FPM_t *texinfo;
int numsurfaces;
msurface_FPM_t *surfaces;
int numsurfedges;
int *surfedges;
int numclipnodes;
dclipnode_t *clipnodes;
int nummarksurfaces;
msurface_FPM_t **marksurfaces;
hull_FPM_t hulls[MAX_MAP_HULLS];
int numtextures;
texture_t **textures;
byte *visdata;
byte *lightdata;
char *entities;
//
// additional model data
//
cache_user_t cache; // only access through Mod_Extradata
} model_FPM_t;
*/
//============================================================================
void Mod_Init (void);
void Mod_ClearAll (void);
//void Mod_ClearAllFPM (void);
model_t *Mod_ForName (char *name, qboolean crash);
//model_FPM_t *Mod_ForNameFPM (char *name, qboolean crash);
void *Mod_Extradata (model_t *mod); // handles caching
//void *Mod_ExtradataFPM (model_FPM_t *mod); // handles caching
void Mod_TouchModel (char *name);
void Mod_TouchModelFPM (char *name);
mleaf_t *Mod_PointInLeaf (float *p, model_t *model);
//mleaf_FPM_t *Mod_PointInLeafFPM (fixedpoint_t *p, model_FPM_t *model);
byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model);
//byte *Mod_LeafPVSFPM (mleaf_FPM_t *leaf, model_FPM_t *model);
#endif // __MODEL__

View File

@@ -0,0 +1,157 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//
// modelgen.h: header file for model generation program
//
// *********************************************************
// * This file must be identical in the modelgen directory *
// * and in the Quake directory, because it's used to *
// * pass data from one to the other via model files. *
// *********************************************************
#ifdef INCLUDELIBS
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
//#include "cmdlib.h"
//#include "scriplib.h"
//#include "trilib.h"
//#include "lbmlib.h"
//#include "mathlib.h"
#endif
#define ALIAS_VERSION 6
#define ALIAS_ONSEAM 0x0020
// must match definition in spritegn.h
#ifndef SYNCTYPE_T
#define SYNCTYPE_T
typedef enum {ST_SYNC=0, ST_RAND } synctype_t;
#endif
typedef enum { ALIAS_SINGLE=0, ALIAS_GROUP } aliasframetype_t;
typedef enum { ALIAS_SKIN_SINGLE=0, ALIAS_SKIN_GROUP } aliasskintype_t;
typedef struct {
int ident;
int version;
vec3_t scale;
vec3_t scale_origin;
float boundingradius;
vec3_t eyeposition;
int numskins;
int skinwidth;
int skinheight;
int numverts;
int numtris;
int numframes;
synctype_t synctype;
int flags;
float size;
} mdl_t;
//Dan East:
typedef struct {
int ident;
int version;
vec3_FPM_t scale;
vec3_FPM_t scale_origin;
fixedpoint_t boundingradius;
vec3_FPM_t eyeposition;
int numskins;
int skinwidth;
int skinheight;
int numverts;
int numtris;
int numframes;
synctype_t synctype;
int flags;
fixedpoint_t size;
} mdl_FPM_t;
// TODO: could be shorts
typedef struct {
int onseam;
int s;
int t;
} stvert_t;
typedef struct dtriangle_s {
int facesfront;
int vertindex[3];
} dtriangle_t;
#define DT_FACES_FRONT 0x0010
// This mirrors trivert_t in trilib.h, is present so Quake knows how to
// load this data
typedef struct {
byte v[3];
byte lightnormalindex;
} trivertx_t;
typedef struct {
trivertx_t bboxmin; // lightnormal isn't used
trivertx_t bboxmax; // lightnormal isn't used
char name[16]; // frame name from grabbing
} daliasframe_t;
typedef struct {
int numframes;
trivertx_t bboxmin; // lightnormal isn't used
trivertx_t bboxmax; // lightnormal isn't used
} daliasgroup_t;
typedef struct {
int numskins;
} daliasskingroup_t;
typedef struct {
float interval;
} daliasinterval_t;
/*
typedef struct {
fixedpoint_t interval;
} daliasinterval_FPM_t;
*/
typedef struct {
float interval;
} daliasskininterval_t;
typedef struct {
aliasframetype_t type;
} daliasframetype_t;
typedef struct {
aliasskintype_t type;
} daliasskintype_t;
#define IDPOLYHEADER (('O'<<24)+('P'<<16)+('D'<<8)+'I')
// little-endian "IDPO"

View File

@@ -0,0 +1,21 @@
// plane_t structure
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct mplane_s
{
vec3_t normal;
float dist;
byte type; // for texture axis selection and fast side tests
byte signbits; // signx + signy<<1 + signz<<1
byte pad[2];
} mplane_t;
//Dan East: Fixed Point Math addition
typedef struct mplane_FPM_s
{
vec3_FPM_t normal;
fixedpoint_t dist;
byte type; // for texture axis selection and fast side tests
byte signbits; // signx + signy<<1 + signz<<1
byte pad[2];
} mplane_FPM_t;

View File

@@ -0,0 +1,337 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// net.h -- quake's interface to the networking layer
struct qsockaddr
{
short sa_family;
unsigned char sa_data[14];
};
#define NET_NAMELEN 64
#define NET_MAXMESSAGE 8192
#define NET_HEADERSIZE (2 * sizeof(unsigned int))
#define NET_DATAGRAMSIZE (MAX_DATAGRAM + NET_HEADERSIZE)
// NetHeader flags
#define NETFLAG_LENGTH_MASK 0x0000ffff
#define NETFLAG_DATA 0x00010000
#define NETFLAG_ACK 0x00020000
#define NETFLAG_NAK 0x00040000
#define NETFLAG_EOM 0x00080000
#define NETFLAG_UNRELIABLE 0x00100000
#define NETFLAG_CTL 0x80000000
#define NET_PROTOCOL_VERSION 3
// This is the network info/connection protocol. It is used to find Quake
// servers, get info about them, and connect to them. Once connected, the
// Quake game protocol (documented elsewhere) is used.
//
//
// General notes:
// game_name is currently always "QUAKE", but is there so this same protocol
// can be used for future games as well; can you say Quake2?
//
// CCREQ_CONNECT
// string game_name "QUAKE"
// byte net_protocol_version NET_PROTOCOL_VERSION
//
// CCREQ_SERVER_INFO
// string game_name "QUAKE"
// byte net_protocol_version NET_PROTOCOL_VERSION
//
// CCREQ_PLAYER_INFO
// byte player_number
//
// CCREQ_RULE_INFO
// string rule
//
//
//
// CCREP_ACCEPT
// long port
//
// CCREP_REJECT
// string reason
//
// CCREP_SERVER_INFO
// string server_address
// string host_name
// string level_name
// byte current_players
// byte max_players
// byte protocol_version NET_PROTOCOL_VERSION
//
// CCREP_PLAYER_INFO
// byte player_number
// string name
// long colors
// long frags
// long connect_time
// string address
//
// CCREP_RULE_INFO
// string rule
// string value
// note:
// There are two address forms used above. The short form is just a
// port number. The address that goes along with the port is defined as
// "whatever address you receive this reponse from". This lets us use
// the host OS to solve the problem of multiple host addresses (possibly
// with no routing between them); the host will use the right address
// when we reply to the inbound connection request. The long from is
// a full address and port in a string. It is used for returning the
// address of a server that is not running locally.
#define CCREQ_CONNECT 0x01
#define CCREQ_SERVER_INFO 0x02
#define CCREQ_PLAYER_INFO 0x03
#define CCREQ_RULE_INFO 0x04
#define CCREP_ACCEPT 0x81
#define CCREP_REJECT 0x82
#define CCREP_SERVER_INFO 0x83
#define CCREP_PLAYER_INFO 0x84
#define CCREP_RULE_INFO 0x85
typedef struct qsocket_s
{
struct qsocket_s *next;
double connecttime;
double lastMessageTime;
double lastSendTime;
qboolean disconnected;
qboolean canSend;
qboolean sendNext;
int driver;
int landriver;
int socket;
void *driverdata;
unsigned int ackSequence;
unsigned int sendSequence;
unsigned int unreliableSendSequence;
int sendMessageLength;
byte sendMessage [NET_MAXMESSAGE];
unsigned int receiveSequence;
unsigned int unreliableReceiveSequence;
int receiveMessageLength;
byte receiveMessage [NET_MAXMESSAGE];
struct qsockaddr addr;
char address[NET_NAMELEN];
} qsocket_t;
extern qsocket_t *net_activeSockets;
extern qsocket_t *net_freeSockets;
extern int net_numsockets;
typedef struct
{
char *name;
qboolean initialized;
int controlSock;
int (*Init) (void);
void (*Shutdown) (void);
void (*Listen) (qboolean state);
int (*OpenSocket) (int port);
int (*CloseSocket) (int socket);
int (*Connect) (int socket, struct qsockaddr *addr);
int (*CheckNewConnections) (void);
int (*Read) (int socket, byte *buf, int len, struct qsockaddr *addr);
int (*Write) (int socket, byte *buf, int len, struct qsockaddr *addr);
int (*Broadcast) (int socket, byte *buf, int len);
char * (*AddrToString) (struct qsockaddr *addr);
int (*StringToAddr) (char *string, struct qsockaddr *addr);
int (*GetSocketAddr) (int socket, struct qsockaddr *addr);
int (*GetNameFromAddr) (struct qsockaddr *addr, char *name);
int (*GetAddrFromName) (char *name, struct qsockaddr *addr);
int (*AddrCompare) (struct qsockaddr *addr1, struct qsockaddr *addr2);
int (*GetSocketPort) (struct qsockaddr *addr);
int (*SetSocketPort) (struct qsockaddr *addr, int port);
} net_landriver_t;
#define MAX_NET_DRIVERS 8
extern int net_numlandrivers;
extern net_landriver_t net_landrivers[MAX_NET_DRIVERS];
typedef struct
{
char *name;
qboolean initialized;
int (*Init) (void);
void (*Listen) (qboolean state);
void (*SearchForHosts) (qboolean xmit);
qsocket_t *(*Connect) (char *host);
qsocket_t *(*CheckNewConnections) (void);
int (*QGetMessage) (qsocket_t *sock);
int (*QSendMessage) (qsocket_t *sock, sizebuf_t *data);
int (*SendUnreliableMessage) (qsocket_t *sock, sizebuf_t *data);
qboolean (*CanSendMessage) (qsocket_t *sock);
qboolean (*CanSendUnreliableMessage) (qsocket_t *sock);
void (*Close) (qsocket_t *sock);
void (*Shutdown) (void);
int controlSock;
} net_driver_t;
extern int net_numdrivers;
extern net_driver_t net_drivers[MAX_NET_DRIVERS];
extern int DEFAULTnet_hostport;
extern int net_hostport;
extern int net_driverlevel;
extern cvar_t hostname;
extern char playername[];
extern int playercolor;
extern int messagesSent;
extern int messagesReceived;
extern int unreliableMessagesSent;
extern int unreliableMessagesReceived;
qsocket_t *NET_NewQSocket (void);
void NET_FreeQSocket(qsocket_t *);
double SetNetTime(void);
#define HOSTCACHESIZE 8
typedef struct
{
char name[16];
char map[16];
char cname[32];
int users;
int maxusers;
int driver;
int ldriver;
struct qsockaddr addr;
} hostcache_t;
extern int hostCacheCount;
extern hostcache_t hostcache[HOSTCACHESIZE];
#if !defined(_WIN32 ) && !defined (__linux__) && !defined (__sun__)
#ifndef htonl
extern unsigned long htonl (unsigned long hostlong);
#endif
#ifndef htons
extern unsigned short htons (unsigned short hostshort);
#endif
#ifndef ntohl
extern unsigned long ntohl (unsigned long netlong);
#endif
#ifndef ntohs
extern unsigned short ntohs (unsigned short netshort);
#endif
#endif
#ifdef IDGODS
qboolean IsID(struct qsockaddr *addr);
#endif
//============================================================================
//
// public network functions
//
//============================================================================
extern double net_time;
extern sizebuf_t net_message;
extern int net_activeconnections;
void NET_Init (void);
void NET_Shutdown (void);
struct qsocket_s *NET_CheckNewConnections (void);
// returns a new connection number if there is one pending, else -1
struct qsocket_s *NET_Connect (char *host);
// called by client to connect to a host. Returns -1 if not able to
qboolean NET_CanSendMessage (qsocket_t *sock);
// Returns true or false if the given qsocket can currently accept a
// message to be transmitted.
int NET_GetMessage (struct qsocket_s *sock);
// returns data in net_message sizebuf
// returns 0 if no data is waiting
// returns 1 if a message was received
// returns 2 if an unreliable message was received
// returns -1 if the connection died
int NET_SendMessage (struct qsocket_s *sock, sizebuf_t *data);
int NET_SendUnreliableMessage (struct qsocket_s *sock, sizebuf_t *data);
// returns 0 if the message connot be delivered reliably, but the connection
// is still considered valid
// returns 1 if the message was sent properly
// returns -1 if the connection died
int NET_SendToAll(sizebuf_t *data, int blocktime);
// This is a reliable *blocking* send to all attached clients.
void NET_Close (struct qsocket_s *sock);
// if a dead connection is returned by a get or send function, this function
// should be called when it is convenient
// Server calls when a client is kicked off for a game related misbehavior
// like an illegal protocal conversation. Client calls when disconnecting
// from a server.
// A netcon_t number will not be reused until this function is called for it
void NET_Poll(void);
typedef struct _PollProcedure
{
struct _PollProcedure *next;
double nextTime;
void (*procedure)();
void *arg;
} PollProcedure;
void SchedulePollProcedure(PollProcedure *pp, double timeOffset);
extern qboolean serialAvailable;
extern qboolean ipxAvailable;
extern qboolean tcpipAvailable;
extern char my_ipx_address[NET_NAMELEN];
extern char my_tcpip_address[NET_NAMELEN];
extern void (*GetComPortConfig) (int portNumber, int *port, int *irq, int *baud, qboolean *useModem);
extern void (*SetComPortConfig) (int portNumber, int port, int irq, int baud, qboolean useModem);
extern void (*GetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
extern void (*SetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
extern qboolean slistInProgress;
extern qboolean slistSilent;
extern qboolean slistLocal;
void NET_Slist_f (void);

View File

@@ -0,0 +1,93 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
#include "net_loop.h"
#include "net_dgrm.h"
net_driver_t net_drivers[MAX_NET_DRIVERS] =
{
{
"Loopback",
false,
Loop_Init,
Loop_Listen,
Loop_SearchForHosts,
Loop_Connect,
Loop_CheckNewConnections,
Loop_GetMessage,
Loop_SendMessage,
Loop_SendUnreliableMessage,
Loop_CanSendMessage,
Loop_CanSendUnreliableMessage,
Loop_Close,
Loop_Shutdown
}
,
{
"Datagram",
false,
Datagram_Init,
Datagram_Listen,
Datagram_SearchForHosts,
Datagram_Connect,
Datagram_CheckNewConnections,
Datagram_GetMessage,
Datagram_SendMessage,
Datagram_SendUnreliableMessage,
Datagram_CanSendMessage,
Datagram_CanSendUnreliableMessage,
Datagram_Close,
Datagram_Shutdown
}
};
int net_numdrivers = 2;
#include "net_udp.h"
net_landriver_t net_landrivers[MAX_NET_DRIVERS] =
{
{
"UDP",
false,
0,
UDP_Init,
UDP_Shutdown,
UDP_Listen,
UDP_OpenSocket,
UDP_CloseSocket,
UDP_Connect,
UDP_CheckNewConnections,
UDP_Read,
UDP_Write,
UDP_Broadcast,
UDP_AddrToString,
UDP_StringToAddr,
UDP_GetSocketAddr,
UDP_GetNameFromAddr,
UDP_GetAddrFromName,
UDP_AddrCompare,
UDP_GetSocketPort,
UDP_SetSocketPort
}
};
int net_numlandrivers = 1;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// net_dgrm.h
int Datagram_Init (void);
void Datagram_Listen (qboolean state);
void Datagram_SearchForHosts (qboolean xmit);
qsocket_t *Datagram_Connect (char *host);
qsocket_t *Datagram_CheckNewConnections (void);
int Datagram_GetMessage (qsocket_t *sock);
int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data);
int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data);
qboolean Datagram_CanSendMessage (qsocket_t *sock);
qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock);
void Datagram_Close (qsocket_t *sock);
void Datagram_Shutdown (void);

View File

@@ -0,0 +1,270 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// net_loop.c
#include "quakedef.h"
#include "net_loop.h"
qboolean localconnectpending = false;
qsocket_t *loop_client = NULL;
qsocket_t *loop_server = NULL;
int Loop_Init (void)
{
if (cls.state == ca_dedicated)
return -1;
return 0;
}
void Loop_Shutdown (void)
{
}
void Loop_Listen (qboolean state)
{
}
void Loop_SearchForHosts (qboolean xmit)
{
if (!sv.active){
return;
}
hostCacheCount = 1;
if (Q_strcmp(hostname.string, "UNNAMED") == 0)
Q_strcpy(hostcache[0].name, "local");
else
Q_strcpy(hostcache[0].name, hostname.string);
Q_strcpy(hostcache[0].map, sv.name);
hostcache[0].users = net_activeconnections;
hostcache[0].maxusers = svs.maxclients;
hostcache[0].driver = net_driverlevel;
Q_strcpy(hostcache[0].cname, "local");
}
qsocket_t *Loop_Connect (char *host)
{
if (Q_strcmp(host,"local") != 0)
return NULL;
GpError("Loop Connect",0);
localconnectpending = true;
if (!loop_client)
{
if ((loop_client = NET_NewQSocket ()) == NULL)
{
GpError("Loop Connect - client Error",0);
Con_Printf("Loop_Connect: no qsocket available\n");
return NULL;
}
Q_strcpy (loop_client->address, "localhost");
}
loop_client->receiveMessageLength = 0;
loop_client->sendMessageLength = 0;
loop_client->canSend = true;
if (!loop_server)
{
if ((loop_server = NET_NewQSocket ()) == NULL)
{
GpError("Loop Connect - server Error",0);
Con_Printf("Loop_Connect: no qsocket available\n");
return NULL;
}
Q_strcpy (loop_server->address, "LOCAL");
}
loop_server->receiveMessageLength = 0;
loop_server->sendMessageLength = 0;
loop_server->canSend = true;
loop_client->driverdata = (void *)loop_server;
loop_server->driverdata = (void *)loop_client;
return loop_client;
}
qsocket_t *Loop_CheckNewConnections (void)
{
GpError("Loop_CheckNewConnections",0);
if (!localconnectpending){
GpError("Loop_CheckNewConnections NULL",0);
return NULL;
}
localconnectpending = false;
loop_server->sendMessageLength = 0;
loop_server->receiveMessageLength = 0;
loop_server->canSend = true;
loop_client->sendMessageLength = 0;
loop_client->receiveMessageLength = 0;
loop_client->canSend = true;
GpError("Loop_CheckNewConnections done",0);
return loop_server;
}
static int IntAlign(int value)
{
return (value + (sizeof(int) - 1)) & (~(sizeof(int) - 1));
}
int Loop_GetMessage (qsocket_t *sock)
{
int ret;
int length;
if (sock->receiveMessageLength == 0){
return 0;
}
ret = sock->receiveMessage[0];
length = sock->receiveMessage[1] + (sock->receiveMessage[2] << 8);
// alignment byte skipped here
SZ_Clear (&net_message);
SZ_Write (&net_message, &sock->receiveMessage[4], length);
length = IntAlign(length + 4);
sock->receiveMessageLength -= length;
if (sock->receiveMessageLength)
Q_memcpy(sock->receiveMessage, &sock->receiveMessage[length], sock->receiveMessageLength);
if (sock->driverdata && ret == 1)
((qsocket_t *)sock->driverdata)->canSend = true;
return ret;
}
int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data)
{
byte *buffer;
int *bufferLength;
if (!sock->driverdata){
return -1;
}
bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength;
if ((*bufferLength + data->cursize + 4) > NET_MAXMESSAGE){
Sys_Error("Loop_SendMessage: overflow\n");
}
buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength;
// message type
*buffer++ = 1;
// length
*buffer++ = data->cursize & 0xff;
*buffer++ = data->cursize >> 8;
// align
buffer++;
// message
Q_memcpy(buffer, data->data, data->cursize);
*bufferLength = IntAlign(*bufferLength + data->cursize + 4);
sock->canSend = false;
return 1;
}
int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
{
byte *buffer;
int *bufferLength;
if (!sock->driverdata){
return -1;
}
bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength;
if ((*bufferLength + data->cursize + sizeof(byte) + sizeof(short)) > NET_MAXMESSAGE){
return 0;
}
buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength;
// message type
*buffer++ = 2;
// length
*buffer++ = data->cursize & 0xff;
*buffer++ = data->cursize >> 8;
// align
buffer++;
// message
Q_memcpy(buffer, data->data, data->cursize);
*bufferLength = IntAlign(*bufferLength + data->cursize + 4);
GpError("Loop_SUM : done",2);
return 1;
}
qboolean Loop_CanSendMessage (qsocket_t *sock)
{
if (!sock->driverdata){
return false;
}
return sock->canSend;
}
qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock)
{
return true;
}
void Loop_Close (qsocket_t *sock)
{
if (sock->driverdata)
((qsocket_t *)sock->driverdata)->driverdata = NULL;
sock->receiveMessageLength = 0;
sock->sendMessageLength = 0;
sock->canSend = true;
if (sock == loop_client)
loop_client = NULL;
else
loop_server = NULL;
}

View File

@@ -0,0 +1,33 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// net_loop.h
int Loop_Init (void);
void Loop_Listen (qboolean state);
void Loop_SearchForHosts (qboolean xmit);
qsocket_t *Loop_Connect (char *host);
qsocket_t *Loop_CheckNewConnections (void);
int Loop_GetMessage (qsocket_t *sock);
int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data);
int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data);
qboolean Loop_CanSendMessage (qsocket_t *sock);
qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock);
void Loop_Close (qsocket_t *sock);
void Loop_Shutdown (void);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// net_ser.h
int Serial_Init (void);
void Serial_Listen (qboolean state);
void Serial_SearchForHosts (qboolean xmit);
qsocket_t *Serial_Connect (char *host);
qsocket_t *Serial_CheckNewConnections (void);
int Serial_GetMessage (qsocket_t *sock);
int Serial_SendMessage (qsocket_t *sock, sizebuf_t *data);
int Serial_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data);
qboolean Serial_CanSendMessage (qsocket_t *sock);
qboolean Serial_CanSendUnreliableMessage (qsocket_t *sock);
void Serial_Close (qsocket_t *sock);
void Serial_Shutdown (void);

View File

@@ -0,0 +1,422 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// net_udp.c
#include "quakedef.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <errno.h>
#ifdef __sun__
#include <sys/filio.h>
#endif
#ifdef NeXT
#include <libc.h>
#endif
extern int gethostname (char *, int);
extern int close (int);
extern cvar_t hostname;
static int net_acceptsocket = -1; // socket for fielding new connections
static int net_controlsocket;
static int net_broadcastsocket = 0;
static struct qsockaddr broadcastaddr;
static unsigned long myAddr;
#include "net_udp.h"
//=============================================================================
int UDP_Init (void)
{
struct hostent *local;
char buff[MAXHOSTNAMELEN];
struct qsockaddr addr;
char *colon;
if (COM_CheckParm ("-noudp"))
return -1;
// determine my name & address
//gethostname(buff, MAXHOSTNAMELEN);
//local = gethostbyname(buff);
sprintf(buff,"gp2x");
// myAddr = *(int *)local->h_addr_list[0];
// myAddr=htonl((192 << 24) | (168 << 16) | (0 << 8) | 2);
myAddr=htonl((10 << 24) | (1 << 16) | (0 << 8) | 2);
// if the quake hostname isn't set, set it to the machine name
if (Q_strcmp(hostname.string, "UNNAMED") == 0)
{
buff[15] = 0;
Cvar_Set ("hostname", buff);
}
if ((net_controlsocket = UDP_OpenSocket (0)) == -1)
Sys_Error("UDP_Init: Unable to open control socket\n");
((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
UDP_GetSocketAddr (net_controlsocket, &addr);
Q_strcpy(my_tcpip_address, UDP_AddrToString (&addr));
colon = Q_strrchr (my_tcpip_address, ':');
if (colon)
*colon = 0;
Con_Printf("UDP Initialized\n");
tcpipAvailable = true;
return net_controlsocket;
}
//=============================================================================
void UDP_Shutdown (void)
{
UDP_Listen (false);
UDP_CloseSocket (net_controlsocket);
}
//=============================================================================
void UDP_Listen (qboolean state)
{
// enable listening
if (state)
{
if (net_acceptsocket != -1)
return;
if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1)
Sys_Error ("UDP_Listen: Unable to open accept socket\n");
return;
}
// disable listening
if (net_acceptsocket == -1)
return;
UDP_CloseSocket (net_acceptsocket);
net_acceptsocket = -1;
}
//=============================================================================
int UDP_OpenSocket (int port)
{
int newsocket;
struct sockaddr_in address;
qboolean _true = true;
if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
return -1;
#if 0
if (ioctl (newsocket, FIONBIO, (char *)&_true) == -1)
goto ErrorReturn;
#endif
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
goto ErrorReturn;
return newsocket;
ErrorReturn:
close (newsocket);
return -1;
}
//=============================================================================
int UDP_CloseSocket (int socket)
{
if (socket == net_broadcastsocket)
net_broadcastsocket = 0;
return close (socket);
}
//=============================================================================
/*
============
PartialIPAddress
this lets you type only as much of the net address as required, using
the local network components to fill in the rest
============
*/
static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
{
char buff[256];
char *b;
int addr;
int num;
int mask;
int run;
int port;
buff[0] = '.';
b = buff;
strcpy(buff+1, in);
if (buff[1] == '.')
b++;
addr = 0;
mask=-1;
while (*b == '.')
{
b++;
num = 0;
run = 0;
while (!( *b < '0' || *b > '9'))
{
num = num*10 + *b++ - '0';
if (++run > 3)
return -1;
}
if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
return -1;
if (num < 0 || num > 255)
return -1;
mask<<=8;
addr = (addr<<8) + num;
}
if (*b++ == ':')
port = Q_atoi(b);
else
port = net_hostport;
hostaddr->sa_family = AF_INET;
((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);
((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
return 0;
}
//=============================================================================
int UDP_Connect (int socket, struct qsockaddr *addr)
{
return 0;
}
//=============================================================================
int UDP_CheckNewConnections (void)
{
unsigned long available;
if (net_acceptsocket == -1)
return -1;
if (ioctl (net_acceptsocket, FIONREAD, &available) == -1)
Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
if (available)
return net_acceptsocket;
return -1;
}
//=============================================================================
int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
{
int addrlen = sizeof (struct qsockaddr);
int ret;
ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED))
return 0;
return ret;
}
//=============================================================================
int UDP_MakeSocketBroadcastCapable (int socket)
{
int i = 1;
// make this socket broadcast capable
if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
return -1;
net_broadcastsocket = socket;
return 0;
}
//=============================================================================
int UDP_Broadcast (int socket, byte *buf, int len)
{
int ret;
if (socket != net_broadcastsocket)
{
if (net_broadcastsocket != 0)
Sys_Error("Attempted to use multiple broadcasts sockets\n");
ret = UDP_MakeSocketBroadcastCapable (socket);
if (ret == -1)
{
Con_Printf("Unable to make socket broadcast capable\n");
return ret;
}
}
return UDP_Write (socket, buf, len, &broadcastaddr);
}
//=============================================================================
int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
{
int ret;
ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
if (ret == -1 && errno == EWOULDBLOCK)
return 0;
return ret;
}
//=============================================================================
char *UDP_AddrToString (struct qsockaddr *addr)
{
static char buffer[22];
int haddr;
haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
return buffer;
}
//=============================================================================
int UDP_StringToAddr (char *string, struct qsockaddr *addr)
{
int ha1, ha2, ha3, ha4, hp;
int ipaddr;
sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
((struct sockaddr_in *)addr)->sin_port = htons(hp);
return 0;
}
//=============================================================================
int UDP_GetSocketAddr (int socket, struct qsockaddr *addr)
{
int addrlen = sizeof(struct qsockaddr);
unsigned int a;
Q_memset(addr, 0, sizeof(struct qsockaddr));
getsockname(socket, (struct sockaddr *)addr, &addrlen);
a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
if (a == 0 || a == inet_addr("127.0.0.1"))
((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
return 0;
}
//=============================================================================
int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name)
{
/*
struct hostent *hostentry;
hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
if (hostentry)
{
Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
return 0;
}
Q_strcpy (name, UDP_AddrToString (addr));
return 0;
*/
sprintf(name,"gp2x");
return 0;
}
//=============================================================================
int UDP_GetAddrFromName(char *name, struct qsockaddr *addr)
{
struct hostent *hostentry;
if (name[0] >= '0' && name[0] <= '9')
return PartialIPAddress (name, addr);
// hostentry = gethostbyname (name);
// if (!hostentry)
// return -1;
addr->sa_family = AF_INET;
((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);
// ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
return 0;
}
//=============================================================================
int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
{
if (addr1->sa_family != addr2->sa_family)
return -1;
if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
return -1;
if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
return 1;
return 0;
}
//=============================================================================
int UDP_GetSocketPort (struct qsockaddr *addr)
{
return ntohs(((struct sockaddr_in *)addr)->sin_port);
}
int UDP_SetSocketPort (struct qsockaddr *addr, int port)
{
((struct sockaddr_in *)addr)->sin_port = htons(port);
return 0;
}
//=============================================================================

View File

@@ -0,0 +1,39 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// net_udp.h
int UDP_Init (void);
void UDP_Shutdown (void);
void UDP_Listen (qboolean state);
int UDP_OpenSocket (int port);
int UDP_CloseSocket (int socket);
int UDP_Connect (int socket, struct qsockaddr *addr);
int UDP_CheckNewConnections (void);
int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr);
int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr);
int UDP_Broadcast (int socket, byte *buf, int len);
char *UDP_AddrToString (struct qsockaddr *addr);
int UDP_StringToAddr (char *string, struct qsockaddr *addr);
int UDP_GetSocketAddr (int socket, struct qsockaddr *addr);
int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name);
int UDP_GetAddrFromName (char *name, struct qsockaddr *addr);
int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2);
int UDP_GetSocketPort (struct qsockaddr *addr);
int UDP_SetSocketPort (struct qsockaddr *addr, int port);

View File

@@ -0,0 +1,167 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// net_vcr.c
#include "quakedef.h"
#include "net_vcr.h"
extern int vcrFile;
// This is the playback portion of the VCR. It reads the file produced
// by the recorder and plays it back to the host. The recording contains
// everything necessary (events, timestamps, and data) to duplicate the game
// from the viewpoint of everything above the network layer.
static struct
{
double time;
int op;
long session;
} next;
int VCR_Init (void)
{
net_drivers[0].Init = VCR_Init;
net_drivers[0].SearchForHosts = VCR_SearchForHosts;
net_drivers[0].Connect = VCR_Connect;
net_drivers[0].CheckNewConnections = VCR_CheckNewConnections;
net_drivers[0].QGetMessage = VCR_GetMessage;
net_drivers[0].QSendMessage = VCR_SendMessage;
net_drivers[0].CanSendMessage = VCR_CanSendMessage;
net_drivers[0].Close = VCR_Close;
net_drivers[0].Shutdown = VCR_Shutdown;
Sys_FileRead(vcrFile, &next, sizeof(next));
return 0;
}
void VCR_ReadNext (void)
{
if (Sys_FileRead(vcrFile, &next, sizeof(next)) == 0)
{
next.op = 255;
Sys_Error ("=== END OF PLAYBACK===\n");
}
if (next.op < 1 || next.op > VCR_MAX_MESSAGE)
Sys_Error ("VCR_ReadNext: bad op");
}
void VCR_Listen (qboolean state)
{
}
void VCR_Shutdown (void)
{
}
int VCR_GetMessage (qsocket_t *sock)
{
int ret;
if (host_time != next.time || next.op != VCR_OP_GETMESSAGE || next.session != *(long *)(&sock->driverdata))
Sys_Error ("VCR missmatch");
Sys_FileRead(vcrFile, &ret, sizeof(int));
if (ret != 1)
{
VCR_ReadNext ();
return ret;
}
Sys_FileRead(vcrFile, &net_message.cursize, sizeof(int));
Sys_FileRead(vcrFile, net_message.data, net_message.cursize);
VCR_ReadNext ();
return 1;
}
int VCR_SendMessage (qsocket_t *sock, sizebuf_t *data)
{
int ret;
if (host_time != next.time || next.op != VCR_OP_SENDMESSAGE || next.session != *(long *)(&sock->driverdata))
Sys_Error ("VCR missmatch");
Sys_FileRead(vcrFile, &ret, sizeof(int));
VCR_ReadNext ();
return ret;
}
qboolean VCR_CanSendMessage (qsocket_t *sock)
{
qboolean ret;
if (host_time != next.time || next.op != VCR_OP_CANSENDMESSAGE || next.session != *(long *)(&sock->driverdata))
Sys_Error ("VCR missmatch");
Sys_FileRead(vcrFile, &ret, sizeof(int));
VCR_ReadNext ();
return ret;
}
void VCR_Close (qsocket_t *sock)
{
}
void VCR_SearchForHosts (qboolean xmit)
{
}
qsocket_t *VCR_Connect (char *host)
{
return NULL;
}
qsocket_t *VCR_CheckNewConnections (void)
{
qsocket_t *sock;
if (host_time != next.time || next.op != VCR_OP_CONNECT)
Sys_Error ("VCR missmatch");
if (!next.session)
{
VCR_ReadNext ();
return NULL;
}
sock = NET_NewQSocket ();
*(long *)(&sock->driverdata) = next.session;
Sys_FileRead (vcrFile, sock->address, NET_NAMELEN);
VCR_ReadNext ();
return sock;
}

View File

@@ -0,0 +1,37 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// net_vcr.h
#define VCR_OP_CONNECT 1
#define VCR_OP_GETMESSAGE 2
#define VCR_OP_SENDMESSAGE 3
#define VCR_OP_CANSENDMESSAGE 4
#define VCR_MAX_MESSAGE 4
int VCR_Init (void);
void VCR_Listen (qboolean state);
void VCR_SearchForHosts (qboolean xmit);
qsocket_t *VCR_Connect (char *host);
qsocket_t *VCR_CheckNewConnections (void);
int VCR_GetMessage (qsocket_t *sock);
int VCR_SendMessage (qsocket_t *sock, sizebuf_t *data);
qboolean VCR_CanSendMessage (qsocket_t *sock);
void VCR_Close (qsocket_t *sock);
void VCR_Shutdown (void);

View File

@@ -0,0 +1,39 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// net_wins.h
int WINS_Init (void);
void WINS_Shutdown (void);
void WINS_Listen (qboolean state);
int WINS_OpenSocket (int port);
int WINS_CloseSocket (int socket);
int WINS_Connect (int socket, struct qsockaddr *addr);
int WINS_CheckNewConnections (void);
int WINS_Read (int socket, byte *buf, int len, struct qsockaddr *addr);
int WINS_Write (int socket, byte *buf, int len, struct qsockaddr *addr);
int WINS_Broadcast (int socket, byte *buf, int len);
char *WINS_AddrToString (struct qsockaddr *addr);
int WINS_StringToAddr (char *string, struct qsockaddr *addr);
int WINS_GetSocketAddr (int socket, struct qsockaddr *addr);
int WINS_GetNameFromAddr (struct qsockaddr *addr, char *name);
int WINS_GetAddrFromName (char *name, struct qsockaddr *addr);
int WINS_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2);
int WINS_GetSocketPort (struct qsockaddr *addr);
int WINS_SetSocketPort (struct qsockaddr *addr, int port);

View File

@@ -0,0 +1,39 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// net_wipx.h
int WIPX_Init (void);
void WIPX_Shutdown (void);
void WIPX_Listen (qboolean state);
int WIPX_OpenSocket (int port);
int WIPX_CloseSocket (int socket);
int WIPX_Connect (int socket, struct qsockaddr *addr);
int WIPX_CheckNewConnections (void);
int WIPX_Read (int socket, byte *buf, int len, struct qsockaddr *addr);
int WIPX_Write (int socket, byte *buf, int len, struct qsockaddr *addr);
int WIPX_Broadcast (int socket, byte *buf, int len);
char *WIPX_AddrToString (struct qsockaddr *addr);
int WIPX_StringToAddr (char *string, struct qsockaddr *addr);
int WIPX_GetSocketAddr (int socket, struct qsockaddr *addr);
int WIPX_GetNameFromAddr (struct qsockaddr *addr, char *name);
int WIPX_GetAddrFromName (char *name, struct qsockaddr *addr);
int WIPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2);
int WIPX_GetSocketPort (struct qsockaddr *addr);
int WIPX_SetSocketPort (struct qsockaddr *addr, int port);

View File

@@ -0,0 +1,70 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//
// nonintel.c: code for non-Intel processors only
//
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h"
#if !id386
/*
================
R_Surf8Patch
================
*/
void R_Surf8Patch ()
{
// we only patch code on Intel
}
/*
================
R_Surf16Patch
================
*/
void R_Surf16Patch ()
{
// we only patch code on Intel
}
/*
================
R_SurfacePatch
================
*/
void R_SurfacePatch (void)
{
// we only patch code on Intel
}
#ifdef USEFPM
void R_SurfacePatchFPM (void)
{
// we only patch code on Intel
}
#endif
#endif // !id386

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// this file is shared by quake and qcc
typedef int func_t;
typedef int string_t;
typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer} etype_t;
#define OFS_NULL 0
#define OFS_RETURN 1
#define OFS_PARM0 4 // leave 3 ofs for each parm to hold vectors
#define OFS_PARM1 7
#define OFS_PARM2 10
#define OFS_PARM3 13
#define OFS_PARM4 16
#define OFS_PARM5 19
#define OFS_PARM6 22
#define OFS_PARM7 25
#define RESERVED_OFS 28
enum {
OP_DONE,
OP_MUL_F,
OP_MUL_V,
OP_MUL_FV,
OP_MUL_VF,
OP_DIV_F,
OP_ADD_F,
OP_ADD_V,
OP_SUB_F,
OP_SUB_V,
OP_EQ_F,
OP_EQ_V,
OP_EQ_S,
OP_EQ_E,
OP_EQ_FNC,
OP_NE_F,
OP_NE_V,
OP_NE_S,
OP_NE_E,
OP_NE_FNC,
OP_LE,
OP_GE,
OP_LT,
OP_GT,
OP_LOAD_F,
OP_LOAD_V,
OP_LOAD_S,
OP_LOAD_ENT,
OP_LOAD_FLD,
OP_LOAD_FNC,
OP_ADDRESS,
OP_STORE_F,
OP_STORE_V,
OP_STORE_S,
OP_STORE_ENT,
OP_STORE_FLD,
OP_STORE_FNC,
OP_STOREP_F,
OP_STOREP_V,
OP_STOREP_S,
OP_STOREP_ENT,
OP_STOREP_FLD,
OP_STOREP_FNC,
OP_RETURN,
OP_NOT_F,
OP_NOT_V,
OP_NOT_S,
OP_NOT_ENT,
OP_NOT_FNC,
OP_IF,
OP_IFNOT,
OP_CALL0,
OP_CALL1,
OP_CALL2,
OP_CALL3,
OP_CALL4,
OP_CALL5,
OP_CALL6,
OP_CALL7,
OP_CALL8,
OP_STATE,
OP_GOTO,
OP_AND,
OP_OR,
OP_BITAND,
OP_BITOR
};
typedef struct statement_s
{
unsigned short op;
short a,b,c;
} dstatement_t;
typedef struct
{
unsigned short type; // if DEF_SAVEGLOBGAL bit is set
// the variable needs to be saved in savegames
unsigned short ofs;
int s_name;
} ddef_t;
#define DEF_SAVEGLOBAL (1<<15)
#define MAX_PARMS 8
typedef struct
{
int first_statement; // negative numbers are builtins
int parm_start;
int locals; // total ints of parms + locals
int profile; // runtime
int s_name;
int s_file; // source file defined in
int numparms;
byte parm_size[MAX_PARMS];
} dfunction_t;
#define PROG_VERSION 6
typedef struct
{
int version;
int crc; // check of header file
int ofs_statements;
int numstatements; // statement 0 is an error
int ofs_globaldefs;
int numglobaldefs;
int ofs_fielddefs;
int numfielddefs;
int ofs_functions;
int numfunctions; // function 0 is an empty
int ofs_strings;
int numstrings; // first string is a null string
int ofs_globals;
int numglobals;
int entityfields;
} dprograms_t;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,979 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
/*
*/
typedef struct
{
int s;
dfunction_t *f;
} prstack_t;
#define MAX_STACK_DEPTH 32
prstack_t pr_stack[MAX_STACK_DEPTH];
int pr_depth;
#define LOCALSTACK_SIZE 2048
int localstack[LOCALSTACK_SIZE];
int localstack_used;
qboolean pr_trace;
dfunction_t *pr_xfunction;
int pr_xstatement;
int pr_argc;
char *pr_opnames[] =
{
"DONE",
"MUL_F",
"MUL_V",
"MUL_FV",
"MUL_VF",
"DIV",
"ADD_F",
"ADD_V",
"SUB_F",
"SUB_V",
"EQ_F",
"EQ_V",
"EQ_S",
"EQ_E",
"EQ_FNC",
"NE_F",
"NE_V",
"NE_S",
"NE_E",
"NE_FNC",
"LE",
"GE",
"LT",
"GT",
"INDIRECT",
"INDIRECT",
"INDIRECT",
"INDIRECT",
"INDIRECT",
"INDIRECT",
"ADDRESS",
"STORE_F",
"STORE_V",
"STORE_S",
"STORE_ENT",
"STORE_FLD",
"STORE_FNC",
"STOREP_F",
"STOREP_V",
"STOREP_S",
"STOREP_ENT",
"STOREP_FLD",
"STOREP_FNC",
"RETURN",
"NOT_F",
"NOT_V",
"NOT_S",
"NOT_ENT",
"NOT_FNC",
"IF",
"IFNOT",
"CALL0",
"CALL1",
"CALL2",
"CALL3",
"CALL4",
"CALL5",
"CALL6",
"CALL7",
"CALL8",
"STATE",
"GOTO",
"AND",
"OR",
"BITAND",
"BITOR"
};
char *PR_GlobalString (int ofs);
char *PR_GlobalStringNoContents (int ofs);
//=============================================================================
/*
=================
PR_PrintStatement
=================
*/
void PR_PrintStatement (dstatement_t *s)
{
int i;
if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
{
Con_Printf ("%s ", pr_opnames[s->op]);
i = strlen(pr_opnames[s->op]);
for ( ; i<10 ; i++)
Con_Printf (" ");
}
if (s->op == OP_IF || s->op == OP_IFNOT)
Con_Printf ("%sbranch %i",PR_GlobalString(s->a),s->b);
else if (s->op == OP_GOTO)
{
Con_Printf ("branch %i",s->a);
}
else if ( (unsigned)(s->op - OP_STORE_F) < 6)
{
Con_Printf ("%s",PR_GlobalString(s->a));
Con_Printf ("%s", PR_GlobalStringNoContents(s->b));
}
else
{
if (s->a)
Con_Printf ("%s",PR_GlobalString(s->a));
if (s->b)
Con_Printf ("%s",PR_GlobalString(s->b));
if (s->c)
Con_Printf ("%s", PR_GlobalStringNoContents(s->c));
}
Con_Printf ("\n");
}
/*
============
PR_StackTrace
============
*/
void PR_StackTrace (void)
{
dfunction_t *f;
int i;
if (pr_depth == 0)
{
Con_Printf ("<NO STACK>\n");
return;
}
pr_stack[pr_depth].f = pr_xfunction;
for (i=pr_depth ; i>=0 ; i--)
{
f = pr_stack[i].f;
if (!f)
{
Con_Printf ("<NO FUNCTION>\n");
}
else
Con_Printf ("%12s : %s\n", pr_strings + f->s_file, pr_strings + f->s_name);
}
}
/*
============
PR_Profile_f
============
*/
void PR_Profile_f (void)
{
dfunction_t *f, *best;
int max;
int num;
int i;
num = 0;
do
{
max = 0;
best = NULL;
for (i=0 ; i<progs->numfunctions ; i++)
{
f = &pr_functions[i];
if (f->profile > max)
{
max = f->profile;
best = f;
}
}
if (best)
{
if (num < 10)
Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name);
num++;
best->profile = 0;
}
} while (best);
}
/*
============
PR_RunError
Aborts the currently executing function
============
*/
void PR_RunError (char *error, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,error);
vsprintf (string,error,argptr);
va_end (argptr);
PR_PrintStatement (pr_statements + pr_xstatement);
PR_StackTrace ();
Con_Printf ("%s\n", string);
pr_depth = 0; // dump the stack so host_error can shutdown functions
Host_Error ("Program error");
}
/*
============================================================================
PR_ExecuteProgram
The interpretation main loop
============================================================================
*/
/*
====================
PR_EnterFunction
Returns the new program statement counter
====================
*/
int PR_EnterFunction (dfunction_t *f)
{
int i, j, c, o;
pr_stack[pr_depth].s = pr_xstatement;
pr_stack[pr_depth].f = pr_xfunction;
pr_depth++;
if (pr_depth >= MAX_STACK_DEPTH)
PR_RunError ("stack overflow");
// save off any locals that the new function steps on
c = f->locals;
if (localstack_used + c > LOCALSTACK_SIZE)
PR_RunError ("PR_ExecuteProgram: locals stack overflow\n");
for (i=0 ; i < c ; i++)
localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
localstack_used += c;
// copy parameters
o = f->parm_start;
for (i=0 ; i<f->numparms ; i++)
{
for (j=0 ; j<f->parm_size[i] ; j++)
{
((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
o++;
}
}
pr_xfunction = f;
return f->first_statement - 1; // offset the s++
}
/*
====================
PR_LeaveFunction
====================
*/
int PR_LeaveFunction (void)
{
int i, c;
if (pr_depth <= 0)
Sys_Error ("prog stack underflow");
// restore locals from the stack
c = pr_xfunction->locals;
localstack_used -= c;
if (localstack_used < 0)
PR_RunError ("PR_ExecuteProgram: locals stack underflow\n");
for (i=0 ; i < c ; i++)
((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
// up stack
pr_depth--;
pr_xfunction = pr_stack[pr_depth].f;
return pr_stack[pr_depth].s;
}
/*
====================
PR_ExecuteProgram
====================
*/
void PR_ExecuteProgram (func_t fnum)
{
eval_t *a, *b, *c;
int s;
dstatement_t *st;
dfunction_t *f, *newf;
int runaway;
int i;
edict_t *ed;
int exitdepth;
eval_t *ptr;
if (!fnum || fnum >= progs->numfunctions)
{
if (pr_global_struct->self)
ED_Print (PROG_TO_EDICT(pr_global_struct->self));
Host_Error ("PR_ExecuteProgram: NULL function");
}
f = &pr_functions[fnum];
runaway = 100000;
pr_trace = false;
// make a stack frame
exitdepth = pr_depth;
s = PR_EnterFunction (f);
while (1)
{
s++; // next statement
st = &pr_statements[s];
a = (eval_t *)&pr_globals[st->a];
b = (eval_t *)&pr_globals[st->b];
c = (eval_t *)&pr_globals[st->c];
if (!--runaway)
PR_RunError ("runaway loop error");
pr_xfunction->profile++;
pr_xstatement = s;
if (pr_trace)
PR_PrintStatement (st);
switch (st->op)
{
case OP_ADD_F:
c->_float = a->_float + b->_float;
break;
case OP_ADD_V:
c->vector[0] = a->vector[0] + b->vector[0];
c->vector[1] = a->vector[1] + b->vector[1];
c->vector[2] = a->vector[2] + b->vector[2];
break;
case OP_SUB_F:
c->_float = a->_float - b->_float;
break;
case OP_SUB_V:
c->vector[0] = a->vector[0] - b->vector[0];
c->vector[1] = a->vector[1] - b->vector[1];
c->vector[2] = a->vector[2] - b->vector[2];
break;
case OP_MUL_F:
c->_float = a->_float * b->_float;
break;
case OP_MUL_V:
c->_float = a->vector[0]*b->vector[0]
+ a->vector[1]*b->vector[1]
+ a->vector[2]*b->vector[2];
break;
case OP_MUL_FV:
c->vector[0] = a->_float * b->vector[0];
c->vector[1] = a->_float * b->vector[1];
c->vector[2] = a->_float * b->vector[2];
break;
case OP_MUL_VF:
c->vector[0] = b->_float * a->vector[0];
c->vector[1] = b->_float * a->vector[1];
c->vector[2] = b->_float * a->vector[2];
break;
case OP_DIV_F:
c->_float = a->_float / b->_float;
break;
case OP_BITAND:
c->_float = (float)((int)a->_float & (int)b->_float);
break;
case OP_BITOR:
c->_float = (float)((int)a->_float | (int)b->_float);
break;
case OP_GE:
c->_float = (float)(a->_float >= b->_float);
break;
case OP_LE:
c->_float = (float)(a->_float <= b->_float);
break;
case OP_GT:
c->_float = (float)(a->_float > b->_float);
break;
case OP_LT:
c->_float = (float)(a->_float < b->_float);
break;
case OP_AND:
c->_float = (float)(a->_float && b->_float);
break;
case OP_OR:
c->_float = (float)(a->_float || b->_float);
break;
case OP_NOT_F:
c->_float = (float)!a->_float;
break;
case OP_NOT_V:
c->_float = (float)(!a->vector[0] && !a->vector[1] && !a->vector[2]);
break;
case OP_NOT_S:
c->_float = (float)(!a->string || !pr_strings[a->string]);
break;
case OP_NOT_FNC:
c->_float = (float)!a->function;
break;
case OP_NOT_ENT:
c->_float = (float)(PROG_TO_EDICT(a->edict) == sv.edicts);
break;
case OP_EQ_F:
c->_float = (float)(a->_float == b->_float);
break;
case OP_EQ_V:
c->_float = (float)((a->vector[0] == b->vector[0]) &&
(a->vector[1] == b->vector[1]) &&
(a->vector[2] == b->vector[2]));
break;
case OP_EQ_S:
c->_float = (float)!strcmp(pr_strings+a->string,pr_strings+b->string);
break;
case OP_EQ_E:
c->_float = (float)(a->_int == b->_int);
break;
case OP_EQ_FNC:
c->_float = (float)(a->function == b->function);
break;
case OP_NE_F:
c->_float = (float)(a->_float != b->_float);
break;
case OP_NE_V:
c->_float = (float)((a->vector[0] != b->vector[0]) ||
(a->vector[1] != b->vector[1]) ||
(a->vector[2] != b->vector[2]));
break;
case OP_NE_S:
c->_float = (float)strcmp(pr_strings+a->string,pr_strings+b->string);
break;
case OP_NE_E:
c->_float = (float)(a->_int != b->_int);
break;
case OP_NE_FNC:
c->_float = (float)(a->function != b->function);
break;
//==================
case OP_STORE_F:
case OP_STORE_ENT:
case OP_STORE_FLD: // integers
case OP_STORE_S:
case OP_STORE_FNC: // pointers
b->_int = a->_int;
break;
case OP_STORE_V:
b->vector[0] = a->vector[0];
b->vector[1] = a->vector[1];
b->vector[2] = a->vector[2];
break;
case OP_STOREP_F:
case OP_STOREP_ENT:
case OP_STOREP_FLD: // integers
case OP_STOREP_S:
case OP_STOREP_FNC: // pointers
ptr = (eval_t *)((byte *)sv.edicts + b->_int);
ptr->_int = a->_int;
break;
case OP_STOREP_V:
ptr = (eval_t *)((byte *)sv.edicts + b->_int);
ptr->vector[0] = a->vector[0];
ptr->vector[1] = a->vector[1];
ptr->vector[2] = a->vector[2];
break;
case OP_ADDRESS:
ed = PROG_TO_EDICT(a->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
PR_RunError ("assignment to world entity");
c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts;
break;
case OP_LOAD_F:
case OP_LOAD_FLD:
case OP_LOAD_ENT:
case OP_LOAD_S:
case OP_LOAD_FNC:
ed = PROG_TO_EDICT(a->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
a = (eval_t *)((int *)&ed->v + b->_int);
c->_int = a->_int;
break;
case OP_LOAD_V:
ed = PROG_TO_EDICT(a->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
a = (eval_t *)((int *)&ed->v + b->_int);
c->vector[0] = a->vector[0];
c->vector[1] = a->vector[1];
c->vector[2] = a->vector[2];
break;
//==================
case OP_IFNOT:
if (!a->_int)
s += st->b - 1; // offset the s++
break;
case OP_IF:
if (a->_int)
s += st->b - 1; // offset the s++
break;
case OP_GOTO:
s += st->a - 1; // offset the s++
break;
case OP_CALL0:
case OP_CALL1:
case OP_CALL2:
case OP_CALL3:
case OP_CALL4:
case OP_CALL5:
case OP_CALL6:
case OP_CALL7:
case OP_CALL8:
pr_argc = st->op - OP_CALL0;
if (!a->function)
PR_RunError ("NULL function");
newf = &pr_functions[a->function];
if (newf->first_statement < 0)
{ // negative statements are built in functions
i = -newf->first_statement;
if (i >= pr_numbuiltins)
PR_RunError ("Bad builtin call number");
pr_builtins[i] ();
break;
}
s = PR_EnterFunction (newf);
break;
case OP_DONE:
case OP_RETURN:
pr_globals[OFS_RETURN] = pr_globals[st->a];
pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
s = PR_LeaveFunction ();
if (pr_depth == exitdepth)
return; // all done
break;
case OP_STATE:
ed = PROG_TO_EDICT(pr_global_struct->self);
#ifdef FPS_20
ed->v.nextthink = (float)(pr_global_struct->time + 0.05);
#else
ed->v.nextthink = (float)(pr_global_struct->time + 0.1);
#endif
if (a->_float != ed->v.frame)
{
ed->v.frame = a->_float;
}
ed->v.think = b->function;
break;
default:
PR_RunError ("Bad opcode %i", st->op);
}
}
}
#ifdef USEFPM
void PR_ExecuteProgramFPM (func_t fnum)
{
eval_t *a, *b, *c;
int s;
dstatement_t *st;
dfunction_t *f, *newf;
int runaway;
int i;
edict_FPM_t *ed;
int exitdepth;
eval_t *ptr;
if (!fnum || fnum >= progs->numfunctions)
{
if (pr_global_struct->self)
ED_PrintFPM (PROG_TO_EDICTFPM(pr_global_struct->self));
Host_Error ("PR_ExecuteProgram: NULL function");
}
f = &pr_functions[fnum];
runaway = 100000;
pr_trace = false;
// make a stack frame
exitdepth = pr_depth;
s = PR_EnterFunction (f);
while (1)
{
s++; // next statement
st = &pr_statements[s];
a = (eval_t *)&pr_globals[st->a];
b = (eval_t *)&pr_globals[st->b];
c = (eval_t *)&pr_globals[st->c];
if (!--runaway)
PR_RunError ("runaway loop error");
pr_xfunction->profile++;
pr_xstatement = s;
if (pr_trace)
PR_PrintStatement (st);
switch (st->op)
{
case OP_ADD_F:
c->_float = a->_float + b->_float;
break;
case OP_ADD_V:
c->vector[0] = a->vector[0] + b->vector[0];
c->vector[1] = a->vector[1] + b->vector[1];
c->vector[2] = a->vector[2] + b->vector[2];
break;
case OP_SUB_F:
c->_float = a->_float - b->_float;
break;
case OP_SUB_V:
c->vector[0] = a->vector[0] - b->vector[0];
c->vector[1] = a->vector[1] - b->vector[1];
c->vector[2] = a->vector[2] - b->vector[2];
break;
case OP_MUL_F:
c->_float = a->_float * b->_float;
break;
case OP_MUL_V:
c->_float = a->vector[0]*b->vector[0]
+ a->vector[1]*b->vector[1]
+ a->vector[2]*b->vector[2];
break;
case OP_MUL_FV:
c->vector[0] = a->_float * b->vector[0];
c->vector[1] = a->_float * b->vector[1];
c->vector[2] = a->_float * b->vector[2];
break;
case OP_MUL_VF:
c->vector[0] = b->_float * a->vector[0];
c->vector[1] = b->_float * a->vector[1];
c->vector[2] = b->_float * a->vector[2];
break;
case OP_DIV_F:
c->_float = a->_float / b->_float;
break;
case OP_BITAND:
c->_float = (float)((int)a->_float & (int)b->_float);
break;
case OP_BITOR:
c->_float = (float)((int)a->_float | (int)b->_float);
break;
case OP_GE:
c->_float = (float)(a->_float >= b->_float);
break;
case OP_LE:
c->_float = (float)(a->_float <= b->_float);
break;
case OP_GT:
c->_float = (float)(a->_float > b->_float);
break;
case OP_LT:
c->_float = (float)(a->_float < b->_float);
break;
case OP_AND:
c->_float = (float)(a->_float && b->_float);
break;
case OP_OR:
c->_float = (float)(a->_float || b->_float);
break;
case OP_NOT_F:
c->_float = (float)(!a->_float);
break;
case OP_NOT_V:
c->_float = (float)(!a->vector[0] && !a->vector[1] && !a->vector[2]);
break;
case OP_NOT_S:
c->_float = (float)(!a->string || !pr_strings[a->string]);
break;
case OP_NOT_FNC:
c->_float = (float)(!a->function);
break;
case OP_NOT_ENT:
c->_float = (float)(PROG_TO_EDICT(a->edict) == sv.edicts);
break;
case OP_EQ_F:
c->_float = (float)(a->_float == b->_float);
break;
case OP_EQ_V:
c->_float = (float)((a->vector[0] == b->vector[0]) &&
(a->vector[1] == b->vector[1]) &&
(a->vector[2] == b->vector[2]));
break;
case OP_EQ_S:
c->_float = (float)!strcmp(pr_strings+a->string,pr_strings+b->string);
break;
case OP_EQ_E:
c->_float = (float)(a->_int == b->_int);
break;
case OP_EQ_FNC:
c->_float = (float)(a->function == b->function);
break;
case OP_NE_F:
c->_float = (float)(a->_float != b->_float);
break;
case OP_NE_V:
c->_float = (float)((a->vector[0] != b->vector[0]) ||
(a->vector[1] != b->vector[1]) ||
(a->vector[2] != b->vector[2]));
break;
case OP_NE_S:
c->_float = (float)strcmp(pr_strings+a->string,pr_strings+b->string);
break;
case OP_NE_E:
c->_float = (float)(a->_int != b->_int);
break;
case OP_NE_FNC:
c->_float = (float)(a->function != b->function);
break;
//==================
case OP_STORE_F:
case OP_STORE_ENT:
case OP_STORE_FLD: // integers
case OP_STORE_S:
case OP_STORE_FNC: // pointers
b->_int = a->_int;
break;
case OP_STORE_V:
b->vector[0] = a->vector[0];
b->vector[1] = a->vector[1];
b->vector[2] = a->vector[2];
break;
case OP_STOREP_F:
case OP_STOREP_ENT:
case OP_STOREP_FLD: // integers
case OP_STOREP_S:
case OP_STOREP_FNC: // pointers
ptr = (eval_t *)((byte *)svFPM.edicts + b->_int);
ptr->_int = a->_int;
break;
case OP_STOREP_V:
ptr = (eval_t *)((byte *)svFPM.edicts + b->_int);
ptr->vector[0] = a->vector[0];
ptr->vector[1] = a->vector[1];
ptr->vector[2] = a->vector[2];
break;
case OP_ADDRESS:
ed = PROG_TO_EDICTFPM(a->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
if (ed == (edict_FPM_t *)svFPM.edicts && svFPM.state == ss_active)
PR_RunError ("assignment to world entity");
c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)svFPM.edicts;
break;
case OP_LOAD_F:
case OP_LOAD_FLD:
case OP_LOAD_ENT:
case OP_LOAD_S:
case OP_LOAD_FNC:
ed = PROG_TO_EDICTFPM(a->edict);
#ifdef PARANOID
NUM_FOR_EDICTFPM(ed); // make sure it's in range
#endif
a = (eval_t *)((int *)&ed->v + b->_int);
c->_int = a->_int;
break;
case OP_LOAD_V:
ed = PROG_TO_EDICTFPM(a->edict);
#ifdef PARANOID
NUM_FOR_EDICTFPM(ed); // make sure it's in range
#endif
a = (eval_t *)((int *)&ed->v + b->_int);
c->vector[0] = a->vector[0];
c->vector[1] = a->vector[1];
c->vector[2] = a->vector[2];
break;
//==================
case OP_IFNOT:
if (!a->_int)
s += st->b - 1; // offset the s++
break;
case OP_IF:
if (a->_int)
s += st->b - 1; // offset the s++
break;
case OP_GOTO:
s += st->a - 1; // offset the s++
break;
case OP_CALL0:
case OP_CALL1:
case OP_CALL2:
case OP_CALL3:
case OP_CALL4:
case OP_CALL5:
case OP_CALL6:
case OP_CALL7:
case OP_CALL8:
pr_argc = st->op - OP_CALL0;
if (!a->function)
PR_RunError ("NULL function");
newf = &pr_functions[a->function];
if (newf->first_statement < 0)
{ // negative statements are built in functions
i = -newf->first_statement;
if (i >= pr_numbuiltins)
PR_RunError ("Bad builtin call number");
pr_builtinsFPM[i] ();
break;
}
s = PR_EnterFunction (newf);
break;
case OP_DONE:
case OP_RETURN:
pr_globals[OFS_RETURN] = pr_globals[st->a];
pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
s = PR_LeaveFunction ();
if (pr_depth == exitdepth)
return; // all done
break;
case OP_STATE:
ed = PROG_TO_EDICTFPM(pr_global_struct->self);
#ifdef FPS_20
ed->v.nextthink = (float)(pr_global_struct->time + 0.05);
#else
ed->v.nextthink = (float)(pr_global_struct->time + 0.1);
#endif
if (a->_float != ed->v.frame)
{
ed->v.frame = a->_float;
}
ed->v.think = b->function;
break;
default:
PR_RunError ("Bad opcode %i", st->op);
}
}
}
#endif //USEFPM

View File

@@ -0,0 +1,24 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef QUAKE2
#include "progdefs.q2"
#else
#include "progdefs.q1"
#endif

View File

@@ -0,0 +1,143 @@
/* file generated by qcc, do not modify */
typedef struct
{ int pad[28];
int self;
int other;
int world;
float time;
float frametime;
float force_retouch;
string_t mapname;
float deathmatch;
float coop;
float teamplay;
float serverflags;
float total_secrets;
float total_monsters;
float found_secrets;
float killed_monsters;
float parm1;
float parm2;
float parm3;
float parm4;
float parm5;
float parm6;
float parm7;
float parm8;
float parm9;
float parm10;
float parm11;
float parm12;
float parm13;
float parm14;
float parm15;
float parm16;
vec3_t v_forward;
vec3_t v_up;
vec3_t v_right;
float trace_allsolid;
float trace_startsolid;
float trace_fraction;
vec3_t trace_endpos;
vec3_t trace_plane_normal;
float trace_plane_dist;
int trace_ent;
float trace_inopen;
float trace_inwater;
int msg_entity;
func_t main;
func_t StartFrame;
func_t PlayerPreThink;
func_t PlayerPostThink;
func_t ClientKill;
func_t ClientConnect;
func_t PutClientInServer;
func_t ClientDisconnect;
func_t SetNewParms;
func_t SetChangeParms;
} globalvars_t;
typedef struct
{
float modelindex;
vec3_t absmin;
vec3_t absmax;
float ltime;
float movetype;
float solid;
vec3_t origin;
vec3_t oldorigin;
vec3_t velocity;
vec3_t angles;
vec3_t avelocity;
vec3_t punchangle;
string_t classname;
string_t model;
float frame;
float skin;
float effects;
vec3_t mins;
vec3_t maxs;
vec3_t size;
func_t touch;
func_t use;
func_t think;
func_t blocked;
float nextthink;
int groundentity;
float health;
float frags;
float weapon;
string_t weaponmodel;
float weaponframe;
float currentammo;
float ammo_shells;
float ammo_nails;
float ammo_rockets;
float ammo_cells;
float items;
float takedamage;
int chain;
float deadflag;
vec3_t view_ofs;
float button0;
float button1;
float button2;
float impulse;
float fixangle;
vec3_t v_angle;
float idealpitch;
string_t netname;
int enemy;
float flags;
float colormap;
float team;
float max_health;
float teleport_time;
float armortype;
float armorvalue;
float waterlevel;
float watertype;
float ideal_yaw;
float yaw_speed;
int aiment;
int goalentity;
float spawnflags;
string_t target;
string_t targetname;
float dmg_take;
float dmg_save;
int dmg_inflictor;
int owner;
vec3_t movedir;
string_t message;
float sounds;
string_t noise;
string_t noise1;
string_t noise2;
string_t noise3;
} entvars_t;
#define PROGHEADER_CRC 5927

View File

@@ -0,0 +1,170 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "pr_comp.h" // defs shared with qcc
#include "progdefs.h" // generated by program cdefs
typedef union eval_s
{
string_t string;
float _float;
float vector[3];
func_t function;
int _int;
int edict;
} eval_t;
#define MAX_ENT_LEAFS 16
typedef struct edict_s
{
qboolean free;
link_t area; // linked to a division node or leaf
int num_leafs;
short leafnums[MAX_ENT_LEAFS];
entity_state_t baseline;
float freetime; // sv.time when the object was freed
entvars_t v; // C exported fields from progs
// other fields from progs come immediately after
} edict_t;
typedef struct edict_FPM_s
{
qboolean free;
link_t area; // linked to a division node or leaf
int num_leafs;
short leafnums[MAX_ENT_LEAFS];
entity_state_FPM_t baseline;
float freetime; // sv.time when the object was freed
entvars_t v; // C exported fields from progs
// other fields from progs come immediately after
} edict_FPM_t;
#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area)
#define EDICT_FROM_AREAFPM(l) STRUCT_FROM_LINK(l,edict_FPM_t,area)
//============================================================================
extern dprograms_t *progs;
extern dfunction_t *pr_functions;
extern char *pr_strings;
extern ddef_t *pr_globaldefs;
extern ddef_t *pr_fielddefs;
extern dstatement_t *pr_statements;
extern globalvars_t *pr_global_struct;
extern float *pr_globals; // same as pr_global_struct
extern int pr_edict_size; // in bytes
//============================================================================
void PR_Init (void);
void PR_ExecuteProgram (func_t fnum);
void PR_ExecuteProgramFPM (func_t fnum);
void PR_LoadProgs (void);
void PR_Profile_f (void);
edict_t *ED_Alloc (void);
edict_FPM_t *ED_AllocFPM (void);
void ED_Free (edict_t *ed);
void ED_FreeFPM (edict_FPM_t *ed);
char *ED_NewString (char *string);
// returns a copy of the string allocated from the server's string heap
void ED_Print (edict_t *ed);
void ED_PrintFPM (edict_FPM_t *ed);
void ED_Write (FILE *f, edict_t *ed);
void ED_WriteFPM (FILE *f, edict_FPM_t *ed);
char *ED_ParseEdict (char *data, edict_t *ent);
char *ED_ParseEdictFPM (char *data, edict_FPM_t *ent);
void ED_WriteGlobals (FILE *f);
void ED_ParseGlobals (char *data);
void ED_LoadFromFile (char *data);
void ED_LoadFromFileFPM (char *data);
//define EDICT_NUM(n) ((edict_t *)(sv.edicts+ (n)*pr_edict_size))
//define NUM_FOR_EDICT(e) (((byte *)(e) - sv.edicts)/pr_edict_size)
edict_t *EDICT_NUM(int n);
edict_FPM_t *EDICT_NUMFPM(int n);
int NUM_FOR_EDICT(edict_t *e);
int NUM_FOR_EDICTFPM(edict_FPM_t *e);
#define NEXT_EDICT(e) ((edict_t *)( (byte *)e + pr_edict_size))
#define NEXT_EDICTFPM(e) ((edict_FPM_t *)( (byte *)e + pr_edict_size))
#define EDICT_TO_PROG(e) ((byte *)e - (byte *)sv.edicts)
#define EDICT_TO_PROGFPM(e) ((byte *)e - (byte *)svFPM.edicts)
#define PROG_TO_EDICT(e) ((edict_t *)((byte *)sv.edicts + e))
#define PROG_TO_EDICTFPM(e) ((edict_FPM_t *)((byte *)svFPM.edicts + e))
//============================================================================
#define G_FLOAT(o) (pr_globals[o])
#define G_INT(o) (*(int *)&pr_globals[o])
#define G_EDICT(o) ((edict_t *)((byte *)sv.edicts+ *(int *)&pr_globals[o]))
#define G_EDICTFPM(o) ((edict_FPM_t *)((byte *)svFPM.edicts+ *(int *)&pr_globals[o]))
#define G_EDICTNUM(o) NUM_FOR_EDICT(G_EDICT(o))
#define G_EDICTNUMFPM(o) NUM_FOR_EDICTFPM(G_EDICTFPM(o))
#define G_VECTOR(o) (&pr_globals[o])
#define G_STRING(o) (pr_strings + *(string_t *)&pr_globals[o])
#define G_FUNCTION(o) (*(func_t *)&pr_globals[o])
#define E_FLOAT(e,o) (((float*)&e->v)[o])
#define E_INT(e,o) (*(int *)&((float*)&e->v)[o])
#define E_VECTOR(e,o) (&((float*)&e->v)[o])
#define E_STRING(e,o) (pr_strings + *(string_t *)&((float*)&e->v)[o])
extern int type_size[8];
typedef void (*builtin_t) (void);
typedef void (*builtin_FPM_t) (void);
extern builtin_t *pr_builtins;
extern builtin_FPM_t *pr_builtinsFPM;
extern int pr_numbuiltins;
extern int pr_numbuiltinsFPM;
extern int pr_argc;
extern qboolean pr_trace;
extern dfunction_t *pr_xfunction;
extern int pr_xstatement;
extern unsigned short pr_crc;
void PR_RunError (char *error, ...);
void ED_PrintEdicts (void);
void ED_PrintEdictsFPM (void);
void ED_PrintNum (int ent);
eval_t *GetEdictFieldValue(edict_t *ed, char *field);
eval_t *GetEdictFieldValueFPM(edict_FPM_t *ed, char *field);

View File

@@ -0,0 +1,167 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// protocol.h -- communications protocols
#define PROTOCOL_VERSION 15
// if the high bit of the servercmd is set, the low bits are fast update flags:
#define U_MOREBITS (1<<0)
#define U_ORIGIN1 (1<<1)
#define U_ORIGIN2 (1<<2)
#define U_ORIGIN3 (1<<3)
#define U_ANGLE2 (1<<4)
#define U_NOLERP (1<<5) // don't interpolate movement
#define U_FRAME (1<<6)
#define U_SIGNAL (1<<7) // just differentiates from other updates
// svc_update can pass all of the fast update bits, plus more
#define U_ANGLE1 (1<<8)
#define U_ANGLE3 (1<<9)
#define U_MODEL (1<<10)
#define U_COLORMAP (1<<11)
#define U_SKIN (1<<12)
#define U_EFFECTS (1<<13)
#define U_LONGENTITY (1<<14)
#define SU_VIEWHEIGHT (1<<0)
#define SU_IDEALPITCH (1<<1)
#define SU_PUNCH1 (1<<2)
#define SU_PUNCH2 (1<<3)
#define SU_PUNCH3 (1<<4)
#define SU_VELOCITY1 (1<<5)
#define SU_VELOCITY2 (1<<6)
#define SU_VELOCITY3 (1<<7)
//define SU_AIMENT (1<<8) AVAILABLE BIT
#define SU_ITEMS (1<<9)
#define SU_ONGROUND (1<<10) // no data follows, the bit is it
#define SU_INWATER (1<<11) // no data follows, the bit is it
#define SU_WEAPONFRAME (1<<12)
#define SU_ARMOR (1<<13)
#define SU_WEAPON (1<<14)
// a sound with no channel is a local only sound
#define SND_VOLUME (1<<0) // a byte
#define SND_ATTENUATION (1<<1) // a byte
#define SND_LOOPING (1<<2) // a long
// defaults for clientinfo messages
#define DEFAULT_VIEWHEIGHT 22
// game types sent by serverinfo
// these determine which intermission screen plays
#define GAME_COOP 0
#define GAME_DEATHMATCH 1
//==================
// note that there are some defs.qc that mirror to these numbers
// also related to svc_strings[] in cl_parse
//==================
//
// server to client
//
#define svc_bad 0
#define svc_nop 1
#define svc_disconnect 2
#define svc_updatestat 3 // [byte] [long]
#define svc_version 4 // [long] server version
#define svc_setview 5 // [short] entity number
#define svc_sound 6 // <see code>
#define svc_time 7 // [float] server time
#define svc_print 8 // [string] null terminated string
#define svc_stufftext 9 // [string] stuffed into client's console buffer
// the string should be \n terminated
#define svc_setangle 10 // [angle3] set the view angle to this absolute value
#define svc_serverinfo 11 // [long] version
// [string] signon string
// [string]..[0]model cache
// [string]...[0]sounds cache
#define svc_lightstyle 12 // [byte] [string]
#define svc_updatename 13 // [byte] [string]
#define svc_updatefrags 14 // [byte] [short]
#define svc_clientdata 15 // <shortbits + data>
#define svc_stopsound 16 // <see code>
#define svc_updatecolors 17 // [byte] [byte]
#define svc_particle 18 // [vec3] <variable>
#define svc_damage 19
#define svc_spawnstatic 20
// svc_spawnbinary 21
#define svc_spawnbaseline 22
#define svc_temp_entity 23
#define svc_setpause 24 // [byte] on / off
#define svc_signonnum 25 // [byte] used for the signon sequence
#define svc_centerprint 26 // [string] to put in center of the screen
#define svc_killedmonster 27
#define svc_foundsecret 28
#define svc_spawnstaticsound 29 // [coord3] [byte] samp [byte] vol [byte] aten
#define svc_intermission 30 // [string] music
#define svc_finale 31 // [string] music [string] text
#define svc_cdtrack 32 // [byte] track [byte] looptrack
#define svc_sellscreen 33
#define svc_cutscene 34
//
// client to server
//
#define clc_bad 0
#define clc_nop 1
#define clc_disconnect 2
#define clc_move 3 // [usercmd_t]
#define clc_stringcmd 4 // [string] message
//
// temp entity events
//
#define TE_SPIKE 0
#define TE_SUPERSPIKE 1
#define TE_GUNSHOT 2
#define TE_EXPLOSION 3
#define TE_TAREXPLOSION 4
#define TE_LIGHTNING1 5
#define TE_LIGHTNING2 6
#define TE_WIZSPIKE 7
#define TE_KNIGHTSPIKE 8
#define TE_LIGHTNING3 9
#define TE_LAVASPLASH 10
#define TE_TELEPORT 11
#define TE_EXPLOSION2 12
// PGM 01/21/97
#define TE_BEAM 13
// PGM 01/21/97
#ifdef QUAKE2
#define TE_IMPLOSION 14
#define TE_RAILTRAIL 15
#endif

View File

@@ -0,0 +1,423 @@
#ifndef _QUAKEDEF_H
#define _QUAKEDEF_H
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// quakedef.h -- primary header for client
//#define GLTEST // experimental stuff
//#define GP32_DEBUGGING 1
//#define USEFPM 1
//#if(GP32_DEBUGGING==0)
//#define _GpError(a,b)
//#else
//extern char gpstr[1024];
//#endif
#define USE_PQ_OPT1 //Uses the fixed point R_EmitEdge_fxp function.
#define USE_PQ_OPT2
//#define USE_PQ_OPT3 //In progress, don't use.
#define USE_PQ_OPT4 //Uses the fixed point D_PolysetCalcGradients function.
#define USE_PQ_OPT5 //Uses the fixed point D_DrawSpans8 (partially from Jacco Biker)
#define MIN_VID_HEIGHT 180
#define SDL 1
#define QUAKE_GAME // as opposed to utilities
#define GP2X_VERSION 1.02
#define VERSION 0.01
#define GLQUAKE_VERSION 1.00
#define D3DQUAKE_VERSION 0.01
#define WINQUAKE_VERSION 0.996
#define LINUX_VERSION 1.30
#define X11_VERSION 1.10
#define POCKETQUAKE_VERSION 0.062
// Yoda
#ifdef SHx
#define DISABLE_OPTIMIZATION optimize("g",off)
#define ENABLE_OPTIMIZATION optimize("g",on)
#else
#define DISABLE_OPTIMIZATION
#define ENABLE_OPTIMIZATION
#endif
typedef signed long long int __int64;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef unsigned int * PDWORD;
//define PARANOID // speed sapping error checking
#ifdef QUAKE2
#define GAMENAME "id1" // directory to look in by default
#else
#define GAMENAME "id1"
#endif
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <setjmp.h>
#include <assert.h>
#if defined(_WIN32) && !defined(WINDED)
#if defined(_M_IX86)
#define __i386__ 1
#endif
void VID_LockBuffer (void);
void VID_UnlockBuffer (void);
#else
#define VID_LockBuffer()
#define VID_UnlockBuffer()
#endif
//#if defined __i386__ // && !defined __sun__
//#define id386 1
//#else
#define id386 0
//#endif
#if id386
#define UNALIGNED_OK 1 // set to 0 if unaligned accesses are not supported
#else
#define UNALIGNED_OK 0
#endif
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define CACHE_SIZE 32 // used to align key data structures
#define UNUSED(x) (x = x) // for pesky compiler / lint warnings
#define MINIMUM_MEMORY 0x550000
#define MINIMUM_MEMORY_LEVELPAK (MINIMUM_MEMORY + 0x100000)
#define MAX_NUM_ARGVS 50
// up / down
#define PITCH 0
// left / right
#define YAW 1
// fall over
#define ROLL 2
#define MAX_QPATH 128 // max length of a quake game pathname
#define MAX_OSPATH 512 // max length of a filesystem pathname
#define ON_EPSILON 0.1 // point on plane side epsilon
#define MAX_MSGLEN 8000 // max length of a reliable message
#define MAX_DATAGRAM 1024 // max length of unreliable message
//
// per-level limits
//
#define MAX_EDICTS 600 // FIXME: ouch! ouch! ouch!
#define MAX_LIGHTSTYLES 64
#define MAX_MODELS 256 // these are sent over the net as bytes
#define MAX_SOUNDS 256 // so they cannot be blindly increased
#define SAVEGAME_COMMENT_LENGTH 39
#define MAX_STYLESTRING 64
//
// stats are integers communicated to the client by the server
//
#define MAX_CL_STATS 32
#define STAT_HEALTH 0
#define STAT_FRAGS 1
#define STAT_WEAPON 2
#define STAT_AMMO 3
#define STAT_ARMOR 4
#define STAT_WEAPONFRAME 5
#define STAT_SHELLS 6
#define STAT_NAILS 7
#define STAT_ROCKETS 8
#define STAT_CELLS 9
#define STAT_ACTIVEWEAPON 10
#define STAT_TOTALSECRETS 11
#define STAT_TOTALMONSTERS 12
#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret
#define STAT_MONSTERS 14 // bumped by svc_killedmonster
// stock defines
#define IT_SHOTGUN 1
#define IT_SUPER_SHOTGUN 2
#define IT_NAILGUN 4
#define IT_SUPER_NAILGUN 8
#define IT_GRENADE_LAUNCHER 16
#define IT_ROCKET_LAUNCHER 32
#define IT_LIGHTNING 64
#define IT_SUPER_LIGHTNING 128
#define IT_SHELLS 256
#define IT_NAILS 512
#define IT_ROCKETS 1024
#define IT_CELLS 2048
#define IT_AXE 4096
#define IT_ARMOR1 8192
#define IT_ARMOR2 16384
#define IT_ARMOR3 32768
#define IT_SUPERHEALTH 65536
#define IT_KEY1 131072
#define IT_KEY2 262144
#define IT_INVISIBILITY 524288
#define IT_INVULNERABILITY 1048576
#define IT_SUIT 2097152
#define IT_QUAD 4194304
#define IT_SIGIL1 (1<<28)
#define IT_SIGIL2 (1<<29)
#define IT_SIGIL3 (1<<30)
#define IT_SIGIL4 (1<<31)
//===========================================
//rogue changed and added defines
#define RIT_SHELLS 128
#define RIT_NAILS 256
#define RIT_ROCKETS 512
#define RIT_CELLS 1024
#define RIT_AXE 2048
#define RIT_LAVA_NAILGUN 4096
#define RIT_LAVA_SUPER_NAILGUN 8192
#define RIT_MULTI_GRENADE 16384
#define RIT_MULTI_ROCKET 32768
#define RIT_PLASMA_GUN 65536
#define RIT_ARMOR1 8388608
#define RIT_ARMOR2 16777216
#define RIT_ARMOR3 33554432
#define RIT_LAVA_NAILS 67108864
#define RIT_PLASMA_AMMO 134217728
#define RIT_MULTI_ROCKETS 268435456
#define RIT_SHIELD 536870912
#define RIT_ANTIGRAV 1073741824
#define RIT_SUPERHEALTH 2147483648
//MED 01/04/97 added hipnotic defines
//===========================================
//hipnotic added defines
#define HIT_PROXIMITY_GUN_BIT 16
#define HIT_MJOLNIR_BIT 7
#define HIT_LASER_CANNON_BIT 23
#define HIT_PROXIMITY_GUN (1<<HIT_PROXIMITY_GUN_BIT)
#define HIT_MJOLNIR (1<<HIT_MJOLNIR_BIT)
#define HIT_LASER_CANNON (1<<HIT_LASER_CANNON_BIT)
#define HIT_WETSUIT (1<<(23+2))
#define HIT_EMPATHY_SHIELDS (1<<(23+3))
//===========================================
#define MAX_SCOREBOARD 16
#define MAX_SCOREBOARDNAME 32
#define SOUND_CHANNELS 8
// This makes anyone on id's net privileged
// Use for multiplayer testing only - VERY dangerous!!!
// #define IDGODS
//Dan East:
//#include "FixedPointMath.h"
#include "common.h"
#include "bspfile.h"
#include "vid.h"
#include "sys.h"
#include "zone.h"
#include "mathlib.h"
typedef struct
{
vec3_t origin;
vec3_t angles;
int modelindex;
int frame;
int colormap;
int skin;
int effects;
} entity_state_t;
typedef struct
{
vec3_FPM_t origin;
vec3_FPM_t angles;
int modelindex;
int frame;
int colormap;
int skin;
int effects;
} entity_state_FPM_t;
#include "wad.h"
#include "draw.h"
#include "cvar.h"
#include "screen.h"
#include "net.h"
#include "protocol.h"
#include "cmd.h"
#include "sbar.h"
#include "sound.h"
#include "render.h"
#include "client.h"
#include "progs.h"
#include "server.h"
//#ifdef GLQUAKE
//#include "gl_model.h"
//#else
#include "model.h"
#include "d_iface.h"
//#endif
#include "input.h"
#include "world.h"
#include "keys.h"
#include "console.h"
#include "view.h"
#include "menu.h"
#include "crc.h"
#include "cdaudio.h"
//#ifdef GLQUAKE
//#include "glquake.h"
//#endif
#include "cpu.h"
#include "slist.h"
int command_kayboard;
int r2_cpu;
int r2_mod;
extern qboolean mouse_avail;
extern float mouse_x, mouse_y;
extern int mouse_oldbuttonstate;
//=============================================================================
// the host system specifies the base of the directory tree, the
// command line parms passed to the program, and the amount of memory
// available for the program to use
typedef struct
{
char *basedir;
char *cachedir; // for development over ISDN lines
int argc;
char **argv;
void *membase;
int memsize;
} quakeparms_t;
//=============================================================================
extern qboolean noclip_anglehack;
//
// host
//
extern quakeparms_t host_parms;
extern cvar_t sys_ticrate;
extern cvar_t sys_nostdout;
extern cvar_t developer;
extern qboolean host_initialized; // true if into command execution
extern double host_frametime;
extern byte *host_basepal;
extern byte *host_colormap;
extern int host_framecount; // incremented every frame, never reset
extern double realtime; // not bounded in any way, changed at
// start of every frame, never reset
/*
extern finalvert_t *finalverts;
extern auxvert_t *auxverts;
extern spanpackage_t *spans;
extern edge_t *ledges;
extern surf_t *lsurfs;
extern byte *basespans;
*/
void Host_ClearMemory (void);
void Host_ClearMemoryFPM (void);
void Host_ServerFrame (void);
void Host_InitCommands (void);
void Host_InitCommandsFPM (void);
void Host_Init (quakeparms_t *parms);
void Host_Shutdown(void);
void Host_Error (char *error, ...);
void Host_EndGame (char *message, ...);
void Host_Frame (float time);
void Host_Quit_f (void);
void Host_ClientCommands (char *fmt, ...);
void Host_ClientCommandsFPM (char *fmt, ...);
void Host_ShutdownServer (qboolean crash);
void Host_ShutdownServerFPM (qboolean crash);
extern qboolean msg_suppress_1; // suppresses resolution and cache size console output
// an fullscreen DIB focus gain/loss
extern int current_skill; // skill level for currently loaded level (in case
// the user changes the cvar while the level is
// running, this reflects the level actually in use)
extern qboolean isDedicated;
extern int minimum_memory;
//
// chase
//
extern cvar_t chase_active;
void Chase_Init (void);
void Chase_Reset (void);
void Chase_Update (void);
void Chase_UpdateFPM (void);
#endif

View File

@@ -0,0 +1,651 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_aclip.c: clip routines for drawing Alias models directly to the screen
#include "quakedef.h"
#include "r_local.h"
#include "d_local.h"
static finalvert_t fv[2][8];
static auxvert_t av[8];
#ifdef USEFPM
static auxvert_FPM_t *avFPM[8];
#endif //USEFPM
void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
#ifdef USEFPM
void R_AliasProjectFinalVertFPM (finalvert_t *fv, auxvert_FPM_t *av);
#endif //USEFPM
void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
/*
================
R_Alias_clip_z
pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
================
*/
void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
auxvert_t *pav0, *pav1, avout;
pav0 = &av[pfv0 - &fv[0][0]];
pav1 = &av[pfv1 - &fv[0][0]];
if (pfv0->v[1] >= pfv1->v[1])
{
scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) /
(pav1->fv[2] - pav0->fv[2]);
avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale;
avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale;
avout.fv[2] = ALIAS_Z_CLIP_PLANE;
out->v[2] = pfv0->v[2] + (int)((pfv1->v[2] - pfv0->v[2]) * scale);
out->v[3] = pfv0->v[3] + (int)((pfv1->v[3] - pfv0->v[3]) * scale);
out->v[4] = pfv0->v[4] + (int)((pfv1->v[4] - pfv0->v[4]) * scale);
}
else
{
scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) /
(pav0->fv[2] - pav1->fv[2]);
avout.fv[0] = pav1->fv[0] + (int)((pav0->fv[0] - pav1->fv[0]) * scale);
avout.fv[1] = pav1->fv[1] + (int)((pav0->fv[1] - pav1->fv[1]) * scale);
avout.fv[2] = ALIAS_Z_CLIP_PLANE;
out->v[2] = pfv1->v[2] + (int)((pfv0->v[2] - pfv1->v[2]) * scale);
out->v[3] = pfv1->v[3] + (int)((pfv0->v[3] - pfv1->v[3]) * scale);
out->v[4] = pfv1->v[4] + (int)((pfv0->v[4] - pfv1->v[4]) * scale);
}
R_AliasProjectFinalVert (out, &avout);
if (out->v[0] < r_refdef.aliasvrect.x)
out->flags |= ALIAS_LEFT_CLIP;
if (out->v[1] < r_refdef.aliasvrect.y)
out->flags |= ALIAS_TOP_CLIP;
if (out->v[0] > r_refdef.aliasvrectright)
out->flags |= ALIAS_RIGHT_CLIP;
if (out->v[1] > r_refdef.aliasvrectbottom)
out->flags |= ALIAS_BOTTOM_CLIP;
}
#ifdef USEFPM
void R_Alias_clip_z_FPM (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
fixedpoint_t scale;
auxvert_FPM_t *pav0, *pav1, avout;
pav0 = avFPM[pfv0 - &fv[0][0]];
pav1 = avFPM[pfv1 - &fv[0][0]];
if (pfv0->v[1] >= pfv1->v[1])
{
scale = FPM_DIV(FPM_SUB(ALIAS_Z_CLIP_PLANE_FPM, pav0->fv[2]),
FPM_SUB(pav1->fv[2], pav0->fv[2]));
avout.fv[0] = FPM_TOLONG(FPM_ADD(pav0->fv[0], FPM_MUL(FPM_SUB(pav1->fv[0], pav0->fv[0]),scale)));
avout.fv[1] = FPM_TOLONG(FPM_ADD(pav0->fv[1], FPM_MUL(FPM_SUB(pav1->fv[1], pav0->fv[1]), scale)));
avout.fv[2] = ALIAS_Z_CLIP_PLANE;
out->v[2] = pfv0->v[2] + FPM_TOLONG(FPM_MUL(FPM_FROMLONG(pfv1->v[2] - pfv0->v[2]), scale));
out->v[3] = pfv0->v[3] + FPM_TOLONG(FPM_MUL(FPM_FROMLONG(pfv1->v[3] - pfv0->v[3]), scale));
out->v[4] = pfv0->v[4] + FPM_TOLONG(FPM_MUL(FPM_FROMLONG(pfv1->v[4] - pfv0->v[4]), scale));
}
else
{
scale = FPM_DIV(FPM_SUB(ALIAS_Z_CLIP_PLANE_FPM, pav1->fv[2]),
FPM_SUB(pav0->fv[2], pav1->fv[2]));
avout.fv[0] = FPM_TOLONG(FPM_ADD(pav1->fv[0], FPM_MUL(FPM_SUB(pav0->fv[0], pav1->fv[0]),scale)));
avout.fv[1] = FPM_TOLONG(FPM_ADD(pav1->fv[1], FPM_MUL(FPM_SUB(pav0->fv[1], pav1->fv[1]), scale)));
avout.fv[2] = ALIAS_Z_CLIP_PLANE;
out->v[2] = pfv1->v[2] + FPM_TOLONG(FPM_MUL(FPM_FROMLONG((pfv0->v[2] - pfv1->v[2])), scale));
out->v[3] = pfv1->v[3] + FPM_TOLONG(FPM_MUL(FPM_FROMLONG(pfv0->v[3] - pfv1->v[3]), scale));
out->v[4] = pfv1->v[4] + FPM_TOLONG(FPM_MUL(FPM_FROMLONG(pfv0->v[4] - pfv1->v[4]), scale));
}
R_AliasProjectFinalVertFPM (out, &avout);
if (out->v[0] < r_refdefFPM.aliasvrect.x)
out->flags |= ALIAS_LEFT_CLIP;
if (out->v[1] < r_refdefFPM.aliasvrect.y)
out->flags |= ALIAS_TOP_CLIP;
if (out->v[0] > r_refdefFPM.aliasvrectright)
out->flags |= ALIAS_RIGHT_CLIP;
if (out->v[1] > r_refdefFPM.aliasvrectbottom)
out->flags |= ALIAS_BOTTOM_CLIP;
}
#endif //USEFPM
#if !id386
void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
int i;
if (pfv0->v[1] >= pfv1->v[1])
{
scale = (float)(r_refdef.aliasvrect.x - pfv0->v[0]) /
(pfv1->v[0] - pfv0->v[0]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv0->v[i] + (int)((pfv1->v[i] - pfv0->v[i])*scale + 0.5);
}
else
{
scale = (float)(r_refdef.aliasvrect.x - pfv1->v[0]) /
(pfv0->v[0] - pfv1->v[0]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv1->v[i] + (int)((pfv0->v[i] - pfv1->v[i])*scale + 0.5);
}
}
#ifdef USEFPM
void R_Alias_clip_leftFPM (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
fixedpoint_t scale;
int i;
if (pfv0->v[1] >= pfv1->v[1])
{
scale = FPM_DIV(FPM_FROMLONG(r_refdef.aliasvrect.x - pfv0->v[0]),
FPM_FROMLONG(pfv1->v[0] - pfv0->v[0]));
for (i=0 ; i<6 ; i++)
out->v[i] = FPM_ADD3(FPM_FROMLONG(pfv0->v[i]), FPM_MUL(FPM_FROMLONG(pfv1->v[i] - pfv0->v[i]),scale), FPM_FROMFLOAT(0.5));
}
else
{
scale = FPM_DIV(FPM_FROMLONG(r_refdef.aliasvrect.x - pfv1->v[0]),
FPM_FROMLONG(pfv0->v[0] - pfv1->v[0]));
for (i=0 ; i<6 ; i++)
out->v[i] = FPM_ADD3(FPM_FROMLONG(pfv1->v[i]), FPM_MUL(FPM_FROMLONG(pfv0->v[i] - pfv1->v[i]),scale), FPM_FROMFLOAT(0.5));
}
}
#endif //USEFPM
void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out)
{
float scale;
int i;
if (pfv0->v[1] >= pfv1->v[1])
{
scale = (float)(r_refdef.aliasvrectright - pfv0->v[0]) /
(pfv1->v[0] - pfv0->v[0]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv0->v[i] + (int)((pfv1->v[i] - pfv0->v[i])*scale + 0.5);
}
else
{
scale = (float)(r_refdef.aliasvrectright - pfv1->v[0]) /
(pfv0->v[0] - pfv1->v[0]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv1->v[i] + (int)((pfv0->v[i] - pfv1->v[i])*scale + 0.5);
}
}
#ifdef USEFPM
void R_Alias_clip_rightFPM (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out)
{
fixedpoint_t scale;
int i;
if (pfv0->v[1] >= pfv1->v[1])
{
scale = FPM_DIV(FPM_FROMLONG(r_refdefFPM.aliasvrectright - pfv0->v[0]),
FPM_FROMLONG(pfv1->v[0] - pfv0->v[0]));
for (i=0 ; i<6 ; i++)
out->v[i] = pfv0->v[i] + FPM_TOLONG(FPM_ADD(FPM_MUL(FPM_FROMLONG(pfv1->v[i] - pfv0->v[i]),scale), FPM_FROMFLOAT(0.5)));
}
else
{
scale = FPM_DIV(FPM_FROMLONG(r_refdefFPM.aliasvrectright - pfv1->v[0]),
FPM_FROMLONG(pfv0->v[0] - pfv1->v[0]));
for (i=0 ; i<6 ; i++)
out->v[i] = pfv1->v[i] + FPM_TOLONG(FPM_ADD(FPM_MUL(FPM_FROMLONG(pfv0->v[i] - pfv1->v[i]),scale), FPM_FROMFLOAT(0.5)));
}
}
#endif //USEFPM
void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
int i;
if (pfv0->v[1] >= pfv1->v[1])
{
scale = (float)(r_refdef.aliasvrect.y - pfv0->v[1]) /
(pfv1->v[1] - pfv0->v[1]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv0->v[i] + (int)((pfv1->v[i] - pfv0->v[i])*scale + 0.5);
}
else
{
scale = (float)(r_refdef.aliasvrect.y - pfv1->v[1]) /
(pfv0->v[1] - pfv1->v[1]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv1->v[i] + (int)((pfv0->v[i] - pfv1->v[i])*scale + 0.5);
}
}
#ifdef USEFPM
void R_Alias_clip_topFPM (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
fixedpoint_t scale;
int i;
if (pfv0->v[1] >= pfv1->v[1])
{
scale = FPM_DIV(FPM_FROMLONG(r_refdefFPM.aliasvrect.y - pfv0->v[1]),
FPM_FROMLONG(pfv1->v[1] - pfv0->v[1]));
for (i=0 ; i<6 ; i++)
out->v[i] = pfv0->v[i] + FPM_TOLONG(FPM_ADD(FPM_MUL(FPM_FROMLONG(pfv1->v[i] - pfv0->v[i]),scale), FPM_FROMFLOAT(0.5)));
}
else
{
scale = FPM_DIV(FPM_FROMLONG(r_refdefFPM.aliasvrect.y - pfv1->v[1]),
FPM_FROMLONG(pfv0->v[1] - pfv1->v[1]));
for (i=0 ; i<6 ; i++)
out->v[i] = pfv1->v[i] + FPM_TOLONG(FPM_ADD(FPM_MUL(FPM_FROMLONG(pfv0->v[i] - pfv1->v[i]),scale), FPM_FROMFLOAT(0.5)));
}
}
#endif //USEFPM
void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out)
{
float scale;
int i;
if (pfv0->v[1] >= pfv1->v[1])
{
scale = (float)(r_refdef.aliasvrectbottom - pfv0->v[1]) /
(pfv1->v[1] - pfv0->v[1]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv0->v[i] + (int)((pfv1->v[i] - pfv0->v[i])*scale + 0.5);
}
else
{
scale = (float)(r_refdef.aliasvrectbottom - pfv1->v[1]) /
(pfv0->v[1] - pfv1->v[1]);
for (i=0 ; i<6 ; i++)
out->v[i] = pfv1->v[i] + (int)((pfv0->v[i] - pfv1->v[i])*scale + 0.5);
}
}
#ifdef USEFPM
void R_Alias_clip_bottomFPM (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out)
{
fixedpoint_t scale;
int i;
if (pfv0->v[1] >= pfv1->v[1])
{
scale = FPM_DIV(FPM_FROMLONG(r_refdefFPM.aliasvrectbottom - pfv0->v[1]),
FPM_FROMLONG(pfv1->v[1] - pfv0->v[1]));
for (i=0 ; i<6 ; i++)
out->v[i] = pfv0->v[i] + FPM_TOLONG(FPM_ADD(FPM_MUL(FPM_FROMLONG(pfv1->v[i] - pfv0->v[i]),scale), FPM_FROMFLOAT(0.5)));
}
else
{
scale = FPM_DIV(FPM_FROMLONG(r_refdefFPM.aliasvrectbottom - pfv1->v[1]),
FPM_FROMLONG(pfv0->v[1] - pfv1->v[1]));
for (i=0 ; i<6 ; i++)
out->v[i] = pfv1->v[i] + FPM_TOLONG(FPM_ADD(FPM_MUL(FPM_FROMLONG(pfv0->v[i] - pfv1->v[i]),scale), FPM_FROMFLOAT(0.5)));
}
}
#endif //USEFPM
#endif
int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count,
void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) )
{
int i,j,k;
int flags, oldflags;
j = count-1;
k = 0;
for (i=0 ; i<count ; j = i, i++)
{
oldflags = in[j].flags & flag;
flags = in[i].flags & flag;
if (flags && oldflags)
continue;
if (oldflags ^ flags)
{
clip (&in[j], &in[i], &out[k]);
out[k].flags = 0;
if (out[k].v[0] < r_refdef.aliasvrect.x)
out[k].flags |= ALIAS_LEFT_CLIP;
if (out[k].v[1] < r_refdef.aliasvrect.y)
out[k].flags |= ALIAS_TOP_CLIP;
if (out[k].v[0] > r_refdef.aliasvrectright)
out[k].flags |= ALIAS_RIGHT_CLIP;
if (out[k].v[1] > r_refdef.aliasvrectbottom)
out[k].flags |= ALIAS_BOTTOM_CLIP;
k++;
}
if (!flags)
{
out[k] = in[i];
k++;
}
}
return k;
}
#ifdef USEFPM
int R_AliasClipFPM (finalvert_t *in, finalvert_t *out, int flag, int count,
void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) )
{
int i,j,k;
int flags, oldflags;
j = count-1;
k = 0;
for (i=0 ; i<count ; j = i, i++)
{
oldflags = in[j].flags & flag;
flags = in[i].flags & flag;
if (flags && oldflags)
continue;
if (oldflags ^ flags)
{
clip (&in[j], &in[i], &out[k]);
out[k].flags = 0;
if (out[k].v[0] < r_refdefFPM.aliasvrect.x)
out[k].flags |= ALIAS_LEFT_CLIP;
if (out[k].v[1] < r_refdefFPM.aliasvrect.y)
out[k].flags |= ALIAS_TOP_CLIP;
if (out[k].v[0] > r_refdefFPM.aliasvrectright)
out[k].flags |= ALIAS_RIGHT_CLIP;
if (out[k].v[1] > r_refdefFPM.aliasvrectbottom)
out[k].flags |= ALIAS_BOTTOM_CLIP;
k++;
}
if (!flags)
{
out[k] = in[i];
k++;
}
}
return k;
}
#endif //USEFPM
/*
================
R_AliasClipTriangle
================
*/
void R_AliasClipTriangle (mtriangle_t *ptri)
{
int i, k, pingpong;
mtriangle_t mtri;
unsigned clipflags;
// copy vertexes and fix seam texture coordinates
if (ptri->facesfront)
{
fv[0][0] = pfinalverts[ptri->vertindex[0]];
fv[0][1] = pfinalverts[ptri->vertindex[1]];
fv[0][2] = pfinalverts[ptri->vertindex[2]];
}
else
{
for (i=0 ; i<3 ; i++)
{
fv[0][i] = pfinalverts[ptri->vertindex[i]];
if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM) )
fv[0][i].v[2] += r_affinetridesc.seamfixupX16;
}
}
// clip
clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
if (clipflags & ALIAS_Z_CLIP)
{
for (i=0 ; i<3 ; i++)
av[i] = pauxverts[ptri->vertindex[i]];
k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z);
if (k == 0)
return;
pingpong = 1;
clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags;
}
else
{
pingpong = 0;
k = 3;
}
if (clipflags & ALIAS_LEFT_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_RIGHT_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_BOTTOM_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_TOP_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_TOP_CLIP, k, R_Alias_clip_top);
if (k == 0)
return;
pingpong ^= 1;
}
for (i=0 ; i<k ; i++)
{
if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x)
fv[pingpong][i].v[0] = r_refdef.aliasvrect.x;
else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright)
fv[pingpong][i].v[0] = r_refdef.aliasvrectright;
if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y)
fv[pingpong][i].v[1] = r_refdef.aliasvrect.y;
else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom)
fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom;
fv[pingpong][i].flags = 0;
}
// draw triangles
mtri.facesfront = ptri->facesfront;
r_affinetridesc.ptriangles = &mtri;
r_affinetridesc.pfinalverts = fv[pingpong];
// FIXME: do all at once as trifan?
mtri.vertindex[0] = 0;
for (i=1 ; i<k-1 ; i++)
{
mtri.vertindex[1] = i;
mtri.vertindex[2] = i+1;
D_PolysetDraw ();
}
}
#ifdef USEFPM
void R_AliasClipTriangleFPM(mtriangle_t *ptri)
{
int i, k, pingpong;
mtriangle_t mtri;
unsigned clipflags;
// copy vertexes and fix seam texture coordinates
if (ptri->facesfront)
{
fv[0][0] = pfinalverts[ptri->vertindex[0]];
fv[0][1] = pfinalverts[ptri->vertindex[1]];
fv[0][2] = pfinalverts[ptri->vertindex[2]];
}
else
{
for (i=0 ; i<3 ; i++)
{
fv[0][i] = pfinalverts[ptri->vertindex[i]];
if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM) )
fv[0][i].v[2] += r_affinetridesc.seamfixupX16;
}
}
// clip
clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
if (clipflags & ALIAS_Z_CLIP)
{
for (i=0 ; i<3 ; i++)
avFPM[i] = &pauxvertsFPM[ptri->vertindex[i]];
k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z_FPM);
if (k == 0)
return;
pingpong = 1;
clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags;
}
else
{
pingpong = 0;
k = 3;
}
if (clipflags & ALIAS_LEFT_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_RIGHT_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_BOTTOM_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_TOP_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_TOP_CLIP, k, R_Alias_clip_top);
if (k == 0)
return;
pingpong ^= 1;
}
for (i=0 ; i<k ; i++)
{
if (fv[pingpong][i].v[0] < r_refdefFPM.aliasvrect.x)
fv[pingpong][i].v[0] = r_refdefFPM.aliasvrect.x;
else if (fv[pingpong][i].v[0] > r_refdefFPM.aliasvrectright)
fv[pingpong][i].v[0] = r_refdefFPM.aliasvrectright;
if (fv[pingpong][i].v[1] < r_refdefFPM.aliasvrect.y)
fv[pingpong][i].v[1] = r_refdefFPM.aliasvrect.y;
else if (fv[pingpong][i].v[1] > r_refdefFPM.aliasvrectbottom)
fv[pingpong][i].v[1] = r_refdefFPM.aliasvrectbottom;
fv[pingpong][i].flags = 0;
}
// draw triangles
mtri.facesfront = ptri->facesfront;
r_affinetridesc.ptriangles = &mtri;
r_affinetridesc.pfinalverts = fv[pingpong];
// FIXME: do all at once as trifan?
mtri.vertindex[0] = 0;
for (i=1 ; i<k-1 ; i++)
{
mtri.vertindex[1] = i;
mtri.vertindex[2] = i+1;
D_PolysetDraw ();
}
}
#endif //USEFPM

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,837 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_bsp.c
#include "quakedef.h"
#include "r_local.h"
#ifdef DEBUG
#include "../LogFloat.h"
#endif
//
// current entity info
//
qboolean insubmodel;
entity_t *currententity;
vec3_t modelorg, base_modelorg;
#ifdef USE_PQ_OPT1
int modelorg_fxp[3];
#endif
// modelorg is the viewpoint reletive to
// the currently rendering entity
vec3_t r_entorigin; // the currently rendering entity in world
// coordinates
float entity_rotation[3][3];
vec3_t r_worldmodelorg;
int r_currentbkey;
typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t;
#define MAX_BMODEL_VERTS 500 // 6K
#define MAX_BMODEL_EDGES 1000 // 12K
static mvertex_t *pbverts;
static bedge_t *pbedges;
static int numbverts, numbedges;
static mvertex_t *pfrontenter, *pfrontexit;
static qboolean makeclippededge;
#ifdef USEFPM
entity_FPM_t *currententityFPM;
vec3_FPM_t modelorgFPM, base_modelorgFPM;
vec3_FPM_t r_entoriginFPM;
fixedpoint_t entity_rotationFPM[3][3];
vec3_FPM_t r_worldmodelorgFPM;
static mvertex_FPM_t *pbvertsFPM;
static bedge_FPM_t *pbedgesFPM;
static mvertex_FPM_t *pfrontenterFPM, *pfrontexitFPM;
#endif //USEFPM
//===========================================================================
/*
================
R_EntityRotate
================
*/
void R_EntityRotate (vec3_t vec)
{
vec3_t tvec;
VectorCopy (vec, tvec);
vec[0] = DotProduct (entity_rotation[0], tvec);
vec[1] = DotProduct (entity_rotation[1], tvec);
vec[2] = DotProduct (entity_rotation[2], tvec);
}
/*
================
R_RotateBmodel
================
*/
void R_RotateBmodel (void)
{
float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
// TODO: should use a look-up table
// TODO: should really be stored with the entity instead of being reconstructed
// TODO: could cache lazily, stored in the entity
// TODO: share work with R_SetUpAliasTransform
// yaw
angle = currententity->angles[YAW];
angle = angle * (float) M_PI*2 / 360;
s = (float)sin(angle);
c = (float)cos(angle);
temp1[0][0] = c;
temp1[0][1] = s;
temp1[0][2] = 0;
temp1[1][0] = -s;
temp1[1][1] = c;
temp1[1][2] = 0;
temp1[2][0] = 0;
temp1[2][1] = 0;
temp1[2][2] = 1;
// pitch
angle = currententity->angles[PITCH];
angle = angle * (float)M_PI*2 / 360;
s = (float)sin(angle);
c = (float)cos(angle);
temp2[0][0] = c;
temp2[0][1] = 0;
temp2[0][2] = -s;
temp2[1][0] = 0;
temp2[1][1] = 1;
temp2[1][2] = 0;
temp2[2][0] = s;
temp2[2][1] = 0;
temp2[2][2] = c;
R_ConcatRotations (temp2, temp1, temp3);
// roll
angle = currententity->angles[ROLL];
angle = angle * (float)M_PI*2 / 360;
s = (float)sin(angle);
c = (float)cos(angle);
temp1[0][0] = 1;
temp1[0][1] = 0;
temp1[0][2] = 0;
temp1[1][0] = 0;
temp1[1][1] = c;
temp1[1][2] = s;
temp1[2][0] = 0;
temp1[2][1] = -s;
temp1[2][2] = c;
R_ConcatRotations (temp1, temp3, entity_rotation);
//
// rotate modelorg and the transformation matrix
//
R_EntityRotate (modelorg);
R_EntityRotate (vpn);
R_EntityRotate (vright);
R_EntityRotate (vup);
R_TransformFrustum ();
}
/*
================
R_RecursiveClipBPoly
================
*/
void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf)
{
bedge_t *psideedges[2], *pnextedge, *ptedge;
int i, side, lastside;
float dist, frac, lastdist;
mplane_t *splitplane, tplane;
mvertex_t *pvert, *plastvert, *ptvert;
mnode_t *pn;
psideedges[0] = psideedges[1] = NULL;
makeclippededge = false;
// transform the BSP plane into model space
// FIXME: cache these?
splitplane = pnode->plane;
tplane.dist = splitplane->dist -
DotProduct(r_entorigin, splitplane->normal);
tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal);
tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal);
tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal);
// clip edges to BSP plane
for ( ; pedges ; pedges = pnextedge)
{
pnextedge = pedges->pnext;
// set the status for the last point as the previous point
// FIXME: cache this stuff somehow?
plastvert = pedges->v[0];
lastdist = DotProduct (plastvert->position, tplane.normal) -
tplane.dist;
if (lastdist > 0)
lastside = 0;
else
lastside = 1;
pvert = pedges->v[1];
dist = DotProduct (pvert->position, tplane.normal) - tplane.dist;
if (dist > 0)
side = 0;
else
side = 1;
if (side != lastside)
{
// clipped
if (numbverts >= MAX_BMODEL_VERTS)
return;
// generate the clipped vertex
frac = lastdist / (lastdist - dist);
ptvert = &pbverts[numbverts++];
ptvert->position[0] = plastvert->position[0] +
frac * (pvert->position[0] -
plastvert->position[0]);
ptvert->position[1] = plastvert->position[1] +
frac * (pvert->position[1] -
plastvert->position[1]);
ptvert->position[2] = plastvert->position[2] +
frac * (pvert->position[2] -
plastvert->position[2]);
// split into two edges, one on each side, and remember entering
// and exiting points
// FIXME: share the clip edge by having a winding direction flag?
if (numbedges >= (MAX_BMODEL_EDGES - 1))
{
Con_Printf ("Out of edges for bmodel\n");
return;
}
ptedge = &pbedges[numbedges];
ptedge->pnext = psideedges[lastside];
psideedges[lastside] = ptedge;
ptedge->v[0] = plastvert;
ptedge->v[1] = ptvert;
ptedge = &pbedges[numbedges + 1];
ptedge->pnext = psideedges[side];
psideedges[side] = ptedge;
ptedge->v[0] = ptvert;
ptedge->v[1] = pvert;
numbedges += 2;
if (side == 0)
{
// entering for front, exiting for back
pfrontenter = ptvert;
makeclippededge = true;
}
else
{
pfrontexit = ptvert;
makeclippededge = true;
}
}
else
{
// add the edge to the appropriate side
pedges->pnext = psideedges[side];
psideedges[side] = pedges;
}
}
// if anything was clipped, reconstitute and add the edges along the clip
// plane to both sides (but in opposite directions)
if (makeclippededge)
{
if (numbedges >= (MAX_BMODEL_EDGES - 2))
{
Con_Printf ("Out of edges for bmodel\n");
return;
}
ptedge = &pbedges[numbedges];
ptedge->pnext = psideedges[0];
psideedges[0] = ptedge;
ptedge->v[0] = pfrontexit;
ptedge->v[1] = pfrontenter;
ptedge = &pbedges[numbedges + 1];
ptedge->pnext = psideedges[1];
psideedges[1] = ptedge;
ptedge->v[0] = pfrontenter;
ptedge->v[1] = pfrontexit;
numbedges += 2;
}
// draw or recurse further
for (i=0 ; i<2 ; i++)
{
if (psideedges[i])
{
// draw if we've reached a non-solid leaf, done if all that's left is a
// solid leaf, and continue down the tree if it's not a leaf
pn = pnode->children[i];
// we're done with this branch if the node or leaf isn't in the PVS
if (pn->visframe == r_visframecount)
{
if (pn->contents < 0)
{
if (pn->contents != CONTENTS_SOLID)
{
r_currentbkey = ((mleaf_t *)pn)->key;
R_RenderBmodelFace (psideedges[i], psurf);
}
}
else
{
R_RecursiveClipBPoly (psideedges[i], pnode->children[i],
psurf);
}
}
}
}
}
/*
================
R_DrawSolidClippedSubmodelPolygons
================
*/
void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel)
{
int i, j, lindex;
vec_t dot;
msurface_t *psurf;
int numsurfaces;
mplane_t *pplane;
mvertex_t bverts[MAX_BMODEL_VERTS];
bedge_t bedges[MAX_BMODEL_EDGES], *pbedge;
medge_t *pedge, *pedges;
// FIXME: use bounding-box-based frustum clipping info?
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
numsurfaces = pmodel->nummodelsurfaces;
pedges = pmodel->edges;
for (i=0 ; i<numsurfaces ; i++, psurf++)
{
// find which side of the node we are on
pplane = psurf->plane;
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
{
// FIXME: use bounding-box-based frustum clipping info?
// copy the edges to bedges, flipping if necessary so always
// clockwise winding
// FIXME: if edges and vertices get caches, these assignments must move
// outside the loop, and overflow checking must be done here
pbverts = bverts;
pbedges = bedges;
numbverts = numbedges = 0;
if (psurf->numedges > 0)
{
pbedge = &bedges[numbedges];
numbedges += psurf->numedges;
for (j=0 ; j<psurf->numedges ; j++)
{
lindex = pmodel->surfedges[psurf->firstedge+j];
if (lindex > 0)
{
pedge = &pedges[lindex];
pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]];
pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]];
}
else
{
lindex = -lindex;
pedge = &pedges[lindex];
pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]];
pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]];
}
pbedge[j].pnext = &pbedge[j+1];
}
pbedge[j-1].pnext = NULL; // mark end of edges
R_RecursiveClipBPoly (pbedge, currententity->topnode, psurf);
}
else
{
Sys_Error ("no edges in bmodel");
}
}
}
}
/*
================
R_DrawSubmodelPolygons
================
*/
void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags)
{
int i;
vec_t dot;
msurface_t *psurf;
int numsurfaces;
mplane_t *pplane;
// FIXME: use bounding-box-based frustum clipping info?
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
numsurfaces = pmodel->nummodelsurfaces;
for (i=0 ; i<numsurfaces ; i++, psurf++)
{
// find which side of the node we are on
pplane = psurf->plane;
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
{
r_currentkey = ((mleaf_t *)currententity->topnode)->key;
// FIXME: use bounding-box-based frustum clipping info?
R_RenderFace (psurf, clipflags);
}
}
}
#ifdef USEFPM
void R_DrawSubmodelPolygonsFPM (model_FPM_t *pmodel, int clipflags)
{
int i;
fixedpoint_t dot;
msurface_FPM_t *psurf;
int numsurfaces;
mplane_FPM_t *pplane;
// FIXME: use bounding-box-based frustum clipping info?
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
numsurfaces = pmodel->nummodelsurfaces;
for (i=0 ; i<numsurfaces ; i++, psurf++)
{
// find which side of the node we are on
pplane = psurf->plane;
dot = FPM_SUB(DotProductFPM (modelorgFPM, pplane->normal), pplane->dist);
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
{
r_currentkey = ((mleaf_FPM_t *)currententityFPM->topnode)->key;
// FIXME: use bounding-box-based frustum clipping info?
// R_RenderFaceFPM (psurf, clipflags); // FPM doesn't exist
R_RenderFace (psurf, clipflags);
}
}
}
#endif //USEFPM
void VerifyFrustumIndexes(char *s) {
int i, ii;
char buf[256];
for (i=0; i<4; i++)
if (pfrustum_indexes[i])
for (ii=0; ii<4; ii++)
if (pfrustum_indexes[i][ii]<0) {
sprintf(buf, "Bad Frustum: [%d][%d]=%d\n%s", i,ii,pfrustum_indexes[i][ii],s);
Sys_Error(buf);
}
}
#ifdef USE_PQ_OPT1
int clipplanes_fxp[4][3];
int clipdist_fxp[4];
#endif
/*
================
R_RecursiveWorldNode
================
*/
void R_RecursiveWorldNode (mnode_t *node, int clipflags)
{
int i, c, side, *pindex;
mplane_t *plane;
msurface_t *surf, **mark;
mleaf_t *pleaf;
double dot;
#ifdef USE_PQ_OPT1
int d_fxp;
#else
double d;
vec3_t acceptpt, rejectpt;
#endif
if (node->contents == CONTENTS_SOLID)
return; // solid
if (node->visframe != r_visframecount)
return;
// cull the clipping planes if not trivial accept
// FIXME: the compiler is doing a lousy job of optimizing here; it could be
// twice as fast in ASM
if (clipflags)
{
for (i=0 ; i<4 ; i++)
{
if (! (clipflags & (1<<i)) )
continue; // don't need to clip against it
// generate accept and reject points
// FIXME: do with fast look-ups or integer tests based on the sign bit
// of the floating point values
pindex = pfrustum_indexes[i];
#ifdef USE_PQ_OPT1
d_fxp=node->minmaxs[pindex[0]]*clipplanes_fxp[i][0]+node->minmaxs[pindex[1]]*clipplanes_fxp[i][1]+node->minmaxs[pindex[2]]*clipplanes_fxp[i][2];
d_fxp-=clipdist_fxp[i];
if (d_fxp <= 0)
return;
d_fxp=node->minmaxs[pindex[3]]*clipplanes_fxp[i][0]+node->minmaxs[pindex[4]]*clipplanes_fxp[i][1]+node->minmaxs[pindex[5]]*clipplanes_fxp[i][2];
d_fxp-=clipdist_fxp[i];
if (d_fxp >= 0)
clipflags &= ~(1<<i); // node is entirely on screen
#else
rejectpt[0] = (float)node->minmaxs[pindex[0]];
rejectpt[1] = (float)node->minmaxs[pindex[1]];
rejectpt[2] = (float)node->minmaxs[pindex[2]];
d = DotProduct (rejectpt, view_clipplanes[i].normal);
d -= view_clipplanes[i].dist;
if (d <= 0)
return;
acceptpt[0] = (float)node->minmaxs[pindex[3+0]];
acceptpt[1] = (float)node->minmaxs[pindex[3+1]];
acceptpt[2] = (float)node->minmaxs[pindex[3+2]];
d = DotProduct (acceptpt, view_clipplanes[i].normal);
d -= view_clipplanes[i].dist;
if (d >= 0)
clipflags &= ~(1<<i); // node is entirely on screen
#endif
}
}
// if a leaf node, draw stuff
if (node->contents < 0)
{
pleaf = (mleaf_t *)node;
mark = pleaf->firstmarksurface;
c = pleaf->nummarksurfaces;
if (c)
{
do
{
(*mark)->visframe = r_framecount;
mark++;
} while (--c);
}
// deal with model fragments in this leaf
if (pleaf->efrags)
{
R_StoreEfrags (&pleaf->efrags);
}
pleaf->key = r_currentkey;
r_currentkey++; // all bmodels in a leaf share the same key
}
else
{
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
plane = node->plane;
switch (plane->type)
{
case PLANE_X:
dot = modelorg[0] - plane->dist;
break;
case PLANE_Y:
dot = modelorg[1] - plane->dist;
break;
case PLANE_Z:
dot = modelorg[2] - plane->dist;
break;
default:
dot = DotProduct (modelorg, plane->normal) - plane->dist;
break;
}
if (dot >= 0)
side = 0;
else
side = 1;
// recurse down the children, front side first
R_RecursiveWorldNode (node->children[side], clipflags);
// draw stuff
c = node->numsurfaces;
if (c)
{
surf = cl.worldmodel->surfaces + node->firstsurface;
if (dot < -BACKFACE_EPSILON)
{
do
{
if ((surf->flags & SURF_PLANEBACK) &&
(surf->visframe == r_framecount))
{
if (r_drawpolys)
{
if (r_worldpolysbacktofront)
{
if (numbtofpolys < MAX_BTOFPOLYS)
{
pbtofpolys[numbtofpolys].clipflags =
clipflags;
pbtofpolys[numbtofpolys].psurf = surf;
numbtofpolys++;
}
}
else
{
R_RenderPoly (surf, clipflags);
}
}
else
{
R_RenderFace (surf, clipflags);
}
}
surf++;
} while (--c);
}
else if (dot > BACKFACE_EPSILON)
{
do
{
if (!(surf->flags & SURF_PLANEBACK) &&
(surf->visframe == r_framecount))
{
if (r_drawpolys)
{
if (r_worldpolysbacktofront)
{
if (numbtofpolys < MAX_BTOFPOLYS)
{
pbtofpolys[numbtofpolys].clipflags =
clipflags;
pbtofpolys[numbtofpolys].psurf = surf;
numbtofpolys++;
}
}
else
{
R_RenderPoly (surf, clipflags);
}
}
else
{
R_RenderFace (surf, clipflags);
}
}
surf++;
} while (--c);
}
// all surfaces on the same node share the same sequence number
r_currentkey++;
}
// recurse down the back side
R_RecursiveWorldNode (node->children[!side], clipflags);
}
}
/*
================
R_RenderWorld
================
*/
void R_RenderWorld (void)
{
int i;
model_t *clmodel;
btofpoly_t btofpolys[MAX_BTOFPOLYS];
GpError("A",8);
pbtofpolys = btofpolys;
currententity = &cl_entities[0];
VectorCopy (r_origin, modelorg);
#ifdef USE_PQ_OPT1
modelorg_fxp[0]=(int)(r_origin[0]*524288.0);
modelorg_fxp[1]=(int)(r_origin[1]*524288.0);
modelorg_fxp[2]=(int)(r_origin[2]*524288.0);
//modelorg_fxp[0]=(int)(r_origin[0]*65536.0);
//modelorg_fxp[1]=(int)(r_origin[1]*65536.0);
//modelorg_fxp[2]=(int)(r_origin[2]*65536.0);
vright_fxp[0]=(int)(256.0/vright[0]);
if (!vright_fxp[0]) vright_fxp[0]=0x7fffffff;
vright_fxp[1]=(int)(256.0/vright[1]);
if (!vright_fxp[1]) vright_fxp[1]=0x7fffffff;
vright_fxp[2]=(int)(256.0/vright[2]);
if (!vright_fxp[2]) vright_fxp[2]=0x7fffffff;
vpn_fxp[0]=(int)(256.0/vpn[0]);
if (!vpn_fxp[0]) vpn_fxp[0]=0x7fffffff;
vpn_fxp[1]=(int)(256.0/vpn[1]);
if (!vpn_fxp[1]) vpn_fxp[1]=0x7fffffff;
vpn_fxp[2]=(int)(256.0/vpn[2]);
if (!vpn_fxp[2]) vpn_fxp[2]=0x7fffffff;
vup_fxp[0]=(int)(256.0/vup[0]);
if (!vup_fxp[0]) vup_fxp[0]=0x7fffffff;
vup_fxp[1]=(int)(256.0/vup[1]);
if (!vup_fxp[1]) vup_fxp[1]=0x7fffffff;
vup_fxp[2]=(int)(256.0/vup[2]);
if (!vup_fxp[2]) vup_fxp[2]=0x7fffffff;
#endif
clmodel = currententity->model;
r_pcurrentvertbase = clmodel->vertexes;
#ifdef USE_PQ_OPT2
r_pcurrentvertbase_fxp = clmodel->vertexes_fxp;
#endif
#ifdef USE_PQ_OPT1
//Dan Fixed point conversion stuff
for (i=0; i<4; i++) {
clipplanes_fxp[i][0]=(int)(view_clipplanes[i].normal[0]*65536.0);
clipplanes_fxp[i][1]=(int)(view_clipplanes[i].normal[1]*65536.0);
clipplanes_fxp[i][2]=(int)(view_clipplanes[i].normal[2]*65536.0);
clipdist_fxp[i] =(int)(view_clipplanes[i].dist*65536.0);
#ifdef USE_PQ_OPT2
view_clipplanes_fxp[i].leftedge=view_clipplanes[i].leftedge;
view_clipplanes_fxp[i].rightedge=view_clipplanes[i].rightedge;
if (!view_clipplanes[i].normal[0]) view_clipplanes_fxp[i].normal[0]=2<<29;
else view_clipplanes_fxp[i].normal[0]=(int)(4096.0f/view_clipplanes[i].normal[0]);
if (!view_clipplanes[i].normal[0]) view_clipplanes_fxp[i].normal[0]=2<<29;
if (!view_clipplanes[i].normal[1]) view_clipplanes_fxp[i].normal[1]=2<<29;
else view_clipplanes_fxp[i].normal[1]=(int)(4096.0f/view_clipplanes[i].normal[1]);
if (!view_clipplanes[i].normal[1]) view_clipplanes_fxp[i].normal[1]=2<<29;
if (!view_clipplanes[i].normal[2]) view_clipplanes_fxp[i].normal[2]=2<<29;
else view_clipplanes_fxp[i].normal[2]=(int)(4096.0f/view_clipplanes[i].normal[2]);
if (!view_clipplanes[i].normal[2]) view_clipplanes_fxp[i].normal[2]=2<<29;
view_clipplanes_fxp[i].dist=(int)(view_clipplanes[i].dist*128.0f);
#endif
#if defined(_X86_)&&defined(DEBUG)
LogFloat(view_clipplanes[i].normal[0], "view_clipplanes[i].normal[0]", i, -1);
LogFloat(view_clipplanes[i].normal[1], "view_clipplanes[i].normal[1]", i, -1);
LogFloat(view_clipplanes[i].normal[2], "view_clipplanes[i].normal[2]", i, -1);
#endif
}
#endif
R_RecursiveWorldNode (clmodel->nodes, 15);
// if the driver wants the polygons back to front, play the visible ones back
// in that order
if (r_worldpolysbacktofront)
{
for (i=numbtofpolys-1 ; i>=0 ; i--)
{
R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,489 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_efrag.c
#include "quakedef.h"
#include "r_local.h"
mnode_t *r_pefragtopnode;
#ifdef USEFPM
mnode_FPM_t *r_pefragtopnodeFPM;
#endif //USEFPM
//===========================================================================
/*
===============================================================================
ENTITY FRAGMENT FUNCTIONS
===============================================================================
*/
efrag_t **lastlink;
vec3_t r_emins, r_emaxs;
entity_t *r_addent;
#ifdef USEFPM
efrag_FPM_t **lastlinkFPM;
vec3_FPM_t r_eminsFPM, r_emaxsFPM;
entity_FPM_t *r_addentFPM;
#endif //USEFPM
/*
================
R_RemoveEfrags
Call when removing an object from the world or moving it to another position
================
*/
void R_RemoveEfrags (entity_t *ent)
{
efrag_t *ef, *old, *walk, **prev;
ef = ent->efrag;
while (ef)
{
prev = &ef->leaf->efrags;
while (1)
{
walk = *prev;
if (!walk)
break;
if (walk == ef)
{ // remove this fragment
*prev = ef->leafnext;
break;
}
else
prev = &walk->leafnext;
}
old = ef;
ef = ef->entnext;
// put it on the free list
old->entnext = cl.free_efrags;
cl.free_efrags = old;
}
ent->efrag = NULL;
}
#ifdef USEFPM
void R_RemoveEfragsFPM (entity_FPM_t *ent)
{
efrag_FPM_t *ef, *old, *walk, **prev;
ef = ent->efrag;
while (ef)
{
prev = &ef->leaf->efrags;
while (1)
{
walk = *prev;
if (!walk)
break;
if (walk == ef)
{ // remove this fragment
*prev = ef->leafnext;
break;
}
else
prev = &walk->leafnext;
}
old = ef;
ef = ef->entnext;
// put it on the free list
old->entnext = clFPM.free_efrags;
clFPM.free_efrags = old;
}
ent->efrag = NULL;
}
#endif //USEFPM
/*
===================
R_SplitEntityOnNode
===================
*/
void R_SplitEntityOnNode (mnode_t *node)
{
efrag_t *ef;
mplane_t *splitplane;
mleaf_t *leaf;
int sides;
if (node->contents == CONTENTS_SOLID)
{
return;
}
// add an efrag if the node is a leaf
if ( node->contents < 0)
{
if (!r_pefragtopnode)
r_pefragtopnode = node;
leaf = (mleaf_t *)node;
// grab an efrag off the free list
ef = cl.free_efrags;
if (!ef)
{
Con_Printf ("Too many efrags!\n");
return; // no free fragments...
}
cl.free_efrags = cl.free_efrags->entnext;
ef->entity = r_addent;
// add the entity link
*lastlink = ef;
lastlink = &ef->entnext;
ef->entnext = NULL;
// set the leaf links
ef->leaf = leaf;
ef->leafnext = leaf->efrags;
leaf->efrags = ef;
return;
}
// NODE_MIXED
splitplane = node->plane;
sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
if (sides == 3)
{
// split on this plane
// if this is the first splitter of this bmodel, remember it
if (!r_pefragtopnode)
r_pefragtopnode = node;
}
// recurse down the contacted sides
if (sides & 1)
R_SplitEntityOnNode (node->children[0]);
if (sides & 2)
R_SplitEntityOnNode (node->children[1]);
}
#ifdef USEFPM
void R_SplitEntityOnNodeFPM (mnode_FPM_t *node)
{
efrag_FPM_t *ef;
mplane_FPM_t *splitplane;
mleaf_FPM_t *leaf;
int sides;
if (node->contents == CONTENTS_SOLID)
{
return;
}
// add an efrag if the node is a leaf
if ( node->contents < 0)
{
if (!r_pefragtopnodeFPM)
r_pefragtopnodeFPM = node;
leaf = (mleaf_FPM_t *)node;
// grab an efrag off the free list
ef = clFPM.free_efrags;
if (!ef)
{
Con_Printf ("Too many efrags!\n");
return; // no free fragments...
}
clFPM.free_efrags = clFPM.free_efrags->entnext;
ef->entity = r_addentFPM;
// add the entity link
*lastlinkFPM = ef;
lastlinkFPM = &ef->entnext;
ef->entnext = NULL;
// set the leaf links
ef->leaf = leaf;
ef->leafnext = leaf->efrags;
leaf->efrags = ef;
return;
}
// NODE_MIXED
splitplane = node->plane;
sides = BOX_ON_PLANE_SIDE_FPM(r_eminsFPM, r_emaxsFPM, splitplane);
if (sides == 3)
{
// split on this plane
// if this is the first splitter of this bmodel, remember it
if (!r_pefragtopnodeFPM)
r_pefragtopnodeFPM = node;
}
// recurse down the contacted sides
if (sides & 1)
R_SplitEntityOnNodeFPM (node->children[0]);
if (sides & 2)
R_SplitEntityOnNodeFPM (node->children[1]);
}
#endif //USEFPM
/*
===================
R_SplitEntityOnNode2
===================
*/
void R_SplitEntityOnNode2 (mnode_t *node)
{
mplane_t *splitplane;
int sides;
if (node->visframe != r_visframecount)
return;
if (node->contents < 0)
{
if (node->contents != CONTENTS_SOLID)
r_pefragtopnode = node; // we've reached a non-solid leaf, so it's
// visible and not BSP clipped
return;
}
splitplane = node->plane;
sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
if (sides == 3)
{
// remember first splitter
r_pefragtopnode = node;
return;
}
// not split yet; recurse down the contacted side
if (sides & 1)
R_SplitEntityOnNode2 (node->children[0]);
else
R_SplitEntityOnNode2 (node->children[1]);
}
#ifdef USEFPM
void R_SplitEntityOnNode2FPM (mnode_FPM_t *node)
{
mplane_FPM_t *splitplane;
int sides;
if (node->visframe != r_visframecount)
return;
if (node->contents < 0)
{
if (node->contents != CONTENTS_SOLID)
r_pefragtopnodeFPM = node; // we've reached a non-solid leaf, so it's
// visible and not BSP clipped
return;
}
splitplane = node->plane;
sides = BOX_ON_PLANE_SIDE_FPM(r_eminsFPM, r_emaxsFPM, splitplane);
if (sides == 3)
{
// remember first splitter
r_pefragtopnodeFPM = node;
return;
}
// not split yet; recurse down the contacted side
if (sides & 1)
R_SplitEntityOnNode2FPM (node->children[0]);
else
R_SplitEntityOnNode2FPM (node->children[1]);
}
#endif //USEFPM
/*
===========
R_AddEfrags
===========
*/
void R_AddEfrags (entity_t *ent)
{
model_t *entmodel;
int i;
if (!ent->model){
return;
}
if (ent == cl_entities){
return; // never add the world
}
r_addent = ent;
lastlink = &ent->efrag;
r_pefragtopnode = NULL;
entmodel = ent->model;
for (i=0 ; i<3 ; i++)
{
r_emins[i] = ent->origin[i] + entmodel->mins[i];
r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
}
R_SplitEntityOnNode (cl.worldmodel->nodes);
ent->topnode = r_pefragtopnode;
}
#ifdef USEFPM
void R_AddEfragsFPM (entity_FPM_t *ent)
{
model_FPM_t *entmodel;
int i;
if (!ent->model)
return;
if (ent == cl_entitiesFPM)
return; // never add the world
r_addentFPM = ent;
lastlinkFPM = &ent->efrag;
r_pefragtopnodeFPM = NULL;
entmodel = ent->model;
for (i=0 ; i<3 ; i++)
{
r_eminsFPM[i] = ent->origin[i] + entmodel->mins[i];
r_emaxsFPM[i] = ent->origin[i] + entmodel->maxs[i];
}
R_SplitEntityOnNodeFPM (clFPM.worldmodel->nodes);
ent->topnode = r_pefragtopnodeFPM;
}
#endif //USEFPM
/*
================
R_StoreEfrags
// FIXME: a lot of this goes away with edge-based
================
*/
void R_StoreEfrags (efrag_t **ppefrag)
{
entity_t *pent;
model_t *clmodel;
efrag_t *pefrag;
while ((pefrag = *ppefrag) != NULL)
{
pent = pefrag->entity;
clmodel = pent->model;
switch (clmodel->type)
{
case mod_alias:
case mod_brush:
case mod_sprite:
pent = pefrag->entity;
if ((pent->visframe != r_framecount) &&
(cl_numvisedicts < MAX_VISEDICTS))
{
cl_visedicts[cl_numvisedicts++] = pent;
// mark that we've recorded this entity for this frame
pent->visframe = r_framecount;
}
ppefrag = &pefrag->leafnext;
break;
default:
Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
}
}
}
#ifdef USEFPM
void R_StoreEfragsFPM (efrag_FPM_t **ppefrag)
{
entity_FPM_t *pent;
model_FPM_t *clmodel;
efrag_FPM_t *pefrag;
while ((pefrag = *ppefrag) != NULL)
{
pent = pefrag->entity;
clmodel = pent->model;
switch (clmodel->type)
{
case mod_alias:
case mod_brush:
case mod_sprite:
pent = pefrag->entity;
if ((pent->visframe != r_framecount) &&
(cl_numvisedicts < MAX_VISEDICTS))
{
cl_visedictsFPM[cl_numvisedicts++] = pent;
// mark that we've recorded this entity for this frame
pent->visframe = r_framecount;
}
ppefrag = &pefrag->leafnext;
break;
default:
Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
}
}
}
#endif //USEFPM

View File

@@ -0,0 +1,444 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_light.c
#include "quakedef.h"
#include "r_local.h"
int r_dlightframecount;
/*
==================
R_AnimateLight
==================
*/
void R_AnimateLight (void)
{
int i,j,k;
//
// light animations
// 'm' is normal light, 'a' is no light, 'z' is double bright
i = (int)(cl.time*10);
for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
{
if (!cl_lightstyle[j].length)
{
d_lightstylevalue[j] = 256;
continue;
}
k = i % cl_lightstyle[j].length;
k = cl_lightstyle[j].map[k] - 'a';
k = k*22;
d_lightstylevalue[j] = k;
}
}
/*
=============================================================================
DYNAMIC LIGHTS
=============================================================================
*/
/*
=============
R_MarkLights
=============
*/
void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
{
mplane_t *splitplane;
float dist;
msurface_t *surf;
int i;
if (node->contents < 0)
return;
splitplane = node->plane;
dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
if (dist > light->radius)
{
R_MarkLights (light, bit, node->children[0]);
return;
}
if (dist < -light->radius)
{
R_MarkLights (light, bit, node->children[1]);
return;
}
// mark the polygons
surf = cl.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->dlightframe != r_dlightframecount)
{
surf->dlightbits = 0;
surf->dlightframe = r_dlightframecount;
}
surf->dlightbits |= bit;
}
R_MarkLights (light, bit, node->children[0]);
R_MarkLights (light, bit, node->children[1]);
}
#ifdef USEFPM
void R_MarkLightsFPM (dlight_FPM_t *light, int bit, mnode_FPM_t *node)
{
mplane_FPM_t *splitplane;
fixedpoint_t dist;
msurface_FPM_t *surf;
int i;
if (node->contents < 0)
return;
splitplane = node->plane;
dist = FPM_SUB(DotProductFPM (light->origin, splitplane->normal), splitplane->dist);
if (dist > light->radius)
{
R_MarkLightsFPM (light, bit, node->children[0]);
return;
}
if (dist < -light->radius)
{
R_MarkLightsFPM (light, bit, node->children[1]);
return;
}
// mark the polygons
surf = clFPM.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->dlightframe != r_dlightframecount)
{
surf->dlightbits = 0;
surf->dlightframe = r_dlightframecount;
}
surf->dlightbits |= bit;
}
R_MarkLightsFPM (light, bit, node->children[0]);
R_MarkLightsFPM (light, bit, node->children[1]);
}
#endif //USEFPM
/*
=============
R_PushDlights
=============
*/
void R_PushDlights (void)
{
int i;
dlight_t *l;
r_dlightframecount = r_framecount + 1; // because the count hasn't
// advanced yet for this frame
l = cl_dlights;
for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
{
if (l->die < cl.time || !l->radius)
continue;
R_MarkLights ( l, 1<<i, cl.worldmodel->nodes );
}
}
#ifdef USEFPM
void R_PushDlightsFPM (void)
{
int i;
dlight_FPM_t *l;
r_dlightframecount = r_framecount + 1; // because the count hasn't
// advanced yet for this frame
l = cl_dlightsFPM;
for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
{
if (l->die < cl.time || !l->radius)
continue;
R_MarkLightsFPM ( l, 1<<i, clFPM.worldmodel->nodes );
}
}
#endif //USEFPM
/*
=============================================================================
LIGHT SAMPLING
=============================================================================
*/
int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
{
int r;
float front, back, frac;
int side;
mplane_t *plane;
vec3_t mid;
msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
unsigned scale;
int maps;
if (node->contents < 0)
return -1; // didn't hit anything
// calculate mid point
// FIXME: optimize for axial
plane = node->plane;
front = DotProduct (start, plane->normal) - plane->dist;
back = DotProduct (end, plane->normal) - plane->dist;
side = front < 0;
if ( (back < 0) == side)
return RecursiveLightPoint (node->children[side], start, end);
frac = front / (front-back);
mid[0] = start[0] + (end[0] - start[0])*frac;
mid[1] = start[1] + (end[1] - start[1])*frac;
mid[2] = start[2] + (end[2] - start[2])*frac;
// go down front side
r = RecursiveLightPoint (node->children[side], start, mid);
if (r >= 0)
return r; // hit something
if ( (back < 0) == side )
return -1; // didn't hit anuthing
// check for impact on this node
surf = cl.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->flags & SURF_DRAWTILED)
continue; // no lightmaps
tex = surf->texinfo;
s = (int)(DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]);
t = (int)(DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3]);
if (s < surf->texturemins[0] ||
t < surf->texturemins[1])
continue;
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if ( ds > surf->extents[0] || dt > surf->extents[1] )
continue;
if (!surf->samples)
return 0;
ds >>= 4;
dt >>= 4;
lightmap = surf->samples;
r = 0;
if (lightmap)
{
lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
scale = d_lightstylevalue[surf->styles[maps]];
r += *lightmap * scale;
lightmap += ((surf->extents[0]>>4)+1) *
((surf->extents[1]>>4)+1);
}
r >>= 8;
}
return r;
}
// go down back side
return RecursiveLightPoint (node->children[!side], mid, end);
}
#ifdef USEFPM
int RecursiveLightPointFPM (mnode_FPM_t *node, vec3_FPM_t start, vec3_FPM_t end)
{
int r;
fixedpoint_t front, back, frac;
int side;
mplane_FPM_t *plane;
vec3_FPM_t mid;
msurface_FPM_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_FPM_t *tex;
byte *lightmap;
unsigned scale;
int maps;
if (node->contents < 0)
return -1; // didn't hit anything
// calculate mid point
// FIXME: optimize for axial
plane = node->plane;
front = FPM_SUB(DotProductFPM (start, plane->normal), plane->dist);
back = FPM_SUB(DotProductFPM (end, plane->normal), plane->dist);
side = front < 0;
if ( (back < 0) == side)
return RecursiveLightPointFPM (node->children[side], start, end);
frac = FPM_DIV(front, FPM_SUB(front,back));
mid[0] = FPM_ADD(start[0], FPM_MUL(FPM_SUB(end[0], start[0]),frac));
mid[1] = FPM_ADD(start[1], FPM_MUL(FPM_SUB(end[1], start[1]),frac));
mid[2] = FPM_ADD(start[2], FPM_MUL(FPM_SUB(end[2], start[2]),frac));
// go down front side
r = RecursiveLightPointFPM (node->children[side], start, mid);
if (r >= 0)
return r; // hit something
if ( (back < 0) == side )
return -1; // didn't hit anuthing
// check for impact on this node
surf = clFPM.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->flags & SURF_DRAWTILED)
continue; // no lightmaps
tex = surf->texinfo;
s = FPM_TOLONG(FPM_ADD(DotProductFPM (mid, tex->vecs[0]), tex->vecs[0][3]));
t = FPM_TOLONG(FPM_ADD(DotProductFPM (mid, tex->vecs[1]), tex->vecs[1][3]));
if (s < surf->texturemins[0] ||
t < surf->texturemins[1])
continue;
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if ( ds > surf->extents[0] || dt > surf->extents[1] )
continue;
if (!surf->samples)
return 0;
ds >>= 4;
dt >>= 4;
lightmap = surf->samples;
r = 0;
if (lightmap)
{
lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
scale = d_lightstylevalue[surf->styles[maps]];
r += *lightmap * scale;
lightmap += ((surf->extents[0]>>4)+1) *
((surf->extents[1]>>4)+1);
}
r >>= 8;
}
return r;
}
// go down back side
return RecursiveLightPointFPM (node->children[!side], mid, end);
}
#endif //USEFPM
int R_LightPoint (vec3_t p)
{
vec3_t end;
int r;
if (!cl.worldmodel->lightdata)
return 255;
end[0] = p[0];
end[1] = p[1];
end[2] = p[2] - 2048;
r = RecursiveLightPoint (cl.worldmodel->nodes, p, end);
if (r == -1)
r = 0;
if (r < r_refdef.ambientlight)
r = r_refdef.ambientlight;
return r;
}
#ifdef USEFPM
int R_LightPointFPM (vec3_FPM_t p)
{
vec3_FPM_t end;
int r;
if (!clFPM.worldmodel->lightdata)
return 255;
end[0] = p[0];
end[1] = p[1];
end[2] = FPM_SUB(p[2], FPM_FROMLONG(2048));
r = RecursiveLightPointFPM (clFPM.worldmodel->nodes, p, end);
if (r == -1)
r = 0;
if (r < r_refdefFPM.ambientlight)
r = r_refdefFPM.ambientlight;
return r;
}
#endif //USEFPM

View File

@@ -0,0 +1,428 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_local.h -- private refresh defs
#ifndef GLQUAKE
#include "r_shared.h"
#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0)
// normalizing factor so player model works out to about
// 1 pixel per triangle
#define BMODEL_FULLY_CLIPPED 0x10 // value returned by R_BmodelCheckBBox ()
// if bbox is trivially rejected
// TODO: put in span spilling to shrink list size
// !!! if this is changed, it must be changed in d_polysa.s too !!!
#define DPS_MAXSPANS MAXHEIGHT+1
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct {
void *pdest;
short *pz;
int count;
byte *ptex;
int sfrac, tfrac, light, zi;
} spanpackage_t;
//===========================================================================
// viewmodel lighting
typedef struct {
int ambientlight;
int shadelight;
float *plightvec;
} alight_t;
/*
typedef struct {
int ambientlight;
int shadelight;
fixedpoint_t *plightvec;
} alight_FPM_t;
*/
//===========================================================================
// clipped bmodel edges
typedef struct bedge_s
{
mvertex_t *v[2];
struct bedge_s *pnext;
} bedge_t;
/*
typedef struct bedge_FPM_s
{
mvertex_FPM_t *v[2];
struct bedge_FPM_s *pnext;
} bedge_FPM_t;
*/
typedef struct {
float fv[3]; // viewspace x, y
} auxvert_t;
/*
typedef struct {
fixedpoint_t fv[3]; // viewspace x, y
} auxvert_FPM_t;
*/
//===========================================================================
extern cvar_t r_draworder;
extern cvar_t r_speeds;
extern cvar_t r_timegraph;
extern cvar_t r_graphheight;
extern cvar_t r_clearcolor;
extern cvar_t r_waterwarp;
extern cvar_t r_fullbright;
extern cvar_t r_drawentities;
extern cvar_t r_aliasstats;
extern cvar_t r_dspeeds;
extern cvar_t r_drawflat;
extern cvar_t r_ambient;
extern cvar_t r_reportsurfout;
extern cvar_t r_maxsurfs;
extern cvar_t r_numsurfs;
extern cvar_t r_reportedgeout;
extern cvar_t r_maxedges;
extern cvar_t r_numedges;
//Dan East:
extern cvar_t r_maxparticles;
#define XCENTERING (1.0 / 2.0)
#define YCENTERING (1.0 / 2.0)
//#define XCENTERINGFPM FPM_FROMFLOAT(1.0 / 2.0)
//#define YCENTERINGFPM FPM_FROMFLOAT(1.0 / 2.0)
#define CLIP_EPSILON 0.001
#define BACKFACE_EPSILON 0.01
//===========================================================================
#define DIST_NOT_SET 98765
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct clipplane_s
{
vec3_t normal;
float dist;
struct clipplane_s *next;
byte leftedge;
byte rightedge;
byte reserved[2];
} clipplane_t;
typedef struct clipplane_fxp_s
{
int normal[3];
int dist;
struct clipplane_fxp_s *next;
byte leftedge;
byte rightedge;
byte reserved[2];
} clipplane_fxp_t;
/*
typedef struct clipplane_FPM_s
{
vec3_FPM_t normal;
fixedpoint_t dist;
struct clipplane_FPM_s *next;
byte leftedge;
byte rightedge;
byte reserved[2];
} clipplane_FPM_t;
*/
extern clipplane_t view_clipplanes[4];
//extern clipplane_FPM_t view_clipplanesFPM[4];
#ifdef USE_PQ_OPT2
extern clipplane_fxp_t view_clipplanes_fxp[4];
#endif
//=============================================================================
void R_RenderWorld (void);
//void R_RenderWorldFPM (void);
//=============================================================================
extern mplane_t screenedge[4];
//extern mplane_FPM_t screenedgeFPM[4];
extern vec3_t r_origin;
extern vec3_t r_entorigin;
//extern vec3_FPM_t r_entoriginFPM;
extern float screenAspect;
extern float verticalFieldOfView;
extern float xOrigin, yOrigin;
extern int r_visframecount;
//=============================================================================
extern int vstartscan;
void R_ClearPolyList (void);
void R_DrawPolyList (void);
//
// current entity info
//
extern qboolean insubmodel;
extern vec3_t r_worldmodelorg;
//extern vec3_FPM_t r_worldmodelorgFPM;
void R_DrawSprite (void);
//void R_DrawSpriteFPM (void);
void R_RenderFace (msurface_t *fa, int clipflags);
//void R_RenderFaceFPM (msurface_FPM_t *fa, int clipflags);
void R_RenderPoly (msurface_t *fa, int clipflags);
//void R_RenderPolyFPM (msurface_FPM_t *fa, int clipflags);
void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf);
//void R_RenderBmodelFaceFPM (bedge_FPM_t *pedges, msurface_FPM_t *psurf);
void R_TransformPlane (mplane_t *p, float *normal, float *dist);
void R_TransformFrustum (void);
//void R_TransformFrustumFPM (void);
void R_SetSkyFrame (void);
//void R_SetSkyFrameFPM (void);
void R_DrawSurfaceBlock16 (void);
void R_DrawSurfaceBlock8 (void);
texture_t *R_TextureAnimation (texture_t *base);
//texture_t *R_TextureAnimationFPM (texture_t *base);
#if id386
void R_DrawSurfaceBlock8_mip0 (void);
void R_DrawSurfaceBlock8_mip1 (void);
void R_DrawSurfaceBlock8_mip2 (void);
void R_DrawSurfaceBlock8_mip3 (void);
#endif
void R_GenSkyTile (void *pdest);
void R_GenSkyTile16 (void *pdest);
void R_Surf8Patch (void);
void R_Surf16Patch (void);
void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags);
//void R_DrawSubmodelPolygonsFPM (model_FPM_t *pmodel, int clipflags);
void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel);
//void R_DrawSolidClippedSubmodelPolygonsFPM (model_FPM_t *pmodel);
void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
surf_t *R_GetSurf (void);
void R_AliasDrawModel (alight_t *plighting);
//void R_AliasDrawModelFPM (alight_FPM_t *plighting);
void R_BeginEdgeFrame (void);
//void R_BeginEdgeFrameFPM (void);
void R_ScanEdges (void);
//void R_ScanEdgesFPM (void);
void D_DrawSurfaces (void);
//void D_DrawSurfacesFPM (void);
void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist);
void R_StepActiveU (edge_t *pedge);
void R_RemoveEdges (edge_t *pedge);
extern void R_Surf8Start (void);
extern void R_Surf8End (void);
extern void R_Surf16Start (void);
extern void R_Surf16End (void);
extern void R_EdgeCodeStart (void);
extern void R_EdgeCodeEnd (void);
extern void R_RotateBmodel (void);
//extern void R_RotateBmodelFPM (void);
extern int c_faceclip;
extern int r_polycount;
extern int r_wholepolycount;
extern model_t *cl_worldmodel;
extern int *pfrustum_indexes[4];
// !!! if this is changed, it must be changed in asm_draw.h too !!!
#define NEAR_CLIP 0.01
//#define NEAR_CLIP_FPM FPM_FROMFLOAT(0.01)
extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
extern int vstartscan;
extern fixed16_t sadjust, tadjust;
extern fixed16_t bbextents, bbextentt;
#define MAXBVERTINDEXES 1000 // new clipped vertices when clipping bmodels
// to the world BSP
extern mvertex_t *r_ptverts, *r_ptvertsmax;
extern vec3_t sbaseaxis[3], tbaseaxis[3];
extern float entity_rotation[3][3];
extern int reinit_surfcache;
extern int r_currentkey;
extern int r_currentbkey;
typedef struct btofpoly_s {
int clipflags;
msurface_t *psurf;
} btofpoly_t;
/*
typedef struct btofpoly_FPM_s {
int clipflags;
msurface_FPM_t *psurf;
} btofpoly_FPM_t;
*/
#define MAX_BTOFPOLYS 5000 // FIXME: tune this
extern int numbtofpolys;
extern btofpoly_t *pbtofpolys;
//extern btofpoly_FPM_t *pbtofpolysFPM;
void R_InitTurb (void);
void R_ZDrawSubmodelPolys (model_t *clmodel);
//void R_ZDrawSubmodelPolysFPM (model_FPM_t *clmodel);
//=========================================================
// Alias models
//=========================================================
#define MAXALIASVERTS 2000 // TODO: tune this
#define ALIAS_Z_CLIP_PLANE 5
//#define ALIAS_Z_CLIP_PLANE_FPM FPM_FROMLONG(5)
extern int numverts;
extern int a_skinwidth;
extern mtriangle_t *ptriangles;
extern int numtriangles;
extern aliashdr_t *paliashdr;
extern mdl_t *pmdl;
extern float leftclip, topclip, rightclip, bottomclip;
extern int r_acliptype;
extern finalvert_t *pfinalverts;
extern auxvert_t *pauxverts;
//extern auxvert_FPM_t *pauxvertsFPM;
qboolean R_AliasCheckBBox (void);
//qboolean R_AliasCheckBBoxFPM (void);
//=========================================================
// turbulence stuff
#define AMP 8*0x10000
#define AMP2 3
#define SPEED 20
//=========================================================
// particle stuff
void R_DrawParticles (void);
//void R_DrawParticlesFPM (void);
void R_InitParticles (void);
//void R_InitParticlesFPM (void);
void R_ClearParticles (void);
//void R_ClearParticlesFPM (void);
void R_ReadPointFile_f (void);
void R_SurfacePatch (void);
//void R_SurfacePatchFPM (void);
extern int r_amodels_drawn;
extern edge_t *auxedges;
//extern edge_FPM_t *auxedgesFPM;
extern int r_numallocatededges;
extern edge_t *r_edges, *edge_p, *edge_max;
//extern edge_FPM_t *r_edgesFPM, *edge_FPM_p, *edge_maxFPM;
extern edge_t *newedges[MAXHEIGHT];
extern edge_t *removeedges[MAXHEIGHT];
//extern edge_FPM_t *newedgesFPM[MAXHEIGHT];
//extern edge_FPM_t *removeedgesFPM[MAXHEIGHT];
extern int screenwidth;
// FIXME: make stack vars when debugging done
extern edge_t edge_head;
extern edge_t edge_tail;
extern edge_t edge_aftertail;
extern int r_bmodelactive;
extern vrect_t *pconupdate;
extern float aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
//extern fixedpoint_t aliasxscaleFPM, aliasyscaleFPM, aliasxcenterFPM, aliasycenterFPM;
extern float r_aliastransition, r_resfudge;
//extern fixedpoint_t r_aliastransitionFPM, r_resfudgeFPM;
extern int r_outofsurfaces;
extern int r_outofedges;
extern mvertex_t *r_pcurrentvertbase;
//extern mvertex_FPM_t *r_pcurrentvertbaseFPM;
#ifdef USE_PQ_OPT2
extern mvertex_fxp_t *r_pcurrentvertbase_fxp;
#endif
extern int r_maxvalidedgeoffset;
void R_AliasClipTriangle (mtriangle_t *ptri);
//void R_AliasClipTriangleFPM (mtriangle_t *ptri);
extern float r_time1;
extern float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
extern float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2;
extern int r_frustum_indexes[4*6];
extern int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs;
extern qboolean r_surfsonstack;
extern cshift_t cshift_water;
extern qboolean r_dowarpold, r_viewchanged;
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
//extern mleaf_FPM_t *r_viewleafFPM, *r_oldviewleafFPM;
extern vec3_t r_emins, r_emaxs;
//extern vec3_FPM_t r_eminsFPM, r_emaxsFPM;
extern mnode_t *r_pefragtopnode;
//extern mnode_FPM_t *r_pefragtopnodeFPM;
extern int r_clipflags;
extern int r_dlightframecount;
extern qboolean r_fov_greater_than_90;
void R_StoreEfrags (efrag_t **ppefrag);
//void R_StoreEfragsFPM (efrag_FPM_t **ppefrag);
void R_TimeRefresh_f (void);
void R_TimeGraph (void);
//void R_TimeGraphFPM (void);
void R_PrintAliasStats (void);
void R_PrintTimes (void);
void R_PrintDSpeeds (void);
void R_AnimateLight (void);
int R_LightPoint (vec3_t p);
//int R_LightPointFPM (vec3_FPM_t p);
void R_SetupFrame (void);
//void R_SetupFrameFPM (void);
void R_cshift_f (void);
void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1);
//void R_EmitEdgeFPM (mvertex_FPM_t *pv0, mvertex_FPM_t *pv1);
void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip);
void R_SplitEntityOnNode2 (mnode_t *node);
//void R_SplitEntityOnNode2FPM (mnode_FPM_t *node);
void R_MarkLights (dlight_t *light, int bit, mnode_t *node);
//void R_MarkLightsFPM (dlight_FPM_t *light, int bit, mnode_FPM_t *node);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,568 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_misc.c
#include "quakedef.h"
#include "r_local.h"
/*
===============
R_CheckVariables
===============
*/
void R_CheckVariables (void)
{
static float oldbright;
if (r_fullbright.value != oldbright)
{
oldbright = r_fullbright.value;
D_FlushCaches (); // so all lighting changes
}
}
/*
============
Show
Debugging use
============
*/
void Show (void)
{
vrect_t vr;
vr.x = vr.y = 0;
vr.width = vid.width;
vr.height = vid.height;
vr.pnext = NULL;
VID_Update (&vr);
}
/*
====================
R_TimeRefresh_f
For program optimization
====================
*/
void R_TimeRefresh_f (void)
{
int i;
float start, stop, time;
int startangle;
vrect_t vr;
startangle = (int)r_refdef.viewangles[1];
start = (float)Sys_FloatTime ();
for (i=0 ; i<128 ; i++)
{
r_refdef.viewangles[1] = (float)(i/128.0*360.0);
VID_LockBuffer ();
R_RenderView ();
VID_UnlockBuffer ();
vr.x = r_refdef.vrect.x;
vr.y = r_refdef.vrect.y;
vr.width = r_refdef.vrect.width;
vr.height = r_refdef.vrect.height;
vr.pnext = NULL;
VID_Update (&vr);
}
stop = (float)Sys_FloatTime ();
time = stop-start;
Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
r_refdef.viewangles[1] = (float)startangle;
}
/*
================
R_LineGraph
Only called by R_DisplayTime
================
*/
void R_LineGraph (int x, int y, int h)
{
int i;
byte *dest;
int s;
// FIXME: should be disabled on no-buffer adapters, or should be in the driver
x += r_refdef.vrect.x;
y += r_refdef.vrect.y;
dest = vid.buffer + vid.rowbytes*y + x;
s = (int)r_graphheight.value;
if (h>s)
h = s;
for (i=0 ; i<h ; i++, dest -= vid.rowbytes*2)
{
dest[0] = 0xff;
*(dest-vid.rowbytes) = 0x30;
}
for ( ; i<s ; i++, dest -= vid.rowbytes*2)
{
dest[0] = 0x30;
*(dest-vid.rowbytes) = 0x30;
}
}
/*
==============
R_TimeGraph
Performance monitoring tool
==============
*/
#define MAX_TIMINGS 100
extern float mouse_x, mouse_y;
void R_TimeGraph (void)
{
static int timex;
int a;
float r_time2;
static byte r_timings[MAX_TIMINGS];
int x;
r_time2 = (float)Sys_FloatTime ();
a = (int)((r_time2-r_time1)/0.01);
//a = fabs(mouse_y * 0.05);
//a = (int)((r_refdef.vieworg[2] + 1024)/1)%(int)r_graphheight.value;
//a = fabs(velocity[0])/20;
//a = ((int)fabs(origin[0])/8)%20;
//a = (cl.idealpitch + 30)/5;
r_timings[timex] = a;
a = timex;
if (r_refdef.vrect.width <= MAX_TIMINGS)
x = r_refdef.vrect.width-1;
else
x = r_refdef.vrect.width -
(r_refdef.vrect.width - MAX_TIMINGS)/2;
do
{
R_LineGraph (x, r_refdef.vrect.height-2, r_timings[a]);
if (x==0)
break; // screen too small to hold entire thing
x--;
a--;
if (a == -1)
a = MAX_TIMINGS-1;
} while (a != timex);
timex = (timex+1)%MAX_TIMINGS;
}
/*
=============
R_PrintTimes
=============
*/
void R_PrintTimes (void)
{
float r_time2;
float ms;
r_time2 = (float)Sys_FloatTime ();
ms = 1000* (r_time2 - r_time1);
Con_Printf ("%5.1f ms %3i/%3i/%3i poly %3i surf\n",
ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf);
c_surf = 0;
}
/*
=============
R_PrintDSpeeds
=============
*/
void R_PrintDSpeeds (void)
{
float ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, dv_time;
r_time2 = (float)Sys_FloatTime ();
dp_time = (dp_time2 - dp_time1) * 1000;
rw_time = (rw_time2 - rw_time1) * 1000;
db_time = (db_time2 - db_time1) * 1000;
se_time = (se_time2 - se_time1) * 1000;
de_time = (de_time2 - de_time1) * 1000;
dv_time = (dv_time2 - dv_time1) * 1000;
ms = (r_time2 - r_time1) * 1000;
Con_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n",
(int)ms, dp_time, (int)rw_time, db_time, (int)se_time, de_time,
dv_time);
}
/*
=============
R_PrintAliasStats
=============
*/
void R_PrintAliasStats (void)
{
Con_Printf ("%3i polygon model drawn\n", r_amodels_drawn);
}
void WarpPalette (void)
{
int i,j;
byte newpalette[768];
int basecolor[3];
basecolor[0] = 130;
basecolor[1] = 80;
basecolor[2] = 50;
// pull the colors halfway to bright brown
for (i=0 ; i<256 ; i++)
{
for (j=0 ; j<3 ; j++)
{
newpalette[i*3+j] = (host_basepal[i*3+j] + basecolor[j])/2;
}
}
VID_ShiftPalette (newpalette);
}
/*
===================
R_TransformFrustum
===================
*/
void R_TransformFrustum (void)
{
int i;
vec3_t v, v2;
for (i=0 ; i<4 ; i++)
{
v[0] = screenedge[i].normal[2];
v[1] = -screenedge[i].normal[0];
v[2] = screenedge[i].normal[1];
v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0];
v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1];
v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2];
VectorCopy (v2, view_clipplanes[i].normal);
view_clipplanes[i].dist = DotProduct (modelorg, v2);
#ifdef USE_PQ_OPT2
if (!v2[0]) view_clipplanes_fxp[i].normal[0]=2<29;
else view_clipplanes_fxp[i].normal[0]=(int)(4096.0f/v2[0]);
if (!v2[1]) view_clipplanes_fxp[i].normal[1]=2<29;
else view_clipplanes_fxp[i].normal[1]=(int)(4096.0f/v2[1]);
if (!v2[2]) view_clipplanes_fxp[i].normal[2]=2<29;
else view_clipplanes_fxp[i].normal[2]=(int)(4096.0f/v2[2]);
view_clipplanes_fxp[i].dist=(int)(view_clipplanes[i].dist*128.0);
#endif
}
}
#if !id386
/*
================
TransformVector
================
*/
void TransformVector (vec3_t in, vec3_t out)
{
out[0] = DotProduct(in,vright);
out[1] = DotProduct(in,vup);
out[2] = DotProduct(in,vpn);
}
#ifdef USE_PQ_OPT
//JB: Optimization
static float last;
static fpvec3 fpvright, fpvup, fpvpn;
void FPTransformVector( fpvec3 in, fpvec3 out )
{
if (last != vright[0])
{
last = vright[0];
fpvright[0] = (int)(16384.0f * vright[0]);
fpvright[1] = (int)(16384.0f * vright[1]);
fpvright[2] = (int)(16384.0f * vright[2]);
fpvup[0] = (int)(16384.0f * vup[0]);
fpvup[1] = (int)(16384.0f * vup[1]);
fpvup[2] = (int)(16384.0f * vup[2]);
fpvpn[0] = (int)(16384.0f * vpn[0]);
fpvpn[1] = (int)(16384.0f * vpn[1]);
fpvpn[2] = (int)(16384.0f * vpn[2]);
}
out[0] = (in[0] * fpvright[0] +
in[1] * fpvright[1] +
in[2] * fpvright[2]) >> 4;
out[1] = (in[0] * fpvup[0] +
in[1] * fpvup[1] +
in[2] * fpvup[2]) >> 4;
out[2] = (in[0] * fpvpn[0] +
in[1] * fpvpn[1] +
in[2] * fpvpn[2]) >> 4;
}
#endif
#endif
/*
================
R_TransformPlane
================
*/
void R_TransformPlane (mplane_t *p, float *normal, float *dist)
{
float d;
d = DotProduct (r_origin, p->normal);
*dist = p->dist - d;
// TODO: when we have rotating entities, this will need to use the view matrix
TransformVector (p->normal, normal);
}
/*
===============
R_SetUpFrustumIndexes
===============
*/
void R_SetUpFrustumIndexes (void)
{
static int i, j, *pindex;
pindex = r_frustum_indexes;
for (i=0 ; i<4 ; i++)
{
for (j=0 ; j<3 ; j++)
{
if (view_clipplanes[i].normal[j] < 0.0)
{
pindex[j] = j;
pindex[j+3] = j+3;
//Dan:
// pindex[j+1]=pindex[j+2]=0;
}
else
{
pindex[j] = j+3;
pindex[j+3] = j;
// pindex[j+1]=pindex[j+2]=0;
}
}
// FIXME: do just once at start
pfrustum_indexes[i] = pindex;
pindex += 6;
}
// VerifyFrustumIndexes("setup");
}
/*
===============
R_SetupFrame
===============
*/
void R_SetupFrame (void)
{
int edgecount;
vrect_t vrect;
float w, h;
// don't allow cheats in multiplayer
if (cl.maxclients > 1)
{
Cvar_Set ("r_draworder", "0");
Cvar_Set ("r_fullbright", "0");
Cvar_Set ("r_ambient", "0");
Cvar_Set ("r_drawflat", "0");
}
if (r_numsurfs.value)
{
if ((surface_p - surfaces) > r_maxsurfsseen)
r_maxsurfsseen = surface_p - surfaces;
Con_Printf ("Used %d of %d surfs; %d max\n", surface_p - surfaces,
surf_max - surfaces, r_maxsurfsseen);
}
if (r_numedges.value)
{
edgecount = edge_p - r_edges;
if (edgecount > r_maxedgesseen)
r_maxedgesseen = edgecount;
Con_Printf ("Used %d of %d edges; %d max\n", edgecount,
r_numallocatededges, r_maxedgesseen);
}
r_refdef.ambientlight = (int)r_ambient.value;
if (r_refdef.ambientlight < 0)
r_refdef.ambientlight = 0;
if (!sv.active)
r_draworder.value = 0; // don't let cheaters look behind walls
R_CheckVariables ();
R_AnimateLight ();
r_framecount++;
numbtofpolys = 0;
// debugging
#if 0
r_refdef.vieworg[0]= 80;
r_refdef.vieworg[1]= 64;
r_refdef.vieworg[2]= 40;
r_refdef.viewangles[0]= 0;
r_refdef.viewangles[1]= 46.763641357;
r_refdef.viewangles[2]= 0;
#endif
// build the transformation matrix for the given view angles
VectorCopy (r_refdef.vieworg, modelorg);
VectorCopy (r_refdef.vieworg, r_origin);
AngleVectors (r_refdef.viewangles, vpn, vright, vup);
// current viewleaf
r_oldviewleaf = r_viewleaf;
r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
r_dowarpold = r_dowarp;
r_dowarp = r_waterwarp.value && (r_viewleaf->contents <= CONTENTS_WATER);
if ((r_dowarp != r_dowarpold) || r_viewchanged || lcd_x.value)
{
if (r_dowarp)
{
if ((vid.width <= (unsigned int)vid.maxwarpwidth) &&
(vid.height <= (unsigned int)vid.maxwarpheight))
{
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height;
R_ViewChanged (&vrect, sb_lines, vid.aspect);
}
else
{
w = (float)vid.width;
h = (float)vid.height;
if (w > vid.maxwarpwidth)
{
h *= (float)vid.maxwarpwidth / w;
w = (float)vid.maxwarpwidth;
}
if (h > vid.maxwarpheight)
{
h = (float)vid.maxwarpheight;
w *= (float)vid.maxwarpheight / h;
}
vrect.x = 0;
vrect.y = 0;
vrect.width = (int)w;
vrect.height = (int)h;
R_ViewChanged (&vrect,
(int)((float)sb_lines * (h/(float)vid.height)),
vid.aspect * (h / w) *
((float)vid.width / (float)vid.height));
}
}
else
{
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height;
R_ViewChanged (&vrect, sb_lines, vid.aspect);
}
r_viewchanged = false;
}
// start off with just the four screen edge clip planes
R_TransformFrustum ();
// save base values
VectorCopy (vpn, base_vpn);
VectorCopy (vright, base_vright);
VectorCopy (vup, base_vup);
VectorCopy (modelorg, base_modelorg);
R_SetSkyFrame ();
// VerifyFrustumIndexes("bef");
R_SetUpFrustumIndexes ();
// VerifyFrustumIndexes("aft");
r_cache_thrash = false;
// clear frame counts
c_faceclip = 0;
d_spanpixcount = 0;
r_polycount = 0;
r_drawnpolycount = 0;
r_wholepolycount = 0;
r_amodels_drawn = 0;
r_outofsurfaces = 0;
r_outofedges = 0;
D_SetupFrame ();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,215 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef GLQUAKE
// r_shared.h: general refresh-related stuff shared between the refresh and the
// driver
// FIXME: clean up and move into d_iface.h
#ifndef _R_SHARED_H_
#define _R_SHARED_H_
#define MAXVERTS 16 // max points in a surface polygon
#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate
// polygon (while processing)
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define MAXHEIGHT 1024
#define MAXWIDTH 1280
#define MAXDIMENSION ((MAXHEIGHT > MAXWIDTH) ? MAXHEIGHT : MAXWIDTH)
#define SIN_BUFFER_SIZE (MAXDIMENSION+CYCLE)
#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to
// be farther away than anything in
// the scene
//===================================================================
extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1);
extern int cachewidth;
extern pixel_t *cacheblock;
extern int screenwidth;
extern float pixelAspect;
extern fixedpoint_t pixelAspectFPM;
extern int r_drawnpolycount;
extern cvar_t r_clearcolor;
extern int sintable[SIN_BUFFER_SIZE];
extern int intsintable[SIN_BUFFER_SIZE];
extern vec3_t vup, base_vup;
extern vec3_FPM_t vupFPM, base_vupFPM;
extern vec3_t vpn, base_vpn;
extern vec3_FPM_t vpnFPM, base_vpnFPM;
extern vec3_t vright, base_vright;
extern vec3_FPM_t vrightFPM, base_vrightFPM;
extern entity_t *currententity;
extern entity_FPM_t *currententityFPM;
#define NUMSTACKEDGES 2400
#define MINEDGES 300
#define NUMSTACKSURFACES 800
#define MINSURFACES 100
#define MAXSPANS 3000
/*
#define NUMSTACKEDGES 2400
#define MINEDGES NUMSTACKEDGES
#define NUMSTACKSURFACES 800
#define MINSURFACES NUMSTACKSURFACES
#define MAXSPANS 3000
*/
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct espan_s
{
int u, v, count;
struct espan_s *pnext;
} espan_t;
// FIXME: compress, make a union if that will help
// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte
typedef struct surf_s
{
struct surf_s *next; // active surface stack in r_edge.c
struct surf_s *prev; // used in r_edge.c for active surf stack
struct espan_s *spans; // pointer to linked list of spans to draw
int key; // sorting key (BSP order)
int last_u; // set during tracing
int spanstate; // 0 = not in span
// 1 = in span
// -1 = in inverted span (end before
// start)
int flags; // currentface flags
void *data; // associated data like msurface_t
entity_t *entity;
float nearzi; // nearest 1/z on surface, for mipmapping
qboolean insubmodel;
#ifndef USE_PQ_OPT3
float d_ziorigin, d_zistepu, d_zistepv;
#else
int d_ziorigin_fxp, d_zistepu_fxp, d_zistepv_fxp;
#endif
int pad[2]; // to 64 bytes
} surf_t;
typedef struct surf_FPM_s
{
struct surf_FPM_s *next; // active surface stack in r_edge.c
struct surf_FPM_s *prev; // used in r_edge.c for active surf stack
struct espan_s *spans; // pointer to linked list of spans to draw
int key; // sorting key (BSP order)
int last_u; // set during tracing
int spanstate; // 0 = not in span
// 1 = in span
// -1 = in inverted span (end before
// start)
int flags; // currentface flags
void *data; // associated data like msurface_t
entity_FPM_t *entity;
fixedpoint_t nearzi; // nearest 1/z on surface, for mipmapping
qboolean insubmodel;
fixedpoint_t d_ziorigin, d_zistepu, d_zistepv;
int pad[2]; // to 64 bytes
} surf_FPM_t;
extern surf_t *surfaces, *surface_p, *surf_max;
extern surf_FPM_t *surfacesFPM, *surface_FPM_p, *surf_maxFPM;
// surfaces are generated in back to front order by the bsp, so if a surf
// pointer is greater than another one, it should be drawn in front
// surfaces[1] is the background, and is used as the active surface stack.
// surfaces[0] is a dummy, because index 0 is used to indicate no surface
// attached to an edge_t
//===================================================================
extern vec3_t sxformaxis[4]; // s axis transformed into viewspace
extern vec3_t txformaxis[4]; // t axis transformed into viewspac
extern vec3_t modelorg, base_modelorg;
extern vec3_FPM_t modelorgFPM, base_modelorgFPM;
extern float xcenter, ycenter;
extern fixedpoint_t xcenterFPM, ycenterFPM;
extern float xscale, yscale;
extern fixedpoint_t xscaleFPM, yscaleFPM;
extern float xscaleinv, yscaleinv;
extern fixedpoint_t xscaleinvFPM, yscaleinvFPM;
extern float xscaleshrink, yscaleshrink;
extern fixedpoint_t xscaleshrinkFPM, yscaleshrinkFPM;
extern int d_lightstylevalue[256]; // 8.8 frac of base light value
extern void TransformVector (vec3_t in, vec3_t out);
#ifdef USE_PQ_OPT
//JB: Optimization
extern void FPTransformVector (fpvec3 in, fpvec3 out);
#endif
extern void TransformVectorFPM (vec3_FPM_t in, vec3_FPM_t out);
extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
fixed8_t endvertu, fixed8_t endvertv);
extern int r_skymade;
extern void R_MakeSky (void);
extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
// flags in finalvert_t.flags
#define ALIAS_LEFT_CLIP 0x0001
#define ALIAS_TOP_CLIP 0x0002
#define ALIAS_RIGHT_CLIP 0x0004
#define ALIAS_BOTTOM_CLIP 0x0008
#define ALIAS_Z_CLIP 0x0010
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define ALIAS_ONSEAM 0x0020 // also defined in modelgen.h;
// must be kept in sync
#define ALIAS_XY_CLIP_MASK 0x000F
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct edge_s
{
fixed16_t u;
fixed16_t u_step;
struct edge_s *prev, *next;
unsigned short surfs[2];
struct edge_s *nextremove;
float nearzi;
medge_t *owner;
} edge_t;
typedef struct edge_FPM_s
{
fixed16_t u;
fixed16_t u_step;
struct edge_FPM_s *prev, *next;
unsigned short surfs[2];
struct edge_FPM_s *nextremove;
fixedpoint_t nearzi;
medge_t *owner;
} edge_FPM_t;
#endif // _R_SHARED_H_
#endif // GLQUAKE

Some files were not shown because too many files have changed in this diff Show More