"Bugs" due to pressing left+right

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
"Bugs" due to pressing left+right
by on (#6115)
Recently I finally tracked down what I thought was a bug in my emulator when playing Battletoads. Very rarely the toad would float above platforms, usually in the snake pit, but sometimes in the ice stage. Once floating he could still stand on things and walk around, but not hit any enemies or the exit hole on snake levels.

I thought it must be an emulator bug in those areas the timing seemed different (the status bar is lower in the snake pit, for example). At some point I caught myself pressing left and right at the same time (using the keyboard arrow keys) and clued in. I held them and the toad just floated up. Argh! I knew about a similar problem in Zelda 2, but hadn't yet bothered to filter this from joypad input. The reason it occured mostly in those vertical scrolling areas is that those are the places where you're changing directions often, thus more likely to press both at the same time.

I just wanted to mention this as a source of phantom bugs in a game that is hard on emulators. I came up with a joypad "filter" which eliminates simultaneous use of left and right, and up and down, preferring the most recently pressed direction ("rollover") rather than just clearing that axis when both are pressed. It was tricky to get the algorithm correct and compact, so I'm showing the code I used.


Code:
const int x_axis = 0xc0;
const int y_axis = 0x30;
int mask = ~0x50;
int prev;

int filter_joypad( int joypad )
{
    int changed = prev ^ joypad;
    int hidden = joypad & ~mask;
   
    if ( (changed & x_axis) && (hidden & x_axis) )
        mask ^= x_axis;
   
    if ( (changed & y_axis) && (hidden & y_axis) )
        mask ^= y_axis;
   
    prev = joypad;
    return joypad & mask;
}


Update: I fixed a bug in the code (holding l+r then pressing up or down caused x axis direction to swap). Like I said, it's a tricky algorithm to get right!
Re: "Bugs" due to pressing left+right
by on (#6139)
blargg wrote:
preferring the most recently pressed direction ("rollover") rather than just clearing that axis when both are pressed.


Good approach, I'm just clearing both axes, and will probably change that :p .. In your implementation, what happens if the user presses left+right or up+down at the same time ? (instead of eg. holding left, then right while still holding left)

by on (#6141)
Heh, if you press left and right at the same moment, it will choose the opposite direction as was last used for that axis. So repeating left+right, release, left+right, release, etc. will give alternating directions for the X axis.

Be sure to provide a way to disable it so people wanting to intentionally invoke these behaviors (as are possible on a real NES) won't be foiled. Setting the mask to ~0 will conveniently disable the filtering.

by on (#6152)
Wouldn't just XOR the left signal with the right one, the right signal with the left one, the down signal with the up one, and the up signal with the down one just be fine to avoid problems ?

by on (#6154)
Do you mean something like this?

Code:
int filter_joypad( int joypad )
{
    return joypad ^ ((joypad >> 1) & 0x50) ^ ((joypad & 0x50) << 1);
}


If you're playing on a keyboard, you might press the other direction before you release the current direction. If you block out that axis until the previous direction is released, you basically introduce a delay into the player input. The point of the more complex algorithm is to avoid this by switching to the new direction immediately, even while both directions are held at once. It also handles the case where you release the new direction while still holding the old one, reverting back to that.

On a decent gamepad you can't press both directions at once so this issue only applies to the keyboard.

by on (#6176)
blargg wrote:
Be sure to provide a way to disable it so people wanting to intentionally invoke these behaviors (as are possible on a real NES) won't be foiled. Setting the mask to ~0 will conveniently disable the filtering.


The construction of the NES controller prohibits L/R and U/D from being pressed at the same time. Unless the controller is worn, that is. Some games don't just act silly if you press opposing directions simultaneously, they just flat out crash -- Commando comes to mind.

by on (#6179)
Quote:
The construction of the NES controller prohibits L/R and U/D from being pressed at the same time.


I was thinking of the "tool-assisted speedrun" crowd, for whom pressing left+right can be done on a normal NES console (with a suitable controller), as opposed to only on an emulator.

by on (#6182)
blargg wrote:
Quote:
The construction of the NES controller prohibits L/R and U/D from being pressed at the same time.


I was thinking of the "tool-assisted speedrun" crowd, for whom pressing left+right can be done on a normal NES console (with a suitable controller), as opposed to only on an emulator.


Which commercial controllers allow for opposing directions at the same time?

by on (#6185)
Any that have screws or cases that can be opened. :)

The tool-assisted people basically consider any set of bits loaded into the joypad's shifter register and presses of reset and power to be fair game. Utilizing glitches due to pressing left+right is considered no different than other glitches (like the ball-in-the-door trick in Metroid). It's a fine line, but it's an option to add (disabling filtering) if your emulator has good movie re-recording capabilities.

by on (#6189)
I once ran across a controller with two joysticks (supposedly the second was for the benefit of left-handers, of which I am one, but I found it rather useless as you get trained to use right-handed equipment despite your left-handedness). Also, many games will, for the benefit of Famicom users, take the inputs of $4016.0 and $4016.1 and OR them together (same for $4017), so that would be another way.

Having once been a follower of the glitch scene, I have gotten into debates with people about whether it's a true glitch or not, since it isn't possible on standard equipment to hold Left+Right simultaneously. I equally denounce glitches that aren't possible without Turbo controllers, especially since the ones I have don't rapid-fire fast enough for me to take advantage. Both kinds of glitches are well-documented for certain games, most notable Zelda LTTP for SNES (both Left-Right pressing and rapid-fire can get you a cheap early victory, easily within a half-hour after starting a new game).

by on (#6192)
And then there are games where you must press left+right, or you get a MISS. Most of those are for the Power Pad or for other platforms' equivalent of the Power Pad.

by on (#6197)
So the power pad can't be used to do this trick? I am pretty sure that this trick can be done on modern consoles via a DDR pad, but I might be wrong and I am sure modern games filter out such unexpected inputs. There were controllers for the SNES that used a touch-sensitive membrane instead of a D-pad. Any chance that allows for both directions at the same time, or does the controller itself filter our such inputs?

It is all fair game, just as long as the demo recorders document what real-world hardware they are using, as a modified controller is similar to using a modified cart or a cheat cart, etc. The coolest tricks, in my opinion, are the ones that can be accomplished with official hardware only, no hacks, no cheat devices, etc. Remember Street Fighter 2's handcuffs and magic throws? Now THAT is a cool trick :)

by on (#6215)
Power Pad feeds into D3 and D4, not D0, although it could easily be rewired to feed into D0.

by on (#77047)
The common decision for emulator is adding a function of enabling "left + right at once".

But I was wondering, what code forces the toad to float in 2D levels? It doesn't happen in 3D ones, where if you press left+right, he will go up, and if you press it every other frame - he'll run up. Adding "down" to left+right will make him run down.
But in a 2D level pressing left+right every other frame will make the toad to RUN up on air.

by on (#77048)
I think it feeds the controller input into a small jump table, which does not have enough entries to handle opposing directions.
Also, necropost anyone?

by on (#77054)
Dwedit wrote:
Also, necropost anyone?

No problem with that.

But new programs for NES and Super NES should take care to handle opposing direction presses inside the game. I've been able to push L+U+R with a licensed third-party Super NES controller. (It was either an SN ProPad or an SN ProgramPad.) And anyone with a dance pad can easily feed opposing presses into any PS1 or PS2 game compatible with a PS1 digital controller.


Anyway, back to topic: If it's really a jump table, and not an acceleration or velocity table, I'm surprised that it doesn't actually crash the game.

by on (#77055)
Quote:
necropost

1995 days. Impressive.