Yaron Nir Posted May 15, 2019 Share Posted May 15, 2019 (edited) Hi All, 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. Toggle breakpoints 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 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 Where: 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 Variables Watch 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 '_' Dump the display list To print the current screen display list use the following example: .dumpdlist The result will be the display list byte array including its memory addresses: 2000: x4 blank 8 2004: mode.i.h 4 @ 480B 2007: mode.i.h 4 @ 490B 200A: mode.i.h 4 @ 4A0B 200D: mode.i.h 4 @ 4B0B 2010: mode.i.h 4 @ 4C0B 2013: mode.i.h 4 @ 4D0B 2016: mode.i.h 4 @ 4E0B 2019: mode.i.h 4 @ 4F0B 201C: mode.i.h 4 @ 500B 201F: mode.i.h 4 @ 510B 2022: mode.i.h 4 @ 520B 2025: mode.i.h 4 @ 530B 2028: mode.i.h 4 @ 540B 202B: mode.i.h 4 @ 550B 202E: mode.i.h 4 @ 560B 2031: mode.i.h 4 @ 570B 2034: mode.i.h 4 @ 580B 2037: mode.i.h 4 @ 590B 203A: mode.i.h 4 @ 5A0B 203D: mode.i.h 4 @ 5B0B 2040: mode.i.h 4 @ 5C0B 2043: mode.i.h 4 @ 5D0B 2046: mode.i.h 4 @ 5E0B 2049: mode.i.h 4 @ 5F0B 204C: waitvbl 200B 2000-204c - the memory address of the display list x4 - the number of times the line appears on the screen (in this example 4 time) blank 8 - a blank line 8 scanlines mode.i.h 4 - ANTIC mode 4 + DLI interrupt flag + Horizontal scroll flag 480B - 5F0B - the address of the screen memory waitvbl 200B - jumps back to the begining of the display list after VBLANK note - this was taken after several screen horizontal scrolls has occurred, that is why the memory addresses doesn't look aligned. Print GTIA To print the current GTIA status use the following example: .gtia The resut will specify the current GTIA status which mosly includes player missile graphics status: Altirra> .gtia Player 0: color = 00, pos = 00, size=0, data = 00 Player 1: color = 00, pos = 00, size=0, data = 00 Player 2: color = 00, pos = 00, size=0, data = 00 Player 3: color = 00, pos = 00, size=0, data = 00 Missile 0: color = 00, pos = 00, size=0, data = 00 Missile 1: color = 00, pos = 00, size=0, data = 00 Missile 2: color = 00, pos = 00, size=0, data = 00 Missile 3: color = 00, pos = 00, size=0, data = 00 Playfield colors: 06 | 86 0c 72 00 PRIOR: 00 (pri= 0 , normal) VDELAY: 00 GRACTL: 00 CONSOL: 08 set <-> 0f input, speaker M0PF: M1PF: M2PF: M3PF: P0PF: P1PF: P2PF: P3PF: M0PL: M1PL: M2PL: M3PL: P0PL: P1PL: P2PL: P3PL: You can see in the result above the information about all 4 players and missiles, their priority, and the collision between them and the playfield. Print ANTIC To print the current ANTIC status use the following example: .antic The resut will specify the current ANTIC status, which include information about display list, pmg address, character set address, dli Altirra> .antic DMACTL = 22 : normal 2-line dlist CHACTL = 02 : invert DLIST = 2000 HSCROL = 0c VSCROL = 00 PMBASE = 00 CHBASE = e0 NMIEN = c0 : dli vbi NMIST = 1f : PENH/V = 00 ff Go until scanline The ability to run the debugger until it reaches a certain scanline. to use that use the following example: gs 100 the result will be the same breakpoint result you always get when your code breaks on a toggled breakpoint: Altirra> gs 100 Scanline breakpoint reached. ( 64:100, 0) A=37 X=20 Y=50 S=F5 P=33 ( ZC) 8188: F0 FC BEQ L0026 you can see the same information as we explored before. 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 Cheers, Yaron Edited June 27, 2019 by Yaron Nir 7 Quote Link to comment Share on other sites More sharing options...
danwinslow Posted May 15, 2019 Share Posted May 15, 2019 Good stuff, Thanks Yaron. I assume this is with the latest version of the compiler? Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted May 15, 2019 Author Share Posted May 15, 2019 Thanks Dan, this is the version i am using: cl65 -V cl65 V2.17 - Git 5c8854f yes, it is the latest... Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted May 15, 2019 Share Posted May 15, 2019 Nice. A note that when focused on a line in the Disassembly window, F9 can be used to toggle a breakpoint. Also, within Console, "frame to be drawn" is better phrased "frame being drawn". Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted May 15, 2019 Author Share Posted May 15, 2019 Nice. A note that when focused on a line in the Disassembly window, F9 can be used to toggle a breakpoint. Also, within Console, "frame to be drawn" is better phrased "frame being drawn". updated. thanks! 1 Quote Link to comment Share on other sites More sharing options...
popmilo Posted May 15, 2019 Share Posted May 15, 2019 Nice Yaron ! This will make life easier for many. 1 Quote Link to comment Share on other sites More sharing options...
Cyprian Posted May 16, 2019 Share Posted May 16, 2019 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. great topic. many thanks 1 Quote Link to comment Share on other sites More sharing options...
Yaron Nir Posted June 27, 2019 Author Share Posted June 27, 2019 Tutorial update, added more debugging commands: .dumpdlist .gtia .antic gs 100 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.