2020-04-26 06:25:03 -04:00
|
|
|
#if defined RW_D3D9 || defined RWLIBS
|
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
#define _WIN32_WINDOWS 0x0500
|
2019-06-01 23:00:38 -04:00
|
|
|
#define WINVER 0x0500
|
|
|
|
#define DIRECTINPUT_VERSION 0x0800
|
|
|
|
|
2019-06-02 17:42:51 -04:00
|
|
|
#include <winerror.h>
|
2019-06-01 23:00:38 -04:00
|
|
|
#include <windows.h>
|
|
|
|
#include <mmsystem.h>
|
|
|
|
#include <shellapi.h>
|
|
|
|
|
|
|
|
#include <windowsx.h>
|
|
|
|
#include <basetsd.h>
|
|
|
|
|
|
|
|
#include <regstr.h>
|
|
|
|
#include <shlobj.h>
|
|
|
|
|
|
|
|
#include <dbt.h>
|
|
|
|
|
|
|
|
#pragma warning( push )
|
|
|
|
#pragma warning( disable : 4005)
|
2019-06-02 17:42:51 -04:00
|
|
|
#include <d3d8.h>
|
2019-06-01 23:00:38 -04:00
|
|
|
#include <ddraw.h>
|
|
|
|
#include <dinput.h>
|
|
|
|
#include <DShow.h>
|
2019-06-02 17:42:51 -04:00
|
|
|
#pragma warning( pop )
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
#define WM_GRAPHNOTIFY WM_USER+13
|
|
|
|
|
2019-06-02 17:42:51 -04:00
|
|
|
#pragma comment( lib, "d3d8.lib" )
|
|
|
|
#pragma comment( lib, "ddraw.lib" )
|
2019-06-01 23:00:38 -04:00
|
|
|
#pragma comment( lib, "Winmm.lib" )
|
|
|
|
#pragma comment( lib, "dxguid.lib" )
|
|
|
|
#pragma comment( lib, "strmiids.lib" )
|
2019-06-05 15:18:06 -04:00
|
|
|
#pragma comment( lib, "dinput8.lib" )
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
#if (defined(_MSC_VER))
|
|
|
|
#include <tchar.h>
|
|
|
|
#endif /* (defined(_MSC_VER)) */
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "rwcore.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include "skeleton.h"
|
|
|
|
#include "platform.h"
|
2020-04-26 06:25:03 -04:00
|
|
|
#include "crossplatform.h"
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
#define MAX_SUBSYSTEMS (16)
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
|
2020-04-17 01:54:14 -04:00
|
|
|
static RwBool ForegroundApp = TRUE;
|
2019-06-02 17:42:51 -04:00
|
|
|
|
2020-04-17 01:54:14 -04:00
|
|
|
static RwBool RwInitialised = FALSE;
|
2019-06-02 17:42:51 -04:00
|
|
|
|
2019-06-01 23:00:38 -04:00
|
|
|
static RwSubSystemInfo GsubSysInfo[MAX_SUBSYSTEMS];
|
2019-06-11 05:30:53 -04:00
|
|
|
static RwInt32 GnumSubSystems = 0;
|
|
|
|
static RwInt32 GcurSel = 0, GcurSelVM = 0;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2020-04-17 01:54:14 -04:00
|
|
|
static RwBool startupDeactivate;
|
2019-06-02 17:42:51 -04:00
|
|
|
|
2020-04-17 01:54:14 -04:00
|
|
|
static RwBool useDefault;
|
2019-06-02 17:42:51 -04:00
|
|
|
|
2020-04-17 01:54:14 -04:00
|
|
|
static RwBool defaultFullscreenRes = TRUE;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
/* Class name for the MS Window's window class. */
|
|
|
|
|
|
|
|
static const RwChar *AppClassName = RWSTRING("Grand theft auto 3");
|
|
|
|
|
2020-04-17 01:54:14 -04:00
|
|
|
static psGlobalType PsGlobal;
|
2019-06-02 09:33:37 -04:00
|
|
|
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
#define PSGLOBAL(var) (((psGlobalType *)(RsGlobal.ps))->var)
|
|
|
|
|
|
|
|
#undef MAKEPOINTS
|
2019-06-11 05:30:53 -04:00
|
|
|
#define MAKEPOINTS(l) (*((POINTS /*FAR*/ *)&(l)))
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
|
|
|
|
#define JIF(x) if (FAILED(hr=(x))) \
|
2019-06-02 17:42:51 -04:00
|
|
|
{debug(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("\n"), hr); return;}
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
#include "patcher.h"
|
2019-06-17 04:30:02 -04:00
|
|
|
#include "main.h"
|
2019-06-01 23:00:38 -04:00
|
|
|
#include "FileMgr.h"
|
|
|
|
#include "Text.h"
|
|
|
|
#include "Pad.h"
|
|
|
|
#include "Timer.h"
|
|
|
|
#include "DMAudio.h"
|
|
|
|
#include "ControllerConfig.h"
|
|
|
|
#include "Frontend.h"
|
|
|
|
#include "Game.h"
|
|
|
|
#include "PCSave.h"
|
2019-06-30 06:53:39 -04:00
|
|
|
#include "Sprite2d.h"
|
2019-08-15 10:51:39 -04:00
|
|
|
#include "AnimViewer.h"
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2019-06-02 09:33:37 -04:00
|
|
|
VALIDATE_SIZE(psGlobalType, 0x28);
|
|
|
|
|
2019-06-01 23:00:38 -04:00
|
|
|
// DirectShow interfaces
|
2019-06-30 06:53:39 -04:00
|
|
|
IGraphBuilder *pGB = nil;
|
|
|
|
IMediaControl *pMC = nil;
|
|
|
|
IMediaEventEx *pME = nil;
|
|
|
|
IVideoWindow *pVW = nil;
|
|
|
|
IMediaSeeking *pMS = nil;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
DWORD dwDXVersion;
|
|
|
|
DWORD _dwMemTotalPhys;
|
2020-04-17 01:54:14 -04:00
|
|
|
DWORD _dwMemAvailPhys;
|
2019-06-01 23:00:38 -04:00
|
|
|
DWORD _dwMemTotalVirtual;
|
|
|
|
DWORD _dwMemAvailVirtual;
|
2020-04-17 01:54:14 -04:00
|
|
|
DWORD _dwMemTotalVideo;
|
2019-06-01 23:00:38 -04:00
|
|
|
DWORD _dwMemAvailVideo;
|
2020-04-17 01:54:14 -04:00
|
|
|
DWORD _dwOperatingSystemVersion;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2020-04-17 01:54:14 -04:00
|
|
|
RwUInt32 gGameState;
|
2019-10-26 23:17:30 -04:00
|
|
|
CJoySticks AllValidWinJoys;
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
CJoySticks::CJoySticks()
|
|
|
|
{
|
2019-10-26 23:17:30 -04:00
|
|
|
for (int i = 0; i < MAX_JOYSTICKS; i++)
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
|
|
|
ClearJoyInfo(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CJoySticks::ClearJoyInfo(int joyID)
|
|
|
|
{
|
|
|
|
m_aJoys[joyID].m_State = JOYPAD_UNUSED;
|
|
|
|
m_aJoys[joyID].m_bInitialised = false;
|
|
|
|
m_aJoys[joyID].m_bHasAxisZ = false;
|
|
|
|
m_aJoys[joyID].m_bHasAxisR = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
void _psCreateFolder(LPCSTR path)
|
|
|
|
{
|
|
|
|
HANDLE hfle = CreateFile(path, GENERIC_READ,
|
|
|
|
FILE_SHARE_READ,
|
2019-06-30 06:53:39 -04:00
|
|
|
nil,
|
2019-06-01 23:00:38 -04:00
|
|
|
OPEN_EXISTING,
|
|
|
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL,
|
2019-06-30 06:53:39 -04:00
|
|
|
nil);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
if ( hfle == INVALID_HANDLE_VALUE )
|
2019-06-30 06:53:39 -04:00
|
|
|
CreateDirectory(path, nil);
|
2019-06-01 23:00:38 -04:00
|
|
|
else
|
|
|
|
CloseHandle(hfle);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
const char *_psGetUserFilesFolder()
|
|
|
|
{
|
2019-06-12 19:12:37 -04:00
|
|
|
#ifdef USE_MY_DOCUMENTS
|
2019-06-01 23:00:38 -04:00
|
|
|
HKEY hKey = NULL;
|
|
|
|
|
|
|
|
static CHAR szUserFiles[256];
|
|
|
|
|
|
|
|
if ( RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
|
|
REGSTR_PATH_SPECIAL_FOLDERS,
|
|
|
|
REG_OPTION_RESERVED,
|
|
|
|
KEY_READ,
|
|
|
|
&hKey) == ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
DWORD KeyType;
|
|
|
|
DWORD KeycbData = sizeof(szUserFiles);
|
|
|
|
if ( RegQueryValueEx(hKey,
|
|
|
|
"Personal",
|
|
|
|
NULL,
|
|
|
|
&KeyType,
|
|
|
|
(LPBYTE)szUserFiles,
|
|
|
|
&KeycbData) == ERROR_SUCCESS )
|
|
|
|
{
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
strcat(szUserFiles, "\\GTA3 User Files");
|
|
|
|
_psCreateFolder(szUserFiles);
|
|
|
|
return szUserFiles;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(szUserFiles, "data");
|
|
|
|
return szUserFiles;
|
2019-06-12 19:12:37 -04:00
|
|
|
#else
|
|
|
|
static CHAR szUserFiles[256];
|
|
|
|
strcpy(szUserFiles, "userfiles");
|
|
|
|
_psCreateFolder(szUserFiles);
|
|
|
|
return szUserFiles;
|
|
|
|
#endif
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
RwBool
|
|
|
|
psCameraBeginUpdate(RwCamera *camera)
|
|
|
|
{
|
|
|
|
if ( !RwCameraBeginUpdate(Scene.camera) )
|
|
|
|
{
|
|
|
|
ForegroundApp = FALSE;
|
|
|
|
RsEventHandler(rsACTIVATE, (void *)FALSE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
psCameraShowRaster(RwCamera *camera)
|
|
|
|
{
|
|
|
|
if (CMenuManager::m_PrefsVsync)
|
|
|
|
RwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPWAITVSYNC);
|
|
|
|
else
|
|
|
|
RwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPDONTWAIT);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
RwUInt32
|
|
|
|
psTimer(void)
|
|
|
|
{
|
|
|
|
RwUInt32 time;
|
|
|
|
|
|
|
|
TIMECAPS TimeCaps;
|
|
|
|
|
|
|
|
timeGetDevCaps(&TimeCaps, sizeof(TIMECAPS));
|
|
|
|
|
|
|
|
timeBeginPeriod(TimeCaps.wPeriodMin);
|
|
|
|
|
|
|
|
time = (RwUInt32) timeGetTime();
|
|
|
|
|
|
|
|
timeEndPeriod(TimeCaps.wPeriodMin);
|
|
|
|
|
|
|
|
return time;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
psMouseSetPos(RwV2d *pos)
|
|
|
|
{
|
|
|
|
POINT point;
|
|
|
|
|
|
|
|
point.x = (RwInt32) pos->x;
|
|
|
|
point.y = (RwInt32) pos->y;
|
|
|
|
|
|
|
|
ClientToScreen(PSGLOBAL(window), &point);
|
|
|
|
|
|
|
|
SetCursorPos(point.x, point.y);
|
|
|
|
|
|
|
|
PSGLOBAL(lastMousePos.x) = (RwInt32)pos->x;
|
|
|
|
|
|
|
|
PSGLOBAL(lastMousePos.y) = (RwInt32)pos->y;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
RwMemoryFunctions*
|
|
|
|
psGetMemoryFunctions(void)
|
|
|
|
{
|
2019-06-30 06:53:39 -04:00
|
|
|
return nil;
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
RwBool
|
|
|
|
psInstallFileSystem(void)
|
|
|
|
{
|
|
|
|
return (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
RwBool
|
|
|
|
psNativeTextureSupport(void)
|
|
|
|
{
|
|
|
|
return RwD3D8DeviceSupportsDXTTexture();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
static BOOL
|
|
|
|
InitApplication(HANDLE instance)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Perform any necessary MS Windows application initialization. Basically,
|
|
|
|
* this means registering the window class for this application.
|
|
|
|
*/
|
|
|
|
|
|
|
|
WNDCLASS windowClass;
|
|
|
|
|
|
|
|
windowClass.style = CS_BYTEALIGNWINDOW;
|
|
|
|
windowClass.lpfnWndProc = (WNDPROC) MainWndProc;
|
|
|
|
windowClass.cbClsExtra = 0;
|
|
|
|
windowClass.cbWndExtra = 0;
|
|
|
|
windowClass.hInstance = (HINSTANCE)instance;
|
2019-06-30 06:53:39 -04:00
|
|
|
windowClass.hIcon = nil;
|
|
|
|
windowClass.hCursor = LoadCursor(nil, IDC_ARROW);
|
|
|
|
windowClass.hbrBackground = nil;
|
2019-06-01 23:00:38 -04:00
|
|
|
windowClass.lpszMenuName = NULL;
|
|
|
|
windowClass.lpszClassName = AppClassName;
|
|
|
|
|
|
|
|
return RegisterClass(&windowClass);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
static HWND
|
|
|
|
InitInstance(HANDLE instance)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Perform any necessary initialization for this instance of the
|
|
|
|
* application.
|
|
|
|
*
|
|
|
|
* Create the MS Window's window instance for this application. The
|
|
|
|
* initial window size is given by the defined camera size. The window
|
|
|
|
* is not given a title as we set it during Init3D() with information
|
|
|
|
* about the version of RenderWare being used.
|
|
|
|
*/
|
|
|
|
|
|
|
|
RECT rect;
|
|
|
|
|
|
|
|
rect.left = rect.top = 0;
|
|
|
|
rect.right = RsGlobal.maximumWidth;
|
|
|
|
rect.bottom = RsGlobal.maximumHeight;
|
|
|
|
|
|
|
|
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
|
|
|
|
|
|
|
|
return CreateWindow(AppClassName, RsGlobal.appName,
|
|
|
|
WS_OVERLAPPEDWINDOW,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
rect.right - rect.left, rect.bottom - rect.top,
|
2019-06-30 06:53:39 -04:00
|
|
|
(HWND)nil, (HMENU)nil, (HINSTANCE)instance, nil);
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
|
2019-06-02 17:42:51 -04:00
|
|
|
void _GetVideoMemInfo(LPDWORD total, LPDWORD avaible)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
LPDIRECTDRAW7 pDD7;
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
hr = DirectDrawCreateEx(nil, (VOID**)&pDD7, IID_IDirectDraw7, nil);
|
2019-06-02 17:42:51 -04:00
|
|
|
|
|
|
|
if ( FAILED(hr) )
|
|
|
|
return;
|
|
|
|
|
|
|
|
DDSCAPS2 caps;
|
|
|
|
|
|
|
|
ZeroMemory(&caps, sizeof(DDSCAPS2));
|
|
|
|
caps.dwCaps = DDSCAPS_VIDEOMEMORY;
|
|
|
|
|
|
|
|
pDD7->GetAvailableVidMem(&caps, total, avaible);
|
|
|
|
|
|
|
|
pDD7->Release();
|
|
|
|
}
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
typedef HRESULT(WINAPI * DIRECTDRAWCREATEEX)( GUID*, VOID**, REFIID, IUnknown* );
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Name: GetDXVersion()
|
|
|
|
// Desc: This function returns the DirectX version number as follows:
|
2019-06-11 05:30:53 -04:00
|
|
|
// 0x0000 = No DirectX installed
|
|
|
|
// 0x0700 = At least DirectX 7 installed.
|
|
|
|
// 0x0800 = At least DirectX 8 installed.
|
2019-06-01 23:00:38 -04:00
|
|
|
//
|
2019-06-11 05:30:53 -04:00
|
|
|
// Please note that this code is intended as a general guideline. Your
|
|
|
|
// app will probably be able to simply query for functionality (via
|
|
|
|
// QueryInterface) for one or two components.
|
2019-06-01 23:00:38 -04:00
|
|
|
//
|
2019-06-11 05:30:53 -04:00
|
|
|
// Please also note:
|
|
|
|
// "if( dwDXVersion != 0x500 ) return FALSE;" is VERY BAD.
|
|
|
|
// "if( dwDXVersion < 0x500 ) return FALSE;" is MUCH BETTER.
|
|
|
|
// to ensure your app will run on future releases of DirectX.
|
2019-06-01 23:00:38 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DWORD GetDXVersion()
|
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
DIRECTDRAWCREATEEX DirectDrawCreateEx = NULL;
|
2019-06-30 06:53:39 -04:00
|
|
|
HINSTANCE hDDrawDLL = nil;
|
|
|
|
HINSTANCE hD3D8DLL = nil;
|
2019-06-11 05:30:53 -04:00
|
|
|
HINSTANCE hDPNHPASTDLL = NULL;
|
|
|
|
DWORD dwDXVersion = 0;
|
|
|
|
//HRESULT hr;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
// First see if DDRAW.DLL even exists.
|
|
|
|
hDDrawDLL = LoadLibrary( "DDRAW.DLL" );
|
2019-06-30 06:53:39 -04:00
|
|
|
if( hDDrawDLL == nil )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
dwDXVersion = 0;
|
|
|
|
OutputDebugString( "Couldn't LoadLibrary DDraw\r\n" );
|
|
|
|
return dwDXVersion;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// DirectX 7.0 Checks
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Check for DirectX 7 by creating a DDraw7 object
|
|
|
|
LPDIRECTDRAW7 pDD7;
|
|
|
|
DirectDrawCreateEx = (DIRECTDRAWCREATEEX)GetProcAddress( hDDrawDLL,
|
|
|
|
"DirectDrawCreateEx" );
|
2019-06-30 06:53:39 -04:00
|
|
|
if( nil == DirectDrawCreateEx )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
FreeLibrary( hDDrawDLL );
|
|
|
|
OutputDebugString( "Couldn't GetProcAddress DirectDrawCreateEx\r\n" );
|
|
|
|
return dwDXVersion;
|
|
|
|
}
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
if( FAILED( DirectDrawCreateEx( nil, (VOID**)&pDD7, IID_IDirectDraw7,
|
|
|
|
nil ) ) )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
FreeLibrary( hDDrawDLL );
|
|
|
|
OutputDebugString( "Couldn't DirectDrawCreateEx\r\n" );
|
|
|
|
return dwDXVersion;
|
|
|
|
}
|
|
|
|
|
|
|
|
// DDraw7 was created successfully. We must be at least DX7.0
|
|
|
|
dwDXVersion = 0x700;
|
|
|
|
pDD7->Release();
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// DirectX 8.0 Checks
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Simply see if D3D8.dll exists.
|
|
|
|
hD3D8DLL = LoadLibrary( "D3D8.DLL" );
|
2019-06-30 06:53:39 -04:00
|
|
|
if( hD3D8DLL == nil )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
FreeLibrary( hDDrawDLL );
|
2019-06-01 23:00:38 -04:00
|
|
|
OutputDebugString( "Couldn't LoadLibrary D3D8.DLL\r\n" );
|
|
|
|
return dwDXVersion;
|
|
|
|
}
|
|
|
|
|
|
|
|
// D3D8.dll exists. We must be at least DX8.0
|
|
|
|
dwDXVersion = 0x800;
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// DirectX 8.1 Checks
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Simply see if dpnhpast.dll exists.
|
|
|
|
hDPNHPASTDLL = LoadLibrary( "dpnhpast.dll" );
|
2019-06-30 06:53:39 -04:00
|
|
|
if( hDPNHPASTDLL == nil )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
FreeLibrary( hDPNHPASTDLL );
|
2019-06-01 23:00:38 -04:00
|
|
|
OutputDebugString( "Couldn't LoadLibrary dpnhpast.dll\r\n" );
|
|
|
|
return dwDXVersion;
|
|
|
|
}
|
|
|
|
|
|
|
|
// dpnhpast.dll exists. We must be at least DX8.1
|
|
|
|
dwDXVersion = 0x801;
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// End of checking for versions of DirectX
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Close open libraries and return
|
|
|
|
FreeLibrary( hDDrawDLL );
|
|
|
|
FreeLibrary( hD3D8DLL );
|
|
|
|
|
|
|
|
return dwDXVersion;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
static char cpuvendor[16] = "UnknownVendr";
|
|
|
|
__declspec(naked) const char * _psGetCpuVendr()
|
|
|
|
{
|
|
|
|
__asm
|
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
push ebx
|
|
|
|
xor eax, eax
|
2019-06-01 23:00:38 -04:00
|
|
|
cpuid
|
2019-06-11 05:30:53 -04:00
|
|
|
mov dword ptr [cpuvendor+0], ebx
|
|
|
|
mov dword ptr [cpuvendor+4], edx
|
|
|
|
mov dword ptr [cpuvendor+8], ecx
|
|
|
|
mov eax, offset cpuvendor
|
|
|
|
pop ebx
|
2019-06-01 23:00:38 -04:00
|
|
|
retn
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
__declspec(naked) RwUInt32 _psGetCpuFeatures()
|
|
|
|
{
|
|
|
|
__asm
|
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
mov eax, 1
|
2019-06-01 23:00:38 -04:00
|
|
|
cpuid
|
2019-06-11 05:30:53 -04:00
|
|
|
mov eax, edx
|
2019-06-01 23:00:38 -04:00
|
|
|
retn
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
__declspec(naked) RwUInt32 _psGetCpuFeaturesEx()
|
|
|
|
{
|
|
|
|
__asm
|
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
mov eax, 80000000h
|
2019-06-01 23:00:38 -04:00
|
|
|
cpuid
|
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
cmp eax, 80000000h
|
|
|
|
jbe short _NOEX
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
mov eax, 80000001h
|
2019-06-01 23:00:38 -04:00
|
|
|
cpuid
|
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
mov eax, edx
|
|
|
|
jmp short _RETEX
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
_NOEX:
|
2019-06-11 05:30:53 -04:00
|
|
|
xor eax, eax
|
|
|
|
mov eax, eax
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
_RETEX:
|
|
|
|
retn
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void _psPrintCpuInfo()
|
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
RwUInt32 features = _psGetCpuFeatures();
|
2019-06-01 23:00:38 -04:00
|
|
|
RwUInt32 FeaturesEx = _psGetCpuFeaturesEx();
|
|
|
|
|
|
|
|
debug("Running on a %s", _psGetCpuVendr());
|
|
|
|
|
|
|
|
if ( features & 0x800000 )
|
|
|
|
debug("with MMX");
|
|
|
|
if ( features & 0x2000000 )
|
|
|
|
debug("with SSE");
|
|
|
|
if ( FeaturesEx & 0x80000000 )
|
|
|
|
debug("with 3DNow");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
#ifdef UNDER_CE
|
2019-06-11 05:30:53 -04:00
|
|
|
#define CMDSTR LPWSTR
|
2019-06-01 23:00:38 -04:00
|
|
|
#else
|
2019-06-11 05:30:53 -04:00
|
|
|
#define CMDSTR LPSTR
|
2019-06-01 23:00:38 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
RwBool
|
|
|
|
psInitialise(void)
|
|
|
|
{
|
2020-02-25 14:01:56 -05:00
|
|
|
PsGlobal.lastMousePos.x = PsGlobal.lastMousePos.y = 0.0f;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
RsGlobal.ps = &PsGlobal;
|
|
|
|
|
|
|
|
PsGlobal.fullScreen = FALSE;
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
PsGlobal.dinterface = nil;
|
|
|
|
PsGlobal.mouse = nil;
|
|
|
|
PsGlobal.joy1 = nil;
|
|
|
|
PsGlobal.joy2 = nil;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
CFileMgr::Initialise();
|
|
|
|
|
|
|
|
C_PcSave::SetSaveDirectory(_psGetUserFilesFolder());
|
|
|
|
|
2019-07-03 07:13:55 -04:00
|
|
|
InitialiseLanguage();
|
2019-06-24 20:34:29 -04:00
|
|
|
|
2019-06-01 23:00:38 -04:00
|
|
|
FrontEndMenuManager.LoadSettings();
|
|
|
|
|
|
|
|
gGameState = GS_START_UP;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_START_UP");
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
_psPrintCpuInfo();
|
|
|
|
|
|
|
|
OSVERSIONINFO verInfo;
|
|
|
|
verInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
|
|
|
|
|
|
GetVersionEx(&verInfo);
|
|
|
|
|
2019-10-26 23:17:30 -04:00
|
|
|
_dwOperatingSystemVersion = OS_WIN95;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
if ( verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
|
|
|
|
{
|
|
|
|
if ( verInfo.dwMajorVersion == 4 )
|
|
|
|
{
|
|
|
|
debug("Operating System is WinNT\n");
|
2019-10-26 23:17:30 -04:00
|
|
|
_dwOperatingSystemVersion = OS_WINNT;
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
else if ( verInfo.dwMajorVersion == 5 )
|
|
|
|
{
|
|
|
|
debug("Operating System is Win2000\n");
|
|
|
|
_dwOperatingSystemVersion = OS_WIN2000;
|
|
|
|
}
|
|
|
|
else if ( verInfo.dwMajorVersion > 5 )
|
|
|
|
{
|
|
|
|
debug("Operating System is WinXP or greater\n");
|
|
|
|
_dwOperatingSystemVersion = OS_WINXP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( verInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
|
|
|
|
{
|
|
|
|
if ( verInfo.dwMajorVersion > 4 || verInfo.dwMajorVersion == 4 && verInfo.dwMinorVersion == 1 )
|
|
|
|
{
|
|
|
|
debug("Operating System is Win98\n");
|
|
|
|
_dwOperatingSystemVersion = OS_WIN98;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
debug("Operating System is Win95\n");
|
|
|
|
_dwOperatingSystemVersion = OS_WIN95;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dwDXVersion = GetDXVersion();
|
|
|
|
debug("DirectX version 0x%x\n", dwDXVersion);
|
|
|
|
|
|
|
|
if ( _dwOperatingSystemVersion == OS_WIN95 )
|
|
|
|
{
|
2019-06-30 06:53:39 -04:00
|
|
|
MessageBoxW(nil,
|
2019-06-11 05:30:53 -04:00
|
|
|
(LPCWSTR)TheText.Get("WIN_95"), // Grand Theft Auto III cannot run on Windows 95
|
2019-06-01 23:00:38 -04:00
|
|
|
(LPCWSTR)TheText.Get("WIN_TTL"), // Grand Theft Auto III
|
|
|
|
MB_OK);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( dwDXVersion < 0x801 )
|
|
|
|
{
|
2019-06-30 06:53:39 -04:00
|
|
|
MessageBoxW(nil,
|
2019-06-11 05:30:53 -04:00
|
|
|
(LPCWSTR)TheText.Get("WIN_DX"), // Grand Theft Auto III requires at least DirectX version 8.1
|
2019-06-01 23:00:38 -04:00
|
|
|
(LPCWSTR)TheText.Get("WIN_TTL"), // Grand Theft Auto III
|
|
|
|
MB_OK);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
MEMORYSTATUS memstats;
|
|
|
|
GlobalMemoryStatus(&memstats);
|
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
_dwMemTotalPhys = memstats.dwTotalPhys;
|
|
|
|
_dwMemAvailPhys = memstats.dwAvailPhys;
|
2019-06-01 23:00:38 -04:00
|
|
|
_dwMemTotalVirtual = memstats.dwTotalVirtual;
|
|
|
|
_dwMemAvailVirtual = memstats.dwAvailVirtual;
|
|
|
|
|
|
|
|
_GetVideoMemInfo(&_dwMemTotalVideo, &_dwMemAvailVideo);
|
2020-04-15 17:44:25 -04:00
|
|
|
#ifdef FIX_BUGS
|
|
|
|
debug("Physical memory size %u\n", _dwMemTotalPhys);
|
|
|
|
debug("Available physical memory %u\n", _dwMemAvailPhys);
|
|
|
|
debug("Video memory size %u\n", _dwMemTotalVideo);
|
|
|
|
debug("Available video memory %u\n", _dwMemAvailVideo);
|
|
|
|
#else
|
2019-06-01 23:00:38 -04:00
|
|
|
debug("Physical memory size %d\n", _dwMemTotalPhys);
|
|
|
|
debug("Available physical memory %d\n", _dwMemAvailPhys);
|
|
|
|
debug("Video memory size %d\n", _dwMemTotalVideo);
|
|
|
|
debug("Available video memory %d\n", _dwMemAvailVideo);
|
2020-04-15 17:44:25 -04:00
|
|
|
#endif
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
if ( _dwMemAvailVideo < (12 * 1024 * 1024) /*12 MB*/ )
|
|
|
|
{
|
2019-06-30 06:53:39 -04:00
|
|
|
MessageBoxW(nil,
|
2019-06-01 23:00:38 -04:00
|
|
|
(LPCWSTR)TheText.Get("WIN_VDM"), // Grand Theft Auto III requires at least 12MB of available video memory
|
|
|
|
(LPCWSTR)TheText.Get("WIN_TTL"), // Grand Theft Auto III
|
|
|
|
MB_OK);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
TheText.Unload();
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
psTerminate(void)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
static RwChar **_VMList;
|
|
|
|
|
|
|
|
RwInt32 _psGetNumVideModes()
|
|
|
|
{
|
|
|
|
return RwEngineGetNumVideoModes();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
RwBool _psFreeVideoModeList()
|
|
|
|
{
|
|
|
|
RwInt32 numModes;
|
|
|
|
RwInt32 i;
|
|
|
|
|
|
|
|
numModes = _psGetNumVideModes();
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( _VMList == nil )
|
2019-06-01 23:00:38 -04:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
for ( i = 0; i < numModes; i++ )
|
|
|
|
{
|
|
|
|
RwFree(_VMList[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
RwFree(_VMList);
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
_VMList = nil;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
RwChar **_psGetVideoModeList()
|
|
|
|
{
|
|
|
|
RwInt32 numModes;
|
|
|
|
RwInt32 i;
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( _VMList != nil )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
return _VMList;
|
|
|
|
}
|
|
|
|
|
|
|
|
numModes = RwEngineGetNumVideoModes();
|
|
|
|
|
|
|
|
_VMList = (RwChar **)RwCalloc(numModes, sizeof(RwChar*));
|
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
for ( i = 0; i < numModes; i++ )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
RwVideoMode vm;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
RwEngineGetVideoModeInfo(&vm, i);
|
|
|
|
|
|
|
|
if ( vm.flags & rwVIDEOMODEEXCLUSIVE )
|
|
|
|
{
|
|
|
|
if ( vm.width >= 640
|
|
|
|
&& vm.height >= 480
|
|
|
|
&& (vm.width == 640
|
|
|
|
&& vm.height == 480)
|
|
|
|
|| !(vm.flags & rwVIDEOMODEEXCLUSIVE)
|
|
|
|
|| (_dwMemTotalVideo - vm.depth * vm.height * vm.width / 8) > (12 * 1024 * 1024)/*12 MB*/ )
|
|
|
|
{
|
|
|
|
_VMList[i] = (RwChar*)RwCalloc(100, sizeof(RwChar));
|
|
|
|
rwsprintf(_VMList[i],"%lu X %lu X %lu", vm.width, vm.height, vm.depth);
|
|
|
|
}
|
|
|
|
else
|
2019-06-30 06:53:39 -04:00
|
|
|
_VMList[i] = nil;
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
else
|
2019-06-30 06:53:39 -04:00
|
|
|
_VMList[i] = nil;
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return _VMList;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
void _psSelectScreenVM(RwInt32 videoMode)
|
|
|
|
{
|
2019-06-30 06:53:39 -04:00
|
|
|
RwTexDictionarySetCurrent( nil );
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
FrontEndMenuManager.UnloadTextures();
|
|
|
|
|
|
|
|
if ( !_psSetVideoMode(RwEngineGetCurrentSubSystem(), videoMode) )
|
|
|
|
{
|
|
|
|
RsGlobal.quit = TRUE;
|
|
|
|
|
|
|
|
ShowWindow(PSGLOBAL(window), SW_HIDE);
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
MessageBoxW(nil,
|
2019-06-01 23:00:38 -04:00
|
|
|
(LPCWSTR)TheText.Get("WIN_RSZ"), // Failed to select new screen resolution
|
|
|
|
(LPCWSTR)TheText.Get("WIN_TTL"), // Grand Theft Auto III
|
|
|
|
MB_OK);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
FrontEndMenuManager.LoadAllTextures();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
2019-06-02 17:42:51 -04:00
|
|
|
void WaitForState(FILTER_STATE State)
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
ASSERT(pMC != nil);
|
2019-06-02 17:42:51 -04:00
|
|
|
|
2019-06-01 23:00:38 -04:00
|
|
|
// Make sure we have switched to the required state
|
|
|
|
LONG lfs;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
hr = pMC->GetState(10, &lfs);
|
|
|
|
} while (State != lfs);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
2019-06-02 17:42:51 -04:00
|
|
|
void HandleGraphEvent(void)
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
LONG evCode, evParam1, evParam2;
|
|
|
|
HRESULT hr=S_OK;
|
2019-06-02 17:42:51 -04:00
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
ASSERT(pME != nil);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
// Process all queued events
|
2019-06-02 17:42:51 -04:00
|
|
|
while (SUCCEEDED(pME->GetEvent(&evCode, (LONG_PTR *)&evParam1,
|
|
|
|
(LONG_PTR *)&evParam2, 0)))
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
// Free memory associated with callback, since we're not using it
|
|
|
|
hr = pME->FreeEventParams(evCode, evParam1, evParam2);
|
|
|
|
|
|
|
|
// If this is the end of the clip, reset to beginning
|
2019-06-02 17:42:51 -04:00
|
|
|
if (EC_COMPLETE == evCode)
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
2019-06-02 17:42:51 -04:00
|
|
|
switch (gGameState)
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
case GS_LOGO_MPEG:
|
2019-06-02 17:42:51 -04:00
|
|
|
{
|
2019-06-01 23:00:38 -04:00
|
|
|
gGameState = GS_INIT_INTRO_MPEG;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_INIT_INTRO_MPEG");
|
2019-06-01 23:00:38 -04:00
|
|
|
break;
|
2019-06-02 17:42:51 -04:00
|
|
|
}
|
2019-06-01 23:00:38 -04:00
|
|
|
case GS_INTRO_MPEG:
|
2019-06-02 17:42:51 -04:00
|
|
|
{
|
2019-06-01 23:00:38 -04:00
|
|
|
gGameState = GS_INIT_ONCE;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_INIT_ONCE");
|
2019-06-01 23:00:38 -04:00
|
|
|
break;
|
2019-06-02 17:42:51 -04:00
|
|
|
}
|
2019-06-01 23:00:38 -04:00
|
|
|
default:
|
2019-06-02 17:42:51 -04:00
|
|
|
{
|
2019-06-01 23:00:38 -04:00
|
|
|
break;
|
2019-06-02 17:42:51 -04:00
|
|
|
}
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pME->SetNotifyWindow((OAHWND)NULL, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
LRESULT CALLBACK
|
|
|
|
MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
POINTS points;
|
|
|
|
static BOOL noMemory = FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
switch( message )
|
|
|
|
{
|
|
|
|
case WM_SETCURSOR:
|
|
|
|
{
|
|
|
|
ShowCursor(FALSE);
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
SetCursor(nil);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
break; // is this correct ?
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_SIZE:
|
|
|
|
{
|
|
|
|
RwRect r;
|
|
|
|
|
|
|
|
r.x = 0;
|
|
|
|
r.y = 0;
|
|
|
|
r.w = LOWORD(lParam);
|
|
|
|
r.h = HIWORD(lParam);
|
|
|
|
|
|
|
|
if (RwInitialised && r.h > 0 && r.w > 0)
|
|
|
|
{
|
|
|
|
RsEventHandler(rsCAMERASIZE, &r);
|
|
|
|
|
|
|
|
if (r.w != LOWORD(lParam) && r.h != HIWORD(lParam))
|
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
WINDOWPLACEMENT wp;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
/* failed to create window of required size */
|
|
|
|
noMemory = TRUE;
|
|
|
|
|
|
|
|
/* stop re-sizing */
|
|
|
|
ReleaseCapture();
|
|
|
|
|
|
|
|
/* handle maximised window */
|
|
|
|
GetWindowPlacement(window, &wp);
|
|
|
|
if (wp.showCmd == SW_SHOWMAXIMIZED)
|
|
|
|
{
|
|
|
|
SendMessage(window, WM_WINDOWPOSCHANGED, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
noMemory = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_SIZING:
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Handle event to ensure window contents are displayed during re-size
|
|
|
|
* as this can be disabled by the user, then if there is not enough
|
|
|
|
* memory things don't work.
|
|
|
|
*/
|
2019-06-11 05:30:53 -04:00
|
|
|
RECT *newPos = (LPRECT) lParam;
|
|
|
|
RECT rect;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
/* redraw window */
|
2019-08-15 10:51:39 -04:00
|
|
|
if (RwInitialised && (gGameState == GS_PLAYING_GAME || gGameState == GS_ANIMVIEWER))
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
2019-08-15 10:51:39 -04:00
|
|
|
RsEventHandler((gGameState == GS_PLAYING_GAME ? rsIDLE : rsANIMVIEWER), (void *)TRUE);
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Manually resize window */
|
|
|
|
rect.left = rect.top = 0;
|
|
|
|
rect.bottom = newPos->bottom - newPos->top;
|
|
|
|
rect.right = newPos->right - newPos->left;
|
|
|
|
|
|
|
|
SetWindowPos(window, HWND_TOP, rect.left, rect.top,
|
|
|
|
(rect.right - rect.left),
|
|
|
|
(rect.bottom - rect.top), SWP_NOMOVE);
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
{
|
|
|
|
SetCapture(window);
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
{
|
|
|
|
SetCapture(window);
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
{
|
|
|
|
SetCapture(window);
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_MOUSEWHEEL:
|
|
|
|
{
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_MOUSEMOVE:
|
|
|
|
{
|
|
|
|
points = MAKEPOINTS(lParam);
|
|
|
|
|
|
|
|
FrontEndMenuManager.m_nMouseTempPosX = points.x;
|
|
|
|
FrontEndMenuManager.m_nMouseTempPosY = points.y;
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_LBUTTONUP:
|
|
|
|
{
|
|
|
|
ReleaseCapture();
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_RBUTTONUP:
|
|
|
|
{
|
|
|
|
ReleaseCapture();
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_MBUTTONUP:
|
|
|
|
{
|
|
|
|
ReleaseCapture();
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
{
|
|
|
|
RsKeyCodes ks;
|
|
|
|
|
|
|
|
if ( _InputTranslateKey(&ks, lParam, wParam) )
|
|
|
|
RsKeyboardEventHandler(rsKEYDOWN, &ks);
|
|
|
|
|
|
|
|
if ( wParam == VK_SHIFT )
|
|
|
|
_InputTranslateShiftKeyUpDown(&ks);
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_KEYUP:
|
|
|
|
{
|
|
|
|
RsKeyCodes ks;
|
|
|
|
|
|
|
|
if ( _InputTranslateKey(&ks, lParam, wParam) )
|
|
|
|
RsKeyboardEventHandler(rsKEYUP, &ks);
|
|
|
|
|
|
|
|
if ( wParam == VK_SHIFT )
|
|
|
|
_InputTranslateShiftKeyUpDown(&ks);
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_SYSKEYDOWN:
|
|
|
|
{
|
|
|
|
RsKeyCodes ks;
|
|
|
|
|
|
|
|
if ( _InputTranslateKey(&ks, lParam, wParam) )
|
|
|
|
RsKeyboardEventHandler(rsKEYDOWN, &ks);
|
|
|
|
|
|
|
|
if ( wParam == VK_SHIFT )
|
|
|
|
_InputTranslateShiftKeyUpDown(&ks);
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_SYSKEYUP:
|
|
|
|
{
|
|
|
|
RsKeyCodes ks;
|
|
|
|
|
|
|
|
if ( _InputTranslateKey(&ks, lParam, wParam) )
|
|
|
|
RsKeyboardEventHandler(rsKEYUP, &ks);
|
|
|
|
|
|
|
|
if ( wParam == VK_SHIFT )
|
|
|
|
_InputTranslateShiftKeyUpDown(&ks);
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_ACTIVATEAPP:
|
|
|
|
{
|
|
|
|
switch ( gGameState )
|
|
|
|
{
|
|
|
|
case GS_LOGO_MPEG:
|
|
|
|
case GS_INTRO_MPEG:
|
|
|
|
{
|
2019-06-30 06:53:39 -04:00
|
|
|
ASSERT(pMC != nil);
|
2019-06-02 17:42:51 -04:00
|
|
|
|
2019-06-01 23:00:38 -04:00
|
|
|
LONG state;
|
|
|
|
pMC->GetState(10, &state);
|
|
|
|
|
|
|
|
if ( !(BOOL)wParam ) // losing activation
|
|
|
|
{
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( state == State_Running && pMC != nil )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
HRESULT hr = pMC->Pause();
|
|
|
|
|
|
|
|
if (hr == S_FALSE)
|
|
|
|
OutputDebugString("Failed to pause the MPEG");
|
|
|
|
else
|
|
|
|
WaitForState(State_Paused);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CenterVideo();
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( state != State_Running && pMC != nil )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
HRESULT hr = pMC->Run();
|
|
|
|
|
|
|
|
if ( hr == S_FALSE )
|
|
|
|
OutputDebugString("Failed to run the MPEG");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WaitForState(State_Running);
|
|
|
|
SetFocus(PSGLOBAL(window));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case GS_START_UP:
|
|
|
|
{
|
|
|
|
if ( !(BOOL)wParam && PSGLOBAL(fullScreen) ) // losing activation
|
|
|
|
startupDeactivate = TRUE;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CPad::GetPad(0)->Clear(false);
|
|
|
|
CPad::GetPad(1)->Clear(false);
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_TIMER:
|
|
|
|
{
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_GRAPHNOTIFY:
|
|
|
|
{
|
|
|
|
if (gGameState == GS_INTRO_MPEG || gGameState == GS_LOGO_MPEG)
|
|
|
|
HandleGraphEvent();
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
case WM_DESTROY:
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Quit message handling.
|
|
|
|
*/
|
2019-06-30 06:53:39 -04:00
|
|
|
ClipCursor(nil);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
_InputShutdown();
|
|
|
|
|
|
|
|
PostQuitMessage(0);
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_DEVICECHANGE:
|
|
|
|
{
|
|
|
|
if( wParam == DBT_DEVICEREMOVECOMPLETE )
|
|
|
|
{
|
|
|
|
PDEV_BROADCAST_HDR pDev = (PDEV_BROADCAST_HDR)lParam;
|
|
|
|
|
|
|
|
if (pDev->dbch_devicetype != DBT_DEVTYP_VOLUME)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if ( DMAudio.IsAudioInitialised() )
|
|
|
|
{
|
|
|
|
PDEV_BROADCAST_VOLUME pVol = (PDEV_BROADCAST_VOLUME)pDev;
|
|
|
|
if ( pVol->dbcv_flags & DBTF_MEDIA )
|
|
|
|
{
|
2019-06-16 18:16:38 -04:00
|
|
|
char c = DMAudio.GetCDAudioDriveLetter();
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
if ( c >= 'A' && pVol->dbcv_unitmask & (1 << (c - 'A')) )
|
|
|
|
{
|
|
|
|
OutputDebugString("About to check CD drive...");
|
|
|
|
|
|
|
|
while ( true )
|
|
|
|
{
|
|
|
|
FrontEndMenuManager.WaitForUserCD();
|
|
|
|
|
|
|
|
if ( !FrontEndMenuManager.m_bQuitGameNoCD )
|
|
|
|
{
|
|
|
|
if ( DMAudio.CheckForAnAudioFileOnCD() )
|
|
|
|
{
|
|
|
|
OutputDebugString("GTA3 Audio CD has been inserted");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OutputDebugString("Exiting game as Audio CD was not inserted");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Let Windows handle all other messages.
|
|
|
|
*/
|
|
|
|
return DefWindowProc(window, message, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
RwBool IsForegroundApp()
|
|
|
|
{
|
|
|
|
return !!ForegroundApp;
|
|
|
|
}
|
|
|
|
|
2019-06-02 17:42:51 -04:00
|
|
|
UINT GetBestRefreshRate(UINT width, UINT height, UINT depth)
|
|
|
|
{
|
|
|
|
LPDIRECT3D8 d3d = Direct3DCreate8(D3D_SDK_VERSION);
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
ASSERT(d3d != nil);
|
2019-06-02 17:42:51 -04:00
|
|
|
|
2019-07-03 07:13:55 -04:00
|
|
|
UINT refreshRate = INT_MAX;
|
2019-06-02 17:42:51 -04:00
|
|
|
D3DFORMAT format;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2019-06-02 17:42:51 -04:00
|
|
|
if ( depth == 32 )
|
|
|
|
format = D3DFMT_X8R8G8B8;
|
|
|
|
else if ( depth == 24 )
|
|
|
|
format = D3DFMT_R8G8B8;
|
|
|
|
else
|
|
|
|
format = D3DFMT_R5G6B5;
|
|
|
|
|
|
|
|
UINT modeCount = d3d->GetAdapterModeCount(GcurSel);
|
|
|
|
|
|
|
|
for ( UINT i = 0; i < modeCount; i++ )
|
|
|
|
{
|
|
|
|
D3DDISPLAYMODE mode;
|
|
|
|
|
|
|
|
d3d->EnumAdapterModes(GcurSel, i, &mode);
|
|
|
|
|
|
|
|
if ( mode.Width == width && mode.Height == height && mode.Format == format )
|
|
|
|
{
|
|
|
|
if ( mode.RefreshRate == 0 )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if ( mode.RefreshRate < refreshRate && mode.RefreshRate >= 60 )
|
|
|
|
refreshRate = mode.RefreshRate;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef FIX_BUGS
|
|
|
|
d3d->Release();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( refreshRate == -1 )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return refreshRate;
|
|
|
|
}
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
RwBool
|
|
|
|
psSelectDevice()
|
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
RwVideoMode vm;
|
|
|
|
RwInt32 subSysNum;
|
|
|
|
RwInt32 AutoRenderer = 0;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
|
|
|
|
RwBool modeFound = FALSE;
|
|
|
|
|
|
|
|
if ( !useDefault )
|
|
|
|
{
|
|
|
|
GnumSubSystems = RwEngineGetNumSubSystems();
|
|
|
|
if ( !GnumSubSystems )
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Just to be sure ... */
|
|
|
|
GnumSubSystems = (GnumSubSystems > MAX_SUBSYSTEMS) ? MAX_SUBSYSTEMS : GnumSubSystems;
|
|
|
|
|
|
|
|
/* Get the names of all the sub systems */
|
|
|
|
for (subSysNum = 0; subSysNum < GnumSubSystems; subSysNum++)
|
|
|
|
{
|
|
|
|
RwEngineGetSubSystemInfo(&GsubSysInfo[subSysNum], subSysNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the default selection */
|
|
|
|
GcurSel = RwEngineGetCurrentSubSystem();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the driver to use the correct sub system */
|
|
|
|
if (!RwEngineSetSubSystem(GcurSel))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( !useDefault )
|
|
|
|
{
|
|
|
|
if ( _psGetVideoModeList()[FrontEndMenuManager.m_nDisplayVideoMode] && FrontEndMenuManager.m_nDisplayVideoMode )
|
|
|
|
{
|
|
|
|
FrontEndMenuManager.m_nPrefsVideoMode = FrontEndMenuManager.m_nDisplayVideoMode;
|
|
|
|
GcurSelVM = FrontEndMenuManager.m_nDisplayVideoMode;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-04-15 17:44:25 -04:00
|
|
|
#ifdef DEFAULT_NATIVE_RESOLUTION
|
|
|
|
// get the native video mode
|
|
|
|
HDC hDevice = GetDC(NULL);
|
|
|
|
int w = GetDeviceCaps(hDevice, HORZRES);
|
|
|
|
int h = GetDeviceCaps(hDevice, VERTRES);
|
|
|
|
int d = GetDeviceCaps(hDevice, BITSPIXEL);
|
|
|
|
#else
|
|
|
|
const int w = 640;
|
|
|
|
const int h = 480;
|
|
|
|
const int d = 16;
|
|
|
|
#endif
|
2019-06-01 23:00:38 -04:00
|
|
|
while ( !modeFound && GcurSelVM < RwEngineGetNumVideoModes() )
|
|
|
|
{
|
|
|
|
RwEngineGetVideoModeInfo(&vm, GcurSelVM);
|
2020-04-15 17:44:25 -04:00
|
|
|
if ( defaultFullscreenRes && vm.width != w
|
|
|
|
|| vm.height != h
|
|
|
|
|| vm.depth != d
|
2019-06-01 23:00:38 -04:00
|
|
|
|| !(vm.flags & rwVIDEOMODEEXCLUSIVE) )
|
|
|
|
++GcurSelVM;
|
|
|
|
else
|
|
|
|
modeFound = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !modeFound )
|
|
|
|
{
|
2020-04-15 17:44:25 -04:00
|
|
|
#ifdef DEFAULT_NATIVE_RESOLUTION
|
|
|
|
GcurSelVM = 1;
|
|
|
|
#else
|
2019-07-02 16:05:11 -04:00
|
|
|
MessageBox(nil, "Cannot find 640x480 video mode", "GTA3", MB_OK);
|
2019-06-01 23:00:38 -04:00
|
|
|
return FALSE;
|
2020-04-15 17:44:25 -04:00
|
|
|
#endif
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RwEngineGetVideoModeInfo(&vm, GcurSelVM);
|
|
|
|
|
|
|
|
FrontEndMenuManager.m_nCurrOption = 0;
|
|
|
|
|
|
|
|
/* Set up the video mode and set the apps window
|
|
|
|
* dimensions to match */
|
|
|
|
if (!RwEngineSetVideoMode(GcurSelVM))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2020-04-17 09:31:11 -04:00
|
|
|
|
2019-06-01 23:00:38 -04:00
|
|
|
if (vm.flags & rwVIDEOMODEEXCLUSIVE)
|
|
|
|
{
|
|
|
|
debug("%dx%dx%d", vm.width, vm.height, vm.depth);
|
|
|
|
|
2019-06-02 17:42:51 -04:00
|
|
|
UINT refresh = GetBestRefreshRate(vm.width, vm.height, vm.depth);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2019-06-02 17:42:51 -04:00
|
|
|
if ( refresh != (UINT)-1 )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
debug("refresh %d", refresh);
|
2019-06-02 17:42:51 -04:00
|
|
|
RwD3D8EngineSetRefreshRate((RwUInt32)refresh);
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vm.flags & rwVIDEOMODEEXCLUSIVE)
|
|
|
|
{
|
|
|
|
RsGlobal.maximumWidth = vm.width;
|
|
|
|
RsGlobal.maximumHeight = vm.height;
|
|
|
|
RsGlobal.width = vm.width;
|
|
|
|
RsGlobal.height = vm.height;
|
|
|
|
|
|
|
|
PSGLOBAL(fullScreen) = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode)
|
|
|
|
{
|
|
|
|
RwInitialised = FALSE;
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
RsEventHandler(rsRWTERMINATE, nil);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
GcurSel = subSystem;
|
|
|
|
GcurSelVM = videoMode;
|
|
|
|
|
|
|
|
useDefault = TRUE;
|
|
|
|
|
|
|
|
if ( RsEventHandler(rsRWINITIALISE, PSGLOBAL(window)) == rsEVENTERROR )
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
RwInitialised = TRUE;
|
|
|
|
useDefault = FALSE;
|
|
|
|
|
|
|
|
RwRect r;
|
|
|
|
|
|
|
|
r.x = 0;
|
|
|
|
r.y = 0;
|
|
|
|
r.w = RsGlobal.maximumWidth;
|
|
|
|
r.h = RsGlobal.maximumHeight;
|
|
|
|
|
|
|
|
RsEventHandler(rsCAMERASIZE, &r);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
static RwChar **
|
|
|
|
CommandLineToArgv(RwChar *cmdLine, RwInt32 *argCount)
|
|
|
|
{
|
|
|
|
RwInt32 numArgs = 0;
|
|
|
|
RwBool inArg, inString;
|
|
|
|
RwInt32 i, len;
|
|
|
|
RwChar *res, *str, **aptr;
|
|
|
|
|
|
|
|
len = strlen(cmdLine);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Count the number of arguments...
|
|
|
|
*/
|
|
|
|
inString = FALSE;
|
|
|
|
inArg = FALSE;
|
|
|
|
|
|
|
|
for(i=0; i<=len; i++)
|
|
|
|
{
|
|
|
|
if( cmdLine[i] == '"' )
|
|
|
|
{
|
|
|
|
inString = !inString;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( (cmdLine[i] <= ' ' && !inString) || i == len )
|
|
|
|
{
|
|
|
|
if( inArg )
|
|
|
|
{
|
|
|
|
inArg = FALSE;
|
|
|
|
|
|
|
|
numArgs++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( !inArg )
|
|
|
|
{
|
|
|
|
inArg = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate memory for result...
|
|
|
|
*/
|
|
|
|
res = (RwChar *)malloc(sizeof(RwChar *) * numArgs + len + 1);
|
|
|
|
str = res + sizeof(RwChar *) * numArgs;
|
|
|
|
aptr = (RwChar **)res;
|
|
|
|
|
|
|
|
strcpy(str, cmdLine);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Walk through cmdLine again this time setting pointer to each arg...
|
|
|
|
*/
|
|
|
|
inArg = FALSE;
|
|
|
|
inString = FALSE;
|
|
|
|
|
|
|
|
for(i=0; i<=len; i++)
|
|
|
|
{
|
|
|
|
if( cmdLine[i] == '"' )
|
|
|
|
{
|
|
|
|
inString = !inString;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( (cmdLine[i] <= ' ' && !inString) || i == len )
|
|
|
|
{
|
|
|
|
if( inArg )
|
|
|
|
{
|
|
|
|
if( str[i-1] == '"' )
|
|
|
|
{
|
|
|
|
str[i-1] = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
str[i] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
inArg = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( !inArg && cmdLine[i] != '"' )
|
|
|
|
{
|
|
|
|
inArg = TRUE;
|
|
|
|
|
|
|
|
*aptr++ = &str[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*argCount = numArgs;
|
|
|
|
|
|
|
|
return (RwChar **)res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
void InitialiseLanguage()
|
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
WORD primUserLCID = PRIMARYLANGID(GetSystemDefaultLCID());
|
2019-06-01 23:00:38 -04:00
|
|
|
WORD primSystemLCID = PRIMARYLANGID(GetUserDefaultLCID());
|
2019-06-30 06:53:39 -04:00
|
|
|
WORD primLayout = PRIMARYLANGID((DWORD)GetKeyboardLayout(0));
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
WORD subUserLCID = SUBLANGID(GetSystemDefaultLCID());
|
|
|
|
WORD subSystemLCID = SUBLANGID(GetUserDefaultLCID());
|
2019-06-30 06:53:39 -04:00
|
|
|
WORD subLayout = SUBLANGID((DWORD)GetKeyboardLayout(0));
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
if ( primUserLCID == LANG_GERMAN
|
2019-06-01 23:00:38 -04:00
|
|
|
|| primSystemLCID == LANG_GERMAN
|
2019-06-11 05:30:53 -04:00
|
|
|
|| primLayout == LANG_GERMAN )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
CGame::nastyGame = false;
|
|
|
|
CMenuManager::m_PrefsAllowNastyGame = false;
|
|
|
|
CGame::germanGame = true;
|
|
|
|
}
|
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
if ( primUserLCID == LANG_FRENCH
|
2019-06-01 23:00:38 -04:00
|
|
|
|| primSystemLCID == LANG_FRENCH
|
2019-06-11 05:30:53 -04:00
|
|
|
|| primLayout == LANG_FRENCH )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
CGame::nastyGame = false;
|
|
|
|
CMenuManager::m_PrefsAllowNastyGame = false;
|
|
|
|
CGame::frenchGame = true;
|
|
|
|
}
|
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
if ( subUserLCID == SUBLANG_ENGLISH_AUS
|
2019-06-01 23:00:38 -04:00
|
|
|
|| subSystemLCID == SUBLANG_ENGLISH_AUS
|
2019-06-11 05:30:53 -04:00
|
|
|
|| subLayout == SUBLANG_ENGLISH_AUS )
|
2019-06-01 23:00:38 -04:00
|
|
|
CGame::noProstitutes = true;
|
2019-07-03 07:13:55 -04:00
|
|
|
|
|
|
|
#ifdef NASTY_GAME
|
|
|
|
CGame::nastyGame = true;
|
|
|
|
CMenuManager::m_PrefsAllowNastyGame = true;
|
|
|
|
CGame::noProstitutes = false;
|
|
|
|
#endif
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2019-06-16 18:16:38 -04:00
|
|
|
int32 lang;
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
switch ( primSystemLCID )
|
|
|
|
{
|
|
|
|
case LANG_GERMAN:
|
|
|
|
{
|
|
|
|
lang = LANG_GERMAN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LANG_FRENCH:
|
|
|
|
{
|
|
|
|
lang = LANG_FRENCH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LANG_SPANISH:
|
|
|
|
{
|
|
|
|
lang = LANG_SPANISH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LANG_ITALIAN:
|
|
|
|
{
|
|
|
|
lang = LANG_ITALIAN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
lang = ( subSystemLCID == SUBLANG_ENGLISH_AUS ) ? -99 : LANG_ENGLISH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CMenuManager::OS_Language = primUserLCID;
|
|
|
|
|
|
|
|
switch ( lang )
|
|
|
|
{
|
|
|
|
case LANG_GERMAN:
|
|
|
|
{
|
|
|
|
CMenuManager::m_PrefsLanguage = LANGUAGE_GERMAN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LANG_SPANISH:
|
|
|
|
{
|
|
|
|
CMenuManager::m_PrefsLanguage = LANGUAGE_SPANISH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LANG_FRENCH:
|
|
|
|
{
|
|
|
|
CMenuManager::m_PrefsLanguage = LANGUAGE_FRENCH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LANG_ITALIAN:
|
|
|
|
{
|
|
|
|
CMenuManager::m_PrefsLanguage = LANGUAGE_ITALIAN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
CMenuManager::m_PrefsLanguage = LANGUAGE_AMERICAN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TheText.Unload();
|
|
|
|
TheText.Load();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
2019-06-02 17:42:51 -04:00
|
|
|
void CenterVideo(void)
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
RECT rect;
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
ASSERT(pVW != nil);
|
2019-06-02 17:42:51 -04:00
|
|
|
|
2019-06-01 23:00:38 -04:00
|
|
|
GetClientRect(PSGLOBAL(window), &rect);
|
|
|
|
|
|
|
|
JIF(pVW->SetWindowPosition(rect.left, rect.top, rect.right, rect.bottom));
|
|
|
|
|
|
|
|
JIF(pVW->put_MessageDrain((OAHWND) PSGLOBAL(window)));
|
|
|
|
|
|
|
|
SetFocus(PSGLOBAL(window));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
2019-08-16 14:17:15 -04:00
|
|
|
void PlayMovieInWindow(int cmdShow, const char* szFile)
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
WCHAR wFileName[256];
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
// Clear open dialog remnants before calling RenderFile()
|
|
|
|
UpdateWindow(PSGLOBAL(window));
|
|
|
|
|
|
|
|
// Convert filename to wide character string
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, szFile, -1, wFileName, sizeof(wFileName) - 1);
|
|
|
|
|
|
|
|
// Initialize COM
|
2019-06-30 06:53:39 -04:00
|
|
|
JIF(CoInitialize(nil));
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
// Get the interface for DirectShow's GraphBuilder
|
2019-06-30 06:53:39 -04:00
|
|
|
JIF(CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC,
|
2019-06-01 23:00:38 -04:00
|
|
|
IID_IGraphBuilder, (void **)&pGB));
|
|
|
|
|
|
|
|
if(SUCCEEDED(hr))
|
|
|
|
{
|
|
|
|
// Have the graph builder construct its the appropriate graph automatically
|
2019-06-30 06:53:39 -04:00
|
|
|
JIF(pGB->RenderFile(&wFileName[0], nil));
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
// QueryInterface for DirectShow interfaces
|
|
|
|
JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC));
|
|
|
|
JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME));
|
|
|
|
JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS));
|
|
|
|
|
|
|
|
// Query for video interfaces, which may not be relevant for audio files
|
|
|
|
JIF(pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW));
|
|
|
|
|
|
|
|
JIF(pVW->put_Owner((OAHWND) PSGLOBAL(window)));
|
|
|
|
JIF(pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN));
|
|
|
|
|
|
|
|
// Have the graph signal event via window callbacks for performance
|
|
|
|
JIF(pME->SetNotifyWindow((OAHWND)PSGLOBAL(window), WM_GRAPHNOTIFY, 0));
|
|
|
|
|
|
|
|
CenterVideo();
|
|
|
|
|
|
|
|
// Run the graph to play the media file
|
|
|
|
JIF(pMC->Run());
|
|
|
|
|
|
|
|
SetFocus(PSGLOBAL(window));
|
|
|
|
}
|
2019-06-02 17:42:51 -04:00
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
ASSERT(pGB != nil);
|
|
|
|
ASSERT(pVW != nil);
|
|
|
|
ASSERT(pME != nil);
|
|
|
|
ASSERT(pMC != nil);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
if(FAILED(hr))
|
|
|
|
CloseClip();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
void CloseInterfaces(void)
|
|
|
|
{
|
|
|
|
// Release and zero DirectShow interfaces
|
|
|
|
SAFE_RELEASE(pME);
|
|
|
|
SAFE_RELEASE(pMS);
|
|
|
|
SAFE_RELEASE(pMC);
|
|
|
|
SAFE_RELEASE(pVW);
|
|
|
|
SAFE_RELEASE(pGB);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
void CloseClip(void)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
// Stop playback
|
|
|
|
if(pMC)
|
|
|
|
hr = pMC->Stop();
|
|
|
|
|
|
|
|
// Free DirectShow interfaces
|
|
|
|
CloseInterfaces();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
void HandleExit()
|
|
|
|
{
|
|
|
|
MSG message;
|
2019-06-30 06:53:39 -04:00
|
|
|
while ( PeekMessage(&message, nil, 0U, 0U, PM_REMOVE|PM_NOYIELD) )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
if( message.message == WM_QUIT )
|
|
|
|
{
|
|
|
|
RsGlobal.quit = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TranslateMessage(&message);
|
|
|
|
DispatchMessage(&message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
int PASCAL
|
2020-04-17 09:31:11 -04:00
|
|
|
WinMain(HINSTANCE instance,
|
2019-06-11 05:30:53 -04:00
|
|
|
HINSTANCE prevInstance __RWUNUSED__,
|
2019-06-01 23:00:38 -04:00
|
|
|
CMDSTR cmdLine,
|
|
|
|
int cmdShow)
|
|
|
|
{
|
|
|
|
MSG message;
|
|
|
|
RwV2d pos;
|
|
|
|
RwInt32 argc, i;
|
|
|
|
RwChar **argv;
|
2020-04-17 09:31:11 -04:00
|
|
|
StaticPatcher::Apply();
|
2019-06-30 06:53:39 -04:00
|
|
|
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2020-04-23 16:25:18 -04:00
|
|
|
/*
|
|
|
|
// TODO: make this an option somewhere
|
|
|
|
AllocConsole();
|
|
|
|
freopen("CONIN$", "r", stdin);
|
|
|
|
freopen("CONOUT$", "w", stdout);
|
|
|
|
freopen("CONOUT$", "w", stderr);
|
|
|
|
*/
|
|
|
|
|
2019-06-01 23:00:38 -04:00
|
|
|
/*
|
|
|
|
* Initialize the platform independent data.
|
|
|
|
* This will in turn initialize the platform specific data...
|
|
|
|
*/
|
2019-06-30 06:53:39 -04:00
|
|
|
if( RsEventHandler(rsINITIALISE, nil) == rsEVENTERROR )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Register the window class...
|
|
|
|
*/
|
|
|
|
if( !InitApplication(instance) )
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get proper command line params, cmdLine passed to us does not
|
|
|
|
* work properly under all circumstances...
|
|
|
|
*/
|
|
|
|
cmdLine = GetCommandLine();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse command line into standard (argv, argc) parameters...
|
|
|
|
*/
|
|
|
|
argv = CommandLineToArgv(cmdLine, &argc);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse command line parameters (except program name) one at
|
|
|
|
* a time BEFORE RenderWare initialization...
|
|
|
|
*/
|
|
|
|
for(i=1; i<argc; i++)
|
|
|
|
{
|
|
|
|
RsEventHandler(rsPREINITCOMMANDLINE, argv[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the window...
|
|
|
|
*/
|
|
|
|
PSGLOBAL(window) = InitInstance(instance);
|
2019-06-30 06:53:39 -04:00
|
|
|
if( PSGLOBAL(window) == nil )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PSGLOBAL(instance) = instance;
|
|
|
|
|
|
|
|
ControlsManager.MakeControllerActionsBlank();
|
|
|
|
ControlsManager.InitDefaultControlConfiguration();
|
|
|
|
|
|
|
|
if ( _InputInitialise() == S_OK )
|
|
|
|
{
|
|
|
|
_InputInitialiseMouse();
|
|
|
|
_InputInitialiseJoys();
|
|
|
|
}
|
|
|
|
|
|
|
|
ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp());
|
|
|
|
|
|
|
|
SetWindowLong(PSGLOBAL(window), GWL_STYLE, WS_POPUP);
|
2019-06-30 06:53:39 -04:00
|
|
|
SetWindowPos(PSGLOBAL(window), nil, 0, 0, 0, 0,
|
2019-06-01 23:00:38 -04:00
|
|
|
SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|
|
|
|
|
SWP_FRAMECHANGED);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize the 3D (RenderWare) components of the app...
|
|
|
|
*/
|
|
|
|
if( rsEVENTERROR == RsEventHandler(rsRWINITIALISE, PSGLOBAL(window)) )
|
|
|
|
{
|
|
|
|
DestroyWindow(PSGLOBAL(window));
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
RsEventHandler(rsTERMINATE, nil);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse command line parameters (except program name) one at
|
|
|
|
* a time AFTER RenderWare initialization...
|
|
|
|
*/
|
|
|
|
for(i=1; i<argc; i++)
|
|
|
|
{
|
|
|
|
RsEventHandler(rsCOMMANDLINE, argv[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Force a camera resize event...
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
RwRect r;
|
|
|
|
|
|
|
|
r.x = 0;
|
|
|
|
r.y = 0;
|
|
|
|
r.w = RsGlobal.maximumWidth;
|
|
|
|
r.h = RsGlobal.maximumHeight;
|
|
|
|
|
|
|
|
RsEventHandler(rsCAMERASIZE, &r);
|
|
|
|
}
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, nil, SPIF_SENDCHANGE);
|
|
|
|
SystemParametersInfo(SPI_SETPOWEROFFACTIVE, FALSE, nil, SPIF_SENDCHANGE);
|
|
|
|
SystemParametersInfo(SPI_SETLOWPOWERACTIVE, FALSE, nil, SPIF_SENDCHANGE);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
|
|
|
|
STICKYKEYS SavedStickyKeys;
|
|
|
|
SavedStickyKeys.cbSize = sizeof(STICKYKEYS);
|
|
|
|
|
|
|
|
SystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(STICKYKEYS), &SavedStickyKeys, SPIF_SENDCHANGE);
|
|
|
|
|
|
|
|
STICKYKEYS NewStickyKeys;
|
|
|
|
NewStickyKeys.cbSize = sizeof(STICKYKEYS);
|
|
|
|
NewStickyKeys.dwFlags = SKF_TWOKEYSOFF;
|
|
|
|
|
|
|
|
SystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &NewStickyKeys, SPIF_SENDCHANGE);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Show the window, and refresh it...
|
|
|
|
*/
|
|
|
|
ShowWindow(PSGLOBAL(window), cmdShow);
|
|
|
|
UpdateWindow(PSGLOBAL(window));
|
|
|
|
|
|
|
|
{
|
|
|
|
CFileMgr::SetDirMyDocuments();
|
|
|
|
|
2019-06-16 18:16:38 -04:00
|
|
|
int32 gta3set = CFileMgr::OpenFile("gta3.set", "r");
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
if ( gta3set )
|
|
|
|
{
|
|
|
|
ControlsManager.LoadSettings(gta3set);
|
|
|
|
CFileMgr::CloseFile(gta3set);
|
|
|
|
}
|
|
|
|
|
|
|
|
CFileMgr::SetDir("");
|
|
|
|
}
|
|
|
|
|
|
|
|
SetErrorMode(SEM_FAILCRITICALERRORS);
|
2019-06-02 17:42:51 -04:00
|
|
|
|
2019-08-15 10:51:39 -04:00
|
|
|
if (!TurnOnAnimViewer) {
|
2019-06-02 18:25:46 -04:00
|
|
|
#ifdef NO_MOVIES
|
2019-08-15 10:51:39 -04:00
|
|
|
gGameState = GS_INIT_FRONTEND;
|
|
|
|
TRACE("gGameState = GS_INIT_FRONTEND");
|
|
|
|
|
|
|
|
LoadingScreen(nil, nil, "loadsc0");
|
|
|
|
if (!CGame::InitialiseOnceAfterRW())
|
|
|
|
RsGlobal.quit = TRUE;
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
#ifndef MASTER
|
|
|
|
CAnimViewer::Initialise();
|
|
|
|
FrontEndMenuManager.m_bGameNotLoaded = false;
|
|
|
|
gGameState = GS_ANIMVIEWER;
|
|
|
|
TurnOnAnimViewer = false;
|
|
|
|
#endif
|
|
|
|
}
|
2019-06-02 18:25:46 -04:00
|
|
|
|
2019-06-01 23:00:38 -04:00
|
|
|
while ( TRUE )
|
|
|
|
{
|
|
|
|
RwInitialised = TRUE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the initial mouse position...
|
|
|
|
*/
|
|
|
|
pos.x = RsGlobal.maximumWidth * 0.5f;
|
|
|
|
pos.y = RsGlobal.maximumHeight * 0.5f;
|
|
|
|
|
|
|
|
RsMouseSetPos(&pos);
|
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
WINDOWPLACEMENT wp;
|
2019-06-01 23:00:38 -04:00
|
|
|
wp.length = sizeof(WINDOWPLACEMENT);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Enter the message processing loop...
|
|
|
|
*/
|
|
|
|
|
2020-04-08 19:52:38 -04:00
|
|
|
while( !RsGlobal.quit && !FrontEndMenuManager.m_bWantToRestart )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
2019-06-30 06:53:39 -04:00
|
|
|
if( PeekMessage(&message, nil, 0U, 0U, PM_REMOVE|PM_NOYIELD) )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
if( message.message == WM_QUIT )
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TranslateMessage(&message);
|
|
|
|
DispatchMessage(&message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( ForegroundApp )
|
2019-06-02 17:42:51 -04:00
|
|
|
{
|
2019-06-01 23:00:38 -04:00
|
|
|
switch ( gGameState )
|
|
|
|
{
|
|
|
|
case GS_START_UP:
|
|
|
|
{
|
|
|
|
gGameState = GS_INIT_LOGO_MPEG;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_INIT_LOGO_MPEG");
|
2019-06-01 23:00:38 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case GS_INIT_LOGO_MPEG:
|
|
|
|
{
|
|
|
|
if ( !startupDeactivate )
|
|
|
|
PlayMovieInWindow(cmdShow, "movies\\Logo.mpg");
|
|
|
|
gGameState = GS_LOGO_MPEG;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_LOGO_MPEG;");
|
2019-06-01 23:00:38 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case GS_LOGO_MPEG:
|
|
|
|
{
|
|
|
|
CPad::UpdatePads();
|
2019-06-02 17:42:51 -04:00
|
|
|
|
|
|
|
if ( startupDeactivate || ControlsManager.GetJoyButtonJustDown() != 0 )
|
2019-06-01 23:00:38 -04:00
|
|
|
++gGameState;
|
|
|
|
else if ( CPad::GetPad(0)->GetLeftMouseJustDown() )
|
|
|
|
++gGameState;
|
2019-10-29 11:21:02 -04:00
|
|
|
else if ( CPad::GetPad(0)->GetEnterJustDown() )
|
2019-06-01 23:00:38 -04:00
|
|
|
++gGameState;
|
2020-04-21 06:28:06 -04:00
|
|
|
else if ( CPad::GetPad(0)->GetCharJustDown(' ') )
|
2019-06-01 23:00:38 -04:00
|
|
|
++gGameState;
|
2019-10-29 11:21:02 -04:00
|
|
|
else if ( CPad::GetPad(0)->GetAltJustDown() )
|
2019-06-01 23:00:38 -04:00
|
|
|
++gGameState;
|
|
|
|
else if ( CPad::GetPad(0)->GetTabJustDown() )
|
|
|
|
++gGameState;
|
2019-06-02 17:42:51 -04:00
|
|
|
|
|
|
|
break;
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
case GS_INIT_INTRO_MPEG:
|
|
|
|
{
|
|
|
|
CloseClip();
|
|
|
|
|
|
|
|
CoUninitialize();
|
|
|
|
|
|
|
|
if ( CMenuManager::OS_Language == LANG_FRENCH || CMenuManager::OS_Language == LANG_GERMAN )
|
|
|
|
PlayMovieInWindow(cmdShow, "movies\\GTAtitlesGER.mpg");
|
|
|
|
else
|
|
|
|
PlayMovieInWindow(cmdShow, "movies\\GTAtitles.mpg");
|
|
|
|
|
|
|
|
gGameState = GS_INTRO_MPEG;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_INTRO_MPEG;");
|
2019-06-01 23:00:38 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case GS_INTRO_MPEG:
|
|
|
|
{
|
|
|
|
CPad::UpdatePads();
|
2019-06-02 17:42:51 -04:00
|
|
|
|
|
|
|
if ( startupDeactivate || ControlsManager.GetJoyButtonJustDown() != 0 )
|
2019-06-01 23:00:38 -04:00
|
|
|
++gGameState;
|
|
|
|
else if ( CPad::GetPad(0)->GetLeftMouseJustDown() )
|
|
|
|
++gGameState;
|
2019-10-29 11:21:02 -04:00
|
|
|
else if ( CPad::GetPad(0)->GetEnterJustDown() )
|
2019-06-01 23:00:38 -04:00
|
|
|
++gGameState;
|
2020-04-21 06:28:06 -04:00
|
|
|
else if ( CPad::GetPad(0)->GetCharJustDown(' ') )
|
2019-06-01 23:00:38 -04:00
|
|
|
++gGameState;
|
2019-10-29 11:21:02 -04:00
|
|
|
else if ( CPad::GetPad(0)->GetAltJustDown() )
|
2019-06-01 23:00:38 -04:00
|
|
|
++gGameState;
|
|
|
|
else if ( CPad::GetPad(0)->GetTabJustDown() )
|
|
|
|
++gGameState;
|
2019-06-02 17:42:51 -04:00
|
|
|
|
|
|
|
break;
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
case GS_INIT_ONCE:
|
|
|
|
{
|
|
|
|
CloseClip();
|
|
|
|
CoUninitialize();
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
LoadingScreen(nil, nil, "loadsc0");
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
if ( !CGame::InitialiseOnceAfterRW() )
|
|
|
|
RsGlobal.quit = TRUE;
|
|
|
|
|
|
|
|
gGameState = GS_INIT_FRONTEND;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_INIT_FRONTEND;");
|
2019-06-01 23:00:38 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case GS_INIT_FRONTEND:
|
|
|
|
{
|
2019-06-30 06:53:39 -04:00
|
|
|
LoadingScreen(nil, nil, "loadsc0");
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
FrontEndMenuManager.m_bGameNotLoaded = true;
|
|
|
|
|
|
|
|
CMenuManager::m_bStartUpFrontEndRequested = true;
|
|
|
|
|
|
|
|
if ( defaultFullscreenRes )
|
|
|
|
{
|
2019-06-02 17:42:51 -04:00
|
|
|
defaultFullscreenRes = FALSE;
|
2019-06-01 23:00:38 -04:00
|
|
|
FrontEndMenuManager.m_nPrefsVideoMode = GcurSelVM;
|
|
|
|
FrontEndMenuManager.m_nDisplayVideoMode = GcurSelVM;
|
|
|
|
}
|
|
|
|
|
|
|
|
gGameState = GS_FRONTEND;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_FRONTEND;");
|
2019-06-01 23:00:38 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case GS_FRONTEND:
|
|
|
|
{
|
|
|
|
GetWindowPlacement(PSGLOBAL(window), &wp);
|
|
|
|
|
2020-03-28 16:28:36 -04:00
|
|
|
if (wp.showCmd != SW_SHOWMINIMIZED)
|
2019-06-30 06:53:39 -04:00
|
|
|
RsEventHandler(rsFRONTENDIDLE, nil);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2020-04-08 19:52:38 -04:00
|
|
|
if ( !FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bWantToLoad )
|
2019-06-02 17:42:51 -04:00
|
|
|
{
|
2019-06-01 23:00:38 -04:00
|
|
|
gGameState = GS_INIT_PLAYING_GAME;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_INIT_PLAYING_GAME;");
|
|
|
|
}
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2020-04-08 19:52:38 -04:00
|
|
|
if ( FrontEndMenuManager.m_bWantToLoad )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
InitialiseGame();
|
|
|
|
FrontEndMenuManager.m_bGameNotLoaded = false;
|
|
|
|
gGameState = GS_PLAYING_GAME;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_PLAYING_GAME;");
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case GS_INIT_PLAYING_GAME:
|
|
|
|
{
|
|
|
|
InitialiseGame();
|
|
|
|
FrontEndMenuManager.m_bGameNotLoaded = false;
|
|
|
|
gGameState = GS_PLAYING_GAME;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_PLAYING_GAME;");
|
2019-06-01 23:00:38 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case GS_PLAYING_GAME:
|
|
|
|
{
|
2019-06-16 18:16:38 -04:00
|
|
|
float ms = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond();
|
2019-06-01 23:00:38 -04:00
|
|
|
if ( RwInitialised )
|
|
|
|
{
|
2019-06-16 18:16:38 -04:00
|
|
|
if (!CMenuManager::m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms)
|
2019-06-01 23:00:38 -04:00
|
|
|
RsEventHandler(rsIDLE, (void *)TRUE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2019-08-15 10:51:39 -04:00
|
|
|
#ifndef MASTER
|
|
|
|
case GS_ANIMVIEWER:
|
|
|
|
{
|
|
|
|
float ms = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond();
|
|
|
|
if (RwInitialised)
|
|
|
|
{
|
|
|
|
if (!CMenuManager::m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms)
|
|
|
|
RsEventHandler(rsANIMVIEWER, (void*)TRUE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( RwCameraBeginUpdate(Scene.camera) )
|
|
|
|
{
|
|
|
|
RwCameraEndUpdate(Scene.camera);
|
|
|
|
ForegroundApp = TRUE;
|
|
|
|
RsEventHandler(rsACTIVATE, (void *)TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
WaitMessage();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* About to shut down - block resize events again...
|
|
|
|
*/
|
|
|
|
RwInitialised = FALSE;
|
|
|
|
|
|
|
|
FrontEndMenuManager.UnloadTextures();
|
2020-04-08 19:52:38 -04:00
|
|
|
if ( !FrontEndMenuManager.m_bWantToRestart )
|
2019-06-01 23:00:38 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
CPad::ResetCheats();
|
|
|
|
CPad::StopPadsShaking();
|
|
|
|
|
2020-02-06 12:35:24 -05:00
|
|
|
DMAudio.ChangeMusicMode(MUSICMODE_DISABLE);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
CTimer::Stop();
|
|
|
|
|
2020-04-08 19:52:38 -04:00
|
|
|
if ( FrontEndMenuManager.m_bWantToLoad )
|
2019-06-01 23:00:38 -04:00
|
|
|
{
|
|
|
|
CGame::ShutDownForRestart();
|
|
|
|
CGame::InitialiseWhenRestarting();
|
2019-10-26 08:20:12 -04:00
|
|
|
DMAudio.ChangeMusicMode(MUSICMODE_GAME);
|
2019-06-01 23:00:38 -04:00
|
|
|
LoadSplash(GetLevelSplashScreen(CGame::currLevel));
|
2020-04-08 19:52:38 -04:00
|
|
|
FrontEndMenuManager.m_bWantToLoad = false;
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( gGameState == GS_PLAYING_GAME )
|
|
|
|
CGame::ShutDown();
|
2019-08-15 10:51:39 -04:00
|
|
|
else if ( gGameState == GS_ANIMVIEWER )
|
|
|
|
CAnimViewer::Shutdown();
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
CTimer::Stop();
|
|
|
|
|
|
|
|
if ( FrontEndMenuManager.m_bFirstTime == true )
|
2019-06-02 17:42:51 -04:00
|
|
|
{
|
2019-06-01 23:00:38 -04:00
|
|
|
gGameState = GS_INIT_FRONTEND;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_INIT_FRONTEND;");
|
|
|
|
}
|
2019-06-01 23:00:38 -04:00
|
|
|
else
|
2019-06-02 17:42:51 -04:00
|
|
|
{
|
2019-06-01 23:00:38 -04:00
|
|
|
gGameState = GS_INIT_PLAYING_GAME;
|
2019-06-02 17:42:51 -04:00
|
|
|
TRACE("gGameState = GS_INIT_PLAYING_GAME;");
|
|
|
|
}
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
FrontEndMenuManager.m_bFirstTime = false;
|
2020-04-08 19:52:38 -04:00
|
|
|
FrontEndMenuManager.m_bWantToRestart = false;
|
2019-06-01 23:00:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( gGameState == GS_PLAYING_GAME )
|
|
|
|
CGame::ShutDown();
|
2019-08-15 10:51:39 -04:00
|
|
|
else if ( gGameState == GS_ANIMVIEWER )
|
|
|
|
CAnimViewer::Shutdown();
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
DMAudio.Terminate();
|
|
|
|
|
|
|
|
_psFreeVideoModeList();
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Tidy up the 3D (RenderWare) components of the application...
|
|
|
|
*/
|
2019-06-30 06:53:39 -04:00
|
|
|
RsEventHandler(rsRWTERMINATE, nil);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Kill the window...
|
|
|
|
*/
|
|
|
|
DestroyWindow(PSGLOBAL(window));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Free the platform dependent data...
|
|
|
|
*/
|
2019-06-30 06:53:39 -04:00
|
|
|
RsEventHandler(rsTERMINATE, nil);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Free the argv strings...
|
|
|
|
*/
|
|
|
|
free(argv);
|
|
|
|
|
|
|
|
ShowCursor(TRUE);
|
|
|
|
|
|
|
|
SystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &SavedStickyKeys, SPIF_SENDCHANGE);
|
2019-06-30 06:53:39 -04:00
|
|
|
SystemParametersInfo(SPI_SETPOWEROFFACTIVE, TRUE, nil, SPIF_SENDCHANGE);
|
|
|
|
SystemParametersInfo(SPI_SETLOWPOWERACTIVE, TRUE, nil, SPIF_SENDCHANGE);
|
|
|
|
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, TRUE, nil, SPIF_SENDCHANGE);
|
2019-06-01 23:00:38 -04:00
|
|
|
|
|
|
|
SetErrorMode(0);
|
|
|
|
|
|
|
|
return message.wParam;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*****************************************************************************
|
|
|
|
*/
|
|
|
|
|
2019-06-05 15:18:06 -04:00
|
|
|
#define DEVICE_AXIS_MIN -2000
|
|
|
|
#define DEVICE_AXIS_MAX 2000
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT _InputInitialise()
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
// Create a DInput object
|
2019-06-30 06:53:39 -04:00
|
|
|
if( FAILED( hr = DirectInput8Create( GetModuleHandle(nil), DIRECTINPUT_VERSION,
|
|
|
|
IID_IDirectInput8, (VOID**)&PSGLOBAL(dinterface), nil ) ) )
|
2019-06-05 15:18:06 -04:00
|
|
|
return hr;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT _InputInitialiseMouse()
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
// Obtain an interface to the system mouse device.
|
2019-06-30 06:53:39 -04:00
|
|
|
if( FAILED( hr = PSGLOBAL(dinterface)->CreateDevice( GUID_SysMouse, &PSGLOBAL(mouse), nil ) ) )
|
2019-06-05 15:18:06 -04:00
|
|
|
return hr;
|
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
// 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 = PSGLOBAL(mouse)->SetDataFormat( &c_dfDIMouse2 ) ) )
|
|
|
|
return hr;
|
2019-06-05 15:18:06 -04:00
|
|
|
|
2019-06-05 15:28:54 -04:00
|
|
|
if( FAILED( hr = PSGLOBAL(mouse)->SetCooperativeLevel( PSGLOBAL(window), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND ) ) )
|
2019-06-05 15:18:06 -04:00
|
|
|
return hr;
|
|
|
|
|
|
|
|
// Acquire the newly created device
|
2019-06-11 05:30:53 -04:00
|
|
|
PSGLOBAL(mouse)->Acquire();
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
RwV2d leftStickPos;
|
|
|
|
RwV2d rightStickPos;
|
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
HRESULT CapturePad(RwInt32 padID)
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
HRESULT hr;
|
2019-06-05 15:18:06 -04:00
|
|
|
DIJOYSTATE2 js;
|
2019-07-25 06:38:25 -04:00
|
|
|
LPDIRECTINPUTDEVICE8 *pPad = nil;
|
|
|
|
|
|
|
|
if( padID == 0 )
|
|
|
|
pPad = &PSGLOBAL(joy1);
|
|
|
|
else if( padID == 1)
|
|
|
|
pPad = &PSGLOBAL(joy2);
|
|
|
|
else
|
|
|
|
assert("invalid padID");
|
2019-06-05 15:18:06 -04:00
|
|
|
|
2019-07-25 06:38:25 -04:00
|
|
|
if ( nil == (*pPad) )
|
2019-06-05 15:18:06 -04:00
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
// Poll the device to read the current state
|
2019-07-25 06:38:25 -04:00
|
|
|
hr = (*pPad)->Poll();
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
if( FAILED(hr) )
|
2019-06-11 05:30:53 -04:00
|
|
|
{
|
|
|
|
// DInput is telling us that the input stream has been
|
|
|
|
// interrupted. We aren't tracking any state between polls, so
|
|
|
|
// we don't have any special reset that needs to be done. We
|
|
|
|
// just re-acquire and try again.
|
2019-07-25 06:38:25 -04:00
|
|
|
hr = (*pPad)->Acquire();
|
2019-06-11 05:30:53 -04:00
|
|
|
while( hr == DIERR_INPUTLOST )
|
2019-07-25 06:38:25 -04:00
|
|
|
hr = (*pPad)->Acquire();
|
2019-06-11 05:30:53 -04:00
|
|
|
|
|
|
|
// 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
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
if( FAILED(hr) )
|
|
|
|
return hr;
|
|
|
|
|
2019-07-25 06:38:25 -04:00
|
|
|
hr = (*pPad)->Poll();
|
2019-06-05 15:18:06 -04:00
|
|
|
if( FAILED(hr) )
|
|
|
|
return hr;
|
2019-06-11 05:30:53 -04:00
|
|
|
}
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
// Get the input's device state
|
2019-07-25 06:38:25 -04:00
|
|
|
if( FAILED( hr = (*pPad)->GetDeviceState( sizeof(DIJOYSTATE2), &js ) ) )
|
2019-06-11 05:30:53 -04:00
|
|
|
return hr; // The device should have been acquired during the Poll()
|
2019-06-05 15:18:06 -04:00
|
|
|
|
2019-10-26 23:17:30 -04:00
|
|
|
if ( ControlsManager.m_bFirstCapture == true )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
|
|
|
memcpy(&ControlsManager.m_OldState, &js, sizeof(DIJOYSTATE2));
|
|
|
|
memcpy(&ControlsManager.m_NewState, &js, sizeof(DIJOYSTATE2));
|
|
|
|
|
2019-10-26 23:17:30 -04:00
|
|
|
ControlsManager.m_bFirstCapture = false;
|
2019-06-05 15:18:06 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(&ControlsManager.m_OldState, &ControlsManager.m_NewState, sizeof(DIJOYSTATE2));
|
2019-07-25 06:38:25 -04:00
|
|
|
memcpy(&ControlsManager.m_NewState, &js, sizeof(DIJOYSTATE2));
|
2019-06-05 15:18:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
RsPadButtonStatus bs;
|
|
|
|
bs.padID = padID;
|
|
|
|
|
|
|
|
RsPadEventHandler(rsPADBUTTONUP, (void *)&bs);
|
|
|
|
|
2019-07-25 06:38:25 -04:00
|
|
|
bool deviceAvailable = (*pPad) != nil;
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
if ( deviceAvailable )
|
|
|
|
{
|
2019-06-16 18:16:38 -04:00
|
|
|
leftStickPos.x = (float)js.lX / (float)((DEVICE_AXIS_MAX - DEVICE_AXIS_MIN) / 2);
|
|
|
|
leftStickPos.y = (float)js.lY / (float)((DEVICE_AXIS_MAX - DEVICE_AXIS_MIN) / 2);
|
2019-06-05 15:18:06 -04:00
|
|
|
|
2019-07-25 06:38:25 -04:00
|
|
|
if (LOWORD(js.rgdwPOV[0]) != 0xFFFF)
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
2019-06-16 18:16:38 -04:00
|
|
|
float angle = DEGTORAD((float)js.rgdwPOV[0] / 100.0f);
|
2019-06-05 15:18:06 -04:00
|
|
|
|
2019-07-10 11:18:26 -04:00
|
|
|
leftStickPos.x = Sin(angle);
|
2019-07-10 11:34:11 -04:00
|
|
|
leftStickPos.y = -Cos(angle);
|
2019-06-05 15:18:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( AllValidWinJoys.m_aJoys[bs.padID].m_bHasAxisR && AllValidWinJoys.m_aJoys[bs.padID].m_bHasAxisZ )
|
|
|
|
{
|
2019-06-16 18:16:38 -04:00
|
|
|
rightStickPos.x = (float)js.lZ / (float)((DEVICE_AXIS_MAX - DEVICE_AXIS_MIN) / 2);
|
|
|
|
rightStickPos.y = (float)js.lRz / (float)((DEVICE_AXIS_MAX - DEVICE_AXIS_MIN) / 2);
|
2019-06-05 15:18:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
if (CPad::m_bMapPadOneToPadTwo)
|
|
|
|
bs.padID = 1;
|
|
|
|
|
|
|
|
RsPadEventHandler(rsPADBUTTONUP, (void *)&bs);
|
|
|
|
RsPadEventHandler(rsPADBUTTONDOWN, (void *)&bs);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
if (CPad::m_bMapPadOneToPadTwo)
|
|
|
|
bs.padID = 1;
|
|
|
|
|
|
|
|
CPad *pad = CPad::GetPad(bs.padID);
|
|
|
|
|
2019-07-10 11:18:26 -04:00
|
|
|
if ( Abs(leftStickPos.x) > 0.3f )
|
2019-06-16 18:16:38 -04:00
|
|
|
pad->PCTempJoyState.LeftStickX = (int32)(leftStickPos.x * 128.0f);
|
2019-06-05 15:18:06 -04:00
|
|
|
|
2019-07-10 11:18:26 -04:00
|
|
|
if ( Abs(leftStickPos.y) > 0.3f )
|
2019-06-16 18:16:38 -04:00
|
|
|
pad->PCTempJoyState.LeftStickY = (int32)(leftStickPos.y * 128.0f);
|
2019-06-05 15:18:06 -04:00
|
|
|
|
2019-07-10 11:18:26 -04:00
|
|
|
if ( Abs(rightStickPos.x) > 0.3f )
|
2019-06-16 18:16:38 -04:00
|
|
|
pad->PCTempJoyState.RightStickX = (int32)(rightStickPos.x * 128.0f);
|
2019-06-05 15:18:06 -04:00
|
|
|
|
2019-07-10 11:18:26 -04:00
|
|
|
if ( Abs(rightStickPos.y) > 0.3f )
|
2019-06-16 18:16:38 -04:00
|
|
|
pad->PCTempJoyState.RightStickY = (int32)(rightStickPos.y * 128.0f);
|
2019-06-05 15:18:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _InputInitialiseJoys()
|
|
|
|
{
|
|
|
|
DIPROPDWORD prop;
|
|
|
|
DIDEVCAPS devCaps;
|
|
|
|
|
2019-06-16 18:16:38 -04:00
|
|
|
for ( int32 i = 0; i < _TODOCONST(2); i++ )
|
2019-06-05 15:18:06 -04:00
|
|
|
AllValidWinJoys.ClearJoyInfo(i);
|
|
|
|
|
|
|
|
_InputAddJoys();
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( PSGLOBAL(joy1) != nil )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
|
|
|
devCaps.dwSize = sizeof(DIDEVCAPS);
|
2019-06-05 15:28:54 -04:00
|
|
|
PSGLOBAL(joy1)->GetCapabilities(&devCaps);
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
prop.diph.dwSize = sizeof(DIPROPDWORD);
|
|
|
|
prop.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
|
|
|
prop.diph.dwObj = 0;
|
|
|
|
prop.diph.dwHow = 0;
|
|
|
|
|
2019-06-05 15:28:54 -04:00
|
|
|
PSGLOBAL(joy1)->GetProperty(DIPROP_VIDPID, (LPDIPROPHEADER)&prop);
|
2019-06-05 15:18:06 -04:00
|
|
|
AllValidWinJoys.m_aJoys[0].m_nVendorID = LOWORD(prop.dwData);
|
|
|
|
AllValidWinJoys.m_aJoys[0].m_nProductID = HIWORD(prop.dwData);
|
|
|
|
AllValidWinJoys.m_aJoys[0].m_bInitialised = true;
|
|
|
|
|
|
|
|
ControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons);
|
|
|
|
}
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( PSGLOBAL(joy2) != nil )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
2019-06-05 15:28:54 -04:00
|
|
|
PSGLOBAL(joy2)->GetProperty(DIPROP_VIDPID, (LPDIPROPHEADER)&prop);
|
2019-06-05 15:18:06 -04:00
|
|
|
AllValidWinJoys.m_aJoys[1].m_nVendorID = LOWORD(prop.dwData);
|
|
|
|
AllValidWinJoys.m_aJoys[1].m_nProductID = HIWORD(prop.dwData);
|
|
|
|
AllValidWinJoys.m_aJoys[1].m_bInitialised = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-03 07:13:55 -04:00
|
|
|
void _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num)
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
|
|
|
DIDEVICEOBJECTINSTANCE objInst;
|
2019-07-03 07:13:55 -04:00
|
|
|
|
2019-06-05 15:18:06 -04:00
|
|
|
objInst.dwSize = sizeof( DIDEVICEOBJECTINSTANCE );
|
|
|
|
|
|
|
|
DIPROPRANGE range;
|
|
|
|
range.diph.dwSize = sizeof(DIPROPRANGE);
|
|
|
|
range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
|
|
|
range.lMin = DEVICE_AXIS_MIN;
|
|
|
|
range.lMax = DEVICE_AXIS_MAX;
|
|
|
|
range.diph.dwHow = DIPH_BYOFFSET;
|
|
|
|
|
|
|
|
// get the info about the object from the device
|
|
|
|
|
|
|
|
range.diph.dwObj = DIJOFS_X;
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( lpDevice != nil )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
if ( SUCCEEDED( lpDevice->GetObjectInfo( &objInst, DIJOFS_X, DIPH_BYOFFSET ) ) )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
|
|
|
if( FAILED( lpDevice->SetProperty( DIPROP_RANGE, (LPCDIPROPHEADER)&range ) ) )
|
2019-07-03 07:13:55 -04:00
|
|
|
return;
|
2019-06-05 15:18:06 -04:00
|
|
|
else
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
range.diph.dwObj = DIJOFS_Y;
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( lpDevice != nil )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
if ( SUCCEEDED( lpDevice->GetObjectInfo( &objInst, DIJOFS_Y, DIPH_BYOFFSET ) ) )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
|
|
|
if( FAILED( lpDevice->SetProperty( DIPROP_RANGE, (LPCDIPROPHEADER)&range ) ) )
|
2019-07-03 07:13:55 -04:00
|
|
|
return;
|
2019-06-05 15:18:06 -04:00
|
|
|
else
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
range.diph.dwObj = DIJOFS_Z;
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( lpDevice != nil )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
if ( SUCCEEDED( lpDevice->GetObjectInfo( &objInst, DIJOFS_Z, DIPH_BYOFFSET ) ) )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
|
|
|
if( FAILED( lpDevice->SetProperty( DIPROP_RANGE, (LPCDIPROPHEADER)&range ) ) )
|
2019-07-03 07:13:55 -04:00
|
|
|
return;
|
2019-06-05 15:18:06 -04:00
|
|
|
else
|
|
|
|
AllValidWinJoys.m_aJoys[num].m_bHasAxisZ = true; // z rightStickPos.x
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
range.diph.dwObj = DIJOFS_RZ;
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( lpDevice != nil )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
if ( SUCCEEDED( lpDevice->GetObjectInfo( &objInst, DIJOFS_RZ, DIPH_BYOFFSET ) ) )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
|
|
|
if( FAILED( lpDevice->SetProperty( DIPROP_RANGE, (LPCDIPROPHEADER)&range ) ) )
|
2019-07-03 07:13:55 -04:00
|
|
|
return;
|
2019-06-05 15:18:06 -04:00
|
|
|
else
|
2019-06-11 05:30:53 -04:00
|
|
|
AllValidWinJoys.m_aJoys[num].m_bHasAxisR = true; // r rightStickPos.y
|
2019-06-05 15:18:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT _InputAddJoys()
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
hr = PSGLOBAL(dinterface)->EnumDevices(DI8DEVCLASS_GAMECTRL, _InputEnumDevicesCallback, nil, DIEDFL_ATTACHEDONLY );
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
if( FAILED(hr) )
|
|
|
|
return hr;
|
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( PSGLOBAL(joy1) == nil )
|
2019-06-05 15:18:06 -04:00
|
|
|
return S_FALSE;
|
|
|
|
|
2019-06-05 15:28:54 -04:00
|
|
|
_InputAddJoyStick(PSGLOBAL(joy1), 0);
|
2019-06-05 15:18:06 -04:00
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( PSGLOBAL(joy2) == nil )
|
2019-06-05 15:18:06 -04:00
|
|
|
return S_OK; // we have one device already so return OK and ignore second
|
|
|
|
|
2019-06-05 15:28:54 -04:00
|
|
|
_InputAddJoyStick(PSGLOBAL(joy2), 1);
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT _InputGetMouseState(DIMOUSESTATE2 *state)
|
|
|
|
{
|
2019-06-11 05:30:53 -04:00
|
|
|
HRESULT hr;
|
2019-06-05 15:18:06 -04:00
|
|
|
|
2019-06-30 06:53:39 -04:00
|
|
|
if ( PSGLOBAL(mouse) == nil )
|
2019-06-05 15:18:06 -04:00
|
|
|
return S_FALSE;
|
|
|
|
|
|
|
|
// Get the input's device state, and put the state in dims
|
|
|
|
ZeroMemory( state, sizeof(DIMOUSESTATE2) );
|
|
|
|
|
2019-06-05 15:28:54 -04:00
|
|
|
hr = PSGLOBAL(mouse)->GetDeviceState( sizeof(DIMOUSESTATE2), state );
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
if( FAILED(hr) )
|
2019-06-11 05:30:53 -04:00
|
|
|
{
|
2019-06-05 15:18:06 -04:00
|
|
|
// DirectInput may be telling us that the input stream has been
|
2019-06-11 05:30:53 -04:00
|
|
|
// interrupted. We aren't tracking any state between polls, so
|
|
|
|
// we don't have any special reset that needs to be done.
|
|
|
|
// We just re-acquire and try again.
|
|
|
|
|
|
|
|
// If input is lost then acquire and keep trying
|
2019-06-05 15:28:54 -04:00
|
|
|
hr = PSGLOBAL(mouse)->Acquire();
|
2019-06-11 05:30:53 -04:00
|
|
|
while( hr == DIERR_INPUTLOST )
|
|
|
|
hr = PSGLOBAL(mouse)->Acquire();
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
ZeroMemory( state, sizeof(DIMOUSESTATE2) );
|
2019-06-05 15:28:54 -04:00
|
|
|
hr = PSGLOBAL(mouse)->GetDeviceState( sizeof(DIMOUSESTATE2), state );
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _InputShutdown()
|
|
|
|
{
|
2019-06-05 15:28:54 -04:00
|
|
|
SAFE_RELEASE(PSGLOBAL(dinterface));
|
2019-06-05 15:18:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL CALLBACK _InputEnumDevicesCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext )
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
static INT Count = 0;
|
|
|
|
|
2019-07-25 06:38:25 -04:00
|
|
|
LPDIRECTINPUTDEVICE8 *pJoystick = nil;
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
if ( Count == 0 )
|
2019-07-25 06:38:25 -04:00
|
|
|
pJoystick = &PSGLOBAL(joy1);
|
2019-06-05 15:18:06 -04:00
|
|
|
else if ( Count == 1 )
|
2019-07-25 06:38:25 -04:00
|
|
|
pJoystick = &PSGLOBAL(joy2);
|
|
|
|
else
|
|
|
|
assert("too many pads");
|
2019-06-05 15:18:06 -04:00
|
|
|
|
|
|
|
// Obtain an interface to the enumerated joystick.
|
2019-07-25 06:38:25 -04:00
|
|
|
hr = PSGLOBAL(dinterface)->CreateDevice( pdidInstance->guidInstance, pJoystick, nil );
|
2019-06-05 15:18:06 -04:00
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
// If it failed, then we can't use this joystick. (Maybe the user unplugged
|
|
|
|
// it while we were in the middle of enumerating it.)
|
2019-07-25 06:38:25 -04:00
|
|
|
if( hr != S_OK )
|
2019-06-11 05:30:53 -04:00
|
|
|
return DIENUM_CONTINUE;
|
2019-07-25 06:38:25 -04:00
|
|
|
|
|
|
|
hr = (*pJoystick)->SetDataFormat( &c_dfDIJoystick2 );
|
|
|
|
if( hr != S_OK )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
2019-07-25 06:38:25 -04:00
|
|
|
(*pJoystick)->Release();
|
2019-06-05 15:18:06 -04:00
|
|
|
return DIENUM_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
++Count;
|
2019-07-25 06:38:25 -04:00
|
|
|
|
|
|
|
hr = (*pJoystick)->SetCooperativeLevel( PSGLOBAL(window), DISCL_NONEXCLUSIVE|DISCL_FOREGROUND );
|
|
|
|
if( hr != S_OK )
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
2019-07-25 06:38:25 -04:00
|
|
|
(*pJoystick)->Release();
|
|
|
|
#ifdef FIX_BUGS
|
|
|
|
// BUG: enum will be called with Count == 2, which will write to a null pointer
|
|
|
|
// So decrement count again since we're not using this pad
|
|
|
|
--Count;
|
|
|
|
#endif
|
2019-06-11 05:30:53 -04:00
|
|
|
return DIENUM_CONTINUE;
|
2019-06-05 15:18:06 -04:00
|
|
|
}
|
|
|
|
|
2019-07-25 06:38:25 -04:00
|
|
|
// Stop enumeration. Note: we're just taking the first two joysticks we get. You
|
|
|
|
// could store all the enumerated joysticks and let the user pick.
|
2019-06-05 15:18:06 -04:00
|
|
|
if ( Count == 2 )
|
|
|
|
return DIENUM_STOP;
|
|
|
|
|
2019-06-11 05:30:53 -04:00
|
|
|
return DIENUM_CONTINUE;
|
2019-06-05 15:18:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL _InputTranslateKey(RsKeyCodes *rs, UINT flag, UINT key)
|
|
|
|
{
|
|
|
|
*rs = rsNULL;
|
|
|
|
|
|
|
|
switch ( key )
|
|
|
|
{
|
|
|
|
case VK_SHIFT:
|
|
|
|
{
|
|
|
|
if ( _dwOperatingSystemVersion == OS_WIN98 )
|
|
|
|
*rs = rsSHIFT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_RETURN:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsPADENTER;
|
|
|
|
else
|
|
|
|
*rs = rsENTER;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_CONTROL:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsRCTRL;
|
|
|
|
else
|
|
|
|
*rs = rsLCTRL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_MENU:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsRALT;
|
|
|
|
else
|
|
|
|
*rs = rsLALT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_APPS:
|
|
|
|
{
|
|
|
|
*rs = rsAPPS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_PAUSE:
|
|
|
|
{
|
|
|
|
*rs = rsPAUSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_CAPITAL:
|
|
|
|
{
|
|
|
|
*rs = rsCAPSLK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_ESCAPE:
|
|
|
|
{
|
|
|
|
*rs = rsESC;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_PRIOR:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsPGUP;
|
|
|
|
else
|
|
|
|
*rs = rsPADPGUP;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_NEXT:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsPGDN;
|
|
|
|
else
|
|
|
|
*rs = rsPADPGDN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_END:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsEND;
|
|
|
|
else
|
|
|
|
*rs = rsPADEND;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_HOME:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsHOME;
|
|
|
|
else
|
|
|
|
*rs = rsPADHOME;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_LEFT:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsLEFT;
|
|
|
|
else
|
|
|
|
*rs = rsPADLEFT;
|
2019-06-05 16:25:13 -04:00
|
|
|
break;
|
2019-06-05 15:18:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
case VK_UP:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsUP;
|
|
|
|
else
|
|
|
|
*rs = rsPADUP;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_RIGHT:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsRIGHT;
|
|
|
|
else
|
|
|
|
*rs = rsPADRIGHT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_DOWN:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsDOWN;
|
|
|
|
else
|
|
|
|
*rs = rsPADDOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_INSERT:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsINS;
|
|
|
|
else
|
|
|
|
*rs = rsPADINS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_DELETE:
|
|
|
|
{
|
|
|
|
if ( _InputIsExtended(flag) )
|
|
|
|
*rs = rsDEL;
|
|
|
|
else
|
|
|
|
*rs = rsPADDEL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_LWIN:
|
|
|
|
{
|
|
|
|
*rs = rsLWIN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_RWIN:
|
|
|
|
{
|
|
|
|
*rs = rsRWIN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_NUMPAD0:
|
|
|
|
{
|
|
|
|
*rs = rsPADINS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_NUMPAD1:
|
|
|
|
{
|
|
|
|
*rs = rsPADEND;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_NUMPAD2:
|
|
|
|
{
|
|
|
|
*rs = rsPADDOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_NUMPAD3:
|
|
|
|
{
|
|
|
|
*rs = rsPADPGDN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_NUMPAD4:
|
|
|
|
{
|
|
|
|
*rs = rsPADLEFT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_NUMPAD5:
|
|
|
|
{
|
|
|
|
*rs = rsPAD5;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_NUMPAD6:
|
|
|
|
{
|
|
|
|
*rs = rsPADRIGHT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_NUMPAD7:
|
|
|
|
{
|
|
|
|
*rs = rsPADHOME;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_NUMPAD8:
|
|
|
|
{
|
|
|
|
*rs = rsPADUP;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_NUMPAD9:
|
|
|
|
{
|
|
|
|
*rs = rsPADPGUP;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_MULTIPLY:
|
|
|
|
{
|
|
|
|
*rs = rsTIMES;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_DIVIDE:
|
|
|
|
{
|
|
|
|
*rs = rsDIVIDE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_ADD:
|
|
|
|
{
|
|
|
|
*rs = rsPLUS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_SUBTRACT:
|
|
|
|
{
|
|
|
|
*rs = rsMINUS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_DECIMAL:
|
|
|
|
{
|
|
|
|
*rs = rsPADDEL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F1:
|
|
|
|
{
|
|
|
|
*rs = rsF1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F2:
|
|
|
|
{
|
|
|
|
*rs = rsF2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F3:
|
|
|
|
{
|
|
|
|
*rs = rsF3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F4:
|
|
|
|
{
|
|
|
|
*rs = rsF4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F5:
|
|
|
|
{
|
|
|
|
*rs = rsF5;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F6:
|
|
|
|
{
|
|
|
|
*rs = rsF6;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F7:
|
|
|
|
{
|
|
|
|
*rs = rsF7;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F8:
|
|
|
|
{
|
|
|
|
*rs = rsF8;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F9:
|
|
|
|
{
|
|
|
|
*rs = rsF9;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F10:
|
|
|
|
{
|
|
|
|
*rs = rsF10;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F11:
|
|
|
|
{
|
|
|
|
*rs = rsF11;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_F12:
|
|
|
|
{
|
|
|
|
*rs = rsF12;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_NUMLOCK:
|
|
|
|
{
|
|
|
|
*rs = rsNUMLOCK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_SCROLL:
|
|
|
|
{
|
|
|
|
*rs = rsSCROLL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_BACK:
|
|
|
|
{
|
|
|
|
*rs = rsBACKSP;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_TAB:
|
|
|
|
{
|
|
|
|
*rs = rsTAB;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
UINT vkey = MapVirtualKey(key, MAPVK_VK_TO_CHAR) & 0xFFFF;
|
|
|
|
if ( vkey < 255 )
|
|
|
|
*rs = (RsKeyCodes)vkey;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return *rs != rsNULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _InputTranslateShiftKeyUpDown(RsKeyCodes *rs)
|
|
|
|
{
|
|
|
|
if ( _dwOperatingSystemVersion != OS_WIN98 )
|
|
|
|
{
|
|
|
|
if ( _InputTranslateShiftKey(rs, VK_LSHIFT, TRUE) )
|
|
|
|
RsKeyboardEventHandler(rsKEYDOWN, rs);
|
|
|
|
if ( _InputTranslateShiftKey(rs, VK_RSHIFT, TRUE) )
|
|
|
|
RsKeyboardEventHandler(rsKEYDOWN, rs);
|
|
|
|
if ( _InputTranslateShiftKey(rs, VK_LSHIFT, FALSE) )
|
|
|
|
RsKeyboardEventHandler(rsKEYUP, rs);
|
|
|
|
if ( _InputTranslateShiftKey(rs, VK_RSHIFT, FALSE) )
|
|
|
|
RsKeyboardEventHandler(rsKEYUP, rs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-03 07:13:55 -04:00
|
|
|
BOOL _InputTranslateShiftKey(RsKeyCodes *rs, UINT key, BOOLEAN bDown)
|
2019-06-05 15:18:06 -04:00
|
|
|
{
|
|
|
|
*rs = rsNULL;
|
|
|
|
switch ( key )
|
|
|
|
{
|
|
|
|
case VK_LSHIFT:
|
|
|
|
{
|
|
|
|
if ( bDown == (GetKeyState(VK_LSHIFT) & 0x8000) >> 15 )
|
|
|
|
*rs = rsLSHIFT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VK_RSHIFT:
|
|
|
|
{
|
|
|
|
if ( bDown == (GetKeyState(VK_RSHIFT) & 0x8000) >> 15 )
|
|
|
|
*rs = rsRSHIFT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
return *rs != rsNULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL _InputIsExtended(INT flag)
|
|
|
|
{
|
|
|
|
return (flag & 0x1000000) != 0;
|
|
|
|
}
|
2019-06-01 23:00:38 -04:00
|
|
|
|
2019-10-29 19:12:58 -04:00
|
|
|
#if (defined(_MSC_VER))
|
|
|
|
int strcasecmp(const char *str1, const char *str2)
|
|
|
|
{
|
|
|
|
return _strcmpi(str1, str2);
|
|
|
|
}
|
|
|
|
#endif
|
2020-04-26 06:25:03 -04:00
|
|
|
#endif
|