Skip to content

Commit a9836d6

Browse files
committed
support my Hornet Gamepad, clean up
1 parent b3e5d8a commit a9836d6

File tree

7 files changed

+296
-90
lines changed

7 files changed

+296
-90
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@
2121

2222
### Notes
2323
* Original SNES Mouse is not supported. (I don't have one, but if you give me the RetrodeTest output I could add it...)
24+
* Latest version also supports my _Speedlink Hornet USB Gamepad_: VID=0079, PID=0011. Various manufacturers use the same IDs, but with different button layouts.
2425
* I also maintain the [RetroArchWiiRetrode](https://github.com/revvv/RetroArchWiiRetrode/) fork.
2526

2627
#### Download
27-
* [snes9xgx-retrode-xbox360-0.4.zip](https://github.com/revvv/snes9xgx-retrode/releases/download/0.4/snes9xgx-retrode-xbox360-0.4.zip)
28+
* [snes9xgx-retrode-xbox360-0.5.zip](https://github.com/revvv/snes9xgx-retrode/releases/download/0.5/snes9xgx-retrode-xbox360-0.5.zip)
2829
* [RetrodeTest-0.1.zip](https://github.com/revvv/snes9xgx-retrode/releases/download/0.1/RetrodeTest-0.1.zip)
2930

3031
![Screenshot](snes9xgx-screenshot.png "Snes9x GX Credits screen")

source/input.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#ifdef HW_RVL
3939
#include "utils/retrode.h"
4040
#include "utils/xbox360.h"
41+
#include "utils/hornet.h"
4142
#endif
4243

4344
#define ANALOG_SENSITIVITY 30
@@ -337,6 +338,7 @@ UpdatePads()
337338
WiiDRC_ScanPads();
338339
Retrode_ScanPads();
339340
XBOX360_ScanPads();
341+
Hornet_ScanPads();
340342
WPAD_ScanPads();
341343
#endif
342344

@@ -539,6 +541,7 @@ static void decodepad (int chan)
539541

540542
jp |= Retrode_ButtonsHeld(chan);
541543
jp |= XBOX360_ButtonsHeld(chan);
544+
jp |= Hornet_ButtonsHeld(chan);
542545
#endif
543546

544547
/***
@@ -904,5 +907,6 @@ char* GetUSBControllerInfo()
904907
{
905908
static char info[50];
906909
snprintf(info, 50, "Retrode: %s, XBOX360: %s", Retrode_Status(), XBOX360_Status());
910+
Hornet_Status(); // Hornet support as undocumented feature ;-)
907911
return info;
908912
}

source/snes9xgx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "filelist.h"
2121

2222
#define APPNAME "Snes9x GX"
23-
#define APPVERSION "4.4.3 Retrode/XBOX360 0.3"
23+
#define APPVERSION "4.4.3 Retrode/XBOX360 0.5"
2424
#define APPFOLDER "snes9xgx"
2525
#define PREF_FILE_NAME "settings.xml"
2626

source/utils/hornet.c

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#ifdef HW_RVL
2+
#include <gccore.h>
3+
4+
static bool setup = false;
5+
static bool replugRequired = false;
6+
static s32 deviceId = 0;
7+
static u8 endpoint = 0;
8+
static u8 bMaxPacketSize = 0;
9+
static u32 jp;
10+
11+
bool isHornetGamepad(usb_devdesc devdesc)
12+
{
13+
return (devdesc.idVendor == 0x0079 && devdesc.idProduct == 0x0011);
14+
}
15+
16+
static u8 getEndpoint(usb_devdesc devdesc)
17+
{
18+
if (devdesc.configurations == NULL || devdesc.configurations->interfaces == NULL ||
19+
devdesc.configurations->interfaces->endpoints == NULL)
20+
{
21+
return -1;
22+
}
23+
return devdesc.configurations->interfaces->endpoints->bEndpointAddress;
24+
}
25+
26+
static int removal_cb(int result, void *usrdata)
27+
{
28+
s32 fd = (s32) usrdata;
29+
if (fd == deviceId)
30+
{
31+
deviceId = 0;
32+
}
33+
return 1;
34+
}
35+
36+
static void open()
37+
{
38+
if (deviceId != 0)
39+
{
40+
return;
41+
}
42+
43+
usb_device_entry dev_entry[8];
44+
u8 dev_count;
45+
if (USB_GetDeviceList(dev_entry, 8, USB_CLASS_HID, &dev_count) < 0)
46+
{
47+
return;
48+
}
49+
50+
for (int i = 0; i < dev_count; ++i)
51+
{
52+
s32 fd;
53+
if (USB_OpenDevice(dev_entry[i].device_id, dev_entry[i].vid, dev_entry[i].pid, &fd) < 0)
54+
{
55+
continue;
56+
}
57+
58+
usb_devdesc devdesc;
59+
if (USB_GetDescriptors(fd, &devdesc) < 0)
60+
{
61+
// You have to replug the controller!
62+
replugRequired = true;
63+
USB_CloseDevice(&fd);
64+
break;
65+
}
66+
67+
if (isHornetGamepad(devdesc))
68+
{
69+
deviceId = fd;
70+
replugRequired = false;
71+
endpoint = getEndpoint(devdesc);
72+
bMaxPacketSize = devdesc.bMaxPacketSize0;
73+
USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*) fd);
74+
break;
75+
}
76+
else
77+
{
78+
USB_CloseDevice(&fd);
79+
}
80+
}
81+
82+
setup = true;
83+
}
84+
85+
void Hornet_ScanPads()
86+
{
87+
if (deviceId == 0)
88+
{
89+
return;
90+
}
91+
92+
uint8_t ATTRIBUTE_ALIGN(32) buf[bMaxPacketSize];
93+
s32 res = USB_ReadIntrMsg(deviceId, endpoint, sizeof(buf), buf);
94+
if (res < 0)
95+
{
96+
return;
97+
}
98+
99+
// Button layout
100+
// A=5,2F
101+
// B=5,1F
102+
// X=6,01
103+
// Y=5,8F
104+
// Select=6,10 ; Hornet button label = "9"
105+
// Start=6,20 ; Hornet button label = "10"
106+
// Up=4,00
107+
// Right=3,FF
108+
// Left=3,00
109+
// Down=4,FF
110+
// L=6,04
111+
// R=6,08
112+
// Unused=6,02 ; Hornet button label = "6"
113+
// Unused=5,4F ; Hornet button label = "3"
114+
115+
jp = 0;
116+
jp |= (buf[4] == 0x00) ? PAD_BUTTON_UP : 0;
117+
jp |= (buf[4] == 0xFF) ? PAD_BUTTON_DOWN : 0;
118+
jp |= (buf[3] == 0x00) ? PAD_BUTTON_LEFT : 0;
119+
jp |= (buf[3] == 0xFF) ? PAD_BUTTON_RIGHT : 0;
120+
121+
jp |= ((buf[5] & 0x2F) == 0x2F) ? PAD_BUTTON_A : 0;
122+
jp |= ((buf[5] & 0x1F) == 0x1F) ? PAD_BUTTON_B : 0;
123+
jp |= ((buf[6] & 0x01) == 0x01) ? PAD_BUTTON_X : 0;
124+
jp |= ((buf[5] & 0x8F) == 0x8F) ? PAD_BUTTON_Y : 0;
125+
126+
jp |= ((buf[6] & 0x04) == 0x04) ? PAD_TRIGGER_L : 0;
127+
jp |= ((buf[6] & 0x08) == 0x08) ? PAD_TRIGGER_R : 0;
128+
129+
jp |= ((buf[6] & 0x20) == 0x20) ? PAD_BUTTON_START : 0;
130+
jp |= ((buf[6] & 0x10) == 0x10) ? PAD_TRIGGER_Z : 0; // Hornet select button maps to Z
131+
132+
jp |= ((buf[6] & 0x02) == 0x02) ? PAD_BUTTON_Y : 0; // Hornet button 6 maps to Y
133+
jp |= ((buf[5] & 0x4F) == 0x4F) ? PAD_BUTTON_B : 0; // Hornet button 3 maps to B
134+
}
135+
136+
u32 Hornet_ButtonsHeld(int chan)
137+
{
138+
if(!setup)
139+
{
140+
open();
141+
}
142+
if (deviceId == 0)
143+
{
144+
return 0;
145+
}
146+
if (chan != 0)
147+
{
148+
return 0;
149+
}
150+
return jp;
151+
}
152+
153+
char* Hornet_Status()
154+
{
155+
open();
156+
if (replugRequired)
157+
return "please replug";
158+
return deviceId ? "connected" : "not found";
159+
}
160+
161+
#endif

source/utils/hornet.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef _HORNET_H_
2+
#define _HORNET_H_
3+
4+
#include <gctypes.h>
5+
6+
#ifdef __cplusplus
7+
extern "C" {
8+
#endif
9+
10+
bool Hornet_ScanPads();
11+
u32 Hornet_ButtonsHeld(int chan);
12+
char* Hornet_Status();
13+
14+
#ifdef __cplusplus
15+
}
16+
#endif
17+
18+
#endif

0 commit comments

Comments
 (0)