home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / win32 / DirectInput.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  27.2 KB  |  1,058 lines

  1. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
  2. // Copyright (C) 1999-2003 Forgotten
  3. // Copyright (C) 2004 Forgotten and the VBA development team
  4.  
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2, or(at your option)
  8. // any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software Foundation,
  17. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  
  19. #include "stdafx.h"
  20. #include "Reg.h"
  21. #include "WinResUtil.h"
  22.  
  23. #define DIRECTINPUT_VERSION 0x0500
  24. #include <dinput.h>
  25.  
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31.  
  32. extern void directXMessage(const char *);
  33. extern void winlog(const char *msg,...);
  34.  
  35. #define POV_UP    1
  36. #define POV_DOWN  2
  37. #define POV_RIGHT 4
  38. #define POV_LEFT  8
  39.  
  40. class DirectInput : public Input {
  41. private:
  42.   HINSTANCE dinputDLL;
  43.  
  44. public:
  45.   virtual void checkDevices();
  46.   DirectInput();
  47.   virtual ~DirectInput();
  48.  
  49.   virtual bool initialize();
  50.   virtual bool readDevices();
  51.   virtual u32 readDevice(int which);
  52.   virtual CString getKeyName(int key);
  53.   virtual void checkKeys();
  54.   virtual void checkMotionKeys();
  55.   virtual void activate();
  56.   virtual void loadSettings();
  57.   virtual void saveSettings();
  58. };
  59.  
  60. struct deviceInfo {
  61.   LPDIRECTINPUTDEVICE device;
  62.   BOOL isPolled;
  63.   int nButtons;
  64.   int nAxes;
  65.   int nPovs;
  66.   BOOL first;
  67.   struct {
  68.     DWORD offset;
  69.     LONG center;
  70.     LONG negative;
  71.     LONG positive;
  72.   } axis[8];
  73.   int needed;
  74.   union {
  75.     UCHAR data[256];
  76.     DIJOYSTATE state;
  77.   };
  78. };
  79.  
  80. static deviceInfo *currentDevice = NULL;
  81. static int numDevices = 1;
  82. static deviceInfo *pDevices = NULL;
  83. static LPDIRECTINPUT pDirectInput = NULL;
  84. static int joyDebug = 0;
  85. static int axisNumber = 0;
  86.  
  87. USHORT joypad[4][13] = {
  88.   {
  89.     DIK_LEFT,  DIK_RIGHT,
  90.     DIK_UP,    DIK_DOWN,
  91.     DIK_Z,     DIK_X,
  92.     DIK_RETURN,DIK_BACK,
  93.     DIK_A,     DIK_S,
  94.     DIK_SPACE, DIK_F12,
  95.     DIK_C
  96.   },
  97.   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  98.   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  99.   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }  
  100. };
  101.  
  102. USHORT motion[4] = {
  103.   DIK_NUMPAD4, DIK_NUMPAD6, DIK_NUMPAD8, DIK_NUMPAD2
  104. };
  105.  
  106. static int winReadKey(char *name, int num)
  107. {
  108.   char buffer[80];
  109.  
  110.   sprintf(buffer, "Joy%d_%s", num, name);
  111.  
  112.   return regQueryDwordValue(buffer, (DWORD)-1);
  113. }
  114.  
  115. void winReadKeys()
  116. {
  117.   int key = -1;
  118.  
  119.   for(int i = 0; i < 4; i++) {
  120.     key = winReadKey("Left", i);
  121.     if(key != -1)
  122.       joypad[i][KEY_LEFT] = key;
  123.     key = winReadKey("Right", i);
  124.     if(key != -1)
  125.       joypad[i][KEY_RIGHT] = key;
  126.     key = winReadKey("Up", i);
  127.     if(key != -1)
  128.       joypad[i][KEY_UP] = key;
  129.     key = winReadKey("Down", i);
  130.     if(key != -1)
  131.       joypad[i][KEY_DOWN] = key;
  132.     key = winReadKey("A", i);
  133.     if(key != -1)
  134.       joypad[i][KEY_BUTTON_A] = key;
  135.     key = winReadKey("B", i);
  136.     if(key != -1)
  137.       joypad[i][KEY_BUTTON_B] = key;
  138.     key = winReadKey("L", i);
  139.     if(key != -1)
  140.       joypad[i][KEY_BUTTON_L] = key;
  141.     key = winReadKey("R", i);
  142.     if(key != -1)
  143.       joypad[i][KEY_BUTTON_R] = key;  
  144.     key = winReadKey("Start", i);
  145.     if(key != -1)
  146.       joypad[i][KEY_BUTTON_START] = key;
  147.     key = winReadKey("Select", i);
  148.     if(key != -1)
  149.       joypad[i][KEY_BUTTON_SELECT] = key;
  150.     key = winReadKey("Speed", i);
  151.     if(key != -1)
  152.       joypad[i][KEY_BUTTON_SPEED] = key;
  153.     key = winReadKey("Capture", i);
  154.     if(key != -1)
  155.       joypad[i][KEY_BUTTON_CAPTURE] = key;
  156.     key = winReadKey("GS", i);
  157.     if(key != -1)
  158.       joypad[i][KEY_BUTTON_GS] = key;
  159.   }
  160.   key = regQueryDwordValue("Motion_Left", (DWORD)-1);
  161.   if(key != -1)
  162.     motion[KEY_LEFT] = key;
  163.   key = regQueryDwordValue("Motion_Right", (DWORD)-1);
  164.   if(key != -1)
  165.     motion[KEY_RIGHT] = key;
  166.   key = regQueryDwordValue("Motion_Up", (DWORD)-1);
  167.   if(key != -1)
  168.     motion[KEY_UP] = key;
  169.   key = regQueryDwordValue("Motion_Down", (DWORD)-1);
  170.   if(key != -1)
  171.     motion[KEY_DOWN] = key;
  172. }
  173.  
  174. static void winSaveKey(char *name, int num, USHORT value)
  175. {
  176.   char buffer[80];
  177.  
  178.   sprintf(buffer, "Joy%d_%s", num, name);
  179.  
  180.   regSetDwordValue(buffer, value);
  181. }
  182.  
  183. void winSaveKeys()
  184. {
  185.   for(int i = 0; i < 4; i++) {
  186.     winSaveKey("Left", i, joypad[i][KEY_LEFT]);
  187.     winSaveKey("Right", i, joypad[i][KEY_RIGHT]);
  188.     winSaveKey("Up", i, joypad[i][KEY_UP]);
  189.     winSaveKey("Speed", i, joypad[i][KEY_BUTTON_SPEED]);
  190.     winSaveKey("Capture", i, joypad[i][KEY_BUTTON_CAPTURE]);
  191.     winSaveKey("GS", i, joypad[i][KEY_BUTTON_GS]);  
  192.     winSaveKey("Down", i, joypad[i][KEY_DOWN]);
  193.     winSaveKey("A", i, joypad[i][KEY_BUTTON_A]);
  194.     winSaveKey("B", i, joypad[i][KEY_BUTTON_B]);
  195.     winSaveKey("L", i, joypad[i][KEY_BUTTON_L]);
  196.     winSaveKey("R", i, joypad[i][KEY_BUTTON_R]);  
  197.     winSaveKey("Start", i, joypad[i][KEY_BUTTON_START]);
  198.     winSaveKey("Select", i, joypad[i][KEY_BUTTON_SELECT]);
  199.   }
  200.   regSetDwordValue("joyVersion", 1);  
  201.  
  202.   regSetDwordValue("Motion_Left",
  203.                    motion[KEY_LEFT]);
  204.   regSetDwordValue("Motion_Right",
  205.                    motion[KEY_RIGHT]);
  206.   regSetDwordValue("Motion_Up",
  207.                    motion[KEY_UP]);
  208.   regSetDwordValue("Motion_Down",
  209.                    motion[KEY_DOWN]);
  210. }
  211.  
  212. static BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
  213.                                        VOID* pContext )
  214. {
  215.   DIPROPRANGE diprg; 
  216.   diprg.diph.dwSize       = sizeof(DIPROPRANGE); 
  217.   diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
  218.   diprg.diph.dwHow        = DIPH_BYOFFSET; 
  219.   diprg.diph.dwObj        = pdidoi->dwOfs; // Specify the enumerated axis
  220.  
  221.   diprg.lMin = -32768;
  222.   diprg.lMax = 32767;
  223.   // try to set the range
  224.   if(FAILED(currentDevice->device->SetProperty(DIPROP_RANGE, &diprg.diph))) {
  225.     // Get the range for the axis
  226.     if( FAILED(currentDevice->device->
  227.                GetProperty( DIPROP_RANGE, &diprg.diph ) ) ) {
  228.       return DIENUM_STOP;
  229.     }
  230.   }
  231.  
  232.   DIPROPDWORD didz;
  233.  
  234.   didz.diph.dwSize = sizeof(didz);
  235.   didz.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  236.   didz.diph.dwHow = DIPH_BYOFFSET;
  237.   didz.diph.dwObj = pdidoi->dwOfs;
  238.  
  239.   didz.dwData = 5000;
  240.  
  241.   currentDevice->device->SetProperty(DIPROP_DEADZONE, &didz.diph);
  242.   
  243.   LONG center = (diprg.lMin + diprg.lMax)/2;
  244.   LONG threshold = (diprg.lMax - center)/2;
  245.  
  246.   // only 8 axis supported
  247.   if(axisNumber < 8) {
  248.     currentDevice->axis[axisNumber].center = center;
  249.     currentDevice->axis[axisNumber].negative = center - threshold;
  250.     currentDevice->axis[axisNumber].positive = center + threshold;
  251.     currentDevice->axis[axisNumber].offset = pdidoi->dwOfs;
  252.   }
  253.   axisNumber++;
  254.   return DIENUM_CONTINUE;
  255. }
  256.  
  257. static BOOL CALLBACK EnumPovsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
  258.                                        VOID* pContext )
  259. {
  260.   return DIENUM_CONTINUE;  
  261. }
  262.  
  263. static BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE pInst,
  264.                                            LPVOID lpvContext)
  265. {
  266.   ZeroMemory(&pDevices[numDevices],sizeof(deviceInfo));
  267.   
  268.   HRESULT hRet = pDirectInput->CreateDevice(pInst->guidInstance,
  269.                                             &pDevices[numDevices].device,
  270.                                             NULL);
  271.   
  272.   if(hRet != DI_OK)
  273.     return DIENUM_STOP;
  274.   
  275.   DIDEVCAPS caps;
  276.   caps.dwSize=sizeof(DIDEVCAPS);
  277.   
  278.   hRet = pDevices[numDevices].device->GetCapabilities(&caps);
  279.   
  280.   if(hRet == DI_OK) {
  281.     if(caps.dwFlags & DIDC_POLLEDDATAFORMAT ||
  282.        caps.dwFlags & DIDC_POLLEDDEVICE)
  283.       pDevices[numDevices].isPolled = TRUE;
  284.     
  285.     pDevices[numDevices].nButtons = caps.dwButtons;
  286.     pDevices[numDevices].nAxes = caps.dwAxes;
  287.     pDevices[numDevices].nPovs = caps.dwPOVs;
  288.  
  289.     for(int i = 0; i < 6; i++) {
  290.       pDevices[numDevices].axis[i].center = 0x8000;
  291.       pDevices[numDevices].axis[i].negative = 0x4000;
  292.       pDevices[numDevices].axis[i].positive = 0xc000;
  293.     }
  294.   } else if(joyDebug)
  295.     winlog("Failed to get device capabilities %08x\n", hRet);
  296.  
  297.   if(joyDebug) {
  298.     // don't translate. debug only
  299.     winlog("******************************\n");
  300.     winlog("Joystick %2d name    : %s\n", numDevices, pInst->tszProductName);
  301.   }
  302.   
  303.   numDevices++;
  304.  
  305.   
  306.   return DIENUM_CONTINUE;
  307. }
  308.  
  309. BOOL CALLBACK DIEnumDevicesCallback2(LPCDIDEVICEINSTANCE pInst,
  310.                                      LPVOID lpvContext)
  311. {
  312.   numDevices++;
  313.   
  314.   return DIENUM_CONTINUE;
  315. }
  316.  
  317. static int getPovState(DWORD value)
  318. {
  319.   int state = 0;
  320.   if(LOWORD(value) != 0xFFFF) {
  321.     if(value < 9000 || value > 27000)
  322.       state |= POV_UP;
  323.     if(value > 0 && value < 18000)
  324.       state |= POV_RIGHT;
  325.     if(value > 9000 && value < 27000)
  326.       state |= POV_DOWN;
  327.     if(value > 18000)
  328.       state |= POV_LEFT;
  329.   }
  330.   return state;
  331. }
  332.  
  333. static void checkKeys()
  334. {
  335.   int dev = 0;
  336.   int i;
  337.  
  338.   for(i = 0; i < numDevices; i++)
  339.     pDevices[i].needed = 0;
  340.  
  341.   for(i = 0; i < 4; i++) {
  342.     dev = joypad[i][KEY_LEFT] >> 8;
  343.     if(dev < numDevices && dev >= 0)
  344.       pDevices[dev].needed = 1;
  345.     else
  346.       joypad[i][KEY_LEFT] = DIK_LEFT;
  347.     
  348.     dev = joypad[i][KEY_RIGHT] >> 8;
  349.     if(dev < numDevices && dev >= 0)
  350.       pDevices[dev].needed = 1;
  351.     else
  352.       joypad[i][KEY_RIGHT] = DIK_RIGHT;
  353.     
  354.     dev = joypad[i][KEY_UP] >> 8;
  355.     if(dev < numDevices && dev >= 0)
  356.       pDevices[dev].needed = 1;
  357.     else
  358.       joypad[i][KEY_UP] = DIK_UP;
  359.     
  360.     dev = joypad[i][KEY_DOWN] >> 8;
  361.     if(dev < numDevices && dev >= 0)
  362.       pDevices[dev].needed = 1;
  363.     else
  364.       joypad[i][KEY_DOWN] = DIK_DOWN;
  365.     
  366.     dev = joypad[i][KEY_BUTTON_A] >> 8;
  367.     if(dev < numDevices && dev >= 0)
  368.       pDevices[dev].needed = 1;
  369.     else
  370.       joypad[i][KEY_BUTTON_A] = DIK_Z;
  371.     
  372.     dev = joypad[i][KEY_BUTTON_B] >> 8;
  373.     if(dev < numDevices && dev >= 0)
  374.       pDevices[dev].needed = 1;
  375.     else
  376.       joypad[i][KEY_BUTTON_B] = DIK_X;
  377.     
  378.     dev = joypad[i][KEY_BUTTON_L] >> 8;
  379.     if(dev < numDevices && dev >= 0)
  380.       pDevices[dev].needed = 1;
  381.     else
  382.       joypad[i][KEY_BUTTON_L] = DIK_A;
  383.     
  384.     dev = joypad[i][KEY_BUTTON_R] >> 8;
  385.     if(dev < numDevices && dev >= 0)
  386.       pDevices[dev].needed = 1;
  387.     else
  388.       joypad[i][KEY_BUTTON_R] = DIK_S;
  389.     
  390.     dev = joypad[i][KEY_BUTTON_START] >> 8;
  391.     if(dev < numDevices && dev >= 0)
  392.       pDevices[dev].needed = 1;
  393.     else
  394.       joypad[i][KEY_BUTTON_START] = DIK_RETURN;
  395.     
  396.     dev = joypad[i][KEY_BUTTON_SELECT] >> 8;
  397.     if(dev < numDevices && dev >= 0)
  398.       pDevices[dev].needed = 1;
  399.     else
  400.       joypad[i][KEY_BUTTON_SELECT] = DIK_BACK;
  401.     
  402.     dev = joypad[i][KEY_BUTTON_SPEED] >> 8;
  403.     if(dev < numDevices && dev >= 0)
  404.       pDevices[dev].needed = 1;
  405.     else
  406.       joypad[i][KEY_BUTTON_SPEED] = DIK_SPACE;
  407.     
  408.     dev = joypad[i][KEY_BUTTON_CAPTURE] >> 8;
  409.     if(dev < numDevices && dev >= 0)
  410.       pDevices[dev].needed = 1;
  411.     else
  412.       joypad[i][KEY_BUTTON_CAPTURE] = DIK_F12;
  413.     
  414.     dev = joypad[i][KEY_BUTTON_GS] >> 8;
  415.     if(dev < numDevices && dev >= 0)
  416.       pDevices[dev].needed = 1;
  417.     else
  418.       joypad[i][KEY_BUTTON_GS] = DIK_C;
  419.   }
  420.     
  421.   dev = motion[KEY_UP] >> 8;
  422.   if(dev < numDevices && dev >= 0)
  423.     pDevices[dev].needed = 1;
  424.   else
  425.     motion[KEY_UP] = DIK_NUMPAD8;  
  426.  
  427.   dev = motion[KEY_DOWN] >> 8;
  428.   if(dev < numDevices && dev >= 0)
  429.     pDevices[dev].needed = 1;
  430.   else
  431.     motion[KEY_DOWN] = DIK_NUMPAD2;  
  432.  
  433.   dev = motion[KEY_LEFT] >> 8;
  434.   if(dev < numDevices && dev >= 0)
  435.     pDevices[dev].needed = 1;
  436.   else
  437.     motion[KEY_LEFT] = DIK_NUMPAD4;  
  438.  
  439.   dev = motion[KEY_RIGHT] >> 8;
  440.   if(dev < numDevices && dev >= 0)
  441.     pDevices[dev].needed = 1;
  442.   else
  443.     motion[KEY_RIGHT] = DIK_NUMPAD6;  
  444. }
  445.  
  446. #define KEYDOWN(buffer,key) (buffer[key] & 0x80)
  447.  
  448. static bool readKeyboard()
  449. {
  450.   if(pDevices[0].needed) {
  451.     HRESULT hret = pDevices[0].device->
  452.       GetDeviceState(256,
  453.                      (LPVOID)pDevices[0].data);
  454.     
  455.     if(hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) {
  456.       hret = pDevices[0].device->Acquire();
  457.       if(hret != DI_OK)
  458.         return false;
  459.       hret = pDevices[0].device->GetDeviceState(256,(LPVOID)pDevices[0].data);
  460.     }
  461.  
  462.     return hret == DI_OK;
  463.   }
  464.   return true;
  465. }
  466.  
  467. static bool readJoystick(int joy)
  468. {
  469.   if(pDevices[joy].needed) {
  470.     if(pDevices[joy].isPolled)
  471.       ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll();
  472.     
  473.     HRESULT hret = pDevices[joy].device->
  474.       GetDeviceState(sizeof(DIJOYSTATE),
  475.                      (LPVOID)&pDevices[joy].state);
  476.     
  477.     if(hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) {
  478.       hret = pDevices[joy].device->Acquire();
  479.       
  480.       if(hret == DI_OK) {
  481.         
  482.         if(pDevices[joy].isPolled)
  483.           ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll();
  484.         
  485.         hret = pDevices[joy].device->
  486.           GetDeviceState(sizeof(DIJOYSTATE),
  487.                          (LPVOID)&pDevices[joy].state);
  488.       }
  489.     }
  490.  
  491.     return hret == DI_OK;
  492.   }
  493.  
  494.   return true;
  495. }
  496.  
  497. static void checkKeyboard()
  498. {
  499.   HRESULT hret = pDevices[0].device->Acquire();  
  500.   hret = pDevices[0].device->
  501.     GetDeviceState(256,
  502.                    (LPVOID)pDevices[0].data);
  503.   
  504.   if(hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) {
  505.     return;
  506.   }
  507.  
  508.   if(hret == DI_OK) {
  509.     for(int i = 0; i < 256; i++) {
  510.       if(KEYDOWN(pDevices[0].data, i)) {
  511.         SendMessage(GetFocus(), JOYCONFIG_MESSAGE,0,i);
  512.         break;
  513.       }
  514.     }
  515.   }
  516. }
  517.  
  518. static void checkJoypads()
  519. {
  520.   DIDEVICEOBJECTINSTANCE di;
  521.  
  522.   ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE));
  523.  
  524.   di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
  525.  
  526.   int i =0;
  527.  
  528.   DIJOYSTATE joystick;
  529.   
  530.   for(i = 1; i < numDevices; i++) {
  531.     HRESULT hret = pDevices[i].device->Acquire();
  532.     
  533.  
  534.     if(pDevices[i].isPolled)
  535.       ((LPDIRECTINPUTDEVICE2)pDevices[i].device)->Poll();
  536.     
  537.     hret = pDevices[i].device->GetDeviceState(sizeof(joystick), &joystick);
  538.  
  539.     int j;
  540.  
  541.     if(pDevices[i].first) {
  542.       memcpy(&pDevices[i].state, &joystick, sizeof(joystick));
  543.       pDevices[i].first = FALSE;
  544.       continue;
  545.     }
  546.     
  547.     for(j = 0; j < pDevices[i].nButtons; j++) {
  548.       if(((pDevices[i].state.rgbButtons[j] ^ joystick.rgbButtons[j]) 
  549.           & joystick.rgbButtons[j]) & 0x80) {
  550.         HWND focus = GetFocus();
  551.  
  552.         SendMessage(focus, JOYCONFIG_MESSAGE, i,j+128);
  553.       }      
  554.     }
  555.  
  556.     for(j = 0; j < pDevices[i].nAxes && j < 8; j++) {
  557.       LONG value = pDevices[i].axis[j].center;
  558.       LONG old = 0;
  559.       switch(pDevices[i].axis[j].offset) {
  560.       case DIJOFS_X:
  561.         value = joystick.lX;
  562.         old = pDevices[i].state.lX;
  563.         break;
  564.       case DIJOFS_Y:
  565.         value = joystick.lY;
  566.         old = pDevices[i].state.lY;     
  567.         break;
  568.       case DIJOFS_Z:
  569.         value = joystick.lZ;
  570.         old = pDevices[i].state.lZ;     
  571.         break;
  572.       case DIJOFS_RX:
  573.         value = joystick.lRx;
  574.         old = pDevices[i].state.lRx;    
  575.         break;
  576.       case DIJOFS_RY:
  577.         value = joystick.lRy;
  578.         old = pDevices[i].state.lRy;    
  579.         break;
  580.       case DIJOFS_RZ:
  581.         value = joystick.lRz;
  582.         old = pDevices[i].state.lRz;    
  583.         break;
  584.       case DIJOFS_SLIDER(0):
  585.         value = joystick.rglSlider[0];
  586.         old = pDevices[i].state.rglSlider[0];   
  587.         break;
  588.       case DIJOFS_SLIDER(1):
  589.         value = joystick.rglSlider[1];
  590.         old = pDevices[i].state.rglSlider[1];   
  591.         break;
  592.       }
  593.       if(value != old) {
  594.         if(value < pDevices[i].axis[j].negative)
  595.           SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1));
  596.         else if (value > pDevices[i].axis[j].positive)
  597.           SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)+1);
  598.       }
  599.     }
  600.  
  601.     for(j = 0;j < 4 && j < pDevices[i].nPovs; j++) {
  602.       if(LOWORD(pDevices[i].state.rgdwPOV[j]) != LOWORD(joystick.rgdwPOV[j])) {
  603.         int state = getPovState(joystick.rgdwPOV[j]);
  604.         
  605.         if(state & POV_UP)
  606.           SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x20);
  607.         else if(state & POV_DOWN)
  608.           SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x21);
  609.         else if(state & POV_RIGHT)
  610.           SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x22);
  611.         else if(state & POV_LEFT)
  612.           SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x23);
  613.       }
  614.     }
  615.  
  616.     memcpy(&pDevices[i].state, &joystick, sizeof(joystick));
  617.   }
  618. }
  619.  
  620. BOOL checkKey(int key)
  621. {
  622.   int dev = (key >> 8);
  623.  
  624.   int k = (key & 255);
  625.   
  626.   if(dev == 0) {
  627.     return KEYDOWN(pDevices[0].data,k);
  628.   } else {
  629.     if(k < 16) {
  630.       int axis = k >> 1;
  631.       LONG value = pDevices[dev].axis[axis].center;
  632.       switch(pDevices[dev].axis[axis].offset) {
  633.       case DIJOFS_X:
  634.         value = pDevices[dev].state.lX;
  635.         break;
  636.       case DIJOFS_Y:
  637.         value = pDevices[dev].state.lY;
  638.         break;
  639.       case DIJOFS_Z:
  640.         value = pDevices[dev].state.lZ;
  641.         break;
  642.       case DIJOFS_RX:
  643.         value = pDevices[dev].state.lRx;
  644.         break;
  645.       case DIJOFS_RY:
  646.         value = pDevices[dev].state.lRy;
  647.         break;
  648.       case DIJOFS_RZ:
  649.         value = pDevices[dev].state.lRz;
  650.         break;
  651.       case DIJOFS_SLIDER(0):
  652.         value = pDevices[dev].state.rglSlider[0];
  653.         break;
  654.       case DIJOFS_SLIDER(1):
  655.         value = pDevices[dev].state.rglSlider[1];
  656.         break;
  657.       }
  658.  
  659.       if(k & 1)
  660.         return value > pDevices[dev].axis[axis].positive;
  661.       return value < pDevices[dev].axis[axis].negative;
  662.     } else if(k < 48) {
  663.       int hat = (k >> 2) & 3;
  664.       int state = getPovState(pDevices[dev].state.rgdwPOV[hat]);
  665.       BOOL res = FALSE;
  666.       switch(k & 3) {
  667.       case 0:
  668.         res = state & POV_UP;
  669.         break;
  670.       case 1:
  671.         res = state & POV_DOWN;
  672.         break;
  673.       case 2:
  674.         res = state & POV_RIGHT;
  675.         break;
  676.       case 3:
  677.         res = state & POV_LEFT;
  678.         break;
  679.       }
  680.       return res;
  681.     } else if(k  >= 128) {
  682.       return pDevices[dev].state.rgbButtons[k-128] & 0x80;
  683.     }
  684.   }
  685.  
  686.   return FALSE;
  687. }
  688.  
  689. DirectInput::DirectInput()
  690. {
  691.   dinputDLL = NULL;
  692. }
  693.  
  694. DirectInput::~DirectInput()
  695. {
  696.   saveSettings();
  697.   if(pDirectInput != NULL) {
  698.     if(pDevices) {
  699.       for(int i = 0; i < numDevices ; i++) {
  700.         if(pDevices[i].device) {
  701.           pDevices[i].device->Unacquire();
  702.           pDevices[i].device->Release();
  703.           pDevices[i].device = NULL;
  704.         }
  705.       }
  706.       free(pDevices);
  707.       pDevices = NULL;
  708.     }
  709.     
  710.     pDirectInput->Release();
  711.     pDirectInput = NULL;
  712.   }
  713.  
  714.   if(dinputDLL) {
  715.     AfxFreeLibrary(dinputDLL);
  716.     dinputDLL = NULL;
  717.   }
  718. }
  719.  
  720. bool DirectInput::initialize()
  721. {
  722.   joyDebug = GetPrivateProfileInt("config",
  723.                                   "joyDebug",
  724.                                   0,
  725.                                   "VBA.ini");
  726.   dinputDLL = AfxLoadLibrary("DINPUT.DLL");
  727.   HRESULT (WINAPI *DInputCreate)(HINSTANCE,DWORD,LPDIRECTINPUT *,IUnknown *);  
  728.   if(dinputDLL != NULL) {    
  729.     DInputCreate = (HRESULT (WINAPI *)(HINSTANCE,DWORD,LPDIRECTINPUT *,IUnknown *))
  730.       GetProcAddress(dinputDLL, "DirectInputCreateA");
  731.     
  732.     if(DInputCreate == NULL) {
  733.       directXMessage("DirectInputCreateA");
  734.       return false;
  735.     }
  736.   } else {
  737.     directXMessage("DINPUT.DLL");
  738.     return false;
  739.   }
  740.   
  741.   HRESULT hret = DInputCreate(AfxGetInstanceHandle(),
  742.                               DIRECTINPUT_VERSION,
  743.                               &pDirectInput,
  744.                               NULL);
  745.   if(hret != DI_OK) {
  746.     //    errorMessage(myLoadString(IDS_ERROR_DISP_CREATE), hret);
  747.     return false;
  748.   }
  749.  
  750.   hret = pDirectInput->EnumDevices(DIDEVTYPE_JOYSTICK,
  751.                                    DIEnumDevicesCallback2,
  752.                                    NULL,
  753.                                    DIEDFL_ATTACHEDONLY);
  754.  
  755.   
  756.   
  757.   pDevices = (deviceInfo *)calloc(numDevices, sizeof(deviceInfo));
  758.  
  759.   hret = pDirectInput->CreateDevice(GUID_SysKeyboard,&pDevices[0].device,NULL);
  760.   pDevices[0].isPolled = false;
  761.   pDevices[0].needed  = true;
  762.  
  763.   if(hret != DI_OK) {
  764.     //    errorMessage(myLoadString(IDS_ERROR_DISP_CREATEDEVICE), hret);
  765.     return false;
  766.   }
  767.  
  768.   
  769.   numDevices = 1;
  770.  
  771.   hret = pDirectInput->EnumDevices(DIDEVTYPE_JOYSTICK,
  772.                                    DIEnumDevicesCallback,
  773.                                    NULL,
  774.                                    DIEDFL_ATTACHEDONLY);  
  775.  
  776.   //  hret = pDevices[0].device->SetCooperativeLevel(hWindow,
  777.   //                                             DISCL_FOREGROUND|
  778.   //                                             DISCL_NONEXCLUSIVE);
  779.   
  780.   if(hret != DI_OK) {
  781.     //    errorMessage(myLoadString(IDS_ERROR_DISP_LEVEL), hret);
  782.     return false;
  783.   }
  784.   
  785.   hret = pDevices[0].device->SetDataFormat(&c_dfDIKeyboard);
  786.  
  787.   if(hret != DI_OK) {
  788.     //    errorMessage(myLoadString(IDS_ERROR_DISP_DATAFORMAT), hret);
  789.     return false;
  790.   }
  791.  
  792.   for(int i = 1; i < numDevices; i++) {
  793.     pDevices[i].device->SetDataFormat(&c_dfDIJoystick);
  794.     pDevices[i].needed = false;
  795.     currentDevice = &pDevices[i];
  796.     axisNumber = 0;
  797.     currentDevice->device->EnumObjects(EnumAxesCallback, NULL, DIDFT_AXIS);
  798.     currentDevice->device->EnumObjects(EnumPovsCallback, NULL, DIDFT_POV);
  799.     if(joyDebug) {
  800.       // don't translate. debug only
  801.       winlog("Joystick %2d polled  : %d\n",    i, currentDevice->isPolled);
  802.       winlog("Joystick %2d buttons : %d\n",    i, currentDevice->nButtons);
  803.       winlog("Joystick %2d povs    : %d\n",    i, currentDevice->nPovs);
  804.       winlog("Joystick %2d axes    : %d\n",    i, currentDevice->nAxes);
  805.       for(int j = 0; j < currentDevice->nAxes; j++) {
  806.         winlog("Axis %2d offset      : %08lx\n", j, currentDevice->axis[j].
  807.                offset);
  808.         winlog("Axis %2d center      : %08lx\n", j, currentDevice->axis[j].
  809.                center);
  810.         winlog("Axis %2d negative    : %08lx\n",   j, currentDevice->axis[j].
  811.                negative);
  812.         winlog("Axis %2d positive    : %08lx\n",   j, currentDevice->axis[j].
  813.                positive);
  814.       }
  815.     }
  816.     
  817.     currentDevice = NULL;
  818.   }
  819.  
  820.   for(i = 0; i < numDevices; i++)
  821.     pDevices[i].device->Acquire();
  822.   
  823.   return true;
  824. }
  825.  
  826. bool DirectInput::readDevices()
  827. {
  828.   bool ok = true;
  829.   for(int i = 0; i < numDevices; i++) {
  830.     if(pDevices[i].needed) {
  831.       if(i) {
  832.         ok = readJoystick(i);
  833.       } else
  834.         ok = readKeyboard();
  835.     }
  836.   }
  837.   return ok;
  838. }
  839.  
  840. u32 DirectInput::readDevice(int which)
  841. {
  842.   u32 res = 0;
  843.   int i = theApp.joypadDefault;
  844.   if(which >= 0 && which <= 3)
  845.     i = which;
  846.   
  847.   if(checkKey(joypad[i][KEY_BUTTON_A]))
  848.     res |= 1;
  849.   if(checkKey(joypad[i][KEY_BUTTON_B]))
  850.     res |= 2;
  851.   if(checkKey(joypad[i][KEY_BUTTON_SELECT]))
  852.     res |= 4;
  853.   if(checkKey(joypad[i][KEY_BUTTON_START]))
  854.     res |= 8;
  855.   if(checkKey(joypad[i][KEY_RIGHT]))
  856.     res |= 16;
  857.   if(checkKey(joypad[i][KEY_LEFT]))
  858.     res |= 32;
  859.   if(checkKey(joypad[i][KEY_UP]))
  860.     res |= 64;
  861.   if(checkKey(joypad[i][KEY_DOWN]))
  862.     res |= 128;
  863.   if(checkKey(joypad[i][KEY_BUTTON_R]))
  864.     res |= 256;
  865.   if(checkKey(joypad[i][KEY_BUTTON_L]))
  866.     res |= 512;
  867.   
  868.   if(checkKey(joypad[i][KEY_BUTTON_GS]))
  869.     res |= 4096;
  870.  
  871.   res |= theApp.skinButtons;
  872.   if(theApp.autoFire) {
  873.     res &= (~theApp.autoFire);
  874.     if(theApp.autoFireToggle)
  875.       res |= theApp.autoFire;
  876.     theApp.autoFireToggle = !theApp.autoFireToggle;
  877.   }
  878.  
  879.   // disallow L+R or U+D of being pressed at the same time
  880.   if((res & 48) == 48)
  881.     res &= ~16;
  882.   if((res & 192) == 192)
  883.     res &= ~128;
  884.  
  885.   if(theApp.movieRecording) {
  886.     if(i == theApp.joypadDefault) {
  887.       if(res != theApp.movieLastJoypad) {
  888.         fwrite(&theApp.movieFrame, 1, sizeof(theApp.movieFrame), theApp.movieFile);
  889.         fwrite(&res, 1, sizeof(res), theApp.movieFile);
  890.         theApp.movieLastJoypad = res;
  891.       }
  892.     }
  893.   }
  894.   if(theApp.moviePlaying) {
  895.     if(theApp.movieFrame == theApp.moviePlayFrame) {
  896.       theApp.movieLastJoypad = theApp.movieNextJoypad;
  897.       theApp.movieReadNext();
  898.     }
  899.     res = theApp.movieLastJoypad;
  900.   }
  901.   // we don't record speed up or screen capture buttons
  902.   if(checkKey(joypad[i][KEY_BUTTON_SPEED]) || theApp.speedupToggle)
  903.     res |= 1024;
  904.   if(checkKey(joypad[i][KEY_BUTTON_CAPTURE]))
  905.     res |= 2048;
  906.  
  907.   return res;
  908. }
  909.  
  910. CString DirectInput::getKeyName(int key)
  911. {
  912.   int d = (key >> 8);
  913.   int k = key & 255;
  914.  
  915.   DIDEVICEOBJECTINSTANCE di;
  916.  
  917.   ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE));
  918.  
  919.   di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
  920.   
  921.   CString winBuffer = winResLoadString(IDS_ERROR);
  922.   
  923.   if(d == 0) {
  924.     pDevices[0].device->GetObjectInfo(&di,key,DIPH_BYOFFSET);
  925.     winBuffer = di.tszName;
  926.   } else {
  927.     if(k < 16) {
  928.       if(k < 4) {
  929.         switch(k) {
  930.         case 0:
  931.           winBuffer.Format(winResLoadString(IDS_JOY_LEFT), d);
  932.           break;
  933.         case 1:
  934.           winBuffer.Format(winResLoadString(IDS_JOY_RIGHT), d);
  935.           break;
  936.         case 2:
  937.           winBuffer.Format(winResLoadString(IDS_JOY_UP), d);
  938.           break;
  939.         case 3:
  940.           winBuffer.Format(winResLoadString(IDS_JOY_DOWN), d);
  941.           break;
  942.         }
  943.       } else {
  944.         pDevices[d].device->GetObjectInfo(&di,
  945.                                           pDevices[d].axis[k>>1].offset,
  946.                                           DIPH_BYOFFSET);
  947.         if(k & 1)
  948.           winBuffer.Format("Joy %d %s +", d, di.tszName);
  949.         else
  950.           winBuffer.Format("Joy %d %s -", d, di.tszName);
  951.       }
  952.     } else if(k < 48) {
  953.       int hat = (k >> 2) & 3;
  954.       pDevices[d].device->GetObjectInfo(&di,
  955.                                         DIJOFS_POV(hat),
  956.                                         DIPH_BYOFFSET);
  957.       char *dir = "up";
  958.       int dd = k & 3;
  959.       if(dd == 1)
  960.         dir = "down";
  961.       else if(dd == 2)
  962.         dir = "right";
  963.       else if(dd == 3)
  964.         dir = "left";
  965.       winBuffer.Format("Joy %d %s %s", d, di.tszName, dir);
  966.     } else {
  967.       pDevices[d].device->GetObjectInfo(&di,
  968.                                         DIJOFS_BUTTON(k-128),
  969.                                         DIPH_BYOFFSET);
  970.       winBuffer.Format(winResLoadString(IDS_JOY_BUTTON),d,di.tszName);
  971.     }
  972.   }
  973.  
  974.   return winBuffer;
  975. }
  976.  
  977. void DirectInput::checkKeys()
  978. {
  979.   ::checkKeys();
  980. }
  981.  
  982. void DirectInput::checkMotionKeys()
  983. {
  984.   if(checkKey(motion[KEY_LEFT])) {
  985.     theApp.sensorX += 3;
  986.     if(theApp.sensorX > 2197)
  987.       theApp.sensorX = 2197;
  988.     if(theApp.sensorX < 2047)
  989.       theApp.sensorX = 2057;
  990.   } else if(checkKey(motion[KEY_RIGHT])) {
  991.     theApp.sensorX -= 3;
  992.     if(theApp.sensorX < 1897)
  993.       theApp.sensorX = 1897;
  994.     if(theApp.sensorX > 2047)
  995.       theApp.sensorX = 2037;
  996.   } else if(theApp.sensorX > 2047) {
  997.     theApp.sensorX -= 2;
  998.     if(theApp.sensorX < 2047)
  999.       theApp.sensorX = 2047;
  1000.   } else {
  1001.     theApp.sensorX += 2;
  1002.     if(theApp.sensorX > 2047)
  1003.       theApp.sensorX = 2047;
  1004.   }
  1005.   
  1006.   if(checkKey(motion[KEY_UP])) {
  1007.     theApp.sensorY += 3;
  1008.     if(theApp.sensorY > 2197)
  1009.       theApp.sensorY = 2197;
  1010.     if(theApp.sensorY < 2047)
  1011.       theApp.sensorY = 2057;
  1012.   } else if(checkKey(motion[KEY_DOWN])) {
  1013.     theApp.sensorY -= 3;
  1014.     if(theApp.sensorY < 1897)
  1015.       theApp.sensorY = 1897;
  1016.     if(theApp.sensorY > 2047)
  1017.       theApp.sensorY = 2037;
  1018.   } else if(theApp.sensorY > 2047) {
  1019.     theApp.sensorY -= 2;
  1020.     if(theApp.sensorY < 2047)
  1021.       theApp.sensorY = 2047;
  1022.   } else {
  1023.     theApp.sensorY += 2;
  1024.     if(theApp.sensorY > 2047)
  1025.       theApp.sensorY = 2047;
  1026.   }  
  1027. }
  1028.  
  1029. Input *newDirectInput()
  1030. {
  1031.   return new DirectInput;
  1032. }
  1033.  
  1034.  
  1035. void DirectInput::checkDevices()
  1036. {
  1037.   checkJoypads();
  1038.   checkKeyboard();
  1039. }
  1040.  
  1041. void DirectInput::activate()
  1042. {
  1043.   for(int i = 0; i < numDevices; i++) {
  1044.     if(pDevices != NULL && pDevices[i].device != NULL)
  1045.       pDevices[i].device->Acquire();
  1046.   }
  1047. }
  1048.  
  1049. void DirectInput::loadSettings()
  1050. {
  1051.   winReadKeys();
  1052. }
  1053.  
  1054. void DirectInput::saveSettings()
  1055. {
  1056.   winSaveKeys();
  1057. }
  1058.