libretro / Mesen

Mesen is a cross-platform (Windows & Linux) NES/Famicom emulator built in C++
https://www.mesen.ca
GNU General Public License v3.0
15 stars 19 forks source link

Some Famicom expansion-port devices request button inputs from the wrong virtual port #42

Open StormedBubbles opened 12 months ago

StormedBubbles commented 12 months ago

Hi,

I found this issue when trying out the Bandai Hyper Shot and the Family Trainer Mat. Those are both devices that would plug in to the Famicom's expansion port if used on real hardware. In lr-mesen, they are selectable via RetroArch's "port 5." However, when selected, the button inputs are taken from whatever device is assigned to port 1 instead. At least for the Family Trainer Mat, that seems to occur because of this section from libretro.cpp:

unsigned powerPadPort = 0;
if(_console->GetSettings()->GetExpansionDevice() == ExpansionPortDevice::FamilyTrainerMat) {
    powerPadPort = 4;
}

keyMappings.Mapping1.PowerPadButtons[0] = getKeyCode(powerPadPort, RETRO_DEVICE_ID_JOYPAD_B);
keyMappings.Mapping1.PowerPadButtons[1] = getKeyCode(powerPadPort, RETRO_DEVICE_ID_JOYPAD_A);
keyMappings.Mapping1.PowerPadButtons[2] = getKeyCode(powerPadPort, RETRO_DEVICE_ID_JOYPAD_Y);
keyMappings.Mapping1.PowerPadButtons[3] = getKeyCode(powerPadPort, RETRO_DEVICE_ID_JOYPAD_X);
keyMappings.Mapping1.PowerPadButtons[4] = getKeyCode(powerPadPort, RETRO_DEVICE_ID_JOYPAD_L);
keyMappings.Mapping1.PowerPadButtons[5] = getKeyCode(powerPadPort, RETRO_DEVICE_ID_JOYPAD_R);
keyMappings.Mapping1.PowerPadButtons[6] = getKeyCode(powerPadPort, RETRO_DEVICE_ID_JOYPAD_LEFT);
keyMappings.Mapping1.PowerPadButtons[7] = getKeyCode(powerPadPort, RETRO_DEVICE_ID_JOYPAD_RIGHT);
keyMappings.Mapping1.PowerPadButtons[8] = getKeyCode(powerPadPort, RETRO_DEVICE_ID_JOYPAD_UP);
keyMappings.Mapping1.PowerPadButtons[9] = getKeyCode(powerPadPort, RETRO_DEVICE_ID_JOYPAD_DOWN);
keyMappings.Mapping1.PowerPadButtons[10] = getKeyCode(powerPadPort, RETRO_DEVICE_ID_JOYPAD_SELECT);
keyMappings.Mapping1.PowerPadButtons[11] = getKeyCode(powerPadPort, RETRO_DEVICE_ID_JOYPAD_START);

The condition in the "if" statement is apparently never met, so powerPadPort is always 0. There is a similar issue with the Bandai Hyper Shot (your lightgun device has to be assigned the mouse index used by port 1), but I can't seem to find where in the code this occurs. I am also not sure what exactly should be the condition in the "if" statement instead. If I find it, then I will send a PR, but does anyone have insight?

StormedBubbles commented 11 months ago

Just to follow up on this, the Family Trainer taking button inputs from port 1 is problematic because at least some of the Family Trainer games require a controller as well as the floor pad. Select and start are mapped to Family Trainer buttons 11 and 12, respectively, so if you use one or both of those, you will simultaneously perform the in-game action and either pause or exit your current activity. Family Trainer 8 (Takeshi's Castle) is an example of this. I just forced powerPadPort to be equal to 4 (so port 5 on the user side) and removed the "if" condition entirely. powerPadPort isn't even used anywhere else. It works, and I can play Family Trainer 8 fine, but I don't know if there is supposed to be some overarching input structure with these expansion-port devices that I'd be interrupting by eliminating that condition which isn't working.