Add support for symbol files
I’ve recently come across the C64 Rom repo by @mist64 (Michael, thanks for setting this up), which contains disassemblies of the original C64 ROMs in a format compatible with the cc65 toolchain. Assembling all ROMs was easy, and by adding the --dbgfile option, ld65 generates debug information that includes a symbol section like this:
sym id=0,name="ppach0",addrsize=absolute,size=1,scope=0,def=1472,ref=1018,val=0xE4B6,seg=10,type=lab
sym id=1,name="chke0",addrsize=absolute,size=1,scope=0,def=565,val=0xE45F,seg=10,type=lab
sym id=2,name="initv1",addrsize=absolute,size=3,scope=0,def=3144,ref=4284,val=0xE455,seg=10,type=lab
sym id=3,name="bvtrs",addrsize=absolute,size=12,scope=0,def=2481,ref=756+3144,val=0xE447,seg=10,type=lab
sym id=4,name="words",addrsize=absolute,size=19,scope=0,def=1482,ref=3167+1295,val=0xE460,seg=10,type=lab
sym id=5,name="fremes",addrsize=absolute,size=37,scope=0,def=3204,ref=2207+1546,val=0xE473,seg=10,type=lab
Feature Proposal
Phase 1: Let VirtualC64 parse the symbol section of the .dbg output to enable:
- Symbolic output in the debugger.
- Setting breakpoints using symbol names instead of addresses.
Phase 2: Let VirtualC64 parse the line section to enable:
- Breakpoints to be set via file and line number.
- Preparation for supporting a DAP (Debug Adapter Protocol) interface in the future.
I have already experimented with implementing a DAP adapter for VirtualC64, which proved quite challenging (to put it nicely). There is currently no VSC client that works out of the box, and supporting it would require me to write a significant amount of JavaScript code, which is something I prefer not to do. That said, enabling VirtualC64 to communicate via DAP with a frontend would be very valuable. I am eager to provide a DAP adapter in the future once the client side supports easy integration.
The disassembler now supports resolving symbols from the LD64 linker. It’s not production-ready yet, since symbol lookup is still O(n) etc.
All RetroShell commands taking an address as argument now resolve symbols (as long as they call the proper function parseAddr, which all commands do that I've been testing):
u16
Console::parseAddr(const string &argv, long fallback) const
{
if (auto resolved = cpu.symbolTable.symbols.seek(argv); resolved) {
return resolved->val;
}
return (u16)parseNum(argv, fallback);
}