Controller Read Issue?

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
JoeGtake2
Posts: 333
Joined: Tue Jul 01, 2014 4:02 pm

Controller Read Issue?

Post by JoeGtake2 »

This is something that went unnoticed until now. I have a controller reading routine that seems to work just fine. It's this:

Code: Select all


GamePadCheck:
      LDA #$01
      STA $4016
      LDA #$00
      STA $4016
ReadControllerBytesLoop:
      PHA
      LDA $4016
      AND #%00000011
      CMP #%00000001
      PLA
      ROR
      DEX
      BNE ReadControllerBytesLoop
      STA gamepad
      RTS

This has worked with no issue. The controller behaves exactly as it should, with some defines. Up, down, left, right, select, start, b and a all function appropriately during gameplay.

The problem - I have set up a placeholder start screen. For a while, i've just had it where a press of the A button jumps to the game loop. This has worked no problem - it loops through the start screen code until A is pressed and then jumps to the main game loop. I finally got around to updating that to the 'start' button, and now it acts as if the start button is pressed at the start of the game and launches right to the main game loop. In fact, this happens for EVERY button except the A button.

Again, the buttons work correctly during game play, but it almost seems as if they are being 'activated' for a frame at the start of the game without an actual press, jumping out of the start screen loop prematurely....all of them except for the A button, which works as expected on the start screen.

Any thoughts as to what could be causing this?



***** When I pull a jump to this routine OUT of my NMI and call it at the top of the start screen loop, that seems to solve the problem...I still don't like not knowing why, if anyone has any thoughts*****
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: Controller Read Issue?

Post by Kasumi »

Any thoughts as to what could be causing this?
If gamepad doesn't change between your start screen and your main loop, then sure, every button that was pressed on the start screen will be pressed for your main loop. If it happens with every button except A, I'd imagine something totally unrelated is clearing out A's bit. (Or a press of A simply has no effect on the first frame of the game for a different reason.)

My game has a soft reset with A+B+Start+Select. It has a start screen that begins the game with a press of start. Reset zeroes out the buttons. So any button that was HELD on soft reset becomes a button press after the first joypad read. (Because the previously held buttons byte is now all clear.) It follows that that game began immediately after soft reset, because start is held down to do the reset, and then the start button hold becomes a press. To fix it, I just read the buttons again at the beginning of the start screen. This made all button presses button holds before the check for a press of start happened.


Where do you check buttons in your main loop? I can't suggest anything without knowing when your buttons are read in the main loop and the start screen. For you it sounds like you'd need another read in between your start screen and main game.

Edit: I might also be misunderstanding the problem. So... is it that your game begins immediately with no button presses when you check any button that's not A? Do you clear out your button RAM before the game begins? And are your button reads in your NMI?

Edit2: And for super completeness, how is X set up in the gamepad read subroutine? Because I don't see it set up there. I'm pretty sure if you read $4016 more than 8 times (and no special hardware is plugged in), you get nothing but set bits. So if you're reading it more than 8 times, that could be it too.
Last edited by Kasumi on Wed Dec 10, 2014 1:15 pm, edited 1 time in total.
User avatar
Tsutarja
Posts: 123
Joined: Sun Oct 12, 2014 11:06 am
Location: Finland

Re: Controller Read Issue?

Post by Tsutarja »

I had this same problem once. To me it seemed like updating the controller too fast corrupts the value. I tried to replicate this for debugging by forcing my game to update the controller too fast, but I couldn't get it to work anymore. It may have been something else, but when I last time had this problem, placing the controller reading in NMI fixed it.

Also, addition to what Kasumi said: when you reset your game, do you clear the memory? Not doing this can lead into issues on reset. The values would be #$00 when you turn on the console, but when you reset you don't know what is stored in memory. Clearing memory makes your game safer and it doesn't cost much time either.
UP SIDE DOWN A B A B B A B A Hidari migi
L R L R STOP & DASH & UP & TALK Ijou nashi
User avatar
Bregalad
Posts: 8036
Joined: Fri Nov 12, 2004 2:49 pm
Location: Caen, France

Re: Controller Read Issue?

Post by Bregalad »

The values would be #$00 when you turn on the console
No !!

The initial contents of the RAM is uninitialized !
User avatar
Tsutarja
Posts: 123
Joined: Sun Oct 12, 2014 11:06 am
Location: Finland

Re: Controller Read Issue?

Post by Tsutarja »

Bregalad wrote: No !!

The initial contents of the RAM is uninitialized !
I remember someone told me this, but I guess I forgot. Maybe because it was never explained. Just mentoined.
UP SIDE DOWN A B A B B A B A Hidari migi
L R L R STOP & DASH & UP & TALK Ijou nashi
User avatar
Bregalad
Posts: 8036
Joined: Fri Nov 12, 2004 2:49 pm
Location: Caen, France

Re: Controller Read Issue?

Post by Bregalad »

