Initial commit.

This commit is contained in:
Jim Gray
2013-04-04 14:32:05 -07:00
parent ba5c81da32
commit d71d53e8ec
2180 changed files with 1393544 additions and 1 deletions

View 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
View 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
View 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
View 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

View 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;
}

View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

23
codemp/win32/resource.h Normal file
View 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

View 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
View 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
View 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
View 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_

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

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

View 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

File diff suppressed because it is too large Load Diff

View 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 ) {
}

View 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;
}

View 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

File diff suppressed because it is too large Load Diff

103
codemp/win32/win_input.h Normal file
View 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_

View 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

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

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

View 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

View 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
View 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

File diff suppressed because it is too large Load Diff

View 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) {
}

File diff suppressed because it is too large Load Diff

1235
codemp/win32/win_net.cpp Normal file

File diff suppressed because it is too large Load Diff

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

File diff suppressed because it is too large Load Diff

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

File diff suppressed because it is too large Load Diff

547
codemp/win32/win_shared.cpp Normal file
View 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
View 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 ();
}
}

View 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
View 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;
}
}

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

File diff suppressed because it is too large Load Diff

101
codemp/win32/winquake.rc Normal file
View 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
/////////////////////////////////////////////////////////////////////////////

View 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