summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Miodrag Milanović <mmicko@gmail.com>2015-02-21 06:43:19 +0100
committer Miodrag Milanović <mmicko@gmail.com>2015-02-21 06:43:19 +0100
commitfe91dfe9f127cb4bcbc36d1056951dda3efecc39 (patch)
treeae8650bc88fd58bd4b370ea7ee5164930228ecaf
parent75aaa54c2b7e98918be78871c872fa4ef15028c3 (diff)
parent2edbf5565ee8dba382b71b0696c5f7d8db5e569b (diff)
Merge pull request #139 from cuavas/master
Debugger love: Windows edition
-rw-r--r--src/emu/debug/dvbpoints.c28
-rw-r--r--src/emu/debug/dvbpoints.h3
-rw-r--r--src/emu/debug/dvmemory.h2
-rw-r--r--src/emu/debug/dvwpoints.c28
-rw-r--r--src/emu/debug/dvwpoints.h3
-rw-r--r--src/osd/modules/debugger/debugwin.c3095
-rw-r--r--src/osd/modules/debugger/osx/debugview.m1
-rw-r--r--src/osd/modules/debugger/win/consolewininfo.c373
-rw-r--r--src/osd/modules/debugger/win/consolewininfo.h53
-rw-r--r--src/osd/modules/debugger/win/debugbaseinfo.c60
-rw-r--r--src/osd/modules/debugger/win/debugbaseinfo.h40
-rw-r--r--src/osd/modules/debugger/win/debugviewinfo.c809
-rw-r--r--src/osd/modules/debugger/win/debugviewinfo.h77
-rw-r--r--src/osd/modules/debugger/win/debugwin.h52
-rw-r--r--src/osd/modules/debugger/win/debugwininfo.c599
-rw-r--r--src/osd/modules/debugger/win/debugwininfo.h142
-rw-r--r--src/osd/modules/debugger/win/disasmbasewininfo.c273
-rw-r--r--src/osd/modules/debugger/win/disasmbasewininfo.h30
-rw-r--r--src/osd/modules/debugger/win/disasmviewinfo.c44
-rw-r--r--src/osd/modules/debugger/win/disasmviewinfo.h32
-rw-r--r--src/osd/modules/debugger/win/disasmwininfo.c149
-rw-r--r--src/osd/modules/debugger/win/disasmwininfo.h36
-rw-r--r--src/osd/modules/debugger/win/editwininfo.c236
-rw-r--r--src/osd/modules/debugger/win/editwininfo.h56
-rw-r--r--src/osd/modules/debugger/win/logwininfo.c47
-rw-r--r--src/osd/modules/debugger/win/logwininfo.h24
-rw-r--r--src/osd/modules/debugger/win/memoryviewinfo.c72
-rw-r--r--src/osd/modules/debugger/win/memoryviewinfo.h36
-rw-r--r--src/osd/modules/debugger/win/memorywininfo.c279
-rw-r--r--src/osd/modules/debugger/win/memorywininfo.h39
-rw-r--r--src/osd/modules/debugger/win/pointswininfo.c117
-rw-r--r--src/osd/modules/debugger/win/pointswininfo.h30
-rw-r--r--src/osd/modules/debugger/win/uimetrics.c71
-rw-r--r--src/osd/modules/debugger/win/uimetrics.h44
-rw-r--r--src/osd/sdl/sdl.mak2
-rw-r--r--src/osd/windows/windows.mak16
-rw-r--r--src/osd/windows/winmain.h5
37 files changed, 3983 insertions, 3020 deletions
diff --git a/src/emu/debug/dvbpoints.c b/src/emu/debug/dvbpoints.c
index 9b48bc96787..5619adff0bd 100644
--- a/src/emu/debug/dvbpoints.c
+++ b/src/emu/debug/dvbpoints.c
@@ -73,26 +73,6 @@ void debug_view_breakpoints::enumerate_sources()
//-------------------------------------------------
-// view_notify - handle notification of updates
-// to cursor changes
-//-------------------------------------------------
-
-void debug_view_breakpoints::view_notify(debug_view_notification type)
-{
-}
-
-
-//-------------------------------------------------
-// view_char - handle a character typed within
-// the current view
-//-------------------------------------------------
-
-void debug_view_breakpoints::view_char(int chval)
-{
-}
-
-
-//-------------------------------------------------
// view_click - handle a mouse click within the
// current view
//-------------------------------------------------
@@ -134,7 +114,7 @@ void debug_view_breakpoints::view_click(const int button, const debug_view_xy& p
device_debug::breakpoint** bpList = NULL;
const int numBPs = breakpoints(SORT_NONE, bpList);
- const int bpIndex = pos.y-1;
+ const int bpIndex = pos.y - 1;
if (bpIndex > numBPs || bpIndex < 0)
return;
@@ -147,7 +127,9 @@ void debug_view_breakpoints::view_click(const int button, const debug_view_xy& p
delete[] bpList;
}
- view_update();
+ begin_update();
+ m_update_pending = true;
+ end_update();
}
@@ -331,7 +313,7 @@ int debug_view_breakpoints::breakpoints(SortMode sort, device_debug::breakpoint*
//-------------------------------------------------
// view_update - update the contents of the
-// disassembly view
+// breakpoints view
//-------------------------------------------------
void debug_view_breakpoints::view_update()
diff --git a/src/emu/debug/dvbpoints.h b/src/emu/debug/dvbpoints.h
index 38cd30de800..bb80b840ebb 100644
--- a/src/emu/debug/dvbpoints.h
+++ b/src/emu/debug/dvbpoints.h
@@ -58,14 +58,11 @@ public:
protected:
// view overrides
virtual void view_update();
- virtual void view_notify(debug_view_notification type);
- virtual void view_char(int chval);
virtual void view_click(const int button, const debug_view_xy& pos);
private:
// internal helpers
void enumerate_sources();
- bool recompute(offs_t pc, int startline, int lines);
void pad_astring_to_length(astring& str, int len);
int breakpoints(SortMode sort, device_debug::breakpoint**& bpList);
diff --git a/src/emu/debug/dvmemory.h b/src/emu/debug/dvmemory.h
index f6811c5d7e1..69db37b3102 100644
--- a/src/emu/debug/dvmemory.h
+++ b/src/emu/debug/dvmemory.h
@@ -54,7 +54,7 @@ public:
// getters
const char *expression() { return m_expression.string(); }
UINT8 bytes_per_chunk() { flush_updates(); return m_bytes_per_chunk; }
- UINT8 chunks_per_row() { flush_updates(); return m_chunks_per_row; }
+ UINT32 chunks_per_row() { flush_updates(); return m_chunks_per_row; }
bool reverse() const { return m_reverse_view; }
bool ascii() const { return m_ascii_view; }
bool physical() const { return m_no_translation; }
diff --git a/src/emu/debug/dvwpoints.c b/src/emu/debug/dvwpoints.c
index e9ff9a8754d..b7054b4e4bb 100644
--- a/src/emu/debug/dvwpoints.c
+++ b/src/emu/debug/dvwpoints.c
@@ -72,26 +72,6 @@ void debug_view_watchpoints::enumerate_sources()
//-------------------------------------------------
-// view_notify - handle notification of updates
-// to cursor changes
-//-------------------------------------------------
-
-void debug_view_watchpoints::view_notify(debug_view_notification type)
-{
-}
-
-
-//-------------------------------------------------
-// view_char - handle a character typed within
-// the current view
-//-------------------------------------------------
-
-void debug_view_watchpoints::view_char(int chval)
-{
-}
-
-
-//-------------------------------------------------
// view_click - handle a mouse click within the
// current view
//-------------------------------------------------
@@ -141,7 +121,7 @@ void debug_view_watchpoints::view_click(const int button, const debug_view_xy& p
device_debug::watchpoint** wpList = NULL;
const int numWPs = watchpoints(SORT_NONE, wpList);
- const int wpIndex = pos.y-1;
+ const int wpIndex = pos.y - 1;
if (wpIndex > numWPs || wpIndex < 0)
return;
@@ -154,7 +134,9 @@ void debug_view_watchpoints::view_click(const int button, const debug_view_xy& p
delete[] wpList;
}
- view_update();
+ begin_update();
+ m_update_pending = true;
+ end_update();
}
@@ -387,7 +369,7 @@ int debug_view_watchpoints::watchpoints(SortMode sort, device_debug::watchpoint*
//-------------------------------------------------
// view_update - update the contents of the
-// disassembly view
+// watchpoints view
//-------------------------------------------------
void debug_view_watchpoints::view_update()
diff --git a/src/emu/debug/dvwpoints.h b/src/emu/debug/dvwpoints.h
index 7c35e9278b6..6414b3b0424 100644
--- a/src/emu/debug/dvwpoints.h
+++ b/src/emu/debug/dvwpoints.h
@@ -62,14 +62,11 @@ public:
protected:
// view overrides
virtual void view_update();
- virtual void view_notify(debug_view_notification type);
- virtual void view_char(int chval);
virtual void view_click(const int button, const debug_view_xy& pos);
private:
// internal helpers
void enumerate_sources();
- bool recompute(offs_t pc, int startline, int lines);
void pad_astring_to_length(astring& str, int len);
int watchpoints(SortMode sort, device_debug::watchpoint**& bpList);
diff --git a/src/osd/modules/debugger/debugwin.c b/src/osd/modules/debugger/debugwin.c
index 658731bc09c..448f35b122c 100644
--- a/src/osd/modules/debugger/debugwin.c
+++ b/src/osd/modules/debugger/debugwin.c
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
// debugwin.c - Win32 debug window handling
@@ -11,3090 +11,257 @@
#if defined(OSD_WINDOWS) /*|| defined(SDLMAME_WIN32)*/
-// standard windows headers
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <windowsx.h>
-#include <tchar.h>
-#include <commdlg.h>
-#ifdef _MSC_VER
-#include <zmouse.h>
-#endif
+#include "win/debugwin.h"
+
+#include "win/consolewininfo.h"
+#include "win/debugwininfo.h"
+#include "win/disasmwininfo.h"
+#include "win/logwininfo.h"
+#include "win/memorywininfo.h"
+#include "win/pointswininfo.h"
+#include "win/uimetrics.h"
-// MAME headers
#include "emu.h"
#include "uiinput.h"
-#include "imagedev/cassette.h"
#include "debugger.h"
-#include "debug/debugvw.h"
-#include "debug/dvdisasm.h"
-#include "debug/dvmemory.h"
-#include "debug/dvstate.h"
-#include "debug/debugvw.h"
-#include "debug/debugcon.h"
-#include "debug/debugcpu.h"
-// MAMEOS headers
-#include "winmain.h"
#include "window.h"
+#include "winmain.h"
#include "../../windows/input.h"
-#include "strconv.h"
-#include "winutf8.h"
-class debugger_windows : public osd_module, public debug_module
+
+class debugger_windows : public osd_module, public debug_module, protected debugger_windows_interface
{
public:
- debugger_windows()
- : osd_module(OSD_DEBUG_PROVIDER, "windows"), debug_module(),
- m_machine(NULL)
+ debugger_windows() :
+ osd_module(OSD_DEBUG_PROVIDER, "windows"),
+ debug_module(),
+ m_machine(NULL),
+ m_metrics(),
+ m_waiting_for_debugger(false),
+ m_window_list(),
+ m_main_console(NULL)
{
}
virtual ~debugger_windows() { }
- virtual int init() { return 0;}
+ virtual int init() { return 0; }
virtual void exit();
virtual void init_debugger(running_machine &machine);
virtual void wait_for_debugger(device_t &device, bool firststop);
virtual void debugger_update();
-private:
- running_machine *m_machine;
-};
-//============================================================
-// PARAMETERS
-//============================================================
-
-#define MAX_VIEWS 4
-#define EDGE_WIDTH 3
-#define MAX_EDIT_STRING 256
-#define HISTORY_LENGTH 20
-#define MAX_OTHER_WND 4
-
-// debugger window styles
-#define DEBUG_WINDOW_STYLE (WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN) & (~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX)
-#define DEBUG_WINDOW_STYLE_EX 0
-
-// debugger view styles
-#define DEBUG_VIEW_STYLE WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN
-#define DEBUG_VIEW_STYLE_EX 0
+protected:
+ virtual running_machine &machine() const { return *m_machine; }
-// edit box styles
-#define EDIT_BOX_STYLE WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL
-#define EDIT_BOX_STYLE_EX 0
+ virtual ui_metrics &metrics() const { return *m_metrics; }
-// combo box styles
-#define COMBO_BOX_STYLE WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL
-#define COMBO_BOX_STYLE_EX 0
+ virtual bool const &waiting_for_debugger() const { return m_waiting_for_debugger; }
+ virtual bool seq_pressed() const;
-// horizontal scroll bar styles
-#define HSCROLL_STYLE WS_CHILD | WS_VISIBLE | SBS_HORZ
-#define HSCROLL_STYLE_EX 0
+ virtual void create_memory_window() { create_window<memorywin_info>(); }
+ virtual void create_disasm_window() { create_window<disasmwin_info>(); }
+ virtual void create_log_window() { create_window<logwin_info>(); }
+ virtual void create_points_window() { create_window<pointswin_info>(); }
+ virtual void remove_window(debugwin_info &info);
-// vertical scroll bar styles
-#define VSCROLL_STYLE WS_CHILD | WS_VISIBLE | SBS_VERT
-#define VSCROLL_STYLE_EX 0
-
-
-enum
-{
- ID_NEW_MEMORY_WND = 1,
- ID_NEW_DISASM_WND,
- ID_NEW_LOG_WND,
- ID_RUN,
- ID_RUN_AND_HIDE,
- ID_RUN_VBLANK,
- ID_RUN_IRQ,
- ID_NEXT_CPU,
- ID_STEP,
- ID_STEP_OVER,
- ID_STEP_OUT,
- ID_HARD_RESET,
- ID_SOFT_RESET,
- ID_EXIT,
-
- ID_1_BYTE_CHUNKS,
- ID_2_BYTE_CHUNKS,
- ID_4_BYTE_CHUNKS,
- ID_8_BYTE_CHUNKS,
- ID_LOGICAL_ADDRESSES,
- ID_PHYSICAL_ADDRESSES,
- ID_REVERSE_VIEW,
- ID_INCREASE_MEM_WIDTH,
- ID_DECREASE_MEM_WIDTH,
-
- ID_SHOW_RAW,
- ID_SHOW_ENCRYPTED,
- ID_SHOW_COMMENTS,
- ID_RUN_TO_CURSOR,
- ID_TOGGLE_BREAKPOINT,
-
- ID_DEVICE_OPTIONS // keep this always at the end
-};
-
-
-
-//============================================================
-// TYPES
-//============================================================
-
-struct debugview_info;
-class debugwin_info;
+ virtual void show_all();
+ virtual void hide_all();
+private:
+ template <typename T> T *create_window();
-struct debugview_info
-{
- debugwin_info * owner;
- debug_view * view;
- HWND wnd;
- HWND hscroll;
- HWND vscroll;
+ running_machine *m_machine;
+ auto_pointer<ui_metrics> m_metrics;
+ bool m_waiting_for_debugger;
+ simple_list<debugwin_info> m_window_list;
+ consolewin_info *m_main_console;
};
-class debugwin_info
+void debugger_windows::exit()
{
-public:
- debugwin_info(running_machine &machine)
- : m_machine(machine) { }
-
- running_machine &machine() const { return m_machine; }
-
- debugwin_info * next;
- HWND wnd;
- HWND focuswnd;
- WNDPROC handler;
-
- UINT32 minwidth, maxwidth;
- UINT32 minheight, maxheight;
- void (*recompute_children)(debugwin_info *);
- void (*update_menu)(debugwin_info *);
-
- int (*handle_command)(debugwin_info *, WPARAM, LPARAM);
- int (*handle_key)(debugwin_info *, WPARAM, LPARAM);
- UINT16 ignore_char_lparam;
-
- debugview_info view[MAX_VIEWS];
-
- HWND editwnd;
- char edit_defstr[256];
- void (*process_string)(debugwin_info *, const char *);
- WNDPROC original_editproc;
- TCHAR history[HISTORY_LENGTH][MAX_EDIT_STRING];
- int history_count;
- int last_history;
-
- HWND otherwnd[MAX_OTHER_WND];
-
-private:
- running_machine & m_machine;
-};
-
-
-//============================================================
-// LOCAL VARIABLES
-//============================================================
-
-static debugwin_info *window_list = NULL;
-static debugwin_info *main_console;
-static UINT32 main_console_regwidth;
-
-static UINT8 waiting_for_debugger;
-
-static HFONT debug_font;
-static UINT32 debug_font_height;
-static UINT32 debug_font_width;
-static UINT32 debug_font_ascent;
-
-static UINT32 hscroll_height;
-static UINT32 vscroll_width;
-
-
-
-//============================================================
-// PROTOTYPES
-//============================================================
-
-static debugwin_info *debugwin_window_create(running_machine &machine, LPCSTR title, WNDPROC handler);
-static void debugwin_window_free(debugwin_info *info);
-static LRESULT CALLBACK debugwin_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
-
-static void debugwin_view_draw_contents(debugview_info *view, HDC dc);
-static LRESULT CALLBACK debugwin_view_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
-static void debugwin_view_update(debug_view &view, void *osdprivate);
-static int debugwin_view_create(debugwin_info *info, int which, debug_view_type type);
-
-static LRESULT CALLBACK debugwin_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
-
-//static void generic_create_window(int type);
-static void generic_recompute_children(debugwin_info *info);
-
-static void memory_create_window(running_machine &machine);
-static void memory_recompute_children(debugwin_info *info);
-static void memory_process_string(debugwin_info *info, const char *string);
-static void memory_update_menu(debugwin_info *info);
-static int memory_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam);
-static int memory_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam);
-static void memory_update_caption(running_machine &machine, HWND wnd);
-
-static void disasm_create_window(running_machine &machine);
-static void disasm_recompute_children(debugwin_info *info);
-static void disasm_process_string(debugwin_info *info, const char *string);
-static void disasm_update_menu(debugwin_info *info);
-static int disasm_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam);
-static int disasm_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam);
-static void disasm_update_caption(running_machine &machine, HWND wnd);
+ // loop over windows and free them
+ while (m_window_list.first() != NULL)
+ m_window_list.first()->destroy();
-static void console_create_window(running_machine &machine);
-static void console_recompute_children(debugwin_info *info);
-static void console_process_string(debugwin_info *info, const char *string);
-static void console_set_cpu(device_t *device);
+ m_main_console = NULL;
+ m_metrics.reset();
+ m_machine = NULL;
+}
-static HMENU create_standard_menubar(void);
-static int global_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam);
-static int global_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam);
-static void smart_set_window_bounds(HWND wnd, HWND parent, RECT *bounds);
-static void smart_show_window(HWND wnd, BOOL show);
-static void smart_show_all(BOOL show);
-static void image_update_menu(debugwin_info *info);
+void debugger_windows::init_debugger(running_machine &machine)
+{
+ m_machine = &machine;
+ m_metrics.reset(global_alloc(ui_metrics(downcast<windows_options &>(m_machine->options()))));
+}
-//============================================================
-// wait_for_debugger
-//============================================================
-
void debugger_windows::wait_for_debugger(device_t &device, bool firststop)
{
- MSG message;
-
// create a console window
- if (main_console == NULL)
- console_create_window(*m_machine);
+ if (m_main_console == NULL)
+ m_main_console = create_window<consolewin_info>();
// update the views in the console to reflect the current CPU
- if (main_console != NULL)
- console_set_cpu(&device);
+ if (m_main_console != NULL)
+ m_main_console->set_cpu(device);
// when we are first stopped, adjust focus to us
- if (firststop && main_console != NULL)
+ if (firststop && (m_main_console != NULL))
{
- SetForegroundWindow(main_console->wnd);
+ m_main_console->set_foreground();
if (winwindow_has_focus())
- SetFocus(main_console->editwnd);
+ m_main_console->set_default_focus();
}
// make sure the debug windows are visible
- waiting_for_debugger = TRUE;
- smart_show_all(TRUE);
+ m_waiting_for_debugger = true;
+ show_all();
// run input polling to ensure that our status is in sync
wininput_poll(*m_machine);
// get and process messages
+ MSG message;
GetMessage(&message, NULL, 0, 0);
switch (message.message)
{
- // check for F10 -- we need to capture that ourselves
- case WM_SYSKEYDOWN:
- case WM_SYSKEYUP:
- if (message.wParam == VK_F4 && message.message == WM_SYSKEYDOWN)
- SendMessage(GetAncestor(GetFocus(), GA_ROOT), WM_CLOSE, 0, 0);
- if (message.wParam == VK_F10)
- SendMessage(GetAncestor(GetFocus(), GA_ROOT), (message.message == WM_SYSKEYDOWN) ? WM_KEYDOWN : WM_KEYUP, message.wParam, message.lParam);
- break;
+ // check for F10 -- we need to capture that ourselves
+ case WM_SYSKEYDOWN:
+ case WM_SYSKEYUP:
+ if (message.wParam == VK_F4 && message.message == WM_SYSKEYDOWN)
+ SendMessage(GetAncestor(GetFocus(), GA_ROOT), WM_CLOSE, 0, 0);
+ if (message.wParam == VK_F10)
+ SendMessage(GetAncestor(GetFocus(), GA_ROOT), (message.message == WM_SYSKEYDOWN) ? WM_KEYDOWN : WM_KEYUP, message.wParam, message.lParam);
+ break;
- // process everything else
- default:
- winwindow_dispatch_message(*m_machine, &message);
- break;
+ // process everything else
+ default:
+ winwindow_dispatch_message(*m_machine, &message);
+ break;
}
// mark the debugger as active
- waiting_for_debugger = FALSE;
+ m_waiting_for_debugger = false;
}
-
-//============================================================
-// debugwin_seq_pressed
-//============================================================
-
-static int debugwin_seq_pressed(running_machine &machine)
-{
- const input_seq &seq = machine.ioport().type_seq(IPT_UI_DEBUG_BREAK);
- int result = FALSE;
- int invert = FALSE;
- int first = TRUE;
- int codenum;
-
- // iterate over all of the codes
- int length = seq.length();
- for (codenum = 0; codenum < length; codenum++)
- {
- input_code code = seq[codenum];
-
- // handle NOT
- if (code == input_seq::not_code)
- invert = TRUE;
-
- // handle OR and END
- else if (code == input_seq::or_code || code == input_seq::end_code)
- {
- // if we have a positive result from the previous set, we're done
- if (result || code == input_seq::end_code)
- break;
-
- // otherwise, reset our state
- result = FALSE;
- invert = FALSE;
- first = TRUE;
- }
-
- // handle everything else as a series of ANDs
- else
- {
- int vkey = wininput_vkey_for_mame_code(code);
- int pressed = (vkey != 0 && (GetAsyncKeyState(vkey) & 0x8000) != 0);
-
- // if this is the first in the sequence, result is set equal
- if (first)
- result = pressed ^ invert;
-
- // further values are ANDed
- else if (result)
- result &= pressed ^ invert;
-
- // no longer first, and clear the invert flag
- first = invert = FALSE;
- }
- }
-
- // return the result if we queried at least one switch
- return result;
-}
-
-
-
-//============================================================
-// debugwin_init_windows
-//============================================================
-
-void debugger_windows::init_debugger(running_machine &machine)
-{
- static int class_registered;
-
- m_machine = &machine;
- // register the window classes
- if (!class_registered)
- {
- WNDCLASS wc = { 0 };
-
- // initialize the description of the window class
- wc.lpszClassName = TEXT("MAMEDebugWindow");
- wc.hInstance = GetModuleHandle(NULL);
- wc.lpfnWndProc = debugwin_window_proc;
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hIcon = LoadIcon(wc.hInstance, MAKEINTRESOURCE(2));
- wc.lpszMenuName = NULL;
- wc.hbrBackground = NULL;
- wc.style = 0;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
-
- // register the class; fail if we can't
- if (!RegisterClass(&wc))
- fatalerror("Unable to register debug window class\n");
-
- // initialize the description of the view class
- wc.lpszClassName = TEXT("MAMEDebugView");
- wc.lpfnWndProc = debugwin_view_proc;
-
- // register the class; fail if we can't
- if (!RegisterClass(&wc))
- fatalerror("Unable to register debug view class\n");
-
- class_registered = TRUE;
- }
-
- // create the font
- if (debug_font == NULL)
- {
- // create a temporary DC
- HDC temp_dc = GetDC(NULL);
- TEXTMETRIC metrics;
- HGDIOBJ old_font;
-
- if (temp_dc != NULL)
- {
- windows_options &options = downcast<windows_options &>(m_machine->options());
- int size = options.debugger_font_size();
- TCHAR *t_face;
-
- // create a standard font
- t_face = tstring_from_utf8(options.debugger_font());
- debug_font = CreateFont(-MulDiv(size, GetDeviceCaps(temp_dc, LOGPIXELSY), 72), 0, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE,
- ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, t_face);
- osd_free(t_face);
- t_face = NULL;
-
- if (debug_font == NULL)
- fatalerror("Unable to create debugger font\n");
-
- // get the metrics
- old_font = SelectObject(temp_dc, debug_font);
- if (GetTextMetrics(temp_dc, &metrics))
- {
- debug_font_width = metrics.tmAveCharWidth;
- debug_font_height = metrics.tmHeight;
- debug_font_ascent = metrics.tmAscent + metrics.tmExternalLeading;
- }
- SelectObject(temp_dc, old_font);
- ReleaseDC(NULL, temp_dc);
- }
- }
-
- // get other metrics
- hscroll_height = GetSystemMetrics(SM_CYHSCROLL);
- vscroll_width = GetSystemMetrics(SM_CXVSCROLL);
-}
-
-
-
-//============================================================
-// debugwin_destroy_windows
-//============================================================
-
-void debugger_windows::exit()
-{
- // loop over windows and free them
- while (window_list != NULL)
- {
- // clear the view list because they will be freed by the core
- memset(window_list->view, 0, sizeof(window_list->view));
- DestroyWindow(window_list->wnd);
- }
-
- main_console = NULL;
-}
-
-
-
-//============================================================
-// debugger_update
-//============================================================
-
void debugger_windows::debugger_update()
{
// if we're running live, do some checks
- if (!winwindow_has_focus() && !debug_cpu_is_stopped(*m_machine) && m_machine->phase() == MACHINE_PHASE_RUNNING)
+ if (!winwindow_has_focus() && !debug_cpu_is_stopped(*m_machine) && (m_machine->phase() == MACHINE_PHASE_RUNNING))
{
// see if the interrupt key is pressed and break if it is
- if (debugwin_seq_pressed(*m_machine))
+ if (seq_pressed())
{
- HWND focuswnd = GetFocus();
- debugwin_info *info;
+ HWND const focuswnd = GetFocus();
debug_cpu_get_visible_cpu(*m_machine)->debug()->halt_on_next_instruction("User-initiated break\n");
// if we were focused on some window's edit box, reset it to default
- for (info = window_list; info != NULL; info = info->next)
- if (focuswnd == info->editwnd)
- {
- SendMessage(focuswnd, WM_SETTEXT, (WPARAM)0, (LPARAM)info->edit_defstr);
- SendMessage(focuswnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
- }
- }
- }
-}
-
-
-
-//============================================================
-// debugwin_window_create
-//============================================================
-
-static debugwin_info *debugwin_window_create(running_machine &machine, LPCSTR title, WNDPROC handler)
-{
- debugwin_info *info = NULL;
- RECT work_bounds;
-
- // allocate memory
- info = global_alloc_clear(debugwin_info(machine));
-
- // create the window
- info->handler = handler;
- info->wnd = win_create_window_ex_utf8(DEBUG_WINDOW_STYLE_EX, "MAMEDebugWindow", title, DEBUG_WINDOW_STYLE,
- 0, 0, 100, 100, win_window_list->m_hwnd, create_standard_menubar(), GetModuleHandle(NULL), info);
- if (info->wnd == NULL)
- goto cleanup;
-
- // fill in some defaults
- SystemParametersInfo(SPI_GETWORKAREA, 0, &work_bounds, 0);
- info->minwidth = 200;
- info->minheight = 200;
- info->maxwidth = work_bounds.right - work_bounds.left;
- info->maxheight = work_bounds.bottom - work_bounds.top;
-
- // set the default handlers
- info->handle_command = global_handle_command;
- info->handle_key = global_handle_key;
- strcpy(info->edit_defstr, "");
-
- // hook us in
- info->next = window_list;
- window_list = info;
-
- return info;
-
-cleanup:
- if (info->wnd != NULL)
- DestroyWindow(info->wnd);
- global_free(info);
- return NULL;
-}
-
-
-
-//============================================================
-// debugwin_window_free
-//============================================================
-
-static void debugwin_window_free(debugwin_info *info)
-{
- debugwin_info **scanptr;
- int viewnum;
-
- // first unlink us from the list
- for (scanptr = &window_list; *scanptr != NULL; scanptr = &(*scanptr)->next)
- if (*scanptr == info)
- {
- *scanptr = info->next;
- break;
+ for (debugwin_info *info = m_window_list.first(); info != NULL; info = info->next())
+ info->restore_field(focuswnd);
}
-
- // free any views
- for (viewnum = 0; viewnum < ARRAY_LENGTH(info->view); viewnum++)
- if (info->view[viewnum].view != NULL)
- {
- info->machine().debug_view().free_view(*info->view[viewnum].view);
- info->view[viewnum].view = NULL;
- }
-
- // free our memory
- global_free(info);
-}
-
-
-
-//============================================================
-// debugwin_window_draw_contents
-//============================================================
-
-static void debugwin_window_draw_contents(debugwin_info *info, HDC dc)
-{
- RECT bounds, parent;
- int curview, curwnd;
-
- // fill the background with light gray
- GetClientRect(info->wnd, &parent);
- FillRect(dc, &parent, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
-
- // get the parent bounds in screen coords
- ClientToScreen(info->wnd, &((POINT *)&parent)[0]);
- ClientToScreen(info->wnd, &((POINT *)&parent)[1]);
-
- // draw edges around all views
- for (curview = 0; curview < MAX_VIEWS; curview++)
- if (info->view[curview].wnd)
- {
- GetWindowRect(info->view[curview].wnd, &bounds);
- bounds.top -= parent.top;
- bounds.bottom -= parent.top;
- bounds.left -= parent.left;
- bounds.right -= parent.left;
- InflateRect(&bounds, EDGE_WIDTH, EDGE_WIDTH);
- DrawEdge(dc, &bounds, EDGE_SUNKEN, BF_RECT);
- }
-
- // draw edges around all children
- if (info->editwnd)
- {
- GetWindowRect(info->editwnd, &bounds);
- bounds.top -= parent.top;
- bounds.bottom -= parent.top;
- bounds.left -= parent.left;
- bounds.right -= parent.left;
- InflateRect(&bounds, EDGE_WIDTH, EDGE_WIDTH);
- DrawEdge(dc, &bounds, EDGE_SUNKEN, BF_RECT);
}
-
- for (curwnd = 0; curwnd < MAX_OTHER_WND; curwnd++)
- if (info->otherwnd[curwnd])
- {
- GetWindowRect(info->otherwnd[curwnd], &bounds);
- bounds.top -= parent.top;
- bounds.bottom -= parent.top;
- bounds.left -= parent.left;
- bounds.right -= parent.left;
- InflateRect(&bounds, EDGE_WIDTH, EDGE_WIDTH);
- DrawEdge(dc, &bounds, EDGE_SUNKEN, BF_RECT);
- }
}
-
-//============================================================
-// debugwin_window_proc
-//============================================================
-
-static LRESULT CALLBACK debugwin_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
+bool debugger_windows::seq_pressed() const
{
- debugwin_info *info = (debugwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
-
- // handle a few messages
- switch (message)
- {
- // set the info pointer
- case WM_CREATE:
- {
- CREATESTRUCT *createinfo = (CREATESTRUCT *)lparam;
- info = (debugwin_info *)createinfo->lpCreateParams;
- SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)createinfo->lpCreateParams);
- if (info->handler)
- SetWindowLongPtr(wnd, GWLP_WNDPROC, (LONG_PTR)info->handler);
- break;
- }
-
- // paint: draw bezels as necessary
- case WM_PAINT:
- {
- PAINTSTRUCT pstruct;
- HDC dc = BeginPaint(wnd, &pstruct);
- debugwin_window_draw_contents(info, dc);
- EndPaint(wnd, &pstruct);
- break;
- }
-
- // keydown: handle debugger keys
- case WM_KEYDOWN:
- if ((*info->handle_key)(info, wparam, lparam))
- info->ignore_char_lparam = lparam >> 16;
- break;
-
- // char: ignore chars associated with keys we've handled
- case WM_CHAR:
- if (info->ignore_char_lparam == (lparam >> 16))
- info->ignore_char_lparam = 0;
- else if (waiting_for_debugger || !debugwin_seq_pressed(info->machine()))
- return DefWindowProc(wnd, message, wparam, lparam);
- break;
-
- // activate: set the focus
- case WM_ACTIVATE:
- if (wparam != WA_INACTIVE && info->focuswnd != NULL)
- SetFocus(info->focuswnd);
- break;
-
- // get min/max info: set the minimum window size
- case WM_GETMINMAXINFO:
- {
- MINMAXINFO *minmax = (MINMAXINFO *)lparam;
- if (info)
- {
- minmax->ptMinTrackSize.x = info->minwidth;
- minmax->ptMinTrackSize.y = info->minheight;
- minmax->ptMaxSize.x = minmax->ptMaxTrackSize.x = info->maxwidth;
- minmax->ptMaxSize.y = minmax->ptMaxTrackSize.y = info->maxheight;
- }
- break;
- }
-
- // sizing: recompute child window locations
- case WM_SIZE:
- case WM_SIZING:
- if (info->recompute_children != NULL)
- (*info->recompute_children)(info);
- InvalidateRect(wnd, NULL, FALSE);
- break;
-
- // mouse wheel: forward to the first view
- case WM_MOUSEWHEEL:
- {
- static int units_carryover = 0;
-
- UINT lines_per_click;
- if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines_per_click, 0))
- lines_per_click = 3;
-
- int units = GET_WHEEL_DELTA_WPARAM(wparam) + units_carryover;
- int clicks = units / WHEEL_DELTA;
- units_carryover = units % WHEEL_DELTA;
-
- int delta = clicks * lines_per_click;
- int viewnum = 0;
- POINT point;
- HWND child;
-
- // figure out which view we are hovering over
- GetCursorPos(&point);
- ScreenToClient(info->wnd, &point);
- child = ChildWindowFromPoint(info->wnd, point);
- if (child)
- {
- for (viewnum = 0; viewnum < MAX_VIEWS; viewnum++)
- if (info->view[viewnum].wnd == child)
- break;
- if (viewnum == MAX_VIEWS)
- break;
- }
-
- // send the appropriate message to this view's scrollbar
- if (info->view[viewnum].wnd && info->view[viewnum].vscroll)
- {
- int message_type = SB_LINEUP;
- if (delta < 0)
- {
- message_type = SB_LINEDOWN;
- delta = -delta;
- }
- while (delta > 0)
- {
- SendMessage(info->view[viewnum].wnd, WM_VSCROLL, message_type, (LPARAM)info->view[viewnum].vscroll);
- delta--;
- }
- }
- break;
- }
-
- // activate: set the focus
- case WM_INITMENU:
- if (info->update_menu != NULL)
- (*info->update_menu)(info);
- break;
-
- // command: handle a comment
- case WM_COMMAND:
- if (!(*info->handle_command)(info, wparam, lparam))
- return DefWindowProc(wnd, message, wparam, lparam);
- break;
+ input_seq const &seq = m_machine->ioport().type_seq(IPT_UI_DEBUG_BREAK);
+ bool result = false;
+ bool invert = false;
+ bool first = true;
- // close: close the window if it's not the main console
- case WM_CLOSE:
- if (main_console && main_console->wnd == wnd)
- {
- smart_show_all(FALSE);
- debug_cpu_get_visible_cpu(info->machine())->debug()->go();
- }
- else
- DestroyWindow(wnd);
- break;
-
- // destroy: close down the window
- case WM_NCDESTROY:
- debugwin_window_free(info);
- break;
-
- // everything else: defaults
- default:
- return DefWindowProc(wnd, message, wparam, lparam);
- }
-
- return 0;
-}
-
-
-
-//============================================================
-// debugwin_view_create
-//============================================================
-
-static int debugwin_view_create(debugwin_info *info, int which, debug_view_type type)
-{
- debugview_info *view = &info->view[which];
-
- // set the owner
- view->owner = info;
-
- // create the child view
- view->wnd = CreateWindowEx(DEBUG_VIEW_STYLE_EX, TEXT("MAMEDebugView"), NULL, DEBUG_VIEW_STYLE,
- 0, 0, 100, 100, info->wnd, NULL, GetModuleHandle(NULL), view);
- if (view->wnd == NULL)
- goto cleanup;
-
- // create the scroll bars
- view->hscroll = CreateWindowEx(HSCROLL_STYLE_EX, TEXT("SCROLLBAR"), NULL, HSCROLL_STYLE,
- 0, 0, 100, CW_USEDEFAULT, view->wnd, NULL, GetModuleHandle(NULL), view);
- view->vscroll = CreateWindowEx(VSCROLL_STYLE_EX, TEXT("SCROLLBAR"), NULL, VSCROLL_STYLE,
- 0, 0, CW_USEDEFAULT, 100, view->wnd, NULL, GetModuleHandle(NULL), view);
- if (view->hscroll == NULL || view->vscroll == NULL)
- goto cleanup;
-
- // create the debug view
- view->view = info->machine().debug_view().alloc_view(type, debugwin_view_update, view);
- if (view->view == NULL)
- goto cleanup;
-
- return 1;
-
-cleanup:
- if (view->view)
- info->machine().debug_view().free_view(*view->view);
- if (view->hscroll)
- DestroyWindow(view->hscroll);
- if (view->vscroll)
- DestroyWindow(view->vscroll);
- if (view->wnd)
- DestroyWindow(view->wnd);
- return 0;
-}
-
-
-
-//============================================================
-// debugwin_view_set_bounds
-//============================================================
-
-static void debugwin_view_set_bounds(debugview_info *info, HWND parent, const RECT *newbounds)
-{
- RECT bounds = *newbounds;
-
- // account for the edges and set the bounds
- if (info->wnd)
- smart_set_window_bounds(info->wnd, parent, &bounds);
-
- // update
- debugwin_view_update(*info->view, info);
-}
-
-
-
-//============================================================
-// debugwin_view_draw_contents
-//============================================================
-
-static void debugwin_view_draw_contents(debugview_info *view, HDC windc)
-{
- const debug_view_char *viewdata = view->view->viewdata();
- debug_view_xy visarea = view->view->visible_size();
- HGDIOBJ oldfont, oldbitmap;
- COLORREF oldfgcolor;
- UINT32 col, row;
- HBITMAP bitmap;
- int oldbkmode;
- RECT client;
- HDC dc;
-
- // get the client rect
- GetClientRect(view->wnd, &client);
-
- // create a compatible DC and an offscreen bitmap
- dc = CreateCompatibleDC(windc);
- if (dc == NULL)
- return;
- bitmap = CreateCompatibleBitmap(windc, client.right, client.bottom);
- if (bitmap == NULL)
- {
- DeleteDC(dc);
- return;
- }
- oldbitmap = SelectObject(dc, bitmap);
-
- // set the font
- oldfont = SelectObject(dc, debug_font);
- oldfgcolor = GetTextColor(dc);
- oldbkmode = GetBkMode(dc);
- SetBkMode(dc, TRANSPARENT);
-
- // iterate over rows and columns
- for (row = 0; row < visarea.y; row++)
- {
- int iter;
-
- // loop twice; once to fill the background and once to draw the text
- for (iter = 0; iter < 2; iter++)
- {
- COLORREF fgcolor = RGB(0x00,0x00,0x00);
- COLORREF bgcolor = RGB(0xff,0xff,0xff);
- HBRUSH bgbrush = NULL;
- int last_attrib = -1;
- TCHAR buffer[256];
- int count = 0;
- RECT bounds;
-
- // initialize the text bounds
- bounds.left = bounds.right = 0;
- bounds.top = row * debug_font_height;
- bounds.bottom = bounds.top + debug_font_height;
-
- // start with a brush on iteration #0
- if (iter == 0)
- bgbrush = CreateSolidBrush(bgcolor);
-
- // iterate over columns
- for (col = 0; col < visarea.x; col++)
- {
- // if the attribute changed, adjust the colors
- if (viewdata[col].attrib != last_attrib)
- {
- 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_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);
-
- // flush any pending drawing
- if (count > 0)
- {
- bounds.right = bounds.left + count * debug_font_width;
- if (iter == 0)
- FillRect(dc, &bounds, bgbrush);
- else
- ExtTextOut(dc, bounds.left, bounds.top, 0, NULL, buffer, count, NULL);
- bounds.left = bounds.right;
- count = 0;
- }
-
- // set the new colors
- if (iter == 0 && oldbg != bgcolor)
- {
- DeleteObject(bgbrush);
- bgbrush = CreateSolidBrush(bgcolor);
- }
- else if (iter == 1)
- SetTextColor(dc, fgcolor);
- last_attrib = viewdata[col].attrib;
- }
-
- // add this character to the buffer
- buffer[count++] = viewdata[col].byte;
- }
-
- // flush any remaining stuff
- if (count > 0)
- {
- bounds.right = bounds.left + count * debug_font_width;
- if (iter == 0)
- FillRect(dc, &bounds, bgbrush);
- else
- ExtTextOut(dc, bounds.left, bounds.top, 0, NULL, buffer, count, NULL);
- }
-
- // erase to the end of the line
- if (iter == 0)
- {
- bounds.left = bounds.right;
- bounds.right = client.right;
- FillRect(dc, &bounds, bgbrush);
- DeleteObject(bgbrush);
- }
- }
-
- // advance viewdata
- viewdata += visarea.x;
- }
-
- // erase anything beyond the bottom with white
- GetClientRect(view->wnd, &client);
- client.top = visarea.y * debug_font_height;
- FillRect(dc, &client, (HBRUSH)GetStockObject(WHITE_BRUSH));
-
- // reset the font
- SetBkMode(dc, oldbkmode);
- SetTextColor(dc, oldfgcolor);
- SelectObject(dc, oldfont);
-
- // blit the final results
- BitBlt(windc, 0, 0, client.right, client.bottom, dc, 0, 0, SRCCOPY);
-
- // undo the offscreen stuff
- SelectObject(dc, oldbitmap);
- DeleteObject(bitmap);
- DeleteDC(dc);
-}
-
-
-
-//============================================================
-// debugwin_view_update
-//============================================================
-
-static void debugwin_view_update(debug_view &view, void *osdprivate)
-{
- debugview_info *info = (debugview_info *)osdprivate;
- RECT bounds, vscroll_bounds, hscroll_bounds;
- debug_view_xy totalsize, visiblesize, topleft;
- int show_vscroll, show_hscroll;
- SCROLLINFO scrollinfo;
-
- assert(info->view == &view);
-
- // get the view window bounds
- GetClientRect(info->wnd, &bounds);
- visiblesize.x = (bounds.right - bounds.left) / debug_font_width;
- visiblesize.y = (bounds.bottom - bounds.top) / debug_font_height;
-
- // get the updated total rows/cols and left row/col
- totalsize = view.total_size();
- topleft = view.visible_position();
-
- // determine if we need to show the scrollbars
- show_vscroll = show_hscroll = FALSE;
- if (totalsize.x > visiblesize.x && bounds.bottom >= hscroll_height)
- {
- bounds.bottom -= hscroll_height;
- visiblesize.y = (bounds.bottom - bounds.top) / debug_font_height;
- show_hscroll = TRUE;
- }
- if (totalsize.y > visiblesize.y && bounds.right >= vscroll_width)
- {
- bounds.right -= vscroll_width;
- visiblesize.x = (bounds.right - bounds.left) / debug_font_width;
- show_vscroll = TRUE;
- }
- if (!show_vscroll && totalsize.y > visiblesize.y && bounds.right >= vscroll_width)
- {
- bounds.right -= vscroll_width;
- visiblesize.x = (bounds.right - bounds.left) / debug_font_width;
- show_vscroll = TRUE;
- }
-
- // compute the bounds of the scrollbars
- GetClientRect(info->wnd, &vscroll_bounds);
- vscroll_bounds.left = vscroll_bounds.right - vscroll_width;
- if (show_hscroll)
- vscroll_bounds.bottom -= hscroll_height;
-
- GetClientRect(info->wnd, &hscroll_bounds);
- hscroll_bounds.top = hscroll_bounds.bottom - hscroll_height;
- if (show_vscroll)
- hscroll_bounds.right -= vscroll_width;
-
- // if we hid the scrollbars, make sure we reset the top/left corners
- if (topleft.y + visiblesize.y > totalsize.y)
- topleft.y = MAX(totalsize.y - visiblesize.y, 0);
- if (topleft.x + visiblesize.x > totalsize.x)
- topleft.x = 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(info->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(info->hscroll, SB_CTL, &scrollinfo, TRUE);
-
- // update window info
- visiblesize.y++;
- visiblesize.x++;
- view.set_visible_size(visiblesize);
- view.set_visible_position(topleft);
-
- // invalidate the bounds
- InvalidateRect(info->wnd, NULL, FALSE);
-
- // adjust the bounds of the scrollbars and show/hide them
- if (info->vscroll)
- {
- if (show_vscroll)
- smart_set_window_bounds(info->vscroll, info->wnd, &vscroll_bounds);
- smart_show_window(info->vscroll, show_vscroll);
- }
- if (info->hscroll)
- {
- if (show_hscroll)
- smart_set_window_bounds(info->hscroll, info->wnd, &hscroll_bounds);
- smart_show_window(info->hscroll, show_hscroll);
- }
-}
-
-
-
-//============================================================
-// debugwin_view_process_scroll
-//============================================================
-
-static UINT32 debugwin_view_process_scroll(debugview_info *info, WORD type, HWND wnd)
-{
- SCROLLINFO scrollinfo;
- INT32 maxval;
- INT32 result;
-
- // get the current info
- scrollinfo.cbSize = sizeof(scrollinfo);
- scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
- GetScrollInfo(wnd, SB_CTL, &scrollinfo);
-
- // by default we stay put
- result = scrollinfo.nPos;
-
- // determine the maximum value
- maxval = (scrollinfo.nMax > scrollinfo.nPage) ? (scrollinfo.nMax - scrollinfo.nPage + 1) : 0;
-
- // handle the message
- switch (type)
- {
- case SB_THUMBTRACK:
- result = scrollinfo.nTrackPos;
- break;
-
- case SB_LEFT:
- result = 0;
- break;
-
- case SB_RIGHT:
- result = maxval;
- break;
-
- case SB_LINELEFT:
- result -= 1;
- break;
-
- case SB_LINERIGHT:
- result += 1;
- break;
-
- case SB_PAGELEFT:
- result -= scrollinfo.nPage - 1;
- break;
-
- case SB_PAGERIGHT:
- result += scrollinfo.nPage - 1;
- break;
- }
-
- // generic rangecheck
- if (result < 0)
- result = 0;
- if (result > maxval)
- result = maxval;
-
- // set the new position
- scrollinfo.fMask = SIF_POS;
- scrollinfo.nPos = result;
- SetScrollInfo(wnd, SB_CTL, &scrollinfo, TRUE);
-
- return (UINT32)result;
-}
-
-
-
-//============================================================
-// debugwin_view_prev_view
-//============================================================
-
-static void debugwin_view_prev_view(debugwin_info *info, debugview_info *curview)
-{
- int curindex = 1;
- int numviews;
-
- // count the number of views
- for (numviews = 0; numviews < MAX_VIEWS; numviews++)
- if (info->view[numviews].wnd == NULL)
- break;
-
- // if we have a curview, find out its index
- if (curview)
- curindex = curview - &info->view[0];
-
- // loop until we find someone to take focus
- while (1)
- {
- // advance to the previous index
- curindex--;
- if (curindex < -1)
- curindex = numviews - 1;
-
- // negative numbers mean the focuswnd
- if (curindex < 0 && info->focuswnd != NULL)
- {
- SetFocus(info->focuswnd);
- break;
- }
-
- // positive numbers mean a view
- else if (curindex >= 0 && info->view[curindex].wnd != NULL && info->view[curindex].view->cursor_supported())
- {
- SetFocus(info->view[curindex].wnd);
- break;
- }
- }
-}
-
-
-
-//============================================================
-// debugwin_view_next_view
-//============================================================
-
-static void debugwin_view_next_view(debugwin_info *info, debugview_info *curview)
-{
- int curindex = -1;
- int numviews;
-
- // count the number of views
- for (numviews = 0; numviews < MAX_VIEWS; numviews++)
- if (info->view[numviews].wnd == NULL)
- break;
-
- // if we have a curview, find out its index
- if (curview)
- curindex = curview - &info->view[0];
-
- // loop until we find someone to take focus
- while (1)
- {
- // advance to the previous index
- curindex++;
- if (curindex >= numviews)
- curindex = -1;
-
- // negative numbers mean the focuswnd
- if (curindex < 0 && info->focuswnd != NULL)
- {
- SetFocus(info->focuswnd);
- break;
- }
-
- // positive numbers mean a view
- else if (curindex >= 0 && info->view[curindex].wnd != NULL && info->view[curindex].view->cursor_supported())
- {
- SetFocus(info->view[curindex].wnd);
- InvalidateRect(info->view[curindex].wnd, NULL, FALSE);
- break;
- }
- }
-}
-
-
-
-//============================================================
-// debugwin_view_proc
-//============================================================
-
-static LRESULT CALLBACK debugwin_view_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
-{
- debugview_info *info = (debugview_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
-
- // handle a few messages
- switch (message)
+ // iterate over all of the codes
+ for (int codenum = 0, length = seq.length(); codenum < length; codenum++)
{
- // set the info pointer
- case WM_CREATE:
- {
- CREATESTRUCT *createinfo = (CREATESTRUCT *)lparam;
- SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)createinfo->lpCreateParams);
- break;
- }
-
- // paint: redraw the last bitmap
- case WM_PAINT:
- {
- PAINTSTRUCT pstruct;
- HDC dc = BeginPaint(wnd, &pstruct);
- debugwin_view_draw_contents(info, dc);
- EndPaint(wnd, &pstruct);
- break;
- }
-
- // keydown: handle debugger keys
- case WM_SYSKEYDOWN:
- if (wparam != VK_F10)
- return DefWindowProc(wnd, message, wparam, lparam);
- // (fall through)
- case WM_KEYDOWN:
- {
- if ((*info->owner->handle_key)(info->owner, wparam, lparam))
- info->owner->ignore_char_lparam = lparam >> 16;
- else
- {
- switch (wparam)
- {
- case VK_UP:
- info->view->process_char(DCH_UP);
- info->owner->ignore_char_lparam = lparam >> 16;
- break;
-
- case VK_DOWN:
- info->view->process_char(DCH_DOWN);
- info->owner->ignore_char_lparam = lparam >> 16;
- break;
-
- case VK_LEFT:
- if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
- info->view->process_char(DCH_CTRLLEFT);
- else
- info->view->process_char(DCH_LEFT);
- info->owner->ignore_char_lparam = lparam >> 16;
- break;
-
- case VK_RIGHT:
- if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
- info->view->process_char(DCH_CTRLRIGHT);
- else
- info->view->process_char(DCH_RIGHT);
- info->owner->ignore_char_lparam = lparam >> 16;
- break;
-
- case VK_PRIOR:
- info->view->process_char(DCH_PUP);
- info->owner->ignore_char_lparam = lparam >> 16;
- break;
-
- case VK_NEXT:
- info->view->process_char(DCH_PDOWN);
- info->owner->ignore_char_lparam = lparam >> 16;
- break;
-
- case VK_HOME:
- if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
- info->view->process_char(DCH_CTRLHOME);
- else
- info->view->process_char(DCH_HOME);
- info->owner->ignore_char_lparam = lparam >> 16;
- break;
-
- case VK_END:
- if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
- info->view->process_char(DCH_CTRLEND);
- else
- info->view->process_char(DCH_END);
- info->owner->ignore_char_lparam = lparam >> 16;
- break;
-
- case VK_ESCAPE:
- if (info->owner->focuswnd != NULL)
- SetFocus(info->owner->focuswnd);
- info->owner->ignore_char_lparam = lparam >> 16;
- break;
-
- case VK_TAB:
- if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
- debugwin_view_prev_view(info->owner, info);
- else
- debugwin_view_next_view(info->owner, info);
- info->owner->ignore_char_lparam = lparam >> 16;
- break;
- }
- }
- break;
- }
-
- // char: ignore chars associated with keys we've handled
- case WM_CHAR:
- {
- if (info->owner->ignore_char_lparam == (lparam >> 16))
- info->owner->ignore_char_lparam = 0;
- else if (waiting_for_debugger || !debugwin_seq_pressed(info->owner->machine()))
- {
- if (wparam >= 32 && wparam < 127 && info->view->cursor_supported())
- info->view->process_char(wparam);
- else
- return DefWindowProc(wnd, message, wparam, lparam);
- }
- break;
- }
-
- // gaining focus
- case WM_SETFOCUS:
- {
- if (info->view->cursor_supported())
- info->view->set_cursor_visible(true);
- break;
- }
-
- // losing focus
- case WM_KILLFOCUS:
- {
- if (info->view->cursor_supported())
- info->view->set_cursor_visible(false);
- break;
- }
-
- // mouse click
- case WM_LBUTTONDOWN:
- {
- if (info->view->cursor_supported())
- {
- debug_view_xy topleft = info->view->visible_position();
- debug_view_xy newpos;
- newpos.x = topleft.x + GET_X_LPARAM(lparam) / debug_font_width;
- newpos.y = topleft.y + GET_Y_LPARAM(lparam) / debug_font_height;
- info->view->set_cursor_position(newpos);
- SetFocus(wnd);
- }
- break;
- }
+ input_code code = seq[codenum];
- // hscroll
- case WM_HSCROLL:
+ if (code == input_seq::not_code)
{
- debug_view_xy topleft = info->view->visible_position();
- topleft.x = debugwin_view_process_scroll(info, LOWORD(wparam), (HWND)lparam);
- info->view->set_visible_position(topleft);
- info->owner->machine().debug_view().flush_osd_updates();
- break;
+ // handle NOT
+ invert = true;
}
-
- // vscroll
- case WM_VSCROLL:
+ else if (code == input_seq::or_code || code == input_seq::end_code)
{
- debug_view_xy topleft = info->view->visible_position();
- topleft.y = debugwin_view_process_scroll(info, LOWORD(wparam), (HWND)lparam);
- info->view->set_visible_position(topleft);
- info->owner->machine().debug_view().flush_osd_updates();
- break;
- }
-
- // everything else: defaults
- default:
- return DefWindowProc(wnd, message, wparam, lparam);
- }
-
- return 0;
-}
-
-
-
-//============================================================
-// debugwin_edit_proc
-//============================================================
-
-static LRESULT CALLBACK debugwin_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
-{
- debugwin_info *info = (debugwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
- TCHAR buffer[MAX_EDIT_STRING];
-
- // handle a few messages
- switch (message)
- {
- // key down: handle navigation in the attached view
- case WM_SYSKEYDOWN:
- if (wparam != VK_F10)
- return CallWindowProc(info->original_editproc, wnd, message, wparam, lparam);
- // (fall through)
- case WM_KEYDOWN:
- switch (wparam)
- {
- case VK_UP:
- if (info->last_history < info->history_count - 1)
- info->last_history++;
- else
- info->last_history = 0;
- SendMessage(wnd, WM_SETTEXT, (WPARAM)0, (LPARAM)&info->history[info->last_history][0]);
- SendMessage(wnd, EM_SETSEL, (WPARAM)MAX_EDIT_STRING, (LPARAM)MAX_EDIT_STRING);
- break;
-
- case VK_DOWN:
- if (info->last_history > 0)
- info->last_history--;
- else if (info->history_count > 0)
- info->last_history = info->history_count - 1;
- else
- info->last_history = 0;
- SendMessage(wnd, WM_SETTEXT, (WPARAM)0, (LPARAM)&info->history[info->last_history][0]);
- SendMessage(wnd, EM_SETSEL, (WPARAM)MAX_EDIT_STRING, (LPARAM)MAX_EDIT_STRING);
- break;
-
- case VK_PRIOR:
- if (info->view[0].wnd && info->view[0].vscroll)
- SendMessage(info->view[0].wnd, WM_VSCROLL, SB_PAGELEFT, (LPARAM)info->view[0].vscroll);
- break;
-
- case VK_NEXT:
- if (info->view[0].wnd && info->view[0].vscroll)
- SendMessage(info->view[0].wnd, WM_VSCROLL, SB_PAGERIGHT, (LPARAM)info->view[0].vscroll);
- break;
-
- case VK_TAB:
- if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
- debugwin_view_prev_view(info, NULL);
- else
- debugwin_view_next_view(info, NULL);
- info->ignore_char_lparam = lparam >> 16;
- break;
-
- default:
- if ((*info->handle_key)(info, wparam, lparam))
- info->ignore_char_lparam = lparam >> 16;
- else
- return CallWindowProc(info->original_editproc, wnd, message, wparam, lparam);
- break;
- }
- break;
-
- // char: handle the return key
- case WM_CHAR:
-
- // ignore chars associated with keys we've handled
- if (info->ignore_char_lparam == (lparam >> 16))
- info->ignore_char_lparam = 0;
- else if (waiting_for_debugger || !debugwin_seq_pressed(info->machine()))
- {
- switch (wparam)
- {
- case 13:
- {
- // fetch the text
- SendMessage(wnd, WM_GETTEXT, (WPARAM)ARRAY_LENGTH(buffer), (LPARAM)buffer);
-
- // add to the history if it's not a repeat of the last one
- if (buffer[0] != 0 && _tcscmp(buffer, &info->history[0][0]))
- {
- memmove(&info->history[1][0], &info->history[0][0], (HISTORY_LENGTH - 1) * MAX_EDIT_STRING);
- _tcscpy(&info->history[0][0], buffer);
- if (info->history_count < HISTORY_LENGTH)
- info->history_count++;
- }
- info->last_history = info->history_count - 1;
-
- // process
- if (info->process_string)
- {
- char *utf8_buffer = utf8_from_tstring(buffer);
- if (utf8_buffer != NULL)
- {
- (*info->process_string)(info, utf8_buffer);
- osd_free(utf8_buffer);
- }
- }
- break;
- }
-
- case 27:
- {
- // fetch the text
- SendMessage(wnd, WM_GETTEXT, (WPARAM)sizeof(buffer), (LPARAM)buffer);
-
- // if it's not empty, clear the text
- if (_tcslen(buffer) > 0)
- {
- info->ignore_char_lparam = lparam >> 16;
- SendMessage(wnd, WM_SETTEXT, (WPARAM)0, (LPARAM)info->edit_defstr);
- }
- break;
- }
-
- default:
- return CallWindowProc(info->original_editproc, wnd, message, wparam, lparam);
- }
- }
- break;
-
- // everything else: defaults
- default:
- return CallWindowProc(info->original_editproc, wnd, message, wparam, lparam);
- }
-
- return 0;
-}
-
-
+ // handle OR and END
-//============================================================
-// generic_create_window
-//============================================================
-
-#ifdef UNUSED_FUNCTION
-static void generic_create_window(running_machine &machine, debug_view_type type)
-{
- debugwin_info *info;
- char title[256];
-
- // create the window
- _snprintf(title, ARRAY_LENGTH(title), "Debug: %s [%s]", machine.system().description, machine.system().name);
- info = debugwin_window_create(machine, title, NULL);
- if (info == NULL || !debugwin_view_create(info, 0, type))
- return;
-
- // set the child function
- info->recompute_children = generic_recompute_children;
-
- // recompute the children once to get the maxwidth
- generic_recompute_children(info);
-
- // position the window and recompute children again
- SetWindowPos(info->wnd, HWND_TOP, 100, 100, info->maxwidth, 200, SWP_SHOWWINDOW);
- generic_recompute_children(info);
-}
-#endif
-
-
-
-//============================================================
-// generic_recompute_children
-//============================================================
-
-static void generic_recompute_children(debugwin_info *info)
-{
- debug_view_xy totalsize = info->view[0].view->total_size();
- RECT parent;
- RECT bounds;
-
- // compute a client rect
- bounds.top = bounds.left = 0;
- bounds.right = totalsize.x * debug_font_width + vscroll_width + 2 * EDGE_WIDTH;
- bounds.bottom = 200;
- AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
-
- // clamp the min/max size
- info->maxwidth = bounds.right - bounds.left;
-
- // get the parent's dimensions
- GetClientRect(info->wnd, &parent);
-
- // view gets the remaining space
- InflateRect(&parent, -EDGE_WIDTH, -EDGE_WIDTH);
- debugwin_view_set_bounds(&info->view[0], info->wnd, &parent);
-}
-
-
-
-//============================================================
-// log_create_window
-//============================================================
-
-static void log_create_window(running_machine &machine)
-{
- debug_view_xy totalsize;
- debugwin_info *info;
- char title[256];
- RECT bounds;
-
- // create the window
- _snprintf(title, ARRAY_LENGTH(title), "Errorlog: %s [%s]", machine.system().description, machine.system().name);
- info = debugwin_window_create(machine, title, NULL);
- if (info == NULL || !debugwin_view_create(info, 0, DVT_LOG))
- return;
-
- // set the child function
- info->recompute_children = generic_recompute_children;
-
- // get the view width
- totalsize = info->view[0].view->total_size();
-
- // compute a client rect
- bounds.top = bounds.left = 0;
- bounds.right = totalsize.x * debug_font_width + vscroll_width + 2 * EDGE_WIDTH;
- bounds.bottom = 200;
- AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
-
- // clamp the min/max size
- info->maxwidth = bounds.right - bounds.left;
-
- // position the window at the bottom-right
- SetWindowPos(info->wnd, HWND_TOP,
- 100, 100,
- bounds.right - bounds.left, bounds.bottom - bounds.top,
- SWP_SHOWWINDOW);
-
- // recompute the children and set focus on the edit box
- generic_recompute_children(info);
-}
-
-
-
-//============================================================
-// memory_create_window
-//============================================================
-
-static void memory_create_window(running_machine &machine)
-{
- device_t *curcpu = debug_cpu_get_visible_cpu(machine);
- debugwin_info *info;
- HMENU optionsmenu;
-
- // create the window
- info = debugwin_window_create(machine, "Memory", NULL);
- if (info == NULL || !debugwin_view_create(info, 0, DVT_MEMORY))
- return;
-
- // set the handlers
- info->handle_command = memory_handle_command;
- info->handle_key = memory_handle_key;
- info->update_menu = memory_update_menu;
-
- // create the options menu
- 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_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(GetMenu(info->wnd), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
-
- // set up the view to track the initial expression
- downcast<debug_view_memory *>(info->view[0].view)->set_expression("0");
- strcpy(info->edit_defstr, "0");
-
- // create an edit box and override its key handling
- info->editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), NULL, EDIT_BOX_STYLE,
- 0, 0, 100, 100, info->wnd, NULL, GetModuleHandle(NULL), NULL);
- info->original_editproc = (WNDPROC)(FPTR)GetWindowLongPtr(info->editwnd, GWLP_WNDPROC);
- SetWindowLongPtr(info->editwnd, GWLP_USERDATA, (LONG_PTR)info);
- SetWindowLongPtr(info->editwnd, GWLP_WNDPROC, (LONG_PTR)debugwin_edit_proc);
- SendMessage(info->editwnd, WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE);
- SendMessage(info->editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT("0"));
- SendMessage(info->editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0);
- SendMessage(info->editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
-
- // create a combo box
- info->otherwnd[0] = CreateWindowEx(COMBO_BOX_STYLE_EX, TEXT("COMBOBOX"), NULL, COMBO_BOX_STYLE,
- 0, 0, 100, 1000, info->wnd, NULL, GetModuleHandle(NULL), NULL);
- SetWindowLongPtr(info->otherwnd[0], GWLP_USERDATA, (LONG_PTR)info);
- SendMessage(info->otherwnd[0], WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE);
-
- // populate the combobox
- int maxlength = 0;
- for (const debug_view_source *source = info->view[0].view->first_source(); source != NULL; source = source->next())
- {
- int length = strlen(source->name());
- if (length > maxlength)
- maxlength = length;
- TCHAR *t_name = tstring_from_utf8(source->name());
- SendMessage(info->otherwnd[0], CB_ADDSTRING, 0, (LPARAM)t_name);
- osd_free(t_name);
- }
- const debug_view_source *source = info->view[0].view->source_for_device(curcpu);
- SendMessage(info->otherwnd[0], CB_SETCURSEL, info->view[0].view->source_list().indexof(*source), 0);
- SendMessage(info->otherwnd[0], CB_SETDROPPEDWIDTH, (maxlength + 2) * debug_font_width + vscroll_width, 0);
- info->view[0].view->set_source(*source);
-
- // set the child functions
- info->recompute_children = memory_recompute_children;
- info->process_string = memory_process_string;
-
- // set the caption
- memory_update_caption(machine, info->wnd);
-
- // recompute the children once to get the maxwidth
- memory_recompute_children(info);
-
- // position the window and recompute children again
- SetWindowPos(info->wnd, HWND_TOP, 100, 100, info->maxwidth, 200, SWP_SHOWWINDOW);
- memory_recompute_children(info);
-
- // mark the edit box as the default focus and set it
- info->focuswnd = info->editwnd;
- SetFocus(info->editwnd);
-}
-
-
-
-//============================================================
-// memory_recompute_children
-//============================================================
-
-static void memory_recompute_children(debugwin_info *info)
-{
- debug_view_xy totalsize = info->view[0].view->total_size();
- RECT parent, memrect, editrect, comborect;
- RECT bounds;
-
- // compute a client rect
- bounds.top = bounds.left = 0;
- bounds.right = totalsize.x * debug_font_width + vscroll_width + 2 * EDGE_WIDTH;
- bounds.bottom = 200;
- AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
-
- // clamp the min/max size
- info->maxwidth = bounds.right - bounds.left;
-
- // get the parent's dimensions
- GetClientRect(info->wnd, &parent);
-
- // edit box gets half of the width
- editrect.top = parent.top + EDGE_WIDTH;
- editrect.bottom = editrect.top + debug_font_height + 4;
- editrect.left = parent.left + EDGE_WIDTH;
- editrect.right = parent.left + (parent.right - parent.left) / 2 - EDGE_WIDTH;
-
- // combo box gets the other half of the width
- comborect.top = editrect.top;
- comborect.bottom = editrect.bottom;
- comborect.left = editrect.right + 2 * EDGE_WIDTH;
- comborect.right = parent.right - EDGE_WIDTH;
-
- // memory view gets the rest
- memrect.top = editrect.bottom + 2 * EDGE_WIDTH;
- memrect.bottom = parent.bottom - EDGE_WIDTH;
- memrect.left = parent.left + EDGE_WIDTH;
- memrect.right = parent.right - EDGE_WIDTH;
-
- // set the bounds of things
- debugwin_view_set_bounds(&info->view[0], info->wnd, &memrect);
- smart_set_window_bounds(info->editwnd, info->wnd, &editrect);
- smart_set_window_bounds(info->otherwnd[0], info->wnd, &comborect);
-}
-
-
-
-//============================================================
-// memory_process_string
-//============================================================
-
-static void memory_process_string(debugwin_info *info, const char *string)
-{
- // set the string to the memory view
- downcast<debug_view_memory *>(info->view[0].view)->set_expression(string);
-
- // select everything in the edit text box
- SendMessage(info->editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
-
- // update the default string to match
- strncpy(info->edit_defstr, string, sizeof(info->edit_defstr) - 1);
-}
-
-
-
-//============================================================
-// memory_update_menu
-//============================================================
-
-static void memory_update_menu(debugwin_info *info)
-{
- debug_view_memory *memview = downcast<debug_view_memory *>(info->view[0].view);
- CheckMenuItem(GetMenu(info->wnd), ID_1_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 1 ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(GetMenu(info->wnd), ID_2_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 2 ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(GetMenu(info->wnd), ID_4_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 4 ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(GetMenu(info->wnd), ID_8_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 8 ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(GetMenu(info->wnd), ID_LOGICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_UNCHECKED : MF_CHECKED));
- CheckMenuItem(GetMenu(info->wnd), ID_PHYSICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(GetMenu(info->wnd), ID_REVERSE_VIEW, MF_BYCOMMAND | (memview->reverse() ? MF_CHECKED : MF_UNCHECKED));
-}
-
-
-
-//============================================================
-// memory_handle_command
-//============================================================
-
-static int memory_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam)
-{
- debug_view_memory *memview = downcast<debug_view_memory *>(info->view[0].view);
- switch (HIWORD(wparam))
- {
- // combo box selection changed
- case CBN_SELCHANGE:
- {
- int sel = SendMessage((HWND)lparam, CB_GETCURSEL, 0, 0);
- if (sel != CB_ERR)
- {
- memview->set_source(*memview->source_list().find(sel));
- memory_update_caption(info->machine(), info->wnd);
+ // if we have a positive result from the previous set, we're done
+ if (result || code == input_seq::end_code)
+ break;
- // reset the focus
- SetFocus(info->focuswnd);
- return 1;
- }
- break;
+ // otherwise, reset our state
+ result = false;
+ invert = false;
+ first = true;
}
-
- // menu selections
- case 0:
- switch (LOWORD(wparam))
- {
- case ID_1_BYTE_CHUNKS:
- memview->set_bytes_per_chunk(1);
- return 1;
-
- case ID_2_BYTE_CHUNKS:
- memview->set_bytes_per_chunk(2);
- return 1;
-
- case ID_4_BYTE_CHUNKS:
- memview->set_bytes_per_chunk(4);
- return 1;
-
- case ID_8_BYTE_CHUNKS:
- memview->set_bytes_per_chunk(8);
- return 1;
-
- case ID_LOGICAL_ADDRESSES:
- memview->set_physical(false);
- return 1;
-
- case ID_PHYSICAL_ADDRESSES:
- memview->set_physical(true);
- return 1;
-
- case ID_REVERSE_VIEW:
- memview->set_reverse(!memview->reverse());
- return 1;
-
- case ID_INCREASE_MEM_WIDTH:
- memview->set_chunks_per_row(memview->chunks_per_row() + 1);
- return 1;
-
- case ID_DECREASE_MEM_WIDTH:
- memview->set_chunks_per_row(memview->chunks_per_row() - 1);
- return 1;
- }
- break;
- }
- return global_handle_command(info, wparam, lparam);
-}
-
-
-
-//============================================================
-// memory_handle_key
-//============================================================
-
-static int memory_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam)
-{
- if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
- {
- switch (wparam)
+ else
{
- case '1':
- SendMessage(info->wnd, WM_COMMAND, ID_1_BYTE_CHUNKS, 0);
- return 1;
-
- case '2':
- SendMessage(info->wnd, WM_COMMAND, ID_2_BYTE_CHUNKS, 0);
- return 1;
-
- case '4':
- SendMessage(info->wnd, WM_COMMAND, ID_4_BYTE_CHUNKS, 0);
- return 1;
-
- case '8':
- SendMessage(info->wnd, WM_COMMAND, ID_8_BYTE_CHUNKS, 0);
- return 1;
-
- case 'L':
- SendMessage(info->wnd, WM_COMMAND, ID_LOGICAL_ADDRESSES, 0);
- return 1;
-
- case 'Y':
- SendMessage(info->wnd, WM_COMMAND, ID_PHYSICAL_ADDRESSES, 0);
- return 1;
+ // handle everything else as a series of ANDs
+ int const vkey = wininput_vkey_for_mame_code(code);
+ bool const pressed = (vkey != 0) && ((GetAsyncKeyState(vkey) & 0x8000) != 0);
- case 'R':
- SendMessage(info->wnd, WM_COMMAND, ID_REVERSE_VIEW, 0);
- return 1;
-
- case 'P':
- SendMessage(info->wnd, WM_COMMAND, ID_INCREASE_MEM_WIDTH, 0);
- return 1;
+ if (first) // if this is the first in the sequence, result is set equal
+ result = pressed ^ invert;
+ else if (result) // further values are ANDed
+ result = result && (pressed ^ invert);
- case 'O':
- SendMessage(info->wnd, WM_COMMAND, ID_DECREASE_MEM_WIDTH, 0);
- return 1;
+ // no longer first, and clear the invert flag
+ first = invert = false;
}
}
- return global_handle_key(info, wparam, lparam);
-}
-
-
-
-//============================================================
-// memory_update_caption
-//============================================================
-
-static void memory_update_caption(running_machine &machine, HWND wnd)
-{
- debugwin_info *info = (debugwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
- astring title;
-
- title.printf("Memory: %s", info->view[0].view->source()->name());
- win_set_window_text_utf8(wnd, title);
-}
-
-
-
-//============================================================
-// disasm_create_window
-//============================================================
-
-static void disasm_create_window(running_machine &machine)
-{
- device_t *curcpu = debug_cpu_get_visible_cpu(machine);
- debugwin_info *info;
- HMENU optionsmenu;
-
- // create the window
- info = debugwin_window_create(machine, "Disassembly", NULL);
- if (info == NULL || !debugwin_view_create(info, 0, DVT_DISASSEMBLY))
- return;
-
- // create the options menu
- optionsmenu = CreatePopupMenu();
- AppendMenu(optionsmenu, MF_ENABLED, ID_TOGGLE_BREAKPOINT, TEXT("Set breakpoint at cursor\tF9"));
- AppendMenu(optionsmenu, MF_ENABLED, ID_RUN_TO_CURSOR, TEXT("Run to cursor\tF4"));
- AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
- AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_RAW, TEXT("Raw opcodes\tCtrl+R"));
- AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_ENCRYPTED, TEXT("Encrypted opcodes\tCtrl+E"));
- AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_COMMENTS, TEXT("Comments\tCtrl+M"));
- AppendMenu(GetMenu(info->wnd), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
-
- // set the handlers
- info->handle_command = disasm_handle_command;
- info->handle_key = disasm_handle_key;
- info->update_menu = disasm_update_menu;
-
- // set up the view to track the initial expression
- downcast<debug_view_disasm *>(info->view[0].view)->set_expression("curpc");
- strcpy(info->edit_defstr, "curpc");
-
- // create an edit box and override its key handling
- info->editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), NULL, EDIT_BOX_STYLE,
- 0, 0, 100, 100, info->wnd, NULL, GetModuleHandle(NULL), NULL);
- info->original_editproc = (WNDPROC)(FPTR)GetWindowLongPtr(info->editwnd, GWLP_WNDPROC);
- SetWindowLongPtr(info->editwnd, GWLP_USERDATA, (LONG_PTR)info);
- SetWindowLongPtr(info->editwnd, GWLP_WNDPROC, (LONG_PTR)debugwin_edit_proc);
- SendMessage(info->editwnd, WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE);
- SendMessage(info->editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT("curpc"));
- SendMessage(info->editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0);
- SendMessage(info->editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
-
- // create a combo box
- info->otherwnd[0] = CreateWindowEx(COMBO_BOX_STYLE_EX, TEXT("COMBOBOX"), NULL, COMBO_BOX_STYLE,
- 0, 0, 100, 1000, info->wnd, NULL, GetModuleHandle(NULL), NULL);
- SetWindowLongPtr(info->otherwnd[0], GWLP_USERDATA, (LONG_PTR)info);
- SendMessage(info->otherwnd[0], WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE);
-
- // populate the combobox
- int maxlength = 0;
- for (const debug_view_source *source = info->view[0].view->first_source(); source != NULL; source = source->next())
- {
- int length = strlen(source->name());
- if (length > maxlength)
- maxlength = length;
- TCHAR *t_name = tstring_from_utf8(source->name());
- SendMessage(info->otherwnd[0], CB_ADDSTRING, 0, (LPARAM)t_name);
- osd_free(t_name);
- }
- const debug_view_source *source = info->view[0].view->source_for_device(curcpu);
- SendMessage(info->otherwnd[0], CB_SETCURSEL, info->view[0].view->source_list().indexof(*source), 0);
- SendMessage(info->otherwnd[0], CB_SETDROPPEDWIDTH, (maxlength + 2) * debug_font_width + vscroll_width, 0);
- info->view[0].view->set_source(*source);
-
- // set the child functions
- info->recompute_children = disasm_recompute_children;
- info->process_string = disasm_process_string;
-
- // set the caption
- disasm_update_caption(machine, info->wnd);
-
- // recompute the children once to get the maxwidth
- disasm_recompute_children(info);
-
- // position the window and recompute children again
- SetWindowPos(info->wnd, HWND_TOP, 100, 100, info->maxwidth, 200, SWP_SHOWWINDOW);
- disasm_recompute_children(info);
-
- // mark the edit box as the default focus and set it
- info->focuswnd = info->editwnd;
- SetFocus(info->editwnd);
-}
-
-
-
-//============================================================
-// disasm_recompute_children
-//============================================================
-
-static void disasm_recompute_children(debugwin_info *info)
-{
- debug_view_xy totalsize = info->view[0].view->total_size();
- RECT parent, dasmrect, editrect, comborect;
- RECT bounds;
- // compute a client rect
- bounds.top = bounds.left = 0;
- bounds.right = totalsize.x * debug_font_width + vscroll_width + 2 * EDGE_WIDTH;
- bounds.bottom = 200;
- AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
-
- // clamp the min/max size
- info->maxwidth = bounds.right - bounds.left;
-
- // get the parent's dimensions
- GetClientRect(info->wnd, &parent);
-
- // edit box gets half of the width
- editrect.top = parent.top + EDGE_WIDTH;
- editrect.bottom = editrect.top + debug_font_height + 4;
- editrect.left = parent.left + EDGE_WIDTH;
- editrect.right = parent.left + (parent.right - parent.left) / 2 - EDGE_WIDTH;
-
- // combo box gets the other half of the width
- comborect.top = editrect.top;
- comborect.bottom = editrect.bottom;
- comborect.left = editrect.right + 2 * EDGE_WIDTH;
- comborect.right = parent.right - EDGE_WIDTH;
-
- // disasm view gets the rest
- dasmrect.top = editrect.bottom + 2 * EDGE_WIDTH;
- dasmrect.bottom = parent.bottom - EDGE_WIDTH;
- dasmrect.left = parent.left + EDGE_WIDTH;
- dasmrect.right = parent.right - EDGE_WIDTH;
-
- // set the bounds of things
- debugwin_view_set_bounds(&info->view[0], info->wnd, &dasmrect);
- smart_set_window_bounds(info->editwnd, info->wnd, &editrect);
- smart_set_window_bounds(info->otherwnd[0], info->wnd, &comborect);
+ // return the result if we queried at least one switch
+ return result;
}
-
-//============================================================
-// disasm_process_string
-//============================================================
-
-static void disasm_process_string(debugwin_info *info, const char *string)
+void debugger_windows::remove_window(debugwin_info &info)
{
- // set the string to the disasm view
- downcast<debug_view_disasm *>(info->view[0].view)->set_expression(string);
-
- // select everything in the edit text box
- SendMessage(info->editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
-
- // update the default string to match
- strncpy(info->edit_defstr, string, sizeof(info->edit_defstr) - 1);
+ m_window_list.remove(info);
}
-
-//============================================================
-// disasm_update_menu
-//============================================================
-
-static void disasm_update_menu(debugwin_info *info)
+void debugger_windows::show_all()
{
- disasm_right_column rightcol = downcast<debug_view_disasm *>(info->view[0].view)->right_column();
- CheckMenuItem(GetMenu(info->wnd), ID_SHOW_RAW, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_RAW ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(GetMenu(info->wnd), ID_SHOW_ENCRYPTED, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_ENCRYPTED ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(GetMenu(info->wnd), ID_SHOW_COMMENTS, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_COMMENTS ? MF_CHECKED : MF_UNCHECKED));
+ for (debugwin_info *info = m_window_list.first(); info != NULL; info = info->next())
+ info->show();
}
-
-//============================================================
-// disasm_handle_command
-//============================================================
-
-static int disasm_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam)
+void debugger_windows::hide_all()
{
- debug_view_disasm *dasmview = downcast<debug_view_disasm *>(info->view[0].view);
- char command[64];
-
- switch (HIWORD(wparam))
- {
- // combo box selection changed
- case CBN_SELCHANGE:
- {
- int sel = SendMessage((HWND)lparam, CB_GETCURSEL, 0, 0);
- if (sel != CB_ERR)
- {
- dasmview->set_source(*dasmview->source_list().find(sel));
- disasm_update_caption(info->machine(), info->wnd);
-
- // reset the focus
- SetFocus(info->focuswnd);
- return 1;
- }
- break;
- }
-
- // menu selections
- case 0:
- switch (LOWORD(wparam))
- {
- case ID_SHOW_RAW:
- dasmview->set_right_column(DASM_RIGHTCOL_RAW);
- (*info->recompute_children)(info);
- return 1;
-
- case ID_SHOW_ENCRYPTED:
- dasmview->set_right_column(DASM_RIGHTCOL_ENCRYPTED);
- (*info->recompute_children)(info);
- return 1;
-
- case ID_SHOW_COMMENTS:
- dasmview->set_right_column(DASM_RIGHTCOL_COMMENTS);
- (*info->recompute_children)(info);
- return 1;
-
- case ID_RUN_TO_CURSOR:
- if (dasmview->cursor_visible() && debug_cpu_get_visible_cpu(info->machine()) == dasmview->source()->device())
- {
- offs_t address = dasmview->selected_address();
- sprintf(command, "go 0x%X", address);
- debug_console_execute_command(info->machine(), command, 1);
- }
- return 1;
-
- case ID_TOGGLE_BREAKPOINT:
- if (dasmview->cursor_visible() && debug_cpu_get_visible_cpu(info->machine()) == dasmview->source()->device())
- {
- offs_t address = dasmview->selected_address();
- device_debug *debug = dasmview->source()->device()->debug();
- INT32 bpindex = -1;
-
- /* first find an existing breakpoint at this address */
- for (device_debug::breakpoint *bp = debug->breakpoint_first(); bp != NULL; bp = bp->next())
- if (address == bp->address())
- {
- bpindex = bp->index();
- break;
- }
-
- /* if it doesn't exist, add a new one */
- if (bpindex == -1)
- sprintf(command, "bpset 0x%X", address);
- else
- sprintf(command, "bpclear 0x%X", bpindex);
- debug_console_execute_command(info->machine(), command, 1);
- }
- return 1;
- }
- break;
- }
- return global_handle_command(info, wparam, lparam);
+ SetForegroundWindow(win_window_list->m_hwnd);
+ for (debugwin_info *info = m_window_list.first(); info != NULL; info = info->next())
+ info->hide();
}
-
-//============================================================
-// disasm_handle_key
-//============================================================
-
-static int disasm_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam)
+template <typename T> T *debugger_windows::create_window()
{
- if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
- {
- switch (wparam)
- {
- case 'R':
- SendMessage(info->wnd, WM_COMMAND, ID_SHOW_RAW, 0);
- return 1;
-
- case 'E':
- SendMessage(info->wnd, WM_COMMAND, ID_SHOW_ENCRYPTED, 0);
- return 1;
-
- case 'N':
- SendMessage(info->wnd, WM_COMMAND, ID_SHOW_COMMENTS, 0);
- return 1;
- }
- }
-
- switch (wparam)
- {
- /* ajg - steals the F4 from the global key handler - but ALT+F4 didn't work anyways ;) */
- case VK_F4:
- SendMessage(info->wnd, WM_COMMAND, ID_RUN_TO_CURSOR, 0);
- return 1;
-
- case VK_F9:
- SendMessage(info->wnd, WM_COMMAND, ID_TOGGLE_BREAKPOINT, 0);
- return 1;
-
- case VK_RETURN:
- if (info->view[0].view->cursor_visible())
- {
- SendMessage(info->wnd, WM_COMMAND, ID_STEP, 0);
- return 1;
- }
- break;
- }
-
- return global_handle_key(info, wparam, lparam);
-}
-
-
-
-//============================================================
-// disasm_update_caption
-//============================================================
-
-static void disasm_update_caption(running_machine &machine, HWND wnd)
-{
- debugwin_info *info = (debugwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
- astring title;
-
- title.printf("Disassembly: %s", info->view[0].view->source()->name());
- win_set_window_text_utf8(wnd, title);
-}
-
-
-enum
-{
- DEVOPTION_OPEN,
- DEVOPTION_CREATE,
- DEVOPTION_CLOSE,
- DEVOPTION_CASSETTE_STOPPAUSE,
- DEVOPTION_CASSETTE_PLAY,
- DEVOPTION_CASSETTE_RECORD,
- DEVOPTION_CASSETTE_REWIND,
- DEVOPTION_CASSETTE_FASTFORWARD,
- DEVOPTION_MAX
-};
-
-//============================================================
-// memory_update_menu
-//============================================================
-
-static void image_update_menu(debugwin_info *info)
-{
- UINT32 cnt = 0;
- HMENU devicesmenu;
-
- DeleteMenu(GetMenu(info->wnd), 2, MF_BYPOSITION);
-
- // create the image menu
- devicesmenu = CreatePopupMenu();
- image_interface_iterator iter(info->machine().root_device());
- for (device_image_interface *img = iter.first(); img != NULL; img = iter.next())
- {
- astring temp;
- UINT flags_for_exists;
- UINT flags_for_writing;
- HMENU devicesubmenu = CreatePopupMenu();
-
- UINT_PTR new_item = ID_DEVICE_OPTIONS + (cnt * DEVOPTION_MAX);
-
- flags_for_exists = MF_ENABLED | MF_STRING;
-
- if (!img->exists())
- flags_for_exists |= MF_GRAYED;
-
- flags_for_writing = flags_for_exists;
- if (img->is_readonly())
- flags_for_writing |= MF_GRAYED;
-
- AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_OPEN, TEXT("Mount..."));
-
- /*if (img->is_creatable())
- AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_CREATE, TEXT("Create..."));
- */
- AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CLOSE, TEXT("Unmount"));
-
- if (img->device().type() == CASSETTE)
- {
- cassette_state state;
- state = (cassette_state)(img->exists() ? (dynamic_cast<cassette_image_device*>(&img->device())->get_state() & CASSETTE_MASK_UISTATE) : CASSETTE_STOPPED);
- AppendMenu(devicesubmenu, MF_SEPARATOR, 0, NULL);
- 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"));
- AppendMenu(devicesubmenu, flags_for_writing | ((state == CASSETTE_RECORD) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_RECORD, TEXT("Record"));
- AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CASSETTE_REWIND, TEXT("Rewind"));
- AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CASSETTE_FASTFORWARD, TEXT("Fast Forward"));
- }
-
- temp.format("%s :%s", img->device().name(), img->exists() ? img->filename() : "[empty slot]");
-
- AppendMenu(devicesmenu, MF_ENABLED | MF_POPUP, (UINT_PTR)devicesubmenu, tstring_from_utf8(temp.cstr()));
-
- cnt++;
- }
- AppendMenu(GetMenu(info->wnd), MF_ENABLED | MF_POPUP, (UINT_PTR)devicesmenu, TEXT("Images"));
-
-}
-
-//============================================================
-// console_create_window
-//============================================================
-
-void console_create_window(running_machine &machine)
-{
- debugwin_info *info;
- int bestwidth, bestheight;
- RECT bounds, work_bounds;
- HMENU optionsmenu;
- UINT32 conchars;
-
- // create the window
- info = debugwin_window_create(machine, "Debug", NULL);
- if (info == NULL)
- return;
- main_console = info;
-
- // create the views
- if (!debugwin_view_create(info, 0, DVT_DISASSEMBLY))
- goto cleanup;
- if (!debugwin_view_create(info, 1, DVT_STATE))
- goto cleanup;
- if (!debugwin_view_create(info, 2, DVT_CONSOLE))
- goto cleanup;
-
- // create the options menu
- optionsmenu = CreatePopupMenu();
- AppendMenu(optionsmenu, MF_ENABLED, ID_TOGGLE_BREAKPOINT, TEXT("Set breakpoint at cursor\tF9"));
- AppendMenu(optionsmenu, MF_ENABLED, ID_RUN_TO_CURSOR, TEXT("Run to cursor\tF4"));
- AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
- AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_RAW, TEXT("Raw opcodes\tCtrl+R"));
- AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_ENCRYPTED, TEXT("Encrypted opcodes\tCtrl+E"));
- AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_COMMENTS, TEXT("Comments\tCtrl+N"));
- AppendMenu(GetMenu(info->wnd), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
-
- // Add image menu only if image devices exist
- {
- image_interface_iterator iter(machine.root_device());
- if (iter.first() != NULL) {
- info->update_menu = image_update_menu;
- image_update_menu(info);
- }
- }
-
- // set the handlers
- info->handle_command = disasm_handle_command;
- info->handle_key = disasm_handle_key;
-
- // create an edit box and override its key handling
- info->editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), NULL, EDIT_BOX_STYLE,
- 0, 0, 100, 100, info->wnd, NULL, GetModuleHandle(NULL), NULL);
- info->original_editproc = (WNDPROC)(FPTR)GetWindowLongPtr(info->editwnd, GWLP_WNDPROC);
- SetWindowLongPtr(info->editwnd, GWLP_USERDATA, (LONG_PTR)info);
- SetWindowLongPtr(info->editwnd, GWLP_WNDPROC, (LONG_PTR)debugwin_edit_proc);
- SendMessage(info->editwnd, WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE);
- SendMessage(info->editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0);
-
- // set the child functions
- info->recompute_children = console_recompute_children;
- info->process_string = console_process_string;
-
- // loop over all register views and get the maximum size
- main_console_regwidth = 0;
- for (const debug_view_source *source = info->view[1].view->first_source(); source != NULL; source = source->next())
- {
- UINT32 regchars;
-
- // set the view and fetch the width
- info->view[1].view->set_source(*source);
- regchars = info->view[1].view->total_size().x;
-
- // track the maximum
- main_console_regwidth = MAX(regchars, main_console_regwidth);
- }
-
- // determine the width of the console (this is fixed)
- conchars = info->view[2].view->total_size().x;
-
- // loop over all CPUs and compute the width range based on dasm width
- info->minwidth = 0;
- info->maxwidth = 0;
- for (const debug_view_source *source = info->view[0].view->first_source(); source != NULL; source = source->next())
+ // allocate memory
+ T *info = global_alloc(T(*this));
+ if (info->is_valid())
{
- UINT32 minwidth, maxwidth, dischars;
-
- // set the view and fetch the width
- info->view[0].view->set_source(*source);
- dischars = info->view[0].view->total_size().x;
-
- // compute the preferred width
- minwidth = EDGE_WIDTH + main_console_regwidth * debug_font_width + vscroll_width + 2 * EDGE_WIDTH + 100 + EDGE_WIDTH;
- maxwidth = EDGE_WIDTH + main_console_regwidth * debug_font_width + vscroll_width + 2 * EDGE_WIDTH + MAX(dischars, conchars) * debug_font_width + vscroll_width + EDGE_WIDTH;
- info->minwidth = MAX(info->minwidth, minwidth);
- info->maxwidth = MAX(info->maxwidth, maxwidth);
+ m_window_list.prepend(*info);
+ return info;
}
-
- // get the work bounds
- SystemParametersInfo(SPI_GETWORKAREA, 0, &work_bounds, 0);
-
- // adjust the min/max sizes for the window style
- bounds.top = bounds.left = 0;
- bounds.right = bounds.bottom = info->minwidth;
- AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
- info->minwidth = bounds.right - bounds.left;
-
- bounds.top = bounds.left = 0;
- bounds.right = bounds.bottom = info->maxwidth;
- AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
- info->maxwidth = bounds.right - bounds.left;
-
- // position the window at the bottom-right
- bestwidth = (info->maxwidth < (work_bounds.right - work_bounds.left)) ? info->maxwidth : (work_bounds.right - work_bounds.left);
- bestheight = (500 < (work_bounds.bottom - work_bounds.top)) ? 500 : (work_bounds.bottom - work_bounds.top);
- SetWindowPos(info->wnd, HWND_TOP,
- work_bounds.right - bestwidth, work_bounds.bottom - bestheight,
- bestwidth, bestheight,
- SWP_SHOWWINDOW);
-
- // recompute the children
- console_set_cpu(debug_cpu_get_visible_cpu(machine));
-
- // set up the disassembly view to track the current pc
- downcast<debug_view_disasm *>(info->view[0].view)->set_expression("curpc");
-
- // mark the edit box as the default focus and set it
- info->focuswnd = info->editwnd;
- SetFocus(info->editwnd);
- return;
-
-cleanup:
- if (info->view[2].view)
- machine.debug_view().free_view(*info->view[2].view);
- if (info->view[1].view)
- machine.debug_view().free_view(*info->view[1].view);
- if (info->view[0].view)
- machine.debug_view().free_view(*info->view[0].view);
-}
-
-
-
-//============================================================
-// console_recompute_children
-//============================================================
-
-static void console_recompute_children(debugwin_info *info)
-{
- RECT parent, regrect, disrect, conrect, editrect;
- UINT32 regchars;//, dischars, conchars;
-
- // get the parent's dimensions
- GetClientRect(info->wnd, &parent);
-
- // get the total width of all three children
- //dischars = info->view[0].view->total_size().x;
- regchars = main_console_regwidth;
- //conchars = info->view[2].view->total_size().x;
-
- // registers always get their desired width, and span the entire height
- regrect.top = parent.top + EDGE_WIDTH;
- regrect.bottom = parent.bottom - EDGE_WIDTH;
- regrect.left = parent.left + EDGE_WIDTH;
- regrect.right = regrect.left + debug_font_width * regchars + vscroll_width;
-
- // edit box goes at the bottom of the remaining area
- editrect.bottom = parent.bottom - EDGE_WIDTH;
- editrect.top = editrect.bottom - debug_font_height - 4;
- editrect.left = regrect.right + EDGE_WIDTH * 2;
- editrect.right = parent.right - EDGE_WIDTH;
-
- // console and disassembly split the difference
- disrect.top = parent.top + EDGE_WIDTH;
- disrect.bottom = (editrect.top - parent.top) / 2 - EDGE_WIDTH;
- disrect.left = regrect.right + EDGE_WIDTH * 2;
- disrect.right = parent.right - EDGE_WIDTH;
-
- conrect.top = disrect.bottom + EDGE_WIDTH * 2;
- conrect.bottom = editrect.top - EDGE_WIDTH;
- conrect.left = regrect.right + EDGE_WIDTH * 2;
- conrect.right = parent.right - EDGE_WIDTH;
-
- // set the bounds of things
- debugwin_view_set_bounds(&info->view[0], info->wnd, &disrect);
- debugwin_view_set_bounds(&info->view[1], info->wnd, &regrect);
- debugwin_view_set_bounds(&info->view[2], info->wnd, &conrect);
- smart_set_window_bounds(info->editwnd, info->wnd, &editrect);
-}
-
-
-
-//============================================================
-// console_process_string
-//============================================================
-
-static void console_process_string(debugwin_info *info, const char *string)
-{
- TCHAR buffer = 0;
-
- // an empty string is a single step
- if (string[0] == 0)
- debug_cpu_get_visible_cpu(info->machine())->debug()->single_step();
-
- // otherwise, just process the command
else
- debug_console_execute_command(info->machine(), string, 1);
-
- // clear the edit text box
- SendMessage(info->editwnd, WM_SETTEXT, 0, (LPARAM)&buffer);
-}
-
-
-
-//============================================================
-// console_set_cpu
-//============================================================
-
-static void console_set_cpu(device_t *device)
-{
- // first set all the views to the new cpu number
- main_console->view[0].view->set_source(*main_console->view[0].view->source_for_device(device));
- main_console->view[1].view->set_source(*main_console->view[1].view->source_for_device(device));
-
- // then update the caption
- char curtitle[256];
- astring title;
-
- title.printf("Debug: %s - %s '%s'", device->machine().system().name, device->name(), device->tag());
- win_get_window_text_utf8(main_console->wnd, curtitle, ARRAY_LENGTH(curtitle));
- if (title.cmp(curtitle) != 0)
- win_set_window_text_utf8(main_console->wnd, title);
-
- // and recompute the children
- console_recompute_children(main_console);
-}
-
-
-
-//============================================================
-// create_standard_menubar
-//============================================================
-
-static HMENU create_standard_menubar(void)
-{
- HMENU menubar, debugmenu;
-
- // create the debug menu
- debugmenu = CreatePopupMenu();
- if (debugmenu == NULL)
- return NULL;
- AppendMenu(debugmenu, MF_ENABLED, ID_NEW_MEMORY_WND, TEXT("New Memory Window\tCtrl+M"));
- AppendMenu(debugmenu, MF_ENABLED, ID_NEW_DISASM_WND, TEXT("New Disassembly Window\tCtrl+D"));
- AppendMenu(debugmenu, MF_ENABLED, ID_NEW_LOG_WND, TEXT("New Error Log Window\tCtrl+L"));
- AppendMenu(debugmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
- AppendMenu(debugmenu, MF_ENABLED, ID_RUN, TEXT("Run\tF5"));
- AppendMenu(debugmenu, MF_ENABLED, ID_RUN_AND_HIDE, TEXT("Run and Hide Debugger\tF12"));
- AppendMenu(debugmenu, MF_ENABLED, ID_NEXT_CPU, TEXT("Run to Next CPU\tF6"));
- AppendMenu(debugmenu, MF_ENABLED, ID_RUN_IRQ, TEXT("Run until Next Interrupt on This CPU\tF7"));
- AppendMenu(debugmenu, MF_ENABLED, ID_RUN_VBLANK, TEXT("Run until Next VBLANK\tF8"));
- AppendMenu(debugmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
- AppendMenu(debugmenu, MF_ENABLED, ID_STEP, TEXT("Step Into\tF11"));
- AppendMenu(debugmenu, MF_ENABLED, ID_STEP_OVER, TEXT("Step Over\tF10"));
- AppendMenu(debugmenu, MF_ENABLED, ID_STEP_OUT, TEXT("Step Out\tShift+F11"));
- AppendMenu(debugmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
- AppendMenu(debugmenu, MF_ENABLED, ID_SOFT_RESET, TEXT("Soft Reset\tF3"));
- AppendMenu(debugmenu, MF_ENABLED, ID_HARD_RESET, TEXT("Hard Reset\tShift+F3"));
- AppendMenu(debugmenu, MF_ENABLED, ID_EXIT, TEXT("Exit"));
-
- // create the menu bar
- menubar = CreateMenu();
- if (menubar == NULL)
{
- DestroyMenu(debugmenu);
+ global_free(info);
return NULL;
}
- AppendMenu(menubar, MF_ENABLED | MF_POPUP, (UINT_PTR)debugmenu, TEXT("Debug"));
-
- return menubar;
-}
-
-//============================================================
-// copy_extension_list
-//============================================================
-
-static int copy_extension_list(char *dest, size_t dest_len, const char *extensions)
-{
- const char *s;
- int pos = 0;
-
- // our extension lists are comma delimited; Win32 expects to see lists
- // delimited by semicolons
- s = extensions;
- while(*s)
- {
- // append a semicolon if not at the beginning
- if (s != extensions)
- pos += snprintf(&dest[pos], dest_len - pos, ";");
-
- // append ".*"
- pos += snprintf(&dest[pos], dest_len - pos, "*.");
-
- // append the file extension
- while(*s && (*s != ','))
- {
- pos += snprintf(&dest[pos], dest_len - pos, "%c", *s);
- s++;
- }
-
- // if we found a comma, advance
- while(*s == ',')
- s++;
- }
- return pos;
-}
-
-//============================================================
-// add_filter_entry
-//============================================================
-
-static int add_filter_entry(char *dest, size_t dest_len, const char *description, const char *extensions)
-{
- int pos = 0;
-
- // add the description
- pos += snprintf(&dest[pos], dest_len - pos, "%s (", description);
-
- // add the extensions to the description
- pos += copy_extension_list(&dest[pos], dest_len - pos, extensions);
-
- // add the trailing rparen and '|' character
- pos += snprintf(&dest[pos], dest_len - pos, ")|");
-
- // now add the extension list itself
- pos += copy_extension_list(&dest[pos], dest_len - pos, extensions);
-
- // append a '|'
- pos += snprintf(&dest[pos], dest_len - pos, "|");
-
- return pos;
-}
-//============================================================
-// build_generic_filter
-//============================================================
-
-static void build_generic_filter(device_image_interface *img, int is_save, char *filter, size_t filter_len)
-{
- char *s;
-
- const char *file_extension;
-
- /* copy the string */
- file_extension = img->file_extensions();
-
- // start writing the filter
- s = filter;
-
- // common image types
- s += add_filter_entry(filter, filter_len, "Common image types", file_extension);
-
- // all files
- s += sprintf(s, "All files (*.*)|*.*|");
-
- // compressed
- if (!is_save)
- s += sprintf(s, "Compressed Images (*.zip)|*.zip|");
-
- *(s++) = '\0';
-}
-
-//============================================================
-// global_handle_command
-//============================================================
-
-static int global_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam)
-{
- if (HIWORD(wparam) == 0)
- switch (LOWORD(wparam))
- {
- case ID_NEW_MEMORY_WND:
- memory_create_window(info->machine());
- return 1;
-
- case ID_NEW_DISASM_WND:
- disasm_create_window(info->machine());
- return 1;
-
- case ID_NEW_LOG_WND:
- log_create_window(info->machine());
- return 1;
-
- case ID_RUN_AND_HIDE:
- smart_show_all(FALSE);
- case ID_RUN:
- debug_cpu_get_visible_cpu(info->machine())->debug()->go();
- return 1;
-
- case ID_NEXT_CPU:
- debug_cpu_get_visible_cpu(info->machine())->debug()->go_next_device();
- return 1;
-
- case ID_RUN_VBLANK:
- debug_cpu_get_visible_cpu(info->machine())->debug()->go_vblank();
- return 1;
-
- case ID_RUN_IRQ:
- debug_cpu_get_visible_cpu(info->machine())->debug()->go_interrupt();
- return 1;
-
- case ID_STEP:
- debug_cpu_get_visible_cpu(info->machine())->debug()->single_step();
- return 1;
-
- case ID_STEP_OVER:
- debug_cpu_get_visible_cpu(info->machine())->debug()->single_step_over();
- return 1;
-
- case ID_STEP_OUT:
- debug_cpu_get_visible_cpu(info->machine())->debug()->single_step_out();
- return 1;
-
- case ID_HARD_RESET:
- info->machine().schedule_hard_reset();
- return 1;
-
- case ID_SOFT_RESET:
- info->machine().schedule_soft_reset();
- debug_cpu_get_visible_cpu(info->machine())->debug()->go();
- return 1;
-
- case ID_EXIT:
- if (info->focuswnd != NULL)
- SetFocus(info->focuswnd);
- info->machine().schedule_exit();
- return 1;
- }
- if (LOWORD(wparam) >= ID_DEVICE_OPTIONS) {
- UINT32 devid = (LOWORD(wparam) - ID_DEVICE_OPTIONS) / DEVOPTION_MAX;
- image_interface_iterator iter(info->machine().root_device());
- device_image_interface *img = iter.byindex(devid);
- if (img!=NULL) {
- switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX)
- {
- case DEVOPTION_OPEN :
- {
- char filter[2048];
- build_generic_filter(img, FALSE, filter, ARRAY_LENGTH(filter));
-
- TCHAR selectedFilename[MAX_PATH];
- selectedFilename[0] = '\0';
- LPTSTR buffer;
- LPTSTR t_filter = NULL;
-
- buffer = tstring_from_utf8(filter);
-
- // convert a pipe-char delimited string into a NUL delimited string
- t_filter = (LPTSTR) alloca((_tcslen(buffer) + 2) * sizeof(*t_filter));
- int i = 0;
- for (i = 0; buffer[i] != '\0'; i++)
- t_filter[i] = (buffer[i] != '|') ? buffer[i] : '\0';
- t_filter[i++] = '\0';
- t_filter[i++] = '\0';
- osd_free(buffer);
-
-
- OPENFILENAME ofn;
- memset(&ofn,0,sizeof(ofn));
- ofn.lStructSize = sizeof(ofn);
- ofn.hwndOwner = NULL;
- ofn.lpstrFile = selectedFilename;
- ofn.lpstrFile[0] = '\0';
- ofn.nMaxFile = MAX_PATH;
- ofn.lpstrFilter = t_filter;
- ofn.nFilterIndex = 1;
- ofn.lpstrFileTitle = NULL;
- ofn.nMaxFileTitle = 0;
- ofn.lpstrInitialDir = NULL;
- ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
-
- if (GetOpenFileName(&ofn)) {
- img->load(utf8_from_tstring(selectedFilename));
- }
- }
- return 1;
-/* case DEVOPTION_CREATE:
- return 1;*/
- case DEVOPTION_CLOSE:
- img->unload();
- return 1;
- default:
- if (img->device().type() == CASSETTE) {
- cassette_image_device* cassette = dynamic_cast<cassette_image_device*>(&img->device());
- switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX)
- {
- case DEVOPTION_CASSETTE_STOPPAUSE:
- cassette->change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE);
- return 1;
- case DEVOPTION_CASSETTE_PLAY:
- cassette->change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE);
- return 1;
- case DEVOPTION_CASSETTE_RECORD:
- cassette->change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE);
- return 1;
- case DEVOPTION_CASSETTE_REWIND:
- cassette->seek(-60.0, SEEK_CUR);
- return 1;
- case DEVOPTION_CASSETTE_FASTFORWARD:
- cassette->seek(+60.0, SEEK_CUR);
- return 1;
- }
- }
- }
- }
- }
- return 0;
-}
-
-
-
-//============================================================
-// global_handle_key
-//============================================================
-
-static int global_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam)
-{
- /* ignore any keys that are received while the debug key is down */
- if (!waiting_for_debugger && debugwin_seq_pressed(info->machine()))
- return 1;
-
- switch (wparam)
- {
- case VK_F3:
- if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
- SendMessage(info->wnd, WM_COMMAND, ID_HARD_RESET, 0);
- else
- SendMessage(info->wnd, WM_COMMAND, ID_SOFT_RESET, 0);
- return 1;
-
- case VK_F4:
- if (GetAsyncKeyState(VK_MENU) & 0x8000)
- {
- /* ajg - never gets here since 'alt' seems to be captured somewhere else - menu maybe? */
- SendMessage(info->wnd, WM_COMMAND, ID_EXIT, 0);
- return 1;
- }
- break;
-
- case VK_F5:
- SendMessage(info->wnd, WM_COMMAND, ID_RUN, 0);
- return 1;
-
- case VK_F6:
- SendMessage(info->wnd, WM_COMMAND, ID_NEXT_CPU, 0);
- return 1;
-
- case VK_F7:
- SendMessage(info->wnd, WM_COMMAND, ID_RUN_IRQ, 0);
- return 1;
-
- case VK_F8:
- SendMessage(info->wnd, WM_COMMAND, ID_RUN_VBLANK, 0);
- return 1;
-
- case VK_F10:
- SendMessage(info->wnd, WM_COMMAND, ID_STEP_OVER, 0);
- return 1;
-
- case VK_F11:
- if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
- SendMessage(info->wnd, WM_COMMAND, ID_STEP_OUT, 0);
- else
- SendMessage(info->wnd, WM_COMMAND, ID_STEP, 0);
- return 1;
-
- case VK_F12:
- SendMessage(info->wnd, WM_COMMAND, ID_RUN_AND_HIDE, 0);
- return 1;
-
- case 'M':
- if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
- {
- SendMessage(info->wnd, WM_COMMAND, ID_NEW_MEMORY_WND, 0);
- return 1;
- }
- break;
-
- case 'D':
- if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
- {
- SendMessage(info->wnd, WM_COMMAND, ID_NEW_DISASM_WND, 0);
- return 1;
- }
- break;
-
- case 'L':
- if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
- {
- SendMessage(info->wnd, WM_COMMAND, ID_NEW_LOG_WND, 0);
- return 1;
- }
- break;
- }
-
- return 0;
-}
-
-
-
-//============================================================
-// smart_set_window_bounds
-//============================================================
-
-static void smart_set_window_bounds(HWND wnd, HWND parent, RECT *bounds)
-{
- RECT curbounds;
- int flags = 0;
-
- // first get the current bounds, relative to the parent
- GetWindowRect(wnd, &curbounds);
- if (parent != NULL)
- {
- RECT parentbounds;
- GetWindowRect(parent, &parentbounds);
- curbounds.top -= parentbounds.top;
- curbounds.bottom -= parentbounds.top;
- curbounds.left -= parentbounds.left;
- curbounds.right -= parentbounds.left;
- }
-
- // if the position matches, don't change it
- if (curbounds.top == bounds->top && curbounds.left == bounds->left)
- flags |= SWP_NOMOVE;
- if ((curbounds.bottom - curbounds.top) == (bounds->bottom - bounds->top) &&
- (curbounds.right - curbounds.left) == (bounds->right - bounds->left))
- flags |= SWP_NOSIZE;
-
- // if we need to, reposition the window
- if (flags != (SWP_NOMOVE | SWP_NOSIZE))
- SetWindowPos(wnd, NULL,
- bounds->left, bounds->top,
- bounds->right - bounds->left, bounds->bottom - bounds->top,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | flags);
}
-
-//============================================================
-// smart_show_window
-//============================================================
-
-static void smart_show_window(HWND wnd, BOOL show)
-{
- BOOL visible = IsWindowVisible(wnd);
- if ((visible && !show) || (!visible && show))
- ShowWindow(wnd, show ? SW_SHOW : SW_HIDE);
-}
-
-
-
-//============================================================
-// smart_show_all
-//============================================================
-
-static void smart_show_all(BOOL show)
-{
- debugwin_info *info;
- if (!show)
- SetForegroundWindow(win_window_list->m_hwnd);
- for (info = window_list; info != NULL; info = info->next)
- smart_show_window(info->wnd, show);
-}
#else /* not windows */
- MODULE_NOT_SUPPORTED(debugger_windows, OSD_DEBUG_PROVIDER, "windows")
+MODULE_NOT_SUPPORTED(debugger_windows, OSD_DEBUG_PROVIDER, "windows")
#endif
MODULE_DEFINITION(DEBUG_WINDOWS, debugger_windows)
diff --git a/src/osd/modules/debugger/osx/debugview.m b/src/osd/modules/debugger/osx/debugview.m
index dbe0bc271a8..92e483bc606 100644
--- a/src/osd/modules/debugger/osx/debugview.m
+++ b/src/osd/modules/debugger/osx/debugview.m
@@ -540,7 +540,6 @@ static void debugwin_view_update(debug_view &view, void *osdprivate)
: (modifiers & NSAlternateKeyMask) ? DCK_MIDDLE_CLICK
: DCK_LEFT_CLICK,
[self convertLocation:location]);
- [self setNeedsDisplay:YES];
}
diff --git a/src/osd/modules/debugger/win/consolewininfo.c b/src/osd/modules/debugger/win/consolewininfo.c
new file mode 100644
index 00000000000..771f2d604ce
--- /dev/null
+++ b/src/osd/modules/debugger/win/consolewininfo.c
@@ -0,0 +1,373 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// consolewininfo.c - Win32 debug window handling
+//
+//============================================================
+
+#include "consolewininfo.h"
+
+#include "debugviewinfo.h"
+#include "disasmviewinfo.h"
+#include "uimetrics.h"
+
+#include "debug/debugcon.h"
+#include "debug/debugcpu.h"
+#include "imagedev/cassette.h"
+
+#include "strconv.h"
+#include "winutf8.h"
+
+
+consolewin_info::consolewin_info(debugger_windows_interface &debugger) :
+ disasmbasewin_info(debugger, true, "Debug", NULL),
+ m_devices_menu(NULL)
+{
+ if ((window() == NULL) || (m_views[0] == NULL))
+ goto cleanup;
+
+ // create the views
+ m_views[1].reset(global_alloc(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)));
+ if (!m_views[2]->is_valid())
+ goto cleanup;
+
+ {
+ // Add image menu only if image devices exist
+ image_interface_iterator iter(machine().root_device());
+ device_image_interface *img = iter.first();
+ if (img != NULL)
+ {
+ m_devices_menu = CreatePopupMenu();
+ for ( ; img != NULL; img = iter.next())
+ {
+ astring temp;
+ temp.format("%s : %s", img->device().name(), img->exists() ? img->filename() : "[no image]");
+ TCHAR *tc_buf = tstring_from_utf8(temp);
+ if (tc_buf != NULL)
+ {
+ AppendMenu(m_devices_menu, MF_ENABLED, 0, tc_buf);
+ osd_free(tc_buf);
+ }
+ }
+ AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)m_devices_menu, TEXT("Images"));
+ }
+
+ // get the work bounds
+ RECT work_bounds, bounds;
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &work_bounds, 0);
+
+ // adjust the min/max sizes for the window style
+ bounds.top = bounds.left = 0;
+ bounds.right = bounds.bottom = EDGE_WIDTH + m_views[1]->maxwidth() + (2 * EDGE_WIDTH) + 100 + EDGE_WIDTH;
+ AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
+ set_minwidth(bounds.right - bounds.left);
+
+ bounds.top = bounds.left = 0;
+ bounds.right = bounds.bottom = EDGE_WIDTH + m_views[1]->maxwidth() + (2 * EDGE_WIDTH) + MAX(m_views[0]->maxwidth(), m_views[2]->maxwidth()) + EDGE_WIDTH;
+ AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
+ set_maxwidth(bounds.right - bounds.left);
+
+ // position the window at the bottom-right
+ int const bestwidth = MIN(maxwidth(), work_bounds.right - work_bounds.left);
+ int const bestheight = MIN(500, work_bounds.bottom - work_bounds.top);
+ SetWindowPos(window(), HWND_TOP,
+ work_bounds.right - bestwidth, work_bounds.bottom - bestheight,
+ bestwidth, bestheight,
+ SWP_SHOWWINDOW);
+ }
+
+ // recompute the children
+ set_cpu(*debug_cpu_get_visible_cpu(machine()));
+
+ // mark the edit box as the default focus and set it
+ set_default_focus();
+ return;
+
+cleanup:
+ m_views[2].reset();
+ m_views[1].reset();
+ m_views[0].reset();
+}
+
+
+consolewin_info::~consolewin_info()
+{
+}
+
+
+void consolewin_info::set_cpu(device_t &device)
+{
+ // first set all the views to the new cpu number
+ m_views[0]->set_source_for_device(device);
+ m_views[1]->set_source_for_device(device);
+
+ // then update the caption
+ char curtitle[256];
+ astring title;
+
+ title.printf("Debug: %s - %s '%s'", device.machine().system().name, device.name(), device.tag());
+ win_get_window_text_utf8(window(), curtitle, ARRAY_LENGTH(curtitle));
+ if (title.cmp(curtitle) != 0)
+ win_set_window_text_utf8(window(), title);
+
+ // and recompute the children
+ recompute_children();
+}
+
+
+void consolewin_info::recompute_children()
+{
+ // get the parent's dimensions
+ RECT parent;
+ GetClientRect(window(), &parent);
+
+ // registers always get their desired width, and span the entire height
+ RECT regrect;
+ regrect.top = parent.top + EDGE_WIDTH;
+ regrect.bottom = parent.bottom - EDGE_WIDTH;
+ regrect.left = parent.left + EDGE_WIDTH;
+ regrect.right = regrect.left + m_views[1]->maxwidth();
+
+ // edit box goes at the bottom of the remaining area
+ RECT editrect;
+ editrect.bottom = parent.bottom - EDGE_WIDTH;
+ editrect.top = editrect.bottom - metrics().debug_font_height() - 4;
+ editrect.left = regrect.right + (EDGE_WIDTH * 2);
+ editrect.right = parent.right - EDGE_WIDTH;
+
+ // console and disassembly split the difference
+ RECT disrect;
+ disrect.top = parent.top + EDGE_WIDTH;
+ disrect.bottom = ((editrect.top - parent.top) / 2) - EDGE_WIDTH;
+ disrect.left = regrect.right + (EDGE_WIDTH * 2);
+ disrect.right = parent.right - EDGE_WIDTH;
+
+ RECT conrect;
+ conrect.top = disrect.bottom + (EDGE_WIDTH * 2);
+ conrect.bottom = editrect.top - EDGE_WIDTH;
+ conrect.left = regrect.right + (EDGE_WIDTH * 2);
+ conrect.right = parent.right - EDGE_WIDTH;
+
+ // set the bounds of things
+ m_views[0]->set_bounds(disrect);
+ m_views[1]->set_bounds(regrect);
+ m_views[2]->set_bounds(conrect);
+ set_editwnd_bounds(editrect);
+}
+
+
+void consolewin_info::update_menu()
+{
+ disasmbasewin_info::update_menu();
+
+ if (m_devices_menu != NULL)
+ {
+ // create the image menu
+ image_interface_iterator iter(machine().root_device());
+ device_image_interface *img;
+ UINT32 cnt;
+ for (img = iter.first(), cnt = 0; img != NULL; img = iter.next(), cnt++)
+ {
+ HMENU const devicesubmenu = CreatePopupMenu();
+
+ UINT_PTR const new_item = ID_DEVICE_OPTIONS + (cnt * DEVOPTION_MAX);
+
+ UINT flags_for_exists = MF_ENABLED | MF_STRING;
+ if (!img->exists())
+ flags_for_exists |= MF_GRAYED;
+
+ UINT flags_for_writing = flags_for_exists;
+ if (img->is_readonly())
+ flags_for_writing |= MF_GRAYED;
+
+ AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_OPEN, TEXT("Mount..."));
+
+ //if (img->is_creatable())
+ //AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_CREATE, TEXT("Create..."));
+ AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CLOSE, TEXT("Unmount"));
+
+ if (img->device().type() == CASSETTE)
+ {
+ cassette_state const state = (cassette_state)(img->exists() ? (downcast<cassette_image_device *>(&img->device())->get_state() & CASSETTE_MASK_UISTATE) : CASSETTE_STOPPED);
+ AppendMenu(devicesubmenu, MF_SEPARATOR, 0, NULL);
+ 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"));
+ AppendMenu(devicesubmenu, flags_for_writing | ((state == CASSETTE_RECORD) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_RECORD, TEXT("Record"));
+ AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CASSETTE_REWIND, TEXT("Rewind"));
+ AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CASSETTE_FASTFORWARD, TEXT("Fast Forward"));
+ }
+
+ astring temp;
+ temp.format("%s :%s", img->device().name(), img->exists() ? img->filename() : "[empty slot]");
+ TCHAR *tc_buf = tstring_from_utf8(temp);
+ if (tc_buf != NULL)
+ {
+ ModifyMenu(m_devices_menu, cnt, MF_BYPOSITION | MF_POPUP, (UINT_PTR)devicesubmenu, tc_buf);
+ osd_free(tc_buf);
+ }
+ }
+ }
+}
+
+
+bool consolewin_info::handle_command(WPARAM wparam, LPARAM lparam)
+{
+ if ((HIWORD(wparam) == 0) && (LOWORD(wparam) >= ID_DEVICE_OPTIONS))
+ {
+ UINT32 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 != NULL)
+ {
+ switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX)
+ {
+ case DEVOPTION_OPEN :
+ {
+ astring filter;
+ build_generic_filter(img, false, filter);
+ LPTSTR t_filter = tstring_from_utf8(filter);
+ if (t_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';
+ }
+
+ TCHAR selectedFilename[MAX_PATH];
+ selectedFilename[0] = '\0';
+ OPENFILENAME ofn;
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = NULL;
+ ofn.lpstrFile = selectedFilename;
+ ofn.lpstrFile[0] = '\0';
+ ofn.nMaxFile = MAX_PATH;
+ ofn.lpstrFilter = t_filter;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = NULL;
+ ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
+
+ if (GetOpenFileName(&ofn))
+ {
+ char *utf8_buf = utf8_from_tstring(selectedFilename);
+ if (utf8_buf != NULL)
+ {
+ img->load(utf8_buf);
+ osd_free(utf8_buf);
+ }
+ }
+ osd_free(t_filter);
+ }
+ }
+ return true;
+ //case DEVOPTION_CREATE:
+ //return true;
+ case DEVOPTION_CLOSE:
+ img->unload();
+ return 1;
+ }
+ if (img->device().type() == CASSETTE)
+ {
+ cassette_image_device *const cassette = downcast<cassette_image_device *>(&img->device());
+ 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(-60.0, SEEK_CUR);
+ return true;
+ case DEVOPTION_CASSETTE_FASTFORWARD:
+ cassette->seek(+60.0, SEEK_CUR);
+ return true;
+ }
+ }
+ }
+ }
+ return disasmbasewin_info::handle_command(wparam, lparam);
+}
+
+
+void consolewin_info::process_string(char const *string)
+{
+ if (string[0] == 0) // an empty string is a single step
+ debug_cpu_get_visible_cpu(machine())->debug()->single_step();
+ else // otherwise, just process the command
+ debug_console_execute_command(machine(), string, 1);
+
+ // clear the edit text box
+ set_editwnd_text("");
+}
+
+
+void consolewin_info::build_generic_filter(device_image_interface *img, bool is_save, astring &filter)
+{
+ // common image types
+ add_filter_entry(filter, "Common image types", img->file_extensions());
+
+ // compressed
+ if (!is_save)
+ filter.cat("Compressed Images (*.zip)|*.zip|");
+
+ // all files
+ filter.cat("All files (*.*)|*.*|");
+}
+
+
+void consolewin_info::add_filter_entry(astring &dest, const char *description, const char *extensions)
+{
+ // add the description
+ dest.cat(description);
+ dest.catformat(" (");
+
+ // add the extensions to the description
+ copy_extension_list(dest, extensions);
+
+ // add the trailing rparen and '|' character
+ dest.cat(")|");
+
+ // now add the extension list itself
+ copy_extension_list(dest, extensions);
+
+ // append a '|'
+ dest.cat('|');
+}
+
+
+void consolewin_info::copy_extension_list(astring &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.cat(';');
+
+ // append ".*"
+ dest.cat("*.");
+
+ // append the file extension
+ while (*s && (*s != ','))
+ dest.cat(*s++);
+
+ // if we found a comma, advance
+ while(*s == ',')
+ s++;
+ }
+}
diff --git a/src/osd/modules/debugger/win/consolewininfo.h b/src/osd/modules/debugger/win/consolewininfo.h
new file mode 100644
index 00000000000..08790fb66b3
--- /dev/null
+++ b/src/osd/modules/debugger/win/consolewininfo.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// consolewininfo.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_CONSOLE_WIN_INFO_H__
+#define __DEBUG_WIN_CONSOLE_WIN_INFO_H__
+
+#include "debugwin.h"
+
+#include "disasmbasewininfo.h"
+
+
+class consolewin_info : public disasmbasewin_info
+{
+public:
+ consolewin_info(debugger_windows_interface &debugger);
+ virtual ~consolewin_info();
+
+ void set_cpu(device_t &device);
+
+protected:
+ virtual void recompute_children();
+ virtual void update_menu();
+ virtual bool handle_command(WPARAM wparam, LPARAM lparam);
+
+private:
+ enum
+ {
+ DEVOPTION_OPEN,
+ DEVOPTION_CREATE,
+ DEVOPTION_CLOSE,
+ DEVOPTION_CASSETTE_STOPPAUSE,
+ DEVOPTION_CASSETTE_PLAY,
+ DEVOPTION_CASSETTE_RECORD,
+ DEVOPTION_CASSETTE_REWIND,
+ DEVOPTION_CASSETTE_FASTFORWARD,
+ DEVOPTION_MAX
+ };
+
+ virtual void process_string(char const *string);
+
+ static void build_generic_filter(device_image_interface *img, bool is_save, astring &filter);
+ static void add_filter_entry(astring &dest, char const *description, char const *extensions);
+ static void copy_extension_list(astring &dest, char const *extensions);
+
+ HMENU m_devices_menu;
+};
+
+#endif
diff --git a/src/osd/modules/debugger/win/debugbaseinfo.c b/src/osd/modules/debugger/win/debugbaseinfo.c
new file mode 100644
index 00000000000..34451875063
--- /dev/null
+++ b/src/osd/modules/debugger/win/debugbaseinfo.c
@@ -0,0 +1,60 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// debugbaseinfo.c - Win32 debug window handling
+//
+//============================================================
+
+#include "debugbaseinfo.h"
+
+
+debugbase_info::debugbase_info(debugger_windows_interface &debugger) :
+ m_debugger(debugger),
+ m_machine(debugger.machine()),
+ m_metrics(debugger.metrics()),
+ m_waiting_for_debugger(debugger.waiting_for_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
+ GetWindowRect(wnd, &curbounds);
+ if (parent != NULL)
+ {
+ RECT parentbounds;
+ GetWindowRect(parent, &parentbounds);
+ curbounds.top -= parentbounds.top;
+ curbounds.bottom -= parentbounds.top;
+ curbounds.left -= parentbounds.left;
+ curbounds.right -= parentbounds.left;
+ }
+
+ // if the position matches, don't change it
+ if (curbounds.top == bounds.top && curbounds.left == bounds.left)
+ flags |= SWP_NOMOVE;
+ if ((curbounds.bottom - curbounds.top) == (bounds.bottom - bounds.top) &&
+ (curbounds.right - curbounds.left) == (bounds.right - bounds.left))
+ flags |= SWP_NOSIZE;
+
+ // if we need to, reposition the window
+ if (flags != (SWP_NOMOVE | SWP_NOSIZE))
+ SetWindowPos(wnd, NULL,
+ 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))
+ ShowWindow(wnd, show ? SW_SHOW : SW_HIDE);
+}
diff --git a/src/osd/modules/debugger/win/debugbaseinfo.h b/src/osd/modules/debugger/win/debugbaseinfo.h
new file mode 100644
index 00000000000..9aee28b49ef
--- /dev/null
+++ b/src/osd/modules/debugger/win/debugbaseinfo.h
@@ -0,0 +1,40 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// debugbaseinfo.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_DEBUG_BASE_INFO_H__
+#define __DEBUG_WIN_DEBUG_BASE_INFO_H__
+
+#include "debugwin.h"
+
+#include "emu.h"
+
+
+class debugbase_info
+{
+protected:
+ debugbase_info(debugger_windows_interface &debugger);
+
+ debugger_windows_interface &debugger() const { return m_debugger; }
+ running_machine &machine() const { return m_machine; }
+ ui_metrics const &metrics() const { return m_metrics; }
+
+ bool waiting_for_debugger() const { return m_waiting_for_debugger; }
+ bool seq_pressed() const { return m_debugger.seq_pressed(); }
+
+ static void smart_set_window_bounds(HWND wnd, HWND parent, RECT const &bounds);
+ static void smart_show_window(HWND wnd, bool show);
+
+private:
+ debugger_windows_interface &m_debugger;
+ running_machine &m_machine;
+ ui_metrics const &m_metrics;
+ bool const &m_waiting_for_debugger;
+};
+
+
+#endif
diff --git a/src/osd/modules/debugger/win/debugviewinfo.c b/src/osd/modules/debugger/win/debugviewinfo.c
new file mode 100644
index 00000000000..e474ab5ebcb
--- /dev/null
+++ b/src/osd/modules/debugger/win/debugviewinfo.c
@@ -0,0 +1,809 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// debugview.c - Win32 debug window handling
+//
+//============================================================
+
+#include "debugviewinfo.h"
+
+#include "debugwininfo.h"
+#include "uimetrics.h"
+
+#include "debug/debugcpu.h"
+
+#include "strconv.h"
+
+
+// debugger view styles
+#define DEBUG_VIEW_STYLE WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN
+#define DEBUG_VIEW_STYLE_EX 0
+
+// combo box styles
+#define COMBO_BOX_STYLE WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL
+#define COMBO_BOX_STYLE_EX 0
+
+// horizontal scroll bar styles
+#define HSCROLL_STYLE WS_CHILD | WS_VISIBLE | SBS_HORZ
+#define HSCROLL_STYLE_EX 0
+
+// vertical scroll bar styles
+#define VSCROLL_STYLE WS_CHILD | WS_VISIBLE | SBS_VERT
+#define VSCROLL_STYLE_EX 0
+
+
+bool debugview_info::s_window_class_registered = false;
+
+
+debugview_info::debugview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent, debug_view_type type) :
+ debugbase_info(debugger),
+ m_owner(owner),
+ m_view(NULL),
+ m_wnd(NULL),
+ m_hscroll(NULL),
+ m_vscroll(NULL)
+{
+ register_window_class();
+
+ // create the child view
+ m_wnd = CreateWindowEx(DEBUG_VIEW_STYLE_EX, TEXT("MAMEDebugView"), NULL, DEBUG_VIEW_STYLE,
+ 0, 0, 100, 100, parent, NULL, GetModuleHandle(NULL), this);
+ if (m_wnd == NULL)
+ goto cleanup;
+
+ // create the scroll bars
+ m_hscroll = CreateWindowEx(HSCROLL_STYLE_EX, TEXT("SCROLLBAR"), NULL, HSCROLL_STYLE,
+ 0, 0, 100, CW_USEDEFAULT, m_wnd, NULL, GetModuleHandle(NULL), this);
+ m_vscroll = CreateWindowEx(VSCROLL_STYLE_EX, TEXT("SCROLLBAR"), NULL, VSCROLL_STYLE,
+ 0, 0, CW_USEDEFAULT, 100, m_wnd, NULL, GetModuleHandle(NULL), this);
+ if ((m_hscroll == NULL) || (m_vscroll == NULL))
+ goto cleanup;
+
+ // create the debug view
+ m_view = machine().debug_view().alloc_view(type, &debugview_info::static_update, this);
+ if (m_view == NULL)
+ goto cleanup;
+
+ return;
+
+cleanup:
+ if (m_view != NULL)
+ machine().debug_view().free_view(*m_view);
+ m_view = NULL;
+ if (m_hscroll != NULL)
+ DestroyWindow(m_hscroll);
+ m_hscroll = NULL;
+ if (m_vscroll != NULL)
+ DestroyWindow(m_vscroll);
+ m_vscroll = NULL;
+ if (m_wnd != NULL)
+ DestroyWindow(m_wnd);
+ m_wnd = NULL;
+}
+
+
+debugview_info::~debugview_info()
+{
+ if (m_view)
+ machine().debug_view().free_view(*m_view);
+ if (m_wnd != NULL)
+ DestroyWindow(m_wnd);
+}
+
+
+bool debugview_info::is_valid() const
+{
+ return m_view && m_hscroll && m_vscroll && m_wnd;
+}
+
+
+UINT32 debugview_info::prefwidth() const
+{
+ return (m_view->total_size().x * metrics().debug_font_width()) + metrics().vscroll_width();
+}
+
+
+UINT32 debugview_info::maxwidth()
+{
+ UINT32 max = m_view->total_size().x;
+ debug_view_source const *const cursource = m_view->source();
+ for (debug_view_source const *source = m_view->first_source(); source != NULL; source = source->next())
+ {
+ m_view->set_source(*source);
+ UINT32 const chars = m_view->total_size().x;
+ if (max < chars)
+ max = chars;
+ }
+ if (cursource != NULL)
+ m_view->set_source(*cursource);
+ return (max * metrics().debug_font_width()) + metrics().vscroll_width();
+}
+
+
+void debugview_info::get_bounds(RECT &bounds) const
+{
+ GetWindowRect(m_wnd, &bounds);
+}
+
+
+void debugview_info::set_bounds(RECT const &newbounds)
+{
+ // account for the edges and set the bounds
+ if (m_wnd)
+ smart_set_window_bounds(m_wnd, GetParent(m_wnd), newbounds);
+
+ // update
+ update();
+}
+
+
+void debugview_info::send_vscroll(int delta)
+{
+ if (m_vscroll)
+ {
+ int message_type = SB_LINEUP;
+ if (delta < 0)
+ {
+ message_type = SB_LINEDOWN;
+ delta = -delta;
+ }
+ while (delta > 0)
+ {
+ SendMessage(m_wnd, WM_VSCROLL, message_type, (LPARAM)m_vscroll);
+ 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);
+ }
+}
+
+
+char const *debugview_info::source_name() const
+{
+ if (m_view != NULL)
+ {
+ debug_view_source const *const source = m_view->source();
+ if (source != NULL)
+ return source->name();
+ }
+ return "";
+}
+
+
+device_t *debugview_info::source_device() const
+{
+ if (m_view != NULL)
+ {
+ debug_view_source const *const source = m_view->source();
+ if (source != NULL)
+ return source->device();
+ }
+ return NULL;
+}
+
+
+bool debugview_info::source_is_visible_cpu() const
+{
+ if (m_view != NULL)
+ {
+ const debug_view_source *const source = m_view->source();
+ return (source != NULL) && (debug_cpu_get_visible_cpu(machine()) == source->device());
+ }
+ return false;
+}
+
+
+bool debugview_info::set_source_index(int index)
+{
+ if (m_view != NULL)
+ {
+ const debug_view_source *const source = m_view->source_list().find(index);
+ if (source != NULL)
+ {
+ m_view->set_source(*source);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool debugview_info::set_source_for_device(device_t &device)
+{
+ if (m_view != NULL)
+ {
+ const debug_view_source *const source = m_view->source_for_device(&device);
+ if (source != NULL)
+ {
+ m_view->set_source(*source);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool debugview_info::set_source_for_visible_cpu()
+{
+ device_t *const curcpu = debug_cpu_get_visible_cpu(machine());
+ if (curcpu != NULL)
+ return set_source_for_device(*curcpu);
+ else
+ return false;
+}
+
+
+HWND debugview_info::create_source_combobox(HWND parent, LONG_PTR userdata)
+{
+ // create a combo box
+ HWND const result = CreateWindowEx(COMBO_BOX_STYLE_EX, TEXT("COMBOBOX"), NULL, COMBO_BOX_STYLE,
+ 0, 0, 100, 1000, parent, NULL, GetModuleHandle(NULL), NULL);
+ SetWindowLongPtr(result, GWLP_USERDATA, userdata);
+ SendMessage(result, WM_SETFONT, (WPARAM)metrics().debug_font(), (LPARAM)FALSE);
+
+ // 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 != NULL; source = source->next())
+ {
+ int const length = strlen(source->name());
+ if (length > maxlength)
+ maxlength = length;
+ TCHAR *t_name = tstring_from_utf8(source->name());
+ SendMessage(result, CB_ADDSTRING, 0, (LPARAM)t_name);
+ osd_free(t_name);
+ }
+ if (cursource != NULL)
+ {
+ SendMessage(result, CB_SETCURSEL, m_view->source_list().indexof(*cursource), 0);
+ SendMessage(result, CB_SETDROPPEDWIDTH, ((maxlength + 2) * metrics().debug_font_width()) + metrics().vscroll_width(), 0);
+ m_view->set_source(*cursource);
+ }
+ return result;
+}
+
+
+void debugview_info::draw_contents(HDC windc)
+{
+ debug_view_char const *viewdata = m_view->viewdata();
+ debug_view_xy const visarea = m_view->visible_size();
+
+ // get the client rect
+ RECT client;
+ GetClientRect(m_wnd, &client);
+
+ // create a compatible DC and an offscreen bitmap
+ HDC const dc = CreateCompatibleDC(windc);
+ if (dc == NULL)
+ return;
+ HBITMAP const bitmap = CreateCompatibleBitmap(windc, client.right, client.bottom);
+ if (bitmap == NULL)
+ {
+ DeleteDC(dc);
+ return;
+ }
+ HGDIOBJ const oldbitmap = SelectObject(dc, bitmap);
+
+ // set the font
+ HGDIOBJ const oldfont = SelectObject(dc, metrics().debug_font());
+ COLORREF const oldfgcolor = GetTextColor(dc);
+ int const oldbkmode = GetBkMode(dc);
+ SetBkMode(dc, TRANSPARENT);
+
+ // iterate over rows and columns
+ for (UINT32 row = 0; row < visarea.y; row++)
+ {
+
+ // loop twice; once to fill the background and once to draw the text
+ for (int iter = 0; iter < 2; iter++)
+ {
+ COLORREF fgcolor = RGB(0x00,0x00,0x00);
+ COLORREF bgcolor = RGB(0xff,0xff,0xff);
+ HBRUSH bgbrush = NULL;
+ int last_attrib = -1;
+ TCHAR buffer[256];
+ int count = 0;
+ RECT bounds;
+
+ // initialize the text bounds
+ bounds.left = bounds.right = 0;
+ bounds.top = row * metrics().debug_font_height();
+ bounds.bottom = bounds.top + metrics().debug_font_height();
+
+ // start with a brush on iteration #0
+ if (iter == 0)
+ bgbrush = CreateSolidBrush(bgcolor);
+
+ // iterate over columns
+ for (UINT32 col = 0; col < visarea.x; col++)
+ {
+ // if the attribute changed, adjust the colors
+ if (viewdata[col].attrib != last_attrib)
+ {
+ 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);
+
+ // flush any pending drawing
+ 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, NULL, buffer, count, NULL);
+ bounds.left = bounds.right;
+ count = 0;
+ }
+
+ // set the new colors
+ if (iter == 0 && oldbg != bgcolor)
+ {
+ DeleteObject(bgbrush);
+ bgbrush = CreateSolidBrush(bgcolor);
+ }
+ else if (iter == 1)
+ SetTextColor(dc, fgcolor);
+ last_attrib = viewdata[col].attrib;
+ }
+
+ // add this character to the buffer
+ buffer[count++] = viewdata[col].byte;
+ }
+
+ // 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, NULL, buffer, count, NULL);
+ }
+
+ // erase to the end of the line
+ if (iter == 0)
+ {
+ bounds.left = bounds.right;
+ bounds.right = client.right;
+ FillRect(dc, &bounds, bgbrush);
+ DeleteObject(bgbrush);
+ }
+ }
+
+ // 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));
+
+ // reset the font
+ SetBkMode(dc, oldbkmode);
+ SetTextColor(dc, oldfgcolor);
+ SelectObject(dc, oldfont);
+
+ // blit the final results
+ BitBlt(windc, 0, 0, client.right, client.bottom, dc, 0, 0, SRCCOPY);
+
+ // undo the offscreen stuff
+ SelectObject(dc, oldbitmap);
+ DeleteObject(bitmap);
+ DeleteDC(dc);
+}
+
+
+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 view window bounds
+ GetClientRect(m_wnd, &bounds);
+ 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())
+ {
+ 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())
+ {
+ bounds.right -= metrics().vscroll_width();
+ visiblesize.x = (bounds.right - bounds.left) / metrics().debug_font_width();
+ show_vscroll = true;
+ }
+
+ // compute the bounds of the scrollbars
+ GetClientRect(m_wnd, &vscroll_bounds);
+ vscroll_bounds.left = vscroll_bounds.right - metrics().vscroll_width();
+ if (show_hscroll)
+ vscroll_bounds.bottom -= metrics().hscroll_height();
+
+ GetClientRect(m_wnd, &hscroll_bounds);
+ hscroll_bounds.top = hscroll_bounds.bottom - metrics().hscroll_height();
+ if (show_vscroll)
+ hscroll_bounds.right -= metrics().vscroll_width();
+
+ // if we hid the scrollbars, make sure we reset the top/left corners
+ if (topleft.y + visiblesize.y > totalsize.y)
+ topleft.y = MAX(totalsize.y - visiblesize.y, 0);
+ if (topleft.x + visiblesize.x > totalsize.x)
+ topleft.x = 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);
+
+ // 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);
+
+ // update window info
+ visiblesize.y++;
+ visiblesize.x++;
+ m_view->set_visible_size(visiblesize);
+ m_view->set_visible_position(topleft);
+
+ // invalidate the bounds
+ InvalidateRect(m_wnd, NULL, FALSE);
+
+ // adjust the bounds of the scrollbars and show/hide them
+ if (m_vscroll)
+ {
+ if (show_vscroll)
+ smart_set_window_bounds(m_vscroll, m_wnd, vscroll_bounds);
+ smart_show_window(m_vscroll, show_vscroll);
+ }
+ if (m_hscroll)
+ {
+ if (show_hscroll)
+ smart_set_window_bounds(m_hscroll, m_wnd, hscroll_bounds);
+ smart_show_window(m_hscroll, show_hscroll);
+ }
+}
+
+
+UINT32 debugview_info::process_scroll(WORD type, HWND wnd)
+{
+ // get the current info
+ SCROLLINFO scrollinfo;
+ scrollinfo.cbSize = sizeof(scrollinfo);
+ scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
+ GetScrollInfo(wnd, SB_CTL, &scrollinfo);
+
+ // by default we stay put
+ INT32 result = scrollinfo.nPos;
+
+ // determine the maximum value
+ INT32 const maxval = (scrollinfo.nMax > scrollinfo.nPage) ? (scrollinfo.nMax - scrollinfo.nPage + 1) : 0;
+
+ // handle the message
+ switch (type)
+ {
+ case SB_THUMBTRACK:
+ result = scrollinfo.nTrackPos;
+ break;
+
+ case SB_LEFT:
+ result = 0;
+ break;
+
+ case SB_RIGHT:
+ result = maxval;
+ break;
+
+ case SB_LINELEFT:
+ result -= 1;
+ break;
+
+ case SB_LINERIGHT:
+ result += 1;
+ break;
+
+ case SB_PAGELEFT:
+ result -= scrollinfo.nPage - 1;
+ break;
+
+ case SB_PAGERIGHT:
+ result += scrollinfo.nPage - 1;
+ break;
+ }
+
+ // generic rangecheck
+ if (result < 0)
+ result = 0;
+ if (result > maxval)
+ result = maxval;
+
+ // set the new position
+ scrollinfo.fMask = SIF_POS;
+ scrollinfo.nPos = result;
+ SetScrollInfo(wnd, SB_CTL, &scrollinfo, TRUE);
+
+ return (UINT32)result;
+}
+
+
+LRESULT debugview_info::view_proc(UINT message, WPARAM wparam, LPARAM lparam)
+{
+ // handle a few messages
+ switch (message)
+ {
+ // paint: redraw the last bitmap
+ case WM_PAINT:
+ {
+ PAINTSTRUCT pstruct;
+ HDC const dc = BeginPaint(m_wnd, &pstruct);
+ draw_contents(dc);
+ EndPaint(m_wnd, &pstruct);
+ break;
+ }
+
+ // keydown: handle debugger keys
+ case WM_SYSKEYDOWN:
+ if (wparam != VK_F10)
+ return DefWindowProc(m_wnd, message, wparam, lparam);
+ // (fall through)
+ case WM_KEYDOWN:
+ {
+ if (m_owner.handle_key(wparam, lparam))
+ {
+ m_owner.set_ignore_char_lparam(lparam);
+ }
+ else
+ {
+ switch (wparam)
+ {
+ case VK_UP:
+ m_view->process_char(DCH_UP);
+ m_owner.set_ignore_char_lparam(lparam);
+ break;
+
+ case VK_DOWN:
+ m_view->process_char(DCH_DOWN);
+ m_owner.set_ignore_char_lparam(lparam);
+ break;
+
+ case VK_LEFT:
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ m_view->process_char(DCH_CTRLLEFT);
+ else
+ m_view->process_char(DCH_LEFT);
+ m_owner.set_ignore_char_lparam(lparam);
+ break;
+
+ case VK_RIGHT:
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ m_view->process_char(DCH_CTRLRIGHT);
+ else
+ m_view->process_char(DCH_RIGHT);
+ m_owner.set_ignore_char_lparam(lparam);
+ break;
+
+ case VK_PRIOR:
+ m_view->process_char(DCH_PUP);
+ m_owner.set_ignore_char_lparam(lparam);
+ break;
+
+ case VK_NEXT:
+ m_view->process_char(DCH_PDOWN);
+ m_owner.set_ignore_char_lparam(lparam);
+ break;
+
+ case VK_HOME:
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ m_view->process_char(DCH_CTRLHOME);
+ else
+ m_view->process_char(DCH_HOME);
+ m_owner.set_ignore_char_lparam(lparam);
+ break;
+
+ case VK_END:
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ m_view->process_char(DCH_CTRLEND);
+ else
+ m_view->process_char(DCH_END);
+ m_owner.set_ignore_char_lparam(lparam);
+ break;
+
+ case VK_ESCAPE:
+ m_owner.set_default_focus();
+ m_owner.set_ignore_char_lparam(lparam);
+ break;
+
+ case VK_TAB:
+ if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
+ m_owner.prev_view(this);
+ else
+ m_owner.next_view(this);
+ m_owner.set_ignore_char_lparam(lparam);
+ break;
+ }
+ }
+ break;
+ }
+
+ // char: ignore chars associated with keys we've handled
+ case WM_CHAR:
+ if (m_owner.check_ignore_char_lparam(lparam))
+ {
+ if (waiting_for_debugger() || !seq_pressed())
+ {
+ if (wparam >= 32 && wparam < 127)
+ {
+ if (m_view->cursor_supported())
+ m_view->set_cursor_visible(true);
+ m_view->process_char(wparam);
+ }
+ else
+ {
+ return DefWindowProc(m_wnd, message, wparam, lparam);
+ }
+ }
+ }
+ break;
+
+ // gaining focus
+ case WM_SETFOCUS:
+ if (m_view->cursor_supported())
+ m_view->set_cursor_visible(true);
+ break;
+
+ // losing focus
+ case WM_KILLFOCUS:
+ if (m_view->cursor_supported())
+ m_view->set_cursor_visible(false);
+ break;
+
+ // mouse click
+ case WM_LBUTTONDOWN:
+ {
+ debug_view_xy topleft = m_view->visible_position();
+ 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);
+ SetFocus(m_wnd);
+ break;
+ }
+
+ // hscroll
+ case WM_HSCROLL:
+ {
+ debug_view_xy topleft = m_view->visible_position();
+ topleft.x = process_scroll(LOWORD(wparam), (HWND)lparam);
+ m_view->set_visible_position(topleft);
+ machine().debug_view().flush_osd_updates();
+ break;
+ }
+
+ // vscroll
+ case WM_VSCROLL:
+ {
+ debug_view_xy topleft = m_view->visible_position();
+ topleft.y = process_scroll(LOWORD(wparam), (HWND)lparam);
+ m_view->set_visible_position(topleft);
+ machine().debug_view().flush_osd_updates();
+ break;
+ }
+
+ // everything else: defaults
+ default:
+ return DefWindowProc(m_wnd, message, wparam, lparam);
+ }
+
+ return 0;
+}
+
+
+void debugview_info::static_update(debug_view &view, void *osdprivate)
+{
+ debugview_info *const info = (debugview_info *)osdprivate;
+ assert(info->m_view == &view);
+ info->update();
+}
+
+
+LRESULT CALLBACK debugview_info::static_view_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ if (message == WM_CREATE)
+ {
+ // set the info pointer
+ CREATESTRUCT const *const createinfo = (CREATESTRUCT *)lparam;
+ SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)createinfo->lpCreateParams);
+ return 0;
+ }
+
+ debugview_info *const info = (debugview_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
+ if (!info)
+ return DefWindowProc(wnd, message, wparam, lparam);
+
+ assert(info->m_wnd == wnd);
+ return info->view_proc(message, wparam, lparam);
+}
+
+
+void debugview_info::register_window_class()
+{
+ if (!s_window_class_registered)
+ {
+ WNDCLASS wc = { 0 };
+
+ // initialize the description of the window class
+ wc.lpszClassName = TEXT("MAMEDebugView");
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.lpfnWndProc = &debugview_info::static_view_proc;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hIcon = LoadIcon(wc.hInstance, MAKEINTRESOURCE(2));
+ wc.lpszMenuName = NULL;
+ wc.hbrBackground = NULL;
+ wc.style = 0;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+
+ // register the class; fail if we can't
+ if (!RegisterClass(&wc))
+ fatalerror("Unable to register debug view class\n");
+
+ s_window_class_registered = true;
+ }
+}
diff --git a/src/osd/modules/debugger/win/debugviewinfo.h b/src/osd/modules/debugger/win/debugviewinfo.h
new file mode 100644
index 00000000000..d804554778a
--- /dev/null
+++ b/src/osd/modules/debugger/win/debugviewinfo.h
@@ -0,0 +1,77 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// debugviewinfo.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_DEBUG_VIEW_INFO_H__
+#define __DEBUG_WIN_DEBUG_VIEW_INFO_H__
+
+#include "debugwin.h"
+
+#include "debugbaseinfo.h"
+
+#include "emu.h"
+#include "debug/debugvw.h"
+
+
+class debugview_info : protected debugbase_info
+{
+public:
+ debugview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent, debug_view_type type);
+ virtual ~debugview_info();
+
+ bool is_valid() const;
+
+ bool owns_window(HWND wnd) const { return m_wnd == wnd; }
+
+ UINT32 prefwidth() const;
+ UINT32 maxwidth();
+ void get_bounds(RECT &bounds) const;
+ void set_bounds(RECT const &newbounds);
+
+ void send_vscroll(int delta);
+ void send_pageup();
+ void send_pagedown();
+ void set_focus() { SetFocus(m_wnd); }
+
+ debug_view_type type() const { return m_view->type(); }
+ debug_view_xy total_size() const { return m_view->total_size(); }
+ bool cursor_supported() const { return m_view->cursor_supported(); }
+ bool cursor_visible() const { return m_view->cursor_visible(); }
+
+ char const *source_name() const;
+ device_t *source_device() const;
+ bool source_is_visible_cpu() const;
+ bool set_source_index(int index);
+ bool set_source_for_device(device_t &device);
+ bool set_source_for_visible_cpu();
+
+ HWND create_source_combobox(HWND parent, LONG_PTR userdata);
+
+protected:
+ template <typename T> T *view() const { return downcast<T *>(m_view); }
+
+private:
+ void draw_contents(HDC windc);
+ void update();
+ UINT32 process_scroll(WORD type, HWND wnd);
+ LRESULT view_proc(UINT message, WPARAM wparam, LPARAM lparam);
+
+ static void static_update(debug_view &view, void *osdprivate);
+ static LRESULT CALLBACK static_view_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
+
+ static void register_window_class();
+
+ debugwin_info &m_owner;
+ debug_view *m_view;
+ HWND m_wnd;
+ HWND m_hscroll;
+ HWND m_vscroll;
+
+ static bool s_window_class_registered;
+};
+
+#endif
diff --git a/src/osd/modules/debugger/win/debugwin.h b/src/osd/modules/debugger/win/debugwin.h
new file mode 100644
index 00000000000..6971e7f93c0
--- /dev/null
+++ b/src/osd/modules/debugger/win/debugwin.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// debugwin.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_DEBUG_WIN_H__
+#define __DEBUG_WIN_DEBUG_WIN_H__
+
+// standard windows headers
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <windowsx.h>
+#include <tchar.h>
+#include <commdlg.h>
+#ifdef _MSC_VER
+#include <zmouse.h>
+#endif
+
+#include "emu.h"
+
+
+class debugview_info;
+class debugwin_info;
+class ui_metrics;
+
+
+class debugger_windows_interface
+{
+public:
+ virtual ~debugger_windows_interface() { }
+
+ virtual running_machine &machine() const = 0;
+
+ virtual ui_metrics &metrics() const = 0;
+
+ virtual bool const &waiting_for_debugger() const = 0;
+ virtual bool seq_pressed() const = 0;
+
+ virtual void create_memory_window() = 0;
+ virtual void create_disasm_window() = 0;
+ virtual void create_log_window() = 0;
+ virtual void create_points_window() = 0;
+ virtual void remove_window(debugwin_info &info) = 0;
+
+ virtual void show_all() = 0;
+ virtual void hide_all() = 0;
+};
+
+#endif
diff --git a/src/osd/modules/debugger/win/debugwininfo.c b/src/osd/modules/debugger/win/debugwininfo.c
new file mode 100644
index 00000000000..3c32db35d9c
--- /dev/null
+++ b/src/osd/modules/debugger/win/debugwininfo.c
@@ -0,0 +1,599 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// debugwininfo.c - Win32 debug window handling
+//
+//============================================================
+
+#include "debugwininfo.h"
+
+#include "debugviewinfo.h"
+
+#include "debug/debugcpu.h"
+#include "imagedev/cassette.h"
+
+#include "strconv.h"
+#include "window.h"
+#include "winutf8.h"
+
+
+bool debugwin_info::s_window_class_registered = false;
+
+
+debugwin_info::debugwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler) :
+ debugbase_info(debugger),
+ m_is_main_console(is_main_console),
+ m_next(NULL),
+ m_wnd(NULL),
+ m_handler(handler),
+ m_minwidth(200),
+ m_maxwidth(0),
+ m_minheight(200),
+ m_maxheight(0),
+ m_ignore_char_lparam(0)
+{
+ register_window_class();
+
+ m_wnd = win_create_window_ex_utf8(DEBUG_WINDOW_STYLE_EX, "MAMEDebugWindow", title, DEBUG_WINDOW_STYLE,
+ 0, 0, 100, 100, win_window_list->m_hwnd, create_standard_menubar(), GetModuleHandle(NULL), this);
+ if (m_wnd == NULL)
+ return;
+
+ RECT work_bounds;
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &work_bounds, 0);
+ m_maxwidth = work_bounds.right - work_bounds.left;
+ m_maxheight = work_bounds.bottom - work_bounds.top;
+}
+
+
+debugwin_info::~debugwin_info()
+{
+}
+
+
+void debugwin_info::destroy()
+{
+ for (int curview = 0; curview < MAX_VIEWS; curview++)
+ m_views[curview].reset();
+ DestroyWindow(m_wnd);
+}
+
+bool debugwin_info::set_default_focus()
+{
+ return false;
+}
+
+
+void debugwin_info::prev_view(debugview_info *curview)
+{
+ // count the number of views
+ int numviews;
+ for (numviews = 0; numviews < MAX_VIEWS; numviews++)
+ {
+ if (m_views[numviews] == NULL)
+ break;
+ }
+
+ // if we have a curview, find out its index
+ int curindex = 1;
+ if (curview)
+ {
+ for (curindex = numviews - 1; curindex > 0; curindex--)
+ {
+ if (m_views[curindex] == curview)
+ break;
+ }
+ if (curindex < 0)
+ curindex = 1;
+ }
+
+ // loop until we find someone to take focus
+ while (1)
+ {
+ // advance to the previous index
+ curindex--;
+ if (curindex < -1)
+ curindex = numviews - 1;
+
+ if (curindex < 0 && set_default_focus())
+ {
+ // negative numbers mean the focuswnd
+ break;
+ }
+ else if (curindex >= 0 && m_views[curindex] != NULL && m_views[curindex]->cursor_supported())
+ {
+ // positive numbers mean a view
+ m_views[curindex]->set_focus();
+ break;
+ }
+ }
+}
+
+
+void debugwin_info::next_view(debugview_info *curview)
+{
+ // count the number of views
+ int numviews;
+ for (numviews = 0; numviews < MAX_VIEWS; numviews++)
+ {
+ if (m_views[numviews] == NULL)
+ break;
+ }
+
+ // if we have a curview, find out its index
+ int curindex = -1;
+ if (curview)
+ {
+ for (curindex = numviews - 1; curindex > 0; curindex--)
+ {
+ if (m_views[curindex] == curview)
+ break;
+ }
+ }
+
+ // loop until we find someone to take focus
+ while (1)
+ {
+ // advance to the previous index
+ curindex++;
+ if (curindex >= numviews)
+ curindex = -1;
+
+ if (curindex < 0 && set_default_focus())
+ {
+ // negative numbers mean the focuswnd
+ break;
+ }
+ else if (curindex >= 0 && m_views[curindex] != NULL && m_views[curindex]->cursor_supported())
+ {
+ // positive numbers mean a view
+ m_views[curindex]->set_focus();
+ break;
+ }
+ }
+}
+
+
+bool debugwin_info::handle_key(WPARAM wparam, LPARAM lparam)
+{
+ /* ignore any keys that are received while the debug key is down */
+ if (!waiting_for_debugger() && seq_pressed())
+ return true;
+
+ switch (wparam)
+ {
+ case VK_F3:
+ if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
+ SendMessage(m_wnd, WM_COMMAND, ID_HARD_RESET, 0);
+ else
+ SendMessage(m_wnd, WM_COMMAND, ID_SOFT_RESET, 0);
+ return true;
+
+ case VK_F4:
+ if (GetAsyncKeyState(VK_MENU) & 0x8000)
+ {
+ /* ajg - never gets here since 'alt' seems to be captured somewhere else - menu maybe? */
+ SendMessage(m_wnd, WM_COMMAND, ID_EXIT, 0);
+ return true;
+ }
+ break;
+
+ case VK_F5:
+ SendMessage(m_wnd, WM_COMMAND, ID_RUN, 0);
+ return true;
+
+ case VK_F6:
+ SendMessage(m_wnd, WM_COMMAND, ID_NEXT_CPU, 0);
+ return true;
+
+ case VK_F7:
+ SendMessage(m_wnd, WM_COMMAND, ID_RUN_IRQ, 0);
+ return true;
+
+ case VK_F8:
+ SendMessage(m_wnd, WM_COMMAND, ID_RUN_VBLANK, 0);
+ return true;
+
+ case VK_F10:
+ SendMessage(m_wnd, WM_COMMAND, ID_STEP_OVER, 0);
+ return true;
+
+ case VK_F11:
+ if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
+ SendMessage(m_wnd, WM_COMMAND, ID_STEP_OUT, 0);
+ else
+ SendMessage(m_wnd, WM_COMMAND, ID_STEP, 0);
+ return true;
+
+ case VK_F12:
+ SendMessage(m_wnd, WM_COMMAND, ID_RUN_AND_HIDE, 0);
+ return true;
+
+ case 'M':
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ {
+ SendMessage(m_wnd, WM_COMMAND, ID_NEW_MEMORY_WND, 0);
+ return true;
+ }
+ break;
+
+ case 'D':
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ {
+ SendMessage(m_wnd, WM_COMMAND, ID_NEW_DISASM_WND, 0);
+ return true;
+ }
+ break;
+
+ case 'L':
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ {
+ SendMessage(m_wnd, WM_COMMAND, ID_NEW_LOG_WND, 0);
+ return true;
+ }
+ break;
+
+ case 'B':
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ {
+ SendMessage(m_wnd, WM_COMMAND, ID_NEW_POINTS_WND, 0);
+ return true;
+ }
+ break;
+ }
+
+ return false;
+}
+
+
+void debugwin_info::recompute_children()
+{
+ if (m_views[0] != NULL)
+ {
+ // compute a client rect
+ RECT bounds;
+ bounds.top = bounds.left = 0;
+ bounds.right = m_views[0]->prefwidth() + (2 * EDGE_WIDTH);
+ bounds.bottom = 200;
+ AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
+
+ // clamp the min/max size
+ set_maxwidth(bounds.right - bounds.left);
+
+ // get the parent's dimensions
+ RECT parent;
+ GetClientRect(window(), &parent);
+
+ // view gets the remaining space
+ InflateRect(&parent, -EDGE_WIDTH, -EDGE_WIDTH);
+ m_views[0]->set_bounds(parent);
+ }
+}
+
+
+bool debugwin_info::handle_command(WPARAM wparam, LPARAM lparam)
+{
+ if (HIWORD(wparam) == 0)
+ {
+ switch (LOWORD(wparam))
+ {
+ case ID_NEW_MEMORY_WND:
+ debugger().create_memory_window();
+ return true;
+
+ case ID_NEW_DISASM_WND:
+ debugger().create_disasm_window();
+ return true;
+
+ case ID_NEW_LOG_WND:
+ debugger().create_log_window();
+ return true;
+
+ case ID_NEW_POINTS_WND:
+ debugger().create_points_window();
+ return true;
+
+ case ID_RUN_AND_HIDE:
+ debugger().hide_all();
+ case ID_RUN:
+ debug_cpu_get_visible_cpu(machine())->debug()->go();
+ return true;
+
+ case ID_NEXT_CPU:
+ debug_cpu_get_visible_cpu(machine())->debug()->go_next_device();
+ return true;
+
+ case ID_RUN_VBLANK:
+ debug_cpu_get_visible_cpu(machine())->debug()->go_vblank();
+ return true;
+
+ case ID_RUN_IRQ:
+ debug_cpu_get_visible_cpu(machine())->debug()->go_interrupt();
+ return true;
+
+ case ID_STEP:
+ debug_cpu_get_visible_cpu(machine())->debug()->single_step();
+ return true;
+
+ case ID_STEP_OVER:
+ debug_cpu_get_visible_cpu(machine())->debug()->single_step_over();
+ return true;
+
+ case ID_STEP_OUT:
+ debug_cpu_get_visible_cpu(machine())->debug()->single_step_out();
+ return true;
+
+ case ID_HARD_RESET:
+ machine().schedule_hard_reset();
+ return true;
+
+ case ID_SOFT_RESET:
+ machine().schedule_soft_reset();
+ debug_cpu_get_visible_cpu(machine())->debug()->go();
+ return true;
+
+ case ID_EXIT:
+ set_default_focus();
+ machine().schedule_exit();
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void debugwin_info::draw_contents(HDC dc)
+{
+ // fill the background with light gray
+ RECT parent;
+ GetClientRect(m_wnd, &parent);
+ FillRect(dc, &parent, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
+
+ // draw edges around all views
+ for (int curview = 0; curview < MAX_VIEWS; curview++)
+ {
+ if (m_views[curview] != NULL)
+ {
+ RECT bounds;
+ m_views[curview]->get_bounds(bounds);
+ draw_border(dc, bounds);
+ }
+ }
+}
+
+
+void debugwin_info::draw_border(HDC dc, RECT &bounds)
+{
+ ScreenToClient(m_wnd, &((POINT *)&bounds)[0]);
+ ScreenToClient(m_wnd, &((POINT *)&bounds)[1]);
+ InflateRect(&bounds, EDGE_WIDTH, EDGE_WIDTH);
+ DrawEdge(dc, &bounds, EDGE_SUNKEN, BF_RECT);
+}
+
+
+void debugwin_info::draw_border(HDC dc, HWND child)
+{
+ RECT bounds;
+ GetWindowRect(child, &bounds);
+ draw_border(dc, bounds);
+}
+
+
+LRESULT debugwin_info::window_proc(UINT message, WPARAM wparam, LPARAM lparam)
+{
+ // handle a few messages
+ switch (message)
+ {
+ // paint: draw bezels as necessary
+ case WM_PAINT:
+ {
+ PAINTSTRUCT pstruct;
+ HDC dc = BeginPaint(m_wnd, &pstruct);
+ draw_contents(dc);
+ EndPaint(m_wnd, &pstruct);
+ break;
+ }
+
+ // keydown: handle debugger keys
+ case WM_KEYDOWN:
+ if (handle_key(wparam, lparam))
+ set_ignore_char_lparam(lparam);
+ break;
+
+ // char: ignore chars associated with keys we've handled
+ case WM_CHAR:
+ if (check_ignore_char_lparam(lparam))
+ {
+ if (waiting_for_debugger() || !seq_pressed())
+ return DefWindowProc(m_wnd, message, wparam, lparam);
+ }
+ break;
+
+ // activate: set the focus
+ case WM_ACTIVATE:
+ if (wparam != WA_INACTIVE)
+ set_default_focus();
+ break;
+
+ // get min/max info: set the minimum window size
+ case WM_GETMINMAXINFO:
+ {
+ MINMAXINFO *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;
+ break;
+ }
+
+ // sizing: recompute child window locations
+ case WM_SIZE:
+ case WM_SIZING:
+ recompute_children();
+ InvalidateRect(m_wnd, NULL, FALSE);
+ break;
+
+ // mouse wheel: forward to the first view
+ case WM_MOUSEWHEEL:
+ {
+ static int units_carryover = 0;
+
+ UINT lines_per_click;
+ if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines_per_click, 0))
+ lines_per_click = 3;
+
+ int const units = GET_WHEEL_DELTA_WPARAM(wparam) + units_carryover;
+ int const clicks = units / WHEEL_DELTA;
+ units_carryover = units % WHEEL_DELTA;
+
+ int const delta = clicks * lines_per_click;
+ int viewnum = 0;
+ POINT point;
+
+ // figure out which view we are hovering over
+ GetCursorPos(&point);
+ ScreenToClient(m_wnd, &point);
+ HWND const child = ChildWindowFromPoint(m_wnd, point);
+ if (child)
+ {
+ for (viewnum = 0; viewnum < MAX_VIEWS; viewnum++)
+ {
+ if ((m_views[viewnum] != NULL) && m_views[viewnum]->owns_window(child))
+ break;
+ }
+ if (viewnum == MAX_VIEWS)
+ break;
+ }
+
+ // send the appropriate message to this view's scrollbar
+ if (m_views[viewnum] != NULL)
+ m_views[viewnum]->send_vscroll(delta);
+
+ break;
+ }
+
+ // activate: set the focus
+ case WM_INITMENU:
+ update_menu();
+ break;
+
+ // command: handle a comment
+ case WM_COMMAND:
+ if (!handle_command(wparam, lparam))
+ return DefWindowProc(m_wnd, message, wparam, lparam);
+ break;
+
+ // close: close the window if it's not the main console
+ case WM_CLOSE:
+ if (m_is_main_console)
+ {
+ debugger().hide_all();
+ debug_cpu_get_visible_cpu(machine())->debug()->go();
+ }
+ else
+ {
+ destroy();
+ }
+ break;
+
+ // destroy: close down the window
+ case WM_NCDESTROY:
+ m_wnd = NULL;
+ debugger().remove_window(*this);
+ break;
+
+ // everything else: defaults
+ default:
+ return DefWindowProc(m_wnd, message, wparam, lparam);
+ }
+
+ return 0;
+}
+
+
+HMENU debugwin_info::create_standard_menubar()
+{
+ // create the debug menu
+ HMENU const debugmenu = CreatePopupMenu();
+ if (debugmenu == NULL)
+ return NULL;
+ AppendMenu(debugmenu, MF_ENABLED, ID_NEW_MEMORY_WND, TEXT("New Memory Window\tCtrl+M"));
+ AppendMenu(debugmenu, MF_ENABLED, ID_NEW_DISASM_WND, TEXT("New Disassembly Window\tCtrl+D"));
+ AppendMenu(debugmenu, MF_ENABLED, ID_NEW_LOG_WND, TEXT("New Error Log Window\tCtrl+L"));
+ AppendMenu(debugmenu, MF_ENABLED, ID_NEW_POINTS_WND, TEXT("New (Break|Watch)points Window\tCtrl+B"));
+ AppendMenu(debugmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
+ AppendMenu(debugmenu, MF_ENABLED, ID_RUN, TEXT("Run\tF5"));
+ AppendMenu(debugmenu, MF_ENABLED, ID_RUN_AND_HIDE, TEXT("Run and Hide Debugger\tF12"));
+ AppendMenu(debugmenu, MF_ENABLED, ID_NEXT_CPU, TEXT("Run to Next CPU\tF6"));
+ AppendMenu(debugmenu, MF_ENABLED, ID_RUN_IRQ, TEXT("Run until Next Interrupt on This CPU\tF7"));
+ AppendMenu(debugmenu, MF_ENABLED, ID_RUN_VBLANK, TEXT("Run until Next VBLANK\tF8"));
+ AppendMenu(debugmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
+ AppendMenu(debugmenu, MF_ENABLED, ID_STEP, TEXT("Step Into\tF11"));
+ AppendMenu(debugmenu, MF_ENABLED, ID_STEP_OVER, TEXT("Step Over\tF10"));
+ AppendMenu(debugmenu, MF_ENABLED, ID_STEP_OUT, TEXT("Step Out\tShift+F11"));
+ AppendMenu(debugmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
+ AppendMenu(debugmenu, MF_ENABLED, ID_SOFT_RESET, TEXT("Soft Reset\tF3"));
+ AppendMenu(debugmenu, MF_ENABLED, ID_HARD_RESET, TEXT("Hard Reset\tShift+F3"));
+ AppendMenu(debugmenu, MF_ENABLED, ID_EXIT, TEXT("Exit"));
+
+ // create the menu bar
+ HMENU const menubar = CreateMenu();
+ if (menubar == NULL)
+ {
+ DestroyMenu(debugmenu);
+ return NULL;
+ }
+ AppendMenu(menubar, MF_ENABLED | MF_POPUP, (UINT_PTR)debugmenu, TEXT("Debug"));
+
+ return menubar;
+}
+
+
+LRESULT CALLBACK debugwin_info::static_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ if (message == WM_CREATE)
+ {
+ // set the info pointer
+ CREATESTRUCT const *const createinfo = (CREATESTRUCT *)lparam;
+ debugwin_info *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 *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
+ if (!info)
+ return DefWindowProc(wnd, message, wparam, lparam);
+
+ assert(info->m_wnd == wnd);
+ return info->window_proc(message, wparam, lparam);
+}
+
+
+void debugwin_info::register_window_class()
+{
+ if (!s_window_class_registered)
+ {
+ WNDCLASS wc = { 0 };
+
+ // initialize the description of the window class
+ wc.lpszClassName = TEXT("MAMEDebugWindow");
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.lpfnWndProc = &debugwin_info::static_window_proc;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hIcon = LoadIcon(wc.hInstance, MAKEINTRESOURCE(2));
+ wc.lpszMenuName = NULL;
+ wc.hbrBackground = NULL;
+ wc.style = 0;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+
+ // register the class; fail if we can't
+ if (!RegisterClass(&wc))
+ fatalerror("Unable to register debug window class\n");
+
+ s_window_class_registered = true;
+ }
+}
diff --git a/src/osd/modules/debugger/win/debugwininfo.h b/src/osd/modules/debugger/win/debugwininfo.h
new file mode 100644
index 00000000000..148d79a651e
--- /dev/null
+++ b/src/osd/modules/debugger/win/debugwininfo.h
@@ -0,0 +1,142 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// debugwininfo.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_DEBUG_WIN_INFO_H__
+#define __DEBUG_WIN_DEBUG_WIN_INFO_H__
+
+#include "debugwin.h"
+
+#include "debugbaseinfo.h"
+
+#include "emu.h"
+
+
+class debugwin_info : protected debugbase_info
+{
+public:
+ template<class U> friend class simple_list;
+
+ debugwin_info(debugger_windows_interface &debugger, bool main_console, LPCSTR title, WNDPROC handler);
+ virtual ~debugwin_info();
+
+ bool is_valid() const { return m_wnd != NULL; }
+ debugwin_info *next() const { return m_next; }
+
+ void set_ignore_char_lparam(LPARAM value) { m_ignore_char_lparam = value >> 16; }
+ bool check_ignore_char_lparam(LPARAM value)
+ {
+ if (m_ignore_char_lparam == (value >> 16))
+ {
+ m_ignore_char_lparam = 0;
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ void show() { smart_show_window(m_wnd, true); }
+ void hide() { smart_show_window(m_wnd, false); }
+ void set_foreground() { SetForegroundWindow(m_wnd); }
+ void destroy();
+
+ virtual bool set_default_focus();
+ void prev_view(debugview_info *curview);
+ void next_view(debugview_info *curview);
+ virtual bool restore_field(HWND wnd) { return false; }
+
+ virtual bool handle_key(WPARAM wparam, LPARAM lparam);
+
+protected:
+ static DWORD const DEBUG_WINDOW_STYLE = (WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN) & (~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX);
+ static DWORD const DEBUG_WINDOW_STYLE_EX = 0;
+
+ static int const MAX_VIEWS = 4;
+ static int const EDGE_WIDTH = 3;
+
+ enum
+ {
+ ID_NEW_MEMORY_WND = 1,
+ ID_NEW_DISASM_WND,
+ ID_NEW_LOG_WND,
+ ID_NEW_POINTS_WND,
+ ID_RUN,
+ ID_RUN_AND_HIDE,
+ ID_RUN_VBLANK,
+ ID_RUN_IRQ,
+ ID_NEXT_CPU,
+ ID_STEP,
+ ID_STEP_OVER,
+ ID_STEP_OUT,
+ ID_HARD_RESET,
+ ID_SOFT_RESET,
+ ID_EXIT,
+
+ ID_1_BYTE_CHUNKS,
+ ID_2_BYTE_CHUNKS,
+ ID_4_BYTE_CHUNKS,
+ ID_8_BYTE_CHUNKS,
+ ID_LOGICAL_ADDRESSES,
+ ID_PHYSICAL_ADDRESSES,
+ ID_REVERSE_VIEW,
+ ID_INCREASE_MEM_WIDTH,
+ ID_DECREASE_MEM_WIDTH,
+
+ ID_TOGGLE_BREAKPOINT,
+ ID_DISABLE_BREAKPOINT,
+ ID_RUN_TO_CURSOR,
+ ID_SHOW_RAW,
+ ID_SHOW_ENCRYPTED,
+ ID_SHOW_COMMENTS,
+
+ ID_SHOW_BREAKPOINTS,
+ ID_SHOW_WATCHPOINTS,
+
+ ID_DEVICE_OPTIONS // always keep this at the end
+ };
+
+ HWND window() const { return m_wnd; }
+ UINT32 minwidth() const { return m_minwidth; }
+ UINT32 maxwidth() const { return m_maxwidth; }
+ void set_minwidth(UINT32 value) { m_minwidth = value; }
+ void set_maxwidth(UINT32 value) { m_maxwidth = value; }
+
+ virtual void recompute_children();
+ virtual void update_menu() { }
+ virtual bool handle_command(WPARAM wparam, LPARAM lparam);
+ virtual void draw_contents(HDC dc);
+ void draw_border(HDC dc, RECT &bounds);
+ void draw_border(HDC dc, HWND child);
+
+ auto_pointer<debugview_info> m_views[MAX_VIEWS];
+
+private:
+ LRESULT window_proc(UINT message, WPARAM wparam, LPARAM lparam);
+
+ HMENU create_standard_menubar();
+
+ static LRESULT CALLBACK static_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
+
+ static void register_window_class();
+
+ bool const m_is_main_console;
+
+ debugwin_info *m_next;
+ HWND m_wnd;
+ WNDPROC const m_handler;
+
+ UINT32 m_minwidth, m_maxwidth;
+ UINT32 m_minheight, m_maxheight;
+
+ UINT16 m_ignore_char_lparam;
+
+ static bool s_window_class_registered;
+};
+
+#endif
diff --git a/src/osd/modules/debugger/win/disasmbasewininfo.c b/src/osd/modules/debugger/win/disasmbasewininfo.c
new file mode 100644
index 00000000000..e636bec57a7
--- /dev/null
+++ b/src/osd/modules/debugger/win/disasmbasewininfo.c
@@ -0,0 +1,273 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// disasmbasewininfo.c - Win32 debug window handling
+//
+//============================================================
+
+#include "disasmbasewininfo.h"
+
+#include "debugviewinfo.h"
+#include "disasmviewinfo.h"
+
+#include "debugger.h"
+#include "debug/debugcon.h"
+#include "debug/debugcpu.h"
+
+//#include "winutf8.h"
+
+
+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] == NULL) || !m_views[0]->is_valid())
+ {
+ m_views[0].reset();
+ return;
+ }
+
+ // create the options menu
+ HMENU const optionsmenu = CreatePopupMenu();
+ AppendMenu(optionsmenu, MF_ENABLED, ID_TOGGLE_BREAKPOINT, TEXT("Toggle breakpoint at cursor\tF9"));
+ AppendMenu(optionsmenu, MF_ENABLED, ID_DISABLE_BREAKPOINT, TEXT("Disable breakpoint at cursor\tShift+F9"));
+ AppendMenu(optionsmenu, MF_ENABLED, ID_RUN_TO_CURSOR, TEXT("Run to cursor\tF4"));
+ AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
+ AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_RAW, TEXT("Raw opcodes\tCtrl+R"));
+ AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_ENCRYPTED, TEXT("Encrypted opcodes\tCtrl+E"));
+ AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_COMMENTS, TEXT("Comments\tCtrl+M"));
+ AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
+
+ // set up the view to track the initial expression
+ downcast<disasmview_info *>(m_views[0].get())->set_expression("curpc");
+ m_views[0]->set_source_for_visible_cpu();
+}
+
+
+disasmbasewin_info::~disasmbasewin_info()
+{
+}
+
+
+bool disasmbasewin_info::handle_key(WPARAM wparam, LPARAM lparam)
+{
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ {
+ switch (wparam)
+ {
+ case 'R':
+ SendMessage(window(), WM_COMMAND, ID_SHOW_RAW, 0);
+ return true;
+
+ case 'E':
+ SendMessage(window(), WM_COMMAND, ID_SHOW_ENCRYPTED, 0);
+ return true;
+
+ case 'N':
+ SendMessage(window(), WM_COMMAND, ID_SHOW_COMMENTS, 0);
+ return true;
+ }
+ }
+
+ switch (wparam)
+ {
+ // ajg - steals the F4 from the global key handler - but ALT+F4 didn't work anyways ;)
+ case VK_F4:
+ SendMessage(window(), WM_COMMAND, ID_RUN_TO_CURSOR, 0);
+ return true;
+
+ case VK_F9:
+ if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
+ SendMessage(window(), WM_COMMAND, ID_DISABLE_BREAKPOINT, 0);
+ else
+ SendMessage(window(), WM_COMMAND, ID_TOGGLE_BREAKPOINT, 0);
+ return true;
+
+ case VK_RETURN:
+ if (m_views[0]->cursor_visible() && m_views[0]->source_is_visible_cpu())
+ {
+ SendMessage(window(), WM_COMMAND, ID_STEP, 0);
+ return true;
+ }
+ break;
+ }
+
+ return editwin_info::handle_key(wparam, lparam);
+}
+
+
+void disasmbasewin_info::update_menu()
+{
+ editwin_info::update_menu();
+
+ disasmview_info *const dasmview = downcast<disasmview_info *>(m_views[0].get());
+ HMENU const menu = GetMenu(window());
+
+ bool const disasm_cursor_visible = dasmview->cursor_visible();
+ if (disasm_cursor_visible)
+ {
+ offs_t const address = dasmview->selected_address();
+ device_debug *const debug = dasmview->source_device()->debug();
+
+ // first find an existing breakpoint at this address
+ device_debug::breakpoint *bp = debug->breakpoint_first();
+ while ((bp != NULL) && (bp->address() != address))
+ bp = bp->next();
+
+ if (bp == NULL)
+ {
+ 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"));
+ }
+ else
+ {
+ ModifyMenu(menu, ID_TOGGLE_BREAKPOINT, MF_BYCOMMAND, ID_TOGGLE_BREAKPOINT, TEXT("Clear breakpoint at cursor\tF9"));
+ if (bp->enabled())
+ ModifyMenu(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND, ID_DISABLE_BREAKPOINT, TEXT("Disable breakpoint at cursor\tShift+F9"));
+ else
+ ModifyMenu(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND, ID_DISABLE_BREAKPOINT, TEXT("Enable breakpoint at cursor\tShift+F9"));
+ }
+ EnableMenuItem(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND | (bp != NULL ? MF_ENABLED : MF_GRAYED));
+ }
+ else
+ {
+ ModifyMenu(menu, ID_TOGGLE_BREAKPOINT, MF_BYCOMMAND, ID_TOGGLE_BREAKPOINT, TEXT("Toggle breakpoint at cursor\tF9"));
+ ModifyMenu(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND, ID_DISABLE_BREAKPOINT, TEXT("Disable breakpoint at cursor\tShift+F9"));
+ EnableMenuItem(menu, ID_DISABLE_BREAKPOINT, MF_BYCOMMAND | MF_GRAYED);
+ }
+ EnableMenuItem(menu, ID_TOGGLE_BREAKPOINT, MF_BYCOMMAND | (disasm_cursor_visible ? MF_ENABLED : MF_GRAYED));
+ EnableMenuItem(menu, ID_RUN_TO_CURSOR, MF_BYCOMMAND | (disasm_cursor_visible ? MF_ENABLED : MF_GRAYED));
+
+ disasm_right_column const rightcol = dasmview->right_column();
+ CheckMenuItem(menu, ID_SHOW_RAW, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_RAW ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(menu, ID_SHOW_ENCRYPTED, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_ENCRYPTED ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(menu, ID_SHOW_COMMENTS, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_COMMENTS ? MF_CHECKED : MF_UNCHECKED));
+}
+
+
+bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam)
+{
+ disasmview_info *const dasmview = downcast<disasmview_info *>(m_views[0].get());
+
+ switch (HIWORD(wparam))
+ {
+ // menu selections
+ case 0:
+ switch (LOWORD(wparam))
+ {
+ case ID_TOGGLE_BREAKPOINT:
+ if (dasmview->cursor_visible())
+ {
+ offs_t const address = dasmview->selected_address();
+ device_debug *const debug = dasmview->source_device()->debug();
+ INT32 bpindex = -1;
+
+ // first find an existing breakpoint at this address
+ for (device_debug::breakpoint *bp = debug->breakpoint_first(); bp != NULL; bp = bp->next())
+ {
+ if (address == bp->address())
+ {
+ bpindex = bp->index();
+ break;
+ }
+ }
+
+ // if it doesn't exist, add a new one
+ if (dasmview->source_is_visible_cpu())
+ {
+ astring command;
+ if (bpindex == -1)
+ command.printf("bpset 0x%X", address);
+ else
+ command.printf("bpclear 0x%X", bpindex);
+ debug_console_execute_command(machine(), command, 1);
+ }
+ else
+ {
+ if (bpindex == -1)
+ {
+ bpindex = debug->breakpoint_set(address, NULL, NULL);
+ debug_console_printf(machine(), "Breakpoint %X set\n", bpindex);
+ }
+ else
+ {
+ debug->breakpoint_clear(bpindex);
+ debug_console_printf(machine(), "Breakpoint %X cleared\n", bpindex);
+ }
+ machine().debug_view().update_all();
+ debugger_refresh_display(machine());
+ }
+ }
+ return true;
+
+ case ID_DISABLE_BREAKPOINT:
+ if (dasmview->cursor_visible())
+ {
+ offs_t const address = dasmview->selected_address();
+ device_debug *const debug = dasmview->source_device()->debug();
+
+ // first find an existing breakpoint at this address
+ device_debug::breakpoint *bp = debug->breakpoint_first();
+ while ((bp != NULL) && (bp->address() != address))
+ bp = bp->next();
+
+ // if it doesn't exist, add a new one
+ if (bp != NULL)
+ {
+ if (dasmview->source_is_visible_cpu())
+ {
+ astring command;
+ command.printf(bp->enabled() ? "bpdisable 0x%X" : "bpenable 0x%X", (UINT32)bp->index());
+ debug_console_execute_command(machine(), command, 1);
+ }
+ else
+ {
+ debug->breakpoint_enable(bp->index(), !bp->enabled());
+ debug_console_printf(machine(), "Breakpoint %X %s\n", (UINT32)bp->index(), bp->enabled() ? "enabled" : "disabled");
+ machine().debug_view().update_all();
+ debugger_refresh_display(machine());
+ }
+ }
+ }
+ return true;
+
+ case ID_RUN_TO_CURSOR:
+ if (dasmview->cursor_visible())
+ {
+ offs_t const address = dasmview->selected_address();
+ if (dasmview->source_is_visible_cpu())
+ {
+ astring command;
+ command.printf("go 0x%X", address);
+ debug_console_execute_command(machine(), command, 1);
+ }
+ else
+ {
+ dasmview->source_device()->debug()->go(address);
+ }
+ }
+ return true;
+
+ case ID_SHOW_RAW:
+ dasmview->set_right_column(DASM_RIGHTCOL_RAW);
+ recompute_children();
+ return true;
+
+ case ID_SHOW_ENCRYPTED:
+ dasmview->set_right_column(DASM_RIGHTCOL_ENCRYPTED);
+ recompute_children();
+ return true;
+
+ case ID_SHOW_COMMENTS:
+ dasmview->set_right_column(DASM_RIGHTCOL_COMMENTS);
+ recompute_children();
+ return true;
+ }
+ break;
+ }
+ return editwin_info::handle_command(wparam, lparam);
+}
diff --git a/src/osd/modules/debugger/win/disasmbasewininfo.h b/src/osd/modules/debugger/win/disasmbasewininfo.h
new file mode 100644
index 00000000000..a74b5196b44
--- /dev/null
+++ b/src/osd/modules/debugger/win/disasmbasewininfo.h
@@ -0,0 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// disasmbasewininfo.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_DISASM_BASE_WIN_INFO_H__
+#define __DEBUG_WIN_DISASM_BASE_WIN_INFO_H__
+
+#include "debugwin.h"
+
+#include "editwininfo.h"
+
+
+class disasmbasewin_info : public editwin_info
+{
+public:
+ disasmbasewin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler);
+ virtual ~disasmbasewin_info();
+
+ virtual bool handle_key(WPARAM wparam, LPARAM lparam);
+
+protected:
+ virtual void update_menu();
+ virtual bool handle_command(WPARAM wparam, LPARAM lparam);
+};
+
+#endif
diff --git a/src/osd/modules/debugger/win/disasmviewinfo.c b/src/osd/modules/debugger/win/disasmviewinfo.c
new file mode 100644
index 00000000000..98ff1188188
--- /dev/null
+++ b/src/osd/modules/debugger/win/disasmviewinfo.c
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// disasmviewinfo.c - Win32 debug window handling
+//
+//============================================================
+
+#include "disasmviewinfo.h"
+
+
+disasmview_info::disasmview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) :
+ debugview_info(debugger, owner, parent, DVT_DISASSEMBLY)
+{
+}
+
+
+disasmview_info::~disasmview_info()
+{
+}
+
+
+disasm_right_column disasmview_info::right_column() const
+{
+ return view<debug_view_disasm>()->right_column();
+}
+
+
+offs_t disasmview_info::selected_address() const
+{
+ return view<debug_view_disasm>()->selected_address();
+}
+
+
+void disasmview_info::set_expression(char const *string)
+{
+ view<debug_view_disasm>()->set_expression(string);
+}
+
+
+void disasmview_info::set_right_column(disasm_right_column contents)
+{
+ view<debug_view_disasm>()->set_right_column(contents);
+} \ No newline at end of file
diff --git a/src/osd/modules/debugger/win/disasmviewinfo.h b/src/osd/modules/debugger/win/disasmviewinfo.h
new file mode 100644
index 00000000000..bfd8e73cd95
--- /dev/null
+++ b/src/osd/modules/debugger/win/disasmviewinfo.h
@@ -0,0 +1,32 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// disasmviewinfo.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_DISASM_VIEW_INFO_H__
+#define __DEBUG_WIN_DISASM_VIEW_INFO_H__
+
+#include "debugwin.h"
+
+#include "debugviewinfo.h"
+
+#include "debug/dvdisasm.h"
+
+
+class disasmview_info : public debugview_info
+{
+public:
+ disasmview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent);
+ virtual ~disasmview_info();
+
+ disasm_right_column right_column() const;
+ offs_t selected_address() const;
+
+ void set_expression(const char *expression);
+ void set_right_column(disasm_right_column contents);
+};
+
+#endif
diff --git a/src/osd/modules/debugger/win/disasmwininfo.c b/src/osd/modules/debugger/win/disasmwininfo.c
new file mode 100644
index 00000000000..9f2db09919c
--- /dev/null
+++ b/src/osd/modules/debugger/win/disasmwininfo.c
@@ -0,0 +1,149 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// disasmwininfo.c - Win32 debug window handling
+//
+//============================================================
+
+#include "disasmwininfo.h"
+
+#include "debugviewinfo.h"
+#include "disasmviewinfo.h"
+#include "uimetrics.h"
+
+#include "debugger.h"
+#include "debug/debugcon.h"
+#include "debug/debugcpu.h"
+
+#include "winutf8.h"
+
+
+disasmwin_info::disasmwin_info(debugger_windows_interface &debugger) :
+ disasmbasewin_info(debugger, false, "Disassembly", NULL),
+ m_combownd(NULL)
+{
+ if ((window() == NULL) || (m_views[0] == NULL))
+ return;
+
+ // set up the view to track the initial expression
+ set_edit_defstr("curpc");
+ set_editwnd_text("curpc");
+ editwnd_select_all();
+
+ // create a combo box
+ m_combownd = m_views[0]->create_source_combobox(window(), (LONG_PTR)this);
+
+ // set the caption
+ update_caption();
+
+ // recompute the children once to get the maxwidth
+ recompute_children();
+
+ // position the window and recompute children again
+ SetWindowPos(window(), HWND_TOP, 100, 100, maxwidth(), 200, SWP_SHOWWINDOW);
+ recompute_children();
+
+ // mark the edit box as the default focus and set it
+ set_default_focus();
+}
+
+
+disasmwin_info::~disasmwin_info()
+{
+}
+
+
+void disasmwin_info::recompute_children()
+{
+ // compute a client rect
+ RECT bounds;
+ bounds.top = bounds.left = 0;
+ bounds.right = m_views[0]->prefwidth() + (2 * EDGE_WIDTH);
+ bounds.bottom = 200;
+ AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
+
+ // clamp the min/max size
+ set_maxwidth(bounds.right - bounds.left);
+
+ // get the parent's dimensions
+ RECT parent;
+ GetClientRect(window(), &parent);
+
+ // edit box gets half of the width
+ RECT editrect;
+ editrect.top = parent.top + EDGE_WIDTH;
+ editrect.bottom = editrect.top + metrics().debug_font_height() + 4;
+ editrect.left = parent.left + EDGE_WIDTH;
+ editrect.right = parent.left + ((parent.right - parent.left) / 2) - EDGE_WIDTH;
+
+ // combo box gets the other half of the width
+ RECT comborect;
+ comborect.top = editrect.top;
+ comborect.bottom = editrect.bottom;
+ comborect.left = editrect.right + (2 * EDGE_WIDTH);
+ comborect.right = parent.right - EDGE_WIDTH;
+
+ // disasm view gets the rest
+ RECT dasmrect;
+ dasmrect.top = editrect.bottom + (2 * EDGE_WIDTH);
+ dasmrect.bottom = parent.bottom - EDGE_WIDTH;
+ dasmrect.left = parent.left + EDGE_WIDTH;
+ dasmrect.right = parent.right - EDGE_WIDTH;
+
+ // set the bounds of things
+ m_views[0]->set_bounds(dasmrect);
+ set_editwnd_bounds(editrect);
+ smart_set_window_bounds(m_combownd, window(), comborect);
+}
+
+
+bool disasmwin_info::handle_command(WPARAM wparam, LPARAM lparam)
+{
+ switch (HIWORD(wparam))
+ {
+ // combo box selection changed
+ case CBN_SELCHANGE:
+ {
+ int const sel = SendMessage((HWND)lparam, CB_GETCURSEL, 0, 0);
+ if (sel != CB_ERR)
+ {
+ m_views[0]->set_source_index(sel);
+ update_caption();
+
+ // reset the focus
+ set_default_focus();
+ return true;
+ }
+ break;
+ }
+ }
+ return disasmbasewin_info::handle_command(wparam, lparam);
+}
+
+
+void disasmwin_info::draw_contents(HDC dc)
+{
+ disasmbasewin_info::draw_contents(dc);
+ if (m_combownd)
+ draw_border(dc, m_combownd);
+}
+
+
+void disasmwin_info::process_string(char const *string)
+{
+ // set the string to the disasm view
+ downcast<disasmview_info *>(m_views[0].get())->set_expression(string);
+
+ // select everything in the edit text box
+ editwnd_select_all();
+
+ // update the default string to match
+ set_edit_defstr(string);
+}
+
+
+void disasmwin_info::update_caption()
+{
+ win_set_window_text_utf8(window(), astring("Disassembly: ", m_views[0]->source_name()));
+}
diff --git a/src/osd/modules/debugger/win/disasmwininfo.h b/src/osd/modules/debugger/win/disasmwininfo.h
new file mode 100644
index 00000000000..7817aa9f456
--- /dev/null
+++ b/src/osd/modules/debugger/win/disasmwininfo.h
@@ -0,0 +1,36 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// disasmwininfo.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_DISASM_WIN_INFO_H__
+#define __DEBUG_WIN_DISASM_WIN_INFO_H__
+
+#include "debugwin.h"
+
+#include "disasmbasewininfo.h"
+
+
+class disasmwin_info : public disasmbasewin_info
+{
+public:
+ disasmwin_info(debugger_windows_interface &debugger);
+ virtual ~disasmwin_info();
+
+protected:
+ virtual void recompute_children();
+ virtual bool handle_command(WPARAM wparam, LPARAM lparam);
+ virtual void draw_contents(HDC dc);
+
+private:
+ virtual void process_string(char const *string);
+
+ void update_caption();
+
+ HWND m_combownd;
+};
+
+#endif
diff --git a/src/osd/modules/debugger/win/editwininfo.c b/src/osd/modules/debugger/win/editwininfo.c
new file mode 100644
index 00000000000..98361430b35
--- /dev/null
+++ b/src/osd/modules/debugger/win/editwininfo.c
@@ -0,0 +1,236 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// editwininfo.c - Win32 debug window handling
+//
+//============================================================
+
+#include "editwininfo.h"
+
+#include "debugviewinfo.h"
+#include "uimetrics.h"
+
+#include "strconv.h"
+
+
+// edit box styles
+#define EDIT_BOX_STYLE WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL
+#define EDIT_BOX_STYLE_EX 0
+
+
+editwin_info::editwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler) :
+ debugwin_info(debugger, is_main_console, title, handler),
+ m_editwnd(NULL),
+ m_edit_defstr(),
+ m_original_editproc(NULL),
+ m_history_count(0),
+ m_last_history(0)
+{
+ if (window() == NULL)
+ return;
+
+ // create an edit box and override its key handling
+ m_editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), NULL, EDIT_BOX_STYLE,
+ 0, 0, 100, 100, window(), NULL, GetModuleHandle(NULL), NULL);
+ m_original_editproc = (WNDPROC)(FPTR)GetWindowLongPtr(m_editwnd, GWLP_WNDPROC);
+ SetWindowLongPtr(m_editwnd, GWLP_USERDATA, (LONG_PTR)this);
+ SetWindowLongPtr(m_editwnd, GWLP_WNDPROC, (LONG_PTR)&editwin_info::static_edit_proc);
+ SendMessage(m_editwnd, WM_SETFONT, (WPARAM)metrics().debug_font(), (LPARAM)FALSE);
+ SendMessage(m_editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0);
+ set_editwnd_text("");
+}
+
+
+editwin_info::~editwin_info()
+{
+}
+
+
+bool editwin_info::restore_field(HWND wnd)
+{
+ if (wnd == m_editwnd)
+ {
+ set_editwnd_text(m_edit_defstr);
+ editwnd_select_all();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+bool editwin_info::set_default_focus()
+{
+ SetFocus(m_editwnd);
+ return true;
+}
+
+
+void editwin_info::set_editwnd_bounds(RECT const &bounds)
+{
+ smart_set_window_bounds(m_editwnd, window(), bounds);
+}
+
+
+void editwin_info::set_editwnd_text(char const *text)
+{
+ TCHAR *tc_buffer = tstring_from_utf8(text);
+ if (tc_buffer != NULL)
+ {
+ SendMessage(m_editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)tc_buffer);
+ osd_free(tc_buffer);
+ }
+}
+
+
+void editwin_info::editwnd_select_all()
+{
+ SendMessage(m_editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
+}
+
+
+void editwin_info::draw_contents(HDC dc)
+{
+ debugwin_info::draw_contents(dc);
+ if (m_editwnd)
+ draw_border(dc, m_editwnd);
+}
+
+
+LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
+{
+ TCHAR buffer[MAX_EDIT_STRING];
+
+ // handle a few messages
+ switch (message)
+ {
+ // key down: handle navigation in the attached view
+ case WM_SYSKEYDOWN:
+ if (wparam != VK_F10)
+ return CallWindowProc(m_original_editproc, m_editwnd, message, wparam, lparam);
+ // (fall through)
+ case WM_KEYDOWN:
+ switch (wparam)
+ {
+ case VK_UP:
+ if (m_last_history < (m_history_count - 1))
+ m_last_history++;
+ else
+ m_last_history = 0;
+ SendMessage(m_editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)&m_history[m_last_history][0]);
+ SendMessage(m_editwnd, EM_SETSEL, (WPARAM)MAX_EDIT_STRING, (LPARAM)MAX_EDIT_STRING);
+ break;
+
+ case VK_DOWN:
+ if (m_last_history > 0)
+ m_last_history--;
+ else if (m_history_count > 0)
+ m_last_history = m_history_count - 1;
+ else
+ m_last_history = 0;
+ SendMessage(m_editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)&m_history[m_last_history][0]);
+ SendMessage(m_editwnd, EM_SETSEL, (WPARAM)MAX_EDIT_STRING, (LPARAM)MAX_EDIT_STRING);
+ break;
+
+ case VK_PRIOR:
+ if (m_views[0] != NULL)
+ m_views[0]->send_pageup();
+ break;
+
+ case VK_NEXT:
+ if (m_views[0] != NULL)
+ m_views[0]->send_pagedown();
+ break;
+
+ case VK_TAB:
+ if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
+ prev_view(NULL);
+ else
+ next_view(NULL);
+ set_ignore_char_lparam(lparam);
+ break;
+
+ default:
+ if (handle_key(wparam, lparam))
+ set_ignore_char_lparam(lparam);
+ else
+ return CallWindowProc(m_original_editproc, m_editwnd, message, wparam, lparam);
+ break;
+ }
+ break;
+
+ // char: handle the return key
+ case WM_CHAR:
+
+ // ignore chars associated with keys we've handled
+ if (check_ignore_char_lparam(lparam))
+ {
+ if (waiting_for_debugger() || !seq_pressed())
+ {
+ switch (wparam)
+ {
+ case 13:
+ {
+ // fetch the text
+ SendMessage(m_editwnd, WM_GETTEXT, (WPARAM)ARRAY_LENGTH(buffer), (LPARAM)buffer);
+
+ // add to the history if it's not a repeat of the last one
+ if (buffer[0] != 0 && _tcscmp(buffer, &m_history[0][0]))
+ {
+ memmove(&m_history[1][0], &m_history[0][0], (HISTORY_LENGTH - 1) * MAX_EDIT_STRING * sizeof(TCHAR));
+ _tcscpy(&m_history[0][0], buffer);
+ if (m_history_count < HISTORY_LENGTH)
+ m_history_count++;
+ }
+ m_last_history = m_history_count - 1;
+
+ // process
+ char *utf8_buffer = utf8_from_tstring(buffer);
+ if (utf8_buffer != NULL)
+ {
+ process_string(utf8_buffer);
+ osd_free(utf8_buffer);
+ }
+ break;
+ }
+
+ case 27:
+ {
+ // fetch the text
+ SendMessage(m_editwnd, WM_GETTEXT, (WPARAM)sizeof(buffer), (LPARAM)buffer);
+
+ // if it's not empty, clear the text
+ if (_tcslen(buffer) > 0)
+ {
+ set_ignore_char_lparam(lparam);
+ set_editwnd_text(m_edit_defstr);
+ editwnd_select_all();
+ }
+ break;
+ }
+
+ default:
+ return CallWindowProc(m_original_editproc, m_editwnd, message, wparam, lparam);
+ }
+ }
+ }
+ break;
+
+ // everything else: defaults
+ default:
+ return CallWindowProc(m_original_editproc, m_editwnd, message, wparam, lparam);
+ }
+
+ return 0;
+}
+
+
+LRESULT CALLBACK editwin_info::static_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ editwin_info *const info = (editwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
+ assert(info.m_editwnd == wnd);
+ return info->edit_proc(message, wparam, lparam);
+}
diff --git a/src/osd/modules/debugger/win/editwininfo.h b/src/osd/modules/debugger/win/editwininfo.h
new file mode 100644
index 00000000000..b89a710781a
--- /dev/null
+++ b/src/osd/modules/debugger/win/editwininfo.h
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// editwininfo.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_EDIT_WIN_INFO_H__
+#define __DEBUG_WIN_EDIT_WIN_INFO_H__
+
+#include "debugwin.h"
+
+#include "debugwininfo.h"
+
+
+class editwin_info : public debugwin_info
+{
+public:
+ editwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler);
+ virtual ~editwin_info();
+
+ virtual bool restore_field(HWND wnd);
+
+ virtual bool set_default_focus();
+
+protected:
+ static DWORD const COMBO_BOX_STYLE = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL;
+ static DWORD const COMBO_BOX_STYLE_EX = 0;
+
+ void set_editwnd_bounds(RECT const &bounds);
+ void set_editwnd_text(char const *text);
+ void editwnd_select_all();
+ void set_edit_defstr(char const *string) { m_edit_defstr = string; }
+
+ virtual void draw_contents(HDC dc);
+
+private:
+ virtual void process_string(char const *string) = 0;
+
+ LRESULT edit_proc(UINT message, WPARAM wparam, LPARAM lparam);
+
+ static LRESULT CALLBACK static_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
+
+ static int const MAX_EDIT_STRING = 256;
+ static int const HISTORY_LENGTH = 20;
+
+ HWND m_editwnd;
+ astring m_edit_defstr;
+ WNDPROC m_original_editproc;
+ TCHAR m_history[HISTORY_LENGTH][MAX_EDIT_STRING];
+ int m_history_count;
+ int m_last_history;
+};
+
+#endif
diff --git a/src/osd/modules/debugger/win/logwininfo.c b/src/osd/modules/debugger/win/logwininfo.c
new file mode 100644
index 00000000000..2f2b06c349d
--- /dev/null
+++ b/src/osd/modules/debugger/win/logwininfo.c
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// logwininfo.c - Win32 debug window handling
+//
+//============================================================
+
+#include "logwininfo.h"
+
+#include "debugviewinfo.h"
+
+
+logwin_info::logwin_info(debugger_windows_interface &debugger) :
+ debugwin_info(debugger, false, astring("Errorlog: ", debugger.machine().system().description, " [", debugger.machine().system().name, "]"), NULL)
+{
+ if (!window())
+ return;
+
+ m_views[0].reset(global_alloc(debugview_info(debugger, *this, window(), DVT_LOG)));
+ if ((m_views[0] == NULL) || !m_views[0]->is_valid())
+ {
+ m_views[0].reset();
+ return;
+ }
+
+ // compute a client rect
+ RECT bounds;
+ bounds.top = bounds.left = 0;
+ bounds.right = m_views[0]->maxwidth() + (2 * EDGE_WIDTH);
+ bounds.bottom = 200;
+ AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
+
+ // 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
+ recompute_children();
+}
+
+
+logwin_info::~logwin_info()
+{
+}
diff --git a/src/osd/modules/debugger/win/logwininfo.h b/src/osd/modules/debugger/win/logwininfo.h
new file mode 100644
index 00000000000..f26a557b2cb
--- /dev/null
+++ b/src/osd/modules/debugger/win/logwininfo.h
@@ -0,0 +1,24 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// logwininfo.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_LOG_WIN_INFO_H__
+#define __DEBUG_WIN_LOG_WIN_INFO_H__
+
+#include "debugwin.h"
+
+#include "debugwininfo.h"
+
+
+class logwin_info : public debugwin_info
+{
+public:
+ logwin_info(debugger_windows_interface &debugger);
+ virtual ~logwin_info();
+};
+
+#endif
diff --git a/src/osd/modules/debugger/win/memoryviewinfo.c b/src/osd/modules/debugger/win/memoryviewinfo.c
new file mode 100644
index 00000000000..4c5bdc44c7e
--- /dev/null
+++ b/src/osd/modules/debugger/win/memoryviewinfo.c
@@ -0,0 +1,72 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// memoryviewinfo.c - Win32 debug window handling
+//
+//============================================================
+
+#include "memoryviewinfo.h"
+
+#include "debug/dvmemory.h"
+
+
+memoryview_info::memoryview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) :
+ debugview_info(debugger, owner, parent, DVT_MEMORY)
+{
+}
+
+
+memoryview_info::~memoryview_info()
+{
+}
+
+
+UINT8 memoryview_info::bytes_per_chunk() const
+{
+ return view<debug_view_memory>()->bytes_per_chunk();
+}
+
+
+UINT32 memoryview_info::chunks_per_row() const
+{
+ return view<debug_view_memory>()->chunks_per_row();
+}
+
+
+bool memoryview_info::reverse() const
+{
+ return view<debug_view_memory>()->reverse();
+}
+
+
+bool memoryview_info::physical() const
+{
+ return view<debug_view_memory>()->physical();
+}
+
+
+void memoryview_info::set_expression(char const *string)
+{
+ view<debug_view_memory>()->set_expression(string);
+}
+
+void memoryview_info::set_bytes_per_chunk(UINT8 chunkbytes)
+{
+ view<debug_view_memory>()->set_bytes_per_chunk(chunkbytes);
+}
+
+void memoryview_info::set_chunks_per_row(UINT32 rowchunks)
+{
+ view<debug_view_memory>()->set_chunks_per_row(rowchunks);
+}
+
+void memoryview_info::set_reverse(bool reverse)
+{
+ view<debug_view_memory>()->set_reverse(reverse);
+}
+
+void memoryview_info::set_physical(bool physical)
+{
+ view<debug_view_memory>()->set_physical(physical);
+}
diff --git a/src/osd/modules/debugger/win/memoryviewinfo.h b/src/osd/modules/debugger/win/memoryviewinfo.h
new file mode 100644
index 00000000000..1951473d68b
--- /dev/null
+++ b/src/osd/modules/debugger/win/memoryviewinfo.h
@@ -0,0 +1,36 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// memoryviewinfo.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_MEMORY_VIEW_INFO_H__
+#define __DEBUG_WIN_MEMORY_VIEW_INFO_H__
+
+#include "debugwin.h"
+
+#include "debugviewinfo.h"
+
+
+class memoryview_info : public debugview_info
+{
+public:
+ memoryview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent);
+ virtual ~memoryview_info();
+
+ UINT8 bytes_per_chunk() const;
+ UINT32 chunks_per_row() const;
+ bool reverse() const;
+ bool ascii() const;
+ bool physical() const;
+
+ void set_expression(char const *string);
+ void set_bytes_per_chunk(UINT8 chunkbytes);
+ void set_chunks_per_row(UINT32 rowchunks);
+ void set_reverse(bool reverse);
+ void set_physical(bool physical);
+};
+
+#endif
diff --git a/src/osd/modules/debugger/win/memorywininfo.c b/src/osd/modules/debugger/win/memorywininfo.c
new file mode 100644
index 00000000000..19a4b121de9
--- /dev/null
+++ b/src/osd/modules/debugger/win/memorywininfo.c
@@ -0,0 +1,279 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// memorywininfo.c - Win32 debug window handling
+//
+//============================================================
+
+#include "memorywininfo.h"
+
+#include "debugviewinfo.h"
+#include "memoryviewinfo.h"
+#include "uimetrics.h"
+
+#include "winutf8.h"
+
+
+memorywin_info::memorywin_info(debugger_windows_interface &debugger) :
+ editwin_info(debugger, false, "Memory", NULL),
+ m_combownd(NULL)
+{
+ if (!window())
+ return;
+
+ m_views[0].reset(global_alloc(memoryview_info(debugger, *this, window())));
+ if ((m_views[0] == NULL) || !m_views[0]->is_valid())
+ {
+ m_views[0].reset();
+ return;
+ }
+
+ // 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_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(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
+
+ // set up the view to track the initial expression
+ downcast<memoryview_info *>(m_views[0].get())->set_expression("0");
+ set_edit_defstr("0");
+ set_editwnd_text("0");
+ editwnd_select_all();
+
+ // create a combo box
+ m_views[0]->set_source_for_visible_cpu();
+ m_combownd = m_views[0]->create_source_combobox(window(), (LONG_PTR)this);
+
+ // set the caption
+ update_caption();
+
+ // recompute the children once to get the maxwidth
+ recompute_children();
+
+ // position the window and recompute children again
+ SetWindowPos(window(), HWND_TOP, 100, 100, maxwidth(), 200, SWP_SHOWWINDOW);
+ recompute_children();
+
+ // mark the edit box as the default focus and set it
+ set_default_focus();
+}
+
+
+memorywin_info::~memorywin_info()
+{
+}
+
+
+bool memorywin_info::handle_key(WPARAM wparam, LPARAM lparam)
+{
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ {
+ switch (wparam)
+ {
+ case '1':
+ SendMessage(window(), WM_COMMAND, ID_1_BYTE_CHUNKS, 0);
+ return true;
+
+ case '2':
+ SendMessage(window(), WM_COMMAND, ID_2_BYTE_CHUNKS, 0);
+ return true;
+
+ case '4':
+ SendMessage(window(), WM_COMMAND, ID_4_BYTE_CHUNKS, 0);
+ return true;
+
+ case '8':
+ SendMessage(window(), WM_COMMAND, ID_8_BYTE_CHUNKS, 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);
+}
+
+
+void memorywin_info::recompute_children()
+{
+ // compute a client rect
+ RECT bounds;
+ bounds.top = bounds.left = 0;
+ bounds.right = m_views[0]->prefwidth() + (2 * EDGE_WIDTH);
+ bounds.bottom = 200;
+ AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
+
+ // clamp the min/max size
+ set_maxwidth(bounds.right - bounds.left);
+
+ // get the parent's dimensions
+ RECT parent;
+ GetClientRect(window(), &parent);
+
+ // edit box gets half of the width
+ RECT editrect;
+ editrect.top = parent.top + EDGE_WIDTH;
+ editrect.bottom = editrect.top + metrics().debug_font_height() + 4;
+ editrect.left = parent.left + EDGE_WIDTH;
+ editrect.right = parent.left + ((parent.right - parent.left) / 2) - EDGE_WIDTH;
+
+ // combo box gets the other half of the width
+ RECT comborect;
+ comborect.top = editrect.top;
+ comborect.bottom = editrect.bottom;
+ comborect.left = editrect.right + (2 * EDGE_WIDTH);
+ comborect.right = parent.right - EDGE_WIDTH;
+
+ // memory view gets the rest
+ RECT memrect;
+ memrect.top = editrect.bottom + (2 * EDGE_WIDTH);
+ memrect.bottom = parent.bottom - EDGE_WIDTH;
+ memrect.left = parent.left + EDGE_WIDTH;
+ memrect.right = parent.right - EDGE_WIDTH;
+
+ // set the bounds of things
+ m_views[0]->set_bounds(memrect);
+ set_editwnd_bounds(editrect);
+ smart_set_window_bounds(m_combownd, window(), comborect);
+}
+
+
+void memorywin_info::update_menu()
+{
+ editwin_info::update_menu();
+
+ memoryview_info *const memview = downcast<memoryview_info *>(m_views[0].get());
+ HMENU const menu = GetMenu(window());
+ CheckMenuItem(menu, ID_1_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 1 ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(menu, ID_2_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 2 ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(menu, ID_4_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 4 ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(menu, ID_8_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 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());
+ switch (HIWORD(wparam))
+ {
+ // combo box selection changed
+ case CBN_SELCHANGE:
+ {
+ int const sel = SendMessage((HWND)lparam, CB_GETCURSEL, 0, 0);
+ if (sel != CB_ERR)
+ {
+ memview->set_source_index(sel);
+ update_caption();
+
+ // reset the focus
+ set_default_focus();
+ return true;
+ }
+ break;
+ }
+
+ // menu selections
+ case 0:
+ switch (LOWORD(wparam))
+ {
+ case ID_1_BYTE_CHUNKS:
+ memview->set_bytes_per_chunk(1);
+ return true;
+
+ case ID_2_BYTE_CHUNKS:
+ memview->set_bytes_per_chunk(2);
+ return true;
+
+ case ID_4_BYTE_CHUNKS:
+ memview->set_bytes_per_chunk(4);
+ return true;
+
+ case ID_8_BYTE_CHUNKS:
+ memview->set_bytes_per_chunk(8);
+ return true;
+
+ case ID_LOGICAL_ADDRESSES:
+ memview->set_physical(false);
+ return true;
+
+ case ID_PHYSICAL_ADDRESSES:
+ memview->set_physical(true);
+ return true;
+
+ case ID_REVERSE_VIEW:
+ memview->set_reverse(!memview->reverse());
+ return true;
+
+ case ID_INCREASE_MEM_WIDTH:
+ memview->set_chunks_per_row(memview->chunks_per_row() + 1);
+ recompute_children();
+ return true;
+
+ case ID_DECREASE_MEM_WIDTH:
+ memview->set_chunks_per_row(memview->chunks_per_row() - 1);
+ recompute_children();
+ return true;
+ }
+ break;
+ }
+ return editwin_info::handle_command(wparam, lparam);
+}
+
+
+void memorywin_info::draw_contents(HDC dc)
+{
+ editwin_info::draw_contents(dc);
+ if (m_combownd)
+ draw_border(dc, m_combownd);
+}
+
+
+void memorywin_info::process_string(char const *string)
+{
+ // set the string to the memory view
+ downcast<memoryview_info *>(m_views[0].get())->set_expression(string);
+
+ // select everything in the edit text box
+ editwnd_select_all();
+
+ // update the default string to match
+ set_edit_defstr(string);
+}
+
+
+void memorywin_info::update_caption()
+{
+ win_set_window_text_utf8(window(), astring("Memory: ", m_views[0]->source_name()));
+}
diff --git a/src/osd/modules/debugger/win/memorywininfo.h b/src/osd/modules/debugger/win/memorywininfo.h
new file mode 100644
index 00000000000..a6e71f8fdcd
--- /dev/null
+++ b/src/osd/modules/debugger/win/memorywininfo.h
@@ -0,0 +1,39 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// memorywininfo.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_MEMORY_WIN_INFO_H__
+#define __DEBUG_WIN_MEMORY_WIN_INFO_H__
+
+#include "debugwin.h"
+
+#include "editwininfo.h"
+
+
+class memorywin_info : public editwin_info
+{
+public:
+ memorywin_info(debugger_windows_interface &debugger);
+ virtual ~memorywin_info();
+
+ virtual bool handle_key(WPARAM wparam, LPARAM lparam);
+
+protected:
+ virtual void recompute_children();
+ virtual void update_menu();
+ virtual bool handle_command(WPARAM wparam, LPARAM lparam);
+ virtual void draw_contents(HDC dc);
+
+private:
+ virtual void process_string(char const *string);
+
+ void update_caption();
+
+ HWND m_combownd;
+};
+
+#endif
diff --git a/src/osd/modules/debugger/win/pointswininfo.c b/src/osd/modules/debugger/win/pointswininfo.c
new file mode 100644
index 00000000000..a958a285046
--- /dev/null
+++ b/src/osd/modules/debugger/win/pointswininfo.c
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// pointswininfo.c - Win32 debug window handling
+//
+//============================================================
+
+#include "pointswininfo.h"
+
+#include "debugviewinfo.h"
+
+#include "winutf8.h"
+
+
+pointswin_info::pointswin_info(debugger_windows_interface &debugger) :
+ debugwin_info(debugger, false, astring("All Breakpoints"), NULL)
+{
+ if (!window())
+ return;
+
+ m_views[0].reset(global_alloc(debugview_info(debugger, *this, window(), DVT_BREAK_POINTS)));
+ if ((m_views[0] == NULL) || !m_views[0]->is_valid())
+ {
+ m_views[0].reset();
+ return;
+ }
+
+ // create the options menu
+ 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(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
+
+ // compute a client rect
+ RECT bounds;
+ bounds.top = bounds.left = 0;
+ bounds.right = m_views[0]->maxwidth() + (2 * EDGE_WIDTH);
+ bounds.bottom = 200;
+ AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
+
+ // 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
+ recompute_children();
+}
+
+
+pointswin_info::~pointswin_info()
+{
+}
+
+
+bool pointswin_info::handle_key(WPARAM wparam, LPARAM lparam)
+{
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ {
+ switch (wparam)
+ {
+ case '1':
+ SendMessage(window(), WM_COMMAND, ID_SHOW_BREAKPOINTS, 0);
+ return true;
+
+ case '2':
+ SendMessage(window(), WM_COMMAND, ID_SHOW_WATCHPOINTS, 0);
+ return true;
+ }
+ }
+
+ return debugwin_info::handle_key(wparam, lparam);
+}
+
+
+void pointswin_info::update_menu()
+{
+ debugwin_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));
+}
+
+
+bool pointswin_info::handle_command(WPARAM wparam, LPARAM lparam)
+{
+ switch (HIWORD(wparam))
+ {
+ // menu selections
+ case 0:
+ switch (LOWORD(wparam))
+ {
+ case ID_SHOW_BREAKPOINTS:
+ m_views[0].reset();
+ m_views[0].reset(global_alloc(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");
+ recompute_children();
+ return true;
+
+ case ID_SHOW_WATCHPOINTS:
+ m_views[0].reset();
+ m_views[0].reset(global_alloc(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;
+ }
+ break;
+ }
+ return debugwin_info::handle_command(wparam, lparam);
+}
diff --git a/src/osd/modules/debugger/win/pointswininfo.h b/src/osd/modules/debugger/win/pointswininfo.h
new file mode 100644
index 00000000000..e04a467bb0a
--- /dev/null
+++ b/src/osd/modules/debugger/win/pointswininfo.h
@@ -0,0 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// pointswininfo.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_POINTS_WIN_INFO_H__
+#define __DEBUG_WIN_POINTS_WIN_INFO_H__
+
+#include "debugwin.h"
+
+#include "debugwininfo.h"
+
+
+class pointswin_info : public debugwin_info
+{
+public:
+ pointswin_info(debugger_windows_interface &debugger);
+ virtual ~pointswin_info();
+
+ virtual bool handle_key(WPARAM wparam, LPARAM lparam);
+
+protected:
+ virtual void update_menu();
+ virtual bool handle_command(WPARAM wparam, LPARAM lparam);
+};
+
+#endif
diff --git a/src/osd/modules/debugger/win/uimetrics.c b/src/osd/modules/debugger/win/uimetrics.c
new file mode 100644
index 00000000000..f61b90275da
--- /dev/null
+++ b/src/osd/modules/debugger/win/uimetrics.c
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// uimetrics.c - Win32 debug window handling
+//
+//============================================================
+
+#include "uimetrics.h"
+
+#include "strconv.h"
+
+
+ui_metrics::ui_metrics(windows_options const &options) :
+ m_debug_font(NULL),
+ m_debug_font_height(0),
+ m_debug_font_width(0),
+ m_debug_font_ascent(0),
+ m_hscroll_height(GetSystemMetrics(SM_CYHSCROLL)),
+ m_vscroll_width(GetSystemMetrics(SM_CXVSCROLL))
+{
+ // create a temporary DC
+ HDC const temp_dc = GetDC(NULL);
+ if (temp_dc != NULL)
+ {
+ int const size = options.debugger_font_size();
+
+ // create a standard font
+ TCHAR *t_face = tstring_from_utf8(options.debugger_font());
+ m_debug_font = CreateFont(-MulDiv(size, GetDeviceCaps(temp_dc, LOGPIXELSY), 72), 0, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE,
+ ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, t_face);
+ osd_free(t_face);
+ t_face = NULL;
+
+ if (m_debug_font == NULL)
+ fatalerror("Unable to create debugger font\n");
+
+ // get the metrics
+ HGDIOBJ const old_font = SelectObject(temp_dc, m_debug_font);
+ TEXTMETRIC metrics;
+ if (GetTextMetrics(temp_dc, &metrics))
+ {
+ m_debug_font_width = metrics.tmAveCharWidth;
+ m_debug_font_height = metrics.tmHeight;
+ m_debug_font_ascent = metrics.tmAscent + metrics.tmExternalLeading;
+ }
+ SelectObject(temp_dc, old_font);
+ ReleaseDC(NULL, temp_dc);
+ }
+}
+
+
+ui_metrics::ui_metrics(ui_metrics const &that) :
+ m_debug_font(NULL),
+ m_debug_font_height(that.m_debug_font_height),
+ m_debug_font_width(that.m_debug_font_width),
+ m_debug_font_ascent(that.m_debug_font_ascent),
+ m_hscroll_height(that.m_hscroll_height),
+ m_vscroll_width(that.m_vscroll_width)
+{
+ LOGFONT lf;
+ if (GetObject(that.m_debug_font, sizeof(lf), &lf))
+ m_debug_font = CreateFontIndirect(&lf);
+}
+
+
+ui_metrics::~ui_metrics()
+{
+ if (m_debug_font)
+ DeleteObject(m_debug_font);
+}
diff --git a/src/osd/modules/debugger/win/uimetrics.h b/src/osd/modules/debugger/win/uimetrics.h
new file mode 100644
index 00000000000..54db03c1be4
--- /dev/null
+++ b/src/osd/modules/debugger/win/uimetrics.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// uimetrics.h - Win32 debug window handling
+//
+//============================================================
+
+#ifndef __DEBUG_WIN_UI_METRICS_H__
+#define __DEBUG_WIN_UI_METRICS_H__
+
+#include "debugwin.h"
+
+#include "emu.h"
+
+#include "winmain.h"
+
+
+class ui_metrics
+{
+public:
+ ui_metrics(windows_options const &options);
+ ui_metrics(ui_metrics const &that);
+ ~ui_metrics();
+
+ HFONT debug_font() const { return m_debug_font; }
+ UINT32 debug_font_height() const { return m_debug_font_height; }
+ UINT32 debug_font_width() const { return m_debug_font_width; }
+ UINT32 debug_font_ascent() const { return m_debug_font_ascent; }
+
+ UINT32 hscroll_height() const { return m_hscroll_height; }
+ UINT32 vscroll_width() const { return m_vscroll_width; }
+
+private:
+ HFONT m_debug_font;
+ UINT32 m_debug_font_height;
+ UINT32 m_debug_font_width;
+ UINT32 m_debug_font_ascent;
+
+ UINT32 const m_hscroll_height;
+ UINT32 const m_vscroll_width;
+};
+
+#endif
diff --git a/src/osd/sdl/sdl.mak b/src/osd/sdl/sdl.mak
index e0dcfdce356..da6bd17a727 100644
--- a/src/osd/sdl/sdl.mak
+++ b/src/osd/sdl/sdl.mak
@@ -767,7 +767,7 @@ OSDOBJS += \
$(OSDOBJ)/modules/debugger/none.o \
$(OSDOBJ)/modules/debugger/debugint.o \
$(OSDOBJ)/modules/debugger/debugwin.o \
- $(OSDOBJ)/modules/debugger/debugqt.o \
+ $(OSDOBJ)/modules/debugger/debugqt.o
#-------------------------------------------------
# BGFX
diff --git a/src/osd/windows/windows.mak b/src/osd/windows/windows.mak
index b9cc10886cb..e9c868a4753 100644
--- a/src/osd/windows/windows.mak
+++ b/src/osd/windows/windows.mak
@@ -93,6 +93,7 @@ OBJDIRS += $(WINOBJ) \
$(OSDOBJ)/modules/midi \
$(OSDOBJ)/modules/font \
$(OSDOBJ)/modules/netdev \
+ $(OSDOBJ)/modules/debugger/win
ifdef USE_QTDEBUG
OBJDIRS += $(OSDOBJ)/modules/debugger/qt
@@ -411,9 +412,22 @@ $(WINOBJ)/drawgdi.o : $(SRC)/emu/rendersw.inc
# add debug-specific files
OSDOBJS += \
$(OSDOBJ)/modules/debugger/debugwin.o \
+ $(OSDOBJ)/modules/debugger/win/consolewininfo.o \
+ $(OSDOBJ)/modules/debugger/win/debugbaseinfo.o \
+ $(OSDOBJ)/modules/debugger/win/debugviewinfo.o \
+ $(OSDOBJ)/modules/debugger/win/debugwininfo.o \
+ $(OSDOBJ)/modules/debugger/win/disasmbasewininfo.o \
+ $(OSDOBJ)/modules/debugger/win/disasmviewinfo.o \
+ $(OSDOBJ)/modules/debugger/win/disasmwininfo.o \
+ $(OSDOBJ)/modules/debugger/win/editwininfo.o \
+ $(OSDOBJ)/modules/debugger/win/logwininfo.o \
+ $(OSDOBJ)/modules/debugger/win/memoryviewinfo.o \
+ $(OSDOBJ)/modules/debugger/win/memorywininfo.o \
+ $(OSDOBJ)/modules/debugger/win/pointswininfo.o \
+ $(OSDOBJ)/modules/debugger/win/uimetrics.o \
$(OSDOBJ)/modules/debugger/debugint.o \
$(OSDOBJ)/modules/debugger/debugqt.o \
- $(OSDOBJ)/modules/debugger/none.o \
+ $(OSDOBJ)/modules/debugger/none.o
# add a stub resource file
RESFILE = $(WINOBJ)/mame.res
diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h
index d732ccf3bf2..dc76254660e 100644
--- a/src/osd/windows/winmain.h
+++ b/src/osd/windows/winmain.h
@@ -6,6 +6,9 @@
//
//============================================================
+#ifndef __WINDOWS_WINMAIN_H__
+#define __WINDOWS_WINMAIN_H__
+
#include "clifront.h"
#include "osdepend.h"
#include "modules/lib/osdobj_common.h"
@@ -292,3 +295,5 @@ extern int osd_num_processors;
// use this to ping the watchdog
void winmain_watchdog_ping(void);
void winmain_dump_stack();
+
+#endif \ No newline at end of file