Trace logger (Window): Show start of frame

This commit is contained in:
Ilari Liusvaara 2014-05-01 04:12:15 +03:00
parent 6fc0cf9cf6
commit e10a2fcfe5
4 changed files with 62 additions and 3 deletions

View file

@ -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<void(uint64_t addr, uint64_t value)> fn, std::function<void()> dtor);
debug_handle debug_add_trace_callback(uint64_t proc, std::function<void(uint64_t proc, const char* str,
bool true_insn)> fn, std::function<void()> dtor);
debug_handle debug_add_frame_callback(std::function<void(uint64_t frame, bool loadstate)> fn,
std::function<void()> 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);

View file

@ -22,14 +22,22 @@ namespace
std::function<void(uint64_t proc, const char* str, bool true_insn)> cb;
std::function<void()> dtor;
};
struct cb_frame
{
std::function<void(uint64_t frame, bool loadstate)> cb;
std::function<void()> dtor;
};
typedef std::list<cb_rwx> cb_list;
typedef std::list<cb_trace> cb2_list;
typedef std::list<cb_frame> cb3_list;
std::map<uint64_t, cb_list> read_cb;
std::map<uint64_t, cb_list> write_cb;
std::map<uint64_t, cb_list> exec_cb;
std::map<uint64_t, cb2_list> trace_cb;
std::map<uint64_t, cb3_list> 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<void()> 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<void(uint64_t
return _debug_add_callback(trace_cb, proc, DEBUG_TRACE, t, dtor);
}
debug_handle debug_add_frame_callback(std::function<void(uint64_t frame, bool loadstate)> fn,
std::function<void()> 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<const std::string&> generate_event(lsnes_cmd, "generate-memory-event", "", "",

View file

@ -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();

View file

@ -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;