As part of my contribution to the cc65 development for the atari 8bit community,
i've decided to write a short tutorial that might help you guys if you wish to debug your code via altirra.
I have been strugling with this for a while now and it is still yet to be perfect (not as easy as debugging code in other environemtns such as visual studio) but it is definately a good starting point.
Compiler flags - add 'debug info'
If you wish to debug your cc65 code, you first need to add 'debug info' to your compiled object.
To add debug mode you need to add the following flags to the compiler:
cl65 --debug-info -Wl --dbgfile,"myapp.dbg" -t atari main.c -o myapp.xex -C myapp.cfg -l myapp.lst -Ln myapp.lbl
To learn about command lines you can use this reference: https://www.cc65.org/doc/cc65-2.html or yoו can use the --help argument in the cl65 command line.
What is relevant for this discussion is the debug info parameters in the command line above.
Let's review and explain what they do:
--debug-info : Add debug info to object file (could use also -g option) -Wl : Pass options to the linker --dbgfile,"myapp.dbg" : produce debug info file named myapp.dbg
The above will create a debug info file and will include debug info in the compiled object.
Altirra debug functions
Now that your binary file object is ready and also include debug info, the next step is to run your xex file with altirra.
here are the main functionalities you need to know for debugging in Altirra:
F8 - press this will enalbe the debugger. pressing this again will let the app continue running with no debuggin F9 - pause the emulator. this can help tracking a specific occurred issue. (F9 within disassembly window or c code window) - is used to toggle breakpoints F11 - step into a routine. this option will step into your routine and debug the code of that routine F10 - step over a routine. this option will step over your routine and move to the next command after the call to that routine
Debugging the C code
when your code runs and you wish to debug it, you press F8.
Altirra then changes its user inteface to be set in debugging mode.
on the right hand side you should see 4 tabs: disassembly, Registers, Call Stack, Memory1
if you don't see these windows or you see only some of them, you can bring them on to screen by selectng
'Debug--Window' from the menu.
Disassembly - you can explore your code in machine and assembly launguages. you have search option on the top where you can insert a memory address to view or a name of a routine to view. the name is the disaseembly name of that routine.
for example, if your code has a routine called 'void draw_screen(void)' , then to find it in the disassembly window you can search for '_draw_screen' search string. just add '_' as a prefix.
Registers - you can view all register values under this screen and also where the program counter is (would be a hex value).
Call Stack - display a stack of your program routines call as they are being called in your app. the routines are presented as a memory address location, so if you wish to know what routine is that, just search it in the disassembly window.
Memory - can be 4 memory windows to view in parallel. in the default case you bring on to screen memory1. this is the memory layout and what it holds in the current debug status. you have a search text box to search a memory location. this is powerful tool to view memory location values and see if anything is at the order.
Viewing your C code
everything so far was either machine language or assembly. to view your c code, go to the 'disassembly' window point your mouse on the assembly code you wish to view as C code. For example, if you found a routine in the disassembly window called '_draw_screen' , right click on the routine and choose 'Go to source'. you will see a new window is opened with your c code.
If you wish the app to debug-break at a certain point of your routine, you can set up a break point. to do that you right click on the c source code and choose 'Toggle breakpoint'. for example, if you wish to break at the beging of the routine 'draw_screen' then you right click the first command on that routine and choose 'Toggle breakpoint'. to remove the breakpoint just choose the option 'Toggle breakpoint' on that line of code again. it will clear the break point.
Run till breakpoint
By pressing F8 your app continues to run until it reaches to the breakpoint set place.
once you have breaked in the desired line, you can use the step into(F11) , step over(F10) functions to debug your code line by line.
Console is the bottom window in the debug mode of altirra. if you don't see it you can bring it on by selecting 'debug--window--console'. in every step of your debug you see an output line in the console.
in that line you can see all the registers and their values, and also the current machine lagunage and assembly command that is being debugged. you can see the same thing at the disassembly window.
an example of a console output line:
Breakpoint 0 hit (104: 2, 2) A=20 X=50 Y=00 S=F5 P=33 ( ZC) 4700: A0 01 LDY #$01
104 - # of frame being drawn
2,2 - first 2 is the vertical line # within the frame , the second 2 is the horizontal position within the current scanline
A,X,Y - are accumulator, X and Y registers
S - The Stack register
P - The status register,
ZC - zero carry
4700: A0 01 - current program counter and machine language for LDY#$01
LDY #$01 - assembly command being executed
the same way your routines have prefix '_' , your variables also have prefix '_' in their disassembly presentation.
In order to watch your variables value, you can use write in the console few commands that will show your variables values on screen.
if you type in the command line:
wb <_your variable name> (note the prefix '_')
it will add your variables to the watch list and then you will start see it on your app screen.
wb - watch byte
ww - watch word
wc - watch clear (to remove a watch)
For example, if your c code declares:
unsigned char count;
Then to watch the value of count you will use wb _count in the console command prompt as char is byte long.
If your c code declares:
unsigned long scr_mem_addr;
Then to watch the value of count you will use ww _count in the console command prompt as long is byte word byte long.
after these command prompt the console will result with:
Watch entry 0 set.
Where 0 is the number of current variables being watched on screen.
the value doesn't appear on screen right away you need first to let the program continue running (F8) then break again to see the value appearing on screen.
To clear a variable from watch just type in:
wc <_variable name>
you can also bring on the watch window (debug--window--watch) and type a variable name to watch (again with prefix '_') but in this window you will only see the memory address of that variable, so in order to see what the value it holds you will need to type in the memory address in the memory window
Print variables value
you can use Altirra commands to print system variables. you simple use the .printf command as in the following example:
.printf "%02X" db(VCOUNT)
This will print to console the current vcount number (where the scanline is currently is). you can use your variables as well just remember to add the prefix '_'
Alttira debugger commands
Here is a list of all altirra debugger commands:
Altirra> .help ` Bypass aliases ? Evaluate expression a Assemble a8 Set Atari800-compatible command aliases ac Clear all command aliases al List command aliases as Set or unset command alias ap Add command alias pattern ba Break on memory access bc Clear breakpoint(s) bl List breakpoints bp Set breakpoint bt Set breakpoint with trace (tracepoint) bx Break on expression (conditional breakpoint) bs Break on disk sector da Display ATASCII string db Display bytes dbi Display bytes w/ INTERNAL dump dd Display double words df Display decimal float di Display INTERNAL string dw Display words dy Display binary e Enter (alter) data in memory f Fill memory fbx Fill bytes with expression g Go gf Go until frame end gr Go until return (step out) gs Go until scanline gt Go with tracing enabled h Show CPU history hma Show heat map accesses hmc Clear heat map hmd Dump heat map memory status hme Enable or disable heat map hmr Show heat map register status k Show call stack lfd Disable logging channel lfe Enable logging channel lfl List logging filter settings lft Enable logging channel with tagging lm List modules ln List nearest symbol m Move memory o Step over r Registers s Search memory st Static trace t Trace (step one instruction) (F11) u Unassemble vta Verifier target add vtc Verifier target clear vtl Verifier target list vtr Verifier target reset wb Watch byte wc Watch clear wl Watch list ww Watch word wx Watch expression x Examine symbols ya Add manual symbol yc Clear manual symbols yd Delete manual symbol yr Read manual symbol table yw Write manual symbol table .antic Display ANTIC status .bank Show memory bank state .base Set numeric parsing base .basic Dump BASIC table pointers .basic_dumpline Dump BASIC program line .basic_dumpstack Dump BASIC runtime stack .basic_rebuildvnt Rebuild BASIC variable name table .basic_save Save BASIC program .basic_vars Dump BASIC variables .batch Run debugger batch script .beam Show ANTIC scan position .caslogdata Toggle verbose cassette data read logging .ciodevs Dump Central Input/Output (CIO) device list .covox Dump Covox sound extension status .diskdumpsec Dump floppy disk sector data .diskorder Set forced phantom sector ordering .diskreadsec Read sector from floppy disk .disktrack Show sector order within track .diskwritesec Read sector from floppy disk .dlhistory Show ANTIC display list execution history .ds1305 Show DS1305 real-time clock status .dma Show current ANTIC DMA pattern .dmabuf Show ANTIC DMA line buffer .dmamap Show ANTIC DMA activity map .dumpdlist Dump ANTIC display list .dumpdsm Dump disassembly to file .dumpsnap Create bootable snapshot image .echo Display message to console .gtia Display GTIA status .ide Display IDE emulator status .ide_dumpsec Dump IDE raw sector .ide_rdsec Read IDE sector into memory .ide_wrsec Write IDE sector from memory .iocb Display CIO I/O control blocks .loadksym Load kernel symbols .loadobj Load executable object .loadsym Load module symbols .map Show memory map layers .netstat Display network connection status .onexeclear Clear queued on-executable commands .onexelist List queued on-executable commands .onexeload Queue command on executable load .onexerun Queue command on executable run .pathdump Dump disassembly of recorded paths to a file .pathrecord Show or change path recording setting .pathreset Clear recorded paths .pathbreak Toggle break on new path .pbi Display Parallel Bus Interface (PBI) status .pclink Display PCLink status .pia Display Peripheral Interface Adapter (PIA) status .pokey Display POKEY status .printf Display message with formatted fields .readmem Read memory from disk .reload Reload symbol files .restart Restart emulated system .sdx_loadsyms Load SpartaDOS X symbols .sio Dump SIO device control block (DCB) .sourcemode Switch between source and disassembly level debugging .sprintf Construct message with formatted fields .sum Compute sum of memory range .tape Display cassette tape deck status .tapedata Display cassette tape data .tracecio Toggle CIO call tracing .traceser Toggle serial I/O port tracing .ultimate Dump Ultimate1MB status .unloadsym Unload module symbols .vbxe Display VBXE status .vbxe_bl Display VBXE blit list (BL) .vbxe_xdl Display VBXE extended display list (XDL) .vbxe_traceblits Toggle VBXE blit tracing .vectors Display kernel vectors .warmreset Warm reset simulation .writemem Write memory to disk Some commands support extended memory syntax: $0000 CPU view of primary memory $01:0000 CPU view, 65C816 high memory n:$0000 ANTIC view of primary memory v:$00000 VBXE memory r:$0000 Main memory x:$00000 Extended memory Some commands support length syntax: db siov L100 db 4000 L>5FFF Use .help <command> for detailed help on that command.
I think these are enough to start with. hope it would be helpful to some of you. any questions, comments, notes, additional info that i can add to this tutorial, don't hesitate and let me know
EDIT: i've updated few things, and added the list of debugger commands
Edited by Yaron Nir, Wed May 15, 2019 9:41 AM.