GameController.hx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. package dx;
  2. @:noCompletion
  3. typedef GameControllerPtr = hl.Abstract<"dx_gctrl_device">;
  4. private class DInputButton {
  5. var num : Int;
  6. var mask : Int;
  7. var axis : Int;
  8. public function new( num : Int, mask : Int, axis : Int ){
  9. this.num = num;
  10. this.mask = mask;
  11. this.axis = axis;
  12. }
  13. }
  14. private class DInputMapping {
  15. var guid : Int;
  16. var name : hl.Bytes;
  17. var button : hl.NativeArray<DInputButton>;
  18. function new( s : String ){
  19. var a = s.split(",");
  20. var suid = a.shift();
  21. var vendor = Std.parseInt( "0x" + suid.substr(8,4) );
  22. var product = Std.parseInt( "0x" + suid.substr(16,4) );
  23. guid = (product&0xFF)<<24 | (product&0xFF00)<<8 | (vendor&0xFF)<<8 | (vendor&0xFF00)>>8;
  24. name = @:privateAccess a.shift().toUtf8();
  25. button = new hl.NativeArray(20);
  26. for( e in a ){
  27. var p = e.split(":");
  28. if( p.length != 2 ) continue;
  29. var btn : DInputButton = switch( p[1].charCodeAt(0) ){
  30. case 'b'.code: new DInputButton(Std.parseInt(p[1].substr(1)), 0, -1);
  31. case 'h'.code: {
  32. var ba = p[1].substr(1).split(".");
  33. if( ba == null )
  34. null;
  35. else
  36. new DInputButton(Std.parseInt(ba[0]), Std.parseInt(ba[1]), -1);
  37. }
  38. case 'a'.code:
  39. new DInputButton(-1,-1,Std.parseInt(p[1].substr(1)));
  40. default: null;
  41. }
  42. if( btn == null ) continue;
  43. switch( p[0] ){
  44. case "leftx": button[0] = btn;
  45. case "lefty": button[1] = btn;
  46. case "rightx": button[2] = btn;
  47. case "righty": button[3] = btn;
  48. case "lefttrigger": button[4] = btn;
  49. case "righttrigger": button[5] = btn;
  50. default:
  51. var idx = switch( p[0] ){
  52. case "dpup": Btn_DPadUp;
  53. case "dpdown": Btn_DPadDown;
  54. case "dpleft": Btn_DPadLeft;
  55. case "dpright": Btn_DPadRight;
  56. case "start": Btn_Start;
  57. case "back": Btn_Back;
  58. case "leftstick": Btn_LeftStick;
  59. case "rightstick": Btn_RightStick;
  60. case "leftshoulder": Btn_LB;
  61. case "rightshoulder": Btn_RB;
  62. case "a": Btn_A;
  63. case "b": Btn_B;
  64. case "x": Btn_X;
  65. case "y": Btn_Y;
  66. default: null;
  67. }
  68. if( idx != null )
  69. button[6+Type.enumIndex(idx)] = btn;
  70. }
  71. }
  72. }
  73. // Default DInput mappings based on libSDL ( https://www.libsdl.org/ )
  74. static var DEFAULTS = [
  75. "03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,",
  76. "03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,",
  77. "03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,",
  78. "03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,",
  79. "03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
  80. "03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,",
  81. "03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,",
  82. "03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,",
  83. "03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
  84. "030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
  85. "030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
  86. "030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
  87. "030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
  88. "030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,",
  89. "030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
  90. "030000006d04000018c2000000000000,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
  91. "030000006d04000019c2000000000000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
  92. "03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
  93. "03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
  94. "03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,",
  95. "030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,",
  96. "030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,",
  97. "03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,",
  98. "03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,",
  99. "030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
  100. "03000000250900000500000000000000,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,",
  101. "030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", // DualShock 4 v1 (Wired or Wireless)
  102. "030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", // DualShock 4 v2 (Wired or Wireless)
  103. "030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", // DualShock 4 (Wireless with Sony adapter)
  104. "03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,",
  105. "030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
  106. "03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,x:b0,y:b1,",
  107. "03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,",
  108. "03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,",
  109. ];
  110. public static function parseDefaults() : hl.NativeArray<DInputMapping> {
  111. var a = [for( s in DEFAULTS ) new DInputMapping(s)];
  112. var n = new hl.NativeArray(a.length);
  113. for( i in 0...a.length ) n[i] = a[i];
  114. return n;
  115. }
  116. }
  117. enum GameControllerButton {
  118. Btn_DPadUp;
  119. Btn_DPadDown;
  120. Btn_DPadLeft;
  121. Btn_DPadRight;
  122. Btn_Start;
  123. Btn_Back;
  124. Btn_LeftStick;
  125. Btn_RightStick;
  126. Btn_LB;
  127. Btn_RB;
  128. Btn_A;
  129. Btn_B;
  130. Btn_X;
  131. Btn_Y;
  132. }
  133. @:keep @:hlNative("directx")
  134. class GameController {
  135. public static var CONFIG = {
  136. analogX : 14,
  137. analogY : 15,
  138. ranalogX : 16,
  139. ranalogY : 17,
  140. LT : 18,
  141. RT : 19,
  142. dpadUp : 0,
  143. dpadDown : 1,
  144. dpadLeft : 2,
  145. dpadRight : 3,
  146. start : 4,
  147. back : 5,
  148. analogClick : 6,
  149. ranalogClick : 7,
  150. LB : 8,
  151. RB : 9,
  152. A : 10,
  153. B : 11,
  154. X : 12,
  155. Y : 13,
  156. names : ["DUp","DDown","DLeft","DRight","Start","Back","LCLK","RCLK","LB","RB","A","B","X","Y","LX","LY","RX","RY","LT","RT"],
  157. };
  158. public static var NUM_BUTTONS = 14;
  159. public static var NUM_AXES = 6;
  160. var ptr(default,null) : GameControllerPtr;
  161. public var index : Int;
  162. public var name(default,null) : String;
  163. public var buttons : haxe.EnumFlags<GameControllerButton>;
  164. public var axes : hl.Bytes;
  165. var rumbleEnd : Null<Float>;
  166. function new(){
  167. }
  168. public inline function update(){
  169. gctrlUpdate(this);
  170. if( rumbleEnd != null && haxe.Timer.stamp() > rumbleEnd ){
  171. gctrlSetVibration(ptr,0.);
  172. rumbleEnd = null;
  173. }
  174. }
  175. public inline function rumble( strength : Float, time_s : Float ){
  176. gctrlSetVibration(ptr,strength);
  177. rumbleEnd = strength <= 0 ? null : haxe.Timer.stamp() + time_s;
  178. }
  179. public inline function getAxis( i : Int ) {
  180. return (i<0 || i>=NUM_AXES) ? 0. : axes.getF64(i*8);
  181. }
  182. public inline function getButtons(){
  183. return buttons.toInt();
  184. }
  185. //
  186. static var UID = 0;
  187. static var ALL = [];
  188. public static function init(){
  189. var mappings = DInputMapping.parseDefaults();
  190. gctrlInit( mappings );
  191. }
  192. public static function detect( onDetect : GameController -> Bool -> Void ){
  193. gctrlDetect(function(ptr:GameControllerPtr, name:hl.Bytes){
  194. if( name != null ){
  195. var d = new GameController();
  196. d.ptr = ptr;
  197. d.name = @:privateAccess String.fromUTF8(name);
  198. d.index = UID++;
  199. d.axes = new hl.Bytes(NUM_AXES*8);
  200. d.update();
  201. ALL.push(d);
  202. onDetect(d,true);
  203. }else{
  204. for( d in ALL ){
  205. if( d.ptr == ptr ){
  206. ALL.remove(d);
  207. onDetect(d,false);
  208. break;
  209. }
  210. }
  211. }
  212. });
  213. }
  214. static function gctrlInit( mappings : hl.NativeArray<DInputMapping> ){}
  215. static function gctrlDetect( onDetect : GameControllerPtr -> hl.Bytes -> Void ){}
  216. static function gctrlUpdate( pad : GameController ){}
  217. static function gctrlSetVibration( ptr : GameControllerPtr, strength : Float ){}
  218. }