Added support for the mayflash MF105 adapter (#1096)

Co-authored-by: Tyler Sanders <ts393@byu.edu>
This commit is contained in:
Tyler Sanders 2025-03-22 08:42:55 -07:00 committed by GitHub
parent 341978ead8
commit 76052c393f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 123 additions and 34 deletions

View File

@ -48,6 +48,7 @@ Wii homebrew is WiiBrew (www.wiibrew.org).
Wii U Pro, and Gamecube controller support
* Wii U GamePad support (requires homebrew injection into Wii U VC title)
* Retrode/Xbox 360/Hornet controller support
* Mayflash PC044 and MF105 SNES to USB adapter support
* SNES Superscope, Mouse, Justifier support
* Cheat support
* Artwork (artwork, cover or screenshot) support
@ -102,7 +103,7 @@ Wii homebrew is WiiBrew (www.wiibrew.org).
[4.5.2 - March 23, 2021]
* Added support for Mayflash 2-port SNES USB adapter (thanks EthanArmbrust!)
* Added support for Mayflash PC044 2-port SNES USB adapter (thanks EthanArmbrust!)
* Added L+R+START for back to menu for Wii Classic Controller
* Updated French translation (thanks Tanooki16!)
* Fixed issue with displaying screenshots

View File

@ -1,19 +1,25 @@
#ifdef HW_RVL
#include <gccore.h>
#define MAYFLASH_VID 0x0E8F
#define MAYFLASH_PID 0x3013
#define MAYFLASH_PC044_VID 0x0E8F
#define MAYFLASH_PC044_PID 0x3013
#define MAYFLASH_MF105_VID 0x2F24
#define MAYFLASH_MF105_PID 0x00F1
static bool setup = false;
static bool replugRequired = false;
static s32 deviceId = 0;
static s32 deviceId = 0;
static s32 secondDeviceId = 0; //Need to keep track of 2 device IDs, since MF105 enumerates as 2 devices
static u8 endpoint = 0;
static u8 bMaxPacketSize = 0;
static u32 jpMayflash[2];
static u8 secondEndpoint = 0; //Need to keep track of 2 endpoints, since MF105 enumerates as 2 devices
static u8 bMaxPacketSize = 0; //Size of usb HID packets sent by device
static u32 jpMayflash[2]; //Array containing inputs for player 1 (index 0) and player 2 (index 1)
static s8 mayflashDeviceType = -1; //-1 for unkown/uninitialized, 0 for PC044, 1 for MF105
static bool isMayflashGamepad(usb_device_entry dev)
{
return dev.vid == MAYFLASH_VID && dev.pid == MAYFLASH_PID;
return (dev.vid == MAYFLASH_PC044_VID && dev.pid == MAYFLASH_PC044_PID) ||
(dev.vid == MAYFLASH_MF105_VID && dev.pid == MAYFLASH_MF105_PID);
}
static u8 getEndpoint(usb_devdesc devdesc)
@ -38,6 +44,7 @@ static int removal_cb(int result, void *usrdata)
static void open()
{
// Opens the device gets the device Id(s), endpoint(s), packet size, etc
if (deviceId != 0)
{
return;
@ -70,32 +77,44 @@ static void open()
USB_CloseDevice(&fd);
break;
}
//set the device type to the given adapter
if (dev_entry[i].vid == MAYFLASH_PC044_VID && dev_entry[i].pid == MAYFLASH_PC044_PID)
{
mayflashDeviceType = 0;
}
else if (dev_entry[i].vid == MAYFLASH_MF105_VID && dev_entry[i].pid == MAYFLASH_MF105_PID)
{
mayflashDeviceType = 1;
//If first device ID is uninitialized, initialize it now
if (deviceId == 0)
{
deviceId = fd;
}
else
{
secondDeviceId = deviceId;
secondEndpoint = endpoint;
}
}
deviceId = fd;
replugRequired = false;
endpoint = getEndpoint(devdesc);
bMaxPacketSize = devdesc.bMaxPacketSize0;
USB_DeviceRemovalNotifyAsync(fd, &removal_cb, (void*) fd);
break;
//May need to continue searching for the other MF105
if (mayflashDeviceType == 0 || secondDeviceId != 0)
{
break;
}
}
setup = true;
}
void Mayflash_ScanPads()
u32 getButtonMappingPC044(const uint8_t *buf)
{
if (deviceId == 0)
{
return;
}
uint8_t ATTRIBUTE_ALIGN(32) buf[bMaxPacketSize];
s32 res = USB_ReadIntrMsg(deviceId, endpoint, sizeof(buf), buf);
if (res < 0)
{
return;
}
//provided a buffer from a PC044, gets the currently pressed buttons and returns it as a u32
// buf[0] contains the port returned
// you have to make 2 calls to get the status, even if you're only interested in one port
// because it is not sure which port is returned first
@ -116,28 +135,97 @@ void Mayflash_ScanPads()
// Down=4,FF
// L=6,04
// R=6,08
u32 jp = 0;
// Directional buttons
jp |= (buf[4] == 0x00) ? PAD_BUTTON_UP : 0;
jp |= (buf[4] == 0xFF) ? PAD_BUTTON_DOWN : 0;
jp |= (buf[3] == 0x00) ? PAD_BUTTON_LEFT : 0;
jp |= (buf[3] == 0xFF) ? PAD_BUTTON_RIGHT : 0;
// Action buttons
jp |= ((buf[5] & 0x2F) == 0x2F) ? PAD_BUTTON_A : 0;
jp |= ((buf[5] & 0x4F) == 0x4F) ? PAD_BUTTON_B : 0;
jp |= ((buf[5] & 0x1F) == 0x1F) ? PAD_BUTTON_X : 0;
jp |= ((buf[5] & 0x8F) == 0x8F) ? PAD_BUTTON_Y : 0;
// Triggers
jp |= ((buf[6] & 0x04) == 0x04) ? PAD_TRIGGER_L : 0;
jp |= ((buf[6] & 0x08) == 0x08) ? PAD_TRIGGER_R : 0;
// Start and Select (mapped to Z)
jp |= ((buf[6] & 0x20) == 0x20) ? PAD_BUTTON_START : 0;
jp |= ((buf[6] & 0x10) == 0x10) ? PAD_TRIGGER_Z : 0; // SNES select button maps to Z
return jp;
}
u32 getButtonMappingMF105(const uint8_t *buf)
{
//provided a buffer from a MF105, gets the currently pressed buttons and returns it as a u32
//Button Inputs
u32 jp = 0;
jp |= (buf[4] == 0x00) ? PAD_BUTTON_UP : 0;
jp |= (buf[4] == 0xFF) ? PAD_BUTTON_DOWN : 0;
jp |= (buf[3] == 0x00) ? PAD_BUTTON_LEFT : 0;
jp |= (buf[3] == 0xFF) ? PAD_BUTTON_RIGHT : 0;
jp |= ((buf[0] & 0x01) == 0x01) ? PAD_BUTTON_Y : 0;
jp |= ((buf[0] & 0x02) == 0x02) ? PAD_BUTTON_B : 0;
jp |= ((buf[0] & 0x04) == 0x04) ? PAD_BUTTON_A : 0;
jp |= ((buf[0] & 0x08) == 0x08) ? PAD_BUTTON_X : 0;
jp |= ((buf[0] & 0x10) == 0x10) ? PAD_TRIGGER_L : 0;
jp |= ((buf[0] & 0x20) == 0x20) ? PAD_TRIGGER_R : 0;
jp |= ((buf[1] & 0x01) == 0x01) ? PAD_TRIGGER_Z : 0; // SNES select button maps to Z
jp |= ((buf[1] & 0x02) == 0x02) ? PAD_BUTTON_START : 0;
//Direction Inputs
switch (buf[2]) {
case 0x00: jp |= PAD_BUTTON_UP; break;
case 0x01: jp |= (PAD_BUTTON_UP | PAD_BUTTON_RIGHT); break;
case 0x02: jp |= PAD_BUTTON_RIGHT; break;
case 0x03: jp |= (PAD_BUTTON_DOWN | PAD_BUTTON_RIGHT); break;
case 0x04: jp |= PAD_BUTTON_DOWN; break;
case 0x05: jp |= (PAD_BUTTON_DOWN | PAD_BUTTON_LEFT); break;
case 0x06: jp |= PAD_BUTTON_LEFT; break;
case 0x07: jp |= (PAD_BUTTON_UP | PAD_BUTTON_LEFT); break;
case 0x08: break; // Neutral (no direction pressed)
}
jp |= ((buf[5] & 0x2F) == 0x2F) ? PAD_BUTTON_A : 0;
jp |= ((buf[5] & 0x4F) == 0x4F) ? PAD_BUTTON_B : 0;
jp |= ((buf[5] & 0x1F) == 0x1F) ? PAD_BUTTON_X : 0;
jp |= ((buf[5] & 0x8F) == 0x8F) ? PAD_BUTTON_Y : 0;
return jp;
}
jp |= ((buf[6] & 0x04) == 0x04) ? PAD_TRIGGER_L : 0;
jp |= ((buf[6] & 0x08) == 0x08) ? PAD_TRIGGER_R : 0;
jp |= ((buf[6] & 0x20) == 0x20) ? PAD_BUTTON_START : 0;
jp |= ((buf[6] & 0x10) == 0x10) ? PAD_TRIGGER_Z : 0; // SNES select button maps to Z
void Mayflash_ScanPads()
{
if (deviceId == 0)
{
return;
}
uint8_t ATTRIBUTE_ALIGN(32) buf[bMaxPacketSize];
s32 res = USB_ReadIntrMsg(deviceId, endpoint, sizeof(buf), buf);
if (res < 0)
{
return;
}
// Process inputs for the PC044 type adapter
if (mayflashDeviceType == 0)
{
// Required, otherwise if the returned port isn't the one we are looking for, jp will be set to zero,
// and held buttons are not possible
jpMayflash[buf[0] - 1] = getButtonMappingMF105(buf);
}
//Mapping for the M105 Adapter
else if (mayflashDeviceType == 1)
{
// First enumerated device is treated as player one, second as player two
jpMayflash[0] = getButtonMappingMF105(buf);
//now get inputs for the second device
res = USB_ReadIntrMsg(secondDeviceId, secondEndpoint, sizeof(buf), buf);
if (res < 0)
{
return;
}
jpMayflash[1] = getButtonMappingMF105(buf);
}
jpMayflash[buf[0] - 1] = jp;
}
u32 Mayflash_ButtonsHeld(int chan)