CA65: generating debug labels for multiple banks (fceux .nl)

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
nesrocks
Posts: 563
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

CA65: generating debug labels for multiple banks (fceux .nl)

Post by nesrocks »

I have been trying to get ca65 to generate labels that are compatible with multiple banks for use with fceux's debugger, but I don't know how to get it to export the gamename.labels.txt file with bank information on each line.

The best way I got was to edit the example_fceux_symbols.py script made by I forgot who (dougeff perhaps?) rainwarrior (thanks!) so it would at least sort the labels that have prefixes to them. For example, every bank 5 label must start with "bk5_" prefix, then it will go to the .5.nl file. All labels with no prefixes go to bank 0 by default (0x0000 - 0x7FF ones go to .ram.nl).

Is there another way to do this?

Code: Select all

#############################################################
# CA65 labels.txt to fceux's .nl files converter script
# Original script by rainwarrior.
# Edited for multiple banks compatibility by Nesrocks 2018
# Visit nesrocks.com
# version 1.3
#############################################################


# All labels that have a bk<number>_ prefix will go to the appropriate file.
# For example "bk7_reset_handler:" will go to the gamename.nes.7.nl file.
#
# Labels that have no prefix in this format and have address 0x8000+ will go to bank 0 file
# and may be randomly overwritten if the memory address is the same.
# Ram and zeropage labels do not need prefixes, they are sorted by the address.
# 
# Warning: this script will delete .nl files with the same rom name that weren't freshly created.
# Script best used in a batch sequence on game compile.
#
# Original folder structure:
# compile.bat
# src/main.asm
# src/system/example_fceux_symbols.py 
# 
# batch command calling this script:
# cd src
# system\example_fceux_symbols.py
#
# You may need to edit this script to adjust for paths in your project folder structure.


#################
# User parameters
#################

banks = 8 # Set your bank count here. i.e: 8 = banks 0-7. If set to 2 it will go into "old" mode and generate files based on addresses only (ram.nl, 0.nl and 1.nl)
trim_prefix = 1 # 0-1. Option to remove the label prefixes on the converted debug file. can help readability on fceux's debugger.
romname = "gamename" # Write your ROM name here, minus .nes extension. No special characters.

#################
# User params end
#################

import sys
import os
assert sys.version_info[0] >= 3, "Python 3 required."

from collections import OrderedDict


def label_to_nl(label_file):
    rawlabels = []

    try:
        of = open(label_file, "rt")
        rawlabels = of.readlines()
    except IOError:
        print("skipped: "+label_file)
        return

    labels = [] # a list of lists. finally will contain a list of labels for each bank. will overwrite labels with same address on the same bank
    ramlabels = [] # zeropage and ram labels go here
    ramstrout = ""
    str_outs = []
    nl_files = []
    prefixes = []

    for bank in range(banks):
        str_outs.append("")
        nl_files.append("..\\" + romname + ".nes." + str(bank) + ".nl")
        prefixes.append("bk" + str(bank) + "_")
        labels.append([])

    # read the raw labels string and populate the labels list of lists
    for line in rawlabels:

        # get a list of words, splitting on spaces
        words = line.split()

        if (words[0] == "al"):
            address = int(words[1], 16) # the memory address
            label = words[2] # the actual symbol
            label = label.lstrip('.') # remove everything to the left of ".", including it

            if (label[0] == '_' and label[1] == '_'): # if the first and second letters of the symbol are _ _
                continue # skip compiler internals


            hasbank = 0 # flag to know if the label on this line has a prefix. if it doesn't, throw it into bank 0

            if (address >= 0x0000 and address <= 0x7FF):
                ramlabels.append(label)
                ramstrout += ("$%04X#%s#\n" % (address, label))

            else:
                for bank in range(banks):
                    if label.startswith(prefixes[bank]):
                        if trim_prefix:
                            label = label[4:]
                        labels[bank].append(label)
                        str_outs[bank] += ("$%04X#%s#\n" % (address, label))
                        hasbank = 1 # set the flag so it skips the next part

                # no prefix detected flag
                if hasbank == 0:
                    # throw into bank 0 if generic amount of banks or if address is bank 0
                    if banks != 2 or (address >= 0x8000 and address <= 0xBFFF):
                        labels[0].append(label)
                        str_outs[0] += ("$%04X#%s#\n" % (address, label))
                    # address must be bank 1
                    elif (address >= 0xC000 and address <= 0xFFFF):
                        labels[1].append(label)
                        str_outs[1] += ("$%04X#%s#\n" % (address, label))

    # write each file that isn't empty
    for bank in range(banks):
        if str_outs[bank] != "":
            open(nl_files[bank], "wt").write(str_outs[bank])
            print("debug symbols: " + nl_files[bank])

        # delete old nl files if they exist
        elif os.path.isfile(nl_files[bank]):
            os.remove(nl_files[bank])

    if ramlabels != "":
        open("..\\" + romname + ".nes.ram.nl", "wt").write(ramstrout)
        print("debug symbols: " + "..\\" + romname + ".nes.ram.nl")


if __name__ == "__main__":
    label_to_nl("..\\" + romname + ".labels.txt")
Last edited by nesrocks on Thu Oct 11, 2018 6:13 am, edited 12 times in total.
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!
https://www.patreon.com/bitinkstudios <- Support me on Patreon!
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: CA65: generating debug labels for multiple banks (fceux

Post by rainwarrior »

I think the script is mine.

I think a better way is probably to parse the debug file instead of an nl file. With that you can get a list of segments/etc. and you could sort out the banks with that.

The example I gave doesn't deal with banks. With Lizard I had 32k banking, so it seemed okay just to split up each bank into a separate link (keeps the symbols separated, neatly deals with the issue of duplicate code conflicts due to there being no fixed bank, etc.). With a fixed bank I'd probably want to do them in one big build instead, and for that I'd need to parse segments.
User avatar
nesrocks
Posts: 563
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

Re: CA65: generating debug labels for multiple banks (fceux

Post by nesrocks »

Thanks for the original script! It's a godsend :)

Oh for some reason I had in my mind that the dbg file was binary compressed, not plain text. Interesting! Will look into that.
I also noticed that I destroyed the .ram file creation, so ranges 0x000 - 0x7FF are going to .0.nl which is no good. I'll udpate that before going the debug file route.
edit: post updated with proper .ram file sorting
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!
https://www.patreon.com/bitinkstudios <- Support me on Patreon!
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: CA65: generating debug labels for multiple banks (fceux

Post by thefox »

If you speak C, there's an "official" library for parsing the debug files at https://github.com/cc65/cc65/tree/master/src/dbginfo
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
nesrocks
Posts: 563
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

Re: CA65: generating debug labels for multiple banks (fceux

Post by nesrocks »

That sounds like it would be very useful. I skimmed through the three files and I have no idea what to do with them or how to use them. I'm not versed in C at all.
I had never used python before, so for this purpose I guess I'll just try to parse the debug file using python for now, since I managed to get something done.

edit: updated the original post to add the ability to use old style bank assigning by address instead of prefixes. Just set banks to 2.
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!
https://www.patreon.com/bitinkstudios <- Support me on Patreon!
Post Reply