$WW,1$* You can enter the debugger with $LK,"Dbg","MN:Dbg"$() or $FG,2$<CTRL-ALT-D>$FG$.  You might enter the debugger through a fault.  Enter $LK,"G","MN:G"$() or $LK,"G2","MN:G2"$() to continue execution.  Place a call to $LK,"Dbg","MN:Dbg"$() in your code at fatal error points to enter the debugger.  If you see a stk dump, record the label+offset and unassemble, $LK,"U","MN:U"$().

* I use $LK,"progress1","MN:progress1"$-$LK,"progress4","MN:progress4"$ for debugging because they show on the wallpaper.  They're just global integer vars.

* While debugging, you specify addresses of assembly  routines with just the label, as in $FG,2$_MALLOC+0x20$FG$.  You specify $LK,"Holy C","FI:::/TempleOS/Doc/HolyC.TXT"$ function names with $FG,2$&$FG$ before functions as in $FG,2$&PrintF+0x10$FG$.

* You can use $LK,"AdamLog","MN:AdamLog"$() to send text to the Adam task window.  It works like $LK,"PrintF","MN:PrintF"$().  I never use this.  Instead I use $LK,"DbgI64","MN:DbgI64"$().

* $LK,"D","MN:D"$() $LK,"DocD","MN:DocD"$() to do 16 column hex dump mem with numbering from zero.  With $LK,"DocD","MN:DocD"$ the values are updated continually and you can alter mem by editing.

* $LK,"Dm","MN:Dm"$() $LK,"DocDm","MN:DocDm"$() to do 16 column hex dump mem with addresses showing.

* $LK,"Da","MN:Da"$() to do one column address dump (for stk, etc.) with symbolic addresses.

* $LK,"Dr","MN:Dr"$() dumps registers.  You can display and modify registers in the debugger with var-like labels, $FG,4$_RAX$FG$, $FG,4$_RBX$FG$, etc.

* $LK,"U","MN:U"$(&FunName+offset) to unassemble mem or $LK,"Uf","MN:Uf"$("FunName") to unassemble a function.

* $LK,"ProfBin","MN:ProfBin"$(),$LK,"ProfAll","MN:ProfAll"$() and $LK,"ProfRep","MN:ProfRep"$() provide code profiling.  See $LK-A,"::/TempleOS/Demo/AutoFile/AFProfile.AUT"$ (This is an $LK,"AutoFile","FF:::/TempleOS/Doc/Glossary.TXT,AutoFile"$.)

* Use $LK,"DbgI64","MN:DbgI64"$(), $LK,"DbgStr","MN:DbgStr"$() and $LK,"DbgAdd","MN:DbgAdd"$() to print debug info bypassing the window framework.  You pass these routines a count in milliseconds for how long it should be displayed.  You can use $LK,"Raw","MN:Raw"$($FG,2$TRUE$FG$) to make all output bypass the window framework.  The WinMgr runs on core0 and will overwrite raw text from other cores when it updates the screen.

* Use $LK,"SysDbg","MN:SysDbg"$() to set a flag which you can read with $LK,"IsSysDbg","MN:IsSysDbg"$() when you wish to trigger some debug activity.  It's just a handy simple flag, nothing fancy.

* Use $LK,"SysDeterministic","MN:SysDeterministic"$() to set a flag which tries to keep the system deterministic for debugging.  $LK,"IsSysDeterministic","MN:IsSysDeterministic"$().  There is a $FG,2$Deterministic$FG$ Kernel config flag.

* There are flags for various trace options that can help debugging when there are compiler bugs.  Often, you place them in $FG,2$#exe{}$FG$ blocks.
$ID,2$
$LK,"Echo","MN:Echo"$() turns on or off raw data going into the lexical analyzer.

$LK,"LTrace","MN:LTrace"$() shows the tokens coming out of the lexical analyzer.

$LK,"CTrace","MN:CTrace"$() unassembles code generated from the Holy C compiler.

$LK,"PTrace","MN:PTrace"$() shows $FG,2$intermediate code$FG$ comming out of the first stage of the compiler (it's not 100% valid because it hasn't been fixed-up).

$LK,"OTrace","MN:OTrace"$() shows intermediate code coming-out after optimization.  $LK,"OPassTraceMask","MN:OPassTraceMask"$() ctrls which passes are displayed.
$ID,-2$

* There is a heap check utility which can find leaks.  Use $LK,"HeapLog","MN:HeapLog"$(), and $LK,"HeapLogRep","MN:HeapLogRep"$().  It's a really simple program which intercepts $LK,"MAlloc","MN:MAlloc"$() and $LK,"Free","MN:Free"$().  You can customize the code to find other heap issues.

* You can define functions for $FG,2$<CTRL-ALT-letter>$FG$ keys, but they must operate in a interrupt environment or in the window mgr when in ques kbd msgs.  You can do $LK,"Raw","MN:Raw"$() output.  Search for $LK,"fp_ctrl_alt_let_cbs","MN:fp_ctrl_alt_let_cbs"$[] and look at the code.  They take scancode as an arg.

* If you recompile $FG,2$Kernel$FG,2$$FG$ with $LK,"MakeOSInstallPrtBootLoader","MN:MakeOSInstallPrtBootLoader"$(), you can set the $FG,4$MemInit$FG$, option to initialize memory to a value at boot, the $FG,4$HeapInit$FG$ option to cause mem allocated off the heap to be initialized or $FG,4$VarInit$FG$ option so both global and local vars will be initialized to a value.  Pick a non-zero value to discover uninitialized var bugs.  You can set $LK,"sys_var_init_flag","MN:sys_var_init_flag"$, and $LK,"sys_heap_init_flag","MN:sys_heap_init_flag"$ directly after booting.  You can also use the $FG,4$ProtectLow$FG$ option to discover $FG,2$NULL$FG$ dereferences.
