Updating to IOQ3 svn 2064, vbos-glsl-17 and various fixes.

This commit is contained in:
Richard Allen 2011-07-11 19:05:03 +00:00
parent bd3aedfaeb
commit 58af049d5f
122 changed files with 6387 additions and 3887 deletions

View file

@ -183,7 +183,7 @@ CGDIR=$(MOUNT_DIR)/cgame
BLIBDIR=$(MOUNT_DIR)/botlib
NDIR=$(MOUNT_DIR)/null
UIDIR=$(MOUNT_DIR)/ui
Q3UIDIR=$(MOUNT_DIR)/q3_ui
Q3UIDIR=$(MOUNT_DIR)/ui
JPDIR=$(MOUNT_DIR)/jpeg-8c
SPEEXDIR=$(MOUNT_DIR)/libspeex
ZDIR=$(MOUNT_DIR)/zlib
@ -1442,6 +1442,7 @@ Q3OBJ = \
$(B)/client/tr_vbo.o \
$(B)/client/tr_fbo.o \
$(B)/client/tr_postprocess.o \
$(B)/client/tr_model_iqm.o \
\
$(B)/client/sdl_gamma.o \
$(B)/client/sdl_input.o \

View file

@ -65,34 +65,34 @@ extern "C" {
#endif
/*
** Copyright (c) 2007-2010 The Khronos Group Inc.
** License Applicability. Except to the extent portions of this file are
** made subject to an alternative license as permitted in the SGI Free
** Software License B, Version 1.1 (the "License"), the contents of this
** file are subject only to the provisions of the License. You may not use
** this file except in compliance with the License. You may obtain a copy
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
** http://oss.sgi.com/projects/FreeB
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
** Note that, as provided in the License, the Software is distributed on an
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
** Original Code. The Original Code is: OpenGL Sample Implementation,
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc.
** Copyright in any portions created by third parties is as indicated
** elsewhere herein. All Rights Reserved.
**
** Additional Notice Provisions: This software was created using the
** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has
** not been independently verified as being compliant with the OpenGL(R)
** version 1.2.1 Specification.
*/
/* Header file version number, required by OpenGL ABI for Linux */
/* glext.h last updated $Date: 2010-12-09 02:15:08 -0800 (Thu, 09 Dec 2010) $ */
/* Current version at http://www.opengl.org/registry/ */
#define GL_GLEXT_VERSION 67
/* Function declaration macros - to move into glplatform.h */
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>

View file

@ -15,7 +15,7 @@ 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 Foobar; if not, write to the Free Software
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/

View file

@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
.section .note.GNU-stack,"",@progbits
#endif
#ifdef __ELF__
#if defined(__ELF__) || defined(__WIN64__)
#define C(label) label
#else
#define C(label) _##label

View file

@ -15,7 +15,7 @@ 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 Foobar; if not, write to the Free Software
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/

View file

@ -3509,7 +3509,7 @@ void BotResetLastAvoidReach(int movestate)
if (latesttime)
{
ms->avoidreachtimes[latest] = 0;
if (ms->avoidreachtries[i] > 0) ms->avoidreachtries[latest]--;
if (ms->avoidreachtries[latest] > 0) ms->avoidreachtries[latest]--;
} //end if
} //end of the function BotResetLastAvoidReach
//===========================================================================

View file

@ -271,7 +271,7 @@ token_t *PC_CopyToken(token_t *token)
#ifdef BSPC
Error("out of token space\n");
#else
Com_Error(ERR_FATAL, "out of token space\n");
Com_Error(ERR_FATAL, "out of token space");
#endif
return NULL;
} //end if

View file

@ -185,7 +185,7 @@ void CG_LoadingClient(int clientNum)
if (loadingPlayerIconCount < MAX_LOADING_PLAYER_ICONS) {
Q_strncpyz(model, Info_ValueForKey(info, "model"), sizeof(model));
skin = Q_strrchr(model, '/');
skin = strrchr(model, '/');
if (skin) {
*skin++ = '\0';
} else {

View file

@ -32,7 +32,7 @@
#include "cg_local.h"
static int (QDECL * syscall) (int arg, ...) = (int (QDECL *) (int, ...)) -1;
static intptr_t (QDECL *syscall)( intptr_t arg, ... ) = (intptr_t (QDECL *)( intptr_t, ...))-1;
Q_EXPORT void dllEntry( intptr_t (QDECL *syscallptr)( intptr_t arg,... ) ) {
syscall = syscallptr;

View file

@ -251,7 +251,7 @@
* */
void COM_StripExtensionInPlace(char *name)
{
char* ext = Q_strrchr(name, '.');
char* ext = strrchr(name, '.');
if (ext)
*ext = 0;
}

View file

@ -82,7 +82,7 @@ SafeFS_Write
static ID_INLINE void SafeFS_Write( const void *buffer, int len, fileHandle_t f )
{
if( FS_Write( buffer, len, f ) < len )
Com_Error( ERR_DROP, "Failed to write avi file\n" );
Com_Error( ERR_DROP, "Failed to write avi file" );
}
/*
@ -142,7 +142,7 @@ static ID_INLINE void START_CHUNK( const char *s )
{
if( afd.chunkStackTop == MAX_RIFF_CHUNKS )
{
Com_Error( ERR_DROP, "ERROR: Top of chunkstack breached\n" );
Com_Error( ERR_DROP, "ERROR: Top of chunkstack breached" );
}
afd.chunkStack[ afd.chunkStackTop ] = bufIndex;
@ -162,7 +162,7 @@ static ID_INLINE void END_CHUNK( void )
if( afd.chunkStackTop <= 0 )
{
Com_Error( ERR_DROP, "ERROR: Bottom of chunkstack breached\n" );
Com_Error( ERR_DROP, "ERROR: Bottom of chunkstack breached" );
}
afd.chunkStackTop--;

View file

@ -300,7 +300,7 @@ rescan:
if ( argc >= 2 )
Com_Error( ERR_SERVERDISCONNECT, "Server disconnected - %s", Cmd_Argv( 1 ) );
else
Com_Error( ERR_SERVERDISCONNECT, "Server disconnected\n" );
Com_Error( ERR_SERVERDISCONNECT, "Server disconnected" );
}
if ( !strcmp( cmd, "bcs0" ) ) {
@ -559,6 +559,7 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) {
return re.RegisterShaderNoMip( VMA(1) );
case CG_R_REGISTERFONT:
re.RegisterFont( VMA(1), args[2], VMA(3));
return 0;
case CG_R_CLEARSCENE:
re.ClearScene();
return 0;
@ -670,7 +671,7 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) {
case CG_REAL_TIME:
return Com_RealTime( VMA(1) );
case CG_SNAPVECTOR:
Sys_SnapVector( VMA(1) );
Q_SnapVector(VMA(1));
return 0;
case CG_CIN_PLAYCINEMATIC:
@ -757,7 +758,7 @@ void CL_InitCGame( void ) {
if ( !cgvm ) {
Com_Error( ERR_DROP, "VM_Create on cgame failed" );
}
cls.state = CA_LOADING;
clc.state = CA_LOADING;
// init for this gamestate
// use the lastExecutedServerCommand instead of the serverCommandSequence
@ -770,7 +771,7 @@ void CL_InitCGame( void ) {
// we will send a usercmd this frame, which
// will cause the server to send us the first snapshot
cls.state = CA_PRIMED;
clc.state = CA_PRIMED;
t2 = Sys_Milliseconds();
@ -908,7 +909,7 @@ void CL_FirstSnapshot( void ) {
if ( cl.snap.snapFlags & SNAPFLAG_NOT_ACTIVE ) {
return;
}
cls.state = CA_ACTIVE;
clc.state = CA_ACTIVE;
// set the timedelta so we are exactly on this first frame
cl.serverTimeDelta = cl.snap.serverTime - cls.realtime;
@ -979,8 +980,8 @@ CL_SetCGameTime
*/
void CL_SetCGameTime( void ) {
// getting a valid frame message ends the connection process
if ( cls.state != CA_ACTIVE ) {
if ( cls.state != CA_PRIMED ) {
if ( clc.state != CA_ACTIVE ) {
if ( clc.state != CA_PRIMED ) {
return;
}
if ( clc.demoplaying ) {
@ -996,7 +997,7 @@ void CL_SetCGameTime( void ) {
cl.newSnapshots = qfalse;
CL_FirstSnapshot();
}
if ( cls.state != CA_ACTIVE ) {
if ( clc.state != CA_ACTIVE ) {
return;
}
}
@ -1109,7 +1110,7 @@ void CL_SetCGameTime( void ) {
// feed another messag, which should change
// the contents of cl.snap
CL_ReadDemoMessage();
if ( cls.state != CA_ACTIVE ) {
if ( clc.state != CA_ACTIVE ) {
return; // end of demo
}
}

View file

@ -1281,7 +1281,7 @@ static void RoQShutdown( void ) {
}
if (cinTable[currentHandle].alterGameState) {
cls.state = CA_DISCONNECTED;
clc.state = CA_DISCONNECTED;
// we can't just do a vstr nextmap, because
// if we are aborting the intro cinematic with
// a devmap command, nextmap would be valid by
@ -1314,7 +1314,7 @@ e_status CIN_StopCinematic(int handle) {
}
if (cinTable[currentHandle].alterGameState) {
if ( cls.state != CA_CINEMATIC ) {
if ( clc.state != CA_CINEMATIC ) {
return cinTable[currentHandle].status;
}
}
@ -1355,7 +1355,7 @@ e_status CIN_RunCinematic (int handle)
currentHandle = handle;
if (cinTable[currentHandle].alterGameState) {
if ( cls.state != CA_CINEMATIC ) {
if ( clc.state != CA_CINEMATIC ) {
return cinTable[currentHandle].status;
}
}
@ -1479,7 +1479,7 @@ int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBi
Com_DPrintf("trFMV::play(), playing %s\n", arg);
if (cinTable[currentHandle].alterGameState) {
cls.state = CA_CINEMATIC;
clc.state = CA_CINEMATIC;
}
Con_Close();
@ -1614,7 +1614,7 @@ void CL_PlayCinematic_f(void) {
int bits = CIN_system;
Com_DPrintf("CL_PlayCinematic_f\n");
if (cls.state == CA_CINEMATIC) {
if (clc.state == CA_CINEMATIC) {
SCR_StopCinematic();
}

View file

@ -72,7 +72,7 @@ Con_ToggleConsole_f
*/
void Con_ToggleConsole_f (void) {
// Can't toggle the console when it's the only thing available
if ( cls.state == CA_DISCONNECTED && Key_GetCatcher( ) == KEYCATCH_CONSOLE ) {
if ( clc.state == CA_DISCONNECTED && Key_GetCatcher( ) == KEYCATCH_CONSOLE ) {
return;
}
@ -343,6 +343,21 @@ void Con_Init (void) {
Cmd_SetCommandCompletionFunc( "condump", Cmd_CompleteTxtName );
}
/*
================
Con_Shutdown
================
*/
void Con_Shutdown(void)
{
Cmd_RemoveCommand("toggleconsole");
Cmd_RemoveCommand("messagemode");
Cmd_RemoveCommand("messagemode2");
Cmd_RemoveCommand("messagemode3");
Cmd_RemoveCommand("messagemode4");
Cmd_RemoveCommand("clear");
Cmd_RemoveCommand("condump");
}
/*
===============
@ -487,7 +502,7 @@ Draw the editline after a ] prompt
void Con_DrawInput (void) {
int y;
if ( cls.state != CA_DISCONNECTED && !(Key_GetCatcher( ) & KEYCATCH_CONSOLE ) ) {
if ( clc.state != CA_DISCONNECTED && !(Key_GetCatcher( ) & KEYCATCH_CONSOLE ) ) {
return;
}
@ -704,7 +719,7 @@ void Con_DrawConsole( void ) {
Con_CheckResize ();
// if disconnected, render console full screen
if ( cls.state == CA_DISCONNECTED ) {
if ( clc.state == CA_DISCONNECTED ) {
if ( !( Key_GetCatcher( ) & (KEYCATCH_UI | KEYCATCH_CGAME)) ) {
Con_DrawSolidConsole( 1.0 );
return;
@ -715,7 +730,7 @@ void Con_DrawConsole( void ) {
Con_DrawSolidConsole( con.displayFrac );
} else {
// draw notify lines
if ( cls.state == CA_ACTIVE ) {
if ( clc.state == CA_ACTIVE ) {
Con_DrawNotify ();
}
}

View file

@ -251,13 +251,13 @@ void CL_cURL_BeginDownload( const char *localName, const char *remoteURL )
clc.downloadCURL = qcurl_easy_init();
if(!clc.downloadCURL) {
Com_Error(ERR_DROP, "CL_cURL_BeginDownload: qcurl_easy_init() "
"failed\n");
"failed");
return;
}
clc.download = FS_SV_FOpenFileWrite(clc.downloadTempName);
if(!clc.download) {
Com_Error(ERR_DROP, "CL_cURL_BeginDownload: failed to open "
"%s for writing\n", clc.downloadTempName);
"%s for writing", clc.downloadTempName);
return;
}
qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, clc.download);
@ -284,7 +284,7 @@ void CL_cURL_BeginDownload( const char *localName, const char *remoteURL )
qcurl_easy_cleanup(clc.downloadCURL);
clc.downloadCURL = NULL;
Com_Error(ERR_DROP, "CL_cURL_BeginDownload: qcurl_multi_init() "
"failed\n");
"failed");
return;
}
qcurl_multi_add_handle(clc.downloadCURLM, clc.downloadCURL);

View file

@ -640,7 +640,7 @@ void CL_CreateNewCommands( void ) {
int cmdNum;
// no need to create usercmds until we have a gamestate
if ( cls.state < CA_PRIMED ) {
if ( clc.state < CA_PRIMED ) {
return;
}
@ -677,7 +677,7 @@ qboolean CL_ReadyToSendPacket( void ) {
int delta;
// don't send anything if playing back a demo
if ( clc.demoplaying || cls.state == CA_CINEMATIC ) {
if ( clc.demoplaying || clc.state == CA_CINEMATIC ) {
return qfalse;
}
@ -689,8 +689,8 @@ qboolean CL_ReadyToSendPacket( void ) {
// if we don't have a valid gamestate yet, only send
// one packet a second
if ( cls.state != CA_ACTIVE &&
cls.state != CA_PRIMED &&
if ( clc.state != CA_ACTIVE &&
clc.state != CA_PRIMED &&
!*clc.downloadTempName &&
cls.realtime - clc.lastPacketSentTime < 1000 ) {
return qfalse;
@ -754,7 +754,7 @@ void CL_WritePacket( void ) {
int count, key;
// don't send anything if playing back a demo
if ( clc.demoplaying || cls.state == CA_CINEMATIC ) {
if ( clc.demoplaying || clc.state == CA_CINEMATIC ) {
return;
}
@ -949,7 +949,7 @@ Called every frame to builds and sends a command packet to the server.
*/
void CL_SendCmd( void ) {
// don't send any message if not connected
if ( cls.state < CA_CONNECTED ) {
if ( clc.state < CA_CONNECTED ) {
return;
}
@ -1047,3 +1047,77 @@ void CL_InitInput( void ) {
cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0);
cl_debugMove = Cvar_Get ("cl_debugMove", "0", 0);
}
/*
============
CL_ShutdownInput
============
*/
void CL_ShutdownInput(void)
{
Cmd_RemoveCommand("centerview");
Cmd_RemoveCommand("+moveup");
Cmd_RemoveCommand("-moveup");
Cmd_RemoveCommand("+movedown");
Cmd_RemoveCommand("-movedown");
Cmd_RemoveCommand("+left");
Cmd_RemoveCommand("-left");
Cmd_RemoveCommand("+right");
Cmd_RemoveCommand("-right");
Cmd_RemoveCommand("+forward");
Cmd_RemoveCommand("-forward");
Cmd_RemoveCommand("+back");
Cmd_RemoveCommand("-back");
Cmd_RemoveCommand("+lookup");
Cmd_RemoveCommand("-lookup");
Cmd_RemoveCommand("+lookdown");
Cmd_RemoveCommand("-lookdown");
Cmd_RemoveCommand("+strafe");
Cmd_RemoveCommand("-strafe");
Cmd_RemoveCommand("+moveleft");
Cmd_RemoveCommand("-moveleft");
Cmd_RemoveCommand("+moveright");
Cmd_RemoveCommand("-moveright");
Cmd_RemoveCommand("+speed");
Cmd_RemoveCommand("-speed");
Cmd_RemoveCommand("+attack");
Cmd_RemoveCommand("-attack");
Cmd_RemoveCommand("+button0");
Cmd_RemoveCommand("-button0");
Cmd_RemoveCommand("+button1");
Cmd_RemoveCommand("-button1");
Cmd_RemoveCommand("+button2");
Cmd_RemoveCommand("-button2");
Cmd_RemoveCommand("+button3");
Cmd_RemoveCommand("-button3");
Cmd_RemoveCommand("+button4");
Cmd_RemoveCommand("-button4");
Cmd_RemoveCommand("+button5");
Cmd_RemoveCommand("-button5");
Cmd_RemoveCommand("+button6");
Cmd_RemoveCommand("-button6");
Cmd_RemoveCommand("+button7");
Cmd_RemoveCommand("-button7");
Cmd_RemoveCommand("+button8");
Cmd_RemoveCommand("-button8");
Cmd_RemoveCommand("+button9");
Cmd_RemoveCommand("-button9");
Cmd_RemoveCommand("+button10");
Cmd_RemoveCommand("-button10");
Cmd_RemoveCommand("+button11");
Cmd_RemoveCommand("-button11");
Cmd_RemoveCommand("+button12");
Cmd_RemoveCommand("-button12");
Cmd_RemoveCommand("+button13");
Cmd_RemoveCommand("-button13");
Cmd_RemoveCommand("+button14");
Cmd_RemoveCommand("-button14");
Cmd_RemoveCommand("+mlook");
Cmd_RemoveCommand("-mlook");
#ifdef USE_VOIP
Cmd_RemoveCommand("+voiprecord");
Cmd_RemoveCommand("-voiprecord");
#endif
}

View file

@ -586,7 +586,7 @@ void Console_Key (int key) {
// enter finishes the line
if ( key == K_ENTER || key == K_KP_ENTER ) {
// if not in the game explicitly prepend a slash if needed
if ( cls.state != CA_ACTIVE &&
if ( clc.state != CA_ACTIVE &&
g_consoleField.buffer[0] &&
g_consoleField.buffer[0] != '\\' &&
g_consoleField.buffer[0] != '/' ) {
@ -625,7 +625,7 @@ void Console_Key (int key) {
CL_SaveConsoleHistory( );
if ( cls.state == CA_DISCONNECTED ) {
if ( clc.state == CA_DISCONNECTED ) {
SCR_UpdateScreen (); // force an update, because the command
} // may take some time
return;
@ -731,7 +731,7 @@ void Message_Key( int key ) {
if ( key == K_ENTER || key == K_KP_ENTER )
{
if ( chatField.buffer[0] && cls.state == CA_ACTIVE ) {
if ( chatField.buffer[0] && clc.state == CA_ACTIVE ) {
if (chat_playerNum != -1 )
Com_sprintf( buffer, sizeof( buffer ), "tell %i \"%s\"\n", chat_playerNum, chatField.buffer );
@ -1196,7 +1196,7 @@ void CL_KeyDownEvent( int key, unsigned time )
// keys can still be used for bound actions
if ( ( key < 128 || key == K_MOUSE1 ) &&
( clc.demoplaying || cls.state == CA_CINEMATIC ) && Key_GetCatcher( ) == 0 ) {
( clc.demoplaying || clc.state == CA_CINEMATIC ) && Key_GetCatcher( ) == 0 ) {
if (Cvar_VariableValue ("com_cameraMode") == 0) {
Cvar_Set ("nextdemo","");
@ -1220,10 +1220,10 @@ void CL_KeyDownEvent( int key, unsigned time )
}
if ( !( Key_GetCatcher( ) & KEYCATCH_UI ) ) {
if ( cls.state == CA_ACTIVE && !clc.demoplaying ) {
if ( clc.state == CA_ACTIVE && !clc.demoplaying ) {
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_INGAME );
}
else if ( cls.state != CA_DISCONNECTED ) {
else if ( clc.state != CA_DISCONNECTED ) {
CL_Disconnect_f();
S_StopAllSounds();
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
@ -1248,7 +1248,7 @@ void CL_KeyDownEvent( int key, unsigned time )
}
} else if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE ) {
Message_Key( key );
} else if ( cls.state == CA_DISCONNECTED ) {
} else if ( clc.state == CA_DISCONNECTED ) {
Console_Key( key );
} else {
// send the bound action
@ -1269,7 +1269,7 @@ void CL_KeyUpEvent( int key, unsigned time )
keys[key].repeats = 0;
keys[key].down = qfalse;
if (key != K_SCROLLOCK && key != K_KP_NUMLOCK && key != K_CAPSLOCK)
anykeydown--;
anykeydown--;
if (anykeydown < 0) {
anykeydown = 0;
@ -1285,7 +1285,7 @@ void CL_KeyUpEvent( int key, unsigned time )
// console mode and menu mode, to keep the character from continuing
// an action started before a mode switch.
//
if( cls.state != CA_DISCONNECTED )
if( clc.state != CA_DISCONNECTED )
CL_ParseBinding( key, qfalse, time );
if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) {
@ -1336,7 +1336,7 @@ void CL_CharEvent( int key ) {
{
Field_CharEvent( &chatField, key );
}
else if ( cls.state == CA_DISCONNECTED )
else if ( clc.state == CA_DISCONNECTED )
{
Field_CharEvent( &g_consoleField, key );
}

View file

@ -231,7 +231,7 @@ void CL_Voip_f( void )
const char *cmd = Cmd_Argv(1);
const char *reason = NULL;
if (cls.state != CA_ACTIVE)
if (clc.state != CA_ACTIVE)
reason = "Not connected to a server";
else if (!clc.speexInitialized)
reason = "Speex not initialized";
@ -329,7 +329,7 @@ void CL_CaptureVoip(void)
if (cl_voipSend->modified) {
qboolean dontCapture = qfalse;
if (cls.state != CA_ACTIVE)
if (clc.state != CA_ACTIVE)
dontCapture = qtrue; // not connected to a server.
else if (!cl_connectedToVoipServer)
dontCapture = qtrue; // server doesn't support VoIP.
@ -623,7 +623,7 @@ void CL_Record_f( void ) {
return;
}
if ( cls.state != CA_ACTIVE ) {
if ( clc.state != CA_ACTIVE ) {
Com_Printf ("You must be in a level to record.\n");
return;
}
@ -932,7 +932,7 @@ static void CL_CompleteDemoName( char *args, int argNum )
{
char demoExt[ 16 ];
Com_sprintf( demoExt, sizeof( demoExt ), ".dm_%d", PROTOCOL_VERSION );
Com_sprintf(demoExt, sizeof(demoExt), ".%s%d", DEMOEXT, com_protocol->integer);
Field_CompleteFilename( "demos", demoExt, qtrue, qtrue );
}
}
@ -966,7 +966,7 @@ void CL_PlayDemo_f( void ) {
CL_Disconnect( qtrue );
// check for an extension .DEMOEXT_?? (?? is protocol)
ext_test = Q_strrchr(arg, '.');
ext_test = strrchr(arg, '.');
if(ext_test && !Q_stricmpn(ext_test + 1, DEMOEXT, ARRAY_LEN(DEMOEXT) - 1))
{
@ -1009,12 +1009,12 @@ void CL_PlayDemo_f( void ) {
Con_Close();
cls.state = CA_CONNECTED;
clc.state = CA_CONNECTED;
clc.demoplaying = qtrue;
Q_strncpyz( cls.servername, Cmd_Argv(1), sizeof( cls.servername ) );
Q_strncpyz( clc.servername, Cmd_Argv(1), sizeof( clc.servername ) );
// read demo messages until connected
while ( cls.state >= CA_CONNECTED && cls.state < CA_PRIMED ) {
while ( clc.state >= CA_CONNECTED && clc.state < CA_PRIMED ) {
CL_ReadDemoMessage();
}
// don't get the first snapshot this frame, to prevent the long
@ -1022,6 +1022,7 @@ void CL_PlayDemo_f( void ) {
clc.firstDemoFrameSkipped = qfalse;
}
/*
====================
CL_StartDemoLoop
@ -1067,7 +1068,13 @@ void CL_NextDemo( void ) {
CL_ShutdownAll
=====================
*/
void CL_ShutdownAll(void) {
void CL_ShutdownAll(qboolean shutdownRef)
{
if(CL_VideoRecording())
CL_CloseAVI();
if(clc.demorecording)
CL_StopRecord_f();
#ifdef USE_CURL
CL_cURL_Shutdown();
@ -1080,9 +1087,10 @@ void CL_ShutdownAll(void) {
CL_ShutdownUI();
// shutdown the renderer
if ( re.Shutdown ) {
re.Shutdown( qfalse ); // don't destroy window or context
}
if(shutdownRef)
CL_ShutdownRef();
else if(re.Shutdown)
re.Shutdown(qfalse); // don't destroy window or context
cls.uiStarted = qfalse;
cls.cgameStarted = qfalse;
@ -1092,17 +1100,15 @@ void CL_ShutdownAll(void) {
/*
=================
CL_FlushMemory
CL_ClearMemory
Called by CL_MapLoading, CL_Connect_f, CL_PlayDemo_f, and CL_ParseGamestate the only
ways a client gets into a game
Also called by Com_Error
Called by Com_GameRestart
=================
*/
void CL_FlushMemory( void ) {
void CL_ClearMemory(qboolean shutdownRef)
{
// shutdown all the client stuff
CL_ShutdownAll();
CL_ShutdownAll(shutdownRef);
// if not running a server clear the whole hunk
if ( !com_sv_running->integer ) {
@ -1115,8 +1121,21 @@ void CL_FlushMemory( void ) {
// clear all the client data on the hunk
Hunk_ClearToMark();
}
}
CL_StartHunkUsers( qfalse );
/*
=================
CL_FlushMemory
Called by CL_MapLoading, CL_Connect_f, CL_PlayDemo_f, and CL_ParseGamestate the only
ways a client gets into a game
Also called by Com_Error
=================
*/
void CL_FlushMemory(void)
{
CL_ClearMemory(qfalse);
CL_StartHunkUsers(qfalse);
}
/*
@ -1130,7 +1149,7 @@ memory on the hunk from cgame, ui, and renderer
*/
void CL_MapLoading( void ) {
if ( com_dedicated->integer ) {
cls.state = CA_DISCONNECTED;
clc.state = CA_DISCONNECTED;
Key_SetCatcher( KEYCATCH_CONSOLE );
return;
}
@ -1143,8 +1162,8 @@ void CL_MapLoading( void ) {
Key_SetCatcher( 0 );
// if we are already connected to the local host, stay connected
if ( cls.state >= CA_CONNECTED && !Q_stricmp( cls.servername, "localhost" ) ) {
cls.state = CA_CONNECTED; // so the connect screen is drawn
if ( clc.state >= CA_CONNECTED && !Q_stricmp( clc.servername, "localhost" ) ) {
clc.state = CA_CONNECTED; // so the connect screen is drawn
Com_Memset( cls.updateInfoString, 0, sizeof( cls.updateInfoString ) );
Com_Memset( clc.serverMessage, 0, sizeof( clc.serverMessage ) );
Com_Memset( &cl.gameState, 0, sizeof( cl.gameState ) );
@ -1154,12 +1173,12 @@ void CL_MapLoading( void ) {
// clear nextmap so the cinematic shutdown doesn't execute it
Cvar_Set( "nextmap", "" );
CL_Disconnect( qtrue );
Q_strncpyz( cls.servername, "localhost", sizeof(cls.servername) );
cls.state = CA_CHALLENGING; // so the connect screen is drawn
Q_strncpyz( clc.servername, "localhost", sizeof(clc.servername) );
clc.state = CA_CHALLENGING; // so the connect screen is drawn
Key_SetCatcher( 0 );
SCR_UpdateScreen();
clc.connectTime = -RETRANSMIT_TIMEOUT;
NET_StringToAdr( cls.servername, &clc.serverAddress, NA_UNSPEC);
NET_StringToAdr( clc.servername, &clc.serverAddress, NA_UNSPEC);
// we don't need a challenge on the localhost
CL_CheckForResend();
@ -1202,6 +1221,16 @@ static void CL_UpdateGUID( const char *prefix, int prefix_len )
prefix, prefix_len ) );
}
static void CL_OldGame(void)
{
if(cls.oldGameSet)
{
// change back to previous fs_game
cls.oldGameSet = qfalse;
Cvar_Set("fs_game", cls.oldGame);
Com_GameRestart(0, qtrue);
}
}
/*
=====================
@ -1276,7 +1305,7 @@ void CL_Disconnect( qboolean showMainMenu ) {
// send a disconnect message to the server
// send it a few times in case one is dropped
if ( cls.state >= CA_CONNECTED ) {
if ( clc.state >= CA_CONNECTED ) {
CL_AddReliableCommand("disconnect", qtrue);
CL_WritePacket();
CL_WritePacket();
@ -1291,7 +1320,7 @@ void CL_Disconnect( qboolean showMainMenu ) {
// wipe the client connection
Com_Memset( &clc, 0, sizeof( clc ) );
cls.state = CA_DISCONNECTED;
clc.state = CA_DISCONNECTED;
// allow cheats locally
Cvar_Set( "sv_cheats", "1" );
@ -1310,7 +1339,9 @@ void CL_Disconnect( qboolean showMainMenu ) {
SCR_UpdateScreen( );
CL_CloseAVI( );
}
CL_UpdateGUID( NULL, 0 );
CL_OldGame();
}
@ -1333,7 +1364,7 @@ void CL_ForwardCommandToServer( const char *string ) {
return;
}
if ( clc.demoplaying || cls.state < CA_CONNECTED || cmd[0] == '+' ) {
if ( clc.demoplaying || clc.state < CA_CONNECTED || cmd[0] == '+' ) {
Com_Printf ("Unknown command \"%s" S_COLOR_WHITE "\"\n", cmd);
return;
}
@ -1476,7 +1507,7 @@ CL_ForwardToServer_f
==================
*/
void CL_ForwardToServer_f( void ) {
if ( cls.state != CA_ACTIVE || clc.demoplaying ) {
if ( clc.state != CA_ACTIVE || clc.demoplaying ) {
Com_Printf ("Not connected to a server.\n");
return;
}
@ -1495,7 +1526,7 @@ CL_Disconnect_f
void CL_Disconnect_f( void ) {
SCR_StopCinematic();
Cvar_Set("ui_singlePlayerActive", "0");
if ( cls.state != CA_DISCONNECTED && cls.state != CA_CINEMATIC ) {
if ( clc.state != CA_DISCONNECTED && clc.state != CA_CINEMATIC ) {
Com_Error (ERR_DISCONNECT, "Disconnected from server");
}
}
@ -1508,12 +1539,12 @@ CL_Reconnect_f
================
*/
void CL_Reconnect_f( void ) {
if ( !strlen( cls.servername ) || !strcmp( cls.servername, "localhost" ) ) {
if ( !strlen( clc.servername ) || !strcmp( clc.servername, "localhost" ) ) {
Com_Printf( "Can't reconnect to localhost.\n" );
return;
}
Cvar_Set("ui_singlePlayerActive", "0");
Cbuf_AddText( va("connect %s\n", cls.servername ) );
Cbuf_AddText( va("connect %s\n", clc.servername ) );
}
/*
@ -1567,11 +1598,11 @@ void CL_Connect_f( void ) {
CL_Disconnect( qtrue );
Con_Close();
Q_strncpyz( cls.servername, server, sizeof(cls.servername) );
Q_strncpyz( clc.servername, server, sizeof(clc.servername) );
if (!NET_StringToAdr(cls.servername, &clc.serverAddress, family) ) {
if (!NET_StringToAdr(clc.servername, &clc.serverAddress, family) ) {
Com_Printf ("Bad server address\n");
cls.state = CA_DISCONNECTED;
clc.state = CA_DISCONNECTED;
return;
}
if (clc.serverAddress.port == 0) {
@ -1580,7 +1611,7 @@ void CL_Connect_f( void ) {
serverString = NET_AdrToStringwPort(clc.serverAddress);
Com_Printf( "%s resolved to %s\n", cls.servername, serverString);
Com_Printf( "%s resolved to %s\n", clc.servername, serverString);
if( cl_guidServerUniq->integer )
CL_UpdateGUID( serverString, strlen( serverString ) );
@ -1590,10 +1621,10 @@ void CL_Connect_f( void ) {
// if we aren't playing on a lan, we need to authenticate
// with the cd key
if(NET_IsLocalAddress(clc.serverAddress))
cls.state = CA_CHALLENGING;
clc.state = CA_CHALLENGING;
else
{
cls.state = CA_CONNECTING;
clc.state = CA_CONNECTING;
// Set a client challenge number that ideally is mirrored back by the server.
clc.challenge = ((rand() << 16) ^ rand()) ^ Com_Milliseconds();
@ -1658,7 +1689,7 @@ void CL_Rcon_f( void ) {
// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=543
Q_strcat (message, MAX_RCON_MESSAGE, Cmd_Cmd()+5);
if ( cls.state >= CA_CONNECTED ) {
if ( clc.state >= CA_CONNECTED ) {
to = clc.netchan.remoteAddress;
} else {
if (!strlen(rconAddress->string)) {
@ -1722,49 +1753,55 @@ void CL_Vid_Restart_f( void ) {
// don't let them loop during the restart
S_StopAllSounds();
// shutdown the UI
CL_ShutdownUI();
// shutdown the CGame
CL_ShutdownCGame();
// shutdown the renderer and clear the renderer interface
CL_ShutdownRef();
// client is no longer pure untill new checksums are sent
CL_ResetPureClientAtServer();
// clear pak references
FS_ClearPakReferences( FS_UI_REF | FS_CGAME_REF );
// reinitialize the filesystem if the game directory or checksum has changed
FS_ConditionalRestart( clc.checksumFeed );
cls.rendererStarted = qfalse;
cls.uiStarted = qfalse;
cls.cgameStarted = qfalse;
cls.soundRegistered = qfalse;
if(!FS_ConditionalRestart(clc.checksumFeed, qtrue))
{
// if not running a server clear the whole hunk
if(com_sv_running->integer)
{
// clear all the client data on the hunk
Hunk_ClearToMark();
}
else
{
// clear the whole hunk
Hunk_Clear();
}
// shutdown the UI
CL_ShutdownUI();
// shutdown the CGame
CL_ShutdownCGame();
// shutdown the renderer and clear the renderer interface
CL_ShutdownRef();
// client is no longer pure untill new checksums are sent
CL_ResetPureClientAtServer();
// clear pak references
FS_ClearPakReferences( FS_UI_REF | FS_CGAME_REF );
// reinitialize the filesystem if the game directory or checksum has changed
// unpause so the cgame definately gets a snapshot and renders a frame
Cvar_Set( "cl_paused", "0" );
cls.rendererStarted = qfalse;
cls.uiStarted = qfalse;
cls.cgameStarted = qfalse;
cls.soundRegistered = qfalse;
// if not running a server clear the whole hunk
if ( !com_sv_running->integer ) {
// clear the whole hunk
Hunk_Clear();
}
else {
// clear all the client data on the hunk
Hunk_ClearToMark();
}
// unpause so the cgame definately gets a snapshot and renders a frame
Cvar_Set("cl_paused", "0");
// initialize the renderer interface
CL_InitRef();
// initialize the renderer interface
CL_InitRef();
// startup all the client stuff
CL_StartHunkUsers( qfalse );
// startup all the client stuff
CL_StartHunkUsers(qfalse);
// start the cgame if connected
if ( cls.state > CA_CONNECTED && cls.state != CA_CINEMATIC ) {
cls.cgameStarted = qtrue;
CL_InitCGame();
// send pure checksums
CL_SendPureChecksums();
// start the cgame if connected
if(clc.state > CA_CONNECTED && clc.state != CA_CINEMATIC)
{
cls.cgameStarted = qtrue;
CL_InitCGame();
// send pure checksums
CL_SendPureChecksums();
}
}
}
@ -1775,10 +1812,10 @@ CL_Snd_Restart
Restart the sound subsystem
=================
*/
void CL_Snd_Restart(void)
void CL_Snd_Shutdown(void)
{
S_Shutdown();
S_Init();
cls.soundStarted = qfalse;
}
/*
@ -1792,7 +1829,8 @@ handles will be invalid
*/
void CL_Snd_Restart_f(void)
{
CL_Snd_Restart();
CL_Snd_Shutdown();
// sound will be reinitialized by vid_restart
CL_Vid_Restart_f();
}
@ -1824,7 +1862,7 @@ void CL_Configstrings_f( void ) {
int i;
int ofs;
if ( cls.state != CA_ACTIVE ) {
if ( clc.state != CA_ACTIVE ) {
Com_Printf( "Not connected to a server.\n");
return;
}
@ -1845,8 +1883,8 @@ CL_Clientinfo_f
*/
void CL_Clientinfo_f( void ) {
Com_Printf( "--------- Client Information ---------\n" );
Com_Printf( "state: %i\n", cls.state );
Com_Printf( "Server: %s\n", cls.servername );
Com_Printf( "state: %i\n", clc.state );
Com_Printf( "Server: %s\n", clc.servername );
Com_Printf ("User info settings:\n");
Info_Print( Cvar_InfoString( CVAR_USERINFO ) );
Com_Printf( "--------------------------------------\n" );
@ -1896,14 +1934,14 @@ void CL_DownloadsComplete( void ) {
}
// let the client game init and load data
cls.state = CA_LOADING;
clc.state = CA_LOADING;
// Pump the loop, this may change gamestate!
Com_EventLoop();
// if the gamestate was changed by calling Com_EventLoop
// then we loaded everything already and we don't want to do it again.
if ( cls.state != CA_LOADING ) {
if ( clc.state != CA_LOADING ) {
return;
}
@ -2089,7 +2127,7 @@ void CL_InitDownloads(void) {
if ( *clc.downloadList ) {
// if autodownloading is not enabled on the server
cls.state = CA_CONNECTED;
clc.state = CA_CONNECTED;
*clc.downloadTempName = *clc.downloadName = 0;
Cvar_Set( "cl_downloadName", "" );
@ -2121,7 +2159,7 @@ void CL_CheckForResend( void ) {
}
// resend if we haven't gotten a reply yet
if ( cls.state != CA_CONNECTING && cls.state != CA_CHALLENGING ) {
if ( clc.state != CA_CONNECTING && clc.state != CA_CHALLENGING ) {
return;
}
@ -2133,7 +2171,7 @@ void CL_CheckForResend( void ) {
clc.connectPacketCount++;
switch ( cls.state ) {
switch ( clc.state ) {
case CA_CONNECTING:
// requesting a challenge .. IPv6 users always get in as authorize server supports no ipv6.
#ifndef STANDALONE
@ -2175,7 +2213,7 @@ void CL_CheckForResend( void ) {
break;
default:
Com_Error( ERR_FATAL, "CL_CheckForResend: bad cls.state" );
Com_Error( ERR_FATAL, "CL_CheckForResend: bad clc.state" );
}
}
@ -2190,7 +2228,7 @@ to the client so it doesn't have to wait for the full timeout period.
===================
*/
void CL_DisconnectPacket( netadr_t from ) {
if ( cls.state < CA_AUTHORIZING ) {
if ( clc.state < CA_AUTHORIZING ) {
return;
}
@ -2408,7 +2446,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
// challenge from the server we are connecting to
if (!Q_stricmp(c, "challengeResponse"))
{
if (cls.state != CA_CONNECTING)
if (clc.state != CA_CONNECTING)
{
Com_DPrintf("Unwanted challenge response received. Ignored.\n");
return;
@ -2431,7 +2469,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
// start sending challenge response instead of challenge request packets
clc.challenge = atoi(Cmd_Argv(1));
cls.state = CA_CHALLENGING;
clc.state = CA_CHALLENGING;
clc.connectPacketCount = 0;
clc.connectTime = -99999;
@ -2444,11 +2482,11 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
// server connection
if ( !Q_stricmp(c, "connectResponse") ) {
if ( cls.state >= CA_CONNECTED ) {
if ( clc.state >= CA_CONNECTED ) {
Com_Printf ("Dup connect received. Ignored.\n");
return;
}
if ( cls.state != CA_CHALLENGING ) {
if ( clc.state != CA_CHALLENGING ) {
Com_Printf ("connectResponse packet while not connecting. Ignored.\n");
return;
}
@ -2457,7 +2495,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
return;
}
Netchan_Setup (NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) );
cls.state = CA_CONNECTED;
clc.state = CA_CONNECTED;
clc.lastPacketSentTime = -9999; // send first packet immediately
return;
}
@ -2540,7 +2578,7 @@ void CL_PacketEvent( netadr_t from, msg_t *msg ) {
return;
}
if ( cls.state < CA_CONNECTED ) {
if ( clc.state < CA_CONNECTED ) {
return; // can't be a valid sequenced packet
}
@ -2594,7 +2632,7 @@ void CL_CheckTimeout( void ) {
// check timeout
//
if ( ( !CL_CheckPaused() || !sv_paused->integer )
&& cls.state >= CA_CONNECTED && cls.state != CA_CINEMATIC
&& clc.state >= CA_CONNECTED && clc.state != CA_CINEMATIC
&& cls.realtime - clc.lastPacketTime > cl_timeout->value*1000) {
if (++cl.timeoutcount > 5) { // timeoutcount saves debugger
Com_Printf ("\nServer connection timed out.\n");
@ -2633,7 +2671,7 @@ CL_CheckUserinfo
*/
void CL_CheckUserinfo( void ) {
// don't add reliable commands when not yet connected
if(cls.state < CA_CHALLENGING)
if(clc.state < CA_CONNECTED)
return;
// don't overflow the reliable command buffer when paused
@ -2664,7 +2702,7 @@ void CL_Frame ( int msec ) {
if(clc.downloadCURLM) {
CL_cURL_PerformDownload();
// we can't process frames normally when in disconnected
// download mode since the ui vm expects cls.state to be
// download mode since the ui vm expects clc.state to be
// CA_CONNECTED
if(clc.cURLDisconnected) {
cls.realFrametime = msec;
@ -2683,7 +2721,7 @@ void CL_Frame ( int msec ) {
// bring up the cd error dialog if needed
cls.cddialog = qfalse;
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_NEED_CD );
} else if ( cls.state == CA_DISCONNECTED && !( Key_GetCatcher( ) & KEYCATCH_UI )
} else if ( clc.state == CA_DISCONNECTED && !( Key_GetCatcher( ) & KEYCATCH_UI )
&& !com_sv_running->integer && uivm ) {
// if disconnected, bring up the menu
S_StopAllSounds();
@ -2693,7 +2731,7 @@ void CL_Frame ( int msec ) {
// if recording an avi, lock to a fixed fps
if ( CL_VideoRecording( ) && cl_aviFrameRate->integer && msec) {
// save the current screen
if ( cls.state == CA_ACTIVE || cl_forceavidemo->integer) {
if ( clc.state == CA_ACTIVE || cl_forceavidemo->integer) {
CL_TakeVideoFrame( );
// fixed time for next frame'
@ -2705,7 +2743,7 @@ void CL_Frame ( int msec ) {
}
if( cl_autoRecordDemo->integer ) {
if( cls.state == CA_ACTIVE && !clc.demorecording && !clc.demoplaying ) {
if( clc.state == CA_ACTIVE && !clc.demorecording && !clc.demoplaying ) {
// If not recording a demo, and we should be, start one
qtime_t now;
char *nowString;
@ -2722,7 +2760,7 @@ void CL_Frame ( int msec ) {
now.tm_min,
now.tm_sec );
Q_strncpyz( serverName, cls.servername, MAX_OSPATH );
Q_strncpyz( serverName, clc.servername, MAX_OSPATH );
// Replace the ":" in the address as it is not a valid
// file name character
p = strstr( serverName, ":" );
@ -2736,7 +2774,7 @@ void CL_Frame ( int msec ) {
Cbuf_ExecuteText( EXEC_NOW,
va( "record %s-%s-%s", nowString, serverName, mapName ) );
}
else if( cls.state != CA_ACTIVE && clc.demorecording ) {
else if( clc.state != CA_ACTIVE && clc.demorecording ) {
// Recording, but not CA_ACTIVE, so stop recording
CL_StopRecord_f( );
}
@ -3117,9 +3155,12 @@ void CL_Init( void ) {
Con_Init ();
CL_ClearState ();
cls.state = CA_DISCONNECTED; // no longer CA_UNINITIALIZED
if(!com_fullyInitialized)
{
CL_ClearState();
clc.state = CA_DISCONNECTED; // no longer CA_UNINITIALIZED
cls.oldGameSet = qfalse;
}
cls.realtime = 0;
@ -3332,7 +3373,8 @@ CL_Shutdown
===============
*/
void CL_Shutdown( char *finalmsg ) {
void CL_Shutdown(char *finalmsg, qboolean disconnect)
{
static qboolean recursive = qfalse;
// check whether the client is running at all.
@ -3347,16 +3389,15 @@ void CL_Shutdown( char *finalmsg ) {
}
recursive = qtrue;
CL_Disconnect( qtrue );
S_Shutdown();
CL_ShutdownRef();
if(disconnect)
CL_Disconnect(qtrue);
CL_ShutdownUI();
CL_ClearMemory(qtrue);
CL_Snd_Shutdown();
Cmd_RemoveCommand ("cmd");
Cmd_RemoveCommand ("configstrings");
Cmd_RemoveCommand ("userinfo");
Cmd_RemoveCommand ("clientinfo");
Cmd_RemoveCommand ("snd_restart");
Cmd_RemoveCommand ("vid_restart");
Cmd_RemoveCommand ("disconnect");
@ -3365,15 +3406,22 @@ void CL_Shutdown( char *finalmsg ) {
Cmd_RemoveCommand ("cinematic");
Cmd_RemoveCommand ("stoprecord");
Cmd_RemoveCommand ("connect");
Cmd_RemoveCommand ("reconnect");
Cmd_RemoveCommand ("localservers");
Cmd_RemoveCommand ("globalservers");
Cmd_RemoveCommand ("rcon");
Cmd_RemoveCommand ("ping");
Cmd_RemoveCommand ("serverstatus");
Cmd_RemoveCommand ("showip");
Cmd_RemoveCommand ("fs_openedList");
Cmd_RemoveCommand ("fs_referencedList");
Cmd_RemoveCommand ("model");
Cmd_RemoveCommand ("video");
Cmd_RemoveCommand ("stopvideo");
Cmd_RemoveCommand ("minimize");
CL_ShutdownInput();
Con_Shutdown();
Cvar_Set( "cl_running", "0" );
@ -3399,6 +3447,8 @@ static void CL_SetServerInfo(serverInfo_t *server, const char *info, int ping) {
server->minPing = atoi(Info_ValueForKey(info, "minping"));
server->maxPing = atoi(Info_ValueForKey(info, "maxping"));
server->punkbuster = atoi(Info_ValueForKey(info, "punkbuster"));
server->g_humanplayers = atoi(Info_ValueForKey(info, "g_humanplayers"));
server->g_needpass = atoi(Info_ValueForKey(info, "g_needpass"));
}
server->ping = ping;
}
@ -3517,6 +3567,8 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) {
cls.localServers[i].gameType = 0;
cls.localServers[i].netType = from.type;
cls.localServers[i].punkbuster = 0;
cls.localServers[i].g_humanplayers = 0;
cls.localServers[i].g_needpass = 0;
Q_strncpyz( info, MSG_ReadString( msg ), MAX_INFO_STRING );
if (strlen(info)) {
@ -3812,17 +3864,14 @@ void CL_GlobalServers_f( void ) {
if(v4enabled)
{
Com_sprintf(command, sizeof(command), "getserversExt %s %s ipv6",
Com_sprintf(command, sizeof(command), "getserversExt %s %s",
cl_gamename->string, Cmd_Argv(2));
}
else
{
Com_sprintf(command, sizeof(command), "getserversExt %s %s",
Com_sprintf(command, sizeof(command), "getserversExt %s %s ipv6",
cl_gamename->string, Cmd_Argv(2));
}
// TODO: test if we only have an IPv6 connection. If it's the case,
// request IPv6 servers only by appending " ipv6" to the command
}
else
Com_sprintf(command, sizeof(command), "getservers %s", Cmd_Argv(2));
@ -4162,7 +4211,7 @@ void CL_ServerStatus_f(void) {
if ( argc != 2 && argc != 3 )
{
if (cls.state != CA_ACTIVE || clc.demoplaying)
if (clc.state != CA_ACTIVE || clc.demoplaying)
{
Com_Printf ("Not connected to a server.\n");
Com_Printf( "usage: serverstatus [-4|-6] server\n");

View file

@ -265,7 +265,7 @@ void CL_ParseSnapshot( msg_t *msg ) {
if(len > sizeof(newSnap.areamask))
{
Com_Error (ERR_DROP,"CL_ParseSnapshot: Invalid size %d for areamask.", len);
Com_Error (ERR_DROP,"CL_ParseSnapshot: Invalid size %d for areamask", len);
return;
}
@ -463,6 +463,7 @@ void CL_ParseGamestate( msg_t *msg ) {
entityState_t nullstate;
int cmd;
char *s;
char oldGame[MAX_QPATH];
Con_Close();
@ -518,6 +519,9 @@ void CL_ParseGamestate( msg_t *msg ) {
// read the checksum feed
clc.checksumFeed = MSG_ReadLong( msg );
// save old gamedir
Cvar_VariableStringBuffer("fs_game", oldGame, sizeof(oldGame));
// parse useful values out of CS_SERVERINFO
CL_ParseServerInfo();
@ -529,7 +533,11 @@ void CL_ParseGamestate( msg_t *msg ) {
CL_StopRecord_f();
// reinitialize the filesystem if the game directory has changed
FS_ConditionalRestart( clc.checksumFeed );
if(FS_ConditionalRestart(clc.checksumFeed, qfalse) && !cls.oldGameSet)
{
cls.oldGameSet = qtrue;
Q_strncpyz(cls.oldGame, oldGame, sizeof(cls.oldGame));
}
// This used to call CL_StartHunkUsers, but now we enter the download state before loading the
// cgame
@ -580,7 +588,7 @@ void CL_ParseDownload ( msg_t *msg ) {
size = MSG_ReadShort ( msg );
if (size < 0 || size > sizeof(data))
{
Com_Error(ERR_DROP, "CL_ParseDownload: Invalid size %d for download chunk.", size);
Com_Error(ERR_DROP, "CL_ParseDownload: Invalid size %d for download chunk", size);
return;
}
@ -885,7 +893,7 @@ void CL_ParseServerMessage( msg_t *msg ) {
// other commands
switch ( cmd ) {
default:
Com_Error (ERR_DROP,"CL_ParseServerMessage: Illegible server message\n");
Com_Error (ERR_DROP,"CL_ParseServerMessage: Illegible server message");
break;
case svc_nop:
break;

View file

@ -360,7 +360,7 @@ void SCR_DrawVoipMeter( void ) {
return; // player doesn't want to show meter at all.
else if (!cl_voipSend->integer)
return; // not recording at the moment.
else if (cls.state != CA_ACTIVE)
else if (clc.state != CA_ACTIVE)
return; // not connected to a server.
else if (!cl_connectedToVoipServer)
return; // server doesn't support VoIP.
@ -480,11 +480,15 @@ This will be called twice if rendering in stereo mode
==================
*/
void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
qboolean uiFullscreen;
re.BeginFrame( stereoFrame );
uiFullscreen = (uivm && VM_Call( uivm, UI_IS_FULLSCREEN ));
// wide aspect ratio screens need to have the sides cleared
// unless they are displaying game renderings
if ( cls.state != CA_ACTIVE && cls.state != CA_CINEMATIC ) {
if ( uiFullscreen || (clc.state != CA_ACTIVE && clc.state != CA_CINEMATIC) ) {
if ( cls.glconfig.vidWidth * 480 > cls.glconfig.vidHeight * 640 ) {
re.SetColor( g_color_table[0] );
re.DrawStretchPic( 0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight, 0, 0, 0, 0, cls.whiteShader );
@ -494,10 +498,10 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
// if the menu is going to cover the entire screen, we
// don't need to render anything under it
if ( uivm && !VM_Call( uivm, UI_IS_FULLSCREEN )) {
switch( cls.state ) {
if ( uivm && !uiFullscreen ) {
switch( clc.state ) {
default:
Com_Error( ERR_FATAL, "SCR_DrawScreenField: bad cls.state" );
Com_Error( ERR_FATAL, "SCR_DrawScreenField: bad clc.state" );
break;
case CA_CINEMATIC:
SCR_DrawCinematic();

View file

@ -35,8 +35,8 @@ GetClientState
*/
static void GetClientState( uiClientState_t *state ) {
state->connectPacketCount = clc.connectPacketCount;
state->connState = cls.state;
Q_strncpyz( state->servername, cls.servername, sizeof( state->servername ) );
state->connState = clc.state;
Q_strncpyz( state->servername, clc.servername, sizeof( state->servername ) );
Q_strncpyz( state->updateInfoString, cls.updateInfoString, sizeof( state->updateInfoString ) );
Q_strncpyz( state->messageString, clc.serverMessage, sizeof( state->messageString ) );
state->clientNum = cl.snap.ps.clientNum;
@ -298,6 +298,8 @@ static void LAN_GetServerInfo( int source, int n, char *buf, int buflen ) {
Info_SetValueForKey( info, "nettype", va("%i",server->netType));
Info_SetValueForKey( info, "addr", NET_AdrToStringwPort(server->adr));
Info_SetValueForKey( info, "punkbuster", va("%i", server->punkbuster));
Info_SetValueForKey( info, "g_needpass", va("%i", server->g_needpass));
Info_SetValueForKey( info, "g_humanplayers", va("%i", server->g_humanplayers));
Q_strncpyz(buf, info, buflen);
} else {
if (buf) {
@ -1114,7 +1116,7 @@ void CL_InitUI( void ) {
if (v == UI_OLD_API_VERSION) {
// Com_Printf(S_COLOR_YELLOW "WARNING: loading old Quake III Arena User Interface version %d\n", v );
// init for this gamestate
VM_Call( uivm, UI_INIT, (cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE));
VM_Call( uivm, UI_INIT, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE));
}
else if (v != UI_API_VERSION) {
Com_Error( ERR_DROP, "User Interface is version %d, expected %d", v, UI_API_VERSION );
@ -1122,12 +1124,8 @@ void CL_InitUI( void ) {
}
else {
// init for this gamestate
VM_Call( uivm, UI_INIT, (cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE) );
VM_Call( uivm, UI_INIT, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE) );
}
// reset any CVAR_CHEAT cvars registered by ui
if ( !clc.demoplaying && !cl_connectedToCheatServer )
Cvar_SetCheatState();
}
#ifndef STANDALONE

View file

@ -162,10 +162,13 @@ demo through a file.
typedef struct {
connstate_t state; // connection status
int clientNum;
int lastPacketSentTime; // for retransmits during connection
int lastPacketTime; // for timeouts
char servername[MAX_OSPATH]; // name of server from original connect (used by reconnect)
netadr_t serverAddress;
int connectTime; // for connection retransmits
int connectPacketCount; // for display on connection dialog
@ -296,15 +299,13 @@ typedef struct {
int ping;
qboolean visible;
int punkbuster;
int g_humanplayers;
int g_needpass;
} serverInfo_t;
typedef struct {
connstate_t state; // connection status
qboolean cddialog; // bring up the cd needed dialog next frame
char servername[MAX_OSPATH]; // name of server from original connect (used by reconnect)
// when the server clears the hunk, all of these must be restarted
qboolean rendererStarted;
qboolean soundStarted;
@ -331,6 +332,9 @@ typedef struct {
serverInfo_t favoriteServers[MAX_OTHER_SERVERS];
int pingUpdateSource; // source currently pinging or updating
char oldGame[MAX_QPATH];
qboolean oldGameSet;
// update server info
netadr_t updateServer;
@ -440,8 +444,6 @@ extern cvar_t *cl_voip;
//
void CL_Init (void);
void CL_FlushMemory(void);
void CL_ShutdownAll(void);
void CL_AddReliableCommand(const char *cmd, qboolean isDisconnectCmd);
void CL_StartHunkUsers( qboolean rendererOnly );
@ -489,7 +491,8 @@ extern kbutton_t in_speed;
extern kbutton_t in_voiprecord;
#endif
void CL_InitInput (void);
void CL_InitInput(void);
void CL_ShutdownInput(void);
void CL_SendCmd (void);
void CL_ClearState (void);
void CL_ReadPackets (void);
@ -533,7 +536,8 @@ qboolean CL_UpdateVisiblePings_f( int source );
void Con_DrawCharacter (int cx, int line, int num);
void Con_CheckResize (void);
void Con_Init (void);
void Con_Init(void);
void Con_Shutdown(void);
void Con_Clear_f (void);
void Con_ToggleConsole_f (void);
void Con_DrawNotify (void);

View file

@ -28,71 +28,90 @@ static snd_codec_t *codecs;
/*
=================
S_FileExtension
S_CodecGetSound
Opens/loads a sound, tries codec based on the sound's file extension
then tries all supported codecs.
=================
*/
static char *S_FileExtension(const char *fni)
static void *S_CodecGetSound(const char *filename, snd_info_t *info)
{
// we should search from the ending to the last '/'
snd_codec_t *codec;
snd_codec_t *orgCodec = NULL;
qboolean orgNameFailed = qfalse;
char localName[ MAX_QPATH ];
const char *ext;
char altName[ MAX_QPATH ];
void *rtn = NULL;
char *fn = (char *) fni + strlen(fni) - 1;
char *eptr = NULL;
Q_strncpyz(localName, filename, MAX_QPATH);
while(*fn != '/' && fn != fni)
ext = COM_GetExtension(localName);
if( *ext )
{
if(*fn == '.')
// Look for the correct loader and use it
for( codec = codecs; codec; codec = codec->next )
{
eptr = fn;
break;
}
fn--;
}
return eptr;
}
/*
=================
S_FindCodecForFile
Select an appropriate codec for a file based on its extension
=================
*/
static snd_codec_t *S_FindCodecForFile(const char *filename)
{
char *ext = S_FileExtension(filename);
snd_codec_t *codec = codecs;
if(!ext)
{
// No extension - auto-detect
while(codec)
{
char fn[MAX_QPATH];
// there is no extension so we do not need to subtract 4 chars
Q_strncpyz(fn, filename, MAX_QPATH);
COM_DefaultExtension(fn, MAX_QPATH, codec->ext);
// Check it exists
if(FS_ReadFile(fn, NULL) != -1)
return codec;
// Nope. Next!
codec = codec->next;
if( !Q_stricmp( ext, codec->ext ) )
{
// Load
if( info )
rtn = codec->load(localName, info);
else
rtn = codec->open(localName);
break;
}
}
// Nothin'
return NULL;
// A loader was found
if( codec )
{
if( !rtn )
{
// Loader failed, most likely because the file isn't there;
// try again without the extension
orgNameFailed = qtrue;
orgCodec = codec;
COM_StripExtension( filename, localName, MAX_QPATH );
}
else
{
// Something loaded
return rtn;
}
}
}
while(codec)
// Try and find a suitable match using all
// the sound codecs supported
for( codec = codecs; codec; codec = codec->next )
{
if(!Q_stricmp(ext, codec->ext))
return codec;
codec = codec->next;
if( codec == orgCodec )
continue;
Com_sprintf( altName, sizeof (altName), "%s.%s", localName, codec->ext );
// Load
if( info )
rtn = codec->load(altName, info);
else
rtn = codec->open(altName);
if( rtn )
{
if( orgNameFailed )
{
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s not present, using %s instead\n",
filename, altName );
}
return rtn;
}
}
Com_Printf(S_COLOR_YELLOW "WARNING: Failed to %s sound %s!\n", info ? "load" : "open", filename);
return NULL;
}
@ -104,10 +123,13 @@ S_CodecInit
void S_CodecInit()
{
codecs = NULL;
S_CodecRegister(&wav_codec);
#ifdef USE_CODEC_VORBIS
S_CodecRegister(&ogg_codec);
#endif
// Register wav codec last so that it is always tried first when a file extension was not found
S_CodecRegister(&wav_codec);
}
/*
@ -138,20 +160,7 @@ S_CodecLoad
*/
void *S_CodecLoad(const char *filename, snd_info_t *info)
{
snd_codec_t *codec;
char fn[MAX_QPATH];
codec = S_FindCodecForFile(filename);
if(!codec)
{
Com_Printf("Unknown extension for %s\n", filename);
return NULL;
}
strncpy(fn, filename, sizeof(fn));
COM_DefaultExtension(fn, sizeof(fn), codec->ext);
return codec->load(fn, info);
return S_CodecGetSound(filename, info);
}
/*
@ -161,20 +170,7 @@ S_CodecOpenStream
*/
snd_stream_t *S_CodecOpenStream(const char *filename)
{
snd_codec_t *codec;
char fn[MAX_QPATH];
codec = S_FindCodecForFile(filename);
if(!codec)
{
Com_Printf("Unknown extension for %s\n", filename);
return NULL;
}
strncpy(fn, filename, sizeof(fn));
COM_DefaultExtension(fn, sizeof(fn), codec->ext);
return codec->open(fn);
return S_CodecGetSound(filename, NULL);
}
void S_CodecCloseStream(snd_stream_t *stream)
@ -205,7 +201,7 @@ snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec)
length = FS_FOpenFileRead(filename, &hnd, qtrue);
if(!hnd)
{
Com_Printf("Can't read sound file %s\n", filename);
Com_DPrintf("Can't read sound file %s\n", filename);
return NULL;
}

View file

@ -41,7 +41,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// Q3 OGG codec
snd_codec_t ogg_codec =
{
".ogg",
"ogg",
S_OGG_CodecLoad,
S_OGG_CodecOpenStream,
S_OGG_CodecReadStream,
@ -450,7 +450,7 @@ void *S_OGG_CodecLoad(const char *filename, snd_info_t *info)
// allocate a buffer
// this buffer must be free-ed by the caller of this function
buffer = Z_Malloc(info->size);
buffer = Hunk_AllocateTempMemory(info->size);
if(!buffer)
{
S_OGG_CodecCloseStream(stream);
@ -464,7 +464,7 @@ void *S_OGG_CodecLoad(const char *filename, snd_info_t *info)
// we don't even have read a single byte
if(bytesRead <= 0)
{
Z_Free(buffer);
Hunk_FreeTempMemory(buffer);
S_OGG_CodecCloseStream(stream);
return NULL;

View file

@ -183,7 +183,7 @@ static qboolean S_ReadRIFFHeader(fileHandle_t file, snd_info_t *info)
// WAV codec
snd_codec_t wav_codec =
{
".wav",
"wav",
S_WAV_CodecLoad,
S_WAV_CodecOpenStream,
S_WAV_CodecReadStream,
@ -205,8 +205,6 @@ void *S_WAV_CodecLoad(const char *filename, snd_info_t *info)
FS_FOpenFileRead(filename, &file, qtrue);
if(!file)
{
Com_Printf( S_COLOR_RED "ERROR: Could not open \"%s\"\n",
filename);
return NULL;
}
@ -220,7 +218,7 @@ void *S_WAV_CodecLoad(const char *filename, snd_info_t *info)
}
// Allocate some memory
buffer = Z_Malloc(info->size);
buffer = Hunk_AllocateTempMemory(info->size);
if(!buffer)
{
FS_FCloseFile(file);

View file

@ -259,10 +259,10 @@ static sfx_t *S_FindName( const char *name ) {
sfx_t *sfx;
if (!name) {
Com_Error (ERR_FATAL, "S_FindName: NULL\n");
Com_Error (ERR_FATAL, "S_FindName: NULL");
}
if (!name[0]) {
Com_Error (ERR_FATAL, "S_FindName: empty name\n");
Com_Error (ERR_FATAL, "S_FindName: empty name");
}
if (strlen(name) >= MAX_QPATH) {
@ -391,9 +391,8 @@ void S_Base_BeginRegistration( void ) {
if (s_numSfx == 0) {
SND_setup();
s_numSfx = 0;
Com_Memset( s_knownSfx, 0, sizeof( s_knownSfx ) );
Com_Memset(sfxHash, 0, sizeof(sfx_t *)*LOOP_HASH);
Com_Memset(s_knownSfx, '\0', sizeof(s_knownSfx));
Com_Memset(sfxHash, '\0', sizeof(sfx_t *) * LOOP_HASH);
S_Base_RegisterSound("sound/feedback/hit.wav", qfalse); // changed to a sound in baseq3
}
@ -1467,8 +1466,10 @@ void S_Base_Shutdown( void ) {
}
SNDDMA_Shutdown();
SND_shutdown();
s_soundStarted = 0;
s_numSfx = 0;
Cmd_RemoveCommand("s_info");
}

View file

@ -202,6 +202,7 @@ qboolean S_LoadSound( sfx_t *sfx );
void SND_free(sndBuffer *v);
sndBuffer* SND_malloc( void );
void SND_setup( void );
void SND_shutdown(void);
void S_PaintChannels(int endtime);

View file

@ -16,7 +16,7 @@ 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 Foobar; if not, write to the Free Software
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
@ -509,7 +509,7 @@ void S_Init( void )
if( started ) {
if( !S_ValidSoundInterface( &si ) ) {
Com_Error( ERR_FATAL, "Sound interface invalid." );
Com_Error( ERR_FATAL, "Sound interface invalid" );
}
S_SoundInfo( );

View file

@ -100,6 +100,12 @@ void SND_setup(void) {
Com_Printf("Sound memory manager started\n");
}
void SND_shutdown(void)
{
free(sfxScratchBuffer);
free(buffer);
}
/*
================
ResampleSfx
@ -255,7 +261,7 @@ qboolean S_LoadSound( sfx_t *sfx )
}
Hunk_FreeTempMemory(samples);
Z_Free(data);
Hunk_FreeTempMemory(data);
return qtrue;
}

View file

@ -258,7 +258,7 @@ static qboolean alBuffersInitialised = qfalse;
// Sound effect storage, data structures
#define MAX_SFX 4096
static alSfx_t knownSfx[MAX_SFX];
static int numSfx = 0;
static sfxHandle_t numSfx = 0;
static sfxHandle_t default_sfx;
@ -337,7 +337,7 @@ S_AL_BufferUseDefault
static void S_AL_BufferUseDefault(sfxHandle_t sfx)
{
if(sfx == default_sfx)
Com_Error(ERR_FATAL, "Can't load default sound effect %s\n", knownSfx[sfx].filename);
Com_Error(ERR_FATAL, "Can't load default sound effect %s", knownSfx[sfx].filename);
Com_Printf( S_COLOR_YELLOW "WARNING: Using default sound for %s\n", knownSfx[sfx].filename);
knownSfx[sfx].isDefault = qtrue;
@ -442,7 +442,7 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
if (!cache)
{
// Don't create AL cache
Z_Free(data);
Hunk_FreeTempMemory(data);
return;
}
@ -454,7 +454,7 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
if((error = qalGetError()) != AL_NO_ERROR)
{
S_AL_BufferUseDefault(sfx);
Z_Free(data);
Hunk_FreeTempMemory(data);
Com_Printf( S_COLOR_RED "ERROR: Can't create a sound buffer for %s - %s\n",
curSfx->filename, S_AL_ErrorMsg(error));
return;
@ -479,7 +479,7 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
if( !S_AL_BufferEvict( ) )
{
S_AL_BufferUseDefault(sfx);
Z_Free(data);
Hunk_FreeTempMemory(data);
Com_Printf( S_COLOR_RED "ERROR: Out of memory loading %s\n", curSfx->filename);
return;
}
@ -493,7 +493,7 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
if(error != AL_NO_ERROR)
{
S_AL_BufferUseDefault(sfx);
Z_Free(data);
Hunk_FreeTempMemory(data);
Com_Printf( S_COLOR_RED "ERROR: Can't fill sound buffer for %s - %s\n",
curSfx->filename, S_AL_ErrorMsg(error));
return;
@ -502,7 +502,7 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
curSfx->info = info;
// Free the memory
Z_Free(data);
Hunk_FreeTempMemory(data);
// Woo!
curSfx->inMemory = qtrue;
@ -570,7 +570,7 @@ void S_AL_BufferShutdown( void )
S_AL_BufferUnload(i);
// Clear the tables
memset(knownSfx, 0, sizeof(knownSfx));
numSfx = 0;
// All undone
alBuffersInitialised = qfalse;
@ -2568,6 +2568,8 @@ S_AL_BeginRegistration
static
void S_AL_BeginRegistration( void )
{
if(!numSfx)
S_AL_BufferInit();
}
/*
@ -3129,6 +3131,7 @@ qboolean S_AL_Init( soundInterface_t *si )
if(inputdevice && !*inputdevice)
inputdevice = NULL;
// Device enumeration support
enumeration_all_ext = qalcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT");
enumeration_ext = qalcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT");
@ -3143,17 +3146,16 @@ qboolean S_AL_Init( soundInterface_t *si )
// get all available devices + the default device name.
if(enumeration_ext)
{
devicelist = qalcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
devicelist = qalcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
defaultdevice = qalcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
}
else
{
// We don't have ALC_ENUMERATE_ALL_EXT but normal enumeration.
devicelist = qalcGetString(NULL, ALC_DEVICE_SPECIFIER);
defaultdevice = qalcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
enumeration_ext = qtrue;
}
else
{
// We don't have ALC_ENUMERATE_ALL_EXT but normal enumeration.
devicelist = qalcGetString(NULL, ALC_DEVICE_SPECIFIER);
defaultdevice = qalcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
enumeration_ext = qtrue;
}
#ifdef _WIN32
// check whether the default device is generic hardware. If it is, change to
@ -3213,7 +3215,6 @@ qboolean S_AL_Init( soundInterface_t *si )
qalDopplerFactor( s_alDopplerFactor->value );
qalDopplerVelocity( s_alDopplerSpeed->value );
#ifdef USE_VOIP
// !!! FIXME: some of these alcCaptureOpenDevice() values should be cvars.
// !!! FIXME: add support for capture device enumeration.

View file

@ -22,8 +22,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "snd_local.h"
long myftol( float f );
#define C0 0.4829629131445341
#define C1 0.8365163037378079
#define C2 0.2241438680420134

View file

@ -240,6 +240,24 @@ char *strchr( const char *string, int c ) {
return (char *)0;
}
char *strrchr(const char *string, int c)
{
const char *found = 0;
while(*string)
{
if(*string == c)
found = string;
string++;
}
if(c)
return (char *) found;
else
return (char *) string;
}
char *strstr( const char *string, const char *strCharSet ) {
while ( *string ) {
int i;
@ -1502,8 +1520,8 @@ static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
#define DP_C_LDOUBLE 4
#define char_to_int(p) (p - '0')
#define MAX(p,q) ((p >= q) ? p : q)
#define MIN(p,q) ((p <= q) ? p : q)
//#define MAX(p,q) ((p >= q) ? p : q)
//#define MIN(p,q) ((p <= q) ? p : q)
static int dopr (char *buffer, size_t maxlen, const char *format, va_list args)
{

View file

@ -88,6 +88,7 @@ char *strcat( char *strDestination, const char *strSource );
char *strcpy( char *strDestination, const char *strSource );
int strcmp( const char *string1, const char *string2 );
char *strchr( const char *string, int c );
char *strrchr(const char *string, int c);
char *strstr( const char *string, const char *strCharSet );
char *strncpy( char *strDest, const char *strSource, size_t count );
char *strtok( char *s, const char *delim);

View file

@ -1618,7 +1618,7 @@ int GetMaterialFromFlag(int flag)
char *p, *out = s;
if (!s)
return NULL;
if ((p = Q_strrchr(s, '/')) != NULL)
if ((p = strrchr(s, '/')) != NULL)
{
*p=0;
out=va("%s", s);
@ -1634,7 +1634,7 @@ int GetMaterialFromFlag(int flag)
return NULL;
if (!*s)
return va("");
if ((p = Q_strrchr(s, '/')) != NULL)
if ((p = strrchr(s, '/')) != NULL)
return p+1;
return va("default");
} */
@ -1648,7 +1648,7 @@ char *modelFromStr(char *s)
if (!s)
return NULL;
strncpy(buffer, s, sizeof(buffer));
if ((p = Q_strrchr(buffer, '/')) != NULL)
if ((p = strrchr(buffer, '/')) != NULL)
*p = '\0';
return buffer;
}
@ -1664,7 +1664,7 @@ char *skinFromStr(char *s)
if (!*s)
return buffer;
strncpy(buffer, s, 128);
if ((p = Q_strrchr(buffer, '/')) != NULL)
if ((p = strrchr(buffer, '/')) != NULL)
return p+1;
strcpy(buffer, "default");
return buffer;

View file

@ -236,7 +236,7 @@ static void PlayerIntroSound(const char *modelAndSkin)
char *skin;
Q_strncpyz(model, modelAndSkin, sizeof(model));
skin = Q_strrchr(model, '/');
skin = strrchr(model, '/');
if (skin) {
*skin++ = '\0';
} else {

View file

@ -1092,7 +1092,7 @@ void ClientUserinfoChanged(int clientNum)
if (g_gametype.integer >= GT_TEAM) {
if (client->sess.savedTeam == TEAM_RED) {
Q_strncpyz(model2, g_RQ3_team1model.string, sizeof(model));
skin2 = Q_strrchr(model2, '/');
skin2 = strrchr(model2, '/');
if (skin2) {
*skin2++ = '\0';
} else {
@ -1107,7 +1107,7 @@ void ClientUserinfoChanged(int clientNum)
}
} else {
Q_strncpyz(model2, g_RQ3_team2model.string, sizeof(model));
skin2 = Q_strrchr(model2, '/');
skin2 = strrchr(model2, '/');
if (skin2) {
*skin2++ = '\0';
} else {
@ -1123,7 +1123,7 @@ void ClientUserinfoChanged(int clientNum)
}
} else {
Q_strncpyz(model2, model, sizeof(model));
skin2 = Q_strrchr(model2, '/');
skin2 = strrchr(model2, '/');
if (skin2) {
*skin2++ = '\0';
} else {

View file

@ -1232,7 +1232,7 @@ void SetTeam(gentity_t * ent, char *s)
ent->client->sess.sub = TEAM_FREE;
}
// they go to the end of the line for tournements
if (team == TEAM_SPECTATOR) {
if (team == TEAM_SPECTATOR && oldTeam != team) {
client->sess.spectatorTime = level.time;
}
// JBravo: not messing with spec system in TP during teamswitches

View file

@ -1442,10 +1442,10 @@ void G_InitGame(int levelTime, int randomSeed, int restart)
//Slicer: Default Radio Gender according to MODEL gender
Q_strncpyz(model, g_RQ3_team1model.string, sizeof(model));
Q_strncpyz(model2, g_RQ3_team2model.string, sizeof(model));
s = Q_strrchr(model, '/');
s = strrchr(model, '/');
if (s)
*s++ = '\0';
s = Q_strrchr(model2, '/');
s = strrchr(model2, '/');
if (s)
*s++ = '\0';
@ -3194,7 +3194,7 @@ int RQ3_ParseBlock(int tag_type, char *tag, int *cur_pos, char *buf, int len)
if (RQ3_GetWord(buf, cur_pos, word_buff, len) != TOKEN_TAG) {
G_Printf("RQ3 config system: found model/skin name: %s\n", word_buff);
Com_sprintf(model, sizeof(model), "%s", word_buff);
skin = Q_strrchr(word_buff, '/');
skin = strrchr(word_buff, '/');
if (skin) {
*skin++ = '\0';
} else {

View file

@ -31,9 +31,8 @@ typedef unsigned char boolean;
#endif
/* #undef RIGHT_SHIFT_IS_UNSIGNED */
// Makro - the code didn't compile in VC++ 2008 Express
#ifdef _MSC_VER
#define INLINE __forceinline
#define INLINE __inline
#else
#define INLINE __inline__
#endif

View file

@ -25,7 +25,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
cvar_t *cl_shownet;
void CL_Shutdown( char *finalmsg ) {
void CL_Shutdown(char *finalmsg, qboolean disconnect)
{
}
void CL_Init( void ) {
@ -79,16 +80,23 @@ void CL_InitKeyCommands( void ) {
void CL_CDDialog( void ) {
}
void CL_FlushMemory( void ) {
void CL_FlushMemory(void)
{
}
void CL_ShutdownAll(qboolean shutdownRef)
{
}
void CL_StartHunkUsers( qboolean rendererOnly ) {
}
void CL_Snd_Restart(void)
void CL_InitRef(void)
{
}
void CL_ShutdownAll(void) {}
void CL_Snd_Shutdown(void)
{
}
qboolean CL_CDKeyValidate( const char *key, const char *checksum ) { return qtrue; }

View file

@ -879,10 +879,10 @@ void UI_MouseEvent( int dx, int dy )
// update mouse screen position
uis.cursorx += dx;
if (uis.cursorx < 0)
uis.cursorx = 0;
else if (uis.cursorx > SCREEN_WIDTH)
uis.cursorx = SCREEN_WIDTH;
if (uis.cursorx < -uis.bias)
uis.cursorx = -uis.bias;
else if (uis.cursorx > SCREEN_WIDTH+uis.bias)
uis.cursorx = SCREEN_WIDTH+uis.bias;
uis.cursory += dy;
if (uis.cursory < 0)
@ -995,6 +995,9 @@ UI_ConsoleCommand
qboolean UI_ConsoleCommand( int realTime ) {
char *cmd;
uis.frametime = realTime - uis.realtime;
uis.realtime = realTime;
cmd = UI_Argv( 0 );
// ensure minimum menu data is available

View file

@ -166,12 +166,6 @@ UI_CreditMenu
===============
*/
void UI_CreditMenu( void ) {
/* This UI_FillRect() hack will blank the borders if you're in widescreen,
so you get a completely black background instead of stripes from the
previous frame on each side of the credits.. */
const float black[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
UI_FillRect(0 - uis.bias, 0, (640.0f / uis.xscale) * 2.0f, 480.0f / uis.yscale, black);
memset( &s_credits, 0 ,sizeof(s_credits) );
s_credits.menu.draw = UI_CreditMenu_Draw;

View file

@ -223,7 +223,7 @@ static void Demos_MenuInit( void ) {
s_demos.list.generic.y = 130;
s_demos.list.width = 16;
s_demos.list.height = 14;
Com_sprintf(extension, sizeof(extension), "dm_%d", (int)trap_Cvar_VariableValue( "protocol" ) );
Com_sprintf(extension, sizeof(extension), ".%s%d", DEMOEXT, (int) trap_Cvar_VariableValue("protocol"));
s_demos.list.numitems = trap_FS_GetFileList( "demos", extension, s_demos.names, NAMEBUFSIZE );
s_demos.list.itemnames = (const char **)s_demos.demolist;
s_demos.list.columns = 3;

View file

@ -469,6 +469,11 @@ static void PlayerModel_SetMenuItems( void )
// model
trap_Cvar_VariableStringBuffer( "model", s_playermodel.modelskin, 64 );
// use default skin if none is set
if (!strchr(s_playermodel.modelskin, '/')) {
Q_strcat(s_playermodel.modelskin, 64, "/default");
}
// find model in our list
for (i=0; i<s_playermodel.nummodels; i++)
{

View file

@ -130,7 +130,7 @@ static void PlayerIcon( const char *modelAndSkin, char *iconName, int iconNameMa
char model[MAX_QPATH];
Q_strncpyz( model, modelAndSkin, sizeof(model));
skin = Q_strrchr( model, '/' );
skin = strrchr( model, '/' );
if ( skin ) {
*skin++ = '\0';
}

View file

@ -1617,7 +1617,7 @@ static void ServerPlayerIcon( const char *modelAndSkin, char *iconName, int icon
char model[MAX_QPATH];
Q_strncpyz( model, modelAndSkin, sizeof(model));
skin = Q_strrchr( model, '/' );
skin = strrchr( model, '/' );
if ( skin ) {
*skin++ = '\0';
}

View file

@ -418,21 +418,29 @@ GraphicsOptions_GetAspectRatios
static void GraphicsOptions_GetAspectRatios( void )
{
int i, r;
// build ratio list from resolutions
for( r = 0; resolutions[r]; r++ )
{
int w, h;
char *x;
char str[ sizeof(ratioBuf[0]) ];
// calculate resolution's aspect ratio
x = strchr( resolutions[r], 'x' ) + 1;
Q_strncpyz( str, resolutions[r], x-resolutions[r] );
w = atoi( str );
h = atoi( x );
Com_sprintf( str, sizeof(str), "%.2f:1", (float)w / (float)h );
// rename common ratios ("1.33:1" -> "4:3")
for( i = 0; knownRatios[i][0]; i++ ) {
if( !Q_stricmp( str, knownRatios[i][0] ) ) {
Q_strncpyz( str, knownRatios[i][1], sizeof( str ) );
break;
}
}
// add ratio to list if it is new
// establish res/ratio relationship
for( i = 0; ratioBuf[i][0]; i++ )
@ -445,23 +453,11 @@ static void GraphicsOptions_GetAspectRatios( void )
Q_strncpyz( ratioBuf[i], str, sizeof(ratioBuf[i]) );
ratioToRes[i] = r;
}
resToRatio[r] = i;
}
// prepare itemlist pointer array
// rename common ratios ("1.33:1" -> "4:3")
for( r = 0; ratioBuf[r][0]; r++ )
{
for( i = 0; knownRatios[i][0]; i++ )
{
if( !Q_stricmp( ratioBuf[r], knownRatios[i][0] ) )
{
Q_strncpyz( ratioBuf[r], knownRatios[i][1], sizeof(ratioBuf[r]) );
break;
}
}
ratios[r] = ratioBuf[r];
ratios[r] = ratioBuf[r];
resToRatio[r] = i;
}
ratios[r] = NULL;
}
@ -683,9 +679,11 @@ static void GraphicsOptions_ApplyChanges( void *unused, int notification )
trap_Cvar_SetValue( "r_mode", s_graphicsoptions.mode.curvalue );
trap_Cvar_SetValue( "r_fullscreen", s_graphicsoptions.fs.curvalue );
trap_Cvar_SetValue( "r_colorbits", 0 );
trap_Cvar_SetValue( "r_depthbits", 0 );
trap_Cvar_SetValue( "r_stencilbits", 0 );
trap_Cvar_Reset("r_colorbits");
trap_Cvar_Reset("r_depthbits");
trap_Cvar_Reset("r_stencilbits");
trap_Cvar_SetValue( "r_vertexLight", s_graphicsoptions.lighting.curvalue );
if ( s_graphicsoptions.geometry.curvalue == 2 )

View file

@ -272,11 +272,11 @@ CopyWinding
*/
winding_t *CopyWinding (winding_t *w)
{
unsigned long size;
intptr_t size;
winding_t *c;
c = AllocWinding (w->numpoints);
size = (long)((winding_t *)0)->p[w->numpoints];
size = (intptr_t) ((winding_t *)0)->p[w->numpoints];
Com_Memcpy (c, w, size);
return c;
}

View file

@ -686,7 +686,7 @@ void Cmd_RemoveCommandSafe( const char *cmd_name )
if( cmd->function )
{
Com_Error( ERR_DROP, "Restricted source tried to remove "
"system command \"%s\"\n", cmd_name );
"system command \"%s\"", cmd_name );
return;
}

View file

@ -90,6 +90,14 @@ cvar_t *com_basegame;
cvar_t *com_homepath;
cvar_t *com_busyWait;
#if idx64
int (*Q_VMftol)(void);
#elif id386
long (QDECL *Q_ftol)(float f);
int (QDECL *Q_VMftol)(void);
void (QDECL *Q_SnapVector)(vec3_t vec);
#endif
// com_speeds times
int time_game;
int time_frontend; // renderer frontend time
@ -330,7 +338,7 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
longjmp (abortframe, -1);
} else {
VM_Forced_Unload_Start();
CL_Shutdown (va("Client fatal crashed: %s", com_errorMessage));
CL_Shutdown (va("Client fatal crashed: %s", com_errorMessage), qtrue);
SV_Shutdown (va("Server fatal crashed: %s", com_errorMessage));
VM_Forced_Unload_Done();
}
@ -354,8 +362,14 @@ void Com_Quit_f( void ) {
// don't try to shutdown if we are in a recursive error
char *p = Cmd_Args( );
if ( !com_errorEntered ) {
// Some VMs might execute "quit" command directly,
// which would trigger an unload of active VM error.
// Sys_Quit will kill this process anyways, so
// a corrupt call stack makes no difference
VM_Forced_Unload_Start();
SV_Shutdown (p[0] ? p : "Server quit");
CL_Shutdown (p[0] ? p : "Client quit");
CL_Shutdown (p[0] ? p : "Client quit", qtrue);
VM_Forced_Unload_Done();
Com_Shutdown ();
FS_Shutdown(qtrue);
}
@ -461,13 +475,13 @@ void Com_StartupVariable( const char *match ) {
}
s = Cmd_Argv(1);
if(!match || !strcmp(s, match))
{
if(Cvar_Flags(s) == CVAR_NONEXISTENT)
Cvar_Get(s, Cmd_Argv(2), CVAR_USER_CREATED);
else
Cvar_Set( s, Cmd_Argv(2) );
Cvar_Set2(s, Cmd_Argv(2), qfalse);
}
}
}
@ -1054,12 +1068,12 @@ void Z_CheckHeap( void ) {
break; // all blocks have been hit
}
if ( (byte *)block + block->size != (byte *)block->next)
Com_Error( ERR_FATAL, "Z_CheckHeap: block size does not touch the next block\n" );
Com_Error( ERR_FATAL, "Z_CheckHeap: block size does not touch the next block" );
if ( block->next->prev != block) {
Com_Error( ERR_FATAL, "Z_CheckHeap: next block doesn't have proper back link\n" );
Com_Error( ERR_FATAL, "Z_CheckHeap: next block doesn't have proper back link" );
}
if ( !block->tag && !block->next->tag ) {
Com_Error( ERR_FATAL, "Z_CheckHeap: two consecutive free blocks\n" );
Com_Error( ERR_FATAL, "Z_CheckHeap: two consecutive free blocks" );
}
}
}
@ -1870,7 +1884,7 @@ void Hunk_Trash( void ) {
return;
#ifdef _DEBUG
Com_Error(ERR_DROP, "hunk trashed\n");
Com_Error(ERR_DROP, "hunk trashed");
return;
#endif
@ -2378,34 +2392,47 @@ Change to a new mod properly with cleaning up cvars before switching.
==================
*/
void Com_GameRestart(int checksumFeed, qboolean clientRestart)
void Com_GameRestart(int checksumFeed, qboolean disconnect)
{
// make sure no recursion can be triggered
if(!com_gameRestarting && com_fullyInitialized)
{
com_gameRestarting = qtrue;
int clWasRunning;
com_gameRestarting = qtrue;
clWasRunning = com_cl_running->integer;
if(clientRestart)
{
CL_Disconnect(qfalse);
CL_ShutdownAll();
}
// Kill server if we have one
if(com_sv_running->integer)
SV_Shutdown("Game directory changed");
if(clWasRunning)
{
if(disconnect)
CL_Disconnect(qfalse);
CL_Shutdown("Game directory changed", disconnect);
}
FS_Restart(checksumFeed);
// Clean out any user and VM created cvars
Cvar_Restart(qtrue);
Com_ExecuteCfg();
// Restart sound subsystem so old handles are flushed
CL_Snd_Restart();
if(clientRestart)
if(disconnect)
{
// We don't want to change any network settings if gamedir
// change was triggered by a connect to server because the
// new network settings might make the connection fail.
NET_Restart_f();
}
if(clWasRunning)
{
CL_Init();
CL_StartHunkUsers(qfalse);
}
com_gameRestarting = qfalse;
}
@ -2421,7 +2448,16 @@ Expose possibility to change current running mod to the user
void Com_GameRestart_f(void)
{
Cvar_Set("fs_game", Cmd_Argv(1));
if(!FS_FilenameCompare(Cmd_Argv(1), com_basegame->string))
{
// This is the standard base game. Servers and clients should
// use "" and not the standard basegame name because this messes
// up pak file negotiation and lots of other stuff
Cvar_Set("fs_game", "");
}
else
Cvar_Set("fs_game", Cmd_Argv(1));
Com_GameRestart(0, qtrue);
}
@ -2565,6 +2601,53 @@ static void Com_DetectAltivec(void)
}
}
/*
=================
Com_DetectSSE
Find out whether we have SSE support for Q_ftol function
=================
*/
#if id386 || idx64
static void Com_DetectSSE(void)
{
#if !idx64
cpuFeatures_t feat;
feat = Sys_GetProcessorFeatures();
if(feat & CF_SSE)
{
if(feat & CF_SSE2)
Q_SnapVector = qsnapvectorsse;
else
Q_SnapVector = qsnapvectorx87;
Q_ftol = qftolsse;
#endif
Q_VMftol = qvmftolsse;
Com_Printf("Have SSE support\n");
#if !idx64
}
else
{
Q_ftol = qftolx87;
Q_VMftol = qvmftolx87;
Q_SnapVector = qsnapvectorx87;
Com_Printf("No SSE support on this machine\n");
}
#endif
}
#else
#define Com_DetectSSE()
#endif
/*
=================
Com_InitRand
@ -2615,6 +2698,8 @@ void Com_Init( char *commandLine ) {
// Swap_Init ();
Cbuf_Init ();
Com_DetectSSE();
// override anything from the config files with command line args
Com_StartupVariable( NULL );
@ -2634,7 +2719,6 @@ void Com_Init( char *commandLine ) {
if(!com_basegame->string[0])
Cvar_ForceReset("com_basegame");
// Com_StartupVariable(
FS_InitFilesystem ();
Com_InitJournaling();
@ -2704,6 +2788,7 @@ void Com_Init( char *commandLine ) {
com_maxfpsMinimized = Cvar_Get( "com_maxfpsMinimized", "0", CVAR_ARCHIVE );
com_abnormalExit = Cvar_Get( "com_abnormalExit", "0", CVAR_ROM );
com_busyWait = Cvar_Get("com_busyWait", "0", CVAR_ARCHIVE);
Cvar_Get("com_errorMessage", "", CVAR_ROM | CVAR_NORESTART);
com_introPlayed = Cvar_Get( "com_introplayed", "0", CVAR_ARCHIVE);

View file

@ -35,8 +35,6 @@ int cvar_numIndexes;
#define FILE_HASH_SIZE 256
static cvar_t *hashTable[FILE_HASH_SIZE];
cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force);
/*
================
return a hash value for the filename
@ -635,10 +633,10 @@ void Cvar_SetSafe( const char *var_name, const char *value )
{
if( value )
Com_Error( ERR_DROP, "Restricted source tried to set "
"\"%s\" to \"%s\"\n", var_name, value );
"\"%s\" to \"%s\"", var_name, value );
else
Com_Error( ERR_DROP, "Restricted source tried to "
"modify \"%s\"\n", var_name );
"modify \"%s\"", var_name );
return;
}
Cvar_Set( var_name, value );

File diff suppressed because it is too large Load diff

View file

@ -273,7 +273,7 @@ int Huff_Receive (node_t *node, int *ch, byte *fin) {
}
if (!node) {
return 0;
// Com_Error(ERR_DROP, "Illegal tree!\n");
// Com_Error(ERR_DROP, "Illegal tree!");
}
return (*ch = node->symbol);
}
@ -291,7 +291,7 @@ void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset) {
if (!node) {
*ch = 0;
return;
// Com_Error(ERR_DROP, "Illegal tree!\n");
// Com_Error(ERR_DROP, "Illegal tree!");
}
*ch = node->symbol;
*offset = bloc;

View file

@ -155,7 +155,7 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) {
msg->cursize += 4;
msg->bit += 32;
} else {
Com_Error(ERR_DROP, "can't read %d bits\n", bits);
Com_Error(ERR_DROP, "can't read %d bits", bits);
}
} else {
// fp = fopen("c:\\netchan.bin", "a");
@ -213,7 +213,7 @@ int MSG_ReadBits( msg_t *msg, int bits ) {
msg->readcount += 4;
msg->bit += 32;
} else {
Com_Error(ERR_DROP, "can't read %d bits\n", bits);
Com_Error(ERR_DROP, "can't read %d bits", bits);
}
} else {
nbits = 0;

View file

@ -63,11 +63,11 @@ static qboolean winsockInitialized = qfalse;
# define _BSD_SOCKLEN_T_
# endif
# include <arpa/inet.h>
# include <sys/socket.h>
# include <errno.h>
# include <netdb.h>
# include <netinet/in.h>
# include <sys/socket.h>
# include <arpa/inet.h>
# include <net/if.h>
# include <sys/ioctl.h>
# include <sys/types.h>
@ -1290,6 +1290,8 @@ static void NET_GetLocalAddress(void)
{
struct ifaddrs *ifap, *search;
numIP = 0;
if(getifaddrs(&ifap))
Com_Printf("NET_GetLocalAddress: Unable to get list of network interfaces: %s\n", NET_ErrorString());
else
@ -1312,6 +1314,8 @@ static void NET_GetLocalAddress( void ) {
struct addrinfo hint;
struct addrinfo *res = NULL;
numIP = 0;
if(gethostname( hostname, 256 ) == SOCKET_ERROR)
return;

View file

@ -829,10 +829,12 @@ vec_t VectorNormalize( vec3_t v ) {
float length, ilength;
length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
length = sqrt (length);
if ( length ) {
ilength = 1/length;
/* writing it this way allows gcc to recognize that rsqrt can be used */
ilength = 1/(float)sqrt (length);
/* sqrt(length) = length * (1 / sqrt(length)) */
length *= ilength;
v[0] *= ilength;
v[1] *= ilength;
v[2] *= ilength;
@ -845,11 +847,13 @@ vec_t VectorNormalize2( const vec3_t v, vec3_t out) {
float length, ilength;
length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
length = sqrt (length);
if (length)
{
ilength = 1/length;
/* writing it this way allows gcc to recognize that rsqrt can be used */
ilength = 1/(float)sqrt (length);
/* sqrt(length) = length * (1 / sqrt(length)) */
length *= ilength;
out[0] = v[0]*ilength;
out[1] = v[1]*ilength;
out[2] = v[2]*ilength;

View file

@ -24,6 +24,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define __Q_PLATFORM_H
// this is for determining if we have an asm version of a C function
#define idx64 0
#ifdef Q3_VM
#define id386 0
@ -76,6 +78,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#if defined(_WIN64) || defined(__WIN64__)
#undef idx64
#define idx64 1
#undef QDECL
#define QDECL __cdecl
@ -85,7 +90,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define OS_STRING "win_mingw64"
#endif
#define ID_INLINE inline
#define ID_INLINE __inline
#define PATH_SEP '\\'
#if defined( __WIN64__ )
@ -144,6 +149,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define ARCH_STRING "i386"
#define Q3_LITTLE_ENDIAN
#elif defined __x86_64__
#undef idx64
#define idx64 1
#define ARCH_STRING "x86_64"
#define Q3_LITTLE_ENDIAN
#endif
@ -170,6 +177,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#if defined __i386__
#define ARCH_STRING "i386"
#elif defined __x86_64__
#undef idx64
#define idx64 1
#define ARCH_STRING "x86_64"
#elif defined __powerpc64__
#define ARCH_STRING "ppc64"
@ -232,6 +241,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifdef __i386__
#define ARCH_STRING "i386"
#elif defined __amd64__
#undef idx64
#define idx64 1
#define ARCH_STRING "amd64"
#elif defined __axp__
#define ARCH_STRING "alpha"

View file

@ -58,20 +58,13 @@ char *COM_SkipPath (char *pathname)
COM_GetExtension
============
*/
const char *COM_GetExtension( const char *name ) {
int length, i;
length = strlen(name)-1;
i = length;
while (name[i] != '.')
{
i--;
if (name[i] == '/' || i == 0)
return ""; // no extension
}
return &name[i+1];
const char *COM_GetExtension( const char *name )
{
const char *dot = strrchr(name, '.'), *slash;
if (dot && (!(slash = strrchr(name, '/')) || slash < dot))
return dot + 1;
else
return "";
}
@ -80,47 +73,31 @@ const char *COM_GetExtension( const char *name ) {
COM_StripExtension
============
*/
void COM_StripExtension( const char *in, char *out, int destsize ) {
int length;
Q_strncpyz(out, in, destsize);
length = strlen(out)-1;
while (length > 0 && out[length] != '.')
{
length--;
if (out[length] == '/')
return; // no extension
}
if (length)
out[length] = 0;
void COM_StripExtension( const char *in, char *out, int destsize )
{
const char *dot = strrchr(in, '.'), *slash;
if (dot && (!(slash = strrchr(in, '/')) || slash < dot))
Q_strncpyz(out, in, (destsize < dot-in+1 ? destsize : dot-in+1));
else
Q_strncpyz(out, in, destsize);
}
/*
==================
COM_DefaultExtension
if path doesn't have an extension, then append
the specified one (which should include the .)
==================
*/
void COM_DefaultExtension (char *path, int maxSize, const char *extension ) {
char oldPath[MAX_QPATH];
char *src;
//
// if path doesn't have a .EXT, append extension
// (extension should include the .)
//
src = path + strlen(path) - 1;
while (*src != '/' && src != path) {
if ( *src == '.' ) {
return; // it has an extension
}
src--;
}
Q_strncpyz( oldPath, path, sizeof( oldPath ) );
Com_sprintf( path, maxSize, "%s%s", oldPath, extension );
void COM_DefaultExtension( char *path, int maxSize, const char *extension )
{
const char *dot = strrchr(path, '.'), *slash;
if (dot && (!(slash = strrchr(path, '/')) || slash < dot))
return;
else
Q_strcat(path, maxSize, extension);
}
/*
@ -683,26 +660,6 @@ int Q_isalpha( int c )
return ( 0 );
}
char* Q_strrchr( const char* string, int c )
{
char cc = c;
char *s;
char *sp=(char *)0;
s = (char*)string;
while (*s)
{
if (*s == cc)
sp = s;
s++;
}
if (cc == 0)
sp = s;
return sp;
}
qboolean Q_isanumber( const char *s )
{
char *p;
@ -972,7 +929,7 @@ void QDECL Com_sprintf(char *dest, int size, const char *fmt, ...)
va_end (argptr);
if(len >= size)
Com_Printf("Com_sprintf: Output length %d too short, require %d bytes.\n", size, len);
Com_Printf("Com_sprintf: Output length %d too short, require %d bytes.\n", size, len + 1);
}
/*

View file

@ -34,6 +34,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define GAMENAME_FOR_MASTER "Reaction" // must NOT contain whitespaces
#define HEARTBEAT_FOR_MASTER GAMENAME_FOR_MASTER
#define FLATLINE_FOR_MASTER GAMENAME_FOR_MASTER "dead"
#define HOMEPATH_NAME_UNIX ".Reaction"
#define HOMEPATH_NAME_WIN "Reaction"
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
#else
#define PRODUCT_NAME "Reaction"
#define BASEGAME "Boomstick"
@ -42,12 +45,15 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define GAMENAME_FOR_MASTER "Reaction"
#define HEARTBEAT_FOR_MASTER "Reaction-1"
#define FLATLINE_FOR_MASTER HEARTBEAT_FOR_MASTER
#define HOMEPATH_NAME_UNIX ".Reaction"
#define HOMEPATH_NAME_WIN "Reaction"
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
#endif
#define BASETA "missionpack"
#ifdef _MSC_VER
#define PRODUCT_VERSION "1.35"
#define PRODUCT_VERSION "1.36"
#endif
#define Q3_VERSION PRODUCT_NAME " " PRODUCT_VERSION
@ -55,6 +61,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define MAX_TEAMNAME 32
#define MAX_MASTER_SERVERS 5 // number of supported master servers
#define DEMOEXT "dm_" // standard demo extension
#ifdef _MSC_VER
#pragma warning(disable : 4018) // signed/unsigned mismatch
@ -175,8 +183,10 @@ typedef int sfxHandle_t;
typedef int fileHandle_t;
typedef int clipHandle_t;
#define PAD(x,y) (((x)+(y)-1) & ~((y)-1))
#define PADLEN(x,y) (PAD((x), (y)) - (x))
#define PAD(base, alignment) (((base)+(alignment)-1) & ~((alignment)-1))
#define PADLEN(base, alignment) (PAD((base), (alignment)) - (base))
#define PADP(base, alignment) ((void *) PAD((intptr_t) (base), (alignment)))
#ifdef __GNUC__
#define QALIGN(x) __attribute__((aligned(x)))
@ -420,6 +430,58 @@ extern vec3_t axisDefault[3];
#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
int Q_isnan(float x);
#if idx64
extern long qftolsse(float f);
extern int qvmftolsse(void);
extern void qsnapvectorsse(vec3_t vec);
#define Q_ftol qftolsse
#define Q_SnapVector qsnapvectorsse
extern int (*Q_VMftol)(void);
#elif id386
extern long QDECL qftolx87(float f);
extern long QDECL qftolsse(float f);
extern int QDECL qvmftolx87(void);
extern int QDECL qvmftolsse(void);
extern void QDECL qsnapvectorx87(vec3_t vec);
extern void QDECL qsnapvectorsse(vec3_t vec);
extern long (QDECL *Q_ftol)(float f);
extern int (QDECL *Q_VMftol)(void);
extern void (QDECL *Q_SnapVector)(vec3_t vec);
#else
#define Q_ftol(f) lrintf((f))
#define Q_SnapVector(vec)\
do\
{\
vec3_t *temp = (vec);\
\
(*temp)[0] = round((*temp)[0]);\
(*temp)[1] = round((*temp)[1]);\
(*temp)[2] = round((*temp)[2]);\
} while(0)
#endif
/*
// if your system does not have lrintf() and round() you can try this block. Please also open a bug report at bugzilla.icculus.org
// or write a mail to the ioq3 mailing list.
#else
#define Q_ftol(v) ((long) (v))
#define Q_round(v) do { if((v) < 0) (v) -= 0.5f; else (v) += 0.5f; (v) = Q_ftol((v)); } while(0)
#define Q_SnapVector(vec) \
do\
{\
vec3_t *temp = (vec);\
\
Q_round((*temp)[0]);\
Q_round((*temp)[1]);\
Q_round((*temp)[2]);\
} while(0)
#endif
*/
#if idppc
static ID_INLINE float Q_rsqrt( float number ) {
@ -494,6 +556,8 @@ typedef struct {
#define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
#define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
#define Byte4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
//Makro - for the UI
#define Vector2Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1])
#define Vector2MA(v,s,b,o) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s))
@ -650,7 +714,6 @@ void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]);
void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
void PerpendicularVector( vec3_t dst, const vec3_t src );
int ReflectVectorByte( vec3_t dir, vec3_t plane );
int Q_isnan( float x );
// Makro - added
void ChangeRefSystem(vec3_t in, vec3_t neworg, vec3_t newaxis[], vec3_t out);
@ -661,6 +724,14 @@ void ChangeAngleRefSystem(vec3_t in, vec3_t newaxis[], vec3_t out);
#define is_digit(c) ((unsigned)to_digit(c) <= 9)
#define to_digit(c) ((c) - '0')
#ifndef MAX
#define MAX(x,y) ((x)>(y)?(x):(y))
#endif
#ifndef MIN
#define MIN(x,y) ((x)<(y)?(x):(y))
#endif
//=============================================
float Com_Clamp( float min, float max, float value );
@ -747,7 +818,6 @@ int Q_strncmp (const char *s1, const char *s2, int n);
int Q_stricmpn (const char *s1, const char *s2, int n);
char *Q_strlwr( char *s1 );
char *Q_strupr( char *s1 );
char *Q_strrchr( const char* string, int c );
const char *Q_stristr( const char *s, const char *find);
// buffer size safe library replacements

View file

@ -242,9 +242,6 @@ PROTOCOL
==============================================================
*/
// Makro - this wasn't defined anywhere...
#define DEMOEXT "dm"
#define PROTOCOL_VERSION 68
// 1.31 - 67
@ -507,6 +504,9 @@ void Cvar_Update( vmCvar_t *vmCvar );
void Cvar_Set( const char *var_name, const char *value );
// will create the variable with no flags if it doesn't exist
cvar_t *Cvar_Set2(const char *var_name, const char *value, qboolean force);
// same as Cvar_Set, but allows more control over setting of cvar
void Cvar_SetSafe( const char *var_name, const char *value );
// sometimes we set variables from an untrusted source: fail if flags & CVAR_PROTECTED
@ -600,7 +600,7 @@ qboolean FS_Initialized( void );
void FS_InitFilesystem ( void );
void FS_Shutdown( qboolean closemfp );
qboolean FS_ConditionalRestart( int checksumFeed );
qboolean FS_ConditionalRestart(int checksumFeed, qboolean disconnect);
void FS_Restart( int checksumFeed );
// shutdown and restart the filesystem so changes to fs_gamedir can take effect
@ -617,7 +617,7 @@ qboolean FS_FileExists( const char *file );
qboolean FS_CreatePath (char *OSPath);
char *FS_FindDll( const char *filename );
vmInterpret_t FS_FindVM(void **startSearch, char *found, int foundlen, const char *name, int enableDll);
char *FS_BuildOSPath( const char *base, const char *game, const char *qpath );
qboolean FS_CompareZipChecksum(const char *zipfile);
@ -633,9 +633,9 @@ fileHandle_t FS_FCreateOpenPipeFile( const char *filename );
// will properly create any needed paths and deal with seperater character issues
fileHandle_t FS_SV_FOpenFileWrite( const char *filename );
int FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp );
long FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp );
void FS_SV_Rename( const char *from, const char *to );
int FS_FOpenFileRead( const char *qpath, fileHandle_t *file, qboolean uniqueFILE );
long FS_FOpenFileRead( const char *qpath, fileHandle_t *file, qboolean uniqueFILE );
// if uniqueFILE is true, then a new FILE will be fopened even if the file
// is found in an already open pak file. If uniqueFILE is false, you must call
// FS_FCloseFile instead of fclose, otherwise the pak FILE would be improperly closed
@ -654,7 +654,8 @@ int FS_Read( void *buffer, int len, fileHandle_t f );
void FS_FCloseFile( fileHandle_t f );
// note: you can't just fclose from another DLL, due to MS libc issues
int FS_ReadFile( const char *qpath, void **buffer );
long FS_ReadFileDir(const char *qpath, void *searchPath, void **buffer);
long FS_ReadFile(const char *qpath, void **buffer);
// returns the length of the file
// a null buffer will just return the file length without loading
// as a quick check for existance. -1 length == not present
@ -671,7 +672,7 @@ void FS_FreeFile( void *buffer );
void FS_WriteFile( const char *qpath, const void *buffer, int size );
// writes a complete file, creating any subdirectories needed
int FS_filelength( fileHandle_t f );
long FS_filelength(fileHandle_t f);
// doesn't work for files that are opened from a pack file
int FS_FTell( fileHandle_t f );
@ -729,6 +730,7 @@ void FS_FilenameCompletion( const char *dir, const char *ext,
qboolean stripExt, void(*callback)(const char *s), qboolean allowNonPureFilesOnDisk );
const char *FS_GetCurrentGameDir(void);
qboolean FS_Which(const char *filename, void *searchPath);
/*
==============================================================
@ -814,7 +816,7 @@ void QDECL Com_Printf( const char *fmt, ... ) __attribute__ ((format (printf,
void QDECL Com_DPrintf( const char *fmt, ... ) __attribute__ ((format (printf, 1, 2)));
void QDECL Com_Error( int code, const char *fmt, ... ) __attribute__ ((format (printf, 2, 3)));
void Com_Quit_f( void );
void Com_GameRestart(int checksumFeed, qboolean clientRestart);
void Com_GameRestart(int checksumFeed, qboolean disconnect);
int Com_Milliseconds( void ); // will be journaled properly
unsigned Com_BlockChecksum( const void *buffer, int length );
@ -869,6 +871,7 @@ extern int time_backend; // renderer backend time
extern int com_frameTime;
extern qboolean com_errorEntered;
extern qboolean com_fullyInitialized;
extern fileHandle_t com_journalFile;
extern fileHandle_t com_journalDataFile;
@ -958,7 +961,7 @@ void CL_InitKeyCommands( void );
void CL_Init( void );
void CL_Disconnect( qboolean showMainMenu );
void CL_Shutdown( char *finalmsg );
void CL_Shutdown(char *finalmsg, qboolean disconnect);
void CL_Frame( int msec );
qboolean CL_GameCommand( void );
void CL_KeyEvent (int key, qboolean down, unsigned time);
@ -988,16 +991,19 @@ void CL_ForwardCommandToServer( const char *string );
void CL_CDDialog( void );
// bring up the "need a cd to play" dialog
void CL_ShutdownAll( void );
// shutdown all the client stuff
void CL_FlushMemory( void );
// dump all memory on an error
void CL_ShutdownAll(qboolean shutdownRef);
// shutdown client
void CL_InitRef(void);
// initialize renderer interface
void CL_StartHunkUsers( qboolean rendererOnly );
// start all the client stuff using the hunk
void CL_Snd_Restart(void);
void CL_Snd_Shutdown(void);
// Restart sound subsystem
void Key_KeynameCompletion( void(*callback)(const char *s) );

View file

@ -35,7 +35,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#endif
// surface geometry should not exceed these limits
#define SHADER_MAX_VERTEXES 1000
#define SHADER_MAX_VERTEXES 4225
#define SHADER_MAX_INDEXES (6*SHADER_MAX_VERTEXES)
#define SHADER_MAX_TRIANGLES (SHADER_MAX_INDEXES / 3)

View file

@ -377,15 +377,20 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc ) {
// load the image
Com_sprintf( filename, sizeof(filename), "vm/%s.qvm", vm->name );
Com_Printf( "Loading vm file %s...\n", filename );
length = FS_ReadFile( filename, &header.v );
length = FS_ReadFileDir(filename, vm->searchPath, &header.v);
if ( !header.h ) {
Com_Printf( "Failed.\n" );
VM_Free( vm );
Com_Printf(S_COLOR_YELLOW "Warning: Couldn't open VM file %s\n", filename);
return NULL;
}
// show where the qvm was loaded from
Cmd_ExecuteString( va( "which %s\n", filename ) );
FS_Which(filename, vm->searchPath);
if( LittleLong( header.h->vmMagic ) == VM_MAGIC_VER2 ) {
Com_Printf( "...which has vmMagic VM_MAGIC_VER2\n" );
@ -400,9 +405,13 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc ) {
|| header.h->bssLength < 0
|| header.h->dataLength < 0
|| header.h->litLength < 0
|| header.h->codeLength <= 0 ) {
VM_Free( vm );
Com_Error( ERR_FATAL, "%s has bad header", filename );
|| header.h->codeLength <= 0 )
{
VM_Free(vm);
FS_FreeFile(header.v);
Com_Printf(S_COLOR_YELLOW "Warning: %s has bad header\n", filename);
return NULL;
}
} else if( LittleLong( header.h->vmMagic ) == VM_MAGIC ) {
// byte swap the header
@ -415,14 +424,21 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc ) {
if ( header.h->bssLength < 0
|| header.h->dataLength < 0
|| header.h->litLength < 0
|| header.h->codeLength <= 0 ) {
VM_Free( vm );
Com_Error( ERR_FATAL, "%s has bad header", filename );
|| header.h->codeLength <= 0 )
{
VM_Free(vm);
FS_FreeFile(header.v);
Com_Printf(S_COLOR_YELLOW "Warning: %s has bad header\n", filename);
return NULL;
}
} else {
VM_Free( vm );
Com_Error( ERR_FATAL, "%s does not have a recognisable "
"magic number in its header", filename );
FS_FreeFile(header.v);
Com_Printf(S_COLOR_YELLOW "Warning: %s does not have a recognisable "
"magic number in its header\n", filename);
return NULL;
}
// round up to next power of 2 so all data operations can
@ -502,7 +518,7 @@ vm_t *VM_Restart( vm_t *vm ) {
Com_Printf( "VM_Restart()\n" );
if( !( header = VM_LoadQVM( vm, qfalse ) ) ) {
Com_Error( ERR_DROP, "VM_Restart failed.\n" );
Com_Error( ERR_DROP, "VM_Restart failed" );
return NULL;
}
@ -524,7 +540,9 @@ vm_t *VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *),
vmInterpret_t interpret ) {
vm_t *vm;
vmHeader_t *header;
int i, remaining;
int i, remaining, retval;
char filename[MAX_OSPATH];
void *startSearch = NULL;
if ( !module || !module[0] || !systemCalls ) {
Com_Error( ERR_FATAL, "VM_Create: bad parms" );
@ -553,29 +571,45 @@ vm_t *VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *),
vm = &vmTable[i];
Q_strncpyz( vm->name, module, sizeof( vm->name ) );
vm->systemCall = systemCalls;
Q_strncpyz(vm->name, module, sizeof(vm->name));
if ( interpret == VMI_NATIVE ) {
// try to load as a system dll
Com_Printf( "Loading dll file %s.\n", vm->name );
vm->dllHandle = Sys_LoadDll( module, &vm->entryPoint, VM_DllSyscall );
if ( vm->dllHandle ) {
return vm;
do
{
retval = FS_FindVM(&startSearch, filename, sizeof(filename), module, (interpret == VMI_NATIVE));
if(retval == VMI_NATIVE)
{
Com_Printf("Try loading dll file %s\n", filename);
vm->dllHandle = Sys_LoadDll(filename, &vm->entryPoint, VM_DllSyscall);
if(vm->dllHandle)
{
vm->systemCall = systemCalls;
return vm;
}
Com_Printf("Failed loading dll, trying next\n");
}
else if(retval == VMI_COMPILED)
{
vm->searchPath = startSearch;
if((header = VM_LoadQVM(vm, qtrue)))
break;
Com_Printf( "Failed to load dll, looking for qvm.\n" );
interpret = VMI_COMPILED;
}
// load the image
if( !( header = VM_LoadQVM( vm, qtrue ) ) ) {
// VM_Free overwrites the name on failed load
Q_strncpyz(vm->name, module, sizeof(vm->name));
}
} while(retval >= 0);
if(retval < 0)
return NULL;
}
vm->systemCall = systemCalls;
// allocate space for the jump targets, which will be filled in by the compile/prep functions
vm->instructionCount = header->instructionCount;
vm->instructionPointers = Hunk_Alloc( vm->instructionCount*4, h_high );
vm->instructionPointers = Hunk_Alloc(vm->instructionCount * sizeof(*vm->instructionPointers), h_high);
// copy or compile the instructions
vm->codeLength = header->codeLength;
@ -588,7 +622,8 @@ vm_t *VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *),
interpret = VMI_BYTECODE;
}
#else
if ( interpret >= VMI_COMPILED ) {
if(interpret != VMI_BYTECODE)
{
vm->compiled = qtrue;
VM_Compile( vm, header );
}
@ -914,3 +949,25 @@ void VM_LogSyscalls( int *args ) {
fprintf(f, "%i: %p (%i) = %i %i %i %i\n", callnum, (void*)(args - (int *)currentVM->dataBase),
args[0], args[1], args[2], args[3], args[4] );
}
/*
=================
VM_BlockCopy
Executes a block copy operation within currentVM data space
=================
*/
void VM_BlockCopy(unsigned int dest, unsigned int src, size_t n)
{
unsigned int dataMask = currentVM->dataMask;
if ((dest & dataMask) != dest
|| (src & dataMask) != src
|| ((dest + n) & dataMask) != dest + n
|| ((src + n) & dataMask) != src + n)
{
Com_Error(ERR_DROP, "OP_BLOCK_COPY out of range!");
}
Com_Memcpy(currentVM->dataBase + dest, currentVM->dataBase + src, n);
}

View file

@ -192,9 +192,8 @@ void VM_PrepareInterpreter( vm_t *vm, vmHeader_t *header ) {
op = (int)code[ byte_pc ];
codeBase[int_pc] = op;
if ( byte_pc > header->codeLength ) {
Com_Error( ERR_FATAL, "VM_PrepareInterpreter: pc > header->codeLength" );
}
if(byte_pc > header->codeLength)
Com_Error(ERR_DROP, "VM_PrepareInterpreter: pc > header->codeLength");
byte_pc++;
int_pc++;
@ -265,6 +264,9 @@ void VM_PrepareInterpreter( vm_t *vm, vmHeader_t *header ) {
case OP_LEF:
case OP_GTF:
case OP_GEF:
if(codeBase[int_pc] < 0 || codeBase[int_pc] > vm->instructionCount)
Com_Error(ERR_DROP, "VM_PrepareInterpreter: Jump to invalid instruction number");
// codeBase[pc] is the instruction index. Convert that into an offset into
//the int-aligned codeBase[] by the lookup table.
codeBase[int_pc] = vm->instructionPointers[codeBase[int_pc]];
@ -312,11 +314,12 @@ locals from sp
==============
*/
#define DEBUGSTR va("%s%i", VM_Indent(vm), opStack-stack )
#define DEBUGSTR va("%s%i", VM_Indent(vm), opStackOfs)
int VM_CallInterpreted( vm_t *vm, int *args ) {
int stack[OPSTACK_SIZE];
int *opStack;
byte stack[OPSTACK_SIZE + 15];
register int *opStack;
register uint8_t opStackOfs;
int programCounter;
int programStack;
int stackOnEntry;
@ -345,10 +348,6 @@ int VM_CallInterpreted( vm_t *vm, int *args ) {
codeImage = (int *)vm->codeBase;
dataMask = vm->dataMask;
// leave a free spot at start of stack so
// that as long as opStack is valid, opStack-1 will
// not corrupt anything
opStack = stack;
programCounter = 0;
programStack -= 48;
@ -368,6 +367,13 @@ int VM_CallInterpreted( vm_t *vm, int *args ) {
VM_Debug(0);
// leave a free spot at start of stack so
// that as long as opStack is valid, opStack-1 will
// not corrupt anything
opStack = PADP(stack, 16);
*opStack = 0xDEADBEEF;
opStackOfs = 0;
// vm_debugLevel=2;
// main interpreter loop, will exit when a LEAVE instruction
// grabs the -1 program counter
@ -379,27 +385,23 @@ int VM_CallInterpreted( vm_t *vm, int *args ) {
// unsigned int r2;
nextInstruction:
r0 = ((int *)opStack)[0];
r1 = ((int *)opStack)[-1];
r0 = opStack[opStackOfs];
r1 = opStack[(uint8_t) (opStackOfs - 1)];
nextInstruction2:
#ifdef DEBUG_VM
if ( (unsigned)programCounter >= vm->codeLength ) {
Com_Error( ERR_DROP, "VM pc out of range" );
}
if ( opStack < stack ) {
Com_Error( ERR_DROP, "VM opStack underflow" );
}
if ( opStack >= stack+OPSTACK_SIZE ) {
Com_Error( ERR_DROP, "VM opStack overflow" );
return 0;
}
if ( programStack <= vm->stackBottom ) {
Com_Error( ERR_DROP, "VM stack overflow" );
return 0;
}
if ( programStack & 3 ) {
Com_Error( ERR_DROP, "VM program stack misaligned" );
return 0;
}
if ( vm_debugLevel > 1 ) {
@ -413,79 +415,67 @@ nextInstruction2:
#ifdef DEBUG_VM
default:
Com_Error( ERR_DROP, "Bad VM instruction" ); // this should be scanned on load!
return 0;
#endif
case OP_BREAK:
vm->breakCount++;
goto nextInstruction2;
case OP_CONST:
opStack++;
opStackOfs++;
r1 = r0;
r0 = *opStack = r2;
r0 = opStack[opStackOfs] = r2;
programCounter += 1;
goto nextInstruction2;
case OP_LOCAL:
opStack++;
opStackOfs++;
r1 = r0;
r0 = *opStack = r2+programStack;
r0 = opStack[opStackOfs] = r2+programStack;
programCounter += 1;
goto nextInstruction2;
case OP_LOAD4:
#ifdef DEBUG_VM
if ( *opStack & 3 ) {
if(opStack[opStackOfs] & 3)
{
Com_Error( ERR_DROP, "OP_LOAD4 misaligned" );
return 0;
}
#endif
r0 = *opStack = *(int *)&image[ r0&dataMask&~3 ];
r0 = opStack[opStackOfs] = *(int *) &image[r0 & dataMask & ~3 ];
goto nextInstruction2;
case OP_LOAD2:
r0 = *opStack = *(unsigned short *)&image[ r0&dataMask&~1 ];
r0 = opStack[opStackOfs] = *(unsigned short *)&image[ r0&dataMask&~1 ];
goto nextInstruction2;
case OP_LOAD1:
r0 = *opStack = image[ r0&dataMask ];
r0 = opStack[opStackOfs] = image[ r0&dataMask ];
goto nextInstruction2;
case OP_STORE4:
*(int *)&image[ r1&(dataMask & ~3) ] = r0;
opStack -= 2;
opStackOfs -= 2;
goto nextInstruction;
case OP_STORE2:
*(short *)&image[ r1&(dataMask & ~1) ] = r0;
opStack -= 2;
opStackOfs -= 2;
goto nextInstruction;
case OP_STORE1:
image[ r1&dataMask ] = r0;
opStack -= 2;
opStackOfs -= 2;
goto nextInstruction;
case OP_ARG:
// single byte offset from programStack
*(int *)&image[ (codeImage[programCounter] + programStack)&dataMask&~3 ] = r0;
opStack--;
opStackOfs--;
programCounter += 1;
goto nextInstruction;
case OP_BLOCK_COPY:
{
int *src, *dest;
int count, srci, desti;
count = r2;
// MrE: copy range check
srci = r0 & dataMask;
desti = r1 & dataMask;
count = ((srci + count) & dataMask) - srci;
count = ((desti + count) & dataMask) - desti;
src = (int *)&image[ srci ];
dest = (int *)&image[ desti ];
memcpy(dest, src, count);
programCounter += 1;
opStack -= 2;
}
VM_BlockCopy(r1, r0, r2);
programCounter += 1;
opStackOfs -= 2;
goto nextInstruction;
case OP_CALL:
@ -494,7 +484,7 @@ nextInstruction2:
// jump to the location on the stack
programCounter = r0;
opStack--;
opStackOfs--;
if ( programCounter < 0 ) {
// system call
int r;
@ -539,8 +529,8 @@ nextInstruction2:
#endif
// save return value
opStack++;
*opStack = r;
opStackOfs++;
opStack[opStackOfs] = r;
programCounter = *(int *)&image[ programStack ];
// vm->callLevel = temp;
#ifdef DEBUG_VM
@ -550,6 +540,7 @@ nextInstruction2:
#endif
} else if ( (unsigned)programCounter >= vm->instructionCount ) {
Com_Error( ERR_DROP, "VM program counter out of range in OP_CALL" );
return 0;
} else {
programCounter = vm->instructionPointers[ programCounter ];
}
@ -557,10 +548,10 @@ nextInstruction2:
// push and pop are only needed for discarded or bad function return values
case OP_PUSH:
opStack++;
opStackOfs++;
goto nextInstruction;
case OP_POP:
opStack--;
opStackOfs--;
goto nextInstruction;
case OP_ENTER:
@ -607,6 +598,7 @@ nextInstruction2:
goto done;
} else if ( (unsigned)programCounter >= vm->codeLength ) {
Com_Error( ERR_DROP, "VM program counter out of range in OP_LEAVE" );
return 0;
}
goto nextInstruction;
@ -618,15 +610,18 @@ nextInstruction2:
case OP_JUMP:
if ( (unsigned)r0 >= vm->instructionCount )
{
Com_Error( ERR_DROP, "VM program counter out of range in OP_JUMP" );
return 0;
}
programCounter = vm->instructionPointers[ r0 ];
opStack--;
opStackOfs--;
goto nextInstruction;
case OP_EQ:
opStack -= 2;
opStackOfs -= 2;
if ( r1 == r0 ) {
programCounter = r2; //vm->instructionPointers[r2];
goto nextInstruction;
@ -636,7 +631,7 @@ nextInstruction2:
}
case OP_NE:
opStack -= 2;
opStackOfs -= 2;
if ( r1 != r0 ) {
programCounter = r2; //vm->instructionPointers[r2];
goto nextInstruction;
@ -646,7 +641,7 @@ nextInstruction2:
}
case OP_LTI:
opStack -= 2;
opStackOfs -= 2;
if ( r1 < r0 ) {
programCounter = r2; //vm->instructionPointers[r2];
goto nextInstruction;
@ -656,7 +651,7 @@ nextInstruction2:
}
case OP_LEI:
opStack -= 2;
opStackOfs -= 2;
if ( r1 <= r0 ) {
programCounter = r2; //vm->instructionPointers[r2];
goto nextInstruction;
@ -666,7 +661,7 @@ nextInstruction2:
}
case OP_GTI:
opStack -= 2;
opStackOfs -= 2;
if ( r1 > r0 ) {
programCounter = r2; //vm->instructionPointers[r2];
goto nextInstruction;
@ -676,7 +671,7 @@ nextInstruction2:
}
case OP_GEI:
opStack -= 2;
opStackOfs -= 2;
if ( r1 >= r0 ) {
programCounter = r2; //vm->instructionPointers[r2];
goto nextInstruction;
@ -686,7 +681,7 @@ nextInstruction2:
}
case OP_LTU:
opStack -= 2;
opStackOfs -= 2;
if ( ((unsigned)r1) < ((unsigned)r0) ) {
programCounter = r2; //vm->instructionPointers[r2];
goto nextInstruction;
@ -696,7 +691,7 @@ nextInstruction2:
}
case OP_LEU:
opStack -= 2;
opStackOfs -= 2;
if ( ((unsigned)r1) <= ((unsigned)r0) ) {
programCounter = r2; //vm->instructionPointers[r2];
goto nextInstruction;
@ -706,7 +701,7 @@ nextInstruction2:
}
case OP_GTU:
opStack -= 2;
opStackOfs -= 2;
if ( ((unsigned)r1) > ((unsigned)r0) ) {
programCounter = r2; //vm->instructionPointers[r2];
goto nextInstruction;
@ -716,7 +711,7 @@ nextInstruction2:
}
case OP_GEU:
opStack -= 2;
opStackOfs -= 2;
if ( ((unsigned)r1) >= ((unsigned)r0) ) {
programCounter = r2; //vm->instructionPointers[r2];
goto nextInstruction;
@ -726,68 +721,74 @@ nextInstruction2:
}
case OP_EQF:
if ( ((float *)opStack)[-1] == *(float *)opStack ) {
opStackOfs -= 2;
if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] == ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
{
programCounter = r2; //vm->instructionPointers[r2];
opStack -= 2;
goto nextInstruction;
} else {
programCounter += 1;
opStack -= 2;
goto nextInstruction;
}
case OP_NEF:
if ( ((float *)opStack)[-1] != *(float *)opStack ) {
opStackOfs -= 2;
if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] != ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
{
programCounter = r2; //vm->instructionPointers[r2];
opStack -= 2;
goto nextInstruction;
} else {
programCounter += 1;
opStack -= 2;
goto nextInstruction;
}
case OP_LTF:
if ( ((float *)opStack)[-1] < *(float *)opStack ) {
opStackOfs -= 2;
if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] < ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
{
programCounter = r2; //vm->instructionPointers[r2];
opStack -= 2;
goto nextInstruction;
} else {
programCounter += 1;
opStack -= 2;
goto nextInstruction;
}
case OP_LEF:
if ( ((float *)opStack)[-1] <= *(float *)opStack ) {
opStackOfs -= 2;
if(((float *) opStack)[(uint8_t) ((uint8_t) (opStackOfs + 1))] <= ((float *) opStack)[(uint8_t) ((uint8_t) (opStackOfs + 2))])
{
programCounter = r2; //vm->instructionPointers[r2];
opStack -= 2;
goto nextInstruction;
} else {
programCounter += 1;
opStack -= 2;
goto nextInstruction;
}
case OP_GTF:
if ( ((float *)opStack)[-1] > *(float *)opStack ) {
opStackOfs -= 2;
if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] > ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
{
programCounter = r2; //vm->instructionPointers[r2];
opStack -= 2;
goto nextInstruction;
} else {
programCounter += 1;
opStack -= 2;
goto nextInstruction;
}
case OP_GEF:
if ( ((float *)opStack)[-1] >= *(float *)opStack ) {
opStackOfs -= 2;
if(((float *) opStack)[(uint8_t) (opStackOfs + 1)] >= ((float *) opStack)[(uint8_t) (opStackOfs + 2)])
{
programCounter = r2; //vm->instructionPointers[r2];
opStack -= 2;
goto nextInstruction;
} else {
programCounter += 1;
opStack -= 2;
goto nextInstruction;
}
@ -795,101 +796,101 @@ nextInstruction2:
//===================================================================
case OP_NEGI:
*opStack = -r0;
opStack[opStackOfs] = -r0;
goto nextInstruction;
case OP_ADD:
opStack[-1] = r1 + r0;
opStack--;
opStackOfs--;
opStack[opStackOfs] = r1 + r0;
goto nextInstruction;
case OP_SUB:
opStack[-1] = r1 - r0;
opStack--;
opStackOfs--;
opStack[opStackOfs] = r1 - r0;
goto nextInstruction;
case OP_DIVI:
opStack[-1] = r1 / r0;
opStack--;
opStackOfs--;
opStack[opStackOfs] = r1 / r0;
goto nextInstruction;
case OP_DIVU:
opStack[-1] = ((unsigned)r1) / ((unsigned)r0);
opStack--;
opStackOfs--;
opStack[opStackOfs] = ((unsigned) r1) / ((unsigned) r0);
goto nextInstruction;
case OP_MODI:
opStack[-1] = r1 % r0;
opStack--;
opStackOfs--;
opStack[opStackOfs] = r1 % r0;
goto nextInstruction;
case OP_MODU:
opStack[-1] = ((unsigned)r1) % (unsigned)r0;
opStack--;
opStackOfs--;
opStack[opStackOfs] = ((unsigned) r1) % ((unsigned) r0);
goto nextInstruction;
case OP_MULI:
opStack[-1] = r1 * r0;
opStack--;
opStackOfs--;
opStack[opStackOfs] = r1 * r0;
goto nextInstruction;
case OP_MULU:
opStack[-1] = ((unsigned)r1) * ((unsigned)r0);
opStack--;
opStackOfs--;
opStack[opStackOfs] = ((unsigned) r1) * ((unsigned) r0);
goto nextInstruction;
case OP_BAND:
opStack[-1] = ((unsigned)r1) & ((unsigned)r0);
opStack--;
opStackOfs--;
opStack[opStackOfs] = ((unsigned) r1) & ((unsigned) r0);
goto nextInstruction;
case OP_BOR:
opStack[-1] = ((unsigned)r1) | ((unsigned)r0);
opStack--;
opStackOfs--;
opStack[opStackOfs] = ((unsigned) r1) | ((unsigned) r0);
goto nextInstruction;
case OP_BXOR:
opStack[-1] = ((unsigned)r1) ^ ((unsigned)r0);
opStack--;
opStackOfs--;
opStack[opStackOfs] = ((unsigned) r1) ^ ((unsigned) r0);
goto nextInstruction;
case OP_BCOM:
*opStack = ~ ((unsigned)r0);
opStack[opStackOfs] = ~((unsigned) r0);
goto nextInstruction;
case OP_LSH:
opStack[-1] = r1 << r0;
opStack--;
opStackOfs--;
opStack[opStackOfs] = r1 << r0;
goto nextInstruction;
case OP_RSHI:
opStack[-1] = r1 >> r0;
opStack--;
opStackOfs--;
opStack[opStackOfs] = r1 >> r0;
goto nextInstruction;
case OP_RSHU:
opStack[-1] = ((unsigned)r1) >> r0;
opStack--;
opStackOfs--;
opStack[opStackOfs] = ((unsigned) r1) >> r0;
goto nextInstruction;
case OP_NEGF:
*(float *)opStack = -*(float *)opStack;
((float *) opStack)[opStackOfs] = -((float *) opStack)[opStackOfs];
goto nextInstruction;
case OP_ADDF:
*(float *)(opStack-1) = *(float *)(opStack-1) + *(float *)opStack;
opStack--;
opStackOfs--;
((float *) opStack)[opStackOfs] = ((float *) opStack)[opStackOfs] + ((float *) opStack)[(uint8_t) (opStackOfs + 1)];
goto nextInstruction;
case OP_SUBF:
*(float *)(opStack-1) = *(float *)(opStack-1) - *(float *)opStack;
opStack--;
opStackOfs--;
((float *) opStack)[opStackOfs] = ((float *) opStack)[opStackOfs] - ((float *) opStack)[(uint8_t) (opStackOfs + 1)];
goto nextInstruction;
case OP_DIVF:
*(float *)(opStack-1) = *(float *)(opStack-1) / *(float *)opStack;
opStack--;
opStackOfs--;
((float *) opStack)[opStackOfs] = ((float *) opStack)[opStackOfs] / ((float *) opStack)[(uint8_t) (opStackOfs + 1)];
goto nextInstruction;
case OP_MULF:
*(float *)(opStack-1) = *(float *)(opStack-1) * *(float *)opStack;
opStack--;
opStackOfs--;
((float *) opStack)[opStackOfs] = ((float *) opStack)[opStackOfs] * ((float *) opStack)[(uint8_t) (opStackOfs + 1)];
goto nextInstruction;
case OP_CVIF:
*(float *)opStack = (float)*opStack;
((float *) opStack)[opStackOfs] = (float) opStack[opStackOfs];
goto nextInstruction;
case OP_CVFI:
*opStack = (int) *(float *)opStack;
opStack[opStackOfs] = Q_ftol(((float *) opStack)[opStackOfs]);
goto nextInstruction;
case OP_SEX8:
*opStack = (signed char)*opStack;
opStack[opStackOfs] = (signed char) opStack[opStackOfs];
goto nextInstruction;
case OP_SEX16:
*opStack = (short)*opStack;
opStack[opStackOfs] = (short) opStack[opStackOfs];
goto nextInstruction;
}
}
@ -897,12 +898,11 @@ nextInstruction2:
done:
vm->currentlyInterpreting = qfalse;
if ( opStack != &stack[1] ) {
Com_Error( ERR_DROP, "Interpreter error: opStack = %ld", (long int) (opStack - stack) );
}
if (opStackOfs != 1 || *opStack != 0xDEADBEEF)
Com_Error(ERR_DROP, "Interpreter error: opStack[0] = %X, opStackOfs = %d", opStack[0], opStackOfs);
vm->programStack = stackOnEntry;
// return the result
return *opStack;
return opStack[opStackOfs];
}

View file

@ -22,7 +22,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "q_shared.h"
#include "qcommon.h"
#define OPSTACK_SIZE 256
// don't change, this is hardcoded into x86 VMs, opStack protection relies
// on this
#define OPSTACK_SIZE 1024
#define OPSTACK_MASK (OPSTACK_SIZE-1)
// don't change
@ -139,7 +141,8 @@ struct vm_s {
//------------------------------------
char name[MAX_QPATH];
char name[MAX_QPATH];
void *searchPath; // hint for FS_ReadFileDir()
// for dynamic linked modules
void *dllHandle;
@ -151,9 +154,10 @@ struct vm_s {
qboolean compiled;
byte *codeBase;
int entryOfs;
int codeLength;
int *instructionPointers;
intptr_t *instructionPointers;
int instructionCount;
byte *dataBase;
@ -186,3 +190,5 @@ vmSymbol_t *VM_ValueToFunctionSymbol( vm_t *vm, int value );
int VM_SymbolToValue( vm_t *vm, const char *symbol );
const char *VM_ValueToSymbol( vm_t *vm, int value );
void VM_LogSyscalls( int *args );
void VM_BlockCopy(unsigned int dest, unsigned int src, size_t n);

View file

@ -47,7 +47,7 @@ static clock_t time_total_vm = 0;
/* exit() won't be called but use it because it is marked with noreturn */
#define DIE( reason ) \
do { \
Com_Error(ERR_DROP, "vm_powerpc compiler error: " reason "\n"); \
Com_Error(ERR_DROP, "vm_powerpc compiler error: " reason); \
exit(1); \
} while(0)
@ -389,23 +389,6 @@ VM_AsmCall( int callSyscallInvNum, int callProgramStack )
return ret;
}
static void
VM_BlockCopy( unsigned int dest, unsigned int src, unsigned int count )
{
unsigned dataMask = currentVM->dataMask;
if ( (dest & dataMask) != dest
|| (src & dataMask) != src
|| ((dest+count) & dataMask) != dest + count
|| ((src+count) & dataMask) != src + count)
{
DIE( "OP_BLOCK_COPY out of range!");
}
memcpy( currentVM->dataBase+dest, currentVM->dataBase+src, count );
}
/*
* code-block descriptors
*/

View file

@ -65,7 +65,6 @@ struct powerpc_opcode
};
static const struct powerpc_opcode powerpc_opcodes[];
static const int powerpc_num_opcodes;
#define PPC_OPCODE_PPC 1
#define PPC_OPCODE_POWER 2
@ -112,7 +111,6 @@ struct powerpc_operand
};
static const struct powerpc_operand powerpc_operands[];
static const unsigned int num_powerpc_operands;
#define PPC_OPERAND_SIGNED (0x1)
#define PPC_OPERAND_SIGNOPT (0x2)
@ -390,7 +388,6 @@ static const struct powerpc_operand powerpc_operands[] =
};
static const unsigned int num_powerpc_operands = ARRAY_LEN (powerpc_operands);
/* The functions used to insert and extract complicated operands. */

View file

@ -36,7 +36,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
/* exit() won't be called but use it because it is marked with noreturn */
#define DIE( reason ) \
do { \
Com_Error(ERR_DROP, "vm_sparc compiler error: " reason "\n"); \
Com_Error(ERR_DROP, "vm_sparc compiler error: " reason); \
exit(1); \
} while(0)
@ -511,6 +511,7 @@ typedef struct VM_Data {
int (*AsmCall)(int, int);
void (*BlockCopy)(unsigned int, unsigned int, unsigned int);
unsigned int *iPointers;
void (*ErrJump)(void);
unsigned int data[0];
} vm_data_t;
@ -698,11 +699,20 @@ static void dst_insn_append(struct func_info * const fp)
fp->insn_index = 0;
}
static void jump_insn_append(struct func_info * const fp, enum sparc_iname iname, int dest)
static void ErrJump(void)
{
Com_Error(ERR_DROP, "program tried to execute code outside VM\n");
exit(1);
}
static void jump_insn_append(vm_t *vm, struct func_info * const fp, enum sparc_iname iname, int dest)
{
struct jump_insn *jp = Z_Malloc(sizeof(*jp));
struct dst_insn *dp;
if (dest < 0 || dest >= vm->instructionCount)
ErrJump();
dp = dst_new(fp, 2, jp, 0);
jp->jump_iname = iname;
@ -734,10 +744,10 @@ static void end_emit(struct func_info * const fp)
dst_insn_append(fp);
}
static void emit_jump(struct func_info * const fp, enum sparc_iname iname, int dest)
static void emit_jump(vm_t *vm, struct func_info * const fp, enum sparc_iname iname, int dest)
{
end_emit(fp);
jump_insn_append(fp, iname, dest);
jump_insn_append(vm, fp, iname, dest);
}
static void analyze_function(struct func_info * const fp)
@ -860,7 +870,7 @@ do { int saved_i_count = (fp)->saved_icount; \
(fp)->saved_icount = saved_i_count; \
} while (0)
static void compile_one_insn(struct func_info * const fp, struct src_insn *sp)
static void compile_one_insn(vm_t *vm, struct func_info * const fp, struct src_insn *sp)
{
start_emit(fp, sp->i_count);
@ -928,11 +938,17 @@ static void compile_one_insn(struct func_info * const fp, struct src_insn *sp)
case OP_JUMP:
if (fp->cached_const) {
EMIT_FALSE_CONST(fp);
emit_jump(fp, BA, fp->cached_const->arg.i);
emit_jump(vm, fp, BA, fp->cached_const->arg.i);
} else {
MAYBE_EMIT_CONST(fp);
in(LDLI, rVMDATA, VM_Data_Offset(iPointers), rTMP);
in(SETHI, vm->instructionCount >> 10, rTMP);
in(ORI, rTMP, vm->instructionCount & 0x3ff, rTMP);
in(SUBCC, rTMP, rFIRST(fp), G0);
in(BLEU, +4*5);
in(LDLI, rVMDATA, VM_Data_Offset(ErrJump), rTMP);
in(SLLI, rFIRST(fp), 2, rFIRST(fp));
in(LDLI, rVMDATA, VM_Data_Offset(iPointers), rTMP);
in(LDL, rTMP, rFIRST(fp), rTMP);
in(JMPL, rTMP, G0, G0);
in(NOP);
@ -943,7 +959,7 @@ static void compile_one_insn(struct func_info * const fp, struct src_insn *sp)
if (fp->cached_const) {
EMIT_FALSE_CONST(fp);
if (fp->cached_const->arg.si >= 0) {
emit_jump(fp, CALL, fp->cached_const->arg.i);
emit_jump(vm, fp, CALL, fp->cached_const->arg.i);
} else {
in(LDLI, rVMDATA, VM_Data_Offset(CallThunk), rTMP);
in(LDLI, rVMDATA, VM_Data_Offset(AsmCall), O3);
@ -959,6 +975,11 @@ static void compile_one_insn(struct func_info * const fp, struct src_insn *sp)
in(NOP);
/* normal call */
in(SETHI, vm->instructionCount >> 10, rTMP);
in(ORI, rTMP, vm->instructionCount & 0x3ff, rTMP);
in(SUBCC, rTMP, rFIRST(fp), G0);
in(BLEU, +4*9);
in(LDLI, rVMDATA, VM_Data_Offset(ErrJump), rTMP);
in(LDLI, rVMDATA, VM_Data_Offset(iPointers), O5);
in(SLLI, rFIRST(fp), 2, rFIRST(fp));
in(LDL, O5, rFIRST(fp), rTMP);
@ -1124,7 +1145,7 @@ static void compile_one_insn(struct func_info * const fp, struct src_insn *sp)
case OP_GTU: iname = BGU; break;
case OP_LEU: iname = BLEU; break;
}
emit_jump(fp, iname, sp->arg.i);
emit_jump(vm, fp, iname, sp->arg.i);
POP_GPR(fp);
POP_GPR(fp);
break;
@ -1297,7 +1318,7 @@ static void compile_one_insn(struct func_info * const fp, struct src_insn *sp)
case OP_GTF: iname = FBG; break;
case OP_LEF: iname = FBLE; break;
}
emit_jump(fp, iname, sp->arg.i);
emit_jump(vm, fp, iname, sp->arg.i);
POP_FPR(fp);
POP_FPR(fp);
break;
@ -1344,7 +1365,7 @@ static void free_source_insns(struct func_info * const fp)
}
}
static void compile_function(struct func_info * const fp)
static void compile_function(vm_t *vm, struct func_info * const fp)
{
struct src_insn *sp;
@ -1359,7 +1380,7 @@ static void compile_function(struct func_info * const fp)
sp = fp->first;
while ((sp = sp->next) != NULL)
compile_one_insn(fp, sp);
compile_one_insn(vm, fp, sp);
free_source_insns(fp);
}
@ -1478,6 +1499,7 @@ static void sparc_compute_code(vm_t *vm, struct func_info * const fp)
data->iPointers = (unsigned int *) vm->instructionPointers;
data->dataLength = VM_Data_Offset(data[fp->data_num]);
data->codeLength = (code_now - code_begin) * sizeof(unsigned int);
data->ErrJump = ErrJump;
#if 0
{
@ -1564,7 +1586,7 @@ void VM_Compile(vm_t *vm, vmHeader_t *header)
if (op == OP_ENTER) {
if (fi.first->next)
compile_function(&fi);
compile_function(vm, &fi);
fi.first->next = NULL;
fi.last = fi.first;
fi.has_call = fi.need_float_tmp = 0;
@ -1592,7 +1614,7 @@ void VM_Compile(vm_t *vm, vmHeader_t *header)
fi.last->next = sp;
fi.last = sp;
}
compile_function(&fi);
compile_function(vm, &fi);
Z_Free(fi.first);

File diff suppressed because it is too large Load diff

View file

@ -70,22 +70,23 @@ static void VM_Destroy_Compiled(vm_t* self);
|
+- r8
eax scratch
ebx scratch
ecx scratch (required for shifts)
edx scratch (required for divisions)
rsi stack pointer (opStack)
rdi program frame pointer (programStack)
r8 pointer data (vm->dataBase)
r10 start of generated code
eax scratch
rbx/bl opStack offset
ecx scratch (required for shifts)
edx scratch (required for divisions)
rsi scratch
rdi program frame pointer (programStack)
r8 pointer data (vm->dataBase)
r9 opStack base (opStack)
r10 start of generated code
*/
static int64_t CROSSCALL callAsmCall(int64_t callProgramStack, int64_t callSyscallNum)
static intptr_t CROSSCALL callAsmCall(intptr_t callProgramStack, int64_t callSyscallNum)
{
vm_t *savedVM;
int64_t ret = 0x77;
int64_t args[11];
intptr_t ret = 0x77;
intptr_t args[11];
// int iargs[11];
int i;
@ -238,18 +239,41 @@ void emit(const char* fmt, ...)
assemble_line(line, strlen(line));
}
#ifdef DEBUG_VM
#define RANGECHECK(reg, bytes) \
emit("movl %%" #reg ", %%ecx"); \
emit("andl $0x%x, %%ecx", vm->dataMask &~(bytes-1)); \
emit("cmpl %%" #reg ", %%ecx"); \
emit("jz rc_ok_i_%08x", instruction); \
emit("movq $%"PRIu64", %%rax", (intptr_t) memviolation); \
emit("callq *%%rax"); \
emit("rc_ok_i_%08x:", instruction)
#elif 1
// check is too expensive, so just confine memory access
#define RANGECHECK(reg, bytes) \
emit("andl $0x%x, %%" #reg, vm->dataMask &~(bytes-1))
#else
#define RANGECHECK(reg, bytes)
#endif
#define STACK_PUSH(bytes) \
emit("addb $0x%x, %%bl", bytes >> 2); \
#define STACK_POP(bytes) \
emit("subb $0x%x, %%bl", bytes >> 2); \
#define CHECK_INSTR_REG(reg) \
emit("cmpl $%u, %%"#reg, header->instructionCount); \
emit("jb jmp_ok_i_%08x", instruction); \
emit("movq $%"PRIu64", %%rax", (uint64_t)jmpviolation); \
emit("movq $%"PRIu64", %%rax", (intptr_t)jmpviolation); \
emit("callq *%%rax"); \
emit("jmp_ok_i_%08x:", instruction);
emit("jmp_ok_i_%08x:", instruction)
#define PREPARE_JMP(reg) \
CHECK_INSTR_REG(reg) \
emit("movq $%"PRIu64", %%rbx", (uint64_t)vm->instructionPointers); \
emit("movl (%%rbx, %%rax, 4), %%eax"); \
emit("addq %%r10, %%rax");
CHECK_INSTR_REG(reg); \
emit("movq $%"PRIu64", %%rsi", (intptr_t)vm->instructionPointers); \
emit("movl (%%rsi, %%rax, 8), %%eax"); \
emit("addq %%r10, %%rax")
#define CHECK_INSTR(nr) \
do { if(nr < 0 || nr >= header->instructionCount) { \
@ -258,10 +282,10 @@ void emit(const char* fmt, ...)
"%s: jump target 0x%x out of range at offset %d", __func__, nr, pc ); \
} } while(0)
#define JMPIARG \
#define JMPIARG() \
CHECK_INSTR(iarg); \
emit("movq $%"PRIu64", %%rax", vm->codeBase+vm->instructionPointers[iarg]); \
emit("jmpq *%%rax");
emit("jmpq *%%rax")
#define CONST_OPTIMIZE
#ifdef CONST_OPTIMIZE
@ -270,8 +294,8 @@ void emit(const char* fmt, ...)
{ \
got_const = 0; \
vm->instructionPointers[instruction-1] = assembler_get_code_size(); \
emit("addq $4, %%rsi"); \
emit("movl $%d, 0(%%rsi)", const_value); \
STACK_PUSH(4); \
emit("movl $%d, (%%r9, %%rbx, 4)", const_value); \
}
#else
#define MAYBE_EMIT_CONST()
@ -280,90 +304,73 @@ void emit(const char* fmt, ...)
// integer compare and jump
#define IJ(op) \
MAYBE_EMIT_CONST(); \
emit("subq $8, %%rsi"); \
emit("movl 4(%%rsi), %%eax"); \
emit("cmpl 8(%%rsi), %%eax"); \
STACK_POP(8); \
emit("movl 4(%%r9, %%rbx, 4), %%eax"); \
emit("cmpl 8(%%r9, %%rbx, 4), %%eax"); \
emit(op " i_%08x", instruction+1); \
JMPIARG \
neednilabel = 1;
JMPIARG(); \
neednilabel = 1
#ifdef USE_X87
#define FJ(bits, op) \
MAYBE_EMIT_CONST(); \
emit("subq $8, %%rsi");\
emit("flds 4(%%rsi)");\
emit("fcomps 8(%%rsi)");\
STACK_POP(8); \
emit("flds 4(%%r9, %%rbx, 4)");\
emit("fcomps 8(%%r9, %%rbx, 4)");\
emit("fnstsw %%ax");\
emit("testb $" #bits ", %%ah");\
emit(op " i_%08x", instruction+1);\
JMPIARG \
neednilabel = 1;
JMPIARG(); \
neednilabel = 1
#define XJ(x)
#else
#define FJ(x, y)
#define XJ(op) \
MAYBE_EMIT_CONST(); \
emit("subq $8, %%rsi");\
emit("movss 4(%%rsi), %%xmm0");\
emit("ucomiss 8(%%rsi), %%xmm0");\
STACK_POP(8); \
emit("movss 4(%%r9, %%rbx, 4), %%xmm0");\
emit("ucomiss 8(%%r9, %%rbx, 4), %%xmm0");\
emit("jp i_%08x", instruction+1);\
emit(op " i_%08x", instruction+1);\
JMPIARG \
neednilabel = 1;
JMPIARG(); \
neednilabel = 1
#endif
#define SIMPLE(op) \
MAYBE_EMIT_CONST(); \
emit("subq $4, %%rsi"); \
emit("movl 4(%%rsi), %%eax"); \
emit(op " %%eax, 0(%%rsi)");
emit("movl (%%r9, %%rbx, 4), %%eax"); \
STACK_POP(4); \
emit(op " %%eax, (%%r9, %%rbx, 4)")
#ifdef USE_X87
#define FSIMPLE(op) \
MAYBE_EMIT_CONST(); \
emit("subq $4, %%rsi"); \
emit("flds 0(%%rsi)"); \
emit(op " 4(%%rsi)"); \
emit("fstps 0(%%rsi)");
STACK_POP(4); \
emit("flds (%%r9, %%rbx, 4)"); \
emit(op " 4(%%r9, %%rbx, 4)"); \
emit("fstps (%%r9, %%rbx, 4)")
#define XSIMPLE(op)
#else
#define FSIMPLE(op)
#define XSIMPLE(op) \
MAYBE_EMIT_CONST(); \
emit("subq $4, %%rsi"); \
emit("movss 0(%%rsi), %%xmm0"); \
emit(op " 4(%%rsi), %%xmm0"); \
emit("movss %%xmm0, 0(%%rsi)");
STACK_POP(4); \
emit("movss (%%r9, %%rbx, 4), %%xmm0"); \
emit(op " 4(%%r9, %%rbx, 4), %%xmm0"); \
emit("movss %%xmm0, (%%r9, %%rbx, 4)")
#endif
#define SHIFT(op) \
MAYBE_EMIT_CONST(); \
emit("subq $4, %%rsi"); \
emit("movl 4(%%rsi), %%ecx"); \
emit("movl 0(%%rsi), %%eax"); \
STACK_POP(4); \
emit("movl 4(%%r9, %%rbx, 4), %%ecx"); \
emit("movl (%%r9, %%rbx, 4), %%eax"); \
emit(op " %%cl, %%eax"); \
emit("movl %%eax, 0(%%rsi)");
#ifdef DEBUG_VM
#define RANGECHECK(reg, bytes) \
emit("movl %%" #reg ", %%ecx"); \
emit("andl $0x%x, %%ecx", vm->dataMask &~(bytes-1)); \
emit("cmpl %%" #reg ", %%ecx"); \
emit("jz rc_ok_i_%08x", instruction); \
emit("movq $%"PRIu64", %%rax", (uint64_t)memviolation); \
emit("callq *%%rax"); \
emit("rc_ok_i_%08x:", instruction);
#elif 1
// check is too expensive, so just confine memory access
#define RANGECHECK(reg, bytes) \
emit("andl $0x%x, %%" #reg, vm->dataMask &~(bytes-1));
#else
#define RANGECHECK(reg, bytes)
#endif
emit("movl %%eax, (%%r9, %%rbx, 4)")
#ifdef DEBUG_VM
#define NOTIMPL(x) \
do { Com_Error(ERR_DROP, "instruction not implemented: %s\n", opnames[x]); } while(0)
do { Com_Error(ERR_DROP, "instruction not implemented: %s", opnames[x]); } while(0)
#else
#define NOTIMPL(x) \
do { Com_Printf(S_COLOR_RED "instruction not implemented: %x\n", x); vm->compiled = qfalse; return; } while(0)
@ -374,37 +381,28 @@ static void* getentrypoint(vm_t* vm)
return vm->codeBase;
}
static void CROSSCALL block_copy_vm(unsigned dest, unsigned src, unsigned count)
{
unsigned dataMask = currentVM->dataMask;
if ((dest & dataMask) != dest
|| (src & dataMask) != src
|| ((dest+count) & dataMask) != dest + count
|| ((src+count) & dataMask) != src + count)
{
Com_Error(ERR_DROP, "OP_BLOCK_COPY out of range!\n");
}
memcpy(currentVM->dataBase+dest, currentVM->dataBase+src, count);
}
static void CROSSCALL eop(void)
{
Com_Error(ERR_DROP, "end of program reached without return!\n");
Com_Error(ERR_DROP, "End of program reached without return!");
exit(1);
}
static void CROSSCALL jmpviolation(void)
{
Com_Error(ERR_DROP, "program tried to execute code outside VM\n");
Com_Error(ERR_DROP, "Program tried to execute code outside VM");
exit(1);
}
#ifdef DEBUG_VM
static void CROSSCALL memviolation(void)
{
Com_Error(ERR_DROP, "program tried to access memory outside VM\n");
Com_Error(ERR_DROP, "Program tried to access memory outside VM, or unaligned memory access");
exit(1);
}
static void CROSSCALL opstackviolation(void)
{
Com_Error(ERR_DROP, "Program corrupted the VM opStack");
exit(1);
}
#endif
@ -535,23 +533,24 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
break;
case OP_CALL:
RANGECHECK(edi, 4);
emit("movl $%d, 0(%%r8, %%rdi, 1)", instruction+1); // save next instruction
emit("movl $%d, (%%r8, %%rdi, 1)", instruction+1); // save next instruction
if(got_const)
{
if ((int)const_value < 0)
goto emit_do_syscall;
CHECK_INSTR(const_value);
emit("movq $%"PRIu64", %%rax", vm->codeBase+vm->instructionPointers[const_value]);
emit("callq *%%rax");
got_const = 0;
break;
if ((int) const_value >= 0)
{
CHECK_INSTR(const_value);
emit("movq $%"PRIu64", %%rax", vm->codeBase+vm->instructionPointers[const_value]);
emit("callq *%%rax");
got_const = 0;
break;
}
}
else
{
MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get instr from stack
emit("subq $4, %%rsi");
emit("movl (%%r9, %%rbx, 4), %%eax"); // get instr from stack
STACK_POP(4);
emit("orl %%eax, %%eax");
emit("jl callSyscall%d", instruction);
@ -562,48 +561,45 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) {
emit("jmp i_%08x", instruction+1);
emit("callSyscall%d:", instruction);
}
emit_do_syscall:
// emit("fnsave 4(%%rsi)");
emit("push %%rsi");
// emit("fnsave 4(%%r9, %%rsi, 1)");
emit("push %%rdi");
emit("push %%r8");
emit("push %%r9");
emit("push %%r10");
emit("movq %%rsp, %%rbx"); // we need to align the stack pointer
emit("subq $8, %%rbx"); // |
emit("andq $127, %%rbx"); // |
emit("subq %%rbx, %%rsp"); // <-+
emit("push %%rbx");
emit("movq %%rsp, %%rsi"); // we need to align the stack pointer
emit("subq $8, %%rsi"); // |
emit("andq $127, %%rsi"); // |
emit("subq %%rsi, %%rsp"); // <-+
emit("push %%rsi");
if(got_const) {
got_const = 0;
emit("movq $%u, %%rsi", -1-const_value); // second argument in rsi
} else {
emit("negl %%eax"); // convert to actual number
emit("decl %%eax");
emit("notl %%eax"); // convert to actual number
// first argument already in rdi
emit("movq %%rax, %%rsi"); // second argument in rsi
}
emit("movq $%"PRIu64", %%rax", (uint64_t)callAsmCall);
emit("movq $%"PRIu64", %%rax", (intptr_t) callAsmCall);
emit("callq *%%rax");
emit("pop %%rbx");
emit("addq %%rbx, %%rsp");
emit("pop %%rsi");
emit("addq %%rsi, %%rsp");
emit("pop %%r10");
emit("pop %%r9");
emit("pop %%r8");
emit("pop %%rdi");
emit("pop %%rsi");
// emit("frstor 4(%%rsi)");
emit("addq $4, %%rsi");
emit("movl %%eax, (%%rsi)"); // store return value
// emit("frstor 4(%%r9, %%rsi, 1)");
STACK_PUSH(4);
emit("movl %%eax, (%%r9, %%rbx, 4)"); // store return value
neednilabel = 1;
break;
case OP_PUSH:
MAYBE_EMIT_CONST();
emit("addq $4, %%rsi");
STACK_PUSH(4);
break;
case OP_POP:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
STACK_POP(4);
break;
case OP_CONST:
MAYBE_EMIT_CONST();
@ -611,25 +607,25 @@ emit_do_syscall:
got_const = 1;
const_value = iarg;
#else
emit("addq $4, %%rsi");
emit("movl $%d, 0(%%rsi)", iarg);
STACK_PUSH(4);
emit("movl $%d, (%%r9, %%rbx, 4)", iarg);
#endif
break;
case OP_LOCAL:
MAYBE_EMIT_CONST();
emit("movl %%edi, %%ebx");
emit("addl $%d,%%ebx", iarg);
emit("addq $4, %%rsi");
emit("movl %%ebx, 0(%%rsi)");
emit("movl %%edi, %%esi");
emit("addl $%d,%%esi", iarg);
STACK_PUSH(4);
emit("movl %%esi, (%%r9, %%rbx, 4)");
break;
case OP_JUMP:
if(got_const) {
iarg = const_value;
got_const = 0;
JMPIARG;
JMPIARG();
} else {
emit("movl 0(%%rsi), %%eax"); // get instr from stack
emit("subq $4, %%rsi");
emit("movl (%%r9, %%rbx, 4), %%eax"); // get instr from stack
STACK_POP(4);
PREPARE_JMP(eax);
emit("jmp *%%rax");
@ -673,13 +669,13 @@ emit_do_syscall:
FJ(0x40, "jnz");
#ifndef USE_X87
MAYBE_EMIT_CONST();
emit("subq $8, %%rsi");
emit("movss 4(%%rsi), %%xmm0");
emit("ucomiss 8(%%rsi), %%xmm0");
STACK_POP(8);
emit("movss 4(%%r9, %%rbx, 4), %%xmm0");
emit("ucomiss 8(%%r9, %%rbx, 4), %%xmm0");
emit("jp dojump_i_%08x", instruction);
emit("jz i_%08x", instruction+1);
emit("dojump_i_%08x:", instruction);
JMPIARG
JMPIARG();
neednilabel = 1;
#endif
break;
@ -701,105 +697,103 @@ emit_do_syscall:
break;
case OP_LOAD1:
MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack
emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
RANGECHECK(eax, 1);
emit("movb 0(%%r8, %%rax, 1), %%al"); // deref into eax
emit("movb (%%r8, %%rax, 1), %%al"); // deref into eax
emit("andq $255, %%rax");
emit("movl %%eax, 0(%%rsi)"); // store on stack
emit("movl %%eax, (%%r9, %%rbx, 4)"); // store on stack
break;
case OP_LOAD2:
MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack
emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
RANGECHECK(eax, 2);
emit("movw 0(%%r8, %%rax, 1), %%ax"); // deref into eax
emit("movl %%eax, 0(%%rsi)"); // store on stack
emit("movw (%%r8, %%rax, 1), %%ax"); // deref into eax
emit("movl %%eax, (%%r9, %%rbx, 4)"); // store on stack
break;
case OP_LOAD4:
MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack
emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
RANGECHECK(eax, 4); // not a pointer!?
emit("movl 0(%%r8, %%rax, 1), %%eax"); // deref into eax
emit("movl %%eax, 0(%%rsi)"); // store on stack
emit("movl (%%r8, %%rax, 1), %%eax"); // deref into eax
emit("movl %%eax, (%%r9, %%rbx, 4)"); // store on stack
break;
case OP_STORE1:
MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack
emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
STACK_POP(8);
emit("andq $255, %%rax");
emit("movl -4(%%rsi), %%ebx"); // get pointer from stack
RANGECHECK(ebx, 1);
emit("movb %%al, 0(%%r8, %%rbx, 1)"); // store in memory
emit("subq $8, %%rsi");
emit("movl 4(%%r9, %%rbx, 4), %%esi"); // get pointer from stack
RANGECHECK(esi, 1);
emit("movb %%al, (%%r8, %%rsi, 1)"); // store in memory
break;
case OP_STORE2:
MAYBE_EMIT_CONST();
emit("movl 0(%%rsi), %%eax"); // get value from stack
emit("movl -4(%%rsi), %%ebx"); // get pointer from stack
RANGECHECK(ebx, 2);
emit("movw %%ax, 0(%%r8, %%rbx, 1)"); // store in memory
emit("subq $8, %%rsi");
emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
STACK_POP(8);
emit("movl 4(%%r9, %%rbx, 4), %%esi"); // get pointer from stack
RANGECHECK(esi, 2);
emit("movw %%ax, (%%r8, %%rsi, 1)"); // store in memory
break;
case OP_STORE4:
MAYBE_EMIT_CONST();
emit("movl -4(%%rsi), %%ebx"); // get pointer from stack
RANGECHECK(ebx, 4);
emit("movl 0(%%rsi), %%ecx"); // get value from stack
emit("movl %%ecx, 0(%%r8, %%rbx, 1)"); // store in memory
emit("subq $8, %%rsi");
emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
STACK_POP(8);
emit("movl 4(%%r9, %%rbx, 4), %%esi"); // get pointer from stack
RANGECHECK(esi, 4);
emit("movl %%eax, (%%r8, %%rsi, 1)"); // store in memory
break;
case OP_ARG:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 4(%%rsi), %%eax"); // get value from stack
emit("movl $0x%hx, %%ebx", barg);
emit("addl %%edi, %%ebx");
RANGECHECK(ebx, 4);
emit("movl %%eax, 0(%%r8,%%rbx, 1)"); // store in args space
emit("movl (%%r9, %%rbx, 4), %%eax"); // get value from stack
STACK_POP(4);
emit("movl $0x%hx, %%esi", barg);
emit("addl %%edi, %%esi");
RANGECHECK(esi, 4);
emit("movl %%eax, (%%r8,%%rsi, 1)"); // store in args space
break;
case OP_BLOCK_COPY:
MAYBE_EMIT_CONST();
emit("subq $8, %%rsi");
emit("push %%rsi");
STACK_POP(8);
emit("push %%rdi");
emit("push %%r8");
emit("push %%r9");
emit("push %%r10");
emit("movq %%rsp, %%rbx"); // we need to align the stack pointer
emit("subq $8, %%rbx"); // |
emit("andq $127, %%rbx"); // |
emit("subq %%rbx, %%rsp"); // <-+
emit("push %%rbx");
emit("movl 4(%%rsi), %%edi"); // 1st argument dest
emit("movl 8(%%rsi), %%esi"); // 2nd argument src
emit("movq %%rsp, %%rsi"); // we need to align the stack pointer
emit("subq $8, %%rsi"); // |
emit("andq $127, %%rsi"); // |
emit("subq %%rsi, %%rsp"); // <-+
emit("push %%rsi");
emit("movl 4(%%r9, %%rbx, 4), %%edi"); // 1st argument dest
emit("movl 8(%%r9, %%rbx, 4), %%rsi"); // 2nd argument src
emit("movl $%d, %%edx", iarg); // 3rd argument count
emit("movq $%"PRIu64", %%rax", (uint64_t)block_copy_vm);
emit("movq $%"PRIu64", %%rax", (intptr_t) VM_BlockCopy);
emit("callq *%%rax");
emit("pop %%rbx");
emit("addq %%rbx, %%rsp");
emit("pop %%rsi");
emit("addq %%rsi, %%rsp");
emit("pop %%r10");
emit("pop %%r9");
emit("pop %%r8");
emit("pop %%rdi");
emit("pop %%rsi");
break;
case OP_SEX8:
MAYBE_EMIT_CONST();
emit("movw 0(%%rsi), %%ax");
emit("movw (%%r9, %%rbx, 4), %%ax");
emit("andq $255, %%rax");
emit("cbw");
emit("cwde");
emit("movl %%eax, 0(%%rsi)");
emit("movl %%eax, (%%r9, %%rbx, 4)");
break;
case OP_SEX16:
MAYBE_EMIT_CONST();
emit("movw 0(%%rsi), %%ax");
emit("movw (%%r9, %%rbx, 4), %%ax");
emit("cwde");
emit("movl %%eax, 0(%%rsi)");
emit("movl %%eax, (%%r9, %%rbx, 4)");
break;
case OP_NEGI:
MAYBE_EMIT_CONST();
emit("negl 0(%%rsi)");
emit("negl (%%r9, %%rbx, 4)");
break;
case OP_ADD:
SIMPLE("addl");
@ -809,50 +803,50 @@ emit_do_syscall:
break;
case OP_DIVI:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
STACK_POP(4);
emit("movl (%%r9, %%rbx, 4), %%eax");
emit("cdq");
emit("idivl 4(%%rsi)");
emit("movl %%eax, 0(%%rsi)");
emit("idivl 4(%%r9, %%rbx, 4)");
emit("movl %%eax, (%%r9, %%rbx, 4)");
break;
case OP_DIVU:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
STACK_POP(4);
emit("movl (%%r9, %%rbx, 4), %%eax");
emit("xorq %%rdx, %%rdx");
emit("divl 4(%%rsi)");
emit("movl %%eax, 0(%%rsi)");
emit("divl 4(%%r9, %%rbx, 4)");
emit("movl %%eax, (%%r9, %%rbx, 4)");
break;
case OP_MODI:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
STACK_POP(4);
emit("movl (%%r9, %%rbx, 4), %%eax");
emit("xorl %%edx, %%edx");
emit("cdq");
emit("idivl 4(%%rsi)");
emit("movl %%edx, 0(%%rsi)");
emit("idivl 4(%%r9, %%rbx, 4)");
emit("movl %%edx, (%%r9, %%rbx, 4)");
break;
case OP_MODU:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
STACK_POP(4);
emit("movl (%%r9, %%rbx, 4), %%eax");
emit("xorl %%edx, %%edx");
emit("divl 4(%%rsi)");
emit("movl %%edx, 0(%%rsi)");
emit("divl 4(%%r9, %%rbx, 4)");
emit("movl %%edx, (%%r9, %%rbx, 4)");
break;
case OP_MULI:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
emit("imull 4(%%rsi)");
emit("movl %%eax, 0(%%rsi)");
STACK_POP(4);
emit("movl (%%r9, %%rbx, 4), %%eax");
emit("imull 4(%%r9, %%rbx, 4)");
emit("movl %%eax, (%%r9, %%rbx, 4)");
break;
case OP_MULU:
MAYBE_EMIT_CONST();
emit("subq $4, %%rsi");
emit("movl 0(%%rsi), %%eax");
emit("mull 4(%%rsi)");
emit("movl %%eax, 0(%%rsi)");
STACK_POP(4);
emit("movl (%%r9, %%rbx, 4), %%eax");
emit("mull 4(%%r9, %%rbx, 4)");
emit("movl %%eax, (%%r9, %%rbx, 4)");
break;
case OP_BAND:
SIMPLE("andl");
@ -865,7 +859,7 @@ emit_do_syscall:
break;
case OP_BCOM:
MAYBE_EMIT_CONST();
emit("notl 0(%%rsi)");
emit("notl (%%r9, %%rbx, 4)");
break;
case OP_LSH:
SHIFT("shl");
@ -879,12 +873,12 @@ emit_do_syscall:
case OP_NEGF:
MAYBE_EMIT_CONST();
#ifdef USE_X87
emit("flds 0(%%rsi)");
emit("flds (%%r9, %%rbx, 4)");
emit("fchs");
emit("fstps 0(%%rsi)");
emit("fstps (%%r9, %%rbx, 4)");
#else
emit("movl $0x80000000, %%eax");
emit("xorl %%eax, 0(%%rsi)");
emit("xorl %%eax, (%%r9, %%rbx, 4)");
#endif
break;
case OP_ADDF:
@ -906,27 +900,27 @@ emit_do_syscall:
case OP_CVIF:
MAYBE_EMIT_CONST();
#ifdef USE_X87
emit("filds 0(%%rsi)");
emit("fstps 0(%%rsi)");
emit("filds (%%r9, %%rbx, 4)");
emit("fstps (%%r9, %%rbx, 4)");
#else
emit("movl 0(%%rsi), %%eax");
emit("movl (%%r9, %%rbx, 4), %%eax");
emit("cvtsi2ss %%eax, %%xmm0");
emit("movss %%xmm0, 0(%%rsi)");
emit("movss %%xmm0, (%%r9, %%rbx, 4)");
#endif
break;
case OP_CVFI:
MAYBE_EMIT_CONST();
#ifdef USE_X87
emit("flds 0(%%rsi)");
emit("fnstcw 4(%%rsi)");
emit("movw $0x0F7F, 8(%%rsi)"); // round toward zero
emit("fldcw 8(%%rsi)");
emit("fistpl 0(%%rsi)");
emit("fldcw 4(%%rsi)");
emit("flds (%%r9, %%rbx, 4)");
emit("fnstcw 4(%%r9, %%rbx, 4)");
emit("movw $0x0F7F, 8(%%r9, %%rbx, 4)"); // round toward zero
emit("fldcw 8(%%r9, %%rbx, 4)");
emit("fistpl (%%r9, %%rbx, 4)");
emit("fldcw 4(%%r9, %%rbx, 4)");
#else
emit("movss 0(%%rsi), %%xmm0");
emit("movss (%%r9, %%rbx, 4), %%xmm0");
emit("cvttss2si %%xmm0, %%eax");
emit("movl %%eax, 0(%%rsi)");
emit("movl %%eax, (%%r9, %%rbx, 4)");
#endif
break;
default:
@ -940,10 +934,10 @@ emit_do_syscall:
if(got_const)
{
VM_FREEBUFFERS(vm);
Com_Error(ERR_DROP, "leftover const\n");
Com_Error(ERR_DROP, "leftover const");
}
emit("movq $%"PRIu64", %%rax", (uint64_t)eop);
emit("movq $%"PRIu64", %%rax", (intptr_t) eop);
emit("callq *%%rax");
} // pass loop
@ -1020,17 +1014,19 @@ This function is called directly by the generated code
static char* memData;
#endif
int VM_CallCompiled( vm_t *vm, int *args ) {
int VM_CallCompiled(vm_t *vm, int *args)
{
int stack[OPSTACK_SIZE + 15];
int programCounter;
int programStack;
int stackOnEntry;
long opStackRet;
byte *image;
void *entryPoint;
void *opStack;
int stack[1024] = { 0xDEADBEEF };
int *opStack;
currentVM = vm;
// Com_Printf("entering %s level %d, call %d, arg1 = 0x%x\n", vm->name, vm->callLevel, args[0], args[1]);
// interpret the code
@ -1067,32 +1063,40 @@ int VM_CallCompiled( vm_t *vm, int *args ) {
// off we go into generated code...
entryPoint = getentrypoint(vm);
opStack = &stack;
opStack = PADP(stack, 16);
*opStack = 0xDEADBEEF;
opStackRet = 0;
__asm__ __volatile__ (
" movq %5,%%rsi \r\n" \
" movl %4,%%edi \r\n" \
" movq %4,%%r8 \r\n" \
" movq %3,%%r9 \r\n" \
" movq %2,%%r10 \r\n" \
" movq %3,%%r8 \r\n" \
" push %%r15 \r\n" \
" push %%r14 \r\n" \
" push %%r13 \r\n" \
" push %%r12 \r\n" \
" subq $24, %%rsp # fix alignment as call pushes one value \r\n" \
" callq *%%r10 \r\n" \
" addq $24, %%rsp \r\n" \
" movl %%edi, %0 \r\n" \
" movq %%rsi, %1 \r\n" \
: "=m" (programStack), "=m" (opStack)
: "m" (entryPoint), "m" (vm->dataBase), "m" (programStack), "m" (opStack)
: "%rsi", "%rdi", "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r10", "%r15", "%xmm0"
" addq $24, %%rsp \r\n" \
" pop %%r12 \r\n" \
" pop %%r13 \r\n" \
" pop %%r14 \r\n" \
" pop %%r15 \r\n"
: "+D" (programStack), "+b" (opStackRet)
: "g" (entryPoint), "g" (opStack), "g" (vm->dataBase), "g" (programStack)
: "%rsi", "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%xmm0"
);
if ( opStack != &stack[1] ) {
Com_Error( ERR_DROP, "opStack corrupted in compiled code (offset %"PRId64")\n", (int64_t) ((void *) &stack[1] - opStack));
}
if(opStackRet != 1 || *opStack != 0xDEADBEEF)
Com_Error(ERR_DROP, "opStack corrupted in compiled code (offset %ld)", opStackRet);
if ( programStack != stackOnEntry - 48 ) {
Com_Error( ERR_DROP, "programStack corrupted in compiled code\n" );
Com_Error( ERR_DROP, "programStack corrupted in compiled code" );
}
// Com_Printf("exiting %s level %d\n", vm->name, vm->callLevel);
vm->programStack = stackOnEntry;
return *(int *)opStack;
return stack[1];
}

View file

@ -43,9 +43,6 @@ static const char* cur_line;
static FILE* fout;
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define crap(fmt, args...) do { \
_crap(__FUNCTION__, fmt, ##args); \
} while(0)
@ -161,6 +158,7 @@ typedef enum {
R_R15 = 0x0F | R_64,
R_AL = R_EAX | R_8,
R_AX = R_EAX | R_16,
R_BL = R_EBX | R_8,
R_CL = R_ECX | R_8,
R_XMM0 = 0x00 | R_XMM,
R_MGP = 0x0F, // mask for general purpose registers
@ -216,6 +214,32 @@ typedef struct {
u8 rcode; // opcode for reg/mem
} opparam_t;
static opparam_t params_add = { subcode: 0, rmcode: 0x01, };
static opparam_t params_or = { subcode: 1, rmcode: 0x09, };
static opparam_t params_and = { subcode: 4, rmcode: 0x21, };
static opparam_t params_sub = { subcode: 5, rmcode: 0x29, };
static opparam_t params_xor = { subcode: 6, rmcode: 0x31, };
static opparam_t params_cmp = { subcode: 7, rmcode: 0x39, mrcode: 0x3b, };
static opparam_t params_dec = { subcode: 1, rcode: 0xff, rcode8: 0xfe, };
static opparam_t params_sar = { subcode: 7, rcode: 0xd3, rcode8: 0xd2, };
static opparam_t params_shl = { subcode: 4, rcode: 0xd3, rcode8: 0xd2, };
static opparam_t params_shr = { subcode: 5, rcode: 0xd3, rcode8: 0xd2, };
static opparam_t params_idiv = { subcode: 7, rcode: 0xf7, rcode8: 0xf6, };
static opparam_t params_div = { subcode: 6, rcode: 0xf7, rcode8: 0xf6, };
static opparam_t params_imul = { subcode: 5, rcode: 0xf7, rcode8: 0xf6, };
static opparam_t params_mul = { subcode: 4, rcode: 0xf7, rcode8: 0xf6, };
static opparam_t params_neg = { subcode: 3, rcode: 0xf7, rcode8: 0xf6, };
static opparam_t params_not = { subcode: 2, rcode: 0xf7, rcode8: 0xf6, };
static opparam_t params_cvtsi2ss = { xmmprefix: 0xf3, rmcode: 0x2a };
static opparam_t params_cvttss2si = { xmmprefix: 0xf3, rmcode: 0x2c };
static opparam_t params_addss = { xmmprefix: 0xf3, mrcode: 0x58 };
static opparam_t params_divss = { xmmprefix: 0xf3, mrcode: 0x5e };
static opparam_t params_movss = { xmmprefix: 0xf3, mrcode: 0x10, rmcode: 0x11 };
static opparam_t params_mulss = { xmmprefix: 0xf3, mrcode: 0x59 };
static opparam_t params_subss = { xmmprefix: 0xf3, mrcode: 0x5c };
static opparam_t params_ucomiss = { mrcode: 0x2e };
/* ************************* */
static unsigned hashkey(const char *string, unsigned len) {
@ -317,34 +341,34 @@ static const char* argtype2str(argtype_t t)
/* ************************* */
static inline int iss8(u64 v)
static inline int iss8(int64_t v)
{
return (llabs(v) <= 0x80); //llabs instead of labs required for __WIN64
return (SCHAR_MIN <= v && v <= SCHAR_MAX);
}
static inline int isu8(u64 v)
{
return (v <= 0xff);
return (v <= UCHAR_MAX);
}
static inline int iss16(u64 v)
static inline int iss16(int64_t v)
{
return (llabs(v) <= 0x8000);
return (SHRT_MIN <= v && v <= SHRT_MAX);
}
static inline int isu16(u64 v)
{
return (v <= 0xffff);
return (v <= USHRT_MAX);
}
static inline int iss32(u64 v)
static inline int iss32(int64_t v)
{
return (llabs(v) <= 0x80000000);
return (INT_MIN <= v && v <= INT_MAX);
}
static inline int isu32(u64 v)
{
return (v <= 0xffffffff);
return (v <= UINT_MAX);
}
static void emit_opsingle(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
@ -598,7 +622,7 @@ static void emit_mov(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
if(arg2.v.reg & R_8)
{
if(!isu8(arg1.v.imm))
if(!iss8(arg1.v.imm))
crap("value too large for 8bit register");
op = 0xb0;
@ -714,19 +738,23 @@ static void emit_subaddand(const char* mnemonic, arg_t arg1, arg_t arg2, void* d
}
compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
modrm |= params->subcode << 3;
if(rex) emit1(rex);
#if 0
if(isu8(arg1.v.imm))
if(arg2.v.reg & R_8)
{
emit1(0x80); // sub reg8/mem8, imm8
emit1(modrm);
emit1(arg1.v.imm & 0xFF);
}
else if(iss8(arg1.v.imm))
{
emit1(0x83); // sub reg/mem, imm8
emit1(modrm);
emit1(arg1.v.imm&0xFF);
emit1(arg1.v.imm & 0xFF);
}
else
#endif
{
emit1(0x81); // sub reg/mem, imm32
emit1(modrm);
@ -896,42 +924,19 @@ static void emit_twobyte(const char* mnemonic, arg_t arg1, arg_t arg2, void* dat
CRAP_INVALID_ARGS;
}
static opparam_t params_add = { subcode: 0, rmcode: 0x01, };
static opparam_t params_or = { subcode: 1, rmcode: 0x09, };
static opparam_t params_and = { subcode: 4, rmcode: 0x21, };
static opparam_t params_sub = { subcode: 5, rmcode: 0x29, };
static opparam_t params_xor = { subcode: 6, rmcode: 0x31, };
static opparam_t params_cmp = { subcode: 7, rmcode: 0x39, mrcode: 0x3b, };
static opparam_t params_dec = { subcode: 1, rcode: 0xff, rcode8: 0xfe, };
static opparam_t params_sar = { subcode: 7, rcode: 0xd3, rcode8: 0xd2, };
static opparam_t params_shl = { subcode: 4, rcode: 0xd3, rcode8: 0xd2, };
static opparam_t params_shr = { subcode: 5, rcode: 0xd3, rcode8: 0xd2, };
static opparam_t params_idiv = { subcode: 7, rcode: 0xf7, rcode8: 0xf6, };
static opparam_t params_div = { subcode: 6, rcode: 0xf7, rcode8: 0xf6, };
static opparam_t params_imul = { subcode: 5, rcode: 0xf7, rcode8: 0xf6, };
static opparam_t params_mul = { subcode: 4, rcode: 0xf7, rcode8: 0xf6, };
static opparam_t params_neg = { subcode: 3, rcode: 0xf7, rcode8: 0xf6, };
static opparam_t params_not = { subcode: 2, rcode: 0xf7, rcode8: 0xf6, };
static opparam_t params_cvtsi2ss = { xmmprefix: 0xf3, rmcode: 0x2a };
static opparam_t params_cvttss2si = { xmmprefix: 0xf3, rmcode: 0x2c };
static opparam_t params_addss = { xmmprefix: 0xf3, mrcode: 0x58 };
static opparam_t params_divss = { xmmprefix: 0xf3, mrcode: 0x5e };
static opparam_t params_movss = { xmmprefix: 0xf3, mrcode: 0x10, rmcode: 0x11 };
static opparam_t params_mulss = { xmmprefix: 0xf3, mrcode: 0x59 };
static opparam_t params_subss = { xmmprefix: 0xf3, mrcode: 0x5c };
static opparam_t params_ucomiss = { mrcode: 0x2e };
static int ops_sorted = 0;
static op_t ops[] = {
{ "addb", emit_subaddand, &params_add },
{ "addl", emit_subaddand, &params_add },
{ "addq", emit_subaddand, &params_add },
{ "addss", emit_twobyte, &params_addss },
{ "andb", emit_subaddand, &params_and },
{ "andl", emit_subaddand, &params_and },
{ "andq", emit_subaddand, &params_and },
{ "callq", emit_call, NULL },
{ "cbw", emit_opsingle16, (void*)0x98 },
{ "cdq", emit_opsingle, (void*)0x99 },
{ "cmpb", emit_subaddand, &params_cmp },
{ "cmpl", emit_subaddand, &params_cmp },
{ "cmpq", emit_subaddand, &params_cmp },
{ "cvtsi2ss", emit_twobyte, &params_cvtsi2ss },
@ -977,18 +982,21 @@ static op_t ops[] = {
{ "nop", emit_opsingle, (void*)0x90 },
{ "notl", emit_op_rm, &params_not },
{ "notq", emit_op_rm, &params_not },
{ "or", emit_subaddand, &params_or },
{ "orb", emit_subaddand, &params_or },
{ "orl", emit_subaddand, &params_or },
{ "orq", emit_subaddand, &params_or },
{ "pop", emit_opreg, (void*)0x58 },
{ "push", emit_opreg, (void*)0x50 },
{ "ret", emit_opsingle, (void*)0xc3 },
{ "sarl", emit_op_rm_cl, &params_sar },
{ "shl", emit_op_rm_cl, &params_shl },
{ "shrl", emit_op_rm_cl, &params_shr },
{ "subb", emit_subaddand, &params_sub },
{ "subl", emit_subaddand, &params_sub },
{ "subq", emit_subaddand, &params_sub },
{ "subss", emit_twobyte, &params_subss },
{ "ucomiss", emit_twobyte, &params_ucomiss },
{ "xorb", emit_subaddand, &params_xor },
{ "xorl", emit_subaddand, &params_xor },
{ "xorq", emit_subaddand, &params_xor },
{ NULL, NULL, NULL }
@ -1013,27 +1021,24 @@ static op_t* getop(const char* n)
}
#else
unsigned m, t, b;
unsigned int m, t, b;
int r;
t = ARRAY_LEN(ops)-1;
b = 0;
while(b <= t)
r = m = -1;
do
{
m = ((t-b)>>1) + b;
if((r = strcmp(ops[m].mnemonic, n)) == 0)
{
return &ops[m];
}
else if(r < 0)
{
if(r < 0)
b = m + 1;
}
else
{
t = m - 1;
}
}
m = ((t - b) >> 1) + b;
if((r = strcmp(ops[m].mnemonic, n)) == 0)
return &ops[m];
} while(b <= t && t);
#endif
return NULL;
@ -1050,6 +1055,10 @@ static reg_t parsereg(const char* str)
{
return R_AX;
}
if(*s == 'b' && s[1] == 'l' && !s[2])
{
return R_BL;
}
if(*s == 'c' && s[1] == 'l' && !s[2])
{
return R_CL;

View file

@ -85,6 +85,7 @@ extern void (APIENTRY * qglUniform1iARB) (GLint location, GLint v0);
extern void (APIENTRY * qglUniform2iARB) (GLint location, GLint v0, GLint v1);
extern void (APIENTRY * qglUniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2);
extern void (APIENTRY * qglUniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
extern void (APIENTRY * qglUniform1fvARB) (GLint location, GLsizei count, const GLfloat * value);
extern void (APIENTRY * qglUniform2fvARB) (GLint location, GLsizei count, const GLfloat * value);
extern void (APIENTRY * qglUniform3fvARB) (GLint location, GLsizei count, const GLfloat * value);
extern void (APIENTRY * qglUniform4fvARB) (GLint location, GLsizei count, const GLfloat * value);

View file

@ -45,13 +45,13 @@ void R_AddAnimSurfaces( trRefEntity_t *ent ) {
shader_t *shader;
int i;
header = (md4Header_t *) tr.currentModel->md4;
header = (md4Header_t *) tr.currentModel->modelData;
lod = (md4LOD_t *)( (byte *)header + header->ofsLODs );
surface = (md4Surface_t *)( (byte *)lod + lod->ofsSurfaces );
for ( i = 0 ; i < lod->numSurfaces ; i++ ) {
shader = R_GetShaderByHandle( surface->shaderIndex );
R_AddDrawSurf( (void *)surface, shader, 0 /*fogNum*/, qfalse );
R_AddDrawSurf( (void *)surface, shader, 0 /*fogNum*/, qfalse, qfalse );
surface = (md4Surface_t *)( (byte *)surface + surface->ofsEnd );
}
}
@ -326,7 +326,7 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
int cull;
qboolean personalModel;
header = (mdrHeader_t *) tr.currentModel->md4;
header = (mdrHeader_t *) tr.currentModel->modelData;
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;
@ -420,7 +420,7 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
&& shader->sort == SS_OPAQUE )
{
R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse );
R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse, qfalse );
}
// projection shadows work fine with personal models
@ -429,11 +429,11 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
&& (ent->e.renderfx & RF_SHADOW_PLANE )
&& shader->sort == SS_OPAQUE )
{
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, qfalse );
}
if (!personalModel)
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse );
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse, qfalse );
surface = (mdrSurface_t *)( (byte *)surface + surface->ofsEnd );
}

View file

@ -60,6 +60,30 @@ void GL_Bind( image_t *image ) {
}
}
/*
** GL_BindCubemap
*/
void GL_BindCubemap( image_t *image ) {
int texnum;
if ( !image ) {
ri.Printf( PRINT_WARNING, "GL_Bind: NULL image\n" );
texnum = tr.defaultImage->texnum;
} else {
texnum = image->texnum;
}
if ( r_nobind->integer && tr.dlightImage ) { // performance evaluation option
texnum = tr.dlightImage->texnum;
}
if ( glState.currenttextures[glState.currenttmu] != texnum ) {
image->frameUsed = tr.frameCount;
glState.currenttextures[glState.currenttmu] = texnum;
qglBindTexture (GL_TEXTURE_CUBE_MAP, texnum);
}
}
/*
** GL_SelectTexture
*/
@ -176,7 +200,7 @@ void GL_Cull( int cullType ) {
if ( cullType == CT_BACK_SIDED )
{
if ( backEnd.viewParms.isMirror )
if ( backEnd.viewParms.isMirror && !backEnd.viewParms.isShadowmap)
{
qglCullFace( GL_FRONT );
}
@ -187,7 +211,7 @@ void GL_Cull( int cullType ) {
}
else
{
if ( backEnd.viewParms.isMirror )
if ( backEnd.viewParms.isMirror && !backEnd.viewParms.isShadowmap)
{
qglCullFace( GL_BACK );
}
@ -227,7 +251,7 @@ void GL_TexEnv( int env )
qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
break;
default:
ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed\n", env );
ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed", env );
break;
}
}
@ -302,7 +326,7 @@ void GL_State( unsigned long stateBits )
break;
default:
srcFactor = GL_ONE; // to get warning to shut up
ri.Error( ERR_DROP, "GL_State: invalid src blend state bits\n" );
ri.Error( ERR_DROP, "GL_State: invalid src blend state bits" );
break;
}
@ -334,7 +358,7 @@ void GL_State( unsigned long stateBits )
break;
default:
dstFactor = GL_ONE; // to get warning to shut up
ri.Error( ERR_DROP, "GL_State: invalid dst blend state bits\n" );
ri.Error( ERR_DROP, "GL_State: invalid dst blend state bits" );
break;
}
@ -552,6 +576,14 @@ void RB_BeginDrawingView (void) {
qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky
#endif
}
// clear to white for shadow maps
if (backEnd.viewParms.isShadowmap)
{
clearBits |= GL_COLOR_BUFFER_BIT;
qglClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
}
qglClear( clearBits );
if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) )
@ -615,6 +647,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
int fogNum, oldFogNum;
int entityNum, oldEntityNum;
int dlighted, oldDlighted;
int pshadowed, oldPshadowed;
qboolean depthRange, oldDepthRange, isCrosshair, wasCrosshair;
int i;
drawSurf_t *drawSurf;
@ -640,6 +673,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
oldDepthRange = qfalse;
wasCrosshair = qfalse;
oldDlighted = qfalse;
oldPshadowed = qfalse;
oldSort = -1;
depthRange = qfalse;
depth[0] = 0.f;
@ -654,13 +688,13 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
continue;
}
oldSort = drawSurf->sort;
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted );
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed );
//
// change the tess parameters if needed
// a "entityMergable" shader is a shader that can have surfaces from seperate
// entities merged into a single batch, like smoke and blood puff sprites
if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted
if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted || pshadowed != oldPshadowed
|| ( entityNum != oldEntityNum && !shader->entityMergable ) ) {
if (oldShader != NULL) {
RB_EndSurface();
@ -670,6 +704,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
oldShader = shader;
oldFogNum = fogNum;
oldDlighted = dlighted;
oldPshadowed = pshadowed;
}
//
@ -771,7 +806,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
{
viewParms_t temp = backEnd.viewParms;
R_SetupProjection(&temp, r_znear->value, qfalse);
R_SetupProjection(&temp, r_znear->value, 0, qfalse);
GL_SetProjectionMatrix( temp.projectionMatrix );
}
@ -1406,6 +1441,34 @@ const void *RB_SwapBuffers( const void *data ) {
return (const void *)(cmd + 1);
}
/*
=============
RB_CapShadowMap
=============
*/
const void *RB_CapShadowMap(const void *data)
{
const capShadowmapCommand_t *cmd = data;
if (cmd->map != -1)
{
GL_SelectTexture(0);
if (cmd->cubeSide != -1)
{
GL_BindCubemap(tr.shadowCubemaps[cmd->map]);
qglCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cmd->cubeSide, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + 256 ), 256, 256, 0);
}
else
{
GL_Bind(tr.pshadowMaps[cmd->map]);
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + 256 ), 256, 256, 0);
}
}
return (const void *)(cmd + 1);
}
/*
====================
RB_ExecuteRenderCommands
@ -1426,6 +1489,8 @@ void RB_ExecuteRenderCommands( const void *data ) {
}
while ( 1 ) {
data = PADP(data, sizeof(void *));
switch ( *(const int *)data ) {
case RC_SET_COLOR:
data = RB_SetColor( data );
@ -1454,6 +1519,9 @@ void RB_ExecuteRenderCommands( const void *data ) {
case RC_CLEARDEPTH:
data = RB_ClearDepth(data);
break;
case RC_CAPSHADOWMAP:
data = RB_CapShadowMap(data);
break;
case RC_END_OF_LIST:
default:
// stop rendering on this thread

View file

@ -275,7 +275,10 @@ static void R_LoadLightmaps( lump_t *l ) {
// create all the lightmaps
numLightmaps = len / (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3);
numLightmaps >>= (tr.worldDeluxeMapping ? 1 : 0);
if (tr.worldDeluxeMapping)
{
numLightmaps >>= 1;
}
if(numLightmaps == 1)
{
@ -369,7 +372,6 @@ static void R_LoadLightmaps( lump_t *l ) {
}
}
}
}
tr.fatLightmap = R_CreateImage(va("_fatlightmap%d", 0), fatbuffer, tr.fatLightmapSize, tr.fatLightmapSize, qfalse, qfalse, GL_CLAMP_TO_EDGE );
@ -1795,13 +1797,10 @@ static void R_CreateWorldVBO(void)
// create arrays
s_worldData.numVerts = numVerts;
s_worldData.verts = verts = ri.Hunk_Alloc(numVerts * sizeof(srfVert_t), h_low);
verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
//optimizedVerts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
s_worldData.numTriangles = numTriangles;
s_worldData.triangles = triangles = ri.Hunk_Alloc(numTriangles * sizeof(srfTriangle_t), h_low);
triangles = ri.Hunk_AllocateTempMemory(numTriangles * sizeof(srfTriangle_t));
// presort surfaces
surfacesSorted = ri.Malloc(numSurfaces * sizeof(*surfacesSorted));
@ -1950,23 +1949,9 @@ static void R_CreateWorldVBO(void)
}
}
#if 0
numVerts = OptimizeVertices(numVerts, verts, numTriangles, triangles, optimizedVerts, CompareWorldVert);
if(c_redundantVertexes)
{
ri.Printf(PRINT_DEVELOPER,
"...removed %i redundant vertices from staticWorldMesh %i ( %s, %i verts %i tris )\n",
c_redundantVertexes, vboSurfaces.currentElements, shader->name, numVerts, numTriangles);
}
s_worldData.vbo = R_CreateVBO2(va("bspModelMesh_vertices %i", 0), numVerts, optimizedVerts,
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BITANGENT |
ATTR_NORMAL | ATTR_COLOR | GLCS_LIGHTCOLOR | ATTR_LIGHTDIRECTION);
#else
s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts,
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BITANGENT |
ATTR_NORMAL | ATTR_COLOR, VBO_USAGE_STATIC);
#endif
s_worldData.ibo = R_CreateIBO2(va("staticBspModel0_IBO %i", 0), numTriangles, triangles, VBO_USAGE_STATIC);
@ -2011,42 +1996,11 @@ static void R_CreateWorldVBO(void)
startTime = ri.Milliseconds();
// Tr3B: FIXME move this to somewhere else?
#if CALC_REDUNDANT_SHADOWVERTS
s_worldData.redundantVertsCalculationNeeded = 0;
for(i = 0; i < s_worldData.numLights; i++)
{
light = &s_worldData.lights[i];
if((r_precomputedLighting->integer || r_vertexLighting->integer) && !light->noRadiosity)
continue;
s_worldData.redundantVertsCalculationNeeded++;
}
if(s_worldData.redundantVertsCalculationNeeded)
{
ri.Printf(PRINT_ALL, "...calculating redundant world vertices ( %i verts )\n", numVerts);
s_worldData.redundantLightVerts = ri.Hunk_Alloc(numVerts * sizeof(int), h_low);
BuildRedundantIndices(numVerts, verts, s_worldData.redundantLightVerts, CompareLightVert);
s_worldData.redundantShadowVerts = ri.Hunk_Alloc(numVerts * sizeof(int), h_low);
BuildRedundantIndices(numVerts, verts, s_worldData.redundantShadowVerts, CompareShadowVert);
s_worldData.redundantShadowAlphaTestVerts = ri.Hunk_Alloc(numVerts * sizeof(int), h_low);
BuildRedundantIndices(numVerts, verts, s_worldData.redundantShadowAlphaTestVerts, CompareShadowVertAlphaTest);
}
endTime = ri.Milliseconds();
ri.Printf(PRINT_ALL, "redundant world vertices calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0);
#endif
ri.Free(surfacesSorted);
//ri.Hunk_FreeTempMemory(triangles);
ri.Hunk_FreeTempMemory(triangles);
//ri.Hunk_FreeTempMemory(optimizedVerts);
//ri.Hunk_FreeTempMemory(verts);
ri.Hunk_FreeTempMemory(verts);
}
@ -2088,6 +2042,7 @@ static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) {
s_worldData.numsurfaces = count;
s_worldData.surfacesViewCount = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesViewCount), h_low );
s_worldData.surfacesDlightBits = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesDlightBits), h_low );
s_worldData.surfacesPshadowBits = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesPshadowBits), h_low );
//s_worldData.numWorldSurfaces = count;
// Two passes, allocate surfaces first, then load them full of data
@ -2147,7 +2102,7 @@ static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) {
{
srfSurfaceFace_t *surface = (srfSurfaceFace_t *)out->data;
out->cullinfo.type = CULLINFO_PLANE; // | CULLINFO_BOX;
out->cullinfo.type = CULLINFO_PLANE | CULLINFO_BOX;
VectorCopy(surface->bounds[0], out->cullinfo.bounds[0]);
VectorCopy(surface->bounds[1], out->cullinfo.bounds[1]);
out->cullinfo.plane = surface->plane;
@ -3163,3 +3118,4 @@ void RE_LoadWorldMap( const char *name ) {
}

View file

@ -202,6 +202,7 @@ void *R_GetCommandBuffer( int bytes ) {
renderCommandList_t *cmdList;
cmdList = &backEndData[tr.smpFrame]->commands;
bytes = PAD(bytes, sizeof(void *));
// always leave room for the end of list command
if ( cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS ) {
@ -241,6 +242,26 @@ void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs ) {
}
/*
=============
R_AddCapShadowmapCmd
=============
*/
void R_AddCapShadowmapCmd( int map, int cubeSide ) {
capShadowmapCommand_t *cmd;
cmd = R_GetCommandBuffer( sizeof( *cmd ) );
if ( !cmd ) {
return;
}
cmd->commandId = RC_CAPSHADOWMAP;
cmd->map = map;
cmd->cubeSide = cubeSide;
}
/*
=============
RE_SetColor
@ -417,7 +438,7 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
R_SyncRenderThread();
if ((err = qglGetError()) != GL_NO_ERROR)
ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!\n", err);
ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!", err);
}
if (glConfig.stereoEnabled) {

View file

@ -123,3 +123,29 @@ void VectorLerp( vec3_t a, vec3_t b, float lerp, vec3_t c)
c[1] = a[1] * (1.0f - lerp) + b[1] * lerp;
c[2] = a[2] * (1.0f - lerp) + b[2] * lerp;
}
qboolean SpheresIntersect(vec3_t origin1, float radius1, vec3_t origin2, float radius2)
{
float radiusSum = radius1 + radius2;
vec3_t diff;
VectorSubtract(origin1, origin2, diff);
if (DotProduct(diff, diff) <= radiusSum * radiusSum)
{
return qtrue;
}
return qfalse;
}
void BoundingSphereOfSpheres(vec3_t origin1, float radius1, vec3_t origin2, float radius2, vec3_t origin3, float *radius3)
{
vec3_t diff;
VectorScale(origin1, 0.5f, origin3);
VectorMA(origin3, 0.5f, origin2, origin3);
VectorSubtract(origin1, origin2, diff);
*radius3 = VectorLength(diff) * 0.5 + MAX(radius1, radius2);
}

View file

@ -41,6 +41,8 @@ void Matrix16Ortho( float left, float right, float bottom, float top, float znea
#define DotProduct4(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3])
#define VectorScale4(a,b,c) ((c)[0]=(a)[0]*(b),(c)[1]=(a)[1]*(b),(c)[2]=(a)[2]*(b),(c)[3]=(a)[3]*(b))
#define VectorCopy5(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3],(b)[4]=(a)[4])
static ID_INLINE int VectorCompare4(const vec4_t v1, const vec4_t v2)
{
if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2] || v1[3] != v2[3])
@ -50,8 +52,23 @@ static ID_INLINE int VectorCompare4(const vec4_t v1, const vec4_t v2)
return 1;
}
static ID_INLINE int VectorCompare5(const vec5_t v1, const vec5_t v2)
{
if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2] || v1[3] != v2[3] || v1[4] != v2[4])
{
return 0;
}
return 1;
}
void VectorLerp( vec3_t a, vec3_t b, float lerp, vec3_t c);
qboolean SpheresIntersect(vec3_t origin1, float radius1, vec3_t origin2, float radius2);
void BoundingSphereOfSpheres(vec3_t origin1, float radius1, vec3_t origin2, float radius2, vec3_t origin3, float *radius3);
#ifndef SGN
#define SGN(x) (((x) >= 0) ? !!(x) : -1)
#endif
#endif

View file

@ -528,3 +528,4 @@ void RB_RenderFlares (void) {
}

File diff suppressed because it is too large Load diff

View file

@ -784,7 +784,7 @@ done:
if ( resampledBuffer != 0 )
ri.Hunk_FreeTempMemory( resampledBuffer );
}
static image_t *R_AllocImage(const char* name, int width, int height, qboolean mipmap, qboolean allowPicmip, int glWrapClampMode)
{
image_t *image;
@ -809,7 +809,7 @@ static image_t *R_AllocImage(const char* name, int width, int height, qboolean m
return image;
}
/*
================
R_CreateImage
@ -820,20 +820,21 @@ Makro - except maybe for render targets
at some point in the near future...
================
*/
image_t *R_CreateImage( const char *name, const byte *pic, int width, int height,
qboolean mipmap, qboolean allowPicmip, int glWrapClampMode ) {
image_t *R_CreateImage2( const char *name, const byte *pic, int width, int height,
qboolean mipmap, qboolean allowPicmip, int glWrapClampMode, qboolean cube ) {
image_t *image;
qboolean isLightmap = qfalse;
long hash;
if (strlen(name) >= MAX_QPATH ) {
ri.Error (ERR_DROP, "R_CreateImage: \"%s\" is too long\n", name);
ri.Error (ERR_DROP, "R_CreateImage: \"%s\" is too long", name);
}
if ( !strncmp( name, "*lightmap", 9 ) ) {
isLightmap = qtrue;
}
if ( tr.numImages == MAX_DRAWIMAGES ) {
ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit\n");
ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit");
}
image = R_AllocImage(name, width, height, mipmap, allowPicmip, glWrapClampMode);
@ -849,18 +850,41 @@ image_t *R_CreateImage( const char *name, const byte *pic, int width, int height
GL_SelectTexture( image->TMU );
}
GL_Bind(image);
if (cube)
{
GL_BindCubemap(image);
qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Upload32( (unsigned *)pic, image->width, image->height,
image->mipmap,
allowPicmip,
isLightmap,
&image->internalFormat,
&image->uploadWidth,
&image->uploadHeight );
qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode );
image->internalFormat = GL_RGBA8;
image->uploadWidth = width;
image->uploadHeight = height;
}
else
{
GL_Bind(image);
Upload32( (unsigned *)pic, image->width, image->height,
image->mipmap,
allowPicmip,
isLightmap,
&image->internalFormat,
&image->uploadWidth,
&image->uploadHeight );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode );
}
qglBindTexture( GL_TEXTURE_2D, 0 );
@ -871,6 +895,18 @@ image_t *R_CreateImage( const char *name, const byte *pic, int width, int height
return image;
}
image_t *R_CreateImage( const char *name, const byte *pic, int width, int height,
qboolean mipmap, qboolean allowPicmip, int glWrapClampMode )
{
return R_CreateImage2( name, pic, width, height, mipmap, allowPicmip, glWrapClampMode, qfalse);
}
image_t *R_CreateCubeImage( const char *name, const byte *pic, int width, int height,
qboolean mipmap, qboolean allowPicmip, int glWrapClampMode )
{
return R_CreateImage2( name, pic, width, height, mipmap, allowPicmip, glWrapClampMode, qtrue);
}
//===================================================================
typedef struct
@ -891,8 +927,7 @@ static imageExtToLoaderMap_t imageLoaders[ ] =
{ "bmp", R_LoadBMP }
};
static int numImageLoaders = sizeof( imageLoaders ) /
sizeof( imageLoaders[ 0 ] );
static int numImageLoaders = ARRAY_LEN( imageLoaders );
/*
=================
@ -905,9 +940,11 @@ Loads any of the supported image types into a cannonical
void R_LoadImage( const char *name, byte **pic, int *width, int *height )
{
qboolean orgNameFailed = qfalse;
int orgLoader = -1;
int i;
char localName[ MAX_QPATH ];
const char *ext;
char *altName;
*pic = NULL;
*width = 0;
@ -938,6 +975,7 @@ void R_LoadImage( const char *name, byte **pic, int *width, int *height )
// Loader failed, most likely because the file isn't there;
// try again without the extension
orgNameFailed = qtrue;
orgLoader = i;
COM_StripExtension( name, localName, MAX_QPATH );
}
else
@ -952,7 +990,10 @@ void R_LoadImage( const char *name, byte **pic, int *width, int *height )
// the image formats supported
for( i = 0; i < numImageLoaders; i++ )
{
char *altName = va( "%s.%s", localName, imageLoaders[ i ].ext );
if (i == orgLoader)
continue;
altName = va( "%s.%s", localName, imageLoaders[ i ].ext );
// Load
imageLoaders[ i ].ImageLoader( altName, pic, width, height );
@ -1208,7 +1249,24 @@ void R_CreateBuiltinImages( void ) {
Com_Memset( data, 255, sizeof( data ) );
tr.whiteImage = R_CreateImage("*white", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT );
// black image, for no specular
if (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer
&& glRefConfig.glsl && r_arb_shader_objects->integer)
{
if (r_dlightShadows->integer)
{
for( x = 0; x < MAX_DLIGHTS; x++)
{
tr.shadowCubemaps[x] = R_CreateCubeImage(va("*shadowcubemap%i", x), (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, qfalse, qfalse, GL_CLAMP_TO_EDGE );
}
}
for( x = 0; x < MAX_DRAWN_PSHADOWS; x++)
{
tr.pshadowMaps[x] = R_CreateImage(va("*shadowmap%i", x), (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, qfalse, qfalse, GL_CLAMP_TO_EDGE );
}
}
// black image
for (x=0 ; x<DEFAULT_SIZE ; x++) {
for (y=0 ; y<DEFAULT_SIZE ; y++) {
data[y][x][0] =
@ -1651,3 +1709,4 @@ void R_SkinList_f( void ) {
}

View file

@ -76,7 +76,7 @@ void R_LoadBMP( const char *name, byte **pic, int *width, int *height )
if (length < 54)
{
ri.Error( ERR_DROP, "LoadBMP: header too short (%s)\n", name );
ri.Error( ERR_DROP, "LoadBMP: header too short (%s)", name );
}
buf_p = buffer.b;
@ -116,7 +116,7 @@ void R_LoadBMP( const char *name, byte **pic, int *width, int *height )
if ( bmpHeader.bitsPerPixel == 8 )
{
if (buf_p + sizeof(bmpHeader.palette) > end)
ri.Error( ERR_DROP, "LoadBMP: header too short (%s)\n", name );
ri.Error( ERR_DROP, "LoadBMP: header too short (%s)", name );
Com_Memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) );
buf_p += sizeof(bmpHeader.palette);
@ -124,26 +124,26 @@ void R_LoadBMP( const char *name, byte **pic, int *width, int *height )
if (buffer.b + bmpHeader.bitmapDataOffset > end)
{
ri.Error( ERR_DROP, "LoadBMP: invalid offset value in header (%s)\n", name );
ri.Error( ERR_DROP, "LoadBMP: invalid offset value in header (%s)", name );
}
buf_p = buffer.b + bmpHeader.bitmapDataOffset;
if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' )
{
ri.Error( ERR_DROP, "LoadBMP: only Windows-style BMP files supported (%s)\n", name );
ri.Error( ERR_DROP, "LoadBMP: only Windows-style BMP files supported (%s)", name );
}
if ( bmpHeader.fileSize != length )
{
ri.Error( ERR_DROP, "LoadBMP: header size does not match file size (%u vs. %u) (%s)\n", bmpHeader.fileSize, length, name );
ri.Error( ERR_DROP, "LoadBMP: header size does not match file size (%u vs. %u) (%s)", bmpHeader.fileSize, length, name );
}
if ( bmpHeader.compression != 0 )
{
ri.Error( ERR_DROP, "LoadBMP: only uncompressed BMP files supported (%s)\n", name );
ri.Error( ERR_DROP, "LoadBMP: only uncompressed BMP files supported (%s)", name );
}
if ( bmpHeader.bitsPerPixel < 8 )
{
ri.Error( ERR_DROP, "LoadBMP: monochrome and 4-bit BMP files not supported (%s)\n", name );
ri.Error( ERR_DROP, "LoadBMP: monochrome and 4-bit BMP files not supported (%s)", name );
}
switch ( bmpHeader.bitsPerPixel )
@ -154,7 +154,7 @@ void R_LoadBMP( const char *name, byte **pic, int *width, int *height )
case 32:
break;
default:
ri.Error( ERR_DROP, "LoadBMP: illegal pixel_size '%hu' in file '%s'\n", bmpHeader.bitsPerPixel, name );
ri.Error( ERR_DROP, "LoadBMP: illegal pixel_size '%hu' in file '%s'", bmpHeader.bitsPerPixel, name );
break;
}
@ -167,11 +167,11 @@ void R_LoadBMP( const char *name, byte **pic, int *width, int *height )
if(columns <= 0 || !rows || numPixels > 0x1FFFFFFF // 4*1FFFFFFF == 0x7FFFFFFC < 0x7FFFFFFF
|| ((numPixels * 4) / columns) / 4 != rows)
{
ri.Error (ERR_DROP, "LoadBMP: %s has an invalid image size\n", name);
ri.Error (ERR_DROP, "LoadBMP: %s has an invalid image size", name);
}
if(buf_p + numPixels*bmpHeader.bitsPerPixel/8 > end)
{
ri.Error (ERR_DROP, "LoadBMP: file truncated (%s)\n", name);
ri.Error (ERR_DROP, "LoadBMP: file truncated (%s)", name);
}
if ( width )

View file

@ -51,7 +51,7 @@ static void R_JPGErrorExit(j_common_ptr cinfo)
/* Let the memory manager delete any temp files before we die */
jpeg_destroy(cinfo);
ri.Error(ERR_FATAL, "%s\n", buffer);
ri.Error(ERR_FATAL, "%s", buffer);
}
static void R_JPGOutputMessage(j_common_ptr cinfo)
@ -138,10 +138,9 @@ void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *heigh
/* Step 4: set parameters for decompression */
/*
* Make sure it always converts images to RGB color space. This will
* automatically convert 8-bit greyscale images to RGB as well.
*/
* Make sure it always converts images to RGB color space. This will
* automatically convert 8-bit greyscale images to RGB as well.
*/
cinfo.out_color_space = JCS_RGB;
/* Step 5: Start decompressor */
@ -170,7 +169,7 @@ void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *heigh
ri.FS_FreeFile (fbuffer.v);
jpeg_destroy_decompress(&cinfo);
ri.Error(ERR_DROP, "LoadJPG: %s has an invalid image format: %dx%d*4=%d, components: %d\n", filename,
ri.Error(ERR_DROP, "LoadJPG: %s has an invalid image format: %dx%d*4=%d, components: %d", filename,
cinfo.output_width, cinfo.output_height, pixelcount * 4, cinfo.output_components);
}
@ -299,7 +298,7 @@ empty_output_buffer (j_compress_ptr cinfo)
jpeg_destroy_compress(cinfo);
// Make crash fatal or we would probably leak memory.
ri.Error(ERR_FATAL, "Output buffer for encoded JPEG image has insufficient size of %d bytes\n",
ri.Error(ERR_FATAL, "Output buffer for encoded JPEG image has insufficient size of %d bytes",
dest->size);
return FALSE;

View file

@ -70,7 +70,7 @@ void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
if(length < 18)
{
ri.Error( ERR_DROP, "LoadTGA: header too short (%s)\n", name );
ri.Error( ERR_DROP, "LoadTGA: header too short (%s)", name );
}
buf_p = buffer.b;
@ -103,17 +103,17 @@ void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
&& targa_header.image_type!=10
&& targa_header.image_type != 3 )
{
ri.Error (ERR_DROP, "LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
ri.Error (ERR_DROP, "LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported");
}
if ( targa_header.colormap_type != 0 )
{
ri.Error( ERR_DROP, "LoadTGA: colormaps not supported\n" );
ri.Error( ERR_DROP, "LoadTGA: colormaps not supported" );
}
if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 )
{
ri.Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
ri.Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)");
}
columns = targa_header.width;
@ -122,7 +122,7 @@ void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
if(!columns || !rows || numPixels > 0x7FFFFFFF || numPixels / columns / 4 != rows)
{
ri.Error (ERR_DROP, "LoadTGA: %s has an invalid image size\n", name);
ri.Error (ERR_DROP, "LoadTGA: %s has an invalid image size", name);
}
@ -131,7 +131,7 @@ void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
if (targa_header.id_length != 0)
{
if (buf_p + targa_header.id_length > end)
ri.Error( ERR_DROP, "LoadTGA: header too short (%s)\n", name );
ri.Error( ERR_DROP, "LoadTGA: header too short (%s)", name );
buf_p += targa_header.id_length; // skip TARGA image comment
}
@ -140,7 +140,7 @@ void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
{
if(buf_p + columns*rows*targa_header.pixel_size/8 > end)
{
ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name);
ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)", name);
}
// Uncompressed RGB or gray scale image
@ -183,7 +183,7 @@ void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
*pixbuf++ = alphabyte;
break;
default:
ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'", targa_header.pixel_size, name );
break;
}
}
@ -201,12 +201,12 @@ void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; ) {
if(buf_p + 1 > end)
ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name);
ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)", name);
packetHeader= *buf_p++;
packetSize = 1 + (packetHeader & 0x7f);
if (packetHeader & 0x80) { // run-length packet
if(buf_p + targa_header.pixel_size/8 > end)
ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name);
ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)", name);
switch (targa_header.pixel_size) {
case 24:
blue = *buf_p++;
@ -221,7 +221,7 @@ void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
alphabyte = *buf_p++;
break;
default:
ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'", targa_header.pixel_size, name );
break;
}
@ -244,7 +244,7 @@ void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
else { // non run-length packet
if(buf_p + targa_header.pixel_size/8*packetSize > end)
ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name);
ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)", name);
for(j=0;j<packetSize;j++) {
switch (targa_header.pixel_size) {
case 24:
@ -267,7 +267,7 @@ void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
*pixbuf++ = alphabyte;
break;
default:
ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'", targa_header.pixel_size, name );
break;
}
column++;

View file

@ -106,6 +106,9 @@ cvar_t *r_specularMapping;
cvar_t *r_deluxeMapping;
cvar_t *r_parallaxMapping;
cvar_t *r_normalAmbient;
cvar_t *r_recalcMD3Normals;
cvar_t *r_dlightShadows;
cvar_t *r_pshadowDist;
cvar_t *r_ignoreGLErrors;
cvar_t *r_logFile;
@ -389,21 +392,21 @@ byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *pa
byte *buffer, *bufstart;
int padwidth, linelen;
GLint packAlign;
qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign);
linelen = width * 3;
padwidth = PAD(linelen, packAlign);
// Allocate a few more bytes so that we can choose an alignment we like
buffer = ri.Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1);
bufstart = (byte *) PAD((intptr_t) buffer + *offset, packAlign);
bufstart = PADP((intptr_t) buffer + *offset, packAlign);
qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart);
*offset = bufstart - buffer;
*padlen = padwidth - linelen;
return buffer;
}
@ -418,13 +421,13 @@ void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName)
byte *srcptr, *destptr;
byte *endline, *endmem;
byte temp;
int linelen, padlen;
size_t offset = 18, memcount;
allbuf = RB_ReadPixels(x, y, width, height, &offset, &padlen);
buffer = allbuf + offset - 18;
Com_Memset (buffer, 0, 18);
buffer[2] = 2; // uncompressed type
buffer[12] = width & 255;
@ -435,10 +438,10 @@ void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName)
// swap rgb to bgr and remove padding from line endings
linelen = width * 3;
srcptr = destptr = allbuf + offset;
endmem = srcptr + (linelen + padlen) * height;
while(srcptr < endmem)
{
endline = srcptr + linelen;
@ -449,10 +452,10 @@ void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName)
*destptr++ = srcptr[2];
*destptr++ = srcptr[1];
*destptr++ = temp;
srcptr += 3;
}
// Skip the pad
srcptr += padlen;
}
@ -472,7 +475,8 @@ void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName)
==================
RB_TakeScreenshotJPEG
==================
*/
*/
void RB_TakeScreenshotJPEG(int x, int y, int width, int height, char *fileName)
{
byte *buffer;
@ -802,8 +806,8 @@ const void *RB_TakeVideoFrameCmd( const void *data )
avipadwidth = PAD(linelen, AVI_LINE_PADDING);
avipadlen = avipadwidth - linelen;
cBuf = (byte *) PAD((intptr_t) cmd->captureBuffer, packAlign);
cBuf = PADP(cmd->captureBuffer, packAlign);
qglReadPixels(0, 0, cmd->width, cmd->height, GL_RGB,
GL_UNSIGNED_BYTE, cBuf);
@ -826,13 +830,13 @@ const void *RB_TakeVideoFrameCmd( const void *data )
{
byte *lineend, *memend;
byte *srcptr, *destptr;
srcptr = cBuf;
destptr = cmd->encodeBuffer;
memend = srcptr + memcount;
// swap R and B and remove line paddings
while(srcptr < memend)
// swap R and B and remove line paddings
while(srcptr < memend)
{
lineend = srcptr + linelen;
while(srcptr < lineend)
@ -1094,6 +1098,9 @@ void R_Register( void )
r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_normalAmbient = ri.Cvar_Get( "r_normalAmbient", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_dlightShadows = ri.Cvar_Get( "r_dlightShadows", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_pshadowDist = ri.Cvar_Get( "r_pshadowDist", "128", CVAR_ARCHIVE );
r_recalcMD3Normals = ri.Cvar_Get( "r_recalcMD3Normals", "0", CVAR_ARCHIVE | CVAR_LATCH );
//
// temporary latched variables that can only change over a restart
@ -1307,7 +1314,8 @@ void R_Init( void ) {
InitOpenGL();
if (glRefConfig.glsl)
if (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer
&& glRefConfig.glsl && r_arb_shader_objects->integer)
{
GLSL_InitGPUShaders();
}
@ -1315,7 +1323,7 @@ void R_Init( void ) {
R_InitImages();
R_InitFBOs();
if (glRefConfig.vertexBufferObject)
if (glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer)
{
R_InitVBOs();
}

View file

@ -365,9 +365,9 @@ void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
}
// save out the byte packet version
((byte *)&ent->ambientLightInt)[0] = myftol( ent->ambientLight[0] );
((byte *)&ent->ambientLightInt)[1] = myftol( ent->ambientLight[1] );
((byte *)&ent->ambientLightInt)[2] = myftol( ent->ambientLight[2] );
((byte *)&ent->ambientLightInt)[0] = Q_ftol(ent->ambientLight[0]);
((byte *)&ent->ambientLightInt)[1] = Q_ftol(ent->ambientLight[1]);
((byte *)&ent->ambientLightInt)[2] = Q_ftol(ent->ambientLight[2]);
((byte *)&ent->ambientLightInt)[3] = 0xff;
// transform the direction to local space

View file

@ -30,21 +30,15 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "tr_public.h"
#include "tr_extramath.h"
#include "qgl.h"
#include "iqm.h"
#define GL_INDEX_TYPE GL_UNSIGNED_INT
typedef unsigned int glIndex_t;
// fast float to int conversion
#if id386 && !defined(__GNUC__)
long myftol( float f );
#else
#define myftol(x) ((int)(x))
#endif
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
#endif
// everything that is needed by the backend needs
@ -52,20 +46,21 @@ long myftol( float f );
// parallel on a dual cpu machine
#define SMP_FRAMES 2
// 12 bits
// 14 bits
// can't be increased without changing bit packing for drawsurfs
// see QSORT_SHADERNUM_SHIFT
#define MAX_SHADERS 16384
#define SHADERNUM_BITS 14
#define MAX_SHADERS (1<<SHADERNUM_BITS)
//#define MAX_SHADER_STATES 2048
#define MAX_STATES_PER_SHADER 32
#define MAX_STATE_NAME 32
// can't be increased without changing bit packing for drawsurfs
#define MAX_VISCOUNTS 5
#define MAX_VBOS 4096
#define MAX_IBOS 4096
typedef struct dlight_s {
vec3_t origin;
vec3_t color; // range from 0.0 to 1.0, should be color normalized
@ -296,8 +291,7 @@ typedef enum {
TCGEN_TEXTURE,
TCGEN_ENVIRONMENT_MAPPED,
TCGEN_FOG,
TCGEN_VECTOR, // S and T from world coordinates
TCGEN_DLIGHT
TCGEN_VECTOR // S and T from world coordinates
} texCoordGen_t;
typedef enum {
@ -395,7 +389,8 @@ enum
TB_NORMALMAP,
TB_DELUXEMAP,
TB_SPECULARMAP,
NUM_TEXTURE_BUNDLES = 5
TB_SHADOWMAP,
NUM_TEXTURE_BUNDLES = 6
};
typedef enum
@ -409,15 +404,6 @@ typedef enum
ST_GLSL
} stageType_t;
typedef enum
{
COLLAPSE_none,
COLLAPSE_genericMulti,
COLLAPSE_lighting_DB,
COLLAPSE_lighting_DBS,
COLLAPSE_reflection_CB
} collapseType_t;
typedef struct {
stageType_t type;
@ -441,6 +427,7 @@ typedef struct {
struct shaderProgram_s *glslShaderGroup;
int glslShaderIndex;
float specularReflectance;
} shaderStage_t;
struct shaderCommands_s;
@ -713,27 +700,30 @@ enum
GENERICDEF_USE_VERTEX_ANIMATION = 0x0004,
GENERICDEF_USE_FOG = 0x0008,
GENERICDEF_USE_RGBAGEN = 0x0010,
GENERICDEF_ALL = 0x001F,
GENERICDEF_COUNT = 0x0020,
GENERICDEF_USE_LIGHTMAP = 0x0020,
GENERICDEF_ALL = 0x003F,
GENERICDEF_COUNT = 0x0040,
};
enum
{
LIGHTDEF_USE_LIGHTMAP = 0x0001,
LIGHTDEF_USE_NORMALMAP = 0x0002,
LIGHTDEF_USE_SPECULARMAP = 0x0004,
LIGHTDEF_USE_DELUXEMAP = 0x0008,
LIGHTDEF_USE_PARALLAXMAP = 0x0010,
LIGHTDEF_TCGEN_ENVIRONMENT = 0x0020,
LIGHTDEF_ENTITY = 0x0040,
LIGHTDEF_ALL = 0x007F,
LIGHTDEF_COUNT = 0x0080
LIGHTDEF_USE_LIGHT_VECTOR = 0x0002,
LIGHTDEF_USE_NORMALMAP = 0x0004,
LIGHTDEF_USE_SPECULARMAP = 0x0008,
LIGHTDEF_USE_DELUXEMAP = 0x0010,
LIGHTDEF_USE_PARALLAXMAP = 0x0020,
LIGHTDEF_TCGEN_ENVIRONMENT = 0x0040,
LIGHTDEF_ENTITY = 0x0080,
LIGHTDEF_ALL = 0x00FF,
LIGHTDEF_COUNT = 0x0100
};
enum
{
GLSL_INT,
GLSL_FLOAT,
GLSL_FLOAT5,
GLSL_VEC2,
GLSL_VEC3,
GLSL_VEC4,
@ -775,9 +765,7 @@ enum
FOGPASS_UNIFORM_FOGDEPTH,
FOGPASS_UNIFORM_FOGEYET,
FOGPASS_UNIFORM_DEFORMGEN,
FOGPASS_UNIFORM_DEFORMWAVE,
FOGPASS_UNIFORM_DEFORMBULGE,
FOGPASS_UNIFORM_DEFORMSPREAD,
FOGPASS_UNIFORM_DEFORMPARAMS,
FOGPASS_UNIFORM_TIME,
FOGPASS_UNIFORM_COLOR,
FOGPASS_UNIFORM_MODELVIEWPROJECTIONMATRIX,
@ -791,9 +779,7 @@ enum
DLIGHT_UNIFORM_DIFFUSEMAP = 0,
DLIGHT_UNIFORM_DLIGHTINFO,
DLIGHT_UNIFORM_DEFORMGEN,
DLIGHT_UNIFORM_DEFORMWAVE,
DLIGHT_UNIFORM_DEFORMBULGE,
DLIGHT_UNIFORM_DEFORMSPREAD,
DLIGHT_UNIFORM_DEFORMPARAMS,
DLIGHT_UNIFORM_TIME,
DLIGHT_UNIFORM_COLOR,
DLIGHT_UNIFORM_MODELVIEWPROJECTIONMATRIX,
@ -802,6 +788,19 @@ enum
};
enum
{
PSHADOW_UNIFORM_SHADOWMAP = 0,
PSHADOW_UNIFORM_MODELVIEWPROJECTIONMATRIX,
PSHADOW_UNIFORM_LIGHTFORWARD,
PSHADOW_UNIFORM_LIGHTUP,
PSHADOW_UNIFORM_LIGHTRIGHT,
PSHADOW_UNIFORM_LIGHTORIGIN,
PSHADOW_UNIFORM_LIGHTRADIUS,
PSHADOW_UNIFORM_COUNT
};
enum
{
GENERIC_UNIFORM_DIFFUSEMAP = 0,
@ -809,25 +808,24 @@ enum
GENERIC_UNIFORM_NORMALMAP,
GENERIC_UNIFORM_DELUXEMAP,
GENERIC_UNIFORM_SPECULARMAP,
GENERIC_UNIFORM_SHADOWMAP,
GENERIC_UNIFORM_DIFFUSETEXMATRIX,
GENERIC_UNIFORM_NORMALTEXMATRIX,
GENERIC_UNIFORM_SPECULARTEXMATRIX,
//GENERIC_UNIFORM_NORMALTEXMATRIX,
//GENERIC_UNIFORM_SPECULARTEXMATRIX,
GENERIC_UNIFORM_TEXTURE1ENV,
GENERIC_UNIFORM_VIEWORIGIN,
GENERIC_UNIFORM_TCGEN0,
GENERIC_UNIFORM_TCGEN0VECTOR0,
GENERIC_UNIFORM_TCGEN0VECTOR1,
GENERIC_UNIFORM_DEFORMGEN,
GENERIC_UNIFORM_DEFORMWAVE,
GENERIC_UNIFORM_DEFORMBULGE,
GENERIC_UNIFORM_DEFORMSPREAD,
GENERIC_UNIFORM_DEFORMPARAMS,
GENERIC_UNIFORM_COLORGEN,
GENERIC_UNIFORM_ALPHAGEN,
GENERIC_UNIFORM_COLOR,
GENERIC_UNIFORM_AMBIENTLIGHT,
GENERIC_UNIFORM_DIRECTEDLIGHT,
GENERIC_UNIFORM_LIGHTORIGIN,
GENERIC_UNIFORM_LIGHTSCALESQR,
GENERIC_UNIFORM_LIGHTRADIUS,
GENERIC_UNIFORM_PORTALRANGE,
GENERIC_UNIFORM_FOGDISTANCE,
GENERIC_UNIFORM_FOGDEPTH,
@ -837,6 +835,7 @@ enum
GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX,
GENERIC_UNIFORM_TIME,
GENERIC_UNIFORM_VERTEXLERP,
GENERIC_UNIFORM_SPECULARREFLECTANCE,
GENERIC_UNIFORM_COUNT
};
@ -875,6 +874,7 @@ typedef struct {
int num_dlights;
struct dlight_s *dlights;
unsigned int dlightMask;
int numPolys;
struct srfPoly_s *polys;
@ -882,6 +882,9 @@ typedef struct {
int numDrawSurfs;
struct drawSurf_s *drawSurfs;
int num_pshadows;
struct pshadow_s *pshadows;
} trRefdef_t;
@ -920,13 +923,14 @@ typedef struct {
vec3_t pvsOrigin; // may be different than or.origin for portals
qboolean isPortal; // true if this view is through a portal
qboolean isMirror; // the portal is a mirror, invert the face culling
qboolean isShadowmap;
int frameSceneNum; // copied from tr.frameSceneNum
int frameCount; // copied from tr.frameCount
cplane_t portalPlane; // clip anything behind this if mirroring
int viewportX, viewportY, viewportWidth, viewportHeight;
float fovX, fovY;
float projectionMatrix[16];
cplane_t frustum[4];
cplane_t frustum[5];
vec3_t visBounds[2];
float zFar;
stereoFrame_t stereoFrame;
@ -955,6 +959,7 @@ typedef enum {
#ifdef RAVENMD4
SF_MDR,
#endif
SF_IQM,
SF_FLARE,
SF_ENTITY, // beams, rails, lightning, etc that can be determined by entity
SF_DISPLAY_LIST,
@ -1031,6 +1036,7 @@ typedef struct srfGridMesh_s
// dynamic lighting information
int dlightBits[SMP_FRAMES];
int pshadowBits[SMP_FRAMES];
// culling information
vec3_t meshBounds[2];
@ -1072,6 +1078,7 @@ typedef struct
// dynamic lighting information
int dlightBits[SMP_FRAMES];
int pshadowBits[SMP_FRAMES];
// culling information
cplane_t plane;
@ -1101,6 +1108,7 @@ typedef struct
// dynamic lighting information
int dlightBits[SMP_FRAMES];
int pshadowBits[SMP_FRAMES];
// culling information
vec3_t bounds[2];
@ -1121,6 +1129,40 @@ typedef struct
IBO_t *ibo;
} srfTriangles_t;
// inter-quake-model
typedef struct {
int num_vertexes;
int num_triangles;
int num_frames;
int num_surfaces;
int num_joints;
struct srfIQModel_s *surfaces;
float *positions;
float *texcoords;
float *normals;
float *tangents;
byte *blendIndexes;
byte *blendWeights;
byte *colors;
int *triangles;
int *jointParents;
float *poseMats;
float *bounds;
char *names;
} iqmData_t;
// inter-quake-model surface
typedef struct srfIQModel_s {
surfaceType_t surfaceType;
char name[MAX_QPATH];
shader_t *shader;
iqmData_t *data;
int first_vertex, num_vertexes;
int first_triangle, num_triangles;
} srfIQModel_t;
typedef struct srfVBOMesh_s
{
@ -1131,6 +1173,7 @@ typedef struct srfVBOMesh_s
// dynamic lighting information
int dlightBits[SMP_FRAMES];
int pshadowBits[SMP_FRAMES];
// culling information
vec3_t bounds[2];
@ -1163,6 +1206,34 @@ typedef struct srfVBOMDVMesh_s
extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void *);
/*
==============================================================================
SHADOWS
==============================================================================
*/
typedef struct pshadow_s
{
float sort;
int numEntities;
int entityNums[8];
vec3_t entityOrigins[8];
float entityRadiuses[8];
float viewRadius;
vec3_t viewOrigin;
vec3_t lightViewAxis[3];
vec3_t lightOrigin;
float lightRadius;
cplane_t cullPlane;
} pshadow_t;
/*
==============================================================================
@ -1248,29 +1319,22 @@ typedef struct {
int numDecisionNodes;
mnode_t *nodes;
int numVerts;
srfVert_t *verts;
int redundantVertsCalculationNeeded;
int *redundantLightVerts; // util to optimize IBOs
int *redundantShadowVerts;
int *redundantShadowAlphaTestVerts;
VBO_t *vbo;
IBO_t *ibo;
int numTriangles;
srfTriangle_t *triangles;
int numWorldSurfaces;
int numsurfaces;
msurface_t *surfaces;
int *surfacesViewCount;
int *surfacesDlightBits;
int *surfacesPshadowBits;
int numMergedSurfaces;
msurface_t *mergedSurfaces;
int *mergedSurfacesViewCount;
int *mergedSurfacesDlightBits;
int *mergedSurfacesPshadowBits;
int nummarksurfaces;
int *marksurfaces;
@ -1379,19 +1443,20 @@ typedef enum {
MOD_MESH,
MOD_MD4,
#ifdef RAVENMD4
MOD_MDR
MOD_MDR,
#endif
MOD_IQM
} modtype_t;
typedef struct model_s {
char name[MAX_QPATH];
modtype_t type;
int index; // model = tr.models[model->index]
int index; // model = tr.models[model->index]
int dataSize; // just for listing purposes
bmodel_t *bmodel; // only if type == MOD_BRUSH
int dataSize; // just for listing purposes
bmodel_t *bmodel; // only if type == MOD_BRUSH
mdvModel_t *mdv[MD3_MAX_LODS]; // only if type == MOD_MESH
void *md4; // only if type == (MOD_MD4 | MOD_MDR)
void *modelData; // only if type == (MOD_MD4 | MOD_MDR | MOD_IQM)
int numLods;
} model_t;
@ -1424,21 +1489,32 @@ compared quickly during the qsorting process
the bits are allocated as follows:
21 - 31 : sorted shader index
11 - 20 : entity index
2 - 6 : fog index
//2 : used to be clipped flag REMOVED - 03.21.00 rad
0 - 1 : dlightmap index
//2 : used to be clipped flag REMOVED - 03.21.00 rad
2 - 6 : fog index
11 - 20 : entity index
21 - 31 : sorted shader index
TTimo - 1.32
0-1 : dlightmap index
2-6 : fog index
7-16 : entity index
17-30 : sorted shader index
SmileTheory - for pshadows
17-31 : sorted shader index
7-16 : entity index
2-6 : fog index
0-1 : dlightmap index
1 : pshadow flag
0 : dlight flag
*/
#define QSORT_SHADERNUM_SHIFT 17
#define QSORT_FOGNUM_SHIFT 2
#define QSORT_ENTITYNUM_SHIFT 7
#define QSORT_FOGNUM_SHIFT 2
#define QSORT_SHADERNUM_SHIFT (QSORT_ENTITYNUM_SHIFT+GENTITYNUM_BITS)
#if (QSORT_SHADERNUM_SHIFT+SHADERNUM_BITS) > 32
#error "Need to update sorting, too many bits."
#endif
#define QSORT_PSHADOW_SHIFT 1
extern int gl_filter_min, gl_filter_max;
@ -1620,6 +1696,8 @@ typedef struct {
image_t *whiteImage; // full of 0xff
image_t *blackImage; // full of 0x000000ff
image_t *identityLightImage; // full of tr.identityLightByte
image_t *shadowCubemaps[MAX_DLIGHTS];
image_t *pshadowMaps[MAX_DRAWN_PSHADOWS];
shader_t *defaultShader;
shader_t *shadowShader;
@ -1652,6 +1730,8 @@ typedef struct {
shaderProgram_t fogShader;
shaderProgram_t dlightallShader;
shaderProgram_t lightallShader[LIGHTDEF_COUNT];
shaderProgram_t shadowmapShader;
shaderProgram_t pshadowShader;
// -----------------------------------------
@ -1854,6 +1934,9 @@ extern cvar_t *r_specularMapping;
extern cvar_t *r_deluxeMapping;
extern cvar_t *r_parallaxMapping;
extern cvar_t *r_normalAmbient;
extern cvar_t *r_dlightShadows;
extern cvar_t *r_pshadowDist;
extern cvar_t *r_recalcMD3Normals;
extern cvar_t *r_greyscale;
@ -1881,6 +1964,8 @@ void R_NoiseInit( void );
void R_SwapBuffers( int );
void R_RenderView( viewParms_t *parms );
void R_RenderDlightCubemaps(const refdef_t *fd);
void R_RenderPshadowMaps(const refdef_t *fd);
void R_AddMD3Surfaces( trRefEntity_t *e );
void R_AddNullModelSurfaces( trRefEntity_t *e );
@ -1891,9 +1976,10 @@ void R_AddLightningBoltSurfaces( trRefEntity_t *e );
void R_AddPolygonSurfaces( void );
void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,
int *fogNum, int *dlightMap );
int *fogNum, int *dlightMap, int *pshadowMap );
void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int fogIndex, int dlightMap );
void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader,
int fogIndex, int dlightMap, int pshadowMap );
void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2);
@ -1912,13 +1998,14 @@ int R_CullPointAndRadiusEx( const vec3_t origin, float radius, const cplane_t* f
int R_CullPointAndRadius( const vec3_t origin, float radius );
int R_CullLocalPointAndRadius( const vec3_t origin, float radius );
void R_SetupProjection(viewParms_t *dest, float zProj, qboolean computeFrustum);
void R_SetupProjection(viewParms_t *dest, float zProj, float zFar, qboolean computeFrustum);
void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms, orientationr_t *or );
/*
** GL wrapper/helper functions
*/
void GL_Bind( image_t *image );
void GL_BindCubemap( image_t *image );
void GL_BindToTMU( image_t *image, int tmu );
void GL_SetDefaultState (void);
void GL_SelectTexture( int unit );
@ -2091,6 +2178,7 @@ typedef struct shaderCommands_s
int fogNum;
int dlightBits; // or together of all vertexDlightBits
int pshadowBits;
int firstIndex;
int numIndexes;
@ -2284,6 +2372,7 @@ void GLSL_SetNumUniforms(shaderProgram_t *program, int numUniforms);
void GLSL_SetUniformName(shaderProgram_t *program, int uniformNum, const char *name);
void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value);
void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat value);
void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_t v);
void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t v);
void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t v);
void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t v);
@ -2344,6 +2433,12 @@ void RB_SurfaceAnim( md4Surface_t *surfType );
void R_MDRAddAnimSurfaces( trRefEntity_t *ent );
void RB_MDRSurfaceAnim( md4Surface_t *surface );
#endif
qboolean R_LoadIQM (model_t *mod, void *buffer, int filesize, const char *name );
void R_AddIQMSurfaces( trRefEntity_t *ent );
void RB_IQMSurfaceAnim( surfaceType_t *surface );
int R_IQMLerpTag( orientation_t *tag, iqmData_t *data,
int startFrame, int endFrame,
float frac, const char *tagName );
/*
=============================================================
@ -2498,6 +2593,12 @@ typedef struct
int commandId;
} clearDepthCommand_t;
typedef struct {
int commandId;
int map;
int cubeSide;
} capShadowmapCommand_t;
typedef enum {
RC_END_OF_LIST,
RC_SET_COLOR,
@ -2508,7 +2609,8 @@ typedef enum {
RC_SCREENSHOT,
RC_VIDEOFRAME,
RC_COLORMASK,
RC_CLEARDEPTH
RC_CLEARDEPTH,
RC_CAPSHADOWMAP
} renderCommand_t;
@ -2528,6 +2630,7 @@ typedef struct {
trRefEntity_t entities[MAX_ENTITIES];
srfPoly_t *polys;//[MAX_POLYS];
polyVert_t *polyVerts;//[MAX_POLYVERTS];
pshadow_t pshadows[MAX_CALC_PSHADOWS];
renderCommandList_t commands;
} backEndData_t;
@ -2550,6 +2653,7 @@ void R_ShutdownCommandBuffers( void );
void R_SyncRenderThread( void );
void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs );
void R_AddCapShadowmapCmd( int dlight, int cubeSide );
void RE_SetColor( const float *rgba );
void RE_StretchPic ( float x, float y, float w, float h,

View file

@ -177,9 +177,16 @@ void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal,
VectorNormalize(bitangent);
// compute the face normal based on vertex points
VectorSubtract(v2, v0, u);
VectorSubtract(v1, v0, v);
CrossProduct(u, v, faceNormal);
if ( normal[0] == 0.0f && normal[1] == 0.0f && normal[2] == 0.0f )
{
VectorSubtract(v2, v0, u);
VectorSubtract(v1, v0, v);
CrossProduct(u, v, faceNormal);
}
else
{
VectorCopy(normal, faceNormal);
}
VectorNormalize(faceNormal);
@ -1061,7 +1068,7 @@ Set up the culling frustum planes for the current view using the results we got
the projection matrix.
=================
*/
void R_SetupFrustum (viewParms_t *dest, float xmin, float xmax, float ymax, float zProj, float stereoSep)
void R_SetupFrustum (viewParms_t *dest, float xmin, float xmax, float ymax, float zProj, float zFar, float stereoSep)
{
vec3_t ofsorigin;
float oppleg, adjleg, length;
@ -1114,6 +1121,18 @@ void R_SetupFrustum (viewParms_t *dest, float xmin, float xmax, float ymax, floa
dest->frustum[i].dist = DotProduct (ofsorigin, dest->frustum[i].normal);
SetPlaneSignbits( &dest->frustum[i] );
}
if (zFar != 0.0f)
{
vec3_t farpoint;
VectorMA(ofsorigin, zFar, dest->or.axis[0], farpoint);
VectorScale(dest->or.axis[0], -1.0f, dest->frustum[4].normal);
dest->frustum[4].type = PLANE_NON_AXIAL;
dest->frustum[4].dist = DotProduct (farpoint, dest->frustum[4].normal);
SetPlaneSignbits( &dest->frustum[4] );
}
}
/*
@ -1121,7 +1140,7 @@ void R_SetupFrustum (viewParms_t *dest, float xmin, float xmax, float ymax, floa
R_SetupProjection
===============
*/
void R_SetupProjection(viewParms_t *dest, float zProj, qboolean computeFrustum)
void R_SetupProjection(viewParms_t *dest, float zProj, float zFar, qboolean computeFrustum)
{
float xmin, xmax, ymin, ymax;
float width, height, stereoSep = r_stereoSeparation->value;
@ -1167,7 +1186,7 @@ void R_SetupProjection(viewParms_t *dest, float zProj, qboolean computeFrustum)
// Now that we have all the data for the projection matrix we can also setup the view frustum.
if(computeFrustum)
R_SetupFrustum(dest, xmin, xmax, ymax, zProj, stereoSep);
R_SetupFrustum(dest, xmin, xmax, ymax, zProj, zFar, stereoSep);
}
/*
@ -1182,7 +1201,8 @@ void R_SetupProjectionZ(viewParms_t *dest)
float zNear, zFar, depth;
zNear = r_znear->value;
zFar = dest->zFar;
zFar = dest->zFar;
depth = zFar - zNear;
dest->projectionMatrix[2] = 0;
@ -1502,6 +1522,7 @@ static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128
shader_t *shader;
int fogNum;
int dlighted;
int pshadowed;
vec4_t clip, eye;
int i;
unsigned int pointOr = 0;
@ -1513,7 +1534,7 @@ static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128
R_RotateForViewer();
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted );
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed );
RB_BeginSurface( shader, fogNum );
rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
@ -1750,7 +1771,7 @@ R_AddDrawSurf
=================
*/
void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader,
int fogIndex, int dlightMap ) {
int fogIndex, int dlightMap, int pshadowMap ) {
int index;
// instead of checking for overflow, we just mask the index
@ -1759,7 +1780,8 @@ void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader,
// the sort data is packed into a single 32 bit value so it can be
// compared quickly during the qsorting process
tr.refdef.drawSurfs[index].sort = (shader->sortedIndex << QSORT_SHADERNUM_SHIFT)
| tr.shiftedEntityNum | ( fogIndex << QSORT_FOGNUM_SHIFT ) | (int)dlightMap;
| tr.shiftedEntityNum | ( fogIndex << QSORT_FOGNUM_SHIFT )
| ((int)pshadowMap << QSORT_PSHADOW_SHIFT) | (int)dlightMap;
tr.refdef.drawSurfs[index].surface = surface;
tr.refdef.numDrawSurfs++;
}
@ -1770,11 +1792,12 @@ R_DecomposeSort
=================
*/
void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,
int *fogNum, int *dlightMap ) {
int *fogNum, int *dlightMap, int *pshadowMap ) {
*fogNum = ( sort >> QSORT_FOGNUM_SHIFT ) & 31;
*shader = tr.sortedShaders[ ( sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1) ];
*entityNum = ( sort >> QSORT_ENTITYNUM_SHIFT ) & (MAX_GENTITIES-1);
*dlightMap = sort & 3;
*pshadowMap = (sort & 2) >> 1;
*dlightMap = sort & 1;
}
/*
@ -1787,6 +1810,7 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
int fogNum;
int entityNum;
int dlighted;
int pshadowed;
int i;
// it is possible for some views to not have any surfaces
@ -1808,123 +1832,134 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
// check for any pass through drawing, which
// may cause another view to be rendered first
for ( i = 0 ; i < numDrawSurfs ; i++ ) {
R_DecomposeSort( (drawSurfs+i)->sort, &entityNum, &shader, &fogNum, &dlighted );
if (!tr.viewParms.isShadowmap)
{
for ( i = 0 ; i < numDrawSurfs ; i++ ) {
R_DecomposeSort( (drawSurfs+i)->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed );
if ( shader->sort > SS_PORTAL ) {
break;
}
// no shader should ever have this sort type
if ( shader->sort == SS_BAD ) {
ri.Error (ERR_DROP, "Shader '%s'with sort == SS_BAD", shader->name );
}
// if the mirror was completely clipped away, we may need to check another surface
if ( R_MirrorViewBySurface( (drawSurfs+i), entityNum) ) {
// this is a debug option to see exactly what is being mirrored
if ( r_portalOnly->integer ) {
return;
if ( shader->sort > SS_PORTAL ) {
break;
}
// no shader should ever have this sort type
if ( shader->sort == SS_BAD ) {
ri.Error (ERR_DROP, "Shader '%s'with sort == SS_BAD", shader->name );
}
// if the mirror was completely clipped away, we may need to check another surface
if ( R_MirrorViewBySurface( (drawSurfs+i), entityNum) ) {
// this is a debug option to see exactly what is being mirrored
if ( r_portalOnly->integer ) {
return;
}
break; // only one mirror view at a time
}
break; // only one mirror view at a time
}
}
R_AddDrawSurfCmd( drawSurfs, numDrawSurfs );
}
static void R_AddEntitySurface (int entityNum)
{
trRefEntity_t *ent;
shader_t *shader;
tr.currentEntityNum = entityNum;
ent = tr.currentEntity = &tr.refdef.entities[tr.currentEntityNum];
ent->needDlights = qfalse;
// preshift the value we are going to OR into the drawsurf sort
tr.shiftedEntityNum = tr.currentEntityNum << QSORT_ENTITYNUM_SHIFT;
//
// the weapon model must be handled special --
// we don't want the hacked weapon position showing in
// mirrors, because the true body position will already be drawn
//
if ( (ent->e.renderfx & RF_FIRST_PERSON) && (tr.viewParms.isPortal || tr.viewParms.isShadowmap)) {
return;
}
// simple generated models, like sprites and beams, are not culled
switch ( ent->e.reType ) {
case RT_PORTALSURFACE:
break; // don't draw anything
case RT_SPRITE:
case RT_BEAM:
case RT_LIGHTNING:
case RT_RAIL_CORE:
case RT_RAIL_RINGS:
// self blood sprites, talk balloons, etc should not be drawn in the primary
// view. We can't just do this check for all entities, because md3
// entities may still want to cast shadows from them
if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal) {
return;
}
shader = R_GetShaderByHandle( ent->e.customShader );
R_AddDrawSurf( &entitySurface, shader, R_SpriteFogNum( ent ), 0, 0 );
break;
case RT_MODEL:
// we must set up parts of tr.or for model culling
R_RotateForEntity( ent, &tr.viewParms, &tr.or );
tr.currentModel = R_GetModelByHandle( ent->e.hModel );
if (!tr.currentModel) {
R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0, 0 );
} else {
switch ( tr.currentModel->type ) {
case MOD_MESH:
R_AddMD3Surfaces( ent );
break;
case MOD_MD4:
R_AddAnimSurfaces( ent );
break;
#ifdef RAVENMD4
case MOD_MDR:
R_MDRAddAnimSurfaces( ent );
break;
#endif
case MOD_IQM:
R_AddIQMSurfaces( ent );
break;
case MOD_BRUSH:
R_AddBrushModelSurfaces( ent );
break;
case MOD_BAD: // null model axis
if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal) {
break;
}
shader = R_GetShaderByHandle( ent->e.customShader );
R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0, 0 );
break;
default:
ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad modeltype" );
break;
}
}
break;
default:
ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad reType" );
}
}
/*
=============
R_AddEntitySurfaces
=============
*/
void R_AddEntitySurfaces (void) {
trRefEntity_t *ent;
shader_t *shader;
int i;
if ( !r_drawentities->integer ) {
return;
}
for ( tr.currentEntityNum = 0;
tr.currentEntityNum < tr.refdef.num_entities;
tr.currentEntityNum++ ) {
ent = tr.currentEntity = &tr.refdef.entities[tr.currentEntityNum];
ent->needDlights = qfalse;
// preshift the value we are going to OR into the drawsurf sort
tr.shiftedEntityNum = tr.currentEntityNum << QSORT_ENTITYNUM_SHIFT;
//
// the weapon model must be handled special --
// we don't want the hacked weapon position showing in
// mirrors, because the true body position will already be drawn
//
if ( (ent->e.renderfx & RF_FIRST_PERSON) && tr.viewParms.isPortal) {
continue;
}
// simple generated models, like sprites and beams, are not culled
switch ( ent->e.reType ) {
case RT_PORTALSURFACE:
break; // don't draw anything
case RT_SPRITE:
case RT_BEAM:
case RT_LIGHTNING:
case RT_RAIL_CORE:
case RT_RAIL_RINGS:
// self blood sprites, talk balloons, etc should not be drawn in the primary
// view. We can't just do this check for all entities, because md3
// entities may still want to cast shadows from them
if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal) {
continue;
}
shader = R_GetShaderByHandle( ent->e.customShader );
R_AddDrawSurf( &entitySurface, shader, R_SpriteFogNum( ent ), 0 );
break;
case RT_MODEL:
// we must set up parts of tr.or for model culling
R_RotateForEntity( ent, &tr.viewParms, &tr.or );
tr.currentModel = R_GetModelByHandle( ent->e.hModel );
if (!tr.currentModel) {
R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0 );
} else {
switch ( tr.currentModel->type ) {
case MOD_MESH:
R_AddMD3Surfaces( ent );
break;
case MOD_MD4:
R_AddAnimSurfaces( ent );
break;
#ifdef RAVENMD4
case MOD_MDR:
R_MDRAddAnimSurfaces( ent );
break;
#endif
case MOD_BRUSH:
R_AddBrushModelSurfaces( ent );
break;
case MOD_BAD: // null model axis
if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal) {
break;
}
shader = R_GetShaderByHandle( ent->e.customShader );
R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0 );
break;
default:
ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad modeltype" );
break;
}
}
break;
default:
ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad reType" );
}
}
for ( i = 0; i < tr.refdef.num_entities; i++)
R_AddEntitySurface(i);
}
@ -1945,7 +1980,8 @@ void R_GenerateDrawSurfs( void ) {
// matrix for lod calculation
// dynamically compute far clip plane distance
R_SetFarClip();
if (!tr.viewParms.isShadowmap)
R_SetFarClip();
// we know the size of the clipping volume. Now set the rest of the projection matrix.
R_SetupProjectionZ (&tr.viewParms);
@ -2036,7 +2072,7 @@ void R_RenderView (viewParms_t *parms) {
// set viewParms.world
R_RotateForViewer ();
R_SetupProjection(&tr.viewParms, r_zproj->value, qtrue);
R_SetupProjection(&tr.viewParms, r_zproj->value, tr.viewParms.zFar, qtrue);
R_GenerateDrawSurfs();
@ -2047,5 +2083,418 @@ void R_RenderView (viewParms_t *parms) {
}
void R_RenderDlightCubemaps(const refdef_t *fd)
{
int i;
for (i = 0; i < tr.refdef.num_dlights; i++)
{
viewParms_t shadowParms;
int j;
// use previous frame to determine visible dlights
if ((1 << i) & tr.refdef.dlightMask)
continue;
Com_Memset( &shadowParms, 0, sizeof( shadowParms ) );
shadowParms.viewportX = tr.refdef.x;
shadowParms.viewportY = glConfig.vidHeight - ( tr.refdef.y + 256 );
shadowParms.viewportWidth = 256;
shadowParms.viewportHeight = 256;
shadowParms.isPortal = qfalse;
shadowParms.isMirror = qtrue; // because it is
shadowParms.fovX = 90;
shadowParms.fovY = 90;
shadowParms.isShadowmap = qtrue;
shadowParms.zFar = tr.refdef.dlights[i].radius;
VectorCopy( tr.refdef.dlights[i].origin, shadowParms.or.origin );
for (j = 0; j < 6; j++)
{
switch(j)
{
case 0:
// -X
VectorSet( shadowParms.or.axis[0], -1, 0, 0);
VectorSet( shadowParms.or.axis[1], 0, 0, -1);
VectorSet( shadowParms.or.axis[2], 0, 1, 0);
break;
case 1:
// +X
VectorSet( shadowParms.or.axis[0], 1, 0, 0);
VectorSet( shadowParms.or.axis[1], 0, 0, 1);
VectorSet( shadowParms.or.axis[2], 0, 1, 0);
break;
case 2:
// -Y
VectorSet( shadowParms.or.axis[0], 0, -1, 0);
VectorSet( shadowParms.or.axis[1], 1, 0, 0);
VectorSet( shadowParms.or.axis[2], 0, 0, -1);
break;
case 3:
// +Y
VectorSet( shadowParms.or.axis[0], 0, 1, 0);
VectorSet( shadowParms.or.axis[1], 1, 0, 0);
VectorSet( shadowParms.or.axis[2], 0, 0, 1);
break;
case 4:
// -Z
VectorSet( shadowParms.or.axis[0], 0, 0, -1);
VectorSet( shadowParms.or.axis[1], 1, 0, 0);
VectorSet( shadowParms.or.axis[2], 0, 1, 0);
break;
case 5:
// +Z
VectorSet( shadowParms.or.axis[0], 0, 0, 1);
VectorSet( shadowParms.or.axis[1], -1, 0, 0);
VectorSet( shadowParms.or.axis[2], 0, 1, 0);
break;
}
R_RenderView(&shadowParms);
R_AddCapShadowmapCmd( i, j );
}
}
}
void R_RenderPshadowMaps(const refdef_t *fd)
{
viewParms_t shadowParms;
int i;
// first, make a list of shadows
for ( i = 0; i < tr.refdef.num_entities; i++)
{
trRefEntity_t *ent = &tr.refdef.entities[i];
if((ent->e.renderfx & (RF_FIRST_PERSON | RF_NOSHADOW)))
continue;
//if((ent->e.renderfx & RF_THIRD_PERSON))
//continue;
if (ent->e.reType == RT_MODEL)
{
model_t *model = R_GetModelByHandle( ent->e.hModel );
pshadow_t shadow;
float radius = 0.0f;
float scale = 1.0f;
vec3_t diff;
int j;
if (!model)
continue;
if (ent->e.nonNormalizedAxes)
{
scale = VectorLength( ent->e.axis[0] );
}
switch (model->type)
{
case MOD_MESH:
{
mdvFrame_t *frame = &model->mdv[0]->frames[ent->e.frame];
radius = frame->radius * scale;
}
break;
case MOD_MD4:
{
// FIXME: actually calculate the radius and bounds, this is a horrible hack
radius = r_pshadowDist->value / 2.0f;
}
break;
#ifdef RAVENMD4
case MOD_MDR:
{
// FIXME: never actually tested this
mdrHeader_t *header = model->modelData;
int frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
mdrFrame_t *frame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame);
radius = frame->radius;
}
break;
#endif
case MOD_IQM:
{
// FIXME: never actually tested this
iqmData_t *data = model->modelData;
vec3_t diag;
float *framebounds;
framebounds = data->bounds + 6*ent->e.frame;
VectorSubtract( framebounds+3, framebounds, diag );
radius = 0.5f * VectorLength( diag );
}
break;
default:
break;
}
if (!radius)
continue;
// Cull entities that are behind the viewer by more than lightRadius
VectorSubtract(ent->e.origin, fd->vieworg, diff);
if (DotProduct(diff, fd->viewaxis[0]) < -r_pshadowDist->value)
continue;
memset(&shadow, 0, sizeof(shadow));
shadow.numEntities = 1;
shadow.entityNums[0] = i;
shadow.viewRadius = radius;
shadow.lightRadius = r_pshadowDist->value;
VectorCopy(ent->e.origin, shadow.viewOrigin);
shadow.sort = DotProduct(diff, diff) / (radius * radius);
VectorCopy(ent->e.origin, shadow.entityOrigins[0]);
shadow.entityRadiuses[0] = radius;
for (j = 0; j < MAX_CALC_PSHADOWS; j++)
{
pshadow_t swap;
if (j + 1 > tr.refdef.num_pshadows)
{
tr.refdef.num_pshadows = j + 1;
tr.refdef.pshadows[j] = shadow;
break;
}
// sort shadows by distance from camera divided by radius
// FIXME: sort better
if (tr.refdef.pshadows[j].sort <= shadow.sort)
continue;
swap = tr.refdef.pshadows[j];
tr.refdef.pshadows[j] = shadow;
shadow = swap;
}
}
}
// next, merge touching pshadows
for ( i = 0; i < tr.refdef.num_pshadows; i++)
{
pshadow_t *ps1 = &tr.refdef.pshadows[i];
int j;
for (j = i + 1; j < tr.refdef.num_pshadows; j++)
{
pshadow_t *ps2 = &tr.refdef.pshadows[j];
int k;
qboolean touch;
if (ps1->numEntities == 8)
break;
touch = qfalse;
if (SpheresIntersect(ps1->viewOrigin, ps1->viewRadius, ps2->viewOrigin, ps2->viewRadius))
{
for (k = 0; k < ps1->numEntities; k++)
{
if (SpheresIntersect(ps1->entityOrigins[k], ps1->entityRadiuses[k], ps2->viewOrigin, ps2->viewRadius))
{
touch = qtrue;
break;
}
}
}
if (touch)
{
vec3_t newOrigin;
float newRadius;
BoundingSphereOfSpheres(ps1->viewOrigin, ps1->viewRadius, ps2->viewOrigin, ps2->viewRadius, newOrigin, &newRadius);
VectorCopy(newOrigin, ps1->viewOrigin);
ps1->viewRadius = newRadius;
ps1->entityNums[ps1->numEntities] = ps2->entityNums[0];
VectorCopy(ps2->viewOrigin, ps1->entityOrigins[ps1->numEntities]);
ps1->entityRadiuses[ps1->numEntities] = ps2->viewRadius;
ps1->numEntities++;
for (k = j; k < tr.refdef.num_pshadows - 1; k++)
{
tr.refdef.pshadows[k] = tr.refdef.pshadows[k + 1];
}
j--;
tr.refdef.num_pshadows--;
}
}
}
// cap number of drawn pshadows
if (tr.refdef.num_pshadows > MAX_DRAWN_PSHADOWS)
{
tr.refdef.num_pshadows = MAX_DRAWN_PSHADOWS;
}
// next, fill up the rest of the shadow info
for ( i = 0; i < tr.refdef.num_pshadows; i++)
{
trRefEntity_t fakeEnt;
pshadow_t *shadow = &tr.refdef.pshadows[i];
vec3_t right;
vec3_t lightDir;
#if 0
VectorSet(lightDir, 0.57735, 0.57735, 0.57735);
#else
// light a fake entity to determine light direction
memset(&fakeEnt, 0, sizeof(fakeEnt));
VectorCopy(shadow->viewOrigin, fakeEnt.e.origin);
R_SetupEntityLighting( &tr.refdef, &fakeEnt);
VectorCopy(fakeEnt.lightDir, lightDir);
#endif
if (shadow->viewRadius * 3.0f > shadow->lightRadius)
{
shadow->lightRadius = shadow->viewRadius * 3.0f;
}
VectorMA(shadow->viewOrigin, shadow->viewRadius, lightDir, shadow->lightOrigin);
// make up a projection, spin doesn't matter
VectorScale(lightDir, -1.0f, shadow->lightViewAxis[0]);
VectorSet(right, 0, 0, -1);
if ( abs(DotProduct(right, shadow->lightViewAxis[0])) > 0.9f )
{
VectorSet(right, -1, 0, 0);
}
CrossProduct(shadow->lightViewAxis[0], right, shadow->lightViewAxis[1]);
VectorNormalize(shadow->lightViewAxis[1]);
CrossProduct(shadow->lightViewAxis[0], shadow->lightViewAxis[1], shadow->lightViewAxis[2]);
VectorCopy(shadow->lightViewAxis[0], shadow->cullPlane.normal);
shadow->cullPlane.dist = DotProduct(shadow->cullPlane.normal, shadow->lightOrigin);
shadow->cullPlane.type = PLANE_NON_AXIAL;
SetPlaneSignbits(&shadow->cullPlane);
}
// next, render shadowmaps
for ( i = 0; i < tr.refdef.num_pshadows; i++)
{
int firstDrawSurf;
pshadow_t *shadow = &tr.refdef.pshadows[i];
int j;
Com_Memset( &shadowParms, 0, sizeof( shadowParms ) );
shadowParms.viewportX = tr.refdef.x;
shadowParms.viewportY = glConfig.vidHeight - ( tr.refdef.y + 256 );
shadowParms.viewportWidth = 256;
shadowParms.viewportHeight = 256;
shadowParms.isPortal = qfalse;
shadowParms.isMirror = qfalse;
shadowParms.fovX = 90;
shadowParms.fovY = 90;
shadowParms.isShadowmap = qtrue;
shadowParms.zFar = shadow->lightRadius;
VectorCopy(shadow->lightOrigin, shadowParms.or.origin);
VectorCopy(shadow->lightViewAxis[0], shadowParms.or.axis[0]);
VectorCopy(shadow->lightViewAxis[1], shadowParms.or.axis[1]);
VectorCopy(shadow->lightViewAxis[2], shadowParms.or.axis[2]);
{
tr.viewCount++;
tr.viewParms = shadowParms;
tr.viewParms.frameSceneNum = tr.frameSceneNum;
tr.viewParms.frameCount = tr.frameCount;
firstDrawSurf = tr.refdef.numDrawSurfs;
tr.viewCount++;
// set viewParms.world
R_RotateForViewer ();
{
float xmin, xmax, ymin, ymax, znear, zfar;
viewParms_t *dest = &tr.viewParms;
vec3_t pop;
xmin = ymin = -shadow->viewRadius;
xmax = ymax = shadow->viewRadius;
znear = 0;
zfar = shadow->lightRadius;
dest->projectionMatrix[0] = 2 / (xmax - xmin);
dest->projectionMatrix[4] = 0;
dest->projectionMatrix[8] = (xmax + xmin) / (xmax - xmin);
dest->projectionMatrix[12] =0;
dest->projectionMatrix[1] = 0;
dest->projectionMatrix[5] = 2 / (ymax - ymin);
dest->projectionMatrix[9] = ( ymax + ymin ) / (ymax - ymin); // normally 0
dest->projectionMatrix[13] = 0;
dest->projectionMatrix[2] = 0;
dest->projectionMatrix[6] = 0;
dest->projectionMatrix[10] = 2 / (zfar - znear);
dest->projectionMatrix[14] = 0;
dest->projectionMatrix[3] = 0;
dest->projectionMatrix[7] = 0;
dest->projectionMatrix[11] = 0;
dest->projectionMatrix[15] = 1;
VectorScale(dest->or.axis[1], 1.0f, dest->frustum[0].normal);
VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[0].normal, pop);
dest->frustum[0].dist = DotProduct(pop, dest->frustum[0].normal);
VectorScale(dest->or.axis[1], -1.0f, dest->frustum[1].normal);
VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[1].normal, pop);
dest->frustum[1].dist = DotProduct(pop, dest->frustum[1].normal);
VectorScale(dest->or.axis[2], 1.0f, dest->frustum[2].normal);
VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[2].normal, pop);
dest->frustum[2].dist = DotProduct(pop, dest->frustum[2].normal);
VectorScale(dest->or.axis[2], -1.0f, dest->frustum[3].normal);
VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[3].normal, pop);
dest->frustum[3].dist = DotProduct(pop, dest->frustum[3].normal);
VectorScale(dest->or.axis[0], -1.0f, dest->frustum[4].normal);
VectorMA(dest->or.origin, -shadow->lightRadius, dest->frustum[4].normal, pop);
dest->frustum[4].dist = DotProduct(pop, dest->frustum[4].normal);
for (j = 0; j < 5; j++)
{
dest->frustum[j].type = PLANE_NON_AXIAL;
SetPlaneSignbits (&dest->frustum[j]);
}
}
for (j = 0; j < shadow->numEntities; j++)
{
R_AddEntitySurface(shadow->entityNums[j]);
}
R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf );
R_AddCapShadowmapCmd( i, -1 );
}
}
}

View file

@ -457,3 +457,4 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
}

View file

@ -185,12 +185,10 @@ int R_ComputeLOD( trRefEntity_t *ent ) {
// and use that as a criteria for selecting LOD
#ifdef RAVENMD4
// This is an MDR model.
if(tr.currentModel->md4)
if(tr.currentModel->type == MOD_MDR)
{
int frameSize;
mdr = (mdrHeader_t *) tr.currentModel->md4;
mdr = (mdrHeader_t *) tr.currentModel->modelData;
frameSize = (size_t) (&((mdrFrame_t *)0)->bones[mdr->numBones]);
mdrframe = (mdrFrame_t *) ((byte *) mdr + mdr->ofsFrames + frameSize * ent->e.frame);
@ -221,7 +219,7 @@ int R_ComputeLOD( trRefEntity_t *ent ) {
}
flod *= tr.currentModel->numLods;
lod = myftol( flod );
lod = Q_ftol(flod);
if ( lod < 0 )
{
@ -297,7 +295,7 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
qboolean personalModel;
// don't add third_person objects if not in a portal
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;
personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !(tr.viewParms.isPortal || tr.viewParms.isShadowmap);
if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
ent->e.frame %= tr.currentModel->mdv[0]->numFrames;
@ -396,7 +394,7 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
// don't add third_person objects if not viewing through a portal
if(!personalModel)
{
R_AddDrawSurf((void *)vboSurface, shader, fogNum, qfalse );
R_AddDrawSurf((void *)vboSurface, shader, fogNum, qfalse, qfalse );
}
}
else
@ -409,7 +407,7 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
&& fogNum == 0
&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
&& shader->sort == SS_OPAQUE ) {
R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse );
R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse, qfalse );
}
// projection shadows work fine with personal models
@ -417,12 +415,12 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
&& fogNum == 0
&& (ent->e.renderfx & RF_SHADOW_PLANE )
&& shader->sort == SS_OPAQUE ) {
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, qfalse );
}
// don't add third_person objects if not viewing through a portal
if ( !personalModel ) {
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse );
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse, qfalse );
}
}
@ -432,3 +430,4 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
}

View file

@ -25,13 +25,195 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define LL(x) x=LittleLong(x)
static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, int bufferSize, const char *modName );
static qboolean R_LoadMD4 (model_t *mod, void *buffer, const char *name );
static qboolean R_LoadMD3(model_t *mod, int lod, void *buffer, int bufferSize, const char *modName);
static qboolean R_LoadMD4(model_t *mod, void *buffer, const char *name );
#ifdef RAVENMD4
static qboolean R_LoadMDR (model_t *mod, void *buffer, int filesize, const char *name );
static qboolean R_LoadMDR(model_t *mod, void *buffer, int filesize, const char *name );
#endif
model_t *loadmodel;
/*
====================
R_RegisterMD3
====================
*/
qhandle_t R_RegisterMD3(const char *name, model_t *mod)
{
union {
unsigned *u;
void *v;
} buf;
int size;
int lod;
int ident;
qboolean loaded = qfalse;
int numLoaded;
char filename[MAX_QPATH], namebuf[MAX_QPATH+20];
char *fext, defex[] = "md3";
numLoaded = 0;
strcpy(filename, name);
fext = strchr(filename, '.');
if(!fext)
fext = defex;
else
{
*fext = '\0';
fext++;
}
for (lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod--)
{
if(lod)
Com_sprintf(namebuf, sizeof(namebuf), "%s_%d.%s", filename, lod, fext);
else
Com_sprintf(namebuf, sizeof(namebuf), "%s.%s", filename, fext);
size = ri.FS_ReadFile( namebuf, &buf.v );
if(!buf.u)
continue;
ident = LittleLong(* (unsigned *) buf.u);
if (ident == MD4_IDENT)
loaded = R_LoadMD4(mod, buf.u, name);
else
{
if (ident == MD3_IDENT)
loaded = R_LoadMD3(mod, lod, buf.u, size, name);
else
ri.Printf(PRINT_WARNING,"R_RegisterMD3: unknown fileid for %s\n", name);
}
ri.FS_FreeFile(buf.v);
if(loaded)
{
mod->numLods++;
numLoaded++;
}
else
break;
}
if(numLoaded)
{
// duplicate into higher lod spots that weren't
// loaded, in case the user changes r_lodbias on the fly
for(lod--; lod >= 0; lod--)
{
mod->numLods++;
mod->mdv[lod] = mod->mdv[lod + 1];
}
return mod->index;
}
#ifdef _DEBUG
ri.Printf(PRINT_WARNING,"R_RegisterMD3: couldn't load %s\n", name);
#endif
mod->type = MOD_BAD;
return 0;
}
#ifdef RAVENMD4
/*
====================
R_RegisterMDR
====================
*/
qhandle_t R_RegisterMDR(const char *name, model_t *mod)
{
union {
unsigned *u;
void *v;
} buf;
int ident;
qboolean loaded = qfalse;
int filesize;
filesize = ri.FS_ReadFile(name, (void **) &buf.v);
if(!buf.u)
{
mod->type = MOD_BAD;
return 0;
}
ident = LittleLong(*(unsigned *)buf.u);
if(ident == MDR_IDENT)
loaded = R_LoadMDR(mod, buf.u, filesize, name);
ri.FS_FreeFile (buf.v);
if(!loaded)
{
ri.Printf(PRINT_WARNING,"R_RegisterMDR: couldn't load mdr file %s\n", name);
mod->type = MOD_BAD;
return 0;
}
return mod->index;
}
#endif
/*
====================
R_RegisterIQM
====================
*/
qhandle_t R_RegisterIQM(const char *name, model_t *mod)
{
union {
unsigned *u;
void *v;
} buf;
qboolean loaded = qfalse;
int filesize;
filesize = ri.FS_ReadFile(name, (void **) &buf.v);
if(!buf.u)
{
mod->type = MOD_BAD;
return 0;
}
loaded = R_LoadIQM(mod, buf.u, filesize, name);
ri.FS_FreeFile (buf.v);
if(!loaded)
{
ri.Printf(PRINT_WARNING,"R_RegisterIQM: couldn't load iqm file %s\n", name);
mod->type = MOD_BAD;
return 0;
}
return mod->index;
}
typedef struct
{
char *ext;
qhandle_t (*ModelLoader)( const char *, model_t * );
} modelExtToLoaderMap_t;
// Note that the ordering indicates the order of preference used
// when there are multiple models of different formats available
static modelExtToLoaderMap_t modelLoaders[ ] =
{
{ "iqm", R_RegisterIQM },
#ifdef RAVENMD4
{ "mdr", R_RegisterMDR },
#endif
{ "md4", R_RegisterMD3 },
{ "md3", R_RegisterMD3 }
};
static int numModelLoaders = ARRAY_LEN(modelLoaders);
//===============================================================================
/*
** R_GetModelByHandle
@ -83,16 +265,13 @@ asked for again.
*/
qhandle_t RE_RegisterModel( const char *name ) {
model_t *mod;
union {
unsigned *u;
void *v;
} buf;
int lod;
int ident;
qboolean loaded = qfalse;
qhandle_t hModel;
int numLoaded;
char *fext, defex[] = "md3", filename[MAX_QPATH], namebuf[MAX_QPATH+20];
qboolean orgNameFailed = qfalse;
int orgLoader = -1;
int i;
char localName[ MAX_QPATH ];
const char *ext;
char altName[ MAX_QPATH ];
if ( !name || !name[0] ) {
ri.Printf( PRINT_ALL, "RE_RegisterModel: NULL name\n" );
@ -131,127 +310,75 @@ qhandle_t RE_RegisterModel( const char *name ) {
// make sure the render thread is stopped
R_SyncRenderThread();
mod->type = MOD_BAD;
mod->numLods = 0;
//
// load the files
//
numLoaded = 0;
Q_strncpyz( localName, name, MAX_QPATH );
strcpy(filename, name);
ext = COM_GetExtension( localName );
fext = strchr(filename, '.');
if(!fext)
fext = defex;
else
if( *ext )
{
*fext = '\0';
fext++;
}
#ifdef RAVENMD4
if(!Q_stricmp(fext, "mdr"))
{
int filesize;
filesize = ri.FS_ReadFile(name, (void **) &buf.v);
if(!buf.u)
// Look for the correct loader and use it
for( i = 0; i < numModelLoaders; i++ )
{
ri.Printf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name);
mod->type = MOD_BAD;
return 0;
}
ident = LittleLong(*(unsigned *)buf.u);
if(ident == MDR_IDENT)
loaded = R_LoadMDR(mod, buf.u, filesize, name);
ri.FS_FreeFile (buf.v);
if(!loaded)
{
ri.Printf(PRINT_WARNING,"RE_RegisterModel: couldn't load mdr file %s\n", name);
mod->type = MOD_BAD;
return 0;
}
return mod->index;
}
#endif
fext = defex;
for ( lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod-- ) {
int bufferSize;
if ( lod )
Com_sprintf(namebuf, sizeof(namebuf), "%s_%d.%s", filename, lod, fext);
else
Com_sprintf(namebuf, sizeof(namebuf), "%s.%s", filename, fext);
bufferSize = ri.FS_ReadFile( namebuf, &buf.v );
if ( !buf.u ) {
continue;
}
loadmodel = mod;
ident = LittleLong(*(unsigned *)buf.u);
if ( ident == MD4_IDENT ) {
loaded = R_LoadMD4( mod, buf.u, name );
} else {
if ( ident != MD3_IDENT ) {
ri.Printf (PRINT_WARNING,"RE_RegisterModel: unknown fileid for %s\n", name);
goto fail;
}
loaded = R_LoadMD3( mod, lod, buf.u, bufferSize, name );
}
ri.FS_FreeFile (buf.v);
if ( !loaded ) {
if ( lod == 0 ) {
goto fail;
} else {
if( !Q_stricmp( ext, modelLoaders[ i ].ext ) )
{
// Load
hModel = modelLoaders[ i ].ModelLoader( localName, mod );
break;
}
} else {
mod->numLods++;
numLoaded++;
// if we have a valid model and are biased
// so that we won't see any higher detail ones,
// stop loading them
// if ( lod <= r_lodbias->integer ) {
// break;
// }
}
// A loader was found
if( i < numModelLoaders )
{
if( !hModel )
{
// Loader failed, most likely because the file isn't there;
// try again without the extension
orgNameFailed = qtrue;
orgLoader = i;
COM_StripExtension( name, localName, MAX_QPATH );
}
else
{
// Something loaded
return mod->index;
}
}
}
if ( numLoaded ) {
// duplicate into higher lod spots that weren't
// loaded, in case the user changes r_lodbias on the fly
for ( lod-- ; lod >= 0 ; lod-- ) {
mod->numLods++;
mod->mdv[lod] = mod->mdv[lod+1];
// Try and find a suitable match using all
// the model formats supported
for( i = 0; i < numModelLoaders; i++ )
{
if (i == orgLoader)
continue;
Com_sprintf( altName, sizeof (altName), "%s.%s", localName, modelLoaders[ i ].ext );
// Load
hModel = modelLoaders[ i ].ModelLoader( altName, mod );
if( hModel )
{
if( orgNameFailed )
{
ri.Printf( PRINT_DEVELOPER, "WARNING: %s not present, using %s instead\n",
name, altName );
}
break;
}
return mod->index;
}
#ifdef _DEBUG
else {
ri.Printf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name);
}
#endif
fail:
// we still keep the model_t around, so if the model name is asked for
// again, we won't bother scanning the filesystem
mod->type = MOD_BAD;
return 0;
return hModel;
}
/*
=================
R_LoadMD3
@ -377,13 +504,15 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
if(md3Surf->numVerts > SHADER_MAX_VERTEXES)
{
ri.Error(ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)",
ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has more than %i verts on a surface (%i)",
modName, SHADER_MAX_VERTEXES, md3Surf->numVerts);
return qfalse;
}
if(md3Surf->numTriangles * 3 > SHADER_MAX_INDEXES)
{
ri.Error(ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)",
ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has more than %i triangles on a surface (%i)",
modName, SHADER_MAX_INDEXES / 3, md3Surf->numTriangles);
return qfalse;
}
// change to surface identifier
@ -447,16 +576,13 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
md3xyz = (md3XyzNormal_t *) ((byte *) md3Surf + md3Surf->ofsXyzNormals);
for(j = 0; j < md3Surf->numVerts * md3Surf->numFrames; j++, md3xyz++, v++)
{
#if 0
unsigned lat, lng;
unsigned short normal;
#endif
v->xyz[0] = LittleShort(md3xyz->xyz[0]) * MD3_XYZ_SCALE;
v->xyz[1] = LittleShort(md3xyz->xyz[1]) * MD3_XYZ_SCALE;
v->xyz[2] = LittleShort(md3xyz->xyz[2]) * MD3_XYZ_SCALE;
#if 0
normal = LittleShort(md3xyz->normal);
lat = ( normal >> 8 ) & 0xff;
@ -471,7 +597,6 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
v->normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
v->normal[1] = tr.sinTable[lat] * tr.sinTable[lng];
v->normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
#endif
}
// swap all the ST
@ -496,7 +621,8 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
{
VectorClear(v->tangent);
VectorClear(v->bitangent);
VectorClear(v->normal);
if (r_recalcMD3Normals->integer)
VectorClear(v->normal);
}
for(f = 0; f < mdvModel->numFrames; f++)
@ -511,6 +637,9 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
t1 = surf->st[tri->indexes[1]].st;
t2 = surf->st[tri->indexes[2]].st;
if (!r_recalcMD3Normals->integer)
VectorCopy(v->normal, normal);
#if 1
R_CalcTangentSpace(tangent, bitangent, normal, v0, v1, v2, t0, t1, t2);
#else
@ -528,8 +657,11 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
v = surf->verts[surf->numVerts * f + tri->indexes[k]].bitangent;
VectorAdd(v, bitangent, v);
v = surf->verts[surf->numVerts * f + tri->indexes[k]].normal;
VectorAdd(v, normal, v);
if (r_recalcMD3Normals->integer)
{
v = surf->verts[surf->numVerts * f + tri->indexes[k]].normal;
VectorAdd(v, normal, v);
}
}
}
}
@ -653,7 +785,7 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char
{
int i, j, k, l;
mdrHeader_t *pinmodel, *mdr;
mdrFrame_t *frame;
mdrFrame_t *frame;
mdrLOD_t *lod, *curlod;
mdrSurface_t *surf, *cursurf;
mdrTriangle_t *tri, *curtri;
@ -705,7 +837,7 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char
}
mod->dataSize += size;
mod->md4 = mdr = ri.Hunk_Alloc( size, h_low );
mod->modelData = mdr = ri.Hunk_Alloc( size, h_low );
// Copy all the values over from the file and fix endian issues in the process, if necessary.
@ -849,13 +981,13 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char
// now do the checks that may fail.
if ( surf->numVerts > SHADER_MAX_VERTEXES )
{
ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i verts on a surface (%i)",
ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i verts on a surface (%i).\n",
mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
return qfalse;
}
if ( surf->numTriangles*3 > SHADER_MAX_INDEXES )
{
ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i triangles on a surface (%i)",
ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i triangles on a surface (%i).\n",
mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
return qfalse;
}
@ -1014,7 +1146,7 @@ static qboolean R_LoadMD4( model_t *mod, void *buffer, const char *mod_name ) {
mod->type = MOD_MD4;
size = LittleLong(pinmodel->ofsEnd);
mod->dataSize += size;
md4 = mod->md4 = ri.Hunk_Alloc( size, h_low );
mod->modelData = md4 = ri.Hunk_Alloc( size, h_low );
Com_Memcpy(md4, buffer, size);
@ -1064,12 +1196,14 @@ static qboolean R_LoadMD4( model_t *mod, void *buffer, const char *mod_name ) {
LL(surf->ofsEnd);
if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)",
ri.Printf(PRINT_WARNING, "R_LoadMD4: %s has more than %i verts on a surface (%i).\n",
mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
return qfalse;
}
if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)",
ri.Printf(PRINT_WARNING, "R_LoadMD4: %s has more than %i triangles on a surface (%i).\n",
mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
return qfalse;
}
// change to surface identifier
@ -1269,7 +1403,7 @@ void R_GetAnimTag( mdrHeader_t *mod, int framenum, const char *tagName, md3Tag_t
// uncompressed model...
//
frameSize = (long)( &((mdrFrame_t *)0)->bones[ mod->numBones ] );
frameSize = (intptr_t)( &((mdrFrame_t *)0)->bones[ mod->numBones ] );
frame = (mdrFrame_t *)((byte *)mod + mod->ofsFrames + framenum * frameSize );
for (j = 0; j < 3; j++)
@ -1311,16 +1445,20 @@ int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFram
if ( !model->mdv[0] )
{
#ifdef RAVENMD4
if(model->md4)
if(model->type == MOD_MDR)
{
start = &start_space;
end = &end_space;
R_GetAnimTag((mdrHeader_t *) model->md4, startFrame, tagName, start);
R_GetAnimTag((mdrHeader_t *) model->md4, endFrame, tagName, end);
R_GetAnimTag((mdrHeader_t *) model->modelData, startFrame, tagName, start);
R_GetAnimTag((mdrHeader_t *) model->modelData, endFrame, tagName, end);
}
else
#endif
{
if( model->type == MOD_IQM ) {
return R_IQMLerpTag( tag, model->modelData,
startFrame, endFrame,
frac, tagName );
} else {
AxisClear( tag->axis );
VectorClear( tag->origin );
@ -1362,29 +1500,62 @@ R_ModelBounds
*/
void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) {
model_t *model;
mdvModel_t *mdvModel;
mdvFrame_t *frame;
model = R_GetModelByHandle( handle );
if ( model->bmodel ) {
if(model->type == MOD_BRUSH) {
VectorCopy( model->bmodel->bounds[0], mins );
VectorCopy( model->bmodel->bounds[1], maxs );
return;
} else if (model->type == MOD_MESH) {
mdvModel_t *header;
mdvFrame_t *frame;
header = model->mdv[0];
frame = header->frames;
VectorCopy( frame->bounds[0], mins );
VectorCopy( frame->bounds[1], maxs );
return;
} else if (model->type == MOD_MD4) {
md4Header_t *header;
md4Frame_t *frame;
header = (md4Header_t *)model->modelData;
frame = (md4Frame_t *) ((byte *)header + header->ofsFrames);
VectorCopy( frame->bounds[0], mins );
VectorCopy( frame->bounds[1], maxs );
return;
#ifdef RAVENMD4
} else if (model->type == MOD_MDR) {
mdrHeader_t *header;
mdrFrame_t *frame;
header = (mdrHeader_t *)model->modelData;
frame = (mdrFrame_t *) ((byte *)header + header->ofsFrames);
VectorCopy( frame->bounds[0], mins );
VectorCopy( frame->bounds[1], maxs );
return;
#endif
} else if(model->type == MOD_IQM) {
iqmData_t *iqmData;
iqmData = model->modelData;
if(iqmData->bounds)
{
VectorCopy(iqmData->bounds, mins);
VectorCopy(iqmData->bounds + 3, maxs);
return;
}
}
if ( !model->mdv[0] ) {
VectorClear( mins );
VectorClear( maxs );
return;
}
mdvModel = model->mdv[0];
frame = mdvModel->frames;
VectorCopy( frame->bounds[0], mins );
VectorCopy( frame->bounds[1], maxs );
VectorClear( mins );
VectorClear( maxs );
}

View file

@ -147,7 +147,7 @@ typedef struct {
// a -1 return means the file does not exist
// NULL can be passed for buf to just determine existance
int (*FS_FileIsInPAK)( const char *name, int *pCheckSum );
int (*FS_ReadFile)( const char *name, void **buf );
long (*FS_ReadFile)( const char *name, void **buf );
void (*FS_FreeFile)( void *buf );
char ** (*FS_ListFiles)( const char *name, const char *extension, int *numfilesfound );
void (*FS_FreeFileList)( char **filelist );

View file

@ -108,7 +108,7 @@ void R_AddPolygonSurfaces( void ) {
for ( i = 0, poly = tr.refdef.polys; i < tr.refdef.numPolys ; i++, poly++ ) {
sh = R_GetShaderByHandle( poly->hShader );
R_AddDrawSurf( ( void * )poly, sh, poly->fogIndex & fogMask, qfalse );
R_AddDrawSurf( ( void * )poly, sh, poly->fogIndex & fogMask, qfalse, qfalse );
}
}
@ -384,6 +384,9 @@ void RE_RenderScene( const refdef_t *fd ) {
tr.refdef.numPolys = r_numpolys - r_firstScenePoly;
tr.refdef.polys = &backEndData[tr.smpFrame]->polys[r_firstScenePoly];
tr.refdef.num_pshadows = 0;
tr.refdef.pshadows = &backEndData[tr.smpFrame]->pshadows[0];
// turn off dynamic lighting globally by clearing all the
// dlights if it needs to be disabled or if vertex lighting is enabled
if ( r_dynamiclight->integer == 0 ||
@ -400,6 +403,22 @@ void RE_RenderScene( const refdef_t *fd ) {
tr.frameSceneNum++;
tr.sceneCount++;
// SmileTheory: playing with shadow mapping
if (!( fd->rdflags & RDF_NOWORLDMODEL ) && tr.refdef.num_dlights && r_dlightShadows->integer
&& glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer
&& glRefConfig.glsl && r_arb_shader_objects->integer)
{
R_RenderDlightCubemaps(fd);
}
/* playing with more shadows */
if(!( fd->rdflags & RDF_NOWORLDMODEL ) && r_shadows->integer == 4
&& glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer
&& glRefConfig.glsl && r_arb_shader_objects->integer)
{
R_RenderPshadowMaps(fd);
}
// setup view parms for the initial view
//
// set up viewport

File diff suppressed because it is too large Load diff

View file

@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#endif
#define WAVEVALUE( table, base, amplitude, phase, freq ) ((base) + table[ myftol( ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude))
#define WAVEVALUE( table, base, amplitude, phase, freq ) ((base) + table[ Q_ftol( ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude))
static float *TableForFunc( genFunc_t func )
{
@ -48,7 +48,7 @@ static float *TableForFunc( genFunc_t func )
break;
}
ri.Error( ERR_DROP, "TableForFunc called with invalid function '%d' in shader '%s'\n", func, tess.shader->name );
ri.Error( ERR_DROP, "TableForFunc called with invalid function '%d' in shader '%s'", func, tess.shader->name );
return NULL;
}
@ -728,7 +728,7 @@ void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors )
glow = 1;
}
v = myftol( 255 * glow );
v = Q_ftol(255 * glow);
color[0] = color[1] = color[2] = v;
color[3] = 255;
v = *(int *)color;
@ -1121,23 +1121,6 @@ void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix )
RB_CalcTransformTexMatrix( &tmi, matrix );
}
#if id386 && !defined(__GNUC__)
long myftol( float f ) {
static int tmp;
__asm fld f
__asm fistp tmp
__asm mov eax, tmp
}
#endif
/*
** RB_CalcSpecularAlpha
**
@ -1300,19 +1283,19 @@ static void RB_CalcDiffuseColor_scalar( unsigned char *colors )
*(int *)&colors[i*4] = ambientLightInt;
continue;
}
j = myftol( ambientLight[0] + incoming * directedLight[0] );
j = Q_ftol(ambientLight[0] + incoming * directedLight[0]);
if ( j > 255 ) {
j = 255;
}
colors[i*4+0] = j;
j = myftol( ambientLight[1] + incoming * directedLight[1] );
j = Q_ftol(ambientLight[1] + incoming * directedLight[1]);
if ( j > 255 ) {
j = 255;
}
colors[i*4+1] = j;
j = myftol( ambientLight[2] + incoming * directedLight[2] );
j = Q_ftol(ambientLight[2] + incoming * directedLight[2]);
if ( j > 255 ) {
j = 255;
}
@ -1335,3 +1318,4 @@ void RB_CalcDiffuseColor( unsigned char *colors )
}

View file

@ -363,7 +363,7 @@ static void ParseTexMod( char *_text, shaderStage_t *stage )
texModInfo_t *tmi;
if ( stage->bundle[0].numTexMods == TR_MAX_TEXMODS ) {
ri.Error( ERR_DROP, "ERROR: too many tcMod stages in shader '%s'\n", shader.name );
ri.Error( ERR_DROP, "ERROR: too many tcMod stages in shader '%s'", shader.name );
return;
}
@ -842,6 +842,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
else if(!Q_stricmp(token, "specularMap"))
{
stage->type = ST_SPECULARMAP;
stage->specularReflectance = 0.04f;
}
else
{
@ -850,6 +851,19 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
}
}
//
// specularReflectance <value>
//
else if (!Q_stricmp(token, "specularreflectance"))
{
token = COM_ParseExt(text, qfalse);
if ( token[0] == 0 )
{
ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular reflectance in shader '%s'\n", shader.name );
continue;
}
stage->specularReflectance = atof( token );
}
//
// rgbGen
//
else if ( !Q_stricmp( token, "rgbGen" ) )
@ -1845,9 +1859,14 @@ static void ComputeVertexAttribs(void)
break;
}
if (pStage->glslShaderGroup)
if (pStage->glslShaderGroup == tr.lightallShader)
{
shader.vertexAttribs |= ATTR_NORMAL | ATTR_BITANGENT | ATTR_TANGENT;
shader.vertexAttribs |= ATTR_NORMAL;
if (pStage->glslShaderIndex & LIGHTDEF_USE_NORMALMAP)
{
shader.vertexAttribs |= ATTR_BITANGENT | ATTR_TANGENT;
}
}
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
@ -1881,7 +1900,7 @@ static void ComputeVertexAttribs(void)
case CGEN_ONE_MINUS_VERTEX:
shader.vertexAttribs |= ATTR_COLOR;
break;
case CGEN_LIGHTING_DIFFUSE:
shader.vertexAttribs |= ATTR_NORMAL;
break;
@ -2107,12 +2126,13 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
{
//ri.Printf(PRINT_ALL, ", specularmap %s", specular->bundle[0].image[0]->imgName);
diffuse->bundle[TB_SPECULARMAP] = specular->bundle[0];
diffuse->specularReflectance = specular->specularReflectance;
defs |= LIGHTDEF_USE_SPECULARMAP;
}
if (!isWorld)
{
defs |= LIGHTDEF_ENTITY;
defs |= LIGHTDEF_ENTITY | LIGHTDEF_USE_LIGHT_VECTOR;
}
if (environment)
@ -2138,6 +2158,31 @@ static qboolean CollapseStagesToGLSL(void)
skip = qtrue;
}
if (!skip)
{
// if 2+ stages and first stage is lightmap, switch them
// this makes it easier for the later bits to process
if (stages[0].active && stages[0].bundle[0].isLightmap && stages[1].active)
{
int blendBits = stages[1].stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
if (blendBits == (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO)
|| blendBits == (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR))
{
int stateBits0 = stages[0].stateBits;
int stateBits1 = stages[1].stateBits;
shaderStage_t swapStage;
swapStage = stages[0];
stages[0] = stages[1];
stages[1] = swapStage;
stages[0].stateBits = stateBits0;
stages[1].stateBits = stateBits1;
}
}
}
if (!skip)
{
// scan for shaders that aren't supported
@ -2148,7 +2193,7 @@ static qboolean CollapseStagesToGLSL(void)
if (!pStage->active)
continue;
if (pStage->bundle[0].isLightmap && i != 0)
if (pStage->bundle[0].isLightmap)
{
int blendBits = pStage->stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
@ -2156,6 +2201,7 @@ static qboolean CollapseStagesToGLSL(void)
&& blendBits != (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR))
{
skip = qtrue;
break;
}
}
@ -2198,19 +2244,21 @@ static qboolean CollapseStagesToGLSL(void)
if (!skip)
{
qboolean processedColormap = qfalse;
for (i = 0; i < MAX_SHADER_STAGES; i++)
{
shaderStage_t *pStage = &stages[i];
shaderStage_t *diffuse, *normal, *specular, *lightmap;
qboolean parallax, environment;
int stateBits;
qboolean parallax, environment, world;
if (!pStage->active)
continue;
if (pStage->type != ST_COLORMAP) // same as diffusemap and lightmap
// skip normal and specular maps
if (pStage->type != ST_COLORMAP)
continue;
// skip lightmaps
if (pStage->bundle[0].isLightmap)
continue;
diffuse = NULL;
@ -2219,15 +2267,7 @@ static qboolean CollapseStagesToGLSL(void)
specular = NULL;
lightmap = NULL;
if (pStage->bundle[0].isLightmap)
{
// stop processing if we've already done all the previous colormaps
if (processedColormap)
break;
lightmap = pStage;
}
// find matching normal, specular, and lightmap for this diffuse stage
for (j = i + 1; j < MAX_SHADER_STAGES; j++)
{
shaderStage_t *pStage2 = &stages[j];
@ -2235,66 +2275,43 @@ static qboolean CollapseStagesToGLSL(void)
if (!pStage2->active)
continue;
if (pStage2->type == ST_NORMALMAP && !normal)
switch(pStage2->type)
{
normal = pStage2;
continue;
}
if (pStage2->type == ST_NORMALPARALLAXMAP && !normal)
{
normal = pStage2;
parallax = qtrue;
continue;
}
if (pStage2->type == ST_SPECULARMAP && !specular)
{
specular = pStage2;
continue;
}
if (pStage2->type != ST_COLORMAP) // same as diffusemap and lightmap
continue;
// stop if
// - we hit another diffusemap after a lightmap
// - we hit the lightmap
if (lightmap)
{
if (pStage2->bundle[0].isLightmap)
{
// wtf? two lightmaps in one shader?
ri.Printf(PRINT_WARNING, "Found two lightmap passes in shader %s\n", shader.name);
case ST_NORMALMAP:
if (!normal)
{
normal = pStage2;
}
break;
}
diffuse = pStage2;
break;
}
else if (pStage2->bundle[0].isLightmap)
{
lightmap = pStage2;
break;
case ST_NORMALPARALLAXMAP:
if (!normal)
{
normal = pStage2;
parallax = qtrue;
}
break;
case ST_SPECULARMAP:
if (!specular)
{
specular = pStage2;
}
break;
case ST_COLORMAP:
if (pStage2->bundle[0].isLightmap)
{
lightmap = pStage2;
}
break;
default:
break;
}
}
if (lightmap == pStage)
{
// after light map
// deal with two lightmap stages problem
if (!diffuse)
break;
stateBits = lightmap->stateBits;
}
else
{
// before light map
diffuse = pStage;
stateBits = diffuse->stateBits;
}
diffuse = pStage;
environment = qfalse;
if (diffuse->bundle[0].tcGen == TCGEN_ENVIRONMENT_MAPPED)
@ -2302,21 +2319,13 @@ static qboolean CollapseStagesToGLSL(void)
environment = qtrue;
}
world = qtrue;
if (diffuse->rgbGen == CGEN_LIGHTING_DIFFUSE)
{
CollapseStagesToLightall(diffuse, normal, specular, NULL, qfalse, parallax, environment);
}
else if (lightmap)
{
CollapseStagesToLightall(diffuse, normal, specular, lightmap, qtrue, parallax, environment);
world = qfalse;
}
processedColormap = qtrue;
diffuse->stateBits = stateBits;
if (lightmap == pStage)
break;
CollapseStagesToLightall(diffuse, normal, specular, lightmap, world, parallax, environment);
}
// deactivate lightmap stages
@ -2400,6 +2409,8 @@ static void FixRenderCommandList( int newShader ) {
const void *curCmd = cmdList->cmds;
while ( 1 ) {
curCmd = PADP(curCmd, sizeof(void *));
switch ( *(const int *)curCmd ) {
case RC_SET_COLOR:
{
@ -2421,15 +2432,16 @@ static void FixRenderCommandList( int newShader ) {
int fogNum;
int entityNum;
int dlightMap;
int pshadowMap;
int sortedIndex;
const drawSurfsCommand_t *ds_cmd = (const drawSurfsCommand_t *)curCmd;
for( i = 0, drawSurf = ds_cmd->drawSurfs; i < ds_cmd->numDrawSurfs; i++, drawSurf++ ) {
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlightMap );
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlightMap, &pshadowMap );
sortedIndex = (( drawSurf->sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1));
if( sortedIndex >= newShader ) {
sortedIndex++;
drawSurf->sort = (sortedIndex << QSORT_SHADERNUM_SHIFT) | entityNum | ( fogNum << QSORT_FOGNUM_SHIFT ) | (int)dlightMap;
drawSurf->sort = (sortedIndex << QSORT_SHADERNUM_SHIFT) | entityNum | ( fogNum << QSORT_FOGNUM_SHIFT ) | ( (int)pshadowMap << QSORT_PSHADOW_SHIFT) | (int)dlightMap;
}
}
curCmd = (const void *)(ds_cmd + 1);

View file

@ -387,15 +387,16 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
static void DrawSkySideVBO( struct image_s *image, const int mins[2], const int maxs[2] )
{
int s, t;
//int firstVertex = tess.numVertexes;
int firstVertex = tess.numVertexes;
//int firstIndex = tess.numIndexes;
vec4_t color;
tess.numVertexes = 0;
tess.numIndexes = 0;
tess.firstIndex = 0;
//tess.numVertexes = 0;
//tess.numIndexes = 0;
tess.firstIndex = tess.numIndexes;
GL_Bind( image );
GL_Cull( CT_TWO_SIDED );
for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
{
@ -427,13 +428,13 @@ static void DrawSkySideVBO( struct image_s *image, const int mins[2], const int
ri.Error(ERR_DROP, "SHADER_MAX_INDEXES hit in DrawSkySideVBO()\n");
}
tess.indexes[tess.numIndexes++] = s + t * (maxs[0] - mins[0] + 1);
tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1);
tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1);
tess.indexes[tess.numIndexes++] = s + t * (maxs[0] - mins[0] + 1) + firstVertex;
tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex;
tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1) + firstVertex;
tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1);
tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1);
tess.indexes[tess.numIndexes++] = (s + 1) + (t + 1) * (maxs[0] - mins[0] + 1);
tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1) + firstVertex;
tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex;
tess.indexes[tess.numIndexes++] = (s + 1) + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex;
}
}
@ -449,8 +450,8 @@ static void DrawSkySideVBO( struct image_s *image, const int mins[2], const int
GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
color[0] = tr.identityLight;
color[1] = tr.identityLight;
color[0] =
color[1] =
color[2] = tr.identityLight;
color[3] = 1.0f;
GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color);
@ -459,17 +460,18 @@ static void DrawSkySideVBO( struct image_s *image, const int mins[2], const int
{
qglEnableClientState( GL_VERTEX_ARRAY );
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
qglDisableClientState( GL_COLOR_ARRAY );
qglVertexPointer(3, GL_FLOAT, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz));
qglTexCoordPointer( 2, GL_FLOAT, glState.currentVBO->stride_st, BUFFER_OFFSET(glState.currentVBO->ofs_st) );
}
qglDrawElements(GL_TRIANGLES, tess.numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex));
qglDrawElements(GL_TRIANGLES, tess.numIndexes - tess.firstIndex, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex * sizeof(GL_INDEX_TYPE)));
//R_BindNullVBO();
//R_BindNullIBO();
tess.numIndexes = 0;
tess.numVertexes = 0;
tess.numIndexes = tess.firstIndex;
tess.numVertexes = firstVertex;
tess.firstIndex = 0;
}
@ -574,7 +576,7 @@ static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean ad
if ( tess.numVertexes >= SHADER_MAX_VERTEXES )
{
ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in FillCloudySkySide()\n" );
ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in FillCloudySkySide()" );
}
}
}
@ -652,10 +654,10 @@ static void FillCloudBox( const shader_t *shader, int stage )
continue;
}
sky_mins_subd[0] = myftol( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS );
sky_mins_subd[1] = myftol( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS );
sky_maxs_subd[0] = myftol( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS );
sky_maxs_subd[1] = myftol( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS );
sky_mins_subd[0] = Q_ftol(sky_mins[0][i] * HALF_SKY_SUBDIVISIONS);
sky_mins_subd[1] = Q_ftol(sky_mins[1][i] * HALF_SKY_SUBDIVISIONS);
sky_maxs_subd[0] = Q_ftol(sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS);
sky_maxs_subd[1] = Q_ftol(sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS);
if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )
sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;
@ -976,3 +978,4 @@ void RB_StageIteratorSky( void ) {
}

View file

@ -333,7 +333,7 @@ static void RB_SurfacePolychain( srfPoly_t *p ) {
tess.numVertexes = numv;
}
static void RB_SurfaceHelper( int numVerts, srfVert_t *verts, int numTriangles, srfTriangle_t *triangles, int dlightBits)
static void RB_SurfaceHelper( int numVerts, srfVert_t *verts, int numTriangles, srfTriangle_t *triangles, int dlightBits, int pshadowBits)
{
int i;
srfTriangle_t *tri;
@ -396,11 +396,12 @@ static void RB_SurfaceHelper( int numVerts, srfVert_t *verts, int numTriangles,
#endif
tess.dlightBits |= dlightBits;
tess.pshadowBits |= pshadowBits;
tess.numVertexes += numVerts;
}
static qboolean RB_SurfaceHelperVBO(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndexes, int firstIndex, int dlightBits, qboolean shaderCheck)
static qboolean RB_SurfaceHelperVBO(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndexes, int firstIndex, int dlightBits, int pshadowBits, qboolean shaderCheck)
{
if( glRefConfig.vertexBufferObject && r_arb_vertex_buffer_object->integer && vbo && ibo)
{
@ -415,6 +416,7 @@ static qboolean RB_SurfaceHelperVBO(VBO_t *vbo, IBO_t *ibo, int numVerts, int nu
RB_CheckVBOandIBO(vbo, ibo);
tess.dlightBits |= dlightBits;
tess.pshadowBits |= pshadowBits;
// merge this into any existing multidraw primitives
mergeForward = -1;
@ -501,12 +503,12 @@ RB_SurfaceTriangles
=============
*/
static void RB_SurfaceTriangles( srfTriangles_t *srf ) {
if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], qtrue ) )
if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], srf->pshadowBits[backEnd.smpFrame], qtrue ) )
{
return;
}
RB_SurfaceHelper(srf->numVerts, srf->verts, srf->numTriangles, srf->triangles, srf->dlightBits[backEnd.smpFrame]);
RB_SurfaceHelper(srf->numVerts, srf->verts, srf->numTriangles, srf->triangles, srf->dlightBits[backEnd.smpFrame], srf->pshadowBits[backEnd.smpFrame]);
}
@ -1218,7 +1220,6 @@ static void RB_SurfaceMesh(mdvSurface_t *surface) {
indexes = surface->numTriangles * 3;
Bob = tess.numIndexes;
Doug = tess.numVertexes;
for (j = 0 ; j < surface->numTriangles ; j++) {
tess.indexes[Bob + j*3 + 0] = Doug + triangles[j].indexes[0];
tess.indexes[Bob + j*3 + 1] = Doug + triangles[j].indexes[1];
@ -1246,12 +1247,12 @@ RB_SurfaceFace
==============
*/
static void RB_SurfaceFace( srfSurfaceFace_t *srf ) {
if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], qtrue ) )
if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], srf->pshadowBits[backEnd.smpFrame], qtrue ) )
{
return;
}
RB_SurfaceHelper(srf->numVerts, srf->verts, srf->numTriangles, srf->triangles, srf->dlightBits[backEnd.smpFrame]);
RB_SurfaceHelper(srf->numVerts, srf->verts, srf->numTriangles, srf->triangles, srf->dlightBits[backEnd.smpFrame], srf->pshadowBits[backEnd.smpFrame]);
}
@ -1307,10 +1308,11 @@ static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
int lodWidth, lodHeight;
int numVertexes;
int dlightBits;
int pshadowBits;
//int *vDlightBits;
qboolean needsNormal;
if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], qtrue ) )
if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], srf->pshadowBits[backEnd.smpFrame], qtrue ) )
{
return;
}
@ -1318,6 +1320,9 @@ static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
dlightBits = srf->dlightBits[backEnd.smpFrame];
tess.dlightBits |= dlightBits;
pshadowBits = srf->pshadowBits[backEnd.smpFrame];
tess.pshadowBits |= pshadowBits;
// determine the allowable discrepance
lodError = LodErrorForVolume( srf->lodOrigin, srf->lodRadius );
@ -1537,7 +1542,7 @@ static void RB_SurfaceFlare(srfFlare_t *surf)
static void RB_SurfaceVBOMesh(srfVBOMesh_t * srf)
{
RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], qfalse );
RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], srf->pshadowBits[backEnd.smpFrame], qfalse );
}
void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface)
@ -1608,6 +1613,7 @@ void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = {
#ifdef RAVENMD4
(void(*)(void*))RB_MDRSurfaceAnim, // SF_MDR,
#endif
(void(*)(void*))RB_IQMSurfaceAnim, // SF_IQM,
(void(*)(void*))RB_SurfaceFlare, // SF_FLARE,
(void(*)(void*))RB_SurfaceEntity, // SF_ENTITY
(void(*)(void*))RB_SurfaceDisplayList, // SF_DISPLAY_LIST

View file

@ -27,6 +27,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces
#define MAX_ENTITIES 1023 // can't be increased without changing drawsurf bit packing
#define MAX_CALC_PSHADOWS 64
#define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces
// renderfx flags
#define RF_MINLIGHT 0x0001 // allways have some light (viewmodel, some items)
#define RF_THIRD_PERSON 0x0002 // don't draw through eyes, only mirrors (player bodies, chat sprites)

View file

@ -40,22 +40,38 @@ static qboolean R_CullSurface( msurface_t *surf ) {
{
// Only true for SF_FACE, so treat like its own function
float d;
cullType_t ct;
if ( !r_facePlaneCull->integer ) {
return qfalse;
}
if (surf->shader->cullType == CT_TWO_SIDED)
ct = surf->shader->cullType;
if (ct == CT_TWO_SIDED)
{
return qfalse;
}
// shadowmaps draw back surfaces
if ( tr.viewParms.isShadowmap )
{
if (ct == CT_FRONT_SIDED)
{
ct = CT_BACK_SIDED;
}
else
{
ct = CT_FRONT_SIDED;
}
}
d = DotProduct (tr.or.viewOrigin, surf->cullinfo.plane.normal);
// don't cull exactly on the plane, because there are levels of rounding
// through the BSP, ICD, and hardware that may cause pixel gaps if an
// epsilon isn't allowed here
if ( surf->shader->cullType == CT_FRONT_SIDED ) {
if ( ct == CT_FRONT_SIDED ) {
if ( d < surf->cullinfo.plane.dist - 8 ) {
return qtrue;
}
@ -143,7 +159,8 @@ static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
}
}
}
else if ( surf->cullinfo.type & CULLINFO_BOX )
if ( surf->cullinfo.type & CULLINFO_BOX )
{
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
if ( ! ( dlightBits & ( 1 << i ) ) ) {
@ -162,6 +179,21 @@ static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
}
}
if ( surf->cullinfo.type & CULLINFO_SPHERE )
{
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
if ( ! ( dlightBits & ( 1 << i ) ) ) {
continue;
}
dl = &tr.refdef.dlights[i];
if (!SpheresIntersect(dl->origin, dl->radius, surf->cullinfo.localOrigin, surf->cullinfo.radius))
{
// dlight doesn't reach the bounds
dlightBits &= ~( 1 << i );
}
}
}
if ( *surf->data == SF_FACE ) {
((srfSurfaceFace_t *)surf->data)->dlightBits[ tr.smpFrame ] = dlightBits;
} else if ( *surf->data == SF_GRID ) {
@ -181,12 +213,97 @@ static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
return dlightBits;
}
/*
====================
R_PshadowSurface
Just like R_DlightSurface, cull any we can
====================
*/
static int R_PshadowSurface( msurface_t *surf, int pshadowBits ) {
float d;
int i;
pshadow_t *ps;
if ( surf->cullinfo.type & CULLINFO_PLANE )
{
int i;
for ( i = 0 ; i < tr.refdef.num_pshadows ; i++ ) {
if ( ! ( pshadowBits & ( 1 << i ) ) ) {
continue;
}
ps = &tr.refdef.pshadows[i];
d = DotProduct( ps->lightOrigin, surf->cullinfo.plane.normal ) - surf->cullinfo.plane.dist;
if ( d < -ps->lightRadius || d > ps->lightRadius ) {
// pshadow doesn't reach the plane
pshadowBits &= ~( 1 << i );
}
}
}
if ( surf->cullinfo.type & CULLINFO_BOX )
{
for ( i = 0 ; i < tr.refdef.num_pshadows ; i++ ) {
if ( ! ( pshadowBits & ( 1 << i ) ) ) {
continue;
}
ps = &tr.refdef.pshadows[i];
if ( ps->lightOrigin[0] - ps->lightRadius > surf->cullinfo.bounds[1][0]
|| ps->lightOrigin[0] + ps->lightRadius < surf->cullinfo.bounds[0][0]
|| ps->lightOrigin[1] - ps->lightRadius > surf->cullinfo.bounds[1][1]
|| ps->lightOrigin[1] + ps->lightRadius < surf->cullinfo.bounds[0][1]
|| ps->lightOrigin[2] - ps->lightRadius > surf->cullinfo.bounds[1][2]
|| ps->lightOrigin[2] + ps->lightRadius < surf->cullinfo.bounds[0][2]
|| BoxOnPlaneSide(surf->cullinfo.bounds[0], surf->cullinfo.bounds[1], &ps->cullPlane) == 2 ) {
// pshadow doesn't reach the bounds
pshadowBits &= ~( 1 << i );
}
}
}
if ( surf->cullinfo.type & CULLINFO_SPHERE )
{
for ( i = 0 ; i < tr.refdef.num_pshadows ; i++ ) {
if ( ! ( pshadowBits & ( 1 << i ) ) ) {
continue;
}
ps = &tr.refdef.pshadows[i];
if (!SpheresIntersect(ps->viewOrigin, ps->viewRadius, surf->cullinfo.localOrigin, surf->cullinfo.radius)
|| DotProduct( surf->cullinfo.localOrigin, ps->cullPlane.normal ) - ps->cullPlane.dist < -surf->cullinfo.radius)
{
// pshadow doesn't reach the bounds
pshadowBits &= ~( 1 << i );
}
}
}
if ( *surf->data == SF_FACE ) {
((srfSurfaceFace_t *)surf->data)->pshadowBits[ tr.smpFrame ] = pshadowBits;
} else if ( *surf->data == SF_GRID ) {
((srfGridMesh_t *)surf->data)->pshadowBits[ tr.smpFrame ] = pshadowBits;
} else if ( *surf->data == SF_TRIANGLES ) {
((srfTriangles_t *)surf->data)->pshadowBits[ tr.smpFrame ] = pshadowBits;
} else if ( *surf->data == SF_VBO_MESH ) {
((srfVBOMesh_t *)surf->data)->pshadowBits[ tr.smpFrame ] = pshadowBits;
} else {
pshadowBits = 0;
}
if ( pshadowBits ) {
//tr.pc.c_dlightSurfaces++;
}
return pshadowBits;
}
/*
======================
R_AddWorldSurface
======================
*/
static void R_AddWorldSurface( msurface_t *surf, int dlightBits ) {
static void R_AddWorldSurface( msurface_t *surf, int dlightBits, int pshadowBits ) {
// FIXME: bmodel fog?
// try to cull before dlighting or adding
@ -200,7 +317,13 @@ static void R_AddWorldSurface( msurface_t *surf, int dlightBits ) {
dlightBits = ( dlightBits != 0 );
}
R_AddDrawSurf( surf->data, surf->shader, surf->fogIndex, dlightBits );
// check for pshadows
/*if ( pshadowBits ) */{
pshadowBits = R_PshadowSurface( surf, pshadowBits);
pshadowBits = ( pshadowBits != 0 );
}
R_AddDrawSurf( surf->data, surf->shader, surf->fogIndex, dlightBits, pshadowBits );
}
/*
@ -240,7 +363,7 @@ void R_AddBrushModelSurfaces ( trRefEntity_t *ent ) {
if (tr.world->surfacesViewCount[surf] != tr.viewCount)
{
tr.world->surfacesViewCount[surf] = tr.viewCount;
R_AddWorldSurface( tr.world->surfaces + surf, tr.currentEntity->needDlights );
R_AddWorldSurface( tr.world->surfaces + surf, tr.currentEntity->needDlights, 0 );
}
}
}
@ -260,10 +383,11 @@ void R_AddBrushModelSurfaces ( trRefEntity_t *ent ) {
R_RecursiveWorldNode
================
*/
static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits ) {
static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits, int pshadowBits ) {
do {
int newDlights[2];
unsigned int newPShadows[2];
// if the node wasn't marked as potentially visible, exit
if (node->visCounts[tr.visIndex] != tr.visCounts[tr.visIndex]) {
@ -316,6 +440,15 @@ static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits )
}
}
if ( planeBits & 16 ) {
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[4]);
if (r == 2) {
return; // culled
}
if ( r == 1 ) {
planeBits &= ~16; // all descendants will also be in front
}
}
}
if ( node->contents != -1 ) {
@ -349,12 +482,36 @@ static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits )
}
}
newPShadows[0] = 0;
newPShadows[1] = 0;
if ( pshadowBits ) {
int i;
for ( i = 0 ; i < tr.refdef.num_pshadows ; i++ ) {
pshadow_t *shadow;
float dist;
if ( pshadowBits & ( 1 << i ) ) {
shadow = &tr.refdef.pshadows[i];
dist = DotProduct( shadow->lightOrigin, node->plane->normal ) - node->plane->dist;
if ( dist > -shadow->lightRadius ) {
newPShadows[0] |= ( 1 << i );
}
if ( dist < shadow->lightRadius ) {
newPShadows[1] |= ( 1 << i );
}
}
}
}
// recurse down the children, front side first
R_RecursiveWorldNode (node->children[0], planeBits, newDlights[0] );
R_RecursiveWorldNode (node->children[0], planeBits, newDlights[0], newPShadows[0] );
// tail recurse
node = node->children[1];
dlightBits = newDlights[1];
pshadowBits = newPShadows[1];
} while ( 1 );
{
@ -397,13 +554,31 @@ static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits )
surf = *view;
if (surf < 0)
{
tr.world->mergedSurfacesViewCount[-surf - 1] = tr.viewCount;
tr.world->mergedSurfacesDlightBits[-surf - 1] = dlightBits;
if (tr.world->mergedSurfacesViewCount[-surf - 1] != tr.viewCount)
{
tr.world->mergedSurfacesViewCount[-surf - 1] = tr.viewCount;
tr.world->mergedSurfacesDlightBits[-surf - 1] = dlightBits;
tr.world->mergedSurfacesPshadowBits[-surf - 1] = pshadowBits;
}
else
{
tr.world->mergedSurfacesDlightBits[-surf - 1] |= dlightBits;
tr.world->mergedSurfacesPshadowBits[-surf - 1] |= pshadowBits;
}
}
else
{
tr.world->surfacesViewCount[surf] = tr.viewCount;
tr.world->surfacesDlightBits[surf] = dlightBits;
if (tr.world->surfacesViewCount[surf] != tr.viewCount)
{
tr.world->surfacesViewCount[surf] = tr.viewCount;
tr.world->surfacesDlightBits[surf] = dlightBits;
tr.world->surfacesPshadowBits[surf] = pshadowBits;
}
else
{
tr.world->surfacesDlightBits[surf] |= dlightBits;
tr.world->surfacesPshadowBits[surf] |= pshadowBits;
}
}
view++;
}
@ -607,18 +782,34 @@ void R_AddWorldSurfaces (void) {
if ( tr.refdef.num_dlights > 32 ) {
tr.refdef.num_dlights = 32 ;
}
R_RecursiveWorldNode( tr.world->nodes, 15, ( 1 << tr.refdef.num_dlights ) - 1 );
if ( tr.refdef.num_pshadows > 32 ) {
tr.refdef.num_pshadows = 32 ;
}
if ( tr.viewParms.isShadowmap)
{
R_RecursiveWorldNode( tr.world->nodes, 31, ( 1 << tr.refdef.num_dlights ) - 1, 0 );
}
else
{
R_RecursiveWorldNode( tr.world->nodes, 15, ( 1 << tr.refdef.num_dlights ) - 1, ( 1 << tr.refdef.num_pshadows ) - 1 );
}
// now add all the potentially visible surfaces
// also mask invisible dlights for next frame
{
int i;
tr.refdef.dlightMask = 0;
for (i = 0; i < tr.world->numWorldSurfaces; i++)
{
if (tr.world->surfacesViewCount[i] != tr.viewCount)
continue;
R_AddWorldSurface( tr.world->surfaces + i, tr.world->surfacesDlightBits[i] );
R_AddWorldSurface( tr.world->surfaces + i, tr.world->surfacesDlightBits[i], tr.world->surfacesPshadowBits[i] );
tr.refdef.dlightMask |= tr.world->surfacesDlightBits[i];
}
for (i = 0; i < tr.world->numMergedSurfaces; i++)
@ -626,7 +817,10 @@ void R_AddWorldSurfaces (void) {
if (tr.world->mergedSurfacesViewCount[i] != tr.viewCount)
continue;
R_AddWorldSurface( tr.world->mergedSurfaces + i, tr.world->mergedSurfacesDlightBits[i] );
R_AddWorldSurface( tr.world->mergedSurfaces + i, tr.world->mergedSurfacesDlightBits[i], tr.world->mergedSurfacesPshadowBits[i] );
tr.refdef.dlightMask |= tr.world->mergedSurfacesDlightBits[i];
}
tr.refdef.dlightMask = ~tr.refdef.dlightMask;
}
}

View file

@ -180,6 +180,7 @@ void (APIENTRY * qglUniform1iARB) (GLint location, GLint v0);
void (APIENTRY * qglUniform2iARB) (GLint location, GLint v0, GLint v1);
void (APIENTRY * qglUniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2);
void (APIENTRY * qglUniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
void (APIENTRY * qglUniform1fvARB) (GLint location, GLsizei count, const GLfloat * value);
void (APIENTRY * qglUniform2fvARB) (GLint location, GLsizei count, const GLfloat * value);
void (APIENTRY * qglUniform3fvARB) (GLint location, GLsizei count, const GLfloat * value);
void (APIENTRY * qglUniform4fvARB) (GLint location, GLsizei count, const GLfloat * value);
@ -975,6 +976,7 @@ static void GLimp_InitExtensions( void )
qglUniform2iARB = NULL;
qglUniform3iARB = NULL;
qglUniform4iARB = NULL;
qglUniform1fvARB = NULL;
qglUniform2fvARB = NULL;
qglUniform3fvARB = NULL;
qglUniform4fvARB = NULL;
@ -1014,6 +1016,7 @@ static void GLimp_InitExtensions( void )
qglUniform2iARB = (PFNGLUNIFORM2IARBPROC) SDL_GL_GetProcAddress("glUniform2iARB");
qglUniform3iARB = (PFNGLUNIFORM3IARBPROC) SDL_GL_GetProcAddress("glUniform3iARB");
qglUniform4iARB = (PFNGLUNIFORM4IARBPROC) SDL_GL_GetProcAddress("glUniform4iARB");
qglUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) SDL_GL_GetProcAddress("glUniform1fvARB");
qglUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) SDL_GL_GetProcAddress("glUniform2fvARB");
qglUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) SDL_GL_GetProcAddress("glUniform3fvARB");
qglUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) SDL_GL_GetProcAddress("glUniform4fvARB");
@ -1231,7 +1234,7 @@ void GLimp_Init( void )
}
// Nothing worked, give up
ri.Error( ERR_FATAL, "GLimp_Init() - could not load OpenGL subsystem\n" );
ri.Error( ERR_FATAL, "GLimp_Init() - could not load OpenGL subsystem" );
success:
// This values force the UI to disable driver selection

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