diff --git a/Core/debugger.c b/Core/debugger.c index 53e38c7..af1649c 100644 --- a/Core/debugger.c +++ b/Core/debugger.c @@ -1728,6 +1728,31 @@ static bool ticks(GB_gameboy_t *gb, char *arguments, char *modifiers, const debu return true; } +static bool usage(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command) +{ + NO_MODIFIERS + + if (strlen(lstrip(arguments))) { + print_usage(gb, command); + return true; + } + + if (gb->last_frame_busy_cycles || gb->last_frame_idle_cycles) { + GB_log(gb, "CPU usage (last frame): %.2f%%\n", (double)gb->last_frame_busy_cycles / (gb->last_frame_busy_cycles + gb->last_frame_idle_cycles) * 100); + } + else { + GB_log(gb, "CPU usage (last frame): N/A\n"); + } + + if (gb->last_second_busy_cycles || gb->last_second_idle_cycles) { + GB_log(gb, "CPU usage (last 60 frames): %.2f%%\n", (double)gb->last_second_busy_cycles / (gb->last_second_busy_cycles + gb->last_second_idle_cycles) * 100); + } + else { + GB_log(gb, "CPU usage (last 60 frames): N/A\n"); + } + + return true; +} static bool palettes(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command) { @@ -2184,6 +2209,7 @@ static const debugger_command_t commands[] = { {"ticks", 2, ticks, "Display the number of CPU ticks since the last time 'ticks' was " "used. Use 'keep' as an argument to display ticks without reseeting " "the count.", "(keep)", .argument_completer = keep_completer}, + {"usage", 2, usage, "Display CPU usage"}, {"cartridge", 2, mbc, "Display information about the MBC and cartridge"}, {"mbc", 3, }, /* Alias */ {"apu", 3, apu, "Display information about the current state of the audio processing unit", diff --git a/Core/display.c b/Core/display.c index a679f2e..2a94a03 100644 --- a/Core/display.c +++ b/Core/display.c @@ -176,6 +176,21 @@ void GB_display_vblank(GB_gameboy_t *gb, GB_vblank_type_t type) gb->cycles_since_vblank_callback = 0; gb->lcd_disabled_outside_of_vblank = false; +#ifndef GB_DISABLE_DEBUGGER + gb->last_frame_idle_cycles = gb->current_frame_idle_cycles; + gb->last_frame_busy_cycles = gb->current_frame_busy_cycles; + gb->current_frame_idle_cycles = 0; + gb->current_frame_busy_cycles = 0; + + if (gb->usage_frame_count++ == 60) { + gb->last_second_idle_cycles = gb->current_second_idle_cycles; + gb->last_second_busy_cycles = gb->current_second_busy_cycles; + gb->current_second_idle_cycles = 0; + gb->current_second_busy_cycles = 0; + gb->usage_frame_count = 0; + } +#endif + /* TODO: Slow in turbo mode! */ if (GB_is_hle_sgb(gb)) { GB_sgb_render(gb); diff --git a/Core/gb.h b/Core/gb.h index 3636930..859dbad 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -785,6 +785,14 @@ struct GB_gameboy_internal_s { /* Callbacks */ GB_debugger_reload_callback_t debugger_reload_callback; + + /* CPU usage */ + uint32_t current_frame_idle_cycles, current_frame_busy_cycles; + uint32_t last_frame_idle_cycles, last_frame_busy_cycles; + + uint32_t current_second_idle_cycles, current_second_busy_cycles; + uint32_t last_second_idle_cycles, last_second_busy_cycles; + uint8_t usage_frame_count; #endif #ifndef GB_DISABLE_REWIND diff --git a/Core/timing.c b/Core/timing.c index fcfb812..b43a970 100644 --- a/Core/timing.c +++ b/Core/timing.c @@ -472,6 +472,8 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles) #ifndef GB_DISABLE_DEBUGGER gb->absolute_debugger_ticks += cycles; + *((gb->halted || gb->stopped)? &gb->current_frame_idle_cycles : &gb->current_frame_busy_cycles) += cycles; + *((gb->halted || gb->stopped)? &gb->current_second_idle_cycles : &gb->current_second_busy_cycles) += cycles; #endif // Not affected by speed boost