diff options
Diffstat (limited to 'src/osd/modules/debugger/debugwin.cpp')
-rw-r--r-- | src/osd/modules/debugger/debugwin.cpp | 291 |
1 files changed, 257 insertions, 34 deletions
diff --git a/src/osd/modules/debugger/debugwin.cpp b/src/osd/modules/debugger/debugwin.cpp index 975e7ba6bc6..8ff26d40fb3 100644 --- a/src/osd/modules/debugger/debugwin.cpp +++ b/src/osd/modules/debugger/debugwin.cpp @@ -2,13 +2,12 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// debugwin.c - Win32 debug window handling +// debugwin.cpp - Win32 debug window handling // //============================================================ #include "emu.h" #include "debug_module.h" -#include "modules/osdmodule.h" #if defined(OSD_WINDOWS) /*|| defined(SDLMAME_WIN32)*/ @@ -22,31 +21,50 @@ #include "win/pointswininfo.h" #include "win/uimetrics.h" +// emu +#include "config.h" #include "debugger.h" #include "debug/debugcpu.h" +#include "util/xmlfile.h" + +// osd/windows #include "window.h" -#include "../input/input_common.h" -#include "../input/input_windows.h" +#include "winmain.h" + +#include "../input/input_windows.h" // for the keyboard translation table + +namespace osd { -class debugger_windows : public osd_module, public debug_module, protected debugger_windows_interface +namespace { + +class debugger_windows : + public osd_module, + public debug_module, + protected debugger::win::debugger_windows_interface { public: debugger_windows() : osd_module(OSD_DEBUG_PROVIDER, "windows"), debug_module(), + m_osd(nullptr), m_machine(nullptr), m_metrics(), m_waiting_for_debugger(false), m_window_list(), - m_main_console(nullptr) + m_main_console(nullptr), + m_next_window_pos{ 0, 0 }, + m_config(), + m_save_windows(true), + m_group_windows(true), + m_group_windows_setting(true) { } virtual ~debugger_windows() { } - virtual int init(const osd_options &options) override { return 0; } + virtual int init(osd_interface &osd, osd_options const &options) override; virtual void exit() override; virtual void init_debugger(running_machine &machine) override; @@ -56,31 +74,63 @@ public: protected: virtual running_machine &machine() const override { return *m_machine; } - virtual ui_metrics &metrics() const override { return *m_metrics; } + virtual debugger::win::ui_metrics &metrics() const override { return *m_metrics; } + virtual void set_color_theme(int index) override; + virtual bool get_save_window_arrangement() const override { return m_save_windows; } + virtual void set_save_window_arrangement(bool save) override { m_save_windows = save; } + virtual bool get_group_windows() const override { return m_group_windows; } + virtual bool get_group_windows_setting() const override { return m_group_windows_setting; } + virtual void set_group_windows_setting(bool group) override { m_group_windows_setting = group; } virtual bool const &waiting_for_debugger() const override { return m_waiting_for_debugger; } virtual bool seq_pressed() const override; - virtual void create_memory_window() override { create_window<memorywin_info>(); } - virtual void create_disasm_window() override { create_window<disasmwin_info>(); } - virtual void create_log_window() override { create_window<logwin_info>(); } - virtual void create_points_window() override { create_window<pointswin_info>(); } - virtual void remove_window(debugwin_info &info) override; + virtual void create_memory_window() override { create_window<debugger::win::memorywin_info>(); } + virtual void create_disasm_window() override { create_window<debugger::win::disasmwin_info>(); } + virtual void create_log_window() override { create_window<debugger::win::logwin_info>(); } + virtual void create_points_window() override { create_window<debugger::win::pointswin_info>(); } + virtual void remove_window(debugger::win::debugwin_info &info) override; virtual void show_all() override; virtual void hide_all() override; + virtual void stagger_window(HWND window, int width, int height) override; + private: template <typename T> T *create_window(); - running_machine *m_machine; - std::unique_ptr<ui_metrics> m_metrics; - bool m_waiting_for_debugger; - std::vector<std::unique_ptr<debugwin_info>> m_window_list; - consolewin_info *m_main_console; + void config_load(config_type cfgtype, config_level cfglevel, util::xml::data_node const *parentnode); + void config_save(config_type cfgtype, util::xml::data_node *parentnode); + + void load_configuration(util::xml::data_node const &parentnode); + + windows_osd_interface *m_osd; + running_machine *m_machine; + std::unique_ptr<debugger::win::ui_metrics> m_metrics; + bool m_waiting_for_debugger; + std::vector<std::unique_ptr<debugger::win::debugwin_info> > m_window_list; + debugger::win::consolewin_info *m_main_console; + + POINT m_next_window_pos; + LONG m_window_start_x; + + util::xml::file::ptr m_config; + bool m_save_windows; + bool m_group_windows; + bool m_group_windows_setting; }; +int debugger_windows::init(osd_interface &osd, osd_options const &options) +{ + m_osd = dynamic_cast<windows_osd_interface *>(&osd); + if (!m_osd) + return -1; + + return 0; +} + + void debugger_windows::exit() { // loop over windows and free them @@ -96,23 +146,52 @@ void debugger_windows::exit() void debugger_windows::init_debugger(running_machine &machine) { m_machine = &machine; - m_metrics = std::make_unique<ui_metrics>(downcast<osd_options &>(m_machine->options())); + m_metrics = std::make_unique<debugger::win::ui_metrics>(downcast<osd_options &>(m_machine->options())); + machine.configuration().config_register( + "debugger", + configuration_manager::load_delegate(&debugger_windows::config_load, this), + configuration_manager::save_delegate(&debugger_windows::config_save, this)); } void debugger_windows::wait_for_debugger(device_t &device, bool firststop) { // create a console window - if (m_main_console == nullptr) - m_main_console = create_window<consolewin_info>(); + if (!m_main_console) + { + m_main_console = create_window<debugger::win::consolewin_info>(); + + // set the starting position for new auxiliary windows + HMONITOR const nearest_monitor = MonitorFromWindow( + dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window(), + MONITOR_DEFAULTTONEAREST); + if (nearest_monitor) + { + MONITORINFO info; + std::memset(&info, 0, sizeof(info)); + info.cbSize = sizeof(info); + if (GetMonitorInfo(nearest_monitor, &info)) + { + m_next_window_pos.x = info.rcWork.left + 100; + m_next_window_pos.y = info.rcWork.top + 100; + m_window_start_x = m_next_window_pos.x; + } + } + } // update the views in the console to reflect the current CPU - if (m_main_console != nullptr) + if (m_main_console) m_main_console->set_cpu(device); // when we are first stopped, adjust focus to us - if (firststop && (m_main_console != nullptr)) + if (firststop && m_main_console) { + if (m_config) + { + for (util::xml::data_node const *node = m_config->get_first_child(); node; node = node->get_next_sibling()) + load_configuration(*node); + m_config.reset(); + } m_main_console->set_foreground(); if (winwindow_has_focus()) m_main_console->set_default_focus(); @@ -123,7 +202,7 @@ void debugger_windows::wait_for_debugger(device_t &device, bool firststop) show_all(); // run input polling to ensure that our status is in sync - downcast<windows_osd_interface&>(machine().osd()).poll_input(*m_machine); + downcast<windows_osd_interface&>(machine().osd()).poll_input_modules(false); // get and process messages MSG message; @@ -142,7 +221,7 @@ void debugger_windows::wait_for_debugger(device_t &device, bool firststop) // process everything else default: - winwindow_dispatch_message(*m_machine, &message); + winwindow_dispatch_message(*m_machine, message); break; } @@ -161,7 +240,7 @@ void debugger_windows::debugger_update() { HWND const focuswnd = GetFocus(); - m_machine->debugger().cpu().get_visible_cpu()->debug()->halt_on_next_instruction("User-initiated break\n"); + m_machine->debugger().debug_break(); // if we were focused on some window's edit box, reset it to default for (auto &info : m_window_list) @@ -171,6 +250,14 @@ void debugger_windows::debugger_update() } +void debugger_windows::set_color_theme(int index) +{ + m_metrics->set_color_theme(index); + for (auto const &window : m_window_list) + window->redraw(); +} + + bool debugger_windows::seq_pressed() const { input_seq const &seq = m_machine->ioport().type_seq(IPT_UI_DEBUG_BREAK); @@ -222,7 +309,7 @@ bool debugger_windows::seq_pressed() const } -void debugger_windows::remove_window(debugwin_info &info) +void debugger_windows::remove_window(debugger::win::debugwin_info &info) { for (auto it = m_window_list.begin(); it != m_window_list.end(); ++it) if (it->get() == &info) { @@ -241,28 +328,164 @@ void debugger_windows::show_all() void debugger_windows::hide_all() { - SetForegroundWindow(std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window()); + SetForegroundWindow(dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window()); for (auto &info : m_window_list) info->hide(); } -template <typename T> T *debugger_windows::create_window() +void debugger_windows::stagger_window(HWND window, int width, int height) +{ + // get width/height for client size + RECT target; + target.left = 0; + target.top = 0; + target.right = width; + target.bottom = height; + if (!AdjustWindowRectEx(&target, GetWindowLong(window, GWL_STYLE), GetMenu(window) ? TRUE : FALSE,GetWindowLong(window, GWL_EXSTYLE))) + { + // really shouldn't end up here, but have to do something + SetWindowPos(window, HWND_TOP, m_next_window_pos.x, m_next_window_pos.y, width, height, SWP_SHOWWINDOW); + return; + } + target.right -= target.left; + target.bottom -= target.top; + target.left = target.top = 0; + + // get the work area for the nearest monitor to the target position + HMONITOR const mon = MonitorFromPoint(m_next_window_pos, MONITOR_DEFAULTTONEAREST); + if (mon) + { + MONITORINFO info; + std::memset(&info, 0, sizeof(info)); + info.cbSize = sizeof(info); + if (GetMonitorInfo(mon, &info)) + { + // restart cascade if necessary + if (((m_next_window_pos.x + target.right) > info.rcWork.right) || ((m_next_window_pos.y + target.bottom) > info.rcWork.bottom)) + { + m_next_window_pos.x = m_window_start_x += 16; + m_next_window_pos.y = info.rcWork.top + 100; + if ((m_next_window_pos.x + target.right) > info.rcWork.right) + m_next_window_pos.x = m_window_start_x = info.rcWork.left + 100; + } + } + } + + // move the window and adjust the next position + MoveWindow(window, m_next_window_pos.x, m_next_window_pos.y, target.right, target.bottom, FALSE); + SetWindowPos(window, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW); + m_next_window_pos.x += 16; + m_next_window_pos.y += 16; +} + + +template <typename T> +T *debugger_windows::create_window() { // allocate memory std::unique_ptr<T> info = std::make_unique<T>(static_cast<debugger_windows_interface &>(*this)); if (info->is_valid()) { + T &result(*info); m_window_list.push_back(std::move(info)); - T *ptr = dynamic_cast<T*>(m_window_list.back().get()); - return ptr; + return &result; } return nullptr; } -#else /* not windows */ -MODULE_NOT_SUPPORTED(debugger_windows, OSD_DEBUG_PROVIDER, "windows") +void debugger_windows::config_load(config_type cfgtype, config_level cfglevel, util::xml::data_node const *parentnode) +{ + if (parentnode) + { + if (config_type::DEFAULT == cfgtype) + { + m_save_windows = 0 != parentnode->get_attribute_int(debugger::ATTR_DEBUGGER_SAVE_WINDOWS, m_save_windows ? 1 : 0); + m_group_windows = m_group_windows_setting = 0 != parentnode->get_attribute_int(debugger::ATTR_DEBUGGER_GROUP_WINDOWS, m_group_windows ? 1 : 0); + util::xml::data_node const *const colors = parentnode->get_child(debugger::NODE_COLORS); + if (colors) + m_metrics->set_color_theme(colors->get_attribute_int(debugger::ATTR_COLORS_THEME, m_metrics->get_color_theme())); + } + else if (config_type::SYSTEM == cfgtype) + { + if (m_main_console) + { + load_configuration(*parentnode); + } + else + { + if (!m_config) + m_config = util::xml::file::create(); + parentnode->copy_into(*m_config); + } + } + } +} + + +void debugger_windows::config_save(config_type cfgtype, util::xml::data_node *parentnode) +{ + if (config_type::DEFAULT == cfgtype) + { + parentnode->set_attribute_int(debugger::ATTR_DEBUGGER_SAVE_WINDOWS, m_save_windows ? 1 : 0); + parentnode->set_attribute_int(debugger::ATTR_DEBUGGER_GROUP_WINDOWS, m_group_windows_setting ? 1 : 0); + util::xml::data_node *const colors = parentnode->add_child(debugger::NODE_COLORS, nullptr); + if (colors) + colors->set_attribute_int(debugger::ATTR_COLORS_THEME, m_metrics->get_color_theme()); + } + else if (m_save_windows && (config_type::SYSTEM == cfgtype)) + { + for (auto &info : m_window_list) + info->save_configuration(*parentnode); + } +} + + +void debugger_windows::load_configuration(util::xml::data_node const &parentnode) +{ + for (util::xml::data_node const *node = parentnode.get_child(debugger::NODE_WINDOW); node; node = node->get_next_sibling(debugger::NODE_WINDOW)) + { + debugger::win::debugwin_info *win = nullptr; + switch (node->get_attribute_int(debugger::ATTR_WINDOW_TYPE, -1)) + { + case debugger::WINDOW_TYPE_CONSOLE: + m_main_console->restore_configuration_from_node(*node); + break; + case debugger::WINDOW_TYPE_MEMORY_VIEWER: + win = create_window<debugger::win::memorywin_info>(); + break; + case debugger::WINDOW_TYPE_DISASSEMBLY_VIEWER: + win = create_window<debugger::win::disasmwin_info>(); + break; + case debugger::WINDOW_TYPE_ERROR_LOG_VIEWER: + win = create_window<debugger::win::logwin_info>(); + break; + case debugger::WINDOW_TYPE_POINTS_VIEWER: + win = create_window<debugger::win::pointswin_info>(); + break; + case debugger::WINDOW_TYPE_DEVICES_VIEWER: + // not supported + break; + case debugger::WINDOW_TYPE_DEVICE_INFO_VIEWER: + // not supported + break; + default: + break; + } + if (win) + win->restore_configuration_from_node(*node); + } +} + +} // anonymous namespace + +} // namespace osd + +#else // not Windows + +namespace osd { namespace { MODULE_NOT_SUPPORTED(debugger_windows, OSD_DEBUG_PROVIDER, "windows") } } + #endif -MODULE_DEFINITION(DEBUG_WINDOWS, debugger_windows) +MODULE_DEFINITION(DEBUG_WINDOWS, osd::debugger_windows) |