From e58fc5ab783460c097d61da07b7a1563e2bd779d Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 30 Apr 2013 15:56:41 +1000 Subject: [PATCH] nRage: Add ability to compile version 2.3c --- Project64.vs2008.sln | 8 + Source/3rd Party/directx/include/dinput.h | 4399 +++++++++++++++++ Source/3rd Party/directx/lib/dinput8.lib | Bin 0 -> 19978 bytes Source/3rd Party/directx/lib/dxguid.lib | Bin 0 -> 104752 bytes .../ControllerSpecs/Controller #1.0.h | 220 + .../ControllerSpecs/Controller #1.1.h | 233 + Source/nragev20/Debug.cpp | 157 + Source/nragev20/Debug.h | 65 + Source/nragev20/DirectInput.cpp | 1290 +++++ Source/nragev20/DirectInput.h | 156 + Source/nragev20/FileAccess.cpp | 1681 +++++++ Source/nragev20/FileAccess.h | 227 + Source/nragev20/GBCart.cpp | 1045 ++++ Source/nragev20/GBCart.h | 78 + Source/nragev20/Interface.cpp | 4056 +++++++++++++++ Source/nragev20/Interface.h | 93 + Source/nragev20/International.cpp | 192 + Source/nragev20/International.h | 42 + Source/nragev20/LICENSE | 340 ++ Source/nragev20/NRagePluginV2.cpp | 1280 +++++ Source/nragev20/NRagePluginV2.h | 394 ++ Source/nragev20/NRagePluginV2.rc | 885 ++++ Source/nragev20/NRage_Input_V2.vcproj | 275 ++ Source/nragev20/PakIO.cpp | 1496 ++++++ Source/nragev20/PakIO.h | 173 + Source/nragev20/README.txt | 210 + Source/nragev20/XInputController.cpp | 774 +++ Source/nragev20/XInputController.h | 160 + Source/nragev20/commonIncludes.h | 55 + Source/nragev20/configs/Controller1.cpf | 37 + Source/nragev20/configs/Shortcuts.sc | 3 + Source/nragev20/resource.h | 374 ++ Source/nragev20/settings.h | 139 + 33 files changed, 20537 insertions(+) create mode 100644 Source/3rd Party/directx/include/dinput.h create mode 100644 Source/3rd Party/directx/lib/dinput8.lib create mode 100644 Source/3rd Party/directx/lib/dxguid.lib create mode 100644 Source/nragev20/ControllerSpecs/Controller #1.0.h create mode 100644 Source/nragev20/ControllerSpecs/Controller #1.1.h create mode 100644 Source/nragev20/Debug.cpp create mode 100644 Source/nragev20/Debug.h create mode 100644 Source/nragev20/DirectInput.cpp create mode 100644 Source/nragev20/DirectInput.h create mode 100644 Source/nragev20/FileAccess.cpp create mode 100644 Source/nragev20/FileAccess.h create mode 100644 Source/nragev20/GBCart.cpp create mode 100644 Source/nragev20/GBCart.h create mode 100644 Source/nragev20/Interface.cpp create mode 100644 Source/nragev20/Interface.h create mode 100644 Source/nragev20/International.cpp create mode 100644 Source/nragev20/International.h create mode 100644 Source/nragev20/LICENSE create mode 100644 Source/nragev20/NRagePluginV2.cpp create mode 100644 Source/nragev20/NRagePluginV2.h create mode 100644 Source/nragev20/NRagePluginV2.rc create mode 100644 Source/nragev20/NRage_Input_V2.vcproj create mode 100644 Source/nragev20/PakIO.cpp create mode 100644 Source/nragev20/PakIO.h create mode 100644 Source/nragev20/README.txt create mode 100644 Source/nragev20/XInputController.cpp create mode 100644 Source/nragev20/XInputController.h create mode 100644 Source/nragev20/commonIncludes.h create mode 100644 Source/nragev20/configs/Controller1.cpf create mode 100644 Source/nragev20/configs/Shortcuts.sc create mode 100644 Source/nragev20/resource.h create mode 100644 Source/nragev20/settings.h diff --git a/Project64.vs2008.sln b/Project64.vs2008.sln index 5b3598e24..3cf4bb139 100644 --- a/Project64.vs2008.sln +++ b/Project64.vs2008.sln @@ -75,6 +75,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SortRdb", "Source\SortRdb\S {B4A4B994-9111-42B1-93C2-6F1CA8BC4421} = {B4A4B994-9111-42B1-93C2-6F1CA8BC4421} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NRage_Input_V2", "Source\nragev20\NRage_Input_V2.vcproj", "{FD617E80-9E40-4138-85DA-B94633972E6A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Beta Release|Win32 = Beta Release|Win32 @@ -182,6 +184,12 @@ Global {5788717F-E3D4-40CF-9637-3A2AEE85BB81}.Debug|Win32.Build.0 = Debug|Win32 {5788717F-E3D4-40CF-9637-3A2AEE85BB81}.Release|Win32.ActiveCfg = Release|Win32 {5788717F-E3D4-40CF-9637-3A2AEE85BB81}.Release|Win32.Build.0 = Release|Win32 + {FD617E80-9E40-4138-85DA-B94633972E6A}.Beta Release|Win32.ActiveCfg = Release|Win32 + {FD617E80-9E40-4138-85DA-B94633972E6A}.Beta Release|Win32.Build.0 = Release|Win32 + {FD617E80-9E40-4138-85DA-B94633972E6A}.Debug|Win32.ActiveCfg = Debug|Win32 + {FD617E80-9E40-4138-85DA-B94633972E6A}.Debug|Win32.Build.0 = Debug|Win32 + {FD617E80-9E40-4138-85DA-B94633972E6A}.Release|Win32.ActiveCfg = Release|Win32 + {FD617E80-9E40-4138-85DA-B94633972E6A}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Source/3rd Party/directx/include/dinput.h b/Source/3rd Party/directx/include/dinput.h new file mode 100644 index 000000000..357c99150 --- /dev/null +++ b/Source/3rd Party/directx/include/dinput.h @@ -0,0 +1,4399 @@ +/**************************************************************************** + * + * Copyright (C) 1996-2000 Microsoft Corporation. All Rights Reserved. + * + * File: dinput.h + * Content: DirectInput include file + * + ****************************************************************************/ + +#ifndef __DINPUT_INCLUDED__ +#define __DINPUT_INCLUDED__ + +#ifndef DIJ_RINGZERO + +#ifdef _WIN32 +#define COM_NO_WINDOWS_H +#include +#endif + +#endif /* DIJ_RINGZERO */ + +#ifdef __cplusplus +extern "C" { +#endif + + + + + +/* + * To build applications for older versions of DirectInput + * + * #define DIRECTINPUT_VERSION [ 0x0300 | 0x0500 | 0x0700 ] + * + * before #include . By default, #include + * will produce a DirectX 8-compatible header file. + * + */ + +#define DIRECTINPUT_HEADER_VERSION 0x0800 +#ifndef DIRECTINPUT_VERSION +#define DIRECTINPUT_VERSION DIRECTINPUT_HEADER_VERSION +#pragma message(__FILE__ ": DIRECTINPUT_VERSION undefined. Defaulting to version 0x0800") +#endif + +#ifndef DIJ_RINGZERO + +/**************************************************************************** + * + * Class IDs + * + ****************************************************************************/ + +DEFINE_GUID(CLSID_DirectInput, 0x25E609E0,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(CLSID_DirectInputDevice, 0x25E609E1,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(CLSID_DirectInput8, 0x25E609E4,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(CLSID_DirectInputDevice8,0x25E609E5,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/**************************************************************************** + * + * Interfaces + * + ****************************************************************************/ + +DEFINE_GUID(IID_IDirectInputA, 0x89521360,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputW, 0x89521361,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInput2A, 0x5944E662,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInput2W, 0x5944E663,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInput7A, 0x9A4CB684,0x236D,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInput7W, 0x9A4CB685,0x236D,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInput8A, 0xBF798030,0x483A,0x4DA2,0xAA,0x99,0x5D,0x64,0xED,0x36,0x97,0x00); +DEFINE_GUID(IID_IDirectInput8W, 0xBF798031,0x483A,0x4DA2,0xAA,0x99,0x5D,0x64,0xED,0x36,0x97,0x00); +DEFINE_GUID(IID_IDirectInputDeviceA, 0x5944E680,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDeviceW, 0x5944E681,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDevice2A,0x5944E682,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDevice2W,0x5944E683,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDevice7A,0x57D7C6BC,0x2356,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInputDevice7W,0x57D7C6BD,0x2356,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInputDevice8A,0x54D41080,0xDC15,0x4833,0xA4,0x1B,0x74,0x8F,0x73,0xA3,0x81,0x79); +DEFINE_GUID(IID_IDirectInputDevice8W,0x54D41081,0xDC15,0x4833,0xA4,0x1B,0x74,0x8F,0x73,0xA3,0x81,0x79); +DEFINE_GUID(IID_IDirectInputEffect, 0xE7E1F7C0,0x88D2,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); + +/**************************************************************************** + * + * Predefined object types + * + ****************************************************************************/ + +DEFINE_GUID(GUID_XAxis, 0xA36D02E0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_YAxis, 0xA36D02E1,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_ZAxis, 0xA36D02E2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_RxAxis, 0xA36D02F4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_RyAxis, 0xA36D02F5,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_RzAxis, 0xA36D02E3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Slider, 0xA36D02E4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(GUID_Button, 0xA36D02F0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Key, 0x55728220,0xD33C,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(GUID_POV, 0xA36D02F2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(GUID_Unknown, 0xA36D02F3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/**************************************************************************** + * + * Predefined product GUIDs + * + ****************************************************************************/ + +DEFINE_GUID(GUID_SysMouse, 0x6F1D2B60,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboard,0x6F1D2B61,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Joystick ,0x6F1D2B70,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysMouseEm, 0x6F1D2B80,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysMouseEm2,0x6F1D2B81,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboardEm, 0x6F1D2B82,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboardEm2,0x6F1D2B83,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/**************************************************************************** + * + * Predefined force feedback effects + * + ****************************************************************************/ + +DEFINE_GUID(GUID_ConstantForce, 0x13541C20,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_RampForce, 0x13541C21,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Square, 0x13541C22,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Sine, 0x13541C23,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Triangle, 0x13541C24,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_SawtoothUp, 0x13541C25,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_SawtoothDown, 0x13541C26,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Spring, 0x13541C27,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Damper, 0x13541C28,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Inertia, 0x13541C29,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Friction, 0x13541C2A,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_CustomForce, 0x13541C2B,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); + +#endif /* DIJ_RINGZERO */ + +/**************************************************************************** + * + * Interfaces and Structures... + * + ****************************************************************************/ + +#if(DIRECTINPUT_VERSION >= 0x0500) + +/**************************************************************************** + * + * IDirectInputEffect + * + ****************************************************************************/ + +#define DIEFT_ALL 0x00000000 + +#define DIEFT_CONSTANTFORCE 0x00000001 +#define DIEFT_RAMPFORCE 0x00000002 +#define DIEFT_PERIODIC 0x00000003 +#define DIEFT_CONDITION 0x00000004 +#define DIEFT_CUSTOMFORCE 0x00000005 +#define DIEFT_HARDWARE 0x000000FF +#define DIEFT_FFATTACK 0x00000200 +#define DIEFT_FFFADE 0x00000400 +#define DIEFT_SATURATION 0x00000800 +#define DIEFT_POSNEGCOEFFICIENTS 0x00001000 +#define DIEFT_POSNEGSATURATION 0x00002000 +#define DIEFT_DEADBAND 0x00004000 +#define DIEFT_STARTDELAY 0x00008000 +#define DIEFT_GETTYPE(n) LOBYTE(n) + +#define DI_DEGREES 100 +#define DI_FFNOMINALMAX 10000 +#define DI_SECONDS 1000000 + +typedef struct DICONSTANTFORCE { + LONG lMagnitude; +} DICONSTANTFORCE, *LPDICONSTANTFORCE; +typedef const DICONSTANTFORCE *LPCDICONSTANTFORCE; + +typedef struct DIRAMPFORCE { + LONG lStart; + LONG lEnd; +} DIRAMPFORCE, *LPDIRAMPFORCE; +typedef const DIRAMPFORCE *LPCDIRAMPFORCE; + +typedef struct DIPERIODIC { + DWORD dwMagnitude; + LONG lOffset; + DWORD dwPhase; + DWORD dwPeriod; +} DIPERIODIC, *LPDIPERIODIC; +typedef const DIPERIODIC *LPCDIPERIODIC; + +typedef struct DICONDITION { + LONG lOffset; + LONG lPositiveCoefficient; + LONG lNegativeCoefficient; + DWORD dwPositiveSaturation; + DWORD dwNegativeSaturation; + LONG lDeadBand; +} DICONDITION, *LPDICONDITION; +typedef const DICONDITION *LPCDICONDITION; + +typedef struct DICUSTOMFORCE { + DWORD cChannels; + DWORD dwSamplePeriod; + DWORD cSamples; + LPLONG rglForceData; +} DICUSTOMFORCE, *LPDICUSTOMFORCE; +typedef const DICUSTOMFORCE *LPCDICUSTOMFORCE; + + +typedef struct DIENVELOPE { + DWORD dwSize; /* sizeof(DIENVELOPE) */ + DWORD dwAttackLevel; + DWORD dwAttackTime; /* Microseconds */ + DWORD dwFadeLevel; + DWORD dwFadeTime; /* Microseconds */ +} DIENVELOPE, *LPDIENVELOPE; +typedef const DIENVELOPE *LPCDIENVELOPE; + + +/* This structure is defined for DirectX 5.0 compatibility */ +typedef struct DIEFFECT_DX5 { + DWORD dwSize; /* sizeof(DIEFFECT_DX5) */ + DWORD dwFlags; /* DIEFF_* */ + DWORD dwDuration; /* Microseconds */ + DWORD dwSamplePeriod; /* Microseconds */ + DWORD dwGain; + DWORD dwTriggerButton; /* or DIEB_NOTRIGGER */ + DWORD dwTriggerRepeatInterval; /* Microseconds */ + DWORD cAxes; /* Number of axes */ + LPDWORD rgdwAxes; /* Array of axes */ + LPLONG rglDirection; /* Array of directions */ + LPDIENVELOPE lpEnvelope; /* Optional */ + DWORD cbTypeSpecificParams; /* Size of params */ + LPVOID lpvTypeSpecificParams; /* Pointer to params */ +} DIEFFECT_DX5, *LPDIEFFECT_DX5; +typedef const DIEFFECT_DX5 *LPCDIEFFECT_DX5; + +typedef struct DIEFFECT { + DWORD dwSize; /* sizeof(DIEFFECT) */ + DWORD dwFlags; /* DIEFF_* */ + DWORD dwDuration; /* Microseconds */ + DWORD dwSamplePeriod; /* Microseconds */ + DWORD dwGain; + DWORD dwTriggerButton; /* or DIEB_NOTRIGGER */ + DWORD dwTriggerRepeatInterval; /* Microseconds */ + DWORD cAxes; /* Number of axes */ + LPDWORD rgdwAxes; /* Array of axes */ + LPLONG rglDirection; /* Array of directions */ + LPDIENVELOPE lpEnvelope; /* Optional */ + DWORD cbTypeSpecificParams; /* Size of params */ + LPVOID lpvTypeSpecificParams; /* Pointer to params */ +#if(DIRECTINPUT_VERSION >= 0x0600) + DWORD dwStartDelay; /* Microseconds */ +#endif /* DIRECTINPUT_VERSION >= 0x0600 */ +} DIEFFECT, *LPDIEFFECT; +typedef DIEFFECT DIEFFECT_DX6; +typedef LPDIEFFECT LPDIEFFECT_DX6; +typedef const DIEFFECT *LPCDIEFFECT; + + +#if(DIRECTINPUT_VERSION >= 0x0700) +#ifndef DIJ_RINGZERO +typedef struct DIFILEEFFECT{ + DWORD dwSize; + GUID GuidEffect; + LPCDIEFFECT lpDiEffect; + CHAR szFriendlyName[MAX_PATH]; +}DIFILEEFFECT, *LPDIFILEEFFECT; +typedef const DIFILEEFFECT *LPCDIFILEEFFECT; +typedef BOOL (FAR PASCAL * LPDIENUMEFFECTSINFILECALLBACK)(LPCDIFILEEFFECT , LPVOID); +#endif /* DIJ_RINGZERO */ +#endif /* DIRECTINPUT_VERSION >= 0x0700 */ + +#define DIEFF_OBJECTIDS 0x00000001 +#define DIEFF_OBJECTOFFSETS 0x00000002 +#define DIEFF_CARTESIAN 0x00000010 +#define DIEFF_POLAR 0x00000020 +#define DIEFF_SPHERICAL 0x00000040 + +#define DIEP_DURATION 0x00000001 +#define DIEP_SAMPLEPERIOD 0x00000002 +#define DIEP_GAIN 0x00000004 +#define DIEP_TRIGGERBUTTON 0x00000008 +#define DIEP_TRIGGERREPEATINTERVAL 0x00000010 +#define DIEP_AXES 0x00000020 +#define DIEP_DIRECTION 0x00000040 +#define DIEP_ENVELOPE 0x00000080 +#define DIEP_TYPESPECIFICPARAMS 0x00000100 +#if(DIRECTINPUT_VERSION >= 0x0600) +#define DIEP_STARTDELAY 0x00000200 +#define DIEP_ALLPARAMS_DX5 0x000001FF +#define DIEP_ALLPARAMS 0x000003FF +#else /* DIRECTINPUT_VERSION < 0x0600 */ +#define DIEP_ALLPARAMS 0x000001FF +#endif /* DIRECTINPUT_VERSION < 0x0600 */ +#define DIEP_START 0x20000000 +#define DIEP_NORESTART 0x40000000 +#define DIEP_NODOWNLOAD 0x80000000 +#define DIEB_NOTRIGGER 0xFFFFFFFF + +#define DIES_SOLO 0x00000001 +#define DIES_NODOWNLOAD 0x80000000 + +#define DIEGES_PLAYING 0x00000001 +#define DIEGES_EMULATED 0x00000002 + +typedef struct DIEFFESCAPE { + DWORD dwSize; + DWORD dwCommand; + LPVOID lpvInBuffer; + DWORD cbInBuffer; + LPVOID lpvOutBuffer; + DWORD cbOutBuffer; +} DIEFFESCAPE, *LPDIEFFESCAPE; + +#ifndef DIJ_RINGZERO + +#undef INTERFACE +#define INTERFACE IDirectInputEffect + +DECLARE_INTERFACE_(IDirectInputEffect, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputEffect methods ***/ + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + STDMETHOD(GetEffectGuid)(THIS_ LPGUID) PURE; + STDMETHOD(GetParameters)(THIS_ LPDIEFFECT,DWORD) PURE; + STDMETHOD(SetParameters)(THIS_ LPCDIEFFECT,DWORD) PURE; + STDMETHOD(Start)(THIS_ DWORD,DWORD) PURE; + STDMETHOD(Stop)(THIS) PURE; + STDMETHOD(GetEffectStatus)(THIS_ LPDWORD) PURE; + STDMETHOD(Download)(THIS) PURE; + STDMETHOD(Unload)(THIS) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; +}; + +typedef struct IDirectInputEffect *LPDIRECTINPUTEFFECT; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInputEffect_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputEffect_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputEffect_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInputEffect_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#define IDirectInputEffect_GetEffectGuid(p,a) (p)->lpVtbl->GetEffectGuid(p,a) +#define IDirectInputEffect_GetParameters(p,a,b) (p)->lpVtbl->GetParameters(p,a,b) +#define IDirectInputEffect_SetParameters(p,a,b) (p)->lpVtbl->SetParameters(p,a,b) +#define IDirectInputEffect_Start(p,a,b) (p)->lpVtbl->Start(p,a,b) +#define IDirectInputEffect_Stop(p) (p)->lpVtbl->Stop(p) +#define IDirectInputEffect_GetEffectStatus(p,a) (p)->lpVtbl->GetEffectStatus(p,a) +#define IDirectInputEffect_Download(p) (p)->lpVtbl->Download(p) +#define IDirectInputEffect_Unload(p) (p)->lpVtbl->Unload(p) +#define IDirectInputEffect_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#else +#define IDirectInputEffect_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputEffect_AddRef(p) (p)->AddRef() +#define IDirectInputEffect_Release(p) (p)->Release() +#define IDirectInputEffect_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#define IDirectInputEffect_GetEffectGuid(p,a) (p)->GetEffectGuid(a) +#define IDirectInputEffect_GetParameters(p,a,b) (p)->GetParameters(a,b) +#define IDirectInputEffect_SetParameters(p,a,b) (p)->SetParameters(a,b) +#define IDirectInputEffect_Start(p,a,b) (p)->Start(a,b) +#define IDirectInputEffect_Stop(p) (p)->Stop() +#define IDirectInputEffect_GetEffectStatus(p,a) (p)->GetEffectStatus(a) +#define IDirectInputEffect_Download(p) (p)->Download() +#define IDirectInputEffect_Unload(p) (p)->Unload() +#define IDirectInputEffect_Escape(p,a) (p)->Escape(a) +#endif + +#endif /* DIJ_RINGZERO */ + +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +/**************************************************************************** + * + * IDirectInputDevice + * + ****************************************************************************/ + +#if DIRECTINPUT_VERSION <= 0x700 +#define DIDEVTYPE_DEVICE 1 +#define DIDEVTYPE_MOUSE 2 +#define DIDEVTYPE_KEYBOARD 3 +#define DIDEVTYPE_JOYSTICK 4 + +#else +#define DI8DEVCLASS_ALL 0 +#define DI8DEVCLASS_DEVICE 1 +#define DI8DEVCLASS_POINTER 2 +#define DI8DEVCLASS_KEYBOARD 3 +#define DI8DEVCLASS_GAMECTRL 4 + +#define DI8DEVTYPE_DEVICE 0x11 +#define DI8DEVTYPE_MOUSE 0x12 +#define DI8DEVTYPE_KEYBOARD 0x13 +#define DI8DEVTYPE_JOYSTICK 0x14 +#define DI8DEVTYPE_GAMEPAD 0x15 +#define DI8DEVTYPE_DRIVING 0x16 +#define DI8DEVTYPE_FLIGHT 0x17 +#define DI8DEVTYPE_1STPERSON 0x18 +#define DI8DEVTYPE_DEVICECTRL 0x19 +#define DI8DEVTYPE_SCREENPOINTER 0x1A +#define DI8DEVTYPE_REMOTE 0x1B +#define DI8DEVTYPE_SUPPLEMENTAL 0x1C +#endif /* DIRECTINPUT_VERSION <= 0x700 */ + +#define DIDEVTYPE_HID 0x00010000 + +#if DIRECTINPUT_VERSION <= 0x700 +#define DIDEVTYPEMOUSE_UNKNOWN 1 +#define DIDEVTYPEMOUSE_TRADITIONAL 2 +#define DIDEVTYPEMOUSE_FINGERSTICK 3 +#define DIDEVTYPEMOUSE_TOUCHPAD 4 +#define DIDEVTYPEMOUSE_TRACKBALL 5 + +#define DIDEVTYPEKEYBOARD_UNKNOWN 0 +#define DIDEVTYPEKEYBOARD_PCXT 1 +#define DIDEVTYPEKEYBOARD_OLIVETTI 2 +#define DIDEVTYPEKEYBOARD_PCAT 3 +#define DIDEVTYPEKEYBOARD_PCENH 4 +#define DIDEVTYPEKEYBOARD_NOKIA1050 5 +#define DIDEVTYPEKEYBOARD_NOKIA9140 6 +#define DIDEVTYPEKEYBOARD_NEC98 7 +#define DIDEVTYPEKEYBOARD_NEC98LAPTOP 8 +#define DIDEVTYPEKEYBOARD_NEC98106 9 +#define DIDEVTYPEKEYBOARD_JAPAN106 10 +#define DIDEVTYPEKEYBOARD_JAPANAX 11 +#define DIDEVTYPEKEYBOARD_J3100 12 + +#define DIDEVTYPEJOYSTICK_UNKNOWN 1 +#define DIDEVTYPEJOYSTICK_TRADITIONAL 2 +#define DIDEVTYPEJOYSTICK_FLIGHTSTICK 3 +#define DIDEVTYPEJOYSTICK_GAMEPAD 4 +#define DIDEVTYPEJOYSTICK_RUDDER 5 +#define DIDEVTYPEJOYSTICK_WHEEL 6 +#define DIDEVTYPEJOYSTICK_HEADTRACKER 7 + +#else +#define DI8DEVTYPEMOUSE_UNKNOWN 1 +#define DI8DEVTYPEMOUSE_TRADITIONAL 2 +#define DI8DEVTYPEMOUSE_FINGERSTICK 3 +#define DI8DEVTYPEMOUSE_TOUCHPAD 4 +#define DI8DEVTYPEMOUSE_TRACKBALL 5 +#define DI8DEVTYPEMOUSE_ABSOLUTE 6 + +#define DI8DEVTYPEKEYBOARD_UNKNOWN 0 +#define DI8DEVTYPEKEYBOARD_PCXT 1 +#define DI8DEVTYPEKEYBOARD_OLIVETTI 2 +#define DI8DEVTYPEKEYBOARD_PCAT 3 +#define DI8DEVTYPEKEYBOARD_PCENH 4 +#define DI8DEVTYPEKEYBOARD_NOKIA1050 5 +#define DI8DEVTYPEKEYBOARD_NOKIA9140 6 +#define DI8DEVTYPEKEYBOARD_NEC98 7 +#define DI8DEVTYPEKEYBOARD_NEC98LAPTOP 8 +#define DI8DEVTYPEKEYBOARD_NEC98106 9 +#define DI8DEVTYPEKEYBOARD_JAPAN106 10 +#define DI8DEVTYPEKEYBOARD_JAPANAX 11 +#define DI8DEVTYPEKEYBOARD_J3100 12 + +#define DI8DEVTYPE_LIMITEDGAMESUBTYPE 1 + +#define DI8DEVTYPEJOYSTICK_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEJOYSTICK_STANDARD 2 + +#define DI8DEVTYPEGAMEPAD_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEGAMEPAD_STANDARD 2 +#define DI8DEVTYPEGAMEPAD_TILT 3 + +#define DI8DEVTYPEDRIVING_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEDRIVING_COMBINEDPEDALS 2 +#define DI8DEVTYPEDRIVING_DUALPEDALS 3 +#define DI8DEVTYPEDRIVING_THREEPEDALS 4 +#define DI8DEVTYPEDRIVING_HANDHELD 5 + +#define DI8DEVTYPEFLIGHT_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEFLIGHT_STICK 2 +#define DI8DEVTYPEFLIGHT_YOKE 3 +#define DI8DEVTYPEFLIGHT_RC 4 + +#define DI8DEVTYPE1STPERSON_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPE1STPERSON_UNKNOWN 2 +#define DI8DEVTYPE1STPERSON_SIXDOF 3 +#define DI8DEVTYPE1STPERSON_SHOOTER 4 + +#define DI8DEVTYPESCREENPTR_UNKNOWN 2 +#define DI8DEVTYPESCREENPTR_LIGHTGUN 3 +#define DI8DEVTYPESCREENPTR_LIGHTPEN 4 +#define DI8DEVTYPESCREENPTR_TOUCH 5 + +#define DI8DEVTYPEREMOTE_UNKNOWN 2 + +#define DI8DEVTYPEDEVICECTRL_UNKNOWN 2 +#define DI8DEVTYPEDEVICECTRL_COMMSSELECTION 3 +#define DI8DEVTYPEDEVICECTRL_COMMSSELECTION_HARDWIRED 4 + +#define DI8DEVTYPESUPPLEMENTAL_UNKNOWN 2 +#define DI8DEVTYPESUPPLEMENTAL_2NDHANDCONTROLLER 3 +#define DI8DEVTYPESUPPLEMENTAL_HEADTRACKER 4 +#define DI8DEVTYPESUPPLEMENTAL_HANDTRACKER 5 +#define DI8DEVTYPESUPPLEMENTAL_SHIFTSTICKGATE 6 +#define DI8DEVTYPESUPPLEMENTAL_SHIFTER 7 +#define DI8DEVTYPESUPPLEMENTAL_THROTTLE 8 +#define DI8DEVTYPESUPPLEMENTAL_SPLITTHROTTLE 9 +#define DI8DEVTYPESUPPLEMENTAL_COMBINEDPEDALS 10 +#define DI8DEVTYPESUPPLEMENTAL_DUALPEDALS 11 +#define DI8DEVTYPESUPPLEMENTAL_THREEPEDALS 12 +#define DI8DEVTYPESUPPLEMENTAL_RUDDERPEDALS 13 +#endif /* DIRECTINPUT_VERSION <= 0x700 */ + +#define GET_DIDEVICE_TYPE(dwDevType) LOBYTE(dwDevType) +#define GET_DIDEVICE_SUBTYPE(dwDevType) HIBYTE(dwDevType) + +#if(DIRECTINPUT_VERSION >= 0x0500) +/* This structure is defined for DirectX 3.0 compatibility */ +typedef struct DIDEVCAPS_DX3 { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDevType; + DWORD dwAxes; + DWORD dwButtons; + DWORD dwPOVs; +} DIDEVCAPS_DX3, *LPDIDEVCAPS_DX3; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +typedef struct DIDEVCAPS { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDevType; + DWORD dwAxes; + DWORD dwButtons; + DWORD dwPOVs; +#if(DIRECTINPUT_VERSION >= 0x0500) + DWORD dwFFSamplePeriod; + DWORD dwFFMinTimeResolution; + DWORD dwFirmwareRevision; + DWORD dwHardwareRevision; + DWORD dwFFDriverVersion; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVCAPS, *LPDIDEVCAPS; + +#define DIDC_ATTACHED 0x00000001 +#define DIDC_POLLEDDEVICE 0x00000002 +#define DIDC_EMULATED 0x00000004 +#define DIDC_POLLEDDATAFORMAT 0x00000008 +#if(DIRECTINPUT_VERSION >= 0x0500) +#define DIDC_FORCEFEEDBACK 0x00000100 +#define DIDC_FFATTACK 0x00000200 +#define DIDC_FFFADE 0x00000400 +#define DIDC_SATURATION 0x00000800 +#define DIDC_POSNEGCOEFFICIENTS 0x00001000 +#define DIDC_POSNEGSATURATION 0x00002000 +#define DIDC_DEADBAND 0x00004000 +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +#define DIDC_STARTDELAY 0x00008000 +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIDC_ALIAS 0x00010000 +#define DIDC_PHANTOM 0x00020000 +#endif /* DIRECTINPUT_VERSION >= 0x050a */ +#if(DIRECTINPUT_VERSION >= 0x0800) +#define DIDC_HIDDEN 0x00040000 +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +#define DIDFT_ALL 0x00000000 + +#define DIDFT_RELAXIS 0x00000001 +#define DIDFT_ABSAXIS 0x00000002 +#define DIDFT_AXIS 0x00000003 + +#define DIDFT_PSHBUTTON 0x00000004 +#define DIDFT_TGLBUTTON 0x00000008 +#define DIDFT_BUTTON 0x0000000C + +#define DIDFT_POV 0x00000010 +#define DIDFT_COLLECTION 0x00000040 +#define DIDFT_NODATA 0x00000080 + +#define DIDFT_ANYINSTANCE 0x00FFFF00 +#define DIDFT_INSTANCEMASK DIDFT_ANYINSTANCE +#define DIDFT_MAKEINSTANCE(n) ((WORD)(n) << 8) +#define DIDFT_GETTYPE(n) LOBYTE(n) +#define DIDFT_GETINSTANCE(n) LOWORD((n) >> 8) +#define DIDFT_FFACTUATOR 0x01000000 +#define DIDFT_FFEFFECTTRIGGER 0x02000000 +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIDFT_OUTPUT 0x10000000 +#define DIDFT_VENDORDEFINED 0x04000000 +#define DIDFT_ALIAS 0x08000000 +#endif /* DIRECTINPUT_VERSION >= 0x050a */ + +#define DIDFT_ENUMCOLLECTION(n) ((WORD)(n) << 8) +#define DIDFT_NOCOLLECTION 0x00FFFF00 + +#ifndef DIJ_RINGZERO + +typedef struct _DIOBJECTDATAFORMAT { + const GUID *pguid; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; +} DIOBJECTDATAFORMAT, *LPDIOBJECTDATAFORMAT; +typedef const DIOBJECTDATAFORMAT *LPCDIOBJECTDATAFORMAT; + +typedef struct _DIDATAFORMAT { + DWORD dwSize; + DWORD dwObjSize; + DWORD dwFlags; + DWORD dwDataSize; + DWORD dwNumObjs; + LPDIOBJECTDATAFORMAT rgodf; +} DIDATAFORMAT, *LPDIDATAFORMAT; +typedef const DIDATAFORMAT *LPCDIDATAFORMAT; + +#define DIDF_ABSAXIS 0x00000001 +#define DIDF_RELAXIS 0x00000002 + +#ifdef __cplusplus +extern "C" { +#endif +extern const DIDATAFORMAT c_dfDIMouse; + +#if(DIRECTINPUT_VERSION >= 0x0700) +extern const DIDATAFORMAT c_dfDIMouse2; +#endif /* DIRECTINPUT_VERSION >= 0x0700 */ + +extern const DIDATAFORMAT c_dfDIKeyboard; + +#if(DIRECTINPUT_VERSION >= 0x0500) +extern const DIDATAFORMAT c_dfDIJoystick; +extern const DIDATAFORMAT c_dfDIJoystick2; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +#ifdef __cplusplus +}; +#endif + + +#if DIRECTINPUT_VERSION > 0x0700 + +typedef struct _DIACTIONA { + UINT_PTR uAppData; + DWORD dwSemantic; + OPTIONAL DWORD dwFlags; + OPTIONAL union { + LPCSTR lptszActionName; + UINT uResIdString; + }; + OPTIONAL GUID guidInstance; + OPTIONAL DWORD dwObjID; + OPTIONAL DWORD dwHow; +} DIACTIONA, *LPDIACTIONA ; +typedef struct _DIACTIONW { + UINT_PTR uAppData; + DWORD dwSemantic; + OPTIONAL DWORD dwFlags; + OPTIONAL union { + LPCWSTR lptszActionName; + UINT uResIdString; + }; + OPTIONAL GUID guidInstance; + OPTIONAL DWORD dwObjID; + OPTIONAL DWORD dwHow; +} DIACTIONW, *LPDIACTIONW ; +#ifdef UNICODE +typedef DIACTIONW DIACTION; +typedef LPDIACTIONW LPDIACTION; +#else +typedef DIACTIONA DIACTION; +typedef LPDIACTIONA LPDIACTION; +#endif // UNICODE + +typedef const DIACTIONA *LPCDIACTIONA; +typedef const DIACTIONW *LPCDIACTIONW; +#ifdef UNICODE +typedef DIACTIONW DIACTION; +typedef LPCDIACTIONW LPCDIACTION; +#else +typedef DIACTIONA DIACTION; +typedef LPCDIACTIONA LPCDIACTION; +#endif // UNICODE +typedef const DIACTION *LPCDIACTION; + + +#define DIA_FORCEFEEDBACK 0x00000001 +#define DIA_APPMAPPED 0x00000002 +#define DIA_APPNOMAP 0x00000004 +#define DIA_NORANGE 0x00000008 +#define DIA_APPFIXED 0x00000010 + +#define DIAH_UNMAPPED 0x00000000 +#define DIAH_USERCONFIG 0x00000001 +#define DIAH_APPREQUESTED 0x00000002 +#define DIAH_HWAPP 0x00000004 +#define DIAH_HWDEFAULT 0x00000008 +#define DIAH_DEFAULT 0x00000020 +#define DIAH_ERROR 0x80000000 + +typedef struct _DIACTIONFORMATA { + DWORD dwSize; + DWORD dwActionSize; + DWORD dwDataSize; + DWORD dwNumActions; + LPDIACTIONA rgoAction; + GUID guidActionMap; + DWORD dwGenre; + DWORD dwBufferSize; + OPTIONAL LONG lAxisMin; + OPTIONAL LONG lAxisMax; + OPTIONAL HINSTANCE hInstString; + FILETIME ftTimeStamp; + DWORD dwCRC; + CHAR tszActionMap[MAX_PATH]; +} DIACTIONFORMATA, *LPDIACTIONFORMATA; +typedef struct _DIACTIONFORMATW { + DWORD dwSize; + DWORD dwActionSize; + DWORD dwDataSize; + DWORD dwNumActions; + LPDIACTIONW rgoAction; + GUID guidActionMap; + DWORD dwGenre; + DWORD dwBufferSize; + OPTIONAL LONG lAxisMin; + OPTIONAL LONG lAxisMax; + OPTIONAL HINSTANCE hInstString; + FILETIME ftTimeStamp; + DWORD dwCRC; + WCHAR tszActionMap[MAX_PATH]; +} DIACTIONFORMATW, *LPDIACTIONFORMATW; +#ifdef UNICODE +typedef DIACTIONFORMATW DIACTIONFORMAT; +typedef LPDIACTIONFORMATW LPDIACTIONFORMAT; +#else +typedef DIACTIONFORMATA DIACTIONFORMAT; +typedef LPDIACTIONFORMATA LPDIACTIONFORMAT; +#endif // UNICODE +typedef const DIACTIONFORMATA *LPCDIACTIONFORMATA; +typedef const DIACTIONFORMATW *LPCDIACTIONFORMATW; +#ifdef UNICODE +typedef DIACTIONFORMATW DIACTIONFORMAT; +typedef LPCDIACTIONFORMATW LPCDIACTIONFORMAT; +#else +typedef DIACTIONFORMATA DIACTIONFORMAT; +typedef LPCDIACTIONFORMATA LPCDIACTIONFORMAT; +#endif // UNICODE +typedef const DIACTIONFORMAT *LPCDIACTIONFORMAT; + +#define DIAFTS_NEWDEVICELOW 0xFFFFFFFF +#define DIAFTS_NEWDEVICEHIGH 0xFFFFFFFF +#define DIAFTS_UNUSEDDEVICELOW 0x00000000 +#define DIAFTS_UNUSEDDEVICEHIGH 0x00000000 + +#define DIDBAM_DEFAULT 0x00000000 +#define DIDBAM_PRESERVE 0x00000001 +#define DIDBAM_INITIALIZE 0x00000002 +#define DIDBAM_HWDEFAULTS 0x00000004 + +#define DIDSAM_DEFAULT 0x00000000 +#define DIDSAM_NOUSER 0x00000001 +#define DIDSAM_FORCESAVE 0x00000002 + +#define DICD_DEFAULT 0x00000000 +#define DICD_EDIT 0x00000001 + +/* + * The following definition is normally defined in d3dtypes.h + */ +#ifndef D3DCOLOR_DEFINED +typedef DWORD D3DCOLOR; +#define D3DCOLOR_DEFINED +#endif + +typedef struct _DICOLORSET{ + DWORD dwSize; + D3DCOLOR cTextFore; + D3DCOLOR cTextHighlight; + D3DCOLOR cCalloutLine; + D3DCOLOR cCalloutHighlight; + D3DCOLOR cBorder; + D3DCOLOR cControlFill; + D3DCOLOR cHighlightFill; + D3DCOLOR cAreaFill; +} DICOLORSET, *LPDICOLORSET; +typedef const DICOLORSET *LPCDICOLORSET; + + +typedef struct _DICONFIGUREDEVICESPARAMSA{ + DWORD dwSize; + DWORD dwcUsers; + LPSTR lptszUserNames; + DWORD dwcFormats; + LPDIACTIONFORMATA lprgFormats; + HWND hwnd; + DICOLORSET dics; + IUnknown FAR * lpUnkDDSTarget; +} DICONFIGUREDEVICESPARAMSA, *LPDICONFIGUREDEVICESPARAMSA; +typedef struct _DICONFIGUREDEVICESPARAMSW{ + DWORD dwSize; + DWORD dwcUsers; + LPWSTR lptszUserNames; + DWORD dwcFormats; + LPDIACTIONFORMATW lprgFormats; + HWND hwnd; + DICOLORSET dics; + IUnknown FAR * lpUnkDDSTarget; +} DICONFIGUREDEVICESPARAMSW, *LPDICONFIGUREDEVICESPARAMSW; +#ifdef UNICODE +typedef DICONFIGUREDEVICESPARAMSW DICONFIGUREDEVICESPARAMS; +typedef LPDICONFIGUREDEVICESPARAMSW LPDICONFIGUREDEVICESPARAMS; +#else +typedef DICONFIGUREDEVICESPARAMSA DICONFIGUREDEVICESPARAMS; +typedef LPDICONFIGUREDEVICESPARAMSA LPDICONFIGUREDEVICESPARAMS; +#endif // UNICODE +typedef const DICONFIGUREDEVICESPARAMSA *LPCDICONFIGUREDEVICESPARAMSA; +typedef const DICONFIGUREDEVICESPARAMSW *LPCDICONFIGUREDEVICESPARAMSW; +#ifdef UNICODE +typedef DICONFIGUREDEVICESPARAMSW DICONFIGUREDEVICESPARAMS; +typedef LPCDICONFIGUREDEVICESPARAMSW LPCDICONFIGUREDEVICESPARAMS; +#else +typedef DICONFIGUREDEVICESPARAMSA DICONFIGUREDEVICESPARAMS; +typedef LPCDICONFIGUREDEVICESPARAMSA LPCDICONFIGUREDEVICESPARAMS; +#endif // UNICODE +typedef const DICONFIGUREDEVICESPARAMS *LPCDICONFIGUREDEVICESPARAMS; + + +#define DIDIFT_CONFIGURATION 0x00000001 +#define DIDIFT_OVERLAY 0x00000002 + +#define DIDAL_CENTERED 0x00000000 +#define DIDAL_LEFTALIGNED 0x00000001 +#define DIDAL_RIGHTALIGNED 0x00000002 +#define DIDAL_MIDDLE 0x00000000 +#define DIDAL_TOPALIGNED 0x00000004 +#define DIDAL_BOTTOMALIGNED 0x00000008 + +typedef struct _DIDEVICEIMAGEINFOA { + CHAR tszImagePath[MAX_PATH]; + DWORD dwFlags; + // These are valid if DIDIFT_OVERLAY is present in dwFlags. + DWORD dwViewID; + RECT rcOverlay; + DWORD dwObjID; + DWORD dwcValidPts; + POINT rgptCalloutLine[5]; + RECT rcCalloutRect; + DWORD dwTextAlign; +} DIDEVICEIMAGEINFOA, *LPDIDEVICEIMAGEINFOA; +typedef struct _DIDEVICEIMAGEINFOW { + WCHAR tszImagePath[MAX_PATH]; + DWORD dwFlags; + // These are valid if DIDIFT_OVERLAY is present in dwFlags. + DWORD dwViewID; + RECT rcOverlay; + DWORD dwObjID; + DWORD dwcValidPts; + POINT rgptCalloutLine[5]; + RECT rcCalloutRect; + DWORD dwTextAlign; +} DIDEVICEIMAGEINFOW, *LPDIDEVICEIMAGEINFOW; +#ifdef UNICODE +typedef DIDEVICEIMAGEINFOW DIDEVICEIMAGEINFO; +typedef LPDIDEVICEIMAGEINFOW LPDIDEVICEIMAGEINFO; +#else +typedef DIDEVICEIMAGEINFOA DIDEVICEIMAGEINFO; +typedef LPDIDEVICEIMAGEINFOA LPDIDEVICEIMAGEINFO; +#endif // UNICODE +typedef const DIDEVICEIMAGEINFOA *LPCDIDEVICEIMAGEINFOA; +typedef const DIDEVICEIMAGEINFOW *LPCDIDEVICEIMAGEINFOW; +#ifdef UNICODE +typedef DIDEVICEIMAGEINFOW DIDEVICEIMAGEINFO; +typedef LPCDIDEVICEIMAGEINFOW LPCDIDEVICEIMAGEINFO; +#else +typedef DIDEVICEIMAGEINFOA DIDEVICEIMAGEINFO; +typedef LPCDIDEVICEIMAGEINFOA LPCDIDEVICEIMAGEINFO; +#endif // UNICODE +typedef const DIDEVICEIMAGEINFO *LPCDIDEVICEIMAGEINFO; + +typedef struct _DIDEVICEIMAGEINFOHEADERA { + DWORD dwSize; + DWORD dwSizeImageInfo; + DWORD dwcViews; + DWORD dwcButtons; + DWORD dwcAxes; + DWORD dwcPOVs; + DWORD dwBufferSize; + DWORD dwBufferUsed; + LPDIDEVICEIMAGEINFOA lprgImageInfoArray; +} DIDEVICEIMAGEINFOHEADERA, *LPDIDEVICEIMAGEINFOHEADERA; +typedef struct _DIDEVICEIMAGEINFOHEADERW { + DWORD dwSize; + DWORD dwSizeImageInfo; + DWORD dwcViews; + DWORD dwcButtons; + DWORD dwcAxes; + DWORD dwcPOVs; + DWORD dwBufferSize; + DWORD dwBufferUsed; + LPDIDEVICEIMAGEINFOW lprgImageInfoArray; +} DIDEVICEIMAGEINFOHEADERW, *LPDIDEVICEIMAGEINFOHEADERW; +#ifdef UNICODE +typedef DIDEVICEIMAGEINFOHEADERW DIDEVICEIMAGEINFOHEADER; +typedef LPDIDEVICEIMAGEINFOHEADERW LPDIDEVICEIMAGEINFOHEADER; +#else +typedef DIDEVICEIMAGEINFOHEADERA DIDEVICEIMAGEINFOHEADER; +typedef LPDIDEVICEIMAGEINFOHEADERA LPDIDEVICEIMAGEINFOHEADER; +#endif // UNICODE +typedef const DIDEVICEIMAGEINFOHEADERA *LPCDIDEVICEIMAGEINFOHEADERA; +typedef const DIDEVICEIMAGEINFOHEADERW *LPCDIDEVICEIMAGEINFOHEADERW; +#ifdef UNICODE +typedef DIDEVICEIMAGEINFOHEADERW DIDEVICEIMAGEINFOHEADER; +typedef LPCDIDEVICEIMAGEINFOHEADERW LPCDIDEVICEIMAGEINFOHEADER; +#else +typedef DIDEVICEIMAGEINFOHEADERA DIDEVICEIMAGEINFOHEADER; +typedef LPCDIDEVICEIMAGEINFOHEADERA LPCDIDEVICEIMAGEINFOHEADER; +#endif // UNICODE +typedef const DIDEVICEIMAGEINFOHEADER *LPCDIDEVICEIMAGEINFOHEADER; + +#endif /* DIRECTINPUT_VERSION > 0x0700 */ + +#if(DIRECTINPUT_VERSION >= 0x0500) +/* These structures are defined for DirectX 3.0 compatibility */ + +typedef struct DIDEVICEOBJECTINSTANCE_DX3A { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + CHAR tszName[MAX_PATH]; +} DIDEVICEOBJECTINSTANCE_DX3A, *LPDIDEVICEOBJECTINSTANCE_DX3A; +typedef struct DIDEVICEOBJECTINSTANCE_DX3W { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + WCHAR tszName[MAX_PATH]; +} DIDEVICEOBJECTINSTANCE_DX3W, *LPDIDEVICEOBJECTINSTANCE_DX3W; +#ifdef UNICODE +typedef DIDEVICEOBJECTINSTANCE_DX3W DIDEVICEOBJECTINSTANCE_DX3; +typedef LPDIDEVICEOBJECTINSTANCE_DX3W LPDIDEVICEOBJECTINSTANCE_DX3; +#else +typedef DIDEVICEOBJECTINSTANCE_DX3A DIDEVICEOBJECTINSTANCE_DX3; +typedef LPDIDEVICEOBJECTINSTANCE_DX3A LPDIDEVICEOBJECTINSTANCE_DX3; +#endif // UNICODE +typedef const DIDEVICEOBJECTINSTANCE_DX3A *LPCDIDEVICEOBJECTINSTANCE_DX3A; +typedef const DIDEVICEOBJECTINSTANCE_DX3W *LPCDIDEVICEOBJECTINSTANCE_DX3W; +typedef const DIDEVICEOBJECTINSTANCE_DX3 *LPCDIDEVICEOBJECTINSTANCE_DX3; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +typedef struct DIDEVICEOBJECTINSTANCEA { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + CHAR tszName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + DWORD dwFFMaxForce; + DWORD dwFFForceResolution; + WORD wCollectionNumber; + WORD wDesignatorIndex; + WORD wUsagePage; + WORD wUsage; + DWORD dwDimension; + WORD wExponent; + WORD wReportId; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEOBJECTINSTANCEA, *LPDIDEVICEOBJECTINSTANCEA; +typedef struct DIDEVICEOBJECTINSTANCEW { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + WCHAR tszName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + DWORD dwFFMaxForce; + DWORD dwFFForceResolution; + WORD wCollectionNumber; + WORD wDesignatorIndex; + WORD wUsagePage; + WORD wUsage; + DWORD dwDimension; + WORD wExponent; + WORD wReportId; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEOBJECTINSTANCEW, *LPDIDEVICEOBJECTINSTANCEW; +#ifdef UNICODE +typedef DIDEVICEOBJECTINSTANCEW DIDEVICEOBJECTINSTANCE; +typedef LPDIDEVICEOBJECTINSTANCEW LPDIDEVICEOBJECTINSTANCE; +#else +typedef DIDEVICEOBJECTINSTANCEA DIDEVICEOBJECTINSTANCE; +typedef LPDIDEVICEOBJECTINSTANCEA LPDIDEVICEOBJECTINSTANCE; +#endif // UNICODE +typedef const DIDEVICEOBJECTINSTANCEA *LPCDIDEVICEOBJECTINSTANCEA; +typedef const DIDEVICEOBJECTINSTANCEW *LPCDIDEVICEOBJECTINSTANCEW; +typedef const DIDEVICEOBJECTINSTANCE *LPCDIDEVICEOBJECTINSTANCE; + +typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKA)(LPCDIDEVICEOBJECTINSTANCEA, LPVOID); +typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKW)(LPCDIDEVICEOBJECTINSTANCEW, LPVOID); +#ifdef UNICODE +#define LPDIENUMDEVICEOBJECTSCALLBACK LPDIENUMDEVICEOBJECTSCALLBACKW +#else +#define LPDIENUMDEVICEOBJECTSCALLBACK LPDIENUMDEVICEOBJECTSCALLBACKA +#endif // !UNICODE + +#if(DIRECTINPUT_VERSION >= 0x0500) +#define DIDOI_FFACTUATOR 0x00000001 +#define DIDOI_FFEFFECTTRIGGER 0x00000002 +#define DIDOI_POLLED 0x00008000 +#define DIDOI_ASPECTPOSITION 0x00000100 +#define DIDOI_ASPECTVELOCITY 0x00000200 +#define DIDOI_ASPECTACCEL 0x00000300 +#define DIDOI_ASPECTFORCE 0x00000400 +#define DIDOI_ASPECTMASK 0x00000F00 +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIDOI_GUIDISUSAGE 0x00010000 +#endif /* DIRECTINPUT_VERSION >= 0x050a */ + +typedef struct DIPROPHEADER { + DWORD dwSize; + DWORD dwHeaderSize; + DWORD dwObj; + DWORD dwHow; +} DIPROPHEADER, *LPDIPROPHEADER; +typedef const DIPROPHEADER *LPCDIPROPHEADER; + +#define DIPH_DEVICE 0 +#define DIPH_BYOFFSET 1 +#define DIPH_BYID 2 +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIPH_BYUSAGE 3 +#endif /* DIRECTINPUT_VERSION >= 0x050a */ + +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIMAKEUSAGEDWORD(UsagePage, Usage) \ + (DWORD)MAKELONG(Usage, UsagePage) +#endif /* DIRECTINPUT_VERSION >= 0x050a */ + +typedef struct DIPROPDWORD { + DIPROPHEADER diph; + DWORD dwData; +} DIPROPDWORD, *LPDIPROPDWORD; +typedef const DIPROPDWORD *LPCDIPROPDWORD; + +#if(DIRECTINPUT_VERSION >= 0x0800) +typedef struct DIPROPPOINTER { + DIPROPHEADER diph; + UINT_PTR uData; +} DIPROPPOINTER, *LPDIPROPPOINTER; +typedef const DIPROPPOINTER *LPCDIPROPPOINTER; +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +typedef struct DIPROPRANGE { + DIPROPHEADER diph; + LONG lMin; + LONG lMax; +} DIPROPRANGE, *LPDIPROPRANGE; +typedef const DIPROPRANGE *LPCDIPROPRANGE; + +#define DIPROPRANGE_NOMIN ((LONG)0x80000000) +#define DIPROPRANGE_NOMAX ((LONG)0x7FFFFFFF) + +#if(DIRECTINPUT_VERSION >= 0x050a) +typedef struct DIPROPCAL { + DIPROPHEADER diph; + LONG lMin; + LONG lCenter; + LONG lMax; +} DIPROPCAL, *LPDIPROPCAL; +typedef const DIPROPCAL *LPCDIPROPCAL; + +typedef struct DIPROPCALPOV { + DIPROPHEADER diph; + LONG lMin[5]; + LONG lMax[5]; +} DIPROPCALPOV, *LPDIPROPCALPOV; +typedef const DIPROPCALPOV *LPCDIPROPCALPOV; + +typedef struct DIPROPGUIDANDPATH { + DIPROPHEADER diph; + GUID guidClass; + WCHAR wszPath[MAX_PATH]; +} DIPROPGUIDANDPATH, *LPDIPROPGUIDANDPATH; +typedef const DIPROPGUIDANDPATH *LPCDIPROPGUIDANDPATH; + +typedef struct DIPROPSTRING { + DIPROPHEADER diph; + WCHAR wsz[MAX_PATH]; +} DIPROPSTRING, *LPDIPROPSTRING; +typedef const DIPROPSTRING *LPCDIPROPSTRING; + +#endif /* DIRECTINPUT_VERSION >= 0x050a */ + +#if(DIRECTINPUT_VERSION >= 0x0800) +#define MAXCPOINTSNUM 8 + +typedef struct _CPOINT +{ + LONG lP; // raw value + DWORD dwLog; // logical_value / max_logical_value * 10000 +} CPOINT, *PCPOINT; + +typedef struct DIPROPCPOINTS { + DIPROPHEADER diph; + DWORD dwCPointsNum; + CPOINT cp[MAXCPOINTSNUM]; +} DIPROPCPOINTS, *LPDIPROPCPOINTS; +typedef const DIPROPCPOINTS *LPCDIPROPCPOINTS; +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + + +#ifdef __cplusplus +#define MAKEDIPROP(prop) (*(const GUID *)(prop)) +#else +#define MAKEDIPROP(prop) ((REFGUID)(prop)) +#endif + +#define DIPROP_BUFFERSIZE MAKEDIPROP(1) + +#define DIPROP_AXISMODE MAKEDIPROP(2) + +#define DIPROPAXISMODE_ABS 0 +#define DIPROPAXISMODE_REL 1 + +#define DIPROP_GRANULARITY MAKEDIPROP(3) + +#define DIPROP_RANGE MAKEDIPROP(4) + +#define DIPROP_DEADZONE MAKEDIPROP(5) + +#define DIPROP_SATURATION MAKEDIPROP(6) + +#define DIPROP_FFGAIN MAKEDIPROP(7) + +#define DIPROP_FFLOAD MAKEDIPROP(8) + +#define DIPROP_AUTOCENTER MAKEDIPROP(9) + +#define DIPROPAUTOCENTER_OFF 0 +#define DIPROPAUTOCENTER_ON 1 + +#define DIPROP_CALIBRATIONMODE MAKEDIPROP(10) + +#define DIPROPCALIBRATIONMODE_COOKED 0 +#define DIPROPCALIBRATIONMODE_RAW 1 + +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIPROP_CALIBRATION MAKEDIPROP(11) + +#define DIPROP_GUIDANDPATH MAKEDIPROP(12) + +#define DIPROP_INSTANCENAME MAKEDIPROP(13) + +#define DIPROP_PRODUCTNAME MAKEDIPROP(14) +#endif /* DIRECTINPUT_VERSION >= 0x050a */ + +#if(DIRECTINPUT_VERSION >= 0x05b2) +#define DIPROP_JOYSTICKID MAKEDIPROP(15) + +#define DIPROP_GETPORTDISPLAYNAME MAKEDIPROP(16) + +#endif /* DIRECTINPUT_VERSION >= 0x05b2 */ + +#if(DIRECTINPUT_VERSION >= 0x0700) +#define DIPROP_PHYSICALRANGE MAKEDIPROP(18) + +#define DIPROP_LOGICALRANGE MAKEDIPROP(19) +#endif /* DIRECTINPUT_VERSION >= 0x0700 */ + +#if(DIRECTINPUT_VERSION >= 0x0800) +#define DIPROP_KEYNAME MAKEDIPROP(20) + +#define DIPROP_CPOINTS MAKEDIPROP(21) + +#define DIPROP_APPDATA MAKEDIPROP(22) + +#define DIPROP_SCANCODE MAKEDIPROP(23) + +#define DIPROP_VIDPID MAKEDIPROP(24) + +#define DIPROP_USERNAME MAKEDIPROP(25) + +#define DIPROP_TYPENAME MAKEDIPROP(26) +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + + +typedef struct DIDEVICEOBJECTDATA_DX3 { + DWORD dwOfs; + DWORD dwData; + DWORD dwTimeStamp; + DWORD dwSequence; +} DIDEVICEOBJECTDATA_DX3, *LPDIDEVICEOBJECTDATA_DX3; +typedef const DIDEVICEOBJECTDATA_DX3 *LPCDIDEVICEOBJECTDATA_DX; + +typedef struct DIDEVICEOBJECTDATA { + DWORD dwOfs; + DWORD dwData; + DWORD dwTimeStamp; + DWORD dwSequence; +#if(DIRECTINPUT_VERSION >= 0x0800) + UINT_PTR uAppData; +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ +} DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA; +typedef const DIDEVICEOBJECTDATA *LPCDIDEVICEOBJECTDATA; + +#define DIGDD_PEEK 0x00000001 + +#define DISEQUENCE_COMPARE(dwSequence1, cmp, dwSequence2) \ + ((int)((dwSequence1) - (dwSequence2)) cmp 0) +#define DISCL_EXCLUSIVE 0x00000001 +#define DISCL_NONEXCLUSIVE 0x00000002 +#define DISCL_FOREGROUND 0x00000004 +#define DISCL_BACKGROUND 0x00000008 +#define DISCL_NOWINKEY 0x00000010 + +#if(DIRECTINPUT_VERSION >= 0x0500) +/* These structures are defined for DirectX 3.0 compatibility */ + +typedef struct DIDEVICEINSTANCE_DX3A { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + CHAR tszInstanceName[MAX_PATH]; + CHAR tszProductName[MAX_PATH]; +} DIDEVICEINSTANCE_DX3A, *LPDIDEVICEINSTANCE_DX3A; +typedef struct DIDEVICEINSTANCE_DX3W { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + WCHAR tszInstanceName[MAX_PATH]; + WCHAR tszProductName[MAX_PATH]; +} DIDEVICEINSTANCE_DX3W, *LPDIDEVICEINSTANCE_DX3W; +#ifdef UNICODE +typedef DIDEVICEINSTANCE_DX3W DIDEVICEINSTANCE_DX3; +typedef LPDIDEVICEINSTANCE_DX3W LPDIDEVICEINSTANCE_DX3; +#else +typedef DIDEVICEINSTANCE_DX3A DIDEVICEINSTANCE_DX3; +typedef LPDIDEVICEINSTANCE_DX3A LPDIDEVICEINSTANCE_DX3; +#endif // UNICODE +typedef const DIDEVICEINSTANCE_DX3A *LPCDIDEVICEINSTANCE_DX3A; +typedef const DIDEVICEINSTANCE_DX3W *LPCDIDEVICEINSTANCE_DX3W; +typedef const DIDEVICEINSTANCE_DX3 *LPCDIDEVICEINSTANCE_DX3; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +typedef struct DIDEVICEINSTANCEA { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + CHAR tszInstanceName[MAX_PATH]; + CHAR tszProductName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + GUID guidFFDriver; + WORD wUsagePage; + WORD wUsage; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEINSTANCEA, *LPDIDEVICEINSTANCEA; +typedef struct DIDEVICEINSTANCEW { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + WCHAR tszInstanceName[MAX_PATH]; + WCHAR tszProductName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + GUID guidFFDriver; + WORD wUsagePage; + WORD wUsage; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEINSTANCEW, *LPDIDEVICEINSTANCEW; +#ifdef UNICODE +typedef DIDEVICEINSTANCEW DIDEVICEINSTANCE; +typedef LPDIDEVICEINSTANCEW LPDIDEVICEINSTANCE; +#else +typedef DIDEVICEINSTANCEA DIDEVICEINSTANCE; +typedef LPDIDEVICEINSTANCEA LPDIDEVICEINSTANCE; +#endif // UNICODE + +typedef const DIDEVICEINSTANCEA *LPCDIDEVICEINSTANCEA; +typedef const DIDEVICEINSTANCEW *LPCDIDEVICEINSTANCEW; +#ifdef UNICODE +typedef DIDEVICEINSTANCEW DIDEVICEINSTANCE; +typedef LPCDIDEVICEINSTANCEW LPCDIDEVICEINSTANCE; +#else +typedef DIDEVICEINSTANCEA DIDEVICEINSTANCE; +typedef LPCDIDEVICEINSTANCEA LPCDIDEVICEINSTANCE; +#endif // UNICODE +typedef const DIDEVICEINSTANCE *LPCDIDEVICEINSTANCE; + +#undef INTERFACE +#define INTERFACE IDirectInputDeviceW + +DECLARE_INTERFACE_(IDirectInputDeviceW, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; +}; + +typedef struct IDirectInputDeviceW *LPDIRECTINPUTDEVICEW; + +#undef INTERFACE +#define INTERFACE IDirectInputDeviceA + +DECLARE_INTERFACE_(IDirectInputDeviceA, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; +}; + +typedef struct IDirectInputDeviceA *LPDIRECTINPUTDEVICEA; + +#ifdef UNICODE +#define IID_IDirectInputDevice IID_IDirectInputDeviceW +#define IDirectInputDevice IDirectInputDeviceW +#define IDirectInputDeviceVtbl IDirectInputDeviceWVtbl +#else +#define IID_IDirectInputDevice IID_IDirectInputDeviceA +#define IDirectInputDevice IDirectInputDeviceA +#define IDirectInputDeviceVtbl IDirectInputDeviceAVtbl +#endif +typedef struct IDirectInputDevice *LPDIRECTINPUTDEVICE; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInputDevice_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInputDevice_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#else +#define IDirectInputDevice_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice_AddRef(p) (p)->AddRef() +#define IDirectInputDevice_Release(p) (p)->Release() +#define IDirectInputDevice_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice_Acquire(p) (p)->Acquire() +#define IDirectInputDevice_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#endif + +#endif /* DIJ_RINGZERO */ + + +#if(DIRECTINPUT_VERSION >= 0x0500) + +#define DISFFC_RESET 0x00000001 +#define DISFFC_STOPALL 0x00000002 +#define DISFFC_PAUSE 0x00000004 +#define DISFFC_CONTINUE 0x00000008 +#define DISFFC_SETACTUATORSON 0x00000010 +#define DISFFC_SETACTUATORSOFF 0x00000020 + +#define DIGFFS_EMPTY 0x00000001 +#define DIGFFS_STOPPED 0x00000002 +#define DIGFFS_PAUSED 0x00000004 +#define DIGFFS_ACTUATORSON 0x00000010 +#define DIGFFS_ACTUATORSOFF 0x00000020 +#define DIGFFS_POWERON 0x00000040 +#define DIGFFS_POWEROFF 0x00000080 +#define DIGFFS_SAFETYSWITCHON 0x00000100 +#define DIGFFS_SAFETYSWITCHOFF 0x00000200 +#define DIGFFS_USERFFSWITCHON 0x00000400 +#define DIGFFS_USERFFSWITCHOFF 0x00000800 +#define DIGFFS_DEVICELOST 0x80000000 + +#ifndef DIJ_RINGZERO + +typedef struct DIEFFECTINFOA { + DWORD dwSize; + GUID guid; + DWORD dwEffType; + DWORD dwStaticParams; + DWORD dwDynamicParams; + CHAR tszName[MAX_PATH]; +} DIEFFECTINFOA, *LPDIEFFECTINFOA; +typedef struct DIEFFECTINFOW { + DWORD dwSize; + GUID guid; + DWORD dwEffType; + DWORD dwStaticParams; + DWORD dwDynamicParams; + WCHAR tszName[MAX_PATH]; +} DIEFFECTINFOW, *LPDIEFFECTINFOW; +#ifdef UNICODE +typedef DIEFFECTINFOW DIEFFECTINFO; +typedef LPDIEFFECTINFOW LPDIEFFECTINFO; +#else +typedef DIEFFECTINFOA DIEFFECTINFO; +typedef LPDIEFFECTINFOA LPDIEFFECTINFO; +#endif // UNICODE +typedef const DIEFFECTINFOA *LPCDIEFFECTINFOA; +typedef const DIEFFECTINFOW *LPCDIEFFECTINFOW; +typedef const DIEFFECTINFO *LPCDIEFFECTINFO; + +#define DISDD_CONTINUE 0x00000001 + +typedef BOOL (FAR PASCAL * LPDIENUMEFFECTSCALLBACKA)(LPCDIEFFECTINFOA, LPVOID); +typedef BOOL (FAR PASCAL * LPDIENUMEFFECTSCALLBACKW)(LPCDIEFFECTINFOW, LPVOID); +#ifdef UNICODE +#define LPDIENUMEFFECTSCALLBACK LPDIENUMEFFECTSCALLBACKW +#else +#define LPDIENUMEFFECTSCALLBACK LPDIENUMEFFECTSCALLBACKA +#endif // !UNICODE +typedef BOOL (FAR PASCAL * LPDIENUMCREATEDEFFECTOBJECTSCALLBACK)(LPDIRECTINPUTEFFECT, LPVOID); + +#undef INTERFACE +#define INTERFACE IDirectInputDevice2W + +DECLARE_INTERFACE_(IDirectInputDevice2W, IDirectInputDeviceW) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + + /*** IDirectInputDevice2W methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW,REFGUID) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; +}; + +typedef struct IDirectInputDevice2W *LPDIRECTINPUTDEVICE2W; + +#undef INTERFACE +#define INTERFACE IDirectInputDevice2A + +DECLARE_INTERFACE_(IDirectInputDevice2A, IDirectInputDeviceA) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + + /*** IDirectInputDevice2A methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA,REFGUID) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; +}; + +typedef struct IDirectInputDevice2A *LPDIRECTINPUTDEVICE2A; + +#ifdef UNICODE +#define IID_IDirectInputDevice2 IID_IDirectInputDevice2W +#define IDirectInputDevice2 IDirectInputDevice2W +#define IDirectInputDevice2Vtbl IDirectInputDevice2WVtbl +#else +#define IID_IDirectInputDevice2 IID_IDirectInputDevice2A +#define IDirectInputDevice2 IDirectInputDevice2A +#define IDirectInputDevice2Vtbl IDirectInputDevice2AVtbl +#endif +typedef struct IDirectInputDevice2 *LPDIRECTINPUTDEVICE2; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInputDevice2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice2_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInputDevice2_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice2_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice2_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice2_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice2_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice2_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice2_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice2_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice2_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice2_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice2_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice2_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice2_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice2_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice2_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#define IDirectInputDevice2_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d) +#define IDirectInputDevice2_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c) +#define IDirectInputDevice2_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b) +#define IDirectInputDevice2_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a) +#define IDirectInputDevice2_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a) +#define IDirectInputDevice2_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c) +#define IDirectInputDevice2_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#define IDirectInputDevice2_Poll(p) (p)->lpVtbl->Poll(p) +#define IDirectInputDevice2_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d) +#else +#define IDirectInputDevice2_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice2_AddRef(p) (p)->AddRef() +#define IDirectInputDevice2_Release(p) (p)->Release() +#define IDirectInputDevice2_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice2_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice2_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice2_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice2_Acquire(p) (p)->Acquire() +#define IDirectInputDevice2_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice2_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice2_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice2_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice2_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice2_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice2_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice2_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice2_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice2_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#define IDirectInputDevice2_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d) +#define IDirectInputDevice2_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c) +#define IDirectInputDevice2_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b) +#define IDirectInputDevice2_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a) +#define IDirectInputDevice2_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a) +#define IDirectInputDevice2_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c) +#define IDirectInputDevice2_Escape(p,a) (p)->Escape(a) +#define IDirectInputDevice2_Poll(p) (p)->Poll() +#define IDirectInputDevice2_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d) +#endif + +#endif /* DIJ_RINGZERO */ + +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +#if(DIRECTINPUT_VERSION >= 0x0700) +#define DIFEF_DEFAULT 0x00000000 +#define DIFEF_INCLUDENONSTANDARD 0x00000001 +#define DIFEF_MODIFYIFNEEDED 0x00000010 + +#ifndef DIJ_RINGZERO + +#undef INTERFACE +#define INTERFACE IDirectInputDevice7W + +DECLARE_INTERFACE_(IDirectInputDevice7W, IDirectInputDevice2W) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDevice2W methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW,REFGUID) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + + /*** IDirectInputDevice7W methods ***/ + STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE; +}; + +typedef struct IDirectInputDevice7W *LPDIRECTINPUTDEVICE7W; + +#undef INTERFACE +#define INTERFACE IDirectInputDevice7A + +DECLARE_INTERFACE_(IDirectInputDevice7A, IDirectInputDevice2A) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDevice2A methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA,REFGUID) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + + /*** IDirectInputDevice7A methods ***/ + STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE; +}; + +typedef struct IDirectInputDevice7A *LPDIRECTINPUTDEVICE7A; + +#ifdef UNICODE +#define IID_IDirectInputDevice7 IID_IDirectInputDevice7W +#define IDirectInputDevice7 IDirectInputDevice7W +#define IDirectInputDevice7Vtbl IDirectInputDevice7WVtbl +#else +#define IID_IDirectInputDevice7 IID_IDirectInputDevice7A +#define IDirectInputDevice7 IDirectInputDevice7A +#define IDirectInputDevice7Vtbl IDirectInputDevice7AVtbl +#endif +typedef struct IDirectInputDevice7 *LPDIRECTINPUTDEVICE7; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInputDevice7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice7_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice7_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInputDevice7_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice7_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice7_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice7_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice7_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice7_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice7_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice7_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice7_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice7_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice7_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice7_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice7_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice7_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice7_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#define IDirectInputDevice7_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d) +#define IDirectInputDevice7_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c) +#define IDirectInputDevice7_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b) +#define IDirectInputDevice7_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a) +#define IDirectInputDevice7_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a) +#define IDirectInputDevice7_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c) +#define IDirectInputDevice7_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#define IDirectInputDevice7_Poll(p) (p)->lpVtbl->Poll(p) +#define IDirectInputDevice7_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d) +#define IDirectInputDevice7_EnumEffectsInFile(p,a,b,c,d) (p)->lpVtbl->EnumEffectsInFile(p,a,b,c,d) +#define IDirectInputDevice7_WriteEffectToFile(p,a,b,c,d) (p)->lpVtbl->WriteEffectToFile(p,a,b,c,d) +#else +#define IDirectInputDevice7_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice7_AddRef(p) (p)->AddRef() +#define IDirectInputDevice7_Release(p) (p)->Release() +#define IDirectInputDevice7_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice7_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice7_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice7_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice7_Acquire(p) (p)->Acquire() +#define IDirectInputDevice7_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice7_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice7_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice7_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice7_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice7_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice7_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice7_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice7_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice7_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#define IDirectInputDevice7_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d) +#define IDirectInputDevice7_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c) +#define IDirectInputDevice7_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b) +#define IDirectInputDevice7_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a) +#define IDirectInputDevice7_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a) +#define IDirectInputDevice7_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c) +#define IDirectInputDevice7_Escape(p,a) (p)->Escape(a) +#define IDirectInputDevice7_Poll(p) (p)->Poll() +#define IDirectInputDevice7_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d) +#define IDirectInputDevice7_EnumEffectsInFile(p,a,b,c,d) (p)->EnumEffectsInFile(a,b,c,d) +#define IDirectInputDevice7_WriteEffectToFile(p,a,b,c,d) (p)->WriteEffectToFile(a,b,c,d) +#endif + +#endif /* DIJ_RINGZERO */ + +#endif /* DIRECTINPUT_VERSION >= 0x0700 */ + +#if(DIRECTINPUT_VERSION >= 0x0800) + +#ifndef DIJ_RINGZERO + +#undef INTERFACE +#define INTERFACE IDirectInputDevice8W + +DECLARE_INTERFACE_(IDirectInputDevice8W, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDevice8W methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW,REFGUID) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE; + STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATW,LPCWSTR,DWORD) PURE; + STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATW,LPCWSTR,DWORD) PURE; + STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERW) PURE; +}; + +typedef struct IDirectInputDevice8W *LPDIRECTINPUTDEVICE8W; + +#undef INTERFACE +#define INTERFACE IDirectInputDevice8A + +DECLARE_INTERFACE_(IDirectInputDevice8A, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDevice8A methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA,REFGUID) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE; + STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATA,LPCSTR,DWORD) PURE; + STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATA,LPCSTR,DWORD) PURE; + STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERA) PURE; +}; + +typedef struct IDirectInputDevice8A *LPDIRECTINPUTDEVICE8A; + +#ifdef UNICODE +#define IID_IDirectInputDevice8 IID_IDirectInputDevice8W +#define IDirectInputDevice8 IDirectInputDevice8W +#define IDirectInputDevice8Vtbl IDirectInputDevice8WVtbl +#else +#define IID_IDirectInputDevice8 IID_IDirectInputDevice8A +#define IDirectInputDevice8 IDirectInputDevice8A +#define IDirectInputDevice8Vtbl IDirectInputDevice8AVtbl +#endif +typedef struct IDirectInputDevice8 *LPDIRECTINPUTDEVICE8; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInputDevice8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice8_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice8_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInputDevice8_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice8_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice8_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice8_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice8_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice8_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice8_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice8_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice8_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice8_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice8_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice8_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice8_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice8_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice8_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#define IDirectInputDevice8_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d) +#define IDirectInputDevice8_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c) +#define IDirectInputDevice8_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b) +#define IDirectInputDevice8_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a) +#define IDirectInputDevice8_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a) +#define IDirectInputDevice8_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c) +#define IDirectInputDevice8_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#define IDirectInputDevice8_Poll(p) (p)->lpVtbl->Poll(p) +#define IDirectInputDevice8_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d) +#define IDirectInputDevice8_EnumEffectsInFile(p,a,b,c,d) (p)->lpVtbl->EnumEffectsInFile(p,a,b,c,d) +#define IDirectInputDevice8_WriteEffectToFile(p,a,b,c,d) (p)->lpVtbl->WriteEffectToFile(p,a,b,c,d) +#define IDirectInputDevice8_BuildActionMap(p,a,b,c) (p)->lpVtbl->BuildActionMap(p,a,b,c) +#define IDirectInputDevice8_SetActionMap(p,a,b,c) (p)->lpVtbl->SetActionMap(p,a,b,c) +#define IDirectInputDevice8_GetImageInfo(p,a) (p)->lpVtbl->GetImageInfo(p,a) +#else +#define IDirectInputDevice8_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice8_AddRef(p) (p)->AddRef() +#define IDirectInputDevice8_Release(p) (p)->Release() +#define IDirectInputDevice8_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice8_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice8_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice8_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice8_Acquire(p) (p)->Acquire() +#define IDirectInputDevice8_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice8_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice8_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice8_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice8_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice8_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice8_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice8_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice8_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice8_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#define IDirectInputDevice8_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d) +#define IDirectInputDevice8_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c) +#define IDirectInputDevice8_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b) +#define IDirectInputDevice8_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a) +#define IDirectInputDevice8_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a) +#define IDirectInputDevice8_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c) +#define IDirectInputDevice8_Escape(p,a) (p)->Escape(a) +#define IDirectInputDevice8_Poll(p) (p)->Poll() +#define IDirectInputDevice8_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d) +#define IDirectInputDevice8_EnumEffectsInFile(p,a,b,c,d) (p)->EnumEffectsInFile(a,b,c,d) +#define IDirectInputDevice8_WriteEffectToFile(p,a,b,c,d) (p)->WriteEffectToFile(a,b,c,d) +#define IDirectInputDevice8_BuildActionMap(p,a,b,c) (p)->BuildActionMap(a,b,c) +#define IDirectInputDevice8_SetActionMap(p,a,b,c) (p)->SetActionMap(a,b,c) +#define IDirectInputDevice8_GetImageInfo(p,a) (p)->GetImageInfo(a) +#endif + +#endif /* DIJ_RINGZERO */ + +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +/**************************************************************************** + * + * Mouse + * + ****************************************************************************/ + +#ifndef DIJ_RINGZERO + +typedef struct _DIMOUSESTATE { + LONG lX; + LONG lY; + LONG lZ; + BYTE rgbButtons[4]; +} DIMOUSESTATE, *LPDIMOUSESTATE; + +#if DIRECTINPUT_VERSION >= 0x0700 +typedef struct _DIMOUSESTATE2 { + LONG lX; + LONG lY; + LONG lZ; + BYTE rgbButtons[8]; +} DIMOUSESTATE2, *LPDIMOUSESTATE2; +#endif + + +#define DIMOFS_X FIELD_OFFSET(DIMOUSESTATE, lX) +#define DIMOFS_Y FIELD_OFFSET(DIMOUSESTATE, lY) +#define DIMOFS_Z FIELD_OFFSET(DIMOUSESTATE, lZ) +#define DIMOFS_BUTTON0 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 0) +#define DIMOFS_BUTTON1 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 1) +#define DIMOFS_BUTTON2 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 2) +#define DIMOFS_BUTTON3 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 3) +#if (DIRECTINPUT_VERSION >= 0x0700) +#define DIMOFS_BUTTON4 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 4) +#define DIMOFS_BUTTON5 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 5) +#define DIMOFS_BUTTON6 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 6) +#define DIMOFS_BUTTON7 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 7) +#endif +#endif /* DIJ_RINGZERO */ + +/**************************************************************************** + * + * Keyboard + * + ****************************************************************************/ + +#ifndef DIJ_RINGZERO + +/**************************************************************************** + * + * DirectInput keyboard scan codes + * + ****************************************************************************/ +#define DIK_ESCAPE 0x01 +#define DIK_1 0x02 +#define DIK_2 0x03 +#define DIK_3 0x04 +#define DIK_4 0x05 +#define DIK_5 0x06 +#define DIK_6 0x07 +#define DIK_7 0x08 +#define DIK_8 0x09 +#define DIK_9 0x0A +#define DIK_0 0x0B +#define DIK_MINUS 0x0C /* - on main keyboard */ +#define DIK_EQUALS 0x0D +#define DIK_BACK 0x0E /* backspace */ +#define DIK_TAB 0x0F +#define DIK_Q 0x10 +#define DIK_W 0x11 +#define DIK_E 0x12 +#define DIK_R 0x13 +#define DIK_T 0x14 +#define DIK_Y 0x15 +#define DIK_U 0x16 +#define DIK_I 0x17 +#define DIK_O 0x18 +#define DIK_P 0x19 +#define DIK_LBRACKET 0x1A +#define DIK_RBRACKET 0x1B +#define DIK_RETURN 0x1C /* Enter on main keyboard */ +#define DIK_LCONTROL 0x1D +#define DIK_A 0x1E +#define DIK_S 0x1F +#define DIK_D 0x20 +#define DIK_F 0x21 +#define DIK_G 0x22 +#define DIK_H 0x23 +#define DIK_J 0x24 +#define DIK_K 0x25 +#define DIK_L 0x26 +#define DIK_SEMICOLON 0x27 +#define DIK_APOSTROPHE 0x28 +#define DIK_GRAVE 0x29 /* accent grave */ +#define DIK_LSHIFT 0x2A +#define DIK_BACKSLASH 0x2B +#define DIK_Z 0x2C +#define DIK_X 0x2D +#define DIK_C 0x2E +#define DIK_V 0x2F +#define DIK_B 0x30 +#define DIK_N 0x31 +#define DIK_M 0x32 +#define DIK_COMMA 0x33 +#define DIK_PERIOD 0x34 /* . on main keyboard */ +#define DIK_SLASH 0x35 /* / on main keyboard */ +#define DIK_RSHIFT 0x36 +#define DIK_MULTIPLY 0x37 /* * on numeric keypad */ +#define DIK_LMENU 0x38 /* left Alt */ +#define DIK_SPACE 0x39 +#define DIK_CAPITAL 0x3A +#define DIK_F1 0x3B +#define DIK_F2 0x3C +#define DIK_F3 0x3D +#define DIK_F4 0x3E +#define DIK_F5 0x3F +#define DIK_F6 0x40 +#define DIK_F7 0x41 +#define DIK_F8 0x42 +#define DIK_F9 0x43 +#define DIK_F10 0x44 +#define DIK_NUMLOCK 0x45 +#define DIK_SCROLL 0x46 /* Scroll Lock */ +#define DIK_NUMPAD7 0x47 +#define DIK_NUMPAD8 0x48 +#define DIK_NUMPAD9 0x49 +#define DIK_SUBTRACT 0x4A /* - on numeric keypad */ +#define DIK_NUMPAD4 0x4B +#define DIK_NUMPAD5 0x4C +#define DIK_NUMPAD6 0x4D +#define DIK_ADD 0x4E /* + on numeric keypad */ +#define DIK_NUMPAD1 0x4F +#define DIK_NUMPAD2 0x50 +#define DIK_NUMPAD3 0x51 +#define DIK_NUMPAD0 0x52 +#define DIK_DECIMAL 0x53 /* . on numeric keypad */ +#define DIK_OEM_102 0x56 /* <> or \| on RT 102-key keyboard (Non-U.S.) */ +#define DIK_F11 0x57 +#define DIK_F12 0x58 +#define DIK_F13 0x64 /* (NEC PC98) */ +#define DIK_F14 0x65 /* (NEC PC98) */ +#define DIK_F15 0x66 /* (NEC PC98) */ +#define DIK_KANA 0x70 /* (Japanese keyboard) */ +#define DIK_ABNT_C1 0x73 /* /? on Brazilian keyboard */ +#define DIK_CONVERT 0x79 /* (Japanese keyboard) */ +#define DIK_NOCONVERT 0x7B /* (Japanese keyboard) */ +#define DIK_YEN 0x7D /* (Japanese keyboard) */ +#define DIK_ABNT_C2 0x7E /* Numpad . on Brazilian keyboard */ +#define DIK_NUMPADEQUALS 0x8D /* = on numeric keypad (NEC PC98) */ +#define DIK_PREVTRACK 0x90 /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */ +#define DIK_AT 0x91 /* (NEC PC98) */ +#define DIK_COLON 0x92 /* (NEC PC98) */ +#define DIK_UNDERLINE 0x93 /* (NEC PC98) */ +#define DIK_KANJI 0x94 /* (Japanese keyboard) */ +#define DIK_STOP 0x95 /* (NEC PC98) */ +#define DIK_AX 0x96 /* (Japan AX) */ +#define DIK_UNLABELED 0x97 /* (J3100) */ +#define DIK_NEXTTRACK 0x99 /* Next Track */ +#define DIK_NUMPADENTER 0x9C /* Enter on numeric keypad */ +#define DIK_RCONTROL 0x9D +#define DIK_MUTE 0xA0 /* Mute */ +#define DIK_CALCULATOR 0xA1 /* Calculator */ +#define DIK_PLAYPAUSE 0xA2 /* Play / Pause */ +#define DIK_MEDIASTOP 0xA4 /* Media Stop */ +#define DIK_VOLUMEDOWN 0xAE /* Volume - */ +#define DIK_VOLUMEUP 0xB0 /* Volume + */ +#define DIK_WEBHOME 0xB2 /* Web home */ +#define DIK_NUMPADCOMMA 0xB3 /* , on numeric keypad (NEC PC98) */ +#define DIK_DIVIDE 0xB5 /* / on numeric keypad */ +#define DIK_SYSRQ 0xB7 +#define DIK_RMENU 0xB8 /* right Alt */ +#define DIK_PAUSE 0xC5 /* Pause */ +#define DIK_HOME 0xC7 /* Home on arrow keypad */ +#define DIK_UP 0xC8 /* UpArrow on arrow keypad */ +#define DIK_PRIOR 0xC9 /* PgUp on arrow keypad */ +#define DIK_LEFT 0xCB /* LeftArrow on arrow keypad */ +#define DIK_RIGHT 0xCD /* RightArrow on arrow keypad */ +#define DIK_END 0xCF /* End on arrow keypad */ +#define DIK_DOWN 0xD0 /* DownArrow on arrow keypad */ +#define DIK_NEXT 0xD1 /* PgDn on arrow keypad */ +#define DIK_INSERT 0xD2 /* Insert on arrow keypad */ +#define DIK_DELETE 0xD3 /* Delete on arrow keypad */ +#define DIK_LWIN 0xDB /* Left Windows key */ +#define DIK_RWIN 0xDC /* Right Windows key */ +#define DIK_APPS 0xDD /* AppMenu key */ +#define DIK_POWER 0xDE /* System Power */ +#define DIK_SLEEP 0xDF /* System Sleep */ +#define DIK_WAKE 0xE3 /* System Wake */ +#define DIK_WEBSEARCH 0xE5 /* Web Search */ +#define DIK_WEBFAVORITES 0xE6 /* Web Favorites */ +#define DIK_WEBREFRESH 0xE7 /* Web Refresh */ +#define DIK_WEBSTOP 0xE8 /* Web Stop */ +#define DIK_WEBFORWARD 0xE9 /* Web Forward */ +#define DIK_WEBBACK 0xEA /* Web Back */ +#define DIK_MYCOMPUTER 0xEB /* My Computer */ +#define DIK_MAIL 0xEC /* Mail */ +#define DIK_MEDIASELECT 0xED /* Media Select */ + +/* + * Alternate names for keys, to facilitate transition from DOS. + */ +#define DIK_BACKSPACE DIK_BACK /* backspace */ +#define DIK_NUMPADSTAR DIK_MULTIPLY /* * on numeric keypad */ +#define DIK_LALT DIK_LMENU /* left Alt */ +#define DIK_CAPSLOCK DIK_CAPITAL /* CapsLock */ +#define DIK_NUMPADMINUS DIK_SUBTRACT /* - on numeric keypad */ +#define DIK_NUMPADPLUS DIK_ADD /* + on numeric keypad */ +#define DIK_NUMPADPERIOD DIK_DECIMAL /* . on numeric keypad */ +#define DIK_NUMPADSLASH DIK_DIVIDE /* / on numeric keypad */ +#define DIK_RALT DIK_RMENU /* right Alt */ +#define DIK_UPARROW DIK_UP /* UpArrow on arrow keypad */ +#define DIK_PGUP DIK_PRIOR /* PgUp on arrow keypad */ +#define DIK_LEFTARROW DIK_LEFT /* LeftArrow on arrow keypad */ +#define DIK_RIGHTARROW DIK_RIGHT /* RightArrow on arrow keypad */ +#define DIK_DOWNARROW DIK_DOWN /* DownArrow on arrow keypad */ +#define DIK_PGDN DIK_NEXT /* PgDn on arrow keypad */ + +/* + * Alternate names for keys originally not used on US keyboards. + */ +#define DIK_CIRCUMFLEX DIK_PREVTRACK /* Japanese keyboard */ + +#endif /* DIJ_RINGZERO */ + +/**************************************************************************** + * + * Joystick + * + ****************************************************************************/ + +#ifndef DIJ_RINGZERO + +typedef struct DIJOYSTATE { + LONG lX; /* x-axis position */ + LONG lY; /* y-axis position */ + LONG lZ; /* z-axis position */ + LONG lRx; /* x-axis rotation */ + LONG lRy; /* y-axis rotation */ + LONG lRz; /* z-axis rotation */ + LONG rglSlider[2]; /* extra axes positions */ + DWORD rgdwPOV[4]; /* POV directions */ + BYTE rgbButtons[32]; /* 32 buttons */ +} DIJOYSTATE, *LPDIJOYSTATE; + +typedef struct DIJOYSTATE2 { + LONG lX; /* x-axis position */ + LONG lY; /* y-axis position */ + LONG lZ; /* z-axis position */ + LONG lRx; /* x-axis rotation */ + LONG lRy; /* y-axis rotation */ + LONG lRz; /* z-axis rotation */ + LONG rglSlider[2]; /* extra axes positions */ + DWORD rgdwPOV[4]; /* POV directions */ + BYTE rgbButtons[128]; /* 128 buttons */ + LONG lVX; /* x-axis velocity */ + LONG lVY; /* y-axis velocity */ + LONG lVZ; /* z-axis velocity */ + LONG lVRx; /* x-axis angular velocity */ + LONG lVRy; /* y-axis angular velocity */ + LONG lVRz; /* z-axis angular velocity */ + LONG rglVSlider[2]; /* extra axes velocities */ + LONG lAX; /* x-axis acceleration */ + LONG lAY; /* y-axis acceleration */ + LONG lAZ; /* z-axis acceleration */ + LONG lARx; /* x-axis angular acceleration */ + LONG lARy; /* y-axis angular acceleration */ + LONG lARz; /* z-axis angular acceleration */ + LONG rglASlider[2]; /* extra axes accelerations */ + LONG lFX; /* x-axis force */ + LONG lFY; /* y-axis force */ + LONG lFZ; /* z-axis force */ + LONG lFRx; /* x-axis torque */ + LONG lFRy; /* y-axis torque */ + LONG lFRz; /* z-axis torque */ + LONG rglFSlider[2]; /* extra axes forces */ +} DIJOYSTATE2, *LPDIJOYSTATE2; + +#define DIJOFS_X FIELD_OFFSET(DIJOYSTATE, lX) +#define DIJOFS_Y FIELD_OFFSET(DIJOYSTATE, lY) +#define DIJOFS_Z FIELD_OFFSET(DIJOYSTATE, lZ) +#define DIJOFS_RX FIELD_OFFSET(DIJOYSTATE, lRx) +#define DIJOFS_RY FIELD_OFFSET(DIJOYSTATE, lRy) +#define DIJOFS_RZ FIELD_OFFSET(DIJOYSTATE, lRz) +#define DIJOFS_SLIDER(n) (FIELD_OFFSET(DIJOYSTATE, rglSlider) + \ + (n) * sizeof(LONG)) +#define DIJOFS_POV(n) (FIELD_OFFSET(DIJOYSTATE, rgdwPOV) + \ + (n) * sizeof(DWORD)) +#define DIJOFS_BUTTON(n) (FIELD_OFFSET(DIJOYSTATE, rgbButtons) + (n)) +#define DIJOFS_BUTTON0 DIJOFS_BUTTON(0) +#define DIJOFS_BUTTON1 DIJOFS_BUTTON(1) +#define DIJOFS_BUTTON2 DIJOFS_BUTTON(2) +#define DIJOFS_BUTTON3 DIJOFS_BUTTON(3) +#define DIJOFS_BUTTON4 DIJOFS_BUTTON(4) +#define DIJOFS_BUTTON5 DIJOFS_BUTTON(5) +#define DIJOFS_BUTTON6 DIJOFS_BUTTON(6) +#define DIJOFS_BUTTON7 DIJOFS_BUTTON(7) +#define DIJOFS_BUTTON8 DIJOFS_BUTTON(8) +#define DIJOFS_BUTTON9 DIJOFS_BUTTON(9) +#define DIJOFS_BUTTON10 DIJOFS_BUTTON(10) +#define DIJOFS_BUTTON11 DIJOFS_BUTTON(11) +#define DIJOFS_BUTTON12 DIJOFS_BUTTON(12) +#define DIJOFS_BUTTON13 DIJOFS_BUTTON(13) +#define DIJOFS_BUTTON14 DIJOFS_BUTTON(14) +#define DIJOFS_BUTTON15 DIJOFS_BUTTON(15) +#define DIJOFS_BUTTON16 DIJOFS_BUTTON(16) +#define DIJOFS_BUTTON17 DIJOFS_BUTTON(17) +#define DIJOFS_BUTTON18 DIJOFS_BUTTON(18) +#define DIJOFS_BUTTON19 DIJOFS_BUTTON(19) +#define DIJOFS_BUTTON20 DIJOFS_BUTTON(20) +#define DIJOFS_BUTTON21 DIJOFS_BUTTON(21) +#define DIJOFS_BUTTON22 DIJOFS_BUTTON(22) +#define DIJOFS_BUTTON23 DIJOFS_BUTTON(23) +#define DIJOFS_BUTTON24 DIJOFS_BUTTON(24) +#define DIJOFS_BUTTON25 DIJOFS_BUTTON(25) +#define DIJOFS_BUTTON26 DIJOFS_BUTTON(26) +#define DIJOFS_BUTTON27 DIJOFS_BUTTON(27) +#define DIJOFS_BUTTON28 DIJOFS_BUTTON(28) +#define DIJOFS_BUTTON29 DIJOFS_BUTTON(29) +#define DIJOFS_BUTTON30 DIJOFS_BUTTON(30) +#define DIJOFS_BUTTON31 DIJOFS_BUTTON(31) + + +#endif /* DIJ_RINGZERO */ + +/**************************************************************************** + * + * IDirectInput + * + ****************************************************************************/ + +#ifndef DIJ_RINGZERO + +#define DIENUM_STOP 0 +#define DIENUM_CONTINUE 1 + +typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKA)(LPCDIDEVICEINSTANCEA, LPVOID); +typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKW)(LPCDIDEVICEINSTANCEW, LPVOID); +#ifdef UNICODE +#define LPDIENUMDEVICESCALLBACK LPDIENUMDEVICESCALLBACKW +#else +#define LPDIENUMDEVICESCALLBACK LPDIENUMDEVICESCALLBACKA +#endif // !UNICODE +typedef BOOL (FAR PASCAL * LPDICONFIGUREDEVICESCALLBACK)(IUnknown FAR *, LPVOID); + +#define DIEDFL_ALLDEVICES 0x00000000 +#define DIEDFL_ATTACHEDONLY 0x00000001 +#if(DIRECTINPUT_VERSION >= 0x0500) +#define DIEDFL_FORCEFEEDBACK 0x00000100 +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIEDFL_INCLUDEALIASES 0x00010000 +#define DIEDFL_INCLUDEPHANTOMS 0x00020000 +#endif /* DIRECTINPUT_VERSION >= 0x050a */ +#if(DIRECTINPUT_VERSION >= 0x0800) +#define DIEDFL_INCLUDEHIDDEN 0x00040000 +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + + +#if(DIRECTINPUT_VERSION >= 0x0800) +typedef BOOL (FAR PASCAL * LPDIENUMDEVICESBYSEMANTICSCBA)(LPCDIDEVICEINSTANCEA, LPDIRECTINPUTDEVICE8A, DWORD, DWORD, LPVOID); +typedef BOOL (FAR PASCAL * LPDIENUMDEVICESBYSEMANTICSCBW)(LPCDIDEVICEINSTANCEW, LPDIRECTINPUTDEVICE8W, DWORD, DWORD, LPVOID); +#ifdef UNICODE +#define LPDIENUMDEVICESBYSEMANTICSCB LPDIENUMDEVICESBYSEMANTICSCBW +#else +#define LPDIENUMDEVICESBYSEMANTICSCB LPDIENUMDEVICESBYSEMANTICSCBA +#endif // !UNICODE +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +#if(DIRECTINPUT_VERSION >= 0x0800) +#define DIEDBS_MAPPEDPRI1 0x00000001 +#define DIEDBS_MAPPEDPRI2 0x00000002 +#define DIEDBS_RECENTDEVICE 0x00000010 +#define DIEDBS_NEWDEVICE 0x00000020 +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +#if(DIRECTINPUT_VERSION >= 0x0800) +#define DIEDBSFL_ATTACHEDONLY 0x00000000 +#define DIEDBSFL_THISUSER 0x00000010 +#define DIEDBSFL_FORCEFEEDBACK DIEDFL_FORCEFEEDBACK +#define DIEDBSFL_AVAILABLEDEVICES 0x00001000 +#define DIEDBSFL_MULTIMICEKEYBOARDS 0x00002000 +#define DIEDBSFL_NONGAMINGDEVICES 0x00004000 +#define DIEDBSFL_VALID 0x00007110 +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +#undef INTERFACE +#define INTERFACE IDirectInputW + +DECLARE_INTERFACE_(IDirectInputW, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputW methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; +}; + +typedef struct IDirectInputW *LPDIRECTINPUTW; + +#undef INTERFACE +#define INTERFACE IDirectInputA + +DECLARE_INTERFACE_(IDirectInputA, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputA methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; +}; + +typedef struct IDirectInputA *LPDIRECTINPUTA; + +#ifdef UNICODE +#define IID_IDirectInput IID_IDirectInputW +#define IDirectInput IDirectInputW +#define IDirectInputVtbl IDirectInputWVtbl +#else +#define IID_IDirectInput IID_IDirectInputA +#define IDirectInput IDirectInputA +#define IDirectInputVtbl IDirectInputAVtbl +#endif +typedef struct IDirectInput *LPDIRECTINPUT; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInput_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInput_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#else +#define IDirectInput_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput_AddRef(p) (p)->AddRef() +#define IDirectInput_Release(p) (p)->Release() +#define IDirectInput_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput_Initialize(p,a,b) (p)->Initialize(a,b) +#endif + +#undef INTERFACE +#define INTERFACE IDirectInput2W + +DECLARE_INTERFACE_(IDirectInput2W, IDirectInputW) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputW methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; + + /*** IDirectInput2W methods ***/ + STDMETHOD(FindDevice)(THIS_ REFGUID,LPCWSTR,LPGUID) PURE; +}; + +typedef struct IDirectInput2W *LPDIRECTINPUT2W; + +#undef INTERFACE +#define INTERFACE IDirectInput2A + +DECLARE_INTERFACE_(IDirectInput2A, IDirectInputA) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputA methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; + + /*** IDirectInput2A methods ***/ + STDMETHOD(FindDevice)(THIS_ REFGUID,LPCSTR,LPGUID) PURE; +}; + +typedef struct IDirectInput2A *LPDIRECTINPUT2A; + +#ifdef UNICODE +#define IID_IDirectInput2 IID_IDirectInput2W +#define IDirectInput2 IDirectInput2W +#define IDirectInput2Vtbl IDirectInput2WVtbl +#else +#define IID_IDirectInput2 IID_IDirectInput2A +#define IDirectInput2 IDirectInput2A +#define IDirectInput2Vtbl IDirectInput2AVtbl +#endif +typedef struct IDirectInput2 *LPDIRECTINPUT2; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInput2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput2_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInput2_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput2_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput2_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput2_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput2_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectInput2_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c) +#else +#define IDirectInput2_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput2_AddRef(p) (p)->AddRef() +#define IDirectInput2_Release(p) (p)->Release() +#define IDirectInput2_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput2_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput2_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput2_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput2_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectInput2_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c) +#endif + + +#undef INTERFACE +#define INTERFACE IDirectInput7W + +DECLARE_INTERFACE_(IDirectInput7W, IDirectInput2W) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInput2W methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; + STDMETHOD(FindDevice)(THIS_ REFGUID,LPCWSTR,LPGUID) PURE; + + /*** IDirectInput7W methods ***/ + STDMETHOD(CreateDeviceEx)(THIS_ REFGUID,REFIID,LPVOID *,LPUNKNOWN) PURE; +}; + +typedef struct IDirectInput7W *LPDIRECTINPUT7W; + +#undef INTERFACE +#define INTERFACE IDirectInput7A + +DECLARE_INTERFACE_(IDirectInput7A, IDirectInput2A) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInput2A methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; + STDMETHOD(FindDevice)(THIS_ REFGUID,LPCSTR,LPGUID) PURE; + + /*** IDirectInput7A methods ***/ + STDMETHOD(CreateDeviceEx)(THIS_ REFGUID,REFIID,LPVOID *,LPUNKNOWN) PURE; +}; + +typedef struct IDirectInput7A *LPDIRECTINPUT7A; + +#ifdef UNICODE +#define IID_IDirectInput7 IID_IDirectInput7W +#define IDirectInput7 IDirectInput7W +#define IDirectInput7Vtbl IDirectInput7WVtbl +#else +#define IID_IDirectInput7 IID_IDirectInput7A +#define IDirectInput7 IDirectInput7A +#define IDirectInput7Vtbl IDirectInput7AVtbl +#endif +typedef struct IDirectInput7 *LPDIRECTINPUT7; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInput7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput7_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput7_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInput7_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput7_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput7_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput7_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput7_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectInput7_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c) +#define IDirectInput7_CreateDeviceEx(p,a,b,c,d) (p)->lpVtbl->CreateDeviceEx(p,a,b,c,d) +#else +#define IDirectInput7_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput7_AddRef(p) (p)->AddRef() +#define IDirectInput7_Release(p) (p)->Release() +#define IDirectInput7_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput7_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput7_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput7_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput7_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectInput7_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c) +#define IDirectInput7_CreateDeviceEx(p,a,b,c,d) (p)->CreateDeviceEx(a,b,c,d) +#endif + +#if(DIRECTINPUT_VERSION >= 0x0800) +#undef INTERFACE +#define INTERFACE IDirectInput8W + +DECLARE_INTERFACE_(IDirectInput8W, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInput8W methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICE8W *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; + STDMETHOD(FindDevice)(THIS_ REFGUID,LPCWSTR,LPGUID) PURE; + STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCWSTR,LPDIACTIONFORMATW,LPDIENUMDEVICESBYSEMANTICSCBW,LPVOID,DWORD) PURE; + STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK,LPDICONFIGUREDEVICESPARAMSW,DWORD,LPVOID) PURE; +}; + +typedef struct IDirectInput8W *LPDIRECTINPUT8W; + +#undef INTERFACE +#define INTERFACE IDirectInput8A + +DECLARE_INTERFACE_(IDirectInput8A, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInput8A methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICE8A *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; + STDMETHOD(FindDevice)(THIS_ REFGUID,LPCSTR,LPGUID) PURE; + STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCSTR,LPDIACTIONFORMATA,LPDIENUMDEVICESBYSEMANTICSCBA,LPVOID,DWORD) PURE; + STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK,LPDICONFIGUREDEVICESPARAMSA,DWORD,LPVOID) PURE; +}; + +typedef struct IDirectInput8A *LPDIRECTINPUT8A; + +#ifdef UNICODE +#define IID_IDirectInput8 IID_IDirectInput8W +#define IDirectInput8 IDirectInput8W +#define IDirectInput8Vtbl IDirectInput8WVtbl +#else +#define IID_IDirectInput8 IID_IDirectInput8A +#define IDirectInput8 IDirectInput8A +#define IDirectInput8Vtbl IDirectInput8AVtbl +#endif +typedef struct IDirectInput8 *LPDIRECTINPUT8; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInput8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput8_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput8_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInput8_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput8_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput8_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput8_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput8_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectInput8_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c) +#define IDirectInput8_EnumDevicesBySemantics(p,a,b,c,d,e) (p)->lpVtbl->EnumDevicesBySemantics(p,a,b,c,d,e) +#define IDirectInput8_ConfigureDevices(p,a,b,c,d) (p)->lpVtbl->ConfigureDevices(p,a,b,c,d) +#else +#define IDirectInput8_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput8_AddRef(p) (p)->AddRef() +#define IDirectInput8_Release(p) (p)->Release() +#define IDirectInput8_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput8_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput8_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput8_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput8_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectInput8_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c) +#define IDirectInput8_EnumDevicesBySemantics(p,a,b,c,d,e) (p)->EnumDevicesBySemantics(a,b,c,d,e) +#define IDirectInput8_ConfigureDevices(p,a,b,c,d) (p)->ConfigureDevices(a,b,c,d) +#endif +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +#if DIRECTINPUT_VERSION > 0x0700 + +extern HRESULT WINAPI DirectInput8Create(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter); + +#else +extern HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter); +extern HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter); +#ifdef UNICODE +#define DirectInputCreate DirectInputCreateW +#else +#define DirectInputCreate DirectInputCreateA +#endif // !UNICODE + +extern HRESULT WINAPI DirectInputCreateEx(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter); + +#endif /* DIRECTINPUT_VERSION > 0x700 */ + +#endif /* DIJ_RINGZERO */ + + +/**************************************************************************** + * + * Return Codes + * + ****************************************************************************/ + +/* + * The operation completed successfully. + */ +#define DI_OK S_OK + +/* + * The device exists but is not currently attached. + */ +#define DI_NOTATTACHED S_FALSE + +/* + * The device buffer overflowed. Some input was lost. + */ +#define DI_BUFFEROVERFLOW S_FALSE + +/* + * The change in device properties had no effect. + */ +#define DI_PROPNOEFFECT S_FALSE + +/* + * The operation had no effect. + */ +#define DI_NOEFFECT S_FALSE + +/* + * The device is a polled device. As a result, device buffering + * will not collect any data and event notifications will not be + * signalled until GetDeviceState is called. + */ +#define DI_POLLEDDEVICE ((HRESULT)0x00000002L) + +/* + * The parameters of the effect were successfully updated by + * IDirectInputEffect::SetParameters, but the effect was not + * downloaded because the device is not exclusively acquired + * or because the DIEP_NODOWNLOAD flag was passed. + */ +#define DI_DOWNLOADSKIPPED ((HRESULT)0x00000003L) + +/* + * The parameters of the effect were successfully updated by + * IDirectInputEffect::SetParameters, but in order to change + * the parameters, the effect needed to be restarted. + */ +#define DI_EFFECTRESTARTED ((HRESULT)0x00000004L) + +/* + * The parameters of the effect were successfully updated by + * IDirectInputEffect::SetParameters, but some of them were + * beyond the capabilities of the device and were truncated. + */ +#define DI_TRUNCATED ((HRESULT)0x00000008L) + +/* + * The settings have been successfully applied but could not be + * persisted. + */ +#define DI_SETTINGSNOTSAVED ((HRESULT)0x0000000BL) + +/* + * Equal to DI_EFFECTRESTARTED | DI_TRUNCATED. + */ +#define DI_TRUNCATEDANDRESTARTED ((HRESULT)0x0000000CL) + +/* + * A SUCCESS code indicating that settings cannot be modified. + */ +#define DI_WRITEPROTECT ((HRESULT)0x00000013L) + +/* + * The application requires a newer version of DirectInput. + */ +#define DIERR_OLDDIRECTINPUTVERSION \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_OLD_WIN_VERSION) + +/* + * The application was written for an unsupported prerelease version + * of DirectInput. + */ +#define DIERR_BETADIRECTINPUTVERSION \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_RMODE_APP) + +/* + * The object could not be created due to an incompatible driver version + * or mismatched or incomplete driver components. + */ +#define DIERR_BADDRIVERVER \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BAD_DRIVER_LEVEL) + +/* + * The device or device instance or effect is not registered with DirectInput. + */ +#define DIERR_DEVICENOTREG REGDB_E_CLASSNOTREG + +/* + * The requested object does not exist. + */ +#define DIERR_NOTFOUND \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND) + +/* + * The requested object does not exist. + */ +#define DIERR_OBJECTNOTFOUND \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND) + +/* + * An invalid parameter was passed to the returning function, + * or the object was not in a state that admitted the function + * to be called. + */ +#define DIERR_INVALIDPARAM E_INVALIDARG + +/* + * The specified interface is not supported by the object + */ +#define DIERR_NOINTERFACE E_NOINTERFACE + +/* + * An undetermined error occured inside the DInput subsystem + */ +#define DIERR_GENERIC E_FAIL + +/* + * The DInput subsystem couldn't allocate sufficient memory to complete the + * caller's request. + */ +#define DIERR_OUTOFMEMORY E_OUTOFMEMORY + +/* + * The function called is not supported at this time + */ +#define DIERR_UNSUPPORTED E_NOTIMPL + +/* + * This object has not been initialized + */ +#define DIERR_NOTINITIALIZED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_READY) + +/* + * This object is already initialized + */ +#define DIERR_ALREADYINITIALIZED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_ALREADY_INITIALIZED) + +/* + * This object does not support aggregation + */ +#define DIERR_NOAGGREGATION CLASS_E_NOAGGREGATION + +/* + * Another app has a higher priority level, preventing this call from + * succeeding. + */ +#define DIERR_OTHERAPPHASPRIO E_ACCESSDENIED + +/* + * Access to the device has been lost. It must be re-acquired. + */ +#define DIERR_INPUTLOST \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_READ_FAULT) + +/* + * The operation cannot be performed while the device is acquired. + */ +#define DIERR_ACQUIRED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BUSY) + +/* + * The operation cannot be performed unless the device is acquired. + */ +#define DIERR_NOTACQUIRED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INVALID_ACCESS) + +/* + * The specified property cannot be changed. + */ +#define DIERR_READONLY E_ACCESSDENIED + +/* + * The device already has an event notification associated with it. + */ +#define DIERR_HANDLEEXISTS E_ACCESSDENIED + +/* + * Data is not yet available. + */ +#ifndef E_PENDING +#define E_PENDING 0x8000000AL +#endif + +/* + * Unable to IDirectInputJoyConfig_Acquire because the user + * does not have sufficient privileges to change the joystick + * configuration. + */ +#define DIERR_INSUFFICIENTPRIVS 0x80040200L + +/* + * The device is full. + */ +#define DIERR_DEVICEFULL 0x80040201L + +/* + * Not all the requested information fit into the buffer. + */ +#define DIERR_MOREDATA 0x80040202L + +/* + * The effect is not downloaded. + */ +#define DIERR_NOTDOWNLOADED 0x80040203L + +/* + * The device cannot be reinitialized because there are still effects + * attached to it. + */ +#define DIERR_HASEFFECTS 0x80040204L + +/* + * The operation cannot be performed unless the device is acquired + * in DISCL_EXCLUSIVE mode. + */ +#define DIERR_NOTEXCLUSIVEACQUIRED 0x80040205L + +/* + * The effect could not be downloaded because essential information + * is missing. For example, no axes have been associated with the + * effect, or no type-specific information has been created. + */ +#define DIERR_INCOMPLETEEFFECT 0x80040206L + +/* + * Attempted to read buffered device data from a device that is + * not buffered. + */ +#define DIERR_NOTBUFFERED 0x80040207L + +/* + * An attempt was made to modify parameters of an effect while it is + * playing. Not all hardware devices support altering the parameters + * of an effect while it is playing. + */ +#define DIERR_EFFECTPLAYING 0x80040208L + +/* + * The operation could not be completed because the device is not + * plugged in. + */ +#define DIERR_UNPLUGGED 0x80040209L + +/* + * SendDeviceData failed because more information was requested + * to be sent than can be sent to the device. Some devices have + * restrictions on how much data can be sent to them. (For example, + * there might be a limit on the number of buttons that can be + * pressed at once.) + */ +#define DIERR_REPORTFULL 0x8004020AL + + +/* + * A mapper file function failed because reading or writing the user or IHV + * settings file failed. + */ +#define DIERR_MAPFILEFAIL 0x8004020BL + + +/*--- DINPUT Mapper Definitions: New for Dx8 ---*/ + + +/*--- Keyboard + Physical Keyboard Device ---*/ + +#define DIKEYBOARD_ESCAPE 0x81000401 +#define DIKEYBOARD_1 0x81000402 +#define DIKEYBOARD_2 0x81000403 +#define DIKEYBOARD_3 0x81000404 +#define DIKEYBOARD_4 0x81000405 +#define DIKEYBOARD_5 0x81000406 +#define DIKEYBOARD_6 0x81000407 +#define DIKEYBOARD_7 0x81000408 +#define DIKEYBOARD_8 0x81000409 +#define DIKEYBOARD_9 0x8100040A +#define DIKEYBOARD_0 0x8100040B +#define DIKEYBOARD_MINUS 0x8100040C /* - on main keyboard */ +#define DIKEYBOARD_EQUALS 0x8100040D +#define DIKEYBOARD_BACK 0x8100040E /* backspace */ +#define DIKEYBOARD_TAB 0x8100040F +#define DIKEYBOARD_Q 0x81000410 +#define DIKEYBOARD_W 0x81000411 +#define DIKEYBOARD_E 0x81000412 +#define DIKEYBOARD_R 0x81000413 +#define DIKEYBOARD_T 0x81000414 +#define DIKEYBOARD_Y 0x81000415 +#define DIKEYBOARD_U 0x81000416 +#define DIKEYBOARD_I 0x81000417 +#define DIKEYBOARD_O 0x81000418 +#define DIKEYBOARD_P 0x81000419 +#define DIKEYBOARD_LBRACKET 0x8100041A +#define DIKEYBOARD_RBRACKET 0x8100041B +#define DIKEYBOARD_RETURN 0x8100041C /* Enter on main keyboard */ +#define DIKEYBOARD_LCONTROL 0x8100041D +#define DIKEYBOARD_A 0x8100041E +#define DIKEYBOARD_S 0x8100041F +#define DIKEYBOARD_D 0x81000420 +#define DIKEYBOARD_F 0x81000421 +#define DIKEYBOARD_G 0x81000422 +#define DIKEYBOARD_H 0x81000423 +#define DIKEYBOARD_J 0x81000424 +#define DIKEYBOARD_K 0x81000425 +#define DIKEYBOARD_L 0x81000426 +#define DIKEYBOARD_SEMICOLON 0x81000427 +#define DIKEYBOARD_APOSTROPHE 0x81000428 +#define DIKEYBOARD_GRAVE 0x81000429 /* accent grave */ +#define DIKEYBOARD_LSHIFT 0x8100042A +#define DIKEYBOARD_BACKSLASH 0x8100042B +#define DIKEYBOARD_Z 0x8100042C +#define DIKEYBOARD_X 0x8100042D +#define DIKEYBOARD_C 0x8100042E +#define DIKEYBOARD_V 0x8100042F +#define DIKEYBOARD_B 0x81000430 +#define DIKEYBOARD_N 0x81000431 +#define DIKEYBOARD_M 0x81000432 +#define DIKEYBOARD_COMMA 0x81000433 +#define DIKEYBOARD_PERIOD 0x81000434 /* . on main keyboard */ +#define DIKEYBOARD_SLASH 0x81000435 /* / on main keyboard */ +#define DIKEYBOARD_RSHIFT 0x81000436 +#define DIKEYBOARD_MULTIPLY 0x81000437 /* * on numeric keypad */ +#define DIKEYBOARD_LMENU 0x81000438 /* left Alt */ +#define DIKEYBOARD_SPACE 0x81000439 +#define DIKEYBOARD_CAPITAL 0x8100043A +#define DIKEYBOARD_F1 0x8100043B +#define DIKEYBOARD_F2 0x8100043C +#define DIKEYBOARD_F3 0x8100043D +#define DIKEYBOARD_F4 0x8100043E +#define DIKEYBOARD_F5 0x8100043F +#define DIKEYBOARD_F6 0x81000440 +#define DIKEYBOARD_F7 0x81000441 +#define DIKEYBOARD_F8 0x81000442 +#define DIKEYBOARD_F9 0x81000443 +#define DIKEYBOARD_F10 0x81000444 +#define DIKEYBOARD_NUMLOCK 0x81000445 +#define DIKEYBOARD_SCROLL 0x81000446 /* Scroll Lock */ +#define DIKEYBOARD_NUMPAD7 0x81000447 +#define DIKEYBOARD_NUMPAD8 0x81000448 +#define DIKEYBOARD_NUMPAD9 0x81000449 +#define DIKEYBOARD_SUBTRACT 0x8100044A /* - on numeric keypad */ +#define DIKEYBOARD_NUMPAD4 0x8100044B +#define DIKEYBOARD_NUMPAD5 0x8100044C +#define DIKEYBOARD_NUMPAD6 0x8100044D +#define DIKEYBOARD_ADD 0x8100044E /* + on numeric keypad */ +#define DIKEYBOARD_NUMPAD1 0x8100044F +#define DIKEYBOARD_NUMPAD2 0x81000450 +#define DIKEYBOARD_NUMPAD3 0x81000451 +#define DIKEYBOARD_NUMPAD0 0x81000452 +#define DIKEYBOARD_DECIMAL 0x81000453 /* . on numeric keypad */ +#define DIKEYBOARD_OEM_102 0x81000456 /* <> or \| on RT 102-key keyboard (Non-U.S.) */ +#define DIKEYBOARD_F11 0x81000457 +#define DIKEYBOARD_F12 0x81000458 +#define DIKEYBOARD_F13 0x81000464 /* (NEC PC98) */ +#define DIKEYBOARD_F14 0x81000465 /* (NEC PC98) */ +#define DIKEYBOARD_F15 0x81000466 /* (NEC PC98) */ +#define DIKEYBOARD_KANA 0x81000470 /* (Japanese keyboard) */ +#define DIKEYBOARD_ABNT_C1 0x81000473 /* /? on Brazilian keyboard */ +#define DIKEYBOARD_CONVERT 0x81000479 /* (Japanese keyboard) */ +#define DIKEYBOARD_NOCONVERT 0x8100047B /* (Japanese keyboard) */ +#define DIKEYBOARD_YEN 0x8100047D /* (Japanese keyboard) */ +#define DIKEYBOARD_ABNT_C2 0x8100047E /* Numpad . on Brazilian keyboard */ +#define DIKEYBOARD_NUMPADEQUALS 0x8100048D /* = on numeric keypad (NEC PC98) */ +#define DIKEYBOARD_PREVTRACK 0x81000490 /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */ +#define DIKEYBOARD_AT 0x81000491 /* (NEC PC98) */ +#define DIKEYBOARD_COLON 0x81000492 /* (NEC PC98) */ +#define DIKEYBOARD_UNDERLINE 0x81000493 /* (NEC PC98) */ +#define DIKEYBOARD_KANJI 0x81000494 /* (Japanese keyboard) */ +#define DIKEYBOARD_STOP 0x81000495 /* (NEC PC98) */ +#define DIKEYBOARD_AX 0x81000496 /* (Japan AX) */ +#define DIKEYBOARD_UNLABELED 0x81000497 /* (J3100) */ +#define DIKEYBOARD_NEXTTRACK 0x81000499 /* Next Track */ +#define DIKEYBOARD_NUMPADENTER 0x8100049C /* Enter on numeric keypad */ +#define DIKEYBOARD_RCONTROL 0x8100049D +#define DIKEYBOARD_MUTE 0x810004A0 /* Mute */ +#define DIKEYBOARD_CALCULATOR 0x810004A1 /* Calculator */ +#define DIKEYBOARD_PLAYPAUSE 0x810004A2 /* Play / Pause */ +#define DIKEYBOARD_MEDIASTOP 0x810004A4 /* Media Stop */ +#define DIKEYBOARD_VOLUMEDOWN 0x810004AE /* Volume - */ +#define DIKEYBOARD_VOLUMEUP 0x810004B0 /* Volume + */ +#define DIKEYBOARD_WEBHOME 0x810004B2 /* Web home */ +#define DIKEYBOARD_NUMPADCOMMA 0x810004B3 /* , on numeric keypad (NEC PC98) */ +#define DIKEYBOARD_DIVIDE 0x810004B5 /* / on numeric keypad */ +#define DIKEYBOARD_SYSRQ 0x810004B7 +#define DIKEYBOARD_RMENU 0x810004B8 /* right Alt */ +#define DIKEYBOARD_PAUSE 0x810004C5 /* Pause */ +#define DIKEYBOARD_HOME 0x810004C7 /* Home on arrow keypad */ +#define DIKEYBOARD_UP 0x810004C8 /* UpArrow on arrow keypad */ +#define DIKEYBOARD_PRIOR 0x810004C9 /* PgUp on arrow keypad */ +#define DIKEYBOARD_LEFT 0x810004CB /* LeftArrow on arrow keypad */ +#define DIKEYBOARD_RIGHT 0x810004CD /* RightArrow on arrow keypad */ +#define DIKEYBOARD_END 0x810004CF /* End on arrow keypad */ +#define DIKEYBOARD_DOWN 0x810004D0 /* DownArrow on arrow keypad */ +#define DIKEYBOARD_NEXT 0x810004D1 /* PgDn on arrow keypad */ +#define DIKEYBOARD_INSERT 0x810004D2 /* Insert on arrow keypad */ +#define DIKEYBOARD_DELETE 0x810004D3 /* Delete on arrow keypad */ +#define DIKEYBOARD_LWIN 0x810004DB /* Left Windows key */ +#define DIKEYBOARD_RWIN 0x810004DC /* Right Windows key */ +#define DIKEYBOARD_APPS 0x810004DD /* AppMenu key */ +#define DIKEYBOARD_POWER 0x810004DE /* System Power */ +#define DIKEYBOARD_SLEEP 0x810004DF /* System Sleep */ +#define DIKEYBOARD_WAKE 0x810004E3 /* System Wake */ +#define DIKEYBOARD_WEBSEARCH 0x810004E5 /* Web Search */ +#define DIKEYBOARD_WEBFAVORITES 0x810004E6 /* Web Favorites */ +#define DIKEYBOARD_WEBREFRESH 0x810004E7 /* Web Refresh */ +#define DIKEYBOARD_WEBSTOP 0x810004E8 /* Web Stop */ +#define DIKEYBOARD_WEBFORWARD 0x810004E9 /* Web Forward */ +#define DIKEYBOARD_WEBBACK 0x810004EA /* Web Back */ +#define DIKEYBOARD_MYCOMPUTER 0x810004EB /* My Computer */ +#define DIKEYBOARD_MAIL 0x810004EC /* Mail */ +#define DIKEYBOARD_MEDIASELECT 0x810004ED /* Media Select */ + + +/*--- MOUSE + Physical Mouse Device ---*/ + +#define DIMOUSE_XAXISAB (0x82000200 |DIMOFS_X ) /* X Axis-absolute: Some mice natively report absolute coordinates */ +#define DIMOUSE_YAXISAB (0x82000200 |DIMOFS_Y ) /* Y Axis-absolute: Some mice natively report absolute coordinates */ +#define DIMOUSE_XAXIS (0x82000300 |DIMOFS_X ) /* X Axis */ +#define DIMOUSE_YAXIS (0x82000300 |DIMOFS_Y ) /* Y Axis */ +#define DIMOUSE_WHEEL (0x82000300 |DIMOFS_Z ) /* Z Axis */ +#define DIMOUSE_BUTTON0 (0x82000400 |DIMOFS_BUTTON0) /* Button 0 */ +#define DIMOUSE_BUTTON1 (0x82000400 |DIMOFS_BUTTON1) /* Button 1 */ +#define DIMOUSE_BUTTON2 (0x82000400 |DIMOFS_BUTTON2) /* Button 2 */ +#define DIMOUSE_BUTTON3 (0x82000400 |DIMOFS_BUTTON3) /* Button 3 */ +#define DIMOUSE_BUTTON4 (0x82000400 |DIMOFS_BUTTON4) /* Button 4 */ +#define DIMOUSE_BUTTON5 (0x82000400 |DIMOFS_BUTTON5) /* Button 5 */ +#define DIMOUSE_BUTTON6 (0x82000400 |DIMOFS_BUTTON6) /* Button 6 */ +#define DIMOUSE_BUTTON7 (0x82000400 |DIMOFS_BUTTON7) /* Button 7 */ + + +/*--- VOICE + Physical Dplay Voice Device ---*/ + +#define DIVOICE_CHANNEL1 0x83000401 +#define DIVOICE_CHANNEL2 0x83000402 +#define DIVOICE_CHANNEL3 0x83000403 +#define DIVOICE_CHANNEL4 0x83000404 +#define DIVOICE_CHANNEL5 0x83000405 +#define DIVOICE_CHANNEL6 0x83000406 +#define DIVOICE_CHANNEL7 0x83000407 +#define DIVOICE_CHANNEL8 0x83000408 +#define DIVOICE_TEAM 0x83000409 +#define DIVOICE_ALL 0x8300040A +#define DIVOICE_RECORDMUTE 0x8300040B +#define DIVOICE_PLAYBACKMUTE 0x8300040C +#define DIVOICE_TRANSMIT 0x8300040D + +#define DIVOICE_VOICECOMMAND 0x83000410 + + +/*--- Driving Simulator - Racing + Vehicle control is primary objective ---*/ +#define DIVIRTUAL_DRIVING_RACE 0x01000000 +#define DIAXIS_DRIVINGR_STEER 0x01008A01 /* Steering */ +#define DIAXIS_DRIVINGR_ACCELERATE 0x01039202 /* Accelerate */ +#define DIAXIS_DRIVINGR_BRAKE 0x01041203 /* Brake-Axis */ +#define DIBUTTON_DRIVINGR_SHIFTUP 0x01000C01 /* Shift to next higher gear */ +#define DIBUTTON_DRIVINGR_SHIFTDOWN 0x01000C02 /* Shift to next lower gear */ +#define DIBUTTON_DRIVINGR_VIEW 0x01001C03 /* Cycle through view options */ +#define DIBUTTON_DRIVINGR_MENU 0x010004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIAXIS_DRIVINGR_ACCEL_AND_BRAKE 0x01014A04 /* Some devices combine accelerate and brake in a single axis */ +#define DIHATSWITCH_DRIVINGR_GLANCE 0x01004601 /* Look around */ +#define DIBUTTON_DRIVINGR_BRAKE 0x01004C04 /* Brake-button */ +#define DIBUTTON_DRIVINGR_DASHBOARD 0x01004405 /* Select next dashboard option */ +#define DIBUTTON_DRIVINGR_AIDS 0x01004406 /* Driver correction aids */ +#define DIBUTTON_DRIVINGR_MAP 0x01004407 /* Display Driving Map */ +#define DIBUTTON_DRIVINGR_BOOST 0x01004408 /* Turbo Boost */ +#define DIBUTTON_DRIVINGR_PIT 0x01004409 /* Pit stop notification */ +#define DIBUTTON_DRIVINGR_ACCELERATE_LINK 0x0103D4E0 /* Fallback Accelerate button */ +#define DIBUTTON_DRIVINGR_STEER_LEFT_LINK 0x0100CCE4 /* Fallback Steer Left button */ +#define DIBUTTON_DRIVINGR_STEER_RIGHT_LINK 0x0100CCEC /* Fallback Steer Right button */ +#define DIBUTTON_DRIVINGR_GLANCE_LEFT_LINK 0x0107C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_DRIVINGR_GLANCE_RIGHT_LINK 0x0107C4EC /* Fallback Glance Right button */ +#define DIBUTTON_DRIVINGR_DEVICE 0x010044FE /* Show input device and controls */ +#define DIBUTTON_DRIVINGR_PAUSE 0x010044FC /* Start / Pause / Restart game */ + +/*--- Driving Simulator - Combat + Combat from within a vehicle is primary objective ---*/ +#define DIVIRTUAL_DRIVING_COMBAT 0x02000000 +#define DIAXIS_DRIVINGC_STEER 0x02008A01 /* Steering */ +#define DIAXIS_DRIVINGC_ACCELERATE 0x02039202 /* Accelerate */ +#define DIAXIS_DRIVINGC_BRAKE 0x02041203 /* Brake-axis */ +#define DIBUTTON_DRIVINGC_FIRE 0x02000C01 /* Fire */ +#define DIBUTTON_DRIVINGC_WEAPONS 0x02000C02 /* Select next weapon */ +#define DIBUTTON_DRIVINGC_TARGET 0x02000C03 /* Select next available target */ +#define DIBUTTON_DRIVINGC_MENU 0x020004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIAXIS_DRIVINGC_ACCEL_AND_BRAKE 0x02014A04 /* Some devices combine accelerate and brake in a single axis */ +#define DIHATSWITCH_DRIVINGC_GLANCE 0x02004601 /* Look around */ +#define DIBUTTON_DRIVINGC_SHIFTUP 0x02004C04 /* Shift to next higher gear */ +#define DIBUTTON_DRIVINGC_SHIFTDOWN 0x02004C05 /* Shift to next lower gear */ +#define DIBUTTON_DRIVINGC_DASHBOARD 0x02004406 /* Select next dashboard option */ +#define DIBUTTON_DRIVINGC_AIDS 0x02004407 /* Driver correction aids */ +#define DIBUTTON_DRIVINGC_BRAKE 0x02004C08 /* Brake-button */ +#define DIBUTTON_DRIVINGC_FIRESECONDARY 0x02004C09 /* Alternative fire button */ +#define DIBUTTON_DRIVINGC_ACCELERATE_LINK 0x0203D4E0 /* Fallback Accelerate button */ +#define DIBUTTON_DRIVINGC_STEER_LEFT_LINK 0x0200CCE4 /* Fallback Steer Left button */ +#define DIBUTTON_DRIVINGC_STEER_RIGHT_LINK 0x0200CCEC /* Fallback Steer Right button */ +#define DIBUTTON_DRIVINGC_GLANCE_LEFT_LINK 0x0207C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_DRIVINGC_GLANCE_RIGHT_LINK 0x0207C4EC /* Fallback Glance Right button */ +#define DIBUTTON_DRIVINGC_DEVICE 0x020044FE /* Show input device and controls */ +#define DIBUTTON_DRIVINGC_PAUSE 0x020044FC /* Start / Pause / Restart game */ + +/*--- Driving Simulator - Tank + Combat from withing a tank is primary objective ---*/ +#define DIVIRTUAL_DRIVING_TANK 0x03000000 +#define DIAXIS_DRIVINGT_STEER 0x03008A01 /* Turn tank left / right */ +#define DIAXIS_DRIVINGT_BARREL 0x03010202 /* Raise / lower barrel */ +#define DIAXIS_DRIVINGT_ACCELERATE 0x03039203 /* Accelerate */ +#define DIAXIS_DRIVINGT_ROTATE 0x03020204 /* Turn barrel left / right */ +#define DIBUTTON_DRIVINGT_FIRE 0x03000C01 /* Fire */ +#define DIBUTTON_DRIVINGT_WEAPONS 0x03000C02 /* Select next weapon */ +#define DIBUTTON_DRIVINGT_TARGET 0x03000C03 /* Selects next available target */ +#define DIBUTTON_DRIVINGT_MENU 0x030004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_DRIVINGT_GLANCE 0x03004601 /* Look around */ +#define DIAXIS_DRIVINGT_BRAKE 0x03045205 /* Brake-axis */ +#define DIAXIS_DRIVINGT_ACCEL_AND_BRAKE 0x03014A06 /* Some devices combine accelerate and brake in a single axis */ +#define DIBUTTON_DRIVINGT_VIEW 0x03005C04 /* Cycle through view options */ +#define DIBUTTON_DRIVINGT_DASHBOARD 0x03005C05 /* Select next dashboard option */ +#define DIBUTTON_DRIVINGT_BRAKE 0x03004C06 /* Brake-button */ +#define DIBUTTON_DRIVINGT_FIRESECONDARY 0x03004C07 /* Alternative fire button */ +#define DIBUTTON_DRIVINGT_ACCELERATE_LINK 0x0303D4E0 /* Fallback Accelerate button */ +#define DIBUTTON_DRIVINGT_STEER_LEFT_LINK 0x0300CCE4 /* Fallback Steer Left button */ +#define DIBUTTON_DRIVINGT_STEER_RIGHT_LINK 0x0300CCEC /* Fallback Steer Right button */ +#define DIBUTTON_DRIVINGT_BARREL_UP_LINK 0x030144E0 /* Fallback Barrel up button */ +#define DIBUTTON_DRIVINGT_BARREL_DOWN_LINK 0x030144E8 /* Fallback Barrel down button */ +#define DIBUTTON_DRIVINGT_ROTATE_LEFT_LINK 0x030244E4 /* Fallback Rotate left button */ +#define DIBUTTON_DRIVINGT_ROTATE_RIGHT_LINK 0x030244EC /* Fallback Rotate right button */ +#define DIBUTTON_DRIVINGT_GLANCE_LEFT_LINK 0x0307C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_DRIVINGT_GLANCE_RIGHT_LINK 0x0307C4EC /* Fallback Glance Right button */ +#define DIBUTTON_DRIVINGT_DEVICE 0x030044FE /* Show input device and controls */ +#define DIBUTTON_DRIVINGT_PAUSE 0x030044FC /* Start / Pause / Restart game */ + +/*--- Flight Simulator - Civilian + Plane control is the primary objective ---*/ +#define DIVIRTUAL_FLYING_CIVILIAN 0x04000000 +#define DIAXIS_FLYINGC_BANK 0x04008A01 /* Roll ship left / right */ +#define DIAXIS_FLYINGC_PITCH 0x04010A02 /* Nose up / down */ +#define DIAXIS_FLYINGC_THROTTLE 0x04039203 /* Throttle */ +#define DIBUTTON_FLYINGC_VIEW 0x04002401 /* Cycle through view options */ +#define DIBUTTON_FLYINGC_DISPLAY 0x04002402 /* Select next dashboard / heads up display option */ +#define DIBUTTON_FLYINGC_GEAR 0x04002C03 /* Gear up / down */ +#define DIBUTTON_FLYINGC_MENU 0x040004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_FLYINGC_GLANCE 0x04004601 /* Look around */ +#define DIAXIS_FLYINGC_BRAKE 0x04046A04 /* Apply Brake */ +#define DIAXIS_FLYINGC_RUDDER 0x04025205 /* Yaw ship left/right */ +#define DIAXIS_FLYINGC_FLAPS 0x04055A06 /* Flaps */ +#define DIBUTTON_FLYINGC_FLAPSUP 0x04006404 /* Increment stepping up until fully retracted */ +#define DIBUTTON_FLYINGC_FLAPSDOWN 0x04006405 /* Decrement stepping down until fully extended */ +#define DIBUTTON_FLYINGC_BRAKE_LINK 0x04046CE0 /* Fallback brake button */ +#define DIBUTTON_FLYINGC_FASTER_LINK 0x0403D4E0 /* Fallback throttle up button */ +#define DIBUTTON_FLYINGC_SLOWER_LINK 0x0403D4E8 /* Fallback throttle down button */ +#define DIBUTTON_FLYINGC_GLANCE_LEFT_LINK 0x0407C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_FLYINGC_GLANCE_RIGHT_LINK 0x0407C4EC /* Fallback Glance Right button */ +#define DIBUTTON_FLYINGC_GLANCE_UP_LINK 0x0407C4E0 /* Fallback Glance Up button */ +#define DIBUTTON_FLYINGC_GLANCE_DOWN_LINK 0x0407C4E8 /* Fallback Glance Down button */ +#define DIBUTTON_FLYINGC_DEVICE 0x040044FE /* Show input device and controls */ +#define DIBUTTON_FLYINGC_PAUSE 0x040044FC /* Start / Pause / Restart game */ + +/*--- Flight Simulator - Military + Aerial combat is the primary objective ---*/ +#define DIVIRTUAL_FLYING_MILITARY 0x05000000 +#define DIAXIS_FLYINGM_BANK 0x05008A01 /* Bank - Roll ship left / right */ +#define DIAXIS_FLYINGM_PITCH 0x05010A02 /* Pitch - Nose up / down */ +#define DIAXIS_FLYINGM_THROTTLE 0x05039203 /* Throttle - faster / slower */ +#define DIBUTTON_FLYINGM_FIRE 0x05000C01 /* Fire */ +#define DIBUTTON_FLYINGM_WEAPONS 0x05000C02 /* Select next weapon */ +#define DIBUTTON_FLYINGM_TARGET 0x05000C03 /* Selects next available target */ +#define DIBUTTON_FLYINGM_MENU 0x050004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_FLYINGM_GLANCE 0x05004601 /* Look around */ +#define DIBUTTON_FLYINGM_COUNTER 0x05005C04 /* Activate counter measures */ +#define DIAXIS_FLYINGM_RUDDER 0x05024A04 /* Rudder - Yaw ship left/right */ +#define DIAXIS_FLYINGM_BRAKE 0x05046205 /* Brake-axis */ +#define DIBUTTON_FLYINGM_VIEW 0x05006405 /* Cycle through view options */ +#define DIBUTTON_FLYINGM_DISPLAY 0x05006406 /* Select next dashboard option */ +#define DIAXIS_FLYINGM_FLAPS 0x05055206 /* Flaps */ +#define DIBUTTON_FLYINGM_FLAPSUP 0x05005407 /* Increment stepping up until fully retracted */ +#define DIBUTTON_FLYINGM_FLAPSDOWN 0x05005408 /* Decrement stepping down until fully extended */ +#define DIBUTTON_FLYINGM_FIRESECONDARY 0x05004C09 /* Alternative fire button */ +#define DIBUTTON_FLYINGM_GEAR 0x0500640A /* Gear up / down */ +#define DIBUTTON_FLYINGM_BRAKE_LINK 0x050464E0 /* Fallback brake button */ +#define DIBUTTON_FLYINGM_FASTER_LINK 0x0503D4E0 /* Fallback throttle up button */ +#define DIBUTTON_FLYINGM_SLOWER_LINK 0x0503D4E8 /* Fallback throttle down button */ +#define DIBUTTON_FLYINGM_GLANCE_LEFT_LINK 0x0507C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_FLYINGM_GLANCE_RIGHT_LINK 0x0507C4EC /* Fallback Glance Right button */ +#define DIBUTTON_FLYINGM_GLANCE_UP_LINK 0x0507C4E0 /* Fallback Glance Up button */ +#define DIBUTTON_FLYINGM_GLANCE_DOWN_LINK 0x0507C4E8 /* Fallback Glance Down button */ +#define DIBUTTON_FLYINGM_DEVICE 0x050044FE /* Show input device and controls */ +#define DIBUTTON_FLYINGM_PAUSE 0x050044FC /* Start / Pause / Restart game */ + +/*--- Flight Simulator - Combat Helicopter + Combat from helicopter is primary objective ---*/ +#define DIVIRTUAL_FLYING_HELICOPTER 0x06000000 +#define DIAXIS_FLYINGH_BANK 0x06008A01 /* Bank - Roll ship left / right */ +#define DIAXIS_FLYINGH_PITCH 0x06010A02 /* Pitch - Nose up / down */ +#define DIAXIS_FLYINGH_COLLECTIVE 0x06018A03 /* Collective - Blade pitch/power */ +#define DIBUTTON_FLYINGH_FIRE 0x06001401 /* Fire */ +#define DIBUTTON_FLYINGH_WEAPONS 0x06001402 /* Select next weapon */ +#define DIBUTTON_FLYINGH_TARGET 0x06001403 /* Selects next available target */ +#define DIBUTTON_FLYINGH_MENU 0x060004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_FLYINGH_GLANCE 0x06004601 /* Look around */ +#define DIAXIS_FLYINGH_TORQUE 0x06025A04 /* Torque - Rotate ship around left / right axis */ +#define DIAXIS_FLYINGH_THROTTLE 0x0603DA05 /* Throttle */ +#define DIBUTTON_FLYINGH_COUNTER 0x06005404 /* Activate counter measures */ +#define DIBUTTON_FLYINGH_VIEW 0x06006405 /* Cycle through view options */ +#define DIBUTTON_FLYINGH_GEAR 0x06006406 /* Gear up / down */ +#define DIBUTTON_FLYINGH_FIRESECONDARY 0x06004C07 /* Alternative fire button */ +#define DIBUTTON_FLYINGH_FASTER_LINK 0x0603DCE0 /* Fallback throttle up button */ +#define DIBUTTON_FLYINGH_SLOWER_LINK 0x0603DCE8 /* Fallback throttle down button */ +#define DIBUTTON_FLYINGH_GLANCE_LEFT_LINK 0x0607C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_FLYINGH_GLANCE_RIGHT_LINK 0x0607C4EC /* Fallback Glance Right button */ +#define DIBUTTON_FLYINGH_GLANCE_UP_LINK 0x0607C4E0 /* Fallback Glance Up button */ +#define DIBUTTON_FLYINGH_GLANCE_DOWN_LINK 0x0607C4E8 /* Fallback Glance Down button */ +#define DIBUTTON_FLYINGH_DEVICE 0x060044FE /* Show input device and controls */ +#define DIBUTTON_FLYINGH_PAUSE 0x060044FC /* Start / Pause / Restart game */ + +/*--- Space Simulator - Combat + Space Simulator with weapons ---*/ +#define DIVIRTUAL_SPACESIM 0x07000000 +#define DIAXIS_SPACESIM_LATERAL 0x07008201 /* Move ship left / right */ +#define DIAXIS_SPACESIM_MOVE 0x07010202 /* Move ship forward/backward */ +#define DIAXIS_SPACESIM_THROTTLE 0x07038203 /* Throttle - Engine speed */ +#define DIBUTTON_SPACESIM_FIRE 0x07000401 /* Fire */ +#define DIBUTTON_SPACESIM_WEAPONS 0x07000402 /* Select next weapon */ +#define DIBUTTON_SPACESIM_TARGET 0x07000403 /* Selects next available target */ +#define DIBUTTON_SPACESIM_MENU 0x070004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_SPACESIM_GLANCE 0x07004601 /* Look around */ +#define DIAXIS_SPACESIM_CLIMB 0x0701C204 /* Climb - Pitch ship up/down */ +#define DIAXIS_SPACESIM_ROTATE 0x07024205 /* Rotate - Turn ship left/right */ +#define DIBUTTON_SPACESIM_VIEW 0x07004404 /* Cycle through view options */ +#define DIBUTTON_SPACESIM_DISPLAY 0x07004405 /* Select next dashboard / heads up display option */ +#define DIBUTTON_SPACESIM_RAISE 0x07004406 /* Raise ship while maintaining current pitch */ +#define DIBUTTON_SPACESIM_LOWER 0x07004407 /* Lower ship while maintaining current pitch */ +#define DIBUTTON_SPACESIM_GEAR 0x07004408 /* Gear up / down */ +#define DIBUTTON_SPACESIM_FIRESECONDARY 0x07004409 /* Alternative fire button */ +#define DIBUTTON_SPACESIM_LEFT_LINK 0x0700C4E4 /* Fallback move left button */ +#define DIBUTTON_SPACESIM_RIGHT_LINK 0x0700C4EC /* Fallback move right button */ +#define DIBUTTON_SPACESIM_FORWARD_LINK 0x070144E0 /* Fallback move forward button */ +#define DIBUTTON_SPACESIM_BACKWARD_LINK 0x070144E8 /* Fallback move backwards button */ +#define DIBUTTON_SPACESIM_FASTER_LINK 0x0703C4E0 /* Fallback throttle up button */ +#define DIBUTTON_SPACESIM_SLOWER_LINK 0x0703C4E8 /* Fallback throttle down button */ +#define DIBUTTON_SPACESIM_TURN_LEFT_LINK 0x070244E4 /* Fallback turn left button */ +#define DIBUTTON_SPACESIM_TURN_RIGHT_LINK 0x070244EC /* Fallback turn right button */ +#define DIBUTTON_SPACESIM_GLANCE_LEFT_LINK 0x0707C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_SPACESIM_GLANCE_RIGHT_LINK 0x0707C4EC /* Fallback Glance Right button */ +#define DIBUTTON_SPACESIM_GLANCE_UP_LINK 0x0707C4E0 /* Fallback Glance Up button */ +#define DIBUTTON_SPACESIM_GLANCE_DOWN_LINK 0x0707C4E8 /* Fallback Glance Down button */ +#define DIBUTTON_SPACESIM_DEVICE 0x070044FE /* Show input device and controls */ +#define DIBUTTON_SPACESIM_PAUSE 0x070044FC /* Start / Pause / Restart game */ + +/*--- Fighting - First Person + Hand to Hand combat is primary objective ---*/ +#define DIVIRTUAL_FIGHTING_HAND2HAND 0x08000000 +#define DIAXIS_FIGHTINGH_LATERAL 0x08008201 /* Sidestep left/right */ +#define DIAXIS_FIGHTINGH_MOVE 0x08010202 /* Move forward/backward */ +#define DIBUTTON_FIGHTINGH_PUNCH 0x08000401 /* Punch */ +#define DIBUTTON_FIGHTINGH_KICK 0x08000402 /* Kick */ +#define DIBUTTON_FIGHTINGH_BLOCK 0x08000403 /* Block */ +#define DIBUTTON_FIGHTINGH_CROUCH 0x08000404 /* Crouch */ +#define DIBUTTON_FIGHTINGH_JUMP 0x08000405 /* Jump */ +#define DIBUTTON_FIGHTINGH_SPECIAL1 0x08000406 /* Apply first special move */ +#define DIBUTTON_FIGHTINGH_SPECIAL2 0x08000407 /* Apply second special move */ +#define DIBUTTON_FIGHTINGH_MENU 0x080004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_FIGHTINGH_SELECT 0x08004408 /* Select special move */ +#define DIHATSWITCH_FIGHTINGH_SLIDE 0x08004601 /* Look around */ +#define DIBUTTON_FIGHTINGH_DISPLAY 0x08004409 /* Shows next on-screen display option */ +#define DIAXIS_FIGHTINGH_ROTATE 0x08024203 /* Rotate - Turn body left/right */ +#define DIBUTTON_FIGHTINGH_DODGE 0x0800440A /* Dodge */ +#define DIBUTTON_FIGHTINGH_LEFT_LINK 0x0800C4E4 /* Fallback left sidestep button */ +#define DIBUTTON_FIGHTINGH_RIGHT_LINK 0x0800C4EC /* Fallback right sidestep button */ +#define DIBUTTON_FIGHTINGH_FORWARD_LINK 0x080144E0 /* Fallback forward button */ +#define DIBUTTON_FIGHTINGH_BACKWARD_LINK 0x080144E8 /* Fallback backward button */ +#define DIBUTTON_FIGHTINGH_DEVICE 0x080044FE /* Show input device and controls */ +#define DIBUTTON_FIGHTINGH_PAUSE 0x080044FC /* Start / Pause / Restart game */ + +/*--- Fighting - First Person Shooting + Navigation and combat are primary objectives ---*/ +#define DIVIRTUAL_FIGHTING_FPS 0x09000000 +#define DIAXIS_FPS_ROTATE 0x09008201 /* Rotate character left/right */ +#define DIAXIS_FPS_MOVE 0x09010202 /* Move forward/backward */ +#define DIBUTTON_FPS_FIRE 0x09000401 /* Fire */ +#define DIBUTTON_FPS_WEAPONS 0x09000402 /* Select next weapon */ +#define DIBUTTON_FPS_APPLY 0x09000403 /* Use item */ +#define DIBUTTON_FPS_SELECT 0x09000404 /* Select next inventory item */ +#define DIBUTTON_FPS_CROUCH 0x09000405 /* Crouch/ climb down/ swim down */ +#define DIBUTTON_FPS_JUMP 0x09000406 /* Jump/ climb up/ swim up */ +#define DIAXIS_FPS_LOOKUPDOWN 0x09018203 /* Look up / down */ +#define DIBUTTON_FPS_STRAFE 0x09000407 /* Enable strafing while active */ +#define DIBUTTON_FPS_MENU 0x090004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_FPS_GLANCE 0x09004601 /* Look around */ +#define DIBUTTON_FPS_DISPLAY 0x09004408 /* Shows next on-screen display option/ map */ +#define DIAXIS_FPS_SIDESTEP 0x09024204 /* Sidestep */ +#define DIBUTTON_FPS_DODGE 0x09004409 /* Dodge */ +#define DIBUTTON_FPS_GLANCEL 0x0900440A /* Glance Left */ +#define DIBUTTON_FPS_GLANCER 0x0900440B /* Glance Right */ +#define DIBUTTON_FPS_FIRESECONDARY 0x0900440C /* Alternative fire button */ +#define DIBUTTON_FPS_ROTATE_LEFT_LINK 0x0900C4E4 /* Fallback rotate left button */ +#define DIBUTTON_FPS_ROTATE_RIGHT_LINK 0x0900C4EC /* Fallback rotate right button */ +#define DIBUTTON_FPS_FORWARD_LINK 0x090144E0 /* Fallback forward button */ +#define DIBUTTON_FPS_BACKWARD_LINK 0x090144E8 /* Fallback backward button */ +#define DIBUTTON_FPS_GLANCE_UP_LINK 0x0901C4E0 /* Fallback look up button */ +#define DIBUTTON_FPS_GLANCE_DOWN_LINK 0x0901C4E8 /* Fallback look down button */ +#define DIBUTTON_FPS_STEP_LEFT_LINK 0x090244E4 /* Fallback step left button */ +#define DIBUTTON_FPS_STEP_RIGHT_LINK 0x090244EC /* Fallback step right button */ +#define DIBUTTON_FPS_DEVICE 0x090044FE /* Show input device and controls */ +#define DIBUTTON_FPS_PAUSE 0x090044FC /* Start / Pause / Restart game */ + +/*--- Fighting - Third Person action + Perspective of camera is behind the main character ---*/ +#define DIVIRTUAL_FIGHTING_THIRDPERSON 0x0A000000 +#define DIAXIS_TPS_TURN 0x0A020201 /* Turn left/right */ +#define DIAXIS_TPS_MOVE 0x0A010202 /* Move forward/backward */ +#define DIBUTTON_TPS_RUN 0x0A000401 /* Run or walk toggle switch */ +#define DIBUTTON_TPS_ACTION 0x0A000402 /* Action Button */ +#define DIBUTTON_TPS_SELECT 0x0A000403 /* Select next weapon */ +#define DIBUTTON_TPS_USE 0x0A000404 /* Use inventory item currently selected */ +#define DIBUTTON_TPS_JUMP 0x0A000405 /* Character Jumps */ +#define DIBUTTON_TPS_MENU 0x0A0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_TPS_GLANCE 0x0A004601 /* Look around */ +#define DIBUTTON_TPS_VIEW 0x0A004406 /* Select camera view */ +#define DIBUTTON_TPS_STEPLEFT 0x0A004407 /* Character takes a left step */ +#define DIBUTTON_TPS_STEPRIGHT 0x0A004408 /* Character takes a right step */ +#define DIAXIS_TPS_STEP 0x0A00C203 /* Character steps left/right */ +#define DIBUTTON_TPS_DODGE 0x0A004409 /* Character dodges or ducks */ +#define DIBUTTON_TPS_INVENTORY 0x0A00440A /* Cycle through inventory */ +#define DIBUTTON_TPS_TURN_LEFT_LINK 0x0A0244E4 /* Fallback turn left button */ +#define DIBUTTON_TPS_TURN_RIGHT_LINK 0x0A0244EC /* Fallback turn right button */ +#define DIBUTTON_TPS_FORWARD_LINK 0x0A0144E0 /* Fallback forward button */ +#define DIBUTTON_TPS_BACKWARD_LINK 0x0A0144E8 /* Fallback backward button */ +#define DIBUTTON_TPS_GLANCE_UP_LINK 0x0A07C4E0 /* Fallback look up button */ +#define DIBUTTON_TPS_GLANCE_DOWN_LINK 0x0A07C4E8 /* Fallback look down button */ +#define DIBUTTON_TPS_GLANCE_LEFT_LINK 0x0A07C4E4 /* Fallback glance up button */ +#define DIBUTTON_TPS_GLANCE_RIGHT_LINK 0x0A07C4EC /* Fallback glance right button */ +#define DIBUTTON_TPS_DEVICE 0x0A0044FE /* Show input device and controls */ +#define DIBUTTON_TPS_PAUSE 0x0A0044FC /* Start / Pause / Restart game */ + +/*--- Strategy - Role Playing + Navigation and problem solving are primary actions ---*/ +#define DIVIRTUAL_STRATEGY_ROLEPLAYING 0x0B000000 +#define DIAXIS_STRATEGYR_LATERAL 0x0B008201 /* sidestep - left/right */ +#define DIAXIS_STRATEGYR_MOVE 0x0B010202 /* move forward/backward */ +#define DIBUTTON_STRATEGYR_GET 0x0B000401 /* Acquire item */ +#define DIBUTTON_STRATEGYR_APPLY 0x0B000402 /* Use selected item */ +#define DIBUTTON_STRATEGYR_SELECT 0x0B000403 /* Select nextitem */ +#define DIBUTTON_STRATEGYR_ATTACK 0x0B000404 /* Attack */ +#define DIBUTTON_STRATEGYR_CAST 0x0B000405 /* Cast Spell */ +#define DIBUTTON_STRATEGYR_CROUCH 0x0B000406 /* Crouch */ +#define DIBUTTON_STRATEGYR_JUMP 0x0B000407 /* Jump */ +#define DIBUTTON_STRATEGYR_MENU 0x0B0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_STRATEGYR_GLANCE 0x0B004601 /* Look around */ +#define DIBUTTON_STRATEGYR_MAP 0x0B004408 /* Cycle through map options */ +#define DIBUTTON_STRATEGYR_DISPLAY 0x0B004409 /* Shows next on-screen display option */ +#define DIAXIS_STRATEGYR_ROTATE 0x0B024203 /* Turn body left/right */ +#define DIBUTTON_STRATEGYR_LEFT_LINK 0x0B00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_STRATEGYR_RIGHT_LINK 0x0B00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_STRATEGYR_FORWARD_LINK 0x0B0144E0 /* Fallback move forward button */ +#define DIBUTTON_STRATEGYR_BACK_LINK 0x0B0144E8 /* Fallback move backward button */ +#define DIBUTTON_STRATEGYR_ROTATE_LEFT_LINK 0x0B0244E4 /* Fallback turn body left button */ +#define DIBUTTON_STRATEGYR_ROTATE_RIGHT_LINK 0x0B0244EC /* Fallback turn body right button */ +#define DIBUTTON_STRATEGYR_DEVICE 0x0B0044FE /* Show input device and controls */ +#define DIBUTTON_STRATEGYR_PAUSE 0x0B0044FC /* Start / Pause / Restart game */ + +/*--- Strategy - Turn based + Navigation and problem solving are primary actions ---*/ +#define DIVIRTUAL_STRATEGY_TURN 0x0C000000 +#define DIAXIS_STRATEGYT_LATERAL 0x0C008201 /* Sidestep left/right */ +#define DIAXIS_STRATEGYT_MOVE 0x0C010202 /* Move forward/backwards */ +#define DIBUTTON_STRATEGYT_SELECT 0x0C000401 /* Select unit or object */ +#define DIBUTTON_STRATEGYT_INSTRUCT 0x0C000402 /* Cycle through instructions */ +#define DIBUTTON_STRATEGYT_APPLY 0x0C000403 /* Apply selected instruction */ +#define DIBUTTON_STRATEGYT_TEAM 0x0C000404 /* Select next team / cycle through all */ +#define DIBUTTON_STRATEGYT_TURN 0x0C000405 /* Indicate turn over */ +#define DIBUTTON_STRATEGYT_MENU 0x0C0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_STRATEGYT_ZOOM 0x0C004406 /* Zoom - in / out */ +#define DIBUTTON_STRATEGYT_MAP 0x0C004407 /* cycle through map options */ +#define DIBUTTON_STRATEGYT_DISPLAY 0x0C004408 /* shows next on-screen display options */ +#define DIBUTTON_STRATEGYT_LEFT_LINK 0x0C00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_STRATEGYT_RIGHT_LINK 0x0C00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_STRATEGYT_FORWARD_LINK 0x0C0144E0 /* Fallback move forward button */ +#define DIBUTTON_STRATEGYT_BACK_LINK 0x0C0144E8 /* Fallback move back button */ +#define DIBUTTON_STRATEGYT_DEVICE 0x0C0044FE /* Show input device and controls */ +#define DIBUTTON_STRATEGYT_PAUSE 0x0C0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Hunting + Hunting ---*/ +#define DIVIRTUAL_SPORTS_HUNTING 0x0D000000 +#define DIAXIS_HUNTING_LATERAL 0x0D008201 /* sidestep left/right */ +#define DIAXIS_HUNTING_MOVE 0x0D010202 /* move forward/backwards */ +#define DIBUTTON_HUNTING_FIRE 0x0D000401 /* Fire selected weapon */ +#define DIBUTTON_HUNTING_AIM 0x0D000402 /* Select aim/move */ +#define DIBUTTON_HUNTING_WEAPON 0x0D000403 /* Select next weapon */ +#define DIBUTTON_HUNTING_BINOCULAR 0x0D000404 /* Look through Binoculars */ +#define DIBUTTON_HUNTING_CALL 0x0D000405 /* Make animal call */ +#define DIBUTTON_HUNTING_MAP 0x0D000406 /* View Map */ +#define DIBUTTON_HUNTING_SPECIAL 0x0D000407 /* Special game operation */ +#define DIBUTTON_HUNTING_MENU 0x0D0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_HUNTING_GLANCE 0x0D004601 /* Look around */ +#define DIBUTTON_HUNTING_DISPLAY 0x0D004408 /* show next on-screen display option */ +#define DIAXIS_HUNTING_ROTATE 0x0D024203 /* Turn body left/right */ +#define DIBUTTON_HUNTING_CROUCH 0x0D004409 /* Crouch/ Climb / Swim down */ +#define DIBUTTON_HUNTING_JUMP 0x0D00440A /* Jump/ Climb up / Swim up */ +#define DIBUTTON_HUNTING_FIRESECONDARY 0x0D00440B /* Alternative fire button */ +#define DIBUTTON_HUNTING_LEFT_LINK 0x0D00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_HUNTING_RIGHT_LINK 0x0D00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_HUNTING_FORWARD_LINK 0x0D0144E0 /* Fallback move forward button */ +#define DIBUTTON_HUNTING_BACK_LINK 0x0D0144E8 /* Fallback move back button */ +#define DIBUTTON_HUNTING_ROTATE_LEFT_LINK 0x0D0244E4 /* Fallback turn body left button */ +#define DIBUTTON_HUNTING_ROTATE_RIGHT_LINK 0x0D0244EC /* Fallback turn body right button */ +#define DIBUTTON_HUNTING_DEVICE 0x0D0044FE /* Show input device and controls */ +#define DIBUTTON_HUNTING_PAUSE 0x0D0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Fishing + Catching Fish is primary objective ---*/ +#define DIVIRTUAL_SPORTS_FISHING 0x0E000000 +#define DIAXIS_FISHING_LATERAL 0x0E008201 /* sidestep left/right */ +#define DIAXIS_FISHING_MOVE 0x0E010202 /* move forward/backwards */ +#define DIBUTTON_FISHING_CAST 0x0E000401 /* Cast line */ +#define DIBUTTON_FISHING_TYPE 0x0E000402 /* Select cast type */ +#define DIBUTTON_FISHING_BINOCULAR 0x0E000403 /* Look through Binocular */ +#define DIBUTTON_FISHING_BAIT 0x0E000404 /* Select type of Bait */ +#define DIBUTTON_FISHING_MAP 0x0E000405 /* View Map */ +#define DIBUTTON_FISHING_MENU 0x0E0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_FISHING_GLANCE 0x0E004601 /* Look around */ +#define DIBUTTON_FISHING_DISPLAY 0x0E004406 /* Show next on-screen display option */ +#define DIAXIS_FISHING_ROTATE 0x0E024203 /* Turn character left / right */ +#define DIBUTTON_FISHING_CROUCH 0x0E004407 /* Crouch/ Climb / Swim down */ +#define DIBUTTON_FISHING_JUMP 0x0E004408 /* Jump/ Climb up / Swim up */ +#define DIBUTTON_FISHING_LEFT_LINK 0x0E00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_FISHING_RIGHT_LINK 0x0E00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_FISHING_FORWARD_LINK 0x0E0144E0 /* Fallback move forward button */ +#define DIBUTTON_FISHING_BACK_LINK 0x0E0144E8 /* Fallback move back button */ +#define DIBUTTON_FISHING_ROTATE_LEFT_LINK 0x0E0244E4 /* Fallback turn body left button */ +#define DIBUTTON_FISHING_ROTATE_RIGHT_LINK 0x0E0244EC /* Fallback turn body right button */ +#define DIBUTTON_FISHING_DEVICE 0x0E0044FE /* Show input device and controls */ +#define DIBUTTON_FISHING_PAUSE 0x0E0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Baseball - Batting + Batter control is primary objective ---*/ +#define DIVIRTUAL_SPORTS_BASEBALL_BAT 0x0F000000 +#define DIAXIS_BASEBALLB_LATERAL 0x0F008201 /* Aim left / right */ +#define DIAXIS_BASEBALLB_MOVE 0x0F010202 /* Aim up / down */ +#define DIBUTTON_BASEBALLB_SELECT 0x0F000401 /* cycle through swing options */ +#define DIBUTTON_BASEBALLB_NORMAL 0x0F000402 /* normal swing */ +#define DIBUTTON_BASEBALLB_POWER 0x0F000403 /* swing for the fence */ +#define DIBUTTON_BASEBALLB_BUNT 0x0F000404 /* bunt */ +#define DIBUTTON_BASEBALLB_STEAL 0x0F000405 /* Base runner attempts to steal a base */ +#define DIBUTTON_BASEBALLB_BURST 0x0F000406 /* Base runner invokes burst of speed */ +#define DIBUTTON_BASEBALLB_SLIDE 0x0F000407 /* Base runner slides into base */ +#define DIBUTTON_BASEBALLB_CONTACT 0x0F000408 /* Contact swing */ +#define DIBUTTON_BASEBALLB_MENU 0x0F0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_BASEBALLB_NOSTEAL 0x0F004409 /* Base runner goes back to a base */ +#define DIBUTTON_BASEBALLB_BOX 0x0F00440A /* Enter or exit batting box */ +#define DIBUTTON_BASEBALLB_LEFT_LINK 0x0F00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_BASEBALLB_RIGHT_LINK 0x0F00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_BASEBALLB_FORWARD_LINK 0x0F0144E0 /* Fallback move forward button */ +#define DIBUTTON_BASEBALLB_BACK_LINK 0x0F0144E8 /* Fallback move back button */ +#define DIBUTTON_BASEBALLB_DEVICE 0x0F0044FE /* Show input device and controls */ +#define DIBUTTON_BASEBALLB_PAUSE 0x0F0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Baseball - Pitching + Pitcher control is primary objective ---*/ +#define DIVIRTUAL_SPORTS_BASEBALL_PITCH 0x10000000 +#define DIAXIS_BASEBALLP_LATERAL 0x10008201 /* Aim left / right */ +#define DIAXIS_BASEBALLP_MOVE 0x10010202 /* Aim up / down */ +#define DIBUTTON_BASEBALLP_SELECT 0x10000401 /* cycle through pitch selections */ +#define DIBUTTON_BASEBALLP_PITCH 0x10000402 /* throw pitch */ +#define DIBUTTON_BASEBALLP_BASE 0x10000403 /* select base to throw to */ +#define DIBUTTON_BASEBALLP_THROW 0x10000404 /* throw to base */ +#define DIBUTTON_BASEBALLP_FAKE 0x10000405 /* Fake a throw to a base */ +#define DIBUTTON_BASEBALLP_MENU 0x100004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_BASEBALLP_WALK 0x10004406 /* Throw intentional walk / pitch out */ +#define DIBUTTON_BASEBALLP_LOOK 0x10004407 /* Look at runners on bases */ +#define DIBUTTON_BASEBALLP_LEFT_LINK 0x1000C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_BASEBALLP_RIGHT_LINK 0x1000C4EC /* Fallback sidestep right button */ +#define DIBUTTON_BASEBALLP_FORWARD_LINK 0x100144E0 /* Fallback move forward button */ +#define DIBUTTON_BASEBALLP_BACK_LINK 0x100144E8 /* Fallback move back button */ +#define DIBUTTON_BASEBALLP_DEVICE 0x100044FE /* Show input device and controls */ +#define DIBUTTON_BASEBALLP_PAUSE 0x100044FC /* Start / Pause / Restart game */ + +/*--- Sports - Baseball - Fielding + Fielder control is primary objective ---*/ +#define DIVIRTUAL_SPORTS_BASEBALL_FIELD 0x11000000 +#define DIAXIS_BASEBALLF_LATERAL 0x11008201 /* Aim left / right */ +#define DIAXIS_BASEBALLF_MOVE 0x11010202 /* Aim up / down */ +#define DIBUTTON_BASEBALLF_NEAREST 0x11000401 /* Switch to fielder nearest to the ball */ +#define DIBUTTON_BASEBALLF_THROW1 0x11000402 /* Make conservative throw */ +#define DIBUTTON_BASEBALLF_THROW2 0x11000403 /* Make aggressive throw */ +#define DIBUTTON_BASEBALLF_BURST 0x11000404 /* Invoke burst of speed */ +#define DIBUTTON_BASEBALLF_JUMP 0x11000405 /* Jump to catch ball */ +#define DIBUTTON_BASEBALLF_DIVE 0x11000406 /* Dive to catch ball */ +#define DIBUTTON_BASEBALLF_MENU 0x110004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_BASEBALLF_SHIFTIN 0x11004407 /* Shift the infield positioning */ +#define DIBUTTON_BASEBALLF_SHIFTOUT 0x11004408 /* Shift the outfield positioning */ +#define DIBUTTON_BASEBALLF_AIM_LEFT_LINK 0x1100C4E4 /* Fallback aim left button */ +#define DIBUTTON_BASEBALLF_AIM_RIGHT_LINK 0x1100C4EC /* Fallback aim right button */ +#define DIBUTTON_BASEBALLF_FORWARD_LINK 0x110144E0 /* Fallback move forward button */ +#define DIBUTTON_BASEBALLF_BACK_LINK 0x110144E8 /* Fallback move back button */ +#define DIBUTTON_BASEBALLF_DEVICE 0x110044FE /* Show input device and controls */ +#define DIBUTTON_BASEBALLF_PAUSE 0x110044FC /* Start / Pause / Restart game */ + +/*--- Sports - Basketball - Offense + Offense ---*/ +#define DIVIRTUAL_SPORTS_BASKETBALL_OFFENSE 0x12000000 +#define DIAXIS_BBALLO_LATERAL 0x12008201 /* left / right */ +#define DIAXIS_BBALLO_MOVE 0x12010202 /* up / down */ +#define DIBUTTON_BBALLO_SHOOT 0x12000401 /* shoot basket */ +#define DIBUTTON_BBALLO_DUNK 0x12000402 /* dunk basket */ +#define DIBUTTON_BBALLO_PASS 0x12000403 /* throw pass */ +#define DIBUTTON_BBALLO_FAKE 0x12000404 /* fake shot or pass */ +#define DIBUTTON_BBALLO_SPECIAL 0x12000405 /* apply special move */ +#define DIBUTTON_BBALLO_PLAYER 0x12000406 /* select next player */ +#define DIBUTTON_BBALLO_BURST 0x12000407 /* invoke burst */ +#define DIBUTTON_BBALLO_CALL 0x12000408 /* call for ball / pass to me */ +#define DIBUTTON_BBALLO_MENU 0x120004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_BBALLO_GLANCE 0x12004601 /* scroll view */ +#define DIBUTTON_BBALLO_SCREEN 0x12004409 /* Call for screen */ +#define DIBUTTON_BBALLO_PLAY 0x1200440A /* Call for specific offensive play */ +#define DIBUTTON_BBALLO_JAB 0x1200440B /* Initiate fake drive to basket */ +#define DIBUTTON_BBALLO_POST 0x1200440C /* Perform post move */ +#define DIBUTTON_BBALLO_TIMEOUT 0x1200440D /* Time Out */ +#define DIBUTTON_BBALLO_SUBSTITUTE 0x1200440E /* substitute one player for another */ +#define DIBUTTON_BBALLO_LEFT_LINK 0x1200C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_BBALLO_RIGHT_LINK 0x1200C4EC /* Fallback sidestep right button */ +#define DIBUTTON_BBALLO_FORWARD_LINK 0x120144E0 /* Fallback move forward button */ +#define DIBUTTON_BBALLO_BACK_LINK 0x120144E8 /* Fallback move back button */ +#define DIBUTTON_BBALLO_DEVICE 0x120044FE /* Show input device and controls */ +#define DIBUTTON_BBALLO_PAUSE 0x120044FC /* Start / Pause / Restart game */ + +/*--- Sports - Basketball - Defense + Defense ---*/ +#define DIVIRTUAL_SPORTS_BASKETBALL_DEFENSE 0x13000000 +#define DIAXIS_BBALLD_LATERAL 0x13008201 /* left / right */ +#define DIAXIS_BBALLD_MOVE 0x13010202 /* up / down */ +#define DIBUTTON_BBALLD_JUMP 0x13000401 /* jump to block shot */ +#define DIBUTTON_BBALLD_STEAL 0x13000402 /* attempt to steal ball */ +#define DIBUTTON_BBALLD_FAKE 0x13000403 /* fake block or steal */ +#define DIBUTTON_BBALLD_SPECIAL 0x13000404 /* apply special move */ +#define DIBUTTON_BBALLD_PLAYER 0x13000405 /* select next player */ +#define DIBUTTON_BBALLD_BURST 0x13000406 /* invoke burst */ +#define DIBUTTON_BBALLD_PLAY 0x13000407 /* call for specific defensive play */ +#define DIBUTTON_BBALLD_MENU 0x130004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_BBALLD_GLANCE 0x13004601 /* scroll view */ +#define DIBUTTON_BBALLD_TIMEOUT 0x13004408 /* Time Out */ +#define DIBUTTON_BBALLD_SUBSTITUTE 0x13004409 /* substitute one player for another */ +#define DIBUTTON_BBALLD_LEFT_LINK 0x1300C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_BBALLD_RIGHT_LINK 0x1300C4EC /* Fallback sidestep right button */ +#define DIBUTTON_BBALLD_FORWARD_LINK 0x130144E0 /* Fallback move forward button */ +#define DIBUTTON_BBALLD_BACK_LINK 0x130144E8 /* Fallback move back button */ +#define DIBUTTON_BBALLD_DEVICE 0x130044FE /* Show input device and controls */ +#define DIBUTTON_BBALLD_PAUSE 0x130044FC /* Start / Pause / Restart game */ + +/*--- Sports - Football - Play + Play selection ---*/ +#define DIVIRTUAL_SPORTS_FOOTBALL_FIELD 0x14000000 +#define DIBUTTON_FOOTBALLP_PLAY 0x14000401 /* cycle through available plays */ +#define DIBUTTON_FOOTBALLP_SELECT 0x14000402 /* select play */ +#define DIBUTTON_FOOTBALLP_HELP 0x14000403 /* Bring up pop-up help */ +#define DIBUTTON_FOOTBALLP_MENU 0x140004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_FOOTBALLP_DEVICE 0x140044FE /* Show input device and controls */ +#define DIBUTTON_FOOTBALLP_PAUSE 0x140044FC /* Start / Pause / Restart game */ + +/*--- Sports - Football - QB + Offense: Quarterback / Kicker ---*/ +#define DIVIRTUAL_SPORTS_FOOTBALL_QBCK 0x15000000 +#define DIAXIS_FOOTBALLQ_LATERAL 0x15008201 /* Move / Aim: left / right */ +#define DIAXIS_FOOTBALLQ_MOVE 0x15010202 /* Move / Aim: up / down */ +#define DIBUTTON_FOOTBALLQ_SELECT 0x15000401 /* Select */ +#define DIBUTTON_FOOTBALLQ_SNAP 0x15000402 /* snap ball - start play */ +#define DIBUTTON_FOOTBALLQ_JUMP 0x15000403 /* jump over defender */ +#define DIBUTTON_FOOTBALLQ_SLIDE 0x15000404 /* Dive/Slide */ +#define DIBUTTON_FOOTBALLQ_PASS 0x15000405 /* throws pass to receiver */ +#define DIBUTTON_FOOTBALLQ_FAKE 0x15000406 /* pump fake pass or fake kick */ +#define DIBUTTON_FOOTBALLQ_MENU 0x150004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_FOOTBALLQ_FAKESNAP 0x15004407 /* Fake snap */ +#define DIBUTTON_FOOTBALLQ_MOTION 0x15004408 /* Send receivers in motion */ +#define DIBUTTON_FOOTBALLQ_AUDIBLE 0x15004409 /* Change offensive play at line of scrimmage */ +#define DIBUTTON_FOOTBALLQ_LEFT_LINK 0x1500C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_FOOTBALLQ_RIGHT_LINK 0x1500C4EC /* Fallback sidestep right button */ +#define DIBUTTON_FOOTBALLQ_FORWARD_LINK 0x150144E0 /* Fallback move forward button */ +#define DIBUTTON_FOOTBALLQ_BACK_LINK 0x150144E8 /* Fallback move back button */ +#define DIBUTTON_FOOTBALLQ_DEVICE 0x150044FE /* Show input device and controls */ +#define DIBUTTON_FOOTBALLQ_PAUSE 0x150044FC /* Start / Pause / Restart game */ + +/*--- Sports - Football - Offense + Offense - Runner ---*/ +#define DIVIRTUAL_SPORTS_FOOTBALL_OFFENSE 0x16000000 +#define DIAXIS_FOOTBALLO_LATERAL 0x16008201 /* Move / Aim: left / right */ +#define DIAXIS_FOOTBALLO_MOVE 0x16010202 /* Move / Aim: up / down */ +#define DIBUTTON_FOOTBALLO_JUMP 0x16000401 /* jump or hurdle over defender */ +#define DIBUTTON_FOOTBALLO_LEFTARM 0x16000402 /* holds out left arm */ +#define DIBUTTON_FOOTBALLO_RIGHTARM 0x16000403 /* holds out right arm */ +#define DIBUTTON_FOOTBALLO_THROW 0x16000404 /* throw pass or lateral ball to another runner */ +#define DIBUTTON_FOOTBALLO_SPIN 0x16000405 /* Spin to avoid defenders */ +#define DIBUTTON_FOOTBALLO_MENU 0x160004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_FOOTBALLO_JUKE 0x16004406 /* Use special move to avoid defenders */ +#define DIBUTTON_FOOTBALLO_SHOULDER 0x16004407 /* Lower shoulder to run over defenders */ +#define DIBUTTON_FOOTBALLO_TURBO 0x16004408 /* Speed burst past defenders */ +#define DIBUTTON_FOOTBALLO_DIVE 0x16004409 /* Dive over defenders */ +#define DIBUTTON_FOOTBALLO_ZOOM 0x1600440A /* Zoom view in / out */ +#define DIBUTTON_FOOTBALLO_SUBSTITUTE 0x1600440B /* substitute one player for another */ +#define DIBUTTON_FOOTBALLO_LEFT_LINK 0x1600C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_FOOTBALLO_RIGHT_LINK 0x1600C4EC /* Fallback sidestep right button */ +#define DIBUTTON_FOOTBALLO_FORWARD_LINK 0x160144E0 /* Fallback move forward button */ +#define DIBUTTON_FOOTBALLO_BACK_LINK 0x160144E8 /* Fallback move back button */ +#define DIBUTTON_FOOTBALLO_DEVICE 0x160044FE /* Show input device and controls */ +#define DIBUTTON_FOOTBALLO_PAUSE 0x160044FC /* Start / Pause / Restart game */ + +/*--- Sports - Football - Defense + Defense ---*/ +#define DIVIRTUAL_SPORTS_FOOTBALL_DEFENSE 0x17000000 +#define DIAXIS_FOOTBALLD_LATERAL 0x17008201 /* Move / Aim: left / right */ +#define DIAXIS_FOOTBALLD_MOVE 0x17010202 /* Move / Aim: up / down */ +#define DIBUTTON_FOOTBALLD_PLAY 0x17000401 /* cycle through available plays */ +#define DIBUTTON_FOOTBALLD_SELECT 0x17000402 /* select player closest to the ball */ +#define DIBUTTON_FOOTBALLD_JUMP 0x17000403 /* jump to intercept or block */ +#define DIBUTTON_FOOTBALLD_TACKLE 0x17000404 /* tackler runner */ +#define DIBUTTON_FOOTBALLD_FAKE 0x17000405 /* hold down to fake tackle or intercept */ +#define DIBUTTON_FOOTBALLD_SUPERTACKLE 0x17000406 /* Initiate special tackle */ +#define DIBUTTON_FOOTBALLD_MENU 0x170004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_FOOTBALLD_SPIN 0x17004407 /* Spin to beat offensive line */ +#define DIBUTTON_FOOTBALLD_SWIM 0x17004408 /* Swim to beat the offensive line */ +#define DIBUTTON_FOOTBALLD_BULLRUSH 0x17004409 /* Bull rush the offensive line */ +#define DIBUTTON_FOOTBALLD_RIP 0x1700440A /* Rip the offensive line */ +#define DIBUTTON_FOOTBALLD_AUDIBLE 0x1700440B /* Change defensive play at the line of scrimmage */ +#define DIBUTTON_FOOTBALLD_ZOOM 0x1700440C /* Zoom view in / out */ +#define DIBUTTON_FOOTBALLD_SUBSTITUTE 0x1700440D /* substitute one player for another */ +#define DIBUTTON_FOOTBALLD_LEFT_LINK 0x1700C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_FOOTBALLD_RIGHT_LINK 0x1700C4EC /* Fallback sidestep right button */ +#define DIBUTTON_FOOTBALLD_FORWARD_LINK 0x170144E0 /* Fallback move forward button */ +#define DIBUTTON_FOOTBALLD_BACK_LINK 0x170144E8 /* Fallback move back button */ +#define DIBUTTON_FOOTBALLD_DEVICE 0x170044FE /* Show input device and controls */ +#define DIBUTTON_FOOTBALLD_PAUSE 0x170044FC /* Start / Pause / Restart game */ + +/*--- Sports - Golf + ---*/ +#define DIVIRTUAL_SPORTS_GOLF 0x18000000 +#define DIAXIS_GOLF_LATERAL 0x18008201 /* Move / Aim: left / right */ +#define DIAXIS_GOLF_MOVE 0x18010202 /* Move / Aim: up / down */ +#define DIBUTTON_GOLF_SWING 0x18000401 /* swing club */ +#define DIBUTTON_GOLF_SELECT 0x18000402 /* cycle between: club / swing strength / ball arc / ball spin */ +#define DIBUTTON_GOLF_UP 0x18000403 /* increase selection */ +#define DIBUTTON_GOLF_DOWN 0x18000404 /* decrease selection */ +#define DIBUTTON_GOLF_TERRAIN 0x18000405 /* shows terrain detail */ +#define DIBUTTON_GOLF_FLYBY 0x18000406 /* view the hole via a flyby */ +#define DIBUTTON_GOLF_MENU 0x180004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_GOLF_SCROLL 0x18004601 /* scroll view */ +#define DIBUTTON_GOLF_ZOOM 0x18004407 /* Zoom view in / out */ +#define DIBUTTON_GOLF_TIMEOUT 0x18004408 /* Call for time out */ +#define DIBUTTON_GOLF_SUBSTITUTE 0x18004409 /* substitute one player for another */ +#define DIBUTTON_GOLF_LEFT_LINK 0x1800C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_GOLF_RIGHT_LINK 0x1800C4EC /* Fallback sidestep right button */ +#define DIBUTTON_GOLF_FORWARD_LINK 0x180144E0 /* Fallback move forward button */ +#define DIBUTTON_GOLF_BACK_LINK 0x180144E8 /* Fallback move back button */ +#define DIBUTTON_GOLF_DEVICE 0x180044FE /* Show input device and controls */ +#define DIBUTTON_GOLF_PAUSE 0x180044FC /* Start / Pause / Restart game */ + +/*--- Sports - Hockey - Offense + Offense ---*/ +#define DIVIRTUAL_SPORTS_HOCKEY_OFFENSE 0x19000000 +#define DIAXIS_HOCKEYO_LATERAL 0x19008201 /* Move / Aim: left / right */ +#define DIAXIS_HOCKEYO_MOVE 0x19010202 /* Move / Aim: up / down */ +#define DIBUTTON_HOCKEYO_SHOOT 0x19000401 /* Shoot */ +#define DIBUTTON_HOCKEYO_PASS 0x19000402 /* pass the puck */ +#define DIBUTTON_HOCKEYO_BURST 0x19000403 /* invoke speed burst */ +#define DIBUTTON_HOCKEYO_SPECIAL 0x19000404 /* invoke special move */ +#define DIBUTTON_HOCKEYO_FAKE 0x19000405 /* hold down to fake pass or kick */ +#define DIBUTTON_HOCKEYO_MENU 0x190004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_HOCKEYO_SCROLL 0x19004601 /* scroll view */ +#define DIBUTTON_HOCKEYO_ZOOM 0x19004406 /* Zoom view in / out */ +#define DIBUTTON_HOCKEYO_STRATEGY 0x19004407 /* Invoke coaching menu for strategy help */ +#define DIBUTTON_HOCKEYO_TIMEOUT 0x19004408 /* Call for time out */ +#define DIBUTTON_HOCKEYO_SUBSTITUTE 0x19004409 /* substitute one player for another */ +#define DIBUTTON_HOCKEYO_LEFT_LINK 0x1900C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_HOCKEYO_RIGHT_LINK 0x1900C4EC /* Fallback sidestep right button */ +#define DIBUTTON_HOCKEYO_FORWARD_LINK 0x190144E0 /* Fallback move forward button */ +#define DIBUTTON_HOCKEYO_BACK_LINK 0x190144E8 /* Fallback move back button */ +#define DIBUTTON_HOCKEYO_DEVICE 0x190044FE /* Show input device and controls */ +#define DIBUTTON_HOCKEYO_PAUSE 0x190044FC /* Start / Pause / Restart game */ + +/*--- Sports - Hockey - Defense + Defense ---*/ +#define DIVIRTUAL_SPORTS_HOCKEY_DEFENSE 0x1A000000 +#define DIAXIS_HOCKEYD_LATERAL 0x1A008201 /* Move / Aim: left / right */ +#define DIAXIS_HOCKEYD_MOVE 0x1A010202 /* Move / Aim: up / down */ +#define DIBUTTON_HOCKEYD_PLAYER 0x1A000401 /* control player closest to the puck */ +#define DIBUTTON_HOCKEYD_STEAL 0x1A000402 /* attempt steal */ +#define DIBUTTON_HOCKEYD_BURST 0x1A000403 /* speed burst or body check */ +#define DIBUTTON_HOCKEYD_BLOCK 0x1A000404 /* block puck */ +#define DIBUTTON_HOCKEYD_FAKE 0x1A000405 /* hold down to fake tackle or intercept */ +#define DIBUTTON_HOCKEYD_MENU 0x1A0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_HOCKEYD_SCROLL 0x1A004601 /* scroll view */ +#define DIBUTTON_HOCKEYD_ZOOM 0x1A004406 /* Zoom view in / out */ +#define DIBUTTON_HOCKEYD_STRATEGY 0x1A004407 /* Invoke coaching menu for strategy help */ +#define DIBUTTON_HOCKEYD_TIMEOUT 0x1A004408 /* Call for time out */ +#define DIBUTTON_HOCKEYD_SUBSTITUTE 0x1A004409 /* substitute one player for another */ +#define DIBUTTON_HOCKEYD_LEFT_LINK 0x1A00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_HOCKEYD_RIGHT_LINK 0x1A00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_HOCKEYD_FORWARD_LINK 0x1A0144E0 /* Fallback move forward button */ +#define DIBUTTON_HOCKEYD_BACK_LINK 0x1A0144E8 /* Fallback move back button */ +#define DIBUTTON_HOCKEYD_DEVICE 0x1A0044FE /* Show input device and controls */ +#define DIBUTTON_HOCKEYD_PAUSE 0x1A0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Hockey - Goalie + Goal tending ---*/ +#define DIVIRTUAL_SPORTS_HOCKEY_GOALIE 0x1B000000 +#define DIAXIS_HOCKEYG_LATERAL 0x1B008201 /* Move / Aim: left / right */ +#define DIAXIS_HOCKEYG_MOVE 0x1B010202 /* Move / Aim: up / down */ +#define DIBUTTON_HOCKEYG_PASS 0x1B000401 /* pass puck */ +#define DIBUTTON_HOCKEYG_POKE 0x1B000402 /* poke / check / hack */ +#define DIBUTTON_HOCKEYG_STEAL 0x1B000403 /* attempt steal */ +#define DIBUTTON_HOCKEYG_BLOCK 0x1B000404 /* block puck */ +#define DIBUTTON_HOCKEYG_MENU 0x1B0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_HOCKEYG_SCROLL 0x1B004601 /* scroll view */ +#define DIBUTTON_HOCKEYG_ZOOM 0x1B004405 /* Zoom view in / out */ +#define DIBUTTON_HOCKEYG_STRATEGY 0x1B004406 /* Invoke coaching menu for strategy help */ +#define DIBUTTON_HOCKEYG_TIMEOUT 0x1B004407 /* Call for time out */ +#define DIBUTTON_HOCKEYG_SUBSTITUTE 0x1B004408 /* substitute one player for another */ +#define DIBUTTON_HOCKEYG_LEFT_LINK 0x1B00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_HOCKEYG_RIGHT_LINK 0x1B00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_HOCKEYG_FORWARD_LINK 0x1B0144E0 /* Fallback move forward button */ +#define DIBUTTON_HOCKEYG_BACK_LINK 0x1B0144E8 /* Fallback move back button */ +#define DIBUTTON_HOCKEYG_DEVICE 0x1B0044FE /* Show input device and controls */ +#define DIBUTTON_HOCKEYG_PAUSE 0x1B0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Mountain Biking + ---*/ +#define DIVIRTUAL_SPORTS_BIKING_MOUNTAIN 0x1C000000 +#define DIAXIS_BIKINGM_TURN 0x1C008201 /* left / right */ +#define DIAXIS_BIKINGM_PEDAL 0x1C010202 /* Pedal faster / slower / brake */ +#define DIBUTTON_BIKINGM_JUMP 0x1C000401 /* jump over obstacle */ +#define DIBUTTON_BIKINGM_CAMERA 0x1C000402 /* switch camera view */ +#define DIBUTTON_BIKINGM_SPECIAL1 0x1C000403 /* perform first special move */ +#define DIBUTTON_BIKINGM_SELECT 0x1C000404 /* Select */ +#define DIBUTTON_BIKINGM_SPECIAL2 0x1C000405 /* perform second special move */ +#define DIBUTTON_BIKINGM_MENU 0x1C0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_BIKINGM_SCROLL 0x1C004601 /* scroll view */ +#define DIBUTTON_BIKINGM_ZOOM 0x1C004406 /* Zoom view in / out */ +#define DIAXIS_BIKINGM_BRAKE 0x1C044203 /* Brake axis */ +#define DIBUTTON_BIKINGM_LEFT_LINK 0x1C00C4E4 /* Fallback turn left button */ +#define DIBUTTON_BIKINGM_RIGHT_LINK 0x1C00C4EC /* Fallback turn right button */ +#define DIBUTTON_BIKINGM_FASTER_LINK 0x1C0144E0 /* Fallback pedal faster button */ +#define DIBUTTON_BIKINGM_SLOWER_LINK 0x1C0144E8 /* Fallback pedal slower button */ +#define DIBUTTON_BIKINGM_BRAKE_BUTTON_LINK 0x1C0444E8 /* Fallback brake button */ +#define DIBUTTON_BIKINGM_DEVICE 0x1C0044FE /* Show input device and controls */ +#define DIBUTTON_BIKINGM_PAUSE 0x1C0044FC /* Start / Pause / Restart game */ + +/*--- Sports: Skiing / Snowboarding / Skateboarding + ---*/ +#define DIVIRTUAL_SPORTS_SKIING 0x1D000000 +#define DIAXIS_SKIING_TURN 0x1D008201 /* left / right */ +#define DIAXIS_SKIING_SPEED 0x1D010202 /* faster / slower */ +#define DIBUTTON_SKIING_JUMP 0x1D000401 /* Jump */ +#define DIBUTTON_SKIING_CROUCH 0x1D000402 /* crouch down */ +#define DIBUTTON_SKIING_CAMERA 0x1D000403 /* switch camera view */ +#define DIBUTTON_SKIING_SPECIAL1 0x1D000404 /* perform first special move */ +#define DIBUTTON_SKIING_SELECT 0x1D000405 /* Select */ +#define DIBUTTON_SKIING_SPECIAL2 0x1D000406 /* perform second special move */ +#define DIBUTTON_SKIING_MENU 0x1D0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_SKIING_GLANCE 0x1D004601 /* scroll view */ +#define DIBUTTON_SKIING_ZOOM 0x1D004407 /* Zoom view in / out */ +#define DIBUTTON_SKIING_LEFT_LINK 0x1D00C4E4 /* Fallback turn left button */ +#define DIBUTTON_SKIING_RIGHT_LINK 0x1D00C4EC /* Fallback turn right button */ +#define DIBUTTON_SKIING_FASTER_LINK 0x1D0144E0 /* Fallback increase speed button */ +#define DIBUTTON_SKIING_SLOWER_LINK 0x1D0144E8 /* Fallback decrease speed button */ +#define DIBUTTON_SKIING_DEVICE 0x1D0044FE /* Show input device and controls */ +#define DIBUTTON_SKIING_PAUSE 0x1D0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Soccer - Offense + Offense ---*/ +#define DIVIRTUAL_SPORTS_SOCCER_OFFENSE 0x1E000000 +#define DIAXIS_SOCCERO_LATERAL 0x1E008201 /* Move / Aim: left / right */ +#define DIAXIS_SOCCERO_MOVE 0x1E010202 /* Move / Aim: up / down */ +#define DIAXIS_SOCCERO_BEND 0x1E018203 /* Bend to soccer shot/pass */ +#define DIBUTTON_SOCCERO_SHOOT 0x1E000401 /* Shoot the ball */ +#define DIBUTTON_SOCCERO_PASS 0x1E000402 /* Pass */ +#define DIBUTTON_SOCCERO_FAKE 0x1E000403 /* Fake */ +#define DIBUTTON_SOCCERO_PLAYER 0x1E000404 /* Select next player */ +#define DIBUTTON_SOCCERO_SPECIAL1 0x1E000405 /* Apply special move */ +#define DIBUTTON_SOCCERO_SELECT 0x1E000406 /* Select special move */ +#define DIBUTTON_SOCCERO_MENU 0x1E0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_SOCCERO_GLANCE 0x1E004601 /* scroll view */ +#define DIBUTTON_SOCCERO_SUBSTITUTE 0x1E004407 /* Substitute one player for another */ +#define DIBUTTON_SOCCERO_SHOOTLOW 0x1E004408 /* Shoot the ball low */ +#define DIBUTTON_SOCCERO_SHOOTHIGH 0x1E004409 /* Shoot the ball high */ +#define DIBUTTON_SOCCERO_PASSTHRU 0x1E00440A /* Make a thru pass */ +#define DIBUTTON_SOCCERO_SPRINT 0x1E00440B /* Sprint / turbo boost */ +#define DIBUTTON_SOCCERO_CONTROL 0x1E00440C /* Obtain control of the ball */ +#define DIBUTTON_SOCCERO_HEAD 0x1E00440D /* Attempt to head the ball */ +#define DIBUTTON_SOCCERO_LEFT_LINK 0x1E00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_SOCCERO_RIGHT_LINK 0x1E00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_SOCCERO_FORWARD_LINK 0x1E0144E0 /* Fallback move forward button */ +#define DIBUTTON_SOCCERO_BACK_LINK 0x1E0144E8 /* Fallback move back button */ +#define DIBUTTON_SOCCERO_DEVICE 0x1E0044FE /* Show input device and controls */ +#define DIBUTTON_SOCCERO_PAUSE 0x1E0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Soccer - Defense + Defense ---*/ +#define DIVIRTUAL_SPORTS_SOCCER_DEFENSE 0x1F000000 +#define DIAXIS_SOCCERD_LATERAL 0x1F008201 /* Move / Aim: left / right */ +#define DIAXIS_SOCCERD_MOVE 0x1F010202 /* Move / Aim: up / down */ +#define DIBUTTON_SOCCERD_BLOCK 0x1F000401 /* Attempt to block shot */ +#define DIBUTTON_SOCCERD_STEAL 0x1F000402 /* Attempt to steal ball */ +#define DIBUTTON_SOCCERD_FAKE 0x1F000403 /* Fake a block or a steal */ +#define DIBUTTON_SOCCERD_PLAYER 0x1F000404 /* Select next player */ +#define DIBUTTON_SOCCERD_SPECIAL 0x1F000405 /* Apply special move */ +#define DIBUTTON_SOCCERD_SELECT 0x1F000406 /* Select special move */ +#define DIBUTTON_SOCCERD_SLIDE 0x1F000407 /* Attempt a slide tackle */ +#define DIBUTTON_SOCCERD_MENU 0x1F0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_SOCCERD_GLANCE 0x1F004601 /* scroll view */ +#define DIBUTTON_SOCCERD_FOUL 0x1F004408 /* Initiate a foul / hard-foul */ +#define DIBUTTON_SOCCERD_HEAD 0x1F004409 /* Attempt a Header */ +#define DIBUTTON_SOCCERD_CLEAR 0x1F00440A /* Attempt to clear the ball down the field */ +#define DIBUTTON_SOCCERD_GOALIECHARGE 0x1F00440B /* Make the goalie charge out of the box */ +#define DIBUTTON_SOCCERD_SUBSTITUTE 0x1F00440C /* Substitute one player for another */ +#define DIBUTTON_SOCCERD_LEFT_LINK 0x1F00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_SOCCERD_RIGHT_LINK 0x1F00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_SOCCERD_FORWARD_LINK 0x1F0144E0 /* Fallback move forward button */ +#define DIBUTTON_SOCCERD_BACK_LINK 0x1F0144E8 /* Fallback move back button */ +#define DIBUTTON_SOCCERD_DEVICE 0x1F0044FE /* Show input device and controls */ +#define DIBUTTON_SOCCERD_PAUSE 0x1F0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Racquet + Tennis - Table-Tennis - Squash ---*/ +#define DIVIRTUAL_SPORTS_RACQUET 0x20000000 +#define DIAXIS_RACQUET_LATERAL 0x20008201 /* Move / Aim: left / right */ +#define DIAXIS_RACQUET_MOVE 0x20010202 /* Move / Aim: up / down */ +#define DIBUTTON_RACQUET_SWING 0x20000401 /* Swing racquet */ +#define DIBUTTON_RACQUET_BACKSWING 0x20000402 /* Swing backhand */ +#define DIBUTTON_RACQUET_SMASH 0x20000403 /* Smash shot */ +#define DIBUTTON_RACQUET_SPECIAL 0x20000404 /* Special shot */ +#define DIBUTTON_RACQUET_SELECT 0x20000405 /* Select special shot */ +#define DIBUTTON_RACQUET_MENU 0x200004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_RACQUET_GLANCE 0x20004601 /* scroll view */ +#define DIBUTTON_RACQUET_TIMEOUT 0x20004406 /* Call for time out */ +#define DIBUTTON_RACQUET_SUBSTITUTE 0x20004407 /* Substitute one player for another */ +#define DIBUTTON_RACQUET_LEFT_LINK 0x2000C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_RACQUET_RIGHT_LINK 0x2000C4EC /* Fallback sidestep right button */ +#define DIBUTTON_RACQUET_FORWARD_LINK 0x200144E0 /* Fallback move forward button */ +#define DIBUTTON_RACQUET_BACK_LINK 0x200144E8 /* Fallback move back button */ +#define DIBUTTON_RACQUET_DEVICE 0x200044FE /* Show input device and controls */ +#define DIBUTTON_RACQUET_PAUSE 0x200044FC /* Start / Pause / Restart game */ + +/*--- Arcade- 2D + Side to Side movement ---*/ +#define DIVIRTUAL_ARCADE_SIDE2SIDE 0x21000000 +#define DIAXIS_ARCADES_LATERAL 0x21008201 /* left / right */ +#define DIAXIS_ARCADES_MOVE 0x21010202 /* up / down */ +#define DIBUTTON_ARCADES_THROW 0x21000401 /* throw object */ +#define DIBUTTON_ARCADES_CARRY 0x21000402 /* carry object */ +#define DIBUTTON_ARCADES_ATTACK 0x21000403 /* attack */ +#define DIBUTTON_ARCADES_SPECIAL 0x21000404 /* apply special move */ +#define DIBUTTON_ARCADES_SELECT 0x21000405 /* select special move */ +#define DIBUTTON_ARCADES_MENU 0x210004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_ARCADES_VIEW 0x21004601 /* scroll view left / right / up / down */ +#define DIBUTTON_ARCADES_LEFT_LINK 0x2100C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_ARCADES_RIGHT_LINK 0x2100C4EC /* Fallback sidestep right button */ +#define DIBUTTON_ARCADES_FORWARD_LINK 0x210144E0 /* Fallback move forward button */ +#define DIBUTTON_ARCADES_BACK_LINK 0x210144E8 /* Fallback move back button */ +#define DIBUTTON_ARCADES_VIEW_UP_LINK 0x2107C4E0 /* Fallback scroll view up button */ +#define DIBUTTON_ARCADES_VIEW_DOWN_LINK 0x2107C4E8 /* Fallback scroll view down button */ +#define DIBUTTON_ARCADES_VIEW_LEFT_LINK 0x2107C4E4 /* Fallback scroll view left button */ +#define DIBUTTON_ARCADES_VIEW_RIGHT_LINK 0x2107C4EC /* Fallback scroll view right button */ +#define DIBUTTON_ARCADES_DEVICE 0x210044FE /* Show input device and controls */ +#define DIBUTTON_ARCADES_PAUSE 0x210044FC /* Start / Pause / Restart game */ + +/*--- Arcade - Platform Game + Character moves around on screen ---*/ +#define DIVIRTUAL_ARCADE_PLATFORM 0x22000000 +#define DIAXIS_ARCADEP_LATERAL 0x22008201 /* Left / right */ +#define DIAXIS_ARCADEP_MOVE 0x22010202 /* Up / down */ +#define DIBUTTON_ARCADEP_JUMP 0x22000401 /* Jump */ +#define DIBUTTON_ARCADEP_FIRE 0x22000402 /* Fire */ +#define DIBUTTON_ARCADEP_CROUCH 0x22000403 /* Crouch */ +#define DIBUTTON_ARCADEP_SPECIAL 0x22000404 /* Apply special move */ +#define DIBUTTON_ARCADEP_SELECT 0x22000405 /* Select special move */ +#define DIBUTTON_ARCADEP_MENU 0x220004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_ARCADEP_VIEW 0x22004601 /* Scroll view */ +#define DIBUTTON_ARCADEP_FIRESECONDARY 0x22004406 /* Alternative fire button */ +#define DIBUTTON_ARCADEP_LEFT_LINK 0x2200C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_ARCADEP_RIGHT_LINK 0x2200C4EC /* Fallback sidestep right button */ +#define DIBUTTON_ARCADEP_FORWARD_LINK 0x220144E0 /* Fallback move forward button */ +#define DIBUTTON_ARCADEP_BACK_LINK 0x220144E8 /* Fallback move back button */ +#define DIBUTTON_ARCADEP_VIEW_UP_LINK 0x2207C4E0 /* Fallback scroll view up button */ +#define DIBUTTON_ARCADEP_VIEW_DOWN_LINK 0x2207C4E8 /* Fallback scroll view down button */ +#define DIBUTTON_ARCADEP_VIEW_LEFT_LINK 0x2207C4E4 /* Fallback scroll view left button */ +#define DIBUTTON_ARCADEP_VIEW_RIGHT_LINK 0x2207C4EC /* Fallback scroll view right button */ +#define DIBUTTON_ARCADEP_DEVICE 0x220044FE /* Show input device and controls */ +#define DIBUTTON_ARCADEP_PAUSE 0x220044FC /* Start / Pause / Restart game */ + +/*--- CAD - 2D Object Control + Controls to select and move objects in 2D ---*/ +#define DIVIRTUAL_CAD_2DCONTROL 0x23000000 +#define DIAXIS_2DCONTROL_LATERAL 0x23008201 /* Move view left / right */ +#define DIAXIS_2DCONTROL_MOVE 0x23010202 /* Move view up / down */ +#define DIAXIS_2DCONTROL_INOUT 0x23018203 /* Zoom - in / out */ +#define DIBUTTON_2DCONTROL_SELECT 0x23000401 /* Select Object */ +#define DIBUTTON_2DCONTROL_SPECIAL1 0x23000402 /* Do first special operation */ +#define DIBUTTON_2DCONTROL_SPECIAL 0x23000403 /* Select special operation */ +#define DIBUTTON_2DCONTROL_SPECIAL2 0x23000404 /* Do second special operation */ +#define DIBUTTON_2DCONTROL_MENU 0x230004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_2DCONTROL_HATSWITCH 0x23004601 /* Hat switch */ +#define DIAXIS_2DCONTROL_ROTATEZ 0x23024204 /* Rotate view clockwise / counterclockwise */ +#define DIBUTTON_2DCONTROL_DISPLAY 0x23004405 /* Shows next on-screen display options */ +#define DIBUTTON_2DCONTROL_DEVICE 0x230044FE /* Show input device and controls */ +#define DIBUTTON_2DCONTROL_PAUSE 0x230044FC /* Start / Pause / Restart game */ + +/*--- CAD - 3D object control + Controls to select and move objects within a 3D environment ---*/ +#define DIVIRTUAL_CAD_3DCONTROL 0x24000000 +#define DIAXIS_3DCONTROL_LATERAL 0x24008201 /* Move view left / right */ +#define DIAXIS_3DCONTROL_MOVE 0x24010202 /* Move view up / down */ +#define DIAXIS_3DCONTROL_INOUT 0x24018203 /* Zoom - in / out */ +#define DIBUTTON_3DCONTROL_SELECT 0x24000401 /* Select Object */ +#define DIBUTTON_3DCONTROL_SPECIAL1 0x24000402 /* Do first special operation */ +#define DIBUTTON_3DCONTROL_SPECIAL 0x24000403 /* Select special operation */ +#define DIBUTTON_3DCONTROL_SPECIAL2 0x24000404 /* Do second special operation */ +#define DIBUTTON_3DCONTROL_MENU 0x240004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_3DCONTROL_HATSWITCH 0x24004601 /* Hat switch */ +#define DIAXIS_3DCONTROL_ROTATEX 0x24034204 /* Rotate view forward or up / backward or down */ +#define DIAXIS_3DCONTROL_ROTATEY 0x2402C205 /* Rotate view clockwise / counterclockwise */ +#define DIAXIS_3DCONTROL_ROTATEZ 0x24024206 /* Rotate view left / right */ +#define DIBUTTON_3DCONTROL_DISPLAY 0x24004405 /* Show next on-screen display options */ +#define DIBUTTON_3DCONTROL_DEVICE 0x240044FE /* Show input device and controls */ +#define DIBUTTON_3DCONTROL_PAUSE 0x240044FC /* Start / Pause / Restart game */ + +/*--- CAD - 3D Navigation - Fly through + Controls for 3D modeling ---*/ +#define DIVIRTUAL_CAD_FLYBY 0x25000000 +#define DIAXIS_CADF_LATERAL 0x25008201 /* move view left / right */ +#define DIAXIS_CADF_MOVE 0x25010202 /* move view up / down */ +#define DIAXIS_CADF_INOUT 0x25018203 /* in / out */ +#define DIBUTTON_CADF_SELECT 0x25000401 /* Select Object */ +#define DIBUTTON_CADF_SPECIAL1 0x25000402 /* do first special operation */ +#define DIBUTTON_CADF_SPECIAL 0x25000403 /* Select special operation */ +#define DIBUTTON_CADF_SPECIAL2 0x25000404 /* do second special operation */ +#define DIBUTTON_CADF_MENU 0x250004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_CADF_HATSWITCH 0x25004601 /* Hat switch */ +#define DIAXIS_CADF_ROTATEX 0x25034204 /* Rotate view forward or up / backward or down */ +#define DIAXIS_CADF_ROTATEY 0x2502C205 /* Rotate view clockwise / counterclockwise */ +#define DIAXIS_CADF_ROTATEZ 0x25024206 /* Rotate view left / right */ +#define DIBUTTON_CADF_DISPLAY 0x25004405 /* shows next on-screen display options */ +#define DIBUTTON_CADF_DEVICE 0x250044FE /* Show input device and controls */ +#define DIBUTTON_CADF_PAUSE 0x250044FC /* Start / Pause / Restart game */ + +/*--- CAD - 3D Model Control + Controls for 3D modeling ---*/ +#define DIVIRTUAL_CAD_MODEL 0x26000000 +#define DIAXIS_CADM_LATERAL 0x26008201 /* move view left / right */ +#define DIAXIS_CADM_MOVE 0x26010202 /* move view up / down */ +#define DIAXIS_CADM_INOUT 0x26018203 /* in / out */ +#define DIBUTTON_CADM_SELECT 0x26000401 /* Select Object */ +#define DIBUTTON_CADM_SPECIAL1 0x26000402 /* do first special operation */ +#define DIBUTTON_CADM_SPECIAL 0x26000403 /* Select special operation */ +#define DIBUTTON_CADM_SPECIAL2 0x26000404 /* do second special operation */ +#define DIBUTTON_CADM_MENU 0x260004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_CADM_HATSWITCH 0x26004601 /* Hat switch */ +#define DIAXIS_CADM_ROTATEX 0x26034204 /* Rotate view forward or up / backward or down */ +#define DIAXIS_CADM_ROTATEY 0x2602C205 /* Rotate view clockwise / counterclockwise */ +#define DIAXIS_CADM_ROTATEZ 0x26024206 /* Rotate view left / right */ +#define DIBUTTON_CADM_DISPLAY 0x26004405 /* shows next on-screen display options */ +#define DIBUTTON_CADM_DEVICE 0x260044FE /* Show input device and controls */ +#define DIBUTTON_CADM_PAUSE 0x260044FC /* Start / Pause / Restart game */ + +/*--- Control - Media Equipment + Remote ---*/ +#define DIVIRTUAL_REMOTE_CONTROL 0x27000000 +#define DIAXIS_REMOTE_SLIDER 0x27050201 /* Slider for adjustment: volume / color / bass / etc */ +#define DIBUTTON_REMOTE_MUTE 0x27000401 /* Set volume on current device to zero */ +#define DIBUTTON_REMOTE_SELECT 0x27000402 /* Next/previous: channel/ track / chapter / picture / station */ +#define DIBUTTON_REMOTE_PLAY 0x27002403 /* Start or pause entertainment on current device */ +#define DIBUTTON_REMOTE_CUE 0x27002404 /* Move through current media */ +#define DIBUTTON_REMOTE_REVIEW 0x27002405 /* Move through current media */ +#define DIBUTTON_REMOTE_CHANGE 0x27002406 /* Select next device */ +#define DIBUTTON_REMOTE_RECORD 0x27002407 /* Start recording the current media */ +#define DIBUTTON_REMOTE_MENU 0x270004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIAXIS_REMOTE_SLIDER2 0x27054202 /* Slider for adjustment: volume */ +#define DIBUTTON_REMOTE_TV 0x27005C08 /* Select TV */ +#define DIBUTTON_REMOTE_CABLE 0x27005C09 /* Select cable box */ +#define DIBUTTON_REMOTE_CD 0x27005C0A /* Select CD player */ +#define DIBUTTON_REMOTE_VCR 0x27005C0B /* Select VCR */ +#define DIBUTTON_REMOTE_TUNER 0x27005C0C /* Select tuner */ +#define DIBUTTON_REMOTE_DVD 0x27005C0D /* Select DVD player */ +#define DIBUTTON_REMOTE_ADJUST 0x27005C0E /* Enter device adjustment menu */ +#define DIBUTTON_REMOTE_DIGIT0 0x2700540F /* Digit 0 */ +#define DIBUTTON_REMOTE_DIGIT1 0x27005410 /* Digit 1 */ +#define DIBUTTON_REMOTE_DIGIT2 0x27005411 /* Digit 2 */ +#define DIBUTTON_REMOTE_DIGIT3 0x27005412 /* Digit 3 */ +#define DIBUTTON_REMOTE_DIGIT4 0x27005413 /* Digit 4 */ +#define DIBUTTON_REMOTE_DIGIT5 0x27005414 /* Digit 5 */ +#define DIBUTTON_REMOTE_DIGIT6 0x27005415 /* Digit 6 */ +#define DIBUTTON_REMOTE_DIGIT7 0x27005416 /* Digit 7 */ +#define DIBUTTON_REMOTE_DIGIT8 0x27005417 /* Digit 8 */ +#define DIBUTTON_REMOTE_DIGIT9 0x27005418 /* Digit 9 */ +#define DIBUTTON_REMOTE_DEVICE 0x270044FE /* Show input device and controls */ +#define DIBUTTON_REMOTE_PAUSE 0x270044FC /* Start / Pause / Restart game */ + +/*--- Control- Web + Help or Browser ---*/ +#define DIVIRTUAL_BROWSER_CONTROL 0x28000000 +#define DIAXIS_BROWSER_LATERAL 0x28008201 /* Move on screen pointer */ +#define DIAXIS_BROWSER_MOVE 0x28010202 /* Move on screen pointer */ +#define DIBUTTON_BROWSER_SELECT 0x28000401 /* Select current item */ +#define DIAXIS_BROWSER_VIEW 0x28018203 /* Move view up/down */ +#define DIBUTTON_BROWSER_REFRESH 0x28000402 /* Refresh */ +#define DIBUTTON_BROWSER_MENU 0x280004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_BROWSER_SEARCH 0x28004403 /* Use search tool */ +#define DIBUTTON_BROWSER_STOP 0x28004404 /* Cease current update */ +#define DIBUTTON_BROWSER_HOME 0x28004405 /* Go directly to "home" location */ +#define DIBUTTON_BROWSER_FAVORITES 0x28004406 /* Mark current site as favorite */ +#define DIBUTTON_BROWSER_NEXT 0x28004407 /* Select Next page */ +#define DIBUTTON_BROWSER_PREVIOUS 0x28004408 /* Select Previous page */ +#define DIBUTTON_BROWSER_HISTORY 0x28004409 /* Show/Hide History */ +#define DIBUTTON_BROWSER_PRINT 0x2800440A /* Print current page */ +#define DIBUTTON_BROWSER_DEVICE 0x280044FE /* Show input device and controls */ +#define DIBUTTON_BROWSER_PAUSE 0x280044FC /* Start / Pause / Restart game */ + +/*--- Driving Simulator - Giant Walking Robot + Walking tank with weapons ---*/ +#define DIVIRTUAL_DRIVING_MECHA 0x29000000 +#define DIAXIS_MECHA_STEER 0x29008201 /* Turns mecha left/right */ +#define DIAXIS_MECHA_TORSO 0x29010202 /* Tilts torso forward/backward */ +#define DIAXIS_MECHA_ROTATE 0x29020203 /* Turns torso left/right */ +#define DIAXIS_MECHA_THROTTLE 0x29038204 /* Engine Speed */ +#define DIBUTTON_MECHA_FIRE 0x29000401 /* Fire */ +#define DIBUTTON_MECHA_WEAPONS 0x29000402 /* Select next weapon group */ +#define DIBUTTON_MECHA_TARGET 0x29000403 /* Select closest enemy available target */ +#define DIBUTTON_MECHA_REVERSE 0x29000404 /* Toggles throttle in/out of reverse */ +#define DIBUTTON_MECHA_ZOOM 0x29000405 /* Zoom in/out targeting reticule */ +#define DIBUTTON_MECHA_JUMP 0x29000406 /* Fires jump jets */ +#define DIBUTTON_MECHA_MENU 0x290004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_MECHA_CENTER 0x29004407 /* Center torso to legs */ +#define DIHATSWITCH_MECHA_GLANCE 0x29004601 /* Look around */ +#define DIBUTTON_MECHA_VIEW 0x29004408 /* Cycle through view options */ +#define DIBUTTON_MECHA_FIRESECONDARY 0x29004409 /* Alternative fire button */ +#define DIBUTTON_MECHA_LEFT_LINK 0x2900C4E4 /* Fallback steer left button */ +#define DIBUTTON_MECHA_RIGHT_LINK 0x2900C4EC /* Fallback steer right button */ +#define DIBUTTON_MECHA_FORWARD_LINK 0x290144E0 /* Fallback tilt torso forward button */ +#define DIBUTTON_MECHA_BACK_LINK 0x290144E8 /* Fallback tilt toroso backward button */ +#define DIBUTTON_MECHA_ROTATE_LEFT_LINK 0x290244E4 /* Fallback rotate toroso right button */ +#define DIBUTTON_MECHA_ROTATE_RIGHT_LINK 0x290244EC /* Fallback rotate torso left button */ +#define DIBUTTON_MECHA_FASTER_LINK 0x2903C4E0 /* Fallback increase engine speed */ +#define DIBUTTON_MECHA_SLOWER_LINK 0x2903C4E8 /* Fallback decrease engine speed */ +#define DIBUTTON_MECHA_DEVICE 0x290044FE /* Show input device and controls */ +#define DIBUTTON_MECHA_PAUSE 0x290044FC /* Start / Pause / Restart game */ + +/* + * "ANY" semantics can be used as a last resort to get mappings for actions + * that match nothing in the chosen virtual genre. These semantics will be + * mapped at a lower priority that virtual genre semantics. Also, hardware + * vendors will not be able to provide sensible mappings for these unless + * they provide application specific mappings. + */ +#define DIAXIS_ANY_X_1 0xFF00C201 +#define DIAXIS_ANY_X_2 0xFF00C202 +#define DIAXIS_ANY_Y_1 0xFF014201 +#define DIAXIS_ANY_Y_2 0xFF014202 +#define DIAXIS_ANY_Z_1 0xFF01C201 +#define DIAXIS_ANY_Z_2 0xFF01C202 +#define DIAXIS_ANY_R_1 0xFF024201 +#define DIAXIS_ANY_R_2 0xFF024202 +#define DIAXIS_ANY_U_1 0xFF02C201 +#define DIAXIS_ANY_U_2 0xFF02C202 +#define DIAXIS_ANY_V_1 0xFF034201 +#define DIAXIS_ANY_V_2 0xFF034202 +#define DIAXIS_ANY_A_1 0xFF03C201 +#define DIAXIS_ANY_A_2 0xFF03C202 +#define DIAXIS_ANY_B_1 0xFF044201 +#define DIAXIS_ANY_B_2 0xFF044202 +#define DIAXIS_ANY_C_1 0xFF04C201 +#define DIAXIS_ANY_C_2 0xFF04C202 +#define DIAXIS_ANY_S_1 0xFF054201 +#define DIAXIS_ANY_S_2 0xFF054202 + +#define DIAXIS_ANY_1 0xFF004201 +#define DIAXIS_ANY_2 0xFF004202 +#define DIAXIS_ANY_3 0xFF004203 +#define DIAXIS_ANY_4 0xFF004204 + +#define DIPOV_ANY_1 0xFF004601 +#define DIPOV_ANY_2 0xFF004602 +#define DIPOV_ANY_3 0xFF004603 +#define DIPOV_ANY_4 0xFF004604 + +#define DIBUTTON_ANY(instance) ( 0xFF004400 | instance ) + + +#ifdef __cplusplus +}; +#endif + +#endif /* __DINPUT_INCLUDED__ */ + +/**************************************************************************** + * + * Definitions for non-IDirectInput (VJoyD) features defined more recently + * than the current sdk files + * + ****************************************************************************/ + +#ifdef _INC_MMSYSTEM +#ifndef MMNOJOY + +#ifndef __VJOYDX_INCLUDED__ +#define __VJOYDX_INCLUDED__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Flag to indicate that the dwReserved2 field of the JOYINFOEX structure + * contains mini-driver specific data to be passed by VJoyD to the mini- + * driver instead of doing a poll. + */ +#define JOY_PASSDRIVERDATA 0x10000000l + +/* + * Informs the joystick driver that the configuration has been changed + * and should be reloaded from the registery. + * dwFlags is reserved and should be set to zero + */ +WINMMAPI MMRESULT WINAPI joyConfigChanged( DWORD dwFlags ); + + +/* + * Hardware Setting indicating that the device is a headtracker + */ +#define JOY_HWS_ISHEADTRACKER 0x02000000l + +/* + * Hardware Setting indicating that the VxD is used to replace + * the standard analog polling + */ +#define JOY_HWS_ISGAMEPORTDRIVER 0x04000000l + +/* + * Hardware Setting indicating that the driver needs a standard + * gameport in order to communicate with the device. + */ +#define JOY_HWS_ISANALOGPORTDRIVER 0x08000000l + +/* + * Hardware Setting indicating that VJoyD should not load this + * driver, it will be loaded externally and will register with + * VJoyD of it's own accord. + */ +#define JOY_HWS_AUTOLOAD 0x10000000l + +/* + * Hardware Setting indicating that the driver acquires any + * resources needed without needing a devnode through VJoyD. + */ +#define JOY_HWS_NODEVNODE 0x20000000l + + +/* + * Hardware Setting indicating that the device is a gameport bus + */ +#define JOY_HWS_ISGAMEPORTBUS 0x80000000l +#define JOY_HWS_GAMEPORTBUSBUSY 0x00000001l + +/* + * Usage Setting indicating that the settings are volatile and + * should be removed if still present on a reboot. + */ +#define JOY_US_VOLATILE 0x00000008L + +#ifdef __cplusplus +}; +#endif + +#endif /* __VJOYDX_INCLUDED__ */ + +#endif /* not MMNOJOY */ +#endif /* _INC_MMSYSTEM */ + +/**************************************************************************** + * + * Definitions for non-IDirectInput (VJoyD) features defined more recently + * than the current ddk files + * + ****************************************************************************/ + +#ifndef DIJ_RINGZERO + +#ifdef _INC_MMDDK +#ifndef MMNOJOYDEV + +#ifndef __VJOYDXD_INCLUDED__ +#define __VJOYDXD_INCLUDED__ +/* + * Poll type in which the do_other field of the JOYOEMPOLLDATA + * structure contains mini-driver specific data passed from an app. + */ +#define JOY_OEMPOLL_PASSDRIVERDATA 7 + +#endif /* __VJOYDXD_INCLUDED__ */ + +#endif /* not MMNOJOYDEV */ +#endif /* _INC_MMDDK */ + +#endif /* DIJ_RINGZERO */ + diff --git a/Source/3rd Party/directx/lib/dinput8.lib b/Source/3rd Party/directx/lib/dinput8.lib new file mode 100644 index 0000000000000000000000000000000000000000..3fad62fbd1105d36612814610cbad88e5ec5d86f GIT binary patch literal 19978 zcmeI)33yc16$kJef)V1V5nNlW!%_vSVX{HMZGf;u1B@Z4NHhaUfYFeQAwd?GQNeu~ z_YHO2cO6^XTI(`(>1uImt+i^~(b`qpPFroQwb=82%Q-hEghEpa{XXvZW#<38^X9!b zci!B4=e>d9hcD=CUUFpd*kI3677A6AS5;MoDtgw3JeF7aDOzldp})e>-rqW72Ih?^ zA`hxJX18`@4%lGKm|@1u2sPEjI$N8&YTM)8UDZ=MTNiY-hRZ{ysVTNJ-qgo~XV=uu zip*`OZkjc>uCA$J#@t!QG}TOMm_*NVYHDXjX4f|~)l8i;rM@=OFuR@}=vCL`t;94n zH?=IPsh!!;y{xs|*U=p-mvzOOPwiFVFK|rj%7q;ZI$L}@Pd8iKYU8EV22-<*E;MEx z{pANzE;6QmkTLDM8MEO4V}^|}CN#roT2o*KnnJqW*%X;UX0X}G3^08()+S$i-|e-D z=Jy)RZz8`1d~=g+yoq`?cb{+NSk;vO?)am}y(2MN+_CVK##lx5xW<-PTWn!fDcSU_ ztK3Lk#YXDNH&R#T)OklwX-iw1v!~wvRZb}1_~)al%CE=gchJao07?; zv6cm03r1D>57EJC*8AY)LK$zlO8+4&_lgf|Ic$Fj9knRCSTAa{8CtS4)zJsQDaap> z95OT3+}W|LV^LRdbp4oMUG1!6yvL0RH+L+J(`G*&xu4Uf?lZAn6l`aJ*`IFvJj}Md zO{>bRHXY!!>66~J=x(EJ+CmT5#cIMg(`aHrj5RI2OzOSA%xLvG|Txfg=Fz<{gXUylVP{QK9Ym%Yk7N+)C|> ztzl1a1k>o}q!PN_$w}5Bzgb7H_gc!s#yI=C#MrM6+bQ&GDzOYz7+$7IYEU1AHV4zt~z1AFR z!acnGEN#JrVR@^++ocp9_u=0cml)l-iFK8c;^-TWugyG6}%Ivpvi-OdCD z4J{WAmv*(T=#s@un(|s&rpoJXuz1i!qGM~OPMb8huA#1W^28C{-LaNZ8iYm!`>3Xk znYmtHIICu2F z?jYCLb9{5gylU!B=^dph!mhND*GJ;^jgiB9cBixBwEEbpSo`AO6zWT3ZLOWg>`hDh zrLVjXK6zfTvsG>EyqAT2{U_4Bo$Y1*-}9b($&0jee_q$Vb{lR+wsyhT+qItRv_HBg z9Ehmj#oukJKsQFSP_GnX*5VZ$^S05AlM~*<&NBnn@;LTv)0`IO<#$)c9@&rM!*6?t z@=#^0ugG96*isRFFpcvmC^Dss=olxVY@ipkxS+JupC~rF)!Zq+F>;tUt*|>CbO?n7 z=yrM*yTd_i78an(=~+sx&ITPuVF9`utg+zHeV&zN(Z26fHI^A*?5@XY`2uu4cx?Te z>Ce%fSI{ab&N5CK>D;Jv8%4J!kEt&cz+}x2EZHYipWL zoU|gg%rrT9o|R8pTkJmZf0^y^z|Q^Ihpjm_pnoc% zo4e3xDAaNE8XFQ$H%1RSy$||!JdFyE4W6CJvGq85X=m*49>*wT8#4skbl#|kgX9ux zEWwA(_GslpltW~DY$;PNSH^cXd-+P`D&=v?Qo(S3W^`p7M#x7?17kH!7c`e6n(ra#VSN@Q&6y;Nu z+mx3ow<~uj$CXc0?o?i;+@;*Dyj=Nog~}HxU#xtI@}q8)O69ARuU5WB8MA)-_`gp1dgU9GZ&bcX z`DW#H%C{)rs(hPrO8Iu>JCyHKzDxOT<$ILxRlZO8e&q+0A5?xw`C;Wplpj@2lb!j+ z018wdr$5_IC_kl~QGP*rU*%!SS>J^esJu#l&h|aOuKbpAPWfGB-oCd!-oEF&zx+T7 zR6d|TXZxN%QvO64^E`X`fy%snZ+*Od&wJAP-0$i`ofM?oAx;X>?H*1F(`|{9B6PdE zlcIFHo0H<45|nmz>XMvNoYI^!gWR(nMJ7wh-ENMOyWKn`ce^+4B^=K=ec#ykw+~R=P)L9RFtsX_oOl^DlZ7lDW zy}Wxo+dZVQj9=Ujb*WFfcWW?<_KRCH!zbOlHJHiy#jRQBlkVM`_Fgp@ul?dKgAot~ zdsk@CpQ~%A&NWl-lnPx(B|0ZjBD0V4(ww#!&X>5=^{cFtEA=aFtgx`)hJsVvmDzgGEZ<^T5i z7_S^`c3~i?mQB5`T?hUggofYV(=OC3$26-&O-Xdt(oSN?%kR>y=tPpYTA0$tmsv< z#;bAXM>mkv{0Nrm(KeeMjoY%>(fH~K^m_&rnH{a&-#uLMino`mRrn-fcC;3sHx%l~ zx0l(G^9#Hkvm?AK{h5vQ=ehQb$j<#)=hmDZIeio6BHnzY_w0!J$OKvx1q;y+(Gtig zcy?fb7=2QpP&^PGDBcO)NsKvIph&zkyt5dyufQNNeU&$X!D9M~YXZgMUEp2B=-&eY zG0t`bb`|5Be_%H;#>T+zVvL%B5;4Zpz#d|Zw1FXF^a+8XVvNp#J;nI;9oS2}H@vra zA9x=zW{-h=#rwhgi9Z8>M*La$vtrCP1H;7BpPIn_;?KdK6CVH{AP&Mo@o;#!cmzB` zJQ5x$9tDpQe;)q4_(1qTF-~s;4iaPb8yGDf1CJ3O3?D510{jIrM(V&J;zQv>#W>Ru zC>4)|$BIL6NbJn6%f!y?x?Eg=BjF>(N5Myl!*EzU37#aL3{MtMfv1RT;2QB%c&Zq)q`)+> zGrOKHc4pTz#Ln!xR_x5Kj}|+#>tn=qSbv>(COlI-3!WvO4bK*1z8r{%kA;sF*TeN< z%<%$q#0_wR80W|WbH$jh296US4<9c+0X{)I51uDJ5k65oAD%C6gd4>t!6%7NhEEnZ z!A;^Q92GBs7l;?a3&qWFv$zFr5x2sv;zjTx@nU$fcnQ2j9D`%xQ{Yp?r^2U-+u%0w zQh2Gj9c~wQz#ZZ^92cJkpC;~vJH^Z3W#TTlOWX~2i%`Z?*Nbm}ZxG)I-zdHbzDayDe6x5RyiR-ze2e&2_*U_4@NME0oD$y- z-!8rbzC(N`e5d#>_%89?@ZI8j;CsaP!uN{rgYOgH58p3-0DeIHApD^CA^0Kj!|=o6 zN8m@qkHU|N({Nh+82p&{i|`l4UxL3RejI*W{AKvd;;+D85q}l_s`v@`3Gvt9uZf?8 zpA>%`{<`=n_$l$z@YCXF;Ah0o!q18`a7O$M_#5Kq;OE58!_SLffL{>52)`))Cj3qD zx8QGyzYTv|{2ll^;_t%W6@L%@p7%}j_FN?EqR{R6_2jW-YSHwSr ze<*$xepUP<_($T`;Mc@IhJP%69e!Q>6Zj|MH{dtKZ^Cbi--6!~{}leI_-F9X#6O3B zF3!O@@!Rm*;&YW z_u==&zlVP>{sa66@gLzoit}(@{3rNN;y=TG7XJnQi}(Zh1M!FOhvL7&e--}?{+swC z_#^S(;lGPNhCden1OA8j6ZjMHKjD9hH^3XjpTeJtcO|>OHgHpr?4}T>FsBHoD5p55 z1g9jY6sI(&45uuo9H%@doQ&}Hk5iCSh*OwTgj1ALoKu2Rl2eLPnp1{TmQ#*Xo)b=v zc>BjG$SK4r%qhYt$|=q%!70fp#VO4x!zs%t$0^SV7udc1;}ql+;uPi-;S}W*=ak@- zV-Hic^|XhEtYPj#Hi!{_&po{&EU( z3ULZ^ig1c@igQYEN^(kZN^{C^%5uta%5%cSNpJr+1v!N{g*inyMLESeB{(HHr8uQI zWjJLy+qLcG zns}V{2iL?uL|ak8-S%=#-1#49c3cz3+tQzF(EWL?eI4A+{aNSMz9wEm?L|{Tw@`;b z!yb(!exYCZ`O%;UvP}~-_ZNWP5_l&4Ld=uf=i8SN(>|N}9TqwdbQtekKmS;HmfyuWt?N_|mj}Hb`p{lA6MEI4-$ua}3e7ya U^?Gsl{~(i}N_qYd|84%i0KK7*4gdfE literal 0 HcmV?d00001 diff --git a/Source/3rd Party/directx/lib/dxguid.lib b/Source/3rd Party/directx/lib/dxguid.lib new file mode 100644 index 0000000000000000000000000000000000000000..72553507ff6d2ca58f4645840301589a3475dea4 GIT binary patch literal 104752 zcmeFad3aMr`|w{V`yvDoWECg~2(pz;5hP901)8=bZP_Vlnzn&9DM<<~iUI{>Qs7b&73$Wn1$UJxzCxCIrk*-ncsE&{&=tJZNAs{k(vARnVBNPo1Z|q#ecTTlIa(R{3wUV=E`zrSUgUbpCY5} zY3csjDCPeT*JvR{+x>2W68c{y*xc!U8f7HeVcGVK6q~;$L-c=?8|QMSxomE?eS!^W zKUJ91Eh)~4egg5f98b2(Uw6{T|EM~_ZF2?Ovx#=w#4M-FUxzE9|55x9mnDm9_0Vv8 zhPS=?xIX5%q^P)|3M6M3WAz5_D3-I#22+$a8e{RgxTrX9mNfkJE{nID#$IlBtVB7ovc3Hv!%|isKNvnBRInW26l1pAZpEcYS=#IryED$>N!K|Y zsrEEKM3}{q5+FO?WwDO)6Vs(TT`5MkPvpi)^(mqMR09T`85v~qQOz&vlAW2Eq^W`3 z%q%AvhW?uCba*Uwhu>HP8Cu>$MO9n0)1o>M)qz}>-Rch13Zum}&gKdjwPiR{a>Jdj z%xp3>k>U*_qAHdr}rRuS$73OP2cdC~vwt;!g_C&dAVbXJy!O zaED7C?6{yLy*@E6eps9#Da;fbJ1E{{FsSl$x+qhxp1o8#hNMW7Av`iE5&kzoJ~_8} zOO^TP0KA;9=HnuxqNC!>q=YyvECrpJanfm9PDaJRx{m#sj}1|R(jFv>kqLHb29*t? zGsTvv5K_X+$E72#tQoBvl-dZ6~KQ zeH_asiy^lq&E_^|XTdVW#)V-t+FZVxoNu-|VO^w;Gsi_FkWP^n8Qv6KVR+NZ^1_=z z*B1J?L|we(YxQwDvL;~}5oVN(iH(6l;N{J_uAy8ShJ-gBZ%Qzj;|vBJ3ow(NPhR@hmSUHYqX66rZ4tjvB6wkBW_fklv6;wpwpX zwPa^_yvG5T4_%ckEfu(ceAFsOkG~*OlZ{L&$vE5SbU1O2Kgvwbi8jW0JaCaCl`bu5)J@Q3*etFjEomw= zPH8C1HOi-Xmqj|~dE?Fur;DDNb(V|_=r9(O);6dTdATEHk$ow*M3omqmh9eahlBK3 zyi*@-)~S|I)N!~y7KewdI^cvZ=ViM+&P;WVK2+~*lTw>HFO-@j&yeG>IZ|vXWH2br zC%L4ZZd-z5oWnWMK_(7ZsVN02s@_NrCAB4Gn6q7}Px z&0nUs(O%L(#t9ondT)M&F)7mGN||VZ<67ztRm_}38e&O?Q@?L0pcWNlCdZ-C5EJj) zjA&b$#hR<$Ja0>kwoGz~AkSl5ZDva*Idl9^KskC$(&C9P16CtuyJH+VjAIjG^gf$p z_5wq+i3Xo=qBA2KF0r{{;nd|uM-c13AuhYe7EK!CuqwwU7bL4oyOYeoT%kiF0(LwJ z@f~m0g%2e+C$wgBlGdP83RC6Am{F$Dmm^smWFBUYHyC{iq}eK%)NPK}#^|*sa*m9Q zH6^ghP$1TPqT7onAKr2p~w35!lSh@5eENdMrchD(cT@2 z%8LrsM|U?F5)Gy>zs1IBO&Rn<04j1iGa1go9vt=j~u~NB`>z%&`*_5M|{3+Q<#bN4MU%x+hDwoR>f?(U=wtw=oh12I2h~kv zVol2;4!?=yh950F(L%a6iFBUJlLRgE zW^+4)jA@$_E)w}cuL^i)prNWEFiiF5;p#uf*>h|eWR#Id5M-}M!POX9c@7P;xakdV zmL**fs2F)MsLCMs>Rt96vK25_dOi8Rxi=ZdrOiGWb z-usYph(2mjNSY)g2ZckqG`S6p;^gK7N<)9p+xC1&mz^9aq}*;sMah|bgXCPkS#mDl zI60SZhatyiB{O*#+D&xxBel`8#BEj-x#-A|4Zb+~JO?%1XdLRd808@iSGtnTZ>y5e zZ*2_R-Jy@HP`##zF#q}FG9QCRzAlrIuZ5g;*b_I-_C|b*@rJZ67u*R9WJ*u!{v+sH zvi!Wm`xK9J18lgQ?OT|f@4L-%zW=t%PXoDnA=9^b$PG}4{Oph~1#vwj`Y%lxfj+xY3HUZyJtfhj%4CF0@AE~jQL32#(x~X$4f4$zpSH=_ zzGcbz{x>v^tXpj<-Tx~XAjUuV10}8&K1LslYu_#xV^5oN} z=ahhNHA=*PCj_hqp11o~hS(hej#&ADD{eAb;rXX+sR8oc&TMkeiJz?Ly4ELqq9se0 zP9D?o0sp%rz|NrAK4mzfBQ5^t>qK(-q?}i{ouLl#=QVYVuT9xed~x(SIKO8VoF6~( zlG~?n>8_05?UbKdtM(dX;MyRk2Wl7O;EjVEd7gLqkmOR|dlS(SUE4(LjuCqEGeS6=2{<3_S70 zr)ufVfbLr4$azD2^LqQ?di&w}_~H8a;rw9oQSPrnG~%ZiIpVKzG!oG9*HGE<*IYRg zu+e^M!B+&*SyJj;IbXgc^6h4Fe?@tbLN&%E(Hp`?tQ3oj(g!LLH%+?lg{qZu@W7R_ za4quvGUZ(l-vZ=&OsXbJf}i!bl+SKG@rL?VpKnZg1H(7s@4`o_iru2%B_(1@i6T!h zT;x_Xyg$HG5jKzVs)kQUezk+o{;$#k6(#5U>2g2IA8E758#k(VEchnCZ58h;7XK0S zv)fgwpXSKVWPM5`7vV~8`u3pmMh9fsBq*F97X2385cOK*HgdBcLw_xB!%KgRnS2p^Q+0^xI&cQ&|u`VNS{T;EQV zVD790n344y)Na1>ix{bG!ktmH*BSM z*Z6YqkdyF0#rV5zA_?S{vwTyLFPsJf6^O!q8bagYL$x;YR$_p{!-vK=?QR>qmm$BG z#BT*G*OWuhmkKBnsRAwK43u}I&CRgqFonB8H4*ChCSy~ShkpKG#_ z*DJ{LTRcrmg&7>#nSM@qQY=uunLI5VZj`qTx(p}WpB-e@ zYvZ-jQ<(T9b3&N(&XhiiJbH;I57VQ_6JWmt+}ICFiih`C;C*)QT`_-o(jzcmlw6$1 z&lr3|Qgc~$R+ikS-kdOU60upxLkvErJGqnY&C`*)NG`G~SO#2Sk(-EqvdHYD!pI$Y zH!2EV%y2p2VUqlcy_XFq4?sO+1Icm3^5k1!I8EM@w9Cf~&Nq?wt^DPa*Ag9WSjmuE zQRHqqUwk5Y55{Wukm2VoPJYeGo0RV9l2=J!n^lzjC_+VLkcT^5_tN`lUP!)!Mpj*p zY`(2hD2@a&lTlYo`6f8zRdq|52^^{1YEyAamNt{TAnEY%o8S%0cVNBERPy!q)Kv0R zD3E5zv`a7Y2a3lzC&E1CQ>;0Q+*r@BkoSymk1Ey5H+Iw-*>62^$by39N#72jq!un%7S^X8Jb4#dH> zpz>O~>XSj$63gdvLT{}6`@sMHI#GUl=hJ_xXLNpg9-{cUqfY@or%fM1c~IsPpr=GX z_0q`ys9OCX%%^bW`G=pZB>8

1H#%ORjXM>PAVol-t_!?omnd ztz*C0fj&!O_m6!vCG?+az@X~ocHffAzYp|C_nzS$$v{0Q-Ho6Z;DH(Sy=$L-R^5U2 zGoF;Y$v#^7_knh+^uoQrPAmUDP(5Cxo7Bp!VLl+;r^S5;Ji1TIJLpEO-(dOof#hQ^ zdiSpI#W^s;*S_krc#2TEUW zmVY0p`gE}T`@r(=1HB)amwz9~z8>U17&4ZBA6Wi?ppt^6vx5-&%?~1-`^9|2`1D>hbf+xAd@|`|v@|!{3xi zdHz1ZEB`()+atd$;itpOzYnxq{e1mV{(T_#eTdW{<=+RYUKpa^`r!qN)J^5z2hzXy z4W1pN6CGsW4wG_xzemFt`v8UdLgn8Fs`^=aVT3zPLcdA*zTGKj`}V1n@0*R@J5jBz zp$7EYiN9F+_krc#2bO;ySpIz={Xmg^F^E3uEB`()r~Las_WhXhd0qMUf$+h@|5M)w za{nOd|N8exyDR@NY0EJ+oXKNH+C%&F8kv%lM*ew(&Lkbw#T%FZ0aI^z@<)aAUo~yn zlH~X5)vIO8-aUHv>OsFZjIPkRVyjA@^evhc6g0OA`S_6hI+K4}#Ofjcss;UZCjZqB zQBw53HR=-1mYki|#;imZl0UdOZa`4ou+FX&_(t9Pt4sbAJk*<%{xG0!*8%>x`hr}D zAQvjg=>$2mAZHci+=5)5AeS%56$o;Lf?SaxS0c!j3UXzFT<|c#@h8ZI2y&r` zo*AXg&Dl?rlYf?V(j!SN@^g$Qz?f}Bo}GYfK7LC!76 zj}{z%f?S9o7b?i<1Ua)HXBFh!f?S>;moLZ_2y%sjT#+DGBFL2ra%F;CaFXEo6XZe! zxlln)C&-xvIjbP&7Uc2-xqLycK#(gGt03nVBS0u=l2y&%@T$vyjoPl;n;Ok#OE<}(E736e+oLP{w z3UY2iE>Dol7vu^Axk5p%NRTTLI|av|AQvLYg$i;yLC!45Sp_+_AeSe|S0u=l2y&%@ zT$vyjoFzE^1i27FE>w`y336sZ&ML^c1-U#yE?_t03nV z9t03nVVcd@Pu|xN_E*rW@cx2?3uO{yJcjG9sVNT9P)Slx>LrDbi1td zZ~YzV=WhY-6I8!$1yXjEpxUJ9^C9rR7eiVZ?N*o5?M(HwY;Wq&lKcZq_DuUEyCbco z&Y78I&mjK-O3;Bnr!|@T(rL{Ho}e++LK_|#)9#t(L++f^Y&hHgQl%q7K{LYdw|`jW zv}X6Dpfz8#?zZ%Pw+Wwr95OR%R&M;6n&*&QQ#D?oNHb%bn{DDe`u1<8#(&v0ypq;PX@?>FL{{FCUdTUpv zb^bI$yL->7#J9g{8$Ivvt;YHqV`J7f95(!wGvCcCUOcPBbojL9^)6(4^4~jn^~r{ zwKw8e##0?Gm1tHJ2Tl3x$r_$;E^Xk_VO(0vrMoZw=$S``lE{MWHm+l(w`RI$zWVE) zBGMl<<@Sw8to~28US#_|l-s|XYwvqpdKZ@t3+}Y~lVi|cy}=wG6r|~m}OrvqHU6PJ3xqmls{(3IG zmP@bZ((iETNspe5XxhF+Gj+1u-w$5>t9_p(WdCfI)2leXWADh45sP;iHncX>sW)Q! zhLv1=1($xCOCKBYVCtwCvOhnQ_vdmhp3kM%tgQKSi%sl!*zn7l9j*)gA`7Octa`NX z$kh1psdK*i>$GP3oS-qgh73P2g`1D+$JLzr#%q=_ZDkreoVIa z(ENLgxcCAtJ)cX@;nLH&bRL(U#-*on=}Nk^Co1=a?fvW4FKeFc70jjgbNpIvzOkf~ z{Jh~E)?cY%>APNgpX|@S|gY49c5R+w%FWo-_Wgrk&Z7#Lvn6TU>jVa_Plf+QrR3Z*uWBxb!?OJ(o+*;?l2k z>6u)52A6KTZmtEt|x36;jJDE$r!lhs4(v!IKEpzdSD&+jM?=QK3zc~L} zwWGaRI)~$jYkJw9d-=3x|5Gx5YR}Q3x5A4xv*G+vS=(XP?{y+~w=dRw{6Ie5>#iPW zom{I}vt)Nr%bk}!t=4%KOwFiJqS?_PXw0%*4KxK@Iy~_mDFSoDTc;DUQZ}*-P z`MT}?iw}E!H(*M?rH6(cJEfV^k?fDQ!;hp_{P*>Qx5wy~YzZ3JeAV|E<43=B@3S-C zgzYyzSG9lVrN7VqsaCz;`?|GjyT7=n%E|8Ca-XhnFK9sKfY)~(`sbyhRYMj;Ywk5a z9uv9rM)i|B7e3pnQ-1$@HNP1gJMZL6Z~eM^)u=`NzPxw-iYxrxU{A~0gSNl5GWq7c z2UDkp9bEXu*-D#-|510^!;6|B3kR((eK2Cu_qm6{LbXSmHao3Ze4mVuqjSC-z@=Z} z(vzaU`f2OMhGFYFXT%N5yxd&dqT5e9{>j!ZZF{_0{2%#W_G{qT-fzJN1E-|6FR=z^ z+FqD9BmC3arG^j2eDm|K8HH`fj%_$7wRV|qO6kwZQ@*>l{?X2RFYls{cFvYhHQt^xR8vi(=Lt)W^>% z{wXZyt^NxZb#e_@(dmcu`_HH4m4;QDmDJ#-ZgY=~PgS{5Il@%d@NDa|Cp24*k?~%0 zc|q50_qvT7d`h!<3t2B)KF-gp+G^MF*{3u+tHJ&`-thO@%Y#0u?TXCnpV_tllpTAg zaq+2KdgkA6x0@PuLbIV2lz(H)bS{0vsM(Ty)UI9odC1wfzIMMKwZ3h7o9t=EMRnpz z#};mFF@xjtU#)R$Nm-A`cm8;7^Qs%wQ}ej^vh+=f-_$sv+4Ta{w=pX?=$G#@SN;^S z+`+IJg>iTfaitr2HMBGk3smVVeuh-VR{OIl*$)`0t>d5oSm{EN_ z>U3PMftl*`g0OtEI(_0|#lcP6kojn%?4RV)$GLRV(bFz=O+Tm08&z}o`3{NejFHav zqk9k4uXDZE=lefvjQzCvOP>A1SBK5La?BXqw%^eOch=n4-m#|c^^0r6PG)~MG$=GD z&pKdE^s2&Xc{N_U+bv|t!2B-@jt$zr=In)0%NDl^I`PYIJFlM9tc-#AG;FliV7k8H z&0@`*rE>e$bnkxi(5h3Kl}F_G8smmf)cn;&4=X%gN8+(^Jm~1=SR%FaDagA3U9wLH4Gf;ycw_S0w53Qua*w1MMo$hPq#!*|YFLeeee^qM>I@wQ7R zG>e*%bVihG%*G$|>0hz_9+Td@&V^YleRcGmUK3}W)GVzjpr!;#X5x>rmi_SZ}jBQI#Xbv5z7S!=t@KYIFdK{Pjdvfi& z3mUhJ-E;P*-+umNee?^*K> zVcR#2OHbv}Q@C^%m$q=}F3tj{+&yI z&!w+%>8o7&@Pli&PS0ZdcWT{l;-9=68o9oyXTG~&YVH&+eelzBLlQ$uG;gjV<0oCe z;{cb=yQv@6S+)Jsxb##mJ%vkmo05Czg~)ZrEz3ux{M2h%P**NJV{i1^nX3Ayb7?Cn zZ_XChzsX$MQr|RN9UsG`Z&bh8cGzy_U+2=-xb#&nt=l@S-$io1+WI^>e~!N%8qTE+ zTw2eic|VMcYq|6QF0K2qp`qpcQ<@dzQ>w!`O^eoy9`)J_XNon`4wK{A?izosRh`$a z9b)OLTzbt|&0G5qviO)H>zv8UPiYo63!3tIt-oJh`*X+(?=3#%-M%$^dhX^;H;$du z?9Zfw#ej7tyT(o;;H8?mJS6@Dr6kXnQsaj z5ZZHb!BH-Kgi9ah(o^26@_XNxnQz@OBl30*OCLVg;-^iA+4iq_ce1(nmn=Po<6C{$ zwPBdbZ^@;+>klK>o+K_k znoIM?U(om^9p8S39lwV&Djaj4KB3tbNsgyJZP#kK<13F#f6k>X`JZ%bmv>ULZJ_Lj z-s%ybnpv#*s3uu2WX~M_GRNm~=_BL1w2A7&j_0;9duC2sDfw%@n7ZcODa(59EEvbi zzuK?iFkPl9{pGJ`&J8No?1SeM{S9S}zG`@PylQ(Ia_I(Kx;~e#$E7t~x-OSK%C$fD zwQ-N1SYNDJDBXW}GxZ6MpUA~)bMb60UXzR0;L>i6KisuWy$%i8@mrnat8wY6-2SM_ z#iw!ciCns3?M(&s9BhA7;L?@2^0K)0jyZUxXx8(mH18ZG&n>k&DlbS{;8^70=pK zewRxZaOrhidM%e;kysG>5;?yr$J5(fdO4SVi%T!#(o4DY5-z=%OXqXxMO=CzmtMf7 z=X2>dx%8`JJLkXo>9>ZBhs?z*XI^^xn}bc;U)fPLYG&N6l~=wQYuTN{%_aOVfN{3DQJ{zXBE_-Ldx;x7|YbsS)_5H!V2PTu}9s4@K zdhK$^rY3JaS-DAR5HqVwm;3v#w)*z%mFZ9P ztGq_PYSE=9`eoOd`PmOY&-ttJH~RM%2Gy+n>sL$u-ZE!Uod)~E7Iqu<>dq~lx2NyB z(f`Y5dqmHD|J7Rk8h;R%edhS})bG-M2)N{;4YWPeRYQNqGZ{H5)FGba2|AmcCneoeM42Y@Q0&v+sF=o@}50=e$#z z*;`4R+}{j8(n!BO^rU7g`84xz%O@QMF8zD>$}f+R=anA}C-bYRuwF3d>p4D*OIPIh zs~0YJTGRHVrl1K~FYOCW%;nlYhHGyH&JUVZH)Zk?*8UvMZ+#{0^{@An`?q$vKXj@2 zad+yIG+f`4?Ohwycvjh2=3ni1bNZHWw*6y9rmlBC!`jz!T(#d;tJ*t}t8YN})*p4e zMec{~A=`6!dH*9Vc8q;C^^|7TDw6)_gRxVB_V;bohLtzw*G{39izhWJs=)p!_;Aby zQ+;)M%`*l6j#0(0PF#5vr7KQaqfWQ%p0h}up0d0wUY%b2Pr|#iD-Ve&3{9LgJAB@( ztNEFQx{fC`>%Nowe@wdu8KE25{kN_=YtHJr>y+kAxPP?lhY>+t#tj(WzgV+(0O8mE zHTJt7?>J{)Db}poMaDzB@%smKtoPoAQN^11C&~Cax*}%H<4T>czg4W6cTMj9y_P?h ztsO(saJ@~A-|uhl`ej)XOIK>2yK0jv?V3LF>NkT){DjP}Y}o$K+nY{n*8WD)c|ZJ- zT4_#S`)|dXSv5(07rGvs^484!lf8;HE1E)of4F1H)7K~Gllw`^_#TkG5qw`*SZTkL=HD(>K)Io5l8LQLVH0 zZbh;5Q7(OiOCRRa{hJ-JkK0qM**;0`ud7e29`tH$)}9%c@cx+2rC*JB@o-~uKWUyx z-u@O(Hy+$EmZXd1{`&W|TJ8ulNgL&O_yOJ3Mym9zPj=7#oy-sOqUHF4h|BwaRi&4{ zxwYw|m8H=KT<7lGdAn8il;LSrR`ey$PssZcFdn+j>{zqsb}~NRrQ;)}(#75OQ<}AK z{qy0Kk7f*=GUP{czFn-{6cT*oiFQ-D_8%U7^U0N}^4^Xcw({Wfq&)-W_FOG{7md#; zoWG_~pJ9cQ+4x;Lxa*6T;z~3tA5s5_56%tHoz(2IlIzo>$9r~8CGW9FuhRqtJ$f7z zlvbg$@~>lCv*_o*1FYnAm(KQ-iy_T}9up=Q{Ug^Eh#g#^GcAMtNBs|6!)rUi6&A7} z{ge71tqzu$x-_!LT8lIbJor_T|3hkqJhcUp;0lU$y77Y_nDq>`fWcN}WVOHei2TEg zN?lrN0fVh7$huIpx{z6esRazSsv;}zCrdc9l)rBW7;IHT*3a+XTE?ttBnCfVumvwh zvEJCb;hSP+tpbJofWcM`lEbY1=B0_udLI<>0|r~<0!C%+9kQrQ7&e$E+GK0Lc#+Y&}78m=zt~WB{|;PzxAr)j?Kw{dps^ z!l(rdwqOLZx?X73lMFg#M2(;pFxb){Yo{l?HM6p*1q`<8A?vQ~J+cu>UHQ}k23z%! z_4#}K$UiovSevN@47M5|Ygo&KUzt@zEnu+qB(kg@7;H60R*UDqQypL7)B*-uO^|iH z=9^nt3zMh?47QpgYi`A&d}d9g7BJXqhOBzwU3W2S5w(E9R&!*X3b&F?r*O~~`UhaJ z)dE@Cb2axe>j1TY!Pe8rDzp}@X4WZc0fViU$oh1}3(3s7PAy=t)e2cXy8JeXS^rQA z7;Lph)}5_0Lzq>Ej7j(bgDnE7MpT<84$op%2(^I0RvTo!@O(}eX7!^MFxYB~tc7J0 zRWo)xwSd7EoDbO?WsNxW8mo&u=#_rJV5=Rnemi?kHRfNZ7BJXqkF19+(mJrZR#6KW zY!OJ+!a7@aN(A{I^80{Vz+mfHlEb#^aIc@^SY5@`0tQ7^YYD6tyu+>WqWmYF@0fQ|vfK+vb zuD*MSS^cR647R!=Yuyuh_bkIb@B3m9y5M^=|6UyyEA>Y79? zV6YX6tm2}Mnao;9Enu+K16c!1x*}$6q!uvP>WQq~H|PGqtRiXwgRNf3I-hsDIsJ4gS=C_aN`Am#>v@vH#$n?8Ci|Gxh+4p4>jh-> z+_Jwvv)WM$7;N=L*80Au7ceV~TEJlIMP$W~x=W5kWo!(i7BJZAhpbAGf2d|QJGFqp z7TF9{Z5 z^#Qej!B!Zu-v6>)B*-u24rnK zus)Yr)vJ&o`2mBiaFWAD@7a6nPBN=GwSd7^1hUrua!EBdx>5@mY>_Tg)fMsTmljr+ zky^lDD+*cNXNIn1RywtS!PY=z6*L+_CO>7&Po)+x*dj|ARSW0Gu28Mn3aAAPwxW?W zxFDY_A(gt0QVSStks+?CYjWe3_n7r9wSd7^46+hz=Q=U#0kwd^RxGkE4Kx16tj6TL z2|r-4MNavu79MTgtQNDnQVSSt4MtXt%M(6fRs^+x!IlYG?!ghanPsIGFxWC9>+b{& znf#QVe}!7WU@IP3!LLN@V%7?30fVgsWc@fRl1vgxUAw6T47SK3Qq_m^x8MGhSzl2L z7;FteR>$Al?qJqUY5{|-p~&jj;gxTgRiPRQk{>YG8b)&146yXdqu-g;m|DPKYdEq> z+f`Mam%C957;KF|mTRwbBdaTpTEJjyB(kPd-1sK5#!?FyY>h(J?bLd|Fl!dIfWg*i zWUYGVZf$0*p%yUMNOl55{D8q$3dvz3YWImzs+FFRTEJk- zhO8$tc9Ijm(!z1n0tQ>D$a;HZ>PO64NG)Knm4>Y18m86E+DR>7u$7Li!`=URpIOJL z1q`6 z+vKwj$s|7mwSd7^CdpxSMHbKK!0Jk-7BJXyAnU?_pI&FyYt#Y;TTWzc`>??zX1zl# zV6c^itkJbDlT(2*qCTP)FxVQ8tdw!RzGc=$Y5{{S7qagEJ=)Ez2h;)vTLe<|Vbz$W zWXe=pSg$4tk{>YG@{kil!DY*m@0FTdKA?$E-|h0fVh6$m*Xphitmi!r9aU23u2+^~*cE z|6tk!7iKaR{^SPzxAr%|KTE zNA*ZIE4@*ftRmnC47O&H9JZG$K0E0YvszIL7;KSAQ)MNcBTrVnb@ihbFxZ-fto}DT z&tp~`wSd9aY-A1TdzN&VvRzhc0fVhM$l5T!#TI7GrWP>Rnv1L+EhbcA)&^<;gDtWd zs@~AvoUa;DN2mo1w%$P2sfo8#d-)QzfWa17daCNOe}DD_YvEti0tQ?2k<~ji^Z~Q# zJVAow2Mo3rkQ_EP3QZBJvC)=Vz+h`3vaSqW^#!Y|AGLtN)*@uRzIxDOX2ntq7;NPu z>-eT()eMkEEnu*<7+JFx-Bn$2Os5tw*dog&Rd38oAb*`jOY5{|-rO0aj$vrZ) zDApco0fVh&$f~=~M3#_>b)H(lVCyYpEuHh`C1(9WEnu*<99g%P=k8)w(>f$be!yVs zZIZ*rM!Tm>KQpT%wSd9a3S^C+H86`=T517WzPsdy!37_SY0@0fVhI$Xb1-;uU5sq!uvPT8pe& z6V694Yb&*Y!PYut_4};GU1ohoEnu)!fUGsUOH?yJDYbyX)_P>c|J(d&R@WnH0fVg# z$a<~ccycMD^kLJwBuIY1VC!9y!^YtkXS+6MRv&5sgRPCosy3)fB(q|u1q`+}A!|g9 z4{9=N47Gs4)@EeA)XM%7v$ClL47SMWO0`{<=YJp0ta;P|23usXs;q>$EvGSSHMM}j z);476R_=O{S?^N|7;J4vR^5V*Hf9~C7BJY_fvlYqnyBWepQr^4wss=3&8*$j0tQ=qk=5eaS*mm8r_=%l zTOS~+-=j+8z*Uar3)BJzTOT58N904Ya}?`$Y5{|-eaLDsFRlZ#>eeGc@&g82`$-NP z8=2J_A7oY^Y5{|-kC1hA;%wDCpGYlWuyp`gclP#nu)4CT1q`-GgH$a%k#K-av`TL* zrWP>R`WRUWGb*%X)=p{xgRMiz%CmGcFzYzAfWg*bWNlr&p$W6@QVSSt9YNOqb#+%U zE4V%hk{>YGI!bcb{wnL(^>b#mpcXLLDneHJFz2_->O(DHu=NSDK5sln)$=B50fVh$ z$kJ#wszz@rwSd9ar^u>W`o&n*!dIyU47NT))|4qHTQKV#Y5{{S(q*bXboHp(n^^~` z1q`;x@?B-!oxj=1th3Yt23ubuYu1+Px0&?|wSd9aSIGLN|3WLXYBeB1@&g82Uy~d* zHliEWY{#q?)B*-u$C1^zulgO%-qZpHTPKh;Z`TVpR#z;wfWg*DWIZ(f@+7m8sRazS zP9dvIH-t1tnE^c10tQ>f$ZBx=-fU*grWP>RI*qIuxv#7G@Lg&FgRK%|O*{@)YDx<~ zp%yUM`UY7yN48tTtjp8_23u#4)u{QQADMNZTEJlIEV3q6uQ`HQ^~hd;A28TDM{?MR zD&62D7eLB(Jx48IutgRMD$8^FL)GYwpcXLLx`3>{XXkWhb&a4FFxa|?tVUl9Rjsid z)B*-uWU-}cVcAm)cC)&sQVSStT}D=|0lQW(YYDZ0!4{cnRdr>4w{8)$Hc<;0Y<-8U z%AdBF%B+3V0tQ=GkhOTogf7e~rWP>Rx{9m^uCtq%b&FcSVCx#Ps%Rw{D8q$Dam2uu+_Xc)#&X)Enu*99a%5$oI_5h%IJ-x7BJYlfvm*& z9cM7hN-bcpbrV?+-*}wItXHT747P3|D|pMs7nrq_TEJk7oI+H+k??Guomm^G1q``+O;mkTgEnu)kCNkA_J$1`efmxTS z1q`-+LRQ5Esa2VEhg!g3>t|%GdiSS4nDu~Kz+mehvf6x|zLZ&&8j&FR0fVhyNDdpl zO)GT`VOC>m0fVhyk@ahZN!6Lvm0G}H>o;UQ*|btGW@)Jf47SRUwYKtegj9}{;nV^K zTfZYK`qwLDX{=Z-Y5{|-`^Z`vvV|0^ShJ}G47SMbQT5@y=|@&GYZJAA!PWz09jmM* z%~9$)L@i*j^(V687k3!WtaH=?23vn2OA}mi2eW>r7BJZQ8(HQiUq8jHD&)`b0|s0F zkQ_Fmsy}gRRHNiikL`I#R|_3m9w#k$Hmk#-8NM^;uo7PzxArRY2A|+k3vmta;P|23r-e zW%{Tsv)-l_FxU!4)<@s1I?AkV)B*-um5}vp?EMU89ikR6*s6>y;|^PYW))Kl7;IHR z*5#LKFJRVnY5{|-s>u3y*Q>8F>kn!HgRN@V>hQX1FIR6&b}#t>gRSbws#Ja7C{|Zf zY5{{S_=1X!jUg{yC8s!L%s)#lV6asaSsP}xKg_JY)B*-uwUBixtGFMtqNxQ8wrV5m zwWznoGiwaBfWg)i$ZG7ck;6jSu2-l947TbZYl*#3bxv7EEnu)!7g^d-=5JYDyQu{X zwlv5po%&f3vrbV97;M!;maFd0OlEygEnu)!A6Zk@r|FsXE46^ZRs&>dde$Ke8Kn;& zQwtbuJ&CN2rW+~Ds?|gqyg|TVt0A)X7rpT%vl>$i7;H5{R^&uODYH6J3m9xYg{%uV zpEEM6AGLtNR%2vsYw^u4W<^sA7;H5`R=@cNS}*>v`6lwv3t!Bs? zy`|Z5W_hRu47QphYt!}_Nz9r>Enu+K0$I<$_!C)bDPv<5wSd9a)5!X2R@?K;dXHMb zV5=pvhBr1&U{(>efWcNPWPK2EmMof-7Jfr5V6fF1Ss&hBevnzE)B*-uA;{{G`>W~< zd!JgsU<)at~`^8nuAI)^o^;jlR8#S#D|pgRRcU z`tI8)q0D-XTEJkd3$n&jh+;b7ZQ{=F6!C47U0rEBtX~)!BSIwSd9ai^y8EF|mxb@Cdbl!B#(H z1^4Pdidko<1q`z+fv3S^JGm4l}DCwSd8v4p|*9yBy3)q!uvP(j%+;lM7T=H+E_P zgDnHH+I;?n>dNbgoTV6Zh1S%bTF{gYY$QVSSt4MNu8wL=q`^%PlQ!Veg1MI-B%qh}^E z>se|6gDoSn+FgiM&Di~^1q`-gkX8S|!AGpFcxnNItypADOFa|Etg+Mr23v8+I`;PW z5+V0O9<_kM)?j3%j=!T?v#q2SFxWC7Yu@l#s&mR-Y5{{SGqRe0byamv`Gi`)U@IP3 zU0+Ly0z&>>pcXLLNzVIZo-lG;U*h)gy zp|wp^tIDsb1q`;vAggBm$AnaR{sy&x!IlMCL*Hnh&#b?w1q`;5k#)Ax>#ApMnwIi7 z1O{7HWc{_VcP~~~2(^I0RtmDVb*M+?TV=ampcXLLvLUPAhm#7Kl|U_Eu$79e$|G#5 z{gpv2V6c^jtOxhDtH$B$)B*-u>Bvfb^_XfLuB8?**s>!l@651ofslW@s09qR#v;r3 zSB>|XRYWadur&@@X04|dFxYwxS$IAFKDB_s))ZtViUUVz+fv6S&uFxs@7~l!p6L zx|o$kEnu)U8(CRdYgA7I7f=frY|TN|l{n)zR@ZiF0fVi%$oh731J&p~MlE2lH4j^Rco7QY5{|-g~&R&NBuWxq)`hPY%N08=(b%{Z_eaV3m9zWBWv5jTTUS4 z-#gR-23w1f)h}rN5oR5r7BJXaf~;wuq#KxZo?5_QYbmn&Hu zt2$TKYb$RbFxYwvSqpxQ?855mLM>phwH#T0zw&)&W(}kkFxYw4z+h`NvL<&eQLR$GqZTmOT7#?~*M6j0Z~Q?mV6e3oS*!m2V;T_huhuj2e}Tc) zI%J*wbnr!HwWby@*eXDlGqS(xK0t430fVje$Xfi>za~~!Jhgzq)&^w7p6Z{)tnt(W z23zkU>tMydO{=Y8bv0@yk0@ZUwH;Y| zw>wpL54utd7;No8){borFSEKLsRazSb|ULhY~c-NjiDAW*xH4x4p-Y%W7b4!0fVjg zkX6us6Csu3Yd*Dr!PahMS^J#3#H@Fz1q`+dkyUX*^U=)ulv==GYY(#eW&cR_tkS~U z)B*-u?<1>fy(+31`-%4QUIqqRdy%y?&ryZd)stGlVCw^9O&Q($6=n^i7BJZQ5Lud& zNvh-P6>0&4t$oNUeR-K`o?k;PV6e3xS^Fks?qV(cj9S28>my{fzgt;#uktFjfWg)Q zWL-=;u6pa^A+>ZrNMiDVAgGF0fVhik+r7U%hQ+@^sKz!fWg*h z$m+JdzUr=iQ)&T&t>8!&`5x2)23ubs>*MM#w`46ePzxAreTl5vx7PP$RwA{4 z!PZyEYWriaGt3%GEnu+qHL~vOKWxgZDbxZ6TgQ=A{mYVr%*v-0FxWbQtj{w#)MeIs zY5{|-lgL^Tlm9NW_D~BLY@I?@wK1Ix%qpT5FxVa@;$QePI0nSnj7;K$J)}iYO z2bgt_TEJkd1X*c2JN0E&<&N^`1qNH+AglA4lSXDWqZTmOI)kitQVg@1)tg$tVCyWh zVq*5Zz$`PhfWg)|WbJ9EX~?WBY5{|-^T=v^efTfTnoBKUuyp}h`!6p2kXh@f1q`+> zB5VCwc;iUf%Ll0i47M&ID|0}+>i9ZCEnu*98CmTY{C1etb(dPeVC!3C?W#ZJDQ5jc zEnu+q9kSe=j@X&ih|F^E0|r}HkacEOS!-r>rxq~Sx{9ok#wW=2xYCCMsRazSt|9Ba zY0r&iRx-7K!PfW4()GHbV^%J;fWcNNvN}GRr@D4nLM>phbsbqd{`#~wt7|*8fWg)c zWS!pl#!t*TMlE2lbrV^=PBi!tJ^1sMsGay2TGS?8$*47Pql*0dXwRA-`Js09qR%8>Ql#y@gcUDe2aF!%w3 zt>2Nga&zd9%xXm~V6b%`S*gp$s;=m}Q41Js{ei4SV>d5kb!n*u47MI1>q=t7HOv}J zEnu+qC$h%G987*vidWzipm41Z5Rt025_1*C{v$|6Y7;IHUR@H~M z)-%gUEnu(}jI1+RA6;VBXlen2txCv>9uoh6S+7tF7;IHWmcHoRS!TUSEnu)!1zFv0 zW~MT06SaWBR#jvjYW2raW*w&%FxaYwtcfGu*vPCOs09qRsw1oAbFEctfZ(q3P6h^B zHIP;K_Lj}8uIAJN23zoNE3pyv;)<)^GOIVWfWcNRWS#!-WJ_iZq!uvPs*S9*&wV?B zS;^D_23t=c%j2oEgjo})1q`<8AZyaxJ`I>Pk6OTBt1hxWjBGrMS*xf847N1LIvrBy zDzgfy1q`<8A#3pX*pgqu)V6fE*S+fr|s?RI~wSd9abI5Yve=eC>qp1Z9wmKuLeV3%s%oaO zX9i8{?Jk?uW6XBjt=jAqyED$>N%swzosKl$Tqwz6ci3FMA+yzG&+_=@lj1!#mm}U~ zv5xbNnmxH0wmyFHZE2Y{hsW%(c>W{oM~t(%Qk||$i^J;Ai*{O4Y%V{VS+1|UZ%b4K z`iX{F94Wqzj{MWQPPe~a(xp3HDMm|{uOsz@Z+3*slI3Ujs9NRg(2bEgFJRO+5Su)f z3=H4=2%AUlH{XzwACW*tT3B{!s?C*TbUK_tN$Q+XeUjdli}TE6P}n%m;Fw^tO|ZF= zF^clcxeiZylHQhT$<82cm8zks2&2xKkwG@W?sU)ybdxsQ(nUS4o^U034k)2C(6QokZUCvC^p(MA7))?>PBZ(H5-2!cN z(?WC^Hj67sn~{-Zv}HI`a>HE~Y49s?oJ%FM&6eU*lEGm~&akN)sJFZMEDG5(ZDu<; z#O2mf3}uq><4CcP;Y#L`aQFwMWtKG;2EWosT2T`8b`sa!a*cjNWI}O}Jr?iON1J{2 zp4_`i6Y(xIW_xUL7MCTHhND!|8av3OjZ=r@<5kLrKdMWJ%dq4o87;1HaNJ5nq9wzg zl0>?}OyxC+Xl1fwO(X5!*_^9wGoi;uyHYSOjCSr|ov1Wt6APE_@F?zqD$XJu#fYG2e zCzuRG3o~fr{i$&VlXSL<(fO^^Y=|%#ViZ%g)5!Rb&&{%t@uZ73li5TaQchE3w4}nA z^&#Z5l{(w(%yy&E!6qE*7pdg)X0)}DS1`5(SGEmr@>o(*B4BEyA3Q2P@4N5bjo~(+K z;!Lq|N$B*=vZHNj7Hh7~lI1;fc?|{PHOdWI+CHIr`<|c+ipBUyb-g_MJ{IiTS|BF8>=ePZ%8TAZ%`>z zo(Rpl@S#cOVdi*)F)7BZ9Dh=-(ah)QqP1q9Oe$*)w;&ED&)@T^)*M)Vh$zV3en*4_KQRetq6Rd&#hRNuN z^&1F}*2Y8_{Fg}_Qv&Nq^_E0vO%c&BfXtzKZFEFZq$xf;DLN`5k}PylUU))uG|P&K zO-hV1#V2T^qlQZhb~IR|C2V+hMut9{oDOn)V`OTDD~|A?F;2VNX3oyaa@pME^raf6 zQW;)OYqR=B!-t~t8!v|sm3I@pF!v2hYc0cge+9!L7nKON!UUMaAJPv%wUlCC4tUN5YJ;dILEvsI#KthN4{z8`ejewN*n( z%8#>g16j&drg8Nap<;XjaydTPNYjBJ zneRPzi?Tc+*MczQCDNSbvcqE;IboUTaXLNeaM{3RC6MO}5<_lZkh7)t>Wf_PDV3VX zXS2&I6RAYqBGL_&_4b)*k~YV#3=vbVI+3GF3|IYmnCj0% zCURw&qkw9j$%SSQ6H2_~u0!Na24qSCQ zOQy}YFjYC^(Oag?L>3V8eC%zEl%GhR&ROjqG74}$x!G#xc&)>pDU}hM1raj+con!2 zni5VPMtaEXr4EFVyXQ8Gqq}-1L63%8thOQKDXi5Ya$FVn0 zX>*)&A{=u*`G!opG_Lq2DxNvZW+e{-T!G?xdul2y31G|p6tB%phI>|g*x$bK?oa8A z<87!nTe^_+&Bm3w>^VJh$STOo>73+-x!Y%l$H4mw8R}gH!+`D=*-;e&F{MM`a#0nM zMlHEH?r_5^5d$gQ^*l^ML+lPb zEz>CsVrbrkj8LB(vJ6p8$bKbq4V0Bd9+lH+i^Jo{BE*)`oo+E7~|514_`;W<|HUBa1#*-t=w=>mIpDy(V|HJcz1;8 zYn8J9PoY-Sqc#kK_nU^cJ?{t`h{9FC&}lDI$1)vS4>mf)?ceW9Y`2M>iWek4J9ZK~ zZeqJ2n%v9si{qIgw&P@V8xFx(cB(+4(`%&lr_oUOJQ|$N zo`JJ7RHPOr#Ye!f%l;OIlO}u=9uK)A7%>4;jF)Q@A9cb*v{*UL}DI1R_EY$^W@Iq~v4 zLW>Q4Y-%lYdi{>tUc3uy(g+-uI6~U^?tDeYM@u5BX;lAD*YH7X5Hqv+`ZS5Z$T|Xw z7wM2DxDqpa#Vz}<&;5zD%fZqr1lKAAS1L;1INnJufng zZ`vYh9jX#B*`vnb;Z(#|tEVD9|5z1qJfF%qa&<+5UcFwoUNMruZePcK@_N3g7WFnk z9yX7U%iU%+OR(v5v3dV4l+k6}4290wr|R22{EpzE44?DQNB9W`e-a_wrMc~q%{zzU zLZLF3(PgCTMWG;ty06LLlg=MpI(-xdJ1ZRb;UK7?G+4|FIc?ARmO zkPhxiCP^^3Xv7Bl4VH?}bZ+VEg;@T4CYgDYQOd(UH)yS8+2TYo!UgwA6uhW0fN0*6V+(1!7Sm4^< r%z}RIib|YAa8DN!KZC09HH{H%JmH-8MkKX(TbtM|v literal 0 HcmV?d00001 diff --git a/Source/nragev20/ControllerSpecs/Controller #1.0.h b/Source/nragev20/ControllerSpecs/Controller #1.0.h new file mode 100644 index 000000000..804ee8d3f --- /dev/null +++ b/Source/nragev20/ControllerSpecs/Controller #1.0.h @@ -0,0 +1,220 @@ +/********************************************************************************** +Common Controller plugin spec, version #1.0 maintained by +zilmar (zilmar@emulation64.com) + +All questions or suggestions should go through the mailing list. +http://www.egroups.com/group/Plugin64-Dev +**********************************************************************************/ +#ifndef _CONTR_H_INCLUDED__ +#define _CONTR_H_INCLUDED__ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Note: BOOL, BYTE, WORD, DWORD, TRUE, FALSE are defined in windows.h */ + +#define PLUGIN_TYPE_CONTROLLER 4 + +/*** Conteroller plugin's ****/ + +#define PLUGIN_NONE 1 +#define PLUGIN_MEMPAK 2 + // not implemeted for non raw data +#define PLUGIN_RUMBLE_PAK 3 + // not implemeted for non raw data +#define PLUGIN_TRANSFER_PAK 4 +#define PLUGIN_RAW 5 + +/********************************************************************************* + Note about Conteroller plugin's: + the rumble pak needs a function for the force feed back joystick and tranfer pak + probaly needs a function for the plugin to be able to select the GB rom and + eeprom... maybe this should be done by the emu instead of the plugin, but I think + it probaly should be done by the plugin. I will see about adding these functions + in the next spec +**********************************************************************************/ + +#define EXPORT __declspec(dllexport) +#define CALL __cdecl + +/***** Structures *****/ +typedef struct { + WORD Version; /* Should be set to 0x0100 */ + WORD Type; /* Set to PLUGIN_TYPE_CONTROLLER */ + char Name[100]; /* Name of the DLL */ + BOOL Reserved1; + BOOL Reserved2; +} PLUGIN_INFO; + +typedef struct { + BOOL Present; + BOOL RawData; + int Plugin; +} CONTROL; + +typedef union { + DWORD Value; + struct { + unsigned R_DPAD : 1; + unsigned L_DPAD : 1; + unsigned D_DPAD : 1; + unsigned U_DPAD : 1; + unsigned START_BUTTON : 1; + unsigned Z_TRIG : 1; + unsigned B_BUTTON : 1; + unsigned A_BUTTON : 1; + + unsigned R_CBUTTON : 1; + unsigned L_CBUTTON : 1; + unsigned D_CBUTTON : 1; + unsigned U_CBUTTON : 1; + unsigned R_TRIG : 1; + unsigned L_TRIG : 1; + unsigned Reserved1 : 1; + unsigned Reserved2 : 1; + + signed Y_AXIS : 8; + + signed X_AXIS : 8; + }; +} BUTTONS; + +/****************************************************************** + Function: CloseDLL + Purpose: This function is called when the emulator is closing + down allowing the dll to de-initialise. + input: none + output: none +*******************************************************************/ +EXPORT void CALL CloseDLL (void); + +/****************************************************************** + Function: ControllerCommand + Purpose: To process the raw data that has just been sent to a + specific controller. + input: - Controller Number (0 to 3) and -1 signalling end of + processing the pif ram. + - Pointer of data to be processed. + output: none + + note: This function is only needed if the DLL is allowing raw + data. + + the data that is being processed looks like this: + initilize controller: 01 03 00 FF FF FF + read controller: 01 04 01 FF FF FF FF +*******************************************************************/ +EXPORT void CALL ControllerCommand ( int Control, BYTE * Command); + +/****************************************************************** + Function: DllAbout + Purpose: This function is optional function that is provided + to give further information about the DLL. + input: a handle to the window that calls this function + output: none +*******************************************************************/ +EXPORT void CALL DllAbout ( HWND hParent ); + +/****************************************************************** + Function: DllConfig + Purpose: This function is optional function that is provided + to allow the user to configure the dll + input: a handle to the window that calls this function + output: none +*******************************************************************/ +EXPORT void CALL DllConfig ( HWND hParent ); + +/****************************************************************** + Function: DllTest + Purpose: This function is optional function that is provided + to allow the user to test the dll + input: a handle to the window that calls this function + output: none +*******************************************************************/ +EXPORT void CALL DllTest ( HWND hParent ); + +/****************************************************************** + Function: GetDllInfo + Purpose: This function allows the emulator to gather information + about the dll by filling in the PluginInfo structure. + input: a pointer to a PLUGIN_INFO stucture that needs to be + filled by the function. (see def above) + output: none +*******************************************************************/ +EXPORT void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo ); + +/****************************************************************** + Function: GetKeys + Purpose: To get the current state of the controllers buttons. + input: - Controller Number (0 to 3) + - A pointer to a BUTTONS structure to be filled with + the controller state. + output: none +*******************************************************************/ +EXPORT void CALL GetKeys(int Control, BUTTONS * Keys ); + +/****************************************************************** + Function: InitiateControllers + Purpose: This function initialises how each of the controllers + should be handled. + input: - The handle to the main window. + - A controller structure that needs to be filled for + the emulator to know how to handle each controller. + output: none +*******************************************************************/ +EXPORT void CALL InitiateControllers (HWND hMainWindow, CONTROL Controls[4]); + +/****************************************************************** + Function: ReadController + Purpose: To process the raw data in the pif ram that is about to + be read. + input: - Controller Number (0 to 3) and -1 signalling end of + processing the pif ram. + - Pointer of data to be processed. + output: none + note: This function is only needed if the DLL is allowing raw + data. +*******************************************************************/ +EXPORT void CALL ReadController ( int Control, BYTE * Command ); + +/****************************************************************** + Function: RomClosed + Purpose: This function is called when a rom is closed. + input: none + output: none +*******************************************************************/ +EXPORT void CALL RomClosed (void); + +/****************************************************************** + Function: RomOpen + Purpose: This function is called when a rom is open. (from the + emulation thread) + input: none + output: none +*******************************************************************/ +EXPORT void CALL RomOpen (void); + +/****************************************************************** + Function: WM_KeyDown + Purpose: To pass the WM_KeyDown message from the emulator to the + plugin. + input: wParam and lParam of the WM_KEYDOWN message. + output: none +*******************************************************************/ +EXPORT void CALL WM_KeyDown( WPARAM wParam, LPARAM lParam ); + +/****************************************************************** + Function: WM_KeyUp + Purpose: To pass the WM_KEYUP message from the emulator to the + plugin. + input: wParam and lParam of the WM_KEYDOWN message. + output: none +*******************************************************************/ +EXPORT void CALL WM_KeyUp( WPARAM wParam, LPARAM lParam ); + +#if defined(__cplusplus) +} +#endif +#endif + diff --git a/Source/nragev20/ControllerSpecs/Controller #1.1.h b/Source/nragev20/ControllerSpecs/Controller #1.1.h new file mode 100644 index 000000000..41d2bf38d --- /dev/null +++ b/Source/nragev20/ControllerSpecs/Controller #1.1.h @@ -0,0 +1,233 @@ +/********************************************************************************** +Common Controller plugin spec, version #1.1 maintained by +zilmar (zilmar@emulation64.com) + +All questions or suggestions should go through the emutalk plugin forum. +http://www.emutalk.net/cgi-bin/ikonboard/ikonboard.cgi?s=3bd272222f66ffff;act=SF;f=20 +**********************************************************************************/ +#ifndef _CONTR_H_INCLUDED__ +#define _CONTR_H_INCLUDED__ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Note: BOOL, BYTE, WORD, DWORD, TRUE, FALSE are defined in windows.h */ + +#define PLUGIN_TYPE_CONTROLLER 4 + +/*** Conteroller plugin's ****/ +#define PLUGIN_NONE 1 +#define PLUGIN_MEMPAK 2 + // not implemeted for non raw data +#define PLUGIN_RUMBLE_PAK 3 + // not implemeted for non raw data +#define PLUGIN_TRANSFER_PAK 4 + // the controller plugin is passed in raw data +#define PLUGIN_RAW 5 + +/********************************************************************************* + Note about Conteroller plugin's: + the rumble pak needs a function for the force feed back joystick and tranfer pak + probaly needs a function for the plugin to be able to select the GB rom and + eeprom... maybe this should be done by the emu instead of the plugin, but I think + it probaly should be done by the plugin. I will see about adding these functions + in the next spec +**********************************************************************************/ + +#define EXPORT __declspec(dllexport) +#define CALL _cdecl + +/***** Structures *****/ +typedef struct { + WORD Version; /* Should be set to 0x0101 */ + WORD Type; /* Set to PLUGIN_TYPE_CONTROLLER */ + char Name[100]; /* Name of the DLL */ + BOOL Reserved1; + BOOL Reserved2; +} PLUGIN_INFO; + +typedef struct { + BOOL Present; + BOOL RawData; + int Plugin; +} CONTROL; + +typedef union { + DWORD Value; + struct { + unsigned R_DPAD : 1; + unsigned L_DPAD : 1; + unsigned D_DPAD : 1; + unsigned U_DPAD : 1; + unsigned START_BUTTON : 1; + unsigned Z_TRIG : 1; + unsigned B_BUTTON : 1; + unsigned A_BUTTON : 1; + + unsigned R_CBUTTON : 1; + unsigned L_CBUTTON : 1; + unsigned D_CBUTTON : 1; + unsigned U_CBUTTON : 1; + unsigned R_TRIG : 1; + unsigned L_TRIG : 1; + unsigned Reserved1 : 1; + unsigned Reserved2 : 1; + + signed Y_AXIS : 8; + + signed X_AXIS : 8; + }; +} BUTTONS; + +typedef struct { + HWND hMainWindow; + HINSTANCE hinst; + + BOOL MemoryBswaped; // If this is set to TRUE, then the memory has been pre + // bswap on a dword (32 bits) boundry, only effects header. + // eg. the first 8 bytes are stored like this: + // 4 3 2 1 8 7 6 5 + BYTE * HEADER; // This is the rom header (first 40h bytes of the rom) + CONTROL *Controls; // A pointer to an array of 4 controllers .. eg: + // CONTROL Controls[4]; +} CONTROL_INFO; + +/****************************************************************** + Function: CloseDLL + Purpose: This function is called when the emulator is closing + down allowing the dll to de-initialise. + input: none + output: none +*******************************************************************/ +EXPORT void CALL CloseDLL (void); + +/****************************************************************** + Function: ControllerCommand + Purpose: To process the raw data that has just been sent to a + specific controller. + input: - Controller Number (0 to 3) and -1 signalling end of + processing the pif ram. + - Pointer of data to be processed. + output: none + + note: This function is only needed if the DLL is allowing raw + data, or the plugin is set to raw + + the data that is being processed looks like this: + initilize controller: 01 03 00 FF FF FF + read controller: 01 04 01 FF FF FF FF +*******************************************************************/ +EXPORT void CALL ControllerCommand ( int Control, BYTE * Command); + +/****************************************************************** + Function: DllAbout + Purpose: This function is optional function that is provided + to give further information about the DLL. + input: a handle to the window that calls this function + output: none +*******************************************************************/ +EXPORT void CALL DllAbout ( HWND hParent ); + +/****************************************************************** + Function: DllConfig + Purpose: This function is optional function that is provided + to allow the user to configure the dll + input: a handle to the window that calls this function + output: none +*******************************************************************/ +EXPORT void CALL DllConfig ( HWND hParent ); + +/****************************************************************** + Function: DllTest + Purpose: This function is optional function that is provided + to allow the user to test the dll + input: a handle to the window that calls this function + output: none +*******************************************************************/ +EXPORT void CALL DllTest ( HWND hParent ); + +/****************************************************************** + Function: GetDllInfo + Purpose: This function allows the emulator to gather information + about the dll by filling in the PluginInfo structure. + input: a pointer to a PLUGIN_INFO stucture that needs to be + filled by the function. (see def above) + output: none +*******************************************************************/ +EXPORT void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo ); + +/****************************************************************** + Function: GetKeys + Purpose: To get the current state of the controllers buttons. + input: - Controller Number (0 to 3) + - A pointer to a BUTTONS structure to be filled with + the controller state. + output: none +*******************************************************************/ +EXPORT void CALL GetKeys(int Control, BUTTONS * Keys ); + +/****************************************************************** + Function: InitiateControllers + Purpose: This function initialises how each of the controllers + should be handled. + input: - The handle to the main window. + - A controller structure that needs to be filled for + the emulator to know how to handle each controller. + output: none +*******************************************************************/ +EXPORT void CALL InitiateControllers (CONTROL_INFO ControlInfo); + +/****************************************************************** + Function: ReadController + Purpose: To process the raw data in the pif ram that is about to + be read. + input: - Controller Number (0 to 3) and -1 signalling end of + processing the pif ram. + - Pointer of data to be processed. + output: none + note: This function is only needed if the DLL is allowing raw + data. +*******************************************************************/ +EXPORT void CALL ReadController ( int Control, BYTE * Command ); + +/****************************************************************** + Function: RomClosed + Purpose: This function is called when a rom is closed. + input: none + output: none +*******************************************************************/ +EXPORT void CALL RomClosed (void); + +/****************************************************************** + Function: RomOpen + Purpose: This function is called when a rom is open. (from the + emulation thread) + input: none + output: none +*******************************************************************/ +EXPORT void CALL RomOpen (void); + +/****************************************************************** + Function: WM_KeyDown + Purpose: To pass the WM_KeyDown message from the emulator to the + plugin. + input: wParam and lParam of the WM_KEYDOWN message. + output: none +*******************************************************************/ +EXPORT void CALL WM_KeyDown( WPARAM wParam, LPARAM lParam ); + +/****************************************************************** + Function: WM_KeyUp + Purpose: To pass the WM_KEYUP message from the emulator to the + plugin. + input: wParam and lParam of the WM_KEYDOWN message. + output: none +*******************************************************************/ +EXPORT void CALL WM_KeyUp( WPARAM wParam, LPARAM lParam ); + +#if defined(__cplusplus) +} +#endif +#endif + diff --git a/Source/nragev20/Debug.cpp b/Source/nragev20/Debug.cpp new file mode 100644 index 000000000..9ece78be2 --- /dev/null +++ b/Source/nragev20/Debug.cpp @@ -0,0 +1,157 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "commonIncludes.h" +#include +#include "FileAccess.h" + +bool bDebug = true; + + +HANDLE hDebug = INVALID_HANDLE_VALUE; + + +void _DebugAnsiFileWrite( LPCSTR szRemark ) +{ + if( !bDebug ) + return; + + if (hDebug == INVALID_HANDLE_VALUE) + { + TCHAR szFile[] = _T("NRage-Debug.txt"); + TCHAR szBuffer[MAX_PATH+1]; + + GetAbsoluteFileName( szBuffer, szFile, DIRECTORY_APPLICATION ); + hDebug = CreateFile( szBuffer, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); + if (hDebug != INVALID_HANDLE_VALUE) + SetFilePointer(hDebug, 0, 0, FILE_END); + } + + if( hDebug != INVALID_HANDLE_VALUE ) + { + DWORD dwWritten; + LPCSTR szText = szRemark; + if( szText == NULL ) + szText = "\r\n"; + + LPCSTR szCurrPos = szText; + + while( ( szCurrPos = strchr( szCurrPos, '\n' )) != NULL ) + { + DWORD length = szCurrPos - szText; + if( length > 0 && szCurrPos[-1] == '\r' ) + --length; + + if( length > 0 ) + WriteFile( hDebug, (LPCVOID)szText, length, &dwWritten, NULL ); + WriteFile( hDebug, "\r\n", 2, &dwWritten, NULL ); + + szText = ++szCurrPos; + } + + DWORD length = lstrlenA( szText ); + + if( length > 0 ) + WriteFile( hDebug, (LPCVOID)szText, length, &dwWritten, NULL ); + } + return; +} + +void _cdecl _DebugWriteA( LPCSTR szFormat, ... ) +{ + if( szFormat != NULL ) + { + char szBuffer[4096]; + + va_list val; + + va_start( val,szFormat ); + wvsprintfA( szBuffer, szFormat, val ); + va_end( val ); + szBuffer[sizeof(szBuffer)-1] = '\0'; + + _DebugAnsiFileWrite( szBuffer ); + } + else + _DebugAnsiFileWrite( NULL ); +} + +void _cdecl _DebugWriteW( const LPCWSTR szFormat, ... ) +{ + if( szFormat != NULL ) + { + WCHAR szBuffer[4096]; + va_list val; + + va_start( val,szFormat ); + wvsprintfW( szBuffer, szFormat, val ); + va_end( val ); + szBuffer[(sizeof(szBuffer) / sizeof(WCHAR))-1] = L'\0'; + + char szAnsi[sizeof(szBuffer) / sizeof(WCHAR)]; + WideCharToMultiByte( CP_ACP, 0, szBuffer, -1, szAnsi, sizeof(szAnsi), NULL, NULL ); + _DebugAnsiFileWrite( szAnsi ); + } + else + _DebugAnsiFileWrite( NULL ); +} + +void _WriteDatasA( LPCSTR Header, const int Control, const unsigned char * Data, const HRESULT hr ) +{ + if( !bDebug || Data == NULL ) + return; + + _DebugWriteA( "%d:%s\n", Control, Header); + + if( hr ) + { + _DebugWriteA( "Failed! ErrorCode: %08X\n", hr ); + } + + + int iEnd = Data[0] + Data[1] + 2; + + for( int i = -1; i < iEnd; i += 8 ) + { + _DebugWriteA( "%02X%02X%02X%02X %02X%02X%02X%02X\n", Data[i+0], Data[i+1], Data[i+2], Data[i+3], Data[i+4], Data[i+5], Data[i+6], Data[i+7] ); + } + + return; +} + +void _CloseDebugFile() +{ + if( hDebug != INVALID_HANDLE_VALUE ) + { + _DebugWriteA("---DEBUG FILE CLOSED---\n"); + CloseHandle( hDebug ); + } +} + +void _DebugFlush() +{ + if( hDebug != INVALID_HANDLE_VALUE ) + { + FlushFileBuffers(hDebug); + } +} diff --git a/Source/nragev20/Debug.h b/Source/nragev20/Debug.h new file mode 100644 index 000000000..397e671b3 --- /dev/null +++ b/Source/nragev20/Debug.h @@ -0,0 +1,65 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include + +#ifdef _DEBUG + +extern bool bDebug; + +void _DebugAnsiFileWrite( LPCSTR szRemark ); +void _WriteDatasA( LPCSTR Header, const int Control, const unsigned char * Data, const HRESULT hr ); +void _cdecl _DebugWriteA( LPCSTR szFormat, ... ); +void _cdecl _DebugWriteW( LPCWSTR szFormat, ... ); +void _CloseDebugFile(); +void _DebugFlush(); + +#define DebugWriteA _DebugWriteA +#define DebugWriteW _DebugWriteW +#define WriteDatasA( header, control, data, hr ) _WriteDatasA( header, control, data, hr ) +#define CloseDebugFile() _CloseDebugFile() +#define DebugWriteByteA(str) DebugWriteA("%02X", str) +#define DebugWriteWordA(str) DebugWriteA("%04X", str) +#define DebugFlush() _DebugFlush() + +#else // #ifndef _DEBUG +#define DebugWriteByteA(str) +#define DebugWriteWordA(str) +#define DebugWriteA ;// +#define DebugWriteW ;// +#define WriteDatasA(header,control,data,hr) +#define CloseDebugFile() +#define DebugFlush() + +#endif // #ifdef _DEBUG + +#ifdef _UNICODE +#define DebugWrite DebugWriteW +#else +#define DebugWrite DebugWriteA +#endif + +#endif // #ifndef _DEBUG_H_ diff --git a/Source/nragev20/DirectInput.cpp b/Source/nragev20/DirectInput.cpp new file mode 100644 index 000000000..14d1b1ba9 --- /dev/null +++ b/Source/nragev20/DirectInput.cpp @@ -0,0 +1,1290 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "commonIncludes.h" +#include +#include "NRagePluginV2.h" +#include "PakIO.h" +#include "DirectInput.h" +#include "XInputController.h" +#include + +// ProtoTypes // +HRESULT AcquireDevice( LPDIRECTINPUTDEVICE8 lpDirectInputDevice ); + +// global Variables // +LPDIRECTINPUT8 g_pDIHandle = NULL; // Base DirectInput8-Handle + +//LPDIRECTINPUTDEVICE8 g_apInputDevice[6] = { NULL, NULL, NULL, NULL, NULL, NULL }; // array of Handles for devices + // 0:Keyboard, 1:Mouse, the rest are FF gamepads + +// BYTE g_acKeystate[256]; // use g_sysKeyboard.stateAs.rgbButtons instead +// DIMOUSESTATE2 g_msMouseState = { 0, 0, 0 }; // Store our mouse state data between reads (because every time we read data, it resets the device data) + // moved to g_sysMouse.stateAs... + +// Update device data tables (so we only have to poll and read the devices once). This is called by GetKeys and ReadController. +void GetDeviceDatas() +{ + HRESULT hr; + +/* if( g_sysKeyboard.didHandle ) + { + hr = g_sysKeyboard.didHandle->Poll(); + if( FAILED( hr )) + AcquireDevice( g_sysKeyboard.didHandle ); // we'll try again next time + + hr = g_sysKeyboard.didHandle->GetDeviceState( sizeof(g_sysKeyboard.stateAs.rgbButtons), &g_sysKeyboard.stateAs.rgbButtons ); + + if( FAILED( hr )) + ZeroMemory( g_sysKeyboard.stateAs.rgbButtons, sizeof(g_sysKeyboard.stateAs.rgbButtons) ); + } */ + + if( g_sysMouse.didHandle ) + { + hr = g_sysMouse.didHandle->Poll(); + + if( FAILED( hr )) + AcquireDevice( g_sysMouse.didHandle ); // we'll try again next time + + hr = g_sysMouse.didHandle->GetDeviceState( sizeof(DIMOUSESTATE2), &g_sysMouse.stateAs.mouseState ); + + if( FAILED( hr )) + ZeroMemory( &g_sysMouse.stateAs.mouseState, sizeof(DIMOUSESTATE2) ); + } + + // need to just poll every damn device we're using + for( int i = 0; i < g_nDevices; i++ ) + { + if( g_devList[i].didHandle ) + { + if( FAILED( g_devList[i].didHandle->Poll() )) + AcquireDevice( g_devList[i].didHandle ); // we'll try again next time + + switch (LOBYTE(g_devList[i].dwDevType)) + { + case DI8DEVTYPE_KEYBOARD: + hr = g_devList[i].didHandle->GetDeviceState( sizeof(g_devList[i].stateAs.rgbButtons), g_devList[i].stateAs.rgbButtons ); + break; + case DI8DEVTYPE_MOUSE: + hr = g_devList[i].didHandle->GetDeviceState( sizeof(g_devList[i].stateAs.mouseState), &g_devList[i].stateAs.mouseState ); + break; + default: + hr = g_devList[i].didHandle->GetDeviceState( sizeof(g_devList[i].stateAs.joyState), &g_devList[i].stateAs.joyState ); + } + } + else + hr = DIERR_NOTACQUIRED; + + if( hr == DIERR_NOTACQUIRED ) // changed this because in the rare condition that we lose input between polling and GetDeviceState we don't want to reset our current controls --rabid + { + ZeroMemory( &g_devList[i].stateAs.joyState, sizeof(DEVICE::INPUTSTATE)); + if (g_devList[i].dwDevType != DI8DEVTYPE_KEYBOARD && g_devList[i].dwDevType != DI8DEVTYPE_MOUSE) + FillMemory( g_devList[i].stateAs.joyState.rgdwPOV, sizeof(g_devList[i].stateAs.joyState.rgdwPOV), 0xFF ); // g_devList[i].stateAs.joyState.rgdwPOV = -1; // -1 is neutral + } + } +} + +// hacked up piece of shit, but it works +inline bool GetJoyPadPOV( PDWORD dwDegree, BYTE AxeId ) +// TRUE if specified Direction is Pressed +{ + if( LOWORD( *dwDegree ) == 0xFFFF ) + return false; + + bool bPressed; + + switch( AxeId ) + { + case AI_POV_DOWN: + bPressed = (( *dwDegree >= 18000 - POVANGLETHRESH ) && (*dwDegree <= 18000 + POVANGLETHRESH )); + break; + case AI_POV_LEFT: + bPressed = (( *dwDegree >= 27000 - POVANGLETHRESH ) && (*dwDegree <= 27000 + POVANGLETHRESH )); + break; + case AI_POV_RIGHT: + bPressed = (( *dwDegree >= 9000 - POVANGLETHRESH ) && (*dwDegree <= 9000 + POVANGLETHRESH )); + break; + case AI_POV_UP: + bPressed = (( *dwDegree >= 36000 - POVANGLETHRESH ) || ( *dwDegree <= 0 + POVANGLETHRESH )); + break; + default: + bPressed = false; + } + + return bPressed; +} + +// Fill in button states and axis states for controller indexController, into the struct pdwData. +// pdwData is a pointer to a 4 byte BUTTONS union, if anyone cares +bool GetNControllerInput ( const int indexController, LPDWORD pdwData ) +{ + *pdwData = 0; + WORD w_Buttons = 0; + // WORD w_Axes = 0; + + LPCONTROLLER pcController = &g_pcControllers[indexController]; // still needs to be here, but not as important --rabid + + bool b_Value; + long l_Value = 0; + + long lAxisValueX = ZEROVALUE; + long lAxisValueY = ZEROVALUE; + + // take this info from the N64 controller struct, regardless of input devices + float d_ModifierX = (float)pcController->bStickRange / 100.0f; + float d_ModifierY = (float)pcController->bStickRange / 100.0f; + + int i; + + // do N64-Buttons / modifiers + for (i = 0; i < pcController->nModifiers; i++ ) + { + BUTTON btnButton = pcController->pModifiers[i].btnButton; + + b_Value = IsBtnPressed( btnButton ); + + bool fChangeMod = false; + + if( pcController->pModifiers[i].bModType == MDT_CONFIG ) + { // Config-Type + if( pcController->pModifiers[i].fToggle ) + { + if( b_Value && !btnButton.fPrevPressed) + { + pcController->pModifiers[i].fStatus = !pcController->pModifiers[i].fStatus; + fChangeMod = true; + } + } + else + { + if( b_Value != (bool)(btnButton.fPrevPressed)) + fChangeMod = true; + } + } + else + { // Move / Macro Type + if( pcController->pModifiers[i].fToggle ) + { + if( b_Value && !btnButton.fPrevPressed ) + pcController->pModifiers[i].fStatus = !pcController->pModifiers[i].fStatus; + fChangeMod = ( pcController->pModifiers[i].fStatus != 0 ); + } + else + { + fChangeMod = b_Value; + } + } + + if( fChangeMod ) + { + switch( pcController->pModifiers[i].bModType ) + { + case MDT_MOVE: + { + LPMODSPEC_MOVE args = (LPMODSPEC_MOVE)&pcController->pModifiers[i].dwSpecific; + d_ModifierX *= args->XModification / 100.0f; + d_ModifierY *= args->YModification / 100.0f; + } + break; + case MDT_MACRO: + { + LPMODSPEC_MACRO args = (LPMODSPEC_MACRO)&pcController->pModifiers[i].dwSpecific; + + if (args->fRapidFire) // w00t! Rapid Fire here + { + if ((unsigned) b_Value != btnButton.fPrevPressed) // New macro pressed + { + args->fPrevFireState = 0; + args->fPrevFireState2 = 0; + } + if(!args->fPrevFireState) // This round, a firing is needed + { + w_Buttons |= args->aButtons; + if( args->fAnalogRight ) + lAxisValueX += MAXAXISVALUE; + else if( args->fAnalogLeft ) + lAxisValueX -= MAXAXISVALUE; + + if( args->fAnalogDown ) + lAxisValueY -= MAXAXISVALUE; + else if( args->fAnalogUp ) // up + lAxisValueY += MAXAXISVALUE; + } + + // Ok, update the firing counters here + if (args->fRapidFireRate) // Do the rapid fire slowly + { // Note that this updates State2 before State... Makes a nice slower square-wave type pulse for the update + args->fPrevFireState2 = (args->fPrevFireState2 + 1) & 1; + if (!args->fPrevFireState2) + { + args->fPrevFireState = (args->fPrevFireState + 1) & 1; + DebugWriteA("Slow Rapid Fire - Mark 2\n"); + } + } + else // Do a fast rapid fire + { + args->fPrevFireState = (args->fPrevFireState + 1) & 1; + DebugWriteA("Fast Rapid Fire\n"); + } + } + else + { + w_Buttons |= args->aButtons; // Note this: It lets you push buttons as well as the macro buttons + if( args->fAnalogRight ) + lAxisValueX += MAXAXISVALUE; + else if( args->fAnalogLeft ) + lAxisValueX -= MAXAXISVALUE; + + if( args->fAnalogDown ) + lAxisValueY -= MAXAXISVALUE; + else if( args->fAnalogUp ) // up + lAxisValueY += MAXAXISVALUE; + + args->fPrevFireState = 0; + } + } + break; + case MDT_CONFIG: + { + LPMODSPEC_CONFIG args = (LPMODSPEC_CONFIG)&pcController->pModifiers[i].dwSpecific; + + if( args->fChangeAnalogConfig ) + { + BYTE bConfig = (BYTE)args->fAnalogStickMode; + if( bConfig < PF_AXESETS ) + pcController->bAxisSet = bConfig; + else + { + if( pcController->bAxisSet == PF_AXESETS-1 ) + pcController->bAxisSet = 0; + else + ++pcController->bAxisSet; + } + + } + if( args->fChangeMouseXAxis ) + if (pcController->bMouseMoveX == MM_BUFF) + pcController->bMouseMoveX = MM_ABS; + else if (pcController->bMouseMoveX == MM_ABS) + pcController->bMouseMoveX = MM_BUFF; + if( args->fChangeMouseYAxis ) + if (pcController->bMouseMoveY == MM_BUFF) + pcController->bMouseMoveY = MM_ABS; + else if (pcController->bMouseMoveY == MM_ABS) + pcController->bMouseMoveY = MM_BUFF; + + if( args->fChangeKeyboardXAxis ) + pcController->fKeyAbsoluteX = !pcController->fKeyAbsoluteX; + if( args->fChangeKeyboardYAxis ) + pcController->fKeyAbsoluteY = !pcController->fKeyAbsoluteY; + } + break; + } + } + + btnButton.fPrevPressed = b_Value; + pcController->pModifiers[i].btnButton = btnButton; + } // END N64 MODIFIERS for + + // do N64-Buttons / modifiers + for( i = 0; i < PF_APADR; i++ ) + { + BUTTON btnButton = pcController->aButton[i]; + + b_Value = IsBtnPressed( btnButton ); + + w_Buttons |= (((WORD)b_Value) << i); + } // END N64 BUTTONS for + + long lDeadZoneValue = pcController->bPadDeadZone * RANGERELATIVE / 100; + float fDeadZoneRelation = (float)RANGERELATIVE / (float)( RANGERELATIVE - lDeadZoneValue ); + + // do N64 joystick axes + for ( i = 0; i < 4; i++ ) + { + // 0 : right + // 1 : left + // 2 : down + // 3 : up + + bool fNegInput = (( i == 1 ) || ( i == 2 )); // Input has to be negated + + BUTTON btnButton = pcController->aButton[PF_APADR + pcController->bAxisSet * 4 + i]; + LPLONG plRawState = (LPLONG)&btnButton.parentDevice->stateAs.joyState; + + switch( btnButton.bBtnType ) + { + case DT_JOYBUTTON: + l_Value = MAXAXISVALUE; + b_Value = ( btnButton.parentDevice->stateAs.joyState.rgbButtons[btnButton.bOffset] & 0x80 ) != 0; + break; + + case DT_JOYSLIDER: + case DT_JOYAXE: + l_Value = plRawState[btnButton.bOffset] - ZEROVALUE; + + if( btnButton.bAxisID ) // negative Range + { + fNegInput = !fNegInput; + + b_Value = ( l_Value <= -lDeadZoneValue ); + if( b_Value ) + l_Value = (long) ((float)(l_Value + lDeadZoneValue ) * fDeadZoneRelation ); + } + else + { + b_Value = ( l_Value >= lDeadZoneValue ); + if( b_Value ) + l_Value = (long) ((float)(l_Value - lDeadZoneValue ) * fDeadZoneRelation ); + } + break; + + case DT_JOYPOV: + l_Value = MAXAXISVALUE; + b_Value = GetJoyPadPOV( (PDWORD)&plRawState[btnButton.bOffset] , btnButton.bAxisID ); + break; + + case DT_KEYBUTTON: + if( btnButton.parentDevice->stateAs.rgbButtons[btnButton.bOffset] & 0x80 ) + { + b_Value = true; + + if(( pcController->fKeyAbsoluteX && i < 2 ) + || ( pcController->fKeyAbsoluteY && i > 1 )) + { + if( pcController->wAxeBuffer[i] < MAXAXISVALUE ) + { + l_Value = pcController->wAxeBuffer[i] = min(( pcController->wAxeBuffer[i] + N64DIVIDER*3), MAXAXISVALUE ); + } + else + l_Value = MAXAXISVALUE; + } + else + { + if( pcController->wAxeBuffer[i] < MAXAXISVALUE ) + { + l_Value = pcController->wAxeBuffer[i] = min(( pcController->wAxeBuffer[i] * 2 + N64DIVIDER*5 ), MAXAXISVALUE ); + } + else + l_Value = MAXAXISVALUE; + } + } + else + { + if(( pcController->fKeyAbsoluteX && i < 2 ) + || ( pcController->fKeyAbsoluteY && i > 1 )) + { + l_Value = pcController->wAxeBuffer[i]; + b_Value = true; + } + else + { + if( pcController->wAxeBuffer[i] > N64DIVIDER ) + { + b_Value = true; + l_Value = pcController->wAxeBuffer[i] = pcController->wAxeBuffer[i] / 2 ; + } + else + b_Value = false; + } + } + break; + + case DT_MOUSEBUTTON: + l_Value = MAXAXISVALUE; + b_Value = ( btnButton.parentDevice->stateAs.mouseState.rgbButtons[btnButton.bOffset] & 0x80 ) != 0; + break; + + case DT_MOUSEAXE: + if( i < 2 ) + pcController->wAxeBuffer[i] += plRawState[btnButton.bOffset] * pcController->wMouseSensitivityX * MOUSESCALEVALUE; // l_Value = btnButton.parentDevice->stateAs.mouseState[btnButton.bOffset]; + else + pcController->wAxeBuffer[i] += plRawState[btnButton.bOffset] * pcController->wMouseSensitivityY * MOUSESCALEVALUE; // l_Value = btnButton.parentDevice->stateAs.mouseState[btnButton.bOffset]; + + l_Value = pcController->wAxeBuffer[i]; + + // wAxeBuffer is positive for axes 0 and 3 if buffer remains, else zero + // wAxeBuffer is negative for axes 1 and 2 if buffer remains, else zero + + if(( pcController->bMouseMoveX == MM_ABS && i < 2 ) || ( pcController->bMouseMoveY == MM_ABS && i > 1 )) + pcController->wAxeBuffer[i] = min( max( MINAXISVALUE, pcController->wAxeBuffer[i]) , MAXAXISVALUE); + else if (( pcController->bMouseMoveX == MM_BUFF && i < 2 ) || ( pcController->bMouseMoveY == MM_BUFF && i > 1 )) + pcController->wAxeBuffer[i] = pcController->wAxeBuffer[i] * MOUSEBUFFERDECAY / 100; + else // "deadpan" mouse + { + pcController->wAxeBuffer[i] = 0; + } + + if( btnButton.bAxisID == AI_AXE_N) // the mouse axis has the '-' flag set + { + fNegInput = !fNegInput; + + b_Value = ( l_Value < ZEROVALUE ); + } + else + { + b_Value = ( l_Value > ZEROVALUE ); + } + + break; + + case DT_UNASSIGNED: + default: + b_Value = false; + } + + if ( b_Value ) + { + if ( fNegInput ) + l_Value = -l_Value; + + if( i < 2 ) + lAxisValueX += l_Value; + else + lAxisValueY += l_Value; + } + } + + if( pcController->fKeyboard ) + { + if( pcController->fKeyAbsoluteX ) + { + if( pcController->wAxeBuffer[0] > pcController->wAxeBuffer[1] ) + { + pcController->wAxeBuffer[0] -= pcController->wAxeBuffer[1]; + pcController->wAxeBuffer[1] = 0; + } + else + { + pcController->wAxeBuffer[1] -= pcController->wAxeBuffer[0]; + pcController->wAxeBuffer[0] = 0; + } + } + if( pcController->fKeyAbsoluteY ) + { + if( pcController->wAxeBuffer[2] > pcController->wAxeBuffer[3] ) + { + pcController->wAxeBuffer[2] -= pcController->wAxeBuffer[3]; + pcController->wAxeBuffer[3] = 0; + } + else + { + pcController->wAxeBuffer[3] -= pcController->wAxeBuffer[2]; + pcController->wAxeBuffer[2] = 0; + } + } + } + + + if (pcController->bRapidFireEnabled) { + if (pcController->bRapidFireCounter >= pcController->bRapidFireRate) { + w_Buttons = (w_Buttons & 0xFF1F); + pcController->bRapidFireCounter = 0; + } else{ + pcController->bRapidFireCounter = pcController->bRapidFireCounter + 1; + } + } + + if( pcController->fRealN64Range && ( lAxisValueX || lAxisValueY )) + { + long lAbsoluteX = ( lAxisValueX > 0 ) ? lAxisValueX : -lAxisValueX; + long lAbsoluteY = ( lAxisValueY > 0 ) ? lAxisValueY : -lAxisValueY; + + long lRangeX; + long lRangeY; + + if( lAbsoluteX > lAbsoluteY ) + { + lRangeX = MAXAXISVALUE; + lRangeY = lRangeX * lAbsoluteY / lAbsoluteX; + } + else + { + lRangeY = MAXAXISVALUE; + lRangeX = lRangeY * lAbsoluteX / lAbsoluteY; + } + + // TODO: optimize this --rabid + double dRangeDiagonal = sqrt((double)(lRangeX * lRangeX + lRangeY * lRangeY)); +// __asm{ +// fld fRangeDiagonal +// fsqrt +// fstp fRangeDiagonal +// fwait +// } + double dRel = MAXAXISVALUE / dRangeDiagonal; + + *pdwData = MAKELONG(w_Buttons, + MAKEWORD( (BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueX * d_ModifierX * dRel )), MAXAXISVALUE) / N64DIVIDER ), + (BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueY * d_ModifierY * dRel )), MAXAXISVALUE) / N64DIVIDER ))); + } + else + { + *pdwData = MAKELONG(w_Buttons, + MAKEWORD( (BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueX * d_ModifierX )), MAXAXISVALUE) / N64DIVIDER ), + (BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueY * d_ModifierY )), MAXAXISVALUE) / N64DIVIDER ))); + } + + + return true; +} + +bool InitDirectInput( HWND hWnd ) +{ + if( g_hDirectInputDLL == NULL ) + g_hDirectInputDLL = LoadLibrary( _T( "dinput8.dll" )); + if( g_hDirectInputDLL == NULL ) + { + ErrorMessage(IDS_ERR_DINOTFOUND, 0, false); + } + else if( !g_pDIHandle ) // is NULL if not yet initialized + { + HRESULT (WINAPI *lpGetDIHandle)( HINSTANCE, DWORD, REFIID, LPVOID*, LPUNKNOWN ) = NULL; + lpGetDIHandle = (HRESULT (WINAPI *)( HINSTANCE, DWORD, REFIID, LPVOID*, LPUNKNOWN ))GetProcAddress( g_hDirectInputDLL, "DirectInput8Create" ); + + if( lpGetDIHandle != NULL ) + { + HRESULT hr; + hr = lpGetDIHandle( g_strEmuInfo.hinst, DIRECTINPUT_VERSION, + IID_IDirectInput8, (LPVOID*)&g_pDIHandle, NULL ); + if( FAILED( hr )) + { + ErrorMessage(IDS_ERR_DICREATE, 0, false); + g_pDIHandle = NULL; + FreeLibrary( g_hDirectInputDLL ); + g_hDirectInputDLL = NULL; + } + } + } + + return (g_pDIHandle != NULL); +} + +// release a DirectInput device. We don't need it anymore. +void ReleaseDevice( LPDIRECTINPUTDEVICE8 &lpDirectInputDevice ) +{ + if( lpDirectInputDevice != NULL) + { + lpDirectInputDevice->Unacquire(); + lpDirectInputDevice->Release(); + lpDirectInputDevice = NULL; + } + return; +} + +// release a DirectInput effect. We don't need it anymore. +void ReleaseEffect( LPDIRECTINPUTEFFECT &lpDirectEffect ) +{ + if( lpDirectEffect != NULL) + { + // should unload the effect on release, I hope + lpDirectEffect->Release(); + lpDirectEffect = NULL; + } + return; +} + +// release our DirectInput effects and devices, our DirectInput handle, and then unload dinput library +void FreeDirectInput () +{ + int i; + // release effects + for( i = 0; i < ARRAYSIZE( g_apdiEffect ); ++i ) + ReleaseEffect( g_apdiEffect[i] ); + ZeroMemory( g_apdiEffect, sizeof(g_apdiEffect) ); + + // release FF devices + for( i = 0; i << ARRAYSIZE(g_apFFDevice); ++i ) + ReleaseDevice( g_apFFDevice[i] ); + ZeroMemory( g_apFFDevice, sizeof(g_apFFDevice) ); + + // release normal devices + for( i = 0; i < g_nDevices; i++ ) + ReleaseDevice( g_devList[i].didHandle ); + ZeroMemory( g_devList, sizeof(g_devList) ); + g_nDevices = 0; + + // release mouse device + ReleaseDevice( g_sysMouse.didHandle ); + ZeroMemory( &g_sysMouse, sizeof(g_sysMouse) ); + + // Release any DirectInput handles. + if( g_pDIHandle != NULL ) + { + g_pDIHandle->Release(); + g_pDIHandle = NULL; + } + // Unload the library. + if( g_hDirectInputDLL != NULL ) + { + FreeLibrary( g_hDirectInputDLL ); + g_hDirectInputDLL = NULL; + } + return; +} + +// Acquire our device. Our device might get unacquired for many many reasons, and we need to be able to reacquire it to get input again. +// We use this a LOT. +inline HRESULT AcquireDevice( LPDIRECTINPUTDEVICE8 lpDirectInputDevice ) +{ + HRESULT hResult = lpDirectInputDevice->Acquire(); + while( hResult == DIERR_INPUTLOST ) + hResult = lpDirectInputDevice->Acquire(); + if( SUCCEEDED( hResult )) + lpDirectInputDevice->Poll(); + return hResult; +} + +// Called by the DirectInput enumerator for each FF device. What kind of force feedback effects does this device support? We'll store it in pvRef. +BOOL CALLBACK EnumGetEffectTypes( LPCDIEFFECTINFO pdei, LPVOID pvRef ) +{ + BYTE bFFType = *(LPBYTE)pvRef; + bFFType |= ( pdei->dwEffType & DIEFT_CONSTANTFORCE ) ? RUMBLE_CONSTANT : 0; + bFFType |= ( pdei->dwEffType & DIEFT_RAMPFORCE ) ? RUMBLE_RAMP : 0; + bFFType |= ( pdei->dwEffType & DIEFT_CONDITION ) ? RUMBLE_CONDITION : 0; + bFFType |= ( pdei->dwEffType & DIEFT_PERIODIC ) ? RUMBLE_PERIODIC : 0; + bFFType |= ( pdei->dwEffType & DIEFT_CUSTOMFORCE ) ? RUMBLE_CUSTOM : 0; + *(WORD*)pvRef = bFFType; + return DIENUM_CONTINUE; +} + +// Called by the DirectInput enumerator for each attached DI device. We use it to make a list of devices. +// EnumMakeDeviceList has been rewritten. --rabid +BOOL CALLBACK EnumMakeDeviceList( LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef ) +{ + if( IsXInputDevice( &lpddi->guidProduct ) ) // Check if is XInput device --tecnicors + return DIENUM_CONTINUE; + + if (IsEqualGUID(g_sysMouse.guidInstance, lpddi->guidInstance)) + return DIENUM_CONTINUE; + + for (int i = 0; i < g_nDevices; i++) + if (IsEqualGUID(g_devList[i].guidInstance, lpddi->guidInstance)) + return ( g_nDevices < ARRAYSIZE(g_devList) ) ? DIENUM_CONTINUE : DIENUM_STOP; + + if (g_nDevices < ARRAYSIZE(g_devList)) // our buffer isn't full yet and the device doesn't already exist in our table + { + lstrcpyn( g_devList[g_nDevices].szProductName, lpddi->tszProductName, MAX_PATH ); + g_devList[g_nDevices].dwDevType = lpddi->dwDevType; + g_devList[g_nDevices].guidInstance = lpddi->guidInstance; + + g_devList[g_nDevices].bProductCounter = 0; // counting similar devices + for( int i = 0; i < g_nDevices; ++i ) + { + if( !lstrcmp( lpddi->tszProductName, g_devList[i].szProductName )) + { + if( g_devList[g_nDevices].bProductCounter == 0 ) + { + g_devList[g_nDevices].bProductCounter = 2; + if( g_devList[i].bProductCounter == 0 ) + g_devList[i].bProductCounter = 1; + } + else + g_devList[g_nDevices].bProductCounter++; // give em instance numbers + } + } + if( !lstrcmp( lpddi->tszProductName, TEXT( STRING_ADAPTOID ))) + g_devList[g_nDevices].bEffType = RUMBLE_DIRECT; + else + g_devList[g_nDevices].bEffType = RUMBLE_NONE; + + if ( GetInputDevice(g_strEmuInfo.hMainWindow, g_devList[g_nDevices].didHandle, lpddi->guidInstance, lpddi->dwDevType, DIB_DEVICE) ) + { + g_devList[g_nDevices].didHandle->EnumEffects( EnumGetEffectTypes, &g_devList[g_nDevices].bEffType, DIEFT_ALL ); + g_nDevices++; + } + else + ZeroMemory(&g_devList[g_nDevices], sizeof(DEVICE)); + } + + return ( g_nDevices < ARRAYSIZE(g_devList) ) ? DIENUM_CONTINUE : DIENUM_STOP; +} + +// Called by an enumerator in GetInputDevice to determine if a device is attached at all. +BOOL CALLBACK EnumIsDeviceAvailable( LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef ) +{ + if( lpddi->guidInstance == *(GUID*)((LPVOID*)pvRef)[0] ) + { + *(bool*)((LPVOID*)pvRef)[1] = true; + return DIENUM_STOP; + } + + return DIENUM_CONTINUE; +} + +// Called by an axis enumerator in GetInputDevice. Set the min and max range so we can pass the rec'd value right to the emulator. +BOOL CALLBACK EnumSetObjectsAxis( LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) +{ + LPDIRECTINPUTDEVICE8 lpDirectInputDevice = (LPDIRECTINPUTDEVICE8)pvRef; + DIPROPRANGE diprg; + + diprg.diph.dwSize = sizeof(DIPROPRANGE); + diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = lpddoi->dwType; + diprg.lMin = MINAXISVALUE; + diprg.lMax = MAXAXISVALUE; + + lpDirectInputDevice->SetProperty(DIPROP_RANGE, &diprg.diph); // HACK: Usually works, but not all devices support setting range. + + return DIENUM_CONTINUE; +} + +// **if passed an existing DirectInputDevice which matches gGuid +// unacquires it, and sets its cooperative level (reinitialize) +// **if the existing device does not match the passed gGuid, the existing device is released +// **if no device was passed or gGuid did not match +// searches for the controller matching gGuid in connected and available devices +// creates a DirectInputDevice +// sets its data format +// sets its cooperative level +// for joysticks, calls EnumSetObjectsAxis for each axis +// GetInputDevice always leaves the returned device in an UNACQUIRED state. +bool GetInputDevice( HWND hWnd, LPDIRECTINPUTDEVICE8 &lpDirectInputDevice, GUID gGuid, DWORD dwDevType, DWORD dwCooperativeLevel ) +{ + DebugWriteA("GetInputDevice: gGuid is {%08.8lX-%04.4hX-%04.4hX-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}\n", gGuid.Data1, gGuid.Data2, gGuid.Data3, gGuid.Data4[0], gGuid.Data4[1], gGuid.Data4[2], gGuid.Data4[3], gGuid.Data4[4], gGuid.Data4[5], gGuid.Data4[6], gGuid.Data4[7]); + if( lpDirectInputDevice != NULL) + { + DIDEVICEINSTANCE didDev; + didDev.dwSize = sizeof(DIDEVICEINSTANCE); + lpDirectInputDevice->GetDeviceInfo( &didDev ); + + if( didDev.guidInstance == gGuid ) + { // we've already gotten this device; unacquire it and initialize + DebugWriteA("GetInputDevice: already created, attempting to reinit\n"); + lpDirectInputDevice->Unacquire(); + lpDirectInputDevice->SetCooperativeLevel( hWnd, dwCooperativeLevel ); + return true; + } + else + ReleaseDevice( lpDirectInputDevice ); + } + + HRESULT hResult; + + LPCDIDATAFORMAT ppDiDataFormat = NULL; + bool Success = false; + + switch( LOBYTE(dwDevType) ) + { + + case DI8DEVTYPE_KEYBOARD: + ppDiDataFormat = &c_dfDIKeyboard; + break; + + case DI8DEVTYPE_MOUSE: + ppDiDataFormat = &c_dfDIMouse2; + break; + + //case DI8DEVTYPE_GAMEPAD: + //case DI8DEVTYPE_JOYSTICK: + //case DI8DEVTYPE_DRIVING: + //case DI8DEVTYPE_1STPERSON: + //case DI8DEVTYPE_FLIGHT: + default: // assume everything else is a gamepad; probably not the best idea but it works + ppDiDataFormat = &c_dfDIJoystick; + break; + } + + bool bDeviceAvailable = false; + + VOID* aRef[2] = { &gGuid, &bDeviceAvailable }; + + // for each available device in our dwDevType category, run EnumIsDeviceAvailable with params "aRef" + g_pDIHandle->EnumDevices( DI8DEVCLASS_ALL, EnumIsDeviceAvailable, (LPVOID)aRef, DIEDFL_ATTACHEDONLY ); + + if( !bDeviceAvailable ) + { + DebugWriteA("GetInputDevice: Device does not appear available\n"); + return false; + } + + hResult = g_pDIHandle->CreateDevice( gGuid, &lpDirectInputDevice, NULL ); + + if( SUCCEEDED( hResult )) + { + hResult = lpDirectInputDevice->SetDataFormat( ppDiDataFormat ); + hResult = lpDirectInputDevice->SetCooperativeLevel( hWnd, dwCooperativeLevel ); + + Success = SUCCEEDED( hResult ); + if (!Success) + { + DebugWriteA("GetInputDevice: SetCooperativeLevel failed\n"); + } + } + else + DebugWriteA("GetInputDevice: CreateDevice failed\n"); + + if( Success && ( ppDiDataFormat == &c_dfDIJoystick )) + lpDirectInputDevice->EnumObjects( EnumSetObjectsAxis, lpDirectInputDevice, DIDFT_AXIS ); + + return Success; +} + +// How many force feedback axes (motors) does our device have? We want to rumble them all. +BOOL CALLBACK EnumCountFFAxes( LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pnAxes ) +{ + *(DWORD*)pnAxes += 1; + return DIENUM_CONTINUE; +} + +// Create a force feedback effect handle and downloads the effect. Parameters are self-explanatory. +bool CreateEffectHandle( HWND hWnd, LPDIRECTINPUTDEVICE8 lpDirectInputDevice, LPDIRECTINPUTEFFECT &pDIEffect, BYTE bRumbleTyp, long lStrength ) +{ + if( pDIEffect ) + ReleaseEffect( pDIEffect ); + + if( !lpDirectInputDevice || bRumbleTyp == RUMBLE_DIRECT ) + return false; + + DWORD nAxes = 0; + DWORD rgdwAxes[] = { DIJOFS_X, DIJOFS_Y }; + + HRESULT hResult; + + // count the FF - axes of the joystick + lpDirectInputDevice->EnumObjects( EnumCountFFAxes, &nAxes, DIDFT_FFACTUATOR | DIDFT_AXIS ); + + if( nAxes == 0 ) + return false; + nAxes = min( nAxes, 2 ); + + + // Must be unaquired for setting stuff like Co-op Level + hResult = lpDirectInputDevice->Unacquire(); + //FF Requires EXCLUSIVE LEVEL, took me hours to find the reason why it wasnt working + hResult = lpDirectInputDevice->SetCooperativeLevel( hWnd, DIB_FF ); + + // fail if we can't set coop level --rabid + if (hResult != DI_OK) + { + DebugWriteA("CreateEffectHandle: couldn't set coop level: %08X\n", hResult); + return false; + } + + // Since we will be playing force feedback effects, we should disable the + // auto-centering spring. + DIPROPDWORD dipdw; + dipdw.diph.dwSize = sizeof(DIPROPDWORD); + dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dipdw.diph.dwObj = 0; + dipdw.diph.dwHow = DIPH_DEVICE; + dipdw.dwData = FALSE; + + hResult = lpDirectInputDevice->SetProperty( DIPROP_AUTOCENTER, &dipdw.diph ); + + long rglDirection[] = { 1, 1 }; + LPGUID EffectGuid; + DIEFFECT eff; + ZeroMemory( &eff, sizeof(eff) ); + + eff.dwSize = sizeof(DIEFFECT); + eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; + eff.dwGain = lStrength * 100; + eff.dwTriggerButton = DIEB_NOTRIGGER; + eff.dwTriggerRepeatInterval = 0; + eff.cAxes = nAxes; //Number of Axes + eff.rgdwAxes = rgdwAxes; + eff.rglDirection = rglDirection; + eff.lpEnvelope = NULL; + eff.dwStartDelay = 0; + + DICONSTANTFORCE cf; + DIRAMPFORCE rf; + DIPERIODIC pf; + + switch( bRumbleTyp ) + { + case RUMBLE_CONSTANT: + EffectGuid = (GUID*)&GUID_ConstantForce; + + eff.dwDuration = 150000; // microseconds + eff.dwSamplePeriod = 0; + eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); + eff.lpvTypeSpecificParams = &cf; + + cf.lMagnitude = 10000; + break; + case RUMBLE_RAMP: + EffectGuid = (GUID*)&GUID_RampForce; + + eff.dwDuration = 300000; // microseconds + eff.dwSamplePeriod = 0; + eff.cbTypeSpecificParams = sizeof(DIRAMPFORCE); + eff.lpvTypeSpecificParams = &rf; + + rf.lStart = 10000; + rf.lEnd = 2000; + break; + + case RUMBLE_CONDITION: + case RUMBLE_PERIODIC: + EffectGuid = (GUID*)&GUID_Sine; + + eff.dwDuration = 150000; // microseconds + eff.dwSamplePeriod = 0; + eff.cbTypeSpecificParams = sizeof(DIPERIODIC); + eff.lpvTypeSpecificParams = &pf; + + pf.dwMagnitude = 10000; + pf.lOffset = 0; + pf.dwPhase = 0; + pf.dwPeriod = 2000; + break; + + case RUMBLE_NONE: + case RUMBLE_CUSTOM: + default: + return false; + } + + hResult = lpDirectInputDevice->CreateEffect( *EffectGuid, &eff, &pDIEffect, NULL ); + + if (hResult == DI_OK) + { + hResult = lpDirectInputDevice->Acquire(); + hResult = pDIEffect->Download(); + } + else + { + DebugWriteA("CreateEffectHandle: didn't CreateEffect: %08X\n", hResult); + } + return SUCCEEDED( hResult ); +} + +// Counts how many of each type of button assignment (keyboard, mouse, gamepad) +DWORD CountControllerStructDevs( CONTROLLER *pController ) +{ + BYTE bMouse = 0, bKeyboard = 0, bGamePad = 0; + BYTE bDType; + + bool fModifier = ( pController->pModifiers != NULL ); + int i = ( fModifier ) ? pController->nModifiers : ARRAYSIZE( pController->aButton ); + i--; + + for( ; i >= 0 || fModifier; --i ) + { + if( i < 0 ) + { + i = ARRAYSIZE( pController->aButton ) - 1; + fModifier = false; + } + + bDType = ( fModifier ) ? pController->pModifiers[i].btnButton.bBtnType + : pController->aButton[i].bBtnType; + + switch( bDType ) + { + case DT_JOYBUTTON: + case DT_JOYAXE: + case DT_JOYSLIDER: + case DT_JOYPOV: + ++bGamePad; + break; + + case DT_KEYBUTTON: + ++bKeyboard; + break; + + case DT_MOUSEBUTTON: + case DT_MOUSEAXE: + ++bMouse; + break; + } + } + + pController->fGamePad = bGamePad != 0; + pController->fKeyboard = bKeyboard != 0; + pController->fMouse = bMouse != 0; + + return MAKELONG( MAKEWORD( bGamePad, bMouse ), MAKEWORD( bKeyboard, ( bMouse + bKeyboard + bGamePad ))); +} + + +// PrepareInputDevices rewritten --rabid +bool PrepareInputDevices() +{ + bool fKeyboard = false; + bool fMouse = false; + bool fGamePad = false; + + for( int i = 0; i < ARRAYSIZE( g_pcControllers ); ++i ) + { + fGamePad = false; + if( g_pcControllers[i].fPlugged ) + { + CountControllerStructDevs( &g_pcControllers[i] ); + + fKeyboard = g_pcControllers[i].fKeyboard != 0; + fMouse = g_pcControllers[i].fMouse != 0; + fGamePad = ( g_pcControllers[i].fGamePad != 0); // we'll assume for now that there's a gamepad to go with those buttons + } + + ReleaseEffect( g_apdiEffect[i] ); + if( g_pcControllers[i].guidFFDevice != GUID_NULL && GetInputDevice( g_strEmuInfo.hMainWindow, g_apFFDevice[i], g_pcControllers[i].guidFFDevice, DI8DEVTYPE_JOYSTICK, DIB_FF )) // not necessarily a joystick type device, but we don't use the data anyway + { + DIDEVICEINSTANCE diDev; + diDev.dwSize = sizeof( DIDEVICEINSTANCE ); + + g_apFFDevice[i]->GetDeviceInfo( &diDev ); + + if( !lstrcmp( diDev.tszProductName, _T( STRING_ADAPTOID ))) + { + g_pcControllers[i].fIsAdaptoid = true; + DebugWriteA("FF device on controller %d is of type Adaptoid\n", i+1); + } + else + { + g_pcControllers[i].fIsAdaptoid = false; + } + + if ( CreateEffectHandle( i, g_pcControllers[i].bRumbleTyp, g_pcControllers[i].bRumbleStrength ) ) + { + AcquireDevice( g_apFFDevice[i] ); + DebugWriteA("Got FF device %d\n", i); + } + else + DebugWriteA("Couldn't get FF device: CreateEffectHandle failed!\n"); + } + else + { + g_apFFDevice[i] = NULL; + DebugWriteA("Didn't get FF device %d\n", i); + } + } + + if( fMouse ) + { + if( !g_sysMouse.didHandle ) + { + if( GetInputDevice( g_strEmuInfo.hMainWindow, g_sysMouse.didHandle, GUID_SysMouse, DI8DEVTYPE_MOUSE, g_bExclusiveMouse ? DIB_MOUSE : DIB_KEYBOARD )) + { + AcquireDevice( g_sysMouse.didHandle ); + } + } + } + else + { + g_bExclusiveMouse = false; + } + + return true; +} + +bool IsAdaptoidCommandSupported( LPDIRECTINPUTDEVICE8 lpDirectInputDevice, DWORD cmd ) +{ + DIEFFESCAPE esc; + DWORD inbuf, outbuf; + HRESULT hr; + + esc.dwSize = sizeof(esc); + esc.dwCommand = ADAPT_TEST; // command to determine if a command is supported + esc.lpvInBuffer = &inbuf; + esc.cbInBuffer = 4; + esc.lpvOutBuffer = &outbuf; + esc.cbOutBuffer = 4; + inbuf = cmd; // command that we are asking is supported + outbuf = 0; + + hr = lpDirectInputDevice->Escape(&esc); + + return( SUCCEEDED(hr) && esc.cbOutBuffer == 4 && outbuf == 0xB0CAB0CA ); +} + +#ifdef _DEBUG +// Direct Adaptoid debugging stuff. +void _debugAd( LPCSTR szMessage, HRESULT res ) +{ + LPCSTR suc = (SUCCEEDED(res)) ? "OK" : "FAILED"; + + DebugWriteA( "%s: %s (RC:%08X)\n", szMessage, suc, res ); +} +#endif // #ifdef _DEBUG + +HRESULT DirectRumbleCommand( LPDIRECTINPUTDEVICE8 lpDirectInputDevice, DWORD cmd ) +{ + DIEFFESCAPE esc; + + esc.dwSize = sizeof(esc); + esc.dwCommand = ADAPT_RUMBLE; // send rumble command + esc.lpvInBuffer = &cmd; // 1=go, 0=stop + esc.cbInBuffer = 4; + esc.lpvOutBuffer = NULL; + esc.cbOutBuffer = 0; + + HRESULT hr = lpDirectInputDevice->Escape(&esc); + +#ifdef _DEBUG + _debugAd( "Direct Adaptoid RumbleCommand", hr ); +#endif // #ifdef _DEBUG + + return hr; +} + +HRESULT InitializeAdaptoid( LPDIRECTINPUTDEVICE8 lpDirectInputDevice, LPBYTE status ) +{ + DIEFFESCAPE esc; + + esc.dwSize = sizeof(esc); + esc.dwCommand = ADAPT_INIT; // Initialize Pak + esc.lpvInBuffer = NULL; + esc.cbInBuffer = 0; + esc.lpvOutBuffer = status; + esc.cbOutBuffer = 1; + + HRESULT hr = lpDirectInputDevice->Escape(&esc); + +#ifdef _DEBUG + _debugAd( "Direct Adaptoid InitPak", hr ); +#endif // #ifdef _DEBUG + + return hr; +} + +HRESULT ReadAdaptoidPak( LPDIRECTINPUTDEVICE8 lpDirectInputDevice, DWORD addr, LPBYTE data ) +{ + DIEFFESCAPE esc; + + esc.dwSize = sizeof(esc); + esc.dwCommand = ADAPT_READPAK; // Read 32 bytes from pak + esc.lpvInBuffer = &addr; + esc.cbInBuffer = 4; + esc.lpvOutBuffer = data; + esc.cbOutBuffer = 32; + + HRESULT hr = lpDirectInputDevice->Escape(&esc); + +#ifdef _DEBUG + LPCSTR suc = (SUCCEEDED(hr)) ? "OK" : "FAILED"; + + DebugWriteA( "Direct Adaptoid ReadPak(Addr:%04X): %s (RC:%08X)\n", addr, suc, hr ); +#endif // #ifdef _DEBUG + + return hr; +} + +HRESULT WriteAdaptoidPak( LPDIRECTINPUTDEVICE8 lpDirectInputDevice, DWORD addr, LPBYTE data ) +{ + DIEFFESCAPE esc; + struct + { + DWORD addr; + BYTE data[32]; + } buf; + + buf.addr = addr; + CopyMemory( buf.data, data, 32 ); + + esc.dwSize = sizeof(esc); + esc.dwCommand = ADAPT_WRITEPAK; // Write 32 bytes to pak + esc.lpvInBuffer = &buf; + esc.cbInBuffer = 36; + esc.lpvOutBuffer = NULL; + esc.cbOutBuffer = 0; + + HRESULT hr = lpDirectInputDevice->Escape(&esc); + +#ifdef _DEBUG + LPCSTR suc = (SUCCEEDED(hr)) ? "OK" : "FAILED"; + + DebugWriteA( "Direct Adaptoid WritePak(Addr:%04X): %s (RC:%08X)\n", addr, suc, hr ); +#endif // #ifdef _DEBUG + + return hr; +} + +BYTE GetAdaptoidStatus( LPDIRECTINPUTDEVICE8 lpDirectInputDevice ) +{ + HRESULT hr; + BYTE bStatus = 0; + hr = InitializeAdaptoid( lpDirectInputDevice, &bStatus ); + + int iRetrys = 10; + while( FAILED( hr ) && iRetrys > 0 ) + { + Sleep( 5 ); + hr = AcquireDevice( lpDirectInputDevice ); + hr = InitializeAdaptoid( lpDirectInputDevice, &bStatus ); + iRetrys--; + } + + return (SUCCEEDED(hr)) ? bStatus : RD_NOPLUGIN | RD_NOTINITIALIZED; +} + +// Fill the handle for g_sysMouse properly +void InitMouse() +{ + if (GetInputDevice( g_strEmuInfo.hMainWindow, g_sysMouse.didHandle, GUID_SysMouse, DI8DEVTYPE_MOUSE, DIB_KEYBOARD )) + { + g_sysMouse.guidInstance = GUID_SysMouse; + g_sysMouse.dwDevType = DI8DEVTYPE_MOUSE; + _tcsncpy(g_sysMouse.szProductName, STRING_GUID_SYSMOUSE, ARRAYSIZE(g_sysMouse.szProductName)); + } + else + g_sysMouse.didHandle = NULL; +} + +// treat btnButton as a b_Value, and return whether it is pressed or not +bool IsBtnPressed(BUTTON btnButton) +{ + long l_Value; + LPLONG plRawState = (LPLONG)&btnButton.parentDevice->stateAs.joyState; + + switch ( btnButton.bBtnType ) + { + case DT_JOYBUTTON: + return ( btnButton.parentDevice->stateAs.joyState.rgbButtons[btnButton.bOffset] & 0x80 ) != 0; + + case DT_JOYSLIDER: + case DT_JOYAXE: + l_Value = plRawState[btnButton.bOffset] - ZEROVALUE; + + if ( btnButton.bAxisID ) + return ( l_Value <= -ABSTHRESHOLD ); + else + return ( l_Value >= ABSTHRESHOLD ); + + case DT_JOYPOV: + return GetJoyPadPOV( (PDWORD)&plRawState[btnButton.bOffset] , btnButton.bAxisID ); + + case DT_KEYBUTTON: + return ( btnButton.parentDevice->stateAs.rgbButtons[btnButton.bOffset] & 0x80 ) != 0; + + case DT_MOUSEBUTTON: + return ( btnButton.parentDevice->stateAs.mouseState.rgbButtons[btnButton.bOffset] & 0x80 ) != 0; + + case DT_MOUSEAXE: + l_Value = MOUSEMOVE; // a.k.a. lvalue is button threshold + + if( btnButton.bAxisID ) + return ( ((LPLONG)(&btnButton.parentDevice->stateAs.mouseState))[btnButton.bOffset] < -l_Value ); + else + return ( ((LPLONG)(&btnButton.parentDevice->stateAs.mouseState))[btnButton.bOffset] > l_Value ); + break; + + case DT_UNASSIGNED: + default: + return false; + } +} diff --git a/Source/nragev20/DirectInput.h b/Source/nragev20/DirectInput.h new file mode 100644 index 000000000..efbc05ccb --- /dev/null +++ b/Source/nragev20/DirectInput.h @@ -0,0 +1,156 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _DIRECTINPUT_H_ +#define _DIRECTINPUT_H_ + +#include + +extern LPDIRECTINPUT8 g_pDIHandle; + + +bool InitDirectInput( HWND hWnd ); +void FreeDirectInput (); +bool PrepareInputDevices(); +void InitMouse(); +void GetDeviceDatas(); +bool GetNControllerInput ( const int indexController, LPDWORD pdwData ); + +BOOL CALLBACK EnumMakeDeviceList( LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef ); + +bool IsBtnPressed(BUTTON btnButton); +bool GetInputDevice( HWND hWnd, LPDIRECTINPUTDEVICE8 &lpDirectInputDevice, GUID gGuid, DWORD dwDevType, DWORD dwCooperativeLevel ); +void ReleaseDevice( LPDIRECTINPUTDEVICE8 &lpDirectInputDevice ); +bool CreateEffectHandle( HWND hWnd, LPDIRECTINPUTDEVICE8 lpDirectInputDevice, LPDIRECTINPUTEFFECT &pDIEffect, BYTE bRumbleTyp, long lStrength ); +void ReleaseEffect( LPDIRECTINPUTEFFECT &lpDirectEffect ); + + +BYTE GetAdaptoidStatus( LPDIRECTINPUTDEVICE8 lpDirectInputDevice ); +bool IsAdaptoidCommandSupported( LPDIRECTINPUTDEVICE8 lpDirectInputDevice, DWORD cmd ); +HRESULT DirectRumbleCommand( LPDIRECTINPUTDEVICE8 lpDirectInputDevice, DWORD cmd ); +HRESULT InitializeAdaptoid( LPDIRECTINPUTDEVICE8 lpDirectInputDevice, LPBYTE status ); +HRESULT ReadAdaptoidPak( LPDIRECTINPUTDEVICE8 lpDirectInputDevice, DWORD addr, LPBYTE data ); +HRESULT WriteAdaptoidPak( LPDIRECTINPUTDEVICE8 lpDirectInputDevice, DWORD addr, LPBYTE data ); + + +#define MINAXISVALUE -32767 +#define MAXAXISVALUE 32767 +#define ZEROVALUE 0 +#define THRESHOLD 90 +#define RANGERELATIVE (MAXAXISVALUE - ZEROVALUE + 1) +#define ABSTHRESHOLD (RANGERELATIVE * THRESHOLD / 100) + // plus or minus this many 1/100 degrees counts as GetJoyPadPOV being pressed +#define POVANGLETHRESH 5675 + +#define MOUSEMOVE 5 + // by default, scale the mouse input by this much +#define MOUSESCALEVALUE 10 + // percent to decay mouse buffer every frame. + // Tweak this from 0-100 to control how much the mouse drifts; values closer to 100 drift more, + // while values closer to 0 are very stiff (deadpan) and don't turn well +#define MOUSEBUFFERDECAY 80 + +#define N64DIVIDER 258 + + +#define DID_KEYBOARD 0 +#define DID_MOUSE 1 +#define DID_GAMEPAD 2 + +#define DIB_KEYBOARD DISCL_NONEXCLUSIVE | DISCL_FOREGROUND +#define DIB_MOUSE DISCL_EXCLUSIVE | DISCL_FOREGROUND +#define DIB_FF DISCL_EXCLUSIVE | DISCL_BACKGROUND +#define DIB_DEVICE DISCL_NONEXCLUSIVE | DISCL_BACKGROUND + +#define DIB_CONFIG DISCL_NONEXCLUSIVE | DISCL_BACKGROUND + +#define RUMBLE_NONE 0x00 +#define RUMBLE_CONSTANT 0x01 +#define RUMBLE_RAMP 0x02 +#define RUMBLE_CONDITION 0x04 +#define RUMBLE_PERIODIC 0x08 +#define RUMBLE_CUSTOM 0x10 + +#define RUMBLE_DIRECT 0x80 + +#define RUMBLE_EFF1 RUMBLE_CONSTANT +#define RUMBLE_EFF2 RUMBLE_RAMP +#define RUMBLE_EFF3 RUMBLE_DIRECT + + // Reported Name of the Adaptoid +#define STRING_ADAPTOID "Adaptoid" +#define STRING_GUID_SYSKEYBOARD _T("Keyboard") +#define STRING_GUID_SYSMOUSE _T("SysMouse") + + // Query API - pass in command #, returns 0xB0CAB0CA if supported +#define ADAPT_TEST 0x7834BB00 + // Send command to rumble pack (DWORD 0=stop, 1=go) +#define ADAPT_RUMBLE 0x7834BB08 + // Initialize pak (returns pak status bit flags) +#define ADAPT_INIT 0x7834BB0C + // Read from pak (reads 32 bytes of data) +#define ADAPT_READPAK 0x7834BB0D + // Write to pak (writes 32 bytes of data) +#define ADAPT_WRITEPAK 0x7834BB0E + // Send command directly to controller - synchronous +#define ADAPT_DIRECTCOMMAND 0x7834BB28 + +// The following inline functions are all overloads for existing functions +inline bool CreateEffectHandle( int iDevice, BYTE bRumbleTyp, long lStrength ) +{ + return CreateEffectHandle( g_strEmuInfo.hMainWindow, g_apFFDevice[iDevice], g_apdiEffect[iDevice], bRumbleTyp, lStrength ); +} + +// this used to exist, but it was only used once and makes things more confusing. Removed. --rabid +//inline void ReleaseEffect( int iEffect ) +//{ +// ReleaseEffect( g_apdiEffect[iEffect] ); +//} + +inline BYTE GetAdaptoidStatus( int iDevice ) +{ + return GetAdaptoidStatus( g_apFFDevice[iDevice] ); +} +inline HRESULT WriteAdaptoidPak( int iDevice, DWORD addr, LPBYTE data ) +{ + return WriteAdaptoidPak( g_apFFDevice[iDevice], addr, data ); +} +inline HRESULT ReadAdaptoidPak( int iDevice, DWORD addr, LPBYTE data ) +{ + return ReadAdaptoidPak( g_apFFDevice[iDevice], addr, data ); +} +inline HRESULT InitializeAdaptoid( int iDevice, LPBYTE status ) +{ + return InitializeAdaptoid( g_apFFDevice[iDevice], status ); +} +inline HRESULT DirectRumbleCommand( int iDevice, DWORD cmd ) +{ + return DirectRumbleCommand( g_apFFDevice[iDevice], cmd ); +} +inline bool IsAdaptoidCommandSupported( int iDevice, DWORD cmd ) +{ + return IsAdaptoidCommandSupported( g_apFFDevice[iDevice], cmd ); +} + + +#endif // #ifndef _DIRECTINPUT_H_ diff --git a/Source/nragev20/FileAccess.cpp b/Source/nragev20/FileAccess.cpp new file mode 100644 index 000000000..79ad98853 --- /dev/null +++ b/Source/nragev20/FileAccess.cpp @@ -0,0 +1,1681 @@ + /* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "commonIncludes.h" +#include +#include +#include +#include +#include +#include "NRagePluginV2.h" +#include "PakIO.h" +#include "Interface.h" +#include "FileAccess.h" +#include "DirectInput.h" +#include +using std::string; + +#ifndef IDR_PROFILE_DEFAULT1 +#define IDR_PROFILE_DEFAULT1 -1 +#endif +#ifndef IDR_PROFILE_DEFAULT2 +#define IDR_PROFILE_DEFAULT2 -1 +#endif +#ifndef IDR_PROFILE_DEFAULT3 +#define IDR_PROFILE_DEFAULT3 -1 +#endif +#ifndef IDR_PROFILE_DEFAULT4 +#define IDR_PROFILE_DEFAULT4 -1 +#endif + +void DumpStreams(FILE * fFile, string strMouse, string strDevs[], string strNull, bool bIsINI); +void DumpControllerSettings(FILE * fFile, int i, bool bIsINI); +void FormatControlsBlock(string * strMouse, string strDevs[], string * strNull, int i); +void FormatModifiersBlock(string * strMouse, string strDevs[], string * strNull, int i); + +// return true if the file exists... let's just use CreateFile with OPEN_EXISTING +bool CheckFileExists( LPCTSTR FileName ) +{ + HANDLE hFile = CreateFile(FileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE ) + { + return false; + } + else + { + CloseHandle(hFile); + return true; + } +} + +// A rather ugly function, but does its job. Called by LoadProfile and LoadProfileFromResource. +// Parses the config data that gets written to profile files. +// returns: +// PL_CATEGORY and removes the brackets if the line looks like a keymapping +// PL_VERSIONSTRING and returns the version number if it's a version line +// for other cases, another PL return value and truncates before the equal sign; so strings like "Button=blah" -> "blah" +// TODO: Perhaps buffer overflow and crash potential here... needs auditing +DWORD ParseLine( LPSTR pszLine ) +{ + DWORD dwReturn = PL_NOHIT; + char *pChar = pszLine; + + switch (pszLine[0]) + { + case '\0': // shortcut out on null string + case '#': // # indicates comment line + return PL_NOHIT; + case '[': + while( *pChar != ']' && *pChar != '\0' ) + { + *pChar = toupper(*pChar); + ++pChar; + } + if( *pChar == ']' ) + { + MoveMemory( pszLine, pszLine+1, (pChar-pszLine) - 1 * sizeof(pszLine[0]) ); // TODO: please double check this --rabid + *(pChar - 1) = '\0'; // since we moved everything back one character, we need to change this ref as well + return PL_CATEGORY; + } + else + return PL_NOHIT; // an open bracket with no closing returns nohit + case '@': + switch( djbHash(pszLine)) // the hash check is case sensitive, and includes the @ symbol + { + case CHK_PROFILEVERSION20: + lstrcpyA( pszLine, "2.0" ); + return PL_VERSIONSTRING; + case CHK_PROFILEVERSION21: + lstrcpyA( pszLine, "2.1" ); + return PL_VERSIONSTRING; + case CHK_PROFILEVERSION22: + lstrcpyA( pszLine, "2.2" ); + return PL_VERSIONSTRING; + default: + DebugWriteA("Unknown version string found with hash %u: %s\n", djbHash(pszLine), pszLine); + return PL_NOHIT; + } // end switch (dbjHash(pszLine)) + // default: keep running + } + + pChar = strchr(pszLine, '='); + + if( !pChar ) // no = sign + { + return PL_NOHIT; + } + else // there is an '=' sign + { + // We hash the string. If the hash matches the hash of one of our targets, we compare strings to verify. + // If we don't use hashes, we have to compare vs a LOT of strings. + *pChar = '\0'; // truncate at the '=' for now + for (char *pIter = pszLine; *pIter; pIter++) + *pIter = toupper(*pIter); + dwReturn = djbHash(pszLine); + + pChar++; + + MoveMemory( pszLine, pChar, (lstrlenA(pChar) + 1) * sizeof(pszLine[0]) ); // change string to match what's to the right of '=' + } + + return dwReturn; +} + +// Called immediately after ParseLine to assign values based on whatever the keyname was +// notes: pszFFDevice may be overwritten with whatever is in pszLine; please make sure pszLine is not too big! +bool ProcessKey( DWORD dwKey, DWORD dwSection, LPCSTR pszLine, LPTSTR pszFFDevice, LPBYTE bFFDeviceNr, bool bIsInterface ) +{ + static TCHAR pszDeviceName[MAX_PATH]; + static BYTE bDeviceNr = 0; + static GUID gGUID; + + bool bReturn = true; + LPCONTROLLER pController = NULL; // used when we're assigning things in the [Controller X] category + LPSHORTCUTS pShortcuts = NULL; + unsigned int iLength = lstrlenA( pszLine ) / 2; // 2 HEX characters correspond to one BYTE; thus iLength represents the length of pszLine after conversion to BYTEs + + switch (dwSection) + { + case CHK_CONTROLLER_1: + if (bIsInterface) + pController = &(g_ivConfig->Controllers[0]); + else + pController = &(g_pcControllers[0]); + break; + case CHK_CONTROLLER_2: + if (bIsInterface) + pController = &(g_ivConfig->Controllers[1]); + else + pController = &(g_pcControllers[1]); + break; + case CHK_CONTROLLER_3: + if (bIsInterface) + pController = &(g_ivConfig->Controllers[2]); + else + pController = &(g_pcControllers[2]); + break; + case CHK_CONTROLLER_4: + if (bIsInterface) + pController = &(g_ivConfig->Controllers[3]); + else + pController = &(g_pcControllers[3]); + break; + case CHK_SHORTCUTS: + if (bIsInterface) + pShortcuts = &(g_ivConfig->Shortcuts); + else + pShortcuts = &g_scShortcuts; + break; + } + + switch( dwKey ) + { + case PL_RESET: + ZeroMemory( pszDeviceName, sizeof(pszDeviceName) ); + gGUID = GUID_NULL; + bDeviceNr = 0; + break; + + case CHK_LANGUAGE: + if (dwSection == CHK_GENERAL) + if (bIsInterface) + g_ivConfig->Language = atoi(pszLine); + else + g_strEmuInfo.Language = atoi(pszLine); + break; + case CHK_SHOWMESSAGES: + if (dwSection == CHK_GENERAL) + if (bIsInterface) + g_ivConfig->fDisplayShortPop = (atoi(pszLine) != 0); + else + g_strEmuInfo.fDisplayShortPop = (atoi(pszLine) != 0); + break; + + case CHK_MEMPAK: + if (dwSection == CHK_LASTBROWSERDIR) + CHAR_TO_TCHAR(g_aszLastBrowse[BF_MEMPAK], pszLine, MAX_PATH); + else if (dwSection == CHK_FOLDERS) + CHAR_TO_TCHAR(g_aszDefFolders[BF_MEMPAK], pszLine, MAX_PATH); + break; + case CHK_GBXROM: + if (dwSection == CHK_LASTBROWSERDIR) + CHAR_TO_TCHAR(g_aszLastBrowse[BF_GBROM], pszLine, MAX_PATH); + else if (dwSection == CHK_FOLDERS) + CHAR_TO_TCHAR(g_aszDefFolders[BF_GBROM], pszLine, MAX_PATH); + break; + case CHK_GBXSAVE: + if (dwSection == CHK_LASTBROWSERDIR) + CHAR_TO_TCHAR(g_aszLastBrowse[BF_GBSAVE], pszLine, MAX_PATH); + else if (dwSection == CHK_FOLDERS) + CHAR_TO_TCHAR(g_aszDefFolders[BF_GBSAVE], pszLine, MAX_PATH); + break; + case CHK_PROFILE: + if (dwSection == CHK_LASTBROWSERDIR) + CHAR_TO_TCHAR(g_aszLastBrowse[BF_PROFILE], pszLine, MAX_PATH); + break; + case CHK_NOTE: + if (dwSection == CHK_LASTBROWSERDIR) + CHAR_TO_TCHAR(g_aszLastBrowse[BF_NOTE], pszLine, MAX_PATH); + break; + case CHK_SHORTCUTS: + if (dwSection == CHK_LASTBROWSERDIR) + CHAR_TO_TCHAR(g_aszLastBrowse[BF_SHORTCUTS], pszLine, MAX_PATH); + break; + case CHK_PLUGGED: + if (pController) + pController->fPlugged = atoi(pszLine); + break; + case CHK_RAWDATA: + if (pController) + pController->fRawData = atoi(pszLine); + break; + case CHK_XINPUT: + if (pController) + pController->fXInput = atoi(pszLine); + break; + case CHK_PAKTYPE: + if (pController) + pController->PakType = atoi(pszLine); + break; + case CHK_REALN64RANGE: + if (pController) + pController->fRealN64Range = atoi(pszLine); + break; + case CHK_RAPIDFIREENABLED: + if (pController) + pController->bRapidFireEnabled = atoi(pszLine) != 0; + break; + case CHK_RAPIDFIRERATE: + if (pController) + pController->bRapidFireRate = atoi(pszLine); + break; + case CHK_STICKRANGE: + if (pController) + pController->bStickRange = atoi(pszLine); + break; + case CHK_MOUSEMOVEX: + if (pController) + pController->bMouseMoveX = atoi(pszLine); + break; + case CHK_MOUSEMOVEY: + if (pController) + pController->bMouseMoveY = atoi(pszLine); + break; + case CHK_AXISSET: + if (pController) + pController->bAxisSet = atoi(pszLine); + break; + case CHK_KEYABSOLUTEX: + if (pController) + pController->fKeyAbsoluteX = atoi(pszLine); + break; + case CHK_KEYABSOLUTEY: + if (pController) + pController->fKeyAbsoluteY = atoi(pszLine); + break; + case CHK_PADDEADZONE: + if (pController) + pController->bPadDeadZone = atoi(pszLine); + break; + case CHK_MOUSESENSITIVITYX: + if (pController) + pController->wMouseSensitivityX = atoi(pszLine); + break; + case CHK_MOUSESENSITIVITYY: + if (pController) + pController->wMouseSensitivityY = atoi(pszLine); + break; + case CHK_RUMBLETYPE: + if (pController) + pController->bRumbleTyp = atoi(pszLine); + break; + case CHK_RUMBLESTRENGTH: + if (pController) + pController->bRumbleStrength = atoi(pszLine); + break; + case CHK_VISUALRUMBLE: + if (pController) + pController->fVisualRumble = atoi(pszLine); + break; + case CHK_FFDEVICEGUID: + if (pController) + { + bReturn = StringtoGUIDA(&pController->guidFFDevice, pszLine); + if (bIsInterface && bReturn) + { + // For some reason, we use ONLY device names and numbers inside the interface for FF device selection. So if we don't set those, + // FFDevice won't load properly. + int nDevice = FindDeviceinList(pController->guidFFDevice); + if (nDevice != -1 && pszFFDevice && bFFDeviceNr) + { + _tcsncpy(pszFFDevice, g_devList[nDevice].szProductName, DEFAULT_BUFFER); + *bFFDeviceNr = g_devList[nDevice].bProductCounter; + } + else + { + pController->guidFFDevice = GUID_NULL; + return false; + } + } + else + return bReturn; + } + break; + case CHK_FFDEVICENAME: + if( pController && pszFFDevice ) + { + CHAR_TO_TCHAR( pszFFDevice, pszLine, MAX_PATH ); // HACK: pszLine is read from a file; could overflow easily. guessed size of pszFFDevice buffer. + return true; + } + break; + + case CHK_FFDEVICENR: + if( pController && bFFDeviceNr && ( iLength >= sizeof(BYTE) )) + { + *bFFDeviceNr = atoi( pszLine ); + return true; + } + break; + case CHK_MEMPAKFILE: + if( pController ) + { + CHAR_TO_TCHAR( pController->szMempakFile, pszLine, MAX_PATH ); + } + break; + case CHK_GBROMFILE: + if( pController ) + { + CHAR_TO_TCHAR( pController->szTransferRom, pszLine, MAX_PATH ); + } + break; + case CHK_GBROMSAVE: + if( pController ) + { + CHAR_TO_TCHAR( pController->szTransferSave, pszLine, MAX_PATH ); + } + break; + + case CHK_DINPUTNAME: + gGUID = GUID_NULL; // invalidate current GUID + CHAR_TO_TCHAR( pszDeviceName, pszLine, MAX_PATH ); + break; + + case CHK_DINPUTNR: + gGUID = GUID_NULL; // invalidate current GUID + if( iLength >= sizeof(BYTE) ) + { + TexttoHexA( pszLine, &bDeviceNr, sizeof(BYTE) ); + } + break; + case CHK_DINPUTGUID: + if (StringtoGUIDA(&gGUID, pszLine)) + return true; + else + { + gGUID = GUID_NULL; // invalidate current GUID + return false; + } + break; + + case CHK_BUTTON: + if ( dwSection == CHK_CONTROLS || pShortcuts || pController ) + { + int controlnum = 0, buttonID = 0; + BUTTON btnWorking; + + ZeroMemory(&btnWorking, sizeof(btnWorking)); + + unsigned int tOffset, tAxisID, tBtnType; + + if (sscanf(pszLine, "%d %d %x %u %u", &controlnum, &buttonID, &tOffset, &tAxisID, &tBtnType) != 5) + return false; + + // done to overcome issues with sscanf and "small" data blocks + btnWorking.bOffset = tOffset; + btnWorking.bAxisID = tAxisID; + btnWorking.bBtnType = tBtnType; + + if (pController) + { + // special case: if we're in one of the categories CHK_CONTROLLER_n, assume we're processing a Profile file. + // Ignore the read controlnum and use our input controller number. + controlnum = (int)(dwSection - CHK_CONTROLLER_1); // HACK: assume our hash reproduces these linearly + } + + // Now we need to assign parentdevice. If we have a valid gGUID, we'll use that... + int found = FindDeviceinList(gGUID); + if (found != -1) + btnWorking.parentDevice = &g_devList[found]; + else + { + // ... otherwise, we do the following in order: + // 1. If bBtnType is of type DT_MOUSEBUTTON or DT_MOUSEAXE, set gGUID to that of g_sysMouse (ignoring the given name and number) + if ( btnWorking.bBtnType == DT_MOUSEBUTTON || btnWorking.bBtnType == DT_MOUSEAXE ) + { + btnWorking.parentDevice = &g_sysMouse; + } + // 2. If bBtnType is of type DT_KEYBUTTON, set gGUID to that of SysKeyboard + else if ( btnWorking.bBtnType == DT_KEYBUTTON ) + { + gGUID = GUID_SysKeyboard; + found = FindDeviceinList(gGUID); + if (found != -1) + btnWorking.parentDevice = &g_devList[found]; + else + btnWorking.parentDevice = NULL; + } + // 3. otherwise, look up the name and number using FindDeviceinList, and set gGUID to that + else + { + found = FindDeviceinList(pszDeviceName, bDeviceNr, true); + if (found != -1) + { + gGUID = g_devList[found].guidInstance; + btnWorking.parentDevice = &g_devList[found]; + } + else + { + DebugWrite(_T("ProcessKey: couldn't find a device in g_devList for %s %d\n"), pszDeviceName, bDeviceNr); + gGUID = GUID_NULL; + btnWorking.parentDevice = NULL; + return false; + } + } + } + + if (pShortcuts) + { + // bounds check on controlnum and buttonID + if ( (controlnum == -1 && buttonID != 0) && ((controlnum < 0) || (controlnum > 3) || (buttonID < 0) || (buttonID >= SC_TOTAL)) ) + { + gGUID = GUID_NULL; // since we may have cached an invalid GUID, invalidate it + return false; + } + + // Copy the completed button to the correct shortcut + if (bIsInterface) + if (controlnum == -1) + g_ivConfig->Shortcuts.bMouseLock = btnWorking; + else + g_ivConfig->Shortcuts.Player[controlnum].aButtons[buttonID] = btnWorking; + else // if (!bIsInterface) + if (controlnum == -1) + g_scShortcuts.bMouseLock = btnWorking; + else + g_scShortcuts.Player[controlnum].aButtons[buttonID] = btnWorking; + } + else // it's a controller button + { + // bounds check on controlnum and buttonID + if ( (controlnum < 0) || (controlnum > 3) || (buttonID < 0) || (buttonID >= ARRAYSIZE(g_pcControllers[0].aButton)) ) + { + gGUID = GUID_NULL; // since we may have cached an invalid GUID, invalidate it + return false; + } + + // Copy the completed button to the correct controller and buttonID + if (bIsInterface) + g_ivConfig->Controllers[controlnum].aButton[buttonID] = btnWorking; + else + g_pcControllers[controlnum].aButton[buttonID] = btnWorking; + } + } + break; + + case CHK_MODIFIER: + // Modifiers format: controlnum bOffset bAxisID bBtnType bModType fToggle fStatus dwSpecific + if ( dwSection == CHK_MODIFIERS || pController ) + { + int controlnum = 0; + MODIFIER modWorking; + + ZeroMemory(&modWorking, sizeof(modWorking)); + + unsigned int tOffset, tAxisID, tBtnType, tModType, tToggle, tStatus, tSpecific; + + if (sscanf(pszLine, "%u %x %u %u %u %u %u %x", &controlnum, &tOffset, &tAxisID, + &tBtnType, &tModType, &tToggle, &tStatus, &tSpecific) != 8) + return false; + + // done to overcome issues with sscanf and "small" data blocks + modWorking.btnButton.bOffset = tOffset; + modWorking.btnButton.bAxisID = tAxisID; + modWorking.btnButton.bBtnType = tBtnType; + modWorking.bModType = tModType; + modWorking.fToggle = tToggle; + modWorking.fStatus = tStatus; + modWorking.dwSpecific = tSpecific; // looks stupid, but unsigned int might not always be DWORD32 + + // Now we need to assign parentdevice. If we have a valid gGUID, we'll use that... + int found = FindDeviceinList(gGUID); + if (found != -1) + modWorking.btnButton.parentDevice = &g_devList[found]; + else + { + // ... otherwise, we do the following in order: + // 1. If bBtnType is of type DT_MOUSEBUTTON or DT_MOUSEAXE, set gGUID to that of g_sysMouse (ignoring the given name and number) + if ( modWorking.btnButton.bBtnType == DT_MOUSEBUTTON || modWorking.btnButton.bBtnType == DT_MOUSEAXE ) + { + modWorking.btnButton.parentDevice = &g_sysMouse; + } + // 2. If bBtnType is of type DT_KEYBUTTON, set gGUID to that of SysKeyboard + else if ( modWorking.btnButton.bBtnType == DT_KEYBUTTON ) + { + gGUID = GUID_SysKeyboard; + int found = FindDeviceinList(gGUID); + if (found != -1) + modWorking.btnButton.parentDevice = &g_devList[found]; + else + modWorking.btnButton.parentDevice = NULL; + } + // 3. otherwise, look up the name and number using FindDeviceinList, and set gGUID to that + else + { + found = FindDeviceinList(pszDeviceName, bDeviceNr, true); + if (found != -1) + { + gGUID = g_devList[found].guidInstance; + modWorking.btnButton.parentDevice = &g_devList[found]; + } + else + { + DebugWrite(_T("ProcessKey: couldn't find a device in g_devList for %s %d\n"), pszDeviceName, bDeviceNr); + gGUID = GUID_NULL; + modWorking.btnButton.parentDevice = NULL; + return false; + } + } + } + + // bounds check on controlnum and buttonID + if ( (controlnum < 0) || (controlnum > 3) ) + { + gGUID = GUID_NULL; // since we may have cached an invalid GUID, invalidate it + return false; + } + + // Allocate and add the completed modifier + if (bIsInterface) + { + if (g_ivConfig->Controllers[controlnum].nModifiers > 0) + { + g_ivConfig->Controllers[controlnum].pModifiers = (LPMODIFIER)P_realloc(g_ivConfig->Controllers[controlnum].pModifiers, (g_ivConfig->Controllers[controlnum].nModifiers + 1) * sizeof(MODIFIER)); + } + else + { + g_ivConfig->Controllers[controlnum].pModifiers = (LPMODIFIER)P_malloc( sizeof(MODIFIER)); + } + g_ivConfig->Controllers[controlnum].pModifiers[g_ivConfig->Controllers[controlnum].nModifiers] = modWorking; + (g_ivConfig->Controllers[controlnum].nModifiers)++; + } + else + { + if (g_pcControllers[controlnum].nModifiers > 0) + { + g_pcControllers[controlnum].pModifiers = (LPMODIFIER)P_realloc(g_pcControllers[controlnum].pModifiers, (g_pcControllers[controlnum].nModifiers + 1) * sizeof(MODIFIER)); + } + else + { + g_pcControllers[controlnum].pModifiers = (LPMODIFIER)P_malloc( sizeof(MODIFIER)); + } + g_pcControllers[controlnum].pModifiers[g_pcControllers[controlnum].nModifiers] = modWorking; + (g_pcControllers[controlnum].nModifiers)++; + } + + } + break; + + } + + return bReturn; +} + +/****************** +Load the default profile from the raw "resource" data (i.e. the builtin defaults contained in the dll) +******************/ +bool LoadProfileFromResource( LPCTSTR pszResource, int iController, bool bIsInterface ) +{ + const DWORD dwControllerSect[] = { CHK_CONTROLLER_1 , CHK_CONTROLLER_2, CHK_CONTROLLER_3, CHK_CONTROLLER_4 }; + if( iController > 3 || iController < 0 ) + return false; + HRSRC res = FindResource( g_strEmuInfo.hinst, pszResource, _T("PROFILE") ); + if( res == NULL ) + return false; + char *profile = (char*)LockResource( LoadResource( g_strEmuInfo.hinst, res )); + char *profileend = profile + SizeofResource( g_strEmuInfo.hinst, res ); + + ProcessKey( PL_RESET, 0, 0, 0, 0, bIsInterface ); + DWORD dwCommand = PL_NOHIT; + char szLine[4096]; + while( profile < profileend ) + { + while( profile < profileend && (CHECK_WHITESPACES( *profile ) || *profile == ' ' )) + ++profile; + int i = 0; + while( profile < profileend && i < sizeof(szLine)-1 && !(CHECK_WHITESPACES( *profile )) ) + szLine[i++] = *profile++; + + szLine[i] = '\0'; + dwCommand = ParseLine( szLine ); + ProcessKey( dwCommand, dwControllerSect[iController], szLine, 0, 0, bIsInterface ); // resource will not contain a FF device + } + return true; +} + +/****************** +See overloaded function above +******************/ +bool LoadProfileFromResource( int indexController, bool bIsInterface ) +{ + const int resIds[] = { IDR_PROFILE_DEFAULT1, IDR_PROFILE_DEFAULT2, IDR_PROFILE_DEFAULT3, IDR_PROFILE_DEFAULT4 }; + + TCHAR szId[20]; + wsprintf( szId, _T("#%i"), resIds[indexController] ); + return LoadProfileFromResource( szId, indexController, bIsInterface ); +} + +// Load a controller profile from a saved configuration file +// need to incorporate type (keyb/mouse/joy), GUID for joy, and bOffset +bool LoadProfileFile( const TCHAR *pszFileName, int iController, TCHAR *pszFFDevice, BYTE *bFFDeviceNr ) +{ + const DWORD dwControllerSect[] = { CHK_CONTROLLER_1 , CHK_CONTROLLER_2, CHK_CONTROLLER_3, CHK_CONTROLLER_4 }; + FILE *proFile = NULL; + char szLine[4096]; + int iVersion = 0; + + if ( (proFile = _tfopen(pszFileName, _T("rS")) ) == NULL) + return false; + + // Test if right Version + while( !iVersion && ( fgets(szLine, sizeof(szLine) - 1, proFile) ) ) + { + szLine[strlen(szLine) - 1] = '\0'; // remove newline + if( ParseLine( szLine ) == PL_VERSIONSTRING ) + iVersion = (int)(atof( szLine ) * 100); + } + if( iVersion != 220 ) // HACK: this should probably not be a hardcoded value + { + fclose(proFile); + return false; + } + + SetControllerDefaults( &(g_ivConfig->Controllers[iController]) ); + pszFFDevice[0] = pszFFDevice[1] = '\0'; + *bFFDeviceNr = 0; + + ProcessKey( PL_RESET, 0, 0, 0, 0, true ); + DWORD dwCommand = PL_NOHIT; + while( fgets(szLine, sizeof(szLine) - 1, proFile) ) + { + szLine[strlen(szLine) - 1] = '\0'; // remove newline + dwCommand = ParseLine( szLine ); + ProcessKey( dwCommand, dwControllerSect[iController], szLine, pszFFDevice, bFFDeviceNr, true ); + } + + fclose(proFile); + + return true; +} + +// Load a controller profile from a saved configuration file +// need to incorporate type (keyb/mouse/joy), GUID for joy, and bOffset +bool LoadShortcutsFile( const TCHAR *pszFileName ) +{ + FILE *fShortsFile = NULL; + char szLine[4096]; + int iVersion = 0; + + if ( (fShortsFile = _tfopen(pszFileName, _T("rS")) ) == NULL) + return false; + + // Test if right Version + while( !iVersion && ( fgets(szLine, sizeof(szLine) - 1, fShortsFile) ) ) + { + szLine[strlen(szLine) - 1] = '\0'; // remove newline + if( ParseLine( szLine ) == PL_VERSIONSTRING ) + iVersion = (int)(atof( szLine ) * 100); + } + if( iVersion != 220 ) // HACK: this should probably not be a hardcoded value + { + fclose(fShortsFile); + return false; + } + + ZeroMemory( &(g_ivConfig->Shortcuts), sizeof(SHORTCUTS) ); + + ProcessKey( PL_RESET, 0, 0, 0, 0, true ); + DWORD dwCommand = PL_NOHIT; + while( fgets(szLine, sizeof(szLine) - 1, fShortsFile) ) + { + szLine[strlen(szLine) - 1] = '\0'; // remove newline + dwCommand = ParseLine( szLine ); + ProcessKey( dwCommand, CHK_SHORTCUTS, szLine, 0, 0, true ); + } + + fclose(fShortsFile); + + return true; +} + +// Serializes the profile for the CURRENT controller for saving to a file +// called in one place, from within Interface.cpp, ControllerTabProc (when you click "Save Profile") +void FormatProfileBlock( FILE * fFile, const int i ) +{ + DumpControllerSettings(fFile, i, false); + + string strMouse; + string strDevs[MAX_DEVICES]; + string strNull; + + FormatControlsBlock(&strMouse, strDevs, &strNull, i); + + DumpStreams(fFile, strMouse, strDevs, strNull, false); + + strMouse.clear(); + for (int j = 0; j < g_nDevices; j++) + strDevs[j].clear(); + strNull.clear(); + + FormatModifiersBlock(&strMouse, strDevs, &strNull, i); + + DumpStreams(fFile, strMouse, strDevs, strNull, false); +} + +// same as FormatProfileBlock, but saves shortcuts instead +void FormatShortcutsBlock(FILE * fFile, bool bIsINI) +{ + // I'm going to use STL strings here because I don't want to screw with buffer management + string strMouse; + string strDevs[MAX_DEVICES]; + string strNull; + + for ( int i = 0; i < 4; i++ ) // Player for + { + for ( int j = 0; j < SC_TOTAL; j++ ) // aButtons for + { + if (g_ivConfig->Shortcuts.Player[i].aButtons[j].parentDevice) // possibly unbound + { + if ( IsEqualGUID(g_sysMouse.guidInstance, g_ivConfig->Shortcuts.Player[i].aButtons[j].parentDevice->guidInstance) ) + { + char szBuf[DEFAULT_BUFFER]; + // add to the mouse stream + sprintf(szBuf, STRING_INI_BUTTON "=%d %d %02X %d %d\n", i, j, g_ivConfig->Shortcuts.Player[i].aButtons[j].bOffset, g_ivConfig->Shortcuts.Player[i].aButtons[j].bAxisID, g_ivConfig->Shortcuts.Player[i].aButtons[j].bBtnType); + strMouse.append(szBuf); + } + else + for (int match = 0; match < g_nDevices; match++) + if ( IsEqualGUID(g_devList[match].guidInstance, g_ivConfig->Shortcuts.Player[i].aButtons[j].parentDevice->guidInstance) ) + { + char szBuf[DEFAULT_BUFFER]; + // add to the appropriate device stream + sprintf(szBuf, STRING_INI_BUTTON "=%d %d %02X %d %d\n", i, j, g_ivConfig->Shortcuts.Player[i].aButtons[j].bOffset, g_ivConfig->Shortcuts.Player[i].aButtons[j].bAxisID, g_ivConfig->Shortcuts.Player[i].aButtons[j].bBtnType); + strDevs[match].append(szBuf); + break; + } + } + } // end buttons for + } // end Player for + + // gotta do it again for that one pesky mouselock button + if (g_ivConfig->Shortcuts.bMouseLock.parentDevice) // possibly unbound + { + if ( IsEqualGUID(g_sysMouse.guidInstance, g_ivConfig->Shortcuts.bMouseLock.parentDevice->guidInstance) ) + { + char szBuf[DEFAULT_BUFFER]; + // add to the mouse stream + sprintf(szBuf, STRING_INI_BUTTON "=%d %d %02X %d %d\n", -1, 0, g_ivConfig->Shortcuts.bMouseLock.bOffset, g_ivConfig->Shortcuts.bMouseLock.bAxisID, g_ivConfig->Shortcuts.bMouseLock.bBtnType); + strMouse.append(szBuf); + } + else + for (int match = 0; match < g_nDevices; match++) + if ( IsEqualGUID(g_devList[match].guidInstance, g_ivConfig->Shortcuts.bMouseLock.parentDevice->guidInstance) ) + { + char szBuf[DEFAULT_BUFFER]; + // add to the appropriate device stream + sprintf(szBuf, STRING_INI_BUTTON "=%d %d %02X %d %d\n", -1, 0, g_ivConfig->Shortcuts.bMouseLock.bOffset, g_ivConfig->Shortcuts.bMouseLock.bAxisID, g_ivConfig->Shortcuts.bMouseLock.bBtnType); + strDevs[match].append(szBuf); + break; + } + } // end shortcuts edge case + + DumpStreams(fFile, strMouse, strDevs, strNull, bIsINI); +} + +// load shortcuts from "resources", i.e. builtin defaults +bool LoadShortcutsFromResource(bool bIsInterface) +{ + if (bIsInterface) + ZeroMemory( &(g_ivConfig->Shortcuts), sizeof(SHORTCUTS) ); + TCHAR szId[20]; + wsprintf( szId, _T("#%i"), IDR_SHORTCUTS_DEFAULT ); + HRSRC res = FindResource( g_strEmuInfo.hinst, szId, _T("SHORTCUT") ); + if( res == NULL ) + return false; + char *profile = (char*)LockResource( LoadResource( g_strEmuInfo.hinst, res )); + char *profileend = profile + SizeofResource( g_strEmuInfo.hinst, res ); + + ProcessKey( PL_RESET, 0, 0, 0, 0, bIsInterface ); + DWORD dwCommand = PL_NOHIT; + char szLine[4096]; + while( profile < profileend ) + { + while( profile < profileend && (CHECK_WHITESPACES( *profile ) || *profile == ' ' )) + ++profile; + int i = 0; + while( profile < profileend && i < sizeof(szLine)-1 && !(CHECK_WHITESPACES( *profile )) ) + szLine[i++] = *profile++; + + szLine[i] = '\0'; + dwCommand = ParseLine( szLine ); + ProcessKey( dwCommand, CHK_SHORTCUTS, szLine, 0, 0, bIsInterface ); + } + return true; + +} + +// returns the user-chosen default directory (path) for each of the following: +// application dir, mempak dir, gameboy rom dir, gameboyrom save dir +// Tries to query user settings; if blank or invalid, returns their defaults +// Massages the output directory a bit +bool GetDirectory( LPTSTR pszDirectory, WORD wDirID ) +{ + bool bReturn = true; + TCHAR szBuffer[MAX_PATH + 1]; + const TCHAR szDefaultStrings[3][DEFAULT_BUFFER] = { STRING_DEF_MEMPAKFILE, STRING_DEF_GBROMFILE, STRING_DEF_GBROMSAVE }; + TCHAR *pSlash; + + pszDirectory[0] = pszDirectory[1] = '\0'; + + switch( wDirID ) + { + case DIRECTORY_MEMPAK: + case DIRECTORY_GBROMS: + case DIRECTORY_GBSAVES: + if (g_aszDefFolders[wDirID][0] == 0) + lstrcpyn( pszDirectory, szDefaultStrings[wDirID], MAX_PATH); + else + lstrcpyn( pszDirectory, g_aszDefFolders[wDirID], MAX_PATH); + break; + + case DIRECTORY_DLL: + if (GetModuleFileName(g_strEmuInfo.hinst, szBuffer, MAX_PATH)) + { + GetFullPathName( szBuffer, MAX_PATH, pszDirectory, &pSlash ); + *pSlash = 0; + } + break; + case DIRECTORY_APPLICATION: + break; + + default: + // we don't know what the hell you're talking about, set pszFileName to current .exe directory + // and return false + bReturn = false; + } + + if( pszDirectory[1] == ':' || ( pszDirectory[1] == '\\' && pszDirectory[0] == '\\' )) // Absolute Path( x: or \\ ) + lstrcpyn( szBuffer, pszDirectory, MAX_PATH ); + else + { + GetModuleFileName( NULL, szBuffer, MAX_PATH ); + pSlash = _tcsrchr( szBuffer, '\\' ); + ++pSlash; + lstrcpyn( pSlash, pszDirectory, MAX_PATH ); + } + GetFullPathName( szBuffer, MAX_PATH, pszDirectory, &pSlash ); + + pSlash = &pszDirectory[lstrlen( pszDirectory ) - 1]; + if( *pSlash != '\\' ) + { + pSlash[1] = '\\'; + pSlash[2] = '\0'; + } + + return bReturn; +} + +// Attempts to store the "absolute" filename for a file; +// if szFileName is an absolute filename (starting with a letter and colon or two backslashes) it is simply copied +// otherwise, it is concatenated with the known directory, such as mempak directory (type given by wDirID) +void GetAbsoluteFileName( TCHAR *szAbsolute, const TCHAR *szFileName, const WORD wDirID ) +{ + if( szFileName[1] == ':' || (szFileName[1] == '\\' && szFileName[0] == '\\')) + lstrcpyn( szAbsolute, szFileName, MAX_PATH ); + else + { + GetDirectory( szAbsolute, wDirID ); + lstrcat( szAbsolute, szFileName); // HACK: possible buffer overflow + } +} + +// Populates the list of mempak/transfer pak files from the config'd directory +BOOL SendFilestoList( HWND hDlgItem, WORD wType ) +{ + HANDLE hFindFile; + + WIN32_FIND_DATA FindFile; + TCHAR szPattern[MAX_PATH + 10]; + TCHAR *pszExtensions; + BOOL Success; + + switch( wType ) + { + case FILIST_MEM: + GetDirectory( szPattern, DIRECTORY_MEMPAK ); + lstrcat( szPattern, _T("*.*") ); + pszExtensions = _T(".mpk\0.n64\0"); + break; + case FILIST_TRANSFER: + GetDirectory( szPattern, DIRECTORY_GBROMS ); + lstrcat( szPattern, _T("*.gb?") ); + pszExtensions = _T(".gb\0.gbc\0"); + break; + default: + return FALSE; + } + + TCHAR *pcPoint; + TCHAR *pszExt; + bool bValidFile; + + hFindFile = FindFirstFile( szPattern, &FindFile ); + if( hFindFile != INVALID_HANDLE_VALUE ) + { + do + { + pszExt = pszExtensions; + pcPoint = _tcsrchr( FindFile.cFileName, _T('.') ); + bValidFile = false; + do + { + if( !lstrcmpi( pcPoint, pszExt )) + bValidFile = true; + pszExt += lstrlen( pszExt ) + 1; + } + while( *pszExt && !bValidFile ); + + if( bValidFile ) + SendMessage( hDlgItem, LB_ADDSTRING, 0, (LPARAM)FindFile.cFileName ); + } + while( FindNextFile( hFindFile, &FindFile )); + FindClose( hFindFile ); + Success = TRUE; + } + else + Success = FALSE; + + return Success; +} + +bool BrowseFolders( HWND hwndParent, TCHAR *pszHeader, TCHAR *pszDirectory ) +{ + ITEMIDLIST *piStart = NULL; + + if( pszDirectory[0] != '\0') + { + IShellFolder* pDesktopFolder; + if( SUCCEEDED( SHGetDesktopFolder( &pDesktopFolder ))) + { + OLECHAR olePath[MAX_PATH]; + ULONG chEaten; + + pDesktopFolder->ParseDisplayName( NULL, NULL, olePath, &chEaten, &piStart, NULL ); + + pDesktopFolder->Release(); + } + } + + BROWSEINFO brInfo; + brInfo.hwndOwner = hwndParent; + brInfo.pidlRoot = piStart; + brInfo.pszDisplayName = pszDirectory; + brInfo.lpszTitle = pszHeader; + brInfo.ulFlags = BIF_RETURNONLYFSDIRS; + brInfo.lpfn = NULL; + + ITEMIDLIST *piList; + + piList = SHBrowseForFolder( &brInfo ); + if( piList ) + { + SHGetPathFromIDList( (const LPITEMIDLIST)piList, pszDirectory ); + LPMALLOC pMal; + if( SUCCEEDED( SHGetMalloc( &pMal ))) + { + pMal->Free( piList ); + pMal->Release(); + } + return true; + } + + return false; +} + +bool GetInitialBrowseDir( TCHAR *pszFileName, DWORD dwType ) +{ + // DIRECTORY_INVALID means there's no corresponding entry in g_aszDefFolders + const WORD wDirectory[] = { DIRECTORY_MEMPAK, DIRECTORY_GBROMS, DIRECTORY_GBSAVES, + DIRECTORY_INVALID, DIRECTORY_INVALID, DIRECTORY_INVALID }; + switch( dwType ) + { + case BF_PROFILE: + case BF_MEMPAK: + case BF_NOTE: + case BF_GBROM: + case BF_GBSAVE: + case BF_SHORTCUTS: + if (g_aszLastBrowse[dwType][0] == 0) + return GetDirectory( pszFileName, wDirectory[dwType]); + else + lstrcpyn(pszFileName, g_aszLastBrowse[dwType], MAX_PATH); + return true; + + default: // we don't know what the hell you're talking about + return GetDirectory( pszFileName, DIRECTORY_INVALID ); + } +} + +bool SaveLastBrowseDir( TCHAR *pszFileName, DWORD dwType ) +{ + TCHAR *cSlash = _tcsrchr( pszFileName, _T('\\') ); + if( cSlash ) + { + switch( dwType ) + { + case BF_PROFILE: + case BF_MEMPAK: + case BF_NOTE: + case BF_GBROM: + case BF_GBSAVE: + case BF_SHORTCUTS: + *cSlash = '\0'; + lstrcpyn(g_aszLastBrowse[dwType], pszFileName, MAX_PATH); + *cSlash = '\\'; + return true; + default: + return false; + } + } + else + return true; +} + +// Pop up a dialog asking for a filename from the user. Returns true if returning a valid filename, false if user cancelled. +// Used when either loading (fSave == false) or saving (fSave == true) some type of file. +// Handy, because it handles all our file type extensions for us. +bool BrowseFile( HWND hDlg, TCHAR *pszFileName, DWORD dwType, bool fSave ) +{ + TCHAR pszFilter[DEFAULT_BUFFER]; + TCHAR *pszTitle = NULL; + DWORD dwFlags = /*OFN_DONTADDTORECENT |*/ OFN_NOCHANGEDIR; + dwFlags |= (fSave) ? OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT + : OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; + TCHAR *pszExt = NULL; + + TCHAR *pszTemp = pszFilter; + int nFilters = 0; + + switch( dwType ) + { + case BF_PROFILE: + LoadString( g_hResourceDLL, IDS_DLG_CPF, pszFilter, DEFAULT_BUFFER ); + pszExt = _T("cpf"); + nFilters = 1; + break; + case BF_MEMPAK: + LoadString( g_hResourceDLL, IDS_DLG_MPKN64, pszFilter, DEFAULT_BUFFER ); + if( !fSave ) + { + LoadString( g_hResourceDLL, IDS_DLG_MPCHOOSE, pszTitle, DEFAULT_BUFFER ); + dwFlags = OFN_HIDEREADONLY; + } + pszExt = _T("mpk"); + nFilters = 2; + break; + case BF_NOTE: + LoadString( g_hResourceDLL, IDS_DLG_A64, pszFilter, DEFAULT_BUFFER ); + pszExt = _T("a64"); + nFilters = 1; + break; + case BF_GBROM: + LoadString( g_hResourceDLL, IDS_DLG_GBGBC, pszFilter, DEFAULT_BUFFER ); + pszExt = _T("gb"); + nFilters = 1; + break; + case BF_GBSAVE: + LoadString( g_hResourceDLL, IDS_DLG_SVSAV, pszFilter, DEFAULT_BUFFER ); + pszExt = _T("sv"); + nFilters = 1; + break; + case BF_SHORTCUTS: + LoadString( g_hResourceDLL, IDS_DLG_SC, pszFilter, DEFAULT_BUFFER ); + pszExt = _T("sc"); + nFilters = 1; + break; + default: + return false; + } + + for ( ; nFilters > 0; nFilters--) { + pszTemp += _tcslen(pszTemp); + pszTemp += 1; + pszTemp += _tcslen(pszTemp); + pszTemp += 1; + } + *pszTemp = _T('\0'); + + dwFlags |= OFN_NOCHANGEDIR; + + TCHAR szFileName[MAX_PATH+1] = _T(""), + szInitialDir[MAX_PATH+1] = _T(""), + *pcSlash; + + + if( pszFileName[1] == _T(':') || ( pszFileName[1] == _T('\\') && pszFileName[0] == _T('\\') )) + { + lstrcpyn( szInitialDir, pszFileName, ARRAYSIZE(szInitialDir) ); + pcSlash = _tcsrchr( szInitialDir, _T('\\') ); + if( pcSlash ) + { + *pcSlash = _T('\0'); + lstrcpyn( szFileName, &pcSlash[1], ARRAYSIZE(szFileName) ); + } + } + else + { + if( !GetInitialBrowseDir( szInitialDir, dwType )) + GetDirectory( szInitialDir, DIRECTORY_APPLICATION ); + lstrcpyn( szFileName, pszFileName, ARRAYSIZE(szFileName) ); + } + + + OPENFILENAME oFile; + + oFile.lStructSize = sizeof (OPENFILENAME); + oFile.hwndOwner = hDlg; + oFile.hInstance = NULL; + oFile.lpstrFilter = pszFilter; + oFile.lpstrCustomFilter = NULL; + oFile.nMaxCustFilter = 0; + oFile.nFilterIndex = 0; + oFile.lpstrFile = szFileName; + oFile.nMaxFile = MAX_PATH; + oFile.lpstrFileTitle = NULL; + oFile.nMaxFileTitle = MAX_PATH; // ignored + oFile.lpstrInitialDir = szInitialDir; + oFile.lpstrTitle = pszTitle; + oFile.Flags = dwFlags; + oFile.nFileOffset = 0; + oFile.nFileExtension = 0; + oFile.lpstrDefExt = pszExt; + oFile.lCustData = 0L; + oFile.lpfnHook = NULL; + oFile.lpTemplateName = NULL; + + if( fSave ) + { + if( !GetSaveFileName( &oFile )) + return false; + } + else + { + if( !GetOpenFileName( &oFile )) + return false; + } + + lstrcpy( pszFileName, szFileName ); + SaveLastBrowseDir( szFileName, dwType ); + return true; +} + +bool ReadMemPakFile( TCHAR *pszMemPakFile, BYTE *aMemPak, bool fCreate ) +{ + DWORD dwCreationDisposition = fCreate ? OPEN_ALWAYS : OPEN_EXISTING; + + HANDLE hFile = CreateFile( pszMemPakFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwCreationDisposition, 0, NULL); + if ( hFile != INVALID_HANDLE_VALUE ) + { + ZeroMemory( aMemPak, PAK_MEM_SIZE ); + TCHAR *pcPoint = _tcsrchr( pszMemPakFile, '.' ); + if( !lstrcmpi( pcPoint, _T(".n64") ) ) + SetFilePointer( hFile, 0x1040, NULL, FILE_BEGIN ); + else + SetFilePointer( hFile, 0L, NULL, FILE_BEGIN ); + + DWORD dwBytesRead; + bool Success = ( ReadFile( hFile, aMemPak, PAK_MEM_SIZE, &dwBytesRead, NULL) != 0 ); + + CloseHandle( hFile ); + return Success; + } + else + ErrorMessage( IDS_ERR_MPREAD, GetLastError(), false ); + return false; +} + +// Used by Interface to create or modify mempak files (not mapped). +// pszMemPakFile is a filename, aMemPak is the data, fCreate tells whether to create a new file +bool WriteMemPakFile( TCHAR *pszMemPakFile, BYTE *aMemPak, bool fCreate ) +{ + DWORD dwCreationDisposition = fCreate ? OPEN_ALWAYS : OPEN_EXISTING; + + HANDLE hFile = CreateFile( pszMemPakFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, dwCreationDisposition, 0, NULL); + if ( hFile != INVALID_HANDLE_VALUE ) + { + DWORD dwBytesWritten = 0; + TCHAR *pcPoint = _tcsrchr( pszMemPakFile, _T('.') ); + if( !lstrcmpi( pcPoint, _T(".n64") ) ) + { + if( fCreate && !GetFileSize( hFile, NULL )) + { + char szHeader[] = "123-456-STD"; + SetFilePointer( hFile, 0L, NULL, FILE_BEGIN ); + WriteFile( hFile, szHeader, sizeof(szHeader), &dwBytesWritten, NULL ); + } + SetFilePointer( hFile, 0x1040, NULL, FILE_BEGIN ); + } + else + SetFilePointer( hFile, 0L, NULL, FILE_BEGIN ); + + bool Success = ( WriteFile( hFile, aMemPak, PAK_MEM_SIZE, &dwBytesWritten, NULL ) != 0 ); + if( Success ) + SetEndOfFile( hFile ); + + CloseHandle( hFile ); + return Success; + } + else + ErrorMessage( IDS_ERR_MPCREATE, GetLastError(), false ); + + return false; +} + +// This func stores the current config data to INI. It stores the Interface's idea of configuration +// As such, it should only be called from the config window (Interface). Otherwise, it will fail. +// Returns true if saved OK, false if there was a problem. +bool StoreConfigToINI() +{ + char szANSIBuf[DEFAULT_BUFFER]; + if (!g_ivConfig) + return false; + + TCHAR szFilename[MAX_PATH]; + GetDirectory(szFilename, DIRECTORY_DLL); + _tcscat(szFilename, _T("NRage.ini")); + FILE *fFile = _tfopen(szFilename, _T("wS")); // write, optimize for sequential + + if (!fFile) + { + DebugWriteA("Couldn't open INI file for output!\n"); + return false; + } + + // first write out any standard header stuff here + fputs(STRING_INI_HEADER, fFile); + + // General + fputs("\n[" STRING_INI_GENERAL "]\n", fFile); + fprintf(fFile, STRING_INI_LANGUAGE "=%d\n", g_ivConfig->Language); + fprintf(fFile, STRING_INI_SHOWMESSAGES "=%d\n", (int)(g_ivConfig->fDisplayShortPop)); + + // Folders + fputs("\n[" STRING_INI_FOLDERS "]\n", fFile); + const char szFolders[ARRAYSIZE(g_aszDefFolders)][DEFAULT_BUFFER] = {STRING_INI_BRMEMPAK "=%s\n", STRING_INI_BRGBROM "=%s\n", STRING_INI_BRGBSAVE "=%s\n"}; + for (int i = 0; i < ARRAYSIZE(szFolders); i++) + { + TCHAR_TO_CHAR( szANSIBuf, g_aszDefFolders[i], DEFAULT_BUFFER ); + fprintf(fFile, szFolders[i], szANSIBuf); + } + + // lastBrowserDir + fputs("\n[" STRING_INI_BROWSER "]\n", fFile); + const char szBrowser[ARRAYSIZE(g_aszLastBrowse)][DEFAULT_BUFFER] = {STRING_INI_BRMEMPAK "=%s\n", STRING_INI_BRGBROM "=%s\n", STRING_INI_BRGBSAVE "=%s\n", + STRING_INI_BRPROFILE "=%s\n", STRING_INI_BRNOTE "=%s\n", STRING_INI_SHORTCUTS "=%s\n" }; + for (int i = 0; i < ARRAYSIZE(szBrowser); i++) + { + TCHAR_TO_CHAR( szANSIBuf, g_aszLastBrowse[i], DEFAULT_BUFFER ); + fprintf(fFile, szBrowser[i], szANSIBuf); + } + + // Controller 1 through 4 + for (int i = 0; i < 4; i++) + { + fprintf(fFile, "\n[" STRING_INI_CONTROLLER " %d]\n", i + 1); + DumpControllerSettings(fFile, i, true); + } + + // Controls + + // I'm going to use STL strings here because I don't want to screw with buffer management + string strMouse; + string strDevs[MAX_DEVICES]; + string strNull; + + fputs("\n[" STRING_INI_CONTROLS "]\n", fFile); + fputs("# Button format: controlnum buttonID bOffset bAxisID bBtnType\n", fFile); + + for ( int i = 0; i < 4; i++ ) // controllers for + { + FormatControlsBlock(&strMouse, strDevs, &strNull, i); + } // end controllers for + + DumpStreams(fFile, strMouse, strDevs, strNull, true); + + strMouse.clear(); + for (int i = 0; i < g_nDevices; i++) + strDevs[i].clear(); + strNull.clear(); + + // Shortcuts + + fputs("\n[" STRING_INI_SHORTCUTS "]\n", fFile); + fputs("# Shortcuts format: controlnum buttonID bOffset bAxisID bBtnType\n", fFile); + + FormatShortcutsBlock(fFile, true); + + // Modifiers + fputs("\n[" STRING_INI_MODIFIERS "]\n", fFile); + fputs("# Modifiers format: controlnum bOffset bAxisID bBtnType bModType fToggle fStatus dwSpecific\n", fFile); + + for ( int i = 0; i < 4; i++ ) // controllers for + { + FormatModifiersBlock(&strMouse, strDevs, &strNull, i); + } // end controllers for + + DumpStreams(fFile, strMouse, strDevs, strNull, true); + + fclose(fFile); + DebugWriteA("Config stored to INI\n"); + return true; +} + +// This func loads the config data from INI into working emulator space. Does not copy into Interface; +// you need to call GetCurrentConfiguration() if you want to do that. +// Returns true if loaded OK, false if there was a problem. +bool LoadConfigFromINI() +{ + FILE *fFile = NULL; + DWORD dwSection = 0; // this will eval to the bracketed "[Section]" we are currently in. + char szLine[4096]; + + TCHAR szFilename[MAX_PATH]; + GetDirectory(szFilename, DIRECTORY_DLL); + _tcscat(szFilename, _T("NRage.ini")); + fFile = _tfopen(szFilename, _T("rS")); // read, optimize for sequential + + if (!fFile) + { + DebugWriteA("Couldn't open INI file for input!\n"); + return false; + } + + for (int i = 0; i < 4; i++) + SetControllerDefaults( &(g_pcControllers[i]) ); + + ProcessKey( PL_RESET, 0, 0, 0, 0, false ); + DWORD dwCommand = PL_NOHIT; + while(( fgets(szLine, sizeof(szLine) - 1, fFile) ) ) + { + szLine[strlen(szLine) - 1] = '\0'; // remove newline + dwCommand = ParseLine( szLine ); + if (dwCommand == PL_NOHIT) + continue; + else if (dwCommand == PL_CATEGORY) + // section changed to szLine + dwSection = djbHash(szLine); + else + ProcessKey( dwCommand, dwSection, szLine, 0, 0, false ); + } + + fclose(fFile); + + return true; +} + +// basically a stripped down version of GetConfigFromINI, called at the very beginning to get our language +LANGID GetLanguageFromINI() +{ + FILE *fFile = NULL; + char szLine[4096]; + + TCHAR szFilename[MAX_PATH]; + GetDirectory(szFilename, DIRECTORY_DLL); + _tcscat(szFilename, _T("NRage.ini")); + fFile = _tfopen(szFilename, _T("rS")); // read, optimize for sequential + + if (!fFile) + { + DebugWriteA("Couldn't open INI file for input!\n"); + return 0; + } + + ProcessKey( PL_RESET, 0, 0, 0, 0, false ); + DWORD dwCommand = PL_NOHIT; + while(( fgets(szLine, sizeof(szLine) - 1, fFile) ) ) + { + szLine[strlen(szLine) - 1] = '\0'; // remove newline + dwCommand = ParseLine( szLine ); + if (dwCommand == CHK_LANGUAGE) + { + LANGID lTemp = 0; + if (sscanf(szLine, "%hu", &lTemp)) + { + fclose(fFile); + return lTemp; + } + } + } + + fclose(fFile); + DebugWriteA("Couldn't find a Language= line in INI file...\n"); + return 0; +} + +// both the following functions assume the buffer is big enough +inline void GUIDtoStringA( char * szGUIDbuf, const GUID guid ) +{ + _snprintf( szGUIDbuf, GUID_STRINGLENGTH + 1, "{%08.8lX-%04.4hX-%04.4hX-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); +} + +inline bool StringtoGUIDA( LPGUID guid, const char * szGUIDbuf ) +{ + short unsigned int lastbyte; + int blah = sscanf(szGUIDbuf, "{%08lX-%04hX-%04hX-%02hX%02hX-%02hX%02hX%02hX%02hX%02hX%02hX}", &guid->Data1, &guid->Data2, &guid->Data3, &guid->Data4[0], &guid->Data4[1], &guid->Data4[2], &guid->Data4[3], &guid->Data4[4], &guid->Data4[5], &guid->Data4[6], &lastbyte); + if (blah == 11) + { + guid->Data4[7] = (BYTE)lastbyte; + return true; + } + else + return false; +} + +// Takes in a file to dump to, and an int i telling which controller's settings to dump. Does not dump buttons or modifiers. +void DumpControllerSettings(FILE * fFile, int i, bool bIsINI) +{ + char szANSIBuf[DEFAULT_BUFFER]; + + fprintf(fFile, STRING_INI_PLUGGED "=%u\n", g_ivConfig->Controllers[i].fPlugged); + fprintf(fFile, STRING_INI_XINPUT "=%u\n", g_ivConfig->Controllers[i].fXInput); + fprintf(fFile, STRING_INI_RAWDATA "=%u\n", g_ivConfig->Controllers[i].fRawData); + fprintf(fFile, STRING_INI_PAKTYPE "=%u\n", g_ivConfig->Controllers[i].PakType); + fprintf(fFile, STRING_INI_REALN64RANGE "=%u\n", g_ivConfig->Controllers[i].fRealN64Range); + fprintf(fFile, STRING_INI_RAPIDFIREENABLED "=%u\n", g_ivConfig->Controllers[i].bRapidFireEnabled); + fprintf(fFile, STRING_INI_RAPIDFIRERATE "=%u\n", g_ivConfig->Controllers[i].bRapidFireRate); + fprintf(fFile, STRING_INI_STICKRANGE "=%u\n", g_ivConfig->Controllers[i].bStickRange); + fprintf(fFile, STRING_INI_MOUSEMOVEX "=%u\n", g_ivConfig->Controllers[i].bMouseMoveX); + fprintf(fFile, STRING_INI_MOUSEMOVEY "=%u\n", g_ivConfig->Controllers[i].bMouseMoveY); + fprintf(fFile, STRING_INI_AXISSET "=%u\n", g_ivConfig->Controllers[i].bAxisSet); + fprintf(fFile, STRING_INI_KEYABSOLUTEX "=%u\n", g_ivConfig->Controllers[i].fKeyAbsoluteX); + fprintf(fFile, STRING_INI_KEYABSOLUTEY "=%u\n", g_ivConfig->Controllers[i].fKeyAbsoluteY); + fprintf(fFile, STRING_INI_PADDEADZONE "=%u\n", g_ivConfig->Controllers[i].bPadDeadZone); + fprintf(fFile, STRING_INI_MOUSESENSX "=%u\n", g_ivConfig->Controllers[i].wMouseSensitivityX); + fprintf(fFile, STRING_INI_MOUSESENSY "=%u\n", g_ivConfig->Controllers[i].wMouseSensitivityY); + fprintf(fFile, STRING_INI_RUMBLETYPE "=%u\n", g_ivConfig->Controllers[i].bRumbleTyp); + fprintf(fFile, STRING_INI_RUMBLESTRENGTH "=%u\n", g_ivConfig->Controllers[i].bRumbleStrength); + fprintf(fFile, STRING_INI_VISUALRUMBLE "=%u\n", g_ivConfig->Controllers[i].fVisualRumble); + + if (bIsINI) + { + char szGUID[DEFAULT_BUFFER]; + int iDevice = FindDeviceinList( g_ivConfig->FFDevices[i].szProductName, g_ivConfig->FFDevices[i].bProductCounter, true ); + if (iDevice == -1) + { + fprintf(fFile, STRING_INI_FFDEVICEGUID "=\n"); + } + else + { + g_ivConfig->Controllers[i].guidFFDevice = g_devList[iDevice].guidInstance; + GUIDtoStringA(szGUID, g_ivConfig->Controllers[i].guidFFDevice); + fprintf(fFile, STRING_INI_FFDEVICEGUID "=%s\n", szGUID); + } + } + else + { + TCHAR_TO_CHAR(szANSIBuf, g_ivConfig->FFDevices[i].szProductName, DEFAULT_BUFFER); + fprintf(fFile, STRING_INI_FFDEVICENAME "=%s\n", szANSIBuf); + fprintf(fFile, STRING_INI_FFDEVICENR "=%u\n", g_ivConfig->FFDevices[i].bProductCounter); + } + + TCHAR_TO_CHAR( szANSIBuf, g_ivConfig->Controllers[i].szMempakFile, DEFAULT_BUFFER ); + fprintf(fFile, STRING_INI_MEMPAKFILE "=%s\n", szANSIBuf); + + TCHAR_TO_CHAR( szANSIBuf, g_ivConfig->Controllers[i].szTransferRom, DEFAULT_BUFFER ); + fprintf(fFile, STRING_INI_GBROMFILE "=%s\n", szANSIBuf); + + TCHAR_TO_CHAR( szANSIBuf, g_ivConfig->Controllers[i].szTransferSave, DEFAULT_BUFFER ); + fprintf(fFile, STRING_INI_GBROMSAVE "=%s\n", szANSIBuf); +} + +// private func, called by StoreConfigToINI to dump cached Button strings to file +void DumpStreams(FILE * fFile, string strMouse, string strDevs[], string strNull, bool bIsINI) +{ + // dump all streams to file, with appropriate DInput lines and name comment + char szANSIBuf[DEFAULT_BUFFER]; + if (!(strMouse.empty())) + { + TCHAR_TO_CHAR( szANSIBuf, g_sysMouse.szProductName, DEFAULT_BUFFER ); + if (bIsINI) + { + fprintf(fFile, "# %s\n", szANSIBuf); + char szGUID[DEFAULT_BUFFER]; + GUIDtoStringA(szGUID, g_sysMouse.guidInstance); + fprintf(fFile, STRING_INI_DINPUTGUID "=%s\n", szGUID); + } + else + { + fprintf(fFile, STRING_INI_DINPUTNAME "=%s\n", szANSIBuf); + fprintf(fFile, STRING_INI_DINPUTNR "=%d\n", 0); + } + fputs(strMouse.c_str(), fFile); + } + if (!(strNull.empty())) + { + fputs("# NOT ASSIGNED\n", fFile); + if (bIsINI) + { + char szGUID[DEFAULT_BUFFER]; + GUIDtoStringA(szGUID, GUID_NULL); + fprintf(fFile, STRING_INI_DINPUTGUID "=%s\n", szGUID); + } + else + { + fprintf(fFile, STRING_INI_DINPUTNAME "=\n"); // leave blank + fprintf(fFile, STRING_INI_DINPUTNR "=\n"); + } + fputs(strNull.c_str(), fFile); + } + for (int i = 0; i < g_nDevices; i++) + { + if (!(strDevs[i].empty())) + { + TCHAR_TO_CHAR( szANSIBuf, g_devList[i].szProductName, DEFAULT_BUFFER ); + if (bIsINI) + { + if (g_devList[i].bProductCounter > 0) + fprintf(fFile, "# %s %d\n", szANSIBuf, g_devList[i].bProductCounter); + else + fprintf(fFile, "# %s\n", szANSIBuf); + char szGUID[DEFAULT_BUFFER]; + GUIDtoStringA(szGUID, g_devList[i].guidInstance); + fprintf(fFile, STRING_INI_DINPUTGUID "=%s\n", szGUID); + } + else + { + fprintf(fFile, STRING_INI_DINPUTNAME "=%s\n", szANSIBuf); + fprintf(fFile, STRING_INI_DINPUTNR "=%d\n", g_devList[i].bProductCounter); + } + fputs(strDevs[i].c_str(), fFile); + } + } +} + +void FormatControlsBlock(string * strMouse, string strDevs[], string * strNull, int i) +{ + for ( int j = 0; j < ARRAYSIZE(g_ivConfig->Controllers[i].aButton); j++ ) // buttons for + { + if (g_ivConfig->Controllers[i].aButton[j].parentDevice) // possibly unbound + { + if ( IsEqualGUID(g_sysMouse.guidInstance, g_ivConfig->Controllers[i].aButton[j].parentDevice->guidInstance) ) + { + char szBuf[DEFAULT_BUFFER]; + // add to the mouse stream + sprintf(szBuf, STRING_INI_BUTTON "=%d %d %02X %d %d\n", i, j, g_ivConfig->Controllers[i].aButton[j].bOffset, g_ivConfig->Controllers[i].aButton[j].bAxisID, g_ivConfig->Controllers[i].aButton[j].bBtnType); + strMouse->append(szBuf); + } + else + { + for (int match = 0; match < g_nDevices; match++) + { + if ( IsEqualGUID(g_devList[match].guidInstance, g_ivConfig->Controllers[i].aButton[j].parentDevice->guidInstance) ) + { + char szBuf[DEFAULT_BUFFER]; + // add to the appropriate device stream + sprintf(szBuf, STRING_INI_BUTTON "=%d %d %02X %d %d\n", i, j, g_ivConfig->Controllers[i].aButton[j].bOffset, g_ivConfig->Controllers[i].aButton[j].bAxisID, g_ivConfig->Controllers[i].aButton[j].bBtnType); + strDevs[match].append(szBuf); + break; + } + } + } + } + else if (g_ivConfig->Controllers[i].aButton[j].bBtnType != DT_UNASSIGNED) + { + int k = g_ivConfig->Controllers[i].aButton[j].bBtnType; + DebugWriteA("Controller %d button %d is of bBtnType %d but has no parentDevice!\n", i, j, k); + } + } // end buttons for +} + +void FormatModifiersBlock(string * strMouse, string strDevs[], string * strNull, int i) +{ + for ( int j = 0; j < g_ivConfig->Controllers[i].nModifiers; j++ ) + { + if (g_ivConfig->Controllers[i].pModifiers[j].btnButton.parentDevice) // is it assigned to a key? + { + if ( IsEqualGUID(g_sysMouse.guidInstance, g_ivConfig->Controllers[i].pModifiers[j].btnButton.parentDevice->guidInstance) ) + { + char szBuf[DEFAULT_BUFFER]; + // add to the mouse stream + sprintf(szBuf, STRING_INI_MODIFIER "=%d %02X %d %d %d %d %d %08X\n", i, g_ivConfig->Controllers[i].pModifiers[j].btnButton.bOffset, + g_ivConfig->Controllers[i].pModifiers[j].btnButton.bAxisID, g_ivConfig->Controllers[i].pModifiers[j].btnButton.bBtnType, + g_ivConfig->Controllers[i].pModifiers[j].bModType, g_ivConfig->Controllers[i].pModifiers[j].fToggle, + g_ivConfig->Controllers[i].pModifiers[j].fStatus, g_ivConfig->Controllers[i].pModifiers[j].dwSpecific); + strMouse->append(szBuf); + } + else + for (int match = 0; match < g_nDevices; match++) + if ( IsEqualGUID(g_devList[match].guidInstance, g_ivConfig->Controllers[i].pModifiers[j].btnButton.parentDevice->guidInstance) ) + { + char szBuf[DEFAULT_BUFFER]; + // add to the mouse stream + sprintf(szBuf, STRING_INI_MODIFIER "=%d %02X %d %d %d %d %d %08X\n", i, g_ivConfig->Controllers[i].pModifiers[j].btnButton.bOffset, + g_ivConfig->Controllers[i].pModifiers[j].btnButton.bAxisID, g_ivConfig->Controllers[i].pModifiers[j].btnButton.bBtnType, + g_ivConfig->Controllers[i].pModifiers[j].bModType, g_ivConfig->Controllers[i].pModifiers[j].fToggle, + g_ivConfig->Controllers[i].pModifiers[j].fStatus, g_ivConfig->Controllers[i].pModifiers[j].dwSpecific); + strDevs[match].append(szBuf); + break; + } + } + else // save modifiers without a keybind + { + char szBuf[DEFAULT_BUFFER]; + // add to the mouse stream + sprintf(szBuf, STRING_INI_MODIFIER "=%d %02X %d %d %d %d %d %08X\n", i, g_ivConfig->Controllers[i].pModifiers[j].btnButton.bOffset, + g_ivConfig->Controllers[i].pModifiers[j].btnButton.bAxisID, g_ivConfig->Controllers[i].pModifiers[j].btnButton.bBtnType, + g_ivConfig->Controllers[i].pModifiers[j].bModType, g_ivConfig->Controllers[i].pModifiers[j].fToggle, + g_ivConfig->Controllers[i].pModifiers[j].fStatus, g_ivConfig->Controllers[i].pModifiers[j].dwSpecific); + strNull->append(szBuf); + } + } +} + +unsigned long djbHash(const char *str) +{ + unsigned long hash = 5381; + int c; + + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; +} diff --git a/Source/nragev20/FileAccess.h b/Source/nragev20/FileAccess.h new file mode 100644 index 000000000..cbf773924 --- /dev/null +++ b/Source/nragev20/FileAccess.h @@ -0,0 +1,227 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _FILEACCESS_H_ +#define _FILEACCESS_H_ + +#include "NRagePluginV2.h" +#include +using std::string; + +bool GetDirectory( LPTSTR pszDirectory, WORD wDirID ); +bool CheckFileExists( LPCTSTR FileName ); +void GetAbsoluteFileName( LPTSTR szAbsolute, LPCTSTR szFileName, const WORD wDirID ); + +BOOL SendFilestoList( HWND hDlgItem, WORD wType ); +bool StoreConfigToINI(); +bool LoadConfigFromINI(); +LANGID GetLanguageFromINI(); + +bool LoadProfileFile( LPCTSTR pszFileName, int iController, LPTSTR pszGameDevice, LPBYTE bGameDeviceNr ); +bool LoadShortcutsFile( LPCTSTR pszFileName ); +void FormatProfileBlock( FILE * fFile, const int iController ); +void FormatShortcutsBlock( FILE * fFile, bool bIsINI ); +bool BrowseFolders( HWND hwndParent, LPTSTR pszHeader, LPTSTR pszDirectory ); +bool BrowseFile( HWND hDlg, LPTSTR pszFileName, DWORD dwType, bool fSave ); +bool ReadMemPakFile( LPTSTR pszMemPakFile, BYTE *aMemPak, bool fCreate ); +bool WriteMemPakFile( LPTSTR pszMemPakFile, BYTE *aMemPak, bool fCreate ); +bool LoadProfileFromResource( int indexController, bool bIsInterface ); +bool LoadShortcutsFromResource( bool bIsInterface ); +inline void GUIDtoStringA( char * szGUIDbuf, const GUID guid ); +inline bool StringtoGUIDA( LPGUID guid, const char * szGUIDbuf ); +unsigned long djbHash(const char *str); + +#ifdef _UNICODE +#define TCHAR_TO_CHAR(x,y,z) wcstombs(x,y,z) +#define CHAR_TO_TCHAR(x,y,z) mbstowcs(x,y,z) +#else +#define TCHAR_TO_CHAR(x,y,z) strncpy(x,y,z) +#define CHAR_TO_TCHAR(x,y,z) strncpy(x,y,z) +#endif + +#define STRING_DEF_MEMPAKFILE _T("MemPaks") +#define STRING_DEF_GBROMFILE _T("GBxRoms") +#define STRING_DEF_GBROMSAVE _T("GBxSaves") + +#define STRING_INI_HEADER "# Generated by NRage input plugin V2 version " VERSIONNUMBER "\n" +// We use these names for loading from INI files and NRage config files +#define STRING_INI_GENERAL "General" +#define STRING_INI_CONTROLLER "Controller" +#define STRING_INI_FOLDERS "Folders" +#define STRING_INI_BROWSER "lastBrowserDir" +#define STRING_INI_CONTROLS "Controls" +#define STRING_INI_SHORTCUTS "Shortcuts" +#define STRING_INI_MODIFIERS "Modifiers" + +#define STRING_INI_LANGUAGE "Language" +#define STRING_INI_SHOWMESSAGES "ShowMessages" + +#define STRING_INI_BRPROFILE "Profile" +#define STRING_INI_BRNOTE "Note" +#define STRING_INI_BRMEMPAK "Mempak" +#define STRING_INI_BRGBROM "GBxRom" +#define STRING_INI_BRGBSAVE "GBxSave" +// #define STRING_INI_BRSHORTCUTS STRING_INI_SHORTCUTS + +#define STRING_INI_PLUGGED "Plugged" +#define STRING_INI_XINPUT "xInput" +#define STRING_INI_RAWDATA "RawData" +#define STRING_INI_PAKTYPE "PakType" +#define STRING_INI_REALN64RANGE "RealN64Range" +#define STRING_INI_RAPIDFIREENABLED "RapidFireEnabled" +#define STRING_INI_RAPIDFIRERATE "RapidFireRate" +#define STRING_INI_STICKRANGE "StickRange" +#define STRING_INI_MOUSEMOVEX "MouseMoveX" +#define STRING_INI_MOUSEMOVEY "MouseMoveY" +#define STRING_INI_AXISSET "AxisSet" +#define STRING_INI_KEYABSOLUTEX "KeyAbsoluteX" +#define STRING_INI_KEYABSOLUTEY "KeyAbsoluteY" +#define STRING_INI_PADDEADZONE "PadDeadZone" +#define STRING_INI_MOUSESENSX "MouseSensitivityX" +#define STRING_INI_MOUSESENSY "MouseSensitivityY" +#define STRING_INI_RUMBLETYPE "RumbleType" +#define STRING_INI_RUMBLESTRENGTH "RumbleStrength" +#define STRING_INI_VISUALRUMBLE "VisualRumble" +#define STRING_INI_FFDEVICEGUID "FFDeviceGUID" +#define STRING_INI_MEMPAKFILE "MemPakFile" +#define STRING_INI_GBROMFILE "GBRomFile" +#define STRING_INI_GBROMSAVE "GBRomSave" + +#define STRING_INI_DINPUTGUID "DInputGUID" +#define STRING_INI_BUTTON "Button" +#define STRING_INI_MODIFIER "Modifier" + +// The following are not found in INI files; only profile and shortcuts files +#define STRING_PROFILEVERSION22 "Controller Profile 2.2" +#define STRING_PROFILEVERSION STRING_PROFILEVERSION22 + +#define STRING_INI_FFDEVICENAME "FFDeviceName" +#define STRING_INI_FFDEVICENR "FFDeviceNr" +#define STRING_INI_DINPUTNAME "DInputName" +#define STRING_INI_DINPUTNR "DInputNr" + + +// the following are hashes for the string values above + +// version strings, including the @ in front +#define CHK_PROFILEVERSION20 2278962538 +#define CHK_PROFILEVERSION21 2278962539 +#define CHK_PROFILEVERSION22 2278962540 + +// categories +#define CHK_GENERAL 63249731 +#define CHK_FOLDERS 3455681620 +#define CHK_LASTBROWSERDIR 2659654652 +#define CHK_CONTROLLER_1 3910856026 +#define CHK_CONTROLLER_2 3910856027 +#define CHK_CONTROLLER_3 3910856028 +#define CHK_CONTROLLER_4 3910856029 +#define CHK_CONTROLS 3459743001 +#define CHK_SHORTCUTS 2945387732 +#define CHK_MODIFIERS 95935975 + +// assignments (to the left of the '=' sign) +#define CHK_LANGUAGE 3857633481 +#define CHK_SHOWMESSAGES 638097246 + +#define CHK_MEMPAK 3230166560 +#define CHK_GBXROM 2992194388 +#define CHK_GBXSAVE 4253155349 + +#define CHK_PROFILE 3606499382 +#define CHK_NOTE 2089365563 + +#define CHK_PLUGGED 3378836077 +#define CHK_XINPUT 3665436173 +#define CHK_RAWDATA 1238573385 +#define CHK_PAKTYPE 2936974691 +#define CHK_REALN64RANGE 1279831790 +#define CHK_RAPIDFIREENABLED 1491009894 +#define CHK_RAPIDFIRERATE 1576165031 +#define CHK_STICKRANGE 4145501776 +#define CHK_MOUSEMOVEX 1825694205 +#define CHK_MOUSEMOVEY 1825694206 +#define CHK_AXISSET 1642523718 +#define CHK_KEYABSOLUTEX 958566277 +#define CHK_KEYABSOLUTEY 958566278 +#define CHK_PADDEADZONE 2913910084 +#define CHK_MOUSESENSITIVITYX 1513071697 +#define CHK_MOUSESENSITIVITYY 1513071698 +#define CHK_RUMBLETYPE 3440038446 +#define CHK_RUMBLESTRENGTH 3038086267 +#define CHK_VISUALRUMBLE 1795686016 +#define CHK_FFDEVICEGUID 2645316746 +#define CHK_MEMPAKFILE 2373591360 +#define CHK_GBROMFILE 2409678172 +#define CHK_GBROMSAVE 2410136971 + +#define CHK_DINPUTGUID 1452894242 +#define CHK_BUTTON 2818908353 +#define CHK_MODIFIER 4037573396 + + +// The following are not found in INI files; only profile and shortcuts files +#define CHK_FFDEVICENAME 2645546658 +#define CHK_FFDEVICENR 2037510273 +#define CHK_DINPUTNAME 1453124154 +#define CHK_DINPUTNR 3965009433 + + +// If any of the following values conflict with djbHash return values (such as a blank string), there will be problems! + +// nothing +#define PL_NOHIT 0 + // [Category] +#define PL_CATEGORY 1 + // @STRING_PROFILEVERSION +#define PL_VERSIONSTRING 10 + + // resets the static vars in ProcessKey +#define PL_RESET 200 + + +#define DIRECTORY_MEMPAK 0 +#define DIRECTORY_GBROMS 1 +#define DIRECTORY_GBSAVES 2 +#define DIRECTORY_DLL 254 +#define DIRECTORY_APPLICATION 255 +#define DIRECTORY_INVALID 256 + + +#define FILIST_MEM 1 +#define FILIST_TRANSFER 2 + +#define BF_LOAD false +#define BF_SAVE true + +#define BF_MEMPAK 0 +#define BF_GBROM 1 +#define BF_GBSAVE 2 +#define BF_PROFILE 3 +#define BF_NOTE 4 +#define BF_SHORTCUTS 5 + + // 32 hex characters, 4 hyphens, 2 end braces +#define GUID_STRINGLENGTH 32+4+2 + +#endif // #ifndef _FILEACCESS_H_ diff --git a/Source/nragev20/GBCart.cpp b/Source/nragev20/GBCart.cpp new file mode 100644 index 000000000..389758099 --- /dev/null +++ b/Source/nragev20/GBCart.cpp @@ -0,0 +1,1045 @@ +/* +** +** +** +** This file's purpose is to emulate the inner workings of a +** GameBoy Game Pak cartrige. +** +** All code is by Mark McGough. MadManMarkAu@hotmail.com +** +** +*/ + +#include "commonIncludes.h" +#include +#include "NRagePluginV2.h" +#include "PakIO.h" +#include "GBCart.h" + +void ClearData(BYTE *Data, int Length); + +bool ReadCartNorm(LPGBCART Cart, WORD dwAddress, BYTE *Data); // For all non-MBC carts; fixed 0x8000 ROM; fixed, optional 0x2000 RAM +bool WriteCartNorm(LPGBCART Cart, WORD dwAddress, BYTE *Data); +bool ReadCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data); +bool WriteCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data); +bool ReadCartMBC2(LPGBCART Cart, WORD dwAddress, BYTE *Data); +bool WriteCartMBC2(LPGBCART Cart, WORD dwAddress, BYTE *Data); +bool ReadCartMBC3(LPGBCART Cart, WORD dwAddress, BYTE *Data); +bool WriteCartMBC3(LPGBCART Cart, WORD dwAddress, BYTE *Data); +bool ReadCartMBC5(LPGBCART Cart, WORD dwAddress, BYTE *Data); +bool WriteCartMBC5(LPGBCART Cart, WORD dwAddress, BYTE *Data); + +// Tries to read RTC data from separate file (not integrated into SAV) +// success sets the useTDF flag +// failure inits the RTC at zero and maybe throws a warning +void ReadTDF(LPGBCART Cart) { +} + +void WriteTDF(LPGBCART Cart) { + // check useTDF flag + // write data from RTC to TDF file +} + +void UpdateRTC(LPGBCART Cart) { + time_t now, dif; + int days; + + now = time(NULL); + dif = now - Cart->timerLastUpdate; + + Cart->TimerData[0] += (BYTE)(dif % 60); + dif /= 60; + Cart->TimerData[1] += (BYTE)(dif % 60); + dif /= 60; + Cart->TimerData[2] += (BYTE)(dif % 24); + dif /= 24; + + days = Cart->TimerData[3] + ((Cart->TimerData[4] & 1) << 8) + dif; + Cart->TimerData[3] = (days & 0xFF); + + if(days > 255) { + if(days > 511) { + days &= 511; + Cart->TimerData[4] |= 0x80; + } + if (days > 255) + Cart->TimerData[4] = (Cart->TimerData[4] & 0xFE) | (days > 255 ? 1 : 0); + } + + Cart->timerLastUpdate = now; + + DebugWriteA("Update RTC: "); + DebugWriteByteA(Cart->TimerData[0]); + DebugWriteA(":"); + DebugWriteByteA(Cart->TimerData[1]); + DebugWriteA(":"); + DebugWriteByteA(Cart->TimerData[2]); + DebugWriteA(":"); + DebugWriteByteA(Cart->TimerData[3]); + DebugWriteA(":"); + DebugWriteByteA(Cart->TimerData[4]); + DebugWriteA("\n"); +} + +// returns true if the ROM was loaded OK +bool LoadCart(LPGBCART Cart, LPCTSTR RomFileName, LPCTSTR RamFileName, LPCTSTR TdfFileName) +{ + HANDLE hTemp; + DWORD dwFilesize; + DWORD NumQuarterBlocks = 0; + + UnloadCart(Cart); // first, make sure any previous carts have been unloaded + + Cart->iCurrentRamBankNo = 0; + Cart->iCurrentRomBankNo = 1; + Cart->bRamEnableState = 0; + Cart->bMBC1RAMbanking = 0; + + // Attempt to load the ROM file. + hTemp = CreateFile(RomFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hTemp != INVALID_HANDLE_VALUE && (Cart->hRomFile = CreateFileMapping(hTemp, NULL, PAGE_READONLY, 0, 0, NULL) ) ) + { + // if the first case fails, the file doesn't exist. The second case can fail if the file size is zero. + dwFilesize = GetFileSize(hTemp, NULL); + CloseHandle(hTemp); + Cart->RomData = (const unsigned char *)MapViewOfFile( Cart->hRomFile, FILE_MAP_READ, 0, 0, 0 ); + } else { + DebugWriteA("Couldn't load the ROM file, GetLastError returned %08x\n", GetLastError()); + if (hTemp != INVALID_HANDLE_VALUE) + CloseHandle(hTemp); // if file size was zero, make sure we don't leak the handle + + ErrorMessage(IDS_ERR_GBROM, 0, false); + return false; + } + + if (dwFilesize < 0x8000) // a Rom file has to be at least 32kb + { + DebugWriteA("ROM file wasn't big enough to be a GB ROM!\n"); + ErrorMessage(IDS_ERR_GBROM, 0, false); + + UnloadCart(Cart); + return false; + } + + DebugWriteA(" Cartridge Type #:"); + DebugWriteByteA(Cart->RomData[0x147]); + DebugWriteA("\n"); + switch (Cart->RomData[0x147]) { // if we hadn't checked the file size before, this might have caused an access violation + case 0x00: + Cart->iCartType = GB_NORM; + Cart->bHasRam = false; + Cart->bHasBattery = false; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x01: + Cart->iCartType = GB_MBC1; + Cart->bHasRam = false; + Cart->bHasBattery = false; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x02: + Cart->iCartType = GB_MBC1; + Cart->bHasRam = true; + Cart->bHasBattery = false; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x03: + Cart->iCartType = GB_MBC1; + Cart->bHasRam = true; + Cart->bHasBattery = true; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x05: + Cart->iCartType = GB_MBC2; + Cart->bHasRam = false; + Cart->bHasBattery = false; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x06: + Cart->iCartType = GB_MBC2; + Cart->bHasRam = false; + Cart->bHasBattery = true; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x08: + Cart->iCartType = GB_NORM; + Cart->bHasRam = true; + Cart->bHasBattery = false; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x09: + Cart->iCartType = GB_NORM; + Cart->bHasRam = true; + Cart->bHasBattery = true; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x0B: + Cart->iCartType = GB_MMMO1; + Cart->bHasRam = false; + Cart->bHasBattery = false; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x0C: + Cart->iCartType = GB_MMMO1; + Cart->bHasRam = true; + Cart->bHasBattery = false; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x0D: + Cart->iCartType = GB_MMMO1; + Cart->bHasRam = true; + Cart->bHasBattery = true; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x0F: + Cart->iCartType = GB_MBC3; + Cart->bHasRam = false; + Cart->bHasBattery = true; + Cart->bHasTimer = true; + Cart->bHasRumble = false; + break; + case 0x10: + Cart->iCartType = GB_MBC3; + Cart->bHasRam = true; + Cart->bHasBattery = true; + Cart->bHasTimer = true; + Cart->bHasRumble = false; + break; + case 0x11: + Cart->iCartType = GB_MBC3; + Cart->bHasRam = false; + Cart->bHasBattery = false; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x12: + Cart->iCartType = GB_MBC3; + Cart->bHasRam = true; + Cart->bHasBattery = true; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x13: + Cart->iCartType = GB_MBC3; + Cart->bHasRam = true; + Cart->bHasBattery = true; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x19: + Cart->iCartType = GB_MBC5; + Cart->bHasRam = false; + Cart->bHasBattery = false; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x1A: + Cart->iCartType = GB_MBC5; + Cart->bHasRam = true; + Cart->bHasBattery = false; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x1B: + Cart->iCartType = GB_MBC5; + Cart->bHasRam = true; + Cart->bHasBattery = true; + Cart->bHasTimer = false; + Cart->bHasRumble = false; + break; + case 0x1C: + Cart->iCartType = GB_MBC5; + Cart->bHasRam = false; + Cart->bHasBattery = false; + Cart->bHasTimer = false; + Cart->bHasRumble = true; + break; + case 0x1D: + Cart->iCartType = GB_MBC5; + Cart->bHasRam = true; + Cart->bHasBattery = false; + Cart->bHasTimer = false; + Cart->bHasRumble = true; + break; + case 0x1E: + Cart->iCartType = GB_MBC5; + Cart->bHasRam = true; + Cart->bHasBattery = true; + Cart->bHasTimer = false; + Cart->bHasRumble = true; + break; + default: + WarningMessage( IDS_ERR_GBROM, MB_OK | MB_ICONWARNING); + DebugWriteA("TPak: unsupported paktype\n"); + UnloadCart(Cart); + return false; + } + + // assign read/write handlers + switch (Cart->iCartType) { + case GB_NORM: // Raw cartridge + Cart->ptrfnReadCart = &ReadCartNorm; + Cart->ptrfnWriteCart = &WriteCartNorm; + break; + case GB_MBC1: + Cart->ptrfnReadCart = &ReadCartMBC1; + Cart->ptrfnWriteCart = &WriteCartMBC1; + break; + case GB_MBC2: + Cart->ptrfnReadCart = &ReadCartMBC2; + Cart->ptrfnWriteCart = &WriteCartMBC2; + break; + case GB_MBC3: + Cart->ptrfnReadCart = &ReadCartMBC3; + Cart->ptrfnWriteCart = &WriteCartMBC3; + break; + case GB_MBC5: + Cart->ptrfnReadCart = &ReadCartMBC5; + Cart->ptrfnWriteCart = &WriteCartMBC5; + break; + default: // Don't pretend we know how to handle carts we don't support + Cart->ptrfnReadCart = NULL; + Cart->ptrfnWriteCart = NULL; + DebugWriteA("Unsupported paktype: can't read/write cart type %02X\n", Cart->iCartType); + UnloadCart(Cart); + return false; + } + + // Determine ROM size for paging checks + Cart->iNumRomBanks = 2; + switch (Cart->RomData[0x148]) { + case 0x01: + Cart->iNumRomBanks = 4; + break; + case 0x02: + Cart->iNumRomBanks = 8; + break; + case 0x03: + Cart->iNumRomBanks = 16; + break; + case 0x04: + Cart->iNumRomBanks = 32; + break; + case 0x05: + Cart->iNumRomBanks = 64; + break; + case 0x06: + Cart->iNumRomBanks = 128; + break; + case 0x52: + Cart->iNumRomBanks = 72; + break; + case 0x53: + Cart->iNumRomBanks = 80; + break; + case 0x54: + Cart->iNumRomBanks = 96; + break; + } + + if (dwFilesize != 0x4000 * Cart->iNumRomBanks) // Now that we know how big the ROM is supposed to be, check it again + { + ErrorMessage(IDS_ERR_GBROM, 0, false); + + UnloadCart(Cart); + return false; + } + + // Determine RAM size for paging checks + Cart->iNumRamBanks = 0; + switch (Cart->RomData[0x149]) { + case 0x01: + Cart->iNumRamBanks = 1; + NumQuarterBlocks = 1; + break; + case 0x02: + Cart->iNumRamBanks = 1; + NumQuarterBlocks = 4; + break; + case 0x03: + Cart->iNumRamBanks = 4; + NumQuarterBlocks = 16; + break; + case 0x04: + Cart->iNumRamBanks = 16; + NumQuarterBlocks = 64; + break; + case 0x05: + Cart->iNumRamBanks = 8; + NumQuarterBlocks = 32; + break; + } + + DebugWriteA("GB cart has %d ROM banks, %d RAM quarter banks\n", Cart->iNumRomBanks, NumQuarterBlocks); + if (Cart->bHasTimer) + { + DebugWriteA("GB cart timer present\n"); + } + + // Attempt to load the SRAM file, but only if RAM is supposed to be present. + // For saving back to a file, if we map too much it will expand the file. + if (Cart->bHasRam) + { + if (Cart->bHasBattery) + { + hTemp = CreateFile( RamFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL ); + if( hTemp == INVALID_HANDLE_VALUE ) + {// test if Read-only access is possible + hTemp = CreateFile( RamFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL ); + if (Cart->bHasTimer && Cart->bHasBattery) { + Cart->RamData = (LPBYTE)P_malloc(NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC)); + ClearData(Cart->RamData, NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC)); + } + else { + Cart->RamData = (LPBYTE)P_malloc(NumQuarterBlocks * 0x0800); + ClearData(Cart->RamData, NumQuarterBlocks * 0x0800); + } + + if( hTemp != INVALID_HANDLE_VALUE ) + { + DWORD dwBytesRead; + + if (Cart->bHasTimer && Cart->bHasBattery) + ReadFile(hTemp, Cart->RamData, NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC), &dwBytesRead, NULL); + else + ReadFile(hTemp, Cart->RamData, NumQuarterBlocks * 0x0800, &dwBytesRead, NULL); + WarningMessage( IDS_DLG_TPAK_READONLY, MB_OK | MB_ICONWARNING); + } + else + { + WarningMessage( IDS_ERR_GBSRAMERR, MB_OK | MB_ICONWARNING); + return true; + } + } else { // file is OK, use a mapping + if (Cart->bHasTimer && Cart->bHasBattery) + Cart->hRamFile = CreateFileMapping( hTemp, NULL, PAGE_READWRITE, 0, NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC), NULL); + else + Cart->hRamFile = CreateFileMapping( hTemp, NULL, PAGE_READWRITE, 0, NumQuarterBlocks * 0x0800, NULL); + + if (Cart->hRamFile != NULL) + { + Cart->RamData = (LPBYTE)MapViewOfFile( Cart->hRamFile, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); + } else { // could happen, if the file isn't big enough AND can't be grown to fit + DWORD dwBytesRead; + if (Cart->bHasTimer && Cart->bHasBattery) { + Cart->RamData = (LPBYTE)P_malloc(NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC)); + ReadFile(hTemp, Cart->RamData, NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC), &dwBytesRead, NULL); + } else { + Cart->RamData = (LPBYTE)P_malloc(NumQuarterBlocks * 0x0800); + ReadFile(hTemp, Cart->RamData, NumQuarterBlocks * 0x0800, &dwBytesRead, NULL); + } + if (dwBytesRead < NumQuarterBlocks * 0x0800 + ((Cart->bHasTimer && Cart->bHasBattery) ? sizeof(gbCartRTC) : 0)) + { + ClearData(Cart->RamData, NumQuarterBlocks * 0x0800 + ((Cart->bHasTimer && Cart->bHasBattery) ? sizeof(gbCartRTC) : 0)); + WarningMessage( IDS_ERR_GBSRAMERR, MB_OK | MB_ICONWARNING); + } + else + { + WarningMessage( IDS_DLG_TPAK_READONLY, MB_OK | MB_ICONWARNING); + } + } + } + + if (Cart->bHasTimer && Cart->bHasBattery) { + dwFilesize = GetFileSize(hTemp, 0); + if (dwFilesize >= (NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC) ) ) { + // Looks like there is extra data in the SAV file than just RAM data... assume it is RTC data. + gbCartRTC RTCTimer; + CopyMemory( &RTCTimer, &Cart->RamData[NumQuarterBlocks * 0x0800], sizeof(RTCTimer) ); + Cart->TimerData[0] = RTCTimer.mapperSeconds; + Cart->TimerData[1] = RTCTimer.mapperMinutes; + Cart->TimerData[2] = RTCTimer.mapperHours; + Cart->TimerData[3] = RTCTimer.mapperDays; + Cart->TimerData[4] = RTCTimer.mapperControl; + Cart->LatchedTimerData[0] = RTCTimer.mapperLSeconds; + Cart->LatchedTimerData[1] = RTCTimer.mapperLMinutes; + Cart->LatchedTimerData[2] = RTCTimer.mapperLHours; + Cart->LatchedTimerData[3] = RTCTimer.mapperLDays; + Cart->LatchedTimerData[4] = RTCTimer.mapperLControl; + Cart->timerLastUpdate = RTCTimer.mapperLastTime; + UpdateRTC(Cart); + } + else { + ReadTDF(Cart); // try to open TDF format, clear/init Cart->TimerData if that fails + } + } + + CloseHandle(hTemp); + } else { + // no battery; just allocate some RAM + Cart->RamData = (LPBYTE)P_malloc(Cart->iNumRamBanks * 0x2000); + } + } + + Cart->TimerDataLatched = false; + + return true; +} + +// Done +bool ReadCartNorm(LPGBCART Cart, WORD dwAddress, BYTE *Data) // For all non-MBC carts; fixed 0x8000 ROM; fixed, optional 0x2000 RAM +{ + switch (dwAddress >> 13) // hack: examine highest 3 bits + { + case 0: + case 1: + case 2: + case 3: // if ((dwAddress >= 0) && (dwAddress <= 0x7FFF)) + CopyMemory(Data, &Cart->RomData[dwAddress], 32); + DebugWriteA("Nonbanked ROM read - RAW\n"); + break; + case 5: + if (Cart->bHasRam) // no MBC, so no enable state to check + { + if (Cart->RomData[0x149] == 1 && (dwAddress - 0xA000) / 0x0800 ) // Only 1/4 of the RAM space is used, and we're out of bounds + { + DebugWriteA("Failed RAM read: Unbanked (out of bounds)"); + ZeroMemory(Data, 32); + } + else + { + CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000], 32); + DebugWriteA("RAM read: Unbanked\n"); + } + } + else + { + ZeroMemory(Data, 32); + DebugWriteA("Failed RAM read: Unbanked (RAM not present)\n"); + } + break; + default: + DebugWriteA("Bad read from RAW cart, address %04X\n", dwAddress); + } + + return true; +} + +// Done +bool WriteCartNorm(LPGBCART Cart, WORD dwAddress, BYTE *Data) +{ + if (!Cart->bHasRam) + { + DebugWriteA("RAM write: no RAM\n"); + return true; + } + + if (Cart->RomData[0x149] == 1) { // Whoops... Only 1/4 of the RAM space is used. + if ((dwAddress >= 0xA000) && (dwAddress <= 0xA7FF)) { // Write to RAM + DebugWriteA("RAM write: Unbanked\n"); + CopyMemory(&Cart->RamData[dwAddress - 0xA000], Data, 32); + } + else + { + DebugWriteA("RAM write: Unbanked (out of range!)\n"); + } + } else { + if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) { // Write to RAM + DebugWriteA("RAM write: Unbanked\n"); + CopyMemory(&Cart->RamData[dwAddress - 0xA000], Data, 32); + } + } + return true; +} + +// Done +bool ReadCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data) +{ + switch (dwAddress >> 13) + { + case 0: + case 1: // if ((dwAddress >= 0) && (dwAddress <= 0x3FFF)) + CopyMemory(Data, &Cart->RomData[dwAddress], 32); + DebugWriteA("Nonbanked ROM read - MBC1\n"); + break; + case 2: + case 3: // else if ((dwAddress >= 0x4000) && (dwAddress <= 0x7FFF)) + if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks) + { + ZeroMemory(Data, 32); + DebugWriteA("Banked ROM read: (Banking Error) Bank %02X\n", Cart->iCurrentRomBankNo); + } + else + { + // for (i=0; i<32; i++) Data[i] = Cart->RomData[(dwAddress - 0x4000) + i + (Cart->iCurrentRomBankNo * 0x4000)]; + CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo << 14)], 32); + DebugWriteA("Banked ROM read: Bank %02X\n", Cart->iCurrentRomBankNo); + } + break; + case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) + if (Cart->bHasRam){ // && Cart->bRamEnableState) { + if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks) { + ZeroMemory(Data, 32); + DebugWriteA("Failed RAM read: (Banking Error) %02X\n", Cart->iCurrentRamBankNo); + } else { + CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], 32); + DebugWriteA("RAM read: Bank %02X\n", Cart->iCurrentRamBankNo); + } + } else { + ZeroMemory(Data, 32); + DebugWriteA("Failed RAM read: (RAM not present)\n"); + } + break; + default: + DebugWriteA("Bad read from MBC1 cart, address %04X\n", dwAddress); + } + + return true; +} + +// Done +bool WriteCartMBC1(LPGBCART Cart, WORD dwAddress, BYTE *Data) +{ + switch (dwAddress >> 13) + { + case 0: // if ((dwAddress >= 0) && (dwAddress <= 0x1FFF)) // RAM enable + Cart->bRamEnableState = (Data[0] == 0x0A); + DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState); + break; + case 1: // else if ((dwAddress >= 0x2000) && (dwAddress <= 0x3FFF)) // ROM bank select + Cart->iCurrentRomBankNo &= 0x60; // keep MSB + Cart->iCurrentRomBankNo |= Data[0] & 0x1F; + + // emulate quirk: 0x00 -> 0x01, 0x20 -> 0x21, 0x40->0x41, 0x60 -> 0x61 + if ((Cart->iCurrentRomBankNo & 0x1F) == 0) { + Cart->iCurrentRomBankNo |= 0x01; + } + DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo); + break; + case 2: // else if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM bank select + if (Cart->bMBC1RAMbanking) { + Cart->iCurrentRamBankNo = Data[0] & 0x03; + DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo); + } + else { + Cart->iCurrentRomBankNo &= 0x1F; + Cart->iCurrentRomBankNo |= ((Data[0] & 0x03) << 5); // set bits 5 and 6 of ROM bank + DebugWriteA("Set ROM Bank MSB, ROM bank now: %02X\n", Cart->iCurrentRomBankNo); + } + break; + case 3: // else if ((dwAddress >= 0x6000) && (dwAddress <= 0x7FFF)) // MBC1 mode select + // this is overly complicated, but it keeps us from having to do bitwise math later + // Basically we shuffle the 2 "magic bits" between iCurrentRomBankNo and iCurrentRamBankNo as necessary. + if (Cart->bMBC1RAMbanking != (Data[0] & 0x01)) { + // we should only alter the ROM and RAM bank numbers if we have changed modes + Cart->bMBC1RAMbanking = Data[0] & 0x01; + if (Cart->bMBC1RAMbanking) + { + Cart->iCurrentRamBankNo = Cart->iCurrentRomBankNo >> 5; // set the ram bank to the "magic bits" + Cart->iCurrentRomBankNo &= 0x1F; // zero out bits 5 and 6 to keep consistency + } + else + { + Cart->iCurrentRomBankNo &= 0x1F; + Cart->iCurrentRomBankNo |= (Cart->iCurrentRamBankNo << 5); + Cart->iCurrentRamBankNo = 0x00; // we can only reach RAM page 0 + } + DebugWriteA("Set MBC1 mode: %s\n", Cart->bMBC1RAMbanking ? "ROMbanking" : "RAMbanking" ); + } + else + { + DebugWriteA("Already in MBC1 mode: %s\n", Cart->bMBC1RAMbanking ? "ROMbanking" : "RAMbanking" ); + } + + break; + case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) // Write to RAM + if (Cart->bHasRam) // && Cart->bRamEnableState) + { + DebugWriteA("RAM write: Bank %02X\n", Cart->iCurrentRamBankNo); + CopyMemory(&Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], Data, 32); + } + else + { + DebugWriteA("Failed RAM write: (RAM not present)\n"); + } + break; + default: + DebugWriteA("Bad write to MBC1 cart, address %04X\n", dwAddress); + } + + return true; +} + +// Done +bool ReadCartMBC2(LPGBCART Cart, WORD dwAddress, BYTE *Data) +{ + switch (dwAddress >> 13) + { + case 0: + case 1: // if ((dwAddress <= 0x3FFF)) + CopyMemory(Data, &Cart->RomData[dwAddress], 32); + DebugWriteA("Nonbanked ROM read - MBC2\n"); + break; + case 2: + case 3: // else if ((dwAddress >= 0x4000) && (dwAddress <= 0x7FFF)) + if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks) { + ZeroMemory(Data, 32); + DebugWriteA("Banked ROM read: (Banking Error) %02X\n", Cart->iCurrentRomBankNo); + } else { + CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo << 14)], 32); + DebugWriteA("Banked ROM read: Bank %02X\n", Cart->iCurrentRomBankNo); + } + break; + case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) + if (Cart->bHasRam && Cart->bRamEnableState) { + CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000], 32); + DebugWriteA("RAM read: Unbanked\n"); + } else { + ZeroMemory(Data, 32); + DebugWriteA("Failed RAM read: (RAM not present or not active)\n"); + } + break; + default: + DebugWriteA("Bad read from MBC2 cart, address %04X\n", dwAddress); + } + + return true; +} + +// Done +bool WriteCartMBC2(LPGBCART Cart, WORD dwAddress, BYTE *Data) +{ + switch (dwAddress >> 13) + { + case 0: // if ((dwAddress <= 0x1FFF)) // We shouldn't be able to read/write to RAM unless this is toggled on + Cart->bRamEnableState = (Data[0] == 0x0A); + DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState); + break; + case 1: // else if ((dwAddress >= 0x2000) && (dwAddress <= 0x3FFF)) // ROM bank select + Cart->iCurrentRomBankNo = Data[0] & 0x0F; + if (Cart->iCurrentRomBankNo == 0) { + Cart->iCurrentRomBankNo = 1; + } + DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo); + break; + case 2: // if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM bank select + if (Cart->bHasRam) { + Cart->iCurrentRamBankNo = Data[0] & 0x07; + DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo); + } + break; + case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF) && Cart->bRamEnableState) // Write to RAM + if (Cart->bHasRam) { + DebugWriteA("RAM write: Bank %02X\n", Cart->iCurrentRamBankNo); + CopyMemory(&Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], Data, 32); + } + break; + default: + DebugWriteA("Bad write to MBC2 cart, address %04X\n", dwAddress); + } + + return true; +} + +// Done +bool ReadCartMBC3(LPGBCART Cart, WORD dwAddress, BYTE *Data) +{ + int i; + + switch (dwAddress >> 13) + { + case 0: + case 1: // if ((dwAddress <= 0x3FFF)) + CopyMemory(Data, &Cart->RomData[dwAddress], 32); + DebugWriteA("Nonbanked ROM read - MBC3\n"); + break; + case 2: + case 3: // else if ((dwAddress >= 0x4000) && (dwAddress <= 0x7FFF)) + if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks) { + ZeroMemory(Data, 32); + DebugWriteA("Banked ROM read: (Banking Error) %02X\n", Cart->iCurrentRomBankNo); + } else { + CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo * 0x4000)], 32); + DebugWriteA("Banked ROM read: Bank %02X\n", Cart->iCurrentRomBankNo); + } + break; + case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) + if (Cart->bHasTimer && (Cart->iCurrentRamBankNo >= 0x08 && Cart->iCurrentRamBankNo <= 0x0c)) { + // w00t! the Timer was just read!! + if (Cart->TimerDataLatched) { + for (i=0; i<32; i++) + Data[i] = Cart->LatchedTimerData[Cart->iCurrentRamBankNo - 0x08]; + } else { + UpdateRTC(Cart); + for (i=0; i<32; i++) + Data[i] = Cart->TimerData[Cart->iCurrentRamBankNo - 0x08]; + } + } + else if (Cart->bHasRam) { + if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks) { + ZeroMemory(Data, 32); + DebugWriteA("Failed RAM read: (Banking Error) %02X\n", Cart->iCurrentRamBankNo); + } + else { + CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo * 0x2000)], 32); + DebugWriteA("RAM read: Bank %02X\n", Cart->iCurrentRamBankNo); + } + //else { + // ZeroMemory(Data, 32); + // //for (i=0; i<32; i++) Data[i] = 0; + // DebugWriteA("Failed RAM read: (RAM not active)\n"); + //} + } else { + ZeroMemory(Data, 32); + DebugWriteA("Failed RAM read: (RAM not present)\n"); + } + break; + default: + DebugWriteA("Bad read from MBC3 cart, address %04X\n", dwAddress); + } + + return true; +} + +// Done +bool WriteCartMBC3(LPGBCART Cart, WORD dwAddress, BYTE *Data) +{ + int i; + + switch (dwAddress >> 13) + { + case 0: // if ((dwAddress <= 0x1FFF)) // We shouldn't be able to read/write to RAM unless this is toggled on + Cart->bRamEnableState = (Data[0] == 0x0A); + DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState); + break; + case 1: // else if ((dwAddress >= 0x2000) && (dwAddress <= 0x3FFF)) // ROM bank select + Cart->iCurrentRomBankNo = Data[0] & 0x7F; + if (Cart->iCurrentRomBankNo == 0) { + Cart->iCurrentRomBankNo = 1; + } + DebugWriteA("Set Rom Bank: %02X\n", Cart->iCurrentRomBankNo); + break; + case 2: // if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM/Clock bank select + if (Cart->bHasRam) { + Cart->iCurrentRamBankNo = Data[0] & 0x03; + DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo); + if (Cart->bHasTimer && (Data[0] >= 0x08 && Data[0] <= 0x0c)) { + // Set the bank for the timer + Cart->iCurrentRamBankNo = Data[0]; + } + } + break; + case 3: // else if ((dwAddress >= 0x6000) && (dwAddress <= 0x7FFF)) // Latch timer data + CopyMemory(Cart->LatchedTimerData, Cart->TimerData, 5 * sizeof(Cart->TimerData[0])); + if (Data[0] & 1) { + // Update timer, save latch values, and set latch state + UpdateRTC(Cart); + for (i=0; i<4; i++) + Cart->LatchedTimerData[i] = Cart->TimerData[i]; + Cart->TimerDataLatched = true; + DebugWriteA("Timer Data Latch: Enable\n"); + } else { + Cart->TimerDataLatched = false; + DebugWriteA("Timer Data Latch: Disable\n"); + } + break; + case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) // Write to RAM + if (Cart->bHasRam) { + if (Cart->iCurrentRamBankNo >= 0x08 && Cart->iCurrentRamBankNo <= 0x0c) { + // Write to the timer + DebugWriteA("Timer write: Bank %02X\n", Cart->iCurrentRamBankNo); + Cart->TimerData[Cart->iCurrentRamBankNo - 0x08] = Data[0]; + } else { + DebugWriteA("RAM write: Bank %02X%s\n", Cart->iCurrentRamBankNo, Cart->bRamEnableState ? "" : " -- NOT ENABLED (but wrote anyway)"); + CopyMemory(&Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo * 0x2000)], Data, 32); + } + } + break; + default: + DebugWriteA("Bad write to MBC3 cart, address %04X\n", dwAddress); + } + + return true; +} + +// Done +bool ReadCartMBC5(LPGBCART Cart, WORD dwAddress, BYTE *Data) +{ + switch (dwAddress >> 13) + { + case 0: + case 1: // if ((dwAddress <= 0x3FFF)) + CopyMemory(Data, &Cart->RomData[dwAddress], 32); + DebugWriteA("Nonbanked ROM read - MBC5\n"); + break; + case 2: + case 3: // else if ((dwAddress >= 0x4000) && (dwAddress <= 0x7FFF)) + if (Cart->iCurrentRomBankNo >= Cart->iNumRomBanks) { + ZeroMemory(Data, 32); + DebugWriteA("Banked ROM read: (Banking Error)"); + DebugWriteByteA(Cart->iCurrentRomBankNo); + DebugWriteA("\n"); + } else { + CopyMemory(Data, &Cart->RomData[dwAddress - 0x4000 + (Cart->iCurrentRomBankNo << 14)], 32); + DebugWriteA("Banked ROM read: Bank="); + DebugWriteByteA(Cart->iCurrentRomBankNo); + DebugWriteA("\n"); + } + break; + case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) + if (Cart->bHasRam) { + if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks) { + ZeroMemory(Data, 32); + DebugWriteA("Failed RAM read: (Banking Error) %02X\n", Cart->iCurrentRamBankNo); + } else { + CopyMemory(Data, &Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], 32); + DebugWriteA("RAM read: Bank %02X\n", Cart->iCurrentRamBankNo); + } + } else { + ZeroMemory(Data, 32); + DebugWriteA("Failed RAM read: (RAM Not Present)\n"); + } + break; + default: + DebugWriteA("Bad read from MBC5 cart, address %04X\n", dwAddress); + } + + return true; +} + +// Done +bool WriteCartMBC5(LPGBCART Cart, WORD dwAddress, BYTE *Data) +{ + switch (dwAddress >> 13) + { + case 0: // if ((dwAddress <= 0x1FFF)) // We shouldn't be able to read/write to RAM unless this is toggled on + Cart->bRamEnableState = (Data[0] == 0x0A); + DebugWriteA("Set RAM enable: %d\n", Cart->bRamEnableState); + break; + case 1: // else if ((dwAddress >= 0x2000) && (dwAddress <= 0x2FFF)) // ROM bank select, low bits + Cart->iCurrentRomBankNo &= 0xFF00; + Cart->iCurrentRomBankNo |= Data[0]; + // Cart->iCurrentRomBankNo = ((int) Data[0]) | (Cart->iCurrentRomBankNo & 0x100); + DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo); + break; + case 2: // else if ((dwAddress >= 0x3000) && (dwAddress <= 0x3FFF)) // ROM bank select, high bit + Cart->iCurrentRomBankNo &= 0x00FF; + Cart->iCurrentRomBankNo |= (Data[0] & 0x01) << 8; + // Cart->iCurrentRomBankNo = (Cart->iCurrentRomBankNo & 0xFF) | ((((int) Data[0]) & 1) * 0x100); + DebugWriteA("Set ROM Bank: %02X\n", Cart->iCurrentRomBankNo); + break; + case 3: // if ((dwAddress >= 0x4000) && (dwAddress <= 0x5FFF)) // RAM bank select + if (Cart->bHasRam) { + Cart->iCurrentRamBankNo = Data[0] & 0x0F; + DebugWriteA("Set RAM Bank: %02X\n", Cart->iCurrentRamBankNo); + } + break; + case 5: // else if ((dwAddress >= 0xA000) && (dwAddress <= 0xBFFF)) // Write to RAM + if (Cart->bHasRam) { + if (Cart->iCurrentRamBankNo >= Cart->iNumRamBanks) { + DebugWriteA("RAM write: Buffer error on "); + DebugWriteByteA(Cart->iCurrentRamBankNo); + DebugWriteA("\n"); + } else { + DebugWriteA("RAM write: Bank %02X\n", Cart->iCurrentRamBankNo); + CopyMemory(&Cart->RamData[dwAddress - 0xA000 + (Cart->iCurrentRamBankNo << 13)], Data, 32); + } + } + break; + default: + DebugWriteA("Bad write to MBC5 cart, address %04X\n", dwAddress); + } + + return true; +} + +bool SaveCart(LPGBCART Cart, LPTSTR SaveFile, LPTSTR TimeFile) +{ + DWORD NumQuarterBlocks = 0; + gbCartRTC RTCTimer; + + if (Cart->bHasRam && Cart->bHasBattery) { + // Write only the bytes that NEED writing! + switch (Cart->RomData[0x149]) { + case 1: + NumQuarterBlocks = 1; + break; + case 2: + NumQuarterBlocks = 4; + break; + case 3: + NumQuarterBlocks = 16; + break; + case 4: + NumQuarterBlocks = 64; + break; + } + FlushViewOfFile( Cart->RamData, NumQuarterBlocks * 0x0800 ); + if (Cart->bHasTimer) { + // Save RTC in VisualBoy Advance format + // TODO: Check if VBA saves are compatible with other emus. + // TODO: Only write RTC data if VBA RTC data was originaly present + RTCTimer.mapperSeconds = Cart->TimerData[0]; + RTCTimer.mapperMinutes = Cart->TimerData[1]; + RTCTimer.mapperHours = Cart->TimerData[2]; + RTCTimer.mapperDays = Cart->TimerData[3]; + RTCTimer.mapperControl = Cart->TimerData[4]; + RTCTimer.mapperLSeconds = Cart->LatchedTimerData[0]; + RTCTimer.mapperLMinutes = Cart->LatchedTimerData[1]; + RTCTimer.mapperLHours = Cart->LatchedTimerData[2]; + RTCTimer.mapperLDays = Cart->LatchedTimerData[3]; + RTCTimer.mapperLControl = Cart->LatchedTimerData[4]; + RTCTimer.mapperLastTime = Cart->timerLastUpdate; + + CopyMemory(Cart->RamData + NumQuarterBlocks * 0x0800, &RTCTimer, sizeof(RTCTimer)); + + FlushViewOfFile( Cart->RamData + NumQuarterBlocks * 0x0800, sizeof(gbCartRTC)); + } + } + return true; +} + +bool UnloadCart(LPGBCART Cart) +{ + if (Cart->hRomFile != NULL) + { + UnmapViewOfFile(Cart->RomData); + CloseHandle(Cart->hRomFile); + Cart->hRomFile = NULL; + } + else if (Cart->RomData != NULL) + { + P_free((LPVOID)(Cart->RomData)); + Cart->RomData = NULL; + } + + if (Cart->hRamFile != NULL) + { + UnmapViewOfFile(Cart->RamData); + CloseHandle(Cart->hRamFile); + Cart->hRamFile = NULL; + } + else if (Cart->RamData != NULL) + { + P_free(Cart->RamData); + Cart->RamData = NULL; + } + return true; +} + +// This is used to clear the RAM data to look like it has just been turned on. +// When a RAM chip is first turned on, it is filled with alternating 128-byte +// blocks of 0x00 and 0xFF. +void ClearData(BYTE *Data, int Length) +{ + int i; + + for (i=0; i +#include + +typedef struct _gbCartRTC { + UINT mapperSeconds; + UINT mapperMinutes; + UINT mapperHours; + UINT mapperDays; + UINT mapperControl; + UINT mapperLSeconds; + UINT mapperLMinutes; + UINT mapperLHours; + UINT mapperLDays; + UINT mapperLControl; + time_t mapperLastTime; +} gbCartRTC, *lpgbCartRTC; + +typedef struct _GBCART +{ + unsigned int iCurrentRomBankNo; + unsigned int iCurrentRamBankNo; + int iCartType; + bool bHasRam; + bool bHasBattery; + bool bHasTimer; + bool bHasRumble; + bool bRamEnableState; + bool bMBC1RAMbanking; // if false, use 2 magic bits for Most Significant Bits of ROM banking (default); if true, use the 2 magic bits for RAM banking + unsigned int iNumRomBanks; + unsigned int iNumRamBanks; + BYTE TimerData[5]; + BYTE LatchedTimerData[5]; + time_t timerLastUpdate; + bool TimerDataLatched; + HANDLE hRomFile; // a file mapping handle + HANDLE hRamFile; // a file mapping handle, must be NULL if malloc'd ram is being used instead of a valid memory mapped file + const unsigned char * RomData; // max [0x200 * 0x4000]; + LPBYTE RamData; // max [0x10 * 0x2000]; + bool (*ptrfnReadCart)(_GBCART * Cart, WORD dwAddress, BYTE *Data); // ReadCart handler + bool (*ptrfnWriteCart)(_GBCART * Cart, WORD dwAddress, BYTE *Data); // WriteCart handler +} GBCART, *LPGBCART; + +bool LoadCart(LPGBCART Cart, LPCTSTR RomFile, LPCTSTR RamFile, LPCTSTR TdfFile); +// bool ReadCart(LPGBCART Cart, WORD dwAddress, BYTE *Data); +// bool WriteCart(LPGBCART Cart, WORD dwAddress, BYTE *Data); +bool SaveCart(LPGBCART Cart, LPTSTR SaveFile, LPTSTR TimeFile); +bool UnloadCart(LPGBCART Cart); + +/* +iCartType values: +0 = no MBC +1 = MBC1 +2 = MBC2 +3 = MMMO1 +4 = MBC3 +5 = MBC5 +6 = Pocket Camera +7 = TAMA 5 +8 = HuC 3 +9 = HuC 1 +Note, that 6 and up are not implemented yet. +*/ + +#define GB_NORM 0x00 +#define GB_MBC1 0x01 +#define GB_MBC2 0x02 +#define GB_MMMO1 0x03 +#define GB_MBC3 0x04 +#define GB_MBC5 0x05 +#define GB_CAMERA 0x06 +#define GB_TAMA5 0x07 +#define GB_HUC3 0x08 +#define GB_HUC1 0x09 + +#endif // #ifndef _GBCART_H_ diff --git a/Source/nragev20/Interface.cpp b/Source/nragev20/Interface.cpp new file mode 100644 index 000000000..2b37b3dcf --- /dev/null +++ b/Source/nragev20/Interface.cpp @@ -0,0 +1,4056 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "commonIncludes.h" +#include +#include +#include +#include "NRagePluginV2.h" +#include "DirectInput.h" +#include "XInputController.h" +#include "FileAccess.h" +#include "PakIO.h" +#include "Interface.h" +#include "International.h" + +// Prototypes // +BOOL CALLBACK ControllerTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +BOOL CALLBACK ControlsTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +BOOL CALLBACK XControlsTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); // Xinput Control main proc. --tecnicors +BOOL CALLBACK DevicesTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +BOOL CALLBACK ModifierTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +BOOL CALLBACK ControllerPakTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +BOOL CALLBACK PakProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +BOOL CALLBACK MemPakProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +BOOL CALLBACK RumblePakProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +BOOL CALLBACK TransferPakProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +BOOL CALLBACK ShortcutsTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +BOOL CALLBACK FoldersDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +LRESULT CALLBACK BlockerProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ); +BOOL InitOverlay(); +HWND MakeOverlay(); + +// BOOL CALLBACK EnumGetKeyDesc( LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef ); // nope, sorry. --rabid +bool GetButtonID( LPDWORD ButtonID, const BYTE bIndex, const BYTE bButtonSet ); +bool GetButtonText( const BUTTON& btnButton, LPTSTR Buffer); +DWORD ScanDevices( LPDWORD lpdwCounter, LPBUTTON pButton ); + +void DeleteControllerSettings( int indexController ); +void GetCurrentConfiguration(); +void UpdateControllerStructures(); + +// global Variables // +INTERFACEVALUES *g_ivConfig = NULL; // this structure holds all GUI-Data; it points to a valid struct only if the config window is open +LPDIRECTINPUTDEVICE8 g_pConfigDevice = NULL; // one device handle for current FF device; between messages so it needs to be persistent +LPDIRECTINPUTEFFECT g_pConfigEffect = NULL; // FF-effect handle +HWND g_hMainDialog = NULL; // handle of base-dialog + +// Main dialog control handler +BOOL CALLBACK MainDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + static HWND hTabControl; + HWND hDlgItem; + long i,j; + + switch(uMsg) + { + case WM_INITDIALOG: + { + DebugWriteA("Config interface: Open\n"); + g_ivConfig = (INTERFACEVALUES*)P_malloc( sizeof(INTERFACEVALUES) ); // TODO: CHECK THIS MALLOC! + ZeroMemory( g_ivConfig, sizeof(INTERFACEVALUES) ); + + CopyMemory( &g_ivConfig->Shortcuts, &g_scShortcuts ,sizeof(SHORTCUTS) ); + for( i = 0; i < 4; ++i ) + DeleteControllerSettings( i ); + + EnterCriticalSection( &g_critical ); // block because the InitiateControllers code may still be running. + if( !g_strEmuInfo.fInitialisedPlugin ) + { + LoadConfigFromINI(); + } + + GetCurrentConfiguration(); + + LeaveCriticalSection( &g_critical ); + + + g_hMainDialog = hDlg; + + // Display Version + { + TCHAR tszBuffer[DEFAULT_BUFFER], tszMsg[DEFAULT_BUFFER / 2]; + + LoadString( g_hResourceDLL, IDS_VERSTRING, tszBuffer, DEFAULT_BUFFER / 2); + _stprintf(tszMsg, tszBuffer, VERSIONINFO); + SetDlgItemText( hDlg, IDC_VERSIONSTRING, tszMsg ); + } + + + // Tab - Control // + hTabControl = NULL; + hDlgItem = GetDlgItem( hDlg, IDC_UPPERTAB ); + + TCITEM tcItem; + tcItem.mask = TCIF_TEXT; + + TCHAR tszText[DEFAULT_BUFFER], tszBuff[DEFAULT_BUFFER]; + tcItem.pszText = tszText; + + LoadString( g_hResourceDLL, IDS_TAB_CONTROLLER, tszBuff, DEFAULT_BUFFER ); + + for (int i = 0; i < 4; i++ ) + { + wsprintf( tszText, tszBuff, i + 1 ); + TabCtrl_InsertItem( hDlgItem, i, &tcItem ); + } + + LoadString( g_hResourceDLL, IDS_TAB_SHORTCUTS, tszText, DEFAULT_BUFFER ); + TabCtrl_InsertItem( hDlgItem, TAB_SHORTCUTS, &tcItem ); + // Tab - Control End // + + g_ivConfig->ChosenTab = TAB_CONTROLLER1; + TabCtrl_SetCurSel( GetDlgItem( hDlg, IDC_UPPERTAB), g_ivConfig->ChosenTab ); + NMHDR nmInit; + nmInit.hwndFrom = hDlgItem; + nmInit.idFrom = IDC_UPPERTAB; + nmInit.code = TCN_SELCHANGE; + MainDlgProc( hDlg, WM_NOTIFY, IDC_UPPERTAB, (LPARAM)&nmInit ); + + // we can't click "Use" without saving when not emulating, because the emu resets controls before loading a ROM + if( !g_bRunning ) + EnableWindow( GetDlgItem( hDlg, IDUSE ), FALSE ); + +#ifndef _UNICODE + EnableWindow( GetDlgItem( hDlg, IDC_LANGUAGE), FALSE ); +#endif // #ifdef _UNICODE + InitOverlay(); + } + + // call routine to show content( recursive call ) + MainDlgProc( hDlg, WM_USER_UPDATE, 0, 0 ); + return TRUE; // the system sets focus to one control element + + case WM_NOTIFY: + hDlgItem = ((LPNMHDR)lParam)->hwndFrom; + i = ((LPNMHDR)lParam)->code; + j = ((LPNMHDR)lParam)->idFrom; + + switch( j ) + { + case IDC_UPPERTAB: + if( i == TCN_SELCHANGE ) + { + i = g_ivConfig->ChosenTab; + g_ivConfig->ChosenTab = TabCtrl_GetCurSel( hDlgItem ); + + if( hTabControl ) + { + if( (( i == TAB_CONTROLLER1 ) || ( i == TAB_CONTROLLER2 ) || ( i == TAB_CONTROLLER3 ) || ( i == TAB_CONTROLLER4 )) && + (( g_ivConfig->ChosenTab == TAB_CONTROLLER1 ) || ( g_ivConfig->ChosenTab == TAB_CONTROLLER2 ) || ( g_ivConfig->ChosenTab == TAB_CONTROLLER3 ) || ( g_ivConfig->ChosenTab == TAB_CONTROLLER4 ))) + { + MainDlgProc( hDlg, WM_USER_UPDATE, 0, 0 ); + return TRUE; + } + else + DestroyWindow( hTabControl ); + } + + switch( g_ivConfig->ChosenTab ) + { + case TAB_CONTROLLER1: + case TAB_CONTROLLER2: + case TAB_CONTROLLER3: + case TAB_CONTROLLER4: + hTabControl = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_CONTROLLER ), hDlg, ControllerTabProc ); + break; + case TAB_SHORTCUTS: + hTabControl = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_SHORTCUT ), hDlg, ShortcutsTabProc ); + break; + default: + hTabControl = NULL; + return TRUE; + } + + RECT rectWindow, + rectTab, rectMain; // need to know the position of the calling tab window relative to its parent + + GetWindowRect( hDlg, &rectMain ); + GetWindowRect( hDlgItem, &rectTab ); + + GetClientRect( hDlgItem, &rectWindow ); + TabCtrl_AdjustRect( hDlgItem, FALSE, &rectWindow ); + + // second, third param: plus Tabwindow's position relative to main + MoveWindow( hTabControl, (rectTab.left - rectMain.left), (rectTab.top - rectMain.top), rectWindow.right - rectWindow.left, rectWindow.bottom - rectWindow.top, FALSE ); + ShowWindow( hTabControl, SW_SHOW ); + } + return TRUE; + default: + return FALSE; + } + + case WM_COMMAND: + hDlgItem = GetDlgItem( hDlg, LOWORD(wParam) ); + + switch( LOWORD(wParam) ) + { + case IDSAVE: + if( hTabControl ) + { + DestroyWindow( hTabControl ); + hTabControl = NULL; + } + DebugWriteA("Config interface: Save\n"); + StoreConfigToINI(); + // NO BREAK-- this is intentional + case IDUSE: + if( hTabControl ) + { + DestroyWindow( hTabControl ); + hTabControl = NULL; + } + DebugWriteA("Config interface: Use\n"); + CopyMemory( &g_scShortcuts ,&g_ivConfig->Shortcuts, sizeof(SHORTCUTS) ); + + UpdateControllerStructures(); + + EndDialog( hDlg, TRUE ); + return TRUE; + case IDCANCEL: + if( hTabControl ) + { + DestroyWindow( hTabControl ); + hTabControl = NULL; + } + EndDialog( hDlg, FALSE ); + return TRUE; + + case IDC_LANGUAGE: + if( HIWORD(wParam) == CBN_SELCHANGE ) + { + i = SendMessage( hDlgItem, CB_GETCURSEL, 0, 0 ); + g_ivConfig->Language = (LANGID) SendMessage( hDlgItem, CB_GETITEMDATA, i, 0 ); + } + return TRUE; + + case IDC_STOREINDB: + case IDC_UPDATEDB: + case IDC_ERASEFROMDB: + case IDC_SAVEPROFILE: + case IDC_LOADPROFILE: + // we don't have handlers for these, so fall through to FALSE + default: + return FALSE; + } + + case WM_CLOSE: + if( hTabControl ) + { + DestroyWindow( hTabControl ); + hTabControl = NULL; + } + EndDialog( hDlg, FALSE ); + return TRUE; + + case WM_DESTROY: + if( hTabControl ) + { + DestroyWindow( hTabControl ); + hTabControl = NULL; + } + EnterCriticalSection(&g_critical); + ReleaseEffect( g_pConfigEffect ); + ReleaseDevice( g_pConfigDevice ); + + for( i = 0; i < 4; ++i ) + { + freePakData( &g_ivConfig->Controllers[i] ); + freeModifiers( &g_ivConfig->Controllers[i] ); + } + P_free( g_ivConfig ); + g_ivConfig = NULL; + DebugWriteA("Config interface: Closed\n"); + LeaveCriticalSection(&g_critical); + return TRUE; + + case WM_USER_UPDATE: +#ifdef _UNICODE + // filling DropDownlist with languages + hDlgItem = GetDlgItem( hDlg, IDC_LANGUAGE ); + SendMessage (hDlgItem, CB_RESETCONTENT, 0, 0); + + { + TCHAR szBuffer[MAX_PATH]; + TCHAR * pSlash; + WIN32_FIND_DATA fData; + long lLangFound = 0; // the index matching our current language + + VerLanguageName(0x0009, szBuffer, DEFAULT_BUFFER); // English (default resource) + j = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)szBuffer ); + SendMessage( hDlgItem, CB_SETITEMDATA, j, 0 ); + + GetModuleFileName( NULL, szBuffer, MAX_PATH ); + pSlash = _tcsrchr( szBuffer, '\\' ); + _tcscpy(pSlash + 1, _T("NRage-Language-*.dll")); + + // Search for any file available called NRage-Language-XXXX.dll (where X is numbers) + HANDLE fSearch = FindFirstFile(szBuffer, &fData); + + while ( fSearch != INVALID_HANDLE_VALUE ) + { + DWORD dwLangID = 0; + if (_stscanf(fData.cFileName, _T("NRage-Language-%u.dll"), &dwLangID)) + { + VerLanguageName(dwLangID, szBuffer, DEFAULT_BUFFER); + j = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)szBuffer ); + SendMessage( hDlgItem, CB_SETITEMDATA, j, dwLangID ); + if (dwLangID == g_ivConfig->Language) + lLangFound = j; + } + if (!FindNextFile(fSearch, &fData)) + fSearch = INVALID_HANDLE_VALUE; + } + FindClose(fSearch); + + SendMessage( hDlgItem, CB_SETCURSEL, lLangFound, 0 ); // set combo box selection + } + // DropDownlist End +#else + hDlgItem = GetDlgItem( hDlg, IDC_LANGUAGE ); + SendMessage(hDlgItem, CB_RESETCONTENT, 0, 0); + j = SendMessage(hDlgItem, CB_ADDSTRING, 0, (LPARAM) _T("Language selection disabled")); + SendMessage( hDlgItem, CB_SETITEMDATA, j, 0 ); + SendMessage(hDlgItem, CB_SETCURSEL, 0, 0); +#endif // #ifdef _UNICODE + // call child-dialog(s) to update their content as well + if( hTabControl ) + SendMessage( hTabControl, WM_USER_UPDATE, 0, 0 ); + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +// return TRUE; //msg got processed +} + +BOOL CALLBACK ControllerTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + static HWND hTabControl; + + CONTROLLER *pcController = &g_ivConfig->Controllers[g_ivConfig->ChosenTab];; + HWND hDlgItem; + long i,j; + + switch(uMsg) + { + case WM_INITDIALOG: + hTabControl = NULL; + + // Tab - Control // + hDlgItem = GetDlgItem( hDlg, IDC_CONTROLLERTAB ); + + TCITEM tcItem; + tcItem.mask = TCIF_TEXT; + + TCHAR tszText[DEFAULT_BUFFER]; + tcItem.pszText = tszText; + + LoadString( g_hResourceDLL, IDS_TAB_CONTROLS, tszText, DEFAULT_BUFFER ); + TabCtrl_InsertItem( hDlgItem, TAB_CONTROLS, &tcItem ); + LoadString( g_hResourceDLL, IDS_TAB_DEVICES, tszText, DEFAULT_BUFFER ); + TabCtrl_InsertItem( hDlgItem, TAB_DEVICES, &tcItem ); + LoadString( g_hResourceDLL, IDS_TAB_MODIFIERS, tszText, DEFAULT_BUFFER ); + TabCtrl_InsertItem( hDlgItem, TAB_MODIFIERS, &tcItem ); + LoadString( g_hResourceDLL, IDS_TAB_CONTROLLERPAK, tszText, DEFAULT_BUFFER ); + TabCtrl_InsertItem( hDlgItem, TAB_PAK, &tcItem ); + + NMHDR nmInit; + nmInit.hwndFrom = hDlgItem; + nmInit.idFrom = IDC_CONTROLLERTAB; + nmInit.code = TCN_SELCHANGE; + + // initiate Tab-Display + ControllerTabProc( hDlg, WM_NOTIFY, IDC_CONTROLLERTAB, (LPARAM)&nmInit ); + // Tab - Control End // + + // call routine to show content( recursive call ) + ControllerTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); + + + return FALSE; // don't give it focus + + case WM_NOTIFY: + hDlgItem = ((LPNMHDR)lParam)->hwndFrom; + i = ((LPNMHDR)lParam)->code; + j = ((LPNMHDR)lParam)->idFrom; + + switch( j ) + { + case IDC_CONTROLLERTAB: + if( i == TCN_SELCHANGE ) + { + if( hTabControl ) + DestroyWindow( hTabControl ); + + i = TabCtrl_GetCurSel( hDlgItem ); + + switch( i ) + { + case TAB_CONTROLS: + if( pcController->fXInput) // added to show the xinput controller config tab --tecnicors + hTabControl = CreateDialog ( g_hResourceDLL, MAKEINTRESOURCE( IDD_XCONTROLS ), hDlg, XControlsTabProc ); + else + hTabControl = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_CONTROLS ), hDlg, ControlsTabProc ); + break; + case TAB_DEVICES: + hTabControl = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_DEVICES ), hDlg, DevicesTabProc ); + break; + case TAB_MODIFIERS: + hTabControl = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_MODIFIER ), hDlg, ModifierTabProc ); + break; + case TAB_PAK: + hTabControl = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_CONTROLLERPAK ), hDlg, ControllerPakTabProc ); + break; + default: + hTabControl = NULL; + return TRUE; + } + hDlgItem = GetDlgItem( hDlg, IDC_CONTROLLERTAB ); + + RECT rectWindow, + rectTab, rectMain; // need to know the position of the calling tab window relative to its parent + + GetWindowRect( hDlg, &rectMain ); + GetWindowRect( hDlgItem, &rectTab ); + + GetClientRect( hDlgItem, &rectWindow ); + TabCtrl_AdjustRect( hDlgItem, FALSE, &rectWindow ); + + MoveWindow( hTabControl, rectWindow.left + (rectTab.left - rectMain.left), rectWindow.top + (rectTab.top - rectMain.top), rectWindow.right - rectWindow.left, rectWindow.bottom - rectWindow.top, FALSE ); + ShowWindow( hTabControl, SW_SHOW ); + return TRUE; + } + else + return FALSE; + default: + return FALSE; + } + + case WM_COMMAND: + hDlgItem = GetDlgItem( hDlg, LOWORD(wParam) ); + + switch( LOWORD(wParam) ) + { + TCHAR tszTitle[DEFAULT_BUFFER], tszText[DEFAULT_BUFFER]; + case IDC_PLUGGED: + pcController->fPlugged = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + return TRUE; + case IDC_CLEARCONTROLLER: + LoadString( g_hResourceDLL, IDS_DLG_CLEAR, tszText, DEFAULT_BUFFER ); + LoadString( g_hResourceDLL, IDS_DLG_CLEAR_TITLE, tszTitle, DEFAULT_BUFFER ); + if( MessageBox( hDlg, tszText, tszTitle, MB_OKCANCEL | MB_ICONWARNING ) == IDOK ) + { + DeleteControllerSettings( g_ivConfig->ChosenTab ); + ControllerTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); + } + return TRUE; + case IDC_SETDEFAULT: + LoadString( g_hResourceDLL, IDS_DLG_CONTROLRESTORE, tszText, DEFAULT_BUFFER ); + LoadString( g_hResourceDLL, IDS_DLG_CONTROLRESTORE_TITLE, tszTitle, DEFAULT_BUFFER ); + if( MessageBox( hDlg, tszText, tszTitle, MB_OKCANCEL | MB_ICONWARNING ) == IDOK ) + { + DeleteControllerSettings( g_ivConfig->ChosenTab ); + LoadProfileFromResource( g_ivConfig->ChosenTab, true); + *(g_ivConfig->FFDevices[g_ivConfig->ChosenTab].szProductName) = '\0'; // default profile has no FF device + g_ivConfig->FFDevices[g_ivConfig->ChosenTab].bProductCounter = 0; + ControllerTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); + } + return TRUE; + + case IDC_SAVEPROFILE: + { + TCHAR szFilename[MAX_PATH+1] = _T(""); + if( BrowseFile( hDlg, szFilename, BF_PROFILE, BF_SAVE )) + { + FILE * fFile = _tfopen( szFilename, _T("wS") ); + if (fFile) + { + fprintf(fFile, "@" STRING_PROFILEVERSION "\n\n"); + FormatProfileBlock( fFile, g_ivConfig->ChosenTab ); + + fclose(fFile); + } + else + WarningMessage( IDS_ERR_PROFWRITE, MB_OK ); + } + } + return TRUE; + + case IDC_LOADPROFILE: + { + TCHAR szFilename[MAX_PATH+1] = TEXT( "" ); + if( BrowseFile( hDlg, szFilename, BF_PROFILE, BF_LOAD )) + { + DebugWrite(_T("Config interface: Load shortcuts file: %s\n"), szFilename); + if( LoadProfileFile( szFilename, g_ivConfig->ChosenTab, g_ivConfig->FFDevices[g_ivConfig->ChosenTab].szProductName, &g_ivConfig->FFDevices[g_ivConfig->ChosenTab].bProductCounter )) + ControllerTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); + else + WarningMessage( IDS_ERR_PROFREAD, MB_OK ); + + } + } + return TRUE; + + case IDC_XINPUT_ENABLER: // change to xinput config --tecnicors + pcController->fXInput = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + if( hTabControl ) + DestroyWindow( hTabControl ); + if( pcController->fXInput ) + hTabControl = CreateDialog ( g_hResourceDLL, MAKEINTRESOURCE( IDD_XCONTROLS ), hDlg, XControlsTabProc ); + else + hTabControl = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_CONTROLS ), hDlg, ControlsTabProc ); + { + hDlgItem = GetDlgItem( hDlg, IDC_CONTROLLERTAB ); + + RECT rectWindow, + rectTab, rectMain; // need to know the position of the calling tab window relative to its parent + + GetWindowRect( hDlg, &rectMain ); + GetWindowRect( hDlgItem, &rectTab ); + + GetClientRect( hDlgItem, &rectWindow ); + TabCtrl_AdjustRect( hDlgItem, FALSE, &rectWindow ); + + MoveWindow( hTabControl, rectWindow.left + (rectTab.left - rectMain.left), rectWindow.top + (rectTab.top - rectMain.top), rectWindow.right - rectWindow.left, rectWindow.bottom - rectWindow.top, FALSE ); + ShowWindow( hTabControl, SW_SHOW ); + } + return TRUE; // END IDC_XINPUT_ENABLER + + default: + return FALSE; + } + + case WM_USER_UPDATE: + // for this dialog + CheckDlgButton( hDlg, IDC_PLUGGED, pcController->fPlugged ? BST_CHECKED : BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_XINPUT_ENABLER, pcController->fXInput ? BST_CHECKED : BST_UNCHECKED ); + + if( hTabControl ) + DestroyWindow( hTabControl ); + if( pcController->fXInput ) + hTabControl = CreateDialog ( g_hResourceDLL, MAKEINTRESOURCE( IDD_XCONTROLS ), hDlg, XControlsTabProc ); + else + hTabControl = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_CONTROLS ), hDlg, ControlsTabProc ); + { + hDlgItem = GetDlgItem( hDlg, IDC_CONTROLLERTAB ); + + RECT rectWindow, + rectTab, rectMain; // need to know the position of the calling tab window relative to its parent + + GetWindowRect( hDlg, &rectMain ); + GetWindowRect( hDlgItem, &rectTab ); + + GetClientRect( hDlgItem, &rectWindow ); + TabCtrl_AdjustRect( hDlgItem, FALSE, &rectWindow ); + + MoveWindow( hTabControl, rectWindow.left + (rectTab.left - rectMain.left), rectWindow.top + (rectTab.top - rectMain.top), rectWindow.right - rectWindow.left, rectWindow.bottom - rectWindow.top, FALSE ); + ShowWindow( hTabControl, SW_SHOW ); + } + + // call child-dialog(s) to update their content as well + if( hTabControl ) + SendMessage( hTabControl, WM_USER_UPDATE, 0, 0 ); + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +} + +// "Controls" tab +BOOL CALLBACK ControlsTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + static LPBUTTON aButtons = NULL; // should point to g_ivConfig->Controllers[g_ivConfig->ChosenTab].aButton array + static DWORD dwButtonID[3]; // 0:ID of PushButton 1:ID of TextWindow 2:offset in aButtons struct + static DWORD dwCounter; + static bool bScanRunning; + static HWND hFocus = NULL; + static HWND hBlocker = NULL; + + TCHAR szBuffer[40], szTemp[40]; + HWND hDlgItem; + long i; + + switch(uMsg) + { + case WM_INITDIALOG: + // SetTicks on TrackBar + hDlgItem = GetDlgItem( hDlg, IDC_CTRRANGE ); + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 100 )); + SendMessage( hDlgItem, TBM_SETTICFREQ, (WPARAM) 10, 0 ); + SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM) 0, 1 ); + + // SetTicks on RapidFire Bar + hDlgItem = GetDlgItem( hDlg, IDC_RAPIDFIRERATE ); + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 32 )); + SendMessage( hDlgItem, TBM_SETTICFREQ, (WPARAM) 1, 0 ); + SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM) 0, 1 ); + + // call routine to show content( recursive call ) + ControlsTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); + return FALSE; // don't give it focus + + case WM_COMMAND: + hDlgItem = GetDlgItem( hDlg, LOWORD(wParam) ); + + switch( LOWORD(wParam) ) + { + case IDC_N64RANGE: + g_ivConfig->Controllers[g_ivConfig->ChosenTab].fRealN64Range = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + return TRUE; + + case IDC_RAPIDFIREENABLE: + g_ivConfig->Controllers[g_ivConfig->ChosenTab].bRapidFireEnabled = (IsDlgButtonChecked( hDlg, LOWORD(wParam)) == BST_CHECKED); + return TRUE; + + case IDC_CONFIG1: + case IDC_CONFIG2: + case IDC_CONFIG3: + if( HIWORD(wParam) == BN_CLICKED ) + { + if( LOWORD(wParam) == IDC_CONFIG1 ) + g_ivConfig->Controllers[g_ivConfig->ChosenTab].bAxisSet = 0; + else if( LOWORD(wParam) == IDC_CONFIG2 ) + g_ivConfig->Controllers[g_ivConfig->ChosenTab].bAxisSet = 1; + else if( LOWORD(wParam) == IDC_CONFIG3 ) + g_ivConfig->Controllers[g_ivConfig->ChosenTab].bAxisSet = 2; + + ControlsTabProc( hDlg, WM_USER_UPDATE, 1, 0 ); + } + return TRUE; + + case IDC_LEFTTRIGGER: + case IDC_RIGHTTRIGGER: + case IDC_ZTRIGGER: + case IDC_DUP: + case IDC_DLEFT: + case IDC_DRIGHT: + case IDC_DDOWN: + case IDC_AUP: + case IDC_ALEFT: + case IDC_ARIGHT: + case IDC_ADOWN: + case IDC_CUP: + case IDC_CLEFT: + case IDC_CRIGHT: + case IDC_CDOWN: + case IDC_ABUTTON: + case IDC_BBUTTON: + case IDC_SBUTTON: // any of these cases means user wants to assign a button + if( bScanRunning ) + { ; // do nothing +/* bScanRunning = false; + KillTimer( hDlg, TIMER_BUTTON ); + GetButtonText( aButtons[dwButtonID[2]], szBuffer ); + SendMessage( GetDlgItem( hDlg, dwButtonID[1] ), WM_SETTEXT , 0, (LPARAM)szBuffer ); */ + } + else if( HIWORD(wParam) == BN_CLICKED ) + { + EnterCriticalSection(&g_critical); + dwButtonID[0] = LOWORD(wParam); + dwCounter = 0; + GetButtonID( dwButtonID, 0, BSET_CONTROLS ); + if( dwButtonID[2] >= PF_APADR ) + dwButtonID[2] += g_ivConfig->Controllers[g_ivConfig->ChosenTab].bAxisSet * 4; + if (hFocus == NULL) + hFocus = SetFocus( NULL ); + hBlocker = MakeOverlay(); + + SetTimer( hDlg, TIMER_BUTTON, INTERVAL_BUTTON, NULL ); + bScanRunning = true; + LeaveCriticalSection(&g_critical); + } + return TRUE; + + default: + return FALSE; + } + + case WM_TIMER: // when assigning buttons, this gets called every 20ms (or value in INTERVAL_BUTTON) + if( wParam == TIMER_BUTTON && bScanRunning ) + { + BUTTON newButton; + + i = ScanDevices( &dwCounter, &newButton); + if( i || dwCounter > 500 ) + { + bScanRunning = false; + KillTimer( hDlg, TIMER_BUTTON ); + + EnterCriticalSection(&g_critical); + if( i == SC_SCANESCAPE ) // Scan aborted + ZeroMemory(&aButtons[dwButtonID[2]], sizeof(BUTTON)); //aButtons[dwButtonID[2]].dwButton = 0; + else if( i == SC_SCANSUCCEED ) // Got a key, mouseclick, joybutton, or axis + aButtons[dwButtonID[2]] = newButton; + DestroyWindow( hBlocker ); + + LeaveCriticalSection(&g_critical); + + + GetButtonText( aButtons[dwButtonID[2]], szBuffer ); + SendMessage( GetDlgItem( hDlg, dwButtonID[1] ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + if( hFocus != NULL ) + { + SetFocus( hFocus ); + hFocus = NULL; + } + } + else + { + if(( dwCounter % 50 ) == 0 ) + { + TCHAR tszText[DEFAULT_BUFFER]; + + LoadString( g_hResourceDLL, IDS_C_POLLING, tszText, DEFAULT_BUFFER ); + wsprintf( szBuffer, tszText, 10 - dwCounter / 50 ); + SendMessage( GetDlgItem( hDlg, dwButtonID[1] ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + } + ++dwCounter; + } + return TRUE; + } + else + return FALSE; + + case WM_HSCROLL: // TrackBars + case WM_VSCROLL: + switch ( GetWindowLong( (HWND)lParam, GWL_ID ) ) + { + case IDC_CTRRANGE: + TCHAR tszText[DEFAULT_BUFFER]; + + LoadString( g_hResourceDLL, IDS_C_RANGE, tszText, DEFAULT_BUFFER ); + g_ivConfig->Controllers[g_ivConfig->ChosenTab].bStickRange = (BYTE)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); + wsprintf( szBuffer, tszText, g_ivConfig->Controllers[g_ivConfig->ChosenTab].bStickRange ); + SendMessage( GetDlgItem( hDlg, IDT_RANGE ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + return TRUE; + case IDC_RAPIDFIRERATE: + g_ivConfig->Controllers[g_ivConfig->ChosenTab].bRapidFireRate = 33 - (BYTE)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); + return TRUE; + default: + return FALSE; + } + + case WM_USER_UPDATE: + bScanRunning = false; + KillTimer( hDlg, TIMER_BUTTON ); + EnterCriticalSection(&g_critical); + aButtons = g_ivConfig->Controllers[g_ivConfig->ChosenTab].aButton; + LeaveCriticalSection(&g_critical); + + + if( wParam == 0 ) + { + CheckDlgButton( hDlg, IDC_N64RANGE, g_ivConfig->Controllers[g_ivConfig->ChosenTab].fRealN64Range ? BST_CHECKED : BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_RAPIDFIREENABLE, g_ivConfig->Controllers[g_ivConfig->ChosenTab].bRapidFireEnabled ? BST_CHECKED : BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_CONFIG1, ( g_ivConfig->Controllers[g_ivConfig->ChosenTab].bAxisSet == 0 ) ? BST_CHECKED : BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_CONFIG2, ( g_ivConfig->Controllers[g_ivConfig->ChosenTab].bAxisSet == 1 ) ? BST_CHECKED : BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_CONFIG3, ( g_ivConfig->Controllers[g_ivConfig->ChosenTab].bAxisSet == 2 ) ? BST_CHECKED : BST_UNCHECKED ); + + + SendMessage( GetDlgItem( hDlg, IDC_CTRRANGE ), TBM_SETPOS, TRUE, g_ivConfig->Controllers[g_ivConfig->ChosenTab].bStickRange ); + LoadString( g_hResourceDLL, IDS_C_RANGE, szTemp, 40 ); + wsprintf( szBuffer, szTemp, g_ivConfig->Controllers[g_ivConfig->ChosenTab].bStickRange ); + SendMessage( GetDlgItem( hDlg, IDT_RANGE ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + SendMessage( GetDlgItem( hDlg, IDC_RAPIDFIRERATE ), TBM_SETPOS, TRUE, 33 - g_ivConfig->Controllers[g_ivConfig->ChosenTab].bRapidFireRate ); + + i = 0; + } + else + i = PF_APADR; + + for( ;i < 18; ++i ) + { + DWORD dwIDs[3]; + dwIDs[2] = i; + if( !GetButtonID( dwIDs, 2, BSET_CONTROLS )) + continue; + + if( dwIDs[2] >= PF_APADR ) + dwIDs[2] += g_ivConfig->Controllers[g_ivConfig->ChosenTab].bAxisSet * 4; + + GetButtonText( aButtons[dwIDs[2]], szBuffer ); + SendMessage( GetDlgItem( hDlg, dwIDs[1] ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + } + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +// return TRUE; //msg got processed +} + +// XInput controllers tab --tecnicors +BOOL CALLBACK XControlsTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + LPXCONTROLLER gController = &g_ivConfig->Controllers[g_ivConfig->ChosenTab].xiController; + + switch( uMsg ) + { + case WM_INITDIALOG: + for( int i = IDC_XC_A; i <= IDC_XC_START; i++ ) + FillN64ButtonComboBox( hDlg, i ); + for( int i = IDC_XC_DPAD; i <= IDC_XC_RTS; i++ ) + FillN64AnalogComboBox( hDlg, i ); + XControlsTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); + return FALSE; + + case WM_USER_UPDATE: + { + TCHAR buffer[MAX_PATH]; + GetDirectory( buffer, DIRECTORY_DLL ); + _stprintf_s( buffer, _T("%sXInput Controller %d Config.xcc"), buffer, gController->nControl + 1 ); + FILE *saveFile = _tfopen( buffer, _T("rS") ); + if( saveFile ) + { + LoadXInputConfigFromFile( saveFile, gController ); + fclose( saveFile ); + } + } + if( !ReadXInputControllerKeys( hDlg, gController )) + for( int i = IDC_XC_A; i <= IDC_XC_RTS; i++ ) + SendDlgItemMessage( hDlg, i, CB_SETCURSEL, 0, ( LPARAM )0 ); + + return TRUE; + + case WM_COMMAND: + switch( LOWORD( wParam )) + { + case IDC_XC_USE: + StoreXInputControllerKeys( hDlg, gController ); + { + TCHAR buffer[MAX_PATH]; + GetDirectory( buffer, DIRECTORY_DLL ); + _stprintf_s( buffer, _T("%sXInput Controller %d Config.xcc"), buffer, gController->nControl + 1 ); + FILE *saveFile = _tfopen( buffer, _T("wS") ); + SaveXInputConfigToFile( saveFile, gController ); + fclose( saveFile ); + } + return TRUE; + } + return FALSE; + default: + return FALSE; + } +}// END Xinput Controller Tab --tecnicors + +BOOL CALLBACK DevicesTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + CONTROLLER *pcController = &g_ivConfig->Controllers[g_ivConfig->ChosenTab]; + TCHAR szBuffer[DEFAULT_BUFFER], szTemp[DEFAULT_BUFFER]; + HWND hDlgItem; + long i; + + switch(uMsg) + { + case WM_INITDIALOG: + + // TrackBars + hDlgItem = GetDlgItem( hDlg, IDC_DEADZONE ); + + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 100 )); + SendMessage( hDlgItem, TBM_SETTICFREQ, (WPARAM) 10, 0 ); + SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM) 0, 1 ); + + hDlgItem = GetDlgItem( hDlg, IDC_MSSENSITIVITY_X ); + + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 1000 )); + SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM) 0, 1 ); + + hDlgItem = GetDlgItem( hDlg, IDC_MSSENSITIVITY_Y ); + + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 1000 )); + SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM) 0, 1 ); + { + short sTics[] = { 25, 50, 75, 100, 125, 150, 200, 250, 300, 400, 500, 600, 700, 800, 900 }; + for( i = 0; i < (sizeof(sTics) / sizeof(short)); ++i ) + SendMessage( hDlgItem, TBM_SETTIC, 0, sTics[i] ); + } + // TrackBars End + + DevicesTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); // setting values + + return FALSE; // don't give it focus + + case WM_COMMAND: + hDlgItem = GetDlgItem( hDlg, LOWORD(wParam) ); + + switch( LOWORD(wParam) ) + { + case IDC_DEADPANMOUSEX: + if( LOWORD(wParam) == IDC_DEADPANMOUSEX ) + i = MM_DEAD; + case IDC_BUFFEREDMOUSEX: + if( LOWORD(wParam) == IDC_BUFFEREDMOUSEX ) + i = MM_BUFF; + case IDC_ABSOLUTEMOUSEX: + if( LOWORD(wParam) == IDC_ABSOLUTEMOUSEX ) + i = MM_ABS; + if(( HIWORD(wParam) == BN_CLICKED ) && ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED )) + pcController->bMouseMoveX = i; + return TRUE; + + case IDC_DEADPANMOUSEY: + if( LOWORD(wParam) == IDC_DEADPANMOUSEY ) + i = MM_DEAD; + case IDC_BUFFEREDMOUSEY: + if( LOWORD(wParam) == IDC_BUFFEREDMOUSEY ) + i = MM_BUFF; + case IDC_ABSOLUTEMOUSEY: + if( LOWORD(wParam) == IDC_ABSOLUTEMOUSEY ) + i = MM_ABS; + if(( HIWORD(wParam) == BN_CLICKED ) && ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED )) + pcController->bMouseMoveY = i; + return TRUE; + + case IDC_ACCELERATEX: + pcController->fKeyAbsoluteX = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + return TRUE; + case IDC_ACCELERATEY: + pcController->fKeyAbsoluteY = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + return TRUE; + + default: + return FALSE; + } + + case WM_HSCROLL: // TrackBars + case WM_VSCROLL: + i = GetWindowLong( (HWND)lParam, GWL_ID ); + switch( i ) + { + case IDC_MSSENSITIVITY_X: + pcController->wMouseSensitivityX = (WORD)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); + LoadString( g_hResourceDLL, IDS_D_MSX, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->wMouseSensitivityX ); + SendMessage( GetDlgItem( hDlg, IDT_MSSENSITIVITY_X ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + return TRUE; + + case IDC_MSSENSITIVITY_Y: + pcController->wMouseSensitivityY = (WORD)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); + LoadString( g_hResourceDLL, IDS_D_MSY, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->wMouseSensitivityY ); + SendMessage( GetDlgItem( hDlg, IDT_MSSENSITIVITY_Y ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + return TRUE; + + case IDC_DEADZONE: + pcController->bPadDeadZone = (BYTE)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); + LoadString( g_hResourceDLL, IDS_D_DEADZONE, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->bPadDeadZone ); + SendMessage( GetDlgItem( hDlg, IDT_DEADZONE ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + return TRUE; + default: + return FALSE; + } + + case WM_USER_UPDATE: + if( pcController->bMouseMoveX == MM_DEAD ) + CheckDlgButton( hDlg, IDC_DEADPANMOUSEX, BST_CHECKED ); + else + CheckDlgButton( hDlg, IDC_DEADPANMOUSEX, BST_UNCHECKED ); + if( pcController->bMouseMoveX == MM_BUFF ) + CheckDlgButton( hDlg, IDC_BUFFEREDMOUSEX, BST_CHECKED ); + else + CheckDlgButton( hDlg, IDC_BUFFEREDMOUSEX, BST_UNCHECKED ); + if( pcController->bMouseMoveX == MM_ABS ) + CheckDlgButton( hDlg, IDC_ABSOLUTEMOUSEX, BST_CHECKED ); + else + CheckDlgButton( hDlg, IDC_ABSOLUTEMOUSEX, BST_UNCHECKED ); + + if( pcController->bMouseMoveY == MM_DEAD ) + CheckDlgButton( hDlg, IDC_DEADPANMOUSEY, BST_CHECKED ); + else + CheckDlgButton( hDlg, IDC_DEADPANMOUSEY, BST_UNCHECKED ); + if( pcController->bMouseMoveY == MM_BUFF ) + CheckDlgButton( hDlg, IDC_BUFFEREDMOUSEY, BST_CHECKED ); + else + CheckDlgButton( hDlg, IDC_BUFFEREDMOUSEY, BST_UNCHECKED ); + if( pcController->bMouseMoveY == MM_ABS ) + CheckDlgButton( hDlg, IDC_ABSOLUTEMOUSEY, BST_CHECKED ); + else + CheckDlgButton( hDlg, IDC_ABSOLUTEMOUSEY, BST_UNCHECKED ); + + CheckDlgButton( hDlg, IDC_ACCELERATEX, pcController->fKeyAbsoluteX ? BST_CHECKED : BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_ACCELERATEY, pcController->fKeyAbsoluteY ? BST_CHECKED : BST_UNCHECKED ); + + // TrackBars + SendMessage( GetDlgItem( hDlg, IDC_DEADZONE ), TBM_SETPOS, TRUE, pcController->bPadDeadZone ); + LoadString( g_hResourceDLL, IDS_D_DEADZONE, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->bPadDeadZone ); + SendMessage( GetDlgItem( hDlg, IDT_DEADZONE ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + + SendMessage( GetDlgItem( hDlg, IDC_MSSENSITIVITY_X ), TBM_SETPOS, TRUE, pcController->wMouseSensitivityX ); + LoadString( g_hResourceDLL, IDS_D_MSX, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->wMouseSensitivityX ); + SendMessage( GetDlgItem( hDlg, IDT_MSSENSITIVITY_X ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + + SendMessage( GetDlgItem( hDlg, IDC_MSSENSITIVITY_Y ), TBM_SETPOS, TRUE, pcController->wMouseSensitivityY ); + LoadString( g_hResourceDLL, IDS_D_MSY, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->wMouseSensitivityY ); + SendMessage( GetDlgItem( hDlg, IDT_MSSENSITIVITY_Y ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + // TrackBars End + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +} + +BOOL CALLBACK MoveModifierDialog( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + + HWND hDlgItem; + long i,j; + DWORD dwValue; + TCHAR szBuffer[DEFAULT_BUFFER], szTemp[DEFAULT_BUFFER]; + + switch(uMsg) + { + case WM_INITDIALOG: + // TrackBars + hDlgItem = GetDlgItem( hDlg, IDC_XMODIFIER ); + + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 500 )); + SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM) 0, 1 ); + { + short sTics[] = { 25, 50, 75, 100, 125, 150, 200, 250, 300, 400, 500 }; + for( i = 0; i < (sizeof(sTics) / sizeof(short)); ++i ) + SendMessage( hDlgItem, TBM_SETTIC, 0, sTics[i] ); + } + + hDlgItem = GetDlgItem( hDlg, IDC_YMODIFIER ); + + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 500 )); + SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM) 0, 1 ); + { + short sTics[] = { 25, 50, 75, 100, 125, 150, 200, 250, 300, 400, 500 }; + for( i = 0; i < (sizeof(sTics) / sizeof(short)); ++i ) + SendMessage( hDlgItem, TBM_SETTIC, 0, sTics[i] ); + } + return FALSE; // don't give it focus + + case WM_HSCROLL: // TrackBars + case WM_VSCROLL: + switch (GetWindowLong( (HWND)lParam, GWL_ID )) + { + case IDC_XMODIFIER: + i = SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); + LoadString( g_hResourceDLL, IDS_M_MOVEVALUE, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, i ); + SendMessage( GetDlgItem( hDlg, IDT_XMODIFIER ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + return TRUE; + + case IDC_YMODIFIER: + i = SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); + LoadString( g_hResourceDLL, IDS_M_MOVEVALUE, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, i ); + SendMessage( GetDlgItem( hDlg, IDT_YMODIFIER ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + return TRUE; + + default: + return FALSE; + } + + case WM_USER_UPDATE: + if( wParam == MDT_MOVE ) + dwValue = (DWORD)lParam; + else + dwValue = MAKELONG( 100, 100 ); + + i = (short)(dwValue & 0x0000FFFF); + + if( i < 0 ) + { + i = -i; + CheckDlgButton( hDlg, IDC_XNEGATE, BST_CHECKED ); + } + else + CheckDlgButton( hDlg, IDC_XNEGATE, BST_UNCHECKED ); + SendMessage( GetDlgItem( hDlg, IDC_XMODIFIER ), TBM_SETPOS, TRUE, i ); + LoadString( g_hResourceDLL, IDS_M_MOVEVALUE, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, i ); + SendMessage( GetDlgItem( hDlg, IDT_XMODIFIER ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + + i = (short)((dwValue >> 16) & 0x0000FFFF); + + if( i < 0 ) + { + i = -i; + CheckDlgButton( hDlg, IDC_YNEGATE, BST_CHECKED ); + } + else + CheckDlgButton( hDlg, IDC_YNEGATE, BST_UNCHECKED ); + SendMessage( GetDlgItem( hDlg, IDC_YMODIFIER ), TBM_SETPOS, TRUE, i ); + LoadString( g_hResourceDLL, IDS_M_MOVEVALUE, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, i ); + SendMessage( GetDlgItem( hDlg, IDT_YMODIFIER ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + return TRUE; + + case WM_USER_READVALUES: + i = SendMessage( GetDlgItem( hDlg, IDC_XMODIFIER ), TBM_GETPOS, 0, 0 ); + if( IsDlgButtonChecked( hDlg, IDC_XNEGATE ) == BST_CHECKED ) + i = -i; + + j = SendMessage( GetDlgItem( hDlg, IDC_YMODIFIER ), TBM_GETPOS, 0, 0 ); + if( IsDlgButtonChecked( hDlg, IDC_YNEGATE ) == BST_CHECKED ) + j = -j; + + *(DWORD*)wParam = MAKELONG( (short)i, (short)j ); + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +} + +BOOL CALLBACK MacroModifierDialog( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + long i; + DWORD dwValue; + + const DWORD aButtons[] ={ IDC_DRIGHT , IDC_DLEFT , IDC_DDOWN , IDC_DUP, + IDC_SBUTTON , IDC_ZTRIG , IDC_BBUTTON , IDC_ABUTTON, + IDC_CRIGHT , IDC_CLEFT , IDC_CDOWN , IDC_CUP, + IDC_RTRIG , IDC_LTRIG , 0 , 0, + IDC_ARIGHT , IDC_ALEFT , IDC_ADOWN , IDC_AUP, + IDC_RAPIDFIREMODE , IDC_RAPIDFIREMODERATE }; + + switch(uMsg) + { + case WM_INITDIALOG: + return FALSE; // don't give it focus + + case WM_USER_UPDATE: + if( wParam == MDT_MACRO ) + dwValue = (DWORD)lParam; + else + dwValue = 0; + + i = sizeof(aButtons) / sizeof(aButtons[0]) - 1; + + while( i >= 0 ) + { + if( aButtons[i] ) + { + if( dwValue & ( 1 << i ) ) + CheckDlgButton( hDlg, aButtons[i], BST_CHECKED ); + else + CheckDlgButton( hDlg, aButtons[i], BST_UNCHECKED ); + } + + i--; + } + return TRUE; + + case WM_USER_READVALUES: + dwValue = 0; + + i = sizeof(aButtons) / sizeof(aButtons[0]) - 1; + while( i >= 0 ) + { + if( aButtons[i] && ( IsDlgButtonChecked( hDlg, aButtons[i] ) == BST_CHECKED )) + dwValue = dwValue | ( 1 << i ); + + i--; + } + + *(DWORD*)wParam = dwValue; + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +} + +BOOL CALLBACK ConfigModifierDialog( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + DWORD dwValue; + + const DWORD aButtons[] ={ IDC_CONFIG1 , 0x000001, + IDC_CONFIG2 , 0x000003, + IDC_CONFIG3 , 0x000005, + IDC_CONFIGCYCLE , 0x0000FF, + IDC_MOUSEX , 0x000100, + IDC_MOUSEY , 0x000200, + IDC_KEYX , 0x010000, + IDC_KEYY , 0x020000 }; + + int i; + + switch(uMsg) + { + case WM_INITDIALOG: + return FALSE; // don't give it focus + + case WM_COMMAND: + switch( LOWORD(wParam) ) + { + case IDC_CONFIG1: + case IDC_CONFIG2: + case IDC_CONFIG3: + case IDC_CONFIGCYCLE: + if(( HIWORD(wParam) == BN_CLICKED ) || ( HIWORD(wParam) == BN_DBLCLK )) + { + EnterCriticalSection(&g_critical); // has a possibility of affecting the buttons we're writing to + bool bCheck = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ) ? false : true; + CheckDlgButton( hDlg, IDC_CONFIG1, BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_CONFIG2, BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_CONFIG3, BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_CONFIGCYCLE, BST_UNCHECKED ); + if( bCheck ) + CheckDlgButton( hDlg, LOWORD(wParam), BST_CHECKED ); + LeaveCriticalSection(&g_critical); + } + return TRUE; + default: + return FALSE; + } + + case WM_USER_UPDATE: + if( wParam == MDT_CONFIG ) + dwValue = (DWORD)lParam; + else + dwValue = 0; + if( dwValue & 0x01 ) + { + BYTE bConfig = (BYTE)((dwValue >> 1) & 0x7F); + if( bConfig >= PF_AXESETS ) + { + CheckDlgButton( hDlg, IDC_CONFIG1, BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_CONFIG2, BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_CONFIG3, BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_CONFIGCYCLE, BST_CHECKED ); + } + else + { + i = PF_AXESETS - 1; + while( i >= 0 ) + { + if( bConfig == i ) + CheckDlgButton( hDlg, aButtons[i*2], BST_CHECKED ); + else + CheckDlgButton( hDlg, aButtons[i*2], BST_UNCHECKED ); + + i--; + } + } + } + + i = sizeof(aButtons) / sizeof(aButtons[0]) - 2; + while( i >= 8 ) + { + if(( dwValue & aButtons[i+1] ) == aButtons[i+1] ) + CheckDlgButton( hDlg, aButtons[i], BST_CHECKED ); + else + CheckDlgButton( hDlg, aButtons[i], BST_UNCHECKED ); + + i -= 2; + } + return TRUE; + + case WM_USER_READVALUES: + dwValue = 0; + + i = sizeof(aButtons) / sizeof(aButtons[0]) - 2; + while( i >= 0 ) + { + if( IsDlgButtonChecked( hDlg, aButtons[i] ) == BST_CHECKED ) + dwValue |= aButtons[i+1]; + i -= 2; + } + + *(DWORD*)wParam = dwValue; + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +} + +void ModDescription( HWND hListView, int iEntry, const LPMODIFIER pModifier ) +{ + TCHAR szBuffer[DEFAULT_BUFFER]; + const UINT iModTypes[] = { IDS_M_TAB_NONE, IDS_M_TAB_MOVE, IDS_M_TAB_MACRO, IDS_M_TAB_CONFIG }; + TCHAR pszModTypes[4][16]; + + for (int i = 0; i < ARRAYSIZE(iModTypes); i++ ) + LoadString( g_hResourceDLL, iModTypes[i], pszModTypes[i], ARRAYSIZE(pszModTypes[i]) ); + + GetButtonText( pModifier->btnButton, szBuffer ); + + ListView_SetItemText( hListView, iEntry, 0,szBuffer ); + + switch( pModifier->bModType ) + { + case MDT_MOVE: + ListView_SetItemText( hListView, iEntry, 1, pszModTypes[1] ); + wsprintf( szBuffer, _T("X:%i%% / Y:%i%%"), (short)(pModifier->dwSpecific & 0x0000FFFF), (short)((pModifier->dwSpecific >> 16) & 0x0000FFFF)); + break; + case MDT_MACRO: + ListView_SetItemText( hListView, iEntry, 1, pszModTypes[2] ); + szBuffer[0] = '\0'; + { + bool bGotKey = false; + DWORD dwValue = pModifier->dwSpecific; + const TCHAR *apszButtons[] ={ _T("Dp->"), _T("Dp<-"), _T("Dp\\/"), _T("Dp/\\"), _T("St"), _T("Z"), _T("B"), _T("A"), + _T("Cb->"), _T("Cb<-"), _T("Cb\\/"), _T("Cb/\\"), _T("R"), _T("L"), NULL, NULL, + _T("As->"), _T("As<-"), _T("As\\/"), _T("As/\\"), _T("()") }; + + int i = sizeof(apszButtons) / sizeof(apszButtons[0]) - 1; + + while( i >= 0 ) + { + if( apszButtons[i] && ( dwValue & ( 1 << i ) )) + { + if( bGotKey ) + lstrcat( szBuffer, _T(" ") ); + else + bGotKey = true; + + lstrcat( szBuffer, apszButtons[i] ); + } + + i--; + } + } + break; + case MDT_CONFIG: + ListView_SetItemText( hListView, iEntry, 1, pszModTypes[3] ); + szBuffer[0] = '\0'; + { + DWORD dwValue = pModifier->dwSpecific; + bool bGotKey = false; + + if( dwValue & 0x1 ) + { + lstrcat( szBuffer, _T("C-") ); + if((( dwValue >> 1 ) & 0x7F ) < PF_AXESETS ) + wsprintf( &szBuffer[lstrlen(szBuffer)], _T("%i"), (( dwValue >> 1 ) & 0x7F )); + else + lstrcat( szBuffer, _T("Sw") ); + bGotKey = true; + } + + if( dwValue & 0x300 ) + { + if( bGotKey ) + lstrcat( szBuffer, _T(" ") ); + else + bGotKey = true; + + lstrcat( szBuffer, _T("Ms-") ); + if( dwValue & 0x100 ) + lstrcat( szBuffer, _T("X") ); + if( dwValue & 0x200 ) + lstrcat( szBuffer, _T("Y") ); + } + + if( dwValue & 0x30000 ) + { + if( bGotKey ) + lstrcat( szBuffer, _T(" ") ); + else + bGotKey = true; + + lstrcat( szBuffer, _T("Kb-") ); + if( dwValue & 0x10000 ) + lstrcat( szBuffer, _T("X") ); + if( dwValue & 0x20000 ) + lstrcat( szBuffer, _T("Y") ); + } + } + break; + + case MDT_NONE: + default: + ListView_SetItemText( hListView, iEntry, 1, pszModTypes[0] ); + szBuffer[0] = '\0'; + } + ListView_SetItemText( hListView, iEntry, 2, szBuffer ); + +} + +BOOL CALLBACK ModifierTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + static BUTTON storage; + static bool bScanRunning; + static DWORD dwCounter; + static HWND hFocus = NULL, hBlocker; + static int iSelectedMod; + static BYTE bDisplayedProbs; + static HWND hModProperties; + static LPCONTROLLER pcController; + + const UINT iModTypes[] = { IDS_M_NONE, IDS_M_MOVE, IDS_M_MACRO, IDS_M_CONFIG }; + TCHAR pszModTypes[4][16]; + + for (int j = 0; j < ARRAYSIZE(iModTypes); j++ ) + LoadString( g_hResourceDLL, iModTypes[j], pszModTypes[j], ARRAYSIZE(pszModTypes[j]) ); + + TCHAR szBuffer[40]; + HWND hDlgItem; + long i; + BYTE bByte; + + switch(uMsg) + { + case WM_INITDIALOG: + bScanRunning = false; + hModProperties = NULL; + bDisplayedProbs = MDT_NONE; + // List View + hDlgItem = GetDlgItem( hDlg, IDC_MODIFIERLIST ); + + LVCOLUMN lvColumn; + + lvColumn.mask = LVCFMT_CENTER | LVCF_WIDTH | LVCF_TEXT; + lvColumn.fmt = LVCFMT_LEFT; + lvColumn.cx = 100; + LoadString( g_hResourceDLL, IDS_M_ASSIGNED, szBuffer, 40 ); + lvColumn.pszText = szBuffer; + ListView_InsertColumn( hDlgItem, 0, &lvColumn ); + + lvColumn.fmt = LVCFMT_CENTER | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvColumn.cx = 43; + lvColumn.iSubItem = 1; + LoadString( g_hResourceDLL, IDS_M_TYPE, szBuffer, 40 ); + lvColumn.pszText = szBuffer; + ListView_InsertColumn( hDlgItem, 1, &lvColumn ); + + lvColumn.cx = 128; + lvColumn.iSubItem = 2; + LoadString( g_hResourceDLL, IDS_M_PARAM, szBuffer, 40 ); + lvColumn.pszText = szBuffer; + ListView_InsertColumn( hDlgItem, 2, &lvColumn ); + + ListView_SetExtendedListViewStyle( hDlgItem, LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP ); + // ListView End + + // DropDown + hDlgItem = GetDlgItem( hDlg, IDC_MODTYP ); + + i = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)pszModTypes[0] ); + SendMessage( hDlgItem, CB_SETITEMDATA, i, MDT_NONE ); + + i = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)pszModTypes[1] ); + SendMessage( hDlgItem, CB_SETITEMDATA, i, MDT_MOVE ); + + i = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)pszModTypes[2] ); + SendMessage( hDlgItem, CB_SETITEMDATA, i, MDT_MACRO ); + + i = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)pszModTypes[3] ); + SendMessage( hDlgItem, CB_SETITEMDATA, i, MDT_CONFIG ); + // DropDown End + + ZeroMemory(&storage, sizeof(BUTTON)); + + ModifierTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); // setting values + + return FALSE; // don't give it focus + + case WM_COMMAND: + hDlgItem = GetDlgItem( hDlg, LOWORD(wParam) ); + switch( LOWORD(wParam) ) + { + case IDC_NEWMODIFIER: + if( pcController->nModifiers < MAX_MODIFIERS ) + { + EnterCriticalSection(&g_critical); + pcController->nModifiers++; + pcController->pModifiers = (MODIFIER*)P_realloc( pcController->pModifiers, sizeof(MODIFIER) * pcController->nModifiers ); + + ZeroMemory( &pcController->pModifiers[pcController->nModifiers - 1], sizeof(MODIFIER) ); + iSelectedMod = pcController->nModifiers - 1; + LeaveCriticalSection(&g_critical); + + ModifierTabProc( hDlg, WM_USER_UPDATE, 0, 1 ); + } + return TRUE; + + case IDC_KILLMODIFIER: + hDlgItem = GetDlgItem( hDlg, IDC_MODIFIERLIST ); + + if( ListView_GetSelectedCount( hDlgItem ) > 0 ) + { + EnterCriticalSection(&g_critical); + for( i = ListView_GetItemCount( hDlgItem ) - 1; i >= 0; i-- ) + { + if( ListView_GetItemState( hDlgItem, i, LVIS_SELECTED )) + { + MoveMemory( &pcController->pModifiers[i], &pcController->pModifiers[i+1], sizeof(MODIFIER) * ( pcController->nModifiers - 1 - i )); + pcController->nModifiers--; + } + } + pcController->pModifiers = (MODIFIER*)P_realloc( pcController->pModifiers, sizeof(MODIFIER) * pcController->nModifiers ); + LeaveCriticalSection(&g_critical); + ModifierTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); + } + return TRUE; + + case IDC_ASSIGNMOD: + EnterCriticalSection(&g_critical); + hDlgItem = GetDlgItem( hDlg, IDC_MODIFIERLIST ); + if( bScanRunning ) + { +/* bScanRunning = false; + KillTimer( hDlg, TIMER_BUTTON ); + BUTTON btnButton; + btnButton = storage; // btnButton.dwButton = GetWindowLong( hDlgItem, GWL_USERDATA ); + GetButtonText( btnButton, szBuffer ); + SendMessage( GetDlgItem( hDlg, IDT_ASSIGNMOD ), WM_SETTEXT , 0, (LPARAM)szBuffer ); */ ; + } + else if( HIWORD(wParam) == BN_CLICKED && ListView_GetItemCount( hDlgItem )) + { + dwCounter = 0; + if (hFocus == NULL) + hFocus = SetFocus( NULL ); + hBlocker = MakeOverlay(); + + SetTimer( hDlg, TIMER_BUTTON, INTERVAL_BUTTON, NULL ); + bScanRunning = true; + } + LeaveCriticalSection(&g_critical); + return TRUE; + + case IDC_MODTYP: + if( HIWORD (wParam) == CBN_SELCHANGE ) + { + ModifierTabProc( hDlg, WM_USER_UPDATE, 1, 1 ); + } + return TRUE; + + case IDC_APPCHANGES: + // ModType + EnterCriticalSection(&g_critical); + hDlgItem = GetDlgItem( hDlg, IDC_MODTYP ); + i = SendMessage( hDlgItem, CB_GETCURSEL, 0, 0 ); + pcController->pModifiers[iSelectedMod].bModType = (BYTE)SendMessage( hDlgItem, CB_GETITEMDATA, i, 0 ); + + // Toggle + pcController->pModifiers[iSelectedMod].fToggle = ( IsDlgButtonChecked( hDlg, IDC_TOGGLE ) == BST_CHECKED ); + // Status + pcController->pModifiers[iSelectedMod].fStatus = ( IsDlgButtonChecked( hDlg, IDC_STATE ) == BST_CHECKED ); + + // Specific Data + if( hModProperties ) + SendMessage( hModProperties, WM_USER_READVALUES, (WPARAM)&pcController->pModifiers[iSelectedMod].dwSpecific, 0 ); + else + pcController->pModifiers[iSelectedMod].dwSpecific = 0; + + // ModButton + pcController->pModifiers[iSelectedMod].btnButton = storage; + LeaveCriticalSection(&g_critical); + + ModDescription( GetDlgItem( hDlg, IDC_MODIFIERLIST ), iSelectedMod, &pcController->pModifiers[iSelectedMod] ); + + return TRUE; + case IDC_RESET: + ModifierTabProc( hDlg, WM_USER_UPDATE, 1, 0 ); + return TRUE; + + case IDC_TOGGLE: + EnableWindow( GetDlgItem( hDlg, IDC_STATE ), ( IsDlgButtonChecked( hDlg, IDC_TOGGLE ) == BST_CHECKED ) ? TRUE : FALSE ); + return TRUE; + case IDC_STATE: + return TRUE; + + default: + return FALSE; + } + + case WM_TIMER: // when assigning modifiers, this gets called every 20ms (or value in INTERVAL_BUTTON) + if( wParam == TIMER_BUTTON && bScanRunning ) + { + BUTTON newButton; + i = ScanDevices( &dwCounter, &newButton ); + if( i || dwCounter > 500 ) + { + bScanRunning = false; + KillTimer( hDlg, TIMER_BUTTON ); + + hDlgItem = GetDlgItem( hDlg, IDC_ASSIGNMOD ); + + EnterCriticalSection(&g_critical); + if( i == SC_SCANESCAPE ) // Got an escape char from keyboard; cancel + ZeroMemory(&storage, sizeof(BUTTON)); + else if( i == SC_SCANSUCCEED ) // Got a button or axis + storage = newButton; + newButton = storage; + DestroyWindow( hBlocker ); + + LeaveCriticalSection(&g_critical); + + GetButtonText( newButton, szBuffer ); + SendMessage( GetDlgItem( hDlg, IDT_ASSIGNMOD ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + if( hFocus != NULL ) + { + SetFocus( hFocus ); + hFocus = NULL; + } + } + else + { + if(( dwCounter % 50 ) == 0 ) + { + TCHAR tszText[DEFAULT_BUFFER]; + + LoadString( g_hResourceDLL, IDS_C_POLLING, tszText, DEFAULT_BUFFER ); + wsprintf( szBuffer, tszText, 10 - dwCounter / 50 ); + SendMessage( GetDlgItem( hDlg, IDT_ASSIGNMOD ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + } + ++dwCounter; + } + return TRUE; + } + else + return FALSE; + + case WM_NOTIFY: + switch( ((LPNMHDR)lParam)->idFrom ) + { + case IDC_MODIFIERLIST: + switch( ((LPNMHDR)lParam)->code ) + { + case LVN_ITEMCHANGED: + ModifierTabProc( hDlg, WM_USER_UPDATE, 1, 0 ); + return TRUE; + default: + return FALSE; + } + default: + return FALSE; + } + + case WM_USER_UPDATE: + pcController = &g_ivConfig->Controllers[g_ivConfig->ChosenTab]; + hDlgItem = GetDlgItem( hDlg, IDC_MODIFIERLIST ); + + if( wParam == 0 ) + { + // Update Modifier List + ListView_DeleteAllItems( hDlgItem ); + if( lParam == 0 ) + iSelectedMod = -1; + + LVITEM lvItem; + lvItem.mask = LVIF_TEXT | LVIF_PARAM; + lvItem.iItem = 0; + lvItem.iSubItem = 0; + lvItem.pszText = _T(""); + + ListView_SetItemCount( hDlgItem, pcController->nModifiers ); + for( lvItem.lParam = 0; lvItem.lParam < pcController->nModifiers; ++lvItem.lParam ) + { + lvItem.iItem = lvItem.lParam; + i = ListView_InsertItem( hDlgItem, &lvItem ); + + ModDescription( hDlgItem, i, &pcController->pModifiers[lvItem.lParam] ); + } + if( iSelectedMod >= 0 && iSelectedMod < ListView_GetItemCount( hDlgItem )) + + ListView_SetItemState( hDlgItem, iSelectedMod, LVIS_SELECTED, LVIS_SELECTED ) + else + iSelectedMod = -1; + + } + else + { + // Get selected Modifier + iSelectedMod = -1; + if( ListView_GetSelectedCount( hDlgItem ) > 0 ) + { + for( i = ListView_GetItemCount( hDlgItem ) - 1; i >= 0; i-- ) + { + if( ListView_GetItemState( hDlgItem, i, LVIS_SELECTED )) + { + iSelectedMod = i; + i = -1; + } + } + } + } + + hDlgItem = GetDlgItem( hDlg, IDC_MODTYP ); + + if( lParam == 0 ) + { + if( iSelectedMod >= 0 ) + { // a mod is selected + EnableWindow( GetDlgItem( hDlg, IDC_ASSIGNMOD ), TRUE ); + EnableWindow( GetDlgItem( hDlg, IDT_ASSIGNMOD ), TRUE ); + EnableWindow( GetDlgItem( hDlg, IDC_TOGGLE ), TRUE ); + EnableWindow( hDlgItem, TRUE ); + EnableWindow( GetDlgItem( hDlg, IDT_MODTYP ), TRUE ); + EnableWindow( GetDlgItem( hDlg, IDC_APPCHANGES ), TRUE ); + EnableWindow( GetDlgItem( hDlg, IDC_RESET ), TRUE ); + + for( i = SendMessage( hDlgItem, CB_GETCOUNT, 0, 0 )-1; i >= 0; i-- ) + { // looking which Mod-Typ + bByte = (BYTE)SendMessage( hDlgItem, CB_GETITEMDATA, i, 0 ); + if( pcController->pModifiers[iSelectedMod].bModType == bByte ) + { + SendMessage( hDlgItem, CB_SETCURSEL, i, 0 ); + i = -10; + } + } + if( i > -5 ) + SendMessage( hDlgItem, CB_SETCURSEL, 0, 0 ); + + CheckDlgButton( hDlg, IDC_TOGGLE, pcController->pModifiers[iSelectedMod].fToggle ? BST_CHECKED : BST_UNCHECKED ); + EnableWindow( GetDlgItem( hDlg, IDC_STATE ), pcController->pModifiers[iSelectedMod].fToggle ? TRUE : FALSE ); + CheckDlgButton( hDlg, IDC_STATE, pcController->pModifiers[iSelectedMod].fStatus ? BST_CHECKED : BST_UNCHECKED ); + + + storage = pcController->pModifiers[iSelectedMod].btnButton; + GetButtonText( pcController->pModifiers[iSelectedMod].btnButton, szBuffer ); + SendMessage( GetDlgItem( hDlg, IDT_ASSIGNMOD ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + } + else + { + EnableWindow( GetDlgItem( hDlg, IDC_ASSIGNMOD ), FALSE ); + EnterCriticalSection(&g_critical); + ZeroMemory(&storage, sizeof(BUTTON)); + LeaveCriticalSection(&g_critical); + SendMessage( GetDlgItem( hDlg, IDT_ASSIGNMOD ), WM_SETTEXT , 0, (LPARAM) _T("") ); + EnableWindow( GetDlgItem( hDlg, IDT_ASSIGNMOD ), FALSE ); + + SendMessage( hDlgItem, CB_SETCURSEL, 0, 0 ); + EnableWindow( hDlgItem, FALSE ); + EnableWindow( GetDlgItem( hDlg, IDT_MODTYP ), FALSE ); + + EnableWindow( GetDlgItem( hDlg, IDC_TOGGLE ), FALSE ); + CheckDlgButton( hDlg, IDC_TOGGLE , BST_UNCHECKED ); + EnableWindow( GetDlgItem( hDlg, IDC_STATE ), FALSE ); + CheckDlgButton( hDlg, IDC_STATE , BST_UNCHECKED ); + EnableWindow( GetDlgItem( hDlg, IDC_APPCHANGES ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDC_RESET ), FALSE ); + } + } + + i = SendMessage( hDlgItem, CB_GETCURSEL, 0, 0 ); + bByte = (BYTE)SendMessage( hDlgItem, CB_GETITEMDATA, i, 0 ); + + + if(( bByte == bDisplayedProbs ) && hModProperties ) + SendMessage( hModProperties, WM_USER_UPDATE, pcController->pModifiers[iSelectedMod].bModType, pcController->pModifiers[iSelectedMod].dwSpecific ); + else + { + if( hModProperties ) + DestroyWindow( hModProperties ); + + switch( bByte ) + { + case MDT_MOVE: + hModProperties = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_MOD_MOVE ), hDlg, MoveModifierDialog ); + break; + case MDT_MACRO: + hModProperties = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_MOD_MACRO ), hDlg, MacroModifierDialog ); + break; + case MDT_CONFIG: + hModProperties = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_MOD_CONFIG ), hDlg, ConfigModifierDialog ); + break; + case MDT_NONE: + default: + hModProperties = NULL; + } + + hDlgItem = GetDlgItem( hDlg, IDC_PROPWINDOW ); + + if( hModProperties ) + { + RECT rectProp, rectMain; // need to know the position of the calling tab window relative to its parent + + GetWindowRect( hDlg, &rectMain ); + GetWindowRect( hDlgItem, &rectProp ); + + MoveWindow( hModProperties, rectProp.left - rectMain.left, rectProp.top - rectMain.top, rectProp.right - rectProp.left, rectProp.bottom - rectProp.top, FALSE ); + SendMessage( hModProperties, WM_USER_UPDATE, pcController->pModifiers[iSelectedMod].bModType, pcController->pModifiers[iSelectedMod].dwSpecific ); + ShowWindow( hModProperties, SW_SHOW ); + } + bDisplayedProbs = bByte; + } + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +} + +BOOL CALLBACK ControllerPakTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + static HWND hPakWindow; + static bool bAdaptoidInList; + static BYTE bCurrentPak; + HWND hDlgItem; + long i,j; + BYTE bByte; + TCHAR tszMsg[DEFAULT_BUFFER]; + + switch(uMsg) + { + case WM_INITDIALOG: + hPakWindow = NULL; + bAdaptoidInList = false; + bCurrentPak = (BYTE)(-1); + + // DropDown-List; + hDlgItem = GetDlgItem( hDlg, IDC_PAKTYPE ); + LoadString( g_hResourceDLL, IDS_P_NONE, tszMsg, DEFAULT_BUFFER ); + i = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)tszMsg ); + SendMessage( hDlgItem, CB_SETITEMDATA, i, PAK_NONE ); + + LoadString( g_hResourceDLL, IDS_P_MEMPAK, tszMsg, DEFAULT_BUFFER ); + i = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)tszMsg ); + SendMessage( hDlgItem, CB_SETITEMDATA, i, PAK_MEM ); + + LoadString( g_hResourceDLL, IDS_P_RUMBLEPAK, tszMsg, DEFAULT_BUFFER ); + i = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)tszMsg ); + SendMessage( hDlgItem, CB_SETITEMDATA, i, PAK_RUMBLE ); + +#ifdef V_TRANSFERPAK + LoadString( g_hResourceDLL, IDS_P_TRANSFERPAK, tszMsg, DEFAULT_BUFFER ); + i = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)tszMsg ); + SendMessage( hDlgItem, CB_SETITEMDATA, i, PAK_TRANSFER ); +#pragma message( "Transferpak enabled in Interface" ) +#endif +#ifdef V_VOICEPAK + LoadString( g_hResourceDLL, IDS_P_VOICEPAK, tszMsg, DEFAULT_BUFFER ); + i = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)tszMsg ); + SendMessage( hDlgItem, CB_SETITEMDATA, i, PAK_VOICE ); +#pragma message( "Voicepak enabled in Interface" ) +#endif + + ControllerPakTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); + return FALSE; // don't give it focus + + case WM_COMMAND: + hDlgItem = GetDlgItem( hDlg, LOWORD(wParam) ); + + switch( LOWORD(wParam) ) + { + case IDC_PAKTYPE: + if( HIWORD (wParam) == CBN_SELCHANGE ) + { + i = SendMessage( hDlgItem, CB_GETCURSEL, 0, 0 ); + g_ivConfig->Controllers[g_ivConfig->ChosenTab].PakType = SendMessage( hDlgItem, CB_GETITEMDATA, i, 0 ); + ControllerPakTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); + } + return TRUE; + case IDC_RAWMODE: + g_ivConfig->Controllers[g_ivConfig->ChosenTab].fRawData = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + ControllerPakTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); + return TRUE; + + default: + return FALSE; + } + + case WM_USER_UPDATE: + CheckDlgButton( hDlg, IDC_RAWMODE, g_ivConfig->Controllers[g_ivConfig->ChosenTab].fRawData ? BST_CHECKED : BST_UNCHECKED ); + //Set Dropdownlist + hDlgItem = GetDlgItem( hDlg, IDC_PAKTYPE ); + + if( g_ivConfig->Controllers[g_ivConfig->ChosenTab].fRawData && + !lstrcmp( g_ivConfig->FFDevices[g_ivConfig->ChosenTab].szProductName, _T(STRING_ADAPTOID) ) && + !bAdaptoidInList ) + { + // add Adaptoid Pak to list + LoadString( g_hResourceDLL, IDS_P_ADAPTOIDPAK, tszMsg, DEFAULT_BUFFER ); + i = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)tszMsg ); + SendMessage( hDlgItem, CB_SETITEMDATA, i, PAK_ADAPTOID ); + bAdaptoidInList = true; + } + + if( bAdaptoidInList && + ( lstrcmp( g_ivConfig->FFDevices[g_ivConfig->ChosenTab].szProductName, _T(STRING_ADAPTOID) ) || + !g_ivConfig->Controllers[g_ivConfig->ChosenTab].fRawData )) + { + // remove Adaptoid Pak from list + i = SendMessage( hDlgItem, CB_GETCOUNT, 0, 0 ) - 1; + while(( i >= 0 )) + { + j = SendMessage( hDlgItem, CB_GETITEMDATA, i, 0 ); + if( j == PAK_ADAPTOID ) + { + SendMessage( hDlgItem, CB_DELETESTRING, i, 0 ); + i = -1; + } + i--; + } + bAdaptoidInList = false; + } + + + i = SendMessage( hDlgItem, CB_GETCOUNT, 0, 0 ) - 1; + + while(( i >= 0 )) + { + bByte = (BYTE)SendMessage( hDlgItem, CB_GETITEMDATA, i, 0 ); + if( g_ivConfig->Controllers[g_ivConfig->ChosenTab].PakType == bByte ) + { + SendMessage( hDlgItem, CB_SETCURSEL, i, 0 ); + i = -10; + } + else + i--; + } + if( i != -10 ) + SendMessage( hDlgItem, CB_SETCURSEL, 0, 0 ); + + // Update Pak-Display + if( g_ivConfig->Controllers[g_ivConfig->ChosenTab].fRawData ) + { + i = SendMessage( GetDlgItem( hDlg, IDC_PAKTYPE ), CB_GETCURSEL, 0, 0 ); + bByte = (BYTE)SendMessage( hDlgItem, CB_GETITEMDATA, i, 0 ); + } + else + bByte = PAK_NONRAW; + + + if( bByte == bCurrentPak && hPakWindow ) + SendMessage( hPakWindow, WM_USER_UPDATE, 0, 0 ); + else + { + if( hPakWindow ) + DestroyWindow( hPakWindow ); + + hDlgItem = GetDlgItem( hDlg, IDC_PAKAREA ); + + switch( bByte ) + { + case PAK_MEM: + hPakWindow = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_PAK_MEMPAK ), hDlg, MemPakProc ); + break; + case PAK_RUMBLE: + hPakWindow = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_PAK_RUMBLE ), hDlg, RumblePakProc ); + break; + case PAK_TRANSFER: + hPakWindow = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_PAK_TRANSFER ), hDlg, TransferPakProc ); + break; + case PAK_ADAPTOID: + hPakWindow = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_PAK_ADAPTOID ), hDlg, PakProc ); + break; + + case PAK_VOICE: + case PAK_NONRAW: + case PAK_NONE: + default: + hPakWindow = CreateDialog( g_hResourceDLL, MAKEINTRESOURCE( IDD_PAK_TEXT ), hDlg, PakProc ); + + } + if( hPakWindow ) + { + RECT rectProp, rectMain; // need to know the position of the calling tab window relative to its parent + + GetWindowRect( hDlg, &rectMain ); + GetWindowRect( hDlgItem, &rectProp ); + + MoveWindow( hPakWindow, rectProp.left - rectMain.left, rectProp.top - rectMain.top, rectProp.right - rectProp.left, rectProp.bottom - rectProp.top, FALSE ); + ShowWindow( hPakWindow, SW_SHOW ); + } + bCurrentPak = bByte; + } + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +} + +BOOL CALLBACK PakProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + TCHAR tszLineOne[DEFAULT_BUFFER] = _T(""), tszLineTwo[DEFAULT_BUFFER] = _T(""); + TCHAR *pszDescription[2] = { tszLineOne, tszLineTwo }; + bool bRAW; + + switch(uMsg) + { + case WM_INITDIALOG: + PakProc( hDlg, WM_USER_UPDATE, 0, 0 ); + return FALSE; // don't give it focus + + case WM_USER_UPDATE: + bRAW = g_ivConfig->Controllers[g_ivConfig->ChosenTab].fRawData ? 1 : 0; + + switch( g_ivConfig->Controllers[g_ivConfig->ChosenTab].PakType ) + { + case PAK_MEM: + LoadString( g_hResourceDLL, IDS_P_MEM_NORAW, pszDescription[0], DEFAULT_BUFFER ); + break; + case PAK_RUMBLE: + LoadString( g_hResourceDLL, IDS_P_RUMBLE_NORAW, pszDescription[0], DEFAULT_BUFFER ); + break; + case PAK_TRANSFER: + LoadString( g_hResourceDLL, IDS_P_TRANSFER_NORAW, pszDescription[0], DEFAULT_BUFFER ); + break; + case PAK_VOICE: + LoadString( g_hResourceDLL, IDS_P_VOICE_RAW, pszDescription[1], DEFAULT_BUFFER ); + pszDescription[0] = pszDescription[1]; + break; + case PAK_ADAPTOID: + LoadString( g_hResourceDLL, IDS_P_ADAPTOID_NORAW, pszDescription[0], DEFAULT_BUFFER ); + break; + case PAK_NONE: + default: + LoadString( g_hResourceDLL, IDS_P_NONE_RAWNORAW, pszDescription[1], DEFAULT_BUFFER ); + pszDescription[0] = pszDescription[1]; + } + SendMessage( GetDlgItem( hDlg, IDT_PAKDESC ), WM_SETTEXT, 0, (LPARAM)pszDescription[bRAW] ); + + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +} + +BOOL CALLBACK MemPakProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + static TCHAR *pszMemPakFile; + static WORD wMemPakState; + static int iSelectedNote; + TCHAR szBuffer[MAX_PATH+1], szTemp[MAX_PATH+1]; + + HWND hDlgItem; + long i,j; + + switch(uMsg) + { + case WM_INITDIALOG: + if( g_bRunning ) + { + EnableWindow( GetDlgItem( hDlg, IDC_CHGDIR ), FALSE ); + LoadString( g_hResourceDLL, IDS_P_MEM_NOCHANGE, szBuffer, MAX_PATH + 1 ); + SendMessage( GetDlgItem( hDlg, IDC_CHGDIR ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + } + iSelectedNote = -1; + // Browser + hDlgItem = GetDlgItem( hDlg, IDC_MEMPAKBROWSER ); + + LVCOLUMN lvColumn; + + lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; + lvColumn.fmt = LVCFMT_LEFT; + lvColumn.cx = 147; + LoadString( g_hResourceDLL, IDS_P_MEM_NAME, szBuffer, MAX_PATH + 1 ); + lvColumn.pszText = szBuffer; + ListView_InsertColumn( hDlgItem, 0, &lvColumn ); + + lvColumn.fmt = LVCFMT_CENTER | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + + lvColumn.cx = 70; + lvColumn.iSubItem = 1; + LoadString( g_hResourceDLL, IDS_P_MEM_REGION, szBuffer, MAX_PATH + 1 ); + lvColumn.pszText = szBuffer; + ListView_InsertColumn( hDlgItem, 1, &lvColumn ); + + lvColumn.cx = 50; + lvColumn.iSubItem = 2; + LoadString( g_hResourceDLL, IDS_P_MEM_BLOCKS, szBuffer, MAX_PATH + 1 ); + lvColumn.pszText = szBuffer; + ListView_InsertColumn( hDlgItem, 2, &lvColumn ); + + ListView_SetExtendedListViewStyle( hDlgItem, LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP ); + + + MemPakProc( hDlg, WM_USER_UPDATE, 0, 0 ); // setting values + return FALSE; // don't give it focus + + case WM_COMMAND: + hDlgItem = GetDlgItem( hDlg, LOWORD(wParam) ); + switch( LOWORD(wParam) ) + { + TCHAR tszTitle[DEFAULT_BUFFER], tszText[DEFAULT_BUFFER]; + + case IDC_MEMPAKLIST: + if( HIWORD(wParam) == LBN_SELCHANGE ) + { + i = SendMessage( hDlgItem, LB_GETCURSEL, 0, 0 ); + SendMessage( hDlgItem, LB_GETTEXT, i, (LPARAM)pszMemPakFile ); + MemPakProc( hDlg, WM_USER_UPDATE, 1, 0 ); + } + return TRUE; + case IDC_BROWSE: + lstrcpyn( szBuffer, pszMemPakFile, ARRAYSIZE(szBuffer) ); + if( BrowseFile( hDlg, szBuffer, BF_MEMPAK, BF_LOAD )) + { + if( !CheckFileExists( szBuffer ) ) + { + BYTE aMemPak[PAK_MEM_SIZE]; + + FormatMemPak( aMemPak ); + WriteMemPakFile( szBuffer, aMemPak, true ); + } + if( CheckFileExists( szBuffer ) ) + { + lstrcpyn( pszMemPakFile, szBuffer, MAX_PATH ); + MemPakProc( hDlg, WM_USER_UPDATE, 0, 0 ); + } + } + return TRUE; + case IDC_CHGDIR: + if( DialogBox( g_hResourceDLL, MAKEINTRESOURCE( IDD_FOLDERS ), hDlg, FoldersDialogProc ) == TRUE ) + MemPakProc( hDlg, WM_USER_UPDATE, 0, 0 ); + return TRUE; + + case IDC_DELMEMPAK: + LoadString( g_hResourceDLL, IDS_DLG_DELETEPAK, tszText, DEFAULT_BUFFER ); + LoadString( g_hResourceDLL, IDS_DLG_MSG_TITLE, tszTitle, DEFAULT_BUFFER ); + if( MessageBox( hDlg, tszText, tszTitle, MB_OKCANCEL | MB_ICONQUESTION ) == IDOK ) + { + GetAbsoluteFileName( szBuffer, pszMemPakFile, DIRECTORY_MEMPAK ); + DeleteFile( szBuffer ); + pszMemPakFile[0] = '\0'; + MemPakProc( hDlg, WM_USER_UPDATE, 0, 0 ); + } + return TRUE; + + case IDC_FORMATMEMPAK: + LoadString( g_hResourceDLL, IDS_DLG_FORMATPAK, tszText, DEFAULT_BUFFER ); + LoadString( g_hResourceDLL, IDS_DLG_MSG_TITLE, tszTitle, DEFAULT_BUFFER ); + if( MessageBox( hDlg, tszText, tszTitle, MB_OKCANCEL | MB_ICONQUESTION ) == IDOK ) + { + GetAbsoluteFileName( szBuffer, pszMemPakFile, DIRECTORY_MEMPAK ); + BYTE aMemPak[PAK_MEM_SIZE]; + + FormatMemPak( aMemPak ); + WriteMemPakFile( szBuffer, aMemPak, false ); + MemPakProc( hDlg, WM_USER_UPDATE, 1, 0 ); + } + return TRUE; + case IDC_SAVENOTE: + { + BYTE aMemPak[PAK_MEM_SIZE]; + if( g_bRunning && ( HIWORD(wMemPakState) == MPAK_INUSE ) + && g_pcControllers[g_ivConfig->ChosenTab].pPakData + && ( *(BYTE*)g_pcControllers[g_ivConfig->ChosenTab].pPakData == PAK_MEM )) + { + EnterCriticalSection( &g_critical ); + CopyMemory( aMemPak, ((MEMPAK*)g_pcControllers[g_ivConfig->ChosenTab].pPakData)->aMemPakData, PAK_MEM_SIZE ); + LeaveCriticalSection( &g_critical ); + } + else + { + GetAbsoluteFileName( szBuffer, pszMemPakFile, DIRECTORY_MEMPAK ); + ReadMemPakFile( szBuffer, aMemPak, false ); + } + + int iChars = TranslateNotes( &aMemPak[0x300 + iSelectedNote * 32 + 0x10], szBuffer, 16 ); + + if( TranslateNotes( &aMemPak[0x300 + iSelectedNote * 32 + 0x0C], &szBuffer[iChars + 1], 1 ) ) + szBuffer[iChars] = _T('_'); + + if( BrowseFile( hDlg, szBuffer, BF_NOTE, BF_SAVE )) + { + TCHAR szAbsoluteMemPak[MAX_PATH+1]; + GetAbsoluteFileName( szAbsoluteMemPak, pszMemPakFile, DIRECTORY_MEMPAK ); + + SaveNoteFileA( aMemPak, iSelectedNote, szBuffer ); + } + } + return TRUE; + case IDC_INSERTNOTE: + { + GetAbsoluteFileName( szBuffer, pszMemPakFile, DIRECTORY_MEMPAK ); + BYTE aMemPak[PAK_MEM_SIZE]; + ReadMemPakFile( szBuffer, aMemPak, false ); + szBuffer[0] = '\0'; + + if( BrowseFile( hDlg, szBuffer, BF_NOTE, BF_LOAD )) + { + if( InsertNoteFile( aMemPak, szBuffer ) ) + { + GetAbsoluteFileName( szBuffer, pszMemPakFile, DIRECTORY_MEMPAK ); + WriteMemPakFile( szBuffer, aMemPak, false ); + MemPakProc( hDlg, WM_USER_UPDATE, 1, 0 ); + } + } + } + return TRUE; + case IDC_DELETENOTE: + LoadString( g_hResourceDLL, IDS_DLG_DELETENOTE, tszText, DEFAULT_BUFFER ); + LoadString( g_hResourceDLL, IDS_DLG_MSG_TITLE, tszTitle, DEFAULT_BUFFER ); + if( MessageBox( hDlg, tszText, tszTitle, MB_OKCANCEL | MB_ICONQUESTION ) == IDOK ) + { + GetAbsoluteFileName( szBuffer, pszMemPakFile, DIRECTORY_MEMPAK ); + BYTE aMemPak[PAK_MEM_SIZE]; + ReadMemPakFile( szBuffer, aMemPak, false ); + if( RemoveNote( aMemPak, iSelectedNote ) ) + { + WriteMemPakFile( szBuffer, aMemPak, false ); + MemPakProc( hDlg, WM_USER_UPDATE, 1, 0 ); + } + } + return TRUE; + default: + return FALSE; + } + + case WM_NOTIFY: + switch( ((LPNMHDR)lParam)->idFrom ) + { + case IDC_MEMPAKBROWSER: + switch( ((LPNMHDR)lParam)->code ) + { + case LVN_ITEMCHANGED: + if( ((LPNMLISTVIEW)lParam)->uNewState & LVIS_SELECTED ) + { + iSelectedNote = ((LPNMLISTVIEW)lParam)->lParam; + if( HIBYTE(wMemPakState) & MPAK_READABLE ) + EnableWindow( GetDlgItem( hDlg, IDC_SAVENOTE ), TRUE ); + if( HIBYTE(wMemPakState) & MPAK_WRITEABLE ) + EnableWindow( GetDlgItem( hDlg, IDC_DELETENOTE ), TRUE ); + } + else + { + iSelectedNote = -1; + EnableWindow( GetDlgItem( hDlg, IDC_SAVENOTE ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDC_DELETENOTE ), FALSE ); + } + return TRUE; + default: + return FALSE; + } + default: + return FALSE; + } + + case WM_USER_UPDATE: + pszMemPakFile = g_ivConfig->Controllers[g_ivConfig->ChosenTab].szMempakFile; + iSelectedNote = -1; + + // Mempak List Window + if( wParam == 0 && lParam == 0 ) + { + hDlgItem = GetDlgItem( hDlg, IDC_MEMPAKLIST ); + SendMessage( hDlgItem, LB_RESETCONTENT, 0, 0 ); + SendFilestoList( hDlgItem, FILIST_MEM ); + + if( pszMemPakFile[1] == ':' || ( pszMemPakFile[1] == '\\' && pszMemPakFile[0] == '\\' )) + { + GetDirectory( szBuffer, DIRECTORY_MEMPAK ); + i = lstrlen( szBuffer ); + if( !_tcsncmp( szBuffer, pszMemPakFile, i )) + { + lstrcpyn( szBuffer, &pszMemPakFile[i], MAX_PATH ); + lstrcpyn( pszMemPakFile, szBuffer, MAX_PATH ); + } + + } + + j = -1; + if( !( pszMemPakFile[1] == ':' || ( pszMemPakFile[1] == '\\' && pszMemPakFile[0] == '\\' )) ) + { + i = SendMessage( hDlgItem, LB_FINDSTRINGEXACT, (WPARAM)(-1), (LPARAM)pszMemPakFile ); + if( i != LB_ERR ) + j = i; + } + SendMessage( hDlgItem, LB_SETCURSEL, j, 0 ); + } + // Mempak List Window End + + // MamPak Full Path+Name + GetAbsoluteFileName( szBuffer, pszMemPakFile, DIRECTORY_MEMPAK ); + + // MemPak Browser + ListView_DeleteAllItems( GetDlgItem( hDlg, IDC_MEMPAKBROWSER )); + if( (!lstrcmpi( &szBuffer[lstrlen(szBuffer)-4], _T(".mpk") )) + || (!lstrcmpi( &szBuffer[lstrlen(szBuffer)-4], _T(".n64") ))) + { + BYTE aMemPakHeader[0x500]; + + bool bMemPakUsed = false; + // first, if we're running emulation we need to make sure we haven't selected a file that's currently in use + if (g_bRunning) + { + TCHAR szMemPakFile[MAX_PATH+1]; + for( i = 0; i < 4; ++i ) + { + if( g_pcControllers[i].pPakData && ( *(BYTE*)g_pcControllers[i].pPakData == PAK_MEM ) && !((LPMEMPAK)g_pcControllers[i].pPakData)->fReadonly ) + { + GetAbsoluteFileName( szMemPakFile, g_pcControllers[i].szMempakFile, DIRECTORY_MEMPAK ); + if( !lstrcmp( szMemPakFile, szBuffer )) + { + // grab the file info from memory instead of the file... but keep in mind we can't do anything dangerous with it + EnterCriticalSection( &g_critical ); + wMemPakState = ShowMemPakContent( ((MEMPAK*)g_pcControllers[i].pPakData)->aMemPakData, GetDlgItem( hDlg, IDC_MEMPAKBROWSER )); + LeaveCriticalSection( &g_critical ); + if (HIBYTE(wMemPakState) == MPAK_OK) + { + LoadString( g_hResourceDLL, IDS_P_MEM_INUSE, szTemp, MAX_PATH + 1 ); + wsprintf( szBuffer, szTemp, LOBYTE(wMemPakState) ); + wMemPakState = MAKEWORD( MPAK_READABLE, MPAK_INUSE ); + } + bMemPakUsed = true; + } + } + } + } + + if( !bMemPakUsed ) + { + HANDLE hFile; + hFile = CreateFile( szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); + if ( hFile != INVALID_HANDLE_VALUE ) + { + DWORD dwFileSize = GetFileSize( hFile, NULL ); + DWORD dwCorrectFileSize = PAK_MEM_SIZE; + + TCHAR *pcPoint = _tcsrchr( szBuffer, _T('.') ); + if( !lstrcmpi( pcPoint, _T(".n64") ) ) + { + SetFilePointer( hFile, PAK_MEM_DEXOFFSET, NULL, FILE_BEGIN ); + dwCorrectFileSize += PAK_MEM_DEXOFFSET; + } + else + SetFilePointer( hFile, 0L, NULL, FILE_BEGIN ); + + if( dwFileSize > ( dwCorrectFileSize - 0x7500 )) + { + DWORD dwBytesRead; + + ReadFile( hFile, aMemPakHeader, 0x500, &dwBytesRead, NULL); + ListView_DeleteAllItems( GetDlgItem( hDlg, IDC_MEMPAKBROWSER )); + wMemPakState = ShowMemPakContent( aMemPakHeader, GetDlgItem( hDlg, IDC_MEMPAKBROWSER )); + } + else + wMemPakState = MAKEWORD( 0, MPAK_DAMAGED ); + + if( HIBYTE( wMemPakState ) == MPAK_OK && + dwFileSize != dwCorrectFileSize ) + wMemPakState = MAKEWORD( LOBYTE( wMemPakState ), MPAK_WRONGSIZE ); + + CloseHandle( hFile ); + } + else + wMemPakState = MAKEWORD( 0, MPAK_ERROR ); + } + } + else + wMemPakState = MAKEWORD( 0, MPAK_NOSELECTION ); + + switch( HIBYTE(wMemPakState) ) + { + case MPAK_OK: + LoadString( g_hResourceDLL, IDS_P_MEM_BLOCKSFREE, szTemp, MAX_PATH + 1 ); + wsprintf( szBuffer, szTemp, LOBYTE(wMemPakState) ); + break; + case MPAK_INUSE: + // text field already set + break; + case MPAK_WRONGSIZE: + LoadString( g_hResourceDLL, IDS_P_MEM_WRONGSIZE, szTemp, MAX_PATH + 1 ); + wsprintf( szBuffer, szTemp, LOBYTE(wMemPakState) ); + break; + case MPAK_NOSELECTION: + LoadString( g_hResourceDLL, IDS_P_MEM_NONESELECTED, szBuffer, MAX_PATH + 1 ); + break; + case MPAK_DAMAGED: + LoadString( g_hResourceDLL, IDS_P_MEM_DAMAGED, szBuffer, MAX_PATH + 1 ); + break; + + case MPAK_ERROR: + default: + { + LoadString( g_hResourceDLL, IDS_P_MEM_ERROR, szTemp, MAX_PATH + 1 ); + DWORD dwError = GetLastError(); + DWORD dwLength = wsprintf( szBuffer, szTemp, dwError ); + FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError , 0, &szBuffer[dwLength], ARRAYSIZE(szBuffer) - dwLength - 1, NULL ); + } + break; + } + SendMessage( GetDlgItem( hDlg, IDT_MEMPAKSTATE ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + + if( HIBYTE(wMemPakState) & MPAK_FORMATABLE ) + { + EnableWindow( GetDlgItem( hDlg, IDC_FORMATMEMPAK ), TRUE ); + EnableWindow( GetDlgItem( hDlg, IDC_DELMEMPAK ), TRUE ); + } + else + { + EnableWindow( GetDlgItem( hDlg, IDC_FORMATMEMPAK ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDC_DELMEMPAK ), FALSE ); + } + + if( HIBYTE(wMemPakState) & MPAK_WRITEABLE ) + EnableWindow( GetDlgItem( hDlg, IDC_INSERTNOTE ), TRUE ); + else + EnableWindow( GetDlgItem( hDlg, IDC_INSERTNOTE ), FALSE ); + + EnableWindow( GetDlgItem( hDlg, IDC_SAVENOTE ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDC_DELETENOTE ), FALSE ); + + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +} + +BOOL CALLBACK RumblePakProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + static BOOL bNewRumbleTyp = true; + IFDEVICE *pifDevice = &g_ivConfig->FFDevices[g_ivConfig->ChosenTab]; + CONTROLLER *pcController = &g_ivConfig->Controllers[g_ivConfig->ChosenTab]; + TCHAR szBuffer[DEFAULT_BUFFER], szTemp[DEFAULT_BUFFER]; + HWND hDlgItem; + long i = 0,j; + + switch(uMsg) + { + case WM_INITDIALOG: + hDlgItem = GetDlgItem( hDlg, IDC_RUMBLESTRENGTH ); + + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 100 )); + SendMessage( hDlgItem, TBM_SETTICFREQ, (WPARAM) 10, 0 ); + SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM) 0, 1 ); + + RumblePakProc( hDlg, WM_USER_UPDATE, 0, 0 ); + return FALSE; // don't give it focus + + case WM_COMMAND: + hDlgItem = GetDlgItem( hDlg, LOWORD(wParam) ); + + switch( LOWORD(wParam) ) + { + case IDC_CTRDEVICE: + if( HIWORD(wParam) == CBN_SELCHANGE ) + { + i = SendMessage( hDlgItem, CB_GETCURSEL, 0, 0 ); + j = SendMessage( hDlgItem, CB_GETITEMDATA, i, 0 ); + + EnterCriticalSection(&g_critical); + if( j == -1 ) + { + pifDevice->bProductCounter = 0; + pifDevice->szProductName[0] = '\0'; + } + else + { + pifDevice->bProductCounter = g_devList[j].bProductCounter; + lstrcpyn( pifDevice->szProductName, g_devList[j].szProductName, sizeof(pifDevice->szProductName) / sizeof(TCHAR) ); + } + LeaveCriticalSection(&g_critical); + + RumblePakProc( hDlg, WM_USER_UPDATE, 0, 0 ); // en/disabling RumbleOptions + } + return TRUE; + + // the following three cases use fallthrough assignment + case IDC_RUMBLE1: + if( LOWORD(wParam) == IDC_RUMBLE1 ) + i = RUMBLE_EFF1; + case IDC_RUMBLE2: + if( LOWORD(wParam) == IDC_RUMBLE2 ) + i = RUMBLE_EFF2; + case IDC_RUMBLE3: + if( LOWORD(wParam) == IDC_RUMBLE3 ) + i = RUMBLE_EFF3; + if(( HIWORD(wParam) == BN_CLICKED ) && + ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED )) + { + pcController->bRumbleTyp = (BYTE)i; + bNewRumbleTyp = true; + } + return TRUE; + + case IDC_VISUALRUMBLE: + pcController->fVisualRumble = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + return TRUE; + + case IDC_RUMBLETEST: + if ( !g_pConfigEffect || bNewRumbleTyp ) + { + EnterCriticalSection(&g_critical); + ReleaseEffect( g_pConfigEffect ); + if ( !CreateEffectHandle(g_hMainDialog, g_pConfigDevice, g_pConfigEffect, pcController->bRumbleTyp, pcController->bRumbleStrength) ) + { + DebugWriteA("Interface: CreateEffectHandle failed\n"); + } + bNewRumbleTyp = false; + LeaveCriticalSection(&g_critical); + } + g_pConfigDevice->Acquire(); + { + HRESULT hRslt = g_pConfigEffect->Start(1, 0); + if (hRslt != DI_OK ) + { + switch (hRslt) + { + case DIERR_INCOMPLETEEFFECT: + DebugWriteA("Test Rumble: DIError: incomplete effect.\n"); + break; + case DIERR_INVALIDPARAM: + DebugWriteA("Test Rumble: DIError: invalid param.\n"); + break; + case DIERR_NOTEXCLUSIVEACQUIRED: + DebugWriteA("Test Rumble: DIError: not exclusive acquired.\n"); + break; + case DIERR_NOTINITIALIZED: + DebugWriteA("Test Rumble: DIError: not initialized.\n"); + break; + case DIERR_UNSUPPORTED: + DebugWriteA("Test Rumble: DIError: unsupported.\n"); + break; + default: + DebugWriteA("Test Rumble: DIError: undocumented: %lX\n", hRslt); + } + } + else + DebugWriteA("Test Rumble: OK\n"); + } + return TRUE; + + default: + return FALSE; + } + + case WM_HSCROLL: // TrackBars + case WM_VSCROLL: + i = GetWindowLong( (HWND)lParam, GWL_ID ); + switch( i ) + { + case IDC_RUMBLESTRENGTH: + pcController->bRumbleStrength = (BYTE)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); + LoadString( g_hResourceDLL, IDS_D_RUMBLESTR, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->bRumbleStrength ); + SendMessage( GetDlgItem( hDlg, IDT_RUMBLESTRENGTH ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + bNewRumbleTyp = true; + return TRUE; + default: + return FALSE; + } + + case WM_USER_UPDATE: + // filling DropDownlist with devices + hDlgItem = GetDlgItem( hDlg, IDC_CTRDEVICE ); + SendMessage (hDlgItem, CB_RESETCONTENT, 0, 0); // HACK: yeah this isn't the best way to do this, but it works. + LoadString( g_hResourceDLL, IDS_P_R_NODEVICE, szBuffer, DEFAULT_BUFFER ); + j = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)szBuffer ); + SendMessage( hDlgItem, CB_SETITEMDATA, j, -1 ); + for( i = 0; i < g_nDevices; i++ ) + { + bool bMatch = false; + // if device is not already set as a FF device in some other tab + for( int m = 0; m < 4; m++) + { + if( g_ivConfig->ChosenTab != m) + if (g_devList[i].bProductCounter == g_ivConfig->FFDevices[m].bProductCounter && !lstrcmp( g_devList[i].szProductName, g_ivConfig->FFDevices[m].szProductName ) ) + bMatch = true; + } + + + if (!bMatch && g_devList[i].bEffType != 0 ) + { + if( g_devList[i].bProductCounter == 0 ) + lstrcpyn( szBuffer, g_devList[i].szProductName, ARRAYSIZE(szBuffer) ); + else + wsprintf( szBuffer, _T("%s %i"), g_devList[i].szProductName, g_devList[i].bProductCounter ); + + j = SendMessage( hDlgItem, CB_ADDSTRING, 0, (LPARAM)szBuffer ); + SendMessage( hDlgItem, CB_SETITEMDATA, j, i ); + } + } + // DropDownlist End + + EnterCriticalSection(&g_critical); + j = FindDeviceinList( pifDevice->szProductName, pifDevice->bProductCounter, true ); + hDlgItem = GetDlgItem( hDlg, IDC_CTRDEVICE ); + ReleaseEffect( g_pConfigEffect ); + ReleaseDevice( g_pConfigDevice ); + if( j == -1 || !g_devList[j].bEffType) + { + SendMessage( hDlgItem, CB_SETCURSEL, 0, 0 ); // set "None" + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLE1 ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLE2 ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLE3 ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLESTRENGTH ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDT_RUMBLESTRENGTH ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLETEST ), FALSE ); + } + else + { + if (! GetInputDevice( g_hMainDialog, g_pConfigDevice, g_devList[j].guidInstance, g_devList[j].dwDevType, DIB_FF ) ) + { + g_pConfigDevice = NULL; + DebugWriteA("Could not GetInputDevice in user update, RumblePakProc.\n"); + } + else + { + DebugWriteA("GetInputDevice in RumblePakProc: OK\n"); + } + + // DropDownList + if( g_devList[j].bProductCounter == 0 ) + i = SendMessage( hDlgItem, CB_FINDSTRINGEXACT, (WPARAM)(-1), (LPARAM)g_devList[j].szProductName ); + else + { + wsprintf( szBuffer, _T("%s %i"), g_devList[j].szProductName, g_devList[j].bProductCounter ); + i = SendMessage( hDlgItem, CB_FINDSTRINGEXACT, (WPARAM)(-1), (LPARAM)szBuffer ); // search index of Device-String + } + + SendMessage( hDlgItem, CB_SETCURSEL, i, 0 ); // select the right string + + if( g_devList[j].bEffType & RUMBLE_EFF1 ) + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLE1 ), TRUE ); + else + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLE1 ), FALSE ); + if( g_devList[j].bEffType & RUMBLE_EFF2 ) + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLE2 ), TRUE ); + else + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLE2 ), FALSE ); + if( g_devList[j].bEffType & RUMBLE_EFF3 ) + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLE3 ), TRUE ); + else + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLE3 ), FALSE ); + + if( ( g_devList[j].bEffType & RUMBLE_EFF1 ) || + ( g_devList[j].bEffType & RUMBLE_EFF2 )) + { + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLESTRENGTH ), TRUE ); + EnableWindow( GetDlgItem( hDlg, IDT_RUMBLESTRENGTH ), TRUE ); + } + else + { + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLESTRENGTH ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDT_RUMBLESTRENGTH ), FALSE ); + } + + if( g_devList[j].bEffType != RUMBLE_NONE ) + { + // if (!CreateEffectHandle(g_hMainDialog, g_pConfigDevice, g_pConfigEffect, pcController->bRumbleTyp, pcController->bRumbleStrength) ) + // { + // DebugWriteA("Interface: CreateEffectHandle failed\n"); + // } + bNewRumbleTyp = true; + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLETEST ), TRUE ); + } + else + EnableWindow( GetDlgItem( hDlg, IDC_RUMBLETEST ), FALSE ); + + } + LeaveCriticalSection(&g_critical); + + if( pcController->bRumbleTyp == RUMBLE_EFF1 ) + CheckDlgButton( hDlg, IDC_RUMBLE1, BST_CHECKED ); + else + CheckDlgButton( hDlg, IDC_RUMBLE1, BST_UNCHECKED ); + if( pcController->bRumbleTyp == RUMBLE_EFF2 ) + CheckDlgButton( hDlg, IDC_RUMBLE2, BST_CHECKED ); + else + CheckDlgButton( hDlg, IDC_RUMBLE2, BST_UNCHECKED ); + if( pcController->bRumbleTyp == RUMBLE_EFF3 ) + CheckDlgButton( hDlg, IDC_RUMBLE3, BST_CHECKED ); + else + CheckDlgButton( hDlg, IDC_RUMBLE3, BST_UNCHECKED ); + + CheckDlgButton( hDlg, IDC_VISUALRUMBLE, pcController->fVisualRumble ? BST_CHECKED : BST_UNCHECKED ); + + // TrackBars + SendMessage( GetDlgItem( hDlg, IDC_RUMBLESTRENGTH ), TBM_SETPOS, TRUE, pcController->bRumbleStrength ); + LoadString( g_hResourceDLL, IDS_D_RUMBLESTR, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->bRumbleStrength ); + SendMessage( GetDlgItem( hDlg, IDT_RUMBLESTRENGTH ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +} + +BOOL CALLBACK TransferPakProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + static LPTSTR pszGBRomFile = NULL; + static LPTSTR pszGBSaveFile = NULL; + TCHAR tszMsg[DEFAULT_BUFFER]; + + switch(uMsg) + { + case WM_INITDIALOG: + if( g_bRunning ) + { + EnableWindow( GetDlgItem( hDlg, IDC_CHGDIR ), FALSE ); + LoadString( g_hResourceDLL, IDS_P_TRANS_NOCHANGE, tszMsg, DEFAULT_BUFFER ); + SendMessage( GetDlgItem( hDlg, IDC_CHGDIR ), WM_SETTEXT, 0, (LPARAM)tszMsg ); + } + + TransferPakProc( hDlg, WM_USER_UPDATE, 0, 0 ); // setting values + return FALSE; // don't give it focus + + case WM_COMMAND: + switch( LOWORD(wParam) ) + { + case IDC_GBROM_EDIT: + if( HIWORD(wParam) == EN_CHANGE ) + GetDlgItemText( hDlg, IDC_GBROM_EDIT, pszGBRomFile, ARRAYSIZE(g_ivConfig->Controllers->szTransferRom) ); + return TRUE; + + case IDC_GBSAVE_EDIT: + if( HIWORD(wParam) == EN_CHANGE ) + GetDlgItemText( hDlg, IDC_GBSAVE_EDIT, pszGBSaveFile, ARRAYSIZE(g_ivConfig->Controllers->szTransferSave) ); + return TRUE; + + case IDC_GBROM_BROWSE: + { + TCHAR szBuffer[MAX_PATH+1]; + GetAbsoluteFileName( szBuffer, pszGBRomFile, DIRECTORY_GBROMS ); + if( BrowseFile( hDlg, szBuffer, BF_GBROM, BF_LOAD )) + { + lstrcpyn( pszGBRomFile, szBuffer, ARRAYSIZE(g_ivConfig->Controllers->szTransferRom) ); + TransferPakProc( hDlg, WM_USER_UPDATE, 0, 0 ); + } + } + return TRUE; + + case IDC_GBSAVE_BROWSE: + { + TCHAR szBuffer[MAX_PATH+1]; + GetAbsoluteFileName( szBuffer, pszGBSaveFile, DIRECTORY_GBSAVES ); + if( BrowseFile( hDlg, szBuffer, BF_GBSAVE, BF_LOAD )) + { + lstrcpyn( pszGBSaveFile, szBuffer, ARRAYSIZE(g_ivConfig->Controllers->szTransferSave) ); + TransferPakProc( hDlg, WM_USER_UPDATE, 0, 0 ); + } + } + return TRUE; + + case IDC_CHGDIR: + if( DialogBox( g_hResourceDLL, MAKEINTRESOURCE( IDD_FOLDERS ), hDlg, FoldersDialogProc ) == TRUE ) + TransferPakProc( hDlg, WM_USER_UPDATE, 0, 0 ); + return TRUE; + + default: + return FALSE; + } + + case WM_USER_UPDATE: + pszGBRomFile = g_ivConfig->Controllers[g_ivConfig->ChosenTab].szTransferRom; + pszGBSaveFile = g_ivConfig->Controllers[g_ivConfig->ChosenTab].szTransferSave; + + SetDlgItemText( hDlg, IDC_GBROM_EDIT, pszGBRomFile ); + SetDlgItemText( hDlg, IDC_GBSAVE_EDIT, pszGBSaveFile ); + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +} + +BOOL CALLBACK ShortcutsTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + static bool bScanRunning; + static DWORD dwButtonID[3]; + static DWORD dwCounter; + static HWND hFocus = NULL; + static int iPlayer = 5; // HACK: player "5" is obviously out of bounds, so indicates no control has been set + + long i; + static HWND hBlocker = NULL; + + TCHAR szBuffer[40]; + + switch(uMsg) + { + case WM_INITDIALOG: + + bScanRunning = false; + iPlayer = 5; + + ShortcutsTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); // setting values + return FALSE; // don't give it focus + + case WM_COMMAND: + switch( LOWORD(wParam) ) + { + case IDC_SHOWMESSAGES: + g_ivConfig->fDisplayShortPop = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + return TRUE; + case IDC_LOCKMOUSE: + iPlayer = -1; + + case IDC_SETNOPAK_P1: + case IDC_SETMEMPAK_P1: + case IDC_SETRUMBLEPAK_P1: + case IDC_SETTRANSFERPAK_P1: + case IDC_SETADAPTOIDPAK_P1: + case IDC_SWMEMRUMBLE_P1: + case IDC_SWMEMADAPTOID_P1: + if (iPlayer > -1) + iPlayer = 0; + + case IDC_SETNOPAK_P2: + case IDC_SETMEMPAK_P2: + case IDC_SETRUMBLEPAK_P2: + case IDC_SETTRANSFERPAK_P2: + case IDC_SETADAPTOIDPAK_P2: + case IDC_SWMEMRUMBLE_P2: + case IDC_SWMEMADAPTOID_P2: + if (iPlayer > 0) + iPlayer = 1; + + case IDC_SETNOPAK_P3: + case IDC_SETMEMPAK_P3: + case IDC_SETRUMBLEPAK_P3: + case IDC_SETTRANSFERPAK_P3: + case IDC_SETADAPTOIDPAK_P3: + case IDC_SWMEMRUMBLE_P3: + case IDC_SWMEMADAPTOID_P3: + if (iPlayer > 1) + iPlayer = 2; + + case IDC_SETNOPAK_P4: + case IDC_SETMEMPAK_P4: + case IDC_SETRUMBLEPAK_P4: + case IDC_SETTRANSFERPAK_P4: + case IDC_SETADAPTOIDPAK_P4: + case IDC_SWMEMRUMBLE_P4: + case IDC_SWMEMADAPTOID_P4: + if (iPlayer > 2) + iPlayer = 3; + + if( bScanRunning ) + { +/* bScanRunning = false; + KillTimer( hDlg, TIMER_BUTTON ); + if( ((LPBYTE)&g_ivConfig->Shortcuts)[dwButtonID[2]] == VK_ESCAPE ) + lstrcpyn( szKeyname, "Unassigned", sizeof(szKeyname) ); + else + GetKeyNameText(( MapVirtualKey( ((LPBYTE)&g_ivConfig->Shortcuts)[dwButtonID[2]], 0 ) << 16 ), szKeyname, sizeof(szKeyname) ); + + SendMessage( GetDlgItem( hDlg, dwButtonID[1] ), WM_SETTEXT, 0, (LPARAM)szKeyname ); */; // do nothing! + } + if( HIWORD(wParam) == BN_CLICKED ) + { + EnterCriticalSection(&g_critical); + dwButtonID[0] = LOWORD(wParam); + dwCounter = 0; + GetButtonID( dwButtonID, 0, BSET_SHORTCUTS ); + if (hFocus == NULL) + hFocus = SetFocus( NULL ); + hBlocker = MakeOverlay(); + + SetTimer( hDlg, TIMER_BUTTON, INTERVAL_BUTTON, NULL ); + bScanRunning = true; + LeaveCriticalSection(&g_critical); + } + return TRUE; + + case IDC_SETDEFAULTSC: + { + TCHAR tszTitle[DEFAULT_BUFFER], tszMsg[DEFAULT_BUFFER]; + + LoadString( g_hResourceDLL, IDS_DLG_SHORTCUTRESTORE, tszMsg, DEFAULT_BUFFER ); + LoadString( g_hResourceDLL, IDS_DLG_CONTROLRESTORE_TITLE, tszTitle, DEFAULT_BUFFER ); + + if( MessageBox( hDlg, tszMsg, tszTitle, MB_OKCANCEL | MB_ICONWARNING ) == IDOK ) + { + LoadShortcutsFromResource(true); + ShortcutsTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); + } + } + return TRUE; + + case IDC_SAVESHORTCUTS: + { + TCHAR szFilename[MAX_PATH+1] = _T( "" ); + if( BrowseFile( hDlg, szFilename, BF_SHORTCUTS, BF_SAVE )) + { + FILE * fFile = _tfopen( szFilename, _T("wS") ); + if (fFile) + { + fprintf(fFile, "@" STRING_PROFILEVERSION "\n\n"); + FormatShortcutsBlock( fFile, false ); + + fclose(fFile); + } + else + WarningMessage( IDS_ERR_PROFWRITE, MB_OK ); + } + } + return TRUE; + + case IDC_LOADSHORTCUTS: + { + TCHAR szFilename[MAX_PATH+1] = TEXT( "" ); + if( BrowseFile( hDlg, szFilename, BF_SHORTCUTS, BF_LOAD )) + { + DebugWrite(_T("Config interface: Load shortcuts file: %s\n"), szFilename); + if( LoadShortcutsFile( szFilename )) + ShortcutsTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); + else + WarningMessage( IDS_ERR_SHORTREAD, MB_OK ); + + } + } + return TRUE; + + default: + return FALSE; + } + + case WM_TIMER: // when assigning shortcuts, this gets called every 20ms (or value in INTERVAL_BUTTON) + if( wParam == TIMER_BUTTON && bScanRunning ) + { + BUTTON newButton; + + i = ScanDevices( &dwCounter, &newButton); + if( i || dwCounter > 500 ) + { + bScanRunning = false; + KillTimer( hDlg, TIMER_BUTTON ); + + EnterCriticalSection(&g_critical); + if( i == SC_SCANESCAPE ) // Scan aborted + { + if (iPlayer == -1) + ZeroMemory(&g_ivConfig->Shortcuts.bMouseLock, sizeof(BUTTON) ); + else + ZeroMemory(&g_ivConfig->Shortcuts.Player[iPlayer].aButtons[dwButtonID[2] % SC_TOTAL], sizeof(BUTTON)); + } + else if( i == SC_SCANSUCCEED ) // Got a key, mouseclick, joybutton, or axis + if (iPlayer == -1) + g_ivConfig->Shortcuts.bMouseLock = newButton; + else + g_ivConfig->Shortcuts.Player[iPlayer].aButtons[dwButtonID[2] % SC_TOTAL] = newButton; + DestroyWindow( hBlocker ); + + + if (iPlayer == -1) + GetButtonText( g_ivConfig->Shortcuts.bMouseLock, szBuffer ); + else + GetButtonText( g_ivConfig->Shortcuts.Player[iPlayer].aButtons[dwButtonID[2] % SC_TOTAL], szBuffer ); + iPlayer = 5; // reset invalid player value + LeaveCriticalSection(&g_critical); + + SendMessage( GetDlgItem( hDlg, dwButtonID[1] ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + if( hFocus != NULL ) + { + SetFocus( hFocus ); + hFocus = NULL; + } + } + else + { + if(( dwCounter % 50 ) == 0 ) + { + TCHAR tszText[DEFAULT_BUFFER]; + + LoadString( g_hResourceDLL, IDS_C_POLLING, tszText, DEFAULT_BUFFER ); + wsprintf( szBuffer, tszText, 10 - dwCounter / 50 ); + SendMessage( GetDlgItem( hDlg, dwButtonID[1] ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + } + ++dwCounter; + } + return TRUE; + } + else + return FALSE; + + case WM_USER_UPDATE: + bScanRunning = false; + KillTimer( hDlg, TIMER_BUTTON ); + + for ( i = 0; i < 4; i++ ) // controllers + for( int j = 0; j < SC_TOTAL * 4; j++ ) // shortcuts + { + DWORD aIDs[3]; + aIDs[2] = i * SC_TOTAL + j; + if( !GetButtonID( aIDs, 2, BSET_SHORTCUTS )) + continue; // for not implemented Buttons, otherwise the behaviour is unsafe + + GetButtonText( g_ivConfig->Shortcuts.Player[i].aButtons[j], szBuffer ); + SendMessage( GetDlgItem( hDlg, aIDs[1] ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + } + + DWORD aIDs[3]; + aIDs[2] = (DWORD)(-1); + if( GetButtonID( aIDs, 2, BSET_SHORTCUTS ) ) + { + GetButtonText( g_ivConfig->Shortcuts.bMouseLock, szBuffer ); + SendMessage( GetDlgItem( hDlg, aIDs[1] ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + } + + CheckDlgButton( hDlg, IDC_SHOWMESSAGES, g_ivConfig->fDisplayShortPop ? BST_CHECKED : BST_UNCHECKED ); + return TRUE; + + default: + return FALSE; //false means the msg didn't got processed + } +} + +BOOL CALLBACK FoldersDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + long i,j; + TCHAR szBuffer[MAX_PATH+1]; + TCHAR szApplication[MAX_PATH+1], + *pcSlash; + + switch(uMsg) + { + case WM_INITDIALOG: + +#if defined(HIDEUNIMPLEMENTED) && !defined(V_TRANSFERPAK) + { + RECT rRect, rGBSave; + GetWindowRect( GetDlgItem( hDlg, IDC_GBSAVEPANEL ), &rGBSave ); + GetWindowRect( GetDlgItem( hDlg, IDC_MEMPAKPANEL ), &rRect ); + int iShift = rRect.bottom - rGBSave.bottom; + + WINDOWPLACEMENT pos; + pos.length = sizeof(WINDOWPLACEMENT); + + GetWindowPlacement( GetDlgItem( hDlg, IDOK ), &pos ); + pos.rcNormalPosition.top += iShift; + pos.rcNormalPosition.bottom += iShift; + SetWindowPlacement( GetDlgItem( hDlg, IDOK ), &pos ); + + GetWindowPlacement( GetDlgItem( hDlg, IDCANCEL ), &pos ); + pos.rcNormalPosition.top += iShift; + pos.rcNormalPosition.bottom += iShift; + SetWindowPlacement( GetDlgItem( hDlg, IDCANCEL ), &pos ); + + GetWindowRect( hDlg, &rRect ); + rRect.bottom += iShift; + + SetWindowPos( hDlg, NULL, rRect.left, rRect.top, rRect.right-rRect.left, rRect.bottom-rRect.top, SWP_NOMOVE | SWP_NOZORDER ); + + int aChilds[] = { IDC_GBROMPANEL, IDC_GBROM_REL, IDC_GBROM_REL_EDIT, IDC_GBROM_BROWSE_REL, IDC_GBROM_ABS, + IDC_GBROM_ABS_EDIT, IDC_GBROM_BROWSE_ABS, IDC_GBSAVEPANEL, IDC_GBSAVE_SAME, IDC_GBSAVE_REL, + IDC_GBSAVE_REL_EDIT, IDC_GBSAVE_BROWSE_REL, IDC_GBSAVE_ABS, IDC_GBSAVE_ABS_EDIT, IDC_GBSAVE_BROWSE_ABS }; + + for( int i = 0; i < sizeof(aChilds)/sizeof(int); ++i ) + DestroyWindow( GetDlgItem( hDlg, aChilds[i] )); + } +#pragma message( "unimplemented Features from the Folderdialog will be removed" ) +#endif // #ifdef HIDEUNIMPLEMENTED + + GetDirectory( szApplication, DIRECTORY_GBROMS ); + GetDirectory( szBuffer, DIRECTORY_GBSAVES ); + j = lstrcmp( szApplication, szBuffer ); + + GetDirectory( szApplication, DIRECTORY_APPLICATION ); + i = lstrlen( szApplication ); + + // MemPak Directory + lstrcpyn(szBuffer, g_aszDefFolders[DIRECTORY_MEMPAK], MAX_PATH); + + if( szBuffer[0] != 0 && ( szBuffer[1] == ':' || ( szBuffer[1] == '\\' && szBuffer[0] == '\\' ))) + { + + CheckDlgButton( hDlg, IDC_MEMPAK_ABS, BST_CHECKED ); + + GetDirectory( szBuffer, DIRECTORY_MEMPAK ); + if( !_tcsncmp( szBuffer, szApplication, i )) + { + TCHAR *pcSub = &szBuffer[i]; + pcSlash = _tcsrchr( pcSub, _T('\\') ); + if( pcSlash && ( pcSlash[1] == '\0' )) *pcSlash = '\0'; + SendMessage( GetDlgItem( hDlg, IDC_MEMPAK_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)pcSub ); + } + else + SendMessage( GetDlgItem( hDlg, IDC_MEMPAK_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)STRING_DEF_MEMPAKFILE ); + } + else + { + CheckDlgButton( hDlg, IDC_MEMPAK_REL, BST_CHECKED ); + + if( szBuffer[0] != 0 ) + SendMessage( GetDlgItem( hDlg, IDC_MEMPAK_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + else + SendMessage( GetDlgItem( hDlg, IDC_MEMPAK_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)STRING_DEF_MEMPAKFILE ); + } + + + GetDirectory( szBuffer, DIRECTORY_MEMPAK ); + pcSlash = _tcsrchr( szBuffer, '\\' ); + if( pcSlash && ( pcSlash[1] == '\0' )) *pcSlash = '\0'; + SendMessage( GetDlgItem( hDlg, IDC_MEMPAK_ABS_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + + // GBRom Directory + lstrcpyn(szBuffer, g_aszDefFolders[DIRECTORY_GBROMS], MAX_PATH); + + if( szBuffer[0] != 0 && ( szBuffer[1] == _T(':') || ( szBuffer[1] == _T('\\') && szBuffer[0] == _T('\\') ))) + { + CheckDlgButton( hDlg, IDC_GBROM_ABS, BST_CHECKED ); + + GetDirectory( szBuffer, DIRECTORY_GBROMS ); + if( !_tcsncmp( szBuffer, szApplication, i )) + { + TCHAR *pcSub = &szBuffer[i]; + pcSlash = _tcsrchr( pcSub, _T('\\') ); + if( pcSlash && ( pcSlash[1] == '\0' )) *pcSlash = '\0'; + SendMessage( GetDlgItem( hDlg, IDC_GBROM_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + } + else + SendMessage( GetDlgItem( hDlg, IDC_GBROM_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)STRING_DEF_GBROMFILE ); + } + else + { + CheckDlgButton( hDlg, IDC_GBROM_REL, BST_CHECKED ); + + if( szBuffer[0] != 0 ) + SendMessage( GetDlgItem( hDlg, IDC_GBROM_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + else + SendMessage( GetDlgItem( hDlg, IDC_GBROM_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)STRING_DEF_GBROMFILE ); + } + + GetDirectory( szBuffer, DIRECTORY_GBROMS ); + pcSlash = _tcsrchr( szBuffer, _T('\\') ); + if( pcSlash && ( pcSlash[1] == _T('\0') )) *pcSlash = '\0'; + SendMessage( GetDlgItem( hDlg, IDC_GBROM_ABS_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + + + // GBSave Directory + lstrcpyn(szBuffer, g_aszDefFolders[DIRECTORY_GBSAVES], MAX_PATH); + + if( !j ) + { + CheckDlgButton( hDlg, IDC_GBSAVE_SAME, BST_CHECKED ); + FoldersDialogProc( hDlg, WM_COMMAND, (WPARAM)MAKELONG( IDC_GBSAVE_SAME, BN_CLICKED ), (LPARAM)GetDlgItem( hDlg, IDC_GBSAVE_SAME )); + SendMessage( GetDlgItem( hDlg, IDC_GBROM_REL_EDIT ), WM_GETTEXT, sizeof(szBuffer), (LPARAM)szBuffer ); + SendMessage( GetDlgItem( hDlg, IDC_GBSAVE_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + } + else + { + if( szBuffer[0] != 0 && ( szBuffer[1] == _T(':') || ( szBuffer[1] == _T('\\') && szBuffer[0] == _T('\\') ))) + { + CheckDlgButton( hDlg, IDC_GBSAVE_ABS, BST_CHECKED ); + + GetDirectory( szBuffer, DIRECTORY_GBSAVES ); + if( !_tcsncmp( szBuffer, szApplication, i )) + { + TCHAR *pcSub = &szBuffer[i]; + pcSlash = _tcsrchr( pcSub, '\\' ); + if( pcSlash && ( pcSlash[1] == '\0' )) *pcSlash = '\0'; + SendMessage( GetDlgItem( hDlg, IDC_GBSAVE_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + } + else + SendMessage( GetDlgItem( hDlg, IDC_GBSAVE_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)STRING_DEF_GBROMSAVE ); + } + else + { + CheckDlgButton( hDlg, IDC_GBSAVE_REL, BST_CHECKED ); + + if( szBuffer[0] != 0 ) + SendMessage( GetDlgItem( hDlg, IDC_GBSAVE_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + else + SendMessage( GetDlgItem( hDlg, IDC_GBSAVE_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)STRING_DEF_GBROMSAVE ); + } + } + + + GetDirectory( szBuffer, DIRECTORY_GBSAVES ); + pcSlash = _tcsrchr( szBuffer, _T('\\') ); + if( pcSlash && ( pcSlash[1] == _T('\0') )) *pcSlash = '\0'; + SendMessage( GetDlgItem( hDlg, IDC_GBSAVE_ABS_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + + + return FALSE; // don't give it focus + + case WM_COMMAND: + switch( LOWORD(wParam) ) + { + case IDC_GBSAVE_ABS: + case IDC_GBSAVE_REL: + EnableWindow( GetDlgItem( hDlg, IDC_GBSAVE_REL_EDIT ), TRUE ); + EnableWindow( GetDlgItem( hDlg, IDC_GBSAVE_ABS_EDIT ), TRUE ); + EnableWindow( GetDlgItem( hDlg, IDC_GBSAVE_BROWSE_REL ), TRUE ); + EnableWindow( GetDlgItem( hDlg, IDC_GBSAVE_BROWSE_ABS ), TRUE ); + return TRUE; + + case IDC_GBSAVE_SAME: + EnableWindow( GetDlgItem( hDlg, IDC_GBSAVE_REL_EDIT ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDC_GBSAVE_ABS_EDIT ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDC_GBSAVE_BROWSE_REL ), FALSE ); + EnableWindow( GetDlgItem( hDlg, IDC_GBSAVE_BROWSE_ABS ), FALSE ); + return TRUE; + + case IDC_MEMPAK_BROWSE_ABS: + szBuffer[0] = '\0'; + if( BrowseFolders( hDlg, NULL, szBuffer )) + SendMessage( GetDlgItem( hDlg, IDC_MEMPAK_ABS_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + return TRUE; + case IDC_GBROM_BROWSE_ABS: + szBuffer[0] = '\0'; + if( BrowseFolders( hDlg, NULL, szBuffer )) + SendMessage( GetDlgItem( hDlg, IDC_GBROM_ABS_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + return TRUE; + case IDC_GBSAVE_BROWSE_ABS: + szBuffer[0] = '\0'; + if( BrowseFolders( hDlg, NULL, szBuffer )) + SendMessage( GetDlgItem( hDlg, IDC_GBSAVE_ABS_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + return TRUE; + case IDC_MEMPAK_BROWSE_REL: + GetDirectory( szApplication, DIRECTORY_APPLICATION ); + lstrcpyn( szBuffer, szApplication, ARRAYSIZE(szBuffer) ); + if( BrowseFolders( hDlg, NULL, szBuffer )) + { + i = lstrlen( szApplication ); + lstrcpyn( szBuffer, &szBuffer[i], ARRAYSIZE(szBuffer) ); // HACK: The lstrcpyn function has an undefined behavior if source and destination buffers overlap. + SendMessage( GetDlgItem( hDlg, IDC_MEMPAK_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + } + return TRUE; + + case IDC_GBROM_BROWSE_REL: + GetDirectory( szApplication, DIRECTORY_APPLICATION ); + lstrcpyn( szBuffer, szApplication, ARRAYSIZE(szBuffer) ); + if( BrowseFolders( hDlg, NULL, szBuffer )) + { + i = lstrlen( szApplication ); + lstrcpyn( szBuffer, &szBuffer[i], ARRAYSIZE(szBuffer) ); // HACK: The lstrcpyn function has an undefined behavior if source and destination buffers overlap. + SendMessage( GetDlgItem( hDlg, IDC_GBROM_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + } + return TRUE; + + case IDC_GBSAVE_BROWSE_REL: + GetDirectory( szApplication, DIRECTORY_APPLICATION ); + lstrcpyn( szBuffer, szApplication, ARRAYSIZE(szBuffer) ); + if( BrowseFolders( hDlg, NULL, szBuffer )) + { + i = lstrlen( szApplication ); + lstrcpyn( szBuffer, &szBuffer[i], ARRAYSIZE(szBuffer) ); // HACK: The lstrcpyn function has an undefined behavior if source and destination buffers overlap. + SendMessage( GetDlgItem( hDlg, IDC_GBSAVE_REL_EDIT ), WM_SETTEXT, 0, (LPARAM)szBuffer ); + } + return TRUE; + + case IDOK: + if( IsDlgButtonChecked( hDlg, IDC_MEMPAK_ABS ) == BST_CHECKED ) + { + SendMessage( GetDlgItem( hDlg, IDC_MEMPAK_ABS_EDIT ), WM_GETTEXT, ARRAYSIZE(szApplication), (LPARAM)szApplication ); + GetFullPathName( szApplication, ARRAYSIZE(szBuffer), szBuffer, &pcSlash ); + } + else + SendMessage( GetDlgItem( hDlg, IDC_MEMPAK_REL_EDIT ), WM_GETTEXT, ARRAYSIZE(szBuffer), (LPARAM)szBuffer ); + pcSlash = _tcsrchr( szBuffer, '\\' ); + if( pcSlash && ( pcSlash[1] == '\0' )) + *pcSlash = '\0'; + + if( !lstrcmp( szBuffer, STRING_DEF_MEMPAKFILE )) + g_aszDefFolders[DIRECTORY_MEMPAK][0] = 0; + else + lstrcpyn(g_aszDefFolders[DIRECTORY_MEMPAK], szBuffer, MAX_PATH); + + if( IsDlgButtonChecked( hDlg, IDC_GBROM_ABS ) == BST_CHECKED ) + { + SendMessage( GetDlgItem( hDlg, IDC_GBROM_ABS_EDIT ), WM_GETTEXT, ARRAYSIZE(szApplication), (LPARAM)szApplication ); + GetFullPathName( szApplication, ARRAYSIZE(szBuffer), szBuffer, &pcSlash ); + } + else + SendMessage( GetDlgItem( hDlg, IDC_GBROM_REL_EDIT ), WM_GETTEXT, ARRAYSIZE(szBuffer), (LPARAM)szBuffer ); + pcSlash = _tcsrchr( szBuffer, '\\' ); + if( pcSlash && ( pcSlash[1] == '\0' )) *pcSlash = '\0'; + + if( !lstrcmp( szBuffer, STRING_DEF_GBROMFILE )) + g_aszDefFolders[DIRECTORY_GBROMS][0] = 0; + else + lstrcpyn(g_aszDefFolders[DIRECTORY_GBROMS], szBuffer, MAX_PATH); + + if( !IsDlgButtonChecked( hDlg, IDC_GBSAVE_SAME ) == BST_CHECKED ) + { + if( IsDlgButtonChecked( hDlg, IDC_GBSAVE_ABS ) == BST_CHECKED ) + { + SendMessage( GetDlgItem( hDlg, IDC_GBSAVE_ABS_EDIT ), WM_GETTEXT, ARRAYSIZE(szApplication), (LPARAM)szApplication ); + GetFullPathName( szApplication, ARRAYSIZE(szBuffer), szBuffer, &pcSlash ); + } + else + SendMessage( GetDlgItem( hDlg, IDC_GBSAVE_REL_EDIT ), WM_GETTEXT, ARRAYSIZE(szBuffer), (LPARAM)szBuffer ); + } + + pcSlash = _tcsrchr( szBuffer, _T('\\') ); + if( pcSlash && ( pcSlash[1] == '\0' )) *pcSlash = '\0'; + + if( !lstrcmp( szBuffer, STRING_DEF_GBROMSAVE )) + g_aszDefFolders[DIRECTORY_GBSAVES][0] = 0; + else + lstrcpyn(g_aszDefFolders[DIRECTORY_GBSAVES], szBuffer, MAX_PATH); + + EndDialog( hDlg, TRUE ); + return TRUE; + + case IDCANCEL: + EndDialog( hDlg, FALSE ); + return TRUE; + + default: + return FALSE; // unhandled WM_COMMAND + } + default: + return FALSE; //false means the msg didn't got processed + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +// A wonderful n squared algorithm to store the key names in a string... what for??? +// called by EnumObjects in MainDlgProcess to enumerate the keys on the keyboard...? +/* BOOL CALLBACK EnumGetKeyDesc( LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef ) +{ + // REMOVED // +} // I am putting this function out of its misery before it causes more grief. --rabid */ + + +// ButtonID is where we store an array of 3 DWORDs: ID of pushbutton, ID of text window, and an offset in the button-structure controls +// bIndex tells us what information to copy, but in a confusing way +// bButtonSet tells us whether we want the data from the Controls array or the Shortcuts array below +// This function is confusing, but not much I can do to fix it now. I'm sorry. --rabid +bool GetButtonID( LPDWORD ButtonID, const BYTE bIndex, const BYTE bButtonSet ) +{ + // TODO: make these const, read from a resource or a define, or something... I don't know + LPDWORD ButtonTable = NULL; + int nEntries = 0; + + // ID of PushButton ID of TextWindow place in Button-structure + const DWORD Controls[][3] = { { IDC_DRIGHT , IDT_DRIGHT , PF_DPADR }, // Controls + { IDC_DLEFT , IDT_DLEFT , PF_DPADL }, + { IDC_DDOWN , IDT_DDOWN , PF_DPADD }, + { IDC_DUP , IDT_DUP , PF_DPADU }, + { IDC_SBUTTON , IDT_SBUTTON , PF_START }, + { IDC_ZTRIGGER , IDT_ZTRIGGER , PF_TRIGGERZ }, + { IDC_BBUTTON , IDT_BBUTTON , PF_BBUTTON }, + { IDC_ABUTTON , IDT_ABUTTON , PF_ABUTTON }, + { IDC_CRIGHT , IDT_CRIGHT , PF_CBUTTONR }, + { IDC_CLEFT , IDT_CLEFT , PF_CBUTTONL }, + { IDC_CDOWN , IDT_CDOWN , PF_CBUTTOND }, + { IDC_CUP , IDT_CUP , PF_CBUTTONU }, + { IDC_RIGHTTRIGGER , IDT_RIGHTTRIGGER , PF_TRIGGERR }, + { IDC_LEFTTRIGGER , IDT_LEFTTRIGGER , PF_TRIGGERL }, + { IDC_ARIGHT , IDT_ARIGHT , PF_APADR }, + { IDC_ALEFT , IDT_ALEFT , PF_APADL }, + { IDC_ADOWN , IDT_ADOWN , PF_APADD }, + { IDC_AUP , IDT_AUP , PF_APADU } }; + + const DWORD Shortcuts[][3]= { + { IDC_SETNOPAK_P1 , IDC_SETNOPAK_P1 , SC_NOPAK }, + { IDC_SETMEMPAK_P1 , IDC_SETMEMPAK_P1 , SC_MEMPAK }, + { IDC_SETRUMBLEPAK_P1 , IDC_SETRUMBLEPAK_P1 , SC_RUMBPAK }, + { IDC_SETTRANSFERPAK_P1 , IDC_SETTRANSFERPAK_P1 , SC_TRANSPAK }, + { IDC_SETADAPTOIDPAK_P1 , IDC_SETADAPTOIDPAK_P1 , SC_ADAPTPAK }, + { IDC_SWMEMRUMBLE_P1 , IDC_SWMEMRUMBLE_P1 , SC_SWMEMRUMB }, + { IDC_SWMEMADAPTOID_P1 , IDC_SWMEMADAPTOID_P1 , SC_SWMEMADAPT }, + + { IDC_SETNOPAK_P2 , IDC_SETNOPAK_P2 , SC_NOPAK + SC_TOTAL }, + { IDC_SETMEMPAK_P2 , IDC_SETMEMPAK_P2 , SC_MEMPAK + SC_TOTAL }, + { IDC_SETRUMBLEPAK_P2 , IDC_SETRUMBLEPAK_P2 , SC_RUMBPAK + SC_TOTAL }, + { IDC_SETTRANSFERPAK_P2 , IDC_SETTRANSFERPAK_P2 , SC_TRANSPAK + SC_TOTAL }, + { IDC_SETADAPTOIDPAK_P2 , IDC_SETADAPTOIDPAK_P2 , SC_ADAPTPAK + SC_TOTAL }, + { IDC_SWMEMRUMBLE_P2 , IDC_SWMEMRUMBLE_P2 , SC_SWMEMRUMB + SC_TOTAL }, + { IDC_SWMEMADAPTOID_P2 , IDC_SWMEMADAPTOID_P2 , SC_SWMEMADAPT + SC_TOTAL }, + + { IDC_SETNOPAK_P3 , IDC_SETNOPAK_P3 , SC_NOPAK + SC_TOTAL * 2 }, + { IDC_SETMEMPAK_P3 , IDC_SETMEMPAK_P3 , SC_MEMPAK + SC_TOTAL * 2 }, + { IDC_SETRUMBLEPAK_P3 , IDC_SETRUMBLEPAK_P3 , SC_RUMBPAK + SC_TOTAL * 2 }, + { IDC_SETTRANSFERPAK_P3 , IDC_SETTRANSFERPAK_P3 , SC_TRANSPAK + SC_TOTAL * 2 }, + { IDC_SETADAPTOIDPAK_P3 , IDC_SETADAPTOIDPAK_P3 , SC_ADAPTPAK + SC_TOTAL * 2 }, + { IDC_SWMEMRUMBLE_P3 , IDC_SWMEMRUMBLE_P3 , SC_SWMEMRUMB + SC_TOTAL * 2 }, + { IDC_SWMEMADAPTOID_P3 , IDC_SWMEMADAPTOID_P3 , SC_SWMEMADAPT + SC_TOTAL * 2 }, + + { IDC_SETNOPAK_P4 , IDC_SETNOPAK_P4 , SC_NOPAK + SC_TOTAL * 3 }, + { IDC_SETMEMPAK_P4 , IDC_SETMEMPAK_P4 , SC_MEMPAK + SC_TOTAL * 3 }, + { IDC_SETRUMBLEPAK_P4 , IDC_SETRUMBLEPAK_P4 , SC_RUMBPAK + SC_TOTAL * 3 }, + { IDC_SETTRANSFERPAK_P4 , IDC_SETTRANSFERPAK_P4 , SC_TRANSPAK + SC_TOTAL * 3 }, + { IDC_SETADAPTOIDPAK_P4 , IDC_SETADAPTOIDPAK_P4 , SC_ADAPTPAK + SC_TOTAL * 3 }, + { IDC_SWMEMRUMBLE_P4 , IDC_SWMEMRUMBLE_P4 , SC_SWMEMRUMB + SC_TOTAL * 3 }, + { IDC_SWMEMADAPTOID_P4 , IDC_SWMEMADAPTOID_P4 , SC_SWMEMADAPT + SC_TOTAL * 3 }, + + { IDC_LOCKMOUSE , IDC_LOCKMOUSE , (DWORD)(-1) } + }; + + + if( bButtonSet == BSET_CONTROLS ) + { + ButtonTable = (LPDWORD)Controls; // HACK: what an ugly solution, using a cast like that + nEntries = ARRAYSIZE( Controls ); + } + + if( bButtonSet == BSET_SHORTCUTS ) + { + ButtonTable = (LPDWORD)Shortcuts; + nEntries = ARRAYSIZE( Shortcuts ); + } + + bool bReturn = false; + + // TODO: fix this! just use 2 dimensional arrays for crying out loud! + if( ButtonTable != NULL ) + { + nEntries *= 3; + for( int i = 0; i < nEntries; i+=3 ) + { + if( ButtonTable[i+bIndex] == ButtonID[bIndex] ) + { + ButtonID[0] = ButtonTable[i+0]; + ButtonID[1] = ButtonTable[i+1]; + ButtonID[2] = ButtonTable[i+2]; + + bReturn = true; + break; + } + } + } + + return bReturn; +} + +// a text-munging routine to spit out what PC control was assigned to a button +bool GetButtonText( const BUTTON& btnButton, LPTSTR Buffer ) +{ + const UINT iDevice[] ={ IDS_BUTTON_UNASSIGNED, + IDS_C_GAMEPAD, + IDS_C_KEYBOARD, + IDS_C_MOUSE }; + const UINT iGamepad[] ={ IDS_C_XAXIS, + IDS_C_YAXIS, + IDS_C_ZAXIS, + IDS_C_XROT, + IDS_C_YROT, + IDS_C_ZROT, + IDS_C_SLIDER, + IDS_C_SLIDER, + IDS_C_POV, + IDS_C_POV, + IDS_C_POV, + IDS_C_POV, + IDS_C_BUTTON }; + const UINT iMouse[] = { IDS_C_XAXIS, + IDS_C_YAXIS, + IDS_C_WHEEL, + IDS_C_BUTTON }; + const LPTSTR AxeID[] = { TEXT( " +" ), + TEXT( " -" ), + TEXT( " /\\" ), + TEXT( " >" ), + TEXT( " \\/" ), + TEXT( " <" ) }; + TCHAR a[16], b[16], buff[16]; // gotta allocate the space, stack is easier than P_malloc + TCHAR Btn[6]; + LPTSTR Text[] = {a, b, NULL }; + bool bReturn = true; + DIDEVICEOBJECTINSTANCE didoi; + didoi.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); + + switch ( btnButton.bBtnType ) + { + case DT_JOYBUTTON: + LoadString( g_hResourceDLL, iDevice[1], Text[0], 16 ); + LoadString( g_hResourceDLL, iGamepad[12], Text[1], 16 ); + Text[2] = Btn; + wsprintf( Btn, TEXT( "%02u" ), btnButton.bOffset ); + break; + case DT_JOYAXE: + LoadString( g_hResourceDLL, iDevice[1], Text[0], 16 ); + LoadString( g_hResourceDLL, iGamepad[btnButton.bOffset], Text[1], 16 ); + Text[2] = AxeID[btnButton.bAxisID]; + break; + case DT_JOYSLIDER: + LoadString( g_hResourceDLL, iDevice[1], Text[0], 16 ); + LoadString( g_hResourceDLL, iGamepad[btnButton.bOffset], buff, 16 ); + wsprintf(Text[1], buff, btnButton.bOffset - 5 ); + Text[2] = AxeID[btnButton.bAxisID]; + case DT_JOYPOV: + LoadString( g_hResourceDLL, iDevice[1], Text[0], 16 ); + LoadString( g_hResourceDLL, iGamepad[btnButton.bOffset], buff, 16 ); + wsprintf(Text[1], buff, btnButton.bOffset - 7 ); + Text[2] = AxeID[2 + btnButton.bAxisID]; + break; + + case DT_KEYBUTTON: + LoadString( g_hResourceDLL, iDevice[2], Text[0], 16 ); + //TODO: this is great! can we do this for all of them? + if (btnButton.parentDevice->didHandle->GetObjectInfo(&didoi, btnButton.bOffset, DIPH_BYOFFSET) == DI_OK) + Text[1] = didoi.tszName; + else + LoadString( g_hResourceDLL, IDS_C_UNKNOWN, Text[1], 16 ); + Text[2] = TEXT( "" ); + break; + + case DT_MOUSEBUTTON: + LoadString( g_hResourceDLL, iDevice[3], Text[0], 16 ); + LoadString( g_hResourceDLL, iMouse[3], Text[1], 16 ); + Text[2] = Btn; + wsprintf( Btn, TEXT( "%02u" ), btnButton.bOffset ); + break; + + case DT_MOUSEAXE: + LoadString( g_hResourceDLL, iDevice[3], Text[0], 16 ); + LoadString( g_hResourceDLL, iMouse[btnButton.bOffset], Text[1], 16 ); + Text[2] = AxeID[btnButton.bAxisID]; + break; + + case DT_UNASSIGNED: + default: + LoadString( g_hResourceDLL, iDevice[0], Text[0], 16 ); + Text[1] = Text[2] = TEXT( "" ); + bReturn = false; + } + + wsprintf( Buffer, TEXT( "%s%s%s" ), Text[0], Text[1], Text[2] ); + return ( bReturn ); +} + +// called when scanning devices to assign N64 buttons +DWORD ScanKeyboard( LPDEVICE lpDevice, LPDWORD lpdwCounter, LPBUTTON pButton ) +{ + HRESULT hr; + BYTE cKeys[256]; + + hr = lpDevice->didHandle->GetDeviceState( sizeof( cKeys ), (LPVOID)&cKeys ); + if ( FAILED(hr) ) + { + lpDevice->didHandle->Acquire(); + return FALSE; + } + + int iGotKey = FALSE; + int i = 0; + + for( i = 0; i < ARRAYSIZE( cKeys ); ++i ) + { + if (( cKeys[i] & 0x80 ) ) + { + if( i == DIK_ESCAPE ) + iGotKey = SC_SCANESCAPE; + else + { + iGotKey = SC_SCANSUCCEED; + pButton->bBtnType = (BYTE)DT_KEYBUTTON; + pButton->bAxisID = (BYTE)0; + pButton->bOffset = (BYTE)i; + pButton->parentDevice = lpDevice; + } + } + } + return iGotKey; +} + +// called when scanning devices to assign N64 buttons +DWORD ScanMouse( LPDEVICE lpDevice, LPDWORD lpdwCounter, LPBUTTON pButton ) +{ + static BYTE rgbInitButtons[8]; + static bool bFirstScan = true; + DIMOUSESTATE2 dm_Current; + HRESULT hr; + + if ( *lpdwCounter == 0 ) + bFirstScan = true; + + hr = lpDevice->didHandle->GetDeviceState( sizeof(DIMOUSESTATE2), &dm_Current ); + if ( FAILED(hr) ) + { + lpDevice->didHandle->Acquire(); + return FALSE; + } + + + if ( bFirstScan ) + { + CopyMemory( rgbInitButtons, dm_Current.rgbButtons, sizeof(rgbInitButtons)); + bFirstScan = false; + lpDevice->didHandle->GetDeviceState( sizeof(DIMOUSESTATE2), &dm_Current ); + } + + int iGotKey = FALSE; + int i = 0; + BYTE bAxeDirection = 0; + long Mouse[] ={ FIELD_OFFSET( DIMOUSESTATE2, lX ) / sizeof(long), + FIELD_OFFSET( DIMOUSESTATE2, lY ) / sizeof(long), + FIELD_OFFSET( DIMOUSESTATE2, lZ ) / sizeof(long) }; + + long lValue; + + for( i = 0; i < ARRAYSIZE(Mouse); ++i ) + { + lValue = ((long*)&dm_Current)[Mouse[i]]; + + if( lValue > MOUSE_THRESHOLD ) + { + iGotKey = SC_SCANSUCCEED; + bAxeDirection = AI_AXE_P; + } + if( lValue < -MOUSE_THRESHOLD ) + { + iGotKey = SC_SCANSUCCEED; + bAxeDirection = AI_AXE_N; + } + if( iGotKey ) + break; + } + + if( iGotKey == SC_SCANSUCCEED ) + { + pButton->bBtnType = (BYTE)DT_MOUSEAXE; + pButton->bAxisID = (BYTE)bAxeDirection; + pButton->bOffset = (BYTE)Mouse[i]; + pButton->parentDevice = lpDevice; + } + else + { + for( i = 0; i < ARRAYSIZE( dm_Current.rgbButtons ); ++i ) + { + if(( dm_Current.rgbButtons[i] != rgbInitButtons[i] ) && ( dm_Current.rgbButtons[i] & 0x80 )) + { + iGotKey = SC_SCANSUCCEED; + pButton->bBtnType = (BYTE)DT_MOUSEBUTTON; + pButton->bAxisID = (BYTE)0; + pButton->bOffset = (BYTE)i; + pButton->parentDevice = lpDevice; + break; + } + } + } + CopyMemory( rgbInitButtons, dm_Current.rgbButtons, sizeof(rgbInitButtons)); + + return iGotKey; +} + +// called when scanning devices to assign N64 buttons +// tries to read any possible button presses or axes from lpDirectInputDevice; called by ScanDevices +DWORD ScanGamePad ( LPDEVICE lpDevice, LPDWORD lpdwCounter, LPBUTTON pButton, int iDeviceNumber ) +{ + static DIJOYSTATE dj_Initial[MAX_DEVICES]; + static bool bFirstScan = true; + HRESULT hr; + + if ( *lpdwCounter == 0 ) + bFirstScan = true; + + hr = lpDevice->didHandle->GetDeviceState( sizeof(DIJOYSTATE), &lpDevice->stateAs.joyState ); + if ( FAILED(hr) ) + { + hr = lpDevice->didHandle->Acquire(); + return FALSE; + } + + if ( bFirstScan ) + { + dj_Initial[iDeviceNumber] = lpDevice->stateAs.joyState; + bFirstScan = false; + return FALSE; // initial scan done; gotta wait until next time + } + + long lAxePos = ZEROVALUE + ( RANGERELATIVE * CONFIGTHRESHOLD / 100 ); + long lAxeNeg = ZEROVALUE - ( RANGERELATIVE * CONFIGTHRESHOLD / 100 ); + long lValue; + + int iGotKey = FALSE; + BYTE bAxeDirection = 0; + + int JoyPad[][2] ={ { FIELD_OFFSET( DIJOYSTATE, lX ) / sizeof(long) , DT_JOYAXE }, + { FIELD_OFFSET( DIJOYSTATE, lY ) / sizeof(long) , DT_JOYAXE }, + { FIELD_OFFSET( DIJOYSTATE, lZ ) / sizeof(long) , DT_JOYAXE }, + { FIELD_OFFSET( DIJOYSTATE, lRx ) / sizeof(long) , DT_JOYAXE }, + { FIELD_OFFSET( DIJOYSTATE, lRy ) / sizeof(long) , DT_JOYAXE }, + { FIELD_OFFSET( DIJOYSTATE, lRz ) / sizeof(long) , DT_JOYAXE }, + { FIELD_OFFSET( DIJOYSTATE, rglSlider[0] ) / sizeof(long) , DT_JOYSLIDER }, + { FIELD_OFFSET( DIJOYSTATE, rglSlider[1] ) / sizeof(long) , DT_JOYSLIDER }, + { FIELD_OFFSET( DIJOYSTATE, rgdwPOV[0] ) / sizeof(long) , DT_JOYPOV }, + { FIELD_OFFSET( DIJOYSTATE, rgdwPOV[1] ) / sizeof(long) , DT_JOYPOV }, + { FIELD_OFFSET( DIJOYSTATE, rgdwPOV[2] ) / sizeof(long) , DT_JOYPOV }, + { FIELD_OFFSET( DIJOYSTATE, rgdwPOV[3] ) / sizeof(long) , DT_JOYPOV } }; + + int i; + + for( i = 0; i < ARRAYSIZE( JoyPad ); ++i ) + { + lValue = ((long*)&lpDevice->stateAs.joyState)[JoyPad[i][0]]; + if( lValue != ((long*)&(dj_Initial[iDeviceNumber]))[JoyPad[i][0]] ) + { + if(( JoyPad[i][1] == DT_JOYAXE ) || ( JoyPad[i][1] == DT_JOYSLIDER )) + { + if( lValue - ((long*)&(dj_Initial[iDeviceNumber]))[JoyPad[i][0]] > lAxePos ) + { + iGotKey = SC_SCANSUCCEED; + bAxeDirection = AI_AXE_P; + break; + } + else if( lValue - ((long*)&(dj_Initial[iDeviceNumber]))[JoyPad[i][0]] < lAxeNeg ) + { + iGotKey = SC_SCANSUCCEED; + bAxeDirection = AI_AXE_N; + break; + } + } + if( JoyPad[i][1] == DT_JOYPOV && LOWORD( lValue ) != 0xFFFF ) + { + iGotKey = SC_SCANSUCCEED; + if (( lValue > 31500 ) || ( lValue < 4500 )) + bAxeDirection = AI_POV_UP; + if (( lValue > 4500 ) && ( lValue < 13500 )) + bAxeDirection = AI_POV_RIGHT; + if (( lValue > 13500 ) && ( lValue < 22500 )) + bAxeDirection = AI_POV_DOWN; + if (( lValue > 22500 ) && ( lValue < 31500 )) + bAxeDirection = AI_POV_LEFT; + break; + } + } + } + + if( iGotKey == SC_SCANSUCCEED ) + { + pButton->bBtnType = (BYTE)JoyPad[i][1]; + pButton->bAxisID = (BYTE)bAxeDirection; + pButton->bOffset = (BYTE)JoyPad[i][0]; + pButton->parentDevice = lpDevice; + } + else + { + for( i = 0; i < ARRAYSIZE( lpDevice->stateAs.joyState.rgbButtons ); ++i ) + { + if (( lpDevice->stateAs.joyState.rgbButtons[i] & 0x80 )) + { + iGotKey = SC_SCANSUCCEED; + pButton->bBtnType = (BYTE)DT_JOYBUTTON; + pButton->bAxisID = (BYTE)0; + pButton->bOffset = (BYTE)i; + pButton->parentDevice = lpDevice; + break; + } + } + } + + return iGotKey; +} + +// called when we assign a control to an N64 button +// returns FALSE if no keyscans recorded, SC_SCANESCAPE if escape pressed on keyboard (to abort), or SC_SUCCEED for a good read +// *apDirectInputDevices is an array of only 2 devices; sys keyboard, sys mouse +DWORD ScanDevices( LPDWORD lpdwCounter, LPBUTTON pButton ) +{ + // Do ALL our polling first-- this ensures consistency (i.e. every device always gets polled at same interval) +/* if( g_sysKeyboard.didHandle ) + { + if( FAILED(g_sysKeyboard.didHandle->Poll())) + g_sysKeyboard.didHandle->Acquire(); + } */ + if( g_sysMouse.didHandle ) + { + if( FAILED(g_sysMouse.didHandle->Poll())) + g_sysMouse.didHandle->Acquire(); + } + for (int i = 0; i < g_nDevices; i++) + if (g_devList[i].didHandle) + if (FAILED(g_devList[i].didHandle->Poll())) + g_devList[i].didHandle->Acquire(); + + // While we have devices to scan, + // if it's a keyboard, ScanKeyboard; if it's a mouse, ScanMouse; + // otherwise ScanGamePad. + + DWORD dwReturn = FALSE; + +// if( !dwReturn && g_sysKeyboard.didHandle ) +// dwReturn = ScanKeyboard( &g_sysKeyboard, lpdwCounter, pButton ); + + if( !dwReturn && g_sysMouse.didHandle ) + dwReturn = ScanMouse( &g_sysMouse, lpdwCounter, pButton ); + + // ScanGamePad on ALL remaining devices + for (int i = 0; !dwReturn && i < g_nDevices; i++) + if (g_devList[i].didHandle) + { + switch (LOBYTE(g_devList[i].dwDevType)) + { + case DI8DEVTYPE_KEYBOARD: + dwReturn = ScanKeyboard( &g_devList[i], lpdwCounter, pButton ); + break; + case DI8DEVTYPE_MOUSE: + dwReturn = ScanMouse( &g_devList[i], lpdwCounter, pButton ); + break; + default: + dwReturn = ScanGamePad( &g_devList[i], lpdwCounter, pButton, i ); + } + } + + return dwReturn; +} + +// sets controller defaults; called when user clicks on "Clear Controller" or "Default Config" +// also called before loading stuff from the INI or from profile files, in case something isn't defined +// DEFAULTS TO NOT PLUGGED. Make sure you "plug" the first controller manually. +void SetControllerDefaults( LPCONTROLLER pcController ) +{ + freePakData( pcController ); + freeModifiers( pcController ); + ZeroMemory( pcController, sizeof(CONTROLLER) ); + + pcController->fRawData = true; + pcController->fRealN64Range = true; + pcController->bRapidFireEnabled = false; + pcController->bRapidFireRate = 3; // Set default rapid fire rate here + pcController->bStickRange = DEFAULT_STICKRANGE; + pcController->bPadDeadZone = DEFAULT_DEADZONE; + pcController->bRumbleTyp = DEFAULT_RUMBLETYP; + pcController->bRumbleStrength = DEFAULT_RUMBLESTRENGTH; + pcController->wMouseSensitivityX = DEFAULT_MOUSESENSIVITY; + pcController->wMouseSensitivityY = DEFAULT_MOUSESENSIVITY; + pcController->PakType = DEFAULT_PAKTYPE; + pcController->bMouseMoveX = DEFAULT_MOUSEMOVE; + pcController->bMouseMoveY = DEFAULT_MOUSEMOVE; +} + +void DeleteControllerSettings( int indexController ) +{ + if( !g_ivConfig ) + return; + + SetControllerDefaults( &g_ivConfig->Controllers[indexController] ); + g_ivConfig->FFDevices[indexController].bProductCounter = 0; + g_ivConfig->FFDevices[indexController].szProductName[0] = _T('\0'); + + return; +} + +// SetModifier activates certain "always on" Config modifiers after they've been inserted or loaded +void SetModifier( LPCONTROLLER pcController ) +{ + for( int i = 0; i < pcController->nModifiers; i++ ) + { + if( pcController->pModifiers[i].bModType == MDT_CONFIG && pcController->pModifiers[i].fStatus ) + { + MODSPEC_CONFIG args; + args.dwValue = pcController->pModifiers[i].dwSpecific; + if( args.fChangeAnalogConfig ) + { + BYTE bConfig = (BYTE)args.fAnalogStickMode; + if( bConfig < PF_AXESETS ) + pcController->bAxisSet = bConfig; + else + { + if( pcController->bAxisSet == PF_AXESETS-1 ) + pcController->bAxisSet = 0; + else + ++pcController->bAxisSet; + } + } + if( args.fChangeMouseXAxis ) + if (pcController->bMouseMoveX == MM_BUFF) + pcController->bMouseMoveX = MM_ABS; + else if (pcController->bMouseMoveX == MM_ABS) + pcController->bMouseMoveX = MM_BUFF; + if( args.fChangeMouseYAxis ) + if (pcController->bMouseMoveY == MM_BUFF) + pcController->bMouseMoveY = MM_ABS; + else if (pcController->bMouseMoveY == MM_ABS) + pcController->bMouseMoveY = MM_BUFF; + + if( args.fChangeKeyboardXAxis ) + pcController->fKeyAbsoluteX = !pcController->fKeyAbsoluteX; + if( args.fChangeKeyboardYAxis ) + pcController->fKeyAbsoluteY = !pcController->fKeyAbsoluteY; + } + } +} + +// Copies over the existing g_pcControllers' idea of configuration over to the interface. +void GetCurrentConfiguration() +{ + EnterCriticalSection( &g_critical ); + + g_ivConfig->Language = g_strEmuInfo.Language; + g_ivConfig->fDisplayShortPop = g_strEmuInfo.fDisplayShortPop; + + LPCONTROLLER pcController; + for( int i = 0; i < 4; i++ ) + { + pcController = &g_ivConfig->Controllers[i]; + CopyMemory( pcController, &g_pcControllers[i], sizeof(CONTROLLER)); + + if( pcController->nModifiers > 0 ) + { + pcController->pModifiers = (LPMODIFIER)P_malloc( sizeof(MODIFIER) * pcController->nModifiers ); + CopyMemory( pcController->pModifiers, g_pcControllers[i].pModifiers, sizeof(MODIFIER) * pcController->nModifiers ); + SetModifier( pcController ); + } + else + pcController->pModifiers = NULL; + + pcController->pPakData = NULL; + + for( int iDevice = 0; iDevice < ARRAYSIZE(g_devList) && g_devList[iDevice].dwDevType; ++iDevice ) + { + if( g_devList[iDevice].guidInstance == pcController->guidFFDevice ) + { + g_ivConfig->FFDevices[i].bProductCounter = g_devList[iDevice].bProductCounter; + lstrcpyn( g_ivConfig->FFDevices[i].szProductName, g_devList[iDevice].szProductName, MAX_PATH ); + break; + } + } + } + + LeaveCriticalSection( &g_critical ); + return; +} + +// Copies over the interface's idea of configuration over to g_pcControllers. +void UpdateControllerStructures() +{ + // bDebug = g_ivConfig->bAutoConfig; + EnterCriticalSection( &g_critical ); + + g_iFirstController = -1; + +#ifdef _UNICODE + // might as well use this time to copy over language info and open the new DLL as well... --rabid + g_strEmuInfo.Language = g_ivConfig->Language; + if (g_hResourceDLL != g_strEmuInfo.hinst) + FreeLibrary(g_hResourceDLL); + g_hResourceDLL = LoadLanguageDLL(g_strEmuInfo.Language); + if( g_hResourceDLL == NULL ) + { + g_strEmuInfo.Language = 0; + g_hResourceDLL = g_strEmuInfo.hinst; + DebugWriteA("couldn't load language DLL, falling back to defaults\n"); + } +#endif // #ifdef _UNICODE + + g_strEmuInfo.fDisplayShortPop = g_ivConfig->fDisplayShortPop; + + LPCONTROLLER pcController; + for( int i = 3; i >= 0; i-- ) + { + pcController = &g_ivConfig->Controllers[i]; + + SaveControllerPak( i ); + CloseControllerPak( i ); +// freePakData( &g_pcControllers[i] ); // called already by CloseControllerPak + freeModifiers( &g_pcControllers[i] ); + + CopyMemory( &g_pcControllers[i], pcController, sizeof(CONTROLLER)); + g_pcControllers[i].pPakData = NULL; + g_pcControllers[i].pModifiers = NULL; + + if( g_pcControllers[i].nModifiers > 0 ) + { + g_pcControllers[i].pModifiers = (LPMODIFIER)P_malloc( sizeof(MODIFIER) * g_pcControllers[i].nModifiers ); + CopyMemory( g_pcControllers[i].pModifiers, pcController->pModifiers, sizeof(MODIFIER) * g_pcControllers[i].nModifiers ); + SetModifier( &g_pcControllers[i] ); + } + + + int iDevice = FindDeviceinList( g_ivConfig->FFDevices[i].szProductName, g_ivConfig->FFDevices[i].bProductCounter, true ); + if( iDevice != -1 && g_devList[iDevice].bEffType ) + { + g_pcControllers[i].guidFFDevice = g_devList[iDevice].guidInstance; + } + else + { + g_pcControllers[i].guidFFDevice = GUID_NULL; + } + + + g_pcControllers[i].fPakCRCError = false; + g_pcControllers[i].fPakInitialized = false; + + if (g_pcControllers[i].fPlugged) + g_iFirstController = i; + } + LeaveCriticalSection( &g_critical ); + return; +} + +LRESULT CALLBACK BlockerProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; + + switch (msg) { + case WM_CREATE: + return 0; + case WM_PAINT: + BeginPaint(hwnd, &ps); + EndPaint(hwnd, &ps); + return 0; + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } +// return 0; +} + +BOOL InitOverlay(void) +{ + // registers our overlay class + + WNDCLASS wc; + + // Fill in the window class structure with parameters + // that describe the main window. + + wc.style = 0; + wc.lpfnWndProc = BlockerProc; // window procedure + wc.cbClsExtra = 0; // no extra class memory + wc.cbWndExtra = 0; // no extra window memory + wc.hInstance = g_strEmuInfo.hinst; + wc.hIcon = 0; + wc.hCursor = NULL; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = _T("BlockerClass"); // name of window class + + // Register the window class. + + return RegisterClass(&wc); +} + +HWND MakeOverlay() +{ + HWND hwnd; + + RECT size; + + GetWindowRect(g_hMainDialog, &size); + + // Create the main window. + + hwnd = CreateWindowEx( + WS_EX_TOPMOST | WS_EX_TRANSPARENT, + _T("BlockerClass"), + _T("Blocker"), + WS_POPUP, + size.left, // horizontal position + size.top, // vertical position + size.right - size.left, // width + size.bottom - size.top, // height + g_hMainDialog, // owner window + (HMENU) NULL, // menu + g_strEmuInfo.hinst, // handle to application instance + (LPVOID) NULL); // window-creation data + + if (!hwnd) + return NULL; + + // Show the window (necessary to block input) + ShowWindow(hwnd, SW_SHOWNOACTIVATE); + return hwnd; +} diff --git a/Source/nragev20/Interface.h b/Source/nragev20/Interface.h new file mode 100644 index 000000000..67587db97 --- /dev/null +++ b/Source/nragev20/Interface.h @@ -0,0 +1,93 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _NRINTERFACE_ +#define _NRINTERFACE_ + +BOOL CALLBACK MainDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); +void SetModifier( CONTROLLER *pcController ); +void SetControllerDefaults( CONTROLLER *pcController ); + + // application internal message +#define WM_USER_UPDATE WM_USER + 1 + // application internal message +#define WM_USER_READVALUES WM_USER + 2 + +#define CONFIGTHRESHOLD 50 +#define MOUSE_THRESHOLD 10 + +#define SC_SCANSUCCEED 0x01 +#define SC_SCANESCAPE 0x10 + +#define TIMER_BUTTON 1 + +#define INTERVAL_BUTTON 20 +#define INTERVAL_RUMBLETEST 20 + +#define MPAK_FORMATABLE 0x01 +#define MPAK_READABLE 0x02 +#define MPAK_WRITEABLE 0x04 + +#define MPAK_OK 0x07 +#define MPAK_INUSE 0x12 +#define MPAK_WRONGSIZE 0x27 +#define MPAK_DAMAGED 0x71 +#define MPAK_ERROR 0x81 +#define MPAK_NOSELECTION 0xF0 + + +#define BSET_CONTROLS 1 +#define BSET_SHORTCUTS 2 + + +typedef struct _IFDEVICE +{ + TCHAR szProductName[MAX_PATH+1]; + BYTE bProductCounter; +} IFDEVICE, *LPIFDEVICE; + +typedef struct _INTERFACEVALUES +{ + BYTE ChosenTab; + CONTROLLER Controllers[4]; + IFDEVICE FFDevices[4]; + SHORTCUTS Shortcuts; + LANGID Language; + bool fDisplayShortPop; +} INTERFACEVALUES, *LPINTERFACEVALUES; + +#define TAB_CONTROLLER1 0 +#define TAB_CONTROLLER2 1 +#define TAB_CONTROLLER3 2 +#define TAB_CONTROLLER4 3 +#define TAB_SHORTCUTS 4 +#define TAB_FOLDERS 5 + +#define TAB_CONTROLS 0 +#define TAB_DEVICES 1 +#define TAB_MODIFIERS 2 +#define TAB_PAK 3 + +extern INTERFACEVALUES *g_ivConfig; + +#endif // _NRINTERFACE_ diff --git a/Source/nragev20/International.cpp b/Source/nragev20/International.cpp new file mode 100644 index 000000000..846f08922 --- /dev/null +++ b/Source/nragev20/International.cpp @@ -0,0 +1,192 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +// Internationalization routines go in this file. + +#include "International.h" +#include +#include +#include +#include +#include "debug.h" + +LANGID GetNTDLLNativeLangID(); +BOOL IsHongKongVersion(); +BOOL CALLBACK EnumLangProc(HANDLE hModule, LPCTSTR lpszType, LPCTSTR lpszName, WORD wIDLanguage, LONG_PTR lParam); + +// The following routines are ripped straight from the SatDLL sample project on the Visual Studio .NET CDs. +// Props to the MS coders for making this solid piece of work. --rabid +// "If it ain't broke, don't fix it." + +// Loads the satellite DLL specified for the language DesiredLanguage +HMODULE LoadLanguageDLL(LANGID DesiredLanguage) +{ + TCHAR SatellitePath[MAX_PATH]; + HMODULE hDLL; + + // First try to load the library with the fully specified language + _stprintf(SatellitePath, _T("NRage-Language-%u.dll"), DesiredLanguage); + hDLL = LoadLibraryEx(SatellitePath, 0, 0); + if( hDLL ) + return hDLL; + else { // try the primary language ID + DesiredLanguage = PRIMARYLANGID(DesiredLanguage); + _stprintf(SatellitePath, _T("NRage-Language-%u.dll"), DesiredLanguage); + hDLL = LoadLibraryEx(SatellitePath, 0, 0); + if( hDLL ) + return hDLL; + else + { + DebugWrite(_T("Couldn't load library: %s\n"), SatellitePath); + return NULL; + } + } +} + +// The following functions contain code to +// detect the language in which the initial +// user interface should be displayed + +BOOL CALLBACK EnumLangProc(HANDLE hModule, LPCTSTR lpszType, LPCTSTR lpszName, + WORD wIDLanguage, LONG_PTR lParam) +{ + PLANGINFO LangInfo; + + LangInfo = (PLANGINFO) lParam; + LangInfo->Count++; + LangInfo->LangID = wIDLanguage; + + return (TRUE); // continue enumeration +} + +// Detects the language of ntdll.dll with some specific processing for +// the Hongkong SAR version +LANGID GetNTDLLNativeLangID() +{ + + LANGINFO LangInfo; + LPCTSTR Type = (LPCTSTR) ((LPVOID)((WORD)16)); + LPCTSTR Name = (LPCTSTR) 1; + + ZeroMemory(&LangInfo,sizeof(LangInfo)); + + // Get the HModule for ntdll. + HMODULE hMod = GetModuleHandle(_T("ntdll.dll")); + if (hMod==NULL) { + return(0); + } + + BOOL result = EnumResourceLanguages(hMod, Type, Name, (ENUMRESLANGPROC)EnumLangProc, (LONG_PTR) &LangInfo); + + if (!result || (LangInfo.Count > 2) || (LangInfo.Count < 1) ) { + return (0); + } + + return (LangInfo.LangID); +} + +// Checks if NT4 system is Hongkong SAR version +BOOL IsHongKongVersion() +{ + HMODULE hMod; + BOOL bRet=FALSE; + typedef BOOL (WINAPI *IMMRELEASECONTEXT)(HWND,HIMC); + IMMRELEASECONTEXT pImmReleaseContext; + + hMod = LoadLibrary(_T("imm32.dll")); + if (hMod) { + pImmReleaseContext = (IMMRELEASECONTEXT)GetProcAddress(hMod,"ImmReleaseContext"); + if (pImmReleaseContext) { + bRet = pImmReleaseContext(NULL,0); + } + FreeLibrary(hMod); + } + return (bRet); +} + +// This function detects a correct initial UI language for all +// platforms (Win9x, ME, NT4, Windows 2000, Windows XP) +LANGID DetectLanguage() +{ + +#define MAX_KEY_BUFFER 80 + + OSVERSIONINFO VersionInfo; + LANGID uiLangID = 0; + HKEY hKey; + DWORD Type, BuffLen = MAX_KEY_BUFFER; + TCHAR LangKeyValue[MAX_KEY_BUFFER]; + + + VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if( !GetVersionEx(&VersionInfo) ) + return(0); + + switch( VersionInfo.dwPlatformId ) { + // On Windows NT, Windows 2000 or higher + case VER_PLATFORM_WIN32_NT: + if( VersionInfo.dwMajorVersion >= 5) // Windows 2000 or higher + { + // we need to dynamically link the GetUserDefaultUILanguage func + HMODULE hmKernDLL = LoadLibrary(_T("kernel32.dll")); + if (hmKernDLL) + { + LANGID (*fpGetLang)() = NULL; + fpGetLang = (LANGID(*)(void))GetProcAddress(hmKernDLL, "GetUserDefaultUILanguage"); + uiLangID = fpGetLang(); + } // and if we couldn't load kernel32.dll, just fall back to default language + } + else { // for NT4 check the language of ntdll.dll + uiLangID = GetNTDLLNativeLangID(); + if (uiLangID == 1033) { // special processing for Honkong SAR version of NT4 + if (IsHongKongVersion()) { + uiLangID = 3076; + } + } + } + break; + // On Windows 95, Windows 98 or Windows ME + case VER_PLATFORM_WIN32_WINDOWS: + // Open the registry key for the UI language + if( RegOpenKeyEx(HKEY_CURRENT_USER,_T("Default\\Control Panel\\Desktop\\ResourceLocale"), 0, + KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS ) { + // Get the type of the default key + if( RegQueryValueEx(hKey, NULL, NULL, &Type, NULL, NULL) == ERROR_SUCCESS + && Type == REG_SZ ) { + // Read the key value + if( RegQueryValueEx(hKey, NULL, NULL, &Type, (LPBYTE)LangKeyValue, &BuffLen) + == ERROR_SUCCESS ) { + uiLangID = _ttoi(LangKeyValue); + } + } + RegCloseKey(hKey); + } + break; + } + + if (uiLangID == 0) { + uiLangID = GetUserDefaultLangID(); + } + // Return the found language ID. + return (uiLangID); +} diff --git a/Source/nragev20/International.h b/Source/nragev20/International.h new file mode 100644 index 000000000..0349c979b --- /dev/null +++ b/Source/nragev20/International.h @@ -0,0 +1,42 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "settings.h" +#include + +#ifndef _NRINTERNATIONAL_ +#define _NRINTERNATIONAL_ + +typedef struct LANGINFO_DEF { + int Count; + LANGID LangID; +} LANGINFO; +typedef LANGINFO *PLANGINFO; + +// only export these functions if UNICODE support is enabled +#ifdef _UNICODE +LANGID DetectLanguage(); +HMODULE LoadLanguageDLL(LANGID DesiredLanguage); +#endif // #ifdef _UNICODE + +#endif // #ifndef _NRINTERNATIONAL_ diff --git a/Source/nragev20/LICENSE b/Source/nragev20/LICENSE new file mode 100644 index 000000000..5b6e7c66c --- /dev/null +++ b/Source/nragev20/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Source/nragev20/NRagePluginV2.cpp b/Source/nragev20/NRagePluginV2.cpp new file mode 100644 index 000000000..81a0aac22 --- /dev/null +++ b/Source/nragev20/NRagePluginV2.cpp @@ -0,0 +1,1280 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "commonIncludes.h" +#include +#include +#include +#include +#include "NRagePluginV2.h" +#include "Interface.h" +#include "FileAccess.h" +#include "PakIO.h" +#include "DirectInput.h" +#include "International.h" + +// ProtoTypes // +bool prepareHeap(); +void FillControls(CONTROL Controls[]); +void InitiatePaks( bool bInitialize ); +void DoShortcut( int iPlayer, int iShortcut ); +DWORD WINAPI MsgThreadFunction( LPVOID lpParam ); +DWORD WINAPI DelayedShortcut(LPVOID lpParam); + +// Global Variables // +HMODULE g_hDirectInputDLL = NULL; // Handle to DirectInput8 library +HMODULE g_hResourceDLL = NULL; // Handle to resource library; used by LoadString for internationalization +HANDLE g_hHeap = NULL; // Handle to our heap +int g_nDevices = 0; // number of devices in g_devList +DEVICE g_devList[MAX_DEVICES]; // list of attached input devices, except SysMouse + // note: we never purge the list of devices during normal operation +DEVICE g_sysMouse; // we need to treat the sysmouse differently, as we may use "locking"; changed from g_apInputDevice[1] --rabid + +EMULATOR_INFO g_strEmuInfo; // emulator info? Stores stuff like our hWnd handle and whether the plugin is initialized yet +TCHAR g_aszDefFolders[3][MAX_PATH]; // default folders: DIRECTORY_MEMPAK, DIRECTORY_GBROMS, DIRECTORY_GBSAVES +TCHAR g_aszLastBrowse[6][MAX_PATH]; // last browsed folders: BF_MEMPAK, BF_GBROM, BF_GBSAVE, BF_PROFILE, BF_NOTE, BF_SHORTCUTS + +CRITICAL_SECTION g_critical; // our critical section semaphore +int g_iFirstController = -1; // The first controller which is plugged in + // Normally controllers are scanned all at once in sequence, 1-4. We only want to scan devices once per pass; + // this is so we get consistent sample rates on our mouse. + +bool g_bRunning = false; // Is the emulator running (i.e. have we opened a ROM)? +bool g_bConfiguring = false; // Are we currently in a config menu? +bool g_bExclusiveMouse = true; // Do we have an exclusive mouse lock? defaults to true unless we have no bound mouse buttons/axes +CONTROLLER g_pcControllers[4]; // Our four N64 controllers, connected or otherwise +SHORTCUTS g_scShortcuts; +LPDIRECTINPUTDEVICE8 g_apFFDevice[4] = { NULL, NULL, NULL, NULL }; // added by rabid +LPDIRECTINPUTEFFECT g_apdiEffect[4] = { NULL, NULL, NULL, NULL }; // array of handles for FF-Effects, one for each controller +TCHAR g_pszThreadMessage[DEFAULT_BUFFER] = _T(""); + +BOOL APIENTRY DllMain( HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) +{ + switch ( ul_reason_for_call ) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls( hModule ); + if( !prepareHeap()) + return FALSE; + DebugWriteA("*** DLL Attach (" VERSIONNUMBER "-Debugbuild | built on " __DATE__ " at " __TIME__")\n"); + ZeroMemory( &g_strEmuInfo, sizeof(g_strEmuInfo) ); + ZeroMemory( g_devList, sizeof(g_devList) ); + ZeroMemory( &g_sysMouse, sizeof(g_sysMouse) ); + ZeroMemory( g_aszDefFolders, sizeof(g_aszDefFolders) ); + ZeroMemory( g_aszLastBrowse, sizeof(g_aszLastBrowse) ); + g_strEmuInfo.hinst = hModule; + g_strEmuInfo.fDisplayShortPop = true; // display pak switching message windows by default +#ifdef _UNICODE + { + g_strEmuInfo.Language = GetLanguageFromINI(); + if ( g_strEmuInfo.Language == 0 ) + { + g_strEmuInfo.Language = DetectLanguage(); + DebugWriteA("Autoselect language: %d\n", g_strEmuInfo.Language); + } + g_hResourceDLL = LoadLanguageDLL(g_strEmuInfo.Language); // HACK: it's theoretically not safe to call LoadLibraryEx from DllMain... --rabid + if( g_hResourceDLL == NULL ) + { + g_strEmuInfo.Language = 0; + g_hResourceDLL = hModule; + DebugWriteA("couldn't load language DLL, falling back to defaults\n"); + } + } +#else + DebugWriteA(" (compiled in ANSI mode, language detection DISABLED.)\n"); + g_strEmuInfo.Language = 0; + g_hResourceDLL = hModule; +#endif // #ifndef _UNICODE + InitializeCriticalSection( &g_critical ); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + //CloseDLL(); + if (g_hResourceDLL != g_strEmuInfo.hinst) + FreeLibrary(g_hResourceDLL); // HACK: it's not safe to call FreeLibrary from DllMain... but screw it + + DebugWriteA("*** DLL Detach\n"); + + CloseDebugFile(); // Moved here from CloseDll + DeleteCriticalSection( &g_critical ); + + // Moved here from CloseDll... Heap is created from DllMain, + // and now it's destroyed by DllMain... just safer code --rabid + if( g_hHeap != NULL ) + { + HeapDestroy( g_hHeap ); + g_hHeap = NULL; + } + break; + } + return TRUE; +} + + +/****************************************************************** + Function: GetDllInfo + Purpose: This function allows the emulator to gather information + about the dll by filling in the PluginInfo structure. + input: a pointer to a PLUGIN_INFO stucture that needs to be + filled by the function. (see def above) + output: none +*******************************************************************/ +EXPORT void CALL GetDllInfo ( PLUGIN_INFO* PluginInfo ) +{ + DebugWriteA("CALLED: GetDllInfo\n"); + strncpy(PluginInfo->Name, STRING_PLUGINNAME +#ifdef _DEBUG + " (Debug)" +#endif + ": " VERSIONNUMBER + , sizeof(PluginInfo->Name)); + PluginInfo->Type = PLUGIN_TYPE_CONTROLLER; + PluginInfo->Version = SPECS_VERSION; +} + +/****************************************************************** + Function: DllAbout + Purpose: This function is optional function that is provided + to give further information about the DLL. + input: a handle to the window that calls this function + output: none +*******************************************************************/ +EXPORT void CALL DllAbout ( HWND hParent ) +{ + DebugWriteA("CALLED: DllAbout\n"); + TCHAR tszTitle[DEFAULT_BUFFER], tszTranslator[DEFAULT_BUFFER]; + + LoadString( g_hResourceDLL, IDS_DLG_ABOUT_TITLE, tszTitle, DEFAULT_BUFFER ); + + TCHAR szText[DEFAULT_BUFFER * 4] = _T(STRING_PLUGINNAME) _T("\n\n") \ + _T("Visit my site for support: >>http://go.to/nrage<<\n\n") \ + _T("Version ") VERSIONINFO _T(" (") _T(__DATE__) _T(")\n") \ + _T("Done by N-Rage\n") \ + _T("\n") \ + _T(" - - - - -\n") \ + _T("Transferpak emulation done by MadManMarkAu\n") \ + _T("Cleanup, tweaks, and language support by RabidDeity\n"); + + LoadString( g_hResourceDLL, IDS_DLG_ABOUT, tszTranslator, DEFAULT_BUFFER ); + + _tcscat(szText, tszTranslator); + + MessageBox( hParent, szText, tszTitle, MB_OK | MB_ICONINFORMATION); + return; +} + +/****************************************************************** + Function: DllConfig + Purpose: This function is optional function that is provided + to allow the user to configure the dll + input: a handle to the window that calls this function + output: none +*******************************************************************/ +EXPORT void CALL DllConfig ( HWND hParent ) +{ + DebugWriteA("CALLED: DllConfig\n"); + static bool bInitCC = false; + if( !prepareHeap()) + return; + + if( !g_pDIHandle ) + { + if( InitDirectInput( hParent )) + { + EnterCriticalSection ( &g_critical ); + InitMouse(); + g_pDIHandle->EnumDevices( DI8DEVCLASS_ALL, EnumMakeDeviceList, NULL, DIEDFL_ATTACHEDONLY ); + LeaveCriticalSection ( &g_critical ); + DebugWriteA("InitDirectInput run in DllConfig, g_nDevices=%d\n", g_nDevices); + } + } + + if( g_pDIHandle && !g_bConfiguring ) + { + g_bConfiguring = true; + if( !bInitCC ) + { + INITCOMMONCONTROLSEX ccCtrls = { sizeof(INITCOMMONCONTROLSEX), + ICC_BAR_CLASSES | ICC_TAB_CLASSES | ICC_LISTVIEW_CLASSES }; + InitCommonControlsEx( &ccCtrls ); // needed for TrackBars & Tabs + } + + EnterCriticalSection( &g_critical ); + if( g_sysMouse.didHandle ) { // unlock mouse while configuring + g_sysMouse.didHandle->SetCooperativeLevel( g_strEmuInfo.hMainWindow, DIB_DEVICE ); + g_sysMouse.didHandle->Acquire(); + } + LeaveCriticalSection( &g_critical ); + + int iOK = DialogBox( g_hResourceDLL, MAKEINTRESOURCE( IDD_MAINCFGDIALOG ), hParent, MainDlgProc ); + + // If we go into the dialog box, and the user navigates to the Rumble window, our FF device can get unacquired. + // So let's reinit them now if we're running, just to be safe --rabid + if( g_bRunning ) + { + EnterCriticalSection( &g_critical ); + // PrepareInputDevices resets g_bExclusiveMouse to false if no mouse keys are bound, and the only way to + // re-enable exclusive mouse is with a shortcut. + // This is undesirable behavior, but it beats the alternative (and we REALLY need to re-init FF devices here) + PrepareInputDevices(); + if (iOK) + { + InitiatePaks( false ); // only re-init the mempaks and such if the user clicked Save or Use + } + + if( g_sysMouse.didHandle ) { + if ( g_bExclusiveMouse ) { // if we have exclusive mouse, we need to relock mouse after closing the config + g_sysMouse.didHandle->SetCooperativeLevel( g_strEmuInfo.hMainWindow, DIB_MOUSE ); + g_sysMouse.didHandle->Acquire(); + if (g_strEmuInfo.fDisplayShortPop) + { + LoadString( g_hResourceDLL, IDS_POP_MOUSELOCKED, g_pszThreadMessage, ARRAYSIZE(g_pszThreadMessage) ); + // HWND hMessage = CreateWindowEx( WS_EX_NOPARENTNOTIFY | WS_EX_STATICEDGE | WS_EX_TOPMOST, _T("STATIC"), pszMessage, WS_CHILD | WS_VISIBLE, 10, 10, 200, 30, g_strEmuInfo.hMainWindow, NULL, g_strEmuInfo.hinst, NULL ); + // SetTimer( hMessage, TIMER_MESSAGEWINDOW, 2000, MessageTimer ); + CreateThread(NULL, 0, MsgThreadFunction, g_pszThreadMessage, 0, NULL); + } + } + else { + g_sysMouse.didHandle->SetCooperativeLevel( g_strEmuInfo.hMainWindow, DIB_KEYBOARD ); + g_sysMouse.didHandle->Acquire(); + } + } + LeaveCriticalSection( &g_critical ); + } + + g_bConfiguring = false; + } + return; +} + +/****************************************************************** + Function: DllTest + Purpose: This function is optional function that is provided + to allow the user to test the dll + input: a handle to the window that calls this function + output: none +*******************************************************************/ +EXPORT void CALL DllTest ( HWND hParent ) +{ + DebugWriteA("CALLED: DllTest\n"); + return; +} + +// It's easier to maintain one version of this, as not much really changes +// between versions. --rabid + +#if SPECS_VERSION == 0x0100 +#pragma message("Conforming to Zilmar Spec 1.0") +/****************************************************************** + Function: InitiateControllers + Purpose: This function initialises how each of the controllers + should be handled. + input: - The handle to the main window. + - A controller structure that needs to be filled for + the emulator to know how to handle each controller. + output: none +*******************************************************************/ +EXPORT void CALL InitiateControllers( HWND hMainWindow, CONTROL Controls[4]) + +#elif SPECS_VERSION >= 0x0101 +#pragma message("Conforming to Zilmar Spec 1.1") +/****************************************************************** + Function: InitiateControllers + Purpose: This function initialises how each of the controllers + should be handled. + input: - A controller structure that needs to be filled for + the emulator to know how to handle each controller. + output: none +*******************************************************************/ +EXPORT void CALL InitiateControllers (CONTROL_INFO ControlInfo) + +#endif // SPECS_VERSION +{ + DebugWriteA("CALLED: InitiateControllers\n"); + if( !prepareHeap()) + return; + +#if SPECS_VERSION == 0x0100 + g_strEmuInfo.hMainWindow = hMainWindow; +// g_strEmuInfo.HEADER = NULL; +#elif SPECS_VERSION >= 0x0101 + g_strEmuInfo.hMainWindow = ControlInfo.hMainWindow; +// g_strEmuInfo.MemoryBswaped = ControlInfo.MemoryBswaped; +// g_strEmuInfo.HEADER = ControlInfo.HEADER; + // UNDONE: Instead of just storing the header, figure out what ROM we're running and save that information somewhere +#endif // SPECS_VERSION + + // The emulator expects us to tell what controllers are plugged in and what their paks are at this point. + + if( !g_pDIHandle ) // if we don't have a directinput handle, we need to make one, attach it to the main window (so it will die if our emulator dies), and enumerate devices + { + if( InitDirectInput( g_strEmuInfo.hMainWindow )) + { + EnterCriticalSection ( &g_critical ); + InitMouse(); + g_pDIHandle->EnumDevices( DI8DEVCLASS_ALL, EnumMakeDeviceList, NULL, DIEDFL_ATTACHEDONLY ); + LeaveCriticalSection ( &g_critical ); + DebugWriteA("InitDirectInput run in InitiateControllers, g_nDevices=%d\n", g_nDevices); + } + else + return; + } + + int iDevice; + + EnterCriticalSection( &g_critical ); + + // ZeroMemory( g_apFFDevice, sizeof(g_apFFDevice) ); // NO, we'll reinit the existing reference if it's already loaded + // ZeroMemory( g_apdiEffect, sizeof(g_apdiEffect) ); // NO, we'll release it with CloseControllerPak + + for( int i = 3; i >= 0; i-- ) + { + SaveControllerPak( i ); + CloseControllerPak( i ); + // freePakData( &g_pcControllers[i] ); // already called by CloseControllerPak + freeModifiers( &g_pcControllers[i] ); + SetControllerDefaults( &g_pcControllers[i] ); + } + + g_pcControllers[0].fPlugged = true; + + if (! LoadConfigFromINI() ) + { + DebugWriteA("\tINI load failed, loading defaults from resource\n"); + for ( int i = 0; i < 4; i++ ) + LoadProfileFromResource( i, false ); + LoadShortcutsFromResource(false); + } + + for( int i = 0; i < 4; i++) // initiate xinput controller and plug then if connected --tecnicors + { + InitiateXInputController( &g_pcControllers[i].xiController, i ); + if( g_pcControllers[i].xiController.bConnected ) + { + g_pcControllers[i].fPlugged = true; + g_pcControllers[i].fGamePad = true; + } + } // END + + // Init: Find force-feedback devices and init + for( int i = 3; i >= 0; i-- ) + { + DebugWriteA("Controller %d: ", i+1); + if( g_pcControllers[i].xiController.bConnected && g_pcControllers[i].fXInput) // if xinput connected, we don't need other config --tecnicors + continue; + + if( g_pcControllers[i].fPlugged ) + { + // Search for right Controller + iDevice = FindDeviceinList( g_pcControllers[i].guidFFDevice ); + if( iDevice != -1 && g_devList[iDevice].bEffType ) + { + DebugWriteA("rumble device set, "); + } + else // we couldn't find the device specified in the INI file, or it was already null + { + g_pcControllers[i].guidFFDevice = GUID_NULL; + DebugWriteA("no rumble device/effect type set, "); + } + + if( g_pcControllers[i].nModifiers > 0) + SetModifier( &g_pcControllers[i] ); + g_iFirstController = i; + DebugWriteA("plugged in, with paktype %d, ", g_pcControllers[i].PakType); + DebugWriteA("RawMode is %d\n", g_pcControllers[i].fRawData); + } + else + { + DebugWriteA("unplugged\n"); + freePakData( &g_pcControllers[i] ); // we don't need to do this again, but there's not much overhead so I'll leave it --rabid + freeModifiers( &g_pcControllers[i] ); + } + } + + PrepareInputDevices(); + + if( g_bExclusiveMouse ) { + // g_sysMouse.didHandle->Unacquire(); + // g_sysMouse.didHandle->SetCooperativeLevel( g_strEmuInfo.hMainWindow, DIB_MOUSE ); // PrepareInputDevices does this. + g_sysMouse.didHandle->Acquire(); + } + + InitiatePaks( true ); + + g_strEmuInfo.fInitialisedPlugin = true; + + LeaveCriticalSection( &g_critical ); + +#if SPECS_VERSION == 0x0100 + FillControls(Controls); +#elif SPECS_VERSION >= 0x0101 + FillControls(ControlInfo.Controls); +#endif // SPECS_VERSION + + return; +} // end InitiateControllers + +/****************************************************************** + Function: RomOpen + Purpose: This function is called when a rom is open. (from the + emulation thread) + input: none + output: none +*******************************************************************/ +EXPORT void CALL RomOpen (void) +{ + DebugWriteA("CALLED: RomOpen\n"); + + //XInputEnable( TRUE ); // enables xinput --tecnicors + + if( !g_strEmuInfo.fInitialisedPlugin ) + { + ErrorMessage(IDS_ERR_NOINIT, 0, false); + return; + } + + EnterCriticalSection( &g_critical ); + // re-init our paks and shortcuts + InitiatePaks( true ); + // LoadShortcuts( &g_scShortcuts ); WHY are we loading shortcuts again?? Should already be loaded! + LeaveCriticalSection( &g_critical ); + g_bRunning = true; + return; +} + +/****************************************************************** + Function: RomClosed + Purpose: This function is called when a rom is closed. + input: none + output: none +*******************************************************************/ +EXPORT void CALL RomClosed(void) +{ + int i; + + //XInputEnable( FALSE ); // disables xinput --tecnicors + + DebugWriteA("CALLED: RomClosed\n"); + EnterCriticalSection( &g_critical ); + + if (g_sysMouse.didHandle) + g_sysMouse.didHandle->SetCooperativeLevel(g_strEmuInfo.hMainWindow, DIB_KEYBOARD); // unlock the mouse, just in case + + for( i = 0; i < ARRAYSIZE(g_pcControllers); ++i ) + { + if( g_pcControllers[i].pPakData ) + { + SaveControllerPak( i ); + CloseControllerPak( i ); + } + // freePakData( &g_pcControllers[i] ); already done by CloseControllerPak --rabid + // DON'T free the modifiers! +// ZeroMemory( &g_pcControllers[i], sizeof(CONTROLLER) ); + } + + for( i = 0; i < ARRAYSIZE( g_apdiEffect ); ++i ) + ReleaseEffect( g_apdiEffect[i] ); + ZeroMemory( g_apdiEffect, sizeof(g_apdiEffect) ); + + g_bRunning = false; + LeaveCriticalSection( &g_critical ); + + return; +} + +/****************************************************************** + Function: GetKeys + Purpose: To get the current state of the controllers buttons. + input: - Controller Number (0 to 3) + - A pointer to a BUTTONS structure to be filled with + the controller state. + output: none +*******************************************************************/ +EXPORT void CALL GetKeys(int Control, BUTTONS * Keys ) +{ +#ifdef ENABLE_RAWPAK_DEBUG + DebugWriteA("CALLED: GetKeys\n"); +#endif + if( g_bConfiguring ) + Keys->Value = 0; + else + { + EnterCriticalSection( &g_critical ); + + if( g_pcControllers[Control].fPlugged ) { + if (Control == g_iFirstController ) + { + GetDeviceDatas(); + CheckShortcuts(); + } + if( g_pcControllers[Control].xiController.bConnected && g_pcControllers[Control].fXInput ) // reads the xinput controller keys, if connected --tecnicors + GetXInputControllerKeys( Control, &Keys->Value ); + else + GetNControllerInput( Control, &Keys->Value ); + } + LeaveCriticalSection( &g_critical ); + } + return; +} + +/****************************************************************** + Function: ControllerCommand + Purpose: To process the raw data that has just been sent to a + specific controller. + input: - Controller Number (0 to 3) and -1 signalling end of + processing the pif ram. + - Pointer of data to be processed. + output: none + + note: This function is only needed if the DLL is allowing raw + data. + + the data that is being processed looks like this: + initilize controller: 01 03 00 FF FF FF + read controller: 01 04 01 FF FF FF FF +*******************************************************************/ +EXPORT void CALL ControllerCommand( int Control, BYTE * Command) +{ + // We don't need to use this because it will be echoed immediately afterwards + // by a call to ReadController + return; +} + +/****************************************************************** + Function: ReadController + Purpose: To process the raw data in the pif ram that is about to + be read. + input: - Controller Number (0 to 3) and -1 signalling end of + processing the pif ram. + - Pointer of data to be processed. + output: none + note: This function is only needed if the DLL is allowing raw + data. +*******************************************************************/ +EXPORT void CALL ReadController( int Control, BYTE * Command ) +{ +#ifdef ENABLE_RAWPAK_DEBUG + DebugWriteA("CALLED: ReadController\n"); +#endif + if( Control == -1 ) + return; + + EnterCriticalSection( &g_critical ); + + if( !g_pcControllers[Control].fPlugged ) + { + Command[1] |= RD_ERROR; + LeaveCriticalSection( &g_critical ); + return; + } + + + switch( Command[2] ) + { + case RD_RESETCONTROLLER: + WriteDatasA( "ResetController-PreProcessing", Control, Command, 0); + case RD_GETSTATUS: + // expected: controller gets 1 byte (command), controller sends back 3 bytes + // should be: Command[0] == 0x01 + // Command[1] == 0x03 +#ifdef ENABLE_RAWPAK_DEBUG + WriteDatasA( "GetStatus-PreProcessing", Control, Command, 0); +#endif + Command[3] = RD_GAMEPAD | RD_ABSOLUTE; + Command[4] = RD_NOEEPROM; + + if( g_pcControllers[Control].fPakInitialized && g_pcControllers[Control].pPakData ) + { + if( *(BYTE*)g_pcControllers[Control].pPakData == PAK_ADAPTOID ) + { + Command[5] = GetAdaptoidStatus( Control ); + + if( Command[5] & RD_NOTINITIALIZED ) + ((ADAPTOIDPAK*)g_pcControllers[Control].pPakData)->fRumblePak = true; + } + else + { + Command[5] = ( *(BYTE*)g_pcControllers[Control].pPakData != PAK_NONE ) ? RD_PLUGIN : RD_NOPLUGIN; + if( g_pcControllers[Control].fPakCRCError ) + { + Command[5] = Command[5] | RD_ADDRCRCERR; + g_pcControllers[Control].fPakCRCError = false; + } + } + } + else + { + if( !g_bConfiguring && InitControllerPak( Control ) && g_pcControllers[Control].pPakData ) + { + g_pcControllers[Control].fPakInitialized = true; + + if( *(BYTE*)g_pcControllers[Control].pPakData == PAK_ADAPTOID ) + Command[5] = GetAdaptoidStatus( Control ); + else + { + Command[5] = ( *(BYTE*)g_pcControllers[Control].pPakData ) ? RD_PLUGIN : RD_NOPLUGIN; + Command[5] = Command[5] | ( g_pcControllers[Control].fPakCRCError ? RD_ADDRCRCERR : 0 ); + } + } + else + Command[5] = RD_NOPLUGIN | RD_NOTINITIALIZED; + } + + if( g_pcControllers[Control].fPakCRCError ) + { + Command[5] = Command[5] | RD_ADDRCRCERR; + g_pcControllers[Control].fPakCRCError = false; + } + +#ifdef ENABLE_RAWPAK_DEBUG + WriteDatasA( "GetStatus-PostProcessing", Control, Command, 0); + DebugWriteA( NULL ); +#endif + break; + + case RD_READKEYS: + // expected: controller gets 1 byte (command), controller sends back 4 bytes + // should be: Command[0] == 0x01 + // Command[1] == 0x04 + if( g_bConfiguring ) + Command[3] = Command[4] = Command[5] = Command[6] = 0; + else + { + if (Control == g_iFirstController ) + { + GetDeviceDatas(); + CheckShortcuts(); + } + if( g_pcControllers[Control].xiController.bConnected && g_pcControllers[Control].fXInput ) // reads xinput controller kesy, if connected --tecnicors + GetXInputControllerKeys( Control, (LPDWORD)&Command[3] ); + else + GetNControllerInput( Control, (DWORD*)&Command[3] ); + } + break; + + + case RD_READPAK: +#ifdef ENABLE_RAWPAK_DEBUG + WriteDatasA( "ReadPak-PreProcessing", Control, Command, 0); +#endif + if( g_pcControllers[Control].fPakInitialized ) + //Command[1] = Command[1] | ReadControllerPak( Control, &Command[3] ); + ReadControllerPak( Control, &Command[3] ); + else + { + DebugWriteA("Tried to read, but pak wasn't initialized!!\n"); + // InitControllerPak( Control ); + Command[1] |= RD_ERROR; + //ZeroMemory( &Command[5], 32 ); + } +#ifdef ENABLE_RAWPAK_DEBUG + WriteDatasA( "ReadPak-PostProcessing", Control, Command, 0); + DebugWriteA( NULL ); +#endif + break; + + case RD_WRITEPAK: +#ifdef ENABLE_RAWPAK_DEBUG + WriteDatasA( "WritePak-PreProcessing", Control, Command, 0); +#endif + if( g_pcControllers[Control].fPakInitialized ) + //Command[1] = Command[1] | WriteControllerPak( Control, &Command[3] ); + WriteControllerPak( Control, &Command[3] ); + else + { + DebugWriteA("Tried to write, but pak wasn't initialized! (paktype was %u)\n", g_pcControllers[Control].PakType); + // InitControllerPak( Control ); + Command[1] |= RD_ERROR; + } +#ifdef ENABLE_PAK_WRITES_DEBUG + WriteDatasA( "WritePak-PostProcessing", Control, Command, 0); + DebugWriteA( NULL ); +#endif + break; + + case RD_READEEPROM: + // Should be handled by the Emulator + WriteDatasA( "ReadEeprom-PreProcessing", Control, Command, 0); + WriteDatasA( "ReadEeprom-PostProcessing", Control, Command, 0); + DebugWriteA( NULL ); + break; + case RD_WRITEEPROM: + // Should be handled by the Emulator + WriteDatasA( "WriteEeprom-PreProcessing", Control, Command, 0); + WriteDatasA( "WriteEeprom-PostProcessing", Control, Command, 0); + DebugWriteA( NULL ); + break; + + default: + // only accessible if the Emulator has bugs.. or maybe the Rom is flawed + WriteDatasA( "ReadController: Bad read", Control, Command, 0); + DebugWriteA( NULL ); + Command[1] = Command[1] | RD_ERROR; + } + + LeaveCriticalSection( &g_critical ); + return; +} + +/****************************************************************** + Function: WM_KeyDown + Purpose: To pass the WM_KeyDown message from the emulator to the + plugin. + input: wParam and lParam of the WM_KEYDOWN message. + output: none +*******************************************************************/ +EXPORT void CALL WM_KeyDown( WPARAM wParam, LPARAM lParam ) +{ + return; +} + +/****************************************************************** + Function: WM_KeyUp + Purpose: To pass the WM_KEYUP message from the emulator to the + plugin. + input: wParam and lParam of the WM_KEYDOWN message. + output: none +*******************************************************************/ +EXPORT void CALL WM_KeyUp( WPARAM wParam, LPARAM lParam ) +{ + return; +} + +/****************************************************************** + Function: CloseDLL + Purpose: This function is called when the emulator is closing + down allowing the dll to de-initialise. + input: none + output: none +*******************************************************************/ +EXPORT void CALL CloseDLL (void) +{ // HACK: THIS IS BROKEN IN PJ64 1.6 (it calls CloseDLL too often) + DebugWriteA("CALLED: CloseDLL\n"); + if( g_bRunning ) + RomClosed(); + for( int i = 0; i < 4; i++ ) + { + freePakData( &g_pcControllers[i] ); + freeModifiers( &g_pcControllers[i] ); + } + + // ZeroMemory( g_pcControllers, sizeof(g_pcControllers) ); // why zero the memory if we're just going to close down? + + FreeDirectInput(); + + return; +} + +// Prepare a global heap. Use P_malloc and P_free as wrappers to grab/release memory. +bool prepareHeap() +{ + if( g_hHeap == NULL ) + g_hHeap = HeapCreate( 0, 4*1024, 0 ); + return (g_hHeap != NULL); +} + +// Frees pakdata memory (called more often than you'd think). +void freePakData( CONTROLLER *pcController ) +{ + if( pcController && pcController->pPakData ) + { + P_free( pcController->pPakData ); + pcController->pPakData = NULL; + } +} + +// Frees modifier memory +void freeModifiers( CONTROLLER *pcController ) +{ + if( pcController && pcController->pModifiers ) + { + pcController->nModifiers = 0; + P_free( pcController->pModifiers ); + pcController->pModifiers = NULL; + } +} + +// After enumerating DirectInput devices into g_devList, find a device by product name and counter +int FindDeviceinList( const TCHAR *pszProductName, const BYTE bProductCounter, bool fFindSimilar ) +{ + if( !(*pszProductName) ) + return -1; + + int i = 0, iSimilar = -1, iExact = -1; + while(( i < ARRAYSIZE(g_devList) ) && ( iExact == -1 )) + { + if( !lstrcmp( g_devList[i].szProductName, pszProductName )) + { + if(( bProductCounter > 0 ) || ( iSimilar == -1 )) + iSimilar = i; + if( g_devList[i].bProductCounter == bProductCounter ) + iExact = i; + } + i++; + } + + if( fFindSimilar && ( iExact == -1 )) + iExact = iSimilar; + + return iExact; +} + +// After enumerating DirectInput devices into g_devList, find a device by GUID. Finding similar devices is impossible. +int FindDeviceinList( REFGUID rGUID ) +{ + if (rGUID == GUID_NULL ) + return -1; + int i = 0; + while( i < ARRAYSIZE(g_devList) ) + { + if ( IsEqualGUID(g_devList[i].guidInstance, rGUID) ) + return i; + i++; + } + return -1; +} + +// Let's initialize all plugged in controllers' paks. +// Input: false means run InitControlPak on each plugged controller. Input true means just clear each pak's CRC error status? +// When we call this from RomOpen, it's true, otherwise (in DllConfig) it's false. +// Rather counterintuitive. +void InitiatePaks( bool bInitialize ) +{ + for( int i = 0; i < 4; i++ ) + { + if( g_pcControllers[i].fPlugged) + { + g_pcControllers[i].fPakCRCError = false; + + if( g_pcControllers[i].fRawData ) + { + if( !bInitialize ) + g_pcControllers[i].fPakInitialized = InitControllerPak( i ); + } + else + { // we only support "RAW mode" paks so this won't do much + ;//if( g_pcControllers[i].PakType == PAK_RUMBLE ) + // CreateEffectHandle( i, g_pcControllers[i].bRumbleTyp, g_pcControllers[i].bRumbleStrength ); + } + } + } +} + +// This used to be "NotifyEmulator" which was supposed to tell the emulator if we changed the way it sees controllers. +// Unfortunately the spec doesn't work that way. Fixed the func and changed the func name to something that makes more sense. +// FillControls takes a Controls array from InitiateControllers and fills it with what we know about whether +// a controller is plugged in, accepting raw data, and what type of pak is plugged in. +void FillControls(CONTROL Controls[4]) +{ + for( int i = 4-1; i >= 0; i-- ) + { + if( g_pcControllers[i].fPlugged ) + { + Controls[i].Present = g_pcControllers[i].fPlugged; + Controls[i].RawData = g_pcControllers[i].fRawData; + + switch( g_pcControllers[i].PakType ) + { + case PAK_MEM: + Controls[i].Plugin = PLUGIN_MEMPAK; + break; + case PAK_RUMBLE: + Controls[i].Plugin = PLUGIN_RUMBLE_PAK; + break; + case PAK_TRANSFER: + Controls[i].Plugin = PLUGIN_TRANSFER_PAK; + break; + case PAK_VOICE: + Controls[i].Plugin = g_pcControllers[i].fRawData ? PLUGIN_RAW : PLUGIN_NONE; + break; + case PAK_ADAPTOID: + Controls[i].Plugin = g_pcControllers[i].fRawData ? PLUGIN_RAW : PLUGIN_NONE; + break; + + case PAK_NONE: + default: + Controls[i].Plugin = PLUGIN_NONE; + } + } + else + { + Controls[i].Plugin = PLUGIN_NONE; + Controls[i].Present = false; + Controls[i].RawData = true; + } + } +} + +// called after a poll to execute any shortcuts +void CheckShortcuts() +{ + static bool bWasPressed[ sizeof(SHORTCUTSPL)/sizeof(BUTTON) ][4]; + static bool bMLWasPressed; // mouselock + bool bMatching = false; + + if ( g_bConfiguring || !g_bRunning ) + return; // we don't process shortcuts if we're in a config menu or are not running emulation + + // just process if key wasnt pressed before + for ( int i = 0; i < 4; i++ ) // controllers + { + for( int j = 0; j < SC_TOTAL; j++ ) + { + bMatching = IsBtnPressed( g_scShortcuts.Player[i].aButtons[j] ); + + if( bMatching && !bWasPressed[j][i] ) + DoShortcut(i, j); + + bWasPressed[j][i] = bMatching; + } + } + + bMatching = IsBtnPressed( g_scShortcuts.bMouseLock ); + + if( bMatching && !bMLWasPressed ) + DoShortcut(-1, -1); // controller -1 means do mouselock shortcut + + bMLWasPressed = bMatching; +} + +// Executes the shortcut iShortcut on controller iController +// Special case: if iPlayer is -1, run the mouselock shortcut +void DoShortcut( int iControl, int iShortcut ) +{ + DebugWriteA("Shortcut: %d %d\n", iControl, iShortcut); + TCHAR pszMessage[DEFAULT_BUFFER / 2] = TEXT(""); + bool bEjectFirst = false; + + if (iControl == -1) + { + EnterCriticalSection( &g_critical ); + if( g_sysMouse.didHandle ) + { + g_sysMouse.didHandle->Unacquire(); + if( g_bExclusiveMouse ) + { + g_sysMouse.didHandle->Unacquire(); + g_sysMouse.didHandle->SetCooperativeLevel( g_strEmuInfo.hMainWindow, DIB_KEYBOARD ); + g_sysMouse.didHandle->Acquire(); + LoadString( g_hResourceDLL, IDS_POP_MOUSEUNLOCKED, pszMessage, ARRAYSIZE(pszMessage) ); + } + else + { + g_sysMouse.didHandle->Unacquire(); + g_sysMouse.didHandle->SetCooperativeLevel( g_strEmuInfo.hMainWindow, DIB_MOUSE ); + g_sysMouse.didHandle->Acquire(); + LoadString( g_hResourceDLL, IDS_POP_MOUSELOCKED, pszMessage, ARRAYSIZE(pszMessage) ); + } + g_sysMouse.didHandle->Acquire(); + g_bExclusiveMouse = !g_bExclusiveMouse; + } + LeaveCriticalSection( &g_critical ); + } + else if( g_pcControllers[iControl].fPlugged ) + { + if( g_pcControllers[iControl].pPakData ) + { + SaveControllerPak( iControl ); + CloseControllerPak( iControl ); + } + + switch (iShortcut) + { + case SC_NOPAK: + EnterCriticalSection( &g_critical ); + g_pcControllers[iControl].PakType = PAK_NONE; + g_pcControllers[iControl].fPakInitialized = false; + LoadString( g_hResourceDLL, IDS_P_NONE, pszMessage, ARRAYSIZE(pszMessage) ); + LeaveCriticalSection( &g_critical ); + break; + + case SC_MEMPAK: + if (PAK_NONE == g_pcControllers[iControl].PakType) + { + EnterCriticalSection( &g_critical ); + g_pcControllers[iControl].PakType = PAK_MEM; + g_pcControllers[iControl].fPakInitialized = false; + LoadString( g_hResourceDLL, IDS_P_MEMPAK, pszMessage, ARRAYSIZE(pszMessage) ); + LeaveCriticalSection( &g_critical ); + } + else + { + bEjectFirst = true; + } + break; + + case SC_RUMBPAK: + if (PAK_NONE == g_pcControllers[iControl].PakType) + { + EnterCriticalSection( &g_critical ); + g_pcControllers[iControl].PakType = PAK_RUMBLE; + g_pcControllers[iControl].fPakInitialized = false; + + if( g_pcControllers[iControl].fRawData ) + if (CreateEffectHandle( iControl, g_pcControllers[iControl].bRumbleTyp, g_pcControllers[iControl].bRumbleStrength ) ) + { + DebugWriteA("CreateEffectHandle for shortcut switch: OK\n"); + } + else + { + DebugWriteA("Couldn't CreateEffectHandle for shortcut switch.\n"); + } + + LoadString( g_hResourceDLL, IDS_P_RUMBLEPAK, pszMessage, ARRAYSIZE(pszMessage) ); + LeaveCriticalSection( &g_critical ); + } + else + { + bEjectFirst = true; + } + break; + + case SC_TRANSPAK: + if (PAK_NONE == g_pcControllers[iControl].PakType) + { + EnterCriticalSection( &g_critical ); + g_pcControllers[iControl].PakType = PAK_TRANSFER; + g_pcControllers[iControl].fPakInitialized = false; + + LoadString( g_hResourceDLL, IDS_P_TRANSFERPAK, pszMessage, ARRAYSIZE(pszMessage) ); + LeaveCriticalSection( &g_critical ); + } + else + { + bEjectFirst = true; + } + break; + + case SC_VOICEPAK: + if (PAK_NONE == g_pcControllers[iControl].PakType) + { + EnterCriticalSection( &g_critical ); + g_pcControllers[iControl].PakType = PAK_VOICE; + g_pcControllers[iControl].fPakInitialized = false; + + LoadString( g_hResourceDLL, IDS_P_VOICEPAK, pszMessage, ARRAYSIZE(pszMessage) ); + LeaveCriticalSection( &g_critical ); + } + else + { + bEjectFirst = true; + } + break; + + case SC_ADAPTPAK: + if (PAK_NONE == g_pcControllers[iControl].PakType) + { + EnterCriticalSection( &g_critical ); + g_pcControllers[iControl].PakType = PAK_ADAPTOID; + g_pcControllers[iControl].fPakInitialized = false; + + LoadString( g_hResourceDLL, IDS_P_ADAPTOIDPAK, pszMessage, ARRAYSIZE(pszMessage) ); + LeaveCriticalSection( &g_critical ); + } + else + { + bEjectFirst = true; + } + break; + + case SC_SWMEMRUMB: + bEjectFirst = true; + if( g_pcControllers[iControl].PakType == PAK_MEM ) + { + iShortcut = PAK_RUMBLE; + } + else + { + iShortcut = PAK_MEM; + } + break; + + case SC_SWMEMADAPT: + bEjectFirst = true; + if( g_pcControllers[iControl].PakType == PAK_MEM ) + { + iShortcut = PAK_ADAPTOID; + } + else + { + iShortcut = PAK_MEM; + } + break; + + default: + DebugWriteA("Invalid iShortcut passed to DoShortcut\n"); + EnterCriticalSection( &g_critical ); + g_pcControllers[iControl].fPakInitialized = false; + LeaveCriticalSection( &g_critical ); + return; + } // switch (iShortcut) + } // else if + + // let the game code re-init the pak. + + if (bEjectFirst) // we need to eject the current pack first; then set a DoShortcut to try again in 1 second + { + EnterCriticalSection( &g_critical ); + g_pcControllers[iControl].PakType = PAK_NONE; + g_pcControllers[iControl].fPakInitialized = false; + LoadString( g_hResourceDLL, IDS_P_SWITCHING, pszMessage, ARRAYSIZE(pszMessage) ); + LeaveCriticalSection( &g_critical ); + + LPMSHORTCUT lpmNextShortcut = (LPMSHORTCUT)P_malloc(sizeof(MSHORTCUT)); + if (!lpmNextShortcut) + return; + lpmNextShortcut->iControl = iControl; + lpmNextShortcut->iShortcut = iShortcut; + CreateThread(NULL, 0, DelayedShortcut, lpmNextShortcut, 0, NULL); + iControl = -2; // this is just a hack to get around the check that appends "Changing Pak X to ..." + } + + if( g_strEmuInfo.fDisplayShortPop && _tcslen(pszMessage) > 0 ) + { + if( iControl >= 0 ) + { + TCHAR tszNotify[DEFAULT_BUFFER / 2]; + + LoadString( g_hResourceDLL, IDS_POP_CHANGEPAK, tszNotify, ARRAYSIZE(tszNotify)); + wsprintf( g_pszThreadMessage, tszNotify, iControl+1, pszMessage ); + } + else + lstrcpyn( g_pszThreadMessage, pszMessage, ARRAYSIZE(g_pszThreadMessage) ); + + CreateThread(NULL, 0, MsgThreadFunction, g_pszThreadMessage, 0, NULL); + } +} + +// Use string table refs to generate and throw an error message with title IDS_ERR_TITLE (see string table in resources) +// Also if compiled with DEBUG, will log the message with DebugWrite +// uID the string table ref to display +// dwError if nonzero, will display a Windows error message using FormatMessage (for use when an API function fails) +// fUserChoose if true, display buttons Retry and Cancel. if false, display single button OK. +// for fUserChoose==true; ErrorMessage returns true if user selects Retry, and false if user selects Cancel. +// for fUserChoose==false; ErrorMessage always returns false. +bool ErrorMessage( UINT uID, DWORD dwError, bool fUserChoose ) +{ + TCHAR pszFirstLine[DEFAULT_BUFFER]; + + bool fReturn = false; + int iBytes; + TCHAR szError[512]; + TCHAR tszErrorTitle[DEFAULT_BUFFER]; + + LoadString( g_hResourceDLL, uID, pszFirstLine, DEFAULT_BUFFER ); + LoadString( g_hResourceDLL, IDS_ERR_TITLE, tszErrorTitle, DEFAULT_BUFFER ); + + if( dwError ) + { + iBytes = wsprintf( szError, _T("%s\n\n Error description: "), pszFirstLine ); + FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError , 0, &szError[iBytes], sizeof(szError) - iBytes, NULL ); + } + else + lstrcpyn( szError, pszFirstLine, 512 ); + + DebugWrite(_T("ErrorMessage! ID:%d "), uID); + DebugFlush(); + + if( fUserChoose ) + fReturn = MessageBox( g_strEmuInfo.hMainWindow, szError, tszErrorTitle, MB_RETRYCANCEL | MB_ICONERROR ) == IDRETRY; + else + MessageBox( g_strEmuInfo.hMainWindow, szError, tszErrorTitle, MB_OK | MB_ICONERROR ); + + DebugWriteA(fReturn ? "(user: retry)\n" : "(user: acknowledge)\n"); + return fReturn; +} + +// Post a message box, using string resource uTextID and MessageBox style uType +int WarningMessage( UINT uTextID, UINT uType ) +{ + DebugWriteA("WarningMessage: ID:%d Type:%d\n", uTextID, uType); + DebugFlush(); + + TCHAR tszTitle[DEFAULT_BUFFER], tszText[DEFAULT_BUFFER]; + + LoadString( g_hResourceDLL, uTextID, tszText, DEFAULT_BUFFER ); + LoadString( g_hResourceDLL, IDS_DLG_WARN_TITLE, tszTitle, DEFAULT_BUFFER ); + + return MessageBox( g_strEmuInfo.hMainWindow, tszText, tszTitle, uType ); +} + + +/* H.Morii + MsgThreadFunction is used because the SetTimer function relies + on the WM_TIMER message which is low priority and will not be + executed if other windows messages are frequently dispatched. */ + +DWORD WINAPI MsgThreadFunction( LPVOID lpParam ) +{ + HWND hMessage = CreateWindowEx( WS_EX_NOPARENTNOTIFY | WS_EX_STATICEDGE | WS_EX_TOPMOST, _T("STATIC"), NULL, WS_CHILD | WS_VISIBLE, 10, 10, 200, 40, g_strEmuInfo.hMainWindow, NULL, g_strEmuInfo.hinst, NULL ); + + /* prepare the screen to bitblt */ + RECT rt; + GetClientRect(hMessage, &rt); + HDC hdc = GetDC(hMessage); + HDC memdc = CreateCompatibleDC(hdc); + HBITMAP hbitmap = CreateCompatibleBitmap(hdc, rt.right - rt.left, rt.bottom - rt.top); + SelectObject(memdc, hbitmap); + + /* draw some nice stuff. + choose fonts, paint the back ground, etc here. */ + FillRect(memdc, &rt, (HBRUSH)(COLOR_WINDOW+1)); + DrawText(memdc, (LPCTSTR)lpParam, -1, &rt, DT_WORDBREAK); + + /* bitblt to kingdom come */ + for (int i = 0; i < 60; i++) + { + Sleep(16); // 1/60 second + BitBlt(hdc, rt.left, rt.top, rt.right - rt.left, rt.bottom - rt.top, memdc, 0, 0, SRCCOPY); + } + + /* cleanup */ + DeleteObject(hbitmap); + DeleteDC(memdc); + ReleaseDC(hMessage, hdc); + + /* Can only destroy windows created from the owner thread */ + DestroyWindow(hMessage); + + return 0; +} + +// This function is called as a thread by DoShortcut in order to tell the plugin to insert a pak shortly +// (usually after we've just removed whatever pak was there) +DWORD WINAPI DelayedShortcut(LPVOID lpParam) +{ + LPMSHORTCUT sc = (LPMSHORTCUT)lpParam; + if (sc && sc->iShortcut != SC_SWMEMRUMB && sc->iShortcut != SC_SWMEMADAPT) // don't allow recursion into self, it would cause a deadlock + { + Sleep(1000); // sleep a little bit before calling DoShortcut again + DoShortcut(sc->iControl, sc->iShortcut); + } + P_free(lpParam); + return 0; +} \ No newline at end of file diff --git a/Source/nragev20/NRagePluginV2.h b/Source/nragev20/NRagePluginV2.h new file mode 100644 index 000000000..2a4259701 --- /dev/null +++ b/Source/nragev20/NRagePluginV2.h @@ -0,0 +1,394 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _NRAGEPLUGIN_ +#define _NRAGEPLUGIN_ + +#include +#include "XInputController.h" + +///////////////////////////////////////////////////////////////////////////////// +//General Plugin + +#define STRING_PLUGINNAME "N-Rage Input Plugin V2" + +#define TIMER_MESSAGEWINDOW 123 + + // maximum number of devices other than SysMouse +#define MAX_DEVICES 32 + // maximum number of modifiers +#define MAX_MODIFIERS 256 + +#define DEFAULT_STICKRANGE 66 +#define DEFAULT_DEADZONE 5 +#define DEFAULT_RUMBLETYP RUMBLE_EFF1 +#define DEFAULT_RUMBLESTRENGTH 80 +#define DEFAULT_MOUSESENSIVITY 100 +#define DEFAULT_PAKTYPE PAK_NONE +#define DEFAULT_MOUSEMOVE MM_BUFF + +#define PAK_NONE 0 +#define PAK_MEM 1 +#define PAK_RUMBLE 2 +#define PAK_TRANSFER 3 +#define PAK_VOICE 4 +#define PAK_ADAPTOID 7 + + // just used to display text in GUI +#define PAK_NONRAW 16 + + + +typedef struct _EMULATOR_INFO +{ + bool fInitialisedPlugin; + HWND hMainWindow; + HINSTANCE hinst; + LANGID Language; + bool fDisplayShortPop; // do we display shortcut message popups? + +// BOOL MemoryBswaped; // If this is set to TRUE, then the memory has been pre + // bswap on a dword (32 bits) boundry, only effects header. + // eg. the first 8 bytes are stored like this: + // 4 3 2 1 8 7 6 5 +// BYTE * HEADER; // This is the rom header (first 40h bytes of the rom) +} EMULATOR_INFO, *LPEMULATOR_INFO; + +typedef struct _DEVICE +{ + LPDIRECTINPUTDEVICE8 didHandle; + TCHAR szProductName[MAX_PATH]; + BYTE bProductCounter; + GUID guidInstance; + DWORD dwDevType; // can be DI8DEVTYPE_KEYBOARD, DI8DEVTYPE_MOUSE, etc + BYTE bEffType; // What rumble effects does this device support? + union INPUTSTATE { // the last polled data from this device + DIJOYSTATE joyState; + DIMOUSESTATE2 mouseState; + BYTE rgbButtons[256]; // keyboard state + } stateAs; +} DEVICE, *LPDEVICE; + +typedef struct _BUTTON +{ + bool fPrevPressed; // Was this button pressed last time we checked? (not to be saved in config) + BYTE bOffset; // Offset in the DirectInput data structure + BYTE bAxisID; // Tells which range of the Axe/POV is important (see AI_AXE_P, AI_POV_UP, etc) + BYTE bBtnType; // Type of device/button: Keyboard key, Joystick axis, Joystick button, Mouse axis, etc + LPDEVICE parentDevice; // pointer to the DEVICE this assignment came from +} BUTTON, *LPBUTTON; + +// Modifiers are a feature built into NRage. Emulator turbo buttons, macros, stuff like that. +typedef struct _MODIFIER +{ + BUTTON btnButton; // button to associate with + BYTE bModType; // Type of modifier (None, Movement, Macro, Config) + BOOL fToggle; // false if you have to hold the button down to activate, true if the modifier toggles on button press + BOOL fStatus; // if true, control defaults to ACTIVE, and deactivates on button press + DWORD32 dwSpecific; // will be cast to MODSPEC_MOVE, MODSPEC_MACRO, or MODSPEC_CONFIG +} MODIFIER, *LPMODIFIER; + +// bModType (modifiers) +#define MDT_NONE 0 +#define MDT_MOVE 1 +#define MDT_MACRO 2 +#define MDT_CONFIG 3 + + // buffered +#define MM_BUFF 0 + // absolute +#define MM_ABS 1 + // deadpan +#define MM_DEAD 2 + + // Number of analog axes. Standard N64 controller has just 2: X and Y joystick. +#define PF_AXESETS 2 + +typedef struct _CONTROLLER // AN N64 CONTROLLER +{ + unsigned fPlugged; // is the controller "plugged" (i.e. does the emulator see a controller on this port?) + unsigned fXInput; // is the controller an xInput device? + unsigned fRawData; // are we using RAW mode for this controller? + unsigned fIsAdaptoid; // is it an adaptoid? + + unsigned fKeyboard; // does it use a keyboard? + unsigned fMouse; // does it use a mouse? + unsigned fGamePad; // does it use a gamepad/joystick? + + unsigned fRealN64Range; // does it have the "Real N64 Range" flag set? + unsigned bAxisSet; // which set of axes are we using? (Control 1, Control 2) + unsigned bMouseMoveX; // does it use buffered/absolute mouse for X? MM_BUFF, MM_ABS, MM_DEAD + unsigned bMouseMoveY; // does it use buffered/absolute mouse for Y? + unsigned fKeyAbsoluteX; // does it use absolute key for X? + unsigned fKeyAbsoluteY; // does it use absolute key for Y? + + unsigned fPakInitialized; // Has our pak been initialized? Used to make sure we don't try to write to a mempak that doesn't point to anything. + unsigned fPakCRCError; // The ROM sends CRC data when it tries to write to a mempak. Is the CRC incorrect? Usually indicates a bad ROM. + unsigned PakType; // what type of controller pak? mempak? rumble? transfer? etc + unsigned fVisualRumble; // is visual rumble enabled for this controller? + + BYTE bRumbleTyp; // what type of rumble effect? none, constant, ramp, or direct? + + GUID guidFFDevice; // GUID of the device that rumble gets sent to + + BYTE bStickRange; // our "range modifier". + + long wAxeBuffer[4]; // makes pseudo-relative Movement possible through keyboard or buttons + // also acts as a mouse buffer + + WORD wMouseSensitivityX; // set per N64 controller, that's OK + WORD wMouseSensitivityY; + BYTE bPadDeadZone; // our manual dead zone, set per N64 controller + BYTE bRumbleStrength; // set per N64 controller + unsigned short nModifiers; // number of modifiers + + bool bRapidFireEnabled; + BYTE bRapidFireRate; + BYTE bRapidFireCounter; + + TCHAR szMempakFile[MAX_PATH+1]; // MemPak-FileName + TCHAR szTransferRom[MAX_PATH+1]; // GameBoyRom-Filename + TCHAR szTransferSave[MAX_PATH+1]; // GameBoyEEPRom-Filename + + BUTTON aButton[14+PF_AXESETS*4]; // Ten buttons, 4 d-pad directions times two (for Config 1 and Config 2) + + MODIFIER *pModifiers; // Array of Modifiers + + void *pPakData; // Pointer to Pak Data (specific): see PakIO.h + // pPakData->bPakType will always be a BYTE indicating what the current pak type is + + XCONTROLLER xiController; // To handle an XInput enabled controller --tecnicors +} CONTROLLER, *LPCONTROLLER; + +// This is the Index of WORD PROFILE.Button[X] + // Buttons: +#define PF_DPADR 0 +#define PF_DPADL 1 +#define PF_DPADD 2 +#define PF_DPADU 3 +#define PF_START 4 +#define PF_TRIGGERZ 5 +#define PF_BBUTTON 6 +#define PF_ABUTTON 7 +#define PF_CBUTTONR 8 +#define PF_CBUTTONL 9 +#define PF_CBUTTOND 10 +#define PF_CBUTTONU 11 +#define PF_TRIGGERR 12 +#define PF_TRIGGERL 13 + + // Analog Stick + // cause you can assign Buttons to it, I need 4 of 'em +#define PF_APADR 14 +#define PF_APADL 15 +#define PF_APADD 16 +#define PF_APADU 17 + + // second Set +// #define PF_APADR 18 +// #define PF_APADL 19 +// #define PF_APADD 20 +// #define PF_APADU 21 + + + + +// Data Format of DWORD Controller.Button: +// + +// BYTE bBtnType : Determines the Device and general Type of Control +// BYTE bAxisID : AxeIndentifier, Tells which range of the Axe/POV is important +// BYTE bOffset : Offset in the DirectInput data structure + +// BYTE bBtnType : Determines the Device and general Type of Control +#define DT_UNASSIGNED 0 + // Joystick +#define DT_JOYBUTTON 1 +#define DT_JOYAXE 2 +#define DT_JOYPOV 3 +#define DT_JOYSLIDER 4 + + // Keyboard +#define DT_KEYBUTTON 5 + + // Mouse +#define DT_MOUSEBUTTON 6 +#define DT_MOUSEAXE 7 + +// BYTE bAxisID : AxeIndentifier, Tells which range of the Axe/POV is important + + // Positive Range of an Axe +#define AI_AXE_P 0 + // Negative Range +#define AI_AXE_N 1 + + // Applies to POVs obviously +#define AI_POV_UP 0 +#define AI_POV_RIGHT 1 +#define AI_POV_DOWN 2 +#define AI_POV_LEFT 3 + +// BYTE bOffset : Offset in the DirectInput data structure + + +typedef union _MODSPEC_MOVE +{ + DWORD dwValue; + struct + { + short XModification; + short YModification; + }; +} MODSPEC_MOVE, *LPMODSPEC_MOVE; + +typedef union _MODSPEC_MACRO +{ + DWORD dwValue; + struct + { + unsigned short aButtons; + unsigned short aFlags; + }; + struct + { + unsigned fDigitalRight :1; + unsigned fDigitalLeft :1; + unsigned fDigitalDown :1; + unsigned fDigitalUp :1; + unsigned fStart :1; + unsigned fTriggerZ :1; + unsigned fBButton :1; + unsigned fAButton :1; + unsigned fCRight :1; + unsigned fCLeft :1; + unsigned fCDown :1; + unsigned fCUp :1; + unsigned fTriggerR :1; + unsigned fTriggerL :1; + unsigned :2; + + unsigned fAnalogRight :1; + unsigned fAnalogLeft :1; + unsigned fAnalogDown :1; + unsigned fAnalogUp :1; + unsigned fRapidFire :1; + unsigned fRapidFireRate :1; + unsigned fPrevFireState :1; + unsigned fPrevFireState2 :1; + }; +} MODSPEC_MACRO, *LPMODSPEC_MACRO; + +typedef union _MODSPEC_CONFIG +{ + DWORD dwValue; + struct + { + BYTE bAnalogStick; + BYTE bMouse; + BYTE bKeyboard; + }; + struct + { + unsigned fChangeAnalogConfig :1; + unsigned fAnalogStickMode :7; + unsigned fChangeMouseXAxis :1; + unsigned fChangeMouseYAxis :1; + unsigned :6; + unsigned fChangeKeyboardXAxis :1; + unsigned fChangeKeyboardYAxis :1; + unsigned :6; + + }; +} MODSPEC_CONFIG, *LPMODSPEC_CONFIG; + +#define SC_NOPAK 0 +#define SC_MEMPAK 1 +#define SC_RUMBPAK 2 +#define SC_TRANSPAK 3 +#define SC_VOICEPAK 4 +#define SC_ADAPTPAK 5 +#define SC_SWMEMRUMB 6 +#define SC_SWMEMADAPT 7 + + // total arraysize of aButtons in SHORTCUTSPL; + // make sure you update this if you change the list above +#define SC_TOTAL 8 + +typedef struct _SHORTCUTSPL +{ + BUTTON aButtons[SC_TOTAL]; + //BUTTON NoPakButton; + //BUTTON MemPakButton; + //BUTTON RumblePakButton; + //BUTTON TransferPakButton; + //BUTTON VoicePakButton; + //BUTTON AdaptoidPakButton; + //BUTTON SwMemRumbleButton; + //BUTTON SwMemAdaptoidButton; +} SHORTCUTSPL, *LPSHORTCUTSPL; + +typedef struct _SHORTCUTS +{ + SHORTCUTSPL Player[4]; + BUTTON bMouseLock; +} SHORTCUTS, *LPSHORTCUTS; + +typedef struct _MSHORTCUT { + int iControl; + int iShortcut; +} MSHORTCUT, *LPMSHORTCUT; // shortcut message + + +#define CHECK_WHITESPACES( str ) ( str == '\r' || str == '\n' || str == '\t' ) + + +extern HANDLE g_hHeap; +extern HMODULE g_hDirectInputDLL; +extern HMODULE g_hResourceDLL; +extern EMULATOR_INFO g_strEmuInfo; +extern TCHAR g_aszDefFolders[3][MAX_PATH]; +extern TCHAR g_aszLastBrowse[6][MAX_PATH]; +extern int g_nDevices; +extern DEVICE g_devList[MAX_DEVICES]; +extern DEVICE g_sysMouse; +extern CONTROLLER g_pcControllers[4]; +extern SHORTCUTS g_scShortcuts; +extern LPDIRECTINPUTDEVICE8 g_apFFDevice[4]; +extern LPDIRECTINPUTEFFECT g_apdiEffect[4]; +extern CRITICAL_SECTION g_critical; + +extern bool g_bRunning; +extern bool g_bConfiguring; +extern bool g_bExclusiveMouse; + +extern int g_iFirstController; + +int WarningMessage( UINT uTextID, UINT uType ); +int FindDeviceinList( const TCHAR *pszProductName, BYTE bProductCounter, bool fFindSimilar ); +int FindDeviceinList( REFGUID rGUID ); +void freePakData( CONTROLLER *pcController ); +void freeModifiers( CONTROLLER *pcController ); +void CheckShortcuts(); +bool ErrorMessage( UINT uID, DWORD dwError, bool fUserChoose ); + +#endif diff --git a/Source/nragev20/NRagePluginV2.rc b/Source/nragev20/NRagePluginV2.rc new file mode 100644 index 000000000..d47f92212 --- /dev/null +++ b/Source/nragev20/NRagePluginV2.rc @@ -0,0 +1,885 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_MAINCFGDIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 389 + TOPMARGIN, 7 + BOTTOMMARGIN, 279 + END + + IDD_CONTROLLER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 371 + TOPMARGIN, 7 + BOTTOMMARGIN, 227 + END + + IDD_SHORTCUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 369 + VERTGUIDE, 83 + VERTGUIDE, 146 + VERTGUIDE, 157 + VERTGUIDE, 219 + VERTGUIDE, 229 + VERTGUIDE, 292 + VERTGUIDE, 303 + VERTGUIDE, 365 + TOPMARGIN, 7 + BOTTOMMARGIN, 228 + HORZGUIDE, 25 + HORZGUIDE, 131 + HORZGUIDE, 195 + END + + IDD_CONTROLS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 363 + VERTGUIDE, 14 + VERTGUIDE, 176 + VERTGUIDE, 182 + VERTGUIDE, 188 + VERTGUIDE, 194 + VERTGUIDE, 356 + TOPMARGIN, 7 + BOTTOMMARGIN, 173 + END + + IDD_CONTROLLERPAK, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 363 + TOPMARGIN, 6 + BOTTOMMARGIN, 173 + END + + IDD_MODIFIER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 363 + VERTGUIDE, 203 + VERTGUIDE, 356 + TOPMARGIN, 7 + BOTTOMMARGIN, 173 + END + + IDD_PAK_MEMPAK, DIALOG + BEGIN + VERTGUIDE, 8 + VERTGUIDE, 143 + VERTGUIDE, 166 + VERTGUIDE, 347 + HORZGUIDE, 11 + HORZGUIDE, 29 + HORZGUIDE, 140 + END + + IDD_PAK_TRANSFER, DIALOG + BEGIN + VERTGUIDE, 8 + VERTGUIDE, 348 + HORZGUIDE, 8 + HORZGUIDE, 140 + END + + IDD_DEVICES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 363 + VERTGUIDE, 16 + VERTGUIDE, 169 + TOPMARGIN, 7 + BOTTOMMARGIN, 173 + END + + IDD_MOD_MOVE, DIALOG + BEGIN + BOTTOMMARGIN, 45 + END + + IDD_FOLDERS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 288 + TOPMARGIN, 7 + BOTTOMMARGIN, 199 + END + + "IDD_MAINCFGDIALOG$(_DEBUG)", DIALOG + BEGIN + LEFTMARGIN, 6 + RIGHTMARGIN, 389 + TOPMARGIN, 7 + BOTTOMMARGIN, 344 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +#if defined(APSTUDIO_INVOKED) || !defined(_DEBUG) +IDD_MAINCFGDIALOG DIALOGEX 0, 0, 396, 286 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "N-Rage Input V2 - Configuration" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CONTROL "PLACEHOLDER",IDC_UPPERTAB,"SysTabControl32",WS_GROUP | WS_TABSTOP,7,7,382,251 + LTEXT "VERSION PLACEHOLDER",IDC_VERSIONSTRING,7,265,82,14,SS_CENTERIMAGE | NOT WS_GROUP + COMBOBOX IDC_LANGUAGE,103,265,112,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "Save",IDSAVE,223,265,50,14,WS_GROUP + PUSHBUTTON "Use",IDUSE,281,265,50,14 + PUSHBUTTON "Cancel",IDCANCEL,339,265,50,14 +END +#endif + +IDD_CONTROLLER DIALOGEX 0, 0, 378, 234 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CONTROL "Plugged",IDC_PLUGGED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,45,13 + PUSHBUTTON "Clear Controller",IDC_CLEARCONTROLLER,63,7,67,13 + PUSHBUTTON "Default Config",IDC_SETDEFAULT,63,21,67,13 + PUSHBUTTON "Load Profile",IDC_LOADPROFILE,191,7,67,13 + PUSHBUTTON "Save Profile",IDC_SAVEPROFILE,272,7,67,13 + CONTROL "PLACEHOLDER",IDC_CONTROLLERTAB,"SysTabControl32",WS_GROUP | WS_TABSTOP,0,38,375,196 + CONTROL "XInput",IDC_XINPUT_ENABLER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,22,37,10 +END + +IDD_SHORTCUT DIALOGEX 0, 0, 376, 235 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + PUSHBUTTON "Load Shortcuts",IDC_LOADSHORTCUTS,142,7,67,13 + PUSHBUTTON "Save Shortcuts",IDC_SAVESHORTCUTS,221,7,67,13 + PUSHBUTTON "Default Config",IDC_SETDEFAULTSC,301,7,67,13 + LTEXT "Unplug ControllerPak",IDC_STATIC,7,38,68,18 + LTEXT "Insert MemPak",IDC_STATIC,7,59,68,18 + LTEXT "Insert RumblePak",IDC_STATIC,7,80,68,18 + LTEXT "Insert TransferPak",IDC_STATIC,7,101,68,18 + LTEXT "Direct AdaptoidPak",IDC_STATIC,7,122,68,18 + LTEXT "MemP <-> RumbleP",IDC_STATIC,7,143,68,18 + LTEXT "MemP <-> AdaptoidP",IDC_STATIC,7,164,68,18 + GROUPBOX "Player 1",IDC_STATIC,80,25,70,160 + PUSHBUTTON "PLACEHOLDER",IDC_SETNOPAK_P1,83,38,63,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETMEMPAK_P1,83,59,63,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETRUMBLEPAK_P1,83,80,63,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETTRANSFERPAK_P1,83,101,63,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETADAPTOIDPAK_P1,83,122,63,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SWMEMRUMBLE_P1,83,143,63,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SWMEMADAPTOID_P1,83,164,63,18,BS_MULTILINE + GROUPBOX "Player 2",IDC_STATIC,153,25,70,160 + PUSHBUTTON "PLACEHOLDER",IDC_SETNOPAK_P2,157,38,62,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETMEMPAK_P2,157,59,62,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETRUMBLEPAK_P2,157,80,62,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETTRANSFERPAK_P2,157,101,62,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETADAPTOIDPAK_P2,157,122,62,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SWMEMRUMBLE_P2,157,143,62,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SWMEMADAPTOID_P2,157,164,62,18,BS_MULTILINE + GROUPBOX "Player 3",IDC_STATIC,226,25,70,160 + PUSHBUTTON "PLACEHOLDER",IDC_SETNOPAK_P3,229,38,63,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETMEMPAK_P3,229,59,63,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETRUMBLEPAK_P3,229,80,63,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETTRANSFERPAK_P3,229,101,63,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETADAPTOIDPAK_P3,229,122,63,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SWMEMRUMBLE_P3,229,143,63,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SWMEMADAPTOID_P3,229,164,63,18,BS_MULTILINE + GROUPBOX "Player 4",IDC_STATIC,299,25,70,160 + PUSHBUTTON "PLACEHOLDER",IDC_SETNOPAK_P4,303,38,62,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETMEMPAK_P4,303,59,62,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETRUMBLEPAK_P4,303,80,62,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETTRANSFERPAK_P4,303,101,62,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SETADAPTOIDPAK_P4,303,122,62,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SWMEMRUMBLE_P4,303,143,62,18,BS_MULTILINE + PUSHBUTTON "PLACEHOLDER",IDC_SWMEMADAPTOID_P4,303,164,62,18,BS_MULTILINE + LTEXT "Lock/Unlock Mouse",IDC_STATIC,7,195,68,18,NOT WS_GROUP + PUSHBUTTON "PLACEHOLDER",IDC_LOCKMOUSE,83,195,63,18,BS_MULTILINE + CONTROL "Show messages",IDC_SHOWMESSAGES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,256,195,109,11 +END + +IDD_CONTROLS DIALOGEX 0, 0, 370, 180 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Digital Pad",IDC_STATIC,7,7,175,62 + PUSHBUTTON "Up",IDC_DUP,13,21,24,10,BS_NOTIFY | WS_GROUP + PUSHBUTTON "Left",IDC_DLEFT,13,32,24,10,BS_NOTIFY + PUSHBUTTON "Right",IDC_DRIGHT,13,43,24,10,BS_NOTIFY + PUSHBUTTON "Down",IDC_DDOWN,13,54,24,10,BS_NOTIFY + CTEXT "PLACEHOLDER",IDT_DUP,39,21,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_DLEFT,39,32,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_DRIGHT,39,43,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_DDOWN,39,54,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + GROUPBOX "Buttons",IDC_STATIC,7,70,175,97 + PUSHBUTTON "Start",IDC_SBUTTON,14,82,24,10,BS_NOTIFY | WS_GROUP + PUSHBUTTON "A",IDC_ABUTTON,14,93,24,10,BS_NOTIFY + PUSHBUTTON "B",IDC_BBUTTON,14,104,24,10,BS_NOTIFY + PUSHBUTTON "L-Trig",IDC_LEFTTRIGGER,14,115,24,10,BS_NOTIFY + PUSHBUTTON "R-Trig",IDC_RIGHTTRIGGER,14,126,24,10,BS_NOTIFY + PUSHBUTTON "Z-Trig",IDC_ZTRIGGER,14,137,24,10,BS_NOTIFY + CTEXT "PLACEHOLDER",IDT_SBUTTON,39,82,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_ABUTTON,39,93,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_BBUTTON,39,104,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_LEFTTRIGGER,39,115,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_RIGHTTRIGGER,39,126,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_ZTRIGGER,39,137,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + CONTROL "Rapid Fire",IDC_RAPIDFIREENABLE,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,14,150,47,12 + CONTROL "PLACEHOLDER",IDC_RAPIDFIRERATE,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,61,150,115,12 + GROUPBOX "C Buttons",IDC_STATIC,188,7,175,62 + PUSHBUTTON "Up",IDC_CUP,193,21,24,10,BS_NOTIFY | WS_GROUP + PUSHBUTTON "Left",IDC_CLEFT,193,32,24,10,BS_NOTIFY + PUSHBUTTON "Right",IDC_CRIGHT,193,43,24,10,BS_NOTIFY + PUSHBUTTON "Down",IDC_CDOWN,193,54,24,10,BS_NOTIFY + CTEXT "PLACEHOLDER",IDT_CUP,219,21,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_CLEFT,219,32,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_CRIGHT,219,43,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_CDOWN,219,54,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE + GROUPBOX "Analog Stick",IDC_STATIC,188,70,175,97 + CTEXT "R PLACEHOLDER",IDT_RANGE,194,81,110,8 + CONTROL "PLACEHOLDER",IDC_CTRRANGE,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,194,89,113,11 + CONTROL "Real N64 Range",IDC_N64RANGE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_GROUP | WS_TABSTOP,312,82,44,19 + CONTROL "Config 1",IDC_CONFIG1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,194,103,42,10 + CONTROL "Config 2",IDC_CONFIG2,"Button",BS_AUTORADIOBUTTON,254,103,42,10 + PUSHBUTTON "Up",IDC_AUP,194,119,24,10,BS_NOTIFY | WS_GROUP + PUSHBUTTON "Left",IDC_ALEFT,194,130,24,10,BS_NOTIFY + PUSHBUTTON "Right",IDC_ARIGHT,194,141,24,10,BS_NOTIFY + PUSHBUTTON "Down",IDC_ADOWN,194,152,24,10,BS_NOTIFY + CTEXT "PLACEHOLDER",IDT_AUP,219,119,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_ALEFT,219,130,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_ARIGHT,219,141,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_ADOWN,219,152,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE +END + +IDD_CONTROLLERPAK DIALOGEX 0, 0, 370, 180 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CONTROL "RawData",IDC_RAWMODE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,6,46,12 + COMBOBOX IDC_PAKTYPE,70,6,109,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "PLACEHOLDER",IDC_PAKAREA,7,25,356,148 +END + +IDD_MODIFIER DIALOGEX 0, 0, 370, 180 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + PUSHBUTTON "New Modifier",IDC_NEWMODIFIER,7,7,54,14,WS_GROUP + PUSHBUTTON "Delete Modifier",IDC_KILLMODIFIER,69,7,54,14 + CONTROL "PLACEHOLDER",IDC_MODIFIERLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,27,183,146 + GROUPBOX "Adjust Modifier",IDC_STATIC,197,7,166,166 + PUSHBUTTON "Assign Mod",IDC_ASSIGNMOD,203,20,42,11 + LTEXT "B",IDT_ASSIGNMOD,245,20,111,11,SS_SUNKEN + CTEXT "Mod Type",IDT_MODTYP,203,35,42,12,SS_CENTERIMAGE + COMBOBOX IDC_MODTYP,245,35,57,98,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "Toggle",IDC_TOGGLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,305,35,36,12 + CONTROL "",IDC_STATE,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,345,35,10,12 + LTEXT "Prop modifier PLACEHOLDER",IDC_PROPWINDOW,203,52,153,99,NOT WS_VISIBLE | WS_TABSTOP + PUSHBUTTON "Apply Changes",IDC_APPCHANGES,205,157,73,11 + PUSHBUTTON "Reset",IDC_RESET,311,157,45,11 +END + +IDD_PAK_MEMPAK DIALOGEX 0, 0, 356, 148 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Current MemPak Directory",IDC_STATIC,0,0,151,148 + PUSHBUTTON "Change MemPak Directory",IDC_CHGDIR,8,12,135,11,WS_GROUP + LISTBOX IDC_MEMPAKLIST,8,29,135,91,LBS_SORT | LBS_NOINTEGRALHEIGHT | NOT WS_BORDER | WS_VSCROLL | WS_GROUP | WS_TABSTOP,WS_EX_CLIENTEDGE + PUSHBUTTON "New MemPak / Browse",IDC_BROWSE,8,123,54,20,BS_MULTILINE | WS_GROUP + PUSHBUTTON "Delete MemPak",IDC_DELMEMPAK,99,123,44,20,BS_MULTILINE + GROUPBOX "MemPak Content",IDC_STATIC,158,0,198,148 + PUSHBUTTON "Format MemPak",IDC_FORMATMEMPAK,167,11,35,18,BS_MULTILINE | WS_GROUP + PUSHBUTTON "Save Note",IDC_SAVENOTE,215,11,35,18,BS_MULTILINE + PUSHBUTTON "Insert Note",IDC_INSERTNOTE,263,11,35,18,BS_MULTILINE + PUSHBUTTON "Delete Note",IDC_DELETENOTE,311,11,35,18,BS_MULTILINE + CONTROL "PLACEHOLDER",IDC_MEMPAKBROWSER,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_NOLABELWRAP | LVS_NOSORTHEADER | WS_GROUP | WS_TABSTOP,166,29,181,91,WS_EX_CLIENTEDGE + CTEXT "Static",IDT_MEMPAKSTATE,166,120,181,20,NOT WS_GROUP,WS_EX_CLIENTEDGE +END + +IDD_PAK_TRANSFER DIALOGEX 0, 0, 356, 148 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + PUSHBUTTON "Change GB-Directories",IDC_CHGDIR,0,0,94,11,WS_GROUP + GROUPBOX "GB Rom File",IDC_STATIC,0,18,355,63 + EDITTEXT IDC_GBROM_EDIT,8,44,291,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse",IDC_GBROM_BROWSE,309,43,39,14,BS_MULTILINE + GROUPBOX "GB Rom Save",IDC_STATIC,0,86,355,62 + EDITTEXT IDC_GBSAVE_EDIT,8,111,291,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse",IDC_GBSAVE_BROWSE,309,110,39,14,BS_MULTILINE +END + +IDD_PAK_ADAPTOID DIALOGEX 0, 0, 356, 148 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CTEXT "Adaptoid Pak will communicate directly with any Pak you insert into the Controller. ",IDT_PAKDESC,95,34,165,19 + LTEXT "If you want to use regular DirectInput force-feedback, choose RumblePak instead.",IDC_STATIC,95,90,165,22 +END + +IDD_DEVICES DIALOGEX 0, 0, 370, 180 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 400, 0, 0x0 +BEGIN + GROUPBOX "Mouse",IDC_STATIC,7,7,171,85 + LTEXT "MSX PLACEHOLDER",IDT_MSSENSITIVITY_X,16,18,153,8,NOT WS_GROUP + CONTROL "Slider3",IDC_MSSENSITIVITY_X,"msctls_trackbar32",WS_GROUP | WS_TABSTOP,16,26,153,11 + CONTROL "Deadpan",IDC_DEADPANMOUSEX,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,32,39,45,10 + CONTROL "Buffered",IDC_BUFFEREDMOUSEX,"Button",BS_AUTORADIOBUTTON,80,39,43,10 + CONTROL "Absolute",IDC_ABSOLUTEMOUSEX,"Button",BS_AUTORADIOBUTTON,126,39,43,10 + LTEXT "MSY PLACEHOLDER",IDT_MSSENSITIVITY_Y,16,56,153,8,NOT WS_GROUP + CONTROL "",IDC_MSSENSITIVITY_Y,"msctls_trackbar32",WS_TABSTOP,16,65,153,11 + CONTROL "Deadpan",IDC_DEADPANMOUSEY,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,32,78,45,10 + CONTROL "Buffered",IDC_BUFFEREDMOUSEY,"Button",BS_AUTORADIOBUTTON,80,78,43,10 + CONTROL "Absolute",IDC_ABSOLUTEMOUSEY,"Button",BS_AUTORADIOBUTTON,126,78,43,10 + GROUPBOX "Keyboard",IDC_STATIC,7,96,171,27 + CONTROL "Absolute X",IDC_ACCELERATEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,107,50,10 + CONTROL "Absolute Y",IDC_ACCELERATEY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,107,50,10 + GROUPBOX "GamePad",IDC_STATIC,7,124,171,38 + CTEXT "Deadzone PLACEHOLDER",IDT_DEADZONE,16,134,153,8 + CONTROL "PLACEHOLDER",IDC_DEADZONE,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,16,144,153,11 +END + +IDD_PAK_TEXT DIALOGEX 0, 0, 356, 148 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CTEXT "PLACEHOLDER",IDT_PAKDESC,56,45,243,57 +END + +IDD_MOD_MOVE DIALOGEX 0, 0, 153, 99 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + GROUPBOX "X-Axis",IDC_STATIC,0,4,153,40 + LTEXT "MOV_PLACEHOLDER",IDT_XMODIFIER,8,15,89,8 + CONTROL "Invert",IDC_XNEGATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,15,34,10 + CONTROL "PLACEHOLDER",IDC_XMODIFIER,"msctls_trackbar32",WS_TABSTOP,8,26,136,12 + GROUPBOX "Y-Axis",IDC_STATIC,0,53,153,40 + LTEXT "MOV_PLACEHOLDER",IDT_YMODIFIER,8,64,89,8 + CONTROL "Invert",IDC_YNEGATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,110,64,34,10 + CONTROL "PLACEHOLDER",IDC_YMODIFIER,"msctls_trackbar32",WS_TABSTOP,8,75,136,12 +END + +IDD_FOLDERS DIALOGEX 50, 50, 295, 206 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + GROUPBOX "MemPak Directory",IDC_MEMPAKPANEL,7,7,281,49 + CONTROL "$AppPath\\",IDC_MEMPAK_REL,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,19,54,12 + CONTROL "",IDC_MEMPAK_ABS,"Button",BS_AUTORADIOBUTTON,13,36,16,12 + EDITTEXT IDC_MEMPAK_REL_EDIT,67,19,199,12,ES_AUTOHSCROLL | WS_GROUP + PUSHBUTTON "...",IDC_MEMPAK_BROWSE_REL,269,19,11,12 + EDITTEXT IDC_MEMPAK_ABS_EDIT,30,36,236,12,ES_AUTOHSCROLL | WS_GROUP + PUSHBUTTON "...",IDC_MEMPAK_BROWSE_ABS,269,36,11,12 + GROUPBOX "GameBoy Rom Directory",IDC_GBROMPANEL,7,60,281,49 + CONTROL "$AppPath\\",IDC_GBROM_REL,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,73,54,12 + CONTROL "",IDC_GBROM_ABS,"Button",BS_AUTORADIOBUTTON,13,90,16,12 + EDITTEXT IDC_GBROM_REL_EDIT,67,73,199,12,ES_AUTOHSCROLL | WS_GROUP + PUSHBUTTON "...",IDC_GBROM_BROWSE_REL,269,73,11,12 + EDITTEXT IDC_GBROM_ABS_EDIT,30,90,236,12,ES_AUTOHSCROLL | WS_GROUP + PUSHBUTTON "...",IDC_GBROM_BROWSE_ABS,269,90,11,12 + GROUPBOX "GameBoy Save Directory",IDC_GBSAVEPANEL,7,114,281,67 + CONTROL "Same Directory as GameBoy Roms",IDC_GBSAVE_SAME,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,127,128,12 + CONTROL "$AppPath\\",IDC_GBSAVE_REL,"Button",BS_AUTORADIOBUTTON,13,144,54,12 + CONTROL "",IDC_GBSAVE_ABS,"Button",BS_AUTORADIOBUTTON,13,161,16,12 + EDITTEXT IDC_GBSAVE_REL_EDIT,67,144,199,12,ES_AUTOHSCROLL | WS_GROUP + PUSHBUTTON "...",IDC_GBSAVE_BROWSE_REL,269,144,11,12 + EDITTEXT IDC_GBSAVE_ABS_EDIT,30,161,236,12,ES_AUTOHSCROLL | WS_GROUP + PUSHBUTTON "...",IDC_GBSAVE_BROWSE_ABS,269,161,11,12 + DEFPUSHBUTTON "OK",IDOK,181,185,50,14 + PUSHBUTTON "Cancel",IDCANCEL,238,185,50,14 +END + +IDD_MOD_MACRO DIALOGEX 0, 0, 153, 98 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CONTROL "L-Trigger",IDC_LTRIG,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,15,3,45,10 + CONTROL "",IDC_ZTRIG,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,71,5,16,8 + CONTROL "R-Trigger",IDC_RTRIG,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_FLAT | WS_TABSTOP,91,3,45,10 + GROUPBOX "D-Pad",IDC_STATIC,15,14,40,41 + CONTROL "",IDC_DUP,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,31,27,9,8 + CONTROL "",IDC_DLEFT,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,21,35,9,8 + CONTROL "",IDC_DRIGHT,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,41,35,9,8 + CONTROL "",IDC_DDOWN,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,31,43,9,8 + CTEXT "Z-Trigger",IDC_STATIC,56,14,38,10 + CONTROL "Start",IDC_SBUTTON,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,60,28,31,10 + GROUPBOX "Analog",IDC_STATIC,55,38,40,41 + CONTROL "",IDC_AUP,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,71,51,9,8 + CONTROL "",IDC_ALEFT,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,61,59,9,8 + CONTROL "",IDC_ARIGHT,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,81,59,9,8 + CONTROL "",IDC_ADOWN,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,71,67,9,8 + GROUPBOX "C-Buttons",IDC_STATIC,95,14,40,41 + CONTROL "",IDC_CUP,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,111,27,9,8 + CONTROL "",IDC_CLEFT,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,101,35,9,8 + CONTROL "",IDC_CRIGHT,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,121,35,9,8 + CONTROL "",IDC_CDOWN,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,111,43,9,8 + CONTROL "B",IDC_BBUTTON,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,101,59,21,10 + CONTROL "A",IDC_ABUTTON,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_FLAT | WS_TABSTOP,101,70,21,10 + CONTROL "Rapid Fire",IDC_RAPIDFIREMODE,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | BS_MULTILINE | WS_TABSTOP,15,57,38,22 + CONTROL "Slow Rapid Fire (Paper Mario, etc..)",IDC_RAPIDFIREMODERATE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,82,120,11 +END + +IDD_MOD_CONFIG DIALOGEX 0, 0, 153, 99 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + GROUPBOX "Analog Stick",IDC_STATIC,0,0,153,37 + RADIOBUTTON "Config 1",IDC_CONFIG1,7,10,42,10,WS_GROUP | WS_TABSTOP + RADIOBUTTON "Config 2",IDC_CONFIG2,55,10,42,10 + RADIOBUTTON "Cycle through Configurations",IDC_CONFIGCYCLE,7,22,106,10 + GROUPBOX "Mouse",IDC_STATIC,0,39,153,28 + CONTROL "Switch X-Mode",IDC_MOUSEX,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,7,50,64,10 + CONTROL "Switch Y-Mode",IDC_MOUSEY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,81,50,64,10 + GROUPBOX "Keyboard",IDC_STATIC,0,71,153,28 + CONTROL "Switch X-Mode",IDC_KEYX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,82,64,10 + CONTROL "Switch Y-Mode",IDC_KEYY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,81,82,64,10 +END + +#if defined(APSTUDIO_INVOKED) || defined(_DEBUG) +#if defined(APSTUDIO_INVOKED) +IDD_MAINCFGDIALOG$(_DEBUG) DIALOGEX 0, 0, 396, 351 +#else +IDD_MAINCFGDIALOG DIALOGEX 0, 0, 396, 351 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "N-Rage Input V2 - Configuration" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "RomID:",IDC_ROMID,6,7,66,8,NOT WS_GROUP + LTEXT "Description:",-1,82,7,38,8,NOT WS_GROUP + EDITTEXT IDC_ROMDESC,138,7,121,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + RTEXT "VERSION PLACEHOLDER",IDC_VERSIONSTRING,274,7,115,10,SS_CENTERIMAGE + COMBOBOX IDC_LANGUAGE,6,25,125,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + CONTROL "PLACEHOLDER",IDC_UPPERTAB,"SysTabControl32",WS_GROUP | WS_TABSTOP,6,93,383,251 + PUSHBUTTON "Save",IDSAVE,339,36,50,14,WS_GROUP + PUSHBUTTON "Use",IDUSE,339,55,50,14 + PUSHBUTTON "Cancel",IDCANCEL,339,73,50,14 +END +#endif + +IDD_PAK_RUMBLE DIALOGEX 0, 0, 356, 148 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + LTEXT "Force-Feedback Device",IDC_STATIC,22,18,124,8,NOT WS_GROUP + COMBOBOX IDC_CTRDEVICE,27,29,127,119,CBS_DROPDOWNLIST | WS_VSCROLL | WS_GROUP | WS_TABSTOP + CONTROL "Constant Force",IDC_RUMBLE1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,29,58,64,10 + CONTROL "Ramp Force",IDC_RUMBLE2,"Button",BS_AUTORADIOBUTTON,29,70,55,10 + CONTROL "Direct Rumble",IDC_RUMBLE3,"Button",BS_AUTORADIOBUTTON,29,82,61,10 + CONTROL "Visual Rumble",IDC_VISUALRUMBLE,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,99,58,61,10 + CTEXT "Rumble Strength PLACEHOLDER",IDT_RUMBLESTRENGTH,29,100,127,8,NOT WS_GROUP + CONTROL "",IDC_RUMBLESTRENGTH,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,29,112,127,11 + PUSHBUTTON "Test Rumble",IDC_RUMBLETEST,221,59,73,28,WS_DISABLED | WS_GROUP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2,3,0,2 + PRODUCTVERSION 2,3,0,2 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Comments", "Release Version" + VALUE "FileDescription", "Zilmar Spec Plugin for N64 Emulators" + VALUE "FileVersion", "2.3c" + VALUE "InternalName", "NRage_Input_V2" + VALUE "LegalCopyright", "Copyright © 2001-2011 N-Rage, compiled under GPL licensing" + VALUE "OriginalFilename", "NRage_Input_V2.dll" + VALUE "ProductName", "NRage_Input_V2" + VALUE "ProductVersion", "2.3c" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// PROFILE +// + +IDR_PROFILE_DEFAULT1 PROFILE "configs\\Controller1.cpf" + +///////////////////////////////////////////////////////////////////////////// +// +// SHORTCUT +// + +IDR_SHORTCUTS_DEFAULT SHORTCUT "configs\\Shortcuts.sc" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_ERR_DINOTFOUND "dinput8.dll could not be found.\nPlease reinstall the latest version of DirectX." + IDS_ERR_DICREATE "Could not create DirectInput object." + IDS_DLG_MPCHOOSE "Choose a MemPak or type a new name to create one." +END + +STRINGTABLE +BEGIN + IDS_ERR_MPREAD "Couldn't read MemPak." + IDS_ERR_GBROM "Can't open GB ROM file!" + IDS_ERR_GBSRAMERR "Can't open SRAM file!\nContinuing with null savedata." + IDS_VERSTRING "Version %s" + IDS_TAB_CONTROLLER "Controller %i" + IDS_TAB_SHORTCUTS "Shortcuts" + IDS_TAB_CONTROLS "Controls" + IDS_TAB_DEVICES "Devices" + IDS_TAB_MODIFIERS "Modifiers" + IDS_TAB_CONTROLLERPAK "Controller Pak" + IDS_DLG_CLEAR "The current controller configuration will be discarded.\nAre you sure?" + IDS_DLG_CLEAR_TITLE "Clear Controller" + IDS_DLG_CONTROLRESTORE "The default controller configuration will be restored.\nAre you sure?" + IDS_DLG_CONTROLRESTORE_TITLE "Restore Default" + IDS_ERR_PROFWRITE "Couldn't write profile." + IDS_ERR_PROFREAD "Couldn't read profile." +END + +STRINGTABLE +BEGIN + IDS_C_POLLING "...Awaiting Input %i..." + IDS_C_RANGE "Range: %i%%" + IDS_D_MSX "Mouse Sensitivity X: %i%%" + IDS_D_MSY "Mouse Sensitivity Y: %i%%" + IDS_D_DEADZONE "Deadzone: %i%%" + IDS_D_RUMBLESTR "Rumble Strength: %i%%" + IDS_M_MOVEVALUE "Movement Value: %i%%" + IDS_M_TAB_NONE "None" + IDS_M_TAB_MOVE "Move" + IDS_M_TAB_MACRO "Macro" + IDS_M_TAB_CONFIG "Config" + IDS_M_MOUSE_PREFIX "Ms-" + IDS_M_KB_PREFIX "Kb-" + IDS_M_NONE "None" + IDS_M_MOVE "Movement" + IDS_M_MACRO "Macro" +END + +STRINGTABLE +BEGIN + IDS_M_CONFIG "Configuration" + IDS_M_ASSIGNED "Assigned to" + IDS_M_TYPE "Type" + IDS_M_PARAM "Parameter" + IDS_P_NONE "None" + IDS_P_MEMPAK "Mem Pak" + IDS_P_RUMBLEPAK "Rumble Pak" + IDS_P_TRANSFERPAK "Transfer Pak" + IDS_P_VOICEPAK "Voice Pak" + IDS_P_ADAPTOIDPAK "Adaptoid Pak" + IDS_P_MEM_NORAW "The MemPak will be handled by the emulator." + IDS_P_RUMBLE_NORAW "The RumblePak will be handled by the emulator.\n\nYou won't get force-feedback;\n the emulator may use its own method (i.e. visual), or it might do nothing at all." + IDS_P_RUMBLE_RAW "You can choose different rumble types\n and adjust rumble strength in the Devices tab." + IDS_P_TRANSFER_NORAW "The TransferPak will be handled by the emulator.\n\nWill very likely do nothing (no emulator can handle this yet)." + IDS_P_VOICE_RAW "Isn't emulated by this plugin\n and likely won't ever be." + IDS_P_ADAPTOID_NORAW "The AdaptoidPak needs RawMode to be activated." +END + +STRINGTABLE +BEGIN + IDS_P_NONE_RAWNORAW "No Pak inserted." + IDS_P_MEM_NOCHANGE "Can't change dir while running." + IDS_P_MEM_NAME "Name" + IDS_P_MEM_REGION "Region" + IDS_P_MEM_BLOCKS "Blocks" + IDS_DLG_DELETEPAK "Do you really want to delete that MemPak?" + IDS_DLG_FORMATPAK "Do you really want to format the MemPak?" + IDS_DLG_DELETENOTE "Do you really want to delete this note?" + IDS_P_MEM_BLOCKSFREE "%i blocks free." + IDS_P_MEM_INUSE "%i blocks free.\nMemPak is currently in use by the emulator." + IDS_P_MEM_WRONGSIZE "%i blocks free.\nMemPak has wrong filesize and may be damaged." + IDS_P_MEM_NONESELECTED "No MemPak selected." + IDS_P_MEM_DAMAGED "MemPak is damaged.\nFormat is necessary." + IDS_BUTTON_UNASSIGNED "Unassigned" + IDS_ERR_SHORTREAD "Couldn't read shortcuts file." + IDS_DLG_SHORTCUTRESTORE "The shortcut configuration will be restored.\nAre you sure?" +END + +STRINGTABLE +BEGIN + IDS_DLG_SHORTCUTRESTORE_TITLE "Restore default" + IDS_C_GAMEPAD "Gamepad: " + IDS_C_KEYBOARD "Keyboard: " + IDS_C_MOUSE "Mouse: " + IDS_C_XAXIS "X-axis" + IDS_C_YAXIS "Y-axis" + IDS_C_ZAXIS "Z-axis" + IDS_C_XROT "X-rotation" + IDS_C_YROT "Y-rotation" + IDS_C_ZROT "Z-rotation" + IDS_C_SLIDER "Slider %i" + IDS_C_POV "PoV %i" + IDS_C_BUTTON "Button " + IDS_C_WHEEL "Wheel" + IDS_C_UNKNOWN "???" + IDS_DLG_ABOUT "Help us translate N-Rage Input V2 into your language!" +END + +STRINGTABLE +BEGIN + IDS_DLG_ABOUT_TITLE "About N-Rage Input V2" + IDS_ERR_NOINIT "Plugin didn't get initialized!" + IDS_POP_MOUSEUNLOCKED "Mouse Unlocked" + IDS_POP_MOUSELOCKED "Mouse Locked" + IDS_POP_CHANGEPAK "Player %i:\nPak changed to %s" + IDS_ERR_MAPVIEW "Couldn't MapViewOfFile" + IDS_DLG_CPF "Controller Profile (*.cpf)\0*.cpf" + IDS_DLG_MPKN64 "MemPak (*.mpk)\0*.mpk\0Dexdrive Save (*.n64)\0*.n64" + IDS_DLG_A64 "MemPak Note (*.a64)\0*.a64" + IDS_DLG_GBGBC "GameBoy ROM (*.gb;*.gbc)\0*.gb;*.gbc" + IDS_DLG_SVSAV "GameBoy Save (*.sv;*.sav)\0*.sv;*.sav" + IDS_ERR_HANDLER "%s\n\n Error description: " + IDS_ERR_MEM_NOSPEC "No MemPak specified; please configure plugin." + IDS_DLG_MEM_READONLY "Mempak %s opened with read-only access.\nAfter exiting the game, the MemPak will NOT be saved." + IDS_ERR_MEMOPEN "Unable to read or create MemPak file %s ; please configure plugin." + IDS_DLG_MEM_BADADDRESSCRC + "Bad AddressCRC detected!\nThis usually indicates a bad ROM.\n\nIgnore it and continue?" +END + +STRINGTABLE +BEGIN + IDS_P_MEM_NOREGION "None" + IDS_P_MEM_BETA "Beta" + IDS_P_MEM_NTSC "NTSC" + IDS_P_MEM_GERMANY "Germany" + IDS_P_MEM_USA "USA" + IDS_P_MEM_FRANCE "France" + IDS_P_MEM_ITALY "Italy" + IDS_P_MEM_JAPAN "Japan" + IDS_P_MEM_EUROPE "Europe" + IDS_P_MEM_SPAIN "Spain" + IDS_P_MEM_AUSTRALIA "Australia" + IDS_P_MEM_PAL "PAL" + IDS_P_MEM_UNKNOWNREGION "Unknown(%02X)" + IDS_ERR_NOTEWRITE "Couldn't write note file." + IDS_ERR_MEMPAK_SPACE "Not enough space on MemPak." + IDS_ERR_MEMPAK_NONOTES "No free notes on MemPak (only 16 notes available per pak)." +END + +STRINGTABLE +BEGIN + IDS_ERR_NOTEEOF "Error reading note file: unexpected end of file or read error." + IDS_ERR_NOTEREAD "Couldn't read note file." + IDS_ERR_TITLE "N-Rage Input V2 Error" + IDS_DLG_MSG_TITLE "N-Rage Input V2 Message" + IDS_DLG_WARN_TITLE "N-Rage Input V2 Warning" + IDS_PLUGIN_TITLE "N-Rage Input V2" + IDS_ERR_MPCREATE "Couldn't create MemPak." + IDS_DLG_SC "Shortcuts File (*.sc)\0*.sc" + IDS_P_MEM_ERROR "ErrorCode %lu: " + IDS_P_R_NODEVICE "None" + IDS_P_TRANS_NOCHANGE "Can't change paks while running" + IDS_DLG_TPAK_READONLY "SRAM opened with read-only access.\nAfter exiting the game, the SRAM will NOT be saved." + IDS_P_SWITCHING "Switching paks..." +END + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Chile) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESL) +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_CHILE +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_XCONTROLS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 363 + VERTGUIDE, 14 + VERTGUIDE, 50 + VERTGUIDE, 56 + VERTGUIDE, 95 + VERTGUIDE, 101 + VERTGUIDE, 137 + VERTGUIDE, 143 + VERTGUIDE, 182 + VERTGUIDE, 188 + VERTGUIDE, 194 + VERTGUIDE, 256 + VERTGUIDE, 262 + VERTGUIDE, 356 + TOPMARGIN, 7 + BOTTOMMARGIN, 173 + HORZGUIDE, 27 + HORZGUIDE, 35 + HORZGUIDE, 41 + HORZGUIDE, 53 + HORZGUIDE, 59 + HORZGUIDE, 71 + HORZGUIDE, 77 + HORZGUIDE, 88 + HORZGUIDE, 95 + HORZGUIDE, 107 + HORZGUIDE, 112 + HORZGUIDE, 124 + HORZGUIDE, 130 + HORZGUIDE, 142 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_XCONTROLS DIALOGEX 0, 0, 370, 180 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "XInput Controller (X360 Controllers) configuration",IDC_XINPUT_TITLE,7,7,160,8 + CTEXT "N64",IDC_STATIC,56,27,39,8 + CTEXT "A",IDC_STATIC,14,41,36,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_A,56,41,39,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "B",IDC_STATIC,14,59,36,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_B,56,59,39,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "X",IDC_STATIC,14,77,36,11,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_X,56,77,39,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "Y",IDC_STATIC,14,95,36,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_Y,56,95,39,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "Back",IDC_STATIC,14,112,36,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_BACK,56,112,39,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "Start",IDC_STATIC,14,130,36,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_START,56,130,39,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "LB",IDC_STATIC,101,41,36,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_LB,143,41,39,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "RB",IDC_STATIC,101,59,36,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_RB,143,59,39,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "XControl",IDC_STATIC,101,27,36,8 + CTEXT "N64",IDC_STATIC,143,27,39,8 + CTEXT "LThSB",IDC_STATIC,101,76,36,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_LTSB,143,77,39,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "RThSB",IDC_STATIC,101,94,36,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_RTSB,143,95,39,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "LT",IDC_STATIC,101,112,36,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_LT,143,112,39,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "RT",IDC_STATIC,101,130,36,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_RT,143,130,39,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + GROUPBOX "D-Pad and Thumbsticks configuration",IDC_STATIC,188,27,175,115 + CTEXT "Left Thumbstick",IDC_STATIC,194,65,62,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + CTEXT "Right Thumbstick",IDC_STATIC,194,89,62,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + CTEXT "D-Pad",IDC_STATIC,194,112,62,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + COMBOBOX IDC_XC_LTS,262,65,94,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_XC_RTS,262,88,94,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_XC_DPAD,262,112,94,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CTEXT "XControl",IDC_STATIC,194,45,62,8 + CTEXT "N64",IDC_STATIC,262,45,94,8 + LTEXT "NOTE: LThSB and RThSB stands for Left/Right Thumbstick button respectively.",IDC_STATIC,14,155,349,18 + CTEXT "XControl",IDC_STATIC,14,27,36,8 + PUSHBUTTON "Save",IDC_XC_USE,306,159,50,14 +END + +#endif // Spanish (Chile) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Source/nragev20/NRage_Input_V2.vcproj b/Source/nragev20/NRage_Input_V2.vcproj new file mode 100644 index 000000000..55ac4e402 --- /dev/null +++ b/Source/nragev20/NRage_Input_V2.vcproj @@ -0,0 +1,275 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/nragev20/PakIO.cpp b/Source/nragev20/PakIO.cpp new file mode 100644 index 000000000..3039749ab --- /dev/null +++ b/Source/nragev20/PakIO.cpp @@ -0,0 +1,1496 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "commonIncludes.h" +#include +#include +#include +#include +#include "NRagePluginV2.h" +#include "DirectInput.h" +#include "Interface.h" +#include "FileAccess.h" +#include "PakIO.h" +#include "GBCart.h" + +// ProtoTypes +BYTE AddressCRC( const unsigned char * Address ); +BYTE DataCRC( const unsigned char * Data, const int iLength ); +VOID CALLBACK WritebackProc( HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime ); + +bool InitControllerPak( const int iControl ) +// Prepares the Pak +{ + if( !g_pcControllers[iControl].fPlugged ) + return false; + bool bReturn = false; + if( g_pcControllers[iControl].pPakData ) + { + SaveControllerPak( iControl ); + CloseControllerPak( iControl ); + } + + switch( g_pcControllers[iControl].PakType ) + { + case PAK_MEM: + { + g_pcControllers[iControl].pPakData = P_malloc( sizeof(MEMPAK)); + MEMPAK *mPak = (MEMPAK*)g_pcControllers[iControl].pPakData; + mPak->bPakType = PAK_MEM; + mPak->fReadonly = false; + mPak->fDexSave = false; + mPak->hMemPakHandle = NULL; + + DWORD dwFilesize = PAK_MEM_SIZE; // expected file size + TCHAR szBuffer[MAX_PATH+1], + szFullPath[MAX_PATH+1], + *pcFile; + + GetAbsoluteFileName( szBuffer, g_pcControllers[iControl].szMempakFile, DIRECTORY_MEMPAK ); + GetFullPathName( szBuffer, sizeof(szFullPath) / sizeof(TCHAR), szFullPath, &pcFile ); + + bool isNewfile = !CheckFileExists( szBuffer ); + + if( pcFile == NULL ) + { // no Filename specified + WarningMessage( IDS_ERR_MEM_NOSPEC, MB_OK | MB_ICONWARNING ); + g_pcControllers[iControl].PakType = PAK_NONE; + break; // memory is freed at the end of this function + } + + TCHAR *pcPoint = _tcsrchr( pcFile, '.' ); + if( !lstrcmpi( pcPoint, _T(".n64") ) ) + { + mPak->fDexSave = true; + dwFilesize += PAK_MEM_DEXOFFSET; + } + else + { + mPak->fDexSave = false; + } + + HANDLE hFileHandle = CreateFile( szFullPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL ); + if( hFileHandle == INVALID_HANDLE_VALUE ) + {// test if Read-only access is possible + hFileHandle = CreateFile( szFullPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL ); + if( hFileHandle != INVALID_HANDLE_VALUE ) + { + TCHAR tszTitle[DEFAULT_BUFFER], tszText[DEFAULT_BUFFER]; + + LoadString( g_hResourceDLL, IDS_DLG_MEM_READONLY, tszText, DEFAULT_BUFFER ); + LoadString( g_hResourceDLL, IDS_DLG_WARN_TITLE, tszTitle, DEFAULT_BUFFER ); + wsprintf( szBuffer, tszText, pcFile ); + MessageBox( g_strEmuInfo.hMainWindow, szBuffer, tszTitle, MB_OK | MB_ICONWARNING ); + mPak->fReadonly = true; + DebugWriteA("Ramfile opened in READ ONLY mode.\n"); + } + else + { + TCHAR tszTitle[DEFAULT_BUFFER], tszText[DEFAULT_BUFFER]; + + LoadString( g_hResourceDLL, IDS_ERR_MEMOPEN, tszText, DEFAULT_BUFFER ); + LoadString( g_hResourceDLL, IDS_DLG_WARN_TITLE, tszTitle, DEFAULT_BUFFER ); + wsprintf( szBuffer, tszText, pcFile ); + MessageBox( g_strEmuInfo.hMainWindow, szBuffer, tszTitle, MB_OK | MB_ICONWARNING ); + g_pcControllers[iControl].PakType = PAK_NONE; // set so that CloseControllerPak doesn't try to close a file that isn't open + DebugWrite(_T("Unable to read or create MemPak file %s.\n"), pcFile); + break; // memory is freed at the end of this function + } + } + + DWORD dwCurrentSize = GetFileSize( hFileHandle, NULL ); + if ( mPak->fReadonly ) + { + DWORD dwBytesRead = 0; + + if( mPak->fDexSave ) + { + SetFilePointer( hFileHandle, PAK_MEM_DEXOFFSET, NULL, FILE_BEGIN ); + } + else + { + SetFilePointer( hFileHandle, 0L, NULL, FILE_BEGIN ); + } + + dwFilesize = min( dwFilesize, GetFileSize( hFileHandle, NULL )); + if( !isNewfile ) + { + mPak->aMemPakData = (LPBYTE)P_malloc( sizeof(BYTE) * PAK_MEM_SIZE ); + if( ReadFile( hFileHandle, mPak->aMemPakData, PAK_MEM_SIZE, &dwBytesRead, NULL )) + { + if( dwBytesRead < dwFilesize ) + FillMemory( (LPBYTE)mPak->aMemPakData + dwBytesRead, PAK_MEM_SIZE - dwBytesRead, 0xFF ); + + bReturn = true; + } + else + P_free( mPak->aMemPakData ); + } + else + { + FormatMemPak( mPak->aMemPakData ); + bReturn = true; + } + CloseHandle( hFileHandle ); + } + else + { + // use mapped file + mPak->hMemPakHandle = CreateFileMapping( hFileHandle, NULL, mPak->fReadonly ? PAGE_READONLY : PAGE_READWRITE, 0, dwFilesize, NULL); + // test for invalid handle + if (mPak->hMemPakHandle == NULL) + { + // note: please don't move the CloseHandle call before GetLastError + DebugWriteA("Couldn't CreateFileMapping for MemPak file : %08x\n", GetLastError()); + CloseHandle(hFileHandle); + break; // memory is freed at the end of the function + } + CloseHandle(hFileHandle); // we can close the file handle now with no problems + + mPak->aMemPakData = (LPBYTE)MapViewOfFile( mPak->hMemPakHandle, FILE_MAP_ALL_ACCESS, 0, 0, mPak->fDexSave ? PAK_MEM_SIZE + PAK_MEM_DEXOFFSET : PAK_MEM_SIZE ); + + // this is a bit tricky: + // if it's a dexsave, move the pakdata pointer forward so it points to where the actual mempak data starts + // we need to make sure to move it back when we UnmapViewOfFile + if (mPak->aMemPakData == NULL) + ErrorMessage(IDS_ERR_MAPVIEW, GetLastError(), false); + + if ( mPak->fDexSave ) + mPak->aMemPakData += PAK_MEM_DEXOFFSET; + + if( dwCurrentSize < dwFilesize ) + FillMemory( (LPBYTE)mPak->aMemPakData + (mPak->fDexSave ? dwCurrentSize - PAK_MEM_DEXOFFSET : dwCurrentSize), dwFilesize - dwCurrentSize, 0xFF ); + + if( isNewfile ) + { + if (mPak->fDexSave ) + { + PVOID pHeader = MapViewOfFile( mPak->hMemPakHandle, FILE_MAP_ALL_ACCESS, 0, 0, PAK_MEM_DEXOFFSET ); + const char szHeader[] = "123-456-STD"; // "OMG-WTF-BBQ"? --rabid + ZeroMemory( pHeader, PAK_MEM_DEXOFFSET ); + CopyMemory( pHeader, szHeader, sizeof(szHeader) ); + FlushViewOfFile( pHeader, PAK_MEM_DEXOFFSET ); + UnmapViewOfFile( pHeader ); + } + FormatMemPak( mPak->aMemPakData ); + } + + bReturn = true; + } + } + break; + + case PAK_RUMBLE: + { + g_pcControllers[iControl].pPakData = P_malloc( sizeof(RUMBLEPAK)); + RUMBLEPAK *rPak = (RUMBLEPAK*)g_pcControllers[iControl].pPakData; + rPak->bPakType = PAK_RUMBLE; + + rPak->fLastData = true; // statistically, if uninitted it would return true --rabid +// rPak->bRumbleTyp = g_pcControllers[iControl].bRumbleTyp; +// rPak->bRumbleStrength = g_pcControllers[iControl].bRumbleStrength; +// rPak->fVisualRumble = g_pcControllers[iControl].fVisualRumble; + if( !g_pcControllers[iControl].xiController.bConnected ) //used to make sure only xinput cotroller rumbles --tecnicors + CreateEffectHandle( iControl, g_pcControllers[iControl].bRumbleTyp, g_pcControllers[iControl].bRumbleStrength ); + bReturn = true; + } + break; + case PAK_TRANSFER: + { + g_pcControllers[iControl].pPakData = P_malloc( sizeof(TRANSFERPAK)); + LPTRANSFERPAK tPak = (LPTRANSFERPAK)g_pcControllers[iControl].pPakData; + tPak->bPakType = PAK_TRANSFER; + + tPak->gbCart.hRomFile = NULL; + tPak->gbCart.hRamFile = NULL; + tPak->gbCart.RomData = NULL; + tPak->gbCart.RamData = NULL; + + /* + * Once the Interface is implemented g_pcControllers[iControl].szTransferRom will hold filename of the GB-Rom + * and g_pcControllers[iControl].szTransferSave holds Filename of the SRAM Save + * + * Here, both files should be opened and the handles stored in tPak ( modify the struct for Your own purposes, only bPakType must stay at first ) + */ + + + //CreateFile( g_pcControllers[iControl].szTransferSave, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL ); + tPak->iCurrentAccessMode = 0; + tPak->iCurrentBankNo = 0; + tPak->iEnableState = false; + tPak->iAccessModeChanged = 0x44; + + tPak->bPakInserted = LoadCart( &tPak->gbCart, g_pcControllers[iControl].szTransferRom, g_pcControllers[iControl].szTransferSave, _T("") ); + + if (tPak->bPakInserted) { + DebugWriteA( "*** Init Transfer Pak - Success***\n" ); + } else { + DebugWriteA( "*** Init Transfer Pak - FAILURE***\n" ); + } + + bReturn = true; + } + break; + + /*case PAK_VOICE: + { + g_pcControllers[iControl].pPakData = P_malloc( sizeof(VOICEPAK)); + VOICEPAK *vPak = (VOICEPAK*)g_pcControllers[iControl].pPakData; + vPak->bPakType = PAK_VOICE; + + bReturn = true; + } + break;*/ + + case PAK_ADAPTOID: + if( !g_pcControllers[iControl].fIsAdaptoid ) + g_pcControllers[iControl].PakType = PAK_NONE; + else + { + g_pcControllers[iControl].pPakData = P_malloc( sizeof(ADAPTOIDPAK)); + ADAPTOIDPAK *aPak = (ADAPTOIDPAK*)g_pcControllers[iControl].pPakData; + aPak->bPakType = PAK_ADAPTOID; + + aPak->bIdentifier = 0x80; +#ifdef ADAPTOIDPAK_RUMBLEFIX + aPak->fRumblePak = true; +#pragma message( "Driver-fix for Rumble with Adaptoid enabled" ) +#else + aPak->fRumblePak = false; +#endif + bReturn = true; + } + break; + + + /*case PAK_NONE: + break;*/ + } + + // if there were any unrecoverable errors and we have allocated pPakData, free it and set paktype to NONE + if( !bReturn && g_pcControllers[iControl].pPakData ) + CloseControllerPak( iControl ); + + return bReturn; +} + + +BYTE ReadControllerPak( const int iControl, LPBYTE Command ) +{ + BYTE bReturn = RD_ERROR; + LPBYTE Data = &Command[2]; + +#ifdef MAKEADRESSCRCCHECK +#pragma message( "Addresscheck for Pak-Reads active" ) + if( AddressCRC( Command ) != (Command[1] & 0x1F) ) + { + g_pcControllers[iControl].fPakCRCError = true; + if( WarningMessage( IDS_DLG_MEM_BADADDRESSCRC, MB_OKCANCEL | MB_ICONQUESTION ) == IDCANCEL ) + return RD_ERROR; + } +#endif + + if( !g_pcControllers[iControl].pPakData ) + return RD_ERROR; + + WORD dwAddress = (Command[0] << 8) + (Command[1] & 0xE0); + + switch( *(BYTE*)g_pcControllers[iControl].pPakData ) + { + case PAK_MEM: + { + MEMPAK *mPak = (MEMPAK*)g_pcControllers[iControl].pPakData; + + if( dwAddress < 0x8000 ) + CopyMemory( Data, &mPak->aMemPakData[dwAddress], 32 ); + else + CopyMemory( Data, &mPak->aMemPakTemp[(dwAddress%0x100)], 32 ); + Data[32] = DataCRC( Data, 32 ); + bReturn = RD_OK; + } + break; + case PAK_RUMBLE: + if(( dwAddress >= 0x8000 ) && ( dwAddress < 0x9000 ) ) + { + RUMBLEPAK *rPak = (RUMBLEPAK*)g_pcControllers[iControl].pPakData; + + if (rPak->fLastData) + FillMemory( Data, 32, 0x80 ); + else + ZeroMemory( Data, 32 ); + + if( g_pcControllers[iControl].xiController.bConnected && g_pcControllers[iControl].fXInput ) // xinput controller rumble --tecnicors + VibrateXInputController( g_pcControllers[iControl].xiController.nControl, 0, 0); + else if (g_apFFDevice[iControl]) + g_apFFDevice[iControl]->Acquire(); + } + else + ZeroMemory( Data, 32 ); + + Data[32] = DataCRC( Data, 32 ); + bReturn = RD_OK; + break; + + case PAK_TRANSFER: + { + LPTRANSFERPAK tPak = (LPTRANSFERPAK)g_pcControllers[iControl].pPakData; // TODO: null pointer check on tPak + // set bReturn = RD_OK when implementing Transferpak + bReturn = RD_OK; + DebugWriteA( "TPak Read:\n" ); + DebugWriteA( " Address: %04X\n", dwAddress ); + + switch (dwAddress >> 12) + { + case 0x8: // if ((dwAddress >= 0x8000) && (dwAddress <= 0x8FFF)) + DebugWriteA( "Query Enable State: %u\n", tPak->iEnableState ); + if (tPak->iEnableState == false) + ZeroMemory(Data, 32); + else + FillMemory(Data, 32, 0x84); + break; + case 0xB: // if ((dwAddress >= 0xB000) && (dwAddress <= 0xBFFF)) + if (tPak->iEnableState == true) { + DebugWriteA( "Query Cart. State:" ); + if (tPak->bPakInserted) { + if (tPak->iCurrentAccessMode == 1) { + FillMemory(Data, 32, 0x89); + DebugWriteA( " Inserted, Access Mode 1\n" ); + } else { + FillMemory(Data, 32, 0x80); + DebugWriteA( " Inserted, Access Mode 0\n" ); + } + Data[0] = Data[0] | tPak->iAccessModeChanged; + } else { + FillMemory(Data, 32, 0x40); // Cart not inserted. + DebugWriteA( " Not Inserted\n" ); + } + tPak->iAccessModeChanged = 0; + } + break; + case 0xC: + case 0xD: + case 0xE: + case 0xF: // if ((dwAddress >= 0xC000)) + if (tPak->iEnableState == true) { + DebugWriteA( "Cart Read: Bank:%i\n", tPak->iCurrentBankNo ); + DebugWriteA( " Address:%04X\n", ((dwAddress & 0xFFE0) - 0xC000) + ((tPak->iCurrentBankNo & 3) * 0x4000) ); + + tPak->gbCart.ptrfnReadCart(&tPak->gbCart, ((dwAddress & 0xFFE0) - 0xC000) + ((tPak->iCurrentBankNo & 3) * 0x4000), Data); + } + break; + default: + DebugWriteA("WARNING: Unusual Pak Read\n" ); + DebugWriteA(" Address: %04X\n", dwAddress); + } // end switch (dwAddress >> 12) + +#ifdef ENABLE_RAWPAK_DEBUG + DebugWriteA( "TPak Data: " ); + + for (int i = 0; i < 32; i ++) { + if ((i < 31) && ((i & 7) == 0)) DebugWriteA( "\n " ); + DebugWriteByteA(Data[i]); + if (i < 31) { + DebugWriteA( ", "); + } + } + DebugWriteA( "\n" ); +#endif + + Data[32] = DataCRC( Data, 32 ); + + bReturn = RD_OK; + } + break; + + /*case PAK_VOICE: + break;*/ + + case PAK_ADAPTOID: + if( ReadAdaptoidPak( iControl, dwAddress, Data ) == DI_OK ) + { + Data[32] = DataCRC( Data, 32 ); + bReturn = RD_OK; + + if( ((ADAPTOIDPAK*)g_pcControllers[iControl].pPakData)->fRumblePak ) + { + BYTE bId = ((ADAPTOIDPAK*)g_pcControllers[iControl].pPakData)->bIdentifier; + if( (( dwAddress == 0x8000 ) && ( bId == 0x80 ) && ( Data[0] != 0x80 )) + || (( dwAddress == 0x8000 ) && ( bId != 0x80 ) && ( Data[0] != 0x00 )) + || (( dwAddress < 0x8000 ) && ( Data[0] != 0x00 ))) + { + ((ADAPTOIDPAK*)g_pcControllers[iControl].pPakData)->fRumblePak = false; + DebugWriteA( "\nAssuming the inserted Pak AINT a RumblePak\nDisabling Rumblefix\n" ); + } + } + } + break; + + /*case PAK_NONE: + break;*/ + } + + return bReturn; +} + +// Called when the N64 tries to write to the controller pak, e.g. a mempak +BYTE WriteControllerPak( const int iControl, LPBYTE Command ) +{ + BYTE bReturn = RD_ERROR; + BYTE *Data = &Command[2]; + +#ifdef MAKEADRESSCRCCHECK +#pragma message( "Addresscheck for Pak-Writes active" ) + if( AddressCRC( Command ) != (Command[1] & 0x1F) ) + { + g_pcControllers[iControl].fPakCRCError = true; + if( WarningMessage( IDS_DLG_MEM_BADADDRESSCRC, MB_OKCANCEL | MB_ICONQUESTION ) == IDCANCEL ) + return RD_ERROR; + } +#endif + + if( !g_pcControllers[iControl].pPakData ) + return RD_ERROR; + + WORD dwAddress = (Command[0] << 8) + (Command[1] & 0xE0); + + switch( *(BYTE*)g_pcControllers[iControl].pPakData ) + { + case PAK_MEM: + { + // Switched to memory-mapped file + // That way, if the computer dies due to power loss or something mid-play, the savegame is still there. + MEMPAK *mPak = (MEMPAK*)g_pcControllers[iControl].pPakData; + + if( dwAddress < 0x8000 ) + { + CopyMemory( &mPak->aMemPakData[dwAddress], Data, 32 ); + if (!mPak->fReadonly ) + SetTimer( g_strEmuInfo.hMainWindow, PAK_MEM, 2000, (TIMERPROC) WritebackProc ); // if we go 2 seconds without a write, call the Writeback proc (which will flush the cache) + } + else + CopyMemory( &mPak->aMemPakTemp[(dwAddress%0x100)], Data, 32 ); + Data[32] = DataCRC( Data, 32 ); + bReturn = RD_OK; + } + break; + case PAK_RUMBLE: + if( dwAddress == PAK_IO_RUMBLE ) + { + if( g_pcControllers[iControl].xiController.bConnected && g_pcControllers[iControl].fXInput ) // xinput controller rumble --tecnicors + { + if( *Data ) + VibrateXInputController( g_pcControllers[iControl].xiController.nControl ); + else + VibrateXInputController( g_pcControllers[iControl].xiController.nControl, 0, 0 ); + goto end_rumble; + } + + if( g_pcControllers[iControl].fVisualRumble ) + FlashWindow( g_strEmuInfo.hMainWindow, ( *Data != 0 ) ? TRUE : FALSE ); + if( g_pcControllers[iControl].bRumbleTyp == RUMBLE_DIRECT ) + { // Adaptoid Direct Rumble + if( g_pcControllers[iControl].fIsAdaptoid ) + DirectRumbleCommand( iControl, *Data ); + } + else + { // FF-FeedBack Rumble + if( g_apdiEffect[iControl] ) + { + g_apFFDevice[iControl]->Acquire(); + if( *Data ) + { + // g_apdiEffect[iControl]->Start( 1, DIES_SOLO ); + HRESULT hr; + hr = g_apdiEffect[iControl]->Start( 1, DIES_NODOWNLOAD ); + if( hr != DI_OK )// just download if needed( seems to work smoother) + { + hr = g_apdiEffect[iControl]->Start( 1, 0 ); + if (hr != DI_OK) + { + DebugWriteA("Rumble: Can't rumble %d: %lX\n", iControl, hr); + } + else + DebugWriteA("Rumble: DIES_NODOWNLOAD failed, regular OK on control %d\n", iControl); + } + else + DebugWriteA("Rumble: DIES_NODOWNLOAD OK on control %d\n", iControl); + } + else + { + g_apdiEffect[iControl]->Stop(); + } + } + } + } + else if (dwAddress >= 0x8000 && dwAddress < 0x9000) + { + RUMBLEPAK *rPak = (RUMBLEPAK*)g_pcControllers[iControl].pPakData; + rPak->fLastData = (*Data) ? true : false; + } + +end_rumble: // added so after xinput controller rumbles, gets here --tecnicors + Data[32] = DataCRC( Data, 32 ); + bReturn = RD_OK; + break; + + case PAK_TRANSFER: + { + LPTRANSFERPAK tPak = (LPTRANSFERPAK)g_pcControllers[iControl].pPakData; + // set bReturn = RD_OK when implementing Transferpak + DebugWriteA( "TPak Write:\n" ); + DebugWriteA( " Address: %04X\n", dwAddress ); + +#ifdef ENABLE_RAWPAK_DEBUG + DebugWriteA( " Data: "); + + for (int i = 0; i < 32; i++) { + if ((i < 31) && ((i & 7) == 0)) DebugWriteA( "\n " ); + DebugWriteByteA( Data[i]); + if (i < 31) { + DebugWriteA( ", " ); + } + } + + DebugWriteA( "\n" ); +#endif // #ifdef ENABLE_RAWPAK_DEBUG + + switch (dwAddress >> 12) + { + case 0x8: // if ((dwAddress >= 0x8000) && (dwAddress <= 0x8FFF)) + if (Data[0] == 0xFE) { + DebugWriteA("Cart Disable\n" ); + tPak->iEnableState = false; + } + else if (Data[0] == 0x84) { + DebugWriteA("Cart Enable\n" ); + tPak->iEnableState = true; + } + else { + DebugWriteA("WARNING: Unusual Cart Enable/Disable\n" ); + DebugWriteA(" Address: " ); + DebugWriteWordA(dwAddress); + DebugWriteA("\n" ); + DebugWriteA(" Data: " ); + DebugWriteByteA(Data[0]); + DebugWriteA("\n" ); + } + break; + case 0xA: // if ((dwAddress >= 0xA000) && (dwAddress <= 0xAFFF)) + if (tPak->iEnableState == true) { + tPak->iCurrentBankNo = Data[0]; + DebugWriteA("Set TPak Bank No:%02X\n", Data[0] ); + } + break; + case 0xB: // if ((dwAddress >= 0xB000) && (dwAddress <= 0xBFFF)) + if (tPak->iEnableState == true) { + tPak->iCurrentAccessMode = Data[0] & 1; + tPak->iAccessModeChanged = 4; + DebugWriteA("Set TPak Access Mode: %04X\n", tPak->iCurrentAccessMode); + if ((Data[0] != 1) && (Data[0] != 0)) { + DebugWriteA("WARNING: Unusual Access Mode Change\n" ); + DebugWriteA(" Address: " ); + DebugWriteWordA(dwAddress); + DebugWriteA("\n" ); + DebugWriteA(" Data: " ); + DebugWriteByteA(Data[0]); + DebugWriteA("\n" ); + } + } + break; + case 0xC: + case 0xD: + case 0xE: + case 0xF: // if (dwAddress >= 0xC000) + tPak->gbCart.ptrfnWriteCart(&tPak->gbCart, ((dwAddress & 0xFFE0) - 0xC000) + ((tPak->iCurrentBankNo & 3) * 0x4000), Data); + if (tPak->gbCart.hRamFile != NULL ) + SetTimer( g_strEmuInfo.hMainWindow, PAK_TRANSFER, 2000, (TIMERPROC) WritebackProc ); // if we go 2 seconds without a write, call the Writeback proc (which will flush the cache) + break; + default: + DebugWriteA("WARNING: Unusual Pak Write\n" ); + DebugWriteA(" Address: %04X\n", dwAddress); + } // end switch (dwAddress >> 12) + + Data[32] = DataCRC( Data, 32 ); + bReturn = RD_OK; + } + break; + + /*case PAK_VOICE: + break;*/ + + case PAK_ADAPTOID: + if(( dwAddress == PAK_IO_RUMBLE ) && ((ADAPTOIDPAK*)g_pcControllers[iControl].pPakData)->fRumblePak ) + { + if( DirectRumbleCommand( iControl, *Data ) == DI_OK ) + { + Data[32] = DataCRC( Data, 32 ); + bReturn = RD_OK; + } + } + else + { + if( WriteAdaptoidPak( iControl, dwAddress, Data ) == DI_OK ) + { + Data[32] = DataCRC( Data, 32 ); + if( dwAddress == 0x8000 ) + ((ADAPTOIDPAK*)g_pcControllers[iControl].pPakData)->bIdentifier = Data[0]; + + bReturn = RD_OK; + } + } + break; + + /*case PAK_NONE: + break;*/ + } + + return bReturn; +} + +void SaveControllerPak( const int iControl ) +{ + if( !g_pcControllers[iControl].pPakData ) + return; + + switch( *(BYTE*)g_pcControllers[iControl].pPakData ) + { + case PAK_MEM: + { + MEMPAK *mPak = (MEMPAK*)g_pcControllers[iControl].pPakData; + + if( !mPak->fReadonly ) + FlushViewOfFile( mPak->aMemPakData, PAK_MEM_SIZE ); // we've already written the stuff, just flush the cache + } + break; + case PAK_RUMBLE: + break; + case PAK_TRANSFER: + { + LPTRANSFERPAK tPak = (LPTRANSFERPAK)g_pcControllers[iControl].pPakData; + // here the changes( if any ) in the SRAM should be saved + + if (tPak->gbCart.hRamFile != NULL) + { + SaveCart(&tPak->gbCart, g_pcControllers[iControl].szTransferSave, _T("")); + DebugWriteA( "*** Save Transfer Pak ***\n" ); + } + } + break; + case PAK_VOICE: + break; + case PAK_ADAPTOID: + break; + + /*case PAK_NONE: + break;*/ + } +} + +// if there is pPakData for the controller, does any closing of handles before freeing the pPakData struct and setting it to NULL +// also sets fPakInitialized to false +void CloseControllerPak( const int iControl ) +{ + if( !g_pcControllers[iControl].pPakData ) + return; + + g_pcControllers[iControl].fPakInitialized = false; + + switch( *(BYTE*)g_pcControllers[iControl].pPakData ) + { + case PAK_MEM: + { + MEMPAK *mPak = (MEMPAK*)g_pcControllers[iControl].pPakData; + + if( mPak->fReadonly ) + { + P_free( mPak->aMemPakData ); + mPak->aMemPakData = NULL; + } + else + { + FlushViewOfFile( mPak->aMemPakData, PAK_MEM_SIZE ); + // if it's a dexsave, our original mapped view is not aMemPakData + UnmapViewOfFile( mPak->fDexSave ? mPak->aMemPakData - PAK_MEM_DEXOFFSET : mPak->aMemPakData ); + if ( mPak->hMemPakHandle != NULL ) + CloseHandle( mPak->hMemPakHandle ); + } + } + break; + case PAK_RUMBLE: + ReleaseEffect( g_apdiEffect[iControl] ); + g_apdiEffect[iControl] = NULL; + break; + case PAK_TRANSFER: + { + LPTRANSFERPAK tPak = (LPTRANSFERPAK)g_pcControllers[iControl].pPakData; + UnloadCart(&tPak->gbCart); + DebugWriteA( "*** Close Transfer Pak ***\n" ); + // close files and free any additionally ressources + } + break; + case PAK_VOICE: + break; + + case PAK_ADAPTOID: + break; + + /*case PAK_NONE: + break;*/ + } + + freePakData( &g_pcControllers[iControl] ); + return; +} + +// returns the number of remaining blocks in a mempak +// aNoteSizes should be an array of 16 bytes, which will be overwritten with the size in blocks of each note +inline WORD CountBlocks( const unsigned char * bMemPakBinary, LPBYTE aNoteSizes ) +{ + WORD wRemainingBlocks = 123; + BYTE bNextIndex; + int i = 0; + while( i < 16 && wRemainingBlocks <= 123 ) + { + aNoteSizes[i] = 0; + bNextIndex = bMemPakBinary[0x307 + (i*0x20)]; + while(( bNextIndex >= 5 ) && ( aNoteSizes[i] < wRemainingBlocks)) + { + aNoteSizes[i]++; + bNextIndex = bMemPakBinary[0x101 + (bNextIndex*2)]; + } + + if( aNoteSizes[i] > wRemainingBlocks ) + wRemainingBlocks = 0xFF; + else + wRemainingBlocks -= aNoteSizes[i]; + + i++; + } + return wRemainingBlocks; +} + + + +void FormatMemPak( LPBYTE aMemPak ) +{ + FillMemory( aMemPak, 0x100, 0xFF ); + + aMemPak[0] = 0x81; + + // generate a valid code( i hope i can calculate it one day) + BYTE aValidCodes[] = { 0x12, 0xC5, 0x8F, 0x6F, 0xA4, 0x28, 0x5B, 0xCA }; + BYTE aCode[8]; + + int iRand = (( (ULONG)aMemPak / 4 + (ULONG)g_strEmuInfo.hMainWindow / 4 ) % (sizeof(aValidCodes)/8) ); + for( int n = 0; n <8; n++ ) + aCode[n] = aValidCodes[n+iRand]; + + //---------- + + aMemPak[0x20+0] = aMemPak[0x60+0] = aMemPak[0x80+0] = aMemPak[0xC0+0] = 0xFF; + aMemPak[0x20+1] = aMemPak[0x60+1] = aMemPak[0x80+1] = aMemPak[0xC0+1] = 0xFF; + aMemPak[0x20+2] = aMemPak[0x60+2] = aMemPak[0x80+2] = aMemPak[0xC0+2] = 0xFF; + aMemPak[0x20+3] = aMemPak[0x60+3] = aMemPak[0x80+3] = aMemPak[0xC0+3] = 0xFF; + + aMemPak[0x20+4] = aMemPak[0x60+4] = aMemPak[0x80+4] = aMemPak[0xC0+4] = aCode[0]; + aMemPak[0x20+5] = aMemPak[0x60+5] = aMemPak[0x80+5] = aMemPak[0xC0+5] = aCode[1]; + aMemPak[0x20+6] = aMemPak[0x60+6] = aMemPak[0x80+6] = aMemPak[0xC0+6] = aCode[2]; + aMemPak[0x20+7] = aMemPak[0x60+7] = aMemPak[0x80+7] = aMemPak[0xC0+7] = aCode[3]; + + //aMemPak[0x30+9] = aMemPak[0x70+9] = aMemPak[0x90+9] = aMemPak[0xD0+9] = 0x01; // not sure + aMemPak[0x30+10] = aMemPak[0x70+10] = aMemPak[0x90+10] = aMemPak[0xD0+10] = 0x01; + + aMemPak[0x30+12] = aMemPak[0x70+12] = aMemPak[0x90+12] = aMemPak[0xD0+12] = aCode[4]; + aMemPak[0x30+13] = aMemPak[0x70+13] = aMemPak[0x90+13] = aMemPak[0xD0+13] = aCode[5]; + aMemPak[0x30+14] = aMemPak[0x70+14] = aMemPak[0x90+14] = aMemPak[0xD0+14] = aCode[6]; + aMemPak[0x30+15] = aMemPak[0x70+15] = aMemPak[0x90+15] = aMemPak[0xD0+15] = aCode[7]; + + + + // Index + ZeroMemory( &aMemPak[0x100], 0x400 ); + + aMemPak[0x100+1] = aMemPak[0x200+1] = 0x71; + for( int i = 0x00b; i < 0x100; i += 2 ) + aMemPak[0x100+i] = aMemPak[0x200+i] = 03; + + + FillMemory( &aMemPak[0x500], 0x7B00, 0xFF ); + +} + +// Translates a mempak header into a real Unicode string, for display in the Mempaks window +// bNote is now where you want to START translating, Text is where the output gets sent, iChars is the number of TCHARs you want translated +// return value is the number of characters actually translated +// Text automatically gets a terminating null, so make sure there's enough space. +int TranslateNotesW( const unsigned char * bNote, LPWSTR Text, const int iChars ) +{ + WCHAR aSpecial[] = { 0x0021, 0x0022, 0x0023, 0x0060, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x003A, 0x003D, 0x003F, 0x0040, 0x2122, 0x00A9, 0x00AE }; + // { '!' , '\"', '#' , '`' , '*' , '+' , ',' , '-' , '.' , '/' , ':' , '=' , '?' , '>' , 'tm', '(c)', '(r)' }; + const WCHAR aJmap[] = { // map of Japanese characters N64 to UTF-16, starting at 0x45 + 0x00A1, 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3, 0x30F2, // small a-i-u-e-o, next are probably small ya-yu-yo, small tsu, wo + 0x30F3, // 0x4F -> 'n' + 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, // nil-K-S + 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, // T-N-H + 0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, // M-Y-R + 0x30EF, // 'wa' + 0x30AC, 0x30AE, 0x30B0, 0x30B2, 0x30B4, 0x30B6, 0x30B8, 0x30BA, 0x30BC, 0x30BE, 0x30C0, 0x30C2, 0x30C5, 0x30C7, 0x30C9, // G-Z-D + 0x30D0, 0x30D3, 0x30D6, 0x30D9, 0x30DC, 0x30D1, 0x30D4, 0x30D7, 0x30DA, 0x30DD // B-P + }; + int iReturn = 0; + + while (iChars - iReturn > 0 && *bNote) + { + BYTE b = *bNote; + if( b <= 0x0F ) // translate Icons as Spaces + *Text = 0x0020; + else if( b <= 0x19 ) // Numbers + *Text = 0x0020 + b; + else if( b <= 0x33 ) // English characters + *Text = 0x0047 + b; + else if( b <= 0x44 ) // special symbols + *Text = aSpecial[b - 0x34]; + else if( b <= 0x94 ) // Japanese (halfwidth katakana, mapped similarly to JIS X 0201 but not enough that we can use a simple codepage) + { + aSpecial[7] = 0x30fc; // change regular dash to Japanese "long sound dash" + *Text = aJmap[b - 0x45]; + } + else // unknown + *Text = 0x00A4; // unknown characters become "currency sign" (looks like a letter o superimposed on an x) + Text++; + iReturn++; + bNote++; + } + + *Text = L'\0'; + + return iReturn; +} + +// TODO: rename this function! It serves a completely different function from TranslateNotesW +// Translates a mempak header into an ASCII string for output to .a64 file +// bNote is now where you want to START translating, Text is where the output gets sent, iChars is the number of chars you want translated +// return value is the number of characters actually translated +// Text automatically gets a terminating null, so make sure there's enough space. +int TranslateNotesA( const unsigned char * bNote, LPSTR Text, const int iChars ) +{ + const UCHAR aSpecial[] ={ 0x21, 0x22, 0x23, 0x60, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x3A, 0x3D, 0x3F, 0x40, 0x99, 0xA9, 0xAE }; + // { '!' , '\"', '#' , '`' , '*' , '+' , ',' , '-' , '.' , '/' , ':' , '=' , '?' , '>' , 'tm', '(c)','(r)' }; + int iReturn = 0; + + while (iChars - iReturn > 0 && *bNote) + { + BYTE b = *bNote; + if( b <= 0x0F ) // translate Icons as Spaces + *Text = 0x20; + else if( b <= 0x19 ) // Numbers + *Text = 0x20 + b; + else if( b <= 0x33 ) // English characters + *Text = 0x47 + b; + else if( b <= 0x44 ) // special symbols + *Text = aSpecial[b - 0x34]; + else if( b <= 0x94 ) // Japan + *Text = 0xC0 + ( b % 40 ); + else // unknown + *Text = (UCHAR)0xA4; // HACK: this will screw up any save with unknown characters + + Text++; + iReturn++; + bNote++; + } + + *Text = '\0'; + return iReturn; +} + +int ReverseNotesA( LPCSTR Text, LPBYTE Note ) +{ + const UCHAR aSpecial[] = { 0x21, 0x22, 0x23, 0x60, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x3A, 0x3D, 0x3F, 0x40, 0x74, 0xA9, 0xAE }; + // { '!' , '\"', '#' , '`' , '*' , '+' , ',' , '-' , '.' , '/' , ':' , '=' , '?' , '>' , 'tm', '(r)','(c)' }; + + LPCSTR TextPos = Text; + while( *TextPos != '\0' ) + { + char c = *TextPos; + *Note = 0x0F; + + if( c >= '0' && c <= '9' ) + *Note = c - '0' + 0x10; + else if( c >= 'A' && c <= 'Z' ) + *Note = c - 'A' + 0x1A; + else if( c >= 'a' && c <= 'z' ) + *Note = c - 'a' + 0x1A; + + else + { + for( int i = 0; i < ARRAYSIZE(aSpecial); ++i ) + { + if( c == aSpecial[i] ) + { + *Note = i + 0x34; + break; + } + } + } + TextPos++; + Note++; + } + return TextPos - Text; +} + +WORD ShowMemPakContent( const unsigned char * bMemPakBinary, HWND hListWindow ) +{ + BYTE bMemPakValid = MPAK_OK; + TCHAR szBuffer[40]; + BYTE aNoteSizes[16]; + bool bFirstChar; + + + LVITEM lvItem; + lvItem.mask = LVIF_TEXT | LVIF_PARAM; + lvItem.iItem = 0; + lvItem.iSubItem = 0; + lvItem.pszText = szBuffer; + + int i = 0, + nNotes = 0, + iSum = 0, + iRemainingBlocks = 0; + + for( i = 0x10A; i < 0x200; i++ ) + iSum += bMemPakBinary[i]; + + + if((( iSum % 256 ) == bMemPakBinary[0x101] )) + { + iRemainingBlocks = CountBlocks( bMemPakBinary, aNoteSizes ); + + if( iRemainingBlocks <= 123 ) + { + for( lvItem.lParam = 0; lvItem.lParam < 16; lvItem.lParam++ ) + { + + if( bMemPakBinary[0x300 + (lvItem.lParam*32)] || + bMemPakBinary[0x301 + (lvItem.lParam*32)] || + bMemPakBinary[0x302 + (lvItem.lParam*32)] ) + { + int iChars = TranslateNotes( &bMemPakBinary[0x300 + (lvItem.lParam*32) + 0x10], szBuffer, 16 ); + + if( TranslateNotes( &bMemPakBinary[0x300 + (lvItem.lParam*32) + 0x0C], &szBuffer[iChars + 1], 1 ) ) + szBuffer[iChars] = _T('_'); + + bFirstChar = true; + for( i = 0; i < (int)lstrlen(szBuffer); i++ ) + { + if( szBuffer[i] == ' ' ) + bFirstChar = true; + else + { + if( bFirstChar && ( szBuffer[i] >= 'a') && ( szBuffer[i] <= 'z')) + { + bFirstChar = false; + szBuffer[i] -= 0x20; + } + } + + } + + i = ListView_InsertItem( hListWindow, &lvItem ); + + switch( bMemPakBinary[0x303 + (lvItem.lParam*32)] ) + { + case 0x00: + LoadString( g_hResourceDLL, IDS_P_MEM_NOREGION, szBuffer, 40 ); + break; + case 0x37: + LoadString( g_hResourceDLL, IDS_P_MEM_BETA, szBuffer, 40 ); + break; + case 0x41: + LoadString( g_hResourceDLL, IDS_P_MEM_NTSC, szBuffer, 40 ); + break; + case 0x44: + LoadString( g_hResourceDLL, IDS_P_MEM_GERMANY, szBuffer, 40 ); + break; + case 0x45: + LoadString( g_hResourceDLL, IDS_P_MEM_USA, szBuffer, 40 ); + break; + case 0x46: + LoadString( g_hResourceDLL, IDS_P_MEM_FRANCE, szBuffer, 40 ); + break; + case 0x49: + LoadString( g_hResourceDLL, IDS_P_MEM_ITALY, szBuffer, 40 ); + break; + case 0x4A: + LoadString( g_hResourceDLL, IDS_P_MEM_JAPAN, szBuffer, 40 ); + break; + case 0x50: + LoadString( g_hResourceDLL, IDS_P_MEM_EUROPE, szBuffer, 40 ); + break; + case 0x53: + LoadString( g_hResourceDLL, IDS_P_MEM_SPAIN, szBuffer, 40 ); + break; + case 0x55: + LoadString( g_hResourceDLL, IDS_P_MEM_AUSTRALIA, szBuffer, 40 ); + break; + case 0x58: + case 0x59: + LoadString( g_hResourceDLL, IDS_P_MEM_PAL, szBuffer, 40 ); + break; + default: + { + TCHAR szTemp[40]; + LoadString( g_hResourceDLL, IDS_P_MEM_UNKNOWNREGION, szTemp, 40 ); + wsprintf( szBuffer, szTemp, bMemPakBinary[0x303 + (lvItem.lParam*32)] ); + } + } + + ListView_SetItemText( hListWindow, i, 1, szBuffer ); + + wsprintf( szBuffer, _T("%i"), aNoteSizes[lvItem.lParam] ); + ListView_SetItemText( hListWindow, i, 2, szBuffer ); + nNotes++; + } + } + + } + else + bMemPakValid = MPAK_DAMAGED; + + } + else + bMemPakValid = MPAK_DAMAGED; + + return MAKEWORD( (BYTE)iRemainingBlocks, bMemPakValid ); +} + +void HextoTextA( const unsigned char * Data, LPSTR szText, const int nBytes ) +{ + const char acValues[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' }; + + for( int i = 0; i < nBytes; i++ ) + { + BYTE byte = *Data; + szText[0] = acValues[(byte>>4) & 0x0F]; + szText[1] = acValues[byte & 0x0F]; + + ++Data; + szText+=2; + } + *szText = '\0'; +} + +// used when reading in a Note file, to convert text to binary (unserialize) +void TexttoHexA( LPCSTR szText, LPBYTE Data, const int nBytes ) +{ + bool fLowByte = false; + LPCSTR endText = szText + nBytes * 2; + + for( ; szText < endText; ++szText ) + { + BYTE bByte = 0; + + if(( '0' <= *szText ) && ( *szText <= '9' )) + bByte = *szText - '0'; + else + { + if(( 'A' <= *szText ) && ( *szText <= 'F' )) + bByte = szText[0] - 'A' + 10; + else if(( 'a' <= *szText ) && ( *szText <= 'f' )) + bByte = szText[0] - 'a' + 10; + } + + if( !fLowByte ) + *Data = bByte << 4; + else + { + *Data |= bByte; + ++Data; + } + + fLowByte = !fLowByte; + } +} + +bool SaveNoteFileA( const unsigned char * aMemPak, const int iNote, LPCTSTR pszFileName ) +{ + BYTE aNoteSizes[16]; + LPBYTE aNote; + bool bReturn = false; + if( CountBlocks( aMemPak, aNoteSizes ) > 123 ) + return false; + + aNote = (LPBYTE)P_malloc( aNoteSizes[iNote] * 0x100 + 32 ); + if( !aNote ) + return false; + + CopyMemory( aNote, &aMemPak[0x300 + iNote * 32], 32 ); + BYTE bNextIndex = aNote[0x7]; + int iBlock = 0; + while( iBlock < aNoteSizes[iNote] ) + { + CopyMemory( &aNote[32 + iBlock * 0x100], &aMemPak[bNextIndex * 0x100], 0x100); + bNextIndex = aMemPak[0x101 + (bNextIndex*2)]; + + iBlock++; + } + + HANDLE hFile = CreateFile( pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + if ( hFile != INVALID_HANDLE_VALUE ) + { + SetFilePointer( hFile, 0L, NULL, FILE_BEGIN ); + char szLine[70]; + + + DWORD dwBytesWritten = 0; + lstrcpyA( szLine, "a64-notes\r\ndescription of game save goes here...\r\na64-data\r\n" ); + WriteFile( hFile, szLine, lstrlenA(szLine), &dwBytesWritten, NULL ); + + CopyMemory( szLine, aNote, 4 ); + szLine[4] = ' '; + szLine[5] = aNote[4]; + szLine[6] = aNote[5]; + szLine[7] = ' '; + HextoTextA( &aNote[8], &szLine[8], 2 ); + + int pos = 12; + szLine[pos++] = ' '; + szLine[pos++] = aNote[0x0A] + '0'; + szLine[pos++] = ' '; + szLine[pos++] = '{'; + + pos += TranslateNotesA( &aNote[0x0C], &szLine[pos], 1 ); + + szLine[pos++] = '}'; + szLine[pos++] = ' '; + szLine[pos++] = '{'; + + pos += TranslateNotesA( &aNote[0x10], &szLine[pos], 16 ); + + lstrcatA( szLine, "}\r\n" ); + WriteFile( hFile, szLine, lstrlenA(szLine), &dwBytesWritten, NULL ); + + for( int i = 32; i < aNoteSizes[iNote] * 0x100 + 32; i += 32 ) + { + HextoTextA( &aNote[i], szLine, 32 ); + WriteFile( hFile, szLine, lstrlenA(szLine), &dwBytesWritten, NULL ); + WriteFile( hFile, "\r\n", 2, &dwBytesWritten, NULL ); + } + WriteFile( hFile, "a64-crc\r\n", 9, &dwBytesWritten, NULL ); + + // TODO: insert crc here + lstrcpynA( szLine, "00000000\r\n", 70 ); + WriteFile( hFile, szLine, lstrlenA(szLine), &dwBytesWritten, NULL ); + // + WriteFile( hFile, "a64-end\r\n", 9, &dwBytesWritten, NULL ); + + SetEndOfFile( hFile ); + bReturn = true; + CloseHandle( hFile ); + } + else + ErrorMessage( IDS_ERR_NOTEREAD, GetLastError(), false ); + + P_free( aNote ); + return bReturn; +} + +// read a Note from a file pszFileName (.a64 format), and insert it into the given MemPak +// returns true on success, false otherwise +bool InsertNoteFile( LPBYTE aMemPak, LPCTSTR pszFileName ) +{ +// bool bReturn = false; + + FILE* nFile = NULL; + + if( (nFile = _tfopen(pszFileName, _T("r") ) ) != NULL ) + { + char szLine[128]; + fpos_t pDataStart; + + while( fgets(szLine, sizeof(szLine) - 1, nFile) ) + { + if( !strncmp( "a64-data", szLine, 8 )) + { + fgetpos(nFile, &pDataStart); + break; + } + } + + // assumes the file keeps going... + // discard the next line + fgets(szLine, sizeof(szLine) - 1, nFile); // not really necessary to check for EOF, as it will fail gracefully when dwNoteSize is zero. + + DWORD dwNoteSize = 0; + while( fgets(szLine, sizeof(szLine) - 1, nFile) && strncmp( "a64-crc", szLine, 7 )) + { + dwNoteSize++; + } + dwNoteSize /= 8; + + BYTE aNoteSizes[16]; + WORD wRemainingBlocks; + int i, + ifreeNote = -1; + + wRemainingBlocks = CountBlocks( aMemPak, aNoteSizes ); + + if( dwNoteSize <= 0 ) + { + ErrorMessage( IDS_ERR_NOTEREAD, 0, false ); + fclose(nFile); + return false; + } + else + { + if( wRemainingBlocks < dwNoteSize ) + { + ErrorMessage( IDS_ERR_MEMPAK_SPACE, 0, false ); + fclose(nFile); + return false; + } + else + { + i = 0; + while(( i < 16 ) && ( ifreeNote == -1 )) + { + if( aNoteSizes[i] == 0 ) + ifreeNote = i; + i++; + } + if( ifreeNote == -1 ) + { + ErrorMessage( IDS_ERR_MEMPAK_NONOTES, 0, false ); + fclose(nFile); + return false; + } + } + } + + // HEADER START + + // .a64 header should look something like this: + // NBCE 01 0203 0 {} {BLASTCORPS GAME} + // first 4 chars are the first 4 bytes + // next 2 chars are the next 2 bytes + // next 4 chars are bytes 8 and 9, in hex (huh?) + // next character is byte 10, in hex (but only one character this time) + // now we've got two sets of braces... the first one contains byte 12 in encoded form (use ReverseNotesA) + // the second one should contain bytes 16 through 31 (ReverseNotesA) + + BYTE *pBlock; + fsetpos(nFile, &pDataStart); + if (! fgets(szLine, sizeof(szLine) - 1, nFile) ) + { + ErrorMessage( IDS_ERR_NOTEEOF, 0, false ); + fclose(nFile); + return false; + } + + szLine[strlen(szLine) - 1] = '\0'; // remove newline + + pBlock = &aMemPak[0x300 + ifreeNote*32]; + CopyMemory( pBlock, szLine, 4 ); + pBlock[4] = szLine[5]; + pBlock[5] = szLine[6]; + TexttoHexA( &szLine[8], &pBlock[8], 2 ); + pBlock[10] = szLine[13] - '0'; + + int len = lstrlenA( szLine ); + + i = 16; + while(( szLine[i] != '}' ) && (i < len)) + i++; + + szLine[i] = '\0'; + i += ReverseNotesA( &szLine[16], &pBlock[12] ); + + while(( szLine[i] != '{' ) && (i < len)) + i++; + + if(i < len) + { + int start = i+1; + while(( szLine[i] != '}' ) && (i < len)) + i++; + if(i < len) + { + szLine[i] = '\0'; + ReverseNotesA( &szLine[start], &pBlock[16] ); + } + } + + while(( szLine[i] != '}' ) && (i < len)) + i++; + szLine[i] = '\0'; + + // HEADER END + + BYTE bDataBlock = 5; + pBlock = &pBlock[7]; + BYTE *pDataBlock; + + while( dwNoteSize > 0 ) + { + while( aMemPak[0x101 + bDataBlock*2] != 0x03 ) + bDataBlock++; + *pBlock = bDataBlock; + pBlock = &aMemPak[0x101 + bDataBlock*2]; + pDataBlock = &aMemPak[bDataBlock * 0x100]; + for( i = 0; i < 0x100; i+=32 ) + { + if (! fgets(szLine, sizeof(szLine) - 1, nFile) ) + { + ErrorMessage( IDS_ERR_NOTEEOF, 0, false ); + fclose(nFile); + return false; + } + + szLine[strlen(szLine) - 1] = '\0'; // remove newline + TexttoHexA( szLine, &pDataBlock[i], 32 ); + } + bDataBlock++; + dwNoteSize--; + } + *pBlock = 0x01; + + int iSum = 0; + + for( i = 0x10A; i < 0x200; i++ ) + iSum += aMemPak[i]; + + aMemPak[0x101] = iSum % 256; + + CopyMemory( &aMemPak[0x200], &aMemPak[0x100], 0x100 ); + + fclose(nFile); + return true; + } + else + ErrorMessage( IDS_ERR_NOTEREAD, 0, false ); + return false; +} + +// Remove a mempak "Note" +// See "MemPak-Format.doc" for more info +bool RemoveNote( LPBYTE aMemPak, const int iNote ) +{ + BYTE bBlock = aMemPak[0x307 + iNote*32]; + int iPos; + + while( bBlock >= 0x05 ) + { + iPos = 0x101 + bBlock*2; + bBlock = aMemPak[iPos]; + aMemPak[iPos] = 0x03; + } + int i = 0, iSum = 0; + for( i = 0x10A; i < 0x200; i++ ) + iSum += aMemPak[i]; + + aMemPak[0x101] = iSum % 256; + + CopyMemory( &aMemPak[0x200], &aMemPak[0x100], 0x100 ); + + ZeroMemory( &aMemPak[0x300 + iNote*32], 32 ); + + return true; +} + + + +BYTE AddressCRC( const unsigned char * Address ) +{ + bool HighBit; + WORD Data = MAKEWORD( Address[1], Address[0] ); + register BYTE Remainder = ( Data >> 11 ) & 0x1F; + + BYTE bBit = 5; + + while( bBit < 16 ) + { + HighBit = (Remainder & 0x10) != 0; + Remainder = (Remainder << 1) & 0x1E; + + Remainder += ( bBit < 11 && Data & (0x8000 >> bBit )) ? 1 : 0; + + Remainder ^= (HighBit) ? 0x15 : 0; + + bBit++; + } + + return Remainder; +} + +BYTE DataCRC( const unsigned char * Data, const int iLength ) +{ + register BYTE Remainder = Data[0]; + + int iByte = 1; + BYTE bBit = 0; + + while( iByte <= iLength ) + { + bool HighBit = ((Remainder & 0x80) != 0); + Remainder = Remainder << 1; + + Remainder += ( iByte < iLength && Data[iByte] & (0x80 >> bBit )) ? 1 : 0; + + Remainder ^= (HighBit) ? 0x85 : 0; + + bBit++; + iByte += bBit/8; + bBit %= 8; + } + + return Remainder; +} + +VOID CALLBACK WritebackProc( HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime ) +{ + KillTimer(hWnd, idEvent); // timer suicide + + switch (idEvent) + { + case PAK_MEM: + DebugWriteA("Mempak: WritebackProc flushed file writes\n"); + for( int i = 0; i < 4; i++ ) + { + MEMPAK *mPak = (MEMPAK*)g_pcControllers[i].pPakData; + + if ( mPak && mPak->bPakType == PAK_MEM && !mPak->fReadonly && mPak->hMemPakHandle != NULL ) + FlushViewOfFile( mPak->aMemPakData, PAK_MEM_SIZE ); + } + return; + case PAK_TRANSFER: + DebugWriteA("TPak: WritebackProc flushed file writes\n"); + for( int i = 0; i < 4; i++ ) + { + LPTRANSFERPAK tPak = (LPTRANSFERPAK)g_pcControllers[i].pPakData; + + if (tPak && tPak->bPakType == PAK_TRANSFER && tPak->bPakInserted && tPak->gbCart.hRamFile != NULL ) + FlushViewOfFile( tPak->gbCart.RamData, (tPak->gbCart.RomData[0x149] == 1 ) ? 0x0800 : tPak->gbCart.iNumRamBanks * 0x2000); + } + return; + } +} diff --git a/Source/nragev20/PakIO.h b/Source/nragev20/PakIO.h new file mode 100644 index 000000000..d8bd176dd --- /dev/null +++ b/Source/nragev20/PakIO.h @@ -0,0 +1,173 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PAKIO_H_ +#define _PAKIO_H_ + +bool InitControllerPak( const int iControl ); +void SaveControllerPak( const int iControl ); +BYTE ReadControllerPak( const int iControl, LPBYTE Command ); +BYTE WriteControllerPak( const int iControl, LPBYTE Command ); +void CloseControllerPak( const int iControl ); +WORD ShowMemPakContent( const unsigned char * bMemPakBinary, HWND hListWindow ); +int TranslateNotesA( const unsigned char * bNote, LPSTR Text, const int iChars ); +int TranslateNotesW( const unsigned char * bNote, LPWSTR Text, const int iChars ); +void FormatMemPak( LPBYTE aMemPak ); +bool SaveNoteFileA( const unsigned char * aMemPak, const int iNote, LPCTSTR pszFileName ); +bool InsertNoteFile( LPBYTE aMemPak, LPCTSTR pszFileName ); +bool RemoveNote( LPBYTE aMemPak, const int iNote ); + +void TexttoHexA( LPCSTR szText, LPBYTE Data, const int nBytes ); +void HextoTextA( const unsigned char * Data, LPSTR szText, const int nBytes ); + +#ifdef _UNICODE +#define TranslateNotes(x,y,z) TranslateNotesW(x,y,z) +#define ReverseNotes(x,y,z) ReverseNotesW(x,y,z) +#else +#define TranslateNotes(x,y,z) TranslateNotesA(x,y,z) +#define ReverseNotes(x,y,z) ReverseNotesA(x,y,z) +#endif + + +//************Raw Data***********// + //byte 1 = number of bytes to send + //byte 2 = number of bytes to recieve + //byte 3 = Command Type + + // get status +#define RD_GETSTATUS 0x00 + // read button values +#define RD_READKEYS 0x01 + // read from controllerpak +#define RD_READPAK 0x02 + // write to controllerpack +#define RD_WRITEPAK 0x03 + // reset controller +#define RD_RESETCONTROLLER 0xff + // read eeprom +#define RD_READEEPROM 0x04 + // write eeprom +#define RD_WRITEEPROM 0x05 + + // Codes for retrieving status + // 0x010300 - A1B2C3FF + + //A1 + // Default GamePad +#define RD_ABSOLUTE 0x01 +#define RD_RELATIVE 0x02 + // Default GamePad +#define RD_GAMEPAD 0x04 + + //B2 +#define RD_EEPROM 0x80 +#define RD_NOEEPROM 0x00 + + //C3 + // No Plugin in Controller +#define RD_NOPLUGIN 0x00 + // Plugin in Controller (Mempack, RumblePack etc) +#define RD_PLUGIN 0x01 + // Pak interface was uninitialized before the call +#define RD_NOTINITIALIZED 0x02 + // Address of last Pak I/O was invalid +#define RD_ADDRCRCERR 0x04 + // eeprom busy +#define RD_EEPROMBUSY 0x80 + +// The Error values are as follows: +// 0x01ER00 - ........ + + //ER + // no error, operation successful. +#define RD_OK 0x00 + // error, device not present for specified command. +#define RD_ERROR 0x80 + // error, unable to send/recieve the number bytes for command type. +#define RD_WRONGSIZE 0x40 + + // the address where rumble-commands are sent to + // this is really 0xC01B but our addressing code truncates the last several bits. +#define PAK_IO_RUMBLE 0xC000 + + // 32 KB mempak +#define PAK_MEM_SIZE 32*1024 +#define PAK_MEM_DEXOFFSET 0x1040 + +// Pak Specific Data // +// First BYTE always determines current Paktype +// this can be different to the paktype in the Controller-structure. +// that makes sure to corectly handle/close the pak. + +//PAK_NONE +//pPakData = NULL; + +//PAK_MEM +typedef struct _MEMPAK +{ + BYTE bPakType; // set to PAK_MEM + HANDLE hMemPakHandle; // a file mapping handle + bool fDexSave; // true if .n64 file, false if .mpk file + bool fReadonly; // set if we can't open mempak file in "write" mode + LPBYTE aMemPakData; //[PAK_MEM_SIZE]; + BYTE aMemPakTemp[0x100]; // some extra on the top for "test" (temporary) data +} MEMPAK, *LPMEMPAK; + +//PAK_RUMBLE +typedef struct _RUMBLEPAK +{ + BYTE bPakType; +// BYTE bRumbleTyp; // obsolete: use g_pcControllers[i].xyz instead --rabid +// BYTE bRumbleStrength; +// bool fVisualRumble; + bool fLastData; // true if the last data sent to block 0x8000 was nonzero +} RUMBLEPAK, *LPRUMBLEPAK; + +#include "GBCart.h" +//PAK_TRANSFER +typedef struct _TRANSFERPAK +{ + BYTE bPakType; + int iCurrentBankNo; + int iCurrentAccessMode; + int iAccessModeChanged; + bool iEnableState; + bool bPakInserted; + GBCART gbCart; +} TRANSFERPAK, *LPTRANSFERPAK; + +//PAK_VOICE +typedef struct _VOICEPAK //not supported +{ + BYTE bPakType; +} VOICEPAK, *LPVOICEPAK; + +//PAK_ADAPTOID +typedef struct _ADAPTOIDPAK +{ + BYTE bPakType; + BYTE bIdentifier; + bool fRumblePak; +} ADAPTOIDPAK, *LPADAPTOIDPAK; + +#endif // #ifndef _PAKIO_H_ diff --git a/Source/nragev20/README.txt b/Source/nragev20/README.txt new file mode 100644 index 000000000..aa9566c4a --- /dev/null +++ b/Source/nragev20/README.txt @@ -0,0 +1,210 @@ +RELEASE Version 2.3c + +Disclaimer: + This software is distributed as is, without any guarantees of + merchantability or fitness for a particular purpose. Basically, + you can't sue us if you screw up your own computer. + This program is freeware released under the GPL. It's freely + distributable, as long as you follow the GPL. You are free to modify it, + but of course we ask that you tell us so we can incorporate bugfixes + in the next version. + Finally, don't try to earn money by distributing it. + +What is it? + This plugin is for use with an N64 emulator that supports input plugins + through Zilmar's input spec. + Some emulators that support it are: Project64, Apollo, 1964, TR64 + +Main Features + Up to four N64 controllers supported + Handles as many game controllers as you can plug in (you may have to tweak + the compile options for huge numbers), plus 1 keyboard and 1 mouse. + Full support of any controls you can see through DirectInput + Emulation of MemPaks, Rumble Paks (via DirectInput Force Feedback), + and Transfer Paks (except GB Tower in Pokemon Stadium games) + Complete Adaptoid support + Up to 256 Configurable "modifiers", in 3 different flavors + System-independent controller profiles + As released, this plugin is compatible with Zilmar's Input Plugin Specs 1.0 + and will work with all emulators that support this spec + +Requirements: + A computer with Windows & DirectX9.0 or higher installed. + An emulator + Some games wouldn't hurt + You need the Microsoft Visual C++ 2010 SP1 Redistributable Package (x86) + +Installation: + Consult your emulator documentation as to where to place the DLL file + (usually its the "plugins" folder or something similar) + Choose the plugin from within the emulator; again, consult the documentation + if you don't know how. + If you have a language .dll, place it in the same directory as your emulator + e.g. project64.exe + +Thanks go out to + Azimer for his help with MemPaks + Zilmar & Jabo for their awesome Project64. + Smiff, Bodie, Cyber, Hotshitu, Gannonboy, Harlay, squall_leonhart, Poobah, Legend + for testing. + MadManMark for adding Transferpaks + RabidDeity for tweaks and additions + aTomIC, Harlay, NaSeR, Siskoo for translations + + +Known Issues: + Old Profiles won't work, this is on purpose. + GB Tower doesn't work in Pokemon Stadium games (not likely to be fixed; just use + a GB emulator to play the games) + No voice pak emulation (only one game supports it anyway) + +For the latest SOURCE CODE please check out trunk from the Subversion server: +https://nragev20.svn.sourceforge.net/svnroot/nragev20/trunk +(you can also find some useful information in the docs directory) +For now, you'll need a copy of Visual Studio... but we're working on a Makefile. + +#---------------------------------------------------------------------# +History: + ++ means fixed/added +/ means changed + +Release 2.3c +/Xinput Rumble and Deadzone fixed (Thanks KrossX) +/Some potential crash and buffer overruns? fixed by kidkat +/Some UI changes to improve readability for high dpi setups + +Release 2.3b +/Xinput config loading fixed ++No longer crashes if an assigned device is removed or not present when starting emulation. +/RC files saved from visual studio break the file lister, reverted and edited with notepad. + +Release 2.2: ++Resolved file browsers not displaying supported file types ++Improved Xinput support by backporting changes from 1964input + +Release 2.2 beta: ++ Experimental Xinput support ++ Fixes to GB Battery support + +Release 2.1 rc3: ++ The last of the shortcut bugs should be fixed. Switching paks should work + just fine; the plugin now inserts a 1 second delay so that the game + can detect the change properly. ++ Message window no longer sucks CPU cycles + + +Release 2.1 rc2: ++ Incorporated koolsmoky's message window patch. The message window should + work perfectly now. + +Release 2.1 rc1: ++ Many many little bugs fixed, and minor tweaks. This should bring the + release versions in line with the tweaks from the DEBUG line. + +Release 2.00b: ++ fixed several problems with Win98; plugin should work under Win98 now ++ fixed several bugs with memory mapped file handles. Solves several crash + issues with mempak or transferpaks ++ changed transfer pak MBC5 code to use proper MBC5 rom bank switching, and + also fixed up MBC3 rom bank switching. This may fix some lingering + transfer pak issues. Also did several tpak speed optimizations + (thanks guille007) + +Release 2.00a: ++ Fixed mouse assignment in Interface. Again. + +Release 2.00 (rabid goes crazy): +/ Large portions of the code completely rewritten. ++ Better detection of devices; more joysticks should work now, as well as steering + wheels and things that aren't strictly "gamepads" ++ .a64 notefile import and export works much better now ++ N64 controllers can now get input from multiple gamepad type devices ++ Now able to assign a key, mouse, or gamepad control to as many N64 control + surfaces as you like ++ international language support +/ device selection for keybinding no longer needed; devices list now shown as + "Force-Feedback Devices" under ControllerPak selection (pick Rumble, and + tick the "RawMode" box) +/ no longer possible to send FF events from multiple controllers to the same FF + device (this shouldn't have worked anyway) ++ capture mouseclicks properly in Controllers tab (disable button clicks while + polling) ++ release exclusive mouse while in config menu (fixes a mouse bind while locked + issue) ++ add independent X/Y mouse sensitivity ++ changed absolute mouse support: now choose between Buffered (default from before), + Absolute, and Deadpan (control only moves while you move the mouse) ++ various optimizations, bugfixes, and spelling fixes ++ LOTS of documentation added to the source; it should be more legible now ++ rewrote controller save and restore (underlying CONTROLLER and BUTTON structs + changed...) +/ Button mappings and modifiers will need to be reset on first load ++ now rewrites mempak and transferpak RAM data to disk almost immediately after + writing to controller (1.83 and previous didn't save the mempak until RomClose) ++ now possible to map shortcuts to buttons and axes as well as keys (be careful) ++ tabbing within the config window actually works now ++ can save and load shortcuts to a file ++ Transferpak MBC5 support fixed (Pokemon Yellow, Perfect Dark), also ROM files should + load much faster now ++ several crash bugs and memory leaks squashed + +Release 1.83: +Changed: Rewrote GB Cart emulation (Now supports ROM-only, MBC1, MBC2, MBC3 and MBC5 carts) +Added: support for GB Cart RTC based on VisualBoy Advance save format. +Added: option for slower rapid-fire in macros. Fixes problems with some games like Paper Mario. +Added: optional and adjustable rapid fire to standard input keys. + +Release 1.82a: +Fixed: Correct handling POV Controls again.. DOH + +Release 1.82: +Added: Transferpak-Emulation - done by MadManMark, so hes the one to thank for this. +Changed: Various cleanups&optimizations, recompiled with VC++ 7.0 + +Release 1.81a: + Fixed a bug introduced by the last version. + +Release 1.81: +Added: Default Profile & default Shortcuts. +Changed: can now open read-only Files, some old & unecessary checks removed + Interface tweaked a bit. + +Release 1.80: +Fixed: another Access Violation, crash within Rumble emulation +Added: MouseLock Shortcut +Changed: Code-Cleanups, "save" and "use" Buttons instead of "Ok" + +Beta 1.79: +Fixed: Access Violations +Added: saving/loading Profiles, visual Rumble, DexDrive support + +Beta 1.78: +Added: MemPak Manager Functions, 2 switchable Analog Stick settings, Config Modifier, absolute KeyBoard setting +Changed: KeyBoard & Mouse Handling + +Beta 1.76: +Only a small Part is based on older Plugins, new gui, new features. +New: Direct Adaptoid support, up to 256 Modifiers, different Rumble settings, Shortcuts +Missing: saving/loading Profiles, Config Modifier, alternate Controlset +Changed: about everything else ;) + +Release 1.61: +Fixed: a small MemPak issue( Perfect Dark ) + +Release 1.60: +Fixed: crashes in Config-Dialog, crashes when a used GamePad isnt available, Toggle-Modifiers now get reset each time a rom is loaded or the configuration changed, now games that reported "no Controller" in RAW Mode will work, multiple Controllers of the same name now get enumerated and detected right. +Changes: Mouse-Axis can now be assigned by moving it. Now all Devices are scaned at once in Config-Window. "Default Axe-Movement" is now replaced by "Default Analog-Stick Range", which means it sets maximum range of the virtual Stick. +Added seperate X/Y Modes for Mouse + +Beta 1.53: Fixed yet more Bugs. Changed Profile-Format, old Profiles wont work( The new Format leaves some Space for future Functions, so they should stay compatible now) +Beta 1.52: Fixed a bunch of bugs, some cleanups, gave the Status-Line a life. +Beta 1.51: Fixed Issues when more than one Pak is used. MemPak is workin now( was alot easier than i thought ). RAW-Handling tweaked. +Beta 1.50b: Finally fixed Rumble Issues, with feedback from bodie & hotshi again. +Beta 1.50: Added Rapid-Fire for Macro-Modifiers, seperate option for negating X/Y Axis. Rumble doesnt works with all gamepads, no clue why not. Thanx to bodie, cyber and hotshitu who gave me allota feedback about Rumble. +Beta 1.49b-d: small Bugfixes, tried to get Rumble working on all GamePads. +Beta 1.49a: fixed some Controllers(including Adaptoid) not working ingame & hopefully the Controllers that dint Rumble +Beta 1.49: some Bugfixes with POV and RRRRRumble is working now! +Beta 1.48: Configuration Routines written from scratch, extended Modifiers, much better Mouse Support, tweaked the whole Code. Almost a new Plugin ;) + +Beta 1.42: This was the last Release before i rewritten the Configuration Stuff, I dint kept track of the Versions before 1.48, many of em were just internal Releases. And I totally messed it up with the Versions-Numbers anyway. diff --git a/Source/nragev20/XInputController.cpp b/Source/nragev20/XInputController.cpp new file mode 100644 index 000000000..17222dcab --- /dev/null +++ b/Source/nragev20/XInputController.cpp @@ -0,0 +1,774 @@ +/* + XInput Controller support for N-Rage`s Dinput8 Plugin by tecnicors + (C) 2009 Daniel Rehren - XInput Controller support + + Author's Email: rehren_007@hotmail.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "XInputController.h" +#include "FileAccess.h" +#include +#include +#include "resource.h" +#include + +BOOL IsXInputDevice( const GUID* pGuidProductFromDirectInput ) +{ + IWbemLocator* pIWbemLocator = NULL; + IEnumWbemClassObject* pEnumDevices = NULL; + IWbemClassObject* pDevices[20] = {0}; + IWbemServices* pIWbemServices = NULL; + BSTR bstrNamespace = NULL; + BSTR bstrDeviceID = NULL; + BSTR bstrClassName = NULL; + DWORD uReturned = 0; + bool bIsXinputDevice= false; + UINT iDevice = 0; + VARIANT var; + HRESULT hr; + + // CoInit if needed + hr = CoInitialize(NULL); + bool bCleanupCOM = SUCCEEDED(hr); + + // Create WMI + hr = CoCreateInstance( __uuidof(WbemLocator), + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IWbemLocator), + (LPVOID*) &pIWbemLocator); + if( FAILED(hr) || pIWbemLocator == NULL ) + goto LCleanup; + + bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );if( bstrNamespace == NULL ) goto LCleanup; + bstrClassName = SysAllocString( L"Win32_PNPEntity" ); if( bstrClassName == NULL ) goto LCleanup; + bstrDeviceID = SysAllocString( L"DeviceID" ); if( bstrDeviceID == NULL ) goto LCleanup; + + // Connect to WMI + hr = pIWbemLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L, + 0L, NULL, NULL, &pIWbemServices ); + if( FAILED(hr) || pIWbemServices == NULL ) + goto LCleanup; + + // Switch security level to IMPERSONATE. + CoSetProxyBlanket( pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, + RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE ); + + hr = pIWbemServices->CreateInstanceEnum( bstrClassName, 0, NULL, &pEnumDevices ); + if( FAILED(hr) || pEnumDevices == NULL ) + goto LCleanup; + + // Loop over all devices + for( ;; ) + { + // Get 20 at a time + hr = pEnumDevices->Next( 10000, 20, pDevices, &uReturned ); + if( FAILED(hr) ) + goto LCleanup; + if( uReturned == 0 ) + break; + + for( iDevice=0; iDeviceGet( bstrDeviceID, 0L, &var, NULL, NULL ); + if( SUCCEEDED( hr ) ) + { + if(var.vt == VT_BSTR && var.bstrVal != NULL) + { + // Check if the device ID contains "IG_". If it does, then it's an XInput device + // This information can not be found from DirectInput + if( wcsstr( var.bstrVal, L"IG_" ) ) + { + // If it does, then get the VID/PID from var.bstrVal + DWORD dwPid = 0, dwVid = 0; + WCHAR* strVid = wcsstr( var.bstrVal, L"VID_" ); + if( strVid && wscanf_s( strVid, L"VID_%4X", &dwVid ) != 1 ) + dwVid = 0; + WCHAR* strPid = wcsstr( var.bstrVal, L"PID_" ); + if( strPid && wscanf_s( strPid, L"PID_%4X", &dwPid ) != 1 ) + dwPid = 0; + + // Compare the VID/PID to the DInput device + DWORD dwVidPid = MAKELONG( dwVid, dwPid ); + if( dwVidPid == pGuidProductFromDirectInput->Data1 ) + { + bIsXinputDevice = true; + goto LCleanup; + } + } + } + VariantClear(&var); + } + SAFE_RELEASE( pDevices[iDevice] ); + } + } + +LCleanup: + if(bstrNamespace) + SysFreeString(bstrNamespace); + if(bstrDeviceID) + SysFreeString(bstrDeviceID); + if(bstrClassName) + SysFreeString(bstrClassName); + for( iDevice=0; iDevice<20; iDevice++ ) + SAFE_RELEASE( pDevices[iDevice] ); + SAFE_RELEASE( pEnumDevices ); + SAFE_RELEASE( pIWbemLocator ); + SAFE_RELEASE( pIWbemServices ); + + if( bCleanupCOM ) + CoUninitialize(); + + return bIsXinputDevice; +} + +void AxisDeadzone( SHORT &AxisValue, long lDeadZoneValue, float fDeadZoneRelation ) +{ + short sign = AxisValue < 0 ? -1 : 1; + float value = AxisValue < 0 ? -AxisValue : AxisValue; + + if(value < lDeadZoneValue) + value = 0; + else + { + value = (value - lDeadZoneValue) * fDeadZoneRelation; + value = value > 32767.0f ? 32767.0f : value; + } + + AxisValue = (SHORT)(value * sign); +} + +void GetXInputControllerKeys( const int indexController, LPDWORD Keys ) +{ + using namespace N64_BUTTONS; + + LPCONTROLLER pcController = &g_pcControllers[indexController]; + LPXCONTROLLER gController = &g_pcControllers[indexController].xiController; + + *Keys = 0; + + if ( !gController->bConfigured ) + return; + + DWORD result; + XINPUT_STATE state; + + result = XInputGetState(gController->nControl, &state); + + if( result != ERROR_SUCCESS ) + return; + + DWORD wButtons = state.Gamepad.wButtons; + + if( pcController->bPadDeadZone > 0 ) + { + const int RANGERELATIVE = 32767; + long lDeadZoneValue = pcController->bPadDeadZone * RANGERELATIVE / 100; + float fDeadZoneRelation = (float)RANGERELATIVE / (float)( RANGERELATIVE - lDeadZoneValue ); + + AxisDeadzone(state.Gamepad.sThumbLX, lDeadZoneValue, fDeadZoneRelation); + AxisDeadzone(state.Gamepad.sThumbLY, lDeadZoneValue, fDeadZoneRelation); + AxisDeadzone(state.Gamepad.sThumbRX, lDeadZoneValue, fDeadZoneRelation); + AxisDeadzone(state.Gamepad.sThumbRY, lDeadZoneValue, fDeadZoneRelation); + } + + short LY = state.Gamepad.sThumbLY * N64_ANALOG_MAX / XC_ANALOG_MAX; + short LX = state.Gamepad.sThumbLX * N64_ANALOG_MAX / XC_ANALOG_MAX; + + short RY = state.Gamepad.sThumbRY * N64_ANALOG_MAX / XC_ANALOG_MAX; + short RX = state.Gamepad.sThumbRX * N64_ANALOG_MAX / XC_ANALOG_MAX; + + short XAx = 0, XAxc = 0; + short YAx = 0, YAxc = 0; + + WORD valButtons = 0; + valButtons |= ( wButtons & gController->stButtons.iDRight ) ? DRight : 0; + valButtons |= ( wButtons & gController->stButtons.iDLeft ) ? DLeft : 0; + valButtons |= ( wButtons & gController->stButtons.iDDown ) ? DDown : 0; + valButtons |= ( wButtons & gController->stButtons.iDUp ) ? DUp : 0; + valButtons |= ( wButtons & gController->stButtons.iStart ) ? Start : 0; + valButtons |= ( wButtons & gController->stButtons.iZ ) ? Z : 0; + valButtons |= ( wButtons & gController->stButtons.iB ) ? B : 0; + valButtons |= ( wButtons & gController->stButtons.iA ) ? A : 0; + valButtons |= ( wButtons & gController->stButtons.iCRight ) ? CRight : 0; + valButtons |= ( wButtons & gController->stButtons.iCLeft ) ? CLeft : 0; + valButtons |= ( wButtons & gController->stButtons.iCDown ) ? CDown : 0; + valButtons |= ( wButtons & gController->stButtons.iCUp ) ? CUp : 0; + valButtons |= ( wButtons & gController->stButtons.iR ) ? R : 0; + valButtons |= ( wButtons & gController->stButtons.iL ) ? L : 0; + + valButtons |= state.Gamepad.bLeftTrigger > 30 ? gController->stAnalogs.iLeftTrigger : 0; + valButtons |= state.Gamepad.bRightTrigger > 30 ? gController->stAnalogs.iRightTrigger : 0; + + if (LX >= BUTTON_ANALOG_VALUE) + valButtons |= gController->stAnalogs.iLXAxis & ((CRight | DRight) << 16) ? gController->stAnalogs.iLXAxis >> 16 : 0; + if (LX <= -BUTTON_ANALOG_VALUE) + valButtons |= gController->stAnalogs.iLXAxis & (CLeft | DLeft) ? gController->stAnalogs.iLXAxis : 0; + if (LY >= BUTTON_ANALOG_VALUE) + valButtons |= gController->stAnalogs.iLYAxis & ((CUp | DUp) << 16) ? gController->stAnalogs.iLYAxis >> 16 : 0; + if (LY <= -BUTTON_ANALOG_VALUE) + valButtons |= gController->stAnalogs.iLYAxis & (CDown | DDown) ? gController->stAnalogs.iLYAxis : 0; + + if (RX >= BUTTON_ANALOG_VALUE) + valButtons |= gController->stAnalogs.iRXAxis & ((CRight | DRight) << 16) ? gController->stAnalogs.iRXAxis >> 16 : 0; + if (RX <= -BUTTON_ANALOG_VALUE) + valButtons |= gController->stAnalogs.iRXAxis & (CLeft | DLeft) ? gController->stAnalogs.iRXAxis : 0; + if (RY >= BUTTON_ANALOG_VALUE) + valButtons |= gController->stAnalogs.iRYAxis & ((CUp | DUp) << 16) ? gController->stAnalogs.iRYAxis >> 16 : 0; + if (RY <= -BUTTON_ANALOG_VALUE) + valButtons |= gController->stAnalogs.iRYAxis & (CDown | DDown) ? gController->stAnalogs.iRYAxis : 0; + + if (gController->stAnalogs.iLXAxis == XAxis) + { + XAx += LX; + XAxc += LX > 0 ? 1 : 0; + } + if (gController->stAnalogs.iRXAxis == XAxis) + { + XAx += RX; + XAxc += RX > 0 ? 1 : 0; + } + if( XAxc ) + XAx /= XAxc; + + if (gController->stAnalogs.iLYAxis == YAxis) + { + YAx += LY; + YAxc += LY > 0 ? 1 : 0; + } + if (gController->stAnalogs.iRYAxis == YAxis) + { + YAx += RY; + YAxc += RY > 0 ? 1 : 0; + } + if( YAxc ) + YAx /= YAxc; + + *Keys = MAKELONG(valButtons, MAKEWORD(XAx, YAx)); +} + +void DefaultXInputControllerKeys( LPXCONTROLLER gController) +{ + using namespace N64_BUTTONS; + + gController->stButtons.iA = XINPUT_GAMEPAD_A | XINPUT_GAMEPAD_Y; + gController->stButtons.iB = XINPUT_GAMEPAD_B | XINPUT_GAMEPAD_X; + gController->stButtons.iStart = XINPUT_GAMEPAD_START | XINPUT_GAMEPAD_BACK; + gController->stButtons.iDDown = XINPUT_GAMEPAD_DPAD_DOWN; + gController->stButtons.iDLeft = XINPUT_GAMEPAD_DPAD_LEFT; + gController->stButtons.iDRight = XINPUT_GAMEPAD_DPAD_RIGHT; + gController->stButtons.iDUp = XINPUT_GAMEPAD_DPAD_UP; + gController->stButtons.iL = XINPUT_GAMEPAD_LEFT_SHOULDER; + gController->stButtons.iR = XINPUT_GAMEPAD_RIGHT_SHOULDER; + gController->stAnalogs.iLeftTrigger = Z; + gController->stAnalogs.iRightTrigger = R; + gController->stAnalogs.iRXAxis = (CRight << 16) | CLeft; + gController->stAnalogs.iRYAxis = (CUp << 16) | CDown; + gController->stAnalogs.iLXAxis = XAxis; + gController->stAnalogs.iLYAxis = YAxis; + gController->bConfigured = true; +} + +void VibrateXInputController( DWORD nController, int LeftMotorVal, int RightMotorVal ) +{ + XINPUT_VIBRATION vibration; + + ZeroMemory( &vibration, sizeof( XINPUT_VIBRATION ) ); + + vibration.wLeftMotorSpeed = LeftMotorVal; + vibration.wRightMotorSpeed = RightMotorVal; + + XInputSetState( nController, &vibration ); +} + +bool InitiateXInputController( LPXCONTROLLER gController, int nControl ) +{ + DWORD result; + XINPUT_STATE state; + + ZeroMemory( &state, sizeof( XINPUT_STATE ) ); + result = XInputGetState( nControl, &state ); + + gController->bConnected = result == ERROR_SUCCESS; + gController->nControl = nControl; + + TCHAR buffer[MAX_PATH]; + GetDirectory( buffer, DIRECTORY_DLL ); + _stprintf_s( buffer, _T("%sXInput Controller %d Config.xcc"), buffer, gController->nControl + 1 ); + FILE *file = _tfopen( buffer, _T("rS") ); + if( file ) + { + LoadXInputConfigFromFile( file, gController ); + fclose( file ); + } + + if( !gController->bConfigured ) + DefaultXInputControllerKeys( gController ); + + return gController->bConnected; +} + +TCHAR * GetN64ButtonNameFromButtonCode( int Button ) +{ + using namespace N64_BUTTONS; + + TCHAR *btnName; + btnName = new TCHAR[10]; + + switch( Button ) + { + case A: _tcscpy_s( btnName, 10, _T( "A" )); break; + case B: _tcscpy_s( btnName, 10, _T( "B" )); break; + case Z: _tcscpy_s( btnName, 10, _T( "Z" )); break; + case L: _tcscpy_s( btnName, 10, _T( "L" )); break; + case R: _tcscpy_s( btnName, 10, _T( "R" )); break; + case Start: _tcscpy_s( btnName, 10, _T( "Start" )); break; + case CUp: _tcscpy_s( btnName, 10, _T( "CUp" )); break; + case CDown: _tcscpy_s( btnName, 10, _T( "CDown" )); break; + case CRight: _tcscpy_s( btnName, 10, _T( "CRight" )); break; + case CLeft: _tcscpy_s( btnName, 10, _T( "CLeft" )); break; + case DUp: _tcscpy_s( btnName, 10, _T( "DUp" )); break; + case DDown: _tcscpy_s( btnName, 10, _T( "DDown" )); break; + case DRight: _tcscpy_s( btnName, 10, _T( "DRight" )); break; + case DLeft: _tcscpy_s( btnName, 10, _T( "DLeft" )); break; + default: _tcscpy_s( btnName, 10, _T( "None" )); + } + return btnName; +} + +TCHAR * GetN64ButtonFromXInputControl( LPXCONTROLLER gController, int XInputButton ) +{ + using namespace N64_BUTTONS; + + if( !gController || !gController->bConfigured ) + return GetN64ButtonNameFromButtonCode( 0 ); + + int N64ButtonCode = 0; + + N64ButtonCode |= gController->stButtons.iA & XInputButton ? A : 0; + N64ButtonCode |= gController->stButtons.iB & XInputButton ? B : 0; + N64ButtonCode |= gController->stButtons.iCDown & XInputButton ? CDown : 0; + N64ButtonCode |= gController->stButtons.iCLeft & XInputButton ? CLeft : 0; + N64ButtonCode |= gController->stButtons.iCRight & XInputButton ? CRight : 0; + N64ButtonCode |= gController->stButtons.iCUp & XInputButton ? CUp : 0; + N64ButtonCode |= gController->stButtons.iDDown & XInputButton ? DDown : 0; + N64ButtonCode |= gController->stButtons.iDLeft & XInputButton ? DLeft : 0; + N64ButtonCode |= gController->stButtons.iDRight & XInputButton ? DRight : 0; + N64ButtonCode |= gController->stButtons.iDUp & XInputButton ? DUp : 0; + N64ButtonCode |= gController->stButtons.iL & XInputButton ? L : 0; + N64ButtonCode |= gController->stButtons.iR & XInputButton ? R : 0; + N64ButtonCode |= gController->stButtons.iStart & XInputButton ? Start : 0; + N64ButtonCode |= gController->stButtons.iZ & XInputButton ? Z : 0; + + return GetN64ButtonNameFromButtonCode( N64ButtonCode ); +} + +TCHAR * GetN64ButtonArrayFromXAnalog( LPXCONTROLLER gController, int XThStickOrXDpad ) +{ + using namespace N64_BUTTONS; + + if( !gController || !gController->bConfigured ) + return NULL; + + TCHAR *name; + name = new TCHAR[15]; + + switch( XThStickOrXDpad ) + { + case XC_LTBS: + if( gController->stAnalogs.iLXAxis == XAxis ) + _tcscpy_s( name, 15, _T( "Analog Stick" )); + else if( gController->stAnalogs.iLXAxis & CLeft ) + _tcscpy_s( name, 15, _T( "C Buttons" )); + else if( gController->stAnalogs.iLXAxis & DLeft ) + _tcscpy_s( name, 15, _T( "DPad" )); + else + _tcscpy_s( name, 15, _T( "None" )); + break; + + case XC_RTBS: + if( gController->stAnalogs.iRXAxis == XAxis ) + _tcscpy_s( name, 15, _T( "Analog Stick" )); + else if( gController->stAnalogs.iRXAxis & CLeft ) + _tcscpy_s( name, 15, _T( "C Buttons" )); + else if( gController->stAnalogs.iRXAxis & DLeft ) + _tcscpy_s( name, 15, _T( "DPad" )); + else + _tcscpy_s( name, 15, _T( "None" )); + break; + + case XC_DPAD: + if( gController->stButtons.iCDown == XINPUT_GAMEPAD_DPAD_DOWN ) + _tcscpy_s( name, 15, _T( "C Button" )); + else if( gController->stButtons.iDDown == XINPUT_GAMEPAD_DPAD_DOWN ) + _tcscpy_s( name, 15, _T( "DPad" )); + else + _tcscpy_s( name, 15, _T( "None" )); + break; + + default: + _tcscpy_s( name, 15, _T( "None" )); + } + return name; +} + +bool ReadXInputControllerKeys( HWND hDlg, LPXCONTROLLER gController ) +{ + if( hDlg == NULL || gController == NULL || !gController->bConfigured) + return false; + + SendDlgItemMessage( hDlg, IDC_XC_A, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonFromXInputControl( gController, XINPUT_GAMEPAD_A )); + SendDlgItemMessage( hDlg, IDC_XC_B, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonFromXInputControl( gController, XINPUT_GAMEPAD_B )); + SendDlgItemMessage( hDlg, IDC_XC_X, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonFromXInputControl( gController, XINPUT_GAMEPAD_X )); + SendDlgItemMessage( hDlg, IDC_XC_Y, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonFromXInputControl( gController, XINPUT_GAMEPAD_Y )); + SendDlgItemMessage( hDlg, IDC_XC_BACK, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonFromXInputControl( gController, XINPUT_GAMEPAD_BACK )); + SendDlgItemMessage( hDlg, IDC_XC_START, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonFromXInputControl( gController, XINPUT_GAMEPAD_START )); + SendDlgItemMessage( hDlg, IDC_XC_LB, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonFromXInputControl( gController, XINPUT_GAMEPAD_LEFT_SHOULDER )); + SendDlgItemMessage( hDlg, IDC_XC_RB, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonFromXInputControl( gController, XINPUT_GAMEPAD_RIGHT_SHOULDER )); + SendDlgItemMessage( hDlg, IDC_XC_LTSB, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonFromXInputControl( gController, XINPUT_GAMEPAD_LEFT_THUMB )); + SendDlgItemMessage( hDlg, IDC_XC_RTSB, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonFromXInputControl( gController, XINPUT_GAMEPAD_RIGHT_THUMB )); + + SendDlgItemMessage( hDlg, IDC_XC_LT, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonNameFromButtonCode( gController->stAnalogs.iLeftTrigger )); + SendDlgItemMessage( hDlg, IDC_XC_RT, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonNameFromButtonCode( gController->stAnalogs.iRightTrigger )); + + SendDlgItemMessage( hDlg, IDC_XC_DPAD, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonArrayFromXAnalog( gController, XC_DPAD )); + SendDlgItemMessage( hDlg, IDC_XC_LTS, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonArrayFromXAnalog( gController, XC_LTBS )); + SendDlgItemMessage( hDlg, IDC_XC_RTS, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonArrayFromXAnalog( gController, XC_RTBS )); + + return true; +} + +int GetComboBoxXInputKey( int ComboBox ) +{ + switch( ComboBox ) + { + case IDC_XC_A: return XINPUT_GAMEPAD_A; + case IDC_XC_B: return XINPUT_GAMEPAD_B; + case IDC_XC_X: return XINPUT_GAMEPAD_X; + case IDC_XC_Y: return XINPUT_GAMEPAD_Y; + case IDC_XC_BACK: return XINPUT_GAMEPAD_BACK; + case IDC_XC_START: return XINPUT_GAMEPAD_START; + case IDC_XC_LB: return XINPUT_GAMEPAD_LEFT_SHOULDER; + case IDC_XC_RB: return XINPUT_GAMEPAD_RIGHT_SHOULDER; + case IDC_XC_LT: return -1; // triggers don't use these macros + case IDC_XC_RT: return -1; + case IDC_XC_LTSB: return XINPUT_GAMEPAD_LEFT_THUMB; + case IDC_XC_RTSB: return XINPUT_GAMEPAD_RIGHT_THUMB; + case IDC_XC_DPAD: return -2; // to handle analogs and dpad + case IDC_XC_LTS: return -2; + case IDC_XC_RTS: return -2; + default: return 0; + } +} + +int GetN64ButtonCode( TCHAR *btnName ) //esta wea esta muy fea, hay que buscar una mejor manera definitivamente.. +{ + using namespace N64_BUTTONS; + + int value = 0; + + if( !_tcscmp( btnName, _T( "A" ))) + value = A; + else if( !_tcscmp( btnName, _T( "B" ))) + value = B; + else if( !_tcscmp( btnName, _T( "R" ))) + value = R; + else if( !_tcscmp( btnName, _T( "L" ))) + value = L; + else if( !_tcscmp( btnName, _T( "Z" ))) + value = Z; + else if( !_tcscmp( btnName, _T( "Start" ))) + value = Start; + else if( !_tcscmp( btnName, _T( "CUp" ))) + value = CUp; + else if( !_tcscmp( btnName, _T( "CDown" ))) + value = CDown; + else if( !_tcscmp( btnName, _T( "CLeft" ))) + value = CLeft; + else if( !_tcscmp( btnName, _T( "CRight" ))) + value = CRight; + else if( !_tcscmp( btnName, _T( "DUp" ))) + value = DUp; + else if( !_tcscmp( btnName, _T( "DDown" ))) + value = DDown; + else if( !_tcscmp( btnName, _T( "DLeft" ))) + value = DLeft; + else if( !_tcscmp( btnName, _T( "DRight" ))) + value = DRight; + + return value; +} + +void ResetXInputControllerKeys( LPXCONTROLLER gController ) +{ + gController->stButtons.iA = 0; + gController->stButtons.iB = 0; + gController->stButtons.iZ = 0; + gController->stButtons.iL = 0; + gController->stButtons.iR = 0; + gController->stButtons.iStart = 0; + gController->stButtons.iCUp = 0; + gController->stButtons.iCLeft = 0; + gController->stButtons.iCDown = 0; + gController->stButtons.iCRight = 0; + gController->stButtons.iDUp = 0; + gController->stButtons.iDLeft = 0; + gController->stButtons.iDDown = 0; + gController->stButtons.iDRight = 0; + + gController->stAnalogs.iLeftTrigger = 0; + gController->stAnalogs.iLXAxis = 0; + gController->stAnalogs.iLYAxis = 0; + gController->stAnalogs.iRightTrigger = 0; + gController->stAnalogs.iRXAxis = 0; + gController->stAnalogs.iRYAxis = 0; +} + +void StoreAnalogConfig( LPXCONTROLLER gController, int ComboBox, int index ) +{ + using namespace N64_BUTTONS; + + switch( index ) + { + case 1: // DPAD + switch( ComboBox ) + { + case IDC_XC_DPAD: + gController->stButtons.iDDown |= XINPUT_GAMEPAD_DPAD_DOWN; + gController->stButtons.iDUp |= XINPUT_GAMEPAD_DPAD_UP; + gController->stButtons.iDLeft |= XINPUT_GAMEPAD_DPAD_LEFT; + gController->stButtons.iDRight |= XINPUT_GAMEPAD_DPAD_RIGHT; + break; + case IDC_XC_LTS: + gController->stAnalogs.iLXAxis = ( DRight << 16 ) | DLeft; + gController->stAnalogs.iLYAxis = ( DUp << 16 ) | DDown; + break; + case IDC_XC_RTS: + gController->stAnalogs.iRXAxis = ( DRight << 16 ) | DLeft; + gController->stAnalogs.iRYAxis = ( DUp << 16 ) | DDown; + break; + } + break; + case 2: // C Buttons + switch( ComboBox ) + { + case IDC_XC_DPAD: + gController->stButtons.iCDown |= XINPUT_GAMEPAD_DPAD_DOWN; + gController->stButtons.iCUp |= XINPUT_GAMEPAD_DPAD_UP; + gController->stButtons.iCLeft |= XINPUT_GAMEPAD_DPAD_LEFT; + gController->stButtons.iCRight |= XINPUT_GAMEPAD_DPAD_RIGHT; + break; + case IDC_XC_LTS: + gController->stAnalogs.iLXAxis = ( CRight << 16 ) | CLeft; + gController->stAnalogs.iLYAxis = ( CUp << 16 ) | CDown; + break; + case IDC_XC_RTS: + gController->stAnalogs.iRXAxis = ( CRight << 16 ) | CLeft; + gController->stAnalogs.iRYAxis = ( CUp << 16 ) | CDown; + break; + } + break; + case 3: // Analog + switch( ComboBox ) + { + case IDC_XC_LTS: + gController->stAnalogs.iLXAxis = XAxis; + gController->stAnalogs.iLYAxis = YAxis; + break; + case IDC_XC_RTS: + gController->stAnalogs.iRXAxis = XAxis; + gController->stAnalogs.iRYAxis = YAxis; + break; + } + break; + } +} + +void StoreXInputControllerKeys( HWND hDlg, LPXCONTROLLER gController ) +{ + LRESULT index = -1; + DWORD value = 0; + + ResetXInputControllerKeys( gController ); + + for( int i = IDC_XC_A; i <= IDC_XC_RTS; i++ ) + { + index = SendDlgItemMessage( hDlg, i, CB_GETCURSEL, 0, 0 ); + value = GetComboBoxXInputKey( i ); + if( value == 0 ) + continue; + else if ( value == -1 ) + { + TCHAR btnName[10] = _T( "\0" ); + SendDlgItemMessage( hDlg, i, CB_GETLBTEXT, index, (LPARAM)(LPTSTR)btnName ); + switch( i ) + { + case IDC_XC_LT: + gController->stAnalogs.iLeftTrigger = GetN64ButtonCode( btnName ); + break; + case IDC_XC_RT: + gController->stAnalogs.iRightTrigger = GetN64ButtonCode( btnName ); + break; + } + continue; + } + else if ( value == -2 ) + { + StoreAnalogConfig( gController, i, index); + continue; + } + + switch( index ) + { + case 1: gController->stButtons.iA |= value; break; + case 2: gController->stButtons.iB |= value; break; + case 3: gController->stButtons.iZ |= value; break; + case 4: gController->stButtons.iL |= value; break; + case 5: gController->stButtons.iR |= value; break; + case 6: gController->stButtons.iStart |= value; break; + case 7: gController->stButtons.iCUp |= value; break; + case 8: gController->stButtons.iCLeft |= value; break; + case 9: gController->stButtons.iCDown |= value; break; + case 10: gController->stButtons.iCRight |= value; break; + case 11: gController->stButtons.iDUp |= value; break; + case 12: gController->stButtons.iDLeft |= value; break; + case 13: gController->stButtons.iDDown |= value; break; + case 14: gController->stButtons.iDRight |= value; break; + } + } + gController->bConfigured = true; +} + +void SaveXInputConfigToFile( FILE *file, LPXCONTROLLER gController ) +{ +// fprintf( file, "[XInput Controller %d]\n", gController->nControl ); + fprintf( file, "A=%lu\n", gController->stButtons.iA ); + fprintf( file, "B=%lu\n", gController->stButtons.iB ); + fprintf( file, "CDown=%lu\n", gController->stButtons.iCDown ); + fprintf( file, "CLeft=%lu\n", gController->stButtons.iCLeft ); + fprintf( file, "CRight=%lu\n", gController->stButtons.iCRight ); + fprintf( file, "CUp=%lu\n", gController->stButtons.iCUp ); + fprintf( file, "DDown=%lu\n", gController->stButtons.iDDown ); + fprintf( file, "DLeft=%lu\n", gController->stButtons.iDLeft ); + fprintf( file, "DRight=%lu\n", gController->stButtons.iDRight ); + fprintf( file, "DUp=%lu\n", gController->stButtons.iDUp ); + fprintf( file, "L=%lu\n", gController->stButtons.iL ); + fprintf( file, "R=%lu\n", gController->stButtons.iR ); + fprintf( file, "Start=%lu\n", gController->stButtons.iStart ); + fprintf( file, "Z=%lu\n", gController->stButtons.iZ ); + fprintf( file, "XAxis=%lu\n", gController->stButtons.iXAxis ); + fprintf( file, "YAxis=%lu\n", gController->stButtons.iYAxis ); + fprintf( file, "LeftTrigger=%lu\n", gController->stAnalogs.iLeftTrigger ); + fprintf( file, "RightTrigger=%lu\n", gController->stAnalogs.iRightTrigger ); + fprintf( file, "LeftXAxis=%lu\n", gController->stAnalogs.iLXAxis ); + fprintf( file, "LeftYAxis=%lu\n", gController->stAnalogs.iLYAxis ); + fprintf( file, "RightXAxis=%lu\n", gController->stAnalogs.iRXAxis ); + fprintf( file, "RightYAxis=%lu\n\n", gController->stAnalogs.iRYAxis ); +} + +void LoadXInputConfigFromFile( FILE *file, LPXCONTROLLER gController ) +{ + char buffer[4096]; + int c = 0; + + while( fgets( buffer, 4096, file )) + { + if( strlen( buffer ) == 1 ) // means end of controller config + break; + c++; + switch( buffer[0] ) + { + case 'A': + sscanf_s( buffer, "A=%lu", &gController->stButtons.iA ); break; + case 'B': + sscanf_s( buffer, "B=%lu", &gController->stButtons.iB ); break; + case 'C': + switch( buffer[1] ) + { + case 'U': + sscanf_s( buffer, "CUp=%lu", &gController->stButtons.iCUp ); break; + case 'D': + sscanf_s( buffer, "CDown=%lu", &gController->stButtons.iCDown ); break; + case 'L': + sscanf_s( buffer, "CLeft=%lu", &gController->stButtons.iCLeft ); break; + case 'R': + sscanf_s( buffer, "CRight=%lu", &gController->stButtons.iCRight ); break; + } + break; + case 'D': + switch( buffer[1] ) + { + case 'U': + sscanf_s( buffer, "DUp=%lu", &gController->stButtons.iDUp ); break; + case 'D': + sscanf_s( buffer, "DDown=%lu", &gController->stButtons.iDDown ); break; + case 'L': + sscanf_s( buffer, "DLeft=%lu", &gController->stButtons.iDLeft ); break; + case 'R': + sscanf_s( buffer, "DRight=%lu", &gController->stButtons.iDRight ); break; + } + break; + case 'L': + switch( buffer[1] ) + { + case '=': + sscanf_s( buffer, "L=%lu", &gController->stButtons.iL ); break; + case 'e': + switch( buffer[4] ) + { + case 'T': + sscanf_s( buffer, "LeftTrigger=%lu", &gController->stAnalogs.iLeftTrigger ); break; + case 'X': + sscanf_s( buffer, "LeftXAxis=%lu", &gController->stAnalogs.iLXAxis ); break; + case 'Y': + sscanf_s( buffer, "LeftYAxis=%lu", &gController->stAnalogs.iLYAxis ); break; + } + break; + } + break; + case 'R': + switch( buffer[1] ) + { + case '=': + sscanf_s( buffer, "R=%lu", &gController->stButtons.iR ); break; + case 'i': + switch( buffer[5] ) + { + case 'T': + sscanf_s( buffer, "RightTrigger=%lu", &gController->stAnalogs.iRightTrigger ); break; + case 'X': + sscanf_s( buffer, "RightXAxis=%lu", &gController->stAnalogs.iRXAxis ); break; + case 'Y': + sscanf_s( buffer, "RightYAxis=%lu", &gController->stAnalogs.iRYAxis ); break; + } + break; + } + break; + case 'Z': + sscanf_s( buffer, "Z=%lu", &gController->stButtons.iZ ); break; + case 'S': + sscanf_s( buffer, "Start=%lu", &gController->stButtons.iStart ); break; + case 'X': + sscanf_s( buffer, "XAxis=%lu", &gController->stButtons.iXAxis ); break; + case 'Y': + sscanf_s( buffer, "YAxis=%lu", &gController->stButtons.iYAxis ); break; + } + } + + gController->bConfigured = c > 20 ; +} diff --git a/Source/nragev20/XInputController.h b/Source/nragev20/XInputController.h new file mode 100644 index 000000000..4059bc574 --- /dev/null +++ b/Source/nragev20/XInputController.h @@ -0,0 +1,160 @@ +/* + XInput Controller support for N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka - N-Rage`s Dinput8 Plugin + (C) 2009 Daniel Rehren - XInput Controller support + + N-Rage`s Dinput8 Plugin: + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + XInput Controller support: + Author's Email: rehren_007@hotmail.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _XINPUTCONTROLLER_H +#define _XINPUTCONTROLLER_H + +//code from http://msdn.microsoft.com/en-us/library/ee417014(VS.85).aspx +#include +#include +//#include <-- only needed for SAFE_RELEASE(x) + +#ifndef SAFE_RELEASE // when Windows Media Device M? is not present +#define SAFE_RELEASE(x) \ + if(x != NULL) \ + { \ + x->Release(); \ + x = NULL; \ + } +#endif + +//----------------------------------------------------------------------------- +// Enum each PNP device using WMI and check each device ID to see if it contains +// "IG_" (ex. "VID_045E&PID_028E&IG_00"). If it does, then it's an XInput device +// Unfortunately this information can not be found by just using DirectInput +//----------------------------------------------------------------------------- +BOOL IsXInputDevice( const GUID* pGuidProductFromDirectInput ); +//END conde from ... + +/* + Xinput header for NRage Plugin, by tecnicors. + + XInput Controller is going to take over the N64 control that matches its + number, ie. first XInput controller is first N64 player, etc. +*/ + +#include "commonIncludes.h" +#include + +//defines +#define N64_ANALOG_MAX 127 +#define XC_ANALOG_MAX 32767 +#define BUTTON_ANALOG_VALUE 107 + +//enums +namespace N64_BUTTONS +{ + // Whith this we can asign buttons to the xinput struct + enum _N64_BUTTONS { A = 0x0080, B = 0x0040, Z = 0x0020, R = 0x1000, L = 0x2000, XAxis = 0x4000, + Start = 0x0010, DUp = 0x0008, DDown = 0x0004, DLeft = 0x0002, YAxis = 0x8000, + DRight = 0x0001, CUp = 0x0800, CDown = 0x0400, CLeft = 0x0200, CRight = 0x0100, + None = 0x0 }; +} + +//structures +typedef struct _XCONTROLLER // XInput controller struct +{ + int nControl; + bool bConnected; + bool bConfigured; + + struct _N64_BUTTONS // For button configurations + { + int iA, iB; + int iStart; + int iL, iR, iZ; + int iXAxis, iYAxis; + int iDUp, iDDown, iDLeft, iDRight; + int iCUp, iCDown, iCLeft, iCRight; + }stButtons; + + struct _XINPUT_ANALOGS // For analog configurations + { + int iLeftTrigger, iRightTrigger; + unsigned int iRXAxis, iRYAxis, iLXAxis, iLYAxis; + }stAnalogs; + +}XCONTROLLER; + +typedef XCONTROLLER *LPXCONTROLLER; + +// Sets the keys pressed for Xinput controller gController, into keys. +void GetXInputControllerKeys( const int indexController, LPDWORD Keys ); +// Sets the default keys for Xinput controller gController. +void DefaultXInputControllerKeys( LPXCONTROLLER gController); +// Vibrates the XInput Control +void VibrateXInputController( DWORD nController, int LeftMotorVal = 65535, int RightMotorVal = 65535 ); +// Initialize nControl XInput enabled controller +bool InitiateXInputController( LPXCONTROLLER gController, int nControl ); + +// XController dialog + +#define XC_DPAD 1 +#define XC_LTBS 2 +#define XC_RTBS 3 + +// Reads current XInput controller key config, and shows it in the dialog. +bool ReadXInputControllerKeys( HWND hDlg, LPXCONTROLLER gController ); +// Stores dialog's button configuration into the XCONTROLLER struct. +void StoreXInputControllerKeys( HWND hDlg, LPXCONTROLLER gController ); +// Fills N64 button comobox with its buttons. +inline void FillN64ButtonComboBox( HWND hDlg, int ComboBox ) +{ + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "None" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "A" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "B" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "Z" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "L" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "R" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "Start" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "C-Up" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "C-Left" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "C-Down" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "C-Right" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "D-Up" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "D-Left" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "D-Down" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "D-Right" )); + SendDlgItemMessage( hDlg, ComboBox, CB_SETCURSEL, 0, ( LPARAM )0 ); +} + +inline void FillN64AnalogComboBox( HWND hDlg, int ComboBox ) +{ + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "None" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "DPad" )); + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "C Buttons" )); + if( ComboBox != IDC_XC_DPAD ) + SendDlgItemMessage( hDlg, ComboBox, CB_ADDSTRING, 0, ( LPARAM )_T( "Analog Stick" )); + SendDlgItemMessage( hDlg, ComboBox, CB_SETCURSEL, 0, ( LPARAM )0); +} + +// Save/Load Keys from own config file + +void SaveXInputConfigToFile( FILE *file, LPXCONTROLLER gController ); +void LoadXInputConfigFromFile( FILE *file, LPXCONTROLLER gController ); + +#endif //_XINPUTCONTROLLER_H \ No newline at end of file diff --git a/Source/nragev20/commonIncludes.h b/Source/nragev20/commonIncludes.h new file mode 100644 index 000000000..dcfc12641 --- /dev/null +++ b/Source/nragev20/commonIncludes.h @@ -0,0 +1,55 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _COMMONINCLUDES_H_ +#define _COMMONINCLUDES_H_ + +#undef WIN32_LEAN_AND_MEAN +#pragma warning(disable:4201) + +#include "settings.h" +#include +#include +#include "resource.h" +#include "Debug.h" + +#if SPECS_VERSION == 0x0100 +#include "./ControllerSpecs/Controller #1.0.h" +#endif // #if SPECS_VERSION == 0x0100 + +#if SPECS_VERSION >= 0x0101 +#include "./ControllerSpecs/Controller #1.1.h" +#endif // #if SPECS_VERSION == 0x0100 + + +#define P_malloc( size ) HeapAlloc( g_hHeap, 0, size ) +#define P_free( memory ) HeapFree( g_hHeap, 0, memory ) +#define P_realloc( memory, size ) \ + ( (memory == NULL) ? P_malloc(size) : HeapReAlloc( g_hHeap, 0, memory, size ) ) + +#ifdef ARRAYSIZE +#undef ARRAYSIZE +#define ARRAYSIZE( array ) (sizeof(array) / sizeof(array[0])) +#endif //ARRAYSIZE + +#endif // #ifndef _COMMONINCLUDES_H_ diff --git a/Source/nragev20/configs/Controller1.cpf b/Source/nragev20/configs/Controller1.cpf new file mode 100644 index 000000000..2a6024a42 --- /dev/null +++ b/Source/nragev20/configs/Controller1.cpf @@ -0,0 +1,37 @@ +Plugged=1 +RawData=1 +PakType=0 +RealN64Range=1 +RapidFireEnabled=0 +RapidFireRate=3 +StickRange=66 +MouseMoveX=0 +MouseMoveY=0 +AxisSet=0 +KeyAbsoluteX=0 +KeyAbsoluteY=0 +PadDeadZone=5 +MouseSensitivityX=100 +MouseSensitivityY=100 +RumbleType=1 +RumbleStrength=80 +VisualRumble=0 +MemPakFile=Mempak1.mpk +Button=0 0 4D 0 5 +Button=0 1 4B 0 5 +Button=0 2 50 0 5 +Button=0 3 48 0 5 +Button=0 4 1C 0 5 +Button=0 5 39 0 5 +Button=0 6 2E 0 5 +Button=0 7 2D 0 5 +Button=0 8 20 0 5 +Button=0 9 1E 0 5 +Button=0 10 1F 0 5 +Button=0 11 11 0 5 +Button=0 12 12 0 5 +Button=0 13 10 0 5 +Button=0 14 CD 0 5 +Button=0 15 CB 0 5 +Button=0 16 D0 0 5 +Button=0 17 C8 0 5 diff --git a/Source/nragev20/configs/Shortcuts.sc b/Source/nragev20/configs/Shortcuts.sc new file mode 100644 index 000000000..2e2a1da21 --- /dev/null +++ b/Source/nragev20/configs/Shortcuts.sc @@ -0,0 +1,3 @@ +Button=0 1 4E 0 5 +Button=0 2 4A 0 5 +Button=-1 0 0F 0 5 diff --git a/Source/nragev20/resource.h b/Source/nragev20/resource.h new file mode 100644 index 000000000..ad81693c1 --- /dev/null +++ b/Source/nragev20/resource.h @@ -0,0 +1,374 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by NRagePluginV2.rc +// +#define IDC_STATIC -1 +#define IDC_STOREINDB 3 +#define IDC_ERASEFROMDB 4 +#define IDC_SAVEPROFILE 5 +#define IDC_UPDATEDB 6 +#define IDC_SAVEBINARY 6 +#define IDC_LOADPROFILE 7 +#define IDC_LOADSHORTCUTS 7 +#define IDUSE 8 +#define IDD_MAINCFGDIALOG 101 +#define IDD_CONTROLLER 104 +#define IDD_SHORTCUT 106 +#define IDD_CONTROLS 108 +#define IDD_CONTROLLERPAK 109 +#define IDD_MODIFIER 111 +#define IDD_PAK_MEMPAK 112 +#define IDD_PAK_TRANSFER 113 +#define IDD_PAK_ADAPTOID 115 +#define IDD_DEVICES 117 +#define IDD_PAK_TEXT 118 +#define IDD_MOD_MOVE 119 +#define IDD_FOLDERS 120 +#define IDD_MOD_MACRO 121 +#define IDD_MOD_CONFIG 122 +#define IDD_PAK_RUMBLE 123 +#define IDR_PROFILE_DEFAULT1 139 +#define IDS_ERR_DINOTFOUND 141 +#define IDS_ERR_DICREATE 142 +#define IDS_DLG_MPCHOOSE 143 +#define IDS_ERR_MPREAD 144 +#define IDR_SHORTCUT1 144 +#define IDR_SHORTCUTS_DEFAULT 144 +#define IDS_ERR_GBROM 145 +#define IDD_XCONTROLS 145 +#define IDS_ERR_GBSRAMERR 146 +#define IDS_VERSTRING 147 +#define IDS_TAB_CONTROLLER 148 +#define IDS_TAB_SHORTCUTS 149 +#define IDS_TAB_CONTROLS 150 +#define IDS_TAB_DEVICES 151 +#define IDS_TAB_MODIFIERS 152 +#define IDS_TAB_CONTROLLERPAK 153 +#define IDS_DLG_CLEAR 154 +#define IDS_DLG_CLEAR_TITLE 155 +#define IDS_DLG_CONTROLRESTORE 156 +#define IDS_DLG_CONTROLRESTORE_TITLE 157 +#define IDS_ERR_PROFWRITE 158 +#define IDS_ERR_PROFREAD 159 +#define IDS_C_POLLING 160 +#define IDS_C_RANGE 161 +#define IDS_D_MSX 162 +#define IDS_D_MSY 163 +#define IDS_D_DEADZONE 164 +#define IDS_D_RUMBLESTR 165 +#define IDS_M_MOVEVALUE 166 +#define IDS_M_TAB_NONE 167 +#define IDS_M_TAB_MOVE 168 +#define IDS_M_TAB_MACRO 169 +#define IDS_M_TAB_CONFIG 170 +#define IDS_M_MOUSE_PREFIX 171 +#define IDS_M_KB_PREFIX 172 +#define IDS_M_NONE 173 +#define IDS_M_MOVE 174 +#define IDS_M_MACRO 175 +#define IDS_M_CONFIG 176 +#define IDS_M_ASSIGNED 177 +#define IDS_M_TYPE 178 +#define IDS_M_PARAM 179 +#define IDS_P_NONE 180 +#define IDS_P_MEMPAK 181 +#define IDS_P_RUMBLEPAK 182 +#define IDS_P_TRANSFERPAK 183 +#define IDS_P_VOICEPAK 184 +#define IDS_P_ADAPTOIDPAK 185 +#define IDS_P_MEM_NORAW 186 +#define IDS_P_RUMBLE_NORAW 187 +#define IDS_P_RUMBLE_RAW 188 +#define IDS_P_TRANSFER_NORAW 189 +#define IDS_P_VOICE_RAW 190 +#define IDS_P_ADAPTOID_NORAW 191 +#define IDS_P_NONE_RAWNORAW 192 +#define IDS_P_MEM_NOCHANGE 193 +#define IDS_P_MEM_NAME 194 +#define IDS_P_MEM_REGION 195 +#define IDS_P_MEM_BLOCKS 196 +#define IDS_DLG_DELETEPAK 197 +#define IDS_DLG_FORMATPAK 198 +#define IDS_DLG_DELETENOTE 199 +#define IDS_P_MEM_BLOCKSFREE 200 +#define IDS_P_MEM_INUSE 201 +#define IDS_P_MEM_WRONGSIZE 202 +#define IDS_P_MEM_NONESELECTED 203 +#define IDS_P_MEM_DAMAGED 204 +#define IDS_BUTTON_UNASSIGNED 205 +#define IDS_STRING206 206 +#define IDS_ERR_SHORTREAD 206 +#define IDS_DLG_SHORTCUTRESTORE 207 +#define IDS_DLG_SHORTCUTRESTORE_TITLE 208 +#define IDS_C_GAMEPAD 209 +#define IDS_C_KEYBOARD 210 +#define IDS_C_MOUSE 211 +#define IDS_C_XAXIS 212 +#define IDS_C_YAXIS 213 +#define IDS_C_ZAXIS 214 +#define IDS_C_XROT 215 +#define IDS_C_YROT 216 +#define IDS_C_ZROT 217 +#define IDS_C_SLIDER 218 +#define IDS_C_POV 219 +#define IDS_C_BUTTON 220 +#define IDS_C_WHEEL 221 +#define IDS_C_UNKNOWN 222 +#define IDS_DLG_ABOUT 223 +#define IDS_DLG_ABOUT_TITLE 224 +#define IDS_ERR_NOINIT 225 +#define IDS_POP_MOUSEUNLOCKED 226 +#define IDS_POP_MOUSELOCKED 227 +#define IDS_POP_CHANGEPAK 228 +#define IDS_ERR_MAPVIEW 229 +#define IDS_DLG_CPF 230 +#define IDS_DLG_MPKN64 231 +#define IDS_DLG_A64 232 +#define IDS_DLG_GBGBC 233 +#define IDS_DLG_SVSAV 234 +#define IDS_ERR_HANDLER 235 +#define IDS_ERR_MEM_NOSPEC 236 +#define IDS_DLG_MEM_READONLY 237 +#define IDS_ERR_MEMOPEN 238 +#define IDS_DLG_MEM_BADADDRESSCRC 239 +#define IDS_P_MEM_NOREGION 240 +#define IDS_P_MEM_BETA 241 +#define IDS_P_MEM_NTSC 242 +#define IDS_P_MEM_GERMANY 243 +#define IDS_P_MEM_USA 244 +#define IDS_P_MEM_FRANCE 245 +#define IDS_P_MEM_ITALY 246 +#define IDS_P_MEM_JAPAN 247 +#define IDS_P_MEM_EUROPE 248 +#define IDS_P_MEM_SPAIN 249 +#define IDS_P_MEM_AUSTRALIA 250 +#define IDS_P_MEM_PAL 251 +#define IDS_P_MEM_UNKNOWNREGION 252 +#define IDS_ERR_NOTEWRITE 253 +#define IDS_ERR_MEMPAK_SPACE 254 +#define IDS_ERR_MEMPAK_NONOTES 255 +#define IDS_ERR_NOTEEOF 256 +#define IDS_ERR_NOTEREAD 257 +#define IDS_ERR_TITLE 258 +#define IDS_DLG_MSG_TITLE 259 +#define IDS_DLG_WARN_TITLE 260 +#define IDS_PLUGIN_TITLE 261 +#define IDS_ERR_MPCREATE 262 +#define IDS_DLG_SC 263 +#define IDS_P_MEM_ERROR 264 +#define IDS_P_R_NODEVICE 265 +#define IDS_STRING266 266 +#define IDS_P_TRANS_NOCHANGE 266 +#define IDS_STRING267 267 +#define IDS_DLG_TPAK_READONLY 267 +#define IDS_STRING268 268 +#define IDS_P_SWITCHING 268 +#define IDC_ROMDESC 1003 +#define IDC_ROMCONFIG 1004 +#define IDC_AUTOCONFIG 1005 +#define IDC_CONTROLLERTAB 1006 +#define IDC_DDOWN 1006 +#define IDC_CURRENTCONFIG 1007 +#define IDC_DLEFT 1007 +#define IDC_ROMID 1008 +#define IDC_DRIGHT 1008 +#define IDC_DUP 1009 +#define IDC_ADOWN 1010 +#define IDC_ALEFT 1011 +#define IDC_ARIGHT 1012 +#define IDC_UPPERTAB 1013 +#define IDC_AUP 1013 +#define IDC_CDOWN 1014 +#define IDC_CLEFT 1015 +#define IDC_CRIGHT 1016 +#define IDC_PAKTYPE 1017 +#define IDC_CUP 1017 +#define IDC_RIGHTTRIGGER 1018 +#define IDC_LEFTTRIGGER 1019 +#define IDC_PAKAREA 1020 +#define IDC_SBUTTON 1020 +#define IDC_ABUTTON 1021 +#define IDC_BBUTTON 1022 +#define IDC_ZTRIGGER 1023 +#define IDC_MEMPAKLIST 1025 +#define IDC_BROWSE 1026 +#define IDC_APPCHANGES 1026 +#define IDC_MEMPAK_BROWSE_ABS 1027 +#define IDC_RESET 1027 +#define IDC_GBSAVE_BROWSE 1027 +#define IDC_GBROM_BROWSE_REL 1028 +#define IDC_MEMPAKBROWSER 1029 +#define IDC_GBROM_BROWSE_ABS 1029 +#define IDC_GBSAVE_BROWSE_ABS 1030 +#define IDC_GBSAVE_BROWSE_REL 1031 +#define IDC_CTRDEVICE 1032 +#define IDC_DEADZONE 1033 +#define IDC_RUMBLE1 1034 +#define IDC_YMODIFIER 1034 +#define IDC_RUMBLE2 1035 +#define IDC_RUMBLE3 1036 +#define IDC_RUMBLESTRENGTH 1037 +#define IDC_MSSENSITIVITY_X 1038 +#define IDC_N64RANGE 1039 +#define IDC_MSSENSITIVITY_Y 1039 +#define IDC_PLUGGED 1040 +#define IDC_CTRRANGE 1041 +#define IDC_RAWMODE 1042 +#define IDT_MSSENSITIVITY_X 1043 +#define IDT_DEADZONE 1044 +#define IDT_RUMBLESTRENGTH 1045 +#define IDT_MSSENSITIVITY_Y 1046 +#define IDT_MEMPAKSTATE 1048 +#define IDT_RANGE 1049 +#define IDC_CLEARCONTROLLER 1050 +#define IDC_MODIFIERLIST 1054 +#define IDC_PROPWINDOW 1055 +#define IDC_KILLMODIFIER 1056 +#define IDC_NEWMODIFIER 1057 +#define IDC_XMODIFIER 1059 +#define IDT_XMODIFIER 1060 +#define IDT_YMODIFIER 1061 +#define IDC_ASSIGNMOD 1063 +#define IDT_ASSIGNMOD 1064 +#define IDC_MODTYP 1065 +#define IDC_MEMPAK_REL 1067 +#define IDC_MEMPAK_ABS 1068 +#define IDC_MEMPAK_REL_EDIT 1069 +#define IDC_MEMPAK_ABS_EDIT 1070 +#define IDC_GBROM_REL 1071 +#define IDC_GBROM_ABS 1072 +#define IDC_GBROM_REL_EDIT 1073 +#define IDC_GBROM_ABS_EDIT 1074 +#define IDC_GBSAVE_REL 1075 +#define IDC_GBSAVE_ABS 1076 +#define IDC_GBSAVE_REL_EDIT 1077 +#define IDC_GBSAVE_ABS_EDIT 1078 +#define IDC_GBSAVE_SAME 1079 +#define IDC_MEMPAK_BROWSE_REL 1081 +#define IDC_CHGDIR 1082 +#define IDT_PAKDESC 1084 +#define IDC_TOGGLE 1085 +#define IDC_XNEGATE 1086 +#define IDC_YNEGATE 1087 +#define IDC_ZTRIG 1090 +#define IDC_RAPIDFIREMODE 1091 +#define IDC_LTRIG 1092 +#define IDC_RTRIG 1093 +#define IDC_SETNOPAK_P1 1096 +#define IDC_LOCKMOUSE 1097 +#define IDT_LEFTTRIGGER 1100 +#define IDT_MODTYP 1100 +#define IDT_RIGHTTRIGGER 1101 +#define IDT_ABUTTON 1102 +#define IDC_SETMEMPAK_P1 1102 +#define IDC_ACCELERATEX 1102 +#define IDT_BBUTTON 1103 +#define IDC_ACCELERATEY 1103 +#define IDT_CDOWN 1104 +#define IDC_SETRUMBLEPAK_P1 1104 +#define IDT_CRIGHT 1105 +#define IDT_CLEFT 1106 +#define IDC_SETTRANSFERPAK_P1 1106 +#define IDT_CUP 1107 +#define IDT_DUP 1108 +#define IDC_SETADAPTOIDPAK_P1 1108 +#define IDT_DLEFT 1109 +#define IDT_DRIGHT 1110 +#define IDC_SWMEMRUMBLE_P1 1110 +#define IDT_DDOWN 1111 +#define IDT_SBUTTON 1112 +#define IDC_SWMEMADAPTOID_P1 1112 +#define IDT_ZTRIGGER 1113 +#define IDT_ADOWN 1114 +#define IDC_SETNOPAK_P2 1114 +#define IDT_ALEFT 1115 +#define IDT_ARIGHT 1116 +#define IDC_SETMEMPAK_P2 1116 +#define IDT_AUP 1117 +#define IDC_SETRUMBLEPAK_P2 1118 +#define IDC_CONFIG1 1119 +#define IDC_SETTRANSFERPAK_P2 1120 +#define IDC_CONFIG2 1120 +#define IDC_CONFIG3 1121 +#define IDC_SETADAPTOIDPAK_P2 1122 +#define IDC_CONFIGCYCLE 1122 +#define IDC_SWMEMRUMBLE_P2 1124 +#define IDC_MOUSEX 1124 +#define IDC_MOUSEY 1125 +#define IDC_SWMEMADAPTOID_P2 1126 +#define IDC_KEYX 1126 +#define IDC_KEYY 1127 +#define IDC_DELMEMPAK 1127 +#define IDC_SETNOPAK_P3 1128 +#define IDC_FORMATMEMPAK 1128 +#define IDC_SAVENOTE 1129 +#define IDC_VISUALRUMBLE 1129 +#define IDC_SETMEMPAK_P3 1130 +#define IDC_INSERTNOTE 1130 +#define IDC_STATE 1130 +#define IDC_DELETENOTE 1131 +#define IDC_SETRUMBLEPAK_P3 1132 +#define IDSAVE 1132 +#define IDC_GBSAVEPANEL 1133 +#define IDC_SETTRANSFERPAK_P3 1134 +#define IDC_MEMPAKPANEL 1134 +#define IDC_GBROMPANEL 1135 +#define IDC_SETADAPTOIDPAK_P3 1136 +#define IDC_SETDEFAULT 1136 +#define IDC_SWMEMRUMBLE_P3 1138 +#define IDC_GBROM_EDIT 1138 +#define IDC_SWMEMADAPTOID_P3 1140 +#define IDC_GBROM_BROWSE 1140 +#define IDC_GBSAVE_EDIT 1141 +#define IDC_SETNOPAK_P4 1142 +#define IDC_VERSIONSTRING 1142 +#define IDC_RAPIDFIREENABLE 1143 +#define IDC_SETMEMPAK_P4 1144 +#define IDC_RAPIDFIRERATE 1145 +#define IDC_SETRUMBLEPAK_P4 1146 +#define IDC_RAPIDFIREMODERATE 1146 +#define IDC_SETTRANSFERPAK_P4 1148 +#define IDC_DEADPANMOUSEY 1148 +#define IDC_BUFFEREDMOUSEY 1149 +#define IDC_SETADAPTOIDPAK_P4 1150 +#define IDC_ABSOLUTEMOUSEY 1150 +#define IDC_DEADPANMOUSEX 1151 +#define IDC_SWMEMRUMBLE_P4 1152 +#define IDC_BUFFEREDMOUSEX 1152 +#define IDC_ABSOLUTEMOUSEX 1153 +#define IDC_SWMEMADAPTOID_P4 1154 +#define IDC_RUMBLETEST 1154 +#define IDC_SETDEFAULTSC 1156 +#define IDC_SAVESHORTCUTS 1157 +#define IDC_COMBO1 1158 +#define IDC_LANGUAGE 1160 +#define IDC_SHOWMESSAGES 1162 +#define IDC_XC_USE 1178 +#define IDC_XINPUT_ENABLER 1179 +#define IDC_XINPUT_TITLE 1180 +#define IDC_XC_A 1181 +#define IDC_XC_B 1182 +#define IDC_XC_X 1183 +#define IDC_XC_Y 1184 +#define IDC_XC_LB 1185 +#define IDC_XC_RB 1186 +#define IDC_XC_LTSB 1187 +#define IDC_XC_RTSB 1188 +#define IDC_XC_LT 1189 +#define IDC_XC_RT 1190 +#define IDC_XC_BACK 1191 +#define IDC_XC_START 1192 +#define IDC_XC_DPAD 1193 +#define IDC_XC_LTS 1194 +#define IDC_XC_RTS 1195 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 147 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1196 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Source/nragev20/settings.h b/Source/nragev20/settings.h new file mode 100644 index 000000000..dd80e1e04 --- /dev/null +++ b/Source/nragev20/settings.h @@ -0,0 +1,139 @@ +/* + N-Rage`s Dinput8 Plugin + (C) 2002, 2006 Norbert Wladyka + + Author`s Email: norbert.wladyka@chello.at + Website: http://go.to/nrage + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _SETTINGS_H_ +#define _SETTINGS_H_ + +#define DIRECTINPUT_VERSION 0x0800 +#define VERSIONNUMBER "2.3c" + + // hacks for GNU C compilers +#ifdef __GNUC__ + +#ifndef WINVER +#define WINVER 0x0500 +#endif // #ifndef WINVER + +#ifndef _WIN32_IE +#define _WIN32_IE 0x0300 +#endif // #ifndef _WIN32_IE + +#ifndef _const unsigned char *_DEFINED +#define _const unsigned char *_DEFINED +typedef const unsigned char *const unsigned char *; +#endif // #ifndef _const unsigned char *_DEFINED + +#endif // #ifdef __GNUC__ + + // Our default buffer size for TCHAR arrays (resources get loaded through here) + // MAKE SURE localized resources do not exceed this limit, or they will be cut off. +#define DEFAULT_BUFFER 256 + + // conform to Plugin Specs 1.0 +#define SPECS_VERSION 0x0100 + // conform to Plugin Specs 1.1 +// #define SPECS_VERSION 0x0101 + + // use default settings for Release and Debugbuild +#define STDCONFIG + +#ifndef STDCONFIG +// ---------------------------------------------------------------------------- +// custom (nonstandard) settings here + // workaround for a Adaptoiddriver bug; + // basically if the Adaptoid USB driver doesn't respond that there's a pak, say there is one anyway +#define ADAPTOIDPAK_RUMBLEFIX + + // remove unimplemented Elements of the GUI +// #define HIDEUNIMPLEMENTED + + // check controllercommands for valid CRC +// #define MAKEADRESSCRCCHECK + // display Button for writing Shortcuts binary +// #define RAWPROFILEWRITE + + // enable selection of Transferpak +// #define V_TRANSFERPAK + // enable selection of VoicePak +// #define V_VOICEPAK +// ---------------------------------------------------------------------------- + +#else +// Standard Settings + +#ifdef _DEBUG +// ---------------------------------------------------------------------------- +// Standard Debug Settings + // workaround for a Adaptoiddriver bug +#define ADAPTOIDPAK_RUMBLEFIX + + // remove unimplemented Elements of the GUI +// #define HIDEUNIMPLEMENTED + + // check controllercommands for valid CRC +#define MAKEADRESSCRCCHECK + // display Button for writing Shortcuts binary +#define RAWPROFILEWRITE + + // enable selection of Transferpak +#define V_TRANSFERPAK + // enable selection of VoicePak +#define V_VOICEPAK + +// spits out loads of extra info for ControllerCommand and ReadController +// #define ENABLE_RAWPAK_DEBUG + +// ---------------------------------------------------------------------------- + +#else +// ---------------------------------------------------------------------------- +// Standard Release Settings + // workaround for a Adaptoiddriver bug +#define ADAPTOIDPAK_RUMBLEFIX + + // remove unimplemented Elements of the GUI +#define HIDEUNIMPLEMENTED + + // check controllercommands for valid CRC +// #define MAKEADRESSCRCCHECK + // display Button for writing Shortcuts binary +// #define RAWPROFILEWRITE + + // enable selection of Transferpak +#define V_TRANSFERPAK + // enable selection of VoicePak +// #define V_VOICEPAK + +// ---------------------------------------------------------------------------- + +#endif // #ifdef _DEBUG +#endif // #ifndef STDCONFIG +#undef STDCONFIG + +#ifdef _DEBUG +#define VERSIONINFO _T(VERSIONNUMBER) _T("-Debugbuild") +#else +#define VERSIONINFO _T(VERSIONNUMBER) +#endif // #ifdef _DEBUG + +#endif // #ifndef _SETTINGS_H_