Finding things in NES Maker and Debugging

Kasumi

New member
NES Maker puts together code and data to be made into a ROM. But it is ASM6 that actually makes the ROM.

Inside your GameEngineData folder is a file called demo.txt. (Assuming you haven't done anything that would change this.) When you build your game, asm6 creates this file as well as game.nes (your actual game). So just what is demo.txt?

Basically everything in your ROM, in one file. Suppose you don't know where NES Maker's palette loading code is. You could open Routines, and Basic, and System, and then realize it's actually in Routines, Basic, DataLoadScripts...

Or you could open demo.txt, which includes all the text in all the files included anywhere, that were used to build your ROM. If you open demo.txt in a text editor, and search it (ctrl+F allows you to start a search in most text editors) you can find things much more quickly without having to browse through all the folders and files. Have you ever seen a variable used someplace, and wonder how it was set up? If you search for its name in demo.txt, you can find every use of it, period.

But that's not all! In addition to having all the code together in one easy to access file, demo.txt also shows exactly where in memory all that code/data will end up. It shows which variables occupy which parts of RAM. This is a tremendous help in debugging one's game. Let's check out some things we can look at.

Grab Mesen if you don't have it: https://www.mesen.ca/

It allows you to look at all kinds of stuff while a game is running. Open your ROM with it. Go to Tools, Debugger. A debugger window will pop up. On it, go to Tools, Memory Tools. This will open up a way to view various values in NES Memory. Usually you want the view dropdown to be on CPU Memory.

All of these values are everything the NES CPU can see at the current point in time. All the ROM it can see, and all the RAM it can see. Open demo.txt and search for gamepad. You'll encounter a line like this:
Code:
00066                           gamepad .dsb 1
This mean the gamepad variable is at $0066 in memory. (The number won't necessarily be 66, depending on the changes you make. But whatever it is is where it will be in NES Memory.)

Go back to Mesen's Memory viewer. Look for $0066 (or whatever value it was). As you press buttons on the gamepad, you will see this value change:
b4K6qQa.gif


Mesen also lets you check out how code is manipulating memory. Go back to the debugger window. in the bottom middle, you'll see "breakpoints". A breakpoint is a condition that, when true, will cause Mesen to pause emulator so you can see EXACTLY what is happening at that point in time.

Right click there, and select, add...

A window will pop up.
NBfkhLK.gif

There is an address (Specific) field. Type $0066 there. This means Mesen will pause when the things you have selected happen with address $0066. How do you select which things you care about? Above that is "Break on:". Whichever boxes are checked are the things Mesen will watch to trigger a breakpoint.

Breaking on Execution means "Stopping when the CPU is running actual code at the address." Since $0066 is RAM, the CPU is unlikely to run it as code. Uncheck that.

Breaking on Write means "Stopping when the CPU is going to store a new value at that address." Check this.

Breaking on Read means "Stopping when the CPU is loading the value stored at this address."
Uncheck this.

NkpxBco.png


(For use outside this tutorial, if multiple boxes are checked, it will stop if any one of those things happens.)

Click okay. Execution of the game will probably stop immediately because the game is writing to the gamepad variable every frame! (Just in case it doesn't stop in the right place, go to Debug, continue in the debugger)

You'll see something a bit like this in the code debugger on the left side of the debugger window:
vwHWuCw.png

The highlighted yellow line is the NEXT thing the CPU will do. Debug, step into will run that line.

But, ignoring that for now. Search for the highlighted address in demo.txt. (In the image above, it's C755, but it will probably be different for you.)

And what do you know? Here's the joypad code:
Code:
0C74A A9 80                     	LDA #$80
0C74C 85 66                     	STA gamepad
0C74E                           	
0C74E                           ReadControllerBytesLoop:
0C74E AD 16 40                  	LDA $4016
0C751 29 03                     	AND #%00000011
0C753 C9 01                     	CMP #%00000001
0C755 66 66                     	ROR gamepad
0C757 90 F5                     	BCC ReadControllerBytesLoop
0C759 60                        	RTS
0C75A A5 66                     	LDA gamepad
0C75C 29 C0                     	AND #%11000000
0C75E C9 C0                     	CMP #%11000000
0C760 D0 04                     	BNE NoFilter_LR

On the left is the address where it is in memory. To the right of that are the bytes that make up the instruction.

So say you were editing a file, and wanted to execute it instruction by instruction to see what it's doing. You'd look up the label in demo.txt. Say for instance you had just added code under the "dontSkipNMI" label. Search for dontSkipNMI in demo.txt. You might find something like this:
Code:
0C3A9 A5 E7                     	LDA doNMI
0C3AB F0 03                     	BEQ dontSkipNMI
0C3AD 4C EE C5                  	JMP skipWholeNMI
0C3B0                           dontSkipNMI:
0C3B0 A9 FF                     	lda #$FF;WHEEE I JUST ADDED THIS CODE
0C3B2                           	
0C3B2 A9 01                     	LDA #$01
0C3B4 85 E7                     	STA doNMI
So dontSkipNMI is at $C3B0 in memory here. In Mesen, I can delete the old breakpoint for gamepad by right clicking on it and selecting delete (or that will keep triggering).

Now I can right click and add a new breakpoint. I will check execution, and type C3B0 as the address.

And when I click okay, Mesen will pause if the CPU ever starts running code at that label. (Note: If the CPU is paused from an old breakpoint, you may have to go to Debug, Continue to resume execution normally until the next breakpoint.)
1WTroyo.gif

Also notice at the top middle of the debugger window "CPU Status". This is the current value in A, X, and Y. As well as the process status flags. Note that it breaks on the instruction I added ("WHEEE I JUST ADDED THIS CODE"). It shows A as zero before that instruction runs. But if I run that instruction, A becomes $FF, exactly as one would expect. The debugger also shows a lot of the other state of the CPU and PPU at the exact in time that the break happened.

You can use this debugger to follow whatever code you want instruction by instruction to make sure it's really doing what you expect. There are some caveats here. It's technically possible for two things to share the same address, so it's not necessarily a guarantee the breakpoints for execution will always work out the way you expect. (NES can only see 32KB of ROM at a time, and NES Maker ROMS are 512KB. The game swaps different portions of the 512 KB into the 32KB, but the debugger can only break on addresses in the 32KB... And granted, that may be confusing, but a separate guide on bank switching and memory management would probably be needed.)

But even if you're not much for scripting, hopefully this has still been an interesting read and it will help you find things within demo.txt.

There are lots of other cool tools as well. Tools, PPU Viewer will show all graphical things as NES sees them. This can be particularly fun to look at games in. It may give you some ideas of how certain effects were done! But no specific tutorial for that, it's much more straightforward.
 

dale_coop

Moderator
Staff member
Thank you kasumi. I love that type of post... Very instructive, demonstrative...
I always wanted to know how to do that (but never had the time to test, search... now, I am at work, reading this post. Yeah, it's perfectly clear. Will try that tonight)
And maybe need to take a look at jorotroid script too "Mesen Label Extractor: This should make debugging easier": http://nesmakers.com/viewtopic.php?f=3&t=1193
 

FrankenGraphics

New member
I'd also recommend windows users to download a third party tool that can search for strings within text files. It saves me a *lot* of time to be able to locate what files (and what rows within those files) that contain a call to a function, for example, in a project as nested as the NESmaker engine.

You can change your windows settings to allow this search behaviour, but it's off by default for the reason that letting you text search through your entire drive is slow. Changing the setting requires a rebuild of windows' search index, which is why you can't do it as a search option on the fly.

I use FileSeek Pro Trial. It's shareware, but the trial mode doesn't limit you in any way that matters.
 
Thanks for sharing this Kasumi!

I have been using this debugging method ever since you showed me. Its incredibly helpful.

If I may add some things from experimenting with the debugger:
Some of you may be discouraged because Mesen doesn't have your labels for branching or variable names, just the memory addresses.
That is pretty easy to fix, without running any external tools.
Use Kasumi's method to find the spot in code you are debugging and compare it to your code. You only need to find it one time. If you right click the specific memory addresses that you are watching, you can assign them a label name. It then reloads the code with your label replacing the memory address.

Just be careful of what Kasumi mentioned. If the code switches to a different bank there is no guarantee that label is accurate anymore.
 

Mugi

Member
chronicleroflegends said:
Use Kasumi's method to find the spot in code you are debugging and compare it to your code. You only need to find it one time. If you right click the specific memory addresses that you are watching, you can assign them a label name. It then reloads the code with your label replacing the memory address.


alternatively, just use this: http://nesmakers.com/viewtopic.php?f=3&t=1193

:p
 

Kasumi

New member
You can also use the official Mesen sanctioned way: https://www.mesen.ca/docs/debugging/debuggerintegration.html#asm6f

It's still worth it to understand where the values come from, though.
 

Mugi

Member
definitely.

I've got a hefty pile of experience debugging things on more "complicated" systems but never really did much with the NES so it's all learning for me too at this point.
always nice to see things from people who actually did this stuff properly :p
 

dale_coop

Moderator
Staff member
Thanks kasumi!
With your illustred explanations. I did with success debug my game yesterday. Everyday learning something new with you guys.

(Like Mugi, I use debugger on more modern languages everyday at my job... but never understood how to do it for nes dev :p
(Like I never understood ASM before NESMaker)
 

puppydrum64

Active member
This was actually very helpful! The only thing is I find the debugger incredibly difficult to use because it forcibly pauses the game, meaning that I cannot use it to track how values change while I play.
 
Top Bottom