diff options
Diffstat (limited to 'src/osd/modules/debugger/win')
29 files changed, 1812 insertions, 620 deletions
diff --git a/src/osd/modules/debugger/win/consolewininfo.cpp b/src/osd/modules/debugger/win/consolewininfo.cpp index a9811f5fc93..a5dfd04cc55 100644 --- a/src/osd/modules/debugger/win/consolewininfo.cpp +++ b/src/osd/modules/debugger/win/consolewininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// consolewininfo.c - Win32 debug window handling +// consolewininfo.cpp - Win32 debug window handling // //============================================================ @@ -12,47 +12,245 @@ #include "debugviewinfo.h" #include "uimetrics.h" -#include "debugger.h" +// devices +#include "imagedev/cassette.h" + +// emu #include "debug/debugcon.h" +#include "debugger.h" +#include "image.h" +#include "softlist_dev.h" #include "debug/debugcpu.h" -#include "imagedev/cassette.h" -#include "strconv.h" +// util +#include "util/xmlfile.h" + +// osd/windows #include "winutf8.h" +// osd +#include "strconv.h" + +// C++ +#include <vector> + +// Windows +#include <commctrl.h> +#include <shlobj.h> +#include <shobjidl.h> +#include <shtypes.h> +#include <wrl/client.h> + + +namespace osd::debugger::win { + +namespace { + +class comdlg_filter_helper +{ +public: + comdlg_filter_helper(comdlg_filter_helper const &) = delete; + comdlg_filter_helper &operator=(comdlg_filter_helper const &) = delete; + + comdlg_filter_helper(device_image_interface &device, bool include_archives) + { + m_count = 0U; + + std::wstring const extensions = osd::text::to_wstring(device.file_extensions()); + std::wstring_view extview = extensions; + m_description = L"Media Image Files ("; + for (auto comma = extview.find(','); !extview.empty(); comma = extview.find(',')) + { + bool const found = std::wstring_view::npos != comma; + std::wstring_view const ext = found ? extview.substr(0, comma) : extview; + extview.remove_prefix(found ? (comma + 1) : extview.length()); + if (m_extensions.empty()) + { + m_default = ext; + m_description.append(L"*."); + m_extensions.append(L"*."); + } + else + { + m_description.append(L"; *."); + m_extensions.append(L";*."); + } + m_description.append(ext); + m_extensions.append(ext); + } + m_description.append(1, L')'); + m_specs[m_count].pszName = m_description.c_str(); + m_specs[m_count].pszSpec = m_extensions.c_str(); + ++m_count; + + if (include_archives) + { + m_specs[m_count].pszName = L"Archive Files (*.zip; *.7z)"; + m_specs[m_count].pszSpec = L"*.zip;*.7z"; + ++m_count; + } + + m_specs[m_count].pszName = L"All Files (*.*)"; + m_specs[m_count].pszSpec = L"*.*"; + ++m_count; + } + + UINT file_types() const noexcept + { + return m_count; + } + + COMDLG_FILTERSPEC const *filter_spec() const noexcept + { + return m_specs; + } + + LPCWSTR default_extension() const noexcept + { + return m_default.c_str(); + } + +private: + COMDLG_FILTERSPEC m_specs[3]; + std::wstring m_description; + std::wstring m_extensions; + std::wstring m_default; + UINT m_count; +}; + + +template <typename T> +void choose_image(device_image_interface &device, HWND owner, REFCLSID class_id, bool allow_archives, T &&handler) +{ + HRESULT hr; + + // create file dialog + Microsoft::WRL::ComPtr<IFileDialog> dialog; + hr = CoCreateInstance(class_id, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dialog)); + + // set file types + if (SUCCEEDED(hr)) + { + DWORD flags; + hr = dialog->GetOptions(&flags); + if (SUCCEEDED(hr)) + hr = dialog->SetOptions(flags | FOS_NOCHANGEDIR | FOS_FORCEFILESYSTEM); + comdlg_filter_helper filters(device, allow_archives); + if (SUCCEEDED(hr)) + hr = dialog->SetFileTypes(filters.file_types(), filters.filter_spec()); + if (SUCCEEDED(hr)) + hr = dialog->SetFileTypeIndex(1); + if (SUCCEEDED(hr)) + hr = dialog->SetDefaultExtension(filters.default_extension()); + } + + // set starting folder + if (SUCCEEDED(hr)) + { + std::string dir = device.working_directory(); + if (dir.empty()) + { + dir = device.device().machine().image().setup_working_directory(); + device.set_working_directory(dir); + } + std::string full; + if (!dir.empty() && !osd_get_full_path(full, dir)) + { + // FIXME: strip off archive names - opening a file inside an archive decompresses it to a temporary location + std::wstring wfull = osd::text::to_wstring(full); + Microsoft::WRL::ComPtr<IShellItem> item; + if (SUCCEEDED(SHCreateItemFromParsingName(wfull.c_str(), nullptr, IID_PPV_ARGS(&item)))) + { + //dialog->SetFolder(item); disabled until + } + } + } + + // show the dialog + if (SUCCEEDED(hr)) + { + hr = dialog->Show(owner); + if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) + return; + } + if (SUCCEEDED(hr)) + { + Microsoft::WRL::ComPtr<IShellItem> result; + hr = dialog->GetResult(&result); + if (SUCCEEDED(hr)) + { + PWSTR selection = nullptr; + hr = result->GetDisplayName(SIGDN_FILESYSPATH, &selection); + if (SUCCEEDED(hr)) + { + std::string const utf_selection = osd::text::from_wstring(selection); + CoTaskMemFree(selection); + handler(utf_selection); + } + } + } + + if (!SUCCEEDED(hr)) + { + int pressed; + TaskDialog( + owner, + nullptr, // instance + nullptr, // title + L"Error showing file dialog", + nullptr, // content + TDCBF_OK_BUTTON, + TD_ERROR_ICON, + &pressed); + } +} + +} // anonymous namespace + + consolewin_info::consolewin_info(debugger_windows_interface &debugger) : disasmbasewin_info(debugger, true, "Debug", nullptr), m_current_cpu(nullptr), m_devices_menu(nullptr) { - if ((window() == nullptr) || (m_views[0] == nullptr)) + if (!window() || !m_views[0]) goto cleanup; // create the views - m_views[1].reset(global_alloc(debugview_info(debugger, *this, window(), DVT_STATE))); + m_views[1].reset(new debugview_info(debugger, *this, window(), DVT_STATE)); if (!m_views[1]->is_valid()) goto cleanup; - m_views[2].reset(global_alloc(debugview_info(debugger, *this, window(), DVT_CONSOLE))); + m_views[2].reset(new debugview_info(debugger, *this, window(), DVT_CONSOLE)); if (!m_views[2]->is_valid()) goto cleanup; { - // Add image menu only if image devices exist - image_interface_iterator iter(machine().root_device()); + // add image menu only if image devices exist + image_interface_enumerator iter(machine().root_device()); if (iter.first() != nullptr) { m_devices_menu = CreatePopupMenu(); for (device_image_interface &img : iter) { - if (!img.user_loadable()) - continue; - osd::text::tstring tc_buf = osd::text::to_tstring(string_format("%s : %s", img.device().name(), img.exists() ? img.filename() : "[no image]")); - AppendMenu(m_devices_menu, MF_ENABLED, 0, tc_buf.c_str()); + if (img.user_loadable()) + { + osd::text::tstring tc_buf = osd::text::to_tstring(string_format("%s : %s", img.device().name(), img.exists() ? img.filename() : "[no image]")); + AppendMenu(m_devices_menu, MF_ENABLED, 0, tc_buf.c_str()); + } } AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)m_devices_menu, TEXT("Media")); } + // add the settings menu + HMENU const settingsmenu = CreatePopupMenu(); + AppendMenu(settingsmenu, MF_ENABLED, ID_SAVE_WINDOWS, TEXT("Save Window Arrangement")); + AppendMenu(settingsmenu, MF_ENABLED, ID_GROUP_WINDOWS, TEXT("Group Debugger Windows (requires restart)")); + AppendMenu(settingsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); + AppendMenu(settingsmenu, MF_ENABLED, ID_LIGHT_BACKGROUND, TEXT("Light Background")); + AppendMenu(settingsmenu, MF_ENABLED, ID_DARK_BACKGROUND, TEXT("Dark Background")); + AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)settingsmenu, TEXT("Settings")); + // get the work bounds RECT work_bounds, bounds; SystemParametersInfo(SPI_GETWORKAREA, 0, &work_bounds, 0); @@ -78,7 +276,7 @@ consolewin_info::consolewin_info(debugger_windows_interface &debugger) : } // recompute the children - set_cpu(*machine().debugger().cpu().get_visible_cpu()); + set_cpu(*machine().debugger().console().get_visible_cpu()); // mark the edit box as the default focus and set it editwin_info::set_default_focus(); @@ -163,11 +361,11 @@ void consolewin_info::update_menu() { disasmbasewin_info::update_menu(); - if (m_devices_menu != nullptr) + if (m_devices_menu) { // create the image menu uint32_t cnt = 0; - for (device_image_interface &img : image_interface_iterator(machine().root_device())) + for (device_image_interface &img : image_interface_enumerator(machine().root_device())) { if (!img.user_loadable()) continue; @@ -184,8 +382,8 @@ void consolewin_info::update_menu() if (img.is_readonly()) flags_for_writing |= MF_GRAYED; - // not working properly, removed for now until investigation can be done - //if (get_softlist_info(&img)) + // FIXME: needs a real software item picker to be useful + //if (get_softlist_info(img)) // AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_ITEM, TEXT("Mount Item...")); AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_OPEN, TEXT("Mount File...")); @@ -199,7 +397,7 @@ void consolewin_info::update_menu() if (img.device().type() == CASSETTE) { - cassette_state const state = cassette_state(downcast<cassette_image_device *>(&img.device())->get_state() & CASSETTE_MASK_UISTATE); + cassette_state const state = downcast<cassette_image_device *>(&img.device())->get_state() & CASSETTE_MASK_UISTATE; AppendMenu(devicesubmenu, MF_SEPARATOR, 0, nullptr); AppendMenu(devicesubmenu, flags_for_exists | ((state == CASSETTE_STOPPED) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_STOPPAUSE, TEXT("Pause/Stop")); AppendMenu(devicesubmenu, flags_for_exists | ((state == CASSETTE_PLAY) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_PLAY, TEXT("Play")); @@ -208,9 +406,9 @@ void consolewin_info::update_menu() AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CASSETTE_FASTFORWARD, TEXT("Fast Forward")); AppendMenu(devicesubmenu, MF_SEPARATOR, 0, nullptr); // Motor state can be overriden by the driver - cassette_state const motor_state = cassette_state(downcast<cassette_image_device *>(&img.device())->get_state() & CASSETTE_MASK_MOTOR); + cassette_state const motor_state = downcast<cassette_image_device *>(&img.device())->get_state() & CASSETTE_MASK_MOTOR; AppendMenu(devicesubmenu, flags_for_exists | ((motor_state == CASSETTE_MOTOR_ENABLED) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_MOTOR, TEXT("Motor")); - cassette_state const speaker_state = cassette_state(downcast<cassette_image_device *>(&img.device())->get_state() & CASSETTE_MASK_SPEAKER); + cassette_state const speaker_state = downcast<cassette_image_device *>(&img.device())->get_state() & CASSETTE_MASK_SPEAKER; AppendMenu(devicesubmenu, flags_for_exists | ((speaker_state == CASSETTE_SPEAKER_ENABLED) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_SOUND, TEXT("Audio while Loading")); } } @@ -249,239 +447,105 @@ void consolewin_info::update_menu() cnt++; } } + + HMENU const menu = GetMenu(window()); + CheckMenuItem(menu, ID_SAVE_WINDOWS, MF_BYCOMMAND | (debugger().get_save_window_arrangement() ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_GROUP_WINDOWS, MF_BYCOMMAND | (debugger().get_group_windows_setting() ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_LIGHT_BACKGROUND, MF_BYCOMMAND | ((ui_metrics::THEME_LIGHT_BACKGROUND == metrics().get_color_theme()) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_DARK_BACKGROUND, MF_BYCOMMAND | ((ui_metrics::THEME_DARK_BACKGROUND == metrics().get_color_theme()) ? MF_CHECKED : MF_UNCHECKED)); } bool consolewin_info::handle_command(WPARAM wparam, LPARAM lparam) { - if ((HIWORD(wparam) == 0) && (LOWORD(wparam) >= ID_DEVICE_OPTIONS)) + if (HIWORD(wparam) == 0) { - uint32_t const devid = (LOWORD(wparam) - ID_DEVICE_OPTIONS) / DEVOPTION_MAX; - image_interface_iterator iter(machine().root_device()); - device_image_interface *const img = iter.byindex(devid); - if (img != nullptr) + if (LOWORD(wparam) >= ID_DEVICE_OPTIONS) { - switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX) + uint32_t const devid = (LOWORD(wparam) - ID_DEVICE_OPTIONS) / DEVOPTION_MAX; + image_interface_enumerator iter(machine().root_device()); + device_image_interface *const img = iter.byindex(devid); + if (img != nullptr) { - case DEVOPTION_ITEM : - { - std::string filter; - build_generic_filter(nullptr, false, filter); - { - osd::text::tstring t_filter = osd::text::to_tstring(filter); - - // convert a pipe-char delimited string into a NUL delimited string - for (int i = 0; t_filter[i] != '\0'; i++) - { - if (t_filter[i] == '|') - t_filter[i] = '\0'; - } - - std::string opt_name = img->instance_name(); - std::string as = slmap.find(opt_name)->second; - - /* Make sure a folder was specified, and that it exists */ - if ((!osd::directory::open(as.c_str())) || (as.find(':') == std::string::npos)) - { - /* Default to emu directory */ - osd_get_full_path(as, "."); - } - osd::text::tstring t_dir = osd::text::to_tstring(as); - - // display the dialog - TCHAR selectedFilename[MAX_PATH]; - selectedFilename[0] = '\0'; - OPENFILENAME ofn; - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = nullptr; - ofn.lpstrFile = selectedFilename; - ofn.lpstrFile[0] = '\0'; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrFilter = t_filter.c_str(); - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = nullptr; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = t_dir.c_str(); - ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - - if (GetOpenFileName(&ofn)) - { - std::string buf = std::string(osd::text::from_tstring(selectedFilename)); - // Get the Item name out of the full path - size_t t1 = buf.find(".zip"); // get rid of zip name and anything after - if (t1 != std::string::npos) - buf.erase(t1); - t1 = buf.find(".7z"); // get rid of 7zip name and anything after - if (t1 != std::string::npos) - buf.erase(t1); - t1 = buf.find_last_of("\\"); // put the swlist name in - buf[t1] = ':'; - t1 = buf.find_last_of("\\"); // get rid of path; we only want the item name - buf.erase(0, t1+1); - - // load software - img->load_software( buf.c_str()); - } - } - } - return true; - case DEVOPTION_OPEN : - { - std::string filter; - build_generic_filter(img, false, filter); - { - osd::text::tstring t_filter = osd::text::to_tstring(filter); - - // convert a pipe-char delimited string into a NUL delimited string - for (int i = 0; t_filter[i] != '\0'; i++) - { - if (t_filter[i] == '|') - t_filter[i] = '\0'; - } - - char buf[400]; - std::string as; - strcpy(buf, machine().options().emu_options::sw_path()); - // This pulls out the first path from a multipath field - const char* t1 = strtok(buf, ";"); - if (t1) - as = t1; // the first path of many - else - as = buf; // the only path - - /* Make sure a folder was specified, and that it exists */ - if ((!osd::directory::open(as.c_str())) || (as.find(':') == std::string::npos)) - { - /* Default to emu directory */ - osd_get_full_path(as, "."); - } - osd::text::tstring t_dir = osd::text::to_tstring(as); - - TCHAR selectedFilename[MAX_PATH]; - selectedFilename[0] = '\0'; - OPENFILENAME ofn; - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = nullptr; - ofn.lpstrFile = selectedFilename; - ofn.lpstrFile[0] = '\0'; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrFilter = t_filter.c_str(); - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = nullptr; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = t_dir.c_str(); - ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - - if (GetOpenFileName(&ofn)) - { - auto utf8_buf = osd::text::from_tstring(selectedFilename); - img->load(utf8_buf.c_str()); - } - } - } - return true; - case DEVOPTION_CREATE: - { - std::string filter; - build_generic_filter(img, true, filter); - { - osd::text::tstring t_filter = osd::text::to_tstring(filter); - // convert a pipe-char delimited string into a NUL delimited string - for (int i = 0; t_filter[i] != '\0'; i++) - { - if (t_filter[i] == '|') - t_filter[i] = '\0'; - } - - char buf[400]; - std::string as; - strcpy(buf, machine().options().emu_options::sw_path()); - // This pulls out the first path from a multipath field - const char* t1 = strtok(buf, ";"); - if (t1) - as = t1; // the first path of many - else - as = buf; // the only path - - /* Make sure a folder was specified, and that it exists */ - if ((!osd::directory::open(as.c_str())) || (as.find(':') == std::string::npos)) - { - /* Default to emu directory */ - osd_get_full_path(as, "."); - } - osd::text::tstring t_dir = osd::text::to_tstring(as); - - TCHAR selectedFilename[MAX_PATH]; - selectedFilename[0] = '\0'; - OPENFILENAME ofn; - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = nullptr; - ofn.lpstrFile = selectedFilename; - ofn.lpstrFile[0] = '\0'; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrFilter = t_filter.c_str(); - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = nullptr; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = t_dir.c_str(); - ofn.Flags = OFN_PATHMUSTEXIST; - - if (GetSaveFileName(&ofn)) - { - auto utf8_buf = osd::text::from_tstring(selectedFilename); - img->create(utf8_buf.c_str(), img->device_get_indexed_creatable_format(0), nullptr); - } - } - } - return true; - case DEVOPTION_CLOSE: - img->unload(); - return true; - } - if (img->device().type() == CASSETTE) - { - cassette_image_device *const cassette = downcast<cassette_image_device *>(&img->device()); - bool s; switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX) { - case DEVOPTION_CASSETTE_STOPPAUSE: - cassette->change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE); + case DEVOPTION_ITEM: + // TODO: this is supposed to show a software list item picker - it never worked properly return true; - case DEVOPTION_CASSETTE_PLAY: - cassette->change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE); + case DEVOPTION_OPEN : + open_image_file(*img); return true; - case DEVOPTION_CASSETTE_RECORD: - cassette->change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE); + case DEVOPTION_CREATE: + create_image_file(*img); return true; - case DEVOPTION_CASSETTE_REWIND: - cassette->seek(0.0, SEEK_SET); // to start + case DEVOPTION_CLOSE: + img->unload(); return true; - case DEVOPTION_CASSETTE_FASTFORWARD: - cassette->seek(+300.0, SEEK_CUR); // 5 minutes forward or end, whichever comes first - break; - case DEVOPTION_CASSETTE_MOTOR: - s =((cassette->get_state() & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED); - cassette->change_state(s ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR); - break; - case DEVOPTION_CASSETTE_SOUND: - s =((cassette->get_state() & CASSETTE_MASK_SPEAKER) == CASSETTE_SPEAKER_MUTED); - cassette->change_state(s ? CASSETTE_SPEAKER_ENABLED : CASSETTE_SPEAKER_MUTED, CASSETTE_MASK_SPEAKER); - break; + } + if (img->device().type() == CASSETTE) + { + auto *const cassette = downcast<cassette_image_device *>(&img->device()); + bool s; + switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX) + { + case DEVOPTION_CASSETTE_STOPPAUSE: + cassette->change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE); + return true; + case DEVOPTION_CASSETTE_PLAY: + cassette->change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE); + return true; + case DEVOPTION_CASSETTE_RECORD: + cassette->change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE); + return true; + case DEVOPTION_CASSETTE_REWIND: + cassette->seek(0.0, SEEK_SET); // to start + return true; + case DEVOPTION_CASSETTE_FASTFORWARD: + cassette->seek(+300.0, SEEK_CUR); // 5 minutes forward or end, whichever comes first + return true; + case DEVOPTION_CASSETTE_MOTOR: + s = ((cassette->get_state() & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED); + cassette->change_state(s ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR); + return true; + case DEVOPTION_CASSETTE_SOUND: + s = ((cassette->get_state() & CASSETTE_MASK_SPEAKER) == CASSETTE_SPEAKER_MUTED); + cassette->change_state(s ? CASSETTE_SPEAKER_ENABLED : CASSETTE_SPEAKER_MUTED, CASSETTE_MASK_SPEAKER); + return true; + } } } } + else switch (LOWORD(wparam)) + { + case ID_SAVE_WINDOWS: + debugger().set_save_window_arrangement(!debugger().get_save_window_arrangement()); + return true; + case ID_GROUP_WINDOWS: + debugger().set_group_windows_setting(!debugger().get_group_windows_setting()); + return true; + case ID_LIGHT_BACKGROUND: + debugger().set_color_theme(ui_metrics::THEME_LIGHT_BACKGROUND); + return true; + case ID_DARK_BACKGROUND: + debugger().set_color_theme(ui_metrics::THEME_DARK_BACKGROUND); + return true; + } } return disasmbasewin_info::handle_command(wparam, lparam); } +void consolewin_info::save_configuration_to_node(util::xml::data_node &node) +{ + disasmbasewin_info::save_configuration_to_node(node); + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_CONSOLE); +} + + void consolewin_info::process_string(std::string const &string) { if (string.empty()) // an empty string is a single step - machine().debugger().cpu().get_visible_cpu()->debug()->single_step(); + machine().debugger().console().get_visible_cpu()->debug()->single_step(); else // otherwise, just process the command machine().debugger().console().execute_command(string, true); @@ -490,94 +554,60 @@ void consolewin_info::process_string(std::string const &string) } -void consolewin_info::build_generic_filter(device_image_interface *img, bool is_save, std::string &filter) +void consolewin_info::open_image_file(device_image_interface &device) { - std::string file_extension; - - if (img) - file_extension = img->file_extensions(); - - if (!is_save) - file_extension.append(",zip,7z"); - - add_filter_entry(filter, "Common image types", file_extension.c_str()); - - filter.append("All files (*.*)|*.*|"); - - if (!is_save) - filter.append("Compressed Images (*.zip;*.7z)|*.zip;*.7z|"); + choose_image( + device, + window(), + CLSID_FileOpenDialog, + true, + [this, &device] (std::string_view selection) + { + auto [err, message] = device.load(selection); + if (err) + machine().debugger().console().printf("Error mounting image file: %s\n", !message.empty() ? message : err.message()); + }); } -void consolewin_info::add_filter_entry(std::string &dest, const char *description, const char *extensions) +void consolewin_info::create_image_file(device_image_interface &device) { - // add the description - dest.append(description); - dest.append(" ("); - - // add the extensions to the description - copy_extension_list(dest, extensions); - - // add the trailing rparen and '|' character - dest.append(")|"); - - // now add the extension list itself - copy_extension_list(dest, extensions); - - // append a '|' - dest.append("|"); + choose_image( + device, + window(), + CLSID_FileSaveDialog, + false, + [this, &device] (std::string_view selection) + { + auto [err, message] = device.create(selection, device.device_get_indexed_creatable_format(0), nullptr); + if (err) + machine().debugger().console().printf("Error creating image file: %s\n", !message.empty() ? message : err.message()); + }); } -void consolewin_info::copy_extension_list(std::string &dest, const char *extensions) -{ - // our extension lists are comma delimited; Win32 expects to see lists - // delimited by semicolons - char const *s = extensions; - while (*s) - { - // append a semicolon if not at the beginning - if (s != extensions) - dest.push_back(';'); - - // append ".*" - dest.append("*."); - - // append the file extension - while (*s && (*s != ',')) - dest.push_back(*s++); - - // if we found a comma, advance - while(*s == ',') - s++; - } -} - -//============================================================ -// get_softlist_info -//============================================================ -bool consolewin_info::get_softlist_info(device_image_interface *img) +bool consolewin_info::get_softlist_info(device_image_interface &device) { bool has_software = false; bool passes_tests = false; - std::string sl_dir, opt_name = img->instance_name(); + std::string sl_dir, opt_name = device.instance_name(); // Get the path to suitable software - for (software_list_device &swlist : software_list_device_iterator(machine().root_device())) + for (software_list_device &swlist : software_list_device_enumerator(machine().root_device())) { for (const software_info &swinfo : swlist.get_info()) { const software_part &part = swinfo.parts().front(); if (swlist.is_compatible(part) == SOFTWARE_IS_COMPATIBLE) { - for (device_image_interface &image : image_interface_iterator(machine().root_device())) + for (device_image_interface &image : image_interface_enumerator(machine().root_device())) { if (!image.user_loadable()) continue; if (!has_software && (opt_name == image.instance_name())) { - const char *interface = image.image_interface(); - if (interface && part.matches_interface(interface)) + const char *intf = image.image_interface(); + if (intf && part.matches_interface(intf)) { sl_dir = "\\" + swlist.list_name(); has_software = true; @@ -598,7 +628,7 @@ bool consolewin_info::get_softlist_info(device_image_interface *img) while (sl_root && !passes_tests) { std::string test_path = sl_root + sl_dir; - if (osd::directory::open(test_path.c_str())) + if (osd::directory::open(test_path)) { passes_tests = true; slmap[opt_name] = test_path; @@ -609,3 +639,5 @@ bool consolewin_info::get_softlist_info(device_image_interface *img) return passes_tests; } + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/consolewininfo.h b/src/osd/modules/debugger/win/consolewininfo.h index 7f8ccc13aec..e79ba667a11 100644 --- a/src/osd/modules/debugger/win/consolewininfo.h +++ b/src/osd/modules/debugger/win/consolewininfo.h @@ -5,15 +5,18 @@ // consolewininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_CONSOLEWININFO_H +#define MAME_DEBUGGER_WIN_CONSOLEWININFO_H -#ifndef __DEBUG_WIN_CONSOLE_WIN_INFO_H__ -#define __DEBUG_WIN_CONSOLE_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "disasmbasewininfo.h" +namespace osd::debugger::win { + class consolewin_info : public disasmbasewin_info { public: @@ -26,6 +29,7 @@ protected: virtual void recompute_children() override; virtual void update_menu() override; virtual bool handle_command(WPARAM wparam, LPARAM lparam) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; private: enum @@ -46,14 +50,15 @@ private: virtual void process_string(std::string const &string) override; - static void build_generic_filter(device_image_interface *img, bool is_save, std::string &filter); - static void add_filter_entry(std::string &dest, char const *description, char const *extensions); - static void copy_extension_list(std::string &dest, char const *extensions); - bool get_softlist_info(device_image_interface *img); + void open_image_file(device_image_interface &device); + void create_image_file(device_image_interface &device); + bool get_softlist_info(device_image_interface &img); device_t *m_current_cpu; - HMENU m_devices_menu; + HMENU m_devices_menu; std::map<std::string,std::string> slmap; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_CONSOLEWININFO_H diff --git a/src/osd/modules/debugger/win/debugbaseinfo.cpp b/src/osd/modules/debugger/win/debugbaseinfo.cpp index 4914d54cfad..0de7331cbc8 100644 --- a/src/osd/modules/debugger/win/debugbaseinfo.cpp +++ b/src/osd/modules/debugger/win/debugbaseinfo.cpp @@ -10,6 +10,8 @@ #include "debugbaseinfo.h" +namespace osd::debugger::win { + debugbase_info::debugbase_info(debugger_windows_interface &debugger) : m_debugger(debugger), m_machine(debugger.machine()), @@ -21,12 +23,10 @@ debugbase_info::debugbase_info(debugger_windows_interface &debugger) : void debugbase_info::smart_set_window_bounds(HWND wnd, HWND parent, RECT const &bounds) { - RECT curbounds; - int flags = 0; - // first get the current bounds, relative to the parent + RECT curbounds; GetWindowRect(wnd, &curbounds); - if (parent != nullptr) + if (parent) { RECT parentbounds; GetWindowRect(parent, &parentbounds); @@ -37,6 +37,7 @@ void debugbase_info::smart_set_window_bounds(HWND wnd, HWND parent, RECT const & } // if the position matches, don't change it + int flags = 0; if (curbounds.top == bounds.top && curbounds.left == bounds.left) flags |= SWP_NOMOVE; if ((curbounds.bottom - curbounds.top) == (bounds.bottom - bounds.top) && @@ -45,17 +46,21 @@ void debugbase_info::smart_set_window_bounds(HWND wnd, HWND parent, RECT const & // if we need to, reposition the window if (flags != (SWP_NOMOVE | SWP_NOSIZE)) - SetWindowPos(wnd, nullptr, - bounds.left, bounds.top, - bounds.right - bounds.left, bounds.bottom - bounds.top, - SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | flags); + { + SetWindowPos( + wnd, nullptr, + bounds.left, bounds.top, + bounds.right - bounds.left, bounds.bottom - bounds.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | flags); + } } - void debugbase_info::smart_show_window(HWND wnd, bool show) { - BOOL const visible = IsWindowVisible(wnd); - if ((visible && !show) || (!visible && show)) + bool const visible = bool(IsWindowVisible(wnd)); + if (visible != show) ShowWindow(wnd, show ? SW_SHOW : SW_HIDE); } + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/debugbaseinfo.h b/src/osd/modules/debugger/win/debugbaseinfo.h index 03fd5a8018d..da874a6b8fd 100644 --- a/src/osd/modules/debugger/win/debugbaseinfo.h +++ b/src/osd/modules/debugger/win/debugbaseinfo.h @@ -5,13 +5,15 @@ // debugbaseinfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DEBUGBASEINFO_H +#define MAME_DEBUGGER_WIN_DEBUGBASEINFO_H -#ifndef __DEBUG_WIN_DEBUG_BASE_INFO_H__ -#define __DEBUG_WIN_DEBUG_BASE_INFO_H__ +#pragma once #include "debugwin.h" +namespace osd::debugger::win { class debugbase_info { @@ -35,5 +37,6 @@ private: bool const &m_waiting_for_debugger; }; +} // namespace osd::debugger::win -#endif +#endif // MAME_DEBUGGER_WIN_DEBUGBASEINFO_H diff --git a/src/osd/modules/debugger/win/debugviewinfo.cpp b/src/osd/modules/debugger/win/debugviewinfo.cpp index 97238ff8862..8f3f05c16d2 100644 --- a/src/osd/modules/debugger/win/debugviewinfo.cpp +++ b/src/osd/modules/debugger/win/debugviewinfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// debugview.c - Win32 debug window handling +// debugviewinfo.cpp - Win32 debug window handling // //============================================================ @@ -12,12 +12,20 @@ #include "debugwininfo.h" #include "uimetrics.h" #include "debugger.h" + +#include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "util/xmlfile.h" + #include "strconv.h" #include "winutil.h" +#include <mmsystem.h> + + +namespace osd::debugger::win { // debugger view styles #define DEBUG_VIEW_STYLE WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN @@ -45,14 +53,15 @@ debugview_info::debugview_info(debugger_windows_interface &debugger, debugwin_in m_view(nullptr), m_wnd(nullptr), m_hscroll(nullptr), - m_vscroll(nullptr) + m_vscroll(nullptr), + m_contextmenu(nullptr) { register_window_class(); // create the child view m_wnd = CreateWindowEx(DEBUG_VIEW_STYLE_EX, TEXT("MAMEDebugView"), nullptr, DEBUG_VIEW_STYLE, 0, 0, 100, 100, parent, nullptr, GetModuleHandleUni(), this); - if (m_wnd == nullptr) + if (!m_wnd) goto cleanup; // create the scroll bars @@ -60,27 +69,27 @@ debugview_info::debugview_info(debugger_windows_interface &debugger, debugwin_in 0, 0, 100, CW_USEDEFAULT, m_wnd, nullptr, GetModuleHandleUni(), this); m_vscroll = CreateWindowEx(VSCROLL_STYLE_EX, TEXT("SCROLLBAR"), nullptr, VSCROLL_STYLE, 0, 0, CW_USEDEFAULT, 100, m_wnd, nullptr, GetModuleHandleUni(), this); - if ((m_hscroll == nullptr) || (m_vscroll == nullptr)) + if (!m_hscroll || !m_vscroll) goto cleanup; // create the debug view m_view = machine().debug_view().alloc_view(type, &debugview_info::static_update, this); - if (m_view == nullptr) + if (!m_view) goto cleanup; return; cleanup: - if (m_hscroll != nullptr) + if (m_hscroll) DestroyWindow(m_hscroll); m_hscroll = nullptr; - if (m_vscroll != nullptr) + if (m_vscroll) DestroyWindow(m_vscroll); m_vscroll = nullptr; - if (m_wnd != nullptr) + if (m_wnd) DestroyWindow(m_wnd); m_wnd = nullptr; - if (m_view != nullptr) + if (m_view) machine().debug_view().free_view(*m_view); m_view = nullptr; } @@ -88,7 +97,9 @@ cleanup: debugview_info::~debugview_info() { - if (m_wnd != nullptr) + if (m_contextmenu) + DestroyMenu(m_contextmenu); + if (m_wnd) DestroyWindow(m_wnd); if (m_view) machine().debug_view().free_view(*m_view); @@ -111,14 +122,14 @@ uint32_t debugview_info::maxwidth() { uint32_t max = m_view->total_size().x; debug_view_source const *const cursource = m_view->source(); - for (const debug_view_source &source : m_view->source_list()) + for (auto &source : m_view->source_list()) { - m_view->set_source(source); + m_view->set_source(*source); uint32_t const chars = m_view->total_size().x; if (max < chars) max = chars; } - if (cursource != nullptr) + if (cursource) m_view->set_source(*cursource); return (max * metrics().debug_font_width()) + metrics().vscroll_width(); } @@ -163,27 +174,35 @@ void debugview_info::send_vscroll(int delta) void debugview_info::send_pageup() { if (m_vscroll) - { SendMessage(m_wnd, WM_VSCROLL, SB_PAGELEFT, (LPARAM)m_vscroll); - } } void debugview_info::send_pagedown() { if (m_vscroll) - { SendMessage(m_wnd, WM_VSCROLL, SB_PAGERIGHT, (LPARAM)m_vscroll); +} + + +int debugview_info::source_index() const +{ + if (m_view) + { + debug_view_source const *const source = m_view->source(); + if (source) + return m_view->source_index(*source); } + return -1; } char const *debugview_info::source_name() const { - if (m_view != nullptr) + if (m_view) { debug_view_source const *const source = m_view->source(); - if (source != nullptr) + if (source) return source->name(); } return ""; @@ -192,10 +211,10 @@ char const *debugview_info::source_name() const device_t *debugview_info::source_device() const { - if (m_view != nullptr) + if (m_view) { debug_view_source const *const source = m_view->source(); - if (source != nullptr) + if (source) return source->device(); } return nullptr; @@ -204,10 +223,10 @@ device_t *debugview_info::source_device() const bool debugview_info::source_is_visible_cpu() const { - if (m_view != nullptr) + if (m_view) { const debug_view_source *const source = m_view->source(); - return (source != nullptr) && (machine().debugger().cpu().get_visible_cpu() == source->device()); + return source && (machine().debugger().console().get_visible_cpu() == source->device()); } return false; } @@ -215,10 +234,10 @@ bool debugview_info::source_is_visible_cpu() const bool debugview_info::set_source_index(int index) { - if (m_view != nullptr) + if (m_view) { - const debug_view_source *const source = m_view->source_list().find(index); - if (source != nullptr) + const debug_view_source *const source = m_view->source(index); + if (source) { m_view->set_source(*source); return true; @@ -230,10 +249,10 @@ bool debugview_info::set_source_index(int index) bool debugview_info::set_source_for_device(device_t &device) { - if (m_view != nullptr) + if (m_view) { const debug_view_source *const source = m_view->source_for_device(&device); - if (source != nullptr) + if (source) { m_view->set_source(*source); return true; @@ -245,8 +264,8 @@ bool debugview_info::set_source_for_device(device_t &device) bool debugview_info::set_source_for_visible_cpu() { - device_t *const curcpu = machine().debugger().cpu().get_visible_cpu(); - if (curcpu != nullptr) + device_t *const curcpu = machine().debugger().console().get_visible_cpu(); + if (curcpu) return set_source_for_device(*curcpu); else return false; @@ -264,7 +283,7 @@ HWND debugview_info::create_source_combobox(HWND parent, LONG_PTR userdata) // populate the combobox debug_view_source const *const cursource = m_view->source(); int maxlength = 0; - for (debug_view_source const *source = m_view->first_source(); source != nullptr; source = source->next()) + for (auto &source : m_view->source_list()) { int const length = strlen(source->name()); if (length > maxlength) @@ -272,9 +291,9 @@ HWND debugview_info::create_source_combobox(HWND parent, LONG_PTR userdata) auto t_name = osd::text::to_tstring(source->name()); SendMessage(result, CB_ADDSTRING, 0, (LPARAM)t_name.c_str()); } - if (cursource != nullptr) + if (cursource) { - SendMessage(result, CB_SETCURSEL, m_view->source_list().indexof(*cursource), 0); + SendMessage(result, CB_SETCURSEL, m_view->source_index(*cursource), 0); SendMessage(result, CB_SETDROPPEDWIDTH, ((maxlength + 2) * metrics().debug_font_width()) + metrics().vscroll_width(), 0); m_view->set_source(*cursource); } @@ -282,6 +301,165 @@ HWND debugview_info::create_source_combobox(HWND parent, LONG_PTR userdata) } +void debugview_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + if (m_view->cursor_supported()) + { + util::xml::data_node const *const selection = node.get_child(NODE_WINDOW_SELECTION); + if (selection) + { + debug_view_xy pos = m_view->cursor_position(); + m_view->set_cursor_visible(0 != selection->get_attribute_int(ATTR_SELECTION_CURSOR_VISIBLE, m_view->cursor_visible() ? 1 : 0)); + selection->get_attribute_int(ATTR_SELECTION_CURSOR_X, pos.x); + selection->get_attribute_int(ATTR_SELECTION_CURSOR_Y, pos.y); + m_view->set_cursor_position(pos); + } + } + + util::xml::data_node const *const scroll = node.get_child(NODE_WINDOW_SCROLL); + if (scroll) + { + debug_view_xy origin = m_view->visible_position(); + origin.x = scroll->get_attribute_int(ATTR_SCROLL_ORIGIN_X, origin.x * metrics().debug_font_width()) / metrics().debug_font_width(); + origin.y = scroll->get_attribute_int(ATTR_SCROLL_ORIGIN_Y, origin.y * metrics().debug_font_height()) / metrics().debug_font_height(); + m_view->set_visible_position(origin); + } +} + + +void debugview_info::save_configuration_to_node(util::xml::data_node &node) +{ + if (m_view->cursor_supported()) + { + util::xml::data_node *const selection = node.add_child(NODE_WINDOW_SELECTION, nullptr); + if (selection) + { + debug_view_xy const pos = m_view->cursor_position(); + selection->set_attribute_int(ATTR_SELECTION_CURSOR_VISIBLE, m_view->cursor_visible() ? 1 : 0); + selection->set_attribute_int(ATTR_SELECTION_CURSOR_X, pos.x); + selection->set_attribute_int(ATTR_SELECTION_CURSOR_Y, pos.y); + } + } + + util::xml::data_node *const scroll = node.add_child(NODE_WINDOW_SCROLL, nullptr); + if (scroll) + { + debug_view_xy const origin = m_view->visible_position(); + scroll->set_attribute_int(ATTR_SCROLL_ORIGIN_X, origin.x * metrics().debug_font_width()); + scroll->set_attribute_int(ATTR_SCROLL_ORIGIN_Y, origin.y * metrics().debug_font_height()); + } +} + + +void debugview_info::add_items_to_context_menu(HMENU menu) +{ + AppendMenu(menu, MF_ENABLED, ID_CONTEXT_COPY_VISIBLE, TEXT("Copy Visible")); + AppendMenu(menu, MF_ENABLED, ID_CONTEXT_PASTE, TEXT("Paste")); +} + + +void debugview_info::update_context_menu(HMENU menu) +{ + EnableMenuItem(menu, ID_CONTEXT_PASTE, MF_BYCOMMAND | (IsClipboardFormatAvailable(CF_UNICODETEXT) ? MF_ENABLED : MF_GRAYED)); +} + + +void debugview_info::handle_context_menu(unsigned command) +{ + switch (command) + { + case ID_CONTEXT_COPY_VISIBLE: + { + // get visible text + debug_view_xy const visarea = m_view->visible_size(); + debug_view_char const *viewdata = m_view->viewdata(); + if (!viewdata) + { + PlaySound(TEXT("SystemAsterisk"), nullptr, SND_SYNC); + break; + } + + // turn into a plain string, trimming trailing whitespace + std::wstring text; + for (uint32_t row = 0; row < visarea.y; row++, viewdata += visarea.x) + { + std::wstring::size_type const start = text.length(); + for (uint32_t col = 0; col < visarea.x; ++col) + text += wchar_t(viewdata[col].byte); + std::wstring::size_type const nonblank = text.find_last_not_of(L"\t\n\v\r "); + if (nonblank != std::wstring::npos) + text.resize((std::max)(start, nonblank + 1)); + text += L"\r\n"; + } + + // copy to the clipboard + HGLOBAL const clip = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(wchar_t)); + if (!clip) + { + PlaySound(TEXT("SystemAsterisk"), nullptr, SND_SYNC); + break; + } + if (!OpenClipboard(m_wnd)) + { + GlobalFree(clip); + PlaySound(TEXT("SystemAsterisk"), nullptr, SND_SYNC); + break; + } + EmptyClipboard(); + LPWSTR const lock = reinterpret_cast<LPWSTR>(GlobalLock(clip)); + std::copy_n(text.c_str(), text.length() + 1, lock); + GlobalUnlock(clip); + if (!SetClipboardData(CF_UNICODETEXT, clip)) + { + GlobalFree(clip); + PlaySound(TEXT("SystemAsterisk"), nullptr, SND_SYNC); + } + CloseClipboard(); + break; + } + + case ID_CONTEXT_PASTE: + if (!IsClipboardFormatAvailable(CF_UNICODETEXT) || !OpenClipboard(m_wnd)) + { + PlaySound(TEXT("SystemAsterisk"), nullptr, SND_SYNC); + } + else + { + HGLOBAL const clip = GetClipboardData(CF_UNICODETEXT); + LPCWSTR lock = clip ? reinterpret_cast<LPCWSTR>(GlobalLock(clip)) : nullptr; + if (!clip || !lock) + { + PlaySound(TEXT("SystemAsterisk"), nullptr, SND_SYNC); + } + else + { + try + { + while (*lock) + { + if ((32 <= *lock) && (127 >= *lock)) + m_view->process_char(*lock); + ++lock; + } + } + catch (...) + { + GlobalUnlock(clip); + CloseClipboard(); + throw; + } + GlobalUnlock(clip); + } + CloseClipboard(); + } + break; + + default: + osd_printf_warning("debugview_info: unhandled context menu item %u\n", command); + } +} + + void debugview_info::draw_contents(HDC windc) { debug_view_char const *viewdata = m_view->viewdata(); @@ -290,18 +468,22 @@ void debugview_info::draw_contents(HDC windc) // get the client rect RECT client; GetClientRect(m_wnd, &client); + bool const need_filldown = client.bottom > (metrics().debug_font_height() * visarea.y); // create a compatible DC and an offscreen bitmap HDC const dc = CreateCompatibleDC(windc); - if (dc == nullptr) + if (!dc) return; HBITMAP const bitmap = CreateCompatibleBitmap(windc, client.right, client.bottom); - if (bitmap == nullptr) + if (!bitmap) { DeleteDC(dc); return; } HGDIOBJ const oldbitmap = SelectObject(dc, bitmap); + bool const show_hscroll = m_hscroll && IsWindowVisible(m_hscroll); + if (show_hscroll) + client.bottom -= metrics().hscroll_height(); // set the font HGDIOBJ const oldfont = SelectObject(dc, metrics().debug_font()); @@ -312,11 +494,13 @@ void debugview_info::draw_contents(HDC windc) // iterate over rows and columns for (uint32_t row = 0; row < visarea.y; row++) { + bool do_filldown = (row == (visarea.y - 1)) && need_filldown; + // loop twice; once to fill the background and once to draw the text for (int iter = 0; iter < 2; iter++) { COLORREF fgcolor; - COLORREF bgcolor = RGB(0xff,0xff,0xff); + COLORREF bgcolor = metrics().view_colors(DCA_NORMAL).second; HBRUSH bgbrush = nullptr; int last_attrib = -1; TCHAR buffer[256]; @@ -340,41 +524,49 @@ void debugview_info::draw_contents(HDC windc) { COLORREF oldbg = bgcolor; - // reset to standard colors - fgcolor = RGB(0x00,0x00,0x00); - bgcolor = RGB(0xff,0xff,0xff); - - // pick new fg/bg colors - if (viewdata[col].attrib & DCA_VISITED) bgcolor = RGB(0xc6, 0xe2, 0xff); - if (viewdata[col].attrib & DCA_ANCILLARY) bgcolor = RGB(0xe0,0xe0,0xe0); - if (viewdata[col].attrib & DCA_SELECTED) bgcolor = RGB(0xff,0x80,0x80); - if (viewdata[col].attrib & DCA_CURRENT) bgcolor = RGB(0xff,0xff,0x00); - if ((viewdata[col].attrib & DCA_SELECTED) && (viewdata[col].attrib & DCA_CURRENT)) bgcolor = RGB(0xff,0xc0,0x80); - if (viewdata[col].attrib & DCA_CHANGED) fgcolor = RGB(0xff,0x00,0x00); - if (viewdata[col].attrib & DCA_INVALID) fgcolor = RGB(0x00,0x00,0xff); - if (viewdata[col].attrib & DCA_DISABLED) fgcolor = RGB((GetRValue(fgcolor) + GetRValue(bgcolor)) / 2, (GetGValue(fgcolor) + GetGValue(bgcolor)) / 2, (GetBValue(fgcolor) + GetBValue(bgcolor)) / 2); - if (viewdata[col].attrib & DCA_COMMENT) fgcolor = RGB(0x00,0x80,0x00); + // pick new colors + std::tie(fgcolor, bgcolor) = metrics().view_colors(viewdata[col].attrib); // flush any pending drawing if (count > 0) { bounds.right = bounds.left + (count * metrics().debug_font_width()); if (iter == 0) + { FillRect(dc, &bounds, bgbrush); + if (do_filldown) + { + COLORREF const filldown = metrics().view_colors(last_attrib & DCA_ANCILLARY).second; + if (oldbg != filldown) + { + DeleteObject(bgbrush); + bgbrush = CreateSolidBrush(filldown); + oldbg = filldown; + } + RECT padding = bounds; + padding.top = padding.bottom; + padding.bottom = client.bottom; + FillRect(dc, &padding, bgbrush); + } + } else + { ExtTextOut(dc, bounds.left, bounds.top, 0, nullptr, buffer, count, nullptr); + } bounds.left = bounds.right; count = 0; } // set the new colors - if (iter == 0 && oldbg != bgcolor) + if (iter == 1) + { + SetTextColor(dc, fgcolor); + } + else if (oldbg != bgcolor) { DeleteObject(bgbrush); bgbrush = CreateSolidBrush(bgcolor); } - else if (iter == 1) - SetTextColor(dc, fgcolor); last_attrib = viewdata[col].attrib; } @@ -383,33 +575,43 @@ void debugview_info::draw_contents(HDC windc) } // flush any remaining stuff - if (count > 0) - { - bounds.right = bounds.left + (count * metrics().debug_font_width()); - if (iter == 0) - FillRect(dc, &bounds, bgbrush); - else - ExtTextOut(dc, bounds.left, bounds.top, 0, nullptr, buffer, count, nullptr); - } - - // erase to the end of the line + bounds.right = bounds.left + (count * metrics().debug_font_width()); if (iter == 0) { - bounds.left = bounds.right; + // erase to the end of the line bounds.right = client.right; FillRect(dc, &bounds, bgbrush); + if (do_filldown) + { + COLORREF const filldown = metrics().view_colors(last_attrib & DCA_ANCILLARY).second; + if (bgcolor != filldown) + { + DeleteObject(bgbrush); + bgbrush = CreateSolidBrush(filldown); + } + bounds.top = bounds.bottom; + bounds.bottom = client.bottom; + FillRect(dc, &bounds, bgbrush); + } DeleteObject(bgbrush); } + else if (count > 0) + { + ExtTextOut(dc, bounds.left, bounds.top, 0, nullptr, buffer, count, nullptr); + } } // advance viewdata viewdata += visarea.x; } - // erase anything beyond the bottom with white - GetClientRect(m_wnd, &client); - client.top = visarea.y * metrics().debug_font_height(); - FillRect(dc, &client, (HBRUSH)GetStockObject(WHITE_BRUSH)); + // prevent garbage from showing in the corner + if (show_hscroll) + { + client.top = client.bottom; + client.bottom = client.top + metrics().hscroll_height(); + FillRect(dc, &client, (HBRUSH)GetStockObject(WHITE_BRUSH)); + } // reset the font SetBkMode(dc, oldbkmode); @@ -428,47 +630,48 @@ void debugview_info::draw_contents(HDC windc) void debugview_info::update() { - RECT bounds, vscroll_bounds, hscroll_bounds; - debug_view_xy totalsize, visiblesize, topleft; - bool show_vscroll, show_hscroll; SCROLLINFO scrollinfo; + // get the updated total rows/cols and left row/col + debug_view_xy const totalsize = m_view->total_size(); + debug_view_xy topleft = m_view->visible_position(); + // get the view window bounds + RECT bounds; GetClientRect(m_wnd, &bounds); + debug_view_xy visiblesize; visiblesize.x = (bounds.right - bounds.left) / metrics().debug_font_width(); visiblesize.y = (bounds.bottom - bounds.top) / metrics().debug_font_height(); - // get the updated total rows/cols and left row/col - totalsize = m_view->total_size(); - topleft = m_view->visible_position(); - // determine if we need to show the scrollbars - show_vscroll = show_hscroll = false; - if (totalsize.x > visiblesize.x && bounds.bottom >= metrics().hscroll_height()) + bool const fit_hscroll = (bounds.bottom - bounds.top) > metrics().hscroll_height(); + bool show_hscroll = fit_hscroll && (totalsize.x > visiblesize.x); + if (show_hscroll) { bounds.bottom -= metrics().hscroll_height(); visiblesize.y = (bounds.bottom - bounds.top) / metrics().debug_font_height(); - show_hscroll = true; - } - if (totalsize.y > visiblesize.y && bounds.right >= metrics().vscroll_width()) - { - bounds.right -= metrics().vscroll_width(); - visiblesize.x = (bounds.right - bounds.left) / metrics().debug_font_width(); - show_vscroll = true; } - if (!show_vscroll && totalsize.y > visiblesize.y && bounds.right >= metrics().vscroll_width()) + bool const fit_vscroll = (bounds.right - bounds.left) > metrics().vscroll_width(); + bool const show_vscroll = fit_vscroll && (totalsize.y > visiblesize.y); + if (show_vscroll) { bounds.right -= metrics().vscroll_width(); visiblesize.x = (bounds.right - bounds.left) / metrics().debug_font_width(); - show_vscroll = true; + if (fit_hscroll && !show_hscroll && (totalsize.x > visiblesize.x)) + { + bounds.bottom -= metrics().hscroll_height(); + visiblesize.y = (bounds.bottom - bounds.top) / metrics().debug_font_height(); + show_hscroll = true; + } } // compute the bounds of the scrollbars + RECT vscroll_bounds; GetClientRect(m_wnd, &vscroll_bounds); vscroll_bounds.left = vscroll_bounds.right - metrics().vscroll_width(); if (show_hscroll) vscroll_bounds.bottom -= metrics().hscroll_height(); - + RECT hscroll_bounds; GetClientRect(m_wnd, &hscroll_bounds); hscroll_bounds.top = hscroll_bounds.bottom - metrics().hscroll_height(); if (show_vscroll) @@ -481,26 +684,34 @@ void debugview_info::update() topleft.x = std::max(totalsize.x - visiblesize.x, 0); // fill out the scroll info struct for the vertical scrollbar - scrollinfo.cbSize = sizeof(scrollinfo); - scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; - scrollinfo.nMin = 0; - scrollinfo.nMax = totalsize.y - 1; - scrollinfo.nPage = visiblesize.y; - scrollinfo.nPos = topleft.y; - SetScrollInfo(m_vscroll, SB_CTL, &scrollinfo, TRUE); + if (m_vscroll) + { + scrollinfo.cbSize = sizeof(scrollinfo); + scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + scrollinfo.nMin = 0; + scrollinfo.nMax = totalsize.y - 1; + scrollinfo.nPage = visiblesize.y; + scrollinfo.nPos = topleft.y; + SetScrollInfo(m_vscroll, SB_CTL, &scrollinfo, TRUE); + } // fill out the scroll info struct for the horizontal scrollbar - scrollinfo.cbSize = sizeof(scrollinfo); - scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; - scrollinfo.nMin = 0; - scrollinfo.nMax = totalsize.x - 1; - scrollinfo.nPage = visiblesize.x; - scrollinfo.nPos = topleft.x; - SetScrollInfo(m_hscroll, SB_CTL, &scrollinfo, TRUE); + if (m_hscroll) + { + scrollinfo.cbSize = sizeof(scrollinfo); + scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + scrollinfo.nMin = 0; + scrollinfo.nMax = totalsize.x - 1; + scrollinfo.nPage = visiblesize.x; + scrollinfo.nPos = topleft.x; + SetScrollInfo(m_hscroll, SB_CTL, &scrollinfo, TRUE); + } // update window info - visiblesize.y++; - visiblesize.x++; + if (((bounds.right - bounds.left) > (visiblesize.x * metrics().debug_font_width())) && ((topleft.x + visiblesize.x) < totalsize.x)) + visiblesize.x++; + if (((bounds.bottom - bounds.top) > (visiblesize.y * metrics().debug_font_height())) && ((topleft.y + visiblesize.y) < totalsize.y)) + visiblesize.y++; m_view->set_visible_size(visiblesize); m_view->set_visible_position(topleft); @@ -580,7 +791,41 @@ uint32_t debugview_info::process_scroll(WORD type, HWND wnd) scrollinfo.nPos = result; SetScrollInfo(wnd, SB_CTL, &scrollinfo, TRUE); - return (uint32_t)result; + return uint32_t(result); +} + + +bool debugview_info::process_context_menu(int x, int y) +{ + // don't show a menu if not in client rect + RECT clientrect; + GetClientRect(m_wnd, &clientrect); + POINT loc{ x, y }; + ScreenToClient(m_wnd, &loc); + if (!PtInRect(&clientrect, loc)) + return false; + + // create the context menu if we haven’t already + if (!m_contextmenu) + { + m_contextmenu = CreatePopupMenu(); + if (!m_contextmenu) + return false; + add_items_to_context_menu(m_contextmenu); + } + + // show the context menu + update_context_menu(m_contextmenu); + BOOL const command(TrackPopupMenu( + m_contextmenu, + (GetSystemMetrics(SM_MENUDROPALIGNMENT) ? TPM_RIGHTALIGN : TPM_LEFTALIGN) | TPM_LEFTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, + x, y, + 0, + m_wnd, + nullptr)); + if (command) + handle_context_menu(command); + return true; } @@ -603,7 +848,7 @@ LRESULT debugview_info::view_proc(UINT message, WPARAM wparam, LPARAM lparam) case WM_SYSKEYDOWN: if (wparam != VK_F10) return DefWindowProc(m_wnd, message, wparam, lparam); - // (fall through) + [[fallthrough]]; case WM_KEYDOWN: { if (m_owner.handle_key(wparam, lparam)) @@ -717,17 +962,33 @@ LRESULT debugview_info::view_proc(UINT message, WPARAM wparam, LPARAM lparam) // mouse click case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: { - debug_view_xy topleft = m_view->visible_position(); + debug_view_xy const topleft = m_view->visible_position(); + debug_view_xy const visiblesize = m_view->visible_size(); debug_view_xy newpos; - newpos.x = topleft.x + GET_X_LPARAM(lparam) / metrics().debug_font_width(); - newpos.y = topleft.y + GET_Y_LPARAM(lparam) / metrics().debug_font_height(); - m_view->process_click(DCK_LEFT_CLICK, newpos); + newpos.x = std::max(std::min<int>(topleft.x + GET_X_LPARAM(lparam) / metrics().debug_font_width(), topleft.x + visiblesize.x - 1), 0); + newpos.y = std::max(std::min<int>(topleft.y + GET_Y_LPARAM(lparam) / metrics().debug_font_height(), topleft.y + visiblesize.y - 1), 0); + m_view->process_click((message == WM_LBUTTONDOWN) ? DCK_LEFT_CLICK : DCK_MIDDLE_CLICK, newpos); SetFocus(m_wnd); break; } - // hscroll + // right click + case WM_RBUTTONDOWN: + if (m_view->cursor_supported()) + { + debug_view_xy const topleft = m_view->visible_position(); + debug_view_xy const visiblesize = m_view->visible_size(); + debug_view_xy newpos; + newpos.x = std::max(std::min<int>(topleft.x + GET_X_LPARAM(lparam) / metrics().debug_font_width(), topleft.x + visiblesize.x - 1), 0); + newpos.y = std::max(std::min<int>(topleft.y + GET_Y_LPARAM(lparam) / metrics().debug_font_height(), topleft.y + visiblesize.y - 1), 0); + m_view->set_cursor_position(newpos); + m_view->set_cursor_visible(true); + } + return DefWindowProc(m_wnd, message, wparam, lparam); + + // horizontal scroll case WM_HSCROLL: { debug_view_xy topleft = m_view->visible_position(); @@ -737,7 +998,7 @@ LRESULT debugview_info::view_proc(UINT message, WPARAM wparam, LPARAM lparam) break; } - // vscroll + // vertical scroll case WM_VSCROLL: { debug_view_xy topleft = m_view->visible_position(); @@ -747,6 +1008,11 @@ LRESULT debugview_info::view_proc(UINT message, WPARAM wparam, LPARAM lparam) break; } + case WM_CONTEXTMENU: + if (!process_context_menu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam))) + return DefWindowProc(m_wnd, message, wparam, lparam); + break; + // everything else: defaults default: return DefWindowProc(m_wnd, message, wparam, lparam); @@ -758,7 +1024,7 @@ LRESULT debugview_info::view_proc(UINT message, WPARAM wparam, LPARAM lparam) void debugview_info::static_update(debug_view &view, void *osdprivate) { - debugview_info *const info = (debugview_info *)osdprivate; + auto *const info = (debugview_info *)osdprivate; assert(info->m_view == &view); info->update(); } @@ -774,7 +1040,7 @@ LRESULT CALLBACK debugview_info::static_view_proc(HWND wnd, UINT message, WPARAM return 0; } - debugview_info *const info = (debugview_info *)(uintptr_t)GetWindowLongPtr(wnd, GWLP_USERDATA); + auto *const info = (debugview_info *)(uintptr_t)GetWindowLongPtr(wnd, GWLP_USERDATA); if (info == nullptr) return DefWindowProc(wnd, message, wparam, lparam); @@ -810,3 +1076,5 @@ void debugview_info::register_window_class() s_window_class_registered = true; } } + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/debugviewinfo.h b/src/osd/modules/debugger/win/debugviewinfo.h index 37d6930e445..a009c368441 100644 --- a/src/osd/modules/debugger/win/debugviewinfo.h +++ b/src/osd/modules/debugger/win/debugviewinfo.h @@ -5,9 +5,10 @@ // debugviewinfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DEBUGVIEWINFO_H +#define MAME_DEBUGGER_WIN_DEBUGVIEWINFO_H -#ifndef __DEBUG_WIN_DEBUG_VIEW_INFO_H__ -#define __DEBUG_WIN_DEBUG_VIEW_INFO_H__ +#pragma once #include "debugwin.h" @@ -16,6 +17,8 @@ #include "debug/debugvw.h" +namespace osd::debugger::win { + class debugview_info : protected debugbase_info { public: @@ -41,6 +44,7 @@ public: bool cursor_supported() const { return m_view->cursor_supported(); } bool cursor_visible() const { return m_view->cursor_visible(); } + int source_index() const; char const *source_name() const; device_t *source_device() const; bool source_is_visible_cpu() const; @@ -50,13 +54,27 @@ public: HWND create_source_combobox(HWND parent, LONG_PTR userdata); + virtual void restore_configuration_from_node(util::xml::data_node const &node); + virtual void save_configuration_to_node(util::xml::data_node &node); + protected: + enum + { + ID_CONTEXT_COPY_VISIBLE = 1, + ID_CONTEXT_PASTE + }; + template <typename T> T *view() const { return downcast<T *>(m_view); } + virtual void add_items_to_context_menu(HMENU menu); + virtual void update_context_menu(HMENU menu); + virtual void handle_context_menu(unsigned command); + private: void draw_contents(HDC windc); void update(); uint32_t process_scroll(WORD type, HWND wnd); + bool process_context_menu(int x, int y); LRESULT view_proc(UINT message, WPARAM wparam, LPARAM lparam); static void static_update(debug_view &view, void *osdprivate); @@ -69,8 +87,11 @@ private: HWND m_wnd; HWND m_hscroll; HWND m_vscroll; + HMENU m_contextmenu; static bool s_window_class_registered; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_DEBUGVIEWINFO_H diff --git a/src/osd/modules/debugger/win/debugwin.h b/src/osd/modules/debugger/win/debugwin.h index ea78f126d5b..d8af29b795e 100644 --- a/src/osd/modules/debugger/win/debugwin.h +++ b/src/osd/modules/debugger/win/debugwin.h @@ -5,9 +5,12 @@ // debugwin.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DEBUGWIN_H +#define MAME_DEBUGGER_WIN_DEBUGWIN_H -#ifndef __DEBUG_WIN_DEBUG_WIN_H__ -#define __DEBUG_WIN_DEBUG_WIN_H__ +#pragma once + +#include "../xmlconfig.h" // standard windows headers #include <windows.h> @@ -19,6 +22,7 @@ #endif +namespace osd::debugger::win { class debugview_info; class debugwin_info; @@ -33,6 +37,12 @@ public: virtual running_machine &machine() const = 0; virtual ui_metrics &metrics() const = 0; + virtual void set_color_theme(int index) = 0; + virtual bool get_save_window_arrangement() const = 0; + virtual void set_save_window_arrangement(bool save) = 0; + virtual bool get_group_windows() const = 0; + virtual bool get_group_windows_setting() const = 0; + virtual void set_group_windows_setting(bool group) = 0; virtual bool const &waiting_for_debugger() const = 0; virtual bool seq_pressed() const = 0; @@ -45,6 +55,10 @@ public: virtual void show_all() = 0; virtual void hide_all() = 0; + + virtual void stagger_window(HWND window, int width, int height) = 0; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_DEBUGWIN_H diff --git a/src/osd/modules/debugger/win/debugwininfo.cpp b/src/osd/modules/debugger/win/debugwininfo.cpp index ac60b980439..f27f7933f08 100644 --- a/src/osd/modules/debugger/win/debugwininfo.cpp +++ b/src/osd/modules/debugger/win/debugwininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// debugwininfo.c - Win32 debug window handling +// debugwininfo.cpp - Win32 debug window handling // //============================================================ @@ -12,13 +12,21 @@ #include "debugviewinfo.h" #include "debugger.h" +#include "debug/debugcon.h" #include "debug/debugcpu.h" + +#include "util/xmlfile.h" + #include "window.h" #include "winutf8.h" - #include "winutil.h" + #include "modules/lib/osdobj_common.h" +#include <cstring> + + +namespace osd::debugger::win { bool debugwin_info::s_window_class_registered = false; @@ -36,9 +44,16 @@ debugwin_info::debugwin_info(debugger_windows_interface &debugger, bool is_main_ { register_window_class(); - m_wnd = win_create_window_ex_utf8(DEBUG_WINDOW_STYLE_EX, "MAMEDebugWindow", title, DEBUG_WINDOW_STYLE, - 0, 0, 100, 100, std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(), create_standard_menubar(), GetModuleHandleUni(), this); - if (m_wnd == nullptr) + m_wnd = win_create_window_ex_utf8( + DEBUG_WINDOW_STYLE_EX, "MAMEDebugWindow", title, DEBUG_WINDOW_STYLE, + 0, 0, 100, 100, + debugger.get_group_windows() + ? dynamic_cast<win_window_info &>(*osd_common_t::window_list().front()).platform_window() + : nullptr, + create_standard_menubar(), + GetModuleHandleUni(), + this); + if (!m_wnd) return; RECT work_bounds; @@ -53,6 +68,12 @@ debugwin_info::~debugwin_info() } +void debugwin_info::redraw() +{ + RedrawWindow(m_wnd, nullptr, nullptr, RDW_INVALIDATE | RDW_ALLCHILDREN); +} + + void debugwin_info::destroy() { for (int curview = 0; curview < MAX_VIEWS; curview++) @@ -250,6 +271,89 @@ bool debugwin_info::handle_key(WPARAM wparam, LPARAM lparam) } +void debugwin_info::save_configuration(util::xml::data_node &parentnode) +{ + util::xml::data_node *const node = parentnode.add_child(NODE_WINDOW, nullptr); + if (node) + save_configuration_to_node(*node); +} + + +void debugwin_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + // get current size to use for defaults + RECT bounds; + POINT origin; + origin.x = 0; + origin.y = 0; + if (!GetClientRect(window(), &bounds) && ClientToScreen(window(), &origin)) + return; + + // get saved size and adjust for window chrome + RECT desired; + desired.left = node.get_attribute_int(ATTR_WINDOW_POSITION_X, origin.x); + desired.top = node.get_attribute_int(ATTR_WINDOW_POSITION_Y, origin.y); + desired.right = desired.left + node.get_attribute_int(ATTR_WINDOW_WIDTH, bounds.right); + desired.bottom = desired.top + node.get_attribute_int(ATTR_WINDOW_HEIGHT, bounds.bottom); + // TODO: sanity checks... + if (!AdjustWindowRectEx(&desired, DEBUG_WINDOW_STYLE, GetMenu(window()) ? TRUE : FALSE, DEBUG_WINDOW_STYLE_EX)) + return; + + // actually move the window + MoveWindow( + window(), + desired.left, + desired.top, + desired.right - desired.left, + desired.bottom - desired.top, + TRUE); + + // restrict to one monitor and avoid toolbars + HMONITOR const nearest_monitor = MonitorFromWindow(window(), MONITOR_DEFAULTTONEAREST); + if (nearest_monitor) + { + MONITORINFO info; + std::memset(&info, 0, sizeof(info)); + info.cbSize = sizeof(info); + if (GetMonitorInfo(nearest_monitor, &info)) + { + if (desired.right > info.rcWork.right) + { + desired.left -= desired.right - info.rcWork.right; + desired.right = info.rcWork.right; + } + if (desired.bottom > info.rcWork.bottom) + { + desired.top -= desired.bottom - info.rcWork.bottom; + desired.bottom = info.rcWork.bottom; + } + if (desired.left < info.rcWork.left) + { + desired.right += info.rcWork.left - desired.left; + desired.left = info.rcWork.left; + } + if (desired.top < info.rcWork.top) + { + desired.bottom += info.rcWork.top - desired.top; + desired.top = info.rcWork.top; + } + desired.bottom = std::min(info.rcWork.bottom, desired.bottom); + desired.right = std::min(info.rcWork.right, desired.right); + MoveWindow( + window(), + desired.left, + desired.top, + desired.right - desired.left, + desired.bottom - desired.top, + TRUE); + } + } + + // sort out contents + recompute_children(); +} + + void debugwin_info::recompute_children() { if (m_views[0] != nullptr) @@ -299,39 +403,40 @@ bool debugwin_info::handle_command(WPARAM wparam, LPARAM lparam) case ID_RUN_AND_HIDE: debugger().hide_all(); + [[fallthrough]]; case ID_RUN: - machine().debugger().cpu().get_visible_cpu()->debug()->go(); + machine().debugger().console().get_visible_cpu()->debug()->go(); return true; case ID_NEXT_CPU: - machine().debugger().cpu().get_visible_cpu()->debug()->go_next_device(); + machine().debugger().console().get_visible_cpu()->debug()->go_next_device(); return true; case ID_RUN_VBLANK: - machine().debugger().cpu().get_visible_cpu()->debug()->go_vblank(); + machine().debugger().console().get_visible_cpu()->debug()->go_vblank(); return true; case ID_RUN_IRQ: - machine().debugger().cpu().get_visible_cpu()->debug()->go_interrupt(); + machine().debugger().console().get_visible_cpu()->debug()->go_interrupt(); return true; case ID_STEP: - machine().debugger().cpu().get_visible_cpu()->debug()->single_step(); + machine().debugger().console().get_visible_cpu()->debug()->single_step(); return true; case ID_STEP_OVER: - machine().debugger().cpu().get_visible_cpu()->debug()->single_step_over(); + machine().debugger().console().get_visible_cpu()->debug()->single_step_over(); return true; case ID_STEP_OUT: - machine().debugger().cpu().get_visible_cpu()->debug()->single_step_out(); + machine().debugger().console().get_visible_cpu()->debug()->single_step_out(); return true; case ID_REWIND_STEP: machine().rewind_step(); // clear all PC & memory tracks - for (device_t &device : device_iterator(machine().root_device())) + for (device_t &device : device_enumerator(machine().root_device())) { device.debug()->track_pc_data_clear(); device.debug()->track_mem_data_clear(); @@ -348,7 +453,7 @@ bool debugwin_info::handle_command(WPARAM wparam, LPARAM lparam) case ID_SOFT_RESET: machine().schedule_soft_reset(); - machine().debugger().cpu().get_visible_cpu()->debug()->go(); + machine().debugger().console().get_visible_cpu()->debug()->go(); return true; case ID_EXIT: @@ -390,6 +495,22 @@ void debugwin_info::draw_border(HDC dc, RECT &bounds) } +void debugwin_info::save_configuration_to_node(util::xml::data_node &node) +{ + RECT bounds; + POINT origin; + origin.x = 0; + origin.y = 0; + if (GetClientRect(window(), &bounds) && ClientToScreen(window(), &origin)) + { + node.set_attribute_int(ATTR_WINDOW_POSITION_X, origin.x); + node.set_attribute_int(ATTR_WINDOW_POSITION_Y, origin.y); + node.set_attribute_int(ATTR_WINDOW_WIDTH, bounds.right); + node.set_attribute_int(ATTR_WINDOW_HEIGHT, bounds.bottom); + } +} + + void debugwin_info::draw_border(HDC dc, HWND child) { RECT bounds; @@ -437,11 +558,10 @@ LRESULT debugwin_info::window_proc(UINT message, WPARAM wparam, LPARAM lparam) // get min/max info: set the minimum window size case WM_GETMINMAXINFO: { - MINMAXINFO *minmax = (MINMAXINFO *)lparam; + auto *minmax = (MINMAXINFO *)lparam; minmax->ptMinTrackSize.x = m_minwidth; minmax->ptMinTrackSize.y = m_minheight; - minmax->ptMaxSize.x = minmax->ptMaxTrackSize.x = m_maxwidth; - minmax->ptMaxSize.y = minmax->ptMaxTrackSize.y = m_maxheight; + // Leave default ptMaxSize and ptMaxTrackSize so maximum size is not restricted break; } @@ -507,7 +627,7 @@ LRESULT debugwin_info::window_proc(UINT message, WPARAM wparam, LPARAM lparam) if (m_is_main_console) { debugger().hide_all(); - machine().debugger().cpu().get_visible_cpu()->debug()->go(); + machine().debugger().console().get_visible_cpu()->debug()->go(); } else { @@ -575,14 +695,14 @@ LRESULT CALLBACK debugwin_info::static_window_proc(HWND wnd, UINT message, WPARA { // set the info pointer CREATESTRUCT const *const createinfo = (CREATESTRUCT *)lparam; - debugwin_info *const info = (debugwin_info *)createinfo->lpCreateParams; + auto *const info = (debugwin_info *)createinfo->lpCreateParams; SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)createinfo->lpCreateParams); if (info->m_handler) SetWindowLongPtr(wnd, GWLP_WNDPROC, (LONG_PTR)info->m_handler); return 0; } - debugwin_info *const info = (debugwin_info *)(uintptr_t)GetWindowLongPtr(wnd, GWLP_USERDATA); + auto *const info = (debugwin_info *)(uintptr_t)GetWindowLongPtr(wnd, GWLP_USERDATA); if (info == nullptr) return DefWindowProc(wnd, message, wparam, lparam); @@ -618,3 +738,5 @@ void debugwin_info::register_window_class() s_window_class_registered = true; } } + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/debugwininfo.h b/src/osd/modules/debugger/win/debugwininfo.h index 2090985d3f9..cf3587253f6 100644 --- a/src/osd/modules/debugger/win/debugwininfo.h +++ b/src/osd/modules/debugger/win/debugwininfo.h @@ -5,20 +5,21 @@ // debugwininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DEBUGWININFO_H +#define MAME_DEBUGGER_WIN_DEBUGWININFO_H -#ifndef __DEBUG_WIN_DEBUG_WIN_INFO_H__ -#define __DEBUG_WIN_DEBUG_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "debugbaseinfo.h" +namespace osd::debugger::win { class debugwin_info : protected debugbase_info { public: - debugwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler); virtual ~debugwin_info(); bool is_valid() const { return m_wnd != nullptr; } @@ -40,6 +41,7 @@ public: void show() const { smart_show_window(m_wnd, true); } void hide() const { smart_show_window(m_wnd, false); } void set_foreground() const { SetForegroundWindow(m_wnd); } + void redraw(); void destroy(); virtual bool set_default_focus(); @@ -49,6 +51,9 @@ public: virtual bool handle_key(WPARAM wparam, LPARAM lparam); + void save_configuration(util::xml::data_node &parentnode); + virtual void restore_configuration_from_node(util::xml::data_node const &node); + protected: static DWORD const DEBUG_WINDOW_STYLE = (WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN) & (~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX); static DWORD const DEBUG_WINDOW_STYLE_EX = 0; @@ -75,13 +80,20 @@ protected: ID_SOFT_RESET, ID_EXIT, - ID_1_BYTE_CHUNKS, - ID_2_BYTE_CHUNKS, - ID_4_BYTE_CHUNKS, - ID_8_BYTE_CHUNKS, - ID_FLOATING_POINT_32BIT, - ID_FLOATING_POINT_64BIT, - ID_FLOATING_POINT_80BIT, + ID_1_BYTE_CHUNKS_HEX, + ID_2_BYTE_CHUNKS_HEX, + ID_4_BYTE_CHUNKS_HEX, + ID_8_BYTE_CHUNKS_HEX, + ID_1_BYTE_CHUNKS_OCT, + ID_2_BYTE_CHUNKS_OCT, + ID_4_BYTE_CHUNKS_OCT, + ID_8_BYTE_CHUNKS_OCT, + ID_FLOAT_32BIT, + ID_FLOAT_64BIT, + ID_FLOAT_80BIT, + ID_HEX_ADDRESSES, + ID_DEC_ADDRESSES, + ID_OCT_ADDRESSES, ID_LOGICAL_ADDRESSES, ID_PHYSICAL_ADDRESSES, ID_REVERSE_VIEW, @@ -97,12 +109,21 @@ protected: ID_SHOW_BREAKPOINTS, ID_SHOW_WATCHPOINTS, + ID_SHOW_REGISTERPOINTS, + ID_SHOW_EXCEPTIONPOINTS, ID_CLEAR_LOG, + ID_SAVE_WINDOWS, + ID_GROUP_WINDOWS, + ID_LIGHT_BACKGROUND, + ID_DARK_BACKGROUND, + ID_DEVICE_OPTIONS // always keep this at the end }; + debugwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler); + bool is_main_console() const { return m_is_main_console; } HWND window() const { return m_wnd; } uint32_t minwidth() const { return m_minwidth; } @@ -117,6 +138,8 @@ protected: void draw_border(HDC dc, RECT &bounds); void draw_border(HDC dc, HWND child); + virtual void save_configuration_to_node(util::xml::data_node &node); + std::unique_ptr<debugview_info> m_views[MAX_VIEWS]; private: @@ -133,12 +156,14 @@ private: HWND m_wnd; WNDPROC const m_handler; - uint32_t m_minwidth, m_maxwidth; - uint32_t m_minheight, m_maxheight; + uint32_t m_minwidth, m_maxwidth; + uint32_t m_minheight, m_maxheight; - uint16_t m_ignore_char_lparam; + uint16_t m_ignore_char_lparam; static bool s_window_class_registered; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_DEBUGWININFO_H diff --git a/src/osd/modules/debugger/win/disasmbasewininfo.cpp b/src/osd/modules/debugger/win/disasmbasewininfo.cpp index c466e059f23..48771c4f133 100644 --- a/src/osd/modules/debugger/win/disasmbasewininfo.cpp +++ b/src/osd/modules/debugger/win/disasmbasewininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// disasmbasewininfo.c - Win32 debug window handling +// disasmbasewininfo.cpp - Win32 debug window handling // //============================================================ @@ -15,18 +15,21 @@ #include "debugger.h" #include "debug/debugcon.h" #include "debug/debugcpu.h" +#include "debug/points.h" //#include "winutf8.h" +namespace osd::debugger::win { + disasmbasewin_info::disasmbasewin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler) : editwin_info(debugger, is_main_console, title, handler) { if (!window()) return; - m_views[0].reset(global_alloc(disasmview_info(debugger, *this, window()))); - if ((m_views[0] == nullptr) || !m_views[0]->is_valid()) + m_views[0].reset(new disasmview_info(debugger, *this, window())); + if (!m_views[0] || !m_views[0]->is_valid()) { m_views[0].reset(); return; @@ -105,7 +108,7 @@ void disasmbasewin_info::update_menu() { editwin_info::update_menu(); - disasmview_info *const dasmview = downcast<disasmview_info *>(m_views[0].get()); + auto *const dasmview = downcast<disasmview_info *>(m_views[0].get()); HMENU const menu = GetMenu(window()); bool const disasm_cursor_visible = dasmview->cursor_visible(); @@ -115,9 +118,9 @@ void disasmbasewin_info::update_menu() device_debug *const debug = dasmview->source_device()->debug(); // first find an existing breakpoint at this address - const device_debug::breakpoint *bp = debug->breakpoint_find(address); + const debug_breakpoint *bp = debug->breakpoint_find(address); - if (bp == nullptr) + if (!bp) { ModifyMenu(menu, ID_TOGGLE_BREAKPOINT, MF_BYCOMMAND, ID_TOGGLE_BREAKPOINT, TEXT("Set breakpoint at cursor\tF9")); ModifyMenu(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND, ID_DISABLE_BREAKPOINT, TEXT("Disable breakpoint at cursor\tShift+F9")); @@ -130,7 +133,7 @@ void disasmbasewin_info::update_menu() else ModifyMenu(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND, ID_DISABLE_BREAKPOINT, TEXT("Enable breakpoint at cursor\tShift+F9")); } - bool const available = (bp != nullptr) && (!is_main_console() || dasmview->source_is_visible_cpu()); + bool const available = bp && (!is_main_console() || dasmview->source_is_visible_cpu()); EnableMenuItem(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND | (available ? MF_ENABLED : MF_GRAYED)); } else @@ -151,7 +154,7 @@ void disasmbasewin_info::update_menu() bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) { - disasmview_info *const dasmview = downcast<disasmview_info *>(m_views[0].get()); + auto *const dasmview = downcast<disasmview_info *>(m_views[0].get()); switch (HIWORD(wparam)) { @@ -166,14 +169,14 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) device_debug *const debug = dasmview->source_device()->debug(); // first find an existing breakpoint at this address - const device_debug::breakpoint *bp = debug->breakpoint_find(address); + const debug_breakpoint *bp = debug->breakpoint_find(address); // if it doesn't exist, add a new one if (!is_main_console()) { if (bp == nullptr) { - int32_t bpindex = debug->breakpoint_set(address, nullptr, nullptr); + int32_t bpindex = debug->breakpoint_set(address); machine().debugger().console().printf("Breakpoint %X set\n", bpindex); } else @@ -192,7 +195,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) command = string_format("bpset 0x%X", address); else command = string_format("bpclear 0x%X", bp->index()); - machine().debugger().console().execute_command(command.c_str(), true); + machine().debugger().console().execute_command(command, true); } } return true; @@ -204,7 +207,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) device_debug *const debug = dasmview->source_device()->debug(); // first find an existing breakpoint at this address - const device_debug::breakpoint *bp = debug->breakpoint_find(address); + const debug_breakpoint *bp = debug->breakpoint_find(address); // if it doesn't exist, add a new one if (bp != nullptr) @@ -220,7 +223,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) { std::string command; command = string_format(bp->enabled() ? "bpdisable 0x%X" : "bpenable 0x%X", (uint32_t)bp->index()); - machine().debugger().console().execute_command(command.c_str(), true); + machine().debugger().console().execute_command(command, true); } } } @@ -234,7 +237,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) { std::string command; command = string_format("go 0x%X", address); - machine().debugger().console().execute_command(command.c_str(), true); + machine().debugger().console().execute_command(command, true); } else { @@ -262,3 +265,19 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam) } return editwin_info::handle_command(wparam, lparam); } + + +void disasmbasewin_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + editwin_info::restore_configuration_from_node(node); + m_views[0]->restore_configuration_from_node(node); +} + + +void disasmbasewin_info::save_configuration_to_node(util::xml::data_node &node) +{ + editwin_info::save_configuration_to_node(node); + m_views[0]->save_configuration_to_node(node); +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/disasmbasewininfo.h b/src/osd/modules/debugger/win/disasmbasewininfo.h index 26cd481b7f6..1ef8245b5a0 100644 --- a/src/osd/modules/debugger/win/disasmbasewininfo.h +++ b/src/osd/modules/debugger/win/disasmbasewininfo.h @@ -5,15 +5,18 @@ // disasmbasewininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DISASMBASEWININFO_H +#define MAME_DEBUGGER_WIN_DISASMBASEWININFO_H -#ifndef __DEBUG_WIN_DISASM_BASE_WIN_INFO_H__ -#define __DEBUG_WIN_DISASM_BASE_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "editwininfo.h" +namespace osd::debugger::win { + class disasmbasewin_info : public editwin_info { public: @@ -21,10 +24,14 @@ public: virtual ~disasmbasewin_info(); virtual bool handle_key(WPARAM wparam, LPARAM lparam) override; + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; protected: virtual void update_menu() override; virtual bool handle_command(WPARAM wparam, LPARAM lparam) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_DISASMBASEWININFO_H diff --git a/src/osd/modules/debugger/win/disasmviewinfo.cpp b/src/osd/modules/debugger/win/disasmviewinfo.cpp index 8884bee5195..3cf9dbd70ff 100644 --- a/src/osd/modules/debugger/win/disasmviewinfo.cpp +++ b/src/osd/modules/debugger/win/disasmviewinfo.cpp @@ -2,13 +2,17 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// disasmviewinfo.c - Win32 debug window handling +// disasmviewinfo.cpp - Win32 debug window handling // //============================================================ #include "emu.h" #include "disasmviewinfo.h" +#include "util/xmlfile.h" + + +namespace osd::debugger::win { disasmview_info::disasmview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) : debugview_info(debugger, owner, parent, DVT_DISASSEMBLY) @@ -21,6 +25,12 @@ disasmview_info::~disasmview_info() } +char const *disasmview_info::expression() const +{ + return view<debug_view_disasm>()->expression(); +} + + disasm_right_column disasmview_info::right_column() const { return view<debug_view_disasm>()->right_column(); @@ -43,3 +53,23 @@ void disasmview_info::set_right_column(disasm_right_column contents) { view<debug_view_disasm>()->set_right_column(contents); } + + +void disasmview_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + debug_view_disasm &dasmview(*view<debug_view_disasm>()); + dasmview.set_right_column(disasm_right_column(node.get_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column()))); + + debugview_info::restore_configuration_from_node(node); +} + + +void disasmview_info::save_configuration_to_node(util::xml::data_node &node) +{ + debugview_info::save_configuration_to_node(node); + + debug_view_disasm &dasmview(*view<debug_view_disasm>()); + node.set_attribute_int(ATTR_WINDOW_DISASSEMBLY_RIGHT_COLUMN, dasmview.right_column()); +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/disasmviewinfo.h b/src/osd/modules/debugger/win/disasmviewinfo.h index d1e7090ef2f..809f92b0c14 100644 --- a/src/osd/modules/debugger/win/disasmviewinfo.h +++ b/src/osd/modules/debugger/win/disasmviewinfo.h @@ -5,9 +5,10 @@ // disasmviewinfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DISASMVIEWINFO_H +#define MAME_DEBUGGER_WIN_DISASMVIEWINFO_H -#ifndef __DEBUG_WIN_DISASM_VIEW_INFO_H__ -#define __DEBUG_WIN_DISASM_VIEW_INFO_H__ +#pragma once #include "debugwin.h" @@ -16,17 +17,25 @@ #include "debug/dvdisasm.h" +namespace osd::debugger::win { + class disasmview_info : public debugview_info { public: disasmview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent); virtual ~disasmview_info(); + char const *expression() const; disasm_right_column right_column() const; offs_t selected_address() const; void set_expression(const std::string &expression); void set_right_column(disasm_right_column contents); + + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_DISASMVIEWINFO_H diff --git a/src/osd/modules/debugger/win/disasmwininfo.cpp b/src/osd/modules/debugger/win/disasmwininfo.cpp index b94eadbba03..6b38609ace8 100644 --- a/src/osd/modules/debugger/win/disasmwininfo.cpp +++ b/src/osd/modules/debugger/win/disasmwininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// disasmwininfo.c - Win32 debug window handling +// disasmwininfo.cpp - Win32 debug window handling // //============================================================ @@ -12,9 +12,14 @@ #include "debugviewinfo.h" #include "disasmviewinfo.h" #include "uimetrics.h" + +#include "util/xmlfile.h" + #include "winutf8.h" +namespace osd::debugger::win { + disasmwin_info::disasmwin_info(debugger_windows_interface &debugger) : disasmbasewin_info(debugger, false, "Disassembly", nullptr), m_combownd(nullptr) @@ -34,11 +39,11 @@ disasmwin_info::disasmwin_info(debugger_windows_interface &debugger) : update_caption(); // recompute the children once to get the maxwidth - disasmwin_info::recompute_children(); + recompute_children(); // position the window and recompute children again - SetWindowPos(window(), HWND_TOP, 100, 100, maxwidth(), 200, SWP_SHOWWINDOW); - disasmwin_info::recompute_children(); + debugger.stagger_window(window(), maxwidth(), 200); + recompute_children(); // mark the edit box as the default focus and set it editwin_info::set_default_focus(); @@ -143,3 +148,34 @@ void disasmwin_info::update_caption() { win_set_window_text_utf8(window(), std::string("Disassembly: ").append(m_views[0]->source_name()).c_str()); } + + +void disasmwin_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + m_views[0]->set_source_index(node.get_attribute_int(ATTR_WINDOW_DISASSEMBLY_CPU, m_views[0]->source_index())); + int const cursource = m_views[0]->source_index(); + if (0 <= cursource) + SendMessage(m_combownd, CB_SETCURSEL, cursource, 0); + update_caption(); + + util::xml::data_node const *const expr = node.get_child(NODE_WINDOW_EXPRESSION); + if (expr && expr->get_value()) + { + set_editwnd_text(expr->get_value()); + process_string(expr->get_value()); + } + + disasmbasewin_info::restore_configuration_from_node(node); +} + + +void disasmwin_info::save_configuration_to_node(util::xml::data_node &node) +{ + disasmbasewin_info::save_configuration_to_node(node); + + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_DISASSEMBLY_VIEWER); + node.set_attribute_int(ATTR_WINDOW_DISASSEMBLY_CPU, m_views[0]->source_index()); + node.add_child(NODE_WINDOW_EXPRESSION, downcast<disasmview_info *>(m_views[0].get())->expression()); +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/disasmwininfo.h b/src/osd/modules/debugger/win/disasmwininfo.h index 34e8275f2f9..e5a5ceaaa0e 100644 --- a/src/osd/modules/debugger/win/disasmwininfo.h +++ b/src/osd/modules/debugger/win/disasmwininfo.h @@ -5,25 +5,31 @@ // disasmwininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_DISASMWININFO_H +#define MAME_DEBUGGER_WIN_DISASMWININFO_H -#ifndef __DEBUG_WIN_DISASM_WIN_INFO_H__ -#define __DEBUG_WIN_DISASM_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "disasmbasewininfo.h" +namespace osd::debugger::win { + class disasmwin_info : public disasmbasewin_info { public: disasmwin_info(debugger_windows_interface &debugger); virtual ~disasmwin_info(); + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; + protected: virtual void recompute_children() override; virtual bool handle_command(WPARAM wparam, LPARAM lparam) override; virtual void draw_contents(HDC dc) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; private: virtual void process_string(const std::string &string) override; @@ -33,4 +39,6 @@ private: HWND m_combownd; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_DISASMWININFO_H diff --git a/src/osd/modules/debugger/win/editwininfo.cpp b/src/osd/modules/debugger/win/editwininfo.cpp index af3dd1bf66e..c62d2b1f4f7 100644 --- a/src/osd/modules/debugger/win/editwininfo.cpp +++ b/src/osd/modules/debugger/win/editwininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// editwininfo.c - Win32 debug window handling +// editwininfo.cpp - Win32 debug window handling // //============================================================ @@ -12,18 +12,22 @@ #include "debugviewinfo.h" #include "uimetrics.h" +#include "xmlfile.h" + #include "strconv.h" #include "winutil.h" +namespace osd::debugger::win { + namespace { constexpr DWORD EDIT_BOX_STYLE = WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL; constexpr DWORD EDIT_BOX_STYLE_EX = 0; constexpr int MAX_EDIT_STRING = 256; -constexpr int HISTORY_LENGTH = 20; +constexpr int HISTORY_LENGTH = 100; } // anonymous namespace @@ -34,7 +38,7 @@ editwin_info::editwin_info(debugger_windows_interface &debugger, bool is_main_co m_edit_defstr(), m_original_editproc(nullptr), m_history(), - m_last_history(0) + m_last_history(-1) { if (window() == nullptr) return; @@ -105,6 +109,43 @@ void editwin_info::draw_contents(HDC dc) } +void editwin_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + m_history.clear(); + util::xml::data_node const *const hist = node.get_child(NODE_WINDOW_HISTORY); + if (hist) + { + util::xml::data_node const *item = hist->get_child(NODE_HISTORY_ITEM); + while (item) + { + if (item->get_value() && *item->get_value()) + { + while (m_history.size() >= HISTORY_LENGTH) + m_history.pop_back(); + m_history.emplace_front(osd::text::to_tstring(item->get_value())); + } + item = item->get_next_sibling(NODE_HISTORY_ITEM); + } + } + m_last_history = -1; + + debugwin_info::restore_configuration_from_node(node); +} + + +void editwin_info::save_configuration_to_node(util::xml::data_node &node) +{ + debugwin_info::save_configuration_to_node(node); + + util::xml::data_node *const hist = node.add_child(NODE_WINDOW_HISTORY, nullptr); + if (hist) + { + for (auto it = m_history.crbegin(); m_history.crend() != it; ++it) + hist->add_child(NODE_HISTORY_ITEM, osd::text::from_tstring(*it).c_str()); + } +} + + LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam) { // handle a few messages @@ -114,7 +155,7 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam) case WM_SYSKEYDOWN: if (wparam != VK_F10) return CallWindowProc(m_original_editproc, m_editwnd, message, wparam, lparam); - // (fall through) + [[fallthrough]]; case WM_KEYDOWN: switch (wparam) { @@ -185,7 +226,7 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam) case 13: // carriage return { // fetch the text - SendMessage(m_editwnd, WM_GETTEXT, WPARAM(ARRAY_LENGTH(buffer)), LPARAM(buffer)); + SendMessage(m_editwnd, WM_GETTEXT, WPARAM(std::size(buffer)), LPARAM(buffer)); // add to the history if it's not a repeat of the last one if (buffer[0] && (m_history.empty() || _tcscmp(buffer, m_history[0].c_str()))) @@ -194,12 +235,12 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam) m_history.pop_back(); m_history.emplace_front(buffer); } - m_last_history = m_history.size() - 1; + m_last_history = -1; // process { auto utf8_buffer = osd::text::from_tstring(buffer); - process_string(utf8_buffer.c_str()); + process_string(utf8_buffer); } } break; @@ -237,7 +278,9 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam) LRESULT CALLBACK editwin_info::static_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) { - editwin_info *const info = (editwin_info *)uintptr_t(GetWindowLongPtr(wnd, GWLP_USERDATA)); + auto *const info = (editwin_info *)uintptr_t(GetWindowLongPtr(wnd, GWLP_USERDATA)); assert(info->m_editwnd == wnd); return info->edit_proc(message, wparam, lparam); } + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/editwininfo.h b/src/osd/modules/debugger/win/editwininfo.h index 1aaee55f1e9..e2c0ce3c4b8 100644 --- a/src/osd/modules/debugger/win/editwininfo.h +++ b/src/osd/modules/debugger/win/editwininfo.h @@ -5,9 +5,10 @@ // editwininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_EDITWININFO_H +#define MAME_DEBUGGER_WIN_EDITWININFO_H -#ifndef MAME_DEBUG_WIN_EDIT_WIN_INFO_H -#define MAME_DEBUG_WIN_EDIT_WIN_INFO_H +#pragma once #include "debugwin.h" @@ -17,6 +18,8 @@ #include <string> +namespace osd::debugger::win { + class editwin_info : public debugwin_info { public: @@ -27,6 +30,8 @@ public: virtual bool set_default_focus() override; + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; + protected: constexpr static DWORD COMBO_BOX_STYLE = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL; constexpr static DWORD COMBO_BOX_STYLE_EX = 0; @@ -38,6 +43,8 @@ protected: virtual void draw_contents(HDC dc) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; + private: typedef std::deque<std::basic_string<TCHAR> > history_deque; @@ -54,4 +61,6 @@ private: int m_last_history; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_EDITWININFO_H diff --git a/src/osd/modules/debugger/win/logviewinfo.cpp b/src/osd/modules/debugger/win/logviewinfo.cpp index affd4acd17a..c6bbdfacb88 100644 --- a/src/osd/modules/debugger/win/logviewinfo.cpp +++ b/src/osd/modules/debugger/win/logviewinfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Samuele Zannoli //============================================================ // -// logviewinfo.c - Win32 debug log window handling +// logviewinfo.cpp - Win32 debug log window handling // //============================================================ @@ -12,6 +12,8 @@ #include "debug/dvtext.h" +namespace osd::debugger::win { + logview_info::logview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) : debugview_info(debugger, owner, parent, DVT_LOG) { @@ -27,3 +29,5 @@ void logview_info::clear() { view<debug_view_log>()->clear(); } + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/logviewinfo.h b/src/osd/modules/debugger/win/logviewinfo.h index da598038864..15de2a3a095 100644 --- a/src/osd/modules/debugger/win/logviewinfo.h +++ b/src/osd/modules/debugger/win/logviewinfo.h @@ -5,15 +5,18 @@ // logviewinfo.h - Win32 debug log window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_LOGVIEWINFO_H +#define MAME_DEBUGGER_WIN_LOGVIEWINFO_H -#ifndef __DEBUG_WIN_LOG_VIEW_INFO_H__ -#define __DEBUG_WIN_LOG_VIEW_INFO_H__ +#pragma once #include "debugwin.h" #include "debugviewinfo.h" +namespace osd::debugger::win { + class logview_info : public debugview_info { public: @@ -23,4 +26,6 @@ public: void clear(); }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_LOGVIEWINFO_H diff --git a/src/osd/modules/debugger/win/logwininfo.cpp b/src/osd/modules/debugger/win/logwininfo.cpp index 6d2cd59b554..40515906bb1 100644 --- a/src/osd/modules/debugger/win/logwininfo.cpp +++ b/src/osd/modules/debugger/win/logwininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// logwininfo.c - Win32 debug window handling +// logwininfo.cpp - Win32 debug window handling // //============================================================ @@ -12,6 +12,10 @@ #include "debugviewinfo.h" #include "logviewinfo.h" +#include "util/xmlfile.h" + + +namespace osd::debugger::win { logwin_info::logwin_info(debugger_windows_interface &debugger) : debugwin_info(debugger, false, std::string("Errorlog: ").append(debugger.machine().system().type.fullname()).append(" [").append(debugger.machine().system().name).append("]").c_str(), nullptr) @@ -19,7 +23,7 @@ logwin_info::logwin_info(debugger_windows_interface &debugger) : if (!window()) return; - m_views[0].reset(global_alloc(logview_info(debugger, *this, window()))); + m_views[0].reset(new logview_info(debugger, *this, window())); if ((m_views[0] == nullptr) || !m_views[0]->is_valid()) { m_views[0].reset(); @@ -41,11 +45,9 @@ logwin_info::logwin_info(debugger_windows_interface &debugger) : // clamp the min/max size set_maxwidth(bounds.right - bounds.left); - // position the window at the bottom-right - SetWindowPos(window(), HWND_TOP, 100, 100, bounds.right - bounds.left, bounds.bottom - bounds.top, SWP_SHOWWINDOW); - - // recompute the children - debugwin_info::recompute_children(); + // position the window and recompute children + debugger.stagger_window(window(), bounds.right - bounds.left, bounds.bottom - bounds.top); + recompute_children(); } @@ -63,3 +65,12 @@ bool logwin_info::handle_command(WPARAM wparam, LPARAM lparam) } return debugwin_info::handle_command(wparam, lparam); } + + +void logwin_info::save_configuration_to_node(util::xml::data_node &node) +{ + debugwin_info::save_configuration_to_node(node); + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_ERROR_LOG_VIEWER); +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/logwininfo.h b/src/osd/modules/debugger/win/logwininfo.h index a816b6f3da3..4e822f1b534 100644 --- a/src/osd/modules/debugger/win/logwininfo.h +++ b/src/osd/modules/debugger/win/logwininfo.h @@ -5,15 +5,18 @@ // logwininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_LOGWININFO_H +#define MAME_DEBUGGER_WIN_LOGWININFO_H -#ifndef __DEBUG_WIN_LOG_WIN_INFO_H__ -#define __DEBUG_WIN_LOG_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "debugwininfo.h" +namespace osd::debugger::win { + class logwin_info : public debugwin_info { public: @@ -22,6 +25,9 @@ public: protected: virtual bool handle_command(WPARAM wparam, LPARAM lparam) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_LOGWININFO_H diff --git a/src/osd/modules/debugger/win/memoryviewinfo.cpp b/src/osd/modules/debugger/win/memoryviewinfo.cpp index 423679f26a9..90e23a557a9 100644 --- a/src/osd/modules/debugger/win/memoryviewinfo.cpp +++ b/src/osd/modules/debugger/win/memoryviewinfo.cpp @@ -2,15 +2,19 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// memoryviewinfo.c - Win32 debug window handling +// memoryviewinfo.cpp - Win32 debug window handling // //============================================================ #include "emu.h" #include "memoryviewinfo.h" -#include "debug/dvmemory.h" +#include "util/xmlfile.h" +#include "strconv.h" + + +namespace osd::debugger::win { memoryview_info::memoryview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) : debugview_info(debugger, owner, parent, DVT_MEMORY) @@ -23,7 +27,13 @@ memoryview_info::~memoryview_info() } -uint8_t memoryview_info::data_format() const +char const *memoryview_info::expression() const +{ + return view<debug_view_memory>()->expression(); +} + + +debug_view_memory::data_format memoryview_info::data_format() const { return view<debug_view_memory>()->get_data_format(); } @@ -46,13 +56,18 @@ bool memoryview_info::physical() const return view<debug_view_memory>()->physical(); } +int memoryview_info::address_radix() const +{ + return view<debug_view_memory>()->address_radix(); +} + void memoryview_info::set_expression(const std::string &string) { view<debug_view_memory>()->set_expression(string); } -void memoryview_info::set_data_format(uint8_t dataformat) +void memoryview_info::set_data_format(debug_view_memory::data_format dataformat) { view<debug_view_memory>()->set_data_format(dataformat); } @@ -71,3 +86,123 @@ void memoryview_info::set_physical(bool physical) { view<debug_view_memory>()->set_physical(physical); } + +void memoryview_info::set_address_radix(int radix) +{ + view<debug_view_memory>()->set_address_radix(radix); +} + + +void memoryview_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + debug_view_memory &memview(*view<debug_view_memory>()); + memview.set_reverse(0 != node.get_attribute_int(ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memview.reverse() ? 1 : 0)); + memview.set_physical(0 != node.get_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_MODE, memview.physical() ? 1 : 0)); + memview.set_address_radix(node.get_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memview.address_radix())); + memview.set_data_format(debug_view_memory::data_format(node.get_attribute_int(ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memview.get_data_format())))); + memview.set_chunks_per_row(node.get_attribute_int(ATTR_WINDOW_MEMORY_ROW_CHUNKS, memview.chunks_per_row())); + + debugview_info::restore_configuration_from_node(node); +} + + +void memoryview_info::save_configuration_to_node(util::xml::data_node &node) +{ + debugview_info::save_configuration_to_node(node); + + debug_view_memory &memview(*view<debug_view_memory>()); + node.set_attribute_int(ATTR_WINDOW_MEMORY_REVERSE_COLUMNS, memview.reverse() ? 1 : 0); + node.set_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_MODE, memview.physical() ? 1 : 0); + node.set_attribute_int(ATTR_WINDOW_MEMORY_ADDRESS_RADIX, memview.address_radix()); + node.set_attribute_int(ATTR_WINDOW_MEMORY_DATA_FORMAT, int(memview.get_data_format())); + node.set_attribute_int(ATTR_WINDOW_MEMORY_ROW_CHUNKS, memview.chunks_per_row()); +} + + +void memoryview_info::add_items_to_context_menu(HMENU menu) +{ + debugview_info::add_items_to_context_menu(menu); + + AppendMenu(menu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); + AppendMenu(menu, MF_GRAYED, ID_CONTEXT_LAST_PC, TEXT("Last PC")); +} + +void memoryview_info::update_context_menu(HMENU menu) +{ + debugview_info::update_context_menu(menu); + + bool enable = false; + debug_view_memory &memview(*view<debug_view_memory>()); + debug_view_memory_source const &source = downcast<debug_view_memory_source const &>(*memview.source()); + address_space *const space = source.space(); + if (space) + { + if (memview.cursor_visible()) + { + // get the last known PC to write to this memory location + debug_view_xy const pos = memview.cursor_position(); + offs_t const address = space->byte_to_address(memview.addressAtCursorPosition(pos)); + offs_t a = address & space->logaddrmask(); + address_space *tspace; + if (!space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, a, tspace)) + { + m_lastpc = "Bad address"; + } + else + { + uint64_t memval = tspace->unmap(); + auto dis = tspace->device().machine().disable_side_effects(); + switch (tspace->data_width()) + { + case 8: memval = tspace->read_byte(a); break; + case 16: memval = tspace->read_word_unaligned(a); break; + case 32: memval = tspace->read_dword_unaligned(a); break; + case 64: memval = tspace->read_qword_unaligned(a); break; + } + + offs_t const pc = source.device()->debug()->track_mem_pc_from_space_address_data( + tspace->spacenum(), + address, + memval); + if (pc != offs_t(-1)) + { + if (tspace->is_octal()) + m_lastpc = util::string_format("Address %o written at PC=%o", address, pc); + else + m_lastpc = util::string_format("Address %x written at PC=%x", address, pc); + enable = true; + } + else + { + m_lastpc = "Unknown PC"; + } + } + } + else + { + m_lastpc = "No address"; + } + } + else + { + m_lastpc = "Not an address space"; + } + ModifyMenuW(menu, ID_CONTEXT_LAST_PC, MF_BYCOMMAND, ID_CONTEXT_LAST_PC, osd::text::to_wstring(m_lastpc).c_str()); + EnableMenuItem(menu, ID_CONTEXT_LAST_PC, MF_BYCOMMAND | (enable ? MF_ENABLED : MF_GRAYED)); +} + +void memoryview_info::handle_context_menu(unsigned command) +{ + switch (command) + { + case ID_CONTEXT_LAST_PC: + // TODO: copy to clipboard + return; + + default: + debugview_info::handle_context_menu(command); + }; + +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/memoryviewinfo.h b/src/osd/modules/debugger/win/memoryviewinfo.h index 2ab810654f3..514c6c13ec6 100644 --- a/src/osd/modules/debugger/win/memoryviewinfo.h +++ b/src/osd/modules/debugger/win/memoryviewinfo.h @@ -5,14 +5,20 @@ // memoryviewinfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_MEMORYVIEWINFO_H +#define MAME_DEBUGGER_WIN_MEMORYVIEWINFO_H -#ifndef __DEBUG_WIN_MEMORY_VIEW_INFO_H__ -#define __DEBUG_WIN_MEMORY_VIEW_INFO_H__ +#pragma once #include "debugwin.h" - #include "debugviewinfo.h" +#include "debug/dvmemory.h" + +#include <string> + + +namespace osd::debugger::win { class memoryview_info : public debugview_info { @@ -20,16 +26,37 @@ public: memoryview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent); virtual ~memoryview_info(); - uint8_t data_format() const; + char const *expression() const; + debug_view_memory::data_format data_format() const; uint32_t chunks_per_row() const; bool reverse() const; bool physical() const; + int address_radix() const; void set_expression(const std::string &string); - void set_data_format(uint8_t dataformat); + void set_data_format(debug_view_memory::data_format dataformat); void set_chunks_per_row(uint32_t rowchunks); void set_reverse(bool reverse); void set_physical(bool physical); + void set_address_radix(int radix); + + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; + +protected: + enum + { + ID_CONTEXT_LAST_PC = 101 + }; + + virtual void add_items_to_context_menu(HMENU menu) override; + virtual void update_context_menu(HMENU menu) override; + virtual void handle_context_menu(unsigned command) override; + +private: + std::string m_lastpc; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_MEMORYVIEWINFO_H diff --git a/src/osd/modules/debugger/win/memorywininfo.cpp b/src/osd/modules/debugger/win/memorywininfo.cpp index 6f461295ec2..92078854e2e 100644 --- a/src/osd/modules/debugger/win/memorywininfo.cpp +++ b/src/osd/modules/debugger/win/memorywininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// memorywininfo.c - Win32 debug window handling +// memorywininfo.cpp - Win32 debug window handling // //============================================================ @@ -13,9 +13,13 @@ #include "memoryviewinfo.h" #include "uimetrics.h" +#include "util/xmlfile.h" + #include "winutf8.h" +namespace osd::debugger::win { + memorywin_info::memorywin_info(debugger_windows_interface &debugger) : editwin_info(debugger, false, "Memory", nullptr), m_combownd(nullptr) @@ -23,7 +27,7 @@ memorywin_info::memorywin_info(debugger_windows_interface &debugger) : if (!window()) return; - m_views[0].reset(global_alloc(memoryview_info(debugger, *this, window()))); + m_views[0].reset(new memoryview_info(debugger, *this, window())); if ((m_views[0] == nullptr) || !m_views[0]->is_valid()) { m_views[0].reset(); @@ -32,21 +36,29 @@ memorywin_info::memorywin_info(debugger_windows_interface &debugger) : // create the options menu HMENU const optionsmenu = CreatePopupMenu(); - AppendMenu(optionsmenu, MF_ENABLED, ID_1_BYTE_CHUNKS, TEXT("1-byte chunks\tCtrl+1")); - AppendMenu(optionsmenu, MF_ENABLED, ID_2_BYTE_CHUNKS, TEXT("2-byte chunks\tCtrl+2")); - AppendMenu(optionsmenu, MF_ENABLED, ID_4_BYTE_CHUNKS, TEXT("4-byte chunks\tCtrl+4")); - AppendMenu(optionsmenu, MF_ENABLED, ID_8_BYTE_CHUNKS, TEXT("8-byte chunks\tCtrl+8")); - AppendMenu(optionsmenu, MF_ENABLED, ID_FLOATING_POINT_32BIT, TEXT("32 bit floating point\tCtrl+9")); - AppendMenu(optionsmenu, MF_ENABLED, ID_FLOATING_POINT_64BIT, TEXT("64 bit floating point")); - AppendMenu(optionsmenu, MF_ENABLED, ID_FLOATING_POINT_80BIT, TEXT("80 bit floating point")); + AppendMenu(optionsmenu, MF_ENABLED, ID_1_BYTE_CHUNKS_HEX, TEXT("1-byte Chunks (Hex)\tCtrl+1")); + AppendMenu(optionsmenu, MF_ENABLED, ID_2_BYTE_CHUNKS_HEX, TEXT("2-byte Chunks (Hex)\tCtrl+2")); + AppendMenu(optionsmenu, MF_ENABLED, ID_4_BYTE_CHUNKS_HEX, TEXT("4-byte Chunks (Hex)\tCtrl+4")); + AppendMenu(optionsmenu, MF_ENABLED, ID_8_BYTE_CHUNKS_HEX, TEXT("8-byte Chunks (Hex)\tCtrl+8")); + AppendMenu(optionsmenu, MF_ENABLED, ID_1_BYTE_CHUNKS_OCT, TEXT("1-byte Chunks (Octal)\tCtrl+3")); + AppendMenu(optionsmenu, MF_ENABLED, ID_2_BYTE_CHUNKS_OCT, TEXT("2-byte Chunks (Octal)\tCtrl+5")); + AppendMenu(optionsmenu, MF_ENABLED, ID_4_BYTE_CHUNKS_OCT, TEXT("4-byte Chunks (Octal)\tCtrl+7")); + AppendMenu(optionsmenu, MF_ENABLED, ID_8_BYTE_CHUNKS_OCT, TEXT("8-byte Chunks (Octal)\tCtrl+9")); + AppendMenu(optionsmenu, MF_ENABLED, ID_FLOAT_32BIT, TEXT("32-bit Floating Point\tCtrl+Shift+F")); + AppendMenu(optionsmenu, MF_ENABLED, ID_FLOAT_64BIT, TEXT("64-bit Floating Point\tCtrl+Shift+D")); + AppendMenu(optionsmenu, MF_ENABLED, ID_FLOAT_80BIT, TEXT("80-bit Floating Point\tCtrl+Shift+E")); + AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); + AppendMenu(optionsmenu, MF_ENABLED, ID_HEX_ADDRESSES, TEXT("Hexadecimal Addresses\tCtrl+Shift+H")); + AppendMenu(optionsmenu, MF_ENABLED, ID_DEC_ADDRESSES, TEXT("Decimal Addresses")); + AppendMenu(optionsmenu, MF_ENABLED, ID_OCT_ADDRESSES, TEXT("Octal Addresses\tCtrl+Shift+O")); AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); AppendMenu(optionsmenu, MF_ENABLED, ID_LOGICAL_ADDRESSES, TEXT("Logical Addresses\tCtrl+L")); AppendMenu(optionsmenu, MF_ENABLED, ID_PHYSICAL_ADDRESSES, TEXT("Physical Addresses\tCtrl+Y")); AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); AppendMenu(optionsmenu, MF_ENABLED, ID_REVERSE_VIEW, TEXT("Reverse View\tCtrl+R")); AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); - AppendMenu(optionsmenu, MF_ENABLED, ID_INCREASE_MEM_WIDTH, TEXT("Increase bytes per line\tCtrl+P")); - AppendMenu(optionsmenu, MF_ENABLED, ID_DECREASE_MEM_WIDTH, TEXT("Decrease bytes per line\tCtrl+O")); + AppendMenu(optionsmenu, MF_ENABLED, ID_INCREASE_MEM_WIDTH, TEXT("Increase Bytes Per Line\tCtrl+P")); + AppendMenu(optionsmenu, MF_ENABLED, ID_DECREASE_MEM_WIDTH, TEXT("Decrease Bytes Per Line\tCtrl+O")); AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options")); // set up the view to track the initial expression @@ -63,11 +75,11 @@ memorywin_info::memorywin_info(debugger_windows_interface &debugger) : update_caption(); // recompute the children once to get the maxwidth - memorywin_info::recompute_children(); + recompute_children(); // position the window and recompute children again - SetWindowPos(window(), HWND_TOP, 100, 100, maxwidth(), 200, SWP_SHOWWINDOW); - memorywin_info::recompute_children(); + debugger.stagger_window(window(), maxwidth(), 200); + recompute_children(); // mark the edit box as the default focus and set it editwin_info::set_default_focus(); @@ -83,47 +95,87 @@ bool memorywin_info::handle_key(WPARAM wparam, LPARAM lparam) { if (GetAsyncKeyState(VK_CONTROL) & 0x8000) { - switch (wparam) + if (GetAsyncKeyState(VK_SHIFT)) { - case '1': - SendMessage(window(), WM_COMMAND, ID_1_BYTE_CHUNKS, 0); - return true; + switch (wparam) + { + case 'F': + SendMessage(window(), WM_COMMAND, ID_FLOAT_32BIT, 0); + return true; - case '2': - SendMessage(window(), WM_COMMAND, ID_2_BYTE_CHUNKS, 0); - return true; + case 'D': + SendMessage(window(), WM_COMMAND, ID_FLOAT_64BIT, 0); + return true; - case '4': - SendMessage(window(), WM_COMMAND, ID_4_BYTE_CHUNKS, 0); - return true; + case 'E': + SendMessage(window(), WM_COMMAND, ID_FLOAT_80BIT, 0); + return true; - case '8': - SendMessage(window(), WM_COMMAND, ID_8_BYTE_CHUNKS, 0); - return true; + case 'H': + SendMessage(window(), WM_COMMAND, ID_HEX_ADDRESSES, 0); + return true; - case '9': - SendMessage(window(), WM_COMMAND, ID_FLOATING_POINT_32BIT, 0); - return true; + case 'O': + SendMessage(window(), WM_COMMAND, ID_OCT_ADDRESSES, 0); + return true; + } + } + else + { + switch (wparam) + { + case '1': + SendMessage(window(), WM_COMMAND, ID_1_BYTE_CHUNKS_HEX, 0); + return true; - case 'L': - SendMessage(window(), WM_COMMAND, ID_LOGICAL_ADDRESSES, 0); - return true; + case '2': + SendMessage(window(), WM_COMMAND, ID_2_BYTE_CHUNKS_HEX, 0); + return true; - case 'Y': - SendMessage(window(), WM_COMMAND, ID_PHYSICAL_ADDRESSES, 0); - return true; + case '4': + SendMessage(window(), WM_COMMAND, ID_4_BYTE_CHUNKS_HEX, 0); + return true; - case 'R': - SendMessage(window(), WM_COMMAND, ID_REVERSE_VIEW, 0); - return true; + case '8': + SendMessage(window(), WM_COMMAND, ID_8_BYTE_CHUNKS_HEX, 0); + return true; - case 'P': - SendMessage(window(), WM_COMMAND, ID_INCREASE_MEM_WIDTH, 0); - return true; + case '3': + SendMessage(window(), WM_COMMAND, ID_1_BYTE_CHUNKS_OCT, 0); + return true; - case 'O': - SendMessage(window(), WM_COMMAND, ID_DECREASE_MEM_WIDTH, 0); - return true; + case '5': + SendMessage(window(), WM_COMMAND, ID_2_BYTE_CHUNKS_OCT, 0); + return true; + + case '7': + SendMessage(window(), WM_COMMAND, ID_4_BYTE_CHUNKS_OCT, 0); + return true; + + case '9': + SendMessage(window(), WM_COMMAND, ID_8_BYTE_CHUNKS_OCT, 0); + return true; + + case 'L': + SendMessage(window(), WM_COMMAND, ID_LOGICAL_ADDRESSES, 0); + return true; + + case 'Y': + SendMessage(window(), WM_COMMAND, ID_PHYSICAL_ADDRESSES, 0); + return true; + + case 'R': + SendMessage(window(), WM_COMMAND, ID_REVERSE_VIEW, 0); + return true; + + case 'P': + SendMessage(window(), WM_COMMAND, ID_INCREASE_MEM_WIDTH, 0); + return true; + + case 'O': + SendMessage(window(), WM_COMMAND, ID_DECREASE_MEM_WIDTH, 0); + return true; + } } } return editwin_info::handle_key(wparam, lparam); @@ -178,25 +230,37 @@ void memorywin_info::update_menu() { editwin_info::update_menu(); - memoryview_info *const memview = downcast<memoryview_info *>(m_views[0].get()); + auto *const memview = downcast<memoryview_info *>(m_views[0].get()); HMENU const menu = GetMenu(window()); - CheckMenuItem(menu, ID_1_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == 1 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_2_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == 2 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_4_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == 4 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_8_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == 8 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_FLOATING_POINT_32BIT, MF_BYCOMMAND | (memview->data_format() == 9 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_FLOATING_POINT_64BIT, MF_BYCOMMAND | (memview->data_format() == 10 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_FLOATING_POINT_80BIT, MF_BYCOMMAND | (memview->data_format() == 11 ? MF_CHECKED : MF_UNCHECKED)); + + CheckMenuItem(menu, ID_1_BYTE_CHUNKS_HEX, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::HEX_8BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_2_BYTE_CHUNKS_HEX, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::HEX_16BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_4_BYTE_CHUNKS_HEX, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::HEX_32BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_8_BYTE_CHUNKS_HEX, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::HEX_64BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_1_BYTE_CHUNKS_OCT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::OCTAL_8BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_2_BYTE_CHUNKS_OCT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::OCTAL_16BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_4_BYTE_CHUNKS_OCT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::OCTAL_32BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_8_BYTE_CHUNKS_OCT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::OCTAL_64BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_FLOAT_32BIT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::FLOAT_32BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_FLOAT_64BIT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::FLOAT_64BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_FLOAT_80BIT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::FLOAT_80BIT) ? MF_CHECKED : MF_UNCHECKED)); + + CheckMenuItem(menu, ID_HEX_ADDRESSES, MF_BYCOMMAND | ((memview->address_radix() == 16) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_DEC_ADDRESSES, MF_BYCOMMAND | ((memview->address_radix() == 10) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_OCT_ADDRESSES, MF_BYCOMMAND | ((memview->address_radix() == 8) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_LOGICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_UNCHECKED : MF_CHECKED)); CheckMenuItem(menu, ID_PHYSICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_REVERSE_VIEW, MF_BYCOMMAND | (memview->reverse() ? MF_CHECKED : MF_UNCHECKED)); + EnableMenuItem(menu, ID_DECREASE_MEM_WIDTH, MF_BYCOMMAND | ((memview->chunks_per_row() > 1) ? MF_ENABLED : MF_GRAYED)); } bool memorywin_info::handle_command(WPARAM wparam, LPARAM lparam) { - memoryview_info *const memview = downcast<memoryview_info *>(m_views[0].get()); + auto *const memview = downcast<memoryview_info *>(m_views[0].get()); switch (HIWORD(wparam)) { // combo box selection changed @@ -219,32 +283,60 @@ bool memorywin_info::handle_command(WPARAM wparam, LPARAM lparam) case 0: switch (LOWORD(wparam)) { - case ID_1_BYTE_CHUNKS: - memview->set_data_format(1); + case ID_1_BYTE_CHUNKS_HEX: + memview->set_data_format(debug_view_memory::data_format::HEX_8BIT); + return true; + + case ID_2_BYTE_CHUNKS_HEX: + memview->set_data_format(debug_view_memory::data_format::HEX_16BIT); + return true; + + case ID_4_BYTE_CHUNKS_HEX: + memview->set_data_format(debug_view_memory::data_format::HEX_32BIT); + return true; + + case ID_8_BYTE_CHUNKS_HEX: + memview->set_data_format(debug_view_memory::data_format::HEX_64BIT); return true; - case ID_2_BYTE_CHUNKS: - memview->set_data_format(2); + case ID_1_BYTE_CHUNKS_OCT: + memview->set_data_format(debug_view_memory::data_format::OCTAL_8BIT); return true; - case ID_4_BYTE_CHUNKS: - memview->set_data_format(4); + case ID_2_BYTE_CHUNKS_OCT: + memview->set_data_format(debug_view_memory::data_format::OCTAL_16BIT); return true; - case ID_8_BYTE_CHUNKS: - memview->set_data_format(8); + case ID_4_BYTE_CHUNKS_OCT: + memview->set_data_format(debug_view_memory::data_format::OCTAL_32BIT); return true; - case ID_FLOATING_POINT_32BIT: - memview->set_data_format(9); + case ID_8_BYTE_CHUNKS_OCT: + memview->set_data_format(debug_view_memory::data_format::OCTAL_64BIT); return true; - case ID_FLOATING_POINT_64BIT: - memview->set_data_format(10); + case ID_FLOAT_32BIT: + memview->set_data_format(debug_view_memory::data_format::FLOAT_32BIT); return true; - case ID_FLOATING_POINT_80BIT: - memview->set_data_format(11); + case ID_FLOAT_64BIT: + memview->set_data_format(debug_view_memory::data_format::FLOAT_64BIT); + return true; + + case ID_FLOAT_80BIT: + memview->set_data_format(debug_view_memory::data_format::FLOAT_80BIT); + return true; + + case ID_HEX_ADDRESSES: + memview->set_address_radix(16); + return true; + + case ID_DEC_ADDRESSES: + memview->set_address_radix(10); + return true; + + case ID_OCT_ADDRESSES: + memview->set_address_radix(8); return true; case ID_LOGICAL_ADDRESSES: @@ -300,3 +392,37 @@ void memorywin_info::update_caption() { win_set_window_text_utf8(window(), std::string("Memory: ").append(m_views[0]->source_name()).c_str()); } + + +void memorywin_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + m_views[0]->set_source_index(node.get_attribute_int(ATTR_WINDOW_MEMORY_REGION, m_views[0]->source_index())); + int const cursource = m_views[0]->source_index(); + if (0 <= cursource) + SendMessage(m_combownd, CB_SETCURSEL, cursource, 0); + update_caption(); + + util::xml::data_node const *const expr = node.get_child(NODE_WINDOW_EXPRESSION); + if (expr && expr->get_value()) + { + set_editwnd_text(expr->get_value()); + process_string(expr->get_value()); + } + + editwin_info::restore_configuration_from_node(node); + + m_views[0]->restore_configuration_from_node(node); +} + + +void memorywin_info::save_configuration_to_node(util::xml::data_node &node) +{ + editwin_info::save_configuration_to_node(node); + + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_MEMORY_VIEWER); + node.set_attribute_int(ATTR_WINDOW_MEMORY_REGION, m_views[0]->source_index()); + node.add_child(NODE_WINDOW_EXPRESSION, downcast<memoryview_info *>(m_views[0].get())->expression()); + m_views[0]->save_configuration_to_node(node); +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/memorywininfo.h b/src/osd/modules/debugger/win/memorywininfo.h index 501d7acc76f..a0a4072be0f 100644 --- a/src/osd/modules/debugger/win/memorywininfo.h +++ b/src/osd/modules/debugger/win/memorywininfo.h @@ -5,15 +5,18 @@ // memorywininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_MEMORYWININFO_H +#define MAME_DEBUGGER_WIN_MEMORYWININFO_H -#ifndef __DEBUG_WIN_MEMORY_WIN_INFO_H__ -#define __DEBUG_WIN_MEMORY_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "editwininfo.h" +namespace osd::debugger::win { + class memorywin_info : public editwin_info { public: @@ -21,12 +24,14 @@ public: virtual ~memorywin_info(); virtual bool handle_key(WPARAM wparam, LPARAM lparam) override; + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; protected: virtual void recompute_children() override; virtual void update_menu() override; virtual bool handle_command(WPARAM wparam, LPARAM lparam) override; virtual void draw_contents(HDC dc) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; private: virtual void process_string(const std::string &string) override; @@ -36,4 +41,6 @@ private: HWND m_combownd; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_MEMORYWININFO_H diff --git a/src/osd/modules/debugger/win/pointswininfo.cpp b/src/osd/modules/debugger/win/pointswininfo.cpp index 24a8f865e6f..70ec6606280 100644 --- a/src/osd/modules/debugger/win/pointswininfo.cpp +++ b/src/osd/modules/debugger/win/pointswininfo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// pointswininfo.c - Win32 debug window handling +// pointswininfo.cpp - Win32 debug window handling // //============================================================ @@ -11,16 +11,20 @@ #include "debugviewinfo.h" +#include "util/xmlfile.h" + #include "winutf8.h" +namespace osd::debugger::win { + pointswin_info::pointswin_info(debugger_windows_interface &debugger) : debugwin_info(debugger, false, std::string("All Breakpoints").c_str(), nullptr) { if (!window()) return; - m_views[0].reset(global_alloc(debugview_info(debugger, *this, window(), DVT_BREAK_POINTS))); + m_views[0].reset(new debugview_info(debugger, *this, window(), DVT_BREAK_POINTS)); if ((m_views[0] == nullptr) || !m_views[0]->is_valid()) { m_views[0].reset(); @@ -31,6 +35,8 @@ pointswin_info::pointswin_info(debugger_windows_interface &debugger) : HMENU const optionsmenu = CreatePopupMenu(); AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_BREAKPOINTS, TEXT("Breakpoints\tCtrl+1")); AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_WATCHPOINTS, TEXT("Watchpoints\tCtrl+2")); + AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_REGISTERPOINTS, TEXT("Registerpoints\tCtrl+3")); + AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_EXCEPTIONPOINTS, TEXT("Exceptionpoints\tCtrl+4")); AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options")); // compute a client rect @@ -43,11 +49,9 @@ pointswin_info::pointswin_info(debugger_windows_interface &debugger) : // clamp the min/max size set_maxwidth(bounds.right - bounds.left); - // position the window at the bottom-right - SetWindowPos(window(), HWND_TOP, 100, 100, bounds.right - bounds.left, bounds.bottom - bounds.top, SWP_SHOWWINDOW); - - // recompute the children - debugwin_info::recompute_children(); + // position the window and recompute children + debugger.stagger_window(window(), bounds.right - bounds.left, bounds.bottom - bounds.top); + recompute_children(); } @@ -69,6 +73,14 @@ bool pointswin_info::handle_key(WPARAM wparam, LPARAM lparam) case '2': SendMessage(window(), WM_COMMAND, ID_SHOW_WATCHPOINTS, 0); return true; + + case '3': + SendMessage(window(), WM_COMMAND, ID_SHOW_REGISTERPOINTS, 0); + return true; + + case '4': + SendMessage(window(), WM_COMMAND, ID_SHOW_EXCEPTIONPOINTS, 0); + return true; } } @@ -83,6 +95,8 @@ void pointswin_info::update_menu() HMENU const menu = GetMenu(window()); CheckMenuItem(menu, ID_SHOW_BREAKPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_BREAK_POINTS ? MF_CHECKED : MF_UNCHECKED)); CheckMenuItem(menu, ID_SHOW_WATCHPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_WATCH_POINTS ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_SHOW_REGISTERPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_REGISTER_POINTS ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_SHOW_EXCEPTIONPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_EXCEPTION_POINTS ? MF_CHECKED : MF_UNCHECKED)); } @@ -96,7 +110,7 @@ bool pointswin_info::handle_command(WPARAM wparam, LPARAM lparam) { case ID_SHOW_BREAKPOINTS: m_views[0].reset(); - m_views[0].reset(global_alloc(debugview_info(debugger(), *this, window(), DVT_BREAK_POINTS))); + m_views[0].reset(new debugview_info(debugger(), *this, window(), DVT_BREAK_POINTS)); if (!m_views[0]->is_valid()) m_views[0].reset(); win_set_window_text_utf8(window(), "All Breakpoints"); @@ -105,14 +119,81 @@ bool pointswin_info::handle_command(WPARAM wparam, LPARAM lparam) case ID_SHOW_WATCHPOINTS: m_views[0].reset(); - m_views[0].reset(global_alloc(debugview_info(debugger(), *this, window(), DVT_WATCH_POINTS))); + m_views[0].reset(new debugview_info(debugger(), *this, window(), DVT_WATCH_POINTS)); if (!m_views[0]->is_valid()) m_views[0].reset(); win_set_window_text_utf8(window(), "All Watchpoints"); recompute_children(); return true; + + case ID_SHOW_REGISTERPOINTS: + m_views[0].reset(); + m_views[0].reset(new debugview_info(debugger(), *this, window(), DVT_REGISTER_POINTS)); + if (!m_views[0]->is_valid()) + m_views[0].reset(); + win_set_window_text_utf8(window(), "All Registerpoints"); + recompute_children(); + return true; + + case ID_SHOW_EXCEPTIONPOINTS: + m_views[0].reset(); + m_views[0].reset(new debugview_info(debugger(), *this, window(), DVT_EXCEPTION_POINTS)); + if (!m_views[0]->is_valid()) + m_views[0].reset(); + win_set_window_text_utf8(window(), "All Exceptionpoints"); + recompute_children(); + return true; } break; } return debugwin_info::handle_command(wparam, lparam); } + + +void pointswin_info::restore_configuration_from_node(util::xml::data_node const &node) +{ + switch (node.get_attribute_int(ATTR_WINDOW_POINTS_TYPE, -1)) + { + case 0: + SendMessage(window(), WM_COMMAND, ID_SHOW_BREAKPOINTS, 0); + break; + case 1: + SendMessage(window(), WM_COMMAND, ID_SHOW_WATCHPOINTS, 0); + break; + case 2: + SendMessage(window(), WM_COMMAND, ID_SHOW_REGISTERPOINTS, 0); + break; + case 3: + SendMessage(window(), WM_COMMAND, ID_SHOW_EXCEPTIONPOINTS, 0); + break; + } + + debugwin_info::restore_configuration_from_node(node); +} + + +void pointswin_info::save_configuration_to_node(util::xml::data_node &node) +{ + debugwin_info::save_configuration_to_node(node); + + node.set_attribute_int(ATTR_WINDOW_TYPE, WINDOW_TYPE_POINTS_VIEWER); + switch (m_views[0]->type()) + { + case DVT_BREAK_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 0); + break; + case DVT_WATCH_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 1); + break; + case DVT_REGISTER_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 2); + break; + case DVT_EXCEPTION_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 3); + break; + default: + break; + } +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/pointswininfo.h b/src/osd/modules/debugger/win/pointswininfo.h index 8ba1b31fc00..506c68519e8 100644 --- a/src/osd/modules/debugger/win/pointswininfo.h +++ b/src/osd/modules/debugger/win/pointswininfo.h @@ -5,15 +5,18 @@ // pointswininfo.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_POINTSWININFO_H +#define MAME_DEBUGGER_WIN_POINTSWININFO_H -#ifndef __DEBUG_WIN_POINTS_WIN_INFO_H__ -#define __DEBUG_WIN_POINTS_WIN_INFO_H__ +#pragma once #include "debugwin.h" #include "debugwininfo.h" +namespace osd::debugger::win { + class pointswin_info : public debugwin_info { public: @@ -21,10 +24,14 @@ public: virtual ~pointswin_info(); virtual bool handle_key(WPARAM wparam, LPARAM lparam) override; + virtual void restore_configuration_from_node(util::xml::data_node const &node) override; protected: virtual void update_menu() override; virtual bool handle_command(WPARAM wparam, LPARAM lparam) override; + virtual void save_configuration_to_node(util::xml::data_node &node) override; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_POINTSWININFO_H diff --git a/src/osd/modules/debugger/win/uimetrics.cpp b/src/osd/modules/debugger/win/uimetrics.cpp index 67eb045c619..e3d21cda06d 100644 --- a/src/osd/modules/debugger/win/uimetrics.cpp +++ b/src/osd/modules/debugger/win/uimetrics.cpp @@ -2,15 +2,48 @@ // copyright-holders:Aaron Giles, Vas Crabb //============================================================ // -// uimetrics.c - Win32 debug window handling +// uimetrics.cpp - Win32 debug window handling // //============================================================ #include "emu.h" #include "uimetrics.h" +#include "debug/debugvw.h" + #include "strconv.h" +#include <algorithm> + + +namespace osd::debugger::win { + +COLORREF const ui_metrics::s_themes[][COLOR_COUNT] = { + { + RGB(0x00, 0x00, 0x00), // foreground normal + RGB(0xff, 0x00, 0x00), // foreground changed + RGB(0x00, 0x00, 0xff), // foreground invalid + RGB(0x00, 0x80, 0x00), // foreground comment + RGB(0xff, 0xff, 0xff), // background normal + RGB(0xff, 0x80, 0x80), // background selected + RGB(0xe0, 0xe0, 0xe0), // background ancillary + RGB(0xff, 0xff, 0x00), // background current + RGB(0xff, 0xc0, 0x80), // background current selected + RGB(0xc0, 0xe0, 0xff) // background visited + }, + { + RGB(0xe0, 0xe0, 0xe0), // foreground normal + RGB(0xff, 0x60, 0xff), // foreground changed + RGB(0x00, 0xc0, 0xe0), // foreground invalid + RGB(0x00, 0xe0, 0x00), // foreground comment + RGB(0x00, 0x00, 0x00), // background normal + RGB(0xe0, 0x00, 0x00), // background selected + RGB(0x40, 0x40, 0x40), // background ancillary + RGB(0x00, 0x00, 0xc0), // background current + RGB(0xb0, 0x60, 0x00), // background current selected + RGB(0x00, 0x40, 0x80) // background visited + } }; + ui_metrics::ui_metrics(osd_options const &options) : m_debug_font(nullptr), @@ -22,7 +55,7 @@ ui_metrics::ui_metrics(osd_options const &options) : { // create a temporary DC HDC const temp_dc = GetDC(nullptr); - if (temp_dc != nullptr) + if (temp_dc) { float const size = options.debugger_font_size(); char const *const face = options.debugger_font(); @@ -47,6 +80,9 @@ ui_metrics::ui_metrics(osd_options const &options) : SelectObject(temp_dc, old_font); ReleaseDC(nullptr, temp_dc); } + + // set default color theme + set_color_theme(THEME_LIGHT_BACKGROUND); } @@ -69,3 +105,56 @@ ui_metrics::~ui_metrics() if (m_debug_font) DeleteObject(m_debug_font); } + + +std::pair<COLORREF, COLORREF> ui_metrics::view_colors(u8 attrib) const +{ + std::pair<COLORREF, COLORREF> result; + + if (attrib & DCA_SELECTED) + result.second = (attrib & DCA_CURRENT) ? m_colors[COLOR_BG_CURRENT_SELECTED] : m_colors[COLOR_BG_SELECTED]; + else if (attrib & DCA_CURRENT) + result.second = m_colors[COLOR_BG_CURRENT]; + else if (attrib & DCA_ANCILLARY) + result.second = m_colors[COLOR_BG_ANCILLARY]; + else if (attrib & DCA_VISITED) + result.second = m_colors[COLOR_BG_VISITED]; + else + result.second = m_colors[COLOR_BG_NORMAL]; + + if (DCA_COMMENT & attrib) + { + result.first = m_colors[COLOR_FG_COMMENT]; + } + else + { + if (attrib & DCA_INVALID) + result.first = m_colors[COLOR_FG_INVALID]; + else if (attrib & DCA_CHANGED) + result.first = m_colors[COLOR_FG_CHANGED]; + else + result.first = m_colors[COLOR_FG_NORMAL]; + + if (attrib & DCA_DISABLED) + { + result.first = RGB( + (GetRValue(result.first) + GetRValue(result.second) + 1) >> 1, + (GetGValue(result.first) + GetGValue(result.second) + 1) >> 1, + (GetBValue(result.first) + GetBValue(result.second) + 1) >> 1); + } + } + + return result; +} + + +void ui_metrics::set_color_theme(int index) +{ + if ((0 <= index) && (std::size(s_themes) > index)) + { + std::copy(std::begin(s_themes[index]), std::end(s_themes[index]), m_colors); + m_color_theme = index; + } +} + +} // namespace osd::debugger::win diff --git a/src/osd/modules/debugger/win/uimetrics.h b/src/osd/modules/debugger/win/uimetrics.h index a360d66924e..e45ae810fa6 100644 --- a/src/osd/modules/debugger/win/uimetrics.h +++ b/src/osd/modules/debugger/win/uimetrics.h @@ -5,19 +5,29 @@ // uimetrics.h - Win32 debug window handling // //============================================================ +#ifndef MAME_DEBUGGER_WIN_UIMETRICS_H +#define MAME_DEBUGGER_WIN_UIMETRICS_H -#ifndef __DEBUG_WIN_UI_METRICS_H__ -#define __DEBUG_WIN_UI_METRICS_H__ +#pragma once #include "debugwin.h" - #include "modules/lib/osdobj_common.h" +#include <utility> + + +namespace osd::debugger::win { class ui_metrics { public: + enum + { + THEME_LIGHT_BACKGROUND, + THEME_DARK_BACKGROUND + }; + ui_metrics(osd_options const &options); ui_metrics(ui_metrics const &that); ~ui_metrics(); @@ -30,7 +40,28 @@ public: uint32_t hscroll_height() const { return m_hscroll_height; } uint32_t vscroll_width() const { return m_vscroll_width; } + std::pair<COLORREF, COLORREF> view_colors(u8 attrib) const; + int get_color_theme() const { return m_color_theme; } + void set_color_theme(int index); + private: + enum + { + COLOR_FG_NORMAL, + COLOR_FG_CHANGED, + COLOR_FG_INVALID, + COLOR_FG_COMMENT, + + COLOR_BG_NORMAL, + COLOR_BG_SELECTED, + COLOR_BG_ANCILLARY, + COLOR_BG_CURRENT, + COLOR_BG_CURRENT_SELECTED, + COLOR_BG_VISITED, + + COLOR_COUNT + }; + HFONT m_debug_font; uint32_t m_debug_font_height; uint32_t m_debug_font_width; @@ -38,6 +69,13 @@ private: uint32_t const m_hscroll_height; uint32_t const m_vscroll_width; + + COLORREF m_colors[COLOR_COUNT]; + int m_color_theme; + + static COLORREF const s_themes[][COLOR_COUNT]; }; -#endif +} // namespace osd::debugger::win + +#endif // MAME_DEBUGGER_WIN_UIMETRICS_H |