Skip to content

Commit 76052c3

Browse files
pianomantyTyler Sanders
andauthored
Added support for the mayflash MF105 adapter (#1096)
Co-authored-by: Tyler Sanders <ts393@byu.edu>
1 parent 341978e commit 76052c3

File tree

2 files changed

+123
-34
lines changed

2 files changed

+123
-34
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Wii homebrew is WiiBrew (www.wiibrew.org).
4848
Wii U Pro, and Gamecube controller support
4949
* Wii U GamePad support (requires homebrew injection into Wii U VC title)
5050
* Retrode/Xbox 360/Hornet controller support
51+
* Mayflash PC044 and MF105 SNES to USB adapter support
5152
* SNES Superscope, Mouse, Justifier support
5253
* Cheat support
5354
* Artwork (artwork, cover or screenshot) support
@@ -102,7 +103,7 @@ Wii homebrew is WiiBrew (www.wiibrew.org).
102103

103104
[4.5.2 - March 23, 2021]
104105

105-
* Added support for Mayflash 2-port SNES USB adapter (thanks EthanArmbrust!)
106+
* Added support for Mayflash PC044 2-port SNES USB adapter (thanks EthanArmbrust!)
106107
* Added L+R+START for back to menu for Wii Classic Controller
107108
* Updated French translation (thanks Tanooki16!)
108109
* Fixed issue with displaying screenshots

source/utils/mayflash.c

Lines changed: 121 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
#ifdef HW_RVL
22
#include <gccore.h>
33

4-
#define MAYFLASH_VID 0x0E8F
5-
#define MAYFLASH_PID 0x3013
4+
#define MAYFLASH_PC044_VID 0x0E8F
5+
#define MAYFLASH_PC044_PID 0x3013
6+
#define MAYFLASH_MF105_VID 0x2F24
7+
#define MAYFLASH_MF105_PID 0x00F1
68

79
static bool setup = false;
810
static bool replugRequired = false;
9-
static s32 deviceId = 0;
11+
static s32 deviceId = 0;
12+
static s32 secondDeviceId = 0; //Need to keep track of 2 device IDs, since MF105 enumerates as 2 devices
1013
static u8 endpoint = 0;
11-
static u8 bMaxPacketSize = 0;
12-
static u32 jpMayflash[2];
14+
static u8 secondEndpoint = 0; //Need to keep track of 2 endpoints, since MF105 enumerates as 2 devices
15+
static u8 bMaxPacketSize = 0; //Size of usb HID packets sent by device
16+
static u32 jpMayflash[2]; //Array containing inputs for player 1 (index 0) and player 2 (index 1)
17+
static s8 mayflashDeviceType = -1; //-1 for unkown/uninitialized, 0 for PC044, 1 for MF105
1318

1419
static bool isMayflashGamepad(usb_device_entry dev)
1520
{
16-
return dev.vid == MAYFLASH_VID && dev.pid == MAYFLASH_PID;
21+
return (dev.vid == MAYFLASH_PC044_VID && dev.pid == MAYFLASH_PC044_PID) ||
22+
(dev.vid == MAYFLASH_MF105_VID && dev.pid == MAYFLASH_MF105_PID);
1723
}
1824

1925
static u8 getEndpoint(usb_devdesc devdesc)
@@ -38,6 +44,7 @@ static int removal_cb(int result, void *usrdata)
3844

3945
static void open()
4046
{
47+
// Opens the device gets the device Id(s), endpoint(s), packet size, etc
4148
if (deviceId != 0)
4249
{
4350
return;
@@ -70,32 +77,44 @@ static void open()
7077
USB_CloseDevice(&fd);
7178
break;
7279
}
80+
//set the device type to the given adapter
81+
if (dev_entry[i].vid == MAYFLASH_PC044_VID && dev_entry[i].pid == MAYFLASH_PC044_PID)
82+
{
83+
mayflashDeviceType = 0;
84+
}
85+
else if (dev_entry[i].vid == MAYFLASH_MF105_VID && dev_entry[i].pid == MAYFLASH_MF105_PID)
86+
{
87+
mayflashDeviceType = 1;
88+
//If first device ID is uninitialized, initialize it now
89+
if (deviceId == 0)
90+
{
91+
deviceId = fd;
92+
}
93+
else
94+
{
95+
secondDeviceId = deviceId;
96+
secondEndpoint = endpoint;
97+
}
98+
}
7399

74100
deviceId = fd;
75101
replugRequired = false;
76102
endpoint = getEndpoint(devdesc);
77103
bMaxPacketSize = devdesc.bMaxPacketSize0;
78104
USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*) fd);
79-
break;
105+
//May need to continue searching for the other MF105
106+
if (mayflashDeviceType == 0 || secondDeviceId != 0)
107+
{
108+
break;
109+
}
80110
}
81111