Ok, Ok, I'll explain.

The RAM of the NES is a 2k SRAM chip, of 6116 type, which is somewhere on the NES' motherboard. This chip, just like any other SRAM chips, is made of SRAM cells, which is basically two logic inverters feeding back each-other.

There is two stable states for this circuit, which correspond to '0' and '1' states. When writing to the SRAM, this forces the circuit into one of these states using an external voltage source. When reading the SRAM the output of the SRAM cell is simply amplified and read. When the SRAM cell is powered on there is no way to predict if it will become '0' or '1', because this will depend on how the internal details of the transistors that makes up the SRAM cell are made. Most of the time the data in the chip is random, but will always start at some given state.
mikaelmoizt
Posts: 120
Joined: Sat Apr 12, 2014 12:11 pm
Location: Gothenburg, Sweden

Re: Controller Read Issue?

Post by mikaelmoizt »

Code: Select all

GamePadCheck:
      LDA #$01
      STA $4016
      LDA #$00
      STA $4016
ReadControllerBytesLoop:
      PHA
      LDA $4016
      AND #%00000011
      CMP #%00000001
      PLA
      ROR
      DEX
      BNE ReadControllerBytesLoop
      STA gamepad
      RTS
I dont know what is causing your problems, but I got a feeling it has something to to with

Code: Select all

dex
loop and/or

Code: Select all

pha ... pla
in maybe combination with pushing and pulling inside nmi?
I´ve got %01100011 problems but the BITs aint one.
User avatar
Tsutarja
Posts: 123
Joined: Sun Oct 12, 2014 11:06 am
Location: Finland

Re: Controller Read Issue?

Post by Tsutarja »

mikaelmoizt wrote: I dont know what is causing your problems, but I got a feeling it has something to to with

Code: Select all

dex
loop and/or

Code: Select all

pha ... pla
in maybe combination with pushing and pulling inside nmi?
Don't you use PHA and PLA in NMI anyway when you store and restore the values of A, X and Y at the beginning and end of NMI?

One reason could be that (which was already mentioned) is that you are not loading new value to X register before reading the controller. Your controller gets read as many times as the last value loaded to X register is. This can cause too many or too few reads and give incorrect value to your gamepad variable. For an example, if you have #$00 in X when you read controller, it gets read, then X is decremented (X register underflows!), then gets compared. In this case the controller gets read total of 256 times.

Try something like this:

Code: Select all

GamePadCheck:
      LDA #$01
      STA $4016
      LDA #$00
      STA $4016
      LDX #$08                    ; Load #$08 to X to ensure that controller is read 8 times
ReadControllerBytesLoop:
      PHA
      LDA $4016
      AND #%00000011
      CMP #%00000001
      PLA
      ROR
      DEX
      BNE ReadControllerBytesLoop
      STA gamepad
      RTS
UP SIDE DOWN A B A B B A B A Hidari migi
L R L R STOP & DASH & UP & TALK Ijou nashi
JoeGtake2
Posts: 333
Joined: Tue Jul 01, 2014 4:02 pm

Re: Controller Read Issue?

Post by JoeGtake2 »

Hey all - thanks for the responses. Yes, X is set to 8 before jumping to the routine. I tried adding it just before the controller bytes loop just in case to the same ends. It's a gremlin, for sure.

Yes, RAM is cleared at reset prior to turning the NMI on, yet when this routine is called inside the NMI, the problem happens. When I take it out of the NMI and just put it at the top of my game loop, there doesn't seem to be an issue.

Just funky nonsense. I'll keep tracking it down, but it's not a problem that has dramatic urgency. Glad to know I wasn't the only one who ran into it!

Thanks.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: Controller Read Issue?

Post by Kasumi »

If it's not urgent, it's not urgent but without more code or a ROM I can't tell you why moving the joypad read outside the NMI works.

I'd still recommend keeping it outside the NMI since your main loop isn't also in your NMI. (Or, that's the impression I'm getting.) The reason is that you're much less likely to miss button input if your game happens to lag for a frame with it at the start of the main loop. I had written a thing about the why of this and will still post it if you're interested. Boils down to NMI read means the player need only press a button for the input to be missed. Start of main loop means the player must press and release (or release and press) between the two main loops for the input to be missed. (It's tough to press a button for a single 60th of a second, and even if you manage it the input might STILL go through properly.)

For the record, pretty Yoshi's Island suffers from a thing like this. Edit: I'm sure absolutely no one else cares, but apparently this isn't Yoshi's Island I'm thinking of. (Though Yoshi has a different quirk that will cause a missed jump on falling platforms.) I fear now I'll never know what game it actually was.
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Controller Read Issue?

Post by koitsu »

Random question, but is your main code initialising S (e.g. ldx #$ff / txs) to something "reasonable", i.e. somewhere in $01xx that doesn't conflict with local variable usage? Otherwise your push/pulls could be essentially overwriting legit data.
Post Reply