git.y1.nz

gbdk-2020

GameBoy Development Kit
download: https://git.y1.nz/archives/gbdk.tar.gz
README | Files | Log | Refs | LICENSE

gbdk-lib/examples/cross-platform/emu_debug/src/emu_debug.c

      1 #include <gbdk/platform.h>
      2 #include <stdint.h>
      3 #include <stdio.h>      // Just for printf()
      4 
      5 #include <gbdk/emu_debug.h> // Use this include to add the Emu debug functions
      6 
      7 
      8 // This example shows how to use support for profiling
      9 // and logging to the debug window in the emulator (BGB or Emulicious).
     10 //
     11 // 1. Build this ROM (emu_debug.gb) then load it in the emulator (BGB or Emulicious)
     12 // 2. Open the internal debugger by pressing the "ESC" or "F1" key
     13 // 3. From the debugger menu choose "debug messages" to open the debug messages window
     14 // 4. Reset the gameboy (you may need to press F9 in the debugger to resume running)
     15 // 5. The debug window will show the debug messages
     16 //
     17 // See the BGB Manual for more information
     18 // ("expressions, breakpoint conditions, and debug messages")
     19 // https://bgb.bircd.org/manual.html#expressions
     20 
     21 // If you see a message like the following, it is safe to ignore. It is a known
     22 // issue with SDCC and should not cause problems.
     23 //
     24 // " src/emu_debug.c:156: info 218: z80instructionSize() failed to parse line node, assuming 999 bytes ' llbl:'
     25 
     26 int main(void)
     27 {
     28     SHOW_BKG;
     29     DISPLAY_ON;
     30 
     31     // Display a message on the screen
     32     printf("Message to the\nScreen\n");
     33 
     34     // Log a message to the Emulator debug message window
     35     EMU_MESSAGE(""); // new line
     36     EMU_MESSAGE("Message to the EMU console");
     37 
     38     // ==== Normal Speed Mode ====
     39     // Profile code: a single NOP instruction
     40     //
     41     // The clock units are "1 nop in [CGB] doublespeed mode".
     42     // So when *not* running in CGB doublespeed mode you
     43     // have to divide by 2 to get the correct cycle count.
     44     //
     45     // You should see the message "NOP TIME: 2".
     46     //
     47     // So in this case, divide the printed value by 2 = The NOP took "1" cycle
     48 
     49     __critical {  // Temporarily turn off interrupts for more accurate measurements
     50         EMU_PROFILE_BEGIN("Profile a single NOP instruction at Normal Speed");
     51             __asm__("nop");
     52         EMU_PROFILE_END("NOP TIME:");
     53     }
     54 
     55 
     56     #ifdef NINTENDO
     57     // ==== Color Game Boy in Double Speed Mode ====
     58     // Profile code: a single NOP instruction
     59     //
     60     // The EMU_PROFILE_BEGIN/END macros don't support the
     61     // Color Game Boy (CGB) in double speed mode (cpu_fast()).
     62     // The example below shows what to use instead (and how to
     63     // check for a CGB and turn on Double Speed mode).
     64     //
     65     // Check and only run this test if on CGB hardware
     66     if (DEVICE_SUPPORTS_COLOR) {
     67 
     68         // Set CGB into double speed mode
     69         // (Requires passing -Wm-yc or -Wm-yC with Lcc during build time)
     70         cpu_fast();
     71         // Set some default DMG styled colors in the CGB Palette
     72         set_default_palette();
     73 
     74         // In CGB Double Speed mode, you don't have to
     75         // divide by 2 to get the cycle count.
     76         //
     77         // You should see the message "NOP TIME: 1".
     78 
     79         __critical {  // Temporarily turn off interrupts for more accurate measurements
     80             EMU_PROFILE_BEGIN("Profile a single NOP instruction at CGB Double Speed");
     81                 __asm__("nop");
     82             // The "-4+" subtracts 4 clocks to compensate for the ones
     83             // used by the debug message itself (Normal speed uses -8)
     84             EMU_MESSAGE("NOP TIME:%-4+LASTCLKS%");
     85         }
     86 
     87         // Return the CGB to normal speed
     88         cpu_slow();
     89     }
     90     #endif // NINTENDO
     91 
     92 
     93     __critical {  // Temporarily turn off interrupts for more accurate measurements
     94 
     95         int c;
     96 
     97         // Profile code in a loop
     98         EMU_PROFILE_BEGIN("Profile code in a loop");
     99             for(c=0; c<5; c++) {
    100                 // Do something
    101                 printf("%d\n", c);
    102             }
    103         // Elapsed cycle count output is in hex.
    104         // Remember to divide by 2 for the result (Normal Speed)
    105         EMU_PROFILE_END("LOOP TIME:");
    106     }
    107 
    108     // ==== Some other things you can print ====
    109 
    110     // - For Game Boy TOTALCLKS shows the clocks counter ("internal divider")
    111     // - For SMS/GG TOTALCLKS is relative to CLKS2VBLANK (so at most it can be the max clocks to vblank)
    112     EMU_MESSAGE("Total Clocks: %TOTALCLKS%");
    113 
    114     // CLKS2VBLANK
    115     EMU_MESSAGE("Clocks until VBLANK: %CLKS2VBLANK%");
    116 
    117     // Which Banks are currently active (for MBC based cartridges)
    118     EMU_MESSAGE("Current  ROM bank: %ROMBANK%");
    119     EMU_MESSAGE("Current SRAM bank: %SRAMBANK%");
    120     // These are not banked on DMG/MGB Game Boys
    121     EMU_MESSAGE("Current VRAM bank: %VRAMBANK%");
    122     EMU_MESSAGE("Current WRAM bank: %WRAMBANK%");
    123 
    124     // Registers (All in this case, or individual ones)
    125     EMU_MESSAGE("All Registers: %ALLREGS%");
    126 
    127     // Simple addition with a register
    128     EMU_MESSAGE("Register A + 1: %A+1%");
    129 
    130     // Note: %SCANLINE% is available in Emulicious (for SMS/GG/GB/GBC) but not BGB
    131     EMU_MESSAGE("Current Scanline: %SCANLINE%");
    132 
    133     #if defined(NINTENDO)
    134         // Read the LY Register a couple times
    135         // Note how the register value is obtained by using parenthesis to de-referenced its address.
    136         // (Current Y coordinate being rendered to the LCD)
    137         EMU_MESSAGE("LY Register (0xFF44): %($ff44)%");
    138         EMU_MESSAGE("LY Register (0xFF44): %($ff44)%");
    139         // Now print a conditional debug message using it
    140         EMU_MESSAGE("Is LY Register > Line 67: %($ff44)>67%Yes;No;");
    141     #endif
    142 
    143     int16_t  var_s16  = -1234;
    144     uint16_t var_u16  = 31002;
    145     uint16_t var_u16h = 0xA50Fu;
    146     int8_t   var_s8   = -56;
    147     uint8_t  var_u8   = 224;
    148     uint8_t  var_u8h  = 0xF8;
    149     char     var_chr  = 'A';
    150     char *   var_string = "Hello Emu Printf";
    151 
    152     // For EMU_printf:
    153     // Note how all the 8 bit arguments must be explicitly cast EXCEPT for %c
    154     // In partifcular, %c MUST NOT be cast or the output will be incorrect
    155     EMU_printf("signed int: %d\n"
    156                "unsigned int: %u\n"
    157                "hex int: 0x%X\n"
    158                "signed byte: %hd\n"
    159                "unsigned byte: %hu\n"
    160                "hex byte: 0x%hX\n"
    161                "Character: %c\n"
    162                "String: %s\n",
    163                 (int16_t) var_s16,
    164                 (uint16_t) var_u16,
    165                 (uint16_t) var_u16h,
    166                 (int8_t)var_s8,
    167                 (uint8_t)var_u8,
    168                 (uint8_t)var_u8h,
    169                 var_chr,    // Do not explicitly cast %c vars for EMU_printf, it expects them auto-promoted to 2 bytes (casting would prevent that)
    170                 var_string);
    171 
    172     // The EMU_TEXT() macro will accept a non-quoted string
    173     EMU_TEXT("The End");
    174 
    175     return 0;
    176 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.