text: /** @file gb/emu_debug.h
  
      Debug window logging and profiling support for emulators (BGB, Emulicious, etc).
  
      Also see the `emu_debug` example project included with gbdk.
  
      See the BGB Manual for more information
      ("expressions, breakpoint conditions, and debug messages")
      http://bgb.bircd.org/manual.html#expressions
  
  */
  #ifndef __EMU_DEBUG_INCLUDE
  #define __EMU_DEBUG_INCLUDE
  
  #include <types.h>
  
  /** Macro to display a message in the emulator debug message window
  
      @param message_text  Quoted text string to display in the debug message window
  
      The following special parameters can be
      used when bracketed with "%" characters.
      \li CPU registers: AF, BC, DE, HL, SP, PC, B, C, D,
          E, H, L, A, ZERO, ZF, Z, CARRY, CY, IME, ALLREGS
      \li Other state values: ROMBANK, XRAMBANK, SRAMBANK,
          WRAMBANK, VRAMBANK, TOTALCLKS, LASTCLKS, CLKS2VBLANK
  
      Example: print a message along with the currently active ROM bank.
      \code{.c}
      EMU_MESSAGE("Current ROM Bank is: %ROMBANK%");
      \endcode
  
  
      See the BGB Manual for more information
      ("expressions, breakpoint conditions, and debug messages")
      http://bgb.bircd.org/manual.html#expressions
  
      @see EMU_PROFILE_BEGIN(), EMU_PROFILE_END()
   */
  #define EMU_MESSAGE(message_text) EMU_MESSAGE1(EMU_MACRONAME(__LINE__), message_text)
  #define BGB_MESSAGE(message_text) EMU_MESSAGE(message_text)
  
  /// \cond DOXYGEN_DO_NOT_DOCUMENT
  #define EMU_MACRONAME(A) EMU_MACRONAME1(A)
  #define EMU_MACRONAME1(A) EMULOG##A
  
  #define EMU_MESSAGE1(name, message_text) \
  __asm \
  .MACRO name msg_t, ?llbl\
    ld d, d \
    jr llbl \
    .dw 0x6464 \
    .dw 0x0000 \
    .ascii msg_t \
  llbl: \
  .ENDM \
  name ^/message_text/ \
  __endasm
  
  #define EMU_MESSAGE_SUFFIX(message_text, message_suffix) EMU_MESSAGE3(EMU_MACRONAME(__LINE__), message_text, message_suffix)
  #define EMU_MESSAGE3(name, message_text, message_suffix) \
  __asm \
  .MACRO name msg_t, msg_s, ?llbl\
    ld d, d \
    jr llbl \
    .dw 0x6464 \
    .dw 0x0000 \
    .ascii msg_t \
    .ascii msg_s \
  llbl: \
  .ENDM \
  name ^/message_text/, ^/message_suffix/ \
  __endasm
  /// \endcond DOXYGEN_DO_NOT_DOCUMENT
  
  /** Macro to __Start__ a profiling block for the emulator (BGB, Emulicious, etc)
  
      @param MSG  Quoted text string to display in the
                  debug message window along with the result
  
      To complete the profiling block and print
      the result call @ref EMU_PROFILE_END.
  
      @see EMU_PROFILE_END(), EMU_MESSAGE()
   */
  #define EMU_PROFILE_BEGIN(MSG) EMU_MESSAGE_SUFFIX(MSG, "%ZEROCLKS%");
  #define BGB_PROFILE_BEGIN(MSG) EMU_PROFILE_BEGIN(MSG)
  /** Macro to __End__ a profiling block and print the results in the emulator debug message window
  
      @param MSG  Quoted text string to display in the
                  debug message window along with the result
  
      This should only be called after a previous call
      to @ref EMU_PROFILE_BEGIN()
  
      The results are in Emulator clock units, which are
      "1 nop in [CGB] doublespeed mode".
  
      So when running in Normal Speed mode (i.e. non-CGB doublespeed)
      the printed result should be __divided by 2__ to get the actual
      ellapsed cycle count.
  
      If running in CB Double Speed mode use the below call instead,
      it correctly compensates for the speed difference. In this
      scenario, the result does  __not need to be divided by 2__ to
      get the ellapsed cycle count.
      \code{.c}
      EMU_MESSAGE("NOP TIME: %-4+LASTCLKS%");
      \endcode
  
      @see EMU_PROFILE_BEGIN(), EMU_MESSAGE()
   */
  #define EMU_PROFILE_END(MSG) EMU_MESSAGE_SUFFIX(MSG,"%-8+LASTCLKS%");
  #define BGB_PROFILE_END(MSG) EMU_PROFILE_END(MSG)
  
  #define EMU_TEXT(MSG) EMU_MESSAGE(MSG)
  #define BGB_TEXT(MSG) EMU_TEXT(MSG)
  
  /** Display preset debug information in the Emulator debug messages window.
  
      This function is equivalent to:
      \code{.c}
      EMU_MESSAGE("PROFILE,%(SP+$0)%,%(SP+$1)%,%A%,%TOTALCLKS%,%ROMBANK%,%WRAMBANK%");
      \endcode
  
  */
  void EMU_profiler_message();
  #define BGB_profiler_message() EMU_profiler_message()
  
  /** Print the string and arguments given by format to the emulator debug message window
  
      @param format   The format string as per printf
  
      Does not return the number of characters printed.
  	Result string MUST BE LESS OR EQUAL THAN 128 BYTES LONG, INCLUDING THE TRAILIG ZERO BYTE!
  
      Currently supported:
      \li \%hx (char as hex)
      \li \%hu (unsigned char)
      \li \%hd (signed char)
      \li \%c (character)
      \li \%u (unsigned int)
      \li \%d (signed int)
      \li \%x (unsigned int as hex)
      \li \%s (string)
  
      Warning: to correctly pass chars for printing as chars, they *must*
      be explicitly re-cast as such when calling the function.
      See @ref docs_chars_varargs for more details.
   */
  void EMU_printf(const char *format, ...) OLDCALL;
  #define BGB_printf(...) EMU_printf(__VA_ARGS__)
  
  static void * __EMU_PROFILER_INIT = &EMU_profiler_message;
  
  /** The Emulator will break into debugger when encounters this line
   */
  #define EMU_BREAKPOINT __asm__("ld b, b");
  #define BGB_BREAKPOINT EMU_BREAKPOINT
  
  #endif
  