mirror of
https://github.com/ReactionQuake3/reaction.git
synced 2025-03-13 22:22:13 +00:00
Updating to IOQ3 svn 2064, vbos-glsl-17 and various fixes.
This commit is contained in:
parent
bd3aedfaeb
commit
58af049d5f
122 changed files with 6387 additions and 3887 deletions
|
@ -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 \
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
===========================================================================
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
===========================================================================
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
//===========================================================================
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -251,7 +251,7 @@
|
|||
* */
|
||||
void COM_StripExtensionInPlace(char *name)
|
||||
{
|
||||
char* ext = Q_strrchr(name, '.');
|
||||
char* ext = strrchr(name, '.');
|
||||
if (ext)
|
||||
*ext = 0;
|
||||
}
|
||||
|
|
|
@ -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--;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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( );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) );
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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, ¶ms_add },
|
||||
{ "addl", emit_subaddand, ¶ms_add },
|
||||
{ "addq", emit_subaddand, ¶ms_add },
|
||||
{ "addss", emit_twobyte, ¶ms_addss },
|
||||
{ "andb", emit_subaddand, ¶ms_and },
|
||||
{ "andl", emit_subaddand, ¶ms_and },
|
||||
{ "andq", emit_subaddand, ¶ms_and },
|
||||
{ "callq", emit_call, NULL },
|
||||
{ "cbw", emit_opsingle16, (void*)0x98 },
|
||||
{ "cdq", emit_opsingle, (void*)0x99 },
|
||||
{ "cmpb", emit_subaddand, ¶ms_cmp },
|
||||
{ "cmpl", emit_subaddand, ¶ms_cmp },
|
||||
{ "cmpq", emit_subaddand, ¶ms_cmp },
|
||||
{ "cvtsi2ss", emit_twobyte, ¶ms_cvtsi2ss },
|
||||
|
@ -977,18 +982,21 @@ static op_t ops[] = {
|
|||
{ "nop", emit_opsingle, (void*)0x90 },
|
||||
{ "notl", emit_op_rm, ¶ms_not },
|
||||
{ "notq", emit_op_rm, ¶ms_not },
|
||||
{ "or", emit_subaddand, ¶ms_or },
|
||||
{ "orb", emit_subaddand, ¶ms_or },
|
||||
{ "orl", emit_subaddand, ¶ms_or },
|
||||
{ "orq", emit_subaddand, ¶ms_or },
|
||||
{ "pop", emit_opreg, (void*)0x58 },
|
||||
{ "push", emit_opreg, (void*)0x50 },
|
||||
{ "ret", emit_opsingle, (void*)0xc3 },
|
||||
{ "sarl", emit_op_rm_cl, ¶ms_sar },
|
||||
{ "shl", emit_op_rm_cl, ¶ms_shl },
|
||||
{ "shrl", emit_op_rm_cl, ¶ms_shr },
|
||||
{ "subb", emit_subaddand, ¶ms_sub },
|
||||
{ "subl", emit_subaddand, ¶ms_sub },
|
||||
{ "subq", emit_subaddand, ¶ms_sub },
|
||||
{ "subss", emit_twobyte, ¶ms_subss },
|
||||
{ "ucomiss", emit_twobyte, ¶ms_ucomiss },
|
||||
{ "xorb", emit_subaddand, ¶ms_xor },
|
||||
{ "xorl", emit_subaddand, ¶ms_xor },
|
||||
{ "xorq", emit_subaddand, ¶ms_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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -528,3 +528,4 @@ void RB_RenderFlares (void) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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 ) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -457,3 +457,4 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 ) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
@ -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 )
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue