From e10a2fcfe5e8b82df79e2556ec6f8d305fffb7a8 Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Thu, 1 May 2014 04:12:15 +0300 Subject: [PATCH] Trace logger (Window): Show start of frame --- include/core/debug.hpp | 4 ++++ src/core/debug.cpp | 37 +++++++++++++++++++++++++++++++--- src/core/mainloop.cpp | 2 ++ src/platform/wxwidgets/tracelogger.cpp | 22 ++++++++++++++++++++ 4 files changed, 62 insertions(+), 3 deletions(-) diff --git a/include/core/debug.hpp b/include/core/debug.hpp index 5dab1093..786b234c 100644 --- a/include/core/debug.hpp +++ b/include/core/debug.hpp @@ -15,6 +15,7 @@ enum debug_type DEBUG_WRITE, DEBUG_EXEC, DEBUG_TRACE, + DEBUG_FRAME, }; extern const uint64_t debug_all_addr; @@ -23,11 +24,14 @@ debug_handle debug_add_callback(uint64_t addr, debug_type type, std::function fn, std::function dtor); debug_handle debug_add_trace_callback(uint64_t proc, std::function fn, std::function dtor); +debug_handle debug_add_frame_callback(std::function fn, + std::function dtor); void debug_remove_callback(uint64_t addr, debug_type type, debug_handle handle); void debug_fire_callback_read(uint64_t addr, uint64_t value); void debug_fire_callback_write(uint64_t addr, uint64_t value); void debug_fire_callback_exec(uint64_t addr, uint64_t value); void debug_fire_callback_trace(uint64_t proc, const char* str, bool true_insn = true); +void debug_fire_callback_frame(uint64_t frame, bool loadstate); void debug_set_cheat(uint64_t addr, uint64_t value); void debug_clear_cheat(uint64_t addr); void debug_setxmask(uint64_t mask); diff --git a/src/core/debug.cpp b/src/core/debug.cpp index c0626c52..32ce481f 100644 --- a/src/core/debug.cpp +++ b/src/core/debug.cpp @@ -22,14 +22,22 @@ namespace std::function cb; std::function dtor; }; + struct cb_frame + { + std::function cb; + std::function dtor; + }; typedef std::list cb_list; typedef std::list cb2_list; + typedef std::list cb3_list; std::map read_cb; std::map write_cb; std::map exec_cb; std::map trace_cb; + std::map frame_cb; cb_list dummy_cb; //Always empty. cb2_list dummy_cb2; //Always empty. + cb3_list dummy_cb3; //Always empty. uint64_t xmask = 1; std::function tracelog_change_cb; struct dispatch::target<> corechange; @@ -61,6 +69,7 @@ namespace case DEBUG_WRITE: return 2; case DEBUG_EXEC: return 4; case DEBUG_TRACE: return 8; + case DEBUG_FRAME: return 0; default: throw std::runtime_error("Invalid debug callback type"); } } @@ -77,7 +86,7 @@ namespace corechange.set(notify_core_change, []() { debug_core_change(); }); corechange_r = true; } - if(!cb.count(addr)) + if(!cb.count(addr) && type != DEBUG_FRAME) our_rom.rtype->set_debug_flags(addr, debug_flag(type), 0); auto& lst = cb[addr]; @@ -99,7 +108,8 @@ namespace } if(cb[addr].empty()) { cb.erase(addr); - our_rom.rtype->set_debug_flags(addr, 0, debug_flag(type)); + if(type != DEBUG_FRAME) + our_rom.rtype->set_debug_flags(addr, 0, debug_flag(type)); } } @@ -136,9 +146,20 @@ debug_handle debug_add_trace_callback(uint64_t proc, std::function fn, + std::function dtor) +{ + cb_frame t; + t.cb = fn; + t.dtor = dtor; + return _debug_add_callback(frame_cb, 0, DEBUG_FRAME, t, dtor); +} + void debug_remove_callback(uint64_t addr, debug_type type, debug_handle handle) { - if(type == DEBUG_TRACE) { + if(type == DEBUG_FRAME) { + _debug_remove_callback(frame_cb, 0, DEBUG_FRAME, handle); + } else if(type == DEBUG_TRACE) { _debug_remove_callback(trace_cb, addr, DEBUG_TRACE, handle); } else { _debug_remove_callback(get_lists(type), addr, type, handle); @@ -195,6 +216,13 @@ void debug_fire_callback_trace(uint64_t proc, const char* str, bool true_insn) do_break_pause(); } +void debug_fire_callback_frame(uint64_t frame, bool loadstate) +{ + cb3_list* cb = frame_cb.count(0) ? &frame_cb[0] : &dummy_cb3; + auto _cb = *cb; + for(auto& i : _cb) i.cb(frame, loadstate); +} + void debug_set_cheat(uint64_t addr, uint64_t value) { our_rom.rtype->set_cheat(addr, value, true); @@ -295,6 +323,9 @@ namespace for(auto& i : trace_cb) for(auto& j : i.second) messages << "TRACE proc=" << i.first << " handle=" << &j << std::endl; + for(auto& i : frame_cb) + for(auto& j : i.second) + messages << "FRAME handle=" << &j << std::endl; }); command::fnptr generate_event(lsnes_cmd, "generate-memory-event", "", "", diff --git a/src/core/mainloop.cpp b/src/core/mainloop.cpp index 6ffa84c6..e65ff850 100644 --- a/src/core/mainloop.cpp +++ b/src/core/mainloop.cpp @@ -1292,6 +1292,7 @@ void main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_ stop_at_frame_active = false; just_did_loadstate = first_round; controls.reset_framehold(); + debug_fire_callback_frame(movb.get_movie().get_current_frame(), true); continue; } else if(r < 0) { //Not exactly desriable, but this at least won't desync. @@ -1313,6 +1314,7 @@ void main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_ just_did_loadstate = false; } frame_irq_time = get_utime() - time_x; + debug_fire_callback_frame(movb.get_movie().get_current_frame(), false); our_rom.rtype->emulate(); random_mix_timing_entropy(); time_x = get_utime(); diff --git a/src/platform/wxwidgets/tracelogger.cpp b/src/platform/wxwidgets/tracelogger.cpp index 87048df2..494463d9 100644 --- a/src/platform/wxwidgets/tracelogger.cpp +++ b/src/platform/wxwidgets/tracelogger.cpp @@ -543,6 +543,7 @@ namespace int cpuid; volatile bool trace_active; debug_handle trace_handle; + debug_handle trace_handle_frame; void do_rwx_break(uint64_t addr, uint64_t value, debug_type type); void kill_debug_hooks(); scroll_bar* scroll; @@ -585,6 +586,7 @@ namespace void wxwin_tracelog::kill_debug_hooks() { debug_remove_callback(cpuid, DEBUG_TRACE, trace_handle); + debug_remove_callback(cpuid, DEBUG_FRAME, trace_handle_frame); threads::alock h(buffer_mutex); for(auto& i : rwx_breakpoints) { if(!i.second.handle) @@ -754,6 +756,26 @@ namespace tmp->m_singlestep->Enable(false); }); }); + this->trace_handle_frame = debug_add_frame_callback([this](uint64_t frame, + bool loadstate) { + std::ostringstream xstr; + xstr << "------------ "; + xstr << "Frame " << frame; + if(loadstate) xstr << " (loadstated)"; + xstr << " ------------"; + std::string str = xstr.str(); + threads::alock h(this->buffer_mutex); + lines_waiting.push_back(str); + if(!this->unprocessed_lines) { + this->unprocessed_lines = true; + runuifun([this]() { this->process_lines(); }); + } + }, [this]() { + auto tmp = this; + if(!tmp->trace_active) + return; + debug_remove_callback(0, DEBUG_TRACE, trace_handle_frame); + }); this->trace_active = true; } else if(trace_active) { this->trace_active = false; -- 2.11.4.GIT