/***************************************************************************/ /* Description: Keyboard.c Part of CPA INO */ /* */ /* Author: F. Jentey */ /* Last Update: 05/03/97 */ /* 30/07/97 Direct Input */ /***************************************************************************/ #include #include "INOInit.h" #include "Keyboard.h" #define C_wMaxSimultanousKey 10 #define C_wDemoSize 5000 /* Define the executing mode */ #define C_wKbNormalMode 0 #define C_wKbDemoPlayingMode 1 #define C_wKbDemoRecordingMode 2 #define C_ucKeyToggled 0x01 /****************************************************************************** tdsKbHistoryRecord : keyboard history information record We suppose that there can't have more than 10 pressed keys simultanously. ******************************************************************************/ typedef struct _td_stKbHistoryRecord { short m_wKeyCode[C_wMaxSimultanousKey]; u_long m_ulRecordTimeCount; u_short m_uwKeyPressedNumber; } td_stKbHistoryRecord; typedef struct _td_stKbDemoRecord { short m_wPressedKeyCount; short m_wPressedKeyTab[C_wMaxSimultanousKey]; } td_stKbDemoRecord; /************************************************************************** Globale vars ***************************************************************************/ /* Keyboard device interface*/ LPDIRECTINPUTDEVICE INO_g_p_stKeyboardInterface; short INO_g_wKeyboardAcquired = 0; /* Keyboard config variables : get the country keyboard config */ char KbLib_LayoutName[KL_NAMELENGTH]; HKL KbLib_LayoutHandle; /* Buffers for the keyboard state */ BYTE KbLib_acTabKey[2][256]; u_short KbLib_uwCurrentTab; /* Table for virtual key code use for ASCII conversion */ /* KbLib_acDikToVirtual is used for the numeric pad, coz */ /* MapVirtualKeyEx() doesn't Verr Num state. */ BYTE KbLib_acVirtualKeyCodeTab[256]; BYTE KbLib_acDikToVirtual[256]; /* Store the key use in the game */ u_short ActiveKey[128]; u_short ActiveKeyNumber; /* Variable to handle the history */ td_stKbHistoryRecord KbLib_H[16]; u_short KbLib_uwHSize; u_short KbLib_uwHHead; u_short KbLib_uwHValidEntries; u_short KbLib_uwKbOk = 0; /* Info variables */ u_long KbLib_ulCounter; short KbLib_wLastKey; short KbLib_wLastASCII; short StateHasChanged; char CurrentString[20]; short CurrentStringLength; u_long ulKbErrorCode; /* Demo mode support */ short KbLib_wCurrentMode; short KbDemoRecordCount, KbDemoRecordCurrent; td_stKbDemoRecord KbDemoRecordTab[C_wDemoSize]; FILE *KbDataDemoFile; short ExitDemoKeyTab[16]; short ExitDemoKeyCount; char KbDemoFileHeader[] = "KeyboardSequence"; char KbErrorString[10][100] = { "You must initialize the keyboard.lib first, see fn_wKbInitKeyboard.", "Wrong key code.", "This function can only be called in demo recording mode.", "You are currently in demo recording or playing mode.", "This function can only be called in demo playing mode.", "Unrecognize file format.", "The function can't open or read the demo file.", "The index in the historic tab is out of range.", "The application has lost the input focus.", "Direct input error." }; char g_cIsAzerty; /********************************************************************* INITIALISATION *********************************************************************/ /* This function must be called one time when the game is launched. The parameter HistorySize is the number of previous status conserve. */ short fn_wKbASCIICode(short wKeyCode); short INO_fn_wInitKeyboard(short wHistorySize, HINSTANCE hInstance, HWND hWindow) { #ifdef INO_USE_DIRECT_INPUT GUID guid = GUID_SysKeyboard; HRESULT DInputErr; #endif u_short i; short wASCIIForKeyA; if (KbLib_uwKbOk == 1) return (0); /*===================================*/ /*============= DInput ==============*/ #ifdef INO_USE_DIRECT_INPUT if (!INO_fn_wInitDirectInput(hInstance,hWindow)) return(C_wKbError); DInputErr = INO_g_p_stDInputInterface->lpVtbl->CreateDevice( INO_g_p_stDInputInterface, &guid, &INO_g_p_stKeyboardInterface, NULL ); switch (DInputErr) { case DI_OK: break; case DIERR_INVALIDPARAM: case DIERR_OUTOFMEMORY: case DIERR_NOINTERFACE: case DIERR_DEVICENOTREG: INO_fn_vReleaseDirectInput(); return(C_wKbError); } /* Make sure the keyboard noit acquire before calling setDataFormat and */ /* SetCooperativeLevel. Return always OK */ DInputErr = INO_g_p_stKeyboardInterface->lpVtbl->Unacquire(INO_g_p_stKeyboardInterface); INO_g_wKeyboardAcquired = 0; /* Tell DirectInput that we want to receive data in keyboard format */ DInputErr = INO_g_p_stKeyboardInterface->lpVtbl->SetDataFormat( INO_g_p_stKeyboardInterface, &c_dfDIKeyboard ); switch (DInputErr) { case DI_OK: break; case DIERR_INVALIDPARAM: case DIERR_ACQUIRED: INO_g_p_stKeyboardInterface->lpVtbl->Release(INO_g_p_stKeyboardInterface); INO_fn_vReleaseDirectInput(); return(C_wKbError); break; } /* Set cooperative level */ DInputErr = INO_g_p_stKeyboardInterface->lpVtbl->SetCooperativeLevel( INO_g_p_stKeyboardInterface, hWindow, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND ); switch (DInputErr) { case DI_OK: break; case DIERR_INVALIDPARAM: INO_g_p_stKeyboardInterface->lpVtbl->Release(INO_g_p_stKeyboardInterface); INO_fn_vReleaseDirectInput(); return(C_wKbError); } /* Try to acquire the keyboard */ DInputErr = INO_g_p_stKeyboardInterface->lpVtbl->Acquire(INO_g_p_stKeyboardInterface); switch (DInputErr) { case DI_OK: case S_FALSE: /* Already acquired, OK */ INO_g_wKeyboardAcquired = 1; break; case DIERR_INPUTLOST: INO_g_wKeyboardAcquired = 0; break; case DIERR_INVALIDPARAM: INO_g_wKeyboardAcquired = 0; INO_g_p_stKeyboardInterface->lpVtbl->Release(INO_g_p_stKeyboardInterface); INO_fn_vReleaseDirectInput(); return(C_wKbError); } #else /*===================================*/ /*========= Without DInput ==========*/ INO_g_wKeyboardAcquired = 1; #endif /*===================================*/ /*===================================*/ memset(KbLib_H,0,sizeof(td_stKbHistoryRecord)*16); memset(KbLib_acTabKey,0,sizeof(BYTE)*256*2); memset(ActiveKey,0,sizeof(u_short)*128); memset(CurrentString,0,17); KbLib_uwHHead = 0; KbLib_uwHSize = 16; /* wHistorySize */ KbLib_uwHValidEntries = 0; KbLib_ulCounter = 0; ActiveKeyNumber = 0; KbLib_uwCurrentTab = 0; /* For ASCII conversion */ GetKeyboardLayoutName(KbLib_LayoutName); KbLib_LayoutHandle = LoadKeyboardLayout(KbLib_LayoutName,KLF_ACTIVATE); /* Keyboard OK */ KbLib_uwKbOk = 1; /* Set the default active Key (All keys) */ for ( i=0x01 ; i<0x58 ; i++ ) INO_fn_wAddActiveKey(i); INO_fn_wAddActiveKey(0x69); /* Pause */ INO_fn_wAddActiveKey(0x9c); INO_fn_wAddActiveKey(0x9d); INO_fn_wAddActiveKey(0xb5); INO_fn_wAddActiveKey(0xb7); INO_fn_wAddActiveKey(0xb8); INO_fn_wAddActiveKey(0xc7); INO_fn_wAddActiveKey(0xc5); /* Num Lock */ INO_fn_wAddActiveKey(0xc8); INO_fn_wAddActiveKey(0xc9); INO_fn_wAddActiveKey(0xcb); INO_fn_wAddActiveKey(0xcd); INO_fn_wAddActiveKey(0xcf); INO_fn_wAddActiveKey(0xd0); INO_fn_wAddActiveKey(0xd1); INO_fn_wAddActiveKey(0xd2); INO_fn_wAddActiveKey(0xd3); INO_fn_wAddActiveKey(0xdb); INO_fn_wAddActiveKey(0xdc); INO_fn_wAddActiveKey(0xdd); /* Fill the Dik to Virtual key code translation table */ /* for numeric pad (Vk when Verr Num is ON) */ KbLib_acDikToVirtual[C_ucKey_PAD_0] = VK_NUMPAD0; KbLib_acDikToVirtual[C_ucKey_PAD_1] = VK_NUMPAD1; KbLib_acDikToVirtual[C_ucKey_PAD_2] = VK_NUMPAD2; KbLib_acDikToVirtual[C_ucKey_PAD_3] = VK_NUMPAD3; KbLib_acDikToVirtual[C_ucKey_PAD_4] = VK_NUMPAD4; KbLib_acDikToVirtual[C_ucKey_PAD_5] = VK_NUMPAD5; KbLib_acDikToVirtual[C_ucKey_PAD_6] = VK_NUMPAD6; KbLib_acDikToVirtual[C_ucKey_PAD_7] = VK_NUMPAD7; KbLib_acDikToVirtual[C_ucKey_PAD_8] = VK_NUMPAD8; KbLib_acDikToVirtual[C_ucKey_PAD_9] = VK_NUMPAD9; KbLib_acDikToVirtual[C_ucKey_PAD_DIV] = VK_DIVIDE; KbLib_acDikToVirtual[C_ucKey_PAD_MUL] = VK_MULTIPLY; KbLib_acDikToVirtual[C_ucKey_PAD_SUB] = VK_SUBTRACT; KbLib_acDikToVirtual[C_ucKey_PAD_ADD] = VK_ADD; KbLib_acDikToVirtual[C_ucKey_PAD_POINT] = VK_DECIMAL; /*===================================*/ /*========= Without DInput ==========*/ #ifndef INO_USE_DIRECT_INPUT for (i=0; i0x53)) && (ActiveKey[i]!=0xb5) ) KbLib_acDikToVirtual[ActiveKey[i]] = MapVirtualKeyEx(ActiveKey[i], 1, KbLib_LayoutHandle); } KbLib_acDikToVirtual[C_ucKey_UP] = VK_UP; KbLib_acDikToVirtual[C_ucKey_DOWN] = VK_DOWN; KbLib_acDikToVirtual[C_ucKey_LEFT] = VK_LEFT; KbLib_acDikToVirtual[C_ucKey_RIGHT] = VK_RIGHT; KbLib_acDikToVirtual[C_ucKey_INS] = VK_INSERT; KbLib_acDikToVirtual[C_ucKey_DEL] = VK_DELETE; KbLib_acDikToVirtual[C_ucKey_HOME] = VK_HOME; KbLib_acDikToVirtual[C_ucKey_END] = VK_END; KbLib_acDikToVirtual[C_ucKey_PRIOR] = VK_PRIOR; KbLib_acDikToVirtual[C_ucKey_NEXT] = VK_NEXT; #endif /*===================================*/ /*===================================*/ /* Demo mode initialization */ KbLib_wCurrentMode = C_wKbNormalMode; ExitDemoKeyCount = 1; fn_wKbAddExitDemoKey(C_ucKey_ESC); CurrentStringLength = 0; /* Find keyboard type (Azerty / Qwerty) */ /* wASCIIForKeyA = INO_fn_wDikToAscii(C_ucKey_A,hDev) & 0xFF;*/ wASCIIForKeyA = fn_wKbASCIICode( C_ucKey_A )& 0xFF; if ((wASCIIForKeyA == 'a') || (wASCIIForKeyA == 'A')) g_cIsAzerty = 1; else g_cIsAzerty = 0; return (0); } /* Reinitialization of the keyboard. The history is clear. */ short INO_fn_wResetKeyboard(void) { if (KbLib_uwKbOk == 0) { ulKbErrorCode = C_ErrKeyboardNotInitialized; return (C_wKbError); } /* TO DO */ return (0); } /* This function free memory and release keyboard ressource. */ short INO_fn_wFreeKeyboard(void) { if (KbLib_uwKbOk == 0) { ulKbErrorCode = C_ErrKeyboardNotInitialized; return (C_wKbError); } /*===================================*/ /*============= DInput ==============*/ #ifdef INO_USE_DIRECT_INPUT if (INO_g_wKeyboardAcquired) INO_g_p_stKeyboardInterface->lpVtbl->Unacquire(INO_g_p_stKeyboardInterface); INO_g_p_stKeyboardInterface->lpVtbl->Release(INO_g_p_stKeyboardInterface); INO_fn_vReleaseDirectInput(); #endif /*===================================*/ /*===================================*/ INO_g_wKeyboardAcquired = 0; KbLib_uwKbOk = 0; return (0); } /* This function returns the number of keys of the keyboard. */ short INO_fn_wGetNumberOfKey() { int result; if (KbLib_uwKbOk == 0) { ulKbErrorCode = C_ErrKeyboardNotInitialized; return (C_wKbError); } result = GetKeyboardType(0); switch(result) { case 1: /* IBM® PC/XT® ( ) or compatible (83-key) keyboard */ return(83); case 2: /* Olivetti® "ICO" (102-key) keyboard */ return(102); case 3: /* IBM PC/AT® (84-key) or similar keyboard */ return(84); case 4: /* IBM enhanced (101- or 102-key) keyboard */ return(102); } /* TO DO: error message */ return (C_wKbError); } /******************************************************************** Configuration functions ********************************************************************/ /* Remove an active key. An error occurs when the specified key isn't active.By default, all keys are active, but you can remove some keys if they aren't used to speed up the fn_wKbRead function. */ short INO_fn_wRemoveActiveKey(short wKeyCode) { u_short i, j; if (KbLib_uwKbOk == 0) { ulKbErrorCode = C_ErrKeyboardNotInitialized; return (C_wKbError); } for ( i=0 ; i 127 ) { /* TO DO: error message */ return (C_wKbError); } /* Test if key is already active */ for ( i=0 ; ilpVtbl->Acquire(INO_g_p_stKeyboardInterface); switch (DInputErr) { case DI_OK: case S_FALSE: INO_g_wKeyboardAcquired = 1; break; case DIERR_INPUTLOST: ulKbErrorCode = C_ErrFocusLost; return (C_wKbError); case DIERR_INVALIDPARAM: INO_g_wKeyboardAcquired = 0; ulKbErrorCode = C_ErrDirectInputError; return (C_wKbError); default: break; } } /* Read all key */ DInputErr = INO_g_p_stKeyboardInterface->lpVtbl->GetDeviceState( INO_g_p_stKeyboardInterface, sizeof(BYTE)*256, KbLib_acTabKey[KbLib_uwCurrentTab] ); switch (DInputErr) { case DI_OK: INO_g_wKeyboardAcquired = 1; break; case E_PENDING: break; case DIERR_INPUTLOST: /*case DIERR_NOTACQUIRED:*/ INO_g_wKeyboardAcquired = 0; ulKbErrorCode = C_ErrFocusLost; return (C_wKbError); case DIERR_INVALIDPARAM: INO_g_wKeyboardAcquired = 0; ulKbErrorCode = C_ErrDirectInputError; return(C_wKbError); default: break; } #else /*===================================*/ /*========= Without DInput ==========*/ for ( i=0 ; i= KbDemoRecordCount) || (i < ActiveKeyNumber) ) fn_wKbExitDemoPlaying(); else { memset(KbLib_acTabKey[KbLib_uwCurrentTab],0,sizeof(BYTE)*256); for ( i=0 ; i KbLib_uwHValidEntries - 1 ) { ulKbErrorCode =C_ErrHistoricOverflow; return (C_wKbError); } else { index = KbLib_uwHHead - wHistoryIndex; if ( index < 0 ) index += KbLib_uwHSize; for ( i=0 ; i KbLib_uwHValidEntries-1 ) { ulKbErrorCode =C_ErrHistoricOverflow; return (C_wKbError); } index = KbLib_uwHHead - wHistoryIndex; if ( index < 0 ) index += KbLib_uwHSize; *p_ulCount = KbLib_H[KbLib_uwHHead].m_ulRecordTimeCount - KbLib_H[index].m_ulRecordTimeCount; return (0); } /* This function compares the string pointed by the p_szTestString with the string formed with the last pressed key. */ short INO_fn_wCompareWithCurrentString(char *p_szTestString) { short l, i; if (KbLib_uwKbOk == 0) { ulKbErrorCode = C_ErrKeyboardNotInitialized; return (C_wKbError); } l = strlen(p_szTestString); if ( l > 16 ) return (C_wKbFalse); if ( l > CurrentStringLength ) return (C_wKbFalse); for ( i = 0 ; i < l ; i++ ) if ( p_szTestString[l-i-1] != CurrentString[CurrentStringLength-i-1] ) break; if ( i == l ) return (C_wKbTrue); return (C_wKbFalse); } /* This function returns a pointer to the last error message string. */ short INO_fn_wGetErrorString(char **pp_szErrorString) { u_long i; i = ulKbErrorCode - C_FirstErrorKeyboard; *pp_szErrorString = KbErrorString[i]; return (0); } /* This function returns a last error code. */ u_long INO_fn_ulGetLastErrorCode(void) { return(ulKbErrorCode); } /********************************************************************* DEMO MODE SUPPORT FUNCTION *********************************************************************/ /* DEFINE THE KEYS TO STOP THE DEMO RECORDING MODE. OF COURSE, THE DEFINE HERE SHOULDN'T BE USED IN THE GAME. DEFAULT IS ESC. */ short INO_fn_wAddStopRecordingKey(short wKeyCode) { int i; if (KbLib_uwKbOk == 0) { ulKbErrorCode = C_ErrKeyboardNotInitialized; return (C_wKbError); } for ( i=0 ; i0x46) && (wKeyCode<0x54)) || (wKeyCode==0xb5)) && (GetKeyState(VK_NUMLOCK) & C_ucKeyToggled) ) VirtualKeyCode = KbLib_acDikToVirtual[wKeyCode]; else VirtualKeyCode = MapVirtualKeyEx(wKeyCode, 1, KbLib_LayoutHandle); /* La fameuse modif qui tue - Elie*/ if ((VirtualKeyCode==0)||(VirtualKeyCode==VK_CAPITAL) ||(VirtualKeyCode==VK_SCROLL)||(VirtualKeyCode==VK_NUMLOCK) ||(VirtualKeyCode==VK_SHIFT)||(VirtualKeyCode==VK_CONTROL) ||(VirtualKeyCode==VK_MENU) ||((VirtualKeyCode>=VK_F1)&&(VirtualKeyCode<=VK_F24)) ) return (C_wKbError); /* Fill the KbLib_acVirtualKeyCodeTab array with SHIFT, ALT and CTRL state */ KbLib_acVirtualKeyCodeTab[VK_SHIFT] = C_ucKeyPressed & ( KbLib_acTabKey[KbLib_uwCurrentTab][C_ucKey_LSHIFT] | KbLib_acTabKey[KbLib_uwCurrentTab][C_ucKey_RSHIFT] ); KbLib_acVirtualKeyCodeTab[VK_CONTROL] = C_ucKeyPressed & ( KbLib_acTabKey[KbLib_uwCurrentTab][C_ucKey_LCTRL] | KbLib_acTabKey[KbLib_uwCurrentTab][C_ucKey_RCTRL] ); KbLib_acVirtualKeyCodeTab[VK_MENU] = C_ucKeyPressed & ( KbLib_acTabKey[KbLib_uwCurrentTab][C_ucKey_LALT] | KbLib_acTabKey[KbLib_uwCurrentTab][C_ucKey_RALT] ); /* Add CAPS LOCK state, (useless for Verr Num, ignored by ToAsciiEx() */ KbLib_acVirtualKeyCodeTab[VK_CAPITAL] = GetKeyState(VK_CAPITAL) & C_ucKeyToggled; /* deuxieme modif qui tue - Elie*/ KbLib_acVirtualKeyCodeTab[VK_NUMLOCK] = GetKeyState(VK_NUMLOCK) & C_ucKeyToggled; iResult = ToAsciiEx(VirtualKeyCode, wKeyCode, KbLib_acVirtualKeyCodeTab, a_ucASCIICode,0 , KbLib_LayoutHandle); switch (iResult) { case 0: return (C_wKbError); break; case 1: iResult = a_ucASCIICode[0] & 0xff; if (!isprint(iResult) /*&& iswprint(iResult)*/) return (C_wKbError); break; case 2: return (C_wKbError); break; } return (a_ucASCIICode[0]); } short valid() { return(KbLib_uwHValidEntries); } short head() { return (KbLib_uwHHead); } short numKey() { short index; index = KbLib_uwHHead-1; if ( index<0 ) index +=KbLib_uwHSize; return (KbLib_H[index].m_uwKeyPressedNumber ); } char * CS(void) { return (CurrentString); }