82112
setup = true;
83113
}
84114

85-
void Mayflash_ScanPads()
115+
u32 getButtonMappingPC044(const uint8_t *buf)
86116
{
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-
117+
//provided a buffer from a PC044, gets the currently pressed buttons and returns it as a u32
99118
// buf[0] contains the port returned
100119
// you have to make 2 calls to get the status, even if you're only interested in one port
101120
// because it is not sure which port is returned first
@@ -116,28 +135,97 @@ void Mayflash_ScanPads()
116135
// Down=4,FF
117136
// L=6,04
118137
// R=6,08
138+
u32 jp = 0;
139+
140+
// Directional buttons
141+
jp |= (buf[4] == 0x00) ? PAD_BUTTON_UP : 0;
142+
jp |= (buf[4] == 0xFF) ? PAD_BUTTON_DOWN : 0;
143+
jp |= (buf[3] == 0x00) ? PAD_BUTTON_LEFT : 0;
144+
jp |= (buf[3] == 0xFF) ? PAD_BUTTON_RIGHT : 0;
145+
146+
// Action buttons
147+
jp |= ((buf[5] & 0x2F) == 0x2F) ? PAD_BUTTON_A : 0;
148+
jp |= ((buf[5] & 0x4F) == 0x4F) ? PAD_BUTTON_B : 0;
149+
jp |= ((buf[5] & 0x1F) == 0x1F) ? PAD_BUTTON_X : 0;
150+
jp |= ((buf[5] & 0x8F) == 0x8F) ? PAD_BUTTON_Y : 0;
151+
152+
// Triggers
153+
jp |= ((buf[6] & 0x04) == 0x04) ? PAD_TRIGGER_L : 0;
154+
jp |= ((buf[6] & 0x08) == 0x08) ? PAD_TRIGGER_R : 0;
155+
156+
// Start and Select (mapped to Z)
157+
jp |= ((buf[6] & 0x20) == 0x20) ? PAD_BUTTON_START : 0;
158+
jp |= ((buf[6] & 0x10) == 0x10) ? PAD_TRIGGER_Z : 0; // SNES select button maps to Z
159+
160+
return jp;
161+
}
119162

