2011年1月24日月曜日

XFPS

サッカーアジアカップの影響で夜更かしして眠れなくなったのでネタをカキコ。
なんかねぇ、1月は正月休みからずっと夜更かし続いて体調崩してます><























あ~こんなの買ってしまった。XFPS。どうしてもね、ハッキング魂というかチート魂を抑えきれなかったのよw

PS3につないで、PCのキーボード/マウス操作をコントローラの操作として代用させる機器です。ボタンの連射機能はオマケでしょう。これを使うと、コントローラで操作しつつ、PCのキーボード(マウス)を併用して操作できるようになります。

にしても、安っぽい外見ですな><もうちょっと何とかならんもんかねぇ。。。

さて、コントローラとPCキーボードとの併用ができる、ということから、チートクソ野郎の僕としては^^;こんな使い方したいなぁなんて思うわけです。
「PS3の画面(NTSC-SD)をキャプチャし、画像処理して、処理結果をコントローラ信号としてPS3に送り込む」
PS3にコントローラを別に繋げば、コントローラで操作しつつPCから必要なときにコントローラ信号を送り込むことができるので、BOT的なアプリだけでなくアシスト的なアプリもできてしまうわけです。(PS3のゲームソフト側でそういう二重化インターフェースを検知してなければ)

で、まずは、自作のPCアプリからPS3コントローラ信号として送り込むことができることを確認しないといけない。


XFPSの本来の使い方ですが、開発元サイトで配布されているアプリ(XFPS1.6 for PS3.exe(2011.01.18現在))を介して、キーボードやマウス操作をPS3コントローラのボタンやスティックに割り当てて使用します。
このアプリは実行ファイル1つのみで動作するもので、SDKは用意されていません。

入力インターフェースのプログラムとしてすぐに思いつく方法としては、
「自作プログラムで、配布アプリ上で割り当てたキーを叩くエミュレーションをさせる」
でしょう。
実際作ってみれば、おそらく、うまく動くだろうし、実用レベルになると思います。
ただ、あんまり美しくないですね。
やっぱり直接デバイスに操作情報を送り込むようにしたい。

ということで、配布アプリの中身をちょっと調べてみて、要点を抜き出したのが、
以下のコードです。

参考にすべきは、Windows DDKのサンプルである、hclientかな?
どうやら、XFPS1.6 for PS3.exeでは、デバイスの接続有無を調べて、デバイスが接続されていればパイプを作成し、
そのパイプに操作データを書き込む(下記コードのhPipeに対してWriteFile()する)ことで実現しているようです。


とまぁ、今回の解析はここまで。
だって、グランツーリスモ5でアシスト機能(BOT機能)ていってもねぇ、なかなか使い道が思いつかない。MT操作をAT操作にする(シフトアップだけAT、シフトダウンはMTとか)くらいしか思いつかないんだもん。


HANDLE hPipe=INVALID_HANDLE_VALUE;


GUID hidGuid;
HDEVINFO hardwareDeviceInfo;


HidD_GetHidGuid(&hidGuid);
hardwareDeviceInfo=SetupDiGetClassDevs(&hidGuid, NULL, NULL, 0x12);


SP_DEVICE_INTERFACE_DATA sp_devinterfacedata;
sp_devinterfacedata.cbSize=sizeof(SP_DEVICE_INTERFACE_DATA);


for(DWORD MemberIndex=0; ; MemberIndex++){
  int ret=SetupDiEnumDeviceInterfaces(hardwareDeviceInfo,
                                      NULL,
                                      &hidGuid,
                                      MemberIndex,
                                      &sp_devinterfacedata);
  if(ret==0) break;


  DWORD requiredLength, predictedLength;
  SetupDiGetDeviceInterfaceDetail(hardwareDeviceInfo,
                                  &sp_devinterfacedata,
                                  NULL,
                                  0,
                                  &requiredLength,
                                  NULL);


  predictedLength=requiredLength;
  PSP_DEVICE_INTERFACE_DETAIL_DATA psp_devinterfacedetaildata=malloc(sizeof(predictedLength));
  psp_devinterfacedetaildata.cbSize=sizeof(SP_DEVICE_INTERFACEDETAIL_DATA);


  SetupDiGetDeviceInterfaceDetail(hardwareDeviceInfo,
                                  &sp_devinterfacedata,
                                  psp_devinterfacedetaildata,
                                  predictedLength,
                                  &requiredLength,
                                  NULL);


  HANDLE hHIDDevice=CreateFile(psp_devinterfacedataildata->DevicePath,
                               0x40000000, // GENERIC_WRITE
                               2,
                               NULL, // no SECURITY_ATTRIBUTES
                               3, // OPEN_EXISTING
                               0x40000000, // FILE_FLAG_OVERLAPPED
                               NULL);
  
  HIDD_ATTRIBUTES HIDAttributes;
  PHIDP_PREPARSED_DATA HIDPreparsedData;
  HIDP_CAPS HIDCaps;
  
  if(hHIDDevice!=INVALID_HANDLE_VALUE){
    HIDAttributes.Size=sizeof(ULONG);
    HidD_GetAttributes(hHIDDevice, &HIDAttributes);
    ret=HidD_GetPreparsedData(hHIDDevice, &HIDPreparsedData);
    if(ret){
      HidP_GetCaps(HIDPreparsedData, &HIDCaps);
      //    ...
      HidD_FreePreparsedData(HIDPreparsedData);
    }
  }
  CloseHandle(hHIDDevice);
  
  char pipeFileName[MAX_PATH];
  
  if((HIDAttributes.VendorID==0x04b4)&&(HIDAttirbutes.ProductID==0x0811)){
    wsprintf(pipeFileName, "%s\\PIPE1", psp_devinterfacedataildata->DevicePath);
    
    hPipe=CreateFile(pipeFileName,
                     0xc0000000, // GENERIC_WRITE|GENERIC_READ
                     3, // FILE_SHARE_READ|FILE_SHARE_WRITE
                     NULL,
                     3, // OPEN_EXISTING
                     0,
                     NULL);
  }
  free(psp_devinterfacedetaildata);
  SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
}


unsigned char DataBuffer;
if(hPipe!=INVALID_HANDLE_VALUE){
  // ...
  DWORD writtenLength;
  WriteFile(hPipe, DataBuffer, 0x32, &writtenLengh, NULL);
  // ...
}

0 件のコメント:

コメントを投稿