From 04f80d1c6934098d02922f6fa7123dfb3455a6bb Mon Sep 17 00:00:00 2001 From: Ignacio Sanchez Gines <863613+drhelius@users.noreply.github.com> Date: Sat, 24 Aug 2024 01:00:24 +0200 Subject: [PATCH] Trace logs --- platforms/shared/desktop/config.cpp | 4 + platforms/shared/desktop/config.h | 2 + platforms/shared/desktop/gui_actions.cpp | 4 +- .../shared/desktop/gui_debug_trace_logger.cpp | 85 ++++++++++++++----- .../shared/desktop/gui_debug_trace_logger.h | 2 + platforms/shared/desktop/gui_filedialogs.cpp | 17 ++++ platforms/shared/desktop/gui_filedialogs.h | 1 + src/geargrafx_core.cpp | 33 ++++--- src/huc6280.cpp | 5 +- src/huc6280.h | 2 + 10 files changed, 116 insertions(+), 39 deletions(-) diff --git a/platforms/shared/desktop/config.cpp b/platforms/shared/desktop/config.cpp index 9e10b3a..bde69f2 100644 --- a/platforms/shared/desktop/config.cpp +++ b/platforms/shared/desktop/config.cpp @@ -116,10 +116,12 @@ void config_read(void) config_debug.show_huc6270_info = read_bool("Debug", "HuC6270Info", false); config_debug.show_psg = read_bool("Debug", "PSG", false); config_debug.show_trace_logger = read_bool("Debug", "TraceLogger", false); + config_debug.trace_counter = read_bool("Debug", "TraceCounter", true); config_debug.trace_bank = read_bool("Debug", "TraceBank", true); config_debug.trace_registers = read_bool("Debug", "TraceRegisters", true); config_debug.trace_flags = read_bool("Debug", "TraceFlags", true); config_debug.trace_cycles = read_bool("Debug", "TraceCycles", true); + config_debug.trace_bytes = read_bool("Debug", "TraceBytes", true); config_debug.dis_show_mem = read_bool("Debug", "DisMem", true); config_debug.dis_show_symbols = read_bool("Debug", "DisSymbols", true); config_debug.dis_show_segment = read_bool("Debug", "DisSegment", true); @@ -235,10 +237,12 @@ void config_write(void) write_bool("Debug", "HuC6270Info", config_debug.show_huc6270_info); write_bool("Debug", "PSG", config_debug.show_psg); write_bool("Debug", "TraceLogger", config_debug.show_trace_logger); + write_bool("Debug", "TraceCounter", config_debug.trace_counter); write_bool("Debug", "TraceBank", config_debug.trace_bank); write_bool("Debug", "TraceRegisters", config_debug.trace_registers); write_bool("Debug", "TraceFlags", config_debug.trace_flags); write_bool("Debug", "TraceCycles", config_debug.trace_cycles); + write_bool("Debug", "TraceBytes", config_debug.trace_bytes); write_bool("Debug", "DisMem", config_debug.dis_show_mem); write_bool("Debug", "DisSymbols", config_debug.dis_show_symbols); write_bool("Debug", "DisSegment", config_debug.dis_show_segment); diff --git a/platforms/shared/desktop/config.h b/platforms/shared/desktop/config.h index c02c88a..5492c6e 100644 --- a/platforms/shared/desktop/config.h +++ b/platforms/shared/desktop/config.h @@ -114,10 +114,12 @@ struct config_Debug bool show_huc6270_info = false; bool show_psg = false; bool show_trace_logger = false; + bool trace_counter = true; bool trace_bank = true; bool trace_registers = true; bool trace_flags = true; bool trace_cycles = true; + bool trace_bytes = true; bool dis_show_mem = true; bool dis_show_symbols = true; bool dis_show_segment = true; diff --git a/platforms/shared/desktop/gui_actions.cpp b/platforms/shared/desktop/gui_actions.cpp index 7b66f82..5c363ec 100644 --- a/platforms/shared/desktop/gui_actions.cpp +++ b/platforms/shared/desktop/gui_actions.cpp @@ -20,6 +20,7 @@ #define GUI_ACTIONS_IMPORT #include "gui_actions.h" #include "gui.h" +#include "gui_debug_trace_logger.h" #include "config.h" #include "emu.h" #include "../../../src/geargrafx.h" @@ -27,6 +28,7 @@ void gui_action_reset(void) { gui_set_status_message("Resetting...", 3000); + gui_debug_trace_logger_clear(); emu_resume(); emu_reset(); @@ -34,7 +36,7 @@ void gui_action_reset(void) if (config_emulator.start_paused) { emu_pause(); - + for (int i=0; i < (HUC6270_MAX_RESOLUTION_WIDTH * HUC6270_MAX_RESOLUTION_HEIGHT); i++) { emu_frame_buffer[i] = 0; diff --git a/platforms/shared/desktop/gui_debug_trace_logger.cpp b/platforms/shared/desktop/gui_debug_trace_logger.cpp index cca037f..e5c381e 100644 --- a/platforms/shared/desktop/gui_debug_trace_logger.cpp +++ b/platforms/shared/desktop/gui_debug_trace_logger.cpp @@ -23,15 +23,19 @@ #include #include "imgui/imgui.h" #include "gui.h" +#include "gui_filedialogs.h" #include "config.h" #include "emu.h" static bool trace_logger_enabled = false; -static int trace_logger_count = 10000; +static int trace_logger_count = 0; +static unsigned int trace_logger_instruction_count = 0; static std::deque trace_logger_lines; static void trace_logger_menu(void); +static const int k_line_count[] = { 1000, 5000, 10000, 50000, 100000, 500000, 1000000 }; + void gui_debug_window_trace_logger(void) { ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f); @@ -46,16 +50,12 @@ void gui_debug_window_trace_logger(void) ImGui::SameLine(); - if (ImGui::InputInt("lines", &trace_logger_count, 1, 1000, ImGuiInputTextFlags_AllowTabInput)) + ImGui::PushItemWidth(100); + if (ImGui::Combo("lines ", &trace_logger_count, "1000\0 5000\0 10000\0 50000\0 100000\0 500000\0 1000000\0\0")) { - if (trace_logger_count < 1) - trace_logger_count = 1; - else if (trace_logger_count > 100000) - trace_logger_count = 100000; - - if ((int)trace_logger_lines.size() > trace_logger_count) + if ((int)trace_logger_lines.size() > k_line_count[trace_logger_count]) { - int diff = trace_logger_lines.size() - trace_logger_count; + int diff = trace_logger_lines.size() - k_line_count[trace_logger_count]; trace_logger_lines.erase(trace_logger_lines.begin(), trace_logger_lines.begin() + diff); } } @@ -67,6 +67,13 @@ void gui_debug_window_trace_logger(void) trace_logger_enabled = !trace_logger_enabled; } + ImGui::SameLine(); + + if (ImGui::Button("Clear")) + { + gui_debug_trace_logger_clear(); + } + if (ImGui::BeginChild("##logger", ImVec2(ImGui::GetContentRegionAvail().x, 0), true, 0)) { ImGui::PushFont(gui_default_font); @@ -95,7 +102,7 @@ void gui_debug_trace_logger_update(GeargrafxCore::GG_Debug_State* state) { if (trace_logger_enabled) { - if ((int)trace_logger_lines.size() >= trace_logger_count) + if ((int)trace_logger_lines.size() >= k_line_count[trace_logger_count]) { trace_logger_lines.pop_front(); } @@ -106,15 +113,15 @@ void gui_debug_trace_logger_update(GeargrafxCore::GG_Debug_State* state) if (!IsValidPointer(record)) return; - char bank[32]; - snprintf(bank, sizeof(bank), "%02X", record->bank); + char bank[8]; + snprintf(bank, sizeof(bank), "%02X:", record->bank); char registers[40]; - snprintf(registers, sizeof(registers), "A: %02X X: %02X Y: %02X S: %02X", + snprintf(registers, sizeof(registers), "A: %02X X: %02X Y: %02X S: %02X ", state->A, state->X, state->Y, state->S); char flags[32]; - snprintf(flags, sizeof(flags), "P: %c%c%c%c%c%c%c%c", + snprintf(flags, sizeof(flags), "P: %c%c%c%c%c%c%c%c ", (state->P & FLAG_NEGATIVE) ? 'N' : 'n', (state->P & FLAG_OVERFLOW) ? 'V' : 'v', (state->P & FLAG_TRANSFER) ? 'T' : 't', @@ -124,14 +131,50 @@ void gui_debug_trace_logger_update(GeargrafxCore::GG_Debug_State* state) (state->P & FLAG_ZERO) ? 'Z' : 'z', (state->P & FLAG_CARRY) ? 'C' : 'c'); + char cycles[16]; + snprintf(cycles, sizeof(cycles), "(%02d) ", state->cycles); + + char counter[16]; + snprintf(counter, sizeof(counter), "%d ", trace_logger_instruction_count); + std::string instr = record->name; instr.erase(std::remove(instr.begin(), instr.end(), '{'), instr.end()); instr.erase(std::remove(instr.begin(), instr.end(), '}'), instr.end()); char line[256]; - snprintf(line, sizeof(line), "%s:%04X %s %s %s %s", bank, state->PC, registers, flags, instr.c_str(), record->bytes); + snprintf(line, sizeof(line), "%s%s%04X %s%s%s%s %s", + config_debug.trace_counter ? counter : "", + config_debug.trace_bank ? bank : "", + state->PC, + config_debug.trace_registers ? registers : "", + config_debug.trace_flags ? flags : "", + config_debug.trace_cycles ? cycles : "", + instr.c_str(), + config_debug.trace_bytes ? record->bytes : ""); trace_logger_lines.push_back(line); + trace_logger_instruction_count++; + } +} + +void gui_debug_trace_logger_clear(void) +{ + trace_logger_lines.clear(); + trace_logger_instruction_count = 0; +} + +void gui_debug_save_log(const char* file_path) +{ + FILE* file = fopen(file_path, "w"); + + if (file != NULL) + { + for (long unsigned int i = 0; i < trace_logger_lines.size(); i++) + { + fprintf(file, "%s\n", trace_logger_lines[i].c_str()); + } + + fclose(file); } } @@ -143,7 +186,7 @@ static void trace_logger_menu(void) { if (ImGui::MenuItem("Save Log As...")) { - + gui_file_dialog_save_log(); } ImGui::EndMenu(); @@ -151,10 +194,12 @@ static void trace_logger_menu(void) if (ImGui::BeginMenu("Log")) { - ImGui::MenuItem("Bank Number", "", &config_debug.trace_bank, config_debug.debug); - ImGui::MenuItem("Registers", "", &config_debug.trace_registers, config_debug.debug); - ImGui::MenuItem("Flags", "", &config_debug.trace_flags, config_debug.debug); - ImGui::MenuItem("Cycles", "", &config_debug.trace_bank, config_debug.debug); + ImGui::MenuItem("Instruction Counter", "", &config_debug.trace_counter); + ImGui::MenuItem("Bank Number", "", &config_debug.trace_bank); + ImGui::MenuItem("Registers", "", &config_debug.trace_registers); + ImGui::MenuItem("Flags", "", &config_debug.trace_flags); + ImGui::MenuItem("Cycles", "", &config_debug.trace_cycles); + ImGui::MenuItem("Bytes", "", &config_debug.trace_bytes); ImGui::EndMenu(); } diff --git a/platforms/shared/desktop/gui_debug_trace_logger.h b/platforms/shared/desktop/gui_debug_trace_logger.h index 022fafc..82c73a5 100644 --- a/platforms/shared/desktop/gui_debug_trace_logger.h +++ b/platforms/shared/desktop/gui_debug_trace_logger.h @@ -30,6 +30,8 @@ EXTERN void gui_debug_window_trace_logger(void); EXTERN void gui_debug_trace_logger_update(GeargrafxCore::GG_Debug_State* state); +EXTERN void gui_debug_trace_logger_clear(void); +EXTERN void gui_debug_save_log(const char* file_path); #undef GUI_DEBUG_TRACE_LOGGER_IMPORT #undef EXTERN diff --git a/platforms/shared/desktop/gui_filedialogs.cpp b/platforms/shared/desktop/gui_filedialogs.cpp index ab75542..19e10fe 100644 --- a/platforms/shared/desktop/gui_filedialogs.cpp +++ b/platforms/shared/desktop/gui_filedialogs.cpp @@ -23,6 +23,7 @@ #include "gui_actions.h" #include "gui_debug_memory.h" #include "gui_debug_disassembler.h" +#include "gui_debug_trace_logger.h" #include "config.h" #include "emu.h" #include "nfd/nfd.h" @@ -195,3 +196,19 @@ void gui_file_dialog_save_disassembler(void) Log("Save Disassembler Error: %s", NFD_GetError()); } } + +void gui_file_dialog_save_log(void) +{ + nfdchar_t *outPath; + nfdfilteritem_t filterItem[1] = { { "Log Files", "txt" } }; + nfdresult_t result = NFD_SaveDialog(&outPath, filterItem, 1, NULL, NULL); + if (result == NFD_OKAY) + { + gui_debug_save_log(outPath); + NFD_FreePath(outPath); + } + else if (result != NFD_CANCEL) + { + Log("Save Log Error: %s", NFD_GetError()); + } +} diff --git a/platforms/shared/desktop/gui_filedialogs.h b/platforms/shared/desktop/gui_filedialogs.h index 5df046b..cc65eed 100644 --- a/platforms/shared/desktop/gui_filedialogs.h +++ b/platforms/shared/desktop/gui_filedialogs.h @@ -36,6 +36,7 @@ EXTERN void gui_file_dialog_load_symbols(void); EXTERN void gui_file_dialog_save_screenshot(void); EXTERN void gui_file_dialog_save_memory_dump(void); EXTERN void gui_file_dialog_save_disassembler(void); +EXTERN void gui_file_dialog_save_log(void); #undef GUI_FILEDIALOGS_IMPORT #undef EXTERN diff --git a/src/geargrafx_core.cpp b/src/geargrafx_core.cpp index 8161662..bfdf218 100644 --- a/src/geargrafx_core.cpp +++ b/src/geargrafx_core.cpp @@ -84,22 +84,14 @@ bool GeargrafxCore::RunToVBlank(u8* frame_buffer, s16* sample_buffer, int* sampl return false; #ifndef GG_DISABLE_DISASSEMBLER - + GG_Debug_State debug_state; + bool get_debug_state = true; bool debug_enable = false; if (IsValidPointer(debug)) { debug_enable = true; m_huc6280->EnableBreakpoints(debug->stop_on_breakpoint); } - - GG_Debug_State debug_state; - debug_state.PC = m_huc6280->GetState()->PC->GetValue(); - debug_state.P = m_huc6280->GetState()->P->GetValue(); - debug_state.A = m_huc6280->GetState()->A->GetValue(); - debug_state.X = m_huc6280->GetState()->X->GetValue(); - debug_state.Y = m_huc6280->GetState()->Y->GetValue(); - debug_state.S = m_huc6280->GetState()->S->GetValue(); - debug_state.cycles = 0; #endif m_huc6260->SetBuffer(frame_buffer); @@ -109,6 +101,18 @@ bool GeargrafxCore::RunToVBlank(u8* frame_buffer, s16* sample_buffer, int* sampl do { +#ifndef GG_DISABLE_DISASSEMBLER + if (get_debug_state) + { + get_debug_state = false; + debug_state.PC = m_huc6280->GetState()->PC->GetValue(); + debug_state.P = m_huc6280->GetState()->P->GetValue(); + debug_state.A = m_huc6280->GetState()->A->GetValue(); + debug_state.X = m_huc6280->GetState()->X->GetValue(); + debug_state.Y = m_huc6280->GetState()->Y->GetValue(); + debug_state.S = m_huc6280->GetState()->S->GetValue(); + } +#endif instruction_completed = false; if (m_clock % 3 == 0) @@ -134,14 +138,9 @@ bool GeargrafxCore::RunToVBlank(u8* frame_buffer, s16* sample_buffer, int* sampl if (debug_enable && instruction_completed && IsValidPointer(m_debug_callback)) { + debug_state.cycles = *m_huc6280->GetState()->CYCLES; m_debug_callback(&debug_state); - debug_state.PC = m_huc6280->GetState()->PC->GetValue(); - debug_state.P = m_huc6280->GetState()->P->GetValue(); - debug_state.A = m_huc6280->GetState()->A->GetValue(); - debug_state.X = m_huc6280->GetState()->X->GetValue(); - debug_state.Y = m_huc6280->GetState()->Y->GetValue(); - debug_state.S = m_huc6280->GetState()->S->GetValue(); - debug_state.cycles = 0; + get_debug_state = true; } #endif // Failsafe: if the emulator is running too long, stop it diff --git a/src/huc6280.cpp b/src/huc6280.cpp index b0472ae..c977c45 100644 --- a/src/huc6280.cpp +++ b/src/huc6280.cpp @@ -46,6 +46,7 @@ HuC6280::HuC6280() m_processor_state.NMI = &m_nmi_requested; m_processor_state.IDR = &m_interrupt_disable_register; m_processor_state.IRR = &m_interrupt_request_register; + m_processor_state.CYCLES = &m_last_instruction_cycles; } HuC6280::~HuC6280() @@ -76,6 +77,7 @@ void HuC6280::Reset() ClearFlag(FLAG_BREAK); m_cycles = 0; m_clock_cycles = 0; + m_last_instruction_cycles = 0; m_irq1_asserted = false; m_irq2_asserted = false; m_nmi_requested = false; @@ -169,6 +171,8 @@ unsigned int HuC6280::Tick() m_cycles += k_huc6280_opcode_cycles[opcode]; + m_last_instruction_cycles = m_cycles; + return m_cycles; } @@ -189,7 +193,6 @@ void HuC6280::ClockTimer() m_timer_counter = m_timer_reload; m_timer_irq = true; SetBit(m_interrupt_request_register, 2); - // Debug("Timer counter underflow, IRQ, reload: %02X", m_timer_reload); } } } diff --git a/src/huc6280.h b/src/huc6280.h index b4ed174..4f74a74 100644 --- a/src/huc6280.h +++ b/src/huc6280.h @@ -66,6 +66,7 @@ class HuC6280 bool* NMI; u8* IDR; u8* IRR; + unsigned int* CYCLES; }; struct GG_Breakpoint @@ -123,6 +124,7 @@ class HuC6280 u8 m_zn_flags_lut[256]; unsigned int m_cycles; unsigned int m_clock_cycles; + unsigned int m_last_instruction_cycles; bool m_irq1_asserted; bool m_irq2_asserted; bool m_nmi_requested;