I'm starting to learn 6502 assembly for a potential NES game project on my off time, and I'm having some trouble setting up the reading of controller input. My background is in C, so I'm familiar with memory and how it works, but the flow control in assembly still escapes me.
Because I'm new, I figured I should start easy and use the button-by-button method described in https://www.vbforums.com/showthread.php?858965-NES-6502-Programming-Tutorial-Part-5-Controller-Commands . This works fine, but it is really repetitive and wordy.
Is there a more elegant way of doing this that isn't completely above my abilities? I don't know enough to integrate code from other sources without some help.
https://wiki.nesdev.com/w/index.php/Controller_reading_code looks promising, but I don't really understand enough of it to use it.
Thank you for your time.
Controllers on the NES are serial devices, each containing an internal shift register. To read the controllers:
Inputs are returned in the order A, B, Select, Start, Up, Down, Left, Right.
So, the first part of that contract can't really be neatened much. You're unavoidably going to see something like:
Assuming you're interested in all eight inputs, and only controller 1 for the sake of example, there's then definitely going to be at least eight reads from $4016. Since it is also the strobe for resetting what's in the shift register, they had better be reads only — no writes or read-modify-writes.
Also it is unfortunately not true that bits 1 to 7 are 0. So e.g. you can't just
ORA
from $4016 and get results a bit at a time. And none of the unofficial opcodes seem that useful in doing a convenient load-and-AND in this situation.So if you wanted to accumulate the results into A then things aren't going to get that elegant.
Of the links you provide:
The vbforums.com suggestion is to load from $4016 eight times, test the lowest bit each time, and react appropriately in that loop. It uses
AND #1
(to set Z) andBEQ
(to test it) to test the bit after loading, whereasLSR
(to move bit 0 into carry) andBCC
(to test carry) would probably me more elegant in the sense that it's a little more compact.The NesDev Wiki link instead rolls each single bit of joypad input through carry and into another byte, so you end up with an 8-bit value in memory that is equal to what was once in the controller's shift register, and you can test and manipulate that at your leisure.
If your concern is simply 'repetitive and wordy' then I think the problem might be your tools, not the hardware — look for a macro assembler. Many of them are a step or two above C's preprocessor, so you might end up being to code the same sequence of steps as something more like:
That's the macro syntax used by a particular real-life assembler for the BBC Micro, and almost certainly not the macro syntax your assembler uses because there's very little standardisation. But there'll be a good macro compiler for the NES, and the job of a macro compiler is to allow you to spell out repetitive parts without copying and pasting.