Skip to content

Instantly share code, notes, and snippets.

@DarkWanderer
Last active August 29, 2015 14:20
Show Gist options
  • Save DarkWanderer/3ac07a213bfc8a02932d to your computer and use it in GitHub Desktop.
Save DarkWanderer/3ac07a213bfc8a02932d to your computer and use it in GitHub Desktop.
Joystick detection test
#include <dinput.h>
#include <assert.h>
#include <exception>
#include <iostream>
#include <string>
#include <chrono>
#include <list>
#pragma region Usings
using std::cout;
using std::endl;
using std::string;
using std::list;
#pragma endregion
#pragma comment (lib,"dxguid.lib")
#pragma comment (lib,"dinput8.lib")
void CheckDxCallResult(HRESULT result)
{
assert(result == DI_OK); // Assertion to be triggered at runtime
if (result != DI_OK)
throw new std::exception("DirectX call was not completed successfully");
}
BOOL __stdcall EnumDevicesCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID referencePointer)
{
auto pDeviceCount = reinterpret_cast<size_t*>(referencePointer);
string instanceName(&pDeviceInstance->tszInstanceName[0]);
string productName(&pDeviceInstance->tszProductName[0]);
cout << " Device:" << endl;
//cout << " Size: " << pDeviceInstance->dwSize << endl;
//cout << " Type: " << pDeviceInstance->dwDevType << endl;
cout << " Name: " << productName << endl;
cout << " Instance: " << instanceName << endl;
(*pDeviceCount)++;
return TRUE;
}
size_t EnumerateGameControllers(IDirectInput8A* directInputObject)
{
cout << "Enumerating devices" << endl;
assert(directInputObject != nullptr);
size_t deviceCount = 0;
CheckDxCallResult(directInputObject->EnumDevices(DI8DEVCLASS_GAMECTRL, &EnumDevicesCallback, &deviceCount, DIEDFL_ATTACHEDONLY));
cout << "Found " << deviceCount << " devices" << endl;
return deviceCount;
}
IDirectInput8* CreateDirectInputObject()
{
HINSTANCE hinstance = GetModuleHandle(nullptr); // A bit of a hack here, see http://forums.codeguru.com/showthread.php?148264-How-to-get-hInstance-handle-in-console-app
IDirectInput8* directInputObject = nullptr;
CheckDxCallResult(DirectInput8Create(hinstance, DIRECTINPUT_VERSION, IID_IDirectInput8, reinterpret_cast<void**>(&directInputObject), nullptr));
return directInputObject;
}
void FillAndFreeMemory()
{
// This function will try to fill memory with blocks until a bad_alloc exception appears
auto start = std::chrono::high_resolution_clock::now();
const size_t blockSize = 1 * 1024;
cout << "Filling memory with blocks of " << blockSize << " bytes" << endl;
try
{
while (true) {
auto arr = new char[blockSize];
}
}
catch (std::bad_alloc& exception)
{
cout << "Caught bad_alloc, memory is full now" << endl;
}
// Uncomment this to try freeing the blocks before enumerating again
//for (auto block : blocks)
// delete[] block;
//blocks.clear();
auto end = std::chrono::high_resolution_clock::now();
cout << "Allocating memory took " << std::chrono::duration<double>(end - start).count() << "s" << endl;
};
int main()
{
cout << "'Disappearing joystick' test v3" << endl;
cout << "This utility tests whether your system is affected by the issue which is causing "
<< "the 'disappearing joystick syndrome' when opening settings in ArmA 3" << endl;
auto di = CreateDirectInputObject();
cout << "Before allocation:" << endl;
auto count1 = EnumerateGameControllers(di);
if (count1 == 0)
{
cout << "This utility requires at least 1 joystick to be present" << endl;
cout << "Plug in a joystick/game controller and restart" << endl;
cout << "Press any key to exit" << endl;
getchar();
exit(1);
}
FillAndFreeMemory();
cout << "After allocation:" << endl;
auto count2 = EnumerateGameControllers(di);
cout << "Finished" << endl;
cout << "Your system seems to be ";
if (count1 == count2)
cout << "NOT ";
cout << "AFFECTED" << endl;
cout << "Press any key to exit" << endl;
getchar();
}
@rogerxxxx
Copy link

What libraries does this snippet rely on for compiling? (ie. Windows 8 SDK?)

What (free or open source) compilers can be used with this snippet?

If the above is easily acquired, I would be more than happy to compile & test the code!

@DarkWanderer
Copy link
Author

Hi rogerxxx,

It relies only on recent versions of Windows SDK - which have DirectX libraries merged. I have not tried any open-source compilers, but I believe any compiler which can compile C++11 programs for windows should be able to handle it. No Microsoft extensions were used.

@rogerxxxx
Copy link

Installed Microsoft Visual 2013 Community (vs2013.4_ce_enu.iso) and Windows 8.1 SDK.

Imported new project from existing code. (ie. joystick/joystick.cpp) Build...

1>------ Build started: Project: joystick, Configuration: Debug Win32 ------
1> joystick.cpp
1> C:\Program Files (x86)\Windows Kits\8.1\Include\um\dinput.h: DIRECTINPUT_VERSION undefined. Defaulting to version 0x0800
1>joystick.cpp(71): warning C4101: 'exception' : unreferenced local variable
1>MSVCRTD.lib(crtexew.obj) : error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup
1>G:\Windows8.1\joystick\Debug\joystick.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

@DarkWanderer
Copy link
Author

You need to compile as Console app, not Windows app

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment