NDX (Nintendulator Debug Extensions)

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Post Reply
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

NDX (Nintendulator Debug Extensions)

Post by thefox »

Download v36 from HERE.
Information down below is partially obsolete, refer to README-NintendulatorDX.txt in the release package instead.


---



Because of new features in CC65 I've been able to add a new feature to Nintendulator's debugger. Now it's possible to view the original source code when debugging if the ROM has been assembled with CC65. I'm not sure how much I'm going to be working on this in the future so I'll just release it now. Here's a screenshot:

Image

This was a quick hack so there probably are some bugs in there. Even in its current state I think it's quite useful though.

How to use

Pass the "--dbgfile foo.nes.dbg" switch to linker to generate the debug file. You'll also need to include the debug information in object files using the "-g" switch when assembling/compiling. The debug file has to have the same name as the iNES rom with ".dbg" extension added, for example "foo.nes.dbg".

NOTE! You need to use the latest snapshot version of CC65 because these features do not exist in the stable version.

For now it only works with iNES roms! Also it will not work if the linker config outputs to more than one file.

How to use the cycle counting timers

Write to $402x to start the timer and $403x to stop it (where x is the timer ID 0-15). $401E/$401F are aliases for $4020/$4030 (for VirtuaNES compatibility). Timer title can be specified with a symbol named "__timerX_title" which points to the zero padded timer title.

Now, one important thing about the timers. If you do STA $4020 followed by STA $4030 it'll report 0 cycles, so the STA cycles don't count. But it also subtracts 4 cycles from all running counters when nested timers are used. For example:

Code: Select all

; this code will report 0 cycles for both timers!
sta $4020
sta $4021
sta $4030
sta $4031
Here are couple of macros for CA65:

Code: Select all

.macro start_timer timer
        sta $4020+timer
.endmacro

.macro stop_timer timer
        sta $4030+timer
.endmacro

.macro timer_title timer, title
    .ident(.sprintf("__timer%d_title", timer)):
        .byte title, 0
.endmacro
How to use debug output feature

This feature allows you to do "printf" style debugging from your applications. It works like this: when the emulator detects a write to $4040, it reads a string from PC+3 and outputs it in the debug window. This feature can thus be used from any assembler. Some simple number formatting is also supported.

Some helper macros for CA65:

Code: Select all

.macro debugOut str
    .local over
    sta $4040
    jmp over
        .byte str, 0
    over:
.endmacro

.define fHex8( addr ) 1, 0, <(addr), >(addr)
.define fDec8( addr ) 1, 1, <(addr), >(addr)
.define fHex16( addr ) 1, 2, <(addr), >(addr)
.define fDec16( addr ) 1, 3, <(addr), >(addr)
Some usage examples:

Code: Select all

.zeropage
  some_var:    .res 2
  other_var:   .res 1

.code
entry:
  lda #$34
  sta some_var
  lda #$12
  sta some_var+1
  debugOut {"entry point reached, some_var = ", fHex16{some_var}, ", isn't that exciting?"}

  lda #123
  sta other_var
  debugOut {"other var is ", fDec8{other_var}, " in decimal"}
Here's a helper macro for C language:

Code: Select all

#define DEBUG_OUT( str )                                                        \
do {                                                                            \
    ( ( void __fastcall__ ( * )( void ) )"\x8D\x40\x40\x60\xEA\xEA" str )();    \
} while ( 0 )
Using it is simple: (NOTE! The parameter has to be a string literal.)

Code: Select all

DEBUG_OUT( "Testing NintendulatorDX debug output from CC65!" );
Unfortunately it's not possible to output the values of variables from C code at this time.

How to use the .proc/.scope profiling feature

This feature allows you to find out how many cycles each .proc/.scope is taking in your program. It works by keeping count of number of cycles taken by each value of the PC register, and writes out the results in a file named "<romname>.nes.profiling.txt" when the ROM is unloaded.

Write to $4041 to start collecting profiling data, and $4042 to stop. You don't have to write to $4042 if you want the data collecting to end when the ROM is unloaded. If you simply want to collect data for the entire run of the program, write to $4041 somewhere in your reset routine.

Currently the feature does NOT support banking, so if you use banked ROMs with it you will get erroneous results.

The results are something like this:

Code: Select all

[module general.o]: 4328012 (91.6 %)
  init: 89352 (2.06 %)
  detectSystem: 60556 (1.4 %)
  initVariables: 44 (0.00102 %)
  reset: 2771377 (64 %)
  setPalette: 24 (0.000555 %)
  updateControllerState: 4903 (0.113 %)
  nmi: 1401756 (32.4 %)
  irq: 0 (0 %)
This tells us that 91.6% of processing time was spent in the module general.o, and out of those 4328012 cycles 1.4% was spent in the routine detectSystem, and so on. In other words, the percentages on the higher levels are always relative to the parent.

Downloads

Emulator + mappers (Unicode, Win2K/XP/Vista/7): http://kkfos.aspekt.fi/downloads/ninten ... x-0.33.zip
I have included a compatible version of the CC65 snapshot in the above package.

That should be all for now.

EDIT: Now supports bankswitching, updated download links.
EDIT: Added the screenshot as an image instead of link
EDIT 2011-01-05: Added some features, updated link to v0.20.
EDIT 2011-02-04: Added a note below CC65 snapshot link
EDIT 2011-02-26: Pulled latest version of Nintendulator from SourceForge SVN and applied the updates, the new version includes timer support, download link updated
EDIT 2011-03-27: Updated to version 0.26, shows init and play cycles for NSF, some bugs fixed
EDIT 2011-07-06: Version 0.27
EDIT 2011-08-03: Version 0.28. Preliminary support for debug messages. Sources added to the package.
EDIT 2011-09-12: Version 0.33. Includes proc/scope profiling support.
EDIT 2012-03-23: Added an example of using the debug output feature from C code.[/size]
Last edited by thefox on Fri Aug 28, 2015 3:47 pm, edited 24 times in total.
User avatar
Gil-Galad
Posts: 321
Joined: Sat Nov 13, 2004 9:43 pm
Location: Ohio, USA
Contact:

Post by Gil-Galad »

Awesome. That really looks like a useful feature. I may try it soon, but not for while since I'm involved in several assembly projects with ASM6. I am interested though.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Post by thefox »

Bankswitching code is now supported. Once again you'll need to update CC65 to the latest snapshot version. Next up is probably some kind of watch window for variables.

I've updated the download links in the first post.
User avatar
neilbaldwin
Posts: 481
Joined: Tue Apr 28, 2009 4:12 am
Contact:

Post by neilbaldwin »

thefox wrote:Bankswitching code is now supported. Once again you'll need to update CC65 to the latest snapshot version. Next up is probably some kind of watch window for variables.

I've updated the download links in the first post.
Heh, I see what you did there.... :)
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Post by thefox »

neilbaldwin wrote:
thefox wrote:Bankswitching code is now supported. Once again you'll need to update CC65 to the latest snapshot version. Next up is probably some kind of watch window for variables.

I've updated the download links in the first post.
Heh, I see what you did there.... :)
I'm not sure I do though. :o

...

Anyways I've added a variable watch feature to this thingaling now. Screenshot:

Image

Still needs some work:
1) reading from memory
2) modifiers for the input string, something like "velocity,word" would instruct it that "velocity" is a pointer to a 16-bit value, or even more complex expression parsing

Downloads will come later. Probably.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Post by thefox »

I worked a little bit on this again. Now the watch list can retrieve and display values from memory. Data size can also be specified (byte/word), e.g. "foo,w" adds a watch on symbol "foo" which points to a 16-bit word. "foo,b" and "foo" are equivalent. Should probably add support for 32-bit and fixed point variables in the future.

Expression parser would be nice.. so you could do stuff like "sprites+20" or "$123+55,w".

EDIT: Forgot to mention, it's also possible to double click on the source listing to set a breakpoint.

Known bugs:
- watch list is not cleared when a new ROM is loaded (need to restart Nintendulator)

Download link for v0.20 is in the first post.

Image
User avatar
neilbaldwin
Posts: 481
Joined: Tue Apr 28, 2009 4:12 am
Contact:

Post by neilbaldwin »

Does this only work with CC65? I mean as opposed to working with CA65?

Probably a dumb question :)
User avatar
Banshaku
Posts: 2417
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Post by Banshaku »

It's good to see that it's moving forward. Hope I can find the time to program on the nes again someday and use it.

If I had time, what I would like to do is instead of adding all the new information inside nintendulator, I would like instead to "attach to the nintendulator process" from a custom IDE. The concept is similar to Visual studio remote debugging. This way, that would remove the clutter of the "one screen debugger" that I don't like. Soon it will become a mess and won't be manageable. Maybe I will have time someday to build that idea. I think that would be the best solution.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

And ideally, an emu supporting remote debugging would support the same protocol as existing remote debug tools, which would let programmers use IDEs that they may already know to debug NES code.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Post by thefox »

neilbaldwin wrote:Does this only work with CC65? I mean as opposed to working with CA65?

Probably a dumb question :)
Works with CA65 (as you can see assembly code listing is displayed in the screenshots). When I'm talking about CC65 I mean the complete package (assembler, linker, archiver etc), not just the C compiler.
Banshaku wrote:It's good to see that it's moving forward. Hope I can find the time to program on the nes again someday and use it.

If I had time, what I would like to do is instead of adding all the new information inside nintendulator, I would like instead to "attach to the nintendulator process" from a custom IDE. The concept is similar to Visual studio remote debugging. This way, that would remove the clutter of the "one screen debugger" that I don't like. Soon it will become a mess and won't be manageable. Maybe I will have time someday to build that idea. I think that would be the best solution.
I agree, that kind of feature would be very nice. Actually it's not the first time that the topic has been brought up in here. But it's a lot of work for (relatively) little gain in functionality.
User avatar
neilbaldwin
Posts: 481
Joined: Tue Apr 28, 2009 4:12 am
Contact:

Post by neilbaldwin »

:) Like I said, probably a dumb question.

OK, next question that isn't a dumb question: can you make Nintendulator support NES2.0 so that you can have ROM/mapper configurations that use >8KB of NVRAM (like SXROM)?

(Though if you're not involved in making Nintendulator then it probably is a dumb question. :) )
User avatar
neilbaldwin
Posts: 481
Joined: Tue Apr 28, 2009 4:12 am
Contact:

Post by neilbaldwin »

Oh and, my build file creates several .o files that are linked together into one ROM. Does that mean this will work with your tool?

Sorry for all the questions: I really like the prospect of this but I really don't have the time to be distracted by it if it's not going to work with my project. That's not your fault, I know :)
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Post by thefox »

neilbaldwin wrote::) Like I said, probably a dumb question.

OK, next question that isn't a dumb question: can you make Nintendulator support NES2.0 so that you can have ROM/mapper configurations that use >8KB of NVRAM (like SXROM)?
I could and might at some point, but it's probably better to e-mail Quietust about it. He's still the sole official developer, I just grabbed the source and hacked away. :)
neilbaldwin wrote:Oh and, my build file creates several .o files that are linked together into one ROM. Does that mean this will work with your tool?
Yeah it will work. What I meant in the first post was that you can't have separate output files like "header.bin" and "code.bin" which are concatenated later. Output must be directly to iNES ROM (code assumes that segment output offsets include the 16 byte header.. this is needed for bankswitching calculations).
Sorry for all the questions: I really like the prospect of this but I really don't have the time to be distracted by it if it's not going to work with my project. That's not your fault, I know :)
Questions are fine. :)
User avatar
neilbaldwin
Posts: 481
Joined: Tue Apr 28, 2009 4:12 am
Contact:

Post by neilbaldwin »

thefox wrote: I could and might at some point, but it's probably better to e-mail Quietust about it. He's still the sole official developer, I just grabbed the source and hacked away. :)
Do you know him? If so, a friendly word would be helpful :)
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Post by thefox »

neilbaldwin wrote:
thefox wrote: I could and might at some point, but it's probably better to e-mail Quietust about it. He's still the sole official developer, I just grabbed the source and hacked away. :)
Do you know him? If so, a friendly word would be helpful :)
Nope, not really.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
Post Reply