News: 11 March 2016 - Forum Rules

Author Topic: Using FCEUX to track what happens when a button gets pressed  (Read 1539 times)

cschifani

  • Jr. Member
  • **
  • Posts: 35
    • View Profile
Using FCEUX to track what happens when a button gets pressed
« on: April 28, 2019, 03:32:45 pm »
I'm trying to learn how to use FCEUX's functions. Suppose that I have the game Rockman 2, and I want to know what routine is run when I press the B button (Rockman shoots one bullet when you do this). What steps should I take to identify the routines that get run and separate them from other routines that would run at the same time, like the stage background and the music. Is it possible to pause the emulator, press B and then advance it one frame, in order to see precisely what routine is registered? Or is there a better way of finding this information? I appreciate any insight anyone might share.

FAST6191

  • Hero Member
  • *****
  • Posts: 3355
    • View Profile
Re: Using FCEUX to track what happens when a button gets pressed
« Reply #1 on: April 29, 2019, 11:06:47 am »
I can't say I have played around with controller hacks for the NES but the general theory is the same regardless of system and I will detail that.

Frame advancement is possible. Not the suggested method really though. The only people really doing anything like that would be tool assisted speedrun people that need frame accurate inputs for their runs, or maybe some people doing lua scripts (FCEUX does have class leading abilities here so I can see it).

Most people would probably come the other way though and set a breakpoint/watchpoint on the hardware register that reads the controller state, or in many cases where that gets debounced* to in normal memory.
For actions in a game it will tend not to be a check every frame** type of routine (hopefully anyway -- such a thing burns CPU power and batteries when on handhelds so it is bad programming) and instead some kind of interrupt.

As such a thing will inherently be in response to the button that should hopefully get rid of any incidental code running at the same time. It could be that two routines run independently and care about the same button press but this is rare. Instead most things will be serial in nature, and even without it then it should be fairly obvious pretty quickly if what is happening is what you are concerned with.

On the flip side I think FCEUX does have that new routine scan option if memory serves. Most people use it to find other things but it would work for this. I forget the name but the general idea is you tell the thing to activate, then do everything but press the button you want for a short bit of the game (whether you can mess around in a starting area or something is game by game really). Tell the emulator that whatever happens next that did not happen before to take note and tell me. Press the button of choice. As all the music, graphics drawing, timer, life... should have happened before then hopefully the only new routine called will be the one that cares about the button. Not all emulators/debuggers will have this functionality, indeed I dare say most won't, so don't rely on it being there for any given system. Also as games are pretty random things when all is said and done (code wise them being about as far as you can get from the classic "convert this database from this form to this form" program) you do risk a false positive for something where the method above will not fail you if you implement it correctly.


*debouncing if you are not familiar with the concept then. Switches are typically binary things (on or off/closed or open) but as they are based on physical things then it is entirely possible some small amount of stretch, corrosion, wear... makes it appear closed one millisecond and open the (and then closed again...) next despite your thumb having not released it or being in the process of it. Rather than suffer strange behaviours there, or have to have things reach out to the hardware every time something wants to know, or have to program around all this then many games/systems will copy the contents of the control state once per frame (maybe longer but hopefully not) and have everything operate off that for the next however long. This also provides you a nice location to do a probably game, or minigame, wide button swap hack as you can easily flip bits around here but I will leave that one for now.


**more modern PC games will decouple input from frame rate, or increase the input polling rate to multiple times per frame but for consoles and games we are likely to deal with around here then assume a debounced hardware section. Also it is still a hardware section that is read/copied so it still applies after a fashion.
« Last Edit: April 29, 2019, 06:53:41 pm by FAST6191 »

Psyklax

  • Hero Member
  • *****
  • Posts: 1112
    • View Profile
    • Psyklax Translations
Re: Using FCEUX to track what happens when a button gets pressed
« Reply #2 on: April 29, 2019, 04:22:57 pm »
I have done this myself so I know how the NES does it.

The way it works is that the game polls the register at $4016 every frame to see which buttons have been pressed, and usually stores the result in zero page RAM, for the game to then examine to determine what it should do. In the case of Megaman 2 (I've just opened it in front of me since I haven't tried this specific game before) the routine in question is at $D0D7 ($3D0E7). I found that out by setting a write breakpoint to $4016, and immediately this routine comes up.

It first writes 1 and 0 to $4016, setting it up to read the button inputs in a serial manner (one at a time). If you pause the game, set the write breakpoint, hold B and unpause, it'll come up with the routine. For some reason it reads from joypad 2, then proceeds to joypad 1. If you hold B, as I said, you'll see that first, $40 is written to $27 in zero page RAM, then on the second pass, $41 is written. The other six times produce $40, so with the game doing a ROtate Right on $23 with the result, you end up with $02 in address $23.

When the polling routine is over, we go to $C095, where the game filters that number in $23 and stores it in $27. Later, there are different routines that check $27. In the case of the one at $DA6C, it checks to see if is a $02 (ie Button B), and if so then goes through whatever else it does.

That's the basics, I'll let you experiment. :)

goldenband

  • Sr. Member
  • ****
  • Posts: 378
    • View Profile
Re: Using FCEUX to track what happens when a button gets pressed
« Reply #3 on: April 29, 2019, 04:48:45 pm »
For some reason it reads from joypad 2, then proceeds to joypad 1.

Interesting. Mega Man 3 has a well-known set of debugging features enabled via controller 2 --

https://tcrf.net/Mega_Man_3_(NES)

-- but I don't know of anything in MM2.

Cyneprepou4uk

  • Hero Member
  • *****
  • Posts: 734
  • I am the baldest romhacker
    • View Profile
« Last Edit: May 01, 2019, 01:35:55 pm by Cyneprepou4uk »

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 7257
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: Using FCEUX to track what happens when a button gets pressed
« Reply #5 on: May 01, 2019, 03:29:28 pm »
It first writes 1 and 0 to $4016, setting it up to read the button inputs in a serial manner (one at a time). If you pause the game, set the write breakpoint, hold B and unpause, it'll come up with the routine. For some reason it reads from joypad 2, then proceeds to joypad 1. If you hold B, as I said, you'll see that first, $40 is written to $27 in zero page RAM, then on the second pass, $41 is written. The other six times produce $40, so with the game doing a ROtate Right on $23 with the result, you end up with $02 in address $23.

Nearly every game, or at least every Japanese-produced game, seems to check both controller ports.
I think it has to do with allowing external controllers (on the expansion port) to be supported, in addition to the original Famicom's built-in controllers.
As to why games usually write $40 or $41, it is a bus issue. From what I read of a technical point, the console still has $40 on the bus, as the usual instructions to read the controller ports are LDA $4016/4017 (that is 0x40 is the last byte in the instruction) and then the bits with the actual input get overwritten (I do recall one doc where they said they tested it by using some unusual code such as a LDA ($nn),Y instruction.) Emulators do this because at least crappy game (some LJN game, I think) EXPECTS to get $40 or $41 though most games will do shifting that effectively masks out the junk bits.
"My watch says 30 chickens" Google, 2018