Programming troubleshooting tips and tricks

FrankenGraphics

New member
Many bugs are edge cases
Some value is ff when it should be 00. Some value is 00 when it should be 01. Look out for buggy values at the wrap-around seam. Edit: or any other edge, such as triggering N flag.

Almost every other bug is a faulty conditional
BNE? Maybe it should've been BEQ. This is easy to mess up, since the logic may appear as "reverse" to human thinking. We tend to think: If the right condition is, let's do this. The CPU thinks: If this condition is met, jump past doing that next thing.
BCC? Did you check whether carry flag is absolutely known at that point? If not, better set or clear that flag first!

Typos and faulty instructions will assemble (and produce hard-to-detect bugs)
A thing to watch out for. If you make a typo or or type in some instruction that might exist on some other processor but not the 6502, a design decision in asm6 will treat that typo as a label. Labels don't do anything in themselves. They're not instructions, nor data. Once the code is assembled, they don't exist in your program binary. They're just something for instructions to point to that looks human-friendly, and un-pointed-to labels are not cause for a warning in asm6 either. That unfortunately also means it will happily assemble your game even though another assembler might've thrown you a warning or error for your convenience. If something you wrote seems buggy, watch out for typos and be careful that all your instructions really are part of the 6502 instruction set.
An example of this type of problem can be found in this thread.

Other generous bug sources:
-If you wrote some variable and don't get the expected result later when reading it, chances are some other piece of code wrote to that variable in-between.
-With only so few quick registers (accumulator, x, y, status flags; especially zero flag, negative flag and carry flag) to juggle things, it's all too easy to overwrite some temporary value held there that you might need for later. When calling subroutines or laying down marcros, always try to check whether that subroutine or macro will clobber data held in your registers). Since nesmaker is rich in routines and macros that come ready-baked and you might've not looked that close on every one of them, this may be an extra important potential source of bugs to look for when writing your own additions to the library.

Happy coding!
 

dale_coop

Moderator
Staff member
Exactly! A lot of issues/bugs in NESMaker are typos and it's a pain in the a** to find it to fix it.
But some would say it's a good practice, an opportunity to learn the code engine >_<
 

FrankenGraphics

New member
oh for the record i meant programming 6502 aseembly in general (and with special regards to asm6 in the case of typos), not the NESmaker codebase in particular. Hiding code in macros this much is a double edged sword though (in-text-editor code-folding wouldn't have as much of a transparency problem). So to avoid register overwriting bugs, you ideally want to start each macro or subroutine with a ;commented description of what input it expects, what it'll output, and what registers it'll affect. Whenever used/called, keep a single line comment at that same place of calling with a shortlist of registers it'll affect without restoring. That helps bring a lot of clarity, but it's also a lot of work.

One funny thing i found in the nesmaker codebase though is that the serial-to-parallel conversion of the controller input is reversed order to what i'd expect. Not that it matters as-is, but replacing the input reading scheme with something more textbook means you would need to remap subsequent input associated code as well.
 
Top Bottom