163+
u32 getButtonMappingMF105(const uint8_t *buf)
164+
{
165+
//provided a buffer from a MF105, gets the currently pressed buttons and returns it as a u32
166+
//Button Inputs
120167
u32 jp = 0;
121-
jp |= (buf[4] == 0x00) ? PAD_BUTTON_UP : 0;
122-
jp |= (buf[4] == 0xFF) ? PAD_BUTTON_DOWN : 0;
123-
jp |= (buf[3] == 0x00) ? PAD_BUTTON_LEFT : 0;
124-
jp |= (buf[3] == 0xFF) ? PAD_BUTTON_RIGHT : 0;
168+
jp |= ((buf[0] & 0x01) == 0x01) ? PAD_BUTTON_Y : 0;
169+
jp |= ((buf[0] & 0x02) == 0x02) ? PAD_BUTTON_B : 0;
170+
jp |= ((buf[0] & 0x04) == 0x04) ? PAD_BUTTON_A : 0;
171+
jp |= ((buf[0] & 0x08) == 0x08) ? PAD_BUTTON_X : 0;
172+
jp |= ((buf[0] & 0x10) == 0x10) ? PAD_TRIGGER_L : 0;
173+
jp |= ((buf[0] & 0x20) == 0x20) ? PAD_TRIGGER_R : 0;
174+
jp |= ((buf[1] & 0x01) == 0x01) ? PAD_TRIGGER_Z : 0; // SNES select button maps to Z
175+
jp |= ((buf[1] & 0x02) == 0x02) ? PAD_BUTTON_START : 0;
176+
//Direction Inputs
177+
switch (buf[2]) {
178+
case 0x00: jp |= PAD_BUTTON_UP; break;
179+
case 0x01: jp |= (PAD_BUTTON_UP | PAD_BUTTON_RIGHT); break;
180+
case 0x02: jp |= PAD_BUTTON_RIGHT; break;
181+
case 0x03: jp |= (PAD_BUTTON_DOWN | PAD_BUTTON_RIGHT); break;
182+
case 0x04: jp |= PAD_BUTTON_DOWN; break;
183+
case 0x05: jp |= (PAD_BUTTON_DOWN | PAD_BUTTON_LEFT); break;
184+
case 0x06: jp |= PAD_BUTTON_LEFT; break;
185+
case 0x07: jp |= (PAD_BUTTON_UP | PAD_BUTTON_LEFT); break;
186+
case 0x08: break; // Neutral (no direction pressed)
187+
}
125188

126-
jp |= ((buf[5] & 0x2F) == 0x2F) ? PAD_BUTTON_A : 0;
127-
jp |= ((buf[5] & 0x4F) == 0x4F) ? PAD_BUTTON_B : 0;
128-
jp |= ((buf[5] & 0x1F) == 0x1F) ? PAD_BUTTON_X : 0;
129-
jp |= ((buf[5] & 0x8F) == 0x8F) ? PAD_BUTTON_Y : 0;
189+
return jp;
190+
}
130191

131-
jp |= ((buf[6] & 0x04) == 0x04) ? PAD_TRIGGER_L : 0;
132-
jp |= ((buf[6] & 0x08) == 0x08) ? PAD_TRIGGER_R : 0;
133192

134-
jp |= ((buf[6] & 0x20) == 0x20) ? PAD_BUTTON_START : 0;
135-
jp |= ((buf[6] & 0x10) == 0x10) ? PAD_TRIGGER_Z : 0; // SNES select button maps to Z
193+
void Mayflash_ScanPads()
194+
{
195+
if (deviceId == 0)
196+
{
197+
return;
198+
}
136199

200+
uint8_t ATTRIBUTE_ALIGN(32) buf[bMaxPacketSize];
201+
s32 res = USB_ReadIntrMsg(deviceId, endpoint, sizeof(buf), buf);
202+
if (res < 0)
203+
{
204+
return;
205+
}
206+
207+
// Process inputs for the PC044 type adapter
208+
if (mayflashDeviceType == 0)
209+
{
137210
// Required, otherwise if the returned port isn't the one we are looking for, jp will be set to zero,
138211
// and held buttons are not possible
212+
jpMayflash[buf[0] - 1] = getButtonMappingMF105(buf);
213+
}
214+
//Mapping for the M105 Adapter
215+
else if (mayflashDeviceType == 1)
216+
{
217+
// First enumerated device is treated as player one, second as player two
218+
jpMayflash[0] = getButtonMappingMF105(buf);
219+
220+
//now get inputs for the second device
221+
res = USB_ReadIntrMsg(secondDeviceId, secondEndpoint, sizeof(buf), buf);
222+
if (res < 0)
223+
{
224+
return;
225+
}
226+
jpMayflash[1] = getButtonMappingMF105(buf);
227+
}
139228

140-
jpMayflash[buf[0] - 1] = jp;
141229
}
142230

143231
u32 Mayflash_ButtonsHeld(int chan)

0 commit comments

Comments
 (0)