Difference between revisions of "Debug messages"
(→Emulator and toolchain specific caveats) |
|||
(5 intermediate revisions by the same user not shown) | |||
Line 53: | Line 53: | ||
|| <pre>%A% %B% %C% %D% %E% %H% %L% | || <pre>%A% %B% %C% %D% %E% %H% %L% | ||
%AF% %BC% %DE% %HL% %PC% %SP% | %AF% %BC% %DE% %HL% %PC% %SP% | ||
− | %ALLREGS% </pre> || The current value of a 8-bit CPU register, 16-bit CPU register. | + | %ALLREGS% </pre> || The current value of a 8-bit CPU register, 16-bit CPU register or a dump of all registers. |
|- | |- | ||
|| <pre>%ZF% %Z% %ZERO% | || <pre>%ZF% %Z% %ZERO% | ||
%CF% %CARRY% | %CF% %CARRY% | ||
− | %IME%</pre> || The current value of a CPU flag or the interrupt master enable. | + | %IME%</pre> || The current value of a CPU flag or the interrupt master enable. (Note: these operands are only supported in BGB and not in Emulicious.) |
− | + | |- | |
+ | || <pre>%ROMBANK% %SRAMBANK% %XRAMBANK% | ||
+ | %WRAMBANK% %VRAMBANK%</pre> || The selected ROM or RAM bank of various types. (Note: %XRAMBANK% is only supported in BGB and not in Emulicious. %XRAMBANK% is an alias for %SRAMBANK% so you can use %SRAMBANK% to be compatible with both.) | ||
+ | |- | ||
+ | || <pre>%TOTALCLKS%</pre> || Number of clock cycles since power on. All these operands output in units of 1 nop in GBC double speed mode. So exeucintg a nop in ''single speed mode'' will increment the clock timers by 2. | ||
+ | |- | ||
+ | || <pre>%CLKS2VBLANK%</pre> || Number of clock cycles until the next VBlank. | ||
+ | |- | ||
+ | || <pre>%LASTCLKS%</pre> || Number of clock cycles since last user of %ZEROCLKS%. (Can be used for benchmarking.) | ||
+ | |- | ||
+ | || <pre>%ZEROCLKS%</pre> || Reset the timer used for %LASTCLKS%. | ||
+ | |- | ||
+ | || <pre>%expression%text if true;text if false;</pre> || Ternary expression, similar to condition?if_true:if_false in c family languages. | ||
+ | |- | ||
+ | || <pre>%(BC)% %(DE)% %(HL)% | ||
+ | %(SP)% %(PC)%</pre> || Read the value at the address specified by the expression. Most commonly used with 16 bit registers, but can be used with any expression. | ||
+ | |- | ||
+ | || <pre>%B+1% %(DE+2)% %(HL+5)+3%</pre> || Add a value to another value. | ||
+ | |- | ||
|} | |} | ||
+ | |||
+ | ==Emulator and toolchain specific caveats== | ||
+ | |||
+ | ===Case sensitivity=== | ||
+ | |||
+ | Any operands above that are full words must be uppercase when used with Emulicious. In BGB, they are case insensitive, and you could even use something like %RoMbAnK%, mocking Spongebob style. | ||
+ | |||
+ | ===Zero pad=== | ||
+ | |||
+ | BGB and Emulicious will behave slightly differently in how they pad values. For example, BGB pads 16 bit register expressions like %HL% to 4 digits, whereas Emulicious doesn't. However, %ALLREGS% does contain values padded to 4 digits. This can be worth keeping in mind if you're planning to parse the log output using code. | ||
+ | |||
+ | ===Garbled text due to charmaps=== | ||
+ | |||
+ | In RGBDS, if you use a custom [https://rgbds.gbdev.io/docs/v0.6.1/rgbasm.5#Character_maps charmap] globally, this will garble the message strings. In this case, make sure to specify a standard ASCII charmap. The example below assumes the "default" charmap is untouched. | ||
+ | |||
+ | <pre> | ||
+ | ; Macro definition. (Usually defined in an include file.) | ||
+ | MACRO debug_message | ||
+ | ld d,d | ||
+ | jr :+ | ||
+ | dw $6464 ; Two ASCII characters: "dd" | ||
+ | dw $0000 ; Identifier for this debug message type | ||
+ | pushc | ||
+ | setcharmap default | ||
+ | db \1 | ||
+ | popc | ||
+ | : | ||
+ | ENDM | ||
+ | |||
+ | ; Invoke the macro | ||
+ | debug_message "Hello!" | ||
+ | |||
+ | </pre> |
Latest revision as of 13:17, 22 December 2024
Debug messages is a feature in Gameboy debuggers that allows you to output debug data from the running program into a log window or file. Currently, two standards exist. Both use the ld d,d instruction followed by a relative jump (jr) jumping over the message payload, and a unique identifier, followed by the message payload itself. Similar to how source code breakpoint use the ld b,b instruction, which is normally a no-op, debug messages use ld d,d. Because of this, debug messages will be ignored with minimal overhaad if executed on real hardware or an emulator without support for them.
Contents
Classic (no$gmb style) debug messages
This style of debug message dates back to no$gmb, but is supported in BGB, Emulicious and possibly other emulators with debug support as well.
Message specified directly
This style of debug message has the syntax shown in the following example code: (RGBDS syntax)
; Macro definition. (Usually defined in an include file.) MACRO debug_message ld d,d jr :+ dw $6464 ; Two ASCII characters: "dd" dw $0000 ; Identifier for this debug message type db \1 : ENDM ; Invoke the macro debug_message "Hello!"
Message specified with a pointer
Alternatively, you can point to a message somewhere else using a far pointer, consisting of an address and a bank, both represented as 16 bit numbers.
; Macro definition. (Usually defined in an include file.) macro debug_message_pointer ld d,d jr :+ dw $6464 ; Two ASCII characters: "dd" dw $0001 ; Identifier for this debug message type dw \1 dw bank(\1) : endm ; Invoke the macro debug_message_pointer a_msg ; A null-terminated string. (Defined somewhere else so code doesn't fall right into it!) a_msg: db "Hello!",0
Operands
Several special operands can be used to print information about the internal state of the emulated machine.
Operand | Description |
---|---|
%A% %B% %C% %D% %E% %H% %L% %AF% %BC% %DE% %HL% %PC% %SP% %ALLREGS% |
The current value of a 8-bit CPU register, 16-bit CPU register or a dump of all registers. |
%ZF% %Z% %ZERO% %CF% %CARRY% %IME% |
The current value of a CPU flag or the interrupt master enable. (Note: these operands are only supported in BGB and not in Emulicious.) |
%ROMBANK% %SRAMBANK% %XRAMBANK% %WRAMBANK% %VRAMBANK% |
The selected ROM or RAM bank of various types. (Note: %XRAMBANK% is only supported in BGB and not in Emulicious. %XRAMBANK% is an alias for %SRAMBANK% so you can use %SRAMBANK% to be compatible with both.) |
%TOTALCLKS% |
Number of clock cycles since power on. All these operands output in units of 1 nop in GBC double speed mode. So exeucintg a nop in single speed mode will increment the clock timers by 2. |
%CLKS2VBLANK% |
Number of clock cycles until the next VBlank. |
%LASTCLKS% |
Number of clock cycles since last user of %ZEROCLKS%. (Can be used for benchmarking.) |
%ZEROCLKS% |
Reset the timer used for %LASTCLKS%. |
%expression%text if true;text if false; |
Ternary expression, similar to condition?if_true:if_false in c family languages. |
%(BC)% %(DE)% %(HL)% %(SP)% %(PC)% |
Read the value at the address specified by the expression. Most commonly used with 16 bit registers, but can be used with any expression. |
%B+1% %(DE+2)% %(HL+5)+3% |
Add a value to another value. |
Emulator and toolchain specific caveats
Case sensitivity
Any operands above that are full words must be uppercase when used with Emulicious. In BGB, they are case insensitive, and you could even use something like %RoMbAnK%, mocking Spongebob style.
Zero pad
BGB and Emulicious will behave slightly differently in how they pad values. For example, BGB pads 16 bit register expressions like %HL% to 4 digits, whereas Emulicious doesn't. However, %ALLREGS% does contain values padded to 4 digits. This can be worth keeping in mind if you're planning to parse the log output using code.
Garbled text due to charmaps
In RGBDS, if you use a custom charmap globally, this will garble the message strings. In this case, make sure to specify a standard ASCII charmap. The example below assumes the "default" charmap is untouched.
; Macro definition. (Usually defined in an include file.) MACRO debug_message ld d,d jr :+ dw $6464 ; Two ASCII characters: "dd" dw $0000 ; Identifier for this debug message type pushc setcharmap default db \1 popc : ENDM ; Invoke the macro debug_message "Hello!"