Initial commit.
This commit is contained in:
98
codemp/win32/AutoVersion.h
Normal file
98
codemp/win32/AutoVersion.h
Normal file
@@ -0,0 +1,98 @@
|
||||
#ifndef __AUTO_VERSION_HEADER
|
||||
#define __AUTO_VERSION_HEADER
|
||||
|
||||
#define VERSION_MAJOR_RELEASE 1
|
||||
#define VERSION_MINOR_RELEASE 0
|
||||
#define VERSION_EXTERNAL_BUILD 0
|
||||
#define VERSION_INTERNAL_BUILD 0
|
||||
|
||||
#define VERSION_STRING "1, 0, 0, 0"
|
||||
#define VERSION_STRING_DOTTED "1.0.0.0"
|
||||
|
||||
#define VERSION_BUILD_NUMBER 86
|
||||
|
||||
// BEGIN COMMENTS
|
||||
// 1.0.0.0 07/21/2003 16:05:31 jmonroe going gold
|
||||
// 0.0.12.0 07/20/2003 19:05:02 jmonroe build 0.12 for qa
|
||||
// 0.0.11.0 07/18/2003 12:08:44 jmonroe dlight fix, ui name fix, jk2 -> ja
|
||||
// 0.0.11.0 07/17/2003 17:19:17 jmonroe build 0.11 for qa
|
||||
// 0.0.10.1 07/16/2003 18:49:28 mgummelt General MP update
|
||||
// 0.0.10.0 07/16/2003 10:45:33 jmonroe new product id
|
||||
// 0.0.10.0 07/14/2003 19:38:41 jmonroe build 0.10 for qa
|
||||
// 0.0.9.0 07/11/2003 17:49:06 jmonroe build 0.09 for qa
|
||||
// 0.0.8.9 07/11/2003 14:38:31 rjohnson Update for siege stress test
|
||||
// 0.0.8.8 07/11/2003 13:09:19 rjohnson general update for test
|
||||
// 0.0.8.7 07/11/2003 10:52:01 rjohnson general update
|
||||
// 0.0.8.6 07/10/2003 16:23:28 rjohnson New test build
|
||||
// 0.0.8.5 07/10/2003 14:45:24 rjohnson General update
|
||||
// 0.0.8.4 07/10/2003 13:28:42 rjohnson General update for test
|
||||
// 0.0.8.3 07/09/2003 15:32:33 jmonroe fix mem leak on dlls
|
||||
// 0.0.8.2 07/09/2003 14:18:14 rjohnson New test for release server bug finding
|
||||
// 0.0.8.1 07/09/2003 13:29:39 rjohnson Update for modem test
|
||||
// 0.0.8.0 07/09/2003 11:09:24 rjohnson General update
|
||||
// 0.0.8.0 07/08/2003 16:47:56 jmonroe build 0.08 for qa
|
||||
// 0.0.7.5 07/07/2003 14:42:27 rjohnson Update for test
|
||||
// 0.0.7.4 07/05/2003 13:36:21 rjohnson new spawn points for duel
|
||||
// 0.0.7.3 07/03/2003 16:27:31 rjohnson Update for rich's code
|
||||
// 0.0.7.2 07/03/2003 16:01:36 rjohnson General update for test
|
||||
// 0.0.7.1 07/03/2003 13:26:18 rjohnson General update for test
|
||||
// 0.0.7.0 07/03/2003 11:41:17 rjohnson Update for Dan
|
||||
// 0.0.7.0 07/02/2003 19:36:05 jmonroe build 7 for qa
|
||||
// 0.0.6.7 07/02/2003 17:00:43 rjohnson General update for test
|
||||
// 0.0.6.6 07/02/2003 14:57:45 rjohnson Update to fix spamming problem
|
||||
// 0.0.6.5 07/02/2003 13:57:16 rjohnson Rich put in a default time limit so siege messages won't spam
|
||||
// 0.0.6.4 07/02/2003 13:26:45 rjohnson General update for test
|
||||
// 0.0.6.3 07/01/2003 14:40:06 rjohnson General update for test
|
||||
// 0.0.6.2 06/30/2003 16:31:56 rjohnson General update for test
|
||||
// 0.0.6.1 06/27/2003 14:30:37 rjohnson General update
|
||||
// 0.0.6.0 06/26/2003 18:44:01 rjohnson update for bob
|
||||
// 0.0.6.0 06/26/2003 17:37:02 jmonroe qa build
|
||||
// 0.0.5.10 06/26/2003 14:23:59 rjohnson General update
|
||||
// 0.0.5.9 06/26/2003 11:43:50 rjohnson General updates from everyone
|
||||
// 0.0.5.8 06/25/2003 18:02:26 rjohnson Update for test
|
||||
// 0.0.5.7 06/25/2003 16:22:06 rjohnson Update for test
|
||||
// 0.0.5.6 06/25/2003 13:35:47 rjohnson Automap and seeker changes and...
|
||||
// 0.0.5.5 06/25/2003 13:07:07 rjohnson Update
|
||||
// 0.0.5.4 06/25/2003 10:44:28 jmonroe EAX 4.0
|
||||
// 0.0.5.3 06/24/2003 14:27:16 rjohnson General Update
|
||||
// 0.0.5.2 06/23/2003 17:42:05 mgummelt Saber changes
|
||||
// 0.0.5.1 06/23/2003 10:30:51 rjohnson Refresh .exe on the net
|
||||
// 0.0.5.0 06/22/2003 16:44:05 mgummelt Rancor & Reborn/Cultist tweaks
|
||||
// 0.0.4.10 06/20/2003 14:26:46 rjohnson Update for 2:30 test
|
||||
// 0.0.4.9 06/20/2003 12:51:17 rjohnson Test of nathan's concept to show scores during duel matches
|
||||
// 0.0.4.8 06/19/2003 18:03:49 rjohnson General upate
|
||||
// 0.0.4.7 06/19/2003 14:22:45 rjohnson General update synch for gil
|
||||
// 0.0.4.6 06/19/2003 12:02:20 mgummelt Lightsaber Damage Fixed
|
||||
// 0.0.4.5 06/19/2003 11:49:13 mgummelt Fighter Control Scheme tweak
|
||||
// 0.0.4.4 06/19/2003 10:31:20 mgummelt Vehicle Fighter Controls 4.0 (fixed build)
|
||||
// 0.0.4.3 06/19/2003 01:40:18 mgummelt Vehicle Control Scheme 4.0
|
||||
// 0.0.4.2 06/18/2003 16:33:01 rjohnson With new and improved Gil compiling optimization settings (blame him!)
|
||||
// 0.0.4.1 06/17/2003 17:43:56 rjohnson Test to see if in game menu works
|
||||
// 0.0.4.0 06/17/2003 14:54:59 rjohnson General update
|
||||
// 0.0.4.0 06/14/2003 01:45:27 jmonroe inc version to synch with qa beta
|
||||
// 0.0.2.7 06/13/2003 17:30:44 rjohnson General update
|
||||
// 0.0.2.6 06/13/2003 16:54:54 rjohnson Fix for siege crash
|
||||
// 0.0.2.5 06/13/2003 14:47:35 rjohnson New stuff
|
||||
// 0.0.2.3 06/12/2003 17:05:57 rjohnson Rate test
|
||||
// 0.0.2.2 06/12/2003 15:46:11 rjohnson Entity reorg, general updates
|
||||
// 0.0.2.1 06/11/2003 13:28:50 rjohnson General new version stuff - lots of stuff by everyone
|
||||
// 0.0.2.0 06/11/2003 01:25:29 jmonroe material based footstep sounds ported from sp
|
||||
// 0.0.2.0 06/08/2003 00:18:19 jmonroe CGEN_LIGHTING_DIFFUSE_ENTITY merges lightingdiffuse and entity color
|
||||
// 0.0.1.16 06/07/2003 22:31:17 rwhitehouse Saber moves sync'd up with SP, skin/model fix (related to hunk switch to Z_Malloc)
|
||||
// 0.0.1.15 06/06/2003 23:05:55 rwhitehouse Vehicle controls suck somewhat less. (MP)
|
||||
// 0.0.1.14 06/05/2003 14:13:10 rwhitehouse swoop changes, attempted vehicle spectator fix
|
||||
// 0.0.1.13 06/04/2003 15:46:11 rwhitehouse The hunk has been removed entirely.
|
||||
// 0.0.1.12 06/03/2003 13:50:29 rwhitehouse swoop choppiness fix
|
||||
// 0.0.1.11 06/03/2003 13:26:46 rwhitehouse swoop infinite loop fix
|
||||
// 0.0.1.10 06/03/2003 11:18:27 rwhitehouse radar siege item fixes
|
||||
// 0.0.1.9 06/02/2003 16:05:35 rwhitehouse new radar flags for siege items and siege objective entities
|
||||
// 0.0.1.8 06/02/2003 14:37:56 rwhitehouse Swoop bug fixes, cartwheel/arial specials added for all saber stances, butterfly attack added for saber staff.
|
||||
// 0.0.1.7 06/01/2003 21:33:52 rwhitehouse anim bug fixes, swoop fixes.
|
||||
// 0.0.1.6 05/28/2003 17:22:11 rwhitehouse swoop fixes
|
||||
// 0.0.1.5 05/28/2003 11:33:02 rwhitehouse Swoop less horribly broken
|
||||
// 0.0.1.4 05/25/2003 19:22:02 rwhitehouse some dlight stuff.. and other things I forget
|
||||
// 0.0.1.2 05/22/2003 16:28:21 rwhitehouse Stencil shadows fixed, vehicle precaching fixed
|
||||
// 0.0.1.1 05/14/2003 16:14:42 jmonroe added version blocks
|
||||
// END COMMENTS
|
||||
|
||||
#endif // __AUTO_VERSION_HEADER
|
||||
104
codemp/win32/JK2cgame.rc
Normal file
104
codemp/win32/JK2cgame.rc
Normal file
@@ -0,0 +1,104 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
#include "AutoVersion.h"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
|
||||
PRODUCTVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "Raven Software"
|
||||
VALUE "CompanyName", "Activision Inc"
|
||||
VALUE "FileDescription", "JA Client Game DLL"
|
||||
VALUE "FileVersion", VERSION_STRING
|
||||
VALUE "InternalName", "JAcgame"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2003"
|
||||
VALUE "OriginalFilename", "JAcgame.dll"
|
||||
VALUE "ProductName", "Jedi Knight®: Jedi Academy (MP)"
|
||||
VALUE "ProductVersion", VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
104
codemp/win32/JK2game.rc
Normal file
104
codemp/win32/JK2game.rc
Normal file
@@ -0,0 +1,104 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
#include "AutoVersion.h"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
|
||||
PRODUCTVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "Raven Software"
|
||||
VALUE "CompanyName", "Activision Inc"
|
||||
VALUE "FileDescription", "JA Game DLL"
|
||||
VALUE "FileVersion", VERSION_STRING
|
||||
VALUE "InternalName", "JAgame"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2003"
|
||||
VALUE "OriginalFilename", "JAgame.dll"
|
||||
VALUE "ProductName", "Jedi Knight®: Jedi Academy (MP)"
|
||||
VALUE "ProductVersion", VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
105
codemp/win32/WinDed.rc
Normal file
105
codemp/win32/WinDed.rc
Normal file
@@ -0,0 +1,105 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
#include "AutoVersion.h"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
|
||||
PRODUCTVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "Raven Software"
|
||||
VALUE "CompanyName", "Activision Inc"
|
||||
VALUE "FileDescription", "Jedi Academy MP Dedicated Server"
|
||||
VALUE "FileVersion", VERSION_STRING
|
||||
VALUE "InternalName", "JA MP Ded"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2003"
|
||||
VALUE "OriginalFilename", "JAMPDed.exe"
|
||||
VALUE "ProductName", "Jedi Knight®: Jedi Academy Dedicated Server"
|
||||
VALUE "ProductVersion", VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
172
codemp/win32/dbg_console_xbox.cpp
Normal file
172
codemp/win32/dbg_console_xbox.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// File: dbg_console_xbox.cpp
|
||||
//
|
||||
// Desc: Listens for string commands sent from a debug console on a
|
||||
// remote dev machine, and forwards them to the Q3 engine.
|
||||
//
|
||||
// Commands are sent from the remote debug console through the debug
|
||||
// channel to the debug monitor on the Xbox machine. The Xbox machine
|
||||
// receives the commands on a separate thread through a
|
||||
// registered command processor callback function. The callback
|
||||
// function will store commands in a buffer, and the app should
|
||||
// poll this buffer once per frame and then decipher and handle
|
||||
// the commands.
|
||||
//
|
||||
// Hist: 02.05.01 - Initial creation for March XDK release
|
||||
// 08.21.02 - Revision and code cleanup
|
||||
// 04.10.02 - Buthcered by BTO for use in JK3:JA
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <xtl.h>
|
||||
#include <xbdm.h>
|
||||
#include <stdio.h>
|
||||
#include "dbg_console_xbox.h"
|
||||
#include "../client/client.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
|
||||
|
||||
// Command prefix for things sent across the dubg channel
|
||||
static const CHAR g_strDebugConsoleCommandPrefix[] = "XCMD";
|
||||
|
||||
|
||||
// Global buffer to receive remote commands from the debug console. Note that
|
||||
// since this data is accessed by the app's main thread, and the debug monitor
|
||||
// thread, we need to protect access with a critical section
|
||||
static CHAR g_strRemoteBuf[MAXRCMDLENGTH];
|
||||
|
||||
|
||||
// The critical section used to protect data that is shared between threads
|
||||
static CRITICAL_SECTION g_CriticalSection;
|
||||
|
||||
|
||||
// Temporary replacement for CRT string funcs, since
|
||||
// we can't call CRT functions on the debug monitor
|
||||
// thread right now.
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: dbgtolower()
|
||||
// Desc: Returns lowercase of char
|
||||
//-----------------------------------------------------------------------------
|
||||
inline CHAR dbgtolower( CHAR ch )
|
||||
{
|
||||
if( ch >= 'A' && ch <= 'Z' )
|
||||
return ch - ( 'A' - 'a' );
|
||||
else
|
||||
return ch;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: dbgstrnicmp()
|
||||
// Desc: Critical section safe string compare.
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL dbgstrnicmp( const CHAR* str1, const CHAR* str2, int n )
|
||||
{
|
||||
while( ( dbgtolower( *str1 ) == dbgtolower( *str2 ) ) && *str1 && n > 0 )
|
||||
{
|
||||
--n;
|
||||
++str1;
|
||||
++str2;
|
||||
}
|
||||
|
||||
return( n == 0 || dbgtolower( *str1 ) == dbgtolower( *str2 ) );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: dbgstrcpy()
|
||||
// Desc: Critical section safe string copy
|
||||
//-----------------------------------------------------------------------------
|
||||
VOID dbgstrcpy( CHAR* strDest, const CHAR* strSrc )
|
||||
{
|
||||
while( ( *strDest++ = *strSrc++ ) != 0 );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: DebugConsoleCmdProcessor()
|
||||
// Desc: Command notification proc that is called by the Xbox debug monitor to
|
||||
// have us process a command. What we'll actually attempt to do is tell
|
||||
// it to make calls to us on a separate thread, so that we can just block
|
||||
// until we're able to process a command.
|
||||
//
|
||||
// Note: Do NOT include newlines in the response string! To do so will confuse
|
||||
// the internal WinSock networking code used by the debug monitor API.
|
||||
//-----------------------------------------------------------------------------
|
||||
HRESULT __stdcall DebugConsoleCmdProcessor( const CHAR* strCommand,
|
||||
CHAR* strResponse, DWORD dwResponseLen,
|
||||
PDM_CMDCONT pdmcc )
|
||||
{
|
||||
// Skip over the command prefix and the exclamation mark
|
||||
strCommand += strlen(g_strDebugConsoleCommandPrefix) + 1;
|
||||
|
||||
// Check if this is the initial connect signal
|
||||
if( dbgstrnicmp( strCommand, "__connect__", 11 ) )
|
||||
{
|
||||
// If so, respond that we're connected
|
||||
lstrcpynA( strResponse, "Connected.", dwResponseLen );
|
||||
return XBDM_NOERR;
|
||||
}
|
||||
|
||||
// g_strRemoteBuf needs to be protected by the critical section
|
||||
EnterCriticalSection( &g_CriticalSection );
|
||||
if( g_strRemoteBuf[0] )
|
||||
{
|
||||
// This means the application has probably stopped polling for debug commands
|
||||
dbgstrcpy( strResponse, "Cannot execute - previous command still pending" );
|
||||
}
|
||||
else
|
||||
{
|
||||
dbgstrcpy( g_strRemoteBuf, strCommand );
|
||||
}
|
||||
LeaveCriticalSection( &g_CriticalSection );
|
||||
|
||||
return XBDM_NOERR;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: DebugConsoleHandleCommands()
|
||||
// Desc: Poll routine called periodically (typically every frame) by the Xbox
|
||||
// app to see if there is a command waiting to be executed, and if so,
|
||||
// execute it.
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL DebugConsoleHandleCommands()
|
||||
{
|
||||
static BOOL bInitialized = FALSE;
|
||||
CHAR strLocalBuf[MAXRCMDLENGTH+1]; // local copy of command
|
||||
|
||||
// Initialize ourselves when we're first called.
|
||||
if( !bInitialized )
|
||||
{
|
||||
// Register our command handler with the debug monitor
|
||||
HRESULT hr = DmRegisterCommandProcessor( g_strDebugConsoleCommandPrefix,
|
||||
DebugConsoleCmdProcessor );
|
||||
if( FAILED(hr) )
|
||||
return FALSE;
|
||||
|
||||
// We'll also need a critical section to protect access to g_strRemoteBuf
|
||||
InitializeCriticalSection( &g_CriticalSection );
|
||||
|
||||
bInitialized = TRUE;
|
||||
}
|
||||
|
||||
// If there's nothing waiting, return.
|
||||
if( !g_strRemoteBuf[0] )
|
||||
return FALSE;
|
||||
|
||||
// Grab a local copy of the command received in the remote buffer
|
||||
EnterCriticalSection( &g_CriticalSection );
|
||||
|
||||
lstrcpyA( strLocalBuf, g_strRemoteBuf );
|
||||
g_strRemoteBuf[0] = 0;
|
||||
|
||||
LeaveCriticalSection( &g_CriticalSection );
|
||||
|
||||
Cbuf_ExecuteText( EXEC_APPEND, va("%s\n", strLocalBuf) );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
34
codemp/win32/dbg_console_xbox.h
Normal file
34
codemp/win32/dbg_console_xbox.h
Normal file
@@ -0,0 +1,34 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// File: dbg_console_xbox.h
|
||||
//
|
||||
// Desc: Header file for communicating with a remote debug console. Please read
|
||||
// the comments in the dbg_console_xbox.cpp file for more info
|
||||
// on the API.
|
||||
//
|
||||
// This header defines the following arrays:
|
||||
//
|
||||
// g_RemoteCommands - This is the list of commands your application provides.
|
||||
// Note that "help" and "set" are provided automatically
|
||||
// This is implemented in DebugCmd.cpp
|
||||
//
|
||||
// g_RemoteVariables - This is a list of variables that your application
|
||||
// exposes. They can be examined and modified by the
|
||||
// remote debug console with the "set" command.
|
||||
// This is implemented in DebugChannel.cpp
|
||||
//
|
||||
// Hist: 02.05.01 - Initial creation for March XDK release
|
||||
// 08.21.02 - Revision and code cleanup
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef DEBUGCMD_H
|
||||
#define DEBUGCMD_H
|
||||
|
||||
#define MAXRCMDLENGTH 256 // Size of the remote cmd buffer
|
||||
|
||||
// Handle any remote commands that have been sent - this should be called
|
||||
// periodically by the application
|
||||
BOOL DebugConsoleHandleCommands();
|
||||
|
||||
#endif // DEBUGCMD_H
|
||||
|
||||
33
codemp/win32/glw_win.h
Normal file
33
codemp/win32/glw_win.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef _WIN32
|
||||
# error You should not be including this file on this platform
|
||||
#endif
|
||||
|
||||
#ifndef __GLW_WIN_H__
|
||||
#define __GLW_WIN_H__
|
||||
#include <windows.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WNDPROC wndproc;
|
||||
|
||||
HDC hDC; // handle to device context
|
||||
HGLRC hGLRC; // handle to GL rendering context
|
||||
|
||||
HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library
|
||||
|
||||
qboolean allowdisplaydepthchange;
|
||||
qboolean pixelFormatSet;
|
||||
|
||||
int desktopBitsPixel;
|
||||
int desktopWidth, desktopHeight;
|
||||
|
||||
qboolean cdsFullscreen;
|
||||
|
||||
FILE *log_fp;
|
||||
} glwstate_t;
|
||||
|
||||
extern glwstate_t glw_state;
|
||||
|
||||
bool GL_CheckForExtension(const char *ext);
|
||||
|
||||
#endif
|
||||
187
codemp/win32/glw_win_dx8.h
Normal file
187
codemp/win32/glw_win_dx8.h
Normal file
@@ -0,0 +1,187 @@
|
||||
|
||||
/*
|
||||
* UNPUBLISHED -- Rights reserved under the copyright laws of the
|
||||
* United States. Use of a copyright notice is precautionary only and
|
||||
* does not imply publication or disclosure.
|
||||
*
|
||||
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
|
||||
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
|
||||
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
|
||||
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
|
||||
*/
|
||||
|
||||
#ifndef __GLW_WIN_H__
|
||||
#define __GLW_WIN_H__
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <d3d8.h>
|
||||
#ifdef _WIN32
|
||||
#include <d3dx8.h>
|
||||
#endif
|
||||
|
||||
#include "../renderer/qgl_console.h"
|
||||
#include "../game/q_shared.h"
|
||||
#include "../qcommon/qfiles.h"
|
||||
|
||||
#define GLW_MAX_TEXTURE_STAGES 2
|
||||
#define GLW_MAX_STRIPS 2048
|
||||
|
||||
|
||||
struct glwstate_t
|
||||
{
|
||||
// Interface to DX
|
||||
IDirect3DDevice8* device;
|
||||
|
||||
// Matrix stuff
|
||||
enum MatrixMode
|
||||
{
|
||||
MatrixMode_Model = 0,
|
||||
MatrixMode_Projection = 1,
|
||||
MatrixMode_Texture0 = 2,
|
||||
MatrixMode_Texture1 = 3,
|
||||
MatrixMode_Texture2 = 4,
|
||||
MatrixMode_Texture3 = 5,
|
||||
|
||||
Num_MatrixModes
|
||||
};
|
||||
|
||||
ID3DXMatrixStack* matrixStack[Num_MatrixModes];
|
||||
MatrixMode matrixMode;
|
||||
|
||||
// Current primitive mode (triangles/quads/strips)
|
||||
D3DPRIMITIVETYPE primitiveMode;
|
||||
|
||||
// Are we in a glBegin/glEnd block? (Used for sanity checks.)
|
||||
bool inDrawBlock;
|
||||
|
||||
// Texturing
|
||||
bool textureStageDirty[GLW_MAX_TEXTURE_STAGES];
|
||||
bool textureStageEnable[GLW_MAX_TEXTURE_STAGES];
|
||||
GLuint currentTexture[GLW_MAX_TEXTURE_STAGES];
|
||||
D3DTEXTUREOP textureEnv[GLW_MAX_TEXTURE_STAGES];
|
||||
|
||||
struct TextureInfo
|
||||
{
|
||||
IDirect3DTexture8* mipmap;
|
||||
D3DTEXTUREFILTERTYPE minFilter, mipFilter, magFilter;
|
||||
D3DTEXTUREADDRESS wrapU, wrapV;
|
||||
float anisotropy;
|
||||
|
||||
// Bookkeeping for insane texture swapper:
|
||||
DWORD size;
|
||||
bool inMemory;
|
||||
void *data;
|
||||
int fileOffset; //Must start as -1!
|
||||
};
|
||||
|
||||
typedef std::map<GLuint, TextureInfo> texturexlat_t;
|
||||
texturexlat_t textureXlat;
|
||||
|
||||
GLuint textureBindNum;
|
||||
|
||||
GLuint serverTU, clientTU;
|
||||
|
||||
// Pointers to various draw buffers
|
||||
const void* vertexPointer;
|
||||
const void* normalPointer;
|
||||
const void* texCoordPointer[GLW_MAX_TEXTURE_STAGES];
|
||||
const void* colorPointer;
|
||||
|
||||
#ifdef _WINDOWS
|
||||
// Temporary storage used when rendering quads
|
||||
const void* vertexPointerBack;
|
||||
const void* normalPointerBack;
|
||||
const void* texCoordPointerBack[GLW_MAX_TEXTURE_STAGES];
|
||||
const void* colorPointerBack;
|
||||
#endif
|
||||
|
||||
// State of draw buffers
|
||||
bool colorArrayState;
|
||||
bool texCoordArrayState[GLW_MAX_TEXTURE_STAGES];
|
||||
bool vertexArrayState;
|
||||
bool normalArrayState;
|
||||
|
||||
// Stride of various draw buffers
|
||||
int vertexStride;
|
||||
int texCoordStride[GLW_MAX_TEXTURE_STAGES];
|
||||
int colorStride;
|
||||
int normalStride;
|
||||
|
||||
// Current number of verts in this packet
|
||||
int numVertices;
|
||||
|
||||
// Max verts allowed in this packet
|
||||
int maxVertices;
|
||||
|
||||
// Total verts to draw (may take multiple packets)
|
||||
int totalVertices;
|
||||
|
||||
// Current number of indices in this packet
|
||||
int numIndices;
|
||||
|
||||
// Max indices allowed in this packet
|
||||
int maxIndices;
|
||||
|
||||
// Total indices to draw
|
||||
int totalIndices;
|
||||
|
||||
// Culling
|
||||
bool cullEnable;
|
||||
D3DCULL cullMode;
|
||||
|
||||
// Viewport
|
||||
D3DVIEWPORT8 viewport;
|
||||
|
||||
// Clearing info
|
||||
D3DCOLOR clearColor;
|
||||
float clearDepth;
|
||||
int clearStencil;
|
||||
|
||||
// Widescreen mode
|
||||
bool isWidescreen;
|
||||
|
||||
// Global color
|
||||
D3DCOLOR currentColor;
|
||||
|
||||
// Scissoring
|
||||
bool scissorEnable;
|
||||
D3DRECT scissorBox;
|
||||
|
||||
// Directional Light
|
||||
D3DLIGHT8 dirLight[2];
|
||||
D3DMATERIAL8 mtrl;
|
||||
|
||||
// Description of current shader
|
||||
DWORD shaderMask;
|
||||
|
||||
// Should we reset matrices on next draw?
|
||||
bool matricesDirty[Num_MatrixModes];
|
||||
|
||||
// Render commands go here
|
||||
DWORD* drawArray;
|
||||
DWORD drawStride;
|
||||
|
||||
// This is designed to be an optimization for triangle strips
|
||||
// as well as making life easier for the flare effect
|
||||
GLushort strip_dest[SHADER_MAX_INDEXES];
|
||||
GLuint strip_lengths[GLW_MAX_STRIPS];
|
||||
GLsizei num_strip_lengths;
|
||||
|
||||
#ifdef _XBOX
|
||||
// class FlareEffect* flareEffect;
|
||||
class LightEffects* lightEffects;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern glwstate_t *glw_state;
|
||||
extern glwstate_t g_glwState;
|
||||
|
||||
void renderObject_HACK();
|
||||
void renderObject_Light( int numIndexes, const unsigned short *indexes );
|
||||
void renderObject_Env();
|
||||
void renderObject_Bump();
|
||||
bool CreateVertexShader( const CHAR* strFilename, const DWORD* pdwVertexDecl, DWORD* pdwVertexShader );
|
||||
bool CreatePixelShader( const CHAR* strFilename, DWORD* pdwPixelShader );
|
||||
|
||||
#endif
|
||||
BIN
codemp/win32/qe3.ico
Normal file
BIN
codemp/win32/qe3.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
23
codemp/win32/resource.h
Normal file
23
codemp/win32/resource.h
Normal file
@@ -0,0 +1,23 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by winquake.rc
|
||||
//
|
||||
#define IDS_STRING1 1
|
||||
#define IDI_ICON1 1
|
||||
#define IDB_BITMAP1 1
|
||||
#define IDB_BITMAP2 128
|
||||
#define IDC_CURSOR1 129
|
||||
#define IDC_CURSOR2 130
|
||||
#define IDC_CURSOR3 131
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 132
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1005
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
53
codemp/win32/shader_constants.h
Normal file
53
codemp/win32/shader_constants.h
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
//
|
||||
// ShaderConstants.h
|
||||
//
|
||||
// Definitions for various shader constants
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef _SHADERCONSTANTS_H_
|
||||
#define _SHADERCONSTANTS_H_
|
||||
|
||||
#define CV_ZERO 0
|
||||
#define CV_ONE 1
|
||||
#define CV_HALF 2
|
||||
|
||||
#define CV_WORLDVIEWPROJ_0 4
|
||||
#define CV_WORLDVIEWPROJ_1 5
|
||||
#define CV_WORLDVIEWPROJ_2 6
|
||||
#define CV_WORLDVIEWPROJ_3 7
|
||||
|
||||
#define CV_WORLDVIEW_0 8
|
||||
#define CV_WORLDVIEW_1 9
|
||||
#define CV_WORLDVIEW_2 10
|
||||
#define CV_WORLDVIEW_3 11
|
||||
|
||||
#define CV_WORLDVIEWIT_0 12
|
||||
#define CV_WORLDVIEWIT_1 13
|
||||
#define CV_WORLDVIEWIT_2 14
|
||||
|
||||
#define CV_WORLD_0 15
|
||||
#define CV_WORLD_1 16
|
||||
#define CV_WORLD_2 17
|
||||
#define CV_WORLD_3 18
|
||||
|
||||
#define CV_VIEWINV_0 19
|
||||
#define CV_VIEWINV_1 20
|
||||
#define CV_VIEWINV_2 21
|
||||
#define CV_VIEWINV_3 22
|
||||
|
||||
#define CV_LIGHT_COLOR 50
|
||||
#define CV_ONE_OVER_LIGHT_RANGE 51
|
||||
|
||||
#define CV_LIGHT_DIRECTION 52
|
||||
#define CV_LIGHT_POSITION 53
|
||||
|
||||
#define CV_CAMERA_DIRECTION 54
|
||||
|
||||
#define CV_VIEWPORT_OFFSETS 95
|
||||
|
||||
#define CP_AMBIENT_COLOR 0
|
||||
#define CP_DIFFUSE_COLOR 1
|
||||
|
||||
#endif
|
||||
85
codemp/win32/snd_fx_img.h
Normal file
85
codemp/win32/snd_fx_img.h
Normal file
@@ -0,0 +1,85 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum _DSP_IMAGE_image_FX_INDICES {
|
||||
GraphI3DL2_I3DL2Reverb = 0,
|
||||
GraphXTalk_XTalk = 1,
|
||||
GraphVoice_Voice_0 = 2,
|
||||
GraphVoice_Voice_1 = 3,
|
||||
GraphVoice_Voice_2 = 4,
|
||||
GraphVoice_Voice_3 = 5
|
||||
} DSP_IMAGE_image_FX_INDICES;
|
||||
|
||||
#define DSI3DL2_ENVIRONMENT_GraphI3DL2_I3DL2Reverb -1000, -100, 0.000000, 1.490000, 0.830000, -2602, 0.007000, 200, 0.011000, 100.000000, 100.000000, 5000.000000
|
||||
|
||||
typedef struct _GraphI3DL2_FX0_I3DL2Reverb_STATE {
|
||||
DWORD dwScratchOffset; // Offset in bytes, of scratch area for this FX
|
||||
DWORD dwScratchLength; // Length in DWORDS, of scratch area for this FX
|
||||
DWORD dwYMemoryOffset; // Offset in DSP WORDS, of Y memory area for this FX
|
||||
DWORD dwYMemoryLength; // Length in DSP WORDS, of Y memory area for this FX
|
||||
DWORD dwFlags; // FX bitfield for various flags. See xgpimage documentation
|
||||
DWORD dwInMixbinPtrs[2]; // XRAM offsets in DSP WORDS, of input mixbins
|
||||
DWORD dwOutMixbinPtrs[35]; // XRAM offsets in DSP WORDS, of output mixbins
|
||||
} GraphI3DL2_FX0_I3DL2Reverb_STATE, *LPGraphI3DL2_FX0_I3DL2Reverb_STATE;
|
||||
|
||||
typedef const GraphI3DL2_FX0_I3DL2Reverb_STATE *LPCGraphI3DL2_FX0_I3DL2Reverb_STATE;
|
||||
|
||||
typedef struct _GraphXTalk_FX0_XTalk_STATE {
|
||||
DWORD dwScratchOffset; // Offset in bytes, of scratch area for this FX
|
||||
DWORD dwScratchLength; // Length in DWORDS, of scratch area for this FX
|
||||
DWORD dwYMemoryOffset; // Offset in DSP WORDS, of Y memory area for this FX
|
||||
DWORD dwYMemoryLength; // Length in DSP WORDS, of Y memory area for this FX
|
||||
DWORD dwFlags; // FX bitfield for various flags. See xgpimage documentation
|
||||
DWORD dwInMixbinPtrs[4]; // XRAM offsets in DSP WORDS, of input mixbins
|
||||
DWORD dwOutMixbinPtrs[4]; // XRAM offsets in DSP WORDS, of output mixbins
|
||||
} GraphXTalk_FX0_XTalk_STATE, *LPGraphXTalk_FX0_XTalk_STATE;
|
||||
|
||||
typedef const GraphXTalk_FX0_XTalk_STATE *LPCGraphXTalk_FX0_XTalk_STATE;
|
||||
|
||||
typedef struct _GraphVoice_FX0_Voice_0_STATE {
|
||||
DWORD dwScratchOffset; // Offset in bytes, of scratch area for this FX
|
||||
DWORD dwScratchLength; // Length in DWORDS, of scratch area for this FX
|
||||
DWORD dwYMemoryOffset; // Offset in DSP WORDS, of Y memory area for this FX
|
||||
DWORD dwYMemoryLength; // Length in DSP WORDS, of Y memory area for this FX
|
||||
DWORD dwFlags; // FX bitfield for various flags. See xgpimage documentation
|
||||
DWORD dwInMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of input mixbins
|
||||
DWORD dwOutMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of output mixbins
|
||||
} GraphVoice_FX0_Voice_0_STATE, *LPGraphVoice_FX0_Voice_0_STATE;
|
||||
|
||||
typedef const GraphVoice_FX0_Voice_0_STATE *LPCGraphVoice_FX0_Voice_0_STATE;
|
||||
|
||||
typedef struct _GraphVoice_FX1_Voice_1_STATE {
|
||||
DWORD dwScratchOffset; // Offset in bytes, of scratch area for this FX
|
||||
DWORD dwScratchLength; // Length in DWORDS, of scratch area for this FX
|
||||
DWORD dwYMemoryOffset; // Offset in DSP WORDS, of Y memory area for this FX
|
||||
DWORD dwYMemoryLength; // Length in DSP WORDS, of Y memory area for this FX
|
||||
DWORD dwFlags; // FX bitfield for various flags. See xgpimage documentation
|
||||
DWORD dwInMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of input mixbins
|
||||
DWORD dwOutMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of output mixbins
|
||||
} GraphVoice_FX1_Voice_1_STATE, *LPGraphVoice_FX1_Voice_1_STATE;
|
||||
|
||||
typedef const GraphVoice_FX1_Voice_1_STATE *LPCGraphVoice_FX1_Voice_1_STATE;
|
||||
|
||||
typedef struct _GraphVoice_FX2_Voice_2_STATE {
|
||||
DWORD dwScratchOffset; // Offset in bytes, of scratch area for this FX
|
||||
DWORD dwScratchLength; // Length in DWORDS, of scratch area for this FX
|
||||
DWORD dwYMemoryOffset; // Offset in DSP WORDS, of Y memory area for this FX
|
||||
DWORD dwYMemoryLength; // Length in DSP WORDS, of Y memory area for this FX
|
||||
DWORD dwFlags; // FX bitfield for various flags. See xgpimage documentation
|
||||
DWORD dwInMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of input mixbins
|
||||
DWORD dwOutMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of output mixbins
|
||||
} GraphVoice_FX2_Voice_2_STATE, *LPGraphVoice_FX2_Voice_2_STATE;
|
||||
|
||||
typedef const GraphVoice_FX2_Voice_2_STATE *LPCGraphVoice_FX2_Voice_2_STATE;
|
||||
|
||||
typedef struct _GraphVoice_FX3_Voice_3_STATE {
|
||||
DWORD dwScratchOffset; // Offset in bytes, of scratch area for this FX
|
||||
DWORD dwScratchLength; // Length in DWORDS, of scratch area for this FX
|
||||
DWORD dwYMemoryOffset; // Offset in DSP WORDS, of Y memory area for this FX
|
||||
DWORD dwYMemoryLength; // Length in DSP WORDS, of Y memory area for this FX
|
||||
DWORD dwFlags; // FX bitfield for various flags. See xgpimage documentation
|
||||
DWORD dwInMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of input mixbins
|
||||
DWORD dwOutMixbinPtrs[1]; // XRAM offsets in DSP WORDS, of output mixbins
|
||||
} GraphVoice_FX3_Voice_3_STATE, *LPGraphVoice_FX3_Voice_3_STATE;
|
||||
|
||||
typedef const GraphVoice_FX3_Voice_3_STATE *LPCGraphVoice_FX3_Voice_3_STATE;
|
||||
104
codemp/win32/ui.rc
Normal file
104
codemp/win32/ui.rc
Normal file
@@ -0,0 +1,104 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
#include "AutoVersion.h"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
|
||||
PRODUCTVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "Raven Software"
|
||||
VALUE "CompanyName", "Activision Inc"
|
||||
VALUE "FileDescription", "JA User Interface DLL"
|
||||
VALUE "FileVersion", VERSION_STRING
|
||||
VALUE "InternalName", "ui"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2003"
|
||||
VALUE "OriginalFilename", "ui.dll"
|
||||
VALUE "ProductName", "Jedi Knight®: Jedi Academy (MP)"
|
||||
VALUE "ProductVersion", VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
32
codemp/win32/win_file.h
Normal file
32
codemp/win32/win_file.h
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
/*
|
||||
* UNPUBLISHED -- Rights reserved under the copyright laws of the
|
||||
* United States. Use of a copyright notice is precautionary only and
|
||||
* does not imply publication or disclosure.
|
||||
*
|
||||
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
|
||||
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
|
||||
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
|
||||
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
|
||||
*/
|
||||
|
||||
#ifndef _WIN_FILE_
|
||||
#define _WIN_FILE_
|
||||
|
||||
typedef int wfhandle_t;
|
||||
|
||||
extern void WF_Init(void);
|
||||
extern void WF_Shutdown(void);
|
||||
extern wfhandle_t WF_Open(const char* name, bool read, bool aligned);
|
||||
extern void WF_Close(wfhandle_t handle);
|
||||
extern int WF_Read(void* buffer, int len, wfhandle_t handle);
|
||||
extern int WF_Write(const void* buffer, int len, wfhandle_t handle);
|
||||
extern int WF_Seek(int offset, int origin, wfhandle_t handle);
|
||||
extern int WF_Tell(wfhandle_t handle);
|
||||
extern int WF_Resize(int size, wfhandle_t handle);
|
||||
|
||||
int Sys_GetFileCode(const char *name);
|
||||
void Sys_InitFileCodes(void);
|
||||
void Sys_ShutdownFileCodes(void);
|
||||
|
||||
#endif _WIN_FILE_
|
||||
171
codemp/win32/win_file_xbox.cpp
Normal file
171
codemp/win32/win_file_xbox.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
|
||||
/*
|
||||
* UNPUBLISHED -- Rights reserved under the copyright laws of the
|
||||
* United States. Use of a copyright notice is precautionary only and
|
||||
* does not imply publication or disclosure.
|
||||
*
|
||||
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
|
||||
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
|
||||
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
|
||||
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
|
||||
*/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "win_file.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
|
||||
#ifdef _XBOX
|
||||
#include <Xtl.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
struct FileTable
|
||||
{
|
||||
bool m_bUsed;
|
||||
bool m_bErrorsFatal;
|
||||
HANDLE m_Handle;
|
||||
};
|
||||
|
||||
FileTable* s_FileTable = NULL;
|
||||
const int WF_MAX_OPEN_FILES = 8;
|
||||
|
||||
void WF_Init(void)
|
||||
{
|
||||
assert(!s_FileTable);
|
||||
|
||||
s_FileTable = new FileTable[WF_MAX_OPEN_FILES];
|
||||
|
||||
for (wfhandle_t i = 0; i < WF_MAX_OPEN_FILES; ++i)
|
||||
{
|
||||
s_FileTable[i].m_bUsed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void WF_Shutdown(void)
|
||||
{
|
||||
assert(s_FileTable);
|
||||
|
||||
for (wfhandle_t i = 0; i < WF_MAX_OPEN_FILES; ++i)
|
||||
{
|
||||
if (s_FileTable[i].m_bUsed)
|
||||
{
|
||||
WF_Close(i);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] s_FileTable;
|
||||
s_FileTable = NULL;
|
||||
}
|
||||
|
||||
static wfhandle_t WF_GetFreeHandle(void)
|
||||
{
|
||||
for (int i = 0; i < WF_MAX_OPEN_FILES; ++i)
|
||||
{
|
||||
if (!s_FileTable[i].m_bUsed)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int WF_Open(const char* name, bool read, bool aligned)
|
||||
{
|
||||
wfhandle_t handle = WF_GetFreeHandle();
|
||||
if (handle == -1) return -1;
|
||||
|
||||
s_FileTable[handle].m_Handle =
|
||||
CreateFile(name, read ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ, 0,
|
||||
read ? OPEN_EXISTING : OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL | (aligned ? FILE_FLAG_NO_BUFFERING : 0), 0);
|
||||
|
||||
if (s_FileTable[handle].m_Handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
s_FileTable[handle].m_bUsed = true;
|
||||
|
||||
// errors are fatal on game partition
|
||||
s_FileTable[handle].m_bErrorsFatal = (name[0] == 'D' || name[0] == 'd');
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void WF_Close(wfhandle_t handle)
|
||||
{
|
||||
assert(handle >= 0 && handle < WF_MAX_OPEN_FILES &&
|
||||
s_FileTable[handle].m_bUsed);
|
||||
|
||||
CloseHandle(s_FileTable[handle].m_Handle);
|
||||
s_FileTable[handle].m_bUsed = false;
|
||||
}
|
||||
|
||||
int WF_Read(void* buffer, int len, wfhandle_t handle)
|
||||
{
|
||||
assert(handle >= 0 && handle < WF_MAX_OPEN_FILES &&
|
||||
s_FileTable[handle].m_bUsed);
|
||||
|
||||
DWORD bytes;
|
||||
if (!ReadFile(s_FileTable[handle].m_Handle, buffer, len, &bytes, 0) &&
|
||||
s_FileTable[handle].m_bErrorsFatal)
|
||||
{
|
||||
#if defined(FINAL_BUILD)
|
||||
extern void ERR_DiscFail(bool);
|
||||
ERR_DiscFail(false);
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int WF_Write(const void* buffer, int len, wfhandle_t handle)
|
||||
{
|
||||
assert(handle >= 0 && handle < WF_MAX_OPEN_FILES &&
|
||||
s_FileTable[handle].m_bUsed);
|
||||
|
||||
DWORD bytes;
|
||||
WriteFile(s_FileTable[handle].m_Handle, buffer, len, &bytes, 0);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int WF_Seek(int offset, int origin, wfhandle_t handle)
|
||||
{
|
||||
assert(handle >= 0 && handle < WF_MAX_OPEN_FILES &&
|
||||
s_FileTable[handle].m_bUsed);
|
||||
|
||||
switch (origin)
|
||||
{
|
||||
case SEEK_CUR: origin = FILE_CURRENT; break;
|
||||
case SEEK_END: origin = FILE_END; break;
|
||||
case SEEK_SET: origin = FILE_BEGIN; break;
|
||||
default: assert(false);
|
||||
}
|
||||
|
||||
return SetFilePointer(s_FileTable[handle].m_Handle, offset, 0, origin) < 0;
|
||||
}
|
||||
|
||||
int WF_Tell(wfhandle_t handle)
|
||||
{
|
||||
assert(handle >= 0 && handle < WF_MAX_OPEN_FILES &&
|
||||
s_FileTable[handle].m_bUsed);
|
||||
|
||||
return SetFilePointer(s_FileTable[handle].m_Handle, 0, 0, FILE_CURRENT);
|
||||
}
|
||||
|
||||
int WF_Resize(int size, wfhandle_t handle)
|
||||
{
|
||||
assert(handle >= 0 && handle < WF_MAX_OPEN_FILES &&
|
||||
s_FileTable[handle].m_bUsed);
|
||||
|
||||
SetFilePointer(s_FileTable[handle].m_Handle, size, NULL, FILE_BEGIN);
|
||||
return SetEndOfFile(s_FileTable[handle].m_Handle);
|
||||
}
|
||||
345
codemp/win32/win_filecode.cpp
Normal file
345
codemp/win32/win_filecode.cpp
Normal file
@@ -0,0 +1,345 @@
|
||||
|
||||
/*
|
||||
* UNPUBLISHED -- Rights reserved under the copyright laws of the
|
||||
* United States. Use of a copyright notice is precautionary only and
|
||||
* does not imply publication or disclosure.
|
||||
*
|
||||
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
|
||||
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
|
||||
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
|
||||
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
|
||||
*/
|
||||
|
||||
#include "../server/exe_headers.h"
|
||||
#include "../client/client.h"
|
||||
#include "../win32/win_local.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "../qcommon/fixedmap.h"
|
||||
#include "../zlib/zlib.h"
|
||||
#include "../qcommon/files.h"
|
||||
|
||||
/***********************************************
|
||||
*
|
||||
* WINDOWS/XBOX VERSION
|
||||
*
|
||||
* Build a translation table, CRC -> file name. We have the memory.
|
||||
*
|
||||
************************************************/
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
#include <windows.h>
|
||||
#elif defined(_XBOX)
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
|
||||
struct FileInfo
|
||||
{
|
||||
char* name;
|
||||
int size;
|
||||
};
|
||||
static VVFixedMap< FileInfo, unsigned int >* s_Files = NULL;
|
||||
static byte* buffer;
|
||||
|
||||
HANDLE s_Mutex = INVALID_HANDLE_VALUE;
|
||||
|
||||
int _buildFileList(const char* path, bool insert, bool buildList)
|
||||
{
|
||||
WIN32_FIND_DATA data;
|
||||
char spec[MAX_OSPATH];
|
||||
int count = 0;
|
||||
|
||||
// Look for all files
|
||||
Com_sprintf(spec, sizeof(spec), "%s\\*.*", path);
|
||||
|
||||
HANDLE h = FindFirstFile(spec, &data);
|
||||
while (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
char full[MAX_OSPATH];
|
||||
Com_sprintf(full, sizeof(full), "%s\\%s", path, data.cFileName);
|
||||
|
||||
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
// Directory -- lets go recursive
|
||||
if (data.cFileName[0] != '.') {
|
||||
count += _buildFileList(full, insert, buildList);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if(insert || buildList)
|
||||
{
|
||||
// Regular file -- add it to the table
|
||||
strlwr(full);
|
||||
unsigned int code = crc32(0, (const byte *)full, strlen(full));
|
||||
|
||||
FileInfo info;
|
||||
info.name = CopyString(full);
|
||||
info.size = data.nFileSizeLow;
|
||||
|
||||
if(insert)
|
||||
{
|
||||
s_Files->Insert(info, code);
|
||||
}
|
||||
|
||||
if(buildList)
|
||||
{
|
||||
// get the length of the filename
|
||||
int len;
|
||||
len = strlen(info.name) + 1;
|
||||
|
||||
// save the file code
|
||||
*(int*)buffer = code;
|
||||
buffer += sizeof(code);
|
||||
|
||||
// save the name of the file
|
||||
strcpy((char*)buffer,info.name);
|
||||
buffer += len;
|
||||
|
||||
// save the size of the file
|
||||
*(int*)buffer = info.size;
|
||||
buffer += sizeof(info.size);
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
// Continue the loop
|
||||
if (!FindNextFile(h, &data))
|
||||
{
|
||||
FindClose(h);
|
||||
return count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool _buildFileListFromSavedList(void)
|
||||
{
|
||||
// open the file up for reading
|
||||
FILE* in;
|
||||
in = fopen("d:\\xbx_filelist","rb");
|
||||
if(!in)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// read in the number of files
|
||||
int count;
|
||||
if(!(fread(&count,sizeof(count),1,in)))
|
||||
{
|
||||
fclose(in);
|
||||
return false;
|
||||
}
|
||||
|
||||
// allocate memory for a temp buffer
|
||||
byte* baseAddr;
|
||||
int bufferSize;
|
||||
bufferSize = count * ( 2 * sizeof(int) + MAX_OSPATH );
|
||||
buffer = (byte*)Z_Malloc(bufferSize,TAG_TEMP_WORKSPACE,qtrue,32);
|
||||
baseAddr = buffer;
|
||||
|
||||
// read the rest of the file into a big buffer
|
||||
if(!(fread(buffer,bufferSize,1,in)))
|
||||
{
|
||||
fclose(in);
|
||||
Z_Free(baseAddr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// allocate some memory for s_Files
|
||||
s_Files = new VVFixedMap<FileInfo, unsigned int>(count);
|
||||
|
||||
// loop through all the files write out the codes
|
||||
int i;
|
||||
for(i = 0; i < count; i++)
|
||||
{
|
||||
FileInfo info;
|
||||
unsigned int code;
|
||||
|
||||
// read the code for the file
|
||||
code = *(int*)buffer;
|
||||
buffer += sizeof(code);
|
||||
|
||||
// read the filename
|
||||
info.name = CopyString((char*)buffer);
|
||||
buffer += (strlen(info.name) + 1);
|
||||
|
||||
// read the size of the file
|
||||
info.size = *(int*)buffer;
|
||||
buffer += sizeof(info.size);
|
||||
|
||||
// save the data - optimization: don't check for dupes!
|
||||
s_Files->InsertUnsafe(info, code);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
Z_Free(baseAddr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sys_SaveFileCodes(void)
|
||||
{
|
||||
bool ret;
|
||||
int res;
|
||||
|
||||
// get the number of files
|
||||
int count;
|
||||
count = _buildFileList(Sys_Cwd(), false, false);
|
||||
|
||||
// open a file for writing
|
||||
FILE* out;
|
||||
out = fopen("d:\\xbx_filelist","wb");
|
||||
if(!out)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// allocate a buffer for writing
|
||||
byte* baseAddr;
|
||||
int bufferSize;
|
||||
|
||||
bufferSize = sizeof(int) + ( count * ( 2 * sizeof(int) + MAX_OSPATH ) );
|
||||
baseAddr = (byte*)Z_Malloc(bufferSize,TAG_TEMP_WORKSPACE,qtrue,32);
|
||||
buffer = baseAddr;
|
||||
|
||||
// write the number of files to the buffer
|
||||
*(int*)buffer = count;
|
||||
buffer += sizeof(count);
|
||||
|
||||
// fill up the rest of the buffer
|
||||
ret = _buildFileList(Sys_Cwd(), false, true);
|
||||
|
||||
if(!ret)
|
||||
{
|
||||
// there was a problem
|
||||
fclose(out);
|
||||
Z_Free(baseAddr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// attempt to write out the data
|
||||
if(!(fwrite(baseAddr,bufferSize,1,out)))
|
||||
{
|
||||
// there was a problem
|
||||
fclose(out);
|
||||
Z_Free(baseAddr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// everything went ok
|
||||
fclose(out);
|
||||
Z_Free(baseAddr);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sys_InitFileCodes(void)
|
||||
{
|
||||
bool ret;
|
||||
int count = 0;
|
||||
|
||||
// First: try to load an existing filecode cache
|
||||
ret = _buildFileListFromSavedList();
|
||||
|
||||
// if we had trouble building the list that way
|
||||
// we need to do it by searching the files
|
||||
if( !ret )
|
||||
{
|
||||
// There was no filelist cache, make one
|
||||
if( !Sys_SaveFileCodes() )
|
||||
Com_Error( ERR_DROP, "ERROR: Couldn't create filecode cache\n" );
|
||||
|
||||
// Now re-read it
|
||||
if( !_buildFileListFromSavedList() )
|
||||
Com_Error( ERR_DROP, "ERROR: Couldn't re-read filecode cache\n" );
|
||||
}
|
||||
s_Files->Sort();
|
||||
|
||||
// make it thread safe
|
||||
s_Mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
}
|
||||
|
||||
void Sys_ShutdownFileCodes(void)
|
||||
{
|
||||
FileInfo* info = NULL;
|
||||
|
||||
info = s_Files->Pop();
|
||||
while(info)
|
||||
{
|
||||
Z_Free(info->name);
|
||||
info->name = NULL;
|
||||
info = s_Files->Pop();
|
||||
}
|
||||
|
||||
delete s_Files;
|
||||
s_Files = NULL;
|
||||
|
||||
CloseHandle(s_Mutex);
|
||||
}
|
||||
|
||||
int Sys_GetFileCode(const char* name)
|
||||
{
|
||||
WaitForSingleObject(s_Mutex, INFINITE);
|
||||
|
||||
// Get system level path
|
||||
char* osname = FS_BuildOSPath(name);
|
||||
|
||||
// Generate hash for file name
|
||||
strlwr(osname);
|
||||
unsigned int code = crc32(0, (const byte *)osname, strlen(osname));
|
||||
|
||||
// Check if the file exists
|
||||
if (!s_Files->Find(code))
|
||||
{
|
||||
ReleaseMutex(s_Mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ReleaseMutex(s_Mutex);
|
||||
return code;
|
||||
}
|
||||
|
||||
const char* Sys_GetFileCodeName(int code)
|
||||
{
|
||||
WaitForSingleObject(s_Mutex, INFINITE);
|
||||
|
||||
FileInfo *entry = s_Files->Find(code);
|
||||
if (entry)
|
||||
{
|
||||
ReleaseMutex(s_Mutex);
|
||||
return entry->name;
|
||||
}
|
||||
|
||||
ReleaseMutex(s_Mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int Sys_GetFileCodeSize(int code)
|
||||
{
|
||||
WaitForSingleObject(s_Mutex, INFINITE);
|
||||
|
||||
FileInfo *entry = s_Files->Find(code);
|
||||
if (entry)
|
||||
{
|
||||
ReleaseMutex(s_Mutex);
|
||||
return entry->size;
|
||||
}
|
||||
|
||||
ReleaseMutex(s_Mutex);
|
||||
return -1;
|
||||
}
|
||||
// Quick function to re-scan for new files, update the filecode
|
||||
// table, and dump the new one to disk
|
||||
void Sys_FilecodeScan_f( void )
|
||||
{
|
||||
// Make an updated filecode cache
|
||||
if( !Sys_SaveFileCodes() )
|
||||
Com_Error( ERR_DROP, "ERROR: Couldn't create filecode cache\n" );
|
||||
|
||||
// Throw out our current list
|
||||
Sys_ShutdownFileCodes();
|
||||
|
||||
// Re-init, which should use the new list we just made
|
||||
Sys_InitFileCodes();
|
||||
}
|
||||
165
codemp/win32/win_gamma.cpp
Normal file
165
codemp/win32/win_gamma.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
/*
|
||||
** WIN_GAMMA.C
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include "../renderer/tr_local.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "glw_win.h"
|
||||
#include "win_local.h"
|
||||
|
||||
static unsigned short s_oldHardwareGamma[3][256];
|
||||
|
||||
/*
|
||||
** WG_CheckHardwareGamma
|
||||
**
|
||||
** Determines if the underlying hardware supports the Win32 gamma correction API.
|
||||
*/
|
||||
void WG_CheckHardwareGamma( void )
|
||||
{
|
||||
HDC hDC;
|
||||
|
||||
glConfig.deviceSupportsGamma = qfalse;
|
||||
|
||||
if ( !r_ignorehwgamma->integer )
|
||||
{
|
||||
hDC = GetDC( GetDesktopWindow() );
|
||||
glConfig.deviceSupportsGamma = (qboolean)GetDeviceGammaRamp( hDC, s_oldHardwareGamma );
|
||||
ReleaseDC( GetDesktopWindow(), hDC );
|
||||
|
||||
if ( glConfig.deviceSupportsGamma )
|
||||
{
|
||||
//
|
||||
// do a sanity check on the gamma values
|
||||
//
|
||||
if ( ( HIBYTE( s_oldHardwareGamma[0][255] ) <= HIBYTE( s_oldHardwareGamma[0][0] ) ) ||
|
||||
( HIBYTE( s_oldHardwareGamma[1][255] ) <= HIBYTE( s_oldHardwareGamma[1][0] ) ) ||
|
||||
( HIBYTE( s_oldHardwareGamma[2][255] ) <= HIBYTE( s_oldHardwareGamma[2][0] ) ) )
|
||||
{
|
||||
glConfig.deviceSupportsGamma = qfalse;
|
||||
Com_Printf (S_COLOR_YELLOW "WARNING: device has broken gamma support, generated gamma.dat\n" );
|
||||
}
|
||||
|
||||
//
|
||||
// make sure that we didn't have a prior crash in the game, and if so we need to
|
||||
// restore the gamma values to at least a linear value
|
||||
//
|
||||
if ( ( HIBYTE( s_oldHardwareGamma[0][181] ) == 255 ) )
|
||||
{
|
||||
int g;
|
||||
|
||||
Com_Printf (S_COLOR_YELLOW "WARNING: suspicious gamma tables, using linear ramp for restoration\n" );
|
||||
|
||||
for ( g = 0; g < 255; g++ )
|
||||
{
|
||||
s_oldHardwareGamma[0][g] = g << 8;
|
||||
s_oldHardwareGamma[1][g] = g << 8;
|
||||
s_oldHardwareGamma[2][g] = g << 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void mapGammaMax( void ) {
|
||||
int i, j;
|
||||
unsigned short table[3][256];
|
||||
|
||||
// try to figure out what win2k will let us get away with setting
|
||||
for ( i = 0 ; i < 256 ; i++ ) {
|
||||
if ( i >= 128 ) {
|
||||
table[0][i] = table[1][i] = table[2][i] = 0xffff;
|
||||
} else {
|
||||
table[0][i] = table[1][i] = table[2][i] = i<<9;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < 128 ; i++ ) {
|
||||
for ( j = i*2 ; j < 255 ; j++ ) {
|
||||
table[0][i] = table[1][i] = table[2][i] = j<<8;
|
||||
if ( !SetDeviceGammaRamp( glw_state.hDC, table ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
table[0][i] = table[1][i] = table[2][i] = i<<9;
|
||||
Com_Printf( "index %i max: %i\n", i, j-1 );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
** GLimp_SetGamma
|
||||
**
|
||||
** This routine should only be called if glConfig.deviceSupportsGamma is TRUE
|
||||
*/
|
||||
void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned char blue[256] ) {
|
||||
unsigned short table[3][256];
|
||||
int i, j;
|
||||
int ret;
|
||||
OSVERSIONINFO vinfo;
|
||||
|
||||
if ( !glConfig.deviceSupportsGamma || r_ignorehwgamma->integer || !glw_state.hDC ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//mapGammaMax();
|
||||
|
||||
for ( i = 0; i < 256; i++ ) {
|
||||
table[0][i] = ( ( ( unsigned short ) red[i] ) << 8 ) | red[i];
|
||||
table[1][i] = ( ( ( unsigned short ) green[i] ) << 8 ) | green[i];
|
||||
table[2][i] = ( ( ( unsigned short ) blue[i] ) << 8 ) | blue[i];
|
||||
}
|
||||
|
||||
// Win2K puts this odd restriction on gamma ramps...
|
||||
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
|
||||
GetVersionEx( &vinfo );
|
||||
if ( vinfo.dwMajorVersion == 5 && vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) {
|
||||
Com_DPrintf( "performing W2K gamma clamp.\n" );
|
||||
for ( j = 0 ; j < 3 ; j++ ) {
|
||||
for ( i = 0 ; i < 128 ; i++ ) {
|
||||
if ( table[j][i] > ( (128+i) << 8 ) ) {
|
||||
table[j][i] = (128+i) << 8;
|
||||
}
|
||||
}
|
||||
if ( table[j][127] > 254<<8 ) {
|
||||
table[j][127] = 254<<8;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Com_DPrintf( "skipping W2K gamma clamp.\n" );
|
||||
}
|
||||
|
||||
// enforce constantly increasing
|
||||
for ( j = 0 ; j < 3 ; j++ ) {
|
||||
for ( i = 1 ; i < 256 ; i++ ) {
|
||||
if ( table[j][i] < table[j][i-1] ) {
|
||||
table[j][i] = table[j][i-1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ret = SetDeviceGammaRamp( glw_state.hDC, table );
|
||||
if ( !ret ) {
|
||||
Com_Printf( "SetDeviceGammaRamp failed.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** WG_RestoreGamma
|
||||
*/
|
||||
void WG_RestoreGamma( void )
|
||||
{
|
||||
if ( glConfig.deviceSupportsGamma )
|
||||
{
|
||||
HDC hDC;
|
||||
|
||||
hDC = GetDC( GetDesktopWindow() );
|
||||
SetDeviceGammaRamp( hDC, s_oldHardwareGamma );
|
||||
ReleaseDC( GetDesktopWindow(), hDC );
|
||||
}
|
||||
}
|
||||
|
||||
73
codemp/win32/win_gamma_console.cpp
Normal file
73
codemp/win32/win_gamma_console.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
** WIN_GAMMA.C
|
||||
*/
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
//#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include "../game/q_shared.h"
|
||||
#include "../renderer/tr_local.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "win_local.h"
|
||||
|
||||
#if defined(_XBOX)
|
||||
#include "glw_win_dx8.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** WG_CheckHardwareGamma
|
||||
**
|
||||
** Determines if the underlying hardware supports the Win32 gamma correction API.
|
||||
*/
|
||||
void WG_CheckHardwareGamma( void )
|
||||
{
|
||||
glConfig.deviceSupportsGamma = qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
** GLimp_SetGamma
|
||||
**
|
||||
** This routine should only be called if glConfig.deviceSupportsGamma is TRUE
|
||||
*/
|
||||
void GLimp_SetGamma( float g ) {
|
||||
#if defined(_GAMECUBE)
|
||||
GXGamma gamma = GX_GM_1_0;
|
||||
if (g >= 2.2f)
|
||||
{
|
||||
gamma = GX_GM_2_2;
|
||||
}
|
||||
else if (g >= 1.7f)
|
||||
{
|
||||
gamma = GX_GM_1_7;
|
||||
}
|
||||
GXSetDispCopyGamma(gamma);
|
||||
#elif defined(_XBOX)
|
||||
const int maxval = 255;
|
||||
|
||||
D3DGAMMARAMP ramp;
|
||||
for ( int i = 0; i < 256; i++ )
|
||||
{
|
||||
int inf;
|
||||
if ( g == 1 ) {
|
||||
inf = maxval * i / 255.0f;
|
||||
} else {
|
||||
inf = maxval * pow ( i/255.0f, 1.0f / g ) + 0.5f;
|
||||
}
|
||||
if (inf < 0) {
|
||||
inf = 0;
|
||||
}
|
||||
if (inf > maxval) {
|
||||
inf = maxval;
|
||||
}
|
||||
ramp.red[i] = inf;
|
||||
ramp.green[i] = inf;
|
||||
ramp.blue[i] = inf;
|
||||
}
|
||||
glw_state->device->SetGammaRamp(D3DSGR_CALIBRATE, &ramp);
|
||||
#endif
|
||||
}
|
||||
|
||||
2095
codemp/win32/win_glimp.cpp
Normal file
2095
codemp/win32/win_glimp.cpp
Normal file
File diff suppressed because it is too large
Load Diff
282
codemp/win32/win_glimp_console.cpp
Normal file
282
codemp/win32/win_glimp_console.cpp
Normal file
@@ -0,0 +1,282 @@
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
/*
|
||||
** WIN_GLIMP.C
|
||||
**
|
||||
** This file contains ALL Win32 specific stuff having to do with the
|
||||
** OpenGL refresh. When a port is being made the following functions
|
||||
** must be implemented by the port:
|
||||
**
|
||||
** GLimp_EndFrame
|
||||
** GLimp_Init
|
||||
** GLimp_LogComment
|
||||
** GLimp_Shutdown
|
||||
**
|
||||
** Note that the GLW_xxx functions are Windows specific GL-subsystem
|
||||
** related functions that are relevant ONLY to win_glimp.c
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include "../renderer/tr_local.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "win_local.h"
|
||||
|
||||
#if defined(_WINDOWS) || defined(_XBOX)
|
||||
#include "glw_win_dx8.h"
|
||||
#elif defined(_GAMECUBE)
|
||||
#include "glw_win_gc.h"
|
||||
#endif
|
||||
|
||||
|
||||
extern void WG_CheckHardwareGamma( void );
|
||||
|
||||
static void GLW_InitExtensions( void );
|
||||
static int GLW_CreateWindow( void );
|
||||
|
||||
//
|
||||
// function declaration
|
||||
//
|
||||
void QGL_EnableLogging( qboolean enable );
|
||||
qboolean QGL_Init( const char *dllname );
|
||||
void QGL_Shutdown( void );
|
||||
void GLW_Init(int width, int height, int colorbits, qboolean cdsFullscreen);
|
||||
void GLW_Shutdown(void);
|
||||
|
||||
|
||||
//
|
||||
// variable declarations
|
||||
//
|
||||
glwstate_t *glw_state = NULL;
|
||||
glwstate_t g_glwState;
|
||||
|
||||
|
||||
/*
|
||||
** GLW_CreateWindow
|
||||
**
|
||||
** Responsible for creating the Alchemy window and initializing the OpenGL driver.
|
||||
*/
|
||||
static qboolean GLW_CreateWindow( int width, int height, int colorbits, qboolean cdsFullscreen )
|
||||
{
|
||||
GLW_Init(width, height, colorbits, cdsFullscreen);
|
||||
IN_Init();
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
static void GLW_InitTextureCompression( void )
|
||||
{
|
||||
glConfig.textureCompression = TC_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
** GLW_InitExtensions
|
||||
*/
|
||||
static void GLW_InitExtensions( void )
|
||||
{
|
||||
// Select our tc scheme
|
||||
GLW_InitTextureCompression();
|
||||
|
||||
// GL_EXT_texture_env_add
|
||||
glConfig.textureEnvAddAvailable = qfalse;
|
||||
if ( strstr( glConfig.extensions_string, "EXT_texture_env_add" ) )
|
||||
{
|
||||
glConfig.textureEnvAddAvailable = qtrue;
|
||||
}
|
||||
|
||||
// GL_EXT_texture_filter_anisotropic
|
||||
glConfig.maxTextureFilterAnisotropy = 0;
|
||||
if ( strstr( glConfig.extensions_string, "EXT_texture_filter_anisotropic" ) )
|
||||
{
|
||||
qglGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.maxTextureFilterAnisotropy );
|
||||
Com_Printf ("...GL_EXT_texture_filter_anisotropic available\n" );
|
||||
|
||||
if ( r_ext_texture_filter_anisotropic->integer>1 )
|
||||
{
|
||||
Com_Printf ("...using GL_EXT_texture_filter_anisotropic\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf ("...ignoring GL_EXT_texture_filter_anisotropic\n" );
|
||||
}
|
||||
Cvar_Set( "r_ext_texture_filter_anisotropic_avail", va("%f",glConfig.maxTextureFilterAnisotropy) );
|
||||
if ( r_ext_texture_filter_anisotropic->value > glConfig.maxTextureFilterAnisotropy )
|
||||
{
|
||||
Cvar_Set( "r_ext_texture_filter_anisotropic", va("%f",glConfig.maxTextureFilterAnisotropy) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf ("...GL_EXT_texture_filter_anisotropic not found\n" );
|
||||
Cvar_Set( "r_ext_texture_filter_anisotropic_avail", "0" );
|
||||
}
|
||||
|
||||
// GL_EXT_clamp_to_edge
|
||||
glConfig.clampToEdgeAvailable = qfalse;
|
||||
if ( strstr( glConfig.extensions_string, "GL_EXT_texture_edge_clamp" ) )
|
||||
{
|
||||
glConfig.clampToEdgeAvailable = qtrue;
|
||||
}
|
||||
|
||||
// GL_ARB_multitexture
|
||||
if ( strstr( glConfig.extensions_string, "GL_ARB_multitexture" ) )
|
||||
{
|
||||
if ( qglActiveTextureARB )
|
||||
{
|
||||
qglGetIntegerv( GL_MAX_ACTIVE_TEXTURES_ARB, &glConfig.maxActiveTextures );
|
||||
|
||||
if ( glConfig.maxActiveTextures < 2 )
|
||||
{
|
||||
qglMultiTexCoord2fARB = NULL;
|
||||
qglActiveTextureARB = NULL;
|
||||
qglClientActiveTextureARB = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** GLW_LoadOpenGL
|
||||
**
|
||||
** GLimp_win.c internal function that attempts to load and use
|
||||
** a specific OpenGL DLL.
|
||||
*/
|
||||
static qboolean GLW_LoadOpenGL()
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
strlwr( strcpy( buffer, OPENGL_DRIVER_NAME ) );
|
||||
|
||||
//
|
||||
// load the driver and bind our function pointers to it
|
||||
//
|
||||
if ( QGL_Init( buffer ) )
|
||||
{
|
||||
GLW_CreateWindow(640, 480, 24, 1);
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
QGL_Shutdown();
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** GLimp_EndFrame
|
||||
*/
|
||||
void GLimp_EndFrame (void)
|
||||
{
|
||||
// don't flip if drawing to front buffer
|
||||
// if ( stricmp( r_drawBuffer->string, "GL_FRONT" ) != 0 )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
static void GLW_StartOpenGL( void )
|
||||
{
|
||||
//
|
||||
// load and initialize the specific OpenGL driver
|
||||
//
|
||||
if ( !GLW_LoadOpenGL() )
|
||||
{
|
||||
Com_Error( ERR_FATAL, "GLW_StartOpenGL() - could not load OpenGL subsystem\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** GLimp_Init
|
||||
**
|
||||
** This is the platform specific OpenGL initialization function. It
|
||||
** is responsible for loading OpenGL, initializing it, setting
|
||||
** extensions, creating a window of the appropriate size, doing
|
||||
** fullscreen manipulations, etc. Its overall responsibility is
|
||||
** to make sure that a functional OpenGL subsystem is operating
|
||||
** when it returns to the ref.
|
||||
*/
|
||||
void GLimp_Init( void )
|
||||
{
|
||||
// load appropriate DLL and initialize subsystem
|
||||
GLW_StartOpenGL();
|
||||
|
||||
// get our config strings
|
||||
glConfig.vendor_string = (const char *) qglGetString (GL_VENDOR);
|
||||
glConfig.renderer_string = (const char *) qglGetString (GL_RENDERER);
|
||||
glConfig.version_string = (const char *) qglGetString (GL_VERSION);
|
||||
glConfig.extensions_string = (const char *) qglGetString (GL_EXTENSIONS);
|
||||
|
||||
if (!glConfig.vendor_string || !glConfig.renderer_string || !glConfig.version_string || !glConfig.extensions_string)
|
||||
{
|
||||
Com_Error( ERR_FATAL, "GLimp_Init() - Invalid GL Driver\n" );
|
||||
}
|
||||
|
||||
// OpenGL driver constants
|
||||
qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &glConfig.maxTextureSize );
|
||||
// stubbed or broken drivers may have reported 0...
|
||||
if ( glConfig.maxTextureSize <= 0 )
|
||||
{
|
||||
glConfig.maxTextureSize = 0;
|
||||
}
|
||||
|
||||
GLW_InitExtensions();
|
||||
WG_CheckHardwareGamma();
|
||||
}
|
||||
|
||||
/*
|
||||
** GLimp_Shutdown
|
||||
**
|
||||
** This routine does all OS specific shutdown procedures for the OpenGL
|
||||
** subsystem.
|
||||
*/
|
||||
void GLimp_Shutdown( void )
|
||||
{
|
||||
// FIXME: Brian, we need better fallbacks from partially initialized failures
|
||||
Com_Printf ("Shutting down OpenGL subsystem\n" );
|
||||
|
||||
// Set the gamma back to normal
|
||||
// GLimp_SetGamma(1.f);
|
||||
|
||||
// kill input system (tied to window)
|
||||
IN_Shutdown();
|
||||
|
||||
// shutdown QGL subsystem
|
||||
GLW_Shutdown();
|
||||
QGL_Shutdown();
|
||||
|
||||
memset( &glConfig, 0, sizeof( glConfig ) );
|
||||
memset( &glState, 0, sizeof( glState ) );
|
||||
}
|
||||
|
||||
/*
|
||||
** GLimp_LogComment
|
||||
*/
|
||||
void GLimp_LogComment( char *comment )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========================================================
|
||||
|
||||
SMP acceleration
|
||||
|
||||
===========================================================
|
||||
*/
|
||||
|
||||
qboolean GLimp_SpawnRenderThread( void (*function)( void ) ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
void *GLimp_RendererSleep( void ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void GLimp_FrontEndSleep( void ) {
|
||||
}
|
||||
|
||||
|
||||
void GLimp_WakeRenderer( void *data ) {
|
||||
}
|
||||
632
codemp/win32/win_highdynamicrange.cpp
Normal file
632
codemp/win32/win_highdynamicrange.cpp
Normal file
@@ -0,0 +1,632 @@
|
||||
//
|
||||
//
|
||||
// Win_HighDynamicRange.cpp
|
||||
//
|
||||
// High dynamic range effect
|
||||
//
|
||||
//
|
||||
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
#include "../renderer/tr_local.h"
|
||||
#include "glw_win_dx8.h"
|
||||
#include "win_local.h"
|
||||
#include "win_highdynamicrange.h"
|
||||
|
||||
#include <xgmath.h>
|
||||
#include <xgraphics.h>
|
||||
|
||||
|
||||
VVHighDynamicRange HDREffect;
|
||||
|
||||
VVHighDynamicRange::VVHighDynamicRange()
|
||||
{
|
||||
m_bInitialized = false;
|
||||
|
||||
m_dwHotBlurPixelShader = 0;
|
||||
m_dwExtractHotPixelShader = 0;
|
||||
}
|
||||
|
||||
|
||||
void VVHighDynamicRange::Initialize()
|
||||
{
|
||||
// Create pixel shader
|
||||
if(!(CreatePixelShader("D:\\base\\media\\hotblur.xpu", &m_dwHotBlurPixelShader)))
|
||||
return;
|
||||
|
||||
if(!(CreatePixelShader("D:\\base\\media\\extracthot.xpu", &m_dwExtractHotPixelShader)))
|
||||
return;
|
||||
|
||||
// Get size of render target
|
||||
LPDIRECT3DSURFACE8 pRenderTarget;
|
||||
glw_state->device->GetRenderTarget( &pRenderTarget );
|
||||
D3DSURFACE_DESC descRenderTarget;
|
||||
pRenderTarget->GetDesc( &descRenderTarget );
|
||||
UINT Width = descRenderTarget.Width;
|
||||
UINT Height = descRenderTarget.Height;
|
||||
D3DFORMAT Format = descRenderTarget.Format;
|
||||
pRenderTarget->Release();
|
||||
|
||||
// Create extract hot text
|
||||
glw_state->device->CreateTexture( Width >> 1, Height >> 1, 1,
|
||||
D3DUSAGE_RENDERTARGET, Format,
|
||||
0, &m_rpHotImage);
|
||||
|
||||
// Make the size a factor of 2 smaller on each axis
|
||||
glw_state->device->CreateTexture( Width >> 1, Height >> 2, 1,
|
||||
D3DUSAGE_RENDERTARGET, Format,
|
||||
0, &m_rpBlur[0]);
|
||||
|
||||
glw_state->device->CreateTexture( Width >> 2, Height >> 2, 1,
|
||||
D3DUSAGE_RENDERTARGET, Format,
|
||||
0, &m_rpBlur[1]);
|
||||
|
||||
// Set bloom scale
|
||||
m_fBloomScale = 1.00f;
|
||||
|
||||
m_bInitialized = true;
|
||||
}
|
||||
|
||||
|
||||
void VVHighDynamicRange::Render()
|
||||
{
|
||||
if(!m_bInitialized)
|
||||
return;
|
||||
|
||||
DWORD lighting, fog, srcblend, destblend, alphablend, zwrite, zenable;
|
||||
|
||||
glw_state->device->GetRenderState( D3DRS_LIGHTING, &lighting );
|
||||
glw_state->device->GetRenderState( D3DRS_FOGENABLE, &fog );
|
||||
glw_state->device->GetRenderState( D3DRS_SRCBLEND, &srcblend );
|
||||
glw_state->device->GetRenderState( D3DRS_DESTBLEND, &destblend );
|
||||
glw_state->device->GetRenderState( D3DRS_ALPHABLENDENABLE, &alphablend );
|
||||
glw_state->device->GetRenderState( D3DRS_ZWRITEENABLE, &zwrite );
|
||||
glw_state->device->GetRenderState( D3DRS_ZENABLE, &zenable );
|
||||
|
||||
HotBlur(); // Blur the hot values in the backbuffer
|
||||
DrawHotBlur(); // Draw blurred hot values, add to scene
|
||||
|
||||
glw_state->device->SetRenderState( D3DRS_LIGHTING, lighting );
|
||||
glw_state->device->SetRenderState( D3DRS_FOGENABLE, fog );
|
||||
glw_state->device->SetRenderState( D3DRS_SRCBLEND, srcblend );
|
||||
glw_state->device->SetRenderState( D3DRS_DESTBLEND, destblend );
|
||||
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, alphablend );
|
||||
glw_state->device->SetRenderState( D3DRS_ZWRITEENABLE, zwrite );
|
||||
glw_state->device->SetRenderState( D3DRS_ZENABLE, zenable );
|
||||
}
|
||||
|
||||
|
||||
void VVHighDynamicRange::DrawHotBlur()
|
||||
{
|
||||
if( !m_pBlur )
|
||||
return;
|
||||
|
||||
LPDIRECT3DTEXTURE8 pTexture = m_pBlur;
|
||||
|
||||
// Get size of backbuffer
|
||||
LPDIRECT3DSURFACE8 pRenderTarget;
|
||||
glw_state->device->GetRenderTarget( &pRenderTarget );
|
||||
D3DSURFACE_DESC descRenderTarget;
|
||||
pRenderTarget->GetDesc( &descRenderTarget );
|
||||
UINT Width = descRenderTarget.Width;
|
||||
UINT Height = descRenderTarget.Height;
|
||||
pRenderTarget->Release();
|
||||
|
||||
// Texture coordinates in linear format textures go from 0 to n-1 rather
|
||||
// than the 0 to 1 that is used for swizzled textures.
|
||||
D3DSURFACE_DESC desc;
|
||||
pTexture->GetLevelDesc( 0, &desc );
|
||||
struct BACKGROUNDVERTEX { D3DXVECTOR4 p; FLOAT tu, tv; } v[4];
|
||||
v[0].p = D3DXVECTOR4( -0.5f, -0.5f, 1.0f, 1.0f );
|
||||
v[0].tu = 0.0f; v[0].tv = 0.0f;
|
||||
v[1].p = D3DXVECTOR4( Width - 0.5f, -0.5f, 1.0f, 1.0f );
|
||||
v[1].tu = (float)desc.Width; v[1].tv = 0.0f;
|
||||
v[2].p = D3DXVECTOR4( -0.5f, Height - 0.5f, 1.0f, 1.0f );
|
||||
v[2].tu = 0.0f; v[2].tv = (float)desc.Height;
|
||||
v[3].p = D3DXVECTOR4( Width - 0.5f, Height - 0.5f, 1.0f, 1.0f );
|
||||
v[3].tu = (float)desc.Width; v[3].tv = (float)desc.Height;
|
||||
|
||||
// Set states
|
||||
glw_state->device->SetPixelShader( 0 );
|
||||
glw_state->device->SetTexture( 0, pTexture );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE2X );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_MAXMIPLEVEL, 0 );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE );
|
||||
glw_state->device->SetRenderState( D3DRS_ZENABLE, FALSE );
|
||||
glw_state->device->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
|
||||
|
||||
XGCOLOR Blend(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Blend*= r_hdrbloom->value;//m_fBloomScale; // adjust blend amount
|
||||
glw_state->device->SetRenderState( D3DRS_TEXTUREFACTOR, Blend );
|
||||
|
||||
// add if requested
|
||||
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, true );
|
||||
glw_state->device->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );
|
||||
glw_state->device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
|
||||
glw_state->device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
|
||||
|
||||
// Render the screen-aligned quadrilateral
|
||||
glw_state->device->SetVertexShader( D3DFVF_XYZRHW|D3DFVF_TEX1 );
|
||||
glw_state->device->DrawVerticesUP( D3DPT_QUADSTRIP, 4, v, sizeof(BACKGROUNDVERTEX) );
|
||||
|
||||
glw_state->device->SetRenderState( D3DRS_ZENABLE, TRUE );
|
||||
}
|
||||
|
||||
|
||||
void VVHighDynamicRange::FilterCopy( LPDIRECT3DTEXTURE8 pTextureDst,
|
||||
LPDIRECT3DTEXTURE8 pTextureSrc,
|
||||
UINT nSample, FilterSample rSample[],
|
||||
UINT nSuperSampleX, UINT nSuperSampleY,
|
||||
bool bCrap,
|
||||
RECT* pRectDst, RECT* pRectSrc
|
||||
)
|
||||
{
|
||||
// Texture space pixel center == screen space pixel center
|
||||
glw_state->device->SetScreenSpaceOffset( -0.5f, -0.5f );
|
||||
|
||||
// Save current render target and depth buffer
|
||||
LPDIRECT3DSURFACE8 pRenderTarget, pZBuffer;
|
||||
glw_state->device->GetRenderTarget( &pRenderTarget );
|
||||
glw_state->device->GetDepthStencilSurface( &pZBuffer );
|
||||
|
||||
// Set destination as render target
|
||||
LPDIRECT3DSURFACE8 pSurface = NULL;
|
||||
pTextureDst->GetSurfaceLevel( 0, &pSurface );
|
||||
glw_state->device->SetRenderTarget( pSurface, NULL ); // no depth-buffering
|
||||
pSurface->Release();
|
||||
|
||||
// Get descriptions of source and destination
|
||||
D3DSURFACE_DESC descSrc;
|
||||
pTextureSrc->GetLevelDesc( 0, &descSrc );
|
||||
D3DSURFACE_DESC descDst;
|
||||
pTextureDst->GetLevelDesc( 0, &descDst );
|
||||
|
||||
// Setup rectangles if not specified on input
|
||||
RECT rectSrc = { 0, 0, descSrc.Width, descSrc.Height };
|
||||
if( pRectSrc == NULL ) pRectSrc = &rectSrc;
|
||||
RECT rectDst = { 0, 0, descDst.Width, descDst.Height };
|
||||
if( pRectDst == NULL )
|
||||
{
|
||||
// If the destination rectangle is not specified,
|
||||
// we change it to match the source rectangle
|
||||
rectDst.right = (pRectSrc->right - pRectSrc->left) / nSuperSampleX;
|
||||
rectDst.bottom = (pRectSrc->bottom - pRectSrc->top) / nSuperSampleY;
|
||||
pRectDst = &rectDst;
|
||||
}
|
||||
assert( (pRectDst->right - pRectDst->left) ==
|
||||
(pRectSrc->right - pRectDst->left) / (INT)nSuperSampleX );
|
||||
assert( (pRectDst->bottom - pRectDst->top) ==
|
||||
(pRectSrc->bottom - pRectDst->top) / (INT)nSuperSampleY );
|
||||
|
||||
//Set render state for filtering
|
||||
glw_state->device->SetRenderState( D3DRS_LIGHTING, FALSE );
|
||||
glw_state->device->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
|
||||
glw_state->device->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
|
||||
glw_state->device->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
|
||||
glw_state->device->SetRenderState( D3DRS_STENCILENABLE, FALSE );
|
||||
glw_state->device->SetRenderState( D3DRS_FOGENABLE, FALSE );
|
||||
// On first rendering, copy new value over current render target contents
|
||||
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
|
||||
// Setup subsequent renderings to add to previous value
|
||||
glw_state->device->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );
|
||||
glw_state->device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
|
||||
glw_state->device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
|
||||
|
||||
// Set texture state
|
||||
for( UINT xx = 0; xx < 4; xx++)
|
||||
{
|
||||
// Use our source texture for all four stages
|
||||
glw_state->device->SetTexture( xx, pTextureSrc);
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_COLOROP, D3DTOP_DISABLE );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
|
||||
|
||||
// Pass texture coords without transformation
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
||||
|
||||
// Each texture has different tex coords
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_TEXCOORDINDEX, xx );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_MAXMIPLEVEL, 0 );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_MIPFILTER, D3DTEXF_NONE );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_COLORKEYOP, D3DTCOLORKEYOP_DISABLE );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_COLORSIGN, 0 );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_ALPHAKILL, D3DTALPHAKILL_DISABLE );
|
||||
}
|
||||
|
||||
// Use hot blur pixel shader
|
||||
if(bCrap)
|
||||
glw_state->device->SetPixelShader( m_dwExtractHotPixelShader );
|
||||
else
|
||||
glw_state->device->SetPixelShader( m_dwHotBlurPixelShader );
|
||||
|
||||
// For screen-space texture-mapped quadrilateral
|
||||
glw_state->device->SetVertexShader( D3DFVF_XYZRHW|D3DFVF_TEX4 );
|
||||
|
||||
// Prepare quadrilateral vertices
|
||||
float x0 = (float)pRectDst->left;
|
||||
float y0 = (float)pRectDst->top;
|
||||
float x1 = (float)pRectDst->right;
|
||||
float y1 = (float)pRectDst->bottom;
|
||||
struct Quad
|
||||
{
|
||||
float x, y, z, w1;
|
||||
struct uv
|
||||
{
|
||||
float u, v;
|
||||
}
|
||||
tex[4]; // each texture has different offset
|
||||
}
|
||||
aQuad[4] =
|
||||
{ // X Y Z 1/W u0 v0 u1 v1 u2 v2 u3 v3
|
||||
{x0, y0, 1.0f, 1.0f, }, // texture coords are set below
|
||||
{x1, y0, 1.0f, 1.0f, },
|
||||
{x0, y1, 1.0f, 1.0f, },
|
||||
{x1, y1, 1.0f, 1.0f, }
|
||||
};
|
||||
|
||||
// Set rendering to just the destination rect
|
||||
glw_state->device->SetScissors( 1, FALSE, (D3DRECT *)pRectDst );
|
||||
|
||||
// Draw a quad for each block of 4 filter coefficients
|
||||
float fOffsetScaleU = (float)nSuperSampleX; // offset for supersample
|
||||
float fOffsetScaleV = (float)nSuperSampleY;
|
||||
float u0 = (float)pRectSrc->left;
|
||||
float v0 = (float)pRectSrc->top;
|
||||
float u1 = (float)pRectSrc->right;
|
||||
float v1 = (float)pRectSrc->bottom;
|
||||
|
||||
|
||||
if( XGIsSwizzledFormat( descSrc.Format ) )
|
||||
{
|
||||
float fWidthScale = 1.f / (float)descSrc.Width;
|
||||
float fHeightScale = 1.f / (float)descSrc.Height;
|
||||
fOffsetScaleU *= fWidthScale;
|
||||
fOffsetScaleV *= fHeightScale;
|
||||
u0 *= fWidthScale;
|
||||
v0 *= fHeightScale;
|
||||
u1 *= fWidthScale;
|
||||
v1 *= fHeightScale;
|
||||
}
|
||||
|
||||
xx = 0; // current texture stage
|
||||
D3DCOLOR rColor[4];
|
||||
DWORD rPSInput[4];
|
||||
for( UINT iSample = 0; iSample < nSample; iSample++ )
|
||||
{
|
||||
// Set filter coefficients
|
||||
float fValue = rSample[iSample].fValue;
|
||||
if( fValue < 0.f )
|
||||
{
|
||||
rColor[xx] = D3DXCOLOR( -fValue, -fValue, -fValue, -fValue );
|
||||
rPSInput[xx] = PS_INPUTMAPPING_SIGNED_NEGATE |
|
||||
((xx % 2) ? PS_REGISTER_C1 : PS_REGISTER_C0);
|
||||
}
|
||||
else
|
||||
{
|
||||
rColor[xx] = D3DXCOLOR( fValue, fValue, fValue, fValue );
|
||||
rPSInput[xx] = PS_INPUTMAPPING_SIGNED_IDENTITY |
|
||||
((xx % 2) ? PS_REGISTER_C1 : PS_REGISTER_C0);
|
||||
}
|
||||
|
||||
// Align supersamples with center of destination pixels
|
||||
float fOffsetX = rSample[iSample].fOffsetX;// * fOffsetScaleU;
|
||||
float fOffsetY = rSample[iSample].fOffsetY;// * fOffsetScaleV;
|
||||
aQuad[0].tex[xx].u = u0 + fOffsetX;
|
||||
aQuad[0].tex[xx].v = v0 + fOffsetY;
|
||||
aQuad[1].tex[xx].u = u1 + fOffsetX;
|
||||
aQuad[1].tex[xx].v = v0 + fOffsetY;
|
||||
aQuad[2].tex[xx].u = u0 + fOffsetX;
|
||||
aQuad[2].tex[xx].v = v1 + fOffsetY;
|
||||
aQuad[3].tex[xx].u = u1 + fOffsetX;
|
||||
aQuad[3].tex[xx].v = v1 + fOffsetY;
|
||||
|
||||
xx++; // Go to next stage
|
||||
if( xx == 4 || iSample == nSample - 1 ) // max texture stages or last sample
|
||||
{
|
||||
// Zero out unused texture stage coefficients
|
||||
// (Only for last filter sample, when number of samples is not divisible by 4)
|
||||
for( ; xx < 4; xx++)
|
||||
{
|
||||
glw_state->device->SetTexture( xx, NULL );
|
||||
rColor[xx] = 0;
|
||||
rPSInput[xx] = PS_INPUTMAPPING_UNSIGNED_IDENTITY | PS_REGISTER_ZERO;
|
||||
}
|
||||
|
||||
// Set coefficients
|
||||
glw_state->device->SetRenderState( D3DRS_PSCONSTANT0_0, rColor[0] );
|
||||
glw_state->device->SetRenderState( D3DRS_PSCONSTANT1_0, rColor[1] );
|
||||
glw_state->device->SetRenderState( D3DRS_PSCONSTANT0_1, rColor[2] );
|
||||
glw_state->device->SetRenderState( D3DRS_PSCONSTANT1_1, rColor[3] );
|
||||
|
||||
if(bCrap)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Remap coefficients to proper sign
|
||||
glw_state->device->SetRenderState(
|
||||
D3DRS_PSRGBINPUTS0,
|
||||
PS_COMBINERINPUTS( rPSInput[0] | PS_CHANNEL_RGB,
|
||||
PS_REGISTER_T0 | PS_CHANNEL_RGB |
|
||||
PS_INPUTMAPPING_SIGNED_IDENTITY,
|
||||
rPSInput[1] | PS_CHANNEL_RGB,
|
||||
PS_REGISTER_T1 | PS_CHANNEL_RGB |
|
||||
PS_INPUTMAPPING_SIGNED_IDENTITY ) );
|
||||
glw_state->device->SetRenderState(
|
||||
D3DRS_PSALPHAINPUTS0,
|
||||
PS_COMBINERINPUTS( rPSInput[0] | PS_CHANNEL_ALPHA,
|
||||
PS_REGISTER_T0 | PS_CHANNEL_ALPHA |
|
||||
PS_INPUTMAPPING_SIGNED_IDENTITY,
|
||||
rPSInput[1] | PS_CHANNEL_ALPHA,
|
||||
PS_REGISTER_T1 | PS_CHANNEL_ALPHA |
|
||||
PS_INPUTMAPPING_SIGNED_IDENTITY ) );
|
||||
glw_state->device->SetRenderState(
|
||||
D3DRS_PSRGBINPUTS1,
|
||||
PS_COMBINERINPUTS( rPSInput[2] | PS_CHANNEL_RGB,
|
||||
PS_REGISTER_T2 | PS_CHANNEL_RGB |
|
||||
PS_INPUTMAPPING_SIGNED_IDENTITY,
|
||||
rPSInput[3] | PS_CHANNEL_RGB,
|
||||
PS_REGISTER_T3 | PS_CHANNEL_RGB |
|
||||
PS_INPUTMAPPING_SIGNED_IDENTITY ) );
|
||||
glw_state->device->SetRenderState(
|
||||
D3DRS_PSALPHAINPUTS1,
|
||||
PS_COMBINERINPUTS( rPSInput[2] | PS_CHANNEL_ALPHA,
|
||||
PS_REGISTER_T2 | PS_CHANNEL_ALPHA |
|
||||
PS_INPUTMAPPING_SIGNED_IDENTITY,
|
||||
rPSInput[3] | PS_CHANNEL_ALPHA,
|
||||
PS_REGISTER_T3 | PS_CHANNEL_ALPHA |
|
||||
PS_INPUTMAPPING_SIGNED_IDENTITY ) );
|
||||
}
|
||||
|
||||
// Draw the quad to filter the coefficients so far
|
||||
// One quad blends 4 textures
|
||||
glw_state->device->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, aQuad, sizeof(Quad) );
|
||||
|
||||
// On subsequent renderings, add to what's in the render target
|
||||
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
|
||||
xx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear texture stages
|
||||
for( xx=0; xx<4; xx++ )
|
||||
{
|
||||
glw_state->device->SetTexture( xx, NULL );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_COLOROP, D3DTOP_DISABLE );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
|
||||
glw_state->device->SetTextureStageState( xx, D3DTSS_MIPMAPLODBIAS, 0 );
|
||||
}
|
||||
|
||||
// Restore render target and zbuffer
|
||||
glw_state->device->SetRenderTarget( pRenderTarget, pZBuffer );
|
||||
|
||||
if( pRenderTarget )
|
||||
pRenderTarget->Release();
|
||||
|
||||
if( pZBuffer )
|
||||
pZBuffer->Release();
|
||||
|
||||
glw_state->device->SetScreenSpaceOffset( 0.0f, 0.0f );
|
||||
}
|
||||
|
||||
|
||||
void VVHighDynamicRange::ExtractHot( LPDIRECT3DTEXTURE8 pTextureDst,
|
||||
LPDIRECT3DTEXTURE8 pTextureSrc,
|
||||
UINT nSuperSampleX, UINT nSuperSampleY,
|
||||
RECT* pRectDst, RECT* pRectSrc )
|
||||
{
|
||||
// Texture space pixel center == screen space pixel center
|
||||
glw_state->device->SetScreenSpaceOffset( -0.5f, -0.5f );
|
||||
|
||||
// Save current render target and depth buffer
|
||||
LPDIRECT3DSURFACE8 pRenderTarget, pZBuffer;
|
||||
glw_state->device->GetRenderTarget( &pRenderTarget );
|
||||
glw_state->device->GetDepthStencilSurface( &pZBuffer );
|
||||
|
||||
// Set destination as render target
|
||||
LPDIRECT3DSURFACE8 pSurface = NULL;
|
||||
pTextureDst->GetSurfaceLevel( 0, &pSurface );
|
||||
glw_state->device->SetRenderTarget( pSurface, NULL ); // no depth-buffering
|
||||
pSurface->Release();
|
||||
|
||||
// Get descriptions of source and destination
|
||||
D3DSURFACE_DESC descSrc;
|
||||
pTextureSrc->GetLevelDesc( 0, &descSrc );
|
||||
D3DSURFACE_DESC descDst;
|
||||
pTextureDst->GetLevelDesc( 0, &descDst );
|
||||
|
||||
// Setup rectangles if not specified on input
|
||||
RECT rectSrc = { 0, 0, descSrc.Width, descSrc.Height };
|
||||
if( pRectSrc == NULL ) pRectSrc = &rectSrc;
|
||||
RECT rectDst = { 0, 0, descDst.Width, descDst.Height };
|
||||
if( pRectDst == NULL )
|
||||
{
|
||||
// If the destination rectangle is not specified,
|
||||
// we change it to match the source rectangle
|
||||
rectDst.right = (pRectSrc->right - pRectSrc->left) / nSuperSampleX;
|
||||
rectDst.bottom = (pRectSrc->bottom - pRectSrc->top) / nSuperSampleY;
|
||||
pRectDst = &rectDst;
|
||||
}
|
||||
assert( (pRectDst->right - pRectDst->left) ==
|
||||
(pRectSrc->right - pRectDst->left) / (INT)nSuperSampleX );
|
||||
assert( (pRectDst->bottom - pRectDst->top) ==
|
||||
(pRectSrc->bottom - pRectDst->top) / (INT)nSuperSampleY );
|
||||
|
||||
//Set render state for filtering
|
||||
glw_state->device->SetRenderState( D3DRS_LIGHTING, FALSE );
|
||||
glw_state->device->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
|
||||
glw_state->device->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
|
||||
glw_state->device->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
|
||||
glw_state->device->SetRenderState( D3DRS_STENCILENABLE, FALSE );
|
||||
glw_state->device->SetRenderState( D3DRS_FOGENABLE, FALSE );
|
||||
glw_state->device->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
|
||||
glw_state->device->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );
|
||||
glw_state->device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
|
||||
glw_state->device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
|
||||
|
||||
glw_state->device->SetTexture( 0, pTextureSrc);
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DISABLE );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
|
||||
|
||||
// Pass texture coords without transformation
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
||||
|
||||
// Each texture has different tex coords
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSU,
|
||||
D3DTADDRESS_CLAMP );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSV,
|
||||
D3DTADDRESS_CLAMP );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_MAXMIPLEVEL, 0 );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_GAUSSIANCUBIC );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_GAUSSIANCUBIC );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_COLORKEYOP,
|
||||
D3DTCOLORKEYOP_DISABLE );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_COLORSIGN, 0 );
|
||||
glw_state->device->SetTextureStageState( 0, D3DTSS_ALPHAKILL,
|
||||
D3DTALPHAKILL_DISABLE );
|
||||
|
||||
// Use extract hot pixel shader
|
||||
glw_state->device->SetPixelShader( m_dwExtractHotPixelShader );
|
||||
|
||||
// For screen-space texture-mapped quadrilateral
|
||||
glw_state->device->SetVertexShader( D3DFVF_XYZRHW|D3DFVF_TEX1 );
|
||||
|
||||
// Prepare quadrilateral vertices
|
||||
float x0 = (float)pRectDst->left;
|
||||
float y0 = (float)pRectDst->top;
|
||||
float x1 = (float)pRectDst->right;
|
||||
float y1 = (float)pRectDst->bottom;
|
||||
struct Quad
|
||||
{
|
||||
float x, y, z, w1;
|
||||
struct uv
|
||||
{
|
||||
float u, v;
|
||||
}
|
||||
tex;
|
||||
}
|
||||
aQuad[4] =
|
||||
{ // X Y Z 1/W u0 v0 u1 v1 u2 v2 u3 v3
|
||||
{x0, y0, 1.0f, 1.0f, }, // texture coords are set below
|
||||
{x1, y0, 1.0f, 1.0f, },
|
||||
{x0, y1, 1.0f, 1.0f, },
|
||||
{x1, y1, 1.0f, 1.0f, }
|
||||
};
|
||||
|
||||
// Set rendering to just the destination rect
|
||||
glw_state->device->SetScissors( 1, FALSE, (D3DRECT *)pRectDst );
|
||||
|
||||
|
||||
// Draw a quad for each block of 4 filter coefficients
|
||||
float u0 = (float)pRectSrc->left;
|
||||
float v0 = (float)pRectSrc->top;
|
||||
float u1 = (float)pRectSrc->right;
|
||||
float v1 = (float)pRectSrc->bottom;
|
||||
|
||||
|
||||
if( XGIsSwizzledFormat( descSrc.Format ) )
|
||||
{
|
||||
float fWidthScale = 1.f / (float)descSrc.Width;
|
||||
float fHeightScale = 1.f / (float)descSrc.Height;
|
||||
u0 *= fWidthScale;
|
||||
v0 *= fHeightScale;
|
||||
u1 *= fWidthScale;
|
||||
v1 *= fHeightScale;
|
||||
}
|
||||
|
||||
aQuad[0].tex.u = u0;
|
||||
aQuad[0].tex.v = v0;
|
||||
aQuad[1].tex.u = u1;
|
||||
aQuad[1].tex.v = v0;
|
||||
aQuad[2].tex.u = u0;
|
||||
aQuad[2].tex.v = v1;
|
||||
aQuad[3].tex.u = u1;
|
||||
aQuad[3].tex.v = v1;
|
||||
|
||||
// Draw the quad
|
||||
glw_state->device->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP,
|
||||
2, aQuad, sizeof(Quad) );
|
||||
|
||||
glw_state->device->SetTexture( 0, NULL );
|
||||
|
||||
|
||||
// Restore render target and zbuffer
|
||||
glw_state->device->SetRenderTarget( pRenderTarget, pZBuffer );
|
||||
|
||||
if( pRenderTarget )
|
||||
pRenderTarget->Release();
|
||||
|
||||
if( pZBuffer )
|
||||
pZBuffer->Release();
|
||||
|
||||
glw_state->device->SetScreenSpaceOffset( 0.0f, 0.0f );
|
||||
}
|
||||
|
||||
|
||||
void VVHighDynamicRange::HotBlur()
|
||||
{
|
||||
// Make D3DTexture wrapper around current render target
|
||||
LPDIRECT3DSURFACE8 pRenderTarget;
|
||||
glw_state->device->GetRenderTarget( &pRenderTarget );
|
||||
D3DSURFACE_DESC descRenderTarget;
|
||||
pRenderTarget->GetDesc( &descRenderTarget );
|
||||
D3DTexture RenderTargetTexture;
|
||||
ZeroMemory( &RenderTargetTexture, sizeof(RenderTargetTexture) );
|
||||
XGSetTextureHeader( descRenderTarget.Width, descRenderTarget.Height,
|
||||
1, 0, descRenderTarget.Format, 0,
|
||||
&RenderTargetTexture, pRenderTarget->Data,
|
||||
descRenderTarget.Width * 4 );
|
||||
pRenderTarget->Release();
|
||||
|
||||
// Filters align to blurriest point in supersamples, on the pixel centers
|
||||
// This takes advantage of the bilinear filtering in the texture map lookup.
|
||||
FilterSample YFilter[] = // 1221 4-tap filter in Y
|
||||
{
|
||||
{ 2.0f/6.f, 0.0f, 1.0f },
|
||||
{ 1.0f/6.f, 0.0f, 3.0f },
|
||||
{ 2.0f/6.f, 0.0f, -1.0f },
|
||||
{ 1.0f/6.f, 0.0f, -3.0f },
|
||||
};
|
||||
FilterSample XFilter[] = // 1221 4-tap filter in X
|
||||
{
|
||||
{ 2.0f/6.f, 1.0f, 0.0f },
|
||||
{ 1.0f/6.f, 3.0f, 0.0f },
|
||||
{ 2.0f/6.f, -1.0f, 0.0f },
|
||||
{ 1.0f/6.f, -3.0f, 0.0f },
|
||||
};
|
||||
|
||||
D3DTexture *pTextureSrc;
|
||||
D3DTexture *pTextureDst;
|
||||
|
||||
pTextureDst = &RenderTargetTexture; // source is backbuffer
|
||||
|
||||
// extract "hot" portion of hte image with downsampling
|
||||
pTextureSrc = pTextureDst;
|
||||
pTextureDst = m_rpHotImage; // destination is blur texture
|
||||
ExtractHot( pTextureDst, pTextureSrc, 2, 2 );
|
||||
|
||||
// 2 passes: Vertical gaussian (1221) followed by
|
||||
// horizontal gaussian (1221), with 2x2 downsampling
|
||||
pTextureSrc = pTextureDst; // destination is next blur texture
|
||||
pTextureDst = m_rpBlur[0]; // destination is blur texture
|
||||
FilterCopy(pTextureDst, pTextureSrc, 4, YFilter, 1, 2, false);
|
||||
|
||||
pTextureSrc = pTextureDst; // source is previous blur texture
|
||||
pTextureDst = m_rpBlur[1]; // destination is next blur texture
|
||||
FilterCopy(pTextureDst, pTextureSrc, 4, XFilter, 2, 1, false);
|
||||
|
||||
m_pBlur = pTextureDst;
|
||||
}
|
||||
77
codemp/win32/win_highdynamicrange.h
Normal file
77
codemp/win32/win_highdynamicrange.h
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
//
|
||||
// Win_HighDynamicRange.h
|
||||
//
|
||||
// Declaration of high dynamic range effect class
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef _WIN_HIGHDYNAMICRANGE_H_
|
||||
#define _WIN_HIGHDYNAMICRANGE_H_
|
||||
|
||||
struct FilterSample
|
||||
{
|
||||
float fValue; // coefficient
|
||||
float fOffsetX, fOffsetY; // subpixel offsets of supersamples in
|
||||
// destination coordinates
|
||||
};
|
||||
|
||||
|
||||
class VVHighDynamicRange
|
||||
{
|
||||
// The blur filters are multipass and need temporary space.
|
||||
#define BLUR_COUNT 2
|
||||
D3DTexture *m_rpHotImage; // hot image
|
||||
D3DTexture *m_rpBlur[BLUR_COUNT]; // bluring textures of decreasing size
|
||||
D3DTexture *m_pBlur; // current blur texture, set by Blur()
|
||||
|
||||
// Light blend intensity scale factor
|
||||
float m_fBloomScale;
|
||||
|
||||
// Pixel shader handles
|
||||
DWORD m_dwHotBlurPixelShader; // blur the hot image
|
||||
DWORD m_dwExtractHotPixelShader; // extract hot image
|
||||
|
||||
bool m_bInitialized;
|
||||
|
||||
// Filtering routine that draws the source texture multiple
|
||||
// times, with sub-pixel offsets and filter coefficients.
|
||||
void FilterCopy( LPDIRECT3DTEXTURE8 pTextureDst,
|
||||
LPDIRECT3DTEXTURE8 pTextureSrc,
|
||||
UINT nSample,
|
||||
FilterSample rSample[],
|
||||
UINT nSuperSampleX,
|
||||
UINT nSuperSampleY,
|
||||
bool bCrap,
|
||||
RECT *pRectDst = NULL, // The destination texture is
|
||||
// written only within this
|
||||
// region.
|
||||
RECT *pRectSrc = NULL );// The source texture is read
|
||||
// outside of this region by
|
||||
// the halfwidth of the
|
||||
// filter.
|
||||
|
||||
// extract hot image with downsamping
|
||||
void ExtractHot( LPDIRECT3DTEXTURE8 pTextureDst,
|
||||
LPDIRECT3DTEXTURE8 pTextureSrc,
|
||||
UINT nSuperSampleX, UINT nSuperSampleY,
|
||||
RECT* pRectDst = NULL,
|
||||
RECT* pRectSrc = NULL );
|
||||
|
||||
// Blur hot texture and set m_pBlur. Calls FilterCopy with
|
||||
// different filter coefficients and offsets
|
||||
void HotBlur();
|
||||
|
||||
// Demonstrate the inputs to the full high dynamic range effect.
|
||||
void DrawHotBlur(); // draw blurred "hot" texture
|
||||
|
||||
public:
|
||||
virtual void Initialize();
|
||||
virtual void Render();
|
||||
|
||||
VVHighDynamicRange();
|
||||
};
|
||||
|
||||
extern VVHighDynamicRange HDREffect;
|
||||
|
||||
#endif
|
||||
1141
codemp/win32/win_input.cpp
Normal file
1141
codemp/win32/win_input.cpp
Normal file
File diff suppressed because it is too large
Load Diff
103
codemp/win32/win_input.h
Normal file
103
codemp/win32/win_input.h
Normal file
@@ -0,0 +1,103 @@
|
||||
#ifndef _WIN_INPUT_H_
|
||||
#define _WIN_INPUT_H_
|
||||
|
||||
#include "../client/keycodes.h"
|
||||
|
||||
bool IN_ControllersChanged(int inserted[], int removed[]);
|
||||
|
||||
#if defined (_XBOX ) || defined (_GAMECUBE)
|
||||
#define _USE_RUMBLE
|
||||
#endif
|
||||
|
||||
bool IN_AnyButtonPressed(void);
|
||||
|
||||
void IN_enableRumble( void );
|
||||
void IN_disableRumble( void );
|
||||
bool IN_usingRumble( void );
|
||||
|
||||
int IN_CreateRumbleScript(int controller, int numStates, bool deleteWhenFinished);
|
||||
void IN_DeleteRumbleScript(int whichScript);
|
||||
void IN_KillRumbleScript(int whichScript);
|
||||
void IN_ExecuteRumbleScript(int whichScript);
|
||||
|
||||
bool IN_AdvanceToNextState(int whichScript);
|
||||
|
||||
void IN_KillRumbleScripts(int controller);
|
||||
void IN_KillRumbleScripts( void );
|
||||
|
||||
#define IN_CMD_GOTO_XTIMES -5
|
||||
#define IN_CMD_GOTO -6
|
||||
|
||||
#define IN_CMD_DEC_ARG2 -7
|
||||
#define IN_CMD_INC_ARG2 -8
|
||||
#define IN_CMD_DEC_ARG1 -9
|
||||
#define IN_CMD_INC_ARG1 -10
|
||||
|
||||
#ifdef _XBOX
|
||||
#define IN_CMD_DEC_LEFT -70
|
||||
#define IN_CMD_DEC_RIGHT -71
|
||||
#define IN_CMD_INC_LEFT -72
|
||||
#define IN_CMD_INC_RIGHT -73
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (_XBOX) // ----- XBOX --------
|
||||
|
||||
int IN_AddRumbleState(int whichScript, int leftSpeed, int rightSpeed, int timeInMs);
|
||||
int IN_AddEffectFade4(int whichScript, int startLeft, int startRight, int endLeft, int endRight, int timeInMs);
|
||||
int IN_AddEffectFadeExp6(int whichScript, int startLeft, int startRight, int endLeft, int endRight, char factor, int timeInMs);
|
||||
|
||||
#elif defined (_GAMECUBE) // ---- GAME CUBE ----
|
||||
|
||||
#define IN_GCACTION_START 1
|
||||
#define IN_GCACTION_STOP 2
|
||||
#define IN_GCACTION_STOPHARD 3
|
||||
int IN_AddRumbleState(int whichScript, int action, int timeInMs, int arg = 0);
|
||||
|
||||
#endif // ------END IF-------
|
||||
|
||||
int IN_AddRumbleStateSpecial(int whichScript, int action, int arg1, int arg2);
|
||||
void IN_KillRumbleState(int whichScript, int index);
|
||||
|
||||
void IN_PauseRumbling(int controller);
|
||||
void IN_PauseRumbling( void );
|
||||
|
||||
void IN_UnPauseRumbling(int controller);
|
||||
void IN_UnPauseRumbling( void );
|
||||
|
||||
void IN_TogglePauseRumbling(int controller);
|
||||
void IN_TogglePauseRumbling( void );
|
||||
int IN_GetMainController();
|
||||
void IN_SetMainController(int id);
|
||||
|
||||
void IN_PadUnplugged(int controller);
|
||||
void IN_PadPlugged(int controller);
|
||||
|
||||
void IN_CommonJoyPress(int controller, fakeAscii_t button, bool pressed);
|
||||
void IN_CommonUpdate(void);
|
||||
|
||||
#define IN_MAX_JOYSTICKS 2
|
||||
// Stores gamepad joystick info
|
||||
struct JoystickInfo
|
||||
{
|
||||
bool valid;
|
||||
float x, y;
|
||||
};
|
||||
|
||||
// Stores gamepad id and joysick info
|
||||
struct PadInfo
|
||||
{
|
||||
JoystickInfo joyInfo[2];
|
||||
int padId;
|
||||
};
|
||||
|
||||
// Buffer for gamepad info
|
||||
extern PadInfo _padInfo;
|
||||
|
||||
bool IN_RumbleAdjust(int controller, int left, int right);
|
||||
void IN_RumbleInit (void);
|
||||
void IN_RumbleShutdown (void);
|
||||
void IN_RumbleFrame (void);
|
||||
|
||||
|
||||
#endif // END _WIN_INPUT_H_
|
||||
689
codemp/win32/win_input_console.cpp
Normal file
689
codemp/win32/win_input_console.cpp
Normal file
@@ -0,0 +1,689 @@
|
||||
// #include "../server/exe_headers.h"
|
||||
|
||||
#include "../client/client.h"
|
||||
|
||||
//JLF
|
||||
//#include "../client/client_ui.h"
|
||||
|
||||
#include "../qcommon/qcommon.h"
|
||||
#ifdef _JK2MP
|
||||
#include "../ui/keycodes.h"
|
||||
#else
|
||||
#include "../client/keycodes.h"
|
||||
#endif
|
||||
|
||||
#include "win_local.h"
|
||||
#include "win_input.h"
|
||||
|
||||
#include "../cgame/cg_local.h"
|
||||
#include "../client/cl_data.h"
|
||||
|
||||
#include "../qcommon/xb_settings.h"
|
||||
|
||||
static void HandleDebugJoystickPress(fakeAscii_t button);
|
||||
|
||||
static bool _UIRunning = false;
|
||||
|
||||
static bool IN_ControllerMustBePlugged(int controller);
|
||||
|
||||
// By default, cheatpad is turned on except in final build. Just change
|
||||
// here to modify that.
|
||||
#ifndef FINAL_BUILD
|
||||
//#define DEBUG_CONTROLLER
|
||||
#endif
|
||||
|
||||
// Controller connection globals
|
||||
signed char uiControllerNotification = -1;
|
||||
extern int unpluggedcontrol2;
|
||||
|
||||
|
||||
bool noControllersConnected = false;
|
||||
bool wasPlugged[4];
|
||||
|
||||
int mainControllerDelayedUnplug = 0;
|
||||
|
||||
|
||||
PadInfo _padInfo; // gamepad thumbstick buffer
|
||||
|
||||
|
||||
|
||||
//If the Xbox white or black button was held for less than this amount of
|
||||
//time while a selection bar was up, the user wants to use the button rather
|
||||
//than reassign it.
|
||||
#define MAX_WB_HOLD_TIME 500
|
||||
|
||||
static fakeAscii_t UIJoy2Key(fakeAscii_t button)
|
||||
{
|
||||
switch(button) {
|
||||
// D-Pad
|
||||
case A_JOY7:
|
||||
return A_CURSOR_DOWN;
|
||||
case A_JOY5:
|
||||
return A_CURSOR_UP;
|
||||
case A_JOY6:
|
||||
return A_CURSOR_RIGHT;
|
||||
case A_JOY8:
|
||||
return A_CURSOR_LEFT;
|
||||
|
||||
// A and B
|
||||
case A_JOY15:
|
||||
return A_MOUSE1;
|
||||
case A_JOY14:
|
||||
return A_ESCAPE;
|
||||
|
||||
// X and Y
|
||||
case A_JOY16:
|
||||
return A_DELETE;
|
||||
case A_JOY13:
|
||||
return A_BACKSPACE;
|
||||
|
||||
// L and R triggers
|
||||
case A_JOY11:
|
||||
return A_PAGE_UP;
|
||||
case A_JOY12:
|
||||
return A_PAGE_DOWN;
|
||||
|
||||
// Start and Back
|
||||
case A_JOY4:
|
||||
return A_MOUSE1;
|
||||
case A_JOY1:
|
||||
return A_ESCAPE;
|
||||
|
||||
// White and Black
|
||||
case A_JOY9:
|
||||
return A_HOME;
|
||||
case A_JOY10:
|
||||
return A_END;
|
||||
|
||||
// Left and Right thumbstick - do nothing in the UI
|
||||
case A_JOY2:
|
||||
return A_SPACE;
|
||||
case A_JOY3:
|
||||
return A_SPACE;
|
||||
}
|
||||
|
||||
return A_SPACE; //Invalid button.
|
||||
}
|
||||
|
||||
struct
|
||||
{
|
||||
int button;
|
||||
bool pressed;
|
||||
} uiKeyQueue[2][5] = {0};
|
||||
int uiQueueLen[2] = {0};
|
||||
int uiLastKeyUpDown[2] = {0};
|
||||
int uiLastKeyLeftRight[2] = {0};
|
||||
|
||||
void IN_UIEmptyQueue()
|
||||
{
|
||||
/// If the ui is not running then this doesn't have any effect
|
||||
if (!_UIRunning)
|
||||
{
|
||||
uiQueueLen[0] = uiQueueLen[1] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// BTO - No CM, bypass that logic.
|
||||
for (int i = 0; i < ClientManager::NumClients(); i++)
|
||||
// for (int i = 0; i < 1; ++i)
|
||||
{
|
||||
ClientManager::ActivateClient(i);
|
||||
int found = 0;
|
||||
int bCancel = 0;
|
||||
for (int j = 0; j < uiQueueLen[i]; j++)
|
||||
{
|
||||
switch (uiKeyQueue[i][j].button)
|
||||
{
|
||||
case A_CURSOR_DOWN:
|
||||
case A_CURSOR_UP:
|
||||
if ( found & 2 ) // Was a left/right key pressed already?
|
||||
bCancel = 1;
|
||||
found |= 1;
|
||||
break;
|
||||
case A_CURSOR_RIGHT:
|
||||
case A_CURSOR_LEFT:
|
||||
if ( found & 1 ) // Was an up/down key already pressed?
|
||||
bCancel = 1;
|
||||
found |= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bCancel) // was it cancelled?
|
||||
{
|
||||
for (int j = 0; j < uiQueueLen[i]; j++)
|
||||
{
|
||||
int time = Sys_Milliseconds();
|
||||
switch (uiKeyQueue[i][j].button)
|
||||
{
|
||||
case A_CURSOR_DOWN:
|
||||
case A_CURSOR_UP:
|
||||
if (uiLastKeyLeftRight[i])
|
||||
{
|
||||
if (uiLastKeyLeftRight[i] > time) // don't allow up/down till left/right has enough leway time
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
uiLastKeyUpDown[i] = time + 150; /// 250 ms sound right?
|
||||
break;
|
||||
case A_CURSOR_LEFT:
|
||||
case A_CURSOR_RIGHT:
|
||||
if (uiLastKeyUpDown[i])
|
||||
{
|
||||
if (uiLastKeyUpDown[i] > time) // don't allow up/down till left/right has enough leway time
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
uiLastKeyLeftRight[i] = time + 150; /// 250 ms sound right?
|
||||
break;
|
||||
}
|
||||
Sys_QueEvent(0, SE_KEY, uiKeyQueue[i][j].button, uiKeyQueue[i][j].pressed, 0, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the queue
|
||||
uiQueueLen[0] = uiQueueLen[1] = 0;
|
||||
}
|
||||
extern int uiClientNum;
|
||||
extern int uiclientInputClosed;
|
||||
extern qboolean uiControllerMenu;
|
||||
extern vmCvar_t ControllerOutNum;
|
||||
|
||||
// extern void G_DemoKeypress();
|
||||
// extern void CG_SkipCredits(void);
|
||||
void IN_CommonJoyPress(int controller, fakeAscii_t button, bool pressed)
|
||||
{
|
||||
//int clientsClosedBitField;
|
||||
int activeClient;
|
||||
// Check for special cases for map hack
|
||||
#ifndef FINAL_BUILD
|
||||
if (Cvar_VariableIntegerValue("cl_maphack"))
|
||||
{
|
||||
if (_UIRunning && button == A_JOY11 && pressed)
|
||||
{
|
||||
// Left trigger -> F1
|
||||
Sys_QueEvent( 0, SE_KEY, A_F1, pressed, 0, NULL );
|
||||
return;
|
||||
}
|
||||
else if (_UIRunning && button == A_JOY12 && pressed)
|
||||
{
|
||||
// Right trigger -> F2
|
||||
Sys_QueEvent( 0, SE_KEY, A_F2, pressed, 0, NULL );
|
||||
return;
|
||||
}
|
||||
else if (_UIRunning && button == A_JOY4 && pressed)
|
||||
{
|
||||
// Start button -> F3
|
||||
// IN_SetMainController(controller);
|
||||
Sys_QueEvent( 0, SE_KEY, A_F3, pressed, 0, NULL );
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Don't allow any input to pass through if an important controller is
|
||||
// disconnected
|
||||
int controllerout = ControllerOutNum.integer;
|
||||
if(controllerout != -1)
|
||||
{
|
||||
if( (controllerout == controller) && (button == A_JOY4) )
|
||||
Sys_QueEvent( 0, SE_KEY, _UIRunning ? UIJoy2Key(button) : button, pressed, 0, NULL );
|
||||
return;
|
||||
}
|
||||
|
||||
//JLF
|
||||
if (_UIRunning && cls.state != CA_ACTIVE && pressed )
|
||||
{
|
||||
int clientnum = ClientManager::ActiveClientNum();
|
||||
int client1controller;
|
||||
if ( ClientManager::splitScreenMode == qtrue)
|
||||
{
|
||||
int clientnum = ClientManager::ActiveClientNum();
|
||||
ClientManager::ActivateClient(0);
|
||||
client1controller = ClientManager::ActiveClient().controller;
|
||||
if ( controller != client1controller)
|
||||
{
|
||||
ClientManager::ActivateClient(1);
|
||||
ClientManager::SetActiveController(controller);
|
||||
}
|
||||
|
||||
ClientManager::SetActiveController(controller);
|
||||
|
||||
ClientManager::ActivateClient(clientnum);
|
||||
}
|
||||
}
|
||||
|
||||
// clientsClosedBitField = Cvar_Get("clientInputClosed", "0" , 0)->integer;
|
||||
|
||||
activeClient = ClientManager::ActiveClientNum();
|
||||
ClientManager::ActivateClient(0);
|
||||
|
||||
if ((uiclientInputClosed & 0x1) && controller == ClientManager::ActiveController()&& UIJoy2Key(button) !=A_ESCAPE)
|
||||
{
|
||||
ClientManager::ActivateClient(activeClient);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ClientManager::splitScreenMode == qtrue)
|
||||
{
|
||||
ClientManager::ActivateClient(1);
|
||||
if ((uiclientInputClosed & 0x02) && controller == ClientManager::ActiveController())
|
||||
{
|
||||
ClientManager::ActivateClient(activeClient);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (controller != ClientManager::ActiveController())
|
||||
{
|
||||
ClientManager::ActivateClient(activeClient);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
ClientManager::ActivateClient(activeClient);
|
||||
|
||||
if (!uiControllerMenu)
|
||||
{
|
||||
if (_UIRunning && cls.state == CA_ACTIVE )
|
||||
{ if (ClientManager::ActiveClientNum()!= uiClientNum)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (ClientManager::ActiveController() != controller)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//END JLF
|
||||
|
||||
#ifdef _XBOX
|
||||
if(ClientManager::splitScreenMode == qtrue)
|
||||
{
|
||||
// Always map start button to ESCAPE
|
||||
// if (!_UIRunning && controller != ClientManager::Controller(0) && controller != ClientManager::Controller(1))
|
||||
if (!_UIRunning && controller != ClientManager::ActiveController())
|
||||
return;
|
||||
|
||||
if (!_UIRunning && button == A_JOY4 && cls.state != CA_CINEMATIC)
|
||||
Sys_QueEvent( 0, SE_KEY, A_ESCAPE, pressed, 0, NULL );
|
||||
|
||||
Sys_QueEvent( 0, SE_KEY, _UIRunning ? UIJoy2Key(button) : button, pressed, 0, NULL );
|
||||
}
|
||||
else
|
||||
#endif // _XBOX
|
||||
|
||||
|
||||
if(IN_GetMainController() == controller || _UIRunning)
|
||||
// if(ClientManager::ActiveController() == controller || _UIRunning)
|
||||
|
||||
{
|
||||
// Always map start button to ESCAPE
|
||||
if (!_UIRunning && button == A_JOY4 && cls.state != CA_CINEMATIC)
|
||||
Sys_QueEvent( 0, SE_KEY, A_ESCAPE, pressed, 0, NULL );
|
||||
|
||||
#ifdef DEBUG_CONTROLLER
|
||||
if (controller != 3)
|
||||
#endif
|
||||
Sys_QueEvent( 0, SE_KEY, _UIRunning ? UIJoy2Key(button) : button, pressed, 0, NULL );
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CONTROLLER
|
||||
if (controller == 3 && pressed)
|
||||
{
|
||||
HandleDebugJoystickPress(button);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
qboolean g_noCheckAxis = qfalse;
|
||||
|
||||
/**********
|
||||
IN_CommonUpdate
|
||||
Updates thumbstick events based on _padInfo and ui_thumbStickMode
|
||||
**********/
|
||||
void IN_CommonUpdate()
|
||||
{
|
||||
extern int Key_GetCatcher( void );
|
||||
_UIRunning = Key_GetCatcher() == KEYCATCH_UI;
|
||||
|
||||
// Even in the UI, only the main controller should be able to scroll:
|
||||
if( _UIRunning && _padInfo.padId == IN_GetMainController() )
|
||||
{
|
||||
Sys_QueEvent( 0,
|
||||
SE_MOUSE,
|
||||
(_padInfo.joyInfo[0].x + _padInfo.joyInfo[1].x) * 4.0f,
|
||||
(_padInfo.joyInfo[0].y + _padInfo.joyInfo[1].y) * -4.0f,
|
||||
0,
|
||||
NULL );
|
||||
}
|
||||
// Splitscreen mode has to have other controllers work
|
||||
else if(_padInfo.padId == IN_GetMainController() || ClientManager::splitScreenMode == qtrue)
|
||||
{
|
||||
// Find out how to configure the thumbsticks
|
||||
//int thumbStickMode = Cvar_Get("ui_thumbStickMode", "0" , 0)->integer;
|
||||
//int thumbStickMode = ClientManager::ActiveClient().cg_thumbsticks;
|
||||
int thumbStickMode = Settings.thumbstickMode[ClientManager::ActiveClientNum()];
|
||||
|
||||
switch(thumbStickMode)
|
||||
{
|
||||
case 0:
|
||||
// Configure left thumbstick to move forward/back & strafe left/right
|
||||
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_SIDE, _padInfo.joyInfo[0].x * 127.0f, 0, NULL );
|
||||
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_FORWARD, _padInfo.joyInfo[0].y * 127.0f, 0, NULL );
|
||||
|
||||
// Configure right thumbstick for freelook
|
||||
Sys_QueEvent( 0, SE_MOUSE, _padInfo.joyInfo[1].x * 48.0f, _padInfo.joyInfo[1].y * 48.0f, 0, NULL );
|
||||
break;
|
||||
case 1:
|
||||
// Configure left thumbstick for freelook
|
||||
Sys_QueEvent( 0, SE_MOUSE, _padInfo.joyInfo[0].x * 48.0f, _padInfo.joyInfo[0].y * 48.0f, 0, NULL );
|
||||
|
||||
// Configure right thumbstick to move forward/back & strafe left/right
|
||||
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_SIDE, _padInfo.joyInfo[1].x * 127.0f, 0, NULL );
|
||||
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_FORWARD, _padInfo.joyInfo[1].y * 127.0f, 0, NULL );
|
||||
break;
|
||||
case 2:
|
||||
// Configure left thumbstick to move forward/back & turn left/right
|
||||
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_FORWARD, _padInfo.joyInfo[0].y * 127.0f, 0, NULL );
|
||||
Sys_QueEvent( 0, SE_MOUSE, _padInfo.joyInfo[0].x * 48.0f, 0.0f, 0, NULL );
|
||||
|
||||
// Configure right thumbstick to look up/down & strafe left/right
|
||||
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_SIDE, _padInfo.joyInfo[1].x * 127.f, 0, NULL );
|
||||
Sys_QueEvent( 0, SE_MOUSE, 0.0f, _padInfo.joyInfo[1].y * 48.0f, 0, NULL );
|
||||
break;
|
||||
case 3:
|
||||
// Configure left thumbstick to look up/down & strafe left/right
|
||||
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_SIDE, _padInfo.joyInfo[0].x * 127.f, 0, NULL );
|
||||
Sys_QueEvent( 0, SE_MOUSE, 0.0f, _padInfo.joyInfo[0].y * 48.0f, 0, NULL );
|
||||
|
||||
// Configure right thumbstick to move forward/back & turn left/right
|
||||
Sys_QueEvent( 0, SE_JOYSTICK_AXIS, AXIS_FORWARD, _padInfo.joyInfo[1].y * 127.0f, 0, NULL );
|
||||
Sys_QueEvent( 0, SE_MOUSE, _padInfo.joyInfo[1].x * 48.0f, 0.0f, 0, NULL );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void startsetMainController(int controller)
|
||||
{
|
||||
IN_SetMainController(controller);
|
||||
if ( !wasPlugged[controller])
|
||||
{
|
||||
mainControllerDelayedUnplug = 1 << controller;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern void UI_SetActiveMenu( const char* menuname,const char *menuID );
|
||||
/*********
|
||||
IN_DisplayControllerUnplugged
|
||||
*********/
|
||||
void IN_DisplayControllerUnplugged(int controller)
|
||||
{
|
||||
|
||||
int activeclient = ClientManager::ActiveClientNum();
|
||||
|
||||
if ( !( cls.keyCatchers & KEYCATCH_UI ) )
|
||||
{
|
||||
if ( cls.state == CA_ACTIVE )
|
||||
{
|
||||
|
||||
Cvar_SetValue("ControllerOutNum", controller);
|
||||
uiControllerNotification = controller;
|
||||
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_NOCONTROLLERINGAME);
|
||||
|
||||
}
|
||||
else //picks up controller out while quiting
|
||||
{
|
||||
if (controller == IN_GetMainController())
|
||||
{
|
||||
mainControllerDelayedUnplug = 1 << controller;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // UI
|
||||
{
|
||||
{
|
||||
if (ClientManager::splitScreenMode)
|
||||
{
|
||||
Cvar_SetValue("ControllerOutNum", controller);
|
||||
uiControllerNotification = controller;
|
||||
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_NOCONTROLLERINGAME);
|
||||
}
|
||||
else if (controller == IN_GetMainController())
|
||||
{
|
||||
Cvar_SetValue("ControllerOutNum", controller);
|
||||
uiControllerNotification = controller;
|
||||
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_NOCONTROLLER);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// END JLF
|
||||
}
|
||||
|
||||
void CheckForSecondPrompt( void )
|
||||
{
|
||||
if(unpluggedcontrol2 != -1 && ControllerOutNum.integer == -1)
|
||||
IN_DisplayControllerUnplugged(unpluggedcontrol2);
|
||||
}
|
||||
|
||||
|
||||
qboolean CurrentStateIsInteractive()
|
||||
{
|
||||
if (cls.state == CA_UNINITIALIZED ||
|
||||
cls.state ==CA_CONNECTING||
|
||||
cls.state ==CA_CONNECTED||
|
||||
cls.state ==CA_CHALLENGING||
|
||||
cls.state ==CA_PRIMED||
|
||||
cls.state ==CA_CINEMATIC ||
|
||||
cls.state ==CA_LOADING)
|
||||
return qfalse;
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
IN_ClearControllerUnplugged
|
||||
*********/
|
||||
static void IN_ClearControllerUnplugged(void)
|
||||
{
|
||||
uiControllerNotification = -1;
|
||||
}
|
||||
|
||||
/*********
|
||||
IN_ControllerMustBePlugged
|
||||
*********/
|
||||
static bool IN_ControllerMustBePlugged(int controller)
|
||||
{
|
||||
if( cls.state == CA_LOADING ||
|
||||
cls.state == CA_CONNECTING ||
|
||||
cls.state == CA_CONNECTED ||
|
||||
cls.state == CA_CHALLENGING ||
|
||||
cls.state == CA_PRIMED ||
|
||||
cls.state == CA_CINEMATIC)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( ClientManager::splitScreenMode == qtrue )
|
||||
{
|
||||
if( controller == IN_GetMainController() )
|
||||
return true;
|
||||
|
||||
if( cls.state == CA_ACTIVE && ClientManager::Controller(1) == controller )
|
||||
return true;
|
||||
}
|
||||
else if( controller == IN_GetMainController() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern void IN_CheckForNoControllers();
|
||||
/*********
|
||||
IN_PadUnplugged
|
||||
*********/
|
||||
void IN_PadUnplugged(int controller)
|
||||
{
|
||||
if(wasPlugged[controller])
|
||||
{
|
||||
Com_Printf("\tController %d unplugged\n",controller);
|
||||
}
|
||||
|
||||
//JLF moved
|
||||
wasPlugged[controller] = false;
|
||||
Cvar_SetValue("ControllersConnectedCount", wasPlugged[0] + wasPlugged[1] + wasPlugged[2] + wasPlugged[3]);
|
||||
|
||||
//IN_CheckForNoControllers();
|
||||
|
||||
if(IN_ControllerMustBePlugged(controller)/*&& SG_GameAllowedToSaveHere(qtrue)*/)
|
||||
{
|
||||
//If UI isn't busy, inform it about controller loss.
|
||||
if(uiControllerNotification == -1 && Cvar_VariableIntegerValue("ControllerOutNum")<0)
|
||||
{
|
||||
mainControllerDelayedUnplug &= ~( 1<< controller);
|
||||
IN_DisplayControllerUnplugged(controller);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ClientManager::splitScreenMode == qtrue)
|
||||
if (controller != uiControllerNotification)
|
||||
unpluggedcontrol2 = controller;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((noControllersConnected && _UIRunning) || controller == IN_GetMainController() || ( cls.state != CA_DISCONNECTED && ClientManager::splitScreenMode))
|
||||
{
|
||||
//store somehow for checking again later
|
||||
mainControllerDelayedUnplug = 1 << controller;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*********
|
||||
IN_PadPlugged
|
||||
*********/
|
||||
void IN_PadPlugged(int controller)
|
||||
{
|
||||
if(!wasPlugged[controller])
|
||||
{
|
||||
Com_Printf("\tController %d plugged\n",controller);
|
||||
}
|
||||
|
||||
if(IN_ControllerMustBePlugged(controller)/*&& SG_GameAllowedToSaveHere(qtrue)*/)
|
||||
{
|
||||
//If UI is dealing with this controller, tell it to stop.
|
||||
if((uiControllerNotification == controller)|| (_UIRunning && cls.state != CA_ACTIVE ))
|
||||
{
|
||||
IN_ClearControllerUnplugged();
|
||||
}
|
||||
if (unpluggedcontrol2 == controller)
|
||||
unpluggedcontrol2 = -1;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (controller == IN_GetMainController())
|
||||
{
|
||||
//store somehow for checking again later
|
||||
mainControllerDelayedUnplug &= ~(1 << controller);
|
||||
}
|
||||
}
|
||||
|
||||
wasPlugged[controller] = true;
|
||||
noControllersConnected = false;
|
||||
Cvar_SetValue("ControllersConnectedCount", wasPlugged[0]+wasPlugged[1] + wasPlugged[2]+wasPlugged[3]);
|
||||
}
|
||||
|
||||
/*********
|
||||
IN_GetMainController
|
||||
*********/
|
||||
int IN_GetMainController(void)
|
||||
{
|
||||
return cls.mainGamepad;
|
||||
}
|
||||
|
||||
/*********
|
||||
IN_SetMainController
|
||||
*********/
|
||||
void IN_SetMainController(int id)
|
||||
{
|
||||
ClientManager::SetActiveController(id);
|
||||
ClientManager::ActivateByControllerId(id);
|
||||
ClientManager::SetMainClient(ClientManager::ActiveClientNum());
|
||||
cls.mainGamepad = id;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
*
|
||||
* DEBUGGING CODE
|
||||
*
|
||||
**********************************************************/
|
||||
|
||||
#ifdef DEBUG_CONTROLLER
|
||||
static void HandleDebugJoystickPress(fakeAscii_t button)
|
||||
{
|
||||
switch(button) {
|
||||
case A_JOY13: // Right pad up (yellow)
|
||||
Cbuf_ExecuteText(EXEC_APPEND, "give all\n");
|
||||
break;
|
||||
case A_JOY16: // Right pad left (blue)
|
||||
Cbuf_ExecuteText(EXEC_APPEND, "viewpos\n");
|
||||
break;
|
||||
case A_JOY14: // Right pad right (red)
|
||||
Cbuf_ExecuteText(EXEC_APPEND, "noclip\n");
|
||||
break;
|
||||
case A_JOY15: // Right pad down (green)
|
||||
Cbuf_ExecuteText(EXEC_APPEND, "god\n");
|
||||
break;
|
||||
case A_JOY4: // Start
|
||||
break;
|
||||
case A_JOY1: // back
|
||||
break;
|
||||
case A_JOY2: // Left thumbstick
|
||||
extern void Z_CompactStats(void);
|
||||
Z_CompactStats();
|
||||
break;
|
||||
case A_JOY12: // Upper right trigger
|
||||
break;
|
||||
case A_JOY8: // Left pad left
|
||||
break;
|
||||
case A_JOY6: // Left pad right
|
||||
break;
|
||||
case A_JOY5: // Left pad up
|
||||
break;
|
||||
case A_JOY7: // Left pad down
|
||||
break;
|
||||
case A_JOY11: // Upper left trigger
|
||||
break;
|
||||
case A_JOY9: // White button
|
||||
break;
|
||||
case A_JOY10: // Black button
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
755
codemp/win32/win_input_rumble.cpp
Normal file
755
codemp/win32/win_input_rumble.cpp
Normal file
@@ -0,0 +1,755 @@
|
||||
|
||||
/*
|
||||
* UNPUBLISHED -- Rights reserved under the copyright laws of the
|
||||
* United States. Use of a copyright notice is precautionary only and
|
||||
* does not imply publication or disclosure.
|
||||
*
|
||||
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
|
||||
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
|
||||
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
|
||||
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
|
||||
*/
|
||||
#include "../cgame/cg_local.h"
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
#include "win_local.h"
|
||||
#include "win_input.h"
|
||||
|
||||
#ifdef _XBOX
|
||||
#include "../client/cl_data.h"
|
||||
#endif
|
||||
|
||||
|
||||
//MB #include "../client/cl_data.h"
|
||||
#include "../game/q_shared.h"
|
||||
|
||||
extern qboolean G_ActivePlayerNormal(void);
|
||||
static int rumble_timer = 0;
|
||||
|
||||
struct rumblestate_t
|
||||
{
|
||||
int timeToStop;
|
||||
|
||||
// Right motor speed on Xbox, action type on Gamecube
|
||||
int arg1;
|
||||
|
||||
// Left motor speed on Xbox, secondary action type on Gamecube
|
||||
int arg2;
|
||||
};
|
||||
|
||||
struct rumblestate_special_t
|
||||
{
|
||||
int code;
|
||||
int arg1;
|
||||
int arg2;
|
||||
};
|
||||
|
||||
struct rumblescript_t
|
||||
{
|
||||
int nextStateAt;
|
||||
|
||||
int controller;
|
||||
|
||||
int currentState;
|
||||
int usedStates;
|
||||
int numStates;
|
||||
|
||||
bool autoDelete;
|
||||
rumblestate_t *states;
|
||||
};
|
||||
|
||||
struct rumblestatus_t
|
||||
{
|
||||
bool changed;
|
||||
bool killed;
|
||||
bool paused;
|
||||
int timePaused;
|
||||
};
|
||||
|
||||
#define MAX_RUMBLE_STATES 10
|
||||
#define MAX_RUMBLE_SCRIPTS 10
|
||||
#define MAX_RUMBLE_CONTROLLERS 4
|
||||
|
||||
// In rumblestate, highest speed for each side takes precidence
|
||||
// Number of rumble states is fairly small, so a plain array will work fine
|
||||
static rumblestatus_t rumbleStatus[MAX_RUMBLE_CONTROLLERS];
|
||||
static rumblescript_t rumbleScripts[MAX_RUMBLE_SCRIPTS];
|
||||
|
||||
cvar_t* in_useRumble = NULL;
|
||||
cvar_t* in_useRumble2 = NULL;
|
||||
|
||||
/***** FIXME Some functions that would be found in a client manager *****/
|
||||
/***** BEGIN FILLER *****/
|
||||
|
||||
// Always return 0 because we have only one client (right now anyway)
|
||||
int ActiveClientNum(void)
|
||||
{
|
||||
#ifdef _XBOX
|
||||
if(ClientManager::splitScreenMode == qtrue)
|
||||
return ClientManager::ActiveClientNum();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The active controller will always be number 0 for now
|
||||
int ActiveController(void)
|
||||
{
|
||||
#ifdef _XBOX
|
||||
if(ClientManager::splitScreenMode == qtrue)
|
||||
return ClientManager::ActiveClient().controller;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
/***** END FILLER *****/
|
||||
|
||||
void IN_enableRumble( void )
|
||||
{
|
||||
if (ActiveClientNum() == 0)
|
||||
{
|
||||
Cvar_Set( "in_useRumble", "1");
|
||||
}
|
||||
else
|
||||
{
|
||||
Cvar_Set( "in_useRumble2", "1");
|
||||
}
|
||||
}
|
||||
|
||||
void IN_disableRumble( void )
|
||||
{
|
||||
if (ActiveClientNum() == 0)
|
||||
{
|
||||
Cvar_Set( "in_useRumble", "0");
|
||||
}
|
||||
else
|
||||
{
|
||||
Cvar_Set( "in_useRumble2", "0");
|
||||
}
|
||||
}
|
||||
|
||||
bool IN_usingRumble( void )
|
||||
{
|
||||
if (ActiveClientNum() == 0)
|
||||
{
|
||||
return in_useRumble->integer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return in_useRumble2->integer;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Creates a rumble script with numStates
|
||||
// Returns -1 on no more room, otherwise an identifier to use for scripts
|
||||
int IN_CreateRumbleScript(int controller, int numStates, bool deleteWhenFinished)
|
||||
{
|
||||
if (!IN_usingRumble()) return -1;
|
||||
|
||||
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return -1;
|
||||
assert (numStates > 0 && numStates < MAX_RUMBLE_STATES);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
|
||||
{
|
||||
if (rumbleScripts[i].states == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == MAX_RUMBLE_SCRIPTS)
|
||||
return -1; // Ran out of scripts
|
||||
|
||||
rumbleScripts[i].autoDelete = deleteWhenFinished;
|
||||
rumbleScripts[i].controller = controller;
|
||||
rumbleScripts[i].currentState = 0;
|
||||
rumbleScripts[i].nextStateAt = 0;
|
||||
rumbleScripts[i].numStates = numStates;
|
||||
rumbleScripts[i].usedStates = 0;
|
||||
rumbleScripts[i].states = new rumblestate_t[numStates];
|
||||
memset(rumbleScripts[i].states, 0, sizeof(rumblestate_t) * numStates);
|
||||
return i;
|
||||
}
|
||||
|
||||
// A negative time will last until you kill it explicitly
|
||||
// Returns index, used to kill or change a state in a script
|
||||
int IN_AddRumbleStateFull(int whichScript, int arg1, int arg2, int timeInMs)
|
||||
{
|
||||
if (!IN_usingRumble()) return -1;
|
||||
|
||||
assert(whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
|
||||
assert(rumbleScripts[whichScript].usedStates < rumbleScripts[whichScript].numStates);
|
||||
|
||||
// Get the current state
|
||||
rumblescript_t *curScript = &rumbleScripts[whichScript];
|
||||
rumblestate_t *curState = &curScript->states[curScript->usedStates];
|
||||
|
||||
curState->arg1 = arg1;
|
||||
curState->arg2 = arg2;
|
||||
|
||||
curState->timeToStop = timeInMs;
|
||||
return curScript->usedStates++;
|
||||
}
|
||||
|
||||
int IN_AddRumbleState(int whichScript, int leftSpeed, int rightSpeed, int timeInMs)
|
||||
{
|
||||
return IN_AddRumbleStateFull(whichScript, leftSpeed, rightSpeed, timeInMs);
|
||||
}
|
||||
|
||||
int IN_AddRumbleStateSpecial(int whichScript, int action, int arg1, int arg2)
|
||||
{
|
||||
if (!IN_usingRumble()) return -1;
|
||||
|
||||
assert(whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
|
||||
assert(rumbleScripts[whichScript].usedStates < rumbleScripts[whichScript].numStates);
|
||||
|
||||
// Get the current state
|
||||
rumblescript_t *curScript = &rumbleScripts[whichScript];
|
||||
rumblestate_special_t *curState = (rumblestate_special_t*)&curScript->states[curScript->usedStates];
|
||||
|
||||
curState->code = action;
|
||||
curState->arg1 = arg1;
|
||||
curState->arg2 = arg2;
|
||||
return curScript->usedStates++;
|
||||
}
|
||||
|
||||
int IN_AddEffectFade4(int whichScript, int startLeft, int startRight,
|
||||
int endLeft, int endRight, int timeInMs)
|
||||
{
|
||||
const int fadeSmoothness = 50; // number of ms between updates, smaller is smoother
|
||||
|
||||
int e = IN_AddRumbleState(whichScript, startLeft, startRight, fadeSmoothness); // Lasts for fadeSmoothness ms
|
||||
|
||||
if (startLeft < endLeft) // Fade increases
|
||||
{
|
||||
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_LEFT, e,
|
||||
(endLeft - startLeft) * fadeSmoothness / timeInMs);
|
||||
}
|
||||
else
|
||||
{
|
||||
IN_AddRumbleStateSpecial(whichScript, IN_CMD_DEC_LEFT, e,
|
||||
(startLeft - endLeft) * fadeSmoothness / timeInMs);
|
||||
}
|
||||
|
||||
if (startRight < endRight)
|
||||
{
|
||||
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_RIGHT, e,
|
||||
(endRight - startRight) * fadeSmoothness / timeInMs);
|
||||
}
|
||||
else
|
||||
{
|
||||
IN_AddRumbleStateSpecial(whichScript, IN_CMD_DEC_RIGHT, e,
|
||||
(startRight - endRight) * fadeSmoothness / timeInMs);
|
||||
}
|
||||
|
||||
return IN_AddRumbleStateSpecial(whichScript, IN_CMD_GOTO_XTIMES,
|
||||
e, timeInMs / fadeSmoothness);
|
||||
}
|
||||
|
||||
int IN_AddEffectFadeExp6(int whichScript, int startLeft, int startRight,
|
||||
int endLeft, int endRight, char factor, int timeInMs)
|
||||
{
|
||||
const int fadeSmoothness = 10; // number of ms between updates, smaller is smoother
|
||||
|
||||
int state = IN_AddRumbleState(whichScript, startLeft, startRight, fadeSmoothness); // Lasts for fadeSmoothness ms
|
||||
|
||||
if (startLeft < endLeft) // Fade increases
|
||||
{
|
||||
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_LEFT, state,
|
||||
(endLeft - startLeft) * fadeSmoothness / timeInMs -
|
||||
(factor / 2) * ( 1 - timeInMs / fadeSmoothness)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
IN_AddRumbleStateSpecial(whichScript, IN_CMD_DEC_LEFT, state,
|
||||
(startLeft - endLeft) * fadeSmoothness / timeInMs -
|
||||
(factor / 2) * ( 1 - timeInMs / fadeSmoothness)
|
||||
);
|
||||
}
|
||||
|
||||
if (startRight < endRight)
|
||||
{
|
||||
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_RIGHT, state,
|
||||
(endRight - startRight) * fadeSmoothness / timeInMs -
|
||||
(factor / 2) * ( 1 - timeInMs / fadeSmoothness)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
IN_AddRumbleStateSpecial(whichScript, IN_CMD_DEC_RIGHT, state,
|
||||
(startRight - endRight) * fadeSmoothness / timeInMs -
|
||||
(factor / 2) * ( 1 - timeInMs / fadeSmoothness)
|
||||
);
|
||||
}
|
||||
|
||||
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_ARG2, state + 1, factor);
|
||||
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_ARG2, state + 2, factor);
|
||||
return IN_AddRumbleStateSpecial(whichScript, IN_CMD_GOTO_XTIMES,
|
||||
state, timeInMs / fadeSmoothness);
|
||||
}
|
||||
|
||||
// Kills a rumble state based on index
|
||||
void IN_KillRumbleState(int whichScript, int index)
|
||||
{
|
||||
if (!IN_usingRumble()) return;
|
||||
|
||||
assert( whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
|
||||
assert( index < rumbleScripts[whichScript].numStates );
|
||||
|
||||
rumbleScripts[whichScript].states[index].timeToStop = 0;
|
||||
rumbleStatus[rumbleScripts[whichScript].controller].changed = true;
|
||||
}
|
||||
|
||||
// Stops the script, if script has autodelete on then it will get deleted, otherwise it will only stop
|
||||
void IN_KillRumbleScript(int whichScript)
|
||||
{
|
||||
if (!IN_usingRumble()) return;
|
||||
|
||||
assert (whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
|
||||
|
||||
if(whichScript < 0 || whichScript > MAX_RUMBLE_SCRIPTS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rumbleScripts[whichScript].nextStateAt = 0;
|
||||
if (rumbleScripts[whichScript].autoDelete)
|
||||
{
|
||||
if (rumbleScripts[whichScript].states)
|
||||
delete [] rumbleScripts[whichScript].states;
|
||||
rumbleScripts[whichScript].states = 0;
|
||||
}
|
||||
|
||||
rumbleStatus[rumbleScripts[whichScript].controller].changed = true;
|
||||
}
|
||||
|
||||
// Stops Rumbling for specific controller
|
||||
void IN_KillRumbleScripts(int controller)
|
||||
{
|
||||
if (!IN_usingRumble()) return;
|
||||
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return;
|
||||
if (rumbleStatus[controller].killed == true) return;
|
||||
|
||||
for (int i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
|
||||
{
|
||||
if (rumbleScripts[i].controller == controller)
|
||||
IN_KillRumbleScript(i);
|
||||
}
|
||||
|
||||
rumbleStatus[controller].killed = IN_RumbleAdjust(controller, 0, 0);
|
||||
}
|
||||
|
||||
// Stops Rumbling on all controllers
|
||||
void IN_KillRumbleScripts( void )
|
||||
{
|
||||
if (!IN_usingRumble()) return;
|
||||
|
||||
for (int i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
|
||||
IN_KillRumbleScript(i);
|
||||
|
||||
for (int j = 0; j < MAX_RUMBLE_CONTROLLERS; j++)
|
||||
{
|
||||
if (!rumbleStatus[j].killed)
|
||||
{
|
||||
rumbleStatus[j].killed = IN_RumbleAdjust(j, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IN_DeleteRumbleScript(int whichScript)
|
||||
{
|
||||
if (!IN_usingRumble()) return;
|
||||
|
||||
assert (whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
|
||||
|
||||
if (rumbleScripts[whichScript].states)
|
||||
delete [] rumbleScripts[whichScript].states;
|
||||
rumbleScripts[whichScript].nextStateAt = 0;
|
||||
rumbleScripts[whichScript].states = 0;
|
||||
|
||||
rumbleStatus[rumbleScripts[whichScript].controller].changed = true;
|
||||
}
|
||||
|
||||
int IN_RunSpecialScript(int whichScript)
|
||||
{
|
||||
rumblestate_special_t *sp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[rumbleScripts[whichScript].currentState];
|
||||
switch (sp->code)
|
||||
{
|
||||
// updates the current state pointer
|
||||
// uses arg1
|
||||
case IN_CMD_GOTO:
|
||||
rumbleScripts[whichScript].currentState = sp->arg1;
|
||||
return rumbleScripts[whichScript].states[sp->arg1].timeToStop;
|
||||
break;
|
||||
// does a goto, and decreases count of arg2, until 0
|
||||
case IN_CMD_GOTO_XTIMES:
|
||||
if (--sp->arg2 >= 0)
|
||||
{
|
||||
rumbleScripts[whichScript].currentState = sp->arg1;
|
||||
return rumbleScripts[whichScript].states[sp->arg1].timeToStop;
|
||||
}
|
||||
else // Go onto next cmd
|
||||
{
|
||||
if (!IN_AdvanceToNextState(whichScript))
|
||||
return -2; // Done
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
// Decreasae Arg2 of a State, sp->arg1 = state, sp->arg2 = amount to decrease arg2 of state by
|
||||
case IN_CMD_DEC_ARG2:
|
||||
{
|
||||
rumblestate_special_t *temp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[sp->arg1];
|
||||
temp->arg2 -= sp->arg2;
|
||||
}
|
||||
break;
|
||||
|
||||
// Increase Arg2 of a State, sp->arg1 = state, sp->arg2 = amount to increase arg2 of state by
|
||||
case IN_CMD_INC_ARG2:
|
||||
{
|
||||
rumblestate_special_t *temp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[sp->arg1];
|
||||
temp->arg2 += sp->arg2;
|
||||
}
|
||||
break;
|
||||
|
||||
// Decreasae Arg1 of a State, sp->arg1 = state, sp->arg2 = amount to decrease arg1 of state by
|
||||
case IN_CMD_DEC_ARG1:
|
||||
{
|
||||
rumblestate_special_t *temp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[sp->arg1];
|
||||
temp->arg1 -= sp->arg2;
|
||||
}
|
||||
break;
|
||||
|
||||
// Increase Arg2 of a State, sp->arg1 = state, sp->arg2 = amount to increase arg1 of state by
|
||||
case IN_CMD_INC_ARG1:
|
||||
{
|
||||
rumblestate_special_t *temp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[sp->arg1];
|
||||
temp->arg1 += sp->arg2;
|
||||
}
|
||||
break;
|
||||
|
||||
case IN_CMD_DEC_LEFT:
|
||||
rumbleScripts[whichScript].states[sp->arg1].arg2 -= sp->arg2;
|
||||
if (rumbleScripts[whichScript].states[sp->arg1].arg2 < 0)
|
||||
rumbleScripts[whichScript].states[sp->arg1].arg2 = 0;
|
||||
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
|
||||
return -2; // Done
|
||||
return rumbleScripts[whichScript].states[++rumbleScripts[whichScript].currentState].timeToStop;
|
||||
break;
|
||||
|
||||
case IN_CMD_DEC_RIGHT:
|
||||
rumbleScripts[whichScript].states[sp->arg1].arg1 -= sp->arg2;
|
||||
if (rumbleScripts[whichScript].states[sp->arg1].arg1 < 0)
|
||||
rumbleScripts[whichScript].states[sp->arg1].arg1 = 0;
|
||||
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
|
||||
return -2; // Done
|
||||
return rumbleScripts[whichScript].states[++rumbleScripts[whichScript].currentState].timeToStop;
|
||||
break;
|
||||
|
||||
case IN_CMD_INC_LEFT:
|
||||
rumbleScripts[whichScript].states[sp->arg1].arg2 += sp->arg2;
|
||||
if (rumbleScripts[whichScript].states[sp->arg1].arg2 > 65534)
|
||||
rumbleScripts[whichScript].states[sp->arg1].arg2 = 65534;
|
||||
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
|
||||
return -2; // Done
|
||||
return rumbleScripts[whichScript].states[++rumbleScripts[whichScript].currentState].timeToStop;
|
||||
break;
|
||||
|
||||
case IN_CMD_INC_RIGHT:
|
||||
rumbleScripts[whichScript].states[sp->arg1].arg1 += sp->arg2;
|
||||
if (rumbleScripts[whichScript].states[sp->arg1].arg1 > 65534)
|
||||
rumbleScripts[whichScript].states[sp->arg1].arg1 = 65534;
|
||||
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
|
||||
return -2; // Done
|
||||
return rumbleScripts[whichScript].states[++rumbleScripts[whichScript].currentState].timeToStop;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IN_Time()
|
||||
{
|
||||
//mb return ClientManager::ActiveClient().cg->time;
|
||||
return cg->time;
|
||||
}
|
||||
|
||||
void IN_ExecuteRumbleScript(int whichScript)
|
||||
{
|
||||
if (!IN_usingRumble()) return;
|
||||
|
||||
assert (whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
|
||||
|
||||
// Can't execute an empty script???
|
||||
assert (rumbleScripts[whichScript].usedStates > 0);
|
||||
|
||||
rumbleScripts[whichScript].currentState = 0;
|
||||
int cmd = rumbleScripts[whichScript].states[rumbleScripts[whichScript].currentState].timeToStop;
|
||||
if (cmd < 0)
|
||||
{
|
||||
cmd = IN_RunSpecialScript(whichScript);
|
||||
}
|
||||
|
||||
rumbleScripts[whichScript].nextStateAt = -1; //IN_Time() + cmd;
|
||||
|
||||
rumbleStatus[rumbleScripts[whichScript].controller].changed = true;
|
||||
rumbleStatus[rumbleScripts[whichScript].controller].killed = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void IN_PauseRumbling(int controller)
|
||||
{
|
||||
IN_KillRumbleScripts();
|
||||
/*
|
||||
if (!IN_usingRumble()) return;
|
||||
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return;
|
||||
if (rumbleStatus[controller].paused == true) return;
|
||||
|
||||
rumbleStatus[controller].timePaused = IN_Time();
|
||||
rumbleStatus[controller].paused = IN_RumbleAdjust(controller, 0, 0);
|
||||
*/
|
||||
}
|
||||
|
||||
void IN_UnPauseRumbling(int controller)
|
||||
{
|
||||
return;
|
||||
/*
|
||||
if (!IN_usingRumble()) return;
|
||||
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return;
|
||||
|
||||
// can't unpause a control that wasn't paused
|
||||
if (rumbleStatus[controller].paused == false) return;
|
||||
|
||||
int cur_time = IN_Time();
|
||||
for (int i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
|
||||
{
|
||||
if (rumbleScripts[i].controller == controller)
|
||||
{
|
||||
if (rumbleScripts[i].nextStateAt == 0) continue;
|
||||
// update the time to stop based on how long it was paused
|
||||
rumbleScripts[i].nextStateAt += (cur_time - rumbleStatus[controller].timePaused);
|
||||
}
|
||||
}
|
||||
|
||||
rumbleStatus[controller].paused = false;
|
||||
rumbleStatus[controller].changed = true;
|
||||
rumbleStatus[controller].killed = false;
|
||||
*/
|
||||
}
|
||||
|
||||
void IN_TogglePauseRumbling(int controller)
|
||||
{
|
||||
if (!IN_usingRumble()) return;
|
||||
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return;
|
||||
if (rumbleStatus[controller].paused)
|
||||
IN_UnPauseRumbling(controller);
|
||||
else
|
||||
IN_PauseRumbling(controller);
|
||||
}
|
||||
|
||||
// Pauses rumbling on all controllers
|
||||
void IN_PauseRumbling( void )
|
||||
{
|
||||
if (!IN_usingRumble()) return;
|
||||
for (int i = 0; i < MAX_RUMBLE_CONTROLLERS; i++)
|
||||
IN_PauseRumbling(i);
|
||||
}
|
||||
|
||||
// UnPauses rumbling on all controllers
|
||||
void IN_UnPauseRumbling( void )
|
||||
{
|
||||
if (!IN_usingRumble()) return;
|
||||
for (int i = 0; i < MAX_RUMBLE_CONTROLLERS; i++)
|
||||
IN_UnPauseRumbling(i);
|
||||
}
|
||||
|
||||
// Toggles Pausing on all controllers
|
||||
void IN_TogglePauseRumbling( void )
|
||||
{
|
||||
if (!IN_usingRumble()) return;
|
||||
for (int i = 0; i < MAX_RUMBLE_CONTROLLERS; i++)
|
||||
IN_TogglePauseRumbling(i);
|
||||
}
|
||||
|
||||
// Returns false when the end of the script is reached
|
||||
bool IN_AdvanceToNextState(int whichScript)
|
||||
{
|
||||
assert( whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS );
|
||||
|
||||
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
|
||||
{
|
||||
// Script is at its end, so kill it( which deletes only if autodelete
|
||||
IN_KillRumbleScript(whichScript);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Advance a state
|
||||
rumbleScripts[whichScript].currentState++;
|
||||
|
||||
int cmd = rumbleScripts[whichScript].states[rumbleScripts[whichScript].currentState].timeToStop;
|
||||
while (cmd < 0)
|
||||
{
|
||||
cmd = IN_RunSpecialScript(whichScript);
|
||||
if (cmd == -1) return true;
|
||||
if (cmd == -2) return false;
|
||||
}
|
||||
|
||||
rumbleScripts[whichScript].nextStateAt = IN_Time() + cmd;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Max rumble takes precidence
|
||||
// Other possibility is some kind of sum of all the speeds
|
||||
// Call this once a frame, to update the controller based on the rumble states
|
||||
void IN_UpdateRumbleFromStates()
|
||||
{
|
||||
if(VM_Call( uivm, UI_IS_FULLSCREEN ))
|
||||
{
|
||||
IN_KillRumbleScripts();
|
||||
return;
|
||||
}
|
||||
|
||||
int usingRumble[2];
|
||||
usingRumble[0] = in_useRumble->integer;
|
||||
usingRumble[1] = in_useRumble2->integer;
|
||||
|
||||
int i;
|
||||
int value[MAX_RUMBLE_CONTROLLERS][2];
|
||||
int cur_time = IN_Time();
|
||||
bool canKillScripts = false;
|
||||
|
||||
memset(value, 0, sizeof(int)*MAX_RUMBLE_CONTROLLERS*2);
|
||||
for (i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
|
||||
{
|
||||
// If rumble is paused on current controller than skip this rumble state
|
||||
if ( rumbleStatus[rumbleScripts[i].controller].paused) continue;
|
||||
|
||||
//*mb ClientManager::ActivateByControllerId(rumbleScripts[i].controller);
|
||||
if ( !usingRumble[ActiveClientNum()] )
|
||||
{
|
||||
IN_KillRumbleScript(i);
|
||||
continue;
|
||||
}
|
||||
/*mb
|
||||
if (!ClientManager::ActiveGentity() || !G_ActivePlayerNormal())
|
||||
{
|
||||
IN_KillRumbleScript(i);
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
// Unset state so skip
|
||||
if ( rumbleScripts[i].nextStateAt == 0) continue;
|
||||
|
||||
canKillScripts = true;
|
||||
|
||||
if(rumbleScripts[i].nextStateAt == -1)
|
||||
{
|
||||
int cmd = rumbleScripts[i].states[rumbleScripts[i].currentState].timeToStop;
|
||||
rumbleScripts[i].nextStateAt = cur_time + cmd;
|
||||
}
|
||||
|
||||
// Time is up on this rumble state
|
||||
if ( rumbleScripts[i].nextStateAt < cur_time)
|
||||
{
|
||||
// If timeToStop is < cur_time and > 0 then end this state otherwise (negative number) always rumble
|
||||
if (rumbleScripts[i].nextStateAt > 0)
|
||||
{
|
||||
rumbleStatus[rumbleScripts[i].controller].changed = true;
|
||||
rumbleStatus[rumbleScripts[i].controller].killed = false;
|
||||
if (!IN_AdvanceToNextState(i)) // Returns false if reached the end of script
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
rumblescript_t *curScript = &rumbleScripts[i];
|
||||
|
||||
if (value[curScript->controller][0] < curScript->states[curScript->currentState].arg2)
|
||||
value[curScript->controller][0] = curScript->states[curScript->currentState].arg2;
|
||||
if (value[curScript->controller][1] < curScript->states[curScript->currentState].arg1)
|
||||
value[curScript->controller][1] = curScript->states[curScript->currentState].arg1;
|
||||
}
|
||||
|
||||
// Go through the 4 controller ports
|
||||
for (i = 0; i < MAX_RUMBLE_CONTROLLERS; i++)
|
||||
{
|
||||
// paused, so do nothing for this controller
|
||||
if ( rumbleStatus[i].paused) continue;
|
||||
|
||||
// Only update the actual hardware if a state has changed
|
||||
if (!rumbleStatus[i].changed) continue;
|
||||
|
||||
IN_RumbleAdjust(i, value[i][0], value[i][1]);
|
||||
|
||||
// State has changed
|
||||
rumbleStatus[i].changed = false;
|
||||
}
|
||||
|
||||
if(canKillScripts)
|
||||
{
|
||||
if( (cur_time - rumble_timer) > 5000 )
|
||||
IN_KillRumbleScripts();
|
||||
}
|
||||
else
|
||||
{
|
||||
rumble_timer = cur_time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
IN_RumbleInit
|
||||
==================
|
||||
*/
|
||||
void IN_RumbleInit (void) {
|
||||
memset(&rumbleStatus, 0, sizeof(rumblestatus_t)*MAX_RUMBLE_CONTROLLERS);
|
||||
memset(&rumbleScripts, 0, sizeof(rumblescript_t)*MAX_RUMBLE_SCRIPTS);
|
||||
|
||||
in_useRumble = Cvar_Get( "in_useRumble", "1", 0 );
|
||||
in_useRumble2 = Cvar_Get( "in_useRumble2", "1", 0 );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
IN_RumbleShutdown
|
||||
==================
|
||||
*/
|
||||
void IN_RumbleShutdown (void) {
|
||||
for (int i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
|
||||
{
|
||||
if (rumbleScripts[i].states)
|
||||
delete [] rumbleScripts[i].states;
|
||||
rumbleScripts[i].states = 0;
|
||||
rumbleScripts[i].nextStateAt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
IN_RumbleFrame
|
||||
==================
|
||||
*/
|
||||
void IN_RumbleFrame (void)
|
||||
{
|
||||
if( com_dedicated->integer )
|
||||
return;
|
||||
|
||||
// Check to see if we need to pause rumbling
|
||||
if(cl_paused->integer && !rumbleStatus[ClientManager::ActiveController()].paused)
|
||||
{
|
||||
IN_PauseRumbling(ClientManager::ActiveController());
|
||||
}
|
||||
else if(!cl_paused->integer && rumbleStatus[ClientManager::ActiveController()].paused)
|
||||
{
|
||||
IN_UnPauseRumbling(ClientManager::ActiveController());
|
||||
}
|
||||
|
||||
// Update the states
|
||||
IN_UpdateRumbleFromStates();
|
||||
}
|
||||
363
codemp/win32/win_input_xbox.cpp
Normal file
363
codemp/win32/win_input_xbox.cpp
Normal file
@@ -0,0 +1,363 @@
|
||||
// win_input.c -- win32 mouse and joystick code
|
||||
// 02/21/97 JCB Added extended DirectInput code to support external controllers.
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
// #include "../server/exe_headers.h"
|
||||
|
||||
#include <xtl.h>
|
||||
#include "glw_win_dx8.h"
|
||||
|
||||
#include "../client/client.h"
|
||||
|
||||
|
||||
#include "../qcommon/qcommon.h"
|
||||
#ifdef _JK2MP
|
||||
#include "../ui/keycodes.h"
|
||||
#else
|
||||
#include "../client/keycodes.h"
|
||||
#endif
|
||||
|
||||
#include "win_local.h"
|
||||
#include "win_input.h"
|
||||
|
||||
#include "../cgame/cg_local.h"
|
||||
#include "../client/cl_data.h"
|
||||
|
||||
#define IN_MAX_CONTROLLERS 4
|
||||
|
||||
void IN_UIEmptyQueue();
|
||||
|
||||
struct inputstate_t
|
||||
{
|
||||
struct controller_t
|
||||
{
|
||||
HANDLE handle;
|
||||
XINPUT_STATE state;
|
||||
XINPUT_FEEDBACK feedback;
|
||||
};
|
||||
controller_t controllers[IN_MAX_CONTROLLERS];
|
||||
};
|
||||
|
||||
inputstate_t in_state;
|
||||
|
||||
/*
|
||||
=========================================================================
|
||||
|
||||
JOYSTICK
|
||||
|
||||
=========================================================================
|
||||
*/
|
||||
extern bool noControllersConnected;
|
||||
|
||||
|
||||
// Process all the insertions and removals, updating handles and such
|
||||
void IN_ProcessChanges(DWORD dwInsert, DWORD dwRemove)
|
||||
{
|
||||
for(int port = 0; port < IN_MAX_CONTROLLERS; ++port)
|
||||
{
|
||||
// Close removals.
|
||||
if((1 << port) & dwRemove)
|
||||
{
|
||||
if ( in_state.controllers[port].handle )
|
||||
{
|
||||
XInputClose( in_state.controllers[port].handle );
|
||||
in_state.controllers[port].handle = 0;
|
||||
}
|
||||
IN_PadUnplugged(port);
|
||||
}
|
||||
|
||||
|
||||
// Open insertions.
|
||||
if( (1 << port) & dwInsert )
|
||||
{
|
||||
|
||||
in_state.controllers[port].handle = XInputOpen( XDEVICE_TYPE_GAMEPAD, port, XDEVICE_NO_SLOT, NULL );
|
||||
IN_PadPlugged(port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*********
|
||||
IN_CheckForNoControllers()
|
||||
If there are no controllers plugged in, the UI
|
||||
is notified so it can display an appropriate
|
||||
message.
|
||||
*********/
|
||||
/*
|
||||
void IN_CheckForNoControllers()
|
||||
{
|
||||
|
||||
if(!noControllersConnected)
|
||||
{
|
||||
extern bool wasPlugged[4];
|
||||
if( !wasPlugged[0] &&
|
||||
!wasPlugged[1] &&
|
||||
!wasPlugged[2] &&
|
||||
!wasPlugged[3] )
|
||||
{
|
||||
// Tell the UI that there are no controllers connected
|
||||
// VM_Call( uivm, UI_CONTROLLER_UNPLUGGED, true, -1);
|
||||
noControllersConnected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
=========================================================================
|
||||
|
||||
RUMBLE SUPPORT
|
||||
|
||||
=========================================================================
|
||||
*/
|
||||
|
||||
bool IN_RumbleAdjust(int controller, int left, int right)
|
||||
{
|
||||
assert(controller >= 0 && controller < IN_MAX_CONTROLLERS);
|
||||
|
||||
// Get a device handle for the controller. This may fail.
|
||||
HANDLE handle = in_state.controllers[controller].handle;
|
||||
|
||||
if (!handle) return false;
|
||||
|
||||
XINPUT_FEEDBACK* fb = &in_state.controllers[controller].feedback;
|
||||
|
||||
// If a prior rumble update is still pending, go away
|
||||
if (fb->Header.dwStatus == ERROR_IO_PENDING) return false;
|
||||
|
||||
fb->Rumble.wLeftMotorSpeed = left;
|
||||
fb->Rumble.wRightMotorSpeed = right;
|
||||
|
||||
return ERROR_IO_PENDING == XInputSetState(handle, fb);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=========================================================================
|
||||
|
||||
=========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
igBool IN_WindowClose(igWindow *window)
|
||||
{
|
||||
SV_Shutdown ("Server quit\n");
|
||||
CL_Shutdown ();
|
||||
Com_Shutdown ();
|
||||
Sys_Quit ();
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Shutdown
|
||||
===========
|
||||
*/
|
||||
void IN_Shutdown( void ) {
|
||||
IN_RumbleShutdown();
|
||||
|
||||
// delete in_state;
|
||||
// in_state = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Init
|
||||
===========
|
||||
*/
|
||||
void IN_Init( void )
|
||||
{
|
||||
// in_state = new inputstate_t;
|
||||
|
||||
// Initialize support for 4 gamepads
|
||||
XDEVICE_PREALLOC_TYPE xdpt[] = {
|
||||
{XDEVICE_TYPE_GAMEPAD, 4},
|
||||
{XDEVICE_TYPE_MEMORY_UNIT, 1},
|
||||
{XDEVICE_TYPE_VOICE_MICROPHONE, 4},
|
||||
{XDEVICE_TYPE_VOICE_HEADPHONE, 4}
|
||||
};
|
||||
Cvar_Get("ControllersConnectedCount", "0", 0);
|
||||
// Initialize the peripherals. We can only ever
|
||||
// call XInitDevices once, no matter what.
|
||||
static bool bInputInitialized = false;
|
||||
if (!bInputInitialized)
|
||||
XInitDevices( sizeof(xdpt) / sizeof(XDEVICE_PREALLOC_TYPE), xdpt );
|
||||
bInputInitialized = true;
|
||||
|
||||
// Zero all of our data, including handles
|
||||
memset(in_state.controllers, 0, sizeof(in_state.controllers));
|
||||
|
||||
// Find out the status of all gamepad ports, then open them
|
||||
IN_ProcessChanges( XGetDevices( XDEVICE_TYPE_GAMEPAD ), 0 );
|
||||
|
||||
IN_RumbleInit();
|
||||
}
|
||||
|
||||
static inline float _joyAxisConvert(SHORT x)
|
||||
{
|
||||
// Change scale
|
||||
float y = x / 32767.0;
|
||||
|
||||
// Cheesy deadzone
|
||||
if(fabs(y) < 0.25f)
|
||||
{
|
||||
y = 0.0f;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
// How many controls on the xbox gamepad?
|
||||
#define IN_NUM_DIGITAL_BUTTONS 8
|
||||
#define IN_NUM_ANALOG_BUTTONS 8
|
||||
// Cutoff where the analog buttons are considered to be "pressed"
|
||||
// This should be smarter.
|
||||
#define IN_ANALOG_BUTTON_THRESHOLD 64
|
||||
|
||||
void IN_UpdateGamepad(int port)
|
||||
{
|
||||
// Lookup table to convert the digital buttons to fakeAscii_t, in mask order
|
||||
const fakeAscii_t digitalXlat[IN_NUM_DIGITAL_BUTTONS] = {
|
||||
A_JOY5, // DPAD_UP
|
||||
A_JOY7, // DPAD_DOWN
|
||||
A_JOY8, // DPAD_LEFT
|
||||
A_JOY6, // DPAD_LEFT
|
||||
A_JOY4, // Start
|
||||
A_JOY1, // Back
|
||||
A_JOY2, // Left stick
|
||||
A_JOY3 // Right stick
|
||||
};
|
||||
|
||||
// Lookup table to convet the analog buttons to fakeAscii_t, in DX order
|
||||
const fakeAscii_t analogXlat[IN_NUM_ANALOG_BUTTONS] = {
|
||||
A_JOY15, // A
|
||||
A_JOY14, // B
|
||||
A_JOY16, // X
|
||||
A_JOY13, // Y
|
||||
A_JOY10, // Black
|
||||
A_JOY9, // White
|
||||
A_JOY11, // Left trigger
|
||||
A_JOY12 // Right trigger
|
||||
};
|
||||
|
||||
// Get new state
|
||||
XINPUT_STATE newState;
|
||||
XInputGetState( in_state.controllers[port].handle, &newState );
|
||||
|
||||
// Get old state
|
||||
XINPUT_STATE &oldState(in_state.controllers[port].state);
|
||||
|
||||
int buttonIdx;
|
||||
bool oldPressed, newPressed;
|
||||
|
||||
// Check all digital buttons first
|
||||
for (buttonIdx = 0; buttonIdx < IN_NUM_DIGITAL_BUTTONS; ++buttonIdx)
|
||||
{
|
||||
oldPressed = oldState.Gamepad.wButtons & (1 << buttonIdx);
|
||||
newPressed = newState.Gamepad.wButtons & (1 << buttonIdx);
|
||||
|
||||
if (oldPressed != newPressed)
|
||||
IN_CommonJoyPress(port, digitalXlat[buttonIdx], newPressed);
|
||||
}
|
||||
|
||||
// Now check all analog buttons
|
||||
for (buttonIdx = 0; buttonIdx < IN_NUM_ANALOG_BUTTONS; ++buttonIdx)
|
||||
{
|
||||
oldPressed = oldState.Gamepad.bAnalogButtons[buttonIdx] > IN_ANALOG_BUTTON_THRESHOLD;
|
||||
newPressed = newState.Gamepad.bAnalogButtons[buttonIdx] > IN_ANALOG_BUTTON_THRESHOLD;
|
||||
|
||||
if (oldPressed != newPressed)
|
||||
IN_CommonJoyPress(port, analogXlat[buttonIdx], newPressed);
|
||||
}
|
||||
|
||||
if ( port == ClientManager::ActiveClient().controller || cls.state != CA_ACTIVE)
|
||||
{
|
||||
// Update joysticks
|
||||
_padInfo.joyInfo[0].x = _joyAxisConvert(newState.Gamepad.sThumbLX);
|
||||
_padInfo.joyInfo[0].y = _joyAxisConvert(newState.Gamepad.sThumbLY);
|
||||
_padInfo.joyInfo[1].x = _joyAxisConvert(newState.Gamepad.sThumbRX);
|
||||
_padInfo.joyInfo[1].y = _joyAxisConvert(newState.Gamepad.sThumbRY);
|
||||
_padInfo.joyInfo[0].valid = _padInfo.joyInfo[1].valid = true;
|
||||
_padInfo.padId = port;
|
||||
|
||||
// Copy state back
|
||||
oldState = newState;
|
||||
// Update game
|
||||
|
||||
IN_CommonUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern qboolean CurrentStateIsInteractive();
|
||||
extern int mainControllerDelayedUnplug;
|
||||
extern vmCvar_t ControllerOutNum;
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
IN_Frame
|
||||
|
||||
Called every frame, even if not generating commands
|
||||
==================
|
||||
*/
|
||||
//extern int ignoreInputTime;
|
||||
|
||||
extern void startsetMainController(int controller);
|
||||
extern void CheckForSecondPrompt( void );
|
||||
|
||||
void IN_Frame (void)
|
||||
{
|
||||
static qboolean first = qtrue;
|
||||
// if (in_state)
|
||||
// {
|
||||
// First, check for changes in device status (removed/inserted pads)
|
||||
DWORD dwInsert, dwRemove;
|
||||
if( XGetDeviceChanges( XDEVICE_TYPE_GAMEPAD, &dwInsert, &dwRemove ) )
|
||||
{
|
||||
IN_ProcessChanges(dwInsert, dwRemove);
|
||||
}
|
||||
|
||||
if ( first)
|
||||
{
|
||||
extern int Sys_GetLaunchController( void );
|
||||
int controller = Sys_GetLaunchController();
|
||||
Com_Printf("\tController %d initialized\n", controller);
|
||||
|
||||
startsetMainController(controller);
|
||||
first = qfalse;
|
||||
}
|
||||
|
||||
if ( mainControllerDelayedUnplug && CurrentStateIsInteractive() && ControllerOutNum.integer < 0)
|
||||
IN_ProcessChanges(0, mainControllerDelayedUnplug);
|
||||
|
||||
|
||||
|
||||
// Generate callbacks for each controller that's plugged in
|
||||
for (int port = 0; port < IN_MAX_CONTROLLERS; ++port) {
|
||||
if (in_state.controllers[port].handle) {
|
||||
|
||||
if(ClientManager::splitScreenMode == qtrue) {
|
||||
//ClientManager::ActivateClient(port);
|
||||
ClientManager::ActivateByControllerId(port);
|
||||
|
||||
}
|
||||
IN_UpdateGamepad(port);
|
||||
}
|
||||
}
|
||||
|
||||
if(ClientManager::splitScreenMode == qtrue)
|
||||
ClientManager::ActivateMainClient();
|
||||
|
||||
IN_UIEmptyQueue();
|
||||
IN_RumbleFrame();
|
||||
CheckForSecondPrompt();
|
||||
// }
|
||||
}
|
||||
908
codemp/win32/win_lighteffects.cpp
Normal file
908
codemp/win32/win_lighteffects.cpp
Normal file
@@ -0,0 +1,908 @@
|
||||
//
|
||||
//
|
||||
// win_lighteffects.cpp
|
||||
//
|
||||
// Various lighting effects w/ pixel shaders
|
||||
//
|
||||
//
|
||||
|
||||
#ifdef VV_LIGHTING
|
||||
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
#include "../renderer/tr_local.h"
|
||||
#include "glw_win_dx8.h"
|
||||
#include "win_local.h"
|
||||
|
||||
#include "win_lighteffects.h"
|
||||
|
||||
#include <xgraphics.h>
|
||||
#include <xgmath.h>
|
||||
|
||||
#include "shader_constants.h"
|
||||
|
||||
|
||||
LightEffects::LightEffects()
|
||||
{
|
||||
m_pCubeMap = NULL;
|
||||
m_pBumpMap = NULL;
|
||||
// m_pSpecularMap = NULL;
|
||||
m_pFalloffMap = NULL;
|
||||
m_dwVertexShaderLight = 0L;
|
||||
m_dwPixelShaderLight = 0L;
|
||||
// m_dwVertexShaderSpecular_Dynamic = 0L;
|
||||
// m_dwPixelShaderSpecular_Dynamic = 0L;
|
||||
// m_dwVertexShaderSpecular_Static = 0L;
|
||||
// m_dwPixelShaderSpecular_Static = 0L;
|
||||
m_dwVertexShaderEnvironment = 0L;
|
||||
// m_dwVertexShaderBump = 0L;
|
||||
// m_dwPixelShaderBump = 0L;
|
||||
m_bInLightPhase = false;
|
||||
m_bInitialized = false;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
|
||||
LightEffects::~LightEffects()
|
||||
{
|
||||
if( m_pCubeMap )
|
||||
m_pCubeMap->Release();
|
||||
m_pCubeMap = NULL;
|
||||
|
||||
if(m_pBumpMap)
|
||||
m_pBumpMap->Release();
|
||||
m_pBumpMap = NULL;
|
||||
|
||||
if(m_pFalloffMap)
|
||||
m_pFalloffMap->Release();
|
||||
m_pFalloffMap = NULL;
|
||||
|
||||
/*if(m_pSpecularMap)
|
||||
m_pSpecularMap->Release();
|
||||
m_pSpecularMap = NULL;*/
|
||||
|
||||
if( glw_state->device )
|
||||
{
|
||||
glw_state->device->DeleteVertexShader( m_dwVertexShaderLight );
|
||||
glw_state->device->DeletePixelShader( m_dwPixelShaderLight );
|
||||
/*glw_state->device->DeleteVertexShader( m_dwVertexShaderSpecular_Dynamic );
|
||||
glw_state->device->DeletePixelShader( m_dwPixelShaderSpecular_Dynamic );
|
||||
glw_state->device->DeleteVertexShader( m_dwVertexShaderSpecular_Static );
|
||||
glw_state->device->DeletePixelShader( m_dwPixelShaderSpecular_Static );*/
|
||||
glw_state->device->DeleteVertexShader( m_dwVertexShaderEnvironment );
|
||||
glw_state->device->DeletePixelShader( m_dwPixelShaderBump );
|
||||
glw_state->device->DeleteVertexShader( m_dwVertexShaderBump );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LightEffects::StartLightPhase()
|
||||
{
|
||||
m_bInLightPhase = true;
|
||||
}
|
||||
|
||||
|
||||
void LightEffects::EndLightPhase()
|
||||
{
|
||||
m_bInLightPhase = false;
|
||||
}
|
||||
|
||||
|
||||
bool LightEffects::Initialize()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// Create a vertex shader
|
||||
DWORD dwVertexDecl[] =
|
||||
{
|
||||
D3DVSD_STREAM( 0 ),
|
||||
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // v0 = Position
|
||||
D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // v1 = Normal
|
||||
D3DVSD_REG( 2, D3DVSDT_FLOAT2 ), // v2 = Base tex coords
|
||||
D3DVSD_REG( 3, D3DVSDT_FLOAT3 ), // v3 = Tangent space tangent
|
||||
D3DVSD_END()
|
||||
};
|
||||
|
||||
if(!( CreateVertexShader("D:\\base\\media\\dlight.xvu", dwVertexDecl, &m_dwVertexShaderLight)))
|
||||
return false;
|
||||
|
||||
/*if(!( CreateVertexShader("D:\\base\\media\\specular_dynamic.xvu", dwVertexDecl, &m_dwVertexShaderSpecular_Dynamic)))
|
||||
return false;
|
||||
|
||||
if(!( CreateVertexShader("D:\\base\\media\\specular_static.xvu", dwVertexDecl, &m_dwVertexShaderSpecular_Static)))
|
||||
return false;*/
|
||||
|
||||
DWORD dwVertexDeclBump[] =
|
||||
{
|
||||
D3DVSD_STREAM( 0 ),
|
||||
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // v0 = Position
|
||||
D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // v1 = Normal
|
||||
D3DVSD_REG( 2, D3DVSDT_FLOAT2 ), // v2 = Base tex coords 0
|
||||
D3DVSD_REG( 3, D3DVSDT_FLOAT2 ), // v2 = Base tex coords 1
|
||||
D3DVSD_REG( 4, D3DVSDT_FLOAT3 ), // v4 = Tangent space tangent
|
||||
D3DVSD_END()
|
||||
};
|
||||
|
||||
if(!( CreateVertexShader("D:\\base\\media\\bump.xvu", dwVertexDeclBump, &m_dwVertexShaderBump)))
|
||||
return false;
|
||||
|
||||
DWORD dwVertexDeclEnv[] =
|
||||
{
|
||||
D3DVSD_STREAM( 0 ),
|
||||
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // v0 = Position
|
||||
D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // v1 = Normal
|
||||
D3DVSD_REG( 2, D3DVSDT_D3DCOLOR ), // v2 = Color
|
||||
D3DVSD_END()
|
||||
};
|
||||
|
||||
if(!( CreateVertexShader("D:\\base\\media\\environment.xvu", dwVertexDeclEnv, &m_dwVertexShaderEnvironment)))
|
||||
return false;
|
||||
|
||||
// Create the pixel shader
|
||||
if(!(CreatePixelShader("D:\\base\\media\\dlight.xpu", &m_dwPixelShaderLight)))
|
||||
return false;
|
||||
|
||||
/*if(!(CreatePixelShader("D:\\base\\media\\specular_dynamic.xpu", &m_dwPixelShaderSpecular_Dynamic)))
|
||||
return false;
|
||||
|
||||
if(!(CreatePixelShader("D:\\base\\media\\specular_static.xpu", &m_dwPixelShaderSpecular_Static)))
|
||||
return false;*/
|
||||
|
||||
if(!(CreatePixelShader("D:\\base\\media\\bump.xpu", &m_dwPixelShaderBump)))
|
||||
return false;
|
||||
|
||||
hr = D3DXCreateTextureFromFileEx(glw_state->device,
|
||||
"D:\\base\\media\\defaultbump.dds",
|
||||
D3DX_DEFAULT,
|
||||
D3DX_DEFAULT,
|
||||
0,
|
||||
0,
|
||||
D3DFMT_A8R8G8B8,
|
||||
0,
|
||||
D3DX_FILTER_LINEAR,
|
||||
D3DX_FILTER_LINEAR,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
&m_pBumpMap);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*hr = D3DXCreateTextureFromFileEx(glw_state->device,
|
||||
"D:\\base\\media\\diffspec.dds",
|
||||
D3DX_DEFAULT,
|
||||
D3DX_DEFAULT,
|
||||
0,
|
||||
0,
|
||||
D3DFMT_A8R8G8B8,
|
||||
0,
|
||||
D3DX_FILTER_LINEAR,
|
||||
D3DX_FILTER_LINEAR,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
&m_pSpecularMap);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}*/
|
||||
|
||||
// Create the volume falloff texture
|
||||
UINT width = 32,
|
||||
height = 32,
|
||||
depth = 32,
|
||||
levels = 1;
|
||||
D3DFORMAT format = D3DFMT_A8;
|
||||
if (FAILED (hr = glw_state->device->CreateVolumeTexture(width, height, depth,
|
||||
1, 0, format, D3DPOOL_DEFAULT, &m_pFalloffMap) ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fill the volume texture
|
||||
D3DVOLUME_DESC desc;
|
||||
D3DLOCKED_BOX lock;
|
||||
m_pFalloffMap->GetLevelDesc( 0, &desc );
|
||||
m_pFalloffMap->LockBox( 0, &lock, 0, 0L );
|
||||
BYTE* pBits = (BYTE*)lock.pBits;
|
||||
|
||||
for( UINT w=0; w<width; w++ )
|
||||
{
|
||||
for( UINT v=0; v<height; v++ )
|
||||
{
|
||||
for( UINT u=0; u<depth; u++ )
|
||||
{
|
||||
FLOAT x = (2.0f*u)/(width-1) - 1.0f; // Ranges from -1 to +1
|
||||
FLOAT y = (2.0f*v)/(height-1) - 1.0f; // Ranges from -1 to +1
|
||||
FLOAT z = (2.0f*w)/(depth-1) - 1.0f;
|
||||
|
||||
FLOAT distance = (float)(x*x + y*y + z*z);
|
||||
if (distance == 0)
|
||||
{
|
||||
*pBits++ = (BYTE)255;
|
||||
}
|
||||
else
|
||||
{
|
||||
FLOAT falloff = min(1.0f, max(0.0f, ((1.0f/2.0f)/distance - 1.0f/2.0f)/1.0f ) );
|
||||
*pBits++ = (BYTE)(255*falloff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DWORD dwPixelSize = XGBytesPerPixelFromFormat( desc.Format );
|
||||
DWORD dwTextureSize = desc.Width * desc.Height * desc.Depth * dwPixelSize;
|
||||
|
||||
BYTE* pSrcBits = new BYTE[ dwTextureSize ];
|
||||
memcpy( pSrcBits, lock.pBits, dwTextureSize );
|
||||
|
||||
XGSwizzleBox( pSrcBits, 0, 0, NULL, lock.pBits,
|
||||
desc.Width, desc.Height, desc.Depth,
|
||||
NULL, dwPixelSize );
|
||||
|
||||
delete [] pSrcBits;
|
||||
|
||||
m_pFalloffMap->UnlockBox( 0 );
|
||||
|
||||
// Create the normalization cube map
|
||||
if(!CreateNormalizationCubeMap( 32, &m_pCubeMap ))
|
||||
return false;
|
||||
|
||||
m_bInitialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LightEffects::RenderDynamicLights()
|
||||
{
|
||||
dlight_t *dl;
|
||||
shaderStage_t *dStage;
|
||||
vec3_t origin;
|
||||
byte clipBits[SHADER_MAX_VERTEXES];
|
||||
glIndex_t hitIndexes[SHADER_MAX_INDEXES];
|
||||
int numIndexes;
|
||||
float radius;
|
||||
int fogging;
|
||||
vec3_t dist;
|
||||
vec3_t e1;
|
||||
vec3_t e2;
|
||||
vec3_t normal;
|
||||
float fac;
|
||||
|
||||
if(!backEnd.refdef.num_dlights)
|
||||
return true;
|
||||
|
||||
glw_state->device->SetRenderState( D3DRS_LIGHTING, FALSE );
|
||||
|
||||
glw_state->device->SetTextureStageState( 1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
|
||||
glw_state->device->SetTextureStageState( 1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
|
||||
glw_state->device->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
|
||||
glw_state->device->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
|
||||
glw_state->device->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
|
||||
|
||||
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
|
||||
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
|
||||
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP );
|
||||
glw_state->device->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
|
||||
glw_state->device->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
|
||||
|
||||
glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
|
||||
glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
|
||||
glw_state->device->SetTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
|
||||
glw_state->device->SetTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
|
||||
glw_state->device->SetTextureStageState( 3, D3DTSS_MIPFILTER, D3DTEXF_POINT );
|
||||
|
||||
glw_state->device->SetTextureStageState( 2, D3DTSS_ALPHAKILL, D3DTALPHAKILL_ENABLE);
|
||||
|
||||
glw_state->device->SetTexture(1, m_pBumpMap);
|
||||
glw_state->device->SetTexture(2, m_pFalloffMap);
|
||||
glw_state->device->SetTexture(3, m_pCubeMap);
|
||||
|
||||
glw_state->device->SetPixelShader(m_dwPixelShaderLight);
|
||||
glw_state->device->SetVertexShader(m_dwVertexShaderLight);
|
||||
|
||||
for(int l = 0; l < backEnd.refdef.num_dlights; l++)
|
||||
{
|
||||
if(!(tess.dlightBits & (1 << l)))
|
||||
continue;
|
||||
|
||||
dl = &backEnd.refdef.dlights[l];
|
||||
if(!dl)
|
||||
continue;
|
||||
|
||||
VectorCopy( dl->transformed, origin );
|
||||
radius = dl->radius;
|
||||
|
||||
int clipall = 63;
|
||||
for (int i = 0 ; i < tess.numVertexes ; i++)
|
||||
{
|
||||
int clip;
|
||||
VectorSubtract( origin, tess.xyz[i], dist );
|
||||
|
||||
clip = 0;
|
||||
if ( dist[0] < -radius )
|
||||
{
|
||||
clip |= 1;
|
||||
}
|
||||
else if ( dist[0] > radius )
|
||||
{
|
||||
clip |= 2;
|
||||
}
|
||||
if ( dist[1] < -radius )
|
||||
{
|
||||
clip |= 4;
|
||||
}
|
||||
else if ( dist[1] > radius )
|
||||
{
|
||||
clip |= 8;
|
||||
}
|
||||
if ( dist[2] < -radius )
|
||||
{
|
||||
clip |= 16;
|
||||
}
|
||||
else if ( dist[2] > radius )
|
||||
{
|
||||
clip |= 32;
|
||||
}
|
||||
|
||||
clipBits[i] = clip;
|
||||
clipall &= clip;
|
||||
}
|
||||
if ( clipall )
|
||||
{
|
||||
continue; // this surface doesn't have any of this light
|
||||
}
|
||||
|
||||
// build a list of triangles that need light
|
||||
numIndexes = 0;
|
||||
for ( i = 0 ; i < tess.numIndexes ; i += 3 )
|
||||
{
|
||||
int a, b, c;
|
||||
|
||||
a = tess.indexes[i];
|
||||
b = tess.indexes[i+1];
|
||||
c = tess.indexes[i+2];
|
||||
if ( clipBits[a] & clipBits[b] & clipBits[c] )
|
||||
{
|
||||
continue; // not lighted
|
||||
}
|
||||
|
||||
VectorSubtract( tess.xyz[a], tess.xyz[b], e1);
|
||||
VectorSubtract( tess.xyz[c], tess.xyz[b], e2);
|
||||
CrossProduct(e1,e2,normal);
|
||||
|
||||
VectorNormalize(normal);
|
||||
fac=DotProduct(normal,origin)-DotProduct(normal, tess.xyz[a]);
|
||||
if (fac >= radius) // out of range
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// save the indexes
|
||||
hitIndexes[numIndexes] = tess.indexes[i];
|
||||
hitIndexes[numIndexes + 1] = tess.indexes[i + 1];
|
||||
hitIndexes[numIndexes + 2] = tess.indexes[i + 2];
|
||||
|
||||
numIndexes += 3;
|
||||
|
||||
if (numIndexes>=SHADER_MAX_VERTEXES-3)
|
||||
{
|
||||
break; // we are out of space, so we are done :)
|
||||
}
|
||||
}
|
||||
|
||||
if ( !numIndexes ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//don't have fog enabled when we redraw with alpha test, or it will double over
|
||||
//and screw the tri up -rww
|
||||
if (r_drawfog->value == 2 &&
|
||||
tr.world &&
|
||||
(tess.fogNum == tr.world->globalFog || tess.fogNum == tr.world->numfogs))
|
||||
{
|
||||
fogging = qglIsEnabled(GL_FOG);
|
||||
|
||||
if (fogging)
|
||||
{
|
||||
qglDisable(GL_FOG);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fogging = 0;
|
||||
}
|
||||
|
||||
dStage = NULL;
|
||||
if (tess.shader)
|
||||
{
|
||||
int j = 0;
|
||||
while (j < tess.shader->numUnfoggedPasses)
|
||||
{
|
||||
const int blendBits = (GLS_SRCBLEND_BITS+GLS_DSTBLEND_BITS);
|
||||
if (((tess.shader->stages[j].bundle[0].image && !tess.shader->stages[j].bundle[0].isLightmap && !tess.shader->stages[j].bundle[0].numTexMods && tess.shader->stages[j].bundle[0].tcGen != TCGEN_ENVIRONMENT_MAPPED && tess.shader->stages[j].bundle[0].tcGen != TCGEN_FOG) ||
|
||||
(tess.shader->stages[j].bundle[1].image && !tess.shader->stages[j].bundle[1].isLightmap && !tess.shader->stages[j].bundle[1].numTexMods && tess.shader->stages[j].bundle[1].tcGen != TCGEN_ENVIRONMENT_MAPPED && tess.shader->stages[j].bundle[1].tcGen != TCGEN_FOG)) &&
|
||||
(tess.shader->stages[j].stateBits & blendBits) == 0 )
|
||||
{ //only use non-lightmap opaque stages
|
||||
dStage = &tess.shader->stages[j];
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
if (dStage)
|
||||
{
|
||||
GL_SelectTexture( 0 );
|
||||
GL_State(0);
|
||||
if (dStage->bundle[0].image && !dStage->bundle[0].isLightmap && !dStage->bundle[0].numTexMods && dStage->bundle[0].tcGen != TCGEN_ENVIRONMENT_MAPPED && dStage->bundle[0].tcGen != TCGEN_FOG)
|
||||
{
|
||||
GL_Bind( dStage->bundle[0].image );
|
||||
}
|
||||
else
|
||||
{
|
||||
GL_Bind( dStage->bundle[1].image );
|
||||
}
|
||||
|
||||
GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);// | GLS_DEPTHFUNC_EQUAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL_Bind( tr.whiteImage );
|
||||
GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE);// | GLS_DEPTHFUNC_EQUAL );
|
||||
}
|
||||
|
||||
glwstate_t::texturexlat_t::iterator inf = glw_state->textureXlat.find(glw_state->currentTexture[0]);
|
||||
|
||||
glw_state->device->SetTexture(0, inf->second.mipmap);
|
||||
|
||||
D3DXVECTOR4 vecLightRange(1.0f / dl->radius, 0.0f, 0.0f, 0.0f);
|
||||
glw_state->device->SetVertexShaderConstant(CV_ONE_OVER_LIGHT_RANGE, (void*)&vecLightRange.x, 1);
|
||||
|
||||
glw_state->device->SetPixelShaderConstant(CP_DIFFUSE_COLOR, &dl->color[0], 1);
|
||||
|
||||
ProcessVertices( (D3DXVECTOR3*)&dl->transformed );
|
||||
|
||||
renderObject_Light( numIndexes, hitIndexes );
|
||||
|
||||
if (fogging)
|
||||
{
|
||||
qglEnable(GL_FOG);
|
||||
}
|
||||
}
|
||||
|
||||
glw_state->device->SetPixelShader( 0 );
|
||||
|
||||
// This is kinda a hack to get the quake renderer to discard
|
||||
// these textures after they are used here, instead of applying
|
||||
// them to more geometry
|
||||
glState.currenttextures[0] = -2;
|
||||
glState.currenttextures[1] = -2;
|
||||
glw_state->currentTexture[0] = -2;
|
||||
glw_state->currentTexture[1] = -2;
|
||||
|
||||
glw_state->device->SetTextureStageState( 2, D3DTSS_ALPHAKILL, D3DTALPHAKILL_DISABLE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//void LightEffects::RenderSpecular()
|
||||
//{
|
||||
// glw_state->device->SetRenderState( D3DRS_LIGHTING, FALSE );
|
||||
// glw_state->device->SetRenderState( D3DRS_FOGENABLE, FALSE );
|
||||
//
|
||||
// glwstate_t::texturexlat_t::iterator i = glw_state->textureXlat.find(glw_state->currentTexture[0]);
|
||||
//
|
||||
// glw_state->device->SetTexture( 0, i->second.mipmap );
|
||||
// glw_state->device->SetTexture( 2, m_pSpecularMap );
|
||||
//
|
||||
// glw_state->device->SetVertexShaderConstant(CV_CAMERA_DIRECTION, D3DXVECTOR4(tr.viewParms.ori.axis[0][0],
|
||||
// tr.viewParms.ori.axis[0][1],
|
||||
// tr.viewParms.ori.axis[0][2],
|
||||
// 1.0f), 1 );
|
||||
//
|
||||
// RenderSpecular_Static();
|
||||
//
|
||||
// if(tess.dlightBits)
|
||||
// RenderSpecular_Dynamic();
|
||||
//
|
||||
// glw_state->device->SetPixelShader(0);
|
||||
//
|
||||
// // This is kinda a hack to get the quake renderer to discard
|
||||
// // these textures after they are used here, instead of applying
|
||||
// // them to more geometry
|
||||
// glState.currenttextures[0] = -2;
|
||||
// glState.currenttextures[1] = -2;
|
||||
// glw_state->currentTexture[0] = -2;
|
||||
// glw_state->currentTexture[1] = -2;
|
||||
//}
|
||||
//
|
||||
//
|
||||
//bool LightEffects::RenderSpecular_Dynamic()
|
||||
//{
|
||||
// VVdlight_t *dl;
|
||||
//
|
||||
// glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
|
||||
// glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
|
||||
// glw_state->device->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
|
||||
// glw_state->device->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
|
||||
// glw_state->device->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
|
||||
// glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
|
||||
// glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
|
||||
// glw_state->device->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
|
||||
// glw_state->device->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
|
||||
// glw_state->device->SetTextureStageState( 2, D3DTSS_MIPFILTER, D3DTEXF_POINT );
|
||||
// glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
|
||||
// glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
|
||||
// glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP );
|
||||
// glw_state->device->SetTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
|
||||
// glw_state->device->SetTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
|
||||
//
|
||||
// glw_state->device->SetTexture( 3, m_pFalloffMap );
|
||||
//
|
||||
// glw_state->device->SetPixelShader(m_dwPixelShaderSpecular_Dynamic);
|
||||
// glw_state->device->SetVertexShader(m_dwVertexShaderSpecular_Dynamic);
|
||||
//
|
||||
// for(int i = 0; i < VVLightMan.num_dlights; i++)
|
||||
// {
|
||||
// if(!(tess.dlightBits & (1 << i)))
|
||||
// continue;
|
||||
//
|
||||
// dl = &VVLightMan.dlights[i];
|
||||
//
|
||||
// D3DXVECTOR4 vecLightRange(1.0f / dl->radius, 0.0f, 0.0f, 0.0f);
|
||||
// glw_state->device->SetVertexShaderConstant(CV_ONE_OVER_LIGHT_RANGE, (void*)&vecLightRange.x, 1);
|
||||
//
|
||||
// ProcessVertices( (D3DXVECTOR3*)&dl->direction, (D3DXVECTOR3*)&dl->transformed );
|
||||
//
|
||||
// renderObject_Light(tess.numIndexes, tess.indexes);
|
||||
// }
|
||||
//
|
||||
// glw_state->device->SetTexture( 3, NULL );
|
||||
//
|
||||
// return true;
|
||||
//}
|
||||
//
|
||||
//
|
||||
//bool LightEffects::RenderSpecular_Static()
|
||||
//{
|
||||
// glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
|
||||
// glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
|
||||
// glw_state->device->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
|
||||
// glw_state->device->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
|
||||
// glw_state->device->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
|
||||
// glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
|
||||
// glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
|
||||
// glw_state->device->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
|
||||
// glw_state->device->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
|
||||
// glw_state->device->SetTextureStageState( 2, D3DTSS_MIPFILTER, D3DTEXF_NONE );
|
||||
//
|
||||
// glw_state->device->SetPixelShader(m_dwPixelShaderSpecular_Static);
|
||||
// glw_state->device->SetVertexShader(m_dwVertexShaderSpecular_Static);
|
||||
//
|
||||
// ProcessVertices( NULL, NULL );
|
||||
//
|
||||
// D3DXVECTOR4 vLight;
|
||||
// if (backEnd.currentEntity && (backEnd.currentEntity->e.hModel||backEnd.currentEntity->e.ghoul2) )
|
||||
// {
|
||||
// vLight.x = backEnd.currentEntity->lightDir[0];
|
||||
// vLight.y = backEnd.currentEntity->lightDir[1];
|
||||
// vLight.z = backEnd.currentEntity->lightDir[2];
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // These values were taken from the RB_CalcSpecularAlpha default case
|
||||
// vLight.x = -960.0f;
|
||||
// vLight.y = 1920.0f;
|
||||
// vLight.z = 96.0f;
|
||||
// }
|
||||
//
|
||||
// vLight.w = 1.0f;
|
||||
//
|
||||
// glw_state->device->SetVertexShaderConstant(CV_LIGHT_DIRECTION, vLight, 1);
|
||||
//
|
||||
// renderObject_Light(tess.numIndexes, tess.indexes);
|
||||
//
|
||||
// return true;
|
||||
//}
|
||||
|
||||
bool LightEffects::RenderEnvironment()
|
||||
{
|
||||
glw_state->device->SetRenderState( D3DRS_LIGHTING, false );
|
||||
glw_state->device->SetRenderState( D3DRS_FOGENABLE, false );
|
||||
|
||||
glw_state->device->SetVertexShaderConstant(CV_CAMERA_DIRECTION, D3DXVECTOR4(backEnd.ori.viewOrigin[0],
|
||||
backEnd.ori.viewOrigin[1],
|
||||
backEnd.ori.viewOrigin[2],
|
||||
1.0f), 1 );
|
||||
|
||||
ProcessVertices(NULL);
|
||||
|
||||
glw_state->device->SetVertexShader(m_dwVertexShaderEnvironment);
|
||||
|
||||
renderObject_Env();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Renders bump maps without the benefit of dynamic lights
|
||||
void LightEffects::RenderBump()
|
||||
{
|
||||
glw_state->device->SetRenderState( D3DRS_LIGHTING, false );
|
||||
glw_state->device->SetRenderState( D3DRS_FOGENABLE, false );
|
||||
|
||||
glwstate_t::texturexlat_t::iterator i = glw_state->textureXlat.find(glw_state->currentTexture[0]);
|
||||
glw_state->device->SetTexture( 0, i->second.mipmap );
|
||||
|
||||
i = glw_state->textureXlat.find(glw_state->currentTexture[1]);
|
||||
glw_state->device->SetTexture( 1, i->second.mipmap );
|
||||
|
||||
glw_state->device->SetTextureStageState(0, D3DTSS_MAXANISOTROPY, i->second.anisotropy);
|
||||
glw_state->device->SetTextureStageState(0, D3DTSS_MINFILTER, i->second.minFilter);
|
||||
glw_state->device->SetTextureStageState(0, D3DTSS_MIPFILTER, i->second.mipFilter);
|
||||
glw_state->device->SetTextureStageState(0, D3DTSS_MAGFILTER, i->second.magFilter);
|
||||
glw_state->device->SetTextureStageState(0, D3DTSS_ADDRESSU, i->second.wrapU);
|
||||
glw_state->device->SetTextureStageState(0, D3DTSS_ADDRESSV, i->second.wrapV);
|
||||
|
||||
glw_state->device->SetTextureStageState(1, D3DTSS_MAXANISOTROPY, i->second.anisotropy);
|
||||
glw_state->device->SetTextureStageState(1, D3DTSS_MINFILTER, i->second.minFilter);
|
||||
glw_state->device->SetTextureStageState(1, D3DTSS_MIPFILTER, i->second.mipFilter);
|
||||
glw_state->device->SetTextureStageState(1, D3DTSS_MAGFILTER, i->second.magFilter);
|
||||
glw_state->device->SetTextureStageState(1, D3DTSS_ADDRESSU, i->second.wrapU);
|
||||
glw_state->device->SetTextureStageState(1, D3DTSS_ADDRESSV, i->second.wrapV);
|
||||
|
||||
glw_state->device->SetRenderState(D3DRS_SPECULARENABLE, true);
|
||||
|
||||
glw_state->device->SetPixelShader(m_dwPixelShaderBump);
|
||||
glw_state->device->SetVertexShader(m_dwVertexShaderBump);
|
||||
|
||||
ProcessVertices(NULL);
|
||||
|
||||
D3DXVECTOR4 vAmbient, vDiffuse, vLightDir;
|
||||
|
||||
if (backEnd.currentEntity && (backEnd.currentEntity->e.hModel||backEnd.currentEntity->e.ghoul2) )
|
||||
{
|
||||
if(tess.shader->stages[0].rgbGen == CGEN_LIGHTING_DIFFUSE_ENTITY)
|
||||
{
|
||||
vAmbient.x = (backEnd.currentEntity->ambientLight[0] / 255.f) * (backEnd.currentEntity->e.shaderRGBA[0] / 255.0);
|
||||
vAmbient.y = (backEnd.currentEntity->ambientLight[1] / 255.f) * (backEnd.currentEntity->e.shaderRGBA[1] / 255.0);
|
||||
vAmbient.z = (backEnd.currentEntity->ambientLight[2] / 255.f) * (backEnd.currentEntity->e.shaderRGBA[2] / 255.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
vAmbient.x = backEnd.currentEntity->ambientLight[0] / 255.f;
|
||||
vAmbient.y = backEnd.currentEntity->ambientLight[1] / 255.f;
|
||||
vAmbient.z = backEnd.currentEntity->ambientLight[2] / 255.f;
|
||||
}
|
||||
|
||||
vDiffuse.x = backEnd.currentEntity->directedLight[0] / 255.f;
|
||||
vDiffuse.y = backEnd.currentEntity->directedLight[1] / 255.f;
|
||||
vDiffuse.z = backEnd.currentEntity->directedLight[2] / 255.f;
|
||||
|
||||
vLightDir.x = DotProduct( backEnd.currentEntity->lightDir, backEnd.currentEntity->e.axis[0] );
|
||||
vLightDir.y = DotProduct( backEnd.currentEntity->lightDir, backEnd.currentEntity->e.axis[1] );
|
||||
vLightDir.z = DotProduct( backEnd.currentEntity->lightDir, backEnd.currentEntity->e.axis[2] );
|
||||
}
|
||||
else
|
||||
{
|
||||
vec3_t sundir;
|
||||
sundir[0] = r_sundir_x->value;
|
||||
sundir[1] = r_sundir_y->value;
|
||||
sundir[2] = r_sundir_z->value;
|
||||
|
||||
VectorNormalize(sundir);
|
||||
|
||||
vLightDir.x = sundir[0];//tr.sunDirection[0];
|
||||
vLightDir.y = sundir[1];//tr.sunDirection[1];
|
||||
vLightDir.z = sundir[2];//tr.sunDirection[2];
|
||||
vLightDir.w = 1.0f;
|
||||
|
||||
vAmbient.x = tr.sunAmbient[0] / 1.5f;
|
||||
vAmbient.y = tr.sunAmbient[1] / 1.5f;
|
||||
vAmbient.z = tr.sunAmbient[2] / 1.5f;
|
||||
|
||||
vDiffuse.x = 1.0f;
|
||||
vDiffuse.y = 1.0f;
|
||||
vDiffuse.z = 1.0f;
|
||||
}
|
||||
|
||||
glw_state->device->SetPixelShaderConstant(CP_AMBIENT_COLOR, vAmbient, 1);
|
||||
glw_state->device->SetPixelShaderConstant(CP_DIFFUSE_COLOR, vDiffuse, 1);
|
||||
|
||||
glw_state->device->SetVertexShaderConstant(CV_LIGHT_DIRECTION, vLightDir, 1);
|
||||
|
||||
glw_state->device->SetVertexShaderConstant(CV_CAMERA_DIRECTION, D3DXVECTOR4(tr.viewParms.ori.axis[0][0],
|
||||
tr.viewParms.ori.axis[0][1],
|
||||
tr.viewParms.ori.axis[0][2],
|
||||
1.0f), 1 );
|
||||
|
||||
renderObject_Bump();
|
||||
|
||||
glw_state->device->SetPixelShader( 0 );
|
||||
|
||||
glw_state->device->SetRenderState(D3DRS_SPECULARENABLE, false);
|
||||
}
|
||||
|
||||
|
||||
//bool LightEffects::RenderStaticLights()
|
||||
//{
|
||||
// VVslight_t *sl;
|
||||
//
|
||||
// for(int i = 0; i < tess.numSlights; i++)
|
||||
// {
|
||||
// sl = &VVLightMan.slights[tess.slightBits[i]];
|
||||
//
|
||||
// D3DXVECTOR4 vecLightRange(1.0f / (sl->radius * 2.0f), sl->radius, 1.0f, 1.0f);
|
||||
// glw_state->device->SetVertexShaderConstant(CV_ONE_OVER_LIGHT_RANGE, (void*)&vecLightRange.x, 1);
|
||||
//
|
||||
// glw_state->device->SetVertexShaderConstant(CV_LIGHT_COLOR, &sl->color[0], 1);
|
||||
//
|
||||
// ProcessVertices( NULL, (D3DXVECTOR3*)&sl->origin );
|
||||
//
|
||||
// renderObject_Light();
|
||||
//
|
||||
// tess.currentPass++;
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
//}
|
||||
|
||||
|
||||
void LightEffects::ProcessVertices( D3DXVECTOR3* pPtLightPos )
|
||||
{
|
||||
|
||||
// Just in case, this doesn't always get set
|
||||
glw_state->device->SetTransform( D3DTS_PROJECTION, glw_state->matrixStack[glw_state->MatrixMode_Projection]->GetTop() );
|
||||
|
||||
// Compute the matrix set
|
||||
XGMATRIX matComposite, matProjectionViewport, matWorld;
|
||||
// Get the projection viewport matrix the fixed pipeline uses.
|
||||
// The viewport matrix includes the viewport x,y scale and the
|
||||
// appropriate z scale.
|
||||
glw_state->device->GetProjectionViewportMatrix( &matProjectionViewport );
|
||||
|
||||
D3DVIEWPORT8 view;
|
||||
glw_state->device->GetViewport(&view);
|
||||
|
||||
// Gotta do this to fix an XDK bug
|
||||
// GetProjectionViewportMatrix does not seem to reflect the viewport values
|
||||
// when the viewport is offset
|
||||
matProjectionViewport._31 += view.X;
|
||||
matProjectionViewport._32 += view.Y;
|
||||
|
||||
XGMatrixMultiply( &matComposite, (XGMATRIX*)glw_state->matrixStack[glwstate_t::MatrixMode_Model]->GetTop(), &matProjectionViewport );
|
||||
|
||||
// Transpose and set the composite matrix.
|
||||
XGMatrixTranspose( &matComposite, &matComposite );
|
||||
glw_state->device->SetVertexShaderConstant( CV_WORLDVIEWPROJ_0, &matComposite, 4 );
|
||||
|
||||
if (pPtLightPos)
|
||||
glw_state->device->SetVertexShaderConstant( CV_LIGHT_POSITION, pPtLightPos, 1 );
|
||||
|
||||
// Set viewport offsets.
|
||||
float fViewportOffsets[4] = { 0.53125f, 0.53125f, 0.0f, 0.0f };
|
||||
glw_state->device->SetVertexShaderConstant( CV_VIEWPORT_OFFSETS, &fViewportOffsets, 1 );
|
||||
|
||||
// Set common constants
|
||||
glw_state->device->SetVertexShaderConstant(CV_ONE, D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f), 1);
|
||||
glw_state->device->SetVertexShaderConstant(CV_HALF, D3DXVECTOR4(0.5f, 0.5f, 0.5f, 0.5f), 1);
|
||||
}
|
||||
|
||||
|
||||
inline D3DCOLOR VectorToRGBA( const D3DXVECTOR3* v, FLOAT fHeight = 1.0f )
|
||||
{
|
||||
D3DCOLOR r = (D3DCOLOR)( ( v->x + 1.0f ) * 127.5f );
|
||||
D3DCOLOR g = (D3DCOLOR)( ( v->y + 1.0f ) * 127.5f );
|
||||
D3DCOLOR b = (D3DCOLOR)( ( v->z + 1.0f ) * 127.5f );
|
||||
D3DCOLOR a = (D3DCOLOR)( 255.0f * fHeight );
|
||||
return( (a<<24L) + (r<<16L) + (g<<8L) + (b<<0L) );
|
||||
}
|
||||
|
||||
|
||||
bool LightEffects::CreateNormalizationCubeMap( DWORD dwSize, LPDIRECT3DCUBETEXTURE8* ppCubeMap )
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// Create the cube map
|
||||
if( FAILED( hr = glw_state->device->CreateCubeTexture( dwSize, 1, 0, D3DFMT_X8R8G8B8,
|
||||
D3DPOOL_DEFAULT, ppCubeMap ) ) )
|
||||
return false;
|
||||
|
||||
// Allocate temp space for swizzling the cubemap surfaces
|
||||
DWORD* pSourceBits = new DWORD[ dwSize * dwSize ];
|
||||
|
||||
// Fill all six sides of the cubemap
|
||||
for( DWORD i=0; i<6; i++ )
|
||||
{
|
||||
// Lock the i'th cubemap surface
|
||||
LPDIRECT3DSURFACE8 pCubeMapFace;
|
||||
(*ppCubeMap)->GetCubeMapSurface( (D3DCUBEMAP_FACES)i, 0, &pCubeMapFace );
|
||||
|
||||
// Write the RGBA-encoded normals to the surface pixels
|
||||
DWORD* pPixel = pSourceBits;
|
||||
D3DXVECTOR3 n;
|
||||
FLOAT w, h;
|
||||
|
||||
for( DWORD y = 0; y < dwSize; y++ )
|
||||
{
|
||||
h = (FLOAT)y / (FLOAT)(dwSize-1); // 0 to 1
|
||||
h = ( h * 2.0f ) - 1.0f; // -1 to 1
|
||||
|
||||
for( DWORD x = 0; x < dwSize; x++ )
|
||||
{
|
||||
w = (FLOAT)x / (FLOAT)(dwSize-1); // 0 to 1
|
||||
w = ( w * 2.0f ) - 1.0f; // -1 to 1
|
||||
|
||||
// Calc the normal for this texel
|
||||
switch( i )
|
||||
{
|
||||
case D3DCUBEMAP_FACE_POSITIVE_X: // +x
|
||||
n.x = +1.0;
|
||||
n.y = -h;
|
||||
n.z = -w;
|
||||
break;
|
||||
|
||||
case D3DCUBEMAP_FACE_NEGATIVE_X: // -x
|
||||
n.x = -1.0;
|
||||
n.y = -h;
|
||||
n.z = +w;
|
||||
break;
|
||||
|
||||
case D3DCUBEMAP_FACE_POSITIVE_Y: // y
|
||||
n.x = +w;
|
||||
n.y = +1.0;
|
||||
n.z = +h;
|
||||
break;
|
||||
|
||||
case D3DCUBEMAP_FACE_NEGATIVE_Y: // -y
|
||||
n.x = +w;
|
||||
n.y = -1.0;
|
||||
n.z = -h;
|
||||
break;
|
||||
|
||||
case D3DCUBEMAP_FACE_POSITIVE_Z: // +z
|
||||
n.x = +w;
|
||||
n.y = -h;
|
||||
n.z = +1.0;
|
||||
break;
|
||||
|
||||
case D3DCUBEMAP_FACE_NEGATIVE_Z: // -z
|
||||
n.x = -w;
|
||||
n.y = -h;
|
||||
n.z = -1.0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Store the normal as an RGBA color
|
||||
D3DXVec3Normalize( &n, &n );
|
||||
*pPixel++ = VectorToRGBA( &n );
|
||||
}
|
||||
}
|
||||
|
||||
// Swizzle the result into the cubemap face surface
|
||||
D3DLOCKED_RECT lock;
|
||||
pCubeMapFace->LockRect( &lock, 0, 0L );
|
||||
XGSwizzleRect( pSourceBits, 0, NULL, lock.pBits, dwSize, dwSize,
|
||||
NULL, sizeof(DWORD) );
|
||||
pCubeMapFace->UnlockRect();
|
||||
|
||||
// Release the cubemap face
|
||||
pCubeMapFace->Release();
|
||||
}
|
||||
|
||||
// Free temp space
|
||||
if( pSourceBits )
|
||||
delete [] pSourceBits;
|
||||
pSourceBits = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif // VV_LIGHTING
|
||||
52
codemp/win32/win_lighteffects.h
Normal file
52
codemp/win32/win_lighteffects.h
Normal file
@@ -0,0 +1,52 @@
|
||||
//
|
||||
//
|
||||
// win_lightefects.h
|
||||
//
|
||||
// Declaration of class for pixel shader light effects
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
#ifndef _WIN_LIGHTEFFECTS_H_
|
||||
#define _WIN_LIGHTEFFECTS_H_
|
||||
|
||||
|
||||
class LightEffects
|
||||
{
|
||||
public:
|
||||
LPDIRECT3DCUBETEXTURE8 m_pCubeMap; // Normalization cubemap
|
||||
LPDIRECT3DTEXTURE8 m_pBumpMap;
|
||||
// LPDIRECT3DTEXTURE8 m_pSpecularMap;
|
||||
LPDIRECT3DVOLUMETEXTURE8 m_pFalloffMap;
|
||||
DWORD m_dwVertexShaderLight;
|
||||
DWORD m_dwPixelShaderLight;
|
||||
/*DWORD m_dwVertexShaderSpecular_Dynamic;
|
||||
DWORD m_dwPixelShaderSpecular_Dynamic;
|
||||
DWORD m_dwVertexShaderSpecular_Static;
|
||||
DWORD m_dwPixelShaderSpecular_Static;*/
|
||||
DWORD m_dwVertexShaderEnvironment;
|
||||
DWORD m_dwVertexShaderBump;
|
||||
DWORD m_dwPixelShaderBump;
|
||||
bool m_bInLightPhase;
|
||||
bool m_bInitialized;
|
||||
|
||||
public:
|
||||
LightEffects();
|
||||
virtual ~LightEffects();
|
||||
|
||||
bool Initialize();
|
||||
void ProcessVertices(D3DXVECTOR3* pPtLightPos);
|
||||
bool RenderDynamicLights();
|
||||
/*bool RenderStaticLights();
|
||||
void RenderSpecular();
|
||||
bool RenderSpecular_Dynamic();
|
||||
bool RenderSpecular_Static();*/
|
||||
bool RenderEnvironment();
|
||||
void RenderBump();
|
||||
bool CreateNormalizationCubeMap( DWORD dwSize, LPDIRECT3DCUBETEXTURE8* ppCubeMap );
|
||||
void StartLightPhase();
|
||||
void EndLightPhase();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
85
codemp/win32/win_local.h
Normal file
85
codemp/win32/win_local.h
Normal file
@@ -0,0 +1,85 @@
|
||||
// win_local.h: Win32-specific Quake3 header file
|
||||
|
||||
#if defined (_MSC_VER) && (_MSC_VER >= 1200)
|
||||
#pragma warning(disable : 4201)
|
||||
#pragma warning( push )
|
||||
#endif
|
||||
//#include <windows.h>
|
||||
#include "../qcommon/platform.h"
|
||||
#if defined (_MSC_VER) && (_MSC_VER >= 1200)
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
|
||||
#ifndef _XBOX
|
||||
#define DIRECTINPUT_VERSION 0x0800 //[ 0x0300 | 0x0500 | 0x0700 | 0x0800 ]
|
||||
#include <dinput.h>
|
||||
#include <dsound.h>
|
||||
#include <winsock.h>
|
||||
#include <wsipx.h>
|
||||
#endif
|
||||
|
||||
void IN_MouseEvent (int mstate);
|
||||
|
||||
void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr );
|
||||
|
||||
void Sys_CreateConsole( void );
|
||||
void Sys_DestroyConsole( void );
|
||||
|
||||
char *Sys_ConsoleInput (void);
|
||||
|
||||
qboolean Sys_GetPacket ( netadr_t *net_from, msg_t *net_message );
|
||||
qboolean Sys_GetBroadcastPacket( msg_t *net_message );
|
||||
|
||||
// Input subsystem
|
||||
|
||||
void IN_Init (void);
|
||||
void IN_Shutdown (void);
|
||||
void IN_JoystickCommands (void);
|
||||
|
||||
void IN_Move (usercmd_t *cmd);
|
||||
// add additional non keyboard / non mouse movement on top of the keyboard move cmd
|
||||
|
||||
void IN_DeactivateWin32Mouse( void);
|
||||
|
||||
void IN_Activate (qboolean active);
|
||||
void IN_Frame (void);
|
||||
|
||||
// window procedure
|
||||
#ifndef _XBOX
|
||||
LONG WINAPI MainWndProc (
|
||||
HWND hWnd,
|
||||
UINT uMsg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
#endif
|
||||
|
||||
void Conbuf_AppendText( const char *msg );
|
||||
|
||||
void SNDDMA_Activate( qboolean bAppActive );
|
||||
int SNDDMA_InitDS ();
|
||||
|
||||
#ifndef _XBOX
|
||||
typedef struct
|
||||
{
|
||||
|
||||
HINSTANCE reflib_library; // Handle to refresh DLL
|
||||
qboolean reflib_active;
|
||||
|
||||
HWND hWnd;
|
||||
HINSTANCE hInstance;
|
||||
qboolean activeApp;
|
||||
qboolean isMinimized;
|
||||
OSVERSIONINFO osversion;
|
||||
|
||||
// when we get a windows message, we store the time off so keyboard processing
|
||||
// can know the exact time of an event
|
||||
unsigned sysMsgTime;
|
||||
} WinVars_t;
|
||||
|
||||
extern WinVars_t g_wv;
|
||||
#endif
|
||||
|
||||
|
||||
#define MAX_QUED_EVENTS 256
|
||||
#define MASK_QUED_EVENTS ( MAX_QUED_EVENTS - 1 )
|
||||
|
||||
1661
codemp/win32/win_main.cpp
Normal file
1661
codemp/win32/win_main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
357
codemp/win32/win_main_common.cpp
Normal file
357
codemp/win32/win_main_common.cpp
Normal file
@@ -0,0 +1,357 @@
|
||||
// win_main.h
|
||||
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "../client/client.h"
|
||||
#include "win_local.h"
|
||||
#include "resource.h"
|
||||
|
||||
#ifndef _GAMECUBE
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
#ifdef _XBOX
|
||||
#include "../cgame/cg_local.h"
|
||||
#include "../client/cl_data.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//#define SPANK_MONKEYS //----(SA) commented out for running net developer release builds
|
||||
int sys_monkeySpank;
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_MonkeyShouldBeSpanked
|
||||
==================
|
||||
*/
|
||||
int Sys_MonkeyShouldBeSpanked( void ) {
|
||||
return sys_monkeySpank;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_FunctionCmp
|
||||
==================
|
||||
*/
|
||||
int Sys_FunctionCmp(void *f1, void *f2) {
|
||||
|
||||
int i, j, l;
|
||||
byte func_end[32] = {0xC3, 0x90, 0x90, 0x00};
|
||||
byte *ptr, *ptr2;
|
||||
byte *f1_ptr, *f2_ptr;
|
||||
|
||||
ptr = (byte *) f1;
|
||||
if (*(byte *)ptr == 0xE9) {
|
||||
//Com_Printf("f1 %p1 jmp %d\n", (int *) f1, *(int*)(ptr+1));
|
||||
f1_ptr = (byte*)(((byte*)f1) + (*(int *)(ptr+1)) + 5);
|
||||
}
|
||||
else {
|
||||
f1_ptr = ptr;
|
||||
}
|
||||
//Com_Printf("f1 ptr %p\n", f1_ptr);
|
||||
|
||||
ptr = (byte *) f2;
|
||||
if (*(byte *)ptr == 0xE9) {
|
||||
//Com_Printf("f2 %p jmp %d\n", (int *) f2, *(int*)(ptr+1));
|
||||
f2_ptr = (byte*)(((byte*)f2) + (*(int *)(ptr+1)) + 5);
|
||||
}
|
||||
else {
|
||||
f2_ptr = ptr;
|
||||
}
|
||||
//Com_Printf("f2 ptr %p\n", f2_ptr);
|
||||
|
||||
#ifdef _DEBUG
|
||||
sprintf((char *)func_end, "%c%c%c%c%c%c%c", 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3);
|
||||
#endif
|
||||
for (i = 0; i < 1024; i++) {
|
||||
for (j = 0; func_end[j]; j++) {
|
||||
if (f1_ptr[i+j] != func_end[j])
|
||||
break;
|
||||
}
|
||||
if (!func_end[j]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
l = i + 7;
|
||||
#else
|
||||
l = i + 2;
|
||||
#endif
|
||||
//Com_Printf("function length = %d\n", l);
|
||||
|
||||
for (i = 0; i < l; i++) {
|
||||
// check for a potential function call
|
||||
if (*((byte *) &f1_ptr[i]) == 0xE8) {
|
||||
// get the function pointers in case this really is a function call
|
||||
ptr = (byte *) (((byte *) &f1_ptr[i]) + (*(int *) &f1_ptr[i+1])) + 5;
|
||||
ptr2 = (byte *) (((byte *) &f2_ptr[i]) + (*(int *) &f2_ptr[i+1])) + 5;
|
||||
// if it was a function call and both f1 and f2 call the same function
|
||||
if (ptr == ptr2) {
|
||||
i += 4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (f1_ptr[i] != f2_ptr[i])
|
||||
return qfalse;
|
||||
}
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_FunctionCheckSum
|
||||
==================
|
||||
*/
|
||||
int Sys_FunctionCheckSum(void *f1) {
|
||||
|
||||
int i, j, l;
|
||||
unsigned shermcrap;
|
||||
byte func_end[32] = {0xC3, 0x90, 0x90, 0x00};
|
||||
byte *ptr;
|
||||
byte *f1_ptr;
|
||||
|
||||
ptr = (byte *) f1;
|
||||
if (*(byte *)ptr == 0xE9) {
|
||||
//Com_Printf("f1 %p1 jmp %d\n", (int *) f1, *(int*)(ptr+1));
|
||||
f1_ptr = (byte*)(((byte*)f1) + (*(int *)(ptr+1)) + 5);
|
||||
}
|
||||
else {
|
||||
f1_ptr = ptr;
|
||||
}
|
||||
//Com_Printf("f1 ptr %p\n", f1_ptr);
|
||||
|
||||
#ifdef _DEBUG
|
||||
sprintf((char *)func_end, "%c%c%c%c%c%c%c", 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3);
|
||||
#endif
|
||||
for (i = 0; i < 1024; i++) {
|
||||
for (j = 0; func_end[j]; j++) {
|
||||
if (f1_ptr[i+j] != func_end[j])
|
||||
break;
|
||||
}
|
||||
if (!func_end[j]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
l = i + 7;
|
||||
#else
|
||||
l = i + 2;
|
||||
#endif
|
||||
//Com_Printf("function length = %d\n", l);
|
||||
shermcrap = Com_BlockChecksum( f1_ptr, l );
|
||||
return (int)shermcrap;
|
||||
}
|
||||
|
||||
|
||||
//NOTE TTimo: heavily NON PORTABLE, PLZ DON'T USE
|
||||
// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=447
|
||||
#if 0
|
||||
//----(SA) added
|
||||
/*
|
||||
==============
|
||||
Sys_ShellExecute
|
||||
|
||||
- Windows only
|
||||
|
||||
Performs an operation on a specified file.
|
||||
|
||||
See info on ShellExecute() for details
|
||||
|
||||
==============
|
||||
*/
|
||||
int Sys_ShellExecute(char *op, char *file, qboolean doexit, char *params, char *dir ) {
|
||||
unsigned int retval;
|
||||
char *se_op;
|
||||
|
||||
// set default operation to "open"
|
||||
if(op) se_op = op;
|
||||
else se_op = "open";
|
||||
|
||||
|
||||
// probably need to protect this some in the future so people have
|
||||
// less chance of system invasion with this powerful interface
|
||||
// (okay, not so invasive, but could be annoying/rude)
|
||||
|
||||
|
||||
retval = (UINT)ShellExecute(NULL, se_op, file, params, dir, SW_NORMAL); // only option forced by game is 'sw_normal'
|
||||
|
||||
if( retval <= 32) { // ERROR
|
||||
Com_DPrintf("Sys_ShellExecuteERROR: %d\n", retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
if ( doexit ) {
|
||||
// (SA) this works better for exiting cleanly...
|
||||
Cbuf_ExecuteText( EXEC_APPEND, "quit" );
|
||||
}
|
||||
|
||||
return 999; // success
|
||||
}
|
||||
//----(SA) end
|
||||
#endif
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_BeginProfiling
|
||||
==================
|
||||
*/
|
||||
void Sys_BeginProfiling( void ) {
|
||||
// this is just used on the mac build
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_DefaultCDPath
|
||||
==============
|
||||
*/
|
||||
char *Sys_DefaultCDPath( void ) {
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_DefaultBasePath
|
||||
==============
|
||||
*/
|
||||
char *Sys_DefaultBasePath( void ) {
|
||||
return Sys_Cwd();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
EVENT LOOP
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
|
||||
sysEvent_t eventQue[MAX_QUED_EVENTS];
|
||||
int eventHead, eventTail;
|
||||
byte sys_packetReceived[MAX_MSGLEN];
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_QueEvent
|
||||
|
||||
A time of 0 will get the current time
|
||||
Ptr should either be null, or point to a block of data that can
|
||||
be freed by the game later.
|
||||
================
|
||||
*/
|
||||
void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr ) {
|
||||
sysEvent_t *ev;
|
||||
|
||||
#ifdef _XBOX
|
||||
if(ClientManager::splitScreenMode == qtrue)
|
||||
{
|
||||
ev = &ClientManager::ActiveClient().eventQue[ ClientManager::ActiveClient().eventHead & MASK_QUED_EVENTS];
|
||||
if ( ClientManager::ActiveClient().eventHead - ClientManager::ActiveClient().eventTail >= MAX_QUED_EVENTS ) {
|
||||
Com_Printf("Sys_QueEvent: overflow\n");
|
||||
// we are discarding an event, but don't leak memory
|
||||
if ( ev->evPtr ) {
|
||||
Z_Free( ev->evPtr );
|
||||
}
|
||||
ClientManager::ActiveClient().eventTail++;
|
||||
}
|
||||
|
||||
ClientManager::ActiveClient().eventHead++;
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
ev = &eventQue[ eventHead & MASK_QUED_EVENTS ];
|
||||
if ( eventHead - eventTail >= MAX_QUED_EVENTS ) {
|
||||
Com_Printf("Sys_QueEvent: overflow\n");
|
||||
// we are discarding an event, but don't leak memory
|
||||
if ( ev->evPtr ) {
|
||||
Z_Free( ev->evPtr );
|
||||
}
|
||||
eventTail++;
|
||||
}
|
||||
|
||||
eventHead++;
|
||||
|
||||
#ifdef _XBOX
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( time == 0 ) {
|
||||
time = Sys_Milliseconds();
|
||||
}
|
||||
|
||||
ev->evTime = time;
|
||||
ev->evType = type;
|
||||
ev->evValue = value;
|
||||
ev->evValue2 = value2;
|
||||
ev->evPtrLength = ptrLength;
|
||||
ev->evPtr = ptr;
|
||||
}
|
||||
|
||||
|
||||
//================================================================
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_Net_Restart_f
|
||||
|
||||
Restart the network subsystem
|
||||
=================
|
||||
*/
|
||||
void Sys_Net_Restart_f( void ) {
|
||||
// NET_Restart();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=======================================================================
|
||||
|
||||
|
||||
void Sys_InitStreamThread( void ) {
|
||||
}
|
||||
|
||||
void Sys_ShutdownStreamThread( void ) {
|
||||
}
|
||||
|
||||
void Sys_BeginStreamedFile( fileHandle_t f, int readAhead ) {
|
||||
}
|
||||
|
||||
void Sys_EndStreamedFile( fileHandle_t f ) {
|
||||
}
|
||||
|
||||
int Sys_StreamedRead( void *buffer, int size, int count, fileHandle_t f ) {
|
||||
return FS_Read( buffer, size * count, f );
|
||||
}
|
||||
|
||||
void Sys_StreamSeek( fileHandle_t f, int offset, int origin ) {
|
||||
FS_Seek( f, offset, origin );
|
||||
}
|
||||
|
||||
|
||||
void *Sys_InitializeCriticalSection() {
|
||||
return (void*)-1;
|
||||
}
|
||||
|
||||
void Sys_EnterCriticalSection(void *ptr) {
|
||||
}
|
||||
|
||||
void Sys_LeaveCriticalSection(void *ptr) {
|
||||
}
|
||||
|
||||
1017
codemp/win32/win_main_console.cpp
Normal file
1017
codemp/win32/win_main_console.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1235
codemp/win32/win_net.cpp
Normal file
1235
codemp/win32/win_net.cpp
Normal file
File diff suppressed because it is too large
Load Diff
747
codemp/win32/win_net_xbox.cpp
Normal file
747
codemp/win32/win_net_xbox.cpp
Normal file
@@ -0,0 +1,747 @@
|
||||
// net_wins.c
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
#include "win_local.h"
|
||||
#include "../xbox/XBLive.h"
|
||||
|
||||
static WSADATA winsockdata;
|
||||
static qboolean winsockInitialized = qfalse;
|
||||
static qboolean networkingEnabled = qfalse;
|
||||
|
||||
static cvar_t *net_noudp;
|
||||
|
||||
static SOCKET v_socket = INVALID_SOCKET;
|
||||
static SOCKET ip_socket = INVALID_SOCKET;
|
||||
static SOCKET ip_broadcast_socket = INVALID_SOCKET;
|
||||
|
||||
#define MAX_IPS 16
|
||||
static int numIP;
|
||||
static byte localIP[MAX_IPS][4];
|
||||
|
||||
byte broadcast_nonce[8]; //Used to uniquely identify broadcast messages bound for this server
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_ErrorString
|
||||
====================
|
||||
*/
|
||||
char *NET_ErrorString( void ) {
|
||||
int code;
|
||||
|
||||
code = WSAGetLastError();
|
||||
switch( code ) {
|
||||
case WSAEINTR: return "WSAEINTR";
|
||||
case WSAEBADF: return "WSAEBADF";
|
||||
case WSAEACCES: return "WSAEACCES";
|
||||
case WSAEDISCON: return "WSAEDISCON";
|
||||
case WSAEFAULT: return "WSAEFAULT";
|
||||
case WSAEINVAL: return "WSAEINVAL";
|
||||
case WSAEMFILE: return "WSAEMFILE";
|
||||
case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
|
||||
case WSAEINPROGRESS: return "WSAEINPROGRESS";
|
||||
case WSAEALREADY: return "WSAEALREADY";
|
||||
case WSAENOTSOCK: return "WSAENOTSOCK";
|
||||
case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
|
||||
case WSAEMSGSIZE: return "WSAEMSGSIZE";
|
||||
case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
|
||||
case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
|
||||
case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
|
||||
case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
|
||||
case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
|
||||
case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
|
||||
case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
|
||||
case WSAEADDRINUSE: return "WSAEADDRINUSE";
|
||||
case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
|
||||
case WSAENETDOWN: return "WSAENETDOWN";
|
||||
case WSAENETUNREACH: return "WSAENETUNREACH";
|
||||
case WSAENETRESET: return "WSAENETRESET";
|
||||
case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR";
|
||||
case WSAECONNRESET: return "WSAECONNRESET";
|
||||
case WSAENOBUFS: return "WSAENOBUFS";
|
||||
case WSAEISCONN: return "WSAEISCONN";
|
||||
case WSAENOTCONN: return "WSAENOTCONN";
|
||||
case WSAESHUTDOWN: return "WSAESHUTDOWN";
|
||||
case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
|
||||
case WSAETIMEDOUT: return "WSAETIMEDOUT";
|
||||
case WSAECONNREFUSED: return "WSAECONNREFUSED";
|
||||
case WSAELOOP: return "WSAELOOP";
|
||||
case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
|
||||
case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
|
||||
case WSASYSNOTREADY: return "WSASYSNOTREADY";
|
||||
case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
|
||||
case WSANOTINITIALISED: return "WSANOTINITIALISED";
|
||||
case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
|
||||
case WSATRY_AGAIN: return "WSATRY_AGAIN";
|
||||
case WSANO_RECOVERY: return "WSANO_RECOVERY";
|
||||
case WSANO_DATA: return "WSANO_DATA";
|
||||
case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
|
||||
default: return "NO ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
void NetadrToSockadr( netadr_t *a, struct sockaddr *s ) {
|
||||
memset( s, 0, sizeof(*s) );
|
||||
|
||||
if( a->type == NA_BROADCAST ) {
|
||||
((struct sockaddr_in *)s)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
|
||||
}
|
||||
else if( a->type == NA_IP ) {
|
||||
((struct sockaddr_in *)s)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SockadrToNetadr( struct sockaddr *s, netadr_t *a ) {
|
||||
if (s->sa_family == AF_INET) {
|
||||
a->type = NA_IP;
|
||||
*(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
|
||||
a->port = ((struct sockaddr_in *)s)->sin_port;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
Sys_StringToAdr
|
||||
|
||||
idnewt
|
||||
192.246.40.70
|
||||
12121212.121212121212
|
||||
=============
|
||||
*/
|
||||
#define DO(src,dest) \
|
||||
copy[0] = s[src]; \
|
||||
copy[1] = s[src + 1]; \
|
||||
sscanf (copy, "%x", &val); \
|
||||
((struct sockaddr_ipx *)sadr)->dest = val
|
||||
|
||||
qboolean Sys_StringToSockaddr( const char *s, struct sockaddr *sadr ) {
|
||||
|
||||
memset( sadr, 0, sizeof( *sadr ) );
|
||||
|
||||
((struct sockaddr_in *)sadr)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)sadr)->sin_port = 0;
|
||||
|
||||
if( s[0] >= '0' && s[0] <= '9' ) {
|
||||
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(s);
|
||||
} else {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
#undef DO
|
||||
|
||||
/*
|
||||
=============
|
||||
Sys_StringToAdr
|
||||
|
||||
idnewt
|
||||
192.246.40.70
|
||||
=============
|
||||
*/
|
||||
qboolean Sys_StringToAdr( const char *s, netadr_t *a ) {
|
||||
struct sockaddr sadr;
|
||||
|
||||
if ( !Sys_StringToSockaddr( s, &sadr ) ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
SockadrToNetadr( &sadr, a );
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_GetPacket
|
||||
|
||||
Never called by the game logic, just the system event queing
|
||||
==================
|
||||
*/
|
||||
qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message )
|
||||
{
|
||||
SOCKET net_socket = ip_socket;
|
||||
|
||||
struct sockaddr from;
|
||||
int fromlen = sizeof(from);
|
||||
|
||||
int ret = recvfrom( net_socket, (char *)net_message->data, net_message->maxsize, 0, &from, &fromlen );
|
||||
|
||||
if (ret == SOCKET_ERROR)
|
||||
{
|
||||
int err = WSAGetLastError();
|
||||
|
||||
if( err == WSAEWOULDBLOCK || err == WSAECONNRESET ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
Com_Printf( "NET_GetPacket: %s\n", NET_ErrorString() );
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
memset( ((struct sockaddr_in *)&from)->sin_zero, 0, 8 );
|
||||
SockadrToNetadr( &from, net_from );
|
||||
|
||||
net_message->readcount = 0;
|
||||
|
||||
if( ret == net_message->maxsize ) {
|
||||
Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) );
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
net_message->cursize = ret;
|
||||
return qtrue;
|
||||
|
||||
}
|
||||
|
||||
|
||||
qboolean Sys_GetBroadcastPacket( msg_t *net_message )
|
||||
{
|
||||
SOCKET net_socket = ip_broadcast_socket;
|
||||
|
||||
struct sockaddr from;
|
||||
int fromlen = sizeof(from);
|
||||
|
||||
int ret = recvfrom( net_socket, (char*)net_message->data, net_message->maxsize, 0, &from, &fromlen );
|
||||
|
||||
if (ret == SOCKET_ERROR)
|
||||
{
|
||||
int err = WSAGetLastError();
|
||||
|
||||
if( err == WSAEWOULDBLOCK ) {//|| err == WSAECONNRESET ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
Com_Printf( "NET_GetPacket: %s\n", NET_ErrorString() );
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
net_message->readcount = 0;
|
||||
|
||||
if( ret == net_message->maxsize ) {
|
||||
Com_Printf("Oversized broadcast packet\n");
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
net_message->cursize = ret;
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_SendVoicePacket
|
||||
==================
|
||||
*/
|
||||
void Sys_SendVoicePacket( int length, const void *data, netadr_t to ) {
|
||||
int ret;
|
||||
struct sockaddr addr;
|
||||
|
||||
// check for valid packet intentions (direct send only!)
|
||||
if( to.type != NA_IP ) {
|
||||
Com_Error( ERR_FATAL, "Sys_SendVoicePacket: bad address type" );
|
||||
return;
|
||||
}
|
||||
|
||||
// check we have our voice socket set up
|
||||
if( v_socket == INVALID_SOCKET ) {
|
||||
return;
|
||||
}
|
||||
|
||||
NetadrToSockadr( &to, &addr );
|
||||
ret = sendto( v_socket, (const char *)data, length, 0, &addr, sizeof(addr) );
|
||||
|
||||
if( ret == SOCKET_ERROR ) {
|
||||
int err = WSAGetLastError();
|
||||
|
||||
// wouldblock is silent
|
||||
if( err == WSAEWOULDBLOCK ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Com_DPrintf( "NET_SendVoicePacket: %s\n", NET_ErrorString() );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_SendPacket
|
||||
==================
|
||||
*/
|
||||
bool Sys_SendPacket( int length, const void *data, netadr_t to ) {
|
||||
int ret;
|
||||
struct sockaddr addr;
|
||||
SOCKET net_socket;
|
||||
|
||||
if( to.type == NA_BROADCAST ) {
|
||||
net_socket = ip_broadcast_socket;
|
||||
}
|
||||
else if( to.type == NA_IP ) {
|
||||
net_socket = ip_socket;
|
||||
}
|
||||
else {
|
||||
Com_Error( ERR_FATAL, "Sys_SendPacket: bad address type" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( net_socket == INVALID_SOCKET) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NetadrToSockadr( &to, &addr );
|
||||
|
||||
ret = sendto( net_socket, (const char *)data, length, 0, &addr, sizeof(addr) );
|
||||
|
||||
if( ret == SOCKET_ERROR ) {
|
||||
int err = WSAGetLastError();
|
||||
|
||||
// wouldblock is silent
|
||||
if( err == WSAEWOULDBLOCK ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// some PPP links do not allow broadcasts and return an error
|
||||
// if( (err == WSAEADDRNOTAVAIL) && ( to.type == NA_BROADCAST ) ) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
#ifndef FINAL_BUILD
|
||||
Com_Printf( "NET_SendPacket: %s\n", NET_ErrorString() );
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_SendBroadcastPacket
|
||||
==================
|
||||
*/
|
||||
void Sys_SendBroadcastPacket( int length, const void *data )
|
||||
{
|
||||
// Setup the broadcast address
|
||||
netadr_t to;
|
||||
Com_Memset( &to, 0, sizeof( to ) );
|
||||
to.port = BigShort( (short)(PORT_BROADCAST) );
|
||||
to.type = NA_BROADCAST;
|
||||
|
||||
Sys_SendPacket(length, data, to);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_IsLANAddress
|
||||
|
||||
LAN clients will have their rate var ignored
|
||||
==================
|
||||
*/
|
||||
qboolean Sys_IsLANAddress( netadr_t adr ) {
|
||||
int i;
|
||||
|
||||
if( adr.type == NA_LOOPBACK ) {
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if( adr.type != NA_IP ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// choose which comparison to use based on the class of the address being tested
|
||||
// any local adresses of a different class than the address being tested will fail based on the first byte
|
||||
|
||||
if( adr.ip[0] == 127 && adr.ip[1] == 0 && adr.ip[2] == 0 && adr.ip[3] == 1 ) {
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if ( (adr.ip[0] == 192 && adr.ip[1] == 168) ||
|
||||
(adr.ip[0] == 10 && adr.ip[1] == 100) ||
|
||||
(adr.ip[0] == 172 && adr.ip[1] == 16) )
|
||||
{
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
// Class A
|
||||
if( (adr.ip[0] & 0x80) == 0x00 ) {
|
||||
for ( i = 0 ; i < numIP ; i++ ) {
|
||||
if( adr.ip[0] == localIP[i][0] ) {
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
// the RFC1918 class a block will pass the above test
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// Class B
|
||||
if( (adr.ip[0] & 0xc0) == 0x80 ) {
|
||||
for ( i = 0 ; i < numIP ; i++ ) {
|
||||
if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] ) {
|
||||
return qtrue;
|
||||
}
|
||||
// also check against the RFC1918 class b blocks
|
||||
if( adr.ip[0] == 172 && localIP[i][0] == 172 && (adr.ip[1] & 0xf0) == 16 && (localIP[i][1] & 0xf0) == 16 ) {
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
return qfalse;
|
||||
}
|
||||
*/
|
||||
//we only look at class C since ISPs and Universities are using class A but we don't want to consider them on the same LAN.
|
||||
|
||||
// Class C
|
||||
for ( i = 0 ; i < numIP ; i++ ) {
|
||||
if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] && adr.ip[2] == localIP[i][2] ) {
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
//check for both on a local lan type thing
|
||||
if( adr.ip[0] == 10 && localIP[i][0] == 10 )
|
||||
{
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
// also check against the RFC1918 class c blocks
|
||||
// if( adr.ip[0] == 192 && localIP[i][0] == 192 && adr.ip[1] == 168 && localIP[i][1] == 168 ) {
|
||||
// return qtrue;
|
||||
// }
|
||||
}
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_ShowIP
|
||||
==================
|
||||
*/
|
||||
void Sys_ShowIP(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < numIP; i++) {
|
||||
Com_Printf( "IP: %i.%i.%i.%i\n", localIP[i][0], localIP[i][1], localIP[i][2], localIP[i][3] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_IPSocket
|
||||
====================
|
||||
*/
|
||||
int NET_IPSocket( char *net_interface, int port, bool broadcast ) {
|
||||
SOCKET newsocket;
|
||||
struct sockaddr_in address;
|
||||
qboolean _true = qtrue;
|
||||
int i = 1;
|
||||
int err;
|
||||
|
||||
if( net_interface ) {
|
||||
Com_Printf( "Opening IP socket: %s:%i\n", net_interface, port );
|
||||
}
|
||||
else {
|
||||
Com_Printf( "Opening IP socket: localhost:%i\n", port );
|
||||
}
|
||||
|
||||
if( ( newsocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) {
|
||||
err = WSAGetLastError();
|
||||
if( err != WSAEAFNOSUPPORT ) {
|
||||
Com_Printf( "WARNING: UDP_OpenSocket: socket: %s\n", NET_ErrorString() );
|
||||
}
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
// make it non-blocking
|
||||
if( ioctlsocket( newsocket, FIONBIO, (unsigned long *)&_true ) == SOCKET_ERROR ) {
|
||||
Com_Printf( "WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString() );
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
// make it broadcast capable - but only if requested. we don't want our main socket to get bogged down:
|
||||
if (!broadcast)
|
||||
i = 0;
|
||||
if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i) ) == SOCKET_ERROR ) {
|
||||
Com_Printf( "WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() );
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
i = 1;
|
||||
|
||||
if( !net_interface || !net_interface[0] || !Q_stricmp(net_interface, "localhost") ) {
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
else {
|
||||
Sys_StringToSockaddr( net_interface, (struct sockaddr *)&address );
|
||||
}
|
||||
|
||||
if( port == PORT_ANY ) {
|
||||
address.sin_port = 0;
|
||||
}
|
||||
else {
|
||||
address.sin_port = htons( (short)port );
|
||||
}
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
|
||||
if( bind( newsocket, (const struct sockaddr *)&address, sizeof(address) ) == SOCKET_ERROR ) {
|
||||
Com_Printf( "WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString() );
|
||||
closesocket( newsocket );
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
return newsocket;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
NET_GetLocalAddress
|
||||
=====================
|
||||
*/
|
||||
// Xbox version supports the force option, so we can prime the
|
||||
// system and hopefully be getting an IP while Com_Init() is running.
|
||||
void NET_GetLocalAddress( bool force )
|
||||
{
|
||||
XNADDR xnMyAddr;
|
||||
DWORD dwStatus;
|
||||
do
|
||||
{
|
||||
// Repeat while pending; OK to do other work in this loop
|
||||
dwStatus = XNetGetTitleXnAddr( &xnMyAddr );
|
||||
} while( dwStatus == XNET_GET_XNADDR_PENDING && force );
|
||||
|
||||
// Error checking
|
||||
if( dwStatus == XNET_GET_XNADDR_NONE )
|
||||
{
|
||||
// If this wasn't the final (necessary) call, then don't worry
|
||||
if( force )
|
||||
assert(!"Error getting XBox title address.");
|
||||
return;
|
||||
}
|
||||
|
||||
*(u_long*)&localIP[0] = xnMyAddr.ina.S_un.S_addr;
|
||||
*(u_long*)localIP[1] = 0;
|
||||
*(u_long*)localIP[2] = 0;
|
||||
*(u_long*)localIP[3] = 0;
|
||||
|
||||
Com_Printf( "IP: %i.%i.%i.%i\n", localIP[0], localIP[1], localIP[2], localIP[3] );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_OpenIP
|
||||
====================
|
||||
*/
|
||||
void NET_OpenIP( void ) {
|
||||
cvar_t *ip;
|
||||
int port;
|
||||
int i;
|
||||
|
||||
ip = Cvar_Get( "net_ip", "localhost", CVAR_LATCH );
|
||||
|
||||
// Don't do the silly quake thing where we keep trying new port numbers.
|
||||
// We can't run more than one server per xbox. And make sure that our ip socket
|
||||
// is NOT broadcast capable, so that the game logic doesn't get confused.
|
||||
ip_socket = NET_IPSocket( ip->string, PORT_SERVER, false );
|
||||
if ( ip_socket ) {
|
||||
Cvar_SetValue( "net_port", PORT_SERVER );
|
||||
NET_GetLocalAddress( false );
|
||||
return;
|
||||
}
|
||||
|
||||
Com_Printf( "WARNING: Couldn't allocate IP port\n");
|
||||
}
|
||||
|
||||
void NET_OpenBroadcastIP()
|
||||
{
|
||||
// This s the only socket that will be used for broadcast
|
||||
// (session discovery on system link)
|
||||
ip_broadcast_socket = NET_IPSocket(NULL, PORT_BROADCAST, true);
|
||||
}
|
||||
|
||||
|
||||
//===================================================================
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_GetCvars
|
||||
====================
|
||||
*/
|
||||
static qboolean NET_GetCvars( void ) {
|
||||
qboolean modified;
|
||||
|
||||
modified = qfalse;
|
||||
|
||||
if( net_noudp && net_noudp->modified ) {
|
||||
modified = qtrue;
|
||||
}
|
||||
net_noudp = Cvar_Get( "net_noudp", "0", CVAR_LATCH | CVAR_ARCHIVE );
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_Config
|
||||
====================
|
||||
*/
|
||||
void NET_Config( qboolean enableNetworking ) {
|
||||
qboolean modified;
|
||||
qboolean stop;
|
||||
qboolean start;
|
||||
|
||||
// get any latched changes to cvars
|
||||
modified = NET_GetCvars();
|
||||
|
||||
if( net_noudp->integer ) {
|
||||
enableNetworking = qfalse;
|
||||
}
|
||||
|
||||
// if enable state is the same and no cvars were modified, we have nothing to do
|
||||
if( enableNetworking == networkingEnabled && !modified ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( enableNetworking == networkingEnabled ) {
|
||||
if( enableNetworking ) {
|
||||
stop = qtrue;
|
||||
start = qtrue;
|
||||
}
|
||||
else {
|
||||
stop = qfalse;
|
||||
start = qfalse;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( enableNetworking ) {
|
||||
stop = qfalse;
|
||||
start = qtrue;
|
||||
}
|
||||
else {
|
||||
stop = qtrue;
|
||||
start = qfalse;
|
||||
}
|
||||
networkingEnabled = enableNetworking;
|
||||
}
|
||||
|
||||
if( stop ) {
|
||||
if ( ip_socket && ip_socket != INVALID_SOCKET ) {
|
||||
closesocket( ip_socket );
|
||||
ip_socket = INVALID_SOCKET;
|
||||
}
|
||||
if ( ip_broadcast_socket && ip_broadcast_socket != INVALID_SOCKET ) {
|
||||
closesocket( ip_broadcast_socket );
|
||||
ip_broadcast_socket = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
if( start ) {
|
||||
if (! net_noudp->integer ) {
|
||||
NET_OpenIP();
|
||||
NET_OpenBroadcastIP();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_Init
|
||||
====================
|
||||
*/
|
||||
void NET_Init( void ) {
|
||||
|
||||
// Run NetStartup with security bypassed
|
||||
// this allows us to communicate with PCs while developing
|
||||
XNetStartupParams xnsp;
|
||||
ZeroMemory( &xnsp, sizeof(xnsp) );
|
||||
xnsp.cfgSizeOfStruct = sizeof(xnsp);
|
||||
|
||||
#ifndef FINAL_BUILD
|
||||
xnsp.cfgFlags |= XNET_STARTUP_BYPASS_SECURITY;
|
||||
#endif
|
||||
|
||||
INT err = XNetStartup( &xnsp );
|
||||
if( err != NO_ERROR ) {
|
||||
Com_Printf( "ERROR: XNetStartup Failed: %d\n", err );
|
||||
return;
|
||||
}
|
||||
|
||||
int r = WSAStartup( MAKEWORD(2,2), &winsockdata );
|
||||
if( r ) {
|
||||
Com_Printf( "WARNING: Winsock initialization failed, returned %d\n", r );
|
||||
return;
|
||||
}
|
||||
|
||||
//Initialize the broadcast nonce
|
||||
XNetRandom( broadcast_nonce, sizeof(broadcast_nonce) );
|
||||
|
||||
winsockInitialized = qtrue;
|
||||
Com_Printf( "Winsock Initialized\n" );
|
||||
|
||||
// this is really just to get the cvars registered
|
||||
NET_GetCvars();
|
||||
|
||||
NET_Config( qtrue );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_Shutdown
|
||||
====================
|
||||
*/
|
||||
void NET_Shutdown( void ) {
|
||||
if ( !winsockInitialized ) {
|
||||
return;
|
||||
}
|
||||
|
||||
NET_Config( qfalse );
|
||||
WSACleanup();
|
||||
winsockInitialized = qfalse;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_Sleep
|
||||
|
||||
sleeps msec or until net socket is ready
|
||||
====================
|
||||
*/
|
||||
void NET_Sleep( int msec ) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_Restart_f
|
||||
====================
|
||||
*/
|
||||
void NET_Restart( void ) {
|
||||
NET_Config( networkingEnabled );
|
||||
}
|
||||
1337
codemp/win32/win_qal_xbox.cpp
Normal file
1337
codemp/win32/win_qal_xbox.cpp
Normal file
File diff suppressed because it is too large
Load Diff
4271
codemp/win32/win_qgl.cpp
Normal file
4271
codemp/win32/win_qgl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
6523
codemp/win32/win_qgl_dx8.cpp
Normal file
6523
codemp/win32/win_qgl_dx8.cpp
Normal file
File diff suppressed because it is too large
Load Diff
547
codemp/win32/win_shared.cpp
Normal file
547
codemp/win32/win_shared.cpp
Normal file
@@ -0,0 +1,547 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
#include "win_local.h"
|
||||
#ifndef _XBOX
|
||||
#include <lmerr.h>
|
||||
#include <lmcons.h>
|
||||
#include <lmwksta.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_Milliseconds
|
||||
================
|
||||
*/
|
||||
int Sys_Milliseconds (bool baseTime)
|
||||
{
|
||||
static int sys_timeBase = timeGetTime();
|
||||
int sys_curtime;
|
||||
|
||||
sys_curtime = timeGetTime();
|
||||
if(!baseTime)
|
||||
{
|
||||
sys_curtime -= sys_timeBase;
|
||||
}
|
||||
|
||||
return sys_curtime;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_SnapVector
|
||||
================
|
||||
*/
|
||||
void Sys_SnapVector( float *v )
|
||||
{
|
||||
int i;
|
||||
float f;
|
||||
|
||||
f = *v;
|
||||
__asm fld f;
|
||||
__asm fistp i;
|
||||
*v = i;
|
||||
v++;
|
||||
f = *v;
|
||||
__asm fld f;
|
||||
__asm fistp i;
|
||||
*v = i;
|
||||
v++;
|
||||
f = *v;
|
||||
__asm fld f;
|
||||
__asm fistp i;
|
||||
*v = i;
|
||||
/*
|
||||
*v = myftol(*v);
|
||||
v++;
|
||||
*v = myftol(*v);
|
||||
v++;
|
||||
*v = myftol(*v);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
**
|
||||
** Disable all optimizations temporarily so this code works correctly!
|
||||
**
|
||||
*/
|
||||
#pragma optimize( "", off )
|
||||
|
||||
/*
|
||||
** --------------------------------------------------------------------------------
|
||||
**
|
||||
** PROCESSOR STUFF
|
||||
**
|
||||
** --------------------------------------------------------------------------------
|
||||
*/
|
||||
static inline void CPUID( int func, unsigned int regs[4] )
|
||||
{
|
||||
unsigned regEAX, regEBX, regECX, regEDX;
|
||||
|
||||
__asm mov eax, func
|
||||
__asm __emit 00fh
|
||||
__asm __emit 0a2h
|
||||
__asm mov regEAX, eax
|
||||
__asm mov regEBX, ebx
|
||||
__asm mov regECX, ecx
|
||||
__asm mov regEDX, edx
|
||||
|
||||
regs[0] = regEAX;
|
||||
regs[1] = regEBX;
|
||||
regs[2] = regECX;
|
||||
regs[3] = regEDX;
|
||||
}
|
||||
|
||||
static int IsPentium( void )
|
||||
{
|
||||
__asm
|
||||
{
|
||||
pushfd // save eflags
|
||||
pop eax
|
||||
test eax, 0x00200000 // check ID bit
|
||||
jz set21 // bit 21 is not set, so jump to set_21
|
||||
and eax, 0xffdfffff // clear bit 21
|
||||
push eax // save new value in register
|
||||
popfd // store new value in flags
|
||||
pushfd
|
||||
pop eax
|
||||
test eax, 0x00200000 // check ID bit
|
||||
jz good
|
||||
jmp err // cpuid not supported
|
||||
set21:
|
||||
or eax, 0x00200000 // set ID bit
|
||||
push eax // store new value
|
||||
popfd // store new value in EFLAGS
|
||||
pushfd
|
||||
pop eax
|
||||
test eax, 0x00200000 // if bit 21 is on
|
||||
jnz good
|
||||
jmp err
|
||||
}
|
||||
|
||||
err:
|
||||
return qfalse;
|
||||
good:
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
static int Is3DNOW( void )
|
||||
{
|
||||
unsigned regs[4];
|
||||
char pstring[16];
|
||||
char processorString[13];
|
||||
|
||||
// get name of processor
|
||||
CPUID( 0, ( unsigned int * ) pstring );
|
||||
processorString[0] = pstring[4];
|
||||
processorString[1] = pstring[5];
|
||||
processorString[2] = pstring[6];
|
||||
processorString[3] = pstring[7];
|
||||
processorString[4] = pstring[12];
|
||||
processorString[5] = pstring[13];
|
||||
processorString[6] = pstring[14];
|
||||
processorString[7] = pstring[15];
|
||||
processorString[8] = pstring[8];
|
||||
processorString[9] = pstring[9];
|
||||
processorString[10] = pstring[10];
|
||||
processorString[11] = pstring[11];
|
||||
processorString[12] = 0;
|
||||
|
||||
// REMOVED because you can have 3DNow! on non-AMD systems
|
||||
// if ( strcmp( processorString, "AuthenticAMD" ) )
|
||||
// return qfalse;
|
||||
|
||||
// check AMD-specific functions
|
||||
CPUID( 0x80000000, regs );
|
||||
if ( regs[0] < 0x80000000 )
|
||||
return qfalse;
|
||||
|
||||
// bit 31 of EDX denotes 3DNOW! support
|
||||
CPUID( 0x80000001, regs );
|
||||
if ( regs[3] & ( 1 << 31 ) )
|
||||
return qtrue;
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
static int IsKNI( void )
|
||||
{
|
||||
unsigned regs[4];
|
||||
|
||||
// get CPU feature bits
|
||||
CPUID( 1, regs );
|
||||
|
||||
// bit 25 of EDX denotes KNI existence
|
||||
if ( regs[3] & ( 1 << 25 ) )
|
||||
return qtrue;
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
static int IsWIL( void )
|
||||
{
|
||||
unsigned regs[4];
|
||||
|
||||
// get CPU feature bits
|
||||
CPUID( 1, regs );
|
||||
|
||||
// bit 26 of EDX denotes WIL existence
|
||||
if ( regs[3] & ( 1 << 26 ) )
|
||||
{
|
||||
// Ok, CPU supports this instruction, but does the OS?
|
||||
//
|
||||
// Test a WIL instruction and make sure you don't get an exception...
|
||||
//
|
||||
__try
|
||||
{
|
||||
__asm
|
||||
{
|
||||
pushad;
|
||||
// xorpd xmm0,xmm0; // Willamette New Instructions
|
||||
__emit 0x0f
|
||||
__emit 0x56
|
||||
__emit 0xc9
|
||||
popad;
|
||||
}
|
||||
}// If OS creates an exception, it doesn't support PentiumIV Instructions
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
// if(_exception_code()==STATUS_ILLEGAL_INSTRUCTION) // forget it, any exception should count as fail for safety
|
||||
return qfalse; // Willamette New Instructions not supported
|
||||
}
|
||||
|
||||
return qtrue; // Williamette/P4 instructions available
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int IsMMX( void )
|
||||
{
|
||||
unsigned int regs[4];
|
||||
|
||||
// get CPU feature bits
|
||||
CPUID( 1, regs );
|
||||
|
||||
// bit 23 of EDX denotes MMX existence
|
||||
if ( regs[3] & ( 1 << 23 ) )
|
||||
return qtrue;
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
int Sys_GetProcessorId( void )
|
||||
{
|
||||
#if defined _M_ALPHA
|
||||
return CPUID_AXP;
|
||||
#elif !defined _M_IX86
|
||||
return CPUID_GENERIC;
|
||||
#else
|
||||
|
||||
// verify we're at least a Pentium or 486 w/ CPUID support
|
||||
if ( !IsPentium() )
|
||||
return CPUID_INTEL_UNSUPPORTED;
|
||||
|
||||
// check for MMX
|
||||
if ( !IsMMX() )
|
||||
{
|
||||
// Pentium or PPro
|
||||
return CPUID_INTEL_PENTIUM;
|
||||
}
|
||||
|
||||
// see if we're an AMD 3DNOW! processor
|
||||
if ( Is3DNOW() )
|
||||
{
|
||||
return CPUID_AMD_3DNOW;
|
||||
}
|
||||
|
||||
// see if we're an Intel Katmai
|
||||
if ( IsKNI() )
|
||||
{
|
||||
// if we are, see if we're a Williamette as well...
|
||||
//
|
||||
if ( IsWIL() )
|
||||
{
|
||||
return CPUID_INTEL_WILLIAMETTE;
|
||||
}
|
||||
return CPUID_INTEL_KATMAI;
|
||||
}
|
||||
|
||||
// by default we're functionally a vanilla Pentium/MMX or P2/MMX
|
||||
return CPUID_INTEL_MMX;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Re-enable optimizations back to what they were
|
||||
**
|
||||
*/
|
||||
#pragma optimize( "", on )
|
||||
|
||||
//============================================
|
||||
|
||||
char *Sys_GetCurrentUser( void )
|
||||
{
|
||||
#ifdef _XBOX
|
||||
return NULL;
|
||||
#else
|
||||
static char s_userName[1024];
|
||||
unsigned long size = sizeof( s_userName );
|
||||
|
||||
|
||||
if ( !GetUserName( s_userName, &size ) )
|
||||
strcpy( s_userName, "player" );
|
||||
|
||||
if ( !s_userName[0] )
|
||||
{
|
||||
strcpy( s_userName, "player" );
|
||||
}
|
||||
|
||||
return s_userName;
|
||||
#endif
|
||||
}
|
||||
|
||||
char *Sys_DefaultHomePath(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *Sys_DefaultInstallPath(void)
|
||||
{
|
||||
return Sys_Cwd();
|
||||
}
|
||||
|
||||
int Sys_GetPhysicalMemory( void )
|
||||
{
|
||||
MEMORYSTATUS MemoryStatus;
|
||||
|
||||
memset( &MemoryStatus, sizeof(MEMORYSTATUS), 0 );
|
||||
MemoryStatus.dwLength = sizeof(MEMORYSTATUS);
|
||||
|
||||
GlobalMemoryStatus( &MemoryStatus );
|
||||
|
||||
return( (int)(MemoryStatus.dwTotalPhys / (1024 * 1024)) + 1 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifndef _XBOX
|
||||
int Sys_GetCPUSpeedOld()
|
||||
{
|
||||
timeBeginPeriod(1);
|
||||
|
||||
#ifdef WIN32
|
||||
int iPriority;
|
||||
HANDLE hThread = GetCurrentThread();
|
||||
|
||||
iPriority = GetThreadPriority(hThread);
|
||||
if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
|
||||
{
|
||||
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
DWORD clockStart = timeGetTime();
|
||||
DWORD clockEnd = clockStart + 100;
|
||||
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
|
||||
__asm
|
||||
{
|
||||
rdtsc
|
||||
mov start, eax
|
||||
}
|
||||
|
||||
while(timeGetTime() < clockEnd)
|
||||
{ // loop for 1 tenth of a second
|
||||
}
|
||||
__asm
|
||||
{
|
||||
rdtsc
|
||||
mov end, eax
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
// Reset priority
|
||||
if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
|
||||
{
|
||||
SetThreadPriority(hThread, iPriority);
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
timeEndPeriod(1);
|
||||
|
||||
unsigned long time;
|
||||
time = end - start;
|
||||
int coarse = time / 100000;
|
||||
int firsttry = floor((coarse + 25) / 50) * 50;
|
||||
if (abs(firsttry - coarse) < 10)
|
||||
{
|
||||
return firsttry;
|
||||
}
|
||||
else
|
||||
{
|
||||
return floor(floor((coarse + 17) / 33.3) * 33.3);
|
||||
}
|
||||
}
|
||||
|
||||
int Sys_GetCPUSpeed()
|
||||
{
|
||||
unsigned long raw_freq; // Raw frequency of CPU in MHz
|
||||
unsigned long norm_freq; // Normalized frequency of CPU in MHz.
|
||||
LARGE_INTEGER t0,t1; // Variables for High-Resolution Performance Counter reads
|
||||
|
||||
unsigned long freq =0; // Most current frequ. calculation
|
||||
unsigned long freq2 =0; // 2nd most current frequ. calc.
|
||||
unsigned long freq3 =0; // 3rd most current frequ. calc.
|
||||
|
||||
unsigned long total; // Sum of previous three frequency calculations
|
||||
int tries=0; // Number of times a calculation has been made on this call to cpuspeed
|
||||
unsigned long total_cycles=0, cycles; // Clock cycles elapsed during test
|
||||
unsigned long stamp0=0, stamp1=0; // Time Stamp Variable for beginning and end of test
|
||||
unsigned long total_ticks=0, ticks; // Microseconds elapsed during test
|
||||
LARGE_INTEGER count_freq; // High Resolution Performance Counter frequency
|
||||
|
||||
#define TOLERANCE 1 // Number of MHz to allow samplings to deviate from average of samplings.
|
||||
#define ROUND_THRESHOLD 6
|
||||
|
||||
#ifdef WIN32
|
||||
int iPriority;
|
||||
HANDLE hThread = GetCurrentThread();
|
||||
#endif // WIN32;
|
||||
|
||||
if ( !QueryPerformanceFrequency ( &count_freq ) )
|
||||
return Sys_GetCPUSpeedOld(); //should never happen
|
||||
|
||||
// On processors supporting the Read
|
||||
// Time Stamp opcode, compare elapsed
|
||||
// time on the High-Resolution Counter
|
||||
// with elapsed cycles on the Time
|
||||
// Stamp Register.
|
||||
|
||||
do { // This do loop runs up to 20 times or until the average of the previous
|
||||
// three calculated frequencies is within 1 MHz of each of the
|
||||
// individual calculated frequencies. This resampling increases the
|
||||
// accuracy of the results since outside factors could affect this calculation
|
||||
|
||||
tries++; // Increment number of times sampled on this call to cpuspeed
|
||||
|
||||
freq3 = freq2; // Shift frequencies back to make
|
||||
freq2 = freq; // room for new frequency measurement
|
||||
|
||||
QueryPerformanceCounter(&t0);// Get high-resolution performance counter time
|
||||
|
||||
t1 = t0; // Set Initial time
|
||||
|
||||
#ifdef WIN32
|
||||
iPriority = GetThreadPriority(hThread);
|
||||
if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
|
||||
{
|
||||
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
while ( (unsigned long)t1.LowPart - (unsigned long)t0.LowPart<50) {
|
||||
// Loop until 50 ticks have passed since last read of hi-res counter. This accounts for overhead later.
|
||||
QueryPerformanceCounter(&t1);
|
||||
_asm {
|
||||
rdtsc; // Read Time Stamp
|
||||
MOV stamp0, EAX
|
||||
}
|
||||
}
|
||||
|
||||
t0 = t1; // Reset Initial Time
|
||||
|
||||
while ((unsigned long)t1.LowPart-(unsigned long)t0.LowPart<2000 ) {
|
||||
// Loop until enough ticks have passed since last read of hi-res counter. This allows for elapsed time for sampling.
|
||||
QueryPerformanceCounter(&t1);
|
||||
__asm {
|
||||
rdtsc; // Read Time Stamp
|
||||
MOV stamp1, EAX
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
|
||||
{ // Reset priority
|
||||
SetThreadPriority(hThread, iPriority);
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
cycles = stamp1 - stamp0; // Number of internal clock cycles is difference between two time stamp readings.
|
||||
|
||||
ticks = (unsigned long) t1.LowPart - (unsigned long) t0.LowPart;
|
||||
// Number of external ticks is difference between two hi-res counter reads.
|
||||
|
||||
|
||||
// Note that some seemingly arbitrary mulitplies and
|
||||
// divides are done below. This is to maintain a
|
||||
// high level of precision without truncating the
|
||||
// most significant data. According to what value
|
||||
// ITERATIIONS is set to, these multiplies and
|
||||
// divides might need to be shifted for optimal
|
||||
// precision.
|
||||
|
||||
ticks = ticks * 100000; // Convert ticks to hundred thousandths of a tick
|
||||
|
||||
ticks = ticks / ( count_freq.LowPart/10 );
|
||||
// Hundred Thousandths of a Ticks / ( 10 ticks/second ) = microseconds (us)
|
||||
|
||||
total_ticks += ticks;
|
||||
total_cycles += cycles;
|
||||
|
||||
if ( ticks%count_freq.LowPart > count_freq.LowPart/2 )
|
||||
ticks++; // Round up if necessary
|
||||
|
||||
if (!ticks){
|
||||
ticks++; // prevent DIV by ZERO
|
||||
}
|
||||
|
||||
freq = cycles/ticks; // Cycles / us = MHz
|
||||
|
||||
if ( cycles%ticks > ticks/2 )
|
||||
freq++; // Round up if necessary
|
||||
|
||||
total = ( freq + freq2 + freq3 ); // Total last three frequency calculations
|
||||
|
||||
} while ( (tries < 3 ) ||
|
||||
(tries < 20)&&
|
||||
((abs(3 * freq -total) > 3*TOLERANCE )||
|
||||
(abs(3 * freq2-total) > 3*TOLERANCE )||
|
||||
(abs(3 * freq3-total) > 3*TOLERANCE )));
|
||||
// Compare last three calculations to average of last three calculations.
|
||||
|
||||
if (!total_ticks){
|
||||
total_ticks++; // prevent DIV by ZERO
|
||||
}
|
||||
|
||||
// Try one more significant digit.
|
||||
freq3 = ( total_cycles * 10 ) / total_ticks;
|
||||
freq2 = ( total_cycles * 100 ) / total_ticks;
|
||||
|
||||
|
||||
if ( freq2 - (freq3 * 10) >= ROUND_THRESHOLD )
|
||||
freq3++;
|
||||
|
||||
raw_freq = total_cycles / total_ticks;
|
||||
norm_freq = raw_freq;
|
||||
|
||||
freq = raw_freq * 10;
|
||||
if( (freq3 - freq) >= ROUND_THRESHOLD )
|
||||
norm_freq++;
|
||||
|
||||
return norm_freq;
|
||||
}
|
||||
#endif
|
||||
|
||||
382
codemp/win32/win_snd.cpp
Normal file
382
codemp/win32/win_snd.cpp
Normal file
@@ -0,0 +1,382 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include "../client/snd_local.h"
|
||||
#include "win_local.h"
|
||||
|
||||
HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter);
|
||||
#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c)
|
||||
|
||||
#define SECONDARY_BUFFER_SIZE 0x10000
|
||||
|
||||
extern int s_UseOpenAL;
|
||||
|
||||
static qboolean dsound_init;
|
||||
static int sample16;
|
||||
static DWORD gSndBufSize;
|
||||
static DWORD locksize;
|
||||
static LPDIRECTSOUND pDS;
|
||||
static LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
|
||||
static HINSTANCE hInstDS;
|
||||
|
||||
|
||||
static const char *DSoundError( int error ) {
|
||||
switch ( error ) {
|
||||
case DSERR_BUFFERLOST:
|
||||
return "DSERR_BUFFERLOST";
|
||||
case DSERR_INVALIDCALL:
|
||||
return "DSERR_INVALIDCALLS";
|
||||
case DSERR_INVALIDPARAM:
|
||||
return "DSERR_INVALIDPARAM";
|
||||
case DSERR_PRIOLEVELNEEDED:
|
||||
return "DSERR_PRIOLEVELNEEDED";
|
||||
case DSERR_ALLOCATED:
|
||||
return "DSERR_ALLOCATED";
|
||||
case DSERR_UNINITIALIZED:
|
||||
return "DSERR_UNINITIALIZED";
|
||||
case DSERR_UNSUPPORTED:
|
||||
return "DSERR_UNSUPPORTED ";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SNDDMA_Shutdown
|
||||
==================
|
||||
*/
|
||||
void SNDDMA_Shutdown( void ) {
|
||||
Com_DPrintf( "Shutting down sound system\n" );
|
||||
|
||||
if ( pDS ) {
|
||||
Com_DPrintf( "Destroying DS buffers\n" );
|
||||
if ( pDS )
|
||||
{
|
||||
Com_DPrintf( "...setting NORMAL coop level\n" );
|
||||
pDS->SetCooperativeLevel( g_wv.hWnd, DSSCL_NORMAL );
|
||||
}
|
||||
|
||||
if ( pDSBuf )
|
||||
{
|
||||
Com_DPrintf( "...stopping and releasing sound buffer\n" );
|
||||
pDSBuf->Stop( );
|
||||
pDSBuf->Release( );
|
||||
}
|
||||
|
||||
// only release primary buffer if it's not also the mixing buffer we just released
|
||||
if ( pDSPBuf && ( pDSBuf != pDSPBuf ) )
|
||||
{
|
||||
Com_DPrintf( "...releasing primary buffer\n" );
|
||||
pDSPBuf->Release( );
|
||||
}
|
||||
pDSBuf = NULL;
|
||||
pDSPBuf = NULL;
|
||||
|
||||
dma.buffer = NULL;
|
||||
|
||||
Com_DPrintf( "...releasing DS object\n" );
|
||||
pDS->Release( );
|
||||
}
|
||||
|
||||
if ( hInstDS ) {
|
||||
Com_DPrintf( "...freeing DSOUND.DLL\n" );
|
||||
FreeLibrary( hInstDS );
|
||||
hInstDS = NULL;
|
||||
}
|
||||
|
||||
pDS = NULL;
|
||||
pDSBuf = NULL;
|
||||
pDSPBuf = NULL;
|
||||
dsound_init = qfalse;
|
||||
memset ((void *)&dma, 0, sizeof (dma));
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SNDDMA_Init
|
||||
|
||||
Initialize direct sound
|
||||
Returns false if failed
|
||||
==================
|
||||
*/
|
||||
qboolean SNDDMA_Init(void) {
|
||||
|
||||
memset ((void *)&dma, 0, sizeof (dma));
|
||||
dsound_init = qfalse;
|
||||
|
||||
if ( !SNDDMA_InitDS () ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
dsound_init = qtrue;
|
||||
|
||||
Com_DPrintf("Completed successfully\n" );
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
int SNDDMA_InitDS ()
|
||||
{
|
||||
HRESULT hresult;
|
||||
qboolean pauseTried;
|
||||
DSBUFFERDESC dsbuf;
|
||||
DSBCAPS dsbcaps;
|
||||
WAVEFORMATEX format;
|
||||
|
||||
Com_Printf( "Initializing DirectSound\n");
|
||||
|
||||
if ( !hInstDS ) {
|
||||
Com_DPrintf( "...loading dsound.dll: " );
|
||||
|
||||
hInstDS = LoadLibrary("dsound.dll");
|
||||
|
||||
if ( hInstDS == NULL ) {
|
||||
Com_Printf ("failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Com_DPrintf ("ok\n");
|
||||
pDirectSoundCreate = (long (__stdcall *)(struct _GUID *,struct IDirectSound ** ,struct IUnknown *))
|
||||
GetProcAddress(hInstDS,"DirectSoundCreate");
|
||||
|
||||
if ( !pDirectSoundCreate ) {
|
||||
Com_Printf ("*** couldn't get DS proc addr ***\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Com_DPrintf( "...creating DS object: " );
|
||||
pauseTried = qfalse;
|
||||
while ( ( hresult = iDirectSoundCreate( NULL, &pDS, NULL ) ) != DS_OK ) {
|
||||
if ( hresult != DSERR_ALLOCATED ) {
|
||||
Com_Printf( "failed\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( pauseTried ) {
|
||||
Com_Printf ("failed, hardware already in use\n" );
|
||||
return 0;
|
||||
}
|
||||
// first try just waiting five seconds and trying again
|
||||
// this will handle the case of a sysyem beep playing when the
|
||||
// game starts
|
||||
Com_DPrintf ("retrying...\n");
|
||||
Sleep( 3000 );
|
||||
pauseTried = qtrue;
|
||||
}
|
||||
Com_DPrintf( "ok\n" );
|
||||
|
||||
Com_DPrintf("...setting DSSCL_PRIORITY coop level: " );
|
||||
|
||||
if ( DS_OK != pDS->SetCooperativeLevel( g_wv.hWnd, DSSCL_PRIORITY ) ) {
|
||||
Com_Printf ("failed\n");
|
||||
SNDDMA_Shutdown ();
|
||||
return qfalse;
|
||||
}
|
||||
Com_DPrintf("ok\n" );
|
||||
|
||||
|
||||
// create the secondary buffer we'll actually work with
|
||||
dma.channels = 2;
|
||||
dma.samplebits = 16;
|
||||
|
||||
if (s_khz->integer == 44)
|
||||
dma.speed = 44100;
|
||||
else if (s_khz->integer == 22)
|
||||
dma.speed = 22050;
|
||||
else
|
||||
dma.speed = 11025;
|
||||
|
||||
memset (&format, 0, sizeof(format));
|
||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
format.nChannels = dma.channels;
|
||||
format.wBitsPerSample = dma.samplebits;
|
||||
format.nSamplesPerSec = dma.speed;
|
||||
format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
|
||||
format.cbSize = 0;
|
||||
format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign;
|
||||
|
||||
memset (&dsbuf, 0, sizeof(dsbuf));
|
||||
dsbuf.dwSize = sizeof(DSBUFFERDESC);
|
||||
|
||||
#define idDSBCAPS_GETCURRENTPOSITION2 0x00010000
|
||||
|
||||
dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCHARDWARE | idDSBCAPS_GETCURRENTPOSITION2;
|
||||
dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
|
||||
dsbuf.lpwfxFormat = &format;
|
||||
|
||||
Com_DPrintf( "...creating secondary buffer: " );
|
||||
if (DS_OK != pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL)) {
|
||||
Com_Printf( " - using ancient version of DirectX -- this will slow FPS\n" );
|
||||
dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY;
|
||||
hresult = pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL);
|
||||
if (hresult != DS_OK) {
|
||||
Com_Printf( "failed to create secondary buffer - %s\n", DSoundError( hresult ) );
|
||||
SNDDMA_Shutdown ();
|
||||
return qfalse;
|
||||
}
|
||||
}
|
||||
Com_Printf( "locked hardware. ok\n" );
|
||||
|
||||
// Make sure mixer is active
|
||||
if ( DS_OK != pDSBuf->Play(0, 0, DSBPLAY_LOOPING) ) {
|
||||
Com_Printf ("*** Looped sound play failed ***\n");
|
||||
SNDDMA_Shutdown ();
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
memset(&dsbcaps, 0, sizeof(dsbcaps));
|
||||
dsbcaps.dwSize = sizeof(dsbcaps);
|
||||
// get the returned buffer size
|
||||
if ( DS_OK != pDSBuf->GetCaps (&dsbcaps) ) {
|
||||
Com_Printf ("*** GetCaps failed ***\n");
|
||||
SNDDMA_Shutdown ();
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
gSndBufSize = dsbcaps.dwBufferBytes;
|
||||
|
||||
dma.channels = format.nChannels;
|
||||
dma.samplebits = format.wBitsPerSample;
|
||||
dma.speed = format.nSamplesPerSec;
|
||||
dma.samples = gSndBufSize/(dma.samplebits/8);
|
||||
dma.submission_chunk = 1;
|
||||
dma.buffer = NULL; // must be locked first
|
||||
|
||||
sample16 = (dma.samplebits/8) - 1;
|
||||
|
||||
SNDDMA_BeginPainting ();
|
||||
if (dma.buffer)
|
||||
memset(dma.buffer, 0, dma.samples * dma.samplebits/8);
|
||||
SNDDMA_Submit ();
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
==============
|
||||
SNDDMA_GetDMAPos
|
||||
|
||||
return the current sample position (in mono samples read)
|
||||
inside the recirculating dma buffer, so the mixing code will know
|
||||
how many sample are required to fill it up.
|
||||
===============
|
||||
*/
|
||||
int SNDDMA_GetDMAPos( void ) {
|
||||
MMTIME mmtime;
|
||||
int s;
|
||||
DWORD dwWrite;
|
||||
|
||||
if ( !dsound_init ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mmtime.wType = TIME_SAMPLES;
|
||||
pDSBuf->GetCurrentPosition(&mmtime.u.sample, &dwWrite);
|
||||
|
||||
s = mmtime.u.sample;
|
||||
|
||||
s >>= sample16;
|
||||
|
||||
s &= (dma.samples-1);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_BeginPainting
|
||||
|
||||
Makes sure dma.buffer is valid
|
||||
===============
|
||||
*/
|
||||
void SNDDMA_BeginPainting( void ) {
|
||||
int reps;
|
||||
DWORD dwSize2;
|
||||
DWORD *pbuf, *pbuf2;
|
||||
HRESULT hresult;
|
||||
DWORD dwStatus;
|
||||
|
||||
if ( !pDSBuf ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if the buffer was lost or stopped, restore it and/or restart it
|
||||
if ( pDSBuf->GetStatus (&dwStatus) != DS_OK ) {
|
||||
Com_Printf ("Couldn't get sound buffer status\n");
|
||||
}
|
||||
|
||||
if (dwStatus & DSBSTATUS_BUFFERLOST)
|
||||
pDSBuf->Restore ();
|
||||
|
||||
if (!(dwStatus & DSBSTATUS_PLAYING))
|
||||
pDSBuf->Play(0, 0, DSBPLAY_LOOPING);
|
||||
|
||||
// lock the dsound buffer
|
||||
|
||||
reps = 0;
|
||||
dma.buffer = NULL;
|
||||
|
||||
while ((hresult = pDSBuf->Lock(0, gSndBufSize, (void **)&pbuf, &locksize,
|
||||
(void **)&pbuf2, &dwSize2, 0)) != DS_OK)
|
||||
{
|
||||
if (hresult != DSERR_BUFFERLOST)
|
||||
{
|
||||
Com_Printf( "SNDDMA_BeginPainting: Lock failed with error '%s'\n", DSoundError( hresult ) );
|
||||
S_Shutdown ();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
pDSBuf->Restore( );
|
||||
}
|
||||
|
||||
if (++reps > 2)
|
||||
return;
|
||||
}
|
||||
dma.buffer = (unsigned char *)pbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_Submit
|
||||
|
||||
Send sound to device if buffer isn't really the dma buffer
|
||||
Also unlocks the dsound buffer
|
||||
===============
|
||||
*/
|
||||
void SNDDMA_Submit( void ) {
|
||||
// unlock the dsound buffer
|
||||
if ( pDSBuf ) {
|
||||
pDSBuf->Unlock(dma.buffer, locksize, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
SNDDMA_Activate
|
||||
|
||||
When we change windows we need to do this
|
||||
=================
|
||||
*/
|
||||
void SNDDMA_Activate( qboolean bAppActive )
|
||||
{
|
||||
if (s_UseOpenAL)
|
||||
{
|
||||
S_AL_MuteAllSounds(!bAppActive);
|
||||
}
|
||||
|
||||
if ( !pDS ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( DS_OK != pDS->SetCooperativeLevel( g_wv.hWnd, DSSCL_PRIORITY ) ) {
|
||||
Com_Printf ("sound SetCooperativeLevel failed\n");
|
||||
SNDDMA_Shutdown ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
456
codemp/win32/win_stream_dx8.cpp
Normal file
456
codemp/win32/win_stream_dx8.cpp
Normal file
@@ -0,0 +1,456 @@
|
||||
|
||||
/*
|
||||
* UNPUBLISHED -- Rights reserved under the copyright laws of the
|
||||
* United States. Use of a copyright notice is precautionary only and
|
||||
* does not imply publication or disclosure.
|
||||
*
|
||||
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
|
||||
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
|
||||
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
|
||||
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
|
||||
*/
|
||||
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
#include "../client/client.h"
|
||||
#include "win_local.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
|
||||
#include "../zlib/zlib.h"
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
#include <windows.h>
|
||||
#elif defined(_XBOX)
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
|
||||
extern void Z_SetNewDeleteTemporary(bool);
|
||||
|
||||
#define STREAM_SLOW_READ 0
|
||||
|
||||
#include "../client/snd_local_console.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
extern HANDLE Sys_FileStreamMutex;
|
||||
extern const char* Sys_GetFileCodeName(int code);
|
||||
extern int Sys_GetFileCodeSize(int code);
|
||||
|
||||
#define STREAM_MAX_OPEN 48
|
||||
struct StreamInfo
|
||||
{
|
||||
unsigned int file;
|
||||
volatile bool used;
|
||||
volatile bool error;
|
||||
volatile bool opening;
|
||||
volatile bool reading;
|
||||
};
|
||||
static StreamInfo* s_Streams = NULL;
|
||||
|
||||
enum IORequestType
|
||||
{
|
||||
IOREQ_OPEN,
|
||||
IOREQ_READ,
|
||||
IOREQ_SHUTDOWN,
|
||||
};
|
||||
|
||||
struct IORequest
|
||||
{
|
||||
IORequestType type;
|
||||
streamHandle_t handle;
|
||||
DWORD data[3];
|
||||
};
|
||||
typedef std::deque<IORequest> requestqueue_t;
|
||||
requestqueue_t* s_IORequestQueue = NULL;
|
||||
|
||||
HANDLE s_Thread = INVALID_HANDLE_VALUE;
|
||||
HANDLE s_QueueMutex = INVALID_HANDLE_VALUE;
|
||||
HANDLE s_QueueLen = INVALID_HANDLE_VALUE;
|
||||
|
||||
#include "../qcommon/fixedmap.h"
|
||||
|
||||
#pragma pack(push, 1);
|
||||
typedef struct
|
||||
{
|
||||
unsigned char filenameFlags;
|
||||
int offset;
|
||||
int size;
|
||||
} sound_file_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
static HANDLE soundfile = INVALID_HANDLE_VALUE;
|
||||
static VVFixedMap< sound_file_t, unsigned int >* soundLookup = NULL;
|
||||
|
||||
void Sys_StreamInitialize( void );
|
||||
|
||||
static DWORD WINAPI _streamThread(LPVOID)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
IORequest req;
|
||||
DWORD bytes;
|
||||
StreamInfo* strm;
|
||||
|
||||
// Wait for the IO queue to fill
|
||||
WaitForSingleObject(s_QueueLen, INFINITE);
|
||||
|
||||
// Grab the next IO request
|
||||
WaitForSingleObject(s_QueueMutex, INFINITE);
|
||||
assert(!s_IORequestQueue->empty());
|
||||
req = s_IORequestQueue->front();
|
||||
s_IORequestQueue->pop_front();
|
||||
ReleaseMutex(s_QueueMutex);
|
||||
|
||||
int offset = 0;
|
||||
sound_file_t* crap;
|
||||
|
||||
// Process request
|
||||
switch (req.type)
|
||||
{
|
||||
case IOREQ_OPEN:
|
||||
|
||||
strm = &s_Streams[req.handle];
|
||||
assert(strm->used);
|
||||
|
||||
strm->file = req.data[0];
|
||||
strm->error = (strm->file == -1);
|
||||
strm->opening = false;
|
||||
break;
|
||||
/*
|
||||
{
|
||||
const char* name = Sys_GetFileCodeName(req.data[0]);
|
||||
|
||||
WaitForSingleObject(Sys_FileStreamMutex, INFINITE);
|
||||
|
||||
strm->file =
|
||||
CreateFile(name, GENERIC_READ,
|
||||
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
ReleaseMutex(Sys_FileStreamMutex);
|
||||
}
|
||||
|
||||
strm->error = (strm->file == INVALID_HANDLE_VALUE);
|
||||
strm->opening = false;
|
||||
break;
|
||||
*/
|
||||
case IOREQ_READ:
|
||||
{
|
||||
strm = &s_Streams[req.handle];
|
||||
assert(strm->used);
|
||||
|
||||
WaitForSingleObject(Sys_FileStreamMutex, INFINITE);
|
||||
|
||||
crap = soundLookup->Find(strm->file);
|
||||
|
||||
if(crap)
|
||||
{
|
||||
offset = crap->offset + req.data[2];
|
||||
strm->error = (SetFilePointer(soundfile, offset, 0, FILE_BEGIN) != offset) ||
|
||||
(ReadFile(soundfile, (void*)req.data[0], req.data[1], &bytes, NULL) == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
strm->error = true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
strm->error =
|
||||
(SetFilePointer(strm->file, req.data[2], 0, FILE_BEGIN) != req.data[2] ||
|
||||
ReadFile(strm->file, (void*)req.data[0], req.data[1], &bytes, NULL) == 0);
|
||||
*/
|
||||
|
||||
ReleaseMutex(Sys_FileStreamMutex);
|
||||
|
||||
strm->reading = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case IOREQ_SHUTDOWN:
|
||||
ExitThread(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void _sendIORequest(const IORequest& req)
|
||||
{
|
||||
// Add request to queue
|
||||
WaitForSingleObject(s_QueueMutex, INFINITE);
|
||||
Z_SetNewDeleteTemporary(true);
|
||||
s_IORequestQueue->push_back(req);
|
||||
Z_SetNewDeleteTemporary(false);
|
||||
ReleaseMutex(s_QueueMutex);
|
||||
|
||||
// Let IO thread know it has one more pending request
|
||||
ReleaseSemaphore(s_QueueLen, 1, NULL);
|
||||
}
|
||||
|
||||
void Sys_IORequestQueueClear(void)
|
||||
{
|
||||
WaitForSingleObject(s_QueueMutex, INFINITE);
|
||||
delete s_IORequestQueue;
|
||||
s_IORequestQueue = new requestqueue_t;
|
||||
ReleaseMutex(s_QueueMutex);
|
||||
}
|
||||
|
||||
void Sys_StreamInit(void)
|
||||
{
|
||||
Sys_StreamInitialize();
|
||||
|
||||
// Create array for storing open streams
|
||||
s_Streams = (StreamInfo*)Z_Malloc(
|
||||
STREAM_MAX_OPEN * sizeof(StreamInfo), TAG_FILESYS, qfalse);
|
||||
for (int i = 0; i < STREAM_MAX_OPEN; ++i)
|
||||
{
|
||||
s_Streams[i].used = false;
|
||||
}
|
||||
|
||||
// Create queue to hold requests for IO thread
|
||||
s_IORequestQueue = new requestqueue_t;
|
||||
|
||||
// Create a thread to service IO
|
||||
s_QueueMutex = CreateMutex(NULL, FALSE, NULL);
|
||||
s_QueueLen = CreateSemaphore(NULL, 0, STREAM_MAX_OPEN * 3, NULL);
|
||||
s_Thread = CreateThread(NULL, 64*1024, _streamThread, 0, 0, NULL);
|
||||
}
|
||||
|
||||
void Sys_StreamShutdown(void)
|
||||
{
|
||||
// Tell the IO thread to shutdown
|
||||
IORequest req;
|
||||
req.type = IOREQ_SHUTDOWN;
|
||||
_sendIORequest(req);
|
||||
|
||||
// Wait for thread to close
|
||||
WaitForSingleObject(s_Thread, INFINITE);
|
||||
|
||||
// Kill IO thread
|
||||
CloseHandle(s_Thread);
|
||||
CloseHandle(s_QueueLen);
|
||||
CloseHandle(s_QueueMutex);
|
||||
|
||||
// Remove queue of IO requests
|
||||
delete s_IORequestQueue;
|
||||
|
||||
// Remove streaming table
|
||||
Z_Free(s_Streams);
|
||||
}
|
||||
|
||||
static streamHandle_t GetFreeHandle(void)
|
||||
{
|
||||
for (streamHandle_t i = 1; i < STREAM_MAX_OPEN; ++i)
|
||||
{
|
||||
if (!s_Streams[i].used) return i;
|
||||
}
|
||||
|
||||
// handle 0 is invalid by convention
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Sys_StreamOpen(int code, streamHandle_t *handle)
|
||||
{
|
||||
// Find a free handle
|
||||
*handle = GetFreeHandle();
|
||||
if (*handle == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Find the file size
|
||||
sound_file_t* crap = soundLookup->Find(code);
|
||||
int size = -1;
|
||||
if(crap)
|
||||
{
|
||||
size = crap->size;
|
||||
}
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
*handle = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Init stream data
|
||||
s_Streams[*handle].used = true;
|
||||
s_Streams[*handle].opening = true;
|
||||
s_Streams[*handle].reading = false;
|
||||
s_Streams[*handle].error = false;
|
||||
|
||||
// Send an open request to the thread
|
||||
IORequest req;
|
||||
req.type = IOREQ_OPEN;
|
||||
req.handle = *handle;
|
||||
req.data[0] = code;
|
||||
_sendIORequest(req);
|
||||
|
||||
// Return file size
|
||||
return size;
|
||||
}
|
||||
|
||||
bool Sys_StreamRead(void* buffer, int size, int pos, streamHandle_t handle)
|
||||
{
|
||||
assert((unsigned int)buffer % 32 == 0);
|
||||
|
||||
// Handle must be valid. Do not allow multiple reads.
|
||||
if (!s_Streams[handle].used || s_Streams[handle].reading) return false;
|
||||
|
||||
// Ready to read
|
||||
s_Streams[handle].reading = true;
|
||||
s_Streams[handle].error = false;
|
||||
|
||||
// Request IO threading reading
|
||||
IORequest req;
|
||||
req.type = IOREQ_READ;
|
||||
req.handle = handle;
|
||||
req.data[0] = (DWORD)buffer;
|
||||
req.data[1] = size;
|
||||
req.data[2] = pos;
|
||||
_sendIORequest(req);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sys_StreamIsReading(streamHandle_t handle)
|
||||
{
|
||||
return s_Streams[handle].used && s_Streams[handle].reading;
|
||||
}
|
||||
|
||||
bool Sys_StreamIsError(streamHandle_t handle)
|
||||
{
|
||||
return s_Streams[handle].used && s_Streams[handle].error;
|
||||
}
|
||||
|
||||
void Sys_StreamClose(streamHandle_t handle)
|
||||
{
|
||||
if (s_Streams[handle].used)
|
||||
{
|
||||
// Block until read is done
|
||||
while (s_Streams[handle].opening || s_Streams[handle].reading);
|
||||
|
||||
// Close the file
|
||||
//CloseHandle(s_Streams[handle].file);
|
||||
s_Streams[handle].used = false;
|
||||
}
|
||||
}
|
||||
|
||||
extern char* FS_BuildOSPath(const char* name);
|
||||
|
||||
unsigned int Sys_GetSoundFileCode(const char* name)
|
||||
{
|
||||
// Get system level path
|
||||
char* osname = FS_BuildOSPath(name);
|
||||
|
||||
// Generate hash for file name
|
||||
strlwr(osname);
|
||||
unsigned int code = crc32(0, (const byte *)osname, strlen(osname));
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
unsigned int Sys_GetSoundFileCodeFlags(unsigned int code)
|
||||
{
|
||||
sound_file_t* sf;
|
||||
sf = soundLookup->Find(code);
|
||||
|
||||
if(!sf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return sf->filenameFlags;
|
||||
}
|
||||
}
|
||||
|
||||
int Sys_GetSoundFileCodeSize(unsigned int code)
|
||||
{
|
||||
sound_file_t* sf;
|
||||
sf = soundLookup->Find(code);
|
||||
|
||||
if(!sf)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return sf->size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Sys_StreamInitialize( void )
|
||||
{
|
||||
// open the sound file
|
||||
soundfile = CreateFile(
|
||||
"d:\\base\\soundbank\\sound.bnk",
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS,
|
||||
NULL );
|
||||
|
||||
// fill in the lookup table
|
||||
HANDLE table = INVALID_HANDLE_VALUE;
|
||||
|
||||
table = CreateFile(
|
||||
"d:\\base\\soundbank\\sound.tbl",
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL );
|
||||
|
||||
DWORD fileSize = 0;
|
||||
fileSize = GetFileSize(
|
||||
table,
|
||||
NULL);
|
||||
|
||||
int numberOfRecords = fileSize / ((sizeof(unsigned int) * 3) + 1);
|
||||
|
||||
soundLookup = new VVFixedMap<sound_file_t, unsigned int>(numberOfRecords);
|
||||
|
||||
byte* tempData = (byte*)Z_Malloc(fileSize, TAG_TEMP_WORKSPACE, true, 32);
|
||||
byte* restore = tempData;
|
||||
|
||||
DWORD bytesRead;
|
||||
|
||||
ReadFile(
|
||||
table,
|
||||
tempData,
|
||||
fileSize,
|
||||
&bytesRead,
|
||||
NULL );
|
||||
|
||||
if(bytesRead != fileSize)
|
||||
Com_Error(0,"Could not read sound index file.\n");
|
||||
|
||||
CloseHandle(table);
|
||||
|
||||
for(int i = 0; i < numberOfRecords; i++)
|
||||
{
|
||||
unsigned int filecode = *(unsigned int*)tempData;
|
||||
tempData += sizeof(unsigned int);
|
||||
unsigned int offset = *(unsigned int*)tempData;
|
||||
tempData += sizeof(unsigned int);
|
||||
int size = *(int*)tempData;
|
||||
tempData += sizeof(int);
|
||||
unsigned char filenameFlags = *(unsigned char*)tempData;
|
||||
tempData++;
|
||||
|
||||
sound_file_t sfile;
|
||||
sfile.offset = offset;
|
||||
sfile.size = size;
|
||||
sfile.filenameFlags = filenameFlags;
|
||||
|
||||
soundLookup->Insert(sfile, filecode);
|
||||
}
|
||||
|
||||
soundLookup->Sort();
|
||||
Z_Free(restore);
|
||||
}
|
||||
574
codemp/win32/win_syscon.cpp
Normal file
574
codemp/win32/win_syscon.cpp
Normal file
@@ -0,0 +1,574 @@
|
||||
// win_syscon.h
|
||||
// this include must remain at the top of every CPP file
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
#include "../client/client.h"
|
||||
#include "win_local.h"
|
||||
|
||||
|
||||
#include "resource.h"
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <conio.h>
|
||||
|
||||
#define COPY_ID 1
|
||||
#define QUIT_ID 2
|
||||
#define CLEAR_ID 3
|
||||
|
||||
#define ERRORBOX_ID 10
|
||||
#define ERRORTEXT_ID 11
|
||||
|
||||
#define EDIT_ID 100
|
||||
#define INPUT_ID 101
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HWND hWnd;
|
||||
HWND hwndBuffer;
|
||||
|
||||
HWND hwndButtonClear;
|
||||
HWND hwndButtonCopy;
|
||||
HWND hwndButtonQuit;
|
||||
|
||||
HWND hwndErrorBox;
|
||||
HWND hwndErrorText;
|
||||
|
||||
HBITMAP hbmLogo;
|
||||
HBITMAP hbmClearBitmap;
|
||||
|
||||
HBRUSH hbrEditBackground;
|
||||
HBRUSH hbrErrorBackground;
|
||||
|
||||
HFONT hfBufferFont;
|
||||
HFONT hfButtonFont;
|
||||
|
||||
HWND hwndInputLine;
|
||||
|
||||
char errorString[80];
|
||||
|
||||
char consoleText[512], returnedText[512];
|
||||
int visLevel;
|
||||
qboolean quitOnClose;
|
||||
int windowWidth, windowHeight;
|
||||
|
||||
WNDPROC SysInputLineWndProc;
|
||||
|
||||
} WinConData;
|
||||
|
||||
static WinConData s_wcd;
|
||||
|
||||
static LONG WINAPI ConWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
const char *cmdString;
|
||||
static qboolean s_timePolarity;
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_ACTIVATE:
|
||||
if ( LOWORD( wParam ) != WA_INACTIVE )
|
||||
{
|
||||
SetFocus( s_wcd.hwndInputLine );
|
||||
}
|
||||
|
||||
if ( com_viewlog && ( com_dedicated && !com_dedicated->integer ) )
|
||||
{
|
||||
// if the viewlog is open, check to see if it's being minimized
|
||||
if ( com_viewlog->integer == 1 )
|
||||
{
|
||||
if ( HIWORD( wParam ) ) // minimized flag
|
||||
{
|
||||
Cvar_Set( "viewlog", "2" );
|
||||
}
|
||||
}
|
||||
else if ( com_viewlog->integer == 2 )
|
||||
{
|
||||
if ( !HIWORD( wParam ) ) // minimized flag
|
||||
{
|
||||
Cvar_Set( "viewlog", "1" );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
if ( ( com_dedicated && com_dedicated->integer ) )
|
||||
{
|
||||
cmdString = CopyString( "quit" );
|
||||
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, (void *)cmdString );
|
||||
}
|
||||
else if ( s_wcd.quitOnClose )
|
||||
{
|
||||
PostQuitMessage( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
Sys_ShowConsole( 0, qfalse );
|
||||
Cvar_Set( "viewlog", "0" );
|
||||
}
|
||||
return 0;
|
||||
case WM_CTLCOLORSTATIC:
|
||||
if ( ( HWND ) lParam == s_wcd.hwndBuffer )
|
||||
{
|
||||
SetBkColor( ( HDC ) wParam, RGB( 0, 0, 0 ) );
|
||||
SetTextColor( ( HDC ) wParam, RGB( 249, 249, 000 ) );
|
||||
return ( long ) s_wcd.hbrEditBackground;
|
||||
}
|
||||
else if ( ( HWND ) lParam == s_wcd.hwndErrorBox )
|
||||
{
|
||||
if ( s_timePolarity & 1 )
|
||||
{
|
||||
SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
|
||||
SetTextColor( ( HDC ) wParam, RGB( 0xff, 0x00, 0x00 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
|
||||
SetTextColor( ( HDC ) wParam, RGB( 0x00, 0x00, 0x00 ) );
|
||||
}
|
||||
return ( long ) s_wcd.hbrErrorBackground;
|
||||
}
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
if ( wParam == COPY_ID )
|
||||
{
|
||||
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
|
||||
SendMessage( s_wcd.hwndBuffer, WM_COPY, 0, 0 );
|
||||
}
|
||||
else if ( wParam == QUIT_ID )
|
||||
{
|
||||
if ( s_wcd.quitOnClose )
|
||||
{
|
||||
PostQuitMessage( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
cmdString = CopyString( "quit" );
|
||||
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, (void *)cmdString );
|
||||
}
|
||||
}
|
||||
else if ( wParam == CLEAR_ID )
|
||||
{
|
||||
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
|
||||
SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, FALSE, ( LPARAM ) "" );
|
||||
UpdateWindow( s_wcd.hwndBuffer );
|
||||
}
|
||||
break;
|
||||
case WM_CREATE:
|
||||
s_wcd.hbrEditBackground = CreateSolidBrush( RGB( 0x00, 0x00, 0x00 ) );
|
||||
s_wcd.hbrErrorBackground = CreateSolidBrush( RGB( 0x80, 0x80, 0x80 ) );
|
||||
SetTimer( hWnd, 1, 1000, NULL );
|
||||
break;
|
||||
case WM_ERASEBKGND:
|
||||
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||||
case WM_TIMER:
|
||||
if ( wParam == 1 )
|
||||
{
|
||||
s_timePolarity = (qboolean)!s_timePolarity;
|
||||
if ( s_wcd.hwndErrorBox )
|
||||
{
|
||||
InvalidateRect( s_wcd.hwndErrorBox, NULL, FALSE );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||||
}
|
||||
|
||||
extern void CompleteCommand( void ) ;
|
||||
|
||||
LONG WINAPI InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
char inputBuffer[1024];
|
||||
|
||||
switch ( uMsg )
|
||||
{
|
||||
case WM_KILLFOCUS:
|
||||
if ( ( HWND ) wParam == s_wcd.hWnd ||
|
||||
( HWND ) wParam == s_wcd.hwndErrorBox )
|
||||
{
|
||||
SetFocus( hWnd );
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CHAR:
|
||||
if ( wParam == 13 )
|
||||
{
|
||||
GetWindowText( s_wcd.hwndInputLine, inputBuffer, sizeof( inputBuffer ) );
|
||||
strncat( s_wcd.consoleText, inputBuffer, sizeof( s_wcd.consoleText ) - strlen( s_wcd.consoleText ) - 5 );
|
||||
strcat( s_wcd.consoleText, "\n" );
|
||||
SetWindowText( s_wcd.hwndInputLine, "" );
|
||||
|
||||
Sys_Print( va( "]%s\n", inputBuffer ) );
|
||||
|
||||
strcpy(kg.g_consoleField.buffer, inputBuffer);
|
||||
kg.historyEditLines[kg.nextHistoryLine % COMMAND_HISTORY] = kg.g_consoleField;
|
||||
kg.nextHistoryLine++;
|
||||
kg.historyLine = kg.nextHistoryLine;
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (wParam == 9 )
|
||||
{
|
||||
GetWindowText( s_wcd.hwndInputLine, inputBuffer, sizeof( inputBuffer ) );
|
||||
strcpy(kg.g_consoleField.buffer, inputBuffer);
|
||||
CompleteCommand();
|
||||
SetWindowText( s_wcd.hwndInputLine, kg.g_consoleField.buffer);
|
||||
SendMessage(s_wcd.hwndInputLine, EM_SETSEL, strlen(kg.g_consoleField.buffer) , MAKELONG(0xffff, 0xffff) );
|
||||
}
|
||||
|
||||
case WM_KEYDOWN:
|
||||
if (wParam == VK_UP)
|
||||
{
|
||||
if ( kg.nextHistoryLine - kg.historyLine < COMMAND_HISTORY && kg.historyLine > 0 )
|
||||
{
|
||||
kg.historyLine--;
|
||||
}
|
||||
kg.g_consoleField = kg.historyEditLines[ kg.historyLine % COMMAND_HISTORY ];
|
||||
SetWindowText( s_wcd.hwndInputLine, kg.g_consoleField.buffer);
|
||||
SendMessage(s_wcd.hwndInputLine, EM_SETSEL, strlen(kg.g_consoleField.buffer) , MAKELONG(0xffff, 0xffff) );
|
||||
return 0;
|
||||
}
|
||||
else if (wParam == VK_DOWN)
|
||||
{
|
||||
if (kg.historyLine == kg.nextHistoryLine)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
kg.historyLine++;
|
||||
kg.g_consoleField = kg.historyEditLines[ kg.historyLine % COMMAND_HISTORY ];
|
||||
SetWindowText( s_wcd.hwndInputLine, kg.g_consoleField.buffer);
|
||||
SendMessage(s_wcd.hwndInputLine, EM_SETSEL, strlen(kg.g_consoleField.buffer) , MAKELONG(0xffff, 0xffff) );
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CallWindowProc( s_wcd.SysInputLineWndProc, hWnd, uMsg, wParam, lParam );
|
||||
}
|
||||
|
||||
/*
|
||||
** Sys_CreateConsole
|
||||
*/
|
||||
void Sys_CreateConsole( void )
|
||||
{
|
||||
HDC hDC;
|
||||
WNDCLASS wc;
|
||||
RECT rect;
|
||||
const char *DEDCLASS = "JAMP WinConsole";
|
||||
int nHeight;
|
||||
int swidth, sheight;
|
||||
int DEDSTYLE = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX;
|
||||
|
||||
memset( &wc, 0, sizeof( wc ) );
|
||||
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = (WNDPROC) ConWndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = g_wv.hInstance;
|
||||
wc.hIcon = LoadIcon( g_wv.hInstance, MAKEINTRESOURCE(IDI_ICON1));
|
||||
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
|
||||
wc.hbrBackground = (HBRUSH__ *)COLOR_INACTIVEBORDER;
|
||||
wc.lpszMenuName = 0;
|
||||
wc.lpszClassName = DEDCLASS;
|
||||
|
||||
if ( !RegisterClass (&wc) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
rect.left = 0;
|
||||
rect.right = 600;
|
||||
rect.top = 0;
|
||||
rect.bottom = 450;
|
||||
AdjustWindowRect( &rect, DEDSTYLE, FALSE );
|
||||
|
||||
hDC = GetDC( GetDesktopWindow() );
|
||||
swidth = GetDeviceCaps( hDC, HORZRES );
|
||||
sheight = GetDeviceCaps( hDC, VERTRES );
|
||||
ReleaseDC( GetDesktopWindow(), hDC );
|
||||
|
||||
s_wcd.windowWidth = rect.right - rect.left + 1;
|
||||
s_wcd.windowHeight = rect.bottom - rect.top + 1;
|
||||
|
||||
s_wcd.hWnd = CreateWindowEx( 0,
|
||||
DEDCLASS,
|
||||
"Jedi Knight Academy MP Console",
|
||||
DEDSTYLE,
|
||||
( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1,
|
||||
NULL,
|
||||
NULL,
|
||||
g_wv.hInstance,
|
||||
NULL );
|
||||
|
||||
if ( s_wcd.hWnd == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// create fonts
|
||||
//
|
||||
hDC = GetDC( s_wcd.hWnd );
|
||||
nHeight = -MulDiv( 8, GetDeviceCaps( hDC, LOGPIXELSY), 72);
|
||||
|
||||
s_wcd.hfBufferFont = CreateFont( nHeight,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
FW_LIGHT,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
DEFAULT_CHARSET,
|
||||
OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS,
|
||||
DEFAULT_QUALITY,
|
||||
FF_MODERN | FIXED_PITCH,
|
||||
"Courier New" );
|
||||
|
||||
ReleaseDC( s_wcd.hWnd, hDC );
|
||||
|
||||
//
|
||||
// create the input line
|
||||
//
|
||||
s_wcd.hwndInputLine = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER |
|
||||
ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP,
|
||||
6, 400, s_wcd.windowWidth-20, 20,
|
||||
s_wcd.hWnd,
|
||||
( HMENU ) INPUT_ID, // child window ID
|
||||
g_wv.hInstance, NULL );
|
||||
|
||||
//
|
||||
// create the buttons
|
||||
//
|
||||
s_wcd.hwndButtonCopy = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | WS_TABSTOP,
|
||||
5, 425, 72, 24,
|
||||
s_wcd.hWnd,
|
||||
( HMENU ) COPY_ID, // child window ID
|
||||
g_wv.hInstance, NULL );
|
||||
SendMessage( s_wcd.hwndButtonCopy, WM_SETTEXT, 0, ( LPARAM ) "Copy" );
|
||||
|
||||
s_wcd.hwndButtonClear = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | WS_TABSTOP,
|
||||
82, 425, 72, 24,
|
||||
s_wcd.hWnd,
|
||||
( HMENU ) CLEAR_ID, // child window ID
|
||||
g_wv.hInstance, NULL );
|
||||
SendMessage( s_wcd.hwndButtonClear, WM_SETTEXT, 0, ( LPARAM ) "Clear" );
|
||||
|
||||
s_wcd.hwndButtonQuit = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | WS_TABSTOP,
|
||||
s_wcd.windowWidth-92, 425, 72, 24,
|
||||
s_wcd.hWnd,
|
||||
( HMENU ) QUIT_ID, // child window ID
|
||||
g_wv.hInstance, NULL );
|
||||
SendMessage( s_wcd.hwndButtonQuit, WM_SETTEXT, 0, ( LPARAM ) "Quit" );
|
||||
|
||||
|
||||
//
|
||||
// create the scrollbuffer
|
||||
//
|
||||
s_wcd.hwndBuffer = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
|
||||
ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_TABSTOP,
|
||||
6, 40, s_wcd.windowWidth-20, 354,
|
||||
s_wcd.hWnd,
|
||||
( HMENU ) EDIT_ID, // child window ID
|
||||
g_wv.hInstance, NULL );
|
||||
SendMessage( s_wcd.hwndBuffer, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
|
||||
|
||||
s_wcd.SysInputLineWndProc = ( WNDPROC ) SetWindowLong( s_wcd.hwndInputLine, GWL_WNDPROC, ( long ) InputLineWndProc );
|
||||
SendMessage( s_wcd.hwndInputLine, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
|
||||
SendMessage( s_wcd.hwndBuffer, EM_LIMITTEXT, ( WPARAM ) 0x7fff, 0 );
|
||||
|
||||
ShowWindow( s_wcd.hWnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow( s_wcd.hWnd );
|
||||
SetForegroundWindow( s_wcd.hWnd );
|
||||
SetFocus( s_wcd.hwndInputLine );
|
||||
|
||||
s_wcd.visLevel = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sys_DestroyConsole
|
||||
*/
|
||||
void Sys_DestroyConsole( void )
|
||||
{
|
||||
if ( s_wcd.hWnd )
|
||||
{
|
||||
DeleteObject(s_wcd.hbrEditBackground);
|
||||
DeleteObject(s_wcd.hbrErrorBackground);
|
||||
DeleteObject(s_wcd.hfBufferFont);
|
||||
|
||||
ShowWindow( s_wcd.hWnd, SW_HIDE );
|
||||
CloseWindow( s_wcd.hWnd );
|
||||
DestroyWindow( s_wcd.hWnd );
|
||||
s_wcd.hWnd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Sys_ShowConsole
|
||||
*/
|
||||
void Sys_ShowConsole( int visLevel, qboolean quitOnClose )
|
||||
{
|
||||
s_wcd.quitOnClose = quitOnClose;
|
||||
|
||||
if ( visLevel == s_wcd.visLevel )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s_wcd.visLevel = visLevel;
|
||||
|
||||
if ( !s_wcd.hWnd )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( visLevel )
|
||||
{
|
||||
case 0:
|
||||
ShowWindow( s_wcd.hWnd, SW_HIDE );
|
||||
break;
|
||||
case 1:
|
||||
ShowWindow( s_wcd.hWnd, SW_SHOWNORMAL );
|
||||
SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
|
||||
break;
|
||||
case 2:
|
||||
ShowWindow( s_wcd.hWnd, SW_MINIMIZE );
|
||||
break;
|
||||
default:
|
||||
Sys_Error( "Invalid visLevel %d sent to Sys_ShowConsole\n", visLevel );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Sys_ConsoleInput
|
||||
*/
|
||||
char *Sys_ConsoleInput( void )
|
||||
{
|
||||
if ( s_wcd.consoleText[0] == 0 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy( s_wcd.returnedText, s_wcd.consoleText );
|
||||
s_wcd.consoleText[0] = 0;
|
||||
|
||||
return s_wcd.returnedText;
|
||||
}
|
||||
|
||||
/*
|
||||
** Conbuf_AppendText
|
||||
*/
|
||||
void Conbuf_AppendText( const char *pMsg )
|
||||
{
|
||||
#define CONSOLE_BUFFER_SIZE 16384
|
||||
if ( !s_wcd.hWnd ) {
|
||||
return;
|
||||
}
|
||||
char buffer[CONSOLE_BUFFER_SIZE*4];
|
||||
char *b = buffer;
|
||||
const char *msg;
|
||||
int bufLen;
|
||||
int i = 0;
|
||||
static unsigned long s_totalChars;
|
||||
|
||||
//
|
||||
// if the message is REALLY long, use just the last portion of it
|
||||
//
|
||||
if ( strlen( pMsg ) > CONSOLE_BUFFER_SIZE - 1 )
|
||||
{
|
||||
msg = pMsg + strlen( pMsg ) - CONSOLE_BUFFER_SIZE + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = pMsg;
|
||||
}
|
||||
|
||||
//
|
||||
// copy into an intermediate buffer
|
||||
//
|
||||
while ( msg[i] && ( ( b - buffer ) < sizeof( buffer ) - 1 ) )
|
||||
{
|
||||
if ( msg[i] == '\n' && msg[i+1] == '\r' )
|
||||
{
|
||||
b[0] = '\r';
|
||||
b[1] = '\n';
|
||||
b += 2;
|
||||
i++;
|
||||
}
|
||||
else if ( msg[i] == '\r' )
|
||||
{
|
||||
b[0] = '\r';
|
||||
b[1] = '\n';
|
||||
b += 2;
|
||||
}
|
||||
else if ( msg[i] == '\n' )
|
||||
{
|
||||
b[0] = '\r';
|
||||
b[1] = '\n';
|
||||
b += 2;
|
||||
}
|
||||
else if ( Q_IsColorString( &msg[i] ) )
|
||||
{
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*b= msg[i];
|
||||
b++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
*b = 0;
|
||||
bufLen = b - buffer;
|
||||
|
||||
s_totalChars += bufLen;
|
||||
|
||||
//
|
||||
// replace selection instead of appending if we're overflowing
|
||||
//
|
||||
if ( s_totalChars > 0x7fff )
|
||||
{
|
||||
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
|
||||
s_totalChars = bufLen;
|
||||
}
|
||||
|
||||
//
|
||||
// put this text into the windows console
|
||||
//
|
||||
SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
|
||||
SendMessage( s_wcd.hwndBuffer, EM_SCROLLCARET, 0, 0 );
|
||||
SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, 0, (LPARAM) buffer );
|
||||
}
|
||||
|
||||
/*
|
||||
** Sys_SetErrorText
|
||||
*/
|
||||
void Sys_SetErrorText( const char *buf )
|
||||
{
|
||||
Q_strncpyz( s_wcd.errorString, buf, sizeof( s_wcd.errorString ) );
|
||||
|
||||
if ( !s_wcd.hwndErrorBox )
|
||||
{
|
||||
s_wcd.hwndErrorBox = CreateWindow( "static", NULL, WS_CHILD | WS_VISIBLE | SS_SUNKEN,
|
||||
6, 5, s_wcd.windowWidth-20, 30,
|
||||
s_wcd.hWnd,
|
||||
( HMENU ) ERRORBOX_ID, // child window ID
|
||||
g_wv.hInstance, NULL );
|
||||
SendMessage( s_wcd.hwndErrorBox, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
|
||||
SetWindowText( s_wcd.hwndErrorBox, s_wcd.errorString );
|
||||
|
||||
DestroyWindow( s_wcd.hwndInputLine );
|
||||
s_wcd.hwndInputLine = NULL;
|
||||
}
|
||||
}
|
||||
547
codemp/win32/win_wndproc.cpp
Normal file
547
codemp/win32/win_wndproc.cpp
Normal file
@@ -0,0 +1,547 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
#include "../client/client.h"
|
||||
#include "win_local.h"
|
||||
|
||||
WinVars_t g_wv;
|
||||
|
||||
// The only directly referenced keycode - the console key (which gives different ascii codes depending on locale)
|
||||
#define CONSOLE_SCAN_CODE 0x29
|
||||
|
||||
#ifndef WM_MOUSEWHEEL
|
||||
#define WM_MOUSEWHEEL (WM_MOUSELAST+1) // message that will be supported by the OS
|
||||
#endif
|
||||
|
||||
static UINT MSH_MOUSEWHEEL;
|
||||
|
||||
// Console variables that we need to access from this module
|
||||
cvar_t *vid_xpos; // X coordinate of window position
|
||||
cvar_t *vid_ypos; // Y coordinate of window position
|
||||
static cvar_t *r_fullscreen;
|
||||
|
||||
#define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) )
|
||||
|
||||
LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
static qboolean s_alttab_disabled;
|
||||
|
||||
static void WIN_DisableAltTab( void )
|
||||
{
|
||||
if ( s_alttab_disabled )
|
||||
return;
|
||||
|
||||
if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) )
|
||||
{
|
||||
RegisterHotKey( 0, 0, MOD_ALT, VK_TAB );
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOL old;
|
||||
|
||||
SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, &old, 0 );
|
||||
}
|
||||
s_alttab_disabled = qtrue;
|
||||
}
|
||||
|
||||
static void WIN_EnableAltTab( void )
|
||||
{
|
||||
if ( s_alttab_disabled )
|
||||
{
|
||||
if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) )
|
||||
{
|
||||
UnregisterHotKey( 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOL old;
|
||||
|
||||
SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, &old, 0 );
|
||||
}
|
||||
|
||||
s_alttab_disabled = qfalse;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
VID_AppActivate
|
||||
==================
|
||||
*/
|
||||
static void VID_AppActivate(BOOL fActive, BOOL minimize)
|
||||
{
|
||||
g_wv.isMinimized = (qboolean)minimize;
|
||||
|
||||
Com_DPrintf("VID_AppActivate: %i\n", fActive );
|
||||
|
||||
Key_ClearStates(); // FIXME!!!
|
||||
|
||||
// we don't want to act like we're active if we're minimized
|
||||
if (fActive && !g_wv.isMinimized )
|
||||
{
|
||||
g_wv.activeApp = qtrue;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_wv.activeApp = qfalse;
|
||||
}
|
||||
|
||||
// minimize/restore mouse-capture on demand
|
||||
if (!g_wv.activeApp )
|
||||
{
|
||||
IN_Activate (qfalse);
|
||||
}
|
||||
else
|
||||
{
|
||||
IN_Activate (qtrue);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
||||
|
||||
static byte virtualKeyConvert[0x92][2] =
|
||||
{
|
||||
{ 0, 0 },
|
||||
{ A_MOUSE1, A_MOUSE1 }, // VK_LBUTTON 01 Left mouse button
|
||||
{ A_MOUSE2, A_MOUSE2 }, // VK_RBUTTON 02 Right mouse button
|
||||
{ 0, 0 }, // VK_CANCEL 03 Control-break processing
|
||||
{ A_MOUSE3, A_MOUSE3 }, // VK_MBUTTON 04 Middle mouse button (three-button mouse)
|
||||
{ A_MOUSE4, A_MOUSE4 }, // VK_XBUTTON1 05 Windows 2000/XP: X1 mouse button
|
||||
{ A_MOUSE5, A_MOUSE5 }, // VK_XBUTTON2 06 Windows 2000/XP: X2 mouse button
|
||||
{ 0, 0 }, // 07 Undefined
|
||||
{ A_BACKSPACE, A_BACKSPACE }, // VK_BACK 08 BACKSPACE key
|
||||
{ A_TAB, A_TAB }, // VK_TAB 09 TAB key
|
||||
{ 0, 0 }, // 0A Reserved
|
||||
{ 0, 0 }, // 0B Reserved
|
||||
{ A_KP_5, 0 }, // VK_CLEAR 0C CLEAR key
|
||||
{ A_ENTER, A_KP_ENTER }, // VK_RETURN 0D ENTER key
|
||||
{ 0, 0 }, // 0E Undefined
|
||||
{ 0, 0 }, // 0F Undefined
|
||||
{ A_SHIFT, A_SHIFT }, // VK_SHIFT 10 SHIFT key
|
||||
{ A_CTRL, A_CTRL }, // VK_CONTROL 11 CTRL key
|
||||
{ A_ALT, A_ALT }, // VK_MENU 12 ALT key
|
||||
{ A_PAUSE, A_PAUSE }, // VK_PAUSE 13 PAUSE key
|
||||
{ A_CAPSLOCK, A_CAPSLOCK }, // VK_CAPITAL 14 CAPS LOCK key
|
||||
{ 0, 0 }, // VK_KANA 15 IME Kana mode
|
||||
{ 0, 0 }, // 16 Undefined
|
||||
{ 0, 0 }, // VK_JUNJA 17 IME Junja mode
|
||||
{ 0, 0 }, // VK_FINAL 18 IME final mode
|
||||
{ 0, 0 }, // VK_KANJI 19 IME Kanji mode
|
||||
{ 0, 0 }, // 1A Undefined
|
||||
{ A_ESCAPE, A_ESCAPE }, // VK_ESCAPE 1B ESC key
|
||||
{ 0, 0 }, // VK_CONVERT 1C IME convert
|
||||
{ 0, 0 }, // VK_NONCONVERT 1D IME nonconvert
|
||||
{ 0, 0 }, // VK_ACCEPT 1E IME accept
|
||||
{ 0, 0 }, // VK_MODECHANGE 1F IME mode change request
|
||||
{ A_SPACE, A_SPACE }, // VK_SPACE 20 SPACEBAR
|
||||
{ A_KP_9, A_PAGE_UP }, // VK_PRIOR 21 PAGE UP key
|
||||
{ A_KP_3, A_PAGE_DOWN }, // VK_NEXT 22 PAGE DOWN key
|
||||
{ A_KP_1, A_END }, // VK_END 23 END key
|
||||
{ A_KP_7, A_HOME }, // VK_HOME 24 HOME key
|
||||
{ A_KP_4, A_CURSOR_LEFT }, // VK_LEFT 25 LEFT ARROW key
|
||||
{ A_KP_8, A_CURSOR_UP }, // VK_UP 26 UP ARROW key
|
||||
{ A_KP_6, A_CURSOR_RIGHT }, // VK_RIGHT 27 RIGHT ARROW key
|
||||
{ A_KP_2, A_CURSOR_DOWN }, // VK_DOWN 28 DOWN ARROW key
|
||||
{ 0, 0 }, // VK_SELECT 29 SELECT key
|
||||
{ 0, 0 }, // VK_PRINT 2A PRINT key
|
||||
{ 0, 0 }, // VK_EXECUTE 2B EXECUTE key
|
||||
{ A_PRINTSCREEN, A_PRINTSCREEN }, // VK_SNAPSHOT 2C PRINT SCREEN key
|
||||
{ A_KP_0, A_INSERT }, // VK_INSERT 2D INS key
|
||||
{ A_KP_PERIOD, A_DELETE }, // VK_DELETE 2E DEL key
|
||||
{ 0, 0 }, // VK_HELP 2F HELP key
|
||||
{ A_0, A_0 }, // 30 0 key
|
||||
{ A_1, A_1 }, // 31 1 key
|
||||
{ A_2, A_2 }, // 32 2 key
|
||||
{ A_3, A_3 }, // 33 3 key
|
||||
{ A_4, A_4 }, // 34 4 key
|
||||
{ A_5, A_5 }, // 35 5 key
|
||||
{ A_6, A_6 }, // 36 6 key
|
||||
{ A_7, A_7 }, // 37 7 key
|
||||
{ A_8, A_8 }, // 38 8 key
|
||||
{ A_9, A_9 }, // 39 9 key
|
||||
{ 0, 0 }, // 3A Undefined
|
||||
{ 0, 0 }, // 3B Undefined
|
||||
{ 0, 0 }, // 3C Undefined
|
||||
{ 0, 0 }, // 3D Undefined
|
||||
{ 0, 0 }, // 3E Undefined
|
||||
{ 0, 0 }, // 3F Undefined
|
||||
{ 0, 0 }, // 40 Undefined
|
||||
{ A_CAP_A, A_CAP_A }, // 41 A key
|
||||
{ A_CAP_B, A_CAP_B }, // 42 B key
|
||||
{ A_CAP_C, A_CAP_C }, // 43 C key
|
||||
{ A_CAP_D, A_CAP_D }, // 44 D key
|
||||
{ A_CAP_E, A_CAP_E }, // 45 E key
|
||||
{ A_CAP_F, A_CAP_F }, // 46 F key
|
||||
{ A_CAP_G, A_CAP_G }, // 47 G key
|
||||
{ A_CAP_H, A_CAP_H }, // 48 H key
|
||||
{ A_CAP_I, A_CAP_I }, // 49 I key
|
||||
{ A_CAP_J, A_CAP_J }, // 4A J key
|
||||
{ A_CAP_K, A_CAP_K }, // 4B K key
|
||||
{ A_CAP_L, A_CAP_L }, // 4C L key
|
||||
{ A_CAP_M, A_CAP_M }, // 4D M key
|
||||
{ A_CAP_N, A_CAP_N }, // 4E N key
|
||||
{ A_CAP_O, A_CAP_O }, // 4F O key
|
||||
{ A_CAP_P, A_CAP_P }, // 50 P key
|
||||
{ A_CAP_Q, A_CAP_Q }, // 51 Q key
|
||||
{ A_CAP_R, A_CAP_R }, // 52 R key
|
||||
{ A_CAP_S, A_CAP_S }, // 53 S key
|
||||
{ A_CAP_T, A_CAP_T }, // 54 T key
|
||||
{ A_CAP_U, A_CAP_U }, // 55 U key
|
||||
{ A_CAP_V, A_CAP_V }, // 56 V key
|
||||
{ A_CAP_W, A_CAP_W }, // 57 W key
|
||||
{ A_CAP_X, A_CAP_X }, // 58 X key
|
||||
{ A_CAP_Y, A_CAP_Y }, // 59 Y key
|
||||
{ A_CAP_Z, A_CAP_Z }, // 5A Z key
|
||||
{ 0, 0 }, // VK_LWIN 5B Left Windows key (Microsoft® Natural® keyboard)
|
||||
{ 0, 0 }, // VK_RWIN 5C Right Windows key (Natural keyboard)
|
||||
{ 0, 0 }, // VK_APPS 5D Applications key (Natural keyboard)
|
||||
{ 0, 0 }, // 5E Reserved
|
||||
{ 0, 0 }, // VK_SLEEP 5F Computer Sleep key
|
||||
{ A_KP_0, A_KP_0 }, // VK_NUMPAD0 60 Numeric keypad 0 key
|
||||
{ A_KP_1, A_KP_1 }, // VK_NUMPAD1 61 Numeric keypad 1 key
|
||||
{ A_KP_2, A_KP_2 }, // VK_NUMPAD2 62 Numeric keypad 2 key
|
||||
{ A_KP_3, A_KP_3 }, // VK_NUMPAD3 63 Numeric keypad 3 key
|
||||
{ A_KP_4, A_KP_4 }, // VK_NUMPAD4 64 Numeric keypad 4 key
|
||||
{ A_KP_5, A_KP_5 }, // VK_NUMPAD5 65 Numeric keypad 5 key
|
||||
{ A_KP_6, A_KP_6 }, // VK_NUMPAD6 66 Numeric keypad 6 key
|
||||
{ A_KP_7, A_KP_7 }, // VK_NUMPAD7 67 Numeric keypad 7 key
|
||||
{ A_KP_8, A_KP_8 }, // VK_NUMPAD8 68 Numeric keypad 8 key
|
||||
{ A_KP_9, A_KP_9 }, // VK_NUMPAD9 69 Numeric keypad 9 key
|
||||
{ A_MULTIPLY, A_MULTIPLY }, // VK_MULTIPLY 6A Multiply key
|
||||
{ A_KP_PLUS, A_KP_PLUS }, // VK_ADD 6B Add key
|
||||
{ 0, 0 }, // VK_SEPARATOR 6C Separator key
|
||||
{ A_KP_MINUS, A_KP_MINUS }, // VK_SUBTRACT 6D Subtract key
|
||||
{ A_KP_PERIOD, A_KP_PERIOD }, // VK_DECIMAL 6E Decimal key
|
||||
{ A_DIVIDE, A_DIVIDE }, // VK_DIVIDE 6F Divide key
|
||||
{ A_F1, A_F1 }, // VK_F1 70 F1 key
|
||||
{ A_F2, A_F2 }, // VK_F2 71 F2 key
|
||||
{ A_F3, A_F3 }, // VK_F3 72 F3 key
|
||||
{ A_F4, A_F4 }, // VK_F4 73 F4 key
|
||||
{ A_F5, A_F5 }, // VK_F5 74 F5 key
|
||||
{ A_F6, A_F6 }, // VK_F6 75 F6 key
|
||||
{ A_F7, A_F7 }, // VK_F7 76 F7 key
|
||||
{ A_F8, A_F8 }, // VK_F8 77 F8 key
|
||||
{ A_F9, A_F9 }, // VK_F9 78 F9 key
|
||||
{ A_F10, A_F10 }, // VK_F10 79 F10 key
|
||||
{ A_F11, A_F11 }, // VK_F11 7A F11 key
|
||||
{ A_F12, A_F12 }, // VK_F12 7B F12 key
|
||||
{ 0, 0 }, // VK_F13 7C F13 key
|
||||
{ 0, 0 }, // VK_F14 7D F14 key
|
||||
{ 0, 0 }, // VK_F15 7E F15 key
|
||||
{ 0, 0 }, // VK_F16 7F F16 key
|
||||
{ 0, 0 }, // VK_F17 80H F17 key
|
||||
{ 0, 0 }, // VK_F18 81H F18 key
|
||||
{ 0, 0 }, // VK_F19 82H F19 key
|
||||
{ 0, 0 }, // VK_F20 83H F20 key
|
||||
{ 0, 0 }, // VK_F21 84H F21 key
|
||||
{ 0, 0 }, // VK_F22 85H F22 key
|
||||
{ 0, 0 }, // VK_F23 86H F23 key
|
||||
{ 0, 0 }, // VK_F24 87H F24 key
|
||||
{ 0, 0 }, // 88 Unassigned
|
||||
{ 0, 0 }, // 89 Unassigned
|
||||
{ 0, 0 }, // 8A Unassigned
|
||||
{ 0, 0 }, // 8B Unassigned
|
||||
{ 0, 0 }, // 8C Unassigned
|
||||
{ 0, 0 }, // 8D Unassigned
|
||||
{ 0, 0 }, // 8E Unassigned
|
||||
{ 0, 0 }, // 8F Unassigned
|
||||
{ A_NUMLOCK, A_NUMLOCK }, // VK_NUMLOCK 90 NUM LOCK key
|
||||
{ A_SCROLLLOCK, A_SCROLLLOCK } // VK_SCROLL 91
|
||||
};
|
||||
|
||||
/*
|
||||
=======
|
||||
MapKey
|
||||
|
||||
Map from windows to quake keynums
|
||||
=======
|
||||
*/
|
||||
static int MapKey (ulong key, word wParam)
|
||||
{
|
||||
ulong result, scan, extended;
|
||||
|
||||
// Check for the console key (hard code to the key you would expect)
|
||||
scan = ( key >> 16 ) & 0xff;
|
||||
if(scan == CONSOLE_SCAN_CODE)
|
||||
{
|
||||
return(A_CONSOLE);
|
||||
}
|
||||
|
||||
// Try to convert the virtual key directly
|
||||
result = 0;
|
||||
extended = (key >> 24) & 1;
|
||||
if(wParam > 0 && wParam <= VK_SCROLL)
|
||||
{
|
||||
// yeuch, but oh well...
|
||||
//
|
||||
if ( wParam >= VK_NUMPAD0 && wParam <= VK_NUMPAD9 )
|
||||
{
|
||||
bool bNumlockOn = !!(GetKeyState( VK_NUMLOCK ) & 1);
|
||||
if ( bNumlockOn )
|
||||
{
|
||||
wParam = 0x30 + (wParam - VK_NUMPAD0); // convert to standard 0..9
|
||||
}
|
||||
}
|
||||
result = virtualKeyConvert[wParam][extended];
|
||||
}
|
||||
// Get the unshifted ascii code (if any)
|
||||
if(!result)
|
||||
{
|
||||
result = MapVirtualKey(wParam, 2) & 0xff;
|
||||
}
|
||||
// Output any debug prints
|
||||
// if(in_debug && in_debug->integer & 1)
|
||||
// {
|
||||
// Com_Printf("WM_KEY: %x : %x : %x\n", key, wParam, result);
|
||||
// }
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
MainWndProc
|
||||
|
||||
main window procedure
|
||||
====================
|
||||
*/
|
||||
|
||||
#define WM_BUTTON4DOWN (WM_MOUSELAST+2)
|
||||
#define WM_BUTTON4UP (WM_MOUSELAST+3)
|
||||
#define MK_BUTTON4L 0x0020
|
||||
#define MK_BUTTON4R 0x0040
|
||||
|
||||
LONG WINAPI MainWndProc (
|
||||
HWND hWnd,
|
||||
UINT uMsg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
byte code;
|
||||
|
||||
if ( uMsg == MSH_MOUSEWHEEL )
|
||||
{
|
||||
if ( ( ( int ) wParam ) > 0 )
|
||||
{
|
||||
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELUP, qtrue, 0, NULL );
|
||||
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELUP, qfalse, 0, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELDOWN, qtrue, 0, NULL );
|
||||
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELDOWN, qfalse, 0, NULL );
|
||||
}
|
||||
return DefWindowProc (hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_MOUSEWHEEL:
|
||||
//
|
||||
//
|
||||
// this chunk of code theoretically only works under NT4 and Win98
|
||||
// since this message doesn't exist under Win95
|
||||
//
|
||||
if ( ( short ) HIWORD( wParam ) > 0 )
|
||||
{
|
||||
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELUP, qtrue, 0, NULL );
|
||||
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELUP, qfalse, 0, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELDOWN, qtrue, 0, NULL );
|
||||
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, A_MWHEELDOWN, qfalse, 0, NULL );
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CREATE:
|
||||
|
||||
g_wv.hWnd = hWnd;
|
||||
|
||||
vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE);
|
||||
vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE);
|
||||
r_fullscreen = Cvar_Get ("r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
||||
|
||||
MSH_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG");
|
||||
if ( r_fullscreen->integer )
|
||||
{
|
||||
WIN_DisableAltTab();
|
||||
}
|
||||
else
|
||||
{
|
||||
WIN_EnableAltTab();
|
||||
}
|
||||
|
||||
break;
|
||||
#if 0
|
||||
case WM_DISPLAYCHANGE:
|
||||
Com_DPrintf( "WM_DISPLAYCHANGE\n" );
|
||||
// we need to force a vid_restart if the user has changed
|
||||
// their desktop resolution while the game is running,
|
||||
// but don't do anything if the message is a result of
|
||||
// our own calling of ChangeDisplaySettings
|
||||
if ( com_insideVidInit ) {
|
||||
break; // we did this on purpose
|
||||
}
|
||||
// something else forced a mode change, so restart all our gl stuff
|
||||
Cbuf_AddText( "vid_restart\n" );
|
||||
break;
|
||||
#endif
|
||||
case WM_DESTROY:
|
||||
// let sound and input know about this?
|
||||
g_wv.hWnd = NULL;
|
||||
if ( r_fullscreen->integer )
|
||||
{
|
||||
WIN_EnableAltTab();
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
Cbuf_ExecuteText( EXEC_APPEND, "quit" );
|
||||
break;
|
||||
|
||||
case WM_ACTIVATE:
|
||||
{
|
||||
int fActive, fMinimized;
|
||||
|
||||
fActive = LOWORD(wParam);
|
||||
fMinimized = (BOOL) HIWORD(wParam);
|
||||
|
||||
VID_AppActivate( fActive != WA_INACTIVE, fMinimized);
|
||||
SNDDMA_Activate( (qboolean)(fActive != WA_INACTIVE && !fMinimized) );
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_MOVE:
|
||||
{
|
||||
int xPos, yPos;
|
||||
RECT r;
|
||||
int style;
|
||||
|
||||
if (!r_fullscreen->integer )
|
||||
{
|
||||
xPos = (short) LOWORD(lParam); // horizontal position
|
||||
yPos = (short) HIWORD(lParam); // vertical position
|
||||
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = 1;
|
||||
r.bottom = 1;
|
||||
|
||||
style = GetWindowLong( hWnd, GWL_STYLE );
|
||||
AdjustWindowRect( &r, style, FALSE );
|
||||
|
||||
Cvar_SetValue( "vid_xpos", xPos + r.left);
|
||||
Cvar_SetValue( "vid_ypos", yPos + r.top);
|
||||
vid_xpos->modified = qfalse;
|
||||
vid_ypos->modified = qfalse;
|
||||
if ( g_wv.activeApp )
|
||||
{
|
||||
IN_Activate (qtrue);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// this is complicated because Win32 seems to pack multiple mouse events into
|
||||
// one update sometimes, so we always check all states and look for events
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_BUTTON4DOWN:
|
||||
case WM_BUTTON4UP:
|
||||
{
|
||||
int temp;
|
||||
|
||||
temp = 0;
|
||||
|
||||
if (wParam & MK_LBUTTON)
|
||||
temp |= 1;
|
||||
|
||||
if (wParam & MK_RBUTTON)
|
||||
temp |= 2;
|
||||
|
||||
if (wParam & MK_MBUTTON)
|
||||
temp |= 4;
|
||||
|
||||
if (wParam & MK_BUTTON4L)
|
||||
temp |= 8;
|
||||
|
||||
if (wParam & MK_BUTTON4R)
|
||||
temp |= 16;
|
||||
|
||||
IN_MouseEvent (temp);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
if ( (wParam&0xFFF0) == SC_SCREENSAVE || (wParam&0xFFF0) == SC_MONITORPOWER)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSKEYDOWN:
|
||||
if ( wParam == VK_RETURN )
|
||||
{
|
||||
if ( r_fullscreen && cl_allowAltEnter &&
|
||||
(cls.state==CA_DISCONNECTED || cls.state==CA_CONNECTED)
|
||||
)
|
||||
{
|
||||
if (cl_allowAltEnter->integer)
|
||||
{
|
||||
Cvar_SetValue( "r_fullscreen", !r_fullscreen->integer );
|
||||
Cbuf_AddText( "vid_restart\n" );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// fall through
|
||||
case WM_KEYDOWN:
|
||||
code = MapKey( lParam, wParam );
|
||||
if(code)
|
||||
{
|
||||
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, code, qtrue, 0, NULL );
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSKEYUP:
|
||||
case WM_KEYUP:
|
||||
code = MapKey( lParam, wParam );
|
||||
if(code)
|
||||
{
|
||||
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, code, qfalse, 0, NULL );
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CHAR:
|
||||
if(((lParam >> 16) & 0xff) != CONSOLE_SCAN_CODE)
|
||||
{
|
||||
Sys_QueEvent( g_wv.sysMsgTime, SE_CHAR, wParam, 0, 0, NULL );
|
||||
}
|
||||
// Output any debug prints
|
||||
// if(in_debug && in_debug->integer & 2)
|
||||
// {
|
||||
// Com_Printf("WM_CHAR: %x\n", wParam);
|
||||
// }
|
||||
break;
|
||||
|
||||
case WM_POWERBROADCAST:
|
||||
if (wParam == PBT_APMQUERYSUSPEND)
|
||||
{
|
||||
#ifndef FINAL_BUILD
|
||||
Com_Printf("Cannot go into hibernate / standby mode while game is running!\n");
|
||||
#endif
|
||||
return BROADCAST_QUERY_DENY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||||
}
|
||||
|
||||
1887
codemp/win32/win_worldeffects.cpp
Normal file
1887
codemp/win32/win_worldeffects.cpp
Normal file
File diff suppressed because it is too large
Load Diff
101
codemp/win32/winquake.rc
Normal file
101
codemp/win32/winquake.rc
Normal file
@@ -0,0 +1,101 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON "qe3.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
#include "AutoVersion.h"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
|
||||
PRODUCTVERSION VERSION_MAJOR_RELEASE,VERSION_MINOR_RELEASE,VERSION_EXTERNAL_BUILD,VERSION_INTERNAL_BUILD
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x0L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "Raven Software"
|
||||
VALUE "CompanyName", "Activision Inc"
|
||||
VALUE "FileDescription", "Jedi Academy MultiPlayer"
|
||||
VALUE "FileVersion", VERSION_STRING
|
||||
VALUE "InternalName", "JA MP"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2003"
|
||||
VALUE "OriginalFilename", "jamp.exe"
|
||||
VALUE "ProductName", "Jedi Knight®: Jedi Academy (MP)"
|
||||
VALUE "ProductVersion", VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
255
codemp/win32/xbox_texture_man.h
Normal file
255
codemp/win32/xbox_texture_man.h
Normal file
@@ -0,0 +1,255 @@
|
||||
|
||||
/*
|
||||
* UNPUBLISHED -- Rights reserved under the copyright laws of the
|
||||
* United States. Use of a copyright notice is precautionary only and
|
||||
* does not imply publication or disclosure.
|
||||
*
|
||||
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
|
||||
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
|
||||
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
|
||||
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
|
||||
*/
|
||||
|
||||
#ifndef __XBOX_TEXTURE_MAN_H__
|
||||
#define __XBOX_TEXTURE_MAN_H__
|
||||
|
||||
#include "glw_win_dx8.h"
|
||||
#include <xtl.h>
|
||||
|
||||
|
||||
// Texture allocator that never frees anything, just grows until it's totally reset:
|
||||
class StaticTextureAllocator
|
||||
{
|
||||
public:
|
||||
StaticTextureAllocator( void ) { }
|
||||
|
||||
void Initialize( unsigned long size )
|
||||
{
|
||||
base = (unsigned char *) D3D_AllocContiguousMemory( size, 0 );
|
||||
allocPoint = 0;
|
||||
poolSize = size;
|
||||
maxAlloc = 0;
|
||||
}
|
||||
|
||||
// No bookkeeping necessary, texNum is unused:
|
||||
void *Allocate( unsigned long size, GLuint texNum )
|
||||
{
|
||||
#ifndef FINAL_BUILD
|
||||
assert( allocPoint + size <= poolSize );
|
||||
if( allocPoint + size > poolSize )
|
||||
throw "Static texture pool full";
|
||||
#endif
|
||||
|
||||
// Current location:
|
||||
void *retVal = base + allocPoint;
|
||||
|
||||
// Advance, then round up:
|
||||
allocPoint += size;
|
||||
allocPoint = (allocPoint + 127) & ~127;
|
||||
|
||||
#ifndef FINAL_BUILD
|
||||
if( allocPoint > maxAlloc )
|
||||
maxAlloc = allocPoint;
|
||||
#endif
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void Reset( void )
|
||||
{
|
||||
// Just move our allocation marker back to the start:
|
||||
allocPoint = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned char *base;
|
||||
unsigned long allocPoint;
|
||||
unsigned long poolSize;
|
||||
unsigned long maxAlloc;
|
||||
};
|
||||
|
||||
class SwappingTextureAllocator
|
||||
{
|
||||
private:
|
||||
struct allocatedTexture_t
|
||||
{
|
||||
GLuint texNum; // Index for textureXlat
|
||||
unsigned char *data; // Pointer to data
|
||||
};
|
||||
|
||||
void _swapAllTexturesToDisk( void )
|
||||
{
|
||||
for( int i = 0; i < numTextures; ++i )
|
||||
{
|
||||
GLuint texNum = allocatedTextures[i].texNum;
|
||||
|
||||
// Get the TextureInfo *
|
||||
glwstate_t::texturexlat_t::iterator it =
|
||||
glw_state->textureXlat.find( texNum );
|
||||
glwstate_t::TextureInfo *info = &it->second;
|
||||
|
||||
//If texture has already been written out, don't write it again.
|
||||
if(info->fileOffset != -1) {
|
||||
info->inMemory = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Stall until the GPU is done with it:
|
||||
info->mipmap->BlockUntilNotBusy();
|
||||
|
||||
//File pointer may have been moved by a read. Set it to the
|
||||
//proper position.
|
||||
if(SetFilePointer(fileHandle, fileOffset, NULL, FILE_BEGIN) ==
|
||||
INVALID_SET_FILE_POINTER) {
|
||||
throw "Couldn't seek end of file";
|
||||
}
|
||||
|
||||
// Write the old texture out to disk:
|
||||
DWORD bytesWritten = 0;
|
||||
if( !WriteFile( fileHandle, allocatedTextures[i].data,
|
||||
info->size, &bytesWritten, NULL ) ||
|
||||
(bytesWritten != info->size) )
|
||||
throw "Couldn't write file";
|
||||
|
||||
// Mark texture as not in memory anymore:
|
||||
info->inMemory = false;
|
||||
|
||||
//Set file offset so we can find the texture later.
|
||||
info->fileOffset = fileOffset;
|
||||
|
||||
//Increment for the next file.
|
||||
fileOffset += info->size;
|
||||
}
|
||||
|
||||
ResetMemory();
|
||||
}
|
||||
|
||||
void ResetMemory( void )
|
||||
{
|
||||
allocPoint = 0;
|
||||
numTextures = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
SwappingTextureAllocator( void ) { }
|
||||
|
||||
void Initialize( unsigned long size )
|
||||
{
|
||||
base = (unsigned char *) D3D_AllocContiguousMemory( size, 0 );
|
||||
poolSize = size;
|
||||
fileHandle = INVALID_HANDLE_VALUE;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
// Allocate enough space for size - it's used for texture texNum:
|
||||
void *Allocate( unsigned long size, GLuint texNum )
|
||||
{
|
||||
// Check for fullness - make room
|
||||
if( allocPoint + size > poolSize )
|
||||
{
|
||||
Com_Printf( "Swapping all model textures to disk!\n" );
|
||||
_swapAllTexturesToDisk();
|
||||
}
|
||||
|
||||
// Current location:
|
||||
void *retVal = base + allocPoint;
|
||||
|
||||
// Advance, then round up:
|
||||
allocPoint += size;
|
||||
allocPoint = (allocPoint + 127) & ~127;
|
||||
|
||||
// Make a note of this texture:
|
||||
allocatedTextures[numTextures].data = (unsigned char *) retVal;
|
||||
allocatedTextures[numTextures].texNum = texNum;
|
||||
++numTextures;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// This should only be called when it's already been determined that the
|
||||
// requested texture isn't in memory. This makes room (if necessary)
|
||||
// and then re-loads it, fixing up the TextureInfo that goes with it
|
||||
void Fetch( GLuint texNum )
|
||||
{
|
||||
glwstate_t::texturexlat_t::iterator i =
|
||||
glw_state->textureXlat.find( texNum );
|
||||
glwstate_t::TextureInfo *info = &i->second;
|
||||
|
||||
unsigned char *newData = (unsigned char *) Allocate( info->size, texNum );
|
||||
|
||||
//Seek to proper file position.
|
||||
if(SetFilePointer(fileHandle, info->fileOffset, NULL, FILE_BEGIN) ==
|
||||
INVALID_SET_FILE_POINTER) {
|
||||
throw "Couldn't seek for reading";
|
||||
}
|
||||
|
||||
// Find the data that goes with this texture on disk:
|
||||
DWORD bytesRead = 0;
|
||||
if( !ReadFile( fileHandle, newData, info->size, &bytesRead, NULL ) ||
|
||||
(bytesRead != info->size) )
|
||||
throw "Couldn't read file";
|
||||
|
||||
// I'm getting errors with locked textures here. How!? Try to make it work,
|
||||
// figure out what the fuck is wrong later: VVFIXME
|
||||
if( info->mipmap->IsBusy() )
|
||||
info->mipmap->BlockUntilNotBusy();
|
||||
|
||||
// Fix up the texture data and other info:
|
||||
info->mipmap->Data = 0;
|
||||
info->mipmap->Register( newData );
|
||||
info->inMemory = true;
|
||||
}
|
||||
|
||||
void Reset( void )
|
||||
{
|
||||
ResetMemory();
|
||||
|
||||
if(fileHandle != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(fileHandle);
|
||||
}
|
||||
|
||||
fileHandle = CreateFile( "z:\\skintextures",
|
||||
GENERIC_WRITE | GENERIC_READ, 0,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
if( fileHandle == INVALID_HANDLE_VALUE )
|
||||
throw "Couldn't create texture swap file";
|
||||
|
||||
fileOffset = 0;
|
||||
}
|
||||
|
||||
// This forces all textures in memory to disk, so that the next frame or
|
||||
// so will re-load whatever's needed. It's only useful in situations where
|
||||
// you know that you're going to cache-miss on a bunch of textures, then
|
||||
// run out of space, and have to re-load them again. (Good when going in
|
||||
// and out of the in-game UI) ?
|
||||
void Flush( void )
|
||||
{
|
||||
_swapAllTexturesToDisk();
|
||||
}
|
||||
|
||||
// Just a little helper for the memory manager to see how much of the pool is used:
|
||||
unsigned long Size( void )
|
||||
{
|
||||
return allocPoint;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned char *base;
|
||||
unsigned long poolSize;
|
||||
unsigned long allocPoint;
|
||||
unsigned long fileOffset;
|
||||
HANDLE fileHandle;
|
||||
|
||||
allocatedTexture_t allocatedTextures[4096];
|
||||
int numTextures;
|
||||
};
|
||||
|
||||
// Global texture allocators:
|
||||
extern StaticTextureAllocator gStaticTextures;
|
||||
extern SwappingTextureAllocator gSkinTextures;
|
||||
|
||||
extern void BeginSkinTextures( void );
|
||||
extern void EndSkinTextures( void );
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user