mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2026-03-20 09:00:25 +01:00
Initial commit
This commit is contained in:
109
neo/sys/win32/rc/doom.rc
Normal file
109
neo/sys/win32/rc/doom.rc
Normal file
@@ -0,0 +1,109 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "doom_resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"doom_resource.h\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\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 "res\\doom.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,1
|
||||
PRODUCTVERSION 1,0,0,1
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "id Software LLC, a ZeniMax Media company"
|
||||
VALUE "FileDescription", "DOOM 3: BFG Edition"
|
||||
VALUE "FileVersion", "1.0.0.1"
|
||||
VALUE "InternalName", "Doom3BFG"
|
||||
VALUE "LegalCopyright", "© 1993-2012 id Software LLC, a ZeniMax Media company"
|
||||
VALUE "OriginalFilename", "Doom3BFG"
|
||||
VALUE "ProductName", "DOOM® 3: BFG Edition™"
|
||||
VALUE "ProductVersion", "1.0.0.1"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
18
neo/sys/win32/rc/doom_resource.h
Normal file
18
neo/sys/win32/rc/doom_resource.h
Normal file
@@ -0,0 +1,18 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by doom.rc
|
||||
//
|
||||
#define IDI_ICON1 4001
|
||||
#define IDR_IDR_USYSGZPS11 4002
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_3D_CONTROLS 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 4003
|
||||
#define _APS_NEXT_COMMAND_VALUE 24000
|
||||
#define _APS_NEXT_CONTROL_VALUE 4200
|
||||
#define _APS_NEXT_SYMED_VALUE 4002
|
||||
#endif
|
||||
#endif
|
||||
BIN
neo/sys/win32/rc/res/doom.ico
Normal file
BIN
neo/sys/win32/rc/res/doom.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
103
neo/sys/win32/win_achievements.cpp
Normal file
103
neo/sys/win32/win_achievements.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
|
||||
#include "win_achievements.h"
|
||||
#include "../sys_session_local.h"
|
||||
|
||||
extern idCVar achievements_Verbose;
|
||||
|
||||
#define STEAM_ACHIEVEMENT_PREFIX "ach_"
|
||||
|
||||
/*
|
||||
========================
|
||||
idAchievementSystemWin::idAchievementSystemWin
|
||||
========================
|
||||
*/
|
||||
idAchievementSystemWin::idAchievementSystemWin() {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idAchievementSystemWin::IsInitialized
|
||||
========================
|
||||
*/
|
||||
bool idAchievementSystemWin::IsInitialized() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================================
|
||||
idAchievementSystemWin::AchievementUnlock
|
||||
================================
|
||||
*/
|
||||
void idAchievementSystemWin::AchievementUnlock( idLocalUser * user, int achievementID ) {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idAchievementSystemWin::AchievementLock
|
||||
========================
|
||||
*/
|
||||
void idAchievementSystemWin::AchievementLock( idLocalUser * user, const int achievementID ) {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idAchievementSystemWin::AchievementLockAll
|
||||
========================
|
||||
*/
|
||||
void idAchievementSystemWin::AchievementLockAll( idLocalUser * user, const int maxId ) {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idAchievementSystemWin::GetAchievementDescription
|
||||
========================
|
||||
*/
|
||||
bool idAchievementSystemWin::GetAchievementDescription( idLocalUser * user, const int achievementID, achievementDescription_t & data ) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idAchievementSystemWin::GetAchievementState
|
||||
========================
|
||||
*/
|
||||
bool idAchievementSystemWin::GetAchievementState( idLocalUser * user, idArray< bool, idAchievementSystem::MAX_ACHIEVEMENTS > & achievements ) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================================
|
||||
idAchievementSystemWin::Pump
|
||||
================================
|
||||
*/
|
||||
void idAchievementSystemWin::Pump() {
|
||||
}
|
||||
49
neo/sys/win32/win_achievements.h
Normal file
49
neo/sys/win32/win_achievements.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef __WIN_ACHIEVEMENTS_H__
|
||||
#define __WIN_ACHIEVEMENTS_H__
|
||||
|
||||
/*
|
||||
================================================
|
||||
idAchievementSystemWin
|
||||
================================================
|
||||
*/
|
||||
class idAchievementSystemWin : public idAchievementSystem {
|
||||
public:
|
||||
idAchievementSystemWin();
|
||||
|
||||
bool IsInitialized();
|
||||
void AchievementUnlock( idLocalUser * user, const int achievementID );
|
||||
void AchievementLock( idLocalUser * user, const int achievementID );
|
||||
void AchievementLockAll( idLocalUser * user, const int maxId );
|
||||
void Pump();
|
||||
bool GetAchievementDescription( idLocalUser * user, const int id, achievementDescription_t & data ) const;
|
||||
bool GetAchievementState( idLocalUser * user, idArray< bool, idAchievementSystem::MAX_ACHIEVEMENTS > & achievements ) const;
|
||||
};
|
||||
|
||||
#endif // __WIN_ACHIEVEMENTS_H__
|
||||
1105
neo/sys/win32/win_cpu.cpp
Normal file
1105
neo/sys/win32/win_cpu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
93
neo/sys/win32/win_gamma.cpp
Normal file
93
neo/sys/win32/win_gamma.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
/*
|
||||
** WIN_GAMMA.C
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include "win_local.h"
|
||||
#include "../../renderer/tr_local.h"
|
||||
|
||||
static unsigned short s_oldHardwareGamma[3][256];
|
||||
|
||||
/*
|
||||
** WG_GetOldGammaRamp
|
||||
**
|
||||
*/
|
||||
void WG_GetOldGammaRamp( void )
|
||||
{
|
||||
HDC hDC;
|
||||
|
||||
hDC = GetDC( GetDesktopWindow() );
|
||||
GetDeviceGammaRamp( hDC, s_oldHardwareGamma );
|
||||
ReleaseDC( GetDesktopWindow(), hDC );
|
||||
|
||||
|
||||
/*
|
||||
** GLimp_SetGamma
|
||||
**
|
||||
*/
|
||||
void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned char blue[256] )
|
||||
{
|
||||
unsigned short table[3][256];
|
||||
int i;
|
||||
|
||||
if ( !glw_state.hDC )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
if ( !SetDeviceGammaRamp( glw_state.hDC, table ) ) {
|
||||
common->Printf( "WARNING: SetDeviceGammaRamp failed.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** WG_RestoreGamma
|
||||
*/
|
||||
void WG_RestoreGamma( void )
|
||||
{
|
||||
HDC hDC;
|
||||
|
||||
// if we never read in a reasonable looking
|
||||
// table, don't write it out
|
||||
if ( s_oldHardwareGamma[0][255] == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
hDC = GetDC( GetDesktopWindow() );
|
||||
SetDeviceGammaRamp( hDC, s_oldHardwareGamma );
|
||||
ReleaseDC( GetDesktopWindow(), hDC );
|
||||
}
|
||||
|
||||
1562
neo/sys/win32/win_glimp.cpp
Normal file
1562
neo/sys/win32/win_glimp.cpp
Normal file
File diff suppressed because it is too large
Load Diff
967
neo/sys/win32/win_input.cpp
Normal file
967
neo/sys/win32/win_input.cpp
Normal file
@@ -0,0 +1,967 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
#include "../sys_session_local.h"
|
||||
|
||||
#include "win_local.h"
|
||||
|
||||
#define DINPUT_BUFFERSIZE 256
|
||||
|
||||
/*
|
||||
============================================================
|
||||
|
||||
DIRECT INPUT KEYBOARD CONTROL
|
||||
|
||||
============================================================
|
||||
*/
|
||||
|
||||
bool IN_StartupKeyboard() {
|
||||
HRESULT hr;
|
||||
bool bExclusive;
|
||||
bool bForeground;
|
||||
bool bImmediate;
|
||||
bool bDisableWindowsKey;
|
||||
DWORD dwCoopFlags;
|
||||
|
||||
if (!win32.g_pdi) {
|
||||
common->Printf("keyboard: DirectInput has not been started\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (win32.g_pKeyboard) {
|
||||
win32.g_pKeyboard->Release();
|
||||
win32.g_pKeyboard = NULL;
|
||||
}
|
||||
|
||||
// Detrimine where the buffer would like to be allocated
|
||||
bExclusive = false;
|
||||
bForeground = true;
|
||||
bImmediate = false;
|
||||
bDisableWindowsKey = true;
|
||||
|
||||
if( bExclusive )
|
||||
dwCoopFlags = DISCL_EXCLUSIVE;
|
||||
else
|
||||
dwCoopFlags = DISCL_NONEXCLUSIVE;
|
||||
|
||||
if( bForeground )
|
||||
dwCoopFlags |= DISCL_FOREGROUND;
|
||||
else
|
||||
dwCoopFlags |= DISCL_BACKGROUND;
|
||||
|
||||
// Disabling the windows key is only allowed only if we are in foreground nonexclusive
|
||||
if( bDisableWindowsKey && !bExclusive && bForeground )
|
||||
dwCoopFlags |= DISCL_NOWINKEY;
|
||||
|
||||
// Obtain an interface to the system keyboard device.
|
||||
if( FAILED( hr = win32.g_pdi->CreateDevice( GUID_SysKeyboard, &win32.g_pKeyboard, NULL ) ) ) {
|
||||
common->Printf("keyboard: couldn't find a keyboard device\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the data format to "keyboard format" - a predefined data format
|
||||
//
|
||||
// A data format specifies which controls on a device we
|
||||
// are interested in, and how they should be reported.
|
||||
//
|
||||
// This tells DirectInput that we will be passing an array
|
||||
// of 256 bytes to IDirectInputDevice::GetDeviceState.
|
||||
if( FAILED( hr = win32.g_pKeyboard->SetDataFormat( &c_dfDIKeyboard ) ) )
|
||||
return false;
|
||||
|
||||
// Set the cooperativity level to let DirectInput know how
|
||||
// this device should interact with the system and with other
|
||||
// DirectInput applications.
|
||||
hr = win32.g_pKeyboard->SetCooperativeLevel( win32.hWnd, dwCoopFlags );
|
||||
if( hr == DIERR_UNSUPPORTED && !bForeground && bExclusive ) {
|
||||
common->Printf("keyboard: SetCooperativeLevel() returned DIERR_UNSUPPORTED.\nFor security reasons, background exclusive keyboard access is not allowed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if( FAILED(hr) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !bImmediate ) {
|
||||
// IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
|
||||
//
|
||||
// DirectInput uses unbuffered I/O (buffer size = 0) by default.
|
||||
// If you want to read buffered data, you need to set a nonzero
|
||||
// buffer size.
|
||||
//
|
||||
// Set the buffer size to DINPUT_BUFFERSIZE (defined above) elements.
|
||||
//
|
||||
// The buffer size is a DWORD property associated with the device.
|
||||
DIPROPDWORD dipdw;
|
||||
|
||||
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
||||
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dipdw.diph.dwObj = 0;
|
||||
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||
dipdw.dwData = DINPUT_BUFFERSIZE; // Arbitary buffer size
|
||||
|
||||
if( FAILED( hr = win32.g_pKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
// Acquire the newly created device
|
||||
win32.g_pKeyboard->Acquire();
|
||||
|
||||
common->Printf( "keyboard: DirectInput initialized.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
IN_DeactivateKeyboard
|
||||
==========================
|
||||
*/
|
||||
void IN_DeactivateKeyboard() {
|
||||
if (!win32.g_pKeyboard) {
|
||||
return;
|
||||
}
|
||||
win32.g_pKeyboard->Unacquire( );
|
||||
}
|
||||
|
||||
/*
|
||||
============================================================
|
||||
|
||||
DIRECT INPUT MOUSE CONTROL
|
||||
|
||||
============================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
========================
|
||||
IN_InitDirectInput
|
||||
========================
|
||||
*/
|
||||
|
||||
void IN_InitDirectInput() {
|
||||
HRESULT hr;
|
||||
|
||||
common->Printf( "Initializing DirectInput...\n" );
|
||||
|
||||
if ( win32.g_pdi != NULL ) {
|
||||
win32.g_pdi->Release(); // if the previous window was destroyed we need to do this
|
||||
win32.g_pdi = NULL;
|
||||
}
|
||||
|
||||
// Register with the DirectInput subsystem and get a pointer
|
||||
// to a IDirectInput interface we can use.
|
||||
// Create the base DirectInput object
|
||||
if ( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&win32.g_pdi, NULL ) ) ) {
|
||||
common->Printf ("DirectInputCreate failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
IN_InitDIMouse
|
||||
========================
|
||||
*/
|
||||
bool IN_InitDIMouse() {
|
||||
HRESULT hr;
|
||||
|
||||
if ( win32.g_pdi == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// obtain an interface to the system mouse device.
|
||||
hr = win32.g_pdi->CreateDevice( GUID_SysMouse, &win32.g_pMouse, NULL);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
common->Printf ("mouse: Couldn't open DI mouse device\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the data format to "mouse format" - a predefined data format
|
||||
//
|
||||
// A data format specifies which controls on a device we
|
||||
// are interested in, and how they should be reported.
|
||||
//
|
||||
// This tells DirectInput that we will be passing a
|
||||
// DIMOUSESTATE2 structure to IDirectInputDevice::GetDeviceState.
|
||||
if( FAILED( hr = win32.g_pMouse->SetDataFormat( &c_dfDIMouse2 ) ) ) {
|
||||
common->Printf ("mouse: Couldn't set DI mouse format\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the cooperativity level.
|
||||
hr = win32.g_pMouse->SetCooperativeLevel( win32.hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
common->Printf ("mouse: Couldn't set DI coop level\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
|
||||
//
|
||||
// DirectInput uses unbuffered I/O (buffer size = 0) by default.
|
||||
// If you want to read buffered data, you need to set a nonzero
|
||||
// buffer size.
|
||||
//
|
||||
// Set the buffer size to SAMPLE_BUFFER_SIZE (defined above) elements.
|
||||
//
|
||||
// The buffer size is a DWORD property associated with the device.
|
||||
DIPROPDWORD dipdw;
|
||||
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
||||
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dipdw.diph.dwObj = 0;
|
||||
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||
dipdw.dwData = DINPUT_BUFFERSIZE; // Arbitary buffer size
|
||||
|
||||
if( FAILED( hr = win32.g_pMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) ) {
|
||||
common->Printf ("mouse: Couldn't set DI buffersize\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
IN_ActivateMouse();
|
||||
|
||||
// clear any pending samples
|
||||
int mouseEvents[MAX_MOUSE_EVENTS][2];
|
||||
Sys_PollMouseInputEvents( mouseEvents );
|
||||
|
||||
common->Printf( "mouse: DirectInput initialized.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==========================
|
||||
IN_ActivateMouse
|
||||
==========================
|
||||
*/
|
||||
void IN_ActivateMouse() {
|
||||
int i;
|
||||
HRESULT hr;
|
||||
|
||||
if ( !win32.in_mouse.GetBool() || win32.mouseGrabbed || !win32.g_pMouse ) {
|
||||
return;
|
||||
}
|
||||
|
||||
win32.mouseGrabbed = true;
|
||||
for ( i = 0; i < 10; i++ ) {
|
||||
if ( ::ShowCursor( false ) < 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// we may fail to reacquire if the window has been recreated
|
||||
hr = win32.g_pMouse->Acquire();
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set the cooperativity level.
|
||||
hr = win32.g_pMouse->SetCooperativeLevel( win32.hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
IN_DeactivateMouse
|
||||
==========================
|
||||
*/
|
||||
void IN_DeactivateMouse() {
|
||||
int i;
|
||||
|
||||
if (!win32.g_pMouse || !win32.mouseGrabbed ) {
|
||||
return;
|
||||
}
|
||||
|
||||
win32.g_pMouse->Unacquire();
|
||||
|
||||
for ( i = 0; i < 10; i++ ) {
|
||||
if ( ::ShowCursor( true ) >= 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
win32.mouseGrabbed = false;
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
IN_DeactivateMouseIfWindowed
|
||||
==========================
|
||||
*/
|
||||
void IN_DeactivateMouseIfWindowed() {
|
||||
if ( !win32.cdsFullscreen ) {
|
||||
IN_DeactivateMouse();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============================================================
|
||||
|
||||
MOUSE CONTROL
|
||||
|
||||
============================================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
Sys_ShutdownInput
|
||||
===========
|
||||
*/
|
||||
void Sys_ShutdownInput() {
|
||||
IN_DeactivateMouse();
|
||||
IN_DeactivateKeyboard();
|
||||
if ( win32.g_pKeyboard ) {
|
||||
win32.g_pKeyboard->Release();
|
||||
win32.g_pKeyboard = NULL;
|
||||
}
|
||||
|
||||
if ( win32.g_pMouse ) {
|
||||
win32.g_pMouse->Release();
|
||||
win32.g_pMouse = NULL;
|
||||
}
|
||||
|
||||
if ( win32.g_pdi ) {
|
||||
win32.g_pdi->Release();
|
||||
win32.g_pdi = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
Sys_InitInput
|
||||
===========
|
||||
*/
|
||||
void Sys_InitInput() {
|
||||
common->Printf ("\n------- Input Initialization -------\n");
|
||||
IN_InitDirectInput();
|
||||
if ( win32.in_mouse.GetBool() ) {
|
||||
IN_InitDIMouse();
|
||||
// don't grab the mouse on initialization
|
||||
Sys_GrabMouseCursor( false );
|
||||
} else {
|
||||
common->Printf ("Mouse control not active.\n");
|
||||
}
|
||||
IN_StartupKeyboard();
|
||||
|
||||
common->Printf ("------------------------------------\n");
|
||||
win32.in_mouse.ClearModified();
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
IN_Frame
|
||||
|
||||
Called every frame, even if not generating commands
|
||||
==================
|
||||
*/
|
||||
void IN_Frame() {
|
||||
bool shouldGrab = true;
|
||||
|
||||
if ( !win32.in_mouse.GetBool() ) {
|
||||
shouldGrab = false;
|
||||
}
|
||||
// if fullscreen, we always want the mouse
|
||||
if ( !win32.cdsFullscreen ) {
|
||||
if ( win32.mouseReleased ) {
|
||||
shouldGrab = false;
|
||||
}
|
||||
if ( win32.movingWindow ) {
|
||||
shouldGrab = false;
|
||||
}
|
||||
if ( !win32.activeApp ) {
|
||||
shouldGrab = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( shouldGrab != win32.mouseGrabbed ) {
|
||||
if ( usercmdGen != NULL ) {
|
||||
usercmdGen->Clear();
|
||||
}
|
||||
|
||||
if ( win32.mouseGrabbed ) {
|
||||
IN_DeactivateMouse();
|
||||
} else {
|
||||
IN_ActivateMouse();
|
||||
|
||||
#if 0 // if we can't reacquire, try reinitializing
|
||||
if ( !IN_InitDIMouse() ) {
|
||||
win32.in_mouse.SetBool( false );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Sys_GrabMouseCursor( bool grabIt ) {
|
||||
win32.mouseReleased = !grabIt;
|
||||
if ( !grabIt ) {
|
||||
// release it right now
|
||||
IN_Frame();
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
|
||||
static DIDEVICEOBJECTDATA polled_didod[ DINPUT_BUFFERSIZE ]; // Receives buffered data
|
||||
|
||||
static int diFetch;
|
||||
static byte toggleFetch[2][ 256 ];
|
||||
|
||||
|
||||
#if 1
|
||||
// I tried doing the full-state get to address a keyboard problem on one system,
|
||||
// but it didn't make any difference
|
||||
|
||||
/*
|
||||
====================
|
||||
Sys_PollKeyboardInputEvents
|
||||
====================
|
||||
*/
|
||||
int Sys_PollKeyboardInputEvents() {
|
||||
DWORD dwElements;
|
||||
HRESULT hr;
|
||||
|
||||
if( win32.g_pKeyboard == NULL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
dwElements = DINPUT_BUFFERSIZE;
|
||||
hr = win32.g_pKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
|
||||
polled_didod, &dwElements, 0 );
|
||||
if( hr != DI_OK )
|
||||
{
|
||||
// We got an error or we got DI_BUFFEROVERFLOW.
|
||||
//
|
||||
// Either way, it means that continuous contact with the
|
||||
// device has been lost, either due to an external
|
||||
// interruption, or because the buffer overflowed
|
||||
// and some events were lost.
|
||||
hr = win32.g_pKeyboard->Acquire();
|
||||
|
||||
|
||||
|
||||
// nuke the garbage
|
||||
if (!FAILED(hr)) {
|
||||
//Bug 951: The following command really clears the garbage input.
|
||||
//The original will still process keys in the buffer and was causing
|
||||
//some problems.
|
||||
win32.g_pKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), NULL, &dwElements, 0 );
|
||||
dwElements = 0;
|
||||
}
|
||||
// hr may be DIERR_OTHERAPPHASPRIO or other errors. This
|
||||
// may occur when the app is minimized or in the process of
|
||||
// switching, so just try again later
|
||||
}
|
||||
|
||||
if( FAILED(hr) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dwElements;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
====================
|
||||
Sys_PollKeyboardInputEvents
|
||||
|
||||
Fake events by getting the entire device state
|
||||
and checking transitions
|
||||
====================
|
||||
*/
|
||||
int Sys_PollKeyboardInputEvents() {
|
||||
HRESULT hr;
|
||||
|
||||
if( win32.g_pKeyboard == NULL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
hr = win32.g_pKeyboard->GetDeviceState( sizeof( toggleFetch[ diFetch ] ), toggleFetch[ diFetch ] );
|
||||
if( hr != DI_OK )
|
||||
{
|
||||
// We got an error or we got DI_BUFFEROVERFLOW.
|
||||
//
|
||||
// Either way, it means that continuous contact with the
|
||||
// device has been lost, either due to an external
|
||||
// interruption, or because the buffer overflowed
|
||||
// and some events were lost.
|
||||
hr = win32.g_pKeyboard->Acquire();
|
||||
|
||||
// nuke the garbage
|
||||
if (!FAILED(hr)) {
|
||||
hr = win32.g_pKeyboard->GetDeviceState( sizeof( toggleFetch[ diFetch ] ), toggleFetch[ diFetch ] );
|
||||
}
|
||||
// hr may be DIERR_OTHERAPPHASPRIO or other errors. This
|
||||
// may occur when the app is minimized or in the process of
|
||||
// switching, so just try again later
|
||||
}
|
||||
|
||||
if( FAILED(hr) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// build faked events
|
||||
int numChanges = 0;
|
||||
|
||||
for ( int i = 0 ; i < 256 ; i++ ) {
|
||||
if ( toggleFetch[0][i] != toggleFetch[1][i] ) {
|
||||
polled_didod[ numChanges ].dwOfs = i;
|
||||
polled_didod[ numChanges ].dwData = toggleFetch[ diFetch ][i] ? 0x80 : 0;
|
||||
numChanges++;
|
||||
}
|
||||
}
|
||||
|
||||
diFetch ^= 1;
|
||||
|
||||
return numChanges;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
====================
|
||||
Sys_PollKeyboardInputEvents
|
||||
====================
|
||||
*/
|
||||
int Sys_ReturnKeyboardInputEvent( const int n, int &ch, bool &state ) {
|
||||
ch = polled_didod[ n ].dwOfs;
|
||||
state = ( polled_didod[ n ].dwData & 0x80 ) == 0x80;
|
||||
if ( ch == K_PRINTSCREEN || ch == K_LCTRL || ch == K_LALT || ch == K_RCTRL || ch == K_RALT ) {
|
||||
// for windows, add a keydown event for print screen here, since
|
||||
// windows doesn't send keydown events to the WndProc for this key.
|
||||
// ctrl and alt are handled here to get around windows sending ctrl and
|
||||
// alt messages when the right-alt is pressed on non-US 102 keyboards.
|
||||
Sys_QueEvent( SE_KEY, ch, state, 0, NULL, 0 );
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
|
||||
void Sys_EndKeyboardInputEvents() {
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
|
||||
|
||||
int Sys_PollMouseInputEvents( int mouseEvents[MAX_MOUSE_EVENTS][2] ) {
|
||||
DWORD dwElements;
|
||||
HRESULT hr;
|
||||
|
||||
if ( !win32.g_pMouse || !win32.mouseGrabbed ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
dwElements = DINPUT_BUFFERSIZE;
|
||||
hr = win32.g_pMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), polled_didod, &dwElements, 0 );
|
||||
|
||||
if( hr != DI_OK ) {
|
||||
hr = win32.g_pMouse->Acquire();
|
||||
// clear the garbage
|
||||
if (!FAILED(hr)) {
|
||||
win32.g_pMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), polled_didod, &dwElements, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
if( FAILED(hr) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( dwElements > MAX_MOUSE_EVENTS ) {
|
||||
dwElements = MAX_MOUSE_EVENTS;
|
||||
}
|
||||
|
||||
for( DWORD i = 0; i < dwElements; i++ ) {
|
||||
mouseEvents[i][0] = M_INVALID;
|
||||
mouseEvents[i][1] = 0;
|
||||
|
||||
if ( polled_didod[i].dwOfs >= DIMOFS_BUTTON0 && polled_didod[i].dwOfs <= DIMOFS_BUTTON7 ) {
|
||||
const int mouseButton = ( polled_didod[i].dwOfs - DIMOFS_BUTTON0 );
|
||||
const bool mouseDown = (polled_didod[i].dwData & 0x80) == 0x80;
|
||||
mouseEvents[i][0] = M_ACTION1 + mouseButton;
|
||||
mouseEvents[i][1] = mouseDown;
|
||||
Sys_QueEvent( SE_KEY, K_MOUSE1 + mouseButton, mouseDown, 0, NULL, 0 );
|
||||
} else {
|
||||
switch (polled_didod[i].dwOfs) {
|
||||
case DIMOFS_X:
|
||||
mouseEvents[i][0] = M_DELTAX;
|
||||
mouseEvents[i][1] = polled_didod[i].dwData;
|
||||
Sys_QueEvent( SE_MOUSE, polled_didod[i].dwData, 0, 0, NULL, 0 );
|
||||
break;
|
||||
case DIMOFS_Y:
|
||||
mouseEvents[i][0] = M_DELTAY;
|
||||
mouseEvents[i][1] = polled_didod[i].dwData;
|
||||
Sys_QueEvent( SE_MOUSE, 0, polled_didod[i].dwData, 0, NULL, 0 );
|
||||
break;
|
||||
case DIMOFS_Z:
|
||||
mouseEvents[i][0] = M_DELTAZ;
|
||||
mouseEvents[i][1] = (int)polled_didod[i].dwData / WHEEL_DELTA;
|
||||
{
|
||||
const int value = (int)polled_didod[i].dwData / WHEEL_DELTA;
|
||||
const int key = value < 0 ? K_MWHEELDOWN : K_MWHEELUP;
|
||||
const int iterations = abs( value );
|
||||
for ( int i = 0; i < iterations; i++ ) {
|
||||
Sys_QueEvent( SE_KEY, key, true, 0, NULL, 0 );
|
||||
Sys_QueEvent( SE_KEY, key, false, 0, NULL, 0 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dwElements;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Joystick Input Handling
|
||||
//=====================================================================================
|
||||
|
||||
void Sys_SetRumble( int device, int low, int hi ) {
|
||||
return win32.g_Joystick.SetRumble( device, low, hi );
|
||||
}
|
||||
|
||||
int Sys_PollJoystickInputEvents( int deviceNum ) {
|
||||
return win32.g_Joystick.PollInputEvents( deviceNum );
|
||||
}
|
||||
|
||||
|
||||
int Sys_ReturnJoystickInputEvent( const int n, int &action, int &value ) {
|
||||
return win32.g_Joystick.ReturnInputEvent( n, action, value );
|
||||
}
|
||||
|
||||
|
||||
void Sys_EndJoystickInputEvents() {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
JoystickSamplingThread
|
||||
========================
|
||||
*/
|
||||
static int threadTimeDeltas[256];
|
||||
static int threadPacket[256];
|
||||
static int threadCount;
|
||||
void JoystickSamplingThread( void *data ) {
|
||||
static int prevTime = 0;
|
||||
static uint64 nextCheck[MAX_JOYSTICKS] = { 0 };
|
||||
const uint64 waitTime = 5000000; // poll every 5 seconds to see if a controller was connected
|
||||
while( 1 ) {
|
||||
// hopefully we see close to 4000 usec each loop
|
||||
int now = Sys_Microseconds();
|
||||
int delta;
|
||||
if ( prevTime == 0 ) {
|
||||
delta = 4000;
|
||||
} else {
|
||||
delta = now - prevTime;
|
||||
}
|
||||
prevTime = now;
|
||||
threadTimeDeltas[threadCount&255] = delta;
|
||||
threadCount++;
|
||||
|
||||
{
|
||||
XINPUT_STATE joyData[MAX_JOYSTICKS];
|
||||
bool validData[MAX_JOYSTICKS];
|
||||
for ( int i = 0 ; i < MAX_JOYSTICKS ; i++ ) {
|
||||
if ( now >= nextCheck[i] ) {
|
||||
// XInputGetState might block... for a _really_ long time..
|
||||
validData[i] = XInputGetState( i, &joyData[i] ) == ERROR_SUCCESS;
|
||||
|
||||
// allow an immediate data poll if the input device is connected else
|
||||
// wait for some time to see if another device was reconnected.
|
||||
// Checking input state infrequently for newly connected devices prevents
|
||||
// severe slowdowns on PC, especially on WinXP64.
|
||||
if ( validData[i] ) {
|
||||
nextCheck[i] = 0;
|
||||
} else {
|
||||
nextCheck[i] = now + waitTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do this short amount of processing inside a critical section
|
||||
idScopedCriticalSection cs( win32.g_Joystick.mutexXis );
|
||||
|
||||
for ( int i = 0 ; i < MAX_JOYSTICKS ; i++ ) {
|
||||
controllerState_t * cs = &win32.g_Joystick.controllers[i];
|
||||
|
||||
if ( !validData[i] ) {
|
||||
cs->valid = false;
|
||||
continue;
|
||||
}
|
||||
cs->valid = true;
|
||||
|
||||
XINPUT_STATE& current = joyData[i];
|
||||
|
||||
cs->current = current;
|
||||
|
||||
// Switch from using cs->current to current to reduce chance of Load-Hit-Store on consoles
|
||||
|
||||
threadPacket[threadCount&255] = current.dwPacketNumber;
|
||||
#if 0
|
||||
if ( xis.dwPacketNumber == oldXis[ inputDeviceNum ].dwPacketNumber ) {
|
||||
return numEvents;
|
||||
}
|
||||
#endif
|
||||
cs->buttonBits |= current.Gamepad.wButtons;
|
||||
}
|
||||
}
|
||||
|
||||
// we want this to be processed at least 250 times a second
|
||||
WaitForSingleObject( win32.g_Joystick.timer, INFINITE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
idJoystickWin32::idJoystickWin32
|
||||
========================
|
||||
*/
|
||||
idJoystickWin32::idJoystickWin32() {
|
||||
numEvents = 0;
|
||||
memset( &events, 0, sizeof( events ) );
|
||||
memset( &controllers, 0, sizeof( controllers ) );
|
||||
memset( buttonStates, 0, sizeof( buttonStates ) );
|
||||
memset( joyAxis, 0, sizeof( joyAxis ) );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idJoystickWin32::Init
|
||||
========================
|
||||
*/
|
||||
bool idJoystickWin32::Init() {
|
||||
idJoystick::Init();
|
||||
|
||||
// setup the timer that the high frequency thread will wait on
|
||||
// to fire every 4 msec
|
||||
timer = CreateWaitableTimer( NULL, FALSE, "JoypadTimer" );
|
||||
LARGE_INTEGER dueTime;
|
||||
dueTime.QuadPart = -1;
|
||||
if ( !SetWaitableTimer( timer, &dueTime, 4, NULL, NULL, FALSE ) ) {
|
||||
idLib::FatalError( "SetWaitableTimer for joystick failed" );
|
||||
}
|
||||
|
||||
// spawn the high frequency joystick reading thread
|
||||
Sys_CreateThread( (xthread_t)JoystickSamplingThread, NULL, THREAD_HIGHEST, "Joystick", CORE_1A );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idJoystickWin32::SetRumble
|
||||
========================
|
||||
*/
|
||||
void idJoystickWin32::SetRumble( int inputDeviceNum, int rumbleLow, int rumbleHigh ) {
|
||||
if ( inputDeviceNum < 0 || inputDeviceNum >= MAX_JOYSTICKS ) {
|
||||
return;
|
||||
}
|
||||
if ( !controllers[inputDeviceNum].valid ) {
|
||||
return;
|
||||
}
|
||||
XINPUT_VIBRATION vibration;
|
||||
vibration.wLeftMotorSpeed = idMath::ClampInt( 0, 65535, rumbleLow );
|
||||
vibration.wRightMotorSpeed = idMath::ClampInt( 0, 65535, rumbleHigh );
|
||||
DWORD err = XInputSetState( inputDeviceNum, &vibration );
|
||||
if ( err != ERROR_SUCCESS ) {
|
||||
idLib::Warning( "XInputSetState error: 0x%x", err );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idJoystickWin32::PostInputEvent
|
||||
========================
|
||||
*/
|
||||
void idJoystickWin32::PostInputEvent( int inputDeviceNum, int event, int value, int range ) {
|
||||
// These events are used for GUI button presses
|
||||
if ( ( event >= J_ACTION1 ) && ( event <= J_ACTION_MAX ) ) {
|
||||
PushButton( inputDeviceNum, K_JOY1 + ( event - J_ACTION1 ), value != 0 );
|
||||
} else if ( event == J_AXIS_LEFT_X ) {
|
||||
PushButton( inputDeviceNum, K_JOY_STICK1_LEFT, ( value < -range ) );
|
||||
PushButton( inputDeviceNum, K_JOY_STICK1_RIGHT, ( value > range ) );
|
||||
} else if ( event == J_AXIS_LEFT_Y ) {
|
||||
PushButton( inputDeviceNum, K_JOY_STICK1_UP, ( value < -range ) );
|
||||
PushButton( inputDeviceNum, K_JOY_STICK1_DOWN, ( value > range ) );
|
||||
} else if ( event == J_AXIS_RIGHT_X ) {
|
||||
PushButton( inputDeviceNum, K_JOY_STICK2_LEFT, ( value < -range ) );
|
||||
PushButton( inputDeviceNum, K_JOY_STICK2_RIGHT, ( value > range ) );
|
||||
} else if ( event == J_AXIS_RIGHT_Y ) {
|
||||
PushButton( inputDeviceNum, K_JOY_STICK2_UP, ( value < -range ) );
|
||||
PushButton( inputDeviceNum, K_JOY_STICK2_DOWN, ( value > range ) );
|
||||
} else if ( ( event >= J_DPAD_UP ) && ( event <= J_DPAD_RIGHT ) ) {
|
||||
PushButton( inputDeviceNum, K_JOY_DPAD_UP + ( event - J_DPAD_UP ), value != 0 );
|
||||
} else if ( event == J_AXIS_LEFT_TRIG ) {
|
||||
PushButton( inputDeviceNum, K_JOY_TRIGGER1, ( value > range ) );
|
||||
} else if ( event == J_AXIS_RIGHT_TRIG ) {
|
||||
PushButton( inputDeviceNum, K_JOY_TRIGGER2, ( value > range ) );
|
||||
}
|
||||
if ( event >= J_AXIS_MIN && event <= J_AXIS_MAX ) {
|
||||
int axis = event - J_AXIS_MIN;
|
||||
int percent = ( value * 16 ) / range;
|
||||
if ( joyAxis[inputDeviceNum][axis] != percent ) {
|
||||
joyAxis[inputDeviceNum][axis] = percent;
|
||||
Sys_QueEvent( SE_JOYSTICK, axis, percent, 0, NULL, inputDeviceNum );
|
||||
}
|
||||
}
|
||||
|
||||
// These events are used for actual game input
|
||||
events[numEvents].event = event;
|
||||
events[numEvents].value = value;
|
||||
numEvents++;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idJoystickWin32::PollInputEvents
|
||||
========================
|
||||
*/
|
||||
int idJoystickWin32::PollInputEvents( int inputDeviceNum ) {
|
||||
numEvents = 0;
|
||||
|
||||
if ( !win32.activeApp ) {
|
||||
return numEvents;
|
||||
}
|
||||
|
||||
assert( inputDeviceNum < 4 );
|
||||
|
||||
// if ( inputDeviceNum > in_joystick.GetInteger() ) {
|
||||
// return numEvents;
|
||||
// }
|
||||
|
||||
controllerState_t *cs = &controllers[ inputDeviceNum ];
|
||||
|
||||
// grab the current packet under a critical section
|
||||
XINPUT_STATE xis;
|
||||
XINPUT_STATE old;
|
||||
int orBits;
|
||||
{
|
||||
idScopedCriticalSection crit( mutexXis );
|
||||
xis = cs->current;
|
||||
old = cs->previous;
|
||||
cs->previous = xis;
|
||||
// fetch or'd button bits
|
||||
orBits = cs->buttonBits;
|
||||
cs->buttonBits = 0;
|
||||
}
|
||||
#if 0
|
||||
if ( XInputGetState( inputDeviceNum, &xis ) != ERROR_SUCCESS ) {
|
||||
return numEvents;
|
||||
}
|
||||
#endif
|
||||
for ( int i = 0 ; i < 32 ; i++ ) {
|
||||
int bit = 1<<i;
|
||||
|
||||
if ( ( ( xis.Gamepad.wButtons | old.Gamepad.wButtons ) & bit ) == 0
|
||||
&& ( orBits & bit ) ) {
|
||||
idLib::Printf( "Dropped button press on bit %i\n", i );
|
||||
}
|
||||
}
|
||||
|
||||
if ( session->IsSystemUIShowing() ) {
|
||||
// memset xis so the current input does not get latched if the UI is showing
|
||||
memset( &xis, 0, sizeof( XINPUT_STATE ) );
|
||||
}
|
||||
|
||||
int joyRemap[16] = {
|
||||
J_DPAD_UP, J_DPAD_DOWN, // Up, Down
|
||||
J_DPAD_LEFT, J_DPAD_RIGHT, // Left, Right
|
||||
J_ACTION9, J_ACTION10, // Start, Back
|
||||
J_ACTION7, J_ACTION8, // Left Stick Down, Right Stick Down
|
||||
J_ACTION5, J_ACTION6, // Black, White (Left Shoulder, Right Shoulder)
|
||||
0, 0, // Unused
|
||||
J_ACTION1, J_ACTION2, // A, B
|
||||
J_ACTION3, J_ACTION4, // X, Y
|
||||
};
|
||||
|
||||
// Check the digital buttons
|
||||
for ( int i = 0; i < 16; i++ ) {
|
||||
int mask = ( 1 << i );
|
||||
if ( ( xis.Gamepad.wButtons & mask ) != ( old.Gamepad.wButtons & mask ) ) {
|
||||
PostInputEvent( inputDeviceNum, joyRemap[i], ( xis.Gamepad.wButtons & mask ) > 0 );
|
||||
}
|
||||
}
|
||||
|
||||
// Check the triggers
|
||||
if ( xis.Gamepad.bLeftTrigger != old.Gamepad.bLeftTrigger ) {
|
||||
PostInputEvent( inputDeviceNum, J_AXIS_LEFT_TRIG, xis.Gamepad.bLeftTrigger * 128 );
|
||||
}
|
||||
if ( xis.Gamepad.bRightTrigger != old.Gamepad.bRightTrigger ) {
|
||||
PostInputEvent( inputDeviceNum, J_AXIS_RIGHT_TRIG, xis.Gamepad.bRightTrigger * 128 );
|
||||
}
|
||||
|
||||
if ( xis.Gamepad.sThumbLX != old.Gamepad.sThumbLX ) {
|
||||
PostInputEvent( inputDeviceNum, J_AXIS_LEFT_X, xis.Gamepad.sThumbLX );
|
||||
}
|
||||
if ( xis.Gamepad.sThumbLY != old.Gamepad.sThumbLY ) {
|
||||
PostInputEvent( inputDeviceNum, J_AXIS_LEFT_Y, -xis.Gamepad.sThumbLY );
|
||||
}
|
||||
if ( xis.Gamepad.sThumbRX != old.Gamepad.sThumbRX ) {
|
||||
PostInputEvent( inputDeviceNum, J_AXIS_RIGHT_X, xis.Gamepad.sThumbRX );
|
||||
}
|
||||
if ( xis.Gamepad.sThumbRY != old.Gamepad.sThumbRY ) {
|
||||
PostInputEvent( inputDeviceNum, J_AXIS_RIGHT_Y, -xis.Gamepad.sThumbRY );
|
||||
}
|
||||
|
||||
return numEvents;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
idJoystickWin32::ReturnInputEvent
|
||||
========================
|
||||
*/
|
||||
int idJoystickWin32::ReturnInputEvent( const int n, int & action, int &value ) {
|
||||
if ( ( n < 0 ) || ( n >= MAX_JOY_EVENT ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
action = events[ n ].event;
|
||||
value = events[ n ].value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idJoystickWin32::PushButton
|
||||
========================
|
||||
*/
|
||||
void idJoystickWin32::PushButton( int inputDeviceNum, int key, bool value ) {
|
||||
// So we don't keep sending the same SE_KEY message over and over again
|
||||
if ( buttonStates[inputDeviceNum][key] != value ) {
|
||||
buttonStates[inputDeviceNum][key] = value;
|
||||
Sys_QueEvent( SE_KEY, key, value, 0, NULL, inputDeviceNum );
|
||||
}
|
||||
}
|
||||
96
neo/sys/win32/win_input.h
Normal file
96
neo/sys/win32/win_input.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
|
||||
//#if defined( ID_VS2010 )
|
||||
//#include "../../../libs/dxsdk_June2010/include/xinput.h"
|
||||
//#else
|
||||
#include <Xinput.h>
|
||||
//#endif
|
||||
|
||||
static const int MAX_JOYSTICKS = 4;
|
||||
|
||||
/*
|
||||
================================================================================================
|
||||
|
||||
Joystick Win32
|
||||
|
||||
================================================================================================
|
||||
*/
|
||||
|
||||
struct controllerState_t {
|
||||
// the current states are updated by the input thread at 250 hz
|
||||
XINPUT_STATE current;
|
||||
|
||||
// the previous state is latched at polling time
|
||||
XINPUT_STATE previous;
|
||||
|
||||
// The current button bits are or'd into this at the high sampling rate, then
|
||||
// zero'd by the main thread when a usercmd_t is created. This prevents the
|
||||
// complete missing of a button press that went down and up between two usercmd_t
|
||||
// creations, although it can add sn extra frame of latency to sensing a release.
|
||||
int buttonBits;
|
||||
|
||||
// Only valid controllers will have their rumble set
|
||||
bool valid;
|
||||
};
|
||||
|
||||
|
||||
class idJoystickWin32 : idJoystick {
|
||||
public:
|
||||
idJoystickWin32();
|
||||
|
||||
virtual bool Init();
|
||||
virtual void SetRumble( int deviceNum, int rumbleLow, int rumbleHigh );
|
||||
virtual int PollInputEvents( int inputDeviceNum );
|
||||
virtual int ReturnInputEvent( const int n, int &action, int &value );
|
||||
virtual void EndInputEvents() {}
|
||||
|
||||
protected:
|
||||
friend void JoystickSamplingThread( void *data );
|
||||
|
||||
void PushButton( int inputDeviceNum, int key, bool value );
|
||||
void PostInputEvent( int inputDeviceNum, int event, int value, int range = 16384 );
|
||||
|
||||
idSysMutex mutexXis; // lock this before using currentXis or stickIntegrations
|
||||
HANDLE timer; // fire every 4 msec
|
||||
|
||||
int numEvents;
|
||||
|
||||
struct {
|
||||
int event;
|
||||
int value;
|
||||
} events[ MAX_JOY_EVENT ];
|
||||
|
||||
controllerState_t controllers[ MAX_JOYSTICKS ];
|
||||
|
||||
// should these be per-controller?
|
||||
bool buttonStates[MAX_INPUT_DEVICES][K_LAST_KEY]; // For keeping track of button up/down events
|
||||
int joyAxis[MAX_INPUT_DEVICES][MAX_JOYSTICK_AXIS]; // For keeping track of joystick axises
|
||||
};
|
||||
166
neo/sys/win32/win_local.h
Normal file
166
neo/sys/win32/win_local.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef __WIN_LOCAL_H__
|
||||
#define __WIN_LOCAL_H__
|
||||
|
||||
#include <windows.h>
|
||||
#include "../../renderer/OpenGL/wglext.h" // windows OpenGL extensions
|
||||
#include "win_input.h"
|
||||
|
||||
// WGL_ARB_extensions_string
|
||||
extern PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
|
||||
|
||||
// WGL_EXT_swap_interval
|
||||
extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
|
||||
|
||||
// WGL_ARB_pixel_format
|
||||
extern PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB;
|
||||
extern PFNWGLGETPIXELFORMATATTRIBFVARBPROC wglGetPixelFormatAttribfvARB;
|
||||
extern PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
|
||||
|
||||
// WGL_ARB_pbuffer
|
||||
extern PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB;
|
||||
extern PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB;
|
||||
extern PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB;
|
||||
extern PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB;
|
||||
extern PFNWGLQUERYPBUFFERARBPROC wglQueryPbufferARB;
|
||||
|
||||
// WGL_ARB_render_texture
|
||||
extern PFNWGLBINDTEXIMAGEARBPROC wglBindTexImageARB;
|
||||
extern PFNWGLRELEASETEXIMAGEARBPROC wglReleaseTexImageARB;
|
||||
extern PFNWGLSETPBUFFERATTRIBARBPROC wglSetPbufferAttribARB;
|
||||
|
||||
#define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_CAPTION|WS_VISIBLE | WS_THICKFRAME)
|
||||
|
||||
void Sys_QueEvent( sysEventType_t type, int value, int value2, int ptrLength, void *ptr, int inputDeviceNum );
|
||||
|
||||
void Sys_CreateConsole();
|
||||
void Sys_DestroyConsole();
|
||||
|
||||
char *Sys_ConsoleInput ();
|
||||
char *Sys_GetCurrentUser();
|
||||
|
||||
void Win_SetErrorText( const char *text );
|
||||
|
||||
cpuid_t Sys_GetCPUId();
|
||||
|
||||
// Input subsystem
|
||||
|
||||
void IN_Init ();
|
||||
void IN_Shutdown ();
|
||||
// add additional non keyboard / non mouse movement on top of the keyboard move cmd
|
||||
|
||||
void IN_DeactivateMouseIfWindowed();
|
||||
void IN_DeactivateMouse();
|
||||
void IN_ActivateMouse();
|
||||
|
||||
void IN_Frame();
|
||||
|
||||
void DisableTaskKeys( BOOL bDisable, BOOL bBeep, BOOL bTaskMgr );
|
||||
|
||||
uint64 Sys_Microseconds();
|
||||
|
||||
// window procedure
|
||||
LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void Conbuf_AppendText( const char *msg );
|
||||
|
||||
typedef struct {
|
||||
HWND hWnd;
|
||||
HINSTANCE hInstance;
|
||||
|
||||
bool activeApp; // changed with WM_ACTIVATE messages
|
||||
bool mouseReleased; // when the game has the console down or is doing a long operation
|
||||
bool movingWindow; // inhibit mouse grab when dragging the window
|
||||
bool mouseGrabbed; // current state of grab and hide
|
||||
|
||||
OSVERSIONINFOEX osversion;
|
||||
|
||||
cpuid_t cpuid;
|
||||
|
||||
// when we get a windows message, we store the time off so keyboard processing
|
||||
// can know the exact time of an event (not really needed now that we use async direct input)
|
||||
int sysMsgTime;
|
||||
|
||||
bool windowClassRegistered;
|
||||
|
||||
WNDPROC wndproc;
|
||||
|
||||
HDC hDC; // handle to device context
|
||||
HGLRC hGLRC; // handle to GL rendering context
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
int pixelformat;
|
||||
|
||||
HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library
|
||||
|
||||
int desktopBitsPixel;
|
||||
int desktopWidth, desktopHeight;
|
||||
|
||||
int cdsFullscreen; // 0 = not fullscreen, otherwise monitor number
|
||||
|
||||
idFileHandle log_fp;
|
||||
|
||||
unsigned short oldHardwareGamma[3][256];
|
||||
// desktop gamma is saved here for restoration at exit
|
||||
|
||||
static idCVar sys_arch;
|
||||
static idCVar sys_cpustring;
|
||||
static idCVar in_mouse;
|
||||
static idCVar win_allowAltTab;
|
||||
static idCVar win_notaskkeys;
|
||||
static idCVar win_username;
|
||||
static idCVar win_outputEditString;
|
||||
static idCVar win_viewlog;
|
||||
static idCVar win_timerUpdate;
|
||||
static idCVar win_allowMultipleInstances;
|
||||
|
||||
CRITICAL_SECTION criticalSections[MAX_CRITICAL_SECTIONS];
|
||||
|
||||
HINSTANCE hInstDI; // direct input
|
||||
|
||||
LPDIRECTINPUT8 g_pdi;
|
||||
LPDIRECTINPUTDEVICE8 g_pMouse;
|
||||
LPDIRECTINPUTDEVICE8 g_pKeyboard;
|
||||
idJoystickWin32 g_Joystick;
|
||||
|
||||
HANDLE renderCommandsEvent;
|
||||
HANDLE renderCompletedEvent;
|
||||
HANDLE renderActiveEvent;
|
||||
HANDLE renderThreadHandle;
|
||||
unsigned long renderThreadId;
|
||||
void (*glimpRenderThread)();
|
||||
void *smpData;
|
||||
int wglErrors;
|
||||
// SMP acceleration vars
|
||||
|
||||
} Win32Vars_t;
|
||||
|
||||
extern Win32Vars_t win32;
|
||||
|
||||
#endif /* !__WIN_LOCAL_H__ */
|
||||
121
neo/sys/win32/win_localuser.cpp
Normal file
121
neo/sys/win32/win_localuser.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
#include "win_localuser.h"
|
||||
|
||||
extern idCVar win_userPersistent;
|
||||
extern idCVar win_userOnline;
|
||||
extern idCVar win_isInParty;
|
||||
extern idCVar win_partyCount;
|
||||
|
||||
/*
|
||||
========================
|
||||
idLocalUserWin::Init
|
||||
========================
|
||||
*/
|
||||
void idLocalUserWin::Init( int inputDevice_, const char * gamertag_, int numLocalUsers ) {
|
||||
if ( numLocalUsers == 1 ) { // Check for 1, since this is now incremented before we get in here
|
||||
// This is the master user
|
||||
gamertag = gamertag_;
|
||||
} else {
|
||||
// On steam, we need to generate a name based off the master user for split-screen users.
|
||||
// We use the number of users on the system to generate the name rather than the device
|
||||
// number so that it is always consistently "username (2)" for the second player.
|
||||
gamertag.Format( "%s (%i)", gamertag_, numLocalUsers );
|
||||
}
|
||||
|
||||
inputDevice = inputDevice_;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idLocalUserWin::IsProfileReady
|
||||
========================
|
||||
*/
|
||||
bool idLocalUserWin::IsProfileReady() const {
|
||||
#ifdef _DEBUG
|
||||
return win_userPersistent.GetBool();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idLocalUserWin::IsOnline
|
||||
========================
|
||||
*/
|
||||
bool idLocalUserWin::IsOnline() const {
|
||||
#ifdef _DEBUG
|
||||
return win_userOnline.GetBool();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idLocalUserWin::IsInParty
|
||||
========================
|
||||
*/
|
||||
bool idLocalUserWin::IsInParty() const {
|
||||
#ifdef _DEBUG
|
||||
return win_isInParty.GetBool();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idLocalUserWin::GetPartyCount
|
||||
========================
|
||||
*/
|
||||
int idLocalUserWin::GetPartyCount() const {
|
||||
// TODO: Implement
|
||||
#ifdef _DEBUG
|
||||
return win_partyCount.GetInteger();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idLocalUserWin::VerifyUserState
|
||||
========================
|
||||
*/
|
||||
bool idLocalUserWin::VerifyUserState( winUserState_t & state ) {
|
||||
|
||||
if ( state.inputDevice != inputDevice ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
75
neo/sys/win32/win_localuser.h
Normal file
75
neo/sys/win32/win_localuser.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef __WIN_LOCALUSER_H__
|
||||
#define __WIN_LOCALUSER_H__
|
||||
|
||||
// This is to quickly get/set the data needed for disc-swapping
|
||||
typedef struct {
|
||||
int inputDevice;
|
||||
} winUserState_t;
|
||||
|
||||
/*
|
||||
================================================
|
||||
idLocalUserWin
|
||||
================================================
|
||||
*/
|
||||
class idLocalUserWin : public idLocalUser {
|
||||
public:
|
||||
static const int MAX_GAMERTAG = 64; // max number of bytes for a gamertag
|
||||
static const int MAX_GAMERTAG_CHARS = 16; // max number of UTF-8 characters to show
|
||||
|
||||
idLocalUserWin() : inputDevice( 0 ) {}
|
||||
|
||||
//==========================================================================================
|
||||
// idLocalUser interface
|
||||
//==========================================================================================
|
||||
virtual bool IsProfileReady() const;
|
||||
virtual bool IsOnline() const;
|
||||
virtual bool IsInParty() const;
|
||||
virtual int GetPartyCount() const;
|
||||
virtual uint32 GetOnlineCaps() const { return ( IsPersistent() && IsOnline() ) ? ( CAP_IS_ONLINE | CAP_CAN_PLAY_ONLINE ) : 0; }
|
||||
virtual int GetInputDevice() const { return inputDevice; }
|
||||
virtual const char * GetGamerTag() const { return gamertag.c_str(); }
|
||||
virtual void PumpPlatform() {}
|
||||
|
||||
//==========================================================================================
|
||||
// idLocalUserWin interface
|
||||
//==========================================================================================
|
||||
void SetInputDevice( int inputDevice_ ) { inputDevice = inputDevice_; }
|
||||
void SetGamerTag( const char * gamerTag_ ) { gamertag = gamerTag_; }
|
||||
winUserState_t GetUserState() { winUserState_t a = { inputDevice }; return a; }
|
||||
bool VerifyUserState( winUserState_t & state );
|
||||
|
||||
void Init( int inputDevice_, const char * gamertag_, int numLocalUsers );
|
||||
|
||||
private:
|
||||
idStrStatic< MAX_GAMERTAG > gamertag;
|
||||
int inputDevice;
|
||||
};
|
||||
|
||||
#endif // __WIN_LOCALUSER_H__
|
||||
1661
neo/sys/win32/win_main.cpp
Normal file
1661
neo/sys/win32/win_main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
987
neo/sys/win32/win_net.cpp
Normal file
987
neo/sys/win32/win_net.cpp
Normal file
@@ -0,0 +1,987 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
|
||||
/*
|
||||
================================================================================================
|
||||
Contains the NetworkSystem implementation specific to Win32.
|
||||
================================================================================================
|
||||
*/
|
||||
|
||||
#include <iptypes.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
static WSADATA winsockdata;
|
||||
static bool winsockInitialized = false;
|
||||
static bool usingSocks = false;
|
||||
|
||||
//lint -e569 ioctl macros trigger this
|
||||
|
||||
// force these libs to be included, so users of idLib don't need to add them to every project
|
||||
#pragma comment(lib, "iphlpapi.lib" )
|
||||
#pragma comment(lib, "wsock32.lib" )
|
||||
|
||||
|
||||
/*
|
||||
================================================================================================
|
||||
|
||||
Network CVars
|
||||
|
||||
================================================================================================
|
||||
*/
|
||||
|
||||
idCVar net_socksServer( "net_socksServer", "", CVAR_ARCHIVE, "" );
|
||||
idCVar net_socksPort( "net_socksPort", "1080", CVAR_ARCHIVE | CVAR_INTEGER, "" );
|
||||
idCVar net_socksUsername( "net_socksUsername", "", CVAR_ARCHIVE, "" );
|
||||
idCVar net_socksPassword( "net_socksPassword", "", CVAR_ARCHIVE, "" );
|
||||
|
||||
idCVar net_ip( "net_ip", "localhost", 0, "local IP address" );
|
||||
|
||||
static struct sockaddr_in socksRelayAddr;
|
||||
|
||||
static SOCKET ip_socket;
|
||||
static SOCKET socks_socket;
|
||||
static char socksBuf[4096];
|
||||
|
||||
typedef struct {
|
||||
unsigned long ip;
|
||||
unsigned long mask;
|
||||
char addr[16];
|
||||
} net_interface;
|
||||
|
||||
#define MAX_INTERFACES 32
|
||||
int num_interfaces = 0;
|
||||
net_interface netint[MAX_INTERFACES];
|
||||
|
||||
/*
|
||||
================================================================================================
|
||||
|
||||
Free Functions
|
||||
|
||||
================================================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
========================
|
||||
NET_ErrorString
|
||||
========================
|
||||
*/
|
||||
char *NET_ErrorString() {
|
||||
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 "WSAECONNABORTED";
|
||||
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";
|
||||
default: return "NO ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Net_NetadrToSockadr
|
||||
========================
|
||||
*/
|
||||
void Net_NetadrToSockadr( const netadr_t *a, sockaddr_in *s ) {
|
||||
memset( s, 0, sizeof(*s) );
|
||||
|
||||
if ( a->type == NA_BROADCAST ) {
|
||||
s->sin_family = AF_INET;
|
||||
s->sin_addr.s_addr = INADDR_BROADCAST;
|
||||
} else if ( a->type == NA_IP || a->type == NA_LOOPBACK ) {
|
||||
s->sin_family = AF_INET;
|
||||
s->sin_addr.s_addr = *(int *)a->ip;
|
||||
}
|
||||
|
||||
s->sin_port = htons( (short)a->port );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Net_SockadrToNetadr
|
||||
========================
|
||||
*/
|
||||
void Net_SockadrToNetadr( sockaddr_in *s, netadr_t *a ) {
|
||||
unsigned int ip;
|
||||
if ( s->sin_family == AF_INET ) {
|
||||
ip = s->sin_addr.s_addr;
|
||||
*(unsigned int *)a->ip = ip;
|
||||
a->port = htons( s->sin_port );
|
||||
// we store in network order, that loopback test is host order..
|
||||
ip = ntohl( ip );
|
||||
if ( ip == INADDR_LOOPBACK ) {
|
||||
a->type = NA_LOOPBACK;
|
||||
} else {
|
||||
a->type = NA_IP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Net_ExtractPort
|
||||
========================
|
||||
*/
|
||||
static bool Net_ExtractPort( const char *src, char *buf, int bufsize, int *port ) {
|
||||
char *p;
|
||||
strncpy( buf, src, bufsize );
|
||||
p = buf; p += Min( bufsize - 1, idStr::Length( src ) ); *p = '\0';
|
||||
p = strchr( buf, ':' );
|
||||
if ( !p ) {
|
||||
return false;
|
||||
}
|
||||
*p = '\0';
|
||||
*port = strtol( p+1, NULL, 10 );
|
||||
if ( errno == ERANGE ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Net_StringToSockaddr
|
||||
========================
|
||||
*/
|
||||
static bool Net_StringToSockaddr( const char *s, sockaddr_in *sadr, bool doDNSResolve ) {
|
||||
struct hostent *h;
|
||||
char buf[256];
|
||||
int port;
|
||||
|
||||
memset( sadr, 0, sizeof( *sadr ) );
|
||||
|
||||
sadr->sin_family = AF_INET;
|
||||
sadr->sin_port = 0;
|
||||
|
||||
if( s[0] >= '0' && s[0] <= '9' ) {
|
||||
unsigned long ret = inet_addr(s);
|
||||
if ( ret != INADDR_NONE ) {
|
||||
*(int *)&sadr->sin_addr = ret;
|
||||
} else {
|
||||
// check for port
|
||||
if ( !Net_ExtractPort( s, buf, sizeof( buf ), &port ) ) {
|
||||
return false;
|
||||
}
|
||||
ret = inet_addr( buf );
|
||||
if ( ret == INADDR_NONE ) {
|
||||
return false;
|
||||
}
|
||||
*(int *)&sadr->sin_addr = ret;
|
||||
sadr->sin_port = htons( port );
|
||||
}
|
||||
} else if ( doDNSResolve ) {
|
||||
// try to remove the port first, otherwise the DNS gets confused into multiple timeouts
|
||||
// failed or not failed, buf is expected to contain the appropriate host to resolve
|
||||
if ( Net_ExtractPort( s, buf, sizeof( buf ), &port ) ) {
|
||||
sadr->sin_port = htons( port );
|
||||
}
|
||||
h = gethostbyname( buf );
|
||||
if ( h == 0 ) {
|
||||
return false;
|
||||
}
|
||||
*(int *)&sadr->sin_addr = *(int *)h->h_addr_list[0];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
NET_IPSocket
|
||||
========================
|
||||
*/
|
||||
int NET_IPSocket( const char *net_interface, int port, netadr_t *bound_to ) {
|
||||
SOCKET newsocket;
|
||||
sockaddr_in address;
|
||||
unsigned long _true = 1;
|
||||
int i = 1;
|
||||
int err;
|
||||
|
||||
if ( port != PORT_ANY ) {
|
||||
if( net_interface ) {
|
||||
idLib::Printf( "Opening IP socket: %s:%i\n", net_interface, port );
|
||||
} else {
|
||||
idLib::Printf( "Opening IP socket: localhost:%i\n", port );
|
||||
}
|
||||
}
|
||||
|
||||
if( ( newsocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) {
|
||||
err = WSAGetLastError();
|
||||
if( err != WSAEAFNOSUPPORT ) {
|
||||
idLib::Printf( "WARNING: UDP_OpenSocket: socket: %s\n", NET_ErrorString() );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make it non-blocking
|
||||
if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) {
|
||||
idLib::Printf( "WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString() );
|
||||
closesocket( newsocket );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make it broadcast capable
|
||||
if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i) ) == SOCKET_ERROR ) {
|
||||
idLib::Printf( "WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() );
|
||||
closesocket( newsocket );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !net_interface || !net_interface[0] || !idStr::Icmp( net_interface, "localhost" ) ) {
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
else {
|
||||
Net_StringToSockaddr( net_interface, &address, true );
|
||||
}
|
||||
|
||||
if( port == PORT_ANY ) {
|
||||
address.sin_port = 0;
|
||||
}
|
||||
else {
|
||||
address.sin_port = htons( (short)port );
|
||||
}
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
|
||||
if( bind( newsocket, (const sockaddr *)&address, sizeof(address) ) == SOCKET_ERROR ) {
|
||||
idLib::Printf( "WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString() );
|
||||
closesocket( newsocket );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if the port was PORT_ANY, we need to query again to know the real port we got bound to
|
||||
// ( this used to be in idUDP::InitForPort )
|
||||
if ( bound_to ) {
|
||||
int len = sizeof( address );
|
||||
getsockname( newsocket, (sockaddr *)&address, &len );
|
||||
Net_SockadrToNetadr( &address, bound_to );
|
||||
}
|
||||
|
||||
return newsocket;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
NET_OpenSocks
|
||||
========================
|
||||
*/
|
||||
void NET_OpenSocks( int port ) {
|
||||
sockaddr_in address;
|
||||
struct hostent *h;
|
||||
int len;
|
||||
bool rfc1929;
|
||||
unsigned char buf[64];
|
||||
|
||||
usingSocks = false;
|
||||
|
||||
idLib::Printf( "Opening connection to SOCKS server.\n" );
|
||||
|
||||
if ( ( socks_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) {
|
||||
idLib::Printf( "WARNING: NET_OpenSocks: socket: %s\n", NET_ErrorString() );
|
||||
return;
|
||||
}
|
||||
|
||||
h = gethostbyname( net_socksServer.GetString() );
|
||||
if ( h == NULL ) {
|
||||
idLib::Printf( "WARNING: NET_OpenSocks: gethostbyname: %s\n", NET_ErrorString() );
|
||||
return;
|
||||
}
|
||||
if ( h->h_addrtype != AF_INET ) {
|
||||
idLib::Printf( "WARNING: NET_OpenSocks: gethostbyname: address type was not AF_INET\n" );
|
||||
return;
|
||||
}
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = *(int *)h->h_addr_list[0];
|
||||
address.sin_port = htons( (short)net_socksPort.GetInteger() );
|
||||
|
||||
if ( connect( socks_socket, (sockaddr *)&address, sizeof( address ) ) == SOCKET_ERROR ) {
|
||||
idLib::Printf( "NET_OpenSocks: connect: %s\n", NET_ErrorString() );
|
||||
return;
|
||||
}
|
||||
|
||||
// send socks authentication handshake
|
||||
if ( *net_socksUsername.GetString() || *net_socksPassword.GetString() ) {
|
||||
rfc1929 = true;
|
||||
}
|
||||
else {
|
||||
rfc1929 = false;
|
||||
}
|
||||
|
||||
buf[0] = 5; // SOCKS version
|
||||
// method count
|
||||
if ( rfc1929 ) {
|
||||
buf[1] = 2;
|
||||
len = 4;
|
||||
}
|
||||
else {
|
||||
buf[1] = 1;
|
||||
len = 3;
|
||||
}
|
||||
buf[2] = 0; // method #1 - method id #00: no authentication
|
||||
if ( rfc1929 ) {
|
||||
buf[2] = 2; // method #2 - method id #02: username/password
|
||||
}
|
||||
if ( send( socks_socket, (const char *)buf, len, 0 ) == SOCKET_ERROR ) {
|
||||
idLib::Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
|
||||
return;
|
||||
}
|
||||
|
||||
// get the response
|
||||
len = recv( socks_socket, (char *)buf, 64, 0 );
|
||||
if ( len == SOCKET_ERROR ) {
|
||||
idLib::Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
|
||||
return;
|
||||
}
|
||||
if ( len != 2 || buf[0] != 5 ) {
|
||||
idLib::Printf( "NET_OpenSocks: bad response\n" );
|
||||
return;
|
||||
}
|
||||
switch( buf[1] ) {
|
||||
case 0: // no authentication
|
||||
break;
|
||||
case 2: // username/password authentication
|
||||
break;
|
||||
default:
|
||||
idLib::Printf( "NET_OpenSocks: request denied\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// do username/password authentication if needed
|
||||
if ( buf[1] == 2 ) {
|
||||
int ulen;
|
||||
int plen;
|
||||
|
||||
// build the request
|
||||
ulen = idStr::Length( net_socksUsername.GetString() );
|
||||
plen = idStr::Length( net_socksPassword.GetString() );
|
||||
|
||||
buf[0] = 1; // username/password authentication version
|
||||
buf[1] = ulen;
|
||||
if ( ulen ) {
|
||||
memcpy( &buf[2], net_socksUsername.GetString(), ulen );
|
||||
}
|
||||
buf[2 + ulen] = plen;
|
||||
if ( plen ) {
|
||||
memcpy( &buf[3 + ulen], net_socksPassword.GetString(), plen );
|
||||
}
|
||||
|
||||
// send it
|
||||
if ( send( socks_socket, (const char *)buf, 3 + ulen + plen, 0 ) == SOCKET_ERROR ) {
|
||||
idLib::Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
|
||||
return;
|
||||
}
|
||||
|
||||
// get the response
|
||||
len = recv( socks_socket, (char *)buf, 64, 0 );
|
||||
if ( len == SOCKET_ERROR ) {
|
||||
idLib::Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
|
||||
return;
|
||||
}
|
||||
if ( len != 2 || buf[0] != 1 ) {
|
||||
idLib::Printf( "NET_OpenSocks: bad response\n" );
|
||||
return;
|
||||
}
|
||||
if ( buf[1] != 0 ) {
|
||||
idLib::Printf( "NET_OpenSocks: authentication failed\n" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// send the UDP associate request
|
||||
buf[0] = 5; // SOCKS version
|
||||
buf[1] = 3; // command: UDP associate
|
||||
buf[2] = 0; // reserved
|
||||
buf[3] = 1; // address type: IPV4
|
||||
*(int *)&buf[4] = INADDR_ANY;
|
||||
*(short *)&buf[8] = htons( (short)port ); // port
|
||||
if ( send( socks_socket, (const char *)buf, 10, 0 ) == SOCKET_ERROR ) {
|
||||
idLib::Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
|
||||
return;
|
||||
}
|
||||
|
||||
// get the response
|
||||
len = recv( socks_socket, (char *)buf, 64, 0 );
|
||||
if( len == SOCKET_ERROR ) {
|
||||
idLib::Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
|
||||
return;
|
||||
}
|
||||
if( len < 2 || buf[0] != 5 ) {
|
||||
idLib::Printf( "NET_OpenSocks: bad response\n" );
|
||||
return;
|
||||
}
|
||||
// check completion code
|
||||
if( buf[1] != 0 ) {
|
||||
idLib::Printf( "NET_OpenSocks: request denied: %i\n", buf[1] );
|
||||
return;
|
||||
}
|
||||
if( buf[3] != 1 ) {
|
||||
idLib::Printf( "NET_OpenSocks: relay address is not IPV4: %i\n", buf[3] );
|
||||
return;
|
||||
}
|
||||
socksRelayAddr.sin_family = AF_INET;
|
||||
socksRelayAddr.sin_addr.s_addr = *(int *)&buf[4];
|
||||
socksRelayAddr.sin_port = *(short *)&buf[8];
|
||||
memset( socksRelayAddr.sin_zero, 0, sizeof( socksRelayAddr.sin_zero ) );
|
||||
|
||||
usingSocks = true;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Net_WaitForData
|
||||
========================
|
||||
*/
|
||||
bool Net_WaitForData( int netSocket, int timeout ) {
|
||||
int ret;
|
||||
fd_set set;
|
||||
struct timeval tv;
|
||||
|
||||
if ( !netSocket ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( timeout < 0 ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
FD_ZERO( &set );
|
||||
FD_SET( static_cast<unsigned int>( netSocket ), &set );
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = timeout * 1000;
|
||||
|
||||
ret = select( netSocket + 1, &set, NULL, NULL, &tv );
|
||||
|
||||
if ( ret == -1 ) {
|
||||
idLib::Printf( "Net_WaitForData select(): %s\n", strerror( errno ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
// timeout with no data
|
||||
if ( ret == 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Net_GetUDPPacket
|
||||
========================
|
||||
*/
|
||||
bool Net_GetUDPPacket( int netSocket, netadr_t &net_from, char *data, int &size, int maxSize ) {
|
||||
int ret;
|
||||
sockaddr_in from;
|
||||
int fromlen;
|
||||
int err;
|
||||
|
||||
if ( !netSocket ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fromlen = sizeof(from);
|
||||
ret = recvfrom( netSocket, data, maxSize, 0, (sockaddr *)&from, &fromlen );
|
||||
if ( ret == SOCKET_ERROR ) {
|
||||
err = WSAGetLastError();
|
||||
|
||||
if ( err == WSAEWOULDBLOCK || err == WSAECONNRESET ) {
|
||||
return false;
|
||||
}
|
||||
char buf[1024];
|
||||
sprintf( buf, "Net_GetUDPPacket: %s\n", NET_ErrorString() );
|
||||
idLib::Printf( buf );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( static_cast<unsigned int>( netSocket ) == ip_socket ) {
|
||||
memset( from.sin_zero, 0, sizeof( from.sin_zero ) );
|
||||
}
|
||||
|
||||
if ( usingSocks && static_cast<unsigned int>( netSocket ) == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) {
|
||||
if ( ret < 10 || data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 1 ) {
|
||||
return false;
|
||||
}
|
||||
net_from.type = NA_IP;
|
||||
net_from.ip[0] = data[4];
|
||||
net_from.ip[1] = data[5];
|
||||
net_from.ip[2] = data[6];
|
||||
net_from.ip[3] = data[7];
|
||||
net_from.port = *(short *)&data[8];
|
||||
memmove( data, &data[10], ret - 10 );
|
||||
} else {
|
||||
Net_SockadrToNetadr( &from, &net_from );
|
||||
}
|
||||
|
||||
if ( ret > maxSize ) {
|
||||
char buf[1024];
|
||||
sprintf( buf, "Net_GetUDPPacket: oversize packet from %s\n", Sys_NetAdrToString( net_from ) );
|
||||
idLib::Printf( buf );
|
||||
return false;
|
||||
}
|
||||
|
||||
size = ret;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Net_SendUDPPacket
|
||||
========================
|
||||
*/
|
||||
void Net_SendUDPPacket( int netSocket, int length, const void *data, const netadr_t to ) {
|
||||
int ret;
|
||||
sockaddr_in addr;
|
||||
|
||||
if ( !netSocket ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Net_NetadrToSockadr( &to, &addr );
|
||||
|
||||
if ( usingSocks && to.type == NA_IP ) {
|
||||
socksBuf[0] = 0; // reserved
|
||||
socksBuf[1] = 0;
|
||||
socksBuf[2] = 0; // fragment (not fragmented)
|
||||
socksBuf[3] = 1; // address type: IPV4
|
||||
*(int *)&socksBuf[4] = addr.sin_addr.s_addr;
|
||||
*(short *)&socksBuf[8] = addr.sin_port;
|
||||
memcpy( &socksBuf[10], data, length );
|
||||
ret = sendto( netSocket, socksBuf, length+10, 0, (sockaddr *)&socksRelayAddr, sizeof(socksRelayAddr) );
|
||||
} else {
|
||||
ret = sendto( netSocket, (const char *)data, length, 0, (sockaddr *)&addr, sizeof(addr) );
|
||||
}
|
||||
if ( ret == SOCKET_ERROR ) {
|
||||
int err = WSAGetLastError();
|
||||
|
||||
// some PPP links do not allow broadcasts and return an error
|
||||
if ( ( err == WSAEADDRNOTAVAIL ) && ( to.type == NA_BROADCAST ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: WSAEWOULDBLOCK used to be silently ignored,
|
||||
// but that means the packet will be dropped so I don't feel it's a good thing to ignore
|
||||
idLib::Printf( "UDP sendto error - packet dropped: %s\n", NET_ErrorString() );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Sys_InitNetworking
|
||||
========================
|
||||
*/
|
||||
void Sys_InitNetworking() {
|
||||
int r;
|
||||
|
||||
if ( winsockInitialized ) {
|
||||
return;
|
||||
}
|
||||
r = WSAStartup( MAKEWORD( 1, 1 ), &winsockdata );
|
||||
if( r ) {
|
||||
idLib::Printf( "WARNING: Winsock initialization failed, returned %d\n", r );
|
||||
return;
|
||||
}
|
||||
|
||||
winsockInitialized = true;
|
||||
idLib::Printf( "Winsock Initialized\n" );
|
||||
|
||||
PIP_ADAPTER_INFO pAdapterInfo;
|
||||
PIP_ADAPTER_INFO pAdapter = NULL;
|
||||
DWORD dwRetVal = 0;
|
||||
PIP_ADDR_STRING pIPAddrString;
|
||||
ULONG ulOutBufLen;
|
||||
bool foundloopback;
|
||||
|
||||
num_interfaces = 0;
|
||||
foundloopback = false;
|
||||
|
||||
pAdapterInfo = (IP_ADAPTER_INFO *)malloc( sizeof( IP_ADAPTER_INFO ) );
|
||||
if( !pAdapterInfo ) {
|
||||
idLib::FatalError( "Sys_InitNetworking: Couldn't malloc( %d )", sizeof( IP_ADAPTER_INFO ) );
|
||||
}
|
||||
ulOutBufLen = sizeof( IP_ADAPTER_INFO );
|
||||
|
||||
// Make an initial call to GetAdaptersInfo to get
|
||||
// the necessary size into the ulOutBufLen variable
|
||||
if( GetAdaptersInfo( pAdapterInfo, &ulOutBufLen ) == ERROR_BUFFER_OVERFLOW ) {
|
||||
free( pAdapterInfo );
|
||||
pAdapterInfo = (IP_ADAPTER_INFO *)malloc( ulOutBufLen );
|
||||
if( !pAdapterInfo ) {
|
||||
idLib::FatalError( "Sys_InitNetworking: Couldn't malloc( %ld )", ulOutBufLen );
|
||||
}
|
||||
}
|
||||
|
||||
if( ( dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) ) != NO_ERROR ) {
|
||||
// happens if you have no network connection
|
||||
idLib::Printf( "Sys_InitNetworking: GetAdaptersInfo failed (%ld).\n", dwRetVal );
|
||||
} else {
|
||||
pAdapter = pAdapterInfo;
|
||||
while( pAdapter ) {
|
||||
idLib::Printf( "Found interface: %s %s - ", pAdapter->AdapterName, pAdapter->Description );
|
||||
pIPAddrString = &pAdapter->IpAddressList;
|
||||
while( pIPAddrString ) {
|
||||
unsigned long ip_a, ip_m;
|
||||
if( !idStr::Icmp( "127.0.0.1", pIPAddrString->IpAddress.String ) ) {
|
||||
foundloopback = true;
|
||||
}
|
||||
ip_a = ntohl( inet_addr( pIPAddrString->IpAddress.String ) );
|
||||
ip_m = ntohl( inet_addr( pIPAddrString->IpMask.String ) );
|
||||
//skip null netmasks
|
||||
if( !ip_m ) {
|
||||
idLib::Printf( "%s NULL netmask - skipped\n", pIPAddrString->IpAddress.String );
|
||||
pIPAddrString = pIPAddrString->Next;
|
||||
continue;
|
||||
}
|
||||
idLib::Printf( "%s/%s\n", pIPAddrString->IpAddress.String, pIPAddrString->IpMask.String );
|
||||
netint[num_interfaces].ip = ip_a;
|
||||
netint[num_interfaces].mask = ip_m;
|
||||
idStr::Copynz( netint[num_interfaces].addr, pIPAddrString->IpAddress.String, sizeof( netint[num_interfaces].addr ) );
|
||||
num_interfaces++;
|
||||
if( num_interfaces >= MAX_INTERFACES ) {
|
||||
idLib::Printf( "Sys_InitNetworking: MAX_INTERFACES(%d) hit.\n", MAX_INTERFACES );
|
||||
free( pAdapterInfo );
|
||||
return;
|
||||
}
|
||||
pIPAddrString = pIPAddrString->Next;
|
||||
}
|
||||
pAdapter = pAdapter->Next;
|
||||
}
|
||||
}
|
||||
// for some retarded reason, win32 doesn't count loopback as an adapter...
|
||||
if( !foundloopback && num_interfaces < MAX_INTERFACES ) {
|
||||
idLib::Printf( "Sys_InitNetworking: adding loopback interface\n" );
|
||||
netint[num_interfaces].ip = ntohl( inet_addr( "127.0.0.1" ) );
|
||||
netint[num_interfaces].mask = ntohl( inet_addr( "255.0.0.0" ) );
|
||||
num_interfaces++;
|
||||
}
|
||||
free( pAdapterInfo );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Sys_ShutdownNetworking
|
||||
========================
|
||||
*/
|
||||
void Sys_ShutdownNetworking() {
|
||||
if ( !winsockInitialized ) {
|
||||
return;
|
||||
}
|
||||
WSACleanup();
|
||||
winsockInitialized = false;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Sys_StringToNetAdr
|
||||
========================
|
||||
*/
|
||||
bool Sys_StringToNetAdr( const char *s, netadr_t *a, bool doDNSResolve ) {
|
||||
sockaddr_in sadr;
|
||||
|
||||
if ( !Net_StringToSockaddr( s, &sadr, doDNSResolve ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Net_SockadrToNetadr( &sadr, a );
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Sys_NetAdrToString
|
||||
========================
|
||||
*/
|
||||
const char *Sys_NetAdrToString( const netadr_t a ) {
|
||||
static int index = 0;
|
||||
static char buf[ 4 ][ 64 ]; // flip/flop
|
||||
char *s;
|
||||
|
||||
s = buf[index];
|
||||
index = (index + 1) & 3;
|
||||
|
||||
if ( a.type == NA_LOOPBACK ) {
|
||||
if ( a.port ) {
|
||||
idStr::snPrintf( s, 64, "localhost:%i", a.port );
|
||||
} else {
|
||||
idStr::snPrintf( s, 64, "localhost" );
|
||||
}
|
||||
} else if ( a.type == NA_IP ) {
|
||||
idStr::snPrintf( s, 64, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], a.port );
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Sys_IsLANAddress
|
||||
========================
|
||||
*/
|
||||
bool Sys_IsLANAddress( const netadr_t adr ) {
|
||||
if ( adr.type == NA_LOOPBACK ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( adr.type != NA_IP ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( num_interfaces ) {
|
||||
int i;
|
||||
unsigned long *p_ip;
|
||||
unsigned long ip;
|
||||
p_ip = (unsigned long *)&adr.ip[0];
|
||||
ip = ntohl( *p_ip );
|
||||
|
||||
for( i = 0; i < num_interfaces; i++ ) {
|
||||
if( ( netint[i].ip & netint[i].mask ) == ( ip & netint[i].mask ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Sys_CompareNetAdrBase
|
||||
|
||||
Compares without the port.
|
||||
========================
|
||||
*/
|
||||
bool Sys_CompareNetAdrBase( const netadr_t a, const netadr_t b ) {
|
||||
if ( a.type != b.type ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( a.type == NA_LOOPBACK ) {
|
||||
if ( a.port == b.port ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( a.type == NA_IP ) {
|
||||
if ( a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
idLib::Printf( "Sys_CompareNetAdrBase: bad address type\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Sys_GetLocalIPCount
|
||||
========================
|
||||
*/
|
||||
int Sys_GetLocalIPCount() {
|
||||
return num_interfaces;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Sys_GetLocalIP
|
||||
========================
|
||||
*/
|
||||
const char * Sys_GetLocalIP( int i ) {
|
||||
if ( ( i < 0 ) || ( i >= num_interfaces ) ) {
|
||||
return NULL;
|
||||
}
|
||||
return netint[i].addr;
|
||||
}
|
||||
|
||||
/*
|
||||
================================================================================================
|
||||
|
||||
idUDP
|
||||
|
||||
================================================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
========================
|
||||
idUDP::idUDP
|
||||
========================
|
||||
*/
|
||||
idUDP::idUDP() {
|
||||
netSocket = 0;
|
||||
memset( &bound_to, 0, sizeof( bound_to ) );
|
||||
silent = false;
|
||||
packetsRead = 0;
|
||||
bytesRead = 0;
|
||||
packetsWritten = 0;
|
||||
bytesWritten = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idUDP::~idUDP
|
||||
========================
|
||||
*/
|
||||
idUDP::~idUDP() {
|
||||
Close();
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idUDP::InitForPort
|
||||
========================
|
||||
*/
|
||||
bool idUDP::InitForPort( int portNumber ) {
|
||||
netSocket = NET_IPSocket( net_ip.GetString(), portNumber, &bound_to );
|
||||
if ( netSocket <= 0 ) {
|
||||
netSocket = 0;
|
||||
memset( &bound_to, 0, sizeof( bound_to ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idUDP::Close
|
||||
========================
|
||||
*/
|
||||
void idUDP::Close() {
|
||||
if ( netSocket ) {
|
||||
closesocket( netSocket );
|
||||
netSocket = 0;
|
||||
memset( &bound_to, 0, sizeof( bound_to ) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idUDP::GetPacket
|
||||
========================
|
||||
*/
|
||||
bool idUDP::GetPacket( netadr_t &from, void *data, int &size, int maxSize ) {
|
||||
bool ret;
|
||||
|
||||
while ( 1 ) {
|
||||
|
||||
ret = Net_GetUDPPacket( netSocket, from, (char *)data, size, maxSize );
|
||||
if ( !ret ) {
|
||||
break;
|
||||
}
|
||||
|
||||
packetsRead++;
|
||||
bytesRead += size;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idUDP::GetPacketBlocking
|
||||
========================
|
||||
*/
|
||||
bool idUDP::GetPacketBlocking( netadr_t &from, void *data, int &size, int maxSize, int timeout ) {
|
||||
|
||||
if ( !Net_WaitForData( netSocket, timeout ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( GetPacket( from, data, size, maxSize ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idUDP::SendPacket
|
||||
========================
|
||||
*/
|
||||
void idUDP::SendPacket( const netadr_t to, const void *data, int size ) {
|
||||
if ( to.type == NA_BAD ) {
|
||||
idLib::Warning( "idUDP::SendPacket: bad address type NA_BAD - ignored" );
|
||||
return;
|
||||
}
|
||||
|
||||
packetsWritten++;
|
||||
bytesWritten += size;
|
||||
|
||||
if ( silent ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Net_SendUDPPacket( netSocket, size, data, to );
|
||||
}
|
||||
2011
neo/sys/win32/win_qgl.cpp
Normal file
2011
neo/sys/win32/win_qgl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
698
neo/sys/win32/win_savegame.cpp
Normal file
698
neo/sys/win32/win_savegame.cpp
Normal file
@@ -0,0 +1,698 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
#include "../sys_session_local.h"
|
||||
#include "../sys_savegame.h"
|
||||
|
||||
idCVar savegame_winInduceDelay( "savegame_winInduceDelay", "0", CVAR_INTEGER, "on windows, this is a delay induced before any file operation occurs" );
|
||||
extern idCVar fs_savepath;
|
||||
extern idCVar saveGame_checksum;
|
||||
extern idCVar savegame_error;
|
||||
|
||||
#define SAVEGAME_SENTINAL 0x12358932
|
||||
|
||||
/*
|
||||
========================
|
||||
void Sys_ExecuteSavegameCommandAsync
|
||||
========================
|
||||
*/
|
||||
void Sys_ExecuteSavegameCommandAsyncImpl( idSaveLoadParms * savegameParms ) {
|
||||
assert( savegameParms != NULL );
|
||||
|
||||
session->GetSaveGameManager().GetSaveGameThread().data.saveLoadParms = savegameParms;
|
||||
|
||||
if ( session->GetSaveGameManager().GetSaveGameThread().GetThreadHandle() == 0 ) {
|
||||
session->GetSaveGameManager().GetSaveGameThread().StartWorkerThread( "Savegame", CORE_ANY );
|
||||
}
|
||||
|
||||
session->GetSaveGameManager().GetSaveGameThread().SignalWork();
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idLocalUser * GetLocalUserFromUserId
|
||||
========================
|
||||
*/
|
||||
idLocalUserWin * GetLocalUserFromSaveParms( const saveGameThreadArgs_t & data ) {
|
||||
if ( ( data.saveLoadParms != NULL) && ( data.saveLoadParms->inputDeviceId >= 0 ) ) {
|
||||
idLocalUser * user = session->GetSignInManager().GetLocalUserByInputDevice( data.saveLoadParms->inputDeviceId );
|
||||
if ( user != NULL ) {
|
||||
idLocalUserWin * userWin = static_cast< idLocalUserWin * >( user );
|
||||
if ( userWin != NULL && data.saveLoadParms->userId == idStr::Hash( userWin->GetGamerTag() ) ) {
|
||||
return userWin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSaveGameThread::SaveGame
|
||||
========================
|
||||
*/
|
||||
int idSaveGameThread::Save() {
|
||||
idLocalUserWin * user = GetLocalUserFromSaveParms( data );
|
||||
if ( user == NULL ) {
|
||||
data.saveLoadParms->errorCode = SAVEGAME_E_INVALID_USER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
idSaveLoadParms * callback = data.saveLoadParms;
|
||||
idStr saveFolder = "savegame";
|
||||
|
||||
saveFolder.AppendPath( callback->directory );
|
||||
|
||||
// Check for the required storage space.
|
||||
int64 requiredSizeBytes = 0;
|
||||
{
|
||||
for ( int i = 0; i < callback->files.Num(); i++ ) {
|
||||
idFile_SaveGame * file = callback->files[i];
|
||||
requiredSizeBytes += ( file->Length() + sizeof( unsigned int ) ); // uint for checksum
|
||||
if ( file->type == SAVEGAMEFILE_PIPELINED ) {
|
||||
requiredSizeBytes += MIN_SAVEGAME_SIZE_BYTES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// Check size of previous files if needed
|
||||
// ALL THE FILES RIGHT NOW---- could use pattern later...
|
||||
idStrList filesToDelete;
|
||||
if ( ( callback->mode & SAVEGAME_MBF_DELETE_FILES ) && !callback->cancelled ) {
|
||||
if ( fileSystem->IsFolder( saveFolder.c_str(), "fs_savePath" ) == FOLDER_YES ) {
|
||||
idFileList * files = fileSystem->ListFilesTree( saveFolder.c_str(), "*.*" );
|
||||
for ( int i = 0; i < files->GetNumFiles(); i++ ) {
|
||||
requiredSizeBytes -= fileSystem->GetFileLength( files->GetFile( i ) );
|
||||
filesToDelete.Append( files->GetFile( i ) );
|
||||
}
|
||||
fileSystem->FreeFileList( files );
|
||||
}
|
||||
}
|
||||
|
||||
// Inform user about size required if necessary
|
||||
if ( requiredSizeBytes > 0 && !callback->cancelled ) {
|
||||
user->StorageSizeAvailable( requiredSizeBytes, callback->requiredSpaceInBytes );
|
||||
if ( callback->requiredSpaceInBytes > 0 ) {
|
||||
// check to make sure savepath actually exists before erroring
|
||||
idStr directory = fs_savepath.GetString();
|
||||
directory += "\\"; // so it doesn't think the last part is a file and ignores in the directory creation
|
||||
fileSystem->CreateOSPath( directory ); // we can't actually check FileExists in production builds, so just try to create it
|
||||
user->StorageSizeAvailable( requiredSizeBytes, callback->requiredSpaceInBytes );
|
||||
|
||||
if ( callback->requiredSpaceInBytes > 0 ) {
|
||||
callback->errorCode = SAVEGAME_E_INSUFFICIENT_ROOM;
|
||||
// safe to return, haven't written any files yet
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all previous files if needed
|
||||
// ALL THE FILES RIGHT NOW---- could use pattern later...
|
||||
for ( int i = 0; i < filesToDelete.Num() && !callback->cancelled; i++ ) {
|
||||
fileSystem->RemoveFile( filesToDelete[i].c_str() );
|
||||
}
|
||||
|
||||
// Save the raw files.
|
||||
for ( int i = 0; i < callback->files.Num() && ret == ERROR_SUCCESS && !callback->cancelled; i++ ) {
|
||||
idFile_SaveGame * file = callback->files[i];
|
||||
|
||||
idStr fileName = saveFolder;
|
||||
fileName.AppendPath( file->GetName() );
|
||||
idStr tempFileName = va( "%s.temp", fileName.c_str() );
|
||||
|
||||
idFile * outputFile = fileSystem->OpenFileWrite( tempFileName, "fs_savePath" );
|
||||
if ( outputFile == NULL ) {
|
||||
idLib::Warning( "[%s]: Couldn't open file for writing, %s. Error = %08x", __FUNCTION__, tempFileName.c_str(), GetLastError() );
|
||||
file->error = true;
|
||||
callback->errorCode = SAVEGAME_E_UNKNOWN;
|
||||
ret = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ( file->type & SAVEGAMEFILE_PIPELINED ) != 0 ) {
|
||||
|
||||
idFile_SaveGamePipelined * inputFile = dynamic_cast< idFile_SaveGamePipelined * >( file );
|
||||
assert( inputFile != NULL );
|
||||
|
||||
blockForIO_t block;
|
||||
while ( inputFile->NextWriteBlock( & block ) ) {
|
||||
if ( (size_t)outputFile->Write( block.data, block.bytes ) != block.bytes ) {
|
||||
idLib::Warning( "[%s]: Write failed. Error = %08x", __FUNCTION__, GetLastError() );
|
||||
file->error = true;
|
||||
callback->errorCode = SAVEGAME_E_INSUFFICIENT_ROOM;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ( ( file->type & SAVEGAMEFILE_BINARY ) || ( file->type & SAVEGAMEFILE_COMPRESSED ) ) {
|
||||
if ( saveGame_checksum.GetBool() ) {
|
||||
unsigned int checksum = MD5_BlockChecksum( file->GetDataPtr(), file->Length() );
|
||||
size_t size = outputFile->WriteBig( checksum );
|
||||
if ( size != sizeof( checksum ) ) {
|
||||
idLib::Warning( "[%s]: Write failed. Error = %08x", __FUNCTION__, GetLastError() );
|
||||
file->error = true;
|
||||
callback->errorCode = SAVEGAME_E_INSUFFICIENT_ROOM;
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t size = outputFile->Write( file->GetDataPtr(), file->Length() );
|
||||
if ( size != (size_t)file->Length() ) {
|
||||
idLib::Warning( "[%s]: Write failed. Error = %08x", __FUNCTION__, GetLastError() );
|
||||
file->error = true;
|
||||
callback->errorCode = SAVEGAME_E_INSUFFICIENT_ROOM;
|
||||
ret = -1;
|
||||
} else {
|
||||
idLib::PrintfIf( saveGame_verbose.GetBool(), "Saved %s (%s)\n", fileName.c_str(), outputFile->GetFullPath() );
|
||||
}
|
||||
}
|
||||
|
||||
delete outputFile;
|
||||
|
||||
if ( ret == ERROR_SUCCESS ) {
|
||||
// Remove the old file
|
||||
if ( !fileSystem->RenameFile( tempFileName, fileName, "fs_savePath" ) ) {
|
||||
idLib::Warning( "Could not start to rename temporary file %s to %s.", tempFileName.c_str(), fileName.c_str() );
|
||||
}
|
||||
} else {
|
||||
fileSystem->RemoveFile( tempFileName );
|
||||
idLib::Warning( "Invalid write to temporary file %s.", tempFileName.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( data.saveLoadParms->cancelled ) {
|
||||
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
|
||||
}
|
||||
|
||||
// Removed because it seemed a bit drastic
|
||||
#if 0
|
||||
// If there is an error, delete the partially saved folder
|
||||
if ( callback->errorCode != SAVEGAME_E_NONE ) {
|
||||
if ( fileSystem->IsFolder( saveFolder, "fs_savePath" ) == FOLDER_YES ) {
|
||||
idFileList * files = fileSystem->ListFilesTree( saveFolder, "/|*" );
|
||||
for ( int i = 0; i < files->GetNumFiles(); i++ ) {
|
||||
fileSystem->RemoveFile( files->GetFile( i ) );
|
||||
}
|
||||
fileSystem->FreeFileList( files );
|
||||
fileSystem->RemoveDir( saveFolder );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocal::LoadGame
|
||||
========================
|
||||
*/
|
||||
int idSaveGameThread::Load() {
|
||||
idSaveLoadParms * callback = data.saveLoadParms;
|
||||
idStr saveFolder = "savegame";
|
||||
|
||||
saveFolder.AppendPath( callback->directory );
|
||||
|
||||
if ( fileSystem->IsFolder( saveFolder, "fs_savePath" ) != FOLDER_YES ) {
|
||||
callback->errorCode = SAVEGAME_E_FOLDER_NOT_FOUND;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = ERROR_SUCCESS;
|
||||
for ( int i = 0; i < callback->files.Num() && ret == ERROR_SUCCESS && !callback->cancelled; i++ ) {
|
||||
idFile_SaveGame * file = callback->files[i];
|
||||
|
||||
idStr filename = saveFolder;
|
||||
filename.AppendPath( file->GetName() );
|
||||
|
||||
idFile * inputFile = fileSystem->OpenFileRead( filename.c_str() );
|
||||
if ( inputFile == NULL ) {
|
||||
file->error = true;
|
||||
if ( !( file->type & SAVEGAMEFILE_OPTIONAL ) ) {
|
||||
callback->errorCode = SAVEGAME_E_CORRUPTED;
|
||||
ret = -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ( file->type & SAVEGAMEFILE_PIPELINED ) != 0 ) {
|
||||
|
||||
idFile_SaveGamePipelined * outputFile = dynamic_cast< idFile_SaveGamePipelined * >( file );
|
||||
assert( outputFile != NULL );
|
||||
|
||||
size_t lastReadBytes = 0;
|
||||
blockForIO_t block;
|
||||
while ( outputFile->NextReadBlock( &block, lastReadBytes ) && !callback->cancelled ) {
|
||||
lastReadBytes = inputFile->Read( block.data, block.bytes );
|
||||
if ( lastReadBytes != block.bytes ) {
|
||||
// Notify end-of-file to the save game file which will cause all reads on the
|
||||
// other end of the pipeline to return zero bytes after the pipeline is drained.
|
||||
outputFile->NextReadBlock( NULL, lastReadBytes );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
size_t size = inputFile->Length();
|
||||
|
||||
unsigned int originalChecksum = 0;
|
||||
if ( ( file->type & SAVEGAMEFILE_BINARY ) != 0 || ( file->type & SAVEGAMEFILE_COMPRESSED ) != 0 ) {
|
||||
if ( saveGame_checksum.GetBool() ) {
|
||||
if ( size >= sizeof( originalChecksum ) ) {
|
||||
inputFile->ReadBig( originalChecksum );
|
||||
size -= sizeof( originalChecksum );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file->SetLength( size );
|
||||
|
||||
size_t sizeRead = inputFile->Read( (void *)file->GetDataPtr(), size );
|
||||
if ( sizeRead != size ) {
|
||||
file->error = true;
|
||||
callback->errorCode = SAVEGAME_E_CORRUPTED;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if ( ( file->type & SAVEGAMEFILE_BINARY ) != 0 || ( file->type & SAVEGAMEFILE_COMPRESSED ) != 0 ) {
|
||||
if ( saveGame_checksum.GetBool() ) {
|
||||
unsigned int checksum = MD5_BlockChecksum( file->GetDataPtr(), file->Length() );
|
||||
if ( checksum != originalChecksum ) {
|
||||
file->error = true;
|
||||
callback->errorCode = SAVEGAME_E_CORRUPTED;
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete inputFile;
|
||||
}
|
||||
|
||||
if ( data.saveLoadParms->cancelled ) {
|
||||
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSaveGameThread::Delete
|
||||
|
||||
This deletes a complete savegame directory
|
||||
========================
|
||||
*/
|
||||
int idSaveGameThread::Delete() {
|
||||
idSaveLoadParms * callback = data.saveLoadParms;
|
||||
idStr saveFolder = "savegame";
|
||||
|
||||
saveFolder.AppendPath( callback->directory );
|
||||
|
||||
int ret = ERROR_SUCCESS;
|
||||
if ( fileSystem->IsFolder( saveFolder, "fs_savePath" ) == FOLDER_YES ) {
|
||||
idFileList * files = fileSystem->ListFilesTree( saveFolder, "/|*" );
|
||||
for ( int i = 0; i < files->GetNumFiles() && !callback->cancelled; i++ ) {
|
||||
fileSystem->RemoveFile( files->GetFile( i ) );
|
||||
}
|
||||
fileSystem->FreeFileList( files );
|
||||
|
||||
fileSystem->RemoveDir( saveFolder );
|
||||
} else {
|
||||
callback->errorCode = SAVEGAME_E_FOLDER_NOT_FOUND;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if ( data.saveLoadParms->cancelled ) {
|
||||
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSaveGameThread::Enumerate
|
||||
========================
|
||||
*/
|
||||
int idSaveGameThread::Enumerate() {
|
||||
idSaveLoadParms * callback = data.saveLoadParms;
|
||||
idStr saveFolder = "savegame";
|
||||
|
||||
callback->detailList.Clear();
|
||||
|
||||
int ret = ERROR_SUCCESS;
|
||||
if ( fileSystem->IsFolder( saveFolder, "fs_savePath" ) == FOLDER_YES ) {
|
||||
idFileList * files = fileSystem->ListFilesTree( saveFolder, SAVEGAME_DETAILS_FILENAME );
|
||||
const idStrList & fileList = files->GetList();
|
||||
|
||||
for ( int i = 0; i < fileList.Num() && !callback->cancelled; i++ ) {
|
||||
idSaveGameDetails * details = callback->detailList.Alloc();
|
||||
// We have more folders on disk than we have room in our save detail list, stop trying to read them in and continue with what we have
|
||||
if ( details == NULL ) {
|
||||
break;
|
||||
}
|
||||
idStr directory = fileList[i];
|
||||
|
||||
idFile * file = fileSystem->OpenFileRead( directory.c_str() );
|
||||
|
||||
if ( file != NULL ) {
|
||||
// Read the DETAIL file for the enumerated data
|
||||
if ( callback->mode & SAVEGAME_MBF_READ_DETAILS ) {
|
||||
if ( !SavegameReadDetailsFromFile( file, *details ) ) {
|
||||
details->damaged = true;
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Use the date from the directory
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrData;
|
||||
BOOL attrRet = GetFileAttributesEx( file->GetFullPath(), GetFileExInfoStandard, &attrData );
|
||||
delete file;
|
||||
if ( attrRet == TRUE ) {
|
||||
FILETIME lastWriteTime = attrData.ftLastWriteTime;
|
||||
const ULONGLONG second = 10000000L; // One second = 10,000,000 * 100 nsec
|
||||
SYSTEMTIME base_st = { 1970, 1, 0, 1, 0, 0, 0, 0 };
|
||||
ULARGE_INTEGER itime;
|
||||
FILETIME base_ft;
|
||||
BOOL success = SystemTimeToFileTime( &base_st, &base_ft );
|
||||
|
||||
itime.QuadPart = ((ULARGE_INTEGER *)&lastWriteTime)->QuadPart;
|
||||
if ( success ) {
|
||||
itime.QuadPart -= ((ULARGE_INTEGER *)&base_ft)->QuadPart;
|
||||
} else {
|
||||
// Hard coded number of 100-nanosecond units from 1/1/1601 to 1/1/1970
|
||||
itime.QuadPart -= 116444736000000000LL;
|
||||
}
|
||||
itime.QuadPart /= second;
|
||||
details->date = itime.QuadPart;
|
||||
}
|
||||
} else {
|
||||
details->damaged = true;
|
||||
}
|
||||
|
||||
// populate the game details struct
|
||||
directory = directory.StripFilename();
|
||||
details->slotName = directory.c_str() + saveFolder.Length() + 1; // Strip off the prefix too
|
||||
// JDC: I hit this all the time assert( fileSystem->IsFolder( directory.c_str(), "fs_savePath" ) == FOLDER_YES );
|
||||
}
|
||||
fileSystem->FreeFileList( files );
|
||||
} else {
|
||||
callback->errorCode = SAVEGAME_E_FOLDER_NOT_FOUND;
|
||||
ret = -3;
|
||||
}
|
||||
|
||||
if ( data.saveLoadParms->cancelled ) {
|
||||
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSaveGameThread::EnumerateFiles
|
||||
========================
|
||||
*/
|
||||
int idSaveGameThread::EnumerateFiles() {
|
||||
idSaveLoadParms * callback = data.saveLoadParms;
|
||||
idStr folder = "savegame";
|
||||
|
||||
folder.AppendPath( callback->directory );
|
||||
|
||||
callback->files.Clear();
|
||||
|
||||
int ret = ERROR_SUCCESS;
|
||||
if ( fileSystem->IsFolder( folder, "fs_savePath" ) == FOLDER_YES ) {
|
||||
// get listing of all the files, but filter out below
|
||||
idFileList * files = fileSystem->ListFilesTree( folder, "*.*" );
|
||||
|
||||
// look for the instance pattern
|
||||
for ( int i = 0; i < files->GetNumFiles() && ret == 0 && !callback->cancelled; i++ ) {
|
||||
idStr fullFilename = files->GetFile( i );
|
||||
idStr filename = fullFilename;
|
||||
filename.StripPath();
|
||||
|
||||
if ( filename.IcmpPrefix( callback->pattern ) != 0 ) {
|
||||
continue;
|
||||
}
|
||||
if ( !callback->postPattern.IsEmpty() && filename.Right( callback->postPattern.Length() ).IcmpPrefix( callback->postPattern ) != 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Read the DETAIL file for the enumerated data
|
||||
if ( callback->mode & SAVEGAME_MBF_READ_DETAILS ) {
|
||||
idSaveGameDetails & details = callback->description;
|
||||
idFile * uncompressed = fileSystem->OpenFileRead( fullFilename.c_str() );
|
||||
|
||||
if ( uncompressed == NULL ) {
|
||||
details.damaged = true;
|
||||
} else {
|
||||
if ( !SavegameReadDetailsFromFile( uncompressed, details ) ) {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
delete uncompressed;
|
||||
}
|
||||
|
||||
// populate the game details struct
|
||||
details.slotName = callback->directory;
|
||||
assert( fileSystem->IsFolder( details.slotName, "fs_savePath" ) == FOLDER_YES );
|
||||
}
|
||||
|
||||
idFile_SaveGame * file = new (TAG_SAVEGAMES) idFile_SaveGame( filename, SAVEGAMEFILE_AUTO_DELETE );
|
||||
callback->files.Append( file );
|
||||
}
|
||||
fileSystem->FreeFileList( files );
|
||||
} else {
|
||||
callback->errorCode = SAVEGAME_E_FOLDER_NOT_FOUND;
|
||||
ret = -3;
|
||||
}
|
||||
|
||||
if ( data.saveLoadParms->cancelled ) {
|
||||
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSaveGameThread::DeleteFiles
|
||||
========================
|
||||
*/
|
||||
int idSaveGameThread::DeleteFiles() {
|
||||
idSaveLoadParms * callback = data.saveLoadParms;
|
||||
idStr folder = "savegame";
|
||||
|
||||
folder.AppendPath( callback->directory );
|
||||
|
||||
// delete the explicitly requested files first
|
||||
for ( int j = 0; j < callback->files.Num() && !callback->cancelled; ++j ) {
|
||||
idFile_SaveGame * file = callback->files[j];
|
||||
idStr fullpath = folder;
|
||||
fullpath.AppendPath( file->GetName() );
|
||||
fileSystem->RemoveFile( fullpath );
|
||||
}
|
||||
|
||||
int ret = ERROR_SUCCESS;
|
||||
if ( fileSystem->IsFolder( folder, "fs_savePath" ) == FOLDER_YES ) {
|
||||
// get listing of all the files, but filter out below
|
||||
idFileList * files = fileSystem->ListFilesTree( folder, "*.*" );
|
||||
|
||||
// look for the instance pattern
|
||||
for ( int i = 0; i < files->GetNumFiles() && !callback->cancelled; i++ ) {
|
||||
idStr filename = files->GetFile( i );
|
||||
filename.StripPath();
|
||||
|
||||
// If there are post/pre patterns to match, make sure we adhere to the patterns
|
||||
if ( callback->pattern.IsEmpty() || ( filename.IcmpPrefix( callback->pattern ) != 0 ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( callback->postPattern.IsEmpty() || ( filename.Right( callback->postPattern.Length() ).IcmpPrefix( callback->postPattern ) != 0 ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fileSystem->RemoveFile( files->GetFile( i ) );
|
||||
}
|
||||
fileSystem->FreeFileList( files );
|
||||
} else {
|
||||
callback->errorCode = SAVEGAME_E_FOLDER_NOT_FOUND;
|
||||
ret = -3;
|
||||
}
|
||||
|
||||
if ( data.saveLoadParms->cancelled ) {
|
||||
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSaveGameThread::DeleteAll
|
||||
|
||||
This deletes all savegame directories
|
||||
========================
|
||||
*/
|
||||
int idSaveGameThread::DeleteAll() {
|
||||
idSaveLoadParms * callback = data.saveLoadParms;
|
||||
idStr saveFolder = "savegame";
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ( fileSystem->IsFolder( saveFolder, "fs_savePath" ) == FOLDER_YES ) {
|
||||
idFileList * files = fileSystem->ListFilesTree( saveFolder, "/|*" );
|
||||
// remove directories after files
|
||||
for ( int i = 0; i < files->GetNumFiles() && !callback->cancelled; i++ ) {
|
||||
// contained files should always be first
|
||||
if ( fileSystem->IsFolder( files->GetFile( i ), "fs_savePath" ) == FOLDER_YES ) {
|
||||
fileSystem->RemoveDir( files->GetFile( i ) );
|
||||
} else {
|
||||
fileSystem->RemoveFile( files->GetFile( i ) );
|
||||
}
|
||||
}
|
||||
fileSystem->FreeFileList( files );
|
||||
} else {
|
||||
callback->errorCode = SAVEGAME_E_FOLDER_NOT_FOUND;
|
||||
ret = -3;
|
||||
}
|
||||
|
||||
if ( data.saveLoadParms->cancelled ) {
|
||||
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSaveGameThread::Run
|
||||
========================
|
||||
*/
|
||||
int idSaveGameThread::Run() {
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
try {
|
||||
idLocalUserWin * user = GetLocalUserFromSaveParms( data );
|
||||
if ( user != NULL && !user->IsStorageDeviceAvailable() ) {
|
||||
data.saveLoadParms->errorCode = SAVEGAME_E_UNABLE_TO_SELECT_STORAGE_DEVICE;
|
||||
}
|
||||
|
||||
if ( savegame_winInduceDelay.GetInteger() > 0 ) {
|
||||
Sys_Sleep( savegame_winInduceDelay.GetInteger() );
|
||||
}
|
||||
|
||||
if ( data.saveLoadParms->mode & SAVEGAME_MBF_SAVE ) {
|
||||
ret = Save();
|
||||
} else if ( data.saveLoadParms->mode & SAVEGAME_MBF_LOAD ) {
|
||||
ret = Load();
|
||||
} else if ( data.saveLoadParms->mode & SAVEGAME_MBF_ENUMERATE ) {
|
||||
ret = Enumerate();
|
||||
} else if ( data.saveLoadParms->mode & SAVEGAME_MBF_DELETE_FOLDER ) {
|
||||
ret = Delete();
|
||||
} else if ( data.saveLoadParms->mode & SAVEGAME_MBF_DELETE_ALL_FOLDERS ) {
|
||||
ret = DeleteAll();
|
||||
} else if ( data.saveLoadParms->mode & SAVEGAME_MBF_DELETE_FILES ) {
|
||||
ret = DeleteFiles();
|
||||
} else if ( data.saveLoadParms->mode & SAVEGAME_MBF_ENUMERATE_FILES ) {
|
||||
ret = EnumerateFiles();
|
||||
}
|
||||
|
||||
// if something failed and no one set an error code, do it now.
|
||||
if ( ret != 0 && data.saveLoadParms->errorCode == SAVEGAME_E_NONE ) {
|
||||
data.saveLoadParms->errorCode = SAVEGAME_E_UNKNOWN;
|
||||
}
|
||||
} catch ( ... ) {
|
||||
// if anything horrible happens, leave it up to the savegame processors to handle in PostProcess().
|
||||
data.saveLoadParms->errorCode = SAVEGAME_E_UNKNOWN;
|
||||
}
|
||||
|
||||
// Make sure to cancel any save game file pipelines.
|
||||
if ( data.saveLoadParms->errorCode != SAVEGAME_E_NONE ) {
|
||||
data.saveLoadParms->CancelSaveGameFilePipelines();
|
||||
}
|
||||
|
||||
// Override error if cvar set
|
||||
if ( savegame_error.GetInteger() != 0 ) {
|
||||
data.saveLoadParms->errorCode = (saveGameError_t)savegame_error.GetInteger();
|
||||
}
|
||||
|
||||
// Tell the waiting caller that we are done
|
||||
data.saveLoadParms->callbackSignal.Raise();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Sys_SaveGameCheck
|
||||
========================
|
||||
*/
|
||||
void Sys_SaveGameCheck( bool & exists, bool & autosaveExists ) {
|
||||
exists = false;
|
||||
autosaveExists = false;
|
||||
|
||||
const idStr autosaveFolderStr = AddSaveFolderPrefix( SAVEGAME_AUTOSAVE_FOLDER, idSaveGameManager::PACKAGE_GAME );
|
||||
const char * autosaveFolder = autosaveFolderStr.c_str();
|
||||
const char * saveFolder = "savegame";
|
||||
|
||||
if ( fileSystem->IsFolder( saveFolder, "fs_savePath" ) == FOLDER_YES ) {
|
||||
idFileList * files = fileSystem->ListFiles( saveFolder, "/" );
|
||||
const idStrList & fileList = files->GetList();
|
||||
|
||||
idLib::PrintfIf( saveGame_verbose.GetBool(), "found %d savegames\n", fileList.Num() );
|
||||
|
||||
for ( int i = 0; i < fileList.Num(); i++ ) {
|
||||
const char * directory = va( "%s/%s", saveFolder, fileList[i].c_str() );
|
||||
|
||||
if ( fileSystem->IsFolder( directory, "fs_savePath" ) == FOLDER_YES ) {
|
||||
exists = true;
|
||||
|
||||
idLib::PrintfIf( saveGame_verbose.GetBool(), "found savegame: %s\n", fileList[i].c_str() );
|
||||
|
||||
if ( idStr::Icmp( fileList[i].c_str(), autosaveFolder ) == 0 ) {
|
||||
autosaveExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileSystem->FreeFileList( files );
|
||||
}
|
||||
}
|
||||
668
neo/sys/win32/win_session_local.cpp
Normal file
668
neo/sys/win32/win_session_local.cpp
Normal file
@@ -0,0 +1,668 @@
|
||||
/*
|
||||
================================================================================================
|
||||
CONFIDENTIAL AND PROPRIETARY INFORMATION/NOT FOR DISCLOSURE WITHOUT WRITTEN PERMISSION
|
||||
Copyright 2010 id Software LLC, a ZeniMax Media company. All Rights Reserved.
|
||||
================================================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
================================================================================================
|
||||
|
||||
Contains the windows implementation of the network session
|
||||
|
||||
================================================================================================
|
||||
*/
|
||||
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
#include "../../framework/Common_local.h"
|
||||
#include "../sys_session_local.h"
|
||||
#include "../sys_stats.h"
|
||||
#include "../sys_savegame.h"
|
||||
#include "../sys_lobby_backend_direct.h"
|
||||
#include "../sys_voicechat.h"
|
||||
#include "win_achievements.h"
|
||||
#include "win_local.h"
|
||||
|
||||
/*
|
||||
========================
|
||||
Global variables
|
||||
========================
|
||||
*/
|
||||
|
||||
extern idCVar net_port;
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::idSessionLocalWin
|
||||
========================
|
||||
*/
|
||||
class idSessionLocalWin : public idSessionLocal {
|
||||
friend class idLobbyToSessionCBLocal;
|
||||
|
||||
public:
|
||||
idSessionLocalWin();
|
||||
virtual ~idSessionLocalWin();
|
||||
|
||||
// idSessionLocal interface
|
||||
virtual void Initialize();
|
||||
virtual void Shutdown();
|
||||
|
||||
virtual void InitializeSoundRelatedSystems();
|
||||
virtual void ShutdownSoundRelatedSystems();
|
||||
|
||||
virtual void PlatformPump();
|
||||
|
||||
virtual void InviteFriends();
|
||||
virtual void InviteParty();
|
||||
virtual void ShowPartySessions();
|
||||
|
||||
virtual void ShowSystemMarketplaceUI() const;
|
||||
|
||||
virtual void ListServers( const idCallback & callback );
|
||||
virtual void CancelListServers();
|
||||
virtual int NumServers() const;
|
||||
virtual const serverInfo_t * ServerInfo( int i ) const;
|
||||
virtual void ConnectToServer( int i );
|
||||
virtual void ShowServerGamerCardUI( int i );
|
||||
|
||||
virtual void ShowLobbyUserGamerCardUI( lobbyUserID_t lobbyUserID );
|
||||
|
||||
virtual void ShowOnlineSignin() {}
|
||||
virtual void UpdateRichPresence() {}
|
||||
virtual void CheckVoicePrivileges() {}
|
||||
|
||||
virtual bool ProcessInputEvent( const sysEvent_t * ev );
|
||||
|
||||
// System UI
|
||||
virtual bool IsSystemUIShowing() const;
|
||||
virtual void SetSystemUIShowing( bool show );
|
||||
|
||||
// Invites
|
||||
virtual void HandleBootableInvite( int64 lobbyId = 0 );
|
||||
virtual void ClearBootableInvite();
|
||||
virtual void ClearPendingInvite();
|
||||
|
||||
virtual bool HasPendingBootableInvite();
|
||||
virtual void SetDiscSwapMPInvite( void * parm );
|
||||
virtual void * GetDiscSwapMPInviteParms();
|
||||
|
||||
virtual void EnumerateDownloadableContent();
|
||||
|
||||
virtual void HandleServerQueryRequest( lobbyAddress_t & remoteAddr, idBitMsg & msg, int msgType );
|
||||
virtual void HandleServerQueryAck( lobbyAddress_t & remoteAddr, idBitMsg & msg );
|
||||
|
||||
// Leaderboards
|
||||
virtual void LeaderboardUpload( lobbyUserID_t lobbyUserID, const leaderboardDefinition_t * leaderboard, const column_t * stats, const idFile_Memory * attachment = NULL );
|
||||
virtual void LeaderboardDownload( int sessionUserIndex, const leaderboardDefinition_t * leaderboard, int startingRank, int numRows, const idLeaderboardCallback & callback );
|
||||
virtual void LeaderboardDownloadAttachment( int sessionUserIndex, const leaderboardDefinition_t * leaderboard, int64 attachmentID );
|
||||
|
||||
// Scoring (currently just for TrueSkill)
|
||||
virtual void SetLobbyUserRelativeScore( lobbyUserID_t lobbyUserID, int relativeScore, int team ) {}
|
||||
|
||||
virtual void LeaderboardFlush();
|
||||
|
||||
virtual idNetSessionPort & GetPort( bool dedicated = false );
|
||||
virtual idLobbyBackend * CreateLobbyBackend( const idMatchParameters & p, float skillLevel, idLobbyBackend::lobbyBackendType_t lobbyType );
|
||||
virtual idLobbyBackend * FindLobbyBackend( const idMatchParameters & p, int numPartyUsers, float skillLevel, idLobbyBackend::lobbyBackendType_t lobbyType );
|
||||
virtual idLobbyBackend * JoinFromConnectInfo( const lobbyConnectInfo_t & connectInfo , idLobbyBackend::lobbyBackendType_t lobbyType );
|
||||
virtual void DestroyLobbyBackend( idLobbyBackend * lobbyBackend );
|
||||
virtual void PumpLobbies();
|
||||
virtual void JoinAfterSwap( void * joinID );
|
||||
|
||||
virtual bool GetLobbyAddressFromNetAddress( const netadr_t & netAddr, lobbyAddress_t & outAddr ) const;
|
||||
virtual bool GetNetAddressFromLobbyAddress( const lobbyAddress_t & lobbyAddress, netadr_t & outNetAddr ) const;
|
||||
|
||||
public:
|
||||
void Connect_f( const idCmdArgs &args );
|
||||
|
||||
private:
|
||||
void EnsurePort();
|
||||
|
||||
idLobbyBackend * CreateLobbyInternal( idLobbyBackend::lobbyBackendType_t lobbyType );
|
||||
|
||||
idArray< idLobbyBackend *, 3 > lobbyBackends;
|
||||
|
||||
idNetSessionPort port;
|
||||
bool canJoinLocalHost;
|
||||
|
||||
idLobbyToSessionCBLocal * lobbyToSessionCB;
|
||||
};
|
||||
|
||||
idSessionLocalWin sessionLocalWin;
|
||||
idSession * session = &sessionLocalWin;
|
||||
|
||||
/*
|
||||
========================
|
||||
idLobbyToSessionCBLocal
|
||||
========================
|
||||
*/
|
||||
class idLobbyToSessionCBLocal : public idLobbyToSessionCB {
|
||||
public:
|
||||
idLobbyToSessionCBLocal( idSessionLocalWin * sessionLocalWin_ ) : sessionLocalWin( sessionLocalWin_ ) { }
|
||||
|
||||
virtual bool CanJoinLocalHost() const { sessionLocalWin->EnsurePort(); return sessionLocalWin->canJoinLocalHost; }
|
||||
virtual class idLobbyBackend * GetLobbyBackend( idLobbyBackend::lobbyBackendType_t type ) const { return sessionLocalWin->lobbyBackends[ type ]; }
|
||||
|
||||
private:
|
||||
idSessionLocalWin * sessionLocalWin;
|
||||
};
|
||||
|
||||
idLobbyToSessionCBLocal lobbyToSessionCBLocal( &sessionLocalWin );
|
||||
idLobbyToSessionCB * lobbyToSessionCB = &lobbyToSessionCBLocal;
|
||||
|
||||
class idVoiceChatMgrWin : public idVoiceChatMgr {
|
||||
public:
|
||||
virtual bool GetLocalChatDataInternal( int talkerIndex, byte * data, int & dataSize ) { return false; }
|
||||
virtual void SubmitIncomingChatDataInternal( int talkerIndex, const byte * data, int dataSize ) { }
|
||||
virtual bool TalkerHasData( int talkerIndex ) { return false; }
|
||||
virtual bool RegisterTalkerInternal( int index ) { return true; }
|
||||
virtual void UnregisterTalkerInternal( int index ) { }
|
||||
};
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::idSessionLocalWin
|
||||
========================
|
||||
*/
|
||||
idSessionLocalWin::idSessionLocalWin() {
|
||||
signInManager = new (TAG_SYSTEM) idSignInManagerWin;
|
||||
saveGameManager = new (TAG_SAVEGAMES) idSaveGameManager();
|
||||
voiceChat = new (TAG_SYSTEM) idVoiceChatMgrWin();
|
||||
lobbyToSessionCB = new (TAG_SYSTEM) idLobbyToSessionCBLocal( this );
|
||||
|
||||
canJoinLocalHost = false;
|
||||
|
||||
lobbyBackends.Zero();
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::idSessionLocalWin
|
||||
========================
|
||||
*/
|
||||
idSessionLocalWin::~idSessionLocalWin() {
|
||||
delete voiceChat;
|
||||
delete lobbyToSessionCB;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::Initialize
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::Initialize() {
|
||||
idSessionLocal::Initialize();
|
||||
|
||||
// The shipping path doesn't load title storage
|
||||
// Instead, we inject values through code which is protected through steam DRM
|
||||
titleStorageVars.Set( "MAX_PLAYERS_ALLOWED", "8" );
|
||||
titleStorageLoaded = true;
|
||||
|
||||
// First-time check for downloadable content once game is launched
|
||||
EnumerateDownloadableContent();
|
||||
|
||||
GetPartyLobby().Initialize( idLobby::TYPE_PARTY, sessionCallbacks );
|
||||
GetGameLobby().Initialize( idLobby::TYPE_GAME, sessionCallbacks );
|
||||
GetGameStateLobby().Initialize( idLobby::TYPE_GAME_STATE, sessionCallbacks );
|
||||
|
||||
achievementSystem = new (TAG_SYSTEM) idAchievementSystemWin();
|
||||
achievementSystem->Init();
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::Shutdown
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::Shutdown() {
|
||||
NET_VERBOSE_PRINT( "NET: Shutdown\n" );
|
||||
idSessionLocal::Shutdown();
|
||||
|
||||
MoveToMainMenu();
|
||||
|
||||
// Wait until we fully shutdown
|
||||
while ( localState != STATE_IDLE && localState != STATE_PRESS_START ) {
|
||||
Pump();
|
||||
}
|
||||
|
||||
if ( achievementSystem != NULL ) {
|
||||
achievementSystem->Shutdown();
|
||||
delete achievementSystem;
|
||||
achievementSystem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::InitializeSoundRelatedSystems
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::InitializeSoundRelatedSystems() {
|
||||
if ( voiceChat != NULL ) {
|
||||
voiceChat->Init( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::ShutdownSoundRelatedSystems
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::ShutdownSoundRelatedSystems() {
|
||||
if ( voiceChat != NULL ) {
|
||||
voiceChat->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::PlatformPump
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::PlatformPump() {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::InviteFriends
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::InviteFriends() {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::InviteParty
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::InviteParty() {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::ShowPartySessions
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::ShowPartySessions() {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::ShowSystemMarketplaceUI
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::ShowSystemMarketplaceUI() const {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::ListServers
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::ListServers( const idCallback & callback ) {
|
||||
ListServersCommon();
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::CancelListServers
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::CancelListServers() {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::NumServers
|
||||
========================
|
||||
*/
|
||||
int idSessionLocalWin::NumServers() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::ServerInfo
|
||||
========================
|
||||
*/
|
||||
const serverInfo_t * idSessionLocalWin::ServerInfo( int i ) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::ConnectToServer
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::ConnectToServer( int i ) {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::Connect_f
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::Connect_f( const idCmdArgs &args ) {
|
||||
if ( args.Argc() < 2 ) {
|
||||
idLib::Printf( "Usage: Connect to IP. Use with net_port. \n");
|
||||
return;
|
||||
}
|
||||
|
||||
Cancel();
|
||||
|
||||
if ( signInManager->GetMasterLocalUser() == NULL ) {
|
||||
signInManager->RegisterLocalUser( 0 );
|
||||
}
|
||||
|
||||
lobbyConnectInfo_t connectInfo;
|
||||
|
||||
Sys_StringToNetAdr( args.Argv(1), &connectInfo.netAddr, true );
|
||||
connectInfo.netAddr.port = net_port.GetInteger();
|
||||
|
||||
ConnectAndMoveToLobby( GetPartyLobby(), connectInfo, false );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
void Connect_f
|
||||
========================
|
||||
*/
|
||||
CONSOLE_COMMAND( connect, "Connect to the specified IP", NULL ) {
|
||||
sessionLocalWin.Connect_f( args );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::ShowServerGamerCardUI
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::ShowServerGamerCardUI( int i ) {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::ShowLobbyUserGamerCardUI(
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::ShowLobbyUserGamerCardUI( lobbyUserID_t lobbyUserID ) {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::ProcessInputEvent
|
||||
========================
|
||||
*/
|
||||
bool idSessionLocalWin::ProcessInputEvent( const sysEvent_t * ev ) {
|
||||
if ( GetSignInManager().ProcessInputEvent( ev ) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::IsSystemUIShowing
|
||||
========================
|
||||
*/
|
||||
bool idSessionLocalWin::IsSystemUIShowing() const {
|
||||
return !win32.activeApp || isSysUIShowing; // If the user alt+tabs away, treat it the same as bringing up the steam overlay
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::SetSystemUIShowing
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::SetSystemUIShowing( bool show ) {
|
||||
isSysUIShowing = show;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::HandleServerQueryRequest
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::HandleServerQueryRequest( lobbyAddress_t & remoteAddr, idBitMsg & msg, int msgType ) {
|
||||
NET_VERBOSE_PRINT( "HandleServerQueryRequest from %s\n", remoteAddr.ToString() );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::HandleServerQueryAck
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::HandleServerQueryAck( lobbyAddress_t & remoteAddr, idBitMsg & msg ) {
|
||||
NET_VERBOSE_PRINT( "HandleServerQueryAck from %s\n", remoteAddr.ToString() );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::ClearBootableInvite
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::ClearBootableInvite() {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::ClearPendingInvite
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::ClearPendingInvite() {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::HandleBootableInvite
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::HandleBootableInvite( int64 lobbyId ) {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::HasPendingBootableInvite
|
||||
========================
|
||||
*/
|
||||
bool idSessionLocalWin::HasPendingBootableInvite() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocal::SetDiscSwapMPInvite
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::SetDiscSwapMPInvite( void * parm ) {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocal::GetDiscSwapMPInviteParms
|
||||
========================
|
||||
*/
|
||||
void * idSessionLocalWin::GetDiscSwapMPInviteParms() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::EnumerateDownloadableContent
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::EnumerateDownloadableContent() {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::LeaderboardUpload
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::LeaderboardUpload( lobbyUserID_t lobbyUserID, const leaderboardDefinition_t * leaderboard, const column_t * stats, const idFile_Memory * attachment ) {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::LeaderboardFlush
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::LeaderboardFlush() {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::LeaderboardDownload
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::LeaderboardDownload( int sessionUserIndex, const leaderboardDefinition_t * leaderboard, int startingRank, int numRows, const idLeaderboardCallback & callback ) {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::LeaderboardDownloadAttachment
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::LeaderboardDownloadAttachment( int sessionUserIndex, const leaderboardDefinition_t * leaderboard, int64 attachmentID ) {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::EnsurePort
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::EnsurePort() {
|
||||
// Init the port using reqular windows sockets
|
||||
if ( port.IsOpen() ) {
|
||||
return; // Already initialized
|
||||
}
|
||||
|
||||
if ( port.InitPort( net_port.GetInteger(), false ) ) {
|
||||
canJoinLocalHost = false;
|
||||
} else {
|
||||
// Assume this is another instantiation on the same machine, and just init using any available port
|
||||
port.InitPort( PORT_ANY, false );
|
||||
canJoinLocalHost = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::GetPort
|
||||
========================
|
||||
*/
|
||||
idNetSessionPort & idSessionLocalWin::GetPort( bool dedicated ) {
|
||||
EnsurePort();
|
||||
return port;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::CreateLobbyBackend
|
||||
========================
|
||||
*/
|
||||
idLobbyBackend * idSessionLocalWin::CreateLobbyBackend( const idMatchParameters & p, float skillLevel, idLobbyBackend::lobbyBackendType_t lobbyType ) {
|
||||
idLobbyBackend * lobbyBackend = CreateLobbyInternal( lobbyType );
|
||||
lobbyBackend->StartHosting( p, skillLevel, lobbyType );
|
||||
return lobbyBackend;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::FindLobbyBackend
|
||||
========================
|
||||
*/
|
||||
idLobbyBackend * idSessionLocalWin::FindLobbyBackend( const idMatchParameters & p, int numPartyUsers, float skillLevel, idLobbyBackend::lobbyBackendType_t lobbyType ) {
|
||||
idLobbyBackend * lobbyBackend = CreateLobbyInternal( lobbyType );
|
||||
lobbyBackend->StartFinding( p, numPartyUsers, skillLevel );
|
||||
return lobbyBackend;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::JoinFromConnectInfo
|
||||
========================
|
||||
*/
|
||||
idLobbyBackend * idSessionLocalWin::JoinFromConnectInfo( const lobbyConnectInfo_t & connectInfo, idLobbyBackend::lobbyBackendType_t lobbyType ) {
|
||||
idLobbyBackend * lobbyBackend = CreateLobbyInternal( lobbyType );
|
||||
lobbyBackend->JoinFromConnectInfo( connectInfo );
|
||||
return lobbyBackend;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::DestroyLobbyBackend
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::DestroyLobbyBackend( idLobbyBackend * lobbyBackend ) {
|
||||
assert( lobbyBackend != NULL );
|
||||
assert( lobbyBackends[lobbyBackend->GetLobbyType()] == lobbyBackend );
|
||||
|
||||
lobbyBackends[lobbyBackend->GetLobbyType()] = NULL;
|
||||
|
||||
lobbyBackend->Shutdown();
|
||||
delete lobbyBackend;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::PumpLobbies
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::PumpLobbies() {
|
||||
assert( lobbyBackends[idLobbyBackend::TYPE_PARTY] == NULL || lobbyBackends[idLobbyBackend::TYPE_PARTY]->GetLobbyType() == idLobbyBackend::TYPE_PARTY );
|
||||
assert( lobbyBackends[idLobbyBackend::TYPE_GAME] == NULL || lobbyBackends[idLobbyBackend::TYPE_GAME]->GetLobbyType() == idLobbyBackend::TYPE_GAME );
|
||||
assert( lobbyBackends[idLobbyBackend::TYPE_GAME_STATE] == NULL || lobbyBackends[idLobbyBackend::TYPE_GAME_STATE]->GetLobbyType() == idLobbyBackend::TYPE_GAME_STATE );
|
||||
|
||||
// Pump lobbyBackends
|
||||
for ( int i = 0; i < lobbyBackends.Num(); i++ ) {
|
||||
if ( lobbyBackends[i] != NULL ) {
|
||||
lobbyBackends[i]->Pump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::CreateLobbyInternal
|
||||
========================
|
||||
*/
|
||||
idLobbyBackend * idSessionLocalWin::CreateLobbyInternal( idLobbyBackend::lobbyBackendType_t lobbyType ) {
|
||||
EnsurePort();
|
||||
idLobbyBackend * lobbyBackend = new (TAG_NETWORKING) idLobbyBackendDirect();
|
||||
|
||||
lobbyBackend->SetLobbyType( lobbyType );
|
||||
|
||||
assert( lobbyBackends[lobbyType] == NULL );
|
||||
lobbyBackends[lobbyType] = lobbyBackend;
|
||||
|
||||
return lobbyBackend;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::JoinAfterSwap
|
||||
========================
|
||||
*/
|
||||
void idSessionLocalWin::JoinAfterSwap( void * joinID ) {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::GetLobbyAddressFromNetAddress
|
||||
========================
|
||||
*/
|
||||
bool idSessionLocalWin::GetLobbyAddressFromNetAddress( const netadr_t & netAddr, lobbyAddress_t & outAddr ) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSessionLocalWin::GetNetAddressFromLobbyAddress
|
||||
========================
|
||||
*/
|
||||
bool idSessionLocalWin::GetNetAddressFromLobbyAddress( const lobbyAddress_t & lobbyAddress, netadr_t & outNetAddr ) const {
|
||||
return false;
|
||||
}
|
||||
800
neo/sys/win32/win_shared.cpp
Normal file
800
neo/sys/win32/win_shared.cpp
Normal file
@@ -0,0 +1,800 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
|
||||
#include "win_local.h"
|
||||
#include <lmerr.h>
|
||||
#include <lmcons.h>
|
||||
#include <lmwksta.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <conio.h>
|
||||
#undef StrCmpN
|
||||
#undef StrCmpNI
|
||||
#undef StrCmpI
|
||||
#include <atlbase.h>
|
||||
|
||||
#include <comdef.h>
|
||||
#include <comutil.h>
|
||||
#include <Wbemidl.h>
|
||||
|
||||
#pragma comment (lib, "wbemuuid.lib")
|
||||
|
||||
#pragma warning(disable:4740) // warning C4740: flow in or out of inline asm code suppresses global optimization
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_Milliseconds
|
||||
================
|
||||
*/
|
||||
int Sys_Milliseconds() {
|
||||
static DWORD sys_timeBase = timeGetTime();
|
||||
return timeGetTime() - sys_timeBase;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Sys_Microseconds
|
||||
========================
|
||||
*/
|
||||
uint64 Sys_Microseconds() {
|
||||
static uint64 ticksPerMicrosecondTimes1024 = 0;
|
||||
|
||||
if ( ticksPerMicrosecondTimes1024 == 0 ) {
|
||||
ticksPerMicrosecondTimes1024 = ( (uint64)Sys_ClockTicksPerSecond() << 10 ) / 1000000;
|
||||
assert( ticksPerMicrosecondTimes1024 > 0 );
|
||||
}
|
||||
|
||||
return ((uint64)( (int64)Sys_GetClockTicks() << 10 )) / ticksPerMicrosecondTimes1024;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetSystemRam
|
||||
|
||||
returns amount of physical memory in MB
|
||||
================
|
||||
*/
|
||||
int Sys_GetSystemRam() {
|
||||
MEMORYSTATUSEX statex;
|
||||
statex.dwLength = sizeof ( statex );
|
||||
GlobalMemoryStatusEx (&statex);
|
||||
int physRam = statex.ullTotalPhys / ( 1024 * 1024 );
|
||||
// HACK: For some reason, ullTotalPhys is sometimes off by a meg or two, so we round up to the nearest 16 megs
|
||||
physRam = ( physRam + 8 ) & ~15;
|
||||
return physRam;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetDriveFreeSpace
|
||||
returns in megabytes
|
||||
================
|
||||
*/
|
||||
int Sys_GetDriveFreeSpace( const char *path ) {
|
||||
DWORDLONG lpFreeBytesAvailable;
|
||||
DWORDLONG lpTotalNumberOfBytes;
|
||||
DWORDLONG lpTotalNumberOfFreeBytes;
|
||||
int ret = 26;
|
||||
//FIXME: see why this is failing on some machines
|
||||
if ( ::GetDiskFreeSpaceEx( path, (PULARGE_INTEGER)&lpFreeBytesAvailable, (PULARGE_INTEGER)&lpTotalNumberOfBytes, (PULARGE_INTEGER)&lpTotalNumberOfFreeBytes ) ) {
|
||||
ret = ( double )( lpFreeBytesAvailable ) / ( 1024.0 * 1024.0 );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Sys_GetDriveFreeSpaceInBytes
|
||||
========================
|
||||
*/
|
||||
int64 Sys_GetDriveFreeSpaceInBytes( const char * path ) {
|
||||
DWORDLONG lpFreeBytesAvailable;
|
||||
DWORDLONG lpTotalNumberOfBytes;
|
||||
DWORDLONG lpTotalNumberOfFreeBytes;
|
||||
int64 ret = 1;
|
||||
//FIXME: see why this is failing on some machines
|
||||
if ( ::GetDiskFreeSpaceEx( path, (PULARGE_INTEGER)&lpFreeBytesAvailable, (PULARGE_INTEGER)&lpTotalNumberOfBytes, (PULARGE_INTEGER)&lpTotalNumberOfFreeBytes ) ) {
|
||||
ret = lpFreeBytesAvailable;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetVideoRam
|
||||
returns in megabytes
|
||||
================
|
||||
*/
|
||||
int Sys_GetVideoRam() {
|
||||
unsigned int retSize = 64;
|
||||
|
||||
CComPtr<IWbemLocator> spLoc = NULL;
|
||||
HRESULT hr = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_SERVER, IID_IWbemLocator, ( LPVOID * ) &spLoc );
|
||||
if ( hr != S_OK || spLoc == NULL ) {
|
||||
return retSize;
|
||||
}
|
||||
|
||||
CComBSTR bstrNamespace( _T( "\\\\.\\root\\CIMV2" ) );
|
||||
CComPtr<IWbemServices> spServices;
|
||||
|
||||
// Connect to CIM
|
||||
hr = spLoc->ConnectServer( bstrNamespace, NULL, NULL, 0, NULL, 0, 0, &spServices );
|
||||
if ( hr != WBEM_S_NO_ERROR ) {
|
||||
return retSize;
|
||||
}
|
||||
|
||||
// Switch the security level to IMPERSONATE so that provider will grant access to system-level objects.
|
||||
hr = CoSetProxyBlanket( spServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
|
||||
if ( hr != S_OK ) {
|
||||
return retSize;
|
||||
}
|
||||
|
||||
// Get the vid controller
|
||||
CComPtr<IEnumWbemClassObject> spEnumInst = NULL;
|
||||
hr = spServices->CreateInstanceEnum( CComBSTR( "Win32_VideoController" ), WBEM_FLAG_SHALLOW, NULL, &spEnumInst );
|
||||
if ( hr != WBEM_S_NO_ERROR || spEnumInst == NULL ) {
|
||||
return retSize;
|
||||
}
|
||||
|
||||
ULONG uNumOfInstances = 0;
|
||||
CComPtr<IWbemClassObject> spInstance = NULL;
|
||||
hr = spEnumInst->Next( 10000, 1, &spInstance, &uNumOfInstances );
|
||||
|
||||
if ( hr == S_OK && spInstance ) {
|
||||
// Get properties from the object
|
||||
CComVariant varSize;
|
||||
hr = spInstance->Get( CComBSTR( _T( "AdapterRAM" ) ), 0, &varSize, 0, 0 );
|
||||
if ( hr == S_OK ) {
|
||||
retSize = varSize.intVal / ( 1024 * 1024 );
|
||||
if ( retSize == 0 ) {
|
||||
retSize = 64;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retSize;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetCurrentMemoryStatus
|
||||
|
||||
returns OS mem info
|
||||
all values are in kB except the memoryload
|
||||
================
|
||||
*/
|
||||
void Sys_GetCurrentMemoryStatus( sysMemoryStats_t &stats ) {
|
||||
MEMORYSTATUSEX statex = {};
|
||||
unsigned __int64 work;
|
||||
|
||||
statex.dwLength = sizeof( statex );
|
||||
GlobalMemoryStatusEx( &statex );
|
||||
|
||||
memset( &stats, 0, sizeof( stats ) );
|
||||
|
||||
stats.memoryLoad = statex.dwMemoryLoad;
|
||||
|
||||
work = statex.ullTotalPhys >> 20;
|
||||
stats.totalPhysical = *(int*)&work;
|
||||
|
||||
work = statex.ullAvailPhys >> 20;
|
||||
stats.availPhysical = *(int*)&work;
|
||||
|
||||
work = statex.ullAvailPageFile >> 20;
|
||||
stats.availPageFile = *(int*)&work;
|
||||
|
||||
work = statex.ullTotalPageFile >> 20;
|
||||
stats.totalPageFile = *(int*)&work;
|
||||
|
||||
work = statex.ullTotalVirtual >> 20;
|
||||
stats.totalVirtual = *(int*)&work;
|
||||
|
||||
work = statex.ullAvailVirtual >> 20;
|
||||
stats.availVirtual = *(int*)&work;
|
||||
|
||||
work = statex.ullAvailExtendedVirtual >> 20;
|
||||
stats.availExtendedVirtual = *(int*)&work;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_LockMemory
|
||||
================
|
||||
*/
|
||||
bool Sys_LockMemory( void *ptr, int bytes ) {
|
||||
return ( VirtualLock( ptr, (SIZE_T)bytes ) != FALSE );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_UnlockMemory
|
||||
================
|
||||
*/
|
||||
bool Sys_UnlockMemory( void *ptr, int bytes ) {
|
||||
return ( VirtualUnlock( ptr, (SIZE_T)bytes ) != FALSE );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_SetPhysicalWorkMemory
|
||||
================
|
||||
*/
|
||||
void Sys_SetPhysicalWorkMemory( int minBytes, int maxBytes ) {
|
||||
::SetProcessWorkingSetSize( GetCurrentProcess(), minBytes, maxBytes );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetCurrentUser
|
||||
================
|
||||
*/
|
||||
char *Sys_GetCurrentUser() {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Call stack
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
|
||||
#define PROLOGUE_SIGNATURE 0x00EC8B55
|
||||
|
||||
#include <dbghelp.h>
|
||||
|
||||
const int UNDECORATE_FLAGS = UNDNAME_NO_MS_KEYWORDS |
|
||||
UNDNAME_NO_ACCESS_SPECIFIERS |
|
||||
UNDNAME_NO_FUNCTION_RETURNS |
|
||||
UNDNAME_NO_ALLOCATION_MODEL |
|
||||
UNDNAME_NO_ALLOCATION_LANGUAGE |
|
||||
UNDNAME_NO_MEMBER_TYPE;
|
||||
|
||||
#if defined(_DEBUG) && 1
|
||||
|
||||
typedef struct symbol_s {
|
||||
int address;
|
||||
char * name;
|
||||
struct symbol_s * next;
|
||||
} symbol_t;
|
||||
|
||||
typedef struct module_s {
|
||||
int address;
|
||||
char * name;
|
||||
symbol_t * symbols;
|
||||
struct module_s * next;
|
||||
} module_t;
|
||||
|
||||
module_t *modules;
|
||||
|
||||
/*
|
||||
==================
|
||||
SkipRestOfLine
|
||||
==================
|
||||
*/
|
||||
void SkipRestOfLine( const char **ptr ) {
|
||||
while( (**ptr) != '\0' && (**ptr) != '\n' && (**ptr) != '\r' ) {
|
||||
(*ptr)++;
|
||||
}
|
||||
while( (**ptr) == '\n' || (**ptr) == '\r' ) {
|
||||
(*ptr)++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SkipWhiteSpace
|
||||
==================
|
||||
*/
|
||||
void SkipWhiteSpace( const char **ptr ) {
|
||||
while( (**ptr) == ' ' ) {
|
||||
(*ptr)++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
ParseHexNumber
|
||||
==================
|
||||
*/
|
||||
int ParseHexNumber( const char **ptr ) {
|
||||
int n = 0;
|
||||
while( (**ptr) >= '0' && (**ptr) <= '9' || (**ptr) >= 'a' && (**ptr) <= 'f' ) {
|
||||
n <<= 4;
|
||||
if ( **ptr >= '0' && **ptr <= '9' ) {
|
||||
n |= ( (**ptr) - '0' );
|
||||
} else {
|
||||
n |= 10 + ( (**ptr) - 'a' );
|
||||
}
|
||||
(*ptr)++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sym_Init
|
||||
==================
|
||||
*/
|
||||
void Sym_Init( long addr ) {
|
||||
TCHAR moduleName[MAX_STRING_CHARS];
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
|
||||
VirtualQuery( (void*)addr, &mbi, sizeof(mbi) );
|
||||
|
||||
GetModuleFileName( (HMODULE)mbi.AllocationBase, moduleName, sizeof( moduleName ) );
|
||||
|
||||
char *ext = moduleName + strlen( moduleName );
|
||||
while( ext > moduleName && *ext != '.' ) {
|
||||
ext--;
|
||||
}
|
||||
if ( ext == moduleName ) {
|
||||
strcat( moduleName, ".map" );
|
||||
} else {
|
||||
strcpy( ext, ".map" );
|
||||
}
|
||||
|
||||
module_t *module = (module_t *) malloc( sizeof( module_t ) );
|
||||
module->name = (char *) malloc( strlen( moduleName ) + 1 );
|
||||
strcpy( module->name, moduleName );
|
||||
module->address = (int)mbi.AllocationBase;
|
||||
module->symbols = NULL;
|
||||
module->next = modules;
|
||||
modules = module;
|
||||
|
||||
FILE * fp = fopen( moduleName, "rb" );
|
||||
if ( fp == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
int pos = ftell( fp );
|
||||
fseek( fp, 0, SEEK_END );
|
||||
int length = ftell( fp );
|
||||
fseek( fp, pos, SEEK_SET );
|
||||
|
||||
char *text = (char *) malloc( length+1 );
|
||||
fread( text, 1, length, fp );
|
||||
text[length] = '\0';
|
||||
fclose( fp );
|
||||
|
||||
const char *ptr = text;
|
||||
|
||||
// skip up to " Address" on a new line
|
||||
while( *ptr != '\0' ) {
|
||||
SkipWhiteSpace( &ptr );
|
||||
if ( idStr::Cmpn( ptr, "Address", 7 ) == 0 ) {
|
||||
SkipRestOfLine( &ptr );
|
||||
break;
|
||||
}
|
||||
SkipRestOfLine( &ptr );
|
||||
}
|
||||
|
||||
int symbolAddress;
|
||||
int symbolLength;
|
||||
char symbolName[MAX_STRING_CHARS];
|
||||
symbol_t *symbol;
|
||||
|
||||
// parse symbols
|
||||
while( *ptr != '\0' ) {
|
||||
|
||||
SkipWhiteSpace( &ptr );
|
||||
|
||||
ParseHexNumber( &ptr );
|
||||
if ( *ptr == ':' ) {
|
||||
ptr++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
ParseHexNumber( &ptr );
|
||||
|
||||
SkipWhiteSpace( &ptr );
|
||||
|
||||
// parse symbol name
|
||||
symbolLength = 0;
|
||||
while( *ptr != '\0' && *ptr != ' ' ) {
|
||||
symbolName[symbolLength++] = *ptr++;
|
||||
if ( symbolLength >= sizeof( symbolName ) - 1 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
symbolName[symbolLength++] = '\0';
|
||||
|
||||
SkipWhiteSpace( &ptr );
|
||||
|
||||
// parse symbol address
|
||||
symbolAddress = ParseHexNumber( &ptr );
|
||||
|
||||
SkipRestOfLine( &ptr );
|
||||
|
||||
symbol = (symbol_t *) malloc( sizeof( symbol_t ) );
|
||||
symbol->name = (char *) malloc( symbolLength );
|
||||
strcpy( symbol->name, symbolName );
|
||||
symbol->address = symbolAddress;
|
||||
symbol->next = module->symbols;
|
||||
module->symbols = symbol;
|
||||
}
|
||||
|
||||
free( text );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sym_Shutdown
|
||||
==================
|
||||
*/
|
||||
void Sym_Shutdown() {
|
||||
module_t *m;
|
||||
symbol_t *s;
|
||||
|
||||
for ( m = modules; m != NULL; m = modules ) {
|
||||
modules = m->next;
|
||||
for ( s = m->symbols; s != NULL; s = m->symbols ) {
|
||||
m->symbols = s->next;
|
||||
free( s->name );
|
||||
free( s );
|
||||
}
|
||||
free( m->name );
|
||||
free( m );
|
||||
}
|
||||
modules = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sym_GetFuncInfo
|
||||
==================
|
||||
*/
|
||||
void Sym_GetFuncInfo( long addr, idStr &module, idStr &funcName ) {
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
module_t *m;
|
||||
symbol_t *s;
|
||||
|
||||
VirtualQuery( (void*)addr, &mbi, sizeof(mbi) );
|
||||
|
||||
for ( m = modules; m != NULL; m = m->next ) {
|
||||
if ( m->address == (int) mbi.AllocationBase ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !m ) {
|
||||
Sym_Init( addr );
|
||||
m = modules;
|
||||
}
|
||||
|
||||
for ( s = m->symbols; s != NULL; s = s->next ) {
|
||||
if ( s->address == addr ) {
|
||||
|
||||
char undName[MAX_STRING_CHARS];
|
||||
if ( UnDecorateSymbolName( s->name, undName, sizeof(undName), UNDECORATE_FLAGS ) ) {
|
||||
funcName = undName;
|
||||
} else {
|
||||
funcName = s->name;
|
||||
}
|
||||
for ( int i = 0; i < funcName.Length(); i++ ) {
|
||||
if ( funcName[i] == '(' ) {
|
||||
funcName.CapLength( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
module = m->name;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf( funcName, "0x%08x", addr );
|
||||
module = "";
|
||||
}
|
||||
|
||||
#elif defined(_DEBUG)
|
||||
|
||||
DWORD lastAllocationBase = -1;
|
||||
HANDLE processHandle;
|
||||
idStr lastModule;
|
||||
|
||||
/*
|
||||
==================
|
||||
Sym_Init
|
||||
==================
|
||||
*/
|
||||
void Sym_Init( long addr ) {
|
||||
TCHAR moduleName[MAX_STRING_CHARS];
|
||||
TCHAR modShortNameBuf[MAX_STRING_CHARS];
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
|
||||
if ( lastAllocationBase != -1 ) {
|
||||
Sym_Shutdown();
|
||||
}
|
||||
|
||||
VirtualQuery( (void*)addr, &mbi, sizeof(mbi) );
|
||||
|
||||
GetModuleFileName( (HMODULE)mbi.AllocationBase, moduleName, sizeof( moduleName ) );
|
||||
_splitpath( moduleName, NULL, NULL, modShortNameBuf, NULL );
|
||||
lastModule = modShortNameBuf;
|
||||
|
||||
processHandle = GetCurrentProcess();
|
||||
if ( !SymInitialize( processHandle, NULL, FALSE ) ) {
|
||||
return;
|
||||
}
|
||||
if ( !SymLoadModule( processHandle, NULL, moduleName, NULL, (DWORD)mbi.AllocationBase, 0 ) ) {
|
||||
SymCleanup( processHandle );
|
||||
return;
|
||||
}
|
||||
|
||||
SymSetOptions( SymGetOptions() & ~SYMOPT_UNDNAME );
|
||||
|
||||
lastAllocationBase = (DWORD) mbi.AllocationBase;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sym_Shutdown
|
||||
==================
|
||||
*/
|
||||
void Sym_Shutdown() {
|
||||
SymUnloadModule( GetCurrentProcess(), lastAllocationBase );
|
||||
SymCleanup( GetCurrentProcess() );
|
||||
lastAllocationBase = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sym_GetFuncInfo
|
||||
==================
|
||||
*/
|
||||
void Sym_GetFuncInfo( long addr, idStr &module, idStr &funcName ) {
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
|
||||
VirtualQuery( (void*)addr, &mbi, sizeof(mbi) );
|
||||
|
||||
if ( (DWORD) mbi.AllocationBase != lastAllocationBase ) {
|
||||
Sym_Init( addr );
|
||||
}
|
||||
|
||||
BYTE symbolBuffer[ sizeof(IMAGEHLP_SYMBOL) + MAX_STRING_CHARS ];
|
||||
PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)&symbolBuffer[0];
|
||||
pSymbol->SizeOfStruct = sizeof(symbolBuffer);
|
||||
pSymbol->MaxNameLength = 1023;
|
||||
pSymbol->Address = 0;
|
||||
pSymbol->Flags = 0;
|
||||
pSymbol->Size =0;
|
||||
|
||||
DWORD symDisplacement = 0;
|
||||
if ( SymGetSymFromAddr( processHandle, addr, &symDisplacement, pSymbol ) ) {
|
||||
// clean up name, throwing away decorations that don't affect uniqueness
|
||||
char undName[MAX_STRING_CHARS];
|
||||
if ( UnDecorateSymbolName( pSymbol->Name, undName, sizeof(undName), UNDECORATE_FLAGS ) ) {
|
||||
funcName = undName;
|
||||
} else {
|
||||
funcName = pSymbol->Name;
|
||||
}
|
||||
module = lastModule;
|
||||
}
|
||||
else {
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
LocalFree( lpMsgBuf );
|
||||
|
||||
// Couldn't retrieve symbol (no debug info?, can't load dbghelp.dll?)
|
||||
sprintf( funcName, "0x%08x", addr );
|
||||
module = "";
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
==================
|
||||
Sym_Init
|
||||
==================
|
||||
*/
|
||||
void Sym_Init( long addr ) {
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sym_Shutdown
|
||||
==================
|
||||
*/
|
||||
void Sym_Shutdown() {
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sym_GetFuncInfo
|
||||
==================
|
||||
*/
|
||||
void Sym_GetFuncInfo( long addr, idStr &module, idStr &funcName ) {
|
||||
module = "";
|
||||
sprintf( funcName, "0x%08x", addr );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
==================
|
||||
GetFuncAddr
|
||||
==================
|
||||
*/
|
||||
address_t GetFuncAddr( address_t midPtPtr ) {
|
||||
long temp;
|
||||
do {
|
||||
temp = (long)(*(long*)midPtPtr);
|
||||
if ( (temp&0x00FFFFFF) == PROLOGUE_SIGNATURE ) {
|
||||
break;
|
||||
}
|
||||
midPtPtr--;
|
||||
} while(true);
|
||||
|
||||
return midPtPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
GetCallerAddr
|
||||
==================
|
||||
*/
|
||||
address_t GetCallerAddr( long _ebp ) {
|
||||
long midPtPtr;
|
||||
long res = 0;
|
||||
|
||||
__asm {
|
||||
mov eax, _ebp
|
||||
mov ecx, [eax] // check for end of stack frames list
|
||||
test ecx, ecx // check for zero stack frame
|
||||
jz label
|
||||
mov eax, [eax+4] // get the ret address
|
||||
test eax, eax // check for zero return address
|
||||
jz label
|
||||
mov midPtPtr, eax
|
||||
}
|
||||
res = GetFuncAddr( midPtPtr );
|
||||
label:
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_GetCallStack
|
||||
|
||||
use /Oy option
|
||||
==================
|
||||
*/
|
||||
void Sys_GetCallStack( address_t *callStack, const int callStackSize ) {
|
||||
#if 1 //def _DEBUG
|
||||
int i;
|
||||
long m_ebp;
|
||||
|
||||
__asm {
|
||||
mov eax, ebp
|
||||
mov m_ebp, eax
|
||||
}
|
||||
// skip last two functions
|
||||
m_ebp = *((long*)m_ebp);
|
||||
m_ebp = *((long*)m_ebp);
|
||||
// list functions
|
||||
for ( i = 0; i < callStackSize; i++ ) {
|
||||
callStack[i] = GetCallerAddr( m_ebp );
|
||||
if ( callStack[i] == 0 ) {
|
||||
break;
|
||||
}
|
||||
m_ebp = *((long*)m_ebp);
|
||||
}
|
||||
#else
|
||||
int i = 0;
|
||||
#endif
|
||||
while( i < callStackSize ) {
|
||||
callStack[i++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_GetCallStackStr
|
||||
==================
|
||||
*/
|
||||
const char *Sys_GetCallStackStr( const address_t *callStack, const int callStackSize ) {
|
||||
static char string[MAX_STRING_CHARS*2];
|
||||
int index, i;
|
||||
idStr module, funcName;
|
||||
|
||||
index = 0;
|
||||
for ( i = callStackSize-1; i >= 0; i-- ) {
|
||||
Sym_GetFuncInfo( callStack[i], module, funcName );
|
||||
index += sprintf( string+index, " -> %s", funcName.c_str() );
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_GetCallStackCurStr
|
||||
==================
|
||||
*/
|
||||
const char *Sys_GetCallStackCurStr( int depth ) {
|
||||
address_t *callStack;
|
||||
|
||||
callStack = (address_t *) _alloca( depth * sizeof( address_t ) );
|
||||
Sys_GetCallStack( callStack, depth );
|
||||
return Sys_GetCallStackStr( callStack, depth );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_GetCallStackCurAddressStr
|
||||
==================
|
||||
*/
|
||||
const char *Sys_GetCallStackCurAddressStr( int depth ) {
|
||||
static char string[MAX_STRING_CHARS*2];
|
||||
address_t *callStack;
|
||||
int index, i;
|
||||
|
||||
callStack = (address_t *) _alloca( depth * sizeof( address_t ) );
|
||||
Sys_GetCallStack( callStack, depth );
|
||||
|
||||
index = 0;
|
||||
for ( i = depth-1; i >= 0; i-- ) {
|
||||
index += sprintf( string+index, " -> 0x%08x", callStack[i] );
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_ShutdownSymbols
|
||||
==================
|
||||
*/
|
||||
void Sys_ShutdownSymbols() {
|
||||
Sym_Shutdown();
|
||||
}
|
||||
146
neo/sys/win32/win_signin.cpp
Normal file
146
neo/sys/win32/win_signin.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
#include "../../framework/PlayerProfile.h"
|
||||
#include "../sys_session_local.h"
|
||||
#include "win_signin.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
idCVar win_userPersistent( "win_userPersistent", "1", CVAR_BOOL, "debugging cvar for profile persistence status" );
|
||||
idCVar win_userOnline( "win_userOnline", "1", CVAR_BOOL, "debugging cvar for profile online status" );
|
||||
idCVar win_isInParty( "win_isInParty", "0", CVAR_BOOL, "debugging cvar for platform party status" );
|
||||
idCVar win_partyCount( "win_partyCount", "0", CVAR_INTEGER, "debugginc var for platform party count" );
|
||||
#endif
|
||||
|
||||
/*
|
||||
========================
|
||||
idSignInManagerWin::Shutdown
|
||||
========================
|
||||
*/
|
||||
void idSignInManagerWin::Shutdown() {
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSignInManagerWin::Pump
|
||||
========================
|
||||
*/
|
||||
void idSignInManagerWin::Pump() {
|
||||
|
||||
// If we have more users than we need, then set to the lower amount
|
||||
// (don't remove the master user though)
|
||||
if ( localUsers.Num() > 1 && localUsers.Num() > maxDesiredLocalUsers ) {
|
||||
localUsers.SetNum( maxDesiredLocalUsers );
|
||||
}
|
||||
|
||||
#ifndef ID_RETAIL
|
||||
// If we don't have enough, then make sure we do
|
||||
// NOTE - We always want at least one user on windows for now,
|
||||
// and this master user will always use controller 0
|
||||
while ( localUsers.Num() < minDesiredLocalUsers ) {
|
||||
RegisterLocalUser( localUsers.Num() );
|
||||
}
|
||||
#endif
|
||||
|
||||
// See if we need to save settings on any of the profiles
|
||||
for ( int i = 0; i < localUsers.Num(); i++ ) {
|
||||
localUsers[i].Pump();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSignInManagerWin::RemoveLocalUserByIndex
|
||||
========================
|
||||
*/
|
||||
void idSignInManagerWin::RemoveLocalUserByIndex( int index ) {
|
||||
session->OnLocalUserSignout( &localUsers[index] );
|
||||
localUsers.RemoveIndex( index );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSignInManagerWin::RegisterLocalUser
|
||||
========================
|
||||
*/
|
||||
void idSignInManagerWin::RegisterLocalUser( int inputDevice ) {
|
||||
if ( GetLocalUserByInputDevice( inputDevice ) != NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
static char machineName[128];
|
||||
DWORD len = 128;
|
||||
::GetComputerName( machineName, &len );
|
||||
|
||||
const char * nameSource = machineName;
|
||||
|
||||
idStr name( nameSource );
|
||||
int nameLength = name.Length();
|
||||
if ( idStr::IsValidUTF8( nameSource, nameLength ) ) {
|
||||
int nameIndex = 0;
|
||||
int numChars = 0;
|
||||
name.Empty();
|
||||
while ( nameIndex < nameLength && numChars++ < idLocalUserWin::MAX_GAMERTAG_CHARS ) {
|
||||
uint32 c = idStr::UTF8Char( nameSource, nameIndex );
|
||||
name.AppendUTF8Char( c );
|
||||
}
|
||||
}
|
||||
|
||||
idLocalUserWin & localUser = *localUsers.Alloc();
|
||||
|
||||
localUser.Init( inputDevice, name.c_str(), localUsers.Num() );
|
||||
localUser.SetLocalUserHandle( GetUniqueLocalUserHandle( localUser.GetGamerTag() ) );
|
||||
|
||||
session->OnLocalUserSignin( &localUser );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idSignInManagerWin::CreateNewUser
|
||||
========================
|
||||
*/
|
||||
bool idSignInManagerWin::CreateNewUser( winUserState_t & state ) {
|
||||
//idScopedGlobalHeap everythingHereGoesInTheGlobalHeap; // users obviously persist across maps
|
||||
|
||||
RemoveAllLocalUsers();
|
||||
RegisterLocalUser( state.inputDevice );
|
||||
|
||||
if ( localUsers.Num() > 0 ) {
|
||||
if ( !localUsers[0].VerifyUserState( state ) ) {
|
||||
RemoveAllLocalUsers();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CONSOLE_COMMAND( testRemoveAllLocalUsers, "Forces removal of local users - mainly for PC testing", NULL ) {
|
||||
session->GetSignInManager().RemoveAllLocalUsers();
|
||||
}
|
||||
62
neo/sys/win32/win_signin.h
Normal file
62
neo/sys/win32/win_signin.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef __WIN_SIGNIN_H__
|
||||
#define __WIN_SIGNIN_H__
|
||||
|
||||
#include "win_localuser.h"
|
||||
|
||||
/*
|
||||
================================================
|
||||
idSignInManagerWin
|
||||
================================================
|
||||
*/
|
||||
class idSignInManagerWin : public idSignInManagerBase {
|
||||
public:
|
||||
|
||||
idSignInManagerWin() : dlcVersionChecked( false ) {}
|
||||
virtual ~idSignInManagerWin() {}
|
||||
|
||||
//==========================================================================================
|
||||
// idSignInManagerBase interface
|
||||
//==========================================================================================
|
||||
virtual void Pump();
|
||||
virtual void Shutdown();
|
||||
virtual int GetNumLocalUsers() const { return localUsers.Num(); }
|
||||
virtual idLocalUser * GetLocalUserByIndex( int index ) { return &localUsers[index]; }
|
||||
virtual const idLocalUser * GetLocalUserByIndex( int index ) const { return &localUsers[index]; }
|
||||
virtual void RemoveLocalUserByIndex( int index );
|
||||
virtual void RegisterLocalUser( int inputDevice ); // Register a local user to the passed in controller
|
||||
|
||||
bool CreateNewUser( winUserState_t & state );
|
||||
|
||||
private:
|
||||
idStaticList< idLocalUserWin, MAX_INPUT_DEVICES > localUsers;
|
||||
bool dlcVersionChecked;
|
||||
};
|
||||
|
||||
#endif
|
||||
37
neo/sys/win32/win_snd.cpp
Normal file
37
neo/sys/win32/win_snd.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
|
||||
// DirectX SDK
|
||||
#include <DxErr.h>
|
||||
|
||||
#include <ks.h>
|
||||
#include <ksmedia.h>
|
||||
#include "../../sound/snd_local.h"
|
||||
#include "win_local.h"
|
||||
29
neo/sys/win32/win_stats.cpp
Normal file
29
neo/sys/win32/win_stats.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#pragma hdrstop
|
||||
#include "../../framework/precompiled.h"
|
||||
32
neo/sys/win32/win_stats.h
Normal file
32
neo/sys/win32/win_stats.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef __WIN_STATS_H__
|
||||
#define __WIN_STATS_H__
|
||||
|
||||
|
||||
#endif // !__WIN_STATS_H__
|
||||
553
neo/sys/win32/win_syscon.cpp
Normal file
553
neo/sys/win32/win_syscon.cpp
Normal file
@@ -0,0 +1,553 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <conio.h>
|
||||
|
||||
#include "win_local.h"
|
||||
#include "rc/doom_resource.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
|
||||
|
||||
#define COMMAND_HISTORY 64
|
||||
|
||||
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];
|
||||
bool quitOnClose;
|
||||
int windowWidth, windowHeight;
|
||||
|
||||
WNDPROC SysInputLineWndProc;
|
||||
|
||||
idEditField historyEditLines[COMMAND_HISTORY];
|
||||
|
||||
int nextHistoryLine;// the last line in the history buffer, not masked
|
||||
int historyLine; // the line being displayed from history buffer
|
||||
// will be <= nextHistoryLine
|
||||
|
||||
idEditField consoleField;
|
||||
|
||||
} WinConData;
|
||||
|
||||
static WinConData s_wcd;
|
||||
|
||||
static LONG WINAPI ConWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
char *cmdString;
|
||||
static bool s_timePolarity;
|
||||
|
||||
switch (uMsg) {
|
||||
case WM_ACTIVATE:
|
||||
if ( LOWORD( wParam ) != WA_INACTIVE ) {
|
||||
SetFocus( s_wcd.hwndInputLine );
|
||||
}
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
if ( s_wcd.quitOnClose ) {
|
||||
PostQuitMessage( 0 );
|
||||
} else {
|
||||
Sys_ShowConsole( 0, false );
|
||||
win32.win_viewlog.SetBool( false );
|
||||
}
|
||||
return 0;
|
||||
case WM_CTLCOLORSTATIC:
|
||||
if ( ( HWND ) lParam == s_wcd.hwndBuffer ) {
|
||||
SetBkColor( ( HDC ) wParam, RGB( 0x00, 0x00, 0x80 ) );
|
||||
SetTextColor( ( HDC ) wParam, RGB( 0xff, 0xff, 0x00 ) );
|
||||
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, 0x0, 0x00 ) );
|
||||
} else {
|
||||
SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
|
||||
SetTextColor( ( HDC ) wParam, RGB( 0x00, 0x0, 0x00 ) );
|
||||
}
|
||||
return ( long ) s_wcd.hbrErrorBackground;
|
||||
}
|
||||
break;
|
||||
case WM_SYSCOMMAND:
|
||||
if ( wParam == SC_CLOSE ) {
|
||||
PostQuitMessage( 0 );
|
||||
}
|
||||
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 = Mem_CopyString( "quit" );
|
||||
Sys_QueEvent( SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString, 0 );
|
||||
}
|
||||
} 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, 0x80 ) );
|
||||
s_wcd.hbrErrorBackground = CreateSolidBrush( RGB( 0x80, 0x80, 0x80 ) );
|
||||
SetTimer( hWnd, 1, 1000, NULL );
|
||||
break;
|
||||
/*
|
||||
case WM_ERASEBKGND:
|
||||
HGDIOBJ oldObject;
|
||||
HDC hdcScaled;
|
||||
hdcScaled = CreateCompatibleDC( ( HDC ) wParam );
|
||||
assert( hdcScaled != 0 );
|
||||
if ( hdcScaled ) {
|
||||
oldObject = SelectObject( ( HDC ) hdcScaled, s_wcd.hbmLogo );
|
||||
assert( oldObject != 0 );
|
||||
if ( oldObject )
|
||||
{
|
||||
StretchBlt( ( HDC ) wParam, 0, 0, s_wcd.windowWidth, s_wcd.windowHeight,
|
||||
hdcScaled, 0, 0, 512, 384,
|
||||
SRCCOPY );
|
||||
}
|
||||
DeleteDC( hdcScaled );
|
||||
hdcScaled = 0;
|
||||
}
|
||||
return 1;
|
||||
*/
|
||||
case WM_TIMER:
|
||||
if ( wParam == 1 ) {
|
||||
s_timePolarity = (bool)!s_timePolarity;
|
||||
if ( s_wcd.hwndErrorBox ) {
|
||||
InvalidateRect( s_wcd.hwndErrorBox, NULL, FALSE );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||||
}
|
||||
|
||||
LONG WINAPI InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
int key, cursor;
|
||||
switch ( uMsg ) {
|
||||
case WM_KILLFOCUS:
|
||||
if ( ( HWND ) wParam == s_wcd.hWnd || ( HWND ) wParam == s_wcd.hwndErrorBox ) {
|
||||
SetFocus( hWnd );
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
key = ( ( lParam >> 16 ) & 0xFF ) | ( ( ( lParam >> 24 ) & 1 ) << 7 );
|
||||
|
||||
// command history
|
||||
if ( ( key == K_UPARROW ) || ( key == K_KP_8 ) ) {
|
||||
if ( s_wcd.nextHistoryLine - s_wcd.historyLine < COMMAND_HISTORY && s_wcd.historyLine > 0 ) {
|
||||
s_wcd.historyLine--;
|
||||
}
|
||||
s_wcd.consoleField = s_wcd.historyEditLines[ s_wcd.historyLine % COMMAND_HISTORY ];
|
||||
|
||||
SetWindowText( s_wcd.hwndInputLine, s_wcd.consoleField.GetBuffer() );
|
||||
SendMessage( s_wcd.hwndInputLine, EM_SETSEL, s_wcd.consoleField.GetCursor(), s_wcd.consoleField.GetCursor() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( ( key == K_DOWNARROW ) || ( key == K_KP_2 ) ) {
|
||||
if ( s_wcd.historyLine == s_wcd.nextHistoryLine ) {
|
||||
return 0;
|
||||
}
|
||||
s_wcd.historyLine++;
|
||||
s_wcd.consoleField = s_wcd.historyEditLines[ s_wcd.historyLine % COMMAND_HISTORY ];
|
||||
|
||||
SetWindowText( s_wcd.hwndInputLine, s_wcd.consoleField.GetBuffer() );
|
||||
SendMessage( s_wcd.hwndInputLine, EM_SETSEL, s_wcd.consoleField.GetCursor(), s_wcd.consoleField.GetCursor() );
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CHAR:
|
||||
key = ( ( lParam >> 16 ) & 0xFF ) | ( ( ( lParam >> 24 ) & 1 ) << 7 );
|
||||
|
||||
GetWindowText( s_wcd.hwndInputLine, s_wcd.consoleField.GetBuffer(), MAX_EDIT_LINE );
|
||||
SendMessage( s_wcd.hwndInputLine, EM_GETSEL, (WPARAM) NULL, (LPARAM) &cursor );
|
||||
s_wcd.consoleField.SetCursor( cursor );
|
||||
|
||||
// enter the line
|
||||
if ( key == K_ENTER || key == K_KP_ENTER ) {
|
||||
strncat( s_wcd.consoleText, s_wcd.consoleField.GetBuffer(), sizeof( s_wcd.consoleText ) - strlen( s_wcd.consoleText ) - 5 );
|
||||
strcat( s_wcd.consoleText, "\n" );
|
||||
SetWindowText( s_wcd.hwndInputLine, "" );
|
||||
|
||||
Sys_Printf( "]%s\n", s_wcd.consoleField.GetBuffer() );
|
||||
|
||||
// copy line to history buffer
|
||||
s_wcd.historyEditLines[s_wcd.nextHistoryLine % COMMAND_HISTORY] = s_wcd.consoleField;
|
||||
s_wcd.nextHistoryLine++;
|
||||
s_wcd.historyLine = s_wcd.nextHistoryLine;
|
||||
|
||||
s_wcd.consoleField.Clear();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// command completion
|
||||
if ( key == K_TAB ) {
|
||||
s_wcd.consoleField.AutoComplete();
|
||||
|
||||
SetWindowText( s_wcd.hwndInputLine, s_wcd.consoleField.GetBuffer() );
|
||||
//s_wcd.consoleField.SetWidthInChars( strlen( s_wcd.consoleField.GetBuffer() ) );
|
||||
SendMessage( s_wcd.hwndInputLine, EM_SETSEL, s_wcd.consoleField.GetCursor(), s_wcd.consoleField.GetCursor() );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clear autocompletion buffer on normal key input
|
||||
if ( ( key >= K_SPACE && key <= K_BACKSPACE ) ||
|
||||
( key >= K_KP_SLASH && key <= K_KP_PLUS ) || ( key >= K_KP_STAR && key <= K_KP_EQUALS ) ) {
|
||||
s_wcd.consoleField.ClearAutoComplete();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CallWindowProc( s_wcd.SysInputLineWndProc, hWnd, uMsg, wParam, lParam );
|
||||
}
|
||||
|
||||
/*
|
||||
** Sys_CreateConsole
|
||||
*/
|
||||
void Sys_CreateConsole() {
|
||||
HDC hDC;
|
||||
WNDCLASS wc;
|
||||
RECT rect;
|
||||
const char *DEDCLASS = WIN32_CONSOLE_CLASS;
|
||||
int nHeight;
|
||||
int swidth, sheight;
|
||||
int DEDSTYLE = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX;
|
||||
int i;
|
||||
|
||||
memset( &wc, 0, sizeof( wc ) );
|
||||
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = (WNDPROC) ConWndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = win32.hInstance;
|
||||
wc.hIcon = LoadIcon( win32.hInstance, MAKEINTRESOURCE(IDI_ICON1));
|
||||
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
|
||||
wc.hbrBackground = (struct HBRUSH__ *)COLOR_WINDOW;
|
||||
wc.lpszMenuName = 0;
|
||||
wc.lpszClassName = DEDCLASS;
|
||||
|
||||
if ( !RegisterClass (&wc) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
rect.left = 0;
|
||||
rect.right = 540;
|
||||
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.hbmLogo = LoadBitmap( win32.hInstance, MAKEINTRESOURCE( IDB_BITMAP_LOGO) );
|
||||
|
||||
s_wcd.hWnd = CreateWindowEx( 0,
|
||||
DEDCLASS,
|
||||
GAME_NAME,
|
||||
DEDSTYLE,
|
||||
( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1,
|
||||
NULL,
|
||||
NULL,
|
||||
win32.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,
|
||||
6, 400, 528, 20,
|
||||
s_wcd.hWnd,
|
||||
( HMENU ) INPUT_ID, // child window ID
|
||||
win32.hInstance, NULL );
|
||||
|
||||
//
|
||||
// create the buttons
|
||||
//
|
||||
s_wcd.hwndButtonCopy = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
|
||||
5, 425, 72, 24,
|
||||
s_wcd.hWnd,
|
||||
( HMENU ) COPY_ID, // child window ID
|
||||
win32.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,
|
||||
82, 425, 72, 24,
|
||||
s_wcd.hWnd,
|
||||
( HMENU ) CLEAR_ID, // child window ID
|
||||
win32.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,
|
||||
462, 425, 72, 24,
|
||||
s_wcd.hWnd,
|
||||
( HMENU ) QUIT_ID, // child window ID
|
||||
win32.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,
|
||||
6, 40, 526, 354,
|
||||
s_wcd.hWnd,
|
||||
( HMENU ) EDIT_ID, // child window ID
|
||||
win32.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 );
|
||||
|
||||
// don't show it now that we have a splash screen up
|
||||
if ( win32.win_viewlog.GetBool() ) {
|
||||
ShowWindow( s_wcd.hWnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow( s_wcd.hWnd );
|
||||
SetForegroundWindow( s_wcd.hWnd );
|
||||
SetFocus( s_wcd.hwndInputLine );
|
||||
}
|
||||
|
||||
|
||||
|
||||
s_wcd.consoleField.Clear();
|
||||
|
||||
for ( i = 0 ; i < COMMAND_HISTORY ; i++ ) {
|
||||
s_wcd.historyEditLines[i].Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Sys_DestroyConsole
|
||||
*/
|
||||
void Sys_DestroyConsole() {
|
||||
if ( s_wcd.hWnd ) {
|
||||
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, bool quitOnClose ) {
|
||||
|
||||
s_wcd.quitOnClose = quitOnClose;
|
||||
|
||||
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() {
|
||||
|
||||
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
|
||||
|
||||
char buffer[CONSOLE_BUFFER_SIZE*2];
|
||||
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 ( idStr::IsColor( &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 > 0x7000 ) {
|
||||
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 );
|
||||
}
|
||||
|
||||
/*
|
||||
** Win_SetErrorText
|
||||
*/
|
||||
void Win_SetErrorText( const char *buf ) {
|
||||
idStr::Copynz( 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, 526, 30,
|
||||
s_wcd.hWnd,
|
||||
( HMENU ) ERRORBOX_ID, // child window ID
|
||||
win32.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;
|
||||
}
|
||||
}
|
||||
142
neo/sys/win32/win_taskkeyhook.cpp
Normal file
142
neo/sys/win32/win_taskkeyhook.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
|
||||
//
|
||||
// This file implements the low-level keyboard hook that traps the task keys.
|
||||
//
|
||||
#include "win_local.h"
|
||||
|
||||
#define DLLEXPORT __declspec(dllexport)
|
||||
|
||||
// Magic registry key/value for "Remove Task Manager" policy.
|
||||
LPCTSTR KEY_DisableTaskMgr = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
|
||||
LPCTSTR VAL_DisableTaskMgr = "DisableTaskMgr";
|
||||
|
||||
// The section is SHARED among all instances of this DLL.
|
||||
// A low-level keyboard hook is always a system-wide hook.
|
||||
#pragma data_seg (".mydata")
|
||||
HHOOK g_hHookKbdLL = NULL; // hook handle
|
||||
BOOL g_bBeep = FALSE; // beep on illegal key
|
||||
#pragma data_seg ()
|
||||
#pragma comment(linker, "/SECTION:.mydata,RWS") // tell linker: make it shared
|
||||
|
||||
/*
|
||||
================
|
||||
MyTaskKeyHookLL
|
||||
|
||||
Low-level keyboard hook:
|
||||
Trap task-switching keys by returning without passing along.
|
||||
================
|
||||
*/
|
||||
LRESULT CALLBACK MyTaskKeyHookLL( int nCode, WPARAM wp, LPARAM lp ) {
|
||||
KBDLLHOOKSTRUCT *pkh = (KBDLLHOOKSTRUCT *) lp;
|
||||
|
||||
if ( nCode == HC_ACTION ) {
|
||||
BOOL bCtrlKeyDown = GetAsyncKeyState( VK_CONTROL)>>((sizeof(SHORT) * 8) - 1 );
|
||||
|
||||
if ( ( pkh->vkCode == VK_ESCAPE && bCtrlKeyDown ) // Ctrl+Esc
|
||||
|| ( pkh->vkCode == VK_TAB && pkh->flags & LLKHF_ALTDOWN ) // Alt+TAB
|
||||
|| ( pkh->vkCode == VK_ESCAPE && pkh->flags & LLKHF_ALTDOWN ) // Alt+Esc
|
||||
|| ( pkh->vkCode == VK_LWIN || pkh->vkCode == VK_RWIN ) // Start Menu
|
||||
) {
|
||||
|
||||
if ( g_bBeep && ( wp == WM_SYSKEYDOWN || wp == WM_KEYDOWN ) ) {
|
||||
MessageBeep( 0 ); // beep on downstroke if requested
|
||||
}
|
||||
return 1; // return without processing the key strokes
|
||||
}
|
||||
}
|
||||
return CallNextHookEx( g_hHookKbdLL, nCode, wp, lp );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
AreTaskKeysDisabled
|
||||
|
||||
Are task keys disabled--ie, is hook installed?
|
||||
Note: This assumes there's no other hook that does the same thing!
|
||||
================
|
||||
*/
|
||||
BOOL AreTaskKeysDisabled() {
|
||||
return g_hHookKbdLL != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
IsTaskMgrDisabled
|
||||
================
|
||||
*/
|
||||
BOOL IsTaskMgrDisabled() {
|
||||
HKEY hk;
|
||||
|
||||
if ( RegOpenKey( HKEY_CURRENT_USER, KEY_DisableTaskMgr, &hk ) != ERROR_SUCCESS ) {
|
||||
return FALSE; // no key ==> not disabled
|
||||
}
|
||||
|
||||
DWORD val = 0;
|
||||
DWORD len = 4;
|
||||
return RegQueryValueEx( hk, VAL_DisableTaskMgr, NULL, NULL, (BYTE*)&val, &len ) == ERROR_SUCCESS && val == 1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DisableTaskKeys
|
||||
================
|
||||
*/
|
||||
void DisableTaskKeys( BOOL bDisable, BOOL bBeep, BOOL bTaskMgr ) {
|
||||
|
||||
// task keys (Ctrl+Esc, Alt-Tab, etc.)
|
||||
if ( bDisable ) {
|
||||
if ( !g_hHookKbdLL ) {
|
||||
g_hHookKbdLL = SetWindowsHookEx( WH_KEYBOARD_LL, MyTaskKeyHookLL, win32.hInstance, 0 );
|
||||
}
|
||||
} else if ( g_hHookKbdLL != NULL ) {
|
||||
UnhookWindowsHookEx( g_hHookKbdLL );
|
||||
g_hHookKbdLL = NULL;
|
||||
}
|
||||
g_bBeep = bBeep;
|
||||
|
||||
// task manager (Ctrl+Alt+Del)
|
||||
if ( bTaskMgr ) {
|
||||
HKEY hk;
|
||||
if ( RegOpenKey( HKEY_CURRENT_USER, KEY_DisableTaskMgr, &hk ) != ERROR_SUCCESS ) {
|
||||
RegCreateKey( HKEY_CURRENT_USER, KEY_DisableTaskMgr, &hk );
|
||||
}
|
||||
if ( bDisable ) {
|
||||
// disable TM: set policy = 1
|
||||
DWORD val = 1;
|
||||
RegSetValueEx( hk, VAL_DisableTaskMgr, NULL, REG_DWORD, (BYTE*)&val, sizeof(val) );
|
||||
} else {
|
||||
// enable TM: remove policy
|
||||
RegDeleteValue( hk,VAL_DisableTaskMgr );
|
||||
}
|
||||
}
|
||||
}
|
||||
429
neo/sys/win32/win_wndproc.cpp
Normal file
429
neo/sys/win32/win_wndproc.cpp
Normal file
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#pragma hdrstop
|
||||
#include "../../idlib/precompiled.h"
|
||||
|
||||
#include "win_local.h"
|
||||
#include "../../renderer/tr_local.h"
|
||||
|
||||
#include <Windowsx.h>
|
||||
|
||||
LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
static bool s_alttab_disabled;
|
||||
|
||||
extern idCVar r_windowX;
|
||||
extern idCVar r_windowY;
|
||||
extern idCVar r_windowWidth;
|
||||
extern idCVar r_windowHeight;
|
||||
|
||||
static void WIN_DisableAltTab() {
|
||||
if ( s_alttab_disabled || win32.win_allowAltTab.GetBool() ) {
|
||||
return;
|
||||
}
|
||||
if ( !idStr::Icmp( cvarSystem->GetCVarString( "sys_arch" ), "winnt" ) ) {
|
||||
RegisterHotKey( 0, 0, MOD_ALT, VK_TAB );
|
||||
} else {
|
||||
BOOL old;
|
||||
|
||||
SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, &old, 0 );
|
||||
}
|
||||
s_alttab_disabled = true;
|
||||
}
|
||||
|
||||
static void WIN_EnableAltTab() {
|
||||
if ( !s_alttab_disabled || win32.win_allowAltTab.GetBool() ) {
|
||||
return;
|
||||
}
|
||||
if ( !idStr::Icmp( cvarSystem->GetCVarString( "sys_arch" ), "winnt" ) ) {
|
||||
UnregisterHotKey( 0, 0 );
|
||||
} else {
|
||||
BOOL old;
|
||||
|
||||
SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, &old, 0 );
|
||||
}
|
||||
|
||||
s_alttab_disabled = false;
|
||||
}
|
||||
|
||||
void WIN_Sizing(WORD side, RECT *rect)
|
||||
{
|
||||
if ( !R_IsInitialized() || renderSystem->GetWidth() <= 0 || renderSystem->GetHeight() <= 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// restrict to a standard aspect ratio
|
||||
int width = rect->right - rect->left;
|
||||
int height = rect->bottom - rect->top;
|
||||
|
||||
// Adjust width/height for window decoration
|
||||
RECT decoRect = { 0, 0, 0, 0 };
|
||||
AdjustWindowRect( &decoRect, WINDOW_STYLE|WS_SYSMENU, FALSE );
|
||||
int decoWidth = decoRect.right - decoRect.left;
|
||||
int decoHeight = decoRect.bottom - decoRect.top;
|
||||
|
||||
width -= decoWidth;
|
||||
height -= decoHeight;
|
||||
|
||||
// Clamp to a minimum size
|
||||
if ( width < SCREEN_WIDTH / 4 ) {
|
||||
width = SCREEN_WIDTH / 4;
|
||||
}
|
||||
if ( height < SCREEN_HEIGHT / 4 ) {
|
||||
height = SCREEN_HEIGHT / 4;
|
||||
}
|
||||
|
||||
const int minWidth = height * 4 / 3;
|
||||
const int maxHeight = width * 3 / 4;
|
||||
|
||||
const int maxWidth = height * 16 / 9;
|
||||
const int minHeight = width * 9 / 16;
|
||||
|
||||
// Set the new size
|
||||
switch ( side ) {
|
||||
case WMSZ_LEFT:
|
||||
rect->left = rect->right - width - decoWidth;
|
||||
rect->bottom = rect->top + idMath::ClampInt( minHeight, maxHeight, height ) + decoHeight;
|
||||
break;
|
||||
case WMSZ_RIGHT:
|
||||
rect->right = rect->left + width + decoWidth;
|
||||
rect->bottom = rect->top + idMath::ClampInt( minHeight, maxHeight, height ) + decoHeight;
|
||||
break;
|
||||
case WMSZ_BOTTOM:
|
||||
case WMSZ_BOTTOMRIGHT:
|
||||
rect->bottom = rect->top + height + decoHeight;
|
||||
rect->right = rect->left + idMath::ClampInt( minWidth, maxWidth, width ) + decoWidth;
|
||||
break;
|
||||
case WMSZ_TOP:
|
||||
case WMSZ_TOPRIGHT:
|
||||
rect->top = rect->bottom - height - decoHeight;
|
||||
rect->right = rect->left + idMath::ClampInt( minWidth, maxWidth, width ) + decoWidth;
|
||||
break;
|
||||
case WMSZ_BOTTOMLEFT:
|
||||
rect->bottom = rect->top + height + decoHeight;
|
||||
rect->left = rect->right - idMath::ClampInt( minWidth, maxWidth, width ) - decoWidth;
|
||||
break;
|
||||
case WMSZ_TOPLEFT:
|
||||
rect->top = rect->bottom - height - decoHeight;
|
||||
rect->left = rect->right - idMath::ClampInt( minWidth, maxWidth, width ) - decoWidth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
MainWndProc
|
||||
|
||||
main window procedure
|
||||
====================
|
||||
*/
|
||||
LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
|
||||
int key;
|
||||
switch( uMsg ) {
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
if (R_IsInitialized()) {
|
||||
RECT rect;
|
||||
if (::GetClientRect(win32.hWnd, &rect)) {
|
||||
|
||||
if ( rect.right > rect.left && rect.bottom > rect.top ) {
|
||||
glConfig.nativeScreenWidth = rect.right - rect.left;
|
||||
glConfig.nativeScreenHeight = rect.bottom - rect.top;
|
||||
|
||||
// save the window size in cvars if we aren't fullscreen
|
||||
int style = GetWindowLong( hWnd, GWL_STYLE );
|
||||
if ( ( style & WS_POPUP ) == 0 ) {
|
||||
r_windowWidth.SetInteger( glConfig.nativeScreenWidth );
|
||||
r_windowHeight.SetInteger( glConfig.nativeScreenHeight );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_MOVE: {
|
||||
int xPos, yPos;
|
||||
RECT r;
|
||||
|
||||
// save the window origin in cvars if we aren't fullscreen
|
||||
int style = GetWindowLong( hWnd, GWL_STYLE );
|
||||
if ( ( style & WS_POPUP ) == 0 ) {
|
||||
xPos = (short) LOWORD(lParam); // horizontal position
|
||||
yPos = (short) HIWORD(lParam); // vertical position
|
||||
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = 1;
|
||||
r.bottom = 1;
|
||||
|
||||
AdjustWindowRect( &r, style, FALSE );
|
||||
|
||||
r_windowX.SetInteger( xPos + r.left );
|
||||
r_windowY.SetInteger( yPos + r.top );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_CREATE:
|
||||
|
||||
win32.hWnd = hWnd;
|
||||
|
||||
if ( win32.cdsFullscreen ) {
|
||||
WIN_DisableAltTab();
|
||||
} else {
|
||||
WIN_EnableAltTab();
|
||||
}
|
||||
|
||||
// do the OpenGL setup
|
||||
void GLW_WM_CREATE( HWND hWnd );
|
||||
GLW_WM_CREATE( hWnd );
|
||||
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
// let sound and input know about this?
|
||||
win32.hWnd = NULL;
|
||||
if ( win32.cdsFullscreen ) {
|
||||
WIN_EnableAltTab();
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
soundSystem->SetMute( true );
|
||||
cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "quit\n" );
|
||||
break;
|
||||
|
||||
case WM_ACTIVATE:
|
||||
// if we got here because of an alt-tab or maximize,
|
||||
// we should activate immediately. If we are here because
|
||||
// the mouse was clicked on a title bar or drag control,
|
||||
// don't activate until the mouse button is released
|
||||
{
|
||||
int fActive, fMinimized;
|
||||
|
||||
fActive = LOWORD(wParam);
|
||||
fMinimized = (BOOL) HIWORD(wParam);
|
||||
|
||||
win32.activeApp = (fActive != WA_INACTIVE);
|
||||
if ( win32.activeApp ) {
|
||||
idKeyInput::ClearStates();
|
||||
Sys_GrabMouseCursor( true );
|
||||
if ( common->IsInitialized() ) {
|
||||
SetCursor( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
if ( fActive == WA_INACTIVE ) {
|
||||
win32.movingWindow = false;
|
||||
if ( common->IsInitialized() ) {
|
||||
SetCursor( LoadCursor( 0, IDC_ARROW ) );
|
||||
}
|
||||
}
|
||||
|
||||
// start playing the game sound world
|
||||
soundSystem->SetMute( !win32.activeApp );
|
||||
|
||||
// we do not actually grab or release the mouse here,
|
||||
// that will be done next time through the main loop
|
||||
}
|
||||
break;
|
||||
case WM_TIMER: {
|
||||
if ( win32.win_timerUpdate.GetBool() ) {
|
||||
common->Frame();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_SYSCOMMAND:
|
||||
if ( wParam == SC_SCREENSAVE || wParam == SC_KEYMENU ) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSKEYDOWN:
|
||||
if ( wParam == 13 ) { // alt-enter toggles full-screen
|
||||
cvarSystem->SetCVarBool( "r_fullscreen", !renderSystem->IsFullScreen() );
|
||||
cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "vid_restart\n" );
|
||||
return 0;
|
||||
}
|
||||
// fall through for other keys
|
||||
case WM_KEYDOWN:
|
||||
key = ( ( lParam >> 16 ) & 0xFF ) | ( ( ( lParam >> 24 ) & 1 ) << 7 );
|
||||
if ( key == K_LCTRL || key == K_LALT || key == K_RCTRL || key == K_RALT ) {
|
||||
// let direct-input handle this because windows sends Alt-Gr
|
||||
// as two events (ctrl then alt)
|
||||
break;
|
||||
}
|
||||
// D
|
||||
if ( key == K_NUMLOCK ) {
|
||||
key = K_PAUSE;
|
||||
} else if ( key == K_PAUSE ) {
|
||||
key = K_NUMLOCK;
|
||||
}
|
||||
Sys_QueEvent( SE_KEY, key, true, 0, NULL, 0 );
|
||||
break;
|
||||
|
||||
case WM_SYSKEYUP:
|
||||
case WM_KEYUP:
|
||||
key = ( ( lParam >> 16 ) & 0xFF ) | ( ( ( lParam >> 24 ) & 1 ) << 7 );
|
||||
if ( key == K_PRINTSCREEN ) {
|
||||
// don't queue printscreen keys. Since windows doesn't send us key
|
||||
// down events for this, we handle queueing them with DirectInput
|
||||
break;
|
||||
} else if ( key == K_LCTRL || key == K_LALT || key == K_RCTRL || key == K_RALT ) {
|
||||
// let direct-input handle this because windows sends Alt-Gr
|
||||
// as two events (ctrl then alt)
|
||||
break;
|
||||
}
|
||||
Sys_QueEvent( SE_KEY, key, false, 0, NULL, 0 );
|
||||
break;
|
||||
|
||||
case WM_CHAR:
|
||||
Sys_QueEvent( SE_CHAR, wParam, 0, 0, NULL, 0 );
|
||||
break;
|
||||
|
||||
case WM_NCLBUTTONDOWN:
|
||||
// win32.movingWindow = true;
|
||||
break;
|
||||
|
||||
case WM_ENTERSIZEMOVE:
|
||||
win32.movingWindow = true;
|
||||
break;
|
||||
|
||||
case WM_EXITSIZEMOVE:
|
||||
win32.movingWindow = false;
|
||||
break;
|
||||
|
||||
case WM_SIZING:
|
||||
WIN_Sizing(wParam, (RECT *)lParam);
|
||||
break;
|
||||
case WM_MOUSEMOVE: {
|
||||
if ( !common->IsInitialized() ) {
|
||||
break;
|
||||
}
|
||||
|
||||
const bool isShellActive = ( game && ( game->Shell_IsActive() || game->IsPDAOpen() ) );
|
||||
const bool isConsoleActive = console->Active();
|
||||
|
||||
if ( win32.activeApp ) {
|
||||
if ( isShellActive ) {
|
||||
// If the shell is active, it will display its own cursor.
|
||||
SetCursor( NULL );
|
||||
} else if ( isConsoleActive ) {
|
||||
// The console is active but the shell is not.
|
||||
// Show the Windows cursor.
|
||||
SetCursor( LoadCursor( 0, IDC_ARROW ) );
|
||||
} else {
|
||||
// The shell not active and neither is the console.
|
||||
// This is normal gameplay, hide the cursor.
|
||||
SetCursor( NULL );
|
||||
}
|
||||
} else {
|
||||
if ( !isShellActive ) {
|
||||
// Always show the cursor when the window is in the background
|
||||
SetCursor( LoadCursor( 0, IDC_ARROW ) );
|
||||
} else {
|
||||
SetCursor( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
const int x = GET_X_LPARAM( lParam );
|
||||
const int y = GET_Y_LPARAM( lParam );
|
||||
|
||||
// Generate an event
|
||||
Sys_QueEvent( SE_MOUSE_ABSOLUTE, x, y, 0, NULL, 0 );
|
||||
|
||||
// Get a mouse leave message
|
||||
TRACKMOUSEEVENT tme = {
|
||||
sizeof( TRACKMOUSEEVENT ),
|
||||
TME_LEAVE,
|
||||
hWnd,
|
||||
0
|
||||
};
|
||||
|
||||
TrackMouseEvent( &tme );
|
||||
|
||||
return 0;
|
||||
}
|
||||
case WM_MOUSELEAVE: {
|
||||
Sys_QueEvent( SE_MOUSE_LEAVE, 0, 0, 0, NULL, 0 );
|
||||
return 0;
|
||||
}
|
||||
case WM_LBUTTONDOWN: {
|
||||
Sys_QueEvent( SE_KEY, K_MOUSE1, 1, 0, NULL, 0 );
|
||||
return 0;
|
||||
}
|
||||
case WM_LBUTTONUP: {
|
||||
Sys_QueEvent( SE_KEY, K_MOUSE1, 0, 0, NULL, 0 );
|
||||
return 0;
|
||||
}
|
||||
case WM_RBUTTONDOWN: {
|
||||
Sys_QueEvent( SE_KEY, K_MOUSE2, 1, 0, NULL, 0 );
|
||||
return 0;
|
||||
}
|
||||
case WM_RBUTTONUP: {
|
||||
Sys_QueEvent( SE_KEY, K_MOUSE2, 0, 0, NULL, 0 );
|
||||
return 0;
|
||||
}
|
||||
case WM_MBUTTONDOWN: {
|
||||
Sys_QueEvent( SE_KEY, K_MOUSE3, 1, 0, NULL, 0 );
|
||||
return 0;
|
||||
}
|
||||
case WM_MBUTTONUP: {
|
||||
Sys_QueEvent( SE_KEY, K_MOUSE3, 0, 0, NULL, 0 );
|
||||
return 0;
|
||||
}
|
||||
case WM_XBUTTONDOWN: {
|
||||
int button = GET_XBUTTON_WPARAM( wParam );
|
||||
if ( button == 1 ) {
|
||||
Sys_QueEvent( SE_KEY, K_MOUSE4, 1, 0, NULL, 0 );
|
||||
} else if ( button == 2 ) {
|
||||
Sys_QueEvent( SE_KEY, K_MOUSE5, 1, 0, NULL, 0 );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case WM_XBUTTONUP: {
|
||||
int button = GET_XBUTTON_WPARAM( wParam );
|
||||
if ( button == 1 ) {
|
||||
Sys_QueEvent( SE_KEY, K_MOUSE4, 0, 0, NULL, 0 );
|
||||
} else if ( button == 2 ) {
|
||||
Sys_QueEvent( SE_KEY, K_MOUSE5, 0, 0, NULL, 0 );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case WM_MOUSEWHEEL: {
|
||||
int delta = GET_WHEEL_DELTA_WPARAM( wParam ) / WHEEL_DELTA;
|
||||
int key = delta < 0 ? K_MWHEELDOWN : K_MWHEELUP;
|
||||
delta = abs( delta );
|
||||
while( delta-- > 0 ) {
|
||||
Sys_QueEvent( SE_KEY, key, true, 0, NULL, 0 );
|
||||
Sys_QueEvent( SE_KEY, key, false, 0, NULL, 0 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||||
}
|
||||
Reference in New Issue
Block a user