/* * Descent 3 * Copyright (C) 2024 Parallax Software * * 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 3 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, see . --- HISTORICAL COMMENTS FOLLOW --- * $Logfile: /DescentIII/Main/D3Launch/JoystickTab.cpp $ * $Revision: 1.1.1.1 $ * $Date: 2003-08-26 03:56:51 $ * $Author: kevinb $ * * * * $Log: not supported by cvs2svn $ * * 16 5/20/99 12:53p Nate * Added GLSetup window, EAX mixer support, and CHFlight+Mouseman Mode * options * * 15 2/22/99 2:46p Nate * Fixed problem with long joystick names/descriptions * * 14 11/30/98 3:42p Nate * Disabled Force Feedback checkbox for demo * * 13 10/12/98 7:13p Nate * Fixed several bugs. * * 12 10/10/98 4:05p Nate * Added detection/scanning window messages * * 11 10/08/98 6:23p Nate * Fixed a few bugs. * * 10 9/22/98 3:33p Nate * Added conditional compiling to help system (can toggle between HTML and * standard windows help) * * 9 9/21/98 5:40p Nate * Incorporated the new HTML help system * * 8 9/15/98 6:02p Nate * Fixed double detection NT bug. * * 7 9/15/98 6:02p Nate * Added Force Feedback detection. * * 6 9/02/98 6:42p Nate * Added improved sound support. * * 5 9/01/98 7:15p Nate * Major Revision #2 * * 4 8/31/98 6:44p Nate * Major Revision * * 3 8/10/98 10:44a Nate * Added Language selection support * * 2 8/05/98 11:54a Nate * Initial Version * * $NoKeywords: $ */ // JoystickTab.cpp : implementation file // #include "stdafx.h" #include "afxpriv.h" #include "afxext.h" #include #include #include "D3Launch.h" #include "JoystickTab.h" #include "dinput.h" #include "OS_Config.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Declare the joystick data JoystickData joystick_data[MAX_NUM_JOYSTICKS]; int Num_joysticks=0; ///////////////////////////////////////////////////////////////////////////// // CJoystickTab property page IMPLEMENT_DYNCREATE(CJoystickTab, CPropertyPage) CJoystickTab::CJoystickTab() : CPropertyPage(CJoystickTab::IDD) { //{{AFX_DATA_INIT(CJoystickTab) //}}AFX_DATA_INIT } CJoystickTab::~CJoystickTab() { } void CJoystickTab::DoDataExchange(CDataExchange* pDX) { CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CJoystickTab) DDX_Control(pDX, IDC_CHFLIGHT_CHECK, m_CHFlightEnabled); DDX_Control(pDX, IDC_MOUSEMAN_CHECK, m_MousemanEnabled); DDX_Control(pDX, IDC_JOYSTICK_LIST, m_joystick_list); DDX_Control(pDX, IDC_FF_ENABLED, m_ff_enabled); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CJoystickTab, CPropertyPage) //{{AFX_MSG_MAP(CJoystickTab) ON_BN_CLICKED(IDC_BTN_CALIBRATE, OnBtnCalibrate) ON_BN_CLICKED(IDC_BTN_DETECT, OnBtnDetect) ON_CBN_SELCHANGE(IDC_JOYSTICK_LIST, OnSelchangeJoystickList) ON_MESSAGE(WM_COMMANDHELP,OnCommandHelp) ON_WM_HELPINFO() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CJoystickTab message handlers int GetJoystickName(int joy_num,char *szRegKey,char *szReturnName); int di_detect_joysticks(int cur_joy, CComboBox *box); void CJoystickTab::OnBtnCalibrate() { // TODO: Add your control notification handler code here STARTUPINFO si; PROCESS_INFORMATION pi; memset( &si, 0, sizeof(STARTUPINFO) ); si.cb = sizeof(si); BOOL ret = CreateProcess( NULL, // pointer to name of executable module "rundll32.exe shell32.dll,Control_RunDLL joy.cpl", // pointer to command line string NULL, // pointer to process security attributes NULL, // pointer to thread security attributes FALSE, // handle inheritance flag CREATE_DEFAULT_ERROR_MODE, // creation flags NULL, // pointer to new environment block NULL, // pointer to current directory name &si, // pointer to STARTUPINFO &pi // pointer to PROCESS_INFORMATION ); if ( !ret ) { char *lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); // Display the string. CString err_msg; err_msg.LoadString(IDS_JOYSTICKTAB_ERR1); MessageBox( lpMsgBuf, err_msg, MB_OK | MB_ICONEXCLAMATION); // Free the buffer. LocalFree( lpMsgBuf ); } } // Detect all the joysticks void CJoystickTab::DetectSticks() { char str[1024]; int j, max, cur_joy; JOYCAPS JoyCaps; Num_joysticks=0; //m_joystick_list.ResetContent(); // Add "none" option CString none_msg; none_msg.LoadString(IDS_JOYSTICKTAB_NONE); strcpy(joystick_data[Num_joysticks].name,none_msg.GetBuffer(0)); joystick_data[Num_joysticks].FF_capable=FALSE; joystick_data[Num_joysticks].ID=JOYSTICK_NONE_ID; Num_joysticks++; //index = m_joystick_list.InsertString(-1, none_msg); //m_joystick_list.SetItemData(index, 99999); // link joystick id to list item //m_joystick_list.SetCurSel(0); //cur_joy = os_config_read_uint(szSectionName, "CurrentJoystick", 0); cur_joy=0; if (di_detect_joysticks(cur_joy, &m_joystick_list)==0) { max = joyGetNumDevs(); for (j=JOYSTICKID1; j1) selected_stick=1; // First joystick in list else selected_stick=0; // None /* // Clear the list m_joystick_list.ResetContent(); // Read in the selected joystick cur_stick = os_config_read_uint(szSectionName, "CurrentJoystick", JOYSTICK_NONE_ID); // Fill the list with the detected joysticks selected_stick=Num_joysticks-1; for (i=0; iSetWindowText(joystick_data[selected_stick].name); UpdateData(FALSE); // Set the FF checkbox is user wants to use FF int ff_enabled = os_config_read_uint(szSectionName, "EnableJoystickFF", 1); if (ff_enabled && joystick_data[selected_stick].FF_capable) { m_ff_enabled.SetCheck(1); } else { m_ff_enabled.SetCheck(0); } UpdateData(FALSE); // Enable or disable the FF checkbox GetDlgItem(IDC_FF_ENABLED,&hwnd); #ifdef DEMO ::EnableWindow(hwnd, FALSE); #else ::EnableWindow(hwnd, joystick_data[selected_stick].FF_capable); #endif // Set the CHFlight checkbox is user wants to use that mode if(os_config_read_uint(szSectionName, "EnableCHFlight", 0)) { m_CHFlightEnabled.SetCheck(1); } else { m_CHFlightEnabled.SetCheck(0); } UpdateData(FALSE); // Set the Mouseman checkbox is user wants to use that mode if(os_config_read_uint(szSectionName, "EnableMouseman", 0)) { m_MousemanEnabled.SetCheck(1); } else { m_MousemanEnabled.SetCheck(0); } UpdateData(FALSE); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } // JAS: Taken from Nov 1996 Game Developer, page 49. // Damn, that is some UGLY code! (But it works...) /*---------------------------------------------------------------------*/ int GetJoystickName(int joy_num,char *szRegKey,char *szReturnName) /* Description : Opens the MediaResources\Joysitick\mjstick.drv\JoystickSettings and extracts Joystick%dOEMName string Arguments : joy_num (r/o) - Joystick Number szRegKey (r/o) - Registry Key of the msjstick.drv ReturnName (r/w) - Return String for name listed in Control Panel Returns : 0 for success 1 for failure /*-----------------------------------------------------------------------*/ { BYTE KeyStr[MAX_PATH] = REGSTR_PATH_JOYCONFIG; // found in regstr.h BYTE KeyJoySetStr[MAX_PATH] = REGSTR_KEY_JOYSETTINGS; // found in Regstr.h BYTE szOEMName[MAX_PATH]; // OEM name from Current Settings HKEY ConfigKey; HKEY JoyConfigKey; // Joystick Configuration HKEY DriverKey; // Joystick Driver Key HKEY OEMPropKey; HKEY PropKey; DWORD Length; if( ERROR_SUCCESS != RegOpenKey( HKEY_LOCAL_MACHINE,REGSTR_PATH_JOYCONFIG,&ConfigKey ) ) { return( 1 ); // It should never get here key received from Caps } if( ERROR_SUCCESS != RegOpenKey( ConfigKey, szRegKey, &DriverKey ) ) { return( 1 ); // It should never get here key received from Caps } // Open CurrentSettings Key if( ERROR_SUCCESS != RegOpenKey( DriverKey, REGSTR_KEY_JOYCURR, &JoyConfigKey ) ) { return( 1 ); // It should never get here always a Current Settings } sprintf((char *)KeyStr,(char *)REGSTR_VAL_JOYNOEMNAME,joy_num+1); Length=sizeof(szOEMName); // Get OEMNAME Configuration if( ERROR_SUCCESS != RegQueryValueEx( JoyConfigKey,(char *)KeyStr,NULL,NULL,(uint8_t *)&szOEMName,&Length)) { return( 1 ); // No OEM name listed return error } RegCloseKey( ConfigKey ); // Closes the registry Key // Open OEM Properties Key if( ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,REGSTR_PATH_JOYOEM,&PropKey ) ) { return( 1 ); // It should never get here key received from Caps } if( ERROR_SUCCESS != RegOpenKey( PropKey, (char *)szOEMName, &OEMPropKey ) ) { return( 1 ); // It should never get here if device is selected } Length=MAX_PATH; // Get Name as listed in Control Panel if( ERROR_SUCCESS != RegQueryValueEx( OEMPropKey,REGSTR_VAL_JOYOEMNAME,NULL,NULL,(uint8_t *)szReturnName,&Length)) { return( 1 ); // No OEM name listed return error } RegCloseKey( OEMPropKey ); // Closes the registry Key return 0; } /* End GetJoystickName */ void CJoystickTab::OnOK() { // TODO: Add your specialized code here and/or call the base class //int index; int cur_joy = 0; if ( m_ff_enabled.GetCheck() ) { os_config_write_uint( szSectionName, "EnableJoystickFF", 1 ); } else { os_config_write_uint( szSectionName, "EnableJoystickFF", 0 ); } if ( m_CHFlightEnabled.GetCheck() ) { os_config_write_uint( szSectionName, "EnableCHFlight", 1 ); } else { os_config_write_uint( szSectionName, "EnableCHFlight", 0 ); } if ( m_MousemanEnabled.GetCheck() ) { os_config_write_uint( szSectionName, "EnableMouseman", 1 ); } else { os_config_write_uint( szSectionName, "EnableMouseman", 0 ); } /* // save the joystick selected to be used in Descent 3 index = m_joystick_list.GetCurSel(); if (index >= 0) cur_joy = joystick_data[index].ID; os_config_write_uint(szSectionName, "CurrentJoystick", cur_joy); */ OutputDebugString("Setting the joystick!\n"); CPropertyPage::OnOK(); } // Pointers to functions contained in DSOUND.dll int Di_dll_loaded = 0; HINSTANCE Di_dll_handle = NULL; HRESULT (__stdcall *pfn_DirectInputCreate) (HINSTANCE, DWORD, LPDIRECTINPUT *, LPUNKNOWN) = NULL; // obtain the function pointers from the dsound.dll void di_dll_get_functions() { pfn_DirectInputCreate = (HRESULT (__stdcall *) (HINSTANCE, DWORD, LPDIRECTINPUT *, LPUNKNOWN)) GetProcAddress(Di_dll_handle, "DirectInputCreateA"); } // Load the dsound.dll, and get funtion pointers // exit: 0 -> dll loaded successfully // !0 -> dll could not be loaded int di_dll_load() { if (!Di_dll_loaded) { Di_dll_handle = LoadLibrary("dinput.dll"); if (!Di_dll_handle) return -1; di_dll_get_functions(); Di_dll_loaded = 1; } return 0; } void di_dll_free() { if (Di_dll_loaded) { FreeLibrary(Di_dll_handle); Di_dll_handle = NULL; Di_dll_loaded = 0; } } typedef struct { CComboBox *box; int cur_joy; int count; } stuff; // Create storage for any temporary debug messages char msg_buffer[1024]; // Callback function for enumerating ALL joysticks BOOL CALLBACK enum_joysticks(LPCDIDEVICEINSTANCE lpddi, LPVOID ptr) { int num; stuff *stuffp = (stuff *) ptr; OutputDebugString("Found joystick in enum!\n"); sprintf(msg_buffer,"%s (%s)\n", lpddi->tszProductName, lpddi->tszInstanceName); OutputDebugString(msg_buffer); // Make sure it is a joystick if (strnicmp(lpddi->tszInstanceName, "Joystick ", 9)) return DIENUM_CONTINUE; // Get the joystick number num = atoi(lpddi->tszInstanceName + 9) - 1; sprintf(msg_buffer,"num=%d\n",num); OutputDebugString(msg_buffer); // Fill in the data sprintf(joystick_data[Num_joysticks].name, "%s (%s)", lpddi->tszProductName, lpddi->tszInstanceName); joystick_data[Num_joysticks].FF_capable=FALSE; joystick_data[Num_joysticks].ID=num; /* i = stuffp->box->InsertString(-1, joystick_data[Num_joysticks].name); stuffp->box->SetItemData(i, num); if (num == stuffp->cur_joy) stuffp->box->SetCurSel(i); */ Num_joysticks++; stuffp->count++; return DIENUM_CONTINUE; } // Callback function for enumerating ONLY force feedback joysticks BOOL CALLBACK enum_ff_joysticks(LPCDIDEVICEINSTANCE lpddi, LPVOID ptr) { int i, num; OutputDebugString("Found force feedback joystick in enum!\n"); sprintf(msg_buffer, "%s (%s)\n", lpddi->tszProductName, lpddi->tszInstanceName); OutputDebugString(msg_buffer); // Make sure it is a joystick if (strnicmp(lpddi->tszInstanceName, "Joystick ", 9)) return DIENUM_CONTINUE; // Get the joystick number num = atoi(lpddi->tszInstanceName + 9) - 1; // Set the ff_capable flag of this joystick for(i=0;itszInstanceName); if (strnicmp(buf, "Joystick ", 9)) return DIENUM_CONTINUE; // Get the joystick number num = atoi(buf + 9) - 1; // Get the name sprintf(buf, "%s (%s)", lpddi->tszProductName, lpddi->tszInstanceName); // Fill in the data strcpy(joystick_data[Num_joysticks].name,buf); joystick_data[Num_joysticks].FF_capable=FALSE; joystick_data[Num_joysticks].ID=num; Num_joysticks++; i = stuffp->box->InsertString(-1, buf); stuffp->box->SetItemData(i, num); if (num == stuffp->cur_joy) stuffp->box->SetCurSel(i); stuffp->count++; */ return DIENUM_CONTINUE; } int di_detect_joysticks(int cur_joy, CComboBox *box) { HRESULT hr; LPDIRECTINPUT di_joystick_obj; stuff s; if (di_dll_load()) return 0; if (!pfn_DirectInputCreate) { di_dll_free(); return 0; } hr = pfn_DirectInputCreate(GetModuleHandle(NULL), DIRECTINPUT_VERSION, &di_joystick_obj, NULL); if (FAILED(hr)) { hr = pfn_DirectInputCreate(GetModuleHandle(NULL), 0x300, &di_joystick_obj, NULL); if (FAILED(hr)) { di_dll_free(); return 0; } } s.count = 0; s.box = box; s.cur_joy = cur_joy; //hr = di_joystick_obj->EnumDevices(DIDEVTYPE_JOYSTICK, enum_joysticks, &s, DIEDFL_ALLDEVICES); hr = di_joystick_obj->EnumDevices(DIDEVTYPE_JOYSTICK, enum_joysticks, &s, DIEDFL_ATTACHEDONLY); if(hr==DIERR_INVALIDPARAM) { OutputDebugString("Bad parm\n"); } if (FAILED(hr)) { di_joystick_obj->Release(); di_dll_free(); return 0; } // Enumerate any force feedback devices if at least one joystick was found if(s.count>0) { hr = di_joystick_obj->EnumDevices(DIDEVTYPE_JOYSTICK, enum_ff_joysticks, &s, DIEDFL_FORCEFEEDBACK | DIEDFL_ATTACHEDONLY); if(hr==DIERR_INVALIDPARAM) { OutputDebugString("Bad parm\n"); } if (FAILED(hr)) { di_joystick_obj->Release(); di_dll_free(); return s.count; // return the number found in first enum } } di_joystick_obj->Release(); di_dll_free(); return s.count; } void CJoystickTab::OnBtnDetect() { // TODO: Add your control notification handler code here //int cur_stick, i; int selected_stick; HWND hwnd; // Set the wait cursor CWaitCursor wc; // Display the scanning window m_MsgDlg.m_ScanningMsg.LoadString(IDS_JOYSTICKTAB_SCANNING); m_MsgDlg.m_WaitMsg.LoadString(IDS_PLEASE_WAIT_MSG); m_MsgDlg.Create(IDD_MSG_DLG,this); m_MsgDlg.ShowWindow(SW_SHOW); m_MsgDlg.UpdateData(FALSE); // Detect all available joysticks DetectSticks(); // Remove the scanning window m_MsgDlg.DestroyWindow(); // Take the first joystick (if one exists) if(Num_joysticks>1) selected_stick=1; // First joystick in list else selected_stick=0; // None /* // Clear the list m_joystick_list.ResetContent(); // Read in the selected joystick cur_stick = Num_joysticks-1; // Fill the list with the detected joysticks selected_stick=Num_joysticks-1; for (i=0; iSetWindowText(joystick_data[selected_stick].name); UpdateData(FALSE); // Set the FF checkbox is user wants to use FF int ff_enabled = os_config_read_uint(szSectionName, "EnableJoystickFF", 1); if (ff_enabled && joystick_data[selected_stick].FF_capable) { m_ff_enabled.SetCheck(1); } else { m_ff_enabled.SetCheck(0); } // Enable or disable the FF checkbox GetDlgItem(IDC_FF_ENABLED,&hwnd); #ifdef DEMO ::EnableWindow(hwnd, FALSE); #else ::EnableWindow(hwnd, joystick_data[selected_stick].FF_capable); #endif UpdateData(FALSE); } void CJoystickTab::OnSelchangeJoystickList() { // TODO: Add your control notification handler code here int index; HWND hwnd; // Get the new joystick list position index=m_joystick_list.GetCurSel(); // Enable or disable the FF checkbox if(index>=0 && index