From 5cc3661437f66a80b8560061575d0de9c4f6471e Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Tue, 1 Apr 2014 00:13:36 +0300 Subject: [PATCH] Refactor emulator status reporting (and fix the statusbar doesn't update bug) --- include/core/emustatus.hpp | 45 +++++ include/platform/wxwidgets/window_mainwindow.hpp | 2 +- src/core/emustatus.cpp | 26 +++ src/core/mainloop.cpp | 244 +++++++++++------------ src/platform/wxwidgets/mainwindow.cpp | 98 +++++---- src/platform/wxwidgets/status.cpp | 144 ++++++------- 6 files changed, 316 insertions(+), 243 deletions(-) create mode 100644 include/core/emustatus.hpp create mode 100644 src/core/emustatus.cpp diff --git a/include/core/emustatus.hpp b/include/core/emustatus.hpp new file mode 100644 index 00000000..ffcc5a82 --- /dev/null +++ b/include/core/emustatus.hpp @@ -0,0 +1,45 @@ +#ifndef _emustatus__hpp__included__ +#define _emustatus__hpp__included__ + +#include +#include +#include +#include +#include "library/triplebuffer.hpp" + +struct _lsnes_status +{ + const static int pause_none; //pause: No pause. + const static int pause_normal; //pause: Normal pause. + const static int pause_break; //pause: Break pause. + const static uint64_t subframe_savepoint; //subframe: Point of save. + const static uint64_t subframe_video; //subframe: Point of video output. + + bool valid; + bool movie_valid; //The movie state variables are valid? + uint64_t curframe; //Current frame number. + uint64_t length; //Movie length. + uint64_t lag; //Lag counter. + uint64_t subframe; //Subframe number. + bool dumping; //Video dump active. + unsigned speed; //Speed% + bool saveslot_valid; //Save slot number/info valid. + uint64_t saveslot; //Save slot number. + std::u32string slotinfo; //Save slot info. + bool branch_valid; //Branch info valid? + std::u32string branch; //Current branch. + bool mbranch_valid; //Movie branch info valid? + std::u32string mbranch; //Current movie branch. + std::u32string macros; //Currently active macros. + int pause; //Pause mode. + char mode; //Movie mode: C:Corrupt, R:Readwrite, P:Readonly, F:Finished. + bool rtc_valid; //RTC time valid? + std::u32string rtc; //RTC time. + std::vector inputs; //Input display. + std::map mvars; //Memory watches. + std::map lvars; //Lua variables. +}; + +extern triplebuffer::triplebuffer<_lsnes_status> lsnes_status; + +#endif diff --git a/include/platform/wxwidgets/window_mainwindow.hpp b/include/platform/wxwidgets/window_mainwindow.hpp index 77975c27..85731f25 100644 --- a/include/platform/wxwidgets/window_mainwindow.hpp +++ b/include/platform/wxwidgets/window_mainwindow.hpp @@ -50,7 +50,7 @@ public: void menu_enable(int id, bool newstate); void menu_separator(); void handle_menu_click(wxCommandEvent& e); - void update_statusbar(const std::map& vars); + void update_statusbar(); void action_updated(); void enter_or_leave_fullscreen(bool fs); void request_rom(rom_request& req); diff --git a/src/core/emustatus.cpp b/src/core/emustatus.cpp new file mode 100644 index 00000000..64f417bb --- /dev/null +++ b/src/core/emustatus.cpp @@ -0,0 +1,26 @@ +#include "core/emustatus.hpp" + +namespace +{ + _lsnes_status statusA; + _lsnes_status statusB; + _lsnes_status statusC; + + struct init { + init() + { + statusA.valid = false; + statusB.valid = false; + statusC.valid = false; + } + } _init; +} + +const int _lsnes_status::pause_none = 0; +const int _lsnes_status::pause_normal = 1; +const int _lsnes_status::pause_break = 2; +const uint64_t _lsnes_status::subframe_savepoint = 0xFFFFFFFFFFFFFFFEULL; +const uint64_t _lsnes_status::subframe_video = 0xFFFFFFFFFFFFFFFFULL; + + +triplebuffer::triplebuffer<_lsnes_status> lsnes_status(statusA, statusB, statusC); diff --git a/src/core/mainloop.cpp b/src/core/mainloop.cpp index 380efbe3..c63f5e38 100644 --- a/src/core/mainloop.cpp +++ b/src/core/mainloop.cpp @@ -5,6 +5,7 @@ #include "core/command.hpp" #include "core/debug.hpp" #include "core/dispatch.hpp" +#include "core/emustatus.hpp" #include "core/framebuffer.hpp" #include "core/framerate.hpp" #include "core/inthread.hpp" @@ -300,7 +301,6 @@ void update_movie_state() { auto p = project_get(); bool readonly = false; - static unsigned last_controllers = 0; { uint64_t magic[4]; our_rom.region->fill_framerate_magic(magic); @@ -309,143 +309,123 @@ void update_movie_state() else voice_frame_number(0, 60.0); //Default. } - auto& _status = platform::get_emustatus(); - if(movb && !system_corrupt) { - _status.set("!frame", (stringfmt() << movb.get_movie().get_current_frame()).str()); - _status.set("!length", (stringfmt() << movb.get_movie().get_frame_count()).str()); - _status.set("!lag", (stringfmt() << movb.get_movie().get_lag_frames()).str()); - if(location_special == SPECIAL_FRAME_START) - _status.set("!subframe", "0"); - else if(location_special == SPECIAL_SAVEPOINT) - _status.set("!subframe", "S"); - else if(location_special == SPECIAL_FRAME_VIDEO) - _status.set("!subframe", "V"); - else - _status.set("!subframe", (stringfmt() << movb.get_movie().next_poll_number()).str()); - } else { - _status.set("!frame", "N/A"); - _status.set("!length", "N/A"); - _status.set("!lag", "N/A"); - _status.set("!subframe", "N/A"); - } - _status.set("!dumping", (information_dispatch::get_dumper_count() ? "Y" : "")); - if(break_pause) - _status.set("!pause", "B"); - else if(amode == ADVANCE_PAUSE) - _status.set("!pause", "P"); - else - _status.set("!pause", ""); - if(movb) { - auto& mo = movb.get_movie(); - readonly = mo.readonly_mode(); - if(system_corrupt) - _status.set("!mode", "C"); - else if(!readonly) - _status.set("!mode", "R"); - else if(mo.get_frame_count() >= mo.get_current_frame()) - _status.set("!mode", "P"); + auto& _status = lsnes_status.get_write(); + try { + if(movb && !system_corrupt) { + _status.movie_valid = true; + _status.curframe = movb.get_movie().get_current_frame(); + _status.length = movb.get_movie().get_frame_count(); + _status.lag = movb.get_movie().get_lag_frames(); + if(location_special == SPECIAL_FRAME_START) + _status.subframe = 0; + else if(location_special == SPECIAL_SAVEPOINT) + _status.subframe = _lsnes_status::subframe_savepoint; + else if(location_special == SPECIAL_FRAME_VIDEO) + _status.subframe = _lsnes_status::subframe_video; + else + _status.subframe = movb.get_movie().next_poll_number(); + } else { + _status.movie_valid = false; + _status.curframe = 0; + _status.length = 0; + _status.lag = 0; + _status.subframe = 0; + } + _status.dumping = (information_dispatch::get_dumper_count() > 0); + if(break_pause) + _status.pause = _lsnes_status::pause_break; + else if(amode == ADVANCE_PAUSE) + _status.pause = _lsnes_status::pause_normal; else - _status.set("!mode", "F"); - } else { - _status.erase("!subframe"); - } - if(jukebox_size > 0) { - int tmp = -1; - std::string sfilen = translate_name_mprefix(save_jukebox_name(save_jukebox_pointer), tmp, -1); - _status.set("!saveslot", (stringfmt() << (save_jukebox_pointer + 1)).str()); - _status.set("!saveslotinfo", get_slotinfo(sfilen)); - } else { - _status.erase("!saveslot"); - _status.erase("!saveslotinfo"); - } - if(p) { - _status.set("!branch", p->get_branch_string()); - } else { - _status.erase("!branch"); - } - { + _status.pause = _lsnes_status::pause_none; + if(movb) { + auto& mo = movb.get_movie(); + readonly = mo.readonly_mode(); + if(system_corrupt) + _status.mode = 'C'; + else if(!readonly) + _status.mode = 'R'; + else if(mo.get_frame_count() >= mo.get_current_frame()) + _status.mode = 'P'; + else + _status.mode = 'F'; + } + if(jukebox_size > 0) { + _status.saveslot_valid = true; + int tmp = -1; + std::string sfilen = translate_name_mprefix(save_jukebox_name(save_jukebox_pointer), tmp, -1); + _status.saveslot = save_jukebox_pointer + 1; + _status.slotinfo = utf8::to32(get_slotinfo(sfilen)); + } else { + _status.saveslot_valid = false; + } + _status.branch_valid = (p != NULL); + if(p) _status.branch = utf8::to32(p->get_branch_string()); + std::string cur_branch = movb ? movb.get_mfile().current_branch() : ""; - if(cur_branch != "") - _status.set("!mbranch", cur_branch); - else - _status.erase("!mbranch"); - } - _status.set("!speed", (stringfmt() << (unsigned)(100 * get_realized_multiplier() + 0.5)).str()); - - if(movb && !system_corrupt) { - time_t timevalue = static_cast(movb.get_mfile().rtc_second); - struct tm* time_decompose = gmtime(&timevalue); - char datebuffer[512]; - strftime(datebuffer, 511, "%Y%m%d(%a)T%H%M%S", time_decompose); - _status.set("RTC", datebuffer); - } else { - _status.erase("RTC"); - } + _status.mbranch_valid = (cur_branch != ""); + _status.mbranch = utf8::to32(cur_branch); + + _status.speed = (unsigned)(100 * get_realized_multiplier() + 0.5); + + if(movb && !system_corrupt) { + time_t timevalue = static_cast(movb.get_mfile().rtc_second); + struct tm* time_decompose = gmtime(&timevalue); + char datebuffer[512]; + strftime(datebuffer, 511, "%Y%m%d(%a)T%H%M%S", time_decompose); + _status.rtc = utf8::to32(datebuffer); + _status.rtc_valid = true; + } else { + _status.rtc_valid = false; + } - auto mset = controls.active_macro_set(); - bool mfirst = true; - std::ostringstream mss; - for(auto i: mset) { - if(!mfirst) mss << ","; - mss << i; - mfirst = false; - } - _status.set("!macros", mss.str()); - - controller_frame c; - if(!multitrack_editor.any_records()) - c = movb.get_movie().get_controls(); - else - c = controls.get_committed(); - for(unsigned i = 0;; i++) { - auto pindex = controls.lcid_to_pcid(i); - if(pindex.first < 0 || !controls.is_present(pindex.first, pindex.second)) { - for(unsigned j = i; j < last_controllers; j++) - _status.erase((stringfmt() << "P" << (j + 1)).str()); - last_controllers = i; - break; + auto mset = controls.active_macro_set(); + bool mfirst = true; + std::ostringstream mss; + for(auto i: mset) { + if(!mfirst) mss << ","; + mss << i; + mfirst = false; } - char32_t buffer[MAX_DISPLAY_LENGTH]; - c.display(pindex.first, pindex.second, buffer); - std::u32string _buffer = buffer; - if(readonly && multitrack_editor.is_enabled()) { - multitrack_edit::state st = multitrack_editor.get(pindex.first, pindex.second); - if(st == multitrack_edit::MT_PRESERVE) - _buffer += U" (keep)"; - else if(st == multitrack_edit::MT_OVERWRITE) - _buffer += U" (rewrite)"; - else if(st == multitrack_edit::MT_OR) - _buffer += U" (OR)"; - else if(st == multitrack_edit::MT_XOR) - _buffer += U" (XOR)"; - else - _buffer += U" (\?\?\?)"; + _status.macros = utf8::to32(mss.str()); + + controller_frame c; + if(!multitrack_editor.any_records()) + c = movb.get_movie().get_controls(); + else + c = controls.get_committed(); + _status.inputs.clear(); + for(unsigned i = 0;; i++) { + auto pindex = controls.lcid_to_pcid(i); + if(pindex.first < 0 || !controls.is_present(pindex.first, pindex.second)) + break; + char32_t buffer[MAX_DISPLAY_LENGTH]; + c.display(pindex.first, pindex.second, buffer); + std::u32string _buffer = buffer; + if(readonly && multitrack_editor.is_enabled()) { + multitrack_edit::state st = multitrack_editor.get(pindex.first, pindex.second); + if(st == multitrack_edit::MT_PRESERVE) + _buffer += U" (keep)"; + else if(st == multitrack_edit::MT_OVERWRITE) + _buffer += U" (rewrite)"; + else if(st == multitrack_edit::MT_OR) + _buffer += U" (OR)"; + else if(st == multitrack_edit::MT_XOR) + _buffer += U" (XOR)"; + else + _buffer += U" (\?\?\?)"; + } + _status.inputs.push_back(_buffer); } - _status.set((stringfmt() << "P" << (i + 1)).str(), _buffer); - } - //Lua variables. - { - static std::map old_luavars; - auto& lvars = get_lua_watch_vars(); - for(auto i : old_luavars) - if(!lvars.count(i.first)) - _status.erase("L[" + i.first + "]"); - for(auto i : lvars) - _status.set("L[" + i.first + "]", i.second); - old_luavars = lvars; - } - //Memory watches. - { - static std::map old_memvars; - auto& mvars = lsnes_memorywatch.get_window_vars(); - for(auto i : old_memvars) - if(!mvars.count(i.first)) - _status.erase("M[" + i.first + "]"); - for(auto i : mvars) - _status.set("M[" + i.first + "]", i.second); - old_memvars = mvars; + //Lua variables. + _status.lvars = get_lua_watch_vars(); + //Memory watches. + _status.mvars = lsnes_memorywatch.get_window_vars(); + + _status.valid = true; + } catch(...) { } - + lsnes_status.put_write(); notify_status_update(); } diff --git a/src/platform/wxwidgets/mainwindow.cpp b/src/platform/wxwidgets/mainwindow.cpp index 7c8ef66d..42e2a875 100644 --- a/src/platform/wxwidgets/mainwindow.cpp +++ b/src/platform/wxwidgets/mainwindow.cpp @@ -19,6 +19,7 @@ #include "core/controller.hpp" #include "core/controllerframe.hpp" #include "core/dispatch.hpp" +#include "core/emustatus.hpp" #include "core/framebuffer.hpp" #include "core/framerate.hpp" #include "core/keymapper.hpp" @@ -215,7 +216,7 @@ namespace void Notify() { if(w->download_in_progress->finished) { - w->update_statusbar(std::map()); + w->update_statusbar(); auto old = w->download_in_progress; w->download_in_progress = NULL; if(old->errormsg != "") { @@ -228,7 +229,7 @@ namespace Stop(); delete this; } else { - w->update_statusbar(std::map()); + w->update_statusbar(); } } private: @@ -1235,6 +1236,7 @@ void wxwin_mainwindow::notify_update_status() throw() spanel->request_paint(); if(mwindow) mwindow->notify_update(); + update_statusbar(); } void wxwin_mainwindow::notify_exit() throw() @@ -1244,14 +1246,14 @@ void wxwin_mainwindow::notify_exit() throw() Destroy(); } -std::u32string read_variable_map(const std::map& vars, const std::string& key) +std::string read_variable_map(const std::map& vars, const std::string& key) { if(!vars.count(key)) - return U""; - return vars.find(key)->second; + return ""; + return utf8::to8(vars.find(key)->second); } -void wxwin_mainwindow::update_statusbar(const std::map& vars) +void wxwin_mainwindow::update_statusbar() { if(download_in_progress) { statusbar->SetStatusText(towxstring(download_in_progress->statusmsg())); @@ -1265,52 +1267,62 @@ void wxwin_mainwindow::update_statusbar(const std::mapSetStatusText(towxstring(s.str())); return; } - if(vars.empty()) + auto& vars = lsnes_status.get_read(); + if(!vars.valid) { + lsnes_status.put_read(); return; + } try { - std::basic_ostringstream s; - bool recording = (read_variable_map(vars, "!mode") == U"R"); - if(recording) - s << U"Frame: " << read_variable_map(vars, "!frame"); - else - s << U"Frame: " << read_variable_map(vars, "!frame") << U"/" << - read_variable_map(vars, "!length"); - s << U" Lag: " << read_variable_map(vars, "!lag"); - s << U" Subframe: " << read_variable_map(vars, "!subframe"); - if(vars.count("!saveslot")) { - s << U" Slot: "; - if(vars.count("!branch")) s << read_variable_map(vars, "!branch") << U"→"; - s << read_variable_map(vars, "!saveslot"); + std::ostringstream s; + bool recording = (vars.mode == 'R'); + if(vars.movie_valid) { + if(recording) + s << "Frame: " << vars.curframe; + else + s << "Frame: " << vars.curframe << "/" << vars.length; + s << " Lag: " << vars.lag; + if(vars.subframe == _lsnes_status::subframe_savepoint) + s << " Subframe: S"; + else if(vars.subframe == _lsnes_status::subframe_video) + s << " Subframe: V"; + else + s << " Subframe: " << vars.subframe; + } else { + s << "Frame: N/A Lag: N/A Subframe: N/A"; + } + if(vars.saveslot_valid) { + s << " Slot: "; + if(vars.branch_valid) s << utf8::to8(vars.branch) << "→"; + s << vars.saveslot; + s << " [" << utf8::to8(vars.slotinfo) << "]"; } - if(vars.count("!saveslotinfo")) - s << U" [" << read_variable_map(vars, "!saveslotinfo") << U"]"; - s << U" Speed: " << read_variable_map(vars, "!speed") << U"%"; - s << U" "; - if(read_variable_map(vars, "!pause") == U"B") - s << U" Breakpoint"; - else if(read_variable_map(vars, "!pause") == U"P") - s << U" Paused"; - if(read_variable_map(vars, "!dumping") != U"") - s << U" Dumping"; - if(read_variable_map(vars, "!mode") == U"C") - s << U" Corrupt"; - else if(read_variable_map(vars, "!mode") == U"R") - s << U" Recording"; - else if(read_variable_map(vars, "!mode") == U"P") - s << U" Playback"; - else if(read_variable_map(vars, "!mode") == U"F") - s << U" Finished"; + s << " Speed: " << vars.speed << "% "; + if(vars.pause == _lsnes_status::pause_break) + s << " Breakpoint"; + else if(vars.pause == _lsnes_status::pause_normal) + s << " Paused"; + if(vars.dumping) + s << " Dumping"; + if(vars.mode == 'C') + s << " Corrupt"; + else if(vars.mode == 'R') + s << " Recording"; + else if(vars.mode == 'P') + s << " Playback"; + else if(vars.mode == 'F') + s << " Finished"; else - s << U" Unknown"; - if(vars.count("!mbranch")) - s << U" Branch: " << read_variable_map(vars, "!mbranch"); - std::u32string macros = read_variable_map(vars, "!macros"); + s << " Unknown"; + if(vars.mbranch_valid) + s << " Branch: " << utf8::to8(vars.mbranch); + std::string macros = utf8::to8(vars.macros); if(macros.length()) - s << U" Macros: " << macros; + s << " Macros: " << macros; statusbar->SetStatusText(towxstring(s.str())); } catch(std::exception& e) { } + lsnes_status.put_read(); } #define NEW_KEYBINDING "A new binding..." diff --git a/src/platform/wxwidgets/status.cpp b/src/platform/wxwidgets/status.cpp index e51562b0..589dbef8 100644 --- a/src/platform/wxwidgets/status.cpp +++ b/src/platform/wxwidgets/status.cpp @@ -1,3 +1,4 @@ +#include "core/emustatus.hpp" #include "core/window.hpp" #include "platform/wxwidgets/platform.hpp" #include "platform/wxwidgets/window_status.hpp" @@ -43,83 +44,92 @@ wxwin_status::~wxwin_status() { } -void wxwin_status::panel::prepare_paint() +namespace { - //Quickly copy the status area. - auto& s = platform::get_emustatus(); - std::map newstatus; - emulator_status::iterator i = s.first(); - while(s.next(i)) - newstatus[i.key] = i.value; + void register_entry(size_t& count, size_t& width, const std::string& text) + { + width = max(width, text_framebuffer::text_width(text)); + count++; + } + + void show_entry(text_framebuffer_panel& tp, bool& sofar, size_t& line, size_t width, const std::string& name, + const std::u32string& text) + { + size_t n = tp.write(name, width + 1, 0, line, 0, 0xFFFFFF); + tp.write(text, 0, n, line++, 0, 0xFFFFFF); + sofar = true; + } + + void draw_split(text_framebuffer_panel& tp, size_t& line) + { + auto s = tp.get_characters(); + for(unsigned i = 0; i < s.first; i++) + tp.write(U"\u2500", 0, i, line, 0, 0xFFFFFF); + line++; + } + + int num_nonzeroes() { return 0; } + template int num_nonzeroes(T hd, U... tl) { + return (hd ? 1 : 0) + num_nonzeroes(tl...); + } + template bool one_nonzero(T... args) { return (num_nonzeroes(args...) == 1); } +} +void wxwin_status::panel::prepare_paint() +{ clear(); - size_t mem_width = 0; - size_t oth_width = 0; - size_t mem_count = 0; - size_t oth_count = 0; - bool single = false; - for(auto i : newstatus) { - if(i.first.length() > 0 && i.first[0] == '!') - continue; - bool x = regex_match("M\\[.*\\]", i.first); - if(x) { - mem_width = max(mem_width, text_framebuffer::text_width(i.first) - 3); - mem_count++; - } else { - oth_width = max(oth_width, text_framebuffer::text_width(i.first)); - oth_count++; + auto& newstatus = lsnes_status.get_read(); + try { + bool entry_so_far = false; + size_t mem_width = 0; + size_t oth_width = 0; + size_t lua_width = 0; + size_t mem_count = 0; + size_t oth_count = 0; + size_t lua_count = 0; + bool single = false; + for(auto& i : newstatus.mvars) register_entry(mem_count, mem_width, i.first); + if(newstatus.rtc_valid) register_entry(oth_count, oth_width, "RTC"); + for(size_t j = 0; j < newstatus.inputs.size(); j++) + register_entry(oth_count, oth_width, (stringfmt() << "P" << (j + 1)).str()); + for(auto& i : newstatus.lvars) register_entry(lua_count, lua_width, i.first); + + if(watch_flag < 0) { + oth_count = 0; + lua_count = 0; } - } - if(watch_flag < 0) - oth_count = 0; - if(watch_flag > 0) - mem_count = 0; - if(!oth_count || !mem_count) - single = true; - - regex_results r; - size_t p = 0; - if(mem_count) { - if(!single) - write("Memory watches:", 0, 0, p++, 0, 0xFFFFFF); - for(auto i : newstatus) { - if(i.first.length() > 0 && i.first[0] == '!') - continue; - if(r = regex("M\\[(.*)\\]", i.first)) { - size_t n = write(r[1], mem_width + 1, 0, p, 0, 0xFFFFFF); - write(i.second, 0, n, p++, 0, 0xFFFFFF); - } + if(watch_flag > 0) + mem_count = 0; + single = one_nonzero(mem_count, oth_count, lua_count); + + regex_results r; + size_t p = 0; + if(mem_count) { + if(entry_so_far) draw_split(*this, p); + if(!single) write("Memory watches:", 0, 0, p++, 0, 0xFFFFFF); + for(auto i : newstatus.mvars) show_entry(*this, entry_so_far, p, mem_width, i.first, + i.second); } - } - if(mem_count && oth_count) { - auto s = get_characters(); - for(unsigned i = 0; i < s.first; i++) - write(U"\u2500", 0, i, p, 0, 0xFFFFFF); - p++; - } - if(oth_count) { - if(!single) - write("Status:", 0, 0, p++, 0, 0xFFFFFF); - for(auto i : newstatus) { - if(i.first.length() > 0 && i.first[0] == '!') - continue; - if(regex_match("M\\[.*\\]", i.first)) - continue; - size_t n = write(i.first, oth_width + 1, 0, p, 0, 0xFFFFFF); - write(i.second, 0, n, p++, 0, 0xFFFFFF); + if(oth_count) { + if(entry_so_far) draw_split(*this, p); + if(!single) write("Status:", 0, 0, p++, 0, 0xFFFFFF); + if(newstatus.rtc_valid) show_entry(*this, entry_so_far, p, oth_width, "RTC", newstatus.rtc); + for(size_t j = 0; j < newstatus.inputs.size(); j++) + show_entry(*this, entry_so_far, p, oth_width, (stringfmt() << "P" << (j + 1)).str(), + newstatus.inputs[j]); } - } - { - std::map specials; - for(auto i : newstatus) - if(i.first.length() > 0 && i.first[0] == '!') - specials[i.first] = i.second; - main_window->update_statusbar(specials); + if(lua_count) { + if(entry_so_far) draw_split(*this, p); + if(!single) write("From Lua:", 0, 0, p++, 0, 0xFFFFFF); + for(auto i : newstatus.lvars) show_entry(*this, entry_so_far, p, lua_width, i.first, + i.second); + } + } catch(...) { } - + lsnes_status.put_read(); } void wxwin_status::notify_update() throw() -- 2.11.4.GIT